braner@batcomputer.TN.CORNELL.EDU (braner) (11/03/86)
[]
/*
* Program to code ST screens in a text file.
* By Moshe Braner, 861103.
*
* Run once, it stays in RAM and is activated by Alt-Help.
*
* This version written for the Megamax C compiler.
*/
#include <osbind.h>
/* register assignments: */
#define REPN D3
#define INDEX D4
#define REP D5
#define ROW D6
#define OUTN D7
#define OLD A2
#define COL A3
#define PHYS A4
#define COLS A5
#define VAR A6
#define BUF A6
#define SP A7
/* non-register variables: */
#define HAND -2
#define ROWS -4
#define RES -6
#define LINEN -8
#define CHKSUM -12 /* long! */
#define DTA -60 /* 44 bytes */
extern dump();
asm {
dump:
MOVE.W #1,0x4EE
MOVEM.L A6-A0/D7-D0,-(SP)
LEA vars+60(PC),VAR
MOVE.B 0xFF8260,D0 /* video resolution */
AND.L #0x00000003,D0
MOVE.L D0,CHKSUM(VAR)
MOVE.W D0,RES(VAR)
ADD.W #0x30,D0
MOVE.B D0,(BUF) /* output resolution (1 byte) */
LEA dumpname+8(PC),A0
MOVE.B D0,(A0) /* modify file name */
PEA DTA(VAR) /* check for last file name used */
MOVE.W #0x1A,-(SP) /* SETDTA */
TRAP #1
ADDQ.L #6,SP
chkname:
CLR.W -(SP) /* attribute 0 = normal files */
PEA dumpname(PC)
MOVE.W #0x4E,-(SP) /* SFIRST */
TRAP #1
ADDQ.L #8,SP
TST D0
BNE.S okname /* not found - use it */
LEA dumpname+4(PC),A0
CMPI.B #0x5A,(A0) /* was 'A' - up to 'Z' ? */
BLT.S incname
MOVE.B #0x41,(A0) /* back to 'A' */
BRA.S okname
incname:
ADDQ.B #1,(A0)
BRA.S chkname
okname:
CLR.W -(SP) /* attribute 0 = r/w file */
PEA dumpname(PC)
MOVE.W #0x3C,-(SP) /* CREATE */
TRAP #1
ADDQ.L #8,SP
TST D0 /* any errors? */
BMI cleanup /* - then skip */
MOVE.W D0,HAND(VAR) /* file handle */
MOVE.W #2,-(SP) /* PHYSBASE */
TRAP #14
ADDQ.L #2,SP
MOVE.L D0,PHYS /* video RAM */
MOVEQ #1,OUTN /* output char counter */
MOVE.W #1,LINEN(VAR) /* line length counter */
MOVE.L #0xFF8240,A0 /* palette */
MOVE.W #15,D2
palette: /* output palette (48 bytes) */
CLR.L D0
MOVE.W (A0)+,D0
ADD.L D0,CHKSUM(VAR)
BSR codeuniq
DBF D2,palette
LEA consts,A0 /* read constants from table */
MOVE.W RES(VAR),D0
ADD.W D0,D0
MOVE.W 0(A0,D0),ROW
MOVE.W ROW,ROWS(VAR)
MOVE.W 6(A0,D0),COLS
MOVE.W #0,COL /* set up for coding */
SUBQ.W #1,ROW
CLR.W REP
CLR.W INDEX
BSR nextw
MOVE.W D0,OLD
BRA.S comp2
comp1: /* compress the picture */
MOVE.W COL,D0
CMP.W COLS,D0
BGE.S endloop
MOVE.W ROWS(VAR),ROW
MOVE.W COL,INDEX
comp2:
BSR nextw
CMP.W OLD,D0
BNE.S notrep
TST.W REP
BNE.S oldrep
SEQ REP
MOVEQ #1,REPN
oldrep:
CMP.W #127,REPN
BLT.S loop1
notrep:
EXG D0,OLD
TST.W REP
BEQ.S uniq
CLR.W REP
BSR coderep
BRA.S loop
uniq:
BSR codeuniq
loop:
BNE.S close /* error writing file */
loop1:
ADDQ.W #1,REPN
DBF ROW,comp2
ADDQ.W #1,COL
BRA comp1
endloop:
TST.W REP /* in middle of repetition? */
BEQ.S done
MOVE.W OLD,D0 /* then go finish it... */
BSR coderep
done:
MOVE.W CHKSUM(VAR),D0 /* append coded checksum */
BSR codeuniq
MOVE.L CHKSUM(VAR),D0
BSR codeuniq
BSR crlf /* end last line */
BSR save /* save to disk */
close:
MOVE.W HAND(VAR),-(SP)
MOVE.W #0x3E,-(SP) /* CLOSE file */
TRAP #1
ADDQ.L #4,SP
cleanup:
MOVEM.L (SP)+,D0-D7/A0-A6
MOVE.W #0xFFFF,0x4EE
/* ADDQ.L #4,SP ROM does it, so me too? */
RTS /* return to interrupt handler */
coderep:
MOVE.W D0,D1
MOVE.W REPN,D0
LSR.W #2,D0
ORI.W #0x40,D0
BSR notz
LSL.W #4,REPN
MOVE.W D1,D0
LSR.W #6,D0
LSR.W #6,D0
OR.W REPN,D0
BRA.S code1
codeuniq:
MOVE.W D0,D1
LSR.W #6,D0
LSR.W #6,D0
code1:
BSR outbyte
MOVE.W D1,D0
LSR.W #6,D0
BSR outbyte
MOVE.W D1,D0
BSR outbyte
CMP.W #4600,OUTN /* buffer almost full? */
BLT.S nosave
save: /* save to disk */
MOVE.L BUF,-(SP)
EXT.L OUTN
MOVE.L OUTN,-(SP)
MOVE.W HAND(VAR),-(SP)
MOVE.W #0x40,-(SP) /* WRITE to file */
TRAP #1
ADDA #12,SP
CMP.W OUTN,D0
BNE.S error /* retain error code */
CLR.W OUTN
nosave:
CLR.W D0 /* no error */
error:
RTS
nextw: /* read 2 bytes from screen */
CLR.L D0
MOVE.B 0(PHYS,INDEX),D0
ADD.W COLS,INDEX
LSL.W #8,D0
MOVE.B 0(PHYS,INDEX),D0
ADD.W COLS,INDEX
ADD.L D0,CHKSUM(VAR)
RTS
outbyte: /* put byte in buffer */
AND.W #0x3F,D0
BEQ.S zzz
ADD.W #0x20,D0 /* offset by ' ' */
BRA.S notz
zzz:
MOVE.W #0x7A,D0 /* but avoid ' ' itself */
notz:
MOVE.B D0,0(BUF,OUTN)
ADDQ.W #1,OUTN
ADDQ.W #1,LINEN(VAR)
CMPI.W #64,LINEN(VAR) /* line long enough? */
BLT.S nocrlf
crlf:
MOVE.B #0x0D,0(BUF,OUTN) /* then append cr-lf */
MOVE.B #0x0A,1(BUF,OUTN)
ADDQ.W #2,OUTN
CLR.W LINEN(VAR)
nocrlf:
RTS
dumpname: /* filename: "DUMPA.CSn" - will be changed */
DC.B 0x44,0x55,0x4D,0x50,0x41,0x2E,0x43,0x53,0x6E,0x00
consts: /* rows/2-1, columns */
DC.W 99,99,199,160,160,80
vars: /* 60-byte variable space, */
/* then 4608-byte output buffer */
}
char dummy[4668]; /* ensure enough space in SBRK */
extern poke_it(); /* put our vector for screen dump */
asm {
poke_it:
LEA dump,A0
MOVE.L #0x000502,A1
MOVE.L A0,(A1)
RTS
}
char *text[] = {
"\033E\r\n",
"\t+--------------------------+\r\n",
"\t| SCREEN DUMP PROGRAM |\r\n",
"\t| (Compressed format) |\r\n",
"\t| for |\r\n",
"\t| Atari ST with TOS in ROM |\r\n",
"\t| by Moshe Braner, 8610 |\r\n",
"\t+--------------------------+\r\n",
"\r\n",
"\tProgram installed. Hit any key.\r\n",
"\r\n",
"\t(Later: press Alt-Help for a screen dump.\r\n",
"\t Dumps into files DUMPA.CSn, DUMPB.CSn, ...\r\n",
"\t where n = 0, 1 or 2 for lo, med or hi res.)\r\n",
"\r\n\n",
""
};
main()
{
register char c;
register char *cp;
register char **cpp;
Supexec(&poke_it); /* mess with vector */
cpp = &text[0]; /* print message */
while (*(cp=*cpp++))
while (c=*cp++)
Bconout(2, c);
Bconin(2); /* wait for keypress */
Ptermres((long)6000, 0); /* stay resident */
}
- Moshe Braner, Cornell U.