Public Class Main #Region " Declarations " Private Const _WRONG_NUM_ARGUMENTS As Integer = 1 Private Const _UNKNOWN_EXCEPTION As Integer = 2 Private Const _BLANK_SPACE_NOT_FOUND As Integer = 3 Private Const _PATTERN_NOT_FOUND As Integer = 4 Private Const _REQUIRED_ARGUMENTS As Integer = 4 Private Const _PAGE_SIZE As Integer = 16384 Private Const _IMAGE_SIZE As Integer = &H20 * _PAGE_SIZE Private Const _PAGE_0_BLOCK As Integer = 8 Private Const _JUMP_TABLE_BLOCK As Integer = 213 #End Region #Region " Public Methods " Public Shared Sub Main(ByVal args() As String) 'Validate correct number of arguments If args.Length <> _REQUIRED_ARGUMENTS Then _DisplayUsage(_WRONG_NUM_ARGUMENTS, "Invalid number of arguments!") Exit Sub End If Try Dim imageFile As New IO.FileStream(args(0), IO.FileMode.Open, IO.FileAccess.Read) Dim imageData(_IMAGE_SIZE - 1) As Byte Dim pages() As Integer = {&H1D, &H1C, &H1B, &H1A, &H19, &H18, 7, 6, 5, 4, 3, 2, 1, 0} Dim pattern() As Byte = {&HCB, &HBC, &H3E} Dim info As New IO.FileInfo(args(1)) Dim page0Address As Integer Dim patchProgramAddress As Integer Dim jumpTableAddress As Integer Dim BCALLPatchAddress As Integer 'Read in all the image data imageFile.Read(imageData, 0, _IMAGE_SIZE) imageFile.Close() 'Find blank space on page 0 page0Address = _FindBlankSpace(imageData, New Integer() {0}, _PAGE_0_BLOCK) 'Find blank space for patch program patchProgramAddress = _FindBlankSpace(imageData, pages, Convert.ToInt32(info.Length)) 'Don't let further searches find the page we just found Dim page As Integer Dim address As Integer = patchProgramAddress While address >= _PAGE_SIZE address -= _PAGE_SIZE page += 1 End While For i As Integer = 0 To pages.Length - 1 If pages(i) = page Then pages(i) = &HFF Next 'Find blank space for new BCALL jump table jumpTableAddress = _FindBlankSpace(imageData, pages, _JUMP_TABLE_BLOCK) 'Find location of BCALL routine patch Dim loc As Integer = BitConverter.ToInt16(imageData, &H29) BCALLPatchAddress = _FindPattern(imageData, loc, _PAGE_SIZE - loc, pattern) 'Write everything out to XML file Dim xmlFile As New Xml.XmlTextWriter(args(2), System.Text.Encoding.ASCII) xmlFile.Formatting = Xml.Formatting.Indented xmlFile.WriteStartDocument(True) xmlFile.WriteStartElement("PatchInfo") xmlFile.WriteStartElement("Page0Address") xmlFile.WriteString(page0Address.ToString("X8")) xmlFile.WriteEndElement() xmlFile.WriteStartElement("PatchProgramAddress") xmlFile.WriteString(patchProgramAddress.ToString("X8")) xmlFile.WriteEndElement() xmlFile.WriteStartElement("JumpTableAddress") xmlFile.WriteString(jumpTableAddress.ToString("X8")) xmlFile.WriteEndElement() xmlFile.WriteStartElement("BCALLPatchAddress") xmlFile.WriteString(BCALLPatchAddress.ToString("X8")) xmlFile.WriteEndElement() xmlFile.WriteEndElement() xmlFile.Close() 'Create .org text file Dim orgFile As New IO.FileStream(args(3), IO.FileMode.Create) Dim line As String = ".org $" & (address Or &H4000).ToString("X4") & Environment.NewLine orgFile.Write(System.Text.ASCIIEncoding.ASCII.GetBytes(line), 0, line.Length) orgFile.Close() Catch ex As GetInfoException _DisplayUsage(ex.ExitCode, ex.Message) Exit Sub Catch ex As Exception _DisplayUsage(_UNKNOWN_EXCEPTION, ex.Message) Exit Sub End Try End Sub #End Region #Region " Private Methods " Private Shared Sub _DisplayUsage(ByVal exitCode As Integer, ByVal msg As String) Console.WriteLine("GetPatchInfo " & My.Application.Info.Version.ToString(3)) Console.WriteLine("-----------------------------------------------------------------") Console.WriteLine("Usage: GetPatchInfo ") Console.WriteLine("Retrieves patch information from 83+ ROM image and outputs") Console.WriteLine(" important addresses to XML file and new .org address to text file.") Console.WriteLine() Console.WriteLine("Example: GetPatchInfo 83Plus.rom prog.bin patch.xml patch.org") Console.WriteLine() Console.Write("ERROR: " & msg) Environment.ExitCode = exitCode End Sub Private Shared Function _FindBlankSpace(ByVal data As Byte(), ByVal pages As Integer(), _ ByVal size As Integer) As Integer Dim i As Integer Dim j As Integer Dim blockSize As Integer For j = 0 To pages.Length - 1 If pages(j) <> &HFF Then blockSize = 0 i = _PAGE_SIZE - 1 'Start out at the end of this page... While data((pages(j) * _PAGE_SIZE) + i) = &HFF 'And we're still at &HFF, so keep going backwards blockSize += 1 i -= 1 End While If blockSize >= size Then 'We found a block big enough, pull out and return it Exit For End If End If Next If blockSize < size Then Throw New GetInfoException(_BLANK_SPACE_NOT_FOUND, _ "Not enough free space in ROM image!") End If Return (pages(j) * _PAGE_SIZE) + i + 1 End Function Private Shared Function _FindPattern(ByVal data As Byte(), ByVal startIndex As Integer, _ ByVal count As Integer, ByVal pattern As Byte()) As Integer Dim i As Integer Dim ret As Integer = startIndex Dim offset As Integer For i = startIndex To startIndex + count - 1 If pattern.Length = offset Then Exit For If data(i) = pattern(offset) OrElse pattern(offset) = &HFF Then 'Still a match so far offset += 1 Else 'No match, start over offset = 0 ret = i + 1 End If Next If i >= startIndex + count Then Throw New GetInfoException(_PATTERN_NOT_FOUND, _ "Pattern to patch was not found in ROM image!") End If Return ret End Function #End Region End Class