Documentation ¶
Overview ¶
Package cpm is the main package for our emulator, it uses memory to emulate execution of things at the bios level.
The package mostly contains the implementation of the syscalls that CP/M programs would expect - along with a little machinery to wire up the Z80 emulator we're using and deal with FCB structures.
Index ¶
- Variables
- func SysCallAuxRead(cpm *CPM) error
- func SysCallAuxWrite(cpm *CPM) error
- func SysCallBDOSVersion(cpm *CPM) error
- func SysCallConsoleStatus(cpm *CPM) error
- func SysCallDeleteFile(cpm *CPM) error
- func SysCallDriveAllReset(cpm *CPM) error
- func SysCallDriveGet(cpm *CPM) error
- func SysCallDriveSet(cpm *CPM) error
- func SysCallExit(cpm *CPM) error
- func SysCallFileClose(cpm *CPM) error
- func SysCallFileOpen(cpm *CPM) error
- func SysCallFindFirst(cpm *CPM) error
- func SysCallFindNext(cpm *CPM) error
- func SysCallGetDriveDPB(cpm *CPM) error
- func SysCallGetIOByte(cpm *CPM) error
- func SysCallLoginVec(cpm *CPM) error
- func SysCallMakeFile(cpm *CPM) error
- func SysCallRawIO(cpm *CPM) error
- func SysCallRead(cpm *CPM) error
- func SysCallReadChar(cpm *CPM) error
- func SysCallReadRand(cpm *CPM) error
- func SysCallReadString(cpm *CPM) error
- func SysCallRenameFile(cpm *CPM) error
- func SysCallSetDMA(cpm *CPM) error
- func SysCallSetIOByte(cpm *CPM) error
- func SysCallUserNumber(cpm *CPM) error
- func SysCallWrite(cpm *CPM) error
- func SysCallWriteChar(cpm *CPM) error
- func SysCallWriteRand(cpm *CPM) error
- func SysCallWriteString(cpm *CPM) error
- type CPM
- type CPMHandler
- type CPMHandlerType
- type FileCache
Constants ¶
This section is empty.
Variables ¶
var ( // ErrExit will be used to handle a CP/M binary calling Exit. // // It should be handled and expected by callers. ErrExit = errors.New("EXIT") // ErrHalt will be used to note that the Z80 emulator executed a HALT // operation, and that terminated the execution of code. // // It should be handled and expected by callers. ErrHalt = errors.New("HALT") // ErrUnimplemented will be used to handle a CP/M binary calling an unimplemented syscall. // // It should be handled and expected by callers. ErrUnimplemented = errors.New("UNIMPLEMENTED") )
Functions ¶
func SysCallAuxRead ¶ added in v0.5.0
SysCallAuxRead reads a single character from the auxillary input.
NOTE: Documentation implies this is blocking, but it seems like tastybasic and mbasic prefer it like this
func SysCallAuxWrite ¶ added in v0.5.0
SysCallAuxWrite writes the single character in the C register auxillary / punch output
func SysCallBDOSVersion ¶ added in v0.3.0
SysCallBDOSVersion returns version details
func SysCallConsoleStatus ¶ added in v0.5.0
SysCallConsoleStatus fakes a test for pending console (character) input.
func SysCallDeleteFile ¶
SysCallDeleteFile deletes the filename(s) matching the pattern specified by the FCB in DE.
func SysCallDriveAllReset ¶ added in v0.2.0
SysCallDriveAllReset resets the drives.
TODO: If there is a file named "$..." then we need to return 0xFF in A, which will be read by the CCP - as created by SUBMIT.COM
func SysCallDriveGet ¶
SysCallDriveGet returns the number of the active drive.
func SysCallDriveSet ¶
SysCallDriveSet updates the current drive number
func SysCallFileClose ¶
SysCallFileClose closes the filename that matches the pattern on the FCB supplied in DE
func SysCallFileOpen ¶
SysCallFileOpen opens the filename that matches the pattern on the FCB supplied in DE
func SysCallFindFirst ¶
SysCallFindFirst finds the first filename, on disk, that matches the glob in the FCB supplied in DE.
func SysCallFindNext ¶
SysCallFindNext finds the next filename that matches the glob set in the FCB in DE.
func SysCallGetDriveDPB ¶
SysCallGetDriveDPB returns the address of the DPB, which is faked.
func SysCallGetIOByte ¶ added in v0.5.0
SysCallGetIOByte gets the IOByte, which is used to describe which devices are used for I/O. No CP/M utilities use it, except for STAT and PIP.
The IOByte lives at 0x0003 in RAM, so it is often accessed directly when it is used.
func SysCallLoginVec ¶ added in v0.3.0
SysCallLoginVec returns the list of logged in drives.
func SysCallMakeFile ¶
SysCallMakeFile creates the file named in the FCB given in DE
func SysCallRawIO ¶
SysCallRawIO handles both simple character output, and input.
func SysCallRead ¶ added in v0.2.0
SysCallRead reads a record from the file named in the FCB given in DE
func SysCallReadChar ¶
SysCallReadChar reads a single character from the console.
func SysCallReadRand ¶
SysCallReadRand reads a random block from the FCB pointed to by DE into the DMA area.
func SysCallReadString ¶
SysCallReadString reads a string from the console, into the buffer pointed to by DE.
func SysCallRenameFile ¶ added in v0.5.0
SysCallRenameFile will handle a rename operation. Note that this will not handle cross-directory renames (i.e. file moving).
func SysCallSetDMA ¶ added in v0.3.0
SysCallSetDMA updates the address of the DMA area, which is used for block I/O.
func SysCallSetIOByte ¶ added in v0.5.0
SysCallSetIOByte sets the IOByte, which is used to describe which devices are used for I/O. No CP/M utilities use it, except for STAT and PIP.
The IOByte lives at 0x0003 in RAM, so it is often accessed directly when it is used.
func SysCallUserNumber ¶
func SysCallWrite ¶ added in v0.2.0
SysCallWrite writes a record to the file named in the FCB given in DE
func SysCallWriteChar ¶
SysCallWriteChar writes the single character in the E register to STDOUT.
func SysCallWriteRand ¶ added in v0.3.0
SysCallWriteRand writes a random block from DMA area to the FCB pointed to by DE.
func SysCallWriteString ¶
SysCallWriteString writes the $-terminated string pointed to by DE to STDOUT
Types ¶
type CPM ¶
type CPM struct { // Syscalls contains the syscalls we know how to emulate, indexed // by their ID. Syscalls map[uint8]CPMHandler // Memory contains the memory the system runs with. Memory *memory.Memory // CPU contains a pointer to the virtual CPU we use to execute // code. The CP/M we're implementing is Z80-based, so we need to // be able to emulate that. CPU z80.CPU // Drives specifies whether we use sub-directories for the // CP/M drives we emulate, instead of the current working directory. Drives bool // Reader is where we get our STDIN from. // // TODO: We should have something similar for STDOUT. Reader *bufio.Reader // Logger holds a logger which we use for debugging and diagnostics. Logger *slog.Logger // contains filtered or unexported fields }
CPM is the object that holds our emulator state
func (*CPM) Execute ¶
Execute executes our named binary, with the specified arguments.
The function will not return until the process being executed terminates, and any error will be returned.
func (*CPM) In ¶ added in v0.5.0
In is called to handle the I/O reading of a Z80 port.
This is called by our embedded Z80 emulator.
func (*CPM) LoadBinary ¶ added in v0.3.0
LoadBinary loads the given CP/M binary at the default address of 0x0100, where it can then be launched by Execute.
func (*CPM) LoadCCP ¶ added in v0.3.0
func (cpm *CPM) LoadCCP()
LoadCCP loads the CCP into RAM, to be executed instead of an external binary.
This function modifies the "start" attribute, to ensure the CCP is loaded and executed at a higher address than the default of 0x0100.
func (*CPM) Out ¶ added in v0.5.0
Out is called to handle the I/O writing to a Z80 port.
This is called by our embedded Z80 emulator, and this will be used by any system which used RST instructions to invoke the CP/M syscalls, rather than using "CALL 0x0005". Notable offenders include Microsoft's BASIC.
type CPMHandler ¶
type CPMHandler struct { // Desc contain the human-readable description of the given CP/M syscall. Desc string // Handler contains the function which should be involved for this syscall. Handler CPMHandlerType }
CPMHandler contains details of a specific call we implement.
While we mostly need a "number to handler", mapping having a name is useful for the logs we produce.
type CPMHandlerType ¶
CPMHandlerType contains the signature of a CP/M bios function.
It is not expected that outside packages will want to add custom BIOS functions, or syscalls, but this is public so that it could be done if it was necessary.