QUESTION: I own a Timex 1000 with memory expansion module 1016 and I have understood that the memory addresses are limited to something less than 36,000. However, I have found that I can store and execute machine code from addresses up around 50,000. I realize that some peculiarity of the addressing of the buss causes the apparently impossible addresses to function. Can you tell me where these instructions are actually stored and why?
ANSWER: Thank you for your good question! You. were on the right track when you mentioned the addressing of the buss. You see, when the ZX-81 was first designed, it was assumed that no one would ever sue more memory than 16K. Therefore, only partial address decoding was provided for; up to 32767. The most significant bit (that would have allowed addressing up to 65,535) was ignored. In Basic, the system variable RAMTOP is set up at initialization and keeps the Basic system from using any address above RAMTOP. However, when you are using machine code, nothing keeps the computer from trying to write to (POKE) or read (PEEK) any address, even if it does not exist.
What is actually happening is this: If you POKE a value into the address 64,000, the number actually goes into Location 31232 (32768 lower). This is because the binary bit pattern for those two addresses is the same except for the most significant bit, which the computer ignores anyway. So, if you POKE numbers into some non-existent high locations, they are actually residing 32768 locations lower. Note that the 64K memories (sold by companies other than Sinclair or Timex) have built in circuitry to decode that MSB and make available for use those upper 32768 bytes.
QUESTION: I like to put machine code in a REM statement at the beginning of a program (TS2068) so that it will load along with the rest of the program. I don’t like the fact that it keeps my program from LISTing properly. Usually, I can’t get any of the program to list after line 1. Any ideas?
ANSWER: sure! Put the machine code in the last line instead of the first. But now we have created a couple of new problems. First, we don’t know the exact location of the last line like we do the first line. And second, the code moves around whenever lines are added or deleted so the code has to be written with only relative jumps. Usually, machine code routines that I plan to store in REM lines are fairly short, and I always use relative jumps where I can anyway.
But how do we find the location of the code so we can run it with the USR function? Well, if it is the last line, then the next thing that follows is the variables, which are pointed to by the system variable VARS. All we have to do is place the following line in the program somewhere before the first USR call: LET VARS=PEEK 23627+256*PEEK 23628: LET LOC= (VARS-2)-code length. You fill in the code length and this must include any extra characters in the REM if you made it a little longer than needed. Now just RANDOMIZE UNS LOC whenever you want to call the routine. The program will list normally down to the last line.
QUESTION: I understand the Commodore 64 computer has a built-in clock that can be set by POKEing in half a dozen values prior to running a program, and the time can be accessed to interrupt a program. Does the TS2068 have this feature?
ANSWER: Yes, and you only have to POKE three values. The “clock” is updated 60 times each second at location 23672. When this number reaches 255 (about four and a quarter seconds), it is reset to zero and the number is location 23673 is incremented. When it reaches 255 (about 18 minutes), it is set to zero and the number in location 23674 is incremented. That gives us over 77 hours before the clock repeats. The easiest way to use the “clock” is to POKE the three locations with 0 at the beginning of your program. That way you start at a known value of zero.
Now, let’s say you want the program to loop doing some task until 25 minutes have passed, and then branch tao an alarm routine. Somewhere in the loop place the following line:
IF PEEK 23672-*256*PEEK 25673*65536*PEEK 23674 > 90000 THEN GOTO 3000
The number 90000 is calculated by 60 . Use the “>” sign instead of equals because the chances of the program calculating the value at the moment it is exactly equal to 90000 is pretty small.
Another variation on this theme might be a game that several people play, each trying to beat the other’s best time. Again set the three clock locations equal to zero at the beginning of the game and then at the end, calculate the seconds used by the following line:
LET SECONDS = INT((PEEK 23672 + 256 * PEEK 23673 + 65536 * PEEK 23674)/60)
By the way the “clock” is stopped during SAVE and LOAD.
QUESTION: I know that if a number is calculated and the result is a whole part and a line of digits after the decimal point, I can strip away the fractional part with INT. But I want whole numbers) and two digits after the decimal (like dollars and cents). How can I do this?
ANSWER: Easy! Just multiply the number by 100, take the INTeger part and divide the answer by 100. Let’s say the answer to your calculation is contained in the variable A. Just add the following line to you program prior to printing:
LET A = .01 * INT(100 * A)
You may want to round the answer to the nearest cent. In that case the line would look like this:
LET A = .01 * INT(.5 + 100 * A)
I hope this helps. Good Luck!