157157#define MINI_DISK_SIZE (MINI_DISK_TRACKS * MINI_DISK_SECT * DSK_SECTSIZE)
158158#define MINI_DISK_DELTA 4096 /* threshold for detecting mini disks */
159159
160+ #define ALTAIR_DISK_SIZE 337664 /* size of regular Altair disks */
161+ #define ALTAIR_DISK_DELTA 256 /* threshold for detecting Altair disks */
162+
160163int32 dsk10 (const int32 port , const int32 io , const int32 data );
161164int32 dsk11 (const int32 port , const int32 io , const int32 data );
162165int32 dsk12 (const int32 port , const int32 io , const int32 data );
@@ -187,6 +190,8 @@ static int32 sectors_per_track [NUM_OF_DSK] = { DSK_SECT, DSK_SECT, DSK_SECT, DS
187190 DSK_SECT , DSK_SECT , DSK_SECT , DSK_SECT ,
188191 DSK_SECT , DSK_SECT , DSK_SECT , DSK_SECT ,
189192 DSK_SECT , DSK_SECT , DSK_SECT , DSK_SECT };
193+ static int32 current_image_size [NUM_OF_DSK ] = {
194+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 };
190195static int32 tracks [NUM_OF_DSK ] = { MAX_TRACKS , MAX_TRACKS , MAX_TRACKS , MAX_TRACKS ,
191196 MAX_TRACKS , MAX_TRACKS , MAX_TRACKS , MAX_TRACKS ,
192197 MAX_TRACKS , MAX_TRACKS , MAX_TRACKS , MAX_TRACKS ,
@@ -310,6 +315,8 @@ static REG dsk_reg[] = {
310315 "Number of tracks register array" ), REG_CIRC },
311316 { BRDATAD (SECTPERTRACK , sectors_per_track , 10 , 32 , NUM_OF_DSK ,
312317 "Number of sectors per track register array" ), REG_CIRC },
318+ { BRDATAD (IMAGESIZE , current_image_size , 10 , 32 , NUM_OF_DSK ,
319+ "Size of disk image array" ), REG_CIRC + REG_RO },
313320 { DRDATAD (IN9COUNT , in9_count , 4 ,
314321 "Count of IN(9) register" ), REG_RO },
315322 { DRDATAD (IN9MESSAGE , in9_message , 4 ,
@@ -396,6 +403,23 @@ static t_stat dsk_reset(DEVICE *dptr) {
396403 sim_map_resource (0x0A , 1 , RESOURCE_TYPE_IO , & dsk12 , "dsk12" , dptr -> flags & DEV_DIS );
397404 return SCPE_OK ;
398405}
406+
407+ static t_bool dsk_image_size_is_near (
408+ const int32 image_size , const int32 expected_size , const int32 delta )
409+ {
410+ return (expected_size - delta < image_size ) &&
411+ (image_size < expected_size + delta );
412+ }
413+
414+ static int32 dsk_boot_start_sector (const int32 image_size )
415+ {
416+ if (dsk_image_size_is_near (
417+ image_size , ALTAIR_DISK_SIZE , ALTAIR_DISK_DELTA ))
418+ return 0 ;
419+
420+ return 8 ;
421+ }
422+
399423/* dsk_attach - determine type of drive attached based on disk image size */
400424
401425static t_stat dsk_attach (UNIT * uptr , const char * cptr ) {
@@ -413,8 +437,10 @@ static t_stat dsk_attach(UNIT *uptr, const char *cptr) {
413437 tracks to 16, otherwise, 32 sectors per track. */
414438
415439 imageSize = sim_fsize (uptr -> fileref );
416- sectors_per_track [thisUnitIndex ] = (((MINI_DISK_SIZE - MINI_DISK_DELTA < imageSize ) &&
417- (imageSize < MINI_DISK_SIZE + MINI_DISK_DELTA )) ?
440+ current_image_size [thisUnitIndex ] = imageSize ;
441+ sectors_per_track [thisUnitIndex ] = (dsk_image_size_is_near (
442+ imageSize , MINI_DISK_SIZE ,
443+ MINI_DISK_DELTA ) ?
418444 MINI_DISK_SECT : DSK_SECT );
419445 return SCPE_OK ;
420446}
@@ -426,7 +452,8 @@ void install_ALTAIRbootROM(void) {
426452}
427453
428454/* The boot routine modifies the boot ROM in such a way that subsequently
429- the specified disk is used for boot purposes.
455+ the specified disk is used for boot purposes. For the standard boot ROM,
456+ the starting sector is chosen from the attached image size.
430457*/
431458static t_stat dsk_boot (int32 unitno , DEVICE * dptr ) {
432459 if (cpu_unit .flags & (UNIT_CPU_ALTAIRROM | UNIT_CPU_BANKED )) {
@@ -435,17 +462,25 @@ static t_stat dsk_boot(int32 unitno, DEVICE *dptr) {
435462 ALTAIR_ROM_LOW , TRUE) == SCPE_OK );
436463 ASSURE (result );
437464 } else {
438- /* check whether we are really modifying an LD A,<> instruction */
465+ if (bootrom_dsk [START_SECTOR_OFFSET - 1 ] == LDB_INSTRUCTION )
466+ bootrom_dsk [START_SECTOR_OFFSET ] =
467+ dsk_boot_start_sector (current_image_size [unitno ]);
468+ else {
469+ sim_printf ("Incorrect boot ROM first sector offset detected.\n" );
470+ return SCPE_IERR ;
471+ }
472+
473+ /* check whether we are really modifying an LD A,<> instruction */
439474 if ((bootrom_dsk [UNIT_NO_OFFSET_1 - 1 ] == LDA_INSTRUCTION ) &&
440475 (bootrom_dsk [UNIT_NO_OFFSET_2 - 1 ] == LDA_INSTRUCTION )) {
441- bootrom_dsk [UNIT_NO_OFFSET_1 ] = unitno & 0xff ; /* LD A,<unitno> */
442- bootrom_dsk [UNIT_NO_OFFSET_2 ] = 0x80 | (unitno & 0xff ); /* LD a,80h | <unitno> */
443- } else { /* Attempt to modify non LD A,<> instructions is refused. */
444- sim_printf ("Incorrect boot ROM offsets detected.\n" );
445- return SCPE_IERR ;
476+ bootrom_dsk [UNIT_NO_OFFSET_1 ] = unitno & 0xff ; /* LD A,<unitno> */
477+ bootrom_dsk [UNIT_NO_OFFSET_2 ] = 0x80 | (unitno & 0xff ); /* LD a,80h | <unitno> */
478+ } else { /* Attempt to modify non LD A,<> instructions is refused. */
479+ sim_printf ("Incorrect boot ROM unit number offset detected.\n" );
480+ return SCPE_IERR ;
481+ }
482+ install_ALTAIRbootROM (); /* install modified ROM */
446483 }
447- install_ALTAIRbootROM (); /* install modified ROM */
448- }
449484 }
450485 * ((int32 * ) sim_PC -> loc ) = ALTAIR_ROM_LOW ;
451486 return SCPE_OK ;
0 commit comments