ref: 49d5b03c43c8eb2f13909c8831705753be1c6233
parent: 2d7f5946613095d37db92f85490a33c5a2eff127
author: qwx <qwx@sciops.net>
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