Your Spectrum
Issue 16, July 1985 - 3D Graphics
Home Contents KwikPik


See also this letter about the article:
Issue 19"Check It Out ..."


3 D D  A  Z  E
It's here - the ultimate in 3D graphics. Mr MegaBasic, Mike Leaman shows another side to his talents with a program that'll transport you into the third dimension.
How often have you wished you could create the smooth three dimensional graphics like the ones Ultimate has made famous in Knight Lore and Alien 8? Well, now you can - almost. Of course, the Ultimate team doesn't actually program on the Spectrum but on a much larger machine, then squirts it down. But you can get pretty close with these machine code routines that'll enable you to move objects in three dimensions.
The tricky bit about 3D graphics is making sure that the objects meant to be at the front of the display look as though that's where they are. So, how's it done? Well, briefly, you have to draw the objects at the back first and then work your way forward.
I've tackled it by keeping a list of all the objects that appear on the screen and this
list contracts and expands according to how many objects there are. The list starts at 64700 and each entry consists of four bytes. Understanding these is the tricky bit. The first byte is the 'X' co-ordinate, the second the 'Y'-co-ordinate, the third the 'Z' co-ordinate and the last byte is the objects' code number. The easiest way to understand these co-ordinates is to think in terms of a matchbox - hold it up in front of you. 'Y' runs along the bottom from left to right, 'X' runs up the edge that goes from the top to bottom and 'Z' is the co-ordinate that travels along the edge that's going away from you. If you're still in trouble or you want to go into further depth, take a look at the articles on 3D plotting in YS issues 2 and 3.
Now back to that list. Those objects that are to be placed at the back come at the start of the list. Then each time an object is displayed or erased, the list is scanned and the appropriate action taken. The shape of each object is stored in 64 bytes of RAM and I've included three objects with the code. The shape list starts at 65047, so that's where you'll find the first object, then the second object is at 65047+64 and so on. The 64 bytes of character info is split into two halves - the first 32 bytes represent the actual shape of the object, similar to the way you would define a UDG but with much more information because of the third dimension. This is followed by the second 32 byte block that describes the shape of the mask needed to erase the object.
Now take a look at the code. It's in two parts - the first part that does all the work starts at 64000 and the second part contains shape info for the three example objects and starts at 65047. Here's how you enter the code. First type in the Hex loader and save it - you may need it later. Now RUN it and it'll automatically lower RAMtop so that there's space for the code. You'll then be asked for a start address - for the main block, enter 64000 and for the shape info enter 65047. Once you've put those in, you can press on with entering the actual code. For starters, you'l1 be prompted with an
A NEW DIMENSION

sample animation - part 1
Memories of Knight Lore come flooding back already. Here's the first of Mike's 3D graphics emulator. The background's been stored already in high memory so that once the characters are moved, the picture will not be obliterated.

sample animation - part 2
Now another set of graphics has been added to the screen. Not only can the program cope with the spheres going back into the picture but also with graphics coming forward.

sample animation - part 3
The shape of the characters that you put up on the screen using the 3D graphics routines is totally up to you. They're created on a 16x16 matrix with a similar mask. Watch out for the manic 3D Space Invaders!

address - look at the main listing - the first prompt'll be 64000 so you should enter F3. The second prompt is 64001, so you'll enter CD93FB, remembering, of course, not to enter any spaces.
When you've reached the end of a block, enter 'S' - the loader will then ask you for a Checksum. For the main block enter 79933, then for the shape data enter 17774. Now the loader checks the code for errors. If it finds one you'll just have to go back and re-check. As soon as you've entered the main block, carry on and enter the shape data and then save the code using:

SAVE "code" CODE 64000,1368

Now enter NEW and type in the test program, again remembering to save it just in
case the code crashes. At last, you're there! If all's well, you should be greeted by a number of bubbles moving across the screen in full and glorious 3D.
OK, I can already hear you asking how you can use the routines yourself. As I've said, it takes four parameters to describe an object - the 'X', `Y' and 'Z' co-ordinates plus the shape code that defines what shape the object is to take. These parameters are passed to the machine code in four locations:

64637 'Y' co-ordinate
64638 'X' co-ordinate
64639 shape code
64640 'Z' co-ordinate


Well, there are three routines that you can usefully adapt. The first is the one that covers the background.
To understand this, you must know that the middle third of the screen is printed first, so you can use this part as a back drop. So, design your back drop and save it into memory which you can do as follows: first, reserve an area of memory using the CLEAR command, then POKE the address of this area into locations 64635 and 64636. Once you've drawn your backdrop, call the routine at 64423 and this'll save the middle third of the screen into memory.
Now to print an object POKE its co-ordinates into the correct memory locations and call the routine at 64489. Then to erase an object POKE its co-ordinates into the correct locations and call the routine at 64556.
You'll also have to remember to execute POKE 64703,0 before you start printing - that
way you'll clear the display list. And finally a word of warning - so that the routine's as fast as possible I've left out all the error checking. You'll have to make sure that none of your 3D objects goes wandering off the edge of the screen or you may find yourself with a system crash.
And now onto next month [see The 3D 3]. Watch out for a 3D graphic designer that'll let you create your own clockwork mice or mutant daleks. Plus, for all the clever people who've mastered YS MegaBasic, I'll be showing you how to convert this month's machine code into MegaBasic. All you'll have to use then are a number of new Basic commands. Of course, all you poor socially deprived Speccy owners still relying on Sinclair Basic will have to resort to the infamous commands POKE and USR. It's a tough life!


This program is available on "ZIPi'T'ape".

A NEW DIMENSION
Use this hex loader to enter the hex code from both the character info and the main assembler listing.
 10 CLEAR 63999
 15 POKE 23658,8
 17 DEF FN h(h$)=16*(CODE (h$)-48-7*(h$(1)>"9"))+(CODE (h$(2))-48-7*(h$(2)>"9"))
 20 INPUT "Start address ";a
 25 LET z=a
 30 INPUT (a), LINE a$
 35 IF a$="S" THEN GO TO 90
 40 PRINT a,a$: POKE 23692,255
 50 FOR z=1 TO LEN a$/2
 60 POKE a,FN h(a$(((z*2)-1) TO )): LET a=a+1
 70 NEXT z
 80 GO TO 30
 90 INPUT "Checksum ";d
100 LET c=0: FOR b=z TO a-1: LET c=c+PEEK b: NEXT b
110 IF c=d THEN PRINT "The code is OK!": STOP
120 PRINT "Oh dear, the code is incorrect": STOP
This is reproduced as it was printed in the magazine - including the error. The variable Z assigned at line 25 is also used in the loop in lines 50-70, so its value gets overwritten. Change the references to Z in the loop to some other letter.
ASSEMBLER 3-DUMP
This is the main assembler listing, which you can either type in using an assembler, monitor or our own Hex loader.
64000  F3       DI
64001  CD93FB   CALL 64403
64004  DD21BCFC LD   IX,64700
64008  DD7E03   LD   A,(IX+003)
64011  A7       AND  A
64012  281E     JR   Z,64044
64014  CD32FA   CALL 64050
64017  AF       XOR  A
64018  DD6E00   LD   L,(IX+000)
64021  DD6601   LD   H,(IX+001)
64024  DD5602   LD   D,(IX+002)
64027  DD23     INC  IX
64029  DD23     INC  IX
64031  DD23     INC  IX
64033  DD23     INC  IX
64035  DDE5     PUSH IX
64037  CD6BFA   CALL 64107
64040  DDE1     POP  IX
64042  18DC     JR   64008
64044  FD213A5C LD   IY,23610
64048  FB       EI
64049  C9       RET
64050  3D       DEC  A
64051  2600     LD   H,000
64053  6F       LD   L,A
64054  29       ADD  HL,HL
64055  29       ADD  HL,HL
64056  29       ADD  HL,HL
64057  29       ADD  HL,HL
64058  29       ADD  HL,HL
64059  29       ADD  HL,HL
64060  0117FE   LD   BC,65047
64063  09       ADD  HL,BC
64064  44       LD   B,H
64065  4D       LD   C,L
64066  C9       RET
64067  3EBF     LD   A,191
64069  90       SUB  B
64070  47       LD   B,A
64071  210040   LD   HL,16384
64074  78       LD   A,B
64075  E6C0     AND  192
64077  1E00     LD   E,000
64079  57       LD   D,A
64080  CB3A     SRL  D
64082  CB3A     SRL  D
64084  CB3A     SRL  D
64086  19       ADD  HL,DE
64087  78       LD   A,B
64088  E607     AND  007
64090  84       ADD  A,H
64091  67       LD   H,A
64092  78       LD   A,B
64093  E638     AND  056
64095  CB27     SLA  A
64097  CB27     SLA  A
64099  5F       LD   E,A
64100  1600     LD   D,000
64102  19       ADD  HL,DE
64103  0600     LD   B,000
64105  09       ADD  HL,BC
64106  C9       RET
64107  328BFB   LD   (64395),A
64110  E5       PUSH HL
64111  C5       PUSH BC
64112  DDE1     POP  IX
64114  212000   LD   HL,00032
64117  09       ADD  HL,BC
64118  E5       PUSH HL
64119  FDE1     POP  IY
64121  E1       POP  HL
64122  CD6BFB   CALL 64363
64125  F5       PUSH AF
64126  CD47FB   CALL 64327
64129  C1       POP  BC
64130  4F       LD   C,A
64131  E607     AND  007
64133  328CFB   LD   (64396),A
64136  6F       LD   L,A
64137  2600     LD   H,000
64139  29       ADD  HL,HL
64140  29       ADD  HL,HL
64141  29       ADD  HL,HL
64142  C5       PUSH BC
64143  010EFB   LD   BC,64270
64146  09       ADD  HL,BC
64147  C1       POP  BC
64148  36C9     LD   (HL),201
64150  2291FB   LD   (64401),HL
64153  79       LD   A,C
64154  CB3F     SRL  A
64156  CB3F     SRL  A
64158  CB3F     SRL  A
64160  4F       LD   C,A
64161  328DFB   LD   (64397),A
64164  78       LD   A,B
64165  328EFB   LD   (64398),A
64168  CD43FA   CALL 64067
64171  0610     LD   B,016
64173  3A8EFB   LD   A,(64398)
64176  C5       PUSH BC
64177  E607     AND  007
64179  FE07     CP   007
64181  2007     JR   NZ,64190
64183  ED4B8DFB LD   BC,(64397)
64187  CD43FA   CALL 64067
64190  FD4600   LD   B,(IY+000)
64193  FD4E01   LD   C,(IY+001)
64196  16FF     LD   D,255
64198  CD0DFB   CALL 64269
64201  E5       PUSH HL
64202  7E       LD   A,(HL)
64203  A0       AND  B
64204  77       LD   (HL),A
64205  23       INC  HL
64206  7E       LD   A,(HL)
64207  A1       AND  C
64208  77       LD   (HL),A
64209  23       INC  HL
64210  7E       LD   A,(HL)
64211  A2       AND  D
64212  77       LD   (HL),A
64213  FD23     INC  IY
64215  FD23     INC  IY
64217  E1       POP  HL
64218  3A8BFB   LD   A,(64395)
64221  A7       AND  A
64222  201C     JR   NZ,64252
64224  E5       PUSH HL
64225  DD4600   LD   B,(IX+000)
64228  DD4E01   LD   C,(IX+001)
64231  1600     LD   D,000
64233  CD0DFB   CALL 64269
64236  78       LD   A,B
64237  B6       OR   (HL)
64238  77       LD   (HL),A
64239  23       INC  HL
64240  79       LD   A,C
64241  B6       OR   (HL)
64242  77       LD   (HL),A
64243  23       INC  HL
64244  7A       LD   A,D
64245  B6       OR   (HL)
64246  77       LD   (HL),A
64247  DD23     INC  IX
64249  DD23     INC  IX
64251  E1       POP  HL
64252  3A8EFB   LD   A,(64398)
64255  3D       DEC  A
64256  328EFB   LD   (64398),A
64259  24       INC  H
64260  C1       POP  BC
64261  10A9     DJNZ 64176
64263  2A91FB   LD   HL,(64401)
64266  36CB     LD   (HL),203
64268  C9       RET
64269  5A       LD   E,D
64270  CB3B     SRL  E
64272  CB18     RR   B
64274  CB19     RR   C
64276  CB1A     RR   D
64278  CB3B     SRL  E
64280  CB18     RR   B
64282  CB19     RR   C
64284  CB1A     RR   D
64286  CB3B     SRL  E
64288  CB18     RR   B
64290  CB19     RR   C
64292  CB1A     RR   D
64294  CB3B     SRL  E
64296  CB18     RR   B
64298  CB19     RR   C
64300  CB1A     RR   D
64302  CB3B     SRL  E
64304  CB18     RR   B
64306  CB19     RR   C
64308  CB1A     RR   D
64310  CB3B     SRL  E
64312  CB18     RR   B
64314  CB19     RR   C
64316  CB1A     RR   D
64318  CB3B     SRL  E
64320  CB18     RR   B
64322  CB19     RR   C
64324  CB1A     RR   D
64326  C9       RET
64327  C5       PUSH BC
64328  D5       PUSH DE
64329  E5       PUSH HL
64330  5C       LD   E,H
64331  2600     LD   H,000
64333  E5       PUSH HL
64334  29       ADD  HL,HL
64335  C1       POP  BC
64336  09       ADD  HL,BC
64337  CB3C     SRL  H
64339  CB1D     RR   L
64341  CB3C     SRL  H
64343  CB1D     RR   L
64345  CB3B     SRL  E
64347  7D       LD   A,L
64348  83       ADD  A,E
64349  F5       PUSH AF
64350  CB3F     SRL  A
64352  E1       POP  HL
64353  84       ADD  A,H
64354  67       LD   H,A
64355  3A8FFB   LD   A,(64399)
64358  84       ADD  A,H
64359  E1       POP  HL
64360  D1       POP  DE
64361  C1       POP  BC
64362  C9       RET
64363  C5       PUSH BC
64364  D5       PUSH DE
64365  E5       PUSH HL
64366  5C       LD   E,H
64367  2600     LD   H,000
64369  E5       PUSH HL
64370  29       ADD  HL,HL
64371  C1       POP  BC
64372  09       ADD  HL,BC
64373  CB3C     SRL  H
64375  CB1D     RR   L
64377  CB3C     SRL  H
64379  CB1D     RR   L
64381  CB3B     SRL  E
64383  7D       LD   A,L
64384  93       SUB  E
64385  82       ADD  A,D
64386  67       LD   H,A
64387  3A90FB   LD   A,(64400)
64390  84       ADD  A,H
64391  E1       POP  HL
64392  D1       POP  DE
64393  C1       POP  BC
64394  C9       RET

64395**00 00 00 00
64399**00 28 00 00
64403  2A7BFC   LD   HL,(64635)
64406  110048   LD   DE,18432
64409  010008   LD   BC,02048
64412  1A       LD   A,(DE)
64413  B6       OR   (HL)
64414  12       LD   (DE),A
64415  13       INC  DE
64416  23       INC  HL
64417  0B       DEC  BC
64418  78       LD   A,B
64419  B1       OR   C
64420  20F6     JR   NZ,64412
64422  C9       RET
64423  ED5B7BFC LD   DE,(64635)
64427  210048   LD   HL,18432
64430  010008   LD   BC,02048
64433  EDB0     LDIR
64435  C9       RET
64436  DD21BCFC LD   IX,64700
64440  DD7E03   LD   A,(IX+003)
64443  A7       AND  A
64444  C8       RET  Z
64445  DD7E01   LD   A,(IX+001)
64448  B9       CP   C
64449  280B     JR   Z,64462
64451  D0       RET  NC
64452  DD23     INC  IX
64454  DD23     INC  IX
64456  DD23     INC  IX
64458  DD23     INC  IX
64460  18EA     JR   64440
64462  DD7E00   LD   A,(IX+000)
64465  B8       CP   B
64466  2804     JR   Z,64472
64468  300A     JR   NC,64480
64470  18EC     JR   64452
64472  DD7E02   LD   A,(IX+002)
64475  BA       CP   D
64476  3002     JR   NC,64480
64478  18E4     JR   64452
64480  DD23     INC  IX
64482  DD23     INC  IX
64484  DD23     INC  IX
64486  DD23     INC  IX
64488  C9       RET
64489  ED4B7DFC LD   BC,(64637)
64493  ED5B7FFC LD   DE,(64639)
64497  C5       PUSH BC
64498  D5       PUSH DE
64499  CDB4FB   CALL 64436
64502  DDE5     PUSH IX
64504  D1       POP  DE
64505  212FFD   LD   HL,64815
64508  E5       PUSH HL
64509  A7       AND  A
64510  ED52     SBC  HL,DE
64512  44       LD   B,H
64513  4D       LD   C,L
64514  1133FD   LD   DE,64819
64517  E1       POP  HL
64518  03       INC  BC
64519  EDB8     LDDR
64521  D1       POP  DE
64522  C1       POP  BC
64523  DD7000   LD   (IX+000),B
64526  DD7101   LD   (IX+001),C
64529  DD7202   LD   (IX+002),D
64532  3A7FFC   LD   A,(64639)
64535  DD7703   LD   (IX+003),A
64538  AF       XOR  A
64539  3233FD   LD   (64819),A
64542  CD00FA   CALL 64000
64545  C9       RET
64546  ED4B7DFC LD   BC,(64637)
64550  ED5B7FFC LD   DE,(64639)
64554  DD21BCFC LD   IX,64700
64558  DD7E03   LD   A,(IX+003)
64561  A7       AND  A
64562  C8       RET  Z
64563  78       LD   A,B
64564  DDBE00   CP   (IX+000)
64567  200C     JR   NZ,64581
64569  79       LD   A,C
64570  DDBE01   CP   (IX+001)
64573  2006     JR   NZ,64581
64575  7A       LD   A,D
64576  DDBE02   CP   (IX+002)
64579  280A     JR   Z,64591
64581  DD23     INC  IX
64583  DD23     INC  IX
64585  DD23     INC  IX
64587  DD23     INC  IX
64589  18DF     JR   64558
64591  DD7E03   LD   A,(IX+003)
64594  CD32FA   CALL 64050
64597  C5       PUSH BC
64598  212FFD   LD   HL,64815
64601  DDE5     PUSH IX
64603  D1       POP  DE
64604  ED52     SBC  HL,DE
64606  44       LD   B,H
64607  4D       LD   C,L
64608  62       LD   H,D
64609  6B       LD   L,E
64610  23       INC  HL
64611  23       INC  HL
64612  23       INC  HL
64613  23       INC  HL
64614  EDB0     LDIR
64616  C1       POP  BC
64617  3A7DFC   LD   A,(64637)
64620  67       LD   H,A
64621  3A7EFC   LD   A,(64638)
64624  6F       LD   L,A
64625  3A80FC   LD   A,(64640)
64628  57       LD   D,A
64629  3E01     LD   A,001
64631  CD6BFA   CALL 64107
64634  C9       RET
64635**00 48 00 00
64639**00 00
64641  00       NOP
CHARACTER INFORMATION
This is the character info used by the main listing for the graphics displayed in 3D. These are stored in 64 bytes, 32 bytes for the shape and another 32 for the mask.
65047**03 C0 0C 30 
65051**10 08 27 04 
65055**2A 04 4C 02 
65059**40 02 40 02 
65063**40 02 20 04 
65067**20 04 10 08 
65071**0C 30 03 C0 
65075**00 00 00 00 
65079**FC 3F F0 0F 
65083**E0 07 C0 03 
65087**C0 03 80 01 
65091**80 01 80 01 
65095**80 01 C0 03 
65099**C0 03 E0 07 
65103**F0 0F FC 3F 
65107**FF FF FF FF 
65111**00 80 01 C0 
65115**01 A0 02 90 
65119**04 88 08 84 
65123**09 02 11 01 
65127**21 06 31 18 
65131**0F 60 01 80 
65135**00 00 00 00 
65139**00 00 00 00 
65143**FF 7F FE 3F 
65147**FE 1F FC 0F 
65151**F8 07 F0 03 
65155**F0 01 E0 00 
65159**C0 01 C0 07 
65163**F0 1F FE 7F 
65167**FF FF FF FF 
65171**FF FF FF FF 
65175**00 00 07 F0 
65179**08 08 10 04 
65183**17 74 13 64 
65187**10 04 12 A4 
65191**15 54 10 04 
65195**10 04 1F FC 
65199**15 54 00 00 
65203**00 00 00 00 
65207**FF FF F8 0F 
65211**F0 07 E0 03 
65215**E0 03 E0 03 
65219**E0 03 E0 03 
65223**E0 03 E0 03 
65227**E0 03 E0 03 
65231**EA AB FF FF 
65235**FF FF FF FF 
THREE D-EMONSTRATION
Once you've entered all the code, here's the program that'll give you the moving picture show. Just type it in and then RUN it. Back row of the stalls, please.
  10 BORDER 0: PAPER 0: INK 6: CLEAR 63999
  20 POKE 64703,0
  30 FOR y=0 TO 30 STEP 10
  40 POKE 64637,y: POKE 64638,0: POKE 64639,1: POKE 64640,0
  50 LET print=USR 64489
  60 NEXT y
  70 FOR y=0 TO 30 STEP 10
  80 FOR x=0 TO 162 STEP 3
  90 POKE 64637,y: POKE 64638,x
 100 LET erase=USR 64546
 110 POKE 64638,x+3: LET print=USR 64489
 115 PAUSE 2
 120 NEXT x
 130 NEXT y
 140 FOR y=0 TO 30 STEP 10
 150 FOR x=165 TO 3 STEP -3
 160 POKE 64637,y: POKE 64638,x
 170 LET erase=USR 64546
 180 POKE 64638,x-3: LET print=USR 64489
 185 PAUSE 2
 190 NEXT x: NEXT y
 200 GO TO 70


Original article & program supplied by Leszek Chmielewski Daniel
Home Contents KwikPik