/***************************************************************************** * * * CQM UDOS file generation for P8000 floppies * * generates UDOS disk from files given as program arguments * * calling without file arguments creates empty, formatted UDOS disk * * Copyright (C) Matt Knoth, 2008, * * * * This program has been derived in part from from LIBDSK 1.2.1 * * LIBDSK: General floppy and diskimage access library * * Copyright (C) 2001-2,2005 John Elliott * * Credits also to Per Ola Ingvarsson and Roger Plant * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Library General Public * * License as published by the Free Software Foundation; either * * version 2 of the License, or (at your option) any later version. * * * * This code is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * Library General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this library; if not, write to the Free * * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * * MA 02111-1307, USA * * * *****************************************************************************/ #include #include #include #include #include #include #include #include unsigned char* get_wr_ptr(unsigned short sec_id); unsigned char* disk=NULL; unsigned char* allocs; int freeblocks=0; /* Automatically generated CRC table */ /* polynomial: 0x104C11DB7, bit reverse algorithm */ const unsigned long crc32r_table[256] = { 0x00000000UL,0x77073096UL,0xEE0E612CUL,0x990951BAUL, 0x076DC419UL,0x706AF48FUL,0xE963A535UL,0x9E6495A3UL, 0x0EDB8832UL,0x79DCB8A4UL,0xE0D5E91EUL,0x97D2D988UL, 0x09B64C2BUL,0x7EB17CBDUL,0xE7B82D07UL,0x90BF1D91UL, 0x1DB71064UL,0x6AB020F2UL,0xF3B97148UL,0x84BE41DEUL, 0x1ADAD47DUL,0x6DDDE4EBUL,0xF4D4B551UL,0x83D385C7UL, 0x136C9856UL,0x646BA8C0UL,0xFD62F97AUL,0x8A65C9ECUL, 0x14015C4FUL,0x63066CD9UL,0xFA0F3D63UL,0x8D080DF5UL, 0x3B6E20C8UL,0x4C69105EUL,0xD56041E4UL,0xA2677172UL, 0x3C03E4D1UL,0x4B04D447UL,0xD20D85FDUL,0xA50AB56BUL, 0x35B5A8FAUL,0x42B2986CUL,0xDBBBC9D6UL,0xACBCF940UL, 0x32D86CE3UL,0x45DF5C75UL,0xDCD60DCFUL,0xABD13D59UL, 0x26D930ACUL,0x51DE003AUL,0xC8D75180UL,0xBFD06116UL, 0x21B4F4B5UL,0x56B3C423UL,0xCFBA9599UL,0xB8BDA50FUL, 0x2802B89EUL,0x5F058808UL,0xC60CD9B2UL,0xB10BE924UL, 0x2F6F7C87UL,0x58684C11UL,0xC1611DABUL,0xB6662D3DUL, 0x76DC4190UL,0x01DB7106UL,0x98D220BCUL,0xEFD5102AUL, 0x71B18589UL,0x06B6B51FUL,0x9FBFE4A5UL,0xE8B8D433UL, 0x7807C9A2UL,0x0F00F934UL,0x9609A88EUL,0xE10E9818UL, 0x7F6A0DBBUL,0x086D3D2DUL,0x91646C97UL,0xE6635C01UL, 0x6B6B51F4UL,0x1C6C6162UL,0x856530D8UL,0xF262004EUL, 0x6C0695EDUL,0x1B01A57BUL,0x8208F4C1UL,0xF50FC457UL, 0x65B0D9C6UL,0x12B7E950UL,0x8BBEB8EAUL,0xFCB9887CUL, 0x62DD1DDFUL,0x15DA2D49UL,0x8CD37CF3UL,0xFBD44C65UL, 0x4DB26158UL,0x3AB551CEUL,0xA3BC0074UL,0xD4BB30E2UL, 0x4ADFA541UL,0x3DD895D7UL,0xA4D1C46DUL,0xD3D6F4FBUL, 0x4369E96AUL,0x346ED9FCUL,0xAD678846UL,0xDA60B8D0UL, 0x44042D73UL,0x33031DE5UL,0xAA0A4C5FUL,0xDD0D7CC9UL, 0x5005713CUL,0x270241AAUL,0xBE0B1010UL,0xC90C2086UL, 0x5768B525UL,0x206F85B3UL,0xB966D409UL,0xCE61E49FUL, 0x5EDEF90EUL,0x29D9C998UL,0xB0D09822UL,0xC7D7A8B4UL, 0x59B33D17UL,0x2EB40D81UL,0xB7BD5C3BUL,0xC0BA6CADUL, 0xEDB88320UL,0x9ABFB3B6UL,0x03B6E20CUL,0x74B1D29AUL, 0xEAD54739UL,0x9DD277AFUL,0x04DB2615UL,0x73DC1683UL, 0xE3630B12UL,0x94643B84UL,0x0D6D6A3EUL,0x7A6A5AA8UL, 0xE40ECF0BUL,0x9309FF9DUL,0x0A00AE27UL,0x7D079EB1UL, 0xF00F9344UL,0x8708A3D2UL,0x1E01F268UL,0x6906C2FEUL, 0xF762575DUL,0x806567CBUL,0x196C3671UL,0x6E6B06E7UL, 0xFED41B76UL,0x89D32BE0UL,0x10DA7A5AUL,0x67DD4ACCUL, 0xF9B9DF6FUL,0x8EBEEFF9UL,0x17B7BE43UL,0x60B08ED5UL, 0xD6D6A3E8UL,0xA1D1937EUL,0x38D8C2C4UL,0x4FDFF252UL, 0xD1BB67F1UL,0xA6BC5767UL,0x3FB506DDUL,0x48B2364BUL, 0xD80D2BDAUL,0xAF0A1B4CUL,0x36034AF6UL,0x41047A60UL, 0xDF60EFC3UL,0xA867DF55UL,0x316E8EEFUL,0x4669BE79UL, 0xCB61B38CUL,0xBC66831AUL,0x256FD2A0UL,0x5268E236UL, 0xCC0C7795UL,0xBB0B4703UL,0x220216B9UL,0x5505262FUL, 0xC5BA3BBEUL,0xB2BD0B28UL,0x2BB45A92UL,0x5CB36A04UL, 0xC2D7FFA7UL,0xB5D0CF31UL,0x2CD99E8BUL,0x5BDEAE1DUL, 0x9B64C2B0UL,0xEC63F226UL,0x756AA39CUL,0x026D930AUL, 0x9C0906A9UL,0xEB0E363FUL,0x72076785UL,0x05005713UL, 0x95BF4A82UL,0xE2B87A14UL,0x7BB12BAEUL,0x0CB61B38UL, 0x92D28E9BUL,0xE5D5BE0DUL,0x7CDCEFB7UL,0x0BDBDF21UL, 0x86D3D2D4UL,0xF1D4E242UL,0x68DDB3F8UL,0x1FDA836EUL, 0x81BE16CDUL,0xF6B9265BUL,0x6FB077E1UL,0x18B74777UL, 0x88085AE6UL,0xFF0F6A70UL,0x66063BCAUL,0x11010B5CUL, 0x8F659EFFUL,0xF862AE69UL,0x616BFFD3UL,0x166CCF45UL, 0xA00AE278UL,0xD70DD2EEUL,0x4E048354UL,0x3903B3C2UL, 0xA7672661UL,0xD06016F7UL,0x4969474DUL,0x3E6E77DBUL, 0xAED16A4AUL,0xD9D65ADCUL,0x40DF0B66UL,0x37D83BF0UL, 0xA9BCAE53UL,0xDEBB9EC5UL,0x47B2CF7FUL,0x30B5FFE9UL, 0xBDBDF21CUL,0xCABAC28AUL,0x53B39330UL,0x24B4A3A6UL, 0xBAD03605UL,0xCDD70693UL,0x54DE5729UL,0x23D967BFUL, 0xB3667A2EUL,0xC4614AB8UL,0x5D681B02UL,0x2A6F2B94UL, 0xB40BBE37UL,0xC30C8EA1UL,0x5A05DF1BUL,0x2D02EF8DUL, }; static void drv_qm_update_crc( unsigned long* crc, unsigned char byte ) { /* Note that there is a bug in the CopyQM CRC calculation */ /* When indexing in this table, they shift the crc ^ data */ /* 2 bits up to address longwords, but they do that in an */ /* eight bit register, so that the top 2 bits are lost, */ /* thus the anding with 0x3f */ *crc = crc32r_table[(byte ^ (unsigned char)*crc) & 0x3f ] ^ (*crc >> 8); } void drv_qm_dump_compressed(FILE* ofp,unsigned long* pcrc,unsigned char* rd_ptr, int sector_size) { unsigned char* p; unsigned char a; int i,l,len; for(i=0; i>8); tmp = 80 * 2 * 16; buf[0x0b]= (unsigned char)tmp; buf[0x0c]= (unsigned char)(tmp>>8); buf[0x10]= (unsigned char)16; buf[0x11]= (unsigned char)(16>>8); buf[0x12]= (unsigned char)2; tmp = (80 * 2 * 16 * 256)>>10; sprintf(&buf[0x1c],"%dK MAME emulation floppy",tmp); buf[0x5a]= (unsigned char)80; buf[0x5b]= (unsigned char)80; sprintf(&buf[0x60],"** NONE **"); // volume label 0x60 fwrite(buf,1,133,ofp); // write header preliminary rd_cyl = 0; rd_head = 0; rd_sec = 1; rd_track = 0; crc = 0l; do { rd_ptr = get_wr_ptr( ((rd_head & 0x01)<<12) | (((rd_sec-1) & 0x0f)<<8) | (rd_cyl & 0xff)); drv_qm_dump_compressed( ofp, &crc, rd_ptr, 256); rd_sec++; if(rd_sec > 16) { rd_sec=1; rd_track++; rd_cyl = (rd_track / 2); rd_head = (rd_track % 2); } } while((rd_cyl < 80) && (rd_head < 2) && (rd_sec < (1 + 16))); buf[0x5c]= (unsigned char)crc; buf[0x5d]= (unsigned char)(crc>>8); buf[0x5e]= (unsigned char)(crc>>16); buf[0x5f]= (unsigned char)(crc>>24); crc = 0l; for(tmp=0; tmp<132; tmp++) crc+=buf[tmp]; crc = - crc; buf[0x84]= (unsigned char)crc; fseek(ofp,0l,SEEK_SET); fwrite(buf,1,133,ofp); // write header final fclose(ofp); } void dump_sector_hex(FILE* ofp,int cyl, int head, int sector) { int m,n; unsigned char* pSec; fprintf(ofp,"ndrv_qm_read(cylinder=%d,head=%d,sector=%d)\n",cyl,head,sector+1); pSec = disk + (256*(32*cyl + 16*head + sector)); for (n = 0; n < 256; n = ((n / 16)+1)*16) { int base = (n/16)*16; int c = 0; fprintf(ofp,"%04x: ", n); for (m = 0; m < (n%16); m++) { fputc(' ',ofp); fputc(' ',ofp); if ((c & 3) == 3) fputc(' ',ofp); c++; } for (m = (n % 16); m < 16; m++) { fprintf(ofp,"%02x", pSec[base+m]); if ((c & 3) == 3) fputc(' ',ofp); c++; if ((n + m + 1) >= 256) break; } for (; c < 16; c++) { fputc(' ',ofp); fputc(' ',ofp); if ((c & 3) == 3) fputc(' ',ofp); } fprintf(ofp," *"); for (m = 0; m < (n%16); m++) fputc(' ',ofp); for (m = (n % 16); m < 16; m++) { if (isprint(pSec[base+m])) fputc(pSec[base+m],ofp); else fputc('.',ofp); if ((n + m + 1) >= 256) break; } fputc('*',ofp); fputc('\n',ofp); } } int sec_alloc(unsigned short sec_id) { int sector, head, cylinder; int idx_totl, idx_byte; unsigned char idx_bits; cylinder= sec_id & 0xff; head = (sec_id & 0x1000)>>12; sector= (sec_id & 0x0f00)>>8; idx_totl = 2*16*cylinder + 2*head + sector; idx_byte = idx_totl>>3; idx_bits = 0x80>>(idx_totl & 0x07); allocs[idx_byte] |= idx_bits; freeblocks--; } unsigned short alloc_free_sector(void) { int i,n,m,c,h,s; for(i=0; (i<320) && (allocs[i]==0xff); i++); // find first empty sector in alloc string if(i>=320) return 0xffff; // disk full for(n=i<<3, m=0x80; (m & allocs[i]); n++, m=m>>1); // find first empty sector in this alloc byte allocs[i] |= m; // allocate this sector freeblocks--; // one more sector used c=n/32; // cylinders, given 32 sectors/cylinder h=((n%32)>15)? 1:0; // head, given 16 sectors/side s=(n%32) & 0x0f; // sector, given 16 sectors/side return (((h & 0x01)<<12) | ((s & 0x0f)<<8) | (c & 0xff)); // sector id } unsigned char* get_wr_ptr(unsigned short sec_id) { int sector, head, cylinder; cylinder= sec_id & 0xff; head = (sec_id & 0x1000)>>12; sector= (sec_id & 0x0f00)>>8; return disk + (256*(32*cylinder + 16*head + sector)); } unsigned short update_directory(unsigned short dscr_blk, char* fname, int order) { unsigned short ptr_blk, dir_blk; unsigned char* dsc_ptr,* ptr_ptr,* dir_ptr; char buf[40], *p; int n,i,j; p=strrchr(fname,'\\'); // DOS type directory separator if(!p) p=strrchr(fname,'/'); // UNIX type directory separator if(p) p++; // set to file name else p=fname; // no hierarchy separator found n=strlen(p); if(n>32) { sprintf(buf,"D%02d%s",order & 0x3f,p+n-29); fprintf(stderr,"WARNING: file name %s length > 32 - shorten to %s\n",p,buf); n=32; } else { strcpy(buf,p); } printf("add file %s\n",buf); dsc_ptr=get_wr_ptr(0x0016); // get directory descriptor, for P8000 in 0x0016 ptr_blk=(dsc_ptr[0x80]<<8) | dsc_ptr[0x81]; // get ptr sector (only one available assumed) ptr_ptr=get_wr_ptr(ptr_blk); // get ptr sector pointer for(i=2; i<=ptr_ptr[0xfa]; i+=2) { // go through all allocated directory data sectors dir_blk=(ptr_ptr[i]<<8) | ptr_ptr[i+1]; // current directory data pointer dir_ptr=get_wr_ptr(dir_blk); // translate to read address for(j=0; (j<256) && (dir_ptr[j]!=0xff); j++); // find 0xff entry end marker if((j>=256) || ((j+n+3)>=255)) continue; // this sector full or defective dir_ptr[j]=(unsigned char)n; // set name length strcpy(&dir_ptr[j+1],buf); // set name dir_ptr[j+n+1]=(unsigned char)(dscr_blk>>8); // set descriptor head/sector dir_ptr[j+n+2]=(unsigned char)(dscr_blk); // set descriptor cylinder dir_ptr[j+n+3]=0xff; // set new end marker break; // all done, go no further } if(i>ptr_ptr[0xfa]) return(0xffff); // all entries taken return(dir_blk); // this directory sector } unsigned short fill_data_sectors(FILE* ifp, unsigned short dscr_blk, int ptr_sectors, int rem_bytes, int sectors) { unsigned short ptr_blk, base_blk, nxt_blk; unsigned char* ptr_ptr,* base_ptr,* nxt_ptr,* dscr_ptr; unsigned char buf[256]; int i,j; dscr_ptr=get_wr_ptr(dscr_blk); // get descriptor accessor ptr_blk=(dscr_ptr[0x80]<<8) | dscr_ptr[0x81]; // first pointer sector ptr_ptr=get_wr_ptr(ptr_blk); // first pointer pointer memset(ptr_ptr,0,256); // clean up pointer sector ptr_ptr[0x00]=(unsigned char)(dscr_blk>>8); // enter descriptor head/sector ptr_ptr[0x01]=(unsigned char)dscr_blk; // enter descriptor cylinder ptr_ptr[0x02]=dscr_ptr[0x08]; // first data block ptr_ptr[0x03]=dscr_ptr[0x09]; // first data block ptr_ptr[0xfa]=0x02; // last entry for now ptr_ptr[0xfc]=(unsigned char)(dscr_blk>>8); // enter descriptor head/sector ptr_ptr[0xfd]=(unsigned char)dscr_blk; // enter descriptor cylinder ptr_ptr[0xfe]=0xff; // mark as last pointer sector ptr_ptr[0xff]=0xff; // mark as last pointer sector if(sectors==0) { // empty files nxt_blk=(ptr_ptr[0x02]<<8) | ptr_ptr[0x03]; // last and only data sector nxt_ptr=get_wr_ptr(nxt_blk); // get write pointer memset(nxt_ptr,0,256); // clean up segment return(nxt_blk); // last data block } // allocate all pointer sectors ///////////////////////////////////////////////////////////////////////////// base_blk=ptr_blk; // initialize base base_ptr=ptr_ptr; // initialize base pointer for(i=1; i>8); // mark previous sector head/sector nxt_ptr[0xfd]=(unsigned char)base_blk; // mark previous sector cylinder nxt_ptr[0xfe]=0xff; // mark end of sectors nxt_ptr[0xff]=0xff; // mark end of sectors base_ptr[0xfe]=(unsigned char)(nxt_blk>>8); // link in new block head/sector base_ptr[0xff]=(unsigned char)nxt_blk; // link in new block cylinder base_blk=nxt_blk; // advance base base_ptr=nxt_ptr; // advance base } // allocate and fill all data sectors //////////////////////////////////////////////////////////////////////// base_blk=ptr_blk; // initialize base base_ptr=ptr_ptr; // initialize base pointer nxt_blk=(ptr_ptr[0x02]<<8)|ptr_ptr[0x03]; // first data block nxt_ptr=get_wr_ptr(nxt_blk); // get write pointer for(i=0, j=1; i>8); // set new data sector head/sector base_ptr[(j<<1)+1]=(unsigned char)nxt_blk; // set new data sector cylinder base_ptr[0xfa]=j<<1; // set last pointer in this segment base_ptr[0xfb]=0x00; // set last pointer in this segment memset(buf,0x00,256); // initialize for last sector trash tail fread(buf,1,256,ifp); // get file data memcpy(nxt_ptr,buf,256); // copy data, last sector tails trash j++; if(j>=125) { // this pointer sector full j=0; // reset entry index base_blk=(base_ptr[0xfe]<<8) | base_ptr[0xff]; // get next block pointer base_ptr=get_wr_ptr(base_blk); // get write pointer if(base_blk==0xffff) { // should not happen tho fprintf(stderr,"ERROR: pointer list error - abort\n"); exit (-1); } } } return(nxt_blk); } int create_empty_disk(void) { struct timeb timeb; struct tm tm_creat; unsigned char* wptr; int i; // create empty disk and allocation table ///////////////////////////////////////////// if(disk) free(disk); // if previously allocated disk=malloc(80*16*2*256); // allocate 640K disk memset(disk,0xe5,80*16*2*256); // format disk allocs=get_wr_ptr(0x0017); // disk allocation table (cyl=23,head=0,sector=0) memset(allocs,0,512); // clear both allocation table sectors sprintf(allocs,"P8000emu - makeUDOSdisk"); // !! relies on 23byte string allocs[23]=0x0d; // fill disk label (relies on 23bytes before) memset(allocs+24,0,320); // clear allocation table memset(allocs+0x15c,0x77,32); // set UDOS magic - don't know what this is allocs+=24; // set to allocation table freeblocks=2560; // initialize free block counter sec_alloc(0x0017); // now allocate table sector 1 sec_alloc(0x0117); // now allocate table sector 2 ftime(&timeb); // get creation time localtime_r(&timeb.time, &tm_creat); // translate to ascii // create initial directory sectors ///////////////////////////// sec_alloc(0x0516); // Directory 1st sector wptr=get_wr_ptr(0x0516); // get Directory wr pointer memset(wptr,0,256); // clear sector wptr[0x00]=0x89; // set DIRECTORY string length sprintf(&wptr[1],"DIRECTORY"); // name this sector wptr[10]=0x00; // descriptor - head/sector wptr[11]=0x16; // descriptor - cylinder wptr[12]=0xff; // mark this as last entry sec_alloc(0x0a16); // 2nd directory data sector wptr=get_wr_ptr(0x0a16); // memset(wptr,0,256); // clear sector wptr[0x00]=0xff; // sec_alloc(0x0116); // 3rd directory data sector wptr=get_wr_ptr(0x0116); // memset(wptr,0,256); // clear sector wptr[0x00]=0xff; // sec_alloc(0x0116); // 3rd directory data sector wptr=get_wr_ptr(0x0116); // memset(wptr,0,256); // clear sector wptr[0x00]=0xff; // sec_alloc(0x0616); // 4th directory data sector wptr=get_wr_ptr(0x0616); // memset(wptr,0,256); // clear sector wptr[0x00]=0xff; // sec_alloc(0x0b16); // 5th directory data sector wptr=get_wr_ptr(0x0b16); // memset(wptr,0,256); // clear sector wptr[0x00]=0xff; // // create initial descriptor sector ///////////////////////////// sec_alloc(0x0016); // Directory Descriptor wptr=get_wr_ptr(0x0016); // get Descriptor wr pointer memset(wptr,0,256); // clear sector wptr[0x06]=0x05; // return ptr to directory wptr[0x07]=0x16; wptr[0x08]=0x05; // pre to first data sector wptr[0x09]=0x16; wptr[0x0a]=0x0b; // pre to last data sector wptr[0x0b]=0x16; wptr[0x0c]=0x40; // file type D wptr[0x0d]=0x05; // number of data sectors in file wptr[0x0e]=0x00; wptr[0x0f]=0x00; // sector size wptr[0x10]=0x01; wptr[0x11]=0x00; // sector size wptr[0x12]=0x01; wptr[0x13]=0xf0; // file properties WELS sprintf(&wptr[0x18],"%02d%02d%02d%c",tm_creat.tm_year-100,tm_creat.tm_mon,tm_creat.tm_mday,0xff); sprintf(&wptr[0x20],"%02d%02d%02d%c",tm_creat.tm_year-100,tm_creat.tm_mon,tm_creat.tm_mday,0xff); wptr[0x80]=0x02; // id of first pointer sector wptr[0x81]=0x16; // create initial data pointer sector ///////////////////////////// sec_alloc(0x0216); // Directory Data Pointer Sector wptr=get_wr_ptr(0x0216); // get Descriptor wr pointer memset(wptr,0,256); // clear sector wptr[0x00]=0x00; // descriptor pointer wptr[0x01]=0x16; wptr[0x02]=0x05; // first data pointer for directory wptr[0x03]=0x16; wptr[0x04]=0x0a; // second data pointer for directory wptr[0x05]=0x16; wptr[0x06]=0x01; // 3rd data pointer for directory wptr[0x07]=0x16; wptr[0x08]=0x06; // 4th data pointer for directory wptr[0x09]=0x16; wptr[0x0a]=0x0b; // 5th data pointer for directory wptr[0x0b]=0x16; wptr[0x0c]=0xff; // end marker wptr[0x0d]=0xff; wptr[0xfa]=0x0a; // last data pointer for directory wptr[0xfb]=0x00; wptr[0xfc]=0x00; // previous ptr - descriptor wptr[0xfd]=0x16; wptr[0xfe]=0xff; // no next pointer wptr[0xff]=0xff; } int main(int argc, char** argv) { FILE* ifp, *ofp; int i,c,s,h; unsigned short dscr_blk, ptr_blk, data_blk, last_blk, dir_blk; unsigned char* dscr_ptr; struct timeb timeb; struct stat fstatus; struct tm tm_creat; create_empty_disk(); for(i=1; i>8; // sector count h=fstatus.st_size & 0xff; // last sector remainder if(h) s++; // true sector count c=(1+s)/125; // initial data/dscr pointer sectors if((1+s)%125) c++; // correct number of data/dscr sectors if((s+c)>freeblocks) { fprintf(stderr,"ERROR: not enough space for file %s (%d bytes) - omitted\n",argv[i],fstatus.st_size); fclose(ifp); continue; } dscr_blk=alloc_free_sector(); // alloc descriptor block dscr_ptr=get_wr_ptr(dscr_blk); // get descriptor write handle ptr_blk=alloc_free_sector(); // alloc first pointer block data_blk=alloc_free_sector(); // alloc first data pointer block dir_blk=update_directory(dscr_blk,argv[i],i); // create directory entry if(dir_blk==0xffff) { // P8000 UDOS allocates 5 initial directory sectors, we leave it by that for now fprintf(stderr,"ERROR: Directory space overflow - omit file %s and beyond\n",argv[i]); fclose(ifp); break; } // fill in file descriptor //////////////////////////////////////////////////////////////////////////// memset(dscr_ptr,0,256); // erase block dscr_ptr[0x06]=(unsigned char)(dir_blk>>8); // head/sector directory dscr_ptr[0x07]=(unsigned char)dir_blk ; // cylinder directory dscr_ptr[0x08]=(unsigned char)(data_blk>>8); // head/sector directory dscr_ptr[0x09]=(unsigned char)data_blk ; // cylinder directory dscr_ptr[0x0c]=0x20; // data type ASCII dscr_ptr[0x0d]=(unsigned char)s; // used data sectors lo dscr_ptr[0x0e]=(unsigned char)(s>>8); // used data sectors hi dscr_ptr[0x10]=0x01; // sector length 256 dscr_ptr[0x12]=0x01; // sector length 256 dscr_ptr[0x13]=0x08; // type R random access dscr_ptr[0x16]=(unsigned char)h; // bytes in last sector sprintf(&dscr_ptr[0x18],"%02d%02d%02d%c",tm_creat.tm_year-100,tm_creat.tm_mon,tm_creat.tm_mday,0xff); sprintf(&dscr_ptr[0x20],"%02d%02d%02d%c",tm_creat.tm_year-100,tm_creat.tm_mon,tm_creat.tm_mday,0xff); dscr_ptr[0x80]=(unsigned char)(ptr_blk>>8); // first ptr sector - head/sector dscr_ptr[0x81]=(unsigned char)(ptr_blk); // first ptr sector - cylinder last_blk=fill_data_sectors(ifp,dscr_blk,c,h,s); // store all data, fill ptr sectors dscr_ptr[0x0a]=(unsigned char)(last_blk>>8); // last data sector, head/sector dscr_ptr[0x0b]=(unsigned char)(last_blk); // last data sector, cylinder fclose(ifp); // all done. } else { fprintf(stderr,"ERROR: unable to open file %s - omitted\n",argv[i]); } } dscr_ptr=get_wr_ptr(0x0117); dscr_ptr[0x77]=(unsigned char)(2560-freeblocks-1); // used blocks low dscr_ptr[0x78]=(unsigned char)((2560-freeblocks-1)>>8); // used blocks high dscr_ptr[0x79]=0x01; // UDOS magic - don't know dscr_ptr[0x7a]=0x20; // UDOS magic - don't know dscr_ptr[0x7b]=0x50; // UDOS magic - don't know dscr_ptr[0x7c]=(unsigned char)(1+freeblocks); // free blocks low dscr_ptr[0x7d]=(unsigned char)((1+freeblocks)>>8); // free blocks high qm_image_save("udosdsk.cqm"); if((ofp=fopen("udosdsk.hex","wb"))!=NULL) { c=h=s=0; while(1) { dump_sector_hex(ofp,c,h,s); s++; if(s>=16) { if(h>=1) { c++; if(c<80) { h=0; s=0; } else break; } else { h=1; s=0; } } } fclose(ofp); } printf("create debug image: ... udosdsk.hex\n"); printf("create disk image: ... udosdsk.cqm\n"); printf("Done.\n"); return 0; }