/*------------------------------------------------------------------------------ ----------------- Copyright J.Hubert 2015 This file is part of demOS demOS is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. demOS 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with demOS. If not, see . ------------------------------------------------------------------------------------------------- */ #define SYSTEM_C #include "DEMOSDK\BASTYPES.H" #include "DEMOSDK\STANDARD.H" #include "DEMOSDK\SYSTEM.H" #include "DEMOSDK\HARDWARE.H" SYScore sys; u16 SYSbeginFrameNum = 0; #ifndef __TOS__ volatile u32 SYSvblcount; volatile u16 SYSvblLcount; static SYSthread SYSidleThread = NULL; void SYSswitchIdle(void) { if ( SYSidleThread != NULL ) { SYSidleThread(); } } u32 SYSreadVideoBase (void) { u8* a = HW_VIDEO_BASE_H; u32 val = (a[0] << 16) | (a[1] << 8) | a[2]; return val; } void SYSwriteVideoBase (u32 _val) { *HW_VIDEO_BASE_H = (u8)(_val >> 16); *HW_VIDEO_BASE_M = (u8)(_val >> 8); *HW_VIDEO_BASE_L = (u8) _val; } #endif ASMIMPORT u32 SYSOSVBL; /* this vector allow to re-root old vbl interrupt from DEMOS DK vbl (used in DEMOS_ALLOW_DEBUGGER mode only) */ void SYSvblinterrupt (void) PCSTUB; u32* SYSdetectEmu (void) PCSTUBRET; void* SYSgemdosSetMode (void* _adr) PCSTUBRET; #if !defined(DEMOS_OPTIMIZED) && !defined(DEMOS_USES_BOOTSECTOR) static void* SYSstdAlloc(void* _alloc, u32 _size) { IGNORE_PARAM(_alloc); return malloc(_size); } static void SYSstdFree(void* _alloc, void* _adr) { IGNORE_PARAM(_alloc); free(_adr); } #endif void SYScheckHWRequirements (void) { # ifdef __TOS__ bool failed = false; /* Check computer is a STe */ if ( (*HW_VECTOR_INIT_PC) != 0xE00030UL ) { failed = true; } /* Check you have two drives */ if ( sys.has2Drives == false ) { failed = true; } if ( failed ) { u8* frameBuffer = (u8*) SYSreadVideoBase(); SYSvsync; STDcpuSetSR(0x2700); *HW_VIDEO_MODE = HW_VIDEO_MODE_4P; STDmset(frameBuffer, 0, 32000); STDmset (&HW_COLOR_LUT[1], 0xFFFFFFFFUL, 30); SYSfastPrint ("Hardware requirements:" , frameBuffer , 160, 8, (u32) sys.fontChars); SYSfastPrint ("STe - at least 1mb - 2 drives", &frameBuffer[160 * 8], 160, 8, (u32) sys.fontChars); while(1) { (*HW_COLOR_LUT) = 0x300; (*HW_COLOR_LUT) = 0x400; } } # endif } void SYSinit(SYSinitParam* _param) { # ifdef DEMOS_USES_BOOTSECTOR u32* emudetect = (u32*) 0x600; # else u32* emudetect = SYSdetectEmu(); # endif if (( emudetect[0] == 0x53544565UL ) && ( emudetect[1] == 0x6d456e67UL )) { sys.emulator = SYSemulator_STEEM; } else if (( emudetect[0] == 0x456D753FUL ) && ( emudetect[1] == 0x456D753FUL )) { sys.emulator = SYSemulator_PACIFIST; } else if ( emudetect[0] == 0x54426f78UL ) { sys.emulator = SYSemulator_TOSBOX; } else { sys.emulator = SYSemulator_NOTDETECTED; } sys.has2Drives = *OS_NFLOPS >= 2; sys.bakUSP = STDgetUSP(); ASSERT(_param->adr != NULL); ASSERT(_param->coreAdr != NULL); RINGallocatorInit ( &sys.mem , _param->adr , _param->size ); RINGallocatorInit ( &sys.coremem, _param->coreAdr, _param->coreSize ); sys.allocatorMem.alloc = (MEMallocFunc) RINGallocatorAlloc; sys.allocatorMem.free = (MEMfreeFunc) RINGallocatorFree; sys.allocatorMem.allocator = &sys.mem; sys.allocatorCoreMem.alloc = (MEMallocFunc) RINGallocatorAlloc; sys.allocatorCoreMem.free = (MEMfreeFunc) RINGallocatorFree; sys.allocatorCoreMem.allocator = &sys.coremem; # if !defined(DEMOS_OPTIMIZED) && !defined(DEMOS_USES_BOOTSECTOR) sys.allocatorStandard.alloc = SYSstdAlloc; sys.allocatorStandard.free = SYSstdFree; sys.allocatorStandard.allocator = NULL; # endif sys.bakvideoMode = *HW_VIDEO_MODE; sys.bakvbl = *HW_VECTOR_VBL; sys.bakdma = *HW_VECTOR_DMA; sys.bakvideoAdr[0] = *HW_VIDEO_BASE_H; sys.bakvideoAdr[1] = *HW_VIDEO_BASE_M; sys.bakvideoAdr[2] = *HW_VIDEO_BASE_L; sys.bakmfpInterruptEnableA = *HW_MFP_INTERRUPT_ENABLE_A; sys.bakmfpInterruptMaskA = *HW_MFP_INTERRUPT_MASK_A; sys.bakmfpInterruptEnableB = *HW_MFP_INTERRUPT_ENABLE_B; sys.bakmfpInterruptMaskB = *HW_MFP_INTERRUPT_MASK_B; # ifndef __TOS__ { u32 adr = (u32) RINGallocatorAlloc ( &sys.coremem, 32000 ); *HW_VIDEO_BASE_H = (u8) (adr >> 16); *HW_VIDEO_BASE_M = (u8) (adr >> 8); *HW_VIDEO_BASE_L = (u8) adr; sys.memoryMapHigh = ((u32)_param->adr) & 0xFF000000; } # endif STDcpuSetSR(0x2700); # ifdef DEMOS_ALLOW_DEBUGGER SYSOSVBL = sys.bakvbl; # else *HW_MFP_INTERRUPT_ENABLE_A = 0; *HW_MFP_INTERRUPT_ENABLE_B = 0; /* SYS_tune(); */ # endif *HW_MICROWIRE_MASK = 0x7FF; *HW_VECTOR_VBL = (u32) SYSvblinterrupt; # ifndef DEMOS_LOAD_FROMHD sys.bakmfpVectorBase = *HW_MFP_VECTOR_BASE; *OS_FLOPVBL = 1; *HW_MFP_INTERRUPT_ENABLE_B |= 0x80; *HW_MFP_INTERRUPT_MASK_B |= 0x80; *HW_MFP_VECTOR_BASE &= ~0x8; # endif *HW_MFP_INTERRUPT_MASK_A |= 0x1; /* enable Timer B mask */ sys.lastKey = 0; if (_param->idleThread != NULL) { sys.idleThreadStackBase = (u8*) RINGallocatorAlloc ( &sys.coremem, _param->idleThreadStackSize ); ASSERT(sys.idleThreadStackBase != NULL); # ifdef __TOS__ if ( SYSsetIdlethread (sys.idleThreadStackBase, sys.idleThreadStackBase + _param->idleThreadStackSize) ) { _param->idleThread (); ASSERT(0); /* you should not return from this function */ } # else SYSidleThread = _param->idleThread; # endif } } void SYS_shutdown(void) { *HW_VIDEO_BASE_H = sys.bakvideoAdr[0]; *HW_VIDEO_BASE_M = sys.bakvideoAdr[1]; *HW_VIDEO_BASE_L = sys.bakvideoAdr[2]; *HW_VIDEO_MODE = sys.bakvideoMode; STDcpuSetSR(0x2700); *HW_VECTOR_VBL = sys.bakvbl; *HW_VECTOR_DMA = sys.bakdma; STDcpuSetSR(0x2300); *HW_MFP_INTERRUPT_ENABLE_A = sys.bakmfpInterruptEnableA; *HW_MFP_INTERRUPT_MASK_A = sys.bakmfpInterruptMaskA; # ifndef DEMOS_LOAD_FROMHD *HW_MFP_INTERRUPT_ENABLE_B = sys.bakmfpInterruptEnableB; *HW_MFP_INTERRUPT_MASK_B = sys.bakmfpInterruptMaskB; *HW_MFP_VECTOR_BASE = sys.bakmfpVectorBase; *OS_FLOPVBL = 0; # endif STDsetUSP (sys.bakUSP); } u8 SYSgetKb(void) { sys.lastKey = *HW_KEYBOARD_DATA; return sys.lastKey; } #ifdef DEMOS_DEBUG u16 SYStraceFPS (void* _image, u16 _pitch, u16 _planePitch, u16 _y) { char temp[2]; temp[0] = SYSvblLcount - SYSbeginFrameNum + '1'; /* frame rate */ temp[1] = 0; SYSdebugPrint ( _image, _pitch, _planePitch, 39, _y, temp); return 12; } static u16 SYS_traceRingAlloc (void* _image, u16 _pitch, u16 _planePitch, u16 _y, RINGallocator* _allocator) { { static char line[] = "buf = end = size= "; STDuxtoa(&line[5] , (u32) _allocator->buffer , 6); STDuxtoa(&line[17], (u32) _allocator->bufferEnd, 6); STDuxtoa(&line[29], _allocator->size , 6); SYSdebugPrint ( _image, _pitch, _planePitch, 0, _y, line); } { static char line[] = "head= tail= last= "; STDuxtoa(&line[5] , (u32)_allocator->head , 6); STDuxtoa(&line[17], (u32)_allocator->tail , 6); STDuxtoa(&line[29], (u32)_allocator->last , 6); SYSdebugPrint ( _image, _pitch, _planePitch, 0, _y + 8, line); } return 20; } u16 SYStraceAllocators (void* _image, u16 _pitch, u16 _planePitch, u16 _y) { u16 h; h = SYS_traceRingAlloc (_image, _pitch, _planePitch, _y , &sys.coremem); h += SYS_traceRingAlloc (_image, _pitch, _planePitch, _y + h, &sys.mem); return h; } u16 SYStraceHW (void* _image, u16 _pitch, u16 _planePitch, u16 _y) { char line[] = "vmod= | key= emul= vbl= | "; STDuxtoa (&line[5] , *HW_VIDEO_MODE, 1); STDuxtoa (&line[7] , *HW_VIDEO_SYNC == HW_VIDEO_SYNC_50HZ ? 0x50 : 0x60, 2); STDuxtoa (&line[14], *HW_KEYBOARD_DATA , 2); STDuxtoa (&line[22], sys.emulator, 1); STDuxtoa (&line[28], SYSvblLcount, 4); STDuxtoa (&line[33], SYSbeginFrameNum, 4); SYSdebugPrint ( _image, _pitch, _planePitch, 0, _y, line); return 12; } #endif