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,38 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include "compiler.h"
|
||||||
|
|
||||||
|
main (argc, argv)
|
||||||
|
int argc;
|
||||||
|
char *argv[];
|
||||||
|
{
|
||||||
|
FILE *infp, *outfp;
|
||||||
|
COUNT bytes_read;
|
||||||
|
DWORD filelen;
|
||||||
|
static char buf[512];
|
||||||
|
|
||||||
|
outfp = fopen (argv[1], "wb");
|
||||||
|
|
||||||
|
infp = fopen (argv[2], BUFFERED_BINREAD);
|
||||||
|
ffilelength (infp, &filelen);
|
||||||
|
while (filelen)
|
||||||
|
{
|
||||||
|
bytes_read = filelen >= sizeof (buf) ?
|
||||||
|
sizeof (buf) : (COUNT)filelen;
|
||||||
|
fwrite (buf, 1, fread (buf, 1, bytes_read, infp), outfp);
|
||||||
|
filelen -= bytes_read;
|
||||||
|
}
|
||||||
|
fclose (infp);
|
||||||
|
|
||||||
|
infp = fopen (argv[3], BUFFERED_BINREAD);
|
||||||
|
ffilelength (infp, &filelen);
|
||||||
|
while (filelen)
|
||||||
|
{
|
||||||
|
bytes_read = filelen >= sizeof (buf) ?
|
||||||
|
sizeof (buf) : (COUNT)filelen;
|
||||||
|
fwrite (buf, 1, fread (buf, 1, bytes_read, infp), outfp);
|
||||||
|
filelen -= bytes_read;
|
||||||
|
}
|
||||||
|
fclose (infp);
|
||||||
|
|
||||||
|
fclose (outfp);
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
LIB_LIST = \
|
||||||
|
\src\libs\video\watcom\video.lib \
|
||||||
|
\src\libs\graphics\watcom\graphics.lib \
|
||||||
|
\src\libs\memory\watcom\memory.lib \
|
||||||
|
\src\libs\resource\watcom\resource.lib \
|
||||||
|
\src\libs\input\watcom\input.lib \
|
||||||
|
\src\libs\sound\watcom\sound.lib \
|
||||||
|
\src\libs\decomp\watcom\decomp.lib \
|
||||||
|
\src\libs\strings\watcom\strings.lib \
|
||||||
|
\src\libs\task\watcom\task.lib \
|
||||||
|
\src\libs\math\watcom\math.lib
|
||||||
|
|
||||||
|
FLAGS = $(CFLAGS) -DPACKAGING -I\src\libs\resource
|
||||||
|
|
||||||
|
ndx.exe pkg.exe unpkg.exe: $(@R).obj $(LIB_LIST)
|
||||||
|
@echo "Loading $@ ... "
|
||||||
|
@$(LINKER) @$(@R).lnk
|
||||||
|
@4gwbind 4gwpro t.exe $@ -V
|
||||||
|
@echo "done"
|
||||||
|
|
||||||
|
ndx.obj pkg.obj unpkg.obj: $(@R).c
|
||||||
|
$(CC) $(FLAGS) $?
|
||||||
|
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
MODEL = M
|
||||||
|
INC1 = ..
|
||||||
|
INC2 = ..\resource
|
||||||
|
#DFLAGS = /Ox /Gc /Gr
|
||||||
|
DFLAGS = /Zi /Od /Gs /Gc /Gr
|
||||||
|
CFLAGS = $(DFLAGS) -DPACKAGING /W4 /A$(MODEL) /NT RESSEG -I$(INC1) -I$(INC2)
|
||||||
|
DEST = \bin
|
||||||
|
EXTHDRS =
|
||||||
|
FFLAGS =
|
||||||
|
HDRS =
|
||||||
|
LDFLAGS = /ST:8192 /CO /NOE
|
||||||
|
LDMAP = $(@R)
|
||||||
|
LIBS = \
|
||||||
|
..\task\task.lib \
|
||||||
|
..\sound\sound.lib \
|
||||||
|
..\input\input.lib \
|
||||||
|
..\resource\resource.lib \
|
||||||
|
..\error\error.lib \
|
||||||
|
..\memory\memory.lib
|
||||||
|
LINKER = link
|
||||||
|
MAKEFILE = Makefile
|
||||||
|
INDEX_OBJS = ndx.obj
|
||||||
|
PACKAGE_OBJS = init.obj getres.obj
|
||||||
|
RES_OBJS = $(INC2)\init.obj $(INC2)\getres.obj
|
||||||
|
SPLIT_OBJS = split.obj combine.obj
|
||||||
|
COMBINE_OBJS = combine.o
|
||||||
|
PRINT = print
|
||||||
|
PROGRAMS = unpkg.exe ndx.exe pkg.exe
|
||||||
|
SETARGV = \lib\${MODEL}setargv
|
||||||
|
INDEX_SRCS = ndx.c
|
||||||
|
PACKAGE_SRCS = pkg.c
|
||||||
|
|
||||||
|
all: $(PROGRAMS)
|
||||||
|
|
||||||
|
ndx.exe: $(INDEX_OBJS) $(LIBS)
|
||||||
|
@echo "Loading $@ ... "
|
||||||
|
@$(LINKER) $(INDEX_OBJS), $@, $(LDMAP), $(LIBS) $(LDFLAGS);
|
||||||
|
@echo "done"
|
||||||
|
|
||||||
|
pkg.exe: $(@R).obj $(PACKAGE_OBJS) $(LIBS)
|
||||||
|
@echo "Loading $@ ... "
|
||||||
|
@$(LINKER) $(@R).obj $(PACKAGE_OBJS), $@, $(LDMAP), $(LIBS) $(LDFLAGS);
|
||||||
|
@echo "done"
|
||||||
|
|
||||||
|
unpkg.exe: $(@R).obj $(RES_OBJS) $(LIBS)
|
||||||
|
@echo "Loading $@ ... "
|
||||||
|
@$(LINKER) $(@R).obj $(RES_OBJS), $@, $(LDMAP), $(LIBS) $(LDFLAGS);
|
||||||
|
@echo "done"
|
||||||
|
|
||||||
|
split.exe combine.exe: $(@:.exe=.obj)
|
||||||
|
@echo "Loading $@ ... "
|
||||||
|
@$(LINKER) $(@:.exe=.obj), $@, $(LDMAP), $(LDFLAGS);
|
||||||
|
@echo "done"
|
||||||
|
|
||||||
|
combine: $(COMBINE_OBJS)
|
||||||
|
@echo "Loading $@ ... "
|
||||||
|
@blink /lc/lib/c.o,$(COMBINE_OBJS) TO $(@) LIB /lc/lib/lc.lib
|
||||||
|
@echo "done"
|
||||||
|
|
||||||
|
backup:
|
||||||
|
(md b:index; ct [*.c,*.h,makefile] b:index)
|
||||||
|
|
||||||
|
init.obj getres.obj: ../resource/$(@:.obj=.c)
|
||||||
|
$(CC) $(CFLAGS) -c $?
|
||||||
|
|
||||||
|
.BEFORE:
|
||||||
|
.AFTER:
|
||||||
|
|
||||||
|
combine.o: combine.c
|
||||||
|
lc -i/src/libs combine.c
|
||||||
@@ -0,0 +1,926 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "reslib.h"
|
||||||
|
#include "resource/index.h"
|
||||||
|
|
||||||
|
INDEX_HEADER index_header;
|
||||||
|
TYPE_DESC type_list[MAX_TYPES];
|
||||||
|
char workbuf[8192];
|
||||||
|
|
||||||
|
typedef union
|
||||||
|
{
|
||||||
|
UWORD data_len;
|
||||||
|
UWORD filename_index;
|
||||||
|
} INSTANCE_INFO;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
BOC_TOKEN,
|
||||||
|
EOC_TOKEN,
|
||||||
|
EOL_TOKEN,
|
||||||
|
STRING_TOKEN
|
||||||
|
} TOKEN_TYPE;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
RESTART_STATE,
|
||||||
|
COMMENT_STATE,
|
||||||
|
ERROR_STATE,
|
||||||
|
|
||||||
|
TYPE_CONTROL_STATE,
|
||||||
|
PATH_STATE,
|
||||||
|
PACKAGE_PATH_STATE,
|
||||||
|
PACKAGE_STATE,
|
||||||
|
INCLUDE_STATE,
|
||||||
|
|
||||||
|
RESOURCE_STATE
|
||||||
|
} LINE_STATE;
|
||||||
|
#define FIRST_KEYWORD TYPE_CONTROL_STATE
|
||||||
|
#define FIRST_TYPE RESOURCE_STATE
|
||||||
|
|
||||||
|
static char *keyword_tab[] =
|
||||||
|
{
|
||||||
|
"TYPE",
|
||||||
|
"PATH",
|
||||||
|
"PACKAGE_PATH",
|
||||||
|
"PACKAGE",
|
||||||
|
"INCLUDE",
|
||||||
|
};
|
||||||
|
#define NUM_KEYWORDS (sizeof (keyword_tab) / sizeof (keyword_tab[0]))
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
TOKEN_TYPE type;
|
||||||
|
char string[256];
|
||||||
|
} TOKEN;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
COUNT string_count, index;
|
||||||
|
MEM_HANDLE hBuf;
|
||||||
|
} STRING_TAB;
|
||||||
|
|
||||||
|
static char type_names[MAX_TYPES][20];
|
||||||
|
static STRING_TAB type_string_tab[MAX_TYPES], package_string_tab;
|
||||||
|
static STRING_TAB instance_file_string_tab, instance_path_string_tab;
|
||||||
|
static STRING_TAB package_file_string_tab, package_path_string_tab;
|
||||||
|
static COUNT last_instance_path_index = (COUNT)~0,
|
||||||
|
last_package_path_index = (COUNT)~0;
|
||||||
|
|
||||||
|
PROC(STATIC
|
||||||
|
TOKEN_TYPE near get_token, (line_buf, ptoken, state),
|
||||||
|
ARG (char **line_buf)
|
||||||
|
ARG (TOKEN *ptoken)
|
||||||
|
ARG_END (LINE_STATE state)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
char ch, last_ch, *str;
|
||||||
|
|
||||||
|
ptoken->type = EOL_TOKEN;
|
||||||
|
EatChars:
|
||||||
|
last_ch = '\0';
|
||||||
|
while ((ch = *(*line_buf)++) == '\0' ||
|
||||||
|
ch == ' ' || isspace (ch) || state == COMMENT_STATE ||
|
||||||
|
ptoken->type == BOC_TOKEN)
|
||||||
|
{
|
||||||
|
if (ch == '\0' || ch == '\n')
|
||||||
|
return (ptoken->type);
|
||||||
|
else if (ch == '/' && last_ch == '*')
|
||||||
|
{
|
||||||
|
if (state == COMMENT_STATE)
|
||||||
|
return (ptoken->type = EOC_TOKEN);
|
||||||
|
else if (ptoken->type != BOC_TOKEN)
|
||||||
|
return (ERROR_STATE);
|
||||||
|
else
|
||||||
|
ptoken->type = EOL_TOKEN;
|
||||||
|
}
|
||||||
|
last_ch = ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
str = ptoken->string;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if ((*str++ = ch) == '*' && last_ch == '/')
|
||||||
|
{
|
||||||
|
if ((str -= 2) == ptoken->string)
|
||||||
|
{
|
||||||
|
ptoken->type = BOC_TOKEN;
|
||||||
|
|
||||||
|
goto EatChars;
|
||||||
|
}
|
||||||
|
--*line_buf;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
last_ch = ch;
|
||||||
|
} while ((ch = *(*line_buf)++) != '\0' && ch != ' ' && !isspace (ch));
|
||||||
|
*str++ = '\0';
|
||||||
|
|
||||||
|
--*line_buf;
|
||||||
|
|
||||||
|
return (ptoken->type = STRING_TOKEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
PROC(STATIC
|
||||||
|
LINE_STATE near GetKeywordState, (ptoken),
|
||||||
|
ARG_END (TOKEN *ptoken)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
strupr (ptoken->string);
|
||||||
|
|
||||||
|
for (i = 0; i < NUM_KEYWORDS; ++i)
|
||||||
|
{
|
||||||
|
if (!strcmp (keyword_tab[i], ptoken->string))
|
||||||
|
return (FIRST_KEYWORD + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = index_header.num_types - 1; i >= 0; --i)
|
||||||
|
{
|
||||||
|
if (!strcmp (type_names[i], ptoken->string))
|
||||||
|
return (FIRST_TYPE + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (ERROR_STATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define TAB_SIZE (64*1024)
|
||||||
|
#define AllocStringTab() mem_request (TAB_SIZE)
|
||||||
|
#define LockStringTab(h) (LPSTR)mem_lock (h)
|
||||||
|
#define UnlockStringTab(h) mem_unlock (h)
|
||||||
|
|
||||||
|
PROC(STATIC
|
||||||
|
COUNT near add_string, (buf, pstring_tab, length),
|
||||||
|
ARG (char *buf)
|
||||||
|
ARG (STRING_TAB *pstring_tab)
|
||||||
|
ARG_END (int length)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (length > 0)
|
||||||
|
{
|
||||||
|
LPSTR lpStr;
|
||||||
|
|
||||||
|
if (pstring_tab->hBuf == NULL_HANDLE)
|
||||||
|
pstring_tab->hBuf = AllocStringTab ();
|
||||||
|
|
||||||
|
lpStr = LockStringTab (pstring_tab->hBuf);
|
||||||
|
lpStr += pstring_tab->index;
|
||||||
|
pstring_tab->index += length;
|
||||||
|
do
|
||||||
|
*lpStr++ = *buf++;
|
||||||
|
while (--length);
|
||||||
|
UnlockStringTab (pstring_tab->hBuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (pstring_tab->index);
|
||||||
|
}
|
||||||
|
|
||||||
|
PROC(STATIC
|
||||||
|
COUNT near get_string, (buf, pstring_tab, index, length),
|
||||||
|
ARG (char *buf)
|
||||||
|
ARG (STRING_TAB *pstring_tab)
|
||||||
|
ARG (COUNT index)
|
||||||
|
ARG_END (int length)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
LPSTR lpStr;
|
||||||
|
|
||||||
|
if (index >= pstring_tab->index)
|
||||||
|
{
|
||||||
|
*buf = '\0';
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
lpStr = LockStringTab (pstring_tab->hBuf);
|
||||||
|
lpStr += index;
|
||||||
|
|
||||||
|
if (length == -1)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
++index;
|
||||||
|
while (*buf++ = *lpStr++);
|
||||||
|
}
|
||||||
|
else if (length > 0)
|
||||||
|
{
|
||||||
|
index += length;
|
||||||
|
do
|
||||||
|
*buf++ = *lpStr++;
|
||||||
|
while (--length);
|
||||||
|
}
|
||||||
|
|
||||||
|
UnlockStringTab (pstring_tab->hBuf);
|
||||||
|
|
||||||
|
return (index);
|
||||||
|
}
|
||||||
|
|
||||||
|
PROC(STATIC
|
||||||
|
COUNT near find_string, (ppath_index, string, pstring_tab),
|
||||||
|
ARG (PCOUNT ppath_index)
|
||||||
|
ARG (char *string)
|
||||||
|
ARG_END (STRING_TAB *pstring_tab)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
COUNT i, string_index;
|
||||||
|
|
||||||
|
for (i = string_index = 0; i < pstring_tab->string_count; ++i)
|
||||||
|
{
|
||||||
|
COUNT pi;
|
||||||
|
BYTE buf[128];
|
||||||
|
|
||||||
|
if (ppath_index == 0)
|
||||||
|
{
|
||||||
|
pi = string_index;
|
||||||
|
string_index = get_string (buf,
|
||||||
|
pstring_tab, string_index, -1);
|
||||||
|
if (!strcmp (buf, string))
|
||||||
|
return (pi);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string_index = get_string ((char *)&pi,
|
||||||
|
pstring_tab, string_index, sizeof (pi));
|
||||||
|
string_index = get_string (buf,
|
||||||
|
pstring_tab, string_index, -1);
|
||||||
|
if (pi == *ppath_index && !strcmp (buf, string))
|
||||||
|
return (i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ppath_index == 0)
|
||||||
|
{
|
||||||
|
++pstring_tab->string_count;
|
||||||
|
add_string (string,
|
||||||
|
pstring_tab,
|
||||||
|
strlen (string) + 1);
|
||||||
|
return (string_index);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
add_string ((char *)ppath_index,
|
||||||
|
pstring_tab,
|
||||||
|
sizeof (*ppath_index));
|
||||||
|
add_string (string,
|
||||||
|
pstring_tab,
|
||||||
|
strlen (string) + 1);
|
||||||
|
|
||||||
|
return (pstring_tab->string_count++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MAX_NUM_FILES 20
|
||||||
|
static COUNT top_file_stack;
|
||||||
|
static FILE *file_stack[MAX_NUM_FILES];
|
||||||
|
|
||||||
|
PROC(STATIC
|
||||||
|
FILE * near pop_file, (),
|
||||||
|
ARG_VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (top_file_stack == 0)
|
||||||
|
return ((FILE *)NULL);
|
||||||
|
else
|
||||||
|
return (file_stack[--top_file_stack]);
|
||||||
|
}
|
||||||
|
|
||||||
|
PROC(STATIC
|
||||||
|
BOOLEAN near push_file, (fp),
|
||||||
|
ARG_END (FILE *fp)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (top_file_stack == MAX_NUM_FILES)
|
||||||
|
return (FALSE);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
file_stack[top_file_stack++] = fp;
|
||||||
|
return (TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PROC(STATIC
|
||||||
|
void near create_headers, (),
|
||||||
|
ARG_VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
COUNT i, file_index;
|
||||||
|
FILE *fp, *inst_fp;
|
||||||
|
|
||||||
|
fp = fopen ("restypes.h", "w");
|
||||||
|
fprintf (fp, "#ifndef _RESTYPES_H\n");
|
||||||
|
fprintf (fp, "#define _RESTYPES_H\n\n");
|
||||||
|
|
||||||
|
fprintf (fp, "enum\n{\n");
|
||||||
|
for (i = 0; i < index_header.num_types; ++i)
|
||||||
|
{
|
||||||
|
if (i == 0)
|
||||||
|
fprintf (fp, " %s = 1", type_names[i]);
|
||||||
|
else
|
||||||
|
fprintf (fp, " %s", type_names[i]);
|
||||||
|
if (i < index_header.num_types - 1)
|
||||||
|
fprintf (fp, ",");
|
||||||
|
fprintf (fp, "\n");
|
||||||
|
}
|
||||||
|
fprintf (fp, "};\n\n");
|
||||||
|
fprintf (fp, "#endif /* _RESTYPES_H */\n\n");
|
||||||
|
fclose (fp);
|
||||||
|
|
||||||
|
fp = fopen ("respkg.h", "w");
|
||||||
|
|
||||||
|
fprintf (fp, "enum\n{\n");
|
||||||
|
for (i = 0, file_index = 0; i < index_header.num_packages; ++i)
|
||||||
|
{
|
||||||
|
COUNT index;
|
||||||
|
|
||||||
|
file_index = get_string ((char *)&index,
|
||||||
|
&package_string_tab,
|
||||||
|
file_index, sizeof (index));
|
||||||
|
file_index = get_string (workbuf,
|
||||||
|
&package_string_tab, file_index, -1);
|
||||||
|
|
||||||
|
if (i == 0)
|
||||||
|
fprintf (fp, " %s = 1", workbuf);
|
||||||
|
else
|
||||||
|
fprintf (fp, " %s", workbuf);
|
||||||
|
if (i < index_header.num_packages - 1)
|
||||||
|
fprintf (fp, ",");
|
||||||
|
fprintf (fp, "\n");
|
||||||
|
}
|
||||||
|
fprintf (fp, "};\n\n");
|
||||||
|
fclose (fp);
|
||||||
|
|
||||||
|
inst_fp = fopen ("resinst.h", "w");
|
||||||
|
|
||||||
|
for (i = 0; i < index_header.num_types; ++i)
|
||||||
|
{
|
||||||
|
if (type_list[i].instance_count > 0)
|
||||||
|
{
|
||||||
|
COUNT j, type_index;
|
||||||
|
|
||||||
|
sprintf (workbuf, "i%.7s.h", type_names[i]);
|
||||||
|
strlwr (workbuf);
|
||||||
|
fprintf (inst_fp, "#include \"%s\"\n", workbuf);
|
||||||
|
|
||||||
|
fp = fopen (workbuf, "w");
|
||||||
|
|
||||||
|
for (j = 0, type_index = 0; j < type_list[i].instance_count; ++j)
|
||||||
|
{
|
||||||
|
RES_PACKAGE pack_id;
|
||||||
|
COUNT file_index;
|
||||||
|
|
||||||
|
type_index = get_string ((char *)&pack_id,
|
||||||
|
&type_string_tab[i], type_index, sizeof (pack_id));
|
||||||
|
type_index = get_string ((char *)&file_index,
|
||||||
|
&type_string_tab[i], type_index, sizeof (file_index));
|
||||||
|
type_index = get_string (workbuf,
|
||||||
|
&type_string_tab[i], type_index, -1);
|
||||||
|
fprintf (fp, "#define %s\t0x%08lxL\n",
|
||||||
|
workbuf, MAKE_RESOURCE (pack_id, i + 1, j));
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef OLD
|
||||||
|
fprintf (fp, "\ntypedef RESOURCE %s_INSTANCE;\n\n", type_names[i]);
|
||||||
|
#else /* !OLD */
|
||||||
|
fprintf (fp, "\n\n");
|
||||||
|
#endif /* OLD */
|
||||||
|
fclose (fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose (inst_fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
PROC(STATIC
|
||||||
|
void near create_index_file, (file_out),
|
||||||
|
ARG_END (char *file_out)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
COUNT i;
|
||||||
|
FILE *fp;
|
||||||
|
DWORD package_path_list_offs, package_file_list_offs;
|
||||||
|
|
||||||
|
fp = fopen (file_out, "wb");
|
||||||
|
fseek (fp, (long)sizeof (index_header) - 6, SEEK_SET);
|
||||||
|
|
||||||
|
printf ("Writing out package descriptions\n");
|
||||||
|
{
|
||||||
|
COUNT file_index;
|
||||||
|
PACKAGE_DESC package;
|
||||||
|
|
||||||
|
package.flags_and_data_loc = 0xFF000000L;
|
||||||
|
for (i = 0, file_index = 0; i < index_header.num_packages; ++i)
|
||||||
|
{
|
||||||
|
COUNT j, index, num_types, num_instances;
|
||||||
|
|
||||||
|
num_types = num_instances = 0;
|
||||||
|
for (j = 0; j < index_header.num_types; ++j)
|
||||||
|
{
|
||||||
|
COUNT instance_index[MAX_TYPES];
|
||||||
|
RES_PACKAGE pack_id;
|
||||||
|
|
||||||
|
if (i == 0)
|
||||||
|
instance_index[j] = 0;
|
||||||
|
|
||||||
|
index = get_string ((char *)&pack_id,
|
||||||
|
&type_string_tab[j],
|
||||||
|
instance_index[j], sizeof (pack_id));
|
||||||
|
if (index > 0 && pack_id == (RES_PACKAGE)(i + 1))
|
||||||
|
{
|
||||||
|
++num_types;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
INSTANCE_INFO info;
|
||||||
|
|
||||||
|
++num_instances;
|
||||||
|
instance_index[j] = index;
|
||||||
|
instance_index[j] = get_string ((char *)&info.filename_index,
|
||||||
|
&type_string_tab[j],
|
||||||
|
instance_index[j], sizeof (info.filename_index));
|
||||||
|
instance_index[j] = get_string (workbuf,
|
||||||
|
&type_string_tab[j], instance_index[j], -1);
|
||||||
|
|
||||||
|
index = get_string ((char *)&pack_id,
|
||||||
|
&type_string_tab[j],
|
||||||
|
instance_index[j], sizeof (pack_id));
|
||||||
|
} while (index > 0 && pack_id == (RES_PACKAGE)(i + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
file_index = get_string ((char *)&index,
|
||||||
|
&package_string_tab,
|
||||||
|
file_index, sizeof (index));
|
||||||
|
file_index = get_string (workbuf,
|
||||||
|
&package_string_tab, file_index, -1);
|
||||||
|
printf ("\t%u total types, %u total instances in package %u -- <0x%lx>\n", num_types, num_instances, i + 1, package.flags_and_data_loc);
|
||||||
|
package.packmem_info = MAKE_RESOURCE (index, num_types, num_instances);
|
||||||
|
fwrite (&package, sizeof (PACKAGE_DESC), 1, fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf ("Writing out instance counts for %d types\n", index_header.num_types);
|
||||||
|
{
|
||||||
|
for (i = 0; i < index_header.num_types; ++i)
|
||||||
|
fwrite (&type_list[i].instance_count,
|
||||||
|
sizeof (type_list[i].instance_count), 1, fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
index_header.packmem_list_offs = (DWORD)ftell (fp);
|
||||||
|
|
||||||
|
printf ("Writing out package member list\n");
|
||||||
|
{ /* write out resource list */
|
||||||
|
for (i = 0; i < index_header.num_packages; ++i)
|
||||||
|
{
|
||||||
|
COUNT index, instance_index[MAX_TYPES];
|
||||||
|
RES_INSTANCE first_instance[MAX_TYPES];
|
||||||
|
RES_PACKAGE pack_id;
|
||||||
|
COUNT j;
|
||||||
|
|
||||||
|
printf ("PACKAGE %u\n", i + 1);
|
||||||
|
for (j = 0; j < index_header.num_types; ++j)
|
||||||
|
{
|
||||||
|
DWORD encoding;
|
||||||
|
|
||||||
|
if (i == 0)
|
||||||
|
{
|
||||||
|
instance_index[j] = 0;
|
||||||
|
first_instance[j] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
index = get_string ((char *)&pack_id,
|
||||||
|
&type_string_tab[j],
|
||||||
|
instance_index[j], sizeof (pack_id));
|
||||||
|
if (index > 0 && pack_id == (RES_PACKAGE)(i + 1))
|
||||||
|
{
|
||||||
|
COUNT instance_count;
|
||||||
|
|
||||||
|
instance_count = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
INSTANCE_INFO info;
|
||||||
|
|
||||||
|
++instance_count;
|
||||||
|
index = get_string ((char *)&info.filename_index,
|
||||||
|
&type_string_tab[j],
|
||||||
|
index, sizeof (info.filename_index));
|
||||||
|
index = get_string (workbuf,
|
||||||
|
&type_string_tab[j], index, -1);
|
||||||
|
|
||||||
|
index = get_string ((char *)&pack_id,
|
||||||
|
&type_string_tab[j],
|
||||||
|
index, sizeof (pack_id));
|
||||||
|
} while (index > 0 && pack_id == (RES_PACKAGE)(i + 1));
|
||||||
|
|
||||||
|
encoding = MAKE_RESOURCE (instance_count,
|
||||||
|
j + 1, first_instance[j]);
|
||||||
|
printf ("\ttype = %u, first_instance = %u, num_instances = %u\n", j + 1, first_instance[j], instance_count);
|
||||||
|
first_instance[j] += instance_count;
|
||||||
|
fwrite (&encoding, sizeof (DWORD), 1, fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf ("\n");
|
||||||
|
for (j = 0; j < index_header.num_types; ++j)
|
||||||
|
{
|
||||||
|
index = get_string ((char *)&pack_id,
|
||||||
|
&type_string_tab[j],
|
||||||
|
instance_index[j], sizeof (pack_id));
|
||||||
|
if (index > 0 && pack_id == (RES_PACKAGE)(i + 1))
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
INSTANCE_INFO info;
|
||||||
|
|
||||||
|
instance_index[j] = index;
|
||||||
|
instance_index[j] = get_string ((char *)&info.filename_index,
|
||||||
|
&type_string_tab[j],
|
||||||
|
instance_index[j], sizeof (info.filename_index));
|
||||||
|
instance_index[j] = get_string (workbuf,
|
||||||
|
&type_string_tab[j], instance_index[j], -1);
|
||||||
|
|
||||||
|
printf ("\tfilename = '%s'(%d)\n", workbuf, info.filename_index);
|
||||||
|
fwrite (&info, INSTANCE_LIST_SIZE, 1, fp);
|
||||||
|
index = get_string ((char *)&pack_id,
|
||||||
|
&type_string_tab[j],
|
||||||
|
instance_index[j], sizeof (pack_id));
|
||||||
|
} while (index > 0 && pack_id == (RES_PACKAGE)(i + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
package_path_list_offs = (DWORD)ftell (fp);
|
||||||
|
|
||||||
|
printf ("Writing out package path list\n");
|
||||||
|
{
|
||||||
|
/* write out path list */
|
||||||
|
COUNT path_index;
|
||||||
|
|
||||||
|
for (i = path_index = 0; i < package_path_string_tab.string_count; ++i)
|
||||||
|
{
|
||||||
|
COUNT old_path_index;
|
||||||
|
BYTE buf[256];
|
||||||
|
|
||||||
|
old_path_index = path_index;
|
||||||
|
path_index = get_string (buf,
|
||||||
|
&package_path_string_tab, path_index, -1);
|
||||||
|
fwrite (buf, path_index - old_path_index, 1, fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
package_file_list_offs = (DWORD)ftell (fp);
|
||||||
|
|
||||||
|
printf ("Writing out package file list\n");
|
||||||
|
{ /* write out file list */
|
||||||
|
COUNT file_index;
|
||||||
|
BYTE buf[FILE_LIST_SIZE + 2]; /* account for '.' and
|
||||||
|
* null char in filename
|
||||||
|
*/
|
||||||
|
COUNT *ppath_offs = (COUNT *)&buf[0];
|
||||||
|
BYTE *pfilename = &buf[sizeof (*ppath_offs)];
|
||||||
|
BYTE *pext = &buf[sizeof (*ppath_offs) + FILE_NAME_SIZE];
|
||||||
|
|
||||||
|
for (i = file_index = 0; i < package_file_string_tab.string_count; ++i)
|
||||||
|
{
|
||||||
|
BYTE *pstr1, *pstr2;
|
||||||
|
|
||||||
|
file_index = get_string ((char *)ppath_offs,
|
||||||
|
&package_file_string_tab, file_index, sizeof (*ppath_offs));
|
||||||
|
file_index = get_string (pfilename,
|
||||||
|
&package_file_string_tab, file_index, -1);
|
||||||
|
printf ("\t'%s'\n", pfilename);
|
||||||
|
pstr1 = pfilename;
|
||||||
|
while (*pstr1 != '.')
|
||||||
|
++pstr1;
|
||||||
|
pstr2 = pext;
|
||||||
|
|
||||||
|
if (pstr1 == pstr2)
|
||||||
|
{
|
||||||
|
while (*pstr2++ = *++pstr1)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
COUNT j;
|
||||||
|
|
||||||
|
*pstr1++ = '\0';
|
||||||
|
|
||||||
|
pstr1 += EXTENSION_SIZE - 1;
|
||||||
|
pstr2 += EXTENSION_SIZE - 1;
|
||||||
|
for (j = 0; j < EXTENSION_SIZE; ++j)
|
||||||
|
*pstr2-- = *pstr1--;
|
||||||
|
}
|
||||||
|
|
||||||
|
fwrite (buf, FILE_LIST_SIZE, 1, fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
index_header.path_list_offs = (DWORD)ftell (fp);
|
||||||
|
|
||||||
|
printf ("Writing out instance path list\n");
|
||||||
|
{
|
||||||
|
/* write out path list */
|
||||||
|
COUNT path_index;
|
||||||
|
|
||||||
|
for (i = path_index = 0; i < instance_path_string_tab.string_count; ++i)
|
||||||
|
{
|
||||||
|
COUNT old_path_index;
|
||||||
|
BYTE buf[256];
|
||||||
|
|
||||||
|
old_path_index = path_index;
|
||||||
|
path_index = get_string (buf,
|
||||||
|
&instance_path_string_tab, path_index, -1);
|
||||||
|
fwrite (buf, path_index - old_path_index, 1, fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fwrite (&package_path_list_offs, sizeof (package_path_list_offs), 1, fp);
|
||||||
|
|
||||||
|
index_header.file_list_offs = (DWORD)ftell (fp);
|
||||||
|
|
||||||
|
printf ("Writing out instance file list\n");
|
||||||
|
{ /* write out file list */
|
||||||
|
COUNT file_index;
|
||||||
|
BYTE buf[FILE_LIST_SIZE + 2]; /* account for '.' and
|
||||||
|
* null char in filename
|
||||||
|
*/
|
||||||
|
COUNT *ppath_offs = (COUNT *)&buf[0];
|
||||||
|
BYTE *pfilename = &buf[sizeof (*ppath_offs)];
|
||||||
|
BYTE *pext = &buf[sizeof (*ppath_offs) + FILE_NAME_SIZE];
|
||||||
|
|
||||||
|
for (i = file_index = 0; i < instance_file_string_tab.string_count; ++i)
|
||||||
|
{
|
||||||
|
BYTE *pstr1, *pstr2;
|
||||||
|
|
||||||
|
file_index = get_string ((char *)ppath_offs,
|
||||||
|
&instance_file_string_tab, file_index, sizeof (*ppath_offs));
|
||||||
|
file_index = get_string (pfilename,
|
||||||
|
&instance_file_string_tab, file_index, -1);
|
||||||
|
pstr1 = pfilename;
|
||||||
|
while (*pstr1 != '.')
|
||||||
|
++pstr1;
|
||||||
|
pstr2 = pext;
|
||||||
|
|
||||||
|
if (pstr1 == pstr2)
|
||||||
|
{
|
||||||
|
while (*pstr2++ = *++pstr1)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
COUNT j;
|
||||||
|
|
||||||
|
*pstr1++ = '\0';
|
||||||
|
|
||||||
|
pstr1 += EXTENSION_SIZE - 1;
|
||||||
|
pstr2 += EXTENSION_SIZE - 1;
|
||||||
|
for (j = 0; j < EXTENSION_SIZE; ++j)
|
||||||
|
*pstr2-- = *pstr1--;
|
||||||
|
}
|
||||||
|
|
||||||
|
fwrite (buf, FILE_LIST_SIZE, 1, fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fwrite (&package_file_list_offs, sizeof (package_file_list_offs), 1, fp);
|
||||||
|
|
||||||
|
fseek (fp, 0L, SEEK_SET);
|
||||||
|
fwrite ((char *)&index_header + 2, sizeof (index_header) - 6, 1, fp);
|
||||||
|
fclose (fp);
|
||||||
|
printf ("%d\n", sizeof (index_header) - 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
PROC(STATIC
|
||||||
|
BOOLEAN near parse_args, (argc, argv, infile, outfile),
|
||||||
|
ARG (int argc)
|
||||||
|
ARG (char *argv[])
|
||||||
|
ARG (char infile[])
|
||||||
|
ARG_END (char outfile[])
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (argc != 3)
|
||||||
|
return (FALSE);
|
||||||
|
|
||||||
|
strcpy (infile, argv[1]);
|
||||||
|
strcpy (outfile, argv[2]);
|
||||||
|
|
||||||
|
return (TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
PROC(STATIC
|
||||||
|
LINE_STATE near parse_line, (fp, line_buf, state),
|
||||||
|
ARG (FILE **fp)
|
||||||
|
ARG (char *line_buf)
|
||||||
|
ARG_END (LINE_STATE state)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
TOKEN_TYPE token_type;
|
||||||
|
TOKEN token;
|
||||||
|
|
||||||
|
while ((token_type = get_token (&line_buf, &token, state)) != EOL_TOKEN)
|
||||||
|
{
|
||||||
|
char loc_buf[128];
|
||||||
|
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case ERROR_STATE:
|
||||||
|
state = RESTART_STATE;
|
||||||
|
case RESTART_STATE:
|
||||||
|
if (token_type == BOC_TOKEN)
|
||||||
|
state = COMMENT_STATE;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (state = GetKeywordState (&token))
|
||||||
|
{
|
||||||
|
case ERROR_STATE:
|
||||||
|
return (ERROR_STATE);
|
||||||
|
case PATH_STATE:
|
||||||
|
if (get_token (&line_buf,
|
||||||
|
&token, state) == STRING_TOKEN)
|
||||||
|
{
|
||||||
|
if (strcmp (token.string, ".") == 0)
|
||||||
|
last_instance_path_index = (COUNT)~0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
last_instance_path_index = find_string (
|
||||||
|
0, token.string,
|
||||||
|
&instance_path_string_tab);
|
||||||
|
get_string (token.string, &instance_path_string_tab, last_instance_path_index, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf ("PATH\n\t'%s'\n", token.string);
|
||||||
|
state = RESTART_STATE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PACKAGE_PATH_STATE:
|
||||||
|
if (get_token (&line_buf,
|
||||||
|
&token, state) == STRING_TOKEN)
|
||||||
|
{
|
||||||
|
if (strcmp (token.string, ".") == 0)
|
||||||
|
last_package_path_index = (COUNT)~0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
last_package_path_index = find_string (
|
||||||
|
0, token.string,
|
||||||
|
&package_path_string_tab);
|
||||||
|
get_string (token.string, &package_path_string_tab, last_package_path_index, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf ("PACKAGE_PATH\n\t'%s'\n", token.string);
|
||||||
|
state = RESTART_STATE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PACKAGE_STATE:
|
||||||
|
if (get_token (&line_buf,
|
||||||
|
&token, state) == STRING_TOKEN)
|
||||||
|
{
|
||||||
|
strcpy (loc_buf, token.string);
|
||||||
|
|
||||||
|
if (get_token (&line_buf,
|
||||||
|
&token, state) == STRING_TOKEN)
|
||||||
|
{
|
||||||
|
COUNT which_string;
|
||||||
|
|
||||||
|
if (index_header.num_packages == MAX_PACKAGES)
|
||||||
|
return (ERROR_STATE);
|
||||||
|
++index_header.num_packages;
|
||||||
|
|
||||||
|
which_string = find_string (
|
||||||
|
&last_package_path_index,
|
||||||
|
token.string,
|
||||||
|
&package_file_string_tab);
|
||||||
|
|
||||||
|
++package_string_tab.string_count;
|
||||||
|
add_string ((char *)&which_string,
|
||||||
|
&package_string_tab,
|
||||||
|
sizeof (which_string));
|
||||||
|
add_string (loc_buf,
|
||||||
|
&package_string_tab,
|
||||||
|
strlen (loc_buf) + 1);
|
||||||
|
|
||||||
|
printf ("PACKAGE\n\t'%s'\n", loc_buf);
|
||||||
|
state = RESTART_STATE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case INCLUDE_STATE:
|
||||||
|
if (get_token (&line_buf,
|
||||||
|
&token, state) == STRING_TOKEN)
|
||||||
|
{
|
||||||
|
if (get_string (loc_buf,
|
||||||
|
&instance_path_string_tab, last_instance_path_index, -1))
|
||||||
|
strcat (loc_buf, "/");
|
||||||
|
strcat (loc_buf, token.string);
|
||||||
|
if (push_file (*fp) &&
|
||||||
|
(*fp = fopen (loc_buf, "r")) != NULL)
|
||||||
|
{
|
||||||
|
printf ("INCLUDE\n\t'%s'\n", loc_buf);
|
||||||
|
state = RESTART_STATE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TYPE_CONTROL_STATE:
|
||||||
|
if (get_token (&line_buf,
|
||||||
|
&token, state) == STRING_TOKEN)
|
||||||
|
{
|
||||||
|
if (GetKeywordState (&token) == ERROR_STATE &&
|
||||||
|
index_header.num_types < MAX_TYPES)
|
||||||
|
{
|
||||||
|
strcpy (type_names[index_header.num_types++],
|
||||||
|
token.string);
|
||||||
|
printf ("TYPE\n\t'%s'\n", token.string);
|
||||||
|
state = RESTART_STATE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
COUNT type;
|
||||||
|
|
||||||
|
type = (COUNT)(state - RESOURCE_STATE);
|
||||||
|
if (type_list[type].instance_count == MAX_INSTANCES)
|
||||||
|
return (ERROR_STATE);
|
||||||
|
++type_list[type].instance_count;
|
||||||
|
|
||||||
|
if (get_token (&line_buf,
|
||||||
|
&token, state) == STRING_TOKEN)
|
||||||
|
{
|
||||||
|
++type_string_tab[type].string_count;
|
||||||
|
add_string ((char *)&index_header.num_packages,
|
||||||
|
&type_string_tab[type],
|
||||||
|
sizeof (index_header.num_packages));
|
||||||
|
add_string ((char *)&instance_file_string_tab.string_count,
|
||||||
|
&type_string_tab[type],
|
||||||
|
sizeof (instance_file_string_tab.string_count));
|
||||||
|
add_string (token.string,
|
||||||
|
&type_string_tab[type],
|
||||||
|
strlen (token.string) + 1);
|
||||||
|
|
||||||
|
if (get_token (&line_buf,
|
||||||
|
&token, state) == STRING_TOKEN)
|
||||||
|
{
|
||||||
|
++instance_file_string_tab.string_count;
|
||||||
|
add_string ((char *)&last_instance_path_index,
|
||||||
|
&instance_file_string_tab,
|
||||||
|
sizeof (last_instance_path_index));
|
||||||
|
add_string (token.string,
|
||||||
|
&instance_file_string_tab,
|
||||||
|
strlen (token.string) + 1);
|
||||||
|
printf ("INSTANCE\n\t'%s'\n", token.string);
|
||||||
|
state = RESTART_STATE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case COMMENT_STATE:
|
||||||
|
if (token_type == EOC_TOKEN)
|
||||||
|
state = RESTART_STATE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (state <= COMMENT_STATE ? state : ERROR_STATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
PROC(
|
||||||
|
void CDECL main, (argc, argv),
|
||||||
|
ARG (int argc)
|
||||||
|
ARG_END (char *argv[])
|
||||||
|
)
|
||||||
|
{
|
||||||
|
char outfile[80];
|
||||||
|
FILE *fp;
|
||||||
|
LINE_STATE state;
|
||||||
|
|
||||||
|
mem_init ((MEM_SIZE)0, 0, NULL_PTR);
|
||||||
|
|
||||||
|
state = ERROR_STATE;
|
||||||
|
if (parse_args (argc, argv, workbuf, outfile) &&
|
||||||
|
(fp = fopen (workbuf, "r")) != NULL)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
while (fgets (workbuf, sizeof (workbuf) - 1, fp) != NULL &&
|
||||||
|
(state = parse_line (&fp, workbuf, state)) != ERROR_STATE)
|
||||||
|
;
|
||||||
|
fclose (fp);
|
||||||
|
} while (state != ERROR_STATE && (fp = pop_file ()) != NULL);
|
||||||
|
|
||||||
|
if (state != ERROR_STATE)
|
||||||
|
{
|
||||||
|
printf ("creating headers\n");
|
||||||
|
create_headers ();
|
||||||
|
printf ("creating index file\n");
|
||||||
|
create_index_file (outfile);
|
||||||
|
printf ("done\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mem_uninit ();
|
||||||
|
|
||||||
|
if (state != ERROR_STATE)
|
||||||
|
exit (0);
|
||||||
|
else
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
@@ -0,0 +1,267 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <io.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "resource/resintrn.h"
|
||||||
|
|
||||||
|
static FILE *package_fp;
|
||||||
|
static BOOLEAN sanity_check;
|
||||||
|
char workbuf[8192];
|
||||||
|
char file_buf[256];
|
||||||
|
static long package_offset;
|
||||||
|
|
||||||
|
PROC_GLOBAL(
|
||||||
|
MEM_HANDLE near load_package, (ResHeaderPtr, res_package),
|
||||||
|
ARG (INDEX_HEADERPTR ResHeaderPtr)
|
||||||
|
ARG_END (RES_PACKAGE res_package)
|
||||||
|
);
|
||||||
|
PROC_GLOBAL(
|
||||||
|
void near get_resource_filename, (ResHeaderPtr, pbuf, file_index),
|
||||||
|
ARG (INDEX_HEADERPTR ResHeaderPtr)
|
||||||
|
ARG (PSTR pbuf)
|
||||||
|
ARG_END (COUNT file_index)
|
||||||
|
);
|
||||||
|
PROC_GLOBAL(
|
||||||
|
DWORD near get_packmem_offs, (ResHeaderPtr, res_package),
|
||||||
|
ARG (INDEX_HEADERPTR ResHeaderPtr)
|
||||||
|
ARG_END (RES_PACKAGE res_package)
|
||||||
|
);
|
||||||
|
|
||||||
|
PROC(STATIC
|
||||||
|
void near copy_data, (in_fp, out_fp, length),
|
||||||
|
ARG (FILE *in_fp)
|
||||||
|
ARG (FILE *out_fp)
|
||||||
|
ARG_END (DWORD length)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
COUNT num_bytes;
|
||||||
|
|
||||||
|
num_bytes = length >= (DWORD)sizeof (workbuf) ?
|
||||||
|
sizeof (workbuf) : (COUNT)length;
|
||||||
|
fread (workbuf, num_bytes, 1, in_fp);
|
||||||
|
fwrite (workbuf, num_bytes, 1, out_fp);
|
||||||
|
length -= num_bytes;
|
||||||
|
} while (length);
|
||||||
|
}
|
||||||
|
|
||||||
|
PROC(STATIC
|
||||||
|
MEM_HANDLE write_resource, (in_fp, length),
|
||||||
|
ARG (FILE *in_fp)
|
||||||
|
ARG_END (DWORD length)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
length = (length + 3) & ~3L;
|
||||||
|
if (strcmp (workbuf, file_buf))
|
||||||
|
{
|
||||||
|
if (!sanity_check)
|
||||||
|
copy_data (in_fp, package_fp, length);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf ("FILE NAMES THE SAME -- COPY ABORTED!!!\n");
|
||||||
|
package_offset = 0L;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((MEM_HANDLE)(length >> 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
PROC(STATIC
|
||||||
|
BOOLEAN file_error, (pFileName),
|
||||||
|
ARG_END (PSTR pFileName)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
printf ("UNABLE TO FIND '%s'\n", pFileName);
|
||||||
|
if (!sanity_check)
|
||||||
|
exit (1);
|
||||||
|
|
||||||
|
return (TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
PROC(STATIC
|
||||||
|
BOOLEAN near parse_args, (argc, argv, infile, outfile),
|
||||||
|
ARG (int argc)
|
||||||
|
ARG (char *argv[])
|
||||||
|
ARG (char infile[])
|
||||||
|
ARG_END (char outfile[])
|
||||||
|
)
|
||||||
|
{
|
||||||
|
while (--argc > 0)
|
||||||
|
{
|
||||||
|
++argv;
|
||||||
|
if ((*argv)[0] == '-'
|
||||||
|
&& toupper ((*argv)[1]) == 'S')
|
||||||
|
sanity_check = TRUE;
|
||||||
|
else if (infile[0] == '\0')
|
||||||
|
strcpy (infile, *argv);
|
||||||
|
else if (outfile[0] == '\0')
|
||||||
|
strcpy (outfile, *argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (infile[0] != '\0' && outfile[0] != '\0');
|
||||||
|
}
|
||||||
|
|
||||||
|
PROC(
|
||||||
|
void CDECL main, (argc, argv),
|
||||||
|
ARG (int argc)
|
||||||
|
ARG_END (char *argv[])
|
||||||
|
)
|
||||||
|
{
|
||||||
|
char outfile[80];
|
||||||
|
|
||||||
|
mem_init ((MEM_SIZE)0, 0, NULL_PTR);
|
||||||
|
|
||||||
|
if (parse_args (argc, argv, workbuf, outfile))
|
||||||
|
{
|
||||||
|
long file_offs;
|
||||||
|
FILE *out_fp;
|
||||||
|
COUNT i, num_types;
|
||||||
|
DWORD old_path_list_offs, old_file_list_offs,
|
||||||
|
package_path_list_offs, package_file_list_offs,
|
||||||
|
header_len;
|
||||||
|
FILE *res_fp;
|
||||||
|
INDEX_HEADERPTR ResHeaderPtr;
|
||||||
|
MEM_HANDLE hList;
|
||||||
|
RES_HANDLE_LISTPTR ResourceHandleListPtr;
|
||||||
|
ENCODEPTR TypeEncodePtr;
|
||||||
|
DATAPTR DataPtr;
|
||||||
|
|
||||||
|
if (InitResourceSystem (workbuf, 0, file_error) == 0)
|
||||||
|
exit (1);
|
||||||
|
res_fp = fopen (workbuf, "rb");
|
||||||
|
|
||||||
|
ResHeaderPtr = _get_current_index_header ();
|
||||||
|
ResHeaderPtr->res_fp = res_fp;
|
||||||
|
old_path_list_offs = ResHeaderPtr->path_list_offs;
|
||||||
|
old_file_list_offs = ResHeaderPtr->file_list_offs;
|
||||||
|
|
||||||
|
/* subtract char index_file_name[36]; DWORD data_offs; MEM_HANDLE hPredHeader, hSuccHeader; */
|
||||||
|
header_len = old_path_list_offs;
|
||||||
|
printf ("INDEX HEADER SIZE: %lu -- (0x%04x)\n", header_len, res_fp);
|
||||||
|
|
||||||
|
if (!sanity_check)
|
||||||
|
{
|
||||||
|
out_fp = fopen (outfile, "wb");
|
||||||
|
fseek (res_fp, 0L, SEEK_SET);
|
||||||
|
copy_data (res_fp, out_fp, header_len);
|
||||||
|
fclose (out_fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
num_types = CountResourceTypes ();
|
||||||
|
for (i = 1; i <= num_types; ++i)
|
||||||
|
InstallResTypeVectors (i, write_resource, NULL_PTR);
|
||||||
|
|
||||||
|
fseek (res_fp, old_file_list_offs -
|
||||||
|
sizeof (package_path_list_offs), SEEK_SET);
|
||||||
|
fread (&package_path_list_offs,
|
||||||
|
sizeof (package_path_list_offs), 1, res_fp);
|
||||||
|
fseek (res_fp, filelength (fileno (res_fp)) -
|
||||||
|
sizeof (package_file_list_offs), SEEK_SET);
|
||||||
|
fread (&package_file_list_offs,
|
||||||
|
sizeof (package_file_list_offs), 1, res_fp);
|
||||||
|
for (i = 1; i <= ResHeaderPtr->num_packages; ++i)
|
||||||
|
{
|
||||||
|
COUNT file_index;
|
||||||
|
|
||||||
|
file_index = GET_PACKAGE (
|
||||||
|
ResHeaderPtr->PackageList[i - 1].packmem_info
|
||||||
|
);
|
||||||
|
ResHeaderPtr->path_list_offs = package_path_list_offs;
|
||||||
|
ResHeaderPtr->file_list_offs = package_file_list_offs;
|
||||||
|
get_resource_filename (ResHeaderPtr, workbuf, file_index);
|
||||||
|
ResHeaderPtr->path_list_offs = old_path_list_offs;
|
||||||
|
ResHeaderPtr->file_list_offs = old_file_list_offs;
|
||||||
|
|
||||||
|
if (!sanity_check && strcmp (workbuf, outfile) == 0)
|
||||||
|
{
|
||||||
|
out_fp = fopen (outfile, "r+b");
|
||||||
|
file_offs = (long)package_file_list_offs +
|
||||||
|
(long)file_index * FILE_LIST_SIZE
|
||||||
|
+ sizeof (UWORD); /* skip path_offset */
|
||||||
|
fseek (out_fp, file_offs, 0);
|
||||||
|
putc ('\0', out_fp);
|
||||||
|
fclose (out_fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
package_fp = fopen (workbuf, "ab");
|
||||||
|
package_offset = LengthResFile (package_fp);
|
||||||
|
printf ("Packaging '%s' at offset %ld . . .\n", workbuf, package_offset);
|
||||||
|
hList = load_package (ResHeaderPtr, i);
|
||||||
|
fclose (package_fp);
|
||||||
|
|
||||||
|
ResHeaderPtr->PackageList[i - 1].flags_and_data_loc =
|
||||||
|
MAKE_DWORD (hList, 0);
|
||||||
|
if (hList)
|
||||||
|
{
|
||||||
|
LockResourceHandleList (ResHeaderPtr, hList, i,
|
||||||
|
&ResourceHandleListPtr, &TypeEncodePtr, &DataPtr);
|
||||||
|
ResourceHandleListPtr->flags_and_data_loc = 0xFF000000 | package_offset;
|
||||||
|
UnlockResourceHandleList (hList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sanity_check)
|
||||||
|
out_fp = fopen (outfile, "r+b");
|
||||||
|
|
||||||
|
for (i = 1; i <= ResHeaderPtr->num_packages; ++i)
|
||||||
|
{
|
||||||
|
COUNT num_types, num_instances;
|
||||||
|
|
||||||
|
num_types = CountPackageTypes (ResHeaderPtr, i);
|
||||||
|
num_instances = CountPackageInstances (ResHeaderPtr, i);
|
||||||
|
|
||||||
|
hList = (MEM_HANDLE)LOWORD (
|
||||||
|
ResHeaderPtr->PackageList[i - 1].flags_and_data_loc);
|
||||||
|
|
||||||
|
if (hList)
|
||||||
|
{
|
||||||
|
LockResourceHandleList (ResHeaderPtr, hList, i,
|
||||||
|
&ResourceHandleListPtr, &TypeEncodePtr, &DataPtr);
|
||||||
|
ResHeaderPtr->PackageList[i - 1].flags_and_data_loc =
|
||||||
|
ResourceHandleListPtr->flags_and_data_loc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sanity_check)
|
||||||
|
{
|
||||||
|
file_offs = (long)get_packmem_offs (ResHeaderPtr, i)
|
||||||
|
+ (num_types * PACKMEM_LIST_SIZE);
|
||||||
|
fseek (out_fp, file_offs, SEEK_SET);
|
||||||
|
while (num_instances--)
|
||||||
|
{
|
||||||
|
COUNT length;
|
||||||
|
|
||||||
|
length = hList ? MAKE_WORD (DataPtr[0], DataPtr[1]) : 0;
|
||||||
|
DataPtr += 2;
|
||||||
|
fwrite (&length, sizeof (length), 1, out_fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hList)
|
||||||
|
{
|
||||||
|
UnlockResourceHandleList (hList);
|
||||||
|
FreeResourceHandleList (hList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sanity_check)
|
||||||
|
{
|
||||||
|
ResHeaderPtr->res_fp = (FILE *)~0;
|
||||||
|
ResHeaderPtr->path_list_offs = package_path_list_offs;
|
||||||
|
ResHeaderPtr->file_list_offs = package_file_list_offs;
|
||||||
|
ResHeaderPtr->index_info.header_len = header_len;
|
||||||
|
|
||||||
|
fseek (out_fp, 0L, SEEK_SET);
|
||||||
|
fwrite (ResHeaderPtr, sizeof (INDEX_HEADER)
|
||||||
|
+ ResHeaderPtr->num_packages * sizeof (PACKAGE_DESC), 1, out_fp);
|
||||||
|
fclose (out_fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
UninitResourceSystem ();
|
||||||
|
}
|
||||||
|
|
||||||
|
mem_uninit ();
|
||||||
|
|
||||||
|
exit (0);
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include "compiler.h"
|
||||||
|
|
||||||
|
main (argc, argv)
|
||||||
|
int argc;
|
||||||
|
char *argv[];
|
||||||
|
{
|
||||||
|
FILE *infp, *outfp;
|
||||||
|
COUNT bytes_read;
|
||||||
|
DWORD filelen, halflen;
|
||||||
|
static char buf[512];
|
||||||
|
|
||||||
|
infp = fopen (argv[1], "rb");
|
||||||
|
|
||||||
|
ffilelength (infp, &filelen);
|
||||||
|
halflen = filelen >> 1;
|
||||||
|
filelen -= halflen;
|
||||||
|
|
||||||
|
outfp = fopen (argv[2], "wb");
|
||||||
|
while (halflen)
|
||||||
|
{
|
||||||
|
bytes_read = halflen >= sizeof (buf) ?
|
||||||
|
sizeof (buf) : (COUNT)halflen;
|
||||||
|
fwrite (buf, 1, fread (buf, 1, bytes_read, infp), outfp);
|
||||||
|
halflen -= bytes_read;
|
||||||
|
}
|
||||||
|
fclose (outfp);
|
||||||
|
|
||||||
|
outfp = fopen (argv[3], "wb");
|
||||||
|
while (filelen)
|
||||||
|
{
|
||||||
|
bytes_read = filelen >= sizeof (buf) ?
|
||||||
|
sizeof (buf) : (COUNT)filelen;
|
||||||
|
fwrite (buf, 1, fread (buf, 1, bytes_read, infp), outfp);
|
||||||
|
filelen -= bytes_read;
|
||||||
|
}
|
||||||
|
fclose (outfp);
|
||||||
|
|
||||||
|
fclose (infp);
|
||||||
|
}
|
||||||
@@ -0,0 +1,129 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "resource/resintrn.h"
|
||||||
|
|
||||||
|
STATIC RES_PACKAGE res_package;
|
||||||
|
STATIC COUNT name_index;
|
||||||
|
STATIC char file_name[100][80];
|
||||||
|
char workbuf[8 * 1024];
|
||||||
|
|
||||||
|
PROC(STATIC
|
||||||
|
MEM_HANDLE WriteData, (fp, len),
|
||||||
|
ARG (FILE *fp)
|
||||||
|
ARG_END (DWORD len)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
COUNT num_bytes;
|
||||||
|
FILE *out_fp;
|
||||||
|
INDEX_HEADERPTR ResHeaderPtr;
|
||||||
|
|
||||||
|
printf ("\tEXTRACTING %lu bytes @ '%s'\n", len, file_name[name_index]);
|
||||||
|
ResHeaderPtr = _get_current_index_header ();
|
||||||
|
if (CountPackageInstances (ResHeaderPtr, res_package) == 1)
|
||||||
|
{
|
||||||
|
RES_PACKAGE r;
|
||||||
|
|
||||||
|
r = res_package;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (r == ResHeaderPtr->num_packages)
|
||||||
|
len = LengthResFile (fp);
|
||||||
|
else if (GET_PACKAGE (
|
||||||
|
ResHeaderPtr->PackageList[r].packmem_info
|
||||||
|
) != GET_PACKAGE (
|
||||||
|
ResHeaderPtr->PackageList[res_package - 1].packmem_info
|
||||||
|
))
|
||||||
|
len = 0;
|
||||||
|
else
|
||||||
|
len = (ResHeaderPtr->PackageList[r].flags_and_data_loc
|
||||||
|
& ~0xFF000000);
|
||||||
|
++r;
|
||||||
|
} while (len == 0);
|
||||||
|
|
||||||
|
len -= ftell (fp);
|
||||||
|
printf ("\t\tOVERRIDING length (%lu)\n", len);
|
||||||
|
#ifdef DEBUG
|
||||||
|
{
|
||||||
|
#include <conio.h>
|
||||||
|
while (!kbhit ());
|
||||||
|
getch ();
|
||||||
|
}
|
||||||
|
#endif /* DEBUG */
|
||||||
|
}
|
||||||
|
|
||||||
|
out_fp = fopen (file_name[name_index++], "wb");
|
||||||
|
do
|
||||||
|
{
|
||||||
|
num_bytes = len <= sizeof (workbuf) ? (COUNT)len : sizeof (workbuf);
|
||||||
|
fread (workbuf, num_bytes, 1, fp);
|
||||||
|
fwrite (workbuf, num_bytes, 1, out_fp);
|
||||||
|
} while (len -= num_bytes);
|
||||||
|
fclose (out_fp);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
PROC(STATIC
|
||||||
|
MEM_HANDLE GetFileName, (fp, len),
|
||||||
|
ARG (FILE *fp)
|
||||||
|
ARG_END (DWORD len)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
printf ("FOUND '%s'\n", _cur_resfile_name);
|
||||||
|
strcpy (file_name[name_index++], _cur_resfile_name);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
PROC(
|
||||||
|
void CDECL main, (argc, argv),
|
||||||
|
ARG (int argc)
|
||||||
|
ARG_END (char **argv)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
COUNT i, num_types;
|
||||||
|
MEM_HANDLE hPkg, hNdx;
|
||||||
|
INDEX_HEADERPTR ResHeaderPtr;
|
||||||
|
|
||||||
|
mem_init ((MEM_SIZE)0, 0, NULL_PTR);
|
||||||
|
|
||||||
|
hPkg = InitResourceSystem (argv[1], 0, NULL_PTR);
|
||||||
|
ResHeaderPtr = _get_current_index_header ();
|
||||||
|
num_types = CountResourceTypes ();
|
||||||
|
for (i = 1; i <= num_types; ++i)
|
||||||
|
{
|
||||||
|
InstallResTypeVectors (i, WriteData, NULL_PTR);
|
||||||
|
}
|
||||||
|
|
||||||
|
hNdx = OpenResourceIndexFile (argv[2]);
|
||||||
|
SetResourceIndex (hNdx);
|
||||||
|
for (i = 1; i <= num_types; ++i)
|
||||||
|
{
|
||||||
|
InstallResTypeVectors (i, GetFileName, NULL_PTR);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (res_package = 1;
|
||||||
|
res_package <= ResHeaderPtr->num_packages;
|
||||||
|
++res_package)
|
||||||
|
{
|
||||||
|
PROC_GLOBAL(
|
||||||
|
MEM_HANDLE near load_package, (ResHeaderPtr, res_package),
|
||||||
|
ARG (INDEX_HEADERPTR ResHeaderPtr)
|
||||||
|
ARG_END (RES_PACKAGE res_package)
|
||||||
|
);
|
||||||
|
|
||||||
|
name_index = 0;
|
||||||
|
SetResourceIndex (hNdx);
|
||||||
|
load_package (_get_current_index_header (), res_package);
|
||||||
|
|
||||||
|
name_index = 0;
|
||||||
|
SetResourceIndex (hPkg);
|
||||||
|
load_package (_get_current_index_header (), res_package);
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseResourceIndex (hNdx);
|
||||||
|
UninitResourceSystem ();
|
||||||
|
|
||||||
|
mem_uninit ();
|
||||||
|
|
||||||
|
exit (0);
|
||||||
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
/*--anim.h----------------------------------------------------------
|
||||||
|
* anim definitions for ANIM2PCX.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* --- DeluxePaint Animation currently imposes this limit, though
|
||||||
|
* file format is capable of more.
|
||||||
|
*/
|
||||||
|
#define MAX_SUPPORTED_FRAMES (UWORD)9999
|
||||||
|
#define MAX_FRAME_CHARS 4 /* # digits in MAX_SUPPORTED_FRAMES */
|
||||||
|
|
||||||
|
#define MAX_FRAMES (UWORD)65534
|
||||||
|
/* Maximum # frames supported by current anim format.
|
||||||
|
* "65534": 1 left at end for "last-to-first" delta.
|
||||||
|
* NOTE: can't usefully be this large, as need free lp's during editting.
|
||||||
|
* Most anim's won't fit 255 pages per lp, so until we allow more than
|
||||||
|
* 255 lp's, won't reach MAX_FRAMES anyway.
|
||||||
|
*/
|
||||||
|
#define MAX_RECORDS (UWORD)65535
|
||||||
|
|
||||||
|
#define FASTEST_RATE 70 /* Fastest rate anim can be played at. */
|
||||||
|
|
||||||
|
#define MAX_LARGE_PAGE_SIZE (UWORD)(320*203)
|
||||||
|
/* WARNING: this may be stored in DP Animation's picture buffer,
|
||||||
|
* ASSUMES we've allocated three extra lines to the buffer.
|
||||||
|
* This allows us to come close to 64 KB, to minimize file wastage.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define NBYTES_IN_BITMAP(bm) ((UWORD)(bm)->width * (UWORD)(bm)->box.h)
|
||||||
|
/* TBD: ASSUMES < 64 KB. Won't be true for Super-VGA. */
|
||||||
|
|
||||||
|
#define BSEG(bitmap) (bitmap)->seg[0]
|
||||||
|
|
||||||
|
#define PALETTE_SIZE (MAX_COLORS * sizeof(LONG))
|
||||||
|
|
||||||
|
#define FIRST_FRAME_N 1 /* Frame #s start at 1. */
|
||||||
|
#define LAST_DELTA_N (FIRST_FRAME_N-1)
|
||||||
|
/* Frame # used to store delta from last-frame to first. */
|
||||||
|
#define LAST_FRAME_N (animFrames-1+FIRST_FRAME_N)
|
||||||
|
extern UWORD animFrames;
|
||||||
|
|
||||||
|
/* --------------- from IFF.H (Interchange File Format) ---------------
|
||||||
|
*/
|
||||||
|
/* --- Four-character IDentifier builder. */
|
||||||
|
#define MakeID(d,c,b,a) ((LONG)(a)<<24 | (LONG)(b)<<16 | \
|
||||||
|
(LONG)(c)<<8 | (LONG)(d) )
|
||||||
|
|
||||||
|
|
||||||
|
/* --------------- anim file format -------------------- */
|
||||||
|
|
||||||
|
#define CCYCLE70 0 /* 70 Hz color-cycle interrupt */
|
||||||
|
/* P:Caused performance problems on slow machines, especially with cache on.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ---Bitmap body types. */
|
||||||
|
#define BMBODY_UNCOMPRESSED 0
|
||||||
|
#define BMBODY_RUNSKIPDUMP 1 /* Must match ANIMA.ASM/MakeRunSkipDump. */
|
||||||
|
|
||||||
|
/* --- RunSkipDump Bitmap body format. Matches ANIM.INC*/
|
||||||
|
#define OP_DUMP 0x00 /* | cnt */
|
||||||
|
#define OP_RUN 0x00 /* Cnt in separate byte. */
|
||||||
|
#define OP_SKIP 0x80 /* | cnt */
|
||||||
|
#define LONG_OP 0x80
|
||||||
|
#define LONG_SKIP 0x00 /* sub-ops for LONG_OP */
|
||||||
|
#define LONG_DUMP 0x80
|
||||||
|
#define LONG_RUN 0xC0
|
||||||
|
#define MAX_SHORT_DUMP 127
|
||||||
|
#define MAX_LONG_DUMP 0x3fff
|
||||||
|
#define MAX_SHORT_RUN 255
|
||||||
|
#define MAX_LONG_RUN 0x3fff
|
||||||
|
#define MAX_SHORT_SKIP 127
|
||||||
|
#define MAX_LONG_SKIP 0x7fff
|
||||||
|
#define MIN_RUN 4 /* When in Dump, minimum worthwhile Run. */
|
||||||
|
#define MIN_SKIP 2 /* When in Dump, minimum worthwhile Skip. */
|
||||||
|
#define MIN_RUN_SKIP 4 /* When in Run, minimum worthwhile Skip. */
|
||||||
|
/* Note: deltaX.nBytes shorter if can subsume Skip in the Run,
|
||||||
|
* but PC screen i/o is slow enough that it is worth time-saving
|
||||||
|
* of having the Skip.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------*/
|
||||||
|
/* Color Cycles */
|
||||||
|
/*----------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#define MAXNCYCS 16
|
||||||
|
/* lpfile depends on the size of this structure */
|
||||||
|
typedef struct {
|
||||||
|
WORD count;
|
||||||
|
WORD rate;
|
||||||
|
WORD flags;
|
||||||
|
UBYTE low, high; /* bounds of range */
|
||||||
|
} Range;
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
; ANIM.INC. RunSkipDump fields used in ANIMA.ASM. MUST MATCH ANIM.H.
|
||||||
|
|
||||||
|
BMBODY_RUNSKIPDUMP = 1 ; RunSkipDump body header.
|
||||||
|
|
||||||
|
; --- RunSkipDump Bitmap body format.
|
||||||
|
OP_DUMP = 000h
|
||||||
|
OP_RUN = 000h
|
||||||
|
OP_SKIP = 080h
|
||||||
|
LONG_OP = 080h
|
||||||
|
LONG_SKIP = 000h ; sub-ops for LONG_OP.
|
||||||
|
LONG_DUMP = 080h
|
||||||
|
LONG_RUN = 0C0h
|
||||||
|
MAX_SHORT_DUMP = 127
|
||||||
|
MAX_LONG_DUMP = 03fffh
|
||||||
|
MAX_SHORT_RUN = 255
|
||||||
|
MAX_LONG_RUN = 03fffh
|
||||||
|
MAX_SHORT_SKIP = 127
|
||||||
|
MAX_LONG_SKIP = 07fffh
|
||||||
|
MIN_RUN = 4 ; When in Dump, minimum worthwhile Run. */
|
||||||
|
MIN_SKIP = 2 ; When in Dump, minimum worthwhile Skip. */
|
||||||
|
MIN_RUN_SKIP = 4 ; When in Run, minimum worthwhile Skip. */
|
||||||
|
|
||||||
@@ -0,0 +1,296 @@
|
|||||||
|
/*--anim2pcx.c----------------------------------------------------------
|
||||||
|
*
|
||||||
|
* Program to translate an anim into a series of PCX picture files,
|
||||||
|
* and back from picture files into an anim.
|
||||||
|
* Note: all pictures are assumed to have the same 256 palette colors.
|
||||||
|
*
|
||||||
|
* This code is intended to be used as a starting point for programmers
|
||||||
|
* needing to convert anims to/from other formats, or to read/write
|
||||||
|
* anim files from their own applications.
|
||||||
|
*
|
||||||
|
* The source code for ANIM2PCX may be freely incorporated into
|
||||||
|
* commercial programs.
|
||||||
|
*
|
||||||
|
* Disclaimer:
|
||||||
|
* THIS PROGRAM IS PROVIDED WITHOUT SEPARATE CHARGE AND IS
|
||||||
|
* PROVIDED AS IS. ELECTRONIC ARTS DISCLAIMS ALL WARRANTIES,
|
||||||
|
* INCLUDING IMPLIED WARRANTIES AND WARRANTIES OF
|
||||||
|
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
*
|
||||||
|
* *** History *********
|
||||||
|
* Date Who Changes
|
||||||
|
* --------- --- ---------------------------------------------------
|
||||||
|
* 24-Oct-90 ss Original release.
|
||||||
|
*------------------------------------------------------------------
|
||||||
|
* Note: all files editted with tab stops every 4 spaces.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include "anim.h"
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys\types.h>
|
||||||
|
#include <sys\stat.h>
|
||||||
|
#include <io.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define local static
|
||||||
|
|
||||||
|
extern char lpfSuffix[];
|
||||||
|
local char pcxSuffix[]= "PCX";
|
||||||
|
|
||||||
|
BOOL FileError = FALSE; /* error reading or writing a file */
|
||||||
|
BOOL EscFlag = FALSE; /* set TRUE when Esc key detected */
|
||||||
|
|
||||||
|
LONG curpal[MAX_COLORS]; /* palette */
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* --- array of bit masks for one byte */
|
||||||
|
BYTE bit_masks[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
|
||||||
|
|
||||||
|
BOOL toAnim;
|
||||||
|
UWORD animFrames = 10;
|
||||||
|
WORD curFrame = FIRST_FRAME_N; /* Frame currently in hidbm. */
|
||||||
|
char animName[FILENAME_ROOT_LENGTH], pictRoot[FILENAME_ROOT_LENGTH];
|
||||||
|
|
||||||
|
BITMAP hidbm, prevFrame; /* Bitmap describing current & previous frames.*/
|
||||||
|
UWORD lpSeg = NULL; /* Segment of lp buffer. */
|
||||||
|
UWORD allocSeg = NULL; /* Segment allocated for delta buffer. */
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------*/
|
||||||
|
/* forward procedure definitions */
|
||||||
|
|
||||||
|
|
||||||
|
/* --------------- main ---------------
|
||||||
|
*/
|
||||||
|
main(argc, argv)
|
||||||
|
WORD argc;
|
||||||
|
char *argv[];
|
||||||
|
{
|
||||||
|
WORD result;
|
||||||
|
BITMAP bitmap;
|
||||||
|
|
||||||
|
/* ----------------------------------------
|
||||||
|
* Analyze arguments.
|
||||||
|
*/
|
||||||
|
switch (argc) {
|
||||||
|
case 1+1: /* anim => pcx */
|
||||||
|
if (strlen(argv[1]) > FILENAME_ROOT_LENGTH)
|
||||||
|
goto usage;
|
||||||
|
strcpy(animName, argv[1]);
|
||||||
|
toAnim = FALSE;
|
||||||
|
break;
|
||||||
|
case 2+1: /* pcx => anim */
|
||||||
|
if (strcmp(argv[1],"join") != SUCCESS &&
|
||||||
|
strcmp(argv[1],"j") != SUCCESS)
|
||||||
|
goto usage;
|
||||||
|
if (strlen(argv[2]) > FILENAME_ROOT_LENGTH)
|
||||||
|
goto usage;
|
||||||
|
strcpy(animName, argv[2]);
|
||||||
|
toAnim = TRUE;
|
||||||
|
break;
|
||||||
|
default: /* Bad arguments. */
|
||||||
|
usage:
|
||||||
|
#define PR(s) printf(s)
|
||||||
|
PR("\nUsage:\n");
|
||||||
|
PR(" \"anim2pcx name\" to split anim name.ANM into a group of\n");
|
||||||
|
PR(" picture files name0001.PCX, name0002.PCX...\n");
|
||||||
|
PR(" \"anim2pcx j name\" or\n");
|
||||||
|
PR(" \"anim2pcx join name\" to join a group of picture files\n");
|
||||||
|
PR(" name0001.PCX, name0002.PCX, into an anim.\n");
|
||||||
|
PR("\n");
|
||||||
|
PR("NOTE: Only the first four letters of \"name\" are used \n");
|
||||||
|
PR("in the picture file names.\n");
|
||||||
|
PR(" \"anim2pcx foobar\" splits FOOBAR.ANM into FOOB0001.PCX...\n");
|
||||||
|
PR(" \"anim2pcx j foobar\" joins FOOB0001.PCX... into FOOBAR.ANM.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------
|
||||||
|
* Prepare for conversion.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* --- Pict name's suffix is first four characters of anim name.
|
||||||
|
* Note: pictRoot may be shorter than four characters.
|
||||||
|
*/
|
||||||
|
strcpy(pictRoot, animName);
|
||||||
|
pictRoot[SEQUENCE_ROOT_LENGTH] = NULL;
|
||||||
|
|
||||||
|
NewBitMap(&hidbm, N_COLUMNS, N_LINES);
|
||||||
|
NewBitMap(&prevFrame, N_COLUMNS, N_LINES);
|
||||||
|
allocSeg = DAlloc(MAX_LARGE_PAGE_SIZE);
|
||||||
|
lpSeg = DAlloc(MAX_LARGE_PAGE_SIZE);
|
||||||
|
if (!allocSeg || !lpSeg)
|
||||||
|
NotEnoughMemExit();
|
||||||
|
|
||||||
|
if (toAnim)
|
||||||
|
result = PCXFilesToAnimFile();
|
||||||
|
else
|
||||||
|
result = AnimFileToPCXFiles();
|
||||||
|
|
||||||
|
/* ASSUME DAlloc'd memory automatically freed. */
|
||||||
|
|
||||||
|
if (EscFlag == TRUE)
|
||||||
|
EmergencyExit("Terminated at user's request");
|
||||||
|
if (FileError)
|
||||||
|
EmergencyExit("File error");
|
||||||
|
if (result != SUCCESS)
|
||||||
|
EmergencyExit("Failed to complete operation");
|
||||||
|
printf("File(s) successfully converted.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------- save_picture0 ---------------
|
||||||
|
*/
|
||||||
|
UWORD save_picture0(char *filename)
|
||||||
|
{
|
||||||
|
UWORD result, file;
|
||||||
|
|
||||||
|
file = CreateFile(filename, pcxSuffix);
|
||||||
|
if (!file) return FAIL;
|
||||||
|
|
||||||
|
OpenIOBuffer(TRUE);
|
||||||
|
result = WritePCX_Header(file, &hidbm, curpal);
|
||||||
|
if (result != SUCCESS) goto done;
|
||||||
|
result = WritePCX_BODY(file, &hidbm);
|
||||||
|
if (result != SUCCESS) goto done;
|
||||||
|
result = WritePCX_256Palette(file, curpal);
|
||||||
|
|
||||||
|
done:
|
||||||
|
WritePCX_Done();
|
||||||
|
CloseIOBuffer(file);
|
||||||
|
closedos(file);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------- AnimFileToPCXFiles ---------------
|
||||||
|
* ASSUMES "animName" already set to the root part of the animation file's
|
||||||
|
* name. (Note: don't include ".ANM" in "animName".)
|
||||||
|
*/
|
||||||
|
WORD AnimFileToPCXFiles()
|
||||||
|
{
|
||||||
|
WORD i, len, result = FAIL;
|
||||||
|
char nm[FILENAME_LENGTH+1];
|
||||||
|
char nstr[SEQUENCE_DIGITS_LENGTH+1];
|
||||||
|
|
||||||
|
if (OpenLpFile() == FAIL) {
|
||||||
|
printf("File \"%s.%s\" not found.\n", animName, lpfSuffix);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Creating %d PCX files from \"%s.%s\".\n",
|
||||||
|
animFrames, animName, lpfSuffix);
|
||||||
|
|
||||||
|
FirstAnimFrame0();
|
||||||
|
for (i = 0; i < animFrames; i++) {
|
||||||
|
strcpy(nm, pictRoot);
|
||||||
|
num_to_string_zeroes(curFrame, nstr, SEQUENCE_DIGITS_LENGTH);
|
||||||
|
strcat(nm, nstr);
|
||||||
|
if (save_picture0(nm) == FAIL)
|
||||||
|
goto done; /* TBD: message to user? */
|
||||||
|
printf("."); /* Inform user of progress. */
|
||||||
|
NextAnimFrame0();
|
||||||
|
if (CheckAbort())
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
printf("\n"); /* Inform user of progress. */
|
||||||
|
result = SUCCESS;
|
||||||
|
|
||||||
|
done:
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------- load_picture0 ---------------
|
||||||
|
*/
|
||||||
|
UWORD load_picture0(char *filename)
|
||||||
|
{
|
||||||
|
UWORD result, file;
|
||||||
|
BitMapHeader bmHdr;
|
||||||
|
|
||||||
|
file = OpenFile(filename, pcxSuffix);
|
||||||
|
if (!file) return FAIL;
|
||||||
|
|
||||||
|
OpenIOBuffer(FALSE);
|
||||||
|
result = ReadPCX_Header(file, &hidbm, curpal, &bmHdr);
|
||||||
|
if (result != SUCCESS) goto done;
|
||||||
|
result = ReadPCX_BODY(file, &hidbm, &bmHdr);
|
||||||
|
|
||||||
|
done:
|
||||||
|
ReadPCX_Done();
|
||||||
|
CloseIOBuffer(file);
|
||||||
|
closedos(file);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------- PCXFilesToAnimFile ---------------
|
||||||
|
* ASSUMES "animName" already set to the root part of the animation file's
|
||||||
|
* name. (Note: don't include ".ANM" in "animName".)
|
||||||
|
*/
|
||||||
|
WORD PCXFilesToAnimFile()
|
||||||
|
{
|
||||||
|
WORD i, file, len, result = FAIL;
|
||||||
|
char nm[FILENAME_LENGTH+1];
|
||||||
|
char nstr[SEQUENCE_DIGITS_LENGTH+1];
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_SUPPORTED_FRAMES; i++) {
|
||||||
|
strcpy(nm, pictRoot);
|
||||||
|
num_to_string_zeroes(i+FIRST_FRAME_N, nstr, SEQUENCE_DIGITS_LENGTH);
|
||||||
|
strcat(nm, nstr);
|
||||||
|
/* --- Verify file exists, then inform user of operation.*/
|
||||||
|
file = OpenFile(nm, pcxSuffix);
|
||||||
|
if (!file) {
|
||||||
|
if (i == 0) {
|
||||||
|
printf("File \"%s.%s\" not found.\n", nm, pcxSuffix);
|
||||||
|
exit(1);
|
||||||
|
} else
|
||||||
|
break; /* Exit "for i" loop that was adding frames. */
|
||||||
|
}
|
||||||
|
CloseFile(file);
|
||||||
|
if (i == 0) {
|
||||||
|
CreateLpFile();
|
||||||
|
FirstAnimFrame0();
|
||||||
|
printf("Creating \"%s.%s\" from PCX files.\n",
|
||||||
|
animName, lpfSuffix);
|
||||||
|
} else {
|
||||||
|
AddFrame(); /* And make that frame current. */
|
||||||
|
far_movmem(BSEG(&hidbm), 0, BSEG(&prevFrame), 0,
|
||||||
|
N_BYTES_IN_BITMAP);
|
||||||
|
/* New frame's "previous frame" has identical contents. */
|
||||||
|
}
|
||||||
|
if (load_picture0(nm) == FAIL)
|
||||||
|
break; /* No more pictures to load. NOT an error,
|
||||||
|
* TBD: but should delete last added frame! */
|
||||||
|
printf("."); /* Inform user of progress. */
|
||||||
|
WriteFinalAnimFrame();
|
||||||
|
if (CheckAbort()) {
|
||||||
|
result = SUCCESS; /* So anim so far will be kept. */
|
||||||
|
i++; /* So correct notion of frame count. */
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create last-to-first delta.
|
||||||
|
* First create it as a new frame at the end of the anim,
|
||||||
|
* then remove it from the frame count and mark the anim
|
||||||
|
* as containing a last-to-first delta.
|
||||||
|
*/
|
||||||
|
strcpy(nm, pictRoot);
|
||||||
|
num_to_string_zeroes(FIRST_FRAME_N, nstr, SEQUENCE_DIGITS_LENGTH);
|
||||||
|
strcat(nm, nstr);
|
||||||
|
AddFrame(); /* And make that frame current. */
|
||||||
|
far_movmem(BSEG(&hidbm), 0, BSEG(&prevFrame), 0,
|
||||||
|
N_BYTES_IN_BITMAP);
|
||||||
|
load_picture0(nm);
|
||||||
|
WriteFinalAnimFrame();
|
||||||
|
ConvertFinalFrameToLastDelta();
|
||||||
|
|
||||||
|
result = SUCCESS;
|
||||||
|
|
||||||
|
done:
|
||||||
|
WriteHdrAndCloseLpFile();
|
||||||
|
if (result == SUCCESS)
|
||||||
|
printf("\nAnim has %d frames.\n", i); /* Inform user of progress. */
|
||||||
|
else
|
||||||
|
DeleteFile(animName, lpfSuffix);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
anim2pcx anima dalloc gio misc misca lpfile pbio
|
||||||
|
anim2pcx.exe
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -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,530 @@
|
|||||||
|
/*----------------------------------------------------------------------*/
|
||||||
|
/* */
|
||||||
|
/* animio.c - Page-flip animation-- file io code. */
|
||||||
|
/* */
|
||||||
|
/*----------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include "anim.h" /* FIRST_FRAME_N */
|
||||||
|
#include "dpiff.h"
|
||||||
|
#include "dialogmg.h" /* for LIST definition */
|
||||||
|
#include "string.h"
|
||||||
|
#include <sys\types.h>
|
||||||
|
#include <sys\stat.h>
|
||||||
|
|
||||||
|
extern SHORT curDepth;
|
||||||
|
extern UWORD *ytable;
|
||||||
|
extern BITMAP hidbm;
|
||||||
|
extern AnimOb curAnimBr;
|
||||||
|
extern SHORT curfps, nPages, curPage;
|
||||||
|
extern animProcHandle *animOps;
|
||||||
|
|
||||||
|
#define local static
|
||||||
|
|
||||||
|
BOOL isAnimBrIO = NO;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
SHORT saveFrameNum;
|
||||||
|
SHORT saveStart, nSave, loadStart = 0;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct IntuiMessage IMsg;
|
||||||
|
|
||||||
|
|
||||||
|
DPAnimChunk dpAnimChnk;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#define AnimOp(N) (*animOps[N])()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
FreeDelta(register Delta * del)
|
||||||
|
{
|
||||||
|
register int p;
|
||||||
|
|
||||||
|
for (p = 0; p < curDepth; p++) {
|
||||||
|
FP_SEG(del->plane[p]) = SFree(FP_SEG(del->plane[p]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------*/
|
||||||
|
/* Read In ANIM iff files */
|
||||||
|
/*--------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef DBGDLTA
|
||||||
|
BOOL dbgdlta = YES;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------*/
|
||||||
|
/*- Read in a DPAN chunk -----------*/
|
||||||
|
/*--------------------------------------------------------------*/
|
||||||
|
IFFP GetDPAnimChunk(context)
|
||||||
|
GroupContext *context;
|
||||||
|
{
|
||||||
|
IFFP iffp = IFFReadBytes(
|
||||||
|
context, (BYTE *) & dpAnimChnk, (LONG) sizeof(DPAnimChunk));
|
||||||
|
|
||||||
|
ByteFlipAnimChunk(&dpAnimChnk);
|
||||||
|
#ifdef DBGDLTA
|
||||||
|
if (dbgdlta) {
|
||||||
|
printf(" GetDPAnimChunk , vers = %d, nframes = %d, flags = %d \n",
|
||||||
|
dpAnimChnk.version, dpAnimChnk.nframes, dpAnimChnk.flags);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return (iffp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------*/
|
||||||
|
/*- Write out a DPAN chunk -----------*/
|
||||||
|
/*--------------------------------------------------------------*/
|
||||||
|
IFFP PutDPAN(context)
|
||||||
|
GroupContext *context;
|
||||||
|
{
|
||||||
|
DPAnimChunk dpAnCh;
|
||||||
|
|
||||||
|
setmem(&dpAnCh, sizeof(DPAnimChunk), 0);
|
||||||
|
dpAnCh.version = DPANIM_VERS3;
|
||||||
|
if (isAnimBrIO) {
|
||||||
|
dpAnCh.nframes = curAnimBr.nCels;
|
||||||
|
dpAnCh.duration = curAnimBr.duration;
|
||||||
|
dpAnCh.flags = curAnimBr.flags;
|
||||||
|
dpAnCh.rate = 0;
|
||||||
|
}
|
||||||
|
#if 0 /* Not supporting anims, just animbrushes. */
|
||||||
|
else {
|
||||||
|
dpAnCh.nframes = nSave;
|
||||||
|
dpAnCh.rate = curfps;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
ByteFlipAnimChunk(&dpAnCh);
|
||||||
|
return
|
||||||
|
PutCk(context, ID_DPAN, (LONG) sizeof(DPAnimChunk), (BYTE *) & dpAnCh);
|
||||||
|
/* NOTE: needn't flip back to IBM byte-order, since not using further. */
|
||||||
|
}
|
||||||
|
|
||||||
|
#if ANIMDISK
|
||||||
|
/*--------------------------------------------------------------*/
|
||||||
|
/* Anim file IO */
|
||||||
|
/*--------------------------------------------------------------*/
|
||||||
|
typedef char FileName[FILENAME_LENGTH + 1];
|
||||||
|
extern WORD curFrame;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------*/
|
||||||
|
/* Saving anim as separate ILBM's */
|
||||||
|
/* */
|
||||||
|
/* Assumes <name> contains the desired file extension and that */
|
||||||
|
/* 1 <= start <= animFrames, 1 <= end <= animFrames */
|
||||||
|
/*---------------------------------------------------------------*/
|
||||||
|
void SaveAnimAsILBMs(name, start, end)
|
||||||
|
char *name;
|
||||||
|
SHORT start, end;
|
||||||
|
{
|
||||||
|
auto int i, len;
|
||||||
|
auto int nframes = end - start + 1;
|
||||||
|
FileName nm, bsname;
|
||||||
|
auto char nstr[SEQUENCE_SUFFIX_LENGTH], ext[FILENAME_SUFFIX_LENGTH + 2];
|
||||||
|
auto struct stat filestat;
|
||||||
|
auto char *ptr;
|
||||||
|
auto BOOL overwrite = NO;
|
||||||
|
|
||||||
|
/* seperate out the file extension, if any */
|
||||||
|
strcpy(bsname, name);
|
||||||
|
ptr = strchr(bsname, '.');
|
||||||
|
if (ptr) {
|
||||||
|
strncpy(ext, ptr, sizeof(ext));
|
||||||
|
ext[sizeof(ext) - 1] = *ptr = '\0';
|
||||||
|
} else
|
||||||
|
ext[0] = '\0';
|
||||||
|
|
||||||
|
len = strlen(bsname);
|
||||||
|
if (!len) {
|
||||||
|
NotAcceptableFileNameMsg();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((len + SEQUENCE_SUFFIX_LENGTH) > FILENAME_ROOT_LENGTH) {
|
||||||
|
BaseNameTooLongMsg();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
AnimGoTo(start);
|
||||||
|
for (i = 0; i < nframes; i++) {
|
||||||
|
strcpy(nm, bsname);
|
||||||
|
num_to_string_zeroes(curFrame, nstr, SEQUENCE_SUFFIX_LENGTH);
|
||||||
|
strcat(nm, nstr);
|
||||||
|
strcat(nm, ext);
|
||||||
|
if (stat(nm, &filestat) != -1) {
|
||||||
|
if (filestat.st_mode & S_IFDIR) {
|
||||||
|
CantReplaceDirMsg();
|
||||||
|
break;
|
||||||
|
} else if (!(filestat.st_mode & S_IWRITE)) {
|
||||||
|
FileIsWriteProtectedMsg();
|
||||||
|
break;
|
||||||
|
} else if (!overwrite) {
|
||||||
|
if (!ReplaceSequence(nm))
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
overwrite = YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!save_picture0(nm))
|
||||||
|
break;
|
||||||
|
AnimStepPage(1);
|
||||||
|
if (CheckAbort()) {
|
||||||
|
ClearAbortFlag();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* ANIMDISK */
|
||||||
|
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------*/
|
||||||
|
/* Loading ILBMs as Anim */
|
||||||
|
/* tries to load a sequence of ilbm files (bname...bname+num-1) */
|
||||||
|
/* as a new anim with <num> frames. */
|
||||||
|
/*--------------------------------------------------------------*/
|
||||||
|
extern char **filename_strings;
|
||||||
|
extern char pict_dir[], dir_mark[];
|
||||||
|
|
||||||
|
LoadILBMsAsAnim(char *bname, SHORT num, BOOL insert, char *pictExtension)
|
||||||
|
{
|
||||||
|
int i, starti, endi, off;
|
||||||
|
char *fname;
|
||||||
|
LIST list;
|
||||||
|
|
||||||
|
#if 1 /* Prepare filenames */
|
||||||
|
set_full_directory(pict_dir);
|
||||||
|
setmem(&list, sizeof(LIST), 0);
|
||||||
|
if (!AllocFilenameStrings())
|
||||||
|
goto bail;
|
||||||
|
NewNames0(&list, pictExtension, FALSE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
off = strlen(dir_mark);
|
||||||
|
starti = -1;
|
||||||
|
for (i = 0; i < list.num_items; i++) {
|
||||||
|
fname = filename_strings[i] + off;
|
||||||
|
if (strcmp(fname, bname) == 0) {
|
||||||
|
starti = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (starti == -1)
|
||||||
|
goto bail;
|
||||||
|
endi = starti + num - 1;
|
||||||
|
endi = MIN(endi, list.num_items - 1);
|
||||||
|
num = endi - starti + 1;
|
||||||
|
|
||||||
|
if (insert) {
|
||||||
|
/* insert pages after curFrame */
|
||||||
|
if (AddPages(num) == FAIL)
|
||||||
|
return;
|
||||||
|
AnimStepPage(1); /* go to first newly added frame */
|
||||||
|
} else {
|
||||||
|
FreeStrings(&list); /* Make room for NewAnim/SaveAnim dialog. */
|
||||||
|
FreeFilenameStrings();
|
||||||
|
/* create a new untitled anim with the appropriate # of frames */
|
||||||
|
if (NewAnim00(TRUE, num, TRUE) == FAIL)
|
||||||
|
return; /* couldn't create new anim or user aborted */
|
||||||
|
#if 1 /* Prepare filenames */
|
||||||
|
set_full_directory(pict_dir);
|
||||||
|
setmem(&list, sizeof(LIST), 0);
|
||||||
|
if (!AllocFilenameStrings())
|
||||||
|
goto bail;
|
||||||
|
NewNames0(&list, pictExtension, FALSE);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
HideControls();
|
||||||
|
ZZZCursor();
|
||||||
|
for (i = starti; i <= endi; i++) {
|
||||||
|
fname = filename_strings[i];
|
||||||
|
if (fname[0] == dir_mark[0]) {
|
||||||
|
DelPages(1); /* But suppose many pages left unfilled? */
|
||||||
|
break; /* TBD: want to continue to find more
|
||||||
|
* dir's? */
|
||||||
|
}
|
||||||
|
fname += off;
|
||||||
|
|
||||||
|
if (!load_picture00(fname, TRUE, TRUE))
|
||||||
|
break;
|
||||||
|
|
||||||
|
#if comingSoon
|
||||||
|
...remap picture(avoid doing on first picture, when getting
|
||||||
|
palette from first picture ?)
|
||||||
|
CopyPaletteFromFile(curpal, oldPaletteFileLetter);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (CheckAbort()) {
|
||||||
|
ClearAbortFlag();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
AnimStepPage(1);
|
||||||
|
}
|
||||||
|
AnimGoTo(FIRST_FRAME_N);
|
||||||
|
UnZZZCursor();
|
||||||
|
ShowControls();
|
||||||
|
bail:
|
||||||
|
FreeStrings(&list);
|
||||||
|
FreeFilenameStrings();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* --------------- Set/Clear AnBrIO ---------------
|
||||||
|
*/
|
||||||
|
SetAnBrIO()
|
||||||
|
{
|
||||||
|
isAnimBrIO = YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClearAnBrIO()
|
||||||
|
{
|
||||||
|
isAnimBrIO = NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------*/
|
||||||
|
/* Anim IFF IO routines */
|
||||||
|
/*--------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
SHORT animLoadState;
|
||||||
|
|
||||||
|
local void SetAnimLoadFail()
|
||||||
|
{
|
||||||
|
animLoadState = FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* 0 */
|
||||||
|
|
||||||
|
|
||||||
|
#define IFF_MEMFAIL -10
|
||||||
|
|
||||||
|
IFFP AnimGetDLTA(context, bmHdr, animHdr, frameCnt, buffer, bufsize)
|
||||||
|
GroupContext *context;
|
||||||
|
BitMapHeader *bmHdr;
|
||||||
|
AnimHdr *animHdr;
|
||||||
|
SHORT frameCnt;
|
||||||
|
BYTE *buffer;
|
||||||
|
LONG bufsize;
|
||||||
|
{
|
||||||
|
IFFP iffp;
|
||||||
|
BITMAP *tmp;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
if (isAnimBrIO)
|
||||||
|
return (GetAnBrDLTA(context, bmHdr, animHdr, frameCnt, buffer, bufsize));
|
||||||
|
#if 1
|
||||||
|
BugExit("AN1");
|
||||||
|
/* "IFF format for Anim only implemented for brush so far"); */
|
||||||
|
#else /* screen anim */
|
||||||
|
if (frameCnt == 1) {
|
||||||
|
animLoadState = SUCCESS;
|
||||||
|
if (loadStart > 0) {
|
||||||
|
#if 0 /* TBD !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
|
||||||
|
if (AnimOp(ANIM_SAVECHGS) == FAIL)
|
||||||
|
return (IFF_MEMFAIL);
|
||||||
|
#endif
|
||||||
|
} else
|
||||||
|
AnimClearDirty();
|
||||||
|
if (animHdr->interleave != 0 && animHdr->interleave != 2) {
|
||||||
|
NotValidAnimMsg();
|
||||||
|
#if 0 /* TBD: Not moved over from Amiga. 1/30/90 */
|
||||||
|
SkipErrorMsg(); /* tell dpio not to put another error req.
|
||||||
|
* up */
|
||||||
|
#endif
|
||||||
|
return (BAD_FORM);
|
||||||
|
}
|
||||||
|
#if 0 /* TBD: Not moved over from Amiga. 1/30/90 */
|
||||||
|
ShowLoadedPalette();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if (CheckAbort()) {
|
||||||
|
ClearAbortFlag();
|
||||||
|
return (IFF_DONE);
|
||||||
|
}
|
||||||
|
if (dpAnimChnk.version > DPANIM_VERS1) {
|
||||||
|
if (frameCnt >= dpAnimChnk.nframes) {
|
||||||
|
/* Skip remaining deltas: they are for circular play */
|
||||||
|
#if 0 /* TBD: Not moved over from Amiga. 1/30/90 */
|
||||||
|
/* TBD: Not an error !!!!!! */
|
||||||
|
SkipErrorMsg(); /* tell dpio not to put an error req. up */
|
||||||
|
#endif
|
||||||
|
return (IFF_DONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if 0 /* TBD !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
|
||||||
|
res = (*animOps[ANIM_GETDLTA])(context, bmHdr, animHdr, frameCnt, buffer, bufsize);
|
||||||
|
#endif /* 0 */
|
||||||
|
|
||||||
|
return (res);
|
||||||
|
#endif /* screen anim */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
IFFP AnimPutDLTAs(context, buffer, bufsize)
|
||||||
|
GroupContext *context;
|
||||||
|
BYTE *buffer;
|
||||||
|
LONG bufsize;
|
||||||
|
{
|
||||||
|
if (isAnimBrIO)
|
||||||
|
return (PutAnBrDLTAs(context, buffer, bufsize));
|
||||||
|
#if 1
|
||||||
|
else
|
||||||
|
return CLIENT_ERROR; /* Not ready to handle Anim yet. */
|
||||||
|
#else
|
||||||
|
else
|
||||||
|
return ((*animOps[ANIM_PUTDLTAS])(context, buffer, bufsize));
|
||||||
|
#endif /* 0 */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
IFFP AnimIFFDone()
|
||||||
|
{
|
||||||
|
SHORT res = IFF_DONE;
|
||||||
|
|
||||||
|
if (isAnimBrIO)
|
||||||
|
return (AnBrIFFDone());
|
||||||
|
else {
|
||||||
|
if (dpAnimChnk.rate > 0)
|
||||||
|
SetRateFPS(dpAnimChnk.rate);
|
||||||
|
res = (*animOps[ANIM_IFF_DONE])();
|
||||||
|
if (animLoadState == FAIL)
|
||||||
|
AnimLoadFailMsg();
|
||||||
|
return (res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* 0 */
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/*------------------------------------------------------------*/
|
||||||
|
/* assume the bitmap the delta applies to is in dbm: read the */
|
||||||
|
/* Delta and apply it to dbm */
|
||||||
|
/*------------------------------------------------------------*/
|
||||||
|
IFFP ReadAndApplyDelta(context, bmHdr, animHdr, dbm, buffer, bufsize)
|
||||||
|
GroupContext *context;
|
||||||
|
BitMapHeader *bmHdr;
|
||||||
|
AnimHdr *animHdr;
|
||||||
|
BITMAP *dbm;
|
||||||
|
UBYTE *buffer;
|
||||||
|
ULONG bufsize;
|
||||||
|
{
|
||||||
|
int i, op, bpr;
|
||||||
|
ULONG iffp = 0;
|
||||||
|
ULONG ploffs[16];
|
||||||
|
ULONG planeSize[8], plast, plOffsSize;
|
||||||
|
SHORT depth = bmHdr->nPlanes;
|
||||||
|
|
||||||
|
op = animHdr->operation;
|
||||||
|
if (op != ANIM_SHORTD && op != ANIM_RIFF && op != ANIM_RUNSKIP) {
|
||||||
|
NotValidAnimMsg();
|
||||||
|
return (IFF_DONE);
|
||||||
|
}
|
||||||
|
plOffsSize = (op == ANIM_SHORTD ? 32 : 64);
|
||||||
|
|
||||||
|
/*--------------------------------------------------------
|
||||||
|
* NOTE: these ploffs are from the beginning of the chunk:
|
||||||
|
* the first one should have a value of 32 for short delta, 64 for riff,
|
||||||
|
* ?4? for ANIM_RUNSKIP.
|
||||||
|
*/
|
||||||
|
iffp = IFFReadBytes(context, (BYTE *) ploffs, plOffsSize);
|
||||||
|
CheckIFFP();
|
||||||
|
|
||||||
|
#ifdef DBGDLTA
|
||||||
|
if (dbgdlta) {
|
||||||
|
printf(" planeOffsets = ");
|
||||||
|
for (i = 0; i < 8; i++)
|
||||||
|
printf(" %d | ", ploffs[i]);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Compute Size of the compressed planes */
|
||||||
|
/* NOTE: ploffs[i] = 0 means no changes for that plane */
|
||||||
|
|
||||||
|
plast = ChunkMoreBytes(context) + plOffsSize;
|
||||||
|
setmem(planeSize, 8 * sizeof(LONG), 0);
|
||||||
|
for (i = depth - 1; i >= 0; i--) {
|
||||||
|
if (ploffs[i]) {
|
||||||
|
planeSize[i] = plast - ploffs[i];
|
||||||
|
plast = ploffs[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef DBGDLTA
|
||||||
|
if (dbgdlta) {
|
||||||
|
printf(" planeSize = ");
|
||||||
|
for (i = 0; i < 8; i++)
|
||||||
|
printf(" %d | ", planeSize[i]);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
bpr = dbm->width;
|
||||||
|
for (i = 0; i < depth; i++) {
|
||||||
|
if (planeSize[i] != 0) {
|
||||||
|
/* FOR NOW, ONLY READ PLANE IF IT ALL FITS INTO BUFFER */
|
||||||
|
if (planeSize[i] > bufsize) {
|
||||||
|
#ifdef DBGDLTA
|
||||||
|
InfoMessage("ReadAndApplyDLTA: plane too big", "for buffer"); /* ENGLISH */
|
||||||
|
#endif
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
iffp = IFFReadBytes(context, buffer, planeSize[i]);
|
||||||
|
if (iffp != IFF_OKAY) {
|
||||||
|
#ifdef DBGDLTA
|
||||||
|
InfoMessage(" ReadBytes error", " in ReadAndApplyDLTA"); /* ENGLISH */
|
||||||
|
#endif
|
||||||
|
return (iffp);
|
||||||
|
}
|
||||||
|
if (i < dbm->planes)
|
||||||
|
switch (op) {
|
||||||
|
case ANIM_SHORTD:
|
||||||
|
DecodeDLTA(dbm->seg[i], buffer);
|
||||||
|
break;
|
||||||
|
case ANIM_RIFF:
|
||||||
|
decode_vkplane(buffer, dbm->seg[i], bpr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (IFF_OKAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* 0 */
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/*--------------------------------------------------------------*/
|
||||||
|
/* This Computes the RIFF delta between two bitmaps, abm and */
|
||||||
|
/* bbm, and outputs it to the IFF stream */
|
||||||
|
/*--------------------------------------------------------------*/
|
||||||
|
|
||||||
|
IFFP OutputRiffDelta(context, anhdr, abm, bbm, delbm)
|
||||||
|
GroupContext *context;
|
||||||
|
AnimHdr *anhdr;
|
||||||
|
BITMAP *abm, *bbm; /* two bitmaps to be compared */
|
||||||
|
BITMAP *delbm; /* contains the resulting delta planes */
|
||||||
|
{
|
||||||
|
ULONG sizes[8];
|
||||||
|
IFFP ifferror = 0;
|
||||||
|
int i;
|
||||||
|
SHORT bpr = abm->width;
|
||||||
|
|
||||||
|
for (i = 0; i < abm->planes; i++)
|
||||||
|
sizes[i] = MkRIFF(abm->seg[i], bbm->seg[i], delbm->seg[i],
|
||||||
|
abm->Rows, bpr, bpr);
|
||||||
|
ifferror = WriteDelta(context, anhdr, delbm->seg, sizes);
|
||||||
|
return (ifferror);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* 0 */
|
||||||
@@ -0,0 +1,151 @@
|
|||||||
|
;-----------------------------------------------------------------
|
||||||
|
; asm.inc
|
||||||
|
; -------
|
||||||
|
; Standard macros for DPaint II MS-DOS ".asm" files.
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
; Memory model configuration.
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
|
||||||
|
LPROG equ 1 ; 1 means large (>64k) program segment
|
||||||
|
LDATA equ 0 ; 1 means large (>64k) data segment
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
; After a standard procedure entry (push bp, mov bp,sp), the first
|
||||||
|
; parm on the stack can be accessed at ARGB[bp].
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
|
||||||
|
if LPROG
|
||||||
|
ARGB equ 6
|
||||||
|
else
|
||||||
|
ARGB equ 4
|
||||||
|
endif
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
; File header: sets up groups, segment names, etc.
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
|
||||||
|
if LPROG
|
||||||
|
HEADER macro module
|
||||||
|
module&_TEXT segment word public 'CODE'
|
||||||
|
module&_TEXT ends
|
||||||
|
_DATA segment word public 'DATA'
|
||||||
|
_DATA ends
|
||||||
|
CONST segment word public 'CONST'
|
||||||
|
CONST ends
|
||||||
|
_BSS segment word public 'BSS'
|
||||||
|
_BSS ends
|
||||||
|
DGROUP group CONST, _BSS, _DATA
|
||||||
|
assume cs:module&_TEXT, ds:DGROUP, ss:DGROUP, es:DGROUP
|
||||||
|
endm
|
||||||
|
else
|
||||||
|
HEADER macro
|
||||||
|
_TEXT segment word public 'CODE'
|
||||||
|
_TEXT ends
|
||||||
|
CONST segment word public 'CONST'
|
||||||
|
CONST ends
|
||||||
|
_BSS segment word public 'BSS'
|
||||||
|
_BSS ends
|
||||||
|
_DATA segment word public 'DATA'
|
||||||
|
_DATA ends
|
||||||
|
DGROUP group CONST, _BSS, _DATA
|
||||||
|
assume cs:_TEXT, ds:DGROUP, ss:DGROUP, es:DGROUP
|
||||||
|
endm
|
||||||
|
endif
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
; Data segment start & end.
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
|
||||||
|
DSEG macro
|
||||||
|
_DATA segment
|
||||||
|
endm
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
|
||||||
|
ENDDS macro
|
||||||
|
_DATA ends
|
||||||
|
endm
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
; Program segment start & end.
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
|
||||||
|
if LPROG
|
||||||
|
PSEG macro module
|
||||||
|
module&_TEXT segment
|
||||||
|
endm
|
||||||
|
else
|
||||||
|
PSEG macro
|
||||||
|
_TEXT segment
|
||||||
|
endm
|
||||||
|
endif
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
|
||||||
|
if LPROG
|
||||||
|
ENDPS macro module
|
||||||
|
module&_TEXT ends
|
||||||
|
endm
|
||||||
|
else
|
||||||
|
ENDPS macro module
|
||||||
|
_TEXT ends
|
||||||
|
endm
|
||||||
|
endif
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
; Procedure start & end.
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
|
||||||
|
STARTPROC macro proc_name
|
||||||
|
if LPROG
|
||||||
|
proc_name proc far
|
||||||
|
else
|
||||||
|
proc_name proc near
|
||||||
|
endif
|
||||||
|
endm
|
||||||
|
|
||||||
|
;--- start a procedure and declare it public ---
|
||||||
|
STARTPROC_PUBLIC macro name
|
||||||
|
public name
|
||||||
|
if LPROG
|
||||||
|
name proc far
|
||||||
|
else
|
||||||
|
name proc near
|
||||||
|
endif
|
||||||
|
endm
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
|
||||||
|
ENDPROC macro proc_name
|
||||||
|
proc_name endp
|
||||||
|
endm
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
; When the 80286 is in real mode, the POPF instruction may recognize
|
||||||
|
; a pending maskable interrupt even if interrupts were off before the
|
||||||
|
; corresponding PUSHF. This macro should be used instead of POPF.
|
||||||
|
; See "IBM Personal Computer Seminar Proceedings" v2, #4 (September '84)
|
||||||
|
; for info about the POPF bug.
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
|
||||||
|
popflags macro
|
||||||
|
jmp $+3 ; jump around IRET
|
||||||
|
iret ; pop CS, IP, and flags
|
||||||
|
push cs
|
||||||
|
call $-2 ; call within segment
|
||||||
|
endm
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
; Offsets to low byte & high byte of a word.
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
LO = 0
|
||||||
|
HI = 1
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
; --- miscellaneous constants
|
||||||
|
|
||||||
|
TRUE equ 1
|
||||||
|
FALSE equ 0
|
||||||
|
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
;-----------------------------------------------------------------
|
||||||
|
; dalloc.asm
|
||||||
|
; ----------
|
||||||
|
; Memory-allocation routines that operate OUTSIDE of the data segment.
|
||||||
|
; These work with SEGMENT addresses, NOT actual pointers.
|
||||||
|
; For allocation in the data segment, just use malloc () and free ().
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
|
||||||
|
include asm.inc
|
||||||
|
|
||||||
|
HEADER dalloc
|
||||||
|
|
||||||
|
PSEG dalloc
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
; WORD DAlloc (size);
|
||||||
|
; UWORD size;
|
||||||
|
; Allocate a block of "size" bytes and return its segment. If
|
||||||
|
; the allocation fails, return NULL.
|
||||||
|
; Since this uses DOS allocation, it will allocate just enough paragraphs
|
||||||
|
; for the number of bytes requested.
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
|
||||||
|
public _DAlloc
|
||||||
|
STARTPROC _DAlloc
|
||||||
|
|
||||||
|
push bp
|
||||||
|
mov bp,sp
|
||||||
|
|
||||||
|
mov ah,048h ; function #
|
||||||
|
|
||||||
|
; bx = number of paragraphs = (bytes >> 4) + (bytes & 0x0f) ? 1 : 0;
|
||||||
|
mov bx,ARGB[bp]
|
||||||
|
mov cl,4
|
||||||
|
shr bx,cl
|
||||||
|
test word ptr ARGB[bp],0fh
|
||||||
|
je dalloc_p0
|
||||||
|
inc bx
|
||||||
|
dalloc_p0:
|
||||||
|
|
||||||
|
int 021h
|
||||||
|
jnc dalloc_p1
|
||||||
|
xor ax,ax ; alloc failed, so return NULL
|
||||||
|
dalloc_p1:
|
||||||
|
|
||||||
|
pop bp
|
||||||
|
ret
|
||||||
|
|
||||||
|
ENDPROC _DAlloc
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
; void SFree (seg);
|
||||||
|
; Was "DFree", but PLink said that conflicted with "dfree".
|
||||||
|
; Free the block at the given segment address.
|
||||||
|
;
|
||||||
|
; Okay to call with NULL, so safe to call on already freed segment
|
||||||
|
; variables. That DOESN'T mean it is okay to maintain two DIFFERENT
|
||||||
|
; segment variables, and try to free the same region twice through
|
||||||
|
; two different variables! Also, it is up to the caller to NULL
|
||||||
|
; his sgment variable when done. Maybe we should switch to a model
|
||||||
|
; where caller passes ADDRESS of segment variable! [sss]
|
||||||
|
; Always returns null, so can use to null a variable holding a
|
||||||
|
; segment address:
|
||||||
|
; "segname = SFree(segname);"
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
|
||||||
|
public _SFree
|
||||||
|
STARTPROC _SFree
|
||||||
|
|
||||||
|
push bp
|
||||||
|
mov bp,sp
|
||||||
|
push es
|
||||||
|
|
||||||
|
; if (!seg), don't do anything
|
||||||
|
test word ptr ARGB[bp],0ffffh
|
||||||
|
jz dfree_done
|
||||||
|
|
||||||
|
; free the segment
|
||||||
|
mov ah,049h
|
||||||
|
mov es,ARGB[bp]
|
||||||
|
int 021h
|
||||||
|
ifdef DEBUGGING
|
||||||
|
jnc dfree_1
|
||||||
|
mov ax,9999
|
||||||
|
push ax
|
||||||
|
call _crash
|
||||||
|
dfree_1:
|
||||||
|
endif
|
||||||
|
|
||||||
|
dfree_done:
|
||||||
|
xor ax,ax ; NULL return value so can assign.
|
||||||
|
pop es
|
||||||
|
pop bp
|
||||||
|
ret
|
||||||
|
|
||||||
|
ENDPROC _SFree
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
|
||||||
|
ENDPS dalloc
|
||||||
|
end
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
;---------------------------------------------------------------------------
|
||||||
|
; ega.mac
|
||||||
|
; This header file defines subroutines to do ega graphics from assembler.
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
|
||||||
|
; EGA register equates
|
||||||
|
|
||||||
|
TS_INDEX equ 3c4h ; Time Sequencer Index
|
||||||
|
TS_MASK equ 2 ; -- Map Mask (Enables CPU writes)
|
||||||
|
GDC_INDEX equ 3ceh ; Graphics Data Controller Index
|
||||||
|
GDC_MODE equ 5 ; -- Mode Register
|
||||||
|
GDC_RSEL equ 4 ; -- Read Map Select
|
||||||
|
CRTC_INDEX equ 3d4h ; CRT Controller Index
|
||||||
|
CRTC_OFFSET equ 13h ; -- Offset Register
|
||||||
|
CRTC_STARTH equ 0ch ; -- High Byte of Start Address
|
||||||
|
CRTC_STARTL equ 0dh ; -- Low Byte of Start Adrress
|
||||||
|
STATUS_REGISTER equ 3dah ; EGA status register
|
||||||
|
VSYNC_MASK equ 08h ; -- Vertical synch bit in status register
|
||||||
|
|
||||||
|
;-------------------------------------------------------------------------
|
||||||
|
; SETREG macro to set internal register <reg> of chip with
|
||||||
|
; index register at <index> to the value stored in AL
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
|
||||||
|
; push dx
|
||||||
|
; mov dx,P1
|
||||||
|
; mov ah,al
|
||||||
|
; mov al,P2
|
||||||
|
; out dx,ax
|
||||||
|
; pop dx
|
||||||
|
|
||||||
|
SETREG macro P1, P2
|
||||||
|
push dx
|
||||||
|
mov dx,P1
|
||||||
|
mov ah,al
|
||||||
|
mov al,P2
|
||||||
|
out dx,al
|
||||||
|
mov al,ah
|
||||||
|
inc dx
|
||||||
|
out dx,al
|
||||||
|
pop dx
|
||||||
|
endm
|
||||||
@@ -0,0 +1,197 @@
|
|||||||
|
/*--gio.c-----------------------------------------------------------------
|
||||||
|
* Buffered i/o.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include <io.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define local static
|
||||||
|
|
||||||
|
/* --- Segment of optional buffer for speeding-up i/o. */
|
||||||
|
local UWORD ioBufferSeg = NULL;
|
||||||
|
local UWORD ioBufSize = 0, ioBufNext, ioBufLimit;
|
||||||
|
local BOOL ioWriting;
|
||||||
|
|
||||||
|
/* ---------- OpenIOBuffer ---------- */
|
||||||
|
void OpenIOBuffer(BOOL forWriting)
|
||||||
|
{
|
||||||
|
register WORD bufSize;
|
||||||
|
auto WORD tempSeg;
|
||||||
|
|
||||||
|
ioWriting = forWriting;
|
||||||
|
|
||||||
|
/* --- Allocate i/o buffer. */
|
||||||
|
if (ioBufferSeg == NULL) {
|
||||||
|
for (bufSize = 16 * 1024; bufSize >= 512; bufSize >>= 1) {
|
||||||
|
ioBufferSeg = DAlloc(bufSize);
|
||||||
|
if (ioBufferSeg) {
|
||||||
|
/* --- Leave at least 4 KB free for other uses. */
|
||||||
|
tempSeg = DAlloc(4096);
|
||||||
|
if (tempSeg) {
|
||||||
|
tempSeg = SFree(tempSeg);
|
||||||
|
break; /* Success; leave loop. */
|
||||||
|
} else
|
||||||
|
ioBufferSeg = SFree(ioBufferSeg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ioBufferSeg != NULL)
|
||||||
|
ioBufSize = bufSize;
|
||||||
|
}
|
||||||
|
ioBufNext = ioBufLimit = 0;
|
||||||
|
/* Reading: When next==limit, buffer is empty.
|
||||||
|
* Writing: When next== 0, buffer is empty.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------- CloseIOBuffer -----------------
|
||||||
|
* Writing: flush any remaining data to file.
|
||||||
|
* Free the i/o buffer. Do this whenever finish i/o, so RAM not tied up.
|
||||||
|
*/
|
||||||
|
void CloseIOBuffer(WORD file)
|
||||||
|
{
|
||||||
|
if (ioWriting)
|
||||||
|
GFlush(file); /* TBD: ignoring error. */
|
||||||
|
ioBufferSeg = SFree(ioBufferSeg);
|
||||||
|
ioBufSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------- GRead ---------------------------------------------
|
||||||
|
* Like DOS "read" function, RETURNS # bytes read, or 0 at EOF,
|
||||||
|
* or -1 at error.
|
||||||
|
*/
|
||||||
|
WORD GRead(WORD file, UBYTE *buffer, UWORD nBytes)
|
||||||
|
{
|
||||||
|
UWORD nRemaining, nAvail, nThisTime;
|
||||||
|
|
||||||
|
if (ioBufferSeg) {
|
||||||
|
nAvail = ioBufLimit - ioBufNext;
|
||||||
|
if (!nAvail && nBytes >= ioBufSize)
|
||||||
|
goto readDirectly; /* More efficient to read buffer directly. */
|
||||||
|
|
||||||
|
/* --- Remaining # bytes that need reading. */
|
||||||
|
for (nRemaining = nBytes; nRemaining; nRemaining -= nThisTime) {
|
||||||
|
if (!nAvail) {
|
||||||
|
ioBufLimit = nAvail =
|
||||||
|
readdos(file, ioBufferSeg, 0, ioBufSize);
|
||||||
|
if (nAvail == 0xffff || nAvail == 0) {
|
||||||
|
ioBufLimit = 0;
|
||||||
|
return (nAvail);
|
||||||
|
}
|
||||||
|
ioBufNext = 0;
|
||||||
|
}
|
||||||
|
nThisTime = MIN(nRemaining, nAvail);
|
||||||
|
far_movmem(ioBufferSeg, ioBufNext,
|
||||||
|
dataseg(), (UWORD)buffer,
|
||||||
|
(UWORD)nThisTime);
|
||||||
|
buffer += nThisTime;
|
||||||
|
ioBufNext += nThisTime;
|
||||||
|
nAvail -= nThisTime;
|
||||||
|
}
|
||||||
|
return (nBytes);
|
||||||
|
} else /* No ioBuf */
|
||||||
|
readDirectly:
|
||||||
|
return (read(file, buffer, nBytes));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------- GReadOne --------------------------------
|
||||||
|
* Like "GRead", but read a single byte, with less overhead.
|
||||||
|
*/
|
||||||
|
WORD GReadOne(WORD file, UBYTE *buffer)
|
||||||
|
{
|
||||||
|
if (!ioBufferSeg || ioBufLimit == ioBufNext)
|
||||||
|
return GRead(file, buffer, 1);
|
||||||
|
|
||||||
|
*buffer = *BYTE_FAR_PTR(ioBufferSeg, ioBufNext);
|
||||||
|
ioBufNext++;
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------- GFlush ------------------------------
|
||||||
|
* Write out any bytes remaining in the buffer.
|
||||||
|
* Return what writedos does, or 0 if nothing to do.
|
||||||
|
*/
|
||||||
|
WORD GFlush(WORD file)
|
||||||
|
{
|
||||||
|
auto WORD result = 0;
|
||||||
|
|
||||||
|
if (ioBufferSeg && ioBufNext && ioWriting) {
|
||||||
|
result = writedos(file, ioBufferSeg, 0, ioBufNext);
|
||||||
|
if (result < ioBufNext)
|
||||||
|
result = -1; /* Disk must be full, turn it into an error. */
|
||||||
|
ioBufNext = 0; /* Writing: buffer is empty. */
|
||||||
|
}
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------- GSeek ----------------------------------------------------
|
||||||
|
* When reading, ASSUMES seeking forwards.
|
||||||
|
* When writing, flush buffer and use lseek.
|
||||||
|
* RETURNS 0 if succeeded in seeking w/i buffer. DIFFERENT THAN LSEEK.
|
||||||
|
*/
|
||||||
|
LONG GSeek(WORD file, LONG count, WORD seekType)
|
||||||
|
{
|
||||||
|
UWORD nAvail;
|
||||||
|
|
||||||
|
if (ioBufferSeg) {
|
||||||
|
if (ioWriting && ioBufNext) {
|
||||||
|
GFlush(file); /* TBD: Ignoring error code. */
|
||||||
|
goto seekDirectly;
|
||||||
|
}
|
||||||
|
nAvail = ioBufLimit - ioBufNext;
|
||||||
|
|
||||||
|
if (seekType != SEEK_CUR) { /* Check for absolute positioning */
|
||||||
|
goto emptyAndSeekDirectly;
|
||||||
|
}
|
||||||
|
if (count > nAvail) {
|
||||||
|
count -= nAvail; /* Adjust seek for bytes already read ahead. */
|
||||||
|
emptyAndSeekDirectly:
|
||||||
|
ioBufNext = ioBufLimit; /* Reading: buffer is empty. */
|
||||||
|
goto seekDirectly;
|
||||||
|
}
|
||||||
|
ioBufNext += (UWORD)count; /* Seek within the buffer. */
|
||||||
|
return (0); /* DIFFERENT THAN LSEEK */
|
||||||
|
} else
|
||||||
|
seekDirectly:
|
||||||
|
return lseek(file, count, seekType);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------- GWrite ---------------------------------------------
|
||||||
|
* Like DOS "write" function, RETURNS # bytes written, or -1 at error.
|
||||||
|
* DIFFERENCE: if can't write them all, returns -1 instead of # written,
|
||||||
|
* UNLESS "writeDirectly", which just uses write().
|
||||||
|
*/
|
||||||
|
WORD GWrite(WORD file, UBYTE * buffer, UWORD nBytes)
|
||||||
|
{
|
||||||
|
UWORD nRemaining, nUnused, nThisTime, nWritten;
|
||||||
|
|
||||||
|
if (ioBufferSeg) {
|
||||||
|
if (!ioBufNext && nBytes >= ioBufSize)
|
||||||
|
goto writeDirectly; /* More efficient to write buffer directly. */
|
||||||
|
|
||||||
|
nUnused = ioBufSize - ioBufNext; /* # bytes unused in buffer. */
|
||||||
|
|
||||||
|
/* Remaining # bytes that need writing. */
|
||||||
|
for (nRemaining = nBytes; nRemaining; nRemaining -= nThisTime) {
|
||||||
|
if (!nUnused) {
|
||||||
|
nWritten = writedos(file, ioBufferSeg, 0, ioBufNext);
|
||||||
|
if (nWritten != ioBufNext) {
|
||||||
|
ioBufNext = 0; /* Flush the data -- it is lost. */
|
||||||
|
return (-1); /* ERROR */
|
||||||
|
}
|
||||||
|
ioBufNext = 0;
|
||||||
|
nUnused = ioBufSize;
|
||||||
|
}
|
||||||
|
nThisTime = MIN(nRemaining, nUnused);
|
||||||
|
far_movmem(dataseg(),
|
||||||
|
(UWORD)buffer, ioBufferSeg,
|
||||||
|
ioBufNext, (UWORD)nThisTime);
|
||||||
|
buffer += nThisTime;
|
||||||
|
ioBufNext += nThisTime;
|
||||||
|
nUnused -= nThisTime;
|
||||||
|
}
|
||||||
|
return (nBytes); /* OKAY */
|
||||||
|
} else /* No ioBuf */
|
||||||
|
writeDirectly:
|
||||||
|
return (write(file, buffer, nBytes));
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,162 @@
|
|||||||
|
/*--main.h----------------------------------------------------------
|
||||||
|
* Main include file for ANIM2PCX.
|
||||||
|
* Note: all files editted with tab stops every 4 spaces.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------
|
||||||
|
* 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 */
|
||||||
|
typedef void (*ProcHandle)();
|
||||||
|
|
||||||
|
/* --- enable argument checking in Microsoft's include files */
|
||||||
|
#define LINT_ARGS
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef NULL
|
||||||
|
#define NULL 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef FALSE
|
||||||
|
#define FALSE 0
|
||||||
|
#define TRUE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define FAIL 1
|
||||||
|
#define SUCCESS 0
|
||||||
|
|
||||||
|
#define MAX_INTEGER 32767
|
||||||
|
|
||||||
|
#define HIWORD(longValue) ((UWORD)((longValue) >> 16))
|
||||||
|
#define LOWORD(longValue) ((UWORD)(longValue))
|
||||||
|
|
||||||
|
/* --- this depends on the memory model we're using */
|
||||||
|
/* Within the 64 KB data segment. */
|
||||||
|
#define NULL_DATAPTR 0
|
||||||
|
/* #define NULL_PROCPTR ((BYTE far *) NULL) */
|
||||||
|
#define NULL_PROCPTR ((ProcHandle) NULL)
|
||||||
|
|
||||||
|
/* --- separate Microsoft "far" ptrs into their segment & offset parts */
|
||||||
|
#define FP_SEG(fp) (*((UWORD *)&(fp) + 1))
|
||||||
|
#define FP_OFF(fp) (*((UWORD *)&(fp)))
|
||||||
|
|
||||||
|
/* --- combine segment & offset into a "far" ptr */
|
||||||
|
#define BYTE_FAR_PTR(seg,off) ((BYTE far *)(((LONG)(seg)<<16)+(off)))
|
||||||
|
#define WORD_FAR_PTR(seg,off) ((WORD far *)(((LONG)(seg)<<16)+(UWORD)(off)))
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#define SWAP(a,b) { (a) ^= (b); (b) ^= (a); (a) ^= (b); }
|
||||||
|
#define ORDER(a,b) if ((a)>(b)) SWAP((a),(b))
|
||||||
|
#define MAX(a,b) ((a)>(b)?(a):(b))
|
||||||
|
#define MIN(a,b) ((a)<(b)?(a):(b))
|
||||||
|
#define ABS(a) ((a)>0?(a):-(a))
|
||||||
|
#define DIV_ROUND(x, d) (((x) + ((d) >> 1)) / (d)) /* ASSUME d > 0. */
|
||||||
|
#define EVEN_UP(a) ( ((a)+1) & ~1 )
|
||||||
|
/* Even number >= a. */
|
||||||
|
|
||||||
|
#define CHECK_DOS(fn) if ((fn) == -1) goto doserr
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------
|
||||||
|
* Graphics data structures.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
WORD x, y;
|
||||||
|
} POINT;
|
||||||
|
typedef struct {
|
||||||
|
WORD w, h;
|
||||||
|
} Dims;
|
||||||
|
typedef struct {
|
||||||
|
WORD x, y, w, h;
|
||||||
|
} Box;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* kludge for easy access to individual red/green/blue values within a LONG.
|
||||||
|
* NOTE: this depends on 808x byte order being low-high.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
UBYTE blue, green, red, unused1;
|
||||||
|
} LONG_RGB;
|
||||||
|
|
||||||
|
/* --- Max # colors visible on screen. */
|
||||||
|
#define MAX_COLORS 256
|
||||||
|
|
||||||
|
/* --- Max # planes that a bitmap can have. */
|
||||||
|
#define MAX_PLANES 4
|
||||||
|
|
||||||
|
/* --- BITMAP structure */
|
||||||
|
typedef struct {
|
||||||
|
WORD width; /* Width in bytes of each row. Must be even. */
|
||||||
|
Box box; /* Pixel bounds of bitmap. (x,y == 0.) */
|
||||||
|
WORD planes; /* Number of planes. */
|
||||||
|
UWORD seg[MAX_PLANES]; /* SEG where each plane is allocated. */
|
||||||
|
} BITMAP;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
BITMAP *bitmap;
|
||||||
|
WORD nPlanes; /* used only in FMT_ONLY mode */
|
||||||
|
UBYTE xpcolor;
|
||||||
|
} MaskBM;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UWORD w, h; /* raster width & height in pixels */
|
||||||
|
UBYTE nPlanes; /* # source bitplanes */
|
||||||
|
} BitMapHeader;
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------
|
||||||
|
* Description of screen format "f" (320 x 200, 256-colors).
|
||||||
|
*/
|
||||||
|
#define ppb 1 /* pixels per byte */
|
||||||
|
#define ppb_minus1 0 /* ppb - 1 */
|
||||||
|
#define ppb_shift 0 /* 1 << ppb_shift == ppb */
|
||||||
|
#define bpp 8 /* bits per pixel */
|
||||||
|
#define bpp_minus1 7 /* bpp - 1 */
|
||||||
|
#define bpp_shift 3 /* 1 << bpp_shift == bpp */
|
||||||
|
#define curDepth 1 /* Single plane in byte-per-pixel format. */
|
||||||
|
#define white_color 0xff /* register # for default white. */
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------
|
||||||
|
* Number of chars in an MS-DOS filename or directory (path) name.
|
||||||
|
*/
|
||||||
|
#define FILENAME_ROOT_LENGTH 8
|
||||||
|
#define FILENAME_SUFFIX_LENGTH 3
|
||||||
|
#define SEQUENCE_ROOT_LENGTH 4 /* XXXX in XXXX0001.PCX, XXXX0002.PCX...*/
|
||||||
|
#define SEQUENCE_DIGITS_LENGTH (FILENAME_ROOT_LENGTH - SEQUENCE_ROOT_LENGTH)
|
||||||
|
#define FILENAME_LENGTH 12 /* ROOT + '.' + SUFFIX */
|
||||||
|
#define PATHNAME_LENGTH 66 /* drive + path (no filename) */
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------
|
||||||
|
* Screen Format "f".
|
||||||
|
*/
|
||||||
|
#define N_COLUMNS 320
|
||||||
|
#define N_LINES 200
|
||||||
|
#define N_BYTES_IN_BITMAP (N_COLUMNS * N_LINES)
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------
|
||||||
|
* Buffered i/o.
|
||||||
|
*/
|
||||||
|
void OpenIOBuffer(BOOL forWriting);
|
||||||
|
void CloseIOBuffer(WORD file);
|
||||||
|
WORD GFlush(WORD file);
|
||||||
|
LONG GSeek(WORD file, LONG count, WORD seekType);
|
||||||
|
WORD GRead(WORD file, UBYTE *buffer, UWORD nBytes);
|
||||||
|
WORD GWrite(WORD file, UBYTE *buffer, UWORD nBytes);
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------
|
||||||
|
* Procedures that need to be declared so parameters or return values of
|
||||||
|
* correct type.
|
||||||
|
*/
|
||||||
|
WORD far *BMLineStart(BITMAP*, WORD, WORD);
|
||||||
|
|
||||||
|
/* --- mnemonic names for Microsoft library functions */
|
||||||
|
#define movmem(source,dest,length) memmove(dest,source,length)
|
||||||
|
#define setmem(ptr,length,value) memset(ptr,value,length)
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
;-----------------------------------------------------------------
|
||||||
|
; prism.inc
|
||||||
|
; ---------
|
||||||
|
; Assembly-language equivalent of prism.h.
|
||||||
|
; Changed for use with file conversion program.
|
||||||
|
; - changed MAX_PLANES from 4 to 8. Altered BITMAP_OFFS, SIZEOF_BITMAP
|
||||||
|
; accordingly.
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
|
||||||
|
; comment these two out to eliminate debugging code!
|
||||||
|
; DEBUGGING equ 1
|
||||||
|
; extrn _crash:far
|
||||||
|
|
||||||
|
; --- miscellaneous constants
|
||||||
|
POSITIVE equ 1
|
||||||
|
NEGATIVE equ 0
|
||||||
|
|
||||||
|
; --- display types. also in test.h.
|
||||||
|
EGA_640x200_16 equ 0
|
||||||
|
EGA_640x350_16 equ 1
|
||||||
|
CGA_320x200_4 equ 2
|
||||||
|
CGA_640x200_2 equ 3
|
||||||
|
EGA_320x200_16 equ 4
|
||||||
|
HERC_720x348_2 equ 5
|
||||||
|
MCGA_640x480_2 equ 6
|
||||||
|
VGA_640x480_16 equ 7
|
||||||
|
MCGA_320x200_256 equ 8
|
||||||
|
TANDY_320x200_16 equ 9
|
||||||
|
VGA_320x200_16 equ 10 ; same as EGA mode, but with VGA color control
|
||||||
|
VGA_640x200_16 equ 11 ; same as EGA mode, but with VGA color control
|
||||||
|
VGA_640x350_16 equ 12 ; same as EGA mode, but with VGA color control
|
||||||
|
|
||||||
|
MAX_LINE_SIZE equ 320
|
||||||
|
MAX_COLORS equ 256
|
||||||
|
MAX_PLANES equ 8
|
||||||
|
MAX_PLANES_SHIFT equ 3 ; MAX_PLANES expressed as left shift
|
||||||
|
|
||||||
|
; --- drawing modes.
|
||||||
|
MODE_COPY equ 0
|
||||||
|
MODE_XOR equ 1
|
||||||
|
MODE_COLOR equ 2
|
||||||
|
MODE_SWAP equ 3
|
||||||
|
MODE_SHADE_UP equ 4
|
||||||
|
MODE_SHADE_DOWN equ 5
|
||||||
|
MODE_BMCOPY equ 6
|
||||||
|
MODE_INV_COLOR equ 7
|
||||||
|
; these two are only used by smear_copy
|
||||||
|
MODE_SMEAR equ 8
|
||||||
|
MODE_BLEND equ 9
|
||||||
|
MODE_SHADE_COPY equ 10
|
||||||
|
|
||||||
|
; --- offsets to parts of the BITMAP structure
|
||||||
|
; NOTE: drawchar.asm contains hard-coded inits for a BITMAP
|
||||||
|
BITMAP_FLAGS equ 0
|
||||||
|
BITMAP_WIDTH equ 2
|
||||||
|
BITMAP_BOX equ 4
|
||||||
|
BITMAP_BOX_X equ 4
|
||||||
|
BITMAP_BOX_Y equ 6
|
||||||
|
BITMAP_BOX_W equ 8
|
||||||
|
BITMAP_BOX_H equ 10
|
||||||
|
BITMAP_PLANES equ 12
|
||||||
|
BITMAP_YTABLE equ 14
|
||||||
|
BITMAP_SEG equ 16
|
||||||
|
BITMAP_OFFS equ 32
|
||||||
|
; --- size of the BITMAP structure
|
||||||
|
SIZEOF_BITMAP equ 34
|
||||||
|
|
||||||
|
; --- offsets to parts of the Box structure
|
||||||
|
BOX_X equ 0
|
||||||
|
BOX_Y equ 2
|
||||||
|
BOX_W equ 4
|
||||||
|
BOX_H equ 6
|
||||||
|
; --- size of the Box structure
|
||||||
|
SIZEOF_BOX equ 8
|
||||||
|
|
||||||
|
; --- offsets to parts of the TMPRAS structure
|
||||||
|
TMPRAS_SEG equ 0
|
||||||
|
TMPRAS_SIZE equ 2
|
||||||
|
|
||||||
|
; --- offsets to parts of the RASTPORT structure
|
||||||
|
RASTPORT_BITMAP equ 0
|
||||||
|
RASTPORT_MODE equ 2
|
||||||
|
RASTPORT_COLOR equ 4
|
||||||
|
|
||||||
|
; bitmap.flags values
|
||||||
|
EGA_BANK_SWITCH equ 1
|
||||||
|
LINEAR_BITMAP equ 2
|
||||||
|
NEED_BYTE_ALIGNMENT equ 4
|
||||||
|
|
||||||
|
; properties of screen formats
|
||||||
|
COLOR_CYCLE equ 1h ; can color cycle
|
||||||
|
MONO_MODE equ 2h ; mode is on mono screen
|
||||||
|
CGA_MODE equ 4h ; mode needs CGA adapter
|
||||||
|
EGA_MODE equ 8h ; mode needs EGA adapter
|
||||||
|
MCGA_MODE equ 10h ; mode needs MCGA adapter
|
||||||
|
VGA_MODE equ 20h ; mode needs VGA adapter
|
||||||
|
TANDY_MODE equ 40h ; mode needs TGA (Tandy) adapter
|
||||||
|
|
||||||
|
; from event.c
|
||||||
|
MAX_CURSOR_H equ 11
|
||||||
@@ -0,0 +1,255 @@
|
|||||||
|
/*--misc.c----------------------------------------------------------
|
||||||
|
* Miscellaneous routines.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include "anim.h"
|
||||||
|
|
||||||
|
#define local static
|
||||||
|
|
||||||
|
extern BOOL EscFlag;
|
||||||
|
extern WORD curFrame;
|
||||||
|
extern BITMAP hidbm, prevFrame;
|
||||||
|
|
||||||
|
/* --------------- BugExit, EmergencyExit ---------------
|
||||||
|
*/
|
||||||
|
BugExit(char *s)
|
||||||
|
{
|
||||||
|
printf("Program Bug: %s.\n", s);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
EmergencyExit(char *s)
|
||||||
|
{
|
||||||
|
printf("%s.\n", s);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
NotEnoughMemExit()
|
||||||
|
{
|
||||||
|
EmergencyExit("Not enough memory to run this program");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------- AbortKeyHit, CheckAbort ---------------
|
||||||
|
*/
|
||||||
|
#define ESC 0x1b
|
||||||
|
|
||||||
|
local BOOL AbortKeyHit()
|
||||||
|
{
|
||||||
|
register WORD i;
|
||||||
|
|
||||||
|
while (char_avail()) { /* Consume keys, looking for ESC. */
|
||||||
|
i = get_char();
|
||||||
|
if (i == ESC) {
|
||||||
|
EscFlag = TRUE; /* Remember ESC was hit. */
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FALSE; /* Abort key not seen. */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Once abort key has been hit, further checks see EscFlag. */
|
||||||
|
BOOL CheckAbort()
|
||||||
|
{
|
||||||
|
return (EscFlag || AbortKeyHit());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------- --------------- */
|
||||||
|
#define bitmap_offs(bm, x, y) (x + (bm)->width * (y))
|
||||||
|
#define BytesNeeded(pix) EVEN_UP(pix) /* one byte-per-pixel */
|
||||||
|
/* Must be whole # words. */
|
||||||
|
|
||||||
|
/* --------------- BMLineStart ---------------
|
||||||
|
* Returns a far pointer to the start of line y
|
||||||
|
* of the given plane in the bitmap.
|
||||||
|
*/
|
||||||
|
|
||||||
|
WORD far *BMLineStart(BITMAP *bm, WORD y, WORD plane)
|
||||||
|
{
|
||||||
|
return (WORD_FAR_PTR(bm->seg[plane], bitmap_offs(bm, 0, y)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------- init_bitmap ---------------
|
||||||
|
*/
|
||||||
|
init_bitmap(bm, width, height)
|
||||||
|
register BITMAP *bm;
|
||||||
|
WORD width, height;
|
||||||
|
{
|
||||||
|
bm->width = BytesNeeded(width);
|
||||||
|
bm->box.x = 0;
|
||||||
|
bm->box.y = 0;
|
||||||
|
bm->box.w = width;
|
||||||
|
bm->box.h = height;
|
||||||
|
bm->planes = curDepth;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------- NewBitMap ---------------
|
||||||
|
* CAUTION: only call when have NOT allocated bm->seg[]'s.
|
||||||
|
*/
|
||||||
|
NewBitMap(BITMAP *bm, WORD width, WORD height)
|
||||||
|
{
|
||||||
|
init_bitmap(bm, width, height);
|
||||||
|
bm->seg[0] = DAlloc(N_BYTES_IN_BITMAP);
|
||||||
|
if (!bm->seg[0])
|
||||||
|
NotEnoughMemExit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------- SetBitMap ---------------
|
||||||
|
*/
|
||||||
|
void SetBitMap(BITMAP *bm, WORD color)
|
||||||
|
{
|
||||||
|
far_setmem(bm->seg[0], 0, N_BYTES_IN_BITMAP, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------- FirstAnimFrame ---------------
|
||||||
|
* Switch to first frame for editing.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Read into lpBuffer, but don't transfer to hidbm.
|
||||||
|
* This gets all the pointers correctly set-up, so that hidbm can
|
||||||
|
* become the new first frame (by calling AnimSetDirtyBox).
|
||||||
|
*/
|
||||||
|
FirstAnimFrame00() {
|
||||||
|
curFrame = FIRST_FRAME_N;
|
||||||
|
ReadLpfFrame(curFrame);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FirstAnimFrame0() {
|
||||||
|
/* --- Clear junk from prevFrame. */
|
||||||
|
far_setmem(BSEG(&prevFrame), 0, N_BYTES_IN_BITMAP, white_color);
|
||||||
|
|
||||||
|
FirstAnimFrame00();
|
||||||
|
PlayDeltaFrame(&hidbm);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------- CopyHidbmToPrevFrame ---------------
|
||||||
|
*/
|
||||||
|
local void CopyHidbmToPrevFrame(void) {
|
||||||
|
far_movmem( BSEG(&hidbm), 0,
|
||||||
|
BSEG(&prevFrame), 0, N_BYTES_IN_BITMAP );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------- NextAnimFrame0 ---------------
|
||||||
|
* Switch to next frame for editing.
|
||||||
|
*/
|
||||||
|
NextAnimFrame0() {
|
||||||
|
curFrame++;
|
||||||
|
|
||||||
|
if (curFrame > LAST_FRAME_N)
|
||||||
|
FirstAnimFrame0();
|
||||||
|
else {
|
||||||
|
/* (old) current frame is (next) prevFrame.
|
||||||
|
* Don't use PlayDeltaFrame, because didn't keep Delta in RAM. */
|
||||||
|
CopyHidbmToPrevFrame();
|
||||||
|
ReadLpfFrame(curFrame);
|
||||||
|
PlayDeltaFrame(&hidbm);
|
||||||
|
/* Convert old current frame to new current frame. */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------
|
||||||
|
* Disk i/o with critical error detection.
|
||||||
|
* -------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
/* returns -1 if it can't read the full number of bytes */
|
||||||
|
int readfull(int file, char *buffer, unsigned int count) {
|
||||||
|
return (readdos(file,dataseg(),buffer,count) == count) ? 0: -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* returns -1 if it can't read the full number of bytes */
|
||||||
|
int readdosfull(UWORD file, UWORD seg, UWORD buffer, UWORD count) {
|
||||||
|
return (readdos(file,seg,buffer,count) == count) ? 0: -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* returns -1 if it can't write the full number of bytes */
|
||||||
|
int writefull(int file, char *buffer, unsigned int count) {
|
||||||
|
return (writedos(file,dataseg(),buffer,count) == count) ? 0: -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* returns -1 if it can't write the full number of bytes */
|
||||||
|
int writedosfull(UWORD file, UWORD seg, UWORD buffer, UWORD count) {
|
||||||
|
return (writedos(file,seg,buffer,count) == count) ? 0: -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
long lseekdos(int file, long offset, int origin) {
|
||||||
|
long result = lseek(file,offset,origin);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------
|
||||||
|
* --------------- do_num_to_string -------------------------------
|
||||||
|
* Convert a number to a string. Parameters:
|
||||||
|
* UWORD num = # to convert to string.
|
||||||
|
* char *string = Ptr to string where you want the #.
|
||||||
|
* UWORD length = # of chars you want in the resulting string. Set to -1
|
||||||
|
* if you don't require any specific string length. If the string
|
||||||
|
* is too short, it will be padded with blanks on the left. If it
|
||||||
|
* is too long, it will be chopped off on the right.
|
||||||
|
* BOOL negative = Set to TRUE if you want numbers > 32767 to be printed
|
||||||
|
* as negative (with a leading "-"), or FALSE otherwise.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* TRUE before calling do_num_to_string, if want padding with 0's
|
||||||
|
* instead of blanks. Must set back to FALSE when done, so
|
||||||
|
* other clients will get ' 's.
|
||||||
|
*/
|
||||||
|
local BOOL padWithZeroes = FALSE;
|
||||||
|
|
||||||
|
void do_num_to_string(UWORD num, char *string, UWORD length, BOOL negative)
|
||||||
|
{
|
||||||
|
UWORD temp;
|
||||||
|
register UWORD index, i;
|
||||||
|
BOOL start;
|
||||||
|
|
||||||
|
index = 0;
|
||||||
|
|
||||||
|
/* --- does caller want negative # printed with leading '-'? */
|
||||||
|
if (negative && num >= 0x8000) {
|
||||||
|
if (index >= length) goto terminate;
|
||||||
|
num = -num;
|
||||||
|
string[index++] = '-';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- convert the # to a string */
|
||||||
|
if (num == 0) {
|
||||||
|
if (index >= length) goto terminate;
|
||||||
|
string[index++] = '0';
|
||||||
|
} else {
|
||||||
|
start = FALSE;
|
||||||
|
for (i = 10000; i > 0; i /= 10) {
|
||||||
|
temp = (num / i);
|
||||||
|
if (temp || start) {
|
||||||
|
/* --- if string has reached max length, stop */
|
||||||
|
if (index >= length) goto terminate;
|
||||||
|
string[index++] = temp + '0';
|
||||||
|
start = TRUE;
|
||||||
|
}
|
||||||
|
num %= i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- terminate the string */
|
||||||
|
terminate:
|
||||||
|
string[index] = 0;
|
||||||
|
|
||||||
|
/* --- if caller wants string to be at least a certain length, do it */
|
||||||
|
i = strlen(string);
|
||||||
|
if ((WORD)i < (WORD)length) {
|
||||||
|
/* --- string is too short, so add spaces to left */
|
||||||
|
while ((WORD)i < (WORD)length) {
|
||||||
|
movmem(string, string + 1, i + 1);
|
||||||
|
string[0] = (padWithZeroes ? '0' : ' ');
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------- num_to_string_zeroes ---------------
|
||||||
|
* Specified length, no negative, padding with zeroes.
|
||||||
|
*/
|
||||||
|
void num_to_string_zeroes(UWORD num, char *string, UWORD length) {
|
||||||
|
padWithZeroes = TRUE;
|
||||||
|
do_num_to_string(num, string, length, FALSE);
|
||||||
|
padWithZeroes = FALSE;
|
||||||
|
}
|
||||||
@@ -0,0 +1,848 @@
|
|||||||
|
;-----------------------------------------------------------------
|
||||||
|
; misca.asm
|
||||||
|
; ---------
|
||||||
|
; Miscellaneous minor assembly-language routines.
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
|
||||||
|
include asm.inc
|
||||||
|
include main.inc
|
||||||
|
include ega.inc
|
||||||
|
|
||||||
|
HEADER misca
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
|
||||||
|
; --- seg & offs of BIOS equipment flag word (we only use its lower byte)
|
||||||
|
EQUIP_SEG equ 40h
|
||||||
|
EQUIP_OFFS equ 10h
|
||||||
|
|
||||||
|
DSEG
|
||||||
|
|
||||||
|
; --- Most recent i/o error code. NOTE: if there was not an error,
|
||||||
|
; this is undefined.
|
||||||
|
public _ioError
|
||||||
|
_ioError dw 0
|
||||||
|
|
||||||
|
; --- used by shift_right
|
||||||
|
public right_shift_masks
|
||||||
|
right_shift_masks equ this word
|
||||||
|
db 11111111b, 11111111b
|
||||||
|
db 01111111b, 11111111b
|
||||||
|
db 00111111b, 11111111b
|
||||||
|
db 00011111b, 11111111b
|
||||||
|
db 00001111b, 11111111b
|
||||||
|
db 00000111b, 11111111b
|
||||||
|
db 00000011b, 11111111b
|
||||||
|
db 00000001b, 11111111b
|
||||||
|
db 00000000b, 11111111b
|
||||||
|
db 00000000b, 01111111b
|
||||||
|
db 00000000b, 00111111b
|
||||||
|
db 00000000b, 00011111b
|
||||||
|
db 00000000b, 00001111b
|
||||||
|
db 00000000b, 00000111b
|
||||||
|
db 00000000b, 00000011b
|
||||||
|
db 00000000b, 00000001b
|
||||||
|
|
||||||
|
; --- used by shift_left
|
||||||
|
left_shift_masks equ this word
|
||||||
|
db 11111111b, 11111111b
|
||||||
|
db 11111111b, 11111110b
|
||||||
|
db 11111111b, 11111100b
|
||||||
|
db 11111111b, 11111000b
|
||||||
|
db 11111111b, 11110000b
|
||||||
|
db 11111111b, 11100000b
|
||||||
|
db 11111111b, 11000000b
|
||||||
|
db 11111111b, 10000000b
|
||||||
|
db 11111111b, 00000000b
|
||||||
|
db 11111110b, 00000000b
|
||||||
|
db 11111100b, 00000000b
|
||||||
|
db 11111000b, 00000000b
|
||||||
|
db 11110000b, 00000000b
|
||||||
|
db 11100000b, 00000000b
|
||||||
|
db 11000000b, 00000000b
|
||||||
|
db 10000000b, 00000000b
|
||||||
|
|
||||||
|
ENDDS
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
|
||||||
|
PSEG misca
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
; WORD dataseg ();
|
||||||
|
; Returns the current value of the DS register.
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
|
||||||
|
public _dataseg
|
||||||
|
STARTPROC _dataseg
|
||||||
|
|
||||||
|
mov ax,ds
|
||||||
|
ret
|
||||||
|
|
||||||
|
ENDPROC _dataseg
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
; WORD codeseg ();
|
||||||
|
; Returns the current value of the CS register.
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
|
||||||
|
public _codeseg
|
||||||
|
STARTPROC _codeseg
|
||||||
|
|
||||||
|
mov ax,cs
|
||||||
|
ret
|
||||||
|
|
||||||
|
ENDPROC _codeseg
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
; void far_setmem (seg, offs, length, value);
|
||||||
|
; WORD seg, offs;
|
||||||
|
; UWORD length;
|
||||||
|
; WORD value;
|
||||||
|
; Set length bytes starting at seg:offs to value.
|
||||||
|
; NOTE: This could be optimized by using stosw if possible.
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
|
||||||
|
public _far_setmem
|
||||||
|
STARTPROC _far_setmem
|
||||||
|
|
||||||
|
push bp
|
||||||
|
mov bp,sp
|
||||||
|
push es
|
||||||
|
push si
|
||||||
|
push di
|
||||||
|
|
||||||
|
mov es,ARGB[bp] ; segment
|
||||||
|
mov di,ARGB+2[bp] ; offset
|
||||||
|
mov cx,ARGB+4[bp] ; count
|
||||||
|
mov al,ARGB+6[bp] ; value
|
||||||
|
jcxz far_setmem_done
|
||||||
|
cld
|
||||||
|
rep stosb
|
||||||
|
far_setmem_done:
|
||||||
|
pop di
|
||||||
|
pop si
|
||||||
|
pop es
|
||||||
|
pop bp
|
||||||
|
ret
|
||||||
|
|
||||||
|
ENDPROC _far_setmem
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
; void far_movmem (sseg, soffs, dseg, doffs, length);
|
||||||
|
; WORD sseg, soffs, dseg, doffs;
|
||||||
|
; UWORD length;
|
||||||
|
; Move length bytes starting at sseg:soffs to dseg:doffs.
|
||||||
|
; This proc doesn't handle overlapping source & dest.
|
||||||
|
; NOTE: Could speed this up by using WORD move!
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
|
||||||
|
public _far_movmem
|
||||||
|
STARTPROC _far_movmem
|
||||||
|
|
||||||
|
push bp
|
||||||
|
mov bp,sp
|
||||||
|
push ds
|
||||||
|
push es
|
||||||
|
push si
|
||||||
|
push di
|
||||||
|
|
||||||
|
mov ds,ARGB[bp] ; source seg
|
||||||
|
mov si,ARGB+2[bp] ; source offs
|
||||||
|
mov es,ARGB+4[bp] ; dest seg
|
||||||
|
mov di,ARGB+6[bp] ; dest offs
|
||||||
|
mov0:
|
||||||
|
mov cx,ARGB+8[bp] ; # bytes
|
||||||
|
jcxz far_movmem_done
|
||||||
|
move_left_to_right:
|
||||||
|
cld
|
||||||
|
rep movsb
|
||||||
|
far_movmem_done:
|
||||||
|
pop di
|
||||||
|
pop si
|
||||||
|
pop es
|
||||||
|
pop ds
|
||||||
|
pop bp
|
||||||
|
ret
|
||||||
|
|
||||||
|
ENDPROC _far_movmem
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
; void far_movmem_same_seg(UWORD seg, UWORD soffs, UWORD doffs, UWORD length);
|
||||||
|
; Move length bytes starting at seg:soffs to seg:doffs,
|
||||||
|
; dealing with possible OVERLAP --
|
||||||
|
; when destination starts AFTER source, move RIGHT-TO-LEFT.
|
||||||
|
; NOTE: Could speed this up by using WORD move!
|
||||||
|
; NOTE: must have same register push/pop sequence as "_far_movmem".
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
|
||||||
|
public _far_movmem_same_seg
|
||||||
|
STARTPROC _far_movmem_same_seg
|
||||||
|
|
||||||
|
push bp
|
||||||
|
mov bp,sp
|
||||||
|
push ds
|
||||||
|
push es
|
||||||
|
push si
|
||||||
|
push di
|
||||||
|
|
||||||
|
mov ds,ARGB[bp] ; source seg
|
||||||
|
mov si,ARGB+2[bp] ; source offs
|
||||||
|
mov es,ARGB[bp] ; dest seg
|
||||||
|
mov di,ARGB+4[bp] ; dest offs
|
||||||
|
mov cx,ARGB+6[bp] ; # bytes
|
||||||
|
jcxz far_movmem_same_seg_done
|
||||||
|
|
||||||
|
cmp di,si
|
||||||
|
jbe move_left_to_right
|
||||||
|
|
||||||
|
std ; Backwards through memory.
|
||||||
|
add si,cx
|
||||||
|
dec si ; Address of last byte.
|
||||||
|
add di,cx
|
||||||
|
dec di ; Address of last byte.
|
||||||
|
rep movsb
|
||||||
|
far_movmem_same_seg_done:
|
||||||
|
cld
|
||||||
|
pop di
|
||||||
|
pop si
|
||||||
|
pop es
|
||||||
|
pop ds
|
||||||
|
pop bp
|
||||||
|
ret
|
||||||
|
|
||||||
|
ENDPROC _far_movmem_same_seg
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
; void far_swapmem (sseg, soffs, dseg, doffs, length);
|
||||||
|
; WORD sseg, soffs, dseg, doffs;
|
||||||
|
; UWORD length;
|
||||||
|
; Swap length bytes starting at sseg:soffs with dseg:doffs.
|
||||||
|
; This proc doesn't handle overlapping source & dest.
|
||||||
|
; NOTE: Could speed this up by using WORD operations! (and by using xchg)
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
|
||||||
|
public _far_swapmem
|
||||||
|
STARTPROC _far_swapmem
|
||||||
|
|
||||||
|
push bp
|
||||||
|
mov bp,sp
|
||||||
|
push ds
|
||||||
|
push es
|
||||||
|
push si
|
||||||
|
push di
|
||||||
|
|
||||||
|
mov ds,ARGB[bp] ; source seg
|
||||||
|
mov si,ARGB+2[bp] ; source offs
|
||||||
|
mov es,ARGB+4[bp] ; dest seg
|
||||||
|
mov di,ARGB+6[bp] ; dest offs
|
||||||
|
mov cx,ARGB+8[bp] ; # bytes
|
||||||
|
jcxz far_swapmem_done
|
||||||
|
cld
|
||||||
|
swap_loop:
|
||||||
|
mov al,[si]
|
||||||
|
mov bl,es:[di]
|
||||||
|
mov [si],bl
|
||||||
|
mov es:[di],al
|
||||||
|
inc si
|
||||||
|
inc di
|
||||||
|
loop swap_loop
|
||||||
|
far_swapmem_done:
|
||||||
|
pop di
|
||||||
|
pop si
|
||||||
|
pop es
|
||||||
|
pop ds
|
||||||
|
pop bp
|
||||||
|
ret
|
||||||
|
|
||||||
|
ENDPROC _far_swapmem
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
; LongFrac LFMULT (a, b);
|
||||||
|
; LongFrac a, b;
|
||||||
|
; Multiply two long fractions (ie, 32-bit fixed point numbers with 16 bits
|
||||||
|
; of binary fraction).
|
||||||
|
;
|
||||||
|
; register usage:
|
||||||
|
; [bp+ARGB] a.low
|
||||||
|
; [bp+ARGB+2] a.hi
|
||||||
|
; [bp+ARGB+4] b.lo
|
||||||
|
; [bp+ARGB+6] b.hi
|
||||||
|
; ax,dx = result (lo,hi)
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
|
||||||
|
public _LFMULT
|
||||||
|
STARTPROC _LFMULT
|
||||||
|
|
||||||
|
push bp
|
||||||
|
mov bp,sp
|
||||||
|
push di
|
||||||
|
push si
|
||||||
|
xor si,si
|
||||||
|
mov ax,[bp+ARGB+2]
|
||||||
|
test ax,ax ; a>0 ?
|
||||||
|
jns aplus
|
||||||
|
not word ptr [bp+ARGB+2] ; a = -a
|
||||||
|
neg word ptr [bp+ARGB]
|
||||||
|
sbb word ptr [bp+ARGB+2],0ffffh
|
||||||
|
not si
|
||||||
|
aplus: mov ax,[bp+ARGB+6]
|
||||||
|
test ax,ax ; b>0?
|
||||||
|
jns bplus
|
||||||
|
not word ptr [bp+ARGB+6] ; b = -b
|
||||||
|
neg word ptr [bp+ARGB+4]
|
||||||
|
sbb word ptr [bp+ARGB+6],0ffffh
|
||||||
|
not si
|
||||||
|
bplus: mov ax,[bp+ARGB] ; get a.lo
|
||||||
|
mul word ptr [bp+ARGB+4] ; a.lo*b.lo
|
||||||
|
mov bx,dx ; res.lo = highhalf(a.lo*b.lo)
|
||||||
|
mov ax,[bp+ARGB+2]
|
||||||
|
mul word ptr [bp+ARGB+6]; a.hi*b.hi
|
||||||
|
mov cx,ax ; res.hi = lowhalf(a.hi*b.hi)
|
||||||
|
mov ax,[bp+ARGB]
|
||||||
|
mul word ptr [bp+ARGB+6] ; a.lo*b.hi
|
||||||
|
add bx,ax
|
||||||
|
adc cx,dx
|
||||||
|
mov ax,[bp+ARGB+2]
|
||||||
|
mul word ptr [bp+ARGB+4] ; a.hi*b.lo
|
||||||
|
add ax,bx ; ax = lo
|
||||||
|
adc dx,cx ; dx = hi
|
||||||
|
test si,si
|
||||||
|
jns leave ; if (neg)
|
||||||
|
not dx ; res = -res
|
||||||
|
neg ax
|
||||||
|
sbb dx,0ffffh
|
||||||
|
leave:
|
||||||
|
pop si
|
||||||
|
pop di
|
||||||
|
pop bp
|
||||||
|
ret
|
||||||
|
|
||||||
|
ENDPROC _LFMULT
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
; Return TRUE if there is a char in the keyboard buffer, or FALSE otherwise.
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
|
||||||
|
public _char_avail
|
||||||
|
STARTPROC _char_avail
|
||||||
|
|
||||||
|
mov ah,1
|
||||||
|
int 16h
|
||||||
|
jz no_char_avail
|
||||||
|
mov ax,-1
|
||||||
|
ret
|
||||||
|
no_char_avail:
|
||||||
|
xor ax,ax
|
||||||
|
ret
|
||||||
|
|
||||||
|
ENDPROC _char_avail
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
; Get an "extended" char, where normal chars are in the range 0-255, and
|
||||||
|
; non-ascii chars (for example, the function keys) are >= 256.
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
|
||||||
|
public _get_char
|
||||||
|
STARTPROC _get_char
|
||||||
|
|
||||||
|
mov ah,0
|
||||||
|
int 16h
|
||||||
|
or al,al
|
||||||
|
jz gc_done
|
||||||
|
xor ah,ah
|
||||||
|
gc_done:
|
||||||
|
ret
|
||||||
|
|
||||||
|
ENDPROC _get_char
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
; set_ioError: if an io or critical error occurred, squirrels
|
||||||
|
; away the error code and clears did_crit_error and returns -1
|
||||||
|
;
|
||||||
|
; Assumes that the carry flag and ax are the results of the last
|
||||||
|
; io operation (int 21h).
|
||||||
|
;
|
||||||
|
; If no error occurred, ax is unchanged.
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
did_crit_error dw 0 ;NOTE: didn't include crit error handler in program.
|
||||||
|
|
||||||
|
STARTPROC set_ioError
|
||||||
|
pushf ; hold carry flag
|
||||||
|
|
||||||
|
test cs:did_crit_error, 0ffffh
|
||||||
|
jz noCritError
|
||||||
|
push cs:did_crit_error
|
||||||
|
pop _ioError
|
||||||
|
|
||||||
|
popflags
|
||||||
|
jmp short ioerr
|
||||||
|
|
||||||
|
noCritError:
|
||||||
|
popflags
|
||||||
|
jnc iodone ; okay; leave ax unchanged
|
||||||
|
mov _ioError,ax
|
||||||
|
ioerr:
|
||||||
|
mov cs:did_crit_error,0
|
||||||
|
mov ax,0ffffh ; return -1 for any error
|
||||||
|
iodone: ret
|
||||||
|
ENDPROC set_ioError
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
; Open Dos File: fileHandle = opendos (name, access);
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
|
||||||
|
public _opendos
|
||||||
|
STARTPROC _opendos
|
||||||
|
|
||||||
|
push bp
|
||||||
|
mov bp,sp
|
||||||
|
mov al,[bp+ARGB+2] ; get access code
|
||||||
|
mov dx,[bp+ARGB] ; pointer to name
|
||||||
|
mov ah,03dh
|
||||||
|
int 021h
|
||||||
|
call set_ioError
|
||||||
|
pop bp
|
||||||
|
ret
|
||||||
|
|
||||||
|
ENDPROC _opendos
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
; Create Dos File: fileHandle = creatdos (name);
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
|
||||||
|
public _creatdos
|
||||||
|
STARTPROC _creatdos
|
||||||
|
|
||||||
|
push bp
|
||||||
|
mov bp,sp
|
||||||
|
xor cx,cx ; attribute= normal files
|
||||||
|
mov dx,[bp+ARGB] ; pointer to name
|
||||||
|
mov ah,03ch
|
||||||
|
int 021h ; do open or create
|
||||||
|
|
||||||
|
jnb cdx ; if carry flag is set
|
||||||
|
mov ax,0FFFFh ; return -1
|
||||||
|
cdx:
|
||||||
|
pop bp
|
||||||
|
ret
|
||||||
|
|
||||||
|
ENDPROC _creatdos
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
; Close Dos File: closedos (filehandle);
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
|
||||||
|
public _closedos
|
||||||
|
STARTPROC _closedos
|
||||||
|
|
||||||
|
push bp
|
||||||
|
mov bp,sp
|
||||||
|
mov bx,[bp+ARGB] ; get file handle
|
||||||
|
mov ah,03eh
|
||||||
|
int 021h ; do read or write
|
||||||
|
pop bp
|
||||||
|
ret
|
||||||
|
|
||||||
|
ENDPROC _closedos
|
||||||
|
|
||||||
|
;----------------------------------------------------------------------
|
||||||
|
; Delete Dos File: deletedos (name);
|
||||||
|
;---------------------------------------------------------------------
|
||||||
|
|
||||||
|
public _deletedos
|
||||||
|
STARTPROC _deletedos
|
||||||
|
|
||||||
|
push bp
|
||||||
|
mov bp,sp
|
||||||
|
mov dx,ARGB[bp] ; pointer to name
|
||||||
|
mov ah,41h
|
||||||
|
int 21h ; delete file
|
||||||
|
call set_ioError
|
||||||
|
pop bp
|
||||||
|
ret
|
||||||
|
|
||||||
|
ENDPROC _deletedos
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
; Read from Dos File: nBytes = readdos (file, seg, offset, length);
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
|
||||||
|
O_FILE = ARGB
|
||||||
|
O_SEG = ARGB+2
|
||||||
|
O_OFFSET = ARGB+4
|
||||||
|
O_LENGTH = ARGB+6
|
||||||
|
|
||||||
|
public _readdos
|
||||||
|
STARTPROC _readdos
|
||||||
|
|
||||||
|
push bp
|
||||||
|
mov bp,sp
|
||||||
|
push ds
|
||||||
|
mov ah,3fh
|
||||||
|
mov bx,O_FILE[bp]
|
||||||
|
mov cx,O_LENGTH[bp]
|
||||||
|
mov ds,O_SEG[bp]
|
||||||
|
mov dx,O_OFFSET[bp]
|
||||||
|
int 021h
|
||||||
|
call set_ioError
|
||||||
|
pop ds
|
||||||
|
pop bp
|
||||||
|
ret
|
||||||
|
|
||||||
|
ENDPROC _readdos
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
; Write to Dos File: nBytes = writedos (file, seg, offset, length);
|
||||||
|
; RETURN -1 on error.
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
|
||||||
|
O_FILE = ARGB
|
||||||
|
O_SEG = ARGB+2
|
||||||
|
O_OFFSET = ARGB+4
|
||||||
|
O_LENGTH = ARGB+6
|
||||||
|
|
||||||
|
public _writedos
|
||||||
|
STARTPROC _writedos
|
||||||
|
|
||||||
|
push bp
|
||||||
|
mov bp,sp
|
||||||
|
push ds
|
||||||
|
mov ah,40h
|
||||||
|
mov bx,O_FILE[bp]
|
||||||
|
mov cx,O_LENGTH[bp]
|
||||||
|
mov ds,O_SEG[bp]
|
||||||
|
mov dx,O_OFFSET[bp]
|
||||||
|
int 021h
|
||||||
|
call set_ioError
|
||||||
|
pop ds
|
||||||
|
pop bp
|
||||||
|
ret
|
||||||
|
|
||||||
|
ENDPROC _writedos
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
; LFDIV (num, denom);
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
|
||||||
|
NUM = ARGB
|
||||||
|
DENOM = ARGB+4
|
||||||
|
|
||||||
|
public _LFDIV
|
||||||
|
STARTPROC _LFDIV
|
||||||
|
|
||||||
|
push bp
|
||||||
|
mov bp,sp
|
||||||
|
|
||||||
|
; neg = FALSE
|
||||||
|
xor cx,cx
|
||||||
|
|
||||||
|
; if (num < 0) { num = -num; neg = !neg; }
|
||||||
|
cmp word ptr NUM+2[bp],0
|
||||||
|
jge lfdiv1
|
||||||
|
mov ax,NUM[bp] ; num = -num
|
||||||
|
mov dx,NUM+2[bp]
|
||||||
|
neg ax
|
||||||
|
adc dx,0
|
||||||
|
neg dx
|
||||||
|
mov NUM[bp],ax
|
||||||
|
mov NUM+2[bp],dx
|
||||||
|
not cx ; neg = !neg
|
||||||
|
lfdiv1:
|
||||||
|
|
||||||
|
; if (denom < 0) { denom = -denom; neg = !neg; }
|
||||||
|
cmp word ptr DENOM+2[bp],0
|
||||||
|
jge lfdiv2
|
||||||
|
mov ax,DENOM[bp] ; denom = -denom
|
||||||
|
mov dx,DENOM+2[bp]
|
||||||
|
neg ax
|
||||||
|
adc dx,0
|
||||||
|
neg dx
|
||||||
|
mov DENOM[bp],ax
|
||||||
|
mov DENOM+2[bp],dx
|
||||||
|
not cx ; neg = !neg
|
||||||
|
lfdiv2:
|
||||||
|
|
||||||
|
; while (denom >= 0x10000) { num >>= 1; denom >>= 1; }
|
||||||
|
mov bx,cx ; save neg in bx
|
||||||
|
lfdiv5:
|
||||||
|
mov cx,DENOM+2[bp]
|
||||||
|
jcxz lfdiv3
|
||||||
|
sar word ptr NUM+2[bp],1 ; num >>= 1
|
||||||
|
rcr word ptr NUM[bp],1
|
||||||
|
sar word ptr DENOM+2[bp],1 ; denom >>= 1
|
||||||
|
rcr word ptr DENOM[bp],1
|
||||||
|
jmp lfdiv5
|
||||||
|
lfdiv3:
|
||||||
|
mov cx,bx ; restore neg to cx
|
||||||
|
|
||||||
|
; high word of result = num / denom
|
||||||
|
mov ax,NUM[bp]
|
||||||
|
mov dx,NUM+2[bp]
|
||||||
|
cmp dx,DENOM[bp] ; test for overflow
|
||||||
|
jb no_overflow
|
||||||
|
mov ax,7fffh ; overflow, so use a large #
|
||||||
|
xor dx,dx
|
||||||
|
jmp lfdiv6
|
||||||
|
no_overflow:
|
||||||
|
div word ptr DENOM[bp]
|
||||||
|
mov bx,ax
|
||||||
|
|
||||||
|
; low word of result = ((num % denom) << 16) / denom
|
||||||
|
lfdiv6:
|
||||||
|
xor ax,ax
|
||||||
|
div word ptr DENOM[bp]
|
||||||
|
mov dx,bx ; dx = high word of result
|
||||||
|
|
||||||
|
; if (neg) result = -result;
|
||||||
|
jcxz lfdiv4
|
||||||
|
neg ax
|
||||||
|
adc dx,0
|
||||||
|
neg dx
|
||||||
|
lfdiv4:
|
||||||
|
|
||||||
|
pop bp
|
||||||
|
ret
|
||||||
|
|
||||||
|
ENDPROC _LFDIV
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
; WORD get_first_mcb ();
|
||||||
|
; Returns address of first MCB in DOS free memory list.
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
|
||||||
|
public _get_first_mcb
|
||||||
|
STARTPROC _get_first_mcb
|
||||||
|
|
||||||
|
mov ah,52h
|
||||||
|
int 21h
|
||||||
|
mov ax,es:[bx-2]
|
||||||
|
ret
|
||||||
|
|
||||||
|
ENDPROC _get_first_mcb
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
; WORD cdist (a, b);
|
||||||
|
; LONG a, b;
|
||||||
|
; Calculate the distance between RGB color values a and b. This is
|
||||||
|
; done using the sum of the absolute R,G,B deltas. It would be more
|
||||||
|
; accurate (but much slower) to calculate the actual distance between them.
|
||||||
|
;
|
||||||
|
; Improved: absdR + absdG + absdB + MAX(absdR, absdG, absdB).
|
||||||
|
; This approximates the sum of squares, by forcing large component to
|
||||||
|
; have double contribution to error term.
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
|
||||||
|
A = ARGB
|
||||||
|
B = ARGB+4
|
||||||
|
|
||||||
|
public _cdist
|
||||||
|
STARTPROC _cdist
|
||||||
|
|
||||||
|
push bp
|
||||||
|
mov bp,sp
|
||||||
|
|
||||||
|
; --- clear top half of ax so we can use it as a word
|
||||||
|
sub ah,ah
|
||||||
|
|
||||||
|
; --- get absolute distance between BLUE coords, put result in bx
|
||||||
|
mov bl,A[bp]
|
||||||
|
mov cl,B[bp]
|
||||||
|
cmp bl,cl
|
||||||
|
jae cdist_p1
|
||||||
|
xchg bl,cl
|
||||||
|
cdist_p1:
|
||||||
|
sub bl,cl
|
||||||
|
sub bh,bh ; BX: abs(delta R).
|
||||||
|
|
||||||
|
mov dx,bx ; dx will be MAX.
|
||||||
|
|
||||||
|
; --- get absolute distance between GREEN coords, add to bx
|
||||||
|
mov al,A+1[bp]
|
||||||
|
mov cl,B+1[bp]
|
||||||
|
cmp al,cl
|
||||||
|
jae cdist_p2
|
||||||
|
xchg al,cl
|
||||||
|
cdist_p2:
|
||||||
|
sub al,cl
|
||||||
|
add bx,ax ; BX: absdR + absdG.
|
||||||
|
|
||||||
|
cmp dx,ax
|
||||||
|
jge cdist_R_ge_G
|
||||||
|
mov dx,ax
|
||||||
|
cdist_R_ge_G: ; DX: MAX(absdR, absdG).
|
||||||
|
|
||||||
|
; --- get absolute distance between RED coords, add bx to this value
|
||||||
|
mov al,A+2[bp]
|
||||||
|
mov cl,B+2[bp]
|
||||||
|
cmp al,cl
|
||||||
|
jae cdist_p3
|
||||||
|
xchg al,cl
|
||||||
|
cdist_p3:
|
||||||
|
sub al,cl
|
||||||
|
add ax,bx ; AX: absdR + absdG + absdB.
|
||||||
|
|
||||||
|
cmp dx,ax
|
||||||
|
jge cdist_RG_ge_B
|
||||||
|
mov dx,ax
|
||||||
|
cdist_RG_ge_B: ; DX: MAX(absdR, absdG, absdB).
|
||||||
|
|
||||||
|
add ax,dx ; AX: absdR + absdG + absdB + MAX(...).
|
||||||
|
|
||||||
|
pop bp
|
||||||
|
ret
|
||||||
|
|
||||||
|
ENDPROC _cdist
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
; void dos_print_string (string);
|
||||||
|
; char *string;
|
||||||
|
; Call DOS to print the given string, in text mode. The string should
|
||||||
|
; not contain a '$', since DOS will treat that as the end of the string,
|
||||||
|
; and not print any chars after that!
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
|
||||||
|
public _dos_print_string
|
||||||
|
STARTPROC _dos_print_string
|
||||||
|
|
||||||
|
push bp
|
||||||
|
mov bp,sp
|
||||||
|
push si
|
||||||
|
|
||||||
|
; --- replace the NULL terminator with a '$', like DOS wants
|
||||||
|
mov si,ARGB[bp]
|
||||||
|
dec si
|
||||||
|
find_dollar:
|
||||||
|
inc si
|
||||||
|
mov al,[si]
|
||||||
|
or al,al
|
||||||
|
jnz find_dollar
|
||||||
|
mov byte ptr [si],'$'
|
||||||
|
|
||||||
|
; --- call DOS to print the string
|
||||||
|
push si
|
||||||
|
mov ah,9
|
||||||
|
mov dx,ARGB[bp]
|
||||||
|
int 21h
|
||||||
|
pop si
|
||||||
|
|
||||||
|
; --- restore NULL string terminator
|
||||||
|
mov byte ptr [si],0
|
||||||
|
|
||||||
|
pop si
|
||||||
|
pop bp
|
||||||
|
ret
|
||||||
|
|
||||||
|
ENDPROC _dos_print_string
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
; Allocate Memory: segment = allocsome (paragraphs, &size)
|
||||||
|
; Will allocate request or largest remaining, whichever is bigger.
|
||||||
|
; Returns segment = 0 if failed. Puts number of paragraphs actually
|
||||||
|
; allocated into *size.
|
||||||
|
; Right now, this is only used by FixTandyMemory.
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
|
||||||
|
public _allocsome
|
||||||
|
STARTPROC _allocsome
|
||||||
|
|
||||||
|
push bp
|
||||||
|
mov bp,sp
|
||||||
|
mov bx,[bp+ARGB]
|
||||||
|
allocscont:
|
||||||
|
mov di,[bp+ARGB+2]
|
||||||
|
mov [di],bx ; return number of words allocated
|
||||||
|
mov ax,0
|
||||||
|
cmp ax,bx
|
||||||
|
je allocsret ; fail nothing requested
|
||||||
|
mov ax,04800h
|
||||||
|
int 021h ; execute DOS function
|
||||||
|
jnc allocsret
|
||||||
|
mov cx,ax
|
||||||
|
mov ax,0 ; error: return NIL
|
||||||
|
cmp cx,7 ; arena trashed
|
||||||
|
jne allocscont ; keep trying until we alloc max left or fail
|
||||||
|
allocsret:
|
||||||
|
pop bp
|
||||||
|
ret
|
||||||
|
|
||||||
|
ENDPROC _allocsome
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
; LONG FreeDiskSpace (drive);
|
||||||
|
; WORD drive; /* 0 = drive A, 1 = drive B, etc... */
|
||||||
|
; Returns free disk space in bytes on the specified drive. If there
|
||||||
|
; is an error accessing that drive, it returns 0.
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
|
||||||
|
public _FreeDiskSpace
|
||||||
|
STARTPROC _FreeDiskSpace
|
||||||
|
|
||||||
|
push bp
|
||||||
|
mov bp,sp
|
||||||
|
|
||||||
|
mov ah,36h
|
||||||
|
mov dl,ARGB[bp]
|
||||||
|
inc dl ; this func uses 1 = drive A, 2 = drive B...
|
||||||
|
int 21h
|
||||||
|
cmp ax,0ffffh
|
||||||
|
jne fds_no_error
|
||||||
|
; --- error getting info, so return 0
|
||||||
|
xor ax,ax
|
||||||
|
xor dx,dx
|
||||||
|
jmp fds_done
|
||||||
|
; --- no error, so return (sectorsPerCluster * bytesPerSector * freeClusters)
|
||||||
|
; NOTE: we assume that sectorsPerCluster * bytesPerSector < 64k.
|
||||||
|
fds_no_error:
|
||||||
|
mul cx
|
||||||
|
mul bx
|
||||||
|
fds_done:
|
||||||
|
pop bp
|
||||||
|
ret
|
||||||
|
|
||||||
|
ENDPROC _FreeDiskSpace
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
; LONG GetSystemTime ();
|
||||||
|
; Returns the number of timer ticks (18.2 per second) since midnight.
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
|
||||||
|
public _GetSystemTime
|
||||||
|
STARTPROC _GetSystemTime
|
||||||
|
|
||||||
|
mov ah,0
|
||||||
|
int 1ah
|
||||||
|
mov ax,dx ; move low word to ax
|
||||||
|
mov dx,cx ; move high word to dx
|
||||||
|
ret
|
||||||
|
|
||||||
|
ENDPROC _GetSystemTime
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
; name WordMulDiv --
|
||||||
|
;
|
||||||
|
; c = (a*num)/denom;
|
||||||
|
;
|
||||||
|
; UWORD muldiv(a,num,denom) UWORD a,num,denom;
|
||||||
|
;
|
||||||
|
; register usage
|
||||||
|
; [bp+ARGB] a
|
||||||
|
; [bp+ARGB+2] num
|
||||||
|
; [bp+ARGB+4] denom
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
|
||||||
|
public _WordMulDiv
|
||||||
|
STARTPROC _WordMulDiv
|
||||||
|
push bp
|
||||||
|
mov bp,sp
|
||||||
|
mov ax,[bp+ARGB]
|
||||||
|
mul word ptr[bp+ARGB+2]
|
||||||
|
div word ptr[bp+ARGB+4]
|
||||||
|
pop bp
|
||||||
|
ret
|
||||||
|
ENDPROC _WordMulDiv
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
|
||||||
|
ENDPS misca
|
||||||
|
END
|
||||||
@@ -0,0 +1,387 @@
|
|||||||
|
/*--pbio.c----------------------------------------------------------*
|
||||||
|
* *
|
||||||
|
* Routines to read & write PC Paintbrush files. *
|
||||||
|
* *
|
||||||
|
* Date Who Changes *
|
||||||
|
* --------- --- -------------------------------------------------- *
|
||||||
|
* 31-Mar-89 mjc band read & write to allow large files. *
|
||||||
|
* 19-Apr-89 mjc 256 color palette added at end of paintbrush file. *
|
||||||
|
* *
|
||||||
|
* TBD: haven't added scroll-offset logic to "to planar" case, since
|
||||||
|
* ANIMDISK is only 8 bpp.
|
||||||
|
*------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <sys\types.h>
|
||||||
|
#include <sys\stat.h>
|
||||||
|
#include <io.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define local static
|
||||||
|
|
||||||
|
/* RowBytes computes the number of bytes in a row, from the width in pixels.*/
|
||||||
|
#define RowBytes(w) (((w) + 15) >> 4 << 1)
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------
|
||||||
|
* 256 Color Palette
|
||||||
|
*
|
||||||
|
* When reading the paintbrush file, the 256 color palette is
|
||||||
|
* sought only if the version number in the header is 5 and the
|
||||||
|
* bits per pixel * planes == 8. The last 769 bytes of the file
|
||||||
|
* must start with 0x0C, and be followed by the 768 byte palette.
|
||||||
|
*
|
||||||
|
* When writing the paintbrush file, we write
|
||||||
|
* version 5 in the header, and append the palette to the end of
|
||||||
|
* the file in the same format as above (0x0C followed by 768
|
||||||
|
* bytes of palette).
|
||||||
|
*------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Return SUCCESS, FAIL, or specific errors ... */
|
||||||
|
#define PB_NOT_ENUF_MEM 2
|
||||||
|
#define PB_NO_256_PALETTE 3
|
||||||
|
|
||||||
|
local WORD readCount; /* For compression. */
|
||||||
|
local UBYTE readChar;
|
||||||
|
|
||||||
|
/* --- Forward declarations. */
|
||||||
|
void GetByte(WORD file);
|
||||||
|
BOOL PutBytes(BYTE far * ptr, WORD bytes, WORD file);
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------*/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
BYTE manufacturer;
|
||||||
|
BYTE version;
|
||||||
|
BYTE encoding;
|
||||||
|
BYTE bitsperpixel;
|
||||||
|
WORD xmin, ymin, xmax, ymax;
|
||||||
|
WORD hres, vres;
|
||||||
|
BYTE colormap[16][3];
|
||||||
|
BYTE reserved;
|
||||||
|
BYTE nplanes;
|
||||||
|
WORD bytesperline;
|
||||||
|
} PCPAINTBRUSH_HEADER;
|
||||||
|
|
||||||
|
local PCPAINTBRUSH_HEADER *pbh = NULL; /* paintbrush header pointer */
|
||||||
|
/* Global pointer so can allocate in header, use fields in body. */
|
||||||
|
|
||||||
|
/*--------------------- Bad Paintbrush Header ----------------------*/
|
||||||
|
#define BadPbHeader(s) (FAIL)
|
||||||
|
|
||||||
|
/*-------------------- Invalid Paintbrush File ---------------------*/
|
||||||
|
#define InvalidPbFile() (FAIL)
|
||||||
|
|
||||||
|
#define WrongPbFileType() (FAIL) /* Expected different data format.*/
|
||||||
|
#define PCXNo256PaletteMsg()
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------*
|
||||||
|
* Read the header of a pc paintbrush file.
|
||||||
|
* Sets bmHdr fields. Calls reSize if necessary.
|
||||||
|
* Returns SUCCESS or FAIL.
|
||||||
|
*-----------------------------------------------------------------*/
|
||||||
|
|
||||||
|
BOOL ReadPCX_Header(WORD file, BITMAP *bitmap, LONG *palette,
|
||||||
|
BitMapHeader *bmHdr)
|
||||||
|
{
|
||||||
|
register WORD i;
|
||||||
|
UBYTE c, palet[256][3];
|
||||||
|
|
||||||
|
if (!pbh) /* Test in case we come through twice w/o freeing. */
|
||||||
|
pbh = malloc(sizeof(PCPAINTBRUSH_HEADER) + 4);
|
||||||
|
if (!pbh)
|
||||||
|
return (FAIL);
|
||||||
|
|
||||||
|
if (read(file, (char *)pbh, sizeof(PCPAINTBRUSH_HEADER)) !=
|
||||||
|
sizeof(PCPAINTBRUSH_HEADER))
|
||||||
|
return (InvalidPbFile());
|
||||||
|
|
||||||
|
/* --- To start of pixel data. */
|
||||||
|
if (0 > lseek(file, (LONG) 128, SEEK_SET))
|
||||||
|
return (InvalidPbFile());
|
||||||
|
|
||||||
|
/* --- Check that the header info is valid. */
|
||||||
|
if (pbh->manufacturer != 10)
|
||||||
|
return (InvalidPbFile());
|
||||||
|
|
||||||
|
/* --- Expecting version with palette at end. */
|
||||||
|
if (pbh->version != 5)
|
||||||
|
return (BadPbHeader(s_wrongPBVersion));
|
||||||
|
|
||||||
|
if (pbh->encoding != 1)
|
||||||
|
return (BadPbHeader(s_unknownEncoding));
|
||||||
|
|
||||||
|
if (pbh->bitsperpixel != 1 && pbh->nplanes != 1)
|
||||||
|
return (BadPbHeader(s_wrongLayout));
|
||||||
|
|
||||||
|
if (pbh->bitsperpixel != 8)
|
||||||
|
return (WrongPbFileType());
|
||||||
|
|
||||||
|
/* --- Compute dimensions and # colors. */
|
||||||
|
setmem(bmHdr, sizeof(BitMapHeader), 0);
|
||||||
|
bmHdr->w = 1 + pbh->xmax - pbh->xmin;
|
||||||
|
bmHdr->h = 1 + pbh->ymax - pbh->ymin;
|
||||||
|
bmHdr->nPlanes = pbh->bitsperpixel * pbh->nplanes;
|
||||||
|
/* MAY BE PACKED. */
|
||||||
|
|
||||||
|
/* --- Get the color map. */
|
||||||
|
if (palette != NULL) {
|
||||||
|
/* If a 256 color palette should be present at the end of the
|
||||||
|
* file, try to fetch it from disk and copy it to the palette.
|
||||||
|
*/
|
||||||
|
c = 0;
|
||||||
|
if (lseek(file, (LONG)-769, SEEK_END) >= 0)
|
||||||
|
if (read(file, &c, 1) == 1)
|
||||||
|
if (read(file, (UBYTE *)&palet[0][0], 768) == 768)
|
||||||
|
if (c == 0x0C)
|
||||||
|
for (i = 0; i < 256; ++i)
|
||||||
|
palette[i] = ((LONG)palet[i][0] << 16) +
|
||||||
|
((LONG)palet[i][1] << 8) +
|
||||||
|
((LONG)palet[i][2]);
|
||||||
|
/* --- To start of pixel data (again). */
|
||||||
|
lseek(file, (LONG)128, SEEK_SET);
|
||||||
|
if (c != 0x0C) {
|
||||||
|
/* ---- We couldn't read a 256 color palette at the end
|
||||||
|
* of the file.
|
||||||
|
*/
|
||||||
|
PCXNo256PaletteMsg();
|
||||||
|
return (PB_NO_256_PALETTE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (SUCCESS); /* Header done; BODY yet to do. */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------*
|
||||||
|
* Read the pixel data into the bitmap. Return SUCCESS or FAIL.
|
||||||
|
*-----------------------------------------------------------------*/
|
||||||
|
#define MaxPCXPlanes 8 /* 256-color, no mask. */
|
||||||
|
|
||||||
|
BOOL ReadPCX_BODY(WORD file, BITMAP *bitmap, BitMapHeader *bmHdr)
|
||||||
|
{
|
||||||
|
register WORD i, iPlane;
|
||||||
|
BOOL result = SUCCESS;
|
||||||
|
BYTE far *dest;
|
||||||
|
WORD bodyNRows, srcPlanesToUse;
|
||||||
|
WORD bodyIRow; /* Increment from 0..bodyNRows-1. */
|
||||||
|
BYTE far *dests[MaxPCXPlanes]; /* Ptrs to dest scan lines. */
|
||||||
|
WORD useBytes;
|
||||||
|
|
||||||
|
/* --------- Initialization. ---------- */
|
||||||
|
readCount = 0; /* For compression. */
|
||||||
|
|
||||||
|
bodyNRows = MIN(bmHdr->h, bitmap->box.h);
|
||||||
|
srcPlanesToUse = MIN(bitmap->planes + bpp_minus1, bmHdr->nPlanes);
|
||||||
|
|
||||||
|
/* ---------- Read all scan lines. ---------- */
|
||||||
|
OpenIOBuffer(FALSE);
|
||||||
|
|
||||||
|
for (bodyIRow = 0; bodyIRow < bodyNRows; ++bodyIRow) {
|
||||||
|
readCount = 0; /* Just in case, supposed to start anew each line. */
|
||||||
|
|
||||||
|
useBytes = MIN(bitmap->width, pbh->bytesperline);
|
||||||
|
|
||||||
|
/* ----- Read a scan line. */
|
||||||
|
dest = (BYTE far *)BMLineStart(bitmap, bodyIRow, 0);
|
||||||
|
for (i = 0; i < pbh->bytesperline; i++) {
|
||||||
|
GetByte(file);
|
||||||
|
if (i < useBytes)
|
||||||
|
*dest++ = readChar;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CloseIOBuffer(file);
|
||||||
|
|
||||||
|
done:
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------- Close Paintbrush File ---------------------*/
|
||||||
|
/* --- NOTE: if change, must change WritePCX_Done, since it calls this. */
|
||||||
|
|
||||||
|
void ReadPCX_Done()
|
||||||
|
{
|
||||||
|
/* --- Free pbh, which is shared by header & body routines. */
|
||||||
|
if (pbh)
|
||||||
|
free(pbh);
|
||||||
|
pbh = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WritePCX_Done()
|
||||||
|
{
|
||||||
|
ReadPCX_Done();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------- Get Byte ---------------------------*/
|
||||||
|
/* Set readCount & readChar. At EOF or file error, returns 0's forever. */
|
||||||
|
|
||||||
|
void GetByte(WORD file)
|
||||||
|
{
|
||||||
|
UBYTE c;
|
||||||
|
|
||||||
|
/* --- if in the middle of a run of encoded bytes, don't read any
|
||||||
|
* more
|
||||||
|
*/
|
||||||
|
if (readCount > 0) {
|
||||||
|
--readCount;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
readCount = 0;
|
||||||
|
if (GReadOne(file, &c) != 1) {
|
||||||
|
sawEOF:
|
||||||
|
readCount = 32767; /* Huge count of 0's to pad the end. */
|
||||||
|
readChar = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((c & 0xc0) == 0xc0) {
|
||||||
|
readCount = (0x3f & c) - 1; /* "-1": consuming one of count. */
|
||||||
|
if (GReadOne(file, &c) != 1)
|
||||||
|
goto sawEOF;
|
||||||
|
}
|
||||||
|
readChar = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------*
|
||||||
|
Output File Routines & Variables
|
||||||
|
*----------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------*
|
||||||
|
Output header for a PC Paintbrush file with the given number
|
||||||
|
of bitsperpixel and planes. One of these two parms must be 1.
|
||||||
|
ASSUMES OKAY TO TRASH buffer[].
|
||||||
|
Returns SUCCESS or FAIL.
|
||||||
|
*---------------------------------------------------------------*/
|
||||||
|
|
||||||
|
BOOL WritePCX_Header(WORD file, BITMAP *bitmap, LONG *palette)
|
||||||
|
{
|
||||||
|
register PCPAINTBRUSH_HEADER *ppbh;
|
||||||
|
WORD i;
|
||||||
|
#define GAP_SIZE (128 - sizeof(PCPAINTBRUSH_HEADER))
|
||||||
|
UBYTE buffer1[GAP_SIZE];
|
||||||
|
|
||||||
|
/* --- init the header that we'll write.
|
||||||
|
* Note: since DPaint never reads & writes at the same time,
|
||||||
|
* it is okay to share the same read & write structure,
|
||||||
|
* unlike in CONVERT.EXE.
|
||||||
|
*/
|
||||||
|
if (!pbh) /* Test in case we come through twice w/o
|
||||||
|
* freeing. */
|
||||||
|
pbh = malloc(sizeof(PCPAINTBRUSH_HEADER) + 4);
|
||||||
|
if (!pbh)
|
||||||
|
return (FAIL);
|
||||||
|
ppbh = pbh; /* Register variable for smaller, faster code. */
|
||||||
|
|
||||||
|
setmem(ppbh, sizeof(PCPAINTBRUSH_HEADER) + 4, 0);
|
||||||
|
ppbh->manufacturer = 10;
|
||||||
|
ppbh->version = 5;
|
||||||
|
ppbh->encoding = 1;
|
||||||
|
|
||||||
|
ppbh->bitsperpixel = bpp;
|
||||||
|
ppbh->xmin = ppbh->ymin = 0;
|
||||||
|
ppbh->xmax = bitmap->box.w - 1;
|
||||||
|
ppbh->ymax = bitmap->box.h - 1;
|
||||||
|
ppbh->hres = N_COLUMNS;
|
||||||
|
ppbh->vres = N_LINES;
|
||||||
|
|
||||||
|
/* --- bytesperline doesn't take into account multiple planes.
|
||||||
|
* Output in same format as bitmap (planar vs packed).
|
||||||
|
*/
|
||||||
|
ppbh->bytesperline = bitmap->width;
|
||||||
|
|
||||||
|
ppbh->nplanes = bitmap->planes;
|
||||||
|
ppbh->reserved = 0;
|
||||||
|
|
||||||
|
/* --- First 16 colors of our palette info. */
|
||||||
|
for (i = 0; i < 16; ++i) {
|
||||||
|
ppbh->colormap[i][0] = (BYTE)(palette[i] >> 16);
|
||||||
|
ppbh->colormap[i][1] = (BYTE)(palette[i] >> 8);
|
||||||
|
ppbh->colormap[i][2] = (BYTE) palette[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- write the 128-byte header */
|
||||||
|
if (GWrite(file, (char *)ppbh, sizeof(PCPAINTBRUSH_HEADER))
|
||||||
|
!= sizeof(PCPAINTBRUSH_HEADER))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
setmem(buffer1, GAP_SIZE, 0);
|
||||||
|
if (GWrite(file, buffer1, GAP_SIZE) != GAP_SIZE)
|
||||||
|
error:
|
||||||
|
return (FAIL);
|
||||||
|
|
||||||
|
return (SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------- WritePCX_BODY ---------------
|
||||||
|
* Write the pixel data.
|
||||||
|
* Returns SUCCESS or an error condition.
|
||||||
|
* -------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
WORD WritePCX_BODY(WORD file, BITMAP *bitmap)
|
||||||
|
{
|
||||||
|
register WORD y;
|
||||||
|
|
||||||
|
/* --- Write to a bit-packed file. */
|
||||||
|
for (y = 0; y < bitmap->box.h; ++y) { /* for each line in band */
|
||||||
|
if (PutBytes((BYTE far *)BMLineStart(bitmap, y, 0),
|
||||||
|
pbh->bytesperline, file))
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-------------------- Output any 256-color palette ------------------------*/
|
||||||
|
BOOL WritePCX_256Palette(WORD file, LONG *palette)
|
||||||
|
{
|
||||||
|
register WORD i;
|
||||||
|
UBYTE c, palet[256][3];
|
||||||
|
|
||||||
|
if (pbh->version == 5 && pbh->bitsperpixel == 8) {
|
||||||
|
for (i = 0; i < 256; ++i) {
|
||||||
|
palet[i][0] = (BYTE)(palette[i] >> 16);
|
||||||
|
palet[i][1] = (BYTE)(palette[i] >> 8);
|
||||||
|
palet[i][2] = (BYTE) palette[i];
|
||||||
|
}
|
||||||
|
c = 0x0C;
|
||||||
|
if (GWrite(file, &c, 1) != 1 ||
|
||||||
|
GWrite(file, (char *)&palet[0][0], 768) != 768)
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------
|
||||||
|
* Write bytes to a file, handling packing as it goes.
|
||||||
|
* Returns SUCCESS or FAIL.
|
||||||
|
*-------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
BOOL PutBytes(BYTE far *ptr, WORD bytes, WORD file)
|
||||||
|
{
|
||||||
|
register WORD startbyte, count;
|
||||||
|
char b;
|
||||||
|
|
||||||
|
while (bytes > 0) {
|
||||||
|
/* --- check for a repeating byte value */
|
||||||
|
startbyte = *ptr++;
|
||||||
|
--bytes;
|
||||||
|
count = 1;
|
||||||
|
while (*ptr == startbyte && bytes > 0 && count < 63) {
|
||||||
|
++ptr;
|
||||||
|
--bytes;
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
/* --- If we can pack the sequence, or if we have to add a
|
||||||
|
* byte before it because the top 2 bits of the value
|
||||||
|
* are 1's, write a packed sequence of 2 bytes.
|
||||||
|
* Otherwise, just write the byte value.
|
||||||
|
*/
|
||||||
|
if (count > 1 || (startbyte & 0xc0) == 0xc0) {
|
||||||
|
b = 0xc0 | count;
|
||||||
|
if (GWrite(file, &b, 1) != 1)
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
b = startbyte;
|
||||||
|
if (GWrite(file, &b, 1) != 1)
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
|
||||||
|
Dear DeluxePaint Animation user:
|
||||||
|
|
||||||
|
Thank you for contacting us regarding the use of animation files created with
|
||||||
|
DeluxePaint Animation.
|
||||||
|
|
||||||
|
The enclosed files be useful for reading and writing animations from you own
|
||||||
|
application code or for converting animations to and from your own file
|
||||||
|
format. The files contain both an executable program as well as C source
|
||||||
|
code. For further details, please see the README.TXT file provided with these
|
||||||
|
files. For information on the ANM (animation) file format, please see the
|
||||||
|
comments in the LPFILE.C file.
|
||||||
|
|
||||||
|
The PCX and PCC format is available from a company called Z-Soft, they can be
|
||||||
|
contacted by calling 404-428-0008.
|
||||||
|
|
||||||
|
Please understand that these files and information are presented as is and
|
||||||
|
that we cannot provide technical support for the Programmer's Kit. However,
|
||||||
|
if you should have any questions concerning the operation of DeluxePaint
|
||||||
|
Animation, please do not hesitate to contact us.
|
||||||
|
|
||||||
|
Electronic Arts Multimedia Support
|
||||||
|
P.O. Box 7578
|
||||||
|
San Mateo, CA 94403-7578
|
||||||
|
(415) 572-2787
|
||||||
|
(415) 571-6552 FAX
|
||||||
|
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
|
||||||
|
Programmer's Kit for Version 1.0
|
||||||
|
DeluxePaint Animation 10/24/90
|
||||||
|
by Electronic Arts
|
||||||
|
|
||||||
|
----------------------
|
||||||
|
This kit has two uses:
|
||||||
|
|
||||||
|
1. It contains a program, ANIM2PCX.EXE, which is readily used to
|
||||||
|
(1) break an animation file into individual picture files for
|
||||||
|
each frame, or
|
||||||
|
(2) to join a group of picture files into an animation file for
|
||||||
|
editting in DPaint Animation or for playback with PLAY.EXE.
|
||||||
|
|
||||||
|
(PLAY.EXE is included in the DeluxePaint Animation package and may be
|
||||||
|
copied and distributed by anyone who has purchased DPaint Animation.)
|
||||||
|
|
||||||
|
The picture files are in the PCX format, which can be read by
|
||||||
|
DeluxePaint Animation, DeluxePaint II Enhanced and other paint programs,
|
||||||
|
and by desktop publishing programs and graphics-importing word processors.
|
||||||
|
|
||||||
|
For instructions on using the program as provided, type:
|
||||||
|
anim2pcx
|
||||||
|
|
||||||
|
|
||||||
|
2. Since the source code for ANIM2PCX is included on this disk,
|
||||||
|
a C programmer can access animations from his/her own application,
|
||||||
|
or write a converter between the ANM format and some other format,
|
||||||
|
by including the subroutines required to read and write ".ANM" files.
|
||||||
|
You will need all the enclosed .C, .H, .ASM, .INC files,
|
||||||
|
except for PBIO.C and GIO.C (which are used to read/write PCX files),
|
||||||
|
and ANIM2PCX.C (which is the main program that you will replace with
|
||||||
|
your own code).
|
||||||
|
For example, to read the frames of an anim, you might write code
|
||||||
|
similar to "AnimFileToPCXFiles()" routine in ANIM2PCX.C
|
||||||
|
|
||||||
|
The only existing documentation on the ANM format
|
||||||
|
is in comments in LPFILE.C.
|
||||||
|
|
||||||
|
|
||||||
|
---------------------
|
||||||
|
The source code for ANIM2PCX may be freely incorporated into
|
||||||
|
commercial programs.
|
||||||
|
|
||||||
|
Disclaimer:
|
||||||
|
THIS PROGRAM IS PROVIDED WITHOUT SEPARATE CHARGE AND IS
|
||||||
|
PROVIDED AS IS. ELECTRONIC ARTS DISCLAIMS ALL WARRANTIES,
|
||||||
|
INCLUDING IMPLIED WARRANTIES AND WARRANTIES OF
|
||||||
|
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
|
||||||
@@ -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;
|
||||||
|
|
||||||
|
|
||||||
@@ -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;
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
Long Description: Info and code on the DeluxePaint Animation .ANM file format
|
||||||
|
Tutorial: No
|
||||||
|
Sample Code: Yes
|
||||||
|
Utility/Tool: No
|
||||||
|
Notes: Nicely documented, and works.
|
||||||
Executable
+2
@@ -0,0 +1,2 @@
|
|||||||
|
anim2pcx %1
|
||||||
|
ren ????0???.pcx %1.pcx
|
||||||
Executable
+2
@@ -0,0 +1,2 @@
|
|||||||
|
\sc2\utils\anm\anim2pcx %1
|
||||||
|
ren *????.pcx %1*????.pcx
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
# Microsoft Developer Studio Project File - Name="anm2pcx" - Package Owner=<4>
|
||||||
|
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||||
|
# ** DO NOT EDIT **
|
||||||
|
|
||||||
|
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||||
|
|
||||||
|
CFG=anm2pcx - Win32 Debug
|
||||||
|
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||||
|
!MESSAGE use the Export Makefile command and run
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "anm2pcx.mak".
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE You can specify a configuration when running NMAKE
|
||||||
|
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "anm2pcx.mak" CFG="anm2pcx - Win32 Debug"
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE Possible choices for configuration are:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE "anm2pcx - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||||
|
!MESSAGE "anm2pcx - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||||
|
!MESSAGE
|
||||||
|
|
||||||
|
# Begin Project
|
||||||
|
# PROP AllowPerConfigDependencies 0
|
||||||
|
# PROP Scc_ProjName ""
|
||||||
|
# PROP Scc_LocalPath ""
|
||||||
|
CPP=cl.exe
|
||||||
|
RSC=rc.exe
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "anm2pcx - Win32 Release"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 0
|
||||||
|
# PROP BASE Output_Dir "Release"
|
||||||
|
# PROP BASE Intermediate_Dir "Release"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 0
|
||||||
|
# PROP Output_Dir "Release"
|
||||||
|
# PROP Intermediate_Dir "Release"
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||||
|
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||||
|
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||||
|
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "anm2pcx - Win32 Debug"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 1
|
||||||
|
# PROP BASE Output_Dir "Debug"
|
||||||
|
# PROP BASE Intermediate_Dir "Debug"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 1
|
||||||
|
# PROP Output_Dir "Debug"
|
||||||
|
# PROP Intermediate_Dir "Debug"
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||||
|
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||||
|
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||||
|
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# Begin Target
|
||||||
|
|
||||||
|
# Name "anm2pcx - Win32 Release"
|
||||||
|
# Name "anm2pcx - Win32 Debug"
|
||||||
|
# Begin Group "Source Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||||
|
# End Group
|
||||||
|
# Begin Group "Header Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||||
|
# End Group
|
||||||
|
# Begin Group "Resource Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||||
|
# End Group
|
||||||
|
# End Target
|
||||||
|
# End Project
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||||
|
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
Project: "anm2pcx"=".\anm2pcx.dsp" - Package Owner=<4>
|
||||||
|
|
||||||
|
Package=<5>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
Package=<4>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
Global:
|
||||||
|
|
||||||
|
Package=<5>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
Package=<3>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
@@ -0,0 +1,158 @@
|
|||||||
|
#include <windows.h>
|
||||||
|
#include <wingdi.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <GL/gl.h>
|
||||||
|
#include <GL/glu.h>
|
||||||
|
|
||||||
|
#include <SDL/SDL.h>
|
||||||
|
|
||||||
|
void process_input(void);
|
||||||
|
void init_sdl(void);
|
||||||
|
SDL_Surface *init_video(void);
|
||||||
|
void showLastError(char *c);
|
||||||
|
|
||||||
|
static char* font_names[] = { "SC2 Arilou", "SC2 Chmmr", "SC2 Earthling",
|
||||||
|
"SC2 Ilwrath", "SC2 Kohr-Ah", "SC2 Melnorme/Druuge", "SC2 Mycon",
|
||||||
|
"SC2 Orz", "SC2 Pkunk", "SC2 Shofixti", "SC2 Slylandro",
|
||||||
|
"SC2 Slylandro Probe", "SC2 Spathi", "SC2 Supox", "SC2 Syreen",
|
||||||
|
"SC2 Talking Pet", "SC2 Thraddash", "SC2 Umgah", "SC2 Ur-Quan",
|
||||||
|
"SC2 Utwig", "SC2 VUX", "SC2 Yehat", "SC2 ZoqFotPik" };
|
||||||
|
#define NUM_FONTS 23
|
||||||
|
int currentFont = 0;
|
||||||
|
|
||||||
|
void init(void) {
|
||||||
|
HDC hdc;
|
||||||
|
|
||||||
|
glClearColor(0.0, 0.0, 0.0, 0.0);
|
||||||
|
glShadeModel(GL_FLAT);
|
||||||
|
// glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void display(void) {
|
||||||
|
HDC hdc;
|
||||||
|
HGDIOBJ hgdiobj;
|
||||||
|
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
if ((hdc = wglGetCurrentDC()) == NULL) {
|
||||||
|
showLastError("wglGetCurrentDC failed");
|
||||||
|
}
|
||||||
|
if ((hgdiobj = SelectObject(hdc, CreateFont(0, 0, 0, 0, FW_DONTCARE,
|
||||||
|
FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
|
||||||
|
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE,
|
||||||
|
font_names[currentFont]))) == NULL) {
|
||||||
|
showLastError("SelectObject failed");
|
||||||
|
}
|
||||||
|
if (!wglUseFontBitmaps(hdc, 0, 255, 1000)) {
|
||||||
|
showLastError("wglUseFontBitmaps failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
glListBase(1000);
|
||||||
|
glRasterPos2d(-.9, .15);
|
||||||
|
glCallLists(strlen(font_names[currentFont]), GL_UNSIGNED_BYTE,
|
||||||
|
font_names[currentFont]);
|
||||||
|
glRasterPos2d(-.9, 0);
|
||||||
|
glCallLists(28, GL_UNSIGNED_BYTE, "Press UP/DOWN to change font");
|
||||||
|
glRasterPos2d(-.9, -.15);
|
||||||
|
glCallLists(23, GL_UNSIGNED_BYTE, "0123 ABC abc !@#$%^&*()");
|
||||||
|
|
||||||
|
if (DeleteObject(hgdiobj) == 0) {
|
||||||
|
showLastError("DeleteObject failed");
|
||||||
|
}
|
||||||
|
glFlush();
|
||||||
|
SDL_GL_SwapBuffers();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char*argv[]) {
|
||||||
|
SDL_Surface *screen;
|
||||||
|
|
||||||
|
init_sdl();
|
||||||
|
init_video();
|
||||||
|
init();
|
||||||
|
while (1) {
|
||||||
|
display();
|
||||||
|
process_input();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The following functions are mostly unimportant -- they just set up opengl and sdl
|
||||||
|
|
||||||
|
// Shows last Windows error in a message box using GetLastError()
|
||||||
|
void showLastError(char *c) {
|
||||||
|
LPVOID lpMsgBuf;
|
||||||
|
FormatMessage(
|
||||||
|
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
|
||||||
|
NULL,
|
||||||
|
GetLastError(),
|
||||||
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
||||||
|
(LPTSTR) &lpMsgBuf,
|
||||||
|
0,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
// Display the string.
|
||||||
|
MessageBox( NULL, lpMsgBuf, c, MB_OK|MB_ICONINFORMATION );
|
||||||
|
|
||||||
|
// Free the buffer.
|
||||||
|
LocalFree( lpMsgBuf );
|
||||||
|
}
|
||||||
|
|
||||||
|
//the following functions merely deal with OpenGL and SDL
|
||||||
|
|
||||||
|
void process_input(void) {
|
||||||
|
SDL_Event e;
|
||||||
|
|
||||||
|
while (SDL_PollEvent(&e)) {
|
||||||
|
switch (e.type) {
|
||||||
|
case SDL_KEYDOWN:
|
||||||
|
if (e.key.keysym.sym == SDLK_ESCAPE) {
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
if (e.key.keysym.sym == SDLK_UP) {
|
||||||
|
currentFont --;
|
||||||
|
if (currentFont < 0) {
|
||||||
|
currentFont = NUM_FONTS - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (e.key.keysym.sym == SDLK_DOWN) {
|
||||||
|
currentFont ++;
|
||||||
|
if (currentFont == NUM_FONTS) {
|
||||||
|
currentFont = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case SDL_QUIT:
|
||||||
|
exit(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_sdl(void) {
|
||||||
|
if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
|
||||||
|
fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
atexit(SDL_Quit);
|
||||||
|
|
||||||
|
SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 );
|
||||||
|
SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 );
|
||||||
|
SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );
|
||||||
|
SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );
|
||||||
|
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Surface *init_video(void) {
|
||||||
|
SDL_Surface *screen;
|
||||||
|
|
||||||
|
screen = SDL_SetVideoMode(640, 480, 16, SDL_SWSURFACE | SDL_OPENGL);
|
||||||
|
if ( screen == NULL ) {
|
||||||
|
fprintf(stderr, "Unable to set video: %s\n", SDL_GetError());
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return screen;
|
||||||
|
}
|
||||||
Executable
+74
@@ -0,0 +1,74 @@
|
|||||||
|
cd \sc2\src\3do_code\comm
|
||||||
|
cd arilou
|
||||||
|
\sc2\Utils\ndx arilou.res \sc2\Content\arilou.con
|
||||||
|
cd ..
|
||||||
|
cd blackur
|
||||||
|
\sc2\Utils\ndx blackur.res \sc2\Content\blackur.con
|
||||||
|
cd ..
|
||||||
|
cd chmmr
|
||||||
|
\sc2\Utils\ndx chmmr.res \sc2\Content\chmmr.con
|
||||||
|
cd ..
|
||||||
|
cd druuge
|
||||||
|
\sc2\Utils\ndx druuge.res \sc2\Content\druuge.con
|
||||||
|
cd ..
|
||||||
|
cd comandr
|
||||||
|
\sc2\Utils\ndx comandr.res \sc2\Content\comandr.con
|
||||||
|
cd ..
|
||||||
|
cd ilwrath
|
||||||
|
\sc2\Utils\ndx ilwrath.res \sc2\Content\ilwrath.con
|
||||||
|
cd ..
|
||||||
|
cd slyhome
|
||||||
|
\sc2\Utils\ndx slyhome.res \sc2\Content\slyhome.con
|
||||||
|
cd ..
|
||||||
|
cd melnorm
|
||||||
|
\sc2\Utils\ndx melnorm.res \sc2\Content\melnorm.con
|
||||||
|
cd ..
|
||||||
|
cd talkpet
|
||||||
|
\sc2\Utils\ndx talkpet.res \sc2\Content\talkpet.con
|
||||||
|
cd ..
|
||||||
|
cd mycon
|
||||||
|
\sc2\Utils\ndx mycon.res \sc2\Content\mycon.con
|
||||||
|
cd ..
|
||||||
|
cd orz
|
||||||
|
\sc2\Utils\ndx orz.res \sc2\Content\orz.con
|
||||||
|
cd ..
|
||||||
|
cd pkunk
|
||||||
|
\sc2\Utils\ndx pkunk.res \sc2\Content\pkunk.con
|
||||||
|
cd ..
|
||||||
|
cd shofixt
|
||||||
|
\sc2\Utils\ndx shofixt.res \sc2\Content\shofixt.con
|
||||||
|
cd ..
|
||||||
|
cd slyland
|
||||||
|
\sc2\Utils\ndx slyland.res \sc2\Content\slyland.con
|
||||||
|
cd ..
|
||||||
|
cd spathi
|
||||||
|
\sc2\Utils\ndx spathi.res \sc2\Content\spathi.con
|
||||||
|
cd ..
|
||||||
|
cd supox
|
||||||
|
\sc2\Utils\ndx supox.res \sc2\Content\supox.con
|
||||||
|
cd ..
|
||||||
|
cd syreen
|
||||||
|
\sc2\Utils\ndx syreen.res \sc2\Content\syreen.con
|
||||||
|
cd ..
|
||||||
|
cd thradd
|
||||||
|
\sc2\Utils\ndx thradd.res \sc2\Content\thradd.con
|
||||||
|
cd ..
|
||||||
|
cd umgah
|
||||||
|
\sc2\Utils\ndx umgah.res \sc2\Content\umgah.con
|
||||||
|
cd ..
|
||||||
|
cd urquan
|
||||||
|
\sc2\Utils\ndx urquan.res \sc2\Content\urquan.con
|
||||||
|
cd ..
|
||||||
|
cd utwig
|
||||||
|
\sc2\Utils\ndx utwig.res \sc2\Content\utwig.con
|
||||||
|
cd ..
|
||||||
|
cd vux
|
||||||
|
\sc2\Utils\ndx vux.res \sc2\Content\vux.con
|
||||||
|
cd ..
|
||||||
|
cd yehat
|
||||||
|
\sc2\Utils\ndx yehat.res \sc2\Content\yehat.con
|
||||||
|
cd ..
|
||||||
|
cd zoqfot
|
||||||
|
\sc2\Utils\ndx zoqfot.res \sc2\Content\zoqfot.con
|
||||||
|
cd ..
|
||||||
|
cd \sc2
|
||||||
Executable
+86
@@ -0,0 +1,86 @@
|
|||||||
|
cd \sc2\src\3do_code
|
||||||
|
\sc2\Utils\ndx star3do.res \sc2\Content\starcon.ndx
|
||||||
|
cd sis_ship
|
||||||
|
\sc2\Utils\ndx sis.res \sc2\Content\sis.dat
|
||||||
|
cd ..
|
||||||
|
cd androsyn
|
||||||
|
\sc2\Utils\ndx androsyn.res \sc2\Content\androsyn.shp
|
||||||
|
cd ..
|
||||||
|
cd arilou
|
||||||
|
\sc2\Utils\ndx arilou.res \sc2\Content\arilou.shp
|
||||||
|
cd ..
|
||||||
|
cd blackurq
|
||||||
|
\sc2\Utils\ndx blackurq.res \sc2\Content\blackurq.shp
|
||||||
|
cd ..
|
||||||
|
cd chenjesu
|
||||||
|
\sc2\Utils\ndx chenjesu.res \sc2\Content\chenjesu.shp
|
||||||
|
cd ..
|
||||||
|
cd chmmr
|
||||||
|
\sc2\Utils\ndx chmmr.res \sc2\Content\chmmr.shp
|
||||||
|
cd ..
|
||||||
|
cd druuge
|
||||||
|
\sc2\Utils\ndx druuge.res \sc2\Content\druuge.shp
|
||||||
|
cd ..
|
||||||
|
cd human
|
||||||
|
\sc2\Utils\ndx human.res \sc2\Content\human.shp
|
||||||
|
cd ..
|
||||||
|
cd ilwrath
|
||||||
|
\sc2\Utils\ndx ilwrath.res \sc2\Content\ilwrath.shp
|
||||||
|
cd ..
|
||||||
|
cd lastbat
|
||||||
|
\sc2\Utils\ndx lastbat.res \sc2\Content\lastbat.shp
|
||||||
|
cd ..
|
||||||
|
cd melnorme
|
||||||
|
\sc2\Utils\ndx melnorme.res \sc2\Content\melnorme.shp
|
||||||
|
cd ..
|
||||||
|
cd mmrnmhrm
|
||||||
|
\sc2\Utils\ndx mmrnmhrm.res \sc2\Content\mmrnmhrm.shp
|
||||||
|
cd ..
|
||||||
|
cd mycon
|
||||||
|
\sc2\Utils\ndx mycon.res \sc2\Content\mycon.shp
|
||||||
|
cd ..
|
||||||
|
cd orz
|
||||||
|
\sc2\Utils\ndx orz.res \sc2\Content\orz.shp
|
||||||
|
cd ..
|
||||||
|
cd pkunk
|
||||||
|
\sc2\Utils\ndx pkunk.res \sc2\Content\pkunk.shp
|
||||||
|
cd ..
|
||||||
|
cd probe
|
||||||
|
\sc2\Utils\ndx probe.res \sc2\Content\probe.sc2
|
||||||
|
cd ..
|
||||||
|
cd shofixti
|
||||||
|
\sc2\Utils\ndx shofixti.res \sc2\Content\shofixti.shp
|
||||||
|
cd ..
|
||||||
|
cd slylandr
|
||||||
|
\sc2\Utils\ndx slylandr.res \sc2\Content\slylandr.shp
|
||||||
|
cd ..
|
||||||
|
cd spathi
|
||||||
|
\sc2\Utils\ndx spathi.res \sc2\Content\spathi.shp
|
||||||
|
cd ..
|
||||||
|
cd supox
|
||||||
|
\sc2\Utils\ndx supox.res \sc2\Content\supox.shp
|
||||||
|
cd ..
|
||||||
|
cd syreen
|
||||||
|
\sc2\Utils\ndx syreen.res \sc2\Content\syreen.shp
|
||||||
|
cd ..
|
||||||
|
cd thradd
|
||||||
|
\sc2\Utils\ndx thradd.res \sc2\Content\thradd.shp
|
||||||
|
cd ..
|
||||||
|
cd umgah
|
||||||
|
\sc2\Utils\ndx umgah.res \sc2\Content\umgah.shp
|
||||||
|
cd ..
|
||||||
|
cd urquan
|
||||||
|
\sc2\Utils\ndx urquan.res \sc2\Content\urquan.shp
|
||||||
|
cd ..
|
||||||
|
cd utwig
|
||||||
|
\sc2\Utils\ndx utwig.res \sc2\Content\utwig.shp
|
||||||
|
cd ..
|
||||||
|
cd vux
|
||||||
|
\sc2\Utils\ndx vux.res \sc2\Content\vux.shp
|
||||||
|
cd ..
|
||||||
|
cd yehat
|
||||||
|
\sc2\Utils\ndx yehat.res \sc2\Content\yehat.shp
|
||||||
|
cd ..
|
||||||
|
cd zoqfot
|
||||||
|
\sc2\Utils\ndx zoqfot.res \sc2\Content\zoqfot.shp
|
||||||
|
cd ..
|
||||||
@@ -0,0 +1,111 @@
|
|||||||
|
# Microsoft Developer Studio Project File - Name="Palette Shifting Test" - Package Owner=<4>
|
||||||
|
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||||
|
# ** DO NOT EDIT **
|
||||||
|
|
||||||
|
# TARGTYPE "Win32 (x86) Application" 0x0101
|
||||||
|
|
||||||
|
CFG=Palette Shifting Test - Win32 Debug
|
||||||
|
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||||
|
!MESSAGE use the Export Makefile command and run
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "Palette Shifting Test.mak".
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE You can specify a configuration when running NMAKE
|
||||||
|
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "Palette Shifting Test.mak" CFG="Palette Shifting Test - Win32 Debug"
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE Possible choices for configuration are:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE "Palette Shifting Test - Win32 Release" (based on "Win32 (x86) Application")
|
||||||
|
!MESSAGE "Palette Shifting Test - Win32 Debug" (based on "Win32 (x86) Application")
|
||||||
|
!MESSAGE
|
||||||
|
|
||||||
|
# Begin Project
|
||||||
|
# PROP AllowPerConfigDependencies 0
|
||||||
|
# PROP Scc_ProjName ""
|
||||||
|
# PROP Scc_LocalPath ""
|
||||||
|
CPP=cl.exe
|
||||||
|
MTL=midl.exe
|
||||||
|
RSC=rc.exe
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "Palette Shifting Test - Win32 Release"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 0
|
||||||
|
# PROP BASE Output_Dir "Release"
|
||||||
|
# PROP BASE Intermediate_Dir "Release"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 0
|
||||||
|
# PROP Output_Dir "Release"
|
||||||
|
# PROP Intermediate_Dir "Release"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
|
||||||
|
# ADD CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
|
||||||
|
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||||
|
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||||
|
# ADD BASE RSC /l 0x1c09 /d "NDEBUG"
|
||||||
|
# ADD RSC /l 0x1c09 /d "NDEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
|
||||||
|
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "Palette Shifting Test - Win32 Debug"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 1
|
||||||
|
# PROP BASE Output_Dir "Debug"
|
||||||
|
# PROP BASE Intermediate_Dir "Debug"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 1
|
||||||
|
# PROP Output_Dir "Debug"
|
||||||
|
# PROP Intermediate_Dir "Debug"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
|
||||||
|
# ADD CPP /nologo /MD /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /FR /YX /FD /GZ /c
|
||||||
|
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||||
|
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||||
|
# ADD BASE RSC /l 0x1c09 /d "_DEBUG"
|
||||||
|
# ADD RSC /l 0x1c09 /d "_DEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
|
||||||
|
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib sdl.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# Begin Target
|
||||||
|
|
||||||
|
# Name "Palette Shifting Test - Win32 Release"
|
||||||
|
# Name "Palette Shifting Test - Win32 Debug"
|
||||||
|
# Begin Group "Source Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\main.cpp
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# Begin Group "Header Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||||
|
# End Group
|
||||||
|
# Begin Group "Resource Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE="..\..\SDL-1.2.4\lib\SDL.lib"
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# End Target
|
||||||
|
# End Project
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||||
|
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
Project: "Palette Shifting Test"=".\Palette Shifting Test.dsp" - Package Owner=<4>
|
||||||
|
|
||||||
|
Package=<5>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
Package=<4>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
Global:
|
||||||
|
|
||||||
|
Package=<5>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
Package=<3>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
@@ -0,0 +1,506 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
|
||||||
|
Palette Shifting Test
|
||||||
|
Copyright (C) 2002 Stuart Binge (datura@mighty.co.za)
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and / or modify it
|
||||||
|
under the terms of the GNU General Public License as published by the Free
|
||||||
|
Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along with
|
||||||
|
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||||
|
Place - Suite 330, Boston, MA 02111-1307, USA. You can also view the GNU
|
||||||
|
General Public License, online, at the GNU Homepage: http://www.gnu.org
|
||||||
|
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE: If you are building with MSVC, make sure that the "Use runtime library"
|
||||||
|
* setting is "Multithreaded DLL", in "Project->Settings->C++->Code Generation".
|
||||||
|
* Use this setting for both debug and runtime builds. Also use "Win32
|
||||||
|
* Application" as the project template, NOT "Win32 Console Application", when
|
||||||
|
* creating a project for this.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE: You'll need to add the OpenGL, GLU, and SDL libs to your project if your
|
||||||
|
* compiler does not understand these lib pragma's.
|
||||||
|
*/
|
||||||
|
#pragma comment(lib, "opengl32")
|
||||||
|
#pragma comment(lib, "glu32")
|
||||||
|
#pragma comment(lib, "sdl")
|
||||||
|
#pragma comment(lib, "sdlmain")
|
||||||
|
|
||||||
|
#include <C:/SDL-1.2.4/include/SDL.h>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
// Win32 GL headers require that windows.h be included before them
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <GL/gl.h>
|
||||||
|
#include <GL/glu.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cmath>
|
||||||
|
#include <climits>
|
||||||
|
|
||||||
|
const double pi = 3.14159265358979323846;
|
||||||
|
|
||||||
|
bool g_bRunning = true;
|
||||||
|
bool g_bRotate = false;
|
||||||
|
bool g_bCycle1 = false;
|
||||||
|
bool g_bCycle2 = false;
|
||||||
|
|
||||||
|
const int g_iWidth = 640;
|
||||||
|
const int g_iHeight = 480;
|
||||||
|
const bool g_bFullscreen = false;
|
||||||
|
|
||||||
|
GLuint g_uiTexName = 0;
|
||||||
|
char* g_pcData;
|
||||||
|
int g_iTexWid;
|
||||||
|
int g_iTexHei;
|
||||||
|
GLfloat g_rpal[256];
|
||||||
|
GLfloat g_gpal[256];
|
||||||
|
GLfloat g_bpal[256];
|
||||||
|
GLfloat g_apal[256];
|
||||||
|
SDL_Surface* g_ssAppWindow;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE: The following structures are assumed to be in little-endian format
|
||||||
|
* (i.e. as used on Intel-32 architecture).
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE: if not building with MSVC, or if your compiler does not understand
|
||||||
|
* pack pragma's, then change this next structure to somehow use 1-byte
|
||||||
|
* alignment.
|
||||||
|
*/
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
|
||||||
|
struct sRGBTriple {
|
||||||
|
Uint8 rgbt_Blue;
|
||||||
|
Uint8 rgbt_Green;
|
||||||
|
Uint8 rgbt_Red;
|
||||||
|
};
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
struct sRGBQuad {
|
||||||
|
Uint8 rgbq_Blue;
|
||||||
|
Uint8 rgbq_Green;
|
||||||
|
Uint8 rgbq_Red;
|
||||||
|
Uint8 rgbq_Reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE: if not building with MSVC, or if your compiler does not understand
|
||||||
|
* pack pragma's, then change this next structure to somehow use 2-byte
|
||||||
|
* alignment.
|
||||||
|
*/
|
||||||
|
#pragma pack(push, 2)
|
||||||
|
|
||||||
|
struct sBitmapFileHeader {
|
||||||
|
Uint16 bfh_Type;
|
||||||
|
Uint32 bfh_Size;
|
||||||
|
Uint16 bfh_Reserved1;
|
||||||
|
Uint16 bfh_Reserved2;
|
||||||
|
Uint32 bfh_OffBits;
|
||||||
|
};
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
// Currently defined valid bitmap headers
|
||||||
|
|
||||||
|
// This first header uses sRGBTriple's for its colour map
|
||||||
|
struct sBitmapHeader_1 {
|
||||||
|
Uint16 bh1_Width;
|
||||||
|
Uint16 bh1_Height;
|
||||||
|
Uint16 bh1_Planes;
|
||||||
|
Uint16 bh1_BitCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Headers 2, 3 and 4 have this structure in common
|
||||||
|
struct sStandardBH {
|
||||||
|
Uint32 Width;
|
||||||
|
Uint32 Height;
|
||||||
|
Uint16 Planes;
|
||||||
|
Uint16 BitCount;
|
||||||
|
Uint32 Compression;
|
||||||
|
Uint32 SizeImage;
|
||||||
|
Uint32 XPelsPerMeter;
|
||||||
|
Uint32 YPelsPerMeter;
|
||||||
|
Uint32 ClrUsed;
|
||||||
|
};
|
||||||
|
|
||||||
|
// The next three headers use sRGBQuad's for their colour map
|
||||||
|
struct sBitmapHeader_2 {
|
||||||
|
sStandardBH std;
|
||||||
|
Uint32 _unused[1];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sBitmapHeader_3 {
|
||||||
|
sStandardBH std;
|
||||||
|
Uint32 _unused[18];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sBitmapHeader_4 {
|
||||||
|
sStandardBH std;
|
||||||
|
Uint32 _unused[22];
|
||||||
|
};
|
||||||
|
|
||||||
|
// End of structures
|
||||||
|
|
||||||
|
bool img_Load8bppBMP(std::string filename) {
|
||||||
|
if (filename.empty()) return false;
|
||||||
|
|
||||||
|
std::ifstream file(filename.c_str(), std::ios_base::binary | std::ios_base::in);
|
||||||
|
if (!file) return false;
|
||||||
|
|
||||||
|
sBitmapFileHeader bfh;
|
||||||
|
|
||||||
|
file.read(reinterpret_cast<char*>(&bfh), sizeof(sBitmapFileHeader));
|
||||||
|
if (file.bad() || file.eof()) return false;
|
||||||
|
|
||||||
|
if (bfh.bfh_Type != (('M' << 8) | 'B')) return false;
|
||||||
|
|
||||||
|
Uint32 hdrsz;
|
||||||
|
|
||||||
|
file.read(reinterpret_cast<char*>(&hdrsz), sizeof(Uint32));
|
||||||
|
if (file.bad() || file.eof()) return false;
|
||||||
|
|
||||||
|
hdrsz -= sizeof(Uint32);
|
||||||
|
|
||||||
|
bool trip = false;
|
||||||
|
|
||||||
|
if (hdrsz == sizeof(sBitmapHeader_1)) {
|
||||||
|
sBitmapHeader_1 bh;
|
||||||
|
file.read(reinterpret_cast<char*>(&bh), sizeof(sBitmapHeader_1));
|
||||||
|
if (file.bad() || file.eof() || bh.bh1_BitCount != 8) return false;
|
||||||
|
|
||||||
|
g_iTexWid = bh.bh1_Width;
|
||||||
|
g_iTexHei = bh.bh1_Height;
|
||||||
|
trip = true;
|
||||||
|
} else if (hdrsz == sizeof(sBitmapHeader_2)) {
|
||||||
|
sBitmapHeader_2 bh;
|
||||||
|
file.read(reinterpret_cast<char*>(&bh), sizeof(sBitmapHeader_2));
|
||||||
|
if (file.bad() || file.eof() || bh.std.BitCount != 8) return false;
|
||||||
|
|
||||||
|
g_iTexWid = bh.std.Width;
|
||||||
|
g_iTexHei = bh.std.Height;
|
||||||
|
} else if (hdrsz == sizeof(sBitmapHeader_3)) {
|
||||||
|
sBitmapHeader_3 bh;
|
||||||
|
file.read(reinterpret_cast<char*>(&bh), sizeof(sBitmapHeader_3));
|
||||||
|
if (file.bad() || file.eof() || bh.std.BitCount != 8) return false;
|
||||||
|
|
||||||
|
g_iTexWid = bh.std.Width;
|
||||||
|
g_iTexHei = bh.std.Height;
|
||||||
|
} else if (hdrsz == sizeof(sBitmapHeader_4)) {
|
||||||
|
sBitmapHeader_4 bh;
|
||||||
|
file.read(reinterpret_cast<char*>(&bh), sizeof(sBitmapHeader_4));
|
||||||
|
if (file.bad() || file.eof() || bh.std.BitCount != 8) return false;
|
||||||
|
|
||||||
|
g_iTexWid = bh.std.Width;
|
||||||
|
g_iTexHei = bh.std.Height;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool invert = true;
|
||||||
|
if (g_iTexHei < 0) {
|
||||||
|
invert = false;
|
||||||
|
g_iTexHei = -g_iTexHei;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trip) {
|
||||||
|
sRGBTriple tmppal[256];
|
||||||
|
file.read(reinterpret_cast<char*>(tmppal), sizeof(sRGBTriple) * 256);
|
||||||
|
|
||||||
|
for (int i = 0; i < 256; i++) {
|
||||||
|
g_rpal[i] = (float)tmppal[i].rgbt_Red / 255.0f;
|
||||||
|
g_gpal[i] = (float)tmppal[i].rgbt_Green / 255.0f;
|
||||||
|
g_bpal[i] = (float)tmppal[i].rgbt_Blue / 255.0f;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sRGBQuad tmppal[256];
|
||||||
|
file.read(reinterpret_cast<char*>(tmppal), sizeof(sRGBQuad) * 256);
|
||||||
|
|
||||||
|
for (int i = 0; i < 256; i++) {
|
||||||
|
g_rpal[i] = (float)tmppal[i].rgbq_Red / 255.0f;
|
||||||
|
g_gpal[i] = (float)tmppal[i].rgbq_Green / 255.0f;
|
||||||
|
g_bpal[i] = (float)tmppal[i].rgbq_Blue / 255.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_pcData = new char[g_iTexWid * g_iTexHei];
|
||||||
|
file.read(g_pcData, g_iTexWid * g_iTexHei);
|
||||||
|
|
||||||
|
if (invert) {
|
||||||
|
char* tmpbuf = new char[g_iTexWid];
|
||||||
|
for (int i = 0; i < g_iTexHei / 2; i++) {
|
||||||
|
memcpy(tmpbuf, g_pcData + (g_iTexHei - 1 - i) * g_iTexWid, g_iTexWid);
|
||||||
|
memcpy(g_pcData + (g_iTexHei - 1 - i) * g_iTexWid, g_pcData + i * g_iTexWid, g_iTexWid);
|
||||||
|
memcpy(g_pcData + i * g_iTexWid, tmpbuf, g_iTexWid);
|
||||||
|
}
|
||||||
|
delete[] tmpbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void inp_KeyHandler(SDL_keysym* keysym) {
|
||||||
|
switch (keysym->sym) {
|
||||||
|
case SDLK_q:
|
||||||
|
g_bCycle1 = !g_bCycle1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDLK_w:
|
||||||
|
g_bCycle2 = !g_bCycle2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDLK_ESCAPE:
|
||||||
|
g_bRunning = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* case SDLK_RETURN:
|
||||||
|
if ((keysym->mod | KMOD_ALT) > 0)
|
||||||
|
SDL_WM_ToggleFullScreen(g_ssAppWindow);
|
||||||
|
break;*/
|
||||||
|
|
||||||
|
case SDLK_SPACE:
|
||||||
|
g_bRotate = !g_bRotate;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_ProcessEvents() {
|
||||||
|
SDL_Event event;
|
||||||
|
|
||||||
|
while (SDL_PollEvent(&event)) {
|
||||||
|
switch (event.type) {
|
||||||
|
case SDL_KEYDOWN:
|
||||||
|
inp_KeyHandler(&event.key.keysym);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_QUIT:
|
||||||
|
g_bRunning = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_DrawFrame() {
|
||||||
|
static float rot = 0.0f;
|
||||||
|
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glLoadIdentity();
|
||||||
|
|
||||||
|
glTranslatef(0.0f, 0.0f, -3.0f);
|
||||||
|
|
||||||
|
if (g_bRotate) rot += 1.0f;
|
||||||
|
|
||||||
|
glRotatef(rot, 0.0, 1.0, 0.0);
|
||||||
|
|
||||||
|
if (g_bCycle1) {
|
||||||
|
GLfloat tmp[4];
|
||||||
|
tmp[0] = g_rpal[256 - 16 - 1];
|
||||||
|
tmp[1] = g_gpal[256 - 16 - 1];
|
||||||
|
tmp[2] = g_bpal[256 - 16 - 1];
|
||||||
|
tmp[3] = g_apal[256 - 16 - 1];
|
||||||
|
for (int i = 256 - 16 - 1; i > 0; i--) {
|
||||||
|
g_rpal[i] = g_rpal[i-1];
|
||||||
|
g_gpal[i] = g_gpal[i-1];
|
||||||
|
g_bpal[i] = g_bpal[i-1];
|
||||||
|
g_apal[i] = g_apal[i-1];
|
||||||
|
}
|
||||||
|
|
||||||
|
g_rpal[0] = tmp[0];
|
||||||
|
g_gpal[0] = tmp[1];
|
||||||
|
g_bpal[0] = tmp[2];
|
||||||
|
g_apal[0] = tmp[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_bCycle2) {
|
||||||
|
GLfloat tmp[4];
|
||||||
|
tmp[0] = g_rpal[256 - 1];
|
||||||
|
tmp[1] = g_gpal[256 - 1];
|
||||||
|
tmp[2] = g_bpal[256 - 1];
|
||||||
|
tmp[3] = g_apal[256 - 1];
|
||||||
|
for (int i = 256 - 1; i > 256 - 16; i--) {
|
||||||
|
g_rpal[i] = g_rpal[i-1];
|
||||||
|
g_gpal[i] = g_gpal[i-1];
|
||||||
|
g_bpal[i] = g_bpal[i-1];
|
||||||
|
g_apal[i] = g_apal[i-1];
|
||||||
|
}
|
||||||
|
|
||||||
|
g_rpal[256 - 16] = tmp[0];
|
||||||
|
g_gpal[256 - 16] = tmp[1];
|
||||||
|
g_bpal[256 - 16] = tmp[2];
|
||||||
|
g_apal[256 - 16] = tmp[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_bCycle1 || g_bCycle2) {
|
||||||
|
glPixelMapfv(GL_PIXEL_MAP_I_TO_R, 256, g_rpal);
|
||||||
|
glPixelMapfv(GL_PIXEL_MAP_I_TO_G, 256, g_gpal);
|
||||||
|
glPixelMapfv(GL_PIXEL_MAP_I_TO_B, 256, g_bpal);
|
||||||
|
glPixelMapfv(GL_PIXEL_MAP_I_TO_A, 256, g_apal);
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, g_uiTexName);
|
||||||
|
glTexSubImage2D
|
||||||
|
(
|
||||||
|
GL_TEXTURE_2D,
|
||||||
|
0, 0, 0,
|
||||||
|
g_iTexWid, g_iTexHei,
|
||||||
|
GL_COLOR_INDEX, GL_UNSIGNED_BYTE,
|
||||||
|
g_pcData
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, g_uiTexName);
|
||||||
|
|
||||||
|
// Front face
|
||||||
|
glTexCoord2f(1.0f, 0.0f);
|
||||||
|
glVertex3f(1.0f, 1.0f, 0.0f);
|
||||||
|
glTexCoord2f(0.0f, 0.0f);
|
||||||
|
glVertex3f(-1.0f, 1.0f, 0.0f);
|
||||||
|
glTexCoord2f(0.0f, 1.0f);
|
||||||
|
glVertex3f(-1.0f, -1.0f, 0.0f);
|
||||||
|
glTexCoord2f(1.0f, 1.0f);
|
||||||
|
glVertex3f(1.0f, -1.0f, 0.0f);
|
||||||
|
|
||||||
|
// Back face
|
||||||
|
glTexCoord2f(1.0f, 0.0f);
|
||||||
|
glVertex3f(-1.0f, 1.0f, 0.0f);
|
||||||
|
glTexCoord2f(0.0f, 0.0f);
|
||||||
|
glVertex3f(1.0f, 1.0f, 0.0f);
|
||||||
|
glTexCoord2f(0.0f, 1.0f);
|
||||||
|
glVertex3f(1.0f, -1.0f, 0.0f);
|
||||||
|
glTexCoord2f(1.0f, 1.0f);
|
||||||
|
glVertex3f(-1.0f, -1.0f, 0.0f);
|
||||||
|
glEnd();
|
||||||
|
|
||||||
|
glFlush();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ogl_Setup() {
|
||||||
|
glViewport(0, 0, g_iWidth, g_iHeight);
|
||||||
|
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glLoadIdentity();
|
||||||
|
|
||||||
|
gluPerspective(45.0, static_cast<float>(g_iWidth) / static_cast<float>(g_iHeight), 0.1, 100);
|
||||||
|
|
||||||
|
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
|
glClearDepth(1.0f);
|
||||||
|
glDepthFunc(GL_LESS);
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
|
glShadeModel(GL_SMOOTH);
|
||||||
|
glDisable(GL_LIGHTING);
|
||||||
|
|
||||||
|
glCullFace(GL_BACK);
|
||||||
|
glFrontFace(GL_CCW);
|
||||||
|
glEnable(GL_CULL_FACE);
|
||||||
|
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
glDisable(GL_ALPHA_TEST);
|
||||||
|
|
||||||
|
glEnable(GL_TEXTURE_2D);
|
||||||
|
|
||||||
|
glGenTextures(1, &g_uiTexName);
|
||||||
|
|
||||||
|
img_Load8bppBMP(std::string("test.bmp"));
|
||||||
|
|
||||||
|
for (int i = 0; i < 256; i++) g_apal[i] = 1.0f;
|
||||||
|
|
||||||
|
/* std::ofstream tf("maps.txt");
|
||||||
|
for (i = 0; i < 256; i++) {
|
||||||
|
tf << i << " R: " << g_rpal[i] << ", G: " << g_gpal[i] << ", B: " << g_bpal[i] << ", A: " << g_apal[i] << std::endl;
|
||||||
|
} */
|
||||||
|
|
||||||
|
/*std::ofstream bin("index.bin", std::ios_base::binary | std::ios_base::out);
|
||||||
|
bin.write(g_data, 512*512);*/
|
||||||
|
|
||||||
|
glPixelTransferi(GL_MAP_COLOR, GL_TRUE);
|
||||||
|
|
||||||
|
glPixelMapfv(GL_PIXEL_MAP_I_TO_R, 256, g_rpal);
|
||||||
|
glPixelMapfv(GL_PIXEL_MAP_I_TO_G, 256, g_gpal);
|
||||||
|
glPixelMapfv(GL_PIXEL_MAP_I_TO_B, 256, g_bpal);
|
||||||
|
glPixelMapfv(GL_PIXEL_MAP_I_TO_A, 256, g_apal);
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, g_uiTexName);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, 4, g_iTexWid, g_iTexHei, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, g_pcData);
|
||||||
|
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv){
|
||||||
|
/* std::ofstream f("test.txt");
|
||||||
|
|
||||||
|
f << "sizeof(sRGBTriple) = " << sizeof(sRGBTriple) << ", sizeof(RGBTRIPLE) = " << sizeof(RGBTRIPLE) << std::endl;
|
||||||
|
f << "sizeof(sRGBQuad) = " << sizeof(sRGBQuad) << ", sizeof(RGBQUAD) = " << sizeof(RGBQUAD) << std::endl;
|
||||||
|
f << "sizeof(sBitmapFileHeader) = " << sizeof(sBitmapFileHeader) << ", sizeof(BITMAPFILEHEADER) = " << sizeof(BITMAPFILEHEADER) << std::endl;
|
||||||
|
f << "sizeof(sBitmapHeader_1) = " << sizeof(sBitmapHeader_1) << ", sizeof(BITMAPCOREHEADER) = " << sizeof(BITMAPCOREHEADER) << std::endl;
|
||||||
|
f << "sizeof(sBitmapHeader_2) = " << sizeof(sBitmapHeader_2) << ", sizeof(BITMAPINFOHEADER) = " << sizeof(BITMAPINFOHEADER) << std::endl;
|
||||||
|
f << "sizeof(sBitmapHeader_3) = " << sizeof(sBitmapHeader_3) << ", sizeof(BITMAPV4HEADER) = " << sizeof(BITMAPV4HEADER) << std::endl;
|
||||||
|
f << "sizeof(sBitmapHeader_4) = " << sizeof(sBitmapHeader_4) << ", sizeof(BITMAPV5HEADER) = " << sizeof(BITMAPV5HEADER) << std::endl;*/
|
||||||
|
|
||||||
|
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
|
||||||
|
std::cerr << "Video initialisation failed: " << SDL_GetError() << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SDL_VideoInfo* info = SDL_GetVideoInfo();
|
||||||
|
if (!info) {
|
||||||
|
std::cerr << "Video information query failed: " << SDL_GetError() << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bpp = info->vfmt->BitsPerPixel;
|
||||||
|
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||||
|
|
||||||
|
int flags = SDL_OPENGL | (g_bFullscreen ? SDL_FULLSCREEN : 0);
|
||||||
|
|
||||||
|
if ((g_ssAppWindow = SDL_SetVideoMode(g_iWidth, g_iHeight, bpp, flags)) == 0) {
|
||||||
|
std::cerr << "Video mode set failed: " << SDL_GetError() << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_WM_SetCaption("Palette Shifting Test", 0);
|
||||||
|
|
||||||
|
ogl_Setup();
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
app_ProcessEvents();
|
||||||
|
if (!g_bRunning) break;
|
||||||
|
app_DrawFrame();
|
||||||
|
SDL_GL_SwapBuffers();
|
||||||
|
}
|
||||||
|
|
||||||
|
delete[] g_pcData;
|
||||||
|
|
||||||
|
glDeleteTextures(1, &g_uiTexName);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
# Microsoft Developer Studio Project File - Name="pcx2png" - Package Owner=<4>
|
||||||
|
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||||
|
# ** DO NOT EDIT **
|
||||||
|
|
||||||
|
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||||
|
|
||||||
|
CFG=pcx2png - Win32 Debug
|
||||||
|
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||||
|
!MESSAGE use the Export Makefile command and run
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "pcx2png.mak".
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE You can specify a configuration when running NMAKE
|
||||||
|
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "pcx2png.mak" CFG="pcx2png - Win32 Debug"
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE Possible choices for configuration are:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE "pcx2png - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||||
|
!MESSAGE "pcx2png - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||||
|
!MESSAGE
|
||||||
|
|
||||||
|
# Begin Project
|
||||||
|
# PROP AllowPerConfigDependencies 0
|
||||||
|
# PROP Scc_ProjName ""
|
||||||
|
# PROP Scc_LocalPath ""
|
||||||
|
CPP=cl.exe
|
||||||
|
RSC=rc.exe
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "pcx2png - Win32 Release"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 0
|
||||||
|
# PROP BASE Output_Dir "Release"
|
||||||
|
# PROP BASE Intermediate_Dir "Release"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 0
|
||||||
|
# PROP Output_Dir "Release"
|
||||||
|
# PROP Intermediate_Dir "Release"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||||
|
# ADD CPP /nologo /W3 /GX /O2 /I "C:\devil\include" /I "C:\mssdk\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||||
|
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||||
|
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"../pcx2png.exe"
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "pcx2png - Win32 Debug"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 1
|
||||||
|
# PROP BASE Output_Dir "Debug"
|
||||||
|
# PROP BASE Intermediate_Dir "Debug"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 1
|
||||||
|
# PROP Output_Dir "Debug"
|
||||||
|
# PROP Intermediate_Dir "Debug"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||||
|
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "C:\devil\include" /I "C:\mssdk\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||||
|
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||||
|
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"../pcx2png.exe" /pdbtype:sept
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# Begin Target
|
||||||
|
|
||||||
|
# Name "pcx2png - Win32 Release"
|
||||||
|
# Name "pcx2png - Win32 Debug"
|
||||||
|
# Begin Group "Source Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\main.cpp
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# Begin Group "Header Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||||
|
# End Group
|
||||||
|
# Begin Group "Resource Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\..\..\DevIL\lib\ILUT.lib
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\..\..\DevIL\lib\il_wrap.lib
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\..\..\DevIL\lib\ILU.lib
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\..\..\DevIL\lib\DevIL.lib
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# End Target
|
||||||
|
# End Project
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||||
|
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
Project: "pcx2png"=".\pcx2png.dsp" - Package Owner=<4>
|
||||||
|
|
||||||
|
Package=<5>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
Package=<4>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
Global:
|
||||||
|
|
||||||
|
Package=<5>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
Package=<3>
|
||||||
|
{{{
|
||||||
|
}}}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
Executable
BIN
Binary file not shown.
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Brainless pcx2png converter.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "il/ilut.h"
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
unsigned int ILid;
|
||||||
|
int size;
|
||||||
|
char filein[256];
|
||||||
|
char filetemp1[256];
|
||||||
|
char filetemp2[256];
|
||||||
|
char fileout[256];
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
if(argc!=2)
|
||||||
|
{
|
||||||
|
printf("Usage: pcx2png filename\n");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf(filein,"%s",argv[1]);
|
||||||
|
sprintf(filetemp1,"%s","deleteme1.pcx");
|
||||||
|
sprintf(filetemp2,"%s","deleteme2.pcx");
|
||||||
|
sprintf(fileout,"%s",filein);
|
||||||
|
size=strlen(fileout);
|
||||||
|
fileout[size-3]='p';
|
||||||
|
fileout[size-2]='n';
|
||||||
|
fileout[size-1]='g';
|
||||||
|
|
||||||
|
ilInit();
|
||||||
|
ilGenImages(1,&ILid);
|
||||||
|
ilBindImage(ILid);
|
||||||
|
ilLoadImage(filein);
|
||||||
|
ilSaveImage(filetemp1);
|
||||||
|
ilLoadImage(filetemp1);
|
||||||
|
ilSaveImage(filetemp2);
|
||||||
|
ilLoadImage(filetemp2);
|
||||||
|
ilSaveImage(fileout);
|
||||||
|
|
||||||
|
printf("In: %s\n",filein);
|
||||||
|
printf("Out: %s\n",fileout);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user