Skip to content

Commit

Permalink
Feature: rudimentary support for PalmOS .prc binaries.
Browse files Browse the repository at this point in the history
  • Loading branch information
uxmal committed Dec 3, 2023
1 parent 5c2fd63 commit 3418ed3
Show file tree
Hide file tree
Showing 13 changed files with 458 additions and 3 deletions.
1 change: 1 addition & 0 deletions src/Drivers/Common.items
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ by the PreBuild.targets file.
<ProjectReference Include="$(SolutionDir)Environments\NeoGeo\NeoGeo.csproj" />
<ProjectReference Include="$(SolutionDir)Environments\OpenVMS\OpenVMS.csproj" />
<ProjectReference Include="$(SolutionDir)Environments\OS2\OS2.csproj" />
<ProjectReference Include="$(SolutionDir)Environments\PalmOS\PalmOS.csproj" />
<ProjectReference Include="$(SolutionDir)Environments\Pdp10Env\Pdp10Env.csproj" />
<ProjectReference Include="$(SolutionDir)Environments\Ps3\Ps3.csproj" />
<ProjectReference Include="$(SolutionDir)Environments\RiscOS\RiscOS.csproj" />
Expand Down
6 changes: 6 additions & 0 deletions src/Drivers/reko.config
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
<Loader Extension="prg" Type="Reko.Environments.C64.PrgLoader,Reko.Environments.C64" Description="C64 PRG image" />
<Loader Extension="rsrc" Type="Reko.Environments.MacOS.Classic.RsrcLoader,Reko.Environments.MacOS" Description="MacOS classic resource fork" Label="rsrc" />
<Loader Extension="tar" Type="Reko.ImageLoaders.Archives.TarLoader,Reko.ImageLoaders.Archives" Description="Tarball" />
<Loader Extension="prc" Type="Reko.Environments.PalmOS.PRC.PrcLoader,Reko.Environments.PalmOS" Description="PalmOS executable" />

<!-- The following loaders have known file formats but no specified file extensions -->
<Loader Label="NintendoDol" Type="Reko.ImageLoaders.Dol.DolLoader,Reko.ImageLoaders.Dol" Description="Nintendo DOL image format" />
Expand Down Expand Up @@ -444,6 +445,11 @@
Type="Reko.Environments.Ps3.Ps3Platform,Reko.Environments.Ps3">
</Environment>

<Environment Name="palmOS"
Description="Palm OS"
Type="Reko.Environments.PalmOS.PalmOSPlatform,Reko.Environments.PalmOSPlatform">
</Environment>

<Environment Name="xbox"
Description="Xbox"
Type="Reko.Environments.Xbox.XboxPlatform,Reko.Environments.Xbox">
Expand Down
2 changes: 1 addition & 1 deletion src/Environments/MacOS/Classic/AppleDoubleLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public override Program LoadProgram(Address? addrLoad)
{
addrLoad ??= PreferredBaseAddress;
var cfgSvc = Services.RequireService<IConfigurationService>();
var rdr = new Core.Memory.BeImageReader(RawImage);
var rdr = new BeImageReader(RawImage);
var hdr = rdr.ReadStruct<Header>();
var things = new Entry[hdr.cEntries];
for (int i = 0; i < things.Length; ++i)
Expand Down
32 changes: 32 additions & 0 deletions src/Environments/PalmOS/PRC/Code0Resource.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#region License
/*
* Copyright (C) 1999-2023 John Källén.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#endregion

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Reko.Environments.PalmOS.PRC
{
public class Code0Resource
{
}
}
46 changes: 46 additions & 0 deletions src/Environments/PalmOS/PRC/PrcHeader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#region License
/*
* Copyright (C) 1999-2023 John Källén.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#endregion

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Reko.Environments.PalmOS.PRC
{
public class PrcHeader
{
public string? name;
public ushort flags;
public ushort version;
public uint create_time;
public uint mod_time;
public uint backup_time;
public uint mod_num;
public uint app_info;
public uint sort_info;
public uint type;
public uint id;
public uint unique_id_seed;
public uint next_record_list;
public ushort num_records;
}
}
180 changes: 180 additions & 0 deletions src/Environments/PalmOS/PRC/PrcLoader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
#region License
/*
* Copyright (C) 1999-2023 John Källén.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#endregion

using Reko.Core;
using Reko.Core.Configuration;
using Reko.Core.Loading;
using Reko.Core.Memory;
using Reko.Core.Services;
using System;
using System.Collections.Generic;
using System.Text;

namespace Reko.Environments.PalmOS.PRC
{
/// <summary>
/// Loads PalmOS PRC files.
/// </summary>

public class PrcLoader : ProgramImageLoader
{
// https://web.mit.edu/tytso/www/pilot/prc-format.html

public PrcLoader(IServiceProvider services, ImageLocation imageLocation, byte[] imgRaw)
: base(services, imageLocation, imgRaw)
{
}

public override Address PreferredBaseAddress
{
get { return Address.Ptr32(0x00100000); }
set { throw new NotImplementedException(); }
}


public override Program LoadProgram(Address? addrLoad)
{
addrLoad ??= PreferredBaseAddress;
var rdr = new BeImageReader(base.RawImage);
var cfgSvc = Services.RequireService<IConfigurationService>();

var header = LoadHeader(rdr);
if (header is null)
throw new BadImageFormatException();
var rsrcHeaders = LoadResourceHeaders(rdr, header.num_records);
if (rsrcHeaders is null)
throw new BadImageFormatException();
var segments = LoadResources(rdr, rsrcHeaders, addrLoad);
if (segments is null)
throw new BadImageFormatException();

var arch = cfgSvc.GetArchitecture("m68k")!;
var platform = new PalmOSPlatform(Services, arch, "palmOS");
var program = new Program(segments, arch, platform);
return program;
}

private PrcHeader? LoadHeader(BeImageReader rdr)
{
var header = new PrcHeader();
var abName = rdr.ReadBytes(0x20);
if (abName.Length != 0x20)
return null;
int i = Array.IndexOf(abName, 0);
if (i < 0)
header.name = Encoding.ASCII.GetString(abName);
else
header.name = Encoding.ASCII.GetString(abName, 0, i);

if (!rdr.TryReadBeUInt16(out header.flags))
return null;
if (!rdr.TryReadBeUInt16(out header.version))
return null;
if (!rdr.TryReadBeUInt32(out header.create_time))
return null;
if (!rdr.TryReadBeUInt32(out header.mod_time))
return null;
if (!rdr.TryReadBeUInt32(out header.backup_time))
return null;

if (!rdr.TryReadBeUInt32(out header.mod_num))
return null;
if (!rdr.TryReadBeUInt32(out header.app_info))
return null;
if (!rdr.TryReadBeUInt32(out header.sort_info))
return null;
if (!rdr.TryReadBeUInt32(out header.type))
return null;

if (!rdr.TryReadBeUInt32(out header.id))
return null;
if (!rdr.TryReadBeUInt32(out header.unique_id_seed))
return null;
if (!rdr.TryReadBeUInt32(out header.next_record_list))
return null;
if (!rdr.TryReadBeUInt16(out header.num_records))
return null;

return header;
}

private List<ResourceHeader>? LoadResourceHeaders(BeImageReader rdr, uint cRecords)
{
var headers = new List<ResourceHeader>();
for (uint i = 0; i < cRecords; ++i)
{
var rhdr = new ResourceHeader();
var abName = rdr.ReadBytes(4);
if (abName.Length != 4)
return null;
rhdr.name = Encoding.ASCII.GetString(abName);
if (!rdr.TryReadBeUInt16(out rhdr.id))
return null;
if (!rdr.TryReadBeUInt32(out rhdr.offset))
return null;
headers.Add(rhdr);
}
return headers;
}

private SegmentMap LoadResources(BeImageReader rdr, List<ResourceHeader> rsrcHeaders, Address addrBase)
{
var segments = new List<ImageSegment>();
var addr = addrBase;
for (int i = 0; i < rsrcHeaders.Count - 1; ++i)
{
var hdr = rsrcHeaders[i];
var length = rsrcHeaders[i+1].offset - hdr.offset;
rdr.Offset = hdr.offset;
var bytes = rdr.ReadBytes(length);
var mem = new ByteMemoryArea(addr, bytes);
string? name = hdr.name;
if (name is null)
name = $"#{hdr.id}";
else
name = $"{name}#{hdr.id}";
var accessMode = AccessMode.Read;
if (hdr.name == "code")
{
if (hdr.id == 0)
{
LoadCode0Resource();
}
else
{
accessMode = AccessMode.ReadExecute;
}
}
var seg = new ImageSegment(name, mem, accessMode);
segments.Add(seg);
addr += length; //$TODO: align to even paragraph boundary?
}
return new SegmentMap(segments.ToArray());
}

private void LoadCode0Resource()
{
//$TODO: according to the doc page, the code0 resource sometimes
// is patterend after MacOS, with a jump table above the "a5 line",
// and sometimes follows a different convention. Needs more investigation,
// and access to different binaries build by different toolchains.
}
}
}
35 changes: 35 additions & 0 deletions src/Environments/PalmOS/PRC/ResourceHeader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#region License
/*
* Copyright (C) 1999-2023 John Källén.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#endregion

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Reko.Environments.PalmOS.PRC
{
public class ResourceHeader
{
public string? name;
public ushort id;
public uint offset;
}
}
16 changes: 16 additions & 0 deletions src/Environments/PalmOS/PalmOS.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="$(ProjectDir)../../Drivers/CommonBuildProperties.items" />
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<OutputType>Library</OutputType>
<RootNamespace>Reko.Environments.PalmOS</RootNamespace>
<AssemblyName>Reko.Environments.PalmOS</AssemblyName>
<Nullable>enable</Nullable>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<Configurations>Debug;Release</Configurations>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Arch\M68k\M68k.csproj" />
<ProjectReference Include="..\..\Core\Core.csproj" />
</ItemGroup>
</Project>
Loading

0 comments on commit 3418ed3

Please sign in to comment.