1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
|
#------------------------------------------------------------------------------
# $File: map,v 1.10 2023/02/03 20:41:57 christos Exp $
# map: file(1) magic for Map data
#
# Garmin .FIT files https://pub.ks-and-ks.ne.jp/cycling/edge500_fit.shtml
8 string .FIT FIT Map data
>15 byte 0
>>35 belong x \b, unit id %d
>>39 lelong x \b, serial %u
# https://pub.ks-and-ks.ne.jp/cycling/edge500_fit.shtml
# 20 years after unix epoch
# TZ=GMT date -d '1989-12-31 0:00' +%s
>>43 leldate+631065600 x \b, %s
>>47 leshort x \b, manufacturer %d
>>47 leshort 1 \b (garmin)
>>49 leshort x \b, product %d
>>53 byte x \b, type %d
>>53 byte 1 \b (Device)
>>53 byte 2 \b (Settings)
>>53 byte 3 \b (Sports/Cycling)
>>53 byte 4 \b (Activity)
>>53 byte 8 \b (Elevations)
>>53 byte 10 \b (Totals)
# Summary: Garmin map
# From: Joerg Jenderek
# URL: https://en.wikipedia.org/wiki/Garmin_.img
# Reference: https://wiki.openstreetmap.org/wiki/OSM_Map_On_Garmin/IMG_File_Format
# sourceforge.net/projects/garmin-img/files/IMG%20File%20Format/1.0/imgformat-1.0.pdf
# GRR: similar to MBR boot sector handled by ./filesystems
0x1FE leshort =0xAA55
# look for valid map signature
>0x13 string =IMG\0
>>0 use garmin-map
0 name garmin-map
>0 ubyte x Garmin
!:mime application/x-garmin-map
# If non-zero, every byte of the entire .img file is to be XORed with this value
>0 ubyte !0 \b, %#x XORed
# goto block before FAT
>(0x40.b*512) ubyte x
# 1st fat name "DLLINFO TXT" only found for vpm
>>&512 string =DLLINFO\ TXT map (Voice Processing)
# there exist 2 other Garmin VPM formats; see ./audio
!:ext vpm
# Deutsch__Yannick_D4481-00_0210.vpm
#>>>512 search/0x0116da60/s RIFF \b; with
# determine type voice type by ./riff
#>>>>&0 indirect x \b
>>&512 string !DLLINFO\ TXT map
!:ext img
# 9 zeros
>1 ubelong !0 \b, zeroes %#x
# Map's version major
>8 ubyte x v%u
# Map's version minor
>9 ubyte x \b.%.2u
# Map description[20], 0x20 padded
>0x49 string x %.20s
# Map name, continued (0x20 padded, \0 terminated)
>0x65 string >\ \b%.31s
# Update year (+1900 for val >= 0x63, +2000 for val <= 0x62)
>0xB ubyte x \b, updated
>>0xB ubyte >0x62
>>>0xB ubyte-100 x 20%.2u
>>0xB ubyte <0x63
>>>0xB ubyte x 20%.2u
# Update month (0-11)
>0xA ubyte x \b-%.2u
# All zeroes
>0xc uleshort !0 \b, zeroes %#x
# Mapsource flag, 1 - file created by Mapsource, 0 - Garmin map visible in Basecamp and Homeport
#>0xE ubyte !0 \b, Mapsource flag %#x
>0xE ubyte 1 \b, Mapsource
# Checksum, sum of all bytes modulo 256 should be 0
#>0xF ubyte x \b, Checksum %#x
# Signature: DSKIMG 0x00 or DSDIMG 0x00 for demo map
>0x10 string !DSKIMG \b, signature "%.7s"
>0x39 use garmin-date
# Map file identifier like GARMIN\0
>0x41 string !GARMIN \b, id "%.7s"
# Block size exponent, E1; appears to always be 0x09; minimum block size 512 bytes
>0x61 ubyte !0x09 \b, E1=%u
# Block size exponent, E2 ; file blocksize=2**(E1+E2)
>>0x62 ubyte x \b, E2=%u
>0x61 ubyte =0x09 \b, blocksize
>>0x62 ubyte 0 512
>>0x62 ubyte 1 1024
>>0x62 ubyte 2 2048
>>0x62 ubyte 3 4096
>>0x62 ubyte 4 8192
>>0x62 ubyte 5 16384
>>0x62 default x
>>>0x62 ubyte x E2=%u
# MBR signature
>0x1FE leshort !0xAA55 \b, invalid MBR
# 512 zeros
>0x200 uquad !0 \b, zeroes %#llx
# First sub-file offset (absolute); sometimes NO/UNKNOWN sub file!
>0x40C ulelong >0 \b, at %#x
# sub-file Header length
#>>(0x40C.l) uleshort x \b, header len %#x
>>(0x40C.l) uleshort x %u bytes
# sub-file Type[10] like "GARMIN RGN" "GARMIN TRE", "GARMIN TYP", etc.
>>(0x40C.l+2) ubyte >0x1F
>>>(0x40C.l+2) ubyte <0xFF
>>>>(0x40C.l+2) string x "%.10s"
# 0x00 for most maps, 0x80 for locked maps (City Nav, City Select, etc.)
>>>>(0x40C.l+13) ubyte >0 \b, locked %#x
# Block sequence numbers like 0000 0100 0200 ... FFFF
# >0x420 ubequad >0 \b, seq. %#16.16llx
# >>0x428 ubequad >0 \b%16.16llx
# >>>0x430 ubequad >0 \b%16.16llx
# >>>>0x438 ubequad >0 \b%16.16llx
# >>>>>0x440 ubequad >0 \b%16.16llx
# >>>>>>0x448 ubequad >0 \b%16.16llx
# >>>>>>>0x450 ubequad >0 \b%16.16llx
# >>>>>>>>0x458 ubequad >0 \b%16.16llx
# >>>>>>>>>0x460 ubequad >0 \b%16.16llx
# >>>>>>>>>>0x468 ubequad >0 \b%16.16llx
# >>>>>>>>>>>0x470 ubequad >0 \b%16.16llx
# >>>>>>>>>>>>0x478 ubequad >0 \b%16.16llx
# >>>>>>>>>>>>>0x480 ubequad >0 \b%16.16llx
# >>>>>>>>>>>>>>0x488 ubequad >0 \b%16.16llx
# >>>>>>>>>>>>>>>0x490 ubequad >0 \b%16.16llx
# >>>>>>>>>>>>>>>>0x498 ubequad >0 \b%16.16llx
# >>>>>>>>>>>>>>>>>0x4A0 ubequad >0 \b%16.16llx
# >>>>>>>>>>>>>>>>>>0x4A8 ubequad >0 \b%16.16llx
# look for end of FAT
#>>0x420 search/512/s \xff\xff FAT END
# Physical block number of FAT header
#>0x40 ubyte x \b, FAT at phy. block %u
>0x40 ubyte x
>>(0x40.b*512) ubyte x
# 1st FAT block
>>>&511 use garmin-fat
# 2nd FAT block
>>>&1023 use garmin-fat
# 3th FAT block
>>>&1535 use garmin-fat
# 4th FAT block
>>>&2047 use garmin-fat
# ... xth FAT block
#
# 314 zeros but not in vpm and also gmaptz.img
>0x84 uquad !0 \b, at 0x84 %#llx
# display FileAllocationTable block entry in garmin map
0 name garmin-fat
>0 ubyte x \b;
# sub file part; 0x0003 seems to be garbage
>0x10 uleshort !0 next %#4.4x
>0x10 uleshort =0
# fat flag 0~dummy block 1~true sub file
>>0 ubyte !1 flag %u
>>0 ubyte =1
# sub-file name like MAKEGMAP 12345678
>>>0x1 string x %.8s
# sub-file typ like RGN TRE MDR LBL
>>>0x9 string x \b.%.3s
# size of sub file
>>>0xC ulelong x \b, %u bytes
# 32-bit block sequence numbers
#>>>0x20 ubequad x \b, seq. %#16.16llx
# display date stored inside Garmin maps like yyyy-mm-dd h:mm:ss
0 name garmin-date
# year like 2018
>0 uleshort x \b, created %u
# month (0-11)
>2 ubyte x \b-%.2u
# day (1-31)
>3 ubyte x \b-%.2u
# hour (0-23)
>4 ubyte x %u
# minute (0-59)
>5 ubyte x \b:%.2u
# second (0-59)
>6 ubyte x \b:%.2u
# Summary: Garmin Map subfiles
# From: Joerg Jenderek
# URL: https://wiki.openstreetmap.org/wiki/OSM_Map_On_Garmin/IMG_File_Format
# Garmin Common Header
2 string GARMIN\
# skip ASCII text by checking for low header length
>0 uleshort <0x1000 Garmin map,
# URL: https://wiki.openstreetmap.org/wiki/OSM_Map_On_Garmin/GMP_Subfile_Format
>>9 string GMP subtile
!:mime application/x-garmin-gpm
!:ext gmp
# copyright message
>>>(0.s) string x %s
>>>0x0E use garmin-date
# URL: https://wiki.openstreetmap.org/wiki/OSM_Map_On_Garmin/MDR_Subfile_Format
# This contains the searchable address table used for finding routing destinations
>>9 string MDR address table
!:mime application/x-garmin-mdr
!:ext mdr
# URL: https://wiki.openstreetmap.org/wiki/OSM_Map_On_Garmin/NOD_Subfile_Format
# http://svn.parabola.me.uk/display/trunk/doc/nod.txt
# This contains the routing information
>>9 string NOD routing
!:mime application/x-garmin-nod
!:ext nod
>>>0x0E use garmin-date
#>>>0x15 ulelong x \b, at %#x
#>>>0x19 ulelong x %#x bytes NOD1
#>>>0x25 ulelong x \b, at %#x
#>>>0x29 ulelong x %#x bytes NOD2
#>>>0x31 ulelong x \b, at %#x
#>>>0x35 ulelong x %#x bytes NOD3
# URL: http://www.pinns.co.uk/osm/net.html
# routable highways (length, direction, allowed speed,house address information)
>>9 string NET highways
!:mime application/x-garmin-net
!:ext net
#>>>0x15 ulelong x \b, at %#x
#>>>0x19 ulelong x %#x bytes NET1
#>>>0x22 ulelong >0
#>>>>0x1E ulelong x \b, at %#x
#>>>>0x22 ulelong x %#x bytes NET2
#>>>0x2B ulelong >0
#>>>>0x27 ulelong x \b, at %#x
#>>>>0x2B ulelong x %#x bytes NET3
# URL: https://wiki.openstreetmap.org/wiki/OSM_Map_On_Garmin/LBL_Subfile_Format
>>9 string LBL labels
!:mime application/x-garmin-lbl
!:ext lbl
>>>(0.s) string x %s
# Label coding type 6h 9h and ah
>>>0x1E ubyte x \b, coding type %#x
#>>>0x15 ulelong x \b, at %#x
#>>>0x19 ulelong x %#x bytes LBL1
#>>>0x1F ulelong x \b, at %#x
#>>>0x23 ulelong x %#x bytes LBL2
#>>>0x2D ulelong x \b, at %#x
#>>>0x31 ulelong x %#x bytes LBL3
# URL: https://wiki.openstreetmap.org/wiki/OSM_Map_On_Garmin/SRT_Subfile_Format
# A lookup table of the chars in the map's codepage, and their collating sequence
>>9 string SRT sort table
!:mime application/x-garmin-srt
!:ext srt
>>>0x0E use garmin-date
# URL: https://wiki.openstreetmap.org/wiki/OSM_Map_On_Garmin/TRE_Subfile_Format
>>9 string TRE tree
!:mime application/x-garmin-tre
!:ext tre
# title like City Nav Europe NTU 2019.2 Basemap
# or OSM Street map
>>>(0.s) string x %s
# 2nd title like Copyright 1995-2018 by GARMIN Corporation.
# or http://www.openstreetmap.org/
>>>>&1 string x %s
>>>0x0E use garmin-date
#>>>0x21 ulelong x \b, at %#x
#>>>0x25 ulelong x %#x bytes TRE1
#>>>0x29 ulelong x \b, at %#x
#>>>0x2D ulelong x %#x bytes TRE2
#>>>0x31 ulelong x \b, at %#x
#>>>0x35 ulelong x %#x bytes TRE3
# Copyright record size
#>>>0x39 uleshort x \b, copyright record size %u
# Map ID
>>>0x74 ulelong x \b, ID %#x
# URL: https://www.gpspower.net/garmin-tutorials/353310-basecamp-installing-free-desktop-map.html
# For road traffic information service (RDS/TMS/TMC). Commonly seen in City Navigator maps
>>9 string TRF traffic,
!:mime application/x-garmin-trf
!:ext trf
# city/region like Preitenegg
>>>(0.s+1) string x 1st %s
# highway part like L606/L148
>>>>&1 string x %s
# URL: https://wiki.openstreetmap.org/wiki/OSM_Map_On_Garmin/Format
# Reference: http://www.pinns.co.uk/osm/typformat.html
# customize the appearance of objects. For GPS and MapSource/Qlandkarte better looking maps
>>9 string TYP types
!:mime application/x-garmin-typ
!:ext typ
>>>0x0E use garmin-date
# character set 1252 65001~UTF8
>>>0x15 uleshort x \b, code page %u
# POIs
#>>>0x17 ulelong x \b, at %#x
#>>>0x1B ulelong x %#x bytes TYP1
# extra pois
#>>>0x5B ulelong x \b, at %#x
#>>>0x5F ulelong x %#x bytes TYP8
# URL: https://wiki.openstreetmap.org/wiki/OSM_Map_On_Garmin/RGN_Subfile_Format
# http://www.pinns.co.uk/osm/RGN.html
# region data used by the Garmin software
>>9 string RGN region
!:mime application/x-garmin-rgn
!:ext rgn
# POIs,Indexed POIs,Polylines or Polygons or first map level
#>>>0x15 ulelong x \b, at %#x
#>>>0x19 ulelong x %#x bytes RGN1
# polygons with extended types
#>>>0x21 ulelong >0
#>>>>0x1D ulelong x \b, at %#x
#>>>>0x21 ulelong x %#x bytes RGN2
# polylines with extended types
#>>>0x3D ulelong >0
#>>>>0x39 ulelong x \b, at %#x
#>>>>0x3D ulelong x %#x bytes RGN3
# extended POIs
#>>>0x59 ulelong >0
#>>>>0x55 ulelong x \b, at %#x
#>>>>0x59 ulelong x %#x bytes RGN3
#>>9 default x unknown map type
# Header length; GMP:31h 35h 3Dh,MDR:11Eh 238h 2C4h 310h,NOD:3Fh 7Fh,NET:64h,
# LBL:2A9h,SRT:1Dh 25h 27h,TRE:CFh 135h,TRF:5Ah,TYP:5Bh 6Eh 7Ch AEh,RGN:7Dh
>>0 uleshort x \b, header length %#x
# URL: https://www.memotech.franken.de/FileFormats/
# Reference: https://www.memotech.franken.de/FileFormats/Garmin_RGN_Format.pdf
# From: Joerg Jenderek
0 string KpGr Garmin update
# format version like: 0064h~1.0
>0x4 uleshort !0x0064
>>4 uleshort/100 x \b, version %u
>>4 uleshort%100 x \b.%u
# 1st Garmin entry
>6 use garmin-entry
# 2nd Garmin entry
>(0x6.l+10) ubyte x
>>&0 use garmin-entry
# 3rd entry
>(0x6.l+10) ubyte x
>>&(&0.l+4) ubyte x
>>>&0 use garmin-entry
# look again at version to use default clause
>0x4 uleshort x
# test for region content by looking for
# Garmin *.srf by ./images with normal builder name "SQA" or longer "hales"
# 1 space after equal sign
>>0x3a search/5/s GARMIN\ BITMAP \b=
!:mime image/x-garmin-exe
!:ext exe
>>>&0 indirect x
# if not bitmap *.srf then region; 1 space after equal sign
>>0x3a default x \b=
!:mime application/x-garmin-rgn
!:ext rgn
# recursiv embedded
>>>0x3a search/5/s KpGrd
>>>>&0 indirect x
# look for ZIP or JAR archive by ./archive and ./zip
>>>0x3a search/5/s PK\003\004
>>>>&0 indirect x
# TODO: other garmin RGN record content like foo
#>>0x3a search/5/s bar BAR
# display information of Garmin RGN record
0 name garmin-entry
# record length: 2 for Data, for Application often 1Bh sometimes 1Dh, "big" for Region
#>0 ulelong x \b, length %#x
# data record (ID='D') with version content like 0064h~1.0
>4 ubyte =0x44
>>5 uleshort !0x0064 \b; Data
>>>5 uleshort/100 x \b, version %u
>>>5 uleshort%100 x \b.%u
# Application Record (ID='A')
>4 ubyte =0x41 \b; App
# version content like 00c8h~2.0
>>5 uleshort !0x00C8
>>>5 uleshort/100 x \b, version %u
>>>5 uleshort%100 x \b.%u
# builder name like: SQA sqa build hales
>>7 string x \b, build by %s
# build date like: Oct 25 1999, Oct 1 2008, Feb 23 2009, Dec 15 2009
>>>&1 string x %s
# build time like: 11:26:12, 11:45:54, 14:16:13, 18:23:01
>>>>&1 string x %s
# region record (ID='R')
>4 ubyte =0x52 \b; Region
# region ID:14~fw_all.bin: 78~ZIP, RGN or SRF bitmap; 148~ZIP or JAR; 249~display firmware; 251~WiFi or GCD firmware; 255~ZIP
>>5 uleshort x ID=%u
# delay in ms: like 0, 500
>>7 ulelong !0 \b, %u ms
# region size (is record length - 10)
#>>11 ulelong x \b, length %#x
# region content like:
# "KpGr"~recursiv embedded,"GARMIN BITMAP"~Garmin Bitmap *.srf, "PK"~ZIP archive
#>>15 string x \b, content "%s"
>>15 ubequad x \b, content %#llx...
# This does NOT WORK!
#>>15 indirect x \b; contains
>4 default x \b; other
# garmin Record ID Identifies the record content like: D A R
>>4 ubyte x ID '%c'
# TOM TOM GPS watches ttbin files:
# https://github.com/ryanbinns/ttwatch/tree/master/ttbin
# From: Daniel Lenski
0 byte 0x20
>1 leshort 0x0007
>>0x76 byte 0x20
>>>0x77 leshort 0x0075 TomTom activity file, v7
>>>>8 leldate x (%s,
>>>>3 byte x device firmware %d.
>>>>4 byte x \b%d.
>>>>5 byte x \b%d,
>>>>6 leshort x product ID %04d)
# Garmin firmware:
# https://www.memotech.franken.de/FileFormats/Garmin_GCD_Format.pdf
# https://www.gpsrchive.com/GPSMAP/GPSMAP%2066sr/Firmware.html
0 string GARMIN
>6 uleshort 100 GARMIN firmware (version 1.0)
|