Subversion Repositories display

Rev

Rev 521 | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
 * Copyright (C) 2007 Steve Ratcliffe
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License version 2 as
 *  published by the Free Software Foundation.
 *
 *  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.
 *
 *
 * Author: Steve Ratcliffe
 * Create date: Dec 16, 2007
 */

package test.display;

import uk.me.parabola.imgfmt.Utils;

/**
 * Standalone program to display a TDB file.
 *
 * @author Steve Ratcliffe
 */

public class TdbDisplay extends CommonDisplay {
        private long nextStart;
        private int codePage = 1252;

        protected void print() {
                while (reader.position() < filelen) {
                        printBlock();
                }
        }

        private void printBlock() {
                byte bid = peek();
                switch (bid) {
                case 0x42: // B
                        printOverviewBlock();
                        break;
                case 0x44: // D
                        printCopyrightBlock();
                        break;
                case 0x4c: // L
                        printDetailBlock();
                        break;
                case 0x50: // P
                        printHeaderBlock();
                        break;
                case 0x54: // T
                        printTBlock();
                        break;
                case 0x52: // R
                        printRBlock();
                        break;
                case 0x53: // S
                        printSBlock();
                        break;
                default:
                        printUnknown();
                        break;
                }
        }

        private void printSBlock() {
                Displayer d = new Displayer(reader);
                String text = "Region block";
                d.setTitle(text);
                int len = blockId(d, text);

                long end = reader.position() + len;
                while (reader.position() < end) {
                        d.byteValue("Region %d?");
                        d.byteValue("Subregion %d");
                        d.zstringValue("name: %s");
                }
                d.print(outStream);
                outStream.flush();
        }

        private void printRBlock() {
                Displayer d = new Displayer(reader);
                String text = "Area block";
                d.setTitle(text);
                blockId(d, text);

                d.byteValue("region %d");
                d.zstringValue("name: %s");
                d.print(outStream);
                outStream.flush();
        }

        private void printTBlock() {
                Displayer d = new Displayer(reader);
                String text = "T block";
                d.setTitle(text);
                blockId(d, text);

                // All unknown, but A,B,C,D appear to be more important in that if you
                // change them it will break.
                d.charValue("unk1 %04x");
                d.byteValue("A %02x");
                d.int3Value("unk2 %06x");
                d.int3Value("unk3 %06x");
                d.byteValue("B %02x");
                d.charValue("unk4 %04x");
                d.byteValue("C %02x");
                d.intValue("unk5 %08x");
                d.byteValue("D %02x");
                d.charValue("unk6 %04x");
                d.print(outStream);
                outStream.flush();
        }

        private byte peek() {
                long pos = reader.position();
                byte b = reader.get();
                reader.position(pos);
                return b;
        }

        private void printHeaderBlock() {
                Displayer d = new Displayer(reader);
                String text = "Header block";
                d.setTitle(text);

                blockId(d, text);

                d.charValue("Product ID %d");
                d.charValue("Family ID %d");
                d.charValue("TDB version %d");
                d.zstringValue("Series name: %s");
                d.charValue("Product version %d");
                d.zstringValue("Family name: %s");

                d.byteValue("unk %d");
                d.byteValue("lowest map level?? %d");
                d.byteValue("unk %d");
                d.byteValue("unk %d");
                d.byteValue("unk %d");
                d.intValue("unk %d");
                d.byteValue("unk %d");
                d.byteValue("highest routable?? %d");
                d.intValue("unk %d");
                d.intValue("unk %d");
                d.intValue("unk %d");
                d.intValue("unk %d");
                d.int3Value("unk %d");
                codePage = d.intValue("codepage %d");
                d.intValue("unk %d");
                d.byteValue("unk %d");
                d.charValue("unk %d");

                printRemainder(d);

                d.print(outStream);
                outStream.flush();
        }

        private void printDetailBlock() {
                Displayer d = new Displayer(reader);
                String text = "Detail block";
                d.setTitle(text);

                long start = reader.position();

                int len = mapBlockCommon(d, text);

                d.charValue("?");
                int n = d.charValue("n");

                int count = 1;
                d.intValue("file" + count++ + " size %d");
                d.intValue("file" + count++ + " size %d");
                d.intValue("file" + count++ + " size %d");
                if (n > 3) d.intValue("file" + count++ + " size %d");
                if (n > 4) d.intValue("file" + count++ + " size %d");
                if (n > 5) d.intValue("file" + count++ + " size %d");
                if (n > 6) d.intValue("file" + count + " size %d");

                if (len > 66) {
                        //d.rawValue(7, "intro");
                        d.byteValue("detail unk1 %d");
                        d.byteValue("region %d?");
                        d.byteValue("subregion %d");
                        d.intValue("?size %d");
                        count = 1;
                        d.zstringValue("file" + count++ + " %s");
                        d.zstringValue("file" + count++ + " %s");
                        d.zstringValue("file" + count++ + " %s");
                        if (n > 3) d.zstringValue("file" + count++ + " %s");
                        if (n > 4) d.zstringValue("file" + count++ + " %s");
                        if (n > 5) d.zstringValue("file" + count++ + " %s");
                        if (n > 6) d.zstringValue("file" + count + " %s");
                }
                d.rawValue((int) (len - (reader.position() - start - 3)));
                d.print(outStream);
        }

        private void printOverviewBlock() {
                Displayer d = new Displayer(reader);
                String text = "Overview block";
                d.setTitle(text);

                mapBlockCommon(d, text);

                d.print(outStream);
        }

        double toDegrees(int tdbUnits) {
                return tdbUnits * 45.0 / (1 << 29);
        }
        private int mapBlockCommon(Displayer d, String text) {
                int len = blockId(d, text);
                //d.rawValue(len);
                d.intValue("Map number %08d");
                d.intValue("Parent map %08d");

                DisplayItem item = d.intItem();
                double n = toDegrees(item.getValue());
                item.addText("North %.7f", (n));

                item = d.intItem();
                double e = toDegrees(item.getValue());
                item.addText("East %.7f", (e));

                item = d.intItem();
                double s = toDegrees(item.getValue());
                item.addText("South %.7f", (s));

                item = d.intItem();
                double w = toDegrees(item.getValue());
                item.addText("West %.7f", (w ));

                d.item().addText("Area %f", (n - s) * (e-w));
                d.zstringValue("Description: %s");
                return len;
        }

        private void printCopyrightBlock() {
                Displayer d = new Displayer(reader);
                String text = "Copyright block";
                d.setTitle(text);

                int len = blockId(d, text);
                d.print(outStream);
                printCopyrightSegment(d, len);
        }

        private void printCopyrightSegment(Displayer d, int len) {
                d.setTitle("Copyright segment");
                long end = reader.position() + len;
                while (reader.position() < end) {
                        d.byteValue("~");
                        d.byteValue("~");
                        d.charValue("~");
                        d.zstringValue("text %s", "cp" + codePage).length();
                        d.print(outStream);
                }
        }

        private void printUnknown() {
                Displayer d = new Displayer(reader);
                String text = "Unknown block";
                d.setTitle(text);

                int len = blockId(d, text);
                d.rawValue(len);

                d.print(outStream);
        }

        private void printRemainder(Displayer d) {
                if (nextStart > reader.position()) {
                        d.rawValue((int) (nextStart - reader.position()));
                }
        }

        private int blockId(Displayer d, String text) {
                d.byteValue(text + " %c");

                int len = d.charValue("block len %d");

                nextStart = reader.position() + len;
                return len;
        }

        public static void main(String[] args) {
                if (args.length < 1) {
                        System.err.println("Usage: tdbdisplay <filename>");
                        System.exit(1);
                }

                CommonDisplay td = new TdbDisplay();
                td.display(args[0]);
        }
}