Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
31 halyavin 1
;
2
; MHC archiver for MenuetOS - very fast compression tool
3
;
4
; version 0.09
5
;
6
; Written by Nikita Lesnikov (nlo_one@mail.ru, Republic of Belarus, Sluck)
7
;
8
 
9
;==============================================================================
10
 
11
;
12
; Brief file format description:
13
;
14
;                  +-----------+------------------------+
15
;  File structure: | Method ID | Compressed data        |
16
;                  +-----------+------------------------+
17
;
18
;  Methods list:
19
;
20
;    0. LZP (order-2 specified specially for *.ASM,*.RAW and MeOS executables)
21
;
22
;  New methods can be easily added without loss of compatibility
23
; with older versions
24
;
25
 
26
;==============================================================================
27
 
28
; SYSTEM HEADER
29
 
30
use32
31
 
32
  org 0x0
33
  db "MENUET01"
34
  dd 0x01
35
  dd ENTRANCE
36
  dd MHC_END
37
  dd 0x300000  ; 3 megs of memory needed
38
  dd 0x2FF000
39
  dd 0x0
40
  dd 0x0
41
 
42
include 'lang.inc'
43
include 'macros.inc'
44
; CODE AREA
45
 
46
ENTRANCE:
47
 
48
; ======== user interface =========
49
 
50
 
51
 call draw_window             ; draw the window
52
 
53
 still:
54
 
55
 mov eax,10                   ; wait for event
56
 int 0x40
57
 
58
 cmp eax,1                    ; redraw?
59
 jnz no_redraw
60
 call draw_window
61
 no_redraw:
62
 
63
 cmp eax,2                    ; key pressed?
64
 jz key
65
 
66
 cmp eax,3                    ; button pressed?
67
 jz button
68
 
69
 jmp still
70
 
71
 ; Key handler
72
 
73
 key:
74
 mov eax,2   ; read it
75
 int 0x40
76
 shr eax,8
77
 
78
 cmp byte [editstate],0
79
 jz  still
80
 
81
 cmp al,8    ; backspace
82
 jnz no_bksp
83
 cmp byte [editpos],0
84
 jz  no_del_last
85
 dec byte [editpos]
86
 xor ebx,ebx
87
 mov bl,byte [editpos]
88
 add ebx,cmfile
89
 cmp byte [editstate],2
90
 jnz no_add_base_1
91
 add ebx,12
92
 no_add_base_1:
93
 mov byte [ebx],32
94
 no_del_last:
95
 call draw_info
96
 jmp still
97
 no_bksp:
98
 
99
 cmp al,13            ; enter
100
 jnz no_enter
101
 mov byte [editstate],0
102
 call draw_info
103
 jmp still
104
 no_enter:
105
 
106
 cmp eax,dword 31
107
 jbe no_lit
108
 cmp eax,dword 95
109
 jb  capital
110
 sub eax,32
111
 capital:
112
 xor ebx,ebx
113
 mov bl,byte [editpos]
114
 add ebx,cmfile
115
 cmp byte [editstate],2
116
 jnz no_add_base_2
117
 add ebx,12
118
 no_add_base_2:
119
 mov byte [ebx],al
120
 inc byte [editpos]
121
 cmp byte [editpos],12
122
 jnz no_null_state
123
 mov byte [editstate],0
124
 no_null_state:
125
 call draw_info
126
 no_lit:
127
 
128
 jmp still
129
 
130
 ; Button handler
131
 
132
 button:
133
 
134
 mov eax,17
135
 int 0x40
136
 
137
 cmp ah,1
138
 jnz no_quit
139
 mov eax,-1
140
 int 0x40
141
 no_quit:
142
 
143
 cmp ah,4
144
 jnz nofirst
145
 cld
146
 mov byte [editstate],1
147
 mov edi,cmfile
148
 mov eax,0x20202020
149
 mov ecx,3
150
 rep stosd
151
 mov byte [editpos],0
152
 mov byte [msgid],0
153
 call draw_info
154
 nofirst:
155
 
156
 cmp ah,5
157
 jnz nosecond
158
 cld
159
 mov byte [editstate],2
160
 mov edi,iofile
161
 mov eax,0x20202020
162
 mov ecx,3
163
 rep stosd
164
 mov byte [editpos],0
165
 mov byte [msgid],0
166
 call draw_info
167
 nosecond:
168
 
169
 cmp ah,2
170
 jnz no_compress
171
 call compress
172
 no_compress:
173
 
174
 cmp ah,3
175
 jnz no_decompress
176
 call decompress
177
 no_decompress:
178
 
179
 cmp ah,6
180
 jnz no_delete_io
181
 pusha
182
 mov eax,32
183
 mov ebx,iofile
184
 int 0x40
185
 popa
186
 no_delete_io:
187
 
188
 cmp ah,7
189
 jnz  no_delete_archive
190
 pusha
191
 mov eax,32
192
 mov ebx,cmfile
193
 int 0x40
194
 popa
195
 no_delete_archive:
196
 
197
 jmp still
198
 
199
 ; WINDOW DRAW
200
 
201
 draw_window:
202
 
203
 mov eax,12  ; Start redrawing
204
 mov ebx,1
205
 int 0x40
206
 
207
 xor eax,eax           ; Define window
208
 mov ebx,100*65536+240
209
 mov ecx,100*65536+130
210
 mov edx,0x02AAAAAA
211
 mov esi,0x80777777
212
 mov edi,0x00777777
213
 int 0x40
214
 
215
 mov eax,4              ; Draw all needed texts
216
 mov ebx,8*65536+8
217
 mov ecx,0x00FFFFFF
218
 mov edx,title
219
 mov esi,arclab-title
220
 int 0x40
221
 
222
 xor ecx,ecx
223
 mov edx,arclab
224
 mov esi,unplab-arclab
225
 add ebx,10*65536+28
226
 int 0x40
227
 
228
 mov edx,unplab
229
 mov esi,fin_text-unplab
230
 add ebx,18
231
 int 0x40
232
 
233
 pusha
234
 
235
 mov eax,8            ; Buttons
236
 mov ebx,222*65536+10
237
 mov ecx,6*65536+10
238
 mov edx,1
239
 mov esi,0x555555
240
 int 0x40
241
 
242
 mov ebx,15*65536+100
243
 mov ecx,70*65536+13
244
 inc edx
245
 int 0x40
246
 
247
 inc edx
248
 add ebx,110*65536
249
 int 0x40
250
 
251
 inc edx
252
 mov ebx,214*65536+11
253
 mov ecx,33*65536+11
254
 int 0x40
255
 
256
 inc edx
257
 add ecx,18*65536
258
 int 0x40
259
 
260
 inc edx
261
 mov ebx,15*65536+100
262
 mov ecx,86*65536+13
263
 int 0x40
264
 
265
 inc edx
266
 add ebx,110*65536
267
 int 0x40
268
 
269
 popa
270
 
271
 mov ecx,0x00FFFFFF
272
 mov edx,keylab
273
 mov esi,dellab-keylab
274
 add ebx,19
275
 int 0x40
276
 
277
 mov edx,dellab
278
 mov esi,title-dellab
279
 add ebx,16
280
 int 0x40
281
 
282
 call draw_info
283
 
284
 mov eax,12          ; Finish redrawing
285
 mov ebx,2
286
 int 0x40
287
 
288
 ret
289
 
290
 draw_info:          ; Draw filenames and compressor state
291
 
292
 activecolor equ 0x00112299
293
 
294
 pusha ; Save registers
295
 
296
 mov eax,13               ; Clean draw area
297
 mov ebx,127*65536+85
298
 mov ecx,33*65536+33
299
 mov edx,0x00AAAAAA
300
 int 0x40
301
 
302
 mov eax,4 ; Draw filenames
303
 mov ebx,134*65536+36
304
 mov edx,cmfile
305
 xor ecx,ecx
306
 mov esi,12
307
 cmp byte [editstate],1
308
 jnz no_active_1
309
 mov ecx,activecolor
310
 no_active_1:
311
 int 0x40
312
 xor ecx,ecx
313
 cmp byte [editstate],2
314
 jnz no_active_2
315
 mov ecx,activecolor
316
 no_active_2:
317
 add ebx,18
318
 add edx,12
319
 int 0x40
320
 
321
 mov eax,13             ; Clean info area
322
 mov ebx,14*65536+210
323
 mov ecx,107*65536+14
324
 mov edx,0x00AAAAAA
325
 int 0x40
326
 
327
 cmp byte [msgid],0     ; Draw info string
328
 jz notype
329
 mov ebx,16*65536+110
330
 xor ecx,ecx
331
 mov esi,16
332
 mov al, byte [msgid]
333
 dec al
334
 shl al,4
335
 xor ah,ah
336
 xor edx,edx
337
 mov dx,ax
338
 add edx,msgtable
339
 mov eax,4
340
 int 0x40
341
 notype:
342
 
343
 popa ; Restore registers
344
 
345
 ret
346
 
347
 ; interface data
348
 
349
 keylab db "    COMPRESS         DECOMPRESS"
350
 dellab db "   DELETE I/O       DELETE *.MHC"
351
 title  db "MHC 0.09"
352
 arclab db "COMPRESSED FILE:"
353
 unplab db "INPUT/OUTPUT FILE:"
354
 fin_text:
355
 
356
 cmfile db "FILENAME.MHC"
357
 iofile db "FILENAME.XYZ"
358
 
359
 editstate db 0
360
 editpos db 0
361
 msgid db 0
362
 
363
 msgtable:
364
 db "COMPRESSING...  "
365
 db "DECOMPRESSING..."
366
 db "I/O NOT FOUND!  "
367
 db "*.MHC NOT FOUND!"
368
 db "INVALID METHOD! "
369
 
370
; ======== compression/decompression engine ========
371
 
372
; Adresses declaration
373
 
374
 hashtable equ  MHC_END
375
 ifile     equ  hashtable+65536*4
376
 ofile     equ  ifile+1000000
377
 
378
 compress:   ; File compression
379
 
380
 call fill_filebufs
381
 
382
 mov eax,6
383
 mov ebx,iofile
384
 xor ecx,ecx
385
 mov edx,ecx
386
 not edx
387
 mov esi,ifile
388
 int 0x40
389
 
390
 cmp eax,0xFFFFFFFF
391
 jnz  compress_filefound              ; i/o file not found
392
 mov byte [msgid],3
393
 call draw_info
394
 ret
395
 
396
 compress_filefound:
397
 
398
 mov byte [msgid],1
399
 call draw_info
400
 
401
 jmp lzp_compress                    ; compress with order-2 LZP
402
 compress_dumpdata:
403
 
404
 push edx
405
 
406
 mov eax,32
407
 mov ebx,cmfile
408
 int 0x40
409
 
410
 mov eax,33
411
 pop edx
412
 mov ebx,cmfile
413
 mov ecx,ofile
414
 xor esi,esi
415
 int 0x40
416
 
417
 mov byte [msgid],0
418
 call draw_info
419
 
420
 ret
421
 
422
 
423
 decompress: ; File decompression
424
 
425
 call fill_filebufs
426
 
427
 mov  eax,6
428
 mov ebx,cmfile
429
 xor ecx,ecx
430
 mov edx,ecx
431
 not edx
432
 mov esi,ofile
433
 int 0x40
434
 
435
 cmp eax,0xFFFFFFFF
436
 jnz  decompress_filefound              ; *.mhc file not found
437
 mov byte [msgid],4
438
 call draw_info
439
 ret
440
 
441
 decompress_filefound:
442
 
443
 cmp byte [ofile],0                     ; Invalid method!
444
 jz  right_method
445
 mov byte [msgid],5
446
 call draw_info
447
 ret
448
 
449
 right_method:
450
 mov byte [msgid],2
451
 call draw_info
452
 
453
 jmp lzp_decompress
454
 decompress_dumpdata:
455
 
456
 push edx
457
 
458
 mov eax,32
459
 mov ebx,iofile
460
 int 0x40
461
 
462
 mov eax,33
463
 pop edx
464
 mov ebx,iofile
465
 mov ecx,ifile
466
 xor esi,esi
467
 int 0x40
468
 
469
 mov byte [msgid],0
470
 call draw_info
471
 
472
 ret
473
 
474
 fill_filebufs:             ; Fill filebufs with garbage to simplify matching
475
 pusha
476
 cld
477
 mov eax,0xF7D9A03F         ; <- "magic number" :) just garbage...
478
 mov ecx,2000000/4
479
 mov edi,ifile
480
 rep stosd
481
 popa
482
 ret
483
 
484
; ==== algorithms section ====
485
 
486
; Method 0: LZP compression algorithm
487
 
488
 lzp_compress:           ; EDX - how much bytes to dump
489
 
490
 cld                     ; clear direction flag
491
 
492
 mov esi,ifile           ; init pointers
493
 mov edi,ofile
494
 
495
 push eax                ; write header: ID0+4bfilesize => total 5 bytes
496
 xor eax,eax
497
 stosb
498
 pop eax
499
 stosd
500
 
501
 pusha                   ; fill hash table
502
 mov eax,ifile
503
 mov edi,hashtable
504
 mov ecx,65536
505
 rep stosd
506
 popa
507
 
508
 add eax,esi              ; calculate endpointer
509
 mov dword [endpointer],eax
510
 
511
 movsw                    ; copy three bytes
512
 movsb
513
 
514
 mov dword [controlp],edi
515
 inc edi
516
 
517
 mov byte [controld],0
518
 mov byte [controlb],0
519
 
520
 c_loop:
521
 cmp dword [endpointer],esi  ; check end of file
522
 ja  c_loop_ok
523
 jmp finish_c_loop
524
 c_loop_ok:
525
 
526
 call chash
527
 call compare
528
 jz   two_match_c
529
 
530
 lodsb
531
 mov byte [literal],al
532
 call chash
533
 call compare
534
 jz   lit_match_c
535
 
536
 mov  al,0
537
 call putbit
538
 mov  al,byte [literal]
539
 stosb
540
 movsb
541
 jmp  end_c_loop
542
 
543
 lit_match_c:
544
 mov al,1
545
 call putbit
546
 mov al,0
547
 call putbit
548
 mov al,byte [literal]
549
 stosb
550
 jmp encode_match
551
 
552
 two_match_c:
553
 mov al,1
554
 call putbit
555
 call putbit
556
 
557
 encode_match:
558
 call incpos
559
 call compare
560
 jz one_c
561
 mov al,0
562
 call putbit
563
 jmp end_c_loop
564
 one_c:
565
 
566
 call incpos
567
 mov  al,1
568
 call putbit
569
 
570
 call compare
571
 jnz ec1
572
 call incpos
573
 call compare
574
 jnz ec2
575
 call incpos
576
 call compare
577
 jnz ec3
578
 call incpos
579
 mov al,1
580
 call putbit
581
 call putbit
582
 call compare
583
 jnz ec4
584
 call incpos
585
 call compare
586
 jnz ec5
587
 call incpos
588
 call compare
589
 jnz ec6
590
 call incpos
591
 call compare
592
 jnz ec7
593
 call incpos
594
 call compare
595
 jnz ec8
596
 call incpos
597
 call compare
598
 jnz ec9
599
 call incpos
600
 call compare
601
 jnz ec10
602
 call incpos
603
 
604
 mov al,1
605
 call putbit
606
 call putbit
607
 call putbit
608
 xor  ecx,ecx
609
 
610
 match_loop_c:
611
 cmp  esi,dword [endpointer]
612
 jae   out_match_loop_c
613
 call compare
614
 jnz  out_match_loop_c
615
 inc  ecx
616
 call incpos
617
 jmp  match_loop_c
618
 out_match_loop_c:
619
 
620
 mov al,0xFF
621
 out_lg:
622
 cmp ecx,255
623
 jb  out_lg_out
624
 stosb
625
 sub ecx,255
626
 jmp out_lg
627
 out_lg_out:
628
 mov al,cl
629
 stosb
630
 jmp end_c_loop
631
 
632
 ec10:
633
 mov al,1
634
 call putbit
635
 call putbit
636
 mov al,0
637
 call putbit
638
 jmp end_c_loop
639
 
640
 ec9:
641
 mov al,1
642
 call putbit
643
 mov al,0
644
 call putbit
645
 mov al,1
646
 call putbit
647
 jmp end_c_loop
648
 
649
 ec8:
650
 mov al,1
651
 call putbit
652
 mov al,0
653
 call putbit
654
 call putbit
655
 jmp end_c_loop
656
 
657
 ec7:
658
 mov al,0
659
 call putbit
660
 mov al,1
661
 call putbit
662
 call putbit
663
 jmp end_c_loop
664
 
665
 ec6:
666
 mov al,0
667
 call putbit
668
 mov al,1
669
 call putbit
670
 mov al,0
671
 call putbit
672
 jmp end_c_loop
673
 
674
 ec5:
675
 mov al,0
676
 call putbit
677
 call putbit
678
 mov al,1
679
 call putbit
680
 jmp end_c_loop
681
 
682
 ec4:
683
 mov al,0
684
 call putbit
685
 call putbit
686
 call putbit
687
 jmp end_c_loop
688
 
689
 ec3:
690
 mov al,1
691
 call putbit
692
 mov al,0
693
 call putbit
694
 jmp end_c_loop
695
 
696
 ec2:
697
 mov al,0
698
 call putbit
699
 mov al,1
700
 call putbit
701
 jmp end_c_loop
702
 
703
 ec1:
704
 mov al,0
705
 call putbit
706
 call putbit
707
 
708
 end_c_loop:
709
 jmp c_loop
710
 
711
 finish_c_loop:
712
 
713
 mov eax,dword [controlp] ; store last tagbyte
714
 mov bl,byte [controld]
715
 mov [eax], byte bl
716
 
717
 sub edi,ofile ; calculate dump size
718
 mov edx,edi
719
 
720
 jmp compress_dumpdata
721
 
722
; LZP decompression algorithm
723
 
724
 lzp_decompress:                        ; EDX - how much bytes to dump
725
 
726
 cld
727
 
728
 mov edi,ifile
729
 mov esi,ofile+1
730
 
731
 pusha                   ; fill hash table
732
 mov eax,ifile
733
 mov edi,hashtable
734
 mov ecx,65536
735
 rep stosd
736
 popa
737
 
738
 lodsd
739
 
740
 mov ebx,edi
741
 add ebx,eax
742
 mov dword [endpointer],ebx
743
 
744
 movsw
745
 movsb
746
 
747
 lodsb
748
 mov byte [controld],al
749
 mov byte [controlb],0
750
 
751
 d_loop:
752
 cmp dword [endpointer],edi
753
 ja d_loop_ok
754
 jmp finish_d_loop
755
 d_loop_ok:
756
 
757
 call getbit
758
 cmp  al,0
759
 jnz  match_d
760
 call dhash
761
 movsb
762
 call dhash
763
 movsb
764
 jmp end_d_loop
765
 
766
 match_d:
767
 
768
 call getbit
769
 cmp  al,0
770
 jnz  no_literal_before_match
771
 call dhash
772
 movsb
773
 no_literal_before_match:
774
 
775
 call dhash
776
 mov ecx,1
777
 call copymatch
778
 
779
 call getbit
780
 cmp  al,0
781
 jz   end_d_loop
782
 mov  ecx,1
783
 call copymatch
784
 call getbit
785
 cmp  al,0
786
 jz   dc2
787
 mov  ecx,2
788
 call copymatch
789
 call getbit
790
 cmp  al,0
791
 jz   end_d_loop
792
 mov  ecx,1
793
 call copymatch
794
 call getbit
795
 cmp  al,0
796
 jz   dc4
797
 mov  ecx,4
798
 call copymatch
799
 call getbit
800
 cmp  al,0
801
 jz   dc5
802
 call getbit
803
 cmp  al,0
804
 jz   dc6
805
 mov  ecx,3
806
 call copymatch
807
 
808
 do:
809
 lodsb
810
 xor  ecx,ecx
811
 mov  cl,al
812
 call copymatch
813
 cmp  al,0xFF
814
 jnz  end_do
815
 jmp do
816
 end_do:
817
 jmp end_d_loop
818
 
819
 dc6:
820
 mov ecx,2
821
 call copymatch
822
 jmp  end_d_loop
823
 
824
 dc5:
825
 call getbit
826
 cmp  al,0
827
 jz   ndc5
828
 mov  ecx,1
829
 call copymatch
830
 ndc5:
831
 jmp  end_d_loop
832
 
833
 dc4:
834
 call getbit
835
 cmp  al,0
836
 jz   ndc4
837
 call getbit
838
 mov  ecx,3
839
 cmp  al,1
840
 jz   ndcc4
841
 dec  ecx
842
 ndcc4:
843
 call copymatch
844
 jmp  end_d_loop
845
 ndc4:
846
 call getbit
847
 cmp  al,0
848
 jz   ndccc4
849
 mov  ecx,1
850
 call copymatch
851
 ndccc4:
852
 jmp  end_d_loop
853
 
854
 dc2:
855
 call getbit
856
 cmp al,0
857
 jz  ndc2
858
 mov ecx,1
859
 call copymatch
860
 ndc2:
861
 
862
 end_d_loop:
863
 jmp d_loop
864
 finish_d_loop:
865
 
866
 mov edx, dword [ofile+1]
867
 
868
 jmp decompress_dumpdata
869
 
870
; LZP subroutines
871
 
872
 putbit:                  ; bit -> byte tag, AL holds bit for output
873
 pusha
874
 mov cl,byte [controlb]
875
 shl al,cl
876
 mov bl,byte [controld]
877
 or  bl,al
878
 mov byte [controld],bl
879
 inc cl
880
 cmp cl,8
881
 jnz just_increment
882
 mov byte [controlb],0
883
 mov byte [controld],0
884
 push edi
885
 mov  edi, dword [controlp]
886
 mov  al,bl
887
 stosb
888
 pop  edi
889
 mov dword [controlp],edi
890
 popa
891
 inc edi
892
 ret
893
 just_increment:
894
 mov byte [controlb],cl
895
 popa
896
 ret
897
 
898
 getbit:                       ; tag byte -> bit, AL holds input
899
 push ecx
900
 mov al,byte [controld]
901
 mov cl,byte [controlb]
902
 shr al,cl
903
 and al,1
904
 inc cl
905
 cmp cl,8
906
 jnz just_increment_d
907
 mov byte [controlb],0
908
 push eax
909
 lodsb
910
 mov byte [controld],al
911
 pop  eax
912
 pop  ecx
913
 ret
914
 just_increment_d:
915
 mov byte [controlb],cl
916
 pop ecx
917
 ret
918
 
919
 chash:                        ; calculate hash -> mp -> fill position
920
 pusha
921
 xor  eax,eax
922
 mov  al, byte [esi-1]
923
 mov  ah, byte [esi-2]
924
 shl  eax,2
925
 add  eax,hashtable
926
 mov  edx,dword [eax]
927
 mov  dword [mp],edx
928
 mov  dword [eax],esi
929
 popa
930
 ret
931
 
932
 dhash:                        ; calculate hash -> mp -> fill position
933
 pusha
934
 xor  eax,eax
935
 mov  al, byte [edi-1]
936
 mov  ah, byte [edi-2]
937
 shl  eax,2
938
 add  eax,hashtable
939
 mov  edx,dword [eax]
940
 mov  dword [mp],edx
941
 mov  dword [eax],edi
942
 popa
943
 ret
944
 
945
 copymatch:                    ; ECX bytes from [mp] to [rp]
946
 push esi
947
 mov  esi,dword [mp]
948
 rep  movsb
949
 mov  dword [mp],esi
950
 pop  esi
951
 ret
952
 
953
 compare:                      ; compare [mp] with [cpos]
954
 push edi
955
 push esi
956
 mov  edi,dword [mp]
957
 cmpsb
958
 pop  esi
959
 pop  edi
960
 ret
961
 
962
 incpos:
963
 inc  dword [mp]
964
 inc  esi
965
 ret
966
 
967
 
968
; LZP algorithm data
969
 
970
 endpointer     dd      0
971
 controlp       dd      0
972
 controlb       db      0
973
 controld       db      0
974
 mp  dd 0
975
 literal        db      0
976
 
977
MHC_END: ; the end... - Nikita Lesnikov (nlo_one)