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();