1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2025-08-09 20:25:17 +00:00
Files
kickc/src/test/ref/sinusgenscale8.asm

604 lines
9.9 KiB
NASM

.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
// PI*2 in u[4.12] format
.const PI2_u4f12 = $6488
// PI in u[4.12] format
.const PI_u4f12 = $3244
// PI/2 in u[4.12] format
.const PI_HALF_u4f12 = $1922
.label print_char_cursor = $f
.label print_line_cursor = 8
main: {
.label tabsize = $14
jsr print_cls
jsr sin8u_table
rts
sintab: .fill $14, 0
}
// Generate unsigned byte sinus table in a min-max range
// sintab - the table to generate into
// tabsize - the number of sinus points (the size of the table)
// min - the minimal value
// max - the maximal value
// sin8u_table(byte* zeropage(4) sintab)
sin8u_table: {
.const min = $a
.const max = $ff
.label amplitude = max-min
.const sum = min+max
.const mid = sum/2+1
.label step = $12
.label sinx = $11
.label sintab = 4
.label x = 2
.label i = 6
jsr div16u
lda #<$400
sta print_char_cursor
lda #>$400
sta print_char_cursor+1
lda #<str
sta print_str.str
lda #>str
sta print_str.str+1
jsr print_str
lda step
sta print_word.w
lda step+1
sta print_word.w+1
jsr print_word
lda #<str1
sta print_str.str
lda #>str1
sta print_str.str+1
jsr print_str
lda #min
sta print_byte.b
jsr print_byte
lda #<str2
sta print_str.str
lda #>str2
sta print_str.str+1
jsr print_str
lda #max
sta print_byte.b
jsr print_byte
lda #<str3
sta print_str.str
lda #>str3
sta print_str.str+1
jsr print_str
lda #amplitude
sta print_byte.b
jsr print_byte
lda #<str4
sta print_str.str
lda #>str4
sta print_str.str+1
jsr print_str
lda #mid
sta print_byte.b
jsr print_byte
lda #<$400
sta print_line_cursor
lda #>$400
sta print_line_cursor+1
jsr print_ln
lda #0
sta i
sta i+1
lda #<main.sintab
sta sintab
lda #>main.sintab
sta sintab+1
lda #0
sta x
sta x+1
// u[4.12]
b1:
lda x
sta sin8s.x
lda x+1
sta sin8s.x+1
jsr sin8s
sta sinx
tay
jsr mul8su
lda mul8su.m+1
tax
axs #-[mid]
txa
ldy #0
sta (sintab),y
inc sintab
bne !+
inc sintab+1
!:
lda print_line_cursor
sta print_char_cursor
lda print_line_cursor+1
sta print_char_cursor+1
lda #<str5
sta print_str.str
lda #>str5
sta print_str.str+1
jsr print_str
lda x
sta print_word.w
lda x+1
sta print_word.w+1
jsr print_word
lda #<str6
sta print_str.str
lda #>str6
sta print_str.str+1
jsr print_str
lda sinx
sta print_sbyte.b
jsr print_sbyte
lda #<str7
sta print_str.str
lda #>str7
sta print_str.str+1
jsr print_str
jsr print_sword
lda #<str8
sta print_str.str
lda #>str8
sta print_str.str+1
jsr print_str
stx print_byte.b
jsr print_byte
jsr print_ln
lda x
clc
adc step
sta x
lda x+1
adc step+1
sta x+1
inc i
bne !+
inc i+1
!:
lda i+1
cmp #>main.tabsize
bcs !b1+
jmp b1
!b1:
bne !+
lda i
cmp #<main.tabsize
bcs !b1+
jmp b1
!b1:
!:
rts
str: .text "step:@"
str1: .text " min:@"
str2: .text " max:@"
str3: .text " ampl:@"
str4: .text " mid:@"
str5: .text "x: @"
str6: .text " sin: @"
str7: .text " scaled: @"
str8: .text " trans: @"
}
// Print a newline
print_ln: {
b1:
lda #$28
clc
adc print_line_cursor
sta print_line_cursor
bcc !+
inc print_line_cursor+1
!:
lda print_line_cursor+1
cmp print_char_cursor+1
bcc b1
bne !+
lda print_line_cursor
cmp print_char_cursor
bcc b1
!:
rts
}
// Print a byte as HEX
// print_byte(byte zeropage($a) b)
print_byte: {
.label b = $a
lda b
lsr
lsr
lsr
lsr
tay
lda print_hextab,y
jsr print_char
lda #$f
and b
tay
lda print_hextab,y
jsr print_char
rts
}
// Print a single char
// print_char(byte register(A) ch)
print_char: {
ldy #0
sta (print_char_cursor),y
inc print_char_cursor
bne !+
inc print_char_cursor+1
!:
rts
}
// Print a zero-terminated string
// print_str(byte* zeropage($b) str)
print_str: {
.label str = $b
b1:
ldy #0
lda (str),y
cmp #'@'
bne b2
rts
b2:
ldy #0
lda (str),y
sta (print_char_cursor),y
inc print_char_cursor
bne !+
inc print_char_cursor+1
!:
inc str
bne !+
inc str+1
!:
jmp b1
}
// Print a signed word as HEX
// print_sword(signed word zeropage($d) w)
print_sword: {
.label w = $d
lda mul8su.m+1
bpl b1
lda #'-'
jsr print_char
sec
lda w
eor #$ff
adc #0
sta w
lda w+1
eor #$ff
adc #0
sta w+1
b1:
lda w
sta print_word.w
lda w+1
sta print_word.w+1
jsr print_word
rts
}
// Print a word as HEX
// print_word(word zeropage($b) w)
print_word: {
.label w = $b
lda w+1
sta print_byte.b
jsr print_byte
lda w
sta print_byte.b
jsr print_byte
rts
}
// Print a signed byte as HEX
// print_sbyte(signed byte zeropage($a) b)
print_sbyte: {
.label b = $a
lda b
bmi b1
lda #' '
jsr print_char
b2:
jsr print_byte
rts
b1:
lda #'-'
jsr print_char
lda b
eor #$ff
clc
adc #1
sta b
jmp b2
}
// Multiply a signed byte and an unsigned byte (into a signed word)
// Fixes offsets introduced by using unsigned multiplication
// mul8su(signed byte register(Y) a)
mul8su: {
.const b = sin8u_table.amplitude+1
.label m = $d
tya
tax
lda #b
sta mul8u.mb
lda #0
sta mul8u.mb+1
jsr mul8u
cpy #0
bpl b1
lda m+1
sec
sbc #b
sta m+1
b1:
rts
}
// Perform binary multiplication of two unsigned 8-bit bytes into a 16-bit unsigned word
// mul8u(byte register(X) a, byte register(A) b)
mul8u: {
.label mb = $b
.label res = $d
.label return = $d
lda #0
sta res
sta res+1
b1:
cpx #0
bne b2
rts
b2:
txa
and #1
cmp #0
beq b3
lda res
clc
adc mb
sta res
lda res+1
adc mb+1
sta res+1
b3:
txa
lsr
tax
asl mb
rol mb+1
jmp b1
}
// Calculate signed byte sinus sin(x)
// x: unsigned word input u[4.12] in the interval $0000 - PI2_u4f12
// result: signed byte sin(x) s[0.7] - using the full range -$7f - $7f
// sin8s(word zeropage($b) x)
sin8s: {
// u[2.6] x^3
.const DIV_6 = $2b
.label _4 = $b
.label x = $b
.label x1 = $14
.label x3 = $15
.label usinx = $16
.label isUpper = $a
lda x+1
cmp #>PI_u4f12
bcc b5
bne !+
lda x
cmp #<PI_u4f12
bcc b5
!:
lda x
sec
sbc #<PI_u4f12
sta x
lda x+1
sbc #>PI_u4f12
sta x+1
lda #1
sta isUpper
jmp b1
b5:
lda #0
sta isUpper
b1:
lda x+1
cmp #>PI_HALF_u4f12
bcc b2
bne !+
lda x
cmp #<PI_HALF_u4f12
bcc b2
!:
sec
lda #<PI_u4f12
sbc x
sta x
lda #>PI_u4f12
sbc x+1
sta x+1
b2:
asl _4
rol _4+1
asl _4
rol _4+1
asl _4
rol _4+1
lda _4+1
sta x1
tax
tay
lda #0
sta mulu8_sel.select
jsr mulu8_sel
tax
ldy x1
lda #1
sta mulu8_sel.select
jsr mulu8_sel
sta x3
tax
lda #1
sta mulu8_sel.select
ldy #DIV_6
jsr mulu8_sel
eor #$ff
sec
adc x1
sta usinx
ldx x3
ldy x1
lda #0
sta mulu8_sel.select
jsr mulu8_sel
tax
ldy x1
lda #0
sta mulu8_sel.select
jsr mulu8_sel
lsr
lsr
lsr
lsr
clc
adc usinx
tax
cpx #$80
bcc b3
dex
b3:
lda isUpper
cmp #0
beq b14
txa
eor #$ff
clc
adc #1
rts
b14:
txa
rts
}
// Calculate val*val for two unsigned byte values - the result is 8 selected bits of the 16-bit result.
// The select parameter indicates how many of the highest bits of the 16-bit result to skip
// mulu8_sel(byte register(X) v1, byte register(Y) v2, byte zeropage($11) select)
mulu8_sel: {
.label _0 = $d
.label _1 = $d
.label select = $11
tya
sta mul8u.mb
lda #0
sta mul8u.mb+1
jsr mul8u
ldy select
beq !e+
!:
asl _1
rol _1+1
dey
bne !-
!e:
lda _1+1
rts
}
// Performs division on two 16 bit unsigned words
// Returns the quotient dividend/divisor.
// The remainder will be set into the global variable rem16u
// Implemented using simple binary division
div16u: {
.label return = $12
jsr divr16u
rts
}
// Performs division on two 16 bit unsigned words and an initial remainder
// Returns the quotient dividend/divisor.
// The final remainder will be set into the global variable rem16u
// Implemented using simple binary division
// divr16u(word zeropage(4) dividend, word zeropage(2) rem)
divr16u: {
.label rem = 2
.label dividend = 4
.label quotient = $12
.label return = $12
ldx #0
txa
sta quotient
sta quotient+1
lda #<PI2_u4f12
sta dividend
lda #>PI2_u4f12
sta dividend+1
txa
sta rem
sta rem+1
b1:
asl rem
rol rem+1
lda dividend+1
and #$80
cmp #0
beq b2
lda #1
ora rem
sta rem
b2:
asl dividend
rol dividend+1
asl quotient
rol quotient+1
lda rem+1
cmp #>main.tabsize
bcc b3
bne !+
lda rem
cmp #<main.tabsize
bcc b3
!:
inc quotient
bne !+
inc quotient+1
!:
lda rem
sec
sbc #<main.tabsize
sta rem
lda rem+1
sbc #>main.tabsize
sta rem+1
b3:
inx
cpx #$10
bne b1
rts
}
// Clear the screen. Also resets current line/char cursor.
print_cls: {
.label sc = 2
lda #<$400
sta sc
lda #>$400
sta sc+1
b1:
lda #' '
ldy #0
sta (sc),y
inc sc
bne !+
inc sc+1
!:
lda sc+1
cmp #>$400+$3e8
bne b1
lda sc
cmp #<$400+$3e8
bne b1
rts
}
print_hextab: .text "0123456789abcdef"