Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rc2014 - subtype for NASCOM Basic (RAM) - enhancement request #256

Closed
feilipu opened this issue Jun 22, 2017 · 36 comments
Closed

rc2014 - subtype for NASCOM Basic (RAM) - enhancement request #256

feilipu opened this issue Jun 22, 2017 · 36 comments

Comments

@feilipu
Copy link
Collaborator

feilipu commented Jun 22, 2017

The RC2014 is expandable, via multiple 3rd party cards, but the basic RC2014 Full Monty, or RC2014 Mini consists of 32kB RAM from 0x8000, with 8kB NASCOM Basic located from 0x0000. Additionally an optional 64kB RAM board provides 56kB RAM from 0x2000.

The ROM contains NASCOM Basic, which provides a simple interface via RST08 for transmitting bytes, and RST10 for receiving bytes via the inbuilt ACIA board. Both calls are blocking, and will not return until a byte is either transmitted or received.

The current +rc2014 implementation supports -subtype=rom and -subtype=rom_zx7, both for generating a complete ROM replacement from any C program.

This is an enhancement request to provide an additional +rc2014 RAM implementation; -subtype=basic, to allow C programs and the z88dk STDIO library to interface with the NASCOM Basic ROM character I/O.

The point of this enhancement is to allow owners of the Full Monty or Mini RC2014 to access z88dk without purchasing any additional hardware. Programs in Intel HEX code generated using z88dk appmake +glue can be uploaded to the RAM of the RC2014 using either a Basic language HEX uploader using the default ROM, or an integrated HexLoadr in an enhanced ROM.

rc_00_output_basic.asm.txt
rc_00_input_basic.asm.txt

I've had a crack at writing the character drivers to take advantage of the available RST jumps, but I'm not sure how to configure the rest of the z88dk platform to take advantage of a new subtype, and ensure that the correct character drivers are included with the subtype selection. I hope this is of some help.

@aralbrec
Copy link
Member

aralbrec commented Jun 22, 2017

For the input side of the basic driver, does the rom's getchar routine handle line editing and character echo while editing? So when you call the rom getchar, the line editing has been performed, person has pressed enter and then getchar will read from the edit buffer one char at a time until the buffer is empty?

This is also the assumption with your original acia drivers where the terminal software on the pi (or pc) allows local editing of a line before sending it.

Something that could be added later as an option is, if it is possible to do raw character io, ie the input sends a character immediately without editing and local echo, then z88dk can do the line editing too. An advantage of this is the z88dk drivers can be configured to manage windows on screen and do things like password mode for input.

Is it possible to gather a command line from basic?

Are there any special steps that have to be taken when returning to basic? Registers that have to be preserved, eg.

Does the basic rom reserve any registers in its interrupt routines? Is it ok if z88dk is using the index registers and the exx set?

@feilipu
Copy link
Collaborator Author

feilipu commented Jun 22, 2017

The NASCOM Basic assembly interface is very simple, and consists of nothing more than an ability to jump "out" of Basic into a user's assembly language routine. A function USR(x) is provided that simply jumps to a specific location in RAM.

On initialisation the USRLOC location is filled with a jp to the location of the illegal function call error routine, but the destination address for the USR(x) jump can be rewritten to point to an assembly routine provided by the user. The address of the user routine needs to be written to the WRKSPC + 0x04 locations, being the USRLOC.

Parameters can be passed into and out of the users assembly language routine, by using the provided functions. The x in USR(x) can be recovered from DE for example.
DEINT ; Get integer -32768 to 32767 and
ABPASS ; Return a signed integer in AB
If the user is unsure of the location of these functions, their address can be obtained by reading the correct memory location, being WRKSPC + 0x0B and WRKSPC + 0x0D locations respectively.

This information above and below can be found in the NASCOM Basic Manual on Page 5,21.

Note that the actual location of WRKSPC and USRLOC depends on the implementation of the initialisation code, the size of Tx and Rx buffers, and the location of RAM. Specifically, the default rc2014 (Grant Searle) ROM places WRKSPC .EQU 8045H. Other ROMs locate the WRKSPC in other locations, so this address is not sacred.

Is it possible to gather a command line from basic?
Are there any special steps that have to be taken when returning to basic? Registers that have to be preserved, eg.
Does the basic rom reserve any registers in its interrupt routines? Is it ok if z88dk is using the index registers and the exx set?

NASCOM Basic provides no additional support to the user's assembly function. On return from the USR(x) function it is assumed that all registers are invalid. A stack of only 16 bytes is provided, and it is suggested that the user relocate the stack if a deeper stack is required. The stack must be restored on return.

The NASCOM Basic character getc and putc routines simply provide blocking reception and transmission of characters via the A register.

Once the user has left Basic for the dark side of assembler, they are pretty much on their own. Any line editing functions from Basic are unavailable to the assembly (or C) function.

The only justification for using the existing NASCOM Basic character functions is that they are locked into the ROM via the RST jump locations, and most relevantly the RST38 INT0 jump is ROMed into filling the getc routine's buffer. There is no RAM jump table that can steer the ACIA interrupt.

For z88dk, all of the STDIO would need to be brought along, if interactive line editing or screen management was required.

@aralbrec
Copy link
Member

Everything is pretty much ready to go, I'm just trying to figure out how to balance the subtype=.. and startup values.

There are two startups now, startup=0 uses acia drivers and startup=16 uses the basic drivers. I think I may add another one that uses none - it will make sense if display hw starts showing up and people would rather display directly instead of pay for stdio. All of these crts can have their driver instantiations user-supplied at compile time but these things are about convenience.

IF the origin of the compile is address 0 then the rc2014_page_zero code is used. This places the acia isr at 0x38 by default but this can be changed at compile time using the right pragma.

This means if you compile using, say, startup=0 which uses the acia drivers and your org is not 0, you will still be using the acia anyway assuming you've got the acia isr running somehow.

Independently of the crts, you can have a rom, compressed rom or ram compile.

For the basic drivers, a rom compile can still make sense if someone keeps basic in the lower 8k and then has something that pages in other roms in some portion of the top 56k. So you could compile a rom program for that 56k that uses the basic acia driver in the bottom 8k.

So subtype=rom, rom_zx7, ram, basic are not sufficient to specify a compile. I think we're left with specifying a startup number to choose the right crt (acia, basic or none) and then a subtype=rom, rom_zx7 (you really don't like romc ? :P ), ram to choose the type of build.

I think I will do this tonight and this can be revisited if a better idea comes up.

@feilipu
Copy link
Collaborator Author

feilipu commented Jun 25, 2017

It seems sensible to leave all of the options open, by having the matrix of -startup and -subtype options. I'd only question whether it is too much work to build all these options. If there's no extra maintenance overhead, then please.

I just wrote myself a couple of clarification paragraphs,... and then erased them. I think I now see why it is worth reflecting for a few hours on the right way to define these -subtype and -startup issues.

I believe, the only difference between rom, romc, and ram is where the BSS and DATA is stored. Whether it is recreated by the rom types, or just stored for the ram type. How the image is created is probably the right and only deciding point for the -subtype.

The hardware differences created by different serial I/O, or other hardware interfaces, can be signalled by -startup as you've pointed out. I know of need for the acia and basic versions. But there's also a sio SIO board with a CTC board too. So perhaps someone will write drivers for that as well. Other hardware is sure to follow.

Having an issue with #266, sorry I couldn't test what's already committed.

@feilipu
Copy link
Collaborator Author

feilipu commented Jun 26, 2017

I've been having a look at the current status, and (if I read it correctly) the -startup=16 etc options aren't yet activated, although the basic drivers are placed already. Correct?

@aralbrec
Copy link
Member

aralbrec commented Jun 26, 2017

Yes a startup case in rc2014_crt.asm.m4 has to be set and a default configuration has to be set in crt_config.inc. For basic it should be a ram model compile and I'm not sure yet if the stack should be part of the output binary and what the default org should be.

I'm looking at the possibility of doing something like "-subtype=acia,rom" and "-subtype=basic,ram" with defaults if either is missing. Right now multiple subtypes will work so this would be a shortcut.

@aralbrec
Copy link
Member

aralbrec commented Jun 26, 2017

Things are committed now. There are only three subtypes: -subtype=basic, -subtype=acia and -subtype=none. Nothing else I was doing was making sense. See below how they are used.

In all compiles -clib=sdcc_iy is the default but this can be changed by adding to the compile line -clib=new (sccz80) or -clib=sdcc_ix (zsdcc with ix library).

-create-app uses appmake +rom which will properly generate all ram and rom model compiles as well as ihx files. To choose something else, drop -create-app and invoke appmake directly.

BASIC COMPILE
zcc +rc2014 -v -subtype=basic -SO3 --max-allocs-per-node200000 test.c -o test -create-app

subtype=basic chooses startup=16 (see rc2014.cfg). startup=16 chooses the crt in rc2014_crt.asm.m4 and also selects __CRTCFG=1. This chooses the default build options in crt_config.inc.

These options choose a ram model compile (a single monolithic binary is produced) with org 0x9000, stack pointer at the top of ram and a heap created between the end of the program and the bottom of the stack. If "CRT_ABPASS" is defined, it is taken as the address of the ABPASS routine to call to return C's return value to basic. On exit, im1 will be set and interrupts enabled (someone may want to use im2 mode). For command line, I haven't done that yet but I am wondering if it's possible to pass the address of a basic string so that the crt could parse that into argv and argc. I didn't spot a VARPTR command or similar that would give the address of a basic string?

Any of the default options can be changed with a pragma. For example, since the location of the c program is defined by the user's answer to memory? at startup, you can compile for any address by changing the value of "CRT_ORG_CODE". You can collect pragmas in a file, eg like this:

"zpragma.inc"

#pragma printf = "%s %c"  // only enable these converters for printf

#pragma output CRT_ORG_CODE = 0x8400  // change org
#pragma output CLIB_MALLOC_HEAP_SIZE = 0  // no heap
#pragma output CLIB_STDIO_HEAP_SIZE = 0  // no stdio heap to open files

#pragma output CRT_ABPASS = 0x800  // location of ABPASS in nascom rom

Then add "-pragma-include:zpragma.inc" to the compile line.

ACIA COMPILE
zcc +rc2014 -v -subtype=acia -SO3 --max-allocs-per-node200000 test.c -o test -create-app

The default is ORG 0, ram org 32768 (data section then bss), compressed rom compile, stack at the top of ram, heap between the end of bss and the bottom of the stack. With org=0, the rc2014 page zero code will be brought in which installs the acia isr at 0x38 by default.

Again, like above, anything can be changed via pragmas. Eg, if you have an all-ram 64k bank, you can change to a ram model compile by setting CRT_MODEL=0 (and CRT_ORG_DATA=0, CRT_ORG_BSS=0 to make a monolithic binary). This will save some memory compared to rom model compiles. If you move org away from 0 (CRT_ORG_CODE), the page zero code will not be included. The acia drivers will assume that the acia isr is running.

Description of the pragmas.

@feilipu
Copy link
Collaborator Author

feilipu commented Jun 26, 2017

Self explanatory. 😄

SBC - Grant Searle
ACIA - feilipu
z88dk

Cold or Warm start, or HexLoadr (C|W|H) ? C

Memory top?  36863
Z80 BASIC Ver 4.7b
Copyright (C) 1978 by Microsoft
3233 Bytes free

Ok
SBC - Grant Searle
ACIA - feilipu
z88dk

Cold or Warm start, or HexLoadr (C|W|H) ? 
HexLoadr: 
****************#
****************#
****************#
.
... a lot of lines...
.
****************#
****************#
***********#
Done

Ok
doke &h8224, &h9000
Ok
print usr(0)

Eliza
Creative Computing
Morristown, New Jersey

Converted to C by Payton Byrd


Hi!  I'm Eliza.

What's your problem?

? 

I see.
? 

I'm not sure I understand you fully.
? 

Come, come ... elucidate your thoughts.
?

HexLoadr blows up after about 2kB at full USART rate. It must be just fractionally slower than needed. I will have to remove the Tx * on each byte to speed it up to see if I can get it to work for multi kByte programs. Edit: fixed, now it runs at line rate.

@feilipu
Copy link
Collaborator Author

feilipu commented Jun 26, 2017

For command line, I haven't done that yet but I am wondering if it's possible to pass the address of a basic string so that the crt could parse that into argv and argc. I didn't spot a VARPTR command or similar that would give the address of a basic string?

I'm not sure how NASCOM Basic defines strings. I will have to do homework on that.
But a sensible option (if there is no inherent Basic way) would be to use DEINT to pass in the address of a C string (null terminated) for the command line.

I'll spend some time playing around with the #pragma options and see how I go. Then, I'll write this up for you on the rc2014 forum.

If the target customer is one of the 600+ rc2014 owners (less those 20 or so active on the forum that have built their own hardware and own their own EEPROM programmers) then there are really only 2 hardware configurations of interest.

  • -subtype=basic32 which is exactly what you have now as default. Probably 60% of people
  • -subtype=basic56 which is the standard ROM, but with the 64kByte RAM module. The remainder of people. For this hardware, moving the default data, bss, and heap origin to 0x2000 and stack to 0x7FFF would probably be the best option. I've asked on the rc2014 forum for an opinion.

@aralbrec
Copy link
Member

Self explanatory. 😄

Nice first time. I assume the typed text is echoed at the terminal?

@blaknite
Copy link

I'm completely new to the land of C and recently built an RC2014. I've since written a snake game for the RC2014 using a library that exposes the NASCOM Basic RST08, RST10 and RST18 subroutines.

This has come along and blown my mind because the basic subtype is what I was working towards - excellent work!

I have a few quick questions about what this target exposes and how. I presume now I can use print, puts, gets, putchar, getchar and the like? Noting that the NASCOM Basic subroutines are blocking, is there any interface for checking the rx buffer? Having had a look through the source I can't spot anything. Being able to skip over blocking I/O is a critical feature for porting the game I wrote to the RC2014 target.

You can see what I exposed and how in this repo: https://github.com/blaknite/rc2014-uart

Thanks for your hard work and I look forward to your response!

@feilipu
Copy link
Collaborator Author

feilipu commented Jun 27, 2017

Self explanatory. 😄
Nice first time. I assume the typed text is echoed at the terminal?

Well, no. Which is odd. It didn't occur to me with eliza, because she gives random answers, no matter what you type. But I also tried clisp and when it didn't show my characters, I assumed it was user (my) failure.

The CR is getting through, otherwise there would be no progress. But, I'm now suspicious that ASCII characters are getting lost somehow.

I'll do some testing with a simple character echo program, and update this comment.

@feilipu
Copy link
Collaborator Author

feilipu commented Jun 27, 2017

Noting that the NASCOM Basic subroutines are blocking, is there any interface for checking the Rx buffer?

The Grant Searle NASCOM Basic provides the fullness of the Rx buffer, using CKINCHAR via RST18. I do exactly the same, in my solution, too.

CKINCHAR        LD       A,(serBufUsed)
                CP       $0
                RET

Spend some time on the z88dk.org wiki site, there's mountains info on stdio there.

Note the RC2014 Target is only connected to the new_lib, although you can use either of the compilers.

Although there are how-to guides on the z88dk wiki, I wrote a simple recipe so that I can quickly find the incantations to rebuild both sdcc and z88dk from scratch. When I trash something it is easiest to just rebuild from scratch.

@blaknite
Copy link

Excellent, thanks @feilipu. Everything in stdio looks to be what I'm after, I'm just unsure if they are blocking or not.

Just to clarify, I will still have to expose RST18 myself if I want to use it in my C program and prevent I/O from blocking?

@feilipu
Copy link
Collaborator Author

feilipu commented Jun 27, 2017

Just to clarify, I will still have to expose RST18 myself if I want to use it in my C program and prevent I/O from blocking?

At the moment RST18 is not exposed, but this build is still very much "work in progress". Give @aralbrec a few days while he finishes up and if you like you can help with testing what's being built (otherwise it is just me), and then I'm sure there'll be positive answer.

@blaknite
Copy link

blaknite commented Jun 27, 2017

At the moment RST18 is not exposed ... Give @aralbrec a few days while he finishes up

No worries, that gives me a good idea of where it's at.

if you like you can help with testing

Will do. Does all this get included in the nightly build? I will probably give it a test run tonight and see what's what.

@feilipu
Copy link
Collaborator Author

feilipu commented Jun 27, 2017

If the target customer is one of the (greater than) 600 rc2014 owners (less those 20 or so active on the forum that have built their own hardware and own their own EEPROM programmers) then there are really only 2 hardware configurations of interest.

Spencer has responded that there are about 180 64kByte RAM boards, and about 50 56kB RAM ROMs sold / delivered. Most of the 64kB RAM boards went to people who purchased CPM flash cards too.

This means the rough statistics are:

  • -subtype=basic32 which is exactly what you have now as default. 70% of people.
  • -subtype=basic56 which is the standard 32kB ROM, but with the 64kB RAM module. 20% of people.
  • -subtype=cpm which is another thread, anyway. The remainder, less than 10% of people.

IMHO, there's no compelling reason to do more than you've already done with -subtype=basic, assuming the 32k RAM ROM (Basic origin at 0x8000), and give people #pragmas to move the DATA and STACK to where they prefer. Just my 2C.

@feilipu
Copy link
Collaborator Author

feilipu commented Jun 27, 2017

if you like you can help with testing

Will do, does all this get included in the nightly build? I will probably give it a test run tonight and see what's what.

@blaknite the best way (IMHO) to use z88dk is to build it yourself, off a git clone of the main repository. I've been tracking it for about 8 months now, and have never seen it left in a broken state.

@aralbrec
Copy link
Member

I have a few quick questions about what this target exposes and how. I presume now I can use print, puts, gets, putchar, getchar and the like? Noting that the NASCOM Basic subroutines are blocking, is there any interface for checking the rx buffer? Having had a look through the source I can't spot anything. Being able to skip over blocking I/O is a critical feature for porting the game I wrote to the RC2014 target.

Everything in stdio will work and so will lower level operations on file descriptors. Keep in mind file io is not complete and you can't do things like open and close files except for memory stream files.

Right now the drivers are blocking and use rst 8 and rst 10. The library is capable of non-blocking io but it will come out as an error so that you have to reset the error state on the stream before continuing, except for best effort functions like read(). I'm hoping to do another rewrite this summer (attempt 3 or 4?) to do non-blocking io properly and to incorporate file io which is not currently implemented in newlib.

However, newlib has another cross-platform input interface to read input devices like keys, joysticks and mice directly in a non-blocking manner called the input library. If what you have in mind is for games, it may fit into an input lib implementation. Recently a volunteer started writing about the zx spectrum and using newlib as he was learning and he recently covered part of the input library which you can maybe read to get an idea of what it is (he did get the in_inkey description a little wrong - it can return any ascii key on the keyboard, shifted or not). Character io through a serial interface probably doesn't match with many of the functions in the input lib (unless you're getting key up and down events) but some of them could probably be implemented.

I'll take a look at how you did things.

Nice first time. I assume the typed text is echoed at the terminal?

Well, no. Which is odd. It didn't occur to me with eliza, because she gives random answers, no matter what you type. But I also tried clisp and when it didn't show my characters, I assumed it was user (my) failure.

The driver is very simple. I'm assuming that you're connected to a terminal program on a PC or pi so that when you type, it only sends an entire line at a time so that editing is taken care of at the terminal with local echo on. So that's where the display happens. Should the input driver be doing an echo?

The drivers can be made more complicated by having the terminal send individual characters as they happen so that there is no delay, no local echo and no line editing at the sender. Then the z88dk driver will be responsible for line editing, whether that's the c library or the nascom rom. If it's the c library, the requirement is z88dk must be able to do backspace. If the terminal can do cursor placement on screen we can go further and z88dk can manage multiple windows on screen. Each of these steps means larger binary sizes.

Just to clarify, I will still have to expose RST18 myself if I want to use it in my C program and prevent I/O from blocking?

yes right now you have to do this yourself.

Will do. Does all this get included in the nightly build? I will probably give it a test run tonight and see what's what.

Yes the current state is built every night. The build failed last night but hopefully it is cleared up for tonight.

-subtype=basic32 which is exactly what you have now as default. 70% of people.
-subtype=basic56 which is the standard 32kB ROM, but with the 64kB RAM module. 20% of people.
-subtype=cpm which is another thread, anyway. The remainder, less than 10% of people.

IMHO, there's no compelling reason to do more than you've already done with -subtype=basic, assuming the 32k RAM ROM (Basic origin at 0x8000), and give people #pragmas to move the DATA and STACK to where they prefer. Just my 2C.

Ok, there is a separate cpm target in both the newlib and classic. Classic is able to do file io for cpm as well.

@feilipu
Copy link
Collaborator Author

feilipu commented Jun 27, 2017

Should the input driver be doing an echo?

NASCOM Basic generates an echo, so mostly terminals leave the local echo off. But, I think that C generally doesn't do an echo, by default.

Not sure what the answer right answer for the rc2014 is, in this case. Probably better to keep it simple where possible.

@aralbrec
Copy link
Member

With the way it's implemented now (it is assumed the connected terminal is in line mode with local echo), it won't be possible to detect live keypresses like @blaknite wants to do. So I think we may have to change to at least a minimal line editing driver done by the c library. This will be similar to the direct io drivers for cpm (dcio). I should have some time tomorrow evening to try it.

@feilipu
Copy link
Collaborator Author

feilipu commented Jun 27, 2017

Since @blaknite and other RC2014 users are the ones who will be doing the most actual programming with z88dk it makes sense to fulfil his (their) desires wherever possible. 😄

I guess the only (obvious) point to remember is that Spencer won't change the default ROM, because it is now a default on every shipped product, so any -subtype=basic solution has to respect the limitations of that ROM, and the users who can't change the ROM.

(Though Spencer did mention on the forum that he might change the default to 56kB Basic. I'll have to persuade him to include the 56kB HexLoadr as the default when he goes to 64kB RAM only. 😄 )

Otherwise, it is just a better project to build a much improved non-blocking buffered optimised ACIA driver for the "clean slate" -subtype=acia build, as we've already started to do.

@feilipu
Copy link
Collaborator Author

feilipu commented Jun 27, 2017

I was disappointed that Startrek wouldn't fit into 32kB, so I added the HexLoadr to my 56kB NASCOM Basic build. It is not the default ROM, but it will reach a few people, I'm sure.

I'm very happy to report that it was straight forward to configure the -subtype=basic to use the #pragma CRT_ORG_CODE to move the code origin to 0x3000.

This enabled Startrek to fit into the rc2014 with 64kB RAM module. Uploading the 82kB HEX file generating 31kB of code (0x3000 through to 0xA820) takes only a few seconds, as the HexLoadr runs at line rate.
Super Star Trek uploaded to rc2014.

@aralbrec
Copy link
Member

I was disappointed that Startrek wouldn't fit into 32kB,

Will it fit if you move the org down further? At 0x9000 it seems there is still 3k left to basic. I was thinking about moving the default org down further so there isn't so much space left unused.

Memory top?  36863
Z80 BASIC Ver 4.7b
Copyright (C) 1978 by Microsoft
3233 Bytes free

Another thing is you can strip the bss section from the output binary if you get the crt to zero bss before starting main. This will reduce the size of the produced ihx file:

#pragma output CRT_ORG_BSS = -1
#pragma output CRT_INITIALIZE_BSS = 1

I was thinking of making that the default too.

@feilipu
Copy link
Collaborator Author

feilipu commented Jun 27, 2017

I was disappointed that Startrek wouldn't fit into 32kB.

Will it fit if you move the org down further?

#pragma output CRT_ORG_CODE = 0x8400
#pragma output CRT_ORG_BSS = -1
#pragma output CRT_INITIALIZE_BSS = 1
SBC - Grant Searle
ACIA - feilipu
z88dk

Cold or Warm start, or HexLoadr (C|W|H) ? C

Memory top?  33791
Z80 BASIC Ver 4.7b
Copyright (C) 1978 by Microsoft
161 Bytes free

Ok

SBC - Grant Searle
ACIA - feilipu
z88dk

Cold or Warm start, or HexLoadr (C|W|H) ? 
HexLoadr: 
######################## - a lot of hash - ##############################
Done

Ok
doke &h8224, &h8400
Ok
print usr(0)

 *************************************
 *                                   *
 *                                   *
 *      * * Super Star Trek * *      *
 *                                   *
 *                                   *
 *************************************

Do you need instructions (y/n): 

                         ------*------
         -------------   `---  ------'
         `-------- --'      / /
                  \\-------  --
                  '-----------'

       The USS Enterprise --- NCC - 1701

It seems so.
Though, not sure whether the heap and stack will have enough room as the game progresses.

@aralbrec
Copy link
Member

Issue #270 is causing the "CRT_ORG_BSS = -1" pragma not to properly separate the bss section from the output binary.

@aralbrec
Copy link
Member

aralbrec commented Jun 28, 2017

It seems so.
Though, not sure whether the heap and stack will have enough room as the game progresses.

I get a compiled binary size of 30775 bytes which includes CODE,DATA,BSS (the pragma to separate BSS is not working otherwise you would add the code binary size to the bss binary size to arrive at the same number). What's not included is the heap or the stack but there is a pragma in startrek.c that eliminates the heap so all that is left is the stack. 65536 - 0x8400 - 30775 = 969 bytes for the stack which is plenty. 256 is comfortable for programs that use floats and don't have deep recursion.

When a command line comes into play, either argv and argc are created on the stack (the crt makes a copy from the original location) or they are created in the original source. If the former happens, you also need stack space to store argv,argc.

@feilipu
Copy link
Collaborator Author

feilipu commented Jun 28, 2017

Just to note that #pragma output CRT_ORG_CODE = 0x8400 will not work for the standard 32kB ROM. There's only 161 bytes available to Basic.

There needs to be space available to Basic for the user to type or upload a Basic program, that will poke the assembled version of a HexLoad program into free RAM. Then this HexLoad program can load the z88dk C binary (Hex).

I'll have a look at the standard version on the RC2014 repository, and see if I can simplify the program and at least calculate how much space it needs to reserve in Basic, and free RAM.

@feilipu
Copy link
Collaborator Author

feilipu commented Jun 28, 2017

I've redone the hexload program in the RC2014 repository, to suit the -subtype=basic option, and left a note about it on the RC2014 Forum.

The Basic hexload.bas program needs quite a few bytes to load itself first, and I found it needs up to about 0x88FF to work.

The active asm hexload code itself only needs a few bytes, and doesn't extend beyond 0x8A00. So, the default origin could be moved down to 0x8A00, but really I don't think that it would save much.

The existing default origin of 0x9000 is easy to remember.

It might be reasonable to have default the C stack start at 0x9000 and grow down. If it grows too far it will only overwrite the hexload program. Not a big loss.

@aralbrec
Copy link
Member

aralbrec commented Jun 28, 2017

It sounds like 0x9000 is a good default org and the idea to move the stack below the code is probably a good one - I'll just have to revisit how the heap is sized by default.

I've committed some new drivers to test under -subtype=basic_dcio. This is the same configuration as -subtype=basic except the drivers are now expecting the terminal to send characters immediately with no local echo. Line editing is handled by the z88dk library - the library only supports backspace at the end of the line. It's generating a backspace char code 12 to move the cursor left one position and it's currently configured to generate beeps with ctrl-g code 7. It performs cr/lf conversion by turining \n into \r\n before sending to the terminal. On input, ctrl-z generates EOF on the stream and ctrl-c will cause the program to exit. cr/lf will be turned into a single \n on the z80 side of the stream.

There is an example program "password.c" that does password mode and edit buffer stuffing that should work with this driver.

The drivers assume that nascom rst 0x8, 0x10, 0x18 only alter the main register set (af, bc, de, hl). If more are altered, then some crashes may occur and push/pop pairs will have to be added. The drivers add about 900 bytes to program size.

Let me know if it's working!

@feilipu
Copy link
Collaborator Author

feilipu commented Jun 29, 2017

Compiling and running the password.c program works easily.
zcc +rc2014 -v -subtype=basic_dcio -SO3 -clib=sdcc_iy --max-allocs-per-node200000 password.c -o password -create-app

But, it is not working as expected. Part of the problem may be my terminal set up. I had a bit of trouble finding a terminal that sent the characters immediately, and settled on GtkTerm 0.99.7-rc1.
My keyboard is a standard ANSI version, set to US English.

screenshot from 2017-06-29 22-25-39

The screen shot shows the -subtype=basic compile in the top half (just to ensure that I was getting different answers for the -subtype=basic_dcio version in the bottom half of the screen) for each normal character, I get a LF.

The DEL key gives:

[_
  3_
    ~_

The backspace gives:

?_

For sanity checking and comparison, with the NASCOM Basic command line on the GtkTerm, backspace moves the cursor back one space, but doesn't delete the character to be removed. The DEL key produces the [3~ character sequence in Basic. My keyboard is not matched to the expected terminal then. So really, I'm not a very good test candidate. Sorry.

Edit. I'm also playing with eliza using GtkTerm, and (as expected) there is no local echo. But also, there is no response to characters entered, or the Enter key.

The only combination (that I found) that generates response is CTRL+SHIFT+ENTER, which seems to generate a CR+LF.

@aralbrec
Copy link
Member

aralbrec commented Jun 30, 2017

The DEL key produces the [3~ character sequence in Basic. My keyboard is not matched to the expected terminal then. So really, I'm not a very good test candidate. Sorry.

I'm trying to get it to match native nascom basic. If you get proper display with the basic rom including line editing, that's what I am trying to duplicate.

I may have made a mistake in treating the attached terminal like an ascii terminal. Maybe it should be treated like a vt terminal so that backspace is not ascii code 12 but rather an escape sequence.

I'm not sure why you are getting a LF after every character echoed during input. The "_" is the cursor btw.

I'll have another go tomorrow - been a bit busy the past few days and maybe this time I will take a closer look at the nascom rom to find out how it's doing line editing.

@aralbrec
Copy link
Member

aralbrec commented Jul 3, 2017

@feilipu Do you mind trying the basic_dcio compile again? I've been reading the nascom source and I can see that the backspace character is different so I've changed that and I've accommodated the CHAR_CR code only that is sent by the terminal when pressing ENTER. Other than that I can't see anything wrong.

There is something strange in the nascom source, however. After printing a CR/LF it sends a bunch of NUL characters. I think this may be to fill up the terminal's input buffer to force output to screen. If that's the case, is it true you do not typically see any typed characters on screen when entering a line in basic? You mainly only see it after enter is pressed?

@feilipu
Copy link
Collaborator Author

feilipu commented Jul 3, 2017

Well, to the best of my knowledge, it is now 100% fixed, and this issue can be closed off from my point of view. 🙇‍♂️

Still it would be good to get a second opinion from someone else with a RC2014, and who is writing games or such like @blaknite.

screenshot from 2017-07-03 19-40-53

After printing a CR/LF it sends a bunch of NULL characters. I think this may be to fill up the terminal's input buffer to force output to screen.

Using GtkTerm 0.99.7-rc1, I don't see the NULL characters when examining the output in HEX over the USB serial interface, so perhaps they're simply destined for old NASCOM hardware? Anyway, they don't influence the outcome.

Perhaps the only loose end left at this stage is to move the default stack origin down to 0x8FFF, given there are 1,600 bytes free there.

I'll put another note up on the RC2014 forum.

@aralbrec
Copy link
Member

aralbrec commented Jul 4, 2017

Finally :)

I think there are a few issues before this can be tied up:

  • Default stack placement at 0x8ffff.
  • Strip off the BSS section by default to shrink the size of ihx files.
  • Make a similar driver for the ACIA build (this one is mainly for rom replacements).
  • Should CTRL-C return to basic (it does now)? Should CTRL-Z generate EOF on stdin (maybe CTRL-D)? Should the TOGGLE-CAPS-LOCK code be eliminated (ascii code 6)?
  • Get rid of the underline cursor; it looks like terminal sw provides its own.
  • Add functions to the input library to simulate instantaneous scanning of the keyboard.
  • Modify the drivers to allow escape codes to be sent to the terminal. Right now any code less than 32 will be sent as ?. The normal thing to do in z88dk is to add a tty emulation layer that will spot and interpret control code sequences. But there is no ansi tty yet so maybe just allowing these codes to be sent is easiest. Flushing stdout may have to mean sending a bunch of NUL chars to clear any pending escape sequence.

@feilipu
Copy link
Collaborator Author

feilipu commented Mar 7, 2018

I think all the issues in above TO DO list are either done, or relate to general terminal handing code (not specific to RC2014).

Its time to open a new issue if there are new broken things appearing in the future.

@feilipu feilipu closed this as completed Mar 7, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants