# CodeWalrus

## Development => Calculators => Calc Projects, Programming & Tutorials => Topic started by: _iPhoenix_ on July 09, 2018, 12:16:43 am

Title: _iPhoenix_ tries to do Assembly things.
Post by: _iPhoenix_ on July 09, 2018, 12:16:43 am

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 and PT_ helped me a bit with this one (Mateo helped me realize that the stack exists, and PT_ helped inspire the drawing code).

`.nolist#include "ti84pce.inc".list  .org UserMem-2  .db tExtTok, tAsm84CeCmp    call _boot_ClearVRAM  call _RunIndicOff  ld de, \$0050; de holds x coord  ld c, \$50; y coord stored in cmainLoop:  ld a, 1 ; draw  call draw  call keyWait  push af ; dammit I love this trick.    ld a, 0 ; erase    call draw  pop af  call move  ld a, b; if b is zero, we stop.  or a, a  jr z, quit ; relative jump is shorter, byte-wise  jr mainLoopquit:  call _RunIndicOn  ret  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 others have made :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 ; save c onto the stack (as part of bc)    ld b, 160d    mlt bc ; this messes with c    push bc ; thanks, Mateo    pop hl    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    inc hl    or a, a    jr z, _erase_draw: ; label not needed, included for legibility.    ld (hl), \$00 ; byte 2    jr _end_erase:    ld (hl), \$ff ; byte 2_end:  pop bc ; restore bc (particularly c)  ret  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)  ret nz ; if a is not zero, return  jr keyWait ; otherwise jump (relative jump saves bytes, according to my highly scientific testing)move: ; 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)   ld b, 1 ; we will set b to 0 if we want to quitchk_Quit: ; label not used, but it increases legibility and does not harm anything (imho)  cp skDel  jp nz, chk_Down  ld b, 0 ; we want to quit  retchk_Down:  cp skDown  jp nz, chk_Left  inc c  retchk_Left:  cp skLeft  jp nz, chk_Right  dec de  retchk_Right:  cp skRight  jp nz, chk_Up  inc de  retchk_Up:  cp skUp  ret nz  dec c  ret`

As you can probably tell, it's as optimized as I can get it, which is to say not very optimized. I realize these things come with time. [size=0]When will the Dunning-Kruger effect kick in? I like feeling competent...[/size] 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. :)

Tips are always welcome.
Title: Re: _iPhoenix_ tries to do Assembly things.
Post by: mazhat on July 10, 2018, 04:11:04 am
I am glad you are pursuing Assembly!
I finished only one program, but I just don't know about
all the hacks, and tricks of the hardware to be even close to decent.
It's a real challenge for smarty pants, such as yourself.

I looked through my old files and found it,
also I know that the beginning isn't optimised,
but I didn't really feel like doing it lol.

`;Low Quality Bootleg Sprite Routine;Created By Matt C./ Mazhat;.NOLIST#define   EQU   .equ#define   equ   .equ#define   END   .end#define   end   .end#include "ti83plus.inc"#include "mirage.inc".LIST     .org \$9d93 ;Origin (set back two to account for AsmPrgm) .db \$BB,\$6D ;Compiled AsmPrgm token ret ;So TIOS wont run the program .db 1 ;Identifier as MirageOS program .db %00000000,%00000000 ;15x15 button .db %00000000,%00000000 .db %00000000,%00000000 .db %00000000,%00000000 .db %00000000,%00000000 .db %00000000,%00000000 .db %00000000,%00000000 .db %00000000,%00000000 .db %00000000,%00000000 .db %00000000,%00000000 .db %00000000,%00000000 .db %00000000,%00000000 .db %00000000,%00000000 .db %00000000,%00000000 .db %00000000,%00000000 .db "Made by Matt C",0 ;Zero terminated description ;Program code starts here ;Reset the variables and such ld a, 0 ld (posY), a ;Set posY ld a, 0 ld (posX), a ;Set posX ld a, \$00 ld (animCounter), a animation:; ;Yes, I know this part is REALLY bad, ;BUT BOY AM I DONE WITH THIS PROGRAM. call drawSprite ld a, 0 ld (posX), a call drawSprite ld a, 1 ld (posX), a call drawSprite ld a, 2 ld (posX), a call drawSprite ld a, 3 ld (posX), a call drawSprite ld a, 4 ld (posX), a call drawSprite ld a, 5 ld (posX), a call drawSprite ld a, 6 ld (posX), a call drawSprite ld a, 7 ld (posX), a call drawSprite ld a, 0 ld (posY), a call drawSprite ld a, 1 ld (posY), a call drawSprite ld a, 2 ld (posY), a call drawSprite ld a, 3 ld (posY), a call drawSprite ld a, 4 ld (posY), a call drawSprite ld a, 5 ld (posY), a call drawSprite ld a, 6 ld (posY), a call drawSprite ld a, 7 ld (posY), a call drawSprite call drawSprite ld a, 7 ld (posX), a call drawSprite ld a, 6 ld (posX), a call drawSprite ld a, 5 ld (posX), a call drawSprite ld a, 4 ld (posX), a call drawSprite ld a, 3 ld (posX), a call drawSprite ld a, 2 ld (posX), a call drawSprite ld a, 1 ld (posX), a call drawSprite ld a, 0 ld (posX), a call drawSprite ld a, 7 ld (posY), a call drawSprite ld a, 6 ld (posY), a call drawSprite ld a, 5 ld (posY), a call drawSprite ld a, 4 ld (posY), a call drawSprite ld a, 3 ld (posY), a call drawSprite ld a, 2 ld (posY), a call drawSprite ld a, 1 ld (posY), a call drawSprite ld a, 0 ld (posY), a call drawSprite ld a, (animCounter) ;Put counter into a inc a ;increase a ld (animCounter), a ;therefore increase counter cp 5 ;animate five times jp nz, animation ld hl, textHello b_call(_HomeUp) ;(CurCol) = 0, (CurRow) = 0. b_call(_putS) ;Display String in HL retanimCounter: .db \$00textHello: .db "MADE IN ASM",0DrawSprite: ld ix, sprite ;Put sprite address into ix ;ld hl, plotsscreen ;First part of buffer ld hl, 0 ;empty out the hl register ld de, (posY) ;Get the Y position ;Check for Vertical Clipping (UP) ld a, (posY) ld c, \$08 ;Else set the counter to 8 or a ;cp 0 jp m, clipUp ;If y-pos is negative add hl, de ;mutliply Y by 12 add hl, de add hl, de add hl, hl add hl, hl ld bc, plotsscreen add hl, bc ;Check for Vertical Clipping (down) ld a, (posY) ;Get the Y Position cp 56 jp p, clipDown ;If the sprite goes off screen ld c, \$08 ;Else set the counter to 8 ;Finding the byte on the buffer where the sprite is ld a, (posX) ;X-Position ld de, 0 ;Empty debufByte: cp 8 ;Check if less than 8 jp m, addOffsetX ;If Negative Return value (Return back) sub 8 ;Take away 8 from 'a' register inc de ;X Offset increase jp bufByte ;Else repeataddOffsetX: add hl, de ;Add the x-offset to hlshiftRight: ;We are bitshifting the sprite according to x, really ld a, (posX) ;First lets see if it goes over the right side of the screen or a ;Check if it goes over the screen jp m, spriteLoop ;Skip if it does (If negative) ld b, (ix) ;put sprite into b ld a, (posX) ;put x-pos into a ld de, 0 ;x-offset: set to zero jp mod ;Get how many bitshifts we need (put into 'a' register) ;(For Previous Line: If it doesn't straddle on two bytes, skips to spriteLoop)sr1: ;ld (LSD), a ;Get the amount we bitshifted by and put it into c for later use by shiftLeft srl b ;Bitshift sprite right dec a ;Decrease counter or a ;cp 0 jp nz, sr1 ;If we're not done the shifting ld (hl), b ;load sprite image into screen when finished shiftingshiftLeft: ;The byte we need to shift left (The second byte) ld a, (posX) ;First lets see if it goes over the right side of the screen cp 88 ;Check if it goes over the screen jp p, spriteLoop ;Skip if it does ld b, (ix) ;Put the sprite into b inc hl ;X-Offset byte on buffer + 1 ld a, 8 ;Let's get the bytes we need to shift left using the number we used to shift right sub e ;Get the left shift value (It will be negative) ;ld e, (LSD) ;sub e ;8-(# that we shifted right by) = How many left shifts we need for this bytesl1: sla b ;Bitshift sprite left dec a ;Dec counter or a ;cp 0 jp nz, sl1 ld (hl), b ;load sprite image into screen dec hl jp spriteLoopdrawToBuffer: ld (hl), b ;load sprite image into screenspriteLoop: ;ld (hl), b ;load sprite image into screen dec c ;dec counter ld a, c ;load counter into a inc ix ;next sprite byte ld de, 12 add hl, de ;next 'y' position on screen cp \$01 ;loop x8 jp p, shiftRight ;Drain the grain in the counter b_call(_grBufCpy) b_call(_grBufClr) retclipDown: sub 64 ;Take away 64 from Y-POS (register a) NEG ;NEGATE IT ld c, a ;Put that number into the counter for drawing sprites jp shiftRightclipUp: ld de, plotsscreen ;Get the plotSScreen add hl, de ;Put plotSScreen into hl NEG ;Negate 'a' to get a positive valueCLUP: dec a ;Counter: The amount of bytes that need to be skipped dec c ;Remainer bytes to draw inc ix ;Skip the byte or a jp nz, CLUP ;Keep skipping until we have the bytes we need to draw jp shiftRightmod: ld e, a ;Get the amount we bitshifted by and put it into ** for later use by shiftLeft cp 8 ;Check if The number is already a mutliple of eight (no need for bitshift) jp z, drawToBuffer ;If zero just draw it without bit shifting anything or a ;Due to technicality, 0 is not a multiple of 8 jp z, drawToBuffer ;So just do the same thing cp 8 jp m, sr1 ;If Negative Return value (Return back) sub 8 ;Take away 8 from 'a' register jp mod ;Else repeat;LSD:;leftShiftData: .db \$00sprite: .db %01111110 .db %10000001 .db %10100101 .db %10000001 .db %10100101 .db %10011001 .db %10000001 .db %01111110posX: .db 0posY: .db 0 end`
Title: Re: _iPhoenix_ tries to do Assembly things.
Post by: _iPhoenix_ on July 12, 2018, 10:32:20 pm
A lot of fun progress has happened since that first post! I've decided on a very simple game where you (a square) walk around a screen collecting coins (also squares).

(https://i.imgur.com/xLGE9x0.gif)

Features:

• Slow!
• Large!
• Unoriginal!
• Nut-free!
• Low-quality graphics!
• Documentation not included!
• 80% All-natural!
• Not a scam!

This game is clearly the pinnacle of ez80 programming and should be worshipped as such.
Title: Re: _iPhoenix_ tries to do Assembly things.
Post by: Caleb Hansberry on July 15, 2018, 11:49:06 pm
I'm also happy you're working on ez80 assembly. It's absolutely a worthwhile endeavor!