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 |
|
|
| offset | size (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):
repeat
b:=ppufile.readentry;
case b of
ib<etc> : begin
end;
ibendsyms : break;
end;
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. |
ibendimplementation | Implementation | End 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;
|
notes:
- 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.
- 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.