| return NULL; | return NULL; | ||||
| } | } | ||||
| static void DecompilePhoneme(FILE *f_out, PHONEME_TAB *ph, int compile_phoneme) | |||||
| { | |||||
| USHORT *pc; | |||||
| int instn; | |||||
| int instn_category; | |||||
| int address, address2; | |||||
| int data1; | |||||
| int type2; | |||||
| int ix; | |||||
| int any; | |||||
| const char *name; | |||||
| char buf[120]; | |||||
| static const char *instn_category_string[16] = { | |||||
| "", "", "IF", "IF OR", | |||||
| "", "", "", "", | |||||
| "", "", "", "FMT", | |||||
| "WAV", "NextVowelStart", "PrevVowelEnd", "+wav" | |||||
| }; | |||||
| static const char *nextPh_string[6] = { | |||||
| "prevPh", "thisPh", "nextPh", "next2Ph", "nextPhW", "**", | |||||
| }; | |||||
| static const char *instn0_string[] = { | |||||
| "invalid", "RETURN", "Continue", "DeleteNextPhoneme", | |||||
| }; | |||||
| static const char *instn10_string[] = { | |||||
| "", "VowelIn", "VowelOut", "Tone", "", | |||||
| }; | |||||
| static const char *instn_jumps[] = { | |||||
| "JMP", "Invalid", "Invalid", "Invalid", | |||||
| "JMP false", "SwitchNextVowelType", "SwitchPrevVowelType", "Invalid" | |||||
| }; | |||||
| static char instn1_paramtype[] = { | |||||
| 0, 3, 3, 3, 3, 3, 3, 1, | |||||
| 1, 1, 1, 1, 1, 0, 0, 0, | |||||
| 3, 3, 3, 3, 3, 3, 3, 3, | |||||
| 0, 0, 0, 0, 0, 0, 0, 0 | |||||
| }; | |||||
| return; | |||||
| if (compile_phoneme) | |||||
| fprintf(f_out, "\nPhoneme %s (%d)\n", WordToString(ph->mnemonic), ph->code); | |||||
| else | |||||
| fprintf(f_out, "\nProcedure %s\n", proc_names[n_procs]); | |||||
| pc = prog_buf; | |||||
| while (pc < prog_out) { | |||||
| instn = *pc++; | |||||
| instn_category = (instn >> 12) & 0xf; | |||||
| data1 = instn & 0xff; | |||||
| type2 = (instn >> 8) & 0xf; | |||||
| fprintf(f_out, " %.3x: %.4x %s", (unsigned int)(pc-prog_buf), instn, instn_category_string[instn_category]); | |||||
| switch (instn_category) | |||||
| { | |||||
| case 0: | |||||
| case 1: | |||||
| type2 = instn >> 8; | |||||
| if (instn < 0x100) { | |||||
| if (data1 > 2) | |||||
| data1 = 0; | |||||
| fprintf(f_out, "%s", instn0_string[data1]); | |||||
| } else if (type2 == i_IPA_NAME) { | |||||
| for (ix = 0; ix < data1; ix += 2) { | |||||
| instn = *pc++; | |||||
| buf[ix] = instn >> 8; | |||||
| buf[ix+1] = instn & 0xff; | |||||
| } | |||||
| buf[ix] = 0; | |||||
| fprintf(f_out, "ipa %s", buf); | |||||
| } else { | |||||
| fprintf(f_out, "%s(", KeyToMnem(keywords, tINSTRN1, type2)); | |||||
| switch (instn1_paramtype[type2]) | |||||
| { | |||||
| case 0: | |||||
| fprintf(f_out, "%.4x", instn); | |||||
| break; | |||||
| case 1: | |||||
| fprintf(f_out, "%d", data1); | |||||
| break; | |||||
| case 3: | |||||
| fprintf(f_out, "%s", WordToString(phoneme_tab2[data1].mnemonic)); | |||||
| break; | |||||
| } | |||||
| fprintf(f_out, ")"); | |||||
| } | |||||
| break; | |||||
| case 2: | |||||
| case 3: | |||||
| if (type2 < 12) { | |||||
| fprintf(f_out, " %s(", nextPh_string[type2 % 6]); | |||||
| if (type2 >= 6) { | |||||
| switch (data1 >> 5) | |||||
| { | |||||
| case 0: | |||||
| name = KeyToMnem(keywords, tPHONEME_TYPE, (data1 & 0x1f)); | |||||
| if (name != NULL) | |||||
| fprintf(f_out, "is%s", name); | |||||
| else | |||||
| fprintf(f_out, "%d %d", (data1 >> 5), (data1 & 0x1f)); | |||||
| break; | |||||
| case 1: | |||||
| fprintf(f_out, "%d %d", (data1 >> 5), (data1 & 0x1f)); | |||||
| break; | |||||
| case 2: | |||||
| fprintf(f_out, "%d %d", (data1 >> 5), (data1 & 0x1f)); | |||||
| break; | |||||
| case 4: | |||||
| name = KeyToMnem(k_properties, -1, 0x80+(data1 & 0x1f)); | |||||
| if (name != NULL) | |||||
| fprintf(f_out, "%s", name); | |||||
| else | |||||
| fprintf(f_out, "%d %d", (data1 >> 5), (data1 & 0x1f)); | |||||
| break; | |||||
| default: | |||||
| fprintf(f_out, "%d %d", (data1 >> 5), (data1 & 0x1f)); | |||||
| break; | |||||
| } | |||||
| } else { | |||||
| fprintf(f_out, "%s", WordToString(phoneme_tab2[data1].mnemonic)); | |||||
| } | |||||
| } else if (type2 == 8) { | |||||
| // list of numbers | |||||
| fprintf(f_out, " StressLevel("); | |||||
| any = 0; | |||||
| for (ix = 0; ix < 8; ix++) { | |||||
| if (data1 & (1 << ix)) { | |||||
| if (any) | |||||
| fputc(',', f_out); | |||||
| any = 1; | |||||
| fprintf(f_out, "%d", ix); | |||||
| } | |||||
| } | |||||
| } else { | |||||
| name = KeyToMnem(k_conditions, tTEST, instn & 0xfff); | |||||
| fprintf(f_out, "%s(", name); | |||||
| } | |||||
| fprintf(f_out, ")"); | |||||
| break; | |||||
| case 6: | |||||
| fprintf(f_out, "%s", instn_jumps[(instn >> 9) & 7]); | |||||
| fprintf(f_out, " %d", instn & 0x1ff); | |||||
| break; | |||||
| case 9: | |||||
| address = ((data1 & 0xf) << 4) + *pc++; | |||||
| fprintf(f_out, "CALL %.5x", address); | |||||
| break; | |||||
| case 10: | |||||
| fprintf(f_out, "%s", instn10_string[type2]); | |||||
| switch (type2) | |||||
| { | |||||
| case 1: | |||||
| case 2: | |||||
| address = (data1 << 16) + pc[0]; | |||||
| address2 = (pc[1] << 16) + pc[2]; | |||||
| pc += 3; | |||||
| fprintf(f_out, " %.6x %.8x", address, address2); | |||||
| break; | |||||
| case 3: | |||||
| address = ((instn & 0xf) << 16) + *pc++; | |||||
| address2 = ((instn & 0xf0) << 12) + *pc++; | |||||
| fprintf(f_out, " %.5x %.5x", address, address2); | |||||
| break; | |||||
| } | |||||
| break; | |||||
| case 11: | |||||
| case 12: | |||||
| case 13: | |||||
| case 14: | |||||
| case 15: | |||||
| address = ((instn & 0xf) << 16) + *pc++; | |||||
| fprintf(f_out, " %d %.5x", (instn >> 4) & 0xff, address*4); | |||||
| break; | |||||
| } | |||||
| fprintf(f_out, "\n"); | |||||
| } | |||||
| } | |||||
| static int n_phoneme_tabs; | static int n_phoneme_tabs; | ||||
| static int n_phcodes; | static int n_phcodes; | ||||
| phoneme_out->mnemonic = 0x01; // will not be recognised | phoneme_out->mnemonic = 0x01; // will not be recognised | ||||
| } | } | ||||
| DecompilePhoneme(f_errors, phoneme_out, compile_phoneme); | |||||
| if (prog_out > prog_buf) { | if (prog_out > prog_buf) { | ||||
| // write out the program for this phoneme | // write out the program for this phoneme | ||||
| fflush(f_phindex); | fflush(f_phindex); |