Hello, I'm Restarting ZX81 Programming After... 30 Years

Any discussions related to the creation of new hardware or software for the ZX80 or ZX81
dr beep
Posts: 2080
Joined: Thu Jun 16, 2011 8:35 am
Location: Boxmeer

Re: Hello, I'm Restarting ZX81 Programming After... 30 Years

Post by dr beep »

When it is just 1K you can use the SP as return to start MC. I haven't tried it to make a BASIC loader that will set SP low on machines with more than 1K. With this method you can load over sysvar and use more without any problems.
IanB
Posts: 60
Joined: Mon Jul 27, 2015 5:40 am
Location: Northampton UK

Re: Hello, I'm Restarting ZX81 Programming After... 30 Years

Post by IanB »

dr beep wrote:When it is just 1K you can use the SP as return to start MC. I haven't tried it to make a BASIC loader that will set SP low on machines with more than 1K. With this method you can load over sysvar and use more without any problems.
I think you've just lost me with that. "Use the SP as a return to start MC", does that mean use the value on top of the stack as the call (or jump) to machine code? Or the Stack Pointer register itself holds the address to jump to?

And why does this not work on more than 1K?

Please bear in mind that I am not as advanced in my knowledge as you, so I might need more explanation :)
dr beep
Posts: 2080
Joined: Thu Jun 16, 2011 8:35 am
Location: Boxmeer

Re: Hello, I'm Restarting ZX81 Programming After... 30 Years

Post by dr beep »

IanB wrote:
dr beep wrote:When it is just 1K you can use the SP as return to start MC. I haven't tried it to make a BASIC loader that will set SP low on machines with more than 1K. With this method you can load over sysvar and use more without any problems.
I think you've just lost me with that. "Use the SP as a return to start MC", does that mean use the value on top of the stack as the call (or jump) to machine code? Or the Stack Pointer register itself holds the address to jump to?

And why does this not work on more than 1K?

Please bear in mind that I am not as advanced in my knowledge as you, so I might need more explanation :)
When you load your program you can load a returnaddress over the returnaddress of the SP. After loading the RET is fetched and this can be a direct jump to your MC. This will not work directly on a machine with more memory since SP will be higher in memory. It is not my trick, but used by someone else. I was thinking of a piece of preloader that will set SP lower and then do the actual load.in this way it should work on all machines. However, unlike TAP-emulation on ZX-Spectrum emulators I don't think that ZX81-emulators have a TAP-emulation with multiple data to load. Single load only.

So I haven't got it working yet for >1K.
dr beep
Posts: 2080
Joined: Thu Jun 16, 2011 8:35 am
Location: Boxmeer

Re: Hello, I'm Restarting ZX81 Programming After... 30 Years

Post by dr beep »

As I am thinking, this might be a spectrum-trick.
IanB
Posts: 60
Joined: Mon Jul 27, 2015 5:40 am
Location: Northampton UK

Re: Hello, I'm Restarting ZX81 Programming After... 30 Years

Post by IanB »

I'm afraid you've completely lost me. The Machine Stack is above the BASIC system's GOSUB stack, and I don't see how it can be affected by a standard tape loading operation I'm afraid, since that only loads as far as the top of the Variables area so far as I can see.
User avatar
PokeMon
Posts: 2264
Joined: Sat Sep 17, 2011 6:48 pm

Re: Hello, I'm Restarting ZX81 Programming After... 30 Years

Post by PokeMon »

Okay - didn't expect you to do it this hard way.
You could set stack yourself if you never return to BASIC - anyway this would require code as well, you wouldn't win too much I think.
You maybe do two or three simple POP BC or so to free more stack size depending what is already on. The GOSUB stack marker $3E00 maybe removed with POP as well. So this takes one byte and gives back two bytes per instruction - not a bad deal. ;)

A good idea to see what's going on with EightyOne would be following two procedures:

During development you might use the following instructions at any time or point to debug:
OUT $FD,A (turn off NMI)
HALT

You may place this anywhere to inspect the system and registers, using the "debug" in menu of EO. Please take notice that the ZX-IDE installs only a minimal version of EO which could be without debug feature. In this case you should install the latest version from here:
http://www.chuntey.com/

The second helpful debug information is to use "save memory block" in EO (adress 16384, 1024 bytes) and to inspect this with a good hex editor - I personally like HxD for that. This could be combined with the OUT/HALT feature for optimum debug.

If you really don't use the BASIC system, many variables could be used, some are necessary and some maybe overwritten after loading and starting your program. You may find out yourself as this is part of the fun to program, too. I think you want to learn youself as well about ZX81. 8-)

This is a minimalistic program to start machine code:

Code: Select all

format zx81
;labelusenumeric
;LISTON

        // hardware options to be set and change defaults in ZX81DEF.INC
        MEMAVL     =       MEM_1K         // can be MEM_1K, MEM_2K, MEM_4K, MEM_8K, MEM_16K, MEM_32K, MEM_48K
                                           // default value is MEM_16K
        STARTMODE  EQU     SLOW_MODE       // SLOW or FAST
        DFILETYPE  EQU     AUTO            // COLLAPSED or EXPANDED or AUTO
        STARTUPMSG EQU     '' // any message will be shown on screen after loading, max. 32 chars

        include '..\SINCL-ZX\ZX81.INC'        // definitions of constants

AUTORUN:
RAND USR _hide #start
start:
        LD A,A

        include '..\SINCL-ZX\ZX81DISP.INC'          ; include D_FILE and needed memory areas
VARS_ADDR:
        db 80h
WORKSPACE:
You don't need any REM line and could start coding directly after the RAND USR statement with the first not very useful instruction LD A,A. The _hide option reduces the code further to just display a 0 as starting address while the correct address is stored in the statement. Wasteful Sinclair added the shown address as a character string representation as well as a following floating point value to speed up listings. 0 is the shortest possible numerical string. dr.beep sometimes omits the last $80 character after the displayfile but I found out that this gives problems on real hardware (other than emulator). So I would keep this single byte. Maybe this is an issue of the acoustic loader of the IDE only - not investigated this in a very detail.

The display file consists of 25 NEWLINE chars ($76) when empty. The first is used for synchronization of the video hardware, the other 24 are closing the available 24 char lines with maximum width of 32 chars per line. The display file might be moved in the system variables but never tried this. The AUTORUN label sets the system to automatically execute the RAND USR line. Have fun coding !
Last edited by PokeMon on Fri Jul 31, 2015 10:18 pm, edited 1 time in total.
User avatar
PokeMon
Posts: 2264
Joined: Sat Sep 17, 2011 6:48 pm

Re: Hello, I'm Restarting ZX81 Programming After... 30 Years

Post by PokeMon »

If you have gaps in your code and want better control of it, you might use the following statements:

Code: Select all

instdrv:
        LD      BC,DRVALIGN
        SBC     HL,BC
        EX      DE,HL
        LDIR                    // load video driver routine
        EX      DE,HL
        LD      BC,DRVALIGN
        SBC     HL,BC
        RET

        db $0066 - $ dup(0)     // fill area with nops
This is the resulting listing (which can be get with simple CTRL-F8):

Code: Select all

                                        instdrv:
004F: [004F] 01 20 00                           LD      BC,DRVALIGN
0052: [0052] ED 42                              SBC     HL,BC
0054: [0054] EB                                 EX      DE,HL
0055: [0055] ED B0                              LDIR                    // load video driver routine
0057: [0057] EB                                 EX      DE,HL
0058: [0058] 01 20 00                           LD      BC,DRVALIGN
005B: [005B] ED 42                              SBC     HL,BC
005D: [005D] C9                                 RET
                                        
005E: [005E] 00 00 00 00 00 00 00 00            db $0066 - $ dup(0)     // fill area with nops
 
So you can helpfully add codelines to your free area the db statement will insert the desired bytes with 0 (NOP) to fill up till address $0066 in this example. If the current address is greater db will automatically stop the compiler as a negative value is not allowed here. This code works better than alignments with align which may be used with the power of 2.

Helpful is the assert statement as well which can check your codesize of whole programs or code blocks for example and to warn for crititical size.

Code: Select all

start_zx81:
        OUT     (IOADRLATROM),A // switch rom page to new instance
        OUT     (IOADRNMIOFF),A // switch off NMI during startup of instance
        AND     $07
        CP      $02
        JP      C,$0
        LD      BC,$7FFF
        JP      ZX81_INIT       // initialize instance
align DRVALIGN
.end:
assert start_zx81.end-start_zx81 = DRVALIGN
IanB
Posts: 60
Joined: Mon Jul 27, 2015 5:40 am
Location: Northampton UK

Re: Hello, I'm Restarting ZX81 Programming After... 30 Years

Post by IanB »

Thanks PokeMon, I'm working my way through understanding and familiarising myself with all this :)
IanB
Posts: 60
Joined: Mon Jul 27, 2015 5:40 am
Location: Northampton UK

Re: Hello, I'm Restarting ZX81 Programming After... 30 Years

Post by IanB »

PokeMon,

I'm making progress with ZX-IDE, but I am a bit stuck with something. I want to include a "pre-drawn" display file with my program, so it loads in the screen (from which I can copy data at the start) but I can't figure out how to set this in the ZX-IDE. Can you advise please?

Edit: It's okay, I figured it out :)
User avatar
PokeMon
Posts: 2264
Joined: Sat Sep 17, 2011 6:48 pm

Re: Hello, I'm Restarting ZX81 Programming After... 30 Years

Post by PokeMon »

Just set up a file or data structure, be sure to have a newline after every 24 lines and one additional at start of dfile (25 in all) - a line never exceeds 32 chars, never use chars/bytes with bit 6 set (only printable chars) and set the variable DFILE manually. The demo includes a static variables section which may not be convenient for your purpose - so maybe copy that section into your main file and setup the desired variables manually. 8-)
Post Reply