Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How to carve up ZX Basic into different ORG values
#1
This might be asking a tricky thing to do but :-

GOAL :  
To have main.bas compile at 24576 as main.tap
with the ability to at runtime, call on the functions in the below separate files

Functions.bas compile at last address use above +1 as functions-Bank1.bin
** ZX Basic functions only 

textdata.bas compile at  last address use above +1 as textdata-Bank3.bin
** Mixture of ZX BASIC and ASM functions and data references.

picturedata.bas  compile at last address use above +1 as picturedata-Bank6.bin
** Mixture of ZX BASIC and ASM functions and picture references but uses the 168384 address to load into.

This I am hoping would result in files being created that I can then join them together into one TAP file which can then be loaded via an emulator.
The idea is then to be able switch to the relevant bank # to call the relevant function,.

Issue:
When the main,bas is compiled the compiler insists on functions being accessible at runtime, a very logical thing, so the compile fails as the methods are not in main.bas but in the other *.BIN files.

Is there a way around this?
I was using blank labels which helps a bit but I can't really do this with the functions (I have not tried though)

thanks
:-)
Reply
#2
Hi @RandomiserUsr,

There aren't a direct way to do this, but there is a workarround that I used in CuadragonNext and now in NextDows OS for Next.
In my case, for the ZX Spectrum Next, I load the modules to $8000 at runtime every time I need, but other approaches are possible.

Modules:
Make a Main module at 24576, as you did.
Make a Vars.bas module that uses a vars zone under $8000 and define the vars like:

Code:
dim moduleLoad as ubyte AT $7ff0
dim moduleParameter1 as ubyte at $7ff1
dim moduleParameter2 as ubyte at $7ff2
dim lives as ubyte at $7ff3
Make all the code modules at $8000. Every module shoul include "Vars.bas". In this way you can share variables from one module to other.

The point id call to set moduleLoad var and moduleParameter1, and so on to the desired module.


Main Module:
Code:
sub ExecModule()
  LoadSD("Module."+str(moduleLoad)+".bin",$8000,16384,0)  ' This is for ZX Next and load the "moduleLoad" in $8000

  ' Save ix register and call $8000
asm
   push ix
   call $8000
   pop ix
end asm

end sub

The code modules can be compiled as standard programs at $8000 and return to Basic when ends...
Code:
' The action to executed is defined by moduleParameter and other variables
if moduleParameter1=1 then
   Command1()
else if moduleParameter=2 then
   Command2()
end if

' Before to exit, set moduloLoad to determite the next module to load and the parameters needed
moduleLoad=2
moduleParameter=3

Try this apporach and share results and apprachs!

Sorry for my bad English, I'm spanish!
Duefectu
www.duefectucorp.com
duefectu@sd-a.com
Reply
#3
(05-17-2021, 07:50 PM)Duefectu Wrote: Hi @RandomiserUsr,

There aren't a direct way to do this, but there is a workarround that I used in CuadragonNext and now in NextDows OS for Next.
In my case, for the ZX Spectrum Next, I load the modules to $8000 at runtime every time I need, but other approaches are possible.

Modules:
Make a Main module at 24576, as you did.
Make a Vars.bas module that uses a vars zone under $8000 and define the vars like:

Code:
dim moduleLoad as ubyte AT $7ff0
dim moduleParameter1 as ubyte at $7ff1
dim moduleParameter2 as ubyte at $7ff2
dim lives as ubyte at $7ff3
Make all the code modules at $8000. Every module shoul include "Vars.bas". In this way you can share variables from one module to other.

The point id call to set moduleLoad var and moduleParameter1, and so on to the desired module.


Main Module:
Code:
sub ExecModule()
  LoadSD("Module."+str(moduleLoad)+".bin",$8000,16384,0)  ' This is for ZX Next and load the "moduleLoad" in $8000

  ' Save ix register and call $8000
asm
   push ix
   call $8000
   pop ix
end asm

end sub

The code modules can be compiled as standard programs at $8000 and return to Basic when ends...
Code:
' The action to executed is defined by moduleParameter and other variables
if moduleParameter1=1 then
   Command1()
else if moduleParameter=2 then
   Command2()
end if

' Before to exit, set moduloLoad to determite the next module to load and the parameters needed
moduleLoad=2
moduleParameter=3

Try this apporach and share results and apprachs!

Sorry for my bad English, I'm spanish!
Thank you Duefectu :-)

I will try this out and your English is good  Smile
Reply
#4
(05-17-2021, 07:50 PM)Duefectu Wrote: Hi @RandomiserUsr,

There aren't a direct way to do this, but there is a workarround that I used in CuadragonNext and now in NextDows OS for Next.
In my case, for the ZX Spectrum Next, I load the modules to $8000 at runtime every time I need, but other approaches are possible.

Modules:
Make a Main module at 24576, as you did.
Make a Vars.bas module that uses a vars zone under $8000 and define the vars like:

Code:
dim moduleLoad as ubyte AT $7ff0
dim moduleParameter1 as ubyte at $7ff1
dim moduleParameter2 as ubyte at $7ff2
dim lives as ubyte at $7ff3
Make all the code modules at $8000. Every module shoul include "Vars.bas". In this way you can share variables from one module to other.

The point id call to set moduleLoad var and moduleParameter1, and so on to the desired module.


Main Module:
Code:
sub ExecModule()
  LoadSD("Module."+str(moduleLoad)+".bin",$8000,16384,0)  ' This is for ZX Next and load the "moduleLoad" in $8000

  ' Save ix register and call $8000
asm
   push ix
   call $8000
   pop ix
end asm

end sub

The code modules can be compiled as standard programs at $8000 and return to Basic when ends...
Code:
' The action to executed is defined by moduleParameter and other variables
if moduleParameter1=1 then
   Command1()
else if moduleParameter=2 then
   Command2()
end if

' Before to exit, set moduloLoad to determite the next module to load and the parameters needed
moduleLoad=2
moduleParameter=3

Try this apporach and share results and apprachs!

Sorry for my bad English, I'm spanish!

With this approach is your initial program a NEX or a SNA?

Could you achieve the same end by compiling all the the modules into a NEX and them swapping the banks?
Reply
#5
(05-17-2021, 07:50 PM)Duefectu Wrote: Hi @RandomiserUsr,

There aren't a direct way to do this, but there is a workarround that I used in CuadragonNext and now in NextDows OS for Next.
In my case, for the ZX Spectrum Next, I load the modules to $8000 at runtime every time I need, but other approaches are possible.

Modules:
Make a Main module at 24576, as you did.
Make a Vars.bas module that uses a vars zone under $8000 and define the vars like:

Code:
dim moduleLoad as ubyte AT $7ff0
dim moduleParameter1 as ubyte at $7ff1
dim moduleParameter2 as ubyte at $7ff2
dim lives as ubyte at $7ff3
Make all the code modules at $8000. Every module shoul include "Vars.bas". In this way you can share variables from one module to other.

The point id call to set moduleLoad var and moduleParameter1, and so on to the desired module.


Main Module:
Code:
sub ExecModule()
  LoadSD("Module."+str(moduleLoad)+".bin",$8000,16384,0)  ' This is for ZX Next and load the "moduleLoad" in $8000

  ' Save ix register and call $8000
asm
   push ix
   call $8000
   pop ix
end asm

end sub

The code modules can be compiled as standard programs at $8000 and return to Basic when ends...
Code:
' The action to executed is defined by moduleParameter and other variables
if moduleParameter1=1 then
   Command1()
else if moduleParameter=2 then
   Command2()
end if

' Before to exit, set moduloLoad to determite the next module to load and the parameters needed
moduleLoad=2
moduleParameter=3

Try this apporach and share results and apprachs!

Sorry for my bad English, I'm spanish!
1) You said to make all the variables like this in the VARS.BAS

dim moduleLoad as ubyte AT $7ff0
dim moduleParameter1 as ubyte at $7ff1
dim moduleParameter2 as ubyte at $7ff2
dim lives as ubyte at $7ff3

Which is fine but some further questions:
a) I have several variables that are set up as CONST and set a value, e.g. CONST printwidth as UBYTE = 42
but this can't can't be used due to compiling errors but DIM can be used so not a major problem.
b) I would need to assign all 100+ variables as $7ff0 but having to start $8000 - 100bytes to enable each variable to be allocated a unique address?


2. You said :-
make a Main module at 24576, as you did.
Make a Vars.bas module that uses a vars zone under $8000
Make all the code modules at $8000. Every module shoul include "Vars.bas".

[font=arial, sans-serif]then I get a bit lost with the below section:-[/font]

[font=arial, sans-serif][font=Tahoma, Verdana, Arial, sans-serif]The point id call to set moduleLoad var and moduleParameter1, and so on to the desired module.[/font][/font]
[font=arial, sans-serif][font=Tahoma, Verdana, Arial, sans-serif]Main Module:[/font][/font]
Code:
Code:
sub ExecModule()
LoadSD("Module."+str(moduleLoad)+".bin",$8000,16384,0) ' This is for ZX Next and load the "moduleLoad" in $8000

' Save ix register and call $8000
asm
push ix
call $8000
pop ix
end asm

end sub


a) Are you saying that the above sub routine should be in the Main.bas or in a module-nnn.bas or both?

b) What is LoadSD () ? I don't have this but I do get what this is trying to do i.e. load in the Module.1.bin into $8000, with 16384k

c) The last bit seems to be a mixture of two things.

the code modules can be compiled as standard programs at $8000 and return to Basic when ends...
Code:
Code:
' The action to executed is defined by moduleParameter and other variables
if moduleParameter1=1 then
Command1()
else if moduleParameter=2 then
Command2()
end if

' Before to exit, set moduloLoad to determite the next module to load and the parameters needed
moduleLoad=2
moduleParameter=3

1. the command to run in this module
Q. How to return variables or just use the vars.bas as shared anyway?

2. the setting of the next module to load and parameter - This bit I am not sure how this all fits in with my Main.bas , VARS.bas and Module.nnn.bas ?


Once again thank you for you time.
Reply
#6
There are no magic and universal anwser!  Big Grin

The first thing is what's the platform target: ZX Spectrum 128K or ZX Spectrum Next?
Also the addresses are not fixed at $6000, $8000, etc., every program has his own demands.

1.a.- I have several variables that are set up as CONST and set a value, e.g. CONST printwidth as UBYTE = 42 but this can't can't be used due to compiling errors but DIM can be used so not a major problem.

There should be no problem using CONST in Vars.bas. What error are you getting?

1.b.- I would need to assign all 100+ variables as $7ff0 but having to start $8000 - 100bytes to enable each variable to be allocated a unique address?

It's only a sample, you can also reserve the space in the main module:
Code:
MyVarsSpace:
asm
     defs 1024   ; Put here the desired space
end asm
Put it at the end of the code, or at the start with a GOTO before, avoid the program runs over MySpaceVars

Then, in Vars:
Code:
DIM moduleLoad as ubyte AT @MyVarsSpace
DIM moduleParameter1 as ubyte at @MyVarsSpace+1
DIM moduleParameter2 as ubyte at @MyVarsSpace+2

DIM Lives as ubyte at @MyVarsSpace+3
DIM Score as uinteger at @MyVarSpace+4
DIM Level as ubyte at @MYVarSpace+6
DIM HighScore as uinteger at @MyVarSpace+7
Take a look at the + value, byte/ubyte add 1, integer/uinteger add 2, etc...

2.a.- Are you saying that the above sub routine should be in the Main.bas or in a module-nnn.bas or both?
The ExecModule must be only in Main.bas

2.b.- What is LoadSD () ? I don't have this but I do get what this is trying to do i.e. load in the Module.1.bin into $8000, with 16384k
The LoadSD is a command form NextLib library for ZX Spectrum Next, and you must replace by memory bank swtich or tape/disk load on Spectrum 128K.

2.c.- The last bit seems to be a mixture of two things.
The point are to set moduleLoad and moduleParameterX before to call the next module. Then you must set before returning to main.bas from moduleX.bas
moduleLoad = Next module to load
moduleParameterX = Optional values for the Next module.


3.a -  How to return variables or just use the vars.bas as shared anyway?
Set at least "moduleLoad" before return to main module in MOduleX.bas

3.b.- the setting of the next module to load and parameter - This bit I am not sure how this all fits in with my Main.bas , VARS.bas and Module.nnn.bas ?
This is architecture, not coding!

A sample of all:

Sample program:
  • Main.bas: Main module with ExecModule method. Apart from system initialisation, his only funcion is to load and execute the module.
  • Module1.bas: Intro of the game. IN: moduleLoad=1, OUT: moduleLoad=2 (menu)
  • Module2.bas: Menu of the game. IN: moduleLoad=2, OUT: moduleLoad=depending on the selected option (3-New game, 4-Define keys, 5-Help)
  • Module3.bas: Game Phase 1. IN: moduleLoad=3, OUT: moduleLoad=depending on action (6-Game Phase 2, 10-Game over)
  • Module4.bas: Define keys. IN: moduleLoad=4, OUT: moduleLoad=2
  • Module5.bas: Help of the game. IN: moduleLoad=5, moduleParameter1=module to return (menu or phase if is called inside a gameplay)
  • Module6.bas: Game Phase 2. IN: moduleLoad=6, OUT: moduleLoad=depending on action (7-Game Phase 7, 10-Game over)
  • Module7.bas: Game Phase 3. IN: moduleLoad=7, OUT: moduleLoad=depending on action (8-Game Phase 8, 10-Game over)
  • ....
  • Module10.bas: Game over. IN: moduleLoad=10, OUT: moduleLoad=2 (load menu of the game)

All modules includes Vars:

Code:
#include "Vars.bas"

And all modules set at least moduleLoad value before return, moduleParameters are optional.

Hope it helps!
Duefectu
www.duefectucorp.com
duefectu@sd-a.com
Reply
#7
(05-22-2021, 09:58 AM)Duefectu Wrote: There are no magic and universal anwser!  Big Grin

The first thing is what's the platform target: ZX Spectrum 128K or ZX Spectrum Next?

Also the addresses are not fixed at $6000, $8000, etc., every program has his own demands.

1.a.- I have several variables that are set up as CONST and set a value, e.g. CONST printwidth as UBYTE = 42 but this can't can't be used due to compiling errors but DIM can be used so not a major problem.

There should be no problem using CONST in Vars.bas. What error are you getting?

1.b.- I would need to assign all 100+ variables as $7ff0 but having to start $8000 - 100bytes to enable each variable to be allocated a unique address?
It's only a sample, you can also reserve the space in the main module:
Code:
MyVarsSpace:
asm
     defs 1024   ; Put here the desired space
end asm
Put it at the end of the code, or at the start with a GOTO before, avoid the program runs over MySpaceVars
Then, in Vars:

Code:
DIM moduleLoad as ubyte AT @MyVarsSpace
DIM moduleParameter1 as ubyte at @MyVarsSpace+1
DIM moduleParameter2 as ubyte at @MyVarsSpace+2

DIM Lives as ubyte at @MyVarsSpace+3
DIM Score as uinteger at @MyVarSpace+4
DIM Level as ubyte at @MYVarSpace+6
DIM HighScore as uinteger at @MyVarSpace+7
Take a look at the + value, byte/ubyte add 1, integer/uinteger add 2, etc...


2.a.- Are you saying that the above sub routine should be in the Main.bas or in a module-nnn.bas or both?
The ExecModule must be only in Main.bas

2.b.- What is LoadSD () ? I don't have this but I do get what this is trying to do i.e. load in the Module.1.bin into $8000, with 16384k
The LoadSD is a command form NextLib library for ZX Spectrum Next, and you must replace by memory bank swtich or tape/disk load on Spectrum 128K.

2.c.- The last bit seems to be a mixture of two things.
The point are to set moduleLoad and moduleParameterX before to call the next module. Then you must set before returning to main.bas from moduleX.bas
moduleLoad = Next module to load
moduleParameterX = Optional values for the Next module.


3.a -  How to return variables or just use the vars.bas as shared anyway?
Set at least "moduleLoad" before return to main module in MOduleX.bas

3.b.- the setting of the next module to load and parameter - This bit I am not sure how this all fits in with my Main.bas , VARS.bas and Module.nnn.bas ?
This is architecture, not coding!

A sample of all:

Sample program:
  • Main.bas: Main module with ExecModule method. Apart from system initialisation, his only funcion is to load and execute the module.
  • Module1.bas: Intro of the game. IN: moduleLoad=1, OUT: moduleLoad=2 (menu)
  • Module2.bas: Menu of the game. IN: moduleLoad=2, OUT: moduleLoad=depending on the selected option (3-New game, 4-Define keys, 5-Help)
  • Module3.bas: Game Phase 1. IN: moduleLoad=3, OUT: moduleLoad=depending on action (6-Game Phase 2, 10-Game over)
  • Module4.bas: Define keys. IN: moduleLoad=4, OUT: moduleLoad=2
  • Module5.bas: Help of the game. IN: moduleLoad=5, moduleParameter1=module to return (menu or phase if is called inside a gameplay)
  • Module6.bas: Game Phase 2. IN: moduleLoad=6, OUT: moduleLoad=depending on action (7-Game Phase 7, 10-Game over)
  • Module7.bas: Game Phase 3. IN: moduleLoad=7, OUT: moduleLoad=depending on action (8-Game Phase 8, 10-Game over)
  • ....
  • Module10.bas: Game over. IN: moduleLoad=10, OUT: moduleLoad=2 (load menu of the game)
All modules includes Vars:
Code:
#include "Vars.bas"

And all modules set at least moduleLoad value before return, moduleParameters are optional.

Hope it helps!

Than you very much for the detailed explanation which makes things clearer for me now.  Smile

The target platform is ZX Spectrum 128K

Have a great weekend
Reply
#8
And only load from tape, .tap, right?

Do you wan't dinamic loading? When finish the level 1 load level 2 from tape?

Or do you want to load all in memory and switch banks?
Duefectu
www.duefectucorp.com
duefectu@sd-a.com
Reply
#9
(05-22-2021, 06:48 PM)Duefectu Wrote: And only load from tape, .tap, right?

Do you wan't dinamic loading? When finish the level 1 load level 2 from tape?

Or do you want to load all in memory and switch banks?

Loading into memory and switch banks?
Reply
#10
You don't need to keep to the memory addresses I have indicated before.
You should prepare a memory map where you should place everything, first as a provisional map and then fit the pieces gradually, taking into account that in Boriel Basic it is very easy to change the compilation address (ORG).

First define the modules, for example:
- Main module
- Vars memory
- Game modules (dynamic loading)
- Sprites
- Tiles
- Music (IM2 player)?

Then place into memory, with a first approach:
$6000 - Main module
$7000 - Vars
$8000 - Game modules (dynamic loading)
$c000 - Sprites
$d000 - Tiles
$e000 - IM2 music player

Start to make modules and adjust the memory to fit the modules, for example:
$6000 - Main module
$7e00 - Vars
$8100 - Game modules (dynamic loading)
$c100 - Sprites
$d100 - Tiles
$e100 - IM2 music player

Hope it helps!
Duefectu
www.duefectucorp.com
duefectu@sd-a.com
Reply
#11
(05-26-2021, 07:57 PM)Duefectu Wrote: You don't need to keep to the memory addresses I have indicated before.
You should prepare a memory map where you should place everything, first as a provisional map and then fit the pieces gradually, taking into account that in Boriel Basic it is very easy to change the compilation address (ORG).

First define the modules, for example:
- Main module
- Vars memory
- Game modules (dynamic loading)
- Sprites
- Tiles
- Music (IM2 player)?

Then place into memory, with a first approach:
$6000 - Main module
$7000 - Vars
$8000 - Game modules (dynamic loading)
$c000 - Sprites
$d000 - Tiles
$e000 - IM2 music player

Start to make modules and adjust the memory to fit the modules, for example:
$6000 - Main module
$7e00 - Vars
$8100 - Game modules (dynamic loading)
$c100 - Sprites
$d100 - Tiles
$e100 - IM2 music player

Hope it helps!
Thanks again - I will try this approach out (though it won't have any sprites or music, just text and graphics)
Reply


Forum Jump:


Users browsing this thread: 2 Guest(s)