Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# KallistiOS ##version##
#
# libkmg Makefile
# Copyright (c)2003 Dan Potter
# Copyright (c)2003 Megan Potter

TARGET = libkmg.a
OBJS = kmg.o
Expand All @@ -13,5 +13,5 @@ include $(KOS_BASE)/addons/Makefile.prefab

# creates the kos link to the headers
create_kos_link:
rm -f ../include/kmg
ln -s ../libkmg/include ../include/kmg
rm -f $(KOS_PORTS)/include/kmg
ln -s $(CURDIR)/include $(KOS_PORTS)/include/kmg
75 changes: 33 additions & 42 deletions include/kmg.h
Original file line number Diff line number Diff line change
@@ -1,77 +1,68 @@
/* KallistiOS ##version##

kmg/kmg.h
Copyrigh (C)2003 Dan Potter
Copyrigh (C)2003 Megan Potter
*/

#ifndef __KMG_KMG_H
#define __KMG_KMG_H

#ifdef _arch_dreamcast
# include <sys/cdefs.h>
__BEGIN_DECLS

# include <arch/types.h>
#else

#ifdef NEED_KOS_TYPES
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned long uint32;
#endif

# include <sys/cdefs.h>
__BEGIN_DECLS
#endif

#include <stdint.h>

/* Header for KMG files. This isn't particularly meant to be future-proof
since generally you'll build your textures into this format and then
pair that data with an executable build. For safety though, we go ahead
and put a version number anyway. All fields are _little endian_. */
typedef struct kmg_header {
uint32 magic; /* Magic code */
uint32 version; /* Version code */
uint32 platform; /* Platform specifier (major format) */
uint32 format; /* Image (minor) format spec */
uint32 width; /* Image width */
uint32 height; /* Image height */
uint32 byte_count; /* Image's data size in bytes */
uint8 padding[36]; /* Pad to a 64-byte header (all zeros) */
uint32_t magic; /* Magic code */
uint32_t version; /* Version code */
uint32_t platform; /* Platform specifier (major format) */
uint32_t format; /* Image (minor) format spec */
uint32_t width; /* Image width */
uint32_t height; /* Image height */
uint32_t byte_count; /* Image's data size in bytes */
uint8_t padding[36]; /* Pad to a 64-byte header (all zeros) */
} kmg_header_t;

/* Magic code -- every KMG will start with one of these. */
#define KMG_MAGIC 0x00474d4b /* 'KMG\0' */
#define KMG_MAGIC 0x00474d4b /* 'KMG\0' */

/* Version specifier -- for this version of the lib. A new version
means the files are incompatible. */
#define KMG_VERSION 1
#define KMG_VERSION 1

/* Platform specifiers */
#define KMG_PLAT_DC 1
#define KMG_PLAT_GBA 2
#define KMG_PLAT_PS2 3
#define KMG_PLAT_DC 1
#define KMG_PLAT_GBA 2
#define KMG_PLAT_PS2 3

/* Format specifiers for DC */
#define KMG_DCFMT_4BPP_PAL 0x01 /* Paletted formats */
#define KMG_DCFMT_8BPP_PAL 0x02
#define KMG_DCFMT_RGB565 0x03 /* True-color formats */
#define KMG_DCFMT_ARGB4444 0x04
#define KMG_DCFMT_ARGB1555 0x05
#define KMG_DCFMT_YUV422 0x06
#define KMG_DCFMT_BUMP 0x07
#define KMG_DCFMT_MASK 0xff

#define KMG_DCFMT_VQ 0x0100 /* VQ-encoded (incl codebook) */
#define KMG_DCFMT_TWIDDLED 0x0200 /* Pre-twiddled */
#define KMG_DCFMT_MIPMAP 0x0400 /* Includes mipmaps */
#define KMG_DCFMT_4BPP_PAL 0x01 /* Paletted formats */
#define KMG_DCFMT_8BPP_PAL 0x02
#define KMG_DCFMT_RGB565 0x03 /* True-color formats */
#define KMG_DCFMT_ARGB4444 0x04
#define KMG_DCFMT_ARGB1555 0x05
#define KMG_DCFMT_YUV422 0x06
#define KMG_DCFMT_BUMP 0x07
#define KMG_DCFMT_MASK 0xff

#define KMG_DCFMT_VQ 0x0100 /* VQ-encoded (incl codebook) */
#define KMG_DCFMT_TWIDDLED 0x0200 /* Pre-twiddled */
#define KMG_DCFMT_MIPMAP 0x0400 /* Includes mipmaps */

#ifdef _arch_dreamcast

/* Call to load a KMG file from the VFS. */
int kmg_to_img(const char * fn, kos_img_t * rv);
/* Call to load a KMG file from the VFS. */
int kmg_to_img(const char *fn, kos_img_t *rv);


__END_DECLS
__END_DECLS
#endif

#endif /* __KMG_KMG_H */
#endif /* __KMG_KMG_H */

226 changes: 113 additions & 113 deletions kmg.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
KOS image format loader library

kmg.c
Copyright (C)2003 Dan Potter
Copyright (C)2003 Megan Potter

*/

Expand All @@ -21,116 +21,116 @@
Note also that the allocated buffer for the image will be 32-byte
aligned so you can DMA the textures straight to VRAM. */

int kmg_to_img(const char * fn, kos_img_t * rv) {
file_t f;
kmg_header_t hdr;
int dep;
void * map;

assert( rv != NULL );

/* Open the file */
f = fs_open(fn, O_RDONLY);
if (f == FILEHND_INVALID) {
dbglog(DBG_ERROR, "kmg_to_img: can't open file '%s'\n", fn);
return -1;
}

/* Read the header */
if (fs_read(f, &hdr, sizeof(hdr)) != sizeof(hdr)) {
fs_close(f);
dbglog(DBG_ERROR, "kmg_to_img: can't read header from file '%s'\n", fn);
return -2;
}

/* Verify a few things */
if (hdr.magic != KMG_MAGIC || hdr.version != KMG_VERSION ||
hdr.platform != KMG_PLAT_DC)
{
fs_close(f);
dbglog(DBG_ERROR, "kmg_to_img: file '%s' is incompatible:\n"
" magic %08lx version %d platform %d\n",
fn, hdr.magic, (int)hdr.version, (int)hdr.platform);
return -3;
}

/* See if we can mmap the thing. If so, then we'll just make it
a non-owned buffer that way and save some transfers. */
map = fs_mmap(f);
if (map) {
rv->data = ((uint8 *)map) + sizeof(hdr);
}

/* Setup the kimg struct */
rv->w = hdr.width;
rv->h = hdr.height;

dep = 0;
if (hdr.format & KMG_DCFMT_VQ)
dep |= PVR_TXRLOAD_FMT_VQ;
if (hdr.format & KMG_DCFMT_TWIDDLED)
dep |= PVR_TXRLOAD_FMT_TWIDDLED;

switch (hdr.format & KMG_DCFMT_MASK) {
case KMG_DCFMT_RGB565:
rv->fmt = KOS_IMG_FMT(KOS_IMG_FMT_RGB565, dep);
break;

case KMG_DCFMT_ARGB4444:
rv->fmt = KOS_IMG_FMT(KOS_IMG_FMT_ARGB4444, dep);
break;

case KMG_DCFMT_ARGB1555:
rv->fmt = KOS_IMG_FMT(KOS_IMG_FMT_ARGB1555, dep);
break;

case KMG_DCFMT_YUV422:
rv->fmt = KOS_IMG_FMT(KOS_IMG_FMT_YUV422, dep);
break;

case KMG_DCFMT_BUMP:
/* XXX */
rv->fmt = KOS_IMG_FMT(KOS_IMG_FMT_RGB565, dep);
break;

case KMG_DCFMT_4BPP_PAL:
case KMG_DCFMT_8BPP_PAL:
default:
assert_msg( 0, "currently-unsupported KMG pixel format" );
fs_close(f);
free(rv->data);
return -5;
}

rv->byte_count = hdr.byte_count;

/* And load the rest of it if necessary */
if (map) {
rv->fmt = KOS_IMG_FMT(KOS_IMG_FMT_I(rv->fmt) | KOS_IMG_NOT_OWNER,
KOS_IMG_FMT_D(rv->fmt));
} else {
rv->data = malloc(hdr.byte_count);
if (!rv->data) {
dbglog(DBG_ERROR, "kmg_to_img: can't malloc(%d) while loading '%s'\n",
(int)hdr.byte_count, fn);
fs_close(f);
return -4;
}
if (fs_read(f, rv->data, rv->byte_count) != rv->byte_count) {
dbglog(DBG_ERROR, "kmg_to_img: can't read %d bytes while loading '%s'\n",
(int)hdr.byte_count, fn);
fs_close(f);
free(rv->data);
return -6;
}
}

/* Ok, all done */
fs_close(f);

/* If the byte count is not a multiple of 32, bump it up as well.
This is for DMA/SQ usage. */
rv->byte_count = (rv->byte_count + 31) & ~31;

return 0;
int kmg_to_img(const char *fn, kos_img_t *rv) {
file_t f;
kmg_header_t hdr;
int dep;
void *map;

assert( rv != NULL );

/* Open the file */
f = fs_open(fn, O_RDONLY);
if (f == FILEHND_INVALID) {
dbglog(DBG_ERROR, "kmg_to_img: can't open file '%s'\n", fn);
return -1;
}

/* Read the header */
if (fs_read(f, &hdr, sizeof(hdr)) != sizeof(hdr)) {
fs_close(f);
dbglog(DBG_ERROR, "kmg_to_img: can't read header from file '%s'\n", fn);
return -2;
}

/* Verify a few things */
if (hdr.magic != KMG_MAGIC || hdr.version != KMG_VERSION ||
hdr.platform != KMG_PLAT_DC)
{
fs_close(f);
dbglog(DBG_ERROR, "kmg_to_img: file '%s' is incompatible:\n"
" magic %08lx version %d platform %d\n",
fn, hdr.magic, (int)hdr.version, (int)hdr.platform);
return -3;
}

/* See if we can mmap the thing. If so, then we'll just make it
a non-owned buffer that way and save some transfers. */
map = fs_mmap(f);
if (map) {
rv->data = ((uint8_t *)map) + sizeof(hdr);
}

/* Setup the kimg struct */
rv->w = hdr.width;
rv->h = hdr.height;

dep = 0;
if (hdr.format & KMG_DCFMT_VQ)
dep |= PVR_TXRLOAD_FMT_VQ;
if (hdr.format & KMG_DCFMT_TWIDDLED)
dep |= PVR_TXRLOAD_FMT_TWIDDLED;

switch (hdr.format & KMG_DCFMT_MASK) {
case KMG_DCFMT_RGB565:
rv->fmt = KOS_IMG_FMT(KOS_IMG_FMT_RGB565, dep);
break;

case KMG_DCFMT_ARGB4444:
rv->fmt = KOS_IMG_FMT(KOS_IMG_FMT_ARGB4444, dep);
break;

case KMG_DCFMT_ARGB1555:
rv->fmt = KOS_IMG_FMT(KOS_IMG_FMT_ARGB1555, dep);
break;

case KMG_DCFMT_YUV422:
rv->fmt = KOS_IMG_FMT(KOS_IMG_FMT_YUV422, dep);
break;

case KMG_DCFMT_BUMP:
/* XXX */
rv->fmt = KOS_IMG_FMT(KOS_IMG_FMT_RGB565, dep);
break;

case KMG_DCFMT_4BPP_PAL:
case KMG_DCFMT_8BPP_PAL:
default:
assert_msg( 0, "currently-unsupported KMG pixel format" );
fs_close(f);
free(rv->data);
return -5;
}

rv->byte_count = hdr.byte_count;

/* And load the rest of it if necessary */
if (map) {
rv->fmt = KOS_IMG_FMT(KOS_IMG_FMT_I(rv->fmt) | KOS_IMG_NOT_OWNER,
KOS_IMG_FMT_D(rv->fmt));
} else {
rv->data = malloc(hdr.byte_count);
if (!rv->data) {
dbglog(DBG_ERROR, "kmg_to_img: can't malloc(%d) while loading '%s'\n",
(int)hdr.byte_count, fn);
fs_close(f);
return -4;
}
if (fs_read(f, rv->data, rv->byte_count) != rv->byte_count) {
dbglog(DBG_ERROR, "kmg_to_img: can't read %d bytes while loading '%s'\n",
(int)hdr.byte_count, fn);
fs_close(f);
free(rv->data);
return -6;
}
}

/* Ok, all done */
fs_close(f);

/* If the byte count is not a multiple of 32, bump it up as well.
This is for DMA/SQ usage. */
rv->byte_count = (rv->byte_count + 31) & ~31;

return 0;
}
8 changes: 4 additions & 4 deletions module_main.c
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
/* KallistiOS ##version##

module_main.c
Copyright (C)2003 Dan Potter
Copyright (C)2003 Megan Potter

*/

#include <kos/library.h>
#include <kos/exports.h>

const char * lib_get_name() {
return "imgloader.kmg";
const char *lib_get_name(void) {
return "imgloader.kmg";
}