home *** CD-ROM | disk | FTP | other *** search
- /*
-
- up/m - unix CP/M.
-
- (C) MCMXC - Nick Sayer - All rights reserved.
-
- See COPYRIGHT file for more details.
-
-
- Configuration section.
-
-
- CPM_FILE - default file with CP/M HEX images.
-
- Addresses 0-2K are CCP, 2K-5.5K - BDOS. 5.5K-16K - BIOS. Address 65535
- will have the length (in pages) of CP/M.
-
- Addresses 16K-? - relocation bitmap. Each bit in the bitmap represents
- a BYTE in 0-16K. If the bit is 1, the high byte of the first address of
- the destination address for the CCP should be added to the byte in 0-16K
- image. That image is then moved to the proper location. The PC is set to
- 32K and the Z-80 starts running. The high byte of the first byte of the
- CCP destination address is gotten from address 65535. This value is
- then adjusted if CP/M is to be relocated lower than the default
- top of memory. The CP/M image to load should have a resident run address
- before relocation of 0.
-
- */
- #define CPM_FILE "CPM"
-
- #include <strings.h>
- #include <ctype.h>
- #include <sgtty.h>
- #include <signal.h>
-
- #include "upm.h"
-
- WORD topmem=256; /* These may be changed by arguments */
- char *cpm_file=CPM_FILE;
-
- struct sgttyb tty_sgtty_data;
-
- static BYTE dph[32]={
-
- /* Disk Paramater Header (diskbufs[]) */
-
- 0x00,0x00, /* TRANSTABLE unused */
- 0x00,0x00, /* unused */
- 0x00,0x00,
- 0x00,0x00,
- 0x80,0xff, /* DIRBUF - patch with topmem-1 later */
- 0x10,0xff, /* DPB - patch with OUR page no. */
- 0x00,0x00, /* CHKVEC - not used */
- 0x20,0xff, /* ALLOCVEC - patch with OUR page no. */
-
- /* Disk Paramater Block */
-
- 0x40,0x00, /* Sectors per track */
- 0x04, /* Block Shift */
- 0x0f, /* Block Mask */
- 0x00, /* Extent Mask */
- 0x00,0x10, /* Blocks on device - patch if variable size implemented */
- 0xff,0x01, /* Directory entries -1 */
- 0xff,0x00, /* Allocation masks for directory */
- 0x00,0x00, /* Check vector size - patch if checkvecs implemented */
- 0x00,0x00, /* offset to first user-track */
- 0x00 /* spare */
- };
-
- /* These are externs in upm.h, but they have to be declared somewhere. */
-
- FILE *disks[16],*devices[5];
- WORD diskbufs[16];
- BYTE ccp_image[SIZE_CCP_IMAGE];
- WORD ccp_start;
-
- /*
-
- relocade(address);
- BYTE address;
-
- Relocate CP/M image at 0000-4000 using bitmap at 4000-4800.
- Copy image to new location, and copy first 5.5K to ccp_image[];
- Stop if we get to the top of RAM.
-
- */
-
- relocate(add,len)
- BYTE add;
- {
- WORD i;
-
- for (i=0;i!=(256*len);i++)
- {
- if ( real_z80_mem[16384+(i>>3)]&(1<<(i&7)) )
- real_z80_mem[i]=real_z80_mem[i]+add;
- real_z80_mem[i+(add<<8)]=real_z80_mem[i];
- if (i<SIZE_CCP_IMAGE)
- ccp_image[i]=real_z80_mem[i];
- }
- }
- int debugflag = 0;
- int dlogflag = 0;
-
- debugit();
-
- main(argc,argv)
- int argc;
- char **argv;
- {
- FILE *cpm;
- char line[80];
- int i;
-
- signal(SIGINT,debugit);
-
- for(i=0;i<16;i++)
- {
- disks[i]=NULL;
- devices[i%5]=NULL; /* hack: only do 0-4 */
- }
-
- /* OPEN ~/.upmrc, send each line to process_args(line); */
-
- argc--; argv++;
- for(;argc--;argv++)
- process_args(*argv);
-
- if (disks[0]==NULL)
- {
- printf("A: must be assigned.\n");
- exit(0);
- }
-
- /*
-
- For each non-null pointer in disks[], lower topmem, and save the pointer
- to diskbufs[]. This assigns space for the allocation vector, and the
- DPH/DPB. Then copy in a "standard" DPH/DPB into the bottom. We'll
- patch it later.
-
- We really should allow disks to be sized at runtime, but for now
- they're fixed at 8MB, so we lower topmem 3 for each one. 2 pages
- for the alloc table, another page (actually 32 bytes)
- for the miscelany.
-
- */
-
- for(i=0;i!=16;i++)
- {
- char j;
-
- if (disks[i]==NULL)
- continue;
- topmem-=3;
- diskbufs[i]=topmem<<8;
- for(j=0;j!=32;j++)
- real_z80_mem[diskbufs[i]+j]=dph[j];
- real_z80_mem[diskbufs[i]+0x0b]=real_z80_mem[diskbufs[i]+0x0f]=topmem;
- }
-
- /*
-
- Now for each non-null disk[] readjust the dirbuf pointer.
- We couldn't do it before because we didn't have a final
- location for dirbuf. topmem-1 is the high-byte of the
- final location for dirbuf. the low byte is 0x80.
- This page of memory is shared with the BIOS "jump" table.
-
- */
-
- for(i=0;i!=16;i++)
- {
- if (disks[i]==NULL)
- continue;
- real_z80_mem[diskbufs[i]+9]=topmem-1;
- }
-
- cpm=fopen(cpm_file,"r");
- if (cpm==NULL)
- {
- printf("Can't open CP/M binaries: %s\n",sys_errlist[errno]);
- exit(1);
- }
- loadhex(cpm);
-
- ccp_start=(topmem-real_z80_mem[65535])<<8;
- relocate(topmem-real_z80_mem[65535],real_z80_mem[65535]);
-
- PC=0x8000;
-
- /*
-
- Now set up the terminal. Just toggling RAW should be enough.
-
- */
-
- gtty(fileno(stdin),&tty_sgtty_data);
- tty_sgtty_data.sg_flags|=RAW;
- tty_sgtty_data.sg_flags&=~ECHO;
- stty(fileno(stdin),&tty_sgtty_data);
-
- do
- { z80_run();
- if(debugflag>1 && debugit()) PC++;
- else if(bios()) break;
- } while(1); /* } while(!bios()); */
-
- gtty(fileno(stdin),&tty_sgtty_data);
- tty_sgtty_data.sg_flags&=~RAW;
- tty_sgtty_data.sg_flags|=ECHO;
- stty(fileno(stdin),&tty_sgtty_data);
- }
-
- /*
-
- The arguments can include A:file-O:file, {TY, LP, PT, U1, U2}:file,
- mem:0-128.
-
- Disk files are fopen()ed "r+", and are assigned to disks[].
- Device files are fopen()ed "r+" and are assigned to devices[], except
- for LP:, which is fopen()ed "w".
-
- The value after mem: lowers the top of memory by that many pages (256
- bytes) to save space for things like BYE, etc.
-
- The arguments MUST be stripped of white-spaces.
-
- */
-
- process_args(arg)
- char *arg;
- {
- char i,left[80],*right;
-
- if (index(arg,':')==NULL)
- {
- printf("Missing ':' in argument.\n");
- return;
- }
-
- strcpy(left,arg);
- right=index(left,':')+1;
- *index(left,':')='\0';
- for(i=0;i!=strlen(left);i++)
- if (islower(left[i]))
- left[i]=toupper(left[i]);
-
- if (strlen(left)==1 && (*left<='O') && (*left>='A'))
- {
- disks[*left-'A']=fopen(right,"r+");
- return;
- }
- if (!strcmp(left,"MEM"))
- {
- topmem-=atoi(right);
- return;
- }
- if (!strcmp(left,"TY"))
- {
- devices[F_TY]=fopen(right,"r+");
- return;
- }
- if (!strcmp(left,"PT"))
- {
- devices[F_PT]=fopen(right,"r+");
- return;
- }
- if (!strcmp(left,"LP"))
- {
- devices[F_LP]=fopen(right,"w");
- return;
- }
- if (!strcmp(left,"U1"))
- {
- devices[F_U1]=fopen(right,"r+");
- return;
- }
- if (!strcmp(left,"U2"))
- {
- devices[F_U2]=fopen(right,"r+");
- return;
- }
- if (!strcmp(left,"DEBUG"))
- {
- debugflag=atoi(right);
- return;
- }
- if (!strcmp(left,"DLOG"))
- {
- dlogflag=atoi(right);
- return;
- }
- if (!strcmp(left,"BIOS"))
- {
- biosflag=atoi(right);
- return;
- }
- if (!strcmp(left,"TRAP"))
- {
- sscanf(right,"%4x",&TRAPval);
- return;
- }
- if (!strcmp(left,"TWRT"))
- {
- sscanf(right,"%4x",&TWRTval);
- return;
- }
- }
-
- coredump()
- {
- FILE *qb;
- int i;
-
- qb=fopen("mem","w");
- for(i=0;i!=65536;i++)
- putc(real_z80_mem[i],qb);
- fclose(qb);
- }
-