Subversion Repositories display

Rev

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

/*
 * Copyright (C) 2009.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 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.
 */

package test.display;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Standalone program to display an MDR file.  There is no freely available
 * knowledge of the file format.
 *
 * Can produce a massive file, so may take some time to write.
 *
 * @author Steve Ratcliffe
 */

public class MdrSummary extends CommonDisplay {
        private static final int NSECT = 41;

        private final Section[] sections = new Section[NSECT];

        // Sections to be displayed
        private final boolean[] wanted = new boolean[NSECT];

        protected void print() {
                readHeaderLen();

                readHeader();

                Section end = new Section("END OF FILE", filelen, 0);
                sections[sections.length - 1] = end;

                printDetails();
                printReverseDetails();
        }

        private void printReverseDetails() {
                Section section = sections[1];
                if (section.getRecordSize() == 4)
                        return;
                reader.position(section.getStart());
                long end = section.getEnd();

                List<Integer> offsets = new ArrayList<Integer>();
                while ((reader.position() < end)) {
                        reader.get4();
                        int offset = reader.get4();
                        offsets.add(offset);
                }

                Integer[] subtotals = new Integer[20];
                for (int off : offsets) {
                        reader.position(off);
                        int len = reader.get2u();

                        int sub = 0;
                        int lastLen = 0;
                        while (reader.position() < off + len) {
                                sub++;
                                reader.get4();
                                int sublen;
                                if (sub == 2)
                                        sublen = lastLen;
                                else
                                        sublen = reader.get4();
                                lastLen = sublen;
                                if (sublen > 0) {
                                        if (subtotals[sub] == null)
                                                subtotals[sub] = 0;
                                        subtotals[sub] += sublen;
                                }
                        }
                }

                int sub = 0;
                for (Integer tot : subtotals) {
                        if (tot != null)
                                System.out.printf("Sub%-2d %-5s total %d\n", sub, Mdr1SubFileDisplay.subToMdr(sub), tot);
                        sub++;
                }
        }

        private void printDetails() {
                int number = 0;
                for (Section s : sections) {
                        if (s != null) {
                                if (s.getLen() > 0)
                                        System.out.printf("MDR %-2d ", number);
                                else
                                        System.out.printf("    %-2d ", number);
                                if (s.getRecordSize() > 0)
                                        System.out.printf("NR=%-7d(%06x) RS=%-2d ",
                                                        s.getNumberOfRecords(),
                                                        s.getNumberOfRecords(),
                                                        s.getRecordSize());
                                else
                                        System.out.printf("DS=%-10d(%08x)  ", s.getLen(), s.getLen());
                                System.out.printf("magic=0x%08x\n", s.getMagic());
                        }

                        number++;
                }
        }

        private void readHeader() {
                int codePage = reader.get2u();
                int id1 = reader.get2u();
                int id2 = reader.get2u();
                int unk3 = reader.get2u();
                System.out.printf("codePage=%d id1=%d id2=%d unk=0x%04x hdrLen=%d\n", codePage, id1, id2, unk3, getHeaderLen());

                addSection(1, true, true);
                addSection(2, true, true);
                addSection(3, true, true);
                addSection(4, true, true);
                addSection(5, true, true);
                addSection(6, true, true);
                addSection(7, true, true);
                addSection(8, true, true);
                addSection(9, true, true);
                addSection(10, false, true);
                addSection(11, true, true);
                addSection(12, true, true);
                addSection(13, true, true);
                addSection(14, true, true);
                addSection(15, false, false); // could consider compressed string flag as 1 byte magic
                int flag = reader.get();
                System.out.printf("Compressed strings flag=0x%04x\n", flag);
                addSection(16, true, true);
                addSection(17, false, true);
                addSection(18, true, true);
                addSection(19, true, true);
                // seen headers stop here: 286 / 0x011e
                addSection(20, true, true);
                addSection(21, true, true);
                addSection(22, true, true);
                addSection(23, true, true);
                addSection(24, true, true);
                addSection(25, true, true);
                addSection(26, true, true);
                addSection(27, true, true);
                addSection(28, true, true);
                addSection(29, true, true);
                // seen headers stop here: 426 / 0x01aa
                addSection(30, true, true);
                addSection(31, false, false);
                addSection(32, true, true);
                addSection(33, false, false);
                addSection(34, true, true);
                addSection(35, true, true);
                addSection(36, true, true);
                addSection(37, true, true);
                addSection(38, true, true);
                addSection(39, true, true);
                addSection(40, true, true);
                // seen headers stop here: 568 / 0x0238
                // looks like three sections, two with 4 ints, one with 5 ints
                // seen headers stop here: 620 / 0x26c
                // mostly zeros
                // seen headers stop here: 668 / 0x029c
        // possibly some sections, but mostly zeros so difficult to tell
                // seen headers stop here: 700 / 0x02bc
                // seen headers stop here: 708 / 0x02c4
                // at 0x02dc, maybe 5 sections without magic or recsize
                // not seen anything after 772 / 0x0304
        }

        private Section addSection(int n, boolean withReclen, boolean withMagic) {
                if (reader.position() >= getHeaderLen())
                        return null;
                long start = reader.get4();
                int len = reader.get4();

                Section section = new Section("MDR " + n, start, len);
                if (withReclen) {
                        int reclen = reader.get2u();
                        section.setRecordSize(reclen);
                }
                if (withMagic) {
                        int magic = reader.get4();
                        section.setMagic(magic);
                }

                sections[n] = section;
                return section;
        }


        /**
         * Print a summary of an mdr file.
         */

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

                MdrSummary md = new MdrSummary();

                String name = args[0];
                if (args.length > 1) {
                        if (args[1].equals("!")) {
                                Arrays.fill(md.wanted, true);
                                for (String a : Arrays.asList(args).subList(2, args.length))
                                        md.wanted[Integer.parseInt(a)] = false;
                        } else {
                                for (String a : Arrays.asList(args).subList(1, args.length))
                                        md.wanted[Integer.parseInt(a)] = true;
                        }
                } else {
                        Arrays.fill(md.wanted, true);
                }

                md.display(name, "MDR");
        }
}