4 * Copyright (C) 1989-2017 Alan R. Baldwin
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 * With enhancements by
34 * The module lkout.c contains the dispatch
35 * function to create the relocated object
36 * code output in the required format.
38 * lkout.c contains the following functions:
48 * lkout.c contains no local variables.
53 * int i 1 - process data
56 * The function lkout() dispatches to the
57 * required output format routine.
63 * int oflag output type flag
64 * int obj_flag Output enabled flag
65 * a_uint pc Current relocation address
66 * int pcb Current pc bytes per address
74 * The REL data is output in the required format.
83 if (i
&& obj_flag
) { return; }
84 if (ofp
== NULL
) { return; }
87 * Create the Byte Output Address
89 for (j
=1; j
<pcb
; j
++) {
120 /*)Function lkflush()
122 * The function lkflush() dispatches
123 * to the required data flushing routine.
129 * int oflag output type flag
130 * FILE * ofp output file handle
133 * VOID iflush() lkout.c
134 * VOID sflush() lkout.c
135 * VOID dflush() lkout.c
138 * Any remaining REL data is flushed
139 * to the output file.
145 if (ofp
== NULL
) { return; }
169 * Record Mark Field - This field signifies the start of a
170 * record, and consists of an ascii colon
173 * Record Length Field - This field consists of two ascii
174 * characters which indicate the number of
175 * data bytes in this record. The
176 * characters are the result of converting
177 * the number of bytes in binary to two
178 * ascii characters, high digit first. An
179 * End of File record contains two ascii
180 * zeros in this field.
182 * Load Address Field - This field consists of the four ascii
183 * characters which result from converting
184 * the the binary value of the address in
185 * which to begin loading this record. The
186 * order is as follows:
188 * High digit of high byte of address.
189 * Low digit of high byte of address.
190 * High digit of low byte of address.
191 * Low digit of low byte of address.
193 * In an End of File record this field con-
194 * sists of four ascii zeros, in a start
195 * address record this is the program entry
196 * address (low), or in a segment record
197 * this is the high order address.
199 * Record Type Field - This field identifies the record type,
200 * which is either 0 for data records, 1
201 * for an End of File record, 3 for a
202 * start address, or 4 for a
203 * segment record. It consists
204 * of two ascii characters, with the high
205 * digit of the record type first, followed
206 * by the low digit of the record type.
208 * Data Field - This field consists of the actual data,
209 * converted to two ascii characters, high
210 * digit first. There are no data bytes in
211 * the End of File record.
213 * Checksum Field - The checksum field is the 8 bit binary
214 * sum of the record length field, the load
215 * address field, the record type field,
216 * and the data field. This sum is then
217 * negated (2's complement) and converted
218 * to two ascii characters, high digit
224 * int i 1 - process data
227 * The function ixx() loads the output buffer with
228 * the relocated data.
231 * a_uint chksum byte checksum
232 * a_uint lo_addr address within segment
233 * a_uint hi_addr segment number
237 * struct sym *sp symbol pointer
238 * a_uint symadr symbol address
241 * int a_bytes T Line Address Bytes
242 * int hilo byte order
243 * FILE * ofp output file handle
244 * int rtaflg first output flag
245 * int rtcnt count of data words
246 * int rtflg[] output the data flag
247 * a_uint rtval[] relocated data
248 * char rtbuf[] output buffer
249 * a_uint rtadr0 address temporary
250 * a_uint rtadr1 address temporary
251 * a_uint rtadr2 address temporary
254 * int fprintf() c_library
255 * VOID iflush() lkout.c
258 * The data is placed into the output buffer.
262 * The number of Data Field bytes is:
264 * 1 Record Mark Field
265 * 2 Record Length Field
266 * 4 Load Address Field
267 * 2 Record Type Field
270 * Plus 32 data bytes (64 characters)
278 a_uint j
, symadr
, chksum
;
281 if (TARGET_IS_6808
&& ap
->a_flag
& A_NOLOAD
)
307 for (i
=0,rtadr2
=0; i
<a_bytes
; i
++) {
308 rtadr2
= (rtadr2
<< 8) | rtval
[i
];
310 if ((rtadr2
!= rtadr1
) || rtaflg
) {
312 * data bytes not contiguous between records
315 rtadr0
= rtadr1
= rtadr2
;
318 for (k
=a_bytes
; k
<rtcnt
; k
++) {
320 rtbuf
[(int) (rtadr1
++ - rtadr0
)] = rtval
[k
];
321 if ((rtadr1
& 0xffff) == 0) {
324 if (rtadr1
- rtadr0
== IXXMAXBYTES
) {
330 sp
= lkpsym(".__.END.", 0);
331 if (sp
&& (sp
->s_axp
->a_bap
->a_ofp
== ofp
)) {
336 chksum
+= symadr
>> 8;
337 chksum
+= symadr
>> 16;
338 chksum
+= symadr
>> 24;
340 fprintf(ofp
, ":04000005%08lX%02lX\n", symadr
, (~chksum
+ 1) & 0x00ff);
342 fprintf(ofp
, ":04000005%08X%02X\n", symadr
, (~chksum
+ 1) & 0x00ff);
346 fprintf(ofp
, ":00000001FF\n");
353 * The function iflush() outputs the relocated data
354 * in the standard Intel format.
357 * a_uint chksum byte checksum
358 * a_uint lo_addr address within segment
359 * a_uint hi_addr segment number
361 * int max number of data bytes
362 * int reclen record length
365 * int a_bytes T Line Address Bytes
366 * FILE * ofp output file handle
367 * int rtaflg first output flag
368 * char rtbuf[] output buffer
369 * a_uint rtadr0 address temporary
370 * a_uint rtadr1 address temporary
373 * int fprintf() c_library
376 * The data is output to the file defined by ofp.
380 * This function derived from the work
381 * of G. Osborn, gary@s-4.com.
382 * The new version concatenates the assembler
383 * output records when they represent contiguous
384 * memory segments to produce IXXMAXBYTES data byte
385 * Intel Hex output lines whenever possible, resulting
386 * in a substantial reduction in file size.
387 * More importantly, the download time
388 * to the target system is much improved.
395 a_uint chksum
, lo_addr
, hi_addr
;
396 // rom addresses, calculated based on the virtual ones
397 a_uint rrtadr0
= rtadr0
;
398 // translate virtual addresses for gameboy
400 if(rrtadr0
> 0x10000)
401 rrtadr0
= (rrtadr0
>>16) * 0x4000 + (rrtadr0
&0xffff) - 0x4000;
404 max
= (int) (rtadr1
- rtadr0
);
407 static a_uint prev_hi_addr
= 0;
409 hi_addr
= (rrtadr0
>> 16) & 0xffff;
410 if ((hi_addr
!= prev_hi_addr
) || rtaflg
) {
414 chksum
+= hi_addr
>> 8;
416 fprintf(ofp
, ":02000004%04lX%02lX\n", hi_addr
, (~chksum
+ 1) & 0x00ff);
418 fprintf(ofp
, ":02000004%04X%02X\n", hi_addr
, (~chksum
+ 1) & 0x00ff);
420 prev_hi_addr
= hi_addr
;
425 * Only the ":" and the checksum itself are excluded
426 * from the checksum. The record length includes
427 * only the data bytes.
429 lo_addr
= rrtadr0
& 0xffff;
433 chksum
+= lo_addr
>> 8;
435 fprintf(ofp
, ":%02X%04lX00", reclen
, lo_addr
);
437 fprintf(ofp
, ":%02X%04X00", reclen
, lo_addr
);
439 for (i
=0; i
<max
; i
++) {
441 fprintf(ofp
, "%02X", rtbuf
[i
] & 0x00ff);
447 fprintf(ofp
, "%02lX\n", (~chksum
+ 1) & 0x00ff);
449 fprintf(ofp
, "%02X\n", (~chksum
+ 1) & 0x00ff);
457 /*)S19/S28/S37 Formats
458 * Record Type Field - This field signifies the start of a
459 * record and identifies the the record
462 * 2-Byte Address: Ascii S1 - Data Record
463 * Ascii S9 - End of File Record
464 * 3-Byte Address: Ascii S2 - Data Record
465 * Ascii S8 - End of File Record
466 * 4-Byte Address: Ascii S3 - Data Record
467 * Ascii S7 - End of File Record
469 * Record Length Field - This field specifies the record length
470 * which includes the address, data, and
471 * checksum fields. The 8 bit record
472 * length value is converted to two ascii
473 * characters, high digit first.
475 * Load Address Field - This field consists of the 4/6/8 ascii
476 * characters which result from converting
477 * the the binary value of the address in
478 * which to begin loading this record. The
479 * order is as follows:
481 * S37: High digit of fourth byte of address.
482 * Low digit of fourth byte of address.
483 * S28/S37: High digit of third byte of address.
484 * Low digit of third byte of address.
485 * S19/S28/S37: High digit of high byte of address.
486 * Low digit of high byte of address.
487 * High digit of low byte of address.
488 * Low digit of low byte of address.
490 * In an End of File record this field con-
491 * sists of either 4/6/8 ascii zeros or the
492 * program entry address.
494 * Data Field - This field consists of the actual data,
495 * converted to two ascii characters, high
496 * digit first. There are no data bytes in
497 * the End of File record.
499 * Checksum Field - The checksum field is the 8 bit binary
500 * sum of the record length field, the load
501 * address field, and the data field. This
502 * sum is then complemented (1's comple-
503 * ment) and converted to two ascii
504 * characters, high digit first.
509 * int i 1 - process data
512 * The function s19() loads the output buffer with
513 * the relocated data.
516 * a_uint addr address temporary
517 * a_uint chksum byte checksum
518 * char * frmt format string pointer
522 * int max number of data bytes
523 * int reclen record length
524 * struct sym *sp symbol pointer
525 * a_uint symadr symbol address
528 * int a_bytes T Line Address Bytes
529 * int hilo byte order
530 * FILE * ofp output file handle
531 * int rtcnt count of data words
532 * int rtflg[] output the data flag
533 * a_uint rtval[] relocated data
534 * char rtbuf[] output buffer
535 * a_uint rtadr0 address temporary
536 * a_uint rtadr1 address temporary
537 * a_uint rtadr2 address temporary
540 * int fprintf() c_library
541 * VOID sflush() lkout.c
544 * The data is placed into the output buffer.
548 * Number of Data Field bytes is:
550 * 2 Record Type Field
551 * 2 Record Length Field
552 * 4/6/8 Load Address Field
555 * Plus 32 data bytes (64 characters)
565 a_uint j
, addr
, symadr
, chksum
;
591 for (i
=0,rtadr2
=0; i
<a_bytes
; i
++) {
592 rtadr2
= (rtadr2
<< 8) | rtval
[i
];
595 if (rtadr2
!= rtadr1
) {
597 * data bytes not contiguous between records
600 rtadr0
= rtadr1
= rtadr2
;
602 for (k
=a_bytes
; k
<rtcnt
; k
++) {
604 rtbuf
[(int) (rtadr1
++ - rtadr0
)] = rtval
[k
];
605 if (rtadr1
- rtadr0
== SXXMAXBYTES
) {
612 * Only the "S_" and the checksum itself are excluded
613 * from the checksum. The record length does not
614 * include "S_" and the pair count. It does
615 * include the address bytes, the data bytes,
618 reclen
= 1 + a_bytes
;
620 sp
= lkpsym(".__.END.", 0);
621 if (sp
&& (sp
->s_axp
->a_bap
->a_ofp
== ofp
)) {
623 for (i
=0,addr
=symadr
; i
<a_bytes
; i
++,addr
>>=8) {
632 case 2: frmt
= "S9%02X%04lX"; addr
= symadr
& 0x0000ffffl
; break;
633 case 3: frmt
= "S8%02X%06lX"; addr
= symadr
& 0x00ffffffl
; break;
634 case 4: frmt
= "S7%02X%08lX"; addr
= symadr
& 0xffffffffl
; break;
639 case 2: frmt
= "S9%02X%04X"; addr
= symadr
& 0x0000ffff; break;
640 case 3: frmt
= "S8%02X%06X"; addr
= symadr
& 0x00ffffff; break;
641 case 4: frmt
= "S7%02X%08X"; addr
= symadr
& 0xffffffff; break;
644 fprintf(ofp
, frmt
, reclen
, addr
);
649 fprintf(ofp
, "%02lX\n", (~chksum
) & 0x00ff);
651 fprintf(ofp
, "%02X\n", (~chksum
) & 0x00ff);
659 * The function sflush() outputs the relocated data
660 * in the standard Motorola format.
663 * a_uint addr address temporary
664 * a_uint chksum byte checksum
665 * char * frmt format string pointer
667 * int max number of data bytes
668 * int reclen record length
671 * int a_bytes T Line Address Bytes
672 * FILE * ofp output file handle
673 * char rtbuf[] output buffer
674 * a_uint rtadr0 address temporary
675 * a_uint rtadr1 address temporary
678 * int fprintf() c_library
681 * The data is output to the file defined by ofp.
685 * Written by G. Osborn, gary@s-4.com, 6-17-98.
686 * The new version concatenates the assembler
687 * output records when they represent contiguous
688 * memory segments to produce SXXMAXBYTES data byte
689 * S_ output lines whenever possible, resulting
690 * in a substantial reduction in file size.
691 * More importantly, the download time
692 * to the target system is much improved.
702 max
= (int) (rtadr1
- rtadr0
);
708 * Only the "S_" and the checksum itself are excluded
709 * from the checksum. The record length does not
710 * include "S_" and the pair count. It does
711 * include the address bytes, the data bytes,
714 reclen
= max
+ 1 + a_bytes
;
716 for (i
=0,addr
=rtadr0
; i
<a_bytes
; i
++,addr
>>=8) {
722 case 2: frmt
= "S1%02X%04lX"; addr
= rtadr0
& 0x0000ffffl
; break;
723 case 3: frmt
= "S2%02X%06lX"; addr
= rtadr0
& 0x00ffffffl
; break;
724 case 4: frmt
= "S3%02X%08lX"; addr
= rtadr0
& 0xffffffffl
; break;
729 case 2: frmt
= "S1%02X%04X"; addr
= rtadr0
& 0x0000ffff; break;
730 case 3: frmt
= "S2%02X%06X"; addr
= rtadr0
& 0x00ffffff; break;
731 case 4: frmt
= "S3%02X%08X"; addr
= rtadr0
& 0xffffffff; break;
734 fprintf(ofp
, frmt
, reclen
, addr
);
735 for (i
=0; i
<max
; i
++) {
737 fprintf(ofp
, "%02X", rtbuf
[i
] & 0x00ff);
743 fprintf(ofp
, "%02lX\n", (~chksum
) & 0x00ff);
745 fprintf(ofp
, "%02X\n", (~chksum
) & 0x00ff);
753 * Each code segment starts with the following record:
755 * Record Preamble - This field is either $00 (for start of new
756 * record) or $FF (for last record in file).
758 * Record Length Field - This field specifies the record length
759 * that follows the Load Address Field.
761 * 16-Bit Length - 2-bytes
762 * 24-Bit Length - 3-bytes
763 * 32-Bit Length - 4-bytes
765 * Load Address Field - This field consists of the address where
766 * the record will be loaded into memory.
768 * 16-Bit Address - 2-bytes
769 * 24-Bit Address - 3-bytes
770 * 32-Bit Address - 4-bytes
772 * Binary Data Bytes - Record Length data bytes.
774 * After the last code segment, a final record like the one above is
775 * placed. In this final segment, the Record Preamble is $FF, the
776 * Record Length Field is $0000 and the Load Adress Field is the
782 * int i 1 - process data
785 * The function decb() loads the output buffer with
786 * the relocated data.
790 * struct sym *sp symbol pointer
791 * a_uint symadr start address
794 * int a_bytes T Line Address Bytes
795 * FILE * ofp output file handle
796 * int rtcnt count of data words
797 * int rtflg[] output the data flag
798 * a_uint rtval[] relocated data
799 * char rtbuf[] output buffer
800 * a_uint rtadr0 address temporary
801 * a_uint rtadr1 address temporary
802 * a_uint rtadr2 address temporary
805 * int putc() c_library
806 * VOID dflush() lkout.c
809 * The data is placed into the output buffer.
844 for (i
=0,rtadr2
=0; i
<a_bytes
; i
++) {
845 rtadr2
= (rtadr2
<< 8) | rtval
[i
];
848 if (rtadr2
!= rtadr1
) {
850 * data bytes not contiguous between records
853 rtadr0
= rtadr1
= rtadr2
;
855 for (k
=a_bytes
; k
<rtcnt
; k
++) {
857 rtbuf
[(int) (rtadr1
++ - rtadr0
)] = rtval
[k
];
858 if (rtadr1
- rtadr0
== (unsigned) (DBXMAXBYTES
- (2 * a_bytes
) - 1)) {
864 /* Disk BASIC BIN Trailer */
865 sp
= lkpsym(".__.END.", 0);
866 if (sp
&& (sp
->s_axp
->a_bap
->a_ofp
== ofp
)) {
876 case 4: putc((int) (0 >> 24) & 0xFF, ofp
);
877 case 3: putc((int) (0 >> 16) & 0xFF, ofp
);
879 case 2: putc((int) (0 >> 8) & 0xFF, ofp
);
880 putc((int) (0 >> 0) & 0xFF, ofp
);
884 /* Starting Address */
886 case 4: putc((int) (symadr
>> 24) & 0xFF, ofp
);
887 case 3: putc((int) (symadr
>> 16) & 0xFF, ofp
);
889 case 2: putc((int) (symadr
>> 8) & 0xFF, ofp
);
890 putc((int) (symadr
>> 0) & 0xFF, ofp
);
899 * The function dflush() outputs the relocated data
900 * in the Disk BASIC loadable format
904 * int max number of data bytes
907 * FILE * ofp output file handle
908 * char rtbuf[] output buffer
909 * a_uint rtadr0 address temporary
910 * a_uint rtadr1 address temporary
913 * int putc() c_library
916 * The data is output to the file defined by ofp.
920 * Written by Boisy G. Pitre, boisy@boisypitre.com, 6-7-04
928 max
= (int) (rtadr1
- rtadr0
);
938 case 4: putc((int) (max
>> 24) & 0xFF, ofp
);
939 case 3: putc((int) (max
>> 16) & 0xFF, ofp
);
941 case 2: putc((int) (max
>> 8) & 0xFF, ofp
);
942 putc((int) (max
>> 0) & 0xFF, ofp
);
948 case 4: putc((int) (rtadr0
>> 24) & 0xFF, ofp
);
949 case 3: putc((int) (rtadr0
>> 16) & 0xFF, ofp
);
951 case 2: putc((int) (rtadr0
>> 8) & 0xFF, ofp
);
952 putc((int) (rtadr0
>> 0) & 0xFF, ofp
);
956 for (i
= 0; i
< max
; i
++) {