2021-06-19 20:11:26 +00:00
|
|
|
/// @file
|
2021-06-19 19:26:05 +00:00
|
|
|
/// A lightweight library for printing on the C64.
|
2021-06-19 20:28:44 +00:00
|
|
|
///
|
2021-06-19 19:26:05 +00:00
|
|
|
/// Printing with this library is done by calling print_ function for each element
|
2020-12-21 07:57:41 +00:00
|
|
|
// Commodore 64 PRG executable file
|
|
|
|
.file [name="romsum-kc.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
|
2020-06-27 20:36:52 +00:00
|
|
|
:BasicUpstart(__start)
|
2020-02-02 07:47:47 +00:00
|
|
|
.label rom = $e000
|
2020-06-27 18:32:09 +00:00
|
|
|
.label print_screen = $400
|
2021-09-23 06:24:56 +00:00
|
|
|
.label last_time = $f
|
|
|
|
.label print_char_cursor = 6
|
|
|
|
.label print_line_cursor = $b
|
|
|
|
.label Ticks = $d
|
|
|
|
.label Ticks_1 = 2
|
2020-12-21 07:57:41 +00:00
|
|
|
.segment Code
|
2020-06-27 20:36:52 +00:00
|
|
|
__start: {
|
2021-05-02 12:28:03 +00:00
|
|
|
// unsigned int last_time
|
2020-06-27 18:32:09 +00:00
|
|
|
lda #<0
|
|
|
|
sta.z last_time
|
|
|
|
sta.z last_time+1
|
|
|
|
jsr main
|
|
|
|
rts
|
|
|
|
}
|
2020-02-02 07:47:47 +00:00
|
|
|
main: {
|
2021-09-23 06:24:56 +00:00
|
|
|
.label i = $d
|
2020-02-23 08:44:36 +00:00
|
|
|
// start()
|
2020-02-02 07:47:47 +00:00
|
|
|
jsr start
|
2020-06-27 18:32:09 +00:00
|
|
|
lda #<print_screen
|
2020-02-02 07:47:47 +00:00
|
|
|
sta.z print_line_cursor
|
2020-06-27 18:32:09 +00:00
|
|
|
lda #>print_screen
|
2020-02-02 07:47:47 +00:00
|
|
|
sta.z print_line_cursor+1
|
2020-06-27 18:32:09 +00:00
|
|
|
lda #<print_screen
|
2020-02-02 07:47:47 +00:00
|
|
|
sta.z print_char_cursor
|
2020-06-27 18:32:09 +00:00
|
|
|
lda #>print_screen
|
2020-02-02 07:47:47 +00:00
|
|
|
sta.z print_char_cursor+1
|
|
|
|
lda #<0
|
|
|
|
sta.z i
|
|
|
|
sta.z i+1
|
|
|
|
__b1:
|
2020-02-23 08:44:36 +00:00
|
|
|
// for(i=0;i<6;i++)
|
2020-02-02 07:47:47 +00:00
|
|
|
lda.z i+1
|
|
|
|
bne !+
|
|
|
|
lda.z i
|
2020-09-28 23:35:08 +00:00
|
|
|
cmp #6
|
2020-02-02 07:47:47 +00:00
|
|
|
bcc __b2
|
|
|
|
!:
|
2020-02-23 08:44:36 +00:00
|
|
|
// end()
|
2020-02-02 07:47:47 +00:00
|
|
|
jsr end
|
2020-02-23 08:44:36 +00:00
|
|
|
// }
|
2020-02-02 07:47:47 +00:00
|
|
|
rts
|
|
|
|
__b2:
|
2020-02-23 08:44:36 +00:00
|
|
|
// sum()
|
2020-02-02 07:47:47 +00:00
|
|
|
jsr sum
|
2020-02-23 08:44:36 +00:00
|
|
|
// sum()
|
2020-04-13 18:00:13 +00:00
|
|
|
// print_uint_decimal(sum())
|
|
|
|
jsr print_uint_decimal
|
2020-02-23 08:44:36 +00:00
|
|
|
// print_ln()
|
2020-02-02 07:47:47 +00:00
|
|
|
jsr print_ln
|
2020-02-23 08:44:36 +00:00
|
|
|
// for(i=0;i<6;i++)
|
2020-02-02 07:47:47 +00:00
|
|
|
inc.z i
|
|
|
|
bne !+
|
|
|
|
inc.z i+1
|
|
|
|
!:
|
|
|
|
lda.z print_line_cursor
|
|
|
|
sta.z print_char_cursor
|
|
|
|
lda.z print_line_cursor+1
|
|
|
|
sta.z print_char_cursor+1
|
|
|
|
jmp __b1
|
|
|
|
}
|
2020-06-27 21:26:57 +00:00
|
|
|
start: {
|
|
|
|
.label LAST_TIME = last_time
|
|
|
|
// asm
|
|
|
|
jsr $ffde
|
|
|
|
sta LAST_TIME
|
|
|
|
stx LAST_TIME+1
|
|
|
|
// }
|
|
|
|
rts
|
|
|
|
}
|
|
|
|
end: {
|
|
|
|
// Ticks = last_time
|
|
|
|
lda.z last_time
|
|
|
|
sta.z Ticks
|
|
|
|
lda.z last_time+1
|
|
|
|
sta.z Ticks+1
|
|
|
|
// start()
|
|
|
|
jsr start
|
|
|
|
// last_time -= Ticks
|
|
|
|
lda.z last_time
|
|
|
|
sec
|
|
|
|
sbc.z Ticks
|
|
|
|
sta.z last_time
|
|
|
|
lda.z last_time+1
|
|
|
|
sbc.z Ticks+1
|
|
|
|
sta.z last_time+1
|
|
|
|
// Ticks = last_time
|
|
|
|
lda.z last_time
|
|
|
|
sta.z Ticks_1
|
|
|
|
lda.z last_time+1
|
|
|
|
sta.z Ticks_1+1
|
|
|
|
// print_uint(Ticks)
|
|
|
|
jsr print_uint
|
|
|
|
// print_ln()
|
|
|
|
jsr print_ln
|
|
|
|
// }
|
|
|
|
rts
|
|
|
|
}
|
|
|
|
sum: {
|
2021-09-23 06:24:56 +00:00
|
|
|
.label s = 2
|
|
|
|
.label p = 8
|
|
|
|
.label return = 2
|
2020-06-27 21:26:57 +00:00
|
|
|
lda #<rom
|
|
|
|
sta.z p
|
|
|
|
lda #>rom
|
|
|
|
sta.z p+1
|
|
|
|
lda #<0
|
|
|
|
sta.z s
|
|
|
|
sta.z s+1
|
|
|
|
tax
|
|
|
|
/* doing it page-by-page is faster than doing just one huge loop */
|
|
|
|
__b1:
|
|
|
|
// for (page = 0; page < 0x20; page++)
|
|
|
|
cpx #$20
|
|
|
|
bcc __b3
|
|
|
|
// }
|
|
|
|
rts
|
|
|
|
__b3:
|
|
|
|
ldy #0
|
|
|
|
__b2:
|
|
|
|
// tmp = p[i]
|
|
|
|
lda (p),y
|
|
|
|
// s += tmp
|
|
|
|
clc
|
|
|
|
adc.z s
|
|
|
|
sta.z s
|
|
|
|
bcc !+
|
|
|
|
inc.z s+1
|
|
|
|
!:
|
|
|
|
// i++;
|
|
|
|
iny
|
|
|
|
// while (i)
|
|
|
|
cpy #0
|
|
|
|
bne __b2
|
|
|
|
// p += 0x100
|
|
|
|
lda.z p
|
2021-06-29 22:58:50 +00:00
|
|
|
clc
|
2020-06-27 21:26:57 +00:00
|
|
|
adc #<$100
|
|
|
|
sta.z p
|
|
|
|
lda.z p+1
|
|
|
|
adc #>$100
|
|
|
|
sta.z p+1
|
|
|
|
// for (page = 0; page < 0x20; page++)
|
|
|
|
inx
|
|
|
|
jmp __b1
|
|
|
|
}
|
|
|
|
// Print a unsigned int as DECIMAL
|
2021-09-23 06:24:56 +00:00
|
|
|
// void print_uint_decimal(__zp(2) unsigned int w)
|
2020-06-27 21:26:57 +00:00
|
|
|
print_uint_decimal: {
|
2021-09-23 06:24:56 +00:00
|
|
|
.label w = 2
|
2020-06-27 21:26:57 +00:00
|
|
|
// utoa(w, decimal_digits, DECIMAL)
|
|
|
|
jsr utoa
|
|
|
|
// print_str(decimal_digits)
|
|
|
|
jsr print_str
|
|
|
|
// }
|
|
|
|
rts
|
|
|
|
}
|
2020-02-02 07:47:47 +00:00
|
|
|
// Print a newline
|
|
|
|
print_ln: {
|
|
|
|
__b1:
|
2024-01-02 18:45:16 +00:00
|
|
|
// print_line_cursor + 0x28
|
2020-02-02 07:47:47 +00:00
|
|
|
lda #$28
|
|
|
|
clc
|
|
|
|
adc.z print_line_cursor
|
|
|
|
sta.z print_line_cursor
|
|
|
|
bcc !+
|
|
|
|
inc.z print_line_cursor+1
|
|
|
|
!:
|
2020-02-23 08:44:36 +00:00
|
|
|
// while (print_line_cursor<print_char_cursor)
|
2020-02-02 07:47:47 +00:00
|
|
|
lda.z print_line_cursor+1
|
|
|
|
cmp.z print_char_cursor+1
|
|
|
|
bcc __b1
|
|
|
|
bne !+
|
|
|
|
lda.z print_line_cursor
|
|
|
|
cmp.z print_char_cursor
|
|
|
|
bcc __b1
|
|
|
|
!:
|
2020-02-23 08:44:36 +00:00
|
|
|
// }
|
2020-02-02 07:47:47 +00:00
|
|
|
rts
|
|
|
|
}
|
2020-06-27 21:26:57 +00:00
|
|
|
// Print a unsigned int as HEX
|
2021-09-23 06:24:56 +00:00
|
|
|
// void print_uint(__zp(2) unsigned int w)
|
2020-06-27 21:26:57 +00:00
|
|
|
print_uint: {
|
2021-09-23 06:24:56 +00:00
|
|
|
.label w = 2
|
2021-06-12 18:57:35 +00:00
|
|
|
// print_uchar(BYTE1(w))
|
2020-06-27 21:26:57 +00:00
|
|
|
ldx.z w+1
|
|
|
|
jsr print_uchar
|
2021-06-12 18:57:35 +00:00
|
|
|
// print_uchar(BYTE0(w))
|
2020-06-27 21:26:57 +00:00
|
|
|
ldx.z w
|
|
|
|
jsr print_uchar
|
2020-04-18 18:54:39 +00:00
|
|
|
// }
|
|
|
|
rts
|
|
|
|
}
|
2020-02-02 07:47:47 +00:00
|
|
|
// Converts unsigned number value to a string representing it in RADIX format.
|
|
|
|
// If the leading digits are zero they are not included in the string.
|
|
|
|
// - value : The number to be converted to RADIX
|
|
|
|
// - buffer : receives the string representing the number and zero-termination.
|
|
|
|
// - radix : The radix to convert the number to (from the enum RADIX)
|
2021-09-23 06:24:56 +00:00
|
|
|
// void utoa(__zp(2) unsigned int value, __zp(8) char *buffer, char radix)
|
2020-02-02 07:47:47 +00:00
|
|
|
utoa: {
|
|
|
|
.const max_digits = 5
|
2021-09-23 06:24:56 +00:00
|
|
|
.label value = 2
|
|
|
|
.label digit_value = 4
|
|
|
|
.label buffer = 8
|
|
|
|
.label digit = $a
|
2020-02-02 07:47:47 +00:00
|
|
|
lda #<decimal_digits
|
|
|
|
sta.z buffer
|
|
|
|
lda #>decimal_digits
|
|
|
|
sta.z buffer+1
|
|
|
|
ldx #0
|
|
|
|
txa
|
|
|
|
sta.z digit
|
|
|
|
__b1:
|
2020-02-23 08:44:36 +00:00
|
|
|
// for( char digit=0; digit<max_digits-1; digit++ )
|
2020-02-02 07:47:47 +00:00
|
|
|
lda.z digit
|
|
|
|
cmp #max_digits-1
|
|
|
|
bcc __b2
|
2020-02-23 08:44:36 +00:00
|
|
|
// *buffer++ = DIGITS[(char)value]
|
2021-06-12 18:57:35 +00:00
|
|
|
ldx.z value
|
|
|
|
lda DIGITS,x
|
2020-02-02 07:47:47 +00:00
|
|
|
ldy #0
|
|
|
|
sta (buffer),y
|
2020-02-23 08:44:36 +00:00
|
|
|
// *buffer++ = DIGITS[(char)value];
|
2020-02-02 07:47:47 +00:00
|
|
|
inc.z buffer
|
|
|
|
bne !+
|
|
|
|
inc.z buffer+1
|
|
|
|
!:
|
2020-02-23 08:44:36 +00:00
|
|
|
// *buffer = 0
|
2020-02-02 07:47:47 +00:00
|
|
|
lda #0
|
|
|
|
tay
|
|
|
|
sta (buffer),y
|
2020-02-23 08:44:36 +00:00
|
|
|
// }
|
2020-02-02 07:47:47 +00:00
|
|
|
rts
|
|
|
|
__b2:
|
2021-05-02 12:28:03 +00:00
|
|
|
// unsigned int digit_value = digit_values[digit]
|
2020-02-02 07:47:47 +00:00
|
|
|
lda.z digit
|
|
|
|
asl
|
|
|
|
tay
|
|
|
|
lda RADIX_DECIMAL_VALUES,y
|
|
|
|
sta.z digit_value
|
|
|
|
lda RADIX_DECIMAL_VALUES+1,y
|
|
|
|
sta.z digit_value+1
|
2020-02-23 08:44:36 +00:00
|
|
|
// if (started || value >= digit_value)
|
2020-02-02 07:47:47 +00:00
|
|
|
cpx #0
|
|
|
|
bne __b5
|
2021-08-13 19:22:17 +00:00
|
|
|
cmp.z value+1
|
|
|
|
bne !+
|
|
|
|
lda.z digit_value
|
|
|
|
cmp.z value
|
|
|
|
beq __b5
|
2020-02-02 07:47:47 +00:00
|
|
|
!:
|
2021-08-13 19:22:17 +00:00
|
|
|
bcc __b5
|
2020-02-02 07:47:47 +00:00
|
|
|
__b4:
|
2020-02-23 08:44:36 +00:00
|
|
|
// for( char digit=0; digit<max_digits-1; digit++ )
|
2020-02-02 07:47:47 +00:00
|
|
|
inc.z digit
|
|
|
|
jmp __b1
|
|
|
|
__b5:
|
2020-02-23 08:44:36 +00:00
|
|
|
// utoa_append(buffer++, value, digit_value)
|
2020-02-02 07:47:47 +00:00
|
|
|
jsr utoa_append
|
2020-02-23 08:44:36 +00:00
|
|
|
// utoa_append(buffer++, value, digit_value)
|
|
|
|
// value = utoa_append(buffer++, value, digit_value)
|
|
|
|
// value = utoa_append(buffer++, value, digit_value);
|
2020-02-02 07:47:47 +00:00
|
|
|
inc.z buffer
|
|
|
|
bne !+
|
|
|
|
inc.z buffer+1
|
|
|
|
!:
|
|
|
|
ldx #1
|
|
|
|
jmp __b4
|
|
|
|
}
|
2020-06-27 21:26:57 +00:00
|
|
|
// Print a zero-terminated string
|
2021-09-23 06:24:56 +00:00
|
|
|
// void print_str(__zp(4) char *str)
|
2020-06-27 21:26:57 +00:00
|
|
|
print_str: {
|
2021-09-23 06:24:56 +00:00
|
|
|
.label str = 4
|
2020-06-27 21:26:57 +00:00
|
|
|
lda #<decimal_digits
|
|
|
|
sta.z str
|
|
|
|
lda #>decimal_digits
|
|
|
|
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
|
|
|
|
}
|
|
|
|
// Print a char as HEX
|
2021-08-10 15:48:55 +00:00
|
|
|
// void print_uchar(__register(X) char b)
|
2020-06-27 21:26:57 +00:00
|
|
|
print_uchar: {
|
|
|
|
// b>>4
|
|
|
|
txa
|
|
|
|
lsr
|
|
|
|
lsr
|
|
|
|
lsr
|
|
|
|
lsr
|
|
|
|
// print_char(print_hextab[b>>4])
|
|
|
|
tay
|
|
|
|
lda DIGITS,y
|
|
|
|
// Table of hexadecimal digits
|
|
|
|
jsr print_char
|
2024-01-02 18:45:16 +00:00
|
|
|
// b&0xf
|
2020-06-27 21:26:57 +00:00
|
|
|
lda #$f
|
|
|
|
axs #0
|
2024-01-02 18:45:16 +00:00
|
|
|
// print_char(print_hextab[b&0xf])
|
2020-06-27 21:26:57 +00:00
|
|
|
lda DIGITS,x
|
|
|
|
jsr print_char
|
|
|
|
// }
|
|
|
|
rts
|
|
|
|
}
|
2020-02-02 07:47:47 +00:00
|
|
|
// 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.
|
2021-09-23 06:24:56 +00:00
|
|
|
// __zp(2) unsigned int utoa_append(__zp(8) char *buffer, __zp(2) unsigned int value, __zp(4) unsigned int sub)
|
2020-02-02 07:47:47 +00:00
|
|
|
utoa_append: {
|
2021-09-23 06:24:56 +00:00
|
|
|
.label buffer = 8
|
|
|
|
.label value = 2
|
|
|
|
.label sub = 4
|
|
|
|
.label return = 2
|
2020-02-02 07:47:47 +00:00
|
|
|
ldx #0
|
|
|
|
__b1:
|
2020-02-23 08:44:36 +00:00
|
|
|
// while (value >= sub)
|
2021-08-13 19:22:17 +00:00
|
|
|
lda.z sub+1
|
|
|
|
cmp.z value+1
|
|
|
|
bne !+
|
|
|
|
lda.z sub
|
|
|
|
cmp.z value
|
|
|
|
beq __b2
|
2020-02-02 07:47:47 +00:00
|
|
|
!:
|
2021-08-13 19:22:17 +00:00
|
|
|
bcc __b2
|
2020-02-23 08:44:36 +00:00
|
|
|
// *buffer = DIGITS[digit]
|
2020-02-02 07:47:47 +00:00
|
|
|
lda DIGITS,x
|
|
|
|
ldy #0
|
|
|
|
sta (buffer),y
|
2020-02-23 08:44:36 +00:00
|
|
|
// }
|
2020-02-02 07:47:47 +00:00
|
|
|
rts
|
|
|
|
__b2:
|
2020-02-23 08:44:36 +00:00
|
|
|
// digit++;
|
2020-02-02 07:47:47 +00:00
|
|
|
inx
|
2020-02-23 08:44:36 +00:00
|
|
|
// value -= sub
|
2020-02-02 07:47:47 +00:00
|
|
|
lda.z value
|
|
|
|
sec
|
|
|
|
sbc.z sub
|
|
|
|
sta.z value
|
|
|
|
lda.z value+1
|
|
|
|
sbc.z sub+1
|
|
|
|
sta.z value+1
|
|
|
|
jmp __b1
|
|
|
|
}
|
2020-06-27 21:26:57 +00:00
|
|
|
// Print a single char
|
2021-08-10 15:48:55 +00:00
|
|
|
// void print_char(__register(A) char ch)
|
2020-06-27 21:26:57 +00:00
|
|
|
print_char: {
|
|
|
|
// *(print_char_cursor++) = ch
|
2020-02-02 07:47:47 +00:00
|
|
|
ldy #0
|
2020-06-27 21:26:57 +00:00
|
|
|
sta (print_char_cursor),y
|
|
|
|
// *(print_char_cursor++) = ch;
|
|
|
|
inc.z print_char_cursor
|
|
|
|
bne !+
|
|
|
|
inc.z print_char_cursor+1
|
2020-02-02 07:47:47 +00:00
|
|
|
!:
|
2020-02-23 08:44:36 +00:00
|
|
|
// }
|
2020-02-02 07:47:47 +00:00
|
|
|
rts
|
|
|
|
}
|
2020-12-21 07:57:41 +00:00
|
|
|
.segment Data
|
2020-02-02 07:47:47 +00:00
|
|
|
// The digits used for numbers
|
|
|
|
DIGITS: .text "0123456789abcdef"
|
|
|
|
// Values of decimal digits
|
|
|
|
RADIX_DECIMAL_VALUES: .word $2710, $3e8, $64, $a
|
2020-04-13 18:00:13 +00:00
|
|
|
// Digits used for storing the decimal unsigned int
|
2020-02-02 07:47:47 +00:00
|
|
|
decimal_digits: .fill 6, 0
|