Author Topic: Z80 ASM Help  (Read 3459 times)

0 Members and 1 Guest are viewing this topic.

Offline Smasher816

  • LV0 Newcomer (Next: 5)
  • Posts: 1
  • Rating: +0/-0
    • View Profile
Z80 ASM Help
« on: September 02, 2012, 07:35:33 pm »
Alright Iv been programming in various (higher level) languages for years.
After messing around with my calculator and creating a large basic program (~500 lines without a computer), I felt I would try my hand at asm.

Hopefully some of the gurus here such as thepenguin77 or calc84maniac will be able to answer my questions better than google has.

1) What is the best way to input a float (Op1) from the user?
Both
Code: [Select]
Input "X: ",X in Basic and the input boxes in PlySmlt2 are good examples.
Will I have to code my own keypress interpreter that then parses the string into a floating number, or is there a bcall() for this kind of thing.

The only thing I found is http://eeems.omnimaga.org/Files/Resources/Tutorials/ASMin28Days/lesson/day27.html#inp however wabbitcode doesn't appear to like the ".module" command.

Any guidance on this task would be awesome.

2) I know this loop is most likely horribly written, but why is the text displayed so slow?
Is it the loop, the repeated _vPutMap rom call, or something else?
Code: [Select]
menu:
LD HL,$0000
LD (curRow),HL

LD HL,menuA
set textInverse,(IY+textFlags)
call putC
res textInverse,(IY+textFlags)

LD HL,$0201
push HL

LD B,9
menuLoop:
pop HL
push BC
LD a,$06
LD b,H
add a,b
LD H,a
pop BC
push HL
LD (penCol),HL

ld de,menuA
ld A,10
sub b
ld H,0
LD L,A
add hl,hl
add hl,hl
add hl,hl
add hl,hl
add hl,hl
add hl,de
call vPutMap
djnz menuLoop

vPutMap:
ld a,(hl)
inc hl
or a;
ret z
bcall(_VPutMap)
jr vPutMap

putC:
ld a,(hl)
inc hl
or a;
ret z
bcall(_PutC)
jr putC

menuA:
.db "     TITLE      ",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.db "1. Item A               ",0,0,0,0,0,0,0,0
.db "2. Item A               ",0,0,0,0,0,0,0,0
.db "3. Item A               ",0,0,0,0,0,0,0,0
.db "4. Item A               ",0,0,0,0,0,0,0,0
.db "5. Item A               ",0,0,0,0,0,0,0,0
.db "6. Item A               ",0,0,0,0,0,0,0,0
.db "7. Item A               ",0,0,0,0,0,0,0,0
.db "8. Item A               ",0,0,0,0,0,0,0,0
.db "9. EXIT                 ",0,0,0,0,0,0,0,0

Offline chickendude

  • LV8 Addict (Next: 1000)
  • ********
  • Posts: 817
  • Rating: +90/-1
  • Pro-Riot Squad
    • View Profile
Re: Z80 ASM Help
« Reply #1 on: September 03, 2012, 04:28:09 am »
1. Key input in asm is much more complicated. Depending on how you want to handle it, there are different options. Generally, you'll have a look-up table which will correspond to the keys you are checking. If using GetCSC, you'd organize the table according to those values (at least, the ones you want to read). If you are planning to use DI (direct input), you might organize them according to the key groups. As for the .module directive, i'm pretty sure you can safely leave that out.

EDIT: And yes, you'll need to convert the key presses into the appropriate characters, then convert the string to a FP number (this part should be pretty easy though).

2. A few things:
Code: [Select]
pop HL
push BC
LD a,$06
LD b,H
add a,b
LD H,a
pop BC
push HL
LD (penCol),HL
=
Code: [Select]
ld a,(penCol)
add a,6
ld (penCol),a
;)

Also, why so many 0's at the end? It'd be simpler to just read through each text until you reach 0, skip the 0, set penCol to 0 and increase penRow by 6 or 7 (essentially, a new line). Then quit the routine when you reach a certain character (maybe $FF) Something like this (haven't tested the code, but it should give you some ideas):
Code: [Select]
putCLoop:
ld a,(hl)
inc hl
inc a ;$FF+1=0
ret z
dec a ;0+1=1, -1=0
jr nz,$+15 ;2
ld (penCol),a ;5
ld a,(penRow) ;8
add a,6 ;10
ld (penRow),a ;13
ld a,(hl) ;14
inc hl ;15 bytes
bcall(_vPutMap)
jr putCLoop
Another reason why it might be slow is because it might be redrawing the entire screen every time, and TI's gbufcopy routine is pretty slow. Maybe try setting the flag to draw to the gbuf first then drawing the gbuf afterward.
« Last Edit: September 03, 2012, 04:38:35 am by chickendude »

Offline thepenguin77

  • z80 Assembly Master
  • LV10 31337 u53r (Next: 2000)
  • **********
  • Posts: 1594
  • Rating: +823/-5
  • The game in my avatar is bit.ly/p0zPWu
    • View Profile
Re: Z80 ASM Help
« Reply #2 on: September 07, 2012, 07:19:37 pm »
First of all, I love that you've lurked long enough to know about calc84 and I. But anyways:

1. For inputting stuff in asm, really, you're going to have to write it yourself. There aren't really any OS routines you could use that will give you what you want.

So, for my example, I'm going to use bcall(_getCSC) and I'm going to ignore 2nd related stuff. (Pressing [,] will just be E).

Here is my most commented routine ever:
Code: [Select]


;#####################################
;Type name
;output: HL = pointer to input string
; carry = user quit

bufSize equ 10 ;this is how long you want the buffer to be
buffer equ saveSScreen ;put this wherever you want

typeName:
bcall(_clrTxtShd) ;if you don't do this, letters will appear under the cursor
ei
set curAble, (iy + curFlags) ;we'll use the OS's cursor since it's easier
ld de, buffer ;de is going to be the pointer
ld b, 0 ;b will be how many characters have been entered

ld hl, 0*256+0 ;this is going to start at (0,0), change this to whatever you want
ld (curRow), hl
typeLoop:
halt ;putting a halt in this loop decreases battery use by like 90%
bcall(_GetCSC) ;this gets whatever key was press (physical key, no 2nd crap)
or a ;was a key pressed
jr z, typeLoop ;no go back around

cp skEnter ;sk[Key pressed] because we're using getCSC
jr nz, notaEnter

ld a, b
or a
jr z, notAEnter ;0 length input is silly
xor a
ld (de), a ;null terminator turns this into a string, you don't have to do this
call curOff
res curAble, (iy + curFlags) ;kill the cursor
ld hl, buffer ;might as well return a pointer
or a ;this resets the carry flag, carry means user quit
ret

notaEnter:
cp skDel
jr z, delTa
cp skLeft ;since we're not the OS, pressing left is going to delete a number
jr nz, notBackSpace
delTa:
ld a, b
or a
jr z, typeLoop ;don't do it if there's nothing there
call curOff ;prevent hanging cursor

ld hl, curCol ;move the cursor back
dec (hl)

dec de ;move the pointer back
dec b ;decrease the number of letters
ld a, ' '
bcall(_PutMap) ;put a blank without moving the cursor

call cursorOn
jr typeLoop

notBackSpace:
cp skClear
jr nz, notClearz ;I have clear quitting, you can do other stuff if you want

call curOff
res curAble, (iy + curFlags)

scf ;this lets the calling routine know you quit
ret

notClearz:
ld c, a
ld a, b
cp bufSize
jr z, typeLoop ;if it's too big, accept no more input
ld a, c

sub skChs ;this is the neg button, it's the lowest value key we want (sk value)
jr c, typeLoop ;if it's under skChs ($11) we don't want the key
cp skComma-skChs+1 ;skComma ($25) is the highest value we will accept
jr nc, typeLoop

ld hl, charTable

add a, l ;this little section is HL + A
ld l, a
jr nc, $+3 ;after this, HL holds a pointer the the character we need to display
inc h
;$$ ;this is just a comment for clarity on the jump, could have used a label

call curOff ;destroys A not HL (this is an actual comment from this code :D )
ld a, (hl)
or a
jr z, justKidding ;the button pressed was in the correct range, it just wasn't a key we wanted

ld (de), a ;add it to the buffer
inc de ;increase the buffer pointer
inc b ;increase the counter for the bufer

bcall(_PutC) ;type the character and increase (curCol)

call cursorOn
jp typeLoop

justKidding:
call cursorOn
jp typeLoop

cursorOn:
res curOn, (iy + curFlags)
jr readyk
curOff:
set curOn, (iy + curFlags)
readyk:
ld a, 1 ;this is a clever little hack, you set the wrong cursor state
ld (curTime), a ;set the curTime to 1, and let an interrupt occur
ei ;since the OS decreases curTime by one every interrupt, it will
halt ;reach zero and the OS will flip the cursor over to the correct state
ret


charTable: ;these are the letters as they appear in order of scan code
.db $1A, "369", 0, 0, 0, 0 ;1A is neg
.db ".258", 0, 0, 0, 0
.db "0147", $1B ;1B is E

So after this is run, if it comes back with carry not set (NC) you will know that you should then parse the buffer for the floating point number. I don't think parsing will be that hard, so I left that up to you ;D If you totally understand this routine, you can rework it to use bcall(_getKey) which will allow for the user to press 2nd. But I don't see the point in this other than to prevent confusion with the E button.


As for part 2 of your post, I'll have to get to that another day. Right now I don't have the time. But, from a quick glance, you might want to check out bcall(_putS) and bcall(_vPutS). The reason is that every bcall is rather slow to call, so calling these single ones that display a whole string can speed things up.

(Where do you look them up? wikiTi and TI's TI-83 Plus System Routines (this link is to the page, you'll have to download the pdf))


Edit:

2)

Ok, here's a much faster version:
Code: [Select]

menu:

 LD HL,$0000
 LD (curRow),HL
 
 LD HL,menuA
 set textInverse,(IY+textFlags)
 bcall(_putS)
 res textInverse,(IY+textFlags)
 
 LD de,$0207
 ld (penCol),de
 
 LD B,9
menuLoop:
 ld a,(penRow) ;like chickendude said
 add a,6 ;but this didn't cause the slowness
 ld (penRow),a
 ld a, 2
 ld (penCol), a

 bcall(_vPutS)
 djnz menuLoop

 bcall(_getKey) ;delay
 ret


menuA:
 .db "     TITLE      ",0
 .db "1. Item A",0
 .db "2. Item A",0
 .db "3. Item A",0
 .db "4. Item A",0
 .db "5. Item A",0
 .db "6. Item A",0
 .db "7. Item A",0
 .db "8. Item A",0
 .db "9. EXIT",0

The reason that your routine was so slow was that you were displaying all of those spaces. Never display spaces in small font like that because it's slow as balls. Also, whenever you run bcall(_vPutS) or bcall(_putS), HL returns pointing to the byte after the zero. This allows you to display all the strings one after another.


If you want even more speed, there is an option. First you "set textWrite, (iy + sgrFlags)". This will allow you to write the small font directly to plotSScreen without writing it to the screen. After it's all there, you can then do bcall(_grBufCpy) (or your own version) to write it to the screen. This is faster because writing to the screen is slow so doing it all at once is faster. The only trouble, (and why I didn't do it to yours), is that it doesn't affect the large font. To get that to work, you'd have to "set fracDrawLFont, (iy + fontFlags)" and then use bcall(_vPutS) to write it to the buffer. But that's a little messy (though not really).
« Last Edit: September 08, 2012, 03:05:40 pm by thepenguin77 »
zStart v1.3.013 9-20-2013 
All of my utilities
TI-Connect Help
You can build a statue out of either 1'x1' blocks or 12'x12' blocks. The 1'x1' blocks will take a lot longer, but the final product is worth it.
       -Runer112