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:
@@ -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;
|
||||
@@ -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
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user