uncompress=->bytes,verbose=false{
#p bytes
rbytes=[]
i=j=0
getb=->{
b=bytes[i] or raise "#{i},#{j}"
i+=1
b
}
setb=->b{
rbytes[j]=b
j+=1
}
copy=->a,off{
(a+1).times{
rbytes[j]=rbytes[j-off]
j+=1
}
}
buf=0
sbits=0
fill=->{
ibak=i
bl=getb[]
bh=getb[]
w=(bh<<8)|bl
buf|=w<<(16-sbits)
sbits+=16
warn "fill @#{ibak}" if verbose
}
getbw=->{
buf>>16
}
discard=->d{
return if d==0
buf=(buf<<d)&0xffffffff
sbits-=d
if sbits<16
fill[]
end
}
judge1=->{
w=getbw[]
#p "j1: %04x" % w
case w
when 0...0x200
[(w>>2)|0x80, 13]
when 0x200...0x400
[w>>3, 12]
when 0x400...0x800
[w>>5, 10]
when 0x800...0x1000
[w>>7, 8]
when 0x1000...0x2000
[w>>9, 6]
when 0x2000...0x4000
[w>>11, 4]
when 0x4000...0x8000
[w>>13, 2]
else
[1, 0]
end
}
judge2=->{
w=getbw[] & 0x7fff
#p "j2: %04x" % w
w &= 0x7fff
case w
when 0...0x800
[w>>9, 7]
when 0x800...0xc00
[(w>>8)-4, 8]
when 0xc00...0x1800
[(w>>7)-0x10, 9]
when 0x1800...0x3000
[(w>>6)-0x40, 10]
else
sw=8-(w>>12)
[(w&0xfff|0x1000)>>sw, 16-sw]
end
}
fill[]
begin
loop{
warn "getf @#{i}" if verbose
cb=getb[]
warn "flag byte: #{'%08b'%cb}" if verbose
7.downto(0){|k|
if cb[k]>0
warn "copyraw @#{i} -> @#{j}" if verbose
setb[getb[]]
else
p1,d1=judge1[]
if p1==0xff
warn "detect end mark (p1=0xff)"
break
end
discard[d1]
p2,d2=judge2[]
discard[d2]
if verbose
warn "repeat @#{j} from -#{p2} by #{p1+1}, consume #{d1+d2}"
bufs=("%032b"%buf)[0...sbits]
warn "pooled #{bufs} ( #{sbits} bits )"
end
copy[p1,p2+1]
end
} or break
}
rescue => e
warn " * error #{e} in uncompression *"
end
rbytes
}
cbytes = $<.flat_map{|line| line.scan(/\w\w/).map{|t| t.to_i(16) } }
rbytes=uncompress[cbytes,true]
0.step{|off|
bytes=[]
dobreak=false
16.times{|i|
b=rbytes[off*16+i] or break
bytes[i]=b
} or dobreak=true
break if bytes.size==0
bstrs=[" "]*16
bytes.each_with_index{|b,i| bstrs[i]="%02x" % b}
puts (" %02x0: %s" % [off, bstrs.each_slice(2).map{|(s1,s2)| s1+s2 }*" "])
break if dobreak
}