Alright, so I've taken up learning Assembly, now that I am more comfortable with middle-to-lower level languages like C and C++, and I've progressed to the stage that I can start to write crappy programs now.
Here's my first actual assembly program. It's pretty bad. You can move a pixel around with the arrow keys. Mateo, PT_, and Runer. helped me a bit with this one (Mateo helped me realize that the stack exists, and PT_ helped inspire the drawing code. PT_, in his 'P_T' form, and Runer showed mesome a lot of useful optimization tips and made me realize how many simple optimizations could have been done.)
Code:
As you can probably tell, it's as optimized as I can get it, which is to say not very optimized. It's optimized (I think? I'm obviously not a good judge of these things. Yet.), not obfuscated. I realize these things come with time. When will the Dunning-Kruger effect kick in? I like feeling mildly competent... I'm trying to keep my code optimized and readable so I can look back on it later.
My current assembly setup is SC3 and the Project Builder. This is a temporary setup, and I'm switching to better tools soon.
Here's my first actual assembly program. It's pretty bad. You can move a pixel around with the arrow keys. Mateo, PT_, and Runer. helped me a bit with this one (Mateo helped me realize that the stack exists, and PT_ helped inspire the drawing code. PT_, in his 'P_T' form, and Runer showed me
Code:
.nolist
#include "ti84pce.inc"
.list
.org UserMem-2
.db tExtTok, tAsm84CeCmp
call _RunIndicOff
call _boot_ClearVRAM
ld de, lcdWidth/2; de holds x coord
ld c, lcdHeight/2; y coord stored in c
mainLoop:
; constrain de and c so they are always on the screen.
ld a, c
cp 240d ; remember: it is 0-indexed, so we check if a < 240 (if a = 240 it is out of bounds)
jr c, chk_de
ld c, lcdHeight - 1
chk_de:
ld a, e
push de
ex de, hl
ld de, $ffffff - lcdWidth + 1 ; if de is >= lcdWidth it will overflow.
adc hl, de
pop de
jr nc, cont
ld de, lcdWidth - 1
cont:
xor a, a ; draw
call draw
keyWait: ; waits for a key, keycode returned in a
call _GetCSC ; get key codes
or a, a; check scan codes by comparing a with itself (I got this "hack" from various routines, it is super clever)
jr z, keyWait ; if a is not zero, we are done
keyEnd:
ld b, a
ld a, $ff ; erase
call draw
; Movement code.
; input in a (getCSC code)
; moves the pixel by updating
; de (x coord) and c (y coord)
; nothing overly arcane happens
; I used to check if a was >= 5 or equal to skDel
; but my code caused bugs so I killed it (and the bugs)
chk_down:
djnz chk_left
inc c
jr mainLoop
chk_left:
djnz chk_right
dec de
; this is my crappy routine to check if de overflowed.
; it just works. Ew.
ex de, hl ; hl is now de
ld de, $ffffff ; de is saved in hl
adc hl, de ; logic explained below
ex de, hl ; de is now hl
jr c, mainLoop
inc de
jr mainLoop
; I feel clever writing the above few lines of code,
; but please burst my ego if you have a better one.
chk_right:
djnz chk_up
inc de
jr mainLoop
chk_up:
djnz chk_quit
ld a, c
adc a, $ff; (n + $ff) % $100 + ((n + $ff)>$100) = n-1 (n!=0)
ld c, a
jr c, mainLoop
inc c
jr mainLoop
chk_quit:
ld a, b
cp skDel - 4
jr nz, mainLoop
call _RunIndicOn
ret ; quit
draw: ; draws our singular pixel (I set high goals)
; (whew this is a bit of work, it gave me lots of appreciation for the sprite routines :P)
; we are using 16bpp mode here, so my routines
; (which are gently modified 8bpp routines) can
; probably be optimized
; takes input in a: 1 = draw the pixel, 0 = erase
push bc
ld l, c
ld h, lcdWidth/2
mlt hl ; this messes with c
add hl, hl ; hl * 2
add hl, hl ; hl * 4 (2 bytes/pixel)
add hl, de
add hl, de ; hl += de * 2
ld bc, vRAM ; this also messes with c
add hl, bc
ld (hl), $ff ; byte 1, color info
inc hl
ld (hl), a ; byte 2, color info stored in a
pop bc
ret
My current assembly setup is SC3 and the Project Builder. This is a temporary setup, and I'm switching to better tools soon.