Subversion Repositories NedoOS

Rev

Details | Last modification | View Log

Rev Author Line No. Line
130 lvd 1
#include <stdio.h>
2
 
3
#include "mhmt-types.h"
4
#include "mhmt-globals.h"
5
#include "mhmt-emit.h"
6
#include "mhmt-lz.h"
7
#include "mhmt-optimal.h"
8
 
9
 
10
 
11
// actually generate output file from optimal chain - MegaLZ version
12
ULONG emit_megalz(struct optchain * optch, ULONG actual_len)
13
{
14
        ULONG position;
15
        LONG length;
16
        LONG disp;
17
 
18
        LONG max_disp; // maximum encountered displacement
19
 
20
 
21
        ULONG varbits,varlen;
22
 
23
        ULONG success = 1;
24
 
25
        max_disp = 0;
26
 
27
 
28
        // some checks
29
        if( !optch )
30
        {
31
                printf("mhmt-emit.c:emit_megalz() - NULL passed!\n");
32
                return 0;
33
        }
34
 
35
        // initialize
36
        success = success && emit_file(NULL, EMIT_FILE_INIT);
37
 
38
        success = success && emit_byte(0, EMIT_BYTE_INIT);
39
 
40
        success = success && emit_bits(0, EMIT_BITS_INIT);
41
 
42
 
43
        // copy first byte as-is
44
        success = success && emit_file( wrk.indata, 1);
45
 
46
        // go emitting codes
47
        position = 1;
48
 
49
        while( (position<actual_len) && success )
50
        {
51
                length = optch[position].code.length;
52
                disp   = optch[position].code.disp;
53
 
54
                if( length==0 )
55
                {
56
                        printf("mhmt-emit.c:emit_megalz() - encountered stop-code in optimal chain before emitting all data!\n");
57
                        return 0;
58
                }
59
                else if( length==1 ) // either copy-byte or len=1 code
60
                {
61
                        if( disp==0 ) // copy-byte (%1<byte>)
62
                        {
63
                                success = success && emit_bits( 0x80000000, 1 );
64
                                success = success && emit_byte( wrk.indata[position], EMIT_BYTE_ADD );
65
                        }
66
                        else if( (-8)<=disp && disp<=(-1) ) // len=1, disp=-1..-8 (%000abc)
67
                        {
68
                                success = success && emit_bits( 0x00000000,   3 );
69
                                success = success && emit_bits( disp<<(32-3), 3 );
70
 
71
                                if( max_disp > disp ) max_disp = disp;
72
                        }
73
                        else
74
                                goto INVALID_CODE_MEGALZ;
75
                }
76
                else if( length==2 )
77
                {
78
                        if( (-256)<=disp && disp<=(-1) ) // %001<byte>
79
                        {
80
                                success = success && emit_bits( 0x20000000, 3 );
81
                                success = success && emit_byte( (UBYTE)(0x00FF & disp), EMIT_BYTE_ADD );
82
 
83
                                if( max_disp > disp ) max_disp = disp;
84
                        }
85
                        else
86
                                goto INVALID_CODE_MEGALZ;
87
                }
88
                else if( 3<=length && length<=255 )
89
                {
90
                        // length coding
91
                        if( length==3 ) // %010
92
                        {
93
                                success = success && emit_bits( 0x40000000, 3 );
94
                        }
95
                        else // length==4..255, %011
96
                        {
97
                                success = success && emit_bits( 0x60000000, 3 );
98
 
99
                                // calculate size of variable bits
100
                                varlen = 0;
101
                                varbits = (length-2)>>1;
102
                                while( varbits )
103
                                {
104
                                        varbits >>= 1;
105
                                        varlen++;
106
                                }
107
 
108
                                varbits = length-2-(1<<varlen); // prepare length coding
109
 
110
                                success = success && emit_bits(       1<<(32-varlen), varlen );
111
                                success = success && emit_bits( varbits<<(32-varlen), varlen );
112
                        }
113
 
114
                        // displacement coding
115
                        if( (-256)<=disp && disp<=(-1) )
116
                        {
117
                                success = success && emit_bits( 0, 1 );
118
                                success = success && emit_byte( (UBYTE)(0x00ff & disp), EMIT_BYTE_ADD );
119
 
120
                                if( max_disp > disp ) max_disp = disp;
121
                        }
122
                        else if( (-4352)<=disp && disp<(-256) )
123
                        {
124
                                success = success && emit_bits( 0x80000000, 1 );
125
 
126
                                success = success && emit_bits( (0x0F00&(disp+0x0100))<<20, 4 );
127
 
128
                                success = success && emit_byte( (UBYTE)(0x00FF & disp), EMIT_BYTE_ADD );
129
 
130
                                if( max_disp > disp ) max_disp = disp;
131
                        }
132
                        else
133
                                goto INVALID_CODE_MEGALZ;
134
                }
135
                else
136
                {
137
INVALID_CODE_MEGALZ:
138
                        printf("mhmt-emit.c:emit_megalz() - invalid code: length=%d, displacement=%d\n",length,disp);
139
                        return 0;
140
                }
141
 
142
                position += length;
143
        }
144
 
145
        // stop-code
146
        success = success && emit_bits( 0x60100000, 12 );
147
        success = success && emit_bits( 0, EMIT_BITS_FINISH ); // this also flushes emit_byte()
148
 
149
        success = success && emit_file( NULL, EMIT_FILE_FINISH );
150
 
151
        if( success )
152
                printf("Maximum displacement actually used is %d.\n",-max_disp);
153
 
154
        return success;
155
}
156
 
157
 
158
 
159
 
160
 
161
 
162
 
163
 
164
 
165
 
166
 
167
 
168
 
169
 
170
 
171
 
172
// actually generate output file from optimal chain - hrum version
173
ULONG emit_hrum(struct optchain * optch, ULONG actual_len)
174
{
175
        ULONG position;
176
        LONG length;
177
        LONG disp;
178
 
179
        LONG max_disp; // maximum encountered displacement
180
 
181
 
182
        ULONG varbits,varlen;
183
 
184
        ULONG success = 1;
185
 
186
        max_disp = 0;
187
 
188
 
189
        // some checks
190
        if( !optch )
191
        {
192
                printf("mhmt-emit.c:emit_hrum() - NULL passed!\n");
193
                return 0;
194
        }
195
 
196
        // initialize
197
        success = success && emit_file(NULL, EMIT_FILE_INIT);
198
 
199
        success = success && emit_byte(0, EMIT_BYTE_INIT);
200
 
201
        success = success && emit_bits(0, EMIT_BITS_INIT);
202
 
203
 
204
        // manage zx header info
205
        if( wrk.zxheader )
206
        {
207
        success = success && emit_file( &wrk.indata[wrk.inlen-5], 5);
208
                success = success && emit_file( (UBYTE*)"\020\020", 2); // 0x10, 0x10
209
        }
210
 
211
        // schedule first byte to be placed just after first bitstream word
212
        success = success && emit_byte( wrk.indata[0], EMIT_BYTE_ADD);
213
 
214
        // go emitting codes
215
        position = 1;
216
 
217
        while( (position<actual_len) && success )
218
        {
219
                length = optch[position].code.length;
220
                disp   = optch[position].code.disp;
221
 
222
                if( length==0 )
223
                {
224
                        printf("mhmt-emit.c:emit_hrum() - encountered stop-code in optimal chain before emitting all data!\n");
225
                        return 0;
226
                }
227
                else if( length==1 ) // either copy-byte or len=1 code
228
                {
229
                        if( disp==0 ) // copy-byte (%1<byte>)
230
                        {
231
                                success = success && emit_bits( 0x80000000, 1 );
232
                                success = success && emit_byte( wrk.indata[position], EMIT_BYTE_ADD );
233
                        }
234
                        else if( (-8)<=disp && disp<=(-1) ) // len=1, disp=-1..-8 (%000abc)
235
                        {
236
                                success = success && emit_bits( 0x00000000,   3 );
237
                                success = success && emit_bits( disp<<(32-3), 3 );
238
 
239
                                if( max_disp > disp ) max_disp = disp;
240
                        }
241
                        else
242
                                goto INVALID_CODE_HRUM;
243
                }
244
                else if( length==2 )
245
                {
246
                        if( (-256)<=disp && disp<=(-1) ) // %001<byte>
247
                        {
248
                                success = success && emit_bits( 0x20000000, 3 );
249
                                success = success && emit_byte( (UBYTE)(0x00FF & disp), EMIT_BYTE_ADD );
250
 
251
                                if( max_disp > disp ) max_disp = disp;
252
                        }
253
                        else
254
                                goto INVALID_CODE_HRUM;
255
                }
256
                else if( 3<=length && length<=255 )
257
                {
258
                        // length coding
259
                        if( length==3 )
260
                        {
261
                                success = success && emit_bits( 0x40000000, 3 );
262
                        }
263
                        else if( length<=15 )
264
                        {
265
                                varlen=2;
266
 
267
                                varbits = (length % 3)<<30; // low 2 bits (except for length==15)
268
                                if( length==15 ) varbits = 0xC0000000;
269
 
270
                                if( length>=6 ) { varbits = 0xC0000000 | (varbits>>2); varlen += 2; }
271
                                if( length>=9 ) { varbits = 0xC0000000 | (varbits>>2); varlen += 2; }
272
                                if( length>=12) { varbits = 0xC0000000 | (varbits>>2); varlen += 2; }
273
 
274
                                success = success && emit_bits( 0x60000000, 3 );
275
                                success = success && emit_bits( varbits, varlen );
276
                        }
277
                        else // 15<length<=255: %01100<len>
278
                        {
279
                                success = success && emit_bits( 0x60000000, 5 );
280
                                success = success && emit_byte( (UBYTE)(length&0x00FF), EMIT_BYTE_ADD );
281
                        }
282
 
283
                        // displacement coding
284
                        if( (-256)<=disp && disp<=(-1) ) // %0<disp>
285
                        {
286
                                success = success && emit_bits( 0x00000000, 1 );
287
                                success = success && emit_byte( (UBYTE)(0x00FF & disp), EMIT_BYTE_ADD );
288
 
289
                                if( max_disp > disp ) max_disp = disp;
290
                        }
291
                        else if( (-4096)<=disp && disp<(-256) ) //%1abcd<disp>
292
                        {
293
                                success = success && emit_bits( 0x80000000, 1 );
294
                                success = success && emit_bits( (0x0F00&disp)<<20, 4 );
295
                                success = success && emit_byte( (UBYTE)(0x00FF & disp), EMIT_BYTE_ADD );
296
 
297
                                if( max_disp > disp ) max_disp = disp;
298
                        }
299
                        else
300
                                goto INVALID_CODE_HRUM;
301
                }
302
                else
303
                {
304
INVALID_CODE_HRUM:
305
                        printf("mhmt-emit.c:emit_hrum() - invalid code: length=%d, displacement=%d\n",length,disp);
306
                        return 0;
307
                }
308
 
309
                position += length;
310
        }
311
 
312
        // stop-code: %01100<0>
313
        success = success && emit_bits( 0x60000000, 5 );
314
        success = success && emit_byte( 0x00, EMIT_BYTE_ADD );
315
 
316
        success = success && emit_bits( 0, EMIT_BITS_FINISH ); // this also flushes emit_byte()
317
        success = success && emit_file( NULL, EMIT_FILE_FINISH );
318
 
319
        if( success )
320
                printf("Maximum displacement actually used is %d.\n",-max_disp);
321
 
322
        return success;
323
}
324
 
325
 
326
 
327
 
328
 
329
 
330
 
331
 
332
 
333
 
334
 
335
 
336
 
337
 
338
 
339
 
340
ULONG emit_hrust(struct optchain * optch, ULONG actual_len)
341
{
342
        ULONG position;
343
        LONG length;
344
        LONG disp;
345
 
346
        LONG max_disp; // maximum encountered displacement
347
 
348
        ULONG varbits,varlen;
349
        ULONG success = 1;
350
 
351
        UBYTE wrlen[2];
352
 
353
        ULONG expbitlen = 2; // expandable match: bitlength of displacement
354
 
355
        ULONG flen;
356
 
357
 
358
        max_disp = 0;
359
 
360
 
361
        // some checks
362
        if( !optch )
363
        {
364
                printf("mhmt-emit.c:emit_hrust() - NULL passed!\n");
365
                return 0;
366
        }
367
 
368
        // initialize
369
        success = success && emit_file(NULL, EMIT_FILE_INIT);
370
 
371
        success = success && emit_byte(0, EMIT_BYTE_INIT);
372
 
373
        success = success && emit_bits(0, EMIT_BITS_INIT);
374
 
375
 
376
        // manage zx header info
377
        if( wrk.zxheader )
378
        {
379
                success = success && emit_file( (UBYTE*)"HR", 2);
380
 
381
                wrlen[0] = wrk.inlen&0x00FF;
382
                wrlen[1] = (wrk.inlen>>8)&0x00FF;
383
                success = success && emit_file( wrlen, 2); // unpacked length mod 65536
384
 
385
                success = success && emit_file( wrlen, 2); // packed length - !to be filled later!
386
 
387
        success = success && emit_file( &wrk.indata[wrk.inlen-6], 6); // last bytes
388
        }
389
 
390
        // schedule first byte to be placed just after first bitstream word
391
        success = success && emit_byte( wrk.indata[0], EMIT_BYTE_ADD);
392
 
393
        // go emitting codes
394
        position = 1;
395
 
396
        while( (position<actual_len) && success )
397
        {
398
                #ifdef DBG
399
                        printf("%04x:",position);
400
                #endif
401
 
402
                length = optch[position].code.length;
403
                disp   = optch[position].code.disp;
404
 
405
                if( length==0 )
406
                {
407
                        printf("mhmt-emit.c:emit_hrust() - encountered stop-code in optimal chain before emitting all data!\n");
408
                        return 0;
409
                }
410
                else if( disp==0 ) // copy-bytes
411
                {
412
                        if( length==1 ) // 1 byte: %1<byte>
413
                        {
414
                                success = success && emit_bits( 0x80000000, 1 );
415
                                success = success && emit_byte( wrk.indata[position], EMIT_BYTE_ADD );
416
                        }
417
                        else if( (12<=length) && (length<=42) && ( !(length&1) ) ) // %0110001abcd<byte,byte,...>
418
                        {
419
                                varbits = (length-12)<<27;
420
                                success = success && emit_bits( 0x62000000, 7 );
421
 
422
                                success = success && emit_bits( varbits, 4 );
423
 
424
                                varlen = 0;
425
                                while( success && (varlen<(ULONG)length) )
426
                                {
427
                                        success = success && emit_byte( wrk.indata[position+varlen], EMIT_BYTE_ADD );
428
                                        varlen++;
429
                                }
430
                        }
431
                        else
432
                                goto INVALID_CODE_HRUST;
433
                }
434
                else if( length==(-3) ) // insertion code
435
                {
436
                        if( (-16)<=disp && disp<=(-1) ) // %011001abcd<byte>
437
                        {
438
                                success = success && emit_bits( 0x64000000, 6 );
439
                                success = success && emit_bits( disp<<(32-4), 4 );
440
                        }
441
                        else if( (-79)<=disp && disp<(-16) )
442
                        {
443
                                if( disp&1 ) // ffb1..ffef: %01001<byte><byte>
444
                                {
445
                                        success = success && emit_bits( 0x48000000, 5 );
446
 
447
                                        varbits = disp&0x00FF;
448
                                        varbits += 15;
449
                                        varbits ^= 3;
450
                                        varbits = ( (varbits>>1)&0x007F ) | ( (varbits<<7)&0x0080 );
451
 
452
                                        success = success && emit_byte( (UBYTE)(varbits&0x00FF), EMIT_BYTE_ADD );
453
                                }
454
                                else // ffb2..ffee: %00110<byte><byte>
455
                                {
456
                                        success = success && emit_bits( 0x30000000, 5 );
457
 
458
                                        varbits = disp&0x00FF;
459
                                        varbits += 15;
460
                                        varbits ^= 2;
461
                                        varbits = ( (varbits>>1)&0x007F ) | ( (varbits<<7)&0x0080 );
462
 
463
                                        success = success && emit_byte( (UBYTE)(varbits&0x00FF), EMIT_BYTE_ADD );
464
                                }
465
                        }
466
                        else
467
                                goto INVALID_CODE_HRUST;
468
 
469
                        success = success && emit_byte( wrk.indata[position+1], EMIT_BYTE_ADD );
470
                }
471
                else if( length==1 ) // %000abc
472
                {
473
                        if( (-8)<=disp && disp<=(-1) )
474
                        {
475
                                success = success && emit_bits( 0x00000000, 3 );
476
                                success = success && emit_bits( disp<<(32-3), 3 );
477
                        }
478
                        else
479
                                goto INVALID_CODE_HRUST;
480
                }
481
                else if( length==2 )
482
                {
483
                        if( (-32)<=disp && disp<=(-1) ) // %00111abcde
484
                        {
485
                                success = success && emit_bits( 0x38000000, 5 );
486
                                success = success && emit_bits( disp<<(32-5), 5 );
487
                        }
488
                        else if( (-256)<=disp && disp<(-32) ) // %00110<byte>
489
                        {
490
                                success = success && emit_bits( 0x30000000, 5 );
491
                                success = success && emit_byte( (UBYTE)(0x00FF & disp), EMIT_BYTE_ADD );
492
                        }
493
                        else if( (-512)<=disp && disp<(-256) ) // %00101<byte>
494
                        {
495
                                success = success && emit_bits( 0x28000000, 5 );
496
                                success = success && emit_byte( (UBYTE)(0x00FF & disp), EMIT_BYTE_ADD );
497
                        }
498
                        else if( (-768)<=disp && disp<(-512) ) // %00100<byte>
499
                        {
500
                                success = success && emit_bits( 0x20000000, 5 );
501
                                success = success && emit_byte( (UBYTE)(0x00FF & disp), EMIT_BYTE_ADD );
502
                        }
503
                        else
504
                                goto INVALID_CODE_HRUST;
505
                }
506
                else if (3<=length && length<=3839 && (-65536)<=disp && disp<=(-1) )
507
                {
508
                        // first see if we need emitting expansion codes
509
 
510
                                //  -513.. -1024  (FDFF..FC00) - 2 bits
511
                                //  -1025..-2048  (FBFF..F800) - 3
512
                                //  -2049..-4096  (F7FF..F000) - 4
513
                                //  -4097..-8192  (EFFF..E000) - 5
514
                                //  -8193..-16384 (DFFF..C000) - 6
515
                                // -16385..-32768 (BFFF..8000) - 7
516
                                // -32769..-65536 (7FFF..0000) - 8
517
                        if( disp<(-512) )
518
                        {
519
                                varbits = 1024;
520
                                varlen  = 2;
521
                                while( (ULONG)(-disp) > varbits )
522
                                {
523
                                        varbits <<= 1;
524
                                        varlen++;
525
                                }
526
 
527
                                // emit expansion codes, if necessary: %00110<FE>
528
                                while( varlen>expbitlen )
529
                                {
530
                                        success = success && emit_bits( 0x30000000, 5 );
531
                                        success = success && emit_byte( 0x00FE, EMIT_BYTE_ADD );
532
                                        #ifdef DBG
533
                                                printf("expansion\n");
534
                                        #endif
535
 
536
                                        expbitlen++;
537
                                }
538
                        }
539
 
540
 
541
 
542
 
543
 
544
                        // emit length
545
 
546
                        if( length<=15 ) // 3..15
547
                        {
548
                                success = success && emit_bits( 0, 1 );
549
 
550
                                if( length==3 )
551
                                {
552
                                        success = success && emit_bits( 0x80000000, 2 ); // %010
553
                                }
554
                                else
555
                                {
556
                                        varlen  = length/3;
557
                                        varbits = length%3;
558
 
559
                                        success = success && emit_bits( 0xFFFFFFFF, varlen<<1 );
560
 
561
                                        if( length!=15 )
562
                                                success = success && emit_bits( varbits<<(32-2), 2 );
563
                                }
564
                        }
565
                        else if( length<=127 ) // 16..127: %0110000abcdefg
566
                        {
567
                                success = success && emit_bits( 0x60000000, 7 );
568
                                success = success && emit_bits( length<<(32-7), 7 );
569
                        }
570
                        else // 128..3839
571
                        {
572
                                success = success && emit_bits( 0x60000000, 7 );
573
                                success = success && emit_bits( length<<(32-15), 7 );
574
                                success = success && emit_byte( (UBYTE)(length&0x00FF), EMIT_BYTE_ADD );
575
                        }
576
 
577
 
578
                        // emit displacement
579
                        if( (-32)<=disp ) // ffe0..ffff: %10abcde
580
                        {
581
                                success = success && emit_bits( 0x80000000, 2 );
582
                                success = success && emit_bits( disp<<(32-5), 5 );
583
                        }
584
                        else if( (-256)<=disp ) // ff00..ffdf: %01<byte>
585
                        {
586
                                success = success && emit_bits( 0x40000000, 2 );
587
                                success = success && emit_byte( (UBYTE)(disp&0x00FF), EMIT_BYTE_ADD );
588
                        }
589
                        else if( (-512)<=disp ) // fe00..feff: %00<byte>
590
                        {
591
                                success = success && emit_bits( 0x00000000, 2 );
592
                                success = success && emit_byte( (UBYTE)(disp&0x00FF), EMIT_BYTE_ADD );
593
                        }
594
                        else // variable code length: [-65536..-512)
595
                        {
596
 
597
                                // displacement itself: %11ab[cdefgh]<byte>
598
                                success = success && emit_bits( 0xC0000000, 2 );
599
                                success = success && emit_bits( disp<<(24-expbitlen), expbitlen );
600
                                success = success && emit_byte( (UBYTE)(disp&0x00FF), EMIT_BYTE_ADD );
601
                        }
602
                }
603
                else
604
                {
605
INVALID_CODE_HRUST:
606
                        printf("mhmt-emit.c:emit_hrust() - invalid code: length=%d, displacement=%d\n",length,disp);
607
                        return 0;
608
                }
609
 
610
                #ifdef DBG
611
                        if( length==(-3) )
612
                        {
613
                                printf("insert-match.len=%d,disp=%d\n",(-length),disp);
614
                        }
615
                        else if( disp==0 )
616
                        {
617
                                printf("copy.len=%d\n",length);
618
                        }
619
                        else
620
                        {
621
                                printf("match.len=%d,disp=%d\n",length,disp);
622
                        }
623
                #endif
624
 
625
 
626
                if( max_disp > disp ) max_disp = disp;
627
 
628
                if( length>0 ) // account for negative length
629
                        position += length;
630
                else
631
                        position -= length;
632
        }
633
 
634
        // stop-code: %0110_0000_0011_11
635
        success = success && emit_bits( 0x603C0000, 14 );
636
 
637
        success = success && emit_bits( 0, EMIT_BITS_FINISH ); // this also flushes emit_byte()
638
        success = success && emit_file( NULL, EMIT_FILE_FINISH );
639
 
640
        // complete the header
641
        if( success && wrk.zxheader )
642
        {
643
                success = success && ( (0xFFFFFFFF) != (flen = ftell(wrk.file_out)) ); //filesize
644
 
645
                success = success && !fseek(wrk.file_out, 4, SEEK_SET); // pos to 4th byte
646
 
647
                wrlen[0] = flen&255;
648
                wrlen[1] = (flen>>8)&255;
649
                // write len
650
                success = success && ( 2==fwrite(wrlen, 1, 2, wrk.file_out) );
651
 
652
                if( !success )
653
                {
654
                        printf("emit_hrust(): failed to write packed length to header!\n");
655
                        return 0;
656
                }
657
        }
658
 
659
 
660
        if( success )
661
        {
662
                printf("Maximum displacement actually used is %d.\n",-max_disp);
663
 
664
                // TODO: patch packed length in file, if zx header
665
        }
666
 
667
 
668
        return success;
669
}
670
 
671
 
672
 
673
 
674
 
675
 
676
 
677
 
678
 
679
 
680
 
681
 
682
 
683
 
684
 
685
 
686
 
687
 
688
 
689
 
690
 
691
 
692
 
693
// actually generate output file from optimal chain - zx7 version
694
ULONG emit_zx7(struct optchain * optch, ULONG actual_len)
695
{
696
        ULONG position;
697
        LONG length;
698
        LONG disp;
699
 
700
        LONG max_disp; // maximum encountered displacement
701
 
702
 
703
        ULONG varbits,varlen;
704
 
705
        ULONG success = 1;
706
 
707
        max_disp = 0;
708
 
709
 
710
        // some checks
711
        if( !optch )
712
        {
713
                printf("mhmt-emit.c:emit_zx7() - NULL passed!\n");
714
                return 0;
715
        }
716
 
717
        // initialize
718
        success = success && emit_file(NULL, EMIT_FILE_INIT);
719
 
720
        success = success && emit_byte(0, EMIT_BYTE_INIT);
721
 
722
        success = success && emit_bits(0, EMIT_BITS_INIT);
723
 
724
 
725
        // copy first byte as-is
726
        success = success && emit_file( wrk.indata, 1);
727
//printf("FIRST: #%02x\n\n",*wrk.indata);
728
 
729
        // go emitting codes
730
        position = 1;
731
 
732
        while( (position<actual_len) && success )
733
        {
734
                length = optch[position].code.length;
735
                disp   = optch[position].code.disp;
736
 
737
                if( length==0 )
738
                {
739
                        printf("mhmt-emit.c:emit_zx7() - encountered stop-code in optimal chain before emitting all data!\n");
740
                        return 0;
741
                }
742
                else if( length==1 ) // copy-byte
743
                {
744
                        if( disp==0 ) // copy-byte (%0<byte>)
745
                        {
746
//printf("BITS: %%");
747
                                success = success && emit_bits( 0x00000000, 1 );
748
                                success = success && emit_byte( wrk.indata[position], EMIT_BYTE_ADD );
749
//printf("\nBYTE: #%02x\n\n",wrk.indata[position]);
750
                        }
751
                        else
752
                                goto INVALID_CODE_ZX7;
753
                }
754
                else if( 2<=length && length<=65536 )
755
                {
756
                        // length coding
757
                        varbits = length-1;
758
                        varlen=0;
759
                        while( varbits )
760
                        {
761
                                varbits>>=1;
762
                                varlen+=1;
763
                        }
764
                        // varlen=1 for len=2,
765
                        //       =2 for len=3,4
766
                        //       =3         5,6,7,8
767
 
768
//printf("BITS: %%");
769
                        success = success && emit_bits( 0x80000000, varlen );
770
                        success = success && emit_bits( (length-1)<<(32-varlen), varlen );
771
 
772
                        // displacement coding
773
                        if( (-128)<=disp && disp<=(-1) )
774
                        {
775
                                success = success && emit_byte( ((UBYTE)(-disp-1))&127, EMIT_BYTE_ADD );
776
//printf("\nBYTE: #%02x\n\n",((UBYTE)(-disp-1))&127);
777
                                if( max_disp > disp ) max_disp = disp;
778
                        }
779
                        else if( (-2176)<=disp && disp<(-128) )
780
                        {
781
                                success = success && emit_byte( (((UBYTE)(-disp-129))&127)|128, EMIT_BYTE_ADD );
782
//printf("\nBYTE: #%02x\n",(((UBYTE)(-disp-129))&127)|128);
783
//printf("BITS: %%");
784
                                success = success && emit_bits( ((-disp-129)&0x780)<<21, 4 );
785
//printf("\n\n");
786
                                if( max_disp > disp ) max_disp = disp;
787
                        }
788
                        else
789
                                goto INVALID_CODE_ZX7;
790
                }
791
                else
792
                {
793
INVALID_CODE_ZX7:
794
                        printf("mhmt-emit.c:emit_zx7() - invalid code: length=%d, displacement=%d\n",length,disp);
795
                        return 0;
796
                }
797
 
798
                position += length;
799
        }
800
 
801
        // stop-code
802
//printf("BITS: %%");
803
        success = success && emit_bits( 0x80004000, 18 );
804
        success = success && emit_bits( 0, EMIT_BITS_FINISH ); // this also flushes emit_byte()
805
//printf("\n");
806
        success = success && emit_file( NULL, EMIT_FILE_FINISH );
807
 
808
        if( success )
809
                printf("Maximum displacement actually used is %d.\n",-max_disp);
810
 
811
        return success;
812
}
813
 
814
 
815
 
816
 
817
 
818
 
819
 
820
 
821
 
822
 
823
 
824
 
825
 
826
 
827
 
828
 
829
 
830
 
831
 
832
 
833
 
834
 
835
 
836
 
837
 
838
 
839
 
840
 
841
 
842
 
843
 
844
 
845
 
846
 
847
 
848
 
849
 
850
 
851
 
852
 
853
 
854
 
855
// emit bytes to the output buffer and flush to file when needed
856
// 'operation' defines what to do as described in *.h
857
// 'byte' is emitted only when length >=1,
858
// When length=EMIT_FILE_FINISH (0), flushes tail to file
859
// When length=EMIT_FILE_INIT (-1), initializes.
860
//
861
// returns zero in case of any problems (fails to write buffer to file), otherwise non-zero
862
ULONG emit_file(UBYTE * bytes, LONG length)
863
{
864
        static UBYTE buffer[EMIT_FILEBUF_SIZE];
865
 
866
        static ULONG position;
867
 
868
 
869
        if( length==EMIT_FILE_INIT )
870
        {
871
                position = 0;
872
 
873
                return 1;
874
        }
875
        else if( length>0 )
876
        {
877
                while( (position+length) >= EMIT_FILEBUF_SIZE ) // if we have to flush buffer
878
                {
879
                        length -= (EMIT_FILEBUF_SIZE-position);
880
 
881
                        while( position < EMIT_FILEBUF_SIZE ) // fill buffer to the end, if possible
882
                        {
883
                                buffer[position++] = *(bytes++);
884
                        }
885
 
886
                        if( EMIT_FILEBUF_SIZE!=fwrite(buffer, 1, EMIT_FILEBUF_SIZE, wrk.file_out) )
887
                        {
888
                                printf("mhmt-emit.c:emit_file() can't write to file!\n");
889
                                return 0;
890
                        }
891
 
892
                        position=0;
893
                }
894
 
895
                while( length-- ) // if something left that does not need flushing
896
                {
897
                        buffer[position++] = *(bytes++);
898
                }
899
 
900
                return 1;
901
        }
902
        else if( length==EMIT_FILE_FINISH )
903
        {
904
                if( position>0 ) // do we have anything to flush?
905
                {
906
                        if( position!=fwrite(buffer, 1, position, wrk.file_out) )
907
                        {
908
                                printf("mhmt-emit.c:emit_file() can't write to file!\n");
909
                                return 0;
910
                        }
911
                }
912
 
913
                return 1;
914
        }
915
        else
916
        {
917
                printf("mhmt-emit.c:emit_file() encountered invalid arguments!\n");
918
                return 0;
919
        }
920
}
921
 
922
 
923
 
924
// store emitted bytes in special buffer, because emitted bits go earlier than corresponding bytes.
925
// then, when bits are flushed to the file, bytes are flushed just after.
926
// returns zero if any problems. "operation" dictates what to do (see *.h)
927
ULONG emit_byte(UBYTE byte, ULONG operation)
928
{
929
        static UBYTE buffer[EMIT_BYTEBUF_SIZE];
930
 
931
        static ULONG in_pos, out_pos;
932
 
933
        ULONG success;
934
 
935
 
936
        switch( operation )
937
        {
938
        case EMIT_BYTE_INIT:
939
 
940
                in_pos  = 0;
941
                out_pos = 0;
942
 
943
                return 1;
944
 
945
 
946
        case EMIT_BYTE_ADD:
947
 
948
                #ifdef DBG
949
                        printf("<%02x>",byte&0x00FF);
950
                #endif
951
 
952
                buffer[in_pos] = byte;
953
 
954
                in_pos = (in_pos+1) & (EMIT_BYTEBUF_SIZE-1);
955
 
956
 
957
                if( in_pos==out_pos ) // overflow!
958
                {
959
                        printf("mhmt-emit.c:emit_byte() buffer overflow!\n");
960
                        return 0;
961
                }
962
 
963
                return 1;
964
 
965
 
966
        case EMIT_BYTE_FLUSH:
967
 
968
                if( in_pos==out_pos ) // nothing to do?
969
                        return 1;
970
                else if( in_pos>out_pos ) // no index wraparound
971
                {
972
                        success = emit_file( &buffer[out_pos], in_pos-out_pos );
973
                }
974
                else // in_pos<out_pos - wraparound
975
                {
976
                        success = emit_file( &buffer[out_pos], EMIT_BYTEBUF_SIZE-out_pos );
977
 
978
                        if( in_pos )
979
                                success = success && emit_file( &buffer[0], in_pos );
980
                }
981
 
982
                out_pos=in_pos;
983
                return success;
984
 
985
        default:
986
                printf("mhmt-emit.c:emit_byte() encountered invalid arguments!\n");
987
                return 0;
988
        }
989
}
990
 
991
 
992
// collects bits, emit to output stream when needed. accounts for word or byte mode, little-big endian, empty or full bits
993
// length is either positive number of bits or one of two special cases (see *.h)
994
//
995
ULONG emit_bits(ULONG msb_aligned_bits, LONG length)
996
{
997
        static ULONG bit_store;
998
        static ULONG bit_count;
999
 
1000
        ULONG max_bits;
1001
 
1002
        ULONG success = 1;
1003
 
1004
 
1005
        max_bits = wrk.wordbit ? 16 : 8;
1006
 
1007
        if( length==EMIT_BITS_INIT )
1008
        {
1009
                bit_store = 0;
1010
                bit_count = 0;
1011
                return 1;
1012
        }
1013
        else if( length==EMIT_BITS_FINISH )
1014
        {
1015
                if( bit_count ) // some bits to flush
1016
                {
1017
                        while( (bit_count++)<max_bits )
1018
                                bit_store <<= 1;
1019
 
1020
                        success = success && emit_bits_flush(bit_store);
1021
                }
1022
 
1023
                success = success && emit_byte(0, EMIT_BYTE_FLUSH);
1024
 
1025
                return success;
1026
        }
1027
        else if( length>0 ) // add bits
1028
        {
1029
                do
1030
                {
1031
                        if( !wrk.fullbits ) // empty bits - check for flushing before shiftin
1032
                        {
1033
                                if( bit_count==max_bits )
1034
                                {
1035
                                        success = success && emit_bits_flush(bit_store);
1036
                                        success = success && emit_byte(0, EMIT_BYTE_FLUSH);
1037
 
1038
                                        bit_count = 0;
1039
                                }
1040
                        }
1041
 
1042
 
1043
//printf("%d",1&(msb_aligned_bits>>31));
1044
 
1045
                        bit_store = (bit_store<<1) | ( 1 & (msb_aligned_bits>>31) );
1046
                        msb_aligned_bits <<= 1;
1047
                        bit_count++;
1048
 
1049
                        if( wrk.fullbits ) // full bits - check for flushing after bit shiftin
1050
                        {
1051
                                if( bit_count==max_bits )
1052
                                {
1053
                                        success = success && emit_bits_flush(bit_store);
1054
                                        success = success && emit_byte(0, EMIT_BYTE_FLUSH);
1055
 
1056
                                        bit_count = 0;
1057
                                }
1058
                        }
1059
 
1060
                } while( --length );
1061
 
1062
                return success;
1063
        }
1064
        else
1065
        {
1066
                printf("mhmt-emit.c:emit_bits() encountered invalid arguments!\n");
1067
                return 0;
1068
        }
1069
}
1070
 
1071
// flushes either word or byte from given bits
1072
//
1073
ULONG emit_bits_flush(ULONG bits)
1074
{
1075
        UBYTE store_byte;
1076
 
1077
        ULONG success = 1;
1078
 
1079
        if( wrk.wordbit ) // 16bits
1080
        {
1081
                if( wrk.bigend ) // big endian
1082
                {
1083
                        store_byte = 0x00FF & (bits >> 8);
1084
                        success = success && emit_file( &store_byte, 1);
1085
 
1086
                        store_byte = 0x00FF & bits;
1087
                        success = success && emit_file( &store_byte, 1);
1088
                }
1089
                else // little endian
1090
                {
1091
                        store_byte = 0x00FF & bits;
1092
                        success = success && emit_file( &store_byte, 1);
1093
 
1094
                        store_byte = 0x00FF & (bits >> 8);
1095
                        success = success && emit_file( &store_byte, 1);
1096
                }
1097
        }
1098
        else // 8bits
1099
        {
1100
                store_byte = 0x00FF & bits;
1101
                success = success && emit_file( &store_byte, 1);
1102
        }
1103
 
1104
        return success;
1105
}
1106