2

I made this code to move a pixel around in the screen area using the arrow keys and the enter button to stop the program. It does seem to work better with all the suggestions so far, but its placement of the pixel is messed up.

#include    "ti83plus.inc"
.org $9D95
  ld a,$2D ;9D95,9D96
  ld ($9872),a ;9D98,9D99,9D9A
  ld a,$1F ;9D97,9D98
  ld ($9873),a ;9D9B,9D9C,9D9D
  jp main
main:
  call clrScreen
  bcall(_getKey)
  ld ($987D),a
  cp $03
  call z,decY
  ld a,($987D)
  cp $04
  call z,incY
  ld a,($987D)
  cp $01
  call z,incX
  ld a,($987D)
  cp $02
  call z,decX
  ld a,($987D)
  cp $05
  ret z
  call dot
  call BTN ;byte to 9874 and 9875
  ld hl,($9874)
  ld (hl),e
  bcall(_GrBufCpy)
  jp main
BTN:
  call BTM
  ld b, 0
  ld a, ($9873);a=y
  ld c,a;c=y
  sll c;leftshift with a 1 added
  rl b;leftshift for 0?
  sll c
  rl b
  sll c
  rl b
  ld h, 0
  ld a, ($9872);a=x
  ld l,a;l=a
  srl l; l/8
  srl l
  srl l
  add hl, bc
  ld bc, $9340
  add hl, bc
  ld ($9874), hl
  ret
srt:
  call HTBC
  djnz srt
  ret
BTM:
  dec l
  ld a,l
  cp $00
  ld e,$80
  ret z
  dec l
  ld a,l
  cp $00
  ld e,$40
  ret z
  dec l
  ld a,l
  cp $00
  ld e,$20
  ret z
  dec l
  ld a,l
  cp $00
  ld e,$10
  ret z
  dec l
  ld a,l
  cp $00
  ld e,$08
  ret z
  dec l
  ld a,l
  cp $00
  ld e,$04
  ret z
  dec l
  ld a,l
  cp $00
  ld e,$02
  ret z
  dec l
  ld a,l
  cp $00
  ld e,$01
  ret z
  jp BTM
HTBC:
  inc bc
  inc bc
  inc bc
  inc bc
  inc bc
  inc bc
  inc bc
  inc bc
  inc bc
  inc bc
  inc bc
  inc bc
  inc bc
  inc bc
  inc bc
  inc bc
  inc bc
  inc bc
  inc bc
  inc bc
  inc bc
  inc bc
  inc bc
  inc bc
  inc bc
  inc bc
  inc bc
  inc bc
  inc bc
  inc bc
  inc bc
  inc bc
  ret
dot:
  ld hl,$0000
  ld a,($9873)
  ld b,a
  cp $00
  ld a,($9872)
  ld l,a
  ret z
  inc b
  call mult
  ret
mult:
  inc hl
  inc hl
  inc hl
  inc hl
  inc hl
  inc hl
  inc hl
  inc hl
  inc hl
  inc hl
  inc hl
  inc hl
  djnz mult
  ret
incX:
  ld a,($9872)
  inc a
  cp $95
  ret z
  ld ($9872),a
  ret
decX:
  ld a,($9872)
  dec a
  cp $FF
  ret z
  ld ($9872),a
  ret
incY:
  ld a,($9873)
  inc a
  cp $63
  ret z
  ld ($9873),a
  ret
decY:
  ld a,($9873)
  dec a
  cp $FF
  ret z
  ld ($9873),a
  ret
clrScreen:
  ld hl,$9340
  ld b,$00
  call clrloop
  ld hl,$9343
  call clrloop
  call clrloop
  call clrloop
  ret
clrloop:
  inc hl
  ld (hl),$00
  djnz clrloop
  ret

it's easiest for me if you say which code block needs to be replaced and with what.

pi_squared
  • 91
  • 6

2 Answers2

0

This:

cp $03
call nz,decY

... says to call decY if a has absolutely any value other then 3. In context, it looks like you probably want call z — call exactly when a has value 3. With the same observation repeating for all your other flag enquiries following a cp.

EDIT: So I think the calling process for placing a pixel is:

Call dot. That loads hl with the target address calculated as:

hl = ($9872) + ($9873) * 12

So given that ($9872) stores your x coordinate and ($9873) stores your y, that calculates a target offset within a framebuffer assuming 12 bytes per line. Wikipedia says the device is 96 pixels per line so that sounds reasonable.

Call BTN. That loads bc with $9340, the address of your framebuffer but then throws b away in favour of h. So net effect is:

($9874) = bc = hl + h*32

A call is made to BTM which picks a byte mask and puts it into e. I think you could simplify that with a looped shift or a lookup but whatever. I didn't seriously inspect it; provided e is not zero you should see some output.

You then store e to ($9874).

Assuming everything else is correct, including the buffer copy, I think possibly BTN is at fault. Probably what you actually want to do is:

hl = (($9872) / 8) + ($9873) * 12
$9874 = hl + $9340
($9874) = e

So, divide the input x by eight because there are eight pixels per byte. Then just add the start of your frame buffer. E.g. (extemporaneously, untested):

ld b, 0
ld c, ($9873)
sll c
rl b
sll c
rl b
sll c
rl b

ld h, 0
ld l, ($9872)
srl l
srl l
srl l

add hl, bc
ld bc, $9340
add hl, bc
ld ($9874), hl

I'm not immediately sure of what BTN is intended to do. dot nearly calculates the output address (subject to not having divided x by 8), an BTM picks a bit mask but BTN seems just to destroy your address.

It's possibly I'm suffering a failure of comprehension, of course.

Tommy
  • 99,986
  • 12
  • 185
  • 204
  • I'm pulling the whole thing apart now, albeit slowly because I'm also at work. One other quick note: both `incY` and `decY` store their result to the wrong address. So they increment or decrement the current y but then store the result to x. – Tommy Apr 18 '16 at 14:49
  • I implemented some of the suggestions and now a pixel appears and moves, though incorrectly. I updated the code on the post. – pi_squared Apr 20 '16 at 01:41
  • Cool, progress! Apologies but it's very late here; I'll have a fresh look tomorrow unless Zeda or somebody else has beaten me to a complete answer in the meantime. – Tommy Apr 20 '16 at 02:50
0

There are several issues that I see with your code, including that you 'call main' which when finished, continues into 'main'. Sometimes this is a handy trick, but not in this case. You have four options with the most efficient being to simply remove the call. Or you can place an 'ret' after, or use 'jp main' or 'jr main'.

#include    "ti83plus.inc"
.org $9D95
  ld a,$2D ;9D95,9D96
  ld ($9872),a ;9D98,9D99,9D9A
  ld a,$1F ;9D97,9D98
  ld ($9873),a ;9D9B,9D9C,9D9D
;  call main

The next issue as pointed out by another comment, is that you are using 'call nz,' when you want 'call z,'

main:
  call clrScreen
  bcall(_getKey)
  ld ($987D),a
  cp $03
  call z,decY
  ld a,($987D)
  cp $04
  call z,incY
  ld a,($987D)
  cp $01
  call z,incX
  ld a,($987D)
  cp $02
  call z,decX

Finally, as far as I can tell, you never actually plot a pixel. I think that if I give you a pixel plotting routine, you have all the info you need to finish your code. If you want the whole routine the way I would do it, just let me know.

pxlInv:
;b=x, c=y
    call getPixelLoc
    xor (hl)
    ld (hl),a
    ret
pxlOn:
;b=x, c=y
    call getPixelLoc
    or (hl)
    ld (hl),a
    ret
pxlOff:
;b=x, c=y
    call getPixelLoc
    cpl
    and (hl)
    ld (hl),a
    ret
pxlTst:
;b=x, c=y
;returns z flag if pixel is off, nz if on.
    getPixelLoc
    and (hl)
    ret
getPixelLoc:
;b=x, c=y
    ld a,c  ; |Make sure the Y coordinate is in bounds
    cp 64   ; |
    ret nc  ;/
    ld a,b  ; |Make sure the X coordinate is in bounds while saving 'x' in A
    cp 96   ; |
    ret nc  ;/
    ld b,0      ;\
    ld h,b      ; |
    ld l,c      ; |
    add hl,hl   ; |Multiply C (the y-coordinate) by 12
    add hl,hl   ; |
    add hl,bc   ; |
    add hl,hl   ;/
    ld c,a      ; |
    srl c       ; |Divide the X coordinate by 2, three times (so ne effect of divide by 8
    srl c       ; |
    srl c       ;/
    add hl,bc   ;Add this to our offset
    ld hl,plotSScreen
    add hl,bc
    and 7       ; |get our pixel mask for the byte
    ld b,a      ; |
    ld a,80h    ; |
    ret z       ; |
    rrca        ; |
    djnz $-1    ;/
    ret
Zeda
  • 382
  • 4
  • 13
  • I'm pretty sure BTN calculates the address to store the pixel to in `$9874`, BTM calculates the value that will represent a pixel on a 1bpp screen, then the `ld (hl), e` is intended to plot the pixel. – Tommy Apr 18 '16 at 14:55