Retrochallenge 2016/01:
Maze War for Olivetti M10 and NEC PC-8201A

Episode 10: Cross-Platform ROM Diving

Last time we were musing about speed, this time it's about broadening compatibility.

Cross-referenced System ROM Diving

Who's afraid of getting wet?

Virtual T

Finally I found some time to play around with Virtual T, the well known TRS-80 Modell 100 & Co emulator, available for almost any host system. Well, this is a great little program — and it's not just an emulator, it also includes an IDE, assembler and disassembler, etc. And with the dissassembler comes a commented ROM view for each of the supported models. That is, Model 100, Model 102, Model 200, Olivetti M10 (apparently a European ROM version), the NEC PC-8201A ("A" please, the "PC-8201" as labeled in the menus is a different machine), and the Kyotronic 85.

*****

Interlude — Short Rant

Like the majority of the Model 100 community, Virtual T is a bit US-centric. Especially the keyboard.
At least in the Mac version the keyboard input is hard wired to low-level US key mappings. At least on a Mac that is somewhat unheard of. Also, at least on a Mac, the keyboard input is quite laggy: Often it takes 4 or 5 attempts to register a keypress, especially with shifted key strtrokes. — This is really a pity, as this renders an otherwise great program somewhat unuseable, at least for the emulator part. *Sniff*

(I know, I should be using a US keyboard for programming, but using this chicklet keyboard of the MBA is already bad enough. Yes, for a chicklet type it's great, but can I please have a full travel mechanical one, trading in some fractions of a centimeter in thickness? Yes, it's an Air, but the MBP doesn't make much of a difference either. Ahh — there are these Kyocera things with full travel Alps … See you later!)

*****

Anyway, back to ROMs and the "Disassembly" view of Virtual T. This provides a really useful recource, as the listings are well commented and commented in a similar way across models, by this also providing a sensible cross-reference. *kudos* Even more so, as there are also commented listings for the TRS-80 Model 102 and the Kyotronic 85, which are not to be found in the usual archives.

Thanks to these resources of fruitful study, we may add two other machines to our compatibility list, namely the TRS-80 Model 102 and the Kyotronic 85. Leaving the TRS-80 Model 200 aside, because this really is quite a different breed, alone for its display dimensions, we're finally able to attempt support for most machines of the family.
(There are still some exceptions, like the Japan-only NEC PC-8201 and the NEC PC-8300. Also, I haven't found anything on the US-version of the Olivetti M10 with the built-in modem option, and there are apparently some local markets versions of the TRS-80 Model 102 featuring different ROM addresses, compare the notes below.)

Kyocera Model Characteristics

Here's a comprehensive list of the known features and differences of the various members of the Kyocera family, as of concern for this project:

Model:Model 100Model 102NEC PC-8201ANEC PC-8201 (JP)Olivetti M10 (EU)Kyotronic 85
PEEK(1):51167148– ? –35225
BASIC System Call:CALLCALLEXECEXECCALLCALL
VARPTR():YesYesNoNoYesYes
LINE command:YesYesNoNoYesYes
HIMEM system variable:YesYesNoNoYesYes
VARPTR():YesYesNoNoYesYes
Cursor Positioning:PRINT@PRINT@LOCATELOCATEPRINT@PRINT@
ANSI Escapes (VT-52):YesYesYesYesYesYes
Disable Interrupts:0x765C0x765C0x76E5– ? –0x73760x730A
Enable Interrupts:0x743C0x743C0x74C0– ? –0x71460x70EA
Keyboard Buffer Cnt.:0xFFAA0xFFAA0xFE68– ? –0xFF6D0xFF6B
Port A (LCD select 1):0xB90xB90xB90xB90xB90xB9
Port B (LCD select 2):0xBA0xBA0xBA0xBA0xBA0xBA
LCD Control Port:0xFE0xFE0xFE0xF00xFE0xFE
LCD Data Port:0xFF0xFF0xFF0xF10xFF0xFF
TELCOM Settings:bwpsxbwpsxbpwsxcbpwsxcbwpsxbwpsx

Note: Apparently, inferring from peeks into ROM-dumps, the NEC PC-8300 is identical to the NEC PC-8201A in all areas relevant to our project, including the boot vector used here as the model ID. Thus, a NEC PC-8300 should do fine with the program, even as it will be recognized as its earlier sister model. Mind that this is not tested. (While Virtual T doesn't emulate the NEC PC-8300 in the standard built, the source comes with a binary dump of its ROM. My conclusions are solely based on this single ROM dump.)

Notes

Informations on the TRS-80 Model 100 and Model 102, the NEC PC-8201A, the Olivetti M-10, and the Kyotronic 85 are based on ROM listings and technical manuals. TRS-80 Model 100 and Model 102 are for our concerns identical, but for the model ID retrieved by PEEK(1).

No information at all can be provided for the NEC 8300. Info on the NEC PC-8201 is partial only, based on the Personal Computer Service Manual NEC PC-8201 (NEC Corporation, 1983).

! Apparently, there are versions with different ROMs of the TRS-80 Model 102 (e.g., Australian version w/o modem) and maybe of the TRS-80 Model 100, too. Nothing can be said about these, sorry. Also, ROM-listings of the Olivetti M10 are all for the European/international version w/o modem. I don't know, if there were any differences in addresses to the US-version with the built-in modem. (The modem-less European version features some unused memory pointers in ROM, which were probably used by the models including the modem option. So, most addresses may be similar, but there is no guarantee.)

System Calls

Most of the models use the BASIC command CALL for system calls with the following syntax:

CALL address [, A [, HL] ] 

address ... address to be called (2 bytes)
A ......... value (1 byte) to be transferred to reg. A (accumulator), defaults to 0
HL ........ value (2 bytes) to be transferred to regs. HL, defaults to 0

The N85-BASIC of the NEC models provides the EXEC command, taking a single argument. Additional values may be supplied by POKES to specific addresses (and may also be retrieved by PEEKs from them after the ML program returns from execution):

EXEC address

address .......... address to be called (2 bytes)

0xF9A7 (63911) ... value (1 byte) for/of reg. A (accumulator), set by "POKE 63911!,V"
0xF9A8 (63912) ... value (1 byte) for/of reg. H, set by "POKE 63912!,V"
0xF9A9 (63913) ... value (1 byte) for/of reg. L, set by "POKE 63913!,V"

Note on N85-BASIC in general: Most of the differences found here in comparison to the MS BASIC dialect of the other Kyocera machines are supposedly due to an attempt at a closer compatibility with GW-BASIC. All the keywords missing on the NEC machines are also missing in GW-BASIC. The same is true for additional or alternate keywords, like EXEC or LOCATE (see below), which are also found in GW-BASIC.

VARPTR()

The BASIC function VARPTR() returns the start location in memory of a variable or array subscript, which's name is provided as the (single) argument.

The N85-BASIC of the NEC models doesn't provide this keyword, but a similar functionallity can be achieved by calling ROM address 0x49AF on the NEC PC-8201A. A simple machine language program (i8085) transfers the arguments to and from this ROM routine:

; Emulation of VARPTR() for the NEC PC-8201A (Steve Sarna, 11/12/84)

0xF370 (62320)   CD AF 49   CALL 49AF
0xF373 (62323)   EB         XCHG
0xF374 (62324)   3A 8B FA   LDA FA8B
0xF377 (62327)   C9         RET
0xF378 (62328)    0                    ; ASCII values of variable name,
                  0                    ; 8 bytes max, zero-padded.
                  0
                  0
                  0
                  0
0xF37F (62335)    0

Address 0xF378 is to be supplied in the HL registers upon calling,
as in the BASIC sequence (compare the sytax of EXEC provided above):

100 POKE 63912!,120 : REM 0x78
110 POKE 63913!,243 : REM 0xF3
120 EXEC 62320!     : REM call 0xF370

See the BASIC program file "VARPTR.NEC" by Steve Sarna (11/12/84) for usage.

And here is another implementation by Gary Weber:

40000 H=0:L=0:TY=0
40010 POKE64448,205:POKE64449,175:POKE64450,73:POKE64451,235
40020 POKE64452,58:POKE64453,139:POKE64454,250:POKE64456,201
40030 IFVY$=""THENPRINT"VY$ not defined!":STOP
40040 FORH=64457TO64463:POKEH,ASC(MID$(VY$,H,1)+CHR$(0)):NEXT:POKE64464,0
40050 POKE63912,201:POKE63913,251:EXEC64448
40060 L=PEEK(63912!):H=PEEK(63913!):TY=PEEK(63911!)
40070 RETURN
40080 ' VARPTR by Gary Weber
40090 ' Entry: VY$ must contain the name of variable of interest
40100 ' Exit: H & L contain variable's address, TY contains type
40110 ' Example:
40120 '   100 A$="This is a sample string."
40130 '   110 VY$="A$":GOSUB 40000
40140 '   120 PRINT "VARPTR of "VY$;" is "L+(H*256)

! Please mind that these programs do not apply to the NEC PC-8300 nor to the NEC PC-8201 (Japanese markets only) for the differences in ROM addresses. Since there are — at least to my humble knowledge — no ROM listings available for them, no advice can be given on this subject.

HIMEM

The pointer to the top of the RAM used by BASIC and its resources isn't available as a system variable in NEC's N85-BASIC. On the PC-8201A, it can be retrieved from memory locations 0xF384 and 0xF384 (lo, hi; decimal 62340, 62341) instead.

Cursor Positioning

Instead of the usual PRINT@ command of MS BASIC, the N85-BASIC of the NEC machines provides a LOCATE command dedicated to the sole purpose of positioning the cursor randomly on the screen, both in terms of X and Y coordinates. (We may assume this to be a bit more of a practical solution to the problems of screen-oriented application layout, but it may not be so great when it comes to cross-platform applications for models of different or unknown screen size.)

Still, there is common ground, namely in the form of ANSI escape sequences (VT-52), including cursor positioning in rows and columns. The codes are the same across all Kyocera models (and this is also the only row in our table where the entries are the same for all the models listed).

TELCOM Settings

For details on the serial line settings, their options and semantics, please refer to Episode #2.

ROM Addresses

Apart from the Model 100 and Model 102 which, while showing some differences, share wide regions of their respective ROMs, near to all addresses and call vectors are different for each of the machines. Don't be tempted by superficial similarities to attempt to use the calls of a distinct model for any other of the family. But, while routines are found at different locations, most models share similar code. There are minor differences, but in terms of basic functions, what can be found on one machine is probably also to be found on all the others.

This is nicely illustrated by the value returned by PEEK(1), being actually the low-byte of the reset vector pointing to the boot routine. While the various models are organized and laid out in a similar fashion, the specific location is that unique that it serves well as a unique model ID (or, in vintage Apple terms, Gestalt.).

There are a few example of perplexity to be found across various fori on ROM calls for one machine not working on others. This shouldn't cause much wonder in the light of the machines as we have learned to know them here.

*****

As for our little project, as already mentioned before, we're going to broaden our compatibility list to 5 models, namely the TRS-80 Model 100 and it's successor, Model 102, the NEC PC-8201A, the Olivetti M10, and the Kyotronic 85, as well. We'll include specific setup code for them in the next versions of the program. (With the NEC PC-8300 being apparently identical to the PC-8201A for our purpose, this would even add a sixth model to our list, without any special efforts on our side.)

Also, I've come up with plans for the implementation of the perspective view into the maze, but this is another story.

*****

P.S.: As for our musings on the history and nature of the Kyocera family, by looking at the various ROMs we may conclude that the Kyotronic 85 was not the original model or reference platform used as the example and as a template for the other machines. At least, there are some unused memory pointers and some unused areas in ROM, suggesting that this was rather a down-sized version of a ROM of a model more rich in features, like the TRS-80 Model 100, than an original that was the first to market and provided a starting point for the other ones.

 

Next:   Episode 11: A Path to the Maze

Previous:   Episode 9: Quest for Speed

Back to the index.

— This series is part of Retrochallenge 2016/01. —