Imports WindowsApplication1.Form1
Imports WindowsApplication1.NJCM
Imports WindowsApplication1.VectorMath
Imports System.IO
Imports WindowsApplication1.Utility
Imports WindowsApplication1.PRS

Imports dword = System.UInt32
Imports float = System.Single
Imports word = System.UInt16

Module BMLExploder
    Function PadCheck(ByVal Q As UInt32) As UInt32
        Return Q + ((&H20 - (Q Mod &H20)) Mod &H20)
    End Function
    Function PaddingCheck(ByVal Q As UInt32) As UInt32
        'Checks to see if padding to an even &h20 boundary is necessary
        Dim t As UInt32 = Q
        If t <> (t And &HFFFFFFE0) Then
            t = (t And &HFFFFFFE0) + &H20
        End If
        Return t
    End Function
    Function BMLExplode(ByVal InFile As String, ByVal OutDir As String) As Boolean
        ' Wherein we attempt to use Syphos and Deathrabbit's Code to read and explode a BML file.
        WriteLn("BML Exploder, based on code by Syphos and Deathrabbit.")
        WriteLn("Starting...")
        If InFile = "" Then WriteLn("No Input File!") : Return False
        If OutDir = "" Then WriteLn("No Output Directory!") : Return False
        Dim ws As New NJCM.IO.ExBinaryReader(FileToBuffer(InFile))
        Dim NumEntries As UInt32 = 0
        Dim txfname As String = ""
        Dim idx As Integer = 0
        Dim tfn As String = ""
        Dim tos As String = ""
        Dim tos2 As String = ""
        Dim q As Integer = 0
        With ws
            .Seek(&H4, SeekOrigin.Begin)
            NumEntries = .ReadDword
            Dim BMLDir(NumEntries) As Types.BMLEntry
            Dim t As New Types.BMLEntry
            Dim I As UInteger = NumEntries
            .Seek(&H40, SeekOrigin.Begin)
            Do
                tos = ""
                tos2 = ""
                q = NumEntries - I
                BMLDir(q) = .ReadBMLEntry
                With BMLDir(q)
                    tos = .Filename & "(" & HexOut(.CompLen) & ", " & HexOut(.RawLen) & ")"
                    If .RAWPVMLen > 0 And .CompPVMLen > 0 Then tos2 = .Filename & ".pvm (" & HexOut(.CompLen) & ", " & HexOut(.RawLen) & ")"
                End With
                WriteLn("File : " & tos)
                If tos2 <> "" Then WriteLn("File : " & tos2)
                I -= 1
            Loop Until I = 0
            Dim DSP As UInt32 = ((&H40 * (NumEntries + 1)) And &HFFFFF800) + &H800
            Dim crp As UInt32 = 0
            Dim outbuf() As Byte
            I = NumEntries

            Do
                idx = NumEntries - I
                .Seek(DSP + crp, SeekOrigin.Begin)
                outbuf = New Byte(BMLDir(idx).RawLen) {}
                q = PRS.decompress(.ReadBytes(BMLDir(idx).CompLen), outbuf)
                tfn = OutDir & "\" & BMLDir(idx).Filename
                WriteLn("Writing " & tfn)
                BufferToFile(PRS.getdestbuffer(q), tfn)
                crp += BMLDir(idx).CompLen
                crp = PaddingCheck(crp)
                outbuf = Nothing

                .Seek(DSP + crp, SeekOrigin.Begin)

                If BMLDir(idx).RAWPVMLen > 0 And BMLDir(idx).CompPVMLen > 0 Then
                    outbuf = New Byte(BMLDir(idx).RAWPVMLen) {}
                    q = PRS.decompress(.ReadBytes(BMLDir(idx).CompPVMLen), outbuf)
                    tfn = OutDir & "\" & BMLDir(idx).Filename & ".pvm"
                    WriteLn("Writing " & tfn)
                    BufferToFile(PRS.getdestbuffer(q), tfn)
                    crp += BMLDir(idx).CompPVMLen
                    crp = PaddingCheck(crp)
                    outbuf = Nothing
                End If
                I -= 1
            Loop Until I = 0

            .Close()
        End With
        WriteLn("...Done!")
        Return True
    End Function
    Function BMLExplode2(ByVal Buf() As Byte, ByVal OutDir As String)
        Dim ws As New NJCM.IO.ExBinaryReader(Buf)
        Dim NumEntries As UInt32 = 0
        Dim txfname As String = ""
        Dim idx As Integer = 0
        Dim tfn As String = ""
        Dim tos As String = ""
        Dim tos2 As String = ""
        Dim q As Integer = 0
        With ws
            .Seek(&H4, SeekOrigin.Begin)
            NumEntries = .ReadDword
            Dim BMLDir(NumEntries) As Types.BMLEntry
            Dim t As New Types.BMLEntry
            Dim I As UInteger = NumEntries
            .Seek(&H40, SeekOrigin.Begin)
            Do
                tos = "     "
                tos2 = "     "
                q = NumEntries - I
                BMLDir(q) = .ReadBMLEntry
                With BMLDir(q)
                    tos = .Filename & "(" & HexOut(.CompLen) & ", " & HexOut(.RawLen) & ")"
                    If .RAWPVMLen > 0 And .CompPVMLen > 0 Then tos2 = .Filename & ".pvm (" & HexOut(.CompLen) & ", " & HexOut(.RawLen) & ")"
                End With
                WriteLn("     File : " & tos)
                If tos2 <> "" Then WriteLn("     File : " & tos2)
                I -= 1
            Loop Until I = 0
            Dim DSP As UInt32 = ((&H40 * (NumEntries + 1)) And &HFFFFF800) + &H800
            Dim crp As UInt32 = 0
            Dim outbuf() As Byte
            I = NumEntries

            Do
                idx = NumEntries - I
                .Seek(DSP + crp, SeekOrigin.Begin)
                outbuf = New Byte(BMLDir(idx).RawLen) {}
                q = PRS.decompress(.ReadBytes(BMLDir(idx).CompLen), outbuf)
                tfn = OutDir & "\" & BMLDir(idx).Filename
                WriteLn("     Writing " & tfn)
                BufferToFile(PRS.getdestbuffer(q), tfn)
                crp += BMLDir(idx).CompLen
                crp = PaddingCheck(crp)
                outbuf = Nothing

                .Seek(DSP + crp, SeekOrigin.Begin)

                If BMLDir(idx).RAWPVMLen > 0 And BMLDir(idx).CompPVMLen > 0 Then
                    outbuf = New Byte(BMLDir(idx).RAWPVMLen) {}
                    q = PRS.decompress(.ReadBytes(BMLDir(idx).CompPVMLen), outbuf)
                    tfn = OutDir & "\" & BMLDir(idx).Filename & ".pvm"
                    WriteLn("     Writing " & tfn)
                    BufferToFile(PRS.getdestbuffer(q), tfn)
                    crp += BMLDir(idx).CompPVMLen
                    crp = PaddingCheck(crp)
                    outbuf = Nothing
                End If
                I -= 1
            Loop Until I = 0

            .Close()
        End With
        WriteLn("...Done!")
        Return True
    End Function
End Module

Module GSLExploder
    Function GetRealOfs(ByVal a As dword, ByVal b As dword) As dword
        Return ((a >> b) + 1) << b
    End Function

    Function GSLExplode(ByVal Infile As String, ByVal OutDir As String) as Boolean
        WriteLn("Starting...")
        If Infile = "" Then WriteLn("No Input File!") : Return False
        If OutDir = "" Then WriteLn("No Output Directory!") : Return False
        Dim ws As New NJCM.IO.ExBinaryReader(FileToBuffer(Infile))
        Dim ne As New Types.GSLEntry("hah!", 0, 0, 0, 0)
        Dim ro As dword = 0
        Dim so As dword = 0
        Dim co As dword = 0
        Dim no As dword = 0
        Dim q1 As New List(Of Types.GSLEntry)

        ws.Seek(0, SeekOrigin.Begin)
        ne = ws.ReadGSLEntry

        Do While ne.FileName <> ""
            WriteLn(HexOut(GetRealOfs(ne.FileLen, 11)) & " " & HexOut(no) & "     " & ne.FileName)
            q1.Add(ne.Clone)
            no += ne.FileLen
            no += (&H800 - (ne.FileLen And &H7FF)) And &H7FF
            ne = ws.ReadGSLEntry
        Loop
        WriteLn(q1.Count.ToString & " Entries in GSL file.")

        so = GetRealOfs(q1.Count * &H30, 15)
        WriteLn("Starting Offset = " & HexOut(so))

        StepControl()

        co = so
        For I As Integer = 0 To q1.Count - 1
            Dim outfile As String = OutDir & "\" & q1(I).FileName
            WriteLn("Reading : " & HexOut(co) & "     Writing : " & q1(I).FileName & ", " & HexOut(q1(I).FileLen) & " bytes.")
            ws.Seek(co, SeekOrigin.Begin)
            Dim tmpbuf() As Byte = ws.ReadBytes(q1(I).FileLen)
            Dim ts As String = ""
            BufferToFile(tmpbuf, outfile)
            co += q1(I).FileLen
            co += ((q1(I).FileLen - 1) And &H7FF) Xor &H7FF
            'co += (&H800 - (q1(I).FileLen And &H7FF)) And &H7FF
        Next
        ws.Close()
        Return True
    End Function
End Module