mirror of
https://github.com/scummvm/scummex.git
synced 2026-05-21 05:40:51 +00:00
208 lines
5.7 KiB
C++
208 lines
5.7 KiB
C++
/* DeScumm - Scumm Script Disassembler
|
|
* Copyright (C) 2001 Ludvig Strigeus
|
|
* Copyright (C) 2002, 2003 The ScummVM Team
|
|
*
|
|
* 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 2
|
|
* 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, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*
|
|
* $Header: /Users/sev/projects/sc/s/scummvm/scummex/descumm.h,v 1.3 2003/09/23 00:47:23 fingolfin Exp $
|
|
*
|
|
*/
|
|
|
|
#ifndef DESCUMM_H
|
|
#define DESCUMM_H
|
|
|
|
#include <assert.h>
|
|
#include <ctype.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#ifdef WIN32
|
|
#include <io.h>
|
|
#include <process.h>
|
|
#endif
|
|
|
|
|
|
#define ARRAYSIZE(x) ((int)(sizeof(x) / sizeof(x[0])))
|
|
|
|
uint32 inline SWAP_32(uint32 a)
|
|
{
|
|
return ((a >> 24) & 0xFF) + ((a >> 8) & 0xFF00) + ((a << 8) & 0xFF0000) +
|
|
((a << 24) & 0xFF000000);
|
|
}
|
|
|
|
uint16 inline SWAP_16(uint16 a)
|
|
{
|
|
return ((a >> 8) & 0xFF) + ((a << 8) & 0xFF00);
|
|
}
|
|
|
|
//
|
|
// The block stack records jump instructions
|
|
//
|
|
struct BlockStack {
|
|
unsigned short from; // From which offset...
|
|
unsigned short to; // ...to which offset
|
|
bool isWhile; // Set to true if we think this jump is part of a while loop
|
|
};
|
|
|
|
extern BlockStack *block_stack;
|
|
extern int num_block_stack;
|
|
|
|
//
|
|
// Jump decoding auxillaries (used by the code which tries to translate jumps
|
|
// back into if / else / while / etc. constructs).
|
|
//
|
|
extern bool pendingElse, haveElse;
|
|
extern int pendingElseTo;
|
|
extern int pendingElseOffs;
|
|
extern int pendingElseOpcode;
|
|
extern int pendingElseIndent;
|
|
|
|
//
|
|
// The opcode of an unconditional jump instruction.
|
|
//
|
|
extern int g_jump_opcode;
|
|
|
|
//
|
|
// Command line options
|
|
//
|
|
extern bool alwaysShowOffs;
|
|
extern bool dontOutputIfs;
|
|
extern bool dontOutputElse;
|
|
extern bool dontOutputElseif;
|
|
extern bool dontOutputWhile;
|
|
extern bool dontShowOpcode;
|
|
extern bool dontShowOffsets;
|
|
extern bool haltOnError;
|
|
|
|
//
|
|
// The SCUMM version used for the script we are descumming.
|
|
//
|
|
extern byte scriptVersion;
|
|
|
|
//
|
|
// Various positions / offsets
|
|
//
|
|
extern byte *cur_pos, *org_pos;
|
|
extern int offs_of_line;
|
|
|
|
//
|
|
// Total size of the currently loaded script
|
|
//
|
|
extern uint size_of_code;
|
|
|
|
struct StackEnt {
|
|
byte type;
|
|
long data;
|
|
StackEnt *left, *right;
|
|
char *str;
|
|
StackEnt **list;
|
|
};
|
|
|
|
class DeScumm {
|
|
private:
|
|
char *strecpy(char *buf, const char *src);
|
|
int get_curoffs();
|
|
int get_byte();
|
|
uint get_word();
|
|
int get_signed_word();
|
|
char *getIndentString(int level);
|
|
void outputLine(char *buf, int curoffs, int opcode, int indent);
|
|
bool indentBlock(unsigned int cur);
|
|
BlockStack *pushBlockStackItem();
|
|
bool maybeAddIf(uint cur, uint to);
|
|
bool maybeAddElse(uint cur, uint to);
|
|
bool maybeAddElseIf(uint cur, uint elseto, uint to);
|
|
void writePendingElse();
|
|
|
|
const char *get_num_string(int i);
|
|
char *get_var(char *buf);
|
|
char *get_var_or_word(char *buf, char condition);
|
|
char *get_var_or_byte(char *buf, char condition);
|
|
char *get_var_until_0xff(char *buf);
|
|
char *putascii(char *buf, int i);
|
|
char *get_ascii(char *buf);
|
|
char *add_a_tok(char *buf, int type);
|
|
char *do_tok(char *buf, const char *text, int args);
|
|
void do_decodeparsestring_v2(char *buf, byte opcode);
|
|
void do_actorset_v12(char *buf, byte opcode);
|
|
void do_actorset(char *buf, byte opcode);
|
|
void AddToExprStack(char *s);
|
|
char *GetFromExprStack(char *buf);
|
|
void do_expr_code(char *buf);
|
|
void do_load_code_to_string(char *buf, byte opcode);
|
|
void do_resource_v2(char *buf, byte opcode);
|
|
void do_resource(char *buf, byte opco);
|
|
void do_pseudoRoom(char *buf);
|
|
void do_room_ops(char *buf);
|
|
void do_room_ops_old(char *buf, byte master_opcode);
|
|
void do_cursor_command(char *buf);
|
|
void do_verbops_v2(char *buf, byte opcode);
|
|
void do_verbops(char *buf, byte opcode);
|
|
void do_print_ego(char *buf, byte opcode);
|
|
void do_unconditional_jump(char *buf);
|
|
void emit_if(char *buf, char *condition);
|
|
void do_if_code(char *buf, byte opcode);
|
|
void do_if_state_code(char *buf, byte opcode);
|
|
void do_varset_code(char *buf, byte opcode);
|
|
void do_matrix_ops(char *buf, byte opcode);
|
|
void get_tok_V12(char *buf);
|
|
void get_tok_V345(char *buf);
|
|
int skipVerbHeader_V12(byte *p);
|
|
int skipVerbHeader_V34(byte *p);
|
|
byte *skipVerbHeader_V5(byte *p);
|
|
|
|
public:
|
|
DeScumm(File& _input, int size, int scummVersion);
|
|
|
|
private:
|
|
char *output;
|
|
|
|
const char *getVarName(uint var);
|
|
void push(StackEnt * se);
|
|
void invalidop(const char *cmd, int op);
|
|
byte *skipVerbHeader_V8(byte *p);
|
|
int skipVerbHeader_V67(byte *p);
|
|
StackEnt *se_new(int type);
|
|
void se_free(StackEnt * se);
|
|
StackEnt *se_neg(StackEnt * se);
|
|
StackEnt *se_int(int i);
|
|
StackEnt *se_var(int i);
|
|
StackEnt *se_array(int i, StackEnt * dim2, StackEnt * dim1);
|
|
StackEnt *se_oper(StackEnt * a, int op);
|
|
StackEnt *se_oper(StackEnt * a, int op, StackEnt * b);
|
|
StackEnt *se_complex(const char *s);
|
|
char *se_astext(StackEnt * se, char *where, bool wantparens = true);
|
|
StackEnt *pop();
|
|
void kill(StackEnt * se);
|
|
void doAssign(StackEnt * dst, StackEnt * src);
|
|
void doAdd(StackEnt * se, int val);
|
|
StackEnt *dup(StackEnt * se);
|
|
void writeArray(int i, StackEnt * dim2, StackEnt * dim1, StackEnt * value);
|
|
void writeVar(int i, StackEnt * value);
|
|
void addArray(int i, StackEnt * dim1, int val);
|
|
void addVar(int i, int val);
|
|
StackEnt *se_get_string();
|
|
StackEnt *se_get_list();
|
|
void ext(const char *fmt);
|
|
void jump();
|
|
void jumpif(StackEnt * se, bool negate);
|
|
void next_line_V8();
|
|
void next_line_V67();
|
|
|
|
};
|
|
|
|
#endif
|