shithub: sce

Download patch

ref: 49d5b03c43c8eb2f13909c8831705753be1c6233
parent: 2d7f5946613095d37db92f85490a33c5a2eff127
author: qwx <[email protected]>
date: Thu Apr 22 15:48:18 EDT 2021

begin rewrite of extraction scripts: add genspr2, scespr, scesha

- genspr2 will replace genspr as the main script; it does setup
  and performs the whole extraction
- scespr: generate a team color sprite sheet for a frame
- scesha: generate a shadow sprite from a frame image

deprecated: sceass, scerot

this implements the last insights on offset calculations.
grp files have a canvas width and height within which each frame
is painted, which was dismissed before.  in fact, these dimensions
must be known to calculate offsets for mirror rotations.

previously, when we generated rotations, we just set the same
offsets as the mirrored frame, which almost always results in an
incorrect x offset.  as vspr shows, only generated rotations have
wrong offsets.  the x offset correction is simply the slack space
between the right edge of the original sprite and the canvas width:

	Δx = canw - r.min.x - r.max.x

this takes care of mirror frames offsets.  next, there's a global
offset for drawing the frame.  this information is not in the grp
file but in unit tables.  units have w·h size in pixels and D/L/R/U
offsets from center in pixels.  offset for units looks to be the
difference between half the canvas width and the L offset, for both
dimensions:

	gΔx = gΔy = canw / 2 - L

for buildings, it seems to be multiples of -32: if global offset for
a dimensions is ≥ 32, it is set to -32:

	gΔx = canw / 2 - L >= 32 ? -32 : 0
	gΔy = canh / 2 - U >= 32 ? -32 : 0

shadows may have x and y offsets.  objects with a shadow sprite have
arbitrary offsets set somewhere else (dat files etc.), those have to
be either found prior to this or eyeballed.  the others have either
implied offsets or ones that are set elsewhere.  so far for ground
units it's (0,7) and (0,42) for air.  the buildings have different
ones that have been eyeballed with vspr.

this patch implements the basis of this all with a rewrite of genspr
and helper scripts.
remaining:
- sprites with transparency
- buildings, separate shadow sprites
- tileset
- clean(er) namespace manipulation
- testing

*hopefully*, it will all work out and we'll be able to fucking go on
to more interesting stuff!

--- /dev/null
+++ b/utils/genspr2
@@ -1,0 +1,72 @@
+#!/bin/rc -e
+rfork n
+bind -a $home/p/pico /bin
+bind -a $home/p/sce/utils /bin
+
+awk -v 'pid='$pid '
+function pipe(cmd){
+	if((cmd | getline x) != 1){
+		print cmd ": aborted"
+		exit("aborted")
+	}
+	return x
+}
+function exec(cmd){
+	if(system(cmd) != 0){
+		print cmd ": aborted"
+		exit("aborted")
+	}
+}
+
+function unit17(u,	i, r, n, fi, fo, gf, dim, rect, Δx, Δy){
+	n = split(units[u], a)
+	gf = u ".grp"
+	split(pipe("grp -s " palfile " " gf), dim)
+	for(i=4; i<=n; i++){
+		frm = a[i] * 17;
+		for(r=0; r<17; r+=2){
+			fi = sprintf(gf ".%05d.bit", frm + r)
+			fo = sprintf(u ".%02d.%02d.bit", frm, r)
+			fs = sprintf(u ".%02d.%02d.s.bit", frm, r)
+			split(pipe("read -c 60 " fi), rect)
+			goff = -(dim[1] / 2 - a[1])
+			Δx = rect[2] + goff
+			Δy = rect[3] + goff
+			exec("scespr " fi " " fo " " Δx " " Δy);
+			if(a[2] != "-")
+				exec("sceshad " fi " " fs " " Δx+a[2] " " Δy+a[3] " " a[2] " " a[3]);
+			if(r != 16){
+				exec("rotate -l " fi " >" tmp)
+				Δx += dim[1] - rect[2] - rect[4]
+				fo = sprintf(u ".%02d.%02d.bit", frm, 31-r)
+				fs = sprintf(u ".%02d.%02d.s.bit", frm, 31-r)
+				exec("scespr " tmp " " fo " " Δx " " Δy);
+				if(a[2] != "-")
+					exec("sceshad " tmp " " fs " " Δx+a[2] " " Δy+a[3] " " a[2] " " a[3]);
+			}
+		}
+	}
+	exec("rm -f " gf ".*bit")
+}
+
+BEGIN{
+	palfile = "SC_Unit_Palette.pal"
+	tmp = "/tmp/genspr." pid
+	units["scv"] = "11 0 7 0"
+	units["drone"] = "11 0 7 0 1 2 3 4"
+	units["mutalid"] = "22 0 42 0 1 2 3 4"
+	for(u in units){
+		unit17(u)
+	}
+}
+END{
+	exec("rm -f " tmp)
+}
+'
+
+# FIXME:
+# - setup: grp files, pal, etc.; tmp workspace
+#	. ramfs + window -m for monitoring
+#	. copy to final destination on success
+# - tileset, buildings + shadows, asprite
+# - testing
--- /dev/null
+++ b/utils/scesha
@@ -1,0 +1,25 @@
+#!/bin/rc -e
+if(! ~ $#* 6){
+	echo usage: $0 fi fo Δx Δy sΔx sΔy
+	exit usage
+}
+tmp=/tmp/scesha.$pid
+fi=$1
+fo=$2
+Δx=$3
+Δy=$4
+sΔx=$5
+sΔy=$6
+
+cat <<EOF | pico
+!r $fi f
+f = z == 3 ? f[x,y,0] == 0 && f[x,y,1] == Z && f[x,y,2] == Z ? 0 : Z/2+1 : 0
+m = y >= Y-($dΔy) ? 0 : f[x,y+($dΔy)]
+m = x >= X-($dΔx) ? 0 : m[x+($dΔx),y]
+r = z == 3 && m > 0 ? 0 : f
+!w $tmp r
+EOF
+
+iconv -c a8r8g8b8 $tmp |\
+	crop -t $Δx $Δy >$fo
+rm $tmp
--- /dev/null
+++ b/utils/scespr
@@ -1,0 +1,41 @@
+#!/bin/rc -e
+if(! ~ $#* 4){
+	echo usage: $0 fi fo Δx Δy
+	exit usage
+}
+tmp=/tmp/scespr.$pid
+fi=$1
+fo=$2
+Δx=$3
+Δy=$4
+dim=`{read -c 60 $fi | awk '{print $4-$2, $5-$3, 8*($5-$3)}'}
+dx=$dim(1)
+dh=$dim(2)
+dy=$dim(3)
+
+cat <<EOF | pico
+!r $fi s
+m = z == 3 ? Z : s[x,y,0] == Z && s[x,y,1] == 0 && s[x,y,2] == Z || s[x,y,0] == 222 && s[x,y,1] == 0 && s[x,y,2] == 222 || s[x,y,0] == 189 && s[x,y,1] == 0 && s[x,y,2] == 189 || s[x,y,0] == 156 && s[x,y,1] == 0 && s[x,y,2] == 156 || s[x,y,0] == 124 && s[x,y,1] == 0 && s[x,y,2] == 124 || s[x,y,0] == 91 && s[x,y,1] == 0 && s[x,y,2] == 91 || s[x,y,0] == 58 && s[x,y,1] == 0 && s[x,y,2] == 58 || s[x,y,0] == 25 && s[x,y,1] == 0 && s[x,y,2] == 25 ? s[x,y,0] : 0
+white = m > 0 ? m : s
+red = m > 0 ? z == 0 ? s[x,y,0] : z == 1 ? s[x,y,1] : z == 2 ? s[x,y,1] : Z : s
+blue = m > 0 ? z == 0 ? s[x,y,1] : z == 1 ? s[x,y,1] : z == 2 ? m : Z : s
+teal = m > 0 ? z == 0 ? s[x,y,1] : z == 1 ? s[x,y,0] : z == 2 ? s[x,y,0] : Z : s
+yellow = m > 0 ? z == 0 ? s[x,y,0] : z == 1 ? s[x,y,0] : z == 2 ? s[x,y,1] : Z : s
+purple = m > 0 ? z == 0 ? s[x,y,0]/2 : z == 1 ? s[x,y,1] : z == 2 ? s[x,y,0] : Z : s
+brown = m > 0 ? z == 0 ? s[x,y,0]/2 : z == 1 ? s[x,y,0]/2 : z == 2 ? s[x,y,1] : Z : s
+orange = m > 0 ? z == 0 ? s[x,y,0] : z == 1 ? s[x,y,0]/2 : z == 2 ? s[x,y,1] : Z : s
+!s $dx $dy
+r = red
+r = y >= 1*$dh && y < 2*$dh ? blue[x,y-1*$dh] : r
+r = y >= 2*$dh && y < 3*$dh ? teal[x,y-2*$dh] : r
+r = y >= 3*$dh && y < 4*$dh ? purple[x,y-3*$dh] : r
+r = y >= 4*$dh && y < 5*$dh ? orange[x,y-4*$dh] : r
+r = y >= 5*$dh && y < 6*$dh ? brown[x,y-5*$dh] : r
+r = y >= 6*$dh && y < 5*$dh ? white[x,y-6*$dh] : r
+r = y >= 7*$dh && y < 8*$dh ? yellow[x,y-7*$dh] : r
+!w r $tmp
+EOF
+
+iconv -c r8g8b8 $tmp |\
+	crop -t $Δx $Δy >$fo
+rm $tmp