Old tools that got removed a long time ago.

git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@1545 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
meep-eep
2005-02-19 00:38:46 +00:00
parent 440fec6289
commit e7eabd46b9
51 changed files with 10988 additions and 0 deletions
+38
View File
@@ -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);
}
+23
View File
@@ -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) $?
+70
View File
@@ -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
+926
View File
@@ -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);
}
+267
View File
@@ -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);
}
+40
View File
@@ -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);
}
+129
View File
@@ -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);
}
+91
View File
@@ -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;
+22
View File
@@ -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. */
+296
View File
@@ -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;
}
+5
View File
@@ -0,0 +1,5 @@
anim2pcx anima dalloc gio misc misca lpfile pbio
anim2pcx.exe

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