' LOLRIP.BAS - Rips SEQ/VAB stuff from legend of legaia "prot.dat" and puts
' it into many PSX-EXE files for conversion into psf.

' Note that in qbasic file offsets are 1 based - this means the first byte in
' a file is offset 1. This is contrary to C file offsets which are 0 based.
' That's why the offsets may look off by 1

' Locations in output file to load stuff into
' The commented ones are the pre-psflib values
'CONST filevabptr = 1116161
'CONST fileseqptr = 985089
'CONST filevboffset = 985085
CONST filevabptr = 135169
CONST fileseqptr = 4097
CONST filevboffset = 4093
' Note: The difference between filevabptr and fileseqptr must be more than
' 2048 bytes

CLS

DIM dword AS STRING * 4, word AS STRING * 2, byte AS STRING * 1
DIM buffer AS STRING * 2048
DIM buffer2 AS STRING * 256
DIM filenumber AS LONG, fileoffset AS LONG
DIM leftover AS LONG
DIM vhlen AS LONG, vblen AS LONG, seqlen AS LONG, templen AS LONG
DIM vhptr AS LONG, vbptr AS LONG, seqptr AS LONG
DIM musicnumber AS LONG
DIM filename AS STRING
DIM datatype AS STRING * 1
DIM x AS INTEGER

' substitute "m" for your cd drive
OPEN "m:\prot.dat" FOR BINARY AS #1

' template.exe is simply any PSX-EXE with the legend of legaia music driver
' code. See constants filevabptr, fileseqptr and filevboffset for the
' locations data is loaded into.

FOR musicnumber = 0 TO 77
filenumber = 990 + musicnumber

  filename = LTRIM$(STR$(musicnumber))
  filename = STRING$(3 - LEN(filename), "0") + filename
  SHELL "copy c:\lol\template.exe c:\lol\" + filename + ".exe /Y > nul"
  OPEN "c:\lol\" + filename + ".exe" FOR BINARY AS #2

  ' The highest byte of "length" fields seems to be a "type" thing, so that's
  ' why it is ignored.

  PRINT "File number: 0x"; HEX$(filenumber)

  ' Get file record
  filenumber = (filenumber + 2) * 4 + 1
  GET #1, filenumber, dword
  fileoffset = CVL(dword) * &H800 + 1
  PRINT "Offset of file: 0x"; HEX$(fileoffset)

  ' Types are:
  ' 0 = VAB header
  ' 1 = VAB body
  ' 2 = SEQ data
  ' 3 = ??? (068 uses this)
  FOR x = 1 TO 3
    GET #1, fileoffset, dword
    datatype = RIGHT$(dword, 1)
    templen = CVL(LEFT$(dword, 3) + CHR$(0))
    SELECT CASE datatype
    CASE CHR$(0)
      vhlen = templen
      vhptr = fileoffset
      PRINT "VH length: 0x"; HEX$(vhlen)
    CASE CHR$(1)
      vblen = templen
      vbptr = fileoffset
      PRINT "VB length: 0x"; HEX$(vblen)
    CASE CHR$(2)
      seqlen = templen
      seqptr = fileoffset
      PRINT "SEQ length: 0x"; HEX$(seqlen)
    END SELECT
    fileoffset = fileoffset + 4 + templen
  NEXT x

  ' Patch VB offset
  word = MKI$(vhlen + 4) ' The +4 is to accommodate the "length/type" record
  PUT #2, filevboffset, word

  ' Copy VAB header
  FOR fileoffset = 0 TO (vhlen \ 256) + 1 ' just to be sure
    GET #1, vhptr + fileoffset * 256 + 4, buffer2
    PUT #2, filevabptr + fileoffset * 256, buffer2
  NEXT fileoffset

  ' Copy VAB body
  PRINT HEX$(filevabptr), HEX$(filevabptr + vhlen)
  FOR fileoffset = 0 TO (vblen \ 2048) + 1 ' just to be sure
    GET #1, vbptr + fileoffset * 2048 + 4, buffer
    PUT #2, filevabptr + fileoffset * 2048 + vhlen + 4, buffer
  NEXT fileoffset

  ' Copy SEQ data
  FOR fileoffset = 0 TO (seqlen \ 256) + 1 ' just to be sure
    GET #1, seqptr + fileoffset * 256 + 4, buffer2
    PUT #2, fileseqptr + fileoffset * 256, buffer2
  NEXT fileoffset

  ' Close file
  CLOSE #2
  PRINT

NEXT musicnumber

CLOSE #1

