ZXSimulator

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

Re: ZXSimulator

Post by bwinkel67 »

NormanDunbar wrote:I gave it a try out, not bad!
Cool, thanks for giving it a go.
NormanDunbar wrote:Question, when I ran the test_bas program, it does give a checkerboard pattern, but it doesn't look like the old ZX-81 checkerboard patter I remember, I wonder if it's correct?
I spent a considerable amount of time insuring that each character is exactly the same, pixel-for-pixel, to the ZX80/81. I did run it side-by-side to the EightOne emulator and got the same characters. So they should be the same. You can run an online web one to quickly see they align:

http://www.zx81stuff.org.uk/zx81/jtyone.html
NormanDunbar wrote:I did a quick test too, printing all the ZX-81 characterset from 0 to 255, this is what I got but I see none of the special "graphics" characters in there, should I have seen them, or is that a "still to come"?
The character translations are all in there but BASIC isn't completely hooked into that part yet. So if you did a loop where you try to generate them on the fly (I forget what the ZX81 BASIC keyword is for that) that likely would give you "?" when it doesn't understand. What would work is to have each character separately in a PRINT:
  • In EightyOne, write a simple BASIC program composed of a single PRINT
  • Have each of the 128 characters generated in that PRINT statement
  • Save the program as a .wav file
  • Convert it to a .p file
  • Use zxtools to grab the text file and save it
  • Load that into the ZXSimulator and run it...voila, you will see all 128 ZX characters
The other way is to do it in a plain old text editor using the ASCII equivalents (i.e. the \ and % prefixes). I will do both later today to demonstrate.

BTW, the ZX81's character mapping is a little funky and I haven't dived into that yet either but in the end I won't be tying in the keywords. So I will only worry about 0-63, 118, and 128-191:
  • The character set has 64 unique glyphs present at code points 0–63. With the most significant bit set the character is generated in inverse video; corresponding to code points 128–191. These 128 values are the only displayable ones allowed in the video memory (known as the display file). The remaining code points (64–127 and 192–255) are used as control characters such as 118 for newline, or uniquely to Sinclair BASIC for keywords, while some are unused.


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

Re: ZXSimulator

Post by bwinkel67 »

Oh boy is the ZXSimulator slow on an unexpanded QL. It currently depends on how many characters the PRINT is trying to print (also not good). So somewhere between 3.5 to 6 times slower for some tests I ran compared to a ZX81 (assuming all the ZX81 emulators run at real-time, not faster). So I have my work cut out for me.

Note that the base QL vs base ZX81 runs only twice as fast comparing the same BASIC program (code comparison below gives 2.9 seconds on QL and 5.7 seconds on ZX81) so that is a bit depressing. I used the online ZX81 (which runs the same speed as EightOne) and had QLAY2 set with speed=200 and delay=1000 (which gives about unexpanded QL performance). I will eventually do the timings on an actual ZX81 and my QL.
10 for i=1 to 13
20 FOR J=1 TO 15
30 PRINT "HI";
40 NEXT J
50 PRINT
60 NEXT I


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

Re: ZXSimulator

Post by bwinkel67 »

The good news, when comparing the ZX81 to my original BASIC interpreter that uses the QL character set, the timing comparison isn't so bad. With the program below using the unexpanded QL settings on QLAY2 (speed 200 and delay 1000) I get for an input value of 25:
  • 1:05 seconds on the ZX81
  • 1.87 seconds on my BASIC interpreter (cl)
  • *cough* 16 seconds on the ZXSimulator (zx)

Code: Select all

10 print "Enter number: ";
15 input a
20 if a = 0 then goto 35
25 for i = 1 to a: print "Hello World. ";
30 goto 10
So generating the character set via graphics calls is very problematic. I will need to find a better solution then plotting it via block function. So perhaps I'll need to see how to redefine the 128 characters that I use for the ZX. Maybe initially I can use the text characters (a little difference in appearance) and just plot the graphics ones).


User avatar
NormanDunbar
Forum Moderator
Posts: 2273
Joined: Tue Dec 14, 2010 9:04 am
Location: Leeds, West Yorkshire, UK
Contact:

Re: ZXSimulator

Post by NormanDunbar »

If you can define a font for the characters you need, you can set a channel to use it as well as setting the x and y increments.

https://superbasic-manual.readthedocs.i ... -font.html

Cheers,
Norm.


Why do they put lightning conductors on churches?
Author of Arduino Software Internals
Author of Arduino Interrupts

No longer on Twitter, find me on https://mastodon.scot/@NormanDunbar.
Derek_Stewart
Font of All Knowledge
Posts: 3957
Joined: Mon Dec 20, 2010 11:40 am
Location: Sunny Runcorn, Cheshire, UK

Re: ZXSimulator

Post by Derek_Stewart »

Hi,

I did this, define a font for converting ZX Spectrum software to the QL.

Dilwyn did some excellent articles in QL Today v13 i2,3,4 PDF available in THE Distrubution.


Regards,

Derek
User avatar
NormanDunbar
Forum Moderator
Posts: 2273
Joined: Tue Dec 14, 2010 9:04 am
Location: Leeds, West Yorkshire, UK
Contact:

Re: ZXSimulator

Post by NormanDunbar »

NormanDunbar wrote:If you can define a font for the characters you need, you can set a channel to use it as well as setting the x and y increments.

https://superbasic-manual.readthedocs.i ... -font.html
Sorry, I forgot the link to the font format. It's at https://superbasic-manual.readthedocs.i ... dix10.html.


Cheers,
Norm.


Why do they put lightning conductors on churches?
Author of Arduino Software Internals
Author of Arduino Interrupts

No longer on Twitter, find me on https://mastodon.scot/@NormanDunbar.
User avatar
bwinkel67
QL Wafer Drive
Posts: 1196
Joined: Thu Oct 03, 2019 2:09 am

Re: ZXSimulator

Post by bwinkel67 »

NormanDunbar wrote:
NormanDunbar wrote:If you can define a font for the characters you need, you can set a channel to use it as well as setting the x and y increments.

https://superbasic-manual.readthedocs.i ... -font.html
Sorry, I forgot the link to the font format. It's at https://superbasic-manual.readthedocs.i ... dix10.html.


Cheers,
Norm.
Great, thanks for the resources. I will eventually need to go this route. I tried optimizing my code with some success, and it was fun optimizing it after getting around the idiosyncrasies of small C.


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

Re: ZXSimulator

Post by bwinkel67 »

So I sped up the current version by a factor of 2, getting the time down from 16 to 8 seconds on a standard QL. It's now about 6 times slower than the ZX81 when printing lots of characters though without I/O it should be the same speed.

I spent a ton of time trying to figure out how Digital 'C' does multidimensional arrays and finally gave up since it didn't match up to its documentation. Instead I strung out a long array to capture all 275 bytes of bitmap and then access it with a somewhat faster map. Also, removing multiplication and division wherever I could in critical loops helped tremendously.

It's not where I want it to be speed wise but it was fun figuring out ways to optimize code without resorting to external stuff like replacing the default font, etc. I will have to go that route to make it run real-time -- but at least I know an unexpanded QL will be able to do that. I will also have to do a little more work on the actual interpreter since it does things the ZX81 doesn't do and it is missing a bunch of functions, etc. Presently it's about 35K in size so trying to keep size in mind since I want it to run on a bare bone QL. Need to figure out how to get rid of some of those Digital C artifacts too (like the cursor which doesn't seem to disappear with cursoff().

Here is the latest version. I fixed the screen so it looks more like a ZX81. Before I conform the BASIC I think I'll implement the AT command so I can do some old school graphics.
zx.zip
(21.54 KiB) Downloaded 109 times
Screen shot:
ZXSimulator.png


User avatar
NormanDunbar
Forum Moderator
Posts: 2273
Joined: Tue Dec 14, 2010 9:04 am
Location: Leeds, West Yorkshire, UK
Contact:

Re: ZXSimulator

Post by NormanDunbar »

Hi Bwinkel67,

your version of Digital C - is it standard edition or Special Edition? The reason I ask is because SE has the ability to call trap and vector code (Assembly language) and I think it should be a simple task to use a font on your main channel to try to speed up the font drawing of characters - you would be using the characters directly rather than having to "block" them out all the time.

Something like this, which I hasten to add is off the top of my head and very untested:

Code: Select all

unsigned char zx81_font[] = { 
    0x00,        /* What is the first character? */
    0x3f,        /* Number of characters minus 1 */
    0xnn, 0xnn, 0xnn, 0xnn, 0xnn, 0xnn, 0xnn, 0xnn, 0xnn, 
    0xnn, 0xnn, 0xnn, 0xnn, 0xnn, 0xnn, 0xnn, 0xnn, 0xnn, 
    ...
};     


Those are the byte data for your font. 64 characters, starting at character 0, each with 9 bytes of data.

To set that font into a channel, you need the font address, the channel id (that's the QDOS channel ID, not a FILE * etc) and a trap3 instruction. You would set up the following registers in the src_reg[] array:

Code: Select all

D0 = 0x25        // SD_FOUNT
D3 = -1            // Timeout
A0 = channel id 
A1 = makeabs(zx81_font)
A2 = 0
Something like the following:

Code: Select all

long src_reg[8];
long ret_reg[8];

#define D0 0
#define D3 3
#define A0 4
#define A1 5
#define A2 6
#define SD_FOUNT 0x25;

src_reg[D0] = SD_FOUNT;
src_reg[D3] = -1;
src_reg[A0] = channel_id;
src_reg[A1] = _makeabs(zx81_font);
src_reg[A2] = 0;

trap3(src_reg, ret_reg);
if (ret_reg[D0] != 0) {
    // Handle oops here.
}
It seems that addresses in Digital C SE are relative to the A6 register, for QDOS they need to be absolute, hence the call to _makeabs() to convert the relative address for the font data into an absolute address for the trap3 call.

Hope this helps/works.

Now the problem is that we need to get the font x and y increments adjusted, that needs an SD_EXTOP call, which is also a trap3 call, but not quite so easy. It need an assembly code routine to load the bytes into the SD_XINC and SD_YINC bytes in the channel definition block.


Cheers,
Norm.


Why do they put lightning conductors on churches?
Author of Arduino Software Internals
Author of Arduino Interrupts

No longer on Twitter, find me on https://mastodon.scot/@NormanDunbar.
User avatar
bwinkel67
QL Wafer Drive
Posts: 1196
Joined: Thu Oct 03, 2019 2:09 am

Re: ZXSimulator

Post by bwinkel67 »

NormanDunbar wrote:Hi Bwinkel67,

your version of Digital C - is it standard edition or Special Edition? The reason I ask is because SE has the ability to call trap and vector code (Assembly language) and I think it should be a simple task to use a font on your main channel to try to speed up the font drawing of characters - you would be using the characters directly rather than having to "block" them out all the time.
...
Cheers,
Norm.
Thank you for the info. Yes, I'm using the Special Edition and have used traps in my terminal program so I will look into that. Is there a way I can get to the entire QL screen? If so, couldn't I just calculate where each character should be and then dump the byte sequence for the font to the screen directly? That would take care of the row/column issue. It would likely break a bunch of software like a pointer environment, me thinks.

Here is an updated version with 4 sample programs (using the ZXText2P graphics mapping to ASCII). I got rid of more redundant/inefficient code in the character printing functions but I only gained a little under 2% so nothing ground breaking. I improved the screen by adding a border so when the background is white it'll show better. Also moved it and resized the window to give optimal output for a JSU/F2 rom (my setup is JSU and I'd like it to work in TV mode though I can run it in monitor mode as well). The one difference is I don't show row 23 which seems to be a wasted row (buffer between output and command line) for plain BASIC programs. Not sure if machine code could access it but I just don't have the space for it if I want to keep it fully visible under JSU/F2 and the simulator won't support machine code (since it's not an emulator).
zx.zip
(22.15 KiB) Downloaded 114 times
It doesn't fully support all the ZX81 BASIC yet but does add a "QUIT" command so you can leave the simulator and CTRL-C stops a program execution. Next I'll focus on fine tuning BASIC to more match the ZX81 BASIC. Presently it allows for more SuperBASIC things which I may get rid of (if it remains it won't interfere with running ZX81 BASIC code but it might be nice to have a one-to-one mapping). I'll also add the "EDIT" feature and will start adding error codes instead of printing out error messages. I may eventually add a side menu with configuration options: maybe allow users to specify different colors for groups of characters like inverse character set, graphics set and inverse graphics set -- sort of a cheap way to add color to ZX81 games -- and if I can't easily solve the speed issue maybe add a less-compatibility mode that will use the built-in QL character set and intersperse it with ZX81 graphics (all to be determined).


Post Reply