code wiki / _hdl_build / nx_mobi_fixture_build.nx
nx_mobi_fixture_build.nx source
↩ module page · 298 lines · 20650 B
1// nx_mobi_fixture_build.nx -- build a DRM-free MOBI (Kindle) fixture sovereignly, so the MOBI reader rung can be
2// gated end-to-end against the REAL on-disk format (PDB container + PalmDOC-compressed text + EXTH metadata),
3// the way nx_epub_fixture_build gives the EPUB rungs a controlled real EPUB. Also writes a DRM-FLAGGED variant
4// (encryptionType=2) so the reader's "detect + DECLINE DRM" path is gated (we read DRM-FREE files; we never
5// circumvent DRM). Structure: 78-byte PDB header + 2 record-info entries + record0 (PalmDOC hdr + minimal MOBI
6// hdr + EXTH author/title) + record1 (PalmDOC-compressed XHTML). expect_exit: 0 license_tier: ORIGINAL
7import "nx_syscalls.nx"
8import "nx_palmdoc.nx"
9const K_MAGIC_262144: i64 = 262144
10const K_MAGIC_4096: i64 = 4096
11const K_MAGIC_65001: i64 = 65001
12const K_MAGIC_17480: i64 = 17480
13const K_MAGIC_1040: i64 = 1040
14const K_MAGIC_1296: i64 = 1296
15
16func mf_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
17func mf_p(s: *u8) -> i64 { sys_write(1, s, mf_slen(s)); return 0 }
18func mf_n(v: i64) -> i64 { let b: *u8=sys_mmap(24); var m: i64=v; if m<0{m=0-m}; let t: *u8=sys_mmap(24); var k: i64=0; if m==0{t[0]=48 as u8;k=1}; while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1}; var i: i64=0; while i<k{b[i]=t[k-1-i];i=i+1}; sys_write(1,b,k); return 0 }
19func ensure_dir(path: *u8) -> i64 { __syscall(258, 0-100, path, 0x1ed, 0, 0, 0); return 0 }
20
21func put16(m: *u8, o: i64, v: i64) -> i64 { m[o]=((v>>8)&0xff) as u8; m[o+1]=(v&0xff) as u8; return o+2 }
22func put32(m: *u8, o: i64, v: i64) -> i64 { m[o]=((v>>24)&0xff) as u8; m[o+1]=((v>>16)&0xff) as u8; m[o+2]=((v>>8)&0xff) as u8; m[o+3]=(v&0xff) as u8; return o+4 }
23func puts(m: *u8, o: i64, s: *u8) -> i64 { var i: i64=0; while s[i]!=(0 as u8){ m[o+i]=s[i]; i=i+1 } return o+i }
24
25func main() -> i64 {
26 ensure_dir("knowledge/fixtures" as *u8)
27 let html: *u8 = "<html><head></head><body><h1>The Liberation of Alice</h1><p>Alice was beginning to get very tired of sitting by her sister on the bank. Alice was beginning to get very tired of sitting by her sister on the bank.</p><p>So she was considering in her own mind whether the pleasure of making a daisy chain would be worth the trouble of getting up and picking the daisies, when suddenly a White Rabbit ran close by her.</p></body></html>" as *u8
28 let htmln: i64 = mf_slen(html)
29
30 let m: *u8 = sys_mmap(K_MAGIC_262144)
31 // ---- PDB header (78 bytes); mmap is zero-filled so unset fields stay 0 ----
32 puts(m, 0, "Liberation Fixture" as *u8) // database name (<=31 chars)
33 puts(m, 60, "BOOK" as *u8) // type
34 puts(m, 64, "MOBI" as *u8) // creator
35 put16(m, 76, 2) // numRecords = 2
36 let list0: i64 = 78 // record-info entry 0 (offset field, backpatched)
37 let list1: i64 = 86 // record-info entry 1
38 // 2-byte gap at 94; records start at 96
39 var o: i64 = 96
40 let rec0: i64 = o
41
42 // ---- record 0: PalmDOC header (16) ----
43 o = put16(m, o, 2) // compression = 2 (PalmDOC)
44 o = put16(m, o, 0) // unused
45 o = put32(m, o, htmln) // textLength (uncompressed)
46 o = put16(m, o, 1) // text record count = 1
47 o = put16(m, o, K_MAGIC_4096) // record size
48 let enc_pos: i64 = o
49 o = put16(m, o, 0) // encryptionType = 0 (NO DRM)
50 o = put16(m, o, 0) // unused
51 // ---- minimal MOBI header ----
52 o = puts(m, o, "MOBI" as *u8)
53 o = put32(m, o, 24) // header length
54 o = put32(m, o, 2) // mobi type = book
55 o = put32(m, o, K_MAGIC_65001) // text encoding = UTF-8
56 o = put32(m, o, 1) // unique id
57 o = put32(m, o, 6) // file version
58 // ---- EXTH block (author + title) ----
59 let exth: i64 = o
60 o = puts(m, o, "EXTH" as *u8)
61 let exthlen_pos: i64 = o
62 o = put32(m, o, 0) // header length placeholder
63 o = put32(m, o, 2) // record count = 2
64 let auth: *u8 = "Lewis Carroll" as *u8; let authn: i64 = mf_slen(auth)
65 o = put32(m, o, 100); o = put32(m, o, 8 + authn); o = puts(m, o, auth) // EXTH 100 = author
66 let titl: *u8 = "The Liberation of Alice" as *u8; let titln: i64 = mf_slen(titl)
67 o = put32(m, o, 503); o = put32(m, o, 8 + titln); o = puts(m, o, titl) // EXTH 503 = title
68 var exthlen: i64 = o - exth
69 while (exthlen % 4) != 0 { m[o]=0 as u8; o=o+1; exthlen=exthlen+1 }
70 put32(m, exthlen_pos, exthlen)
71 while (o % 4) != 0 { m[o]=0 as u8; o=o+1 } // pad record 0 to 4-byte boundary
72
73 // ---- record 1: PalmDOC-compressed XHTML ----
74 let rec1: i64 = o
75 let cn: i64 = palmdoc_compress(html, htmln, (m as i64 + o) as *u8, K_MAGIC_262144 - o)
76 o = o + cn
77
78 // backpatch the record-info offsets
79 put32(m, list0, rec0)
80 put32(m, list1, rec1)
81
82 let fd: i64 = sys_openat_wr("knowledge/fixtures/nishi_mobi_fixture.mobi" as *u8, 0x1a4)
83 if fd < 0 { mf_p("MOBI-FIXTURE-FAIL open\n" as *u8); sys_exit(1); return 1 }
84 sys_write(fd, m, o); sys_close(fd)
85
86 // DRM-flagged variant (encryptionType=2) for the reader's detect+decline gate
87 put16(m, enc_pos, 2)
88 let fd2: i64 = sys_openat_wr("knowledge/fixtures/nishi_mobi_drm.mobi" as *u8, 0x1a4)
89 if fd2 >= 0 { sys_write(fd2, m, o); sys_close(fd2) }
90
91 mf_p("MOBI-FIXTURE bytes=" as *u8); mf_n(o); mf_p(" htmln=" as *u8); mf_n(htmln); mf_p(" compressed_rec1=" as *u8); mf_n(cn)
92 mf_p(" -> knowledge/fixtures/nishi_mobi_fixture.mobi (+ _drm variant)\n" as *u8)
93
94 // ---- HUFF/CDIC variant: nishi_mobi_huff.mobi (compression 17480) ----
95 // 4 PDB records: rec0=PalmDOC+MOBI hdr (Huffman Record Offset/Count at MOBI+0x70/0x74) + EXTH;
96 // rec1=HUFF stream (codelen-1: 256 dict1 entries all 0x181 -> bit'1'=>phrase0, bit'0'=>phrase1; 0x80 =>
97 // phrase0 + phrase1*7); rec2=HUFF record; rec3=CDIC (phrase0/1 = HTML fragments). This is the MINIMAL Huffman
98 // case (all-terminal codelen-1) -- it gates the 17480 pipeline end-to-end; real multi-codelen Kindle HUFF
99 // needs a real DRM-free file (no open HUFF encoder exists -- Calibre/KindleUnpack only DECODE HUFF).
100 let h: *u8 = sys_mmap(K_MAGIC_262144)
101 let p0: *u8 = "<html><body><p>Alice was beginning to get very tired.</p>" as *u8; let p0n: i64 = mf_slen(p0)
102 let p1: *u8 = "<p>So a White Rabbit ran close by her.</p>" as *u8; let p1n: i64 = mf_slen(p1)
103 puts(h, 0, "Liberation HUFF" as *u8)
104 puts(h, 60, "BOOK" as *u8); puts(h, 64, "MOBI" as *u8)
105 put16(h, 76, 4) // numRecords = 4
106 let hrec0: i64 = 112 // 78 + 4*8 + 2-byte gap
107 var ho: i64 = hrec0
108 ho = put16(h, ho, K_MAGIC_17480) // compression = HUFF/CDIC
109 ho = put16(h, ho, 0)
110 ho = put32(h, ho, p0n + p1n*7) // uncompressed textLength
111 ho = put16(h, ho, 1) // text record count = 1
112 ho = put16(h, ho, K_MAGIC_4096)
113 let henc_pos: i64 = ho
114 ho = put16(h, ho, 0) // encryptionType = 0 (NO DRM)
115 ho = put16(h, ho, 0)
116 let mobistart: i64 = ho // == hrec0 + 16
117 puts(h, mobistart, "MOBI" as *u8)
118 put32(h, mobistart + 4, 232) // MOBI header length
119 put32(h, mobistart + 8, 2) // mobi type = book
120 put32(h, mobistart + 12, K_MAGIC_65001) // text encoding UTF-8
121 put32(h, mobistart + 16, 1) // unique id
122 put32(h, mobistart + 20, 6) // file version
123 put32(h, mobistart + 96, 2) // Huffman Record Offset (record-0 0x70 = MOBI-hdr +96) = PDB record 2
124 put32(h, mobistart + 100, 2) // Huffman Record Count (record-0 0x74 = MOBI-hdr +100) = 2 (HUFF + CDIC)
125 ho = mobistart + 232
126 let hexth: i64 = ho
127 ho = puts(h, ho, "EXTH" as *u8)
128 let hexthlen_pos: i64 = ho
129 ho = put32(h, ho, 0); ho = put32(h, ho, 2) // header-length placeholder + record count
130 ho = put32(h, ho, 100); ho = put32(h, ho, 8 + authn); ho = puts(h, ho, auth)
131 ho = put32(h, ho, 503); ho = put32(h, ho, 8 + titln); ho = puts(h, ho, titl)
132 var hexthlen: i64 = ho - hexth
133 while (hexthlen % 4) != 0 { h[ho]=0 as u8; ho=ho+1; hexthlen=hexthlen+1 }
134 put32(h, hexthlen_pos, hexthlen)
135 while (ho % 4) != 0 { h[ho]=0 as u8; ho=ho+1 }
136 let hrec1: i64 = ho // rec1: the HUFF-compressed text stream
137 h[ho] = 0x80 as u8; ho = ho + 1
138 while (ho % 4) != 0 { h[ho]=0 as u8; ho=ho+1 }
139 let hrec2: i64 = ho // rec2: HUFF record (magic + off1/off2 + dict1[256] + dict2[64])
140 puts(h, ho, "HUFF" as *u8); h[ho+4]=0 as u8; h[ho+5]=0 as u8; h[ho+6]=0 as u8; h[ho+7]=0x18 as u8
141 put32(h, ho+8, 16); put32(h, ho+12, 16 + 256*4)
142 var di: i64 = 0; while di < 256 { put32(h, ho+16+di*4, 0x181); di=di+1 } // codelen1, term, maxcode-raw 1
143 di = 0; while di < 64 { put32(h, ho+K_MAGIC_1040+di*4, 0); di=di+1 } // dict2 zero (term path)
144 ho = ho + K_MAGIC_1296
145 let hrec3: i64 = ho // rec3: CDIC record (2 terminal phrases)
146 puts(h, ho, "CDIC" as *u8); h[ho+4]=0 as u8; h[ho+5]=0 as u8; h[ho+6]=0 as u8; h[ho+7]=0x10 as u8
147 put32(h, ho+8, 2); put32(h, ho+12, 1) // phrases=2, bits=1
148 put16(h, ho+16, 4) // off[0] = 4 (phrase0 header at cdic+20)
149 put16(h, ho+18, 6 + p0n) // off[1] = 6+p0n
150 put16(h, ho+20, 0x8000 + p0n); puts(h, ho+22, p0) // phrase0: terminal | len, bytes
151 put16(h, ho+22+p0n, 0x8000 + p1n); puts(h, ho+24+p0n, p1) // phrase1
152 ho = ho + 24 + p0n + p1n
153 put32(h, 78, hrec0); put32(h, 86, hrec1); put32(h, 94, hrec2); put32(h, 102, hrec3)
154 let fdh: i64 = sys_openat_wr("knowledge/fixtures/nishi_mobi_huff.mobi" as *u8, 0x1a4)
155 if fdh >= 0 { sys_write(fdh, h, ho); sys_close(fdh) }
156 mf_p("MOBI-HUFF-FIXTURE bytes=" as *u8); mf_n(ho); mf_p(" rec1@" as *u8); mf_n(hrec1); mf_p(" huff@" as *u8); mf_n(hrec2); mf_p(" cdic@" as *u8); mf_n(hrec3)
157 mf_p(" -> knowledge/fixtures/nishi_mobi_huff.mobi\n" as *u8)
158
159 // ---- COVER variant: nishi_mobi_cover.mobi (PalmDOC text + an EMBEDDED cover image record) ----
160 // 3 PDB records: rec0=PalmDOC hdr + extended MOBI hdr (First Image index @ MOBI-hdr 0x6c=+92 -> PDB record 2) +
161 // EXTH (author/title + 201 coveroffset=0); rec1=PalmDOC text; rec2=a real 35-byte opaque GIF cover. This gates the
162 // reader EXTRACTING the cover out of the file ITSELF (offline, no download) -- how Calibre gets the cover.
163 let c: *u8 = sys_mmap(K_MAGIC_262144)
164 puts(c, 0, "Liberation Cover" as *u8)
165 puts(c, 60, "BOOK" as *u8); puts(c, 64, "MOBI" as *u8)
166 put16(c, 76, 3) // numRecords = 3
167 let crec0: i64 = 78 + 3*8 + 2 // record-info list (3*8) + 2-byte gap -> records start at 104
168 var co: i64 = crec0
169 co = put16(c, co, 2) // compression = PalmDOC
170 co = put16(c, co, 0)
171 co = put32(c, co, htmln) // textLength (uncompressed)
172 co = put16(c, co, 1) // text record count = 1
173 co = put16(c, co, K_MAGIC_4096)
174 co = put16(c, co, 0) // encryptionType = 0 (NO DRM)
175 co = put16(c, co, 0)
176 let cmobi: i64 = co // == crec0 + 16, MOBI header start
177 puts(c, cmobi, "MOBI" as *u8)
178 put32(c, cmobi + 4, 96) // MOBI header length = 96 (large enough to hold First Image index @ +92)
179 put32(c, cmobi + 8, 2) // mobi type = book
180 put32(c, cmobi + 12, K_MAGIC_65001) // text encoding UTF-8
181 put32(c, cmobi + 16, 1) // unique id
182 put32(c, cmobi + 20, 6) // file version
183 put32(c, cmobi + 92, 2) // First Image index (MOBI-hdr 0x6c = +92) = PDB record 2 (the cover)
184 co = cmobi + 96
185 let cexth: i64 = co
186 co = puts(c, co, "EXTH" as *u8)
187 let cexthlen_pos: i64 = co
188 co = put32(c, co, 0); co = put32(c, co, 6) // header-length placeholder + record count = 6
189 co = put32(c, co, 100); co = put32(c, co, 8 + authn); co = puts(c, co, auth)
190 co = put32(c, co, 503); co = put32(c, co, 8 + titln); co = puts(c, co, titl)
191 let pubr: *u8 = "Nishi Press" as *u8; let pubrn: i64 = mf_slen(pubr)
192 co = put32(c, co, 101); co = put32(c, co, 8 + pubrn); co = puts(c, co, pubr) // EXTH 101 publisher
193 let pdate: *u8 = "2026-06-23" as *u8; let pdaten: i64 = mf_slen(pdate)
194 co = put32(c, co, 106); co = put32(c, co, 8 + pdaten); co = puts(c, co, pdate) // EXTH 106 publishing date
195 let pdesc: *u8 = "<p>A <i>sample</i> liberation and cover demo.</p>" as *u8; let pdescn: i64 = mf_slen(pdesc)
196 co = put32(c, co, 103); co = put32(c, co, 8 + pdescn); co = puts(c, co, pdesc) // EXTH 103 description (HTML)
197 co = put32(c, co, 201); co = put32(c, co, 12); co = put32(c, co, 0) // EXTH 201 coveroffset = 0 -> cover at First Image index
198 var cexthlen: i64 = co - cexth
199 while (cexthlen % 4) != 0 { c[co]=0 as u8; co=co+1; cexthlen=cexthlen+1 }
200 put32(c, cexthlen_pos, cexthlen)
201 while (co % 4) != 0 { c[co]=0 as u8; co=co+1 }
202 let crec1: i64 = co // rec1: PalmDOC-compressed text
203 let ccn: i64 = palmdoc_compress(html, htmln, (c as i64 + co) as *u8, K_MAGIC_262144 - co)
204 co = co + ccn
205 while (co % 4) != 0 { c[co]=0 as u8; co=co+1 }
206 let crec2: i64 = co // rec2: the cover image (35-byte opaque 1x1 GIF, color 0 = navy 1a2238)
207 let g: *u8 = (c as i64 + co) as *u8
208 g[0]=0x47 as u8; g[1]=0x49 as u8; g[2]=0x46 as u8; g[3]=0x38 as u8; g[4]=0x39 as u8; g[5]=0x61 as u8 // "GIF89a"
209 g[6]=0x01 as u8; g[7]=0x00 as u8; g[8]=0x01 as u8; g[9]=0x00 as u8 // 1x1
210 g[10]=0x80 as u8; g[11]=0x00 as u8; g[12]=0x00 as u8 // GCT present (2 colors)
211 g[13]=0x1a as u8; g[14]=0x22 as u8; g[15]=0x38 as u8 // color 0 = navy
212 g[16]=0xff as u8; g[17]=0xff as u8; g[18]=0xff as u8 // color 1 = white
213 g[19]=0x2c as u8; g[20]=0x00 as u8; g[21]=0x00 as u8; g[22]=0x00 as u8; g[23]=0x00 as u8; g[24]=0x01 as u8; g[25]=0x00 as u8; g[26]=0x01 as u8; g[27]=0x00 as u8; g[28]=0x00 as u8 // image descriptor 1x1
214 g[29]=0x02 as u8; g[30]=0x02 as u8; g[31]=0x44 as u8; g[32]=0x01 as u8; g[33]=0x00 as u8 // LZW: min-code 2, one pixel (idx 0)
215 g[34]=0x3b as u8 // trailer
216 co = co + 35
217 put32(c, 78, crec0); put32(c, 86, crec1); put32(c, 94, crec2)
218 let fdc: i64 = sys_openat_wr("knowledge/fixtures/nishi_mobi_cover.mobi" as *u8, 0x1a4)
219 if fdc >= 0 { sys_write(fdc, c, co); sys_close(fdc) }
220 mf_p("MOBI-COVER-FIXTURE bytes=" as *u8); mf_n(co); mf_p(" rec2(cover)@" as *u8); mf_n(crec2); mf_p(" gif=35B -> knowledge/fixtures/nishi_mobi_cover.mobi\n" as *u8)
221
222 // ---- CHAPTERS variant: nishi_mobi_chapters.mobi (PalmDOC; 3 chapters via <mbp:pagebreak> -> real navigable TOC) ----
223 let chtml: *u8 = "<html><body><h1>Chapter One</h1><p>In the beginning Alice fell down the rabbit hole and kept falling for a very long time indeed.</p><mbp:pagebreak/><h1>Chapter Two</h1><p>The White Rabbit checked his pocket watch nervously and hurried along the winding path.</p><mbp:pagebreak/><h1>Chapter Three</h1><p>At the tea party the Mad Hatter poured more tea and offered Alice a seat by the window.</p></body></html>" as *u8
224 let chtmln: i64 = mf_slen(chtml)
225 let ch: *u8 = sys_mmap(K_MAGIC_262144)
226 puts(ch, 0, "Chapters Fixture" as *u8)
227 puts(ch, 60, "BOOK" as *u8); puts(ch, 64, "MOBI" as *u8)
228 put16(ch, 76, 2) // numRecords = 2
229 var cho: i64 = 96 // 78 + 2*8 + 2-byte gap
230 let chrec0: i64 = cho
231 cho = put16(ch, cho, 2) // compression = PalmDOC
232 cho = put16(ch, cho, 0)
233 cho = put32(ch, cho, chtmln) // textLength
234 cho = put16(ch, cho, 1) // text record count = 1
235 cho = put16(ch, cho, K_MAGIC_4096)
236 cho = put16(ch, cho, 0) // encryptionType = 0
237 cho = put16(ch, cho, 0)
238 cho = puts(ch, cho, "MOBI" as *u8)
239 cho = put32(ch, cho, 24) // MOBI header length
240 cho = put32(ch, cho, 2) // mobi type = book
241 cho = put32(ch, cho, K_MAGIC_65001) // UTF-8
242 cho = put32(ch, cho, 1) // unique id
243 cho = put32(ch, cho, 6) // file version
244 let chexth: i64 = cho
245 cho = puts(ch, cho, "EXTH" as *u8)
246 let chexthlen_pos: i64 = cho
247 cho = put32(ch, cho, 0); cho = put32(ch, cho, 2) // hdr-len placeholder + record count = 2
248 cho = put32(ch, cho, 100); cho = put32(ch, cho, 8 + authn); cho = puts(ch, cho, auth)
249 let chtitl: *u8 = "Three-Chapter Demo" as *u8; let chtitln: i64 = mf_slen(chtitl)
250 cho = put32(ch, cho, 503); cho = put32(ch, cho, 8 + chtitln); cho = puts(ch, cho, chtitl)
251 var chexthlen: i64 = cho - chexth
252 while (chexthlen % 4) != 0 { ch[cho]=0 as u8; cho=cho+1; chexthlen=chexthlen+1 }
253 put32(ch, chexthlen_pos, chexthlen)
254 while (cho % 4) != 0 { ch[cho]=0 as u8; cho=cho+1 }
255 let chrec1: i64 = cho
256 let chcn: i64 = palmdoc_compress(chtml, chtmln, (ch as i64 + cho) as *u8, K_MAGIC_262144 - cho)
257 cho = cho + chcn
258 put32(ch, 78, chrec0); put32(ch, 86, chrec1)
259 let fdch: i64 = sys_openat_wr("knowledge/fixtures/nishi_mobi_chapters.mobi" as *u8, 0x1a4)
260 if fdch >= 0 { sys_write(fdch, ch, cho); sys_close(fdch) }
261 mf_p("MOBI-CHAPTERS-FIXTURE bytes=" as *u8); mf_n(cho); mf_p(" (3 chapters via pagebreak) -> knowledge/fixtures/nishi_mobi_chapters.mobi\n" as *u8)
262
263 // ---- HEADINGS variant: nishi_mobi_headings.mobi (PalmDOC; 3 <h1> chapters, NO pagebreaks -> heading-fallback TOC) ----
264 let hhtml: *u8 = "<html><body><h1>Alpha</h1><p>The first chapter about the alpha wolves running through snow.</p><h1>Beta</h1><p>The second chapter where beta fish swim in clear water.</p><h1>Gamma</h1><p>The third chapter on gamma rays beaming from space.</p></body></html>" as *u8
265 let hhtmln: i64 = mf_slen(hhtml)
266 let hh: *u8 = sys_mmap(K_MAGIC_262144)
267 puts(hh, 0, "Headings Fixture" as *u8)
268 puts(hh, 60, "BOOK" as *u8); puts(hh, 64, "MOBI" as *u8)
269 put16(hh, 76, 2) // numRecords = 2
270 var hho: i64 = 96
271 let hhrec0: i64 = hho
272 hho = put16(hh, hho, 2); hho = put16(hh, hho, 0) // compression PalmDOC
273 hho = put32(hh, hho, hhtmln); hho = put16(hh, hho, 1); hho = put16(hh, hho, K_MAGIC_4096)
274 hho = put16(hh, hho, 0); hho = put16(hh, hho, 0) // enc=0
275 hho = puts(hh, hho, "MOBI" as *u8)
276 put32(hh, hho, 24); put32(hh, hho+4, 2); put32(hh, hho+8, K_MAGIC_65001); put32(hh, hho+12, 1); put32(hh, hho+16, 6); hho = hho + 20
277 let hhexth: i64 = hho
278 hho = puts(hh, hho, "EXTH" as *u8)
279 let hhexthlen_pos: i64 = hho
280 hho = put32(hh, hho, 0); hho = put32(hh, hho, 2)
281 hho = put32(hh, hho, 100); hho = put32(hh, hho, 8 + authn); hho = puts(hh, hho, auth)
282 let hhtitl: *u8 = "Heading Demo" as *u8; let hhtitln: i64 = mf_slen(hhtitl)
283 hho = put32(hh, hho, 503); hho = put32(hh, hho, 8 + hhtitln); hho = puts(hh, hho, hhtitl)
284 var hhexthlen: i64 = hho - hhexth
285 while (hhexthlen % 4) != 0 { hh[hho]=0 as u8; hho=hho+1; hhexthlen=hhexthlen+1 }
286 put32(hh, hhexthlen_pos, hhexthlen)
287 while (hho % 4) != 0 { hh[hho]=0 as u8; hho=hho+1 }
288 let hhrec1: i64 = hho
289 let hhcn: i64 = palmdoc_compress(hhtml, hhtmln, (hh as i64 + hho) as *u8, K_MAGIC_262144 - hho)
290 hho = hho + hhcn
291 put32(hh, 78, hhrec0); put32(hh, 86, hhrec1)
292 let fdhh: i64 = sys_openat_wr("knowledge/fixtures/nishi_mobi_headings.mobi" as *u8, 0x1a4)
293 if fdhh >= 0 { sys_write(fdhh, hh, hho); sys_close(fdhh) }
294 mf_p("MOBI-HEADINGS-FIXTURE bytes=" as *u8); mf_n(hho); mf_p(" (3 <h1> chapters, no pagebreak) -> knowledge/fixtures/nishi_mobi_headings.mobi\n" as *u8)
295
296 mf_p("MOBI-FIXTURE-OK\n" as *u8)
297 sys_exit(0); return 0
298}