Compare commits

...

47 Commits

Author SHA1 Message Date
Wayne Warthen
39afeda279 Documentation Tweaks 2025-04-03 16:19:23 -07:00
Wayne Warthen
23c5f7b8c0 Merge pull request #519 from fraser125/fraser125-Front-Panel-Table
Update UserGuide.md - Front Panel Table
2025-04-03 15:26:52 -07:00
fraser
91c7349026 Update UserGuide.md - Front Panel Table
I thought a Table layout for the Front Panel switches would be a bit easier to follow.
2025-04-03 14:50:43 -07:00
Wayne Warthen
80995f5264 Update TE.COM
@Laci1953 updated TE under RomWBW to support up to 512K of RAM buffers.
2025-04-03 13:52:56 -07:00
Wayne Warthen
56c9edb547 Updates to TE and COWFE
- Minor updates to TE.COM and COWFE.COM provided by @Laci1953.
- Fixed typo in TE ReadMe identified by @stickbreaker.

Co-Authored-By: ladislau szilagyi <87603175+Laci1953@users.noreply.github.com>
2025-04-02 11:20:00 -07:00
Wayne Warthen
af21691d4e Add TE Editor
Added latest RomWBW version of TE Editor from @Laci1953.

Co-Authored-By: ladislau szilagyi <87603175+Laci1953@users.noreply.github.com>
2025-04-01 12:07:51 -07:00
Wayne Warthen
3a228e3c1f Merge pull request #517 from kiwisincebirth/map/doc-hdd
Improvements to User Guide by improving readability
2025-03-31 17:45:12 -07:00
Mark Pruden
d299a9009f Corrected unintended deleteion 2025-04-01 11:42:47 +11:00
Mark Pruden
667aeeb24d Improvements to User Guide by simplifying content 2025-04-01 11:36:15 +11:00
Wayne Warthen
067560ae74 More User Guide Improvements from Issue #516
Thanks and credit to @kiwisincebirth for the suggestions.
2025-03-31 16:50:29 -07:00
Wayne Warthen
ef0656f162 Improve User Guide per Issue #516
- Small changes to Combo Hard Disk Images section as suggested by @kiwisincebirth.
2025-03-31 13:50:50 -07:00
Wayne Warthen
a8a5a85c5c Update Cowgol Disk Image, Issue #506
Updated Cowgol disk image with the latest distribution from Ladislau Szilagyi.

Co-Authored-By: ladislau szilagyi <87603175+Laci1953@users.noreply.github.com>
2025-03-29 14:06:34 -07:00
Wayne Warthen
4dcd00089e Bump Version, Release Candidate 1 2025-03-28 19:44:46 -07:00
Wayne Warthen
f4caf244af Update Makefile
- Fix filename case
2025-03-28 17:32:40 -07:00
Wayne Warthen
a91deeb347 Add Peter Onion's ZDE ANSI Keyboard Support
- Added new ANSI keyboard support from Peter Onion.
- ZDE is now built as part of the RomWBW build itself.
- Did not yet include support for modified ZDE escape character.
- See <https://groups.google.com/g/rc2014-z80/c/hAZen3pZb7o>

Co-Authored-By: PeterOGB <7755057+peterogb@users.noreply.github.com>
2025-03-28 17:25:55 -07:00
Wayne Warthen
3804c69428 Minor Typos & Regen Doc 2025-03-26 12:51:47 -07:00
Wayne Warthen
1b45d32af2 Merge pull request #513 from kiwisincebirth/map/disk-doc
Revised Section 6.2.4 of UserGuide
2025-03-26 12:38:48 -07:00
Wayne Warthen
83e3b8f24f Resolve Merge Conflict 2025-03-26 11:55:51 -07:00
Wayne Warthen
29f6fea4aa Resolve Merge Conflict 2025-03-26 11:51:55 -07:00
Wayne Warthen
bf61350280 Regen Docs 2025-03-26 11:41:26 -07:00
Wayne Warthen
ecf2cdfba2 Fix Device Attribute Definition in System Guide, Issue #515 2025-03-26 11:37:41 -07:00
Wayne Warthen
9fc2c6129b Fix CIO Table in System Guide, Issue #514 2025-03-26 11:23:23 -07:00
Mark Pruden
8f80f2f9cd Revised Section 6.2.4 of UserGuide See Issue #508 2025-03-26 13:39:37 +11:00
Wayne Warthen
81d81952d3 Regen Docs 2025-03-24 11:30:12 -07:00
Wayne Warthen
ed532cb51b Fix Type in INTINF API Description, Issue #512 2025-03-24 11:20:27 -07:00
Wayne Warthen
a46e05258c Clarify .COM File Location and Naming. Issue #511 2025-03-24 11:17:30 -07:00
Wayne Warthen
a35dbefeda Fix System Guide Typo, Issue #510 2025-03-24 11:12:32 -07:00
Wayne Warthen
74f4149034 Merge pull request #509 from kiwisincebirth/map/drivereset
COPYSL : Reset CP/M Drives after Completion.
2025-03-22 18:40:19 -07:00
Mark Pruden
34cc40f459 Added Code to Reset All Drives after successful completion. 2025-03-22 22:10:32 +11:00
Wayne Warthen
6f5aa06fb3 Improve cpmtools Makefile, Issue #505
See issue #505.  This change should improve build compatibility if there are multiple variants of ncurses installed.

Thanks and credit to @mabartibin.

Co-Authored-By: mabartibin <16798058+mabartibin@users.noreply.github.com>
2025-03-21 18:50:49 -07:00
Wayne Warthen
b28e308bfd Include COPYSL in Build Process 2025-03-21 17:01:14 -07:00
Wayne Warthen
3d23cea071 Merge pull request #507 from kiwisincebirth/map/copysl
Source Code (Inactive) for CopySL Utility
2025-03-21 16:19:42 -07:00
Mark Pruden
f7b8efd964 Added source Code for copySL, build scripts not updated 2025-02-27 10:21:29 +11:00
Wayne Warthen
3c7e3d7586 Issue v3.5 Release Candidate 2025-02-24 12:30:05 -08:00
Wayne Warthen
f359f5fb61 Update SIMH Emulator 2025-02-22 16:19:08 -08:00
Wayne Warthen
50deb280b5 Update Build.cmd
- Remove debugging
2025-02-22 15:22:30 -08:00
Wayne Warthen
7654a6b2ed Minor Doc Sync 2025-02-22 15:10:32 -08:00
Wayne Warthen
dd9e7d6532 Restore ZEX to User Area 0 for BP Disk Image
ZEX.COM is required on user area 0 of BP disk images because it is used for startup processing prior to establishing a path to user area 15.
2025-02-19 15:28:52 -08:00
Wayne Warthen
37ebfefea3 Merge branch 'master' of https://github.com/wwarthen/RomWBW 2025-02-19 14:20:30 -08:00
Wayne Warthen
6d8ecbb49a Fix XM and ZMD Under UNA
Looks like the UNA driver for both XM and ZMD has always been borked.  This fixes it and tested working.
2025-02-19 14:20:26 -08:00
Wayne Warthen
dfb005ae9e Merge pull request #503 from feilipu/patch-1
HBIOS UART - manage /DTR along with /RTS
2025-02-18 16:24:24 -08:00
Phillip Stevens
5806522402 UART manage /DTR along with /RTS
The RC2014 Single and Dual UART Modules do not have the /RTS line connected. The /DTR line is used to signal flow control.

This PR simply adds active management of the /DTR.
The current UART initialisation process already does configuration, but not active management.
2025-02-19 10:09:07 +11:00
Wayne Warthen
930bcce7da Doc Improvements
- Added missing applications to Applications document
- Added a debug statement to Build.cmd in BPBIOS
2025-02-18 10:44:48 -08:00
Wayne Warthen
ad7d7638d3 Update BBC BASIC
- Updated BBC BASIC (Z80) source from R.T.Russell's repository.
2025-02-17 17:21:44 -08:00
Wayne Warthen
da05245b4a Improved STRICTPART Implementation
- Improved implementation of STRICTPART conditional based on comments from @kiwisincebirth.  See Issue #490.
2025-02-13 16:06:43 -08:00
Wayne Warthen
9469aaf333 Delete Unblock.cmd 2025-02-12 20:07:52 -08:00
Wayne Warthen
363218b0eb Create Unblock.cmd 2025-02-12 19:04:38 -08:00
118 changed files with 59732 additions and 20287 deletions

View File

@@ -11,3 +11,4 @@ if exist Tunes\*.vgm del Tunes\*.vgm
if exist bbcbasic.txt del bbcbasic.txt
pushd Test && call Clean || exit /b 1 & popd
pushd ZDE && call Clean || exit /b 1 & popd

View File

@@ -1,6 +1,6 @@
TOOLS = ../../Tools
MOREDIFF := $(shell $(TOOLS)/unix/casefn.sh *.com)
SUBDIRS = Test
SUBDIRS = Test ZDE
include $(TOOLS)/Makefile.inc

View File

@@ -0,0 +1,4 @@
@echo off
setlocal
if exist *.com del *.com

6
Binary/Apps/ZDE/Makefile Normal file
View File

@@ -0,0 +1,6 @@
TOOLS = ../../../Tools
include $(TOOLS)/Makefile.inc
clean::
@rm -f *.com

View File

@@ -0,0 +1,10 @@
***********************************************************************
*** ***
*** R o m W B W ***
*** ***
*** Z80/Z180 System Software ***
*** ***
***********************************************************************
This directory contains the ZDE executable binaries. They are
in their original, unconfigured state.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -51,7 +51,7 @@ release of RomWBW.
allows OS to recover from applications that reprogram the TMS
video display controller.
- Implemented "application" RAM banks that can be discovered bia
- Implemented "application" RAM banks that can be discovered via
the HBIOS API.
- Documentation improvements (Mark Pruden), including:

View File

@@ -7,7 +7,7 @@
**RomWBW Introduction** \
Version 3.5 \
Wayne Warthen ([wwarthen@gmail.com](mailto:wwarthen@gmail.com)) \
12 Feb 2025
03 Apr 2025
# Overview

View File

@@ -1,6 +1,6 @@
RomWBW Introduction
Wayne Warthen (wwarthen@gmail.com)
12 Feb 2025
03 Apr 2025
@@ -17,11 +17,11 @@ Z80/180/280 retro-computing hardware systems.
A wide variety of platforms are supported including those produced by
these developer communities:
- RetroBrew Computers (https://www.retrobrewcomputers.org)
- RC2014 (https://rc2014.co.uk),
RC2014-Z80 (https://groups.google.com/g/rc2014-z80)
- Retro Computing (https://groups.google.com/g/retro-comp)
- Small Computer Central (https://smallcomputercentral.com/)
- RetroBrew Computers (https://www.retrobrewcomputers.org)
- RC2014 (https://rc2014.co.uk),
RC2014-Z80 (https://groups.google.com/g/rc2014-z80)
- Retro Computing (https://groups.google.com/g/retro-comp)
- Small Computer Central (https://smallcomputercentral.com/)
A complete list of the currently supported platforms is found in RomWBW
Hardware .
@@ -41,16 +41,16 @@ Card) and move it between systems transparently.
Supported hardware features of RomWBW include:
- Z80 Family CPUs including Z80, Z180, and Z280
- Banked memory services for several banking designs
- Disk drivers for RAM, ROM, Floppy, IDE ATA/ATAPI, CF, SD, USB, Zip,
Iomega
- Serial drivers including UART (16550-like), ASCI, ACIA, SIO
- Video drivers including TMS9918, SY6545, MOS8563, HD6445
- Keyboard (PS/2) drivers via VT8242 or PPI interfaces
- Real time clock drivers including DS1302, BQ4845
- Support for CP/NET networking using Wiznet, MT011 or Serial
- Built-in VT-100 terminal emulation support
- Z80 Family CPUs including Z80, Z180, and Z280
- Banked memory services for several banking designs
- Disk drivers for RAM, ROM, Floppy, IDE ATA/ATAPI, CF, SD, USB, Zip,
Iomega
- Serial drivers including UART (16550-like), ASCI, ACIA, SIO
- Video drivers including TMS9918, SY6545, MOS8563, HD6445
- Keyboard (PS/2) drivers via VT8242 or PPI interfaces
- Real time clock drivers including DS1302, BQ4845
- Support for CP/NET networking using Wiznet, MT011 or Serial
- Built-in VT-100 terminal emulation support
A dynamic disk drive letter assignment mechanism allows mapping
operating system drive letters to any available disk media.
@@ -73,22 +73,22 @@ changing media.
Some of the included software:
- Operating Systems (CP/M 2.2, ZSDOS, NZ-COM, CP/M 3, ZPM3, Z3PLUS,
QPM )
- Support for other operating systems, p-System, FreeRTOS, and FUZIX.
- Programming Tools (Z80ASM, Turbo Pascal, Forth, Cowgol)
- C Compilers including Aztec-C, and HI-TECH C
- Microsoft Basic Compiler, and Microsoft Fortran
- Some games such as Colossal Cave, Zork, etc
- Wordstar Word processing software
- Operating Systems (CP/M 2.2, ZSDOS, NZ-COM, CP/M 3, ZPM3, Z3PLUS, QPM
)
- Support for other operating systems, p-System, FreeRTOS, and FUZIX.
- Programming Tools (Z80ASM, Turbo Pascal, Forth, Cowgol)
- C Compilers including Aztec-C, and HI-TECH C
- Microsoft Basic Compiler, and Microsoft Fortran
- Some games such as Colossal Cave, Zork, etc
- Wordstar Word processing software
Some of the provided software can be launched directly from the ROM
firmware itself:
- System Monitor
- Operating Systems (CP/M 2.2, ZSDOS)
- ROM BASIC (Nascom BASIC and Tasty BASIC)
- ROM Forth
- System Monitor
- Operating Systems (CP/M 2.2, ZSDOS)
- ROM BASIC (Nascom BASIC and Tasty BASIC)
- ROM Forth
A tool is provided that allows you to access a FAT-12/16/32 filesystem.
The FAT filesystem may be coresident on the same disk media as RomWBW
@@ -174,25 +174,24 @@ Documentation
There are several documents that form the core of the RomWBW
documentation:
- RomWBW User Guide is the main user guide for RomWBW, it covers the
major topics of how to install, manage and use RomWBW, and includes
additional guidance to the use of some of the operating systems
supported by RomWBW
- RomWBW User Guide is the main user guide for RomWBW, it covers the
major topics of how to install, manage and use RomWBW, and includes
additional guidance to the use of some of the operating systems
supported by RomWBW
- RomWBW Hardware contains a description of all the hardware
platforms, and devices supported by RomWBW.
- RomWBW Hardware contains a description of all the hardware platforms,
and devices supported by RomWBW.
- RomWBW Applications is a reference for the ROM-hosted and OS-hosted
applications created or customized to enhance the operation of
RomWBW.
- RomWBW Applications is a reference for the ROM-hosted and OS-hosted
applications created or customized to enhance the operation of RomWBW.
- RomWBW Disk Catalog is a reference for the contents of the disk
images provided with RomWBW, with a description of many of the files
on each image
- RomWBW Disk Catalog is a reference for the contents of the disk images
provided with RomWBW, with a description of many of the files on each
image
- RomWBW System Guide discusses much of the internal design and
construction of RomWBW. It includes a reference for the RomWBW HBIOS
API functions.
- RomWBW System Guide discusses much of the internal design and
construction of RomWBW. It includes a reference for the RomWBW HBIOS
API functions.
Each of the operating systems and ROM applications included with RomWBW
are sophisticated tools in their own right. It is not reasonable to
@@ -217,9 +216,9 @@ Getting Assistance
The best way to get assistance with RomWBW or any aspect of the
RetroBrew Computers projects is via one of the community forums:
- RetroBrew Computers Forum
- RC2014 Google Group
- retro-comp Google Group
- RetroBrew Computers Forum
- RC2014 Google Group
- retro-comp Google Group
Submission of issues and bugs are welcome at the RomWBW GitHub
Repository.
@@ -244,110 +243,108 @@ RetroBrew Computers Community. I sincerely appreciate all of their
contributions. The list below is probably missing many names please
let me know if I missed you!
- Andrew Lynch started it all when he created the N8VEM Z80 SBC which
became the first platform RomWBW supported. Some of his original
code can still be found in RomWBW.
- Andrew Lynch started it all when he created the N8VEM Z80 SBC which
became the first platform RomWBW supported. Some of his original code
can still be found in RomWBW.
- Dan Werner wrote much of the code from which RomWBW was originally
derived and he has always been a great source of knowledge and
advice.
- Dan Werner wrote much of the code from which RomWBW was originally
derived and he has always been a great source of knowledge and advice.
- Douglas Goodall contributed code, time, testing, and advice in “the
early days”. He created an entire suite of application programs to
enhance the use of RomWBW. Unfortunately, they have become unusable
due to internal changes within RomWBW. As of RomWBW 2.6, these
applications are no longer provided.
- Douglas Goodall contributed code, time, testing, and advice in “the
early days”. He created an entire suite of application programs to
enhance the use of RomWBW. Unfortunately, they have become unusable
due to internal changes within RomWBW. As of RomWBW 2.6, these
applications are no longer provided.
- Sergey Kiselev created several hardware platforms for RomWBW
including the very popular Zeta.
- Sergey Kiselev created several hardware platforms for RomWBW including
the very popular Zeta.
- David Giles created support for the Z180 CSIO which is now included
SD Card driver.
- David Giles created support for the Z180 CSIO which is now included SD
Card driver.
- Phil Summers contributed the Forth and BASIC adaptations in ROM, the
AY-3-8910 sound driver, DMA support, and a long list of general code
and documentation enhancements.
- Phil Summers contributed the Forth and BASIC adaptations in ROM, the
AY-3-8910 sound driver, DMA support, and a long list of general code
and documentation enhancements.
- Ed Brindley contributed some of the code that supports the RCBus
platform.
- Ed Brindley contributed some of the code that supports the RCBus
platform.
- Spencer Owen created the RC2014 series of hobbyist kit computers
which has exponentially increased RomWBW usage. Some of his kits
include RomWBW.
- Spencer Owen created the RC2014 series of hobbyist kit computers which
has exponentially increased RomWBW usage. Some of his kits include
RomWBW.
- Stephen Cousins has likewise created a series of hobbyist kit
computers at Small Computer Central and is distributing RomWBW with
many of them.
- Stephen Cousins has likewise created a series of hobbyist kit
computers at Small Computer Central and is distributing RomWBW with
many of them.
- Alan Cox has contributed some driver code and has provided a great
deal of advice.
- Alan Cox has contributed some driver code and has provided a great
deal of advice.
- The CP/NET client files were developed by Douglas Miller.
- The CP/NET client files were developed by Douglas Miller.
- Phillip Stevens contributed support for FreeRTOS.
- Phillip Stevens contributed support for FreeRTOS.
- Curt Mayer contributed the original Linux / MacOS build process.
- Curt Mayer contributed the original Linux / MacOS build process.
- UNA BIOS and FDISK80 are the products of John Coffman.
- UNA BIOS and FDISK80 are the products of John Coffman.
- FLASH4 is a product of Will Sowerbutts.
- FLASH4 is a product of Will Sowerbutts.
- CLRDIR is a product of Max Scane.
- CLRDIR is a product of Max Scane.
- Tasty Basic is a product of Dimitri Theulings.
- Tasty Basic is a product of Dimitri Theulings.
- Dean Netherton contributed eZ80 CPU support, the sound driver
interface, and the SN76489 sound driver.
- Dean Netherton contributed eZ80 CPU support, the sound driver
interface, and the SN76489 sound driver.
- The RomWBW Disk Catalog document was produced by Mykl Orders.
- The RomWBW Disk Catalog document was produced by Mykl Orders.
- Rob Prouse has created many of the supplemental disk images
including Aztec C, HiTech C, SLR Z80ASM, Turbo Pascal, Microsoft
BASIC Compiler, Microsoft Fortran Compiler, and a Games compendium.
- Rob Prouse has created many of the supplemental disk images including
Aztec C, HiTech C, SLR Z80ASM, Turbo Pascal, Microsoft BASIC Compiler,
Microsoft Fortran Compiler, and a Games compendium.
- Martin R has provided substantial help reviewing and improving the
User Guide and Applications documents.
- Martin R has provided substantial help reviewing and improving the
User Guide and Applications documents.
- Mark Pruden has made a wide variety of contributions including:
- Mark Pruden has made a wide variety of contributions including:
- significant content in the Disk Catalog and User Guide
- creation of the Introduction and Hardware documents
- Z3PLUS operating system disk image
- COPYSL utility
- a feature for RomWBW configuration by NVRAM
- the /B bulk mode of disk assignment to the ASSIGN utility
- significant content in the Disk Catalog and User Guide
- creation of the Introduction and Hardware documents
- Z3PLUS operating system disk image
- COPYSL utility
- a feature for RomWBW configuration by NVRAM
- the /B bulk mode of disk assignment to the ASSIGN utility
- Jacques Pelletier has contributed the DS1501 RTC driver code.
- Jacques Pelletier has contributed the DS1501 RTC driver code.
- Jose Collado has contributed enhancements to the TMS driver
including compatibility with standard TMS register configuration.
- Jose Collado has contributed enhancements to the TMS driver including
compatibility with standard TMS register configuration.
- Kevin Boone has contributed a generic HBIOS date/time utility
(WDATE).
- Kevin Boone has contributed a generic HBIOS date/time utility (WDATE).
- Matt Carroll has contributed a fix to XM.COM that corrects the port
specification when doing a send.
- Matt Carroll has contributed a fix to XM.COM that corrects the port
specification when doing a send.
- Dean Jenkins enhanced the build process to accommodate the Raspberry
Pi 4.
- Dean Jenkins enhanced the build process to accommodate the Raspberry
Pi 4.
- Tom Plano has contributed a new utility (HTALK) to allow talking
directly to HBIOS COM ports.
- Tom Plano has contributed a new utility (HTALK) to allow talking
directly to HBIOS COM ports.
- Lars Nelson has contributed several generic utilities such as a
universal (OS agnostic) UNARC application.
- Lars Nelson has contributed several generic utilities such as a
universal (OS agnostic) UNARC application.
- Dylan Hall added support for specifying a secondary console.
- Dylan Hall added support for specifying a secondary console.
- Bill Shen has contributed boot loaders for several of his systems.
- Bill Shen has contributed boot loaders for several of his systems.
- Laszlo Szolnoki has contributed an EF9345 video display controller
driver.
- Laszlo Szolnoki has contributed an EF9345 video display controller
driver.
- Ladislau Szilagyi has contributed an enhanced version of CP/M Cowgol
that leverages RomWBW memory banking.
- Ladislau Szilagyi has contributed an enhanced version of CP/M Cowgol
that leverages RomWBW memory banking.
- Les Bird has contributed support for the NABU w/ Option Board
- Les Bird has contributed support for the NABU w/ Option Board
Related Projects

View File

@@ -1,16 +1,21 @@
This is a RomWBW HBIOS adaptation of BBCBASIC v5.00. The
cursor and screen management assumes the use of an ANSI/VT-100 terminal
which is generally correct for RomWBW. Support for a hardware system
timer is also implemented. If your system does not have a hardware
timer, the TIME function will always return 0 and the timeout
This is a RomWBW HBIOS adaptation of BBCBASIC v5.00 by R.T.Russell.
This implementation was adapted from the source code found at
https://github.com/rtrussell/BBCZ80.
The cursor and screen management assumes the use of an ANSI/VT-100
terminal which is generally correct for RomWBW. Support for a hardware
system timer is also implemented. If your system does not have a
hardware timer, the TIME function will always return 0 and the timeout
parameter of the INKEY(n) function will not be observed (will never
timeout).
What follows is some basic information on BBCBASIC from the
distribution. Note that it starts with the v3.00 information and
later on provides information on the changes in v5.00.
later on provides information on the changes in v5.00. Complete
documentation for the BBC BASIC (Z80) is found online at
https://www.bbcbasic.co.uk/bbcbasic/mancpm/index.html.
-- WBW 1:15 PM 5/30/2024
-- WBW 4:21 PM 2/17/2025
@@ -23,55 +28,55 @@ later on provides information on the changes in v5.00.
1. INTRODUCTION
BBC BASIC (Z80) has been designed to be as compatible as possible with
Version 4 of the 6502 BBC BASIC resident in the BBC Micro Master series.
The language syntax is not always identical to that of the 6502 version,
BBC BASIC (Z80) has been designed to be as compatible as possible with
Version 4 of the 6502 BBC BASIC resident in the BBC Micro Master series.
The language syntax is not always identical to that of the 6502 version,
but in most cases the Z80 version is more tolerant.
BBC BASIC (Z80) is as machine independent as possible and, as supplied,
it will run on any CP/M 2.2 (or later) system using a Z80 processor
(checks are carried out to ensure that the processor is a Z80 and that
the version of CP/M is at least 2.2). It is minimally configured for an
BBC BASIC (Z80) is as machine independent as possible and, as supplied,
it will run on any CP/M 2.2 (or later) system using a Z80 processor
(checks are carried out to ensure that the processor is a Z80 and that
the version of CP/M is at least 2.2). It is minimally configured for an
ADM3a-compatible VDU.
Few CP/M systems offer colour graphics of the quality provided as
standard on the BBC Microcomputer, and no software can provide colour
high-resolution graphics from a monochrome character-orientated computer.
However, many CP/M system users are interested in the advanced program
structures available from BBC BASIC and, within the limitations of the
host computer, BBC BASIC (Z80) provides the programming structures and
Few CP/M systems offer colour graphics of the quality provided as
standard on the BBC Microcomputer, and no software can provide colour
high-resolution graphics from a monochrome character-orientated computer.
However, many CP/M system users are interested in the advanced program
structures available from BBC BASIC and, within the limitations of the
host computer, BBC BASIC (Z80) provides the programming structures and
the non-graphic commands and functions specified for BBC BASIC.
In order to make full use of the facilities available in BBC BASIC (Z80)
it is necessary to install a small patch to adapt it to the capabilities
of the host computer. The source code of the patch present in the
In order to make full use of the facilities available in BBC BASIC (Z80)
it is necessary to install a small patch to adapt it to the capabilities
of the host computer. The source code of the patch present in the
distribution version is supplied as BBCDIST.MAC.
This documentation should be read in conjunction with a standard BBC
BASIC manual. Only those features which differ from the standard Acorn
This documentation should be read in conjunction with a standard BBC
BASIC manual. Only those features which differ from the standard Acorn
versions are documented here.
2. MEMORY UTILISATION
BBC BASIC (Z80) requires about 16 Kbytes of code space, resulting in a
value of PAGE of about &3E00. The remainder of the user memory is
available for BASIC programs, variables (heap) and stack. Depending on
BBC BASIC (Z80) requires about 16 Kbytes of code space, resulting in a
value of PAGE of about &3E00. The remainder of the user memory is
available for BASIC programs, variables (heap) and stack. Depending on
the system configuration, HIMEM can have a value up to &FE00.
3. COMMANDS, STATEMENTS AND FUNCTIONS
The syntax of BASIC commands, statements and functions is in most cases
identical to that of the BBC Micro version (BASIC 4). The few
The syntax of BASIC commands, statements and functions is in most cases
identical to that of the BBC Micro version (BASIC 4). The few
differences are documented here:
ADVAL
This function is not implemented.
CALL
CALL sets up a table in RAM containing details of the parameters; the
processor's IX register is set to the address of this parameter table.
CALL sets up a table in RAM containing details of the parameters; the
processor's IX register is set to the address of this parameter table.
The other processor registers are initialised as follows:
A is initialised to the least significant byte of A%
@@ -92,7 +97,7 @@ later on provides information on the changes in v5.00.
128 Fixed string $A%
129 Movable string A$
On entry to the subroutine the parameter table contains the following
On entry to the subroutine the parameter table contains the following
values:
Number of parameters 1 byte (at IX)
@@ -103,29 +108,29 @@ later on provides information on the changes in v5.00.
Parameter type ) repeated as often as necessary
Parameter address )
Except in the case of a movable string (normal string variable), the
parameter address given is the absolute address at which the item is
stored. In the case of movable strings (type 129) it is the address of a
4-byte parameter block containing the current length, the maximum length
Except in the case of a movable string (normal string variable), the
parameter address given is the absolute address at which the item is
stored. In the case of movable strings (type 129) it is the address of a
4-byte parameter block containing the current length, the maximum length
and the start address of the string (LSB first) in that order.
Integer variables are stored in twos complement form with their least
Integer variables are stored in twos complement form with their least
significant byte first.
Fixed strings are stored as the characters of the string followed by a
Fixed strings are stored as the characters of the string followed by a
carriage return (&0D).
Floating point variables are stored in binary floating point format with
their least significant byte first; the fifth byte is the exponent. The
mantissa is stored as a binary fraction in sign and magnitude format.
Bit 7 of the most significant byte is the sign bit and, for the purposes
of calculating the magnitude of the number, this bit is assumed to be set
to one. The exponent is stored as an integer in excess 127 format (to
Floating point variables are stored in binary floating point format with
their least significant byte first; the fifth byte is the exponent. The
mantissa is stored as a binary fraction in sign and magnitude format.
Bit 7 of the most significant byte is the sign bit and, for the purposes
of calculating the magnitude of the number, this bit is assumed to be set
to one. The exponent is stored as an integer in excess 127 format (to
find the exponent subtract 127 from the value in the fifth byte).
If the exponent byte of a floating point number is zero, the number is an
integer stored in integer format in the mantissa bytes. Thus an integer
can be represented in two different ways in a real variable. For example
If the exponent byte of a floating point number is zero, the number is an
integer stored in integer format in the mantissa bytes. Thus an integer
can be represented in two different ways in a real variable. For example
the value +5 can be stored as:
05 00 00 00 00 Integer 5
@@ -138,15 +143,15 @@ later on provides information on the changes in v5.00.
This statement is not implemented.
EDIT
A command to edit or concatenate and edit the specified program line(s).
The specified lines (including their line numbers) are listed as a single
line. By changing only the line number you can use EDIT to duplicate a
A command to edit or concatenate and edit the specified program line(s).
The specified lines (including their line numbers) are listed as a single
line. By changing only the line number you can use EDIT to duplicate a
line.
EDIT 230
EDIT 200,230
The following control functions are active both in the EDIT mode and in
The following control functions are active both in the EDIT mode and in
the immediate entry mode (i.e. at the BASIC prompt):
Move the cursor one character position to the left
@@ -159,8 +164,8 @@ later on provides information on the changes in v5.00.
Delete all characters to the left of the cursor
Delete all characters from the cursor to the end of the line
The choice of which keys activate these functions is made when BBC BASIC
is configured for a particular system. The distribution version uses ^H,
The choice of which keys activate these functions is made when BBC BASIC
is configured for a particular system. The distribution version uses ^H,
^I, ^K, ^J, ^A, ^E, DEL (&7F), ^L and ^X.
To exit EDIT mode and replace the edited line, type RETURN (ENTER).
@@ -171,28 +176,28 @@ later on provides information on the changes in v5.00.
This statement is not implemented.
GET
This function waits for a character to be typed at the keyboard, and
This function waits for a character to be typed at the keyboard, and
returns the ASCII code.
GET can also be used to read data from a processor I/O port; full 16-bit
GET can also be used to read data from a processor I/O port; full 16-bit
port addressing is available:
N% = GET(X%) : REM input from port X%
INKEY
This function waits for a specified maximum number of centiseconds for a
character to be typed at the keyboard. If no character is typed in that
time, the value -1 is returned. In the distribution version the delay is
determined by a simple software timing loop, and may be very inaccurate.
The customisation patch allows this to be adjusted to suit the system in
This function waits for a specified maximum number of centiseconds for a
character to be typed at the keyboard. If no character is typed in that
time, the value -1 is returned. In the distribution version the delay is
determined by a simple software timing loop, and may be very inaccurate.
The customisation patch allows this to be adjusted to suit the system in
use.
INPUT#
The format of data files is different from that used by the BBC Micro, in
part to improve compatibility with standard CP/M files. Numeric values
are stored as five bytes in the format documented under CALL; if the
fifth byte is zero the value is an integer. Strings are stored as the
characters of the string (in the correct order!) followed by a carriage
The format of data files is different from that used by the BBC Micro, in
part to improve compatibility with standard CP/M files. Numeric values
are stored as five bytes in the format documented under CALL; if the
fifth byte is zero the value is an integer. Strings are stored as the
characters of the string (in the correct order!) followed by a carriage
return (&0D).
MODE
@@ -208,15 +213,15 @@ later on provides information on the changes in v5.00.
This function is not implemented.
PRINT#
The format of data files is different from that used by the BBC Micro, in
part to improve compatibility with standard CP/M files. Numeric values
are stored as five bytes in the format documented under CALL; if the
fifth byte is zero the value is an integer. Strings are stored as the
characters of the string (in the correct order!) followed by a carriage
The format of data files is different from that used by the BBC Micro, in
part to improve compatibility with standard CP/M files. Numeric values
are stored as five bytes in the format documented under CALL; if the
fifth byte is zero the value is an integer. Strings are stored as the
characters of the string (in the correct order!) followed by a carriage
return (&0D).
PUT
A statement to output data to a processor port. Full 16-bit addressing
A statement to output data to a processor port. Full 16-bit addressing
is available.
PUT A%,N% : REM Output N% to port A%
@@ -225,7 +230,7 @@ later on provides information on the changes in v5.00.
This statement is not implemented.
TIME
This pseudo-variable is not implemented in the distribution version, but
This pseudo-variable is not implemented in the distribution version, but
can be supported by means of the customisation patch. See BBCDIST.MAC.
USR
@@ -240,34 +245,34 @@ later on provides information on the changes in v5.00.
H is initialised to the least significant byte of H%
L is initialised to the least significant byte of L%
USR returns a 32-bit integer result composed of the processor's H, L, H'
USR returns a 32-bit integer result composed of the processor's H, L, H'
and L' registers, with H being the most significant.
4. RESIDENT Z80 ASSEMBLER
The in-line assembler is accessed in exactly the same way as the 6502
assembler in the BBC Micro version of BBC BASIC. That is, '[' enters
The in-line assembler is accessed in exactly the same way as the 6502
assembler in the BBC Micro version of BBC BASIC. That is, '[' enters
assembler mode and ']' exits assembler mode.
All standard Zilog mnemonics are accepted: ADD, ADC and SBC must be
followed by A or HL. For example, ADD A,C is accepted but ADD C is not.
However, the brackets around the port number in IN and OUT are optional.
Thus both OUT (5),A and OUT 5,A are accepted. The instruction IN F,(C)
All standard Zilog mnemonics are accepted: ADD, ADC and SBC must be
followed by A or HL. For example, ADD A,C is accepted but ADD C is not.
However, the brackets around the port number in IN and OUT are optional.
Thus both OUT (5),A and OUT 5,A are accepted. The instruction IN F,(C)
is not accepted, but the equivalent code is produced from IN (HL),C
The pseudo-ops DEFB, DEFW and DEFM are included. DEFM works like EQUS in
The pseudo-ops DEFB, DEFW and DEFM are included. DEFM works like EQUS in
the 6502 version.
5. OPERATING SYSTEM INTERFACE
The following resident Operating System ("star") commands are
implemented. They may be accessed directly (e.g. *BYE) or via the OSCLI
The following resident Operating System ("star") commands are
implemented. They may be accessed directly (e.g. *BYE) or via the OSCLI
statement (OSCLI "BYE").
Control characters, lower-case characters, DEL and quotation marks may be
incorporated in filenames by using the 'escape' character '|'. However,
Control characters, lower-case characters, DEL and quotation marks may be
incorporated in filenames by using the 'escape' character '|'. However,
there is no equivalent to the BBC Microcomputer's '|!' to set bit 7.
*BYE
@@ -278,7 +283,7 @@ later on provides information on the changes in v5.00.
*. [filespec]
*DIR [filespec]
List the files which match the (optional) ambiguous filespec. If the
List the files which match the (optional) ambiguous filespec. If the
filespec is omitted, all .BBC files are listed:
*DIR List all .BBC files on the disk
*DIR B:*.* List all files on disk B:
@@ -288,53 +293,53 @@ later on provides information on the changes in v5.00.
Select drive d as the default drive for subsequent disk operations.
*ERA filespec
Erase (delete) the specified disk file or files. The extension defaults
Erase (delete) the specified disk file or files. The extension defaults
to .BBC if omitted.
*ESC [ON|OFF]
*ESC OFF disables the abort action of the ESCape key; after *ESC OFF the
ESCape key simply returns the ASCII code ESC (27). *ESC ON, or *ESC,
*ESC OFF disables the abort action of the ESCape key; after *ESC OFF the
ESCape key simply returns the ASCII code ESC (27). *ESC ON, or *ESC,
restores the normal action of the ESCape key.
*EXEC filespec
Accept console input from the specified file instead of from the
Accept console input from the specified file instead of from the
keyboard. If the extension is omitted, .BBC is assumed.
*LOAD filespec aaaa
Loads the specified file into memory at address aaaa. The load address
Loads the specified file into memory at address aaaa. The load address
must be specified. If the extension is omitted, .BBC is assumed.
*OPT [n]
Select the destination for console output characters. The value n is in
Select the destination for console output characters. The value n is in
the range 0 to 2, as follows:
0 Send characters to the console output
1 Send characters to the auxiliary output
2 Send characters to the printer (list) output
*REN newfile=oldfile
*RENAME newfile=oldfile
Renames 'oldfile' as 'newfile'. If the extension is omitted, .BBC is
Renames 'oldfile' as 'newfile'. If the extension is omitted, .BBC is
assumed.
*RESET
Rest the disk system (CP/M function 13). This command does not close any
files nor does it perform any other housekeeping function. You should
Rest the disk system (CP/M function 13). This command does not close any
files nor does it perform any other housekeeping function. You should
use *RESET after you have changed a disk.
*SAVE filespec aaaa bbbb
*SAVE filespec aaaa +llll
This command saves a specified range of memory to disk. The address range
is specified either as start (aaaa) and end+1 (bbbb) or as start (aaaa)
This command saves a specified range of memory to disk. The address range
is specified either as start (aaaa) and end+1 (bbbb) or as start (aaaa)
and length (llll). If the extension is omitted, .BBC is assumed.
*SPOOL [filespec]
Copy all subsequent console output to the specified file. If the filename
is omitted, any current spool file is closed and spooling is terminated.
Copy all subsequent console output to the specified file. If the filename
is omitted, any current spool file is closed and spooling is terminated.
If the extension is omitted, .BBC is assumed.
*TYPE filespec
Type the specified file to the screen. If the extension is omitted, .BBC
Type the specified file to the screen. If the extension is omitted, .BBC
is assumed.
*| comment
@@ -352,7 +357,7 @@ later on provides information on the changes in v5.00.
Trappable - BASIC:
1 Out of range 24 Exp range
2 25
2 25
3 26 No such variable
4 Mistake 27 Missing )
5 Missing , 28 Bad HEX
@@ -383,9 +388,9 @@ later on provides information on the changes in v5.00.
198 Disk full 254 Bad command
200 Close error 255 CP/M error
204 Bad name

New features in BBC BASIC (Z80) version 5.00, May 2024:
New features in BBC BASIC (Z80) version 5.00, January 2025:
1. BASIC V statements
@@ -394,7 +399,7 @@ New features in BBC BASIC (Z80) version 5.00, May 2024:
1.3 CASE...WHEN...OTHERWISE...ENDCASE
1.4 LOCAL DATA / RESTORE DATA
1.5 ON ERROR LOCAL / RESTORE ERROR
1.6 DIM var LOCAL size
1.6 DIM var LOCAL size
1.7 ERROR err, message$
1.8 RESTORE +n
1.9 SWAP var1,var2
@@ -408,10 +413,10 @@ New features in BBC BASIC (Z80) version 5.00, May 2024:
2.3 REPORT$
2.4 Binary constants
2.5 LEFT$ & RIGHT$ with last parameter omitted
2.6 MOD(array)
2.7 SUM(array)
2.8 SUMLEN(array)
2.9 GET$#file
2.6 MOD(array())
2.7 SUM(array())
2.8 SUMLEN(array())
2.9 GET$#file
3. BASIC V whole array operations
@@ -423,9 +428,12 @@ New features in BBC BASIC (Z80) version 5.00, May 2024:
3.6 Array initialisation lists
3.7 Array compound assignment (+= etc.)
3.8 Make a whole array LOCAL
3.9 DIM a LOCAL array (on the stack) +
3.9 DIM a LOCAL array (on the stack) +
* String array expressions are not currently supported, instead of using
a$() = b$() + c$() use a$() = b$() : a$() += c$()
The use of EVAL with whole-array expressions is not currently supported.
* String array expressions A$() = B$() + C$() are not currently supported.
+ LOCAL string arrays should be initialised to their maximum needed length
to eliminate the risk of a memory leak each time the PROC/FN is called:
LOCAL a$() : DIM a$(size%) : a$() = STRING$(max%, "a") : a$() = ""
@@ -434,22 +442,27 @@ New features in BBC BASIC (Z80) version 5.00, May 2024:
4.1 Bit-shifts <<, >>, >>>
4.2 Floating-point indirection (|)
4.3 RETURNed parameters from FN/PROC
4.4 Compound assignment (+=, -=, *=, /= etc.)
4.5 Assigning to a sub-string: LEFT$()=, MID$()= , RIGHT$()=
4.6 Hooks for CIRCLE,ELLIPSE,FILL,LINE,MOUSE,ORIGIN,RECTANGLE,TINT,SYS,WAIT
4.7 Hooks for WIDTH function, TINT function, MODE function
4.3 Additional VDU delimiter '|'
4.4 RETURNed parameters from FN/PROC
4.5 Compound assignment (+=, -=, *=, /= etc.)
4.6 Assigning to a sub-string: LEFT$()=, MID$()= , RIGHT$()=
4.7 Hooks for CIRCLE, ELLIPSE, FILL, LINE, ORIGIN, RECTANGLE (graphics)
4.8 Hooks for MOUSE, OFF, ON, SYS, TINT, WAIT (statements)
4.9 Hooks for MODE function, TINT function, WIDTH function
5. Extensions to Acorn's BASIC V, compatible with BB4W, BBCSDL and BBCTTY
5.1 EXIT REPEAT / WHILE / FOR [var]
5.2 Address-of operator ^
5.3 Byte variables and arrays (& suffix)
5.2 Address-of operator (^)
5.3 Byte (unsigned 8-bit) variables and arrays (& suffix)
5.4 'BY len' and 'TO term' qualifiers to GET$#file
5.5 ELSE IF <condition> THEN; (trailing semicolon)
5.6 == synonymous with = in comparisons
5.7 DIM a global array inside a FN/PROC (use RETURN)
5.8 DIM var LOCAL -1 returns the stack pointer, even outside a FN/PROC
5.9 RESTORE LOCAL restores local variables without exiting the FN/PROC
Note: The token for PUT has changed from &CE in version 3 to &0E in version 5.
If this token is present in existing programs it will list as ENDWHILE rather
than PUT, and the programs will need to be modified to restore functionality.
than PUT, and the programs will need to be modified to restore functionality.


File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,64 +1,68 @@
NAME ('HOOK')
;
GLOBAL CLG
GLOBAL COLOUR
GLOBAL DRAW
GLOBAL ENVEL
GLOBAL GCOL
GLOBAL MODE
GLOBAL MOVE
GLOBAL PLOT
GLOBAL SOUND
GLOBAL PUTIMS
GLOBAL CIRCLE
GLOBAL ELLIPSE
GLOBAL FILL
GLOBAL MOUSE
GLOBAL ORIGIN
GLOBAL RECTAN
GLOBAL LINE
GLOBAL TINT
GLOBAL WAIT
GLOBAL SYS
;
GLOBAL ADVAL
GLOBAL POINT
GLOBAL GETIMS
GLOBAL TINTFN
GLOBAL MODEFN
GLOBAL WIDFN
;
EXTRN EXTERR
;
CLG:
COLOUR:
DRAW:
ENVEL:
GCOL:
MODE:
MOVE:
PLOT:
SOUND:
ADVAL:
POINT:
GETIMS:
PUTIMS:
CIRCLE:
ELLIPSE:
FILL:
MOUSE:
ORIGIN:
RECTAN:
LINE:
TINT:
TINTFN:
MODEFN:
WIDFN:
WAIT:
SYS:
XOR A
CALL EXTERR
DEFM 'Sorry'
DEFB 0
;
END
NAME ('HOOK')
;
GLOBAL CLG
GLOBAL COLOUR
GLOBAL DRAW
GLOBAL ENVEL
GLOBAL GCOL
GLOBAL MODE
GLOBAL MOVE
GLOBAL PLOT
GLOBAL SOUND
GLOBAL PUTIMS
GLOBAL CIRCLE
GLOBAL ELLIPS
GLOBAL FILL
GLOBAL MOUSE
GLOBAL ORIGIN
GLOBAL RECTAN
GLOBAL LINE
GLOBAL TINT
GLOBAL WAIT
GLOBAL SYS
GLOBAL CSRON
GLOBAL CSROFF
;
GLOBAL ADVAL
GLOBAL POINT
GLOBAL GETIMS
GLOBAL TINTFN
GLOBAL MODEFN
GLOBAL WIDFN
;
EXTRN EXTERR
;
CLG:
COLOUR:
DRAW:
ENVEL:
GCOL:
MODE:
MOVE:
PLOT:
SOUND:
ADVAL:
POINT:
GETIMS:
PUTIMS:
CIRCLE:
ELLIPS:
FILL:
MOUSE:
ORIGIN:
RECTAN:
LINE:
TINT:
TINTFN:
MODEFN:
WIDFN:
WAIT:
SYS:
CSRON:
CSROFF:
XOR A
CALL EXTERR
DEFM 'Sorry'
DEFB 0
;
END

View File

@@ -0,0 +1,19 @@
Copyright (c) 2024, Richard T. Russell, http://www.rtrussell.co.uk/
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -29,6 +29,7 @@ call :build Survey || exit /b
call :build HTalk || exit /b
call :build BBCBASIC || exit /b
call :build copysl || exit /b
call :build ZDE || exit /b
goto :eof

View File

@@ -24,6 +24,7 @@ call :clean Survey || exit /b
call :clean HTalk || exit /b
call :clean BBCBASIC || exit /b
call :clean copysl || exit /b
call :clean ZDE || exit /b
goto :eof

View File

@@ -1,5 +1,5 @@
SUBDIRS = HTalk XM FDU FAT Tune Test ZMP ZMD Dev VGM cpuspd reboot Survey BBCBASIC copysl \
sysgen syscopy assign format talk mode rtc timer
sysgen syscopy assign format talk mode rtc timer ZDE
TOOLS =../../Tools
include $(TOOLS)/Makefile.inc

View File

@@ -146,6 +146,13 @@ MINIT_UB1:
LD A,E ; Put in A
LD (CPUSPD),A ; Save it
;
LD A,(UNIT) ; get current unit specified
CP 0FFH ; check for undefined
JR NZ,MINIT_UB2 ; if already specified, go ahead
XOR A ; default is unit 0
LD (UNIT),A ; and save it
;
MINIT_UB2:
JP UB_INIT ; UNA BIOS init
;
MINIT_RET:
@@ -535,8 +542,10 @@ UB_SENDR:
PUSH BC
PUSH DE
PUSH HL
LD BC,0012H ; unit 0, func 12h (write char)
LD E,A ; character to E
LD A,(UNIT) ; unit
LD B,A ; to B
LD C,12H ; func 12h (write char)
RST 08
POP HL
POP DE
@@ -568,7 +577,9 @@ UB_MDIN:
PUSH BC
PUSH DE
PUSH HL
LD BC,0011H ; unit 0, func 12h (write char)
LD A,(UNIT) ; unit
LD B,A ; to B
LD C,11H ; func 11h (read char)
RST 08
LD A,E ; byte received to A
POP HL
@@ -586,12 +597,14 @@ UB_RCVRDY:
PUSH BC
PUSH DE
PUSH HL
LD BC,0013H ; unit 0, func 13h (input stat)
LD A,(UNIT) ; unit
LD B,A ; to B
LD C,13H ; func 13h (input stat)
RST 08
XOR A ; zero accum ; 4
CP E ; CF means not zero ; 4
CCF ; CF means zero ; 4
RLA ; ZF means not zero ; 4
LD A,E ; move char count to accum
SUB 1 ; CF set IFF zero
RL A ; CF to bit 0 of A
AND 01H ; set Z flag as needed
LD A,0 ; report no line errors
POP HL
POP DE
@@ -606,12 +619,14 @@ UB_SNDRDY:
PUSH BC
PUSH DE
PUSH HL
LD BC,0014H ; unit 0, func 14h (output stat)
LD A,(UNIT) ; unit
LD B,A ; to B
LD C,14H ; func 14h (output stat)
RST 08
XOR A ; zero accum ; 4
CP E ; CF means not zero ; 4
CCF ; CF means zero ; 4
RLA ; ZF means not zero ; 4
LD A,E ; char avail to send to accum
SUB 1 ; CF set IFF zero
RL A ; CF to bit 0 of A
AND 01H ; set Z flag as needed
POP HL
POP DE
POP BC

35
Source/Apps/ZDE/Build.cmd Normal file
View File

@@ -0,0 +1,35 @@
@echo off
setlocal
set TOOLS=../../../Tools
set PATH=%TOOLS%\tasm32;%TOOLS%\zxcc;%PATH%
set TASMTABS=%TOOLS%\tasm32
set CPMDIR80=%TOOLS%/cpm/
:: These variations of ZDE are built here as reference copies. They
:: are not copied anywhere else during the build.
:: The resulting .COM files are manually
:: copied to /Source/Images/d_ws/u1 as needed.
zxcc ZMAC -ZDE16 -/P -/H || exit /b
zxcc MLOAD25 ZDE16 || exit /b
copy /Y zde16.com ..\..\..\Binary\Apps\ZDE\ || exit /b
zxcc ZMAC ZDE16A.PAT -/H || exit /b
zxcc MLOAD25 ZDE16A=ZDE16.COM,ZDE16A.HEX || exit /b
copy /Y zde16a.com ..\..\..\Binary\Apps\ZDE\ || exit /b
zxcc ZMAC -ZDE17 -/P -/H || exit /b
zxcc MLOAD25 ZDE17 || exit /b
copy /Y zde17.com ..\..\..\Binary\Apps\ZDE\ || exit /b
zxcc ZMAC -ZDE18 -/P -/H || exit /b
zxcc MLOAD25 ZDE18 || exit /b
copy /Y zde18.com ..\..\..\Binary\Apps\ZDE\ || exit /b
zxcc ZMAC -ZDE19 -/P -/H || exit /b
zxcc MLOAD25 ZDE19 || exit /b
copy /Y zde19.com ..\..\..\Binary\Apps\ZDE\ || exit /b

View File

@@ -0,0 +1,9 @@
@echo off
setlocal
if exist *.prn del *.prn
if exist *.err del *.err
if exist *.rel del *.rel
if exist *.com del *.com
if exist *.hex del *.hex
if exist *.sym del *.sym

15
Source/Apps/ZDE/Makefile Normal file
View File

@@ -0,0 +1,15 @@
# These variations of ZDE are built here as reference copies. They
# are not copied anywhere else during the build.
# The resulting .COM files are manually
# copied to /Source/Images/d_ws/u1 as needed.
OBJECTS = zde16.com zde16a.com zde17.com zde18.com zde19.com
DEST = ../../../Binary/Apps/ZDE
TOOLS = ../../../Tools
OTHERS = *.hex
include $(TOOLS)/Makefile.inc
zde16a.com: zde16.com zde16a.pat
$(ZXCC) ZMAC zde16a.pat -/H
$(ZXCC) MLOAD25 zde16a=zde16.com,zde16a.hex || exit /b

38
Source/Apps/ZDE/ReadMe.md Normal file
View File

@@ -0,0 +1,38 @@
# ZDE 1.6 (Z-System Display Editor) reconstituted source - MECPARTS
11/19/2020
Using the source code of [VDE 2.67]
(http://www.classiccmp.org/cpmarchives/cpm/Software/WalnutCD/enterprs/cpm/utils/s/vde267sc.lbr)
as a guide, I've reconstituted the source code for [ZDE 1.6](http://www.classiccmp.org/cpmarchives/cpm/Software/WalnutCD/cpm/editor/zde16.lbr).
The resulting source code is available from the GitHub repository
https://github.com/mecparts/zde.
The source has been assembled with:
* Al Hawley's ZMAC: assemble as is.
* MicroSoft's M80: rename to ZDE16.MAC, un-comment the first two lines
and assemble. Use RELHEX to create ZDE16.HEX.
* ZASM (Cromemco's ASMB): Rename to ZDE16.Z80 and assemble. Use RELHEX
to create ZDE16.HEX.
Use MLOAD to create ZDE16.COM.
There are still a couple of routines new to ZDE that I haven't figured
out (yet). But most of them have been sussed out.
## ZDE 1.7 - MECPARTS 11/24/2020
I've fixed the "doesn't preserve timestamps for files larger than a
single extent under ZSDOS" bug that was present in v1.6. The existing
ZDENST16.COM program will work with the 1.7 to set the program up for
your terminal and printer.
## ZDE 1.8 - Lars Nelson 12/3/2022
Added routine to save create time stamp under CP/M Plus since
CP/M Plus, unlike ZSDOS, has no native ability to set time stamps.
## ZDE 1.9 - Peter Onion 03/27/2025
- Added support for ANSI PgUp, PgDn, Home, & End.
- Support ANSI F1 key for menu/error escape.

8111
Source/Apps/ZDE/zde16.z80 Normal file

File diff suppressed because it is too large Load Diff

102
Source/Apps/ZDE/zde16a.pat Normal file
View File

@@ -0,0 +1,102 @@
; This patch file modifies the officially-distributed .COM file
; for ZDE Ver 1.6 (copyright by Carson Wilson) to:
; - Correct a bug which did not preserve create times when
; editing files > 1 extent.
; - Use an apparently 'dead' byte in the configuration area as
; a configuration flag to allow disabling the 'Auto-Indent'
; feature which was always 'on' in ZDE1.6.
;
; With the second change, you may configure the 'Auto-Indent'
; feature to be active (as distributed) or disabled (as this patch
; is configured) by altering the DB at label 'AIDflt' in the
; second part of this patch file below.
;
; Assemble this file to a .HEX file (example uses ZMAC) as:
;
; ZMAC ZDE16A.PAT /H
;
; then overlay the resulting ZDE16.HEX onto ZDE16.COM with MYLOAD
; (or equivalent) as:
;
; MYLOAD ZDE.COM=ZDE.COM,ZDE16.HEX
;
; The resulting ZDE.COM will be identified as 'ZDE 1.6a' in the
; text identification string near the beginning of the .COM file.
;
; Harold F. Bower, 18 July 2001.
;
; CP/M Standard Equates
;
BDOS EQU 0005H
FCB EQU 005CH
DMA EQU 0080H
TPA EQU 0100H
;
SDMA EQU 26 ; CP/M Function to set DMA Address
;
; Needed locations within ZDE 1.6
;
Fill EQU TPA+0F8BH ; For Date Patch
TimBuf EQU TPA+3B3FH ; " " "
;
VTFlg EQU TPA+3ADAH ; For Auto-Ins Patch
HCRFlg EQU TPA+3AE3H ; " " " "
LfMarg EQU TPA+3AFDH ; " " " "
;
; ----------- Begin Patch File -----------
;
; --- Fix Create Time Stamp Preservation Error ---
ORG TPA+0029H
; was:
DB 'a, (C)' ; DB ', Copr.'
ORG TPA+2461H
; was:
LD (FCB+13),A ; CALL ClUsrF
;
ORG TPA+2F10H
; was:
LD B,4 ; CALL ClUsrF
CALL ClUsrF ; LD DE,TimBuf
LD DE,TimBuf ; LD C,SDMA
CALL SetDMA ; CALL BDOS
;
ORG TPA+30AAH
; was:
LD DE,DMA ; LD C,SDMA
SetDMA: LD C,SDMA ; LD DE,DMA
;
ORG TPA+30B4H
; was:
ClUsrF: XOR A ; XOR A
EX DE,HL ; LD (FCB+13),A
JP Fill ; RET
;
; --- Usurp Config Flag for Auto-Insert use, sense on startup ---
;
ORG TPA+0057H
; was: 0FFH
AIDflt: DB 00H ; Set Desired default (0=Off, FF=On)
;
ORG TPA+262AH
; was:
LD (LfMarg),HL ; LD HL,0101H
XOR A ; LD (LfMarg),HL
LD (VTFlg),A ; XOR A
LD (HCRFlg),A ; LD (VTFlg),A
NOP ; LD (HCRFlg),A
LD A,(AIDflt) ; DEC A
;
ORG TPA+2711H
; was:
NOP ; LD A,(0157H) {Unknown Use}
NOP ; OR A
NOP ; JP Z,Error2
NOP
NOP
NOP
NOP
;
;------------ End of Patch File ------------
END


8111
Source/Apps/ZDE/zde17.z80 Normal file

File diff suppressed because it is too large Load Diff

8567
Source/Apps/ZDE/zde18.z80 Normal file

File diff suppressed because it is too large Load Diff

8598
Source/Apps/ZDE/zde19.z80 Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -180,6 +180,14 @@ MINIT_UB1:
INC E ; Fix up for value truncation
LD A,E ; Put in A
LD (CPUSPD),A ; Save it
;
LD A,(UNIT) ; get current unit specified
CP 0FFH ; check for undefined
JR NZ,MINIT_UB2 ; if already specified, go ahead
XOR A ; default is unit 0
LD (UNIT),A ; and save it
;
MINIT_UB2:
;
JP UB_INIT ; UNA BIOS init
;
@@ -578,8 +586,10 @@ UB_SENDR:
PUSH BC
PUSH DE
PUSH HL
LD BC,0012H ; unit 0, func 12h (write char)
LD E,A ; character to E
LD A,(UNIT) ; unit
LD B,A ; to B
LD C,12H ; func 12h (write char)
RST 08
POP HL
POP DE
@@ -611,7 +621,9 @@ UB_MDIN:
PUSH BC
PUSH DE
PUSH HL
LD BC,0011H ; unit 0, func 12h (write char)
LD A,(UNIT) ; unit
LD B,A ; to B
LD C,11H ; func 11h (read char)
RST 08
LD A,E ; byte received to A
POP HL
@@ -629,12 +641,14 @@ UB_RCVRDY:
PUSH BC
PUSH DE
PUSH HL
LD BC,0013H ; unit 0, func 13h (input stat)
LD A,(UNIT) ; unit
LD B,A ; to B
LD C,13H ; func 13h (input stat)
RST 08
XOR A ; zero accum ; 4
CP E ; CF means not zero ; 4
CCF ; CF means zero ; 4
RLA ; ZF means not zero ; 4
LD A,E ; move char count to accum
SUB 1 ; CF set IFF zero
RL A ; CF to bit 0 of A
AND 01H ; set Z flag as needed
LD A,0 ; report no line errors
POP HL
POP DE
@@ -649,12 +663,14 @@ UB_SNDRDY:
PUSH BC
PUSH DE
PUSH HL
LD BC,0014H ; unit 0, func 14h (output stat)
LD A,(UNIT) ; unit
LD B,A ; to B
LD C,14H ; func 14h (output stat)
RST 08
XOR A ; zero accum ; 4
CP E ; CF means not zero ; 4
CCF ; CF means zero ; 4
RLA ; ZF means not zero ; 4
LD A,E ; char avail to send to accum
SUB 1 ; CF set IFF zero
RL A ; CF to bit 0 of A
AND 01H ; set Z flag as needed
POP HL
POP DE
POP BC

View File

@@ -1,8 +1,11 @@
@echo off
setlocal
:: copysl.com is currently distributed as a binary application, so
:: it is not built here.
set TOOLS=../../../Tools
set PATH=%TOOLS%\tasm32;%PATH%
set TASMTABS=%TOOLS%\tasm32
tasm -t80 -g3 -fFF copysl.asm copysl.com copysl.lst || exit /b
copy /Y copysl.com ..\..\..\Binary\Apps\ || exit /b
copy /Y copysl.doc ..\..\..\Binary\Apps\ || exit /b

View File

@@ -1,5 +1,6 @@
@echo off
setlocal
:: copysl.com is currently distributed as a binary application, so
:: we do not delete the .COM file.
if exist *.com del *.com
if exist *.lst del *.lst
if exist *.bin del *.bin

View File

@@ -1,7 +1,9 @@
OBJECTS = copysl.com
NODELETE = $(OBJECTS)
DOCS = copysl.doc
DEST = ../../../Binary/Apps
DOCDEST = ../../../Binary/Apps
TOOLS=../../../Tools
include $(TOOLS)/Makefile.inc
TOOLS =../../../Tools
USETASM=1
include $(TOOLS)/Makefile.inc

View File

@@ -0,0 +1,16 @@
;
bdos .EQU 5
;
; Force BDOS to reset (logout) all drives
;
drvrst:
ld c,$0D ; BDOS Reset Disk function
call bdos ; do it
;
ld c,$25 ; BDOS Reset Multiple Drives
ld de,$FFFF ; all drives
call bdos ; do it
;
xor a ; signal success
ret
;

328
Source/Apps/copysl/cio.asm Normal file
View File

@@ -0,0 +1,328 @@
BDOS .EQU 5
; bdos commands
CONIN .EQU 1
CONOUT .EQU 2
DIRCONIO .EQU 6
; TODO for more routines see assign.asm
; ===============
; INPUT
; Console Input
getchr:
PUSH BC
PUSH DE
PUSH HL
LD C,CONIN
CALL BDOS
POP HL
POP DE
POP BC
RET
; direct console io
; BDOS 6 - FF FE FD - commands
conread:
RET
constatus:
RET
coninput:
RET
; =======================================
; STANDARD OUTPUT
;
; Print character in A without destroying any registers
;
prtchr:
; PUSH AF
PUSH HL ; We must preserve HL, as the BDOS call sets it
PUSH BC
PUSH DE
LD C, CONOUT
LD E, A
CALL BDOS
POP DE
POP BC
POP HL
; POP AF
RET
;
prtdot:
push af
ld a, '.'
call prtchr
pop af
ret
;
; Print a zero terminated string at (HL) without destroying any registers
;
prtstr:
PUSH AF
PUSH BC
push de
prtstr1:
ld a,(hl)
or 0
jr z,prtstr2
ld c, CONOUT
ld e,a
push hl
call BDOS
pop hl
inc hl
jr prtstr1
prtstr2:
pop de
pop bc
pop af
ret
;
; Print the value in A in hex without destroying any registers
;
prthex:
push af ; save AF
push de ; save DE
call hexascii ; convert value in A to hex chars in DE
ld a,d ; get the high order hex char
call prtchr ; print it
ld a,e ; get the low order hex char
call prtchr ; print it
pop de ; restore DE
pop af ; restore AF
ret ; done
;
; print the hex word value in bc
;
prthexword:
push af
ld a,b
call prthex
ld a,c
call prthex
pop af
ret
;
; Convert binary value in A to ascii hex characters in DE
;
hexascii:
ld d,a ; save A in D
call hexconv ; convert low nibble of A to hex
ld e,a ; save it in E
ld a,d ; get original value back
rlca ; rotate high order nibble to low bits
rlca
rlca
rlca
call hexconv ; convert nibble
ld d,a ; save it in D
ret ; done
;
; Convert low nibble of A to ascii hex
;
hexconv:
and 0Fh ; low nibble only
add a,90h
daa
adc a,40h
daa
ret
;
; Print the decimal value of A, with leading zero suppression
;
prtdec:
push hl
ld h,0
ld l,a
call prtdecword ; print it
pop hl
ret
;
; Print the Decimal value (word) in HL
;
prtdecword:
push af
push bc
push de
push hl
call prtdec0
pop hl
pop de
pop bc
pop af
ret
;
prtdec0:
ld e,'0'
ld bc,-10000
call prtdec1
ld bc,-1000
call prtdec1
ld bc,-100
call prtdec1
ld c,-10
call prtdec1
ld e,0
ld c,-1
prtdec1:
ld a,'0' - 1
prtdec2:
inc a
add hl,bc
jr c,prtdec2
sbc hl,bc
cp e
ret z
ld e,0
call prtchr
ret
;
; Print a byte buffer in hex pointed to by DE
; Register A has size of buffer
;
prthexbuf:
or a
ret z ; empty buffer
prthexbuf1:
ld a,' '
call prtchr
ld a,(de)
call prthex
inc de
djnz prthexbuf1
ret
;
; Start a new Line
;
prtcrlf2:
call prtcrlf
prtcrlf:
push hl
ld hl, prtcrlf_msg
call prtstr
pop hl
ret
prtcrlf_msg:
.DB 13,10,0
; =================================
; following is from dmamon util.asm
;
; IMMEDIATE PRINT
; =================================
;
; PRINT A CHARACTER REFERENCED BY POINTER AT TOP OF STACK
; USAGE:
; CALL IPRTCHR
; .DB 'X'
;
iprtchr:
EX (SP),HL
PUSH AF
LD A,(HL)
CALL prtchr
POP AF
INC HL
EX (SP),HL
RET
; Print a string referenced by pointer at top of stack
; Usage
; call iprtstr
; .DB "text", 0
;
iprtstr:
EX (SP),HL
CALL prtstr
INC HL
EX (SP),HL
RET
;
; ===========================================================
;
; Following is for INPUT, used to process command line args
;
; ===========================================================
;
; Skip whitespace at buffer adr in DE, returns with first
; non-whitespace character in A.
;
skipws:
ld a,(hl) ; get next char
or a ; check for eol
ret z ; done if so
cp ' ' ; blank?
ret nz ; nope, done
inc hl ; bump buffer pointer
jr skipws ; and loop
;
; Uppercase character in A
;
upcase:
cp 'a' ; below 'a'?
ret c ; if so, nothing to do
cp 'z'+1 ; above 'z'?
ret nc ; if so, nothing to do
and ~020h ; convert character to lower
ret ; done
;
; Get numeric chars at HL and convert to number returned in A
; Carry flag set on overflow
; C is used as a working register
;
getnum:
ld c,0 ; C is working register
getnum1:
ld a,(hl) ; get the active char
cp '0' ; compare to ascii '0'
jr c,getnum2 ; abort if below
cp '9' + 1 ; compare to ascii '9'
jr nc,getnum2 ; abort if above
;
ld a,c ; get working value to A
rlca ; multiply by 10
ret c ; overflow, return with carry set
rlca ; ...
ret c ; overflow, return with carry set
add a,c ; ...
ret c ; overflow, return with carry set
rlca ; ...
ret c ; overflow, return with carry set
ld c,a ; back to C
ld a,(hl) ; get new digit
sub '0' ; make binary
add a,c ; add in working value
ret c ; overflow, return with carry set
ld c,a ; back to C
;
inc hl ; bump to next char
jr getnum1 ; loop
;
getnum2:
ld a,c ; return result in A
or a ; with flags set, CF is cleared
ret
;
; Is character in A numeric? NZ if not
;
isnum:
cp '0' ; compare to ascii '0'
jr c,isnum1 ; abort if below
cp '9' + 1 ; compare to ascii '9'
jr nc,isnum1 ; abort if above
cp a ; set Z
ret
isnum1:
or 0FFh ; set NZ
ret ; and done

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@@ -1,6 +1,6 @@
==========================================================================
CopySlice Utility v0.2 for RomWbW computers
written by Mark Pruden (Sept 2024)
CopySlice Utility v0.3 for RomWbW computers
written by Mark Pruden (March 2025)
==========================================================================
Purpose:
@@ -12,37 +12,37 @@ from one disk slice to another slice
Background
----------
This tool is only supported by RomWBW HBIOS, it uses HDIOS for all its
disk IO. UNA UBIOS is not supported by this tool.
This tool is only supported by RomWBW HBIOS, it uses HDIOS for all its
disk IO. UNA UBIOS is not supported by this tool.
This tool is running on CP/M 2.2 or 3.0 and has access to full 64kb of
RAM, with a minimum of 48kb TPA
This tool only works with hard disk devices, other media types like
floppy, are not supported at this time. This tool works across different
This tool only works with hard disk devices, other media types like
floppy, are not supported at this time. This tool works across different
hard disk device types, even of different physical type
Both hd1k and hd512 are fully supported, however copying from one layout
Both hd1k and hd512 are fully supported, however copying from one layout
type to the other is not supported.
During operation data is copied in a single read/write pass, data is not
During operation data is copied in a single read/write pass, data is not
verified by default. If there is a write error, it will be reported, and
operation will stop.
General Usage
-------------
This tool operates at the disk level via RomWBW, thus all disk identifiers
This tool operates at the disk level via RomWBW, thus all disk identifiers
are in the RomWBW <disk>.<unit> format
The syntax (similar to copy) for the command is:
COPYSL <destunit>[.<slice>]=<srcunit>[.<slice>] [/options]
E.g.
COPYSL 3.3=2.10 /U
Means copy from slice 10 on disk 2, onto disk 3 slice 3. This is in
Means copy from slice 10 on disk 2, onto disk 3 slice 3. This is in
unattended mode, so you will not be asked to confirm the copy operation.
Options
@@ -54,39 +54,40 @@ V - Verify. Does an additional read and verify after write.
Description
-----------
When run COPYSL will perform command line argument validation and display
When run COPYSL will perform command line argument validation and display
an error if they are illegal. Also any disk IO errors will cause COPYSL
to exit.
When specifying slice number(s) a check is made that the slice number is
valid, i.e. not too large that it would extend past the end of the
When specifying slice number(s) a check is made that the slice number is
valid, i.e. not too large that it would extend past the end of the
partition (hd1k), or the end of the media (hd512). For hd512 a check is
also performed to ensure that the slice would not extend into the first
also performed to ensure that the slice would not extend into the first
defined partition.
The copy operation will be faster if the source disk has been formatted
with the CP/M file system, since during copy the CP/M directory is scanned,
and unused blocks are not copied.
with the CP/M file system, since during copy the CP/M directory is scanned,
and unused blocks are not copied.
If a filesystem is not found, (or the /F option is chosen) all data is
If a filesystem is not found, (or the /F option is chosen) all data is
copied.
Verification (if option chosen) will do an aditional read (after write)
and compare the data read matches what was written. This compare is only
on every 32'nd byte. This is done for efficiency.
on every 32'nd byte. This is done for efficiency.
During copy dots "." will be displayed to indicate progress of the copy.
Each "." represents 16 kBytes of data. Each line of "." 's is 1 mBytes.
Testing
-------
This tool has been writen and tested on a SC126 computer. Testing been on both
This tool has been writen and tested on a SC126 computer. Testing been on both
SD and CF media types, and with both hd1k and hd512 formats
History
-------
* v 0.1 Initial Release
* v 0.2 Added the /v command option to read and verify after write
* v 0.3 Refresh CP/M disk buffers after completion
Future
------
@@ -95,4 +96,3 @@ Future
This would be at the cost of performance
* ability to abort once the copy has started <ctrl><c>


110
Source/Apps/copysl/crc.asm Normal file
View File

@@ -0,0 +1,110 @@
;
; Simple Block Compare for Comparison purposes
; Both HL and DL contain Block pointers to compare
; HL MUST start on an even block e.g. 8000h
; RET NZ - Failure, Z if no issue
;
_cmp20block
; inc de ; uncommnet to test crc fail!
ld bc, 20h ; 10t Size of Pointer Increment
_cmp20block1:
ld a, (de) ; 7t Do The comparison itself
cp (hl) ; 7t
JR NZ, _cmp20block2 ; 7t / 12t = 21t
add hl, bc ; 11t Add the Increment to both pointers
ex de, hl ; 4t
add hl, bc ; 11t
ex de, hl ; 4t = 30t
ld a, h ; 4t High order byte on Even Boundary
bit 4, a ; 8t has bit 4 been set then exceeded 1000h (4k boundary)
JR Z, _cmp20block1 ; 12t / 7t = 24t
xor a ; 4t
RET ; 10t Return Success
_cmp20block2:
scf ; signal CARRY FLAG Also
RET ; This is the error
; clock cycles for above
; add 40h -> 64 (loop) * 73t =>> 4,672 - 1.56%
; add 20h ->128 (loop) * 73t =>> 9,344 - 3.13% <= WENT WITH THIS
; add 10h ->256 (loop) * 73t =>> 18,688 - 6.25%
; accuracy = 88/4096 => 2.1%
; =====================================================================
; From : https://tomdalby.com/other/crc.html
; And : https://map.grauw.nl/sources/external/z80bits.html#6.1
; =====================================================================
;
; =====================================================================
; input - hl=start of memory to check, de=length of memory to check
; returns - a=result crc
; 20b
; =====================================================================
; THE COMMNETED LINES NEED TO BE UNCOMMENTED
_crc8b:
xor a ; 4t - initial value so first byte can be XORed in (CCITT)
; ld c, 07h ; 7t - c=polyonimal used in loop (small speed up)
_byteloop8b:
xor (hl) ; 7t - xor in next byte, for first pass a=(hl)
inc hl ; 6t - next mem
; ld b, 8 ; 7t - loop over 8 bits
_rotate8b:
; add a,a ; 4t - shift crc left one
; jr nc, _nextbit8b ; 12/7t - only xor polyonimal if msb set (carry=1)
; xor c ; 4t - CRC8_CCITT = 0x07
_nextbit8b:
; djnz _rotate8b ; 13/8t
ld b,a ; 4t - preserve a in b
dec de ; 6t - counter-1
ld a,d ; 4t - check if de=0
or e ; 4t
ld a,b ; 4t - restore a
jr nz, _byteloop8b ; 12/7t
ret ; 10t
; Clock Cycle For above with 4k bypes
; Loop = 4096 * 47 cycles + 11 => 192,523 x 2 (src/dest) => 385,046
; acuracy = 1 / 256 => 0.4 %
; =====================================================================
; CRC-CCITT
;
; CCITT polynomial 1021h
; Initial Value FFFFh
;
; input - de=start of memory to check, bc=length of memory to check
; returns - hl=result crc
; =====================================================================
_crc16:
ld hl, 0ffffh ; 10t - initial crc = $ffff
_byte16:
; push bc ; 11t - preserve counter
ld a,(de) ; 7t - get byte
inc de ; 6t - next mem
; xor h ; 4t - xor byte into crc high byte
; ld h,a ; 4t - back into high byte
; ld b,8 ; 7t - rotate 8 bits
_rotate16:
; add hl,hl ; 11t - rotate crc left one
; jr nc,_nextbit16 ; 12/7t - only xor polyonimal if msb set
; ld a,h ; 4t
; xor 10h ; 7t - high byte with $10
; ld h,a ; 4t
; ld a,l ; 4t
; xor 21h ; 7t - low byte with $21
; ld l,a ; 4t - hl now xor $1021
_nextbit16:
; djnz _rotate16 ; 13/8t - loop over 8 bits
; pop bc ; 10t - bring back main counter
dec bc ; 6t
ld a,b ; 4t
or c ; 4t
jr nz,_byte16 ; 12/7t
ret ; 10t
;

View File

@@ -0,0 +1,178 @@
;
; HBIOS FUNCTIONS
;
;
BF_DIO .EQU 010H
BF_DIOSTATUS .EQU BF_DIO + 0 ; DISK STATUS
BF_DIORESET .EQU BF_DIO + 1 ; DISK RESET
BF_DIOSEEK .EQU BF_DIO + 2 ; DISK SEEK
BF_DIOREAD .EQU BF_DIO + 3 ; DISK READ SECTORS
BF_DIOWRITE .EQU BF_DIO + 4 ; DISK WRITE SECTORS
BF_DIOVERIFY .EQU BF_DIO + 5 ; DISK VERIFY SECTORS
BF_DIOFORMAT .EQU BF_DIO + 6 ; DISK FORMAT TRACK
BF_DIODEVICE .EQU BF_DIO + 7 ; DISK DEVICE INFO REPORT
BF_DIOMEDIA .EQU BF_DIO + 8 ; DISK MEDIA REPORT
BF_DIODEFMED .EQU BF_DIO + 9 ; DEFINE DISK MEDIA
BF_DIOCAP .EQU BF_DIO + 10 ; DISK CAPACITY REPORT
BF_DIOGEOM .EQU BF_DIO + 11 ; DISK GEOMETRY REPORT
;
BF_SYS .EQU 0F0H
BF_SYSRESET .EQU BF_SYS + 0 ; SOFT RESET HBIOS
BF_SYSVER .EQU BF_SYS + 1 ; GET HBIOS VERSION
BF_SYSSETBNK .EQU BF_SYS + 2 ; SET CURRENT BANK
BF_SYSGETBNK .EQU BF_SYS + 3 ; GET CURRENT BANK
BF_SYSSETCPY .EQU BF_SYS + 4 ; BANK MEMORY COPY SETUP
BF_SYSBNKCPY .EQU BF_SYS + 5 ; BANK MEMORY COPY
BF_SYSALLOC .EQU BF_SYS + 6 ; ALLOC HBIOS HEAP MEMORY
BF_SYSFREE .EQU BF_SYS + 7 ; FREE HBIOS HEAP MEMORY
BF_SYSGET .EQU BF_SYS + 8 ; GET HBIOS INFO
BF_SYSSET .EQU BF_SYS + 9 ; SET HBIOS PARAMETERS
BF_SYSPEEK .EQU BF_SYS + 10 ; GET A BYTE VALUE FROM ALT BANK
BF_SYSPOKE .EQU BF_SYS + 11 ; SET A BYTE VALUE IN ALT BANK
BF_SYSINT .EQU BF_SYS + 12 ; MANAGE INTERRUPT VECTORS
;
BF_SYSGET_CIOCNT .EQU 00h ; GET CHAR UNIT COUNT
BF_SYSGET_CIOFN .EQU 01h ; GET CIO UNIT FN/DATA ADR
BF_SYSGET_DIOCNT .EQU 10h ; GET DISK UNIT COUNT
BF_SYSGET_DIOFN .EQU 11h ; GET DIO UNIT FN/DATA ADR
BF_SYSGET_RTCCNT .EQU 20h ; GET RTC UNIT COUNT
BF_SYSGET_DSKYCNT .EQU 30h ; GET DSKY UNIT COUNT
BF_SYSGET_VDACNT .EQU 40h ; GET VDA UNIT COUNT
BF_SYSGET_VDAFN .EQU 41h ; GET VDA UNIT FN/DATA ADR
BF_SYSGET_SNDCNT .EQU 50h ; GET VDA UNIT COUNT
BF_SYSGET_SNDFN .EQU 51h ; GET SND UNIT FN/DATA ADR
BF_SYSGET_TIMER .EQU 0D0h ; GET CURRENT TIMER VALUE
BF_SYSGET_SECS .EQU 0D1h ; GET CURRENT SECONDS VALUE
BF_SYSGET_BOOTINFO .EQU 0E0h ; GET BOOT INFORMATION
BF_SYSGET_CPUINFO .EQU 0F0h ; GET CPU INFORMATION
BF_SYSGET_MEMINFO .EQU 0F1h ; GET MEMORY CAPACTITY INFO
BF_SYSGET_BNKINFO .EQU 0F2h ; GET BANK ASSIGNMENT INFO
BF_SYSGET_CPUSPD .EQU 0F3h ; GET CLOCK SPEED & WAIT STATES
BF_SYSGET_PANEL .EQU 0F4h ; GET FRONT PANEL SWITCHES VAL
BF_SYSGET_APPBNKS .EQU 0F5h ; GET APP BANK INFORMATION
;
; MEDIA ID VALUES
;
MID_NONE .EQU 0
MID_MDROM .EQU 1
MID_MDRAM .EQU 2
MID_RF .EQU 3
MID_HD .EQU 4
MID_FD720 .EQU 5
MID_FD144 .EQU 6
MID_FD360 .EQU 7
MID_FD120 .EQU 8
MID_FD111 .EQU 9
MID_HDNEW .EQU 10
; -----------------
;
; Read timer in sconds.
;
sysgetseconds:
ld b,BF_SYSGET
ld c,BF_SYSGET_SECS
rst 08 ; do it
ret
; -----------------
;
; Return non zero if A (media ID)
; is a type of hard drive
; If not A=0 and Z flag is set
;
isaharddrive:
cp MID_HD
jr z, ishdd1
cp MID_HDNEW
jr z, ishdd1
xor a ; clear A and set Z flag
ret
ishdd1:
or a ; set Z flag and return
ret
; -------------------------------------
;
; used to pass the buffer address argument
;
bankid .DB 0 ; bank id used for read writes
dma .DW 8000h ; address argument for read write
;
;
; basic setup for disk io
; call to get the current bank IO
;
initdiskio:
; Get current RAM bank
ld b,BF_SYSGETBNK ; HBIOS GetBank function
RST 08 ; do it via RST vector, C=bank id
JP NZ, err_hbios
ld a,c ; put bank id in A
ld (bankid),a ; put bank id in Argument
RET
;
;
; Read disk sector(s)
; DE:HL is LBA, B is sector count, C is disk unit
; (dma) is the buffer address
; (bankid) is the memory bank
; Returns E sectors read, and A status
;
diskread:
; Seek to requested sector in DE:HL
push bc ; save unit & count
set 7,d ; set LBA access flag
ld b,BF_DIOSEEK ; HBIOS func: seek
rst 08 ; do it
pop bc ; recover unit & count
jp nz,err_diskio ; handle error
; Read sector(s) into buffer
ld e,b ; transfer count
ld b,BF_DIOREAD ; HBIOS func: disk read
ld hl,(dma) ; read into info sec buffer
ld a,(bankid) ; user bank
ld d,a
rst 08 ; do it
jp nz,err_diskio ; handle error
xor a ; signal success
ret ; and done
;
; Write disk sector(s)
; DE:HL is LBA, B is sector count, C is disk unit
; (dma) is the buffer address
; (bankid) is the memory bank
; Returns E sectors written, and A status
;
diskwrite:
; Seek to requested sector in DE:HL
push bc ; save unit & count
set 7,d ; set LBA access flag
ld b,BF_DIOSEEK ; HBIOS func: seek
rst 08 ; do it
pop bc ; recover unit & count
jp nz,err_diskio ; handle error
; Write sector(s) from buffer
ld e,b ; transfer count
ld b,BF_DIOWRITE ; HBIOS func: disk write
ld hl,(dma) ; write from sec buffer
ld a,(bankid) ; user bank
ld d,a
rst 08 ; do it
jp nz,err_diskio ; handle error
xor a ; signal success
ret ; and done
;
err_diskio:
; push hl
; ld hl,str_err_prefix
; call prtstr
; pop hl
; or 0ffh ; signal error
ret ; done
;str_err_prefix db 13,10,13,10,"*** ",0

File diff suppressed because it is too large Load Diff

View File

@@ -688,34 +688,34 @@ RomWBW enhancements. These applications are typically documented in the
"RomWBW Applications.pdf" document in the Doc directory of the
RomWBW Distribution.
| **File** | **Source** | **Description** |
|----------------|-----------------|---------------------------------------------------------------|
| `ASSIGN.COM` | RomWBW | Assign,remove,swap drive letters of RomWBW disk slices |
| `CLRDIR.COM` | Max Scane | Initializes the directory area of a disk |
| `COPYSL.COM` | M.Pruden | Copy CPM Hard Disk Slices |
| `COPYSL.DOC` | M.Pruden | Documentation for COPYSL.COM |
| `CPUSPD.COM` | RomWBW | CPU Speed |
| `FAT.COM` | RomWBW | MS-DOS FAT filesystem tool (list, copy, delete, format, etc.) |
| `FDISK80.COM` | John Coffman | Hard disk partitioning tool |
| `FDU.COM` | RomWBW | Floppy Disk Utility, Test and format floppy disks |
| `FDU.DOC` | RomWBW | Documentation for FDU |
| `FLASH.COM` | Will Sowerbutts | Program FLASH chips in-situ |
| `FLASH.DOC` | Will Sowerbutts | Documentation for FLASH |
| `FORMAT.COM` | RomWBW | Placeholder application with formatting instructions |
| `HTALK.COM` | Tom Plano | Terminal utility talking directly to HBIOS Character Units |
| `MODE.COM` | RomWBW | Change serial line characteristics (baud rate, etc.) |
| `REBOOT.COM` | MartinR | Cold or Warm Boot the RomWBW System |
| `RTC.COM` | Andrew Lynch | Test real time clock hardware on your system |
| `SURVEY.COM` | RomWBW | Display system resources summary |
| `SYSCOPY.COM` | RomWBW | Copy system tracks to disks (make bootable) |
| `TALK.COM` | RomWBW | Route console I/O to & from specified serial port |
| `TIMER.COM` | RomWBW | Test and display system timer ticks |
| `TUNE.COM` | RomWBW | Play .PT2, .PT3, and .MYM audio files on supported hardware |
| `VGMPLAY.COM` | | Simple player for VGM (Video Game Music) files. |
| `WDATE.COM` | Kevin Boone | Utility to configure RTC Date. |
| `XM.COM` | RomWBW | XModem file transfer application |
| **File** | **Source** | **Description** |
|----------------|-------------------|---------------------------------------------------------------|
| `ASSIGN.COM` | RomWBW | Assign,remove,swap drive letters of RomWBW disk slices |
| `CLRDIR.COM` | Max Scane | Initializes the directory area of a disk |
| `COPYSL.COM` | M.Pruden | Copy CPM Hard Disk Slices |
| `COPYSL.DOC` | M.Pruden | Documentation for COPYSL.COM |
| `CPUSPD.COM` | RomWBW | CPU Speed |
| `FAT.COM` | RomWBW | MS-DOS FAT filesystem tool (list, copy, delete, format, etc.) |
| `FDISK80.COM` | John Coffman | Hard disk partitioning tool |
| `FDU.COM` | RomWBW | Floppy Disk Utility, Test and format floppy disks |
| `FDU.DOC` | RomWBW | Documentation for FDU |
| `FLASH.COM` | Will Sowerbutts | Program FLASH chips in-situ |
| `FLASH.DOC` | Will Sowerbutts | Documentation for FLASH |
| `FORMAT.COM` | RomWBW | Placeholder application with formatting instructions |
| `HTALK.COM` | Tom Plano | Terminal utility talking directly to HBIOS Character Units |
| `MODE.COM` | RomWBW | Change serial line characteristics (baud rate, etc.) |
| `REBOOT.COM` | MartinR | Cold or Warm Boot the RomWBW System |
| `RTC.COM` | Andrew Lynch | Test real time clock hardware on your system |
| `SURVEY.COM` | RomWBW | Display system resources summary |
| `SYSCOPY.COM` | RomWBW | Copy system tracks to disks (make bootable) |
| `TALK.COM` | RomWBW | Route console I/O to & from specified serial port |
| `TIMER.COM` | RomWBW | Test and display system timer ticks |
| `TUNE.COM` | RomWBW | Play .PT2, .PT3, and .MYM audio files on supported hardware |
| `VGMPLAY.COM` | | Simple player for VGM (Video Game Music) files. |
| `WDATE.COM` | Kevin Boone | Utility to configure RTC Date. |
| `XM.COM` | RomWBW | XModem file transfer application |
Then we have some more general purpose applcations.
Then we have some more general purpose applications.
In general, there is no documentation for these applications included with the RomWBW
distribution. Some provide command line help themselves. Some are fairly obvious.
@@ -742,7 +742,9 @@ distribution. Some provide command line help themselves. Some are fairly obvio
| `SUPERSUB.DOC` | | Documentation for SUPERSUB |
| `SYSGEN.COM` | DRI | Copy system tracks to disks |
| `TBASIC.COM` | Dimitri Theulings | Tasty Basic. This also exists as a Rom appication |
| `TDLBASIC.COM` | | TDL Zapple 12K BASIC language interpreter |
| `TDLBASIC.COM` | | TDL Zapple 12K BASIC language interpreter |
| `TE.COM` | Ladislau Szilagyi | RomWBW enhanced version of TE editor |
| `TE.DOC` | Ladislau Szilagyi | TE Editor Documentation |
| `UNARC.COM` | | Extract file(s) from .ARC or .ARK archive |
| `UNARC.DOC` | | Documentation for UNARC |
| `UNCR.COM` | | Decompress Crunched file(s). See CRUNCH.COM |

View File

@@ -16,7 +16,7 @@ constraints, new hardware platforms can be supported by simply
adjusting values in a build configuration file.
RomWBW is geared toward hardware being developed in modern
retro-computing hobbyist communities, not as a replacement for
retro-computing hobbyist communities, not as replacement software for
legacy hardware. As a result, RomWBW requires at least 128KB
of bank switched RAM.
@@ -42,11 +42,11 @@ RomWBW firmware (ROM) includes:
It is appropriate to note that much of the code and components that make
up a complete RomWBW package are derived from pre-existing work. Most
notably, the embedded operating system is simply a ROM-based copy of
notably, the embedded operating systems are simply ROM-based copies of
generic CP/M or ZSDOS. Much of the hardware support code was originally
produced by other members of the RetroBrew Computers Community.
The remainder of this document focuses on HBIOS which is the
The remainder of this document focuses on RomWBW HBIOS which is the
fundamental basis of RomWBW.
# Background
@@ -61,13 +61,13 @@ space that is much larger than the CPU address space (typically 512K or
the CPU using a technique called bank switching. To achieve this, the
physical memory is divided up into chunks (banks) of 32K each. A
designated area of the CPU's 64K address space is then reserved to "map"
any of the physical memory chunks. You can think of this as a window
any of the physical memory chunks. You can think of this as a window
that can be adjusted to view portions of the physical memory in 32K
blocks. In the case of RomWBW, the lower 32K of the CPU address space is
used for this purpose (the window). The upper 32K of CPU address space
used for this purpose (the window). The upper 32K of CPU address space
is assigned a fixed 32K area of physical memory that never changes. The
lower 32K can be "mapped" on the fly to any of the 32K banks of physical
memory at a time. The only constraint is that the CPU cannot be
memory at a time. The primary constraint is that the CPU cannot be
executing code in the lower 32K of CPU address space at the time that a
bank switch is performed.
@@ -91,6 +91,17 @@ operating system is unaware this has occurred. As control is returned to
the operating system, the lower 32KB of memory is switched back to the
original memory bank.
The HBIOS functions are invoked simply by placing function parameters
in Z80 registers and calling an address within the HBIOS proxy.
Additionally, HBIOS implements a complete hardware interrupt management
framework. When a hardware interrupt occurs, control vectors through
the HBIOS proxy which saves the machine state, selects the HBIOS
driver bank into memory, and transfers control to the registered
driver's interrupt handler. Upon completion of interrupt processing,
control returns via the HBIOS proxy, machine state is restored, and
normal processing resumes. The interrupt management framework supports
Z80 interrupt modes 1, 2, and 3 (Z280).
HBIOS is completely agnostic with respect to the operating system (it
does not know or care what operating system is using it). The operating
system makes simple calls to HBIOS to access any desired hardware
@@ -124,8 +135,23 @@ execution.
# Runtime Memory Layout
![Bank Switched Memory Layout](Graphics/BankSwitchedMemory){ width=100% }
RomWBW divides the standard 64KB Z80 address space into 2 sections.
The lower 32KB is the "banked" area. This is the area that will
contain any of the 32KB chunks of physical RAM based on which bank is
currently selected. The upper 32KB is "fixed". This area of memory
is never swapped out and is used to contain software and operating
systems that must remain in the Z80 address space.
Figure 4.1 depicts the memory layout for a system running the CP/M
operating system. Applications residing in TPA invoke BDOS services
of CP/M, BDOS invokes the custom CBIOS APIs, and finally CBIOS
invokes HBIOS functions as needed by calling into the HBIOS proxy.
The HBIOS proxy swaps in the HBIOS bank as needed to perform the
requested function.
Additional banks of RAM are used to create a virtual disk drive.
![Bank Switched Memory Layout](Graphics/BankSwitchedMemory){ width=100% }
## Bank Id
@@ -139,7 +165,8 @@ a ROM bank is being referred to. If it is 1, it indicates a RAM bank
is being referred to.
For example, let's say we have a typical system with 512KB of ROM and
512KB of RAM. The Bank Ids would look like this:
512KB of RAM. The following table demonstrates how Bank Ids represent
areas of physical memory.
| Physical Memory | Type | Physical Bank | Bank Id |
|-------------------|------|---------------|-----------|
@@ -265,28 +292,55 @@ hence the name "Common".
# Disk Layout
RomWBW supports two hard disk layouts: the Classic layout used by
RomWBW with 512 directory entries per slice and a Modern layout with
1024 directory entries per slice. These layouts are referred to as
hd512 and hd1k respectively.
RomWBW supports the use of PC MBR hard disk partitioning (see
<https://en.wikipedia.org/wiki/Disk_partitioning>). When accessing
a hard disk device, HBIOS will look for a partition with type id 0x2E
and will use that partition exclusively for all storage. If a hard
disk does not have a valid partition table with a partition of type
0x2E, the HBIOS will treat the hard disk as dedicated storage and
will store data starting at the first sector of the disk.
The use of a partition of type 0x2E is preferred for RomWBW and is
referred to as a "Modern" disk layout. If there is no RomWBW
partition on the disk, then the disk is designated as having a
"Classic" disk layout.
When a disk uses a RomWBW partition (type 0x2E) for storage (Modern
layout), the CP/M filesystems on that disk will utilize a format with
1,024 directory entries per filesystem. If there is no RomWBW
partition, the CP/M filesystems will have 512 directory entries per
filesystem. As a result, the Modern disk layout with a RomWBW partition
is also referred to as the "hd1k" layout indicating 1024 directory
entries. Similarly, the Classic disk layout (no partition of type 0x2E)
is also referred to as the "hd512" layout indicating 512 directory
entries.
The layout type of any hard disk is simply dictated by the existence of
a RomWBW partition. This also means that if you add or remove a
partition table entry of type 0x2E on existing hard disk media, you will
lose access to any pre-existing CP/M data on the disk. If used,
partitioning should be done before putting any data on the disk.
WARNING: You **can not** mix the two hard disk layouts on one hard
disk device. You can use different layouts on different hard disk
devices in a single system though.
RomWBW determines which of the hard disk layouts to use for a given
hard disk device based on whether there is a RomWBW hard disk
partition on the disk containing the slices. If there is no RomWBW
partition, then RomWBW will assume the 512 directory entry format for
all slices and will assume the slices start at the first sector of
the hard disk. If there is a RomWBW partition on the hard disk
device, then RomWBW will assume the 1024 directory entry format for
all slices and will assume the slices are located in the defined
partition.
Regardless of whether a disk is Modern or Classic, RomWBW supports
the concept of CP/M filesystem slices. In general, CP/M filesystems are
limited to 8MB. Since current disk media is dramatically larger than
this, RomWBW implements a mechanism to put many (up to 256) CP/M
filesystems on a single disk. Each such filesystem is called a slice
referring to the idea that the disk has been sliced into many
independent CP/M filesystems. RomWBW allows the disk slices to be
mapped to the limited (16) drive letters of CP/M. The mapping can be
modified on-the-fly on a running system as desired.
RomWBW supports up to 256 CP/M slices (0-255). Under hd512, the slices
begin at the start of the hard disk. Under hd1k, the slices reside
within partition type 0x2E.
If the case of a Modern disk layout (with a RomWBW partition), the
slices are contained within the defined partition area and the number
of slices is dictated by the size of the partition. In the case of a
Classic disk layout (no RomWBW partition), the slices are located at the
start of the disk (first sector). In either case, the slices are just
sequential areas of space on the hard disk.
RomWBW accesses all hard disks using Logical Block Addressing (pure
sector offset). When necessary, RomWBW simulates the following disk
@@ -315,12 +369,11 @@ and CP/M knows nothing about the FAT partition. However, the FAT
application can be run under CP/M to access the FAT partition
programmatically.
A CP/M slice is (re)initialized using the CP/M command CLRDIR. A CP/M
slice can be made bootable by copying system image to the System Area
using SYSCOPY.
Before being used, A CP/M slice must be (re)initialized using the CP/M
command CLRDIR. A CP/M slice can be made bootable by copying a system
image to the System Area using SYSCOPY.
The FAT partition can be created from CP/M using the FDISK80 application.
The FAT partition can be initialized using the FAT application from CP/M
using the command `FAT FORMAT n:` where n is the RomWBW disk unit
number containing the FAT partition to be formatted.
@@ -380,10 +433,10 @@ There are two important Media ID's relating to Hard Disk Layouts:
HBIOS typically does not understand the format of data on a device,
instead just treating all hard disks as raw sectors. `MID_HD` is the typical
Media ID used by HBIOS to describe high capaity hard disk media
Media ID used by HBIOS to describe high capacity hard disk media
When the Modern Disk Layout was added, the `MID_HDNEW`, was added to
differentiate (at the oerating system level) between the Classic and Modern layouts.
differentiate (at the operating system level) between the Classic and Modern layouts.
However HBIOS itself typically does NOT make this distinction, since the use
of these two formats is determined by the operating system based on the
@@ -464,8 +517,10 @@ of a system image before programming it to the ROM; or 2) easily switch
between system images on the fly.
During the RomWBW build process, one of the output files produced is an
actual CP/M application (an executable .COM program file). Once you have
a running CP/M (or compatible) system, you can upload/copy this
actual CP/M application (an executable .COM program file). Like the
normal .ROM files, this file is placed in the Binary directory with the
same name as the ROM file, but with the file extension of .ROM. Once
you have a running CP/M (or compatible) system, you can upload/copy this
application file to the filesystem. By executing this file, you will
initiate an Application Boot using the system image contained in the
application file itself.
@@ -501,7 +556,7 @@ and control is passed to the Boot Loader.
## Boot Recovery
To assist users when driver faults or misconfiguration causes a boot
To assist users when driver faults or mis-configuration causes a boot
failure, RomWBW supports a limited recovery capability. This is
achieved by allowing the user to reboot their machine, loading
a minimal driver set. Implementation of this feature requires a
@@ -638,7 +693,7 @@ CRT character device, the data is actually passed to a built-in terminal
emulator which, in turn, utilizes a set of VDA (Video Display Adapter)
functions (such as cursor positioning, scrolling, etc.).
Figure 7.1 depicts the relationship between these components
Figure 9.1 depicts the relationship between these components
of HBIOS video processing:
![Character / Emulation / Video Services](Graphics/CharacterEmulationVideoServices){ width=100% }
@@ -689,7 +744,7 @@ must be careful not to modify the operating environment in any way that
the operating system does not expect.
In general, the desired function is placed in the B register. Register C
is frequently used to specify a subfunction or a target device unit
is frequently used to specify a sub-function or a target device unit
number. Additional registers are used as defined by the specific
function. Register A should be used to return function result
information. See below for result code definitions.
@@ -712,7 +767,7 @@ lower 32K of CPU address space. For optimal performance, such buffers
should be placed in the upper 32K of CPU address space.
HBIOS also implements a small number of core functions in the HBIOS
proxy area at the top of RAM. These exist primarily to faciliate the
proxy area at the top of RAM. These exist primarily to facilitate the
operation of normal HBIOS function calls. However, they are available
to be used by OSes and applications. These functions can only be
invoked by calling into a jump table in upper RAM.
@@ -766,10 +821,11 @@ below enumerates these values.
| CIODEV_DUART | 0x09 | SCC2681 Family Dual UART | duart.asm |
| CIODEV_Z2U | 0x0A | Zilog Z280 Built-in Serial Ports | z2u.asm |
| CIODEV_LPT | 0x0B | Parallel I/O Controller | lpt.asm |
| CIODEV_ESPCON | 0x0B | ESP32 VGA Console | esp.asm |
| CIODEV_ESPSER | 0x0B | ESP32 Serial Port | esp.asm |
| CIODEV_SCON | 0x0B | S100 Console | scon.asm |
| CIODEV_EZ80UART | 0x11 | eZ80 Built-in UART0 Interface | ez80uart.asm |
| CIODEV_ESPCON | 0x0C | ESP32 VGA Console | esp.asm |
| CIODEV_ESPSER | 0x0D | ESP32 Serial Port | esp.asm |
| CIODEV_SCON | 0x0E | S100 Console | scon.asm |
| CIODEV_SSER | 0x0F | Simple Serial Console | sser.asm |
| CIODEV_EZ80UART | 0x10 | eZ80 Built-in UART0 Interface | ez80uart.asm |
Character devices can usually be configured with line characteristics
such as speed, framing, etc. A word value (16 bit) is used to describe
@@ -906,7 +962,9 @@ Returns the current Line Characteristics (DE) of the specified Character
Returns device information for the specified Character Unit (C). The
status (A) is a standard HBIOS result code.
Device Attribute (C) values are: 0 = RS/232, 1 = Terminal, 2 = Parallel.
The two high bits of Device Attribute (C) are: 00 = RS/232, 01 = Terminal,
10 = Parallel. The remaining bits should be ignored and are used
internally.
Device Type (D) indicates the specific hardware driver that handles the
specified Character Unit. Values are listed at the start of this
@@ -1981,7 +2039,7 @@ standard HBIOS result code.
| | E: Keycode |
Read the next key data from keyboard of the specified Video Unit (C). If
a keyboard buffer is used, return the next key code in the buffer. If
a keyboard buffer is used, return the next key code in the buffer. If
no key data is available, this function will wait indefinitely for a
keypress. The Status (A) is a standard HBIOS result code.
@@ -1989,7 +2047,7 @@ The Scancode (C) value is the raw scancode from the keyboard for the
keypress. Scancodes are from the PS/2 scancode set 2 standard.
The Keystate (D) is a bitmap representing the value of all modifier keys
and shift states as they existed at the time of the keystroke. The
and shift states as they existed at the time of the keystroke. The
bitmap is defined as:
| **Bit** | **Keystate Indication** |
@@ -2331,7 +2389,7 @@ start of the Slice (E). The Status (A) is a standard HBIOS result code.
This function extends upon [Function 0x18 -- Disk Media (DIOMEDIA)] for hard
disk media by scanning for a partition to determine if the disk uses HD512
or HD1K, correctly reporting MID_HD or MID_HDNEW respectively.
See the folowing for some background [Mapping to Media ID]
See the following for some background [Mapping to Media ID]
It will also return the sector number of the first sector in the
slice if the slice number is valid. If the slice number is invalid
@@ -2721,7 +2779,7 @@ Switches may be returned as a 16 bit (HL) or 8 bit (L) value. It is up to the ca
to process the returned value correctly. Note for Switch 0xFF (status) the returned value
is primarily in the Status (A) register.
Errors are signalled in the return by setting the NZ flag. When set the
Errors are signaled in the return by setting the NZ flag. When set the
(A) register may contain an error code, but this code does not conform to RomWBW standard
Success is indicated by setting the Z flag
@@ -3039,7 +3097,7 @@ Status (A) is a standard HBIOS result code.
This function allows the caller to query information about the interrupt
configuration of the running system and allows adding or hooking
interrupt handlers dynamically. Register C is used to specify a
subfunction. Additional input and output registers may be used as
sub-function. Additional input and output registers may be used as
defined by the sub-function. The Status (A) is a standard
HBIOS result code.
@@ -3099,13 +3157,11 @@ with the handler prior to uninstalling it.
| C: 0x00 | D: Interrupt Mode |
| | E: IVT Size |
Return current Interrupt Mode (D) of the system. Also return the
number of Interrupt Vector Table (IVT) entries in IVT Size (E).
interrupt mode in D and size of interrupt vector table in E. For
IM1, the size of the table is the number of vectors chained together.
For IM2, the size of the table is the number of slots in the vector
table. The Status (A) is a standard
HBIOS result code.
Return current Interrupt Mode (D) of the system. Also return the number
of Interrupt Vector Table (IVT) entries in IVT (E). For IM1, the size
of the table is the number of vectors chained together. For IM2, the
size of the table is the number of slots in the vector table. The
Status (A) is a standard HBIOS result code.
#### SYSINT Subfunction 0x10 -- Get Interrupt (INTGET)
@@ -3468,5 +3524,3 @@ The following section outlines the read only data referenced by the
| DCNTL* | 14 | 1 | Z180 DMA/WAIT CONTROL |
* ONLY PRESENT FOR Z180 BUILDS

View File

@@ -833,24 +833,63 @@ disk device performs I/O, the LED will light while the disk is active.
This is only possible for the first 8 disk units.
The second row of the front panel is composed of switches that allow
you to control a few aspects of the system startup.
you to control a few aspects of the system startup. The switches are
also re-read during warm boot, so confirm the switch settings are your
desired boot configuration before executing 'REBOOT /W'.
The first two switches affect the device used as the initial console.
| CRT/Serial | Sec/Pri | Explanation |
|------------|---------|-------------------------------------------------------------|
| CRT | Pri | Primary Cathode Ray Tube device (high speed console) |
| CRT | Sec | Secondary Cathode Ray Tube device (high speed console) |
| Serial | Pri | Boot Console is Primary Serial Port |
| Serial | Sec | Boot Console is Secondary Serial Port |
The first two switches affect the device used as the console initially.
Setting the CRT/Serial switch will cause the system to boot directly
to an attached CRT device (if available). Setting the Pri/Sec switch
will cause the system to boot to the secondary Serial or CRT device
(depending on the setting of the first switch).
If not available (default): "Char Unit 0" is used
The final six switches allow you to cause the system to automatically
boot into a desired function. The Auto/Menu switch must be set to
enable this, otherwise the normal ROM Loader prompt will be used.
If the Disk/ROM switch is not set, then you can use the last 3
switches to select a ROM app to auto-start. If the Disk/ROM switch is
set, then the system will attempt a disk boot based on the following
switches. The Floppy/Hard switch can be used to boot to a Floppy or
Hard Disk. In either case, the first Floppy or Hard Disk will be used
for the boot. If a Hard Disk boot is selected, then the last three
switches can be used to select any of the first 8 slices.
The final six switches allow you to select the desired boot device.
+-----------+----------+-------------+--------------------------+-------------------------------------------------+
| | | | ROM/App/Boot Slice | |
| Auto / | Disk / | Floppy / +--------+--------+--------+-------------------------------------------------+
| Menu | ROM | Hard | 4 | 2 | 1 | Explanation |
+===========+==========+=============+========+========+========+=================================================+
| Menu | -- | -- | -- | -- | -- | Boot to RomWBW Menu |
+-----------+----------+-------------+--------+--------+--------+-------------------------------------------------+
| Auto | Disk | Floppy | # | # | # | Boot Selected Floppy Disk Index |
+-----------+----------+-------------+--------+--------+--------+-------------------------------------------------+
| Auto | Disk | Hard | # | # | # | Boot Selected Hard Disk Index |
+-----------+----------+-------------+--------+--------+--------+-------------------------------------------------+
| Auto | ROM | -- | # | # | # | Boot selected ROM Index |
+-----------+----------+-------------+--------+--------+--------+-------------------------------------------------+
If not available: Boot Loader Command Prompt \
'--' Ignored \
'#' bit flag to select any three bits 4,2,1
ROM or Hard Disk - First 8 Drive Images
+-------+-----------------+-----------+
| | Floppy / Hard \ | |
| 4 2 1 | Drive Index | ROM Index |
+=======+=================+===========+
| 0 0 0 | Zero | Monitor |
+-------+-----------------+-----------+
| 0 0 1 | One | BASIC |
+-------+-----------------+-----------+
| 0 2 0 | Two | Forth |
+-------+-----------------+-----------+
| 0 2 1 | Three | Game |
+-------+-----------------+-----------+
| 4 0 0 | Four | CP/M |
+-------+-----------------+-----------+
| 4 0 1 | Five | Z-System |
+-------+-----------------+-----------+
| 4 2 0 | Six | Net Boot |
+-------+-----------------+-----------+
| 4 2 1 | Seven | User |
+-------+-----------------+-----------+
# Disk Management
@@ -1293,7 +1332,7 @@ disk drive space to store a sequential series of slices that contain the
actual CP/M filesystems referred to by drive letters by the operating
system.
Two physical layout schemes exist:
Two hard disk layout schemes exist:
* Modern (hd1k)
* Legacy (hd512)
@@ -1309,6 +1348,7 @@ recommended for the following reasons:
* Larger number of directory entries per filesystem
* Simplifies creation of coresident FAT filesystem
* Reduces chances of data corruption
* Each slice occupies exactly 8MB (an exact power of 2) in size
Both the legacy and modern disk layouts continue to be fully supported
by RomWBW. There are no plans to deprecate the legacy layout.
@@ -1830,20 +1870,21 @@ command prompt.
Keeping in mind that a RomWBW hard disk (including CF/SD/USB devices)
allows you to have multiple slices (CP/M filesystems), there are a
couple ways to image hard disk media. The easiest approach is to
use the "combo" disk image. This image is already prepared
use the Combo Disk Image. This hard disk image is already prepared
with 6 slices containing 5 ready-to-run OSes and a slice with
the WordStar application files.
Alternatively, you can create your own
hard disk image with the specific slice contents you choose.
Alternatively, you can create your own hard disk image with the specific
slice contents you choose.
### Standard Hard Disk Physical Layout
### Standard Hard Disk Layout
As previously described in [Hard Disk Layouts], the exact placement of
slices and optional FAT partition will vary depending on which disk
layout (hd512 or hd1k) you are using and your partition table entries.
To simplify the use of hard disk images, RomWBW has adopted standard
partition table entries for disk image files provided.
To simplify the use of hard disk images, RomWBW has adopted a standard
partition layout for disk image files provided. This standard
layout is used to produce the Combo Disk Images described below.
These partition sizes and locations were chosen to:
@@ -1851,72 +1892,43 @@ These partition sizes and locations were chosen to:
- Allow for 64 CP/M filesystem slices
- Allow for a 384KB FAT filesystem
**NOTE:** RomWBW is not limited to these partition table entries. You
can change the size and location of the RomWBW and/or FAT partitions to
increase/decrease the number of slices or FAT filesystem size.
The standard partition table table entries are:
+---------------------------------+-------------------------------+-------------------------------+
| | **--- Legacy (hd512) ---** | **--- Modern (hd1k) ---** |
| | **--- Modern (hd1k) ---** | **--- Legacy (hd512) ---** |
| +---------------+---------------+---------------+---------------+
| | Byte(s) | Sector(s) | Byte(s) | Sector(s) |
+=================================+==============:+==============:+==============:+==============:+
| RomWBW (slices) Start | 0 | 0 | 1,048,576 | 2,048 |
| RomWBW Partition Start | 1 MB | 2,048 | -- | -- |
+---------------------------------+---------------+---------------+---------------+---------------+
| RomWBW (slices) Size | 545,259,520 | 1,064,960 | 536,870,912 | 1,048,576 |
| RomWBW Partition Size | 512 MB | 1,048,576 | -- | -- |
+---------------------------------+---------------+---------------+---------------+---------------+
| FAT Filesystem Start | 545,259,520 | 1,064,960 | 537,919,488 | 1,050,624 |
| FAT Filesystem Start | 513 MB | 1,050,624 | 520 MB | 1,064,960 |
+---------------------------------+---------------+---------------+---------------+---------------+
| FAT Filesystem Size | 402,653,184 | 786,432 | 402,653,184 | 786,432 |
| FAT Filesystem Size | 384 MB | 786,432 | 384 MB | 786,432 |
+---------------------------------+---------------+---------------+---------------+---------------+
| \<end\> | 947,912,704 | 1,851,392 | 940,572,672 | 1,837,056 |
| \<end\> | 897 MB | 1,851,392 | 904 MB | 1,837,056 |
+---------------------------------+---------------+---------------+---------------+---------------+
The above partition table entries will result in the following locations and sizes of
filesystems on the RomWBW disk images.
**NOTE:** RomWBW is not limited to these partition table entries. You
can change the size and location of the RomWBW and/or FAT partitions to
increase/decrease the number of slices or FAT filesystem size. Doing
so would require using `FDISK80` to define your own custom disk layout
and initializing your filesystems manually.
The $doc_sys$ has more information on the standard disk layouts as
implemented in the Combo Disk Images. Additionally, there is a document
called "Hard Disk Anatomy.pdf" in the Doc directory of the RomWBW
distribution with detailed information on the standard disk
layouts.
+---------------------------------+-------------------------------+-------------------------------+
| | **--- Legacy (hd512) ---** | **--- Modern (hd1k) ---** |
| +---------------+---------------+---------------+---------------+
| | Byte(s) | Sector(s) | Byte(s) | Sector(s) |
+=================================+==============:+==============:+==============:+==============:+
| Prefix Start | -- | -- | 0 | 0 |
+---------------------------------+---------------+---------------+---------------+---------------+
| Prefix Size | -- | -- | 1,048,576 | 2,048 |
+---------------------------------+---------------+---------------+---------------+---------------+
| Slice Size | 8,519,680 | 16,640 | 8,388,608 | 16,384 |
+---------------------------------+---------------+---------------+---------------+---------------+
| Slice 0 Start | 0 | 0 | 1,048,576 | 2,048 |
+---------------------------------+---------------+---------------+---------------+---------------+
| Slice 1 Start | 8,519,680 | 16,640 | 9,437,184 | 18,432 |
+---------------------------------+---------------+---------------+---------------+---------------+
| Slice 2 Start | 17,039,360 | 33,280 | 17,825,792 | 34,816 |
+---------------------------------+---------------+---------------+---------------+---------------+
| Slice 3 Start | 25,559,040 | 49,920 | 26,214,400 | 51,200 |
+---------------------------------+---------------+---------------+---------------+---------------+
| Slice 4 Start | 34,078,720 | 66,560 | 34,603,008 | 67,584 |
+---------------------------------+---------------+---------------+---------------+---------------+
| Slice 5 Start | 42,598,400 | 83,200 | 42,991,616 | 83,968 |
+---------------------------------+---------------+---------------+---------------+---------------+
| Slice 6 Start | 51,118,080 | 99,840 | 51,380,224 | 100,352 |
+---------------------------------+---------------+---------------+---------------+---------------+
| Slice 7 Start | 59,637,760 | 116,480 | 59,768,832 | 116,736 |
+---------------------------------+---------------+---------------+---------------+---------------+
| Slice 63 Start | 536,739,840 | 1,048,320 | 529,530,880 | 1,034,240 |
+---------------------------------+---------------+---------------+---------------+---------------+
| FAT Filesystem Start | 545,259,520 | 1,064,960 | 537,919,488 | 1,050,624 |
+---------------------------------+---------------+---------------+---------------+---------------+
| FAT Filesystem Size | 402,653,184 | 786,432 | 402,653,184 | 786,432 |
+---------------------------------+---------------+---------------+---------------+---------------+
| \<end\> | 947,912,704 | 1,851,392 | 940,572,672 | 1,837,056 |
+---------------------------------+---------------+---------------+---------------+---------------+
### Combo Hard Disk Image
#### Combo Hard Disk Image
The combo disk image is essentially just a single image that has several
of the individual filesystem images (slices) already concatenated
together. The combo disk image contains the following 6 slices in the
positions indicated:
The Combo Disk Image is essentially just a single disk image that has
several of the individual filesystem images (slices) already
concatenated together using the standard disk layout described above.
The Combo Disk Image includes the partition table of the standard disk
layout and the following 6 slices in the positions indicated:
| **Slice** | **Description** |
|------------|-----------------------------------------|
@@ -1928,68 +1940,67 @@ positions indicated:
| Slice 5 | WordStar v4 & ZDE Applications |
| Slice 6-63 | _blank unformatted_ |
There are actually 2 primary combo disk images in the
distribution. One for an hd512 disk layout (hd512_combo.img) and one
There are actually 2 Combo Disk Images in the
distribution. One for an hd512 disk layout (hd512_combo.img) and one
for an hd1k disk layout (hd1k_combo.img). Simply use the image file that
corresponds to your desired hard disk layout. Review the information
in [Hard Disk Layouts] if you need more information of the disk layout
options.
> **Note**: Apart from the hd512 and hd1k combo disk images (mentioned above)
> there are actaully a number of other `hd1k_*_combo.img` files. These
> additional combo files are platform (generally romless) specific,
> **Note**: Apart from the hd512 and hd1k Combo Disk Images (mentioned above)
> there are actually a number of other `hd1k_*_combo.img` files. These
> additional combo files are platform (generally romless) specific,
> and should be ignored unless you are on one of these platforms.
> If you are on one of these platforms you must use the correct combo file
The combo disk image actaully only contains the initial partition table,
and the first 6 slices (Slice 0 to 5), this is approximately 49MB in size.
While the partition table reserves space to store 64 CP/M filesystem
slices as well as a single 384MB FAT filesystem, these area remain
empty, and must be manuall initialized manually.
The Combo Disk Image actually only contains the initial partition table,
and the first 6 slices (Slice 0 to 5), this is approximately 49MB in
size. While the partition table reserves space to store 64 CP/M
filesystem slices as well as a single 384MB FAT filesystem, these areas
remain empty, and must be initialized manually using `CLRDIR` for CP/M
filesystems and `FAT FORMAT` for the FAT filesystem.
#### Combo Image Capacity
#### Combo Disk Image Capacity
The combo disk image layout was designed to fit well on a 1GB hard disk.
The 64 CP/M slices (approximately 512MB) and 384MB FAT filesystem all
fit well within a 1GB hard disk. This size choice was a bit arbitrary,
but based on the idea that 1GB CF/SD/USB Media is easy and cheap to
acquire.
The standard hard disk layout used by the Combo Disk Image was designed
to fit well on a 1GB hard disk. The 64 CP/M slices (approximately 512MB)
and 384MB FAT filesystem all fit well within a 1GB hard disk. This
size choice was a bit arbitrary, but based on the idea that 1GB
CF/SD/USB Media is easy and cheap to acquire.
It is fine if your hard disk is smaller than 1GB. It just
means that it will not be possible to use the pre-allocated FAT
filesystem partition and any CP/M filesystem slices that don't fit.
The true number of CP/M filesystem slices that
will fit on your specific physical hard disk can be calculated as
described in [Hard Disk Capacity].
It is fine if your hard disk is smaller than 1GB. It just means that it
will not be possible to use the pre-allocated FAT filesystem partition
and any CP/M filesystem slices that don't fit. The true number of CP/M
filesystem slices that will fit on your specific physical hard disk can
be calculated as described in [Hard Disk Capacity].
If you attempt to access a slice past the end of the
physical hard disk you will get "no disk" errors.
You should calculate the maximum number of slices your hard disk
will support and do not exceed this number.
If you attempt to access a slice past the end of the physical hard disk
you will get "no disk" errors. You should calculate the maximum number
of slices your hard disk will support and do not exceed this number.
#### Combo Image Advice
#### Combo Disk Image Advice
A great way to maintain your own data on a hard disk is to put this
data in slices beyond the first 6. By doing so, you can always
"re-image" your drive media with the combo image without overlaying the data
A great way to maintain your own data on a hard disk is to put your data
in slices beyond the first 6. By doing so, you can always "re-image"
your drive media with the Combo Disk Image without overlaying the data
stored in the slices beyond the first 6. Just be very careful to use
the same combo image layout (hd512 or hd1k) as you used originally.
### Custom Hard Disk Image
For hard disks, each .img file represents a single slice (CP/M
filesystem). Since a hard disk can contain many slices, you can just
For hard disks, each .img file represents a single slice (CP/M
filesystem). Since a hard disk can contain many slices, you can just
concatenate the slices (.img files) together to create your desired hard
disk image.
disk image.
If you look in the Binary directory of the distribution, you will see
that there are more disk (slice) images than the 6 that are included
in the "combo" disk images. These images are identified by looking
for the files that start with hd1k_ or hd512_.
that there are more disk (slice) images than the 6 that are included in
the Combo Disk Images. These supplemental disk images are identified by
looking for the files that start with hd1k_ or hd512_.
#### Adding Slices to Combo Image
You can add slices to the combo disk images simply by tacking
You can add slices to the Combo Disk Images simply by tacking
slices onto the end. For example, if you want to add a slice
containing the MSX ROMs to the end of the combo image, you could
use one of the following command lines depending on your operating
@@ -2052,7 +2063,7 @@ please refer to the ReadMe.txt file in the Source/Images directory.
### Writing Hard Disk Images
Once you have chosen a combo hard disk image file or prepared your own
Once you have chosen a Combo Hard Disk Image file or prepared your own
custom hard disk image file, it will need to be written to the media
using your modern computer. When using this method,
the disk will be partitioned and setup with 1 or more slices containing
@@ -2117,13 +2128,13 @@ survive re-imaging, you **must** follow these rules:
This section covers techniques to copy partial images onto pre-existing media,
in effect performing a selective slice copy. These techniques currently **only** apply to
hd1k formatted media, which has a convenient 1MB size metric.
hd1k formatted media, which has a partition table entry, and a convenient 1MB size metric.
However adapting to hd512 is possible, but left to the user.
On Linux/MacOS the `dd` command can be used to write data in a controlled manner.
Although Windows does not have a native `dd` command, there are multiple
options for installing it including [MSYS2](https://www.msys2.org/),
[CygWin](https://www.cygwin.com/),
You will need to have access to a Linux/MacOS machine, or have the
Linux tools for Windows installed, including the `dd` command line tool.
For Windows there are multiple options for installing `dd` including
[MSYS2](https://www.msys2.org/), [CygWin](https://www.cygwin.com/),
and [dd for Windows](http://www.chrysocome.net/dd).
**WARNING**: The `dd` command is a low-level utility that writes
@@ -2146,21 +2157,80 @@ From the documentation of `dd` the following options are important.
of the default 512
```
In the following examples we use the above options, noting the `of=` option
is specific to your computer but defines the block device that the target
media is mounted to in the operating system,
and `bs=1MB` defines the block size used in other parameters which is convienient
since it aligns perfectly with slices which are exactly 8MB
and the initial partition table is exactly 1MB.
The best approach is to copy data to the RomWBW partition. To do this, you
must first determine the name that your operating system is using for the
RomWBW disk and partition. An easy way to determine this may be the linux `mount`
command, which lists the currently mounted partitions. From here you can more easily
determine the naming scheme used by your operating system.
Typically disk devices are named something like `/dev/disk9` or `/dev/sdg`, noting above
the `g` is a alphabetic and it could be any letter. This naming is arbitrary
and depend on the operating system, and the specific hardware connecting the device
Partitions are typically named by simply adding a number after the name of the hard disk
device. For example, the first partition could be `/dev/disk9s1`, `/dev/sdg1`, or `/dev/sdgp1`.
In the following examples we use the above `dd` options, noting the `of=` option
is the RomWBW target partition.
** NOTE ** A second approach (Examples 3 and 4) is to address the hard
disk as a raw disk device and we take explicit steps to calculate the
start of the RomWBW partition. While this works, it is better to use the
partition relative approach.
The commands in the examples below are run from the `Binary` folder of RomWBW distribution.
#### Example 1 : Copy the Combo Image without replacing partition table
#### Example 1 : Copy the Games image to an empty slice of our media
In this example we will copy the (hd1k) combo image over our media
without replacing the partition table. In this example we assume the media
has already been formated with the combo image, and we have modified
the partition table, which we do not want to overrite.
In this example we will copy the (hd1k) games image to Slice 6 (free)
of our existing media. In this example we assume the media
has already been formatted with the combo image, which already
contains 6 slices (numbered from 0 to 5).
We are just copying the needed slice to the existing media
as a new slice (number 6) after the existing slices making it the 7th slice.
```
Binary % sudo dd if=hd1k_games.img of=/dev/sdg1 seek=6 bs=8M
Password:
1+0 records in
1+0 records out
8388608 bytes transferred in 1.917296 secs (4375228 bytes/sec)
```
Since bs=8MB the `seek=6` skips the first 6 (8MB slices) slices (in the target image)
and writes the games image to the 7th slice.
#### Example 2 : Copy the entire Combo Image without replacing partition table
In all of the following examples we use `bs=1MB` to defines the block size used
in other parameters. This is convenient since the combo image reserves 1MB for
the partition table at the start of the disk.
In this example we will copy the (hd1k) combo image (which includes a partition table)
over our media without replacing the partition table. In this example we assume the media
has already been formatted with the combo image, and we have modified the partition table,
which we do not want to overwrite.
```
Binary % sudo dd if=hd1k_combo.img of=/dev/sdg1 skip=1 bs=1M
Password:
48+0 records in
48+0 records out
50331648 bytes transferred in 11.503776 secs (4745528 bytes/sec)
```
The `skip=1` skips the first 1MB (partition table) in the input file,
effectively stripping out the combo images partition table, before overwriting
the slices in the target partition.
#### Example 3 : Copy the Combo Image without replacing partition table
This example is identical to Example 2 except it writes to the target
disk device itself (`of=/dev/disk9`), not the target partition.
```
Binary % sudo dd if=hd1k_combo.img of=/dev/disk9 skip=1 seek=1 bs=1M
@@ -2174,14 +2244,14 @@ Password:
The `skip=1` skips the first 1MB in the input file, and likewise
`seek=1` skips the first 1MB of the target media file we are writing to,
tus in effect we are skipping the first 1MB, which contains the
thus in effect we are skipping the first 1MB, which contains the
partition table itself.
#### Example 2 : Copy the Games image to an empty slice of our media
#### Example 4 : Copy the Games image to an empty slice of our media
In this example we will copy the (hd1k) games image to Slice 6 (free)
of our existing media. In this example we assume the media
has already been formated with the combo image, which already
has already been formatted with the combo image, which already
contains 6 slices (numbered from 0 to 5)
We are just coping the needed slice to this existing media
as a new slice (number 6) after the existing slices making it the 7th slice.
@@ -2203,27 +2273,6 @@ and 1 is the size of the partition table im megabytes.
Thus we are skipping 6 slices (in the combo image)
and writing to the 7th slice.
#### Example 3 : Copy image using partition
In the previous examples, the hard disk is addressed as a raw disk
device and we took steps to calculate the assumed start of the RomWBW
partition. However, as long as the hd1k format is in use, it is
also possible to just point `dd` directly to the partition itself.
To do this, you must first determine the name that your operating
system is using for the desired partition. Frequently, partitions
are named by simply adding a number after the name of the hard disk
device. For example, if the hard disk is /dev/sdg, the first
partition is frequently /dev/sdg1 or /dev/sdgp1.
Taking advantage of this, it is safer and easier to calculate the
offset of a slice within the partition. It is simply the slice
number \* 8MB. Example 2 above, could now be performed as:
```
Binary % sudo dd if=hd1k_games.img of=/dev/sdg1 seek=48 bs=1M
```
# Operating Systems
One of the primary goals of RomWBW is to expose a set of generic
@@ -2819,7 +2868,7 @@ is analogous to the CP/M 2.2 `STAT` command. Do **not** use the CP/M
Source/Images/d_qpm/u0 directory.
- The QPM disk image is not included as one of the slices on the
RomWBW combo disk image. If you want to include QPM, you can do
RomWBW Combo Disk Image. If you want to include QPM, you can do
so by following the directions in Source/Images/Readme.txt.
## UCSD p-System

View File

@@ -71,7 +71,7 @@ Bank ID Usage
0x82 User TPA
0x83 Common
ROMless Standard Bank Layout (512K)
ROMless Standard Bank Layout (512K): ZRC, ZRC512, EZ512, Z1RCC, ZZRCC, FZ80
Bank ID Usage
------- ------

View File

@@ -5137,20 +5137,10 @@ EXT_SLICE2A:
ADD HL,DE ; MOVE HL FWD TO GET TO LBA OFFSET
CP $2E ; CP/M PARTITION?
JR Z,EXT_SLICE3B ; HD1K, GRAB THE LBA OFFSET
CP $00 ; IS ANOTHER PARTITION TYPE, NOT CPM
JR NZ,EXT_SLICE3A ; OTHER VALID PART TYPE
EXT_SLICE2B:
LD DE,12 ; REMAINING SIZE TO GET TO NEXT PARTITION
EXT_SLICE2C:
ADD HL,DE ; BUMP TO NEXT PARTITION ENTRY - TYPE
DJNZ EXT_SLICE2A ; LOOP THRU TABLE
JR EXT_SLICE3C ; READ ALL - NO CP/M PARTITION FOUND
;
EXT_SLICE3A:
;
#IF (STRICTPART)
;
; THE FOLLOWING CODE RECORDS THE START OF A FOREIGN PARTITION AS THE IMPLIED
; THE FOLLOWING TEST RECORDS THE START OF A FOREIGN PARTITION AS THE IMPLIED
; END OF NON-PARTITIONED CP/M SPACE (HD512). THIS IS SUBSEQUENTLY USED TO
; ENSURE WE DON'T ACCESS AN HD512 SLICE THAT IS ACTUALLY INSIDE OF A
; FOREIGN PARTITION. HOWEVER, ROMWBW HAS PREVIOUSLY IGNORED FOREIGN
@@ -5159,6 +5149,18 @@ EXT_SLICE3A:
; THE STRICTPART CONDITIONAL WILL ENABLE STRICT PARTITION TABLE
; VALIDATION, IF DESIRED.
;
CP $00 ; IS ANOTHER PARTITION TYPE, NOT CPM
JR NZ,EXT_SLICE3A ; OTHER VALID PART TYPE
#ENDIF
;
EXT_SLICE2B:
LD DE,12 ; REMAINING SIZE TO GET TO NEXT PARTITION
EXT_SLICE2C:
ADD HL,DE ; BUMP TO NEXT PARTITION ENTRY - TYPE
DJNZ EXT_SLICE2A ; LOOP THRU TABLE
JR EXT_SLICE3C ; READ ALL - NO CP/M PARTITION FOUND
;
EXT_SLICE3A:
; FOUND OTHER (NOT CPM) PARTITION
LD A,(SLICE_FND) ; HAVE WE ALREADY FOUND PROCESSED NON CPM
OR A ; PARTITION, AND CAPTURED ITS START SECTOR, SO
@@ -5179,12 +5181,6 @@ EXT_SLICE3A:
LD DE,8 ; AND INC HL BY 8 TO GET TO NEXT PARITION
JR EXT_SLICE2C ; CONTINUE TO NEXT PARTITION
;
#ELSE
;
JR EXT_SLICE2B ; IGNORE FOREIGN PARTITIONS AND GO TO NEXT PART
;
#ENDIF
;
EXT_SLICE3B:
; FOUND CP/M (HD1K) PARTITION - RECORD THIS
LD A,MID_HDNEW ; DISCOVERED HD1K MEDIA
@@ -8433,7 +8429,7 @@ PS_SERIAL:
CALL NEWLINE
RET
;
; PRINT CHARACTER TYPE (SERIAL ATTRIBUTE IN E)
; PRINT CHARACTER TYPE (SERIAL ATTRIBUTE IN C)
;
PS_PRTST:
LD HL,PS_STPPT

View File

@@ -393,9 +393,8 @@ CIODEV_LPT .EQU $0B
CIODEV_ESPCON .EQU $0C
CIODEV_ESPSER .EQU $0D
CIODEV_SCON .EQU $0E
CIODEV_EF .EQU $0F
CIODEV_SSER .EQU $10
CIODEV_EZ80UART .EQU $11
CIODEV_SSER .EQU $0F
CIODEV_EZ80UART .EQU $10
;
; SUB TYPES OF CHAR DEVICES
;

View File

@@ -29,7 +29,7 @@
; - NHYODYNE Z80 $68
; - NHYODYNE DUART $80,$88
; - RCBUS EPSER $A0,$A8
; - RCBUS DUAL RS232 $80,$88
; - RCBUS SERIAL $80,$88,$A0,$A8,$C0,$C8,$E0,$E8
; - EPITX $A0,$A8
; - NABU $48
; - HEATH $C0,$C8,$D0
@@ -320,7 +320,7 @@ UART_INTRCV1:
LD C,(IY+3) ; LSR PORT TO C
DEC C ; POINT TO MCR PORT
IN A,(C) ; GET MCR VALUE
AND ~%00000010 ; CLEAR RTS
AND ~%00000011 ; CLEAR RTS & DTR
OUT (C),A ; AND SAVE IT
;
UART_INTRCV2:
@@ -412,7 +412,7 @@ UART_INTIN:
LD C,(IY+3) ; LSR PORT TO C
DEC C ; POINT TO MCR PORT
IN A,(C) ; GET MCR VALUE
OR %00000010 ; SET RTS
OR %00000011 ; SET RTS & DTR
OUT (C),A ; AND SAVE IT
;
UART_INTIN1:

View File

@@ -1,7 +1,7 @@
@echo off
setlocal
:: call BuildDisk.cmd bp hd wbw_hd1k
:: call BuildDisk.cmd bp hd wbw_hd1k ..\zsdos\zsys_wbw.sys
:: copy /b hd1k_prefix.dat + ..\..\Binary\hd1k_bp.img + ..\..\Binary\hd1k_cpm22.img + ..\..\Binary\hd1k_zsdos.img + ..\..\Binary\hd1k_nzcom.img + ..\..\Binary\hd1k_cpm3.img + ..\..\Binary\hd1k_zpm3.img + ..\..\Binary\hd1k_ws4.img ..\..\Binary\hd1k_combo_bp.img || exit /b
:: goto :eof

View File

@@ -0,0 +1,207 @@
The version of TE included with RomWBW is provided by Ladislau Szilagyi.
It is distributed from his GitHub repository at
https://github.com/Laci1953/RC2014-CPM/tree/main/System/te%20text%20editor.
RomWBW includes the RomWBW specific version of TE (TEWBW), but is called
just TE. TEWBW is distributed as a hex file. It has already been
converted to a .COM file in the RomWBW distribution.
The following is a copy of the ReadMe file from the TE distribution.
-- WBW 11:14 AM 4/1/2025
# Updated on April 2025
-----------------------------
The text editor TE was written by Miguel Garcia.
It's simple, user friendly, and edits the text in the RAM (it's fast...).
But, because the CP/M's 64KB RAM is limited as capacity (the operating system, the program and the text file must fit inside these 64KB RAM), the original TE allowed only small files to be edited (up to 20K).
I made this adaptation to harness the advantages of being provided with some extra RAM, in certain Z80 hardware platforms.
This version of the text editor TE works on the following hardware environments:
TE64 - any RC2014 with 64KB RAM
TE128 - Z80 systems provided with SC108, SC114, SC118, SC150, SC152 or the Phillip Stevens memory module (128 KB RAM),
TE512 - Z80 systems provided with the 512KB RAM + 512KB ROM module
TEZ80ALL - Z80ALL (25MHz Z80, 4 x 32KB RAM, VGA 48x64, keyboard) (see https://github.com/Laci1953/Software-for-Z80ALL-retro-computer/tree/main/TE)
TES80 - Simple80 (2 x 64KB RAM)
TEWBW - RC2014 running RomWBW
Use the HiTech tools to compile & link the sources.
Settings:
TE64: 64K RAM systems - up to 2048 lines, VT100 compatible, with WordStar style keyboard (accepts also arrow keys)
TE128: 128K RAM systems - up to 4093 lines, VT100 compatible, with WordStar style keyboard (accepts also arrow keys)
TE512: 512K RAM systems - up to 8192 lines, VT100 compatible, with WordStar style keyboard (accepts also arrow keys)
TEZ80ALL: Z80ALL standalone retro computer - up to 8192 lines, VGA 48x64, with WordStar style keyboard (accepts also arrow keys)
TES80: 128K RAM systems - up to 4093 lines, VT100 compatible, with WordStar style keyboard (accepts also arrow keys)
TEWBW: up to 4096 lines, VT100 compatible, with WordStar style keyboard (accepts also arrow keys)
Design details and some constraints:
1. For the 512KB version:
-------------------------
To handle the memory allocation requests, a new memory allocator was written.
How it works:
The 512KB RAM module uses 32 16KB "virtual" RAM pages, mapped to one of 4 "physical" pages 0000-3FFF, 4000-7FFF, 8000-BFFF and C000-FFFF.
Any virtual page can be mapped to any physical page.
The memory physical area from 8000H to BFFFH (let's name-it "work area") is used to load one of the 32 "virtual" 16KB pages from the 512KB RAM, and the memory allocator returns a pointer to the available buffer and a byte containing the index of the 16KB page that contains this buffer (let's name-it "page index").
When that buffer needs to be accessed for read/write operations, the 16KB RAM page must be first loaded into the "work area",
using a function call with the "page index" as parameter.
Of course, to "free" the allocated buffer, this "page index" must be provided too.
Text files up to 400KB can be edited.
The 512KB version can be run on any CP/M version, regardless of its TPA area size.
2. For the 128KB version:
-------------------------
To handle the memory allocation requests, a new memory allocator was written.
How it works:
The 128KB RAM is divided into 2 "virtual" 64KB banks: the lower and the upper bank. A port selects which "virtual" 64KB RAM bank is mapped to the physical 64KB RAM.
In order to execute code that switches from the lower to the upper bank (and back...),
that piece of code must be present at the same physical address in both of banks (the so called "shadow code)".
It is impossible to store shadow code in the upper bank using only programs resident in RAM,
for this only ROM-based code may help; SCM contains an API function ( $2B ) which moves a byte to a given address of the upper RAM bank.
In early SCM version (e.g. v1.0), this API call is not documented (it cannot be found in the SCM manual), I've found-it by browsing through the SCM source code...
Therefore, by using this $2B SCM API call, the shadow code can be moved to the upper RAM bank.
As a second possibility, this routine can be stored also, at a fixed address (7F00H) in the EPROM used to boot CP/M (see https://github.com/Laci1953/RC2014-CPM/tree/main/BOOT ).
But, for the memory allocator, we have also another important constraint: the shadow code must be stored in top of the physical 64KB RAM, in order to offer as much possible RAM available to be allocated (storing at the bottom of the physical 64KB RAM is out of question, we have there the 100H BIOS buffers area). There is only one possible solution: storing a small shadow code on top of CP/M's BIOS. My shadow code is less than 40H.
Studying the "classic" RC2014 CP/M that is currently used with 64/128MB CF's, I discovered that the BIOS "eats" practically all the space to FFFF ! There was no room for my shadow code!
I solved this issue by building a smaller CP/M, for both 64MB & 128MB CF's. You may find this CP/M in the PutSys folder.
The algorithm used to allocate memory is the following: if the usual call to malloc fails, the new allocator accesses the upper 64KB RAM bank and allocates there the buffer.
Besides the address of the buffer, a byte containing the RAM bank index is returned too (0=lower 64KB RAM, 1=upper 64KB RAM).
To access a buffer reserved in the upper 64KB RAM bank, special functions must be used to read/write a byte, a word, or a string.
Text files up to 80KB can be edited.
But, this comes with a cost: when opening a file to be edited, the editor reads all the text and store this text in the dynamic memory, and this takes time, because every single byte that has to be moved to the upper RAM bank is not simply moved, as in case of the lower bank, but is passed to the shadow code in order to be stored in the upper RAM bank. Also, a buffer for every new text line that is read must be allocated, and this allocation means also accessing the shadow code, in order to manage (read/write) the data structures that handle the available memory pool.
Once the file is read, the browse/search operations prove to be quick (compared for example with the performance of WordStar), because no more file read operations are needed, all the text is in the memory.
As a conclusion: the TE editor 128KB version will work only for RC2014 systems provided with my "custom CP/M"
Comparing the two versions of TE (128KB vs. 512KB), the 512KB version is by far the best.
First, the size of files that can be edited is larger (400KB vs. 80KB).
Then, the initial phase of file reading when starting the editor is faster.
But, I consider both versions of the TE editor as a step forward in the right direction, allowing larger files to be edited in memory, with an elegant an efficient user interface.
February 2022
-------------
TE now supports TABs.
The files, when loaded, will be displayed using TABs indentation.
The TAB interval (4 or 8) may be set from the command line: >TE file.ext [ 4 | 8 ] ; default = 8.
March 2023
----------
I made some improvements mainly related to the usability of the tool.
1. First, I opted to display a small help message, in the case when RE is executed without parameters; the message is showing all the available options.
-------------
D>te
TE text editor
Copyright (c) 2015-2021 Miguel Garcia / FloppySoftware
Adapted for 128KB RAM by Ladislau Szilagyi
Use: >TE [options] [filename]
where options (lowercase or uppercase) are:
-Tn (n = 4 or 8) sets the tabs to n spaces, default is 8
-Hnn sets the screen height (up to 99, default is 24)
-Wnnn sets the screen width (up to 200, default is 80)
Continue? (N/n = quit) :
------------
You can press N/n to quit to CP/M, or any other key to continue TE, being presented with an empty screen, ready for text input...
2. Tabs can be used freely in the text; you have two options related to TAB's alignment ( 4 or 8 ); the default is 8.
You can change-it to 4 using the option -T in the command line.
It important to mention that the use of TABs does not increase the size of the text file, nor the size of buffers allocated in memory to store the text; this is because TABs are inflated/deflated to/from blanks only when needed, (e.g.) when displayed on screen.
3. When reading/writing files, a line containing a counter of the lines being processed is displayed, to offer to the user a clue related to the status of the I/O operation.
4. The number of columns/lines can now be selected directly in the command line, using the -W or -H options; default values are 24 for lines, and 80 for columns.
I opted to unify the two versions of source code (128/512), now there is a single set of source files for both 128KB and 512KB TE versions.
As a reminder, the TE128 can edit files with sizes up to 80KB, and TE512 up to 400KB.
April 2023
----------
I made a major improvement, allowing text files with long lines to be processed (lines with up to 145 chars for 80 column screens, up to 115 chars for 64 column screens).
I have now also a TE adapted for Bill Shen's Z80ALL (Z80 at 25MHz, 4 x 32KB RAM, VGA 48x64, keyboard).
Text files up to 64KB can be edited.
This version is fast enough to allow handling large files without the handicap of long waiting interval until the whole file is read - some seconds are enough...
September 2023
--------------
I improved the code related to cursor placement, in the line and up/down between lines; this involves keeping track of TAB's, and assuring that the cursor is always positioned to a position containing a "real" character (e.g. when moving the cursor in a line containing multiple TAB's, the cursor is never placed to a position that does not contain a character or a TAB)
Also, BackSpace behavior was aligned to the above rule.
October 2023
--------------
The 128KB RAM version is now capable to edit text files with size up to 80KB; also, the initial "read file" step is faster.
March 2025
----------
Besides the "arrow" keys (UP, DOWN, LEFT, RIGHT), in the TE version 1.12, also the following keys can be used to move the cursor:
-PgUp (displays the previous page of text),
-PgDn (displays the next page of text),
-Home (displays the first page of text),
-End (displays the last page of text)
Also, here are some clarifications related to the "text blocks handling" feature:
TE is able to select, copy, paste and delete contiguous sets of lines of text (blocks).
Use ^KB to mark the starting line of a block and ^KK to mark the ending line of a block.
Then, you may use block-related operations, e.g.:
Type ^O to copy this block to the clipboard (the block will be displayed on video reverse),
move the cursor to another place in the file and type ^W to paste the block.
April 2025
----------
The TEWBW.HEX file is built to be used on RC2014 computers running RomWBW (version 3.5.0 or later)
The size of the files that can be edited depends on the RomWBW configuration (more exactly on the number of RAM banks available for apps).
For example, if installing RCZ80_std.rom on a RC2014 provided with 512KB ROM + 512KB RAM, we get 3 x 32KB = 96KB available to store the files.
Files up to 4096 lines are accepted.

Binary file not shown.

Binary file not shown.

View File

@@ -7,11 +7,11 @@ from his GitHub repository at https://github.com/Laci1953/Cowgol_on_CP_M.
The COWFE program included here is the RomWBW-specific version that
is tailored to RomWBW memory management.
The primary distribution site for Cowgol 2.0 is at
Ladislau's distribution is derived from Cowgol 2.0 by David Given at
https://github.com/davidgiven/cowgol.
The user manual is available in the Doc/Language directory
Cowgol Language.pdf
The user manual is available in the RomWBW distribution in the
Doc/Language directory. The file is "Cowgol Language.pdf"
The Hi-Tech C compiler components were sourced from the updated
version by Tony Nicholson at https://github.com/agn453/HI-TECH-Z80-C.
@@ -28,7 +28,7 @@ There are two example Cowgol applications included:
application (no assembler or C components). The command
line to build the application is:
COWGOL HEXDUMP.COW
COWGOL -M HEXDUMP.COW
- DYNMSORT demonstrates a sort algorithm and is composed of
Cowgol, C, and assembler components. The command line to
@@ -47,7 +47,7 @@ applications which can be used as follows:
The Adventure game program source has been added. The command to
build the source is:
COWGOL ADVENT.COW ADVMAIN.COW XRND.AS
COWGOL -O MISC.COO STRING.COO RANFILE.COO ADVENT.COW ADVTRAV.COW ADVMAIN.COW
or you can use the SUBMIT file:
@@ -57,3 +57,8 @@ WARNING: You will need to build this application under CP/M 3 because
COWGOL needs more main memory than is available under CP/M 2.2.
-- WBW 11:43 AM 2/25/2024
The Cowgol distribution has been updated based on the latest
release by Ladislau Szilagyi as of 2/25/2025.
-- WBW 1:24 PM 3/29/2025

File diff suppressed because it is too large Load Diff

View File

@@ -1,2 +1,2 @@
COWGOL -O ADVENT.COW ADVMAIN.COW XRND.AS
COWGOL -O MISC.COO STRING.COO RANFILE.COO ADVENT.COW ADVTRAV.COW ADVMAIN.COW


File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,587 @@
##
## This is Daimler's 350-point "Adventure" (circa June 1990, according
## to Russel Dalenberg). Its version information lists
##
## -Conversion to BDS C by J. R. Jaeger
## -Unix standardization by Jerry D. Pohl.
## -OS/2 Conversion by Martin Heller
## -Conversion to TurboC 2.0 by Daimler
##
## It contains Jerry Pohl's original ADVENT.DOC (dated 12 JUNE 1984),
## plus comments from Martin Heller (dated 30-Aug-1988). Strangely for
## an expansion, Daimler's version actually introduces a number of typos
## into the data files, and disables a handful of inessential verbs
## (READ, EAT, FILL) with the comment that there is "no room" for them
## (presumably in the PC's limited memory).
## -------------------------------------------------------------------
## Adapted for HiTech C Z80 under CP/M by Ladislau Szilagyi, Oct. 2023
## Uncommented Daimler's disabled verbs - game is complete again !
## Added a new pseudo-random number generator (Xorshift)
## Adapted to Cowgol language by Ladislau Szilagyi, Feb. 2025
include "misc.coh";
include "string.coh";
@decl sub get_dbugflg(): (ret: int16) @extern("get_dbugflg");
@decl sub bug(n: uint8) @extern("bug");
@decl sub set_newloc(v: int16) @extern("set_newloc");
@decl sub set_oldloc(v: int16) @extern("set_oldloc");
@decl sub set_oldloc2(v: int16) @extern("set_oldloc2");
@decl sub toting(item: uint16): (ret: uint8) @extern("toting");
@decl sub at(item: uint16): (ret: uint8) @extern("at");
@decl sub get_prop(obj: uint8): (ret: int16) @extern("get_prop");
@decl sub badmove(motion: int16, verb: int16) @extern("badmove");
@decl sub rspeak(msg: uint8) @extern("rspeak");
@decl sub spcmove(rdest: uint16) @extern("spcmove");
@decl sub forced(atloc: uint16): (ret: uint8) @extern("forced");
@decl sub set_motion(v: int16) @extern("set_motion");
var dummy: [uint8];
const MAXTRAV := (16+1); # max # of travel directions from loc
# +1 for terminator travel[x].tdest=-1
record trav is
tdest: int16;
tverb: int16;
tcond: int16;
end record;
var travel: trav[MAXTRAV];
# WARNING: the travel array for the cave is stored as MAXLOC
# strings. the strings are an array of 1..MAXTRAV
# LONG INTEGERS. this requires 32 bit LONG INTEGERS.
# these values are used in database.c "gettrav".
# tdset*1000000 + tverb*1000 + tcond = value stored
var cave: [uint8][] :=
{
"2002,2044,2029,3003,3012,3019,3043,4005,4013,4014,4046,4030,5006,5045,5043,8063,",
"1002000,1012000,1007000,1043000,1045000,1030000,5006000,5045000,5046000,",
"1003000,1011000,1032000,1044000,11062000,33065000,79005000,79014000,",
"1004000,1012000,1045000,5006000,5043000,5044000,5029000,7005000,7046000,7030000,8063000,",
"4009000,4043000,4030000,5006050,5007050,5045050,6006000,5044000,5046000,",
"1002000,1045000,4009000,4043000,4044000,4030000,5006000,5046000,",
"1012000,4004000,4045000,5006000,5043000,5044000,8005000,8015000,8016000,8046000,595060000,595014000,595030000,",
"5006000,5043000,5046000,5044000,1012000,7004000,7013000,7045000,9003303,9019303,9030303,593003000,",
"8011303,8029303,593011000,10017000,10018000,10019000,10044000,14031000,11051000,",
"9011000,9020000,9021000,9043000,11019000,11022000,11044000,11051000,14031000,",
"8063303,9064000,10017000,10018000,10023000,10024000,10043000,12025000,12019000,12029000,12044000,3062000,14031000,",
"8063303,9064000,11030000,11043000,11051000,13019000,13029000,13044000,14031000,",
"8063303,9064000,11051000,12025000,12043000,14023000,14031000,14044000,",
"8063303,9064000,11051000,13023000,13043000,20030150,20031150,20034150,15030000,16033000,16044000,",
"1803,1804,1700,1703,1704,1901,1903,1904,2202,2203,2203,2203,2202,2204,1402,3405,",
"14001000,",
"15038000,15043000,596039312,21007412,597041412,597042412,597044412,597069412,27041000,",
"15038000,15011000,15045000,",
"15010000,15029000,15043000,28045311,28036311,29046311,29037311,30044311,30007311,32045000,74049035,32049211,74066000,",
"001000,",
"001000,",
"15001000,",
"67043000,67042000,68044000,68061000,25030000,25031000,648052000,",
"67029000,67011000,",
"23029000,23011000,31056724,26056000,",
"88001000,",
"596039312,21007412,597041412,597042412,597043412,597069412,17041000,40045000,41044000,",
"19038000,19011000,19046000,33045000,33055000,36030000,36052000,",
"19038000,19011000,19045000,",
"19038000,19011000,19043000,62044000,62029000,",
"89001524,90001000,",
"19001000,",
"3065000,28046000,34043000,34053000,34054000,35044000,302071159,100071000,",
"33030000,33055000,15029000,",
"33043000,33055000,20039000,",
"37043000,37017000,28029000,28052000,39044000,65070000,",
"36044000,36017000,38030000,38031000,38056000,",
"37056000,37029000,37011000,595060000,595014000,595030000,595004000,595005000,",
"36043000,36023000,64030000,64052000,64058000,65070000,",
"41001000,",
"42046000,42029000,42023000,42056000,27043000,59045000,60044000,60017000,",
"41029000,42045000,43043000,45046000,80044000,",
"42044000,44046000,45043000,",
"43043000,48030000,50046000,82045000,",
"42044000,43045000,46043000,47046000,87029000,87030000,",
"45044000,45011000,",
"45043000,45011000,",
"44029000,44011000,",
"50043000,51044000,",
"44043000,49044000,51030000,52046000,",
"49044000,50029000,52043000,53046000,",
"50044000,51043000,52046000,53029000,55045000,86030000,",
"51044000,52045000,54046000,",
"53044000,53011000,",
"52044000,55045000,56030000,57043000,",
"55029000,55011000,",
"13030000,13056000,55044000,58046000,83045000,84043000,",
"57043000,57011000,",
"27001000,",
"41043000,41029000,41017000,61044000,62045000,62030000,62052000,",
"60043000,62045000,107046100,",
"60044000,63045000,30043000,61046000,",
"62046000,62011000,",
"39029000,39056000,39059000,65044000,65070000,103045000,103074000,106043000,",
"64043000,66044000,556046080,68061000,556029080,70029050,39029000,556045060,72045075,71045000,556030080,106030000,",
"65047000,67044000,556046080,77025000,96043000,556050050,97072000,",
"66043000,23044000,23042000,24030000,24031000,",
"23046000,69029000,69056000,65045000,",
"68030000,68061000,120046331,119046000,109045000,113075000,",
"71045000,65030000,65023000,111046000,",
"65048000,70046000,110045000,",
"65070000,118049000,73045000,97048000,97072000,",
"72046000,72017000,72011000,",
"19043000,120044331,121044000,75030000,",
"76046000,77045000,",
"75045000,",
"75043000,78044000,66045000,66017000,",
"77046000,",
"3001000,",
"42045000,80044000,80046000,81043000,",
"80044000,80011000,",
"44046000,44011000,",
"57046000,84043000,85044000,",
"57045000,83044000,114050000,",
"83043000,83011000,",
"52029000,52011000,",
"45029000,45030000,",
"25030000,25056000,25043000,20039000,92044000,92027000,",
"25001000,",
"23001000,",
"95045000,95073000,95023000,72030000,72056000,",
"88046000,93043000,94045000,",
"92046000,92027000,92011000,",
"92046000,92027000,92023000,95045309,95003309,95073309,611045000,",
"94046000,94011000,92027000,91044000,",
"66044000,66011000,",
"66048000,72044000,72017000,98029000,98045000,98073000,",
"97046000,97072000,99044000,",
"98050000,98073000,301043000,301023000,100043000,",
"301044000,301023000,301011000,99044000,302071159,33071000,101047000,101022000,",
"100046000,100071000,100011000,",
"103030000,103074000,103011000,",
"102029000,102038000,104030000,618046114,619046115,64046000,",
"103029000,103074000,105030000,",
"104029000,104011000,103074000,",
"64029000,65044000,108043000,",
"131046000,132049000,133047000,134048000,135029000,136050000,137043000,138044000,139045000,61030000,",
"556043095,556045095,556046095,556047095,556048095,556049095,556050095,556029095,556030095,106043000,626044000,",
"69046000,113045000,113075000,",
"71044000,20039000,",
"70045000,50030040,50039040,50056040,53030050,45030000,",
"131049000,132045000,133043000,134050000,135048000,136047000,137044000,138030000,139029000,140046000,",
"109046000,109011000,109109000,",
"84048000,",
"116049000,",
"115047000,593030000,",
"118049000,660041233,660042233,660069233,660047233,661041332,303041000,21039332,596039000,",
"72030000,117029000,",
"69045000,69011000,653043000,65307000,",
"69045000,74043000,",
"74043000,74011000,653045000,653007000,",
"123047000,660041233,660042233,660069233,660049233,303041000,596039000,124077000,126028000,129040000,",
"122044000,124043000,124077000,126028000,129040000,",
"123044000,125047000,125036000,128048000,128037000,128030000,126028000,129040000,",
"124046000,124077000,126045000,126028000,127043000,127017000,",
"125046000,125023000,125011000,124077000,610030000,610039000,",
"125044000,125011000,125017000,124077000,126028000,",
"124045000,124029000,124077000,129046000,129030000,129040000,126028000,",
"128044000,128029000,124077000,130043000,130019000,130040000,130003000,126028000,",
"129044000,124077000,126028000,",
"107044000,132048000,133050000,134049000,135047000,136029000,137030000,138045000,139046000,112043000,",
"107050000,131029000,133045000,134046000,135044000,136049000,137047000,138043000,139030000,112048000,",
"107029000,131030000,132044000,134047000,135049000,136043000,137045000,138050000,139048000,112046000,",
"107047000,131045000,132050000,133048000,135043000,136030000,137046000,138029000,139044000,112049000,",
"107045000,131048000,132030000,133046000,134043000,136044000,137049000,138047000,139050000,112029000,",
"107043000,131044000,132029000,133049000,134030000,135046000,137050000,138048000,139047000,112045000,",
"107048000,131047000,132046000,133030000,134029000,135050000,136045000,138049000,139043000,112044000,",
"107030000,131043000,132047000,133029000,134044000,135045000,136046000,137048000,139049000,112050000,",
"107049000,131050000,132043000,133044000,134045000,135030000,136048000,137029000,138046000,112047000,",
"112045000,112011000,"
};
var caveend: [uint8][] :=
{
"000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
"6000,6000,7000,8000,4000,0000,0000,5000,9150,1150,4150,5150,3150,3150,9000,5000,",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
",",
","
};
# Routine to fill travel array for a given location
sub gettrav(loc: uint8) @extern("gettrav") is
var i: uint8;
var t: int32;
var p1: [uint8];
var q1: [uint8];
var p2: [uint8];
var q2: [uint8];
var buf1: uint8[256];
var buf2: uint8[256];
var aptr: [uint8];
var atrav: uint8[256];
var hasend: uint8 := 1;
dummy := strcpy(&buf1[0], cave[loc - 1]);
p1 := &buf1[0];
dummy := strcpy(&buf2[0], caveend[loc - 1]);
p2 := &buf2[0];
if [p2] == ',' then
hasend := 0;
end if;
aptr := &atrav[0];
q1 := strchr(p1, ',');
while q1 != nil loop
[q1] := 0;
dummy := strcpy(aptr, p1);
p1 := q1 + 1;
if hasend == 1 then
q2 := strchr(p2, ',');
[q2] := 0;
dummy := strcat(aptr, p2);
p2 := q2 + 1;
end if;
q1 := strchr(p1, ',');
#print(aptr); print_nl();
aptr := aptr + strlen(aptr) + 1;
end loop;
[aptr] := 0;
aptr := &atrav[0];
i := 0;
while i < MAXTRAV loop
t := atol(aptr); # convert to long int
travel[i].tcond := (t % 1000) as int16;
t := t / 1000;
travel[i].tverb := (t % 1000) as int16;
t := t / 1000;
travel[i].tdest := (t % 1000) as int16;
aptr := aptr + strlen(aptr) + 1;
if [aptr] == 0 then
i := i + 1;
travel[i].tdest := -1; # end of array
if get_dbugflg() == 1 then
i := 0;
while travel[i].tdest != -1 loop
print("cave[");
print(itoa(loc as int16));
print("] = ");
print(itoa(travel[i].tdest));
print_char(' ');
print(itoa(travel[i].tverb));
print_char(' ');
print(itoa(travel[i].tcond));
print_nl();
i := i + 1;
end loop;
end if;
return;
end if;
i := i + 1;
end loop;
bug(33);
end sub;
# Routine to figure out a new location
# given current location and a motion.
sub dotrav(loc: int16, motion: int16, verb:int16) @extern("dotrav") is
var mvflag: uint8;
var hitflag: uint8;
var kk: uint8;
var rdest: int16;
var rverb: int16;
var rcond: int16;
var robject: int16;
var pctt: uint16;
set_newloc(loc);
mvflag := 0;
hitflag := 0;
pctt := xrnd() % 100;
kk := 0;
while travel[kk].tdest >= 0 and mvflag == 0 loop
rdest := travel[kk].tdest;
rverb := travel[kk].tverb;
rcond := travel[kk].tcond;
robject := rcond % 100;
if get_dbugflg() == 1 then
print("rdest = ");
print(itoa(rdest));
print(", rverb = ");
print(itoa(rverb));
print(", rcond = ");
print(itoa(rcond));
print(", robject = ");
print(itoa(robject));
print(" in dotrav\n");
end if;
if rverb != 1 and rverb != motion and hitflag == 0 then
kk := kk + 1;
continue;
end if;
hitflag := hitflag + 1;
var r := rcond;
r := r / 100;
if r == 3 or r == 4 or r == 5 then r := 7; end if;
case r is
when 0:
if rcond == 0 or pctt < rcond as uint16 then
mvflag := mvflag + 1;
end if;
if rcond == 1 and get_dbugflg() == 1 then
print("%% move ");
print(itoa(pctt as int16));
print_char(' ');
print(itoa(mvflag as int16));
print_nl();
end if;
when 1:
if robject == 0 or toting(robject as uint16) == 1 then
mvflag := mvflag + 1;
end if;
when 2:
if toting(robject as uint16) == 1 or at(robject as uint16) == 1 then
mvflag := mvflag + 1;
end if;
#when 3:
#when 4:
#when 5:
when 7:
if get_prop(robject as uint8) != (rcond/100)-3 then
mvflag := mvflag + 1;
end if;
when else:
bug(37);
end case;
kk := kk + 1;
end loop;
if mvflag == 0 then
badmove(motion, verb);
elseif rdest > 500 then
rspeak((rdest-500) as uint8);
elseif rdest>300 then
spcmove(rdest as uint16);
else
set_newloc(rdest);
if get_dbugflg() == 1 then
print("newloc in dotrav = ");
print(itoa(rdest)); #newloc
print_nl();
end if;
end if;
end sub;
# Routine to copy a travel array
sub copytrv(trav1: [trav], trav2: [trav]) is
var i: uint8;
i := 0;
while i < MAXTRAV loop
[trav2].tdest := [trav1].tdest;
[trav2].tverb := [trav1].tverb;
[trav2].tcond := [trav1].tcond;
trav1 := @next trav1;
trav2 := @next trav2;
i := i + 1;
end loop;
end sub;
# Routine to handle request to return
# from whence we came!
sub goback(loc: int16, oldloc: int16, oldloc2: int16, verb: int16) @extern("goback") is
var kk: uint8;
var k2: uint8;
var want: int16;
var temp: int16;
var strav: trav[MAXTRAV];
if forced(oldloc as uint16) == 1 then
want := oldloc2;
else
want := oldloc;
end if;
set_oldloc2(oldloc);
oldloc2 := oldloc;
set_oldloc(loc);
oldloc := loc;
k2 := 0;
if want == loc then
rspeak(91);
return;
end if;
copytrv(&travel[0], &strav[0]);
kk := 0;
while travel[kk].tdest != 0xFFFF loop
if travel[kk].tcond == 0 and travel[kk].tdest == want then
set_motion(travel[kk].tverb);
dotrav(loc, travel[kk].tverb, verb);
return;
end if;
if travel[kk].tcond == 0 then
k2 := kk;
temp := travel[kk].tdest;
gettrav(temp as uint8);
if forced(temp as uint16) == 1 and travel[0].tdest == want then
k2 := temp as uint8;
end if;
copytrv(&strav[0], &travel[0]);
end if;
kk := kk + 1;
end loop;
if k2 > 0 then
set_motion(travel[k2].tverb);
dotrav(loc, travel[k2].tverb, verb);
else
rspeak(140);
end if;
end sub;

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,32 @@
include "misc.coh";
var fp: int16;
sub factorial(n: int16): (ret: int16) is
var tmp: int16;
if n == 1 then
ret := 1;
else
# ret := n * factorial(n - 1);
@asm "ld hl,(", n, ")";
@asm "push hl";
n := n - 1;
@asm "ld hl,(", n, ")";
@asm "ld ix,(", fp, ")";
@asm "ld de, 1f";
@asm "push de";
@asm "jp (ix)";
@asm "1:";
@asm "ld (", tmp, "),hl"; #tmp = factorial(n-1)
@asm "pop hl";
@asm "ld (", n, "),hl";
ret := n * tmp;
end if;
end sub;
#setup pointer to factorial
@asm "ld hl,", factorial;
@asm "ld (", fp, "),hl";
print_i16(factorial(5));

Binary file not shown.

View File

@@ -1,2 +1,2 @@
COWGOL HEXDUMP.COW
COWGOL -M HEXDUMP.COW


View File

@@ -0,0 +1,17 @@
sub Exit() is
@asm "rst 0";
end sub;
sub MemSet(buf: [uint8], ch: uint8, len: uint16) is
# A=ch, HL=buf
@asm "ld de,(", len, ")"; # DE=len
@asm "jp __MemSet";
end sub;
sub MemCopy(src: [uint8], len: uint16, dest: [uint8]) is
# HL=src
@asm "ld de,(", dest, ")"; # DE=dest
@asm "ld bc,(", len, ")"; # BC=len
@asm "jp __MemCopy";
end sub;

View File

@@ -0,0 +1,19 @@
sub BiosSetup() is
@asm "jp __BiosSetup";
end sub;
sub ConOut(ch: uint8) is
@asm "jp __ConOut";
end sub;
sub ConIn(): (ret: uint8) is
@asm "jp __ConIn";
end sub;
sub ConSts(): (ret: uint8) is
@asm "jp __ConSts";
end sub;
sub putstr(str: [uint8]) is
@asm "jp __putstr";
end sub;

View File

@@ -0,0 +1,35 @@
sub get_char(): (ch: uint8) is
@asm "jp __get_char";
end sub;
sub get_str(buf: [uint8]) is
@asm "jp __get_str";
end sub;
sub print_char(ch: uint8) is
@asm "jp __print_char";
end sub;
sub print(buf: [uint8]) is
@asm "jp __print";
end sub;
sub print_nl() is
@asm "jp __print_nl";
end sub;
sub print_i8(n: int8) is
@asm "jp __print_i8";
end sub;
sub print_i16(n: int16) is
@asm "jp __print_i16";
end sub;
sub print_hex_i8(n: int8) is
@asm "jp __print_hex_i8";
end sub;
sub print_hex_i16(n: int16) is
@asm "jp __print_hex_i16";
end sub;

View File

@@ -0,0 +1,41 @@
sub positive(fp: int16): (ret: int16) is
@asm "jp __positive";
end sub;
sub neg(fp: int16): (ret: int16) is
@asm "jp __neg";
end sub;
sub fpmul(fp1: int16, fp2: int16): (ret: int16) is
# HL=fp1
@asm "ld de,(", fp2, ")"; # DE=fp2
@asm "jp __fpmul";
end sub;
sub fpdiv(fp1: int16, fp2: int16): (ret: int16) is
# HL=fp1
@asm "ld de,(", fp2, ")"; # DE=fp2
@asm "jp __fpdiv";
end sub;
sub fpsqrt(fp: int16): (ret: int16) is
@asm "jp __fpsqrt";
end sub;
sub fpsin(fp: int16): (ret: int16) is
@asm "jp __fpsin";
end sub;
sub fpcos(fp: int16): (ret: int16) is
@asm "jp __fpcos";
end sub;
sub fparctan(fp: int16): (ret: int16) is
@asm "jp __fparctan";
end sub;
sub xdivytofp(x: int16, y: int16): (ret: int16) is
# HL=x
@asm "ld bc,(", y, ")"; # BC=y
@asm "jp __xdivytofp";
end sub;

Binary file not shown.

View File

@@ -0,0 +1,35 @@
sub IsDigit(ch: uint8): (ret: uint8) is
# A=ch
@asm "jp __IsDigit";
end sub;
sub ToLower(c: uint8): (cc: uint8) is
# A=ch
@asm "jp __ToLower";
end sub;
sub CopyString(src: [uint8], dest: [uint8]) is
# HL=src
@asm "ld de,(", dest, ")"; # DE=dest
@asm "jp __CopyString";
end sub;
sub StrCmp(s1: [uint8], s2: [uint8]): (res: int8) is
# HL=s1
@asm "ld de,(", s2, ")"; # DE=s2
@asm "jp __StrCmp";
end sub;
sub StrICmp(s1: [uint8], s2: [uint8]): (res: int8) is
# HL=s1
@asm "ld de,(", s2, ")"; # DE=s2
@asm "jp __StrICmp";
end sub;
sub StrLen(s: [uint8]): (size: uint16) is
# HL = s
@asm "jp __StrLen";
end sub;

View File

@@ -1,23 +1,23 @@
int L[500], R[500];
// Merges two subarrays of arr[].
// First subarray is arr[l..m]
// Second subarray is arr[m+1..r]
/* Merges two subarrays of arr[].
First subarray is arr[l..m]
Second subarray is arr[m+1..r] */
void merge(int arr[], int l, int m, int r)
{
int i, j, k;
int n1 = m - l + 1;
int n2 = r - m;
// Copy data to temp arrays L[] and R[]
/* Copy data to temp arrays L[] and R[] */
for (i = 0; i < n1; i++)
L[i] = arr[l + i];
for (j = 0; j < n2; j++)
R[j] = arr[m + 1 + j];
// Merge the temp arrays back into arr[l..r
/* Merge the temp arrays back into arr[l..r] */
i = 0;
j = 0;
k = l;
@@ -38,8 +38,7 @@ void merge(int arr[], int l, int m, int r)
k++;
}
// Copy the remaining elements of L[],
// if there are any
/* Copy the remaining elements of L[], if there are any */
while (i < n1)
{
arr[k] = L[i];
@@ -47,8 +46,7 @@ void merge(int arr[], int l, int m, int r)
k++;
}
// Copy the remaining elements of R[],
// if there are any
/* Copy the remaining elements of R[], if there are any */
while (j < n2)
{
arr[k] = R[j];
@@ -57,9 +55,9 @@ void merge(int arr[], int l, int m, int r)
}
}
// l is for left index and r is right index of the
// sub-array of arr to be sorted
// first call with l = 0, r = sizeof(arr) - 1
/* l is for left index and r is right index of the
sub-array of arr to be sorted
first call with l = 0, r = sizeof(arr) - 1 */
void mergeSort(int arr[], int l, int r)
{
int m;
@@ -68,7 +66,7 @@ void mergeSort(int arr[], int l, int r)
{
m = l + (r - l) / 2;
// Sort first and second halves
/* Sort first and second halves */
mergeSort(arr, l, m);
mergeSort(arr, m + 1, r);

View File

@@ -0,0 +1,36 @@
@decl sub exit() @extern("exit");
@decl sub get_char(): (c: uint8) @extern("get_char");
@decl sub get_line(p: [uint8]) @extern("get_line");
@decl sub print_char(c: uint8) @extern("print_char");
@decl sub print(ptr: [uint8]) @extern("print");
@decl sub print_nl() @extern("print_nl");
@decl sub print_hex_i8(char: uint8) @extern("print_hex_i8");
@decl sub print_hex_i16(word: uint16) @extern("print_hex_i16");
@decl sub print_hex_i32(dword: uint32) @extern("print_hex_i32");
@decl sub print_i8(v: int8) @extern("print_i8");
@decl sub print_i16(v: int16) @extern("print_i16");
@decl sub isdigit(ch: uint8): (ret: uint8) @extern("isdigit");
@decl sub itoa(i: int16): (pbuf: [uint8]) @extern("itoa");
@decl sub uitoa(i: uint16): (pbuf: [uint8]) @extern("uitoa");
@decl sub ltoa(i: int32): (pbuf: [uint8]) @extern("ltoa");
@decl sub atoi(p: [uint8]): (ret: int16) @extern("atoi");
@decl sub atol(p: [uint8]): (ret: int32) @extern("atol");
@decl sub atofixed(p: [uint8]): (ret: uint16) @extern("atofixed");
# fdigits: number of digits in fractional part
@decl sub fixedtoa(f: uint16, fdigits: uint8): (ret: [uint8]) @extern("fixedtoa");
@decl sub memcpy(dest: [uint8], src: [uint8], size: uint16): (ret: [uint8]) @extern("memcpy");
@decl sub memset(dest: [uint8], char: uint8, size: uint16): (ret: [uint8]) @extern("memset");
@decl sub xrnd() :(ret: uint16) @extern("xrnd");
@decl sub xrndseed() @extern("xrndseed");
@decl sub ArgvInit() @extern("ArgvInit");
@decl sub ArgvNext(): (arg: [uint8]) extern("ArgvNext");

Binary file not shown.

View File

@@ -0,0 +1,646 @@
sub exit() @extern("exit") is
@asm "rst 0";
end sub;
sub get_char(): (c: uint8) @extern("get_char") is
@asm "ld c, 1";
@asm "call 5";
@asm "ld (", c, "), a";
end sub;
sub print_char(c: uint8) @extern("print_char") is
if c == 10 then
@asm "ld e, 13";
@asm "ld c, 2";
@asm "call 5";
end if;
@asm "ld a, (", c, ")";
@asm "ld e, a";
@asm "ld c, 2";
@asm "call 5";
end sub;
sub print(ptr: [uint8]) @extern("print") is
var ch: uint8;
@asm "ld hl,(", ptr, ")";
@asm "1:";
@asm "ld a,(hl)";
@asm "or a";
@asm "ret z";
@asm "ld (", ch, "), a";
@asm "push hl";
print_char(ch);
@asm "pop hl";
@asm "inc hl";
@asm "jr 1b";
end sub;
sub print_nl() @extern("print_nl") is
print_char('\n');
end sub;
sub print_hex_i8(char: uint8) @extern("print_hex_i8") is
var ra: uint8;
@asm "call Bin2Hex";
@asm "push bc";
@asm "ld (", ra, "),a";
print_char(ra);
@asm "pop bc";
@asm "ld a,c";
@asm "ld (", ra, "),a";
print_char(ra);
@asm "ret";
@asm "Bin2Hex:";
@asm "ld c,a";
@asm "and 0FH";
@asm "call nibble2hex";
@asm "ld a,c";
@asm "ld c,b";
@asm "and 0F0H";
@asm "rrca";
@asm "rrca";
@asm "rrca";
@asm "rrca";
@asm "nibble2hex:";
@asm "add a,090h";
@asm "daa";
@asm "adc a,040h";
@asm "daa";
@asm "ld b,a";
@asm "ret";
end sub;
sub print_hex_i16(word: uint16) @extern("print_hex_i16") is
var ra: uint8;
@asm "ld a,(", word, "+1)";
@asm "ld (", ra, "),a";
print_hex_i8(ra);
@asm "ld a,(", word, ")";
@asm "ld (", ra, "),a";
print_hex_i8(ra);
end sub;
sub print_hex_i32(dword: uint32) @extern("print_hex_i32") is
var v16: uint16;
@asm "ld hl,(", dword, "+2)";
@asm "ld (", v16, "),hl";
print_hex_i16(v16);
@asm "ld hl,(", dword, ")";
@asm "ld (", v16, "),hl";
print_hex_i16(v16);
end sub;
sub Bn2Dec() is
@asm "ld (bufptr),hl";
@asm "ld (buffer),hl";
@asm "ex de,hl";
@asm "xor a";
@asm "ld (curlen),a";
@asm "cnvert:";
@asm "ld e,0";
@asm "ld b,16";
@asm "or a";
@asm "dvloop:";
@asm "rl l";
@asm "rl h";
@asm "rl e";
@asm "ld a,e";
@asm "sub 10";
@asm "ccf";
@asm "jr nc,deccnt";
@asm "ld e,a";
@asm "deccnt:";
@asm "djnz dvloop";
@asm "rl l";
@asm "rl h";
@asm "chins:";
@asm "ld a,e";
@asm "add a,30h";
@asm "call insert";
@asm "ld a,h";
@asm "or l";
@asm "jr nz,cnvert";
@asm "ld hl,(buffer)";
@asm "ld c,(hl)";
@asm "ld b,0";
@asm "ld d,h";
@asm "ld e,l";
@asm "inc hl";
@asm "ldir";
@asm "xor a";
@asm "ld (de),a";
@asm "ret";
@asm "insert:";
@asm "push hl";
@asm "push af";
@asm "ld hl,(bufptr)";
@asm "ld d,h";
@asm "ld e,l";
@asm "inc de";
@asm "ld (bufptr),de";
@asm "ld a,(curlen)";
@asm "or a";
@asm "jr z,exitmr";
@asm "ld c,a";
@asm "ld b,0";
@asm "lddr";
@asm "exitmr:";
@asm "ld a,(curlen)";
@asm "inc a";
@asm "ld (curlen),a";
@asm "ld (hl),a";
@asm "ex de,hl";
@asm "pop af";
@asm "ld (hl),a";
@asm "pop hl";
@asm "ret";
@asm "buffer: defs 2";
@asm "bufptr: defs 2";
@asm "curlen: defs 1";
end sub;
var buf12:uint8[12];
sub print_i8(v: int8) @extern("print_i8") is
@asm "ld hl,", buf12 ;
@asm "ld a,(", v, ")";
@asm "or a";
@asm "jp p,1f";
@asm "ld (hl),'-'";
@asm "inc hl";
@asm "neg";
@asm "1:";
@asm "ld e,a";
@asm "ld d,0";
Bn2Dec();
print(&buf12[0]);
@asm "ret";
end sub;
sub print_i16(v: int16) @extern("print_i16") is
@asm "ld hl,", buf12 ;
@asm "ld de,(", v, ")";
@asm "bit 7,d";
@asm "jr z,1f";
@asm "xor a";
@asm "ld hl,0";
@asm "sbc hl,de";
@asm "ex de,hl";
@asm "ld hl,", buf12 ;
@asm "ld (hl),'-'";
@asm "inc hl";
@asm "1:";
Bn2Dec();
print(&buf12[0]);
@asm "ret";
end sub;
sub get_line(p: [uint8]) @extern("get_line") is
var ch: uint8;
loop
ch := get_char();
if ch == '\r' then
print_nl();
[p] := 0;
return;
end if;
[p] := ch;
p := p + 1;
end loop;
end sub;
sub itoa(i: int16): (pbuf: [uint8]) @extern("itoa") is
var sign: uint8;
pbuf := &buf12[8]; # points to terminating zero
[pbuf] := 0;
if (i >= 0) then
sign := 0;
else
i := -i; sign := 1;
end if;
loop
pbuf := pbuf - 1;
[pbuf] := '0' + ((i % 10) as uint8);
i := i / 10;
if i == 0 then break; end if;
end loop;
if (sign == 1) then
pbuf := pbuf - 1; [pbuf] := '-';
end if;
end sub;
sub uitoa(i: uint16): (pbuf: [uint8]) @extern("uitoa") is
pbuf := &buf12[8]; # points to terminating zero
[pbuf] := 0;
loop
pbuf := pbuf - 1;
[pbuf] := '0' + ((i % 10) as uint8);
i := i / 10;
if i == 0 then break; end if;
end loop;
end sub;
sub ltoa(i: int32): (pbuf: [uint8]) @extern("ltoa") is
var sign: uint8 := 0;
if i < 0 then
sign := 1;
end if;
pbuf := &buf12[11]; # points to terminating zero
[pbuf] := 0;
loop
pbuf := pbuf - 1;
[pbuf] := '0' + ((i % 10) as uint8);
i := i / 10;
if i == 0 then break; end if;
end loop;
if sign == 1 then
pbuf := pbuf - 1;
[pbuf] := '-';
end if;
end sub;
sub isdigit(ch: uint8): (ret: uint8) @extern("isdigit") is
@asm "ld a,(", ch, ")";
@asm "cp 30h";
@asm "jr c,1f";
@asm "cp 3Ah";
@asm "jr nc,1f";
@asm "ld a,1";
@asm "ret";
@asm "1:";
@asm "xor a";
@asm "ret";
end sub;
sub atoi(p: [uint8]): (ret: int16) @extern("atoi") is
var sign: uint8 := 0;
ret := 0;
if [p] == '-' then
sign := 1;
p := p + 1;
elseif [p] == '+' then
p := p + 1;
end if;
while [p] != 0 loop
if isdigit([p]) == 1 then
ret := ret * 10 + (([p] - '0') as int16);
p := p + 1;
else
break;
end if;
end loop;
if sign == 1 then
ret := -ret;
end if;
end sub;
sub atol(p: [uint8]): (ret: int32) @extern("atol") is
var sign: uint8 := 0;
ret := 0;
if [p] == '-' then
sign := 1;
p := p + 1;
end if;
while [p] != 0 loop
if isdigit([p]) == 1 then
ret := ret * 10 + (([p] - '0') as int32); p := p + 1;
else
ret := -1; return;
end if;
end loop;
if sign == 1 then
ret := -ret;
end if;
end sub;
# accepts [+|-]iii[.ddd] min -127.999 max 127.999
sub atofixed(p: [uint8]): (ret: uint16) @extern("atofixed") is
var intp: int16 := 0;
var dec: uint16 := 0;
var sign: uint8 := 0;
var i: uint8;
sub check_int(): (isok: uint8) is
isok := 1;
if intp > 127 then
ret := 0;
isok := 0;
end if;
end sub;
sub set_sign() is
if sign == 1 then
intp := -intp;
end if;
end sub;
sub get_dec(): (isok: uint8) is
var s16: uint16 := 0;
var f: uint16 := 1000;
i := 0;
while i<3 loop
if isdigit([p]) == 1 then
s16 := s16 + ([p] - '0') as uint16 * f;
f := f / 10;
p := p + 1;
elseif [p] == 0 then
if s16 == 0 then isok := 1; return; end if;
break;
else
isok := 0;
return;
end if;
i := i + 1;
end loop;
if s16 >= 5000 then
dec := dec | 0b10000000;
s16 := s16 - 5000;
end if;
if s16 >= 2500 then
dec := dec | 0b01000000;
s16 := s16 - 2500;
end if;
if s16 >= 1250 then
dec := dec | 0b00100000;
s16 := s16 - 1250;
end if;
if s16 >= 0625 then
dec := dec | 0b00010000;
s16 := s16 - 0625;
end if;
if s16 >= 0312 then
dec := dec | 0b00001000;
s16 := s16 - 0312;
end if;
if s16 >= 0156 then
dec := dec | 0b00000100;
s16 := s16 - 0156;
end if;
if s16 >= 0078 then
dec := dec | 0b00000010;
s16 := s16 - 0078;
end if;
if s16 >= 0039 then
dec := dec | 0b00000001;
end if;
isok := 1;
end sub;
if [p] == '+' then
p := p + 1;
elseif [p] == '-' then
sign := 1;
p := p + 1;
end if;
i := 0;
while i < 3 loop
if isdigit([p]) == 1 then
intp := intp * 10;
intp := intp + ([p] - '0') as int16;
p := p + 1;
elseif [p] == '.' then
p := p + 1;
if check_int() == 0 then return; end if;
set_sign();
if get_dec() == 0 then return; end if;
ret := (intp << 8) as uint16 | dec;
return;
elseif [p] == 0 then
if check_int() == 0 then return; end if;
set_sign();
ret := (intp << 8) as uint16;
return;
else
ret := 0;
return;
end if;
i := i + 1;
end loop;
if check_int() == 0 then return; end if;
if [p] == '.' then
p := p + 1;
set_sign();
if get_dec() == 0 then return; end if;
ret := (intp << 8) as uint16 | dec;
elseif [p] == 0 then
set_sign();
ret := (intp << 8) as uint16;
else
ret := 0;
end if;
end sub;
sub fixedtoa(f: uint16, fdigits: uint8): (ret: [uint8]) @extern("fixedtoa") is
var intp: int8;
var sign: uint8 := 0;
var dec: uint8;
var vdec: uint32 := 0;
var pbuf: [uint8] := &buf12[4]; # position of .
var i: uint8;
if fdigits > 3 then fdigits := 3; end if;
intp := (f >> 8) as int8;
dec := f as uint8;
if intp < 0 then
intp := - intp;
sign := 1;
end if;
#first the integer part, without leading zeros
loop
pbuf := pbuf - 1;
[pbuf] := '0' + ((intp % 10) as uint8);
intp := intp / 10;
if intp == 0 then break; end if;
end loop;
if (sign == 1) then
pbuf := pbuf - 1; [pbuf] := '-';
end if;
ret := pbuf; #to be returned...
#fractional part requested...?
if fdigits == 0 then
buf12[4] := 0; #...no, keep only the integer part
return;
end if;
#...yes, build fractional part
pbuf := &buf12[4];
[pbuf] := '.';
if dec & 0b00000001 != 0 then vdec := vdec + 00390625; end if;
if dec & 0b00000010 != 0 then vdec := vdec + 00781250; end if;
if dec & 0b00000100 != 0 then vdec := vdec + 01562500; end if;
if dec & 0b00001000 != 0 then vdec := vdec + 03125000; end if;
if dec & 0b00010000 != 0 then vdec := vdec + 06250000; end if;
if dec & 0b00100000 != 0 then vdec := vdec + 12500000; end if;
if dec & 0b01000000 != 0 then vdec := vdec + 25000000; end if;
if dec & 0b10000000 != 0 then vdec := vdec + 50000000; end if;
vdec := vdec / 100000; #keep only the 3 top digits
pbuf := &buf12[8];
i := 0;
while i < 3 loop
pbuf := pbuf - 1;
[pbuf] := '0' + ((vdec % 10) as uint8);
vdec := vdec / 10;
i := i + 1;
end loop;
# keep only 'fdigits' digits
buf12[4+fdigits+1] := 0;
end sub;
sub memcpy(dest: [uint8], src: [uint8], size: uint16): (ret: [uint8]) @extern("memcpy") is
@asm "ld hl,(", src, ")";
@asm "ld de,(", dest, ")";
@asm "ld bc,(", size, ")";
@asm "push de";
@asm "ld a,b";
@asm "or c";
@asm "jr z,1f";
@asm "ldir";
@asm "1:";
@asm "pop hl";
@asm "ret";
end sub;
sub memset(dest: [uint8], char: uint8, size: uint16): (ret: [uint8]) @extern("memset") is
@asm "ld hl,(", dest, ")";
@asm "ld bc,(", size, ")";
@asm "ld a,(", char, ")";
@asm "ld e,a";
@asm "push hl";
@asm "2:";
@asm "ld a,b";
@asm "or c";
@asm "jr z,1f";
@asm "ld (hl),e";
@asm "inc hl";
@asm "dec bc";
@asm "jr 2b";
@asm "1:";
@asm "pop hl";
@asm "ret";
end sub;
var random: uint16;
sub xrnd(): (ret: uint16) @extern("xrnd") is
@asm " ld hl,(", random, ")";
@asm " ld a,h ";
@asm " rra ";
@asm " ld a,l ";
@asm " rra ";
@asm " xor h ";
@asm " ld h,a ";
@asm " ld a,l ";
@asm " rra ";
@asm " ld a,h ";
@asm " rra ";
@asm " xor l ";
@asm " ld l,a ";
@asm " xor h ";
@asm " ld h,a ";
@asm " ld (", random, "),hl ";
@asm " res 7,h ";
@asm " ld (", ret, "),hl";
@asm " ret ";
end sub;
sub xrndseed() @extern("xrndseed") is
@asm " ld a,r ";
@asm " ld l,a ";
@asm " ld a,r ";
@asm " ld h,a ";
@asm " or l ";
@asm " jr nz,1f ";
@asm " inc hl ";
@asm " 1: ";
@asm " ld (", random, "),hl ";
@asm " ret ";
end sub;
var argv_pointer: [uint8];
sub ArgvInit() @extern("ArgvInit") is
argv_pointer := 0x81 as [uint8];
[argv_pointer + [0x80 as [uint8]] as intptr] := 0;
end sub;
# Returns null is there's no next argument.
sub ArgvNext(): (arg: [uint8]) extern("ArgvNext") is
# No more arguments?
if argv_pointer == (0 as [uint8]) then
arg := argv_pointer;
return;
end if;
# Skip leading whitespace.
var c: uint8;
loop
c := [argv_pointer];
if c != ' ' then
break;
end if;
argv_pointer := argv_pointer + 1;
end loop;
arg := argv_pointer;
# Skip to end of word and terminate.
loop
c := [argv_pointer];
if (c == ' ') or (c == '\n') or (c == 0) then
break;
end if;
argv_pointer := argv_pointer + 1;
end loop;
[argv_pointer] := 0;
if c == ' ' then
argv_pointer := argv_pointer + 1;
else
argv_pointer := 0 as [uint8];
end if;
end sub;

Binary file not shown.

View File

@@ -0,0 +1,10 @@
@decl sub FCBOpenIn(fcb: [FCB], filename: [uint8]): (errno: uint8) @extern("FCBOpenIn");
@decl sub FCBOpenUp(fcb: [FCB], filename: [uint8]): (errno: uint8) @extern("FCBOpenUp");
@decl sub FCBOpenOut(fcb: [FCB], filename: [uint8]): (errno: uint8) @extern("FCBOpenOut");
@decl sub FCBClose(fcb: [FCB]): (errno: uint8) @extern("FCBClose");
@decl sub FCBSeek(fcb: [FCB], pos: uint32) @extern("FCBSeek");
@decl sub FCBPos(fcb: [FCB]): (pos: uint32) @extern("FCBPos");
@decl sub FCBExt(fcb: [FCB]): (len: uint32) @extern("FCBExt");
@decl sub FCBGetChar(fcb: [FCB]): (c: uint8) @extern("FCBGetChar");
@decl sub FCBPutChar(fcb: [FCB], c: uint8) @extern("FCBPutChar");

Binary file not shown.

View File

@@ -0,0 +1,214 @@
sub memset(dest: [uint8], char: uint8, size: uint16) is
@asm "ld hl,(", dest, ")";
@asm "ld bc,(", size, ")";
@asm "ld a,(", char, ")";
@asm "ld e,a";
@asm "2:";
@asm "ld a,b";
@asm "or c";
@asm "ret z";
@asm "ld (hl),e";
@asm "inc hl";
@asm "dec bc";
@asm "jr 2b";
end sub;
# file I/O support ---------------------------------------------------------
record CpmFCB is
dr: uint8;
f: uint8[11];
ex: uint8;
s1: uint8;
s2: uint8;
rc: uint8;
d: uint8[16];
cr: uint8;
r: uint16;
r2: uint8;
end record;
record FCB is
bufferptr: uint8; # byte just read
dirty: uint8;
cpm: CpmFCB;
buffer: uint8[128];
end record;
sub file_i_init(fcb: [FCB], filename: [uint8]) is
sub fill(dest: [uint8], src: [uint8], len: uint8): (srcout: [uint8]) is
loop
var c := [src];
if (c < 32) or (c == '.') then
c := ' ';
elseif (c == '*') then
c := '?';
else
src := src + 1;
end if;
if (c >= 'a') and (c <= 'z') then
c := c - ('a' - 'A');
end if;
[dest] := c;
dest := dest + 1;
len := len - 1;
if len == 0 then
break;
end if;
end loop;
srcout := src;
end sub;
memset(fcb as [uint8], 0, @bytesof FCB);
memset(&fcb.cpm.f[0] as [uint8], ' ', 11);
filename := fill(&fcb.cpm.f[0], filename, 8);
var c: uint8;
loop
c := [filename];
if (c < 32) or (c == '.') then
break;
end if;
filename := filename + 1;
end loop;
if c == '.' then
filename := fill(&fcb.cpm.f[8], filename+1, 3);
end if;
fcb.cpm.r := 0xffff;
fcb.bufferptr := 127;
end sub;
sub fcb_i_gbpb(fcb: [FCB], c: uint8) is
var cpmfcb := &fcb.cpm;
var dma := &fcb.buffer[0];
@asm "ld c, 26"; # SET DMA
@asm "ld de, (", dma, ")";
@asm "call 5";
@asm "ld a, (", c, ")";
@asm "ld c, a";
@asm "ld de, (", cpmfcb, ")";
@asm "call 5";
end sub;
sub fcb_i_blockin(fcb: [FCB]) is
memset(&fcb.buffer[0], 0, 128);
fcb_i_gbpb(fcb, 33); # READ RANDOM
fcb.dirty := 0;
end sub;
sub fcb_i_blockout(fcb: [FCB]) is
if fcb.dirty != 0 then
fcb_i_gbpb(fcb, 34); # WRITE RANDOM
fcb.dirty := 0;
end if;
end sub;
sub fcb_i_changeblock(fcb: [FCB], newblock: uint16) is
if newblock != fcb.cpm.r then
fcb_i_blockout(fcb);
fcb.cpm.r := newblock;
fcb_i_blockin(fcb);
end if;
end sub;
sub fcb_a_to_error() is
@asm "cp 0xff";
@asm "ld a, 0";
@asm "ret nz";
@asm "inc a";
end sub;
sub FCBOpenIn(fcb: [FCB], filename: [uint8]): (errno: uint8) @extern("FCBOpenIn") is
file_i_init(fcb, filename);
var cpmfcb := &fcb.cpm;
@asm "ld c, 15"; # OPEN_FILE
@asm "ld de, (", cpmfcb, ")";
@asm "call 5";
@asm "call", fcb_a_to_error;
@asm "ld (", errno, "), a";
end sub;
sub FCBOpenUp(fcb: [FCB], filename: [uint8]): (errno: uint8) @extern("FCBOpenUp") is
(errno) := FCBOpenIn(fcb, filename);
end sub;
sub FCBOpenOut(fcb: [FCB], filename: [uint8]): (errno: uint8) @extern("FCBOpenOut") is
file_i_init(fcb, filename);
var cpmfcb := &fcb.cpm;
@asm "ld c, 19"; # DELETE_FILE
@asm "ld de, (", cpmfcb, ")";
@asm "call 5";
@asm "ld c, 22"; # CREATE_FILE
@asm "ld de, (", cpmfcb, ")";
@asm "call 5";
@asm "call", fcb_a_to_error;
@asm "ld (", errno, "), a";
end sub;
sub FCBClose(fcb: [FCB]): (errno: uint8) @extern("FCBClose") is
fcb_i_blockout(fcb);
var cpmfcb := &fcb.cpm;
@asm "ld c, 16"; # CLOSE_FILE
@asm "ld de, (", cpmfcb, ")";
@asm "call 5";
@asm "call", fcb_a_to_error;
@asm "ld (", errno, "), a";
end sub;
sub FCBSeek(fcb: [FCB], pos: uint32) @extern("FCBSeek") is
pos := pos - 1; # seek to *previous* character
var newblock := (pos >> 7) as uint16;
var newptr := (pos as uint8) & 127;
fcb_i_changeblock(fcb, newblock);
fcb.bufferptr := newptr;
end sub;
sub FCBPos(fcb: [FCB]): (pos: uint32) @extern("FCBPos") is
pos := (((fcb.cpm.r as uint32) << 7) | (fcb.bufferptr as uint32)) + 1;
end sub;
sub FCBExt(fcb: [FCB]): (len: uint32) @extern("FCBExt") is
var oldblock := fcb.cpm.r;
var cpmfcb := &fcb.cpm;
@asm "ld c, 16"; # CLOSE_FILE (actually flushing it to disk)
@asm "ld de, (", cpmfcb, ")";
@asm "call 5";
@asm "ld c, 35"; # COMPUTE FILE SIZE
@asm "ld de, (", cpmfcb, ")";
@asm "call 5";
len := ([&fcb.cpm.r as [uint32]] & 0x00ffffff) << 7;
fcb.cpm.r := oldblock;
end sub;
sub fcb_i_nextchar(fcb: [FCB]) is
fcb.bufferptr := fcb.bufferptr + 1;
if fcb.bufferptr == 128 then
fcb_i_changeblock(fcb, fcb.cpm.r + 1);
fcb.bufferptr := 0;
end if;
end sub;
sub FCBGetChar(fcb: [FCB]): (c: uint8) @extern("FCBGetChar") is
fcb_i_nextchar(fcb);
c := fcb.buffer[fcb.bufferptr];
end sub;
sub FCBPutChar(fcb: [FCB], c: uint8) @extern("FCBPutChar") is
fcb_i_nextchar(fcb);
fcb.buffer[fcb.bufferptr] := c;
fcb.dirty := 1;
end sub;
# ---------------------------------------------------------

View File

@@ -0,0 +1,63 @@
# CP/M Z80 sequential files
#
# supports two kind of files: text files (0x1A is EOF) & binary files (0 is EOF)
#
# FCBOpenIn : opens specified existing file for read (type: IO_TEXT or IO_BIN)
# FCBOpenOut : opens new, empty specified file for write (creates file) (type: IO_TEXT or IO_BIN)
# FCBOpenInOut : opens existing specified file for read/write (just opens, NOT creates file) (type: IO_TEXT or IO_BIN)
# FCBOpenForAppend : opens existing specified binary file for write & positions the write cursor after the last actual 128-bytes record,
# : or creates a new, empty binary file, if the specified file was not found
# FCBClose : closes the specified file (writing all the file data to disk if the file was opened for write)
# FCBRewind : equivalent to FCBClose + FCBOpenIn, works only for files already opened for read
# FCBGetChar : reads a byte from a file already opened for read or read/write
# FCBPutChar : writes a byte to a file already opened for write or read/write
#
record CpmFCB is
dr: uint8;
f: uint8[11];
ex: uint8;
s1: uint8;
s2: uint8;
rc: uint8;
d: uint8[16];
cr: uint8;
r0: uint8;
r1: uint8;
r2: uint8;
end record;
record FCB is
bufferptr: uint8; # offset in buffer
iotype: uint8;
datatype: uint8;
cpm: CpmFCB;
buffer: uint8[128];
end record;
# file types
const IO_TEXT := 0;
const IO_BIN := 1;
# I/O return codes (error numbers)
const SUCCESS := 0;
const ERR_NO_FILE := 1;
const ERR_BAD_IO := 2;
const ERR_DIR_FULL := 3;
const ERR_DISK_FULL := 4;
const ERR_EOF := 5;
@decl sub FCBOpenIn(fcb: [FCB], filename: [uint8], filetype: uint8): (errno: uint8) @extern("FCBOpenIn");
@decl sub FCBOpenOut(fcb: [FCB], filename: [uint8], filetype: uint8): (errno: uint8) @extern("FCBOpenOut");
@decl sub FCBOpenInOut(fcb: [FCB], filename: [uint8], filetype: uint8): (errno: uint8) @extern("FCBOpenInOut");
#only for binary files
@decl sub FCBOpenForAppend(fcb: [FCB], filename: [uint8]): (errno: uint8) @extern("FCBOpenForAppend");
@decl sub FCBGetChar(fcb: [FCB]): (c: uint8, errno: uint8) @extern("FCBGetChar");
@decl sub FCBPutChar(fcb: [FCB], c: uint8): (errno: uint8) @extern("FCBPutChar");
@decl sub FCBClose(fcb: [FCB]): (errno: uint8) @extern("FCBClose");
# only for files open for READ
@decl sub FCBRewind(fcb: [FCB]): (errno: uint8) @extern("FCBRewind");

Binary file not shown.

View File

@@ -0,0 +1,390 @@
const IO_READ := 0;
const IO_WRITE := 1;
const IO_READ_WRITE := 2;
const IO_TEXT := 0;
const IO_BIN := 1;
const SUCCESS := 0;
const ERR_NO_FILE := 1;
const ERR_BAD_IO := 2;
const ERR_DIR_FULL := 3;
const ERR_DISK_FULL := 4;
const ERR_EOF := 5;
const CHAR_EOF := 0x1A;
record CpmFCB is
dr: uint8;
f: uint8[11];
ex: uint8;
s1: uint8;
s2: uint8;
rc: uint8;
d: uint8[16];
cr: uint8;
r0: uint8;
r1: uint8;
r2: uint8;
end record;
record FCB is
bufferptr: uint8; # offset in buffer
iotype: uint8;
datatype: uint8;
cpm: CpmFCB;
buffer: uint8[128];
end record;
sub MemSet(p:[uint8], char:uint8, size:uint16) is
@asm "ld a,(", char, ")";
@asm "ld de,(", size, ")";
@asm "ld hl,(", p, ")";
@asm "ld c,a";
@asm "loopm:";
@asm "ld a,e";
@asm "or d";
@asm "ret z";
@asm "ld (hl),c";
@asm "inc hl";
@asm "dec de";
@asm "jr loopm";
end sub;
sub MemCopy(src: [uint8], size: intptr, dest: [uint8]) is
@asm "ld de,(", dest, ")";
@asm "ld hl,(", src, ")";
@asm "ld bc,(", size, ")";
@asm "ld a,b";
@asm "or c";
@asm "ret z";
@asm "ldir";
@asm "ret";
end sub;
sub fcb_init(fcb: [FCB], filename: [uint8]) is
sub fill(dest: [uint8], src: [uint8], len: uint8): (srcout: [uint8]) is
loop
var c := [src];
if (c < 32) or (c == '.') then
c := ' ';
elseif (c == '*') then
c := '?';
else
src := src + 1;
end if;
if (c >= 'a') and (c <= 'z') then
c := c - ('a' - 'A');
end if;
[dest] := c;
dest := dest + 1;
len := len - 1;
if len == 0 then
break;
end if;
end loop;
srcout := src;
end sub;
MemSet(fcb as [uint8], 0, @bytesof FCB);
MemSet(&fcb.cpm.f[0] as [uint8], ' ', 11);
filename := fill(&fcb.cpm.f[0], filename, 8);
var c: uint8;
loop
c := [filename];
if (c < 32) or (c == '.') then
break;
end if;
filename := filename + 1;
end loop;
if c == '.' then
filename := fill(&fcb.cpm.f[8], filename+1, 3);
end if;
end sub;
sub FCBOpenIn(fcb: [FCB], filename: [uint8], type: uint8): (errno: uint8) @extern("FCBOpenIn") is
var cpmfcb := &fcb.cpm;
var cpmerr: uint8;
fcb_init(fcb, filename);
fcb.iotype := IO_READ;
fcb.datatype := type;
@asm "ld c, 15"; # OPEN_FILE
@asm "ld de, (", cpmfcb, ")";
@asm "call 5";
@asm "ld (", cpmerr, "), a";
if cpmerr == 0xFF then
errno := ERR_NO_FILE;
else
errno := SUCCESS;
end if;
end sub;
sub FCBOpenRW(fcb: [FCB], type: uint8, iotype: uint8): (errno: uint8) is
var cpmfcb := &fcb.cpm;
var cpmerr: uint8;
var c: uint8;
fcb.iotype := iotype;
fcb.datatype := type;
if iotype == IO_WRITE then
@asm "ld c, 19"; # DELETE_FILE
@asm "ld de, (", cpmfcb, ")";
@asm "call 5";
@asm "ld c, 22"; # CREATE_FILE
@asm "ld de, (", cpmfcb, ")";
@asm "call 5";
@asm "ld (", cpmerr, "), a";
if cpmerr == 0xFF then
errno := ERR_DIR_FULL;
else
errno := SUCCESS;
end if;
else #IO_READ_WRITE
@asm "ld c, 15"; # OPEN_FILE
@asm "ld de, (", cpmfcb, ")";
@asm "call 5";
@asm "ld (", cpmerr, "), a";
if cpmerr == 0xFF then
errno := ERR_NO_FILE;
else
errno := SUCCESS;
end if;
end if;
if fcb.datatype == IO_TEXT then
c := CHAR_EOF;
else
c := 0;
end if;
MemSet(&fcb.buffer[0], c, 128);
end sub;
sub FCBOpenOut(fcb: [FCB], filename: [uint8], type: uint8): (errno: uint8) @extern("FCBOpenOut") is
fcb_init(fcb, filename);
errno := FCBOpenRW(fcb, type, IO_WRITE);
end sub;
sub FCBOpenInOut(fcb: [FCB], filename: [uint8], type: uint8): (errno: uint8) @extern("FCBOpenInOut") is
fcb_init(fcb, filename);
errno := FCBOpenRW(fcb, type, IO_READ_WRITE);
end sub;
sub FCBOpenForAppend(fcb: [FCB], filename: [uint8]): (errno: uint8) @extern("FCBOpenForAppend") is
var cpmfcb := &fcb.cpm;
var cpmerr: uint8;
fcb_init(fcb, filename);
@asm "ld c, 17"; # SEARCH_FILE
@asm "ld de, (", cpmfcb, ")";
@asm "call 5";
@asm "ld (", cpmerr, "), a";
if cpmerr == 0xFF then
# not found, open it for write
errno := FCBOpenRW(fcb, IO_BIN, IO_WRITE);
else
# found, open it for read/write
errno := FCBOpenRW(fcb, IO_BIN, IO_READ_WRITE);
# errno should be SUCCESS
if errno != SUCCESS then
return;
end if;
var dma := &fcb.buffer[0];
@asm "ld c, 26"; # SET DMA
@asm "ld de, (", dma, ")";
@asm "call 5";
@asm "ld c, 35"; # COMPUTE FILE SIZE
@asm "ld de, (", cpmfcb, ")";
@asm "call 5";
MemSet(&fcb.buffer[0] as [uint8], 0, 128);
@asm "ld c, 34"; # WRITE RANDOM
@asm "ld de, (", cpmfcb, ")";
@asm "call 5";
errno := SUCCESS;
end if;
end sub;
sub FCBGetChar(fcb: [FCB]): (c: uint8, errno: uint8) @extern("FCBGetChar") is
if fcb.iotype == IO_WRITE then
errno := ERR_BAD_IO;
c := 0;
return;
end if;
var index: uint8 := fcb.bufferptr;
if index == 0 then
var cpmfcb := &fcb.cpm;
var cpmerr: uint8;
var dma := &fcb.buffer[0];
@asm "ld c, 26"; # SET DMA
@asm "ld de, (", dma, ")";
@asm "call 5";
@asm "ld c, 20"; # READ SEQ
@asm "ld de, (", cpmfcb, ")";
@asm "call 5";
@asm "ld (", cpmerr, "),a";
if cpmerr != 0 then
c := 0;
errno := ERR_EOF;
return;
end if;
c := fcb.buffer[0];
fcb.bufferptr := 1;
else
c := fcb.buffer[index];
if index == 127 then
fcb.bufferptr := 0;
else
fcb.bufferptr := index + 1;
end if;
end if;
if fcb.datatype == IO_TEXT and c == CHAR_EOF then
errno := ERR_EOF;
else
errno := SUCCESS;
end if;
end sub;
sub FCBPutChar(fcb: [FCB], c: uint8): (errno: uint8) @extern("FCBPutChar") is
if fcb.iotype == IO_READ then
errno := ERR_BAD_IO;
return;
end if;
var index: uint8 := fcb.bufferptr;
fcb.buffer[index] := c;
if index == 127 then
var cpmfcb := &fcb.cpm;
var cpmerr: uint8;
var dma := &fcb.buffer[0];
@asm "ld c, 26"; # SET DMA
@asm "ld de, (", dma, ")";
@asm "call 5";
@asm "ld c, 21"; # WRITE SEQ
@asm "ld de, (", cpmfcb, ")";
@asm "call 5";
@asm "ld (", cpmerr, "),a";
if cpmerr != 0 then
errno := ERR_DISK_FULL;
return;
end if;
fcb.bufferptr := 0;
if fcb.datatype == IO_TEXT then
c := CHAR_EOF;
else
c := 0;
end if;
MemSet(&fcb.buffer[0], c, 128);
else
fcb.bufferptr := index + 1;
end if;
errno := SUCCESS;
end sub;
sub FCBClose(fcb: [FCB]): (errno: uint8) @extern("FCBClose") is
var cpmfcb := &fcb.cpm;
var closeerr: uint8;
var writeerr: uint8 := 0;
errno := SUCCESS;
if fcb.iotype == IO_READ then
return;
end if;
if fcb.bufferptr != 0 then
var dma := &fcb.buffer[0];
@asm "ld c, 26"; # SET DMA
@asm "ld de, (", dma, ")";
@asm "call 5";
@asm "ld c, 21"; # WRITE SEQ
@asm "ld de, (", cpmfcb, ")";
@asm "call 5";
@asm "ld (", writeerr, "),a";
end if;
@asm "ld c, 16"; # CLOSE_FILE
@asm "ld de, (", cpmfcb, ")";
@asm "call 5";
@asm "ld (", closeerr, "),a";
if writeerr != 0 then
errno := ERR_DISK_FULL;
return;
end if;
if closeerr == 0xFF then
errno := ERR_NO_FILE;
end if;
end sub;
# only for files open for READ
sub FCBRewind(fcb: [FCB]): (errno: uint8) @extern("FCBRewind") is
var cpmfcb := &fcb.cpm;
var cpmerr: uint8;
if fcb.iotype != IO_READ then
errno := ERR_BAD_IO;
return;
end if;
errno := FCBClose(fcb);
if errno != SUCCESS then
return;
end if;
var file: uint8[11];
MemCopy(&cpmfcb.f[0], 11, &file[0]);
MemSet(cpmfcb as [uint8], 0, @bytesof CpmFCB);
MemCopy(&file[0], 11, &cpmfcb.f[0]);
fcb.bufferptr := 0;
@asm "ld c, 15"; # OPEN_FILE
@asm "ld de, (", cpmfcb, ")";
@asm "call 5";
@asm "ld (", cpmerr, "), a";
if cpmerr == 0xFF then
errno := ERR_NO_FILE;
else
errno := SUCCESS;
end if;
end sub;

View File

@@ -0,0 +1,8 @@
@decl sub strlen(str: [uint8]): (len: uint16) @extern("strlen");
@decl sub strcpy(dest: [uint8], src: [uint8]): (ret: [uint8]) @extern("strcpy");
@decl sub strcat(dest: [uint8], src: [uint8]): (ret: [uint8]) @extern("strcat");
@decl sub strcmp(str1: [uint8], str2: [uint8]): (ret: int8) @extern("strcmp");
@decl sub strcasecmp(str1: [uint8], str2: [uint8]): (ret: int8) @extern("strcasecmp");
@decl sub strstr(str: [uint8], tosearch: [uint8]): (ret: [uint8]) @extern("strstr");
@decl sub strchr(str: [uint8], tosearch: uint8): (ret: [uint8]) @extern("strchr");
@decl sub tolower(char: uint8): (ret: uint8) @extern("tolower");

Binary file not shown.

View File

@@ -0,0 +1,192 @@
sub strlen(str: [uint8]): (len: uint16) @extern("strlen") is
@asm "ld de,(", str, ")";
@asm "ld hl,0";
@asm "1:";
@asm "ld a,(de)";
@asm "or a";
@asm "ret z";
@asm "inc de";
@asm "inc hl";
@asm "jr 1b";
end sub;
# returns dest
sub strcpy(dest: [uint8], src: [uint8]): (ret: [uint8]) @extern("strcpy") is
@asm "ld hl,(", src, ")";
@asm "ld de,(", dest, ")";
@asm "push de";
@asm "1:";
@asm "ld a,(hl)";
@asm "ld (de),a";
@asm "or a";
@asm "jr z,2f";
@asm "inc hl";
@asm "inc de";
@asm "jr 1b";
@asm "2:";
@asm "pop hl";
@asm "ret";
end sub;
# returns dest
sub strcat(dest: [uint8], src: [uint8]): (ret: [uint8]) @extern("strcat") is
@asm "ld hl,(", src, ")";
@asm "ld de,(", dest, ")";
@asm "push de";
@asm "1:";
@asm "ld a,(de)";
@asm "inc de";
@asm "or a";
@asm "jr nz,1b";
@asm "dec de";
@asm "2:";
@asm "ld a,(hl)";
@asm "ld (de),a";
@asm "or a";
@asm "jr z,3f";
@asm "inc hl";
@asm "inc de";
@asm "jr 2b";
@asm "3:";
@asm "pop hl";
@asm "ret";
end sub;
# returns 0 if equal, 1 if greather, else -1
sub strcmp(str1: [uint8], str2: [uint8]): (ret: int8) @extern("strcmp") is
@asm "ld de,(", str1, ")";
@asm "ld hl,(", str2, ")";
@asm "1:";
@asm "ld a,(de)";
@asm "cp (hl)";
@asm "jr nz,2f";
@asm "or a";
@asm "ret z";
@asm "jr 3f";
@asm "2:";
@asm "jr nc,4f";
@asm "ld a,-1";
@asm "ret";
@asm "3:";
@asm "inc hl";
@asm "inc de";
@asm "jr 1b";
@asm "4:";
@asm "ld a,1";
@asm "ret";
end sub;
sub tolower(char: uint8): (ret: uint8) @extern("tolower") is
@asm "ld a,(", char, ")";
@asm "cp 41H";
@asm "ret c";
@asm "cp 5AH+1";
@asm "ret nc";
@asm "or 20H";
@asm "ret";
end sub;
# case insensitive, returns 0 if equal, 1 if greather, else -1
sub strcasecmp(str1: [uint8], str2: [uint8]): (ret: uint8) @extern("strcasecmp") is
var c1: uint8;
var c2: uint8;
@asm "ld de,(", str1, ")";
@asm "ld hl,(", str2, ")";
@asm "1:";
@asm "ld a,(hl)";
@asm "call tolower";
@asm "ld c,a";
@asm "ld a,(de)";
@asm "call tolower";
@asm "cp c";
@asm "jr nz,2f";
@asm "or a";
@asm "ret z";
@asm "jr 3f";
@asm "2:";
@asm "jr nc,4f";
@asm "ld a,-1";
@asm "ret";
@asm "3:";
@asm "inc hl";
@asm "inc de";
@asm "jr 1b";
@asm "4:";
@asm "ld a,1";
@asm "ret";
@asm "tolower:";
@asm "cp 41H";
@asm "ret c";
@asm "cp 5AH+1";
@asm "ret nc";
@asm "or 20H";
@asm "ret";
end sub;
sub strstr(str: [uint8], tosearch: [uint8]): (ret: [uint8]) @extern("strstr") is
@asm "ld de,(", tosearch, ")";
@asm "ld hl,(", str, ")";
@asm "1:";
@asm "ld a,(de)";
@asm "cp (hl)";
@asm "jr z,2f";
@asm "inc hl";
@asm "ld a,(hl)";
@asm "or a";
@asm "jr nz,1b";
@asm "3:";
@asm "ld hl,0";
@asm "ret";
@asm "2:";
@asm "ld b,d";
@asm "ld c,e";
@asm "inc de";
@asm "ld a,(de)";
@asm "or a";
@asm "ret z";
@asm "push hl";
@asm "inc hl";
@asm "6:";
@asm "ld a,(de)";
@asm "cp (hl)";
@asm "jr nz,4f";
@asm "inc hl";
@asm "inc de";
@asm "ld a,(de)";
@asm "or a";
@asm "jr z,5f";
@asm "ld a,(hl)";
@asm "or a";
@asm "jr nz,6b";
@asm "pop hl";
@asm "jr 3b";
@asm "5:";
@asm "pop hl";
@asm "ret";
@asm "4:";
@asm "pop hl";
@asm "inc hl";
@asm "ld a,(hl)";
@asm "or a";
@asm "jr z,3b";
@asm "ld d,b";
@asm "ld e,c";
@asm "jr 1b";
end sub;
sub strchr(str: [uint8], tosearch: uint8): (ret: [uint8]) @extern("strchr") is
@asm "ld a,(", tosearch, ")";
@asm "ld c,a";
@asm "ld hl,(", str, ")";
@asm "1:";
@asm "ld a,c";
@asm "cp (hl)";
@asm "ret z";
@asm "inc hl";
@asm "ld a,(hl)";
@asm "or a";
@asm "jr nz,1b";
@asm "ld hl,0";
@asm "ret";
end sub;

View File

@@ -0,0 +1,3 @@
sub Test() is
@asm "call _xrndseed";
end sub;

View File

@@ -0,0 +1,2 @@
COWGOL TESTAS.COW RAND.AS


View File

@@ -1,53 +0,0 @@
; Xorshift is a class of pseudorandom number generators discovered
; by George Marsaglia and detailed in his 2003 paper, Xorshift RNGs.
;
; 16-bit xorshift pseudorandom number generator by John Metcalf
; returns hl = pseudorandom number
; corrupts a
; generates 16-bit pseudorandom numbers with a period of 65535
; using the xorshift method:
; hl ^= hl << 7
; hl ^= hl >> 9
; hl ^= hl << 8
; some alternative shift triplets which also perform well are:
; 6, 7, 13; 7, 9, 13; 9, 7, 13.
psect text
GLOBAL _xrnd, _xrndseed
_xrnd:
ld hl,1 ; seed must not be 0
ld a,h
rra
ld a,l
rra
xor h
ld h,a
ld a,l
rra
ld a,h
rra
xor l
ld l,a
xor h
ld h,a
ld (_xrnd+1),hl
res 7,h ;make-it positive...
ret
_xrndseed:
ld a,r
ld l,a
ld a,r
ld h,a
or l ; HL must be not NULL
jr nz,1f
inc hl
1:
ld (_xrnd+1),hl
ret


Some files were not shown because too many files have changed in this diff Show More