Ultima: Exodus - Dialogue Dumper

From NES Hacker Wiki
Jump to: navigation, search

This is a FreeBASIC program that will extract and decode all of the 6-bit encoded dialogue from Ultima: Exodus and save it to a file. This program was written by User:TheAlmightyGuru.

Source

' Change these paths to the location of you uncompressed ROM, and where you want the dialogue dump to be saved.
Open "C:\Ultima - Exodus (USA).nes" For Binary As #1
Open "C:\Ultima - Exodus Dialogue Dump.txt" For Binary As #2

Dim As Integer X, BlockNo, ROMOffset, Backup, TextNo, DialogueCount
Dim As UByte Buffer(0 To 2)
Dim As UByte TextOffset(0 To 3)
Dim As String BinaryData, OutputText, Dialogue(0 To 3)

For BlockNo = 1 To 2
    ' The game's dialogue is broken into two sections.
    If BlockNo = 1 Then
		ROMOffset = &H14210
		DialogueCount = 238
    Else
		ROMOffset = &H15F5C
		DialogueCount = 229
    End If
        
	For TextNo = 1 To DialogueCount
		Put #2, , "--= &" + Hex(ROMOffset, 5) + " =--" + Chr(13) + Chr(10)
		
		' Get to the start of the dialog.
		Get #1, ROMOffset + 1, X, 0

		Backup = 0
		Do
			' Load the 3 encoded bytes and convert it to a binary string.
			BinaryData = ""
			For X = 0 To 2
				Get #1, , Buffer(X)
				BinaryData = BinaryData + Bin(Buffer(X), 8)
			Next X
			ROMOffset = ROMOffset + 3
			
			' Convert the binary string into 4 offsets.
			For X = 0 To 3
				TextOffset(X) = CByte("&B00" + Mid(BinaryData, 1 + (X * 6), 6))
			Next X

			' Convert the offsets to their ASCII equivalent.
			For X = 0 To 3
				Select Case TextOffset(X)
				Case 0 To 25
					' Letters
					Dialogue(X) = Chr(TextOffset(X) + 65)
				Case 26
					Dialogue(X) = "!"
				Case 27
					Dialogue(X) = "?"
				Case 28
					Dialogue(X) = "."
				Case 29
					Dialogue(X) = ","
				Case 31
					Dialogue(X) = Chr(34) ' Quotation mark
				Case 32 To 42
					' Numbers
					Dialogue(X) = Chr(TextOffset(X) + 16)
				Case 43
					Dialogue(X) = "-"
				Case 44
					Dialogue(X) = "'"
				Case 45
					Dialogue(X) = " "
				Case 46
					Dialogue(X) = ":"
				Case 48
					Dialogue(X) = "(name) "
				Case 49
					Dialogue(X) = "(monster) "
				Case 50
					Dialogue(X) = "(amount) "
				Case 52
					Dialogue(X) = "(1st dialogue only)" + Chr(13) + Chr(10)
				Case 53
					Dialogue(X) = "(y/n)"
				Case 56
					Dialogue(X) = "(acquire pray command)" + Chr(13) + Chr(10)
				Case 57
					Dialogue(X) = "(acquire bribe command)" + Chr(13) + Chr(10)
				Case 62		' Line Break
					Dialogue(X) = Chr(17)
				Case 63		' End of Dialogue
					Dialogue(X) = Chr(31)
					If X = 0 Then Backup = 2
					If X = 1 Then Backup = 1
				Case Else	' Unknown
					Dialogue(X) = "[" + Str(TextOffset(X)) + "]"
				End Select
			Next X

			' Write the ASCII data to the file.
			For X = 0 To 3
				Select Case ASC(Dialogue(X))
				Case 17		' Line Break
					Put #2,, Chr(13) + Chr(10)
				Case 31		' End of Dialogue
					Put #2,, Chr(13) + Chr(10) + Chr(13) + Chr(10)
					
					' Leave the loop.
					Exit Do
				Case Else
					Put #2,, Dialogue(X)
				End Select
			Next X
		Loop

		' Backup to use the characters after the end of dialogue marker.
		ROMOffset = ROMOffset - Backup
	Next TextNo
Next BlockNo

Close #1
Close #2