Skip to content

Commit 319b8b1

Browse files
committed
Fixing string offset explanations.
1 parent 10561f5 commit 319b8b1

File tree

1 file changed

+102
-69
lines changed

1 file changed

+102
-69
lines changed

doc/modules/ROOT/pages/exports.adoc

Lines changed: 102 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -240,72 +240,25 @@ And so the row index grows backwards towards the rows that are being added forwa
240240
The structure of the rows themselves is determined by the _type_ of the table, using the values shown in <<table-types,Table types>>.
241241
Unless otherwise noted, these table types and rows appear in `export.pdb` files.
242242

243-
[#artist-rows]
244-
=== Artist Rows
245-
246-
Artist rows hold an Artist name and ID, with the structure shown in <<artist-row-near>> or
247-
<<artist-row-far>>.
248-
The _subtype_ value at bytes{nbsp}``00``-`01` determines which variant is used.
249-
If the artist name was allocated close enough to the row to be reached by a single
250-
byte offset, offset, _subtype_ has the value `0060`, and the row has the structure in <<artist-row-near>>
251-
If the name is too far away for that, _subtype_ has the value `0064` and the row has the structure in <<artist-row-far>>.
252-
253-
[#artist-row-near]
254-
.Artist row with nearby name.
255-
[bytefield]
256-
----
257-
(def boxes-per-row 0x0a)
258-
(def left-margin 1)
259-
(draw-column-headers)
260-
(draw-box 0x60 {:span 2})
261-
(draw-box (text "i" :math [:sub "shift"]) {:span 2})
262-
(draw-box (text "id" :math) {:span 4})
263-
(draw-box (text "u" :math [:sub 1]))
264-
(draw-box (text "o" :math [:sub "n"]))
265-
----
266-
267-
[#artist-row-far]
268-
.Artist row with far name.
269-
[bytefield]
270-
----
271-
(def boxes-per-row 0x0c)
272-
(def left-margin 1)
273-
(draw-column-headers)
274-
(draw-box 0x64 {:span 2})
275-
(draw-box (text "i" :math [:sub "shift"]) {:span 2})
276-
(draw-box (text "id" :math) {:span 4})
277-
(draw-box (text "u" :math [:sub 1]))
278-
(draw-box (text "o" :math [:sub "n"]))
279-
(draw-box (text "o" :math [:sub "far"]) {:span 2})
280-
----
281-
282-
In either case, _subtype_ is followed by the unexplained two-byte value found in many row types that Mr. Lesniak called __index_shift__, and then by _id_, the ID of this artist row itself, at bytes{nbsp}``04``-`07`, an unknown value at byte{nbsp}``08``, and __ofs_name_near__ at byte{nbsp}``09`` (labeled _o~n~_), the one-byte name offset used only in the first variant.
283-
284-
If _subtype_ is `0064`, the value of __ofs_name_near__ is ignored, and instead the two-byte value __ofs_name_far__ (labeled _o~far~_) is used. Which of either
285-
variants occurs seems to also depend on the length of the name, so the `64 00` subtype may occur even if
286-
the string itself is placed directly following __ofs_name_far__.
287-
288-
Whichever name offset is used, it is a pointer to the artist name.
289-
To find the location of the name, add the value of the offset to the address of the start of the artist row itself.
290-
This gives the address of a DeviceSQL string holding the name, with the structure explained in <<devicesql-strings>>.
291-
292243
[#album-rows]
293244
=== Album Rows
294245

295246
Album rows hold an album name and ID along with an artist association, with the two structure variants shown below.
296-
The value at bytes bytes{nbsp}``00``-`01` are the subtype and differentiate the two variants (similar to the album rows). The value `80 00` is for the short version while `84 00` is for the long version.
297-
It is
298-
followed by a two-byte value Mr. Lesniak called __index_shift__, although I don’t know what that means, and another four bytes of unknown purpose.
247+
The value at bytes bytes{nbsp}``00``-`01` are the _subtype_ and differentiate the two variants.footnote:subtype[The Album, Artist, Tag, Tag Track, and Track tables all use subtypes to determine the size of string offsets, although Track rows seem to always be big enough to require the two-byte offset variant.]
248+
The value `80` is for the short version while `84` is for the long version.
249+
It is followed by a two-byte value Mr. Lesniak called __index_shift__, although I don’t know what that means, and another four bytes of unknown purpose.
299250
But at bytes{nbsp}``08``-`0b` we finally find a value we have a use for: __artist_id__ holds the ID of an artist row associated with this track row.
300251
This is followed by __id__, the ID of this track row itself, at bytes{nbsp}``0c``-`0f`.
301252
We assume that there are index tables somewhere that would let us locate the page and row index of a record given its table type and ID, but we have not yet found and figured them out.
302253

254+
This is followed by four more bytes with unknown meaning, and then the two subtypes diverge, because the remaining values consume a different number of bytes in each variant:
255+
256+
For subtype `80` there is a byte holding the value `03` followed by the final byte in the row, __ofs_name_near__ at byte{nbsp}``15``, a single byte pointer to the track name (labeled _o~n~_ in the <<album-row-near,byte field diagram>>). To find the location of the name, add __ofs_name_near__ bytes to the address of the start of the track row.
257+
258+
If the subtype is `84`, the row is of the second form, so the value `0003` takes up two bytes, followed by a two byte offset, __ofs_name_far__, at bytes{nbsp}``16``–`17` (labeled _o~far~_ in the <<album-row-far,diagram>>).
259+
260+
Which variant occurs seems to also depend on the length of the name (if the string takes more than about 200 bytes, the far name variant is used), so the `84` subtype may occur even if the string itself is placed directly following __ofs_name_far__.
303261

304-
This is followed by five more bytes with unknown meaning, and for subtype `80 00` the final byte in the row, __ofs_name_near__ is a pointer to the track name (labeled _o~n~_ in the byte field diagram).
305-
To find the location of the name, add __ofs_name_near__ bytes to the address of the start of the
306-
track row. If the subtype is `84 00`, the row is of the second form, with an additinal two byte offset __ofs_name_far__. In this case, the __ofs_name_near__ is ignored (though usually `00`). Which of either
307-
variants occurs seems to also depend on the length of the name, so the `84 00` subtype may occur even if
308-
the string itself is placed directly following __ofs_name_far__.
309262
The name itself is encoded in a surprisingly baroque way, explained in <<devicesql-strings>>.
310263

311264
[#album-row-near]
@@ -319,7 +272,7 @@ The name itself is encoded in a surprisingly baroque way, explained in <<devices
319272
(draw-box (text "artist_id" :math) {:span 4})
320273
(draw-box (text "id" :math) {:span 4})
321274
(draw-box (text "unknown" :math [:sub 3]) {:span 4})
322-
(draw-box (text "u" :math [:sub 4]))
275+
(draw-box 0x03)
323276
(draw-box (text "o" :math [:sub "n"]))
324277
----
325278

@@ -334,11 +287,59 @@ The name itself is encoded in a surprisingly baroque way, explained in <<devices
334287
(draw-box (text "artist_id" :math) {:span 4})
335288
(draw-box (text "id" :math) {:span 4})
336289
(draw-box (text "unknown" :math [:sub 3]) {:span 4})
337-
(draw-box (text "u" :math [:sub 4]))
290+
(draw-box 0x03 {:span 2})
291+
(draw-box (text "o" :math [:sub "far"]) {:span 2})
292+
----
293+
294+
295+
[#artist-rows]
296+
=== Artist Rows
297+
298+
Artist rows hold an Artist name and ID, with the structure shown in <<artist-row-near>> or
299+
<<artist-row-far>>.
300+
The _subtype_ value at bytes{nbsp}``00``-`01` determines which variant is used.footnote:subtype[]
301+
If the artist name is short enough and was allocated close enough to the row to be reached by a single
302+
byte offset, _subtype_ has the value `0060`, and the row has the structure in <<artist-row-near>>
303+
If the name is larger than about 200 bytes or is too far away for that, _subtype_ has the value `0064` and the row has the structure in <<artist-row-far>>
304+
305+
[#artist-row-near]
306+
.Artist row with nearby name.
307+
[bytefield]
308+
----
309+
(def boxes-per-row 0x0a)
310+
(def left-margin 1)
311+
(draw-column-headers)
312+
(draw-box 0x60 {:span 2})
313+
(draw-box (text "i" :math [:sub "shift"]) {:span 2})
314+
(draw-box (text "id" :math) {:span 4})
315+
(draw-box 0x03)
338316
(draw-box (text "o" :math [:sub "n"]))
317+
----
318+
319+
[#artist-row-far]
320+
.Artist row with far name.
321+
[bytefield]
322+
----
323+
(def boxes-per-row 0x0c)
324+
(def left-margin 1)
325+
(draw-column-headers)
326+
(draw-box 0x64 {:span 2})
327+
(draw-box (text "i" :math [:sub "shift"]) {:span 2})
328+
(draw-box (text "id" :math) {:span 4})
329+
(draw-box 0x03 {:span 2})
339330
(draw-box (text "o" :math [:sub "far"]) {:span 2})
340331
----
341332

333+
In either case, _subtype_ is followed by the unexplained two-byte value found in many row types that Mr. Lesniak called __index_shift__, and then by _id_, the ID of this artist row itself, at bytes{nbsp}``04``-`07`.
334+
After the id, the number 3 is always stored, followed by the offset to the name string.
335+
For subtype `0060`, each of these values take a single byte, and __ofs_name_near__ at byte{nbsp}``09`` (labeled _o~n~_), is the one-byte name offset.
336+
For subtype `0064`, each is stored in two bytes, and the two-byte name offset value __ofs_name_far__ (labeled _o~far~_) is found at bytes{nbsp}``0a``–`0b`.
337+
338+
Whichever name offset is used, it is a pointer to the artist name.
339+
To find the location of the name, add the value of the offset to the address of the start of the artist row itself.
340+
This gives the address of a DeviceSQL string holding the name, with the structure explained in <<devicesql-strings>>.
341+
342+
342343
[#artwork-rows]
343344
=== Artwork Rows
344345

@@ -538,28 +539,50 @@ Tags provide a flexible way for DJs to categorize tracks, supported by the “My
538539
Tags have names, and can be assigned to any number of tracks.
539540
Tags themselves can be grouped into categories, which are stored in the same table.
540541

541-
The rows have the following structure:
542+
Tag rows have the structure shown in <<tag-row-near>> or
543+
<<tag-row-far>>.
544+
The _subtype_ value at bytes{nbsp}``00``-`01` determines which variant is used.footnote:subtype[]
545+
If the tag name is short enough and was allocated close enough to the row to be reached by a single
546+
byte offset, _subtype_ has the value `0680`, and the row has the structure in <<tag-row-near>>
547+
If the name is larger than about 200 bytes or is too far away for that, _subtype_ has the value `0684` and the row has the structure in <<tag-row-far>>
542548

543-
.Tag row.
549+
[#tag-row-near]
550+
.Tag row with nearby name.
544551
[bytefield]
545552
----
546553
(draw-column-headers)
547-
(draw-related-boxes [0x80 0x06])
554+
(draw-box 0x680 {:span 2})
548555
(draw-box (text "tag_index" :math) {:span 2})
549556
(draw-related-boxes (repeat 8 0))
550557
(draw-box (text "category" :math) {:span 4})
551558
(draw-box (text "category_pos" :math) {:span 4})
552559
(draw-box (text "id" :math) {:span 4})
553560
(draw-box (text "raw_is_category" :math) {:span 4})
554-
(draw-related-boxes [0x03 0x1f])
555-
(draw-box (text "flags" :math))
556-
(draw-gap (text "name" :math))
557-
(draw-box 3)
561+
(draw-box 0x03)
562+
(draw-box (text "o" :math [:sub "n"]))
563+
(draw-box (text "o" :math [:sub "u"]))
558564
(draw-bottom)
559565
----
560566

561-
The first two bytes serve an unknown purpose but their values always seem to be the same.
562-
They are followed by __tag_index__ at bytes{nbsp}``02``--``03`` which seems to increment by `20` for each row.
567+
[#tag-row-far]
568+
.Tag row with far name.
569+
[bytefield]
570+
----
571+
(draw-column-headers)
572+
(draw-box 0x684 {:span 2})
573+
(draw-box (text "tag_index" :math) {:span 2})
574+
(draw-related-boxes (repeat 8 0))
575+
(draw-box (text "category" :math) {:span 4})
576+
(draw-box (text "category_pos" :math) {:span 4})
577+
(draw-box (text "id" :math) {:span 4})
578+
(draw-box (text "raw_is_category" :math) {:span 4})
579+
(draw-box 0x03 {:span 2})
580+
(draw-box (text "o" :math [:sub "far"]) {:span 2})
581+
(draw-box (text "o" :math [:sub "ufar"]) {:span 2})
582+
(draw-bottom)
583+
----
584+
585+
__tag_index__ at bytes{nbsp}``02``–`03` seems to increment by `20` for each row.
563586
This is followed by another eight bytes of unknown purpose that always seem to be zero.
564587

565588
The __category__ at bytes{nbsp}``0c``–``0f`` holds the ID of the category to which the tag belongs; if this row is itself a category, this field has the value 0.
@@ -572,7 +595,17 @@ Tags seem to have very large _id_ values, while the four categories have fixed `
572595
The value of __raw_is_category__ at bytes{nbsp}``18``–``1b`` is non-zero when this row stores a tag category instead of a tag.
573596
It is followed by two bytes of unknown purpose that always seem to have the same values, and a byte that may hold some sort of flags that have not yet been understood.
574597

575-
A variable number of bytes starting at byte{nbsp}``1f`` is a <<devicesql-strings,DeviceSQL string>> holding the _name_ of the tag or category. Finally, this is followed by a byte with an unknown purpose, whose value always seems to be 3.
598+
After the __raw_is_category__, the number 3 is always stored, followed by the offset to the name string, and another string offset with unknown purpose.
599+
600+
For subtype `0680`, each of these values take a single byte, and __ofs_name_near__ at byte{nbsp}``1d`` (labeled _o~n~_), is the one-byte name offset.
601+
__ofs_unknown_near__ at byte{nbsp}``1e`` (labeled _o~u~_), is a one-byte offset to what seems to always be an empty string.
602+
603+
For subtype `0684`, each is stored in two bytes, and the two-byte name offset value __ofs_name_far__ (labeled _o~far~_) is found at bytes{nbsp}``1e``–`1f`.
604+
The offset to the unknown (but seemingly always empty) string (labeled _o~ufar~_) takes the final two bytes.
605+
606+
Whichever name offset is used, it is a pointer to the tag name.
607+
To find the location of the name, add the value of the offset to the address of the start of the tag row itself.
608+
This gives the address of a DeviceSQL string holding the name, with the structure explained in <<devicesql-strings>>.
576609

577610
[#tag-track-rows]
578611
=== Tag Track Rows

0 commit comments

Comments
 (0)