Skip to content

Instantly share code, notes, and snippets.

@bbbradsmith
Last active July 18, 2020 06:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bbbradsmith/559057c5fc28443d0c38b0d0c674aa72 to your computer and use it in GitHub Desktop.
Save bbbradsmith/559057c5fc28443d0c38b0d0c674aa72 to your computer and use it in GitHub Desktop.
The Endless Night map dumper
# map dumper for The Endless Night (DOS, 1993, Andy Wood / MythicArts)
# Brad Smith, 2020-07-18
# make a "dump" folder before running this
# Python 3
import math
import PIL.Image
import PIL.ImageDraw
def hexs(data):
s = ""
for b in data:
s += " %02X" % b
if len(s) > 0:
return s[1:]
return s
def read_pal(f):
print("read_pal("+f+")")
b = open(f,"rb").read()
c = bytearray()
for i in range(7,len(b)):
p = b[i]
if ((i-7)%4) == 3:
assert (p == 0) # alpha channel should be 0
continue
assert (p < 64) # out of range?
c.append((p*4) & 0xFF)
return c
def read_tiles(f,pal):
print("read_tiles("+f+")")
b = open(f,"rb").read()
t = []
for i in range(0,len(b)-807,808):
img = PIL.Image.new("P",(20,20),255)
img.putpalette(pal)
for y in range(20):
for x in range(20):
p = b[0xB+i+(y*20)+x]
img.putpixel((x,y),p)
t.append(img)
#print("Tile %02X: %s" % (i//808,hexs(b[i:i+0xB])))
return t
def read_map(f,t,pals,palmap):
print("read_map("+f+")")
b = open(f,"rb").read()
ww,wh = 12,8 # size of world, multiplies to 96
mw,mh = 16,10 # size of each map
tw,th = t[0].size # size of a tile
wr = ww * wh
img = PIL.Image.new("RGB",(tw*mw*ww,th*mh*wh),255)
#img.putpalette(t[0].getpalette())
for m in range(wr):
for y in range(mh):
for x in range(mw):
# 7 byte header + 3D array of [y][x][map]
ix = 7 + 2 * (m + (x * wr) + (y * mw * wr))
p = b[ix]
wx = m % ww
wy = m // ww
rxy = ((wx*mw+x)*tw,(wy*mh+y)*th)
imt = t[p]
tp = palmap[wy][wx]
imt.putpalette(pals[tp])
img.paste(imt,rxy)
return img
def arrange_tiles(t,mw,mh,pal):
img = PIL.Image.new("P",(20*mw,20*mh),255)
img.putpalette(pal)
for ti in range(len(t)):
y = 20 * (ti // mw)
x = 20 * (ti % mw)
img.paste(t[ti],(x,y))
return img
# dunno where the per-screen palette is stored,
# just manually duplicating it here
mappals = [
[0,0,0,1,1,1,1,1,1,1,1,1],
[0,0,0,1,1,1,1,1,1,1,1,1],
[0,0,0,0,0,0,0,0,0,0,0,2],
[0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,2,2,0,0,0,0,0],
[2,0,0,0,2,2,2,2,0,0,0,0],
]
pal = read_pal("NIGHT.PAL")
pic = read_pal("NIGHTICE.PAL")
psa = read_pal("NIGHTSAN.PAL")
spr = read_tiles("NIGHT.SPR",pal)
scr = read_map("NIGHT.SCR",spr,[pal,pic,psa],mappals)
# details to manually correct:
# goat on 0,4
# horse 1,0
# ship 11,2
# cave looks weird? (0-tiles that should be grass) 11,7
# sheep 9,4
# merchant gap 4,4
# merchant gap 5,4
# yeti 7,0
# eldirood 10,0
open("dump\\NIGHT.PAL.pal", "wb").write(pal)
open("dump\\NIGHTICE.PAL.pal","wb").write(pic)
open("dump\\NIGHTSAN.PAL.pal","wb").write(psa)
for i in range(len(spr)):
#spr[i].save("dump\\NIGHT.SPR.%02X.png"%(i))
pass
arrange_tiles(spr,8,4,pal).save("dump\\NIGHT.SPR.png")
arrange_tiles(spr,8,4,pic).save("dump\\NIGHT.SPR.ice.png")
arrange_tiles(spr,8,4,psa).save("dump\\NIGHT.SPR.sand.png")
scr.save("dump\\NIGHT.SCR.png")
print("Done!")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment