Giter VIP home page Giter VIP logo

runcpm's People

Contributors

csoren avatar dastels avatar drawkula avatar dressupgeekout avatar ethandicks avatar geowar1 avatar guidol70 avatar kant avatar kklis avatar mecparts avatar mikecornflake avatar mockbatheborg avatar polluks avatar pzembrod avatar ravn avatar sijnstra avatar tomxp411 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

runcpm's Issues

readme.md ... open questions.

32bit?

RunCPM is a 32 bits application which allows you to execute old CP/M 8 bits programs on Windows, Mac OS X, Linux, FreeBSD, MS-DOS and Arduino DUE.

I don't use any compiler options on Debian to force 32bit code generation...

runcpm/src/RunCPM/RunCPM$ file RunCPM
RunCPM: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=eb4fa888e367bcf02ffba3dbfb2f394b8d345bf1, not stripped

...so what is dropping out of the compiler is a 64bit executable.

Getting Started

...needs to mention the user areas now and where to drop the contents from A.ZIP and/or packing A.ZIP to contain the path A/0 may be an option...

RunCPM has an icon now...

As seen in commit 492c868 RunCPM has an icon now.

Maybe this is the moment to update RunCPM's gallery at hackaday.io?

20181110-093146-gmt--just_for_fun
20181110-095045-gmt--just_for_fun

Okay... this Sixel stuff maybe is overshooting a bit but RunCPM's page(s) at hackaday.io might benefit from an update due to the added platform(s) and other improvements.

Cannot compile

Trying to compile latest download (as of today) and i get an overflow for the RAM array.

Not sure where it's coming from I've tried compiling for the uno (the actual target) but also for the mega and the due and they all get the same thing

D:\Arduino\arduino-builder -dump-prefs -logger=machine -hardware D:\Arduino\hardware -hardware C:\Users\Charles Blackburn\AppData\Local\Arduino15\packages -tools D:\Arduino\tools-builder -tools D:\Arduino\hardware\tools\avr -tools C:\Users\Charles Blackburn\AppData\Local\Arduino15\packages -built-in-libraries D:\Arduino\libraries -libraries C:\Users\Charles Blackburn\Documents\Arduino\libraries -fqbn=arduino:avr:uno -ide-version=10804 -build-path C:\Users\CHARLE1\AppData\Local\Temp\arduino_build_416580 -warnings=none -build-cache C:\Users\CHARLE1\AppData\Local\Temp\arduino_cache_784956 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.arduinoOTA.path=C:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\tools\arduinoOTA\1.1.1 -prefs=runtime.tools.avrdude.path=C:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino9 -prefs=runtime.tools.avr-gcc.path=C:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\4.9.2-atmel3.5.4-arduino2 -verbose C:\Users\Charles Blackburn\Documents\Arduino\RunCPM\RunCPM\RunCPM.ino
D:\Arduino\arduino-builder -compile -logger=machine -hardware D:\Arduino\hardware -hardware C:\Users\Charles Blackburn\AppData\Local\Arduino15\packages -tools D:\Arduino\tools-builder -tools D:\Arduino\hardware\tools\avr -tools C:\Users\Charles Blackburn\AppData\Local\Arduino15\packages -built-in-libraries D:\Arduino\libraries -libraries C:\Users\Charles Blackburn\Documents\Arduino\libraries -fqbn=arduino:avr:uno -ide-version=10804 -build-path C:\Users\CHARLE1\AppData\Local\Temp\arduino_build_416580 -warnings=none -build-cache C:\Users\CHARLE1\AppData\Local\Temp\arduino_cache_784956 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.arduinoOTA.path=C:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\tools\arduinoOTA\1.1.1 -prefs=runtime.tools.avrdude.path=C:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino9 -prefs=runtime.tools.avr-gcc.path=C:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\4.9.2-atmel3.5.4-arduino2 -verbose C:\Users\Charles Blackburn\Documents\Arduino\RunCPM\RunCPM\RunCPM.ino
Using board 'uno' from platform in folder: C:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21
Using core 'arduino' from platform in folder: C:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21
Detecting libraries used...
"C:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\4.9.2-atmel3.5.4-arduino2/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -flto -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10804 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR "-IC:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\cores\arduino" "-IC:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\variants\standard" "C:\Users\CHARLE1\AppData\Local\Temp\arduino_build_416580\sketch\RunCPM.ino.cpp" -o "nul"
"C:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\4.9.2-atmel3.5.4-arduino2/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -flto -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10804 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR "-IC:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\cores\arduino" "-IC:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\variants\standard" "-IC:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\libraries\SPI\src" "C:\Users\CHARLE
1\AppData\Local\Temp\arduino_build_416580\sketch\RunCPM.ino.cpp" -o "nul"
"C:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\4.9.2-atmel3.5.4-arduino2/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -flto -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10804 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR "-IC:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\cores\arduino" "-IC:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\variants\standard" "-IC:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\libraries\SPI\src" "-IC:\Users\Charles Blackburn\Documents\Arduino\libraries\SD\src" "C:\Users\CHARLE1\AppData\Local\Temp\arduino_build_416580\sketch\RunCPM.ino.cpp" -o "nul"
Using cached library dependencies for file: C:\Users\CHARLE
1\AppData\Local\Temp\arduino_build_416580\sketch\main.c
"C:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\4.9.2-atmel3.5.4-arduino2/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -flto -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10804 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR "-IC:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\cores\arduino" "-IC:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\variants\standard" "-IC:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\libraries\SPI\src" "-IC:\Users\Charles Blackburn\Documents\Arduino\libraries\SD\src" "C:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\libraries\SPI\src\SPI.cpp" -o "nul"
"C:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\4.9.2-atmel3.5.4-arduino2/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -flto -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10804 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR "-IC:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\cores\arduino" "-IC:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\variants\standard" "-IC:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\libraries\SPI\src" "-IC:\Users\Charles Blackburn\Documents\Arduino\libraries\SD\src" "C:\Users\Charles Blackburn\Documents\Arduino\libraries\SD\src\File.cpp" -o "nul"
"C:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\4.9.2-atmel3.5.4-arduino2/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -flto -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10804 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR "-IC:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\cores\arduino" "-IC:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\variants\standard" "-IC:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\libraries\SPI\src" "-IC:\Users\Charles Blackburn\Documents\Arduino\libraries\SD\src" "C:\Users\Charles Blackburn\Documents\Arduino\libraries\SD\src\SD.cpp" -o "nul"
"C:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\4.9.2-atmel3.5.4-arduino2/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -flto -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10804 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR "-IC:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\cores\arduino" "-IC:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\variants\standard" "-IC:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\libraries\SPI\src" "-IC:\Users\Charles Blackburn\Documents\Arduino\libraries\SD\src" "C:\Users\Charles Blackburn\Documents\Arduino\libraries\SD\src\utility\Sd2Card.cpp" -o "nul"
"C:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\4.9.2-atmel3.5.4-arduino2/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -flto -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10804 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR "-IC:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\cores\arduino" "-IC:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\variants\standard" "-IC:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\libraries\SPI\src" "-IC:\Users\Charles Blackburn\Documents\Arduino\libraries\SD\src" "C:\Users\Charles Blackburn\Documents\Arduino\libraries\SD\src\utility\SdFile.cpp" -o "nul"
"C:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\4.9.2-atmel3.5.4-arduino2/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -flto -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10804 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR "-IC:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\cores\arduino" "-IC:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\variants\standard" "-IC:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\libraries\SPI\src" "-IC:\Users\Charles Blackburn\Documents\Arduino\libraries\SD\src" "C:\Users\Charles Blackburn\Documents\Arduino\libraries\SD\src\utility\SdVolume.cpp" -o "nul"
Generating function prototypes...
"C:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\4.9.2-atmel3.5.4-arduino2/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -flto -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10804 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR "-IC:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\cores\arduino" "-IC:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\variants\standard" "-IC:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\libraries\SPI\src" "-IC:\Users\Charles Blackburn\Documents\Arduino\libraries\SD\src" "C:\Users\CHARLE1\AppData\Local\Temp\arduino_build_416580\sketch\RunCPM.ino.cpp" -o "C:\Users\CHARLE1\AppData\Local\Temp\arduino_build_416580\preproc\ctags_target_for_gcc_minus_e.cpp"
"D:\Arduino\tools-builder\ctags\5.8-arduino11/ctags" -u --language-force=c++ -f - --c++-kinds=svpf --fields=KSTtzns --line-directives "C:\Users\CHARLE1\AppData\Local\Temp\arduino_build_416580\preproc\ctags_target_for_gcc_minus_e.cpp"
Compiling sketch...
Using previously compiled file: C:\Users\CHARLE
1\AppData\Local\Temp\arduino_build_416580\sketch\main.c.o
"C:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\4.9.2-atmel3.5.4-arduino2/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -MMD -flto -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10804 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR "-IC:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\cores\arduino" "-IC:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\variants\standard" "-IC:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\libraries\SPI\src" "-IC:\Users\Charles Blackburn\Documents\Arduino\libraries\SD\src" "C:\Users\CHARLE1\AppData\Local\Temp\arduino_build_416580\sketch\RunCPM.ino.cpp" -o "C:\Users\CHARLE1\AppData\Local\Temp\arduino_build_416580\sketch\RunCPM.ino.cpp.o"
In file included from C:\Users\Charles Blackburn\Documents\Arduino\RunCPM\RunCPM\RunCPM.ino:1:0:

globals.h:137: error: overflow in constant expression

uint8 RAM[RAMSIZE];

              ^

globals.h:137: error: overflow in array dimension

In file included from c:\users\charles blackburn\appdata\local\arduino15\packages\arduino\tools\avr-gcc\4.9.2-atmel3.5.4-arduino2\avr\include\avr\io.h:99:0,

             from c:\users\charles blackburn\appdata\local\arduino15\packages\arduino\tools\avr-gcc\4.9.2-atmel3.5.4-arduino2\avr\include\avr\pgmspace.h:90,

             from C:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\cores\arduino/Arduino.h:28,

             from C:\Users\CHARLE~1\AppData\Local\Temp\arduino_build_416580\sketch\RunCPM.ino.cpp:1:

cpu.h:14: error: expected unqualified-id before 'volatile'

int32 SP; /* SP register */

   ^

cpu.h:14: error: expected ')' before 'volatile'

cpu.h:14: error: expected ')' before 'volatile'

Multiple libraries were found for "SD.h"
Used: C:\Users\Charles Blackburn\Documents\Arduino\libraries\SD
Not used: D:\Arduino\libraries\old_SD
Not used: D:\Arduino\libraries\SD
Using library SPI at version 1.0 in folder: C:\Users\Charles Blackburn\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\libraries\SPI
Using library SD at version 1.2.2 in folder: C:\Users\Charles Blackburn\Documents\Arduino\libraries\SD
exit status 1
overflow in constant expression

Certain errors seem to cause files to disappear

I have verified this with 2 CCP. I have used the internal as well as CCP-CCPZ.60

If I cause certain I/O errors to occur, files seem to disappear. After trying a few things, I discovered that my files were not truly disappearing, the User area was changing to "1".

How to test:
Create a system with at least 1 drive.
Do a DIR A: to verify that you see all of the files.
Try to switch to a non-existant drive letter. Example: C:
You will get a bdos error. Hit any key to put you back to A:
Do a DIR, where did the files go??
You have been put into USER 1.
Type USER 0 and poof! The files are back again.

I have verify that more than 1 CCP has this anomoly.
Is this an emulation problem or normal for CPM?

I am running Centos 7.6, make posix build
I have all user areas created A/0, A/1, A/2, etc...

Arduino Compile Error

Platform: Arduino IDE ver 1.8.9
Board: ESP32
OS: Windows 10 with latest updates
Issue: Compiling runCPM produces the following error code:
In file included from C:\Users<myuser>\Documents\Arduino\Sketches\RunCPM\RunCPM\RunCPM.ino:50:0:

C:\Users<myuser>\AppData\Local\Temp\arduino_build_483789\sketch\abstraction_arduino.h: In function 'bool _sys_extendfile(char*, long unsigned int)':

C:\Users<myuser>\AppData\Local\Temp\arduino_build_483789\sketch\abstraction_arduino.h:171:29: warning: comparison of unsigned expression < 0 is always false [-Wtype-limits]

 if (f.write((uint8_t)0) < 0) {
                                  ^

Can you change the _sys_extendfile() routine so it functions correctly?
My changed routine is attached; however, modify it any way you desire to make if functional.

_sys_extendfile.txt

Thanks for developing this! I'm still waiting on my ESP32 board. Then I want to test runCPM on it.
Garry

DIR confusion...

CP/M 2.2 Emulator v3.1 by Marcelo Dantas
      Build Sep 24 2018 - 19:14:00
       with Lua scripting support
-----------------------------------------
CCP: INTERNAL v1.4  CCP Address: 0xf400

A0>e:
E0>dir
A: VIDATT   Z80 : WS       COM : WS       OVR : WSCHANGE COM
A: WSCHANGE OVR : WSCHHELP OVR : WSHELP   OVR : WSMSGS   OVR
A: WSPRINT  OVR : WSPRINT  TST : WSREADME BAK : WSREADME TXT
A: WSSHORT  OVR : WSU      COM
E0>█

The drive E directory listing lines should be prefixed with E:.

I found screenlogs where other CCPs did it how I expected it to be e.g. in: #48 (comment)


A friendly neighbour:

Altair 8800 (Z80) simulator V3.9-0 build 1000 (scp created Jun 20 2017 at 15:02:55 with gcc 6.3.0 20170516)


64K CP/M Version 2.2 (SIMH ALTAIR 8800, BIOS V1.27, 2 HD, 02-May-2009)

A>e:
E>dir
E: VIDATT   Z80 : WS       OVR : WSCHANGE COM : WSCHANGE OVR
E: WSCHHELP OVR : WSHELP   OVR : WSMSGS   OVR : WSPRINT  OVR
E: WSPRINT  TST : WSREADME TXT : WSSHORT  OVR : WSU      COM
E: WS       COM
E>█

cannot run adv.com (Classic Adventure Game)

I have teensy 3.6
Arduino 1.8.4
RunCPM Version 2.8

I have tried 64k and 60k
I have tried various cpm, cpmz, cpmz2, cpmz3, internal etc....

When I try to run adv.com, I get "Glitch! Symbol table not found. STOP UGG!"
That string is found inside the adv.com

I have tried the same files on a real Z80 CPM 2.2 and they run aok.

Is there some debugging I can try?

Comal 80 broken in Posix port

Since commit c80f7a0 Comal-80 for CP/M does not accept input on MacOS X and Linux.

How to reproduce:

  • Download Comal-80 from http://www.autometer.de/unix4fun/z80pack/ftp/comal.tgz
  • Extract files with from disk image with cpmtools and put in a disk directory (e.g. C).
  • Start latest RunCPM. Go to disk C: and run "comal". You can't input anything in the Comal prompt.
  • Revert commit c80f7a0 and rebuild RunCPM.
  • Start RunCPM again. Go to disk C: and run "comal". Now everything works ok.

Accessing ESP32/RunCPM via Network WiFi using telnet

I just received a TTGO board. I compiled RunCPM and it seems to work.

I created a ESP32_telnetd.h and with a small change to the arduino_abstraction, I am now able to telnet into the ESP32/RunCPM board.

Seems to work, nothing has failed yet. The EXIT (was halt the emulator) command does a network close and waits for another inbound connection.

Is there a blog somewhere that we can post code and make comments?
Github seems to be the wrong tool for that type of activity.

$telnet 192.168.31.139

Trying 192.168.31.139...
Connected to 192.168.31.139.
Escape character is '^]'.

CP/M 2.2 Emulator v3.7 by Marcelo Dantas
Arduino read/write support by Krzysztof Klis
Build Jan 6 2019 - 22:27:16
'--------------------------------------------'
CCP: INTERNAL v1.5 CCP Address: 0xe400
BOARD: TTGO_T1
Initializing SD card.

RunCPM Version 3.7 (CP/M 2.2 60K)

A0>info
RunCPM System Information v1.0

RunCPM Version 3.7 running on ESP32
CCP is Internal Version 1.5
CCP loads at address E400h
BDOS is at address EC00h
BIOS is at address FE00h
60160 bytes available for applications

RunCPM Version 3.7 (CP/M 2.2 60K)

A0>exit

Connection closed by foreign host.

Latest Windows 10 upgrade, 1803, breaks TE.COM

Hi All,

I am noticing something strange here, maybe you have seen the same and may be able to help.
I have tried many different things with no results. Here is the issue:
After I had to reinstall Windows 10, and Visual Studio 2017, when I built RunCPM it won't accept ESC-X to exit TE.COM (distributed on disk A:).
ESC-N and ESC-A seem to work, but not ESC-X.
Maybe I drew a blank, maybe I am not seeing something obvious, but if one of you has seen the same, let me know. I want to find out what is causing it.

Thanks,
Marcelo.

Speed tests

Has anyone done any speed tests? I'm wondering what the ESP32 runs at in terms of a real Z80 clock speed. It seems a little slow (but then, I got a bit spoiled with Grant Searle's Cyclone II board which runs like a 50Mhz Z80). On the ESP32, loading up, say MBASIC takes 6 seconds - and I'm wondering how much of this is disk activity and how much is CPU activity. Or maybe I've just forgotten how slow real floppy drives were!
Quick test on mbasic doing 10,000 multiplies in a loop takes 7 seconds.
The ESP32 reports a clock speed of an insane 240Mhz, and even allowing 20 instructions per Z80 instruction should still give a decent Z80 speed.

Tiny Terminal

I built a tiny terminal using a 128x64 oled and a PS2 keyboard and an Arduino Uno. It is good enough for STAT and MBASIC and Kermit and other simple CP/M testing. I'm building a bigger display for Wordstar etc. It is pretty simple to put together with some jumper wires.
I know there are some CP/M versions out there that combine display and CP/M but I kind of like the idea of a generic box with a D9 socket and small display and PS2 socket and you can use it on different machines.
This issue can be noted as closed once read :)
Code below.


// Tiny terminal Arduino with I2C display, keyboard and RS232
// PS2 keyboard powered by 5V, data pin 2, clk pin 3
// I2C display on SCL and SDA ‎A4 (SDA), A5 (SCL)
// Max3232 or Max2321 module powered by 5V, on Tx and Rx pins 0 and 1 (disconnect Rx when programming)
// for keyboard, // https://github.com/techpaul/PS2KeyMap/
// for display, #include <Adafruit_GFX.h> and #include <Adafruit_SSD1306.h>
// Scrolling screen, backspace but no VT100 cursor movement
// 21x6 display 
// US keyboard but can change this if needed to UK, French or German (see code).
// outputs an ascii code for keypress. 9600 baud
// also output the control characters eg ^A outputs ascii 1, ^B ascii 2. 
// arrow and home keys mapped to wordstar ^S^D etc
// caps lock, num lock work as do leds on the keyboard when press these
// function keys not mapped as don't map to any ascii values, could potentially map to ascii 128 to 255

/*  KeyboardPS2AdvancedSimpleTest.ino

  PS2KeyAdvanced library example

  Advanced support PS2 Keyboard to get every key code byte from a PS2 Keyboard
  for testing purposes.

  IMPORTANT WARNING

    If using a DUE or similar board with 3V3 I/O you MUST put a level translator
    like a Texas Instruments TXS0102 or FET circuit as the signals are
    Bi-directional (signals transmitted from both ends on same wire).

    Failure to do so may damage your Arduino Due or similar board.

  Test History
    September 2014 Uno and Mega 2560 September 2014 using Arduino V1.6.0
    January 2016   Uno, Mega 2560 and Due using Arduino 1.6.7 and Due Board
                    Manager V1.6.6

  This is for a LATIN style keyboard using Scan code set 2. See various
  websites on what different scan code sets use. Scan Code Set 2 is the
  default scan code set for PS2 keyboards on power up.

  Will support most keyboards even ones with multimedia keys or even 24 function keys.

  The circuit:
   * KBD Clock (PS2 pin 1) to an interrupt pin on Arduino ( this example pin 3 )
   * KBD Data (PS2 pin 5) to a data pin ( this example pin 4 )
   * +5V from Arduino to PS2 pin 4
   * GND from Arduino to PS2 pin 3

   The connector to mate with PS2 keyboard is a 6 pin Female Mini-Din connector
   PS2 Pins to signal
    1       KBD Data
    3       GND
    4       +5V
    5       KBD Clock

   Keyboard has 5V and GND connected see plenty of examples and
   photos around on Arduino site and other sites about the PS2 Connector.

 Interrupts

   Clock pin from PS2 keyboard MUST be connected to an interrupt
   pin, these vary with the different types of Arduino

  PS2KeyAdvanced requires both pins specified for begin()

    keyboard.begin( data_pin, irq_pin );

  Valid irq pins:
     Arduino Uno:  2, 3
     Arduino Due:  All pins, except 13 (LED)
     Arduino Mega: 2, 3, 18, 19, 20, 21
     Teensy 2.0:   All pins, except 13 (LED)
     Teensy 2.0:   5, 6, 7, 8
     Teensy 1.0:   0, 1, 2, 3, 4, 6, 7, 16
     Teensy++ 2.0: 0, 1, 2, 3, 18, 19, 36, 37
     Teensy++ 1.0: 0, 1, 2, 3, 18, 19, 36, 37
     Sanguino:     2, 10, 11

  Read method Returns an UNSIGNED INT containing
        Make/Break status
        Caps status
        Shift, CTRL, ALT, ALT GR, GUI keys
        Flag for function key not a displayable/printable character
        8 bit key code

  Code Ranges (bottom byte of unsigned int)
        0       invalid/error
        1-1F    Functions (Caps, Shift, ALT, Enter, DEL... )
        1A-1F   Functions with ASCII control code
                    (DEL, BS, TAB, ESC, ENTER, SPACE)
        20-61   Printable characters noting
                    0-9 = 0x30 to 0x39 as ASCII
                    A to Z = 0x41 to 0x5A as upper case ASCII type codes
                    8B Extra European key
        61-A0   Function keys and other special keys (plus F2 and F1)
                    61-78 F1 to F24
                    79-8A Multimedia
                    8B NOT included
                    8C-8E ACPI power
                    91-A0 and F2 and F1 - Special multilingual
        A8-FF   Keyboard communications commands (note F2 and F1 are special
                codes for special multi-lingual keyboards)

    By using these ranges it is possible to perform detection of any key and do
    easy translation to ASCII/UTF-8 avoiding keys that do not have a valid code.

    Top Byte is 8 bits denoting as follows with defines for bit code

        Define name bit     description
        PS2_BREAK   15      1 = Break key code
                   (MSB)    0 = Make Key code
        PS2_SHIFT   14      1 = Shift key pressed as well (either side)
                            0 = NO shift key
        PS2_CTRL    13      1 = Ctrl key pressed as well (either side)
                            0 = NO Ctrl key
        PS2_CAPS    12      1 = Caps Lock ON
                            0 = Caps lock OFF
        PS2_ALT     11      1 = Left Alt key pressed as well
                            0 = NO Left Alt key
        PS2_ALT_GR  10      1 = Right Alt (Alt GR) key pressed as well
                            0 = NO Right Alt key
        PS2_GUI      9      1 = GUI key pressed as well (either)
                            0 = NO GUI key
        PS2_FUNCTION 8      1 = FUNCTION key non-printable character (plus space, tab, enter)
                            0 = standard character key

  Error Codes
     Most functions return 0 or 0xFFFF as error, other codes to note and
     handle appropriately
        0xAA   keyboard has reset and passed power up tests
               will happen if keyboard plugged in after code start
        0xFC   Keyboard General error or power up fail

  See PS2Keyboard.h file for returned definitions of Keys

  Note defines starting
            PS2_KEY_* are the codes this library returns
            PS2_*     remaining defines for use in higher levels

  To get the key as ASCII/UTF-8 single byte character conversion requires use
  of PS2KeyMap library AS WELL.

  Written by Paul Carpenter, PC Services <[email protected]>
*/

// oled SSD1306 tiny display constants
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
char screen[126]; // 21 characters per line, 6 lines
uint8_t screenColumn = 0; // screen column 0 to 20 (there are 21 characters per line)


const uint8_t screenCols = 21; // 21
const uint8_t screenRows = 6; // 6
const uint8_t fontHeight = 10;
const uint8_t fontWidth = 6;
uint8_t cursorCol = 0;
uint8_t cursorRow = 0;
uint8_t screenArray[screenCols*screenRows];
boolean cursorOn = false;

// millisecond timer - used by oled and radio
uint32_t oldFiveHundredMillisecond = 0;

// string arrays
char inputString1[30]; // general purpose input string, 30 bytes, careful not to overflow this with long strings
//char inputString2[30]; // general purpose input string, 30 bytes
char outputString[30]; // general output string, 30 bytes

const uint16_t serialBufferSize = 128; // crashes with more than this, likely stack overflow
uint8_t serialBuffer[serialBufferSize];
uint16_t serialHead = 0;
uint16_t serialTail = 0;

#include <PS2KeyAdvanced.h>
#include <PS2KeyMap.h> // https://github.com/techpaul/PS2KeyMap/ and see examples folder. 
// Keyboard constants  Change to suit your Arduino
//  Valid irq pins:    Arduino Uno/Nano:  2, 3
#define DATAPIN 2
#define IRQPIN  3
PS2KeyAdvanced keyboard;
PS2KeyMap keymap;

void setup() {
  Serial.begin(9600); 
  // display setup
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // some boards have the address as 0x78 but it actually is 3C
  //display.begin(SSD1306_SWITCHCAPVCC, 0x78);
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.display();
  fillSpaces();
  printScreenArray(); // clears screen and reprints but does not display
  const static char s1[] PROGMEM = "*********************"; // store the text in flash
  printString(getString(s1));
  const static char s2[] PROGMEM = " Tiny Termimal 21x6"; // store the text in flash
  printStringln(getString(s2));
  const static char s3[] PROGMEM = " PS2 Key, 9600 Baud"; // store the text in flash
  printStringln(getString(s3));
  const static char s4[] PROGMEM = "    SSD1306 Oled"; // store the text in flash
  printStringln(getString(s4));
  const static char s5[] PROGMEM = "*********************"; // store the text in flash
  printString(getString(s5));
  // Configure the keyboard library
  keyboard.begin( DATAPIN, IRQPIN );
  // see keytolcd demo, may be a bit more useful for just getting the characters
  keyboard.setNoBreak( 1 );         // No break codes for keys (when key released)
  keyboard.setNoRepeat( 1 );        // Don't repeat shift ctrl etc
  keymap.selectMap( (char *)"US" );
  //keymap.selectMap( (char *)"UK" );
  //keymap.selectMap( (char *)"FR" );
  //keymap.selectMap( (char *)"DE" );
}

void loop() {
  // cycles approx 3x per millisecond if nothing much happening. display.display() takes 35ms
  // https://github.com/arduino/Arduino/issues/4822  softSerial can't do loopback! Disables interrupts for sending so never gets its own message, so use the programming serial port
    scanKeyboardRemap(); // scan and remap to ascii
    while (Serial.available() > 0) {
      writeSerialBuffer(Serial.read()); // read into buffer
    }
    if (availableSerialBuffer() == true) {
      printLcdChar(readSerialBuffer()); // read in byte if available. If was just one byte, then refresh the display
      if (availableSerialBuffer() == false) {
       display.display(); // refresh display so more responsive
      }
    }
    while (Serial.available() > 0) {
      writeSerialBuffer(Serial.read()); // read into buffer any more bytes that might have come in while doing display.display as can't do two of these in a row, will overflow the internal arduino buffer
    }
    if ((millis() - oldFiveHundredMillisecond) >= 500) {
      flashCursor();
      if (availableSerialBuffer() == false) {
        display.display(); // refresh display, this is slow so only do if there are no bytes pending in the serial buffer
      }  
    oldFiveHundredMillisecond = millis();
  }
}


// **************** begin OLED routines ******************

uint16_t decodeAddress(uint8_t x, uint8_t y)
{
  // if width is 80 then array stores 0 to 79 then next row is 80 up
  uint16_t address;
  address = y;
  address = address * screenCols;
  address = address + x;
  return address;
}

void printScreenArray()
{
  uint8_t x = 0;
  uint8_t y = 0;
  uint16_t x1 = 0;
  uint16_t y1 = 0;
  uint16_t address;
  display.clearDisplay(); // clear the display
  for(y=0;y<screenRows;y++) {
    x = 0;
    address = decodeAddress(x,y);
    y1 = y * fontHeight; // based on font size
    x1 = 0;
    for (x=0;x<screenCols;x++) {
      display.setCursor(x1,y1);
      display.write(screenArray[address]);
      address++;
      x1 = x1 + fontWidth; // based on character width
    }
  }
  // display.display(); // done in the main loop, do need this to refresh the display
}

void storeCharacter(uint8_t ch, uint8_t y, uint8_t x)
{
  uint16_t address;
  address = decodeAddress(x, y);
  screenArray[address] = ch;
}

void displayCharacter(uint8_t y, uint8_t x)
{
  uint16_t address;
  uint8_t ch;
  uint16_t x1 = 0;
  uint16_t y1 = 0;
  address = decodeAddress(x, y);
  ch = screenArray[address];
  moveCursor(x, y);
  display.write(ch);
  // display.display done in main timing loop, only if no characters waiting to come in
}

void storeAndDisplayCharacter(uint8_t ch)
{
  if ((ch > 31) && (ch < 127)) { // printable/stored character 32 to 126
    storeCharacter(ch, cursorRow, cursorCol); 
    displayCharacter(cursorRow, cursorCol);
    cursorCol++;
    if (cursorCol >= screenCols) {
      cursorCol = 0;
      cursorRow++;
    }
    if (cursorRow >= screenRows) {
      scrollUp();
      cursorRow--;
      printScreenArray(); // reprint whole screen after a scroll
    }
    moveCursor(cursorCol, cursorRow);
  }
  if (ch == 10) {
    if (cursorRow == (screenRows - 1)) {
      scrollUp(); // on bottom line of the screen so linefeed leaves cursor where it is, x and y, scrolls everything up one line. 
      printScreenArray(); // reprint whole screen after a scroll
    }else{
      cursorRow++;  // otherwise just move the cursor down one line
    }
  }
  if (ch == 13) {
    cursorCol = 0; // carriage return, cursor to column 0
  }
  if (ch == 8) { // backspace
    if (cursorCol > 0) {
      cursorCol--; // move cursor back one
    }else{
      if (cursorRow >= 0 ) {
        cursorRow--; // move cursor up to end of previous line
        cursorCol = screenCols - 1; // move to end of previous line 
      }
    }
    printScreenArray(); // reprint whole screen after backspace - eg if CP/M gets a backspace, sends to monitor backspace then print space, then backspace again
  }
}

void moveCursor(uint16_t col, uint16_t row)
{
  uint16_t x;
  uint16_t y;
  y = row * fontHeight; // based on font size
  x = col * fontWidth; 
  display.setCursor(x, y);
}

void scrollUp()
{
  uint16_t addressDest;
  uint16_t addressSource;
  uint8_t x = 0;
  uint8_t y = 0;
  for (y=0;y<(screenRows - 1);y++) {
    x = 0;
    addressDest = decodeAddress(x, y);
    addressSource = decodeAddress(x, (y+1));
    for (x=0;x<screenCols;x++) {
      screenArray[addressDest] = screenArray[addressSource];
      addressDest++;
      addressSource++;
    }
  }
  y = screenRows - 1; // now make the bottom line on the screen blank
  x = 0;
  addressDest = decodeAddress(x, y);
  for (x=0;x<screenCols;x++) {
    screenArray[addressDest] = ' ';
    addressDest++;
  }
}

void fillScreenTest()
{
  uint8_t x = 0;
  uint8_t y = 0;
  uint16_t address;
  uint8_t i;
  for (y=0;y<screenRows;y++) {
    x = 0;
    i=97+y;
    address = decodeAddress(x, y);
    for (x=0;x<screenCols;x++) {
      screenArray[address] = i;
      i++;
      address++;
    }
  }
}

void fillSpaces()
{
  uint16_t i;
  uint16_t total;
  total = screenCols*screenRows;
  for (i=0;i<total;i++) {
    screenArray[i] = ' ';
  }
}

void dumpScreenArray()
{
  uint16_t i;
  uint16_t total;
  total = screenCols*screenRows;
  for (i=0;i<total;i++) {
    Serial.print(screenArray[i]);
    Serial.print(' ');
  }
}

void flashCursor()
{
  uint16_t curX;// in pixels so need 16 bit resolution for large displays
  uint16_t curY; 
  curX = cursorCol * fontWidth;
  curY = cursorRow * fontHeight;
  display.fillRect(curX, curY, fontWidth, fontHeight,BLACK); // standard font behaviour for all libraries is to only print pixels and not erase the previous ones
  moveCursor(cursorCol, cursorRow);
  if (cursorOn == true) {
    display.write('_');
  }
  cursorOn = !cursorOn;
}

void printLcdChar(uint8_t c)
{
  cursorOn = false; // redisplay with no line before printing anything
  flashCursor();
  storeAndDisplayCharacter(c); // new version of code
}  

// *********************** end OLED routines ********************

// *********************** string routines ***********************

int freeRam () {
  extern int __heap_start, *__brkval; 
  int v; 
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 
}

char* getString(const char* str) // String replacement - move string from flash to local buffer
{
  strcpy_P(outputString, (char*)str);
  return outputString;
}

void printString(const char *str) // all output directed through this one routine, so can change Serial.print to whatever display is being used
{ 
    const char *p;
    p = str;
    while (*p) {
        //Serial.print(*p); // send to serial, explanation in majenko's webpage
        printLcdChar(*p); // or send to lcd
        p++;
    }
}

void printStringln(const char *str) // print line with crlf
{
    printString(str); 
    crlf(); // carriage return, line feed
}

void crlf() // carriage return and linefeed
{
  const static char crlf[] PROGMEM = "\r\n"; // carriage return, then line feed, maybe not the most efficient way to do this but works
  printString(getString(crlf)); // print out, using one central function for output so easier to change destination with different displays
}

void printNumber(long n)
{
  char* outputString = integerToString(n); // convert to number
  printString(outputString);
}

char* integerToString(int n) // returns outputString
{
  itoa(n, outputString, 10); // itoa is for integers, 10 is for base 10 (could use 2 for binary, 16 for hex)
  return outputString;
}

void printUnsigned(uint16_t n)
{
  char* outputString = unsignedToString(n); // convert to number
  printString(outputString);
}

char* unsignedToString(uint16_t n) // returns outputString
{
  utoa(n, outputString, 10); // itoa is for integers, 10 is for base 10 (could use 2 for binary, 16 for hex)
  return outputString;
}
// *********************** end string routines *****************************

void scanKeyboardRemap()
{
  uint16_t code;
  uint8_t remapCode;
  uint8_t ascii;
  uint8_t ctrl;
  code = keyboard.available();
  if( code > 0 ) {
    code = keyboard.read();
    //Serial.print( F( "Value " ) );
    //Serial.print( code, HEX );
    switch (code) {
      // map arrow keys to Wordstar - comment out if not needed 
      case 0x0111: outputAscii(17); // Home = ^QS
                   outputAscii(19);
                   break; 
      case 0x0112: outputAscii(17); // End = ^QD
                   outputAscii(4);
                   break;
      case 0x0113: outputAscii(18); // Page Up = ^R
                   break;
      case 0x0114: outputAscii(3); // Page Down = ^C    
                   break;                      
      case 0x0115: outputAscii(19);  // Left arrow = ^S
                   break;
      case 0x0116: outputAscii(4);  // Right arrow = ^D
                   break;
      case 0x0117: outputAscii(5);  // Up arrow = ^E
                   break;
      case 0x0118: outputAscii(24); // Down arrow = ^X
                   break;
      case 0x0119: outputAscii(22);  // Insert = ^V
                   break;        
    }
    remapCode = keymap.remapKey( code );
    if( remapCode > 0 ) {
      //Serial.print(F("["));
      //Serial.print( remapCode, HEX );
      //Serial.print(F("]"));
      if( ( remapCode & 0xFF ) ) {
        //Serial.print( F( " mapped " ) );
        //Serial.print( remapCode, HEX );
        //Serial.print( F( " - Status Bits " ) );
        //Serial.print( remapCode >> 8, HEX );
        //Serial.println("");
        ctrl = (code >> 8);
        ascii = remapCode & 0xFF;
        if (ascii < 128) {
          //Serial.print( F( " Ascii decimal " ) );
          if (ctrl == 0x20) { // Ctrl/smalls so subtract 97
            if ((ascii>= 97) && (ascii <=122)) {
              ascii = ascii - 96; // a to z to ascii 1 to 26
            }
          }
          if (ctrl == 0x30) { // Ctrl/caps so subtract 65
            if ((ascii>= 65) && (ascii <=90)) {
              ascii = ascii - 64; // A to Z to ascii 1 to 26
            }
          }
          //Serial.print( ascii, DEC );
          //Serial.print( F( "  ( " ) );
          //Serial.write( ascii );
          //Serial.print( F( " )\n" ) );
          outputAscii(ascii); // send out serial port
        }
      }
    }   
  }
}

void outputAscii(uint8_t ch)
{
  // single point to output anything to the serial port
  Serial.write(ch);
  //Serial.print(F(" = ascii ")); // debugging
  //Serial.print(ch, DEC ); // debugging
  //Serial.println(""); // debugging
}

void writeSerialBuffer(uint8_t ch)
{
  serialBuffer[serialHead] = ch;
  serialHead++;
  if (serialHead >= serialBufferSize) {
    serialHead = 0;
  }
}

uint8_t readSerialBuffer()
{
  uint8_t ch;
  ch = serialBuffer[serialTail];
  serialTail++;
  if (serialTail >= serialBufferSize) {
    serialTail = 0;
  }
  return ch;
}

boolean availableSerialBuffer()
{
  boolean availableBuffer = false;
  if (serialTail != serialHead) { 
    availableBuffer = true;
  }
  return availableBuffer;
}

RunCPM SD disk problem (long/short file names?)

Problem: With teensy 3.6, files in A/0 of sd showing duplicated, one normal short name e.g. asm.com and one false short name _AS~~.COM
Scenario:Using RunCPM files of 2018-feb-01, move contents of DISK/A.ZIP to SD under OSX (or Windows 10), and also copy DR 60K ccp to root of SD; take fresh Arduino 1.85 IDE for OSX, install teensyduino, open RunCPM.ino from unzip of github runcpm files. Build and upload Runcpm to teensy 3.6 with above SD card inserted. Terminal shows RunCPM running ok except no files visible on A; extract SD card to PC to move "A" files into folder A/0; re-insert SD card in teensy 3.6 and reboot; RunCPM working OK except see all files in folder A/0 ok and also see all files with a newly created short name, e.g. ASM.COM visible as ASM.COM and _AS~~1.COM. This looks like some sort of long/short naming problem.
Note 1) this error was visible also on windows10 hosted teensy3.6;
Note 2) on some occasions the error may show as only showing first file on disk folder A/0 with normal name, the other files wouldn't be visible. (on this occasion after teensy reboot to get screen shot, I only saw this flavour of error, could not get screen shot of error showing as full directory with duplicates.
Note 3) SD card is 4gb type 4 micro sd hc sandisk formatted as FAT 16
Note 4) with scenario on note 2 above , i found on subsequent testing that dir shows 1 file, but pip b:=a:. will find all files with proper name and all the false duplicates with _AS~.COM style of name

How to change clock speed of ESP32

Hi All,
I am trying to reduce the clock speed of my ESP32 module but it seems a bit difficult to change or somewhere I read we can't change the clock speed of the ESP32.
As my application is temperature sensitive and running on the battery so I thought by using lower clock speed I can achieve both.
Please let me know if anyone knows how to fix this issue.

Hi Tech C 3.09 hangs

While testing a variety of programs, I met one issue. The compiler run under runcpm hangs. It seems to be associated to the C.COM program chaining the various compilation steps. I did not go far enough to figure out what triggers the failure.
the same compiler works properly in a simh environment and a couple of other emulators.
the programs generated with it work perfectly under it.

Cannot write files to SD in ESP32 port

I have compiled the ESP32 port in a lolin D32 and all seem to be fine. All works except write files in the filesystem.

Each time i try to wite a file (saving zork, installing wordstar, editing with TE, etc i get an error.

A0>ed kk

DISK OR DIRECTORY FULL

the erase command is working, pip,rena, etc no.

Any clue?

only changed the pins in the SD definition and hat to change the sd.begin line to:

if (SD.begin(SDINIT,SD_SCK_MHZ(30))) {
(tried lower speeds, but the error is the same, with higher speeds, lots of problems accesing files)

make make detect changes in headers and the Makefile itself...

# Link the program
$(PROG): $(OBJS)
        $(LD) $(OBJS) -o $(PROG) $(LDFLAGS)

$(PROG): only depends on $(OBJS) which is the only C source of this project.
Changes to headers or the Makefile itself will not trigger a rebuild.

Adding $(wildcard *.h) Makefile.posix will be just a bit too active and trigger a rebuild even if a header for a different platform has changed, but I think that's tolerable. And it catches all headers by wildcard and so never adding a header to the Makefile can be forgotten.

...and later:

# Compile everything.
all: clean $(PROG)

I think a forced "make clean" before remake is not needed when the above change detects changed Makefile, C source and headers...

Improve the handling of $$$.SUB file

$$$.SUB should always be checked on drive A: user area 0.
Even after many years, no standard was defined for this, and some CCPs and implementations of SUBMIT handled it differently.
A: user area 0 seems so be a good base for a standard (especially nowadays, when no one will complain about it), so I will implement this shortly.

Bdos Error on A : Select

Compiling using the Posix makefile and running this on Linux (Lubuntu) for both CCP_CCPZ with 64K and the CCP_DR with 60K only gives Bdos errors as below. No amount of pressing Enter or ^C ever resolved the problem.

      Build Feb 17 2017 - 00:49:00
       with Lua scripting support
-----------------------------------------
CCP: CCP-DR.60K  CCP Address: 0xe400
RunCPM Version 2.8 (CP/M 2.2 60K)
Bdos Error on A : Select

Trying the CCP_INTERNAL I also get the error. Here two Enters gives me the A> -prompt, but the error comes back as soon as I try a disk access.

CP/M 2.2 Emulator v2.8 by Marcelo Dantas
      Build Feb 17 2017 - 00:54:55
       with Lua scripting support
-----------------------------------------
CCP: INTERNAL v1.3  CCP Address: 0xe400
RunCPM Version 2.8 (CP/M 2.2 60K)
Bdos Error on A : Select
Bdos Error on A : Select
A>DIR
Bdos Error on A : Select

The build process seems ok except for some minor nagging by the archiver that says:
ar: `u' modifier ignored since `D' is the default (see `U')

Terminal emulation?

I've tried configuring wordstar to use an ansi/vt100 terminal but it isn't working; is the terminal emulation something I need to turn on?

.gitignore += more non source files

After building (make posix build) several files not registered with git show up in git status and in the comments on each commit. They are RunCPM, main.o, lua/lua, lua/luac and lots of lua/*.o files. Will it cause problems to add them to .gitignore?

submit does not work in runcpm for arduino due

Submit.com and submitd.com doesn´t appear to work. The only program that appears to work is supersub.com, a more powerful submit-like utility, but only works in A: drive, not B:, C:,..

STM32 Port

Hi All,

I have pulled my STM32 board from the drawer and gave it a try on the Arduino.
It seems to work fine with code from this project: https://www.stm32duino.com/
Source code here: https://github.com/rogerclarkmelbourne/Arduino_STM32
SD Library here: https://github.com/stm32duino/STM32SD (I have not tested this yet)
There's a good chance this will work for running RunCPM.

I have tried compiling RunCPM for it but got some errors, also, the code needs defines to use different settings when building for this board. Not sure when I will be able to port it, but if anyone wants to give it a try, check pages the above.

I am not using the guy's STM32duino boot loader, as I feel it is not needed, you can program the STM board from Arduino using the on-board st-link. Needs to install the ST-Link driver btw.

I was able to load a led-blink program onto it, which is already some progress.

Cheers,
Mockba.

ESP32 Port

My ESP32 boards will be arriving in a few days.
Let's see if this is going to work right out of the box, or if it will require a lot of coding to happen.
Or even if it will not be at all possible.
Stay tuned.

Cannot initialise SD card

I have a DUE with Keystudio WS100 Ethernet Card. Using the SD card driver examples I can read/write and list files on the SD card but when starting RunCPM I get the following error on the DUE serial port..

CP/M 2.2 Emulator v3.7 by Marcelo Dantas
Arduino read/write support by Krzysztof Klis
Build Mar 26 2019 - 10:45:03

CCP: CCP-DR.60K CCP Address: 0xe400
BOARD: ARDUINO DUE
Initializing SD card.
Unable to initialize SD card.
CPU halted.

RunCPM 3.7 for Win does exit after DIR

Today I did download v3.7 of RunCPM and the actual A.ZIP,
but wheater the content of the old A.ZIP or the new A.ZIP
RunCPM 3.7 on Windows does exit for me after gigving the command DIR :(
`
CP/M 2.2 Emulator v3.7 by Marcelo Dantas
Build Nov 29 2018 - 01:41:18

CCP : CCP-ZCP2.60K CCP Address: 0xe400

RunCPM Version 3.7 (CP/M 2.2 60K)

A>DIR
1STREAD .ME

C:\TEMP\RunCPM_Win>
`
I didnt got this with a v3.7 compiled under armbian-linux on a Pi-Style SBC.

make -f Makefile.posix run

$ make -f Makefile.posix run
rm -f RunCPM
rm -f main.o
gcc -Wall -O0 -fPIC -Wno-unused-variable -c main.c
gcc main.o -o RunCPM -lncurses
RunCPM
make: RunCPM: Command not found
Makefile.posix:51: recipe for target 'run' failed
make: *** [run] Error 127
$ tail -2 Makefile.posix 
run: all
        $(PROG)

Executing $(PROG) will not work unless you include . in your PATH which is a big nono in the unix universe.

...and probably the sources directory does not have the CCP and the CP/M drives subdirectories, so make run does not make much sense for 99,593% of all RunCPM users...
o;-)

Drop the "run:" target until somewhen there is "install:" too?

Unable to load CP/M CCP. CPU halted.

Hello. I'm trying to run it on a teensy 3.5 but without success.
I change the SD type, A folder, 0 subfolder... there's something I'm missing?

`user S`? Only a HiTech-C hiccup?

I've HiTech-C installed in C/0 and keep my C workspace in C/1.
The location is defined in C/1/ENVIRON:

C1>type environ
HITECH=0:C:

Watching the drive/user structure with watch 'ls -d ?/?' in an own terminal window while compiling stuff shows, that the directory C/S is created while compiling...

C1>c myhi.c
HI-TECH C COMPILER (CP/M-80) V3.09
Copyright (C) 1984-87 HI-TECH SOFTWARE


C1>myhi
No meltdown, no specte.
No rowhammer, no brainslammer!

CP/M!
;-)


C1>█

...and not while running the result.

I'm currently using the internal CCP but I remember having seen C/S while using CCPZ too.

Is HiTech-C the only software creating strange drive/user directories?
Does this happen only on RunCPM's posix port?
Please have a look at your drive/user trees.

So far it looks like having no other side effects than generating this strange user area directory. I can live with that but if it shows up in other contexts too, narrowing it down may become easier.

Dropping CCPHEAD?

Is the CPPHEAD message really needed that often?
Its contents does not change.
Would showing this at most once be enough?

I'll mute it in a local branch if the majority loves to see it frequently...

Existing nonexisting files... I'm confuzzeld...

Once upon a time...

C: contains Hi-Tech-C V3.09.
...and there is a file OPTIONS:

CP/M 2.2 Emulator v2.7 by Marcelo Dantas
      Build Sep 21 2016 - 08:26:21
-----------------------------------------
CCP: CCP-DR.BIN Loaded at 0xf400

RunCPM Version 2.7 (CP/M 2.2 64K)

A>c:
C>dir options
C: OPTIONS     
C>type options
OPTIONS?

C>a:stat options

 Recs  Bytes  Ext Acc
    0     0k    1 R/W C:OPTIONS
Bytes Remaining On C: 960k

C>_

...looking from Debian:

runcpm/run$ ls -l C/0/OPTIONS 
-rw-r--r-- 1 yeti yeti 768 Sep 18 08:07 C/0/OPTIONS
runcpm/run$ stat -cx%nx C/0/OPTIONS
xC/0/OPTIONSx
runcpm/run$ _

It exists, has a length and has no spaces after the filename.


Experiment to reproduce it with an own file...

runcpm/run$ echo WORLD > C/0/HELLO
runcpm/run$ _

Look from CP/M...

CP/M 2.2 Emulator v2.7 by Marcelo Dantas
      Build Sep 21 2016 - 08:26:21
-----------------------------------------
CCP: CCP-DR.BIN Loaded at 0xf400

RunCPM Version 2.7 (CP/M 2.2 64K)

A>c:
C>dir hello
C: HELLO       
C>type hello
HELLO?

C>era hello

...then RunCPM hangs.

It is ok to look confused now?


More testing...

A>mbasic
BASIC-85 Rev. 5.29
[CP/M Version]
Copyright 1985-1986  $  by Microsoft
Created: 28-Jul-85
38968 Bytes free
Ok
open"O",1,"HELLO"
Ok
print#1,"WORLD"
Ok
close 1
Ok
system

RunCPM Version 2.7 (CP/M 2.2 64K)

A>dir hello
A: HELLO       
A>type hello
WORLD

A>_

View from Debian:

runcpm/run$ ls -l A/0/HELL*
-rw-r--r-- 1 yeti yeti 128 Sep 21 10:02 A/0/HELLO.
runcpm/run$ stat -cx%nx A/0/HELLO. 
xA/0/HELLO.x
runcpm/run$ _

Idea:

runcpm/run$ mv C/0/OPTIONS C/0/OPTIONS.

Back to CP/M:

C>type options
Z80 CP/M C compiler options:

-A      Generate a self-relocating .COM program
-R      Link in command line wild card expansion code
-V      Be verbose during compilation
-S      Generate assembler code in a .AS file; don't assemble or link
-C      Generate object code only; don't link.
-O      Invoke the peephole optimizer
-I      Specify an include directory, e.g. -I1:B:
-U      Undefine a predefined symbol, e.g. -UDEBUG
-D      Define a symbol, e.g. -DDEBUG=1
-L      Scan a library, e.g. -LF scans the floating point library
-F      Generate a symbol file suitable for use with debug.com, e.g.
                -Ffile.sym; default file name is L.SYM.
-W      Set warning level, e.g. -w5 or -w-2
-X      Suppress local symbols in symbol tables
-M      Generate a map file, e.g. -Mfile.map

C>_

\o/


Conclusion

Files without extension need a trailing dot on *nixish filesystems for not confusing RunCPM (and me! )...
;-)

Broken keyboard input

Is it just me or the latest (15.8.1) update of Visual Studio 2017 just broke text input?
Still wondering what might be the issue.

MLOAD v2.1 has CCP 6 byte overwrite bug.

MLOAD v2.1 has a bug where it will overwrite the first six bytes of the CCP.
Normally this is not a problem, unless the CCP is not rewritten following a warm boot.

MLOAD v2.5 fixes this problem.
See the version notes in the mload.asm

Since z80.eu is down, the wayback machine has the required zip file.

Cant compile RunCPM v3.7 for Arduindo DUE

I downloaded the Master today and did try to compile (with Arduino IDE 1.8.7) for the Arduino DUE.
First I did see I missed the SDFat Library and installed the v1.0.7 via "Manage Library"

But while compiling the IDE has some problems mit the SDFAT EX from the RunCPM.ino

Please read attached .txt file
Arduino_DUE_ErrMsgs.txt

Kermit for file transfers

Now have Kermit working for file transfers to and from a PC, and also for transfers between two ESP32 boards running RunCPM. There are quite a few additions to the code, particularly with adding in handling for iobyte. Hopefully these can be added in some sort of 'official' way. They can all be added with conditional #ifdef ESP32 so as to not affect any other code. There is a small bug in the existing code where iobyte gets reset on return to the A> prompt so changing it with STAT was not working. Fixed by moving the initial iobyte declaration to a 'cold boot' part of the code, ie just before the signon message. Below is a copy of all the notes I made along the way.
Pinout for SD card https://github.com/espressif/arduino-esp32/tree/master/libraries/SD
MISO IO19, MOSI I023, CLK IO18, CS IO5, 3V and 0V. These are all in a group apart from the 3V3. (ESP32 pins are all 3V3)
for arduino sized boards they have a reset when uploading the program. The smaller boards need the reset button pushed prior to uploading
globals.h - commented out USE_PUN and USE_LST for the moment
changed the esp32 pin definitions for the arduino form factor board "ESPDUINO-32"
#elif defined ESP32 // ESP32 boards
SdFatSoftSpiEX<19, 23, 18> SD; // MISO, MOSI, SCK Some boards use 2,15,14,13, other 12,14,27,26
#define SDINIT 5 // CS
#define LED 2 // TTGO_T1=22 LOLIN32_Pro=5(inverted) DOIT_Esp32=2 ESP32-PICO-KIT=no led, Espduino pin 2
#define LEDinv 0
#define BOARD "ESPDUINO-32"
added in two new serial ports (the ESP32 has 3 hardware uarts, and later could possibly add software uarts as well)
Serial1.begin(SERIALSPD,SERIAL_8N1, 26, 25); //Baud rate, parity mode, RX, TX ESP32
Serial2.begin(SERIALSPD,SERIAL_8N1, 17, 16); //Baud rate, parity mode, RX, TX ESP32
commented out // _RamWrite(0x0003, 0x3D); in cpm.h as this is resetting the iobyte on a warm boot, which means that STAT could change the iobyte but as soon as stat finished, it got changed back again
now have this line in the RunCPM tab
_clrscr();
_RamWrite(0x0003, 0x3D); // IOBYTE set
_puts("CP/M 2.2 Emulator v" VERSION " by Marcelo Dantas\r\n");
Then extensive changes to abstraction_ardunio.h so that all IO is redirected as per the iobyte. Example of the code is for console out
void outCON(uint8_t ch)
{
uint8_t iobyte;
iobyte = iobyteCON(); // 00, 01 10, 11
switch (iobyte) {
case 0: deviceTTYout(ch);
break;
case 1: deviceCRTout(ch);
break;
case 2: deviceBATout(ch);
break;
case 3: deviceUC1out(ch);
break;
}
}

If you run STAT VAL: it prints out the list of all the 13 physical devices that can be connected (the table would suggest 4x4=16 but some are repeated)
CON: = TTY: CRT: BAT: UC1:
RDR: = TTY: PTR: UR1: UR2:
PUN: = TTY: PTP: UP1: UP2:
LST: = TTY: CRT: LPT: UL1:
In our case the important thing is the console is connected to the CRT, which is the first serial port
Run STAT DEV: and it lists the current layout eg CON: CRT:
To change this, run STAT CON:=TTY: and now the console changes from Serial to Serial 1
It is very helpful at this point to have a D9 to USB adaptor, and also a terminal program such as Teraterm
Next were lots of experiments with the RDR port. It is possible to do things like PIP TEST.TXT=RDR:
however, this does not work for large files over about 30K as CP/M runs out of Z80 memory and then goes to write all the data to the disk and then the buffer overflows.
Tried adding a very large buffer and slow baud rates but I think the ESP32 memory can be used for better things.
Outputting data works fine too, eg PIP PUN:=TEST.TXT but it did need code to poll the number of bytes still available in the buffer and put in a 100ms delay if the buffer is getting full.
The next experiment is with Kermit. There is a "generic" version of Kermit that uses iobyte. The kermit documentation says that it defaults to PTR being the port with the following settings:
SET PORT xxx input from output to
CRT CRT: CRT:
PTR PTR: PTP:
However, lots of experiments(which are much easier on a simulation) suggest that this documentation is not correct, and that in fact the default setting for Kermit is to redirect CON to BAT
This is done by changing the two lower bits for iobyte from (our default of 01 which is CRT) to 10 which is BAT
Putting a debug on _kbhit shows that Kermit alternately polls the default port then the BAT port, so you can abort the transfer with a keypress (not sure which one though)
So for debugging at this point, attach a D9 to USB to Serial1 and open another terminal and use STAT CON:=TTY: to test the Serial One port, and then STAT CON:=BAT to test the Serial Two port
Once that is working, then replicate the whole thing with another ESP32 board. Connect these two with a D9 male to male crossover cable (pin 2 to 3, 3 to 2 and 5 to 5)
and it is then possible to run kermit on both boards and transfer files
KERMIT SEND TEST.TXT and KERMIT RECEIVE TEST.TXT
Kermit pauses every 10 secs or so to write data out to the disk and some packets look like they are resent
Text files are fine. Sending MBASIC.COM did not seem to work, the file was corrupted. However, using UNLOAD MBASIC.COM and sending MBASIC.HEX and then LOAD MBASIC.HEX all worked fine
For debugging it makes sense to leave the USB programming cable and use a terminal program (or even the arduino terminal program). This default is Serial Zero port.
For using the board standalone, TTY on Serial One may be better. It may be worth copying Grant Searle's idea of iobyte being set by the first character that comes in a port, CRT or TTY
see Grant Searle's page http://searle.hostei.com/grant/cpm/index.html discussion using two serial ports and switching using iobyte
Further thoughts, the ESP32 has Wifi and Bluetooth. These could ?? be CP/M 'devices'. The ESP32 bluetooth example is only a few lines.

[FAQ?] Graphics? Yes we can!

Well... there is no standard for graphics with CP/M but there are SIXELs!

And because this kind of graphics is just like printing with a dot matrix printer, CP/M programs easily can do it if connected to a terminal capable of sixel graphics:

grafik

Above snapshot was taken from RunCPM in an XTerm on Debian9. There are more sixel enabled terminals and it should work similar, if you connect RunCPM on an Arduino-DUE to one of them.

These files...

(yeti@kumari:16)/home/wrk/runcpm/run/C/1$ ls -l MB6EL.*
-rw-r--r-- 1 yeti yeti  896 Aug 13 16:41 MB6EL.C
-rw-r--r-- 1 yeti yeti 3712 Aug 13 16:41 MB6EL.COM
-rw-r--r-- 1 yeti yeti  128 Aug 13 16:13 MB6EL.SUB

...are attached as: mb6el.zip

Console redirection and adding extra ports on the ESP32

This isn't really an 'issue' so can be closed by Mr Mockba, but I thought I might write some notes about the code that was changed to enable Kermit file transfers.

  1. The board I am using is called ESPDUINO-32 and if you google this and select images, you can see it is an arduino form factor. I specifically went for the one with the large USB socket as this is plugged and unplugged many times and is mechanically stronger than the small ones. This particular board is not listed in the arduino IDE but it seems to compile ok with many of the ones that are listed. I used the first board in the list which is called ESP332 Dev Module.

  2. Near the beginning of the RunCPM module are some ifdef's, I changed the pins for the SD card to 19,23 and 18, the CS pin is 5, and the led is on pin 2.

#elif defined ESP32 // ESP32 boards
  SdFatSoftSpiEX<19, 23, 18> SD; // MISO, MOSI, SCK Some boards use 2,15,14,13, other 12,14,27,26
  #define SDINIT 5 // CS
  #define LED 2 // TTGO_T1=22 LOLIN32_Pro=5(inverted) DOIT_Esp32=2 ESP32-PICO-KIT=no led, Espduino pin 2
  #define LEDinv 0
  #define BOARD "ESPDUINO-32"
  1. in void setup() I added the two new serial ports (the ESP32 has three uarts. Just a thought here, the DUE has 4 ports so this idea could also work on that board too).
#ifdef ESP32  
  Serial1.begin(9600,SERIAL_8N1, 26, 25);    //Baud rate, parity mode, RX, TX  ESP32
  Serial2.begin(9600,SERIAL_8N1, 17, 16);    //Baud rate, parity mode, RX, TX  ESP32
#endif  
  1. For hardware I used Max3232 modules available on ebay. Run from the 3V3 pin. In keeping with the old-skool spirit, computers have male D9 plugs and devices (modems, terminals) are female D9. The female Max3232 modules are much more common - I had to search a bit to get the male ones. I made a crossover cable with two female sockets and pin 5 to 5, 2 to 3 and 3 to 2. I also had some modules with faults - some wouldn't work, and one had crosstalk between Tx and Rx so characters printed twice on the screen. I've also had some dodgy max3232 chips before and found that in this case it may be worth getting these from a big supplier like Radio Spares or Element 14 or similar.

  2. I got a copy of generic Kermit from Columbia University. It is in the CP/M archives. This needs no modification at all. If anyone has problems getting this I'll post a copy here.

  3. Below is a wall of code. This goes in the abstraction_arduino.h file. It needs to go above the console abstraction functions (I think this is because functions need to be declared before you use them, and this applies in .h files but not .ino files. ). Once this code is copied in, test everything still compiles ok. None of this should affect compilation as it isn't linked yet to any of the existing code.

// ***************************** Physical Device List **************************************
//CON: = TTY: CRT: BAT: UC1:
//RDR: = TTY: PTR: UR1: UR2:
//PUN: = TTY: PTP: UP1: UP2:
//LST: = TTY: CRT: LPT: UL1:

// TTY

void deviceTTYout(uint8_t ch)  // same as _putch 
{
  Serial1.write(ch); // same as _putch but with buffer overflow protection
  while (Serial1.availableForWrite() < 20) {
      delay(100); // at 9600 baud, ESP32 output buffer is 128 bytes, if stops when only 20 chars left in the output buffer, and pause 100ms, then have about 115 left as sending about 1 per ms.
  }
}

uint8_t deviceTTYavailable(void) {  // same as _kbhit
  return(Serial1.available());
}

uint8_t deviceTTYin(void) {  // same as _getch
  while (!Serial1.available());
  return(Serial1.read());
}

uint8_t deviceTTYinEcho(void) { // same as _getche
  uint8_t ch = deviceTTYin();
  deviceTTYout(ch);
  return(ch);
}

// CRT

void deviceCRTout(uint8_t ch)  // same as _putch 
{
  Serial.write(ch); // same as _putch but with buffer overflow protection
  while (Serial.availableForWrite() < 20) {
      delay(100); // at 9600 baud, ESP32 output buffer is 128 bytes, if stop when only 20 chars left in the output buffer, and pause 100ms, then have about 115 left as sending about 1 per ms.
  }
}

uint8_t deviceCRTavailable(void) {  // same as _kbhit
  return(Serial.available());
}

uint8_t deviceCRTin(void) {  // same as _getch
  while (!Serial.available());
  return(Serial.read());
}

uint8_t deviceCRTinEcho(void) { // same as _getche
  uint8_t ch = deviceCRTin();
  deviceCRTout(ch);
  return(ch);
}

// UR1 

uint8_t deviceUR1in(void) {
    uint8_t ch = 26;
    return ch;
}

// UP1 

void deviceUP1out(uint8_t ch) {
  // add code here
}

// BAT, console device, input and output and can see if characters waiting, input used by Kermit as the default input device

void deviceBATout(uint8_t ch) 
{
  Serial2.write(ch); // same as _putch but with buffer overflow protection
  while (Serial2.availableForWrite() < 20) {
      delay(100); // at 9600 baud, ESP32 output buffer is 128 bytes, if stop when only 20 chars left in the output buffer, and pause 100ms, then have about 115 left as sending about 1 per ms.
  }
}

uint8_t deviceBATavailable(void) {  
   return(Serial2.available());
}

uint8_t deviceBATin(void) {  
  while (!Serial2.available());
  return(Serial2.read());
}

uint8_t deviceBATinEcho(void) { 
  uint8_t ch = deviceBATin();
  deviceBATout(ch);
  return(ch);
}

// UC1, console device

void deviceUC1out(uint8_t ch) 
{
  // add code here
}

uint8_t deviceUC1available(void) {  
  return(1); // add code here
}

uint8_t deviceUC1in(void) {  
    return(26); // add code here
}

uint8_t deviceUC1inEcho(void) { 
  uint8_t ch = deviceUC1in();
  deviceUC1out(ch);
  return(ch);
}

// PTR, reader device

uint8_t devicePTRin(void) {
    return 26; // add code here
}

// UR2, reader device

uint8_t deviceUR2in(void) {
    return 26; // add code here
}

// PTP,  punch device

void devicePTPout(uint8_t ch) {
    Serial2.write(ch); // used by Kermit as the default output device
    while (Serial2.availableForWrite() < 20) {
      delay(100); // at 9600 baud, if stop when only 20 chars left, and pause 100ms, then have about 115 left, as sending about 1 per ms. Should not need to do this if using small packets with Kermit
    }
}

// UP2, punch device

void deviceUP2out(uint8_t ch) {
  // add code here - eg write to file
}

// UL1,  LST device

void deviceUL1out(uint8_t ch) {
  // add code here - eg write to file
}


// LPT,  LST device

void deviceLPTout(uint8_t ch) {
  // add code here
}

// *************************************

// redirection for CON RDR PUN and LST eg CONin, CONout, CONavailable directed to one of four places depending on IOBYTE. 

uint8_t iobyteCON()
{
  uint8_t iobyte;
  iobyte = _RamRead(0x0003);
  iobyte = iobyte & 0x03; // mask off 00000011
  return iobyte;
}

uint8_t iobyteRDR()
{
  uint8_t iobyte;
  iobyte = _RamRead(0x0003);
  iobyte = iobyte & 0x0C; // mask off 00001100
  iobyte = iobyte >> 2; // bitshift so low 2 bits
  return iobyte;
}

uint8_t iobytePUN()
{
  uint8_t iobyte;
  iobyte = _RamRead(0x0003);
  iobyte = iobyte & 0x30; // mask off 00110000
  iobyte = iobyte >> 4; // bitshift so low 2 bits
  return iobyte;
}

uint8_t iobyteLST()
{
  uint8_t iobyte;
  iobyte = _RamRead(0x0003);
  iobyte = iobyte & 0xC0; // mask off 11000000
  iobyte = iobyte >> 6; // bitshift so low 2 bits
  return iobyte;
}

//CON: = TTY: CRT: BAT: UC1:
void outCON(uint8_t ch)
{
  uint8_t iobyte;
  iobyte = iobyteCON(); // 00, 01 10, 11
  switch (iobyte) {
    case 0: deviceTTYout(ch);
            break;
    case 1: deviceCRTout(ch);
            break;
    case 2: deviceBATout(ch);
            break;
    case 3: deviceUC1out(ch);
            break;                                 
  }
}

uint8_t availableCON()
{
  uint8_t iobyte;
  uint8_t dataAvailable;
  iobyte = iobyteCON(); // 00, 01 10, 11
  switch (iobyte) {
    case 0: dataAvailable = deviceTTYavailable();
            break;
    case 1: dataAvailable = deviceCRTavailable();
            break;
    case 2: dataAvailable = deviceBATavailable();
            break;
    case 3: dataAvailable = deviceUC1available();
            break;                                 
  }
  return dataAvailable;
}

uint8_t inCON(void)
{
  uint8_t iobyte;
  uint8_t dataIn;
  iobyte = iobyteCON(); // 00, 01 10, 11
  switch (iobyte) {
    case 0: dataIn = deviceTTYin();
            break;
    case 1: dataIn = deviceCRTin();
            break;
    case 2: dataIn = deviceBATin();
            break;
    case 3: dataIn = deviceUC1in();
            break;                                 
  }
  return dataIn;
}

uint8_t echoCON()
{
  uint8_t ch;
  ch = inCON();
  outCON(ch);
  return(ch);
}

//RDR: = TTY: PTR: UR1: UR2:
uint8_t inRDR(void)
{
  uint8_t iobyte;
  uint8_t dataIn;
  iobyte = iobyteRDR(); // 00, 01 10, 11
  switch (iobyte) {
    case 0: dataIn = deviceTTYin();
            break;
    case 1: dataIn = devicePTRin();
            break;
    case 2: dataIn = deviceUR1in();
            break;
    case 3: dataIn = deviceUR2in();
            break;                                 
  }
  return dataIn;
}

//PUN: = TTY: PTP: UP1: UP2:
void outPUN(uint8_t ch)
{
  uint8_t iobyte;
  iobyte = iobytePUN(); // 00, 01 10, 11
  switch (iobyte) {
    case 0: deviceTTYout(ch);
            break;
    case 1: devicePTPout(ch);
            break;
    case 2: deviceUP1out(ch);
            break;
    case 3: deviceUP2out(ch);
            break;                                 
  }
}

//LST: = TTY: CRT: LPT: UL1:
void outLST(uint8_t ch)
{
  uint8_t iobyte;
  iobyte = iobyteLST(); // 00, 01 10, 11
  switch (iobyte) {
    case 0: deviceTTYout(ch);
            break;
    case 1: deviceCRTout(ch);
            break;
    case 2: deviceLPTout(ch);
            break;
    case 3: deviceUL1out(ch);
            break;                                 
  }
}
  1. Next is to change the console code so that instead of, say, sending a character to the Serial port, instead, redirect it to the code above. I found it safer when debugging to comment out code rather than delete it, so you can see what has been changed.
/* Console abstraction functions */
/*===============================================================================*/

uint8_t _kbhit(void) {
  //return(Serial.available());
  return availableCON();  // redirect based on iobyte
}

uint8_t _getch(void) {
  //while (!Serial.available());
  //return(Serial.read());
  return inCON(); // redirect based on iobyte
}

uint8_t _getche(void) {
  //uint8_t ch = _getch();
  //Serial.write(ch);
  //return(ch);
  return echoCON(); // redirect based on iobyte
}

void _putch(uint8_t ch) {
  //Serial.write(ch);
  outCON(ch); // redirect based on iobyte
}

void _clrscr(void) {
  Serial.println("\e[H\e[J"); // done once at startup so left as is
}
  1. Looking back through the code. I think that is pretty much it. I did end up adding in a tiny bit of code in the cpm.h bdos function to redirect to the reader device, however in the code above the reader device doesn't do anything. But this does give an idea how to add in other devices.
	/*
		C = 3 : Auxiliary (Reader) input
		Returns: A=Char
		*/
	case 3:
#ifdef ESP32
    HL = inRDR();
#else    
    HL = 0x1a; // ^Z end file
#enif d   
		break;
  1. Commented out the ioport ramwrite setting in cpm.h and moved it to the void setup() routine in RunCPM. I am not sure if this has been changed in a recent update. I did a clean install on 11th August and rebuilt it using these instructions and this did need to be changed.
    _RamWrite(0x0003, 0x3D);

  2. Thinking how to use the ports, Grant Searle has a system where the first character that comes in defines which port is being used. I am thinking of something even simpler. For debugging the iobyte is set at startup so CON goes to CRT on the USB serial port. Once a board is working and it is going in a box, recompile with the iobyte set at startup to TTY which is on Serial 1. The box I am making has a hole for the USB socket so you can plug that in and that is for programming and for using a PC terminal program. Then a male D9 for TTY and that goes to a physical terminal (eg a PropTerm, or a Raspberry Pi, or one using an Arduino Uno). And the second male D9 is BAT: and that is for file transfers. I have some vague ideas that the 4th port could be something to do with Wifi or Bluetooth as these are both on the ESP32.

  3. One small bug I am working on - kermit works rock solid between two boards, but when using teraterm with a kermit transfer, it seems to have many dropped packets. This is true at baud rates from 1200 to 115200. I have tried different Max3232 modules, different USB to serial devices and different boards. I haven't tried different terminal programs. This may not be such an issue, because the huge advantage of RunCPM over all other real and emulated CP/M systems is that it uses Fat32 files on the SD card. Thanks++ to Mr Borg for this :)

Q: User areas

When "user areas" get turned on as default feature:
Are you planning to add creating the missing numbered subdirectories on the fly?

...and... RunCPM/globals.h, line 48:

User numbers are 0-9, then A-F for users 12-15

...10-15...

STAT (on STM build) does not see all drives + reports same free size for all

STAT on my STM build doesn't consider a disk as present unless it's explicitly referenced, or has been 'visitied'. In any event, the free space for all disks seems to return the same value for all disks - but not always the same value, so, for example, A: is reported as different sizes (see examples below)

Here, I run STAT after walking round or referencing a few disks and doing a few RESETs. The system has drives A-D (all upper case), each with a '0' subfolder. The drives have different things on them.


CP/M 2.2 Emulator v3.7 by Marcelo Dantas
Arduino read/write support by Krzysztof Klis
      Build Jun 24 2019 - 19:29:15
--------------------------------------------
CCP: CCP-DR.60K    CCP Address: 0xe400
BOARD: STM32F411 Nucleo
Initializing SD card.

RunCPM Version 3.7 (CP/M 2.2 60K)

A>stat
A: R/W, Space: 898k
A>stat b:
Bytes Remaining On B: 898k
A>stat
A: R/W, Space: 898k
B: R/W, Space: 898k
A>

[RESET]

CP/M 2.2 Emulator v3.7 by Marcelo Dantas
Arduino read/write support by Krzysztof Klis
      Build Jun 24 2019 - 19:29:15
--------------------------------------------
CCP: CCP-DR.60K    CCP Address: 0xe400
BOARD: STM32F411 Nucleo
Initializing SD card.

RunCPM Version 3.7 (CP/M 2.2 60K)

A>stat b:
Bytes Remaining On B: 898k
A>stat
A: R/W, Space: 898k
B: R/W, Space: 898k
A>
B>a:stat
A: R/W, Space: 898k

[RESET]

CP/M 2.2 Emulator v3.7 by Marcelo Dantas
Arduino read/write support by Krzysztof Klis
      Build Jun 24 2019 - 19:29:15
--------------------------------------------
CCP: CCP-DR.60K    CCP Address: 0xe400
BOARD: STM32F411 Nucleo
Initializing SD card.

RunCPM Version 3.7 (CP/M 2.2 60K)

A>stat b:
Bytes Remaining On B: 898k
A>stat
A: R/W, Space: 898k
B: R/W, Space: 898k
A>d:
D>dir
D: ZORK1    COM : ZORK1    DAT : ZORK2    COM : ZORK2    DAT
D: ZORK3    COM : ZORK3    DAT
D>e:
Bdos Error on E : Select

RunCPM Version 3.7 (CP/M 2.2 60K)

D>dir
D: ZORK1    COM : ZORK1    DAT : ZORK2    COM : ZORK2    DAT
D: ZORK3    COM : ZORK3    DAT
D>a:
A>stat
A: R/W, Space: 962k
D: R/W, Space: 962k
A>b:
B>a:stat
A: R/W, Space: 962k
B: R/W, Space: 962k
D: R/W, Space: 962k
B>
B>a:stat
A: R/W, Space: 962k
B: R/W, Space: 962k
D: R/W, Space: 962k
B>a:stat c:
Bytes Remaining On C: 962k
B>a:stat
A: R/W, Space: 962k
B: R/W, Space: 962k
C: R/W, Space: 962k
D: R/W, Space: 962k

May need to add ENABLE_VIRTUAL_TERMINAL_PROCESSING

Hello, I tried runcpm.exe and it runs under Windows 7 except for processing of ANSI terminal escape sequences. Upon investigation it seems there is a flag that must be set for the console host to filter and process the escape sequences ( ENABLE_VIRTUAL_TERMINAL_PROCESSING). I even tried the another method with a program called "ansicon.exe" and it did not work. I discovered this issue trying the TE.COM editor and TURBO Pascal for CPM-80. The ANSI escape sequences just get echoed to the console. I think this flag can be added to the function void _console_init(void) in abstraction_vstudio.h
Here is the Microsoft Reference URL on Console Virtual Terminal Sequences: https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences

Is there a Problem in the Posix port or do I have a case of PEBCAK here?

I'm trying to build and run RunCPM on Debian-8.5/amd64 (tried on Debian-7.11/armhf (on Cubietruck) some days ago too) but I always get results like below...

CP/M 2.2 Emulator v2.6 by Marcelo Dantas
      Build Sep  8 2016 - 17:31:15
-----------------------------------------
CCP: CCP-DR.BIN Loaded at 0xf400

RunCPM Version 2.6 (CP/M 2.2 64K)

A>dir
A: 1STREAD  ME  : BDOS     ASM : BDOS     SUB : CLEAN    SUB
A: DISKDEF  LIB : DUMP     ASM : ED       COM : EXIT     ASM
A: EXIT     COM : EXIT     SUB : EXIT     Z80 : LOAD     COM
A: MBASIC   COM : MLOAD    ASM : MLOAD    COM : MLOAD    DOC
A: MOVCPM   COM : OPCODES  TXT : STAT     COM : SUBMIT   COM
A: SYSGEN   COM : XSUB     COM : Z80ASM   COM : ZCPR     ASM
A: ZCPR     SUB : ZCPRHDR  LIB : ZEXALL   COM : ZEXDOC   COM
A: ZSID     COM : ZTRAN4   COM
A>exit
EXIT?

A>mbasic
MBASIC?

A>_

"Internal" commands like dir work but others do not.

Integrated debugger

Hi, I've been looking through the source code, getting an idea of RunCPM's strucutre and the BIOS emulation, and I noticed what looks like a debug monitor in the CPU module.

What I can't figure out is how to break into this debug module, so I can use this to test and debug 8080/Z80 code using the debugger.

Is there a way to do this from within the emulator, or should I build a custom version of the code with a way to break in to the debugger?

Windows RunCPM folder can't be on Dropbox

On Windows, RunCPM seems unable to cope with the RunCPM folder being on Dropbox. On startup, we get:

Bdos Error on A : Select

I'm not currently set up to recompile on Windows, but I think I can see the problem.

In abstraction_vstudio.h, around line 126, we have:

int _sys_select(uint8 *disk) {
return((uint8)GetFileAttributes((LPCSTR)disk) == 0x10);
}

I checked the file attributes returned by the WIN32 API using Python, and it seems that the folder in Dropbox returns 0x30 instead of 0x10. The attributes are a bit mask, so that's 0x20 | 0x10, where 0x10 is the "I'm a directory" bit and 0x20 is the "archive" bit.

I think the problem would go away if the above lines of code were replaced by:

int _sys_select(uint8 *disk) {
return(((uint8)GetFileAttributes((LPCSTR)disk) & 0x10) != 0);
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.