A.4 The sections

Apart from the header section, all the data in the PPU file is separated into data blocks, which permit easily adding additional data blocks, without compromising backward compatibility. This is similar to both Electronic Arts IFF chunk format and Microsoft’s RIFF chunk format.

Each ’chunk’ (tppuentry) has the following format, and can be nested:

Table A.4: chunk data format

offsetsize (bytes)description

00h 1 Block type (nested (2) or main (1))
01h 1 Block identifier
02h 4 Size of this data block
06h+ ¡variable¿ Data for this block

Each main section chunk must end with an end chunk. Nested chunks are used for record, class or object fields.

To read an entry you can simply call ppufile.readentry:byte, it returns the tppuentry.nr field, which holds the type of the entry. A common way how this works is (example is for the symbols):

    case b of  
   ib<etc> : begin  
 ibendsyms : break;  
  until false;

The possible entry types are found in ppu.pas, but a short description of the most common ones are shown in table (A.5).

Table A.5: Possible PPU Entry types

Symbolic name Location Description

ibmodulename General Name of this unit.
ibsourcefiles General Name of source files.
ibusedmacros General Name and state of macros used.
ibloadunit General Modules used by this units.
inlinkunitofiles General Object files associated with this unit.
iblinkunitstaticlibs General Static libraries associated with this unit.
iblinkunitsharedlibs General Shared libraries associated with this unit.
ibendinterface General End of General information section.
ibstartdefs Interface Start of definitions.
ibenddefs Interface End of definitions.
ibstartsyms Interface Start of symbol data.
ibendsyms Interface End of symbol data.
ibendimplementationImplementationEnd of implementation data.
ibendbrowser Browser End of browser section.
ibend General End of Unit file.

Then you can parse each entry type yourself. ppufile.readentry will take care of skipping unread bytes in the entry and reads the next entry correctly! A special function is skipuntilentry(untilb:byte):boolean; which will read the ppufile until it finds entry untilb in the main entries.

Parsing an entry can be done with ppufile.getxxx functions. The available functions are:

procedure ppufile.getdata(var b;len:longint);  
function  getbyte:byte;  
function  getword:word;  
function  getlongint:longint;  
function  getreal:ppureal;  
function  getstring:string;

To check if you’re at the end of an entry you can use the following function:

function  EndOfEntry:boolean;


  1. ppureal is the best real that exists for the cpu where the unit is created for. Currently it is extended for i386 and single for m68k.
  2. the ibobjectdef and ibrecorddef have stored a definition and symbol section for themselves. So you’ll need a recursive call. See ppudump.pp for a correct implementation.

A complete list of entries and what their fields contain can be found in ppudump.pp.