home *** CD-ROM | disk | FTP | other *** search
- /*
- ******************************************************************************
- * *
- * fastdump.c version 1.1 of 19 June 1988 (C) L.J.M. de Wit 1988 *
- * *
- * This software may be used and distributed freely if not used commercially *
- * and the originator (me) is mentioned. *
- * *
- ******************************************************************************
- *
- * NAME
- * fastdump - fast ascii screen dump
- *
- * SYNTAX
- * fastdump.prg
- *
- * DESCRIPTION
- * Fastdump does a fast screen dump whenever the Alt Help key is pressed.
- * It reads the screen memory to match on font characters; matched
- * characters are printed as-is, non-matched characters as spaces.
- * It has some intelligence as to avoid printing trailing spaces.
- * It is very useful as afterwards printer, e.g. after a compilation with
- * error messages, or a program that exits with failure messages, and also
- * for printing source/text from within an editor, or for programs that do
- * not provide for hardcopy output.
- *
- * Fastdump should be in the AUTO folder as FASTDUMP.PRG so that it is
- * installed memory resident when the system is loaded. It then overrides
- * the standard screen dump routine.
- *
- * BUGS
- * The program does not provide for RS232 printing yet. The Centronics port
- * is used.
- *
- * The routine is not used when it is called from the XBIOS. This is because
- * of old disk-based TOS versions that had the dump vector hardcoded. A
- * future release of this program (if there will be any &-) will use the
- * screen dump vector at address 0x502.
- *
- * Characters in reverse video are not matched yet with their reverse images
- * so that reverse video now results in spaces. Also something for the next
- * release.
- *
- * DECISIONS
- * The current version is compiled with a Lattice C compiler; people using
- * other compilers should be aware of the fact that on entrance of do_dump()
- * the contents of A4/A5 will be different from what it was when the
- * program was started (being an interrupt-routine) so that register
- * relative addressing cannot be used in this case (or A4 should be loaded
- * when the routine is entered). For Lattice C absolute addressing is the
- * default so that there was no problem in this case.
- * After compilation the module should be linked only with the standard
- * library (for the gemdos function). So the link file should contain:
- * INPUT fastdump.bin
- * LIBRARY clib.bin
- * startup.bin is not used, and the function startup() is used as entry point.
- * The size of the resulting code is much smaller now (not using stdio etc).
- *
- */
-
- #include <osbind.h>
- #include <portab.h>
-
- #define DUMPFLG (*(WORD *)0x4EE) /* Alt Help pressed flag */
- #define SSHIFTMD (*(BYTE *)0x44C) /* Screen Shift Mode */
- #define V_BAS_AD (*(LONG *)0x44E) /* logical screen base address */
- #define NVBLS (*(WORD *)0x454) /* length of this array */
- #define VBLQUEUE (*(que_ptr *)0x456) /* array of VBL vectors */
- #define HZ_200 (*(LONG *)0x4BA) /* 200 Hz system clock */
- #define CENTRONICS_BUSY (1 & *(BYTE *)0xFFFFFA01)
- #define GI ((BYTE *)0xFFFF8800) /* I/O locations for sound chip*/
-
- /* font definitions */
- typedef struct font_header {
- WORD f_id; /* font identifier; system font = 1 */
- WORD f_point; /* font size in points */
- char f_name[32]; /* font name */
- WORD f_low; /* lowest ascii code in font */
- WORD f_high; /* highest ascii code in font */
- WORD f_top; /* relative distance of top to base line */
- WORD f_ascent; /* relative distance of ascent to base line */
- WORD f_half; /* relative distance of half to base line */
- WORD f_descent; /* relative distance of descent to base line */
- WORD f_bottom; /* relative distance of bottom to base line */
- WORD f_maxcharw; /* maximal character width in font */
- WORD f_maxcellw; /* maximal cell width in font */
- WORD f_loffset; /* left offset */
- WORD f_roffset; /* right offset */
- WORD f_fatsiz; /* degree of fattening */
- WORD f_ulsiz; /* underline degree */
- WORD f_normask; /* normal cancelled mask */
- WORD f_skewmask; /* skewing cancelled mask */
- WORD f_flag; /* flag:
- * bit 0: system font;
- * bit 1: hor. offset;
- * bit 2: byte swap;
- * bit 3: non proportional font
- */
- WORD *f_horoff; /* pointer to horizontal offsets table */
- WORD *f_charoff; /* pointer to character offsets table */
- char *f_data; /* pointer to font data table */
- WORD f_fontw; /* total width of all chars in font */
- WORD f_fonth; /* height of font (# scanlines) */
- struct font_header
- *f_next; /* pointer to next font header */
- } font_header;
-
- static UWORD g_fheader[] = { 0xA000, /* LineA exception 0 */
- 0x222F,0x0004, /* MOVE.L 4(SP),D1 */
- 0xE581, /* ASL.L #2,D1 */
- 0x2031,0x1800, /* MOVE.L 0(A1,D1),D0 */
- 0x4E75 }; /* RTS */
-
- static UWORD get_sr[] = { 0x7000, /* MOVEQ.L #0,D0 */
- 0x40C0, /* MOVE.W SR,D0 */
- 0x007C,0x0700, /* OR.W #$700,SR */
- 0x4E75 }; /* RTS */
-
- static UWORD set_sr[] = { 0x46EF,0x0006, /* MOVE.W 6(SP),SR */
- 0x4E75 }; /* RTS */
-
- WORD planes;
- font_header *fhp;
-
- static void do_dump(), startup();
- static BYTE lstout(), get_schar(),
- read_gi(), write_gi(), dummy();
-
- typedef void (**que_ptr)(); /* que_ptr points to an array of pointers
- * to functions returning void
- */
-
- static void startup(base)
- LONG *base;
- {
- LONG memneed;
- extern LONG _mneed;
- WORD i, nvbls;
- LONG ssp;
-
- memneed = 0x100 + /* base page */
- base[3] + /* text length */
- base[5] + /* data length */
- base[7] + /* bss length */
- 0x800 + /* workspace */
- 0x900; /* for stack */
-
- ssp = Super(0); /* Supervisor mode */
- nvbls = NVBLS; /* length of VBLQUEUE array */
-
- for (i = 0; i < nvbls; i++) {
- if (VBLQUEUE[i] == (void (*)())0) {/* If empty slot found */
- VBLQUEUE[i] = do_dump; /* set vector for new routine */
- break;
- }
- }
-
- Super(ssp); /* Back to User mode again */
-
- if (i < nvbls) { /* If empty slot was found */
- Ptermres(memneed,0); /* make resident & terminate */
- } else { /* else report the problem & */
- Cconws("Cannot bind new VBL routine\r\n");
- Pterm(1); /* terminate with error status */
- }
- }
-
- static void do_dump() /* The interrupt routine */
- {
- WORD i, j;
- char *s, *t;
- WORD rows, cols; /* Rows & columns of screen */
- char line[81]; /* Holds a line to be printed */
- BYTE status; /* Printer ready status */
- BYTE rez; /* resolution 2 high 1 med 0 low*/
-
- if (DUMPFLG != 0) { /* Alt Help not pressed? */
- return;
- }
-
- if ((rez = SSHIFTMD & 3) == 3) {
- rez = 2;
- }
- fhp = (*(font_header *(*)())g_fheader)
- ((rez == 2) ? 2 : 1); /* pointer to standard font */
- planes = 4 >> rez; /* # of bit planes: 4, 2 or 1 */
- rows = 25;
- cols = (rez == 0) ? 40 : 80;
-
- for (i = 0; i < rows; i++) { /* Handle each screen row ... */
- s = line; t = line;
- for (j = 0; j < cols; j++, s++) { /* Handle each column per row */
- *s = get_schar(i,j); /* Get ASCII value at this pos.*/
- if ((*s != ' ') || (*t != ' ')) {/* t: last nonsp. or first sp. */
- t = s;
- }
- }
- *s = '\0'; /* null-terminate line */
- if (*t == ' ') {
- *t = '\0'; /* discards trailing spaces */
- }
-
- status = 0;
- for (s = line; *s != '\0'; s++) { /* print each char/test status */
- status = lstout(*s);
- if (status != 0) break; /* printer not ready; abort */
- }
-
- if (status != 0) break; /* abort */
-
- lstout('\r'); lstout('\n'); /* terminate line with CR/LF */
-
- if (DUMPFLG != 0) { /* Alt Help pressed again? */
- break;
- }
- }
-
- DUMPFLG = -1; /* No Hardcopy */
- }
-
- static BYTE lstout(c) /* Send one character */
- char c; /* to Centronics port */
- {
- LONG start;
- BYTE not_ready;
-
- start = HZ_200;
- do { /* poll the status */
- not_ready = CENTRONICS_BUSY;
- dummy(); /* to prevent erroneous optim. */
- } while (not_ready &&
- (HZ_200 - start < 6000)); /* 30 sec. timeout */
-
- if (!not_ready) { /* The actual printing */
- BYTE val;
- LONG istatus;
-
- istatus = (*(LONG (*)())get_sr)(); /* Save SR */
- val = read_gi(7);
- write_gi(7,val | 0x80);
- (*(LONG (*)())set_sr)(istatus); /* Restore SR */
- write_gi(15,c);
-
- val = read_gi(14);
- write_gi(14,val & 0xDF);
- val = read_gi(14);
- write_gi(14,val | 0x20);
- }
-
- return not_ready; /* return 0 for OK */
- }
-
- static BYTE read_gi(reg) /* Read from G.I. sound chip */
- BYTE reg;
- {
- LONG istatus;
-
- istatus = (*(LONG (*)())get_sr)(); /* Save SR */
- GI[0] = reg;
- reg = dummy(); /* prevents optimizing away .. */
- reg = GI[0]; /* ... this statement */
- (*(LONG (*)())set_sr)(istatus); /* Restore SR */
-
- return reg;
- }
-
- static BYTE dummy() /* This function is used to */
- { /* fool the compiler so that */
- return 0; /* no statement is optimized */
- } /* away (volatile variables) */
-
- static BYTE write_gi(reg,val) /* Write to G.I. sound chip */
- BYTE reg,val;
- {
- LONG istatus;
-
- istatus = (*(LONG (*)())get_sr)(); /* Save SR */
- GI[0] = reg;
- GI[2] = val;
- reg = dummy(); /* prevents optimizing away .. */
- reg = GI[0]; /* ... this statement */
- (*(LONG (*)())set_sr)(istatus); /* Restore SR */
-
- return reg;
- }
-
- static BYTE get_schar(i,j) /* Find match in a font for */
- WORD i,j; /* the character bit image at */
- { /* position (row,col) */
- register WORD l; /* line counter */
- register BYTE *cpd, /* char ptr into font_data */
- *cps; /* char ptr into ch_img[] */
- register WORD p, c;
- WORD *curadd, /* screen address of top word */
- sval; /* will hold a word of image */
- BYTE ch_img[16], /* will hold image as bytes */
- or_all; /* OR of all bytes of image */
- UWORD w_p_l, /* # words per line */
- maxl; /* height of a char in lines */
-
- w_p_l = (planes == 1) ? 40 : 80;
- maxl = (planes == 1) ? 16 : 8;
- curadd = (WORD *)(V_BAS_AD + i * 1280 + (j & ~1) * planes);
-
- /* prepare ch_img[] to hold a adjusted copy of the bit image */
- or_all = 0;
- for (l = 0; l < maxl; l++) {
- sval = 0;
- for (p = 0; p < planes; p++) { /* OR in all colour bit planes */
- sval |= curadd[l * w_p_l + p];
- }
-
- ch_img[l] = (j & 1) ? sval & 0xff /* Take lower or upper byte */
- : (sval >> 8) & 0xff; /* as appropriate */
- or_all |= ch_img[l]; /* Keeps inclusive Or of all */
- }
-
- /* search */
- if (or_all == 0) { /* Not a pixel set */
- c = ' '; /* then space will be printed */
- } else { /* else for each char in font */
- for (c = fhp->f_low; c <= fhp->f_high; c++) {
- cpd = fhp->f_data + (fhp->f_charoff[c] >> 3);
- cps = ch_img;
- for (l = 0; l < maxl; l++) { /* Compare each line (byte) */
- if (*cps++ != *cpd) break; /* Match failed at this line */
- cpd += fhp->f_fontw;
- }
- if (l >= maxl) break; /* All lines matched */
- }
-
- if ((c == '\0') || (c > fhp->f_high)) { /* If no match */
- c = ' '; /* use space instead */
- }
- }
-
- return (BYTE)c; /* Return matched char or space*/
- }
-
-
-