Public Class Main #Region " Declarations " Private Const _WRONG_NUM_ARGUMENTS As Integer = 1 Private Const _UNKNOWN_EXCEPTION As Integer = 2 Private Const _PATTERN_NOT_FOUND As Integer = 3 Private Const _REQUIRED_ARGUMENTS As Integer = 4 Private Const _PAGE_SIZE As Integer = 16384 Private Const _IMAGE_SIZE As Integer = _PAGE_SIZE * &H20 Private Const _JUMP_TABLE_SIZE 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 page0Address As Integer Dim patchProgramAddress As Integer Dim jumpTableAddress As Integer Dim BCALLPatchAddress As Integer Dim startIndex As Integer 'Read in XML file of information Dim xmlFile As New Xml.XmlTextReader(args(3)) xmlFile.ReadStartElement("PatchInfo") xmlFile.ReadStartElement("Page0Address") page0Address = Convert.ToInt32(xmlFile.ReadContentAsString(), 16) xmlFile.ReadEndElement() xmlFile.ReadStartElement("PatchProgramAddress") patchProgramAddress = Convert.ToInt32(xmlFile.ReadContentAsString(), 16) xmlFile.ReadEndElement() xmlFile.ReadStartElement("JumpTableAddress") jumpTableAddress = Convert.ToInt32(xmlFile.ReadContentAsString(), 16) xmlFile.ReadEndElement() xmlFile.ReadStartElement("BCALLPatchAddress") BCALLPatchAddress = Convert.ToInt32(xmlFile.ReadContentAsString(), 16) xmlFile.ReadEndElement() xmlFile.ReadEndElement() xmlFile.Close() 'Open ROM image and read it all in Dim imageFile As New IO.FileStream(args(0), IO.FileMode.Open, IO.FileAccess.Read) Dim imageData(_IMAGE_SIZE - 1) As Byte imageFile.Read(imageData, 0, _IMAGE_SIZE) imageFile.Close() 'Validate OS imageData(&H56) = &H5A 'Remove (NOP out) all references to _SetFlashLowerBound startIndex = 0 Dim setFlashLowerBoundPattern() As Byte = {&HEF, &HCF, &H80} Do startIndex = _FindPattern(imageData, startIndex, _IMAGE_SIZE - startIndex, _ setFlashLowerBoundPattern) If startIndex > 0 Then imageData(startIndex + 0) = 0 imageData(startIndex + 1) = 0 imageData(startIndex + 2) = 0 End If Loop While startIndex > 0 'Patch any LCD delays startIndex = 0 Dim LCDDelayPattern() As Byte = {&HDB, &H2, &HE6, &H2} Do startIndex = _FindPattern(imageData, startIndex, _PAGE_SIZE - startIndex, _ LCDDelayPattern) If startIndex > 0 Then imageData(startIndex + 0) = &HF5 imageData(startIndex + 1) = &HF5 imageData(startIndex + 2) = &HF1 imageData(startIndex + 3) = &HF1 imageData(startIndex + 4) = 0 imageData(startIndex + 5) = 0 End If Loop While startIndex > 0 'Patch boot code jump on page 0 startIndex = 0 Dim bootCodeJumpPattern() As Byte = {&HC3, &HD5, &H80} startIndex = _FindPattern(imageData, 0, _PAGE_SIZE, bootCodeJumpPattern) If startIndex > 0 Then imageData(startIndex + 1) = &HCF imageData(startIndex + 2) = &H80 End If 'Patch BCALL routine to call our code instead imageData(BCALLPatchAddress + 0) = &HCD imageData(BCALLPatchAddress + 1) = Convert.ToByte(page0Address And &HFF) imageData(BCALLPatchAddress + 2) = Convert.ToByte(((page0Address And &HFF00) >> 8) And &HFF) imageData(BCALLPatchAddress + 3) = 0 'Put our code for the BCALL routine to call Dim jumpTableAddr As Integer = jumpTableAddress Dim jumpTablePage As Integer While jumpTableAddr >= _PAGE_SIZE jumpTableAddr -= _PAGE_SIZE jumpTablePage += 1 End While jumpTableAddr = jumpTableAddr Or &H4000 imageData(page0Address + 0) = &H60 imageData(page0Address + 1) = &H11 imageData(page0Address + 2) = Convert.ToByte(jumpTableAddr And &HFF) imageData(page0Address + 3) = Convert.ToByte(((jumpTableAddr And &HFF00) >> 8) And &H3F) imageData(page0Address + 4) = &H19 imageData(page0Address + 5) = &H3E imageData(page0Address + 6) = Convert.ToByte(jumpTablePage) imageData(page0Address + 7) = &HC9 'Read in patch program Dim info As New IO.FileInfo(args(1)) Dim progData(Convert.ToInt32(info.Length)) As Byte Dim progFile As New IO.FileStream(args(1), IO.FileMode.Open, IO.FileAccess.Read) progFile.Read(progData, 0, Convert.ToInt32(progFile.Length)) progFile.Close() 'Write patch program to memory For i As Long = 0 To info.Length - 1 imageData(Convert.ToInt32(patchProgramAddress + i)) = progData(Convert.ToInt32(i)) Next 'Read in LST file Dim listLines As New List(Of String) Dim lstFile As New IO.StreamReader(args(2)) While Not lstFile.EndOfStream listLines.Add(lstFile.ReadLine()) End While lstFile.Close() 'Copy old jump table from page 1Fh to new location For i As Integer = 0 To _JUMP_TABLE_SIZE - 1 imageData(jumpTableAddress + i) = imageData(&H1F * _PAGE_SIZE + i) Next 'Save offsets of each routine Dim progPage As Integer Dim progAddress As Integer = patchProgramAddress While progAddress >= _PAGE_SIZE progAddress -= _PAGE_SIZE progPage += 1 End While progAddress = progAddress Or &H4000 Dim entryPoints As Dictionary(Of String, Integer) = _BuildEntryPointList() For Each entryPoint As KeyValuePair(Of String, Integer) In entryPoints For Each line As String In listLines If line.ToLower.Contains("x_" & entryPoint.Key & ":") Then 'This line is the start of this entry point, save it in our dictionary Dim address As Integer = progAddress + Convert.ToInt32(line.Substring(7, 4), 16) imageData(jumpTableAddress + entryPoint.Value + 0) = Convert.ToByte(address And &HFF) imageData(jumpTableAddress + entryPoint.Value + 1) = Convert.ToByte(((address And &HFF00) >> 8) And &HFF) imageData(jumpTableAddress + entryPoint.Value + 2) = Convert.ToByte(progPage) End If Next Next 'Write ROM image back out imageFile = New IO.FileStream(args(0), IO.FileMode.Open, IO.FileAccess.Write) imageFile.Write(imageData, 0, _IMAGE_SIZE) imageFile.Close() Catch ex As DoPatchException _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("Do73Patch " & My.Application.Info.Version.ToString(3)) Console.WriteLine("---------------------------------------------------------------------") Console.WriteLine("Usage: Do73Patch ") Console.WriteLine("Patches 83+ ROM image using XML information and BIN of patch program.") Console.WriteLine() Console.WriteLine("Example: Do73Patch 83Plus.rom prog.bin prog.lst patch.xml") Console.WriteLine() Console.Write("ERROR: " & msg) Environment.ExitCode = exitCode End Sub 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 ret = 0 End If Return ret End Function Private Shared Function _BuildEntryPointList() As Dictionary(Of String, Integer) Dim base As Integer = 0 '&H1F * _PAGE_SIZE Dim ret As New Dictionary(Of String, Integer) ret.Add("MD5Final".ToLower(), base + &H18) ret.Add("RSAValidate".ToLower(), base + &H1B) ret.Add("cmpStr".ToLower(), base + &H1E) ret.Add("WriteAByte".ToLower(), base + &H21) ret.Add("EraseFlash".ToLower(), base + &H24) ret.Add("FindFirstCertField".ToLower(), base + &H27) ret.Add("ZeroToCertificate".ToLower(), base + &H2A) ret.Add("GetCertificateEnd".ToLower(), base + &H2D) ret.Add("FindGroupedField".ToLower(), base + &H30) ret.Add("ret_1".ToLower(), base + &H33) ret.Add("ret_2".ToLower(), base + &H36) ret.Add("ret_3".ToLower(), base + &H39) ret.Add("ret_4".ToLower(), base + &H3C) ret.Add("ret_5".ToLower(), base + &H3F) ret.Add("Mult8By8".ToLower(), base + &H42) ret.Add("Mult16By8".ToLower(), base + &H45) ret.Add("Div16By8".ToLower(), base + &H48) ret.Add("Div16By16".ToLower(), base + &H4B) ret.Add("804Eh".ToLower(), base + &H4E) ret.Add("LoadAIndPaged".ToLower(), base + &H51) ret.Add("FlashToRam2".ToLower(), base + &H54) ret.Add("GetCertificateStart".ToLower(), base + &H57) ret.Add("GetFieldSize".ToLower(), base + &H5A) ret.Add("FindSubField".ToLower(), base + &H5D) ret.Add("EraseCertificateSector".ToLower(), base + &H60) ret.Add("CheckHeaderKey".ToLower(), base + &H63) ret.Add("8066h".ToLower(), base + &H66) ret.Add("8069h".ToLower(), base + &H69) ret.Add("Load_LFontV2".ToLower(), base + &H6C) ret.Add("Load_LFontV".ToLower(), base + &H6F) ret.Add("ReceiveOS".ToLower(), base + &H72) ret.Add("FindOSHeaderSubField".ToLower(), base + &H75) ret.Add("FindNextCertField".ToLower(), base + &H78) ret.Add("GetByteOrBoot".ToLower(), base + &H7B) ret.Add("getSerial".ToLower(), base + &H7E) ret.Add("ReceiveCalcID".ToLower(), base + &H81) ret.Add("EraseFlashPage".ToLower(), base + &H84) ret.Add("WriteFlashUnsafe".ToLower(), base + &H87) ret.Add("dispBootVer".ToLower(), base + &H8A) ret.Add("MD5Init".ToLower(), base + &H8D) ret.Add("MD5Update".ToLower(), base + &H90) ret.Add("MarkOSInvalid".ToLower(), base + &H93) ret.Add("FindProgramLicense".ToLower(), base + &H96) ret.Add("MarkOSValid".ToLower(), base + &H99) ret.Add("CheckOSValidated".ToLower(), base + &H9C) ret.Add("SetupAppPubKey".ToLower(), base + &H809F) ret.Add("SigModR".ToLower(), base + &HA2) ret.Add("TransformHash".ToLower(), base + &HA5) ret.Add("IsAppFreeware".ToLower(), base + &HA8) ret.Add("FindAppHeaderSubField".ToLower(), base + &HAB) ret.Add("WriteValidationNumber".ToLower(), base + &HAE) ret.Add("Div32By16".ToLower(), base + &HB1) ret.Add("FindGroup".ToLower(), base + &HB4) ret.Add("getBootVer".ToLower(), base + &HB7) ret.Add("getHardwareVerison".ToLower(), base + &HBA) ret.Add("xorA".ToLower(), base + &HBD) ret.Add("bignumpowermod17".ToLower(), base + &HC0) ret.Add("ProdNrPart1".ToLower(), base + &HC3) ret.Add("WriteAByteSafe".ToLower(), base + &HC6) ret.Add("WriteFlash".ToLower(), base + &HC9) ret.Add("SetupDateStampPubKey".ToLower(), base + &HCC) Return ret End Function #End Region End Class