forked from amberisvibin/chibi-pc09
copy all local files to repo
cp/m files, sprites, circuit design
This commit is contained in:
6
emu/z80pack-1.9/cpmsim/cpm2
Executable file
6
emu/z80pack-1.9/cpmsim/cpm2
Executable file
@@ -0,0 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
rm -f disks/drive[ab].cpm
|
||||
ln disks/library/cpm2-1.dsk disks/drivea.cpm
|
||||
ln disks/library/cpm2-2.dsk disks/driveb.cpm
|
||||
cpmsim
|
6
emu/z80pack-1.9/cpmsim/cpm3
Executable file
6
emu/z80pack-1.9/cpmsim/cpm3
Executable file
@@ -0,0 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
rm -f disks/drive[ab].cpm
|
||||
ln disks/library/cpm3-1.dsk disks/drivea.cpm
|
||||
ln disks/library/cpm3-2.dsk disks/driveb.cpm
|
||||
cpmsim
|
BIN
emu/z80pack-1.9/cpmsim/disks/drivea.cpm
Normal file
BIN
emu/z80pack-1.9/cpmsim/disks/drivea.cpm
Normal file
Binary file not shown.
BIN
emu/z80pack-1.9/cpmsim/disks/driveb.cpm
Normal file
BIN
emu/z80pack-1.9/cpmsim/disks/driveb.cpm
Normal file
Binary file not shown.
BIN
emu/z80pack-1.9/cpmsim/disks/drivei.cpm
Normal file
BIN
emu/z80pack-1.9/cpmsim/disks/drivei.cpm
Normal file
Binary file not shown.
BIN
emu/z80pack-1.9/cpmsim/disks/library/cpm2-1.dsk
Normal file
BIN
emu/z80pack-1.9/cpmsim/disks/library/cpm2-1.dsk
Normal file
Binary file not shown.
BIN
emu/z80pack-1.9/cpmsim/disks/library/cpm2-2.dsk
Normal file
BIN
emu/z80pack-1.9/cpmsim/disks/library/cpm2-2.dsk
Normal file
Binary file not shown.
BIN
emu/z80pack-1.9/cpmsim/disks/library/cpm3-1.dsk
Normal file
BIN
emu/z80pack-1.9/cpmsim/disks/library/cpm3-1.dsk
Normal file
Binary file not shown.
BIN
emu/z80pack-1.9/cpmsim/disks/library/cpm3-2.dsk
Normal file
BIN
emu/z80pack-1.9/cpmsim/disks/library/cpm3-2.dsk
Normal file
Binary file not shown.
BIN
emu/z80pack-1.9/cpmsim/disks/library/hd-tools.dsk
Normal file
BIN
emu/z80pack-1.9/cpmsim/disks/library/hd-tools.dsk
Normal file
Binary file not shown.
BIN
emu/z80pack-1.9/cpmsim/disks/library/mpm-1.dsk
Normal file
BIN
emu/z80pack-1.9/cpmsim/disks/library/mpm-1.dsk
Normal file
Binary file not shown.
BIN
emu/z80pack-1.9/cpmsim/disks/library/mpm-2.dsk
Normal file
BIN
emu/z80pack-1.9/cpmsim/disks/library/mpm-2.dsk
Normal file
Binary file not shown.
6
emu/z80pack-1.9/cpmsim/mpm
Executable file
6
emu/z80pack-1.9/cpmsim/mpm
Executable file
@@ -0,0 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
rm -f disks/drive[ab].cpm
|
||||
ln disks/library/mpm-1.dsk disks/drivea.cpm
|
||||
ln disks/library/mpm-2.dsk disks/driveb.cpm
|
||||
cpmsim -h
|
32
emu/z80pack-1.9/cpmsim/srccpm2/Makefile
Normal file
32
emu/z80pack-1.9/cpmsim/srccpm2/Makefile
Normal file
@@ -0,0 +1,32 @@
|
||||
CFLAGS= -O -s
|
||||
|
||||
all: format putsys bin2hex send receive bios.bin boot.bin
|
||||
@echo "done"
|
||||
|
||||
format: format.c
|
||||
cc $(CFLAGS) -o format format.c
|
||||
cp format ..
|
||||
|
||||
putsys: putsys.c
|
||||
cc $(CFLAGS) -o putsys putsys.c
|
||||
|
||||
bin2hex: bin2hex.c
|
||||
cc $(CFLAGS) -o bin2hex bin2hex.c
|
||||
cp bin2hex ..
|
||||
|
||||
send: send.c
|
||||
cc $(CFLAGS) -o send send.c
|
||||
cp send ..
|
||||
|
||||
receive: receive.c
|
||||
cc $(CFLAGS) -o receive receive.c
|
||||
cp receive ..
|
||||
|
||||
bios.bin: bios.asm
|
||||
z80asm -vl -sn -x bios.asm
|
||||
|
||||
boot.bin: boot.asm
|
||||
z80asm -vl -sn boot.asm
|
||||
|
||||
clean:
|
||||
rm -f *.lis bios.bin boot.bin format putsys bin2hex receive send
|
161
emu/z80pack-1.9/cpmsim/srccpm2/bin2hex.c
Normal file
161
emu/z80pack-1.9/cpmsim/srccpm2/bin2hex.c
Normal file
@@ -0,0 +1,161 @@
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
void help(char *name)
|
||||
{
|
||||
printf("%s - BINARY to Intel HEX file convertor version 1.00\n"\
|
||||
"(c)BCL Vysoke Myto 2001 (benedikt@lphard.cz)\n\n",name);
|
||||
printf("Usage: %s [-option] binfile hexfile\n"\
|
||||
" -l Bytes to read from binary file\n"\
|
||||
" -i Binary file starting offset\n"\
|
||||
" -o Output file offset (where HEX data starts)\n"\
|
||||
" -t Exclude EOF record\n"\
|
||||
" -a Append to end of existing HEX file\n"\
|
||||
" -q Quiet mode (no statistics are printed)\n", name);
|
||||
}
|
||||
|
||||
int main(int argc,char *argv[])/*Main routine*/
|
||||
{
|
||||
char *ifile = NULL;
|
||||
char *ofile = NULL;
|
||||
char c;
|
||||
FILE *inp, *outp;
|
||||
int ch,csum;
|
||||
int ofsa = 0;
|
||||
int cnt = 0;
|
||||
struct stat statbuf;
|
||||
long int foffset = 0;
|
||||
long int fsize = 0;
|
||||
long int fsub;
|
||||
long int fpoint = 0;
|
||||
long int adrs = 0;
|
||||
unsigned char quiet = 0;
|
||||
unsigned char eofrec = 0;
|
||||
unsigned char append = 0;
|
||||
|
||||
opterr = 0; //print error message if unknown option
|
||||
|
||||
while ((c = getopt (argc, argv, "l:i:o:taqv")) != -1)
|
||||
switch (c) {
|
||||
case 'l':
|
||||
fsize = atol(optarg);
|
||||
break;
|
||||
case 'i':
|
||||
foffset = atol(optarg);
|
||||
break;
|
||||
case 'o':
|
||||
adrs = atol(optarg);
|
||||
break;
|
||||
case 't':
|
||||
eofrec = 1;
|
||||
break;
|
||||
case 'a':
|
||||
append = 1;
|
||||
break;
|
||||
case 'q':
|
||||
quiet = 1;
|
||||
break;
|
||||
case 'v':
|
||||
printf("%s - BINARY to Intel HEX file convertor version 1.00\n"\
|
||||
"(c)BCL Vysoke Myto 2001 (benedikt@lphard.cz)\n",argv[0]);
|
||||
return 0;
|
||||
case '?':
|
||||
help (argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((argc - optind) != 2) {
|
||||
printf("ERROR: Missing input/output file.\n");
|
||||
help(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
ifile = argv[optind];
|
||||
ofile = argv[optind+1];
|
||||
|
||||
/*Open file check*/
|
||||
if((inp = fopen(ifile, "rb")) == NULL){
|
||||
printf("ERROR: Cannot open input file.\n");
|
||||
return 1;
|
||||
}
|
||||
fseek (inp, foffset, SEEK_SET);
|
||||
|
||||
if (append == 0) {
|
||||
if((outp = fopen(ofile, "wt")) == NULL){
|
||||
printf("ERROR: Cannot open output file.\n");
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
if((outp = fopen(ofile, "at")) == NULL){
|
||||
printf("ERROR: Cannot re-open output file.\n");
|
||||
return 1;
|
||||
}
|
||||
fseek (outp, 0, SEEK_END);
|
||||
}
|
||||
|
||||
fstat(fileno(inp), &statbuf);
|
||||
if (quiet == 0) printf("Input file size=%ld\n",statbuf.st_size);
|
||||
if (foffset > statbuf.st_size) {
|
||||
printf("ERROR: Input offset > input file length\n");
|
||||
}
|
||||
if ((fsize == 0) || (fsize > (statbuf.st_size - foffset)))
|
||||
fsize = statbuf.st_size - foffset;
|
||||
|
||||
// fprintf(outp,":020000020000FC\n");/*Start Header*/
|
||||
fsub = fsize - fpoint;
|
||||
if (fsub > 0x20) {
|
||||
fprintf(outp,":20%04X00",adrs);/*Hex line Header*/
|
||||
csum = 0x20 + (adrs>>8) + (adrs & 0xFF);
|
||||
adrs += 0x20;
|
||||
}
|
||||
else {
|
||||
fprintf(outp, ":%02X%04X00", fsub,adrs);/*Hex line Header*/
|
||||
csum = fsub + (adrs>>8) + (adrs & 0xFF);
|
||||
adrs += fsub;
|
||||
}
|
||||
while (fsub > 0){
|
||||
ch = fgetc(inp);
|
||||
fprintf(outp,"%02X",ch);/*Put data*/
|
||||
cnt++; fpoint++;
|
||||
fsub = fsize - fpoint;
|
||||
csum = ch + csum;
|
||||
if((fsub == 0)||(cnt == 0x20)){
|
||||
cnt = 0; csum = 0xFF & (~csum + 1);
|
||||
fprintf(outp,"%02X\n",csum);/*Put checksum*/
|
||||
if(fsub == 0) break;
|
||||
if(adrs > 0xFFFF){
|
||||
ofsa = 0x1000 + ofsa;
|
||||
adrs = 0;
|
||||
fprintf(outp,":02000002%04X",ofsa);/*Change offset address*/
|
||||
csum = 0x02 + 0x02 + (ofsa>>8) + (ofsa & 0xFF);
|
||||
csum = 0xFF & (~csum + 1);
|
||||
fprintf(outp,"%02X\n", csum);
|
||||
}
|
||||
adrs = 0xFFFF & adrs;
|
||||
if (fsub > 0x20) {
|
||||
fprintf(outp,":20%04X00",adrs);/*Next Hex line Header*/
|
||||
csum = 0x20 + (adrs>>8) + (adrs & 0xFF);
|
||||
adrs += 0x20;
|
||||
}
|
||||
else {
|
||||
if(fsub > 0){
|
||||
fprintf(outp, ":%02X%04X00", fsub,adrs);/*Next Hex line Header*/
|
||||
csum = fsub + (adrs>>8) + (adrs & 0xFF);
|
||||
adrs += fsub;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (eofrec == 0) fprintf(outp,":00000001FF\n");/*End footer*/
|
||||
fflush (outp);
|
||||
|
||||
fstat(fileno(outp), &statbuf);
|
||||
if (quiet == 0) printf("Output file size=%ld\n",statbuf.st_size);
|
||||
|
||||
fclose(inp);
|
||||
fclose(outp);
|
||||
return 0;
|
||||
}
|
375
emu/z80pack-1.9/cpmsim/srccpm2/bios.asm
Normal file
375
emu/z80pack-1.9/cpmsim/srccpm2/bios.asm
Normal file
@@ -0,0 +1,375 @@
|
||||
; CBIOS for Z80-Simulator
|
||||
;
|
||||
; Copyright (C) 1988-2006 by Udo Munk
|
||||
;
|
||||
MSIZE EQU 64 ;cp/m version memory size in kilobytes
|
||||
;
|
||||
; "bias" is address offset from 3400H for memory systems
|
||||
; than 16K (referred to as "b" throughout the text).
|
||||
;
|
||||
BIAS EQU (MSIZE-20)*1024
|
||||
CCP EQU 3400H+BIAS ;base of ccp
|
||||
BDOS EQU CCP+806H ;base of bdos
|
||||
BIOS EQU CCP+1600H ;base of bios
|
||||
CDISK EQU 0004H ;current disk number 0=A,...,15=P
|
||||
IOBYTE EQU 0003H ;intel i/o byte
|
||||
;
|
||||
; I/O ports
|
||||
;
|
||||
CONSTA EQU 0 ;console status port
|
||||
CONDAT EQU 1 ;console data port
|
||||
PRTSTA EQU 2 ;printer status port
|
||||
PRTDAT EQU 3 ;printer data port
|
||||
AUXDAT EQU 5 ;auxiliary data port
|
||||
FDCD EQU 10 ;fdc-port: # of drive
|
||||
FDCT EQU 11 ;fdc-port: # of track
|
||||
FDCS EQU 12 ;fdc-port: # of sector
|
||||
FDCOP EQU 13 ;fdc-port: command
|
||||
FDCST EQU 14 ;fdc-port: status
|
||||
DMAL EQU 15 ;dma-port: dma address low
|
||||
DMAH EQU 16 ;dma-port: dma address high
|
||||
;
|
||||
ORG BIOS ;origin of this program
|
||||
NSECTS EQU (BIOS-CCP)/128 ;warm start sector count
|
||||
;
|
||||
; jump vector for individual subroutines
|
||||
;
|
||||
JP BOOT ;cold start
|
||||
WBOOTE: JP WBOOT ;warm start
|
||||
JP CONST ;console status
|
||||
JP CONIN ;console character in
|
||||
JP CONOUT ;console character out
|
||||
JP LIST ;list character out
|
||||
JP PUNCH ;punch character out
|
||||
JP READER ;reader character out
|
||||
JP HOME ;move head to home position
|
||||
JP SELDSK ;select disk
|
||||
JP SETTRK ;set track number
|
||||
JP SETSEC ;set sector number
|
||||
JP SETDMA ;set dma address
|
||||
JP READ ;read disk
|
||||
JP WRITE ;write disk
|
||||
JP LISTST ;return list status
|
||||
JP SECTRAN ;sector translate
|
||||
;
|
||||
; fixed data tables for four-drive standard
|
||||
; IBM-compatible 8" disks
|
||||
;
|
||||
; disk parameter header for disk 00
|
||||
DPBASE: DEFW TRANS,0000H
|
||||
DEFW 0000H,0000H
|
||||
DEFW DIRBF,DPBLK
|
||||
DEFW CHK00,ALL00
|
||||
; disk parameter header for disk 01
|
||||
DEFW TRANS,0000H
|
||||
DEFW 0000H,0000H
|
||||
DEFW DIRBF,DPBLK
|
||||
DEFW CHK01,ALL01
|
||||
; disk parameter header for disk 02
|
||||
DEFW TRANS,0000H
|
||||
DEFW 0000H,0000H
|
||||
DEFW DIRBF,DPBLK
|
||||
DEFW CHK02,ALL02
|
||||
; disk parameter header for disk 03
|
||||
DEFW TRANS,0000H
|
||||
DEFW 0000H,0000H
|
||||
DEFW DIRBF,DPBLK
|
||||
DEFW CHK03,ALL03
|
||||
;
|
||||
; sector translate vector for the IBM 8" disks
|
||||
;
|
||||
TRANS: DEFB 1,7,13,19 ;sectors 1,2,3,4
|
||||
DEFB 25,5,11,17 ;sectors 5,6,7,8
|
||||
DEFB 23,3,9,15 ;sectors 9,10,11,12
|
||||
DEFB 21,2,8,14 ;sectors 13,14,15,16
|
||||
DEFB 20,26,6,12 ;sectors 17,18,19,20
|
||||
DEFB 18,24,4,10 ;sectors 21,22,23,24
|
||||
DEFB 16,22 ;sectors 25,26
|
||||
;
|
||||
; disk parameter block, common to all IBM 8" disks
|
||||
;
|
||||
DPBLK: DEFW 26 ;sectors per track
|
||||
DEFB 3 ;block shift factor
|
||||
DEFB 7 ;block mask
|
||||
DEFB 0 ;extent mask
|
||||
DEFW 242 ;disk size-1
|
||||
DEFW 63 ;directory max
|
||||
DEFB 192 ;alloc 0
|
||||
DEFB 0 ;alloc 1
|
||||
DEFW 16 ;check size
|
||||
DEFW 2 ;track offset
|
||||
;
|
||||
; fixed data tables for 4MB harddisk
|
||||
;
|
||||
; disk parameter header
|
||||
HDBASE: DEFW HDTRA,0000H
|
||||
DEFW 0000H,0000H
|
||||
DEFW DIRBF,HDBLK
|
||||
DEFW CHKHD,ALLHD
|
||||
;
|
||||
; sector translate vector for the hardisk
|
||||
;
|
||||
HDTRA: DEFB 1,2,3,4,5,6,7,8,9,10
|
||||
DEFB 11,12,13,14,15,16,17,18,19,20
|
||||
DEFB 21,22,23,24,25,26,27,28,29,30
|
||||
DEFB 31,32,33,34,35,36,37,38,39,40
|
||||
DEFB 41,42,43,44,45,46,47,48,49,50
|
||||
DEFB 51,52,53,54,55,56,57,58,59,60
|
||||
DEFB 61,62,63,64,65,66,67,68,69,70
|
||||
DEFB 71,72,73,74,75,76,77,78,79,80
|
||||
DEFB 81,82,83,84,85,86,87,88,89,90
|
||||
DEFB 91,92,93,94,95,96,97,98,99,100
|
||||
DEFB 101,102,103,104,105,106,107,108,109,110
|
||||
DEFB 111,112,113,114,115,116,117,118,119,120
|
||||
DEFB 121,122,123,124,125,126,127,128
|
||||
;
|
||||
; disk parameter block for harddisk
|
||||
;
|
||||
HDBLK: DEFW 128 ;sectors per track
|
||||
DEFB 4 ;block shift factor
|
||||
DEFB 15 ;block mask
|
||||
DEFB 0 ;extent mask
|
||||
DEFW 2039 ;disk size-1
|
||||
DEFW 1023 ;directory max
|
||||
DEFB 255 ;alloc 0
|
||||
DEFB 255 ;alloc 1
|
||||
DEFW 0 ;check size
|
||||
DEFW 0 ;track offset
|
||||
;
|
||||
; signon message
|
||||
;
|
||||
SIGNON: DEFM '64K CP/M Vers. 2.2 (CBIOS V1.1 for Z80SIM, '
|
||||
DEFM 'Copyright 1988-2006 by Udo Munk)'
|
||||
DEFB 13,10,0
|
||||
;
|
||||
; end of fixed tables
|
||||
;
|
||||
; individual subroutines to perform each function
|
||||
; simplest case is to just perform parameter initialization
|
||||
;
|
||||
BOOT: LD SP,80H ;use space below buffer for stack
|
||||
LD HL,SIGNON ;print message
|
||||
BOOTL: LD A,(HL)
|
||||
OR A
|
||||
JP Z,BOOTC
|
||||
LD C,A
|
||||
CALL CONOUT
|
||||
INC HL
|
||||
JP BOOTL
|
||||
BOOTC: XOR A ;zero in the accum
|
||||
LD (IOBYTE),A ;clear the iobyte
|
||||
LD (CDISK),A ;select disk zero
|
||||
JP GOCPM ;initialize and go to cp/m
|
||||
;
|
||||
; simplest case is to read the disk until all sectors loaded
|
||||
;
|
||||
WBOOT: LD SP,80H ;use space below buffer for stack
|
||||
LD C,0 ;select disk 0
|
||||
CALL SELDSK
|
||||
CALL HOME ;go to track 00
|
||||
;
|
||||
LD B,NSECTS ;b counts # of sectors to load
|
||||
LD C,0 ;c has the current track number
|
||||
LD D,2 ;d has the next sector to read
|
||||
; note that we begin by reading track 0, sector 2 since sector 1
|
||||
; contains the cold start loader, which is skipped in a warm start
|
||||
LD HL,CCP ;base of cp/m (initial load point)
|
||||
LOAD1: ;load one more sector
|
||||
PUSH BC ;save sector count, current track
|
||||
PUSH DE ;save next sector to read
|
||||
PUSH HL ;save dma address
|
||||
LD C,D ;get sector address to register c
|
||||
CALL SETSEC ;set sector address from register c
|
||||
POP BC ;recall dma address to b,c
|
||||
PUSH BC ;replace on stack for later recall
|
||||
CALL SETDMA ;set dma address from b,c
|
||||
; drive set to 0, track set, sector set, dma address set
|
||||
CALL READ
|
||||
CP 00H ;any errors?
|
||||
JP NZ,WBOOT ;retry the entire boot if an error occurs
|
||||
; no error, move to next sector
|
||||
POP HL ;recall dma address
|
||||
LD DE,128 ;dma=dma+128
|
||||
ADD HL,DE ;new dma address is in h,l
|
||||
POP DE ;recall sector address
|
||||
POP BC ;recall number of sectors remaining, and current trk
|
||||
DEC B ;sectors=sectors-1
|
||||
JP Z,GOCPM ;transfer to cp/m if all have been loaded
|
||||
; more sectors remain to load, check for track change
|
||||
INC D
|
||||
LD A,D ;sector=27?, if so, change tracks
|
||||
CP 27
|
||||
JP C,LOAD1 ;carry generated if sector<27
|
||||
; end of current track, go to next track
|
||||
LD D,1 ;begin with first sector of next track
|
||||
INC C ;track=track+1
|
||||
; save register state, and change tracks
|
||||
CALL SETTRK ;track address set from register c
|
||||
JP LOAD1 ;for another sector
|
||||
; end of load operation, set parameters and go to cp/m
|
||||
GOCPM:
|
||||
LD A,0C3H ;c3 is a jmp instruction
|
||||
LD (0),A ;for jmp to wboot
|
||||
LD HL,WBOOTE ;wboot entry point
|
||||
LD (1),HL ;set address field for jmp at 0
|
||||
;
|
||||
LD (5),A ;for jmp to bdos
|
||||
LD HL,BDOS ;bdos entry point
|
||||
LD (6),HL ;address field of jump at 5 to bdos
|
||||
;
|
||||
LD BC,80H ;default dma address is 80h
|
||||
CALL SETDMA
|
||||
;
|
||||
EI ;enable the interrupt system
|
||||
LD A,(CDISK) ;get current disk number
|
||||
LD C,A ;send to the ccp
|
||||
JP CCP ;go to cp/m for further processing
|
||||
;
|
||||
;
|
||||
; simple i/o handlers
|
||||
;
|
||||
; console status, return 0ffh if character ready, 00h if not
|
||||
;
|
||||
CONST: IN A,(CONSTA) ;get console status
|
||||
RET
|
||||
;
|
||||
; console character into register a
|
||||
;
|
||||
CONIN: IN A,(CONDAT) ;get character from console
|
||||
RET
|
||||
;
|
||||
; console character output from register c
|
||||
;
|
||||
CONOUT: LD A,C ;get to accumulator
|
||||
OUT (CONDAT),A ;send character to console
|
||||
RET
|
||||
;
|
||||
; list character from register c
|
||||
;
|
||||
LIST: LD A,C ;character to register a
|
||||
OUT (PRTDAT),A
|
||||
RET
|
||||
;
|
||||
; return list status (0 if not ready, 0xff if ready)
|
||||
;
|
||||
LISTST: IN A,(PRTSTA)
|
||||
RET
|
||||
;
|
||||
; punch character from register c
|
||||
;
|
||||
PUNCH: LD A,C ;character to register a
|
||||
OUT (AUXDAT),A
|
||||
RET
|
||||
;
|
||||
; read character into register a from reader device
|
||||
;
|
||||
READER: IN A,(AUXDAT)
|
||||
RET
|
||||
;
|
||||
;
|
||||
; i/o drivers for the disk follow
|
||||
;
|
||||
; move to the track 00 position of current drive
|
||||
; translate this call into a settrk call with parameter 00
|
||||
;
|
||||
HOME: LD C,0 ;select track 0
|
||||
JP SETTRK ;we will move to 00 on first read/write
|
||||
;
|
||||
; select disk given by register C
|
||||
;
|
||||
SELDSK: LD HL,0000H ;error return code
|
||||
LD A,C
|
||||
CP 4 ;must be between 0 and 3
|
||||
JR NC,SELHD ;no carry if 4,5,...
|
||||
; disk number is in the proper range
|
||||
; compute proper disk parameter header address
|
||||
OUT (FDCD),A ;selekt disk drive
|
||||
LD L,A ;L=disk number 0,1,2,3
|
||||
ADD HL,HL ;*2
|
||||
ADD HL,HL ;*4
|
||||
ADD HL,HL ;*8
|
||||
ADD HL,HL ;*16 (size of each header)
|
||||
LD DE,DPBASE
|
||||
ADD HL,DE ;HL=.dpbase(diskno*16)
|
||||
RET
|
||||
SELHD: CP 8 ;select the harddisk?
|
||||
RET NZ ;no, error
|
||||
OUT (FDCD),A ;select disk drive
|
||||
LD HL,HDBASE ;HL=hdbase for harddisk
|
||||
RET
|
||||
;
|
||||
; set track given by register c
|
||||
;
|
||||
SETTRK: LD A,C
|
||||
OUT (FDCT),A
|
||||
RET
|
||||
;
|
||||
; set sector given by register c
|
||||
;
|
||||
SETSEC: LD A,C
|
||||
OUT (FDCS),A
|
||||
RET
|
||||
;
|
||||
; translate the sector given by BC using the
|
||||
; translate table given by DE
|
||||
;
|
||||
SECTRAN:
|
||||
EX DE,HL ;HL=.trans
|
||||
ADD HL,BC ;HL=.trans(sector)
|
||||
LD L,(HL) ;L = trans(sector)
|
||||
LD H,0 ;HL= trans(sector)
|
||||
RET ;with value in HL
|
||||
;
|
||||
; set dma address given by registers b and c
|
||||
;
|
||||
SETDMA: LD A,C ;low order address
|
||||
OUT (DMAL),A
|
||||
LD A,B ;high order address
|
||||
OUT (DMAH),A ;in dma
|
||||
RET
|
||||
;
|
||||
; perform read operation
|
||||
;
|
||||
READ: XOR A ;read command -> A
|
||||
JP WAITIO ;to perform the actual i/o
|
||||
;
|
||||
; perform a write operation
|
||||
;
|
||||
WRITE: LD A,1 ;write command -> A
|
||||
;
|
||||
; enter here from read and write to perform the actual i/o
|
||||
; operation. return a 00h in register a if the operation completes
|
||||
; properly, and 01h if an error occurs during the read or write
|
||||
;
|
||||
; in this case, we have saved the disk number in 'diskno' (0-3)
|
||||
; the track number in 'track' (0-76)
|
||||
; the sector number in 'sector' (1-26)
|
||||
; the dma address in 'dmaad' (0-65535)
|
||||
;
|
||||
WAITIO: OUT (FDCOP),A ;start i/o operation
|
||||
IN A,(FDCST) ;status of i/o operation -> A
|
||||
RET
|
||||
;
|
||||
; the remainder of the CBIOS is reserved uninitialized
|
||||
; data area, and does not need to be a part of the
|
||||
; system memory image (the space must be available,
|
||||
; however, between "begdat" and "enddat").
|
||||
;
|
||||
; scratch ram area for BDOS use
|
||||
;
|
||||
BEGDAT EQU $ ;beginning of data area
|
||||
DIRBF: DEFS 128 ;scratch directory area
|
||||
ALL00: DEFS 31 ;allocation vector 0
|
||||
ALL01: DEFS 31 ;allocation vector 1
|
||||
ALL02: DEFS 31 ;allocation vector 2
|
||||
ALL03: DEFS 31 ;allocation vector 3
|
||||
ALLHD: DEFS 255 ;allocation vector harddisk
|
||||
CHK00: DEFS 16 ;check vector 0
|
||||
CHK01: DEFS 16 ;check vector 1
|
||||
CHK02: DEFS 16 ;check vector 2
|
||||
CHK03: DEFS 16 ;check vector 3
|
||||
CHKHD: DEFS 0 ;check vector harddisk
|
||||
;
|
||||
ENDDAT EQU $ ;end of data area
|
||||
DATSIZ EQU $-BEGDAT ;size of data area
|
||||
END ;of BIOS
|
74
emu/z80pack-1.9/cpmsim/srccpm2/boot.asm
Normal file
74
emu/z80pack-1.9/cpmsim/srccpm2/boot.asm
Normal file
@@ -0,0 +1,74 @@
|
||||
; CP/M 2.2 boot-loader for Z80-Simulator
|
||||
;
|
||||
; Copyright (C) 1988 by Udo Munk
|
||||
;
|
||||
ORG 0 ; mem base of boot
|
||||
;
|
||||
MSIZE EQU 64 ; mem size in kbytes
|
||||
;
|
||||
BIAS EQU (MSIZE-20)*1024 ; offset from 20k system
|
||||
CCP EQU 3400H+BIAS ; base of the ccp
|
||||
BIOS EQU CCP+1600H ; base of the bios
|
||||
BIOSL EQU 0300H ; length of the bios
|
||||
BOOT EQU BIOS
|
||||
SIZE EQU BIOS+BIOSL-CCP ; size of cp/m system
|
||||
SECTS EQU SIZE/128 ; # of sectors to load
|
||||
;
|
||||
; I/O ports
|
||||
;
|
||||
DRIVE EQU 10 ; fdc-port: # of drive
|
||||
TRACK EQU 11 ; fdc-port: # of track
|
||||
SECTOR EQU 12 ; fdc-port: # of sector
|
||||
FDCOP EQU 13 ; fdc-port: command
|
||||
FDCST EQU 14 ; fdc-port: status
|
||||
DMAL EQU 15 ; dma-port: dma address low
|
||||
DMAH EQU 16 ; dma-port: dma address high
|
||||
;
|
||||
; begin the load operation
|
||||
;
|
||||
COLD: LD BC,2 ; b=track 0, c=sector 2
|
||||
LD D,SECTS ; d=# sectors to load
|
||||
LD HL,CCP ; base transfer address
|
||||
LD A,0 ; select drive A
|
||||
OUT (DRIVE),A
|
||||
;
|
||||
; load the next sector
|
||||
;
|
||||
LSECT: LD A,B ; set track
|
||||
OUT (TRACK),A
|
||||
LD A,C ; set sector
|
||||
OUT (SECTOR),A
|
||||
LD A,L ; set dma address low
|
||||
OUT (DMAL),A
|
||||
LD A,H ; set dma adress high
|
||||
OUT (DMAH),A
|
||||
XOR A ; read sector
|
||||
OUT (FDCOP),A
|
||||
IN A,(FDCST) ; get status of fdc
|
||||
CP 0 ; read successful ?
|
||||
JP Z,CONT ; yes, continue
|
||||
HALT ; no, halt cpu
|
||||
CONT:
|
||||
; go to next sector if load is incomplete
|
||||
DEC D ; sects=sects-1
|
||||
JP Z,BOOT ; head for the bios
|
||||
;
|
||||
; more sectors to load
|
||||
;
|
||||
; we aren't using a stack, so use <sp> as scratch register
|
||||
; to hold the load address increment
|
||||
;
|
||||
LD SP,128 ; 128 bytes per sector
|
||||
ADD HL,SP ; <hl> = <hl> + 128
|
||||
;
|
||||
INC C ; sector = sector + 1
|
||||
LD A,C
|
||||
CP 27 ; last sector of track ?
|
||||
JP C,LSECT ; no, go read another
|
||||
;
|
||||
; end of track, increment to next track
|
||||
;
|
||||
LD C,1 ; sector = 1
|
||||
INC B ; track = track + 1
|
||||
JP LSECT ; for another group
|
||||
END ; of boot loader
|
BIN
emu/z80pack-1.9/cpmsim/srccpm2/cpm.bin
Normal file
BIN
emu/z80pack-1.9/cpmsim/srccpm2/cpm.bin
Normal file
Binary file not shown.
69
emu/z80pack-1.9/cpmsim/srccpm2/format.c
Normal file
69
emu/z80pack-1.9/cpmsim/srccpm2/format.c
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* CP/M 2.2 Formats a simulated Disk Drive
|
||||
*
|
||||
* Copyright (C) 1988-2006 by Udo Munk
|
||||
*
|
||||
* History:
|
||||
* 29-APR-88 Development on TARGON/35 with AT&T Unix System V.3
|
||||
* 11-MAR-93 comments in english
|
||||
* 01-OCT-06 modified to compile on modern POSIX OS's
|
||||
* 18-NOV-06 added a second harddisk
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <memory.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#define TRACK 77
|
||||
#define SECTOR 26
|
||||
#define HDTRACK 255
|
||||
#define HDSECTOR 128
|
||||
|
||||
/*
|
||||
* This program is able to format the following disk formats:
|
||||
*
|
||||
* drive A: 8" IBM SS,SD
|
||||
* drive B: 8" IBM SS,SD
|
||||
* drive C: 8" IBM SS,SD
|
||||
* drive D: 8" IBM SS,SD
|
||||
* drive I: 4MB harddisk
|
||||
* drive J: 4MB harddisk
|
||||
*/
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
register int i;
|
||||
int fd;
|
||||
char drive;
|
||||
static unsigned char sector[128];
|
||||
static char fn[] = "disks/drive?.cpm";
|
||||
static char usage[] = "usage: format a | b | c | d | i | j";
|
||||
|
||||
if (argc != 2) {
|
||||
puts(usage);
|
||||
exit(1);
|
||||
}
|
||||
i = *argv[1];
|
||||
if (argc != 2 ||
|
||||
(i != 'a' && i != 'b' && i != 'c' && i != 'd' && i != 'i'
|
||||
&& i != 'j')) {
|
||||
puts(usage);
|
||||
exit(1);
|
||||
}
|
||||
fn[11] = drive = (char) i;
|
||||
memset((char *) sector, 0xe5, 128);
|
||||
if ((fd = creat(fn, 0644)) == -1) {
|
||||
perror("disk file");
|
||||
exit(1);
|
||||
}
|
||||
if (drive != 'i' && drive != 'j') {
|
||||
for (i = 0; i < TRACK * SECTOR; i++)
|
||||
write(fd, (char *) sector, 128);
|
||||
} else {
|
||||
for (i = 0; i < HDTRACK * HDSECTOR; i++)
|
||||
write(fd, (char *) sector, 128);
|
||||
}
|
||||
close(fd);
|
||||
return(0);
|
||||
}
|
106
emu/z80pack-1.9/cpmsim/srccpm2/putsys.c
Normal file
106
emu/z80pack-1.9/cpmsim/srccpm2/putsys.c
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Write the CP/M systemfiles to system tracks of drive A
|
||||
*
|
||||
* Copyright (C) 1988-2006 by Udo Munk
|
||||
*
|
||||
* History:
|
||||
* 29-APR-88 Development on TARGON/35 with AT&T Unix System V.3
|
||||
* 11-MAR-93 comments in english and ported to COHERENT 4.0
|
||||
* 02-OCT-06 modified to compile on modern POSIX OS's
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <memory.h>
|
||||
|
||||
/*
|
||||
* This program writes the CP/M 2.2 OS from the following files
|
||||
* onto the system tracks of the boot disk (drivea.cpm):
|
||||
*
|
||||
* boot loader boot.bin (Mostek binary format)
|
||||
* CCP cpm.bin (binary format)
|
||||
* BDOS cpm.bin (binary format)
|
||||
* BIOS bios.bin (Mostek binary format)
|
||||
*/
|
||||
int main(void)
|
||||
{
|
||||
unsigned char header[3];
|
||||
unsigned char sector[128];
|
||||
register int i;
|
||||
int fd, drivea, readed;
|
||||
|
||||
/* open drive A for writing */
|
||||
if ((drivea = open("../disks/drivea.cpm", O_WRONLY)) == -1) {
|
||||
perror("file ../disks/drivea.cpm");
|
||||
exit(1);
|
||||
}
|
||||
/* open boot loader (boot.bin) for reading */
|
||||
if ((fd = open("boot.bin", O_RDONLY)) == -1) {
|
||||
perror("file boot.bin");
|
||||
exit(1);
|
||||
}
|
||||
/* read and check 3 byte header */
|
||||
if ((readed = read(fd, (char *) header, 3)) != 3) {
|
||||
perror("file boot.bin");
|
||||
exit(1);
|
||||
}
|
||||
if (header[0] != 0xff || header[1] != 0 || header[2] != 0) {
|
||||
puts("start adress of boot.bin <> 0");
|
||||
exit(0);
|
||||
}
|
||||
/* read boot loader */
|
||||
memset((char *) sector, 0, 128);
|
||||
read(fd, (char *) sector, 128);
|
||||
close(fd);
|
||||
/* and write it to disk in drive A */
|
||||
write(drivea, (char *) sector, 128);
|
||||
/* open CP/M system file (cpm.bin) for reading */
|
||||
if ((fd = open("cpm.bin", O_RDONLY)) == -1) {
|
||||
perror("file cpm.bin");
|
||||
exit(1);
|
||||
}
|
||||
/* position to CCP in cpm.bin, needed if created with SAVE or similar */
|
||||
lseek(fd, (long) 17 * 128, 0);
|
||||
/* read CCP and BDOS from cpm.bin and write them to disk in drive A */
|
||||
for (i = 0; i < 44; i++) {
|
||||
if ((readed = read(fd, (char *) sector, 128)) != 128) {
|
||||
perror("file cpm.bin");
|
||||
exit(1);
|
||||
}
|
||||
write(drivea, (char *) sector, 128);
|
||||
}
|
||||
close(fd);
|
||||
/* open BIOS (bios.bin) for reading */
|
||||
if ((fd = open("bios.bin", O_RDONLY)) == -1) {
|
||||
perror("file bios.bin");
|
||||
exit(1);
|
||||
}
|
||||
/* read and check 3 byte header */
|
||||
if ((readed = read(fd, (char *) header, 3)) != 3) {
|
||||
perror("file bios.bin");
|
||||
exit(1);
|
||||
}
|
||||
if (header[0] != 0xff) {
|
||||
puts("unknown format of bios.bin");
|
||||
exit(0);
|
||||
}
|
||||
/* read BIOS from bios.bin and write it to disk in drive A */
|
||||
i = 0;
|
||||
while ((readed = read(fd, (char *) sector, 128)) == 128) {
|
||||
write(drivea, (char *) sector, 128);
|
||||
i++;
|
||||
if (i == 6) {
|
||||
puts("6 sectors written, can't write any more!");
|
||||
goto stop;
|
||||
}
|
||||
}
|
||||
if (readed > 0) {
|
||||
write(drivea, (char *) sector, 128);
|
||||
}
|
||||
stop:
|
||||
close(fd);
|
||||
close(drivea);
|
||||
return(0);
|
||||
}
|
56
emu/z80pack-1.9/cpmsim/srccpm2/receive.c
Normal file
56
emu/z80pack-1.9/cpmsim/srccpm2/receive.c
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Receive a file out of the named pipe "auxout" from CP/M simulation
|
||||
*
|
||||
* Copyright (C) 1988-2006 by Udo Munk
|
||||
*
|
||||
* History:
|
||||
* 05-OKT-88 Development on TARGON/35 with AT&T Unix System V.3
|
||||
* 11-MAR-93 comments in english and ported to COHERENT 4.0
|
||||
* 01-OCT-06 modified to compile on modern POSIX OS's
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
int fdin, fdout;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char c;
|
||||
void int_handler(void);
|
||||
|
||||
if (argc != 2) {
|
||||
puts("usage: receive filname &");
|
||||
exit(1);
|
||||
}
|
||||
if ((fdin = open("auxout", O_RDONLY)) == -1) {
|
||||
perror("pipe auxout");
|
||||
exit(1);
|
||||
}
|
||||
if ((fdout = creat(argv[1], 0644)) == -1) {
|
||||
perror(argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
signal(SIGINT, SIG_IGN);
|
||||
signal(SIGQUIT, SIG_IGN);
|
||||
signal(SIGHUP, int_handler);
|
||||
|
||||
for (;;) {
|
||||
if (read(fdin, &c, 1) == 1)
|
||||
if (c != '\r')
|
||||
write(fdout, &c, 1);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
void int_handler(void)
|
||||
{
|
||||
close(fdin);
|
||||
close(fdout);
|
||||
exit(0);
|
||||
}
|
57
emu/z80pack-1.9/cpmsim/srccpm2/send.c
Normal file
57
emu/z80pack-1.9/cpmsim/srccpm2/send.c
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Sends a file through named pipe "auxin" to the CP/M simulation
|
||||
*
|
||||
* Copyright (C) 1988-2006 by Udo Munk
|
||||
*
|
||||
* History:
|
||||
* 05-OKT-88 Development on TARGON/35 with AT&T Unix System V.3
|
||||
* 11-MAR-93 comments in english and ported to COHERENT 4.0
|
||||
* 01-OCT-06 modified to compile on modern POSIX OS's
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
void sendbuf(int);
|
||||
|
||||
char buf[BUFSIZ];
|
||||
char cr = '\r';
|
||||
int fdout, fdin;
|
||||
|
||||
int main(int argc,char *argv[])
|
||||
{
|
||||
register int readed;
|
||||
|
||||
if (argc != 2) {
|
||||
puts("usage: send filname &");
|
||||
exit(1);
|
||||
}
|
||||
if ((fdin = open(argv[1], O_RDONLY)) == -1) {
|
||||
perror(argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
if ((fdout = open("auxin", O_WRONLY)) == -1) {
|
||||
perror("pipe auxin");
|
||||
exit(1);
|
||||
}
|
||||
while ((readed = read(fdin, buf, BUFSIZ)) == BUFSIZ)
|
||||
sendbuf(BUFSIZ);
|
||||
if (readed)
|
||||
sendbuf(readed);
|
||||
close(fdin);
|
||||
close(fdout);
|
||||
return(0);
|
||||
}
|
||||
|
||||
void sendbuf(int size)
|
||||
{
|
||||
register char *s = buf;
|
||||
|
||||
while (s - buf < size) {
|
||||
if (*s == '\n')
|
||||
write(fdout, (char *) &cr, 1);
|
||||
write(fdout, s++, 1);
|
||||
}
|
||||
}
|
13
emu/z80pack-1.9/cpmsim/srccpm3/Makefile
Normal file
13
emu/z80pack-1.9/cpmsim/srccpm3/Makefile
Normal file
@@ -0,0 +1,13 @@
|
||||
CFLAGS= -O -s
|
||||
|
||||
all: putsys boot.bin
|
||||
echo done
|
||||
|
||||
putsys: putsys.c
|
||||
cc $(CFLAGS) -o putsys putsys.c
|
||||
|
||||
boot.bin: boot.asm
|
||||
z80asm -vl -sn -fb boot.asm
|
||||
|
||||
clean:
|
||||
rm -f *.lis putsys boot.bin
|
582
emu/z80pack-1.9/cpmsim/srccpm3/bios3.mac
Normal file
582
emu/z80pack-1.9/cpmsim/srccpm3/bios3.mac
Normal file
@@ -0,0 +1,582 @@
|
||||
; CP/M 3 BIOS for Z80-Simulator
|
||||
;
|
||||
; Copyright (C) 1989-2006 by Udo Munk
|
||||
;
|
||||
.Z80
|
||||
;
|
||||
; bdos functions
|
||||
;
|
||||
WARM EQU 0
|
||||
BDOS EQU 5
|
||||
PRINT EQU 9
|
||||
OPEN EQU 15
|
||||
READS EQU 20
|
||||
DMA EQU 26
|
||||
MULTI EQU 44
|
||||
;
|
||||
; i/o ports
|
||||
;
|
||||
CONSTA EQU 0 ;console status port
|
||||
CONDAT EQU 1 ;console data port
|
||||
PRTSTA EQU 2 ;printer status port
|
||||
PRTDAT EQU 3 ;printer data port
|
||||
AUXSTA EQU 4 ;auxilary status port
|
||||
AUXDAT EQU 5 ;auxilary data port
|
||||
FDCD EQU 10 ;fdc-port: # of drive
|
||||
FDCT EQU 11 ;fdc-port: # of track
|
||||
FDCS EQU 12 ;fdc-port: # of sector
|
||||
FDCOP EQU 13 ;fdc-port: command
|
||||
FDCST EQU 14 ;fdc-port: status
|
||||
DMAL EQU 15 ;dma-port: dma address low
|
||||
DMAH EQU 16 ;dma-port: dma address high
|
||||
MMUINI EQU 20 ;initialize mmu
|
||||
MMUSEL EQU 21 ;bank select mmu
|
||||
CLKCMD EQU 25 ;clock command
|
||||
CLKDAT EQU 26 ;clock data
|
||||
;
|
||||
; clock commands
|
||||
;
|
||||
GETSEC EQU 0 ;get seconds
|
||||
GETMIN EQU 1 ;get minutes
|
||||
GETHOU EQU 2 ;get hours
|
||||
GETDAL EQU 3 ;get days low
|
||||
GETDAH EQU 4 ;get days high
|
||||
;
|
||||
; character device mode byte fields
|
||||
;
|
||||
mb$input EQU 00000001B ;device may do input
|
||||
mb$output EQU 00000010B ;device may do output
|
||||
mb$in$out EQU mb$input+mb$output ;device may do both
|
||||
baud$none EQU 0
|
||||
;
|
||||
; external references in scb
|
||||
;
|
||||
EXTRN @civec, @covec, @aovec, @aivec, @lovec, @bnkbf
|
||||
EXTRN @crdma, @crdsk, @fx, @resel, @vinfo, @usrcd
|
||||
EXTRN @ermde, @date, @hour, @min, @sec, @mxtpa
|
||||
;
|
||||
CSEG
|
||||
;
|
||||
; cp/m 3 jump vector for individual subroutines
|
||||
;
|
||||
JP BOOT ;perform cold start initialization
|
||||
WBOOTE: JP WBOOT ;perform warm start initialization
|
||||
JP CONST ;check for console input char ready
|
||||
JP CONIN ;read console character in
|
||||
JP CONOUT ;write console character out
|
||||
JP LIST ;write list character out
|
||||
JP AUXOUT ;write auxiliary output char
|
||||
JP AUXIN ;read auxiliary input char
|
||||
JP HOME ;move head to track 0 on selcted disk
|
||||
JP SELDSK ;select disk drive
|
||||
JP SETTRK ;set track number
|
||||
JP SETSEC ;set sector number
|
||||
JP SETDMA ;set dma address
|
||||
JP READ ;read specified sector
|
||||
JP WRITE ;write specified sector
|
||||
JP LISTST ;return list status
|
||||
JP SECTRAN ;translate logical to physical sector
|
||||
JP CONOST ;return output status of console
|
||||
JP AUXIST ;return input status of aux. port
|
||||
JP AUXOST ;return output status of aux. port
|
||||
JP DEVTBL ;return address of character i/o table
|
||||
JP DEVINI ;initialize character i/o devices
|
||||
JP DRVTBL ;return address of disk drive table
|
||||
JP MULTIO ;set number of sectors to read/write
|
||||
JP FLUSH ;flush deblocking buffers
|
||||
JP MOVE ;memory to memory move
|
||||
JP TIME ;time set/get signal
|
||||
JP SELMEM ;select bank of memory
|
||||
JP SETBNK ;specify bank for dma operation
|
||||
JP XMOVE ;set bank for memory dma transfer
|
||||
JP 0 ;reserved for system implementor
|
||||
JP 0 ;reserved for future use
|
||||
JP 0 ;reserved for future use
|
||||
;
|
||||
; drive table
|
||||
;
|
||||
DRIVES: DW DPH0
|
||||
DW DPH1
|
||||
DW DPH2
|
||||
DW DPH3
|
||||
DW 0
|
||||
DW 0
|
||||
DW 0
|
||||
DW 0
|
||||
DW DPH8
|
||||
DW DPH9
|
||||
DW 0
|
||||
DW 0
|
||||
DW 0
|
||||
DW 0
|
||||
DW 0
|
||||
DW 0
|
||||
;
|
||||
; fixed data tables for IBM-compatible 8" disks
|
||||
;
|
||||
; disk parameter header
|
||||
;
|
||||
DPH0: DEFW TRANS ;sector translation table
|
||||
DB 0,0,0,0,0,0,0,0,0 ;bdos scratch area
|
||||
DB 0 ;media flag
|
||||
DEFW DPB0 ;disk parameter block
|
||||
DEFW 0FFFEH ;checksum vector
|
||||
DEFW 0FFFEH ;allocation vector
|
||||
DEFW 0FFFEH ;directory buffer control block
|
||||
DEFW 0FFFFH ;dtabcb not used
|
||||
DEFW 0FFFEH ;hashing
|
||||
DEFB 0 ;hash bank
|
||||
DPH1: DEFW TRANS ;sector translation table
|
||||
DB 0,0,0,0,0,0,0,0,0 ;bdos scratch area
|
||||
DB 0 ;media flag
|
||||
DEFW DPB0 ;disk parameter block
|
||||
DEFW 0FFFEH ;checksum vector
|
||||
DEFW 0FFFEH ;allocation vector
|
||||
DEFW 0FFFEH ;directory buffer control block
|
||||
DEFW 0FFFFH ;dtabcb not used
|
||||
DEFW 0FFFEH ;hashing
|
||||
DEFB 0 ;hash bank
|
||||
DPH2: DEFW TRANS ;sector translation table
|
||||
DB 0,0,0,0,0,0,0,0,0 ;bdos scratch area
|
||||
DB 0 ;media flag
|
||||
DEFW DPB0 ;disk parameter block
|
||||
DEFW 0FFFEH ;checksum vector
|
||||
DEFW 0FFFEH ;allocation vector
|
||||
DEFW 0FFFEH ;directory buffer control block
|
||||
DEFW 0FFFFH ;dtabcb not used
|
||||
DEFW 0FFFEH ;hashing
|
||||
DEFB 0 ;hash bank
|
||||
DPH3: DEFW TRANS ;sector translation table
|
||||
DB 0,0,0,0,0,0,0,0,0 ;bdos scratch area
|
||||
DB 0 ;media flag
|
||||
DEFW DPB0 ;disk parameter block
|
||||
DEFW 0FFFEH ;checksum vector
|
||||
DEFW 0FFFEH ;allocation vector
|
||||
DEFW 0FFFEH ;directory buffer control block
|
||||
DEFW 0FFFFH ;dtabcb not used
|
||||
DEFW 0FFFEH ;hashing
|
||||
DEFB 0 ;hash bank
|
||||
;
|
||||
; sector translate vector for the IBM 8" disk
|
||||
;
|
||||
TRANS: DEFB 1,7,13,19 ;sectors 1,2,3,4
|
||||
DEFB 25,5,11,17 ;sectors 5,6,7,8
|
||||
DEFB 23,3,9,15 ;sectors 9,10,11,12
|
||||
DEFB 21,2,8,14 ;sectors 13,14,15,16
|
||||
DEFB 20,26,6,12 ;sectors 17,18,19,20
|
||||
DEFB 18,24,4,10 ;sectors 21,22,23,24
|
||||
DEFB 16,22 ;sectors 25,26
|
||||
;
|
||||
; disk parameter block for the IBM 8" disk
|
||||
;
|
||||
DPB0: DEFW 26 ;sectors per track
|
||||
DEFB 3 ;block shift factor
|
||||
DEFB 7 ;block mask
|
||||
DEFB 0 ;extent mask
|
||||
DEFW 242 ;disk size-1
|
||||
DEFW 63 ;directory max
|
||||
DEFB 192 ;alloc 0
|
||||
DEFB 0 ;alloc 1
|
||||
DEFW 16 ;check size
|
||||
DEFW 2 ;track offset
|
||||
DEFB 0,0 ;physical sector size and shift
|
||||
;
|
||||
; fixed data tables for 4mb harddisks
|
||||
;
|
||||
; disk parameter header
|
||||
;
|
||||
DPH8: DEFW HDTRA ;sector translation table
|
||||
DB 0,0,0,0,0,0,0,0,0 ;bdos scratch area
|
||||
DB 0 ;media flag
|
||||
DEFW DPB1 ;disk parameter block
|
||||
DEFW 0FFFEH ;checksum vector
|
||||
DEFW 0FFFEH ;allocation vector
|
||||
DEFW 0FFFEH ;directory buffer control block
|
||||
DEFW 0FFFFH ;dtabcb not used
|
||||
DEFW 0FFFEH ;hashing
|
||||
DEFB 0 ;hash bank
|
||||
DPH9: DEFW HDTRA ;sector translation table
|
||||
DB 0,0,0,0,0,0,0,0,0 ;bdos scratch area
|
||||
DB 0 ;media flag
|
||||
DEFW DPB1 ;disk parameter block
|
||||
DEFW 0FFFEH ;checksum vector
|
||||
DEFW 0FFFEH ;allocation vector
|
||||
DEFW 0FFFEH ;directory buffer control block
|
||||
DEFW 0FFFFH ;dtabcb not used
|
||||
DEFW 0FFFEH ;hashing
|
||||
DEFB 0 ;hash bank
|
||||
;
|
||||
; sector translate vector for 4mb harddisk
|
||||
;
|
||||
HDTRA: DEFB 1,2,3,4,5,6,7,8,9,10
|
||||
DEFB 11,12,13,14,15,16,17,18,19,20
|
||||
DEFB 21,22,23,24,25,26,27,28,29,30
|
||||
DEFB 31,32,33,34,35,36,37,38,39,40
|
||||
DEFB 41,42,43,44,45,46,47,48,49,50
|
||||
DEFB 51,52,53,54,55,56,57,58,59,60
|
||||
DEFB 61,62,63,64,65,66,67,68,69,70
|
||||
DEFB 71,72,73,74,75,76,77,78,79,80
|
||||
DEFB 81,82,83,84,85,86,87,88,89,90
|
||||
DEFB 91,92,93,94,95,96,97,98,99,100
|
||||
DEFB 101,102,103,104,105,106,107,108,109,110
|
||||
DEFB 111,112,113,114,115,116,117,118,119,120
|
||||
DEFB 121,122,123,124,125,126,127,128
|
||||
;
|
||||
; disk parameter block for 4mb harddisk
|
||||
;
|
||||
DPB1: DEFW 128 ;sectors per track
|
||||
DEFB 4 ;block shift factor
|
||||
DEFB 15 ;block mask
|
||||
DEFB 0 ;extent mask
|
||||
DEFW 2039 ;disk size-1
|
||||
DEFW 1023 ;directory max
|
||||
DEFB 255 ;alloc 0
|
||||
DEFB 255 ;alloc 1
|
||||
DEFW 0 ;check size
|
||||
DEFW 0 ;track offset
|
||||
DEFB 0,0 ;physical sector size and shift
|
||||
;
|
||||
; character device table
|
||||
;
|
||||
CHRTBL: DEFB 'CRT '
|
||||
DEFB mb$in$out
|
||||
DEFB baud$none
|
||||
DEFB 'LPT '
|
||||
DEFB mb$output
|
||||
DEFB baud$none
|
||||
DEFB 'PTP '
|
||||
DEFB mb$output
|
||||
DEFB baud$none
|
||||
DEFB 'PTR '
|
||||
DEFB mb$input
|
||||
DEFB baud$none
|
||||
DEFB 0
|
||||
;
|
||||
; signon message
|
||||
;
|
||||
SIGNON: DEFB 13,10
|
||||
DEFM 'BANKED BIOS3 V1.4 for Z80SIM, '
|
||||
DEFM 'Copyright 1989-2006 by Udo Munk'
|
||||
DEFB 13,10
|
||||
DEFB 0
|
||||
;
|
||||
; small stack
|
||||
;
|
||||
DS 8
|
||||
STACK:
|
||||
;
|
||||
; fcb for loading ccp
|
||||
;
|
||||
CCPFCB: DEFB 1,'CCP COM',0,0,0,0
|
||||
DEFB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
CCPREC: DEFB 0,0,0
|
||||
;
|
||||
DSEG
|
||||
;
|
||||
; bios error messages
|
||||
;
|
||||
CCPOER: DEFB 13,10,'BIOS ERROR: cannot open CCP.COM',13,10,'$'
|
||||
CCPIOE: DEFB 13,10,'BIOS ERROR: reading CCP.COM',13,10,'$'
|
||||
;
|
||||
CSEG
|
||||
;
|
||||
DRIVE: DEFB 0 ;drive to select
|
||||
BANK: DEFB 0 ;bank to select for dma
|
||||
;
|
||||
; end of fixed tables
|
||||
;
|
||||
; individual subroutines to perform each function
|
||||
;
|
||||
DSEG
|
||||
;
|
||||
BOOT: LD B,1 ;indicate cold boot
|
||||
;
|
||||
LD HL,8000H
|
||||
LD (@civec),HL ;CONSOLE:=CON for input
|
||||
LD (@covec),HL ;CONSOLE:=CON for output
|
||||
LD HL,4000H
|
||||
LD (@lovec),HL ;LST:=LPT
|
||||
LD HL,2000H
|
||||
LD (@aovec),HL ;AUXOUT:=PTP
|
||||
LD HL,1000H
|
||||
LD (@aivec),HL ;AUXIN:=PTR
|
||||
;
|
||||
LD A,3 ;initialize 3 memory banks
|
||||
OUT (MMUINI),A
|
||||
JP WBOOT1
|
||||
;
|
||||
CSEG
|
||||
;
|
||||
WBOOT: LD B,0 ;indicate warm boot
|
||||
WBOOT1: LD SP,STACK
|
||||
;
|
||||
; initialize low memory jumps in bank 1
|
||||
;
|
||||
LD A,1
|
||||
CALL SELMEM
|
||||
;
|
||||
LD A,0C3H ;jmp instruction
|
||||
LD (WARM),A
|
||||
LD HL,WBOOTE ;warm boot enty point
|
||||
LD (WARM+1),HL
|
||||
LD (BDOS),A
|
||||
LD HL,(@mxtpa) ;bdos entry point
|
||||
LD (BDOS+1),HL
|
||||
;
|
||||
; print message on cold boot
|
||||
;
|
||||
LD A,B
|
||||
OR A
|
||||
JP Z,LDCCP
|
||||
LD HL,SIGNON ;print message
|
||||
WBOOT2: LD A,(HL)
|
||||
OR A
|
||||
JP Z,LDCCP
|
||||
LD C,A
|
||||
CALL CONOUT
|
||||
INC HL
|
||||
JP WBOOT2
|
||||
;
|
||||
; load ccp.com into tpa
|
||||
;
|
||||
LDCCP: XOR A ;initialize fcb
|
||||
LD (CCPFCB+15),A
|
||||
LD HL,0
|
||||
LD (CCPREC),HL
|
||||
LD DE,CCPFCB ;open file ccp.com
|
||||
LD C,OPEN
|
||||
CALL BDOS
|
||||
LD DE,CCPOER
|
||||
INC A
|
||||
JP Z,CCPERR ;print error if file not found
|
||||
LD DE,0100H ;setup DMA to tpa
|
||||
LD C,DMA
|
||||
CALL BDOS
|
||||
LD DE,128 ;read up to 16KB
|
||||
LD C,MULTI
|
||||
CALL BDOS
|
||||
LD DE,CCPFCB ;read the ccp into memory
|
||||
LD C,READS
|
||||
CALL BDOS
|
||||
LD DE,CCPIOE
|
||||
INC A
|
||||
JP NZ,0100H ;start ccp
|
||||
CCPERR: LD C,PRINT ;print error message
|
||||
CALL BDOS
|
||||
HALT
|
||||
;
|
||||
; character i/o drivers
|
||||
;
|
||||
DEVTBL: LD HL,CHRTBL
|
||||
RET
|
||||
;
|
||||
; character device initialization
|
||||
;
|
||||
DEVINI: RET
|
||||
;
|
||||
; console in status, return 0ffh if character ready, 00h if not
|
||||
;
|
||||
CONST: IN A,(CONSTA)
|
||||
RET
|
||||
;
|
||||
; console character input from register a
|
||||
;
|
||||
CONIN: IN A,(CONDAT)
|
||||
RET
|
||||
;
|
||||
; console out status, return 0ffh if ready, 00h if not
|
||||
CONOST: LD A,0FFH ;console out always ready
|
||||
RET
|
||||
;
|
||||
; console character output from register c
|
||||
;
|
||||
CONOUT: LD A,C ;get to accumulator
|
||||
OUT (CONDAT),A ;send character to console
|
||||
RET
|
||||
;
|
||||
; list out status, return 0ffh if ready, 00h if not
|
||||
;
|
||||
LISTST: LD A,0FFH ;list out always ready
|
||||
RET
|
||||
;
|
||||
; list character output from register C
|
||||
;
|
||||
LIST: LD A,C
|
||||
OUT (PRTDAT),A
|
||||
RET
|
||||
;
|
||||
; auxilary input status, 0ffh if ready, 00h if not
|
||||
;
|
||||
AUXIST: XOR A ;never ready, hardware not available yet
|
||||
RET
|
||||
;
|
||||
; auxilary output status, 0ffh if ready, 00h if not
|
||||
;
|
||||
AUXOST: XOR A ;never ready, hadware not available yet
|
||||
RET
|
||||
;
|
||||
; auxilary input
|
||||
;
|
||||
AUXIN: IN A,(AUXDAT)
|
||||
RET
|
||||
;
|
||||
; auxilary output from register c
|
||||
;
|
||||
AUXOUT: LD A,C
|
||||
OUT (AUXDAT),A
|
||||
RET
|
||||
;
|
||||
;
|
||||
; i/o drivers for the disks
|
||||
;
|
||||
DRVTBL: LD HL,DRIVES
|
||||
RET
|
||||
;
|
||||
DSEG
|
||||
;
|
||||
; move to the track 00 position of current drive
|
||||
; translate this call into a settrk call with parameter 00
|
||||
;
|
||||
HOME: LD C,0 ;select track 0
|
||||
JP SETTRK ;we will move to 00 on first read/write
|
||||
;
|
||||
; select disk given by register C
|
||||
;
|
||||
SELDSK: LD HL,0000H ;error return code
|
||||
LD A,C
|
||||
LD (DRIVE),A
|
||||
CP 4 ;disk drive 1-4?
|
||||
JP C,SEL1 ;go
|
||||
CP 8 ;harddisk 1?
|
||||
JP Z,SEL1 ;go
|
||||
CP 9 ;harddisk 2?
|
||||
RET NZ ;no, error
|
||||
; disk number is in the proper range
|
||||
; return proper disk parameter header address
|
||||
SEL1: LD L,C
|
||||
LD H,0
|
||||
ADD HL,HL ;drive index in hl
|
||||
LD BC,DRIVES
|
||||
ADD HL,BC ;get pointer to dph
|
||||
LD A,(HL)
|
||||
INC HL
|
||||
LD H,(HL)
|
||||
LD L,A
|
||||
LD A,(DRIVE)
|
||||
OUT (FDCD),A ;selekt disk drive
|
||||
RET
|
||||
;
|
||||
; set track given by register c
|
||||
;
|
||||
SETTRK: LD A,C
|
||||
OUT (FDCT),A
|
||||
RET
|
||||
;
|
||||
; set sector given by register c
|
||||
;
|
||||
SETSEC: LD A,C
|
||||
OUT (FDCS),A
|
||||
RET
|
||||
;
|
||||
; translate the sector given by bc using the
|
||||
; translate table given by de
|
||||
;
|
||||
SECTRAN:
|
||||
EX DE,HL ;hl=.trans
|
||||
ADD HL,BC ;hl=.trans(sector)
|
||||
LD L,(HL) ;l = trans(sector)
|
||||
LD H,0 ;hl= trans(sector)
|
||||
RET ;with value in HL
|
||||
;
|
||||
; set dma address given by registers b and c
|
||||
;
|
||||
SETDMA: LD A,C ;low order address
|
||||
OUT (DMAL),A
|
||||
LD A,B ;high order address
|
||||
OUT (DMAH),A
|
||||
RET
|
||||
;
|
||||
CSEG
|
||||
;
|
||||
; perform read operation
|
||||
;
|
||||
READ: LD A,(BANK) ;switch to saved bank
|
||||
OUT (MMUSEL),A
|
||||
XOR A ;read command -> A
|
||||
JP WAITIO ;to perform the actual i/o
|
||||
;
|
||||
; perform write operation
|
||||
;
|
||||
WRITE: LD A,(BANK) ;switch to saved bank
|
||||
OUT (MMUSEL),A
|
||||
LD A,1 ;write command -> A
|
||||
;
|
||||
; enter here from read and write to perform the actual i/o
|
||||
; operation. return 00h in register a if the operation completes
|
||||
; properly, and 01h if an error occurs during the read or write
|
||||
;
|
||||
WAITIO: OUT (FDCOP),A ;start i/o operation
|
||||
XOR A ;reselect bank 0
|
||||
OUT (MMUSEL),A
|
||||
IN A,(FDCST) ;status of i/o operation -> A
|
||||
RET
|
||||
;
|
||||
; nothing to do
|
||||
;
|
||||
MULTIO: XOR A
|
||||
RET
|
||||
;
|
||||
; nothing to do
|
||||
;
|
||||
FLUSH: XOR A
|
||||
RET
|
||||
;
|
||||
; memory move
|
||||
;
|
||||
MOVE: EX DE,HL
|
||||
LDIR
|
||||
EX DE,HL
|
||||
RET
|
||||
;
|
||||
; select memory bank
|
||||
SELMEM: OUT (MMUSEL),A
|
||||
RET
|
||||
;
|
||||
; specify memory bank for dma operation
|
||||
SETBNK: LD (BANK),A
|
||||
RET
|
||||
;
|
||||
; xmove not implemented yet, hardware missing
|
||||
;
|
||||
XMOVE: RET
|
||||
;
|
||||
; get/set time
|
||||
;
|
||||
TIME:
|
||||
LD A,C
|
||||
CP 0FFH
|
||||
RET Z ;we cannot set the UNIX time from here
|
||||
LD A,GETSEC ;get seconds
|
||||
OUT (CLKCMD),A
|
||||
IN A,(CLKDAT)
|
||||
LD (@sec),A
|
||||
LD A,GETMIN ;get minutes
|
||||
OUT (CLKCMD),A
|
||||
IN A,(CLKDAT)
|
||||
LD (@min),A
|
||||
LD A,GETHOU ;get hours
|
||||
OUT (CLKCMD),A
|
||||
IN A,(CLKDAT)
|
||||
LD (@hour),A
|
||||
LD A,GETDAL ;get day
|
||||
OUT (CLKCMD),A
|
||||
IN A,(CLKDAT)
|
||||
LD (@date),A
|
||||
LD A,GETDAH
|
||||
OUT (CLKCMD),A
|
||||
IN A,(CLKDAT)
|
||||
LD (@date+1),A
|
||||
RET
|
||||
;
|
||||
ENDDAT EQU $ ;end
|
||||
END ;of BIOS
|
67
emu/z80pack-1.9/cpmsim/srccpm3/boot.asm
Normal file
67
emu/z80pack-1.9/cpmsim/srccpm3/boot.asm
Normal file
@@ -0,0 +1,67 @@
|
||||
; CP/M 3 boot-loader for Z80-Simulator
|
||||
;
|
||||
; Copyright (C) 1989-2006 by Udo Munk
|
||||
;
|
||||
ORG 0 ; mem base of boot
|
||||
;
|
||||
BOOT EQU 0100H ; cpmldr runs at 0100H
|
||||
SECTS EQU 51 ; # of sectors to load (26 * 2 - 1)
|
||||
;
|
||||
; I/O ports
|
||||
;
|
||||
DRIVE EQU 10 ; fdc-port: # of drive
|
||||
TRACK EQU 11 ; fdc-port: # of track
|
||||
SECTOR EQU 12 ; fdc-port: # of sector
|
||||
FDCOP EQU 13 ; fdc-port: command
|
||||
FDCST EQU 14 ; fdc-port: status
|
||||
DMAL EQU 15 ; dma-port: dma address low
|
||||
DMAH EQU 16 ; dma-port: dma address high
|
||||
;
|
||||
; begin the load operation
|
||||
;
|
||||
COLD: LD BC,2 ; b=track 0, c=sector 2
|
||||
LD D,SECTS ; d=# sectors to load
|
||||
LD HL,BOOT ; base transfer address
|
||||
LD A,0 ; select drive A
|
||||
OUT (DRIVE),A
|
||||
;
|
||||
; load the next sector
|
||||
;
|
||||
LSECT: LD A,B ; set track
|
||||
OUT (TRACK),A
|
||||
LD A,C ; set sector
|
||||
OUT (SECTOR),A
|
||||
LD A,L ; set dma address low
|
||||
OUT (DMAL),A
|
||||
LD A,H ; set dma adress high
|
||||
OUT (DMAH),A
|
||||
XOR A ; read sector
|
||||
OUT (FDCOP),A
|
||||
IN A,(FDCST) ; get status of fdc
|
||||
CP 0 ; read successful ?
|
||||
JP Z,CONT ; yes, continue
|
||||
HALT ; no, halt cpu
|
||||
CONT:
|
||||
; go to next sector if load is incomplete
|
||||
DEC D ; sects=sects-1
|
||||
JP Z,BOOT ; head for the bios
|
||||
;
|
||||
; more sectors to load
|
||||
;
|
||||
; we aren't using a stack, so use <sp> as scratch register
|
||||
; to hold the load address increment
|
||||
;
|
||||
LD SP,128 ; 128 bytes per sector
|
||||
ADD HL,SP ; <hl> = <hl> + 128
|
||||
;
|
||||
INC C ; sector = sector + 1
|
||||
LD A,C
|
||||
CP 27 ; last sector of track ?
|
||||
JP C,LSECT ; no, go read another
|
||||
;
|
||||
; end of track, increment to next track
|
||||
;
|
||||
LD C,1 ; sector = 1
|
||||
INC B ; track = track + 1
|
||||
JP LSECT ; for another group
|
||||
END ; of boot loader
|
BIN
emu/z80pack-1.9/cpmsim/srccpm3/cpmldr.bin
Normal file
BIN
emu/z80pack-1.9/cpmsim/srccpm3/cpmldr.bin
Normal file
Binary file not shown.
212
emu/z80pack-1.9/cpmsim/srccpm3/ldrbios3.mac
Normal file
212
emu/z80pack-1.9/cpmsim/srccpm3/ldrbios3.mac
Normal file
@@ -0,0 +1,212 @@
|
||||
; CP/M 3 LDRBIOS for Z80-Simulator
|
||||
;
|
||||
; Copyright (C) 1989-2006 by Udo Munk
|
||||
;
|
||||
.Z80
|
||||
;
|
||||
; I/O ports
|
||||
;
|
||||
CONSTA EQU 0 ;console status port
|
||||
CONDAT EQU 1 ;console data port
|
||||
FDCD EQU 10 ;fdc-port: # of drive
|
||||
FDCT EQU 11 ;fdc-port: # of track
|
||||
FDCS EQU 12 ;fdc-port: # of sector
|
||||
FDCOP EQU 13 ;fdc-port: command
|
||||
FDCST EQU 14 ;fdc-port: status
|
||||
DMAL EQU 15 ;dma-port: dma address low
|
||||
DMAH EQU 16 ;dma-port: dma address high
|
||||
;
|
||||
CSEG
|
||||
;
|
||||
; jump vector for individual subroutines
|
||||
; * needs to be implemented
|
||||
;
|
||||
JP BOOT ; * perform cold start initialization
|
||||
JP WBOOT ; perform warm start initialization
|
||||
JP CONST ; check for console input char ready
|
||||
JP CONIN ; read console character in
|
||||
JP CONOUT ; * write console character out
|
||||
JP LIST ; write list character out
|
||||
JP AUXOUT ; write auxiliary output char
|
||||
JP AUXIN ; read auxiliary input char
|
||||
JP HOME ; * move head to track 0 on selcted disk
|
||||
JP SELDSK ; * select disk drive
|
||||
JP SETTRK ; * set track number
|
||||
JP SETSEC ; * set sector number
|
||||
JP SETDMA ; * set dma address
|
||||
JP READ ; * read specified sector
|
||||
JP WRITE ; write specified sector
|
||||
JP LISTST ; return list status
|
||||
JP SECTRAN ; * translate logical to physical sector
|
||||
JP CONOST ; return output status of console
|
||||
JP AUXIST ; return input status of aux. port
|
||||
JP AUXOST ; return output status of aux. port
|
||||
JP DEVTBL ; return address of character i/o table
|
||||
JP DEVINI ; initialize character i/o devices
|
||||
JP DRVTBL ; return address of disk drive table
|
||||
JP MULTIO ; set number of sectors to read/write
|
||||
JP FLUSH ; flush deblocking buffers
|
||||
JP MOVE ; * memory to memory move
|
||||
JP TIME ; time set/get signal
|
||||
JP SELMEM ; select bank of memory
|
||||
JP SETBNK ; specify bank for dma operation
|
||||
JP XMOVE ; set bank for memory dma transfer
|
||||
JP 0 ; reserved for system implementor
|
||||
JP 0 ; reserved for future use
|
||||
JP 0 ; reserved for future use
|
||||
;
|
||||
; fixed data tables for a IBM-compatible 8" disk
|
||||
;
|
||||
; disk parameter header
|
||||
;
|
||||
DPH0: DEFW TRANS ;sector translation table
|
||||
DB 0,0,0,0,0,0,0,0,0 ;bdos scratch area
|
||||
DB 0 ;media flag
|
||||
DEFW DPB0 ;disk parameter block
|
||||
DEFW 0FFFEH ;checksum vector
|
||||
DEFW 0FFFEH ;allocation vector
|
||||
DEFW 0FFFEH ;directory buffer control block
|
||||
DEFW 0FFFFH ;dtabcb not used
|
||||
DEFW 0FFFFH ;hashing not used
|
||||
DEFB 0 ;hash bank
|
||||
;
|
||||
; sector translate vector for the IBM 8" disk
|
||||
;
|
||||
TRANS: DEFB 1,7,13,19 ;sectors 1,2,3,4
|
||||
DEFB 25,5,11,17 ;sectors 5,6,7,8
|
||||
DEFB 23,3,9,15 ;sectors 9,10,11,12
|
||||
DEFB 21,2,8,14 ;sectors 13,14,15,16
|
||||
DEFB 20,26,6,12 ;sectors 17,18,19,20
|
||||
DEFB 18,24,4,10 ;sectors 21,22,23,24
|
||||
DEFB 16,22 ;sectors 25,26
|
||||
;
|
||||
; disk parameter block for the IBM 8" disk
|
||||
;
|
||||
DPB0: DEFW 26 ;sectors per track
|
||||
DEFB 3 ;block shift factor
|
||||
DEFB 7 ;block mask
|
||||
DEFB 0 ;extent mask
|
||||
DEFW 242 ;disk size-1
|
||||
DEFW 63 ;directory max
|
||||
DEFB 192 ;alloc 0
|
||||
DEFB 0 ;alloc 1
|
||||
DEFW 16 ;check size
|
||||
DEFW 2 ;track offset
|
||||
DEFB 0,0 ;physical sector size and shift
|
||||
;
|
||||
; signon message
|
||||
;
|
||||
SIGNON: DEFB 13,10
|
||||
DEFM 'LDRBIOS3 V1.1 for Z80SIM, '
|
||||
DEFM 'Copyright 1989-2006 by Udo Munk'
|
||||
DEFB 13,10,0
|
||||
;
|
||||
; end of fixed tables
|
||||
;
|
||||
; individual subroutines to perform each function
|
||||
;
|
||||
BOOT: LD HL,SIGNON ;print message
|
||||
BOOTL: LD A,(HL)
|
||||
OR A
|
||||
JP Z,WBOOT
|
||||
LD C,A
|
||||
CALL CONOUT
|
||||
INC HL
|
||||
JP BOOTL
|
||||
;
|
||||
; those are not implemented in loader bios
|
||||
;
|
||||
WBOOT:
|
||||
CONST:
|
||||
CONIN:
|
||||
LIST:
|
||||
AUXOUT:
|
||||
AUXIN:
|
||||
WRITE:
|
||||
LISTST:
|
||||
CONOST:
|
||||
AUXIST:
|
||||
AUXOST:
|
||||
DEVTBL:
|
||||
DEVINI:
|
||||
DRVTBL:
|
||||
MULTIO:
|
||||
FLUSH:
|
||||
TIME:
|
||||
SELMEM:
|
||||
SETBNK:
|
||||
XMOVE: RET
|
||||
;
|
||||
; console character output from register c
|
||||
;
|
||||
CONOUT: LD A,C ;get to accumulator
|
||||
OUT (CONDAT),A ;send character to console
|
||||
RET
|
||||
;
|
||||
;
|
||||
; i/o drivers for the disk follow
|
||||
;
|
||||
; move to the track 00 position of current drive
|
||||
; translate this call into a settrk call with parameter 00
|
||||
;
|
||||
HOME: LD C,0 ;select track 0
|
||||
JP SETTRK ;we will move to 00 on first read/write
|
||||
;
|
||||
; select disk given by register C
|
||||
;
|
||||
SELDSK: LD HL,0000H ;error return code
|
||||
LD A,C
|
||||
CP 0 ;we boot from drive 0 only
|
||||
RET NZ ;return error
|
||||
; disk number is in the proper range
|
||||
; return proper disk parameter header address
|
||||
OUT (FDCD),A ;selekt disk drive
|
||||
LD HL,DPH0
|
||||
RET
|
||||
;
|
||||
; set track given by register c
|
||||
;
|
||||
SETTRK: LD A,C
|
||||
OUT (FDCT),A
|
||||
RET
|
||||
;
|
||||
; set sector given by register c
|
||||
;
|
||||
SETSEC: LD A,C
|
||||
OUT (FDCS),A
|
||||
RET
|
||||
;
|
||||
; translate the sector given by BC using the
|
||||
; translate table given by DE
|
||||
;
|
||||
SECTRAN:
|
||||
EX DE,HL ;hl=.trans
|
||||
ADD HL,BC ;hl=.trans(sector)
|
||||
LD L,(HL) ;l = trans(sector)
|
||||
LD H,0 ;hl= trans(sector)
|
||||
RET ;with value in hl
|
||||
;
|
||||
; set dma address given by registers b and c
|
||||
;
|
||||
SETDMA: LD A,C ;low order address
|
||||
OUT (DMAL),A
|
||||
LD A,B ;high order address
|
||||
OUT (DMAH),A ;in dma
|
||||
RET
|
||||
;
|
||||
; perform read operation
|
||||
;
|
||||
READ: XOR A ;read command -> a
|
||||
OUT (FDCOP),A ;start i/o operation
|
||||
IN A,(FDCST) ;status of i/o operation -> a
|
||||
RET
|
||||
;
|
||||
; memory move
|
||||
;
|
||||
MOVE: EX DE,HL
|
||||
LDIR
|
||||
EX DE,HL
|
||||
RET
|
||||
;
|
||||
ENDDAT EQU $ ;end
|
||||
END ;of bios
|
59
emu/z80pack-1.9/cpmsim/srccpm3/putsys.c
Normal file
59
emu/z80pack-1.9/cpmsim/srccpm3/putsys.c
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Write the CP/M 3 systemfiles to system tracks of drive A
|
||||
*
|
||||
* Copyright (C) 1988-2006 by Udo Munk
|
||||
*
|
||||
* History:
|
||||
* 29-APR-88 Development on TARGON/35 with AT&T Unix System V.3
|
||||
* 11-MAR-93 comments in english and ported to COHERENT 4.0
|
||||
* 02-OCT-06 modified to compile on modern POSIX OS's
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <memory.h>
|
||||
|
||||
/*
|
||||
* This program writes the CP/M 3 OS from the following files
|
||||
* onto the system tracks of the boot disk (drivea.cpm):
|
||||
*
|
||||
* boot loader boot.bin
|
||||
* cpmldr cpmldr.bin
|
||||
*/
|
||||
int main(void)
|
||||
{
|
||||
unsigned char sector[128];
|
||||
register int i;
|
||||
int fd, drivea, readed;
|
||||
|
||||
/* open drive A for writing */
|
||||
if ((drivea = open("../disks/drivea.cpm", O_WRONLY)) == -1) {
|
||||
perror("file ../disks/drivea.cpm");
|
||||
exit(1);
|
||||
}
|
||||
/* open boot loader (boot.bin) for reading */
|
||||
if ((fd = open("boot.bin", O_RDONLY)) == -1) {
|
||||
perror("file boot.bin");
|
||||
exit(1);
|
||||
}
|
||||
/* read boot loader */
|
||||
memset((char *) sector, 0, 128);
|
||||
read(fd, (char *) sector, 128);
|
||||
close(fd);
|
||||
/* and write it to disk in drive A */
|
||||
write(drivea, (char *) sector, 128);
|
||||
/* open CP/M 3 cpmldr file (cpmldr.bin) for reading */
|
||||
if ((fd = open("cpmldr.bin", O_RDONLY)) == -1) {
|
||||
perror("file cpmldr.bin");
|
||||
exit(1);
|
||||
}
|
||||
/* read from cpmldr.bin and write to disk in drive A */
|
||||
while ((readed = read(fd, (char *) sector, 128)) == 128)
|
||||
write(drivea, (char *) sector, 128);
|
||||
write(drivea, (char *) sector, 128);
|
||||
close(fd);
|
||||
close(drivea);
|
||||
return(0);
|
||||
}
|
503
emu/z80pack-1.9/cpmsim/srcmpm/bnkxios.mac
Normal file
503
emu/z80pack-1.9/cpmsim/srcmpm/bnkxios.mac
Normal file
@@ -0,0 +1,503 @@
|
||||
; MP/M 2 XIOS for Z80-Simulator
|
||||
;
|
||||
; Copyright (C) 1989-2006 by Udo Munk
|
||||
;
|
||||
.Z80
|
||||
CSEG
|
||||
;
|
||||
; i/o ports
|
||||
;
|
||||
CONSTA EQU 0 ;console status port
|
||||
CONDAT EQU 1 ;console data port
|
||||
PRTSTA EQU 2 ;printer status port
|
||||
PRTDAT EQU 3 ;printer data port
|
||||
AUXSTA EQU 4 ;auxilary status port
|
||||
AUXDAT EQU 5 ;auxilary data port
|
||||
FDCD EQU 10 ;fdc-port: # of drive
|
||||
FDCT EQU 11 ;fdc-port: # of track
|
||||
FDCS EQU 12 ;fdc-port: # of sector
|
||||
FDCOP EQU 13 ;fdc-port: command
|
||||
FDCST EQU 14 ;fdc-port: status
|
||||
DMAL EQU 15 ;dma-port: dma address low
|
||||
DMAH EQU 16 ;dma-port: dma address high
|
||||
MMUINI EQU 20 ;initialize mmu
|
||||
MMUSEL EQU 21 ;bank select mmu
|
||||
CLKCMD EQU 25 ;clock command
|
||||
CLKDAT EQU 26 ;clock data
|
||||
TIMER EQU 27 ;interrupt timer
|
||||
;
|
||||
; clock commands
|
||||
;
|
||||
GETSEC EQU 0 ;get seconds
|
||||
GETMIN EQU 1 ;get minutes
|
||||
GETHOU EQU 2 ;get hours
|
||||
GETDAL EQU 3 ;get days low
|
||||
GETDAH EQU 4 ;get days high
|
||||
;
|
||||
BDOS EQU 5 ;bdos calls
|
||||
SETTD EQU 104 ;bdos set time and date
|
||||
;
|
||||
POLL EQU 131 ;xdos poll function
|
||||
PLCI0 EQU 0 ;poll console in #0
|
||||
FLAGSET EQU 133 ;xdos flag set function
|
||||
SYSDATA EQU 154 ;xdos syste data address
|
||||
;
|
||||
; jump vector for individual subroutines
|
||||
;
|
||||
JP COMMONBASE ;commonbase
|
||||
JP WARMSTART ;warm start
|
||||
JP CONST ;console status
|
||||
JP CONIN ;console character in
|
||||
JP CONOUT ;console character out
|
||||
JP LIST ;list character out
|
||||
JP PUNCH ;not used by MP/M 2
|
||||
JP READER ;not used by MP/M 2
|
||||
JP HOME ;move head to home
|
||||
JP SELDSK ;select disk
|
||||
JP SETTRK ;set track numer
|
||||
JP SETSEC ;set sector number
|
||||
JP SETDMA ;set dma address
|
||||
JP READ ;read disk
|
||||
JP WRITE ;write disk
|
||||
JP LISTST ;not used by MP/M 2
|
||||
JP SECTRAN ;sector translate
|
||||
JP SELMEMORY ;select memory
|
||||
JP POLLDEVICE ;poll device
|
||||
JP STARTCLOCK ;start clock
|
||||
JP STOPCLOCK ;stop clock
|
||||
JP EXITREGION ;exit region
|
||||
JP MAXCONSOLE ;maximum console number
|
||||
JP SYSTEMINIT ;system initialization
|
||||
JP IDLE ;idle prozedure
|
||||
;
|
||||
COMMONBASE:
|
||||
JP COLDSTART
|
||||
SWTUSER:
|
||||
JP $-$
|
||||
SWTSYS: JP $-$
|
||||
PDISP: JP $-$
|
||||
XDOS: JP $-$
|
||||
SYSDAT: DEFW $-$
|
||||
;
|
||||
COLDSTART:
|
||||
WARMSTART:
|
||||
LD C,0
|
||||
JP XDOS ;system reset, terminate prozess
|
||||
;
|
||||
; MP/M II V2.0 Console Bios
|
||||
;
|
||||
CONST:
|
||||
CALL PTBLJMP ;compute and jump to handler
|
||||
DW PTSTI0
|
||||
;
|
||||
CONIN:
|
||||
CALL PTBLJMP ;compute and jump to handle
|
||||
DW PTIN0
|
||||
;
|
||||
CONOUT:
|
||||
CALL PTBLJMP ;compute and jump to handler
|
||||
DW PTOUT0
|
||||
;
|
||||
PTSTI0: IN A,(CONSTA) ;console 0 input
|
||||
RET
|
||||
;
|
||||
PTIN0: LD C,POLL ;poll console 0 status in
|
||||
LD E,PLCI0
|
||||
CALL XDOS ;poll console 0
|
||||
IN A,(CONDAT) ;read character
|
||||
AND 7FH ;strip parity
|
||||
RET
|
||||
;
|
||||
PTOUT0: LD A,C ;console 0 output
|
||||
OUT (CONDAT),A
|
||||
RET
|
||||
;
|
||||
PTBLJMP: ;compute and jump to handler
|
||||
LD A,D
|
||||
ADD A,A ;double table index for adress offset
|
||||
POP HL ;return adress of jump table
|
||||
LD E,A
|
||||
LD D,0
|
||||
ADD HL,DE ;table index * 2 + table base
|
||||
LD E,(HL) ;get handler address
|
||||
INC HL
|
||||
LD D,(HL)
|
||||
EX DE,HL
|
||||
JP (HL) ;jump to computed handler
|
||||
;
|
||||
LIST:
|
||||
LD A,C
|
||||
OUT (PRTDAT),A
|
||||
RET
|
||||
;
|
||||
; not used by MP/M 2
|
||||
PUNCH:
|
||||
READER:
|
||||
LISTST:
|
||||
RET
|
||||
;
|
||||
; MP/M II V2.0 Xios
|
||||
;
|
||||
; select/protect memory
|
||||
; BC = address of memory descriptor
|
||||
SELMEMORY:
|
||||
LD HL,3 ;offset memory bank in memory descriptor
|
||||
ADD HL,BC
|
||||
LD A,(HL) ;get bank
|
||||
OUT (MMUSEL),A ;and select it
|
||||
RET
|
||||
;
|
||||
; poll character devices
|
||||
;
|
||||
POLLDEVICE:
|
||||
JP PTSTI0 ;poll console 0 status in
|
||||
;
|
||||
; start clock
|
||||
;
|
||||
STARTCLOCK:
|
||||
LD A,0FFH
|
||||
LD (TICKN),A
|
||||
RET
|
||||
;
|
||||
; stop clock
|
||||
;
|
||||
STOPCLOCK:
|
||||
XOR A
|
||||
LD (TICKN),A
|
||||
RET
|
||||
;
|
||||
; exit region:
|
||||
; enable interrupt if not preempted or in dispatcher
|
||||
;
|
||||
EXITREGION:
|
||||
LD A,(PREEMP)
|
||||
OR A
|
||||
RET NZ
|
||||
EI
|
||||
RET
|
||||
;
|
||||
; maximum console number
|
||||
;
|
||||
MAXCONSOLE:
|
||||
LD A,1
|
||||
RET
|
||||
;
|
||||
; system initialization
|
||||
; C MP/M debugger restart #
|
||||
; DE MP/M entry point for debugger
|
||||
; HL BIOS jump table address
|
||||
;
|
||||
SYSTEMINIT:
|
||||
;
|
||||
;doesn't work
|
||||
PUSH HL
|
||||
LD C,SYSDATA ;get system data page address
|
||||
CALL XDOS
|
||||
CALL SETTOD ;set tod from hardware clock
|
||||
POP HL
|
||||
;
|
||||
LD A,8 ;initialize banked memory
|
||||
OUT (MMUINI),A
|
||||
LD B,A
|
||||
;
|
||||
SYS1: DEC B
|
||||
LD A,B
|
||||
OUT (MMUSEL),A ;select every bank and initialize
|
||||
LD A,0C3H ;jp instruction
|
||||
LD (0),A
|
||||
LD (38H),A
|
||||
LD (1),HL
|
||||
PUSH HL
|
||||
LD HL,INTHND
|
||||
LD (39H),HL
|
||||
POP HL
|
||||
JP NZ,SYS1
|
||||
;
|
||||
LD HL,SIGNON ;print message
|
||||
SYS2: LD A,(HL)
|
||||
OR A
|
||||
JP Z,SYS3
|
||||
OUT (CONDAT),A
|
||||
INC HL
|
||||
JP SYS2
|
||||
;
|
||||
SYS3: IM 1
|
||||
LD A,1 ;enable 20ms interrupt timer
|
||||
OUT (TIMER),A
|
||||
EI
|
||||
RET
|
||||
;
|
||||
; set mp/m tod from hardware clock
|
||||
; hl = tod address
|
||||
;
|
||||
SETTOD: LD A,GETDAL
|
||||
OUT (CLKCMD),A
|
||||
IN A,(CLKDAT)
|
||||
LD (HL),A
|
||||
INC HL
|
||||
LD A,GETDAH
|
||||
OUT (CLKCMD),A
|
||||
IN A,(CLKDAT)
|
||||
LD (HL),A
|
||||
INC HL
|
||||
LD A,GETHOU
|
||||
OUT (CLKCMD),A
|
||||
IN A,(CLKDAT)
|
||||
LD (HL),A
|
||||
INC HL
|
||||
LD A,GETMIN
|
||||
OUT (CLKCMD),A
|
||||
IN A,(CLKDAT)
|
||||
LD (HL),A
|
||||
RET
|
||||
;
|
||||
; idle
|
||||
;
|
||||
IDLE: EI
|
||||
HALT
|
||||
RET
|
||||
;
|
||||
; interrupt handler
|
||||
;
|
||||
INTHND: LD (SVDHL),HL ;save registers
|
||||
POP HL
|
||||
LD (SVDRET),HL
|
||||
PUSH AF
|
||||
LD HL,0
|
||||
ADD HL,SP
|
||||
LD (SVDSP),HL
|
||||
LD SP,INTSTK
|
||||
PUSH DE
|
||||
PUSH BC
|
||||
LD A,0FFH ;set preempted flag
|
||||
LD (PREEMP),A
|
||||
LD A,(TICKN)
|
||||
OR A ;test tick, indicates delayed process
|
||||
JP Z,INTHND1
|
||||
LD C,FLAGSET ;set flag #1 each tick
|
||||
LD E,1
|
||||
CALL XDOS
|
||||
INTHND1:
|
||||
LD HL,CNT50 ;decrement tick counter
|
||||
DEC (HL)
|
||||
JP NZ,INTDONE
|
||||
LD (HL),50 ;set flag #2 each second
|
||||
LD C,FLAGSET
|
||||
LD E,2
|
||||
CALL XDOS
|
||||
INTDONE:
|
||||
XOR A ;clear preempted flag
|
||||
LD (PREEMP),A
|
||||
POP BC ;restore registers
|
||||
POP DE
|
||||
LD HL,(SVDSP)
|
||||
LD SP,HL
|
||||
POP AF
|
||||
LD HL,(SVDRET)
|
||||
PUSH HL
|
||||
LD HL,(PDISP+1) ;dispatch processes
|
||||
PUSH HL
|
||||
LD HL,(SVDHL)
|
||||
RETI
|
||||
;
|
||||
; i/o drivers for disks
|
||||
;
|
||||
; move to the track 00 position of current drive
|
||||
; translate this call into a settrk call with parameter 00
|
||||
;
|
||||
HOME: LD C,0 ;select track 0
|
||||
JP SETTRK ;we will move to 00 on first read/write
|
||||
;
|
||||
; select disk given by register C
|
||||
;
|
||||
SELDSK: LD HL,0000H ;error return code
|
||||
LD A,C
|
||||
CP 4 ;must be between 0 and 3
|
||||
JR NC,SELHD ;no carry if 4,5,...
|
||||
; disk number is in the proper range
|
||||
; compute proper disk parameter header address
|
||||
OUT (FDCD),A ;selekt disk drive
|
||||
LD L,A ;L=disk number 0,1,2,3
|
||||
ADD HL,HL ;*2
|
||||
ADD HL,HL ;*4
|
||||
ADD HL,HL ;*8
|
||||
ADD HL,HL ;*16 (size of each header)
|
||||
LD DE,DPBASE
|
||||
ADD HL,DE ;HL=.dpbase(diskno*16)
|
||||
RET
|
||||
SELHD: CP 8 ;select the harddisk?
|
||||
RET NZ ;no, error
|
||||
OUT (FDCD),A ;select disk drive
|
||||
LD HL,HDBASE ;HL=hdbase for harddisk
|
||||
RET
|
||||
;
|
||||
; set track given by register c
|
||||
;
|
||||
SETTRK: LD A,C
|
||||
OUT (FDCT),A
|
||||
RET
|
||||
;
|
||||
; set sector given by register c
|
||||
;
|
||||
SETSEC: LD A,C
|
||||
OUT (FDCS),A
|
||||
RET
|
||||
;
|
||||
; translate the sector given by BC using the
|
||||
; translate table given by DE
|
||||
;
|
||||
SECTRAN:
|
||||
EX DE,HL ;HL=.trans
|
||||
ADD HL,BC ;HL=.trans(sector)
|
||||
LD L,(HL) ;L = trans(sector)
|
||||
LD H,0 ;HL= trans(sector)
|
||||
RET ;with value in HL
|
||||
;
|
||||
; set dma address given by registers b and c
|
||||
;
|
||||
SETDMA: LD A,C ;low order address
|
||||
OUT (DMAL),A
|
||||
LD A,B ;high order address
|
||||
OUT (DMAH),A ;in dma
|
||||
RET
|
||||
;
|
||||
; perform read operation
|
||||
;
|
||||
READ: XOR A ;read command -> A
|
||||
JP WAITIO ;to perform the actual i/o
|
||||
;
|
||||
; perform a write operation
|
||||
;
|
||||
WRITE: LD A,1 ;write command -> A
|
||||
;
|
||||
; enter here from read and write to perform the actual i/o
|
||||
; operation. return a 00h in register a if the operation completes
|
||||
; properly, and 01h if an error occurs during the read or write
|
||||
;
|
||||
; in this case, we have saved the disk number in 'diskno' (0-3)
|
||||
; the track number in 'track' (0-76)
|
||||
; the sector number in 'sector' (1-26)
|
||||
; the dma address in 'dmaad' (0-65535)
|
||||
;
|
||||
WAITIO: OUT (FDCOP),A ;start i/o operation
|
||||
IN A,(FDCST) ;status of i/o operation -> A
|
||||
RET
|
||||
;
|
||||
; XIOS data segment
|
||||
;
|
||||
SIGNON: DEFB 13,10
|
||||
DEFM 'MP/M 2 XIOS V1.1 for Z80SIM, '
|
||||
DEFM 'Copyright 1989-2006 by Udo Munk'
|
||||
DEFB 13,10,0
|
||||
;
|
||||
TICKN: DEFB 0 ;flag for tick
|
||||
PREEMP: DEFB 0 ;preempted flag
|
||||
TOD: DEFS 4 ;time of day
|
||||
SVDHL: DEFS 2 ;save hl during interrupt
|
||||
SVDRET: DEFS 2 ;save return address during interrupt
|
||||
SVDSP: DEFS 2 ;save sp during interrupt
|
||||
CNT50: DEFB 50 ;50 ticks a 20ms = 1 second
|
||||
;interrupt stack
|
||||
DEFW 0C7C7H,0C7C7H,0C7C7H,0C7C7H
|
||||
DEFW 0C7C7H,0C7C7H,0C7C7H,0C7C7H
|
||||
DEFW 0C7C7H,0C7C7H,0C7C7H,0C7C7H
|
||||
DEFW 0C7C7H,0C7C7H,0C7C7H,0C7C7H
|
||||
INTSTK:
|
||||
;
|
||||
; fixed data tables for four-drive standard
|
||||
; IBM-compatible 8" disks
|
||||
;
|
||||
; disk parameter header for disk 00
|
||||
DPBASE: DEFW TRANS,0000H
|
||||
DEFW 0000H,0000H
|
||||
DEFW DIRBF,DPBLK
|
||||
DEFW CHK00,ALL00
|
||||
; disk parameter header for disk 01
|
||||
DEFW TRANS,0000H
|
||||
DEFW 0000H,0000H
|
||||
DEFW DIRBF,DPBLK
|
||||
DEFW CHK01,ALL01
|
||||
; disk parameter header for disk 02
|
||||
DEFW TRANS,0000H
|
||||
DEFW 0000H,0000H
|
||||
DEFW DIRBF,DPBLK
|
||||
DEFW CHK02,ALL02
|
||||
; disk parameter header for disk 03
|
||||
DEFW TRANS,0000H
|
||||
DEFW 0000H,0000H
|
||||
DEFW DIRBF,DPBLK
|
||||
DEFW CHK03,ALL03
|
||||
;
|
||||
; sector translate vector for the IBM 8" disks
|
||||
;
|
||||
TRANS: DEFB 1,7,13,19 ;sectors 1,2,3,4
|
||||
DEFB 25,5,11,17 ;sectors 5,6,7,8
|
||||
DEFB 23,3,9,15 ;sectors 9,10,11,12
|
||||
DEFB 21,2,8,14 ;sectors 13,14,15,16
|
||||
DEFB 20,26,6,12 ;sectors 17,18,19,20
|
||||
DEFB 18,24,4,10 ;sectors 21,22,23,24
|
||||
DEFB 16,22 ;sectors 25,26
|
||||
;
|
||||
; disk parameter block, common to all IBM 8" disks
|
||||
;
|
||||
DPBLK: DEFW 26 ;sectors per track
|
||||
DEFB 3 ;block shift factor
|
||||
DEFB 7 ;block mask
|
||||
DEFB 0 ;extent mask
|
||||
DEFW 242 ;disk size-1
|
||||
DEFW 63 ;directory max
|
||||
DEFB 192 ;alloc 0
|
||||
DEFB 0 ;alloc 1
|
||||
DEFW 16 ;check size
|
||||
DEFW 2 ;track offset
|
||||
;
|
||||
; fixed data tables for 4MB harddisk
|
||||
;
|
||||
; disk parameter header
|
||||
HDBASE: DEFW HDTRA,0000H
|
||||
DEFW 0000H,0000H
|
||||
DEFW DIRBF,HDBLK
|
||||
DEFW CHKHD,ALLHD
|
||||
;
|
||||
; sector translate vector for the hardisk
|
||||
;
|
||||
HDTRA: DEFB 1,2,3,4,5,6,7,8,9,10
|
||||
DEFB 11,12,13,14,15,16,17,18,19,20
|
||||
DEFB 21,22,23,24,25,26,27,28,29,30
|
||||
DEFB 31,32,33,34,35,36,37,38,39,40
|
||||
DEFB 41,42,43,44,45,46,47,48,49,50
|
||||
DEFB 51,52,53,54,55,56,57,58,59,60
|
||||
DEFB 61,62,63,64,65,66,67,68,69,70
|
||||
DEFB 71,72,73,74,75,76,77,78,79,80
|
||||
DEFB 81,82,83,84,85,86,87,88,89,90
|
||||
DEFB 91,92,93,94,95,96,97,98,99,100
|
||||
DEFB 101,102,103,104,105,106,107,108,109,110
|
||||
DEFB 111,112,113,114,115,116,117,118,119,120
|
||||
DEFB 121,122,123,124,125,126,127,128
|
||||
;
|
||||
; disk parameter block for harddisk
|
||||
;
|
||||
HDBLK: DEFW 128 ;sectors per track
|
||||
DEFB 4 ;block shift factor
|
||||
DEFB 15 ;block mask
|
||||
DEFB 0 ;extent mask
|
||||
DEFW 2039 ;disk size-1
|
||||
DEFW 1023 ;directory max
|
||||
DEFB 255 ;alloc 0
|
||||
DEFB 255 ;alloc 1
|
||||
DEFW 0 ;check size
|
||||
DEFW 0 ;track offset
|
||||
;
|
||||
DIRBF: DEFS 128 ;scratch directory area
|
||||
ALL00: DEFS 31 ;allocation vector 0
|
||||
ALL01: DEFS 31 ;allocation vector 1
|
||||
ALL02: DEFS 31 ;allocation vector 2
|
||||
ALL03: DEFS 31 ;allocation vector 3
|
||||
ALLHD: DEFS 255 ;allocation vector harddisk
|
||||
CHK00: DEFS 16 ;check vector 0
|
||||
CHK01: DEFS 16 ;check vector 1
|
||||
CHK02: DEFS 16 ;check vector 2
|
||||
CHK03: DEFS 16 ;check vector 3
|
||||
CHKHD: DEFS 0 ;check vector harddisk
|
||||
;
|
||||
END
|
177
emu/z80pack-1.9/cpmsim/srcmpm/ldrbios.mac
Normal file
177
emu/z80pack-1.9/cpmsim/srcmpm/ldrbios.mac
Normal file
@@ -0,0 +1,177 @@
|
||||
; MP/M 2 LDRBIOS for Z80-Simulator
|
||||
;
|
||||
; Copyright (C) 1989-2006 by Udo Munk
|
||||
;
|
||||
ORG 1700H
|
||||
;
|
||||
; I/O ports
|
||||
;
|
||||
CONSTA EQU 0 ;console status port
|
||||
CONDAT EQU 1 ;console data port
|
||||
FDCD EQU 10 ;fdc-port: # of drive
|
||||
FDCT EQU 11 ;fdc-port: # of track
|
||||
FDCS EQU 12 ;fdc-port: # of sector
|
||||
FDCOP EQU 13 ;fdc-port: command
|
||||
FDCST EQU 14 ;fdc-port: status
|
||||
DMAL EQU 15 ;dma-port: dma address low
|
||||
DMAH EQU 16 ;dma-port: dma address high
|
||||
;
|
||||
; jump vector for individual subroutines
|
||||
;
|
||||
JP BOOT ;perform cold start initialization
|
||||
JP WBOOT ;perform warm start initialization
|
||||
JP CONST ;check for console input char ready
|
||||
JP CONIN ;read console character in
|
||||
JP CONOUT ;write console character out
|
||||
JP LIST ;write list character out
|
||||
JP AUXOUT ;write auxiliary output char
|
||||
JP AUXIN ;read auxiliary input char
|
||||
JP HOME ;move head to track 0 on selcted disk
|
||||
JP SELDSK ;select disk drive
|
||||
JP SETTRK ;set track number
|
||||
JP SETSEC ;set sector number
|
||||
JP SETDMA ;set dma address
|
||||
JP READ ;read specified sector
|
||||
JP WRITE ;write specified sector
|
||||
JP LISTST ;return list status
|
||||
JP SECTRAN ;translate logical to physical sector
|
||||
;
|
||||
; fixed data tables for a IBM-compatible 8" disk
|
||||
;
|
||||
; disk parameter header
|
||||
;
|
||||
DPH: DEFW TRANS,0000H
|
||||
DEFW 0000H,0000H
|
||||
DEFW DIRBF,DPBLK
|
||||
DEFW CHK00,ALL00
|
||||
;
|
||||
; sector translate vector for the IBM 8" disk
|
||||
;
|
||||
TRANS: DEFB 1,7,13,19 ;sectors 1,2,3,4
|
||||
DEFB 25,5,11,17 ;sectors 5,6,7,8
|
||||
DEFB 23,3,9,15 ;sectors 9,10,11,12
|
||||
DEFB 21,2,8,14 ;sectors 13,14,15,16
|
||||
DEFB 20,26,6,12 ;sectors 17,18,19,20
|
||||
DEFB 18,24,4,10 ;sectors 21,22,23,24
|
||||
DEFB 16,22 ;sectors 25,26
|
||||
;
|
||||
; disk parameter block for the IBM 8" disk
|
||||
;
|
||||
DPBLK: DEFW 26 ;sectors per track
|
||||
DEFB 3 ;block shift factor
|
||||
DEFB 7 ;block mask
|
||||
DEFB 0 ;extent mask
|
||||
DEFW 242 ;disk size-1
|
||||
DEFW 63 ;directory max
|
||||
DEFB 192 ;alloc 0
|
||||
DEFB 0 ;alloc 1
|
||||
DEFW 16 ;check size
|
||||
DEFW 2 ;track offset
|
||||
;
|
||||
; signon message
|
||||
;
|
||||
SIGNON: DEFB 13,10
|
||||
DEFM 'LDRBIOS V1.0 for Z80SIM, '
|
||||
DEFM 'Copyright 1989-2006 by Udo Munk'
|
||||
DEFB 13,10,0
|
||||
;
|
||||
; end of fixed tables
|
||||
;
|
||||
; individual subroutines to perform each function
|
||||
;
|
||||
BOOT: LD HL,SIGNON ;print message
|
||||
BOOTL: LD A,(HL)
|
||||
OR A
|
||||
JP Z,WBOOT
|
||||
LD C,A
|
||||
CALL CONOUT
|
||||
INC HL
|
||||
JP BOOTL
|
||||
;
|
||||
; those are not implemented in loader bios
|
||||
;
|
||||
WBOOT:
|
||||
CONST:
|
||||
CONIN:
|
||||
LIST:
|
||||
AUXOUT:
|
||||
AUXIN:
|
||||
WRITE:
|
||||
LISTST:
|
||||
RET
|
||||
;
|
||||
; console character output from register c
|
||||
;
|
||||
CONOUT: LD A,C ;get to accumulator
|
||||
OUT (CONDAT),A ;send character to console
|
||||
RET
|
||||
;
|
||||
;
|
||||
; i/o drivers for the disk follow
|
||||
;
|
||||
; move to the track 00 position of current drive
|
||||
; translate this call into a settrk call with parameter 00
|
||||
;
|
||||
HOME: LD C,0 ;select track 0
|
||||
JP SETTRK ;we will move to 00 on first read/write
|
||||
;
|
||||
; select disk given by register C
|
||||
;
|
||||
SELDSK: PUSH BC
|
||||
CALL BOOT ;signon message
|
||||
POP BC
|
||||
LD HL,0000H ;error return code
|
||||
LD A,C
|
||||
CP 0 ;we boot from drive 0 only
|
||||
RET NZ ;return error
|
||||
; disk number is in the proper range
|
||||
; return proper disk parameter header address
|
||||
OUT (FDCD),A ;selekt disk drive
|
||||
LD HL,DPH
|
||||
RET
|
||||
;
|
||||
; set track given by register c
|
||||
;
|
||||
SETTRK: LD A,C
|
||||
OUT (FDCT),A
|
||||
RET
|
||||
;
|
||||
; set sector given by register c
|
||||
;
|
||||
SETSEC: LD A,C
|
||||
OUT (FDCS),A
|
||||
RET
|
||||
;
|
||||
; translate the sector given by BC using the
|
||||
; translate table given by DE
|
||||
;
|
||||
SECTRAN:
|
||||
EX DE,HL ;hl=.trans
|
||||
ADD HL,BC ;hl=.trans(sector)
|
||||
LD L,(HL) ;l = trans(sector)
|
||||
LD H,0 ;hl= trans(sector)
|
||||
RET ;with value in hl
|
||||
;
|
||||
; set dma address given by registers b and c
|
||||
;
|
||||
SETDMA: LD A,C ;low order address
|
||||
OUT (DMAL),A
|
||||
LD A,B ;high order address
|
||||
OUT (DMAH),A ;in dma
|
||||
RET
|
||||
;
|
||||
; perform read operation
|
||||
;
|
||||
READ: XOR A ;read command -> a
|
||||
OUT (FDCOP),A ;start i/o operation
|
||||
IN A,(FDCST) ;status of i/o operation -> a
|
||||
RET
|
||||
;
|
||||
BEGDAT EQU $
|
||||
DIRBF: DEFS 128 ;scratch directory area
|
||||
ALL00: DEFS 31 ;allocation vector
|
||||
CHK00: DEFS 16 ;check vector
|
||||
;
|
||||
ENDDAT EQU $ ;end
|
||||
DATSIZ EQU $-BEGDAT ;size of data area
|
||||
END ;of bios
|
74
emu/z80pack-1.9/cpmsim/srcsim/Makefile
Normal file
74
emu/z80pack-1.9/cpmsim/srcsim/Makefile
Normal file
@@ -0,0 +1,74 @@
|
||||
CFLAGS= -O -c -Wall
|
||||
LFLAGS= -s
|
||||
|
||||
OBJ = sim0.o \
|
||||
sim1.o \
|
||||
sim2.o \
|
||||
sim3.o \
|
||||
sim4.o \
|
||||
sim5.o \
|
||||
sim6.o \
|
||||
sim7.o \
|
||||
simctl.o \
|
||||
simint.o \
|
||||
iosim.o \
|
||||
simfun.o \
|
||||
simglb.o
|
||||
|
||||
all: ../auxin ../auxout ../cpmsim
|
||||
@echo "done."
|
||||
|
||||
../auxin:
|
||||
test -f ../auxin || mknod ../auxin p
|
||||
|
||||
../auxout:
|
||||
test -f ../auxout || mknod ../auxout p
|
||||
|
||||
../cpmsim : $(OBJ)
|
||||
cc $(OBJ) $(LFLAGS) -o ../cpmsim
|
||||
|
||||
sim0.c:
|
||||
lnsrc
|
||||
|
||||
sim0.o : sim0.c sim.h simglb.h
|
||||
cc $(CFLAGS) sim0.c
|
||||
|
||||
sim1.o : sim1.c sim.h simglb.h
|
||||
cc $(CFLAGS) sim1.c
|
||||
|
||||
sim2.o : sim2.c sim.h simglb.h
|
||||
cc $(CFLAGS) sim2.c
|
||||
|
||||
sim3.o : sim3.c sim.h simglb.h
|
||||
cc $(CFLAGS) sim3.c
|
||||
|
||||
sim4.o : sim4.c sim.h simglb.h
|
||||
cc $(CFLAGS) sim4.c
|
||||
|
||||
sim5.o : sim5.c sim.h simglb.h
|
||||
cc $(CFLAGS) sim5.c
|
||||
|
||||
sim6.o : sim6.c sim.h simglb.h
|
||||
cc $(CFLAGS) sim6.c
|
||||
|
||||
sim7.o : sim7.c sim.h simglb.h
|
||||
cc $(CFLAGS) sim7.c
|
||||
|
||||
simctl.o : simctl.c sim.h simglb.h
|
||||
cc $(CFLAGS) simctl.c
|
||||
|
||||
simint.o : simint.c sim.h simglb.h
|
||||
cc $(CFLAGS) simint.c
|
||||
|
||||
iosim.o : iosim.c sim.h simglb.h
|
||||
cc $(CFLAGS) iosim.c
|
||||
|
||||
simfun.o : simfun.c sim.h
|
||||
cc $(CFLAGS) simfun.c
|
||||
|
||||
simglb.o : simglb.c sim.h
|
||||
cc $(CFLAGS) simglb.c
|
||||
|
||||
clean:
|
||||
rm -f *.o
|
||||
ulnsrc
|
868
emu/z80pack-1.9/cpmsim/srcsim/iosim.c
Normal file
868
emu/z80pack-1.9/cpmsim/srcsim/iosim.c
Normal file
@@ -0,0 +1,868 @@
|
||||
/*
|
||||
* Z80SIM - a Z80-CPU simulator
|
||||
*
|
||||
* Copyright (C) 1987-2006 by Udo Munk
|
||||
*
|
||||
* This modul contains a complex I/O-simulation for running
|
||||
* CP/M 2, CP/M 3, MP/M...
|
||||
* Please note this this doesn't emulate any hardware which
|
||||
* ever existed, we've got all virtual circuits in here!
|
||||
*
|
||||
* History:
|
||||
* 28-SEP-87 Development on TARGON/35 with AT&T Unix System V.3
|
||||
* 19-MAY-89 Additions for CP/M 3.0 und MP/M
|
||||
* 23-DEC-90 Ported to COHERENT 3.0
|
||||
* 10-JUN-92 Some optimization done
|
||||
* 25-JUN-92 Flush output of stdout only at every OUT to port 0
|
||||
* 25-JUN-92 Comments in english and ported to COHERENT 4.0
|
||||
* 05-OCT-06 modified to compile on modern POSIX OS's
|
||||
* 18-NOV-06 added a second harddisk
|
||||
*/
|
||||
|
||||
/*
|
||||
* This module contains the I/O handlers for a simulation
|
||||
* of the hardware required for a CP/M system.
|
||||
*
|
||||
* Used I/O ports:
|
||||
*
|
||||
* 0 - console status
|
||||
* 1 - console data
|
||||
*
|
||||
* 2 - printer status
|
||||
* 3 - printer data
|
||||
*
|
||||
* 4 - auxilary status
|
||||
* 5 - auxilary data
|
||||
*
|
||||
* 10 - FDC drive
|
||||
* 11 - FDC track
|
||||
* 12 - FDC sector
|
||||
* 13 - FDC command
|
||||
* 14 - FDC status
|
||||
*
|
||||
* 15 - DMA destination address low
|
||||
* 16 - DMA destination address high
|
||||
*
|
||||
* 20 - MMU initialization
|
||||
* 21 - MMU bank select
|
||||
*
|
||||
* 25 - clock command
|
||||
* 26 - clock data
|
||||
* 27 - 20ms timer causing INT, only usable in IM 1
|
||||
*
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include "sim.h"
|
||||
#include "simglb.h"
|
||||
|
||||
/*
|
||||
* Structure to describe a emulated floppy disk drive:
|
||||
* pointer to filename
|
||||
* pointer to file descriptor
|
||||
* number of tracks
|
||||
* number of sectors
|
||||
*/
|
||||
struct dskdef {
|
||||
char *fn;
|
||||
int *fd;
|
||||
unsigned int tracks;
|
||||
unsigned int sectors;
|
||||
};
|
||||
|
||||
static BYTE drive; /* current drive A..P (0..15) */
|
||||
static BYTE track; /* current track (0..255) */
|
||||
static BYTE sector; /* current sektor (0..255) */
|
||||
static BYTE status; /* status of last I/O operation on FDC */
|
||||
static BYTE dmadl; /* current DMA adresse destination low */
|
||||
static BYTE dmadh; /* current DMA adresse destination high */
|
||||
static BYTE clkcmd; /* clock command */
|
||||
static BYTE timer; /* 20ms timer */
|
||||
static int drivea; /* fd for file "drivea.cpm" */
|
||||
static int driveb; /* fd for file "driveb.cpm" */
|
||||
static int drivec; /* fd for file "drivec.cpm" */
|
||||
static int drived; /* fd for file "drived.cpm" */
|
||||
static int drivee; /* fd for file "drivee.cpm" */
|
||||
static int drivef; /* fd for file "drivef.cpm" */
|
||||
static int driveg; /* fd for file "driveg.cpm" */
|
||||
static int driveh; /* fd for file "driveh.cpm" */
|
||||
static int drivei; /* fd for file "drivei.cpm" */
|
||||
static int drivej; /* fd for file "drivej.cpm" */
|
||||
static int drivek; /* fd for file "drivek.cpm" */
|
||||
static int drivel; /* fd for file "drivel.cpm" */
|
||||
static int drivem; /* fd for file "drivem.cpm" */
|
||||
static int driven; /* fd for file "driven.cpm" */
|
||||
static int driveo; /* fd for file "driveo.cpm" */
|
||||
static int drivep; /* fd for file "drivep.cpm" */
|
||||
static int printer; /* fd for file "printer.cpm" */
|
||||
static int auxin; /* fd for pipe "auxin" */
|
||||
static int auxout; /* fd for pipe "auxout" */
|
||||
static int aux_in_eof; /* status of pipe "auxin" (<>0 means EOF) */
|
||||
static int pid_rec; /* PID of the receiving process for auxiliary */
|
||||
static char last_char; /* buffer for 1 character (console status) */
|
||||
|
||||
static struct dskdef disks[16] = {
|
||||
{ "disks/drivea.cpm", &drivea, 77, 26 },
|
||||
{ "disks/driveb.cpm", &driveb, 77, 26 },
|
||||
{ "disks/drivec.cpm", &drivec, 77, 26 },
|
||||
{ "disks/drived.cpm", &drived, 77, 26 },
|
||||
{ "disks/drivee.cpm", &drivee, -1, -1 },
|
||||
{ "disks/drivef.cpm", &drivef, -1, -1 },
|
||||
{ "disks/driveg.cpm", &driveg, -1, -1 },
|
||||
{ "disks/driveh.cpm", &driveh, -1, -1 },
|
||||
{ "disks/drivei.cpm", &drivei, 255, 128 },
|
||||
{ "disks/drivej.cpm", &drivej, 255, 128 },
|
||||
{ "disks/drivek.cpm", &drivek, -1, -1 },
|
||||
{ "disks/drivel.cpm", &drivel, -1, -1 },
|
||||
{ "disks/drivem.cpm", &drivem, -1, -1 },
|
||||
{ "disks/driven.cpm", &driven, -1, -1 },
|
||||
{ "disks/driveo.cpm", &driveo, -1, -1 },
|
||||
{ "disks/drivep.cpm", &drivep, -1, -1 }
|
||||
};
|
||||
|
||||
/*
|
||||
* MMU:
|
||||
* ===
|
||||
*
|
||||
* +--------+
|
||||
* 16KB | common |
|
||||
* +--------+
|
||||
* +--------+ +--------+ .......... +--------+
|
||||
* | | | | | |
|
||||
* 48KB | | | | .......... | |
|
||||
* | bank 0 | | bank 1 | | bank n |
|
||||
* +--------+ +--------+ .......... +--------+
|
||||
*/
|
||||
#define MAXSEG 16 /* max. number of memory banks */
|
||||
#define SEGSIZ 49152 /* size of one bank = 48KBytes */
|
||||
static char *mmu[MAXSEG]; /* MMU with pointers to the banks */
|
||||
static int selbnk; /* current bank */
|
||||
static int maxbnk; /* number of initialized banks */
|
||||
|
||||
/*
|
||||
* Forward declaration of the I/O handlers for all used ports
|
||||
*/
|
||||
static BYTE io_trap(void);
|
||||
static BYTE cond_in(void), cond_out(BYTE), cons_in(void), cons_out(BYTE);
|
||||
static BYTE prtd_in(void), prtd_out(BYTE), prts_in(void), prts_out(BYTE);
|
||||
static BYTE auxd_in(void), auxd_out(BYTE), auxs_in(void), auxs_out(BYTE);
|
||||
static BYTE fdcd_in(void), fdcd_out(BYTE);
|
||||
static BYTE fdct_in(void), fdct_out(BYTE);
|
||||
static BYTE fdcs_in(void), fdcs_out(BYTE);
|
||||
static BYTE fdco_in(void), fdco_out(BYTE);
|
||||
static BYTE fdcx_in(void), fdcx_out(BYTE);
|
||||
static BYTE dmal_in(void), dmal_out(BYTE);
|
||||
static BYTE dmah_in(void), dmah_out(BYTE);
|
||||
static BYTE mmui_in(void), mmui_out(BYTE), mmus_in(void), mmus_out(BYTE);
|
||||
static BYTE clkc_in(void), clkc_out(BYTE), clkd_in(void), clkd_out(BYTE);
|
||||
static BYTE time_in(void), time_out(BYTE);
|
||||
static void int_timer(int);
|
||||
|
||||
static int to_bcd(int), get_date(struct tm *);
|
||||
|
||||
/*
|
||||
* This array contains two function pointer for every
|
||||
* active port, one for input and one for output.
|
||||
*/
|
||||
static BYTE (*port[256][2]) () = {
|
||||
{ cons_in, cons_out }, /* port 0 */
|
||||
{ cond_in, cond_out }, /* port 1 */
|
||||
{ prts_in, prts_out }, /* port 2 */
|
||||
{ prtd_in, prtd_out }, /* port 3 */
|
||||
{ auxs_in, auxs_out }, /* port 4 */
|
||||
{ auxd_in, auxd_out }, /* port 5 */
|
||||
{ io_trap, io_trap }, /* port 6 */
|
||||
{ io_trap, io_trap }, /* port 7 */
|
||||
{ io_trap, io_trap }, /* port 8 */
|
||||
{ io_trap, io_trap }, /* port 9 */
|
||||
{ fdcd_in, fdcd_out }, /* port 10 */
|
||||
{ fdct_in, fdct_out }, /* port 11 */
|
||||
{ fdcs_in, fdcs_out }, /* port 12 */
|
||||
{ fdco_in, fdco_out }, /* port 13 */
|
||||
{ fdcx_in, fdcx_out }, /* port 14 */
|
||||
{ dmal_in, dmal_out }, /* port 15 */
|
||||
{ dmah_in, dmah_out }, /* port 16 */
|
||||
{ io_trap, io_trap }, /* port 17 */
|
||||
{ io_trap, io_trap }, /* port 18 */
|
||||
{ io_trap, io_trap }, /* port 19 */
|
||||
{ mmui_in, mmui_out }, /* port 20 */
|
||||
{ mmus_in, mmus_out }, /* port 21 */
|
||||
{ io_trap, io_trap }, /* port 22 */
|
||||
{ io_trap, io_trap }, /* port 23 */
|
||||
{ io_trap, io_trap }, /* port 24 */
|
||||
{ clkc_in, clkc_out }, /* port 25 */
|
||||
{ clkd_in, clkd_out }, /* port 26 */
|
||||
{ time_in, time_out } /* port 27 */
|
||||
};
|
||||
|
||||
/*
|
||||
* This function initializes the I/O handlers:
|
||||
* 1. Initialize all unused ports with the I/O trap handler.
|
||||
* 2. Initialize the MMU with NULL pointers.
|
||||
* 3. Open the files which emulates the disk drives. The file
|
||||
* for drive A must be opened, or CP/M can't be booted.
|
||||
* Errors for opening one of the other 15 drives results
|
||||
* in a NULL pointer for fd in the dskdef structure,
|
||||
* so that this drive can't be used.
|
||||
* 4. Create and open the file "printer.cpm" for emulation
|
||||
* of a printer.
|
||||
* 5. Fork the process for receiving from the serial port.
|
||||
* 6. Open the named pipes "auxin" and "auxout" for simulation
|
||||
* of a serial port.
|
||||
*/
|
||||
void init_io(void)
|
||||
{
|
||||
register int i;
|
||||
|
||||
for (i = 28; i <= 255; i++) {
|
||||
port[i][0] = io_trap;
|
||||
port[i][1] = io_trap;
|
||||
}
|
||||
for (i = 0; i < MAXSEG; i++)
|
||||
mmu[i] = NULL;
|
||||
if ((*disks[0].fd = open(disks[0].fn, O_RDWR)) == -1) {
|
||||
perror("file disks/drivea.cpm");
|
||||
exit(1);
|
||||
}
|
||||
for (i = 1; i <= 15; i++)
|
||||
if ((*disks[i].fd = open(disks[i].fn, O_RDWR)) == -1)
|
||||
disks[i].fd = NULL;
|
||||
if ((printer = creat("printer.cpm", 0644)) == -1) {
|
||||
perror("file printer.cpm");
|
||||
exit(1);
|
||||
}
|
||||
pid_rec = fork();
|
||||
switch (pid_rec) {
|
||||
case -1:
|
||||
puts("can't fork");
|
||||
exit(1);
|
||||
case 0:
|
||||
execlp("./receive", "receive", "auxiliary.cpm", (char *) NULL);
|
||||
puts("can't exec receive process");
|
||||
exit(1);
|
||||
}
|
||||
if ((auxin = open("auxin", O_RDONLY | O_NDELAY)) == -1) {
|
||||
perror("pipe auxin");
|
||||
exit(1);
|
||||
}
|
||||
if ((auxout = open("auxout", O_WRONLY)) == -1) {
|
||||
perror("pipe auxout");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This function stops the I/O handlers:
|
||||
*
|
||||
* 1. The files emulating the disk drives are closed.
|
||||
* 2. The file "printer.com" emulating a printer is closed.
|
||||
* 3. The named pipes "auxin" and "auxout" are closed.
|
||||
* 4. The receiving process for the serial port is stopped.
|
||||
*/
|
||||
void exit_io(void)
|
||||
{
|
||||
register int i;
|
||||
|
||||
for (i = 0; i <= 15; i++)
|
||||
if (disks[i].fd != NULL)
|
||||
close(*disks[i].fd);
|
||||
close(printer);
|
||||
close(auxin);
|
||||
close(auxout);
|
||||
kill(pid_rec, SIGHUP);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called for every IN opcode from the
|
||||
* CPU emulation. It calls the right handler for the
|
||||
* port, from which input is wanted.
|
||||
*/
|
||||
BYTE io_in(BYTE adr)
|
||||
{
|
||||
return((*port[adr][0]) ());
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called for every OUT opcode from the
|
||||
* CPU emulation. It calls the right handler for the port,
|
||||
* to which output is wanted.
|
||||
*/
|
||||
BYTE io_out(BYTE adr, BYTE data)
|
||||
{
|
||||
(*port[adr][1]) (data);
|
||||
return((BYTE) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O trap handler
|
||||
*/
|
||||
static BYTE io_trap(void)
|
||||
{
|
||||
if (i_flag) {
|
||||
cpu_error = IOTRAP;
|
||||
cpu_state = STOPPED;
|
||||
}
|
||||
return((BYTE) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for read console status:
|
||||
* 0xff : input available
|
||||
* 0x00 : no input available
|
||||
*/
|
||||
static BYTE cons_in(void)
|
||||
{
|
||||
register int flags, readed;
|
||||
|
||||
if (last_char)
|
||||
return((BYTE) 0xff);
|
||||
if (cntl_c)
|
||||
return((BYTE) 0xff);
|
||||
if (cntl_bs)
|
||||
return((BYTE) 0xff);
|
||||
else {
|
||||
flags = fcntl(0, F_GETFL, 0);
|
||||
fcntl(0, F_SETFL, flags | O_NDELAY);
|
||||
readed = read(0, &last_char, 1);
|
||||
fcntl(0, F_SETFL, flags);
|
||||
if (readed == 1)
|
||||
return((BYTE) 0xff);
|
||||
}
|
||||
return((BYTE) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for write console status:
|
||||
* no reaction
|
||||
*/
|
||||
static BYTE cons_out(BYTE data)
|
||||
{
|
||||
data = data;
|
||||
return((BYTE) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for read console data:
|
||||
* read one character from the terminal without echo
|
||||
* and character transformations
|
||||
*/
|
||||
static BYTE cond_in(void)
|
||||
{
|
||||
char c;
|
||||
|
||||
aborted:
|
||||
if (last_char) {
|
||||
c = last_char;
|
||||
last_char = '\0';
|
||||
} else if (cntl_c) {
|
||||
cntl_c--;
|
||||
c = 0x03;
|
||||
} else if (cntl_bs) {
|
||||
cntl_bs--;
|
||||
c = 0x1c;
|
||||
} else if (read(0, &c, 1) != 1) {
|
||||
goto aborted;
|
||||
}
|
||||
return((BYTE) c);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for write console data:
|
||||
* the output is written to the terminal
|
||||
*/
|
||||
static BYTE cond_out(BYTE data)
|
||||
{
|
||||
while ((write(fileno(stdout), (char *) &data, 1)) != 1)
|
||||
;
|
||||
fflush(stdout);
|
||||
return((BYTE) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for read printer status:
|
||||
* the printer is ready all the time
|
||||
*/
|
||||
static BYTE prts_in(void)
|
||||
{
|
||||
return((BYTE) 0xff);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for write printer status:
|
||||
* no reaction
|
||||
*/
|
||||
static BYTE prts_out(BYTE data)
|
||||
{
|
||||
data = data;
|
||||
return((BYTE) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for read printer data:
|
||||
* always read a 0 from the printer
|
||||
*/
|
||||
static BYTE prtd_in(void)
|
||||
{
|
||||
return((BYTE) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for write printer data:
|
||||
* the output is written to file "printer.cpm"
|
||||
*/
|
||||
static BYTE prtd_out(BYTE data)
|
||||
{
|
||||
if (data != '\r')
|
||||
while ((write(printer, (char *) &data, 1)) != 1)
|
||||
;
|
||||
return((BYTE) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for read aux status:
|
||||
* return EOF status of the aux device
|
||||
*/
|
||||
static BYTE auxs_in(void)
|
||||
{
|
||||
return((BYTE) aux_in_eof);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for write aux status:
|
||||
* change EOF status of the aux device
|
||||
*/
|
||||
static BYTE auxs_out(BYTE data)
|
||||
{
|
||||
aux_in_eof = data;
|
||||
return((BYTE) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for read aux data:
|
||||
* read next byte from pipe "auxin"
|
||||
*/
|
||||
static BYTE auxd_in(void)
|
||||
{
|
||||
char c;
|
||||
|
||||
if (read(auxin, &c, 1) == 1)
|
||||
return((BYTE) c);
|
||||
else {
|
||||
aux_in_eof = 0xff;
|
||||
return((BYTE) 0x1a); /* CP/M EOF */
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for write aux data:
|
||||
* write output to pipe "auxout"
|
||||
*/
|
||||
static BYTE auxd_out(BYTE data)
|
||||
{
|
||||
if (data != '\r')
|
||||
write(auxout, (char *) &data, 1);
|
||||
return((BYTE) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for read FDC drive:
|
||||
* return the current drive
|
||||
*/
|
||||
static BYTE fdcd_in(void)
|
||||
{
|
||||
return((BYTE) drive);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for write FDC drive:
|
||||
* set the current drive
|
||||
*/
|
||||
static BYTE fdcd_out(BYTE data)
|
||||
{
|
||||
drive = data;
|
||||
return((BYTE) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for read FDC track:
|
||||
* return the current track
|
||||
*/
|
||||
static BYTE fdct_in(void)
|
||||
{
|
||||
return((BYTE) track);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for write FDC track:
|
||||
* set the current track
|
||||
*/
|
||||
static BYTE fdct_out(BYTE data)
|
||||
{
|
||||
track = data;
|
||||
return((BYTE) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for read FDC sector
|
||||
* return the current sector
|
||||
*/
|
||||
static BYTE fdcs_in(void)
|
||||
{
|
||||
return((BYTE) sector);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for write FDC sector:
|
||||
* set the current sector
|
||||
*/
|
||||
static BYTE fdcs_out(BYTE data)
|
||||
{
|
||||
sector = data;
|
||||
return((BYTE) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for read FDC command:
|
||||
* always returns 0
|
||||
*/
|
||||
static BYTE fdco_in(void)
|
||||
{
|
||||
return((BYTE) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for write FDC command:
|
||||
* transfer one sector in the wanted direction,
|
||||
* 0 = read, 1 = write
|
||||
*
|
||||
* The status byte of the FDC is set as follows:
|
||||
* 0 - ok
|
||||
* 1 - illegal drive
|
||||
* 2 - illegal track
|
||||
* 3 - illegal sector
|
||||
* 4 - seek error
|
||||
* 5 - read error
|
||||
* 6 - write error
|
||||
* 7 - illegal command to FDC
|
||||
*/
|
||||
static BYTE fdco_out(BYTE data)
|
||||
{
|
||||
register long pos;
|
||||
if (disks[drive].fd == NULL) {
|
||||
status = 1;
|
||||
return((BYTE) 0);
|
||||
}
|
||||
if (track > disks[drive].tracks) {
|
||||
status = 2;
|
||||
return((BYTE) 0);
|
||||
}
|
||||
if (sector > disks[drive].sectors) {
|
||||
status = 3;
|
||||
return((BYTE) 0);
|
||||
}
|
||||
pos = (((long)track) * ((long)disks[drive].sectors) + sector - 1) << 7;
|
||||
if (lseek(*disks[drive].fd, pos, 0) == -1L) {
|
||||
status = 4;
|
||||
return((BYTE) 0);
|
||||
}
|
||||
switch (data) {
|
||||
case 0: /* read */
|
||||
if (read(*disks[drive].fd, (char *) ram + (dmadh << 8) +
|
||||
dmadl, 128) != 128)
|
||||
status = 5;
|
||||
else
|
||||
status = 0;
|
||||
break;
|
||||
case 1: /* write */
|
||||
if (write(*disks[drive].fd, (char *) ram + (dmadh << 8) +
|
||||
dmadl, 128) != 128)
|
||||
status = 6;
|
||||
else
|
||||
status = 0;
|
||||
break;
|
||||
default: /* illegal command */
|
||||
status = 7;
|
||||
break;
|
||||
}
|
||||
return((BYTE) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for read FDC status:
|
||||
* returns status of last FDC operation,
|
||||
* 0 = ok, else some error
|
||||
*/
|
||||
static BYTE fdcx_in(void)
|
||||
{
|
||||
return((BYTE) status);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for write FDC status:
|
||||
* no reaction
|
||||
*/
|
||||
static BYTE fdcx_out(BYTE data)
|
||||
{
|
||||
data = data;
|
||||
return((BYTE) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for read lower byte of DMA address:
|
||||
* return lower byte of current DMA address
|
||||
*/
|
||||
static BYTE dmal_in(void)
|
||||
{
|
||||
return((BYTE) dmadl);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for write lower byte of DMA address:
|
||||
* set lower byte of DMA address
|
||||
*/
|
||||
static BYTE dmal_out(BYTE data)
|
||||
{
|
||||
dmadl = data;
|
||||
return((BYTE) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for read higher byte of DMA address:
|
||||
* return higher byte of current DMA address
|
||||
*/
|
||||
static BYTE dmah_in(void)
|
||||
{
|
||||
return((BYTE) dmadh);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for write higher byte of DMA address:
|
||||
* set higher byte of the DMA address
|
||||
*/
|
||||
static BYTE dmah_out(BYTE data)
|
||||
{
|
||||
dmadh = data;
|
||||
return((BYTE) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for read MMU initialization:
|
||||
* return number of initialized MMU banks
|
||||
*/
|
||||
static BYTE mmui_in(void)
|
||||
{
|
||||
return((BYTE) maxbnk);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for write MMU initialization:
|
||||
* for the FIRST call the memory for the wanted number of banks
|
||||
* is allocated and pointers to the memory is stored in the MMU array
|
||||
*/
|
||||
static BYTE mmui_out(BYTE data)
|
||||
{
|
||||
register int i;
|
||||
|
||||
if (mmu[0] != NULL)
|
||||
return((BYTE) 0);
|
||||
if (data > MAXSEG) {
|
||||
printf("Try to init %d banks, available %d banks\n",
|
||||
data, MAXSEG);
|
||||
exit(1);
|
||||
}
|
||||
for (i = 0; i < data; i++) {
|
||||
if ((mmu[i] = malloc(SEGSIZ)) == NULL) {
|
||||
printf("can't allocate memory for bank %d\n", i+1);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
maxbnk = data;
|
||||
return((BYTE) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for read MMU bank select:
|
||||
* return current selected MMU bank
|
||||
*/
|
||||
static BYTE mmus_in(void)
|
||||
{
|
||||
return((BYTE) selbnk);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for write MMU bank select:
|
||||
* if the current selected bank is not equal the wanted bank,
|
||||
* the current bank is saved. Then the memory of the wanted
|
||||
* bank is copied into the CPU address space and this bank is
|
||||
* set to be the current one now.
|
||||
*/
|
||||
static BYTE mmus_out(BYTE data)
|
||||
{
|
||||
if (data > maxbnk) {
|
||||
printf("Try to select unallocated bank %d\n", data);
|
||||
exit(1);
|
||||
}
|
||||
if (data == selbnk)
|
||||
return((BYTE) 0);
|
||||
memcpy(mmu[selbnk], (char *) ram, SEGSIZ);
|
||||
memcpy((char *) ram, mmu[data], SEGSIZ);
|
||||
selbnk = data;
|
||||
return((BYTE) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for read clock command:
|
||||
* return last clock command
|
||||
*/
|
||||
static BYTE clkc_in(void)
|
||||
{
|
||||
return(clkcmd);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for write clock command:
|
||||
* set the wanted clock command
|
||||
*/
|
||||
static BYTE clkc_out(BYTE data)
|
||||
{
|
||||
clkcmd = data;
|
||||
return((BYTE) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for read clock data:
|
||||
* dependent from the last clock command the following
|
||||
* informations are given from the system clock:
|
||||
* 0 - seconds in BCD
|
||||
* 1 - minutes in BCD
|
||||
* 2 - hours in BCD
|
||||
* 3 - low byte number of days since 1.1.1978
|
||||
* 4 - high byte number of days since 1.1.1978
|
||||
* for every other clock command a 0 is returned
|
||||
*/
|
||||
static BYTE clkd_in(void)
|
||||
{
|
||||
register struct tm *t;
|
||||
register int val;
|
||||
time_t Time;
|
||||
|
||||
time(&Time);
|
||||
t = localtime(&Time);
|
||||
switch(clkcmd) {
|
||||
case 0: /* seconds in BCD */
|
||||
val = to_bcd(t->tm_sec);
|
||||
break;
|
||||
case 1: /* minutes in BCD */
|
||||
val = to_bcd(t->tm_min);
|
||||
break;
|
||||
case 2: /* hours in BCD */
|
||||
val = to_bcd(t->tm_hour);
|
||||
break;
|
||||
case 3: /* low byte days */
|
||||
val = get_date(t) & 255;
|
||||
break;
|
||||
case 4: /* high byte days */
|
||||
val = get_date(t) >> 8;
|
||||
break;
|
||||
default:
|
||||
val = 0;
|
||||
break;
|
||||
}
|
||||
return((BYTE) val);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for write clock data:
|
||||
* under UNIX the system clock only can be set by the
|
||||
* super user, so we do nothing here
|
||||
*/
|
||||
static BYTE clkd_out(BYTE data)
|
||||
{
|
||||
data = data;
|
||||
return((BYTE) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert an integer to BCD
|
||||
*/
|
||||
static int to_bcd(int val)
|
||||
{
|
||||
register int i = 0;
|
||||
|
||||
while (val >= 10) {
|
||||
i += val / 10;
|
||||
i <<= 4;
|
||||
val %= 10;
|
||||
}
|
||||
i += val;
|
||||
return (i);
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate number of days since 1.1.1978
|
||||
* The Y2K bug here is intentional, CP/M 3 has a Y2K bug fix
|
||||
*/
|
||||
static int get_date(struct tm *t)
|
||||
{
|
||||
register int i;
|
||||
register int val = 0;
|
||||
|
||||
for (i = 1978; i < 1900 + t->tm_year; i++) {
|
||||
val += 365;
|
||||
if (i % 4 == 0)
|
||||
val++;
|
||||
}
|
||||
val += t->tm_yday + 1;
|
||||
return(val);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for write timer
|
||||
*/
|
||||
static BYTE time_out(BYTE data)
|
||||
{
|
||||
static struct itimerval tim;
|
||||
static struct sigaction newact;
|
||||
|
||||
if (data == 1) {
|
||||
timer = 1;
|
||||
newact.sa_handler = int_timer;
|
||||
sigaction(SIGALRM, &newact, NULL);
|
||||
tim.it_value.tv_sec = 0;
|
||||
tim.it_value.tv_usec = 20000;
|
||||
tim.it_interval.tv_sec = 0;
|
||||
tim.it_interval.tv_usec = 20000;
|
||||
setitimer(ITIMER_REAL, &tim, NULL);
|
||||
} else {
|
||||
timer = 0;
|
||||
newact.sa_handler = SIG_IGN;
|
||||
sigaction(SIGALRM, &newact, NULL);
|
||||
tim.it_value.tv_sec = 0;
|
||||
tim.it_value.tv_usec = 0;
|
||||
setitimer(ITIMER_REAL, &tim, NULL);
|
||||
}
|
||||
return((BYTE) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O handler for read timer
|
||||
*/
|
||||
static BYTE time_in(void)
|
||||
{
|
||||
return(timer);
|
||||
}
|
||||
|
||||
/*
|
||||
* timer interrupt causes maskerable CPU interrupt
|
||||
*/
|
||||
static void int_timer(int sig)
|
||||
{
|
||||
int_type = INT_INT;
|
||||
}
|
14
emu/z80pack-1.9/cpmsim/srcsim/lnsrc
Executable file
14
emu/z80pack-1.9/cpmsim/srcsim/lnsrc
Executable file
@@ -0,0 +1,14 @@
|
||||
# use this to link the common parts of Z80 simulation
|
||||
|
||||
ln ../../z80sim/sim0.c sim0.c
|
||||
ln ../../z80sim/sim1.c sim1.c
|
||||
ln ../../z80sim/sim2.c sim2.c
|
||||
ln ../../z80sim/sim3.c sim3.c
|
||||
ln ../../z80sim/sim4.c sim4.c
|
||||
ln ../../z80sim/sim5.c sim5.c
|
||||
ln ../../z80sim/sim6.c sim6.c
|
||||
ln ../../z80sim/sim7.c sim7.c
|
||||
ln ../../z80sim/simfun.c simfun.c
|
||||
ln ../../z80sim/simint.c simint.c
|
||||
ln ../../z80sim/simglb.c simglb.c
|
||||
ln ../../z80sim/simglb.h simglb.h
|
96
emu/z80pack-1.9/cpmsim/srcsim/sim.h
Normal file
96
emu/z80pack-1.9/cpmsim/srcsim/sim.h
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Z80SIM - a Z80-CPU simulator
|
||||
*
|
||||
* Copyright (C) 1987-2006 by Udo Munk
|
||||
*
|
||||
* History:
|
||||
* 28-SEP-87 Develoment on TARGON/35 with AT&T Unix System V.3
|
||||
* 11-JAN-89 Release 1.1
|
||||
* 08-FEB-89 Release 1.2
|
||||
* 13-MAR-89 Release 1.3
|
||||
* 09-FEB-90 Release 1.4 Ported to TARGON/31 M10/30
|
||||
* 23-DEC-90 Release 1.5 Ported to COHERENT 3.0
|
||||
* 10-JUN-92 Release 1.6 long casting problem solved with COHERENT 3.2
|
||||
* and some optimization
|
||||
* 25-JUN-92 Release 1.7 comments in english
|
||||
* 02-OCT-06 Release 1.8 modified to compile on modern POSIX OS's
|
||||
*/
|
||||
|
||||
/*
|
||||
* The following defines may be activated, commented or modified
|
||||
* by user for her/his own purpose.
|
||||
*/
|
||||
#define WANT_INT /* interrupt for MP/M */
|
||||
/*#define WANT_SPC*/ /* CP/M doesn't work with SP over-/underrun */
|
||||
/*#define WANT_PCC*/ /* CP/M doesn't work with PC overrun */
|
||||
/*#define CNTL_C*/ /* don't abort simulation with cntl-c */
|
||||
#define CNTL_BS /* emergency exit with cntl-\ :-) */
|
||||
/*#define CNTL_Z*/ /* don't suspend simulation with cntl-z */
|
||||
#define WANT_TIM /* run length measurement needed to adjust CPU speed */
|
||||
/*#define HISIZE 1000*//* no history */
|
||||
/*#define SBSIZE 10*/ /* no breakpoints */
|
||||
|
||||
/*
|
||||
* The following lines of this file should not be modified by user
|
||||
*/
|
||||
#define COPYR "Copyright (C) 1987-2006 by Udo Munk"
|
||||
#define RELEASE "1.9"
|
||||
|
||||
#define LENCMD 80 /* length of command buffers etc */
|
||||
|
||||
#define S_FLAG 128 /* bit definitions of CPU flags */
|
||||
#define Z_FLAG 64
|
||||
#define N2_FLAG 32
|
||||
#define H_FLAG 16
|
||||
#define N1_FLAG 8
|
||||
#define P_FLAG 4
|
||||
#define N_FLAG 2
|
||||
#define C_FLAG 1
|
||||
|
||||
/* operation of simulated CPU */
|
||||
#define SINGLE_STEP 0 /* single step */
|
||||
#define CONTIN_RUN 1 /* continual run */
|
||||
#define STOPPED 0 /* stop CPU because of error */
|
||||
|
||||
/* causes of error */
|
||||
#define NONE 0 /* no error */
|
||||
#define OPHALT 1 /* HALT op-code trap */
|
||||
#define IOTRAP 2 /* IN/OUT trap */
|
||||
#define OPTRAP1 3 /* illegal 1 byte op-code trap */
|
||||
#define OPTRAP2 4 /* illegal 2 byte op-code trap */
|
||||
#define OPTRAP4 5 /* illegal 4 byte op-code trap */
|
||||
#define USERINT 6 /* user interrupt */
|
||||
|
||||
/* type of CPU interrupt */
|
||||
#define INT_NONE 0
|
||||
#define INT_NMI 1 /* non maskable interrupt */
|
||||
#define INT_INT 2 /* maskable interrupt */
|
||||
|
||||
typedef unsigned short WORD; /* 16 bit unsigned */
|
||||
typedef unsigned char BYTE; /* 8 bit unsigned */
|
||||
|
||||
#ifdef HISIZE
|
||||
struct history { /* structure of a history entry */
|
||||
WORD h_adr; /* address of execution */
|
||||
WORD h_af; /* register AF */
|
||||
WORD h_bc; /* register BC */
|
||||
WORD h_de; /* register DE */
|
||||
WORD h_hl; /* register HL */
|
||||
WORD h_ix; /* register IX */
|
||||
WORD h_iy; /* register IY */
|
||||
WORD h_sp; /* register SP */
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef SBSIZE
|
||||
struct softbreak { /* structure of a breakpoint */
|
||||
WORD sb_adr; /* address of breakpoint */
|
||||
BYTE sb_oldopc; /* op-code at address of breakpoint */
|
||||
int sb_passcount; /* pass counter of breakpoint */
|
||||
int sb_pass; /* no. of pass to break */
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef isxdigit
|
||||
#define isxdigit(c) ((c<='f'&&c>='a')||(c<='F'&&c>='A')||(c<='9'&&c>='0'))
|
||||
#endif
|
92
emu/z80pack-1.9/cpmsim/srcsim/simctl.c
Normal file
92
emu/z80pack-1.9/cpmsim/srcsim/simctl.c
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Z80SIM - a Z80-CPU simulator
|
||||
*
|
||||
* Copyright (C) 1987-2006 by Udo Munk
|
||||
*
|
||||
* History:
|
||||
* 28-SEP-87 Development on TARGON/35 with AT&T Unix System V.3
|
||||
* 14-MAR-89 new option -l
|
||||
* 23-DEC-90 Ported to COHERENT 3.0
|
||||
* 06-OCT-06 modified to compile on modern POSIX OS's
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <termios.h>
|
||||
#include <fcntl.h>
|
||||
#include "sim.h"
|
||||
#include "simglb.h"
|
||||
|
||||
extern void cpu(void);
|
||||
|
||||
struct termios old_term, new_term;
|
||||
|
||||
/*
|
||||
* This function gets the CP/M boot sector from first track/sector
|
||||
* of disk drive A (file drivea.cpm) into memory started at 0.
|
||||
* Then the Z80 CPU emulation is started and the system should boot.
|
||||
*/
|
||||
void mon(void)
|
||||
{
|
||||
register int fd;
|
||||
|
||||
if (!l_flag) {
|
||||
if ((fd = open("disks/drivea.cpm", O_RDONLY)) == -1) {
|
||||
perror("file disks/drivea.cpm");
|
||||
return;
|
||||
}
|
||||
if (read(fd, (char *) ram, 128) != 128) {
|
||||
perror("file disks/drivea.cpm");
|
||||
return;
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
tcgetattr(0, &old_term);
|
||||
new_term = old_term;
|
||||
new_term.c_lflag &= ~(ICANON | ECHO);
|
||||
new_term.c_iflag &= ~(IXON | IXANY | IXOFF);
|
||||
new_term.c_iflag &= ~(IGNCR | ICRNL | INLCR);
|
||||
new_term.c_cc[VMIN] = 1;
|
||||
#ifndef CNTL_Z
|
||||
new_term.c_cc[VSUSP] = 0;
|
||||
#endif
|
||||
tcsetattr(0, TCSADRAIN, &new_term);
|
||||
|
||||
cpu_state = CONTIN_RUN;
|
||||
cpu_error = NONE;
|
||||
cpu();
|
||||
|
||||
tcsetattr(0, TCSADRAIN, &old_term);
|
||||
|
||||
switch (cpu_error) {
|
||||
case NONE:
|
||||
break;
|
||||
case OPHALT:
|
||||
printf("\nHALT Op-Code reached at %04x\n",
|
||||
(unsigned int)(PC - ram - 1));
|
||||
break;
|
||||
case IOTRAP:
|
||||
printf("\nI/O Trap at %04x\n", (unsigned int)(PC - ram));
|
||||
break;
|
||||
case OPTRAP1:
|
||||
printf("\nOp-code trap at %04x %02x\n",
|
||||
(unsigned int)(PC - 1 - ram), *(PC - 1));
|
||||
break;
|
||||
case OPTRAP2:
|
||||
printf("\nOp-code trap at %04x %02x %02x\n",
|
||||
(unsigned int)(PC - 2 - ram), *(PC - 2), *(PC - 1));
|
||||
break;
|
||||
case OPTRAP4:
|
||||
printf("\nOp-code trap at %04x %02x %02x %02x %02x\n",
|
||||
(unsigned int)(PC - 4 - ram), *(PC - 4), *(PC - 3),
|
||||
*(PC - 2), *(PC - 1));
|
||||
break;
|
||||
case USERINT:
|
||||
puts("\nUser Interrupt");
|
||||
break;
|
||||
default:
|
||||
printf("\nUnknown error %d\n", cpu_error);
|
||||
break;
|
||||
}
|
||||
}
|
6
emu/z80pack-1.9/cpmsim/srcsim/ulnsrc
Executable file
6
emu/z80pack-1.9/cpmsim/srcsim/ulnsrc
Executable file
@@ -0,0 +1,6 @@
|
||||
# use this to unlink the common parts of Z80 simulation
|
||||
|
||||
rm sim[0-7].c
|
||||
rm simfun.c
|
||||
rm simint.c
|
||||
rm simglb.[hc]
|
Reference in New Issue
Block a user