castingflame wrote:....I just used ORG 0x2000 (or what ever the dot command location should be).
There's no need for any ORG. "-subtype=dot" sets up a memory map with org already set to 0x2000. Instead place your code in "SECTION code_user". This will place it in that container and the memory map will have that container at 0x2000.
I am building a little hardware device for the Next and the dot command will be used for my testing purposes only. Obviously it will be a very valuable for me to be able to write them.
Very nice. Yes and they're fairly easy to do... you just have to get over that hump.
Perhaps TMI which you can skip...
There are several dot command variations in z88dk (and we have to update them because Garry has been making changes in NextOS). The one you're using with "-subtype=dot" is the original 8k-limited one from esxdos and is the one that everyone else is using. In z88dk there are a couple more "-subtype=dotx" where you have one piece in the 8k area and one piece in main memory; this one loads itself and checks that ramtop is low enough to run or else errors out with a message. This allows dot commands to be fairly large but it uses some of basic's memory to run. Another is "-subtype=dotn" which would be a native zx next dot format. This one requests memory pages from NextOS and loads your program into those. It's the same as dotx except none of basic's memory is used. "dot" and "dotx" are compatible with original esxdos and can run on other machines with esxdos. "dotn" would be NextOS only. You can also launch the zx next in 48k or 128k spectrum mode from the boot menu. These are systems that run esxdos. "dotn" or dot commands written assuming NextOS present cannot run on the zx next in these modes. However the dot commands are stored in the same place on the sd card so you can accidentally run them from 48k/128k and cause crashes. You can end up in a situation where you have NextOS only dot commands that cannot be run from these modes. So we provide a solution for that too... you can assemble/compile the same source code into two different versions of the same dot command, one for esxdos and one for NextOS. Then a bit of code in front can choose the version to run depending on whether NextOS is present. Then you can have the same dot command running in all modes. The NextOS version can usually be made better.
----
Anyway, a little more info on "-subtype=dot" starting with your compile line. I will throw you in the deep end here showing all the machinery behind the curtain but the aim is mainly to let you know how things work. The next part I'll show just "how to do it".
zcc +zxn -vn -startup=31 -clib=sdcc_iy mm.asm -o mm -subtype=dot -create-app
"-startup" chooses the startup code by number. "-clib" chooses library (and c compiler if used). "-subtype" can modify the startup number and chooses output type for "-create-app".
The first thing zcc does is look up the machine configuration "zxn.cfg" in lib/config:
https://github.com/z88dk/z88dk/blob/mas ... ig/zxn.cfg
Here it finds out what clib and subtype do. As you can see it adds more options to the compile line. It's not really too important what's there; it's just the machinery that z88dk uses to target lots of different machines. For "-subtype=dot" you can see "-startupoffset=0x100". This means 0x100 is going to be added to your "-startup" number and this will change which crt startup code your compile uses to one suitable for dot commands (and this offset is only done for dot commands at this time).
The compile line above chooses crt31 but the subtype changes that to 31+256=287.
The crts for the zx next are numbered 0-31 right now with this offset added to choose a crt with the same characterists as these 0-31 but for dot commands. The difference will be in the memory map (org 0x2000) and the start and exit code. The crt has to ensure things are safe to return to basic (save IY, HL', SP) and the exit code has to restore basic state and make sure the return values are what's expected by esxdos. "dotn" type has to allocate nextos pages on start and deallocate on exit, etc.
There are many different crts for convenience. They mainly differ by what text input and text output streams are present.
( the final crt number is "__STARTUP" in
https://github.com/z88dk/z88dk/blob/mas ... asm.m4#L41 )
crt0 has a text output stream that is the familiar 32x24 spectrum resolution with fixed with 8x8 fonts.
crt8 uses the standard 256x192 spectrum display but uses proportional font printing using fzx.
crt16 has a text output stream for the timex 512x192 mode using fixed with 8x8 fonts to the text resoluton is 64x24.
.. and so on.
The goal is to support all of the next's screen modes. These canned crts set up one text output stream (on stdout) and are there for convenience but you can set up your own set of text output streams and can have several text output windows set up possibly using different display resolutions. On the next, it's easy to split the display into different modes using the copper or line interrupts.
All z88dk code in the newlib is independent of the rom so it will all work as dot commands or if you decide to page out the rom and put your own code in the bottom 16k. There is one exception:
crt30 which uses rst$10 to print. This is there specifically for dot commands but it can be used generally too. Dot commands normally print using the rom. Since all the code is from the rom, it's also much smaller which makes it attractive for 8k dots. However there is no input stream (stdin) on this crt.
For your asm program there is crt31 which has no text streams at all. The downside is you do your own print / input code (rst$10 can be used in your dot command too) and the upside there is no extra code added to support the printing mentioned above.
All the canned crts are found inside the zx next target:
https://github.com/z88dk/z88dk/tree/mas ... xn/startup
The one you're using for "-startup=31" and "-subtype=dot" is 31+256=287.
https://github.com/z88dk/z88dk/blob/mas ... sm.m4#L116
The first line of code in this crt is at "__Start". The goal of the crt is to do any initialization, call your "_main" and then do any cleanup. What it does is up to you and is controlled by pragmas, with default behaviour determined by z88dk.
The list of default pragmas for dot commands is here:
https://github.com/z88dk/z88dk/blob/mas ... ig.inc#L68
(CRT_ORG_CODE, CRT_ORG_DATA, etc are the pragmas these TAR_* are in a different form because they are defaults)
What these mean is documented here:
https://www.z88dk.org/wiki/doku.php?id= ... figuration
You can change what the crt does by modifying these settings using a list of pragmas in another file.
----
How to do it.
The compile line will be something like:
zcc +zxn -vn -startup=31 -clib=sdcc_iy mm.asm -o mm -pragma-include:zpragma.inc -subtype=dot -create-app
Your asm will be placed in "SECTION code_user" and the entry point will be "_main" made global with "PUBLIC _main".
You tell the crt what you want it to do with pragmas. I'll give you a pragma file you can modify. Call it "zpragma.inc"
zpragma.inc
Code: Select all
#pragma output CRT_ENABLE_COMMANDLINE = 2 // pass esxdos command line without processing
I thought there were going to be more pragmas in the file when I started writing but the defaults are already set to the minimum for an asm program.
If you don't want to use this pragma file you can get rid of "-pragma-include:zpragma.inc" in the compile line.
The crt will:
1. save IY, HL', SP for return to basic
2*. set up the command line
3. call _main
4. restore IY, HL', SP for basic
5*. return status to esxdos (may generate error or OK)
* SET UP THE COMMAND LINE
If "CRT_ENABLE_COMMANDLINE=3" which is the default, the crt will parse the command line into zero-terminated strings and generate argc,argv as expected by c programs. You can also use this in your asm program if you prefer an argc/argv interface to the dot command's argument list.
If "CRT_ENABLE_COMMANDLINE=2", the crt will not do anything about the command line. Your program will be passed the parameter buffer as sent by esxdos.
* RETURN STATUS
Is in HL.
If HL=0 this means OK
If HL > 0 and HL < 256 then you are choosing a canned error message from esxdos:
https://github.com/z88dk/z88dk/blob/mas ... os.m4#L108
If you want to cause a "Nonsense in ESXDOS, 0:1" error on return you would "ld hl,__ESXDOS_ENONSENSE" before returning from _main. All ports, constants, etc are already defined in z88dk so you can get hold of this constant like this:
Code: Select all
EXTERN __ESXDOS_ENONSENSE
...
ld hl,__ESXDOS_ENONSENSE
ret
If HL >= 256, HL is the address of a custom message string that terminates in last_char+0x80. This will be printed as an error at the bottom of the screen on exit.
--
So when _main starts:
1. On entry
* If "CRT_ENABLE_COMMANDLINE=2"
HL = address of command line buffer as passed by esxdos
BC = address of command line buffer with dot name in front as passed by nextos
the stack will also contain copies of these:
HL as passed by esxdos (this is a pointer to the command line buffer)
BC as passed by nextos (this is a pointer to the command line buffer with dot name at front)
return address
* If "CRT_ENABLE_COMMANDLINE=3" (the default)
HL = char **argv as expected by c (array of zero terminated strings for each word on command line)
BC = int argc as expected by c (number of words on command line)
the stack will also contain copies of these:
HL = argv
BC = argc
return address
And when main exits:
HL = return code as described under return status above.
You can exit from any point with:
EXTERN __Exit
jp __Exit
The crt always resets the stack and sets up for return to esxdos.