Ticket #9024: 2nd.patch

File 2nd.patch, 5.1 KB (added by SF/kjdf, 15 years ago)
  • misc.h

     
     1#ifndef MISC_H
     2#define MISC_H
     3
     4#include <fstream>
     5
     6using namespace std;
     7
     8typedef unsigned char uint8;
     9typedef unsigned short uint16;
     10typedef unsigned uint32;
     11
     12uint32 read_be_uint32(ifstream &f) {
     13        uint32 ret = 0;
     14        ret |= f.get() << 24;
     15        ret |= f.get() << 16;
     16        ret |= f.get() << 8;
     17        ret |= f.get();
     18        return ret;
     19}
     20
     21uint32 read_le_uint32(ifstream &f) {
     22        uint32 ret = 0;
     23        ret |= f.get();
     24        ret |= f.get() << 8;
     25        ret |= f.get() << 16;
     26        ret |= f.get() << 24;
     27        return ret;
     28}
     29
     30uint16 read_le_uint16(ifstream &f) {
     31        uint16 ret = 0;
     32        ret |= f.get();
     33        ret |= f.get() << 8;
     34        return ret;
     35}
     36
     37#endif
  • parser.h

     
     1#ifndef READER_H
     2#define READER_H
     3
     4
     5#include <fstream>
     6#include <vector>
     7
     8#include <cassert>
     9#include <cstring>
     10#include <cstdio>
     11
     12using namespace std;
     13
     14
     15#include "misc.h"
     16#include "instruction.h"
     17
     18
     19using namespace std;
     20
     21
     22struct Parser {
     23        virtual vector<Instruction*> parseFile(const char *filename) = 0;
     24};
     25
     26
     27struct Reader {
     28        virtual void readInstruction(ifstream &f, vector<Instruction*> &v, uint32 addr) = 0;
     29};
     30
     31
     32struct SimpleReader : public Reader {
     33
     34        string _description;
     35        int _skip;
     36
     37        SimpleReader(string description, int skip=0) : _description(description), _skip(skip) {};
     38
     39        virtual void readInstruction(ifstream &f, vector<Instruction*> &v, uint32 addr) {
     40                for (int i = 0; i < _skip; i++) {
     41                        char c = f.get();
     42                        printf("SKIPPED: 0x%x\n", (unsigned int) c);
     43                }
     44                v.push_back(new Instruction(_description, addr));
     45        }
     46};
     47
     48
     49struct SubopcodeReader : public Reader {
     50
     51        Reader *_dispatchTable[256];
     52
     53        SubopcodeReader() {
     54                memset(_dispatchTable, 0, sizeof(_dispatchTable));
     55        }
     56
     57        void registerOpcode(uint8 opcode, Reader *reader) {
     58                _dispatchTable[opcode] = reader;
     59        }
     60
     61        void readInstruction(ifstream& f, vector<Instruction*> &v, uint32 addr) {
     62                uint8 opcode = f.get();
     63                Reader* reader = _dispatchTable[opcode];
     64                assert(reader);
     65                reader->readInstruction(f, v, addr);
     66        }
     67};
     68
     69
     70struct Scumm6Parser {
     71
     72        Reader *_dispatchTable[256];
     73
     74        Scumm6Parser() {
     75                memset(_dispatchTable, 0, sizeof(_dispatchTable));
     76                _dispatchTable[0] = new SimpleReader("zero", 0);
     77                _dispatchTable[1] = new SimpleReader("one", 1);
     78                _dispatchTable[2] = new SimpleReader("two", 2);
     79                SubopcodeReader *three = new SubopcodeReader();
     80                three->registerOpcode(1, new SimpleReader("three/1", 1));
     81                three->registerOpcode(2, new SimpleReader("three/2", 2));
     82                _dispatchTable[3] = three;
     83                _dispatchTable[4] = new SimpleReader("four", 4);
     84        }
     85
     86        void parseHeader(ifstream &f) {
     87                switch (read_be_uint32(f)) {
     88                case 'LSC2':
     89                        read_le_uint32(f);
     90                        read_le_uint32(f); // script number
     91                        break;
     92                case 'LSCR':
     93                        read_le_uint32(f);
     94                        f.get(); // script number
     95                        break;
     96                case 'SCRP':
     97                case 'ENCD':
     98                case 'EXCD':
     99                        read_le_uint32(f);
     100                        break;
     101                case 'VERB':
     102                        read_le_uint32(f);
     103                        uint16 minOffset = 65535;
     104                        for (uint8 code = f.get(); code != 0; code = f.get()) {
     105                                uint16 offset = read_le_uint16(f);
     106                                printf("%2X - %.4X\n", code, offset);
     107                                if (offset < minOffset)
     108                                        minOffset = offset;
     109                        }
     110                        f.seekg(minOffset);
     111                        break;
     112                }
     113        }
     114
     115        vector<Instruction*> parseFile(const char *filename) {
     116                vector<Instruction*> v;
     117                ifstream f;
     118                f.open(filename, ios::binary);
     119                parseHeader(f);
     120                while (true) {
     121                        uint8 addr = f.tellg();
     122                        uint8 opcode = f.get();
     123                        if (f.eof())
     124                                return v;
     125                        Reader* reader = _dispatchTable[opcode];
     126                        assert(reader);
     127                        reader->readInstruction(f, v, addr);
     128                }
     129        }
     130
     131};
     132
     133
     134#endif
  • decompiler.cc

     
     1#include <iostream>
     2#include <vector>
     3
     4using namespace std;
     5
     6#include "parser.h"
     7#include "instruction.h"
     8
     9
     10int main(int argc, char **argv) {
     11        vector<Instruction*> v = Scumm6Parser().parseFile(argv[1]);
     12        for (unsigned i = 0; i < v.size(); i++)
     13                cout << v[i]->_addr << ": " << v[i]->_description << endl;
     14        return 0;
     15}
  • instruction.h

     
     1#ifndef INSTRUCTION_H
     2#define INSTRUCTION_H
     3
     4#include <string>
     5
     6#include "misc.h"
     7
     8struct Instruction {
     9        string _description;
     10        uint32 _addr;
     11        Instruction(string description, uint32 addr) : _description(description), _addr(addr) {}
     12};
     13
     14#endif
  • Makefile

     
     1.PHONY: clean
     2
     3DEPS = $(patsubst %.cc,%.o,$(*.cc))
     4
     5#%.o: %.cc
     6#       g++ -Wall -g -c $< -o $@
     7
     8decompiler: decompiler.o $(DEPS)
     9        g++ -Wall -g $^ -o $@
     10
     11decompiler.o: decompiler.cc misc.h instruction.h parser.h
     12        g++ -Wall -g -c decompiler.cc -o decompiler.o
     13
     14clean:
     15        rm -rf decompiler *.o