| 1 | /*\r |
| 2 | * (C) Copyright 2002, Brian Knittel.\r |
| 3 | * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN\r |
| 4 | * RISK basis, there is no warranty of fitness for any purpose, and the rest of the\r |
| 5 | * usual yada-yada. Please keep this notice and the copyright in any distributions\r |
| 6 | * or modifications.\r |
| 7 | *\r |
| 8 | * This is not a supported product, but I welcome bug reports and fixes.\r |
| 9 | * Mail to sim@ibm1130.org\r |
| 10 | */\r |
| 11 | \r |
| 12 | // DISKVIEW - lists contents of an 1130 system disk image file. Not finished yet.\r |
| 13 | // needs LET/SLET listing routine.\r |
| 14 | //\r |
| 15 | // usage:\r |
| 16 | // diskview -v diskfile\r |
| 17 | \r |
| 18 | #include <stdio.h>\r |
| 19 | #include <stdlib.h>\r |
| 20 | #include <string.h>\r |
| 21 | #include <stdarg.h>\r |
| 22 | #include "util_io.h"\r |
| 23 | \r |
| 24 | #define BETWEEN(v,a,b) (((v) >= (a)) && ((v) <= (b)))\r |
| 25 | #define MIN(a,b) (((a) <= (b)) ? (a) : (b))\r |
| 26 | #define MAX(a,b) (((a) >= (b)) ? (a) : (b))\r |
| 27 | \r |
| 28 | #ifndef TRUE\r |
| 29 | # define TRUE 1\r |
| 30 | # define FALSE 0\r |
| 31 | # define BOOL int\r |
| 32 | #endif\r |
| 33 | \r |
| 34 | #define NOT_DEF 0x0658 // defective cylinder table entry means no defect\r |
| 35 | \r |
| 36 | #define DSK_NUMWD 321 /* words/sector */\r |
| 37 | #define DSK_NUMCY 203 /* cylinders/drive */\r |
| 38 | #define DSK_SECCYL 8 /* sectors per cylinder */\r |
| 39 | #define SECLEN 320 /* data words per sector */\r |
| 40 | #define SLETLEN ((3*SECLEN)/4) /* length of slet in records */\r |
| 41 | \r |
| 42 | typedef unsigned short WORD;\r |
| 43 | \r |
| 44 | FILE *fp;\r |
| 45 | WORD buf[DSK_NUMWD];\r |
| 46 | WORD dcom[DSK_NUMWD];\r |
| 47 | \r |
| 48 | #pragma pack(2)\r |
| 49 | struct tag_slet {\r |
| 50 | WORD phid;\r |
| 51 | WORD addr;\r |
| 52 | WORD nwords;\r |
| 53 | WORD sector;\r |
| 54 | } slet[SLETLEN];\r |
| 55 | \r |
| 56 | #pragma pack()\r |
| 57 | \r |
| 58 | WORD dcyl[3];\r |
| 59 | BOOL verbose = FALSE;\r |
| 60 | \r |
| 61 | void checksectors (void);\r |
| 62 | void dump_id (void);\r |
| 63 | void dump_dcom (void);\r |
| 64 | void dump_resmon (void);\r |
| 65 | void dump_slet (void);\r |
| 66 | void dump_hdng (void);\r |
| 67 | void dump_scra (void);\r |
| 68 | void dump_let (void);\r |
| 69 | void dump_flet (void);\r |
| 70 | void dump_cib (void);\r |
| 71 | void getsector (int sec, WORD *sbuf);\r |
| 72 | void getdcyl (void);\r |
| 73 | char *lowcase (char *str);\r |
| 74 | \r |
| 75 | void bail(char *fmt, ...);\r |
| 76 | char *trim (char *s);\r |
| 77 | \r |
| 78 | int main (int argc, char **argv)\r |
| 79 | {\r |
| 80 | char *fname = NULL, *arg;\r |
| 81 | static char usestr[] = "Usage: diskview [-v] filename";\r |
| 82 | int i;\r |
| 83 | \r |
| 84 | for (i = 1; i < argc;) {\r |
| 85 | arg = argv[i++];\r |
| 86 | if (*arg == '-') {\r |
| 87 | arg++;\r |
| 88 | lowcase(arg);\r |
| 89 | while (*arg) {\r |
| 90 | switch (*arg++) {\r |
| 91 | case 'v':\r |
| 92 | verbose = TRUE;\r |
| 93 | break;\r |
| 94 | \r |
| 95 | default:\r |
| 96 | bail(usestr);\r |
| 97 | }\r |
| 98 | }\r |
| 99 | }\r |
| 100 | else if (fname == NULL)\r |
| 101 | fname = arg;\r |
| 102 | else\r |
| 103 | bail(usestr);\r |
| 104 | }\r |
| 105 | \r |
| 106 | if (fname == NULL)\r |
| 107 | bail(usestr);\r |
| 108 | \r |
| 109 | if ((fp = fopen(fname, "rb")) == NULL) {\r |
| 110 | perror(fname);\r |
| 111 | return 2;\r |
| 112 | }\r |
| 113 | \r |
| 114 | printf("%s:\n", fname);\r |
| 115 | \r |
| 116 | checksectors();\r |
| 117 | getdcyl();\r |
| 118 | \r |
| 119 | dump_id(); // ID & coldstart\r |
| 120 | dump_dcom(); // DCOM\r |
| 121 | dump_resmon(); // resident image\r |
| 122 | dump_slet(); // SLET\r |
| 123 | dump_hdng(); // heading sector\r |
| 124 | dump_scra();\r |
| 125 | dump_flet();\r |
| 126 | dump_cib();\r |
| 127 | dump_let();\r |
| 128 | \r |
| 129 | fclose(fp);\r |
| 130 | return 0;\r |
| 131 | }\r |
| 132 | \r |
| 133 | // checksectors - verify that all sectors are properly numbered\r |
| 134 | \r |
| 135 | void checksectors ()\r |
| 136 | {\r |
| 137 | WORD sec = 0;\r |
| 138 | \r |
| 139 | fseek(fp, 0, SEEK_SET);\r |
| 140 | \r |
| 141 | for (sec = 0; sec < DSK_NUMCY*DSK_SECCYL; sec++) {\r |
| 142 | if (fxread(buf, sizeof(WORD), DSK_NUMWD, fp) != DSK_NUMWD)\r |
| 143 | bail("File read error or not a disk image file");\r |
| 144 | \r |
| 145 | if (buf[0] != sec)\r |
| 146 | bail("Sector /%x is misnumbered, run checkdisk [-f]", sec);\r |
| 147 | }\r |
| 148 | }\r |
| 149 | \r |
| 150 | // get defective cylinder list\r |
| 151 | \r |
| 152 | void getdcyl (void)\r |
| 153 | {\r |
| 154 | fseek(fp, sizeof(WORD), SEEK_SET); // skip sector count\r |
| 155 | if (fxread(dcyl, sizeof(WORD), 3, fp) != 3)\r |
| 156 | bail("Unable to read defective cylinder table");\r |
| 157 | }\r |
| 158 | \r |
| 159 | // getsector - read specified absolute sector\r |
| 160 | \r |
| 161 | void getsector (int sec, WORD *sbuf)\r |
| 162 | {\r |
| 163 | int i, cyl, ssec;\r |
| 164 | \r |
| 165 | sec &= 0x7FF; // mask of drive bits, if any\r |
| 166 | \r |
| 167 | cyl = sec / DSK_SECCYL; // get cylinder\r |
| 168 | ssec = sec & ~(DSK_SECCYL-1); // mask to get starting sector of cylinder\r |
| 169 | for (i = 0; i < 3; i++) { // map through defective cylinder table\r |
| 170 | if (dcyl[i] == ssec) {\r |
| 171 | sec &= (DSK_SECCYL-1); // mask to get base sector\r |
| 172 | cyl = DSK_NUMCY-3+i; // replacements are last three on disk\r |
| 173 | sec += cyl*DSK_SECCYL; // add new cylinder offset\r |
| 174 | break;\r |
| 175 | }\r |
| 176 | }\r |
| 177 | // read the sector\r |
| 178 | if (fseek(fp, (sec*DSK_NUMWD+1)*sizeof(WORD), SEEK_SET) != 0)\r |
| 179 | bail("File seek failed");\r |
| 180 | \r |
| 181 | if (fxread(sbuf, sizeof(WORD), DSK_NUMWD, fp) != DSK_NUMWD)\r |
| 182 | bail("File read error or not a disk image file");\r |
| 183 | }\r |
| 184 | \r |
| 185 | void dump (int nwords)\r |
| 186 | {\r |
| 187 | int i, nline = 0;\r |
| 188 | \r |
| 189 | for (i = 0; i < nwords; i++) {\r |
| 190 | if (nline == 16) {\r |
| 191 | putchar('\n');\r |
| 192 | nline = 0;\r |
| 193 | }\r |
| 194 | \r |
| 195 | printf("%04x", buf[i]);\r |
| 196 | nline++;\r |
| 197 | }\r |
| 198 | putchar('\n');\r |
| 199 | }\r |
| 200 | \r |
| 201 | void showmajor (char *label)\r |
| 202 | {\r |
| 203 | int i;\r |
| 204 | \r |
| 205 | printf("\n--- %s ", label);\r |
| 206 | \r |
| 207 | for (i = strlen(label); i < 40; i++)\r |
| 208 | putchar('-');\r |
| 209 | \r |
| 210 | putchar('\n');\r |
| 211 | putchar('\n');\r |
| 212 | }\r |
| 213 | \r |
| 214 | void name (char *label)\r |
| 215 | {\r |
| 216 | printf("%-32.32s ", label);\r |
| 217 | }\r |
| 218 | \r |
| 219 | void pbf (char *label, WORD *buf, int nwords)\r |
| 220 | {\r |
| 221 | int i, nout;\r |
| 222 | \r |
| 223 | name(label);\r |
| 224 | \r |
| 225 | for (i = nout = 0; i < nwords; i++, nout++) {\r |
| 226 | if (nout == 8) {\r |
| 227 | putchar('\n');\r |
| 228 | name("");\r |
| 229 | nout = 0;\r |
| 230 | }\r |
| 231 | printf(" %04x", buf[i]);\r |
| 232 | }\r |
| 233 | \r |
| 234 | putchar('\n');\r |
| 235 | }\r |
| 236 | \r |
| 237 | void prt (char *label, char *fmt, ...)\r |
| 238 | {\r |
| 239 | va_list args;\r |
| 240 | \r |
| 241 | name(label);\r |
| 242 | \r |
| 243 | putchar(' ');\r |
| 244 | va_start(args, fmt);\r |
| 245 | vprintf(fmt, args);\r |
| 246 | va_end(args);\r |
| 247 | \r |
| 248 | putchar('\n');\r |
| 249 | }\r |
| 250 | \r |
| 251 | void dump_id (void)\r |
| 252 | {\r |
| 253 | showmajor("Sector 0 - ID & coldstart");\r |
| 254 | getsector(0, buf);\r |
| 255 | \r |
| 256 | pbf("DCYL def cyl table", buf+ 0, 3);\r |
| 257 | pbf("CIDN cart id", buf+ 3, 1);\r |
| 258 | pbf(" copy code", buf+ 4, 1);\r |
| 259 | pbf("DTYP disk type", buf+ 7, 1);\r |
| 260 | pbf(" diskz copy", buf+ 30, 8);\r |
| 261 | pbf(" cold start pgm",buf+270, 8);\r |
| 262 | }\r |
| 263 | \r |
| 264 | // EQUIVALENCES FOR DCOM PARAMETERS \r |
| 265 | #define NAME 4 // NAME OF PROGRAM/CORE LOAD\r |
| 266 | #define DBCT 6 // BLOCK CT OF PROGRAM/CORE LOAD\r |
| 267 | #define FCNT 7 // FILES SWITCH\r |
| 268 | #define SYSC 8 // SYSTEM/NON-SYSTEM CARTRIDGE INDR\r |
| 269 | #define JBSW 9 // JOBT SWITCH\r |
| 270 | #define CBSW 10 // CLB-RETURN SWITCH\r |
| 271 | #define LCNT 11 // NO. OF LOCALS\r |
| 272 | #define MPSW 12 // CORE MAP SWITCH\r |
| 273 | #define MDF1 13 // NO. DUP CTRL RECORDS (MODIF)\r |
| 274 | #define MDF2 14 // ADDR OF MODIF BUFFER\r |
| 275 | #define NCNT 15 // NO. OF NOCALS\r |
| 276 | #define ENTY 16 // RLTV ENTRY ADDR OF PROGRAM\r |
| 277 | #define RP67 17 // 1442-5 SWITCH\r |
| 278 | #define TODR 18 // OBJECT WORK STORAGE DRIVE CODE\r |
| 279 | #define FHOL 20 // ADDR LARGEST HOLE IN FIXED AREA\r |
| 280 | #define FSZE 21 // BLK CNT LARGEST HOLE IN FXA\r |
| 281 | #define UHOL 22 // ADDR LAST HOLE IN USER AREA 2-10\r |
| 282 | #define USZE 23 // BLK CNT LAST HOLE IN UA 2-10\r |
| 283 | #define DCSW 24 // DUP CALL SWITCH\r |
| 284 | #define PIOD 25 // PRINCIPAL I/O DEVICE INDICATOR\r |
| 285 | #define PPTR 26 // PRINCIPAL PRINT DEVICE INDICATOR\r |
| 286 | #define CIAD 27 // RLTV ADDR IN @STRT OF CIL ADDR\r |
| 287 | #define ACIN 28 // AVAILABLE CARTRIDGE INDICATOR\r |
| 288 | #define GRPH 29 // 2250 INDICATOR 2G2\r |
| 289 | #define GCNT 30 // NO. G2250 RECORDS 2G2\r |
| 290 | #define LOSW 31 // LOCAL-CALLS-LOCAL SWITCH 2-2\r |
| 291 | #define X3SW 32 // SPECIAL ILS SWITCH 2-2\r |
| 292 | #define ECNT 33 // NO. OF *EQUAT RCDS 2-4\r |
| 293 | #define ANDU 35 // 1+BLK ADDR END OF UA (ADJUSTED)\r |
| 294 | #define BNDU 40 // 1+BLK ADDR END OF UA (BASE)\r |
| 295 | #define FPAD 45 // FILE PROTECT ADDR\r |
| 296 | #define PCID 50 // CARTRIDGE ID, PHYSICAL DRIVE\r |
| 297 | #define CIDN 55 // CARTRIDGE ID, LOGICAL DRIVE\r |
| 298 | #define CIBA 60 // SCTR ADDR OF CIB\r |
| 299 | #define SCRA 65 // SCTR ADDR OF SCRA\r |
| 300 | #define FMAT 70 // FORMAT OF PROG IN WORKING STG\r |
| 301 | #define FLET 75 // SCTR ADDR 1ST SCTR OF FLET\r |
| 302 | #define ULET 80 // SCTR ADDR 1ST SCTR OF LET\r |
| 303 | #define WSCT 85 // BLK CNT OF PROG IN WORKING STG\r |
| 304 | #define CSHN 90 // NO. SCTRS IN CUSHION AREA\r |
| 305 | \r |
| 306 | struct tag_dcominfo {\r |
| 307 | char *nm;\r |
| 308 | int offset;\r |
| 309 | char *descr;\r |
| 310 | } dcominfo[] = {\r |
| 311 | "NAME", 4, "NAME OF PROGRAM/CORE LOAD",\r |
| 312 | "DBCT", 6, "BLOCK CT OF PROGRAM/CORE LOAD",\r |
| 313 | "FCNT", 7, "FILES SWITCH",\r |
| 314 | "SYSC", 8, "SYSTEM/NON-SYSTEM CARTRIDGE INDR",\r |
| 315 | "JBSW", 9, "JOBT SWITCH",\r |
| 316 | "CBSW", 10, "CLB-RETURN SWITCH",\r |
| 317 | "LCNT", 11, "NO. OF LOCALS",\r |
| 318 | "MPSW", 12, "CORE MAP SWITCH",\r |
| 319 | "MDF1", 13, "NO. DUP CTRL RECORDS (MODIF)",\r |
| 320 | "MDF2", 14, "ADDR OF MODIF BUFFER",\r |
| 321 | "NCNT", 15, "NO. OF NOCALS",\r |
| 322 | "ENTY", 16, "RLTV ENTRY ADDR OF PROGRAM",\r |
| 323 | "RP67", 17, "1442-5 SWITCH",\r |
| 324 | "TODR", 18, "OBJECT WORK STORAGE DRIVE CODE",\r |
| 325 | "FHOL", 20, "ADDR LARGEST HOLE IN FIXED AREA",\r |
| 326 | "FSZE", 21, "BLK CNT LARGEST HOLE IN FXA",\r |
| 327 | "UHOL", 22, "ADDR LAST HOLE IN USER AREA",\r |
| 328 | "USZE", 23, "BLK CNT LAST HOLE IN UA",\r |
| 329 | "DCSW", 24, "DUP CALL SWITCH",\r |
| 330 | "PIOD", 25, "PRINCIPAL I/O DEVICE INDICATOR",\r |
| 331 | "PPTR", 26, "PRINCIPAL PRINT DEVICE INDICATOR",\r |
| 332 | "CIAD", 27, "RLTV ADDR IN @STRT OF CIL ADDR",\r |
| 333 | "ACIN", 28, "AVAILABLE CARTRIDGE INDICATOR",\r |
| 334 | "GRPH", 29, "2250 INDICATOR",\r |
| 335 | "GCNT", 30, "NO. G2250 RECORDS",\r |
| 336 | "LOSW", 31, "LOCAL-CALLS-LOCAL SWITCH",\r |
| 337 | "X3SW", 32, "SPECIAL ILS SWITCH",\r |
| 338 | "ECNT", 33, "NO. OF *EQUAT RCDS",\r |
| 339 | "ANDU", 35, "1+BLK ADDR END OF UA (ADJUSTED)",\r |
| 340 | "BNDU", 40, "1+BLK ADDR END OF UA (BASE)",\r |
| 341 | "FPAD", 45, "FILE PROTECT ADDR",\r |
| 342 | "PCID", 50, "CARTRIDGE ID, PHYSICAL DRIVE",\r |
| 343 | "CIDN", 55, "CARTRIDGE ID, LOGICAL DRIVE",\r |
| 344 | "CIBA", 60, "SCTR ADDR OF CIB",\r |
| 345 | "SCRA", 65, "SCTR ADDR OF SCRA",\r |
| 346 | "FMAT", 70, "FORMAT OF PROG IN WORKING STG",\r |
| 347 | "FLET", 75, "SCTR ADDR 1ST SCTR OF FLET",\r |
| 348 | "ULET", 80, "SCTR ADDR 1ST SCTR OF LET",\r |
| 349 | "WSCT", 85, "BLK CNT OF PROG IN WORKING STG",\r |
| 350 | "CSHN", 90, "NO. SCTRS IN CUSHION AREA",\r |
| 351 | NULL\r |
| 352 | };\r |
| 353 | \r |
| 354 | void dump_dcom (void)\r |
| 355 | {\r |
| 356 | struct tag_dcominfo *d;\r |
| 357 | char txt[50];\r |
| 358 | \r |
| 359 | showmajor("Sector 1 - DCOM");\r |
| 360 | getsector(1, dcom);\r |
| 361 | \r |
| 362 | for (d = dcominfo; d->nm != NULL; d++) {\r |
| 363 | sprintf(txt, "%-4.4s %s", d->nm, d->descr);\r |
| 364 | pbf(txt, dcom+d->offset, 1);\r |
| 365 | }\r |
| 366 | }\r |
| 367 | \r |
| 368 | void dump_resmon (void)\r |
| 369 | {\r |
| 370 | showmajor("Sector 2 - Resident Image");\r |
| 371 | getsector(2, buf);\r |
| 372 | dump(verbose ? SECLEN : 32);\r |
| 373 | }\r |
| 374 | \r |
| 375 | struct {\r |
| 376 | int pfrom, pto;\r |
| 377 | int printed;\r |
| 378 | char *name;\r |
| 379 | } sletinfo[] = {\r |
| 380 | 0x01, 0x12, FALSE, "DUP",\r |
| 381 | 0x1F, 0x39, FALSE, "Fortran",\r |
| 382 | 0x51, 0x5C, FALSE, "Cobol",\r |
| 383 | 0x6E, 0x74, FALSE, "Supervisor",\r |
| 384 | 0x78, 0x84, FALSE, "Core Load Builder",\r |
| 385 | 0x8C, 0x8C, FALSE, "Sys 1403 prt",\r |
| 386 | 0x8D, 0x8D, FALSE, "Sys 1132 prt",\r |
| 387 | 0x8E, 0x8E, FALSE, "Sys console prt",\r |
| 388 | 0x8F, 0x8F, FALSE, "Sys 2501 rdr",\r |
| 389 | 0x90, 0x90, FALSE, "Sys 1442 rdr/pun",\r |
| 390 | 0x91, 0x91, FALSE, "Sys 1134 paper tape",\r |
| 391 | 0x92, 0x92, FALSE, "Sys kbd",\r |
| 392 | 0x93, 0x93, FALSE, "Sys 2501/1442 conv",\r |
| 393 | 0x94, 0x94, FALSE, "Sys 1134 conv",\r |
| 394 | 0x95, 0x95, FALSE, "Sys kbd conv",\r |
| 395 | 0x96, 0x96, FALSE, "Sys diskz",\r |
| 396 | 0x97, 0x97, FALSE, "Sys disk1",\r |
| 397 | 0x98, 0x98, FALSE, "Sys diskn",\r |
| 398 | 0x99, 0x99, FALSE, "(primary print)",\r |
| 399 | 0x9A, 0x9A, FALSE, "(primary input)",\r |
| 400 | 0x9B, 0x9B, FALSE, "(primary input excl kbd)",\r |
| 401 | 0x9C, 0x9C, FALSE, "(primary sys conv)",\r |
| 402 | 0x9D, 0x9D, FALSE, "(primary conv excl kbd)",\r |
| 403 | 0xA0, 0xA1, FALSE, "Core Image Loader",\r |
| 404 | 0xB0, 0xCC, FALSE, "RPG",\r |
| 405 | 0xCD, 0xCE, FALSE, "Dup Part 2",\r |
| 406 | 0xCF, 0xF6, FALSE, "Macro Assembler",\r |
| 407 | 0\r |
| 408 | };\r |
| 409 | \r |
| 410 | void dump_slet (void)\r |
| 411 | {\r |
| 412 | int i, j, iphase, nsecs, sec, max_sec = 0;\r |
| 413 | char sstr[16], *smark;\r |
| 414 | \r |
| 415 | showmajor("Sectors 3-5 - SLET");\r |
| 416 | for (i = 0; i < 3; i++) {\r |
| 417 | getsector(3+i, buf);\r |
| 418 | memmove(((WORD *) slet)+SECLEN*i, buf, SECLEN*sizeof(WORD));\r |
| 419 | }\r |
| 420 | \r |
| 421 | printf("# PHID Addr Len Sector Secs\n");\r |
| 422 | printf("------------------------------------------\n");\r |
| 423 | for (i = 0; i < SLETLEN; i++) {\r |
| 424 | if (slet[i].phid == 0)\r |
| 425 | break;\r |
| 426 | \r |
| 427 | sec = slet[i].sector;\r |
| 428 | iphase = (int) (signed short) slet[i].phid;\r |
| 429 | nsecs = (slet[i].nwords + SECLEN-1)/SECLEN;\r |
| 430 | \r |
| 431 | if (sec & 0xF800) {\r |
| 432 | smark = "*";\r |
| 433 | sec &= 0x7FF;\r |
| 434 | }\r |
| 435 | else\r |
| 436 | smark = " ";\r |
| 437 | \r |
| 438 | for (j = 0; sletinfo[j].pfrom != 0; j++)\r |
| 439 | if (sletinfo[j].pfrom <= iphase && sletinfo[j].pto >= iphase)\r |
| 440 | break;\r |
| 441 | \r |
| 442 | sprintf(sstr, "(%d.%d)", sec / DSK_SECCYL, slet[i].sector % DSK_SECCYL);\r |
| 443 | \r |
| 444 | printf("%3d %04x %4d %04x %04x %04x %s %-7s %3x",\r |
| 445 | i, slet[i].phid, iphase, slet[i].addr, slet[i].nwords, slet[i].sector, smark, sstr, nsecs);\r |
| 446 | \r |
| 447 | if (iphase < 0)\r |
| 448 | iphase = -iphase;\r |
| 449 | \r |
| 450 | if (sletinfo[j].pfrom == 0)\r |
| 451 | printf(" ???");\r |
| 452 | else if (! sletinfo[j].printed) {\r |
| 453 | printf(" %s", sletinfo[j].name);\r |
| 454 | sletinfo[j].printed = TRUE;\r |
| 455 | }\r |
| 456 | \r |
| 457 | for (j = 0; j < i; j++) {\r |
| 458 | if (sec == (slet[j].sector & 0x7FF)) {\r |
| 459 | printf(" (same as %04x)", slet[j].phid);\r |
| 460 | break;\r |
| 461 | }\r |
| 462 | }\r |
| 463 | \r |
| 464 | max_sec = MAX(max_sec, sec+nsecs-1); // find last sector used\r |
| 465 | \r |
| 466 | putchar('\n');\r |
| 467 | \r |
| 468 | if (i >= 15 && ! verbose) {\r |
| 469 | printf("...\n");\r |
| 470 | break;\r |
| 471 | }\r |
| 472 | }\r |
| 473 | }\r |
| 474 | \r |
| 475 | int ascii_to_ebcdic_table[128] = \r |
| 476 | {\r |
| 477 | 0x00,0x01,0x02,0x03,0x37,0x2d,0x2e,0x2f, 0x16,0x05,0x25,0x0b,0x0c,0x0d,0x0e,0x0f,\r |
| 478 | 0x10,0x11,0x12,0x13,0x3c,0x3d,0x32,0x26, 0x18,0x19,0x3f,0x27,0x1c,0x1d,0x1e,0x1f,\r |
| 479 | 0x40,0x5a,0x7f,0x7b,0x5b,0x6c,0x50,0x7d, 0x4d,0x5d,0x5c,0x4e,0x6b,0x60,0x4b,0x61,\r |
| 480 | 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7, 0xf8,0xf9,0x7a,0x5e,0x4c,0x7e,0x6e,0x6f,\r |
| 481 | \r |
| 482 | 0x7c,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7, 0xc8,0xc9,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,\r |
| 483 | 0xd7,0xd8,0xd9,0xe2,0xe3,0xe4,0xe5,0xe6, 0xe7,0xe8,0xe9,0xba,0xe0,0xbb,0xb0,0x6d,\r |
| 484 | 0x79,0x81,0x82,0x83,0x84,0x85,0x86,0x87, 0x88,0x89,0x91,0x92,0x93,0x94,0x95,0x96,\r |
| 485 | 0x97,0x98,0x99,0xa2,0xa3,0xa4,0xa5,0xa6, 0xa7,0xa8,0xa9,0xc0,0x4f,0xd0,0xa1,0x07,\r |
| 486 | };\r |
| 487 | \r |
| 488 | int ebcdic_to_ascii (int ch)\r |
| 489 | {\r |
| 490 | int j;\r |
| 491 | \r |
| 492 | for (j = 32; j < 128; j++)\r |
| 493 | if (ascii_to_ebcdic_table[j] == ch)\r |
| 494 | return j;\r |
| 495 | \r |
| 496 | return '?';\r |
| 497 | }\r |
| 498 | \r |
| 499 | #define HDR_LEN 120\r |
| 500 | \r |
| 501 | void dump_hdng(void)\r |
| 502 | {\r |
| 503 | int i;\r |
| 504 | char str[HDR_LEN+1], *p = str;\r |
| 505 | \r |
| 506 | showmajor("Sector 7 - Heading");\r |
| 507 | getsector(7, buf);\r |
| 508 | \r |
| 509 | for (i = 0; i < (HDR_LEN/2); i++) {\r |
| 510 | *p++ = ebcdic_to_ascii((buf[i] >> 8) & 0xFF);\r |
| 511 | *p++ = ebcdic_to_ascii( buf[i] & 0xFF);\r |
| 512 | }\r |
| 513 | \r |
| 514 | *p = '\0';\r |
| 515 | trim(str);\r |
| 516 | printf("%s\n", str);\r |
| 517 | }\r |
| 518 | \r |
| 519 | BOOL mget (int offset, char *name)\r |
| 520 | {\r |
| 521 | char title[80];\r |
| 522 | \r |
| 523 | if (dcom[offset] == 0)\r |
| 524 | return FALSE;\r |
| 525 | \r |
| 526 | getsector(dcom[offset], buf);\r |
| 527 | sprintf(title, "Sector %x - %s", dcom[offset], name);\r |
| 528 | showmajor(title);\r |
| 529 | return TRUE;\r |
| 530 | }\r |
| 531 | \r |
| 532 | void dump_scra (void)\r |
| 533 | {\r |
| 534 | if (! mget(SCRA, "SCRA"))\r |
| 535 | return;\r |
| 536 | \r |
| 537 | dump(verbose ? SECLEN : 32);\r |
| 538 | }\r |
| 539 | \r |
| 540 | void dump_let (void)\r |
| 541 | {\r |
| 542 | if (! mget(ULET, "LET"))\r |
| 543 | return;\r |
| 544 | }\r |
| 545 | \r |
| 546 | void dump_flet (void)\r |
| 547 | {\r |
| 548 | if (! mget(FLET, "FLET"))\r |
| 549 | return;\r |
| 550 | }\r |
| 551 | \r |
| 552 | void dump_cib (void)\r |
| 553 | {\r |
| 554 | if (! mget(CIBA, "CIB"))\r |
| 555 | return;\r |
| 556 | \r |
| 557 | dump(verbose ? SECLEN : 32);\r |
| 558 | }\r |
| 559 | \r |
| 560 | #define LFHD 5 // WORD COUNT OF LET/FLET HEADER PMN09970\r |
| 561 | #define LFEN 3 // NO OF WDS PER LET/FLET ENTRY PMN09980\r |
| 562 | #define SCTN 0 // RLTY ADDR OF LET/FLET SCTR NO. PMN09990\r |
| 563 | #define UAFX 1 // RLTV ADDR OF SCTR ADDR OF UA/FXA PMN10000\r |
| 564 | #define WDSA 3 // RLTV ADDR OF WDS AVAIL IN SCTR PMN10010\r |
| 565 | #define NEXT 4 // RLTV ADDR OF ADDR NEXT SCTR PMN10020\r |
| 566 | #define LFNM 0 // RLTV ADDR OF LET/FLET ENTRY NAME PMN10030\r |
| 567 | #define BLCT 2 // RLTV ADDR OF LET/FLET ENTRY DBCT PMN10040\r |
| 568 | \r |
| 569 | void bail (char *fmt, ...)\r |
| 570 | {\r |
| 571 | va_list args;\r |
| 572 | \r |
| 573 | va_start(args, fmt);\r |
| 574 | fprintf(stderr, fmt, args);\r |
| 575 | va_end(args);\r |
| 576 | putchar('\n');\r |
| 577 | \r |
| 578 | exit(1);\r |
| 579 | }\r |
| 580 | \r |
| 581 | // ---------------------------------------------------------------------------------\r |
| 582 | // trim - remove trailing whitespace from string s\r |
| 583 | // ---------------------------------------------------------------------------------\r |
| 584 | \r |
| 585 | char *trim (char *s)\r |
| 586 | {\r |
| 587 | char *os = s, *nb;\r |
| 588 | \r |
| 589 | for (nb = s-1; *s; s++)\r |
| 590 | if (*s > ' ')\r |
| 591 | nb = s;\r |
| 592 | \r |
| 593 | nb[1] = '\0';\r |
| 594 | return os;\r |
| 595 | }\r |
| 596 | \r |
| 597 | /* ------------------------------------------------------------------------ \r |
| 598 | * lowcase - force a string to lowercase (ASCII)\r |
| 599 | * ------------------------------------------------------------------------ */\r |
| 600 | \r |
| 601 | char *lowcase (char *str)\r |
| 602 | {\r |
| 603 | char *s;\r |
| 604 | \r |
| 605 | for (s = str; *s; s++) {\r |
| 606 | if (*s >= 'A' && *s <= 'Z')\r |
| 607 | *s += 32;\r |
| 608 | } \r |
| 609 | \r |
| 610 | return str;\r |
| 611 | }\r |
| 612 | \r |