prog8/compiler/res/prog8lib/prog8lib.asm
2019-08-18 02:05:51 +02:00

1674 lines
33 KiB
NASM

; Prog8 internal library routines - always included by the compiler
;
; Written by Irmen de Jong (irmen@razorvine.net) - license: GNU GPL 3.0
;
; indent format: TABS, size=8
init_system .proc
; -- initializes the machine to a sane starting state
; Called automatically by the loader program logic.
; This means that the BASIC, KERNAL and CHARGEN ROMs are banked in,
; the VIC, SID and CIA chips are reset, screen is cleared, and the default IRQ is set.
; Also a different color scheme is chosen to identify ourselves a little.
; Uppercase charset is activated, and all three registers set to 0, status flags cleared.
sei
cld
lda #%00101111
sta $00
lda #%00100111
sta $01
jsr c64.IOINIT
jsr c64.RESTOR
jsr c64.CINT
lda #6
sta c64.EXTCOL
lda #7
sta c64.COLOR
lda #0
sta c64.BGCOL0
tax
tay
clc
clv
cli
rts
.pend
read_byte_from_address .proc
; -- read the byte from the memory address on the top of the stack, return in A (stack remains unchanged)
lda c64.ESTACK_LO+1,x
ldy c64.ESTACK_HI+1,x
sta (+) +1
sty (+) +2
+ lda $ffff ; modified
rts
.pend
add_a_to_zpword .proc
; -- add ubyte in A to the uword in c64.SCRATCH_ZPWORD1
clc
adc c64.SCRATCH_ZPWORD1
sta c64.SCRATCH_ZPWORD1
bcc +
inc c64.SCRATCH_ZPWORD1+1
+ rts
.pend
pop_index_times_5 .proc
inx
lda c64.ESTACK_LO,x
asl a
asl a
clc
adc c64.ESTACK_LO,x
rts
.pend
neg_b .proc
lda #0
sec
sbc c64.ESTACK_LO+1,x
sta c64.ESTACK_LO+1,x
rts
.pend
neg_w .proc
sec
lda #0
sbc c64.ESTACK_LO+1,x
sta c64.ESTACK_LO+1,x
lda #0
sbc c64.ESTACK_HI+1,x
sta c64.ESTACK_HI+1,x
rts
.pend
inv_word .proc
lda c64.ESTACK_LO+1,x
eor #255
sta c64.ESTACK_LO+1,x
lda c64.ESTACK_HI+1,x
eor #255
sta c64.ESTACK_HI+1,x
rts
.pend
not_byte .proc
lda c64.ESTACK_LO+1,x
beq +
lda #1
+ eor #1
sta c64.ESTACK_LO+1,x
rts
.pend
not_word .proc
lda c64.ESTACK_LO + 1,x
ora c64.ESTACK_HI + 1,x
beq +
lda #1
+ eor #1
sta c64.ESTACK_LO + 1,x
lsr a
sta c64.ESTACK_HI + 1,x
rts
.pend
bitand_b .proc
; -- bitwise and (of 2 bytes)
lda c64.ESTACK_LO+2,x
and c64.ESTACK_LO+1,x
inx
sta c64.ESTACK_LO+1,x
rts
.pend
bitor_b .proc
; -- bitwise or (of 2 bytes)
lda c64.ESTACK_LO+2,x
ora c64.ESTACK_LO+1,x
inx
sta c64.ESTACK_LO+1,x
rts
.pend
bitxor_b .proc
; -- bitwise xor (of 2 bytes)
lda c64.ESTACK_LO+2,x
eor c64.ESTACK_LO+1,x
inx
sta c64.ESTACK_LO+1,x
rts
.pend
bitand_w .proc
; -- bitwise and (of 2 words)
lda c64.ESTACK_LO+2,x
and c64.ESTACK_LO+1,x
sta c64.ESTACK_LO+2,x
lda c64.ESTACK_HI+2,x
and c64.ESTACK_HI+1,x
sta c64.ESTACK_HI+2,x
inx
rts
.pend
bitor_w .proc
; -- bitwise or (of 2 words)
lda c64.ESTACK_LO+2,x
ora c64.ESTACK_LO+1,x
sta c64.ESTACK_LO+2,x
lda c64.ESTACK_HI+2,x
ora c64.ESTACK_HI+1,x
sta c64.ESTACK_HI+2,x
inx
rts
.pend
bitxor_w .proc
; -- bitwise xor (of 2 bytes)
lda c64.ESTACK_LO+2,x
eor c64.ESTACK_LO+1,x
sta c64.ESTACK_LO+2,x
lda c64.ESTACK_HI+2,x
eor c64.ESTACK_HI+1,x
sta c64.ESTACK_HI+2,x
inx
rts
.pend
and_b .proc
; -- logical and (of 2 bytes)
lda c64.ESTACK_LO+2,x
beq +
lda #1
+ sta c64.SCRATCH_ZPB1
lda c64.ESTACK_LO+1,x
beq +
lda #1
+ and c64.SCRATCH_ZPB1
inx
sta c64.ESTACK_LO+1,x
rts
.pend
or_b .proc
; -- logical or (of 2 bytes)
lda c64.ESTACK_LO+2,x
ora c64.ESTACK_LO+1,x
beq +
lda #1
+ inx
sta c64.ESTACK_LO+1,x
rts
.pend
xor_b .proc
; -- logical xor (of 2 bytes)
lda c64.ESTACK_LO+2,x
beq +
lda #1
+ sta c64.SCRATCH_ZPB1
lda c64.ESTACK_LO+1,x
beq +
lda #1
+ eor c64.SCRATCH_ZPB1
inx
sta c64.ESTACK_LO+1,x
rts
.pend
and_w .proc
; -- logical and (word and word -> byte)
lda c64.ESTACK_LO+2,x
ora c64.ESTACK_HI+2,x
beq +
lda #1
+ sta c64.SCRATCH_ZPB1
lda c64.ESTACK_LO+1,x
ora c64.ESTACK_HI+1,x
beq +
lda #1
+ and c64.SCRATCH_ZPB1
inx
sta c64.ESTACK_LO+1,x
sta c64.ESTACK_HI+1,x
rts
.pend
or_w .proc
; -- logical or (word or word -> byte)
lda c64.ESTACK_LO+2,x
ora c64.ESTACK_LO+1,x
ora c64.ESTACK_HI+2,x
ora c64.ESTACK_HI+1,x
beq +
lda #1
+ inx
sta c64.ESTACK_LO+1,x
sta c64.ESTACK_HI+1,x
rts
.pend
xor_w .proc
; -- logical xor (word xor word -> byte)
lda c64.ESTACK_LO+2,x
ora c64.ESTACK_HI+2,x
beq +
lda #1
+ sta c64.SCRATCH_ZPB1
lda c64.ESTACK_LO+1,x
ora c64.ESTACK_HI+1,x
beq +
lda #1
+ eor c64.SCRATCH_ZPB1
inx
sta c64.ESTACK_LO+1,x
sta c64.ESTACK_HI+1,x
rts
.pend
abs_b .proc
; -- push abs(byte) on stack (as byte)
lda c64.ESTACK_LO+1,x
bmi neg_b
rts
.pend
abs_w .proc
; -- push abs(word) on stack (as word)
lda c64.ESTACK_HI+1,x
bmi neg_w
rts
.pend
add_w .proc
; -- push word+word / uword+uword
inx
clc
lda c64.ESTACK_LO,x
adc c64.ESTACK_LO+1,x
sta c64.ESTACK_LO+1,x
lda c64.ESTACK_HI,x
adc c64.ESTACK_HI+1,x
sta c64.ESTACK_HI+1,x
rts
.pend
sub_w .proc
; -- push word-word
inx
sec
lda c64.ESTACK_LO+1,x
sbc c64.ESTACK_LO,x
sta c64.ESTACK_LO+1,x
lda c64.ESTACK_HI+1,x
sbc c64.ESTACK_HI,x
sta c64.ESTACK_HI+1,x
rts
.pend
mul_byte .proc
; -- b*b->b (signed and unsigned)
inx
lda c64.ESTACK_LO,x
ldy c64.ESTACK_LO+1,x
jsr math.multiply_bytes
sta c64.ESTACK_LO+1,x
rts
.pend
mul_word .proc
inx
lda c64.ESTACK_LO,x
sta c64.SCRATCH_ZPWORD1
lda c64.ESTACK_HI,x
sta c64.SCRATCH_ZPWORD1+1
lda c64.ESTACK_LO+1,x
ldy c64.ESTACK_HI+1,x
stx c64.SCRATCH_ZPREGX
jsr math.multiply_words
ldx c64.SCRATCH_ZPREGX
lda math.multiply_words.result
sta c64.ESTACK_LO+1,x
lda math.multiply_words.result+1
sta c64.ESTACK_HI+1,x
rts
.pend
idiv_b .proc
; signed division: use unsigned division and fix sign of result afterwards
inx
lda c64.ESTACK_LO,x
eor c64.ESTACK_LO+1,x
php ; save sign of result
lda c64.ESTACK_LO,x
bpl +
eor #$ff
sec
adc #0 ; make num1 positive
+ tay
inx
lda c64.ESTACK_LO,x
bpl +
eor #$ff
sec
adc #0 ; make num2 positive
+ jsr math.divmod_ub
sta _remainder
tya
plp ; get sign of result
bpl +
eor #$ff
sec
adc #0 ; negate result
+ sta c64.ESTACK_LO,x
dex
rts
_remainder .byte 0
.pend
idiv_ub .proc
inx
ldy c64.ESTACK_LO,x
lda c64.ESTACK_LO+1,x
jsr math.divmod_ub
tya
sta c64.ESTACK_LO+1,x
rts
.pend
idiv_w .proc
; signed division: use unsigned division and fix sign of result afterwards
lda c64.ESTACK_HI+2,x
eor c64.ESTACK_HI+1,x
php ; save sign of result
lda c64.ESTACK_HI+1,x
bpl +
jsr neg_w ; make value positive
+ inx
lda c64.ESTACK_HI+1,x
bpl +
jsr neg_w ; make value positive
+ lda c64.ESTACK_LO+1,x
sta c64.SCRATCH_ZPWORD1
lda c64.ESTACK_HI+1,x
sta c64.SCRATCH_ZPWORD1+1
lda c64.ESTACK_LO,x
ldy c64.ESTACK_HI,x
jsr math.divmod_uw_asm
sta c64.ESTACK_LO+1,x
tya
sta c64.ESTACK_HI+1,x
plp
bpl +
jmp neg_w ; negate result
+ rts
.pend
idiv_uw .proc
inx
lda c64.ESTACK_LO+1,x
sta c64.SCRATCH_ZPWORD1
lda c64.ESTACK_HI+1,x
sta c64.SCRATCH_ZPWORD1+1
lda c64.ESTACK_LO,x
ldy c64.ESTACK_HI,x
jsr math.divmod_uw_asm
sta c64.ESTACK_LO+1,x
tya
sta c64.ESTACK_HI+1,x
rts
.pend
remainder_ub .proc
inx
ldy c64.ESTACK_LO,x ; right operand
lda c64.ESTACK_LO+1,x ; left operand
jsr math.divmod_ub
sta c64.ESTACK_LO+1,x
rts
.pend
remainder_uw .proc
inx
lda c64.ESTACK_LO+1,x
sta c64.SCRATCH_ZPWORD1
lda c64.ESTACK_HI+1,x
sta c64.SCRATCH_ZPWORD1+1
lda c64.ESTACK_LO,x
ldy c64.ESTACK_HI,x
jsr math.divmod_uw_asm
lda c64.SCRATCH_ZPWORD2
sta c64.ESTACK_LO+1,x
lda c64.SCRATCH_ZPWORD2+1
sta c64.ESTACK_HI+1,x
rts
.pend
equal_w .proc
; -- are the two words on the stack identical?
lda c64.ESTACK_LO+1,x
cmp c64.ESTACK_LO+2,x
bne equal_b._equal_b_false
lda c64.ESTACK_HI+1,x
cmp c64.ESTACK_HI+2,x
bne equal_b._equal_b_false
beq equal_b._equal_b_true
.pend
notequal_b .proc
; -- are the two bytes on the stack different?
lda c64.ESTACK_LO+1,x
cmp c64.ESTACK_LO+2,x
beq equal_b._equal_b_false
bne equal_b._equal_b_true
.pend
notequal_w .proc
; -- are the two words on the stack different?
lda c64.ESTACK_HI+1,x
cmp c64.ESTACK_HI+2,x
beq notequal_b
bne equal_b._equal_b_true
.pend
less_ub .proc
lda c64.ESTACK_LO+2,x
cmp c64.ESTACK_LO+1,x
bcc equal_b._equal_b_true
bcs equal_b._equal_b_false
.pend
less_b .proc
; see http://www.6502.org/tutorials/compare_beyond.html
lda c64.ESTACK_LO+2,x
sec
sbc c64.ESTACK_LO+1,x
bvc +
eor #$80
+ bmi equal_b._equal_b_true
bpl equal_b._equal_b_false
.pend
less_uw .proc
lda c64.ESTACK_HI+2,x
cmp c64.ESTACK_HI+1,x
bcc equal_b._equal_b_true
bne equal_b._equal_b_false
lda c64.ESTACK_LO+2,x
cmp c64.ESTACK_LO+1,x
bcc equal_b._equal_b_true
bcs equal_b._equal_b_false
.pend
less_w .proc
lda c64.ESTACK_LO+2,x
cmp c64.ESTACK_LO+1,x
lda c64.ESTACK_HI+2,x
sbc c64.ESTACK_HI+1,x
bvc +
eor #$80
+ bmi equal_b._equal_b_true
bpl equal_b._equal_b_false
.pend
equal_b .proc
; -- are the two bytes on the stack identical?
lda c64.ESTACK_LO+2,x
cmp c64.ESTACK_LO+1,x
bne _equal_b_false
_equal_b_true lda #1
_equal_b_store inx
sta c64.ESTACK_LO+1,x
rts
_equal_b_false lda #0
beq _equal_b_store
.pend
lesseq_ub .proc
lda c64.ESTACK_LO+1,x
cmp c64.ESTACK_LO+2,x
bcs equal_b._equal_b_true
bcc equal_b._equal_b_false
.pend
lesseq_b .proc
; see http://www.6502.org/tutorials/compare_beyond.html
lda c64.ESTACK_LO+2,x
clc
sbc c64.ESTACK_LO+1,x
bvc +
eor #$80
+ bmi equal_b._equal_b_true
bpl equal_b._equal_b_false
.pend
lesseq_uw .proc
lda c64.ESTACK_HI+1,x
cmp c64.ESTACK_HI+2,x
bcc equal_b._equal_b_false
bne equal_b._equal_b_true
lda c64.ESTACK_LO+1,x
cmp c64.ESTACK_LO+2,x
bcs equal_b._equal_b_true
bcc equal_b._equal_b_false
.pend
lesseq_w .proc
lda c64.ESTACK_LO+1,x
cmp c64.ESTACK_LO+2,x
lda c64.ESTACK_HI+1,x
sbc c64.ESTACK_HI+2,x
bvc +
eor #$80
+ bpl equal_b._equal_b_true
bmi equal_b._equal_b_false
.pend
greater_ub .proc
lda c64.ESTACK_LO+2,x
cmp c64.ESTACK_LO+1,x
beq equal_b._equal_b_false
bcs equal_b._equal_b_true
bcc equal_b._equal_b_false
.pend
greater_b .proc
; see http://www.6502.org/tutorials/compare_beyond.html
lda c64.ESTACK_LO+2,x
clc
sbc c64.ESTACK_LO+1,x
bvc +
eor #$80
+ bpl equal_b._equal_b_true
bmi equal_b._equal_b_false
.pend
greater_uw .proc
lda c64.ESTACK_HI+1,x
cmp c64.ESTACK_HI+2,x
bcc equal_b._equal_b_true
bne equal_b._equal_b_false
lda c64.ESTACK_LO+1,x
cmp c64.ESTACK_LO+2,x
bcc equal_b._equal_b_true
bcs equal_b._equal_b_false
.pend
greater_w .proc
lda c64.ESTACK_LO+1,x
cmp c64.ESTACK_LO+2,x
lda c64.ESTACK_HI+1,x
sbc c64.ESTACK_HI+2,x
bvc +
eor #$80
+ bmi equal_b._equal_b_true
bpl equal_b._equal_b_false
.pend
greatereq_ub .proc
lda c64.ESTACK_LO+2,x
cmp c64.ESTACK_LO+1,x
bcs equal_b._equal_b_true
bcc equal_b._equal_b_false
.pend
greatereq_b .proc
; see http://www.6502.org/tutorials/compare_beyond.html
lda c64.ESTACK_LO+2,x
sec
sbc c64.ESTACK_LO+1,x
bvc +
eor #$80
+ bpl equal_b._equal_b_true
bmi equal_b._equal_b_false
.pend
greatereq_uw .proc
lda c64.ESTACK_HI+2,x
cmp c64.ESTACK_HI+1,x
bcc equal_b._equal_b_false
bne equal_b._equal_b_true
lda c64.ESTACK_LO+2,x
cmp c64.ESTACK_LO+1,x
bcs equal_b._equal_b_true
bcc equal_b._equal_b_false
.pend
greatereq_w .proc
lda c64.ESTACK_LO+2,x
cmp c64.ESTACK_LO+1,x
lda c64.ESTACK_HI+2,x
sbc c64.ESTACK_HI+1,x
bvc +
eor #$80
+ bpl equal_b._equal_b_true
bmi equal_b._equal_b_false
.pend
func_read_flags .proc
; -- put the processor status register on the stack
php
pla
sta c64.ESTACK_LO,x
dex
rts
.pend
func_sqrt16 .proc
lda c64.ESTACK_LO+1,x
sta c64.SCRATCH_ZPWORD2
lda c64.ESTACK_HI+1,x
sta c64.SCRATCH_ZPWORD2+1
stx c64.SCRATCH_ZPREGX
ldy #$00 ; r = 0
ldx #$07
clc ; clear bit 16 of m
_loop
tya
ora _stab-1,x
sta c64.SCRATCH_ZPB1 ; (r asl 8) | (d asl 7)
lda c64.SCRATCH_ZPWORD2+1
bcs _skip0 ; m >= 65536? then t <= m is always true
cmp c64.SCRATCH_ZPB1
bcc _skip1 ; t <= m
_skip0
sbc c64.SCRATCH_ZPB1
sta c64.SCRATCH_ZPWORD2+1 ; m = m - t
tya
ora _stab,x
tay ; r = r or d
_skip1
asl c64.SCRATCH_ZPWORD2
rol c64.SCRATCH_ZPWORD2+1 ; m = m asl 1
dex
bne _loop
; last iteration
bcs _skip2
sty c64.SCRATCH_ZPB1
lda c64.SCRATCH_ZPWORD2
cmp #$80
lda c64.SCRATCH_ZPWORD2+1
sbc c64.SCRATCH_ZPB1
bcc _skip3
_skip2
iny ; r = r or d (d is 1 here)
_skip3
ldx c64.SCRATCH_ZPREGX
tya
sta c64.ESTACK_LO+1,x
lda #0
sta c64.ESTACK_HI+1,x
rts
_stab .byte $01,$02,$04,$08,$10,$20,$40,$80
.pend
func_sin8 .proc
ldy c64.ESTACK_LO+1,x
lda _sinecos8,y
sta c64.ESTACK_LO+1,x
rts
_sinecos8 .char 127 * sin(range(256+64) * rad(360.0/256.0))
.pend
func_sin8u .proc
ldy c64.ESTACK_LO+1,x
lda _sinecos8u,y
sta c64.ESTACK_LO+1,x
rts
_sinecos8u .byte 128 + 127.5 * sin(range(256+64) * rad(360.0/256.0))
.pend
func_sin16 .proc
ldy c64.ESTACK_LO+1,x
lda _sinecos8lo,y
sta c64.ESTACK_LO+1,x
lda _sinecos8hi,y
sta c64.ESTACK_HI+1,x
rts
_ := 32767 * sin(range(256+64) * rad(360.0/256.0))
_sinecos8lo .byte <_
_sinecos8hi .byte >_
.pend
func_sin16u .proc
ldy c64.ESTACK_LO+1,x
lda _sinecos8ulo,y
sta c64.ESTACK_LO+1,x
lda _sinecos8uhi,y
sta c64.ESTACK_HI+1,x
rts
_ := 32768 + 32767.5 * sin(range(256+64) * rad(360.0/256.0))
_sinecos8ulo .byte <_
_sinecos8uhi .byte >_
.pend
func_cos8 .proc
ldy c64.ESTACK_LO+1,x
lda func_sin8._sinecos8+64,y
sta c64.ESTACK_LO+1,x
rts
.pend
func_cos8u .proc
ldy c64.ESTACK_LO+1,x
lda func_sin8u._sinecos8u+64,y
sta c64.ESTACK_LO+1,x
rts
.pend
func_cos16 .proc
ldy c64.ESTACK_LO+1,x
lda func_sin16._sinecos8lo+64,y
sta c64.ESTACK_LO+1,x
lda func_sin16._sinecos8hi+64,y
sta c64.ESTACK_HI+1,x
rts
.pend
func_cos16u .proc
ldy c64.ESTACK_LO+1,x
lda func_sin16u._sinecos8ulo+64,y
sta c64.ESTACK_LO+1,x
lda func_sin16u._sinecos8uhi+64,y
sta c64.ESTACK_HI+1,x
rts
.pend
peek_address .proc
; -- peek address on stack into c64.SCRATCH_ZPWORD1
lda c64.ESTACK_LO+1,x
sta c64.SCRATCH_ZPWORD1
lda c64.ESTACK_HI+1,x
sta c64.SCRATCH_ZPWORD1+1
rts
.pend
func_any_b .proc
inx
lda c64.ESTACK_LO,x ; array size
_entry sta _cmp_mod+1 ; self-modifying code
jsr peek_address
ldy #0
- lda (c64.SCRATCH_ZPWORD1),y
bne _got_any
iny
_cmp_mod cpy #255 ; modified
bne -
lda #0
sta c64.ESTACK_LO+1,x
rts
_got_any lda #1
sta c64.ESTACK_LO+1,x
rts
.pend
func_any_w .proc
inx
lda c64.ESTACK_LO,x ; array size
asl a ; times 2 because of word
jmp func_any_b._entry
.pend
func_all_b .proc
inx
lda c64.ESTACK_LO,x ; array size
sta _cmp_mod+1 ; self-modifying code
jsr peek_address
ldy #0
- lda (c64.SCRATCH_ZPWORD1),y
beq _got_not_all
iny
_cmp_mod cpy #255 ; modified
bne -
lda #1
sta c64.ESTACK_LO+1,x
rts
_got_not_all lda #0
sta c64.ESTACK_LO+1,x
rts
.pend
func_all_w .proc
inx
lda c64.ESTACK_LO,x ; array size
asl a ; times 2 because of word
sta _cmp_mod+1 ; self-modifying code
jsr peek_address
ldy #0
- lda (c64.SCRATCH_ZPWORD1),y
bne +
iny
lda (c64.SCRATCH_ZPWORD1),y
bne ++
lda #0
sta c64.ESTACK_LO+1,x
rts
+ iny
+ iny
_cmp_mod cpy #255 ; modified
bne -
lda #1
sta c64.ESTACK_LO+1,x
rts
.pend
func_max_ub .proc
jsr pop_array_and_lengthmin1Y
lda #0
sta c64.SCRATCH_ZPB1
- lda (c64.SCRATCH_ZPWORD1),y
cmp c64.SCRATCH_ZPB1
bcc +
sta c64.SCRATCH_ZPB1
+ dey
cpy #255
bne -
lda c64.SCRATCH_ZPB1
sta c64.ESTACK_LO,x
dex
rts
.pend
func_max_b .proc
jsr pop_array_and_lengthmin1Y
lda #-128
sta c64.SCRATCH_ZPB1
- lda (c64.SCRATCH_ZPWORD1),y
sec
sbc c64.SCRATCH_ZPB1
bvc +
eor #$80
+ bmi +
lda (c64.SCRATCH_ZPWORD1),y
sta c64.SCRATCH_ZPB1
+ dey
cpy #255
bne -
lda c64.SCRATCH_ZPB1
sta c64.ESTACK_LO,x
dex
rts
.pend
func_max_uw .proc
lda #0
sta _result_maxuw
sta _result_maxuw+1
jsr pop_array_and_lengthmin1Y
tya
asl a
tay
_loop
iny
lda (c64.SCRATCH_ZPWORD1),y
dey
cmp _result_maxuw+1
bcc _lesseq
bne _greater
lda (c64.SCRATCH_ZPWORD1),y
cmp _result_maxuw
bcc _lesseq
_greater lda (c64.SCRATCH_ZPWORD1),y
sta _result_maxuw
iny
lda (c64.SCRATCH_ZPWORD1),y
sta _result_maxuw+1
dey
_lesseq dey
dey
cpy #254
bne _loop
lda _result_maxuw
sta c64.ESTACK_LO,x
lda _result_maxuw+1
sta c64.ESTACK_HI,x
dex
rts
_result_maxuw .word 0
.pend
func_max_w .proc
lda #$00
sta _result_maxw
lda #$80
sta _result_maxw+1
jsr pop_array_and_lengthmin1Y
tya
asl a
tay
_loop
lda (c64.SCRATCH_ZPWORD1),y
cmp _result_maxw
iny
lda (c64.SCRATCH_ZPWORD1),y
dey
sbc _result_maxw+1
bvc +
eor #$80
+ bmi _lesseq
lda (c64.SCRATCH_ZPWORD1),y
sta _result_maxw
iny
lda (c64.SCRATCH_ZPWORD1),y
sta _result_maxw+1
dey
_lesseq dey
dey
cpy #254
bne _loop
lda _result_maxw
sta c64.ESTACK_LO,x
lda _result_maxw+1
sta c64.ESTACK_HI,x
dex
rts
_result_maxw .word 0
.pend
func_sum_b .proc
jsr pop_array_and_lengthmin1Y
lda #0
sta c64.ESTACK_LO,x
sta c64.ESTACK_HI,x
_loop lda (c64.SCRATCH_ZPWORD1),y
pha
clc
adc c64.ESTACK_LO,x
sta c64.ESTACK_LO,x
; sign extend the high byte
pla
and #$80
beq +
lda #$ff
+ adc c64.ESTACK_HI,x
sta c64.ESTACK_HI,x
dey
cpy #255
bne _loop
dex
rts
.pend
func_sum_ub .proc
jsr pop_array_and_lengthmin1Y
lda #0
sta c64.ESTACK_HI,x
- clc
adc (c64.SCRATCH_ZPWORD1),y
bcc +
inc c64.ESTACK_HI,x
+ dey
cpy #255
bne -
sta c64.ESTACK_LO,x
dex
rts
.pend
func_sum_uw .proc
jsr pop_array_and_lengthmin1Y
tya
asl a
tay
lda #0
sta c64.ESTACK_LO,x
sta c64.ESTACK_HI,x
- lda (c64.SCRATCH_ZPWORD1),y
iny
clc
adc c64.ESTACK_LO,x
sta c64.ESTACK_LO,x
lda (c64.SCRATCH_ZPWORD1),y
adc c64.ESTACK_HI,x
sta c64.ESTACK_HI,x
dey
dey
dey
cpy #254
bne -
dex
rts
.pend
func_sum_w .proc
jmp func_sum_uw
.pend
pop_array_and_lengthmin1Y .proc
inx
ldy c64.ESTACK_LO,x
dey ; length minus 1, for iteration
lda c64.ESTACK_LO+1,x
sta c64.SCRATCH_ZPWORD1
lda c64.ESTACK_HI+1,x
sta c64.SCRATCH_ZPWORD1+1
inx
rts
.pend
func_min_ub .proc
jsr pop_array_and_lengthmin1Y
lda #255
sta c64.SCRATCH_ZPB1
- lda (c64.SCRATCH_ZPWORD1),y
cmp c64.SCRATCH_ZPB1
bcs +
sta c64.SCRATCH_ZPB1
+ dey
cpy #255
bne -
lda c64.SCRATCH_ZPB1
sta c64.ESTACK_LO,x
dex
rts
.pend
func_min_b .proc
jsr pop_array_and_lengthmin1Y
lda #127
sta c64.SCRATCH_ZPB1
- lda (c64.SCRATCH_ZPWORD1),y
clc
sbc c64.SCRATCH_ZPB1
bvc +
eor #$80
+ bpl +
lda (c64.SCRATCH_ZPWORD1),y
sta c64.SCRATCH_ZPB1
+ dey
cpy #255
bne -
lda c64.SCRATCH_ZPB1
sta c64.ESTACK_LO,x
dex
rts
.pend
func_min_uw .proc
lda #$ff
sta _result_minuw
sta _result_minuw+1
jsr pop_array_and_lengthmin1Y
tya
asl a
tay
_loop
iny
lda (c64.SCRATCH_ZPWORD1),y
dey
cmp _result_minuw+1
bcc _less
bne _gtequ
lda (c64.SCRATCH_ZPWORD1),y
cmp _result_minuw
bcs _gtequ
_less lda (c64.SCRATCH_ZPWORD1),y
sta _result_minuw
iny
lda (c64.SCRATCH_ZPWORD1),y
sta _result_minuw+1
dey
_gtequ dey
dey
cpy #254
bne _loop
lda _result_minuw
sta c64.ESTACK_LO,x
lda _result_minuw+1
sta c64.ESTACK_HI,x
dex
rts
_result_minuw .word 0
.pend
func_min_w .proc
lda #$ff
sta _result_minw
lda #$7f
sta _result_minw+1
jsr pop_array_and_lengthmin1Y
tya
asl a
tay
_loop
lda (c64.SCRATCH_ZPWORD1),y
cmp _result_minw
iny
lda (c64.SCRATCH_ZPWORD1),y
dey
sbc _result_minw+1
bvc +
eor #$80
+ bpl _gtequ
lda (c64.SCRATCH_ZPWORD1),y
sta _result_minw
iny
lda (c64.SCRATCH_ZPWORD1),y
sta _result_minw+1
dey
_gtequ dey
dey
cpy #254
bne _loop
lda _result_minw
sta c64.ESTACK_LO,x
lda _result_minw+1
sta c64.ESTACK_HI,x
dex
rts
_result_minw .word 0
.pend
func_strlen .proc
; -- push length of 0-terminated string on stack
jsr peek_address
ldy #0
- lda (c64.SCRATCH_ZPWORD1),y
beq +
iny
bne -
+ tya
sta c64.ESTACK_LO+1,x
rts
.pend
func_rnd .proc
; -- put a random ubyte on the estack
jsr math.randbyte
sta c64.ESTACK_LO,x
dex
rts
.pend
func_rndw .proc
; -- put a random uword on the estack
jsr math.randword
sta c64.ESTACK_LO,x
tya
sta c64.ESTACK_HI,x
dex
rts
.pend
func_memcopy .proc
; note: clobbers A,Y
inx
stx c64.SCRATCH_ZPREGX
lda c64.ESTACK_LO+2,x
sta c64.SCRATCH_ZPWORD1
lda c64.ESTACK_HI+2,x
sta c64.SCRATCH_ZPWORD1+1
lda c64.ESTACK_LO+1,x
sta c64.SCRATCH_ZPWORD2
lda c64.ESTACK_HI+1,x
sta c64.SCRATCH_ZPWORD2+1
lda c64.ESTACK_LO,x
tax
ldy #0
- lda (c64.SCRATCH_ZPWORD1), y
sta (c64.SCRATCH_ZPWORD2), y
iny
dex
bne -
ldx c64.SCRATCH_ZPREGX
inx
inx
rts
.pend
func_memset .proc
; note: clobbers A,Y
inx
stx c64.SCRATCH_ZPREGX
lda c64.ESTACK_LO+2,x
sta c64.SCRATCH_ZPWORD1
lda c64.ESTACK_HI+2,x
sta c64.SCRATCH_ZPWORD1+1
lda c64.ESTACK_LO+1,x
sta c64.SCRATCH_ZPB1
ldy c64.ESTACK_HI+1,x
lda c64.ESTACK_LO,x
ldx c64.SCRATCH_ZPB1
jsr memset
ldx c64.SCRATCH_ZPREGX
inx
inx
rts
.pend
func_memsetw .proc
; note: clobbers A,Y
; -- fill memory from (SCRATCH_ZPWORD1) number of words in SCRATCH_ZPWORD2, with word value in AY.
inx
stx c64.SCRATCH_ZPREGX
lda c64.ESTACK_LO+2,x
sta c64.SCRATCH_ZPWORD1
lda c64.ESTACK_HI+2,x
sta c64.SCRATCH_ZPWORD1+1
lda c64.ESTACK_LO+1,x
sta c64.SCRATCH_ZPWORD2
lda c64.ESTACK_HI+1,x
sta c64.SCRATCH_ZPWORD2+1
lda c64.ESTACK_LO,x
ldy c64.ESTACK_HI,x
jsr memsetw
ldx c64.SCRATCH_ZPREGX
inx
inx
rts
.pend
memcopy16_up .proc
; -- copy memory UP from (SCRATCH_ZPWORD1) to (SCRATCH_ZPWORD2) of length X/Y (16-bit, X=lo, Y=hi)
; clobbers register A,X,Y
source = c64.SCRATCH_ZPWORD1
dest = c64.SCRATCH_ZPWORD2
length = c64.SCRATCH_ZPB1 ; (and SCRATCH_ZPREG)
stx length
sty length+1
ldx length ; move low byte of length into X
bne + ; jump to start if X > 0
dec length ; subtract 1 from length
+ ldy #0 ; set Y to 0
- lda (source),y ; set A to whatever (source) points to offset by Y
sta (dest),y ; move A to location pointed to by (dest) offset by Y
iny ; increment Y
bne + ; if Y<>0 then (rolled over) then still moving bytes
inc source+1 ; increment hi byte of source
inc dest+1 ; increment hi byte of dest
+ dex ; decrement X (lo byte counter)
bne - ; if X<>0 then move another byte
dec length ; we've moved 255 bytes, dec length
bpl - ; if length is still positive go back and move more
rts ; done
.pend
memset .proc
; -- fill memory from (SCRATCH_ZPWORD1), length XY, with value in A.
; clobbers X, Y
stx c64.SCRATCH_ZPB1
sty c64.SCRATCH_ZPREG
ldy #0
ldx c64.SCRATCH_ZPREG
beq _lastpage
_fullpage sta (c64.SCRATCH_ZPWORD1),y
iny
bne _fullpage
inc c64.SCRATCH_ZPWORD1+1 ; next page
dex
bne _fullpage
_lastpage ldy c64.SCRATCH_ZPB1
beq +
- dey
sta (c64.SCRATCH_ZPWORD1),y
bne -
+ rts
.pend
memsetw .proc
; -- fill memory from (SCRATCH_ZPWORD1) number of words in SCRATCH_ZPWORD2, with word value in AY.
; clobbers A, X, Y
sta _mod1+1 ; self-modify
sty _mod1b+1 ; self-modify
sta _mod2+1 ; self-modify
sty _mod2b+1 ; self-modify
ldx c64.SCRATCH_ZPWORD1
stx c64.SCRATCH_ZPB1
ldx c64.SCRATCH_ZPWORD1+1
inx
stx c64.SCRATCH_ZPREG ; second page
ldy #0
ldx c64.SCRATCH_ZPWORD2+1
beq _lastpage
_fullpage
_mod1 lda #0 ; self-modified
sta (c64.SCRATCH_ZPWORD1),y ; first page
sta (c64.SCRATCH_ZPB1),y ; second page
iny
_mod1b lda #0 ; self-modified
sta (c64.SCRATCH_ZPWORD1),y ; first page
sta (c64.SCRATCH_ZPB1),y ; second page
iny
bne _fullpage
inc c64.SCRATCH_ZPWORD1+1 ; next page pair
inc c64.SCRATCH_ZPWORD1+1 ; next page pair
inc c64.SCRATCH_ZPB1+1 ; next page pair
inc c64.SCRATCH_ZPB1+1 ; next page pair
dex
bne _fullpage
_lastpage ldx c64.SCRATCH_ZPWORD2
beq _done
ldy #0
-
_mod2 lda #0 ; self-modified
sta (c64.SCRATCH_ZPWORD1), y
inc c64.SCRATCH_ZPWORD1
bne _mod2b
inc c64.SCRATCH_ZPWORD1+1
_mod2b lda #0 ; self-modified
sta (c64.SCRATCH_ZPWORD1), y
inc c64.SCRATCH_ZPWORD1
bne +
inc c64.SCRATCH_ZPWORD1+1
+ dex
bne -
_done rts
.pend
sort_ub .proc
; 8bit unsigned sort
; sorting subroutine coded by mats rosengren (mats.rosengren@esa.int)
; input: address of array to sort in c64.SCRATCH_ZPWORD1, length in c64.SCRATCH_ZPB1
; first, put pointer BEFORE array
lda c64.SCRATCH_ZPWORD1
bne +
dec c64.SCRATCH_ZPWORD1+1
+ dec c64.SCRATCH_ZPWORD1
_sortloop ldy c64.SCRATCH_ZPB1 ;start of subroutine sort
lda (c64.SCRATCH_ZPWORD1),y ;last value in (what is left of) sequence to be sorted
sta c64.SCRATCH_ZPREG ;save value. will be over-written by largest number
jmp _l2
_l1 dey
beq _l3
lda (c64.SCRATCH_ZPWORD1),y
cmp c64.SCRATCH_ZPWORD2+1
bcc _l1
_l2 sty c64.SCRATCH_ZPWORD2 ;index of potentially largest value
sta c64.SCRATCH_ZPWORD2+1 ;potentially largest value
jmp _l1
_l3 ldy c64.SCRATCH_ZPB1 ;where the largest value shall be put
lda c64.SCRATCH_ZPWORD2+1 ;the largest value
sta (c64.SCRATCH_ZPWORD1),y ;put largest value in place
ldy c64.SCRATCH_ZPWORD2 ;index of free space
lda c64.SCRATCH_ZPREG ;the over-written value
sta (c64.SCRATCH_ZPWORD1),y ;put the over-written value in the free space
dec c64.SCRATCH_ZPB1 ;end of the shorter sequence still left
bne _sortloop ;start working with the shorter sequence
rts
.pend
sort_b .proc
; 8bit signed sort
; sorting subroutine coded by mats rosengren (mats.rosengren@esa.int)
; input: address of array to sort in c64.SCRATCH_ZPWORD1, length in c64.SCRATCH_ZPB1
; first, put pointer BEFORE array
lda c64.SCRATCH_ZPWORD1
bne +
dec c64.SCRATCH_ZPWORD1+1
+ dec c64.SCRATCH_ZPWORD1
_sortloop ldy c64.SCRATCH_ZPB1 ;start of subroutine sort
lda (c64.SCRATCH_ZPWORD1),y ;last value in (what is left of) sequence to be sorted
sta c64.SCRATCH_ZPREG ;save value. will be over-written by largest number
jmp _l2
_l1 dey
beq _l3
lda (c64.SCRATCH_ZPWORD1),y
cmp c64.SCRATCH_ZPWORD2+1
bmi _l1
_l2 sty c64.SCRATCH_ZPWORD2 ;index of potentially largest value
sta c64.SCRATCH_ZPWORD2+1 ;potentially largest value
jmp _l1
_l3 ldy c64.SCRATCH_ZPB1 ;where the largest value shall be put
lda c64.SCRATCH_ZPWORD2+1 ;the largest value
sta (c64.SCRATCH_ZPWORD1),y ;put largest value in place
ldy c64.SCRATCH_ZPWORD2 ;index of free space
lda c64.SCRATCH_ZPREG ;the over-written value
sta (c64.SCRATCH_ZPWORD1),y ;put the over-written value in the free space
dec c64.SCRATCH_ZPB1 ;end of the shorter sequence still left
bne _sortloop ;start working with the shorter sequence
rts
.pend
sort_uw .proc
; 16bit unsigned sort
; sorting subroutine coded by mats rosengren (mats.rosengren@esa.int)
; input: address of array to sort in c64.SCRATCH_ZPWORD1, length in c64.SCRATCH_ZPB1
; first: subtract 2 of the pointer
asl c64.SCRATCH_ZPB1 ; *2 because words
lda c64.SCRATCH_ZPWORD1
sec
sbc #2
sta c64.SCRATCH_ZPWORD1
bcs _sort_loop
dec c64.SCRATCH_ZPWORD1+1
_sort_loop ldy c64.SCRATCH_ZPB1 ;start of subroutine sort
lda (c64.SCRATCH_ZPWORD1),y ;last value in (what is left of) sequence to be sorted
sta _work3 ;save value. will be over-written by largest number
iny
lda (c64.SCRATCH_ZPWORD1),y
sta _work3+1
dey
jmp _l2
_l1 dey
dey
beq _l3
iny
lda (c64.SCRATCH_ZPWORD1),y
dey
cmp c64.SCRATCH_ZPWORD2+1
bne +
lda (c64.SCRATCH_ZPWORD1),y
cmp c64.SCRATCH_ZPWORD2
+ bcc _l1
_l2 sty _work1 ;index of potentially largest value
lda (c64.SCRATCH_ZPWORD1),y
sta c64.SCRATCH_ZPWORD2 ;potentially largest value
iny
lda (c64.SCRATCH_ZPWORD1),y
sta c64.SCRATCH_ZPWORD2+1
dey
jmp _l1
_l3 ldy c64.SCRATCH_ZPB1 ;where the largest value shall be put
lda c64.SCRATCH_ZPWORD2 ;the largest value
sta (c64.SCRATCH_ZPWORD1),y ;put largest value in place
iny
lda c64.SCRATCH_ZPWORD2+1
sta (c64.SCRATCH_ZPWORD1),y
ldy _work1 ;index of free space
lda _work3 ;the over-written value
sta (c64.SCRATCH_ZPWORD1),y ;put the over-written value in the free space
iny
lda _work3+1
sta (c64.SCRATCH_ZPWORD1),y
dey
dec c64.SCRATCH_ZPB1 ;end of the shorter sequence still left
dec c64.SCRATCH_ZPB1
bne _sort_loop ;start working with the shorter sequence
rts
_work1 .byte 0
_work3 .word 0
.pend
sort_w .proc
; 16bit signed sort
; sorting subroutine coded by mats rosengren (mats.rosengren@esa.int)
; input: address of array to sort in c64.SCRATCH_ZPWORD1, length in c64.SCRATCH_ZPB1
; first: subtract 2 of the pointer
asl c64.SCRATCH_ZPB1 ; *2 because words
lda c64.SCRATCH_ZPWORD1
sec
sbc #2
sta c64.SCRATCH_ZPWORD1
bcs _sort_loop
dec c64.SCRATCH_ZPWORD1+1
_sort_loop ldy c64.SCRATCH_ZPB1 ;start of subroutine sort
lda (c64.SCRATCH_ZPWORD1),y ;last value in (what is left of) sequence to be sorted
sta _work3 ;save value. will be over-written by largest number
iny
lda (c64.SCRATCH_ZPWORD1),y
sta _work3+1
dey
jmp _l2
_l1 dey
dey
beq _l3
lda (c64.SCRATCH_ZPWORD1),y
cmp c64.SCRATCH_ZPWORD2
iny
lda (c64.SCRATCH_ZPWORD1),y
dey
sbc c64.SCRATCH_ZPWORD2+1
bvc +
eor #$80
+ bmi _l1
_l2 sty _work1 ;index of potentially largest value
lda (c64.SCRATCH_ZPWORD1),y
sta c64.SCRATCH_ZPWORD2 ;potentially largest value
iny
lda (c64.SCRATCH_ZPWORD1),y
sta c64.SCRATCH_ZPWORD2+1
dey
jmp _l1
_l3 ldy c64.SCRATCH_ZPB1 ;where the largest value shall be put
lda c64.SCRATCH_ZPWORD2 ;the largest value
sta (c64.SCRATCH_ZPWORD1),y ;put largest value in place
iny
lda c64.SCRATCH_ZPWORD2+1
sta (c64.SCRATCH_ZPWORD1),y
ldy _work1 ;index of free space
lda _work3 ;the over-written value
sta (c64.SCRATCH_ZPWORD1),y ;put the over-written value in the free space
iny
lda _work3+1
sta (c64.SCRATCH_ZPWORD1),y
dey
dec c64.SCRATCH_ZPB1 ;end of the shorter sequence still left
dec c64.SCRATCH_ZPB1
bne _sort_loop ;start working with the shorter sequence
rts
_work1 .byte 0
_work3 .word 0
.pend
reverse_b .proc
; --- reverse an array of bytes (in-place)
; inputs: pointer to array in c64.SCRATCH_ZPWORD1, length in A
_left_index = c64.SCRATCH_ZPWORD2
_right_index = c64.SCRATCH_ZPWORD2+1
pha
sec
sbc #1
sta _left_index
lda #0
sta _right_index
pla
lsr a
tay
_loop sty c64.SCRATCH_ZPREG
ldy _left_index
lda (c64.SCRATCH_ZPWORD1),y
pha
ldy _right_index
lda (c64.SCRATCH_ZPWORD1),y
ldy _left_index
sta (c64.SCRATCH_ZPWORD1),y
pla
ldy _right_index
sta (c64.SCRATCH_ZPWORD1),y
inc _right_index
dec _left_index
ldy c64.SCRATCH_ZPREG
dey
bne _loop
rts
.pend
reverse_w .proc
; --- reverse an array of words (in-place)
; inputs: pointer to array in c64.SCRATCH_ZPWORD1, length in A
_left_index = c64.SCRATCH_ZPWORD2
_right_index = c64.SCRATCH_ZPWORD2+1
pha
asl a ; *2 because words
sec
sbc #2
sta _left_index
lda #0
sta _right_index
pla
lsr a
pha
tay
; first reverse the lsbs
_loop_lo sty c64.SCRATCH_ZPREG
ldy _left_index
lda (c64.SCRATCH_ZPWORD1),y
pha
ldy _right_index
lda (c64.SCRATCH_ZPWORD1),y
ldy _left_index
sta (c64.SCRATCH_ZPWORD1),y
pla
ldy _right_index
sta (c64.SCRATCH_ZPWORD1),y
inc _right_index
inc _right_index
dec _left_index
dec _left_index
ldy c64.SCRATCH_ZPREG
dey
bne _loop_lo
; now reverse the msbs
dec _right_index
inc _left_index
inc _left_index
inc _left_index
pla
tay
_loop_hi sty c64.SCRATCH_ZPREG
ldy _left_index
lda (c64.SCRATCH_ZPWORD1),y
pha
ldy _right_index
lda (c64.SCRATCH_ZPWORD1),y
ldy _left_index
sta (c64.SCRATCH_ZPWORD1),y
pla
ldy _right_index
sta (c64.SCRATCH_ZPWORD1),y
dec _right_index
dec _right_index
inc _left_index
inc _left_index
ldy c64.SCRATCH_ZPREG
dey
bne _loop_hi
rts
.pend