Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ; ============================================================================
- ; epub2txt -- an EPUB reader for 8088/8086 DOS
- ; ============================================================================
- ;
- ; PUBLIC DOMAIN BECAUSE GENERATED CODE CANNOT
- ; BE COPYRIGHTED OR COPYLEFTED
- ;
- ; I tried a second LLM to get the AI-Bros off my back.
- ; It is not worth the rivers and the sky.
- ;
- ; An interactive EPUB reader written entirely in 8086 assembly (NASM
- ; syntax), targeting real-mode DOS on original 8088 hardware. It parses
- ; the ZIP container, decompresses DEFLATE streams, strips HTML, folds
- ; UTF-8 to ASCII, word-wraps, and presents the book through a more-style
- ; pager with chapter navigation and resume bookmarks.
- ; Tested under dosemu and DOSBox.
- ;
- ; Final codebase: September 30, 2026
- ;
- ; HOW THIS WAS MADE
- ;
- ; This program was generated through an extended interactive session with
- ; Kimi (kimi.ai), an AI coding assistant by Moonshot AI, working from the
- ; specification "epub to text in 8088 assembler" -- which grew, through
- ; use, into a full-screen reader.
- ;
- ; The development was iterative and test-driven in an unusual way:
- ;
- ; 1. Algorithm-first verification. Before any machine-code debugging, the
- ; assembly logic (bit reader, Huffman table construction, inflate state
- ; machine, NCX parser) was ported 1:1 to Python and run against real
- ; deflate streams and captured EPUB bytes. This caught design bugs
- ; (illegal addressing modes, register clobbering across int 21h) that
- ; reading alone missed.
- ;
- ; 2. A hardware-specific bug. The target DOS clobbers DX across int 21h
- ; calls (standard DOS preserves it). Every early build kept a live value
- ; in DX across a file read inside the bit reader, so the very first
- ; getbits call -- and every 2048-byte buffer refill -- silently
- ; corrupted the decode. The fix: all file-I/O wrappers (next_byte,
- ; seek, flush_out) push/pop every register, so no register assumption
- ; is ever made across a DOS call.
- ;
- ; 3. A console-specific bug. Output originally used Unix-style LF-only
- ; line endings. dosemu's console forgives that (LF implies column 1),
- ; but DOSBox -- like real DOS CON -- keeps the column on LF, producing
- ; a staircase of "extra spaces." The fix routes every output byte
- ; through one routine that expands LF to CRLF.
- ;
- ; 4. Gradual feature growth. What began as "extract text" grew through
- ; user feedback into: UTF-8 folding, a TOC parsed from toc.ncx with
- ; real chapter titles, anchor-scoped chapter extraction, word wrap at
- ; a configurable width, a paged reader with SPACE/B/Q and
- ; cross-section navigation, screen clearing, and .bkm resume
- ; bookmarks.
- ;
- ; Notable simplifications (by design, on an 8088): no quoted-attribute
- ; tracking in tags, no ZIP64, navPoint-granular TOC capped at 32 entries /
- ; 31-char anchors, and single-byte ASCII folds (ss->s rather than ss).
- ;
- ; ----------------------------------------------------------------------------
- ; REQUIREMENTS
- ;
- ; - NASM 2.x (developed with NASM 2.11.08; any 2.x should work)
- ; - MS-DOS / PC-DOS / FreeDOS 2.0 or later -- real hardware, DOSBox,
- ; dosemu, or another emulator
- ; - ~50 KB free conventional memory for the .COM
- ;
- ; COMPILE INSTRUCTIONS
- ;
- ; nasm -f bin epub2txt.asm -o epub2txt.com
- ;
- ; That's it -- flat binary, no linker. The source enforces "cpu 8086", so
- ; NASM will reject any instruction the 8088 can't execute.
- ;
- ; ----------------------------------------------------------------------------
- ; USAGE
- ;
- ; epub2txt <file.epub> [-w W] [-p L] [-l | N]
- ;
- ; -w W word-wrap width, clamped 20..200 (default 78)
- ; -p L lines per page, clamped 5..60 (default 24)
- ; -l list all chapters (titles from toc.ncx)
- ; N display chapter N only
- ;
- ; Options may be combined in any order after the filename.
- ;
- ; Examples:
- ;
- ; REM Read a book interactively:
- ; epub2txt dickens.epub
- ;
- ; REM List the chapters:
- ; epub2txt dickens.epub -l
- ;
- ; REM Read just chapter 3:
- ; epub2txt dickens.epub 3
- ;
- ; REM Narrow wrap, short pages, chapter 5:
- ; epub2txt dickens.epub -w 60 -p 20 5
- ;
- ; REM Resume where you left off (see bookmarks below):
- ; epub2txt dickens.epub
- ;
- ; READER KEYS
- ;
- ; SPACE next page
- ; B previous page; at a section's start, jump to the bottom of the
- ; previous section/chapter
- ; Q quit (saves bookmark)
- ;
- ; Every page is displayed on a freshly cleared screen; the "-- more --"
- ; prompt erases itself before each new page.
- ;
- ; BOOKMARKS
- ;
- ; While reading, Q writes your position (chapter and page) to a file named
- ; after the book -- dickens.epub -> dickens.bkm. Running
- ; "epub2txt dickens.epub" with no other arguments resumes from that spot.
- ; Reading to the end of the book deletes the bookmark, so the next bare
- ; run starts fresh. The resume page is re-clamped after re-extraction, so
- ; changing -w/-p between sessions is harmless. -l never touches bookmarks.
- ;
- ; ----------------------------------------------------------------------------
- ; HOW IT WORKS (INTERNALS)
- ;
- ; - Container: ZIP central-directory walk; the End-Of-Central-Directory
- ; record is validated by checking that record + comment length lands
- ; exactly at EOF (rejecting false PK\05\06 signatures inside file data).
- ; - Decompression: full DEFLATE -- stored, fixed-Huffman, and
- ; dynamic-Huffman blocks -- with a byte-at-a-time LSB-first bit reader
- ; and a 32 KB sliding window with wraparound.
- ; - TOC: toc.ncx is inflated through a small XML state machine that pairs
- ; each <text> title with the following src="..."; anchors after '#' are
- ; kept for chapter scoping.
- ; - Chapter extraction: output is suppressed until id="anchor" (or
- ; name="anchor") is seen in the raw byte stream, and stops at the next
- ; navPoint's anchor in the same file.
- ; - Output pipeline: HTML tags stripped (block tags become newlines,
- ; script/style bodies dropped, entities resolved), UTF-8 folded to ASCII
- ; via a 256-entry table (Latin-1 + Latin Extended-A + punctuation),
- ; greedy word wrap that never splits words, and CRLF line endings --
- ; emitted at a single choke point so every console (dosemu, DOSBox,
- ; real DOS) renders pages identically.
- ; - Pagination: wrapped output is buffered to a temp file (EPUB2TX.$$$,
- ; deleted on exit) while a page-offset index is built; the reader seeks
- ; through that index to display pages and to jump between sections.
- ; - Portability hardening: every int 21h wrapper preserves all registers,
- ; because the development target's DOS clobbers DX -- never trust
- ; register preservation across DOS calls on unknown systems.
- ;
- ; LIMITATIONS
- ;
- ; - Chapters beyond the 32nd navPoint are not listed; anchors longer than
- ; 31 chars are truncated.
- ; - Characters with no ASCII equivalent become '?'.
- ; - The NCX src matching is case-insensitive suffix matching; a book whose
- ; NCX references files that don't exist in the archive falls back to
- ; archive-order behavior.
- ; - 1024 pages max in the page index (~24k lines of wrapped text).
- ;
- ; CREDITS
- ;
- ; Written by Kimi (kimi.ai, Moonshot AI) in collaboration with the user,
- ; over the course of a single long debugging session on 8088 hardware --
- ; including three rounds of Python-level algorithm verification, one very
- ; stubborn register-clobbering DOS, and one console that liked Unix
- ; newlines more than DOS does.
- ; ============================================================================
- ;
- ; epub2txt.asm -- interactive EPUB reader, 8088/8086 real mode, DOS .COM
- ; FINAL BUILD -- HTML stripping, UTF-8->ASCII folding, navPoint TOC/selection
- ; from toc.ncx, word wrap (-w), paged reading (-p) with
- ; SPACE/B/Q, cross-section navigation, clear-screen paging,
- ; and .bkm resume bookmarks.
- ; Build: nasm -f bin epub2txt.asm -o epub2txt.com
- ; Run: epub2txt book.epub [-w W] [-p L] [-l | N]
- ; -w W wrap width (20..200, default 78)
- ; -p L lines/page (5..60, default 24)
- ; -l list chapters
- ; N display chapter N
- ; bare filename resumes from book.bkm if present (Q saves, end deletes)
- cpu 8086
- bits 16
- org 0x100
- INBUF_SIZE equ 2048
- OUTBUF_SIZE equ 512
- ;---------------------------------------------------------------- anchor matcher
- %macro ANCH 3
- mov bl, [%1]
- cmp bl, 4
- je %%q
- cmp bl, 0
- je %%s0
- cmp bl, 1
- je %%s1
- cmp bl, 2
- je %%s2
- cmp bl, 3
- je %%s3
- cmp bl, 10
- je %%s10
- cmp bl, 11
- je %%s11
- cmp bl, 12
- je %%s12
- mov byte [%1], 0
- clc
- jmp %%done
- %%s0:
- cmp al, 'i'
- je %%t1
- cmp al, 'n'
- je %%t10
- clc
- jmp %%done
- %%t1:
- mov byte [%1], 1
- clc
- jmp %%done
- %%t10:
- mov byte [%1], 10
- clc
- jmp %%done
- %%s1:
- cmp al, 'd'
- je %%t2
- cmp al, 'n'
- je %%t10
- mov byte [%1], 0
- clc
- jmp %%done
- %%t2:
- mov byte [%1], 2
- clc
- jmp %%done
- %%s10:
- cmp al, 'a'
- je %%t11
- mov byte [%1], 0
- clc
- jmp %%done
- %%t11:
- mov byte [%1], 11
- clc
- jmp %%done
- %%s11:
- cmp al, 'm'
- je %%t12
- mov byte [%1], 0
- clc
- jmp %%done
- %%t12:
- mov byte [%1], 12
- clc
- jmp %%done
- %%s12:
- cmp al, 'e'
- je %%t3
- mov byte [%1], 0
- clc
- jmp %%done
- %%s2:
- cmp al, '='
- je %%t3
- mov byte [%1], 0
- clc
- jmp %%done
- %%t3:
- mov byte [%1], 3
- clc
- jmp %%done
- %%s3:
- cmp al, 34
- je %%t4
- cmp al, 39
- je %%t4
- mov byte [%1], 0
- clc
- jmp %%done
- %%t4:
- mov [%2], al
- mov byte [%3], 0
- mov byte [%1], 4
- clc
- jmp %%done
- %%q:
- mov bl, [%3]
- mov bh, 0
- push si
- add si, bx
- mov dl, [si]
- pop si
- test dl, dl
- jz %%atend
- cmp al, dl
- jne %%reset
- inc byte [%3]
- clc
- jmp %%done
- %%atend:
- cmp al, [%2]
- jne %%reset
- mov byte [%1], 0
- stc
- jmp %%done
- %%reset:
- mov byte [%1], 0
- clc
- %%done:
- %endmacro
- ;---------------------------------------------------------------- entry point
- start:
- mov si, 0x81
- call skip_sp
- mov di, iname
- call copy_tok
- cmp byte [iname], 0
- je .usage
- mov word [wrapw], 78
- mov word [pagel], 24
- .argloop:
- call skip_sp
- cmp byte [si], 0x0D
- je .noopt
- mov al, [si]
- cmp al, '-'
- jne .trynum
- inc si
- mov al, [si]
- cmp al, 'w'
- je .optw
- cmp al, 'p'
- je .optp
- cmp al, 'l'
- je .optl
- jmp .badarg
- .optw:
- inc si
- call parse_num
- jc .badarg
- cmp ax, 20
- jae .w1
- mov ax, 20
- .w1:
- cmp ax, 200
- jbe .w2
- mov ax, 200
- .w2:
- mov [wrapw], ax
- jmp .argloop
- .optp:
- inc si
- call parse_num
- jc .badarg
- cmp ax, 5
- jae .p1
- mov ax, 5
- .p1:
- cmp ax, 60
- jbe .p2
- mov ax, 60
- .p2:
- mov [pagel], ax
- jmp .argloop
- .optl:
- inc si
- mov byte [mode], 1
- jmp .argloop
- .trynum:
- cmp al, '0'
- jb .badarg
- cmp al, '9'
- ja .badarg
- call parse_num
- jc .badarg
- mov [chapnum], ax
- mov byte [mode], 2
- jmp .argloop
- .noopt:
- mov ax, 0x3D00
- mov dx, iname
- int 0x21
- jc .usage
- mov [fh], ax
- call find_eocd
- jc .badzip
- mov word [oh], 1
- call make_bkmname
- call load_toc
- call load_bookmark
- call setup_paging
- cmp byte [mode], 1
- jne .not_list
- call list_navpoints
- jmp .close
- .not_list:
- cmp byte [mode], 2
- jne .go
- mov ax, [chapnum]
- test ax, ax
- jz .nosec
- cmp ax, [tcount]
- ja .nosec
- dec ax
- mov [seli], ax
- call sel_chapter
- .go:
- mov ax, [eocd_cdoff_lo]
- mov [cdpos_lo], ax
- mov ax, [eocd_cdoff_hi]
- mov [cdpos_hi], ax
- mov ax, [eocd_entries]
- mov [nentries], ax
- .entry_loop:
- cmp word [nentries], 0
- je .alldone
- dec word [nentries]
- call process_entry
- jnc .entry_loop
- .alldone:
- call wrap_finish
- call flush_out
- .close:
- cmp byte [mode], 2
- jne .c0
- cmp byte [chapfound], 0
- jne .c0
- mov dx, msg_nosec
- mov ah, 9
- int 0x21
- .c0:
- call cleanup
- mov ax, 0x4C00
- int 0x21
- .nosec:
- mov dx, msg_nosec
- mov ah, 9
- int 0x21
- call cleanup
- mov ax, 0x4C01
- int 0x21
- .usage:
- mov dx, msg_usage
- mov ah, 9
- int 0x21
- mov ax, 0x4C01
- int 0x21
- .badarg:
- mov dx, msg_usage
- mov ah, 9
- int 0x21
- mov ax, 0x4C01
- int 0x21
- .badzip:
- mov dx, msg_bad
- mov ah, 9
- int 0x21
- mov ax, 0x4C01
- int 0x21
- ;---------------------------------------------------------------- bookmarks
- make_bkmname: ; iname -> bkmname (strip last ext, append .bkm)
- xor bx, bx
- xor si, si
- .scan:
- mov al, [iname + si]
- test al, al
- jz .got
- cmp al, '.'
- jne .n
- mov bx, si
- .n:
- inc si
- jmp .scan
- .got:
- test bx, bx
- jnz .cp
- mov bx, si
- .cp:
- xor si, si
- .cpl:
- cmp si, bx
- jae .app
- mov al, [iname + si]
- mov [bkmname + si], al
- inc si
- jmp .cpl
- .app:
- mov byte [bkmname + bx], '.'
- mov byte [bkmname + bx + 1], 'b'
- mov byte [bkmname + bx + 2], 'k'
- mov byte [bkmname + bx + 3], 'm'
- mov byte [bkmname + bx + 4], 0
- ret
- load_bookmark: ; bare-filename resume from .bkm
- cmp byte [mode], 0
- jne .done
- mov ax, 0x3D00
- mov dx, bkmname
- int 0x21
- jc .done
- mov bx, ax
- mov ah, 0x3F
- mov cx, 16
- mov dx, bkmline
- int 0x21
- mov si, ax ; bytes read
- mov ah, 0x3E
- int 0x21
- test si, si
- jz .done
- mov byte [bkmline + si], 0
- mov si, bkmline
- call parse_num ; K (0 = whole book)
- jc .done
- push ax
- call parse_num ; P (page)
- jc .bdone
- mov [respage], ax
- pop ax
- test ax, ax
- jz .done
- cmp ax, [tcount]
- ja .done
- mov [chapnum], ax
- mov byte [mode], 2
- jmp .done
- .bdone:
- pop ax
- .done:
- ret
- save_bookmark: ; write "K P\r\n" (K = chapter, 0 = whole book)
- cmp byte [mode], 1
- je .done
- mov di, bkmline
- xor ax, ax
- cmp byte [mode], 2
- jne .k0
- mov ax, [seli]
- inc ax
- .k0:
- call fmt_dec_di
- mov byte [di], ' '
- inc di
- mov ax, [page]
- call fmt_dec_di
- mov byte [di], 13
- inc di
- mov byte [di], 10
- inc di
- mov ah, 0x3C
- xor cx, cx
- mov dx, bkmname
- int 0x21
- jc .done
- mov bx, ax
- mov cx, di
- sub cx, bkmline
- mov dx, bkmline
- mov ah, 0x40
- int 0x21
- mov ah, 0x3E
- int 0x21
- .done:
- ret
- delete_bookmark:
- mov ah, 0x41
- mov dx, bkmname
- int 0x21
- ret
- fmt_dec_di: ; append decimal of ax at [di], advance di
- mov bx, scratch + 8
- mov cx, 10
- .d:
- xor dx, dx
- div cx
- add dl, '0'
- dec bx
- mov [bx], dl
- test ax, ax
- jnz .d
- .cp:
- cmp bx, scratch + 8
- jae .r
- mov al, [bx]
- mov [di], al
- inc bx
- inc di
- jmp .cp
- .r:
- ret
- ;---------------------------------------------------------------- pagination
- setup_paging:
- mov word [paging], 0
- mov ax, 0x4400
- mov bx, 1
- int 0x21
- jc .done
- test ax, 0x8000
- jz .done
- mov ah, 0x3C
- xor cx, cx
- mov dx, tmpname
- int 0x21
- jc .done
- mov [th], ax
- mov [oh], ax
- mov byte [paging], 1
- mov word [tmppos_lo], 0
- mov word [tmppos_hi], 0
- mov word [wlines], 0
- mov word [pgused], 0
- mov word [seccnt], 0
- .done:
- ret
- cleanup:
- cmp byte [paging], 0
- je .c2
- call init_pages
- call pager
- mov ah, 0x3E
- mov bx, [th]
- int 0x21
- mov ah, 0x41
- mov dx, tmpname
- int 0x21
- .c2:
- mov ah, 0x3E
- mov bx, [fh]
- int 0x21
- ret
- init_pages:
- mov ax, [pgused]
- test ax, ax
- jz .set
- dec ax
- shl ax, 1
- shl ax, 1
- mov si, pgidx
- add si, ax
- mov dx, [si]
- mov cx, [si + 2]
- cmp cx, [tmppos_hi]
- jne .set
- cmp dx, [tmppos_lo]
- jne .set
- dec word [pgused]
- .set:
- mov ax, [pgused]
- inc ax
- mov [pages], ax
- ret
- page_off_dxd: ; ax = page -> dx = off lo, cx = off hi
- test ax, ax
- jz .zero
- dec ax
- shl ax, 1
- shl ax, 1
- mov si, pgidx
- add si, ax
- mov dx, [si]
- mov cx, [si + 2]
- ret
- .zero:
- xor dx, dx
- xor cx, cx
- ret
- sec_of_page: ; [cursec] = section containing current page
- mov ax, [page]
- call page_off_dxd
- mov word [cursec], 0
- xor bx, bx
- .sl:
- cmp bx, [seccnt]
- jae .done
- mov ax, bx
- shl ax, 1
- shl ax, 1
- mov si, secidx
- add si, ax
- mov ax, [si]
- push word [si + 2]
- pop di
- cmp di, cx
- jb .take
- ja .next
- cmp ax, dx
- ja .next
- .take:
- mov [cursec], bx
- .next:
- inc bx
- jmp .sl
- .done:
- ret
- page_of_secstart: ; ax = section index -> ax = page containing it
- shl ax, 1
- shl ax, 1
- mov si, secidx
- add si, ax
- mov dx, [si]
- mov cx, [si + 2]
- xor bx, bx
- xor di, di
- .ct:
- cmp bx, [pgused]
- jae .done
- mov ax, bx
- shl ax, 1
- shl ax, 1
- mov si, pgidx
- add si, ax
- mov ax, [si]
- mov si, [si + 2]
- cmp si, cx
- jb .take
- ja .skip
- cmp ax, dx
- ja .skip
- .take:
- inc di
- .skip:
- inc bx
- jmp .ct
- .done:
- mov ax, di
- ret
- sel_chapter: ; [seli] (0-based) -> p_fsrc/p_sanc/p_panc
- mov ax, [seli]
- mov bx, 120
- mul bx
- mov bx, tsrc
- add bx, ax
- mov [p_fsrc], bx
- mov ax, [seli]
- shl ax, 1
- shl ax, 1
- shl ax, 1
- shl ax, 1
- shl ax, 1
- mov bx, tanc
- add bx, ax
- mov [p_sanc], bx
- mov word [p_panc], 0
- mov cx, [seli]
- inc cx
- .fs:
- cmp cx, [tcount]
- jae .fd
- mov ax, cx
- mov bx, 120
- mul bx
- mov si, tsrc
- add si, ax
- mov di, [p_fsrc]
- call strcmp_t
- jc .fy
- inc cx
- jmp .fs
- .fy:
- mov ax, cx
- shl ax, 1
- shl ax, 1
- shl ax, 1
- shl ax, 1
- shl ax, 1
- mov bx, tanc
- add bx, ax
- mov [p_panc], bx
- .fd:
- ret
- reextract: ; mode 2: extract chapter [seli] into fresh temp
- mov ah, 0x3E
- mov bx, [th]
- int 0x21
- mov ah, 0x41
- mov dx, tmpname
- int 0x21
- mov ah, 0x3C
- xor cx, cx
- mov dx, tmpname
- int 0x21
- mov [th], ax
- mov [oh], ax
- mov word [tmppos_lo], 0
- mov word [tmppos_hi], 0
- mov word [wlines], 0
- mov word [pgused], 0
- mov word [seccnt], 0
- call sel_chapter
- mov byte [chapfound], 0
- mov ax, [eocd_cdoff_lo]
- mov [cdpos_lo], ax
- mov ax, [eocd_cdoff_hi]
- mov [cdpos_hi], ax
- mov ax, [eocd_entries]
- mov [nentries], ax
- .rx:
- cmp word [nentries], 0
- je .rdone
- dec word [nentries]
- call process_entry
- jnc .rx
- .rdone:
- call wrap_finish
- call flush_out
- call init_pages
- ret
- clear_screen:
- push ax
- push bx
- push cx
- push dx
- mov ax, 0x0600
- mov cx, 0x0000
- mov dx, 0x184F
- mov bh, 0x07
- int 0x10
- mov ah, 0x02
- mov bh, 0
- mov dx, 0x0000
- int 0x10
- pop dx
- pop cx
- pop bx
- pop ax
- ret
- display_page:
- call clear_screen
- mov ax, [page]
- call page_off_dxd
- mov bx, [th]
- mov ah, 0x42
- xor al, al
- int 0x21
- mov word [linecnt], 0
- .rd:
- mov ah, 0x3F
- mov bx, [th]
- mov cx, 128
- mov dx, pbuf
- int 0x21
- test ax, ax
- jz .done
- mov [rdlen], ax
- xor si, si
- .sc:
- cmp si, [rdlen]
- jae .wrfull
- cmp byte [pbuf + si], 10
- jne .nf
- inc word [linecnt]
- mov bx, [pagel]
- cmp [linecnt], bx
- jae .upto
- .nf:
- inc si
- jmp .sc
- .upto:
- inc si
- mov cx, si
- jmp .wr
- .wrfull:
- mov cx, [rdlen]
- .wr:
- mov ah, 0x40
- mov bx, 1
- mov dx, pbuf
- int 0x21
- mov bx, [pagel]
- cmp [linecnt], bx
- jb .rd
- .done:
- ret
- pager:
- mov ax, [respage]
- cmp ax, [pages]
- jb .pset
- mov ax, [pages]
- dec ax
- .pset:
- mov [page], ax
- .ploop:
- call display_page
- .pr:
- call erase_prompt
- mov dx, p_msg
- mov ah, 9
- int 0x21
- mov ah, 7
- int 0x21
- cmp al, 'q'
- je .kquit
- cmp al, 'Q'
- je .kquit
- cmp al, 'b'
- je .kback
- cmp al, 'B'
- je .kback
- cmp al, ' '
- je .knext
- jmp .pr
- .kquit:
- call erase_prompt
- call save_bookmark
- jmp .fin
- .kback:
- call erase_prompt
- jmp .back
- .knext:
- call erase_prompt
- jmp .next
- .back:
- cmp word [page], 0
- jne .pgback
- cmp byte [mode], 2
- je .secback2
- cmp byte [mode], 0
- jne .ploop
- call sec_of_page
- mov ax, [cursec]
- test ax, ax
- jz .ploop
- call page_of_secstart
- dec ax
- mov [page], ax
- jmp .ploop
- .pgback:
- dec word [page]
- jmp .ploop
- .secback2:
- mov ax, [seli]
- test ax, ax
- jz .ploop
- dec word [seli]
- call reextract
- mov ax, [pages]
- dec ax
- mov [page], ax
- jmp .ploop
- .next:
- mov ax, [page]
- inc ax
- cmp ax, [pages]
- jae .secnext
- mov [page], ax
- jmp .ploop
- .secnext:
- cmp byte [mode], 2
- je .secnext2
- cmp byte [mode], 0
- jne .endreached
- call sec_of_page
- mov ax, [cursec]
- inc ax
- cmp ax, [seccnt]
- jae .endreached
- call page_of_secstart
- mov [page], ax
- jmp .ploop
- .secnext2:
- mov ax, [seli]
- inc ax
- cmp ax, [tcount]
- jae .endreached
- mov [seli], ax
- call reextract
- mov word [page], 0
- jmp .ploop
- .endreached:
- cmp byte [mode], 1
- je .fin
- call delete_bookmark
- jmp .fin
- .fin:
- ret
- erase_prompt:
- mov dx, p_erase
- mov cx, 15
- mov ah, 0x40
- mov bx, 1
- int 0x21
- ret
- ;---------------------------------------------------------------- args
- skip_sp:
- .l: mov al, [si]
- cmp al, 0x20
- je .i
- cmp al, 0x09
- je .i
- ret
- .i: inc si
- jmp .l
- copy_tok:
- xor dl, dl
- .l: mov al, [si]
- cmp al, 0x20
- je .d
- cmp al, 0x0D
- je .d
- cmp dl, 63
- jae .d
- mov [di], al
- inc di
- inc dl
- inc si
- jmp .l
- .d: mov byte [di], 0
- ret
- parse_num: ; skip spaces, parse decimal -> ax; CF=1 if none
- call skip_sp
- xor ax, ax
- xor cx, cx
- .l:
- mov bl, [si]
- cmp bl, '0'
- jb .done
- cmp bl, '9'
- ja .done
- sub bl, '0'
- xor bh, bh
- mov dx, ax
- shl ax, 1
- shl ax, 1
- add ax, dx
- shl ax, 1
- add ax, bx
- inc si
- inc cx
- cmp ax, 500
- ja .bad
- jmp .l
- .done:
- test cx, cx
- jz .none
- clc
- ret
- .none:
- stc
- ret
- .bad:
- stc
- ret
- ;---------------------------------------------------------------- file layer
- seek:
- push bx
- push si
- push di
- mov ah, 0x42
- xor al, al
- mov bx, [fh]
- int 0x21
- pop di
- pop si
- pop bx
- mov word [inbuf_len], 0
- mov word [inbuf_pos], 0
- ret
- next_byte:
- push bx
- push cx
- push dx
- push si
- push di
- mov bx, [inbuf_pos]
- cmp bx, [inbuf_len]
- jb .have
- mov ah, 0x3F
- mov bx, [fh]
- mov cx, INBUF_SIZE
- mov dx, inbuf
- int 0x21
- jc .eof
- test ax, ax
- jz .eof
- mov [inbuf_len], ax
- xor bx, bx
- .have:
- mov al, [inbuf + bx]
- inc bx
- mov [inbuf_pos], bx
- pop di
- pop si
- pop dx
- pop cx
- pop bx
- clc
- ret
- .eof:
- pop di
- pop si
- pop dx
- pop cx
- pop bx
- stc
- ret
- ;---------------------------------------------------------------- bit reader
- getbit:
- mov cl, [bit_idx]
- cmp cl, 8
- jb .have
- call next_byte
- jc .eof
- mov [cur_byte], al
- mov byte [bit_idx], 0
- xor cl, cl
- .have:
- mov al, [cur_byte]
- shr al, cl
- and al, 1
- xor ah, ah
- inc byte [bit_idx]
- clc
- ret
- .eof:
- stc
- ret
- getbits:
- mov bl, cl
- xor bh, bh
- xor dx, dx
- test cl, cl
- jnz .g
- xor ax, ax
- clc
- ret
- .g:
- test bl, bl
- jz .done
- call getbit
- jc .eof
- mov cl, bh
- shl ax, cl
- or dx, ax
- inc bh
- dec bl
- jmp .g
- .done:
- mov ax, dx
- clc
- ret
- .eof:
- stc
- ret
- stream_byte:
- cmp byte [bit_idx], 8
- jne .via_bits
- jmp next_byte
- .via_bits:
- mov cl, 8
- call getbits
- ret
- ;---------------------------------------------------------------- huffman
- decode:
- mov word [h_code], 0
- mov word [h_first], 0
- mov word [h_index], 0
- mov cx, 1
- .loop:
- push cx
- mov cl, 1
- call getbits
- pop cx
- jc .err
- or [h_code], ax
- mov bx, cx
- shl bx, 1
- mov dx, [si + bx]
- mov ax, [h_code]
- sub ax, dx
- cmp ax, [h_first]
- jl .found
- add [h_index], dx
- add dx, [h_first]
- shl dx, 1
- mov [h_first], dx
- shl word [h_code], 1
- inc cx
- cmp cx, 15
- jbe .loop
- .err:
- stc
- ret
- .found:
- mov ax, [h_code]
- sub ax, [h_first]
- add ax, [h_index]
- mov bx, ax
- shl bx, 1
- mov ax, [di + bx]
- clc
- ret
- build_table:
- mov [bt_lens], si
- mov [bt_n], cx
- mov [bt_cnt], di
- mov [bt_sym], bx
- xor ax, ax
- mov cx, 16
- .z: mov [di], ax
- inc di
- inc di
- loop .z
- xor si, si
- mov cx, [bt_n]
- .c: cmp si, cx
- jae .offs
- mov bx, [bt_lens]
- mov al, [bx + si]
- test al, al
- jz .cn
- xor ah, ah
- shl ax, 1
- mov di, ax
- mov bx, [bt_cnt]
- inc word [bx + di]
- .cn:
- inc si
- jmp .c
- .offs:
- xor dx, dx
- mov cx, 1
- .o: mov bx, cx
- shl bx, 1
- mov [offs + bx], dx
- mov di, [bt_cnt]
- mov ax, [di + bx]
- add dx, ax
- inc cx
- cmp cx, 15
- jbe .o
- xor si, si
- .p: cmp si, [bt_n]
- jae .done
- mov bx, [bt_lens]
- mov al, [bx + si]
- test al, al
- jz .pn
- xor ah, ah
- shl ax, 1
- mov di, ax
- mov ax, [offs + di]
- inc word [offs + di]
- shl ax, 1
- mov bx, [bt_sym]
- add bx, ax
- mov [bx], si
- .pn:
- inc si
- jmp .p
- .done:
- ret
- ;---------------------------------------------------------------- inflate
- inflate:
- mov word [wpos], 0
- mov byte [bit_idx], 8
- mov byte [cur_byte], 0
- .block:
- mov cl, 1
- call getbits
- jc .fail
- mov [bfinal], ax
- mov cl, 2
- call getbits
- jc .fail
- cmp al, 0
- je .stored
- cmp al, 1
- je .fixed
- cmp al, 2
- je .dynamic
- jmp .fail
- .stored:
- mov byte [bit_idx], 8
- mov cl, 8
- call getbits
- jc .fail
- mov [slen], ax
- mov cl, 8
- call getbits
- jc .fail
- mov bx, ax
- mov cl, 8
- shl bx, cl
- or [slen], bx
- mov cl, 8
- call getbits
- mov [snlen], ax
- mov cl, 8
- call getbits
- mov bx, ax
- mov cl, 8
- shl bx, cl
- or [snlen], bx
- mov ax, [slen]
- not ax
- cmp ax, [snlen]
- jne .fail
- .copy:
- cmp word [slen], 0
- je .bend
- call stream_byte
- jc .fail
- call emit_raw
- dec word [slen]
- jmp .copy
- .fixed:
- call build_fixed
- jmp .syms
- .dynamic:
- call build_dynamic
- jc .fail
- .syms:
- mov si, counts_lit
- mov di, syms_lit
- call decode
- jc .fail
- cmp ax, 256
- jb .lit
- je .bend
- cmp ax, 285
- ja .fail
- sub ax, 257
- mov byte [cidx], al
- mov bl, al
- xor bh, bh
- mov cl, [len_extra + bx]
- test cl, cl
- jz .noex
- call getbits
- jc .fail
- mov [mtmp], ax
- jmp .base
- .noex:
- mov word [mtmp], 0
- .base:
- mov bl, [cidx]
- xor bh, bh
- shl bx, 1
- mov ax, [len_base + bx]
- add ax, [mtmp]
- mov [mlen], ax
- mov si, counts_dist
- mov di, syms_dist
- call decode
- jc .fail
- cmp ax, 29
- ja .fail
- mov byte [cidx], al
- mov bl, al
- xor bh, bh
- mov cl, [dist_extra + bx]
- test cl, cl
- jz .dno
- call getbits
- jc .fail
- mov [mtmp], ax
- jmp .dbase
- .dno:
- mov word [mtmp], 0
- .dbase:
- mov bl, [cidx]
- xor bh, bh
- shl bx, 1
- mov ax, [dist_base + bx]
- add ax, [mtmp]
- mov [mdist], ax
- .mcopy:
- mov bx, [wpos]
- sub bx, [mdist]
- and bx, 0x7FFF
- mov al, [window + bx]
- call emit_raw
- dec word [mlen]
- jnz .mcopy
- jmp .syms
- .lit:
- call emit_raw
- jmp .syms
- .bend:
- cmp word [bfinal], 0
- je .block
- clc
- ret
- .fail:
- stc
- ret
- build_fixed:
- xor bx, bx
- .l8a:
- cmp bx, 144
- jae .l9
- mov byte [lens + bx], 8
- inc bx
- jmp .l8a
- .l9:
- cmp bx, 256
- jae .l7
- mov byte [lens + bx], 9
- inc bx
- jmp .l9
- .l7:
- cmp bx, 280
- jae .l8b
- mov byte [lens + bx], 7
- inc bx
- jmp .l7
- .l8b:
- cmp bx, 288
- jae .ld
- mov byte [lens + bx], 8
- inc bx
- jmp .l8b
- .ld:
- cmp bx, 320
- jae .b
- mov byte [lens + bx], 5
- inc bx
- jmp .ld
- .b:
- mov si, lens
- mov cx, 288
- mov di, counts_lit
- mov bx, syms_lit
- call build_table
- mov si, lens + 288
- mov cx, 32
- mov di, counts_dist
- mov bx, syms_dist
- call build_table
- ret
- build_dynamic:
- mov di, cl_lens
- xor ax, ax
- mov cx, 19
- .z: mov [di], al
- inc di
- loop .z
- mov cl, 5
- call getbits
- jc .fail
- add ax, 257
- mov [nlit], ax
- mov cl, 5
- call getbits
- jc .fail
- inc ax
- mov [ndist], ax
- mov cl, 4
- call getbits
- jc .fail
- add ax, 4
- mov [ncl], ax
- mov word [hci], 0
- .rd:
- mov bx, [hci]
- cmp bx, [ncl]
- jae .bld
- mov cl, 3
- call getbits
- jc .fail
- mov bx, [hci]
- mov si, order
- mov bl, [si + bx]
- xor bh, bh
- mov [cl_lens + bx], al
- inc word [hci]
- jmp .rd
- .bld:
- mov si, cl_lens
- mov cx, 19
- mov di, counts_cl
- mov bx, syms_cl
- call build_table
- mov ax, [nlit]
- add ax, [ndist]
- mov [totl], ax
- mov word [hci], 0
- mov si, counts_cl
- mov di, syms_cl
- .rl:
- mov bx, [hci]
- cmp bx, [totl]
- jae .split
- call decode
- jc .fail
- cmp ax, 15
- ja .rep
- mov bx, [hci]
- mov [lens + bx], al
- inc word [hci]
- jmp .rl
- .rep:
- cmp ax, 16
- je .r16
- cmp ax, 17
- je .r17
- cmp ax, 18
- je .r18
- jmp .fail
- .r16:
- mov cl, 2
- call getbits
- jc .fail
- add ax, 3
- mov [repn], ax
- mov bx, [hci]
- test bx, bx
- jz .fail
- dec bx
- mov al, [lens + bx]
- jmp .fill
- .r17:
- mov cl, 3
- call getbits
- jc .fail
- add ax, 3
- mov [repn], ax
- xor al, al
- jmp .fill
- .r18:
- mov cl, 7
- call getbits
- jc .fail
- add ax, 11
- mov [repn], ax
- xor al, al
- .fill:
- mov cx, [repn]
- .f: mov bx, [hci]
- cmp bx, [totl]
- jae .fail
- mov [lens + bx], al
- inc word [hci]
- loop .f
- jmp .rl
- .split:
- mov si, lens
- mov cx, [nlit]
- mov di, counts_lit
- mov bx, syms_lit
- call build_table
- mov si, lens
- add si, [nlit]
- mov cx, [ndist]
- mov di, counts_dist
- mov bx, syms_dist
- call build_table
- clc
- ret
- .fail:
- stc
- ret
- ;---------------------------------------------------------------- zip layer
- find_eocd:
- mov bx, [fh]
- mov ax, 0x4202
- xor cx, cx
- xor dx, dx
- int 0x21
- jc .fail
- mov [fsize_lo], ax
- mov [fsize_hi], dx
- sub ax, 4096
- sbb dx, 0
- jnc .ok
- xor ax, ax
- xor dx, dx
- .ok:
- mov [scan_lo], ax
- mov [scan_hi], dx
- .chunk:
- mov cx, [scan_hi]
- mov dx, [scan_lo]
- call seek
- mov ah, 0x3F
- mov bx, [fh]
- mov cx, INBUF_SIZE
- mov dx, inbuf
- int 0x21
- jc .fail
- test ax, ax
- jz .fail
- mov [chunklen], ax
- xor si, si
- .sl:
- mov ax, [chunklen]
- sub ax, 21
- cmp si, ax
- jae .next
- cmp byte [inbuf + si], 'P'
- jne .sn
- cmp byte [inbuf + si + 1], 'K'
- jne .sn
- cmp byte [inbuf + si + 2], 5
- jne .sn
- cmp byte [inbuf + si + 3], 6
- jne .sn
- mov ax, [scan_lo]
- add ax, si
- mov [cand_lo], ax
- mov ax, [scan_hi]
- adc ax, 0
- mov [cand_hi], ax
- mov dx, [cand_lo]
- mov cx, [cand_hi]
- call seek
- mov ah, 0x3F
- mov bx, [fh]
- mov cx, 22
- mov dx, eocdbuf
- int 0x21
- jc .fail
- cmp ax, 22
- jne .fail
- mov ax, [cand_lo]
- add ax, 22
- mov dx, [cand_hi]
- adc dx, 0
- add ax, [eocdbuf + 20]
- adc dx, 0
- cmp ax, [fsize_lo]
- jne .sn
- cmp dx, [fsize_hi]
- jne .sn
- mov ax, [eocdbuf + 10]
- mov [eocd_entries], ax
- mov ax, [eocdbuf + 16]
- mov [eocd_cdoff_lo], ax
- mov ax, [eocdbuf + 18]
- mov [eocd_cdoff_hi], ax
- clc
- ret
- .sn:
- inc si
- jmp .sl
- .next:
- mov ax, [chunklen]
- sub ax, 21
- jbe .fail
- add [scan_lo], ax
- adc word [scan_hi], 0
- jmp .chunk
- .fail:
- stc
- ret
- process_entry:
- mov cx, [cdpos_hi]
- mov dx, [cdpos_lo]
- call seek
- mov ah, 0x3F
- mov bx, [fh]
- mov cx, 46
- mov dx, cdbuf
- int 0x21
- jc .next
- cmp ax, 46
- jne .done
- cmp byte [cdbuf], 'P'
- jne .done
- cmp byte [cdbuf + 1], 'K'
- jne .done
- cmp byte [cdbuf + 2], 1
- jne .done
- cmp byte [cdbuf + 3], 2
- jne .done
- mov ax, [cdbuf + 10]
- mov [method], ax
- mov ax, [cdbuf + 20]
- mov [csz_lo], ax
- mov ax, [cdbuf + 22]
- mov [csz_hi], ax
- mov ax, [cdbuf + 28]
- mov [cnamelen], ax
- mov ax, [cdbuf + 30]
- mov [cextralen], ax
- mov ax, [cdbuf + 32]
- mov [ccommentlen], ax
- mov ax, [cdbuf + 42]
- mov [lhoff_lo], ax
- mov ax, [cdbuf + 44]
- mov [lhoff_hi], ax
- mov ax, [cnamelen]
- add [cdpos_lo], ax
- adc word [cdpos_hi], 0
- mov ax, [cextralen]
- add [cdpos_lo], ax
- adc word [cdpos_hi], 0
- mov ax, [ccommentlen]
- add [cdpos_lo], ax
- adc word [cdpos_hi], 0
- add word [cdpos_lo], 46
- adc word [cdpos_hi], 0
- mov ah, 0x3F
- mov bx, [fh]
- mov cx, [cnamelen]
- cmp cx, 250
- jbe .lenok
- mov cx, 250
- .lenok:
- mov [cnamelen], cx
- mov dx, nbuf
- int 0x21
- call lower_name
- call check_ext
- jnc .next
- cmp byte [mode], 0
- je .extract
- mov si, [p_fsrc]
- call ends_with
- jnc .next
- mov byte [chapfound], 1
- .extract:
- mov cx, [lhoff_hi]
- mov dx, [lhoff_lo]
- call seek
- mov ah, 0x3F
- mov bx, [fh]
- mov cx, 30
- mov dx, lhbuf
- int 0x21
- jc .next
- cmp ax, 30
- jne .next
- cmp byte [lhbuf], 'P'
- jne .next
- cmp byte [lhbuf + 1], 'K'
- jne .next
- cmp byte [lhbuf + 2], 3
- jne .next
- cmp byte [lhbuf + 3], 4
- jne .next
- mov ax, [lhbuf + 26]
- add [lhoff_lo], ax
- adc word [lhoff_hi], 0
- mov ax, [lhbuf + 28]
- add [lhoff_lo], ax
- adc word [lhoff_hi], 0
- add word [lhoff_lo], 30
- adc word [lhoff_hi], 0
- mov word [inbuf_len], 0
- mov word [inbuf_pos], 0
- mov byte [bit_idx], 8
- mov byte [cur_byte], 0
- mov byte [u_count], 0
- mov word [wpos], 0
- mov byte [pstate], 0
- mov byte [tag_len], 0
- mov byte [ent_len], 0
- mov byte [sk_state], 0
- mov byte [out_on], 1
- mov byte [anch_scan], 0
- cmp byte [mode], 2
- jne .noscope
- mov byte [anch_scan], 1
- mov byte [as_state], 0
- mov byte [bs_state], 0
- mov si, [p_sanc]
- cmp byte [si], 0
- je .noscope
- mov byte [out_on], 0
- .noscope:
- cmp byte [paging], 0
- je .norec
- mov ax, [seccnt]
- cmp ax, 32
- jae .norec
- shl ax, 1
- shl ax, 1
- mov di, secidx
- add di, ax
- mov bx, [tmppos_lo]
- add bx, [outbuf_len]
- mov [di], bx
- mov bx, [tmppos_hi]
- adc bx, 0
- mov [di + 2], bx
- inc word [seccnt]
- .norec:
- mov cx, [lhoff_hi]
- mov dx, [lhoff_lo]
- call seek
- mov ax, [method]
- cmp ax, 0
- je .stored
- cmp ax, 8
- je .deflate
- jmp .next
- .stored:
- call extract_stored
- jmp .next
- .deflate:
- call inflate
- .next:
- clc
- ret
- .done:
- stc
- ret
- extract_stored:
- .loop:
- mov ax, [csz_lo]
- or ax, [csz_hi]
- jz .done
- call next_byte
- jc .done
- call emit_raw
- dec word [csz_lo]
- cmp word [csz_lo], 0xFFFF
- jne .loop
- dec word [csz_hi]
- jmp .loop
- .done:
- ret
- lower_name:
- xor si, si
- .l: cmp si, [cnamelen]
- jae .d
- mov al, [nbuf + si]
- cmp al, 'A'
- jb .s
- cmp al, 'Z'
- ja .s
- add al, 32
- .s: mov [lname + si], al
- inc si
- jmp .l
- .d: mov byte [lname + si], 0
- ret
- check_ext:
- xor si, si
- .len:
- cmp byte [lname + si], 0
- je .got
- inc si
- jmp .len
- .got:
- cmp si, 6
- jb .h5
- cmp byte [lname + si - 6], '.'
- jne .h5
- cmp byte [lname + si - 5], 'x'
- jne .h5
- cmp byte [lname + si - 4], 'h'
- jne .h5
- cmp byte [lname + si - 3], 't'
- jne .h5
- cmp byte [lname + si - 2], 'm'
- jne .h5
- cmp byte [lname + si - 1], 'l'
- jne .h5
- stc
- ret
- .h5:
- cmp si, 5
- jb .h4
- cmp byte [lname + si - 5], '.'
- jne .h4
- cmp byte [lname + si - 4], 'h'
- jne .h4
- cmp byte [lname + si - 3], 't'
- jne .h4
- cmp byte [lname + si - 2], 'm'
- jne .h4
- cmp byte [lname + si - 1], 'l'
- jne .h4
- stc
- ret
- .h4:
- cmp si, 4
- jb .no
- cmp byte [lname + si - 4], '.'
- jne .no
- cmp byte [lname + si - 3], 'h'
- jne .no
- cmp byte [lname + si - 2], 't'
- jne .no
- cmp byte [lname + si - 1], 'm'
- jne .no
- stc
- ret
- .no:
- clc
- ret
- ;---------------------------------------------------------------- ncx loading
- load_toc:
- mov ax, [eocd_cdoff_lo]
- mov [scan_lo], ax
- mov ax, [eocd_cdoff_hi]
- mov [scan_hi], ax
- mov ax, [eocd_entries]
- mov [ncxl], ax
- .loop:
- cmp word [ncxl], 0
- je .done
- dec word [ncxl]
- mov cx, [scan_hi]
- mov dx, [scan_lo]
- call seek
- mov ah, 0x3F
- mov bx, [fh]
- mov cx, 46
- mov dx, cdbuf
- int 0x21
- jc .done
- cmp ax, 46
- jne .done
- mov ax, [cdbuf + 10]
- mov [method], ax
- mov ax, [cdbuf + 20]
- mov [csz_lo], ax
- mov ax, [cdbuf + 22]
- mov [csz_hi], ax
- mov ax, [cdbuf + 28]
- mov [cnamelen], ax
- mov ax, [cdbuf + 30]
- mov [cextralen], ax
- mov ax, [cdbuf + 32]
- mov [ccommentlen], ax
- mov ax, [cdbuf + 42]
- mov [lhoff_lo], ax
- mov ax, [cdbuf + 44]
- mov [lhoff_hi], ax
- mov ax, [cnamelen]
- add [scan_lo], ax
- adc word [scan_hi], 0
- mov ax, [cextralen]
- add [scan_lo], ax
- adc word [scan_hi], 0
- mov ax, [ccommentlen]
- add [scan_lo], ax
- adc word [scan_hi], 0
- add word [scan_lo], 46
- adc word [scan_hi], 0
- mov ah, 0x3F
- mov bx, [fh]
- mov cx, [cnamelen]
- cmp cx, 250
- jbe .lenok
- mov cx, 250
- .lenok:
- mov [cnamelen], cx
- mov dx, nbuf
- int 0x21
- call lower_name
- call check_ncx
- jnc .loop
- mov cx, [lhoff_hi]
- mov dx, [lhoff_lo]
- call seek
- mov ah, 0x3F
- mov bx, [fh]
- mov cx, 30
- mov dx, lhbuf
- int 0x21
- jc .done
- cmp ax, 30
- jne .done
- cmp byte [lhbuf], 'P'
- jne .done
- cmp byte [lhbuf + 1], 'K'
- jne .done
- mov ax, [lhbuf + 26]
- add [lhoff_lo], ax
- adc word [lhoff_hi], 0
- mov ax, [lhbuf + 28]
- add [lhoff_lo], ax
- adc word [lhoff_hi], 0
- add word [lhoff_lo], 30
- adc word [lhoff_hi], 0
- mov word [inbuf_len], 0
- mov word [inbuf_pos], 0
- mov byte [bit_idx], 8
- mov byte [cur_byte], 0
- mov word [wpos], 0
- mov byte [nx_state], 0
- mov byte [nx_tpend], 0
- mov byte [u_count], 0
- mov byte [ncx_mode], 1
- mov cx, [lhoff_hi]
- mov dx, [lhoff_lo]
- call seek
- mov ax, [method]
- cmp ax, 0
- je .stored
- cmp ax, 8
- je .deflate
- jmp .clr
- .stored:
- call extract_stored
- jmp .clr
- .deflate:
- call inflate
- .clr:
- mov byte [ncx_mode], 0
- .done:
- ret
- check_ncx:
- xor si, si
- .len:
- cmp byte [lname + si], 0
- je .got
- inc si
- jmp .len
- .got:
- cmp si, 4
- jb .no
- cmp byte [lname + si - 4], '.'
- jne .no
- cmp byte [lname + si - 3], 'n'
- jne .no
- cmp byte [lname + si - 2], 'c'
- jne .no
- cmp byte [lname + si - 1], 'x'
- jne .no
- stc
- ret
- .no:
- clc
- ret
- ;---------------------------------------------------------------- ncx parser
- ncx_feed:
- mov cl, [nx_state]
- cmp cl, 0
- je .s_scan
- cmp cl, 1
- je .s_tag
- cmp cl, 2
- je .s_title
- cmp cl, 3
- je .s_r
- cmp cl, 4
- je .s_c
- cmp cl, 5
- je .s_eq
- cmp cl, 6
- je .s_quote
- cmp cl, 7
- je .s_src
- cmp cl, 8
- je .s_anchor
- ret
- .s_scan:
- cmp al, '<'
- jne .ret
- mov byte [nx_state], 1
- mov byte [nx_tagpos], 0
- mov byte [nx_close], 0
- mov byte [nx_inname], 1
- ret
- .s_tag:
- cmp al, '>'
- je .tag_end
- cmp al, '/'
- jne .not_slash
- cmp byte [nx_tagpos], 0
- jne .not_slash
- mov byte [nx_close], 1
- ret
- .not_slash:
- mov dl, al
- or dl, 0x20
- cmp dl, 'a'
- jb .notletter
- cmp dl, 'z'
- ja .notletter
- cmp byte [nx_inname], 0
- je .attr_letter
- cmp byte [nx_tagpos], 8
- jae .ret
- cmp byte [nx_close], 0
- jne .ret
- mov bl, [nx_tagpos]
- xor bh, bh
- mov [nx_tagbuf + bx], dl
- inc byte [nx_tagpos]
- ret
- .attr_letter:
- cmp dl, 's'
- jne .ret
- mov byte [nx_state], 3
- ret
- .notletter:
- mov byte [nx_inname], 0
- ret
- .tag_end:
- cmp byte [nx_close], 0
- jne .te_done
- cmp byte [nx_tagpos], 4
- jne .te_done
- cmp word [nx_tagbuf], 'te'
- jne .te_done
- cmp word [nx_tagbuf + 2], 'xt'
- jne .te_done
- mov byte [nx_state], 2
- mov byte [nx_tpos], 0
- ret
- .te_done:
- mov byte [nx_state], 0
- ret
- .s_title:
- cmp al, '<'
- jne .t_store
- mov bl, [nx_tpos]
- xor bh, bh
- mov byte [nx_tbuf + bx], 0
- mov byte [nx_tpend], 1
- mov byte [nx_state], 1
- mov byte [nx_tagpos], 0
- mov byte [nx_close], 0
- mov byte [nx_inname], 1
- ret
- .t_store:
- mov bl, [nx_tpos]
- cmp bl, 63
- jae .ret
- xor bh, bh
- mov [nx_tbuf + bx], al
- inc byte [nx_tpos]
- ret
- .s_r:
- cmp al, 'r'
- je .r_ok
- mov byte [nx_state], 1
- ret
- .r_ok:
- mov byte [nx_state], 4
- ret
- .s_c:
- cmp al, 'c'
- je .c_ok
- mov byte [nx_state], 1
- ret
- .c_ok:
- mov byte [nx_state], 5
- ret
- .s_eq:
- cmp al, '='
- je .eq_ok
- cmp al, ' '
- je .ret
- cmp al, 9
- je .ret
- mov byte [nx_state], 1
- ret
- .eq_ok:
- mov byte [nx_state], 6
- ret
- .s_quote:
- cmp al, 34
- je .q_ok
- cmp al, 39
- je .q_ok
- mov byte [nx_state], 1
- ret
- .q_ok:
- mov [nx_q], al
- mov byte [nx_spos], 0
- mov byte [nx_apos], 0
- mov byte [nx_state], 7
- ret
- .s_src:
- cmp al, [nx_q]
- je .src_end
- cmp al, '#'
- je .anchor
- mov bl, [nx_spos]
- cmp bl, 119
- jae .ret
- xor bh, bh
- mov [nx_sbuf + bx], al
- inc byte [nx_spos]
- ret
- .anchor:
- mov byte [nx_state], 8
- ret
- .src_end:
- call src_done
- mov byte [nx_state], 1
- ret
- .s_anchor:
- cmp al, [nx_q]
- je .src_end
- mov bl, [nx_apos]
- cmp bl, 31
- jae .ret
- xor bh, bh
- mov [nx_abuf + bx], al
- inc byte [nx_apos]
- ret
- .ret:
- ret
- src_done:
- mov bl, [nx_spos]
- xor bh, bh
- mov byte [nx_sbuf + bx], 0
- mov bl, [nx_apos]
- xor bh, bh
- mov byte [nx_abuf + bx], 0
- cmp byte [nx_tpend], 0
- je .done
- mov ax, [tcount]
- cmp ax, 32
- jae .done
- mov cx, ax
- shl ax, 1
- shl ax, 1
- shl ax, 1
- shl ax, 1
- shl ax, 1
- shl ax, 1
- mov di, ttit
- add di, ax
- mov byte [u_count], 0
- xor si, si
- xor dx, dx
- .tc:
- cmp dx, 63
- jae .td
- mov al, [nx_tbuf + si]
- test al, al
- jz .td
- call fold_to_di
- inc si
- inc dx
- jmp .tc
- .td:
- mov byte [di], 0
- mov ax, [tcount]
- mov bx, 120
- mul bx
- mov di, tsrc
- add di, ax
- xor si, si
- xor cx, cx
- .sc:
- cmp cx, 119
- jae .sd
- mov al, [nx_sbuf + si]
- test al, al
- jz .sd
- cmp al, 'A'
- jb .sl
- cmp al, 'Z'
- ja .sl
- add al, 32
- .sl:
- mov [di], al
- inc di
- inc si
- inc cx
- jmp .sc
- .sd:
- mov byte [di], 0
- mov ax, [tcount]
- shl ax, 1
- shl ax, 1
- shl ax, 1
- shl ax, 1
- shl ax, 1
- mov di, tanc
- add di, ax
- xor si, si
- xor cx, cx
- .ac:
- cmp cx, 31
- jae .ad
- mov al, [nx_abuf + si]
- test al, al
- jz .ad
- mov [di], al
- inc di
- inc si
- inc cx
- jmp .ac
- .ad:
- mov byte [di], 0
- inc word [tcount]
- mov byte [nx_tpend], 0
- .done:
- ret
- ;---------------------------------------------------------------- chapter helpers
- strcmp_t:
- .sl:
- mov al, [si]
- cmp al, [di]
- jne .no
- test al, al
- jz .yes
- inc si
- inc di
- jmp .sl
- .yes:
- stc
- ret
- .no:
- clc
- ret
- ends_with:
- mov bx, si
- xor cx, cx
- .sl:
- cmp byte [bx], 0
- je .gotl
- inc bx
- inc cx
- jmp .sl
- .gotl:
- mov si, lname
- xor di, di
- .ll:
- cmp byte [si], 0
- je .gotd
- inc si
- inc di
- jmp .ll
- .gotd:
- cmp cx, di
- ja .no
- sub si, cx
- sub bx, cx
- .cmp:
- cmp cx, 0
- je .yes
- mov al, [si]
- cmp al, [bx]
- jne .no
- inc si
- inc bx
- dec cx
- jmp .cmp
- .yes:
- stc
- ret
- .no:
- clc
- ret
- anchor_scan:
- cmp byte [out_on], 0
- jne .stopm
- mov si, [p_sanc]
- ANCH as_state, as_q, as_pos
- jnc .ret
- mov byte [out_on], 1
- ret
- .stopm:
- cmp word [p_panc], 0
- je .ret
- mov si, [p_panc]
- ANCH bs_state, bs_q, bs_pos
- jnc .ret
- mov byte [out_on], 0
- .ret:
- ret
- list_navpoints:
- mov word [ncxl], 0
- .ln_loop:
- mov ax, [ncxl]
- cmp ax, [tcount]
- jae .ln_done
- call print_nav_line
- inc word [ncxl]
- jmp .ln_loop
- .ln_done:
- ret
- print_nav_line:
- mov di, scratch + 8
- mov ax, [ncxl]
- inc ax
- mov bx, 10
- xor cx, cx
- .dig:
- xor dx, dx
- div bx
- add dl, '0'
- dec di
- mov [di], dl
- inc cx
- test ax, ax
- jnz .dig
- mov si, di
- mov di, tocline
- .cp:
- mov al, [si]
- mov [di], al
- inc si
- inc di
- loop .cp
- mov byte [di], ':'
- inc di
- mov byte [di], ' '
- inc di
- mov ax, [ncxl]
- shl ax, 1
- shl ax, 1
- shl ax, 1
- shl ax, 1
- shl ax, 1
- shl ax, 1
- mov si, ttit
- add si, ax
- .tcopy:
- mov al, [si]
- test al, al
- jz .fin
- mov [di], al
- inc si
- inc di
- jmp .tcopy
- .fin:
- mov byte [di], 13
- inc di
- mov byte [di], 10
- inc di
- mov cx, di
- sub cx, tocline
- mov dx, tocline
- mov ah, 0x40
- mov bx, [oh]
- int 0x21
- ret
- ;---------------------------------------------------------------- text layer
- emit_raw:
- mov bx, [wpos]
- mov [window + bx], al
- inc bx
- and bx, 0x7FFF
- mov [wpos], bx
- cmp byte [ncx_mode], 0
- jne ncx_feed
- cmp byte [anch_scan], 0
- je .tail
- call anchor_scan
- .tail:
- jmp feed
- feed:
- mov cl, [pstate]
- cmp cl, 1
- je .tag
- cmp cl, 2
- je .skip
- cmp cl, 3
- je .ent
- cmp al, '<'
- je .t_lt
- cmp al, '&'
- je .t_amp
- jmp emit_text
- .t_lt:
- mov byte [pstate], 1
- mov byte [tag_len], 0
- mov byte [tag_nl], 0
- ret
- .t_amp:
- mov byte [pstate], 3
- mov byte [ent_len], 0
- ret
- .tag:
- cmp al, '>'
- je .t_gt
- mov bl, [tag_len]
- cmp bl, 8
- jae .t_ret
- cmp al, 'A'
- jb .t_nolow
- cmp al, 'Z'
- ja .t_nolow
- add al, 32
- .t_nolow:
- xor bh, bh
- mov [tagbuf + bx], al
- inc byte [tag_len]
- cmp byte [tag_len], 1
- jne .t_ret
- cmp al, 'p'
- je .t_nl
- cmp al, 'b'
- je .t_nl
- cmp al, 'd'
- je .t_nl
- cmp al, 'h'
- je .t_nl
- cmp al, 'l'
- je .t_nl
- cmp al, 't'
- je .t_nl
- jmp .t_ret
- .t_nl:
- mov byte [tag_nl], 1
- .t_ret:
- ret
- .t_gt:
- mov byte [pstate], 0
- cmp byte [tag_nl], 0
- je .t_gt2
- mov al, 10
- call out_char
- .t_gt2:
- cmp byte [tag_len], 6
- jb .t_done
- cmp word [tagbuf], 'sc'
- jne .t_sty
- cmp word [tagbuf + 2], 'ri'
- jne .t_done
- cmp word [tagbuf + 4], 'pt'
- jne .t_done
- jmp .t_skip
- .t_sty:
- cmp word [tagbuf], 'st'
- jne .t_done
- cmp word [tagbuf + 2], 'yl'
- jne .t_done
- cmp byte [tagbuf + 4], 'e'
- jne .t_done
- .t_skip:
- mov byte [pstate], 2
- mov byte [sk_state], 0
- .t_done:
- ret
- .skip:
- mov cl, [sk_state]
- cmp cl, 1
- je .s1
- cmp cl, 2
- je .s2
- cmp al, '<'
- jne .s_ret
- mov byte [sk_state], 1
- ret
- .s1:
- cmp al, '/'
- je .s1a
- cmp al, '<'
- je .s_ret
- mov byte [sk_state], 0
- ret
- .s1a:
- mov byte [sk_state], 2
- mov byte [sk_len], 0
- ret
- .s2:
- cmp al, '>'
- je .s2end
- mov bl, [sk_len]
- cmp bl, 8
- jae .s_ret
- cmp al, 'A'
- jb .s2n
- cmp al, 'Z'
- ja .s2n
- add al, 32
- .s2n:
- xor bh, bh
- mov [skbuf + bx], al
- inc byte [sk_len]
- ret
- .s2end:
- cmp byte [sk_len], 6
- jb .s2no
- cmp word [skbuf], 'sc'
- jne .s2sty
- cmp word [skbuf + 2], 'ri'
- jne .s2no
- cmp word [skbuf + 4], 'pt'
- jne .s2no
- jmp .s2yes
- .s2sty:
- cmp word [skbuf], 'st'
- jne .s2no
- cmp word [skbuf + 2], 'yl'
- jne .s2no
- cmp byte [skbuf + 4], 'e'
- jne .s2no
- .s2yes:
- mov byte [pstate], 0
- .s2no:
- mov byte [sk_state], 0
- .s_ret:
- ret
- .ent:
- cmp al, ';'
- je .e_end
- mov bl, [ent_len]
- cmp bl, 7
- jae .e_flush
- xor bh, bh
- mov [entbuf + bx], al
- inc byte [ent_len]
- ret
- .e_end:
- call resolve_ent
- test ax, ax
- jz .e_flush
- call fold_out
- mov byte [pstate], 0
- ret
- .e_flush:
- mov al, '&'
- call out_char
- xor bl, bl
- .ef:
- cmp bl, [ent_len]
- jae .efd
- xor bh, bh
- mov al, [entbuf + bx]
- push bx
- call out_char
- pop bx
- inc bl
- jmp .ef
- .efd:
- mov byte [pstate], 0
- ret
- resolve_ent:
- cmp byte [entbuf], '#'
- je .num
- mov bl, [ent_len]
- cmp bl, 2
- je .l2
- cmp bl, 3
- je .l3
- cmp bl, 4
- je .l4
- xor ax, ax
- ret
- .l2:
- cmp word [entbuf], 'lt'
- jne .n2
- mov al, '<'
- ret
- .n2:
- cmp word [entbuf], 'gt'
- jne .no
- mov al, '>'
- ret
- .l3:
- cmp word [entbuf], 'am'
- jne .no
- cmp byte [entbuf + 2], 'p'
- jne .no
- mov al, '&'
- ret
- .l4:
- cmp word [entbuf], 'qu'
- jne .a4
- cmp word [entbuf + 2], 'ot'
- jne .no
- mov al, '"'
- ret
- .a4:
- cmp word [entbuf], 'ap'
- jne .n4
- cmp word [entbuf + 2], 'os'
- jne .no
- mov al, 39
- ret
- .n4:
- cmp word [entbuf], 'nb'
- jne .no
- cmp word [entbuf + 2], 'sp'
- jne .no
- mov al, ' '
- ret
- .num:
- xor ax, ax
- mov cl, 1
- .nl:
- cmp cl, [ent_len]
- jae .nd
- mov bl, cl
- xor bh, bh
- mov dl, [entbuf + bx]
- cmp dl, '0'
- jb .no
- cmp dl, '9'
- ja .no
- push cx
- sub dl, '0'
- mov bx, ax
- shl ax, 1
- shl ax, 1
- add ax, bx
- shl ax, 1
- xor dh, dh
- add ax, dx
- pop cx
- inc cl
- jmp .nl
- .nd:
- ret
- .no:
- xor al, al
- ret
- ;---------------------------------------------------------------- utf-8 -> ascii
- emit_text:
- cmp al, 0x80
- jb out_char
- mov cl, [u_count]
- test cl, cl
- jnz .cont
- cmp al, 0xC0
- jb .bad
- cmp al, 0xE0
- jb .lead2
- cmp al, 0xF0
- jb .lead3
- cmp al, 0xF8
- jb .lead4
- jmp .bad
- .lead2:
- and al, 0x1F
- xor ah, ah
- mov [u_cp], ax
- mov byte [u_count], 1
- ret
- .lead3:
- and al, 0x0F
- xor ah, ah
- mov [u_cp], ax
- mov byte [u_count], 2
- ret
- .lead4:
- and al, 0x07
- xor ah, ah
- mov [u_cp], ax
- mov byte [u_count], 3
- ret
- .cont:
- mov cl, al
- and cl, 0xC0
- cmp cl, 0x80
- jne .bad
- and al, 0x3F
- xor ah, ah
- mov bx, [u_cp]
- shl bx, 1
- shl bx, 1
- shl bx, 1
- shl bx, 1
- shl bx, 1
- shl bx, 1
- or bx, ax
- mov [u_cp], bx
- dec byte [u_count]
- jnz .ret
- mov ax, [u_cp]
- call fold_out
- .ret:
- ret
- .bad:
- mov byte [u_count], 0
- mov al, '?'
- jmp out_char
- fold_out:
- cmp ax, 0x80
- jb out_char
- cmp ax, 0x180
- jae .punct
- sub ax, 0x80
- mov bx, ax
- mov al, [foldtab + bx]
- jmp out_char
- .punct:
- cmp ax, 0x2018
- je .sq
- cmp ax, 0x2019
- je .sq
- cmp ax, 0x201C
- je .dq
- cmp ax, 0x201D
- je .dq
- cmp ax, 0x2013
- je .dash
- cmp ax, 0x2014
- je .dash
- cmp ax, 0x2026
- je .dots
- mov al, '?'
- jmp out_char
- .sq:
- mov al, 39
- jmp out_char
- .dq:
- mov al, 34
- jmp out_char
- .dash:
- mov al, '-'
- jmp out_char
- .dots:
- mov al, '.'
- jmp out_char
- fold_to_di:
- cmp al, 0x80
- jb .asc
- mov cl, [u_count]
- test cl, cl
- jnz .cont
- cmp al, 0xC0
- jb .bad
- cmp al, 0xE0
- jb .l2
- cmp al, 0xF0
- jb .l3
- cmp al, 0xF8
- jb .l4
- jmp .bad
- .l2:
- and al, 0x1F
- xor ah, ah
- mov [u_cp], ax
- mov byte [u_count], 1
- ret
- .l3:
- and al, 0x0F
- xor ah, ah
- mov [u_cp], ax
- mov byte [u_count], 2
- ret
- .l4:
- and al, 0x07
- xor ah, ah
- mov [u_cp], ax
- mov byte [u_count], 3
- ret
- .cont:
- mov cl, al
- and cl, 0xC0
- cmp cl, 0x80
- jne .bad
- and al, 0x3F
- xor ah, ah
- mov bx, [u_cp]
- shl bx, 1
- shl bx, 1
- shl bx, 1
- shl bx, 1
- shl bx, 1
- shl bx, 1
- or bx, ax
- mov [u_cp], bx
- dec byte [u_count]
- jnz .ret
- mov ax, [u_cp]
- call fold_char
- .ret:
- ret
- .asc:
- mov [di], al
- inc di
- ret
- .bad:
- mov byte [u_count], 0
- mov al, '?'
- mov [di], al
- inc di
- ret
- fold_char:
- cmp ax, 0x80
- jb .a
- cmp ax, 0x180
- jae .p
- sub ax, 0x80
- mov bx, ax
- mov al, [foldtab + bx]
- jmp .a
- .p:
- cmp ax, 0x2018
- je .sq
- cmp ax, 0x2019
- je .sq
- cmp ax, 0x201C
- je .dq
- cmp ax, 0x201D
- je .dq
- cmp ax, 0x2013
- je .da
- cmp ax, 0x2014
- je .da
- cmp ax, 0x2026
- je .do
- mov al, '?'
- jmp .a
- .sq:
- mov al, 39
- jmp .a
- .dq:
- mov al, 34
- jmp .a
- .da:
- mov al, '-'
- jmp .a
- .do:
- mov al, '.'
- .a:
- mov [di], al
- inc di
- ret
- ;---------------------------------------------------------------- word wrap
- out_char:
- cmp byte [out_on], 0
- jne .go
- ret
- .go:
- cmp al, 13
- je .drop
- cmp al, 9
- je .sp
- cmp al, 10
- je .nl
- cmp al, ' '
- je .sp
- mov bl, [ww_len]
- cmp bl, 100
- jae .wordfull
- xor bh, bh
- mov [ww_buf + bx], al
- inc byte [ww_len]
- ret
- .wordfull:
- call flush_word_raw
- mov bl, [ww_len]
- xor bh, bh
- mov [ww_buf + bx], al
- inc byte [ww_len]
- ret
- .drop:
- ret
- .nl:
- cmp byte [ww_len], 0
- je .nl2
- cmp byte [ww_sp], 0
- je .nl1
- cmp word [ww_col], 0
- je .nl1
- mov al, ' '
- call raw_out
- inc word [ww_col]
- .nl1:
- call emit_word
- .nl2:
- mov al, 10
- call raw_out
- mov word [ww_col], 0
- mov byte [ww_sp], 0
- ret
- .sp:
- call place_word
- mov byte [ww_sp], 1
- ret
- place_word:
- cmp byte [ww_len], 0
- je .ret
- cmp word [ww_col], 0
- je .atstart
- mov bx, [ww_col]
- cmp byte [ww_sp], 0
- je .nopre
- inc bx
- .nopre:
- mov al, [ww_len]
- xor ah, ah
- add bx, ax
- cmp bx, [wrapw]
- ja .wrap
- cmp byte [ww_sp], 0
- je .emit
- mov al, ' '
- call raw_out
- inc word [ww_col]
- .emit:
- call emit_word
- ret
- .wrap:
- mov al, 10
- call raw_out
- mov word [ww_col], 0
- call emit_word
- ret
- .atstart:
- call emit_word
- .ret:
- ret
- emit_word:
- xor bx, bx
- .l:
- cmp bl, [ww_len]
- jae .d
- mov al, [ww_buf + bx]
- push bx
- call raw_out
- pop bx
- inc bl
- jmp .l
- .d:
- mov al, [ww_len]
- xor ah, ah
- add [ww_col], ax
- mov byte [ww_len], 0
- ret
- flush_word_raw:
- cmp byte [ww_sp], 0
- je .f1
- cmp word [ww_col], 0
- je .f1
- mov al, ' '
- call raw_out
- inc word [ww_col]
- .f1:
- mov al, [ww_len]
- xor ah, ah
- mov bx, [ww_col]
- add bx, ax
- cmp bx, [wrapw]
- jbe .fit
- cmp word [ww_col], 0
- je .fit
- mov al, 10
- call raw_out
- mov word [ww_col], 0
- .fit:
- call emit_word
- mov byte [ww_sp], 0
- ret
- raw_out: ; al -> outbuf; LF expanded to CRLF; page bookkeeping
- cmp al, 10
- jne .main
- push ax
- mov al, 13 ; CR first
- call raw_store
- pop ax
- .main:
- call raw_store
- cmp byte [paging], 0
- je .ret
- cmp al, 10
- jne .ret
- inc word [wlines]
- mov bx, [pagel]
- cmp [wlines], bx
- jb .ret
- mov word [wlines], 0
- mov ax, [pgused]
- cmp ax, 1024
- jae .ret
- shl ax, 1
- shl ax, 1
- mov di, pgidx
- add di, ax
- mov bx, [tmppos_lo]
- add bx, [outbuf_len]
- mov [di], bx
- mov bx, [tmppos_hi]
- adc bx, 0
- mov [di + 2], bx
- inc word [pgused]
- .ret:
- ret
- raw_store: ; al -> outbuf; flush at OUTBUF_SIZE
- mov bx, [outbuf_len]
- mov [outbuf + bx], al
- inc bx
- mov [outbuf_len], bx
- cmp bx, OUTBUF_SIZE
- jb .ok
- call flush_out
- .ok:
- ret
- wrap_finish:
- call place_word
- cmp word [ww_col], 0
- je .wfd
- mov al, 10
- call raw_out
- mov word [ww_col], 0
- .wfd:
- ret
- flush_out:
- push bx
- push cx
- push dx
- push si
- push di
- mov cx, [outbuf_len]
- test cx, cx
- jz .z
- mov ah, 0x40
- mov bx, [oh]
- mov dx, outbuf
- int 0x21
- cmp byte [paging], 0
- je .nc
- add [tmppos_lo], ax
- adc word [tmppos_hi], 0
- .nc:
- mov word [outbuf_len], 0
- .z:
- pop di
- pop si
- pop dx
- pop cx
- pop bx
- ret
- ;---------------------------------------------------------------- data
- order: db 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15
- len_base: dw 3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59
- dw 67,83,99,115,131,163,195,227,258
- len_extra: db 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0
- dist_base: dw 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769
- dw 1025,1537,2049,3073,4097,6145,8193,12289,16385,24577
- dist_extra: db 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13
- msg_usage: db "usage: epub2txt <file.epub> [-w W] [-p L] [-l | N]", 13, 10, "$"
- msg_bad: db "error: not a valid epub/zip", 13, 10, "$"
- msg_nosec: db "section not found", 13, 10, "$"
- tmpname: db "EPUB2TX.$$$", 0
- p_msg: db "-- more --$"
- p_erase: db 13, " ", 13
- foldtab:
- db '?','?',',','f','"','.','+','+','^','%','S','<','O','?','Z','?'
- db '?',39,39,34,34,'*','-','-','~','?','s','>','o','?','z','Y'
- db ' ','!','c','L','?','Y','|','?','?','?','a','<','?','?','?','?'
- db '?','+','2','3','?','u','?','.','?','1','o','>','?','?','?','?'
- db 'A','A','A','A','A','A','A','C','E','E','E','E','I','I','I','I'
- db 'D','N','O','O','O','O','O','*','O','U','U','U','U','Y','T','s'
- db 'a','a','a','a','a','a','a','c','e','e','e','e','i','i','i','i'
- db 'd','n','o','o','o','o','o','/','o','u','u','u','u','y','t','y'
- db 'A','a','A','a','A','a','C','c','C','c','C','c','C','c','D','d'
- db 'D','d','E','e','E','e','E','e','E','e','E','e','G','g','G','g'
- db 'G','g','G','g','H','h','H','h','I','i','I','i','I','i','I','i'
- db 'I','i','I','i','J','j','K','k','k','L','l','L','l','L','l','L'
- db 'l','L','l','N','n','N','n','N','n','n','N','n','O','o','O','o'
- db 'O','o','O','o','R','r','R','r','R','r','S','s','S','s','S','s'
- db 'S','s','T','t','T','t','T','t','U','u','U','u','U','u','U','u'
- db 'U','u','W','w','Y','y','Y','Z','z','Z','z','Z','z','Z','z','s'
- ; globals
- fh: dw 0
- oh: dw 1
- th: dw 0
- paging: db 0
- tmppos_lo: dw 0
- tmppos_hi: dw 0
- wlines: dw 0
- pgused: dw 0
- page: dw 0
- pages: dw 0
- linecnt: dw 0
- rdlen: dw 0
- seccnt: dw 0
- cursec: dw 0
- wrapw: dw 78
- pagel: dw 24
- respage: dw 0
- mode: db 0
- chapnum: dw 0
- chapfound: db 0
- seli: dw 0
- p_fsrc: dw 0
- p_sanc: dw 0
- p_panc: dw 0
- out_on: db 1
- anch_scan: db 0
- as_state: db 0
- as_q: db 0
- as_pos: db 0
- bs_state: db 0
- bs_q: db 0
- bs_pos: db 0
- ww_col: dw 0
- ww_len: db 0
- ww_sp: db 0
- ncx_mode: db 0
- nx_state: db 0
- nx_tagpos: db 0
- nx_close: db 0
- nx_inname: db 0
- nx_q: db 0
- nx_tpend: db 0
- nx_spos: db 0
- nx_apos: db 0
- nx_tpos: db 0
- tcount: dw 0
- ncxl: dw 0
- inbuf_len: dw 0
- inbuf_pos: dw 0
- cur_byte: db 0
- bit_idx: db 0
- wpos: dw 0
- outbuf_len: dw 0
- eocd_entries: dw 0
- eocd_cdoff_lo: dw 0
- eocd_cdoff_hi: dw 0
- cdpos_lo: dw 0
- cdpos_hi: dw 0
- nentries: dw 0
- scan_lo: dw 0
- scan_hi: dw 0
- chunklen: dw 0
- fsize_lo: dw 0
- fsize_hi: dw 0
- cand_lo: dw 0
- cand_hi: dw 0
- method: dw 0
- csz_lo: dw 0
- csz_hi: dw 0
- cnamelen: dw 0
- cextralen: dw 0
- ccommentlen: dw 0
- lhoff_lo: dw 0
- lhoff_hi: dw 0
- slen: dw 0
- snlen: dw 0
- bfinal: dw 0
- nlit: dw 0
- ndist: dw 0
- ncl: dw 0
- totl: dw 0
- hci: dw 0
- repn: dw 0
- mlen: dw 0
- mdist: dw 0
- mtmp: dw 0
- cidx: db 0
- u_count: db 0
- u_cp: dw 0
- h_code: dw 0
- h_first: dw 0
- h_index: dw 0
- bt_lens: dw 0
- bt_n: dw 0
- bt_cnt: dw 0
- bt_sym: dw 0
- pstate: db 0
- tag_len: db 0
- tag_nl: db 0
- ent_len: db 0
- sk_state: db 0
- sk_len: db 0
- ; buffers
- iname: times 64 db 0
- oname: times 8 db 0
- nbuf: times 250 db 0
- lname: times 250 db 0
- cdbuf: times 46 db 0
- lhbuf: times 30 db 0
- eocdbuf: times 22 db 0
- tagbuf: times 8 db 0
- entbuf: times 8 db 0
- skbuf: times 8 db 0
- nx_tagbuf: times 9 db 0
- nx_tbuf: times 64 db 0
- nx_sbuf: times 120 db 0
- nx_abuf: times 32 db 0
- tocline: times 280 db 0
- scratch: times 8 db 0
- ww_buf: times 100 db 0
- pbuf: times 128 db 0
- bkmname: times 70 db 0
- bkmline: times 20 db 0
- tsrc: times 3840 db 0
- ttit: times 2048 db 0
- tanc: times 1024 db 0
- pgidx: times 4096 db 0
- secidx: times 128 db 0
- cl_lens: times 19 db 0
- lens: times 320 db 0
- counts_lit: times 16 dw 0
- counts_dist: times 16 dw 0
- counts_cl: times 16 dw 0
- offs: times 16 dw 0
- syms_lit: times 288 dw 0
- syms_dist: times 32 dw 0
- syms_cl: times 19 dw 0
- outbuf: times OUTBUF_SIZE db 0
- inbuf: times INBUF_SIZE db 0
- window: times 32768 db 0
Add Comment
Please, Sign In to add comment