/*************************************************************/ /* AUTHOR .... : Bert van Oortmarssen */ /* NAME ...... : plist.c have to think of a better name */ /* PROJECTS .. : zx81 */ /* DATE ...... : */ /* TASK ...... : translate 'P' file to basic */ /* */ /*************************************************************/ #include #include #include typedef unsigned char BYTE; char *disp[256] = { " ", "{1}", "{2}", "{3}", "{4}", "{5}", "{6}", "{7}", "{8}", "{9}", "{10}", "\"", "&", "$", ":", "?", "(", ")", ">", "<", "=", "+", "-", "*", "/", ";", ",", ".", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "RND ", "INKEY$ ", "PI ", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "#", "|1|", "|2|", "|3|", "|4|", "|5|", "|6|", "|7|", "|8|", "|9|", "|10|", "\"", "&", "$", ":", "?", "(", ")", ">", "<", "=", "+", "-", "*", "/", ";", ",", ".", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "`'", "AT ", "TAB ", NULL, "CODE ", "VAL ", "LEN ", "SIN ", "COS ", "TAN ", "ASN ", "ACS ", "ATN ", "LN ", "EXP ", "INT ", "SQR ", "SGN ", "ABS ", "PEEK ", "USR ", "STR$ ", "CHR$ ", "NOT ", "** ", "OR ", "AND ", "<= ", ">= ", "<> ", " THEN ", " TO ", " STEP ", "LPRINT ", "LLIST ", "STOP ", "SLOW ", "FAST ", "NEW ", "SCROLL ", "CONT ", "DIM ", "REM ", "FOR ", "GOTO ", "GOSUB ", "INPUT ", "LOAD ", "LIST ", "LET ", "PAUSE ", "NEXT ", "POKE ", "PRINT ", "PLOT ", "RUN ", "SAVE ", "RAND ", "IF ", "CLS ", "UNPLOT ", "CLEAR ", "RETURN ", "COPY " }; int LH (BYTE *p) { return ( *p + (*(p+1)<<8)); } int HL (BYTE *p) { return ((*p << 8) + *(p+1)); } int PutNumberIfNotTooComplicated (BYTE *b, FILE *fo) { int nexp = b[0] - 129; int nval; int sign = (b[1] & 0x80) ? -1 : 1; int b1 = b[1] & 0x7F; if (nexp < 0 || nexp > 15) return (0); if (b[3]!=0 || b[4]!=0) return (0); nval = b[2]; if (nexp > 7) nval += b1 << (nexp-7); else nval += b1 >> (7-nexp); nval += 1 << nexp; nval = sign * nval; fprintf (fo, " %5d", nval); return (1); } void PutNumber (BYTE *b, FILE *fo) { if (!PutNumberIfNotTooComplicated (b, fo)) fputs (" -+-+-", fo); } void BytesLines (char *szfi, char *szfo) { FILE *fp; FILE *fo; int j, n, m, k, oldm, nlen, len, cnt; BYTE *bbig; BYTE b, b2[2], c2[2], b116[116]; char *s; int Se_ppc; int Sd_file; int Svars; int Se_line; int ndisplay, nvarspace, oke; if ((fp=fopen (szfi, "rb"))==NULL) { fprintf (stderr," *** error *** Can't read file %s \n", szfi); exit(1); } if (szfo==NULL) { fo = stdout; } else { if ((fo=fopen (szfo, "wt"))==NULL) { fprintf (stderr," *** error *** Can't open output file %s \n", szfo); fclose (fp); exit(1); } } if (116==fread(b116, 1, 116, fp)) { bbig = (BYTE *) malloc (30000); Se_ppc = LH(b116 + 1); Sd_file= LH(b116 + 3); Svars = LH(b116 + 7); Se_line= LH(b116 + 11); ndisplay = Svars - Sd_file; nvarspace = Se_line - Svars - 1; fprintf (fo, " E_PPC = %04X %5u\n", Se_ppc, Se_ppc ); fprintf (fo, " D_FILE = %04X %5u\n", Sd_file, Sd_file); fprintf (fo, " VARS = %04X %5u\n", Svars, Svars ); fprintf (fo, " E_LINE = %04X %5u\n", Se_line, Se_line); fprintf (fo, "-----------------------------\n"); cnt = 16509; m = 116; while (cnt < Sd_file) { oldm = m; fread (b2, 1, 2, fp); m += 2; fread (c2, 1, 2, fp); m += 2; cnt += 4; len = LH(c2); fprintf (fo, "[%04X] %5d (%4d) ", oldm, HL(b2), len); b = 0; m = ftell(fp); if (len > 30000) { fprintf (stderr, "Silly length = %d\n", len); len = 30000; } nlen = fread (bbig, 1, len, fp); if (nlen != len) { fprintf (stderr, "Incorrect length = %d (only %d avail)\n", len, nlen); len = nlen; } oke = bbig[len-1]==0x76; for (k=0; k < len -1; k++) { s = disp[bbig[k]]; if (s) fputs (s, fo); if (bbig[k]==0x7E) { /* fputc (' ', fo); */ k += 5; } if (!oke && bbig[k]==0x76) break; } fputc ('\n', fo); if (!oke) { fprintf (fo, "huh ??? seeking new sync point \n"); if (k < len - 1) { fprintf (fo, "k=%d (len=%d) sync point ? \n", k, len); fseek (fp, m + k + 1, SEEK_SET); cnt += k+1; } else { /* read until 0x76 is found ... */ fprintf (fo, "forward search for sync point \n", k, len); k = 0; while (1==fread (bbig, 1, 1, fp) && bbig[0]!=0x76) { cnt++; k++; } if (bbig[0]==0x76) fprintf (fo, "FOUND new forward search sync point [skipping %d bytes] \n", k); } } else cnt += len; } fprintf (fo, "-----------------------------\n"); /* now the display */ ndisplay = fread (bbig, 1, ndisplay, fp); /* now the variables */ nvarspace = fread (bbig, 1, nvarspace, fp); if (nvarspace > 30000) { fprintf (fo, "huh ??? nvarspace ?? %d\n", nvarspace); nvarspace = 0; } k = 0; while (k < nvarspace) { b = bbig[k]; m = b >> 5; switch (m) { case 2 : /* letter string */ fputs (disp[(b & 0x3F) + 0x20], fo); fputc ('$', fo); n = LH(&bbig[k+1]); k += 3; while (n > 0 && (k < nvarspace)) { s = (k < nvarspace) ? disp [bbig[k]] : NULL; if (s) fputs (s, fo); k++; n--; } break; case 3 : /* single letter number */ fprintf (fo, "%-8s", disp[b & 0x3F]); PutNumber (bbig + k+1, fo); k += 6; break; case 5 : /* multiple letter number */ fputs (disp[b & 0x3F], fo); j = 1; do { k++; fputs (disp[bbig[k] & 0x3F], fo); j++; } while ((k < nvarspace) && (bbig[k] & 0x80)==0); while (j++ < 8) fputc (' ', fo); if (k < nvarspace) PutNumber (bbig + k+1, fo); k += 6; break; case 4 : /* array of numbers */ b = bbig[k] + 0x20; fprintf (fo, "DIM: %-3s", disp[b & 0x3F]); k++; n = LH (&bbig[k]); k += 2; j = 1 + 2 * bbig[k]; n = (n - j) / 5; k += j; while (n > 0 && k < nvarspace) { PutNumber (bbig + k, fo); k += 5; n--; } break; case 7 : /* control variable */ fprintf (fo, "%-8s", disp[b & 0x3F]); k++; if (k < nvarspace) { fputs (" curval:", fo); PutNumber (bbig + k, fo); k+=5; } if (k < nvarspace) { fputs (" limit:", fo); PutNumber (bbig + k, fo); k+=5; } if (k < nvarspace) { fputs (" step:", fo); PutNumber (bbig + k, fo); k+=5; } if (k < nvarspace) fprintf (fo," Loop Line: %d ", LH(bbig+k)); k += 2; break; default : k += 9999; } fputc ('\n', fo); } free (bbig); } if (fo!=stdout) fclose (fo); fclose (fp); } int main (int argc, char **argv) { if (argc>1) { BytesLines (argv[1], (argc > 2) ? argv[2] : NULL); } else { fprintf (stderr, " %s filename.in [filename.out] \n", argv[0]); fprintf (stderr, " (c) berto %s %s \n", __DATE__, __TIME__); } return(0); }