aboutsummaryrefslogtreecommitdiffstats
path: root/src/gfile/gfile_fs_rom.c
blob: ec07ec34506a62440468e8f7feee3258647b1025 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
/*
 * This file is subject to the terms of the GFX License. If a copy of
 * the license was not distributed with this file, you can obtain one at:
 *
 *              http://ugfx.org/license.html
 */

/********************************************************
 * The ROM file-system
 ********************************************************/

#include "../../gfx.h"

#if GFX_USE_GFILE && GFILE_NEED_ROMFS

#include "gfile_fs.h"

#include <string.h>

// What directory file formats do we understand
#define ROMFS_DIR_VER_MAX			0x0000

// Compression Formats
#define ROMFS_CMP_UNCOMPRESSED		0

typedef struct ROMFS_DIRENTRY {
	uint16_t						ver;			// Directory Entry Version
	uint16_t						cmp;			// Compression format
	const struct ROMFS_DIRENTRY *	next;			// The next entry
	const char *					name;			// The file name
	long int						size;			// The file size
	const char *					file;			// The file data
} ROMFS_DIRENTRY;

#define ROMFS_DIRENTRY_HEAD		0
#include "romfs_files.h"
static const ROMFS_DIRENTRY const *FsROMHead = ROMFS_DIRENTRY_HEAD;

typedef struct ROMFileList {
	gfileList				fl;
	const ROMFS_DIRENTRY	*pdir;
} ROMFileList;


static bool_t ROMExists(const char *fname);
static long int	ROMFilesize(const char *fname);
static bool_t ROMOpen(GFILE *f, const char *fname);
static void ROMClose(GFILE *f);
static int ROMRead(GFILE *f, void *buf, int size);
static bool_t ROMSetpos(GFILE *f, long int pos);
static long int ROMGetsize(GFILE *f);
static bool_t ROMEof(GFILE *f);
#if GFILE_NEED_FILELISTS
	static gfileList *ROMFlOpen(const char *path, bool_t dirs);
	static const char *ROMFlRead(gfileList *pfl);
	static void ROMFlClose(gfileList *pfl);
#endif

const GFILEVMT FsROMVMT = {
	GFSFLG_CASESENSITIVE|GFSFLG_SEEKABLE|GFSFLG_FAST,	// flags
	'S',												// prefix
	0, ROMExists, ROMFilesize, 0,
	ROMOpen, ROMClose, ROMRead, 0,
	ROMSetpos, ROMGetsize, ROMEof,
	0, 0, 0,
	#if GFILE_NEED_FILELISTS
		ROMFlOpen, ROMFlRead, ROMFlClose
	#endif
};

static const ROMFS_DIRENTRY *ROMFindFile(const char *fname)
{
	const ROMFS_DIRENTRY *p;

	for(p = FsROMHead; p; p = p->next) {
		if (p->ver <= ROMFS_DIR_VER_MAX && p->cmp == ROMFS_CMP_UNCOMPRESSED && !strcmp(p->name, fname))
			break;
	}
	return p;
}

static bool_t ROMExists(const char *fname)
{
	return ROMFindFile(fname) != 0;
}

static long int	ROMFilesize(const char *fname)
{
	const ROMFS_DIRENTRY *p;

	if (!(p = ROMFindFile(fname))) return -1;
	return p->size;
}

static bool_t ROMOpen(GFILE *f, const char *fname)
{
	const ROMFS_DIRENTRY *p;

	if (!(p = ROMFindFile(fname))) return FALSE;
	f->obj = (void *)p;
	return TRUE;
}

static void ROMClose(GFILE *f)
{
	(void)f;
}

static int ROMRead(GFILE *f, void *buf, int size)
{
	const ROMFS_DIRENTRY *p;

	p = (const ROMFS_DIRENTRY *)f->obj;
	if (p->size - f->pos < size)
		size = p->size - f->pos;
	if (size <= 0)	return 0;
	memcpy(buf, p->file+f->pos, size);
	return size;
}

static bool_t ROMSetpos(GFILE *f, long int pos)
{
	return pos <= ((const ROMFS_DIRENTRY *)f->obj)->size;
}

static long int ROMGetsize(GFILE *f)
{
	return ((const ROMFS_DIRENTRY *)f->obj)->size;
}

static bool_t ROMEof(GFILE *f)
{
	return f->pos >= ((const ROMFS_DIRENTRY *)f->obj)->size;
}

#if GFILE_NEED_FILELISTS
	static gfileList *ROMFlOpen(const char *path, bool_t dirs) {
		ROMFileList *	p;
		(void)			path;

		// We don't support directories or path searching
		if (dirs)
			return 0;

		// Allocate the list buffer
		if (!(p = gfxAlloc(sizeof(ROMFileList))))
			return 0;

		// Initialize it and return it.
		p->pdir = 0;
		return &p->fl;
	}

	static const char *ROMFlRead(gfileList *pfl) {
		#define rfl		((ROMFileList *)pfl)

		// Is it the first entry
		if (!rfl->pdir) {
			rfl->pdir = FsROMHead;
			return FsROMHead->name;
		}

		// Is it not the last entry
		if (rfl->pdir->next) {
			rfl->pdir = rfl->pdir->next;
			return rfl->pdir->name;
		}

		return 0;
		#undef rfl
	}

	static void ROMFlClose(gfileList *pfl) {
		gfxFree(pfl);
	}
#endif

#endif //GFX_USE_GFILE && GFILE_NEED_ROMFS