ref: 344b1ae931dc2aafeac0a526a5c1432f36570e4f
author: Jacob Moody <moody@posixcafe.org>
date: Sun Feb 12 22:02:48 EST 2023
grpfs
--- /dev/null
+++ b/grpfs.c
@@ -1,0 +1,245 @@
+#include <u.h>
+#include <libc.h>
+#include <fcall.h>
+#include <thread.h>
+#include <9p.h>
+
+typedef struct Tile Tile;
+typedef struct XFile XFile;
+typedef struct Grp Grp;
+
+enum { Qfile, Qtile };
+
+struct XFile {
+ char type;
+ char name[12+1];
+ ushort x, y;
+ ulong size; /* for Qtile size is of image(6) buffer */
+ ulong off;
+ uchar *buf;
+};
+
+struct Grp {
+ int fd;
+ int nf;
+ XFile *f;
+ int nt;
+ XFile *tiles;
+ uint pal[256];
+};
+
+ulong
+get16(uchar *b)
+{
+ ulong x;
+
+ x = (b[0]<<0) | (b[1]<<8);
+ return x;
+}
+
+ulong
+get32(uchar *b)
+{
+ ulong x;
+
+ x = (b[0]<<0) | (b[1]<<8) | (b[2]<<16) | (b[3]<<24);
+ return x;
+}
+
+Grp ggrp;
+
+static void
+fsreadtile(Req *r)
+{
+ XFile *f;
+ static uchar buf[64*1024];
+ uint *dot;
+ int i;
+
+ f = r->fid->file->aux;
+ if(f->buf == nil){
+ print("reading %d x %d tile\n", f->x, f->y);
+ f->buf = mallocz((11 * 5) + 5 + (f->x * f->y * 4), 1);
+ sprint((char*)f->buf, "%11s %11d %11d %11d %11d", "a8r8g8b8", 0, 0, f->x, f->y);
+ dot = (uint*)(f->buf + (11 * 5) + 5);
+ pread(ggrp.fd, buf, f->x * f->y, f->off);
+ for(i = 0; i < f->x * f->y; i++){
+ dot[i] = ggrp.pal[buf[i]];
+ }
+ f->size = (11 * 5) + 5 + (f->x * f->y * 4);
+ }
+ readbuf(r, f->buf, f->size);
+ respond(r, nil);
+}
+
+static void
+fsread(Req *r)
+{
+ XFile *f;
+
+ f = r->fid->file->aux;
+
+ if(f->type == Qtile){
+ fsreadtile(r);
+ return;
+ }
+
+ r->ofcall.count = r->ifcall.count;
+ if(r->ifcall.offset >= f->size){
+ r->ofcall.count = 0;
+ respond(r, nil);
+ return;
+ }
+ if(r->ifcall.offset+r->ofcall.count > f->size)
+ r->ofcall.count = f->size - r->ifcall.offset;
+ r->ofcall.count = pread(ggrp.fd, r->ofcall.data, r->ofcall.count, r->ifcall.offset+f->off);
+ respond(r, nil);
+}
+
+Srv fs = {
+ .read=fsread,
+};
+
+void
+parseart(int fd, ulong off)
+{
+ static short tilesx[1024];
+ static short tilesy[1024];
+ uchar buf[16];
+ XFile *f;
+ int nt, i, n;
+ ulong start;
+
+ start = off;
+ n = pread(fd, buf, 16, start);
+ off += n;
+ nt = get32(buf+12) - get32(buf+8) + 1;
+
+ for(i = 0; i < nt; i++){
+ pread(fd, buf, 2, start + 16 + (i * 2));
+ tilesx[i] = get16(buf);
+ }
+ for(i = 0; i < nt; i++){
+ pread(fd, buf, 2, start + 16 + ((i+nt) * 2));
+ tilesy[i] = get16(buf);
+ }
+ off += (nt * 2) + (nt * 2) + (nt * 4);
+
+ ggrp.tiles = realloc(ggrp.tiles, sizeof(XFile) * (ggrp.nt + nt));
+ memset(&ggrp.tiles[ggrp.nt], 0, nt * sizeof(XFile));
+ f = ggrp.tiles + ggrp.nt;
+ for(i = 0; i < nt; i++,f++){
+ f->type = Qtile;
+ f->x = tilesx[i];
+ f->y = tilesy[i];
+ f->off = off;
+ off += tilesx[i] * tilesy[i];
+ }
+ ggrp.nt += nt;
+}
+
+void
+parsepal(int fd, int off)
+{
+ uchar buf[256 * 3];
+ int i;
+
+ memset(ggrp.pal, 0, sizeof ggrp.pal);
+ pread(fd, buf, sizeof buf, off);
+ for(i = 0; i < sizeof buf; i += 3){
+ //print("%ud %ud %ud\n", buf[i], buf[i+1], buf[i+2]);
+ ggrp.pal[i/3] = ((buf[i+2]*4)<<0) | ((buf[i+1]*4)<<8) | ((buf[i]*4)<<16);
+ }
+}
+
+void
+parsegrp(int fd)
+{
+ char *kens = "KenSilverman";
+ uchar buf[64];
+ int i, n;
+ ulong off;
+ XFile *f;
+ char *user;
+ File *dir;
+
+ off = n = read(fd, buf, strlen(kens));
+ if(n < 0 || memcmp(buf, kens, n) != 0)
+ sysfatal("invalid file");
+
+ n = read(fd, buf, 4);
+ if(n != 4)
+ sysfatal("failed to read number of files");
+
+ user = getenv("user");
+ fs.tree = alloctree(user, "sys", 0644, nil);
+ off += n;
+ ggrp.fd = fd;
+ ggrp.nf = get32((uchar*)buf);
+ ggrp.f = f = mallocz(sizeof(XFile) * ggrp.nf, 1);
+ for(i = 0; i < ggrp.nf; i++,f++){
+ n = read(fd, f->name, sizeof(f->name) - 1);
+ off += n;
+ n = read(fd, buf, 4);
+ off += n;
+ f->size = get32((uchar*)buf);
+ }
+
+ ggrp.nt = 0;
+ f = ggrp.f;
+ for(i = 0; i < ggrp.nf; i++,f++){
+ f->off = off;
+ if(strstr(f->name, ".ART") != nil)
+ parseart(fd, off);
+ else
+ createfile(fs.tree->root, f->name, user, 0666, f);
+
+ if(strcmp(f->name, "PALETTE.DAT") == 0)
+ parsepal(fd, off);
+ off = f->off + f->size;
+ }
+
+ dir = createfile(fs.tree->root, "ART", user, 0644|DMDIR, nil);
+ for(i = 0; i < ggrp.nt; i++)
+ createfile(dir, smprint("%05d.TILE", i), user, 0666, ggrp.tiles + i);
+ free(user);
+}
+
+static void
+usage(void)
+{
+ fprint(2, "usage: %s grpfile\n", argv0);
+ exits("usage");
+}
+
+void
+main(int argc, char **argv)
+{
+ char *mtpt, *srvname;
+ int fd;
+
+ srvname = nil;
+ mtpt = "/mnt/grp";
+ ARGBEGIN{
+ case 's':
+ srvname = EARGF(usage());
+ break;
+ case 'm':
+ mtpt = EARGF(usage());
+ break;
+ default:
+ usage();
+ break;
+ }ARGEND;
+
+ if(argc < 1)
+ usage();
+
+ fd = open(argv[0], OREAD);
+ if(fd < 0)
+ sysfatal("%r");
+
+ parsegrp(fd);
+ postmountsrv(&fs, srvname, mtpt, MREPL);
+ exits(nil);
+}
--- /dev/null
+++ b/mkfile
@@ -1,0 +1,7 @@
+</$objtype/mkfile
+
+BIN=/$objtype/bin/games
+TARG=\
+ grpfs\
+
+</sys/src/cmd/mkmany