RLEASM.ASM 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597
  1. ; The Catacomb Source Code
  2. ; Copyright (C) 1993-2014 Flat Rock Software
  3. ;
  4. ; This program is free software; you can redistribute it and/or modify
  5. ; it under the terms of the GNU General Public License as published by
  6. ; the Free Software Foundation; either version 2 of the License, or
  7. ; (at your option) any later version.
  8. ;
  9. ; This program is distributed in the hope that it will be useful,
  10. ; but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. ; GNU General Public License for more details.
  13. ;
  14. ; You should have received a copy of the GNU General Public License along
  15. ; with this program; if not, write to the Free Software Foundation, Inc.,
  16. ; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  17. %NOLIST
  18. %TITLE "RLE compression v0.00"
  19. ;==========================================================
  20. ; RLE compression in assemlby.
  21. ; Written by Lane Roath, Copyright (c) 1990 IFD & Softdisk
  22. ;
  23. ;----------------------------------------------------------
  24. ;
  25. ;09-Aug-90 0.00 Start coding, converting source C in Dr. Dobb's
  26. ;
  27. ;==========================================================
  28. IDEAL
  29. MODEL small,C
  30. STACK 0200
  31. ;==========================================================
  32. MinCnt = 3-1 ;min count for repeat
  33. MaxCnt = 127+MinCnt ;max count (128+ = non repeat string)
  34. DATASEG
  35. handle dw ? ;file i/o requirements are here!
  36. flength1 dw ?
  37. flength2 dw ?
  38. buf1 dw ?
  39. buf2 dw ?
  40. foff1 dw ?
  41. foff2 dw ?
  42. ; We store our memory allocation results here
  43. RLESeg dw ? ;RLE packed buf (src/dest)
  44. SrcSeg dw ? ;original source data
  45. RLEIdx dw ? ;indexes for read/write bufs
  46. SRCIdx dw ?
  47. SrcLen dw 2 dup (?) ;length of source & dest bufs
  48. RLELen dw 2 dup (?)
  49. ByteCnt dw ? ;# of sequential bytes
  50. LastByte db ? ;last byte found
  51. DifCnt dw ? ;# of different bytes
  52. EndByte dw ?
  53. ;==========================================================
  54. ;
  55. CODESEG
  56. ;
  57. ;==========================================================
  58. ;
  59. ; Initialize our variables & buffers
  60. ;
  61. ;==========================================================
  62. PROC InitRLE ;internal
  63. mov [ByteCnt],0
  64. mov [DifCnt],1
  65. mov [RLELen],0
  66. mov [RLELen+2],0
  67. mov SI,[SrcIdx] ;init Source Index (SrcIdx)
  68. mov DI,[RLEIdx] ; & dest index (RLEIdx)
  69. ret
  70. ENDP
  71. ;==========================================================
  72. ;
  73. ; Output a compression string (repeated bytes)
  74. ;
  75. ;==========================================================
  76. PROC OutputRep
  77. push SI
  78. push ES ;save needed registers
  79. push AX
  80. mov ES,[RLESeg] ;get dest buffer seg
  81. mov AX,[ByteCnt]
  82. sub AL,2 ;get byte count - 3 (already -1)
  83. stosb
  84. mov AL,[LastByte] ; & output byte to repeat
  85. stosb
  86. mov SI,[SrcIdx]
  87. inc SI ;update source index (length + 1)
  88. add SI,[ByteCnt]
  89. mov [SrcIdx],SI ; & save for next output
  90. add [RLELen],2 ;update RLE length
  91. adc [RLELen+2],0
  92. mov [ByteCnt],0 ;we output everything!
  93. pop AX
  94. pop ES ;restore registers
  95. ; mov BL,[ES:SI]
  96. ; mov [LastByte],BL ;this is 'last' byte!
  97. pop SI
  98. ret
  99. ENDP
  100. ;==========================================================
  101. ;
  102. ; Output a unique string with count byte preceeding
  103. ;
  104. ;==========================================================
  105. PROC OutputDif
  106. push ES ;save important registers
  107. push AX
  108. push SI
  109. mov ES,[RLESeg] ;get dest buffer seg
  110. mov AX,[DifCnt]
  111. add AL,7Fh ; & save byte count - 1 with hi bit set
  112. stosb
  113. mov CX,[DifCnt] ;get # of bytes to copy
  114. mov AX,CX ;# of bytes read (count is -1)
  115. inc AX
  116. add [RLELen],AX ;update RLE length
  117. adc [RLELen+2],0
  118. mov SI,[SrcIdx] ; & starting position in source
  119. push DS
  120. mov DS,[SrcSeg] ;set source seg
  121. REP movsb
  122. pop DS ; & copy the string
  123. mov [DifCnt],0 ;we output everything!
  124. mov [SrcIdx],SI ;save for next output
  125. pop SI
  126. pop AX
  127. pop ES ;restore registers
  128. ret
  129. ENDP
  130. ;==========================================================
  131. ;
  132. ; EXPAND a RLE compressed file segment
  133. ;
  134. ;==========================================================
  135. PUBLIC Expand
  136. PROC Expand
  137. call InitRLE ;init our vars & buffers
  138. xchg SI,DI ;swap SI and DI
  139. mov DX,1
  140. @@bank:
  141. mov ES,[SrcSeg] ;point to source buffer
  142. xor AH,AH
  143. @@get:
  144. cmp DI,0FFF0h ;don't bog us down!
  145. jb @@ok
  146. mov AX,DI
  147. shr AX,1
  148. shr AX,1 ;offset / 16
  149. shr AX,1
  150. shr AX,1
  151. add [SrcSeg],AX ; + seg reg = normalized ptr
  152. ; and DI,0Fh
  153. mov DI,0
  154. mov AX,SI
  155. shr AX,1
  156. shr AX,1 ;offset / 16
  157. shr AX,1
  158. shr AX,1
  159. add [RLESeg],AX ; + segment register = normalized ptr
  160. and SI,0Fh
  161. jmp SHORT @@bank
  162. @@ok:
  163. sub [SrcLen],DX ;subtract out # of chars
  164. sbb [SrcLen+2],0
  165. jc @@Done ;exit if we are done!
  166. xor DX,DX
  167. @@0:
  168. push DS
  169. mov DS,[RLESeg] ;point to RLE buffer
  170. lodsb ; & get code byte
  171. cmp AL,80h
  172. jb @@rpt ;repeat code?
  173. sub AL,7Fh
  174. mov CX,AX ; no- string length = code - $80 + 1
  175. mov DX,AX
  176. REP movsb ;copy string
  177. pop DS
  178. jmp SHORT @@get ; & do some more
  179. @@rpt:
  180. add AL,3 ;# of bytes = code + 3
  181. mov CX,AX
  182. mov DX,AX
  183. lodsb ;get byte to repeat
  184. REP stosb
  185. pop DS ; & store that many bytes
  186. jmp SHORT @@get
  187. @@Done:
  188. ret
  189. ENDP
  190. ;==========================================================
  191. ;
  192. ; COMPRESS data buffer using RLE
  193. ;
  194. ;==========================================================
  195. PUBLIC Compress
  196. PROC Compress
  197. call InitRLE ;init vars
  198. @@bank:
  199. mov ES,[SrcSeg] ;get first byte of data
  200. mov AL,[ES:SI]
  201. mov [LastByte],AL ; & set as last byte
  202. @@get:
  203. cmp SI,0FF00h ;don't bog us down!
  204. jb @@ok
  205. jmp @@Done ;send any patial strings!
  206. mov AX,SI
  207. shr AX,1
  208. shr AX,1 ;offset / 16
  209. shr AX,1
  210. shr AX,1
  211. add [SrcSeg],AX ; + segment register = normalized
  212. and SI,0Fh
  213. mov [SrcIdx],0 ;which is our new 'start'
  214. mov AX,DI
  215. shr AX,1
  216. shr AX,1 ;offset / 16
  217. shr AX,1
  218. shr AX,1
  219. add [RLESeg],AX ; + segment register = normalized ptr
  220. and DI,0Fh
  221. inc [DifCnt]
  222. jmp SHORT @@bank
  223. @@ok:
  224. sub [SrcLen],1 ;subtract out # of chars
  225. sbb [SrcLen+2],0
  226. jnc @@0
  227. jmp NEAR @@Done ;exit if we are done!
  228. @@0:
  229. inc SI ;get next byte
  230. mov AL,[ES:SI]
  231. cmp AL,[LastByte]
  232. jne @@dif ;same as last byte?
  233. inc [ByteCnt] ; yes- count it
  234. cmp [ByteCnt],MinCnt
  235. jb @@get
  236. cmp [DifCnt],1 ;ok, got a rep string...already have dif?
  237. jbe @@same
  238. dec [DifCnt]
  239. call OutputDif ; yes- output that string first
  240. @@same:
  241. mov [DifCnt],0 ;force even if not output!
  242. cmp [ByteCnt],MaxCnt
  243. jb @@get ;have we gotten too big?
  244. call OutputRep ; yes, save string & continue
  245. cmp AL,[ES:SI+1] ;another repeat?
  246. jne @@gget
  247. cmp AL,[ES:SI+2]
  248. jne @@gget
  249. inc SI ;need this for >127 byte strings!
  250. @@gget: jmp NEAR @@get
  251. ;-------------------------------------------------------------
  252. @@dif:
  253. mov CX,[ByteCnt] ;any dups yet?
  254. jcxz @@cnt
  255. cmp CX,MinCnt ;repeats before now?
  256. jb @@add
  257. call OutputRep ; yes- save repeat bytes
  258. jmp SHORT @@cnt
  259. @@add:
  260. add [DifCnt],CX ;add bad repeats to dif count
  261. mov [ByteCnt],0 ; & no more dupes!
  262. @@cnt:
  263. inc [DifCnt] ;count byte as different
  264. mov [LastByte],AL
  265. cmp [DifCnt],MaxCnt-MinCnt-1 ;still in range?
  266. jb @@goget
  267. call OutputDif ; no- output string & continue
  268. ; mov AL,[ES:SI+1]
  269. cmp AL,[ES:SI+1]
  270. jne @@goget ;if repeat follows, specialize!
  271. cmp AL,[ES:SI+2]
  272. jne @@goget
  273. inc SI ;why?
  274. inc [DifCnt]
  275. @@goget:
  276. jmp NEAR @@get
  277. ;-------------------------------------------------------------
  278. @@Done:
  279. mov CX,[ByteCnt] ;any reps left?
  280. jcxz @@1
  281. cmp CX,MinCnt ; yes- enough to output?
  282. jb @@2
  283. cmp [DifCnt],1 ; yes, any difs before these?
  284. jb @@3
  285. call OutputDif ; yes- output them
  286. @@3:
  287. call OutputRep ;output rep bytes
  288. jmp SHORT @@4
  289. @@2:
  290. add [DifCnt],CX ;update dif count w/small rep
  291. @@1:
  292. mov CX,[DifCnt] ;anything to output?
  293. jcxz @@4
  294. call OutputDif ;output dif string
  295. @@4:
  296. ret
  297. ENDP
  298. ;====================================================
  299. ;
  300. ; C interface to compress file
  301. ;
  302. ;====================================================
  303. PUBLIC RLECompress
  304. PROC RLECompress NEAR Source:DWORD,_Length:DWORD,Destination:DWORD
  305. mov AX,[WORD Source]
  306. mov [SrcIdx],AX
  307. mov AX,[WORD Source+2]
  308. mov [SrcSeg],AX ;set source buffer
  309. mov AX,[WORD Destination]
  310. mov [RLEIdx],AX
  311. mov AX,[WORD Destination+2]
  312. mov [RLESeg],AX ; & destination buffer
  313. mov AX,[WORD _Length]
  314. mov [SrcLen],AX ;save length
  315. mov AX,[WORD _Length+2]
  316. mov [SrcLen+2],AX
  317. call Compress ;do the compression
  318. mov AX,[RLELen] ;return length of compressed file
  319. mov DX,[RLELen+2]
  320. ret
  321. ENDP
  322. ;====================================================
  323. ;
  324. ; C interface to expand file
  325. ;
  326. ;====================================================
  327. PUBLIC RLEExpand
  328. PROC RLEExpand NEAR Source:DWORD,Destination:DWORD,_Length:DWORD
  329. mov AX,[WORD Source]
  330. mov [RLEIdx],AX
  331. mov AX,[WORD Source+2]
  332. mov [RLESeg],AX ;set source buffer
  333. mov AX,[WORD Destination]
  334. mov [SrcIdx],AX
  335. mov AX,[WORD Destination+2]
  336. mov [SrcSeg],AX ; & destination buffer
  337. mov AX,[WORD _Length]
  338. mov [SrcLen],AX ;save length
  339. mov AX,[WORD _Length+2]
  340. mov [SrcLen+2],AX
  341. call Expand ;do the expansion
  342. ret
  343. ENDP
  344. end
  345. ;=============================================
  346. ;
  347. ; Load a *LARGE* file into a FAR buffer!
  348. ; by John Romero (C) 1990 PCRcade
  349. ; To seperate ASM code by Lane Roath
  350. ;
  351. ;=============================================
  352. PUBLIC LoadFile
  353. PROC LoadFile NEAR filename:WORD,buffer:DWORD
  354. mov AX,[WORD buffer] ;buf1=FP_OFF(buffer)
  355. mov [buf1],AX
  356. mov AX,[WORD buffer+2] ;buf2=FP_SEG(buffer)
  357. mov [buf2],AX
  358. mov [foff1],0 ;file offset = 0 (start)
  359. mov [foff2],0
  360. mov dx,[filename]
  361. mov ax,3d00h ;OPEN w/handle (read only)
  362. int 21h
  363. jc @@out
  364. mov [handle],ax
  365. mov bx,ax
  366. xor cx,cx
  367. xor dx,dx
  368. mov ax,4202h
  369. int 21h ;SEEK (find file length)
  370. jc @@out
  371. mov [flength1],ax
  372. mov [flength2],dx
  373. mov cx,[flength2]
  374. inc cx ;<- at least once!
  375. @@L_1:
  376. push cx
  377. mov cx,[foff2]
  378. mov dx,[foff1]
  379. mov ax,4200h
  380. int 21h ;SEEK from start
  381. push ds
  382. mov bx,[handle]
  383. mov cx,-1
  384. mov dx,[buf1]
  385. mov ax,[buf2]
  386. mov ds,ax
  387. mov ah,3fh ;READ w/handle
  388. int 21h
  389. pop ds
  390. pop cx
  391. jc @@out
  392. cmp ax,-1
  393. jne @@out
  394. push cx ;need to read the last byte
  395. push ds ;into the segment! IMPORTANT!
  396. mov bx,[handle]
  397. mov cx,1
  398. mov dx,[buf1]
  399. add dx,-1
  400. mov ax,[buf2]
  401. mov ds,ax
  402. mov ah,3fh
  403. int 21h
  404. pop ds
  405. pop cx
  406. add [buf2],1000h
  407. inc [foff2]
  408. loop @@L_1
  409. @@out:
  410. mov bx,[handle] ;CLOSE w/handle
  411. mov ah,3eh
  412. int 21h
  413. mov AX,[flength1] ;(flength2*0x10000+flength1)
  414. mov DX,[flength2]
  415. ret
  416. ENDP
  417. ;=============================================
  418. ;
  419. ; Save a *LARGE* file from a FAR buffer!
  420. ; by John Romero (C) 1990 PCRcade
  421. ; To seperate ASM code by Lane Roath
  422. ;
  423. ;=============================================
  424. PUBLIC SaveFile
  425. PROC SaveFile NEAR filename:WORD,buffer:DWORD,fsize:DWORD
  426. mov AX,[WORD buffer] ;buf1=FP_OFF(buffer)
  427. mov [buf1],AX
  428. mov AX,[WORD buffer+2] ;buf2=FP_SEG(buffer)
  429. mov [buf2],AX
  430. mov [foff1],0 ;file offset = 0 (start)
  431. mov [foff2],0
  432. mov dx,[filename]
  433. mov ax,3c00h ;CREATE w/handle (read only)
  434. xor cx,cx
  435. int 21h
  436. jc @@out
  437. mov [handle],ax
  438. cmp [WORD fsize+2],0 ;larger than 1 segment?
  439. je @@L2
  440. @@L1:
  441. push ds
  442. mov bx,[handle]
  443. mov cx,8000h
  444. mov dx,[buf1]
  445. mov ax,[buf2]
  446. mov ds,ax
  447. mov ah,40h ;WRITE w/handle
  448. int 21h
  449. pop ds
  450. add [buf2],800h ;bump ptr up 1/2 segment
  451. sub [WORD fsize],8000h ;done yet?
  452. sbb [WORD fsize+2],0
  453. cmp [WORD Fsize+2],0
  454. ja @@L1
  455. cmp [WORD fsize],8000h
  456. jae @@L1
  457. @@L2:
  458. push ds
  459. mov bx,[handle]
  460. mov cx,[WORD fsize]
  461. mov dx,[buf1]
  462. mov ax,[buf2]
  463. mov ds,ax
  464. mov ah,40h ;WRITE w/handle
  465. int 21h
  466. pop ds
  467. @@out:
  468. mov bx,[handle] ;CLOSE w/handle
  469. mov ah,3eh
  470. int 21h
  471. RET
  472. ENDP
  473. END