Skip to content

Instantly share code, notes, and snippets.

@bbbradsmith
Last active September 20, 2022 07:53
Show Gist options
  • Save bbbradsmith/b21472e912933b08bed6670b2ccbcd88 to your computer and use it in GitHub Desktop.
Save bbbradsmith/b21472e912933b08bed6670b2ccbcd88 to your computer and use it in GitHub Desktop.
Ice Kiss (DOS) graphics extractor
# Extracts sprites from the Korean DOS game Ice Kiss
# First run icekiss_sprite_file_extract.py to create the sprite bin files
# Also, take a screenshot of the gameplay with DOSBox to make a PNG with the correct palette
# Then run this to extract graphics from them
import PIL.Image
screenshot = PIL.Image.open("screenshot.png") # use for palette
def decode_file(filename):
print(filename)
f = open(filename,"rb").read()
count = f[0x20] | (f[0x21]<<8)
print("%2d images" % (count))
offset = 0x22
last_offset = offset
for i in range(count):
w = f[offset+0] | (f[offset+1]<<8)
h = f[offset+2] | (f[offset+3]<<8)
comp = f[offset+4]
size = f[offset+5] | (f[offset+6]<<8)
print("%2d: %3d x %3d (%d) $%04X @ $%08X" % (i,w,h,comp,size,offset))
img = PIL.Image.new("P",(w,h),255)
img.putpalette(screenshot.getpalette())
offset += 0x35
if comp == 0:
# uncompressed, non-planar image
for y in range(h):
for x in range(w):
img.putpixel((x,y),f[offset])
offset += 1
else:
assert (comp == 1)
# each image is split into 4 byteplains (unchained VGA style)
# starting at 0,0 in the image, each packet is 2 bytes:
# byte A = pixels to skip over
# byte B = pixels to copy
# followed by B pixels to copy
# if byte A = FF this is a "newline" command
# after the image height is completed, jump to the next plane of 4
# repeat until the image is full
# (rows can be completed in multiple passes)
end_offset = offset + size
r = 0
x = 0
x_max = 0
x_start = 0
while (offset < end_offset):
skip = f[offset]
if skip == 0xFF: # "newline"
#print("$%08X: %02X" % (offset,skip))
offset += 1
x_max = max(x,x_max)
r += 1
if (r %(h*4)) == 0: # multiple passes: resume where previous pass left off?
x_start = x_max
x = x_start
continue
raw = f[offset+1]
#print("$%08X: %02X + %02X = %d" % (offset,skip,raw,skip+raw))
offset += 2
x += skip
p = (r // h) % 4
dy = r % h
for j in range(raw):
dx = (x*4)+p
assert (dx < w)
img.putpixel((dx,dy),f[offset])
offset += 1
x += 1
fo = "%s.%02d.png" % (filename,i)
print("%-30s ($%4X bytes)" % (fo,offset - last_offset))
img.save(fo)
# advance to next image
end_offset = offset
new_offset = last_offset + size + 0x35
if end_offset != new_offset:
print("Skipped bytes at: %08X - %08X" % (end_offset,new_offset))
offset = new_offset
last_offset = offset
print("done.")
for i in range(0,10):
decode_file("Sprite.%d.bin" % (i))
# Extracts packed graphics files from Korean DOS game Ice Kiss
# (Files are packed within ICEKISS.EXE)
exe = open("ICEKISS.EXE","rb").read()
s = "O2 Object Sprite".encode("ASCII")
fo = []
for i in range(len(exe)):
for j in range(len(s)):
if i+j > len(exe): break
if s[j] != exe[i+j]: break
if j == len(s)-1:
fo.append(i)
print("$%08X" % (i))
print(fo)
print(s)
for i in range(len(fo)):
si = fo[i]
ei = len(exe)
if i+1 < len(fo):
ei = fo[i+1]
f = exe[si:ei]
open("Sprite.%1d.bin" % (i),"wb").write(f)
print("done")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment