Значок ресурса

Plot / BASIC Variables List

Нет прав на скачивание
Автор: Stewart Nicholls
Год: 1983
Издатели: Your Computer
Языки: 🇬🇧 Английский
Формат: 📼 TZX лента
Требования: 🖥️ ZX Spectrum 16K

Ссылки:
Страница на ZXArt
Страница на World Of Spectrum
Страница на Spectrum Computing

Скриншоты:
Plot-BASICVariablesList.gif


Spectrum MC/Basic


Sorting Variables





If you find that setting the parameters


of a machine-code routine is a bit of a


drag, Stewart Nicholls' program could


give you the best of both worlds.





Do you get tired of having to set parameters of a machine-


code routine by poking numerous addresses with the neces-


sary values? If you do, the following machine-code routine


is the answer: it makes poking completely unnecessary.


The problem is avoided by setting up the values using


Basic variables and then searching the variables area to


find their value and storing them in the spare bytes of the


printer buffer.


To demonstrate the technique, I have attached the search


program to a routine which prints a message anywhere on the


screen using characters of any height or width, in any ink


colour.


The x and y variables are used for the start of the mes-


sage; since these are the co-ordinates of the top-left


corner of the first character of the message the usual


Spectrum plot positions apply. That is, 0,0 is the bottom


left-hand corner of the screen. For the height of the cha-


racters, h is used. Normal height is 1, 22 will be full


screen. Width of characters is 2. Normal width is 1, 32 is


full screen for one character.


The string containing the message to be printed will be


a$. The only limitations on the message are that it can


only contain characters from code 32 - space - to code 127


- copyright - and that the number of characters multiplied


by width of character should not exceed 23 with the plot


position at the left-hand edge of screen. If this is ex-


ceeded the program will not crash but the message will wrap


round the screen overprinting as it goes.


The program is fully mug-trapped and any wrong parameter


of x and y will be corrected before plotting the string.


The machine code to find the variables x, y, h, w and a$ is


shown in listing 1. [Listing 1 was a code loader, "large"


on the TZX. This loaded (and tested) the machine code de-


scribed, which is on the TZX as "largecode".]


If you read through Chapter 24 of the Sinclair Manual,


you will see that there are six types of variable, namely:


a number whose name is one letter - type (i); a number


whose name is two or more letters - type (ii); an array of


numbers - type (iii); FOR-NEXT loop control - type (iv);


string variable - type (v); an array of characters - type


(vi).


Each of these variables is uniquely identified by its


first byte.


Variable type i = 96d + (letter code - 96d)


Variable type ii = 160d + (first letter code - 96d)


Variable type iii = 128d + (letter code - 96d)


Variable type iv = 224d + (letter code - 96d)


Variable type v = 64d + (letter code - 96d)


Variable type vi = 192d + (letter code - 96d)


The variables we will be searching for will be types (i)


and (v).


If we take, for example, the variable x which has a cha-


racter code of 120, then using the formula (i) given, its


unique first byte is 120. So in order to find variable x we


must search through the variables for this unique code,


which will then point to the start of the x variable infor-


mation. This is not just a simple case of running through


the variables one byte at a time using a CPIR instruction,


as this may find the code 120 held in a string or an array


of characters. So we must find the start of each variable,


check if it is the one we want, and if not, then jump to


the start of the next variable. This means that we must


identify the type of variable found before we know how far


to jump to the next one. This is not as difficult a task as


it might first appear because of the way in which the


Spectrum stores the variable parameters.


With three of the variables, namely array of numbers,


array of character and strings, the length of the variable


is held in the two bytes following the unique byte code.


What is more helpful, bit 5 of the unique code is zero and


the remaining three variables have bit 5 set at one.


The length of the three remaining variables can be calcu-


lated by this method:


Type (i) length = 6 bytes including unique code.


Type (ii) length = number of letters of variable + 5 bytes.


Type (iv) length = 19 bytes including unique code.


We now have the information to enable us to jump over each


type of variable, and the checks must be made in the follo-


wing order: first, check if the code is 120; if yes then


return from routine; check bit 5 and if zero jump by


value in next two bytes + 1 : GOTO 1


Check bit 6 and if zero check following bytes for


BIT 7 = 1


that is the last character of the variable, then jump six


bytes and Goto 1. Check but 7 and if zero then jump 6 bytes


and Goto 1. Now it must be a FOR/NEXT loop so jump 19 bytes


and Goto 1.


The mnemonics of the machine-code to do this are shown in


the Find subroutine. This uses address 23728 to hold the


unique code of the variable for which we are searching. The


HL register holds the address being checked, and the accu-


mulator is loaded with the unique code from address 23728.


The subroutine only takes 46 bytes to check, jump and


locate the start address of any variable.


Now that we have found the start address of our variable


x we must find its value. You will see that the value for


whole numbers is held in the third and fourth bytes follo-


wing the unique code. In our case we are only interested in


numbers from 0 to 255 for x. So we can ignore the high byte


and store the low byte, that is the third byte. This


applies to all our variables x, y, h and w.


With this in mind a subroutine, Setup, can be assembled


to move along three bytes from the address held in HL and


then store the value held in this address in the printer


buffer area of memory. So we now have the means of finding


and storing values of x, y, h and w in addresses 23296/7/8


and 9.


We can now move to the slightly more complicated string


parameters. In our case we need to find a$, unique code 65.


The same Find routine can be used to find the start of the


variable. Once found we then move to the next two bytes to


find the LEN of the string as follows:


INC HL


LD E,(HL)


INC HL


LD D,(HL)


This will put the length of the string into the DE regis-


ter, and, as we can safely limit the length of the string


to 255 characters we only need to store the number in low


byte:


LD (23300),DE


The number in address 23301 will be overwritten with the


first character in the string:


PUSH DE Get number of characters into BC


POP BC


INC HL Set HL at start of characters


LD DE,23301


LDIR Transfer information


The above will transfer the string characters from the


variables to the printer buffer starting at address 23301.


With this routine we now have x, y, h, w, length of


string, and characters in string stored consecutively in


the printer buffer, and can go straight into the routine to


plot the string based on these parameters.


The plot routine finds the start of the eight bytes for


each character in the character and, for each byte, a


Rotate Left instruction is carried out either plotting or


unplotting depending whether Carry is set or not. Again use


is made of the two unused bytes in the Systems Variables


23728/9 to hold and update the x,y plot positions for each


character.


If the y plot position goes below zero, then it is reset


to 175 to give a wrap around effect and likewise if the x


position goes above 255 it is reset to zero. So now we have


a machine-code program than can be called from Basic with


no POKEs in sight - for example:


10 LET x=0: LET y=0: LET h=8: LET w=4:


LET a$="Finished": INK 6: RANDOMIZE USR 32393


This saves 13 POKEs including LEN a$. Listing 1 ["large"]


shows the Basic program to set up the machine code above


RAMTOP. On a 16K Spectrum this is immediately before the


user-defined graphics and occupies 255 bytes. Once the


machine-code is entered the Basic can be NEWed and the code


saved in the usual way.


There are a couple of points to watch with this program.


First, ensude that all the variables are defined before a


call is made to the routine as failure to find a variable


will crash the program. Second, do not use x, y, h or w as


a control variable in a FOR-NEXT loop because the Spectrum


will then delete the simple variable and use the FOR-NEXT


loop to hold further values of x, y, h and w. This can be


demonstrated by the simple Basic program:


10 FOR a=1 TO 10


20 PRINT a;


30 NEXT a


40 LET a=3


50 NEXT a


This program will produce a continuous loop resetting a to


3 and jumping back into the FOR-NEXT loop showing that the


variable - a - is line 40 is part of the FOR-NEXT loop


control variable. If this was not the case the Spectrum


would give an error report:


1 NEXT without FOR, 50:1


You can have a small Basic subroutine to work out the


width of characters and the start plot position to give


information printed centrally on any line; such a program


is given in listing 2 with sample printout. [This is called


"Plot" on the TZX, with one line added to auto-load the


machine code.]


We can now tackle a machine-code program to print out all


the variables used after a program has been run. Note that


this may not be all the variables in the listing as when a


program is run certain subroutines may not have been called


and so variables held in those routines will not have been


placed into the variables area.


This program - listing 3 - could be of use in debugging


Basic programs. Listing 3 is in the form of a machine-code


dump which should be held in DATA statements as listing 1,


and poked into a memory position of your choice. There are


no Jump or Call commands to within the program. I find it


handy to have two versions of the program, one stored above


RAMTOP and another in a line 1 REM statement containing 331


zeros and called using


RANDOMIZE USR 23760


The machine-code is then held in the Basic area of RAM and


can be merged with any program - as long as the program


does not have a line 1, which will be overwritten. One


point to note when saving the Basic REM statement on tape


is to use CLEAR to erase all variables used in the machine-


code loader, otherwise these will be saved and merged along


with the REM statement. This is good practice on any pro-


gram which does not require the variables to be saved.


[This code, saved as a CODE file ready to be loaded any-


where in memory, including into a REM statement should you


want to, is on the TZX as "variables".]


Listing 4 is a demonstration program setting up varia-


bles, and shows a screen copy of the machine-code output


which lists these variables under their variable types.


Notice how the Spectrum converts all variables to lower


case and also that variables a, h, l, o, w, x and z have


been listed under the FOR-NEXT loop only and not under


number. [This is on the TZX as "Basicvars".]


Listing 5 shows the machine-code mnemonics for assembly


into a REM statement, for anyone who wishes to check


through the program to see how it works. The first section


from addresses 5CD0 to 5CE5 sets up the border, paper and


ink colours; from 5Ce6 to 5D46 prints the heading. The


remainder of the program checks the variables one by one


finding the type of variable, locating the next print posi-


tion in that variables column, updating the print position


and printing the variable.


The section from 5D94 to 5DBE is interesting in that it


checks for a column reaching the bottom of the screen and


if it does then waits for a key press before scrolling 21


lines, leaving the heading on the screen and printing the


next variable in position. A return to Basic is only made


when all the variables have been listed.





[ As listing 5 provided nothing more than a bare assembly


dump of the code (with a typo, to boot), I haven't copied


it. Listings 1 and 2, however, were accompanied by (unnum-


bered) hex listings with labels (which are referred to in


the article). The order was not quite rational, but sorted


by address, these listings were as follows: ]





Start address for 16K machine code 32235


ORG 32235


Subroutine to find variables


FIND LD HL, (23627)


START: LD A, (23728)


CP (HL)


RET Z


BIT 5, (HL)


JR NZ, NEXT


INC HL


LD E, (HL)


INC HL


LD D, (HL)


ADD HL, DE


INC HL


JR START


NEXT: BIT 6, (HL)


JR NZ, NEXT1


LOOP5: INC HL


LD A, (HL)


BIT 7, A


JR Z, START


LOOP6: LD DE, 6


ADD HL, DE


JR START


NEXT1: BIT 7, (HL)


JR Z, LOOP6


LD DE, 19


ADD HL, DE


JR START





Subroutine to set parameters of variable to be found


SETUP LD (23728), A


CALL FIND


INC HL


INC HL


INC HL


LD A, (HL)


LD (BC), A


RET





Start of machine-code routine


RUN LD BC, 23296


LD A, 120


CALL SETUP


INC BC


LD A, 121


CALL SETUP


INC BC


LD A, 104


CALL SETUP


INC BC


LD A, 119


CALL SETUP


LD A, 65


LD (23728), A


CALL FIND


INC HL


LD E, (HL)


INC HL


LD D, (HL)


LD (23300), DE


PUSH DE


POP BC


INC HL


LD DE, 23301


LDIR





Routine to plot the string


LD HL, (23296)


XOR A


LD A, H


SBC A, 176


JR C, YES


LD H, A


LD (23296), HL


YES: LD (23728), HL


LD HL, 23301


RUN1: PUSH HL


LD A, (HL)


LD H, 0


LD L, A


ADD HL, HL


ADD HL, HL


ADD HL, HL


LD DE, 15360


ADD HL, DE


LD B, 8


LOOP4: PUSH BC


LD BC, (23297)


LOOP3: LD A, (HL)


PUSH HL


PUSH BC


LD B, 8


LOOP2: PUSH BC


RLA


PUSH AF


JP C, PLOT


LD HL, (23299)


LD A, (23728)


ADD A, L


LD (23728), A


JP 32527


PLOT: LD BC, (23298)


LOOP1: PUSH BC


LD BC, (23728)


PUSH BC


CALL 22E5H


POP BC


INC C


LD (23728), BC


POP BC


DJNZ LOOP1


END: POP AF


POP BC


DJNZ LOOP2


LD A, (23296)


LD HL, 23728


LD (HL), A


INC HL


XOR A


LD A, (HL)


SBC A, 176


JR C, OK


LD (HL), A


JR CONT


OK: LD A, (HL)


CP 0


JR NZ, OK1


LD (HL), 176


OK1: DEC (HL)


CONT: POP BC


POP HL


DJNZ LOOP3


INC HL


POP BC


DJNZ LOOP4


LD A, (23299)


ADD A, A


ADD A, A


ADD A, A


LD L, A


LD A, (23728)


ADD A, L


LD (23296), A


LD (23728), A


LD A, (23297)


LD (23729), A


POP HL


INC HL


LD A, (23300)


DEC A


RET Z


LD (23300), A


JP RUN1
Автор
Verter_bot
Загрузки
0
Просмотры
17
Расширение
zip
Размер
2.5 КБ
Хэш
201f290eca715301b980e7824ed18186
Первый выпуск
Последнее обновление

Оценки

0.00 звезд(ы) 0 оценок
Назад
Вверх