LoginLogin
Nintendo shutting down 3DS + Wii U online services, see our post

How to make a simple notepad with saving and loading

Root / Submissions / [.]

SamCreated:
So you know how to display stuff, right? Like, with LOCATE and PRINT. There are other ways to display characters on screen, but we'll use that for now. First of all, we're going to code a way to display what we want.
CLS
LOCATE 0,0
?"Stuff!"
Okay, but we know we want to be able to change what's displayed. Let's create a string: it'll allow us to do just that.
the code
CLS
TEXT$="Stuff!"
LOCATE 0,0
?TEXT$
That's cool. Now we want to be able to change the text while the program is running. We encounter a problem here: as you'll notice, the program stops running as soon as it's done printing the text. Let's code a loop that never ends, so the program keeps running.
the code
CLS
TEXT$="Stuff!"
LOCATE 0,0
?TEXT$
WHILE 1
WEND
Now it runs forever. Notice that we're using "WHILE 1", which actually means "While (1) is true...". In SmileBASIC, TRUE represents 1 and FALSE represents 0. So, since 1 is always true, which means it's always equal to 1, the loop will always keep going. But we want to change text, and right now we can't do anything! It would be pretty neat if we could use the keyboard to enter text, so that's what we'll do. The command we need for this is INKEY$(). Actually, it doesn't work like LOCATE and PRINT. It works a bit like a string, like the TEXT$ thingy we wrote earlier, except that instead of it letting us store whatever we want in it, it always gives us a character from the keyboard. For example, we could display INKEY$() just like we did with TEXT$.
the code
CLS
TEXT$="Stuff!"
LOCATE 0,0
?TEXT$
WHILE 1
LOCATE 0,1
?INKEY$()
WEND
Neat. Now, let's try to edit the TEXT$ string by adding INKEY$() to it!
the code
CLS
TEXT$="Stuff!"
LOCATE 0,0
?TEXT$
WHILE 1
TEXT$=TEXT$+INKEY$()
LOCATE 0,1
?TEXT$
WEND
It's that simple. Now, there are still a few problems with what we currently have. When we try to remove characters, it instead adds a strange character. And when we try to use Enter to skip a line, it doesn't do it. Let's make it so if INKEY$() sees a backspace, the previous character gets deleted (instead of adding the weird symbol). If you're wondering how we can know which character the backspace is, do the following:
  • Run what we currently have;
  • Do a backspace;
  • Stop the program;
  • On the Direct screen, type "?RIGHT$(TEXT$,1)": it should show you the strange character;
  • Now type "?ASC(?RIGHT$(TEXT$,1))": this command shows what number the character represents.
If you've done all of this, you'll find that the number is 8. We can now do what we wanted. Also, let's simplify some of our code. We're going to store INKEY$() in a string we'll call A$.
the code
CLS
TEXT$="Stuff!"
WHILE 1
A$=INKEY$()
IF ASC(A$)!=8 THEN TEXT$=TEXT$+A$
IF ASC(A$)==8 THEN TEXT$=LEFT$(TEXT$,LEN(TEXT$)-1)
LOCATE 0,0
?TEXT$
WEND
"If the character we just typed in isn't 8, then the text is the text plus what we typed in." "If the character we just typed in IS 8, then the text is, starting from the left, the entirety of its lenght minus one character." Oh yeah, an error. We love those. The problem we have right now is that ASC() doesn't like when it gets an empty string. That is, when we aren't typing anything. Let's solve this.
the code
CLS
TEXT$="Stuff!"
WHILE 1
A$=INKEY$()
IF A$!="" THEN
 IF ASC(A$)!=8 THEN TEXT$=TEXT$+A$
 IF ASC(A$)==8 THEN TEXT$=LEFT$(TEXT$,LEN(TEXT$)-1)
ENDIF
LOCATE 0,0
?TEXT$
WEND
This is getting a bit disgusting, so I put spaces inside of the IF statement so we don't get lost too much. You don't have to. Okay, this still isn't working. Can you see why? It's because we aren't cleaning up the screen. Also, you may notice by using many times the backspace that eventually, you run out of numbers to remove and the program gives another error. We can also stop this.
the code
TEXT$="Stuff!"
WHILE 1
CLS
A$=INKEY$()
IF A$!="" THEN
 IF ASC(A$)!=8 THEN TEXT$=TEXT$+A$
 IF ASC(A$)==8 AND LEN(TEXT$)>0 THEN TEXT$=LEFT$(TEXT$,LEN(TEXT$)-1)
ENDIF
LOCATE 0,0
?TEXT$
WEND
Now it works... kinda? It's super glitchy. That's because we're trying to clean the screen "all the time". Let's slow things down a little, with VSYNC. (Or with WAIT. Either works.)
the code
TEXT$="Stuff!"
WHILE 1
VSYNC
CLS
A$=INKEY$()
IF A$!="" THEN
 IF ASC(A$)!=8 THEN TEXT$=TEXT$+A$
 IF ASC(A$)==8 AND LEN(TEXT$)>0 THEN TEXT$=LEFT$(TEXT$,LEN(TEXT$)-1)
ENDIF
LOCATE 0,0
?TEXT$
WEND
Yay! It works now! All that's left to do is line skipping, and then we'll be working on saving and loading. Use the same method as earlier to find which character the line skip is, and you'll find the number 13.
the code
TEXT$="Stuff!"
WHILE 1
VSYNC
CLS
A$=INKEY$()
IF A$!="" THEN
 IF ASC(A$)!=8 THEN TEXT$=TEXT$+A$
 IF ASC(A$)==8 AND LEN(TEXT$)>0 THEN TEXT$=LEFT$(TEXT$,LEN(TEXT$)-1)
ENDIF
S=0
T=0
FOR I=0 TO LEN(TEXT$)-1
 IF ASC(MID$(TEXT$,I,1))==13 THEN
  LOCATE 0,S
  ?MID$(TEXT$,T,I+1-T)
  INC S
  T=I+1
 ENDIF
NEXT
LOCATE 0,S
?MID$(TEXT$,T,I+1-T)
WEND
Yeah... this one's complicated. We stored two variables. S tells us on which line we are, and T stores in memory at how many characters we were the last time we encountered a line skip. Then, I used black magic (trial and error) to find exactly how all of this would fit together in one function. But seriously, if you try this, it works really well. I'm sure someone could find some other way to do it. But now, we have a program that can perfectly display stuff like we wanted. It's time to save and load. Let's make it so when we press X, the TEXT$ string will be saved, and when we press Y, the string is loaded.
the code
TEXT$="Stuff!"
WHILE 1
VSYNC
CLS
A$=INKEY$()
IF A$!="" THEN
 IF ASC(A$)!=8 THEN TEXT$=TEXT$+A$
 IF ASC(A$)==8 AND LEN(TEXT$)>0 THEN TEXT$=LEFT$(TEXT$,LEN(TEXT$)-1)
ENDIF
S=0
T=0
FOR I=0 TO LEN(TEXT$)-1
 IF ASC(MID$(TEXT$,I,1))==13 THEN
  LOCATE 0,S
  ?MID$(TEXT$,T,I+1-T)
  INC S
  T=I+1
 ENDIF
NEXT
LOCATE 0,S
?MID$(TEXT$,T,I+1-T)
IF BUTTON()AND #X THEN SAVE "TXT:OATMEAL",TEXT$
IF BUTTON()AND #Y THEN LOAD "TXT:OATMEAL",0 OUT TEXT$
WEND
Bam! It already works. The only problem I see here is that if the file doesn't exist when we try to load it, the TEXT$ is reset. In a real app, you shouldn't have to lose your progress just for trying to load something that doesn't exist! Let's solve this.
the final code
TEXT$="Stuff!"
WHILE 1
VSYNC
CLS
A$=INKEY$()
IF A$!="" THEN
 IF ASC(A$)!=8 THEN TEXT$=TEXT$+A$
 IF ASC(A$)==8 AND LEN(TEXT$)>0 THEN TEXT$=LEFT$(TEXT$,LEN(TEXT$)-1)
ENDIF
S=0
T=0
FOR I=0 TO LEN(TEXT$)-1
 IF ASC(MID$(TEXT$,I,1))==13 THEN
  LOCATE 0,S
  ?MID$(TEXT$,T,I+1-T)
  INC S
  T=I+1
 ENDIF
NEXT
LOCATE 0,S
?MID$(TEXT$,T,I+1-T)
IF BUTTON()AND #X THEN SAVE "TXT:OATMEAL",TEXT$
IF BUTTON()AND #Y && CHKFILE("TXT:OATMEAL") THEN LOAD "TXT:OATMEAL",0 OUT TEXT$
WEND
I wrote this super fast, so things probably aren't 100% clear. I suggest that you mess around with the commands in order to get used to them, and if you get stuck, of course, we'll be here to help.

>or with WAIT. Either works please, Sam, I can't continue reading this

The tutorial is
@great
thanks Sam!