/** * Read from RTC/NVRAM data register ($ff8963) */ void NvRam_Data_ReadByte(void) { Uint8 value = 0; if (nvram_index == NVRAM_SECONDS || nvram_index == NVRAM_MINUTES || nvram_index == NVRAM_HOURS || (nvram_index >=NVRAM_DAY && nvram_index <=NVRAM_YEAR) ) { /* access to RTC? - then read host clock and return its values */ time_t tim = time(NULL); struct tm *curtim = localtime(&tim); /* current time */ switch(nvram_index) { case NVRAM_SECONDS: value = curtim->tm_sec; break; case NVRAM_MINUTES: value = curtim->tm_min; break; case NVRAM_HOURS: value = curtim->tm_hour; break; case NVRAM_DAY: value = curtim->tm_mday; break; case NVRAM_MONTH: value = curtim->tm_mon+1; break; case NVRAM_YEAR: value = curtim->tm_year - 68; break; } } else if (nvram_index == 10) { static bool rtc_uip = true; value = rtc_uip ? 0x80 : 0; rtc_uip = !rtc_uip; } else if (nvram_index == 13) { value = 0x80; // Valid RAM and Time bit } else if (nvram_index < 14) { Log_Printf(LOG_DEBUG, "Read from unsupported RTC/NVRAM register 0x%x.\n", nvram_index); value = nvram[nvram_index]; } else { value = nvram[nvram_index]; } LOG_TRACE(TRACE_NVRAM, "NVRAM: read data at %d = %d ($%02x)\n", nvram_index, value, value); IoMem_WriteByte(0xff8963, value); }
/** * Set default memory configuration, connected floppies, memory size and * clear the ST-RAM area. * As TOS checks hardware for memory size + connected devices on boot-up * we set these values ourselves and fill in the magic numbers so TOS * skips these tests. */ void STMemory_SetDefaultConfig(void) { int i; int screensize, limit; int memtop, phystop; Uint8 nMemControllerByte; Uint8 nFalcSysCntrl; static const int MemControllerTable[] = { 0x01, /* 512 KiB */ 0x05, /* 1 MiB */ 0x02, /* 2 MiB */ 0x06, /* 2.5 MiB */ 0x0A /* 4 MiB */ }; if (bRamTosImage) { /* Clear ST-RAM, excluding the RAM TOS image */ STMemory_Clear(0x00000000, TosAddress); STMemory_Clear(TosAddress+TosSize, STRamEnd); } else { /* Clear whole ST-RAM */ STMemory_Clear(0x00000000, STRamEnd); } /* Mirror ROM boot vectors */ STMemory_WriteLong(0x00, STMemory_ReadLong(TosAddress)); STMemory_WriteLong(0x04, STMemory_ReadLong(TosAddress+4)); /* Fill in magic numbers to bypass TOS' memory tests for faster boot or * if VDI resolution is enabled or if more than 4 MB of ram are used * or if TT RAM added in Falcon mode. * (for highest compatibility, those tests should not be bypassed in * the common STF/STE cases as some programs like "Yolanda" rely on * the RAM content after those tests) */ if ( ConfigureParams.System.bFastBoot || bUseVDIRes || ( ConfigureParams.Memory.nMemorySize > 4 && !bIsEmuTOS ) || ( ( ConfigureParams.System.nMachineType == MACHINE_FALCON ) && TTmemory ) ) { /* Write magic values to sysvars to signal valid config */ STMemory_WriteLong(0x420, 0x752019f3); /* memvalid */ STMemory_WriteLong(0x43a, 0x237698aa); /* memval2 */ STMemory_WriteLong(0x51a, 0x5555aaaa); /* memval3 */ /* If ST RAM detection is bypassed, we must also force TT RAM config if enabled */ if ( TTmemory ) STMemory_WriteLong ( 0x5a4 , 0x01000000 + TTmem_size ); /* ramtop */ else STMemory_WriteLong ( 0x5a4 , 0 ); /* ramtop */ STMemory_WriteLong ( 0x5a8 , 0x1357bd13 ); /* ramvalid */ /* On Falcon, set bit6=1 at $ff8007 to simulate a warm start */ /* (else memory detection is not skipped after a cold start/reset) */ if ( ConfigureParams.System.nMachineType == MACHINE_FALCON ) STMemory_WriteByte ( 0xff8007, IoMem_ReadByte(0xff8007) | 0x40 ); /* On TT, set bit0=1 at $ff8e09 to simulate a warm start */ /* (else memory detection is not skipped after a cold start/reset) */ if ( ConfigureParams.System.nMachineType == MACHINE_TT ) STMemory_WriteByte ( 0xff8e09, IoMem_ReadByte(0xff8e09) | 0x01 ); } /* Set memory size, adjust for extra VDI screens if needed. */ screensize = VDIWidth * VDIHeight / 8 * VDIPlanes; /* Use 32 kiB in normal screen mode or when the screen size is smaller than 32 kiB */ if (!bUseVDIRes || screensize < 0x8000) screensize = 0x8000; /* mem top - upper end of user memory (right before the screen memory) * memtop / phystop must be dividable by 512 or TOS crashes */ memtop = (STRamEnd - screensize) & 0xfffffe00; /* phys top - 32k gap causes least issues with apps & TOS * as that's the largest _common_ screen size. EmuTOS behavior * depends on machine type. * * TODO: what to do about _native_ TT & Videl resolutions * which size is >32k? Should memtop be adapted also for * those? */ switch (ConfigureParams.System.nMachineType) { case MACHINE_FALCON: /* TOS v4 doesn't work with VDI mode (yet), and * EmuTOS works with correct gap, so use that */ phystop = STRamEnd; break; case MACHINE_TT: /* For correct TOS v3 memory detection, phystop should be * at the end of memory, not at memtop + 32k. * * However: * - TOS v3 crashes/hangs if phystop-memtop gap is larger * than largest real HW screen size (150k) * - NVDI hangs if gap is larger than 32k in any other than * monochrome mode */ if (VDIPlanes == 1) limit = 1280*960/8; else limit = 0x8000; if (screensize > limit) { phystop = memtop + limit; fprintf(stderr, "WARNING: too large VDI mode for TOS v3 memory detection to work correctly!\n"); } else phystop = STRamEnd; break; default: phystop = memtop + 0x8000; } STMemory_WriteLong(0x436, memtop); STMemory_WriteLong(0x42e, phystop); if (bUseVDIRes) fprintf(stderr, "VDI mode memtop: 0x%x, phystop: 0x%x (screensize: %d kB, memtop->phystop: %d kB)\n", memtop, phystop, (screensize+511) / 1024, (phystop-memtop+511) / 1024); /* Set memory controller byte according to different memory sizes */ /* Setting per bank: %00=128k %01=512k %10=2Mb %11=reserved. - e.g. %1010 means 4Mb */ if (ConfigureParams.Memory.nMemorySize <= 4) nMemControllerByte = MemControllerTable[ConfigureParams.Memory.nMemorySize]; else nMemControllerByte = 0x0f; STMemory_WriteByte(0x424, nMemControllerByte); IoMem_WriteByte(0xff8001, nMemControllerByte); if (ConfigureParams.System.nMachineType == MACHINE_FALCON) { /* Set the Falcon memory and monitor configuration register: $ffff8006.b [R] 76543210 Monitor-memory |||||||| |||||||+- RAM Wait Status ||||||| 0 = 1 Wait (default) ||||||| 1 = 0 Wait ||||||+-- Video Bus size ??? |||||| 0 = 16 Bit |||||| 1 = 32 Bit (default) ||||++--- ROM Wait Status |||| 00 = Reserved |||| 01 = 2 Wait (default) |||| 10 = 1 Wait |||| 11 = 0 Wait ||++----- Falcon Memory || 00 = 1 MB || 01 = 4 MB || 10 = 14 MB || 11 = no boot ! ++------- Monitor-Typ 00 - Monochrome (SM124) 01 - Color (SC1224) 10 - VGA Color 11 - Television Bit 1 seems not to be well documented. It's used by TOS at bootup to compute the memory size. After some tests, I get the following RAM values (Bits 5, 4, 1 are involved) : 00 = 512 Ko 20 = 8192 Ko 02 = 1024 Ko 22 = 14366 Ko 10 = 2048 Ko 30 = Illegal 12 = 4096 Ko 32 = Illegal I use these values for Hatari's emulation. I also set the bit 3 and 2 at value 01 are mentioned in the register description. */ if (ConfigureParams.Memory.nMemorySize == 14) /* 14 Meg */ nFalcSysCntrl = 0x26; else if (ConfigureParams.Memory.nMemorySize == 8) /* 8 Meg */ nFalcSysCntrl = 0x24; else if (ConfigureParams.Memory.nMemorySize == 4) /* 4 Meg */ nFalcSysCntrl = 0x16; else if (ConfigureParams.Memory.nMemorySize == 2) /* 2 Meg */ nFalcSysCntrl = 0x14; else if (ConfigureParams.Memory.nMemorySize == 1) /* 1 Meg */ nFalcSysCntrl = 0x06; else nFalcSysCntrl = 0x04; /* 512 Ko */ switch(ConfigureParams.Screen.nMonitorType) { case MONITOR_TYPE_TV: nFalcSysCntrl |= FALCON_MONITOR_TV; break; case MONITOR_TYPE_VGA: nFalcSysCntrl |= FALCON_MONITOR_VGA; break; case MONITOR_TYPE_RGB: nFalcSysCntrl |= FALCON_MONITOR_RGB; break; case MONITOR_TYPE_MONO: nFalcSysCntrl |= FALCON_MONITOR_MONO; break; } STMemory_WriteByte(0xff8006, nFalcSysCntrl); } /* Set TOS floppies */ STMemory_WriteWord(0x446, nBootDrive); /* Boot up on A(0) or C(2) */ /* Create connected drives mask (only for harddrives, don't change floppy drive detected by TOS) */ ConnectedDriveMask = STMemory_ReadLong(0x4c2); // Get initial drive mask (see what TOS thinks) if (GEMDOS_EMU_ON) { for (i = 0; i < MAX_HARDDRIVES; i++) { if (emudrives[i] != NULL) // Is this GEMDOS drive enabled? ConnectedDriveMask |= (1 << emudrives[i]->drive_number); } } /* Set connected drives system variable. * NOTE: some TOS images overwrite this value, see 'OpCode_SysInit', too */ STMemory_WriteLong(0x4c2, ConnectedDriveMask); }
/** * Read from RTC/NVRAM offset selection register ($ff8961) */ void NvRam_Select_ReadByte(void) { IoMem_WriteByte(0xff8961, nvram_index); }
/** * Set default memory configuration, connected floppies, memory size and * clear the ST-RAM area. * As TOS checks hardware for memory size + connected devices on boot-up * we set these values ourselves and fill in the magic numbers so TOS * skips these tests. */ void STMemory_SetDefaultConfig(void) { int i; int screensize; int memtop; Uint8 nMemControllerByte; Uint8 nFalcSysCntrl; static const int MemControllerTable[] = { 0x01, /* 512 KiB */ 0x05, /* 1 MiB */ 0x02, /* 2 MiB */ 0x06, /* 2.5 MiB */ 0x0A /* 4 MiB */ }; if (bRamTosImage) { /* Clear ST-RAM, excluding the RAM TOS image */ STMemory_Clear(0x00000000, TosAddress); STMemory_Clear(TosAddress+TosSize, STRamEnd); } else { /* Clear whole ST-RAM */ STMemory_Clear(0x00000000, STRamEnd); } /* Mirror ROM boot vectors */ STMemory_WriteLong(0x00, STMemory_ReadLong(TosAddress)); STMemory_WriteLong(0x04, STMemory_ReadLong(TosAddress+4)); /* Fill in magic numbers to bypass TOS' memory tests for faster boot or * if VDI resolution is enabled or if more than 4 MB of ram are used. * (for highest compatibility, those tests should not be bypassed in * the common STF/STE cases as some programs like "Yolanda" rely on * the RAM content after those tests) */ if (ConfigureParams.System.bFastBoot || bUseVDIRes || (ConfigureParams.Memory.nMemorySize > 4 && !bIsEmuTOS)) { /* Write magic values to sysvars to signal valid config */ STMemory_WriteLong(0x420, 0x752019f3); /* memvalid */ STMemory_WriteLong(0x43a, 0x237698aa); /* memval2 */ STMemory_WriteLong(0x51a, 0x5555aaaa); /* memval3 */ } /* Set memory size, adjust for extra VDI screens if needed. * Note: TOS seems to set phys_top-0x8000 as the screen base * address - so we have to move phys_top down in VDI resolution * mode, although there is more "physical" ST RAM available. */ screensize = VDIWidth * VDIHeight / 8 * VDIPlanes; /* Use 32 kiB in normal screen mode or when the screen size is smaller than 32 kiB */ if (!bUseVDIRes || screensize < 0x8000) screensize = 0x8000; /* mem top - upper end of user memory (right before the screen memory). * Note: memtop / phystop must be dividable by 512, or TOS crashes */ memtop = (STRamEnd - screensize) & 0xfffffe00; STMemory_WriteLong(0x436, memtop); /* phys top - This must be memtop + 0x8000 to make TOS happy */ STMemory_WriteLong(0x42e, memtop+0x8000); /* Set memory controller byte according to different memory sizes */ /* Setting per bank: %00=128k %01=512k %10=2Mb %11=reserved. - e.g. %1010 means 4Mb */ if (ConfigureParams.Memory.nMemorySize <= 4) nMemControllerByte = MemControllerTable[ConfigureParams.Memory.nMemorySize]; else nMemControllerByte = 0x0f; STMemory_WriteByte(0x424, nMemControllerByte); IoMem_WriteByte(0xff8001, nMemControllerByte); if (ConfigureParams.System.nMachineType == MACHINE_FALCON) { /* Set the Falcon memory and monitor configuration register: $ffff8006.b [R] 76543210 Monitor-memory |||||||| |||||||+- RAM Wait Status ||||||| 0 = 1 Wait (default) ||||||| 1 = 0 Wait ||||||+-- Video Bus size ??? |||||| 0 = 16 Bit |||||| 1 = 32 Bit (default) ||||++--- ROM Wait Status |||| 00 = Reserved |||| 01 = 2 Wait (default) |||| 10 = 1 Wait |||| 11 = 0 Wait ||++----- Falcon Memory || 00 = 1 MB || 01 = 4 MB || 10 = 14 MB || 11 = no boot ! ++------- Monitor-Typ 00 - Monochrome (SM124) 01 - Color (SC1224) 10 - VGA Color 11 - Television Bit 1 seems not to be well documented. It's used by TOS at bootup to compute the memory size. After some tests, I get the following RAM values (Bits 5, 4, 1 are involved) : 00 = 512 Ko 20 = 8192 Ko 02 = 1024 Ko 22 = 14366 Ko 10 = 2048 Ko 30 = Illegal 12 = 4096 Ko 32 = Illegal I use these values for Hatari's emulation. I also set the bit 3 and 2 at value 01 are mentioned in the register description. */ if (ConfigureParams.Memory.nMemorySize == 14) /* 14 Meg */ nFalcSysCntrl = 0x26; else if (ConfigureParams.Memory.nMemorySize == 8) /* 8 Meg */ nFalcSysCntrl = 0x24; else if (ConfigureParams.Memory.nMemorySize == 4) /* 4 Meg */ nFalcSysCntrl = 0x16; else if (ConfigureParams.Memory.nMemorySize == 2) /* 2 Meg */ nFalcSysCntrl = 0x14; else if (ConfigureParams.Memory.nMemorySize == 1) /* 1 Meg */ nFalcSysCntrl = 0x06; else nFalcSysCntrl = 0x04; /* 512 Ko */ switch(ConfigureParams.Screen.nMonitorType) { case MONITOR_TYPE_TV: nFalcSysCntrl |= FALCON_MONITOR_TV; break; case MONITOR_TYPE_VGA: nFalcSysCntrl |= FALCON_MONITOR_VGA; break; case MONITOR_TYPE_RGB: nFalcSysCntrl |= FALCON_MONITOR_RGB; break; case MONITOR_TYPE_MONO: nFalcSysCntrl |= FALCON_MONITOR_MONO; break; } STMemory_WriteByte(0xff8006, nFalcSysCntrl); } /* Set TOS floppies */ STMemory_WriteWord(0x446, nBootDrive); /* Boot up on A(0) or C(2) */ /* Create connected drives mask: */ ConnectedDriveMask = STMemory_ReadLong(0x4c2); // Get initial drive mask (see what TOS thinks) ConnectedDriveMask |= 0x03; // Always use A: and B: if (GEMDOS_EMU_ON) { for (i = 0; i < MAX_HARDDRIVES; i++) { if (emudrives[i] != NULL) // Is this GEMDOS drive enabled? ConnectedDriveMask |= (1 << emudrives[i]->drive_number); } } /* Set connected drives system variable. * NOTE: some TOS images overwrite this value, see 'OpCode_SysInit', too */ STMemory_WriteLong(0x4c2, ConnectedDriveMask); }