/*------------------------------------------------------------------------------ ----------------- 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 . ------------------------------------------------------------------------------------------------- */ /*! @brief @ref SYS @file */ /*! @defgroup SYS Implements DemOS core system services.
System provides:
- interrupt backup / setup / restore system
- standardized VBL routine
- 2 ring buffers:
- one for core system (never freed)
- another for transient demo screens data
- a bi-threaded system, mixed between cooperative (main => idle thread) and preemptive (idle thread => main)
- one main thread: task executed here should be sliced by frame / synchronized with VBL
At the end of main thread, main loop yield to idle thread background task with a call to SYSswitchIdle
- idle thread: executes a background task not synchronized with the VBL. The task is restored in its last state then it is interrupted by VBL rescheduling the main thread
- some simple synchronization primitives
*/ #ifndef SYSTEM_H #define SYSTEM_H #include "DEMOSDK\BASTYPES.H" #include "DEMOSDK\ALLOC.H" ENUM(SYSemulator) { SYSemulator_NOTDETECTED, SYSemulator_STEEM, SYSemulator_TOSBOX, SYSemulator_PACIFIST }; STRUCT(SYScore) { RINGallocator coremem; RINGallocator mem; void* bakGemdos32; void* bakUSP; u8 bakvideoMode; u8 bakmfpInterruptEnableA; u8 bakmfpInterruptMaskA; u8 bakmfpInterruptEnableB; u8 bakmfpInterruptMaskB; u8 bakmfpVectorBase; u32 bakvbl; u32 bakdma; u8 bakvideoAdr[3]; bool has2Drives; u8 lastKey; SYSemulator emulator; u8* idleThreadStackBase; u8* font; u16 fontChars[256]; MEMallocator allocatorCoreMem; MEMallocator allocatorMem; # if !defined(DEMOS_OPTIMIZED) && !defined(DEMOS_USES_BOOTSECTOR) MEMallocator allocatorStandard; # endif # ifndef __TOS__ u32 memoryMapHigh; # endif }; typedef void (*SYSthread)(void); STRUCT(SYSinitParam) { void* coreAdr; u32 coreSize; void* adr; u32 size; SYSthread idleThread; u16 idleThreadStackSize; }; #ifndef SYSTEM_C extern SYScore sys; extern u16 SYSbeginFrameNum; #endif void SYSinit (SYSinitParam* _param); void SYS_shutdown (void); void SYSvsync (void); void SYScheckHWRequirements (void); extern volatile u32 SYSvblcount; extern volatile u16 SYSvblLcount; #ifdef __TOS__ # define SYSvsync { u16 currentvblcount = SYSvblLcount; while (SYSvblLcount == currentvblcount); } # define SYSmemoryHighMap 0 #else # define SYSvsync # define SYSmemoryHighMap sys.memoryMapHigh #endif void SYSswitchIdle(void); bool SYSsetIdlethread(void* _stacklow, void*_stackhigh); void SYStune(void); u32 SYSreadVideoBase (void); void SYSwriteVideoBase (u32 _val); #define SYS_kbhit (sys.lastKey != *HW_KEYBOARD_DATA) u8 SYSgetKb(void); void SYSfastPrint(char* _s, void* _screenprintadr, u16 _screenPitch, u16 _bitplanPitch, u32 _fontadr); #define SYS_1P_BITSHIFT 1 #define SYS_2P_BITSHIFT 2 #define SYS_4P_BITSHIFT 3 #ifdef DEMOS_DEBUG u16 SYStraceFPS (void* _image, u16 _pitch, u16 _planePitch, u16 _y); u16 SYStraceAllocators (void* _image, u16 _pitch, u16 _planePitch, u16 _y); u16 SYStraceHW (void* _image, u16 _pitch, u16 _planePitch, u16 _y); void SYSdebugPrint (void* _screen, u16 _screenPitch, u16 _bitplanPitchShift, u16 _col, u16 _y, char* _s); #else # define SYSdebugPrint(_screen, _screenPitch, _bitplanPitchShift, _col, _y, _s) #endif typedef s8 SYSlock; #define SYSlockInit(_lock) { _lock = 0; } bool SYSlockMain (SYSlock* _lock); /* when called from main thread => you should manage retry if locked (non blocking strategy) */ void SYSlockIdle (SYSlock* _lock); /* when called from idle thread, it will spin till it is unlocked by main thread (blocking strategy) */ void* SYSgemdosSetMode (void* _adr); void SYSreset (void); #endif