66 lines
2.5 KiB
Python
66 lines
2.5 KiB
Python
import struct,zlib,re,json,runpy,sys,uuid,os,tempfile
|
|
from pathlib import Path
|
|
ROOT=Path(__file__).resolve().parents[1]
|
|
EVIDENCE=Path(os.environ['CAPITAL_TEST_EVIDENCE'])
|
|
S=json.load(open(os.environ['CAPITAL_TEST_STATE']))
|
|
ART=next(Path(tempfile.gettempdir()).glob('vcc-c-project-*/Builds/'+S['artifact']['artifact_id']+'/build/CAPITAL.bin'))
|
|
mp=ART.with_suffix('.map').read_text()
|
|
addr=int(re.search(r'Symbol: _font5x8 .*?= ([0-9A-Fa-f]+)',mp)[1],16)
|
|
blob=ART.read_bytes();memory={};p=0
|
|
while p<len(blob):
|
|
t=blob[p];n,a=struct.unpack('>HH',blob[p+1:p+5]);p+=5
|
|
if t==255:break
|
|
for i,b in enumerate(blob[p:p+n]):memory[a+i]=b
|
|
p+=n
|
|
font=bytes(memory[addr+i] for i in range(768))
|
|
|
|
def png(path):
|
|
b=Path(path).read_bytes();p=8;dat=b''
|
|
while p<len(b):
|
|
n=int.from_bytes(b[p:p+4],'big');t=b[p+4:p+8];v=b[p+8:p+8+n];p+=n+12
|
|
if t==b'IHDR':w,h,depth,ct,*_=struct.unpack('>IIBBBBB',v)
|
|
if t==b'IDAT':dat+=v
|
|
assert depth==8 and ct in (2,6),(depth,ct)
|
|
channels=3 if ct==2 else 4;stride=w*channels;raw=zlib.decompress(dat);out=[];prior=bytearray(stride);p=0
|
|
for y in range(h):
|
|
f=raw[p];p+=1;row=bytearray(raw[p:p+stride]);p+=stride
|
|
for i in range(stride):
|
|
a=row[i-channels] if i>=channels else 0;b=prior[i];c=prior[i-channels] if i>=channels else 0
|
|
if f==1:pred=a
|
|
elif f==2:pred=b
|
|
elif f==3:pred=(a+b)//2
|
|
elif f==4:
|
|
v=a+b-c;pa=abs(v-a);pb=abs(v-b);pc=abs(v-c);pred=a if pa<=pb and pa<=pc else b if pb<=pc else c
|
|
else:pred=0
|
|
row[i]=(row[i]+pred)&255
|
|
out.append(row);prior=row
|
|
return w,h,channels,out
|
|
class Screen:
|
|
def __init__(self,path):self.w,self.h,self.ch,self.rows=png(path)
|
|
def pixel(self,x,y):return tuple(self.rows[y][x*self.ch:x*self.ch+3])
|
|
def guest(self,x,y):return self.pixel(x*2,50+y*2)
|
|
def text(self,x,y,n,color=None):
|
|
bg=self.guest(x+5,y);out=''
|
|
for j in range(n):
|
|
bits=[]
|
|
for row in range(8):
|
|
for col in range(5):bits.append(self.guest(x+j*6+col,y+row)==color if color else self.guest(x+j*6+col,y+row)!=bg)
|
|
scores=[]
|
|
for c in range(32,127):
|
|
expected=[not(font[(c-32)*8+r]&(128>>co)) for r in range(8) for co in range(5)]
|
|
scores.append((sum(a!=b for a,b in zip(bits,expected)),c))
|
|
d,c=min(scores);out+=chr(c) if d==0 else '?'
|
|
return out.rstrip()
|
|
|
|
def shuffle(seed=2709):
|
|
rng=seed
|
|
def rand(n):
|
|
nonlocal rng
|
|
while True:
|
|
x=rng;x^=x<<7;x&=65535;x^=x>>9;x^=x<<8;x&=65535;rng=x;x-=1
|
|
if x<65535-65535%n:return x%n
|
|
order=list(range(50))
|
|
for i in range(49,0,-1):j=rand(i+1);order[i],order[j]=order[j],order[i]
|
|
return order,rand
|
|
|