Block save / load
Re: Block save / load
This is an interesting thread.
Is a long time that I was thinking that in order to fully (at least to the maximum extent) utilize the 1K memory it would be good to have a extremely small piece of code that (also reusing the standard load routines) could load programs. It means that first you would load a "standard program" that is the loader, than this program will allocate itself in the last bytes of memory and then load the program itself.
Advantages:
1. will load from 4000h instead of 4009h allowing to immediately fill this space with data
2. will allow immidiate utilization and filling of system variables needed by BASIC (program will start immediately the machine code)
3. will avoid the basic program skeleton to start the machine code
4. if shor enough will probably load even more bytes (standard loader do not fully load till the very 1K end)
The loader program initiation can be articulated since it will be rewritten, just the final loading part should be very small. This mean for example that can evaluate ROM versions and put correct addresses if needed, or setup additional structures/register values before jumping to the final load.
Is a long time that I was thinking that in order to fully (at least to the maximum extent) utilize the 1K memory it would be good to have a extremely small piece of code that (also reusing the standard load routines) could load programs. It means that first you would load a "standard program" that is the loader, than this program will allocate itself in the last bytes of memory and then load the program itself.
Advantages:
1. will load from 4000h instead of 4009h allowing to immediately fill this space with data
2. will allow immidiate utilization and filling of system variables needed by BASIC (program will start immediately the machine code)
3. will avoid the basic program skeleton to start the machine code
4. if shor enough will probably load even more bytes (standard loader do not fully load till the very 1K end)
The loader program initiation can be articulated since it will be rewritten, just the final loading part should be very small. This mean for example that can evaluate ROM versions and put correct addresses if needed, or setup additional structures/register values before jumping to the final load.
Re: Block save / load
My 1K model to code ASM has start of machinecode all over sysvar so no bytes are lost on sysvar and printerbuffer. Even the end of the BASIC-line and the REM for your machinecodeline are skipped.marste wrote: ↑Fri Apr 26, 2024 5:22 pm This is an interesting thread.
Is a long time that I was thinking that in order to fully (at least to the maximum extent) utilize the 1K memory it would be good to have a extremely small piece of code that (also reusing the standard load routines) could load programs. It means that first you would load a "standard program" that is the loader, than this program will allocate itself in the last bytes of memory and then load the program itself.
Advantages:
1. will load from 4000h instead of 4009h allowing to immediately fill this space with data
2. will allow immidiate utilization and filling of system variables needed by BASIC (program will start immediately the machine code)
3. will avoid the basic program skeleton to start the machine code
4. if shor enough will probably load even more bytes (standard loader do not fully load till the very 1K end)
The loader program initiation can be articulated since it will be rewritten, just the final loading part should be very small. This mean for example that can evaluate ROM versions and put correct addresses if needed, or setup additional structures/register values before jumping to the final load.
Re: Block save / load
With "standard load" machine code can be written all over the sysvar not used by BASIC intepreter (that has to start after load finish). #2dr beep wrote: ↑Sat Apr 27, 2024 10:17 amMy 1K model to code ASM has start of machinecode all over sysvar so no bytes are lost on sysvar and printerbuffer. Even the end of the BASIC-line and the REM for your machinecodeline are skipped.marste wrote: ↑Fri Apr 26, 2024 5:22 pm ...
Advantages:
1. will load from 4000h instead of 4009h allowing to immediately fill this space with data
2. will allow immidiate utilization and filling of system variables needed by BASIC (program will start immediately the machine code)
3. will avoid the basic program skeleton to start the machine code
4. if shor enough will probably load even more bytes (standard loader do not fully load till the very 1K end)
...
Moreover, there should be the space (even if on sysvars, little and very optimized) of this BASIC preamble to start the ASM program. #3
And regarding #4 I checked and standard load seems cannot go after 0x43BE, meaning 66 bytes less than theoretical maximum of 0X43FF (to be added to the first 9 of #1).
PS: surely the bytes can be used after the start of the program, but with the loader you can immediately fill them with desired data or code
Re: Block save / load
I had hoped to have a small loader that would allow loading more data in a 1K machine. Now bound on around 949 bytes.
Alas, this routine is way too large to have use in 1K. My optimized model is more effective on a 1K model.
Alas, this routine is way too large to have use in 1K. My optimized model is more effective on a 1K model.
Re: Block save / load
I have at the moment no means to test it (my dev environment is broken), but the following program should be able to fully load 1008 bytes into memory (from 0x4000 to 0x4400 - 16 bytes)...
The block to be load should be saved with standard routines and should be equal or bigger than 1008 bytes (if bigger the remaining part will not be loaded).
Note that when load routine stops the first target loader instruction (call IN_BYTE) is already damaged.
The block to be load should be saved with standard routines and should be equal or bigger than 1008 bytes (if bigger the remaining part will not be loaded).
Note that when load routine stops the first target loader instruction (call IN_BYTE) is already damaged.
Code: Select all
SET_FAST equ 0x2E7
IN_BYTE equ 0x34C
TARGET_LOAD equ 0x4400 + LOAD_PROG_BEG - LOAD_PROG_END
MEMORY_END equ 0x4400
PROGRAM_START equ TARGET_LOAD - 2 ; this will allow 3 bytes instruction
; but can be moved anywhere
START:
call SET_FAST ; load operations to be managed in FAST mode
ld hl, 0x4400 ; cleanup and put stack at the very end of memory
ld sp, hl ; /
ld hl, 0x4000 ; start loading data at 4000h
ld hl, LOAD_PROG_BEG ; relocate loader to end of memory
ld de, TARGET_LOAD ; /
push de ; /
ld bc, LOAD_PROG_END - LOAD_PROG_BEG ; /
ldir ; _/
pop de ; load up to TARGET_LOAD
jp TARGET_LOAD ; start loading
LOAD_PROG_BEG: ; this label will be at "TARGET_LOAD:" address
call IN_BYTE ; ROM routine IN-BYTE loads a byte
ld (hl), c ; insert assembled byte in memory
or a ; verify if end reached
sbc hl, de ; /
add hl, de ; /
jr nz, LOAD_PROG_START ; (relocatable jump)
jp PROGRAM_START ; program should go into SLOW mode if needed
db 0, 0, 0, 0 ; stack space
LOAD_PROG_END:
Re: Block save / load
The program itself is over 40 bytes so you can never load 1008 bytes on a 1K machine.marste wrote: ↑Tue Apr 30, 2024 3:13 am I have at the moment no means to test it (my dev environment is broken), but the following program should be able to fully load 1008 bytes into memory (from 0x4000 to 0x4400 - 16 bytes)...
The block to be load should be saved with standard routines and should be equal or bigger than 1008 bytes (if bigger the remaining part will not be loaded).
Note that when load routine stops the first target loader instruction (call IN_BYTE) is already damaged.
Code: Select all
SET_FAST equ 0x2E7 IN_BYTE equ 0x34C TARGET_LOAD equ 0x4400 + LOAD_PROG_BEG - LOAD_PROG_END MEMORY_END equ 0x4400 PROGRAM_START equ TARGET_LOAD - 2 ; this will allow 3 bytes instruction ; but can be moved anywhere START: call SET_FAST ; load operations to be managed in FAST mode ld hl, 0x4400 ; cleanup and put stack at the very end of memory ld sp, hl ; / ld hl, 0x4000 ; start loading data at 4000h ld hl, LOAD_PROG_BEG ; relocate loader to end of memory ld de, TARGET_LOAD ; / push de ; / ld bc, LOAD_PROG_END - LOAD_PROG_BEG ; / ldir ; _/ pop de ; load up to TARGET_LOAD jp TARGET_LOAD ; start loading LOAD_PROG_BEG: ; this label will be at "TARGET_LOAD:" address call IN_BYTE ; ROM routine IN-BYTE loads a byte ld (hl), c ; insert assembled byte in memory or a ; verify if end reached sbc hl, de ; / add hl, de ; / jr nz, LOAD_PROG_START ; (relocatable jump) jp PROGRAM_START ; program should go into SLOW mode if needed db 0, 0, 0, 0 ; stack space LOAD_PROG_END:
Re: Block save / load
The loader routine is just 17 bytes ("_BEG" to "_END"), and it is relocated to the end of the memory at the program start. Everything else is rewritten as all the rest of the memory during the load process.
And become even 16 bytes because the loader stop when it starts overwriting itself (for now just the first byte).
Could become 15 bytes (removing "or a" instruction) if carry is always reset (or set) on the BYTE_IN routine exit: to be checked if possible.
And I'm pretty sure that you and few others here can even improve it
PS: in the process of studying the internal rom LOAD routine I added more comments to this part of the ROM disassembly; in case someone is interested here the link https://github.com/stevexyz/ZX-81-ROMS/ ... s/zx81.asm
PPS: I've just noticed a typo "jr nz, LOAD_PROG_START" should be read "jr nz, LOAD_PROG_BEG"!
And become even 16 bytes because the loader stop when it starts overwriting itself (for now just the first byte).
Could become 15 bytes (removing "or a" instruction) if carry is always reset (or set) on the BYTE_IN routine exit: to be checked if possible.
And I'm pretty sure that you and few others here can even improve it
PS: in the process of studying the internal rom LOAD routine I added more comments to this part of the ROM disassembly; in case someone is interested here the link https://github.com/stevexyz/ZX-81-ROMS/ ... s/zx81.asm
PPS: I've just noticed a typo "jr nz, LOAD_PROG_START" should be read "jr nz, LOAD_PROG_BEG"!
Re: Block save / load
I am gonna try to make a universal model to start coding in it.marste wrote: ↑Tue Apr 30, 2024 12:50 pm The loader routine is just 17 bytes ("_BEG" to "_END"), and it is relocated to the end of the memory at the program start. Everything else is rewritten as all the rest of the memory during the load process.
And become even 16 bytes because the loader stop when it starts overwriting itself (for now just the first byte).
Could become 15 bytes (removing "or a" instruction) if carry is always reset (or set) on the BYTE_IN routine exit: to be checked if possible.
And I'm pretty sure that you and few others here can even improve it
PS: in the process of studying the internal rom LOAD routine I added more comments to this part of the ROM disassembly; in case someone is interested here the link https://github.com/stevexyz/ZX-81-ROMS/ ... s/zx81.asm
PPS: I've just noticed a typo "jr nz, LOAD_PROG_START" should be read "jr nz, LOAD_PROG_BEG"!
Most times the screen is compressed enough I can copy routines over sysvar and decompress, but my latest game had no room for that.
This could add a lot.
Re: Block save / load
I was thinking of this loader:
where the loaded code would load a RET over LOAD_PROG_BEG
and START is the start in the loaded program.
Gonna give it a try.
Code: Select all
START:
call SET_FAST ; load operations to be managed in FAST mode
ld sp, #4400-2 ; /
ld hl, 0x4000 ; start loading data at 4000h
ld hl, LOAD_PROG_BEG ; relocate loader to end of memory
ld de, TARGET_LOAD ; /
push de ; /
ld bc, LOAD_PROG_END - LOAD_PROG_BEG ; /
ldir ; _/
ret
LOAD_PROG_BEG: ; this label will be at "TARGET_LOAD:" address
call IN_BYTE ; ROM routine IN-BYTE loads a byte
ld (hl), c ; insert assembled byte in memory
jr LOAD_PROG_BEG ; (relocatable jump)
db 0, 0, 0, 0 ; stack space
dw start
LOAD_PROG_END:
and START is the start in the loaded program.
Gonna give it a try.
Re: Block save / load
So I have the loader starting, but how do I built my datablock to load?
I am using EightyOne to test the program.
Who can help with a working exemple?
The block to load is then 1010 bytes when my idea is working where at the end the stack will get a few more bytes.
I am using EightyOne to test the program.
Who can help with a working exemple?
The block to load is then 1010 bytes when my idea is working where at the end the stack will get a few more bytes.