shithub: dporg

Download patch

ref: 2680c99732db8591e945c10dfb67f45d3c9f551f
parent: 5f46149bb72df55aecbe51fd6faec2dc3b36ef1a
author: qwx <qwx@sciops.net>
date: Mon May 17 04:16:01 EDT 2021

drw: add drawing text

- load charmap and split font sprite sheet into a pic array
- scrollpic: fix out of bounds when moving past pic's right boundary
- change background color to same as emulators at least for now
- intro: fix setting string index out of bounds

--- a/dat.h
+++ b/dat.h
@@ -11,6 +11,8 @@
 	Vcentery = Vh / 2,
 	Vfntw = 7,
 	Vfnth = 12,
+	Vfntspc = 1,
+	Vfntpicw = Vfntspc+Vfntw+Vfntspc,
 
 	Kfire = 0,
 	K↑,
@@ -34,7 +36,6 @@
 extern u32int *pal;
 
 enum{
-	PCfont,
 	PCarrow,
 	PCspace,
 	PCgrid,
@@ -56,6 +57,10 @@
 	int h;
 };
 extern Pic pics[PCend], canvas;
+extern nfontmap;
+extern uchar *fontmap;
+extern int nglyph;
+extern Pic *dfont;
 
 enum{
 	DShip = 0xffbb0000,
--- a/drw.c
+++ b/drw.c
@@ -11,24 +11,32 @@
 static u32int fb[Vw * Vfullh];
 static int scale, fbsz;
 static Rectangle fbsr;
-static Image *fbs;
+static Image *fbs, *bgcol;
 static u32int *fbsbuf;
 
 void
 scrollpic(Pic *pp, int Δx)
 {
-	int h, w;
-	u32int *s, *d;
+	int h, x, Δs;
+	u32int *s, *d, *e;
 
 	d = canvas.p;
-	s = pp->p + Δx % pp->w;
+	Δx %= pp->w;
+	s = pp->p + Δx;
+	x = (canvas.w + Δx) - pp->w;
+	Δs = pp->w - canvas.w;
+	if(x > 0)
+		Δs += pp->w;
 	for(h=0; h<canvas.h; h++){
-		for(w=0; w<canvas.w; w++){
+		for(x=Δx, e=d+canvas.w; d<e; d++, s++){
 			if(*s >> 24)
 				*d = *s;
-			d++, s++;
+			if(x++ == pp->w){
+				s -= pp->w;
+				x = 0;
+			}
 		}
-		s += pp->w - canvas.w;
+		s += Δs;
 	}
 }
 
@@ -38,6 +46,7 @@
 	int w, pw;
 	u32int *d, *s, *e;
 
+	assert(x < Vw && y < Vh);
 	d = fb + Vw * y + x;
 	s = pp->p;
 	pw = pp->w;
@@ -55,16 +64,37 @@
 void
 drawsubstr(int x, int y, char *s, char *e)
 {
-	// FIXME
-	USED(x,y,s,e);
-	//use a drawsubpic?
+	int c, w, h, px, py;
+
+	w = dfont[0].w;
+	h = dfont[0].h;
+	x += Vfntspc;
+	for(px=x, py=y; s<e; s++){
+		c = *s;
+		if(c == '\n'){
+			px = x;
+			py += h;
+			if(py >= Vh - h)
+				sysfatal("drawsubstr: drawing string past screen: %s at %d,%d", s, x, y);
+			continue;
+		}else if(c < fontmap[0])
+			goto skip;
+		/* FIXME: characters >128 */
+		c -= fontmap[0];
+		if(c > nglyph)
+			sysfatal("drawsubstr: invalid glyph index %d (nglyph %d)", c, nglyph);
+		drawpic(px, py, &dfont[c]);
+	skip:
+		px += w;
+		if(px >= Vw - w)
+			sysfatal("drawsubstr: drawing string past screen: %s at %d,%d", s, x, y);
+	}
 }
 
 void
 drawstr(int x, int y, char *s)
 {
-	// FIXME
-	USED(x,y,s);
+	drawsubstr(x, y, s, s+strlen(s));
 }
 
 void
@@ -160,7 +190,7 @@
 	fbsbuf = nil;
 	if(scale != 1)
 		fbsbuf = emalloc(fbsz);
-	draw(screen, screen->r, display->black, nil, ZP);
+	draw(screen, screen->r, bgcol, nil, ZP);
 	if(paint)
 		drawfb();
 	else
@@ -173,5 +203,7 @@
 	if(initdraw(nil, nil, "dporg") < 0)
 		sysfatal("initdraw: %r");
 	loadpics();
+	if((bgcol = allocimage(display, Rect(0,0,1,1), XRGB32, 1, 0xccccccff)) == nil)
+		sysfatal("allocimage: %r");
 	resetfb(0);
 }
--- a/fs.c
+++ b/fs.c
@@ -7,6 +7,10 @@
 
 s32int sintab[256];
 char **basestr;
+int nfontmap;
+uchar *fontmap;
+int nglyph;
+Pic *dfont;
 
 static Biobuf *
 eopen(char *s, int mode)
@@ -27,6 +31,20 @@
 	return n;
 }
 
+static vlong
+bsize(Biobuf *bf)
+{
+	vlong n;
+	Dir *d;
+
+	d = dirfstat(Bfildes(bf));
+	if(d == nil)
+		sysfatal("bstat: %r");
+	n = d->length;
+	free(d);
+	return n;
+}
+
 static u8int
 get8(Biobuf *bf)
 {
@@ -99,10 +117,38 @@
 	free(b);
 }
 
+static void
+loadfont(void)
+{
+	int i, n, nx, ny;
+	u32int *d, *s;
+	Pic pic, *pp;
+
+	loadpic("a.bit", &pic);
+	nx = pic.w / Vfntpicw;
+	ny = pic.h / Vfnth;
+	if(pic.w % nx != 0 || pic.h % ny != 0)
+		sysfatal("loadfont: invalid font pic");
+	nglyph = nx * ny;
+	dfont = emalloc(nglyph * sizeof *dfont);
+	for(i=0, pp=dfont; pp<dfont+nglyph; pp++, i++){
+		pp->w = Vfntw;
+		pp->h = Vfnth;
+		pp->p = emalloc(pp->w * pp->h * sizeof *pp->p);
+		d = pp->p;
+		s = pic.p + i / nx * pic.w * pp->h + i % nx * Vfntpicw + Vfntspc;
+		for(n=0; n<pp->h; n++){
+			memcpy(d, s, pp->w * sizeof *d);
+			d += pp->w;
+			s += pic.w;
+		}
+	}
+	free(pic.p);
+}
+
 void
 loadpics(void)
 {
-	loadpic("a.bit", pics + PCfont);
 	loadpic("b.bit", pics + PCarrow);
 	loadpic("c.bit", pics + PCspace);
 	loadpic("d.bit", pics + PCgrid);
@@ -116,6 +162,7 @@
 	loadpic("p.bit", pics + PCcur);
 	loadpic("q.bit", pics + PCscroll);
 	loadpic("r.bit", pics + PCgibs);
+	loadfont();
 	canvas.p = emalloc(Vw * Vfullh * sizeof *canvas.p);
 	canvas.w = Vw;
 	canvas.h = Vfullh;
@@ -171,6 +218,20 @@
 }
 
 static void
+loadfontmap(void)
+{
+	int n;
+	Biobuf *bf;
+
+	bf = eopen("a.map", OREAD);
+	n = bsize(bf);
+	fontmap = emalloc(n * sizeof *fontmap);
+	eread(bf, fontmap, n);
+	nfontmap = n;
+	Bterm(bf);
+}
+
+static void
 loadbasestr(void)
 {
 	int nel;
@@ -201,6 +262,7 @@
 	loadsintab();
 	loadpal();
 	loadbasestr();
+	loadfontmap();
 }
 
 // grids: 32/256/2048
@@ -211,6 +273,3 @@
 // entities.str
 // mappings.bin
 // map bsp + str (on demand, with shim load gauge)
-// a.map
-// base.str
-// + old project code
--- a/fsm.intro.c
+++ b/fsm.intro.c
@@ -79,8 +79,6 @@
 static void
 drawintrostr(void)
 {
-	if(stri < strlen(curstr))
-		stri = tc / txtΔt;
 	drawsubstr(canvmidx, canvmidy, curstr, curstr+stri);
 }
 
@@ -116,10 +114,12 @@
 static void
 scrollstep(void)
 {
-	int tc₁, tc₂;
+	static int tc₁, tc₂;
 
 	if(tc < steptc)
 		return;
+	if(tc >= tc₂ && stri < strlen(curstr))
+		stri++;
 	drawbg();
 	drawintrostr();
 	drawprompt();