ZXSimulator

Anything QL Software or Programming Related.
User avatar
bwinkel67
QL Wafer Drive
Posts: 1187
Joined: Thu Oct 03, 2019 2:09 am

Re: ZXSimulator

Post by bwinkel67 »

Just realized that the toupper() call in the getvar() function is not needed since when I load in a program I convert to uppercase while reading the file and I convert to uppercase when reading from keyboard. So that will speed it up slightly. Little tweaks here and there speed things up since as long as there is consistency with input and output the upcasing can be offloaded to those non-critical areas where the user expects things to be slow, esp during keyboard input where human speed comes into play.


User avatar
bwinkel67
QL Wafer Drive
Posts: 1187
Joined: Thu Oct 03, 2019 2:09 am

Re: ZXSimulator

Post by bwinkel67 »

So all my work on making things more efficient and I screwed up the functions (CHR$, CODE, INKEY$, LEN, etc...). I no longer parsed them because I didn't include all symbol delimiters. The original BASIC was different in functions and I hadn't thought much about it. Also, I updated both demo BASIC programs. BANNER_BAS now has both square and spiral banner routines and you just choose either one or both...looks pretty cool. BALL_BAS now prints out the speed and also improves the S(low)/F(ast) feature by capturing the INKEY$ in a variable, otherwise the second one would get lost on a fast system (like QLAY2 running on a fast desktop). Oh, and I upped the variable storage from 7 to 32 just so I would stop running out...still static though.

Note, the latest version is 4 seconds faster than the best. It did the Banner (1-square) demo twice through in 98 seconds...which is an almost 5% improvement (previous fastest was 102.4 seconds and that didn't do all the boundary checks for PRINT). For the EightyOne emulator at 50Hz emulation (default it is set to), it ran in 57 seconds...I think this is a newer version and I have tested it on an older version in 52 seconds which I think was running at about 54hz (bottom of the screen seems to show it). The new one lets you pick 50Hz or 60Hz and I'm guessing 50Hz is the default PAL speed for the ZX81. So ZXSimulator is now about 40% slower and catching up (again, as timed on an unexpaded BBQL).
zx.zip
(22.82 KiB) Downloaded 106 times
And I generated .p files for both demo programs and alas, they work perfectly in the EightyOne emulator. I wrote them in the ZXSimulator so that's pretty cool they work as advertised on a real ZX81 emulator. Give em a try...
pfiles.zip
(1.54 KiB) Downloaded 92 times


User avatar
bwinkel67
QL Wafer Drive
Posts: 1187
Joined: Thu Oct 03, 2019 2:09 am

Re: ZXSimulator

Post by bwinkel67 »

In case anyone is interested in some of the speedups from the last version, I thought I'd detailed them here. Code speedup in a high level language can be both algorithmically (i.e. when I started drawing the characters via block's line drawing ability rather than plotting each pixel via block's 1x1 ability, which reduced block calls from 30+ to 5) and reorganizing code, which I was doing here this time.

So in many cases I have functions independent of each other (and perhaps this is a byproduct of a high level language such as C) and each one worries about eating all the possible extra spaces but also aborts if it can't find what it was looking for to let the next call (possible the same function again) worry about it. One thing that each function did was to revert back to where it started from if it failed to match what it was looking for. So if I did a call to getkey("TO") and TO didn't match up, it would return leaving the token pointer where it found it. So the problem is that the work each did skipping all those extra spaces was lost and it would essentially be redone over and over again as the parser tried to figure out what each line of code is trying to do.

Here is a simple code example where sp is the global pointer to the current input string:

Code: Select all

getsym (sym)
   char sym[];
{
   char ch;
   int i, op;

   op = sp;    /* <- this means we undo all our work */
   while (str[sp] == ' ') sp++;
   for (i=0; (ch=sym[i])!='\0'; i++)
      if (str[sp] == ch) sp++; else { sp=op; return BADCHAR; }

   return NOERR;
}
A simple improvement is to move the "op = sp" after the while as that will cause the pointer to move ahead so that the next call to it or related functions don't redo the work. Even though you want to write these functions to do no harm if they fail, certainly, skipping useless blank space is better than keeping it for the next to do. I did this for two functions (getsym and getkey) and this had a huge impact, esp considering that getkey was called for each built-in function in an expression. One future improvement is to move the function mapping call a little lower in the chain so that common value holding entities (variables, numbers and strings) come before (currently vars and strings come after). It's a balancing act since you just don't know what entity is in an expression so you optimize based on the most common one.

Code: Select all

getsym (sym)
   char sym[];
{
   char ch;
   int i, op;

   while (str[sp] == ' ') sp++;
   op = sp;    /* <- so we don't undo everything we've done */
   for (i=0; (ch=sym[i])!='\0'; i++)
      if (str[sp] == ch) sp++; else { sp=op; return BADCHAR; }

   return NOERR;
}
Another small fix that actually really helped a bunch was checking for specific pre symbols after verifying the keyword was valid. Doing it before was a bit wasteful since it did for all non-matching keywords as well.

So from this:

Code: Select all

getkey (key)
   char key[];
{
   char ch;
   int i, op;

   while (str[sp] == ' ') { sp++; } op = sp;
   if (strchr(delim,str[op-1]) == NULL)   /* <- checking this before is wasteful */
       { sp=op; return BADCHAR; }
   for (i=0; (ch=key[i])!='\0'; i++)
      if (toupper(str[sp]) == ch) sp++; else { sp=op; return BADCHAR; }
   if (strchr(delim,str[sp]) == NULL)
      { sp=op; return BADCHAR; }

   return NOERR;
}
To this which removes that strchr call for all failed matches (where there are usually many) plus you reduce overall code size since you do the "sp=op; return BADCHAR" only once.

Code: Select all

getkey (key)
   char key[];
{
   char ch;
   int i, op;

   while (str[sp] == ' ') { sp++; } op = sp;
   for (i=0; (ch=key[i])!='\0'; i++)
      if (toupper(str[sp]) == ch) sp++; else { sp=op; return BADCHAR; }
   if (strchr(delim,str[op-1]) == NULL || strchr(delim,str[sp]) == NULL)
      { sp=op; return BADCHAR; }

   return NOERR;
}


User avatar
bwinkel67
QL Wafer Drive
Posts: 1187
Joined: Thu Oct 03, 2019 2:09 am

Re: ZXSimulator

Post by bwinkel67 »

So I ran my BANNER_BAS demo program in QLAY2 with its speed set at 5,000 and delay at 30 and this is what I got. I created an animated GIF to reduce the size from the movie file (plus optimized it which makes it look a little grainier).
QLAY-at-high-speed.gif
QLAY-at-high-speed.gif (395.03 KiB) Viewed 2698 times
It is cycling through a square pattern normal and then inverted, followed by a spiral pattern, normal and then inverted, and repeats. That would take a little over 3 minutes on a BBQL running ZXSimultor and about 2 minutes on a ZX81.

With QLAY2 speed at 10,000 with 0 delay it just flashes...I had posted the GIF but it's too annoying on the eyes so I removed it.

I think the BANNER_BAS demo looks best with QLAY2 speed set at 1000 and delay at 120 as you can follow the spiral patter a bit more easily...the GIF would just be too big to show here.


User avatar
bwinkel67
QL Wafer Drive
Posts: 1187
Joined: Thu Oct 03, 2019 2:09 am

Re: ZXSimulator

Post by bwinkel67 »

Latest version...I took out some useless toupper() calls after I realized I needed them only in three places: 1) when reading in a file 2) when inputting a program 3) when getting input via INKEY$/INPUT while a program is running. I was still doing the toupper() in getcmd() which means that every BASIC command was being slowed down by that one call. Gained a couple of seconds from that to 96.5 seconds getting closer to that 57 value (ZX81 in PAL mode).
zx.zip
(22.96 KiB) Downloaded 99 times
Also, I was parsing expressions for the arguments to functions CODE, CHR$, and LEN which was problematic since I could get equalities in there and this caused a problem:

Code: Select all

IF CODE K$=38 THEN PRINT "A"
This would be parsed this way:

Code: Select all

IF CODE (K$=38) THEN PRINT "A"
Getting precedence trees just right can be a bit of a pain. So now it parses just values for arguments to functions which works better. My original BASIC interpreter was a bit more flexible than ZX81 BASIC and allowed for parsing expressions for functions but it also forced using parenthesis for functions so you would have to write it this way:

Code: Select all

if code(k$) = 38 then print "A"
Finally, I had taken care of all instances of dealing with graphic's characters except for the LEN function and since the underlying strings use escape characters, it would give longer values for strings containing graphics characters...i.e. the string "\..\.'\##" would return 9 instead of 3...fixed now.

...and, I've started writing a simple Elite program:

Code: Select all

10 REM ELITE
20 GOSUB 1000
400 REM PLAY
410 LET K$=INKEY$
420 IF K$="F" THEN GOSUB 2000
430 GOTO 410
500 STOP
1000 REM DRAW DISPLAY
1010 FOR I=0 TO 31
1030 PRINT AT 15,I;"\.."
1040 NEXT I
1050 FOR I=16 TO 21
1060 PRINT AT I,7;"\: "
1070 PRINT AT I,24;"\ :"
1080 NEXT I
1090 PRINT AT 17,12;"\ .\..\.'\''\''\'.\..\. "
1100 PRINT AT 18,10;"\..\''\' ","   \ '\''\.."
1110 PRINT AT 19,9;"\.'","      \'."
1120 PRINT AT 20,8;"\ .\' ","      \ '\. "
1130 PRINT AT 21,8;"\ :  E L I T E   \: "
1140 PRINT AT 6,14;"\.'  \'."
1150 PRINT AT 7,14;"\'.  \.'"
1200 RETURN
2000 REM FIRE LASER
2010 FOR I=14 TO 7 STEP -1
2020 PRINT AT I,22-I;"\.'"
2030 PRINT AT I,9+I;"\'."
2040 NEXT I
2050 PAUSE 4
2060 FOR I=14 TO 7 STEP -1
2070 PRINT AT I,22-I;" "
2080 PRINT AT I,9+I;" "
2090 NEXT I
2100 RETURN


User avatar
bwinkel67
QL Wafer Drive
Posts: 1187
Joined: Thu Oct 03, 2019 2:09 am

Re: ZXSimulator

Post by bwinkel67 »

Latest version. This one implements a few more functions including ABS, INT, NOT, SGN, and it fixes RND temporarily. Since I'm only doing integer arithmetic and haven't gone through the code and converted it to floating point (waiting until the end to do that since I have to touch many functions) I decided to make RND workable. So if you call it by itself it returns a positive number between 0 and 32767. But if you multiply it by a number it returns an integer value between 0 and that number. Not quite what the ZX81 does but pretty close. So the expression INT(RND*6)+1 will indeed return a number between 1 and 6 (but so right now you don't need the INT value since RND only returns integers). This way I can continue with the Elite game and get it to work and then fix the numeric values to be floating point and it will still work. Note it only works with multiply so if you try an do RND+2 you'll get a large number. It is basically hard coded to look for *.

Here it is. Slowed down by about 3 or so seconds due to the new functions and improvement in var error handling.
zx.zip
(24.13 KiB) Downloaded 95 times
Last edited by bwinkel67 on Tue Apr 14, 2020 9:39 am, edited 1 time in total.


User avatar
bwinkel67
QL Wafer Drive
Posts: 1187
Joined: Thu Oct 03, 2019 2:09 am

Re: ZXSimulator

Post by bwinkel67 »

Current version of Elite for the ZXSimulator that goes with the latest version (above):

This version has moving stars and an enemy ship. No logic yet for moving left/right/up/down and/or shooting at the ship (that's next). Then adding a planet, maybe a space station w/docking and some bartering. We will see how far I can take the demo. I think my linear search for line numbers will start impeding and will need to be changed to a binary search in the BASIC interpreter (or course running on a QL in accelerated mode makes that a non-issue).

Note this was written in the ZXSimulator though I've been using it in QLAY2 running a bit faster than the unexpanded QL but it could be written on an unexpaned QL and the experience is far better than the original ZX81. One feature I may add in the end is a renumber features because its'a pain to do it by hand.

Code: Select all

10 REM ELITE
20 GOSUB 1000
30 LET SHIP=0
40 LET STARS=0
400 REM PLAY
410 LET K$=INKEY$
420 IF K$="F" THEN GOSUB 3000
430 GOSUB 2000
440 GOSUB 4000
450 GOSUB 5000
460 GOTO 410
500 STOP
1000 REM DRAW DISPLAY
1010 FOR I=0 TO 31
1030 PRINT AT 15,I;"\.."
1040 NEXT I
1050 FOR I=16 TO 21
1060 PRINT AT I,7;"\: "
1070 PRINT AT I,24;"\ :"
1080 NEXT I
1090 PRINT AT 17,12;"\ .\..\.'\''\''\'.\..\. "
1100 PRINT AT 18,10;"\..\''\' ","   \ '\''\.."
1110 PRINT AT 19,9;"\.'","      \'."
1120 PRINT AT 20,8;"\ .\' ","      \ '\. "
1130 PRINT AT 21,8;"\ :  E L I T E   \: "
1140 RETURN
2000 REM LASER SIGHT
2010 PRINT AT 6,14;"\.'  \'."
2020 PRINT AT 7,14;"\'.  \.'"
2030 RETURN
3000 REM FIRE LASER
3010 FOR I=14 TO 7 STEP -1
3020 PRINT AT I,22-I;"\.'"
3030 PRINT AT I,9+I;"\'."
3040 NEXT I
3050 PAUSE 4
3060 FOR I=14 TO 7 STEP -1
3070 PRINT AT I,22-I;" "
3080 PRINT AT I,9+I;" "
3090 NEXT I
3100 RETURN
4000 REM ENEMY SHIP
4010 IF SHIP=0 AND INT (RND*6)<>1 THEN RETURN
4020 IF SHIP=0 THEN GOTO 4170
4030 UNPLOT EX-1,EY
4040 UNPLOT EX+1,EY
4050 UNPLOT EX,EY-1
4060 UNPLOT EX,EY+1
4070 LET DIR=INT (RND*8)+1
4080 IF DIR=1 AND EY<42 THEN LET EY=EY+1
4090 IF DIR=2 AND EX<62 THEN LET EX=EX+1
4100 IF DIR=3 AND EY>28 THEN LET EY=EY-1
4110 IF DIR=4 AND EX>1 THEN LET EX=EX-1
4120 PLOT EX-1,EY
4130 PLOT EX+1,EY
4140 PLOT EX,EY-1
4150 PLOT EX,EY+1
4160 RETURN
4170 LET SHIP=1
4180 LET EX=INT (RND*62)+1
4190 LET EY=INT (RND*10)+33
4200 GOTO 4120
5000 REM STARS
5010 IF STARS=0 THEN GOTO 5110
5020 IF SX-SM>0 THEN PRINT AT SY+SM,SX-SM;" "
5030 IF SY+SM*2-4<14 THEN PRINT AT SY+SM*2-4,SX+10;" "
5040 IF SX+SM+20 < 32 THEN PRINT AT SY+SM-1,SX+SM+20;" "
5050 IF INT (RND*10)=1 THEN LET SM=SM+1
5060 IF SM>7 THEN GOTO 5110
5070 IF SX-SM>0 THEN PRINT AT SY+SM,SX-SM;"."
5080 IF SY+SM*2-4<14 THEN PRINT AT SY+SM*2-4,SX+10;"."
5090 IF SX+SM+20 < 32 THEN PRINT AT SY+SM-1,SX+SM+20;"."
5100 RETURN
5110 LET STARS=1
5120 LET SM=0
5130 LET SX=INT (RND*3)+5
5140 LET SY=INT(RND*2)+4
5150 GOTO 5070
And here is the zip file of the .p file which loads and runs without issue in EightyOne.
elite.zip
(1.1 KiB) Downloaded 82 times


User avatar
bwinkel67
QL Wafer Drive
Posts: 1187
Joined: Thu Oct 03, 2019 2:09 am

Re: ZXSimulator

Post by bwinkel67 »

bwinkel67 wrote:New version. Nothing major for the ZXSimulator, just a small bug fix where INPUT A$ for the string it included the new-line character and so now it doesn't. I did update the Elite.bas game and now it has a the ability to move up/down/left/right and fire at the enemy ship and eventually kill it (animated explosion and all). You can also redefine the key bindings for the game in configuration window (default is F for fire and A/D/W/S for movement).

It plays ok on an accelerated QL within ZXSimulator but is hard to play on an unexpanded QL or ZX81. I think I will change it to have the up/down/left/right controls remember the last position so you don't have to keep pressing the appropriate key and checking the INKEY$ each time to move (i.e. the control stick will not go back to zero). That should make it more playable. Then I can add some display elements and see if planets and commerce can be included. It will be much simpler than the real Elite game but it is just for demo purposes.
After all that I decided to change the Elite demo to make it more playable. This one keeps cursor state info so if you move to the left it keeps moving until you move to the right. It also has filled out the display a bit more and shows which direction you are moving and has stubbed out the other areas though they are not yet functional. Still slow on the ZXSimulator (and an actual ZX81) but the actual Elite game wasn't about fast paced action anyways (at least the C64 versoin).

Including the ZXSimulator zip file since it contains it plus .p and code dump so you can see what I did.
zx.zip
(24.96 KiB) Downloaded 93 times
ZX81 p file:
elite.zip
(2.13 KiB) Downloaded 97 times

Code: Select all

10 REM ELITE
20 GOSUB 1000
40 GOSUB 2000
50 GOSUB 6000
400 REM PLAY
410 LET DY=0
420 LET DX=0
430 LET KEY=CODE INKEY$
440 IF KEY<>0 AND KEY<> FIRE THEN GOSUB 1300
450 IF KEY=FIRE THEN GOSUB 3000
460 IF KEY=LEFT THEN LET DX=DX+1
470 IF KEY=RIGHT THEN LET DX=DX-1
480 IF KEY=UP THEN LET DY=DY-1
490 IF KEY=DOWN THEN LET DY=DY+1
500 GOSUB 2000
510 GOSUB 4000
520 GOSUB 5000
530 GOTO 430
999 STOP
1000 REM DRAW DISPLAY
1010 FOR I=0 TO 31
1030 PRINT AT 15,I;"\.."
1040 NEXT I
1050 FOR I=16 TO 21
1060 PRINT AT I,7;"\ :"
1070 PRINT AT I,24;"\: "
1080 NEXT I
1090 PRINT AT 17,12;"\ .\..\.'\''\''\'.\..\. "
1100 PRINT AT 18,10;"\..\''\' ","   \ '\''\.."
1110 PRINT AT 19,9;"\.'","      \'."
1120 PRINT AT 20,8;"\ .\' ","      \ '\. "
1130 PRINT AT 21,8;"\ :  E L I T E   \: "
1140 PRINT AT 19,15;"\ :\:  "
1150 PRINT AT 17,0;"FUEL:"
1160 PRINT AT 18,0;"\##\##\##\##\##\##\##"
1170 PRINT AT 20,0;"ENERGY"
1180 PRINT AT 21,0;"\##\##\##\##\##\##\##"
1190 PRINT AT 17,25;"AMMO:"
1200 PRINT AT 18,25;"\##\##\##\##\##\##\##"
1210 PRINT AT 20,25;"SHIELD:"
1220 PRINT AT 21,25;"\##\##\##\##\##\##\##"
1230 RETURN
1300 REM CONTROLS
1310 PRINT AT 18,15;"  "
1320 PRINT AT 19,14;" \ :\:  "
1330 PRINT AT 20,15;"  "
1340 IF DX<>0 OR DY<>0 THEN LET KEY=0
1350 LET DY=0
1360 LET DX=0
1370 IF KEY=LEFT THEN PRINT AT 19,14;"\ :"
1380 IF KEY=RIGHT THEN PRINT AT 19,17;"\: "
1390 IF KEY=up THEN PRINT AT 18,15;"\ '\' "
1400 IF KEY=DOWN THEN PRINT AT 20,15;"\ .\. "
1410 RETURN
2000 REM LASER SIGHT
2010 PRINT AT 6,14;"\.'  \'."
2020 PRINT AT 7,14;"\'.  \.'"
2030 RETURN
3000 REM FIRE LASER
3010 FOR I=14 TO 7 STEP -1
3020 PRINT AT I,22-I;"\.'"
3030 PRINT AT I,9+I;"\'."
3040 NEXT I
3050 PAUSE 4
3060 FOR I=14 TO 7 STEP -1
3070 PRINT AT I,22-I;" "
3080 PRINT AT I,9+I;" "
3090 NEXT I
3100 IF EY<29 OR EY>30 THEN RETURN
3110 IF EX<30 OR EX>33 THEN RETURN
3120 LET EL=EL-1
3130 RETURN
4000 REM ENEMY SHIP
4010 IF SHIP=0 AND INT (RND*6)<>1 THEN RETURN
4020 IF SHIP=0 THEN GOTO 4240
4030 IF EY<13 OR EY>43 THEN GOTO 4060
4040 IF EX>=1 AND EX<65 THEN UNPLOT EX-1,EY
4050 IF EX>-2 AND EX<63 THEN UNPLOT EX+1,EY
4060 IF EX<0 OR EX>64 THEN GOTO 4090
4070 IF EY>13 AND EY<45 THEN UNPLOT EX,EY-1
4080 IF EY>11 AND EY<43 THEN UNPLOT EX,EY+1
4090 IF EL=0 THEN GOTO 4300
4100 LET DIR=INT (RND*8)+1
4110 IF DIR=1 AND EY<42 THEN LET EY=EY+1
4120 IF DIR=2 AND EX<62 THEN LET EX=EX+1
4130 IF DIR=3 AND EY>28 THEN LET EY=EY-1
4140 IF DIR=4 AND EX>1 THEN LET EX=EX-1
4150 LET EX=EX+DX
4160 LET EY=EY+DY
4170 IF EY<13 OR EY>43 THEN GOTO 4200
4180 IF EX>=1 AND EX<65 THEN PLOT EX-1,EY
4190 IF EX>-2 AND EX<63 THEN PLOT EX+1,EY
4200 IF EX<0 OR EX>63 THEN GOTO 4230
4210 IF EY>13 AND EY<45 THEN PLOT EX,EY-1
4220 IF EY>11 AND EY<43 THEN PLOT EX,EY+1
4230 RETURN
4240 LET SHIP=1
4250 LET EL=INT (RND*3)+2
4260 LET EX=INT (RND*62)+1
4270 LET EY=INT (RND*10)+33
4280 GOTO 4170
4300 REM SHIP EXPLODES
4310 LET SHIP=0
4320 FOR I=1 TO 2
4330 PLOT EX,EY
4340 PLOT EX-1,EY
4350 PLOT EX+1,EY
4360 PLOT EX,EY-1
4370 PLOT EX,EY+1
4380 UNPLOT EX,EY
4390 PLOT EX-2,EY-2
4400 PLOT EX+2,EY-2
4410 PLOT EX-2,EY+2
4420 PLOT EX+2,EY+2
4430 UNPLOT EX-1,EY
4440 UNPLOT EX+1,EY
4450 UNPLOT EX,EY-1
4460 UNPLOT EX,EY+1
4470 UNPLOT EX-2,EY-2
4480 UNPLOT EX+2,EY-2
4490 UNPLOT EX-2,EY+2
4500 UNPLOT EX+2,EY+2
4510 NEXT I
4520 RETURN
5000 REM STAR FIELD
5010 IF STARS=0 THEN GOTO 5120
5020 LET S$=" "
5030 GOSUB 5200
5040 IF INT (RND*10)=1 THEN LET SM=SM+1
5050 LET SX=SX+DX
5060 LET SY=SY-DY
5070 LET SM=SM-DY
5080 IF SY+SM>13 THEN GOTO 5130
5090 LET S$="."
5100 GOSUB 5200
5110 RETURN
5120 LET STARS=1
5130 LET SM=0
5140 LET SX=INT (RND*3)+5
5150 LET SY=INT(RND*2)+4
5160 GOTO 5090
5200 REM STAR
5210 IF SY+SM>=0 AND SY+SM<14 AND SX-SM>=0 AND SX-SM<32 THEN PRINT AT SY+SM,SX-SM;S$
5220 IF SY+SM*2-4>=0 AND SY+SM*2-4<14 AND SX+10>=0 AND SX+10<32 THEN PRINT AT SY+SM*2-4,SX+10;S$
5230 IF SY+SM-1>=0 AND SY+SM-1<14 AND SX+SM+20>=0 AND SX+SM+20<32 THEN PRINT AT SY+SM-1,SX+SM+20;S$
5240 RETURN
6000 REM SETTINGS
6010 LET SHIP=0
6020 LET STARS=0
6030 LET FIRE=CODE "F"
6040 LET LEFT=CODE "A"
6050 LET RIGHT=CODE "D"
6060 LET DOWN=CODE "W"
6070 LET UP=CODE "S"
6080 PRINT AT 0,0;"S:TART C:ONFIGURE?",,,"  DEFAULT: F,A,D,W,S"
6090 GOSUB 6500
6100 PRINT AT 0,0;"                  ",,,"                    "
6110 IF KEY=CODE "S" THEN RETURN
6120 PRINT AT 0,0;"PRESS KEY FOR ACTION:"
6130 PRINT AT 2,2;"FIRE?"
6140 GOSUB 6500
6150 LET FIRE=KEY
6160 PRINT AT 2,2;"LEFT?"
6170 GOSUB 6500
6180 LET LEFT=KEY
6190 PRINT AT 2,2;"RIGHT?"
6200 GOSUB 6500
6210 LET RIGHT=KEY
6220 PRINT AT 2,2;"UP?   "
6230 GOSUB 6500
6240 LET UP=KEY
6250 PRINT AT 2,2;"DOWN? "
6260 GOSUB 6500
6270 LET DOWN=KEY
6280 PRINT AT 0,0;"                     "
6290 PRINT AT 2,2;"      "
6300 RETURN
6500 REM GET KEY
6510 LET KEY=CODE INKEY$
6520 IF KEY<>0 THEN RETURN
6530 GOTO 6510


User avatar
bwinkel67
QL Wafer Drive
Posts: 1187
Joined: Thu Oct 03, 2019 2:09 am

Re: ZXSimulator

Post by bwinkel67 »

Here'ss a video of Elite playing on ZXSimulator (accelerated, not unexpanded QL): https://vimeo.com/408952080

And here's a screen shot:
ZX-Elite.png


Derek_Stewart
Font of All Knowledge
Posts: 3928
Joined: Mon Dec 20, 2010 11:40 am
Location: Sunny Runcorn, Cheshire, UK

Re: ZXSimulator

Post by Derek_Stewart »

Hi,

Nice video, have tried the other ZX81 emulators for the QL?

Just thought, convert your Elite programme to Superbasic and compile it with Qliberator or Turbo.


Regards,

Derek
Post Reply