1
0
mirror of https://github.com/weiju/amiga-stuff synced 2025-11-20 08:48:41 +00:00

fixed bug in IFF reading

char buffer is not automatically aligned on a word boundary
on a plain 68000, so we need to ensure about that ourselves
checked on a500 setup
This commit is contained in:
Wei-ju Wu
2016-01-11 08:00:38 -08:00
parent 2ff7b6c237
commit 3b04b00490
5 changed files with 89 additions and 57 deletions

View File

@ -1,6 +1,6 @@
#CC=vc +aos68k #CC=vc +aos68k
CC=vc +kick13 CC=vc +kick13
CFLAGS=-c99 -I$(NDK_INC) CFLAGS=-c99 -I$(NDK_INC) -DDEBUG
all: iffview all: iffview

View File

@ -69,7 +69,7 @@ struct Gadget gadgets[] = {
}; };
BOOL initialized = 0; BOOL initialized = 0;
#define PATHBUFFER_SIZE 32 #define PATHBUFFER_SIZE 200
char dirname[PATHBUFFER_SIZE + 1]; char dirname[PATHBUFFER_SIZE + 1];
BPTR flock; BPTR flock;
LONG error; LONG error;
@ -101,6 +101,8 @@ struct Requester *open_file(struct Window *window)
/* scan current directory */ /* scan current directory */
puts("scanning directory..."); puts("scanning directory...");
/*
// on AmigaOS 1.x, this function does not exist !!!
GetCurrentDirName(dirname, PATHBUFFER_SIZE); GetCurrentDirName(dirname, PATHBUFFER_SIZE);
printf("current dir: '%s'\n", dirname); printf("current dir: '%s'\n", dirname);
flock = Lock(dirname, SHARED_LOCK); flock = Lock(dirname, SHARED_LOCK);
@ -110,11 +112,11 @@ struct Requester *open_file(struct Window *window)
} }
error = IoErr(); error = IoErr();
if (error != ERROR_NO_MORE_ENTRIES) { if (error != ERROR_NO_MORE_ENTRIES) {
/* an error occurred */
puts("unknown I/O error, TODO handle"); puts("unknown I/O error, TODO handle");
} }
} }
UnLock(flock); UnLock(flock);
*/
initialized = 1; initialized = 1;
} }

View File

@ -29,6 +29,7 @@
#include <clib/alib_stdio_protos.h> #include <clib/alib_stdio_protos.h>
#endif #endif
#include "filereq.h" #include "filereq.h"
#include "ilbm.h"
#define WIN_LEFT 10 #define WIN_LEFT 10
#define WIN_TOP 10 #define WIN_TOP 10
@ -169,12 +170,29 @@ void setup_menu()
SetMenuStrip(window, &menus[0]); SetMenuStrip(window, &menus[0]);
} }
struct Image image = { 0, 0, 0, 0, 0, NULL, 0, 0, NULL};
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
ILBMData *ilbm_data = NULL;
if (window = OpenWindow(&newwin)) { if (window = OpenWindow(&newwin)) {
int wordwidth, finalsize;
setup_menu(); setup_menu();
ilbm_data = parse_file("examples/Kickstart13.iff");
image.Width = ilbm_data->bmheader->w;
image.Height = ilbm_data->bmheader->h;
image.Depth = ilbm_data->bmheader->nPlanes;
wordwidth = (image.Width + 16) / 16;
finalsize = wordwidth * image.Height * image.Depth * sizeof(UWORD);
image.ImageData = AllocMem(finalsize, MEMF_CHIP);
printf("loaded size: %d, final size: %d\n", ilbm_data->data_bytes, finalsize);
memcpy(image.ImageData, ilbm_data->imgdata, ilbm_data->data_bytes);
image.PlanePick = (1 << image.Depth) - 1;
// Note: rastport is the entire window, including title bars
DrawImage(window->RPort, &image, 5, 10);
handle_events(); handle_events();
} }
if (ilbm_data) free_ilbm_data(ilbm_data);
cleanup(); cleanup();
return 1; return 1;
} }

View File

@ -59,13 +59,14 @@ BitMapHeader *read_BMHD(FILE *fp, int datasize)
return header; return header;
} }
ColorRegister *read_CMAP(FILE *fp, int datasize) ColorRegister *read_CMAP(FILE *fp, int datasize, int *ncols)
{ {
int num_colors = datasize / 3, bytes_read; int num_colors = datasize / 3, bytes_read;
ColorRegister *colors; ColorRegister *colors;
colors = malloc(datasize); colors = malloc(datasize);
bytes_read = fread(colors, sizeof(ColorRegister), num_colors, fp); bytes_read = fread(colors, sizeof(ColorRegister), num_colors, fp);
*ncols = num_colors;
return colors; return colors;
} }
@ -98,12 +99,14 @@ void read_CRNG(FILE *fp, int datasize)
#endif #endif
} }
UBYTE *read_BODY(FILE *fp, int datasize, BitMapHeader *bmheader) UBYTE *read_BODY(FILE *fp, int datasize, BitMapHeader *bmheader, int *data_bytes)
{ {
ULONG bytes_read; ULONG bytes_read;
BYTE *buffer = malloc(datasize), *dst_buffer; BYTE *buffer, *dst_buffer;
int src_i = 0, dst_i = 0, dst_size; int src_i = 0, dst_i = 0, dst_size;
buffer = malloc(datasize);
*data_bytes = datasize;
dst_size = bmheader->w * bmheader->h * bmheader->nPlanes / 8; dst_size = bmheader->w * bmheader->h * bmheader->nPlanes / 8;
printf("target size: %d, data size: %d\n", dst_size, datasize); printf("target size: %d, data size: %d\n", dst_size, datasize);
bytes_read = fread(buffer, sizeof(char), datasize, fp); bytes_read = fread(buffer, sizeof(char), datasize, fp);
@ -113,6 +116,7 @@ UBYTE *read_BODY(FILE *fp, int datasize, BitMapHeader *bmheader)
int i; int i;
/* decompress data */ /* decompress data */
dst_buffer = malloc(dst_size); dst_buffer = malloc(dst_size);
*data_bytes = dst_size;
while (src_i < datasize) { while (src_i < datasize) {
b0 = buffer[src_i++]; b0 = buffer[src_i++];
if (b0 >= 0) { if (b0 >= 0) {
@ -130,64 +134,58 @@ UBYTE *read_BODY(FILE *fp, int datasize, BitMapHeader *bmheader)
#define skip_chunk(fp, datasize) fseek(fp, datasize, SEEK_CUR) #define skip_chunk(fp, datasize) fseek(fp, datasize, SEEK_CUR)
IFFData *read_chunks(FILE *fp, int filesize, int total_read) ILBMData *read_chunks(FILE *fp, int filesize, int total_read)
{ {
char id[5], buffer[CHUNK_HEADER_SIZE]; // make sure that our char buffers are aligned on word boundaries
int i, bytes_read, datasize; unsigned char buffer[CHUNK_HEADER_SIZE], id[5];
BitMapHeader *bmheader = NULL; int i, bytes_read, datasize, imgdata_size;
ColorRegister *colors = NULL; BitMapHeader *bmheader = NULL;
UBYTE *imgdata = NULL; ColorRegister *colors = NULL;
IFFData *result = malloc(sizeof(IFFData)); UBYTE *imgdata = NULL;
ILBMData *result = calloc(1, sizeof(ILBMData));
while (total_read < filesize) {
bytes_read = fread(buffer, sizeof(char), 8, fp);
for (i = 0; i < 4; i++) id[i] = buffer[i];
id[4] = 0;
while (total_read < filesize) {
bytes_read = fread(buffer, sizeof(char), 8, fp);
for (i = 0; i < 4; i++) id[i] = buffer[i];
id[4] = 0;
#ifdef LITTLE_ENDIAN #ifdef LITTLE_ENDIAN
datasize = __bswap_32(*((ULONG *) &buffer[4])); datasize = __bswap_32(*((ULONG *) &buffer[4]));
#else #else
datasize = *((ULONG *) &buffer[4]); datasize = *((ULONG *) &buffer[4]);
#endif #endif
if (!strncmp("BMHD", buffer, 4)) bmheader = read_BMHD(fp, datasize);
if (!strncmp("BMHD", buffer, 4)) bmheader = read_BMHD(fp, datasize); else if (!strncmp("CMAP", buffer, 4)) colors = read_CMAP(fp, datasize, &result->num_colors);
else if (!strncmp("CMAP", buffer, 4)) colors = read_CMAP(fp, datasize); else if (!strncmp("CRNG", buffer, 4)) read_CRNG(fp, datasize);
else if (!strncmp("CRNG", buffer, 4)) read_CRNG(fp, datasize); else if (!strncmp("CAMG", buffer, 4)) read_CAMG(fp, datasize);
else if (!strncmp("CAMG", buffer, 4)) read_CAMG(fp, datasize); else if (!strncmp("BODY", buffer, 4)) imgdata = read_BODY(fp, datasize, bmheader, &imgdata_size);
else if (!strncmp("BODY", buffer, 4)) imgdata = read_BODY(fp, datasize, bmheader); else {
else {
#ifdef DEBUG #ifdef DEBUG
printf("WARNING - Unsupported chunk '%s', size: %d\n", id, datasize); printf("WARNING - Unsupported chunk '%s', size: %d\n", id, datasize);
#endif #endif
skip_chunk(fp, datasize); skip_chunk(fp, datasize);
}
/* Padding to even if necessary */
if (datasize % 2) {
fseek(fp, 1, SEEK_CUR);
datasize++;
}
total_read += datasize + CHUNK_HEADER_SIZE;
} }
/* Padding to even if necessary */ printf("total read: %d\n", total_read);
if (datasize % 2) { result->imgdata = imgdata;
fseek(fp, 1, SEEK_CUR); result->data_bytes = imgdata_size;
datasize++; result->colors = colors;
} result->bmheader = bmheader;
total_read += datasize + CHUNK_HEADER_SIZE; return result;
}
printf("total read: %d\n", total_read);
/*
if (imgdata) free(imgdata);
if (colors) free(colors);
if (bmheader) free(bmheader);*/
result->imgdata = imgdata;
result->colors = colors;
result->bmheader = bmheader;
return result;
} }
IFFData *parse_file(const char *path) ILBMData *parse_file(const char *path)
{ {
FILE *fp; FILE *fp;
char buffer[IFF_HEADER_SIZE]; char buffer[IFF_HEADER_SIZE];
size_t bytes_read; size_t bytes_read;
ULONG filesize, total_read = 0; ULONG filesize, total_read = 0;
IFFData *result = NULL; ILBMData *result = NULL;
fp = fopen(path, "rb"); fp = fopen(path, "rb");
@ -214,10 +212,11 @@ IFFData *parse_file(const char *path)
} else { } else {
puts("not an IFF file"); puts("not an IFF file");
} }
fclose(fp);
return result; return result;
} }
void free_iffdata(IFFData *data) void free_ilbm_data(ILBMData *data)
{ {
if (data) { if (data) {
if (data->colors) free(data->colors); if (data->colors) free(data->colors);
@ -227,15 +226,24 @@ void free_iffdata(IFFData *data)
} }
} }
void print_ilbm_info(ILBMData *data)
{
printf("width: %d, height: %d, # planes: %d # colors: %d\n",
(int) data->bmheader->w,
(int) data->bmheader->h,
(int) data->bmheader->nPlanes,
data->num_colors);
}
#ifdef STANDALONE #ifdef STANDALONE
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
if (argc <= 1) { if (argc <= 1) {
puts("usage: ilbm <image-file>"); puts("usage: ilbm <image-file>");
} else { } else {
IFFData *data = parse_file(argv[1]); ILBMData *data = parse_file(argv[1]);
free_iffdata(data); print_ilbm_info(data);
free_ilbm_data(data);
} }
} }
#endif #endif

View File

@ -34,6 +34,9 @@
#define LONG int32_t #define LONG int32_t
#define WORD int16_t #define WORD int16_t
#define BYTE int8_t #define BYTE int8_t
typedef int BOOL;
#define TRUE 1
#define FALSE 0
#define HAM 0x800 #define HAM 0x800
#define EXTRA_HALFBRITE 0x80 #define EXTRA_HALFBRITE 0x80
@ -77,12 +80,13 @@ typedef struct {
UBYTE low, high; UBYTE low, high;
} CRange; } CRange;
typedef struct _IFFData { typedef struct _ILBMData {
BitMapHeader *bmheader; BitMapHeader *bmheader;
int num_colors, data_bytes;
ColorRegister *colors; ColorRegister *colors;
UBYTE *imgdata; UBYTE *imgdata;
} IFFData; } ILBMData;
extern IFFData *parse_file(const char *path); extern ILBMData *parse_file(const char *path);
extern void free_iffdata(IFFData *data); extern void free_ilbm_data(ILBMData *data);
#endif /* __ILBM_H__ */ #endif /* __ILBM_H__ */