SDX High Memory

About the BASIC system (not including PROGRAMMING)
Bill B
Posts: 232
Joined: 26 Jan 2014 16:31

SDX High Memory

Post by Bill B » 24 Mar 2020 18:26

I have been trying to improve my understanding of exactly what use SDX BASIC makes of high memory (above 0xC000).

The first thing I found is that only part of high memory is initialised when you first start the system. A lot more is loaded into high memory when you issue a USER command.

To investigate further, I used MEMU to emulate an SDX, issued the command USER DIR "A:", and then dumped the contents of memory to a file (<F9+d> for Andy's MEMU, or <F10+d> for my fork). I am now attempting to disassemble the resulting memory dump. Some of the address labels can be obtained from file SDXHIGH.INC from Andy's ROM source here.

I have only just started, but have already come across a few puzzles:
  • The start of the equivalent of BDOS is at D706. The BDOS function code (C register) is eventually tested for validity at D733. However the test is for values less than #29 (hex=41 dec). However my documentation of BDOS functions for CP/M 2.2 only goes up to #24. So what are #25 - #28?
  • The value of C is then used to select an address from a jump table starting at D747. However, looking at some of the addresses in this table:
    • #02. Console output => Address D890.
    • #0A. Read console buffer => Address D8E1.
  • These addresses fall in the range occupied by the file control blocks CHNL1 to CHNL5 (D840 to D911). In the memory dump this range is mostly zero filled, but in general will change as files are opened and closed. So these two BDOS functions clearly cannot work.
  • Similarly, the routine starting at D823 contains jumps to D845 (from D827) and D842 (from d835). So again this routine cannot work.
So it looks as though the file control blocks have been placed on top of part of the BDOS, rendering it not fully functional. :?

Code: Select all

LSTHIGH:        DEFB    #4B, #16, #00, #00, #1F, #69                                    ; D700 D700 4B 16 00 00 1F 69    Start of BDOS (JP JP59K)
JP59K:          JP      LD711                                                           ; D706 D706 C3 11 D7
LD709:          SBC     A,C                                                             ; D709 D709 99
                RST     L0010                                                           ; D70A D70A D7
                DEFB    #A5                                                             ; D70B D70B A5    Send 5 bytes to screen.
                DEFS    "\D7\AB\D7\B1\D7"                                               ; D70C D70C D7 AB D7 B1 D7
LD711:          EX      DE,HL                                                           ; D711 D711 EB
                LD      (XDA43),HL                                                      ; D712 D712 22 43 DA
                EX      DE,HL                                                           ; D715 D715 EB
                LD      A,E                                                             ; D716 D716 7B
                LD      (XE4D6),A                                                       ; D717 D717 32 D6 E4
                LD      HL,#0000                                                        ; D71A D71A 21 00 00
                LD      (XDA45),HL                                                      ; D71D D71D 22 45 DA
                ADD     HL,SP                                                           ; D720 D720 39
                LD      (XDA0F),HL                                                      ; D721 D721 22 0F DA
                LD      SP,XDA00                                                        ; D724 D724 31 00 DA
                XOR     A                                                               ; D727 D727 AF
                LD      (XE4E0),A                                                       ; D728 D728 32 E0 E4
                LD      (XE4DE),A                                                       ; D72B D72B 32 DE E4
                LD      HL,LE474                                                        ; D72E D72E 21 74 E4
                PUSH    HL                                                              ; D731 D731 E5
                LD      A,C                                                             ; D732 D732 79
                CP      #29                                                             ; D733 D733 FE 29
                RET     NC                                                              ; D735 D735 D0
                LD      C,E                                                             ; D736 D736 4B
                LD      HL,XD747                                                        ; D737 D737 21 47 D7
                LD      E,A                                                             ; D73A D73A 5F
                LD      D,#00                                                           ; D73B D73B 16 00
                ADD     HL,DE                                                           ; D73D D73D 19
                ADD     HL,DE                                                           ; D73E D73E 19
                LD      E,(HL)                                                          ; D73F D73F 5E
                INC     HL                                                              ; D740 D740 23
                LD      D,(HL)                                                          ; D741 D741 56
                LD      HL,(XDA43)                                                      ; D742 D742 2A 43 DA
                EX      DE,HL                                                           ; D745 D745 EB
                JP      (HL)                                                            ; D746 D746 E9
XD747:          DEFW    LE503, LD9C8, LD890, LD9CE, LE512, LE50F, LD9D4, LD9ED          ; D747 D747 03 E5 C8 D9 90 D8 CE D9 12 E5 0F E5 D4 D9 ED D9
                DEFW    LD9F3, LD9F8, LD8E1, LD9FE, LE37E, LE383, LE345, LE39C          ; D757 D757 F3 D9 F8 D9 E1 D8 FE D9 7E E3 83 E3 45 E3 9C E3
                DEFW    LE3A5, LE3AB, LE3C8, LE3D7, LE3E0, LE3E6, LE3EC, LE3F5          ; D767 D767 A5 E3 AB E3 C8 E3 D7 E3 E0 E3 E6 E3 EC E3 F5 E3
                DEFW    LE3FE, LE404, LE40A, LE411, LDC2C, LE417, LE41D, LE426          ; D777 D777 FE E3 04 E4 0A E4 11 E4 2C DC 17 E4 1D E4 26 E4
                DEFW    LE42D, LE441, LE447, LE44D, LE30E, LE453, LDA04, LDA04          ; D787 D787 2D E4 41 E4 47 E4 4D E4 0E E3 53 E4 04 DA 04 DA
                DEFW    LE49B                                                           ; D797 D797 9B E4
                LD      HL,XD7CA                                                        ; D799 D799 21 CA D7
                CALL    LD7E5                                                           ; D79C D79C CD E5 D7
                CP      #03                                                             ; D79F D79F FE 03
                JP      Z,LEC46                                                         ; D7A1 D7A1 CA 46 EC    Select ROM 0 and return to BASIC
                RET                                                                     ; D7A4 D7A4 C9
LD7A5:          LD      HL,XD7D5                                                        ; D7A5 D7A5 21 D5 D7
                JP      LD7B4                                                           ; D7A8 D7A8 C3 B4 D7
LD7AB:          LD      HL,XD7E1                                                        ; D7AB D7AB 21 E1 D7
                JP      LD7B4                                                           ; D7AE D7AE C3 B4 D7
LD7B1:          LD      HL,XD7DC                                                        ; D7B1 D7B1 21 DC D7
LD7B4:          CALL    LD7E5                                                           ; D7B4 D7B4 CD E5 D7
                JP      LEC46                                                           ; D7B7 D7B7 C3 46 EC    Select ROM 0 and return to BASIC
DSKMSG:         DEFS    "Bdos Err On "                                                  ; D7BA D7BA 42 64 6F 73 20 45 72 72 20 4F 6E 20    Disk error message
DSKERR:         DEFS    " : $"                                                          ; D7C6 D7C6 20 3A 20 24
XD7CA:          DEFS    "Bad Sector$"                                                   ; D7CA D7CA 42 61 64 20 53 65 63 74 6F 72 24
XD7D5:          DEFS    "Select$"                                                       ; D7D5 D7D5 53 65 6C 65 63 74 24
XD7DC:          DEFS    "File "                                                         ; D7DC D7DC 46 69 6C 65 20
XD7E1:          DEFS    "R/O$"                                                          ; D7E1 D7E1 52 2F 4F 24
LD7E5:          PUSH    HL                                                              ; D7E5 D7E5 E5
                LD      BC,#D80E                                                        ; D7E6 D7E6 01 0E D8
                CALL    LD804                                                           ; D7E9 D7E9 CD 04 D8
                LD      A,(XDA42)                                                       ; D7EC D7EC 3A 42 DA
                ADD     A,#41                                                           ; D7EF D7EF C6 41
                LD      (DSKERR),A                                                      ; D7F1 D7F1 32 C6 D7
                LD      BC,DSKMSG                                                       ; D7F4 D7F4 01 BA D7
                CALL    LD804                                                           ; D7F7 D7F7 CD 04 D8
                POP     BC                                                              ; D7FA D7FA C1
                CALL    LD804                                                           ; D7FB D7FB CD 04 D8
                CALL    L0079                                                           ; D7FE D7FE CD 79 00
                JR      Z,LD7FE                                                         ; D801 D801 28 FB
                RET                                                                     ; D803 D803 C9
LD804:          LD      A,(BC)                                                          ; D804 D804 0A
                CP      #24                                                             ; D805 D805 FE 24
                RET     Z                                                               ; D807 D807 C8
                CALL    L0CAB                                                           ; D808 D808 CD AB 0C
                INC     BC                                                              ; D80B D80B 03
                JR      LD804                                                           ; D80C D80C 18 F6
CRLF0:          DEFS    "\0D\0A$\00"                                                    ; D80E D80E 0D 0A 24 00
                POP     AF                                                              ; D812 D812 F1
                RET                                                                     ; D813 D813 C9
LD814:          CP      #0D                                                             ; D814 D814 FE 0D
                RET     Z                                                               ; D816 D816 C8
                CP      #0A                                                             ; D817 D817 FE 0A
                RET     Z                                                               ; D819 D819 C8
                CP      #09                                                             ; D81A D81A FE 09
                RET     Z                                                               ; D81C D81C C8
                CP      #08                                                             ; D81D D81D FE 08
                RET     Z                                                               ; D81F D81F C8
                CP      #20                                                             ; D820 D820 FE 20
                RET                                                                     ; D822 D822 C9
LD823:          LD      A,(XDA0E)                                                       ; D823 D823 3A 0E DA
                OR      A                                                               ; D826 D826 B7
                JP      NZ,LD845                                                        ; D827 D827 C2 45 D8
                CALL    LE506                                                           ; D82A D82A CD 06 E5
                AND     #01                                                             ; D82D D82D E6 01
                RET     Z                                                               ; D82F D82F C8
                CALL    LE509                                                           ; D830 D830 CD 09 E5
                CP      #13                                                             ; D833 D833 FE 13
                JP      NZ,LD842                                                        ; D835 D835 C2 42 D8
                CALL    LE509                                                           ; D838 D838 CD 09 E5
                CP      #03                                                             ; D83B D83B FE 03
                JP      Z,L0000                                                         ; D83D D83D CA 00 00
CHNL1:          DEFB    #00, #00                                                        ; D840 D840 00 00    File control block
LD842:          DEFB    #00, #00, #00                                                   ; D842 D842 00 00 00
LD845:          DEFB    #00, #00, #00, #00, #00, #00, #00, #00                          ; D845 D845 00 00 00 00 00 00 00 00
                DEFB    #00, #00, #00, #00, #00, #00, #00, #00                          ; D84D D84D 00 00 00 00 00 00 00 00
                DEFB    #00, #00, #00, #00, #00, #00, #00, #00                          ; D855 D855 00 00 00 00 00 00 00 00
                DEFB    #00, #00, #00, #00, #00, #00, #00, #00                          ; D85D D85D 00 00 00 00 00 00 00 00
                DEFB    #00, #00, #00, #00, #00                                         ; D865 D865 00 00 00 00 00
CHNL2:          DEFB    #00, #00, #00, #00, #00, #00, #00, #00                          ; D86A D86A 00 00 00 00 00 00 00 00    File control block
                DEFB    #00, #00, #00, #00, #00, #00, #00, #00                          ; D872 D872 00 00 00 00 00 00 00 00
                DEFB    #00, #00, #00, #00, #00, #00, #00, #00                          ; D87A D87A 00 00 00 00 00 00 00 00
                DEFB    #00, #00, #00, #00, #00, #00, #00, #00                          ; D882 D882 00 00 00 00 00 00 00 00
                DEFB    #00, #00, #00, #00, #00, #00                                    ; D88A D88A 00 00 00 00 00 00
LD890:          DEFB    #00, #00, #00, #00                                              ; D890 D890 00 00 00 00
CHNL3:          DEFB    #00, #00, #00, #00, #00, #00, #00, #00                          ; D894 D894 00 00 00 00 00 00 00 00    File control block
                DEFB    #00, #00, #00, #00, #00, #00, #00, #00                          ; D89C D89C 00 00 00 00 00 00 00 00
                DEFB    #00, #00, #00, #00, #00, #00, #00, #00                          ; D8A4 D8A4 00 00 00 00 00 00 00 00
                DEFB    #00, #00, #00, #00, #00, #00, #00, #00                          ; D8AC D8AC 00 00 00 00 00 00 00 00
                DEFB    #00, #00, #00, #00, #00, #00, #00, #00                          ; D8B4 D8B4 00 00 00 00 00 00 00 00
                DEFB    #00, #00                                                        ; D8BC D8BC 00 00
CHNL4:          DEFB    #00, #00, #00, #00, #00, #00, #00, #00                          ; D8BE D8BE 00 00 00 00 00 00 00 00    File control block
                DEFB    #00, #00, #00, #00, #00, #00, #00, #00                          ; D8C6 D8C6 00 00 00 00 00 00 00 00
                DEFB    #00, #00, #00, #00, #00, #00, #00, #00                          ; D8CE D8CE 00 00 00 00 00 00 00 00
                DEFB    #00, #00, #00, #00, #00, #00, #00, #00                          ; D8D6 D8D6 00 00 00 00 00 00 00 00
                DEFB    #00, #00, #00                                                   ; D8DE D8DE 00 00 00
LD8E1:          DEFB    #00, #00, #00, #00, #00, #00, #00                               ; D8E1 D8E1 00 00 00 00 00 00 00
CHNL5:          DEFB    #01, #3F, #3F, #3F, #3F, #3F, #3F, #3F                          ; D8E8 D8E8 01 3F 3F 3F 3F 3F 3F 3F    File control block
                DEFB    #3F, #3F, #3F, #3F                                              ; D8F0 D8F0 3F 3F 3F 3F
LINPUT:         DEFB    #00, #00                                                        ; D8F4 D8F4 00 00
IXTEMP:         DEFB    #00, #00                                                        ; D8F6 D8F6 00 00
STORE:          DEFB    #00, #00, #00, #00, #00, #00, #00, #00                          ; D8F8 D8F8 00 00 00 00 00 00 00 00
                DEFB    #00, #00, #00, #00, #00, #00, #00, #00                          ; D900 D900 00 00 00 00 00 00 00 00
                DEFB    #00, #00, #00, #00, #00, #00, #00, #00                          ; D908 D908 00 00 00 00 00 00 00 00
                DEFB    #00, #00                                                        ; D910 D910 00 00

Martin A
Posts: 449
Joined: 09 Nov 2013 21:03

Re: SDX High Memory

Post by Martin A » 25 Mar 2020 00:36

The SDX only uses the BDOS part of CPM. It has the BASIC ROM calls for things like keyboard and display handling.

All of the function calls below 12 or so are redundant. I'm on the wrong computer to check the SDX rom source, but I'm not sure it even loads the BIOS tracks.

Bill B
Posts: 232
Joined: 26 Jan 2014 16:31

Re: SDX High Memory

Post by Bill B » 26 Mar 2020 10:06

Agree, not all the BDOS is required for the SDX, but it is an interesting compromise:
  • The simplest solution would have been to load the BDOS/BIOS in full, and place the file control blocks and other data structures below that. This would however use the maximum amount of high memory.
  • Putting these data structures on top of the BDOS reduces the high memory used. However it must have been a significant amount of work to decide where these structures could be put without breaking required functionality. And it still leaves a significant amount of dead code occupying memory.
  • Would it have been much more work to re-implement the BDOS / BIOS, retaining only the functions actually required? This would have freed more high memory,
  • Even better, a lot of the routines in high memory could have been implemented in ROM, with just the entry points in high memory, freeing even more space.
So I wonder why Memotech chose the approach they did :?

I am also curious as to the development history. Was FDXB developed first, and then SDX BASIC derived from that?

Martin A
Posts: 449
Joined: 09 Nov 2013 21:03

Re: SDX High Memory

Post by Martin A » 26 Mar 2020 15:49

I imagine the main reason was compatibility, or possibly speed of implementation. The SDX used the same discs as the FDX. Which means the BIOS/BDOS is optimised for CPM. The SDX just makes the best use of the "borrowed" code. When I got the upgrade form the original big box SDX to CPM, FDXB was able to load and use the discs and the basic programs saved on the SDX (including the tape games I'd managed to "convert").

The SDX rom, when it reads the system track, patches it on the fly to deal with the "non CPM" environment. There are only 16 word sized addresses that are changed. Adding in full relocation would have been much more complex given that it's 8080 code and uses JMP and CALL a LOT .

I've been able to check the SDX source, this is the file with the CPM calls SDX uses. The lowest call used is 13 and the highest 35 (decimal), But the equates were there for up to 40. For my builds I've commented the unused ones out to speed up assembly.

In MP/M or CPM 3.1 call 37 (#25) is reset drive and 40 (#28) is write random with zero fill. Could the rom have been developed on a CPM3.1 system ??

Code: Select all

; BDOS.INC  Basic BDOS function numbers etc.
;
;  BDOS    EQU     &05
;  TRUE    EQU     &FFFF
;  FALSE   EQU     &0000
;  K       EQU     1024
;  CONIN   EQU     1
;  CONOUT  EQU     2
;  RDRIN   EQU     3
;  PUNOUT  EQU     4
;  LSTOUT  EQU     5
;  DCONIO  EQU     6
;  GETIOB  EQU     7
;  SETIOB  EQU     8
;  PRINTF  EQU     9
;  RCBUFF  EQU     10
;  CONST   EQU     11
;  RETVER  EQU     12
   RESDSC  EQU     13
   SELDSC  EQU     14
   OPENF   EQU     15
   CLOSEF  EQU     16
   SFF     EQU     17
   SFN     EQU     18
   DELFIL  EQU     19
;  RSEQ    EQU     20
;  WSEQ    EQU     21
   MAKFIL  EQU     22
   RENFIL  EQU     23
;  RETLV   EQU     24
   RCDSC   EQU     25
   SETDMA  EQU     26
   GETAA   EQU     27
;  WPDSC   EQU     28
;  GETROV  EQU     29
   SFATTR  EQU     30
   GETDPB  EQU     31
;  GSUSR   EQU     32
   RRAN    EQU     33
   WRAN    EQU     34
   CFSIZE  EQU     35
;  SETRR   EQU     36
;  RESDRV  EQU     37
;  WRANF   EQU     40
;  FCB1    EQU     &5C
;  FCB2    EQU     &6C
;  R0      EQU     33
;  R1      EQU     34
;  R2      EQU     35
The early FDX systems were shipped with Mbasic according to the PCW review because FDXB wasn't ready. I got my FDX single - AKA big box SDX and upgraded it to CPM, so the SDX method of borrowing from CPM might well have pre-dated FDXB.

Bill B
Posts: 232
Joined: 26 Jan 2014 16:31

Re: SDX High Memory

Post by Bill B » 26 Mar 2020 17:10

It turns out that functions #25 and #28 are implemented in CP/M 2.2, see the source here. Presumably just not documented.

I suppose what I am really questioning is why SDX makes use of the system tracks from the drive rather than just implementing everything in ROM. Was it really much quicker to spend the time needed to understand the BDOS well enough to patch and overlay it?

One possibility might be that this approach worked around any Digital Research copyright on the CP/M drive format.

Martin A
Posts: 449
Joined: 09 Nov 2013 21:03

Re: SDX High Memory

Post by Martin A » 26 Mar 2020 17:57

FDXB seems to have a vanilla copy of a large chunk of the BIOS/BDOS in it's final 8k. That too only uses the disc functions and probably for space reasons doesn't include the low functions at all. That top 8k also has to hold the low level drivers for the screen and discs as well as the basic extensions.

Since everything required does fit in 8k, space can't be the reason for not using a rom on the SDX. There is a fair bit of self modifying code, so that could be part of it I guess. FDXB runs in ram like CPM so no changes were needed for that.

If it's any help working out what the SDX is doing, there's a buildable version of FDXB in the archive attached, some of it is even doccumented!
BuildMTX.zip
(87.38 KiB) Downloaded 2 times

Bill B
Posts: 232
Joined: 26 Jan 2014 16:31

Re: SDX High Memory

Post by Bill B » 26 Mar 2020 19:39

Thinking about this has raised a side question: Was there ever a manual for SDX BASIC? I never had one, and I don't see one on Dave's site.

There is documentation for FDXB, and mostly you can just replace "DISC" by "USER". But FDXB relies upon CP/M to do disk formatting. So there are some commands that are not documented.

It was thinking about formatting that raised the question. In CP/M if you just format a disk in CP/M it does not have the BDOS installed. Such disks are probably not usable on an SDX, certainly single drive systems. It is necessary to do SYSCOPY after formatting to write the BDOS.

What does the SDX do when formatting? Does it make a clean copy of the system tracks somewhere in memory to then install on the newly formatted drive? Or does it just copy the corrupted version from high memory? The latter would work for the SDX. However it would not be bootable (only readable) under CP/M. I will have to take a look at the ROM source.

Bill B
Posts: 232
Joined: 26 Jan 2014 16:31

Re: SDX High Memory

Post by Bill B » 26 Mar 2020 19:52

Looking at the ROM source there is a USER SYSCOPY command. This works by making a clean copy of the system tracks on a source disk, and then writing them back to the destination disk. Only issue is that the copy of the system tracks is placed at 0x8000, potentially overwriting any loaded program.

Martin A
Posts: 449
Joined: 09 Nov 2013 21:03

Re: SDX High Memory

Post by Martin A » 26 Mar 2020 21:14

The MTX wouldn't be the first system of that era, overwriting a program in memory.

The C64 would do that getting a directory listing. Acorn DFS needed a separate format program trashing the program in memory.

I haven't looked, but I'd hazard a guess SDX USER FORMAT probably wasn't too careful where it built the track data ready for writing to the disc ?

Memory was so short in the machines of the era using main memory for the disc buffer in copy etc must be pretty common. But trashing it without a warning is a bit naughty :oops:

The FDX single did come with a manual, but my copy is long gone. Hopefully someone with an SDX will be able to confirm. CFX's help screen info came form the FDXB manual.

Bill B
Posts: 232
Joined: 26 Jan 2014 16:31

Re: SDX High Memory

Post by Bill B » 26 Mar 2020 22:22

It is perhaps significant that back in the day I did not even know I had SDX ROM BASIC. Whenever I wanted BASIC with disk support I used FDXB.

I think I even asked Memotech about it when I first got the drive, as I was not anticipating the extra cost of having to buy an 80 column monitor needed for CP/M.

Post Reply