HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

SFmpq ruby interface

04-15-2007, 10:05 PM#1
PipeDream
Ruby/DL2 links a handful of functions from sfmpq.dll. I'm using ruby 1.8.5. See the examples at the bottom.

Code:
require 'dl/import'
require 'dl/struct'
require 'dl/types'

module SFmpqapi
	extend DL::Importable
	LongArg = struct [ "long val" ]
	StrArg = struct [ "char str[1000000]" ]
	dlload 'sfmpq.dll'
	extern 'BOOL SFileOpenArchive(char *,int,int,void *)'
	extern 'BOOL SFileCloseArchive(int)'
	extern 'BOOL SFileOpenFileEx(int,char*,int,int*)'
	extern 'int SFileGetFileSize(int,int)' #really int,int*
	extern 'BOOL SFileCloseFile(int)'
	extern 'int MpqOpenArchiveForUpdate(char*,int,int)'
	extern 'int MpqCloseUpdatedArchive(int,int)'
	extern 'BOOL MpqAddFileFromBuffer(int,char*,int,char*,int)'
	extern 'BOOL MpqCompactArchive(int)'
	extern 'BOOL MpqDeleteFile(int,char*)'
end

MOAU_OPEN_EXISTING = 4

def createstr(len)
	s = ""
	len.times { s = s + "0" }
	s
end
sfmpq = ::DL::dlopen("sfmpq.dll")
SFileReadFile = sfmpq['SFileReadFile','IIsIiI']

class SFReadMPQFile
	attr_reader :mpq,:name,:handle
	def initialize(mpq,filename)
		@mpq = mpq
		@name = filename
		phandle = SFmpqapi::LongArg.malloc
		ok = SFmpqapi::sFileOpenFileEx(mpq.handle,@name,0,phandle)
		raise "Could not open file #{@name} in #{@mpq.name}" unless ok
		@handle = phandle.val
	end
	def close()
		ok = SFmpqapi::sFileCloseFile(@handle)
		raise "Could not close file #{@name} in #{@mpq.name}" unless ok
	end
	def size()
		SFmpqapi::sFileGetFileSize(@handle,0)
	end
	def read()
		len = self.size()
		s = createstr(len)
		x = SFileReadFile.call(@handle,s,len,0,0)
		ok = x[0]==1
		nread = x[1][3]
		ok = ok and nread==len
		raise "Could not read file #{@name} in #{@mpq.name}" unless ok
		filedata = x[1][1].each_line {|l| l.gsub!(/\r/,'')}	#chop pesky line enders
		#filedata = x[1][1]
	end
	def to_s()
		"file: #{@mpq.name}/#{@name} handle: #{@handle}"
	end
end

class SFReadMPQ
	attr_reader :name,:handle
	def initialize(mpqname)
		@name = mpqname
		phandle = SFmpqapi::LongArg.malloc
		ok = SFmpqapi::sFileOpenArchive(mpqname,15,0,phandle)
		raise "Could not open archive #{@name}" unless ok
		@handle = phandle.val
	end
	def close()
		SFmpqapi::sFileCloseArchive(@handle)
	end
	def open(filename)
		SFReadMPQFile.new(self,filename)
	end
end

class SFWriteMPQ
	attr_reader :name,:handle
	def initialize(mpqname)
		@name = mpqname
		phandle = SFmpqapi::LongArg.malloc
		@handle = SFmpqapi::mpqOpenArchiveForUpdate(mpqname,MOAU_OPEN_EXISTING,0)
		raise "Could not open archive #{@name}" unless @handle != 0
	end
	def close()
		ok = SFmpqapi::mpqCloseUpdatedArchive(@handle,0)
		raise "Could not close archive #{@name}" unless ok
	end
	def delete(filename)
		ok = SFmpqapi::mpqDeleteFile(@handle,filename)
		raise "Could not delete file #{filename} in #{@name}" unless ok
	end
	def addfile(filename,buf)
		ok = SFmpqapi::mpqAddFileFromBuffer(@handle,buf,buf.size,filename,1)
		raise "Could not add file #{filename} to #{@name}" unless ok
	end
	def compact()
		ok = SFmpqapi::mpqCompactArchive(@handle)
		raise "Could not compact archive #{@name}" unless ok
	end
end

def testread()
	mpq = SFReadMPQ.new("heap.w3x")
	foo = mpq.open("foo.j")
	print "#{foo.size}\n"
	print "#{foo.read}\n"
	#print "#{foo}\n"
	foo.close
	mpq.close
end
def testwrite()
	mpq = SFWriteMPQ.new("heap.w3x")
	mpq.addfile("foo.j","bar")
#	mpq.delete("(attributes)")
	mpq.compact
	mpq.close
end
#testwrite()
#testread()
04-16-2007, 05:08 PM#2
PitzerMike
Aahh, Ruby *runs away*

Will you use it for anything particular?
04-16-2007, 10:45 PM#3
PipeDream
Nope, just saw this:
Quote:
Originally Posted by Korolen
I was planning on using a high-level language like Ruby, but that will be hard to extend to use a MPQ tool like SFMpq.