Tech Note 02: NS Basic/Palm PDB File StructureOct 27, 2002© NSB Corporation. All rights reserved. |
"PDB" is the abbreviation of "Palm Database". It is not a difficult structure
to understand and figure out with the correct tools. Once you
know this structure, you can easily make pdb files using VB or
other tools. In this short Tech note, I'll explain the structure of the most simple PDB file. Once you understand this, you will be able to understand other, more advanced cases more easily. Getting Started We will
be using a Non-keyed database in NS Basic/Palm. Dim Db as Database Dim res as Integer res=DbCreate(Db,"DB-CREATE-TEST",0,"Test") 'Creator ID is "Test" If res=0 then 'Created successfully res=DbOpen(Db,"DB-CREATE-TEST",0) res=DbPosition(Db,1,0) 'Position pointer to record 1 res=DbPut(Db,"NS BASIC") 'Write it res=DbPosition(Db,2,0) 'Position pointer to record 2 res=DbPut(Db,"mizuno-ami") res=DbPosition(Db,3,0) res=DbPut(Db,"Simple Sample") res=DbClose(Db) End ifReading the database can be done through this code: (Field1008 shows the data which specified record at Field1006.) Dim Db as Database Dim res as Integer Dim intSet as Integer Dim strData as String intSet=Val(Field1006.Text) res=DbOpen(Db,"DB-CREATE-TEST",0) res=DbPosition(Db,intSet,0) 'Position pointer to the value in field1006 res=DbGet(Db,strData) res=DbClose(Db) Field1008.text=strData 'Display your db dataAfter inputting this code into a sample project, you can create a sample database. (A very simple example is included in this ZIP file) After compiling, and running the program, create a database by clicking on "Create" Now "Export the database" by right clicking on POSE and selecting "Export Database". Select the file we created, called "DB-CREAT-TEST", and export it to a location that we can easily find (the desktop). To check to ensure the database has been made correctly, type in "1" in the "Record" field and then read. We created 3 records. To see the "inside" of the PDB file you will need a hex editor. I will be using Hex Workshop 3.11 (actually another hex editor is shown, but Hex Workshop works well for this purpose), but any hex or binary editor will do. A PDB file is split up into 3 sections:
The Header Let's look at the Database header.
Let's look up these data in order. The database name is typically 32 byte data, followed by a null terminator "00" (Each field we see will be terminated by null). In most cases, you will find other unusal strings (like "ANL") after the null that you did not write. This is perfectly normal, depending on how the database was made. Palm ignores data after "00". The next 2 bytes, you can find "00 08", this is the attribute of the file. If it is set to "00 08", then this file will be backed to your PC at Hotsync. Usually, you must manually set this flag "00 08". The next 2 bytes, is the version number. This is the same number you would see by going to the info screen on the Palm and checking the version number there. In our example, "00 00" is written here, so our version number is the decimal equivalent of "00 00" hex, also "0". The next bit of information is the create time, the modify time and the backup time, all measured in seconds data (4 bytes) Palm uses a unique format for all times, measured in seconds since '1904-01-01 00:00:00'. We won't have to worry about this, so we'll skip it here. You can find ample information on the internet about this if you wish. When doing Hotsync, this data is updated. The next bit of data is the 'modification number' a number that counts the numbe rof times a modification has been done. When you will make a new PDB file, you can write "00 00 00 00" it. The application info size and sort info size, is also something we need not worry about. For our case, this is "00 00 00 00", simply meaning that this information is not present. The simplest database does not need this information. The next 2 bytes of data may be familiar to you. The first 4 bytes is file type and next 4 bytes is creator ID. As a database , the type will be usually "data". The creator ID will be set by you when you create this database file using DbCreate(). In our example case, "Test". Next 8 bytes , I don't know in detail but I know these are not needed for our purpose. The last 2 bytes of header is number of records. Records we wrote are 3 records, and so here is "00 03".(written in hex) The data here is 2 bytes, meaning that the maximum number of records is 65535 records. Those are the basic details of the header data of 78 bytes. Location information (Record Header - "Table of Contents") After the header, the Palm must know what record to lookup and where to look it up. The Palm uses a technique very similar to a book's table of contents. After knowing what "chapter" to look up, you go to the table of contents to look up the page number and then go quickly to the page number. Can you skip the TOC and go directly to the page? Sure you can, if you know where it is, otherwise you must scan each page for the information you want. This is very slow. It is slow on the Palm as well. In our example of 3 records, we should have a table of contents with 3 entries (records)in it and 3 page numbers (locations)
It may be helpful for you to understand that this is an index. Let's start from the beginning. After the header (78bytes) we are at position 78 or in hex 4E. The next four bytes are the location information for the first record number. Reading in the four bytes, we get 00 00 00 68 (hex). This is the address of the first record in our database. If we go to address 68 (the leading zeros drop off), we find our first record, "NS BASIC". If we want the second record, we read our next table of contents entry starting 4 bytes after our location of record 1 (note, each TOC entry is 8 bytes, so from byte 78, we would skip the first 8 bytes (rec#1) and then read at offset 78+8=86 dec or 56 hex which would read the beginning of record #2 (mizuno...)
Once we know the structure of the PDB header, we can theoretically find
any record number we want. All we have to do is a simple calculation
and read the table of contents. How? As an example in this case,
to read the 3rd record, the header is 78 byte, so 78 + 3 * 8 = 102 -> 066H, is the
start of record #3's real data
location. This tutorial was originally made by mizuno-ami and then modified/translated/cleaned up by Jeff VanderWal. |