Author Topic: Z80 Homebrew Computer - fault finding  (Read 96943 times)

8BPogle and 1 Guest are viewing this topic.

Offline grumpydoc

  • Super Contributor
  • ***
  • Posts: 2905
  • Country: gb
Re: Z80 Homebrew Computer - fault finding
« Reply #125 on: March 29, 2017, 03:52:49 pm »
OK, input buffer:

This is defined, as with a lot of assembler source code not in the way you do in C code by saying the buffer is so many bytes long but by saying where it starts and then saying where the next thing starts, the lines which do this are:


BUFFER  .EQU    WRKSPC+61H           ; Input buffer
STACK   .EQU    WRKSPC+66H           ; Initial stack
CURPOS  .EQU    WRKSPC+0ABH          ; Character position on line


The input buffer starts at offset 0x61 in the workspace and extends to the byte before CURPOS ie. 0xAA.

0xAB - 0x61 is 0x4A or 74 bytes.

So, to expand you need to look carefully at the whole of the workspace layout beyond that and adjust every offset afterwards to take into account the increase.

You also need to work out what is happening with "STACK" which seems to be in the middle of the buffer.

The buffer length is hard coded in at least one other place that I spotted which is during initialisation when the end is marked with a '\0' by this code

        CALL    PRNTCRLF        ; Output CRLF
        LD      (BUFFER+72+1),A ; Mark end of buffer
        LD      (PROGST),A      ; Initialise program area


A will be zero here following the call to PRNTCRLF.

In short it will be a bit of a pain.

It is better to set up storage with db, dw or ds (or equivalent in whatever assembler you are using) as it is then much easier to add an item or change the size of an item.

 

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: Z80 Homebrew Computer - fault finding
« Reply #126 on: March 29, 2017, 05:13:07 pm »
OK, input buffer:

This is defined, as with a lot of assembler source code not in the way you do in C code by saying the buffer is so many bytes long but by saying where it starts and then saying where the next thing starts, the lines which do this are:


BUFFER  .EQU    WRKSPC+61H           ; Input buffer
STACK   .EQU    WRKSPC+66H           ; Initial stack
CURPOS  .EQU    WRKSPC+0ABH          ; Character position on line


The input buffer starts at offset 0x61 in the workspace and extends to the byte before CURPOS ie. 0xAA.

0xAB - 0x61 is 0x4A or 74 bytes.

So, to expand you need to look carefully at the whole of the workspace layout beyond that and adjust every offset afterwards to take into account the increase.

You also need to work out what is happening with "STACK" which seems to be in the middle of the buffer.

The buffer length is hard coded in at least one other place that I spotted which is during initialisation when the end is marked with a '\0' by this code

        CALL    PRNTCRLF        ; Output CRLF
        LD      (BUFFER+72+1),A ; Mark end of buffer
        LD      (PROGST),A      ; Initialise program area


A will be zero here following the call to PRNTCRLF.

In short it will be a bit of a pain.

It is better to set up storage with db, dw or ds (or equivalent in whatever assembler you are using) as it is then much easier to add an item or change the size of an item.

Grumpydoc, you are - as always - a mine of information!   ;D

I was halfway there with some of the changes I'd made.  I'd gone through the code and replaced the (two) occurrances of the hardcoded line length with a variable specified at the start of the code, so it could be changed easily in one location.

I then found out that changing the value didn't make much difference.  The line length was originally 72 as you found hardcoded and after I'd tried to lengthen it, it topped out at 74. I had looked at the BUFFER, STACK and CURPOS locations at the top of the code but hadn't really stopped to think about what was going on there.

I'm just wondering how I'd go about finding a 'safe spot' in the RAM that I could use for the BUFFER instead - so instead of it being at WORKSP+61H, I could point to 02100H or something similar without worrying about it getting overwritten by a user program?

EDIT

Would this be the line to change to bump the user program space up a little in the RAM and allow me to move the BUFFER here instead?

Code: [Select]
PROGST  .EQU    WRKSPC+0F9H     ; Start of program text area
« Last Edit: March 29, 2017, 05:31:14 pm by nockieboy »
 

Offline PA0PBZ

  • Super Contributor
  • ***
  • Posts: 5125
  • Country: nl
Re: Z80 Homebrew Computer - fault finding
« Reply #127 on: March 29, 2017, 05:22:47 pm »
Also, see:

Code: [Select]
PUTCTL: LD      A,B             ; Get number of bytes in buffer
        CP      72+1            ; Test for line overflow
        LD      A,CTRLG         ; Set a bell
        JP      NC,OUTNBS       ; Ring bell if buffer full

this is not really made to be modified easily...
Keyboard error: Press F1 to continue.
 

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: Z80 Homebrew Computer - fault finding
« Reply #128 on: March 29, 2017, 05:26:21 pm »
Also, see:

Code: [Select]
PUTCTL: LD      A,B             ; Get number of bytes in buffer
        CP      72+1            ; Test for line overflow
        LD      A,CTRLG         ; Set a bell
        JP      NC,OUTNBS       ; Ring bell if buffer full

this is not really made to be modified easily...

I've just replaced the hardcoded
Code: [Select]
72+1 with this:

Code: [Select]
PUTCTL: LD      A,B             ; Get number of bytes in buffer
        CP      LINEBUFFER+1    ; Test for line overflow

And specified LINEBUFFER at the start of the code with the other EQU statements.
 

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: Z80 Homebrew Computer - fault finding
« Reply #129 on: March 29, 2017, 05:43:27 pm »
Sorted it. I've moved the BUFFER to here:

Code: [Select]
BUFFER .EQU WRKSPC+0F9H ; Input buffer
PROGST  .EQU    WRKSPC+154H     ; Start of program text area
STLOOK  .EQU    WRKSPC+1B8H     ; Start of memory test

And moved the following PROGST and STLOOK away from it by another 10H, so it now has 5AH space (90 chars) and I can continue my type-in without messing with splitting long lines up. ;)

For info, the line buffer size is hardcoded twice in the assembly - I've replaced both instances with a variable and specified it at the top of the code:
Code: [Select]
LINEBUFFER .EQU 5AH ; Maximum line length

All works nicely. :)
 

Offline grumpydoc

  • Super Contributor
  • ***
  • Posts: 2905
  • Country: gb
Re: Z80 Homebrew Computer - fault finding
« Reply #130 on: March 29, 2017, 05:45:26 pm »
Sorted it. I've moved the BUFFER to here:

Code: [Select]
BUFFER .EQU WRKSPC+0F9H ; Input buffer
PROGST  .EQU    WRKSPC+154H     ; Start of program text area
STLOOK  .EQU    WRKSPC+1B8H     ; Start of memory test

And moved the following PROGST and STLOOK away from it by another 10H, so it now has 5AH space (90 chars) and I can continue my type-in without messing with splitting long lines up. ;)

For info, the line buffer size is hardcoded twice in the assembly - I've replaced both instances with a variable and specified it at the top of the code:
Code: [Select]
LINEBUFFER .EQU 5AH ; Maximum line length

All works nicely. :)
Well, done.  :-+

As a purely stylistic thing I would have called something which pertains to the length of a buffer BUFLEN or similar rather than LINEBUFFER.
 

Offline grumpydoc

  • Super Contributor
  • ***
  • Posts: 2905
  • Country: gb
Re: Z80 Homebrew Computer - fault finding
« Reply #131 on: March 29, 2017, 06:00:34 pm »
Just another thought.

If you edit any of the code watch the


WRKSPC  .EQU    2045H


The original Nascom implementation had the interpreter itself in ROM up in the top 8k starting at 0xE000 and the workspace started at 0x1000, Grant Searle seems to have switched this around to have the interpreter start at 0x150 (not sure why that address) with the workspace presumably immediately above that. However he has just hard-coded the workspace start address. If you expand the code at all without moving the workspace you will wind up with corruption of the end of the interpreter code.
 

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: Z80 Homebrew Computer - fault finding
« Reply #132 on: March 29, 2017, 06:47:48 pm »
Just another thought.

If you edit any of the code watch the


WRKSPC  .EQU    2045H


The original Nascom implementation had the interpreter itself in ROM up in the top 8k starting at 0xE000 and the workspace started at 0x1000, Grant Searle seems to have switched this around to have the interpreter start at 0x150 (not sure why that address) with the workspace presumably immediately above that. However he has just hard-coded the workspace start address. If you expand the code at all without moving the workspace you will wind up with corruption of the end of the interpreter code.

Oooh good point. The interpreter starts at 0150H because immediately before that is the bootstrap code that handles the UART initialisation and serial IO.  I guess he thought it'd be simpler to have the code starting at the bottom of memory as the Z80 starts reading instructions from 0000h.
 

Offline grumpydoc

  • Super Contributor
  • ***
  • Posts: 2905
  • Country: gb
Re: Z80 Homebrew Computer - fault finding
« Reply #133 on: March 29, 2017, 07:51:45 pm »
Oooh good point. The interpreter starts at 0150H because immediately before that is the bootstrap code that handles the UART initialisation and serial IO.  I guess he thought it'd be simpler to have the code starting at the bottom of memory as the Z80 starts reading instructions from 0000h.
Either in low memory with the BASIC program code above it and perhaps the stack at the top of RAM or at the top of RAM with the workspace starting in low memory and the stack just under the interpreter machine code are be equally sensible.

The difficulty with placing the interpreter at the top of RAM is that the top 8k might not always be 0xE000 - 0xFFFF - it was common for systems to not have a full 64k of memory - any absolute jumps or calls would have to be changed, putting your code in low memory avoided this problem so mostly that's where programs loaded. ISTR that part of the process of installing CP/M is to relocate the BDOS code high in memory (I'm probably about to find out).

It's just that in switching the memory map around without changing the code to be a bit more robust means that there is a good chance of things going pear shaped if you forget to move the workspace.

I suspect that the code is not the original Microsoft source anyway but was reverse assembled from the Nascom ROM.

 

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: Z80 Homebrew Computer - fault finding
« Reply #134 on: March 30, 2017, 07:44:54 am »
The low address memory needs to be kept clear if you intend using some of the Z80 interupt modes. The NMI jumps to 0x66 and RST jumps to a select range of addresses from 0x00 to 0x38.

Yes, good point wilfred. It looks like the jumps are catered for in the initial block of code.  At the moment I've no plans for anything to do with interrupts directly as far as I know.  The next big thing for me is to get a CompactFlash card connected via an 8-bit IDE interface as per Grant's CP/M implementation and see if I can get some permanent storage set up.
 

Offline grumpydoc

  • Super Contributor
  • ***
  • Posts: 2905
  • Country: gb
Re: Z80 Homebrew Computer - fault finding
« Reply #135 on: March 30, 2017, 09:10:50 am »
The low address memory needs to be kept clear if you intend using some of the Z80 interupt modes. The NMI jumps to 0x66 and RST jumps to a select range of addresses from 0x00 to 0x38.

Yes, good point wilfred. It looks like the jumps are catered for in the initial block of code.  At the moment I've no plans for anything to do with interrupts directly as far as I know.  The next big thing for me is to get a CompactFlash card connected via an 8-bit IDE interface as per Grant's CP/M implementation and see if I can get some permanent storage set up.
Usually the first page is kept clear, CP/M starts the TPA (transient program area) at 0x0100, but it uses some of page zero for a buffer and BDOS vector, plus probably a couple of other things that I can't remember.

0x0150 just struck me as an odd place to start the BASIC image.

One pain in my own design https://www.eevblog.com/forum/projects/z80-single-(perf)board-computer/ is that the memory expansion method will make it difficult to keep all the jumps etc in the 1st page consistent between banks. That said the bank scheme itself not much worse than the Z80180 family but on those chips I believe the DMA (which can copy blocks) has access to the full expanded address space.

I'm somewhat drawn to using 2x 74F189 to create a mapped system where any 4k page in the Z80 physical address space can map to any 4k page in the 1M expanded space but they are getting hard to find, and expensive, even on everyone's favourite supplier of tat and obsolete parts.
 

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: Z80 Homebrew Computer - fault finding
« Reply #136 on: March 30, 2017, 09:31:43 am »
One pain in my own design https://www.eevblog.com/forum/projects/z80-single-(perf)board-computer/ is that the memory expansion method will make it difficult to keep all the jumps etc in the 1st page consistent between banks. That said the bank scheme itself not much worse than the Z80180 family but on those chips I believe the DMA (which can copy blocks) has access to the full expanded address space.

I'm somewhat drawn to using 2x 74F189 to create a mapped system where any 4k page in the Z80 physical address space can map to any 4k page in the 1M expanded space but they are getting hard to find, and expensive, even on everyone's favourite supplier of tat and obsolete parts.

The more I look at your design, the more I realise I've got a lot to learn!

I'd like to implement something like I2C (or even SPI - could use SD cards then) on my system too, so I could just add an LCD display, an EEPROM or realtime clock later, but I'm finding it hard to get concrete information on how to build one (other than the standard specifications which, on their own, aren't much use to an electronics luddite like me.) Without spoonfeeding me a design (though feel free if you have any examples), is there anywhere I can go online to find an example of an I2C bus implemented on a Z80 system or some documentation that'll point me in the right direction? 

From what I can gather, it seems to be primarily a software-based standard, so in theory I could implement it with something as simple as a couple of IO lines and some programming?
 

Offline grumpydoc

  • Super Contributor
  • ***
  • Posts: 2905
  • Country: gb
Re: Z80 Homebrew Computer - fault finding
« Reply #137 on: March 30, 2017, 10:33:04 am »
I'd like to implement something like I2C (or even SPI - could use SD cards then) on my system too, so I could just add an LCD display, an EEPROM or realtime clock later, but I'm finding it hard to get concrete information on how to build one (other than the standard specifications which, on their own, aren't much use to an electronics luddite like me.) Without spoonfeeding me a design (though feel free if you have any examples), is there anywhere I can go online to find an example of an I2C bus implemented on a Z80 system or some documentation that'll point me in the right direction? 

From what I can gather, it seems to be primarily a software-based standard, so in theory I could implement it with something as simple as a couple of IO lines and some programming?
I haven't tackled I2C yet but as far as I can see it just needs a couple of open drain outputs and a couple of inputs so should be pretty easy electrically. After that it's all software, as you say.

https://learn.sparkfun.com/tutorials/i2c might be a good place to start.
 

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: Z80 Homebrew Computer - fault finding
« Reply #138 on: April 14, 2017, 09:49:18 pm »
Okay, well I haven't made much progress on the I2C front yet - I'm still holding off on rebuilding my SBC to the CP/M-spec version that Grant Searle outlines, which is my main goal before I start adding too much other stuff, though I've got the parts I need to do it.

In the meantime, I've added an IO output port to the system with 8 LEDs and written a basic (geddit?) program to do stuff with the LEDs, like a Cylon's visor animation, binary number quiz (which I'm successfully using to teach my 5-year old daughter binary!!) and, today, a reflex game where you have to stop the program (CTRL-C) when the end LED (D7 on the bus) is lit.  Each level increases the speed that the light 'scans' up and down the row of 8 LEDs, making it harder to do.  Little'un loves it.  :-+

Then another thought occurred.  Instead of breaking the program execution with CTRL-C to stop the light, and the following hassle of RUN-ing the program again and going through the options to get to the reflex game, why not add an input port to the SBC and wire a switch up (with the requisite red button!) to the IO port that would pause the program or otherwise fire a subroutine to check if the light was stopped on the right LED?

I've got no issues with wiring up an IO input port (have some 74HCT245s I can use) with the switch.  The question is, can I set up an interrupt-driven trigger that will call a subroutine in the BASIC program when the button is pressed?

I can poll the IO input to see if the button is being pressed with each step in the light animation (it uses a simple FOR..NEXT loop to light up a single LED in sequence on the IO port) but this seems a bit clunky.  Then again, perhaps I'm overthinking or over-engineering the problem and a simple input poll after the output has been set would be enough?   :-//
 

Offline grumpydoc

  • Super Contributor
  • ***
  • Posts: 2905
  • Country: gb
Re: Z80 Homebrew Computer - fault finding
« Reply #139 on: April 15, 2017, 12:05:06 pm »
If you want to  use interrupt driven I/O it is easiest to use the Z80 peripherals rather than "raw" buffers and latches - however I'm pretty certain that the BASIC interpreter has no way to tie a subroutine to the interrupt.
 

Offline netdudeuk

  • Frequent Contributor
  • **
  • Posts: 447
  • Country: gb
Re: Z80 Homebrew Computer - fault finding
« Reply #140 on: April 15, 2017, 12:50:14 pm »
I'm pretty certain that the BASIC interpreter has no way to tie a subroutine to the interrupt.

Agreed.

You could write some assembly language to do these simple things and then polling would be instantaneous.
 

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: Z80 Homebrew Computer - fault finding
« Reply #141 on: April 15, 2017, 03:32:14 pm »
If you want to  use interrupt driven I/O it is easiest to use the Z80 peripherals rather than "raw" buffers and latches - however I'm pretty certain that the BASIC interpreter has no way to tie a subroutine to the interrupt.

Yeah, thought as much.  No matter, I've written a simple check into the routine that delays the next light in the sequence lighting up.  It slows the whole thing down noticeably (easy to forget how powerful modern computers are!) but it works a treat.  :-+

I'd love to be able to modify the Nascom basic a little myself and add a couple of extra commands.  Top of my list would be a RENUM command.  I've got a copy of the assembly for Locomotive BASIC as used on the Amstrad range of 8-bit computers, but I've got some work to do before I can understand Z80 assembly well enough to translate a command like that over!  :scared:
 

Offline C

  • Super Contributor
  • ***
  • Posts: 1346
  • Country: us
Re: Z80 Homebrew Computer - fault finding
« Reply #142 on: April 19, 2017, 12:24:34 am »
This might help with BASIC

Microsoft BASIC Decoded
http://www.classiccmp.org/cpmarchives/trs80/mirrors/pilot.ucdavis.edu/davidk/documentation/62-1001.htm

This is about the Microsoft ROM basic used on TRS-80 that would get extended to Disk basic when using an OS. Quick note about TRS-80, 12k ROM starting at 0H, 4K IO space followed by ram. Low address things like INT & restart instructions were redirected to ram so that they could be changed.
 

Also you might like to know that HPL which was a HP interpreted language would let you program interrupts in the interpreted language. Was a simple thing done. Between the execution of two lines, it would check for a flag to see if an interrupt had happened during previous line an do a gosub if this was true. Note that between two lines you have a good machine state as far as basic is concerned. Think some versions of Basic also had this capability.


 

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: Z80 Homebrew Computer - fault finding
« Reply #143 on: April 19, 2017, 01:39:26 pm »
This might help with BASIC

Microsoft BASIC Decoded
http://www.classiccmp.org/cpmarchives/trs80/mirrors/pilot.ucdavis.edu/davidk/documentation/62-1001.htm

This is about the Microsoft ROM basic used on TRS-80 that would get extended to Disk basic when using an OS. Quick note about TRS-80, 12k ROM starting at 0H, 4K IO space followed by ram. Low address things like INT & restart instructions were redirected to ram so that they could be changed.

Thanks C, that link was fantastic and full of information for me to work my way through!  :-+ 

I've solved the interrupt issue in BASIC by not using an interrupt  :palm:, but it's working fine.  I'm now fully engaged on studying the BASIC assembly and working out how I can hack it to include new instructions (note: I'm customizing the interpreter assembly itself, rather than adding extensions through any other means. Grant Searle managed it, so I won't let it beat me!)  :-/O

I've got an AY-3-8912 chip on its way over from China, so I'm hoping I've got enough time to work out how to add my own commands to the BASIC before it arrives and I start adding sound capabilities to my SBC and replacing the clunky IO system I have at the moment.
 

Offline C

  • Super Contributor
  • ***
  • Posts: 1346
  • Country: us
Re: Z80 Homebrew Computer - fault finding
« Reply #144 on: April 19, 2017, 05:23:40 pm »
In your reading of that and other books, you might want to keep some ideas in mind.

Dartmouth Basic was the start of Basic. What you see when you type LIST was in memory as text. Microsoft was trying to save space as well as making basic faster. A token for Print is faster to interpret then the text "Print" and also saves space.
Microsoft Basic uses tokens when running a program. Microsoft also changed some other things to make program faster and smaller. One change was to convert Line numbers to binary. There are many more changes to make it possible to load & run larger programs faster using less memory.
For Microsoft Basic when you type LIST one step in the process is convert token back to text. This then requires a Convert text to token so that you can enter a program. So you have three data items, The Text(print), The Token for print and where code to do print is located.
The TRS-80 12k rom Basic could do the Text to token & Token to Text of some commands for Disk Basic but was missing the code to do that command. With Disk Basic loaded, code for command is in memory. With out Disk Basic loaded, Return error.
The nice thing about the Rom Basic was that it was very patch able. There was locations where you could change locations in Ram that you could change to allow adding more commands & get the needed code to run.

One of the first steps on power up with out a disk system was to copy some data from rom to an area of ram. Microsoft used an assembler command that says, "Assemble this code to run at location X but store the binary at location Y. This step is very powerful as it allows patching.

Note that where the Basic program that was converted to tokens did change in Ram. The OS used overlays & some versions of Basic used overlays also. If you want to get a better understanding concept you could look at source for LDOS which you should be able to find.
One extreme Z80 system back then was the LOBO MAX80 which only had 512 bytes of rom.  Just enough Rom to load code from hard disk or floppy.

One thing that you might want to add to your bag of tricks is to connect some memory to IO space. With 3 IO addresses data used as addresses to IO Memory and one IO address data used for data, you would have 16MB of storage.
 
Put above together. On power up, CLEAR a FF. With FF cleared low memory is ROM, You can now run some boot code. With FF SET low memory is Ram. Keep it simple, On power up, copy a block of code from Rom to Ram. Jump to block of code in RAM and SET FF. This RAM code can again be simple and just copy a block of code from IO Memory to RAM  and jump to new code just loaded. Note that this code does not need to change as you improve or add to system, Code changes are made to IO memory storage which could easily be EEROM. The Z80 could write to EEROM IO Memory so you would have equal of a Flash disk drive,   

The RAM boot code could easily read an IO port to allow loading of different blocks from IO storage. You could use this to switch from what works to a new untested block of code to try and easily go back if it did not work. 



     
 

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: Z80 Homebrew Computer - fault finding
« Reply #145 on: April 19, 2017, 08:49:06 pm »
Thanks C - there's plenty for me to be getting on with there!  :-+

Here's where I'm at with the customisation of the NASCOM BASIC - I'm experimenting at the moment trying to add a custom command.  For experimentation purposes, I'm trying to create a command called TEST which displays a simple string before returning execution back to the Input Phase.

The code in the Verb Action Routines isn't the issue (I can display the text without any problems) - the issue I'm having is getting the interpreter to recognise the new command.  I've added the keyword TEST to the Reserved Word List and Verb Action Address List, as below:

Code: [Select]
; RESERVED WORD LIST

WORDS:  .BYTE   'E'+80H,"ND"
......       
        .BYTE   'C'+80H,"LEAR"
        .BYTE   'C'+80H,"LOAD"
        .BYTE   'C'+80H,"SAVE"
        .BYTE   'N'+80H,"EW"
.BYTE   'T'+80H,"EST"

And the Keyword Address Table:

Code: [Select]
; KEYWORD ADDRESS TABLE

WORDTB: .WORD   PEND
        .WORD   FOR
........
        .WORD   TEST                          ; Should have an offset of A5

But, if the keyword address table works as I think it should (and the Microsoft Basic Decoded book outlines it) then the TEST keyword should have an offset of A5.  But the next bit of code causes problems with that due to specific allocation of offsets to keywords (the TAB keyword is assigned an offset of A5...) (NOTE that offset = token, I think.)

Code: [Select]
; RESERVED WORD TOKEN VALUES

ZEND    .EQU    080H            ; END
ZFOR    .EQU    081H            ; FOR
ZDATA   .EQU    083H            ; DATA
ZGOTO   .EQU    088H            ; GOTO
ZGOSUB  .EQU    08CH            ; GOSUB
ZREM    .EQU    08EH            ; REM
ZPRINT  .EQU    09EH            ; PRINT
ZNEW    .EQU    0A4H            ; NEW

ZTAB    .EQU    0A5H            ; TAB
ZTO     .EQU    0A6H            ; TO
ZFN     .EQU    0A7H            ; FN
ZSPC    .EQU    0A8H            ; SPC
ZTHEN   .EQU    0A9H            ; THEN
ZNOT    .EQU    0AAH            ; NOT
ZSTEP   .EQU    0ABH            ; STEP

So, I've managed to get my custom code to work by redirecting an existing command (in this case CLOAD, which is redirected to the REM function anyway by Grant Searle's edits) to it, but I'd really like to be able to add my own commands without overwriting (and thus being limited in the number I can use) existing commands.

Any suggestions?  All I can get is a Syntax Error when I try to add a command.
 

Offline C

  • Super Contributor
  • ***
  • Posts: 1346
  • Country: us
Re: Z80 Homebrew Computer - fault finding
« Reply #146 on: April 20, 2017, 03:27:26 am »
Note that there were a large number of books about TRS80 that could help you. Microsoft's rom basic for the TRS80 was called Level II Basic.

Just a quick guess & from rusty memory. Think that some token values where used for other purposes. Think some could only be at start of a basic line while others could only be in middle of line. Exp  "FOR" at first while "NEXT" has to be in the line.
Expect to find constants that separate different ranges of tokens.

So as a guess your new command is not fully hooked in to all places needed or the token value falls out of range. You may need an entry in ; RESERVED WORD TOKEN VALUES

Just the quick look at Grant Searle's Basic source, Think source was a disassembly with a missing the step to be rewritten to be easy to change. Think of this, Why have a powerful assembler that could compute locations and sizes and not use this power to make source easer to change.
Keep in mind that Microsoft should have used it's most powerful assembler{macro-80 or better} to create Microsoft Basic.

In "; BASIC WORK SPACE LOCATIONS" you have a lot of
EQU

In my thinking each of these should be a data statement that reserves some space.

So a good first step could be to modify the source to use the assembler more.
Note also that there are Z80 emulators that run on linux that would let you run powerful old tools for Z80 on PC.


 

Offline C

  • Super Contributor
  • ***
  • Posts: 1346
  • Country: us
Re: Z80 Homebrew Computer - fault finding
« Reply #147 on: April 20, 2017, 05:54:30 pm »
In "Microsoft BASIC Decoded" chapter 4 is some information about the structure of some of the tables.

In "Microsoft BASIC Decoded" chapter 5 is A BASIC SORT Verb program using data from rom

Facts:
You want to add new statements (test) and have modified statement (CLOAD)
Most Basics have a PEEK & POKE statements to read and change memory.

History
If the past it was not uncommon to write a Z80 disassembler or other tool in basic. A disassembler in basic could using PEEK disassemble the Roms in a system or output the data in a format that an external disassembler could use.

Idea:
Use Basic or some assembly that is started with Basics "CLOAD" command to dump out the tables that basic uses to do it's job. This would give you the information that the Z80 was actually using at the time. If you make the output great, then you should be able to easily spot what went wrong.
The above two chapters should be some help to do this.
Note that from what I see some token values get changed from array index value as token to a lookup token value.

Using this information, I would add comment blocks in front of each block of code that processes a basic statement. Then when you come back a year from now and want to add something new you just have to read the comments and not have to relearn by reading source code how it works.

In reading the books you might not have cough on to the idea of a non basic program using parts of rom basic to make a program smaller and less work. If you have floating point math in rom why not use it in a non basic program?

Don't forget to use your tools against themselves. Think of this, Start with original source, get listing and binary. Make changes to source and get listing and binary. If original binary = changed binary, then your changes will probably fall in to better source for assembler category.

Have you compared the many different NASCOM Basic sources to see what is different between the different versions?
 

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: Z80 Homebrew Computer - fault finding
« Reply #148 on: April 21, 2017, 08:20:16 pm »
Have you compared the many different NASCOM Basic sources to see what is different between the different versions?

No I haven't.  To be honest, I've not had much luck finding any other versions of BASIC (or their source) that I could try in place of the NASCOM BASIC I currently have.  |O
 

Offline C

  • Super Contributor
  • ***
  • Posts: 1346
  • Country: us
Re: Z80 Homebrew Computer - fault finding
« Reply #149 on: April 23, 2017, 03:34:16 pm »
Some of the values below are used as token values, while some are used to compute a range of token values.
Some are NOT used at all!

Code: [Select]
; RESERVED WORD TOKEN VALUES

ZEND    .EQU    080H            ; END
ZFOR    .EQU    081H            ; FOR
ZDATA   .EQU    083H            ; DATA
ZGOTO   .EQU    088H            ; GOTO
ZGOSUB  .EQU    08CH            ; GOSUB
ZREM    .EQU    08EH            ; REM
ZPRINT  .EQU    09EH            ; PRINT
ZNEW    .EQU    0A4H            ; NEW

ZTAB    .EQU    0A5H            ; TAB
ZTO     .EQU    0A6H            ; TO
ZFN     .EQU    0A7H            ; FN
ZSPC    .EQU    0A8H            ; SPC
ZTHEN   .EQU    0A9H            ; THEN
ZNOT    .EQU    0AAH            ; NOT
ZSTEP   .EQU    0ABH            ; STEP

ZPLUS   .EQU    0ACH            ; +
ZMINUS  .EQU    0ADH            ; -
ZTIMES  .EQU    0AEH            ; *
ZDIV    .EQU    0AFH            ; /
ZOR     .EQU    0B2H            ; OR
ZGTR    .EQU    0B3H            ; >
ZEQUAL  .EQU    0B4H            ; M
ZLTH    .EQU    0B5H            ; <
ZSGN    .EQU    0B6H            ; SGN
ZPOINT  .EQU    0C7H            ; POINT
ZLEFT   .EQU    0CDH +2         ; LEFT$
Suggest you comment out all the above lines and let the assembler generate some errors if one is needed.

When you get an error for lines like the following
Code: [Select]
CALL    CHKSYN          ; Make sure "=" follows
        .BYTE      ZEQUAL          ; "=" token
change to
Code: [Select]
CALL    CHKSYN          ; Make sure "=" follows
        .BYTE      TEQUAL          ; "=" token
add the following
Code: [Select]
        .BYTE   '='+80H
   TEQUAL  .EQU    0B4H ; Token value           
.....

Do the same for ones like
Code: [Select]
CP      ZFOR            ; Is it a "FOR" token

Some are used to compute a range like this
Quote
ONJMP:  SUB     ZEND            ; Is it a token?
        JP      C,LET           ; No - try to assign it
        CP      ZNEW+1-ZEND     ; END to NEW ?
For these I would uncomment the Z____ EQU
Here I would move the ZEND EQU to before
Code: [Select]
WORDS:  .BYTE   'E'+80H,"ND"
and ZNEW after the proper line

Note that ZEND = First token value
ZNEW is Last statement token value with the following tokens being part of a statement.
Between ZSTEP & ZPLUS is a shift to reserved words as operators

ZSGN marks start of functions as reserved words.
Code: [Select]
[
ZSGN    .EQU    0B6H            ; SGN FIRST FUNCTION TOKEN

The result of these changes lets you easily tell what is just a token value that can be changed and what is a range of tokens.

Something like this
Code: [Select]
        .BYTE   'N'+80H,"EW"
; Add new statements here
ZNEW    .EQU    0A4H            ; NEW
: ZNEW should be last statement token value above
        .BYTE   'T'+80H,"AB("
TTAB    .EQU    ZNEW+1 ;0A5H            ; TAB TOKEN
        .BYTE   'T'+80H,"O"
TTO     .EQU    TTAB+1 :0A6H            ; TO TOKEN
        .BYTE   'F'+80H,"N"
TFN     .EQU    TTO+1 ;0A7H            ; FN TOKEN
        .BYTE   'S'+80H,"PC("
TSPC    .EQU    TFN+1 ;0A8H            ; SPC TOKEN
        .BYTE   'T'+80H,"HEN"
TTHEN   .EQU    TSPC+1 ;0A9H            ; THEN TOKEN
        .BYTE   'N'+80H,"OT"
TNOT    .EQU    TTHEN+1 ;0AAH            ; NOT TOKEN
        .BYTE   'S'+80H,"TEP"
TSTEP   .EQU    TNOT+1 ;0ABH            ; STEP TOKEN
; Operators below
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf