private static BeImageReader?GetA5InitImageReader(ImageSegment a5dataSegment) { var a5data = a5dataSegment.MemoryArea; var a5dr = new BeImageReader((ByteMemoryArea)a5data, 0); if (!a5dr.TryReadBeUInt32(out uint a5d0)) { return(null); } if (!a5dr.TryReadBeUInt16(out ushort a5d1)) { return(null); } var a5dheaderOffset = a5dr.ReadBeUInt16(); const uint A5Init_Sig_Movem_l = 0x48E77FF8; // movem.l\td1-d7/a0-a4,-(a7) const ushort A5Init_Sig_Lea = 0x49FA; // First word of lea\t$????(pc),a4 instruction if (a5d0 != A5Init_Sig_Movem_l || a5d1 != A5Init_Sig_Lea || a5dheaderOffset >= a5dataSegment.MemoryArea.Length) { // Starting code bytes incorrect or // Invalid offset to compressed global data - outside of A5World memory segment. // No global compressed data return(null); } a5dr.Seek(a5dheaderOffset - 2); return(a5dr); }
private void ProcessJumpTable(uint jtOffset) { var j = new JumpTable(); ImageReader ir = new BeImageReader(image, jtOffset); j.AboveA5Size = ir.ReadBeUInt32(); j.BelowA5Size = ir.ReadBeUInt32(); j.JumpTableSize = ir.ReadBeUInt32(); j.JumpTableOffset = ir.ReadBeUInt32(); uint size = j.JumpTableSize; while (size > 0) { JumpTableEntry jte = new JumpTableEntry(); jte.RoutineOffsetFromSegmentStart = ir.ReadBeUInt16(); jte.Instruction = ir.ReadBeUInt32(); jte.LoadSegTrapNumber = ir.ReadBeUInt16(); Debug.WriteLine(string.Format("Jump table entry: {0:x2} {1:X4} {2:X2}", jte.RoutineOffsetFromSegmentStart, jte.Instruction, jte.LoadSegTrapNumber)); size -= 8; } }
public void Relocate() { var memA5 = (ByteMemoryArea)platform.A5World.MemoryArea; var a5belowWriter = new BeImageWriter(memA5, 0); var a5belowReader = new BeImageReader(memA5, 0); uint a5globalOffset = platform.A5Offset - a5dbelow; var a5WorldAddress = (UInt32)((platform.A5World.Address.Offset + platform.A5Offset) & 0xFFFFFFFF); // set Repeat count = 1, reset after each completed copy cycle // byte token lower 4 bits number of words to copy from compressed data // byte token upper 4 bits number of words to skip in global application data space // if either value is 0 then get run length value which is in bytes. // if the new run length value for copy is 0 then it's the end of compression data. for (;;) { int a5repeat = 1; // Skip is number of 16-bit words to skip uint a5globalSkip = a5dr.ReadByte(); if (a5globalSkip == 0) { a5globalSkip = a5dr.ReadByte(); if (a5globalSkip == 0) { break; } if (a5globalSkip > 0x7F) { a5globalSkip = ((a5globalSkip & 0x7F) << 8) + a5dr.ReadByte(); a5globalSkip = (a5globalSkip << 16) + a5dr.ReadBeUInt16(); } else { a5repeat = ResourceFork.GetRunLengthValue(a5dr, ref a5repeat); //$BUG: a5repeat could return the value 0. The do-while below will // decrement a5repeat before testing. This will lead to an effective // repeat count of 2^32; likely not wanted. } } else { if ((a5globalSkip & 0x80) == 0x80) { a5globalSkip = ((a5globalSkip & 0x7F) << 8) + a5dr.ReadByte(); } } a5globalSkip = a5globalSkip * 2; do { a5globalOffset += a5globalSkip; a5belowReader.Seek(a5globalOffset, SeekOrigin.Begin); uint a5ptrOffset = a5belowReader.ReadBeUInt32(); a5belowWriter.Position = (int)a5globalOffset; // write relocated A5World pointers to absolute address in A5World segment // Possible register/mark as Global pointer references to strings a5belowWriter.WriteBeUInt32((a5WorldAddress + a5ptrOffset) & 0xFFFFFFFF); --a5repeat; } while (a5repeat > 0); } }