Old tools that got removed a long time ago.

git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@1545 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
meep-eep
2005-02-19 00:38:46 +00:00
parent 440fec6289
commit e7eabd46b9
51 changed files with 10988 additions and 0 deletions
+138
View File
@@ -0,0 +1,138 @@
DeluxePaint Animation ".ANM" files consist of a large header and a series of
structures that can be up to 64 KB long each. The programmer refers to these
structures as "Large Pages". Large Pages are a format for dividing a file
into 64 KB chunks that can be stored out-of-sequence in the file. That is,
a large page can be logically inserted into the file, without having to move
all the following data out of the way.
Each large page holds one or more "records". A record represents one frame
of the original animation. A record is of any length from 0 to almost 64 KB.
The records in a large page are sequential. However, the first large page
may not contain the first frames of the anim file. Each large page contains
a sequential set of records but the large pages themselves are not in
sequential order. It is possible for the first large page in a file to
contain the last few frames of the animation. When you process the anim file
you must scan the large page structures to find which large page conatins the
frame you wish to display or process next.
A DeluxePaint Animation "ANM" ("Anim") file is built on this mechanism,
so that as frames change in size, they can be maintained with a minimum
of extra file i/o, yet without loss of playback performance.
In addition, there is an optional special record which is the delta from
the last frame to the first frame, for smooth playback of looping anims.
The following is the structure of a DeluxeAnimate anim file header.
Header size is exactly 2816 bytes. The first large page structure can be
reached by simply seeking to this location in the file.
ULONG id; 4 character ID == "LPF "
UWORD maxLps; max # largePages allowed. 256 FOR NOW.
UWORD nLps; # largePages in this file.
ULONG nRecords; # records in this file. 65534 is current limit plus
one for last-to-first delta for looping the animation
UWORD maxRecsPerLp; # records permitted in an lp. 256 FOR NOW.
UWORD lpfTableOffset; Absolute Seek position of lpfTable. 1280 FOR NOW.
The lpf Table is an array of 256 large page structures
that is used to facilitate finding records in an anim
file without having to seek through all of the Large
Pages to find which one a specific record lives in.
ULONG contentType; 4 character ID == "ANIM"
UWORD width; Width of screen in pixels.
UWORD height; Height of screen in pixels.
UBYTE variant; 0==ANIM.
UBYTE version; 0==frame rate is multiple of 18 cycles/sec.
1==frame rate is multiple of 70 cycles/sec.
UBYTE hasLastDelta; 1==Last record is a delta from last-to-first frame.
UBYTE lastDeltaValid; 0==The last-to-first delta (if present) hasn't been
updated to match the current first&last frames, so it
should be ignored.
UBYTE pixelType; 0==256 color.
UBYTE CompressionType; 1==(RunSkipDump) Only one used FOR NOW.
UBYTE otherRecsPerFrm; 0 FOR NOW.
UBYTE bitmaptype; 1==320x200, 256-color. Only one implemented so far.
UBYTE recordTypes[32]; Not yet implemented.
ULONG nFrames; In case future version adds other records at end of
file, we still know how many actual frames.
NOTE: DOES include last-to-first delta when present.
UWORD framesPerSecond; Number of frames to play per second.
UWORD pad2[29]; 58 bytes of filler to round up to 128 bytes total.
Range cycles[16]; Color cycling info (128 bytes long).
This is the format of a cycle structure.
typedef struct {
WORD count;
WORD rate;
WORD flags;
UBYTE low, high; /* bounds of range */
} Range;
total is = 256 bytes.
Following the anim file header is the color palette
ULONG palette[256] Color palette arranged as 3 bytes each of Red Green
& Blue and one unused byte.
Following the palette is an array of structures that are copies of the
large page headers. This array is loaded and used to find which large page
a given frame can be found in.
Large_page LParay[256] Copies of all the Large Page structures in the anim
file. Each Large Page structure is 6 bytes long so
the total length of this table is 1536 bytes. Even if
the file only contains 1 large page there are still
256 entries of 6 bytes each.
The Large Pages follow the LParray and are in the sequence dictated by
their order of occurence in the LParray in the anim file header.
The following is the structure of a single Large Page in an anim file. Each
Large Page is exactly 64k long in the anim file. The only exception is the
last large page wich is truncated to be only as long as necessary.
UWORD baseRecord; Number of first record in this large page.
UWORD nRecords; Number of records in lp.
bit 15 of "nRecords" == "has continuation from previous lp".
bit 14 of "nRecords" == "final record continues on next lp".
UWORD nBytes; Total number of bytes of contents, excluding header.
UWORD BytesContinued; The number of bytes of the last record of the
previous large page that extend into this large page.
This was never implemented and is always 0.
UWORD RecordSizes[nRecords] Array of lengths of each record in the large page.
The actual records start here. Each record has a variable length header that
is like the following structure.
typedef struct{
UBYTE IDnum; always 66
UBYTE Flags; 0==no extra bytes field next
UWORD extrabytes; if Flags is non zero this is # of bytes
to skip before compressed data starts
extrabytes does not include the size
of the 2 previous bytes. Also make
sure you round the final address up to
an even byte boundry.
} record_header;
+351
View File
@@ -0,0 +1,351 @@
; my generic graphics routines for C programs
.8086
.model large,c
;*****************************************************************************
; Program code starts here
;*****************************************************************************
EQUIP_FLAG EQU byte ptr ds:[10h] ; (in Video Display Data Area)
CGAbits EQU 00100000b ; bits for EQUIP_FLAG
MDAbits EQU 00110000b
.code
public SetVideoMode
SetVideoMode proc far
push bp ; preserve caller registers
mov bp,sp
push ds
mov ax,40h
mov ds,ax ; DS -> Video Display Data Area
mov bl,CGAbits ; BL := bits indicating presence of CGA
mov al,6[bp] ; AL := desired video mode number
mov ah,al ; test if desired mode is monochrome
and ah,7
cmp ah,7
jne L01 ; jump if desired mode not 7 or 0Fh
mov bl,MDAbits ; BL := bits indicating presence of MDA
L01: and EQUIP_FLAG,11001111b
or EQUIP_FLAG,bl ; set bits in EQUIP_FLAG
xor ah,ah ; AH := 0 (INT 10h function number)
push bp
int 10h ; call ROM BIOS to set the video mode
pop bp
pop ds ; restore caller registers and return
pop bp
ret
SetVideoMode endp
public GetVideoMode
GetVideoMode proc far
push bp
mov ah,0Fh ; Get video mode sub-function
int 10h ; call ROM BIOS to get video mode number
pop bp
xor ah,ah ; AX := video mode number
ret
GetVideoMode endp
; LoadPalette(numcolors, startcolor, paletteaddr)
public LoadPalette
LoadPalette proc far
push bp
mov bp,sp
push bx
push cx
push dx
push es
mov bx,8[bp]
mov cx,6[bp]
mov es,12[bp]
mov dx,10[bp]
mov ax,1012h
int 10H
pop es
pop dx
pop cx
pop bx
pop bp
ret
LoadPalette endp
; initialize the mouse to its default values and display it
public InitMouse
InitMouse proc far
push ax
mov ax,0
int 33h
mov ax,1
int 33h
pop ax
ret
InitMouse endp
; display the mouse cursor
public ShowMouse
ShowMouse proc far
push ax
mov ax,1
int 33h
pop ax
ret
ShowMouse endp
; hide the mouse cursor
public HideMouse
HideMouse proc far
push ax
mov ax,2
int 33h
pop ax
ret
HideMouse endp
; read the mouse buttons and cursor position
; on exit:
; BX = button state bit 0 = left button bit 1 = right button
; CX = cursor x position
; DX = cursor y position
public ReadMouse
ReadMouse proc far
push bp
mov bp,sp
push ds
push si
push bx
push cx
push dx
mov ax,3
int 33h
lds si,6[bp]
mov [si],bx
lds si,10[bp]
mov [si],cx
lds si,14[bp]
mov [si],dx
pop dx
pop cx
pop bx
pop si
pop ds
pop bp
ret
ReadMouse endp
; PlayRunSkipDump(sourcebuf, destbuf);
public PlayRunSkipDump
PlayRunSkipDump proc far
ARGB = 6
PR_SRC_SEG = ARGB+2
PR_SRC_ADDR = ARGB
PR_DST_SEG = ARGB+6
PR_DST_ADDR = ARGB+4
push bp
mov bp,sp
push si
push di
push es
mov si,PR_SRC_ADDR[bp]
mov di,PR_DST_ADDR[bp]
mov es,PR_DST_SEG[bp]
push ds ; Save DS:DGROUP.
mov ds,PR_SRC_SEG[bp] ; SET DS:dstSeg. NOT DGROUP.
sub ch,ch ; SET CH = 0.
jmp short nextOp
skip:
sub cl,80h ; Strip off sign bit, leaving skip cnt.
jz longOp ; cnt==0 indicates a long op.
; --- shortSkip ---
add di,cx ; skip # pixels. (CH=0)
; --- variation on NEXTOP inline to minimize jmp's ---
nextOp: ; Get and decode next op.
mov cl,[si]
inc si
jcxz run
or cl,cl ; Test CL's sign bit.
jl skip
dump:
rep movsb ; copy # pixels. (CH=0)
; --- variation on NEXTOP inline to minimize jmp's ---
mov cl,[si]
inc si
or cl,cl ; Test CL's sign bit.
jl skip
jg dump
run:
mov cl,[si] ; 8-bit unsigned count.
inc si
lodsb ; pixel value.
rep stosb ; set # pixels to value. (CH=0)
; --- variation on NEXTOP inline to minimize jmp's ---
mov cl,[si]
inc si
jcxz run
or cl,cl ; Test CL's sign bit.
jl skip
jmp short dump
longOp: ; NOTE: if load into CX, must clear CH afterwards.
lodsw ; 16-bit unsigned count.
or ax,ax ; set flags.
jle notLongSkip
;longSkip:
add di,ax ; skip # pixels.
jmp short nextOp
; longSkip only used for > 2*127, so can't be very many,
; so don't bother saving one jmp with inline NEXTOP.
notLongSkip:
jz stop ; long count of zero means "stop code".
mov cx,ax ; may SET CH non-zero.
sub ch,80h ; Clear sign bit.
cmp ch,40h
jge longRun
; --- For maximum speed on longDump, caller should insure src & dst are
; aligned. To do so, caller must calculate whether
; src DATA will begin on same (odd or even) alignment as dst data.
; If not, first put a 1-byte Dump, which occupies 2 src bytes, thereby
; shifting relative alignment (src moves 2, dst moves 1).
;longDump
test si,1 ; Insure src word-aligned.
; In case caller didn't sync src & dst, we chose
; to align src because we know it is of benefit --
; aligning dst on 8-bit video cards might not be of
; any benefit.
jz dumpWordAligned
movsb ; get to word boundary.
dec cx
dumpWordAligned:
shr cx,1 ; Convert byte count to word count.
jc dumpOddByte
rep movsw ; Word-aligned.
longOpDone:
sub ch,ch ; SET CH = 0.
jmp short nextOp
dumpOddByte:
rep movsw ; Word-aligned.
movsb
jmp short longOpDone
longRun:
sub ch,40h ; Clear "longRun" bit.
lodsb
mov ah,al ; Replicate byte to word value.
test di,1 ; Insure dst word-aligned.
jz runWordAligned
stosb
dec cx
runWordAligned:
shr cx,1 ; Convert byte count to word count.
jc runOddByte
rep stosw ; Word-aligned.
jmp short longOpDone
runOddByte:
rep stosw ; Word-aligned.
stosb
jmp short longOpDone
stop:
pop ds ; Restore DS:DGROUP.
mov ax,di ; RETURN final dstAddr.
pop es
pop di
pop si
pop bp
ret
PlayRunSkipDump endp
; clear the screen to a color
; cls(color);
public cls
cls proc far
push bp
mov bp,sp
push di
push es
push cx
mov ax,0A000h
mov es,ax
xor di,di
mov al,6[bp]
mov ah,al
mov cx,32000
rep stosw
pop cx
pop es
pop di
pop bp
ret
cls endp
end
+8
View File
@@ -0,0 +1,8 @@
showanim.obj: showanim.c showanim.h
cl /c /Zi /AL showanim.c
cgraph.obj: cgraph.asm
masm $*;
showanim.exe: showanim.obj cgraph.obj
link /co showanim+cgraph;
+323
View File
@@ -0,0 +1,323 @@
/*
This is a small program to play a deluxe animate file. No attempt has
been made to time the animation speed correctly. The playback speed will
be dictated by the speed of your machine.
*/
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#define EXIT_FAILURE 1
#define EXIT_SUCCESS 0
#define TRUE 1
#define FALSE 0
/* Typedefs for portability. */
typedef char BOOL; /* 0==FALSE, 1==TRUE */
typedef char BYTE; /* signed 8-bit number */
typedef unsigned char UBYTE; /* unsigned 8-bit number */
typedef int WORD; /* signed 16-bit number */
typedef unsigned int UWORD; /* unsigned 16-bit number */
typedef long LONG; /* signed 32-bit number */
typedef unsigned long ULONG; /* unsigned 32-bit number */
/* function prototypes */
void SetVideoMode(UWORD mode);
WORD GetVideoMode(void);
void LoadPalette(UWORD numcolors, UWORD startcolor, UBYTE *paletteaddr);
void InitMouse(void);
void ShowMouse(void);
void HideMouse(void);
void ReadMouse(UWORD *buttonstate, UWORD *mousex, UWORD *mousey);
void PlayRunSkipDump(UBYTE *srcbuf, UBYTE *dstbuf);
void cls(UWORD color);
#include "showanim.h" /* contains structures for large page files */
lpfileheader lpheader; /* file header will be loaded into this structure */
lp_descriptor LpArray[256]; /* arrays of large page structs used to find frames */
UBYTE lppalette[768]; /* anim file palette is loaded here */
UBYTE *screen = (char *)0xA0000000l; /* pointer to the screen */
UWORD curlpnum=0xFFFF; /* initialize to an invalid Large page number */
lp_descriptor curlp; /* header of large page currently in memory */
UWORD *thepage; /* pointer to the buffer where current large page is loaded */
FILE *infile; /* input file pointer */
ULONG inputsize; /* input file size. I allways get this out of habbit */
/* support routines for the rest of the program start here */
/* given a frame number return the large page number it resides in */
UWORD findpage(framenumber)
UWORD framenumber;
{
UWORD i;
for(i=0; i<lpheader.nLps; i++)
{
if(LpArray[i].baseRecord <= framenumber && LpArray[i].baseRecord + LpArray[i].nRecords > framenumber)
return(i);
}
return(i);
}
/* seek out and load in the large page specified */
loadpage(pagenumber, pagepointer)
UWORD pagenumber;
UWORD *pagepointer;
{
if(curlpnum!=pagenumber)
{
curlpnum=pagenumber;
fseek(infile, 0x0B00l+(LONG)pagenumber * 0x10000l,SEEK_SET);
fread(&curlp, sizeof(lp_descriptor), 1, infile);
getw(infile); /* skip empty word */
fread(pagepointer, curlp.nBytes+(curlp.nRecords*2), 1, infile);
}
}
/* This version of the decompressor is here for portability to non PC's */
void CPlayRunSkipDump(srcP,dstP)
BYTE *srcP; /* srcP points at first sequence in Body */
BYTE *dstP; /* dstP points at pixel #0 on screen. */
{
BYTE cnt;
UWORD wordCnt;
UBYTE pixel;
nextOp:
cnt = (signed char) *srcP++;
if (cnt > 0)
goto dump;
if (cnt == 0)
goto run;
cnt -= 0x80;
if (cnt == 0)
goto longOp;
/* shortSkip */
dstP += cnt; /* adding 7-bit count to 32-bit pointer */
goto nextOp;
dump:
do
{
*dstP++ = *srcP++;
} while (--cnt);
dstP += cnt;
srcP += cnt;
goto nextOp;
run:
wordCnt = (UBYTE)*srcP++; /* 8-bit unsigned count */
pixel = *srcP++;
do
{
*dstP++ = pixel;
} while (--wordCnt);
dstP += wordCnt;
goto nextOp;
longOp:
wordCnt = *((UWORD far *)srcP)++;
if ((WORD)wordCnt <= 0)
goto notLongSkip; /* Do SIGNED test. */
/* longSkip. */
dstP += wordCnt;
goto nextOp;
notLongSkip:
if (wordCnt == 0)
goto stop;
wordCnt -= 0x8000; /* Remove sign bit. */
if (wordCnt >= 0x4000)
goto longRun;
/* longDump. */
do
{
*dstP++ = *srcP++;
} while (--wordCnt);
dstP += wordCnt;
srcP += wordCnt;
goto nextOp;
longRun:
wordCnt -= 0x4000; /* Clear "longRun" bit. */
pixel = *srcP++;
do
{
*dstP++ = pixel;
} while (--wordCnt);
dstP += wordCnt;
goto nextOp;
stop: /* all done */
;
}
/* draw the frame sepcified from the large page in the buffer pointed to */
renderframe(framenumber, pagepointer)
UWORD framenumber;
UWORD *pagepointer;
{
UWORD offset=0;
UWORD i;
UWORD destframe;
UBYTE *ppointer;
destframe = framenumber - curlp.baseRecord;
for(i = 0; i < destframe; i++)
{
offset += pagepointer[i];
}
ppointer = (UBYTE *)pagepointer;
ppointer+=curlp.nRecords*2+offset;
if(ppointer[1])
{
ppointer += (4 + (((UWORD *)ppointer)[1] + (((UWORD *)ppointer)[1] & 1)));
}
else
{
ppointer+=4;
}
/*
this is the C version of the decompressor, uncomment it if you are not
running on a PC
*/
/* CPlayRunSkipDump(ppointer, screen); */
PlayRunSkipDump(ppointer, screen);
}
/* high level frame draw routine */
void drawframe(framenumber)
UWORD framenumber;
{
loadpage(findpage(framenumber), thepage);
renderframe(framenumber, thepage);
}
/* main program code */
main(argc,argv)
int argc;
char *argv[];
{
UWORD i;
UWORD framecount;
WORD oldvideomode;
UWORD mousebutton=0, mousex=0, mousey=0;
/* had to use "halloc" because I had to allocate a buffer exactly 64k long */
thepage =(UWORD *)halloc(0x10000l,1); /* allocate page buffer */
if(argc < 2)
{
printf("'Showanim file.ANM' display Deluxe animate file on VGA screen.\n\n");
return EXIT_FAILURE;
}
if((infile = fopen(argv[1],"rb")) == NULL)
{
printf("Input file not found!\n");
return EXIT_FAILURE;
}
/* get the size of the anim file */
fseek(infile, 0L, SEEK_END);
inputsize = ftell(infile);
rewind(infile);
/* read the anim file header */
if(fread(&lpheader,sizeof(lpfileheader),1,infile) == NULL)
{
printf("Error reading file header!\n");
return EXIT_FAILURE;
}
fseek(infile, 128L, SEEK_CUR); /* skip color cycling structures */
/* read in the color palette */
for(i=0; i<768; i+=3)
{
lppalette[i+2] = (UBYTE)((getc(infile) >> 2) & 63); /* read red */
lppalette[i+1] = (UBYTE)((getc(infile) >> 2) & 63); /* read green */
lppalette[i] = (UBYTE)((getc(infile) >> 2) & 63); /* read blue */
getc(infile); /* skip over the extra pad byte */
}
/* read in large page descriptors */
fread(LpArray,sizeof(lp_descriptor),256,infile);
/* the file pointer now points to the first large page structure */
oldvideomode = GetVideoMode(); /* save the current video mode */
SetVideoMode(0x13); /* set the video mode to 13h MCGA 256 color */
cls(0); /* clear the screen to black */
LoadPalette(256,0,lppalette); /* init the color palette */
InitMouse();
HideMouse();
drawframe(0); /* draw the first frame of the file */
ShowMouse();
mousebutton=0;
/*
Remember, the last frame in the file is a delta back to the first frame.
You should only draw the first frame once and then use the last frame to
redraw the first frame.
*/
while(!(mousebutton&1))
{
for(framecount = 1; framecount < (UWORD)lpheader.nRecords; framecount++)
{
ReadMouse(&mousebutton, &mousex, &mousey);
while(!(mousebutton&3))
ReadMouse(&mousebutton, &mousex, &mousey);
if(mousebutton&1)
break;
HideMouse();
drawframe(framecount);
ShowMouse();
}
}
HideMouse();
SetVideoMode(oldvideomode);
fclose(infile);
hfree(thepage);
return EXIT_SUCCESS;
}
+69
View File
@@ -0,0 +1,69 @@
/* structure declarations for deluxe animate large page files */
typedef struct {
ULONG id; /* 4 character ID == "LPF " */
UWORD maxLps; /* max # largePages allowed. 256 FOR NOW. */
UWORD nLps; /* # largePages in this file. */
ULONG nRecords; /* # records in this file. 65534 is current limit plus */
/* one for last-to-first delta for looping the animation */
UWORD maxRecsPerLp; /* # records permitted in an lp. 256 FOR NOW. */
UWORD lpfTableOffset; /* Absolute Seek position of lpfTable. 1280 FOR NOW.
The lpf Table is an array of 256 large page structures
that is used to facilitate finding records in an anim
file without having to seek through all of the Large
Pages to find which one a specific record lives in. */
ULONG contentType; /* 4 character ID == "ANIM" */
UWORD width; /* Width of screen in pixels. */
UWORD height; /* Height of screen in pixels. */
UBYTE variant; /* 0==ANIM. */
UBYTE version; /* 0==frame rate is multiple of 18 cycles/sec.
1==frame rate is multiple of 70 cycles/sec. */
UBYTE hasLastDelta; /* 1==Last record is a delta from last-to-first frame. */
UBYTE lastDeltaValid; /* 0==The last-to-first delta (if present) hasn't been
updated to match the current first&last frames, so it
should be ignored. */
UBYTE pixelType; /* 0==256 color. */
UBYTE CompressionType; /* 1==(RunSkipDump) Only one used FOR NOW. */
UBYTE otherRecsPerFrm; /* 0 FOR NOW. */
UBYTE bitmaptype; /* 1==320x200, 256-color. Only one implemented so far. */
UBYTE recordTypes[32]; /* Not yet implemented. */
ULONG nFrames; /* In case future version adds other records at end of
file, we still know how many actual frames.
NOTE: DOES include last-to-first delta when present. */
UWORD framesPerSecond; /* Number of frames to play per second. */
UWORD pad2[29]; /* 58 bytes of filler to round up to 128 bytes total. */
} lpfileheader;
/* this is the format of an large page structure */
typedef struct {
UWORD baseRecord; /* Number of first record in this large page. */
UWORD nRecords; /* Number of records in lp.
bit 15 of "nRecords" == "has continuation from previous lp".
bit 14 of "nRecords" == "final record continues on next lp". */
UWORD nBytes; /* Total number of bytes of contents, excluding header. */
} lp_descriptor;