Exemplo n.º 1
0
def readData(dlPath):
    fname = dlPath + '/darkland.enm'
    data = map(ord, open(fname).read())
    dataLen = len(data)

    enemyTypes = []
    pos = 0
    for i in xrange(0, 71):
        et = OrderedDict()
        et['image_group'] = sread(data[pos:pos+4]) ; pos += 4
        et['name'] = sread(data[pos:pos+10]) ; pos += 10
        et['num_variants'] = data[pos] ; pos += 1
        et['pal_cnt'] = data[pos] ; pos += 1 # number of palettes in enemypal?
        et['unknown2'] = data[pos] ; pos += 1
        et['pal_start'] = data[pos] ; pos += 1 # palettes starting index in enemypal
        et['unknown4'] = bread(data[pos:pos+2]) ; pos += 2
        attrs = {}
        for attr in ('end','str','agl','per','int','chr','df'):
            attrs[attr] = data[pos] ; pos += 1
        et['attrs'] = attrs
        skills = {}
        for s in ('wEdg','wImp','wFll','wPol','wThr','wBow','wMsl','alch','relg','virt','spkC','spkL','r_w','heal','artf','stlh','strW','ride','wdWs'):
            skills[s] = data[pos] ; pos += 1
        et['skills'] = skills
        et['unknown5'] = data[pos] ; pos += 1
        pos += 1 # const 0
        et['unknown6'] = data[pos] ; pos += 1 # underground related?

        et['unknown7'] = data[pos] ; pos += 1
        et['unknown8'] = data[pos:pos+0x42] ; pos += 0x42
        et['unknown9'] = data[pos:pos+0x1e] ; pos += 0x1e
        et['unknown10'] = data[pos:pos+2] ; pos += 2
        et['vital_arm_type'] = data[pos] ; pos += 1
        et['limb_arm_typetype'] = data[pos] ; pos += 1

        et['armor_q'] = data[pos] ; pos += 1
        et['unknown11'] = data[pos] ; pos += 1
        et['shield_type'] = data[pos] ; pos += 1
        et['shield_q'] = data[pos] ; pos += 1
        et['unknown12'] = data[pos:pos+6] ; pos += 6
        et['unknown13'] = data[pos:pos+6] ; pos += 6
        et['weapon_types'] = data[pos:pos+6] ; pos += 6
        et['weapon_q'] = data[pos] ; pos += 1
        et['unknown14'] = data[pos:pos+11] ; pos += 11
        et['unknown15'] = data[pos:pos+20] ; pos += 20
        enemyTypes.append(et)

    enemies = []
    for i in xrange(0, 82):
        e = OrderedDict()
        e['type'] = bread(data[pos:pos+2]) ; pos += 2
        e['type_str'] = enemyTypes[e['type']]['name']
        e['name'] = sread(data[pos:pos+12]) ; pos += 12
        pos += 8 # all 0
        e['unknown'] = bread(data[pos:pos+2]) ; pos += 2
        e['unknown_bin'] = bin(e['unknown'])
        enemies.append(e)

    return enemyTypes, enemies
Exemplo n.º 2
0
def readData(dlPath):
    fname = dlPath + '/tacanim.db'
    data = map(ord, open(fname).read())
    dataLen = len(data)

    tacanim = {}
    pos = 0
    while pos < dataLen:
        charCode = sread(data[pos:pos + 4])
        pos += 4
        tacanim[charCode] = data[pos:pos + 10]
        pos += 10
        # last four bytes looks like 2 times width, depth for walk & combat??
        # Nope? :( change of last 4 bytes has no effect in battle

    return {'tacanim': tacanim}
Exemplo n.º 3
0
def readData(dlPath):
    fname = dlPath + '/darkland.loc'

    data = map(ord, open(fname).read())
    dataLen = len(data)
    #print fname, dataLen, 'B'
    pos = 0

    cnt = bread(data[pos:pos + 2])
    #print cnt, bread(data[pos:pos+1])
    pos += 2

    locs = []

    for i in xrange(0, cnt):
        c = OrderedDict()

        c['icon'] = bread(data[pos:pos + 2])
        pos += 2  # (enum location_icon)
        #Map image for the location. Note that this basically corresponds to the 'type' of location.
        #print c['icon']
        c['str_loc_type'] = locTypes[
            c['icon']] if c['icon'] < len(locTypes) else str(c['icon'])
        c['unknown1'] = bread(data[pos:pos + 2])
        pos += 2
        #c['unknown1_bin'] = bin(c['unknown1'])
        #0 for cities, other locations range from 0x08-0x0e.
        c['coords'] = (bread(data[pos:pos + 2]), bread(data[pos + 2:pos + 4]))
        pos += 4
        #Map coordinates.
        c['unknown2'] = bread(data[pos:pos + 2])
        pos += 2
        #Ranges from 1-10.
        #Seems to be 4 or 9 for live Raubritters (1 for dead); perhaps it's a strength?
        c['unknown3'] = bread(data[pos:pos + 2])
        pos += 2
        #Most range from 1-5, except pagan altars, which are 0x63 (99).
        c['menu'] = bread(data[pos:pos + 2])
        pos += 2
        #Card displayed on entering the location.
        c['unknown4'] = bread(data[pos:pos + 2])
        pos += 2
        #Always 0x62 except for castles currently occupied by Raubritters (icon=2); those are 0x92.
        c['unknown5'] = data[pos]
        pos += 1
        c['city_size'] = data[pos]
        pos += 1
        #Size of the city.
        #Cities range from 3 (small) to 8 (Koln); non-cities are always 1.
        c['local_rep'] = bread(data[pos:pos + 2])
        pos += 2
        #Local reputation.
        #In this file, this is always zero. The copy of this structure that lives in the saved game files gets non-zero values.
        #Ranges from -150 to 150 (although others claim to have observed numbers outside this range).
        c['unknown6'] = data[pos]
        pos += 1
        #Zero seems to indicate an "active" site.
        #Ruins of a Raubritter castle get 0x04, as do destroyed villages.
        #Some other locations get 0x20 or 0x24.
        c['unknown7_c'] = bread(data[pos:pos + 3])
        pos += 3
        # [constant: { 0x19, 0x19, 0x19 }]
        c['inn_cache_idx'] = bread(data[pos:pos + 2])
        pos += 2
        #In this file, this is always 0xffff (-1).
        #In a saved game file, if the party stores items at an inn (in a city), this value becomes an index into cache_offsets (found in dksaveXX.sav).
        c['unknown8_c'] = bread(data[pos:pos + 2])
        pos += 2
        #[constant: 0x0000]
        c['unknown9'] = bread(data[pos:pos + 2])
        pos += 2
        #All are zero except for Nurnberg, which is 0xc0.
        c['unknown10_c'] = bread(data[pos:pos + 8])
        pos += 8
        # [constant: all 0x00]
        c['name'] = sread(data[pos:pos + 20])
        pos += 20
        locs.append(c)

    return locs
Exemplo n.º 4
0
from utils import bread, sread

# catalog filename
fname = sys.argv[1]
# output dir
ddir = sys.argv[2]

data = map(ord, open(fname).read())
dataLen = len(data)
print fname, dataLen, 'B'
pos = 0

cnt = bread(data[pos:pos + 2])
print cnt
pos += 2

for i in xrange(0, cnt):
    fn = sread(data[pos:pos + 12])
    pos += 12
    # dword TS
    pos += 4
    dataLen = bread(data[pos:pos + 4])
    pos += 4
    dataOffs = bread(data[pos:pos + 4])
    pos += 4
    print fn, dataOffs, dataLen

    fh = open(ddir + '/' + fn, "wb")
    fh.write(bytearray(data[dataOffs:dataOffs + dataLen]))
    fh.close()
Exemplo n.º 5
0
def readData(dlPath):
    fname = dlPath + '/darkland.lst'

    data = map(ord, open(fname).read())
    dataLen = len(data)
    #print fname, dataLen, 'B'
    itemCnt, saintCnt, formCnt = data[0], data[1], data[2]
    pos = 3

    items = []

    for i in xrange(0, itemCnt):
        c = OrderedDict()
        c['name'] = sread(data[pos:pos + 20])
        pos += 20
        c['short_name'] = sread(data[pos:pos + 10])
        pos += 10
        c['type'] = bread(data[pos:pos + 2])
        pos += 2
        flags = (('is_edged', 'is_impact', 'is_polearm', 'is_flail',
                  'is_thrown', 'is_bow', 'is_metal_armor', 'is_shield'),
                 ('is_unknown1', 'is_unknown2', 'is_component', 'is_potion',
                  'is_relic', 'is_horse', 'is_quest_1', 'is_const0_1'),
                 ('is_lockpicks', 'is_light', 'is_arrow', 'is_const0_2',
                  'is_quarrel', 'is_ball', 'is_const0_3', 'is_quest_2'),
                 ('is_throw_potion', 'is_const0_4', 'is_nonmetal_armor',
                  'is_missile_weapon', 'is_unknown3', 'is_music',
                  'is_const0_6', 'is_const0_7'),
                 ('is_unknown4', 'is_unknown5', 'is_const0_8', 'is_const0_9',
                  'is_const0_10', 'is_const0_11', 'is_const0_12',
                  'is_unknown6'))
        for f in flags:
            bits = data[pos]
            pos += 1
            for b, n in enumerate(f):
                c[n] = True if bits & (1 << b) else False
        c['weight'] = data[pos]
        pos += 1
        c['quality'] = data[pos]
        pos += 1
        c['rarity'] = data[pos]
        pos += 1  # missing in Merle's doc!
        c['unknown1'] = bread(data[pos:pos + 2])
        pos += 2
        #Non-zero only for relics.
        #Ranges from 0x06 (St. Edward's Ring) to 0x50 (St. Gabriel's Horn).
        c['unknown2'] = bread(data[pos:pos + 2])
        pos += 2
        #Non-zero only for relics, and for the "residency permit" (which is unused by the game).
        #Ranges from 0x05 to 0x27 (residency permit).
        c['value'] = bread(data[pos:pos + 2])
        pos += 2
        items.append(c)

    saints = []
    for i in xrange(0, saintCnt):
        s = ''
        while data[pos]:
            s += chr(data[pos])
            pos += 1
        pos += 1
        saints.append({'name': s})

    for i in xrange(0, saintCnt):
        s = ''
        while data[pos]:
            s += chr(data[pos])
            pos += 1
        pos += 1
        saints[i]['short_name'] = s

    formulae = []
    for i in xrange(0, formCnt):
        s = ''
        while data[pos]:
            s += chr(data[pos])
            pos += 1
        pos += 1
        formulae.append({'name': s})

    for i in xrange(0, formCnt):
        s = ''
        while data[pos]:
            s += chr(data[pos])
            pos += 1
        pos += 1
        formulae[i]['short_name'] = s

    # read saints descriptions
    fname = dlPath + '/darkland.snt'
    data = map(ord, open(fname).read())
    pos = 1
    for i in xrange(0, len(saints)):
        saints[i]['description'] = sread(data[pos:pos + 0x168])
        pos += 0x168

    return items, saints, formulae
Exemplo n.º 6
0
def readData(dlPath):
    fname = dlPath + '/darkland.cty'

    data = map(ord, open(fname).read())
    dataLen = len(data)
    #print fname, dataLen, 'B'
    pos = 0

    cnt = data[pos]
    #print cnt, bread(data[pos:pos+1])
    pos += 1

    cities = []

    for i in xrange(0, cnt):
        c = OrderedDict()

        c['short_name'] = sread(data[pos:pos + 32])
        pos += 32
        c['name'] = sread(data[pos:pos + 32])
        pos += 32
        #city_data = (size 0x2e)
        dataPos = pos

        c['city_size'] = bread(data[pos:pos + 2])
        pos += 2
        #Size of the city. Ranges from 3 (small) to 8 (Koln).

        c['entry_coords'] = (bread(data[pos:pos + 2]),
                             bread(data[pos + 2:pos + 4]))
        pos += 4
        # City location on the map.
        c['exit_coords'] = (bread(data[pos:pos + 2]),
                            bread(data[pos + 2:pos + 4]))
        pos += 4
        # Party coordinates when leaving a city.
        # When you leave a city, you don't exit at the same point as you entered. The exit coordinates were (usually) selected so as not to place you in an untenable position (the ocean, trapped by a river loop, etc).

        dests = []
        for i in xrange(0, 4):
            tgt = bread(data[pos:pos + 2])
            pos += 2
            if tgt != 0xffff:
                dests.append(tgt)
        c['dock_destinations'] = dests
        # Dock destination cities.
        # This contains the indices (in the cities array) of the destinations available via the city docks the docks.
        # 0xffff is used for "no destination". Inland cities have all 0xffffs.

        c['coast'] = bread(data[pos:pos + 2])
        pos += 2
        #if coastal, side of the river ???[Hamburg] TODO.
        #    Values are: 0xffff (inland), 0 (north of the river), 1 (south of the river)
        #    0 and 1 cities are on or near tidal zones (swamps), and may be subject to flooding.
        c['unknown_cd_1'] = bread(data[pos:pos + 2])
        pos += 2
        # [constant: 4]

        c['pseudo_ordinal'] = bread(data[pos:pos + 2])
        pos += 2
        # At first glance, this looks like an ordinal offset running from 0 to 0x5b, but 0x18 is missing, and 0x3c repeats.
        # This value is probably not used.

        c['city_type'] = bread(data[pos:pos + 2])
        pos += 2
        # Type of city
        c['unknown_cd_2'] = bread(data[pos:pos + 2])
        pos += 2
        #    0, 1, 2, or 3.
        c['unknown_cd_3'] = bread(data[pos:pos + 2])
        pos += 2
        # [constant: 0]

        #city_contents = bread(data[pos:pos+2])# bitmask[16 bits]
        city_contents = (data[pos] << 8) | data[pos + 1]  # bitmask[16 bits]
        pos += 2
        #Buildings and locations in the city.
        #    Bits are on iff there is one of that type of building.
        opts = ('has_kloster', 'has_slums', 'has_unknown1', 'has_cathedral',
                'has_unknown2', 'has_no_fortress', 'has_town_hall',
                'has_polit', 'has_constant1', 'has_constant2', 'has_constant3',
                'has_constant4', 'has_docks', 'has_unknown3', 'has_pawnshop',
                'has_university')
        for i, o in enumerate(opts):
            c[o] = 1 if city_contents & (1 << (15 - i)) else 0
        c['bin_city_contents'] = bin(city_contents)
        c['unknown_cd_4'] = bread(data[pos:pos + 2])
        pos += 2
        # [constant: 0]

        c['qual_black'] = data[pos]
        pos += 1
        #Quality of the blacksmith.
        #    This, and the other nine qualities, all seem to work in the same way.
        #    A zero value indicates that the city does not have that particular shop.
        #    Non-zero values do not exactly equal the quality of the items available, but merely indicate relative qualities! For example, Nurnberg has a 0x31 (49) listed for the armory, but offers q37 (0x25) armor. However, if one city has a higher value than another, then that city's items will be of equal or greater quality.
        #    The quality of the healer is not stored here, but is apparently random. (TODO: verify?)
        #    TODO: comments about Quality of the alchemist, university, pharmacist being the seed thing.
        c['qual_merch'] = data[pos]
        pos += 1
        #Quality of the merchant.
        c['qual_sword'] = data[pos]
        pos += 1
        #Quality of the swordsmith.
        c['qual_armor'] = data[pos]
        pos += 1
        #Quality of the armorer.
        c['qual_unk1'] = data[pos]
        pos += 1
        c['qual_bow'] = data[pos]
        pos += 1
        #Quality of the bowyer.
        c['qual_tink'] = data[pos]
        pos += 1
        #Quality of the tinker.
        c['qual_unk2'] = data[pos]
        pos += 1
        c['qual_cloth'] = data[pos]
        pos += 1
        # Quality of the clothing merchant.
        c['qual_unk3'] = data[pos]
        pos += 1
        # [constant: 0]
        c['unknown_cd_5'] = data[pos]
        pos += 1
        # unknown byte
        # Since the following byte is 0 or 1, this and that might actually be a single word value.
        c['unknown_cd_6'] = data[pos]
        pos += 1
        # unknown byte
        # Either zero or one (only a couple of ones).
        c['unknown_cd_5-6'] = bread(data[pos - 2:pos])  # word

        c['leader_name'] = sread(data[pos:pos + 32])
        pos += 32
        c['ruler_name'] = sread(data[pos:pos + 32])
        pos += 32
        c['unknown'] = sread(data[pos:pos + 32])
        pos += 32
        #TODO: is this non-empty ever? (ditto for other two unknowns)
        c['polit_name'] = sread(data[pos:pos + 32])
        pos += 32
        #Name of the political center or town square.
        #TODO: describe what empty values look like
        c['town_hall_name'] = sread(data[pos:pos + 32])
        pos += 32
        c['fortress_name'] = sread(data[pos:pos + 32])
        pos += 32
        #Name of the city fortress or castle.
        c['cathedral_name'] = sread(data[pos:pos + 32])
        pos += 32
        c['church_name'] = sread(data[pos:pos + 32])
        pos += 32
        c['market_name'] = sread(data[pos:pos + 32])
        pos += 32
        #Name of the marketplace.
        c['unknown2'] = sread(data[pos:pos + 32])
        pos += 32
        #Often contains "Munzenplatz". Possibly this is "central square name".
        c['slum_name'] = sread(data[pos:pos + 32])
        pos += 32
        c['unknown3'] = sread(data[pos:pos + 32])
        pos += 32
        #Many places have "Zeughaus", which translates to "armoury"; others end in "-turm" (tower?) or "-tor" (gate?). Quite possible this is for one of the unused "rebellion" codepath.
        c['pawnshop_name'] = sread(data[pos:pos + 32])
        pos += 32
        #Name of the pawnshop.
        #All pawnshops are named the same; this is either 'Leifhaus' or is empty.
        c['kloster_name'] = sread(data[pos:pos + 32])
        pos += 32
        #Name of the kloster (church law and administration building).
        c['inn_name'] = sread(data[pos:pos + 32])
        pos += 32
        c['university_name'] = sread(data[pos:pos + 32])
        pos += 32
        cities.append(c)

    # read descriptions + generate some attrs
    fname = dlPath + '/darkland.dsc'
    data = map(ord, open(fname).read())
    pos = 1
    for c in cities:
        c['description'] = sread(data[pos:pos + 80])
        pos += 80

        c['str_dock_destinations'] = ', '.join(
            [cities[d]['short_name'] for d in c['dock_destinations']])
        c['str_city_type'] = cityTypes[c['city_type']]

    return cities