[net.micro.atari16] SCODE - a program to code ST screens

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.