Ast A. Moore wrote: ↑Mon Mar 28, 2022 7:50 am
TMD2003 wrote: ↑Mon Mar 28, 2022 1:30 am
But the final chapter in interrupts... I could live a thousand lifetimes and never put a DI or a RETN or IM 2 in any of my routines. I've read it twice and it's still incomprehensible gobbledegook.
What’s tripping you up specifically about interrupts?
What I was really trying to say was, this is something so far beyond my level that I cannot even attempt to use it yet. If the entire concept of interrupts can be likened to the final year of a Masters degree, I am still working my way through primary school - and it is very, very unlikely I will ever get even close to this level.
But nevertheless, I thought I'd attempt something more challenging - something I have yet to tackle and (more to the point)
is something I'll find useful.
It's how to handle BASIC variables via machine code.
To put this in context, I've also been re-typing all of the
40 Best Machine Code Routines, and some of those late in the book access the variables area.
All I know so far is: the variables area starts at the address held in VARS and ends at one less than the address held in E_LINE. And while I still have trouble decoding the way that numerical variables are held (mainly because they're all five-byte floating point values that are also beyond my level at this stage),
string variables I can see by PEEKing this area.
I see: the letter of the variable, always as a capital, then two bytes for the number of characters, then the characters themselves. Superficially, it seems easy to search for a particular string variable.
So I have started with this BASIC program that should test whether or not there is a method that is
absolutely failsafe in finding a required string variable. I have chosen to look for Q$.
To cause the maximum number of hurdles, I've set up the following:
- Define a string Z$ with twelve characters in it, one of which is Q.
- Define four blank strings A$-D$.
- Define an array L(4) into which random values between 10 and 20 are inserted.
- Populate A$-D$ to a length of L(n) (n=1-4 corresponding to A$-D$), with the characters from Z$. It is likely that all of these will contain one or more Qs.
- INPUT LINE Q$, which defines the string I will search for.
- (eventually...) Execute the machine code routine, search for the variable Q$ and have my evil way with it.
Code: Select all
10 LET z$="VQFods634#%&"
20 LET a$="": LET b$="": LET c$="": LET d$=""
30 DIM l(4)
40 FOR n=1 TO 4
50 LET l(n)=INT (RND*11)+10
60 NEXT n
70 PRINT "LENGTH OF A$ = ";l(1)
80 PRINT "LENGTH OF B$ = ";l(2)
90 PRINT "LENGTH OF C$ = ";l(3)
100 PRINT "LENGTH OF D$ = ";l(4)
110 FOR n=1 TO l(1): LET z=INT (RND*12)+1: LET a$=a$+z$(z): NEXT n: PRINT "A$ = ";a$
120 FOR n=1 TO l(2): LET z=INT (RND*12)+1: LET b$=b$+z$(z): NEXT n: PRINT "B$ = ";b$
130 FOR n=1 TO l(3): LET z=INT (RND*12)+1: LET c$=c$+z$(z): NEXT n: PRINT "C$ = ";c$
140 FOR n=1 TO l(4): LET z=INT (RND*12)+1: LET d$=d$+z$(z): NEXT n: PRINT "D$ = ";d$
150 INPUT "Q$ = "; LINE q$
199 REM view variables area
200 FOR n=(PEEK 23627+256*PEEK 23628) TO (PEEK 23641+256*PEEK 23642)-1
210 PRINT n;" "; INK (2 AND PEEK n<32);PEEK n; INK 0;TAB 12;CHR$ ((32 AND PEEK n<32)+(PEEK n AND PEEK n>=32))
220 NEXT n
So far, all I know is:
- LD HL,(23267) / LD DE,(23641) / DEC DE will set the start and end points of the variables ares where I want them (unless I find it's a better idea to use IX instead of HL, which it might be). If I was then to LD A,(DE), A would read 128. (Or at least, it should, if I've done everything right.)
- At some stage there will be CP 81, followed by JR NZ (backwards) to cycle round until we reach a Q...
then we get to the tricky bit.
And that tricky bit is: how do we establish
beyond any doubt that the Q we're looking at is the one we want? There is at least one Q in the variables area (within Z$) and another unspecified but probably non-zero number of Qs after that, before we get to the Q that signals that this is the variable Q$.
You may say "Aha! Look at the value immediately after it!", but there's a problem. In this case, all the Qs in Z$ and the junk variables A$-D$ will be followed by values between 32-128, but in a
general case that won't necessarily be true; there may be control characters inside other string variables with values under 32. And likewise, there's no guarantee that the value after the Q we want will be under 32, because the string length can easily be 32 or more, or greater than 288, or...
It must be possible, because every time BASIC recalls Q$, the ROM routine to do so always knows exactly where it is.
Once this has been sorted out, I can make some very rudimentary string handling routines, even if it's something as mundane and milquetoast as a ROT13 encoder, or reversing the order of the characters, for a string Q$ of any length.
So far, if I want to do anything like this, I have to resort to a bit of BASIC to POKE the CODE of each character into a series of addresses above RAMTOP, before I can do what I want with them. And now that I think of it, this is what I had to do on
Super Mario Fruit Machine 2; my bit of machine code to print all the reels on screen was supposed to speed it up significantly, but the four POKEs required for each character, of which there were nine, robbed the game of most of the speed bonus. While it might have been possible to hold all the reels as a series of bytes above RAMTOP and then write an easier routine to access those without having to probe the variables area, either I didn't think of that at the time or had already invested too much time into making it work the BASIC way that this would have required a significant rewrite (and the fact that I wrote the game using BASin probably doesn't help on that front).