home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
GEMini Atari
/
GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso
/
files
/
utility
/
fastdump
/
fastdump.src
next >
Wrap
C/C++ Source or Header
|
1989-03-29
|
14KB
|
341 lines
/*
******************************************************************************
* *
* 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*/
}