home *** CD-ROM | disk | FTP | other *** search
/ Amiga Elysian Archive / AmigaElysianArchive.iso / games / utils / ztools.lha / ztools / src / txd.c < prev    next >
C/C++ Source or Header  |  1992-12-17  |  35KB  |  1,014 lines

  1. /* txd.c V1.3
  2.  *
  3.  * Z code disassembler.
  4.  *
  5.  * No switches, no nothing, just give it a story file name, and you're off.
  6.  * Requires txio.c and tx.h. To reduce some CPU cost define NO_LOW_SCAN, but
  7.  * some low address routines may be skipped.
  8.  *
  9.  * Currently only works for type 3, 4 and 5 games.
  10.  *
  11.  * Usage: txd story-file-name
  12.  *
  13.  * Mark Howell 25 August 1992 howell_ma@movies.enet.dec.com
  14.  *
  15.  * History:
  16.  *    Merge separate disassemblers for each type into one program
  17.  *    Fix logic error in low routine scan
  18.  *    Force PC past start PC in middle routine scan
  19.  */
  20.  
  21. #include "tx.h"
  22.  
  23. #define MAX_PCS 100
  24.  
  25. #ifdef __STDC__
  26. static int decode_code (void);
  27. static int decode_inputs (void);
  28. static int decode_opcode (void);
  29. static int decode_operands (const char *, int, int, int);
  30. static int decode_outputs (void);
  31. static int decode_routine (void);
  32. static void decode_operand (int, int);
  33. static void decode_program (void);
  34. static void decode_strings (unsigned long);
  35. static void scan_strings (unsigned long);
  36. static int lookup_string (unsigned long);
  37. static void scan_words (void);
  38. static unsigned long lookup_word (unsigned long);
  39. #else
  40. static int decode_code ();
  41. static int decode_inputs ();
  42. static int decode_opcode ();
  43. static int decode_operands ();
  44. static int decode_outputs ();
  45. static int decode_routine ();
  46. static void decode_operand ();
  47. static void decode_program ();
  48. static void decode_strings ();
  49. static void scan_strings ();
  50. static int lookup_string ();
  51. static void scan_words ();
  52. static unsigned long lookup_word ();
  53. #endif
  54.  
  55. static unsigned long pctable[MAX_PCS];
  56. static int pcindex = 0;
  57.  
  58. static unsigned long start_data_pc, end_data_pc;
  59.  
  60. static decode_t decode;
  61. static opcode_t opcode;
  62.  
  63. #ifdef __STDC__
  64. int main (int argc, char *argv [])
  65. #else
  66. int main (argc, argv)
  67. int argc;
  68. char *argv [];
  69. #endif
  70. {
  71.  
  72.     if (argc != 2) {
  73.         fprintf (stderr, "Usage: %s data-file\n", argv [0]);
  74.         exit (EXIT_FAILURE);
  75.     }
  76.  
  77.     open_story (argv [1]);
  78.  
  79.     configure (V3, V5);
  80.  
  81.     load_cache ();
  82.  
  83.     decode.pc = (unsigned long) h_data_size;
  84.     decode.initial_pc = (unsigned long) h_start_pc;
  85.  
  86.     printf ("Resident data ends at %lx, program starts at %lx, file ends at %lx\n",
  87.             (unsigned long) h_data_size, (unsigned long) h_start_pc, (unsigned long) h_file_size * story_scaler);
  88.  
  89.     printf ("\nStarting analysis pass at address %lx\n", decode.pc);
  90.  
  91.     decode.first_pass = 1;
  92.     decode_program ();
  93.  
  94.     scan_strings (decode.pc);
  95.     scan_words ();
  96.  
  97.     printf ("\nEnd of analysis pass, low address = %lx, high address = %lx\n",
  98.             decode.low_address, decode.high_address);
  99.     if (start_data_pc)
  100.         printf ("\nData PC range = %lx to %lx\n", start_data_pc, end_data_pc);
  101.  
  102.     decode.first_pass = 0;
  103.     decode_program ();
  104.  
  105.     decode_strings (decode.pc);
  106.  
  107.     close_story ();
  108.  
  109.     exit (EXIT_SUCCESS);
  110.  
  111.     return (0);
  112.  
  113. }/* main */
  114.  
  115. /* decode_program - Decode Z code in two passes */
  116.  
  117. #ifdef __STDC__
  118. static void decode_program (void)
  119. #else
  120. static void decode_program ()
  121. #endif
  122. {
  123.     unsigned long pc, low_pc, high_pc, prev_low_pc, prev_high_pc;
  124.     int flag, vars;
  125.  
  126.     if (decode.first_pass) {
  127. #if !defined(NO_LOW_SCAN)
  128.         /* Scan for low routines */
  129.         decode.pc = (decode.pc + (story_scaler - 1)) & ~(story_scaler - 1);
  130.         for (pc = decode.pc, flag = 0; pc < (decode.initial_pc - 1) && !flag; pc += story_scaler) {
  131.             decode.pc = pc;
  132.             while (decode.pc < (decode.initial_pc - 1) && (decode_routine () == END_OF_ROUTINE) && pcindex == 0)
  133.                 decode.pc = (decode.pc + (story_scaler - 1)) & ~(story_scaler - 1);
  134.             if (decode.pc == (decode.initial_pc - 1)) {
  135.                 decode.pc = pc;
  136.                 flag = 1;
  137.             }
  138.             pcindex = 0;
  139.         }
  140.         if (!flag)
  141. #endif /* !defined(NO_LOW_SCAN) */
  142.             decode.pc = decode.initial_pc - 1;
  143.         /* Fill in middle routines */
  144.         decode.low_address = decode.pc;
  145.         decode.high_address = decode.pc;
  146.         start_data_pc = 0;
  147.         end_data_pc = 0;
  148.         do {
  149.             prev_low_pc = decode.low_address;
  150.             prev_high_pc = decode.high_address;
  151.             flag = 0;
  152.             pcindex = 0;
  153.             low_pc = decode.low_address;
  154.             high_pc = decode.high_address;
  155.             pc = decode.pc = decode.low_address;
  156.             while (decode.pc <= high_pc || decode.pc <= (decode.initial_pc - 1)) {
  157.                 if (start_data_pc == decode.pc)
  158.                     decode.pc = end_data_pc;
  159.                 if (decode_routine () != END_OF_ROUTINE) {
  160.                     if (start_data_pc == 0)
  161.                         start_data_pc = decode.pc;
  162.                     flag = 1;
  163.                     end_data_pc = 0;
  164.                     pcindex = 0;
  165.                     pc = (pc + (story_scaler - 1)) & ~(story_scaler - 1);
  166.                     do {
  167.                         pc += story_scaler;
  168.                         vars = (char) read_data_byte (&pc);
  169.                         pc--;
  170.                     } while (vars < 0 || vars > 15);
  171.                     decode.pc = pc;
  172.                 } else {
  173.                     if (start_data_pc && end_data_pc == 0)
  174.                         end_data_pc = pc;
  175.                     pc = (decode.pc + (story_scaler - 1)) & ~(story_scaler - 1);
  176.                     if (!flag) {
  177.                         low_pc = decode.low_address;
  178.                         high_pc = decode.high_address;
  179.                     }
  180.                 }
  181.             }
  182.             decode.low_address = low_pc;
  183.             decode.high_address = high_pc;
  184.         } while (low_pc < prev_low_pc || high_pc > prev_high_pc);
  185.         /* Scan for high routines */
  186.         pc = decode.pc;
  187.         while (decode_routine () == END_OF_ROUTINE) {
  188.             decode.high_address = pc;
  189.             pc = decode.pc;
  190.         }
  191.     } else {
  192.         printf ("\n[start of code at %lx]\n", decode.low_address);
  193.         for (decode.pc = decode.low_address;
  194.              decode.pc <= decode.high_address; )
  195.             decode_routine ();
  196.         printf ("\n[end of code at %lx]\n", decode.pc);
  197.     }
  198.  
  199. }/* decode_program */
  200.  
  201. /* decode_routine - Decode a routine from start address to last instruction */
  202.  
  203. #ifdef __STDC__
  204. static int decode_routine (void)
  205. #else
  206. static int decode_routine ()
  207. #endif
  208. {
  209.     unsigned long old_pc;
  210.     int vars, status, count, i;
  211.  
  212.     if (decode.first_pass) {
  213.         old_pc = decode.pc;
  214.         decode.pc = (decode.pc + (story_scaler - 1)) & ~(story_scaler - 1);
  215.         vars = read_data_byte (&decode.pc);
  216.         if (vars >= 0 && vars <= 15) {
  217.             if (h_type == V3 || h_type == V4)
  218.                 for (; vars; vars--)
  219.                     read_data_word (&decode.pc);
  220.             if (decode_code () == END_OF_ROUTINE)
  221.                 return (END_OF_ROUTINE);
  222.         }
  223.         decode.pc = old_pc;
  224.         if ((status = decode_code ()) != END_OF_ROUTINE) {
  225.             decode.pc = old_pc;
  226.             return (status);
  227.         }
  228.         pctable[pcindex++] = old_pc;
  229.         if (pcindex == MAX_PCS) {
  230.             fprintf (stderr, "\nFatal: too many orphan code fragments\n");
  231.             exit (EXIT_FAILURE);
  232.         }
  233.     } else {
  234.         if (decode.pc == start_data_pc) {
  235.             printf ("\n[start of data at %lx]\n\n", decode.pc);
  236.             count = 0;
  237.             while (decode.pc < end_data_pc) {
  238.                 printf ("[%04x]", (unsigned int) read_data_word (&decode.pc));
  239.                 if (++count == 13) {
  240.                     printf ("\n");
  241.                     count = 0;
  242.                 }
  243.             }
  244.             printf ("\n\n[end of data at %lx]\n", decode.pc);
  245.             decode.pc = end_data_pc;
  246.         }
  247.         for (i = 0; i < pcindex && decode.pc != pctable[i]; i++)
  248.             ;
  249.         if (i == pcindex) {
  250.             decode.pc = (decode.pc + (story_scaler - 1)) & ~(story_scaler - 1);
  251.             vars = read_data_byte (&decode.pc);
  252.             printf ("%soutine %lx, %d local",
  253.                     (decode.pc == decode.initial_pc) ? "\nMain r" : "\nR",
  254.                     (unsigned long) decode.pc - 1,
  255.                     vars);
  256.             if (vars != 1)
  257.                 printf ("s");
  258.             if (h_type == V3 || h_type == V4) {
  259.                 printf (" (");
  260.                 for (; vars; vars--) {
  261.                     printf ("%04x", (unsigned int) read_data_word (&decode.pc));
  262.                     if (vars > 1)
  263.                         printf (",");
  264.                 }
  265.                 printf (")");
  266.             }
  267.             printf ("\n\n");
  268.         } else
  269.             printf ("\norphan code fragment:\n\n");
  270.         status = decode_code ();
  271.     }
  272.  
  273.     return (status);
  274.  
  275. }/* decode_routine */
  276.  
  277. /* decode_code - grab opcode and determine the class */
  278.  
  279. #ifdef __STDC__
  280. static int decode_code (void)
  281. #else
  282. static int decode_code ()
  283. #endif
  284. {
  285.     int status;
  286.  
  287.     decode.high_pc = decode.pc;
  288.     do {
  289.         if (!decode.first_pass)
  290.             printf ("%5lx:  ", decode.pc);
  291.         opcode.opcode = read_data_byte (&decode.pc);
  292.         if (h_type == V5 && opcode.opcode == 0xbe) {
  293.             opcode.opcode = read_data_byte (&decode.pc);
  294.             opcode.class = EXTENDED_OPERAND;
  295.         } else if (opcode.opcode < 0x80)
  296.             opcode.class = TWO_OPERAND;
  297.         else
  298.             if (opcode.opcode < 0xb0)
  299.                 opcode.class = ONE_OPERAND;
  300.             else
  301.                 if (opcode.opcode < 0xc0)
  302.                     opcode.class = ZERO_OPERAND;
  303.                 else
  304.                     opcode.class = VARIABLE_OPERAND;
  305.         status = decode_opcode ();
  306.     } while (status == END_OF_INSTRUCTION);
  307.  
  308.     return (status);
  309.  
  310. }/* decode_code */
  311.  
  312. /* decode_opcode - Check and decode the opcode itself */
  313.  
  314. #define caseline(opc, text, operands, type1, type2) \
  315.     case opc: return (decode_operands (text, operands, type1, type2))
  316.  
  317. #ifdef __STDC__
  318. static int decode_opcode (void)
  319. #else
  320. static int decode_opcode ()
  321. #endif
  322. {
  323.     int code;
  324.  
  325.     code = opcode.opcode;
  326.  
  327.     switch (opcode.class) {
  328.  
  329.         case EXTENDED_OPERAND:
  330.             code &= 0x3f;
  331.             switch (code) {
  332.                 caseline (0x00, "SAVE",                 0,   STORE,   NONE);
  333.                 caseline (0x01, "RESTORE",              0,   STORE,   NONE);
  334.                 caseline (0x02, "SHIFT",                2,   STORE,   NONE);
  335.  
  336.                 caseline (0x04, "GRAPHICS",             1,   STORE,   NONE);
  337.  
  338.                 caseline (0x09, "SAVE UNDO",            0,   STORE,   NONE);
  339.                 caseline (0x0A, "RESTORE UNDO",         0,   STORE,   NONE);
  340.  
  341.                 default:
  342.                     return (decode_operands ("ILLEGAL", 0, ILLEGAL, NONE));
  343.             }
  344.  
  345.         case TWO_OPERAND:
  346.             code &= 0x1f;
  347.  
  348.         case VARIABLE_OPERAND:
  349.             code &= 0x3f;
  350.             switch (code) {
  351.  
  352.                 caseline (0x01, "JE",                  -4,  BRANCH,   NONE);
  353.                 caseline (0x02, "JLE",                  2,  BRANCH,   NONE);
  354.                 caseline (0x03, "JGE",                  2,  BRANCH,   NONE);
  355.                 caseline (0x04, "DEC_CHK",              2,  BRANCH,    VAR);
  356.                 caseline (0x05, "INC_CHK",              2,  BRANCH,    VAR);
  357.                 caseline (0x06, "COMPARE_POBJ",         2,  BRANCH,   NONE);
  358.                 caseline (0x07, "TEST",                 2,  BRANCH,   NONE);
  359.                 caseline (0x08, "OR",                   2,   STORE,   NONE);
  360.                 caseline (0x09, "AND",                  2,   STORE,   NONE);
  361.                 caseline (0x0A, "TEST_ATTR",            2,  BRANCH,   NONE);
  362.                 caseline (0x0B, "SET_ATTR",             2,    NONE,   NONE);
  363.                 caseline (0x0C, "CLEAR_ATTR",           2,    NONE,   NONE);
  364.                 caseline (0x0D, "STORE",                2,    NONE,    VAR);
  365.                 caseline (0x0E, "INSERT_OBJ",           2,    NONE,   NONE);
  366.                 caseline (0x0F, "LOADW",                2,   STORE,   NONE);
  367.                 caseline (0x10, "LOADB",                2,   STORE,   NONE);
  368.                 caseline (0x11, "GET_PROP",             2,   STORE,   NONE);
  369.                 caseline (0x12, "GET_PROP_ADDR",        2,   STORE,   NONE);
  370.                 caseline (0x13, "GET_NEXT_PROP",        2,   STORE,   NONE);
  371.                 caseline (0x14, "ADD",                  2,   STORE,   NONE);
  372.                 caseline (0x15, "SUB",                  2,   STORE,   NONE);
  373.                 caseline (0x16, "MUL",                  2,   STORE,   NONE);
  374.                 caseline (0x17, "DIV",                  2,   STORE,   NONE);
  375.                 caseline (0x18, "MOD",                  2,   STORE,   NONE);
  376.  
  377.                 caseline (0x20, "CALL",                -4,    CALL,   NONE);
  378.                 caseline (0x21, "STOREW",               3,    NONE,   NONE);
  379.                 caseline (0x22, "STOREB",               3,    NONE,   NONE);
  380.                 caseline (0x23, "PUT_PROP",             3,    NONE,   NONE);
  381.  
  382.                 caseline (0x25, "PRINT_CHAR",           1,   PCHAR,   NONE);
  383.                 caseline (0x26, "PRINT_NUM",            1,    NONE,   NONE);
  384.                 caseline (0x27, "RANDOM",               1,   STORE,   NONE);
  385.                 caseline (0x28, "PUSH",                 1,    NONE,   NONE);
  386.                 caseline (0x29, "POP",                  1,    NONE,    VAR);
  387.                 caseline (0x2A, "STATUS_SIZE",          1,    NONE,   NONE);
  388.                 caseline (0x2B, "SET_WINDOW",           1,    NONE,   NONE);
  389.  
  390.                 caseline (0x33, "SET_PRINT",           -2,    NONE,   NONE);
  391.                 caseline (0x34, "#RECORD_MODE",         1,    NONE,   NONE);
  392.                 caseline (0x35, "SOUND",               -4,    NONE,   NONE);
  393.  
  394.                 default:
  395.                     switch (h_type) {
  396.                         case V3:
  397.                             switch (code) {
  398.                                 caseline (0x24, "READ",                 2,    NONE,   NONE);
  399.                             }
  400.                         case V4:
  401.                             switch (code) {
  402.                                 caseline (0x19, "CALL",                 2,    CALL,   NONE);
  403.  
  404.                                 caseline (0x24, "READ",                -4,    NONE,   NONE);
  405.  
  406.                                 caseline (0x2C, "CALL",                -8,    CALL,   NONE);
  407.                                 caseline (0x2D, "ERASE_WINDOW",         1,    NONE,   NONE);
  408.                                 caseline (0x2E, "ERASE_LINE",           1,    NONE,   NONE);
  409.                                 caseline (0x2F, "SET_CURSOR",           2,    NONE,   NONE);
  410.  
  411.                                 caseline (0x31, "VIDEO_ATTR",           1,   VATTR,   NONE);
  412.                                 caseline (0x32, "SET_FORMAT",           1,    NONE,   NONE);
  413.  
  414.                                 caseline (0x36, "READ_CHAR",           -3,   STORE,   NONE);
  415.                                 caseline (0x37, "SCANW",               -4,   STORE, OBJECT);
  416.                             }
  417.                         case V5:
  418.                             switch (code) {
  419.                                 caseline (0x19, "CALL",                 2,    CALL,   NONE);
  420.                                 caseline (0x1A, "CALL",                 2,   NCALL,   NONE);
  421.                                 caseline (0x1B, "OPCODE 0x1B",          2,    NONE,   NONE);
  422.  
  423.                                 caseline (0x24, "READ",                -4,   STORE,   NONE);
  424.  
  425.                                 caseline (0x2C, "CALL",                -8,    CALL,   NONE);
  426.                                 caseline (0x2D, "ERASE_WINDOW",         1,    NONE,   NONE);
  427.                                 caseline (0x2E, "ERASE_LINE",           1,    NONE,   NONE);
  428.                                 caseline (0x2F, "SET_CURSOR",           2,    NONE,   NONE);
  429.  
  430.                                 caseline (0x31, "VIDEO_ATTR",           1,   VATTR,   NONE);
  431.                                 caseline (0x32, "SET_FORMAT",           1,    NONE,   NONE);
  432.  
  433.                                 caseline (0x36, "READ_CHAR",           -3,   STORE,   NONE);
  434.                                 caseline (0x37, "SCANW",               -4,   STORE, OBJECT);
  435.  
  436.                                 caseline (0x39, "CALL",                -4,   NCALL,   NONE);
  437.                                 caseline (0x3A, "CALL",                -8,   NCALL,   NONE);
  438.                                 caseline (0x3B, "PARSE",               -4,    NONE,   NONE);
  439.                                 caseline (0x3C, "ENCRYPT",              4,    NONE,   NONE);
  440.                                 caseline (0x3D, "BLOCK_COPY",           3,    NONE,   NONE);
  441.                                 caseline (0x3E, "PRINT_TEXT",          -3,    NONE,   NONE);
  442.                                 caseline (0x3F, "CHECK_VA_ARG",         1,  BRANCH,   NONE);
  443.                             }
  444.                     }
  445.                     return (decode_operands ("ILLEGAL", 0, ILLEGAL, NONE));
  446.             }
  447.  
  448.         case ONE_OPERAND:
  449.             code &= 0x0f;
  450.             switch (code) {
  451.                 caseline (0x00, "JZ",                   1,  BRANCH,   NONE);
  452.                 caseline (0x01, "GET_SIBLING",          1,   STORE, OBJECT);
  453.                 caseline (0x02, "GET_CHILD",            1,   STORE, OBJECT);
  454.                 caseline (0x03, "GET_PARENT",           1,   STORE,   NONE);
  455.                 caseline (0x04, "GET_PROP_LEN",         1,   STORE,   NONE);
  456.                 caseline (0x05, "INC",                  1,    NONE,    VAR);
  457.                 caseline (0x06, "DEC",                  1,    NONE,    VAR);
  458.                 caseline (0x07, "PRINT_ADDR",           1,    NONE,   NONE);
  459.  
  460.                 caseline (0x09, "REMOVE_OBJ",           1,    NONE,   NONE);
  461.                 caseline (0x0A, "PRINT_OBJ",            1,    NONE,   NONE);
  462.                 caseline (0x0B, "RET",                  1,  RETURN,   NONE);
  463.                 caseline (0x0C, "JUMP",                 1,    JUMP,   NONE);
  464.                 caseline (0x0D, "PRINT_PADDR",          1,    NONE,   NONE);
  465.                 caseline (0x0E, "LOAD",                 1,   STORE,    VAR);
  466.  
  467.                 default:
  468.                     switch (h_type) {
  469.                         case V3:
  470.                             switch (code) {
  471.                                 caseline (0x0F, "NOT",                  1,   STORE,   NONE);
  472.                             }
  473.                         case V4:
  474.                             switch (code) {
  475.                                 caseline (0x08, "CALL",                 1,    CALL,   NONE);
  476.  
  477.                                 caseline (0x0F, "NOT",                  1,   STORE,   NONE);
  478.                             }
  479.                         case V5:
  480.                             switch (code) {
  481.                                 caseline (0x08, "CALL",                 1,    CALL,   NONE);
  482.  
  483.                                 caseline (0x0F, "CALL",                 1,   NCALL,   NONE);
  484.                             }
  485.                     }
  486.                     return (decode_operands ("ILLEGAL", 0, ILLEGAL, NONE));
  487.             }
  488.  
  489.         case ZERO_OPERAND:
  490.             code &= 0x0f;
  491.             switch (code) {
  492.                 caseline (0x00, "RET           #TRUE",  0,  RETURN,   NONE);
  493.                 caseline (0x01, "RET           #FALSE", 0,  RETURN,   NONE);
  494.                 caseline (0x02, "PRINT",                0,    NONE,   TEXT);
  495.                 caseline (0x03, "PRINT_RET",            0,  RETURN,   TEXT);
  496.  
  497.                 caseline (0x07, "RESTART",              0,    NONE,   NONE);
  498.                 caseline (0x08, "RET           (SP)+",  0,  RETURN,   NONE);
  499.                 caseline (0x09, "POP",                  0,    NONE,   NONE);
  500.                 caseline (0x0A, "QUIT",                 0,    NONE,   NONE);
  501.                 caseline (0x0B, "NEW_LINE",             0,    NONE,   NONE);
  502.  
  503.                 caseline (0x0D, "VERIFY",               0,  BRANCH,   NONE);
  504.  
  505.                 default:
  506.                     switch (h_type) {
  507.                         case V3:
  508.                             switch (code) {
  509.                                 caseline (0x05, "SAVE",                 0,  BRANCH,   NONE);
  510.                                 caseline (0x06, "RESTORE",              0,  BRANCH,   NONE);
  511.  
  512.                                 caseline (0x0C, "SHOW_SCORE",           0,    NONE,   NONE);
  513.                             }
  514.                         case V4:
  515.                             switch (code) {
  516.                                 caseline (0x05, "SAVE",                 0,   STORE,   NONE);
  517.                                 caseline (0x06, "RESTORE",              0,   STORE,   NONE);
  518.                             }
  519.                         case V5:
  520.                             switch (code) {
  521.                                 /* From a bug in Wishbringer V23 */
  522.                                 caseline (0x0C, "SHOW_SCORE",           0,    NONE,   NONE);
  523.                             }
  524.                     }
  525.                     return (decode_operands ("ILLEGAL", 0, ILLEGAL, NONE));
  526.             }
  527.  
  528.         default:
  529.             fprintf (stderr, "\nFatal: bad class (%d)\n", opcode.class);
  530.             exit (EXIT_FAILURE);
  531.     }
  532.     return (0);
  533.  
  534. }/* decode_opcode */
  535.  
  536. #undef caseline
  537.  
  538. /* decode_operands - Decode operands of opcode */
  539.  
  540. #ifdef __STDC__
  541. static int decode_operands (const char *opcode_name, int input_opers, int type, int special)
  542. #else
  543. static int decode_operands (opcode_name, input_opers, type, special)
  544. const char *opcode_name;
  545. int input_opers;
  546. int type;
  547. int special;
  548. #endif
  549. {
  550.     size_t len;
  551.     int opers, status;
  552.  
  553.     opcode.type = type;
  554.     opcode.special = special;
  555.  
  556.     if (opcode.type == ILLEGAL)
  557.         return (BAD_OPCODE);
  558.  
  559.     if (decode.first_pass) {
  560.         opers = decode_inputs ();
  561.         if (input_opers < 0) {
  562.             if (opers > abs (input_opers))
  563.                 return (BAD_OPCODE);
  564.         } else
  565.             if (opers != input_opers)
  566.                 return (BAD_OPCODE);
  567.         status = decode_outputs ();
  568.     } else {
  569.         printf (opcode_name);
  570.         for (len = strlen (opcode_name); len < 14; len++)
  571.             printf (" ");
  572.         opers = decode_inputs ();
  573.         if (opers > 0 && ((opcode.type == CALL) || (opcode.type == BRANCH) || (opcode.type == STORE)))
  574.             printf (" -> ");
  575.         status = decode_outputs ();
  576.         printf ("\n");
  577.     }
  578.     if (decode.pc > decode.high_pc)
  579.         decode.high_pc = decode.pc;
  580.  
  581.     return (status);
  582.  
  583. }/* decode_operands */
  584.  
  585. /* decode_inputs - Decode input operands */
  586.  
  587. #ifdef __STDC__
  588. static int decode_inputs (void)
  589. #else
  590. static int decode_inputs ()
  591. #endif
  592. {
  593.     int modes, addr_mode, maxopers, opers = 0;
  594.  
  595.     switch (opcode.class) {
  596.  
  597.         case ONE_OPERAND:
  598.             decode_operand ((opcode.opcode >> 4) & 0x03, 1);
  599.             opers = 1;
  600.             break;
  601.  
  602.         case TWO_OPERAND:
  603.             decode_operand ((opcode.opcode & 0x40) ? VARIABLE : BYTE_IMMED, 1);
  604.             if (!decode.first_pass)
  605.                 printf (",");
  606.             decode_operand ((opcode.opcode & 0x20) ? VARIABLE : BYTE_IMMED, 0);
  607.             opers = 2;
  608.             break;
  609.  
  610.         case VARIABLE_OPERAND:
  611.         case EXTENDED_OPERAND:
  612.             if ((opcode.opcode & 0x3f) == 0x2c ||
  613.                 (opcode.opcode & 0x3f) == 0x3a) {
  614.                 modes = read_data_word (&decode.pc);
  615.                 maxopers = 8;
  616.             } else {
  617.                 modes = read_data_byte (&decode.pc);
  618.                 maxopers = 4;
  619.             }
  620.             for (addr_mode = 0, opers = 0;
  621.                  (addr_mode != NO_OPERAND) && maxopers; maxopers--) {
  622.                 addr_mode = (modes >> ((maxopers - 1) * 2)) & 0x03;
  623.                 if (addr_mode != NO_OPERAND) {
  624.                     if (!decode.first_pass && opers) {
  625.                         if ((opcode.type == CALL || opcode.type == NCALL) && opers == 1)
  626.                             printf (" (");
  627.                         else
  628.                             printf (",");
  629.                     }
  630.                     decode_operand (addr_mode, opers == 0);
  631.                     opers++;
  632.                 }
  633.             }
  634.             if (!decode.first_pass && (opcode.type == CALL || opcode.type == NCALL) && opers > 1)
  635.                 printf (")");
  636.             break;
  637.  
  638.         case ZERO_OPERAND:
  639.             if (opcode.special == TEXT) {
  640.                 if (decode.first_pass) {
  641.                     while ((short) read_data_word (&decode.pc) >= 0)
  642.                         ;
  643.                 } else {
  644.                     printf ("\"");
  645.                     decode_text (&decode.pc);
  646.                     printf ("\"");
  647.                 }
  648.             }
  649.             break;
  650.  
  651.         default:
  652.             fprintf (stderr, "\nFatal: bad class (%d)\n", opcode.class);
  653.             exit (EXIT_FAILURE);
  654.     }
  655.  
  656.     return (opers);
  657.  
  658. }/* decode_inputs */
  659.  
  660. /* decode_operand - Decode one operand */
  661.  
  662. #ifdef __STDC__
  663. static void decode_operand (int addr_mode, int flag)
  664. #else
  665. static void decode_operand (addr_mode, flag)
  666. int addr_mode;
  667. int flag;
  668. #endif
  669. {
  670.     unsigned long addr = 0;
  671.     int vars, type, special;
  672.  
  673.     if (flag) {
  674.         type = opcode.type;
  675.         special = opcode.special;
  676.     } else {
  677.         type = NONE;
  678.         special = NONE;
  679.     }
  680.     if (special == VAR)
  681.         addr_mode = VARIABLE;
  682.     switch (addr_mode) {
  683.  
  684.         case WORD_IMMED:
  685.             addr = (zword_t) read_data_word (&decode.pc);
  686.             break;
  687.  
  688.         case BYTE_IMMED:
  689.             addr = (zbyte_t) read_data_byte (&decode.pc);
  690.             break;
  691.  
  692.         case VARIABLE:
  693.             addr = read_data_byte (&decode.pc);
  694.             if (!decode.first_pass) {
  695.                 if (addr == 0)
  696.                     printf ("(SP)+");
  697.                 else
  698.                     if (addr < 16)
  699.                         printf ("L%02lx", (unsigned long) (addr - 1));
  700.                     else
  701.                         printf ("G%02lx", (unsigned long) (addr - 16));
  702.             }
  703.  
  704.         case NO_OPERAND:
  705.             return;
  706.  
  707.         default:
  708.             fprintf (stderr, "\nFatal: bad addressing mode (%d)\n", addr_mode);
  709.             exit (EXIT_FAILURE);
  710.     }
  711.     switch (type) {
  712.  
  713.         case NCALL:
  714.         case CALL:
  715.             addr *= story_scaler;
  716.             if (!decode.first_pass)
  717.                 printf ("%lx", addr);
  718.             if (addr < decode.low_address &&
  719.                 addr >= (unsigned long) h_data_size) {
  720.                 vars = read_data_byte (&addr);
  721.                 if (vars >= 0 && vars <= 15)
  722.                     decode.low_address = addr - 1;
  723.             }
  724.             if (addr > decode.high_address &&
  725.                 addr < ((unsigned long) h_file_size * story_scaler)) {
  726.                 vars = read_data_byte (&addr);
  727.                 if (vars >= 0 && vars <= 15)
  728.                     decode.high_address = addr - 1;
  729.             }
  730.             break;
  731.  
  732.         case JUMP:
  733.             addr = decode.pc + (short) addr - 2;
  734.             if (!decode.first_pass)
  735.                 printf ("%lx", addr);
  736.             if (addr > decode.high_pc)
  737.                 decode.high_pc = addr;
  738.             break;
  739.  
  740.         case PCHAR:
  741.             if (!decode.first_pass)
  742.                 if (isprint ((char) addr)) {
  743.                     printf ("\'%c\'", (char) addr);
  744.                     break;
  745.                 }
  746.  
  747.         case VATTR:
  748.             if (!decode.first_pass) {
  749.                 switch ((char) addr) {
  750.                     case NORMAL:
  751.                         printf ("NORMAL");
  752.                         break;
  753.                     case REVERSE:
  754.                         printf ("REVERSE");
  755.                         break;
  756.                     case BOLD:
  757.                         printf ("BOLD");
  758.                         break;
  759.                     case BLINK:
  760.                         printf ("BLINK");
  761.                         break;
  762.                     case UNDERSCORE:
  763.                         printf ("UNDERSCORE");
  764.                         break;
  765.                 }
  766.                 if (addr >= 0 && addr <= 4)
  767.                     break;
  768.             }
  769.  
  770.         default:
  771.             if (!decode.first_pass)
  772.                 if (addr_mode == WORD_IMMED) {
  773.                     printf ("#%04lx", addr);
  774.                     if (special = lookup_string (addr * story_scaler))
  775.                         printf ("[s%d]", special);
  776.                     if (addr = lookup_word (addr)) {
  777.                         printf ("[w\"");
  778.                         decode_text (&addr);
  779.                         printf ("\"]");
  780.                     }
  781.                 } else
  782.                     printf ("#%02lx", addr);
  783.     }
  784.  
  785. }/* decode_operand */
  786.  
  787. /* decode_outputs - Decode output operand */
  788.  
  789. #ifdef __STDC__
  790. static int decode_outputs (void)
  791. #else
  792. static int decode_outputs ()
  793. #endif
  794. {
  795.     unsigned long addr;
  796.  
  797.     switch (opcode.type) {
  798.  
  799.         case CALL:
  800.         case STORE:
  801.             addr = (zbyte_t) read_data_byte (&decode.pc);
  802.             if (!decode.first_pass) {
  803.                 if (addr == 0)
  804.                     printf ("-(SP)");
  805.                 else
  806.                     if (addr < 16)
  807.                         printf ("L%02lx", (unsigned long) (addr - 1));
  808.                     else
  809.                         printf ("G%02lx", (unsigned long) (addr - 16));
  810.             }
  811.             if (opcode.special != OBJECT)
  812.                 break;
  813.             else
  814.                 if (!decode.first_pass)
  815.                     printf (", ");
  816.  
  817.         case BRANCH:
  818.             addr = (zbyte_t) read_data_byte (&decode.pc);
  819.             if (!decode.first_pass) {
  820.                 if (addr & 0x80)
  821.                     printf ("[TRUE]");
  822.                 else
  823.                     printf ("[FALSE]");
  824.             }
  825.             addr &= 0x7f;
  826.             if (addr & 0x40)
  827.                 addr &= 0x3f;
  828.             else {
  829.                 addr = (addr << 8) | (zbyte_t) read_data_byte (&decode.pc);
  830.                 if (addr & 0x2000) {
  831.                     addr &= 0x1fff;
  832.                     addr |= ~0x1fff;
  833.                 }
  834.             }
  835.             if (addr == 0) {
  836.                 if (!decode.first_pass)
  837.                     printf (" RET #FALSE");
  838.             } else if (addr == 1) {
  839.                 if (!decode.first_pass)
  840.                     printf (" RET #TRUE");
  841.             } else {
  842.                 addr = decode.pc + addr - 2;
  843.                 if (!decode.first_pass)
  844.                     printf (" %lx", addr);
  845.                 if (addr > decode.high_pc)
  846.                     decode.high_pc = addr;
  847.             }
  848.             break;
  849.  
  850.         case RETURN:
  851.         case JUMP:
  852.             if (decode.pc > decode.high_pc)
  853.                 return (END_OF_ROUTINE);
  854.  
  855.         case NCALL:
  856.         case NONE:
  857.         case PCHAR:
  858.         case VATTR:
  859.             break;
  860.  
  861.         default:
  862.             fprintf (stderr, "\nFatal: bad type (%d)\n", opcode.type);
  863.             exit (EXIT_FAILURE);
  864.     }
  865.  
  866.     return (END_OF_INSTRUCTION);
  867.  
  868. }/* decode_outputs */
  869.  
  870. /* decode_strings - Dump text after end of code */
  871.  
  872. #ifdef __STDC__
  873. static void decode_strings (unsigned long pc)
  874. #else
  875. static void decode_strings (pc)
  876. unsigned long pc;
  877. #endif
  878. {
  879.     int count = 1;
  880.  
  881.     pc = (pc + (story_scaler - 1)) & ~(story_scaler - 1);
  882.     printf ("\n[start of text at %lx]\n\n", pc);
  883.     while (pc < ((unsigned long) h_file_size * story_scaler)) {
  884.         printf ("%5lx: [s%d] \"", pc, count++);
  885.         decode_text (&pc);
  886.         printf ("\"\n");
  887.         pc = (pc + (story_scaler - 1)) & ~(story_scaler - 1);
  888.     }
  889.     printf ("\n[end of text at %lx]\n\n[End of file]\n", pc);
  890.  
  891. }/* decode_strings */
  892.  
  893. typedef struct string_item {
  894.     struct string_item *next;
  895.     unsigned long text_addr;
  896.     int text_num;
  897. } string_item_t;
  898.  
  899. static string_item_t *strings_base = NULL;
  900.  
  901. /* scan_strings - build string address table */
  902.  
  903. #ifdef __STDC__
  904. static void scan_strings (unsigned long pc)
  905. #else
  906. static void scan_strings (pc)
  907. unsigned long pc;
  908. #endif
  909. {
  910.     int count = 1;
  911.     string_item_t *string_item;
  912.     zword_t data;
  913.  
  914.     pc = (pc + (story_scaler - 1)) & ~(story_scaler - 1);
  915.     while (pc < ((unsigned long) h_file_size * story_scaler)) {
  916.         string_item = (string_item_t *) malloc (sizeof (string_item_t));
  917.         if (string_item == NULL) {
  918.             fprintf (stderr, "Insufficient memory\n");
  919.             exit (EXIT_FAILURE);
  920.         }
  921.         string_item->text_addr = pc;
  922.         string_item->text_num = count++;
  923.         string_item->next = strings_base;
  924.         strings_base = string_item;
  925.         do
  926.             data = (zword_t) read_data_word (&pc);
  927.         while ((data & 0x8000) == 0);
  928.         pc = (pc + (story_scaler - 1)) & ~(story_scaler - 1);
  929.     }
  930.  
  931. }/* scan_strings */
  932.  
  933. /* lookup_string - lookup a string address */
  934.  
  935. #ifdef __STDC__
  936. static int lookup_string (unsigned long addr)
  937. #else
  938. static int lookup_string (addr)
  939. unsigned long addr;
  940. #endif
  941. {
  942.     string_item_t *string_item;
  943.  
  944.     for (string_item = strings_base; string_item->next != NULL; string_item = string_item->next)
  945.         if (string_item->text_addr == addr)
  946.             return (string_item->text_num);
  947.  
  948.     return (0);
  949.  
  950. }/* lookup_string */
  951.  
  952. typedef struct word_item {
  953.     struct word_item *next;
  954.     unsigned long word_addr;
  955. } word_item_t;
  956.  
  957. static word_item_t *words_base = NULL;
  958.  
  959. /* scan_words - build dictionary address table */
  960.  
  961. #ifdef __STDC__
  962. static void scan_words (void)
  963. #else
  964. static void scan_words ()
  965. #endif
  966. {
  967.     unsigned long offset;
  968.     int separator_count, word_size, word_count, i;
  969.     word_item_t *word_item;
  970.  
  971.     offset = (unsigned long) h_words_offset;
  972.     separator_count = (int) read_data_byte (&offset);
  973.     offset += separator_count;
  974.     word_size = (int) read_data_byte (&offset);
  975.     word_count = (int) read_data_word (&offset);
  976.  
  977.     for (i = 0; i < word_count; i++) {
  978.         if ((offset + 4) < (unsigned long) h_data_size)
  979.             if (h_type == V3)
  980.                 set_byte (offset + 2, get_byte (offset + 2) | 0x80);
  981.             else
  982.                 set_byte (offset + 4, get_byte (offset + 4) | 0x80);
  983.         word_item = (word_item_t *) malloc (sizeof (word_item_t));
  984.         if (word_item == NULL) {
  985.             fprintf (stderr, "Insufficient memory\n");
  986.             exit (EXIT_FAILURE);
  987.         }
  988.         word_item->word_addr = offset;
  989.         word_item->next = words_base;
  990.         words_base = word_item;
  991.         offset += word_size;
  992.     }
  993.  
  994. }/* scan_words */
  995.  
  996. /* lookup_word - lookup a word address */
  997.  
  998. #ifdef __STDC__
  999. static unsigned long lookup_word (unsigned long addr)
  1000. #else
  1001. static unsigned long lookup_word (addr)
  1002. unsigned long addr;
  1003. #endif
  1004. {
  1005.     word_item_t *word_item;
  1006.  
  1007.     for (word_item = words_base; word_item->next != NULL; word_item = word_item->next)
  1008.         if (word_item->word_addr == addr)
  1009.             return (word_item->word_addr);
  1010.  
  1011.     return (0);
  1012.  
  1013. }/* lookup_word */
  1014.