Using MCoder2 in EightyOne

Anything Sinclair ZX Basic related; history, development, tips - differences between BASIC on the ZX80 and ZX81
User avatar
GCHarder
Posts: 427
Joined: Sat Dec 14, 2013 7:46 pm

Re: Using MCoder2 in EightyOne

Post by GCHarder »

I've compiled large programs using XavSnap's emulator (make sure the 8k region is disabled or it will hang).
And also sz81. I tried again last night with a 15k Basic program, Platform Jack, which I posted awhile ago in the games forum. All I did was Poke 16389,255 followed by NEW. I could not get it to compile in EO. I think MCoder may alter some sysvars which causes the hangup.

Hope this helps.

Greg
User avatar
XavSnap
Posts: 1940
Joined: Sat May 10, 2008 4:23 pm
Location: 'Zx81 France' Fb group.

Re: Using MCoder2 in EightyOne

Post by XavSnap »

Hi,

Is there any downloadable P file of the original file ? Just to change some routines...

Repeat some display=slow down...
ET1.JPG
Repeat IF command=slow down...
ET2.JPG

Code: Select all

545 GOSUB 8000+INT (RND*6)*2 [0-5]
8000 RETURN...=0 NOTHING TO DO
8002 PRINT...=1
8003 RETRUN
8004 PRINT...=2
8005 RETURN
8006 GOTO 8010...=3 
8007 REM NO RETURN
8008 PRINT...=4
8009 RETURN
8010 PRINT...=5 (3 OR >4)
8011 RETURN
Last edited by XavSnap on Mon Mar 14, 2022 2:04 am, edited 2 times in total.
Xavier ...on the Facebook groupe : "Zx81 France"(fr)
bwinkel67
Posts: 147
Joined: Mon Mar 23, 2020 2:38 am

Re: Using MCoder2 in EightyOne

Post by bwinkel67 »

Oh thanks, I will try that after I get my current attempt to work. So I spent oodles of time trimming down my program and the magic number seems to be just under 4100 bytes. The trick is, since MCODER2 doesn't naturally share variables, that you tease out code that doesn't require any. For me, I have one large routine that prepares the screen, one that fires a laser, one that displays an explosion, all of which don't require any shared information. Even one-liners like printing a scope, takes up less space if you turn it into its own compiled routine and call it via LET L=USR 12345, so that's the trick of continuously shrinking the main driving program.

The final thing I had to do is ensure each of my lines were on the 10's and then remove all trailing 0's so now my code runs from 10 to 315, instead of 100 to 3150. You don't save on the smaller line numbers but do on the GOTO and GOSUB's which shrink by a byte each for the smaller numbers. So now I'm pretty close of having it compiled. I will share the program here when complete...it's my version of Elite that I wrote as a demo program for my Sinclair QL ZX81 emulator: ZXSimulator. On an accelerated QL the emulator runs nice and in turn so does the Elite game within the emulator...but on an unexpanded QL it runs at the same speed as a ZX81 and plods along pretty slowly. So a speed-up on a ZX81 of 3x to 4x would make it really nice and playable.

You can play it online at ZXSimulator.orgfree.com (type: LOAD "WIN1_ELIT_BAS" ... yes, the E is missing since DOSBox can't handle more than 8 characters). That will let you see how it should have run and if you have a brand new machine, the nested emulation of DOSBox -> QLAY -> ZXSimulator will run nice and fast. For the MCODER2 compilation, I did have to get rid of the configuration menu (so only WASD and F for controls) and presently it will just say GAME OVER though I plan to find somewhere to poke an integer to, so I can communicate if you won or lost the game and by how much. What's a good spot to peek/poke to share an integer?
bwinkel67
Posts: 147
Joined: Mon Mar 23, 2020 2:38 am

Re: Using MCoder2 in EightyOne

Post by bwinkel67 »

GCHarder wrote: Sun Mar 13, 2022 10:08 pm I've compiled large programs using XavSnap's emulator (make sure the 8k region is disabled or it will hang).
And also sz81. I tried again last night with a 15k Basic program, Platform Jack, which I posted awhile ago in the games forum. All I did was Poke 16389,255 followed by NEW. I could not get it to compile in EO. I think MCoder may alter some sysvars which causes the hangup.

Hope this helps.

Greg
So the poke 16389,255 followed by NEW doesn't work in EightyOne since when you load in the program (not from a menu but in the emulator, which doesn't do an implied NEW) the 16389 location gets reset to 111 (i.e. PRINT PEEK 16389). I did try that trick and compiled my 8K program and MCODER2 just kept crashing. Note that I saw someone else post that POKE 16389,192 followed by NEW would work, and it didn't for me. As I posted earlier today, I've been teasing my program apart to get it to compile.

I also tried the zx81 emulator with no success...
User avatar
mrtinb
Posts: 1906
Joined: Fri Nov 06, 2015 5:44 pm
Location: Denmark
Contact:

Re: Using MCoder2 in EightyOne

Post by mrtinb »

When you select a file to load in EightyOne, then the emulator resets and start from scratch.

So if you want to load a program, after you have setup RAMTOP, you need to load the file from the tape recorder, and NOT from the File menu.
Martin
https://zx.rtin.be
ZX81, Lambda 8300, Commodore 64, Mac G4 Cube
bwinkel67
Posts: 147
Joined: Mon Mar 23, 2020 2:38 am

Re: Using MCoder2 in EightyOne

Post by bwinkel67 »

Yes, I'm doing all that. However, after the first compile, if you want to load the next code snippet, it just overwrites what you have since MCODER2 is now connected to your program and no longer sitting in memory waiting for a program to load. So my solution is to use EightyOne's tools->BASIC Listing feature and save out the BASIC code, remove the old chunk of BASIC, and copy in the new chunk -- I have 11 chunks, so I have to do that 11 times. (For some reason RAND USR 17281 doesn't always work to remove the BASIC listing).

One weird thing that that method reveals is that MCODER2 is set up to always generate code at 2 REM and what you do is POKE the previous REMs to 1. But you basically have to do that for all previous REMs, so after the 3rd code snippet added, I get the following when saving it to disk:

Code: Select all

0 REM ...
1 REM first MC code snippet
1 REM second MC code snippet
2 REM new code snippet
3 REM MCODER2
300 PRINT "THIRD CODE SNIPPET"
So after that new 3rd code snippet was added and saved, I need to go in and change the duplicate REMs to the following:

Code: Select all

0 REM ...
1 REM first MC code snippet
2 REM second MC code snippet
3 REM new code snippet
4 REM MCODER2
400 PRINT "FOURTH CODE SNIPPET"
...and replace the old code (200 PRINT "THIRD CODE SNIPPET") with the new one (400 PRINT "FOURTH CODE SNIPPET"), load it back into EightyOne, and...this is the painful part...poke to change both 2 REM and 3 REM to be both be 1 REM since MCDOER2 looks for the last 1 REM and then adds 2 REM for the next newest code snippet. If you don't poke the other REM's to be 1, then it inserts the newest code snippet BEFORE your other ones, thus loosing your starting points to each (I mean, I suppose I could try and calculate what they are but either way, it's a pain).

This gets worse with more. I have 11 to compile separately so at one point I have ten REMs all saying 1 REM, right before I compile (LET L=USR 17300):

Code: Select all

0 REM ...
1 REM ...
1 REM ...
1 REM ...
1 REM ...
1 REM ...
1 REM ...
1 REM ...
1 REM ...
1 REM ...
1 REM ...
12 REM MCODER2
1100 PRINT "ELEVENTH CODE SNIPPET"
But to load it into EightyOne via a BASIC listing the above REMs need to be sequential, so I basically have to then do ten POKES to get it to the above state for the next compile (i.e. L=USR 17300) to work. It's been quite a pain but at least it's doable.

Well, I presently am half way there and it all works, but whew, what a pain...
User avatar
mrtinb
Posts: 1906
Joined: Fri Nov 06, 2015 5:44 pm
Location: Denmark
Contact:

Re: Using MCoder2 in EightyOne

Post by mrtinb »

When I need to load and save Basic lines, I use SIMDOS2 which is a RAMdisk. SIMDOS2 requires RAM at 8k-16k, and can use any space above 32k for RAMdisk.

Maybe it can help you. I have not used it together with MCODER2 though.

viewtopic.php?p=37855#p37855
Martin
https://zx.rtin.be
ZX81, Lambda 8300, Commodore 64, Mac G4 Cube
bwinkel67
Posts: 147
Joined: Mon Mar 23, 2020 2:38 am

Re: Using MCoder2 in EightyOne

Post by bwinkel67 »

So I got it compiled, pieced together, and working with my 11 step plan. The game needs work as it now seems too fast to play. I need to try it on my actual TS1000 since I believe the EightyOne emulator runs faster than stock. If it runs closer to half that speed it might make it workable, but as of now, it's not very playable (i.e. too hard). I need to change its behavior: the pirate needs to wiggle less, the controls need to be less sensitive, might need more shield/ammo/fuel, etc. It has some weird bugs in it regarding screen behavior that the original BASIC doesn't...must be an MCODER2 thing I need to figure out.

I'll be doing a video on the steps I had to take to create the MC version (not too bad, just time consuming). I think I mentioned before, for MCODER2, the magic number seems to be at 4100 bytes for the source (in it's original 16K form). Sure would be nice to just compile the entire thing when having 32K of memory but I have not been able to do that. I am using EightyOne 1.26 and none of the RAMTOP pokes worked. I also tried it on zz81 emulator (version 2.3.10) to no avail. I haven't tried the VB81_XuR but that requires installation and I'm always a bit wary of having to install something...plus the installation is in French so I have no idea what I'm agreeing to replace. I also seem to get contradictory comments of "MCODER2 does this and that so it can't work above 16K" vs "I have my large program compiled in MCODER2 no problem" so it's hard to align those...

Attached are both the MC and non-MC version of the game. You'll note that in the MC version you cannot yet set keys and the ending just tells you the game is over, not how many pirates you killed. I also extended the time of the pirate since it runs much faster so you don't just want the pirate to appear and disappear. The game was designed for running slowly in BASIC since it was a demo program for my ZXSimulator, so those kinks need to be ironed out.

Elite.zip
(9.19 KiB) Downloaded 101 times

Thanks for all the help, esp mrtinb!
bwinkel67
Posts: 147
Joined: Mon Mar 23, 2020 2:38 am

Re: Using MCoder2 in EightyOne

Post by bwinkel67 »

Ok, fixed the few bugs and added a delay with the keyboard which kind of improves things. Note that with keys, if you press the same direction a second time, it re-centers the virtual joystick (i.e. putting it to neutral).

Still have one bug that I did a work around. If I have a string variable:

Code: Select all

10 F$="12345"
...and I try to print the part of the string:

Code: Select all

20 PRINT F$(1 To 4)
It prints it as: F123

Not sure why the F appears in there, but the workaround is to make the string one longer and start the slice from 2.

Here it is...starting to play pretty well. Again, EliteMC.p is the machine code version compiled with MCODER2 and Elite.p is the original BASIC version that has a few more features.

Elite.zip
(8.81 KiB) Downloaded 112 times
Fruitcake
Posts: 346
Joined: Wed Sep 01, 2010 10:53 pm

Re: Using MCoder2 in EightyOne

Post by Fruitcake »

bwinkel67 wrote: Mon Mar 14, 2022 2:20 am So the poke 16389,255 followed by NEW doesn't work in EightyOne since when you load in the program (not from a menu but in the emulator, which doesn't do an implied NEW) the 16389 location gets reset to 111 (i.e. PRINT PEEK 16389). I did try that trick and compiled my 8K program and MCODER2 just kept crashing. Note that I saw someone else post that POKE 16389,192 followed by NEW would work, and it didn't for me. As I posted earlier today, I've been teasing my program apart to get it to compile.
I've reproduced the issue you were seeing and so understand where the confusion is coming from.

When you load MCODER2, it sets system variable 16389 to $6F (111) and loads its Merge routine above RAMTOP. The idea is you can now load in a BASIC program and type RAND USR 32462 and MCODER2 is merged into your program at lines 0 to 3. A copy of MCODER2 is initially held in memory at ($6F00) 28416 so the largest BASIC program you can load is about 11K or so if you wish to use the merge facility. After merging, RAMTOP gets set at ($6F00) 28416. Saving out the program to tape, resetting the ZX81 and loading the saved program back in means RAMTOP will be restored to ($8000) 32768 and so extra RAM will be available to the compiler but at the expense of losing the merging ability (but then you no longer need this as your BASIC program is now merged). But since you are using EightyOne, you can completely ignore MCODER2's merge facility and do things in a much simpler way.

To get MCODER2 working with more than 16K RAM, do the following:
- In EightyOne set the RAM to 48K RAM
- LOAD MCODER2
- Using EightyOne's BASIC Listing window, save out as MCODER2.B81
- Reset the ZX81
- LOAD in your BASIC program
- Using EightyOne's BASIC Listing window, save out your program, e.g. YOURPROGRAM.B81
- Using a text editor on your PC, copy the contents MCODER2.B81 and paste it at the start of YOURPROGRAM.B81
- Save the updated YOURPROGRAM.B81 file
- Reset the ZX81
- Type POKE 16389,255
- Type POKE 16388,255
- Type NEW
- Load in YOURPROGRAM.B81 file, e.g. drag/drop into EightyOne or the Tape Manager, etc
- You now have a ZX81 with 48K and your BASIC program with MCODER2 loaded in
- Type RAND USR 17300 to compile

A BASIC program can utilise all the 48K RAM but the key thing is for the display file to never straddle across the 32K boundary; it must either be fully below it or fully above it. The instructions for the Memotech 32K RAM pack describe how you can push the display file above the boundary:

Memotech32K..gif

I'm not sure if MCODER2 automatically guarantees that the display file will never straddle the 32K boundary so you might need to use the Memotech technique to ensure it never does.

As a test of compiling a large BASIC program, I grabbed the original BASIC version of your game and ran MCODER2 on it, replacing each line it complained with any other one it was happy about to keep the program size large and kept doing this until MCODER2 was happy with all the syntax. It then successfully compiled the whole program. I couldn't properly run the compiled game as all the line replacements I had made meant it was performing gibberish logic but it ran enough to prove that this approach works for compiling a larger BASIC program.

When I used MCODER2 back in the 80s I only had 16K RAM and so also struggled to get a good sized BASIC program to compile in one hit. Trying to split it into chunks was painful and so I never really pursued this, so it's interesting to read you've been having success using that approach. Good work! It's nice to see these original utilities still being used.

If only I had more than 16K back then... Still, I did managed to create a few games using just 16K. I still have the compiled forms but sadly no longer have the original BASIC listings for them. One day I'll have to see how feasible it is to reverse engineering a compiled program back into a BASIC listing...
Post Reply