Skip to content

Instantly share code, notes, and snippets.

@BleuLlama
Created January 3, 2016 06:38
Show Gist options
  • Save BleuLlama/2428ed6683360b082c0f to your computer and use it in GitHub Desktop.
Save BleuLlama/2428ed6683360b082c0f to your computer and use it in GitHub Desktop.
ca65 V2.15 - Git b6f429f
Main file : llamacalc.asm
Current file: llamacalc.asm
000000r 1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
000000r 1 ; LlamaCalc - a programmer's calculator for KIM (1/Uno)
000000r 1 ;
000000r 1 ; 2016-01 Scott Lawrence
000000r 1 ;
000000r 1 ; Created for the RetroChallenge RC2016-1
000000r 1 ; Scott Lawrence - [email protected]
000000r 1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
000000r 1
000000r 1 .define VERSIONH #$00
000000r 1 .define VERSIONL #$01
000000r 1 ; v 0001 - 2016-01-01 - initial version, keypad input support
000000r 1
000000r 1
000000r 1 ; define the functionality we want to use in the library
000000r 1 UseVideoDisplay0 = 1 ; video display 0
000000r 1
000000r 1 ; include our functions
000000r 1 .include "KimDefs.asm"
000000r 2 ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
000000r 2 ; Kim OS defines
000000r 2
000000r 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
000000r 2 ; keypad
000000r 2
000000r 2 ; key presses
000000r 2 AK = $1EFE ; ROMFN: key down a=0, key up a<>0
000000r 2 GETKEY = $1F6A ; ROMFN: A>15 = bad key, otherwise, it's the key
000000r 2
000000r 2 ; key codes
000000r 2 .define KEY_NONE #$15
000000r 2 .define KEY_SPECIAL_MASK #$10
000000r 2 .define KEY_AD #$10
000000r 2 .define KEY_DA #$11
000000r 2 .define KEY_PC #$14
000000r 2 .define KEY_PL #$12
000000r 2
000000r 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
000000r 2 ; 7-seg display
000000r 2
000000r 2 SCANDS = $1F1F ; F9, FA, FB -> Display
000000r 2 POINTH = $FB
000000r 2 POINTL = $FA
000000r 2 INH = $F9
000000r 2
000000r 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
000000r 2 ; Serial TTY
000000r 2
000000r 2 GETCH = $1E5A ; ROMFN: Gets TTY char to A
000000r 2 OUTCH = $1EA0 ; ROMFN: Prints A as ASCII to TTY
000000r 2 OUTSP = $1E9E ; ROMFN: Prints ' ' to TTY
000000r 2 PRTBYT = $1E3B ; ROMFN: TTY Out A as 2 hex chars
000000r 2 PRTPNT = $1E1D ; ROMFN: Prints FB, FA to TTY
000000r 2
000000r 2
000000r 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
000000r 2 ; Video Display 0
000000r 2
000000r 2 RASTER = $4000 ; base of raster memory
000000r 2
000000r 2 ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
000000r 2
000000r 1 .include "KimLib.asm"
000000r 2 ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
000000r 2 ; KimLib
000000r 2 ; Standard use library functions
000000r 2 ;
000000r 2 ; 2015-12-29+
000000r 2 ; Scott Lawrence - [email protected]
000000r 2
000000r 2 ; include this after including "KimDefines.asm"
000000r 2 ; your code should start with the label "main"
000000r 2
000000r 2 ; defineables:
000000r 2 ; UseVideoDisplay0 - turn on Video Display framebuffer at $4000
000000r 2
000000r 2
000000r 2 ; for standard, we'll start at 0100.
000000r 2 .org $0100
000100 2
000100 2
000100 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
000100 2 ; entrypoint
000100 2 ; - this is where the code will start from
000100 2 ; - we have this jump to the user's 'main'
000100 2 entrypoint:
000100 2 4C 40 01 jmp main
000103 2
000103 2
000103 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
000103 2 ; end
000103 2 ; - jump here to end everything
000103 2 end:
000103 2 00 brk
000104 2
000104 2 .if .defined(UseVideoDisplay0)
000104 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
000104 2 ; cls
000104 2 ; - clear the screen
000104 2 ; - jsr cls - fills with black
000104 2 ; - jsr fillscr - fills with the color in (A & 0x0F)
000104 2 cls:
000104 2 A9 00 lda #$00 ; a = 7 ; color
000106 2
000106 2 fillscr:
000106 2 AA tax ; x = a (store it aside)
000107 2 A0 FF ldy #$FF ; y = 0
000109 2
000109 2 clsloop:
000109 2 C8 iny ; y++
00010A 2 8A txa ; restore color
00010B 2
00010B 2 ; we'll do this call 4 times for each 255 byte (0x0100) sections
00010B 2 ; we could do it once for each section, but it's a lot slower.
00010B 2 ; we can do it 8 times for each section, but it doubles the code
00010B 2 ; chunk, so we'll just go with this for now. whatever.
00010B 2 99 00 40 sta RASTER + $0000, y
00010E 2 99 40 40 sta RASTER + $0040, y
000111 2 99 80 40 sta RASTER + $0080, y
000114 2 99 C0 40 sta RASTER + $00C0, y
000117 2
000117 2 99 00 41 sta RASTER + $0100, y
00011A 2 99 40 41 sta RASTER + $0140, y
00011D 2 99 80 41 sta RASTER + $0180, y
000120 2 99 C0 41 sta RASTER + $01C0, y
000123 2
000123 2 99 00 42 sta RASTER + $0200, y
000126 2 99 40 42 sta RASTER + $0240, y
000129 2 99 80 42 sta RASTER + $0280, y
00012C 2 99 C0 42 sta RASTER + $02C0, y
00012F 2
00012F 2 99 00 43 sta RASTER + $0300, y
000132 2 99 40 43 sta RASTER + $0340, y
000135 2 99 80 43 sta RASTER + $0380, y
000138 2 99 C0 43 sta RASTER + $03C0, y
00013B 2
00013B 2 ; use $FF for single, $7F for double, $3F for quad
00013B 2 C0 3F cpy #$3F ; does y==(last)?
00013D 2 D0 CA bne clsloop ; nope, go again
00013F 2
00013F 2 60 rts
000140 2
000140 2 .endif ; UseVideoDisplay0
000140 2 ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
000140 2
000140 1
000140 1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
000140 1 ;; RAM used
000140 1 KEYBAK = $10
000140 1 SHIFTSCRATCH = $11
000140 1
000140 1
000140 1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
000140 1 ; main
000140 1 ; - the library entry point.
000140 1 main:
000140 1 .if .defined(UseVideoDisplay0)
000140 1 20 04 01 jsr cls ; clear the screen black
000143 1 .endif
000143 1 20 4F 01 jsr cls7seg
000146 1 20 5B 01 jsr displayVersion ; display the version number
000149 1 4C 6B 01 jmp keyinput ; press a key, get a color
00014C 1 20 03 01 jsr end ; end it
00014F 1
00014F 1
00014F 1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
00014F 1 cls7seg:
00014F 1 ; 1. clear the 7 segment display
00014F 1 A9 00 lda #$00
000151 1 85 FB sta POINTH ; left two digits
000153 1 85 FA sta POINTL ; middle two digits
000155 1 85 F9 sta INH ; right two digits
000157 1 20 1F 1F jsr SCANDS ; draw it to the display
00015A 1 60 rts
00015B 1
00015B 1 displayVersion:
00015B 1 A9 00 lda #$00
00015D 1 85 F9 sta INH ; right two digits
00015F 1
00015F 1 A9 00 lda VERSIONH
000161 1 85 FB sta POINTH ; v00
000163 1 A9 01 lda VERSIONL
000165 1 85 FA sta POINTL ; 01
000167 1
000167 1 20 1F 1F jsr SCANDS ; draw it to the display
00016A 1 60 rts
00016B 1
00016B 1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
00016B 1 keyinput:
00016B 1 ; check for key
00016B 1 20 6A 1F jsr GETKEY ; get a keypress
00016E 1 C9 15 cmp KEY_NONE ; $15 is "no press"
000170 1 F0 F9 beq keyinput ; then there's no press, check again
000172 1
000172 1 ; store aside a backup of the press
000172 1 85 10 sta KEYBAK ; KeyBak = a
000174 1
000174 1 ; check for AD/DA/PC/+ keys
000174 1 29 10 and KEY_SPECIAL_MASK
000176 1 C9 10 cmp KEY_SPECIAL_MASK
000178 1 D0 10 bne keyShiftIntoDisplay ; nope. regular key press
00017A 1
00017A 1 ; it's a control key!
00017A 1 handleControlKey:
00017A 1 A5 10 lda KEYBAK ; restore A
00017C 1 85 F9 sta INH ; just shove it to the display
00017E 1 A9 00 lda #$0 ; clear A
000180 1 85 FA sta POINTL ; short circuit
000182 1 85 FB sta POINTH
000184 1 20 1F 1F jsr SCANDS ; update display
000187 1 4C 6B 01 jmp keyinput ; repeat
00018A 1
00018A 1
00018A 1 ; handler for nibbles...
00018A 1 keyShiftIntoDisplay:
00018A 1 ; right byte
00018A 1 A5 10 lda KEYBAK ; A = Key pressed (A to be shifted in)
00018C 1
00018C 1 A6 F9 ldx INH ; X = INH
00018E 1 20 AC 01 jsr shifter ; shift around nibbles
000191 1 86 F9 stx INH ; store X back out
000193 1
000193 1 ; middle byte
000193 1 A6 FA ldx POINTL ; X from the byte
000195 1 20 AC 01 jsr shifter ; shift ecverything around
000198 1 86 FA stx POINTL ; store the modified X back out
00019A 1
00019A 1 ; left byte
00019A 1 A6 FB ldx POINTH ; X from the byte
00019C 1 20 AC 01 jsr shifter ; shift ecverything around
00019F 1 86 FB stx POINTH ; store the modified X back out
0001A1 1
0001A1 1 ; and finally display it to the screen
0001A1 1 20 1F 1F jsr SCANDS ; and display it to the screen
0001A4 1
0001A4 1
0001A4 1 .if .defined(UseVideoDisplay0)
0001A4 1 ; and display the color
0001A4 1 A5 10 lda KEYBAK
0001A6 1 20 06 01 jsr fillscr ; fill the screen
0001A9 1 .endif
0001A9 1
0001A9 1 4C 6B 01 jmp keyinput ; repeat...
0001AC 1
0001AC 1
0001AC 1 ; shifter
0001AC 1 ; roll A through X (for keypad->multibyte display use)
0001AC 1 ; eg: A=$0D X=$4C -> X=$CD A=$0C
0001AC 1 ; in: A - nibble to shift in from the right
0001AC 1 ; in: X - byte to work on
0001AC 1 ; mod: Y - scratch
0001AC 1 ; out: A - nibble shifted out
0001AC 1 shifter:
0001AC 1 ; 1. store aside A in Y
0001AC 1 29 0F and #$0F ; clean up A (just in case)
0001AE 1 85 11 sta SHIFTSCRATCH
0001B0 1 ; A = input byte / nib
0001B0 1 ; X = starting byte
0001B0 1 ; SHIFTSCRATCH = masked input nibble
0001B0 1
0001B0 1 ; 2. generate carry result, store on stack
0001B0 1 8A txa ; A = X
0001B1 1 4A lsr
0001B2 1 4A lsr
0001B3 1 4A lsr
0001B4 1 4A lsr ; A >>= 4 (shift nibble down)
0001B5 1 ;and #$0F ; A &= 0x0F (mask it) (unnecessary due to LSR)
0001B5 1 48 pha ; push A onto stack
0001B6 1
0001B6 1 ; A = carry nibble (junk now)
0001B6 1 ; X = starting byte
0001B6 1 ; SHIFTSCRATCH = masked input nibble
0001B6 1 ; stack = x >> 4 (carry nibble)
0001B6 1
0001B6 1 ; 3. shift nibble and apply new carry in
0001B6 1 8A txa ; A = X
0001B7 1 0A asl
0001B8 1 0A asl
0001B9 1 0A asl
0001BA 1 0A asl ; a <<=4 (shift nibble up)
0001BB 1 ;and #$F0 ; A &= 0xF0 (mask it) (unnecessary due to ASL)
0001BB 1 05 11 ora SHIFTSCRATCH ; A = A | SCRATCH ( shift in nibble)
0001BD 1 ; A = output byte (shifted nibbles)
0001BD 1 ; X = junk
0001BD 1 ; SHIFTSCRATCH = masked input nibble (junk now)
0001BD 1
0001BD 1 ; 4. Setup return values
0001BD 1 AA tax ; X = A
0001BE 1 68 pla ; pop A from stack (from 2.)
0001BF 1 ; X = output byte
0001BF 1 ; A = carry nibble
0001BF 1
0001BF 1 ; 5. and return
0001BF 1 60 rts ; return
0001BF 1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment