/// @file /// A lightweight library for printing on the C64. /// /// Printing with this library is done by calling print_ function for each element // Commodore 64 PRG executable file .file [name="multiply-16bit-const.prg", type="prg", segments="Program"] .segmentdef Program [segments="Basic, Code, Data"] .segmentdef Basic [start=$0801] .segmentdef Code [start=$80d] .segmentdef Data [startAfter="Code"] .segment Basic :BasicUpstart(main) .label print_screen = $400 .label print_char_cursor = $c .label print_line_cursor = $11 .label print_char_cursor_1 = $11 .label print_line_cursor_1 = $f .segment Code main: { .label i = $13 .label __5 = 2 .label __6 = 2 .label __7 = 2 .label __8 = 2 .label __9 = 2 .label __10 = 2 .label __11 = 2 // print_cls() jsr print_cls lda #print_screen sta.z print_char_cursor_1+1 lda #print_screen sta.z print_line_cursor_1+1 lda #<0 sta.z i sta.z i+1 lda #<0>>$10 sta.z i+2 lda #>0>>$10 sta.z i+3 __b1: // for(unsigned long i=0;i<3330;i+=333) lda.z i+3 cmp #>$d02>>$10 bcc __b2 bne !+ lda.z i+2 cmp #<$d02>>$10 bcc __b2 bne !+ lda.z i+1 cmp #>$d02 bcc __b2 bne !+ lda.z i cmp #<$d02 bcc __b2 !: // } rts __b2: // print_ulong_decimal(i*555) lda.z i asl sta.z __5 lda.z i+1 rol sta.z __5+1 lda.z i+2 rol sta.z __5+2 lda.z i+3 rol sta.z __5+3 asl.z __5 rol.z __5+1 rol.z __5+2 rol.z __5+3 asl.z __5 rol.z __5+1 rol.z __5+2 rol.z __5+3 asl.z __5 rol.z __5+1 rol.z __5+2 rol.z __5+3 clc lda.z __6 adc.z i sta.z __6 lda.z __6+1 adc.z i+1 sta.z __6+1 lda.z __6+2 adc.z i+2 sta.z __6+2 lda.z __6+3 adc.z i+3 sta.z __6+3 asl.z __7 rol.z __7+1 rol.z __7+2 rol.z __7+3 asl.z __7 rol.z __7+1 rol.z __7+2 rol.z __7+3 clc lda.z __8 adc.z i sta.z __8 lda.z __8+1 adc.z i+1 sta.z __8+1 lda.z __8+2 adc.z i+2 sta.z __8+2 lda.z __8+3 adc.z i+3 sta.z __8+3 asl.z __9 rol.z __9+1 rol.z __9+2 rol.z __9+3 asl.z __9 rol.z __9+1 rol.z __9+2 rol.z __9+3 clc lda.z __10 adc.z i sta.z __10 lda.z __10+1 adc.z i+1 sta.z __10+1 lda.z __10+2 adc.z i+2 sta.z __10+2 lda.z __10+3 adc.z i+3 sta.z __10+3 asl.z __11 rol.z __11+1 rol.z __11+2 rol.z __11+3 clc lda.z print_ulong_decimal.w adc.z i sta.z print_ulong_decimal.w lda.z print_ulong_decimal.w+1 adc.z i+1 sta.z print_ulong_decimal.w+1 lda.z print_ulong_decimal.w+2 adc.z i+2 sta.z print_ulong_decimal.w+2 lda.z print_ulong_decimal.w+3 adc.z i+3 sta.z print_ulong_decimal.w+3 jsr print_ulong_decimal // print_ln() jsr print_ln // i+=333 clc lda.z i adc #<$14d sta.z i lda.z i+1 adc #>$14d sta.z i+1 lda.z i+2 adc #0 sta.z i+2 lda.z i+3 adc #0 sta.z i+3 lda.z print_line_cursor sta.z print_line_cursor_1 lda.z print_line_cursor+1 sta.z print_line_cursor_1+1 jmp __b1 } // Clear the screen. Also resets current line/char cursor. print_cls: { // memset(print_screen, ' ', 1000) jsr memset // } rts } // Print a unsigned long as DECIMAL // void print_ulong_decimal(__zp(2) unsigned long w) print_ulong_decimal: { .label w = 2 // ultoa(w, decimal_digits_long, DECIMAL) jsr ultoa // print_str(decimal_digits_long) jsr print_str // } rts } // Print a newline print_ln: { __b1: // print_line_cursor + 0x28 lda #$28 clc adc.z print_line_cursor_1 sta.z print_line_cursor lda #0 adc.z print_line_cursor_1+1 sta.z print_line_cursor+1 // while (print_line_cursorstr sta.z dst+1 __b1: // for(char* dst = str; dst!=end; dst++) lda.z dst+1 cmp #>end bne __b2 lda.z dst cmp #decimal_digits_long sta.z buffer+1 ldx #0 txa sta.z digit __b1: // for( char digit=0; digit= digit_value) cpx #0 bne __b5 lda.z value+3 cmp.z digit_value+3 bcc !+ bne __b5 lda.z value+2 cmp.z digit_value+2 bcc !+ bne __b5 lda.z value+1 cmp.z digit_value+1 bcc !+ bne __b5 lda.z value cmp.z digit_value bcs __b5 !: __b4: // for( char digit=0; digitdecimal_digits_long sta.z str+1 __b1: // while(*str) ldy #0 lda (str),y cmp #0 bne __b2 // } rts __b2: // print_char(*(str++)) ldy #0 lda (str),y jsr print_char // print_char(*(str++)); inc.z str bne !+ inc.z str+1 !: jmp __b1 } // Used to convert a single digit of an unsigned number value to a string representation // Counts a single digit up from '0' as long as the value is larger than sub. // Each time the digit is increased sub is subtracted from value. // - buffer : pointer to the char that receives the digit // - value : The value where the digit will be derived from // - sub : the value of a '1' in the digit. Subtracted continually while the digit is increased. // (For decimal the subs used are 10000, 1000, 100, 10, 1) // returns : the value reduced by sub * digit so that it is less than sub. // __zp(2) unsigned long ultoa_append(__zp($a) char *buffer, __zp(2) unsigned long value, __zp(6) unsigned long sub) ultoa_append: { .label buffer = $a .label value = 2 .label sub = 6 .label return = 2 ldx #0 __b1: // while (value >= sub) lda.z value+3 cmp.z sub+3 bcc !+ bne __b2 lda.z value+2 cmp.z sub+2 bcc !+ bne __b2 lda.z value+1 cmp.z sub+1 bcc !+ bne __b2 lda.z value cmp.z sub bcs __b2 !: // *buffer = DIGITS[digit] lda DIGITS,x ldy #0 sta (buffer),y // } rts __b2: // digit++; inx // value -= sub lda.z value sec sbc.z sub sta.z value lda.z value+1 sbc.z sub+1 sta.z value+1 lda.z value+2 sbc.z sub+2 sta.z value+2 lda.z value+3 sbc.z sub+3 sta.z value+3 jmp __b1 } // Print a single char // void print_char(__register(A) char ch) print_char: { // *(print_char_cursor++) = ch ldy #0 sta (print_char_cursor),y // *(print_char_cursor++) = ch; inc.z print_char_cursor bne !+ inc.z print_char_cursor+1 !: // } rts } .segment Data // The digits used for numbers DIGITS: .text "0123456789abcdef" // Values of decimal digits RADIX_DECIMAL_VALUES_LONG: .dword $3b9aca00, $5f5e100, $989680, $f4240, $186a0, $2710, $3e8, $64, $a // Digits used for storing the decimal unsigned int decimal_digits_long: .fill $b, 0