/* 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 . * */ #include "common/textconsole.h" #include "m4/adv_r/chunk_ops.h" #include "m4/core/errors.h" #include "m4/core/imath.h" #include "m4/vars.h" namespace M4 { int32 conv_ops_text_strlen(char *s) { int32 len = strlen(s) + 1; // Added +1 for null char. if ((len % 4) == 0) return len; len += 4 - (len % 4); return len; } void conv_ops_unknown_chunk(int32 tag, const char *s) { char *tag_name = (char *)&tag; error_show(FL, 'PARS', "'%s' What type is this chunk: %c%c%c%c ?", s, tag_name[3], tag_name[2], tag_name[1], tag_name[0]); } /* * Find an entry and auto-advance the pointer past it. */ char *conv_ops_get_entry(int32 i, int32 *next, int32 *tag, Conv *c) { int32 num_blocks; int32 j = 0, k = 0; lnode_chunk *L; node_chunk *N; text_chunk *T; w_reply_chunk *W; conv_chunk *CC; if ((i + c->myCNode) > c->chunkSize) { error_show(FL, 'PARS', "Conv pointer skipped past chunk EOF. Please check script and make sure HAG is up to date"); } char *outChunk = &(c->conv[c->myCNode]); *tag = *(int32 *)&outChunk[i]; if (_GC(swap)) *tag = convert_intel32(*tag); switch (*tag) { case C_ASGN_CHUNK: k = sizeof(c_assign_chunk); break; case ASGN_CHUNK: k = sizeof(assign_chunk); break; case CONV_CHUNK: CC = (conv_chunk *)&outChunk[i]; j = CC->size; break; case DECL_CHUNK: k = sizeof(decl_chunk); break; case FALL_CHUNK: k = sizeof(fall_chunk); break; case LNODE_CHUNK: L = (lnode_chunk *)&outChunk[i]; k = sizeof(lnode_chunk); if (_GC(swap)) { j = convert_intel32(L->num_entries) * sizeof(int32); j = convert_intel32(j); } else { j = L->num_entries * sizeof(int32); } break; case NODE_CHUNK: N = (node_chunk *)&outChunk[i]; k = sizeof(node_chunk); if (_GC(swap)) { j = convert_intel32(N->num_entries) * sizeof(int32); j = convert_intel32(j); } else { j = N->num_entries * sizeof(int32); //was += } break; case ENTRY_CHUNK: k = sizeof(entry_chunk); break; case TEXT_CHUNK: case MESSAGE_CHUNK: T = (text_chunk *)&outChunk[i]; num_blocks = T->size; k = sizeof(text_chunk); j = num_blocks; break; case REPLY_CHUNK: k = sizeof(reply_chunk); break; case WEIGHT_REPLY_CHUNK: case WEIGHT_PREPLY_CHUNK: W = (w_reply_chunk *)&outChunk[i]; k = sizeof(w_reply_chunk); if (_GC(swap)) { j = convert_intel32(W->num_replies) * (2 * sizeof(int32)); //was += j = convert_intel32(j); } else { j = W->num_replies * (2 * sizeof(int32)); //was += } break; case COND_REPLY_CHUNK: k = sizeof(c_reply_chunk); break; case COND_EXIT_GOTO_CHUNK: case COND_GOTO_CHUNK: k = sizeof(c_goto_chunk); break; case GOTO_CHUNK: case EXIT_GOTO_CHUNK: k = sizeof(goto_chunk); break; case HIDE_CHUNK: case UHID_CHUNK: case DSTR_CHUNK: k = sizeof(misc_chunk); break; case CHDE_CHUNK: case CUHD_CHUNK: case CDST_CHUNK: k = sizeof(c_misc_chunk); break; default: error_show(FL, 'PARS', "Tag: %d (%x) Node: %d (%x hex)", *tag, *tag, c->myCNode, c->myCNode); break; } if (_GC(swap)) j = convert_intel32(j); j += k; j += i; *next = j; return &outChunk[i]; } static void swap_assign(assign_chunk *a) { a->tag = convert_intel32(a->tag); a->index = convert_intel32(a->index); a->op = convert_intel32(a->op); a->opnd1 = convert_intel32(a->opnd1); } assign_chunk *get_asgn(Conv *c, int32 cSize) { char *s = &(c->conv[c->myCNode]); return (assign_chunk *)&s[cSize]; } static void swap_c_asgn(c_assign_chunk *c) { c->tag = convert_intel32(c->tag); c->c_op_l = convert_intel32(c->c_op_l); c->c_op = convert_intel32(c->c_op); c->c_op_r = convert_intel32(c->c_op_r); c->index = convert_intel32(c->index); c->op = convert_intel32(c->op); c->opnd1 = convert_intel32(c->opnd1); } c_assign_chunk *get_c_asgn(Conv *c, int32 cSize) { char *s = &(c->conv[c->myCNode]); return (c_assign_chunk *)&s[cSize]; } static void swap_conv(conv_chunk *c) { c->tag = convert_intel32(c->tag); c->size = convert_intel32(c->size); } conv_chunk *get_conv(Conv *c, int32 cSize) { char *s = &(c->conv[c->myCNode]); return (conv_chunk *)&s[cSize]; } static void swap_decl(decl_chunk *d) { d->tag = convert_intel32(d->tag); d->val = convert_intel32(d->val); d->flags = convert_intel32(d->flags); } decl_chunk *get_decl(Conv *c, int32 cSize) { return (decl_chunk *)&c->conv[cSize]; } static void swap_fall(fall_chunk *l) { l->tag = convert_intel32(l->tag); l->val = convert_intel32(l->val); l->index = convert_intel32(l->index); } fall_chunk *get_fall(Conv *c, int32 cSize) { char *s = &(c->conv[c->myCNode]); return (fall_chunk *)&s[cSize]; } static void swap_lnode(lnode_chunk *l) { l->tag = convert_intel32(l->tag); l->hash = convert_intel32(l->hash); l->size = convert_intel32(l->size); l->entry_num = convert_intel32(l->entry_num); l->num_entries = convert_intel32(l->num_entries); int32 *L = (int32 *)l; L += 5; for (int i = 0; i < l->num_entries; i++) { L[i] = convert_intel32(L[i]); } } lnode_chunk *get_lnode(Conv *c, int32 cSize) { char *s = &(c->conv[c->myCNode]); return (lnode_chunk *)&s[cSize]; } static void swap_node(node_chunk *n) { n->tag = convert_intel32(n->tag); n->hash = convert_intel32(n->hash); n->size = convert_intel32(n->size); n->num_entries = convert_intel32(n->num_entries); int32 *L = (int32 *)(n + 1); for (int i = 0; i < n->num_entries; i++) { L[i] = convert_intel32(L[i]); } } node_chunk *get_node(Conv *c, int32 cSize) { char *s = &(c->conv[c->myCNode]); return (node_chunk *)&s[cSize]; } static void swap_entry(entry_chunk *e) { e->tag = convert_intel32(e->tag); e->size = convert_intel32(e->size); e->status = convert_intel32(e->status); } entry_chunk *get_entry(Conv *c, int32 cSize) { char *s = &(c->conv[c->myCNode]); return (entry_chunk *)&s[cSize]; } entry_chunk *get_hash_entry(Conv *c, int32 cSize) { char *s = &(c->conv[0]); return (entry_chunk *)&s[cSize]; } static void swap_text(text_chunk *t) { t->tag = convert_intel32(t->tag); t->size = convert_intel32(t->size); } text_chunk *get_text(Conv *c, int32 cSize) { char *s = &(c->conv[c->myCNode]); return (text_chunk *)&s[cSize]; } static void swap_mesg(mesg_chunk *m) { m->tag = convert_intel32(m->tag); m->size = convert_intel32(m->size); } mesg_chunk *get_mesg(Conv *c, int32 cSize) { char *s = &(c->conv[c->myCNode]); return (mesg_chunk *)&s[cSize]; } static void swap_reply(reply_chunk *r) { r->tag = convert_intel32(r->tag); r->index = convert_intel32(r->index); } reply_chunk *get_reply(Conv *c, int32 cSize) { char *s = &(c->conv[c->myCNode]); return (reply_chunk *)&s[cSize]; } static void swap_c_reply(c_reply_chunk *c) { c->tag = convert_intel32(c->tag); c->op_l = convert_intel32(c->op_l); c->op = convert_intel32(c->op); c->op_r = convert_intel32(c->op_r); c->index = convert_intel32(c->index); } c_reply_chunk *get_c_reply(Conv *c, int32 cSize) { char *s = &(c->conv[c->myCNode]); return (c_reply_chunk *)&s[cSize]; } static void swap_w_reply(w_reply_chunk *c) { c->tag = convert_intel32(c->tag); c->num_replies = convert_intel32(c->num_replies); } w_reply_chunk *get_w_reply(Conv *c, int32 cSize) { char *s = &(c->conv[c->myCNode]); return (w_reply_chunk *)&s[cSize]; } static void swap_w_entry(w_entry_chunk *w) { w->weight = convert_intel32(w->weight); w->index = convert_intel32(w->index); } w_entry_chunk *get_w_entry(Conv *c, int32 cSize) { char *s = &(c->conv[c->myCNode]); return (w_entry_chunk *)&s[cSize]; } static void swap_goto(goto_chunk *g) { g->tag = convert_intel32(g->tag); g->index = convert_intel32(g->index); } goto_chunk *get_goto(Conv *c, int32 cSize) { char *s = &(c->conv[c->myCNode]); return (goto_chunk *)&s[cSize]; } static void swap_c_goto(c_goto_chunk *c) { c->tag = convert_intel32(c->tag); c->opnd1 = convert_intel32(c->opnd1); c->op = convert_intel32(c->op); c->opnd2 = convert_intel32(c->opnd2); c->index = convert_intel32(c->index); } c_goto_chunk *get_c_goto(Conv *c, int32 cSize) { char *s = &(c->conv[c->myCNode]); return (c_goto_chunk *)&s[cSize]; } static void swap_misc(misc_chunk *m) { m->tag = convert_intel32(m->tag); m->index = convert_intel32(m->index); } misc_chunk *get_misc(Conv *c, int32 cSize) { char *s = &(c->conv[c->myCNode]); return (misc_chunk *)&s[cSize]; } static void swap_c_misc(c_misc_chunk *c) { c->tag = convert_intel32(c->tag); c->c_op_l = convert_intel32(c->c_op_l); c->c_op = convert_intel32(c->c_op); c->c_op_r = convert_intel32(c->c_op_r); c->index = convert_intel32(c->index); } c_misc_chunk *get_c_misc(Conv *c, int32 cSize) { char *s = &(c->conv[c->myCNode]); return (c_misc_chunk *)&s[cSize]; } int32 get_long(Conv *c, int32 cSize) { char *s = &(c->conv[c->myCNode]); int32 *l = (int32 *)&s[cSize]; return *l; } char *get_string(Conv *c, int32 cSize) { return &c->conv[cSize]; } int conv_ops_cond_successful(int32 l_op, int32 op, int32 r_op) { switch (op) { case PERCENT: return l_op % r_op; case GE: return l_op >= r_op; case LE: return l_op <= r_op; case GT: return l_op > r_op; case LT: return l_op < r_op; case NE: case CNE: return !(l_op == r_op); case IS_ASSIGNED: return l_op == r_op; case ANDAND: return l_op && r_op; case OROR: return l_op || r_op; } return 0; } int32 conv_ops_process_asgn(int32 val, int32 oprtr, int32 opnd) { switch (oprtr) { case PPLUS: val += opnd; break; case MINUS: val -= opnd; break; case TIMES: val *= opnd; break; case DIVIDE: val /= opnd; break; case IS_ASSIGNED: val = opnd; break; default: error_show(FL, 'PARS', "Operator must be a +,-,*,/,=, Please check tag type: %d in token header file", oprtr); break; } return val; } void conv_swap_words(Conv *c) { int32 ent = 0, tag = 0, next; if (!c) return; c->myCNode = 0; const int32 ent_old = c->myCNode; c->myCNode = 0; _GC(swap) = true; while (ent < c->chunkSize) { conv_ops_get_entry(ent, &next, &tag, c); switch (tag) { case C_ASGN_CHUNK: { c_assign_chunk *c_asgn = get_c_asgn(c, ent); swap_c_asgn(c_asgn); } break; case ASGN_CHUNK: { assign_chunk *asgn = get_asgn(c, ent); swap_assign(asgn); } break; case HIDE_CHUNK: case DSTR_CHUNK: case UHID_CHUNK: { misc_chunk *misc = get_misc(c, ent); swap_misc(misc); } break; case CHDE_CHUNK: case CUHD_CHUNK: case CDST_CHUNK: { c_misc_chunk *c_misc = get_c_misc(c, ent); swap_c_misc(c_misc); } break; case CONV_CHUNK: { conv_chunk *conv = get_conv(c, ent); swap_conv(conv); } break; case DECL_CHUNK: { decl_chunk *decl = get_decl(c, ent); swap_decl(decl); } break; case FALL_CHUNK: { fall_chunk *fall = get_fall(c, ent); swap_fall(fall); } break; case LNODE_CHUNK: { lnode_chunk *lnode = get_lnode(c, ent); swap_lnode(lnode); } break; case NODE_CHUNK: { node_chunk *node = get_node(c, ent); swap_node(node); } break; case ENTRY_CHUNK: { entry_chunk *entry = get_entry(c, ent); swap_entry(entry); } break; case TEXT_CHUNK: { text_chunk *text = get_text(c, ent); swap_text(text); } break; case REPLY_CHUNK: { reply_chunk *reply = get_reply(c, ent); swap_reply(reply); } break; case WEIGHT_REPLY_CHUNK: case WEIGHT_PREPLY_CHUNK: { w_reply_chunk *w_reply = get_w_reply(c, ent); swap_w_reply(w_reply); int32 tempEnt = ent + sizeof(w_reply_chunk); for (int x = 0; x < w_reply->num_replies; x++) { w_entry_chunk *w_entry = get_w_entry(c, tempEnt); swap_w_entry(w_entry); tempEnt += sizeof(w_entry_chunk); } } break; case COND_REPLY_CHUNK: { c_reply_chunk *c_reply = get_c_reply(c, ent); swap_c_reply(c_reply); } break; case MESSAGE_CHUNK: { mesg_chunk *mesg = get_mesg(c, ent); swap_mesg(mesg); } break; case GOTO_CHUNK: case EXIT_GOTO_CHUNK: { goto_chunk *go = get_goto(c, ent); swap_goto(go); } break; case COND_GOTO_CHUNK: case COND_EXIT_GOTO_CHUNK: { c_goto_chunk *c_goto = get_c_goto(c, ent); swap_c_goto(c_goto); } break; default: break; } ent = next; } _GC(swap) = false; c->myCNode = ent_old; } } // End of namespace M4