public static void fdwarrio_decode() {
        char xortable[][]
                = {
                    /* note how the first lines are highly repetitive, while the */
                    /* last ones get more and more unique. */
                    {0x00, 0x00, 0x14, 0x14, 0x14, 0x14, 0x00, 0x00}, /* .0.0..0..x..x..x */
                    {0x00, 0x11, 0x00, 0x11, 0x11, 0x00, 0x11, 0x00}, /* .0.0..1..x..x..x */
                    {0x00, 0x05, 0x05, 0x00, 0x00, 0x05, 0x05, 0x00}, /* .0.1..0..x..x..x */
                    {0x00, 0x00, 0x44, 0x44, 0x14, 0x14, 0x50, 0x50}, /* .0.1..1..x..x..x */
                    {0x00, 0x00, 0x14, 0x14, 0x50, 0x50, 0x44, 0x44}, /* .1.0..0..x..x..x */
                    {0x00, 0x05, 0x05, 0x00, 0x50, 0x55, 0x55, 0x50}, /* .1.0..1..x..x..x */
                    {0x00, 0x11, 0x05, 0x14, 0x14, 0x05, 0x11, 0x00}, /* .1.1..0..x..x..x */
                    {0x00, 0x41, 0x05, 0x44, 0x14, 0x55, 0x11, 0x50}, /* .1.1..1..x..x..x */
                    {0x00, 0x11, 0x05, 0x14, 0x50, 0x41, 0x55, 0x44} /* extra line for data decode */};
        int A;
        UBytePtr rom = memory_region(REGION_CPU1);
        int diff = memory_region_length(REGION_CPU1) / 2;

        memory_set_opcode_base(0, new UBytePtr(rom, diff));

        for (A = 0x0000; A < 0x8000; A++) {
            int row, col;
            char src;

            src = rom.read(A);

            /* pick the translation table from bits 0, 3, 6, 9, 12 and 14 of the address */
            row = (A & 1) + (((A >> 3) & 1) << 1) + (((A >> 6) & 1) << 2)
                    + (((A >> 9) & 1) << 3) + (((A >> 12) & 1) << 4) + (((A >> 14) & 1) << 5);

            /* pick the offset in the table from bits 0, 2, 4 and 6 of the source data */
            col = ((src >> 0) & 1) + (((src >> 2) & 1) << 1) + (((src >> 4) & 1) << 2);
            /* the bottom half of the translation table is the mirror image of the top */
            if ((src & 0x40) != 0) {
                col = 7 - col;
            }

            /* decode the opcodes */
            rom.write(A + diff, src ^ xortable[row >> 3][col] ^ 0x40);
            if ((row & 1) != 0) {
                rom.write(A + diff, rom.read(A + diff) ^ 0x10);
            }
            if ((row & 2) != 0) {
                rom.write(A + diff, rom.read(A + diff) ^ 0x04);
            }
            if ((row & 4) != 0) {
                rom.write(A + diff, rom.read(A + diff) ^ 0x01);
            }

            /* decode the data */
            row++;	/* the data XOR table is shifted by one position!!!! */

            rom.write(A, src ^ xortable[row >> 3][col]);
            if ((row & 1) != 0) {
                rom.write(A, rom.read(A) ^ 0x10);
            }
            if ((row & 2) != 0) {
                rom.write(A, rom.read(A) ^ 0x04);
            }
            if ((row & 4) != 0) {
                rom.write(A, rom.read(A) ^ 0x01);
            }
        }

        /* copy the opcodes from the not encrypted part of the ROMs */
        for (A = 0x8000; A < diff; A++) {
            rom.write(A + diff, rom.read(A));
        }
    }