|
Post by shinali on May 1, 2014 2:33:23 GMT -5
At the moment, I'm mostly concerned with learning how to unpack the res files. They seem to be a straight up concatenation of all sorts of files used by the game, and it seems to me that the way to unpack it would be to go by file headers (RIFF for WAVs. TRPS for sprites(?), etc), though they would have no name associated with them. Would the game be referencing hardcoded file offsets when they need to get a particular resource?
I know there is an existing unpacker called resedit or something (which all the links for are broken it seems), but is there more to the res format than I realize? Is there an actual map that correlate names to the assets?
Finding info on memory structures doesn't seem too bad, though I'm not too worried about it at the moment as I'm not at that stage yet.
|
|
|
Post by Pilot on May 1, 2014 18:06:07 GMT -5
|
|
|
Post by shinali on May 1, 2014 19:47:09 GMT -5
My DNS seems to think the URL doesn't exist. I've found it anyway through Wayback Machine.
I guess I was right when the file references were hard coded into the game. Are there any docs on the Hardwar specific file types (SPRT, WLD, SHP, etc) or do I have to figure those out as well?
|
|
|
Post by Pilot on May 2, 2014 11:07:42 GMT -5
My DNS seems to think the URL doesn't exist. I've found it anyway through Wayback Machine. I guess I was right when the file references were hard coded into the game. Are there any docs on the Hardwar specific file types (SPRT, WLD, SHP, etc) or do I have to figure those out as well? Sorry about that, link is now fixed. I do not know the answer to your question. I assume you can find a few answers here.
|
|
|
Post by ouch on May 3, 2014 2:19:06 GMT -5
|
|
|
Post by shinali on May 4, 2014 0:59:07 GMT -5
I've figured out the res container format from reversing the game and it turns out all the relevant info of files were at the end, with file names XOR encoded with the string SOFTWAREREFINERY. Weird to have this level of protection but whatever.
Thanks much for the links! I have a much better time with actual info than staring at a mess of assembly, stack and registers.
|
|
|
Post by Denacity on May 4, 2014 13:29:08 GMT -5
what are you plan on doing with the information?
|
|
|
Post by shinali on May 6, 2014 12:50:39 GMT -5
I want to start an open source project that clones Hardwar, so I'm looking into how much information is available and how easily I can reverse the game. I'm looking at the container and data formats so I can try to get something to look at relatively quickly.
I didn't want to mention it as I'm sure you guys went through your fair share of failed projects, and I really don't want to sound like I'm promising anything.
EDIT: also seems like Duncan done a lot of the work on file formats with his python scripts, which is awesome. I think I still have to reverse the SRGB format that Ian Martin added, but I found the procedure for it already.
|
|
|
Post by Denacity on May 6, 2014 19:56:23 GMT -5
yeah, there were a lot of projects that had good promise, then the devs just hit a brick wall and stopped, most notably, that was the fate of HardWater.
Best of luck to ya though.
|
|
|
Post by duncan on May 8, 2014 1:49:47 GMT -5
Hi, sorry for spotting this late, but it appears you are very proficient at this.
I will try help with whatever I know if needed - although most I did is already some time ago, so it will be digging in memory lane. Also I find myselve being more timestrapped these days.
I mainly focussed on replicating the game world models in a usable format so would not need to create my own when developing a faithfull hardwar clone. But I lack the skills and the time to gain them to bring my dreams to the next stage and code a real game. Also never set on a language to use.
Success
|
|
|
Post by shinali on May 9, 2014 22:31:38 GMT -5
Sorry for the late reply, had to play nurse for my lady friend.
I've had a little trouble with the spr2bmp with SOFTNEW.SPR and tried to reconfirm with the game, but it seems correct for textures used in the game. Maybe logos are decoded differently, since they're mostly used with DirectDraw? I'm a lot better at making games than reversing them.
Languages don't matter so much but I'm set on C++ since it's going to be an open source project. I'm hoping to setup a basic structure with OGRE and Artemis relatively soon.
|
|
|
Post by duncan on May 10, 2014 7:48:29 GMT -5
softnew.spr should convert, at least I found a correct softnew.bmp on my drive. Maybe the spr2bmp you used was an early version. A version that generates 24bit bmp is needed to work with Blender. That is you need spr2bmp24.py
#spr2bmp24.py
#Python 3.2 (r32:88452, Feb 20 2011, 10:19:59)
#Python script to convert hardwars SPR to BMP #Duncan June2011 #adapted for use in res2blend
#It seems blender needs 24 bits bmp
#make 24 bits #24 bits without alpha gives 8 bits (1 byte) per color channel #needs rowpadding #no alpha in spr, perhaps one transparent color
#known limitations # - only one palette file used atm # - transparancy not set # - images turned upsidedown, affects texture mapping
from hwpaths import *
import math import array from struct import pack,unpack
import hwpal from hwpal import *
import hwres from hwres import resdata
def allspr(): print('converting spr2bmp, this may take several seconds') for i in range(len(resdata)): if resdata[i][1] == 'SPR': convertspr(resdata[i][0],resdata[i][2],resdata[i][3]) def convertspr(fname,offset,fsize): #load spr file print(fname,offset,fsize)
f = open(respath,'rb') dump = f.seek(offset,0)
fheader = array.array('L') fheader.fromfile(f,12) fpixelarray = array.array('B') dump = f.seek(offset+fheader[8],0) fpixelarray.fromfile(f,fheader[1]*fheader[2]) f.close()
# row padding, each row needs to be multiple of 4 bmprowpadding = 4-(fheader[1]*3-int(fheader[1]*3/4)*4) if bmprowpadding == 4: bmprowpadding = 0
# compose bmp pixel array bmppixelarray = array.array('B')
for i in range(fheader[2]): #native hardwar pixelarray order in spr gives 'upside down' bmp #for ii in range(fheader[1]): # colorindex = fpixelarray[i*fheader[1]+ii]
#horizontal mirroring - creates 'correct' logo.bmp, but affects ingame texturing #...unless whpconvert takes this into account in uv mapping for ii in range(fheader[1]):
colorindex = fpixelarray[(fheader[2]-1-i)*fheader[1]+ii]
#some pictures require another palette, color index may go out of range, quickfix if colorindex >= palnumcolors[1]: colorindex = 0
#multiply by 4 to go from SPR 6 bit per color channel to BMP 8 bit per channel bmppixelarray.append(palred[colorindex] *4) bmppixelarray.append(palgreen[colorindex]*4) bmppixelarray.append(palblue[colorindex] *4)
#alpha channel - still need to check for transparancy in hardwar pal #bmppixelarray.append(0)
for ii in range(bmprowpadding): bmppixelarray.append(0x11)
# compose bmp file- (14 bytes) and dip- (40 bytes) header
#header structure as reported in wikipedia #bmp file header (14 bytes) # B 'B' # B 'M' # L filesize # H 0 # H 0 # L 54 (offset to pixel array)(14+40)
#bmp dip header (40 bytes) # L 40 (number of byte in dib header) # L width in pixels # L height in pixels # H 1 (number of color planes used) # H bits per pixel # L 0 (=BI_RGB)(compression/bitmask flag) # L size of pixel array # L horizontal resolution in pixel per meter # L vertical resolution in pixel per meter # L number of colors in palette (required for <=8 bit bmps) # L number of important colors (0 = all)
#bmp dipheader optinally continued w/ bitmask data (32 bit example) # L red channel bitmask (0x00FF0000) # L green channel bitmask (0x0000FF00) # L blue channel bitmask (0x000000FF) # L alpha channel bitmask (0xFF000000) # (... something on color space, hopefully not needed)
bitsperpixel = 24 bmpsize = 14+40+len(bmppixelarray) bmppixeloffset = 14+40 bmpfileheader = pack('LHHL',bmpsize,0,0,bmppixeloffset) bmpdipheader = pack('LLLHHLLLLLL',40,fheader[1],fheader[2],1,bitsperpixel,0,len(bmppixelarray),0,0,0,0)
s = '' for i in range(len(bmpfileheader)): s+='B' bmpfileheaderbytes = unpack(s,bmpfileheader) s = '' for i in range(len(bmpdipheader)): s+='B' bmpdipheaderbytes = unpack(s,bmpdipheader) # compose bmp data in single byte array bmpbytes = array.array('B') bmpbytes.append(66) bmpbytes.append(77)
for i in range(len(bmpfileheaderbytes)): bmpbytes.append(bmpfileheaderbytes[i])
for i in range(len(bmpdipheaderbytes)): bmpbytes.append(bmpdipheaderbytes[i])
# write bmp data
bmp = open(bmppath+fname[:-4]+'.bmp','wb') bmpbytes.tofile(bmp) bmppixelarray.tofile(bmp) bmp.close()
|
|