I have finally reached the point where I only have two problems. Well, I also need to optimize. Anyway, the first problem: the calculator doesn't turn off, at least not in jsTIfied. The second problem: the calculator always acts as though I typed in the wrong password.

Here is my code. What is wrong with it?

Code:
.nolist
   #include "ti84pcse.inc"
   #define MathPrintFlags1 $44
   #define MathPrintActive 5
.list
   .org UserMem-2
   .db tExtTok,tAsm84CCmp

PasswordProgram:
   bcall(_EnableAPD)
   ld a,1
   ld (apdTimer),a
   ld (apdSubTimer),a
   res MathPrintActive,(iy+MathPrintFlags1)
   bcall(_ClrScrnFull)
   bcall(_HomeUp)
   ld hl,PressText
   bcall(_PutS)
   bcall(_NewLine)
   bcall(_NewLine)
   bcall(_PutS)
Unlock:
   bcall(_GetCSC)
   or a
   jr z,Unlock
   bcall(_ClrScrnFull)
   bcall(_HomeUp)
   ld hl,Prompt
   bcall(_PutS)
   ld a,$20
   bcall(_PutC)
   ld b,0
KeyPress1:
   bcall(_GetCSC)
   or a
   jr z,KeyPress1
   cp kUp
   ld a,$2A
   bcall(_PutC)
   jr nz,KeyPress2
   inc b
KeyPress2:
   bcall(_GetCSC)
   or a
   jr z,KeyPress2
   cp kRight
   ld a,$2A
   bcall(_PutC)
   jr nz,KeyPress3
   inc b
KeyPress3:
   bcall(_GetCSC)
   or a
   jr z,KeyPress3
   cp kDown
   ld a,$2A
   bcall(_PutC)
   jr nz,KeyPress4
   inc b
KeyPress4:
   bcall(_GetCSC)
   or a
   jr z,KeyPress4
   cp kDown
   ld a,$2A
   bcall(_PutC)
   jr nz,Check
   inc b
Check:
   ld a,b
   cp 4
   ret z
WrongPassword:
   ld hl,WrongPasswordMsg
   bcall(_NewLine)
   bcall(_PutS)
Stuff:
   bcall(_GetCSC)
   or a
   jr z,Stuff
   jp PasswordProgram
PressText:
   .db "Calculator locked.",0
   .db "Press a key to unlock.",0
Prompt:
   .db "Password:",0
WrongPasswordMsg:
   .db "Wrong password!",0
The problem could be with the way you use the registers. The registers are really volatile and are very likely to change value when you run another routine (in your own code or as a bcall). Don't expect that the registers will be preserved unless you preserve them yourself.

Also, you're using the wrong key codes. Those are for _GetKey, _GetCSC codes are prefixed with "sk", eg "skUp", "skRight", etc. Add an "s" in front of all those keys and you should be good to go.

EDIT: Also, try setting apdRunning in apdFlags:
Code:
   set apdRunning,(iy+apdFlags)
Thank you so much! I have now reached the final stages of the program creation, if not the end. Interestingly, this is the first time I have ever, in my entire life (and I know many programming languages), completed a major programming project.

(Your suggestion about setting the apdRunning flag worked, as you have probably inferred.)

One last thing. Can anybody find any optimizations, major or minor, to make to this program?
Here's what i came up with:
Code:
PasswordProgram:
   bcall(_EnableApd)
   ld a,1
   ld (apdTimer),a
   ld (apdSubTimer),a
   set apdRunning,(iy+apdFlags)
   bcall(_ClrScrnFull)
   bcall(_HomeUp)
   ld hl,PressText
   bcall(_PutS)
   bcall(_NewLine)
   bcall(_NewLine)
   bcall(_PutS)
   call GetKey            ;pauses the calc
   bcall(_ClrScrnFull)
   bcall(_HomeUp)
   ld hl,Prompt
   bcall(_PutS)
   ld a,$20
   bcall(_PutC)
;*********** changes start here *******************
   ld bc,$0400            ;the routine will set c>0 if password was incorrect
   ld hl,Password         ;label where our password is stored
KeyPress:
   call GetKey            ;waits for a key to be pressed, returns with key in a
   cp (hl)               ;compares with the key value we've stored in Password
   inc hl               ;inc/dec for 16-bit registers doesn't affect the flags
    jr z,drawStar         ;if it was correct, leave c alone
      inc c            ;otherwise, mark it as incorrect
drawStar:
   ld a,'*'            ;draw the star/asterisk
   bcall(_PutC)
   djnz KeyPress         ;repeat 4 times
   dec c               ;this checks if c = 0
   inc c
    ret z               ;if it = 0, then we can quit
WrongPassword:
   ld hl,WrongPasswordMsg
   bcall(_NewLine)
   bcall(_PutS)
Stuff:
   call GetKey
   jp PasswordProgram

GetKey:
   push hl
      bcall(_GetCSC)      ;_GetCSC modifies hl, so we need to save it
   pop hl
   or a
   jr z,GetKey
   ret

PressText:
   .db "Calculator locked.",0
   .db "Press a key to unlock.",0
Prompt:
   .db "Password:",0
WrongPasswordMsg:
   .db "Wrong password!",0
Password:
   .db skUp
   .db skRight
   .db skDown
   .db skDown


EDIT: Also, what about adding in an option to change the password? All you need to do is read the values with _GetCSC and overwrite them in Password. DoorsCS will take care of writing it back into your program (program writeback) for you.

Anyway, congratulations! Now your calculator is secure!
One last question. I need to display my email address in small font (_VPutS), and I want to color it navy blue. I already know how to color text with normal (large) font, and I have all the code to color small font except: what is the address of the flag that enables colored small font? WikiTI says that the flag is called penDrawColor, and it is one of the bits at (iy+$14). To the extent of my knowledge, this does not exist in my ti84pcse.inc (like the equivalent flag for large font). So, which bit of (iy+$14) is penDrawColor, or is it even at (iy+$14)?
If you're using _VPutS, text is colored already. You just need to set the color using drawFGcolor (or at least that's what I call it in Doors CSE's source, and it looks like the WikiTI include file calls it the same thing):
Code:
   ld de,BLACK
   ld (drawFGColor),de
KermMartian wrote:
If you're using _VPutS, text is colored already. You just need to set the color using drawFGcolor (or at least that's what I call it in Doors CSE's source, and it looks like the WikiTI include file calls it the same thing):
Code:
   ld de,BLACK
   ld (drawFGColor),de

Can't you just do

Code:

ld (drawFGColor),BLACK

? Or is this just so you can change text color with the same command?
You can't load an immediate value into an immediate memory address in z80 assembly. BLACK is a numeric constant ($0000, incidentally, as it's a 16-bit 5-6-5 RGB color), and drawFGColor is a 16-bit memory address.
123outerme wrote:
KermMartian wrote:
If you're using _VPutS, text is colored already. You just need to set the color using drawFGcolor (or at least that's what I call it in Doors CSE's source, and it looks like the WikiTI include file calls it the same thing):
Code:
   ld de,BLACK
   ld (drawFGColor),de

Can't you just do

Code:

ld (drawFGColor),BLACK

? Or is this just so you can change text color with the same command?

Nah, because the z80 doesn't let you store things like that into memory. You need to load it into a register pair first, and then store it. Smile
Thanks! I get it now Smile
Thanks everyone! I shall use this program for my personal use, and create another version without all the "This calculator belongs to..." stuff (my personal information), and in which users can change their password, and which I shall post in the Archives.
scAFwATLxpKzRCmVaHv wrote:
Thanks everyone! I shall use this program for my personal use, and create another version without all the "This calculator belongs to..." stuff (my personal information), and in which users can change their password, and which I shall post in the Archives.

Great! Now as the first successful program is done, do you have any further plans? Nice work on getting this done and sticking with it; z80 is certainly not an easy language to get used to. Keep it up! Smile
"One must not count his or her chickens before they hatch."

I have another problem. I can't get the right coordinates for _VPutS. What would be the small font coordinates (the value of penRow) for the beginning of row 3 of large font? When I experiment with coordinates, the small font often doesn't even show up at all, which causes other side effects later in the program.

In answer to MateoConLechuga's question, my immediate next plan for Z80 is the fake reset program. That, of course, will not be something that I will publish in the Archives. After that, I will do what I said: publish a modified version of this program. After that...I really don't know. I shall probably begin working on a chess app for the CSE. Actually, for the CE: by the time I am done with the fake reset program, the TI-84 Plus CE will have come out, and I will have bought it. An eZ80! So awesome!
I also plan to generally help the Z80 community by adding documentation for the CSE (flags, RAM, bcalls, etc.) on WikiTI. There is an enormous lack of such documentation, as I have often found to my dismay.
I assumed that you were asking about Z80 Assembly and compatible languages. Other than that, I shall learn Python and Java, the two most useful programming languages that one can learn. I don't have any specific project plans for those high-level languages.
Just to clarify, penRow operates on a pixel basis. Setting penRow to 0 is the very top row of pixels, setting it to 4 is the 5th row of pixels. Not the fifth row of text, the fifth row of pixels on the screen (4 pixels from the top). On the 83+ you generally add 6 to move down a row of text. How are you loading your coordinates? penCol comes before penRow in memory, so if you want to load both at the same time you have to load it into penCol (unlike big text where you load it into curRow). Eg.:

Code:
ld de,$0408
ld (penCol),de     ;ld (penRow),de won't update penCol
I figured out the coordinates a few seconds before you (chickendude) posted. However, I still thank you, because I didn't realize that you could load to curCol and curRow at the same time.
However, this isn't working for me. I suspect that it might have something to do with little-endianness.
Here is the unoptimized code that works:

Code:
   ld bc,$05
   ld (penCol),bc
   ld bc,$50
   ld (penRow),bc

How would I simplify that into two instructions?
scAFwATLxpKzRCmVaHv wrote:
I figured out the coordinates a few seconds before you (chickendude) posted. However, I still thank you, because I didn't realize that you could load to curCol and curRow at the same time.
However, this isn't working for me. I suspect that it might have something to do with little-endianness.
Here is the unoptimized code that works:

Code:
   ld bc,$05
   ld (penCol),bc
   ld bc,$50
   ld (penRow),bc

How would I simplify that into two instructions?

It's because you are overwritting one with another. You could do:

Code:
   ld   bc,$5005
   ld   (pencol),bc
Smile

EDIT: Of course, say you have an X & Y point in decimal. You can load them by doing:

Code:
   ld bc,256*Y+X
   ld   (pencol),bc


Hope this helps! Smile
There's a problem with that code, too. You are loading two bytes into a one-byte address.

Code:
ld bc,$05       ;c = $05, b = $00 (you are really writing ld bc,$0005)
ld (penCol),bc  ;(penCol) = c, (penCol+1) = b. penCol+1 is penRow
ld bc,$50       ;c = $50, b = $00 (remember, bc is 16-bit)
ld (penRow),bc  ;(penRow) = $50, (penRow+1)=$05. I dunno what penRow+1 is, but you probably don't want to be overwriting it blindly.


EDIT: Adding onto to Mateo's post, you could also do "ld bc,(Y<<8)+X".
Thanks all. But then why isn't

Code:
   ld bc,$5005
   ld (penCol),bc

working? Isn't that what you said; doesn't it follow the 256*Y+X pattern?
I dunno, you aren't overwriting it somewhere else?
Perhaps there is something else in the code. Can you post some more?

Also is there anything on screen at all? Does the program crash etc?
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 3 of 5
» All times are UTC - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement