Files
Client/rylCoder_16.02.2008_src/CRylCoder.vb
LGram16 dd97ddec92 Restructure repository to include all source folders
Move git root from Client/ to src/ to track all source code:
- Client: Game client source (moved to Client/Client/)
- Server: Game server source
- GameTools: Development tools
- CryptoSource: Encryption utilities
- database: Database scripts
- Script: Game scripts
- rylCoder_16.02.2008_src: Legacy coder tools
- GMFont, Game: Additional resources

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 20:17:20 +09:00

2159 lines
98 KiB
VB.net
Raw Permalink Blame History

'################################################
'## ##
'## RYL mcf & gsf file editor ##
'## ##
'## (C) 2006 & 2007 AlphA ##
'## ##
'## This source is for private development. ##
'## You can have this source only with the ##
'## owners permission. ##
'## ##
'################################################
Imports System.Reflection
Imports System.Diagnostics
Public Class CMcfCoder
#Region "Data"
Friend Shared xorKey() As Byte = {&HAC, &H29, &H55, &H42}
#End Region
Public Enum Col
EFirstCol = 0
ESecondCol = 1
EThirdCol = 2
EForthCol = 3
End Enum
Public Shared Function DeCryptByte(ByVal num As Byte, Optional ByVal column As Col = Col.EFirstCol) As Byte
Return (num Xor xorKey(column))
End Function
Public Shared Function EnCryptByte(ByVal num As Byte, Optional ByVal column As Col = Col.EFirstCol) As Byte
Return (num Xor xorKey(column))
End Function
Public Shared Function DeCryptArea(ByRef data As Byte(), Optional ByVal startCol As Col = Col.EFirstCol) As Byte()
Dim out(data.Length - 1) As Byte
Dim pos As Integer = startCol
Dim i As Long = 0
For Each b As Byte In data
out(i) = DeCryptByte(b, pos)
pos += 1
i += 1
If pos > 3 Then pos = 0
Next
Return out
End Function
Public Shared Function EnCryptArea(ByRef data As Byte(), Optional ByVal startCol As Col = Col.EFirstCol) As Byte()
Dim out(data.Length - 1) As Byte
Dim pos As Integer = startCol
Dim i As Long = 0
For Each b As Byte In data
out(i) = EnCryptByte(b, pos)
pos += 1
i += 1
If pos > 3 Then pos = 0
Next
Return out
End Function
Private Shared Function printCol(ByVal column As Col) As Integer
Select Case column
Case Col.EFirstCol : Return 0
Case Col.ESecondCol : Return 1
Case Col.EThirdCol : Return 2
Case Col.EForthCol : Return 3
End Select
End Function
Public Shared Function getCol(ByVal index As Long) As Col
Return ModulusFromDivination(index, 4)
End Function
Public Shared Function ModulusFromDivination(ByVal nr1 As Long, ByVal nr2 As Long) As Integer
Dim div As Double = nr1 / nr2
Dim rDiv As Long = Math.Floor(div)
If div = rDiv Then
Return 0
Else
'Dim fp As Long = Convert.ToInt64(div.ToString.Split(New Char() {".", ","})(0), 10)
Return nr1 - (nr2 * rDiv)
End If
End Function
Public Shared Function position(ByRef data As Byte(), ByRef searchFor As Byte(), Optional ByVal startFrom As Long = 0, Optional ByVal numberOfMaxresults As Integer = 0, Optional ByVal Length As Long = 0) As Long()
Dim poses As Long() = {}
For index As Long = startFrom To IIf(Length > 0, startFrom + Length, data.Length - 1)
If data.Length - index >= searchFor.Length Then
Dim arr As Byte() = {}
For i As Integer = 0 To searchFor.Length - 1
ReDim Preserve arr(i)
arr(i) = data(index + i)
Next
If compareArr(arr, searchFor) Then
ReDim Preserve poses(UBound(poses) + 1)
poses(UBound(poses)) = index
If poses.Length = numberOfMaxresults Then Exit For
End If
Else
Exit For
End If
Next
Return poses
End Function
Private Shared Function compareArr(ByRef d1 As Byte(), ByRef d2 As Byte()) As Boolean
For i As Integer = 0 To d1.Length - 1
If UBound(d2) < i OrElse d1(i) <> d2(i) Then Return False
Next
Return True
End Function
Public Shared Function SpliceArr(ByRef data As Byte(), ByVal startPos As Long, ByVal endPos As Long) As Byte()
If data Is Nothing Then Return New Byte() {}
If endPos - startPos <= 0 OrElse startPos >= data.Length OrElse endPos >= data.Length Then Return New Byte() {}
Dim out(endPos - startPos) As Byte
Dim i As Long = 0
For index As Long = startPos To endPos
out(i) = data(index)
i += 1
Next
Return out
End Function
Public Shared Function SpliceArrByLen(ByRef data As Byte(), ByVal startPos As Long, ByVal length As Long) As Byte()
Return SpliceArr(data, startPos, startPos + length - 1)
End Function
End Class
Public Class CGsfCoder
Public Shared gsfName As String() = {"ItemScript", "MonsterProtoType", "Chemical", "Script1", "SkillScript", "SpecialCompensation", "MineralVein"}
Public Enum gsfType
EItemScript = 0
EMonsterProtoType = 1
EChemical = 2
EScript1 = 3
ESkillScript = 4
ESpecialCompensation = 5
EMineralVein = 6
End Enum
Public Structure GsfFile
Dim picture As Byte()
Dim gsfData As Byte()
Dim type As gsfType
Dim version As Integer
End Structure
Public Enum DataType
ENull = 0
EBool = 1
EInteger = 2
EFloat = 3
EString = 4
End Enum
Public Structure SParamElem
Dim value As Object
Dim type As DataType
'Dim opDataLen As Integer
End Structure
Public Structure STableLine
Dim params As SParamElem()
End Structure
#Region "Data"
Friend Shared typeCodes As Integer() = {17073, 60006, 41094, 17073, 50407, 84703, 214233}
Friend Shared xorDat As String() = { _
"A3 49 DC EA 09 B7 01 A4 A1 11 11 8E 80 35 5B DD 38 D5 4E 36 0C A2 BB 05 36 57 2E 98 BE 88 3C 28 43 63 A0 E9 E1 6D 51 CB", _
"4D 62 84 43 89 C7 89 83 65 29 53 95 7C C0 A1 0C DB D7 04 D8 6A D1 73 1D 21 67 86 8D A4 A0 34 BD 31 20 61 0E E9 63 B4 C0", _
"A3 49 DC EA 09 B7 01 A4 A1 11 11 8E 80 35 5B DD 38 D5 4E 36 0C A2 BB 05 36 57 2E 98 BE 88 3C 28 43 63 A0 E9 E1 6D 51 CB", _
"34 B5 B2 3D 7D 43 8C C0 21 25 CD B6 53 76 CE 5D D4 87 CA 84 81 CB 5E 04 BA 69 3E 65 DE 21 8A 63 62 71 90 87 0A 52 28 44", _
"34 B5 B2 3D 7D 43 8C C0 21 25 CD B6 53 76 CE 5D D4 87 CA 84 81 CB 5E 04 BA 69 3E 65 DE 21 8A 63 62 71 90 87 0A 52 28 44", _
"A3 49 DC EA 09 B7 01 A4 A1 11 11 8E 80 35 5B DD 38 D5 4E 36 0C A2 BB 05 36 57 2E 98 BE 88 3C 28 43 63 A0 E9 E1 6D 51 CB", _
"4D 62 84 43 89 C7 89 83 65 29 53 95 7C C0 A1 0C DB D7 04 D8 6A D1 73 1D 21 67 86 8D A4 A0 34 BD 31 20 61 0E E9 63 B4 C0 " _
}
Private Const saveBuffer As Long = 10 * 1024 * 1024
#End Region
#Region "Dll-Imports"
Private Declare Function __lzo_init3 Lib "memoryZ.dll" () As Integer
Private Declare Function lzo_version_string Lib "memoryZ.dll" () As String
Private Declare Function lzo_version_date Lib "memoryZ.dll" () As String
Private Declare Function lzo1x_1_compress Lib "memoryZ.dll" (ByVal src As Byte(), ByVal src_len As Integer, ByVal dst As Byte(), ByRef dst_len As Integer, ByVal wrkmem As Byte()) As Integer
Private Declare Function lzo1x_decompress Lib "memoryZ.dll" (ByVal src As Byte(), ByVal src_len As Integer, ByVal dst As Byte(), ByRef dst_len As Integer, ByVal wrkmem As Byte()) As Integer
#End Region
Private Structure testIdLine
Dim id As Integer
Dim line As String
End Structure
Private Shared Function lineForId(ByVal coll As ArrayList, ByVal id As Integer) As String
For Each l As testIdLine In coll
If l.id = id Then
Return l.line
End If
Next
Return ""
End Function
Public Shared Function Struct2text(ByRef table As STableLine(), ByVal type As gsfType, Optional ByVal version As Integer = 0) As String()
Dim struct As SGsfDataStructure = getStructureInfo(type)
Dim lines(table.Length + 8) As String
Dim lcnt As Integer = 9
lines(0) = "///////////////////////////////////////////////////////"
lines(1) = "//"
lines(2) = "// " & [Enum].GetName(GetType(gsfType), type).Substring(1) & IIf(version > 0, " ver. " & version, "")
lines(3) = "//"
lines(4) = "// Created by rylCoder " & Application.ProductVersion.Substring(0, Application.ProductVersion.Length - 2) & " <20> 2006 & 2007 AlphA"
lines(5) = "//"
lines(6) = "///////////////////////////////////////////////////////"
lines(7) = ""
lines(8) = ""
If struct.redirections.Length < 1 Then
lines(8) = "//"
Dim cells As SGsfDataCell() = struct.cells
Array.Sort(cells, New CDataCellColComparer)
For Each s As SGsfDataCell In cells
If Not s.hide Then lines(8) &= s.name & vbTab
Next
lines(8) = lines(8).Substring(0, lines(8).Length - vbTab.Length)
End If
For Each t As CGsfCoder.STableLine In table
lines(lcnt) = New String("")
For Each p As CGsfCoder.SParamElem In t.params
lines(lcnt) &= p.value & vbTab
Next
If lines(lcnt).Length > 0 Then lines(lcnt) = lines(lcnt).Substring(0, lines(lcnt).Length - vbTab.Length)
lcnt += 1
Next
''for working on gsfStruct only!
''once its ready this part has to be deleted
'Dim larr As New ArrayList
'larr.Add(lines(8))
'Dim sr As New IO.StreamReader("MonsterPrototype.txt")
'Dim l2arr As New ArrayList
'sr.ReadLine()
'Do While Not sr.EndOfStream
' Dim l As String = sr.ReadLine.Trim
' Dim id As Integer = Val(l.Split(" ")(0))
' Dim c As New testIdLine
' c.id = id
' c.line = l
' l2arr.Add(c)
'Loop
'sr.Close()
'For j As Integer = 9 To lines.Length - 1
' Dim id As Integer = Val(lines(j).Split(" ")(0))
' Dim l As String = lineForId(l2arr, id)
' If l <> "" Then
' larr.Add(lines(j))
' Dim cc As String() = l.Split(vbTab)
' larr.Add(String.Join(vbTab, cc))
' End If
'Next
'lines = larr.ToArray(GetType(String))
''til(here)
Return lines
End Function
Public Shared Function Text2Struct(ByRef lines As String()) As STableLine()
'Dim t As String = "E" & lines(2).Substring(3)
'Dim type As gsfType = [Enum].Parse(GetType(gsfType), t, True)
Dim table As New ArrayList
For i As Integer = 0 To lines.Length - 1
Dim l As String = lines(i).Trim()
If l <> "" AndAlso l.Length > 0 AndAlso (l.Length < 2 OrElse l.Substring(0, 2) <> "//") Then
Dim splices As String() = l.Split(vbTab)
Dim params(splices.Length - 1) As SParamElem
For k As Integer = 0 To splices.Length - 1
params(k) = CreateParamElem(DataType.EString, splices(k))
Next
Dim tl As New STableLine
tl.params = params
table.Add(tl)
End If
Next
Return table.ToArray(GetType(STableLine))
End Function
Public Shared Function Data2Struct(ByRef data As Byte(), ByVal type As gsfType, Optional ByVal testVersion As Integer = 0, Optional ByRef resultVersion As Integer = 0) As STableLine()
Dim struct As SGsfDataStructure = getStructureInfo(type, testVersion)
If struct.version > 0 Then resultVersion = struct.version
Dim out As New ArrayList
' ------ rules ------
Dim enableEmptyLineIgnore As Boolean = False
Dim emptyLineIgnoreCol As Integer = 0
Dim emptyLineIgnoreVal As Object = Nothing
Dim emptyLineIgnoreRepeat As Integer = 0
Dim emptyLineCounter As Integer = 0
Dim emptyLineCounterActive As Boolean = False
If Not struct.rules Is Nothing Then
Dim n As Xml.XmlNode = struct.rules.SelectSingleNode("repeatemptyline")
If Not n Is Nothing Then
enableEmptyLineIgnore = True
emptyLineIgnoreCol = n.Attributes.GetNamedItem("listentocol").Value - 1
emptyLineIgnoreVal = n.Attributes.GetNamedItem("onvalue").Value
'If Val(emptyLineIgnoreVal) = emptyLineIgnoreVal Then emptyLineIgnoreVal = Val(emptyLineIgnoreVal)
emptyLineIgnoreRepeat = n.Attributes.GetNamedItem("repeat").Value
End If
End If
' ---- end rules ----
If struct.cellsSize > 0 Then
Dim sr As New IO.BinaryReader(New IO.MemoryStream(data))
Do While sr.BaseStream.Position < sr.BaseStream.Length
Dim params As New ArrayList
Dim lineEnd As Boolean = False
Do While Not lineEnd
For Each p As SGsfDataCell In struct.cells
Dim e As SParamElem = CreateParamElem(getParamElemType(p.dataType), readCell(sr, p))
'If p.col = 2 Then Debug.WriteLine(e.value)
If p.replace > 0 Then
e.type = DataType.EString
For Each rep As SGsfReplacementTable In struct.replacements
If rep.id = p.replace Then
For Each repE As SGsfReplacementElem In rep.elems
If repE.fromItem = e.value Then
e.value = repE.toItem
Exit For
End If
Next
End If
Next
ElseIf p.multiplier > 0 Then
e.value = e.value * p.multiplier
End If
If Not p.hide Then params.Add(e)
Next
' virtual cells which will be ignored on file saving into gsf
For Each p As SGsfDataCell In struct.textVirtualCells
Dim expressionValue As Object = p.virtualCellExpression.Invoke(Nothing, New Object() {params.ToArray(GetType(SParamElem))})
Dim e As SParamElem = CreateParamElem(getParamElemType(p.dataType), expressionValue)
If p.replace > 0 Then
e.type = DataType.EString
For Each rep As SGsfReplacementTable In struct.replacements
If rep.id = p.replace Then
For Each repE As SGsfReplacementElem In rep.elems
If repE.fromItem = e.value Then
e.value = repE.toItem
Exit For
End If
Next
End If
Next
ElseIf p.multiplier > 0 Then
e.value = e.value * p.multiplier
End If
If Not p.hide Then params.Add(e)
Next
If struct.hasLineSplit AndAlso struct.lineSpplit.len > 0 Then
Dim e As SParamElem = CreateParamElem(getParamElemType(struct.lineSpplit.dataType), readCell(sr, struct.lineSpplit))
If e.value = struct.lineSpplit.value Then
lineEnd = True
Else
lineEnd = False
sr.BaseStream.Seek(struct.lineSpplit.len * (-1), IO.SeekOrigin.Current)
End If
Else
lineEnd = True
End If
Loop
If emptyLineCounterActive Then
If emptyLineCounter = emptyLineIgnoreRepeat Then
emptyLineCounterActive = False
End If
emptyLineCounter += 1
End If
If params.Count > 0 Then
Dim nl As New STableLine
Dim paramsL(params.Count - 1) As SParamElem
If struct.hasColNums Then
Dim sI As Integer = 0
Dim usedCols As New ArrayList
For Each p As SGsfDataCell In struct.cells
If p.col > 0 AndAlso Not p.hide Then
paramsL(p.col - 1) = params(sI)
If usedCols.IndexOf(p.col) >= 0 Then
Throw New Exception("Col " & p.col & " used multiple times")
End If
usedCols.Add(p.col)
sI += 1
End If
Next
For Each p As SGsfDataCell In struct.textVirtualCells
If p.col > 0 AndAlso Not p.hide Then
paramsL(p.col - 1) = params(sI)
If usedCols.IndexOf(p.col) >= 0 Then
Throw New Exception("Col " & p.col & " used multiple times")
End If
usedCols.Add(p.col)
sI += 1
End If
Next
Else
paramsL = params.ToArray(GetType(SParamElem))
End If
nl.params = redirectCells(struct, paramsL)
'Dim ka As SParamElem() = redirectCells(struct, nl.params, False)
If Not emptyLineCounterActive Then
out.Add(nl)
End If
If enableEmptyLineIgnore AndAlso nl.params(emptyLineIgnoreCol).value = emptyLineIgnoreVal AndAlso Not emptyLineCounterActive Then
emptyLineCounterActive = True
emptyLineCounter = 0
End If
'Debug.WriteLine(sr.BaseStream.Position & ": " & params(22).value)
End If
Loop
sr.Close()
End If
Return out.ToArray(GetType(STableLine))
End Function
Public Shared Function Struct2Data(ByRef table As STableLine(), ByVal type As gsfType, Optional ByVal version As Integer = 0) As Byte()
Dim struct As SGsfDataStructure = getStructureInfo(type, version)
Dim buff(saveBuffer - 1) As Byte
Dim sw As New IO.BinaryWriter(New IO.MemoryStream(buff))
' ------ rules ------
Dim enableEmptyLineIgnore As Boolean = False
Dim emptyLineIgnoreCol As Integer = 0
Dim emptyLineIgnoreVal As Object = Nothing
Dim emptyLineIgnoreRepeat As Integer = 0
Dim emptyLineCounter As Integer = 0
Dim emptyLineCounterActive As Boolean = False
If Not struct.rules Is Nothing Then
Dim n As Xml.XmlNode = struct.rules.SelectSingleNode("repeatemptyline")
If Not n Is Nothing Then
enableEmptyLineIgnore = True
emptyLineIgnoreCol = n.Attributes.GetNamedItem("listentocol").Value - 1
emptyLineIgnoreVal = n.Attributes.GetNamedItem("onvalue").Value
'If Val(emptyLineIgnoreVal) = emptyLineIgnoreVal Then emptyLineIgnoreVal = Val(emptyLineIgnoreVal)
emptyLineIgnoreRepeat = n.Attributes.GetNamedItem("repeat").Value
End If
End If
' ---- end rules ----
Dim row As Integer = 0
Do While row < table.Length OrElse emptyLineCounterActive
Dim params As SParamElem() = {}
If emptyLineCounterActive Then
If emptyLineCounter = emptyLineIgnoreRepeat Then
emptyLineCounterActive = False
End If
emptyLineCounter += 1
End If
If Not emptyLineCounterActive Then params = redirectCells(struct, table(row).params, False)
If enableEmptyLineIgnore AndAlso Not emptyLineCounterActive AndAlso params(emptyLineIgnoreCol).value = emptyLineIgnoreVal Then
emptyLineCounterActive = True
emptyLineCounter = 0
End If
If struct.hasColNums AndAlso (Not emptyLineCounterActive OrElse emptyLineCounter = 0) Then
Dim sI As Integer = 0
Dim paramsL(params.Length - 1) As SParamElem
For Each p As SGsfDataCell In struct.cells
If p.col > 0 AndAlso Not p.hide Then
paramsL(sI) = params(p.col - 1)
sI += 1
End If
Next
params = paramsL
End If
Dim colSn As Integer = 0
Dim colEn As Integer = 0
Dim mCol As Integer = params.Length - 1
Dim skip As Boolean = False
If struct.cells.Length - 1 > mCol Then mCol = struct.cells.Length - 1
For col As Integer = 0 To mCol
If colSn > struct.cells.Length - 1 Then colSn = 0
Dim p As SGsfDataCell
If colSn < struct.cells.Length Then
p = struct.cells(colSn)
ElseIf struct.textVirtualCells.Length > 0 Then
skip = True
'p = struct.textVirtualCells(colSn - struct.cells.Length)
End If
If Not skip Then
Dim v As Object = 0
If p.hide Then
v = p.value
ElseIf emptyLineCounterActive AndAlso emptyLineCounter > 0 Then
If p.dataType Is GetType(Char()) Then
v = ""
ElseIf p.dataType Is GetType(Char) Then
v = Chr(0)
Else
v = 0
End If
Else
v = params(colEn).value
End If
'---------------------- replacement start ----------------------
If p.replace > 0 AndAlso (Not emptyLineCounterActive OrElse emptyLineCounter = 0) Then
For Each rep As SGsfReplacementTable In struct.replacements
If rep.id = p.replace Then
For Each repE As SGsfReplacementElem In rep.elems
If repE.toItem = v Then
v = repE.fromItem
Exit For
End If
Next
End If
Next
ElseIf p.multiplier > 0 Then
v = v / p.multiplier
End If
'---------------------- replacement end ------------------------
writeCell(sw, p, v)
End If
colSn += 1
If Not p.hide Then colEn += 1 '1 round late when hide
Next
If struct.hasLineSplit Then
writeCell(sw, struct.lineSpplit, struct.lineSpplit.value)
End If
If Not emptyLineCounterActive OrElse emptyLineCounter = 0 Then row += 1
Loop
Dim len As Long = sw.BaseStream.Position
sw.Seek(0, IO.SeekOrigin.Begin)
Dim out(len - 1) As Byte
sw.BaseStream.Read(out, 0, len)
sw.Close()
Return out
End Function
Public Shared Function Crypt(ByRef file As GsfFile) As Byte()
Dim cr As Byte() = CryptArea(file.gsfData, file.type)
Dim out(file.picture.Length + cr.Length - 1) As Byte
Array.ConstrainedCopy(file.picture, 0, out, 0, file.picture.Length)
Array.ConstrainedCopy(cr, 0, out, file.picture.Length + 0, cr.Length)
Return out
End Function
Public Shared Function DeCrypt(ByRef data As Byte()) As GsfFile 'for full picture
Dim gf As New GsfFile
gf.type = getGsfType(data)
Dim foundPos As Long = getFileSplitPos(data)
Dim image(foundPos - 1) As Byte
Dim gsfdata(data.Length - foundPos - 1) As Byte
Array.ConstrainedCopy(data, 0, image, 0, image.Length)
Array.ConstrainedCopy(data, foundPos, gsfdata, 0, gsfdata.Length)
gf.picture = image
gf.gsfData = DeCryptArea(gsfdata, gf.type)
Return gf
End Function
Public Shared Function CryptArea(ByVal data As Byte(), ByVal type As gsfType) As Byte()
xorDataArea(data, GetXorData(type))
For i As Integer = 0 To data.Length - 1
Dim b As Byte = data(i)
If b > &H7F Then
data(i) = (b - &H80) * 2 + 1
Else
data(i) = b * 2
End If
Next
Dim compData As Byte() = Compress(data)
Dim ndata(compData.Length + 3) As Byte
AddMath.SetUInt32inBytes(ndata, data.Length, 0)
Array.ConstrainedCopy(compData, 0, ndata, 4, compData.Length)
Return ndata
End Function
Public Shared Function DeCryptArea(ByRef data As Byte(), ByVal type As gsfType) As Byte() 'for gsf data only
Dim len As Integer = AddMath.getUInt32(0, data)
Dim sliceData(data.Length - 5) As Byte
Array.ConstrainedCopy(data, 4, sliceData, 0, sliceData.Length)
Dim decompData As Byte() = DeCompress(sliceData, len)
For i As Integer = 0 To decompData.Length - 1
Dim b As Byte = decompData(i)
If b Mod 2 Then
decompData(i) = (b - 1) / 2 + &H80
Else
decompData(i) = b / 2
End If
Next
xorDataArea(decompData, GetXorData(type))
Return decompData
End Function
Private Shared Function Compress(ByRef data As Byte()) As Byte()
Return FischR.Wrapper.Compress(data)
End Function
Private Shared Function DeCompress(ByRef data As Byte(), ByVal unCompLength As Integer) As Byte()
Return FischR.Wrapper.Decompress(data, unCompLength)
End Function
Private Shared Function GetXorData(ByVal type As gsfType) As Byte()
Dim xorStr As String = ""
If type > -1 AndAlso type < xorDat.Length Then
xorStr = xorDat(type)
End If
Dim slices As String() = xorStr.Trim.Split(" ")
Dim out(slices.Length - 1) As Byte
For i As Integer = 0 To slices.Length - 1
If slices(i).Trim <> "" Then out(i) = Byte.Parse(slices(i), Globalization.NumberStyles.HexNumber)
Next
Return out
End Function
Private Shared Sub xorDataArea(ByRef data As Byte(), ByRef key As Byte())
Dim col As Integer = 0
For i As Integer = 0 To data.Length - 1
If col > key.Length - 1 Then
col = 0
End If
Dim vi As Byte = data(i)
Dim vo As Byte = vi Xor key(col)
data(i) = vo
col += 1
Next
End Sub
Public Shared Function getGsfType(ByRef file As Byte()) As gsfType
Dim typec As UInt32 = AddMath.getUInt32(0, file)
Dim found As Boolean = False
For j As Integer = 0 To typeCodes.Length - 1
If typeCodes(j) = typec Then
If j = gsfType.EItemScript Then
If file.Length < 50 * 1024 Then j = gsfType.EScript1
End If
Return j
End If
Next
Throw New Exception("Unrecognized gsf file type")
End Function
Public Shared Function getFileSplitPos(ByRef data As Byte()) As Long
Dim lB As Byte = 0
Dim i As Long = 0
For Each b As Byte In data
If lB = &HFF AndAlso b = &HD9 AndAlso data(i + 4) = 0 AndAlso data(i + 5) = 0 AndAlso (data(i + 1) <> &H38 OrElse data(i + 1) <> &H42 OrElse data(i + 1) <> &H49 OrElse data(i + 1) <> &H4D) Then
Return i + 1
End If
lB = b
i += 1
Next
Throw New Exception("GSF data cant be found inside this file")
End Function
Public Shared Function CreateParamElem(ByVal type As DataType, ByVal value As Object) As SParamElem
Dim a As New SParamElem
a.type = type
a.value = value
Return a
End Function
Private Structure SGsfReplacementElem
Dim fromItem As Integer
Dim toItem As String
End Structure
Private Structure SGsfReplacementTable
Dim id As Integer
Dim elems As SGsfReplacementElem()
End Structure
Private Structure SGsfRedirElem
Dim name As String
Dim fromCol As Integer
Dim toCol As Integer
End Structure
Private Structure SGsfRedirTableTestItem
Dim values As Object()
End Structure
Private Structure SGsfRedirTable
Dim name As String
Dim useAsHeader As Boolean
Dim values As SGsfRedirTableTestItem()
Dim elems As SGsfRedirElem()
End Structure
Friend Structure SGsfDataCell
Dim name As String
Dim dataType As Type
Dim len As Integer
Dim value As Integer
Dim hide As Boolean
Dim col As Integer
Dim replace As Integer
Dim hex As Boolean
Dim endTag As Byte
Dim multiplier As Integer
Dim redirCase As Integer
Dim virtualCellExpression As System.Reflection.MethodInfo
End Structure
Private Structure SGsfDataStructure
Dim cells As SGsfDataCell()
Dim textVirtualCells As SGsfDataCell()
Dim lineSpplit As SGsfDataCell
Dim hasLineSplit As Boolean
Dim cellsSize As Integer
Dim hasColNums As Boolean
Dim replacements As SGsfReplacementTable()
Dim redirections As SGsfRedirTable()
Dim rules As Xml.XmlNode
Dim version As Integer
End Structure
Private Shared Function getStructureInfo(ByVal type As gsfType, Optional ByVal version As Integer = 0) As SGsfDataStructure
Dim x As New Xml.XmlDataDocument
Dim t As String = [Enum].GetName(GetType(gsfType), type).Substring(1)
Dim appN As String() = Application.ExecutablePath.Split(New Char() {"\", "/"})
Dim appF As String = Application.ExecutablePath.Substring(0, Application.ExecutablePath.Length - appN(UBound(appN)).Length)
If IO.File.Exists(appF & "gsfStruct.xml") Then
x.Load(appF & "gsfStruct.xml")
Else
x.LoadXml(Global.rylCoder.My.Resources.gsfStruct)
End If
Dim fileN As Xml.XmlNode = Nothing
If version < 0 Then
Dim fNs As Xml.XmlNodeList = x.SelectNodes("gsf/file[@name='" & t & "']")
Dim ind As Integer = Math.Abs(version) - 1
If ind > fNs.Count - 1 Then
Throw New GsfVersionLoopOutOfRange("Not supported GSF version")
End If
fileN = fNs.Item(ind)
Else
fileN = x.SelectSingleNode("gsf/file[@name='" & t & "'" & IIf(version > 0, " and @version=" & version, "") & "]")
End If
If fileN Is Nothing Then Throw New NotSupportedException("This GSF file is not supported")
Dim dataS As New SGsfDataStructure
If Not fileN.Attributes.GetNamedItem("version") Is Nothing Then dataS.version = AddMath.resolveInteger(fileN.Attributes.GetNamedItem("version").Value)
Dim structN As Xml.XmlNode = fileN.SelectSingleNode("structure")
If Not structN Is Nothing Then
Dim cellsN As Xml.XmlNode = structN.SelectSingleNode("cells")
Dim virtualCellsNode As Xml.XmlNodeList = structN.SelectNodes("virtualcells/text/cell")
Dim cellsNs As Xml.XmlNodeList = structN.SelectNodes("cells/cell")
Dim splitN As Xml.XmlNode = structN.SelectSingleNode("linesplit")
If Not cellsN Is Nothing Then
dataS.cellsSize = AddMath.resolveInteger(cellsN.Attributes.GetNamedItem("size").Value)
If Not cellsN.Attributes.GetNamedItem("hascolumns") Is Nothing Then dataS.hasColNums = IIf(AddMath.resolveInteger(cellsN.Attributes.GetNamedItem("hascolumns").Value) > 0, True, False)
End If
If Not splitN Is Nothing Then
Dim cell As Xml.XmlNode = splitN
Dim ca As New SGsfDataCell
If Not cell.Attributes.GetNamedItem("type") Is Nothing Then ca.dataType = AddMath.resolveDataType(cell.Attributes.GetNamedItem("type").Value)
If Not cell.Attributes.GetNamedItem("type") Is Nothing Then ca.len = AddMath.resolveDataTypeLen(cell.Attributes.GetNamedItem("type").Value)
If Not cell.Attributes.GetNamedItem("hide") Is Nothing Then ca.hide = IIf(AddMath.resolveInteger(cell.Attributes.GetNamedItem("hide").Value) > 0, True, False)
If Not cell.Attributes.GetNamedItem("hex") Is Nothing Then ca.hex = IIf(AddMath.resolveInteger(cell.Attributes.GetNamedItem("hex").Value) > 0, True, False)
If Not cell.Attributes.GetNamedItem("name") Is Nothing Then ca.name = cell.Attributes.GetNamedItem("name").Value
If Not cell.Attributes.GetNamedItem("val") Is Nothing Then ca.value = AddMath.resolveInteger(cell.Attributes.GetNamedItem("val").Value)
If Not cell.Attributes.GetNamedItem("col") Is Nothing Then ca.col = AddMath.resolveInteger(cell.Attributes.GetNamedItem("col").Value)
dataS.lineSpplit = ca
dataS.hasLineSplit = True
End If
If cellsNs.Count > 0 Then
Dim cArr(cellsNs.Count - 1) As SGsfDataCell
Dim i As Integer = 0
For Each cell As Xml.XmlNode In cellsNs
Dim ca As New SGsfDataCell
If Not cell.Attributes.GetNamedItem("type") Is Nothing Then ca.dataType = AddMath.resolveDataType(cell.Attributes.GetNamedItem("type").Value)
If Not cell.Attributes.GetNamedItem("type") Is Nothing Then ca.len = AddMath.resolveDataTypeLen(cell.Attributes.GetNamedItem("type").Value)
If Not cell.Attributes.GetNamedItem("hide") Is Nothing Then ca.hide = IIf(AddMath.resolveInteger(cell.Attributes.GetNamedItem("hide").Value) > 0, True, False)
If Not cell.Attributes.GetNamedItem("hex") Is Nothing Then ca.hex = IIf(AddMath.resolveInteger(cell.Attributes.GetNamedItem("hex").Value) > 0, True, False)
If Not cell.Attributes.GetNamedItem("name") Is Nothing Then ca.name = cell.Attributes.GetNamedItem("name").Value
If Not cell.Attributes.GetNamedItem("val") Is Nothing Then ca.value = AddMath.resolveInteger(cell.Attributes.GetNamedItem("val").Value)
If Not cell.Attributes.GetNamedItem("col") Is Nothing Then ca.col = AddMath.resolveInteger(cell.Attributes.GetNamedItem("col").Value)
If Not cell.Attributes.GetNamedItem("replace") Is Nothing Then ca.replace = AddMath.resolveInteger(cell.Attributes.GetNamedItem("replace").Value)
If Not cell.Attributes.GetNamedItem("endtag") Is Nothing Then ca.endTag = AddMath.resolveInteger(cell.Attributes.GetNamedItem("endtag").Value)
If Not cell.Attributes.GetNamedItem("multiplier") Is Nothing Then ca.multiplier = AddMath.resolveInteger(cell.Attributes.GetNamedItem("multiplier").Value)
If Not cell.Attributes.GetNamedItem("redir_case") Is Nothing Then ca.redirCase = AddMath.resolveInteger(cell.Attributes.GetNamedItem("redir_case").Value)
cArr(i) = ca
i += 1
Next
dataS.cells = cArr
End If
If virtualCellsNode.Count > 0 Then
Dim cArr(virtualCellsNode.Count - 1) As SGsfDataCell
Dim i As Integer = 0
For Each cell As Xml.XmlNode In virtualCellsNode
Dim ca As New SGsfDataCell
If Not cell.Attributes.GetNamedItem("type") Is Nothing Then ca.dataType = AddMath.resolveDataType(cell.Attributes.GetNamedItem("type").Value)
If Not cell.Attributes.GetNamedItem("type") Is Nothing Then ca.len = AddMath.resolveDataTypeLen(cell.Attributes.GetNamedItem("type").Value)
If Not cell.Attributes.GetNamedItem("hide") Is Nothing Then ca.hide = IIf(AddMath.resolveInteger(cell.Attributes.GetNamedItem("hide").Value) > 0, True, False)
If Not cell.Attributes.GetNamedItem("hex") Is Nothing Then ca.hex = IIf(AddMath.resolveInteger(cell.Attributes.GetNamedItem("hex").Value) > 0, True, False)
If Not cell.Attributes.GetNamedItem("name") Is Nothing Then ca.name = cell.Attributes.GetNamedItem("name").Value
If Not cell.Attributes.GetNamedItem("val") Is Nothing Then ca.value = AddMath.resolveInteger(cell.Attributes.GetNamedItem("val").Value)
If Not cell.Attributes.GetNamedItem("col") Is Nothing Then ca.col = AddMath.resolveInteger(cell.Attributes.GetNamedItem("col").Value)
If Not cell.Attributes.GetNamedItem("replace") Is Nothing Then ca.replace = AddMath.resolveInteger(cell.Attributes.GetNamedItem("replace").Value)
If Not cell.Attributes.GetNamedItem("endtag") Is Nothing Then ca.endTag = AddMath.resolveInteger(cell.Attributes.GetNamedItem("endtag").Value)
If Not cell.Attributes.GetNamedItem("multiplier") Is Nothing Then ca.multiplier = AddMath.resolveInteger(cell.Attributes.GetNamedItem("multiplier").Value)
If Not cell.Attributes.GetNamedItem("redir_case") Is Nothing Then ca.redirCase = AddMath.resolveInteger(cell.Attributes.GetNamedItem("redir_case").Value)
If Not cell.Attributes.GetNamedItem("value") Is Nothing Then ca.virtualCellExpression = CEvalProvider.GetFunction(cell.Attributes.GetNamedItem("value").Value) Else ca.virtualCellExpression = CEvalProvider.GetFunction(cell.InnerText)
cArr(i) = ca
i += 1
Next
dataS.textVirtualCells = cArr
Else
dataS.textVirtualCells = New SGsfDataCell() {}
End If
End If
Dim repsN As Xml.XmlNodeList = fileN.SelectNodes("replacements/replacement")
Dim reps As SGsfReplacementTable() = {}
If repsN.Count > 0 Then
ReDim reps(repsN.Count - 1)
Dim j As Integer = 0
For Each rN As Xml.XmlNode In repsN
Dim rep As New SGsfReplacementTable
rep.id = rN.Attributes.GetNamedItem("id").Value
Dim repENs As Xml.XmlNodeList = rN.SelectNodes("elem")
Dim repelems As New ArrayList
For Each repEN As Xml.XmlNode In repENs
Dim repE As New SGsfReplacementElem
repE.fromItem = AddMath.resolveInteger(repEN.Attributes.GetNamedItem("from").Value)
repE.toItem = repEN.Attributes.GetNamedItem("to").Value
repelems.Add(repE)
Next
rep.elems = repelems.ToArray(GetType(SGsfReplacementElem))
reps(j) = rep
j += 1
Next
End If
dataS.replacements = reps
Dim redirN As Xml.XmlNodeList = fileN.SelectNodes("redirections/redirection")
Dim redirs As SGsfRedirTable() = {}
If redirN.Count > 0 Then
ReDim redirs(redirN.Count - 1)
Dim j As Integer = 0
For Each rN As Xml.XmlNode In redirN
Dim red As New SGsfRedirTable
red.name = rN.Attributes.GetNamedItem("name").Value
Dim vs As String() = rN.Attributes.GetNamedItem("values").Value.Split(";")
Dim vals(vs.Length - 1) As SGsfRedirTableTestItem
Dim jj As Integer = 0
For Each vv As String In vs
vals(jj) = New SGsfRedirTableTestItem
vals(jj).values = vv.Split(",")
jj += 1
Next
red.values = vals
Dim redENs As Xml.XmlNodeList = rN.SelectNodes("cell")
Dim redelems As New ArrayList
jj = 1
For Each redEN As Xml.XmlNode In redENs
Dim redE As New SGsfRedirElem
redE.fromCol = AddMath.resolveInteger(redEN.Attributes.GetNamedItem("col").Value)
redE.name = redEN.Attributes.GetNamedItem("name").Value
redE.toCol = jj
If redE.fromCol > 0 Then
redelems.Add(redE)
jj += 1
End If
Next
red.elems = redelems.ToArray(GetType(SGsfRedirElem))
redirs(j) = red
j += 1
Next
End If
dataS.redirections = redirs
dataS.rules = fileN.SelectSingleNode("rules")
Return dataS
End Function
Private Shared Function getParamElemType(ByRef type As Type) As DataType
If type Is GetType(Byte) Then
Return DataType.EInteger
ElseIf type Is GetType(Int16) Then
Return DataType.EInteger
ElseIf type Is GetType(UInt16) Then
Return DataType.EInteger
ElseIf type Is GetType(Int32) Then
Return DataType.EInteger
ElseIf type Is GetType(UInt32) Then
Return DataType.EInteger
ElseIf type Is GetType(Char) Then
Return DataType.EString
ElseIf type Is GetType(Char()) Then
Return DataType.EString
End If
Return DataType.ENull
End Function
Private Shared Function readCell(ByRef reader As IO.BinaryReader, ByRef cell As SGsfDataCell) As Object
If cell.dataType Is GetType(Byte) Then
Return addHextag(reader.ReadByte(), cell)
ElseIf cell.dataType Is GetType(Int16) Then
Return addHextag(reader.ReadInt16, cell)
ElseIf cell.dataType Is GetType(UInt16) Then
Return addHextag(reader.ReadUInt16, cell)
ElseIf cell.dataType Is GetType(Int32) Then
Return addHextag(reader.ReadInt32, cell)
ElseIf cell.dataType Is GetType(UInt32) Then
Return addHextag(reader.ReadUInt32, cell)
ElseIf cell.dataType Is GetType(Char) Then
Return Chr(reader.ReadByte)
ElseIf cell.dataType Is GetType(Single) Then
Return reader.ReadSingle
ElseIf cell.dataType Is GetType(Char()) Then
Dim bs As Byte() = reader.ReadBytes(cell.len)
Dim ms As String = ""
Dim i As Integer = 0
Do While i < bs.Length AndAlso bs(i) <> cell.endTag AndAlso bs(i) <> 0
ms &= Chr(bs(i))
i += 1
Loop
Return ms
End If
Return 0
End Function
Private Shared Sub writeCell(ByRef writer As IO.BinaryWriter, ByRef cell As SGsfDataCell, ByVal data As Object)
If cell.dataType Is GetType(Byte) Then
Dim d As Byte = 0
If Not cell.hex OrElse data.ToString.Length < 3 Then
d = CType(data, Byte)
Else
d = Convert.ToByte(data.substring(2), 16)
End If
writer.Write(d)
ElseIf cell.dataType Is GetType(Int16) Then
Dim d As Int16 = 0
If Not cell.hex OrElse data.ToString.Length < 3 Then
d = CType(data, Int16)
Else
d = Convert.ToInt16(data.substring(2), 16)
End If
writer.Write(d)
ElseIf cell.dataType Is GetType(UInt16) Then
Dim d As UInt16 = 0
If Not cell.hex OrElse data.ToString.Length < 3 Then
d = CType(data, UInt16)
Else
d = Convert.ToUInt16(data.substring(2), 16)
End If
writer.Write(d)
ElseIf cell.dataType Is GetType(Int32) Then
Dim d As Int32 = 0
If Not cell.hex OrElse data.ToString.Length < 3 Then
d = CType(data, Int32)
Else
d = Convert.ToInt32(data.substring(2), 16)
End If
writer.Write(d)
ElseIf cell.dataType Is GetType(UInt32) Then
Dim d As UInt32 = 0
If Not cell.hex OrElse data.ToString.Length < 3 Then
d = CType(data, UInt32)
Else
d = Convert.ToUInt32(data.substring(2), 16)
End If
writer.Write(d)
ElseIf cell.dataType Is GetType(Char) Then
Dim d As Char = CType(data, Char)
writer.Write(d)
ElseIf cell.dataType Is GetType(Single) Then
Dim d As Single = CType(data, Single)
writer.Write(d)
ElseIf cell.dataType Is GetType(Char()) Then
Dim d(cell.len - 1) As Byte
If Not data Is Nothing Then
Dim s As String = CType(data, String)
For i As Integer = 0 To s.Length - 1
d(i) = Asc(s(i))
Next
If s.Length > 0 AndAlso s.Length < d.Length Then d(s.Length) = cell.endTag
writer.Write(d)
End If
End If
End Sub
Private Shared Function addHextag(ByVal obj As Object, ByRef cell As SGsfDataCell) As Object
If cell.hex AndAlso Val(obj) > 0 Then
Return "0x" & Hex(obj).ToUpper
Else
Return obj
End If
End Function
Protected Class CDataCellColComparer
Implements IComparer
Function Compare(ByVal x As Object, ByVal y As Object) As Integer _
Implements IComparer.Compare
Dim lX As SGsfDataCell = CType(x, SGsfDataCell)
Dim ly As SGsfDataCell = CType(y, SGsfDataCell)
Return IIf(lX.col > ly.col, 1, IIf(lX.col < ly.col, -1, 0))
End Function
End Class
Public Class GsfVersionLoopOutOfRange
Inherits System.Exception
Public Sub New(ByVal message As String)
MyBase.New(message)
End Sub
End Class
Private Shared Function redirectCells(ByRef struct As SGsfDataStructure, ByRef cells As SParamElem(), Optional ByVal data2structDir As Boolean = True, Optional ByVal rowID As Integer = 0) As SParamElem()
'1 0 2 3 200 1 true 1 2 3 200 1
'0 0 1 7 100 0 ==> 1 7 100 0
'2 0 3 9 200 1 false 2 3 9 100 1
'0 0 1 4 150 2 <== 1 4 150 2
If struct.redirections.Length < 1 Then Return cells
Dim redirTable As SGsfRedirTable = Nothing
Dim out As New ArrayList 'SParamElem() = {}
Dim tableFound As Boolean = False
If data2structDir Then
Dim toComp As Object() = {}
For i As Integer = 0 To struct.cells.Length - 1
If struct.cells(i).redirCase > 0 Then
Dim c As Integer = i
If struct.hasColNums Then c = struct.cells(i).col - 1
ReDim Preserve toComp(UBound(toComp) + 1)
toComp(UBound(toComp)) = cells(c).value
End If
Next
For Each tab As SGsfRedirTable In struct.redirections
For Each e As SGsfRedirTableTestItem In tab.values
Dim vs As Integer = 0
Dim match As Integer = 0
For Each v As Object In e.values
If v = "*" OrElse v = toComp(vs) Then match += 1
vs += 1
Next
If match = e.values.Length Then
redirTable = tab
tableFound = True
Exit For
End If
Next
Next
If tableFound Then
Dim col As Integer = 1
Dim len As Integer = 0
For k As Integer = 0 To cells.Length - 1
out.Add(Nothing)
Next
For Each v As SParamElem In cells
Dim redE As SGsfRedirElem = Nothing
Dim redEfound As Boolean = False
For Each e As SGsfRedirElem In redirTable.elems
If e.fromCol = col Then
redE = e
redEfound = True
Exit For
End If
Next
If redEfound Then
out(redE.toCol - 1) = v
len += 1
End If
col += 1
Next
Dim nA As New ArrayList
For k As Integer = 0 To out.Count - 1
If Not out(k) Is Nothing Then nA.Add(out(k))
Next
out = nA
Else
'Debug.WriteLine("GSF redirect table not found on loading for: " & String.Join(" - ", AddMath.ObjArrToStr(toComp)))
Return cells
End If
Else
Dim toComp As Object() = {}
Dim numToComp As Integer = 0
If cells.Length < struct.cells.Length Then 'if the col count is same as the main struct it doesnt use a redir template
For i As Integer = 0 To struct.cells.Length - 1
If struct.cells(i).redirCase > 0 Then
numToComp += 1
End If
Next
For i As Integer = cells.Length - numToComp To cells.Length - 1
ReDim Preserve toComp(UBound(toComp) + 1)
toComp(UBound(toComp)) = cells(i).value
Next
For Each tab As SGsfRedirTable In struct.redirections
For Each e As SGsfRedirTableTestItem In tab.values
Dim vs As Integer = 0
Dim match As Integer = 0
For Each v As Object In e.values
If v = "*" OrElse v = toComp(vs) Then match += 1
vs += 1
Next
If match = e.values.Length Then
redirTable = tab
tableFound = True
Exit For
End If
Next
Next
If tableFound Then
Dim col As Integer = 1
Dim len As Integer = 0
Dim sCells(struct.cells.Length - 1) As SGsfDataCell
Array.Copy(struct.cells, sCells, struct.cells.Length)
Array.Sort(sCells, New CDataCellColComparer)
For k As Integer = 0 To sCells.Length - 1
If Not sCells(k).hide Then
Dim obj As Object = sCells(k).value
If sCells(k).replace > 0 Then
For Each rep As SGsfReplacementTable In struct.replacements
If rep.id = sCells(k).replace Then
For Each repE As SGsfReplacementElem In rep.elems
If repE.fromItem = obj Then
obj = repE.toItem
Exit For
End If
Next
End If
Next
End If
out.Add(CreateParamElem(DataType.EInteger, obj))
End If
Next
For Each v As SParamElem In cells
Dim redE As SGsfRedirElem = Nothing
Dim redEfound As Boolean = False
For Each e As SGsfRedirElem In redirTable.elems
If e.toCol = col Then
redE = e
redEfound = True
Exit For
End If
Next
If redEfound Then
out(redE.fromCol - 1) = v
len += 1
End If
col += 1
Next
Else
Debug.WriteLine("GSF redirect table not found on saving for: " & String.Join(" - ", AddMath.ObjArrToStr(toComp)))
Return cells
End If
Else
Return cells
End If
End If
Return out.ToArray(GetType(SParamElem))
End Function
End Class
Public Class CMcfBase
Protected decScript As Byte() = {}
Protected iFunctions As SFunction() = {}
Protected Shared scriptSectionStartTag As Byte() = {&H55, &H89, &HE5}
Protected Shared scriptSectionStopTag As Byte() = {&H89, &HEC, &H5D, &HC3}
Protected Const scriptSectionSpaceTag As Byte = &H90
Protected Const scriptAreaSplitTag As Byte = &HCC
Protected Const scriptSpaceMultiplier As Integer = 3
Protected RYLVersion As Integer = 0
Protected FileType As EFileType = EFileType.EUnknown
Public Const compilerTempMemSize As Integer = 5242880
Public Enum EFileType
EUnknown = 0
ENpcScript = 1
EQuest = 2
EScript = 3
End Enum
Public Shared SFileType As String() = {"Unknown", "NPC Script", "Quest", "Script"}
Public Structure SFunction
Dim id As Integer
Dim name As String
Dim index As Long
Dim parameterTypes() As DataType
Dim returnType As DataType
Dim isExternal As Boolean
Dim data() As SScriptLine
Public Overrides Function ToString() As String
Return "[" & id & "] " & name & ", index: 0x" & AddMath.Hex2(index) & ", return: " & [Enum].GetName(GetType(DataType), returnType) & ", isExternal: " & IIf(isExternal, "Yes", "No") & ", ParamCount: " & parameterTypes.Length
End Function
End Structure
Protected Structure SOffStr
Dim off As Long
Dim str As String
End Structure
Public Structure SScriptLine
Dim callTo As Integer
Dim parameters() As SParamElem
End Structure
Public Enum DataType
EVoid = 0
EBool = 1
EInteger = 2
EFloat = 3
EString = 4
End Enum
Public Structure SParamElem
Dim value As Object
Dim type As DataType
End Structure
Public Shared DataTypeString As String() = {"void", "bool", "int", "float", "string"}
Public ReadOnly Property Functions() As SFunction()
Get
Return iFunctions
End Get
End Property
Public ReadOnly Property Data() As Byte()
Get
Return decScript
End Get
End Property
Protected Class CFunctionSorter
Implements IComparer
Function Compare(ByVal x As Object, ByVal y As Object) As Integer _
Implements IComparer.Compare
Dim lX As SFunction = CType(x, SFunction)
Dim lY As SFunction = CType(y, SFunction)
Return New CaseInsensitiveComparer().Compare(lX.index, lY.index)
End Function
End Class
Protected Class CFunctionSorterByName
Implements IComparer
Function Compare(ByVal x As Object, ByVal y As Object) As Integer _
Implements IComparer.Compare
Dim lX As SFunction = CType(x, SFunction)
Dim lY As SFunction = CType(y, SFunction)
Return New CaseInsensitiveComparer().Compare(lX.name, lY.name)
End Function
End Class
Public Shared Function CreateParamElem(ByVal type As DataType, ByVal value As Object) As SParamElem
Dim a As New SParamElem
a.type = type
a.value = value
Return a
End Function
Protected Sub lookForFileType()
Dim Ryl2NpcScriptFunctions As String() = {"AddWords", "SetPosition", "SetNPC", "AddDialog", "AddItem", "AddZoneMove", "AddQuest", "SetDropGrade", "SetDropBase", "AddQuestWords", "AddPopup", "SetNPCAttribute"}
Dim Ryl2QuestFunctions As String() = {"QuestEnd", "QuestSkillPointBonus", "QuestStart", "QuestType", "QuestArea", "QuestTitle", "QuestDesc", "QuestShortDesc", "QuestIcon", "QuestCompleteSave", "QuestLevel", "QuestAward", "AddPhase", "Phase_Target", "Trigger_Start", "Trigger_Puton", "Trigger_Geton", "Trigger_Talk", "Trigger_Kill", "Trigger_Pick", "Trigger_Fame", "Trigger_LevelTalk", "Else", "Event_Disappear", "Event_Get", "Event_Spawn", "Event_MonsterDrop", "Event_Award", "Event_MsgBox", "Event_Phase", "Event_End", "Event_AwardItem", "Event_AddQuest", "Event_Move", "Event_TheaterMode"}
Dim Ryl1NpcScriptFunctions As String() = {"AddWords", "SetPosition", "SetNPC", "AddDialog", "AddItem", "AddSkillBook", "AddZoneMove", "AddQuest"}
Dim Ryl2ScriptFunctions As String() = {"AddString", "AddString", "RylNation"}
Dim Ryl1QuestFunction As String() = {"QuestTitle", "QuestDesc", "QuestShortDesc", "QuestIcon", "QuestCompleteSave", "QuestLevel", "QuestAward", "AddPhase", "Phase_Target", "Trigger_Start", "Trigger_Puton", "Trigger_Geton", "Trigger_Talk", "Trigger_Kill", "Trigger_Pick", "Else", "Event_Disappear", "Event_Get", "Event_Spawn", "Event_MonsterDrop", "Event_Award", "Event_MsgBox", "Event_Phase", "Event_End"}
Dim r2n% = 0, r2q% = 0, r1n% = 0, r2s% = 0, r1q% = 0
Dim questStartFound As Boolean = False
For Each f As SFunction In iFunctions
If Array.IndexOf(Ryl2NpcScriptFunctions, f.name) >= 0 Then r2n += 1
If Array.IndexOf(Ryl2QuestFunctions, f.name) >= 0 Then r2q += 1
If Array.IndexOf(Ryl1NpcScriptFunctions, f.name) >= 0 Then r1n += 1
If Array.IndexOf(Ryl2ScriptFunctions, f.name) >= 0 Then r2s += 1
If Array.IndexOf(Ryl1QuestFunction, f.name) >= 0 Then r1q += 1
If f.name = "QuestStart" Then questStartFound = True
Next
If r2n = Ryl2NpcScriptFunctions.Length Then
RYLVersion = 2
FileType = EFileType.ENpcScript
ElseIf r2q = Ryl2QuestFunctions.Length Then
RYLVersion = 2
FileType = EFileType.EQuest
ElseIf r1n = Ryl1NpcScriptFunctions.Length Then
RYLVersion = 1
FileType = EFileType.ENpcScript
ElseIf r2s = Ryl2ScriptFunctions.Length Then
RYLVersion = 2
FileType = EFileType.EScript
ElseIf r1q = Ryl1QuestFunction.Length AndAlso questStartFound = False Then
RYLVersion = 1
FileType = EFileType.EQuest
Else
RYLVersion = 0
FileType = EFileType.EUnknown
End If
End Sub
Protected Function getFunctionId(ByVal functions As SFunction(), ByVal index As Integer) As Integer
For Each f As SFunction In functions
If f.index = index Then Return f.id
Next
Return -1
End Function
Public Shared Function CreateMainFunction() As SFunction
Dim mainFunc As New SFunction
mainFunc.id = 0
mainFunc.index = scriptSpaceMultiplier
mainFunc.isExternal = False
mainFunc.name = ""
mainFunc.returnType = DataType.EVoid
mainFunc.parameterTypes = New DataType() {}
Return mainFunc
End Function
End Class
Public Class CMcfDecompiler
Inherits CMcfBase
Private pointers As Long() = {}
Private traceStart&, traceLength&, textStart&, textLength&, scriptStart&, scriptLength&, functionsStart&, functionsLength&
Private Sub setMainOffsets()
traceStart = 3 * 4
traceLength = AddMath.getUInt32(4, decScript) * 4
textStart = traceStart + traceLength + 12
textLength = AddMath.getUInt32(traceStart + traceLength + 4, decScript)
scriptStart = textStart + textLength
scriptLength = AddMath.getUInt32(traceStart + traceLength + 8, decScript)
functionsStart = scriptStart + scriptLength
functionsLength = decScript.Length - functionsStart
ReDim pointers(traceLength / 4 - 1)
Dim pos As Long = traceStart
For i As Long = 0 To traceLength / 4 - 1
pointers(i) = AddMath.getUInt32(pos, decScript)
pos += 4
Next
End Sub
Private Function getFunctions() As SFunction()
Dim functionCount As Integer = AddMath.getUInt32(functionsStart, decScript) + 1
Dim pos As Long = functionsStart + 4
Dim functions(functionCount - 1) As SFunction
' Main function definition
functions(0) = CreateMainFunction()
For i As Integer = 1 To functionCount - 1
Dim fName As String = ""
Do While decScript(pos) <> &HA
fName &= Chr(decScript(pos))
pos += 1
Loop
pos += 1
Dim params As UInt32 = AddMath.getUInt32(pos, decScript)
pos += 4
Dim index As UInt32 = AddMath.getUInt32(pos, decScript)
pos += 4
Dim func As New SFunction
func.name = fName
func.parameterTypes = New DataType() {}
' 0xABBB BBBB <- up to 7 parameter types and the first one is return value, 0 for void
Dim paraListH As Char() = Hex(params).ToCharArray
If paraListH.Length = 8 Then
func.returnType = Val(paraListH(0))
paraListH = Hex(params - Val(paraListH(0)) * &H10000000).ToCharArray
Else
func.returnType = DataType.EVoid
End If
If paraListH.Length > 0 AndAlso Not (paraListH.Length = 1 AndAlso paraListH(0) = "0") Then
Array.Reverse(paraListH)
For Each c As Char In paraListH
ReDim Preserve func.parameterTypes(UBound(func.parameterTypes) + 1)
func.parameterTypes(UBound(func.parameterTypes)) = Val(c)
Next
End If
func.index = index
functions(i) = func
Next
Array.Sort(functions, New CFunctionSorter) 'Order the functions by indexes so they look like original's
For i As Integer = 0 To functionCount - 1
functions(i).id = i
'Debug.WriteLine(functions(i).ToString())
Next
parseDataArea(functions) 'Reads out the calls and parameters for each function, also defines if its a external function
Return functions
End Function
Private Sub parseDataArea(ByRef functions As SFunction())
Dim sr As New IO.BinaryReader(New IO.MemoryStream(decScript))
Dim txt() As SOffStr = getTexts()
For cfID As Integer = 0 To functions.Length - 1
Dim cFunc As SFunction = functions(cfID)
cFunc.isExternal = False
Dim calls As New List(Of SScriptLine)
Dim ongoingParams As New List(Of Integer)
sr.BaseStream.Seek(cFunc.index + scriptStart + 3, IO.SeekOrigin.Begin)
Do While sr.BaseStream.Position < sr.BaseStream.Length
Dim b As Byte = sr.ReadByte()
If b = &H51 Then b = sr.ReadByte() 'just a seperator, can be for the reason there can be in-place string and or 64bit pointers
If b = &HB9 Then 'Parameter
ongoingParams.Add(sr.ReadInt32())
ElseIf b = &HE8 Then 'Function definition
Dim f As Integer = sr.ReadInt32() 'The number shows the position of the function definition FROM currect position, can easily be negative
f = sr.BaseStream.Position - scriptStart + f
'Create a new script line to the function
Dim fID As Integer = getFunctionId(functions, f)
If fID < 0 Then Throw New Exception("Function with position " & f.ToString() & " not found in the declarations. Pos:" & sr.BaseStream.Position)
If functions(fID).parameterTypes.Length <> ongoingParams.Count Then Throw New Exception("Defined parameter count (" & ongoingParams.Count & ") does not match the declared function (" & functions(fID).name & ") parameters count (" & functions(fID).parameterTypes.Length & "), Pos:" & sr.BaseStream.Position)
calls.Add(CreateScriptLine(functions, fID, ongoingParams, txt, sr.BaseStream.Position))
ongoingParams.Clear()
ElseIf b = &H81 Then 'Function parameter's total length (all are 32bit pointers for reference types or 32bit value types anyway)
sr.ReadByte() '0xC4
Dim c As Integer = sr.ReadInt32() 'No use for this if the program is correctly compiled
ElseIf b = scriptSectionSpaceTag Then 'Empty function. E.g. External
cFunc.isExternal = True
ElseIf b = &H89 Then 'function definition end tag
Exit Do
End If
Loop
cFunc.data = calls.ToArray()
functions(cfID) = cFunc
Next
End Sub
Private Function CreateScriptLine(ByRef functions As SFunction(), ByVal callToFunctionID As Integer, ByRef params As List(Of Integer), ByRef texts As SOffStr(), ByVal debugPos As Long) As SScriptLine
Dim callToFunc As SFunction = functions(callToFunctionID)
Dim SLine As New SScriptLine
SLine.callTo = callToFunctionID
SLine.parameters = New SParamElem(params.Count - 1) {}
For i As Integer = 0 To params.Count - 1
SLine.parameters(i) = New SParamElem
SLine.parameters(i).type = callToFunc.parameterTypes(i)
SLine.parameters(i).value = params(i)
Select Case callToFunc.parameterTypes(i)
Case DataType.EFloat
Try
SLine.parameters(i).value = AddMath.DecToSingle(SLine.parameters(i).value)
Catch ex As Exception
Throw New Exception("Cant convert data to float on parameter " & (i + 1) & ", Pos:" & debugPos, ex)
End Try
Case DataType.EString
Dim found As Boolean = False
For Each txtE As SOffStr In texts
If txtE.off = SLine.parameters(i).value Then
SLine.parameters(i).value = txtE.str
found = True
Exit For
End If
Next
If Not found Then Throw New Exception("No string found for the position " & SLine.parameters(i).value & ", " & (i + 1) & "'th parameter, call pos:" & debugPos)
Case DataType.EBool
If SLine.parameters(i).value = 0 Then
SLine.parameters(i).value = False
ElseIf SLine.parameters(i).value = 1 Then
SLine.parameters(i).value = True
Else
Throw New Exception("Value " & SLine.parameters(i).value & " is not boolean (0 or 1) in parameter " & (i + 1) & ", Pos:" & debugPos)
End If
End Select
Next
Return SLine
End Function
Private Function getTexts() As SOffStr()
Dim out() As SOffStr = {}
Dim tmpStr As String = ""
Dim tmpOff As Long = 0
For i As Long = 0 To textLength - 1
Dim c As Byte = decScript(textStart + i)
If c = &H0 Then
Dim struc As New SOffStr
struc.off = tmpOff
struc.str = tmpStr
tmpStr = ""
tmpOff = i + 1
ReDim Preserve out(UBound(out) + 1)
out(UBound(out)) = struc
Else
tmpStr &= Chr(c)
End If
Next
Return out
End Function
Public Sub Decompile(ByVal decData() As Byte)
decScript = decData
setMainOffsets()
iFunctions = getFunctions()
End Sub
Public ReadOnly Property RYLFileVersion() As Integer
Get
If RYLVersion < 1 Then lookForFileType()
Return RYLVersion
End Get
End Property
Public ReadOnly Property RYLFileType() As EFileType
Get
If RYLVersion < 1 Then lookForFileType()
Return FileType
End Get
End Property
End Class
Public Class CMcfCompiler
Inherits CMcfBase
Private pointers As Long() = {}
Private headerLength&, textLength&, scriptLength&, functionsLength&
Private stringsToAdd As SOffStr() = {}
Public Sub Compile(ByRef Functions As SFunction())
iFunctions = Functions
decScript = New Byte() {}
Dim txt As Byte() = createTextArea()
textLength = txt.Length
Dim data As Byte() = createDataArea()
scriptLength = data.Length
Dim funcS As Byte() = createFunctionArea()
functionsLength = funcS.Length
Dim h As Byte() = createHeader()
headerLength = h.Length
Dim modulus As Integer = CMcfCoder.ModulusFromDivination(headerLength + textLength + scriptLength + functionsLength, 4)
Dim j As Integer = 0
For i As Integer = functionsLength - modulus To functionsLength - 1
funcS(i) = CMcfCoder.EnCryptByte(&H0, CType(j, CMcfCoder.Col))
j += 1
Next
AddMath.addBytesToEnd(decScript, h)
AddMath.addBytesToEnd(decScript, txt)
AddMath.addBytesToEnd(decScript, data)
AddMath.addBytesToEnd(decScript, funcS)
End Sub
Private Function createHeader() As Byte()
'Dim pointers() As UInt32 = {}
Dim outB(3 * 4 + pointers.Length * 4 + 3 * 4 - 1) As Byte
AddMath.SetUInt32inBytes(outB, pointers.Length, 4)
Dim pos As Long = 3 * 4
For Each pntr As UInt32 In pointers
AddMath.SetUInt32inBytes(outB, pntr, pos)
pos += 4
Next
outB(pos) = &H1C 'dunno
AddMath.SetUInt32inBytes(outB, textLength, pos + 4) 'text area size
AddMath.SetUInt32inBytes(outB, scriptLength, pos + 8) 'script area size
Return outB
End Function
Private Function createTextArea() As Byte() 'and parse the scriptlines parameters
Dim out As Byte() = {}
Dim sLC As Long = 0
Dim fId As Integer = 0
For Each f As SFunction In iFunctions
For Each sL As SScriptLine In f.data
Dim parC As Long = 0
For Each par As SParamElem In sL.parameters
If par.type = DataType.EString Then
Dim str As String = par.value
Dim off As Long = getStrOff(str, stringsToAdd)
If off < 0 Then
off = out.Length
ReDim Preserve stringsToAdd(UBound(stringsToAdd) + 1)
stringsToAdd(UBound(stringsToAdd)) = New SOffStr
stringsToAdd(UBound(stringsToAdd)).off = off
stringsToAdd(UBound(stringsToAdd)).str = str
ReDim Preserve out(off + str.Length)
Dim i As Long = 0
For Each c As Char In str
out(off + i) = Asc(c)
i += 1
Next
out(off + i) = &H0
End If
End If
parC += 1
Next
sLC += 1
Next
fId += 1
Next
Return out
End Function
Private Function createDataArea() As Byte()
Dim txtPointers As New List(Of Long)
Dim out(compilerTempMemSize - 1) As Byte
Dim sw As New IO.BinaryWriter(New IO.MemoryStream(out))
Dim functionAddrReWrite As New List(Of Long)
For i As Integer = 0 To scriptSpaceMultiplier - 1
sw.Write(scriptSectionSpaceTag)
Next
For fID As Integer = 0 To iFunctions.Length - 1
iFunctions(fID).index = sw.BaseStream.Position
Dim func As SFunction = iFunctions(fID)
sw.Write(scriptSectionStartTag) 'add start (55 89 E5)
If func.isExternal Then ' For external functions add the param placement (5bytes+3xparams)
For i As Integer = 1 To 5 + func.parameterTypes.Length * scriptSpaceMultiplier
sw.Write(scriptSectionSpaceTag)
Next
Else
For fLine As Integer = 0 To func.data.Length - 1
writeScriptLine(func.data(fLine), sw, txtPointers)
functionAddrReWrite.Add(sw.BaseStream.Position - 10) '10 = call pointer 4bytes + 0x81 0xC4 + param count 4bytes
Next
End If
sw.Write(scriptSectionStopTag) 'add ending (89 EC 5D C3)
If func.name = "" Then '"main" function is seperated from others (CC CC CC)
For i As Integer = 0 To scriptSpaceMultiplier - 1
sw.Write(scriptAreaSplitTag)
Next
End If
Next
sw.Flush()
Array.Resize(out, sw.BaseStream.Position)
' Set the indexes now
For Each pos As Long In functionAddrReWrite
Dim fId As Integer = AddMath.getUInt32(pos, out)
AddMath.SetInt32inBytes(out, iFunctions(fId).index - (pos + 4), pos) 'function calls are relative to the place where it is called from (4 becose the jump-from pace is the end of the destination position declaration(int32))
Next
pointers = txtPointers.ToArray()
Return out
End Function
Private Sub writeScriptLine(ByVal sLine As SScriptLine, ByRef sw As IO.BinaryWriter, ByRef txtPointers As List(Of Long))
Dim uFunc As SFunction = iFunctions(sLine.callTo)
For i As Integer = 0 To uFunc.parameterTypes.Length - 1
Dim v As Object = sLine.parameters(i).value
sw.Write(CType(&HB9, Byte))
Select Case uFunc.parameterTypes(i)
Case DataType.EBool
sw.Write(CType(IIf(v, 1, 0), Int32))
Case DataType.EFloat
sw.Write(CType(v, Single))
Case DataType.EInteger
sw.Write(CType(v, Int32))
Case DataType.EString
txtPointers.Add(sw.BaseStream.Position)
sw.Write(CType(getStrOff(v, stringsToAdd), Int32))
Case DataType.EVoid
sw.Write(CType(0, Int32))
End Select
sw.Write(CType(&H51, Byte))
Next
sw.Write(CType(&HE8, Byte))
sw.Write(CType(uFunc.id, Int32)) 'we dont know atm the positions of the functions so we replace them later with the id
sw.Write(CType(&H81, Byte))
sw.Write(CType(&HC4, Byte))
sw.Write(CType(uFunc.parameterTypes.Length * 4, Int32)) 'just incase of a 64bit cpu i use everywhere int32
End Sub
'Private Function createDataArea() As Byte()
' Dim txtPointers As New ArrayList
' Dim endingSize As Long = scriptSectionStopTag.Length + scriptSpaceMultiplier
' For Each f As SFunction In iFunctions
' endingSize += f.parameterCount * scriptSpaceMultiplier + 5 + scriptSectionStartTag.Length + scriptSectionStopTag.Length
' Next
' Dim lines As SScriptLine() = iScriptLines
' Array.Reverse(lines)
' Dim byteLines As New ArrayList
' Dim offset As Long = endingSize
' For lIndex As Long = 0 To lines.Length - 1
' Dim line As SScriptLine = lines(lIndex)
' Dim byteLine(line.parameters.Length * 6 + 11 - 1) As Byte
' Dim pos As Long = 0
' offset += byteLine.Length
' For Each p As SParamElem In line.parameters
' If p.type = DataType.EString Then
' p.value = getStrOff(p.value, stringsToAdd)
' End If
' byteLine(pos) = &HB9
' AddMath.SetUInt32inBytes(byteLine, p.value, pos + 1)
' If p.type = DataType.EString Then txtPointers.Add(offset - pos - 1)
' byteLine(pos + 5) = &H51
' pos += 6
' Next
' byteLine(pos) = &HE8
' AddMath.SetUInt32inBytes(byteLine, (offset - line.func.sumCode + 6), pos + 1) 'index 'magic 6 <- secret
' byteLine(pos + 5) = &H81
' byteLine(pos + 6) = &HC4
' AddMath.SetUInt32inBytes(byteLine, line.parameters.Length * 4, pos + 7) 'param count
' byteLines.Add(byteLine)
' Next
' byteLines.Reverse()
' offset += scriptSectionStartTag.Length + scriptSpaceMultiplier
' ' we know the right size now. Lets make the function indexes, thereafter sort and parameter list
' For i As Integer = 0 To iFunctions.Length - 1
' iFunctions(i).index = offset + (&HC + iFunctions(i).parameterCount * 6 - 1) - iFunctions(i).sumCode
' Next
' Array.Sort(iFunctions, New CFunctionSorter)
' 'txt pointers re'calculation
' Dim k As Long = 0
' ReDim pointers(txtPointers.Count - 1)
' For Each p As Long In txtPointers
' pointers(k) = offset - p
' k += 1
' Next
' Array.Sort(pointers)
' txtPointers = Nothing
' Dim out(offset - 1) As Byte
' offset = 0
' For i As Integer = 0 To scriptSpaceMultiplier
' out(i + offset) = scriptSectionSpaceTag
' Next
' offset += scriptSpaceMultiplier
' For i As Integer = 0 To scriptSectionStartTag.Length - 1
' out(i + offset) = scriptSectionStartTag(i)
' Next
' offset += scriptSectionStartTag.Length
' For lIndex As Long = 0 To byteLines.Count - 1 ' copy
' Dim lB As Byte() = byteLines(lIndex)
' For Each b As Byte In lB
' out(offset) = b
' offset += 1
' Next
' Next
' For i As Integer = 0 To scriptSectionStopTag.Length - 1
' out(i + offset) = scriptSectionStopTag(i)
' Next
' offset += scriptSectionStopTag.Length
' For i As Integer = 0 To scriptSpaceMultiplier ' area split
' out(i + offset) = scriptAreaSplitTag
' Next
' offset += scriptSpaceMultiplier
' For Each f As SFunction In iFunctions
' For i As Integer = 0 To scriptSectionStartTag.Length - 1
' out(i + offset) = scriptSectionStartTag(i)
' Next
' offset += scriptSectionStartTag.Length
' For i As Integer = 1 To 5 + f.parameterCount * scriptSpaceMultiplier
' out(offset) = scriptSectionSpaceTag
' offset += 1
' Next
' For i As Integer = 0 To scriptSectionStopTag.Length - 1
' out(i + offset) = scriptSectionStopTag(i)
' Next
' offset += scriptSectionStopTag.Length
' Next
' Return out
'End Function
Private Function createFunctionArea() As Byte()
Dim fS As New ArrayList
Dim offSet As Long = 0
Dim funcs(UBound(iFunctions)) As SFunction 'dont mess up the ByRef function list
Array.Copy(iFunctions, funcs, iFunctions.Length)
Array.Sort(funcs, New CFunctionSorterByName)
For fId As Integer = 1 To funcs.Length - 1 'skip first cose its the main function which will not be in the declaration area
Dim f As SFunction = funcs(fId)
Dim line(f.name.Length + 1 + 2 * 4 - 1) As Byte
Dim lOff As Long = 0
For Each c As Char In f.name
line(lOff) = Asc(c)
lOff += 1
Next
line(lOff) = &HA
Dim paraListH(f.parameterTypes.Length - 1) As String
Dim i As Integer = 0
For Each p As DataType In f.parameterTypes
paraListH(i) = CType(CType(p, Integer), String)
i += 1
Next
Dim par As UInt32 = 0
If paraListH.Length > 0 Then
Array.Reverse(paraListH)
par = Convert.ToUInt32(String.Join("", paraListH), 16)
End If
If f.returnType > 0 Then par += CType(f.returnType, Integer) * &H10000000
AddMath.SetUInt32inBytes(line, par, lOff + 1)
lOff += 5
AddMath.SetUInt32inBytes(line, f.index, lOff)
lOff += 4
offSet += lOff
fS.Add(line)
Next
Dim out(offSet + 4 + 16 - 1) As Byte
AddMath.SetUInt32inBytes(out, funcs.Length - 1, 0) 'main function will not be in here
offSet = 4
For Each l As Byte() In fS
For Each b As Byte In l
out(offSet) = b
offSet += 1
Next
Next
Dim ending As Byte() = {&H4, &H0, &H0, &H0, &H10, &H0, &H0, &H0, &H14, &H0, &H0, &H0, &H18, &H0, &H0, &H0}
For Each e As Byte In ending
out(offSet) = e
offSet += 1
Next
Return out
End Function
Private Function getStrOff(ByVal str As String, ByRef OffStrArr As SOffStr()) As Long
For Each pr As SOffStr In OffStrArr
If pr.str = str Then
Return pr.off
End If
Next
Return -1
End Function
End Class
Public Class AddMath
Private Shared badChars As String() = {vbNewLine, vbCr, vbLf}
Public Shared Function TrimCrLf(ByVal txt As String) As String
For Each t As String In badChars
txt.Replace(t, "")
Next
Return Trim(txt)
End Function
Public Shared Function ObjArrToStr(ByRef objA As Object()) As String()
Dim o(objA.Length - 1) As String
Dim i As Integer = 0
For Each ob As Object In objA
o(i) = ob.ToString
i += 1
Next
Return o
End Function
Public Shared Function resolveDataType(ByVal type As String) As Type
If Left(type, 5) = "char[" Then Return GetType(Char())
Select Case type
Case "byte" : Return GetType(Byte)
Case "i16" : Return GetType(Int16)
Case "ui16" : Return GetType(UInt16)
Case "i32" : Return GetType(Int32)
Case "ui32" : Return GetType(UInt32)
Case "char" : Return GetType(Char)
Case "float" : Return GetType(Single)
Case Else
Throw New Exception("Unsupported data type")
End Select
End Function
Public Shared Function resolveDataTypeLen(ByVal type As String) As Integer
If Left(type, 5) = "char[" Then Return resolveInteger(type.Substring(5, type.Length - 6))
Select Case type
Case "byte" : Return 1
Case "i16" : Return 2
Case "ui16" : Return 2
Case "i32" : Return 4
Case "ui32" : Return 4
Case "char" : Return 1
Case "float" : Return 4
Case Else
Throw New Exception("Unsupported data type")
End Select
End Function
Public Shared Function resolveInteger(ByVal num As String) As Integer
If num.Length > 2 AndAlso num.Substring(0, 2) = "0x" Then
Return Integer.Parse(num.Substring(2), Globalization.NumberStyles.HexNumber)
ElseIf num = "" Then
Return 0
Else
Return Integer.Parse(num)
End If
End Function
Public Shared Function getUInt32(ByVal pos As Long, ByRef arr As Byte()) As UInt32
Dim out As UInt32
For i As Integer = 3 To 0 Step -1
Dim t As Byte = arr(i + pos)
out += t * Math.Pow(&H100, i)
Next
Return out
End Function
Public Shared Function UInt32toBytes(ByVal val As UInt32) As Byte()
Dim out(3) As Byte
Dim str As String = Hex(val)
Dim firstB As String = ""
If CMcfCoder.ModulusFromDivination(str.Length, 2) > 0 Then
firstB = str.Substring(0, 1)
str = str.Substring(1)
End If
Dim poss As Integer = str.Length - 2
Dim ks As Integer = 0
Do While poss >= 0
Dim k As String = ""
k = str.Substring(poss, 2)
Dim b As Byte = Convert.ToByte(k, 16)
out(ks) = b
ks += 1
poss -= 2
Loop
If firstB <> "" Then out(ks) = Convert.ToByte(firstB, 16)
Return out
End Function
Public Shared Sub SetUInt32inBytes(ByRef data As Byte(), ByVal val As UInt32, ByVal pos As Long)
Dim str As String = Hex(val)
Dim firstB As String = ""
If CMcfCoder.ModulusFromDivination(str.Length, 2) > 0 Then
firstB = str.Substring(0, 1)
str = str.Substring(1)
End If
Dim poss As Integer = str.Length - 2
Dim ks As Integer = 0
Do While poss >= 0
Dim k As String = ""
k = str.Substring(poss, 2)
Dim b As Byte = Convert.ToByte(k, 16)
data(ks + pos) = b
ks += 1
poss -= 2
Loop
If firstB <> "" Then
data(ks + pos) = Convert.ToByte(firstB, 16)
ks += 1
End If
If ks < 4 Then
For i As Integer = ks To 3
data(pos + ks) = &H0
Next
End If
End Sub
Public Shared Sub SetInt32inBytes(ByRef data As Byte(), ByVal val As Int32, ByVal pos As Long)
Dim str As String = Hex(val)
Dim firstB As String = ""
If CMcfCoder.ModulusFromDivination(str.Length, 2) > 0 Then
firstB = str.Substring(0, 1)
str = str.Substring(1)
End If
Dim poss As Integer = str.Length - 2
Dim ks As Integer = 0
Do While poss >= 0
Dim k As String = ""
k = str.Substring(poss, 2)
Dim b As Byte = Convert.ToByte(k, 16)
data(ks + pos) = b
ks += 1
poss -= 2
Loop
If firstB <> "" Then
data(ks + pos) = Convert.ToByte(firstB, 16)
ks += 1
End If
If ks < 4 Then
For i As Integer = ks To 3
data(pos + ks) = &H0
Next
End If
End Sub
Public Shared Sub addBytesToEnd(ByRef toWhere As Byte(), ByRef whatToAdd As Byte())
ReDim Preserve toWhere(UBound(toWhere) + whatToAdd.Length)
Dim k As Integer = 0
For i As Long = toWhere.Length - whatToAdd.Length To toWhere.Length - 1
toWhere(i) = whatToAdd(k)
k += 1
Next
End Sub
Public Shared Sub debugByteArr(ByRef arr As Byte())
Dim i As Integer = 0
Dim col As Integer = 0
Debug.WriteLine("--- Start of dump ---")
For Each bb As Byte In arr
Debug.Write(Hex2(bb) & " ")
If i = 3 Then Debug.Write(" ")
i += 1
If i > 3 Then
i = 0
col += 1
End If
If col > 4 Then
col = 0
Debug.WriteLine("")
End If
Next
Debug.WriteLine("")
Debug.WriteLine("--- End of dump ---")
End Sub
Public Shared Function Hex2(ByVal nr As Long) As String
Dim o As String = "" & Hex(nr).ToUpper
If o.Length < 2 Then o = "0" & o
Return o
End Function
Public Shared Function position(ByRef data As Byte(), ByRef searchFor As Byte(), Optional ByVal startFrom As Long = 0, Optional ByVal numberOfMaxresults As Integer = 0, Optional ByVal Length As Long = 0) As Long()
Dim poses As Long() = {}
For index As Long = startFrom To IIf(Length > 0, startFrom + Length, data.Length - 1)
If data.Length - index >= searchFor.Length Then
Dim arr As Byte() = {}
For i As Integer = 0 To searchFor.Length - 1
ReDim Preserve arr(i)
arr(i) = data(index + i)
Next
If compareArr(arr, searchFor) Then
ReDim Preserve poses(UBound(poses) + 1)
poses(UBound(poses)) = index
If numberOfMaxresults > 0 AndAlso poses.Length = numberOfMaxresults Then Exit For
End If
Else
Exit For
End If
Next
Return poses
End Function
Public Shared Function compareArr(ByRef d1 As Byte(), ByRef d2 As Byte()) As Boolean
For i As Integer = 0 To d1.Length - 1
If UBound(d2) < i OrElse d1(i) <> d2(i) Then Return False
Next
Return True
End Function
Public Shared Function MultiplyBytes(ByVal data As Byte, ByVal multiplier As Integer) As Byte()
Dim out(multiplier - 1) As Byte
For i As Integer = 0 To multiplier - 1
out(i) = data
Next
Return out
End Function
Public Shared Function SingleToDec(ByVal pos As Single)
Return getUInt32(0, BitConverter.GetBytes(pos))
End Function
Public Shared Function DecToSingle(ByVal dec As Long)
Return BitConverter.ToSingle(UInt32toBytes(dec), 0)
End Function
Public Shared Function IntArr2StrArr(ByRef iArr As Integer()) As String()
Dim out As New ArrayList
For Each i As Integer In iArr
out.Add(i.ToString)
Next
Return out.ToArray(GetType(String))
End Function
Public Class Array
Public Shared Function IndexOfArray(ByRef searchIn As Integer()(), ByRef searchFor As Integer()) As Integer
Dim ind As Integer = 0
For Each ob() As Integer In searchIn
Dim found As Boolean = True
If searchFor.Length <> ob.Length Then found = False
If found Then
For k As Integer = 0 To ob.Length - 1
If ob(k) <> searchFor(k) Then
found = False
Exit For
End If
Next
End If
If found Then Return ind
ind += 1
Next
Return -1
End Function
End Class
Public Shared Function resizeImage(ByRef img As Bitmap, ByVal sX As Integer, ByVal sY As Integer, ByVal dW As Integer, ByVal dH As Integer, Optional ByVal zoomMultiplier As Single = 1) As Bitmap
Dim recOrg As New Rectangle(sX, sY, Math.Round(dW / zoomMultiplier), Math.Round(dH / zoomMultiplier))
Dim bmpOut As New Bitmap(dW, dH, img.PixelFormat)
Dim grpOut As Graphics = Graphics.FromImage(bmpOut)
Dim recDes As New Rectangle(0, 0, dW, dH)
grpOut.DrawImage(img, recDes, recOrg, GraphicsUnit.Pixel)
Return bmpOut
End Function
Public Shared Function getRylFolder() As String
Try
Dim key As Microsoft.Win32.RegistryKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall", False)
Dim str3 As String
For Each str3 In key.GetSubKeyNames
Dim key2 As Microsoft.Win32.RegistryKey = key.OpenSubKey(str3, False)
Dim str2 As String = ""
Try
str2 = key2.GetValue("DisplayName", "").ToString
Catch exception1 As Exception
End Try
If ((str2.IndexOf("RYL") <> -1) OrElse (str2.IndexOf("R.Y.L") <> -1)) Then
Try
Dim str4 As String = key2.GetValue("InstallLocation", "").ToString
If ((str4.Length <= 1) OrElse ((Convert.ToString(str4.Chars((str4.Length - 1))) <> "/") AndAlso (Convert.ToString(str4.Chars((str4.Length - 1))) <> "\"))) Then
Return str4
End If
Return str4.Substring(0, (str4.Length - 1))
Catch exception4 As Exception
End Try
End If
Next
Catch exception5 As Exception
End Try
Return ""
End Function
Public Shared Sub setRylFolder(ByVal folder As String)
Dim key As Microsoft.Win32.RegistryKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall", False)
Dim str3 As String
For Each str3 In key.GetSubKeyNames
Dim key2 As Microsoft.Win32.RegistryKey = key.OpenSubKey(str3, False)
Dim str2 As String = ""
Try
str2 = key2.GetValue("DisplayName", "").ToString
Catch exception1 As Exception
End Try
If ((str2.IndexOf("RYL") <> -1) OrElse (str2.IndexOf("R.Y.L") <> -1)) Then
Dim key3 As Microsoft.Win32.RegistryKey = key.OpenSubKey(str3, True)
key3.SetValue("InstallLocation", folder)
Exit Sub
End If
Next
key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall", True)
Dim nKey As Microsoft.Win32.RegistryKey = key.CreateSubKey("R.Y.L")
nKey.SetValue("DisplayName", "R.Y.L")
nKey.SetValue("InstallLocation", folder)
End Sub
Public Enum FileType
GsfFile
McfFile
SkeyGcmdsFile
Unknown
End Enum
Public Shared Function fileTypeFromName(ByVal file As String) As FileType
Dim ext As String = IO.Path.GetExtension(file).ToLower()
Select Case ext
Case ".gsf" : Return FileType.GsfFile
Case ".mcf" : Return FileType.McfFile
Case ".skey" : Return FileType.SkeyGcmdsFile
Case ".gcmds" : Return FileType.SkeyGcmdsFile
Case Else : Return FileType.Unknown
End Select
End Function
Public Shared Sub sharedDataOverWrite(ByVal file As String)
Dim lines As String() = {}
If Not IO.File.Exists(file) Then Return
Try
lines = IO.File.ReadAllLines(file)
Catch ex As Exception
Return
End Try
For Each line As String In lines
Try
line = line.Trim()
If line <> String.Empty AndAlso Not line.StartsWith("//") Then
Dim splice1 As String() = line.Split("=")
Dim splice2 As String() = splice1(0).Trim().Split(".")
Dim type As String = splice2(0)
Dim fileType As String = splice2(1)
Dim index As Integer = 0
If UBound(splice2) > 1 Then index = splice2(2)
Dim data As String = splice1(1).Trim()
Select Case fileType
Case "mcf"
If type = "xor" Then
CMcfCoder.xorKey = parseByteArray(data)
End If
Case "gcmds"
If type = "xor" Then
CGcmdsCoder.key = parseByteArray(data)
End If
Case "gsf"
If type = "xor" Then
CGsfCoder.xorDat(index) = data
ElseIf type = "off" Then
CGsfCoder.typeCodes(index) = data
End If
Case "global"
If type = "usageNotice" Then
If Not data = "1" AndAlso Not data = "0" Then Throw New ArgumentException("Value can be 1 or 0")
frmNpcEdit.enableServerNotice = (data = "1")
ElseIf type = "syntaxHighlight" Then
If Not data = "1" AndAlso Not data = "0" Then Throw New ArgumentException("Value can be 1 or 0")
frmNpcEdit.syntaxHighlightEnabled = (data = "1")
End If
End Select
End If
Catch ex As Exception
Dim sw As IO.StreamWriter = IO.File.AppendText(file)
sw.WriteLine("//" & Date.Now.ToString())
sw.WriteLine("//" & vbTab & "Line: " & line)
sw.WriteLine("//" & vbTab & "Exception: " & ex.Message)
sw.WriteLine("//" & vbTab & "Source: " & ex.StackTrace.Replace(vbNewLine, vbNewLine & "//" & vbTab & vbTab))
sw.Flush()
sw.Close()
End Try
Next
End Sub
Public Shared Function parseByteArray(ByVal line As String) As Byte()
Dim xorStr As String = line
Dim slices As String() = xorStr.Trim.Split(" ")
Dim out(slices.Length - 1) As Byte
For i As Integer = 0 To slices.Length - 1
If slices(i).Trim <> "" Then out(i) = Byte.Parse(slices(i), Globalization.NumberStyles.HexNumber)
Next
Return out
End Function
End Class
Public Class CGcmdsCoder
#Region "Data"
Friend Shared key As Byte() = {&H5A, &H5F, &H61, &H6C, &H6C, &H5F, &H41, &H5F, &H33, &H44}
#End Region
Public Shared Function Decode(ByRef data As Byte()) As String
Dim kPos As Integer = 0
Dim mStr(data.Length - 1) As Char
For i As Integer = 0 To data.Length - 1
If kPos > key.Length - 1 Then kPos = 0
mStr(i) = Chr(data(i) Xor key(kPos))
kPos += 1
Next
Dim txt As New String(mStr, 0, mStr.Length)
Dim header As String = "" & _
"///////////////////////////////////////////////////////" & vbNewLine & _
"//" & vbNewLine & _
"// Gcmds & skey structure ver. 1.0" & vbNewLine & _
"//" & vbNewLine & _
"// Created by rylCoder " & Application.ProductVersion.Substring(0, Application.ProductVersion.Length - 2) & " <20> 2006 & 2007 AlphA" & vbNewLine & _
"//" & vbNewLine & _
"///////////////////////////////////////////////////////" & vbNewLine & vbNewLine
Return header & txt
End Function
Public Shared Function Encode(ByRef lines As String()) As Byte()
Dim kPos As Integer = 0
Dim str As String = ""
For Each l As String In lines
If l.Length < 2 OrElse l.Substring(0, 2) <> "//" Then
str &= l & vbNewLine
End If
Next
If str.Length > vbNewLine.Length Then str = str.Substring(0, str.Length - vbNewLine.Length)
Dim data(str.Length - 1) As Byte
For i As Integer = 0 To data.Length - 1
If kPos > key.Length - 1 Then kPos = 0
data(i) = Asc(str(i)) Xor key(kPos)
kPos += 1
Next
Return data
End Function
End Class
Public Class Asm
<System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.Demand, Name:="FullTrust")> _
Public Shared Function Run(ByVal resource As String, ByVal clas As String, ByVal func As String, ByVal args As Object()) As Object
Dim a As Assembly = Assembly.Load(CType(New System.Resources.ResourceManager("rylCoder.Resources", Assembly.GetExecutingAssembly()).GetObject(resource), Byte()))
Dim t As Type = a.GetType(clas)
Dim clas2 As Object = Activator.CreateInstance(t)
Return t.InvokeMember(func, BindingFlags.Default Or BindingFlags.InvokeMethod, Nothing, clas2, args)
End Function
End Class