-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathout.asm
3150 lines (2997 loc) · 59.4 KB
/
out.asm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
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
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
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
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
keep obj/out
mcopy out.mac
****************************************************************
*
* Ouput Module
*
* This module handles writing the output file and locating the
* proper load segment for code segments.
*
****************************************************************
copy directPage
****************************************************************
*
* OutCommon - global data for the segment module
*
****************************************************************
*
OutCommon data
;
; Constants
;
nameSize equ 10 size of a load segment name
dictGrowSize equ 4096 grow size for the dictionary buffer
dynGrowSize equ 1024 grow size for synamic segment buffer
;
; global variables
;
expressSegment ds 2 express segment number
keepRefnum ds 2 keep file reference number
lastLoadNumber ds 4 last load number allocated
loadList ds 4 head of load segment list
loadNamePtr ds 4 pointer to the name of the load segment
;
; Dynamic segment information
;
dynHandle ds 4 handle of the dynamic segment buffer
dynSize ds 2 bytes left in the buffer
dynBuffSize ds 4 total memory in the segment buffer
dynStart ds 4 ptr to the start of the buffer
dynSegment ds 2 dynamic segment number
;
; Current load segment information
;
loadNext ds 4 pointer to the next load segment
loadLast ds 4 pointer to the last load segment
loadPtr ds 4 pointer to the storage location for this record
loadNumber ds 2 number of this load segment
loadType ds 2 load segment type
loadORG ds 4 load segment origin
loadAlign ds 4 load segment aligment
loadBankSize ds 4 load segment bank size
loadName ds nameSize name of the load segment
loadSeg ds 4 handle of the segment buffer
loadSegStart ds 4 start of the segment buffer
loadPC ds 4 size of the load segment
loadOp ds 4 op disp for the segment buffer
loadOpSt ds 4 op at start of current lConst
loadDict ds 4 handle of the dictionary buffer
loadDictStart ds 4 start of the dictionary buffer
loadDictSize ds 2 bytes left in the dictionary buffer
loadDp ds 4 dp disp for the dictionary buffer
loadPass2 ds 2 are we ready for pass 2?
loadEnd anop end of the record
loadSize equ loadEnd-loadNext size of a load module record (even!)
end
****************************************************************
*
* AddEnd - add an end record to the dictionary
*
* Inputs:
* loadNext... - load segment record
*
****************************************************************
*
AddEnd private
using OutCommon
lda loadDictSize make sure there is room in the dictionary
bne lb1
jsr ExpandDictBuffer
lb1 short M save the end marker
lda #0
sta [dp]
long M
inc4 dp update dp
dec loadDictSize update loadDictSize
rts
end
****************************************************************
*
* AddSegment - add a segment to the expressload table
*
* Inputs:
* r8 - pointer to the segment to add
* r4,r8 - expressload list pointers
* expOffset - segment offset pointer
* expMap - segment map pointer
* expHeader - segment header map
* expressSegment - express segment number
*
****************************************************************
*
AddSegment private
using OutCommon
jsr MoveSegment move the segment ot the new list
sub4 expHeader,expOffset,r12 set the segment offset
lda r12
sta [expOffset]
ldy #6 zero the reserved words
lda #0
lb1 sta [expOffset],Y
dey
dey
bne lb1
add4 expOffset,#8 update the offset pointer
ldy #loadNumber-loadNext get the old segment number
lda [r4],Y
dec A set it's mapped segment
asl A
tay
lda expressSegment
sta [expMap],Y
ldy #loadNumber-loadNext set the new segment number
sta [r4],Y
inc expressSegment update segment number
add4 fMark,#69+5 allow for the segment header & lconst
move4 fMark,mark1 set the lconst mark
ldy #loadPC-loadNext find the segment size
lda [r4],Y
sta len1
iny
iny
lda [r4],Y
sta len1+2
add4 fMark,len1 allow for the segment body
move4 fMark,mark2 set the reloc mark
ldy #loadDp-loadNext find the reloc size
lda [r4],Y
sta len2
iny
iny
lda [r4],Y
sta len2+2
ora len2 if len2 = 0 then
bne lb1a
stz mark2 mark2 = 0
stz mark2+2
lb1a add4 fMark,len2 allow for the dictionary
inc4 fMark allow for the end mark
ldy #loadBankSize-loadNext set the bank size
lda [r4],Y
sta bankSize
iny
iny
lda [r4],Y
sta bankSize+2
ldy #loadType-loadNext set the segment type
lda [r4],Y
sta kind
ldy #loadOrg-loadNext set the origin
lda [r4],Y
sta org
iny
iny
lda [r4],Y
sta org+2
ldy #loadAlign-loadNext set the alignment factor
lda [r4],Y
sta align
iny
iny
lda [r4],Y
sta align+2
ldy #loadNumber-loadNext set the segment number
lda [r4],Y
sta segNum
ldx #nameSize-2 set the segment name
ldy #loadName-loadNext+nameSize-2
lb2 lda [r4],Y
sta name,X
dey
dey
dex
dex
bpl lb2
ldy #segEnd-mark1-1 move the header to the express segment
short M
lb3 lda mark1,Y
sta [expHeader],Y
dey
bpl lb3
long M
add4 expHeader,#69 update the segment header pointer
rts
mark1 ds 4 lConst file mark
len1 ds 4 lConst length
mark2 ds 4 reloc file mark
len2 ds 4 reloc length
dc i1'0' undefined
dc i1'0' label length
dc i1'4' number length
dc i1'2' version
bankSize ds 4 bank size
kind ds 2 segment type
dc i'0' undefined
org ds 4 origin
align ds 4 alignment
dc i1'0' numsex
dc i1'0' undefined
segNum ds 2 segment number
dc i4'0' segment entry
dc i'lname-len1' disp to name
dc i'segend-mark1' disp to body
lname dc 10c' ' load name
dc i1'10' segment name length
name ds 10 segment name
segend anop
end
****************************************************************
*
* CheckHeader - check the header parameters
*
* Inputs:
* segOrg - origin for this segment
* segAlign - alignment for this segment
* segType - type for this segment
* segBanksize - banksize for this segment
* loadType - load segment type
* loadORG - load segment origin
* loadAlign - load segment aligment
* loadBankSize - load segment bank size
*
* Outputs:
* loadType - load segment type
* loadORG - load segment origin
* loadAlign - load segment aligment
* loadBankSize - load segment bank size
*
****************************************************************
*
CheckHeader private
using OutCommon
using Common
;
; Set the load segment type
;
lda loadPC if at the start of the segment then
ora loadPC+2
bne st1
lda segType use segType
and #$FEFF
sta loadType
bra st4 else
st1 lda segType or in the or flags
and #$1D00
ora loadType
sta loadType
lda segType mask out missing and flags
and #$E200
ora #$1DFF
and loadType
sta loadType
lda loadType get the type without flags
and #$007F
sta r0
lda segType
and #$007F
cmp r0 if they do not match then
beq st4
cmp #1 if seg is data then
bne st2
lda r0 if not load in [code,init,dp] then
beq st4
cmp #$10
beq st4
cmp #$12
beq st4
err15 ph4 #0 flag segment conflict
ph2 #15
jsr Error
bra st4
st2 cmp #0 else if seg in [code,init,dp] then
beq st3
cmp #$10
beq st3
cmp #$12
bne err15
st3 lda r0 if load = data then
cmp #1
bne err15
lda loadType use seg type
and #$FF00
sta loadType
lda segType
and #$007F
ora loadType
sta loadType
! else flag the error
st4 anop endif
lda bankOrg if bankOrg then
beq st5
lda loadType bank org the program
ora #$0100
sta loadType
st5 anop endif
;
; Set the load segment origin (pass 1)
;
lda pass branch if pass 2
cmp #2
beq or0
lda segOrg skip if org is 0
ora segOrg+2
jeq or4
lda loadPC if at the start of the segment then
ora loadPC+2
ora loadOrg
ora loadOrg+2
bne po1
move4 segOrg,loadOrg loadOrg = segOrg
bra po3 else
po1 sub4 segOrg,loadOrg,r0 update the pc
lda r2
bmi po3
cmpl r0,pc
blt po3
move4 r0,pc
po3 anop endif
bra or4
;
; Set the load segment origin (pass 2)
;
or0 lda segOrg skip if org is 0
ora segOrg+2
beq or4
lda loadPC if at the start of the segment then
ora loadPC+2
ora loadOrg
ora loadOrg+2
bne or1
move4 segOrg,loadOrg loadOrg = segOrg
bra or3 else
or1 sub4 segOrg,loadOrg,r0 update the pc
sub4 r0,pc
lda r2
bpl or2 if disp is negative then
ph4 #0 Error(NULL,3)
ph2 #3
jsr Error
bra or3 else
or2 lda r0 define DS bytes to fill space
ora r2
beq or3
jsr DefineDS
or3 anop endif
jsr CheckAlignOrg check for conflicts between align,org
or4 anop
;
; Set the load segment alignment (pass 1)
;
lda pass branch if pass 2
cmp #2
beq sa0
lda segAlign skip if alignment is 0
ora segAlign+2
jeq sa4
lda loadPC if at the start of the segment then
ora loadPC+2
ora loadAlign
ora loadAlign+2
bne la1
move4 segAlign,loadAlign loadAlign = segAlign
bra la3 else
la1 cmpl loadAlign,segAlign if loadAlign < segAlign then
bge la2
move4 segAlign,loadAlign loadAlign = segAlign
la2 move4 segAlign,r0 PrepareAlign(segAlign)
jsr PrepareAlign
la3 anop endif
bra sa4
;
; Set the load segment alignment (pass 2)
;
sa0 lda segAlign skip if alignment is 0
ora segAlign+2
beq sa4
ph4 segAlign make sure the align is a power of 2
jsr CheckAlign
lda loadPC if at the start of the segment then
ora loadPC+2
ora loadAlign
ora loadAlign+2
bne sa1
move4 segAlign,loadAlign loadAlign = segAlign
bra sa3 else
sa1 cmpl loadAlign,segAlign if loadAlign < segAlign then
bge sa2
move4 segAlign,loadAlign loadAlign = segAlign
sa2 move4 segAlign,r0 DefineAlign(segAlign)
jsr DefineAlign
sa3 anop endif
jsr CheckAlignOrg check for conflicts between align,org
sa4 anop
;
; Set the load segment bank size
;
lda pass branch if pass 2
cmp #2
beq rt1
lda loadBankSize if loadBanksize = 0
ora loadBanksize+2
beq bs1
cmpl segBanksize,loadBanksize or ((segBanksize < loadBanksize)
bge bs2 and (segBanksize <> 0)) then
lda segBanksize
ora segBanksize+2
beq bs2
bs1 move4 segBankSize,loadBankSize loadBankSize = segBankSize
bs2 anop
rt1 rts
;
; CheckAlignOrg - make sure the align and org do not conflict
;
CheckAlignOrg anop
lda loadAlign if loadAlign <> 0 then
ora loadAlign+2
beq ca2
sub4 loadAlign,#1,r0 if loadOrg & (loadAlign-1) then
lda r0
and loadOrg
bne ca1
lda r2
and loadOrg+2
beq ca2
ca1 ph4 #0 Error(NULL,21)
ph2 #21
jsr Error
ca2 rts
end
****************************************************************
*
* CompactCInterseg - compact a cInterseg record
*
* Inputs:
* r0 - ptr to the cInterseg record
* r4 - ptr to the end of the dictionary
* dp - ptr to the next free byte in the dictionary
*
****************************************************************
*
CompactCInterseg private
using Common
using OutCommon
;
; See if the record can be compacted
;
lda [r0] length must be 2 or 3
xba
and #$00FF
cmp #2
beq ck1
cmp #3
jne nc1
ck1 sta length
cmp #3 if length = 3 then
bne ck2
ldy #2 shift count must be 0
lda [r0],Y
and #$00FF
jne nc1
stz shift
lda #2 set the record type
sta recordType
ldy #5 set the segment number
lda [r0],Y
and #$00FF
sta segment
bra ck3 else {if length = 2 then}
ck2 ldy #5 segment number must be <= 12
lda [r0],Y
and #$00FF
sta segment
cmp #13
jge nc1
ldx express if express then
beq ck2a
cmp #12 don't use 12, either
jeq nc1
ck2a clc set the record type for shift 0
lda segment
adc #13
sta recordType
ldy #2 shift must be 0 or -16
lda [r0],Y
and #$00FF
sta shift
beq ck3
cmp #$00F0
jne nc1
add2 recordType,#12 set the record type for shift -16
ck3 anop
;
; Create a Super record
;
lda #13 create the record header
cmp loadDictSize make sure there is room in the
blt sp1 dictionary
jsr ExpandDictBuffer
sp1 add4 dp,#1,recordLengthPtr save a pointer to the length field
sub4 recordLengthPtr,loadDictStart
short M set the op code
lda #$F7
sta [dp]
ldy #5 set the super record type
lda recordType
sta [dp],Y
long M
add4 dp,#6 skip the super record header
sub2 loadDictSize,#6
ldy #4 set the segment offset page
lda [r0],Y
and #$00FF
sta page
beq pg3 if page <> 0 then
sta r12 while (r12 := page) > $7F do
pg1 lda r12
cmp #$80
blt pg2
short M write a skip page for $7F pages
lda #$FF
sta [dp]
long M
inc4 dp
dec loadDictSize
sub2 r12,#$7F r12 -= $7F
bra pg1 endwhile
pg2 lda r12 if r12 <> 0 then
beq pg3
short M write a skip page for r12 pages
ora #$80
sta [dp]
long M
inc4 dp
dec loadDictSize
pg3 anop
move4 dp,r12 initialize the page counter
short M
lda #$FF
sta [r12]
long M
inc4 dp skip the page counter
dec loadDictSize
move4 r0,r8 for each dictionary record do
sp2 cmpl r8,r4
jeq sp14
lda [r8] if it is a Reloc then
and #$00FF
cmp #$E2
bne sp3
add4 r8,#11 skip the record
bra sp2 loop
sp3 cmp #$75 if it is a skipped cReloc or
beq sp4 cReloc then
cmp #$F5
bne sp5
sp4 add4 r8,#7 skip the record
bra sp2 loop
sp5 cmp #$76 if it is a skipped cInterseg then
bne sp6
add4 r8,#8 skip the record
bra sp2 loop
sp6 cmp #$E3 if it is an Interseg then
bne sp7
add4 r8,#15 skip the record
bra sp2 loop
sp7 ldy #2 if the cInterseg is a different type
short M then
lda [r8],Y
cmp shift
bne sp7a
dey
lda [r8],Y
cmp length
bne sp7a
cmp #3
beq sp8
ldy #5
lda [r8],Y
cmp segment
beq sp8
sp7a long M skip the record
add4 r8,#8
brl sp2 loop
sp8 long M make sure there is room in the
lda #5 dictionary
cmp loadDictSize
blt sp9
sub4 r12,loadDictStart
jsr ExpandDictBuffer
add4 r12,loadDictStart
sp9 short M if r8^.page <> page then
sec
ldy #4
lda [r8],Y
sbc page
beq sp13
dec A if r8^.page - page > 1 then
beq sp12
sp10 cmp #$80 record a page skip
blt sp11
tax
lda #$FF
sta [dp]
long M
inc4 dp
dec loadDictSize
short M
txa
sec
sbc #$7F
bra sp10
sp11 cmp #0
beq sp12
ora #$80
sta [dp]
long M
inc4 dp
dec loadDictSize
short M
sp12 ldy #4 record the new page
lda [r8],Y
sta page
lda #$FF set up a record count
sta [dp]
long M
move4 dp,r12
inc4 dp
dec loadDictSize
short M
sp13 lda [r12] increment the record count
inc A
sta [r12]
ldy #3 set the offset
lda [r8],Y
sta [dp]
long M
inc4 dp
dec loadDictSize
short M mark the record
lda [r8]
and #$7F
sta [r8]
long M
add4 r8,#8 skip the record
brl sp2 loop
sp14 anop set the super record length
add4 recordLengthPtr,loadDictStart,r12
sub4 dp,r12,recordLengthPtr
sub4 recordLengthPtr,#4
ldy #2
lda recordLengthPtr
sta [r12]
lda recordLengthPtr+2
sta [r12],Y
rts
;
; Cannot compact - put the unchanged record in the dictionary
;
nc1 lda #8 make sure there is room in the
cmp loadDictSize dictionary
blt nc2
jsr ExpandDictBuffer
nc2 ldy #6 move the record
nc3 lda [r0],Y
sta [dp],Y
dey
dey
bpl nc3
add4 dp,#8 skip the record
sub2 loadDictSize,#8
add4 r0,#8
rts
;
; Local data
;
recordLengthPtr ds 4 pointer to the super record length field
page ds 2 current cReloc page number
length ds 2 length of the cReloc fields
shift ds 2 shift count
segment ds 2 segment number
recordType ds 2 type of the Super record
end
****************************************************************
*
* CompactCReloc - compact a cReloc record
*
* Inputs:
* r0 - ptr to the cReloc record
* r4 - ptr to the end of the dictionary
* dp - ptr to the next free byte in the dictionary
*
****************************************************************
*
CompactCReloc private
using OutCommon
;
; See if the record can be compacted
;
lda [r0] length must be 2 or 3
xba
and #$00FF
cmp #2
beq ck1
cmp #3
jne nc1
ck1 sta length
ldy #2 shift count must be 0
lda [r0],Y
and #$00FF
jne nc1
;
; Create a Super record
;
lda #13 create the record header
cmp loadDictSize make sure there is room in the
blt sp1 dictionary
jsr ExpandDictBuffer
sp1 add4 dp,#1,recordLengthPtr save a pointer to the length field
sub4 recordLengthPtr,loadDictStart
short M set the op code
lda #$F7
sta [dp]
ldy #5 set the super record type
lda length
and #$01
sta [dp],Y
long M
add4 dp,#6 skip the super record header
sub2 loadDictSize,#6
ldy #4 set the segment offset page
lda [r0],Y
and #$00FF
sta page
beq pg3 if page <> 0 then
sta r12 while (r12 := page) > $7F do
pg1 lda r12
cmp #$80
blt pg2
short M write a skip page for $7F pages
lda #$FF
sta [dp]
long M
inc4 dp
dec loadDictSize
sub2 r12,#$7F r12 -= $7F
bra pg1 endwhile
pg2 lda r12 if r12 <> 0 then
beq pg3
short M write a skip page for r12 pages
ora #$80
sta [dp]
long M
inc4 dp
dec loadDictSize
pg3 anop
move4 dp,r12 initialize the page counter
short M
lda #$FF
sta [r12]
long M
inc4 dp skip the page counter
dec loadDictSize
move4 r0,r8 for each dictionary record do
sp2 cmpl r8,r4
jeq sp14
lda [r8] if it is a Reloc then
and #$00FF
cmp #$E2
bne sp3
add4 r8,#11 skip the record
bra sp2 loop
sp3 cmp #$75 if it is a skipped cReloc then
bne sp4
add4 r8,#7 skip the record
bra sp2 loop
sp4 cmp #$F6 if it is a cInterseg or skipped
beq sp5 cInterseg then
cmp #$76
bne sp6
sp5 add4 r8,#8 skip the record
bra sp2 loop
sp6 cmp #$E3 if it is an Interseg then
bne sp7
add4 r8,#15 skip the record
bra sp2 loop
sp7 ldy #1 if the cReloc is a different type then
lda [r8],Y
cmp length (checks length and shift=0)
beq sp8
add4 r8,#7 skip the record
bra sp2 loop
sp8 lda #5 make sure there is room in the
cmp loadDictSize dictionary
blt sp9
sub4 r12,loadDictStart
jsr ExpandDictBuffer
add4 r12,loadDictStart
sp9 short M if r8^.page <> page then
sec
ldy #4
lda [r8],Y
sbc page
beq sp13
dec A if r8^.page - page > 1 then
beq sp12
sp10 cmp #$80 record a page skip
blt sp11
tax
lda #$FF
sta [dp]
long M
inc4 dp
dec loadDictSize
short M
txa
sec
sbc #$7F
bra sp10
sp11 cmp #0
beq sp12
ora #$80
sta [dp]
long M
inc4 dp
dec loadDictSize
short M
sp12 ldy #4 record the new page
lda [r8],Y
sta page
lda #$FF set up a record count
sta [dp]
long M
move4 dp,r12
inc4 dp
dec loadDictSize
short M
sp13 lda [r12] increment the record count
inc A
sta [r12]
ldy #3 set the offset
lda [r8],Y
sta [dp]
long M
inc4 dp
dec loadDictSize
short M mark the record
lda [r8]
and #$7F
sta [r8]
long M
add4 r8,#7 skip the record
brl sp2 loop
sp14 anop set the super record length
add4 recordLengthPtr,loadDictStart,r12
sub4 dp,r12,recordLengthPtr
sub4 recordLengthPtr,#4
ldy #2
lda recordLengthPtr
sta [r12]
lda recordLengthPtr+2
sta [r12],Y
rts
;
; Cannot compact - put the unchanged record in the dictionary
;
nc1 lda #8 make sure there is room in the
cmp loadDictSize dictionary
blt nc2
jsr ExpandDictBuffer
nc2 ldy #6 move the record
nc3 lda [r0],Y
sta [dp],Y
dey
dey
bpl nc3
add4 dp,#7 skip the record
sub2 loadDictSize,#7
add4 r0,#7
rts
;
; Local data
;
recordLengthPtr ds 4 pointer to the super record length field
page ds 2 current cReloc page number
length ds 2 length of the cReloc fields
end
****************************************************************
*
* CompactSegment - compact a single segment
*
* Inputs:
* LoadNext... - segment record
*
****************************************************************
*
CompactSegment private
using OutCommon
using Common
lda loadDict if there is no dictionary then
ora loadDict+2
bne lb1
rts return
lb1 move4 loadDict,dictHandle save the dictionary handle
move4 loadDictStart,r0 get a pointer to the dictionary
move4 dp,r4 get a pointer to the dictionary end
stz loadDictStart zero the current load dictionary
stz loadDictStart+2
stz loadDict
stz loadDict+2
stz loadDp
stz loadDp+2
stz dp
stz dp+2
stz loadDictSize
stz loadDictSize+2
lb2 cmpl r0,r4 for each dictionary entry do
jeq lb12
lda [r0] if r0^ = cReloc then
and #$00FF
cmp #$00F5
bne lb3
jsr CompactCReloc compact the record
bra lb2 loop
lb3 cmp #$75 if r0^ = skipped cReloc then
bne lb4
add4 r0,#7 skip the record
bra lb2 loop
lb4 cmp #$E2 if r0^ = Reloc then
bne lb7
lda #12 make sure there is room in the
cmp loadDictSize dictionary
blt lb5
jsr ExpandDictBuffer
lb5 ldy #10 move the record
lb6 lda [r0],Y
sta [dp],Y
dey
dey
bpl lb6
add4 dp,#11 skip the record
sub2 loadDictSize,#11
add4 r0,#11
bra lb2 loop
lb7 cmp #$F6 if r0^ = cInterseg then
bne lb8
jsr CompactCInterseg compact the record
bra lb2 loop
lb8 cmp #$76 if r0^ = skipped cInterseg then
bne lb9
add4 r0,#8 skip the record
brl lb2 loop
! (condition must be true) if r0^ = Interseg then
lb9 lda #16 make sure there is room in the
cmp loadDictSize dictionary
blt lb10
jsr ExpandDictBuffer
lb10 ldy #14 move the record
lb11 lda [r0],Y
sta [dp],Y