TempleOSTS_140317.ISO

This commit is contained in:
Terry A. Davis authored and minexew committed 2018-09-08 21:46:02 +02:00
1 parent 2d2a65d572
commit 7ef616a20e
1416 files changed
+223873 -53917

No files matched your search

+2
View File
@@ -0,0 +1,2 @@
#exe {ImportHashTable(adam_task->hash_table);};
+11
View File
@@ -0,0 +1,11 @@
//This is executed by Adam at boot.
//See $LK,"Adam1 Start-up",A="FF:::/Kernel/KEnd.CPP,Adam1:2"$
extern I8i OptEqu(I64i num,I8i val);
OptEqu(0,0); //(0,0)=EchoOff (0,1)=EchoOn
#include "/Kernel/Adam1a.HPP"
#include "/Compiler/CmpDefs.HPP"
#include "/Kernel/Adam1b.HPP"
#include "/Kernel/Adam1c.HPP"
#include "/Compiler/Cmp.HPP"
Cd("/Adam");;
#include "Adam2"
+3626
View File
File diff suppressed because it is too large. Load diff
+288
View File
@@ -0,0 +1,288 @@
/*
In this file, syms defined Kernel assembly
files are given C+ definitions. This file
is included when you compile the kernel, after
the assembly files have been assembled, making
the HolyC definitions available for the HolyC Kernel
files. It is also included as part of booting.
The assembly global labels are stored as HTT_EXPORT_SYS_SYM
entries in the hash table. These symols are placed
into the Kernel binary module and added to the
sym hash table at boot before this file
gets #included during boot.
See
$LK,"Adam1b",A="FF:::/Kernel/Kernel.PRJ,Adam1b"$ for where it is included during compiling the kernel.
$LK,"Adam1b",A="FF:::/Kernel/Adam1.CPP,Adam1b"$ for where it is included during boots.
$LK,"LoadKernel",A="FF:::/Kernel/KEnd.CPP,LoadKernel"$ for where the Kernel syms are added to the hash tables.
*/
#help_index "Misc;Messages"
public _extern SYS_FOCUS_TASK CTask *sys_focus_task;
#help_index "Graphics/Screen"
//This is the INT 0x10 mode number.
public _extern SYS_BIOS_GR_MODE U16 bios_gr_mode;
#help_index "PCI"
public _extern SYS_PCI_BUSSES U16 sys_pci_busses;
#help_index "Misc"
public _extern SYS_CTRL_ALT_FLAGS I64 sys_ctrl_alt_flags[1];
public _extern SYS_COMPILE_TIME CDate sys_compile_time;
#help_index "Boot"
_extern SYS_BOOT_BASE U32 sys_boot_base;
_extern SYS_BOOT_CODE U32 sys_boot_code;
_extern SYS_RUN_LEVEL U32 sys_run_level;
_extern SYS_BOOT_PATCH_TABLE_BASE U32 sys_boot_patch_table_base;
#help_index "Misc/Progress Bars"
public _extern SYS_PROGRESSES CProgress sys_progresses[NUM_PROGRESS_BARS];
public _extern SYS_PROGRESS1 I64 progress1;
public _extern SYS_PROGRESS1_MAX I64 progress1_max;
public _extern SYS_PROGRESS1_DESC U8 progress1_desc[PROGRESS_DESC_LEN+1];
public _extern SYS_PROGRESS2 I64 progress2;
public _extern SYS_PROGRESS2_MAX I64 progress2_max;
public _extern SYS_PROGRESS2_DESC U8 progress2_desc[PROGRESS_DESC_LEN+1];
public _extern SYS_PROGRESS3 I64 progress3;
public _extern SYS_PROGRESS3_MAX I64 progress3_max;
public _extern SYS_PROGRESS3_DESC U8 progress3_desc[PROGRESS_DESC_LEN+1];
public _extern SYS_PROGRESS4 I64 progress4;
public _extern SYS_PROGRESS4_MAX I64 progress4_max;
public _extern SYS_PROGRESS4_DESC U8 progress4_desc[PROGRESS_DESC_LEN+1];
#help_index "Bit"
#help_file "::/Doc/Bit"
public _intern IC_BT Bool Bt(U8 *bit_field,I64 bit);
public _intern IC_BTS Bool Bts(U8 *bit_field,I64 bit);
public _intern IC_BTR Bool Btr(U8 *bit_field,I64 bit);
public _intern IC_BTC Bool Btc(U8 *bit_field,I64 bit);
public _extern _BEQU Bool BEqu(U8 *bit_field,I64 bit,Bool val);
//Locked for (for multitple CPU's)
public _intern IC_LBTS Bool LBts(U8 *bit_field,I64 bit);
public _intern IC_LBTR Bool LBtr(U8 *bit_field,I64 bit);
public _intern IC_LBTC Bool LBtc(U8 *bit_field,I64 bit);
public _extern _LBEQU Bool LBEqu(U8 *bit_field,I64 bit,Bool val);
//Scan I64 sized item fwd for first set bit, starting at lowest.
//Return -1 if not found.
public _intern IC_BSF I64 Bsf(I64 bit_field_val);
//Scan I64 sized item reverse for first set bit, starting at highest.
//Return -1 if not found.
public _intern IC_BSR I64 Bsr(I64 bit_field_val);
public _extern _BIT_FIELD_OR_U32 U0 BFieldOrU32(
U8 *bit_field,I64 bit,U32 pattern);
public _extern _BIT_FIELD_EXTRACT_U32 U32 BFieldExtU32(
U8 *bit_field,I64 bit,I64 size);
#help_index "Data Types/Circular Queue"
#help_file "::/Doc/Que"
public _intern IC_QUE_INIT U0 QueInit(CQue *root);
//Ins item into que after predicessor.
public _intern IC_QUE_INS U0 QueIns(CQue *entry,CQue *pred);
//Reversed insert into que. Ins
//item into que before successor.
public _intern IC_QUE_INS_REV U0 QueInsRev(CQue *entry,CQue *succ);
//Remove item from que.
public _intern IC_QUE_REM U0 QueRem(CQue *entry);
#help_index "Task"
public _intern IC_PREEMPT Bool Preempt(Bool val);
#help_index "I/O;Processor/IO Port"
public _intern IC_IN_U8 I64 InU8(I64 port);
public _intern IC_IN_U16 I64 InU16(I64 port);
public _intern IC_IN_U32 I64 InU32(I64 port);
public _intern IC_OUT_U8 U0 OutU8(I64 port, I64 val);
public _intern IC_OUT_U16 U0 OutU16(I64 port, I64 val);
public _intern IC_OUT_U32 U0 OutU32(I64 port, I64 val);
public _extern _REP_IN_U8 U0 RepInU8(U8 *buf,I64 cnt,I64 port);
public _extern _REP_IN_U16 U0 RepInU16(U8 *buf,I64 cnt,I64 port);
public _extern _REP_IN_U32 U0 RepInU32(U8 *buf,I64 cnt,I64 port);
public _extern _REP_OUT_U8 U0 RepOutU8(U8 *buf,I64 cnt,I64 port);
public _extern _REP_OUT_U16 U0 RepOutU16(U8 *buf,I64 cnt,I64 port);
public _extern _REP_OUT_U32 U0 RepOutU32(U8 *buf,I64 cnt,I64 port);
#help_index "Memory"
//Only goes fwd.
public _extern _MEMCPY U8 *MemCpy(U8 *dst,U8 *src,I64 cnt);
public _extern _MEMCMP I64 MemCmp(U8 *ptr1,U8 *ptr2,I64 cnt);
public _extern _MEMSET U8 *MemSet(U8 *dst,I64 val,I64 cnt);
public _extern _MEMSET U8 *MemSetU8(U8 *dst,I64 val,I64 U8cnt);
public _extern _MEMSET_U16 U16 *MemSetU16(U16 *dst,I64 val,I64 U16cnt);
public _extern _MEMSET_U32 U32 *MemSetU32(U32 *dst,I64 val,I64 U32cnt);
public _extern _MEMSET_U64 U64 *MemSetU64(U64 *dst,I64 val,I64 U64cnt);
public _extern SYS_CODE_BP CBlkPool *sys_code_bp;
public _extern SYS_DATA_BP CBlkPool *sys_data_bp;
public _extern SYS_HEAP_BASE U8 *sys_heap_base;
public _extern SYS_HEAP_LIMIT U8 *sys_heap_limit;
_extern SYS_HEAP_INIT_FLAG U8 sys_heap_init_flag;
_extern SYS_HEAP_INIT_VAL U8 sys_heap_init_val;
_extern SYS_MEM_INIT_FLAG U8 sys_mem_init_flag;
_extern SYS_MEM_INIT_VAL U8 sys_mem_init_val;
_extern SYS_VAR_INIT_FLAG U8 sys_var_init_flag;
_extern SYS_VAR_INIT_VAL U8 sys_var_init_val;
_extern SYS_HEAP_DBG_FLAG U8 sys_heap_dbg;
#help_index "Char/Conversion"
public _intern IC_TOUPPER I64 ToUpper(U8 ch);
#help_index "Char/Operations"
public _intern IC_STRLEN I64 StrLen(U8 *st);
#help_index "Processor"
public _extern _CPUID U0 CPUId(U32 rax,CRAXRBCRCXRDX *result);
public _intern IC_SET_RAX U0 SetRAX(I64 d);
public _intern IC_GET_RAX I64 GetRAX();
public _extern _SYS_HLT U0 SysHlt(); //Loops
public _intern IC_POP I64 Pop();
public _intern IC_PUSH U0 Push(I64 d);
public _intern IC_GET_RFLAGS I64 GetRFlags();
public _intern IC_CARRY I64 Carry();
public _intern IC_SET_RFLAGS U0 SetRFlags(I64 d);
public _intern IC_GET_RSP U8 *GetRSP();
public _intern IC_SET_RSP U0 SetRSP(U8 *d);
public _intern IC_GET_RBP U8 *GetRBP();
public _intern IC_SET_RBP U0 SetRBP(U8 *d);
public _extern SYS_CACHE_LINE_WIDTH I64 sys_cache_line_width;
_extern SYS_GDT CGDT sys_gdt;
public _extern _XCHG_U64 U64 XchgU64(U64 *dst,U64 d);
public _extern _XCHG_U32 U64 XchgU32(U32 *dst,U32 d);
public _extern _XCHG_U16 U64 XchgU16(U16 *dst,U16 d);
public _extern _XCHG_U8 U64 XchgU8 (U8 *dst,U8 d);
public _extern _LXCHG_U64 U64 LXchgU64(U64 *dst,U64 d);
public _extern _LXCHG_U32 U64 LXchgU32(U32 *dst,U32 d);
public _extern _LXCHG_U16 U64 LXchgU16(U16 *dst,U16 d);
public _extern _LXCHG_U8 U64 LXchgU8(U8 *dst,U8 d);
//Model Specific Reg
//See $LK,"MSRs",A="MN:IA32_EFER"$
public _extern _SET_MSR U0 SetMSR(I64 model_specific_reg,I64 val);
#help_index "Processor/Cache;Memory/Cache"
public _intern IC_INVLPG U0 InvlPg(U8 *a);
//Flush cache line.
public _intern IC_CLFLUSH U0 CLFlush(U8 *a);
#help_index "MultiCore"
#help_file "::/Doc/MultiCore"
public _extern SYS_MP_CNT I64 mp_cnt;
_extern SYS_MP_CNT_INITIAL I64 mp_cnt_initial; //only used during $LK,"MPStart",A="MN:MPStart"$
_extern SYS_MP_CNT_LOCK I64 mp_cnt_lock;
public _extern SYS_CPU_STRUCTS CCPU *cpu_structs;
_extern SYS_SEMAS CSema sys_semas[NUM_SYS_SEMAS];
#help_index "MultiCore;Processor"
//This points to the current $LK,"CCPU",A="MN:CCPU"$ structure.
//It returns the val in the GS segment reg.
public _intern IC_GS CCPU *Gs();
#help_index "Time/CPU Cycles"
public _intern IC_RDTSC I64 GetTSC(); //Time Stamp Counter
#help_index "Time/HPET"
public _intern IC_HPET I64 HPET();
#help_index "Time/Jiffies"
#help_file "::/Doc/TimeJiffy"
_extern SYS_TIMER I64 sys_timer;
public _extern SYS_JIFFIES I64 sys_jiffies;
#help_index "Math"
public _intern IC_TO_I64 I64 ToI64(F64 d); //This truncates
public _intern IC_TO_F64 F64 ToF64(I64 i);
public _intern IC_TO_BOOL Bool ToBool(I64 i);
public _intern IC_ABS_I64 I64 AbsI64(I64 i);
public _intern IC_SIGN_I64 I64 SignI64(I64 i);
public _intern IC_SQR_I64 I64 SqrI64(I64 i);
public _intern IC_SQR_U64 U64 SqrU64(U64 i);
public _intern IC_SWAP_U8 U0 SwapU8(U8 *n1,U8 *n2);
public _intern IC_SWAP_U16 U0 SwapU16(U16 *n1,U16 *n2);
public _intern IC_SWAP_U32 U0 SwapU32(U32 *n1,U32 *n2);
public _intern IC_SWAP_U64 U0 SwapU64(U64 *n1,U64 *n2);
public _intern IC_MIN_I64 I64 MinI64(I64 n1,I64 n2);
public _intern IC_MAX_I64 I64 MaxI64(I64 n1,I64 n2);
public _intern IC_MIN_U64 U64 MinU64(U64 n1,U64 n2);
public _intern IC_MAX_U64 U64 MaxU64(U64 n1,U64 n2);
public _intern IC_MOD_U64 U64 ModU64(U64 *q,U64 d);
public _intern IC_SQR F64 Sqr(F64 d);
public _intern IC_ABS F64 Abs(F64 d);
public _intern IC_SQRT F64 Sqrt(F64 d);
public _intern IC_SIN F64 Sin(F64 d);
public _intern IC_COS F64 Cos(F64 d);
public _intern IC_TAN F64 Tan(F64 d);
public _intern IC_ATAN F64 ATan(F64 d);
public _extern _CLAMP_I64 I64 ClampI64(I64 p,I64 lo,I64 hi);
public _extern _CLAMP_U64 U64 ClampU64(U64 p,U64 lo,U64 hi);
public _extern _SIGN F64 Sign(F64 d);
public _extern _ARG F64 Arg(F64 x,F64 y);
public _extern _ROUND F64 Round(F64 d);
public _extern _TRUNC F64 Trunc(F64 d);
public _extern _FLOOR F64 Floor(F64 d);
public _extern _CEIL F64 Ceil(F64 d);
public _extern _POW F64 Pow(F64 base,F64 power);
public _extern _POW10 F64 Pow10(F64 d);
public _extern _LOG2 F64 Log2(F64 d);
public _extern _LOG10 F64 Log10(F64 d);
public _extern _LN F64 Ln(F64 d);
public _extern _EXP F64 Exp(F64 d);
_extern _FLDCW U0 Fldcw(U16 w);
_extern _FCLEX U0 Fclex();
_extern _FSTCW U16 Fstcw();
_extern _FSTSW U16 Fstsw();
_extern _FXSAVE U0 Fxsave(CFPU *fpu_mmx);
_extern _FXRSTOR U0 Fxrstor(CFPU *fpu_mmx);
#help_index "Math/CD3;ODE/CD3"
#help_file "::/Doc/D3"
public _extern _D3_EQU CD3 *D3Equ(CD3 *dst,F64 x,F64 y,F64 z);
public _extern _D3_ZERO CD3 *D3Zero(CD3 *dst);
public _extern _D3_COPY CD3 *D3Copy(CD3 *dst,CD3 *src);
public _extern _D3_NORM F64 D3Norm(CD3 *d);
public _extern _D3_SQR_NORM F64 D3SqrNorm(CD3 *d);
public _extern _D3_ADD CD3 *D3Add(CD3 *d1,CD3 *d2,CD3 *sum);
public _extern _D3_SUB CD3 *D3Sub(CD3 *d1,CD3 *d2,CD3 *diff);
public _extern _D3_MUL CD3 *D3Mul(F64 c,CD3 *d,CD3 *prod);
public _extern _D3_DIV CD3 *D3Div(F64 c,CD3 *d,CD3 *quot);
public _extern _D3_ADD_EQU CD3 *D3AddEqu(CD3 *sum,CD3 *d);
public _extern _D3_SUB_EQU CD3 *D3SubEqu(CD3 *diff,CD3 *d);
public _extern _D3_MUL_EQU CD3 *D3MulEqu(CD3 *prod,F64 c);
public _extern _D3_DIV_EQU CD3 *D3DivEqu(CD3 *quot,F64 c);
public _extern _D3_DIST F64 D3Dist(CD3 *d1,CD3 *d2);
public _extern _D3_SQR_DIST F64 D3SqrDist(CD3 *d1,CD3 *d2);
//Dot Product
public _extern _D3_DOT F64 D3Dot(CD3 *d1,CD3 *d2);
//Cross Product
public _extern _D3_CROSS CD3 *D3Cross(CD3 *d1,CD3 *d2,CD3 *prod);
//Convert to unit vect
public _extern _D3_UNIT CD3 *D3Unit(CD3 *d);
#help_index "Task;Processor"
//This points to the current $LK,"CTask",A="MN:CTask"$ structure.
//It returns the val in the FS segment reg.
public _intern IC_FS CTask *Fs();
#help_index "Call"
public _extern _CALL I64 Call(U8 *s);
//fp_addr can have any fixed number of arguments.
public _extern _CALLIND I64 CallInd(/*argpop*/I64 (*fp_addr)(...),...);
//This is just an array of ptrs to funs.
//See $LK,"Extern Num Definitions",A="MN:EXT_NUM_ENTRIES"$
public _extern SYS_EXTERN_TABLE /*argpop*/ I64 (**ext)(...);
//Can have any fixed number of arguments.
public _extern _CALLEXTNUM I64 CallExtNum(I64 num,...);
//Search sym table for fun name and pass it args.
//Can have any fixed number of arguments.
public _extern _CALLEXTSTR I64 CallExtStr(/*argpop*/ U8 *name,...);
#help_index ""
+799
View File
@@ -0,0 +1,799 @@
#help_index "Time/Jiffies"
//18.33333*65536Hz (SYS_TIMER_FREQ)
public extern I64 SysTimerRead();
#help_index "Task"
extern CTask *sys_winmgr_task,*sys_task_being_screen_updated;
public extern CTask *adam_task;
public extern I64 sys_num_spawned_tasks;
extern U0 TaskFinishOffDying();
public _extern _YIELD U0 Yield();
_extern _TASK_CONTEXT_RESTORE U0 TaskContextRestore();
_extern _TASK_END_NOW U0 TaskEndNow();
#help_index "Task/Misc"
public extern U0 TSSBusy(I64 tr,Bool val=OFF);
public extern U0 OverRideSingleUserSwap();
public extern U0 WinDerivedValsUpdate(CTask *task=NULL);
public extern U0 TaskDerivedValsUpdate(CTask *task=NULL,Bool update_z_buf=TRUE);
extern U0 (*fp_update_ctrls)(CTask *task);
#help_index "Time/CPU Cycles"
#help_file "::/Doc/TimeCycles"
public extern I64 time_stamp_freq,time_stamp_kHz_freq;
public extern I64 TaskTotalTime();
//This is sampled once at boot time
public extern I64 time_stamp_freq_initial;
#help_index "Time/HPET"
#help_file "::/Doc/TimeHPET"
public extern I64 HPET_freq,HPET_initial,HPET_kHz_freq;
#help_index "Time/Seconds"
public extern F64 tS(); //From SysTimerFreq.
public extern Bool Blink(F64 Hz=2.5);
#help_index "Snd"
public extern U0 Snd(F64 freq);
public extern Bool Mute(Bool val);
public extern Bool IsMute();
public extern F64 snd_freq;
public extern U0 Beep(I64 freq=500,Bool busy=FALSE);
public extern Bool snd_record;
extern CSndData snd_record_root;
#help_index "Processor"
extern U8 *sys_fault_handlers_code;
extern I64 *sys_idt;
public extern U8 *IntEntryGet(I64 irq);
public extern U8 *IntEntrySet(I64 irq,U0 (*fp_new_handler)(),I64 type=IDTET_IRQ,I64 dpl=0);
extern CPCIDev sys_pci_dev_root;
extern CMemRange sys_mem32_dev_root;
#help_index "Task/Delay;Time/CPU Cycles"
extern I64 TimeStampFreqCal();
public extern U0 BusyWait(I64 æS); //Loosely timed
public extern U0 PortNop(); //On the order of 1uS
#help_index "Task/Delay;Time/Jiffies"
public extern U0 SleepUntil(I64 wake_jiffy);
public extern U0 Sleep(I64 mS);
#help_index "Task"
public extern Bool IsPreempt();
#help_index "Debugging"
#help_file "::/Doc/Dbg"
extern CTask *sys_dbg_focus_task;
extern U8 *sys_dbg_msg;
extern I64 sys_dbg_msg_num;
public extern Bool IsSysDbg();
public extern Bool SysDbg(Bool val);
public extern Bool ChkPtr(U8 *ptr);
public extern Bool ChkCodePtr(U8 *ptr);
public extern Bool ChkOnStk(U8 *ptr,CTask *task=NULL);
public extern I64 UnusedStk(CTask *task=NULL);
public extern U8 *Caller(I64 num=1);
public extern U8 *TaskCaller(CTask *task=NULL,I64 num=0,Bool saved_context=FALSE);
public extern Bool SingleUser(Bool val);
public extern Bool IsSingleUser();
#help_index "Debugging/Dump"
public extern U0 D(U8 *addr,I64 cnt=0x80,Bool show_offset=TRUE);
public extern U0 Dm(U8 *addr,I64 cnt=0x80);
public extern U0 Da(U8 **addr,I64 cnt=0x10);
extern I64 *TaskRegAddr(CTask *task,I64 reg_num);
public extern U0 Dr(CTask *task=NULL);
public extern U0 StkRep(CTask *task=NULL);
public extern U0 CallerRep(U8 **rbp=NULL,CTask *task=NULL);
#help_index "Debugging;Debugging/Debugger"
public extern U0 Dbg(U8 *msg=NULL,I64 msg_num=0);
#help_index "Debugging/Debugger"
public extern Bool InDbg(Bool val);
public extern Bool IsDbg();
public extern U0 G(U8 *ip=INVALID_PTR,CTask *task=NULL);
public extern U0 G2(U8 *ip=INVALID_PTR,CTask *task=NULL);
public extern U0 S(U8 *ip=INVALID_PTR,CTask *task=NULL);
public extern U0 E(U8 *addr,I64 cnt=512,I64 ed_flags=0);
extern CBpt *BptFind(U8 *needle_addr,CTask *haystack_task=NULL,Bool rem=FALSE);
public extern Bool BptS(U8 *addr,CTask *task=NULL,Bool live=TRUE);
public extern Bool BptR(U8 *addr,CTask *task=NULL,Bool live=TRUE,Bool rem=TRUE);
public extern Bool B(U8 *addr,CTask *task=NULL,Bool live=TRUE) //Toggle breakpoint
public extern I64 B2(CTask *task=NULL,Bool live=TRUE);
#help_index "Debugging/Raw Output"
public extern Bool Raw(Bool val);
public extern Bool IsRaw();
extern U0 RawDr(CTask *task=NULL);
public extern U0 RawPutChar(I64 ch);
public extern U0 VGAFlush();
public extern U0 RawPrint(I64 mS=100,U8 *fmt,...);
public extern U0 RawD(I64 mS=100,U8 *addr,I64 cnt=0x80);
public extern U0 RawDm(I64 mS=100,U8 *addr,I64 cnt=0x80);
#help_index "Graphics/Color"
extern U0 (*fp_set_std_palette)();
public extern U8 *Color2Text(U8 *buf,CColorROPU32 c);
#help_index "Graphics/Screen"
extern I64 gr_width,gr_height;
#help_index "Char"
#help_file "::/Doc/Char"
public extern U8 *gr_font;
#help_index "Char/System"
public extern Bool text_mode;
extern U0 (**fp_ctrl_alt_let_cbs)(I64 sc);
extern I64 ctrl_alt_let_in_irq_flags;
extern U8 **ctrl_alt_let_descs;
extern I64 **ctrl_alt_let_ret_addr; //addr of ret addr on stack in kbd irq
extern CSrvCmd sys_macro_root;
extern CKeyDev sys_put_key_root;
extern CTask *sys_macro_util_task;
extern I64 sys_raw_col,sys_raw_flags;
extern U8 *sys_raw_screen_image;
extern I64 text_rows,text_cols;
public extern CKeyDev *KeyDevAdd(Bool (*fp_put_key)(I64 ch,I64 sc),Bool (*fp_puts)(U8 *st),I64 priority,Bool key_descs=FALSE);
public extern U0 KeyDevRem(CKeyDev *tempp);
public extern U0 SetKeyDesc(U8 *fmt,...);
public extern U0 SetCtrlAltLetCB(U8 ch,U0 (*fp_handler)(I64 sc),U8 *desc,Bool in_irq=FALSE);
extern U8 key_desc[128];
extern U8 *key_handler;
#help_index "Char/Output"
public extern U0 Print(U8 *fmt,...);
public extern U0 PrintErr(U8 *fmt,...);
public extern U0 PrintWarn(U8 *fmt,...);
public extern U0 NewLine(I64 cnt=1);
public extern U0 Spaces(I64 cnt=1);
public extern U0 PutKey(I64 ch=0,I64 sc=0);
public extern U0 PutChars(U64 ch);
extern U0 PutS(U8 *st); //Use $LK,"Print",A="MN:Print"$()
public extern U8 *Bin2Hex(U8 *dst,I64 n;I64 width);
public extern U0 PutHex(I64 n,I64 width);
public extern Bool Silent(Bool val);
public extern Bool IsSilent();
public extern U0 GetOutOfDollar();
#help_index "Char/Conversion"
public extern I64 A2I64(U8 *st,I64 radix=10,U8 **_end_ptr=NULL);
#help_index "Input Pointer/Mouse"
public extern I64 mouse_evt_time;
extern I64 mouse_pkt_size;
#help_index "Char/Input"
public extern I64 kbd_evt_time;
extern Bool kbd_irqs_working;
public extern I64 PressAKey();
public extern Bool AreYouSure();
public extern I64 GetKey(I64 *_scancode=NULL,Bool echo=FALSE,Bool raw_cursor=FALSE);
public extern I64 GetChar(I64 *_scancode=NULL,Bool echo=TRUE,Bool raw_cursor=FALSE);
public extern Bool ScanKey(I64 *_ch=NULL,I64 *_scancode=NULL,Bool echo=FALSE);
public extern Bool YorN();
public extern I64 GetS(U8 *buf,I64 size,Bool allow_ext=TRUE);
public extern I64 KbdMouseEvtTime();
//Gets $LK,"Flags",A="MN:GETSF_SHIFT_ESC_EXIT"$
public extern U8 *MGetS(I64 flags=0);
extern U8 *(*fp_mgets)(I64 flags=0);
public extern U8 *ScanJoin(U8 *src,U8 *fmt,I64 argc,I64 *argv);
public extern U8 *Scan(U8 *src,U8 *fmt,...);
#help_index "Char/Lists"
public extern U8 *LstSub(I64 sub, U8 *lst);
public extern I64 LstMatch(U8 *needle, U8 *haystack_lst,I64 flags=0);
#help_index "Hash;Char/Lists"
public extern I64 HashLstAdd(U8 *lst,I64 type,CHashTable *table);
#help_index "Char/Operations"
public extern I64 StrOcc(U8 *src, U8 ch);
public extern U8 *StrFirstOcc(U8 *src,U8 *marker);
public extern U8 *StrLastOcc(U8 *src,U8 *marker);
public extern I64 Spaces2Tabs(U8 *dst,U8 *src);
public extern U8 *Tabs2Spaces(U8 *src);
public extern U8 *ScaleIndent(U8 *src,F64 indent_scale_factor);
public extern U8 *StrUtil(U8 *_src,I64 flags);
public extern U8 *MStrUtil(U8 *src,I64 flags,F64 indent_scale_factor=0);
public extern U8 *StrFirstRem(U8 *src,U8 *marker,U8 *dst=NULL);
public extern U8 *StrLastRem(U8 *src,U8 *marker,U8 *dst=NULL);
public extern Bool WildMatch(U8 *test_str,U8 *wild_str);
public extern U8 *StrFind(U8 *needle,U8 *haystack_str,I64 flags=0);
public extern U8 *SPrintJoin(U8 *dst,U8 *fmt,I64 argc,I64 *argv);
public extern U8 *SPrint(U8 *dst,U8 *fmt,...);
public extern U8 *CatPrint(U8 *dst,U8 *fmt,...);
public extern U8 *MPrint(U8 *fmt,...);
#help_index "Char/Define"
#help_file "::/Doc/Define"
public extern CHashDefineStr *DefineLoad(U8 *name,U8 *st);
public extern U0 DefinePrint(U8 *name,U8 *src,...);
public extern U8 *Define(U8 *name);
#help_index "Char/Define;Char/Lists"
public extern CHashDefineStr *DefineLstLoad(U8 *name,U8 *st);
public extern U8 *DefineSub(I64 sub,U8 *name);
public extern I64 DefineCnt(U8 *name);
public extern I64 DefineMatch(U8 *needle,U8 *haystack_lst_name,I64 flags=0);
#help_index "Hash;Char/Define;Char/Lists"
public extern I64 HashDefineLstAdd(U8 *name,I64 type,CHashTable *table);
#help_index "Memory"
#help_file "::/Doc/Mem"
public extern I64 MemPageSize(U8 *a)
public extern Bool MemPagePresentMark(U8 *a,Bool val);
public extern Bool MemLowPagesProtect(Bool val=TRUE);
public extern U8 *MemBlks2MegAlloc(I64 *_pages2Meg,CBlkPool *bp=NULL);
public extern U8 *MemBlksUncachedAlloc(I64 *_pages2Meg,CBlkPool *bp=NULL);
public extern U8 *MemBlksWriteThroughAlloc(I64 *_pages2Meg,CBlkPool *bp=NULL);
public extern U0 MemBlks2MegFree(CMemBlk *m,I64 pages2Meg,CBlkPool *bp=NULL);
public extern U8 *MemBlksIndependentAlloc(I64 *_pages512,CBlkPool *bp=NULL);
public extern I64 *MemPageTable(U8 *a);
public extern U0 MemBlksNonTaskFree(CMemBlk *m,I64 pages512,CBlkPool *bp=NULL);
public _extern _MALLOC U8 *MAlloc(I64 size,CTask *mem_task=NULL);
public _extern _FREE U0 Free(U8 *addr);
public _extern _MSIZE I64 MSize(U8 *src); //size of heap object
public _extern _MSIZE2 I64 MSize2(U8 *src); //Internal size
public _extern _MHEAP_CTRL CHeapCtrl *MHeapCtrl(U8 *src);
public extern U8 *CAlloc(I64 size,CTask *mem_task=NULL);
public extern U8 *MAllocIdentical(U8 *src,CTask *mem_task=NULL);
public extern U8 *MAllocAligned(I64 size,I64 alignment,CTask *mem_task=NULL,I64 misalignment=0);
public extern U8 *CAllocAligned(I64 size,I64 alignment,CTask *mem_task=NULL,I64 misalignment=0);
public extern I64 Scale2Mem(I64 min,I64 max,I64 limit=2*1024*1024*1024);
#help_index "Memory/Heap Ctrl"
public extern U0 BlkPoolAdd(CBlkPool *bp,CMemBlk *m,I64 pages512);
public extern U0 BlkPoolInit(CBlkPool *bp,I64 pages512);
public extern CHeapCtrl *HeapCtrlInit(CHeapCtrl *hc=NULL,CTask *task=NULL,CBlkPool *bp);
public extern U0 HeapCtrlDel(CHeapCtrl *hc);
public extern CHeapCtrl *HeapCtrlBPInit(CBlkPool *bp,I64 pages512);
#help_index "Memory/Adam Heap"
public extern U8 *AMAlloc(I64 size);
public extern U8 *AMAllocIdentical(U8 *src);
public extern U8 *ACAlloc(I64 size);
#help_index "Char/Operations;Memory"
public extern U8 *StrNew(U8 *buf,CTask *mem_task=NULL);
#help_index "Char/Operations;Memory/Adam Heap"
public extern U8 *AStrNew(U8 *buf);
#help_index "Device"
public extern U8 *Mem32DevAlloc(I64 size,I64 alignment);
public extern U8 *Mem64DevAlloc(I64 *_pages2Meg);
public extern U0 Mem32DevFree(U8 *base);
public extern U0 Mem64DevFree(U8 *base,I64 pages2Meg);
public extern CHeapCtrl *sys_uncached_heap;
#help_index "Task"
public extern U0 Exit();
public extern U0 Kill(CTask *task,Bool wait=TRUE);
public extern Bool Suspend(CTask *task=NULL,Bool state=TRUE);
public extern Bool IsSuspended(CTask *task=NULL);
public extern Bool TaskValidate(CTask *task);
public extern U0 TaskQueIns(CTask *task,CTask *pred=NULL);
public extern U0 TaskQueRem(CTask *task);
public extern U0 TaskWait(CTask *task=NULL);
public extern U0 UserCmdLine();
public extern CTask *SpawnUser(U8 *fmt=NULL,...);
extern U0 TaskFinishOff(CTask *task);
#help_index "Task;MultiCore"
public extern CTask *Spawn(U0 (*fp_addr)(U8 *data),U8 *data=NULL,
U8 *task_name=NULL,I64 target_cpu=-1, //-1 means current CPU
CTask *parent=NULL, //NULL means adam
I64 stk_size=0,I64 flags=1<<SVCf_ADD_TO_QUE);
#help_index "Task/Srv"
public extern U0 SrvCmdDel(CSrvCmd *tempc);
public extern U0 TaskRstAwaitingMsg(CTask *task=NULL);
public extern CSrvCmd *TaskExe(CTask *srv,CTask *master,U8 *data,I64 flags);
public extern I64 SrvCmdsHandler(CTask *task=NULL);
public extern I64 SrvUser(U8 *fmt,...);
extern U0 SrvUserCmdLine();
public extern U0 SrvTaskCont();
public extern I64 Adam(U8 *fmt,...);
public extern U0 AdamLog(U8 *fmt,...);
public extern U0 AdamErr(U8 *fmt,...);
#help_index "Task/Text & Msgs"
public extern CSrvCmd *TaskText(CTask *srv,CTask *master,
U8 *data,I64 flags);
#help_index "Task/Text & Msgs;Messages"
public extern CSrvCmd *TaskMsg(CTask *srv,CTask *master,
I64 msg_code,I64 p1,I64 p2,I64 flags);
public extern U0 PostMsg(CTask *task,I64 msg_code,I64 p1,I64 p2,I64 flags=0);
public extern U0 SendMsg(CTask *task,I64 msg_code,I64 p1,I64 p2,I64 flags=0);
public extern U0 Msg(I64 msg_code,I64 p1,I64 p2,I64 flags=0);
#help_index "Exceptions"
//Exceptions are thrown through the following function call.
public extern U0 throw(I64 ch=0,Bool no_log=FALSE);
//The following are used internally and should not be called directly
extern U0 SysTry(U8 *start_label,U8 *skip_label);
extern U0 SysUntry();
public extern U0 ThrowBreak(CTask *task=NULL);
public extern Bool BreakLock(CTask *task=NULL);
public extern Bool BreakUnlock(CTask *task=NULL);
public extern U0 PutExcept(Bool catch_it=TRUE);
#help_index "Compression/Piece by Piece"
public extern U0 ArcCompressBuf(CArcCtrl *c);
public extern U0 ArcFinishCompression(CArcCtrl *c);
public extern U0 ArcExpandBuf(CArcCtrl *c);
public extern CArcCtrl *ArcCtrlNew(Bool expand,Bool seven_bit);
public extern U0 ArcCtrlDel(CArcCtrl *c);
#help_index "Compression"
public extern CArcCompress *CompressBuf(U8 *src,I64 size,I64 flags=0,CTask *mem_task=NULL);
public extern U8 *ExpandBuf(CArcCompress *r,CTask *mem_task=NULL);
#help_index "AutoFile"
#help_file "::/Doc/AutoFile"
#help_index "Task/Text & Msgs;AutoFile"
public extern U0 Auto(U8 *fmt,...);
public extern U0 AutoStr(U8 *fmt,...);
public extern U0 AutoFile(U8 *filename);
public extern U0 XTalk(CTask *task,U8 *fmt,...);
public extern U0 XTalkWait(CTask *task,U8 *fmt,...);
public extern U0 XTalkStr(CTask *task,U8 *fmt,...);
public extern U0 XTalkStrWait(CTask *task,U8 *fmt,...);
#help_index "Misc/Progress Bars"
public extern U0 ProgressBarsRst();
#help_index "Math"
public extern U16 RandU16(); //With timestamp
public extern U32 RandU32();
public extern U64 RandU64();
public extern I16 RandI16();
public extern I32 RandI32();
public extern I64 RandI64();
public extern F64 Rand();
public extern U16 Rand2U16(); //Without timestamp
public extern U32 Rand2U32();
public extern U64 Rand2U64();
public extern I16 Rand2I16();
public extern I32 Rand2I32();
public extern I64 Rand2I64();
public extern F64 Rand2();
public extern U0 Randomize(I64 seed=0);
public extern U64 FloorU64(U64 num,U64 to);
public extern U64 CeilU64(U64 num,U64 to);
public extern I64 RoundI64(I64 num,I64 to);
public extern I64 FloorI64(I64 num,I64 to);
public extern I64 CeilI64(I64 num,I64 to);
#help_index "Misc"
public extern U0 QSortI64(I64 *base,I64 num, I64 (*fp_compare)(I64 e1,I64 e2));
public extern U0 QSort(U8 *base,I64 num, I64 width,I64 (*fp_compare)(U8 *e1,U8 *e2));
public extern U16 EndianU16(U16 d);
public extern U32 EndianU32(U32 d);
public extern U64 EndianU64(U64 d);
extern I64 sys_rnd_seed;
#help_index "Bit"
public extern I64 BCnt(I64 d);
public extern U8 *reverse_bits_table,*set_bits_table;
#help_index "Doc/Clipboard"
public extern CDoc *sys_clipboard_doc;
#help_index "Time/Date;Date"
public extern U16 mon_start_days1[12];
public extern U16 mon_start_days2[12];
public extern I64 YearStartDate(I64 year);
public extern I64 FirstDayOfMon(I64 i);
public extern I64 LastDayOfMon(I64 i);
public extern I64 FirstDayOfYear(I64 i);
public extern I64 LastDayOfYear(I64 i);
public extern I64 DayOfWeek(I64 i);
#help_index "Time/Date/CDate;Date/CDate"
#help_file "::/Doc/TimeDate"
public extern CDate Struct2Date(CDateStruct *_ds);
public extern U0 Date2Struct(CDateStruct *_ds,CDate cdt);
extern U0 Date2ISO1(CISO1Date *dst,CDate cdt);
public extern CDate local_time_offset;
public extern CDate Now();
public extern I64 Hour12 (CDate cdt=MIN_I64);
public extern I64 Hour24 (CDate cdt=MIN_I64);
public extern I64 Minute (CDate cdt=MIN_I64);
public extern I64 Second (CDate cdt=MIN_I64);
public extern I64 Day (CDate cdt=MIN_I64);
public extern I64 WeekDay(CDate cdt=MIN_I64);
public extern I64 Month (CDate cdt=MIN_I64);
public extern I64 Year (CDate cdt=MIN_I64);
extern U8 *MPrintTime(CDate cdt);
extern U8 *MPrintDate(CDate cdt);
#help_index "File/System"
extern U8 sys_temp_filename[136];
extern I64 sys_dsk_reads,sys_dsk_writes;
extern CCacheBlk *sys_dsk_cache_base,*sys_dsk_cache_ctrl;
extern CCacheBlk **sys_dsk_cache_hash_table;
extern I64 sys_dsk_cache_size;
extern U0 DskCacheInit(I64 size_in_U8s);
public extern U0 DskCacheInvalidate(CPrt *p);
public extern CBlkDev *sys_blkdevs;
public extern CPrt *sys_prts;
extern CPrt *drv_to_prt[32];
#help_index "PCI;Info;File/System;Device"
public extern I64 ATARep(Bool pmt=TRUE,Bool just_ide=FALSE,CATARep **_root=NULL);
#help_index "File/System"
public extern CATARep *ATAIDDrvs(CATARep *root,U8 _sys_acct_drv,CATARep **_ata_drv,CATARep **_atapi_drv);
extern CBlkDev *ATAMount(U8 first_drv_let,I64 type,I64 base0,I64 base1,I64 unit);
public extern I64 sys_auto_mount_ide_cnt;
public extern I64 AutoMountIDE();
extern I64 ATAProbe(I64 base0,I64 base1,I64 unit);
extern Bool ATAPIStartStop(CBlkDev *bdev,F64 timeout,Bool start);
extern I64 BlkDevAdd(CBlkDev *bdev,Bool one_prt,Bool make_free);
extern U0 ATAReadBlks(CBlkDev *bdev,U8 *buf, I64 blk, I64 cnt);
extern U0 ATAWriteBlks(CBlkDev *bdev,U8 *buf, I64 blk, I64 cnt);
#help_index "File/Cmd Line (Typically);Cmd Line (Typically)"
#help_file "::/Doc/CmdLine"
public extern U0 ChgDsk(U8 drv_let=0);
public extern Bool Drv(U8 drv_let);
public extern Bool Cd(U8 *dirname,Bool make_dirs=FALSE);
public extern Bool MapDrv(U8 drv_let,CPrt *p);
public extern I64 Dir(U8 *wild="*",Bool full=FALSE);
public extern I64 Del(U8 *wild,Bool print_msg=TRUE);
public extern Bool MkDir(U8 *filename);
#help_index "Info;File/Cmd Line (Typically);Cmd Line (Typically);Install"
public extern U0 PrtRep();
#help_index "File/Program Routines/Low Level"
extern CDirEntry *SysFilesFind(U8 *files_find_mask,I64 fuf_flags);
extern I64 SysDel(U8 *wild,Bool make_mask); //this is dangerous
extern Bool CopySingle(U8 *f1,U8 *f2); //Just one file
extern U0 CleanMAPBuf(CPrt *p);
extern U0 FAT32FreeClusters(CPrt *p,I64 c);
extern U0 RedSeaFSFreeClusters(CPrt *p,I64 c,I64 cnt);
public extern Bool BlkDevLock(CBlkDev *bdev);
public extern Bool PrtLock(CPrt *p);
public extern Bool BlkDevUnlock(CBlkDev *bdev,Bool rst=FALSE);
public extern Bool PrtUnlock(CPrt *p,Bool rst=FALSE);
public extern U0 BlkDevsRelease();
public extern CPrt *PrtMakeFree(U8 drv_let);
public extern CPrt *PrtNextFree(U8 first_drv_let='C');
public extern CBlkDev *BlkDevNextFree(U8 first_drv_let,I64 type);
public extern U0 PrtsRelease();
public extern I64 ClusterNumNext(CPrt *p,I64 c,I64 cnt=1);
public extern I64 Cluster2Blk(CPrt *p,I64 c);
public extern I64 RClustersBlks(CPrt *p,U8 *buf,I64 c,I64 blks);
public extern I64 RClusters(CPrt *p,U8 *buf,I64 c,I64 cnt);
public extern I64 WClustersBlks(CPrt *p,U8 *buf,I64 c,I64 blks);
public extern I64 WClusters(CPrt *p,U8 *buf,I64 c,I64 cnt);
public extern I64 ClustersAlloc(CPrt *p,I64 c=0,I64 cnt=1,Bool contiguous=FALSE);
public extern Bool RBlks(CPrt *p,U8 *buf, I64 blk, I64 cnt);
public extern Bool WBlks(CPrt *p,U8 *buf, I64 blk, I64 cnt);
public extern U0 WZeroBlks(CPrt *p,I64 blk,I64 cnt);
public extern U0 PrtChk(CPrt *p);
public extern U0 BlkDevChk(CBlkDev *bdev);
public extern U8 Prt2Drv(CPrt *p=NULL);
public extern CPrt *Drv2Prt(U8 drv_let=0);
public extern CBlkDev *Drv2BlkDev(U8 drv_let=0);
extern I64 Name2DirCluster(CPrt *p,U8 *dirname);
extern I64 Name2ParentDirCluster(CPrt *p,U8 *dirname);
public extern U8 *DrvSerialNum(U8 drv_let=0);
public extern U8 *DrvModelNum(U8 drv_let=0);
#help_index "File/Program Routines/CFile"
public extern CFile *FOpen(U8 *filename,U8 *flags,I64 cnt=0);
public extern I64 FSize(CFile *f);
public extern U0 FClose(CFile *f);
public extern Bool FRBlks(CFile *f,U8 *buf,I64 blk=FFB_NEXT_BLK,I64 cnt=1);
public extern Bool FWBlks(CFile *f,U8 *buf,I64 blk=FFB_NEXT_BLK,I64 cnt=1);
#help_index "File/CD DVD"
public extern U0 CDImageRead(U8 cd_drv_let,U8 *out_name);
public extern U0 CDImageWrite(U8 cd_drv_let,U8 *in_name=NULL,I64 media_type=MT_CD);
public extern U8 *sys_dft_iso_name;
#help_index "File/FileNames"
public extern U8 *sys_acct;
public extern Bool FilesFindMatch(U8 *test_filename,U8 *files_find_mask,I64 fuf_flags=0);
public extern Bool IsDotZ(U8 *filename);
public extern Bool IsDotC(U8 *filename);
public extern U8 *FileExtDot(U8 *src);
public extern U8 *FileExtRem(U8 *src,U8 *dst=NULL);
public extern U0 PutFileLink(U8 *filename,I64 line=0,Bool plain_text=FALSE);
public extern U0 PutDirLink(U8 *dirname);
public extern U8 *CurDir(CTask *task=NULL,CTask *mem_task=NULL);
public extern U8 *DirNameAbs(U8 *dirname);
public extern U8 *DirFile(U8 *dirname,U8 *name=NULL,U8 *_extension=NULL);
public extern U8 *ToggleZorNotZ(U8 *name);
public extern U8 *FileNameAbs(U8 *filename,I64 fuf_flags=0);
public extern Bool FileNameChk(U8 *filename);
public extern U8 *ChgExt(U8 *filename,U8 *extension);
public extern U8 *DftExt(U8 *filename,U8 *extension);
public extern Bool IsDir(U8 *dir_name);
public extern Bool IsDrvWritable(U8 drv_let=0);
extern CDirEntry *Cd2DirEntry(CDirEntry *tempde,U8 *abs_name);
public extern U0 ToFileLine(U8 *_fl_file_line,U8 **_filename,I64 *_linenum);
#help_index "File/Program Routines/Utils"
public extern U0 ScanFlags(U8 *f,U8 *lst,U8 *st);
public extern U8 *SPrintFlags(U8 *dst,U8 *lst,I64 flags);
public extern U0 FileAccessDel(CFileAccess *fa);
public extern CFileAccess *FileAccessNew(U8 *mask,Bool make_mask=FALSE,Bool make_dirs=FALSE,Bool no_mask=FALSE);
extern I64 FileAttr(U8 *name,I64 old_attr=0);
public extern U0 DirEntryDel(CDirEntry *tempde);
public extern U0 DirEntryDel2(CDirEntry *tempde);
public extern U0 DirLstDel(CDirEntry *tempde);
public extern U0 DirLstDel2(CDirEntry *tempde);
public extern Bool DirNew(CPrt *p,U8 *cur_dir,CDirEntry *tempde,Bool free_old_chain=TRUE);
#help_index "File/Program Routines"
public extern CDirEntry *FilesFind(U8 *files_find_mask,I64 fuf_flags=0);
public extern Bool FileFind(U8 *filename,CDirEntry *_de=NULL,I64 fuf_flags=0);
public extern U8 *FileRead(U8 *filename,I64 *_size=NULL,I64 *_attr=NULL,Bool raw=FALSE);
public extern I64 FileWrite(U8 *filename,U8 *fbuf,
I64 size,CDate cdt=0,I64 attr=0,Bool raw=FALSE);
#help_index "Install;File/Cmd Line (Typically);Cmd Line (Typically);"
public extern U0 Mount(Bool repartition=FALSE);
public extern U0 Fmt(U8 drv_let,Bool quick=TRUE,Bool confirm=TRUE,I64 type=PT_FAT32);
#help_index "Install"
#help_file "::/Doc/Install"
extern CATARep *ATARepFind(CATARep *haystack_root,I64 needle_num);
public extern Bool DrvEnable(U8 drv_let,Bool val);
public extern U8 sys_first_hd_drv_let,sys_first_cd_drv_let;
extern Bool boot_drv_pmt,cdrom_boot_is_good;
#help_index "Hash"
#help_file "::/Doc/Hash"
public _extern _HASH_STR I64 HashStr(U8 *st);
public _extern _HASH_FIND CHash *HashFind(U8 *needle_str,CHashTable *haystack_table,I64 mask,I64 instance=1);
public _extern _HASH_SINGLE_TABLE_FIND CHash *
HashSingleTableFind(U8 *needle_str,CHashTable *haystack_table,I64 mask,I64 instance=1);
public _extern _HASH_BUCKET_FIND CHash **
HashBucketFind(U8 *needle_str,CHashTable *haystack_table);
public _extern _HASH_ADD U0 HashAdd(CHash *temph,CHashTable *table);
public _extern _HASH_ADD_AFTER U0 HashAddAfter(CHash *temph,CHash *pred,CHashTable *table);
public _extern _HASH_REM_DEL Bool HashRemDel(CHash *temph,CHashTable *table,
I64 instance=1);//instance must match temph's
public extern CHashGeneric *HashPublic(U8 *st,I64 mask,Bool val=TRUE);
public extern CHashGeneric *HashGenericAdd(U8 *name,I64 type,I64 val=0,I64 u8=0,I64 u16=0,CTask *task=NULL);
public extern I64 HashTypeNum(CHash *temph);
public extern I64 HashVal(CHash *temph);
public extern CHashTable *HashTableNew(I64 size,CTask *mem_task=NULL);
public extern U0 HashDel(CHashSrcSym *temph);
public extern U0 HashTableDel(CHashTable *table);
public extern I64 HashTablePurge(CHashTable *tempht);
extern U0 SysSymImportsResolve(U8 *sptr,I64 ld_flags=0);
#help_index "Compiler/Lex"
public extern U0 SetSrcFileInfo(CLex *lx,CHashSrcSym *h);
#help_index "Hash/Frame"
#help_file "::/Doc/Frame"
public extern I64 FramePtr(U8 *name,CTask *task=NULL);
public extern CHashGeneric *FramePtrAdd(U8 *name,I64 val,CTask *task=NULL);
public extern I64 FramePtrSet(U8 *name,I64 val,CTask *task=NULL);
public extern I64 FramePtrDel(U8 *name,CTask *task=NULL);
#help_index "Compiler;Cmd Line (Typically)"
public extern U8 *Load(U8 *filename,I64 ld_flags=0,
CBinFile *bfh_addr=INVALID_PTR); //INVALID_PTR means don't care what load addr.
#help_index "Boot"
#help_file "::/Doc/Boot"
public extern U0 Reboot();
#help_index "MultiCore;Task/Srv"
public extern CSrvCmd *JobQue(I64 (*fp_addr)(U8 *data),U8 *data=NULL,
I64 target_cpu=1,I64 flags=1<<SVCf_FREE_ON_COMPLETE,
I64 cmd_code=SVCT_CALL,U8 *aux_str=NULL,I64 aux1=0,I64 aux2=0);
#help_index "MultiCore"
extern U8 mp_apic_ids[MP_MAX_PROCESSORS];
extern CMPCrash *mp_crash;
public extern U0 MPInt(U8 num,I64 cpu_num=1);
public extern U0 MPIntAll(U8 num);
public extern U0 MPWake(I64 target_cpu);
extern U0 MPSethServerTask();
extern CTask *SpawnQue(U0 (*fp_addr)(U8 *data),U8 *data=NULL,
U8 *task_name=NULL,I64 target_cpu,
CTask *parent=NULL, //NULL means adam
I64 stk_size=0,I64 flags=1<<SVCf_ADD_TO_QUE);
public extern U0 MPNMInt();
public extern U0 MPStart();
#help_index "Task/Srv;MultiCore"
public extern Bool ScanResult(CSrvCmd *rqst=NULL,I64 *_result=NULL);
public extern I64 GetResult(CSrvCmd *rqst=NULL);
#help_index "MultiCore;Boot"
public extern U0 MPHalt();
#help_index "Math"
public extern F64 Clamp(F64 num,F64 lo,F64 hi);
public extern F64 Min(F64 n1,F64 n2);
public extern F64 Max(F64 n1,F64 n2);
public extern F64 Pow10I64(I64 i);
#help_index "PCI"
public extern U8 PCIReadU8(I64 bus,I64 dev,I64 fun,I64 rg);
public extern U16 PCIReadU16(I64 bus,I64 dev,I64 fun,I64 rg);
public extern U32 PCIReadU32(I64 bus,I64 dev,I64 fun,I64 rg);
public extern U0 PCIWriteU8(I64 bus,I64 dev,I64 fun,I64 rg,I64 val);
public extern U0 PCIWriteU16(I64 bus,I64 dev,I64 fun,I64 rg,I64 val);
public extern U0 PCIWriteU32(I64 bus,I64 dev,I64 fun,I64 rg,I64 val);
public extern I64 PCIClassFind(I64 class_code,I64 n);
//These are far call routines in the BIOS
public _extern SYS_BIOS32_SERVICE_DIR U32 sys_BIOS32_service_dir;
public _extern SYS_PCI_SERVICES U32 sys_pci_services;
#help_index "PCI;Call"
public _extern C32_EAX U32 c32_eax;
public _extern C32_EBX U32 c32_ebx;
public _extern C32_ECX U32 c32_ecx;
public _extern C32_EDX U32 c32_edx;
public _extern C32_ESI U32 c32_esi;
public _extern C32_EDI U32 c32_edi;
public _extern C32_EFLAGS U32 c32_eflags;
//Not reentrant
public _extern _FAR_CALL32 Bool FarCall32(U0 (*fp_addr)());
#help_index "Call"
//fp_addr can have any fixed number of arguments.
public argpop extern I64 CallStkGrow(I64 stk_size_threshold,I64 stk_size,/*argpop*/I64 (*fp_addr)(...),...);
#help_index "Data Types/Circular Queue"
public extern U0 QueDel(CQue *root,Bool querem=FALSE);
public extern CQue *QueCopy(CQue *root,CTask *mem_task=NULL);
public extern I64 QueCnt(CQue *root);
public extern I64 QueSize(CQue *root);
#help_index "Data Types"
public extern U0 LinkedLstDel(U8 **_lst);
public extern U8 *LinkedLstCopy(U8 **_lst,CTask *mem_task=NULL);
public extern I64 LinkedLstCnt(U8 **_lst);
public extern I64 LinkedLstSize(U8 **_lst);
public extern CQueVectU8 *QueVectU8New(I64 min_index=0);
public extern U0 QueVectU8Put(CQueVectU8 *v,I64 index,U8 ch);
public extern U0 QueVectU8Del(CQueVectU8 *v);
public extern I64 QueVectU8Get(CQueVectU8 *v,I64 index);
public extern CFifoU8 *FifoU8New(I64 size,CTask *mem_task=NULL);
public extern U0 FifoU8Del(CFifoU8 *f);
public extern Bool FifoU8Ins(CFifoU8 *f,U8 b);
public extern Bool FifoU8Rem(CFifoU8 *f,U8 *_b);
public extern Bool FifoU8Peek(CFifoU8 *f,U8 *_b);
public extern U0 FifoU8Flush(CFifoU8 *f);
public extern I64 FifoU8Cnt(CFifoU8 *f);
public extern CFifoI64 *FifoI64New(I64 size,CTask *mem_task=NULL);
public extern U0 FifoI64Del(CFifoI64 *f);
public extern Bool FifoI64Ins(CFifoI64 *f,I64 q);
public extern Bool FifoI64Rem(CFifoI64 *f,I64 *_q);
public extern Bool FifoI64Peek(CFifoI64 *f,I64 *_q);
public extern U0 FifoI64Flush(CFifoI64 *f);
public extern I64 FifoI64Cnt(CFifoI64 *f);
#help_index "Char/Operations"
public _extern _STRCMP I64 StrCmp(U8 *st1,U8 *st2);
public _extern _STRICMP I64 StrICmp(U8 *st1,U8 *st2);
public _extern _STRNCMP I64 StrNCmp(U8 *st1,U8 *st2,I64 n);
public _extern _STRNICMP I64 StrNICmp(U8 *st1,U8 *st2,I64 n);
public _extern _STRMATCH U8 *StrMatch(U8 *needle,U8 *haystack_str);
public _extern _STRIMATCH U8 *StrIMatch(U8 *needle,U8 *haystack_str);
public _extern _STRCPY U0 StrCpy(U8 *dst,U8 *src);
#help_index "Char/Input"
public extern I64 sys_key_cnt;
public extern U0 SetTypeMatic(U8 delay);
extern U0 KbdInit();
extern I64 KbdMsgsQue();
extern U0 KbdMouseVarsInit();
extern Bool MouseDriverInstall();
extern U0 KbdMouseHandler(Bool poll_kbd,Bool poll_mouse);
public extern U32 key_down_bitmap[8],key_down_bitmap2[8];
#help_index "Char/BitMaps"
public extern U32 chars_bitmap_alpha[16];
public extern U32 chars_bitmap_alpha_numeric[16];
public extern U32 chars_bitmap_alpha_numeric_no_at[16];
public extern U32 chars_bitmap_word[16];
public extern U32 chars_bitmap_dec_numeric[16];
public extern U32 chars_bitmap_hex_numeric[16];
public extern U32 chars_bitmap_white_space[16];
public extern U32 chars_bitmap_non_eol_white_space[16];
public extern U32 chars_bitmap_zero_cr_nl_cursor[16];
public extern U32 chars_bitmap_zero_tab_ff_cr_nl_cursor[16];
public extern U32 chars_bitmap_zero_tab_ff_cr_nl_cursor_dollar[16];
public extern U32 chars_bitmap_getkey[16];
public extern U32 chars_bitmap_printable[16];
public extern U32 chars_bitmap_displayable[16];
public extern U32 chars_bitmap_safe_dollar[16];
public extern U32 chars_bitmap_filename[16];
public extern U32 chars_bitmap_non_eol[16];
#help_index "Char/Conversion"
public extern I64 A2ScanCode(I64 ch,I64 sc_flags=0);
public extern U8 ScanCode2A(I64 sc);
public extern U8 *A2KeyName(I64 ch,Bool include_ctrl=TRUE);
public extern U8 *ScanCode2KeyName(I64 sc);
#help_index "Input Pointer/Mouse"
public extern F64 mxx_scale,myy_scale,mzz_scale;
//These are the coordinates before
//they get scaled.
public extern I64 mxx_prescale,myy_prescale,mzz_prescale;
public extern I64 mxx,myy,mzz;
public extern F64 mouse_speed;
extern I64 old_mxx,old_myy,old_mzz;
public extern Bool mouse_buttons[5];
extern Bool mouse_installed;
extern I64 mouse_install_attempts,
mouse_last_evt_time;
extern Bool mouse_has_wheel;
extern Bool mouse_has_ext_buttons;
extern Bool mouse_evt;
extern Bool mouse_install_attempt_in_progress;
extern CFifoI64 *scan_code_fifo;
extern I64 sys_last_down_scan_code;
extern Bool kbdmouse_rst;
extern Bool mouse_irqs_working;
#help_index "Input Pointer"
#help_file "::/Doc/InputPointer"
public extern I64 ipx,ipy,ipz,ip_throttle,ip_throttle_step;
public extern I64 ipx_offset,ipy_offset,ipz_offset;
public extern F64 ipx_scale,ipy_scale,ipz_scale;
public extern F64 ip_speed;
public extern I64 ip_dev;
public extern I64 iptx,ipty;
public extern Bool ip_lb,ip_cb,ip_rb;
extern Bool ip_lb_last,ip_cb_last,ip_rb_last;
public extern Bool ip_has_wheel;
extern F64 ip_last_move_time;
public extern CGrid ip_grid;
public extern U0 GridInit();
public extern U0 SetIP(I64 x=MAX_I64,I64 y=MAX_I64,I64 z=MAX_I64,I64 l=MAX_I64,I64 r=MAX_I64,I64 c=MAX_I64);
#help_index "Input Pointer/Displayed Image"
public extern Bool ip_on; //Show or hide cursor
extern U0 IPVarsUpdate(I64 x,I64 y,I64 z,Bool l,Bool c,Bool r);
extern U0 IPVarsInit();
public extern I64 ipx_presnap,ipy_presnap,ipz_presnap;
#help_index "Messages"
extern U0 InputFilterTask();
public extern I64 ScanMsg(I64 *_p1=NULL,I64 *_p2=NULL,I64 mask=~1,CTask *task=NULL);
public extern I64 FlushMsgs(CTask *task=NULL);
public extern I64 GetMsg(I64 *_p1=NULL,I64 *_p2=NULL,I64 mask=~1,CTask *task=NULL);
public extern I64 ScanChar();
#help_index "Misc;Messages"
public extern I64 sys_cur_scan_code;
#help_index "Doc/Task"
extern CDoc *(*fp_doc_put)(CTask *task=NULL);
#help_index "Char/Conversion"
public extern F64 A2F64(U8 *src,U8 **_end_ptr=NULL);
#help_index "Char/Conversion;Time/Date/CDate;Date/CDate"
public extern CDate A2Date(U8 *src);
#help_index "Debugging/PSect;Hash"
public extern CHash *PSectFind(U8 *addr,I64 *_offset);
extern CPSectCache *psect_cache;
extern I64 psect_cache_index;
#help_index "Debugging/PSect"
public extern I64 SrcLineNum(U8 *addr,I64 cnt=1);
public extern U8 *SrcFileName(U8 *addr,I64 cnt=1,CTask *mem_task=NULL);
public extern U8 *SrcEdLink(U8 *addr,I64 cnt=1,CTask *mem_task=NULL);
public extern Bool PutSrcLink(U8 *addr,I64 cnt=1,U8 *buf=NULL);
#help_index "Debugging;Debugging/Debugger"
public extern U0 EdLite(U8 *filename,I64 num=1);
extern U8 *sys_fix_file_line;
public extern U0 SetFix(U8 *filename,I64 line);
extern U0 EdLiteFileLine(U8 *fl_file_line);
public extern U0 Fix();
#help_index "Debugging/Debugger;Doc/Cmd Line (Typically);Cmd Line (Typically);Training"
public extern U0 Man(U8 *st);
#help_index "Task/Srv;Compiler"
public extern U0 UserTaskCont();
public extern I64 ExeCmdLine(CLex *lx);
#help_index "Training;Debugging/Debugger"
public extern U0 Help();
#help_index ""
+297
View File
@@ -0,0 +1,297 @@
asm {
USE32
SYS_BIOS32_SERVICE_DIR:: DU32 0;
SYS_PCI_SERVICES:: DU32 0;
SYS_FIND_BIOS32_SERVICE_DIR::
MOV ESI,0xE0000
MOV ECX,(0x100000-0xE0000)/4
@@05: CMP U32 [ESI],'_32_'
JNE @@20
PUSH ECX
XOR ECX,ECX
MOV CL,U8 9[ESI]
SHL ECX,4
@@10: MOV EDI,ESI
XOR EAX,EAX
XOR EDX,EDX
@@15: MOV DL,U8 [EDI]
ADD EAX,EDX
INC EDI
DEC ECX
JNZ @@15
POP ECX
TEST AL,AL
JNZ @@20
MOV U32 [SYS_BIOS32_SERVICE_DIR],ESI
MOV ESI,U32 4[ESI]
MOV U32 [SYS_BIOS32_SERVICE_CALL],ESI
RET
@@20: ADD ESI,4
LOOP @@05
MOV U32 [SYS_BIOS32_SERVICE_DIR],0
RET
SYS_FIND_PCI_SERVICES::
MOV ESI,U32 [SYS_BIOS32_SERVICE_DIR]
TEST ESI,ESI
JNZ @@05
MOV U32 [SYS_PCI_SERVICES],0
RET
@@05: MOV EAX,'$$PCI'
XOR EBX,EBX
DU8 0x9A; //CALL CGDT.cs32:BIOS32_SERVICE
SYS_BIOS32_SERVICE_CALL:: DU32 0;
DU16 CGDT.cs32;
TEST AL,AL
JNZ @@05
LEA ESI,U32 [EBX+EDX]
MOV U32 [SYS_PCI_SERVICES],ESI
RET
@@05: MOV U32 [SYS_PCI_SERVICES],0
RET
USE64
C32_EAX:: DU32 0;
C32_EBX:: DU32 0;
C32_ECX:: DU32 0;
C32_EDX:: DU32 0;
C32_ESI:: DU32 0;
C32_EDI:: DU32 0;
C32_EFLAGS:: DU32 0;
C32_RSP:: DU64 0;
_FAR_CALL32::
//This calls a 32-bit mode routine.
//(We must switch from 64-bit mode to do it.)
//
//NON REENTRANT
//
PUSH RBP
MOV RBP,RSP
MOV RAX,U64 SF_ARG1[RBP]
TEST RAX,RAX
JNZ @@05
POP RBP
RET1 8 //return FALSE
@@05: MOV U32 [C32_ADD],EAX
PUSH_REGS
PUSHFD
XOR RAX,RAX
PUSH U64 FS:CTask.addr[RAX]
PUSH U64 GS:CCPU.addr[RAX]
MOV U64 [C32_RSP],RSP
PUSH U32 CGDT.ds //STKSEG
PUSH U32 0x9C000 //STK
PUSH U32 0 //FLAGS--interrupts off
PUSH U32 CGDT.cs32
LEA RAX,[@@15]
PUSH RAX
IRET
USE32
@@15:
WBINVD
//disable paging
MOV_EAX_CR0
BTR EAX,31
MOV_CR0_EAX
MOV ECX,IA32_EFER
XOR EDX,EDX
XOR EAX,EAX
WRMSR
MOV AX,CGDT.ds
MOV FS,AX
MOV GS,AX
//SS already set
MOV EAX,U32 [C32_EAX]
MOV EBX,U32 [C32_EBX]
MOV ECX,U32 [C32_ECX]
MOV EDX,U32 [C32_EDX]
MOV ESI,U32 [C32_ESI]
MOV EDI,U32 [C32_EDI]
MOV U32 [C32_EFLAGS],0
DU8 0x9A; //CALL CGDT.cs32:[C32_ADD]
C32_ADD:: DU32 0;
DU16 CGDT.cs32;
PUSHFD
POP U32 [C32_EFLAGS]
MOV U32 [C32_EAX],EAX
MOV U32 [C32_EBX],EBX
MOV U32 [C32_ECX],ECX
MOV U32 [C32_EDX],EDX
MOV U32 [C32_ESI],ESI
MOV U32 [C32_EDI],EDI
CALL INIT_EM64T
USE64
MOV AX,CGDT.ds
MOV DS,AX
MOV ES,AX
MOV SS,AX
MOV RSP,U64 [C32_RSP]
POP RAX
CALL SET_GS_BASE
POP RAX
CALL SET_FS_BASE
POPFD
POP_REGS
XOR RAX,RAX
MOV AL,TRUE
POP RBP
RET1 8
}
_extern C32_EAX U32 c32_eax;
_extern C32_EBX U32 c32_ebx;
_extern C32_ECX U32 c32_ecx;
_extern C32_EDX U32 c32_edx;
_extern C32_ESI U32 c32_esi;
_extern C32_EDI U32 c32_edi;
_extern C32_EFLAGS U32 c32_eflags;
_extern SYS_PCI_SERVICES U32 sys_pci_services;
//Not reentrant--used to call BIOS32
//Takes like, 250uS.
_extern _FAR_CALL32 Bool FarCall32(U0 (*fp_addr)());
U8 PCIReadU8(I64 bus,I64 dev,I64 fun,I64 rg)
{
I64 result;
PUSHFD
CLI
while (LBts(&sys_semas[SYS_SEMA_FAR_CALL32],0))
Yield;
c32_eax=0xB108;
c32_ebx=bus<<8+dev<<3+fun;
c32_edi=rg;
if (FarCall32(sys_pci_services))
result=c32_ecx.u8[0];
else
result=0xFF;
LBtr(&sys_semas[SYS_SEMA_FAR_CALL32],0);
POPFD
return result;
}
U16 PCIReadU16(I64 bus,I64 dev,I64 fun,I64 rg)
{
I64 result;
PUSHFD
CLI
while (LBts(&sys_semas[SYS_SEMA_FAR_CALL32],0))
Yield;
c32_eax=0xB109;
c32_ebx=bus<<8+dev<<3+fun;
c32_edi=rg;
if (FarCall32(sys_pci_services))
result=c32_ecx.u16[0];
else
result=0xFFFF;
LBtr(&sys_semas[SYS_SEMA_FAR_CALL32],0);
POPFD
return result;
}
U32 PCIReadU32(I64 bus,I64 dev,I64 fun,I64 rg)
{
I64 result;
PUSHFD
CLI
while (LBts(&sys_semas[SYS_SEMA_FAR_CALL32],0))
Yield;
c32_eax=0xB10A;
c32_ebx=bus<<8+dev<<3+fun;
c32_edi=rg;
if (FarCall32(sys_pci_services))
result=c32_ecx;
else
result=0xFFFFFFFF;
LBtr(&sys_semas[SYS_SEMA_FAR_CALL32],0);
POPFD
return result;
}
U0 PCIWriteU8(I64 bus,I64 dev,I64 fun,I64 rg,I64 val)
{
PUSHFD
CLI
while (LBts(&sys_semas[SYS_SEMA_FAR_CALL32],0))
Yield;
c32_eax=0xB10B;
c32_ebx=bus<<8+dev<<3+fun;
c32_edi=rg;
c32_ecx=val;
FarCall32(sys_pci_services);
LBtr(&sys_semas[SYS_SEMA_FAR_CALL32],0);
POPFD
}
U0 PCIWriteU16(I64 bus,I64 dev,I64 fun,I64 rg,I64 val)
{
PUSHFD
CLI
while (LBts(&sys_semas[SYS_SEMA_FAR_CALL32],0))
Yield;
c32_eax=0xB10C;
c32_ebx=bus<<8+dev<<3+fun;
c32_edi=rg;
c32_ecx=val;
FarCall32(sys_pci_services);
LBtr(&sys_semas[SYS_SEMA_FAR_CALL32],0);
POPFD
}
U0 PCIWriteU32(I64 bus,I64 dev,I64 fun,I64 rg,I64 val)
{
PUSHFD
CLI
while (LBts(&sys_semas[SYS_SEMA_FAR_CALL32],0))
Yield;
c32_eax=0xB10D;
c32_ebx=bus<<8+dev<<3+fun;
c32_edi=rg;
c32_ecx=val;
FarCall32(sys_pci_services);
LBtr(&sys_semas[SYS_SEMA_FAR_CALL32],0);
POPFD
}
I64 PCIClassFind(I64 class_code,I64 n)
{
//class_code is low three bytes
//n is index starting at zero
//Returns: -1 not found
// else bus,dev,fun.
I64 result;
PUSHFD
CLI
while (LBts(&sys_semas[SYS_SEMA_FAR_CALL32],0))
Yield;
c32_eax=0xB103;
c32_esi=n;
c32_ecx=class_code;
if (FarCall32(sys_pci_services) && !c32_eax.u8[1])
result=c32_ebx.u8[1]<<16+(c32_ebx&0xF8)<<5+c32_ebx&7;
else
result=-1;
LBtr(&sys_semas[SYS_SEMA_FAR_CALL32],0);
POPFD
return result;
}
+310
View File
@@ -0,0 +1,310 @@
//See $LK,"::/Doc/Acknowledgements.TXT"$.
//See $LK,"CArcCompress",A="MN:CArcCompress"$, $LK,"CArcEntry",A="MN:CArcEntry"$, and $LK,"CArcCtrl",A="MN:CArcCtrl"$
asm {
USE64
/****
U0 ArcGetEntry(CArcCtrl *c)
{
I64 i;
CArcEntry *temp,*temp1;
if (c->entry_used) {
i=c->free_index;
c->entry_used=FALSE;
c->cur_entry=c->next_entry;
c->cur_bits_in_use=c->next_bits_in_use;
if (c->next_bits_in_use<ARC_MAX_BITS) {
c->next_entry = &c->compress[i++];
if (i==c->free_limit) {
c->next_bits_in_use++;
c->free_limit=1<<c->next_bits_in_use;
}
} else {
do if (++i==c->free_limit)
i=c->min_table_entry;
while (c->hash[i]);
temp=&c->compress[i];
c->next_entry=temp;
temp1=&c->hash[temp->basecode];
while (temp1) {
if (temp1->next==temp) {
temp1->next=temp->next;
break;
} else
temp1=temp1->next;
}
}
c->free_index=i;
}
}
****/
_ARC_GET_ENTRY::
PUSH RBP
MOV RBP,RSP
PUSH RSI
PUSH RDI
MOV RSI,U64 SF_ARG1[RBP]
BTR U64 CArcCtrl.entry_used[RSI],0
JNC I32 @@30
MOV RDX,U64 CArcCtrl.free_index[RSI]
MOV RAX,U64 CArcCtrl.next_entry[RSI]
MOV U64 CArcCtrl.cur_entry[RSI],RAX
MOV RCX,U64 CArcCtrl.next_bits_in_use[RSI]
MOV U64 CArcCtrl.cur_bits_in_use[RSI],RCX
CMP RCX,ARC_MAX_BITS
JAE @@05
MOV RAX,RDX
SHL RAX,4
LEA RAX,U64 CArcCtrl.compress[RSI+RAX]
MOV U64 CArcCtrl.next_entry[RSI],RAX
INC RDX
CMP U64 CArcCtrl.free_limit[RSI],RDX
JNE @@25
INC RCX
MOV U64 CArcCtrl.next_bits_in_use[RSI],RCX
MOV RAX,1
SHL RAX,CL
MOV U64 CArcCtrl.free_limit[RSI],RAX
JMP @@25
@@05: INC RDX
CMP U64 CArcCtrl.free_limit[RSI],RDX
JNE @@10
MOV RDX,U64 CArcCtrl.min_table_entry[RSI]
@@10: MOV RAX,U64 CArcCtrl.hash[RSI+RDX*8]
TEST RAX,RAX
JNZ @@05
MOV RDI,RDX
SHL RDI,4
LEA RDI,U64 CArcCtrl.compress[RSI+RDI]
MOV U32 CArcCtrl.next_entry[RSI],EDI
MOVZX RBX,U16 CArcEntry.basecode[RDI]
LEA RCX,U64 CArcCtrl.hash[RSI+RBX*8]
@@15: TEST RCX,RCX
JZ @@25
MOV RAX,U64 CArcEntry.next[RCX]
CMP RDI,RAX
JNE @@20
MOV RAX,U64 CArcEntry.next[RDI]
MOV U64 CArcEntry.next[RCX],RAX
JMP @@25
@@20: MOV RCX,RAX
JMP @@15
@@25: MOV U64 CArcCtrl.free_index[RSI],RDX
@@30: POP RDI
POP RSI
POP RBP
RET1 8
}
_extern _ARC_GET_ENTRY U0 ArcGetEntry(CArcCtrl *c);
I64 ArcDetermineCompressionType(U8 *src,I64 size)
{
while (size--)
if (*src++&0x80)
return CT_8_BIT;
return CT_7_BIT;
}
U0 ArcCompressBuf(CArcCtrl *c)
//Use $LK,"CompressBuf",A="MN:CompressBuf"$() unless you are doing
//more than one buffer.
{
CArcEntry *temp,*temp1;
I64 ch,basecode;
U8 *src_ptr,*src_limit;
src_ptr=c->src_buf+c->src_pos;
src_limit=c->src_buf+c->src_size;
if (c->saved_basecode==MAX_U32)
basecode=*src_ptr++;
else
basecode=c->saved_basecode;
while (src_ptr<src_limit && c->dst_pos+c->cur_bits_in_use<=c->dst_size) {
ArcGetEntry(c);
ac_start:
if (src_ptr>=src_limit) goto ac_done;
ch=*src_ptr++;
if (temp=c->hash[basecode])
do {
if (temp->ch==ch) {
basecode=temp-&c->compress[0];
goto ac_start;
}
} while (temp=temp->next);
BFieldOrU32(c->dst_buf,c->dst_pos,basecode);
c->dst_pos+=c->cur_bits_in_use;
c->entry_used=TRUE;
temp=c->cur_entry;
temp->basecode=basecode;
temp->ch=ch;
temp1=&c->hash[basecode];
temp->next=temp1->next;
temp1->next=temp;
basecode=ch;
}
ac_done:
c->saved_basecode=basecode;
c->src_pos=src_ptr-c->src_buf;
}
U0 ArcFinishCompression(CArcCtrl *c)
{
if (c->dst_pos+c->cur_bits_in_use<=c->dst_size) {
BFieldOrU32(c->dst_buf,c->dst_pos,c->saved_basecode);
c->dst_pos+=c->next_bits_in_use;
}
}
U0 ArcExpandBuf(CArcCtrl *c)
//Use $LK,"ExpandBuf",A="MN:ExpandBuf"$() unless you know what
//you're doing.
{
U8 *dst_ptr,*dst_limit;
I64 basecode,lastcode,code;
CArcEntry *temp,*temp1;
dst_ptr=c->dst_buf+c->dst_pos;
dst_limit=c->dst_buf+c->dst_size;
while (dst_ptr<dst_limit && c->stk_ptr!=c->stk_base)
*dst_ptr++ = * -- c->stk_ptr;
if (c->stk_ptr==c->stk_base && dst_ptr<dst_limit) {
if (c->saved_basecode==MAX_U32) {
lastcode=BFieldExtU32(c->src_buf,c->src_pos,
c->next_bits_in_use);
c->src_pos+=c->next_bits_in_use;
*dst_ptr++=lastcode;
ArcGetEntry(c);
c->last_ch=lastcode;
} else
lastcode=c->saved_basecode;
while (dst_ptr<dst_limit && c->src_pos+c->next_bits_in_use<=c->src_size) {
basecode=BFieldExtU32(c->src_buf,c->src_pos,
c->next_bits_in_use);
c->src_pos+=c->next_bits_in_use;
if (c->cur_entry==&c->compress[basecode]) {
*c->stk_ptr++=c->last_ch;
code=lastcode;
} else
code=basecode;
while (code>=c->min_table_entry) {
*c->stk_ptr++=c->compress[code].ch;
code=c->compress[code].basecode;
}
*c->stk_ptr++=code;
c->last_ch=code;
c->entry_used=TRUE;
temp=c->cur_entry;
temp->basecode=lastcode;
temp->ch=c->last_ch;
temp1=&c->hash[lastcode];
temp->next=temp1->next;
temp1->next=temp;
ArcGetEntry(c);
while (dst_ptr<dst_limit && c->stk_ptr!=c->stk_base)
*dst_ptr++ = * -- c->stk_ptr;
lastcode=basecode;
}
c->saved_basecode=lastcode;
}
c->dst_pos=dst_ptr-c->dst_buf;
}
CArcCtrl *ArcCtrlNew(Bool expand,Bool seven_bit)
{
CArcCtrl *c;
c=CAlloc(sizeof(CArcCtrl));
if (expand) {
c->stk_base=MAlloc(ARC_MAX_ENTRY+1);
c->stk_ptr=c->stk_base;
}
if (seven_bit)
c->min_bits=7;
else
c->min_bits=8;
c->min_table_entry=1<<c->min_bits;
c->free_index=c->min_table_entry;
c->next_bits_in_use=c->min_bits+1;
c->free_limit=1<<c->next_bits_in_use;
c->saved_basecode=MAX_U32;
c->entry_used=TRUE;
ArcGetEntry(c);
c->entry_used=TRUE;
return c;
}
U0 ArcCtrlDel(CArcCtrl *c)
{
Free(c->stk_base);
Free(c);
}
CArcCompress *CompressBuf(U8 *src,I64 size,I64 flags=0,CTask *mem_task=NULL)
{
CArcCompress *result;
I64 size_out;
Bool seven_bit=ArcDetermineCompressionType(src,size)==CT_7_BIT;
CArcCtrl *c=ArcCtrlNew(FALSE,seven_bit);
c->src_size=size;
c->src_buf=src;
c->dst_size=(size+sizeof(CArcCompress))<<3;
c->dst_buf=CAlloc(c->dst_size>>3);
c->dst_pos=sizeof(CArcCompress)<<3;
ArcCompressBuf(c);
ArcFinishCompression(c);
if (c->src_pos==c->src_size) {
size_out=(c->dst_pos+7)>>3;
result=MAlloc(size_out,mem_task);
MemCpy(result,c->dst_buf,size_out);
if (seven_bit)
result->compression_type=CT_7_BIT;
else
result->compression_type=CT_8_BIT;
result->compressed_size=size_out;
} else {
result=MAlloc(size+sizeof(CArcCompress),mem_task);
MemCpy(&result->body,src,size);
result->compression_type=CT_NONE;
result->compressed_size=size+sizeof(CArcCompress);
}
result->expanded_size=size;
result->flags=flags;
Free(c->dst_buf);
ArcCtrlDel(c);
return result;
}
U8 *ExpandBuf(CArcCompress *r,CTask *mem_task=NULL)
{
CArcCtrl *c;
Bool seven_bit;
U8 *result=MAlloc(r->expanded_size+1,mem_task);
result[r->expanded_size]=0; //terminate
seven_bit= r->compression_type==CT_7_BIT;
if (r->compression_type==CT_NONE)
MemCpy(result,&r->body,r->expanded_size);
else {
c=ArcCtrlNew(TRUE,seven_bit);
c->src_size=r->compressed_size<<3;
c->src_pos=sizeof(CArcCompress)<<3;
c->src_buf=r;
c->dst_size=r->expanded_size;
c->dst_buf=result;
c->dst_pos=0;
ArcExpandBuf(c);
ArcCtrlDel(c);
}
return result;
}
+323
View File
@@ -0,0 +1,323 @@
U0 LinkedLstDel(U8 **_lst)
{
U8 **templ;
while (_lst) {
templ=*_lst;
Free(_lst);
_lst=templ;
}
}
U8 *LinkedLstCopy(U8 **_lst,CTask *mem_task=NULL)
{
U8 *result=NULL,**templ=&result;
while (_lst) {
templ=*templ=MAllocIdentical(_lst,mem_task);
_lst=*_lst;
}
return result;
}
I64 LinkedLstCnt(U8 **_lst)
{
I64 result=0;
while (_lst) {
result++;
_lst=*_lst;
}
return result;
}
I64 LinkedLstSize(U8 **_lst)
{
I64 result=0;
while (_lst) {
result+=MSize2(_lst);
_lst=*_lst;
}
return result;
}
U0 QueDel(CQue *root,Bool querem=FALSE) //Does not delete root
{
CQue *tempq=root->next,*tempq1;
while (tempq!=root) {
tempq1=tempq->next;
if (querem)
QueRem(tempq);
Free(tempq);
tempq=tempq1;
}
}
CQue *QueCopy(CQue *root,CTask *mem_task=NULL)
{
CQue *result=MAllocIdentical(root,mem_task),*tempq=root->next,*tempq1;
QueInit(result);
while (tempq!=root) {
tempq1=MAllocIdentical(tempq,mem_task);
QueIns(tempq1,result->last);
tempq=tempq->next;
}
return result;
}
I64 QueCnt(CQue *root) //Does not include root
{
CQue *tempq=root->next;
I64 result=0;
while (tempq!=root) {
result++;
tempq=tempq->next;
}
return result;
}
I64 QueSize(CQue *root) //Does not include root
{
CQue *tempq=root->next;
I64 result=0;
while (tempq!=root) {
result+=MSize2(tempq);
tempq=tempq->next;
}
return result;
}
CQueVectU8 *QueVectU8New(I64 min_index=0)
{
CQueVectU8 *result=MAlloc(sizeof(CQueVectU8));
result->next=result->last=result;
result->total_cnt=result->node_cnt=0;
result->min_index=min_index;
return result;
}
U0 QueVectU8Put(CQueVectU8 *v,I64 index,U8 ch)
{
CQueVectU8 *tempv;
index-=v->min_index;
if (index<0) return;
if (index<v->total_cnt) {
tempv=v;
do {
index-=tempv->node_cnt;
if (index<0) {
tempv->body[index+tempv->node_cnt]=ch;
return;
}
tempv=tempv->next;
} while (tempv!=v);
} else
index-=v->total_cnt;
while (TRUE) {
tempv=v->last;
if (tempv->node_cnt>=QUE_VECT_U8_CNT) {
tempv=MAlloc(sizeof(CQueVectU8));
tempv->node_cnt=0;
QueIns(tempv,v->last);
}
if (index--) {
tempv->body[tempv->node_cnt++]=0;
v->total_cnt++;
} else {
tempv->body[tempv->node_cnt++]=ch;
v->total_cnt++;
break;
}
}
}
U0 QueVectU8Del(CQueVectU8 *v)
{
if (v) {
QueDel(v);
Free(v);
}
}
I64 QueVectU8Get(CQueVectU8 *v,I64 index)
{
CQueVectU8 *tempv;
index-=v->min_index;
if (!(0<=index<v->total_cnt)) return 0;
tempv=v;
do {
index-=tempv->node_cnt;
if (index<0)
return tempv->body[index+tempv->node_cnt];
tempv=tempv->next;
} while (tempv!=v);
return 0;
}
CFifoU8 *FifoU8New(I64 size,CTask *mem_task=NULL)
{
CFifoU8 *f;
if (!mem_task) mem_task=Fs;
f=MAlloc(sizeof(CFifoU8),mem_task);
f->buf=MAlloc(size,mem_task);
f->mask=size-1;
f->in_ptr=0;
f->out_ptr=0;
return f;
}
U0 FifoU8Del(CFifoU8 *f)
{
Free(f->buf);
Free(f);
}
Bool FifoU8Ins(CFifoU8 *f,U8 b)
{
I64 new_in_ptr;
PUSHFD
CLI
new_in_ptr=(f->in_ptr+1)&f->mask;
if (new_in_ptr==f->out_ptr) {
POPFD
return FALSE;
} else {
f->buf[f->in_ptr]=b;
f->in_ptr=new_in_ptr;
POPFD
return TRUE;
}
}
Bool FifoU8Rem(CFifoU8 *f,U8 *_b)
{
PUSHFD
CLI
if (f->in_ptr==f->out_ptr) {
POPFD
return FALSE;
} else {
*_b=f->buf[f->out_ptr];
f->out_ptr=(f->out_ptr+1)&f->mask;
POPFD
return TRUE;
}
}
Bool FifoU8Peek(CFifoU8 *f,U8 *_b)
{
PUSHFD
CLI
if (f->in_ptr==f->out_ptr) {
POPFD
return FALSE;
} else {
*_b=f->buf[f->out_ptr];
POPFD
return TRUE;
}
}
U0 FifoU8Flush(CFifoU8 *f)
{
PUSHFD
CLI
f->out_ptr=f->in_ptr;
POPFD
}
I64 FifoU8Cnt(CFifoU8 *f)
{
I64 result;
PUSHFD
CLI
if (f->out_ptr>f->in_ptr)
result=f->mask+1-(f->out_ptr-f->in_ptr);
else
result=f->in_ptr-f->out_ptr;
POPFD
return result;
}
CFifoI64 *FifoI64New(I64 size,CTask *mem_task=NULL)
{
CFifoI64 *f;
if (!mem_task) mem_task=Fs;
f=MAlloc(sizeof(CFifoI64),mem_task);
f->buf=MAlloc(size*sizeof(I64),mem_task);
f->mask=size-1;
f->in_ptr=0;
f->out_ptr=0;
return f;
}
U0 FifoI64Del(CFifoI64 *f)
{
Free(f->buf);
Free(f);
}
Bool FifoI64Ins(CFifoI64 *f,I64 q)
{
I64 new_in_ptr;
PUSHFD
CLI
new_in_ptr=(f->in_ptr+1)&f->mask;
if (new_in_ptr==f->out_ptr) {
POPFD
return FALSE;
} else {
f->buf[f->in_ptr]=q;
f->in_ptr=new_in_ptr;
POPFD
return TRUE;
}
}
Bool FifoI64Rem(CFifoI64 *f,I64 *_q)
{
PUSHFD
CLI
if (f->in_ptr==f->out_ptr) {
POPFD
return FALSE;
} else {
*_q=f->buf[f->out_ptr];
f->out_ptr=(f->out_ptr+1)&f->mask;
POPFD
return TRUE;
}
}
Bool FifoI64Peek(CFifoI64 *f,I64 *_q)
{
PUSHFD
CLI
if (f->in_ptr==f->out_ptr) {
POPFD
return FALSE;
} else {
*_q=f->buf[f->out_ptr];
POPFD
return TRUE;
}
}
U0 FifoI64Flush(CFifoI64 *f)
{
PUSHFD
CLI
f->out_ptr=f->in_ptr;
POPFD
}
I64 FifoI64Cnt(CFifoI64 *f)
{
I64 result;
PUSHFD
CLI
if (f->out_ptr>f->in_ptr)
result=f->mask+1-(f->out_ptr-f->in_ptr);
else
result=f->in_ptr-f->out_ptr;
POPFD
return result;
}
+264
View File
@@ -0,0 +1,264 @@
//See $LK,"::/Doc/TimeDate.TXT"$
U16 mon_start_days1[12]={
0,31,59,90,120,151,181,212,243,273,304,334};
U16 mon_start_days2[12]={
0,31,60,91,121,152,182,213,244,274,305,335};
I64 YearStartDate(I64 year)
{
I64 y1=year-1,yd4000=y1/4000,yd400=y1/400,yd100=y1/100,yd4=y1/4;
return year*365+yd4-yd100+yd400-yd4000;
}
CDate Struct2Date(CDateStruct *_ds)
{
CDate cdt;
I64 i1,i2;
i1=YearStartDate(_ds->year);
i2=YearStartDate(_ds->year+1);
if (i2-i1==365)
i1+=mon_start_days1[_ds->mon-1];
else
i1+=mon_start_days2[_ds->mon-1];
cdt.date=i1+_ds->day_of_mon-1;
cdt.time=(_ds->sec10000+100*(_ds->sec100+100*(_ds->sec+60*(_ds->min+60*_ds->hour))))<<21/(15*15*3*625);
return cdt;
}
I64 DayOfWeek(I64 i)
{
i+=CDATE_BASE_DAY_OF_WEEK;
if (i>=0)
return i % 7;
else
return 6-(6-i)%7;
}
U0 Date2Struct(CDateStruct *_ds,CDate cdt)
{
I64 i,k,date=cdt.date;
_ds->day_of_week=DayOfWeek(date);
_ds->year=(date+1)*100000/CDATE_YEAR_DAYS_INT;
i=YearStartDate(_ds->year);
while (i>date) {
_ds->year--;
i=YearStartDate(_ds->year);
}
date-=i;
if (YearStartDate(_ds->year+1)-i==365) {
k=0;
while (date>=mon_start_days1[k+1] && k<11)
k++;
date-=mon_start_days1[k];
} else {
k=0;
while (date>=mon_start_days2[k+1] && k<11)
k++;
date-=mon_start_days2[k];
}
_ds->mon=k+1;
_ds->day_of_mon=date+1;
k=(625*15*15*3*cdt.time)>>21+1;
_ds->sec10000=ModU64(&k,100);
_ds->sec100=ModU64(&k,100);
_ds->sec=ModU64(&k,60);
_ds->min=ModU64(&k,60);
_ds->hour =k;
}
I64 FirstDayOfMon(I64 i)
{
CDateStruct ds;
CDate cdt=0;
cdt.date=i;
Date2Struct(&ds,cdt);
ds.day_of_mon=1;
cdt=Struct2Date(&ds);
return cdt.date;
}
I64 LastDayOfMon(I64 i)
{
CDateStruct ds;
CDate cdt=0;
cdt.date=i;
Date2Struct(&ds,cdt);
ds.mon++;
if (ds.mon==13) {
ds.mon=0;
ds.year++;
}
ds.day_of_mon=1;
cdt=Struct2Date(&ds);
return cdt.date-1;
}
I64 FirstDayOfYear(I64 i)
{
CDateStruct ds;
CDate cdt=0;
cdt.date=i;
Date2Struct(&ds,cdt);
ds.day_of_mon=1;
ds.mon=1;
cdt=Struct2Date(&ds);
return cdt.date;
}
I64 LastDayOfYear(I64 i)
{
CDateStruct ds;
CDate cdt=0;
cdt.date=i;
Date2Struct(&ds,cdt);
ds.day_of_mon=1;
ds.mon=1;
ds.year++;
cdt=Struct2Date(&ds);
return cdt.date-1;
}
I64 Bcd2Bin(U64 b)
{
I64 i,result=0;
for (i=0;i<16;i++) {
result=result*10+b>>60;
b<<=4;
}
return result;
}
U0 GetDateTimeStruct(CDateStruct *_ds)
{
I64 i;
U8 *b=_ds;
Bool is_bcd;
MemSet(_ds,0,sizeof(CDateStruct));
PUSHFD
CLI
while (LBts(&sys_semas[SYS_SEMA_SYS_DATE],0))
PAUSE
OutU8(0x70,0x0A);
do {
while (InU8(0x71) & 0x80)
PAUSE
OutU8(0x70,0);
b[2]=InU8(0x71);
OutU8(0x70,2);
b[3]=InU8(0x71);
OutU8(0x70,4);
b[4]=InU8(0x71);
OutU8(0x70,6);
b[5]=InU8(0x71);
OutU8(0x70,7);
b[6]=InU8(0x71);
OutU8(0x70,8);
b[7]=InU8(0x71);
OutU8(0x70,9);
b[8]=InU8(0x71);
OutU8(0x70,0x0A);
} while (InU8(0x71) & 0x80);
OutU8(0x70,0x0B);
if (InU8(0x71) & 4)
is_bcd=FALSE;
else
is_bcd=TRUE;
LBtr(&sys_semas[SYS_SEMA_SYS_DATE],0);
POPFD
if (is_bcd)
for (i=2;i<9;i++)
b[i]=Bcd2Bin(b[i]);
if (_ds->year>255) _ds->year=255;
_ds->year+=2000;
if (_ds->mon>12) _ds->mon=12;
if (_ds->day_of_mon>31) _ds->day_of_mon=31;
if (_ds->day_of_week>6) _ds->day_of_week=6;
if (_ds->hour>23) _ds->hour=23;
if (_ds->min>59) _ds->min=59;
if (_ds->sec>59) _ds->sec=59;
}
CDate Now()
{
CDateStruct ds;
GetDateTimeStruct(&ds);
return Struct2Date(&ds)-local_time_offset;
}
I64 Second(CDate cdt=MIN_I64)
{
CDateStruct ds;
if (cdt==MIN_I64) cdt=Now;
Date2Struct(&ds,cdt+local_time_offset);
return ds.sec;
}
I64 Minute(CDate cdt=MIN_I64)
{
CDateStruct ds;
if (cdt==MIN_I64) cdt=Now;
Date2Struct(&ds,cdt+local_time_offset);
return ds.min;
}
I64 Hour12(CDate cdt=MIN_I64)
{
CDateStruct ds;
if (cdt==MIN_I64) cdt=Now;
Date2Struct(&ds,cdt+local_time_offset);
if (ds.hour>=12)
return ds.hour-12;
else
return ds.hour;
}
I64 Hour24(CDate cdt=MIN_I64)
{
CDateStruct ds;
if (cdt==MIN_I64) cdt=Now;
Date2Struct(&ds,cdt+local_time_offset);
return ds.hour;
}
I64 Day(CDate cdt=MIN_I64)
{
CDateStruct ds;
if (cdt==MIN_I64) cdt=Now;
Date2Struct(&ds,cdt+local_time_offset);
return ds.day_of_mon;
}
I64 WeekDay(CDate cdt=MIN_I64)
{
CDateStruct ds;
if (cdt==MIN_I64) cdt=Now;
Date2Struct(&ds,cdt+local_time_offset);
return ds.day_of_week;
}
I64 Month(CDate cdt=MIN_I64)
{ //Jan is 1
CDateStruct ds;
if (cdt==MIN_I64) cdt=Now;
Date2Struct(&ds,cdt+local_time_offset);
return ds.mon;
}
I64 Year(CDate cdt=MIN_I64)
{
CDateStruct ds;
if (cdt==MIN_I64) cdt=Now;
Date2Struct(&ds,cdt+local_time_offset);
return ds.year;
}
+659
View File
@@ -0,0 +1,659 @@
Bool ChkPtr(U8 *ptr)
{
if (sys_heap_base<=ptr<=MEM_MAPPED_SPACE) {
if (*MemPageTable(ptr)&1)
return TRUE;
else
return FALSE;
} else if (ptr<sys_boot_base)
return FALSE;
else if (ptr<VGA_GRAPHIC_MEM_BASE)
return TRUE;
else
return FALSE;
}
Bool ChkCodePtr(U8 *ptr)
{
if (sys_heap_base<=ptr<=sys_heap_limit) {
if (*MemPageTable(ptr)&1)
return TRUE;
else
return FALSE;
} else if (ptr<sys_boot_base)
return FALSE;
else if (ptr<VGA_GRAPHIC_MEM_BASE)
return TRUE;
else
return FALSE;
}
Bool ChkOnStk(U8 *ptr,CTask *task=NULL)
{
Bool result=FALSE;
PUSHFD
CLI
if (task) {
if (&task->stk->stk_base<=ptr<=(&task->stk->stk_base)(U8 *)+task->stk->stk_size)
result=TRUE;
} else if (sys_heap_base<=ptr<=sys_heap_limit)
result=TRUE;
POPFD
return result;
}
I64 UnusedStk(CTask *task=NULL)
{
I64 result;
if (!task) task=Fs;
PUSHFD
CLI
if (task==Fs)
result=GetRSP()(U8 *)-(&task->stk->stk_base)(U8 *);
else
result=task->rsp(U8 *)-(&task->stk->stk_base)(U8 *);
POPFD
return result;
}
U8 *Caller(I64 num=1)
//Returns the addr of the fun
//which called this one, or the caller
//of the caller, etc.
{
U8 **rbp=GetRBP,**ptr;
while (num--) {
if (rbp>=*rbp)
return NULL;
rbp=*rbp;
if (!ChkOnStk(rbp,Fs))
return NULL;
}
ptr=rbp+1;
return *ptr;
}
U8 *TaskCaller(CTask *task=NULL,I64 num=0,Bool saved_context=FALSE)
{
U8 **ptr,**rbp,**rsp;
if (!task) task=Fs;
if (!saved_context && task==Fs)
return Caller(num+1);
if (!TaskValidate(task))
return NULL;
rbp=task->rbp;
rsp=task->rsp;
if (num) {
while (ChkOnStk(rbp,task)) {
ptr=rbp+1;
if (! --num)
return *ptr;
if (rbp>=*rbp)
break;
rbp=*rbp;
}
return NULL;
} else {
if (task->rip==_RET)
return *rsp;
else
return task->rip;
}
}
#define STK_REP_LEN 32
U0 StkRep(CTask *task=NULL)
//Reports whats on the stk
{
I64 i,j,addr,
**rbp,**rsp,*my_rsp[STK_REP_LEN];
CHashTable *old_hash=Fs->hash_table;
if (!task) task=Fs;
if (!TaskValidate(task))
return;
PUSHFD
CLI
if (task==Fs) {
rbp=GetRBP;
rsp=rbp+3;
rbp=*rbp;
} else {
rsp=task->rsp;
rbp=task->rbp;
}
if (task->rip==_RET)
addr=*rsp;
else
addr=task->rip;
MemCpy(my_rsp,rsp,STK_REP_LEN*sizeof(U8 *));
POPFD
Fs->hash_table=task->hash_table;
for (i=0;i<STK_REP_LEN;i++) {
"%08X [RSP+%04X]: %016X ",rsp+i,
i*sizeof(U8 *),my_rsp[i];
while (TRUE) {
if (!(&task->stk->stk_base<=rbp<(&task->stk->stk_base)(U8 *)+task->stk->stk_size))
break;
j=rbp-rsp;
if (j>=i)
break;
addr=my_rsp[j+1];
if (rbp>=my_rsp[j])
break;
rbp=my_rsp[j];
}
if (my_rsp[i]==addr)
"$$RED$$";
"%P$$FG$$\n",my_rsp[i];
}
NewLine;
Fs->hash_table=old_hash;
}
U0 CallerRep(U8 **rbp=NULL,CTask *task=NULL)
//Prints a report of calling routines
{
I64 **ptr;
if (!task) task=Fs;
if (!rbp) {
if (task==Fs)
rbp=GetRBP;
else
rbp=task->rbp;
}
"CallerRep:\n";
while (ChkOnStk(rbp,task)) {
ptr=rbp+1;
"%08X:%08tX:%P\n",ptr,*ptr,*ptr;
if (rbp>=*rbp)
break;
rbp=*rbp;
}
}
U0 D(U8 *addr,I64 cnt=0x80,Bool show_offset=TRUE)
//Dump mem, showing offsets.
//See $LK,"DocD",A="MN:DocD"$() for a live dump.
{
I64 i,j,ch;
U8 *ptr=addr;
while (cnt) {
if (show_offset)
"%08X ",ptr-addr;
else
"%010X ",ptr;
if (cnt>16)
j=16;
else
j=cnt;
for (i=0;i<j;i++)
"%02X ",ptr[i];
for (;i<16;i++)
" ";
for (i=0;i<j;i++) {
ch=ptr[i];
if (ch<CH_SHIFT_SPACE || ch==CH_BACKSPACE)
ch='.';
'' ch;
if (ch=='$$')
'' ch;
}
NewLine;
cnt-=j;
ptr+=j;
}
}
U0 Dm(U8 *addr,I64 cnt=0x80)
//Show mem addr, not offsets
{
D(addr,cnt,FALSE);
}
U0 Da(U8 **addr,I64 cnt=0x10)
//Dump mem, showing symbolic addresses
{
while (cnt-->0) {
"%08X:%08X,%P\n",addr,*addr,*addr;
addr++;
}
}
U0 RawPrint(I64 mS=100,U8 *fmt,...)
//Print using $LK,"Raw",A="MN:Raw"$ screen
//output for a length of time.
//$BK,1$Your heap must be good.$BK,0$
{
U8 *buf=SPrintJoin(NULL,fmt,argc,argv);
Bool old_raw,old_input_filter;
PUSHFD
CLI
old_raw=Raw(ON);
old_input_filter=LBtr(&Fs->task_flags,TASKf_INPUT_FILTER_TASK);
"%s",buf;
BusyWait(mS<<10);
POPFD
LBEqu(&Fs->task_flags,TASKf_INPUT_FILTER_TASK,old_input_filter);
Raw(old_raw);
Free(buf);
}
U0 RawD(I64 mS=100,U8 *addr,I64 cnt=0x80)
//Dumps a block of mem using $LK,"Raw",A="MN:Raw"$
//screen output for a fixed length
//of time.
{
Bool old_raw,old_input_filter;
PUSHFD
CLI
old_raw=Raw(ON);
old_input_filter=LBtr(&Fs->task_flags,TASKf_INPUT_FILTER_TASK);
D(addr,cnt);
BusyWait(mS<<10);
POPFD
LBEqu(&Fs->task_flags,TASKf_INPUT_FILTER_TASK,old_input_filter);
Raw(old_raw);
}
U0 RawDm(I64 mS=100,U8 *addr,I64 cnt=0x80)
//Dumps a block of mem using $LK,"Raw",A="MN:Raw"$
//screen output for a fixed length
//of time.
{
Bool old_raw,old_input_filter;
PUSHFD
CLI
old_raw=Raw(ON);
old_input_filter=LBtr(&Fs->task_flags,TASKf_INPUT_FILTER_TASK);
Dm(addr,cnt);
BusyWait(mS<<10);
POPFD
LBEqu(&Fs->task_flags,TASKf_INPUT_FILTER_TASK,old_input_filter);
Raw(old_raw);
}
I64 *TaskRegAddr(CTask *task,I64 reg_num)
{
switch (reg_num) {
case REG_RAX: return &task->rax;
case REG_RCX: return &task->rcx;
case REG_RDX: return &task->rdx;
case REG_RBX: return &task->rbx;
case REG_RSP: return &task->rsp;
case REG_RBP: return &task->rbp;
case REG_RSI: return &task->rsi;
case REG_RDI: return &task->rdi;
case 8 : return &task->r8;
case 9 : return &task->r9;
case 10: return &task->r10;
case 11: return &task->r11;
case 12: return &task->r12;
case 13: return &task->r13;
case 14: return &task->r14;
case 15: return &task->r15;
}
return NULL;
}
#define RAWDR_COL 40
U0 RawDr(CTask *task=NULL)
{
I64 i,j,old_col=sys_raw_col;
Bool old_raw=Raw(ON);
U8 buf[200];
if (!task) task=Fs;
for (i=0;i<16;i++) {
sys_raw_col=i*text_cols+RAWDR_COL;
"º%3Z:%016X\n",i,"ST_U64_REGS",*TaskRegAddr(task,i);
}
sys_raw_col=i++*text_cols+RAWDR_COL;
"ºRIP:%016X\n",task->rip;
sys_raw_col=i++*text_cols+RAWDR_COL;
"º%-*tp\n",text_cols-(RAWDR_COL+1)-1,Fs->rip;
sys_raw_col=i++*text_cols+RAWDR_COL;
'º';
if (Bt(&sys_run_level,RLf_COMPILER)) {
j=Fs->rip;
Ui(buf,&j,,,TRUE);
"%s",buf;
} else
NewLine;
sys_raw_col=i*text_cols+RAWDR_COL;
'È';
for (j=0;j<text_cols-RAWDR_COL-1;j++)
'Í';
sys_raw_col=old_col;
Raw(old_raw);
}
U0 Dr(CTask *task=NULL)
{//Dump regs
I64 i;
if (!task) task=Fs;
for (i=0;i<16;i++)
"%3Z:%016X\n",i,"ST_U64_REGS",*TaskRegAddr(task,i);
"RIP:%016X\n",task->rip;
}
U0 OverRideSingleUserSwap()
{//You never need this, probably.
Bool old_single=SingleUser(OFF);
Yield;
SingleUser(old_single);
}
U8 *SysMGetS(I64)
{
U8 buf[512];
GetS(buf,512,FALSE);
return StrNew(buf);
}
CBpt *BptFind(U8 *needle_addr,CTask *haystack_task=NULL,Bool rem=FALSE)
{
CBpt *result=NULL,*tempb,*tempb1,*tempb2;
if (!haystack_task) haystack_task=Fs;
PUSHFD
CLI
tempb1=&haystack_task->bpt_lst;
tempb=haystack_task->bpt_lst;
while (tempb) {
tempb2=tempb->next;
if (tempb->addr==needle_addr) {
result=tempb;
if (rem)
tempb1->next=tempb2;
else
tempb1=&tempb->next;
} else
tempb1=&tempb->next;
tempb=tempb2;
}
POPFD
return result;
}
Bool BptS(U8 *addr,CTask *task=NULL,Bool live=TRUE)
{//Set breakpoint
CBpt *tempb;
Bool result=TRUE;
if (!task) task=Fs;
PUSHFD
CLI
if (!(tempb=BptFind(addr,task,FALSE))) {
tempb=CAlloc(sizeof(CBpt),task);
tempb->addr=addr;
tempb->val=*addr;
result=FALSE;
tempb->next=task->bpt_lst;
task->bpt_lst=tempb;
if (task==Fs && live)
*addr=OC_BPT;
}
POPFD
return result;
}
Bool BptR(U8 *addr,CTask *task=NULL,Bool live=TRUE,Bool rem=TRUE)
{//Rem breakpoint
CBpt *tempb;
Bool result=FALSE;
if (!task) task=Fs;
PUSHFD
CLI
if (tempb=BptFind(addr,task,rem)) {
if (task==Fs && live)
*tempb->addr=tempb->val;
result=TRUE;
if (rem)
Free(tempb);
}
POPFD
return result;
}
Bool B(U8 *addr,CTask *task=NULL,Bool live=TRUE)
{//Toggle breakpoint
//Returns TRUE if removed
Bool result=FALSE;
PUSHFD
CLI
if (BptFind(addr,task,FALSE)) {
BptR(addr,task,live,TRUE);
result=TRUE;
} else
BptS(addr,task,live);
POPFD
return result;
}
I64 B2(CTask *task=NULL,Bool live=TRUE)
{ //Rem all breakpoints
//Returns cnt of removed
I64 result=0;
CBpt *tempb,*tempb1;
if (!task) task=Fs;
PUSHFD
CLI
tempb=task->bpt_lst;
task->bpt_lst=NULL;
while (tempb) {
tempb1=tempb->next;
if (task==Fs && live)
*tempb->addr=tempb->val;
Free(tempb);
tempb=tempb1;
result++;
}
POPFD
return result;
}
U0 G(U8 *ip=INVALID_PTR,CTask *task=NULL)
//Go
{
if (!task) task=Fs;
if (ip!=INVALID_PTR) task->rip=ip;
if (BptFind(task->rip,task))
"\nDo one of the following, first:\n"
">S;\t\t\t//Single step\n"
">B2;\t\t\t//Clear all break points\n"
">G2;\t\t\t//Clear all break points and Go\n\n"
"After resuming, <CTRL-ALT-T> changes focus task\n"
"After resuming, <CTRL-ALT-F> flushes screen VGA cache\n";
else {
LBtr(&task->task_flags,TASKf_DISABLE_BPTS);
LBtr(&task->rflags,RFLAGf_TRAP);//No single step
Suspend(task,FALSE);
if (task==Fs) {
if (IsDbg && task->next_lex!=&task->next_lex) {
"Exit Dbg\n";
Btr(&task->last_lex->flags,Lf_PMT);
}
} else
Exit;
}
}
U0 G2(U8 *ip=INVALID_PTR,CTask *task=NULL)
//Rem all breakpoints and Go.
{
if (!task) task=Fs;
B2(task);
if (ext[EXT_WIN_FOCUS])
CallExtNum(EXT_WIN_FOCUS,sys_dbg_focus_task);
VGAFlush;
G(ip,task);
}
public U0 S(U8 *ip=INVALID_PTR,CTask *task=NULL) //Single-step.
{ //Single step
if (!task) task=Fs;
PUSHFD
CLI
if (ip!=INVALID_PTR) task->rip=ip;
LBts(&task->task_flags,TASKf_DISABLE_BPTS);
LBts(&task->rflags,RFLAGf_TRAP);
Suspend(task,FALSE);
if (task==Fs) {
if (IsDbg) {
if (task->next_lex!=&task->next_lex)
Btr(&task->last_lex->flags,Lf_PMT);
}
} else
Exit;
POPFD
}
U0 DbgHelp()
{
"\n"
"The cmd line is basically the same as normal. Here are some common\n"
"debugging commands.\n\n"
">EdLite(\"FileName\");\t\t//Edit file.\n"
">D(0x100000);\t\t\t//Dump page tables.\n"
">Dm(0x100000);\t\t\t//Dump page tables.\n"
">Dm(Fs,sizeof(CTask));\t\t//Dump current task record.\n"
">ClassRep(Fs,\"CTask\",1);\t//Dump current task record.\n"
">ClassRep(Fs,,1);\t\t//(It knows lastclass.)\n"
">CallerRep;\t\t\t//Stack trace report.\n"
">Da(_RSP);\t\t\t//Dump stk.\n"
">Dr;\t\t\t\t//Dump Regs.\n"
">1+2*3+&Print;\t\t\t//Show calculation result.\n"
">*(0x70000)(I64 *)=0x123456789;\t//Assign value to 0x70000-0x70007.\n"
">_RAX=0x1234;\t\t\t//Set RAX to 0x1234.\n"
">_RIP=&SysThrowBreak;\t\t//Set RIP.\n"
">I64 i;\t\t\t\t//Declare variable.\n"
">i=_RCX+_RDX;\t\t\t//Assign to variable.\n"
">U(&Print+0x8);\t\t\t//Unassemble Print.\n"
">Uf(\"Print\");\t\t\t//Unassembler function \"Print\".\n"
">Man(\"Print\");\t\t\t//Edit Src for \"Print\".\n"
">E(_RIP);\t\t\t//Edit Src Code.\n"
">Fix;\t\t\t\t//Edit Last Err Src Code.\n"
">B(&Main+0x20);\t\t\t//Toggle break point.\n"
">B2;\t\t\t\t//Clear all break points.\n"
">S;\t\t\t\t//Single step.\n"
">G;\t\t\t\t//Resume execution.\n"
">G2;\t\t\t\t//B2;VGAFlush;WinFocus;G;\n"
">Exit;\t\t\t\t//Exit (kill) task.\n\n"
"After resuming, <CTRL-ALT-T> changes focus task.\n"
"After resuming, <CTRL-ALT-F> flushes screen VGA cache.\n\n";
}
U0 Dbg2()
{
Bool old_win_inhibit,old_waiting_msg;
I64 i,old_dbg_mgets;
U8 buf[200];
if (IsRaw) {
i=Fs->rip;
Ui(buf,&i);
"%s",buf;
} else
U(Fs->rip,1);
old_waiting_msg=LBtr(&Fs->task_flags,TASKf_AWAITING_MSG);
old_win_inhibit=Fs->win_inhibit;
Fs->win_inhibit=WIG_USER_TASK_DFT;
sys_focus_task=Fs;
sys_cur_scan_code=0;
old_dbg_mgets=fp_mgets;
fp_mgets=&SysMGetS;
while (!mouse_install_attempts)
OverRideSingleUserSwap;
UserTaskCont;
fp_mgets=old_dbg_mgets;
Fs->win_inhibit=old_win_inhibit;
LBEqu(&Fs->task_flags,TASKf_AWAITING_MSG,old_waiting_msg);
}
U0 Fault3(I64 fault_num,I64 fault_err_code)
{
nounusedwarn fault_err_code;
Bool was_in_dbg;
PUSHFD
CLI
was_in_dbg=InDbg(ON);
if (Gs->num && mp_crash) {
mp_cnt=1;
mp_crash->cpu_num=Gs->num;
mp_crash->task=Fs;
mp_crash->msg=sys_dbg_msg;
mp_crash->msg_num=sys_dbg_msg_num;
MPInt(I_MP_CRASH,0);
SysHlt;
}
"\n\tTempleOS Debugger\n\n"
">Help;\t//For help.\n\n";
Beep(500,TRUE);
if (fault_num==I_DBG) {
if (sys_dbg_msg) {
"\n!!! %s",sys_dbg_msg;
if (sys_dbg_msg_num)
"%016X",sys_dbg_msg_num;
" !!!\n\n";
}
}
CallerRep;
Dbg2;
InDbg(was_in_dbg);
POPFD
}
U0 Fault2(I64 fault_num,I64 fault_err_code) //Called from $LK,"Fault2",A="FF:::/Kernel/Interrupts.CPP,Fault2"$
{
//$BK,1$Be careful not to swap-out and ruin the saved context$BK,0$
Bool was_raw,was_single_user,was_silent;
I64 i,old_raw_flags=sys_raw_flags;
if (fault_num==I_DIVIDE_BY_ZERO) {
"RIP:%P\n",Fs->rip;
throw('DivZero');
}
was_single_user=SingleUser(ON);
if (!IsDbg)
sys_dbg_focus_task=sys_focus_task;
sys_focus_task=NULL;
if (fault_num==I_BPT)
Fs->rip--;
was_raw=Raw(ON);
was_silent=Silent(OFF);
sys_raw_flags|=RWF_SHOW_DOLLAR|RWF_SCROLL;
"Task \"";
"%s",Fs->task_title;
"\"\n";
"Fault:0x%02X %Z\t\tErr Code:%08X\n",fault_num,fault_num,"ST_INT_NAMES",fault_err_code;
"RIP:%08X",Fs->rip; //Sometimes crashes on %p, so do this first
":%p RSP:%08X\n",Fs->rip,Fs->rsp;
if (fault_num==I_PAGE_FAULT) {
MOV_RAX_CR2
i=GetRAX;
"Fault Addr:%08X:%p\n",i,i;
}
Fault3(fault_num,fault_err_code);
Silent(was_silent);
Raw(was_raw);
sys_raw_flags=old_raw_flags;
SingleUser(was_single_user);
if (LBtr(&Fs->task_flags,TASKf_KILL_AFTER_DBG))
Exit;
}
U0 Dbg(U8 *msg=NULL,I64 msg_num=0)
//Enters the debugger. Can be used as a panic.
{
PUSHFD
CLI
sys_dbg_msg=msg;
sys_dbg_msg_num=msg_num;
INT I_DBG
POPFD
}
+145
View File
@@ -0,0 +1,145 @@
CHashDefineStr *DefineLoad(U8 *name,U8 *st)
{
CHashDefineStr *temph=CAlloc(sizeof(CHashDefineStr));
temph->type=HTT_DEFINE_STR;
temph->str=StrNew(name);
temph->data=StrNew(st);
temph->cnt=-1;
temph->src_link=MPrint("AD:0x%X",Caller);
HashAdd(temph,Fs->hash_table);
return temph;
}
CHashDefineStr *DefineLstLoad(U8 *name,U8 *st)
{ //Not especially efficient but handy.
I64 cnt=0;
U8 *ptr,**lst;
CHashDefineStr *temph=CAlloc(sizeof(CHashDefineStr));
temph->type=HTT_DEFINE_STR;
temph->str=StrNew(name);
temph->src_link=MPrint("AD:0x%X",Caller);
ptr=st;
while (*ptr) {
if (*ptr!='@')
cnt++;
while (*ptr++);
}
temph->data=MAlloc(ptr+1-st);
MemCpy(temph->data,st,ptr+1-st);
temph->cnt=cnt;
lst=temph->sub_lst=MAlloc(cnt*sizeof(U8 *));
ptr=st;
while (*ptr) {
if (*ptr!='@')
*lst++=ptr;
while (*ptr++);
}
HashAdd(temph,Fs->hash_table);
return temph;
}
U0 UndefinedDefine(U8 *name)
{
ST_ERR_ST "Undefined Define: '%s'.\n",name;
throw('UndefDef');
}
U8 *Define(U8 *name)
{
CHashDefineStr *temph;
if (temph=HashFind(name,Fs->hash_table,HTT_DEFINE_STR))
return temph->data;
else if (name)
UndefinedDefine(name);
else
return NULL;
}
U8 *DefineSub(I64 sub,U8 *name)
{
CHashDefineStr *temph;
if (temph=HashFind(name,Fs->hash_table,HTT_DEFINE_STR)) {
if (0<=sub<temph->cnt)
return temph->sub_lst[sub];
else
return NULL;
} else if (name)
UndefinedDefine(name);
else
return NULL;
}
I64 DefineCnt(U8 *name)
{
CHashDefineStr *temph;
if (temph=HashFind(name,Fs->hash_table,HTT_DEFINE_STR))
return temph->cnt;
else if (name)
UndefinedDefine(name);
else
return -1;
}
I64 DefineMatch(U8 *needle,U8 *haystack_lst_name,I64 flags=0)
{
return LstMatch(needle,Define(haystack_lst_name),flags);
}
U0 DefinePrint(U8 *name,U8 *src,...)
{
U8 *buf=SPrintJoin(NULL,src,argc,argv);
DefineLoad(name,buf);
Free(buf);
}
U0 SysDefinesLoad()
{
DefineLstLoad("ST_OFF_ON","Off\0On\0");
DefineLstLoad("ST_HTT_TYPES","ExportSysSym\0ImportSysSym\0DefineStr\0GlbVar\0Class\0"
"IntType\0Funct\0Word\0DictWord\0KeyWord\0AsmKeyWord\0OpCode\0Reg\0"
"File\0Module\0HelpFile\0Frame Ptr\0"
" \0 \0 \0 \0 \0 \0"
"Private\0Public\0Export\0Import\0Imm\0Goto\0Res\0Unres\0Local\0");
DefineLstLoad("ST_DAYS_OF_WEEK","Sunday\0Monday\0Tuesday\0Wednesday\0"
"Thursday\0Friday\0Saturday\0");
DefineLstLoad("ST_MONTHS","January\0February\0March\0April\0May\0"
"June\0July\0August\0September\0October\0November\0December\0");
DefineLstLoad("ST_FILE_ATTRS","R\0H\0S\0V\0D\0A\0 \0 \0X\0Y\0T\0Z\0C\0F\0");
DefineLstLoad("ST_FILE_UTIL_FLAGS","r\0d\0i\0a\0c\0R\0p\0m\0x\0s\0"
"D\0F\0T\0S\0A\0J\0G\0Z\0O\0P\0f\0l\0lb\0la\0");
DefineLstLoad("ST_BLKDEV_TYPES","NULL\0RAM\0ATA\0ATAPI\0");
DefineLstLoad("ST_PRT_TYPES","NULL\0REDSEA\0FAT32\0ISO9660\0ISO13490\0ISO13346\0NTFS\0UNKNOWN\0");
DefineLstLoad("ST_COLORS","BLACK\0BLUE\0GREEN\0CYAN\0"
"RED\0PURPLE\0BROWN\0LTGRAY\0DKGRAY\0LTBLUE\0LTGREEN\0"
"LTCYAN\0LTRED\0LTPURPLE\0YELLOW\0WHITE\0");
DefineLstLoad("ST_INT_NAMES",
"Divide Error\0SingleStep\0NMI\0Breakpoint\0Overflow\0BOUND Range Exceeded\0Invalid Opcode\0No Math Coprocessor\0"
"Double Fault\0Coprocessor Segment Fault\0Invalid TASK\0Segment Not Present\0Stk Segment Fault\0General Protection\0Page Fault\0 \0"
"Math Fault\0Alignment Check\0Machine Check\0SIMD Exception\0 \0 \0 \0 \0"
" \0 \0 \0 \0 \0 \0 \0 \0"
" \0 \0 \0 \0 \0 \0 \0 \0"
" \0 \0 \0 \0 \0 \0 \0 \0"
"MP Crash\0Wake\0Dbg\0");
}
U8 *Color2Text(U8 *buf,CColorROPU32 c)
{
if (0<=c.c0.color<16)
StrCpy(buf,DefineSub(c.c0.color,"ST_COLORS"));
else if (c.c0.color==COLOR_TRANSPARENT)
StrCpy(buf,"TRANSPARENT");
else
StrCpy(buf,"INVALID");
if (c&ROPF_DITHER) {
CatPrint(buf,"/");
if (0<=c.c1.color<16)
CatPrint(buf,DefineSub(c.c1.color,"ST_COLORS"));
else if (c.c1.color==COLOR_TRANSPARENT)
CatPrint(buf,"TRANSPARENT");
else
CatPrint(buf,"INVALID");
}
return buf;
}
+279
View File
@@ -0,0 +1,279 @@
U0 RawPutChar(I64 ch)
{
/* This is for RAW output during boot
before the window mgr is running
and for the debugger.
See $LK,"GrUpdateForegroundOfText",A="MN:GrUpdateForegroundOfText"$ for
the normal screen text output routine.
See also $LK,"GrUpdateScreen",A="MN:GrUpdateScreen"$().
*/
Bool old_preempt=Preempt(OFF);
I64 i,row,col;
U8 *ptr,*ptr1,*ptr2;
if (!(sys_raw_flags&RWF_SHOW_DOLLAR)) {
if (ch=='$$') {
if (sys_raw_flags&RWF_IN_DOLLAR) {
sys_raw_flags&=~RWF_IN_DOLLAR;
if (!(sys_raw_flags & RWF_LAST_DOLLAR)) {
sys_raw_flags&=~RWF_LAST_DOLLAR;
Preempt(old_preempt);
return;
}
} else {
sys_raw_flags|=RWF_IN_DOLLAR|RWF_LAST_DOLLAR;
Preempt(old_preempt);
return;
}
}
sys_raw_flags&=~RWF_LAST_DOLLAR;
if (sys_raw_flags&RWF_IN_DOLLAR) {
Preempt(old_preempt);
return;
}
}
if (ch=='\t') {
RawPutChar(CH_SPACE);
while (sys_raw_col & 7)
RawPutChar(CH_SPACE);
} else if (ch==CH_BACKSPACE) {
sys_raw_col--;
RawPutChar(CH_SPACE);
sys_raw_col--;
} else if (ch=='\n') {
RawPutChar(CH_SPACE);
while (sys_raw_col % text_cols)
RawPutChar(CH_SPACE);
} else if (Bt(chars_bitmap_displayable,ch)) {
row=sys_raw_col/text_cols%text_rows;
col=sys_raw_col%text_cols;
if (text_mode) {
if (sys_raw_flags&RWF_SCROLL && sys_raw_col && !row && !col) {
MemCpy(VGA_TEXT_MEM_BASE,VGA_TEXT_MEM_BASE+text_cols,
text_cols*(text_rows-1)*2);
MemSet(VGA_TEXT_MEM_BASE+text_cols*(text_rows-1)*2,0,text_cols*2);
sys_raw_col-=text_cols;
row=text_rows-1;
}
ptr=VGA_TEXT_MEM_BASE+(row*text_cols+col)*2;
ptr[0]=ch;
ptr[1]=BLACK<<4+WHITE;
} else {
OutU8(VGA_SC_INDEX,VGA_MAP_MASK);
OutU8(VGA_SC_DATA,0x0F); //All planes -- WHITE
if (sys_raw_flags&RWF_SCROLL && sys_raw_col && !row && !col) {
//Scroll cached image
MemCpy(sys_raw_screen_image,sys_raw_screen_image+gr_width*FONT_HEIGHT>>3,
gr_width*(gr_height-FONT_HEIGHT)>>3);
MemSet(sys_raw_screen_image+gr_width*(gr_height-FONT_HEIGHT)>>3,0,gr_width*FONT_HEIGHT>>3);
MemCpy(VGA_GRAPHIC_MEM_BASE,sys_raw_screen_image,gr_width*gr_height>>3);
sys_raw_col-=text_cols;
row=text_rows-1;
}
PUSHFD
CLI
ptr=ptr1=col+row*gr_width;
ptr+=VGA_GRAPHIC_MEM_BASE;
ptr1+=sys_raw_screen_image; //Write to cached image as well
ptr2=&gr_font[(ch&255)*FONT_HEIGHT];
for (i=0;i<FONT_HEIGHT;i++) {
*ptr=*ptr1=reverse_bits_table[*ptr2++];
ptr+=gr_width>>3;
ptr1+=gr_width>>3;
}
POPFD
}
sys_raw_col++;
}
Preempt(old_preempt);
}
U0 VGAFlush()
{
LBts(&sys_semas[SYS_SEMA_FLUSH_VGA_IMAGE],0);
}
U0 WinDerivedValsUpdate(CTask *task=NULL)
{
if (!task) task=Fs;
//Assert: This is called with TASKLf_TASK_LOCK set
PUSHFD
CLI
task->win_width =task->win_right-task->win_left+1;
task->win_height=task->win_bottom-task->win_top+1;
//Inside the Border
task->pix_left =FONT_WIDTH*task->win_left;
task->pix_right =FONT_WIDTH*(task->win_right+1)-1;
task->pix_width =task->pix_right-task->pix_left+1;
task->pix_top =FONT_HEIGHT*task->win_top;
task->pix_bottom=FONT_HEIGHT*(task->win_bottom+1)-1;
task->pix_height=task->pix_bottom-task->pix_top+1;
//Outside the border
if (Bt(&task->display_flags,DISPLAYf_NO_BORDER)) {
task->border_pix_left =task->pix_left;
task->border_pix_right =task->pix_right;
task->border_pix_top =task->pix_top;
task->border_pix_bottom=task->pix_bottom;
} else {
task->border_pix_left =task->pix_left-FONT_WIDTH;
task->border_pix_right =task->pix_right+FONT_WIDTH;
task->border_pix_top =task->pix_top-FONT_HEIGHT;
task->border_pix_bottom=task->pix_bottom+FONT_HEIGHT;
}
POPFD
}
Bool KDRawDisplayPutKey(I64 ch,I64)
{
if (IsRaw) {
RawPutChar(ch);
return TRUE;
} else
return FALSE;
}
Bool KDRawDisplayPutS(U8 *st)
{
I64 ch;
if (IsRaw) {
while (ch=*st++)
RawPutChar(ch);
return TRUE;
} else
return FALSE;
}
Bool KDInputFilterPutKey(I64 ch,I64 scancode)
{
Bool old_preempt;
if (Bt(&Fs->task_flags,TASKf_INPUT_FILTER_TASK)) {
old_preempt=Preempt(OFF);
Msg(MSG_KEY_DOWN,ch,scancode);
Preempt(old_preempt);
return TRUE;
} else
return FALSE;
}
Bool KDInputFilterPutS(U8 *st)
{
I64 ch;
Bool old_preempt;
if (Bt(&Fs->task_flags,TASKf_INPUT_FILTER_TASK)) {
old_preempt=Preempt(OFF);
while (ch=*st++)
Msg(MSG_KEY_DOWN,ch,0);
Preempt(old_preempt);
return TRUE;
} else
return FALSE;
}
U0 PutKey(I64 ch=0,I64 sc=0)
{ //See $LK,"PutKeyHandling",A="FA:::/Doc/KeyBoard.TXT,PutKeyHandling"$
CKeyDev *tempp;
if (ch||sc) {
tempp=sys_put_key_root.next;
if (!Bt(&Fs->display_flags,DISPLAYf_SILENT)) {
if (sys_cur_scan_code & SCF_SCROLL && sys_focus_task==Fs)
while (sys_cur_scan_code & SCF_SCROLL)
Yield; //Wait on SCROLL LOCK Key
while (tempp!=&sys_put_key_root) {
if ((!(sc & SCF_KEY_DESC) || tempp->flags & KDF_HAS_DESCS) &&
(*tempp->put_key)(ch,sc))
break;
tempp=tempp->next;
}
}
}
}
U0 PutChars(U64 ch)
{ //You can pack multiple chars into a U64.
while (ch) {
PutKey(ch&255,0);
ch>>=8;
}
}
U0 PutS(U8 *st)
{ //Use $LK,"Print",A="MN:Print"$(). See $LK,"PutKeyHandling",A="FA:::/Doc/KeyBoard.TXT,PutKeyHandling"$
I64 ch;
U8 *ptr;
Bool cont=TRUE;
if (!st) return;
CKeyDev *tempp=sys_put_key_root.next;
if (!Bt(&Fs->display_flags,DISPLAYf_SILENT)) {
if (sys_cur_scan_code & SCF_SCROLL && sys_focus_task==Fs)
while (sys_cur_scan_code & SCF_SCROLL)
Yield;
while (cont && tempp!=&sys_put_key_root) {
if (tempp->put_s) {
if ((*tempp->put_s)(st))
break;
} else {
ptr=st;
while (ch=*ptr++)
if ((*tempp->put_key)(ch,0))
cont=FALSE;
}
tempp=tempp->next;
}
}
}
U0 SetKeyDesc(U8 *fmt,...)
{
I64 i;
U8 *buf=SPrintJoin(NULL,fmt,argc,argv);
StrCpy(key_desc,buf);
key_handler=Caller;
Free(buf);
for (i=0;i<5;i++)
Yield; //This makes KeyMap work better
}
U0 SetCtrlAltLetCB(U8 ch,U0 (*fp_handler)(I64 sc),U8 *desc,Bool in_irq=FALSE)
{
ch=ToUpper(ch)-'A';
if (ch<26) {
fp_ctrl_alt_let_cbs[ch]=fp_handler;
Free(ctrl_alt_let_descs[ch]);
ctrl_alt_let_descs[ch]=AStrNew(desc);
BEqu(&ctrl_alt_let_in_irq_flags,ch,in_irq);
}
}
CKeyDev *KeyDevAdd(Bool (*fp_put_key)(I64 ch,I64 sc),Bool (*fp_puts)(U8 *st),I64 priority,Bool key_descs=FALSE)
//Places hook in StdOut chain
{ //See $LK,"PutKeyHandling",A="FA:::/Doc/KeyBoard.TXT,PutKeyHandling"$
Bool old_preempt=Preempt(OFF);
CKeyDev *tempp,*tempp1=sys_put_key_root.last;
tempp=ACAlloc(sizeof(CKeyDev));
tempp->put_key=fp_put_key;
tempp->put_s=fp_puts;
tempp->priority=priority;
if (key_descs)
tempp->flags|=KDF_HAS_DESCS;
while (tempp1->priority>priority)
tempp1=tempp1->last;
QueIns(tempp,tempp1);
Preempt(old_preempt);
return tempp;
}
U0 KeyDevRem(CKeyDev *tempp)
{
Bool old_preempt=Preempt(OFF);
QueRem(tempp);
Preempt(old_preempt);
Free(tempp);
}
+31
View File
@@ -0,0 +1,31 @@
//See $LK,"::/Doc/Acknowledgements.TXT"$.
#define ATA_NOP 0x00
#define ATA_DEV_RST 0x08
#define ATA_PACKET 0xA0
#define ATA_READ_NATIVE_MAX 0xF8
#define ATA_READ_NATIVE_MAX_EXT 0x27
#define ATA_SET_MAX 0xF9
#define ATA_SET_MAX_EXT 0x37
#define ATA_READ_MULTI 0xC4
#define ATA_READ_MULTI_EXT 0x29
#define ATA_WRITE_MULTI 0xC5
#define ATA_WRITE_MULTI_EXT 0x39
#define ATA_ID_DEV 0xEC
#define ATAS_ERR 0x01
#define ATAS_DRQ 0x08
#define ATAS_DF 0x20
#define ATAS_DRDY 0x40
#define ATAS_BSY 0x80
#define ATAR0_DATA 0
#define ATAR0_FEAT 1
#define ATAR0_NSECT 2
#define ATAR0_SECT 3
#define ATAR0_LCYL 4
#define ATAR0_HCYL 5
#define ATAR0_SELECT 6
#define ATAR0_STAT 7
#define ATAR0_CMD 7
#define ATAR1_CTRL 2
+726
View File
@@ -0,0 +1,726 @@
Bool BlkDevLock(CBlkDev *bdev)
{
BlkDevChk(bdev);
while (bdev->lock_fwding)
bdev=bdev->lock_fwding;
if (!Bt(&bdev->locked_flags,BDlf_LOCKED) || bdev->owning_task!=Fs) {
while (LBts(&bdev->locked_flags,BDlf_LOCKED))
Yield;
bdev->owning_task=Fs;
return TRUE;
} else
return FALSE;
}
Bool PrtLock(CPrt *p)
{
PrtChk(p);
BlkDevLock(p->bdev);
if (!Bt(&p->locked_flags,Plf_LOCKED) || p->owning_task!=Fs) {
while (LBts(&p->locked_flags,Plf_LOCKED))
Yield;
p->owning_task=Fs;
return TRUE;
} else
return FALSE;
}
Bool BlkDevUnlock(CBlkDev *bdev,Bool rst=FALSE)
{
BlkDevChk(bdev);
while (bdev->lock_fwding)
bdev=bdev->lock_fwding;
if (Bt(&bdev->locked_flags,BDlf_LOCKED) && bdev->owning_task==Fs) {
if (rst)
bdev->flags&=~(BDF_INITIALIZED|BDF_INIT_IN_PROGRESS);
bdev->owning_task=NULL;
LBtr(&bdev->locked_flags,BDlf_LOCKED);
Yield; //Prevent deadlock
return TRUE;
} else
return FALSE;
}
Bool PrtUnlock(CPrt *p,Bool rst=FALSE)
{
PrtChk(p);
if (Bt(&p->locked_flags,Plf_LOCKED) && p->owning_task==Fs) {
BlkDevUnlock(p->bdev,rst);
p->owning_task=NULL;
LBtr(&p->locked_flags,Plf_LOCKED);
Yield; //Prevent deadlock
return TRUE;
} else
return FALSE;
}
Bool BlkDevInit(CBlkDev *bdev)
{
CPrt *p=Drv2Prt(bdev->first_drv_let);
Bool old_preempt=Preempt(OFF),result=FALSE;
if (!LBts(&bdev->flags,BDf_INITIALIZED)) {
bdev->flags|=BDF_INIT_IN_PROGRESS;
switch(bdev->type) {
case BDT_RAM:
if (!bdev->RAM_dsk) {
bdev->RAM_dsk=AMAlloc((bdev->max_blk+1)<<BLK_SIZE_BITS);
bdev->max_blk=MSize(bdev->RAM_dsk)>>BLK_SIZE_BITS-1;
}
p->type=PT_REDSEA;
p->size=bdev->max_blk+1;
if (RedSeaFSDrvValidate(bdev->first_drv_let))
RedSeaFSPrtInit(p);
else
RedSeaFSFmt(bdev->first_drv_let);
result=TRUE;
break;
case BDT_ATA:
bdev->max_reads=128;
bdev->max_writes=1;
result=ATAInit(bdev);
break;
case BDT_ATAPI:
//0xFFFF*4 is too big for my taste
bdev->max_reads=0x800*4;
//max of maybe a quarter of disk cache
if (bdev->max_reads>sys_dsk_cache_size/BLK_SIZE/4)
bdev->max_reads=sys_dsk_cache_size/BLK_SIZE/4 & ~3;
if (bdev->max_reads<128)
bdev->max_reads=128;
bdev->max_writes=0xFFFF*4;
if (result=ATAInit(bdev))
p->size=bdev->max_blk+1;
break;
}
if (result && bdev->flags & BDF_READ_CACHE)
DskCacheInvalidate(p);
bdev->flags&=~BDF_INIT_IN_PROGRESS;
} else
result=TRUE;
Preempt(old_preempt);
return result;
}
U0 BlkDevsRelease()
{
I64 i;
CBlkDev *bdev;
for (i=0;i<NUM_BLKDEVS;i++) {
bdev=&sys_blkdevs[i];
if (bdev->owning_task==Fs && bdev->bd_signature==BD_SIGNATURE_VAL)
BlkDevUnlock(bdev,TRUE);
}
}
U0 PrtsRelease()
{
I64 i;
CPrt *p;
for (i=0;i<NUM_PRTS;i++) {
p=&sys_prts[i];
if (p->owning_task==Fs && p->pt_signature==PRT_SIGNATURE_VAL)
PrtUnlock(p,TRUE);
}
}
CPrt *PrtMakeFree(U8 drv_let)
{//!!! drv is not a remapped prt.
I64 i=ToUpper(drv_let)-'A';
CPrt *result;
if (!(0<=i<NUM_PRTS))
throw('Prt');
result=&sys_prts[i];
MemSet(result,0,sizeof(CPrt));
result->drv_let='A'+i;
return result;
}
CPrt *PrtNextFree(U8 first_drv_let='C')
{//!!! first_drv_let is not a remapped prt.
I64 i=ToUpper(first_drv_let)-'A';
if (!(0<=i<NUM_PRTS))
throw('Prt');
do
if (sys_prts[i].pt_signature!=PRT_SIGNATURE_VAL)
return PrtMakeFree(i+'A');
while (++i<NUM_PRTS);
throw('Prt');
return NULL; //never gets here
}
CBlkDev *BlkDevNextFree(U8 first_drv_let,I64 type)
{
I64 i=0;
CBlkDev *result;
do {
result=&sys_blkdevs[i];
if (result->bd_signature!=BD_SIGNATURE_VAL) {
MemSet(result,0,sizeof(CBlkDev));
result->first_drv_let=first_drv_let;
result->type=type;
if (type==BDT_ATAPI)
result->flags=BDF_REMOVABLE;
else
result->flags=0;
if (type!=BDT_RAM)
result->flags|=BDF_READ_CACHE;
if (type==BDT_ATAPI) {
result->blk_size=CD_BLK_SIZE;
result->flags|=BDF_READ_ONLY;
} else
result->blk_size=BLK_SIZE;
result->max_blk=0xEFFFFFFF;
return result;
}
} while (++i<NUM_BLKDEVS);
throw('BlkDev');
return NULL; //never gets here
}
U0 MapBufAlloc(CPrt *p,I64 num_blks)
{
PrtChk(p);
Free(p->cur_map_blk);
Free(p->buffered_map_dirty_bits);
p->num_buffered_map_blks=num_blks;
p->cur_map_blk=AMAlloc(num_blks<<BLK_SIZE_BITS);
p->buffered_map_dirty_bits=ACAlloc((num_blks+7)>>3);
p->cur_map_blk_num=0;
RBlks(p,p->cur_map_blk,p->map1,p->num_buffered_map_blks);
}
U0 CleanMAPBuf(CPrt *p,I64 MAP_select=-1)
{
I64 i;
if ((MAP_select==-1 || !MAP_select) && p->map1!=p->map2)
for (i=0;i<p->num_buffered_map_blks;i++)
if (Bt(p->buffered_map_dirty_bits,i))
WBlks(p,p->cur_map_blk(I64)+i<<BLK_SIZE_BITS,p->map1+i+p->cur_map_blk_num,1);
if (MAP_select==-1 || MAP_select==1 || p->map1==p->map2)
for (i=0;i<p->num_buffered_map_blks;i++)
if (LBtr(p->buffered_map_dirty_bits,i))
WBlks(p,p->cur_map_blk(I64)+i<<BLK_SIZE_BITS,p->map2+i+p->cur_map_blk_num,1);
}
U0 SetFSBuf(CPrt *p,I64 c,I64 map_select=-1)
{
I64 MAP_blk_num;
if (c==INVALID_CLUSTER)
throw('Prt');
if (p->type==PT_FAT32)
MAP_blk_num=c>>(BLK_SIZE_BITS-2);
else
MAP_blk_num=c>>(BLK_SIZE_BITS+3);
if (MAP_blk_num!=p->cur_map_blk_num) {
CleanMAPBuf(p,map_select);
p->cur_map_blk_num=MAP_blk_num;
if (map_select==-1 || !map_select)
RBlks(p,p->cur_map_blk,p->map1+p->cur_map_blk_num,1);
else
RBlks(p,p->cur_map_blk,p->map2+p->cur_map_blk_num,1);
}
}
#define ZERO_BUF_SIZE 2048
U0 WZeroBlks(CPrt *p,I64 blk,I64 cnt)
{
I64 n;
U8 *z=CAlloc(ZERO_BUF_SIZE<<BLK_SIZE_BITS);
Bool show_progress;
if (cnt>ZERO_BUF_SIZE && p->bdev->type!=BDT_RAM) {
progress1=0; progress1_max=cnt;
StrCpy(progress1_desc,"Zeroing");
show_progress=TRUE;
} else
show_progress=FALSE;
while (cnt>0) {
n=cnt;
if (n>ZERO_BUF_SIZE)
n=ZERO_BUF_SIZE;
WBlks(p,z,blk,n);
blk+=n;
cnt-=n;
if (show_progress)
progress1+=n;
Yield; //Prevent locking
}
Free(z);
if (show_progress) {
*progress1_desc=0;
progress1=progress1_max=0;
}
}
//Very dangerous
Bool SetDrvType(U8 drv_let,I64 type=PT_REDSEA)
{
I64 i,j,ext_base,prt_num,offset,cur_type;
CMasterBoot mbr;
CBlkDev *bdev=Drv2BlkDev(drv_let);
prt_num=bdev->first_drv_let-'A';
switch (bdev->type) {
case BDT_ATA:
offset=0;
ext_base=INVALID_CLUSTER;
while (TRUE) {
ATAReadBlks(bdev,&mbr,offset,1);
j=-1;
for (i=0;i<4;i++) {
cur_type=mbr.p[i].type;
if (cur_type) {
if (cur_type==5 || cur_type==15)
j=i;
else {
if (prt_num+'A'==ToUpper(drv_let)) {
switch (type) {
case PT_REDSEA:
mbr.p[i].type=MBR_PT_REDSEA;
break;
case PT_FAT32:
mbr.p[i].type=MBR_PT_FAT32a;
break;
default:
Dbg;
}
mbr.p[i].active=0x80;
ATAWriteBlks(bdev,&mbr,offset,1);
return TRUE;
}
prt_num++;
}
}
}
if (j<0)
break;
if (!mbr.p[j].offset)
break;
if (ext_base==INVALID_CLUSTER) {
offset=mbr.p[j].offset;
ext_base=offset;
} else
offset=mbr.p[j].offset+ext_base;
}
break;
}
}
Bool RBlks(CPrt *p,U8 *buf, I64 blk, I64 cnt)
{
Bool result=TRUE,unlock;
CBlkDev *bdev=p->bdev;
if (cnt<=0) return TRUE;
PrtChk(p);
try {
unlock=PrtLock(p);
BlkDevInit(bdev);
if (p->offset && blk<p->offset || blk+cnt>p->offset+p->size)
throw('Prt');
blk+=bdev->offset;
if (bdev->flags & BDF_READ_CACHE)
RCache(p,&buf,&blk,&cnt);
if (cnt>0) {
switch (bdev->type) {
case BDT_RAM:
MemCpy(buf,bdev->RAM_dsk+blk<<BLK_SIZE_BITS,cnt<<BLK_SIZE_BITS);
break;
case BDT_ATA:
case BDT_ATAPI:
result=ATARBlks(p,buf,blk,cnt);
break;
}
bdev->last_time=tS;
if (bdev->flags & BDF_READ_CACHE)
DskCacheAdd(p,buf,blk,cnt);
}
if (unlock)
PrtUnlock(p);
} catch
if (unlock)
PrtUnlock(p);
return result;
}
Bool WBlks(CPrt *p,U8 *buf, I64 blk, I64 cnt)
{
Bool result=TRUE,unlock;
CBlkDev *bdev=p->bdev;
if (cnt<=0) return TRUE;
PrtChk(p);
try {
unlock=PrtLock(p);
BlkDevInit(bdev);
if (bdev->flags&BDF_READ_ONLY &&
!(bdev->flags & BDF_READ_ONLY_OVERRIDE))
throw('BlkDev');
if (p->offset && blk<p->offset || blk+cnt>p->offset+p->size)
throw('Prt');
blk+=bdev->offset;
if (cnt>0) {
switch (bdev->type) {
case BDT_RAM:
MemCpy(bdev->RAM_dsk+blk<<BLK_SIZE_BITS,buf,cnt<<BLK_SIZE_BITS);
break;
case BDT_ATA:
case BDT_ATAPI:
result=ATAWBlks(p,buf,blk,cnt);
break;
}
bdev->last_time=tS;
if (bdev->flags & BDF_READ_CACHE)
DskCacheAdd(p,buf,blk,cnt);
}
if (unlock)
PrtUnlock(p);
} catch
if (unlock)
PrtUnlock(p);
return result;
}
U0 DskCacheInvalidate(CPrt *p)
{
Bool unlock;
CBlkDev *bdev=p->bdev;
PrtChk(p);
try {
unlock=PrtLock(p);
BlkDevInit(bdev);
if (bdev->flags & BDF_READ_CACHE)
DskCacheInvalidate2(p);
if (p->type==PT_ISO9660) {
if (!(bdev->flags & BDF_READ_ONLY_OVERRIDE))
ISOPrtInit(p,(32767/bdev->blk_size+1)*
bdev->blk_size>>BLK_SIZE_BITS);
}
if (unlock)
PrtUnlock(p);
} catch
if (unlock)
PrtUnlock(p);
}
U0 ChgDsk(U8 drv_let=0)
{ //This is needed for removable media
CPrt *p=Drv2Prt(drv_let);
CBlkDev *bdev=p->bdev;
Bool old_preempt=Preempt(OFF);
if (!(bdev->flags&BDF_INITIALIZED))
BlkDevInit(bdev);
else if (bdev->flags&BDF_REMOVABLE)
DskCacheInvalidate(p);
Drv(drv_let);
RedSeaFSFreeFreeLst(p);
Preempt(old_preempt);
}
U8 *DrvSerialNum(U8 drv_let=0)
{ //20 bytes max.
CBlkDev *bdev=Drv2BlkDev(drv_let);
U16 *st,*result=NULL;
I64 i;
if (bdev->dev_id_record) {
st=CAlloc(20+1);
for (i=0;i<10;i++)
st[i]=EndianU16(bdev->dev_id_record[10+i]);
result=MStrUtil(st,SUF_REM_LEADING|SUF_REM_TRAILING);
Free(st);
}
return result;
}
U8 *DrvModelNum(U8 drv_let=0)
{ //40 bytes max.
CBlkDev *bdev=Drv2BlkDev(drv_let);
U16 *st,*result=NULL;
I64 i;
if (bdev->dev_id_record) {
st=CAlloc(40+1);
for (i=0;i<20;i++)
st[i]=EndianU16(bdev->dev_id_record[27+i]);
result=MStrUtil(st,SUF_REM_LEADING|SUF_REM_TRAILING);
Free(st);
}
return result;
}
U0 PrtRep()
{ //Partition report
CPrt *p;
CBlkDev *bdev;
I64 i,drv_let;
U8 *st;
"\nDefined Partitions:\n\n";
for (i=0,p=sys_prts;i<NUM_PRTS;i++,p++) {
if (p->pt_signature==PRT_SIGNATURE_VAL) {
bdev=p->bdev;
drv_let=Prt2Drv(p);
if (Bt(&p->type,PTf_DISABLE))
"$$RED$$X";
else if (drv_let==*sys_acct)
"$$GREEN$$:";
else
'' CH_SPACE;
"$$PURPLE$$%C %-8Z %-9Z %04X %04X %02X$$FG$$\n",
drv_let,p->type.u16[0],"ST_PRT_TYPES",
bdev->type,"ST_BLKDEV_TYPES",bdev->base0,bdev->base1,bdev->unit;
if (st=DrvModelNum(drv_let)) {
" $$CYAN$$Model# :%s$$FG$$\n",st;
Free(st);
}
if (st=DrvSerialNum(drv_let)) {
" $$CYAN$$Serial#:%s$$FG$$\n",st;
Free(st);
}
" %016X-%016X\n",
p->offset,p->offset+p->size-1;
p->offset,p->offset+p->size-1;
}
}
}
I64 ClusterNumNext(CPrt *p,I64 c,I64 cnt=1)
{
Bool unlock;
PrtChk(p);
if (cnt<=0) return c;
try {
unlock=PrtLock(p);
switch (p->type) {
case PT_ISO9660:
case PT_REDSEA:
c+=cnt;
break;
case PT_FAT32:
while (cnt-->0 && 0<c<0x0FFFFFF8) {
SetFSBuf(p,c);
c=p->cur_map_blk[c & (BLK_SIZE/4-1)];
}
if (!(0<c<0x0FFFFFF8))
c=INVALID_CLUSTER;
break;
default:
Dbg;
}
if (unlock)
PrtUnlock(p);
} catch
if (unlock)
PrtUnlock(p);
return c;
}
I64 Cluster2Blk(CPrt *p,I64 c)
{
PrtChk(p);
return p->data+c*p->spc;
}
I64 RClustersBlks(CPrt *p,U8 *buf,I64 c,I64 blks)
{ //This accepts blk count, so padding on last cluster is not read.
I64 i;
Bool unlock;
PrtChk(p);
if (blks<=0) return c;
try {
unlock=PrtLock(p);
switch (p->type) {
case PT_ISO9660:
case PT_REDSEA:
RBlks(p,buf,p->data+c*p->spc,blks);
c+=(blks+p->spc-1)/p->spc;
break;
case PT_FAT32:
while (blks && 0<c<0x0FFFFFF8) {
i=blks;
if (i>p->spc)
i=p->spc;
RBlks(p,buf,p->data+c*p->spc,i);
buf+=i<<BLK_SIZE_BITS;
c=ClusterNumNext(p,c,1);
blks-=i;
}
if (blks)
Dbg;
break;
default:
Dbg;
}
if (unlock)
PrtUnlock(p);
} catch
if (unlock)
PrtUnlock(p);
return c;
}
I64 RClusters(CPrt *p,U8 *buf,I64 c,I64 cnt)
{
return RClustersBlks(p,buf,c,cnt*p->spc);
}
Bool CFileNameTo(U8 *dst,U8 *src)
{
MemSet(dst,0,CDIR_FILENAME_LEN);
if (!FileNameChk(src))
return FALSE;
StrCpy(dst,src);
return TRUE;
}
I64 Name2DirCluster(CPrt *p,U8 *dirname)
{
Bool cont=TRUE,unlock;
I64 cur_dir_cluster;
CDirEntry de;
U8 *buf=StrNew(dirname),*buf2=StrNew(dirname);
PrtChk(p);
try {
unlock=PrtLock(p);
cur_dir_cluster=p->root_cluster;
while (*buf && cont) {
StrFirstRem(buf,"/",buf2);
if (*buf2) {
switch (p->type) {
case PT_REDSEA:
cont=RedSeaFSFileFind(p,cur_dir_cluster,buf2,&de,FUF_JUST_DIRS);
break;
case PT_FAT32:
cont=FAT32FileFind(p,cur_dir_cluster,buf2,&de,FUF_JUST_DIRS);
break;
case PT_ISO9660:
cont=ISO1FileFind(p,cur_dir_cluster,buf2,&de,FUF_JUST_DIRS);
break;
default:
Dbg;
}
cur_dir_cluster=de.cluster;
}
}
if (!cont) {
"%s ",dirname;
PrintErr("File not found.\n");
cur_dir_cluster=0;
}
if (unlock)
PrtUnlock(p);
} catch
if (unlock)
PrtUnlock(p);
Free(buf);
Free(buf2);
return cur_dir_cluster;
}
I64 Name2ParentDirCluster(CPrt *p,U8 *dirname)
{
Bool cont=TRUE,unlock;
I64 cur_dir_cluster,cur_dir_cluster2;
CDirEntry de;
U8 *buf=StrNew(dirname),*buf2=StrNew(dirname);
PrtChk(p);
try {
unlock=PrtLock(p);
cur_dir_cluster=cur_dir_cluster2=p->root_cluster;
while (*buf && cont) {
cur_dir_cluster2=cur_dir_cluster;
StrFirstRem(buf,"/",buf2);
if (*buf2) {
switch (p->type) {
case PT_REDSEA:
cont=RedSeaFSFileFind(p,cur_dir_cluster,buf2,&de,FUF_JUST_DIRS);
break;
case PT_FAT32:
cont=FAT32FileFind(p,cur_dir_cluster,buf2,&de,FUF_JUST_DIRS);
break;
case PT_ISO9660:
cont=ISO1FileFind(p,cur_dir_cluster,buf2,&de,FUF_JUST_DIRS);
break;
default:
Dbg;
}
cur_dir_cluster=de.cluster;
}
}
if (!cont) {
"%s ",dirname;
PrintErr("File not found.\n");
cur_dir_cluster2=0;
}
if (unlock)
PrtUnlock(p);
} catch
if (unlock)
PrtUnlock(p);
Free(buf);
Free(buf2);
return cur_dir_cluster2;
}
I64 WClustersBlks(CPrt *p,U8 *buf,I64 c,I64 blks)
{ //This accepts blk count, so padding on last cluster is not written.
I64 i;
Bool unlock;
PrtChk(p);
if (blks<=0) return c;
try {
unlock=PrtLock(p);
switch (p->type) {
case PT_REDSEA:
WBlks(p,buf,p->data+c*p->spc,blks);
c=0;
break;
case PT_FAT32:
while (blks) {
if (!(0<c<0x0FFFFFF8))
Dbg;
i=blks;
if (i>p->spc)
i=p->spc;
WBlks(p,buf,p->data+c*p->spc,i);
buf+=i<<BLK_SIZE_BITS;
c=ClusterNumNext(p,c);
blks-=i;
}
break;
default:
Dbg;
}
if (unlock)
PrtUnlock(p);
} catch
if (unlock)
PrtUnlock(p);
return c;
}
I64 WClusters(CPrt *p,U8 *buf,I64 c,I64 cnt)
{
return WClustersBlks(p,buf,c,cnt*p->spc);
}
//c=0 means first cluster in chain
I64 ClustersAlloc(CPrt *p,I64 c=0,I64 cnt=1,Bool contiguous=FALSE)
{
PrtChk(p);
if (cnt<=0) return c;
switch (p->type) {
case PT_REDSEA:
return RedSeaFSAllocClusters(p,cnt);
case PT_FAT32:
if (contiguous) {
if (c) throw('File');
return FAT32AllocContiguousClusters(p,cnt);
} else
return FAT32AllocClusters(p,c,cnt);
default:
Dbg;
}
}
+489
View File
@@ -0,0 +1,489 @@
Bool MapDrv(U8 drv_let,CPrt *p)
{
drv_let=ToUpper(drv_let);
if ('A'<=drv_let<='Z') {
drv_to_prt[drv_let-'A']=p;
p->drv_let=drv_let;
return TRUE;
} else
return FALSE;
}
Bool Drv(U8 drv_let)
{
CPrt *p=Drv2Prt(drv_let);
CBlkDev *bdev=p->bdev;
BlkDevChk(bdev);
if (p!=Fs->cur_prt) {
if (bdev->flags & BDF_REMOVABLE && !(bdev->flags & BDF_INITIALIZED))
ChgDsk(Prt2Drv(p));
if (bdev->type==BDT_RAM)
BlkDevInit(bdev);
}
Fs->cur_prt=p;
Free(Fs->cur_dir);
Fs->cur_dir=StrNew("/");
switch (p->type) {
case PT_REDSEA:
case PT_FAT32:
case PT_ISO9660:
return TRUE;
default:
PrintErr("File System Not Supported\n");
return FALSE;
}
}
Bool Cd(U8 *dirname,Bool make_dirs=FALSE)
{//Optionally, will create the directories if they don't exist.
I64 maxlen,cur_dir_cluster=0;
U8 *chg_to_buf,*new_cur_dir,*buf;
CPrt *p;
Bool result=TRUE;
if (!*dirname)
return TRUE;
if (dirname[1]==':') {
if (*dirname==':') {
if (Fs->cur_prt->drv_let!=*sys_acct && !Drv(*dirname))
return FALSE;
} else if (Fs->cur_prt!=Drv2Prt(*dirname) && !Drv(*dirname))
return FALSE;
dirname+=2;
}
if (*dirname=='/' || !*dirname || !Fs->cur_dir) {
Free(Fs->cur_dir);
Fs->cur_dir=StrNew("/");
if (*dirname=='/')
dirname++;
}
chg_to_buf=MStrUtil(dirname,SUF_REM_LEADING|SUF_REM_TRAILING|SUF_REM_CTRL_CHARS);
maxlen=StrLen(Fs->cur_dir)+1+StrLen(chg_to_buf)+1;
new_cur_dir=MAlloc(maxlen);
buf=MAlloc(maxlen);
StrCpy(new_cur_dir,Fs->cur_dir);
while (*chg_to_buf && result) {
StrFirstRem(chg_to_buf,"/",buf);
if (!*buf)
StrCpy(new_cur_dir,"/");
else if (!StrCmp(buf,"..")) {
StrLastRem(new_cur_dir,"/");
if (!*new_cur_dir)
StrCpy(new_cur_dir,"/");
} else if (StrCmp(buf,".") && *buf) {
if (!StrCmp(buf,"HOME")) {
result=Cd(sys_acct);
Free(new_cur_dir);
new_cur_dir=MAlloc(maxlen+StrLen(sys_acct));
StrCpy(new_cur_dir,sys_acct+2);
} else {
p=Fs->cur_prt;
cur_dir_cluster=Name2DirCluster(p,new_cur_dir);
switch (p->type) {
case PT_REDSEA:
result=RedSeaFSCd(buf,cur_dir_cluster);
break;
case PT_FAT32:
result=FAT32Cd(buf,cur_dir_cluster);
break;
case PT_ISO9660:
result=ISO1Cd(buf,cur_dir_cluster);
break;
default:
PrintErr("File System Not Supported\n");
result=FALSE;
}
if (!result && make_dirs) {
Free(Fs->cur_dir);
Fs->cur_dir=StrNew(new_cur_dir);
result=MkDir(buf);
}
if (result) {
if (StrCmp(new_cur_dir,"/"))
CatPrint(new_cur_dir,"/");
CatPrint(new_cur_dir,buf);
}
}
}
}
Free(Fs->cur_dir);
Fs->cur_dir=StrNew(new_cur_dir);
Free(buf);
Free(chg_to_buf);
Free(new_cur_dir);
return result;
}
U0 FileAccessDel(CFileAccess *fa)
{
CBlkDev *bdev;
if (!fa) return;
bdev=fa->old_prt->bdev;
if (!(bdev->flags & BDF_INIT_IN_PROGRESS)) {
if (fa->old_dir) {
Drv(Prt2Drv(fa->old_prt));
Cd(fa->old_dir);
}
} else {
Fs->cur_prt=fa->old_prt;
Free(Fs->cur_dir);
Fs->cur_dir=StrNew("/");
}
Free(fa->old_dir);
Free(fa->mask);
Free(fa);
}
CFileAccess *FileAccessNew(U8 *_mask,Bool make_mask=FALSE,Bool make_dirs=FALSE,Bool no_mask=FALSE)
{
Bool valid=TRUE,old_silent;
U8 *buf,*mask,*temp_mask;
CFileAccess *fa=CAlloc(sizeof(CFileAccess));
mask=MStrUtil(_mask,SUF_REM_LEADING|SUF_REM_TRAILING|SUF_REM_CTRL_CHARS);
temp_mask=mask;
fa->old_dir=StrNew(Fs->cur_dir);
fa->old_prt=Fs->cur_prt;
if (*mask && mask[1]==':') {
if (Fs->cur_prt!=Drv2Prt(*mask) && !Drv(*mask))
valid=FALSE;
mask+=2;
}
if (StrMatch("HOME",mask) && Fs->cur_prt!=Drv2Prt(*sys_acct))
Drv(*sys_acct);
fa->p=Fs->cur_prt;
PrtChk(fa->p);
buf=MAlloc(StrLen(mask)+2);
StrCpy(buf,mask);
fa->mask=MAlloc(StrLen(mask)+2);
if (no_mask)
*fa->mask=0;
else
StrLastRem(buf,"/",fa->mask);
if (*mask=='/' && !*buf)
StrCpy(buf,"/");
//If began with Dir, change to Dir.
if (*buf && !Cd(buf,make_dirs))
valid=FALSE;
if (valid && make_mask) {
if (!*fa->mask) {
Free(fa->mask);
fa->mask=StrNew("*");
} else {
if (!make_dirs || FileNameChk(fa->mask)) {
old_silent=Silent(ON);
//Try mask to see if Dir. If Dir, change to dir and set to "*".
if (Cd(fa->mask,make_dirs)) {
Free(fa->mask);
fa->mask=StrNew("*");
}
Silent(old_silent);
}
}
}
Free(buf);
Free(temp_mask);
if (!valid) {
FileAccessDel(fa);
fa=NULL;
// throw('File');
}
return fa;
}
CDirEntry *FilesFind(U8 *files_find_mask,I64 fuf_flags=0)
{
/*
Flags:
$LK,"FUF_RECURSE",A="MN:FUF_RECURSE"$ +r Recurse
$LK,"FUF_SINGLE",A="MN:FUF_SINGLE"$ +s Single File (Optimization for one file in mask.)
$LK,"FUF_FLATTEN_TREE",A="MN:FUF_FLATTEN_TREE"$ +f $BK,1$use with '+F'$BK,0$. Just use +F, probably.
$LK,"FUF_JUST_DIRS",A="MN:FUF_JUST_DIRS"$ +D just directories
$LK,"FUF_JUST_FILES",A="MN:FUF_JUST_FILES"$ +F just files (Flattens trees)
$LK,"FUF_CLUSTER_ORDER",A="MN:FUF_CLUSTER_ORDER"$ +O sort by cluster (move head one direction)
$LK,"FUF_JUST_TXT",A="MN:FUF_JUST_TXT"$ +T just text files : $LK,"FILEMASK_TXT",A="MN:FILEMASK_TXT"$
$LK,"FUF_JUST_SRC",A="MN:FUF_JUST_SRC"$ +S just src files : $LK,"FILEMASK_SRC",A="MN:FILEMASK_SRC"$
$LK,"FUF_JUST_AOT",A="MN:FUF_JUST_AOT"$ +A just aot files : $LK,"FILEMASK_AOT",A="MN:FILEMASK_AOT"$
$LK,"FUF_JUST_JIT",A="MN:FUF_JUST_JIT"$ +J just jit files : $LK,"FILEMASK_JIT",A="MN:FILEMASK_JIT"$
$LK,"FUF_JUST_GRA",A="MN:FUF_JUST_GRA"$ +G just graphic files : $LK,"FILEMASK_GRA",A="MN:FILEMASK_GRA"$
See $LK,"ST_FILE_UTIL_FLAGS",A="MN:ST_FILE_UTIL_FLAGS"$ when used in calling program taking text flags.
*/
CDirEntry *result;
CFileAccess *fa;
if (fuf_flags&~FUG_FILES_FIND)
throw('FUF');
if (fuf_flags&FUF_SINGLE) {
result=MAlloc(sizeof(CDirEntry));
if (!FileFind(files_find_mask,result)) {
Free(result);
return NULL;
}
} else if (fa=FileAccessNew(files_find_mask,TRUE)) {
result=SysFilesFind(fa->mask,fuf_flags);
FileAccessDel(fa);
} else
return NULL;
return result;
}
Bool IsDir(U8 *dir_name)
{
U8 *mask=MPrint("%s/*",dir_name);
Bool result,old_silent=Silent(ON);
CFileAccess *fa;
if (fa=FileAccessNew(mask)) {
FileAccessDel(fa);
result=TRUE;
} else
result=FALSE;
Free(mask);
Silent(old_silent);
return result;
}
I64 Dir(U8 *files_find_mask="*",Bool full=FALSE)
{
I64 result;
CFileAccess *fa;
if (fa=FileAccessNew(files_find_mask,TRUE)) {
result=Dir2(fa->mask,0,full);
FileAccessDel(fa);
return result;
} else
return 0;
}
I64 Del(U8 *files_find_mask,Bool print_msg=TRUE)
{
I64 result=0;
CFileAccess *fa;
if (fa=FileAccessNew(files_find_mask)) {
switch (fa->p->type) {
case PT_REDSEA:
result=RedSeaFSFilesDel(fa->p,Fs->cur_dir,fa->mask,0,FALSE,print_msg);
break;
case PT_FAT32:
result=FAT32FilesDel(fa->p,Fs->cur_dir,fa->mask,0,FALSE,print_msg);
break;
case PT_ISO9660:
PrintErr("Not Writable\n");
break;
default:
PrintErr("File System Not Supported\n");
}
FileAccessDel(fa);
}
return result;
}
U8 *FileRead(U8 *filename,I64 *_size=NULL,I64 *_attr=NULL,Bool raw=FALSE)
{
CHashGeneric *temph;
U8 *absname,*altname,*curname,*result=NULL;
I64 i,size=0,attr=0;
CFileAccess *fa;
CArcCompress *ac;
absname=FileNameAbs(filename);
altname=ToggleZorNotZ(absname);
if (!raw && ((temph=HashFind(absname,adam_task->hash_table,HTT_FILE))||
(temph=HashFind(altname,adam_task->hash_table,HTT_FILE)))) {
size=temph->user_data1;
result=MAlloc(size+1);
MemCpy(result,temph->user_data0,size);
result[size]=0; //Terminate
attr=FileAttr(temph->str,attr);
} else {
for (i=0;i<2 && !result;i++) {//Try name, then altname
if (!i)
curname=absname;
else
curname=altname;
if (fa=FileAccessNew(curname)) {
switch (fa->p->type) {
case PT_REDSEA:
result=RedSeaFSFileRead(fa->p,Fs->cur_dir,fa->mask,&size,&attr);
break;
case PT_FAT32:
result=FAT32FileRead(fa->p,Fs->cur_dir,fa->mask,&size,&attr);
break;
case PT_ISO9660:
result=ISO1FileRead(fa->p,Fs->cur_dir,fa->mask,&size,&attr);
break;
default:
PrintErr("File System Not Supported\n");
}
FileAccessDel(fa);
}
}
//Search parent directories.
for (i=0;i<2 && !result;i++) {//Try name, then altname
if (!i)
curname=absname;
else
curname=altname;
if (fa=FileAccessNew(curname)) {
while (!result && StrCmp(Fs->cur_dir,"/")) {
Cd("..");
switch (Fs->cur_prt->type) {
case PT_REDSEA:
result=RedSeaFSFileRead(fa->p,Fs->cur_dir,fa->mask,&size,&attr);
break;
case PT_FAT32:
result=FAT32FileRead(fa->p,Fs->cur_dir,fa->mask,&size,&attr);
break;
case PT_ISO9660:
result=ISO1FileRead(fa->p,Fs->cur_dir,fa->mask,&size,&attr);
break;
default:
PrintErr("File System Not Supported\n");
}
}
FileAccessDel(fa);
}
}
if (!result) {
"%s ",filename;
PrintErr("File not found.\n");
}
if (result && !raw && attr & _ATTR_RESIDENT)
HashGenericAdd(curname,HTT_FILE,AMAllocIdentical(result),size,0,adam_task);
}
if (result && !raw && attr & _ATTR_COMPRESSED) {
ac=result;
size=ac->expanded_size;
result=ExpandBuf(ac);
Free(ac);
}
if (_attr) *_attr=attr;
if (_size) *_size=size;
Free(absname);
Free(altname);
return result;
}
Bool FileFind(U8 *filename,CDirEntry *_de=NULL,I64 fuf_flags=0)
{ //$LK,"FUF_JUST_DIRS",A="MN:FUF_JUST_DIRS"$, $LK,"FUF_JUST_FILES",A="MN:FUF_JUST_FILES"$, $LK,"FUF_Z_OR_NOT_Z",A="MN:FUF_Z_OR_NOT_Z"$, $LK,"FUF_SCAN_PARENTS",A="MN:FUF_SCAN_PARENTS"$
//If you pass _de, you must Free(_de->full_name);
I64 i,j,cur_dir_cluster;
U8 *altname,*curname,*full_name=NULL;
CDirEntry de;
CFileAccess *fa;
Bool result=FALSE;
if (fuf_flags&~FUG_FILE_FIND)
throw('FUF');
if (!filename) return FALSE;
altname=ToggleZorNotZ(filename);
if (fuf_flags&FUF_Z_OR_NOT_Z)
j=2;
else
j=1;
for (i=0;i<j && !result;i++) {
if (!i)
curname=filename;
else
curname=altname;
if (fa=FileAccessNew(curname)) {
cur_dir_cluster=Name2DirCluster(fa->p,Fs->cur_dir);
switch (fa->p->type) {
case PT_REDSEA:
result=RedSeaFSFileFind(fa->p,cur_dir_cluster,fa->mask,&de,fuf_flags);
break;
case PT_FAT32:
result=FAT32FileFind(fa->p,cur_dir_cluster,fa->mask,&de,fuf_flags);
break;
case PT_ISO9660:
result=ISO1FileFind(fa->p,cur_dir_cluster,fa->mask,&de,fuf_flags);
break;
default:
PrintErr("File System Not Supported\n");
}
if (result && _de)
full_name=MPrint("%C:%s/%s",Fs->cur_prt->drv_let,Fs->cur_dir,de.name);
FileAccessDel(fa);
}
}
for (i=0;i<j && !result && fuf_flags&FUF_SCAN_PARENTS;i++) {
if (!i)
curname=filename;
else
curname=altname;
if (fa=FileAccessNew(curname)) {
cur_dir_cluster=Name2DirCluster(fa->p,Fs->cur_dir);
while (!result && StrCmp(Fs->cur_dir,"/")) {
Cd("..");
cur_dir_cluster=Name2DirCluster(fa->p,Fs->cur_dir);
switch (fa->p->type) {
case PT_REDSEA:
result=RedSeaFSFileFind(fa->p,cur_dir_cluster,fa->mask,&de,fuf_flags);
break;
case PT_FAT32:
result=FAT32FileFind(fa->p,cur_dir_cluster,fa->mask,&de,fuf_flags);
break;
case PT_ISO9660:
result=ISO1FileFind(fa->p,cur_dir_cluster,fa->mask,&de,fuf_flags);
break;
default:
PrintErr("File System Not Supported\n");
}
}
if (result && _de)
full_name=MPrint("%C:%s/%s",Fs->cur_prt->drv_let,Fs->cur_dir,de.name);
FileAccessDel(fa);
}
}
if (_de) {
if (result) {
MemCpy(_de,&de,sizeof(CDirEntry));
_de->full_name=full_name;
} else
MemSet(_de,0,sizeof(CDirEntry));
}
Free(altname);
return result;
}
I64 FileWrite(U8 *filename,U8 *fbuf,
I64 size,CDate cdt=0,I64 attr=0,Bool raw=FALSE)
{
I64 c=0;
CHashGeneric *temph;
CFileAccess *fa;
U8 *fbuf2,*absname=FileNameAbs(filename);
if (fa=FileAccessNew(filename,FALSE,TRUE)) {
attr=FileAttr(fa->mask,attr);
if (attr&_ATTR_COMPRESSED && !raw) {
fbuf=CompressBuf(fbuf,size);
size=fbuf(CArcCompress *)->compressed_size;
fbuf2=fbuf;
} else
fbuf2=NULL;
if (!cdt) cdt=Now;
switch (fa->p->type) {
case PT_REDSEA:
c=RedSeaFSFileWrite(fa->p,Fs->cur_dir,fa->mask,fbuf,size,cdt,attr);
break;
case PT_FAT32:
c=FAT32FileWrite(fa->p,Fs->cur_dir,fa->mask,fbuf,size,cdt,attr);
break;
case PT_ISO9660:
PrintErr("Not Writable\n");
break;
default:
PrintErr("File System Not Supported\n");
}
if (temph=HashFind(absname,adam_task->hash_table,HTT_FILE)) {
if (!raw && attr & _ATTR_RESIDENT) {
Free(temph->user_data0);
temph->user_data0=AMAllocIdentical(fbuf);
temph->user_data1=size;
} else
HashRemDel(temph,adam_task->hash_table);
} else if (!raw && attr & _ATTR_RESIDENT)
HashGenericAdd(absname,HTT_FILE,AMAllocIdentical(fbuf),size,0,adam_task);
Free(fbuf2);
FileAccessDel(fa);
}
Free(absname);
return c;
}
+361
View File
@@ -0,0 +1,361 @@
Bool CopySingleZ(U8 *f1,U8 *f2) //Just one file
{
U8 *file_buf=NULL;
I64 size,attr=0,c;
CDirEntry de;
if (FileFind(f1,&de,FUF_JUST_FILES)) {
Free(de.full_name);
file_buf=FileRead(f1,&size,&attr);
attr=FileAttr(f2,attr);
if (file_buf) {
"Copying %s to %s\n",f1,f2;
c=FileWrite(f2,file_buf,size,de.datetime,attr);
Free(file_buf);
return ToBool(c);
} else
PrintErr("File not found.\n");
} else
PrintErr("File not found.\n");
return FALSE;
}
#define COPY_BUF_BLKS 0x80
Bool CopySingle(U8 *f1,U8 *f2) //Just one file
{
U8 *absf1=FileNameAbs(f1),*absf2=FileNameAbs(f2),*buf;
I64 cnt,n,size,attr1=FileAttr(f1),attr2=FileAttr(f2),i,j;
CFile *in_file=NULL,*out_file=NULL;
if (!StrCmp(absf1,absf2)) { //onto self?
Free(absf1);
Free(absf2);
return FALSE;
}
Free(absf1);
Free(absf2);
if (attr1!=attr2)
return CopySingleZ(f1,f2);
buf=MAlloc(COPY_BUF_BLKS<<BLK_SIZE_BITS);
if (attr1 & _ATTR_CONTIGUOUS)
in_file=FOpen(f1,"rc");
else
in_file=FOpen(f1,"r");
if (in_file) {
size=FSize(in_file);
cnt=(size+BLK_SIZE-1)>>BLK_SIZE_BITS;
if (attr2 & _ATTR_CONTIGUOUS)
out_file=FOpen(f2,"wc",cnt);
else
out_file=FOpen(f2,"w",cnt);
if (out_file) {
"Copying %s to %s\n",f1,f2;
j=size;
while (cnt>0) {
if (cnt>COPY_BUF_BLKS) {
n=COPY_BUF_BLKS;
i=n<<BLK_SIZE_BITS;
} else {
n=cnt;
i=j;
}
FRBlks(in_file, buf,FFB_NEXT_BLK,n);
FWBlks(out_file,buf,FFB_NEXT_BLK,n);
cnt-=n;
j-=n<<BLK_SIZE_BITS;
}
out_file->flags|=FF_USE_OLD_DATETIME;
out_file->de.datetime=in_file->de.datetime;
out_file->de.size=size;
out_file->de.attr=FileAttr(f2,in_file->de.attr);
FClose(out_file);
FClose(in_file);
Free(buf);
return TRUE;
} else
PrintErr("File not found.\n");
FClose(in_file);
} else
PrintErr("File not found.\n");
Free(buf);
return FALSE;
}
Bool MkDir(U8 *filename)
{
U8 *name;
CFileAccess *fa;
Bool result=FALSE;
if (FileFind(filename,,FUF_JUST_DIRS))
return FALSE;
if (fa=FileAccessNew(filename)) {
if (*fa->mask) {
if (!FileNameChk(fa->mask))
PrintErr("Invalid FileName.\n");
else {
"Make Directory:%s\n",filename;
name=MStrUtil(fa->mask,SUF_REM_LEADING|SUF_REM_TRAILING|SUF_REM_CTRL_CHARS);
switch (fa->p->type) {
case PT_REDSEA:
result=RedSeaFSMkDir(fa->p,Fs->cur_dir,name);
break;
case PT_FAT32:
result=FAT32MkDir(fa->p,Fs->cur_dir,name);
break;
case PT_ISO9660:
PrintErr("Not Writable\n");
break;
default:
PrintErr("File System Not Supported\n");
}
Free(name);
}
}
FileAccessDel(fa);
}
return result;
}
I64 SysDel(U8 *wild,Bool make_mask) //this is dangerous
{
I64 result=0;
CFileAccess *fa;
if (fa=FileAccessNew(wild,make_mask)) {
switch (fa->p->type) {
case PT_REDSEA:
result=RedSeaFSFilesDel(fa->p,Fs->cur_dir,fa->mask,0,TRUE,TRUE);
break;
case PT_FAT32:
result=FAT32FilesDel(fa->p,Fs->cur_dir,fa->mask,0,TRUE,TRUE);
break;
case PT_ISO9660:
PrintErr("Not Writable\n");
break;
default:
PrintErr("File System Not Supported\n");
}
FileAccessDel(fa);
}
return result;
}
U0 Fmt(I64 drv_let,Bool quick=TRUE,Bool confirm=TRUE,I64 type=PT_FAT32)
{//See $LK,"PT_FAT32",A="MN:PT_FAT32"$ for a lst of supported file system types.
CPrt *p=Drv2Prt(drv_let);
Bool old_silent=IsSilent;
if (confirm && !AreYouSure)
return;
if (!p) {
PrintErr("Invalid Drive\n");
return;
}
switch (type) {
case PT_REDSEA:
Silent(ON);
Drv(drv_let);
Silent(old_silent);
RedSeaFSFmt(drv_let,quick);
DskCacheInvalidate(Drv2Prt(drv_let));
Drv(drv_let);
break;
case PT_FAT32:
Silent(ON);
Drv(drv_let);
Silent(old_silent);
FAT32Fmt(drv_let,quick);
DskCacheInvalidate(Drv2Prt(drv_let));
Drv(drv_let);
break;
case PT_ISO9660:
PrintErr("Not Writable\n");
break;
default:
PrintErr("File System Not Supported\n");
}
}
U0 CDImageRead(U8 cd_drv_let,U8 *out_name)
{
CBlkDev *bdev=Drv2BlkDev(cd_drv_let);
CPrt *p=Drv2Prt(cd_drv_let);
U8 *buf=MAlloc(COPY_BUF_BLKS<<BLK_SIZE_BITS),
*out_name2=DftExt(out_name,"ISO");
CFile *f=FOpen(out_name2,"w");
I64 n,spc=bdev->blk_size>>BLK_SIZE_BITS,blk=0,cnt,retry;
BlkDevInit(bdev);
if (bdev->type!=BDT_ATAPI)
throw('BlkDev');
if (!out_name)
out_name=sys_dft_iso_name;
cnt=CeilU64(p->size,spc);
while (cnt>0) {
if (cnt>COPY_BUF_BLKS)
n=COPY_BUF_BLKS;
else
n=cnt;
if (n>bdev->max_reads)
n=bdev->max_reads;
retry=4;
while (--retry)
if (ATAPIReadBlks2(bdev,tS+7.0+0.004*n/spc,buf,blk/spc,n/spc,TRUE))
//n is 0x800 if max_reads. Up to 8 additional seconds
break;
if (!retry)
ATAPIReadBlks2(bdev,0,buf,blk/spc,n/spc,TRUE);
FWBlks(f,buf,blk,n);
cnt-=n;
blk+=n;
}
FClose(f);
Free(buf);
Free(out_name2);
}
class CDualBuf
{
U8 *buf0,*buf1;
I64 in_buf,out_buf,cnt;
U8 *filename;
CBlkDev *CD_bdev;
};
U0 CDImageWriteTask(CDualBuf *d)
{
U8 *buf;
I64 n,blk=0,cnt=d->cnt;
CFile *f;
Preempt(ON);
if (FileAttr(d->filename)&_ATTR_CONTIGUOUS)
f=FOpen(d->filename,"rc");
else
f=FOpen(d->filename,"r");
while (cnt>0) {
if (cnt>COPY_BUF_BLKS)
n=COPY_BUF_BLKS;
else
n=cnt;
if (n>d->CD_bdev->max_writes)
n=d->CD_bdev->max_writes;
if (d->in_buf&1)
buf=d->buf1;
else
buf=d->buf0;
while (d->in_buf>d->out_buf+1)
Yield;
FRBlks(f,buf,blk,n);
d->in_buf++;
cnt-=n;
blk+=n;
}
FClose(f);
}
U0 CDImageWrite(U8 cd_drv_let,U8 *in_name=NULL,I64 media_type=MT_CD)
{
CDualBuf *d=CAlloc(sizeof(CDualBuf));
U8 *buf,*in_name2,*in_name3;
I64 i,n,spc,blk=0,cnt;
CPrt *p=Drv2Prt(cd_drv_let);
CBlkDev *bdev=p->bdev,*bdev2;
CTask *task;
Bool old_preempt;
CFile *f;
if (!in_name)
in_name=sys_dft_iso_name;
in_name3=DftExt(in_name,"ISO");
in_name2=FileNameAbs(in_name3);
f=FOpen(in_name2,"r");
if (!f) {
Free(d);
return;
}
cnt=(FSize(f)+BLK_SIZE-1)>>BLK_SIZE_BITS;
FClose(f);
if (bdev->type!=BDT_ATAPI)
throw('BlkDev');
bdev2=Drv2BlkDev(*in_name2);
while (bdev2->lock_fwding)
bdev2=bdev2->lock_fwding;
if ((bdev2->type==BDT_ATA || bdev2->type==BDT_ATAPI) &&
bdev2->base0==bdev->base0) {
"Can't Burn CD on same ATA ctrller as File.\n\n";
throw('BlkDev');
}
bdev->flags|=BDF_READ_ONLY_OVERRIDE;
BlkDevInit(bdev);
spc=bdev->blk_size>>BLK_SIZE_BITS;
if (p->size<cnt)
p->size=cnt;
d->filename=in_name2;
d->CD_bdev=bdev;
d->buf0=MAlloc(COPY_BUF_BLKS<<BLK_SIZE_BITS);
d->buf1=MAlloc(COPY_BUF_BLKS<<BLK_SIZE_BITS);
d->cnt=cnt;
old_preempt=Preempt(OFF);
task=Spawn(&CDImageWriteTask,d,"Write CD");
while (d->in_buf<=d->out_buf)
Yield;
BlkDevLock(bdev);
ATAPIWaitReady(bdev,0);
progress1=0; progress1_max=cnt;
StrCpy(progress1_desc,"Writing");
while (cnt>0) {
if (cnt>COPY_BUF_BLKS)
n=COPY_BUF_BLKS;
else
n=cnt;
if (n>bdev->max_writes)
n=bdev->max_writes;
if (d->out_buf&1)
buf=d->buf1;
else
buf=d->buf0;
while (d->in_buf<=d->out_buf)
Yield;
ATAPIWriteBlks(bdev,buf,blk/spc,(n+spc-1)/spc);
d->out_buf++;
cnt-=n;
blk+=n;
progress1+=n;
}
ATAPISync(bdev);
progress1=0; progress1_max=2;
StrCpy(progress1_desc,"Closing");
for (i=0;i<2;i++) {
ATAPIClose(bdev,0x100,i); //Close tracks
progress1++;
}
ATAPISync(bdev);
ATAPIClose(bdev,0x200); //close disk
ATAPISync(bdev);
if (media_type==MT_DVD) {
ATAPIClose(bdev,0x300);
ATAPISync(bdev);
}
*progress1_desc=0;
progress1=progress1_max=0;
bdev->flags&=~BDF_READ_ONLY_OVERRIDE;
BlkDevUnlock(bdev);
Free(d->buf0);
Free(d->buf1);
Free(in_name2);
Free(in_name3);
Preempt(old_preempt);
Free(d);
}
+887
View File
@@ -0,0 +1,887 @@
U0 ATABlkSelect(CBlkDev *bdev,I64 blk,I64 cnt)
{
if (bdev->type!=BDT_ATAPI && bdev->base1)
OutU8(bdev->base1+ATAR1_CTRL,0x8);
if (bdev->flags & BDF_EXT_SIZE) {
OutU8(bdev->base0+ATAR0_NSECT,cnt.u8[1]);
OutU8(bdev->base0+ATAR0_SECT,blk.u8[3]);
OutU8(bdev->base0+ATAR0_LCYL,blk.u8[4]);
OutU8(bdev->base0+ATAR0_HCYL,blk.u8[5]);
OutU8(bdev->base0+ATAR0_NSECT,cnt);
OutU8(bdev->base0+ATAR0_SECT,blk);
OutU8(bdev->base0+ATAR0_LCYL,blk.u8[1]);
OutU8(bdev->base0+ATAR0_HCYL,blk.u8[2]);
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
} else {
OutU8(bdev->base0+ATAR0_NSECT,cnt);
OutU8(bdev->base0+ATAR0_SECT,blk);
OutU8(bdev->base0+ATAR0_LCYL,blk.u8[1]);
OutU8(bdev->base0+ATAR0_HCYL,blk.u8[2]);
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4|blk.u8[3]);
}
}
Bool ATAWaitNotBUSY(CBlkDev *bdev,F64 timeout)
{
I64 i;
do {
for (i=0;i<3;i++)
if (!(InU8(bdev->base0+ATAR0_STAT)&ATAS_BSY))
return TRUE;
Yield;
} while (!(0<timeout<tS));
return FALSE;
}
Bool ATAWaitDRQ(CBlkDev *bdev,F64 timeout)
{
I64 i;
do {
for (i=0;i<3;i++)
if (InU8(bdev->base0+ATAR0_STAT)&ATAS_DRQ)
return TRUE;
Yield;
} while (!(0<timeout<tS));
return FALSE;
}
Bool ATANop(CBlkDev *bdev,F64 timeout)
{
if (bdev->flags & BDF_EXT_SIZE)
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
else
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
OutU8(bdev->base0+ATAR0_FEAT,0);
OutU8(bdev->base0+ATAR0_CMD,ATA_NOP);
return ATAWaitNotBUSY(bdev,timeout);
}
U0 ATACmd(CBlkDev *bdev,U8 cmd)
{
OutU8(bdev->base0+ATAR0_FEAT,0);
OutU8(bdev->base0+ATAR0_CMD,cmd);
bdev->last_time=tS;
PortNop;
}
Bool ATAGetResult(CBlkDev *bdev,F64 timeout,U8 *buf,I64 cnt,I64 _avail,Bool one_read)
{
I64 avail,overflow;
bdev->flags&=~BDF_LAST_WAS_WRITE;
MemSet(buf,0,cnt);
while (cnt>0) {
if (!ATAWaitDRQ(bdev,timeout))
return FALSE;
if (_avail)
avail=_avail;
else
avail=InU8(bdev->base0+ATAR0_HCYL)<<8+InU8(bdev->base0+ATAR0_LCYL);
if (avail) {
if (avail>cnt) {
overflow=avail-cnt;
avail=cnt;
} else
overflow=0;
if (avail&2)
RepInU16(buf,avail>>1,bdev->base0+ATAR0_DATA);
else
RepInU32(buf,avail>>2,bdev->base0+ATAR0_DATA);
cnt-=avail;
buf+=avail;
while (overflow>0) {
InU16(bdev->base0+ATAR0_DATA);
overflow-=2;
if (0<timeout<tS)
return FALSE;
}
if (one_read)
break;
} else
Yield;
}
return ATAWaitNotBUSY(bdev,timeout);
}
Bool ATAPIWritePktWord(CBlkDev *bdev,F64 timeout,...)
{
I64 i;
for (i=0;i<argc;i++) {
if (!ATAWaitDRQ(bdev,timeout))
return FALSE;
OutU16(bdev->base0+ATAR0_DATA,EndianU16(argv[i]));
bdev->last_time=tS;
}
return TRUE;
}
Bool ATAPISetMaxSpeed(CBlkDev *bdev)
{
if (bdev->flags & BDF_EXT_SIZE)
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
else
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
OutU8(bdev->base0+ATAR0_LCYL,0);
OutU8(bdev->base0+ATAR0_HCYL,0);
ATACmd(bdev,ATA_PACKET);
ATAPIWritePktWord(bdev,0,0xBB00,0xFFFF,0xFFFF,0,0,0);
return ATAWaitNotBUSY(bdev,0);
}
Bool ATAPISeek(CBlkDev *bdev,I64 native_blk)
{
if (bdev->flags & BDF_EXT_SIZE)
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
else
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
OutU8(bdev->base0+ATAR0_LCYL,0);
OutU8(bdev->base0+ATAR0_HCYL,0);
ATACmd(bdev,ATA_PACKET);
ATAPIWritePktWord(bdev,0,0x2B00,native_blk>>16,native_blk,0,0,0);
return ATAWaitNotBUSY(bdev,0);
}
Bool ATAPIStartStop(CBlkDev *bdev,F64 timeout,Bool start)
{
I64 i;
if (start)
i=0x100;
else
i=0;
if (bdev->flags & BDF_EXT_SIZE)
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
else
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
ATACmd(bdev,ATA_PACKET);
//Start/Stop
if (ATAPIWritePktWord(bdev,timeout,0x1B00,0,i,0,0,0))
return ATAWaitNotBUSY(bdev,timeout);
else
return FALSE;
}
I64 ATAGetDevId(CBlkDev *bdev,F64 timeout,U16 **_id_record)
{
U16 *id_record;
if (_id_record) *_id_record=NULL;
if (bdev->type!=BDT_ATAPI && bdev->base1)
OutU8(bdev->base1+ATAR1_CTRL,0x8);
if (bdev->flags & BDF_EXT_SIZE)
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
else
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
ATACmd(bdev,ATA_ID_DEV);
if (!ATAWaitNotBUSY(bdev,timeout))
return BDT_NULL;
if (InU8(bdev->base0+ATAR0_STAT)&ATAS_ERR)
return BDT_ATAPI;
id_record=ACAlloc(512);
if (!ATAGetResult(bdev,timeout,id_record,512,512,FALSE)) {
Free(id_record);
return BDT_NULL;
}
if (_id_record) *_id_record=id_record;
return BDT_ATA;
}
I64 ATAReadNativeMax(CBlkDev *bdev,F64 timeout)
{ //returns zero on err
I64 result=0;
Bool okay=TRUE;
if (bdev->type==BDT_ATAPI) {
if (bdev->flags & BDF_EXT_SIZE)
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
else
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
ATACmd(bdev,ATA_DEV_RST);
if (!ATAWaitNotBUSY(bdev,0))
okay=FALSE;
} else {
while (InU8(bdev->base0+ATAR0_STAT) & ATAS_BSY) {
if (bdev->flags&BDF_LAST_WAS_WRITE)
OutU16(bdev->base0+ATAR0_DATA,0);
else
InU16(bdev->base0+ATAR0_DATA);
Yield;
if (0<timeout<tS)
return FALSE;
}
Free(bdev->dev_id_record);
if (ATAGetDevId(bdev,timeout,&bdev->dev_id_record)==BDT_NULL)
okay=FALSE;
else
BEqu(&bdev->flags,BDf_EXT_SIZE,Bt(&bdev->dev_id_record[86],10));
}
if (okay) {
if (bdev->flags & BDF_EXT_SIZE && bdev->base1) {
OutU8(bdev->base1+ATAR1_CTRL,0x8);
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
ATACmd(bdev,ATA_READ_NATIVE_MAX_EXT);
if (ATAWaitNotBUSY(bdev,timeout)) {
result.u8[0]=InU8(bdev->base0+ATAR0_SECT);
result.u8[1]=InU8(bdev->base0+ATAR0_LCYL);
result.u8[2]=InU8(bdev->base0+ATAR0_HCYL);
OutU8(bdev->base1+ATAR1_CTRL,0x80);
result.u8[3]=InU8(bdev->base0+ATAR0_SECT);
result.u8[4]=InU8(bdev->base0+ATAR0_LCYL);
result.u8[5]=InU8(bdev->base0+ATAR0_HCYL);
if (result>>24==result&0xFFFFFF) {//Kludge to make qemu-kvm work
bdev->flags&=~BDF_EXT_SIZE;
result&=0xFFFFFF;
}
}
} else {
if (bdev->type!=BDT_ATAPI && bdev->base1)
OutU8(bdev->base1+ATAR1_CTRL,0x8);
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
ATACmd(bdev,ATA_READ_NATIVE_MAX);
if (ATAWaitNotBUSY(bdev,timeout)) {
result.u8[0]=InU8(bdev->base0+ATAR0_SECT);
result.u8[1]=InU8(bdev->base0+ATAR0_LCYL);
result.u8[2]=InU8(bdev->base0+ATAR0_HCYL);
result.u8[3]=InU8(bdev->base0+ATAR0_SELECT) & 0xF;
}
}
}
return bdev->max_blk=result;
}
I64 ATAPIReadCapacity(CBlkDev *bdev,I64 *_blk_size=NULL)
{ //Supposedly this can return a result +/- 75 sects.
//Error might just be for music.
Bool unlock=BlkDevLock(bdev);
U32 buf[2];
if (ATAWaitNotBUSY(bdev,0)) {
if (bdev->flags & BDF_EXT_SIZE)
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
else
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
OutU8(bdev->base0+ATAR0_LCYL,8);
OutU8(bdev->base0+ATAR0_HCYL,0);
ATACmd(bdev,ATA_PACKET);
ATAPIWritePktWord(bdev,0,0x2500,0,0,0,0,0);
if (!ATAGetResult(bdev,0,buf,8,0,TRUE))
buf[0]=buf[1]=0;
} else
buf[0]=buf[1]=0;
if (unlock) BlkDevUnlock(bdev);
if (_blk_size) *_blk_size=EndianU32(buf[1]);
return EndianU32(buf[0]);
}
CATAPITrack *ATAPIReadTrackInfo(CBlkDev *bdev,I64 blk)
{
CATAPITrack *result=CAlloc(sizeof(CATAPITrack));
Bool unlock=BlkDevLock(bdev);
if (ATAWaitNotBUSY(bdev,0)) {
if (bdev->flags & BDF_EXT_SIZE)
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
else
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
OutU8(bdev->base0+ATAR0_LCYL,sizeof(CATAPITrack)&0xFF);
OutU8(bdev->base0+ATAR0_HCYL,sizeof(CATAPITrack)>>8);
ATACmd(bdev,ATA_PACKET);
ATAPIWritePktWord(bdev,0,0x5200,blk.u16[1],blk.u16[0],
(sizeof(CATAPITrack)&0xFF00)>>8,(sizeof(CATAPITrack)&0x00FF)<<8,0);
if (!ATAGetResult(bdev,0,result,sizeof(CATAPITrack),0,TRUE)) {
Free(result);
result=NULL;
}
} else {
Free(result);
result=NULL;
}
if (unlock) BlkDevUnlock(bdev);
return result;
}
Bool ATAInit(CBlkDev *bdev)
{
Bool unlock=BlkDevLock(bdev),okay=FALSE;
if (bdev->type==BDT_ATAPI)
bdev->flags&=~BDF_EXT_SIZE;
else
bdev->flags|=BDF_EXT_SIZE;
if (ATAReadNativeMax(bdev,tS+0.1)) {
ATABlkSelect(bdev,bdev->max_blk,0);
if (bdev->flags&BDF_EXT_SIZE)
ATACmd(bdev,ATA_SET_MAX_EXT);
else
ATACmd(bdev,ATA_SET_MAX);
if (ATAWaitNotBUSY(bdev,0)) {
okay=TRUE;
if (bdev->type==BDT_ATAPI) {
if (ATAPIStartStop(bdev,0,TRUE)) {
if(!ATAPISetMaxSpeed(bdev))
okay=FALSE;
} else
okay=FALSE;
}
}
}
if (unlock) BlkDevUnlock(bdev);
return okay;
}
Bool ATAPIWaitReady(CBlkDev *bdev,F64 timeout)
{
do {
if (!ATAWaitNotBUSY(bdev,timeout) ||
!ATANop(bdev,timeout) ||
!ATAPIStartStop(bdev,timeout,TRUE))
return FALSE;
if (InU8(bdev->base0+ATAR0_STAT) & ATAS_DRDY &&
!InU8(bdev->base0+ATAR0_FEAT));
return TRUE;
ATAInit(bdev);
Yield;
} while (!(0<timeout<tS));
return FALSE;
}
U0 ATAReadBlks(CBlkDev *bdev,U8 *buf, I64 blk, I64 cnt)
{
I64 retries=3;
Bool unlock=BlkDevLock(bdev);
retry:
ATABlkSelect(bdev,blk,cnt);
if (bdev->flags & BDF_EXT_SIZE)
ATACmd(bdev,ATA_READ_MULTI_EXT);
else
ATACmd(bdev,ATA_READ_MULTI);
if (!ATAGetResult(bdev,tS+1.0,buf,cnt*bdev->blk_size,BLK_SIZE,FALSE)) {
if (retries--) {
ATAWaitNotBUSY(bdev,0);
goto retry;
} else
throw('BlkDev');
}
sys_dsk_reads+=(cnt*bdev->blk_size)>>BLK_SIZE_BITS;
if (unlock) BlkDevUnlock(bdev);
}
I64 ATAProbe(I64 base0,I64 base1,I64 unit)
{
CBlkDev bdev;
MemSet(&bdev,0,sizeof(CBlkDev));
bdev.type=BDT_ATAPI;
bdev.base0=base0;
bdev.base1=base1;
bdev.unit=unit;
bdev.blk_size=CD_BLK_SIZE;
return ATAGetDevId(&bdev,tS+0.1,NULL);
}
Bool ATAPIReadBlks2(CBlkDev *bdev,F64 timeout,U8 *buf, I64 native_blk, I64 cnt,Bool lock)
{
Bool result=FALSE,unlock;
if (cnt<=0)
return FALSE;
if (lock)
unlock=BlkDevLock(bdev);
if (ATAPIWaitReady(bdev,timeout)) {
if (bdev->flags & BDF_EXT_SIZE)
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
else
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
OutU8(bdev->base0+ATAR0_LCYL,bdev->blk_size);
OutU8(bdev->base0+ATAR0_HCYL,bdev->blk_size.u8[1]);
ATACmd(bdev,ATA_PACKET);
if (ATAPIWritePktWord(bdev,timeout,0xA800,
native_blk.u16[1],native_blk,cnt.u16[1],cnt,0) &&
ATAGetResult(bdev,timeout,buf,cnt*bdev->blk_size,0,FALSE)) {
sys_dsk_reads+=(cnt*bdev->blk_size)>>BLK_SIZE_BITS;
result=TRUE;
}
}
// ATAPIStartStop(bdev,0,FALSE);
if (lock && unlock) BlkDevUnlock(bdev);
return result;
}
U0 ATAPIReadBlks(CBlkDev *bdev,U8 *buf, I64 blk, I64 cnt)
{
CPrt *p=Drv2Prt(bdev->first_drv_let);
I64 retry,spc=bdev->blk_size>>BLK_SIZE_BITS,n,blk2,
l2=bdev->max_reads<<1+spc<<1;
U8 *cd_buf=MAlloc(l2<<BLK_SIZE_BITS);
if (cnt>0) {
if (blk<=bdev->max_reads)
blk2=0;
else
blk2=FloorU64(blk-bdev->max_reads,spc);
if (blk2+l2>p->size)
l2=p->size-blk2;
n=(l2+spc-1)/spc;
retry=4;
while (--retry)
if (ATAPIReadBlks2(bdev,tS+7.0+0.004*n,cd_buf,blk2/spc,n,TRUE))
//n is 0x800 if max_reads. Up to 8 additional seconds
break;
if (!retry)
ATAPIReadBlks2(bdev,0,cd_buf,blk2/spc,n,TRUE);
if (bdev->flags & BDF_READ_CACHE)
DskCacheAdd(p,cd_buf,blk2,n*spc);
MemCpy(buf,cd_buf+(blk-blk2)<<BLK_SIZE_BITS,cnt<<BLK_SIZE_BITS);
}
Free(cd_buf);
}
Bool ATARBlks(CPrt *p,U8 *buf, I64 blk, I64 cnt)
{
I64 n;
CBlkDev *bdev=p->bdev;
while (cnt>0) {
n=cnt;
if (n>bdev->max_reads)
n=bdev->max_reads;
if (bdev->type==BDT_ATAPI)
ATAPIReadBlks(bdev,buf,blk,n);
else
ATAReadBlks(bdev,buf,blk,n);
buf+=n<<BLK_SIZE_BITS;
blk+=n;
cnt-=n;
}
return TRUE;
}
//This is for low level disk access
//Call WBlks() instead
U0 ATAWriteBlks(CBlkDev *bdev,U8 *buf, I64 blk, I64 cnt)
{
I64 i,U32s_avail,sects_avail,retries=3;
F64 timeout;
Bool unlock=BlkDevLock(bdev);
retry:
ATABlkSelect(bdev,blk,cnt);
if (bdev->flags&BDF_EXT_SIZE)
ATACmd(bdev,ATA_WRITE_MULTI_EXT);
else
ATACmd(bdev,ATA_WRITE_MULTI);
bdev->flags|=BDF_LAST_WAS_WRITE;
while (cnt>0) {
timeout=tS+1.0;
while (TRUE) {
i=InU8(bdev->base0+ATAR0_STAT);
if (!(i & ATAS_DRDY)||!(i & ATAS_DRQ)) {
Yield;
} else
break;
if (/* i&ATAS_ERR||*/ tS>timeout) {
if (retries--) {
ATAWaitNotBUSY(bdev,0);
goto retry;
} else
throw('BlkDev');
}
}
sects_avail=1;
U32s_avail=sects_avail<<BLK_SIZE_BITS>>2;
RepOutU32(buf,U32s_avail,bdev->base0+ATAR0_DATA);
buf+=U32s_avail<<2;
cnt-=sects_avail;
retries=3;
}
ATAWaitNotBUSY(bdev,0);
if (unlock) BlkDevUnlock(bdev);
}
Bool ATAPISync(CBlkDev *bdev)
{
Bool okay=TRUE;
if (!ATAWaitNotBUSY(bdev,0))
okay=FALSE;
else {
if (bdev->flags & BDF_EXT_SIZE)
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
else
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
OutU8(bdev->base0+ATAR0_LCYL,0);
OutU8(bdev->base0+ATAR0_HCYL,0);
ATACmd(bdev,ATA_PACKET);
ATAPIWritePktWord(bdev,0,0x3500,0,0,0,0,0);
if (!ATAWaitNotBUSY(bdev,0))
okay=FALSE;
}
return okay;
}
U0 ATAPIClose(CBlkDev *bdev,I64 close_field=0x200,I64 track=0)
{
//0x200 CD/DVD part 1
//0x300 DVD part 2
if (bdev->flags & BDF_EXT_SIZE)
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
else
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
OutU8(bdev->base0+ATAR0_LCYL,0);
OutU8(bdev->base0+ATAR0_HCYL,0);
ATACmd(bdev,ATA_PACKET);
ATAPIWritePktWord(bdev,0,0x5B00,close_field,track,0,0,0);
ATAWaitNotBUSY(bdev,0);
}
U0 ATAPIWriteBlks(CBlkDev *bdev,U8 *buf, I64 native_blk, I64 cnt)
{
I64 U32s_avail;
U8 *buf2;
ATAWaitNotBUSY(bdev,0);
ATAPISeek(bdev,native_blk);
OutU8(bdev->base0+ATAR0_FEAT,0);
OutU8(bdev->base0+ATAR0_LCYL,bdev->blk_size);
OutU8(bdev->base0+ATAR0_HCYL,bdev->blk_size.u8[1]);
if (bdev->flags & BDF_EXT_SIZE)
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
else
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
OutU8(bdev->base0+ATAR0_CMD,ATA_PACKET);
ATAPIWritePktWord(bdev,0,0x0400,native_blk.u16[1],native_blk,cnt.u16[1],cnt,0);
bdev->flags|=BDF_LAST_WAS_WRITE;
ATAWaitNotBUSY(bdev,0);
ATAPISeek(bdev,native_blk);
if (bdev->flags & BDF_EXT_SIZE)
OutU8(bdev->base0+ATAR0_SELECT,0xEF|bdev->unit<<4);
else
OutU8(bdev->base0+ATAR0_SELECT,0xE0|bdev->unit<<4);
OutU8(bdev->base0+ATAR0_LCYL,bdev->blk_size);
OutU8(bdev->base0+ATAR0_HCYL,bdev->blk_size.u8[1]);
ATACmd(bdev,ATA_PACKET);
ATAPIWritePktWord(bdev,0,0xAA00,native_blk.u16[1],native_blk,cnt.u16[1],cnt,0);
buf2=buf+bdev->blk_size*cnt;
while (buf<buf2) {
ATAWaitDRQ(bdev,0);
U32s_avail=(InU8(bdev->base0+ATAR0_HCYL)<<8+InU8(bdev->base0+ATAR0_LCYL))>>2;
if (buf+U32s_avail<<2>buf2)
U32s_avail=(buf2-buf)>>2;
if (U32s_avail) {
RepOutU32(buf,U32s_avail,bdev->base0+ATAR0_DATA);
buf+=U32s_avail<<2;
sys_dsk_writes+=U32s_avail>>(BLK_SIZE_BITS-2);
}
}
ATAWaitNotBUSY(bdev,0);
}
Bool ATAWBlks(CPrt *p,U8 *buf, I64 blk, I64 cnt)
{
I64 n,spc;
CBlkDev *bdev=p->bdev;
Bool unlock;
spc=bdev->blk_size>>BLK_SIZE_BITS;
if (bdev->type==BDT_ATAPI) {
unlock=BlkDevLock(bdev);
ATAPIWaitReady(bdev,0);
}
while (cnt>0) {
n=cnt;
if (n>bdev->max_writes)
n=bdev->max_writes;
if (bdev->type==BDT_ATAPI)
ATAPIWriteBlks(bdev,buf,blk/spc,(n+spc-1)/spc);
else
ATAWriteBlks(bdev,buf,blk,n);
buf+=n<<BLK_SIZE_BITS;
blk+=n;
cnt-=n;
sys_dsk_writes+=n;
}
if (bdev->type==BDT_ATAPI) {
ATAPISync(bdev);
// ATAPIStartStop(bdev,0,FALSE);
if (unlock) BlkDevUnlock(bdev);
}
return TRUE;
}
Bool BootCdProbe(CBlkDev *bdev)
{
CKernel *img=CAlloc(CD_BLK_SIZE);
I64 i;
Bool result=FALSE;
"Port: %04X,%04X Unit: %02X ",bdev->base0,bdev->base1,bdev->unit;
if (ATAProbe(bdev->base0,bdev->base1,bdev->unit)==BDT_ATAPI) {
" ATAPI";
if (ATAPIStartStop(bdev,tS+5.0,TRUE)) {
" Started";
for (i=0;i<2;i++) { //Retry
if (ATAPIReadBlks2(bdev,tS+7.0,img,sys_boot_code.u16[1],1,FALSE)) {
if (img->compile_time==sys_compile_time) {
" Found";
return TRUE;
} else
" Read";
} else
" NoRead";
}
}
}
" Nope\n";
Free(img);
return result;
}
Bool BootCdProbeAll(CBlkDev *bdev)
{
I64 d1,d2,i,j,k;
bdev->base1=0;
for (k=0;k<256;k++) {
i=-1;
while (TRUE) {
j=PCIClassFind(0x010100+k,++i);
if (j<0)
break;
"Subcode:0x%X Bus:0x%X Dev:0x%X Fun:0x%X\n",k,j.u8[2],j.u8[1],j.u8[0];
d1=PCIReadU32(j.u8[2],j.u8[1],j.u8[0],0x10);
d2=PCIReadU32(j.u8[2],j.u8[1],j.u8[0],0x14);
if (d1&1 && d2&1) {
if (bdev->base0=d1&-8) {
bdev->unit=0;
if (BootCdProbe(bdev))
return TRUE;
bdev->unit=1;
if (BootCdProbe(bdev))
return TRUE;
}
}
d1=PCIReadU32(j.u8[2],j.u8[1],j.u8[0],0x18);
d2=PCIReadU32(j.u8[2],j.u8[1],j.u8[0],0x1C);
if (d1&1 && d2&1) {
if (bdev->base0=d1&-8) {
bdev->unit=0;
if (BootCdProbe(bdev))
return TRUE;
bdev->unit=1;
if (BootCdProbe(bdev))
return TRUE;
}
}
}
}
d1=0x1F0;
d2=0x3F6;
if (bdev->base0=d1&-8) {
bdev->unit=0;
if (BootCdProbe(bdev))
return TRUE;
bdev->unit=1;
if (BootCdProbe(bdev))
return TRUE;
}
d1=0x170;
d2=0x376;
if (bdev->base0=d1&-8) {
bdev->unit=0;
if (BootCdProbe(bdev))
return TRUE;
bdev->unit=1;
if (BootCdProbe(bdev))
return TRUE;
}
}
U0 ATARepEntry(I64 base0,I64 base1,I64 unit,I64 irq,U8 *msg,CATARep **_root,I64 *num_hints)
{
I64 type;
base0&=-8;
base1&=-4;
CATARep *tempha;
if (type=ATAProbe(base0,base1,unit)) {
*num_hints+=1;
"\n\n$$PURPLE$$ $$BT+X,\"%d\",LM=\"%d\\n\"$$$$FG$$$$LM,4$$",*num_hints,*num_hints;
if (type==BDT_ATA)
"$$RED$$ATA ";
else
"$$RED$$ATAPI ";
"$$LTBLUE$$%s$$FG$$\nBase0:0x%04X Base1:0x%04X\nIrq:0x%02X Unit:%d$$LM,0$$\n",msg,base0,base1,irq,unit;
if (_root) {
tempha=CAlloc(sizeof(CATARep));
tempha->next=*_root;
*_root=tempha;
tempha->num=*num_hints;
tempha->type=type;
tempha->base0=base0;
tempha->base1=base1;
tempha->unit=unit;
}
}
}
Bool ATARepExitAllApplications()
{
"\nWe're going to probe hardware.\n"
"$$RED$$Exit all other applications.$$FG$$\n"
"Press '$$PURPLE$$p$$FG$$' to probe or '$$PURPLE$$s$$FG$$' to skip.\n";
if (ToUpper(GetChar(,FALSE))=='S')
return TRUE;
else
return FALSE;
}
public I64 ATARep(Bool pmt=TRUE,Bool just_ide=FALSE,CATARep **_root=NULL)
{
I64 d1,d2,d3,i,j,k,cnt=0,unlock_flags=0,num_hints=0;
#assert NUM_BLKDEVS<=64
Bool old_preempt;
if (_root) *_root=NULL;
if (pmt && ATARepExitAllApplications)
return 0;
old_preempt=Preempt(OFF);
for (i=0;i<NUM_BLKDEVS;i++)
if (sys_blkdevs[i].bd_signature==BD_SIGNATURE_VAL)
BEqu(&unlock_flags,i,
BlkDevLock(&sys_blkdevs[i]));
if (!just_ide)
for (k=0;k<256;k++) {
i=-1;
while (TRUE) {
j=PCIClassFind(0x010100+k,++i);
if (j<0)
break;
"\nSubcode:0x%X Bus:0x%X Dev:0x%X Fun:0x%X\n",k,j.u8[2],j.u8[1],j.u8[0];
cnt++;
d1=PCIReadU32(j.u8[2],j.u8[1],j.u8[0],0x10);
d2=PCIReadU32(j.u8[2],j.u8[1],j.u8[0],0x14);
d3=PCIReadU8(j.u8[2],j.u8[1],j.u8[0],0x3C);
if (d1&1 && d2&1) {
ATARepEntry(d1,d2,0,d3,"Primary IDE",_root,&num_hints);
ATARepEntry(d1,d2,1,d3,"Primary IDE",_root,&num_hints);
} else {
d1=0x1F0; d2=0x3F6; d3=14;
ATARepEntry(d1,d2,0,d3,"Primary IDE",_root,&num_hints);
ATARepEntry(d1,d2,1,d3,"Primary IDE",_root,&num_hints);
}
d1=PCIReadU32(j.u8[2],j.u8[1],j.u8[0],0x18);
d2=PCIReadU32(j.u8[2],j.u8[1],j.u8[0],0x1C);
if (d1&1 && d2&1) {
ATARepEntry(d1,d2,0,d3,"Secondary IDE",_root,&num_hints);
ATARepEntry(d1,d2,1,d3,"Secondary IDE",_root,&num_hints);
} else {
d1=0x170; d2=0x376; d3=15;
ATARepEntry(d1,d2,0,d3,"Secondary IDE",_root,&num_hints);
ATARepEntry(d1,d2,1,d3,"Secondary IDE",_root,&num_hints);
}
}
}
if (!cnt) {
d1=0x1F0; d2=0x3F6; d3=14;
ATARepEntry(d1,d2,0,d3,"Primary IDE",_root,&num_hints);
ATARepEntry(d1,d2,1,d3,"Primary IDE",_root,&num_hints);
d1=0x170; d2=0x376; d3=15;
ATARepEntry(d1,d2,0,d3,"Secondary IDE",_root,&num_hints);
ATARepEntry(d1,d2,1,d3,"Secondary IDE",_root,&num_hints);
}
NewLine(2);
for (i=0;i<NUM_BLKDEVS;i++)
if (Bt(&unlock_flags,i))
BlkDevUnlock(&sys_blkdevs[i]);
Preempt(old_preempt);
return num_hints;
}
CATARep *ATAIDDrvs(CATARep *root,U8 _sys_acct_drv,CATARep **_ata_drv,CATARep **_atapi_drv)
{
CATARep *result=NULL,*tempha=root,*ata_drv=NULL,*atapi_drv=NULL;
CBlkDev *bdev;
Bool was_silent=Silent(ON);
try
bdev=Drv2BlkDev(_sys_acct_drv);
catch {
Fs->catch_except=TRUE;
bdev=NULL;
}
Silent(was_silent);
while (tempha) {
if (!result && bdev && bdev->type==tempha->type) {
if (bdev->type==BDT_ATAPI &&
bdev->base0==tempha->base0 && bdev->unit==tempha->unit)
result=atapi_drv=tempha;
else if (bdev->type==BDT_ATA && bdev->base0==tempha->base0 &&
bdev->base1==tempha->base1 && bdev->unit==tempha->unit)
result=ata_drv=tempha;
}
if (!result || result->type!=tempha->type) {
if (tempha->type==BDT_ATA) {
if (!ata_drv || tempha->unit<ata_drv->unit ||
tempha->unit==ata_drv->unit && tempha->num<ata_drv->num)
ata_drv=tempha;
} else if (tempha->type==BDT_ATAPI) {
if (!atapi_drv || tempha->unit<atapi_drv->unit ||
tempha->unit==atapi_drv->unit && tempha->num<atapi_drv->num)
atapi_drv=tempha;
}
}
tempha=tempha->next;
}
if (_ata_drv) *_ata_drv =ata_drv;
if (_atapi_drv) *_atapi_drv=atapi_drv;
return result;
}
CBlkDev *ATAMount(U8 first_drv_let,I64 type,I64 base0,I64 base1,I64 unit)
{
CBlkDev *result;
if (0<=first_drv_let-'A'<NUM_PRTS && (type==BDT_ATA || type==BDT_ATAPI) &&
0<=unit<=1) {
result=BlkDevNextFree(first_drv_let,type);
result->unit=unit;
result->base0=base0;
result->base1=base1;
if (BlkDevAdd(result,FALSE,FALSE))
return result;
}
return NULL;
}
I64 AutoMountIDE()
{
I64 result=0;
CATARep *root=NULL,*ata_drv=NULL,*atapi_drv=NULL,*tempha;
ATARep(FALSE,TRUE,&root);
ATAIDDrvs(root,*sys_acct,&ata_drv,&atapi_drv);
if (ata_drv && ATAMount(sys_first_hd_drv_let,BDT_ATA,
ata_drv->base0,ata_drv->base1,ata_drv->unit))
result++;
if (atapi_drv && ATAMount(sys_first_cd_drv_let,BDT_ATAPI,
atapi_drv->base0,atapi_drv->base1,atapi_drv->unit))
result++;
tempha=root;
while (tempha) {
if (tempha!=ata_drv && tempha!=atapi_drv) {
if (tempha->type==BDT_ATA && ATAMount(sys_first_hd_drv_let,BDT_ATA,
tempha->base0,tempha->base1,tempha->unit))
result++;
else if (tempha->type==BDT_ATAPI && ATAMount(sys_first_cd_drv_let,BDT_ATAPI,
tempha->base0,tempha->base1,tempha->unit))
result++;
}
tempha=tempha->next;
}
LinkedLstDel(root);
sys_auto_mount_ide_cnt=result;
return result;
}
+339
View File
@@ -0,0 +1,339 @@
U0 SetBlkDevLockFwding(CBlkDev *bdev)
{
CBlkDev *bdev1;
I64 i;
switch (bdev->type) {
case BDT_RAM:
break;
case BDT_ATA:
case BDT_ATAPI:
for (i=0;i<NUM_BLKDEVS;i++) {
bdev1=&sys_blkdevs[i];
if (bdev1->bd_signature==BD_SIGNATURE_VAL && bdev!=bdev1 &&
(bdev1->type==BDT_ATAPI || bdev1->type==BDT_ATA) &&
bdev1->base0==bdev->base0) {
bdev->lock_fwding=bdev1;
break;
}
}
break;
}
}
I64 BlkDevAdd(CBlkDev *bdev,Bool one_prt,Bool make_free)
{
I64 i,j,ext_base,offset,result=0;
CPrt *p;
CBootStruct br;
CMasterBoot mbr;
bdev->bd_signature=BD_SIGNATURE_VAL;
if (make_free)
p=PrtMakeFree(bdev->first_drv_let+result);
else
p=PrtNextFree(bdev->first_drv_let+result);
p->bdev=bdev;
p->size=bdev->max_blk+1;
switch (bdev->type) {
case BDT_RAM:
p->pt_signature=PRT_SIGNATURE_VAL;
p->type=PT_REDSEA;
//This is to force creation of a RAM
//drive during boot, so it is probably
//MAlloced to the same addr and can
//be assumed to be already formatted.
//If this line is removed, RAM Drives
//will be allocated on a just-in-time
//basis.
if (BlkDevInit(bdev))
result++;
else
p->pt_signature=0;
break;
case BDT_ATA:
p->pt_signature=PRT_SIGNATURE_VAL; //Temporarily validate
if (!BlkDevInit(bdev))
p->pt_signature=0; //Revoke validation
else {
p->pt_signature=0; //Revoke validation
if (one_prt) {
p->pt_signature=PRT_SIGNATURE_VAL;
result++;
p->type=PT_REDSEA;
p->size=bdev->max_blk+1;
//The following read is a test read.
//if it hangs, the drive is not supported.
ATAReadBlks(bdev,&mbr,0,1);
break;
}
offset=0;
ext_base=INVALID_CLUSTER;
while (TRUE) {
ATAReadBlks(bdev,&mbr,offset,1);
if (mbr.signature!=0xAA55)
break;
j=-1;
for (i=0;i<4;i++) {
if (mbr.p[i].type) {
if (make_free)
p=PrtMakeFree(bdev->first_drv_let+result);
else
p=PrtNextFree(bdev->first_drv_let+result);
p->bdev=bdev;
p->offset=mbr.p[i].offset+offset;
p->size =mbr.p[i].size;
switch (mbr.p[i].type) {
case MBR_PT_REDSEA:
p->pt_signature=PRT_SIGNATURE_VAL;
result++;
p->type=PT_REDSEA;
RedSeaFSPrtInit(p);
break;
case MBR_PT_FAT32a:
case MBR_PT_FAT32b:
case MBR_PT_FAT32c:
case MBR_PT_FAT32d:
case MBR_PT_FAT32e:
case MBR_PT_FAT32f:
ATAReadBlks(bdev,&br,p->offset,1);
p->pt_signature=PRT_SIGNATURE_VAL;
result++;
if (br.signature==MBR_PT_REDSEA) {
p->type=PT_REDSEA;
RedSeaFSPrtInit(p);
} else {
p->type=PT_FAT32;
FAT32PrtInit(p);
}
break;
case MBR_PT_NTFS:
p->pt_signature=PRT_SIGNATURE_VAL;
result++;
p->type=PT_NTFS;
break;
case 5:
case 15:
j=i;
break;
default:
p->pt_signature=PRT_SIGNATURE_VAL;
result++;
p->type=PT_UNKNOWN;
}
}
}
if (j<0)
break;
if (!mbr.p[j].offset)
break;
if (ext_base==INVALID_CLUSTER) {
offset=mbr.p[j].offset;
ext_base=offset;
} else
offset=mbr.p[j].offset+ext_base;
}
}
break;
case BDT_ATAPI:
p->pt_signature=PRT_SIGNATURE_VAL;
result++;
p->type=PT_ISO9660; //Start with this
p->size =0;
break;
}
if (result)
SetBlkDevLockFwding(bdev);
else
MemSet(bdev,0,sizeof(CBlkDev));
return result;
}
Bool DrvEnable(U8 drv_let,Bool val)
{//This can be used to unmount a drive or remount,
//but not mount the first time.
CPrt *p;
Bool result=FALSE;
try {
p=Drv2Prt(drv_let);
result=!LBEqu(&p->type,PTf_DISABLE,!val);
} catch
Fs->catch_except=TRUE;
return result;
}
CATARep *ATARepFind(CATARep *haystack_root,I64 needle_num)
{
while (haystack_root) {
if (haystack_root->num==needle_num)
return haystack_root;
haystack_root=haystack_root->next;
}
return NULL;
}
U0 Mount(Bool repartition=FALSE)
{
CBlkDev *bdev;
I64 first_prt_num,type,unit,num_hints;
U8 blks_buf[128],addr_buf[128],base0_buf[128],base1_buf[128];
Bool add;
CATARep *root,*tempha;
do {
PrtRep;
"\n****** Mount Drives ******\n"
"The first drive letter is the letter\n"
"of the first partition. If adding\n"
"a hard drive, you should pick 'C'.\n"
"If more than one partition is present\n"
"they will be lettered in sequence.\n"
"\nFirst Drive Letter ($$PURPLE$$<ENTER>$$FG$$ to exit):";
first_prt_num=ToUpper(GetChar)-'A';
NewLine;
if (0<=first_prt_num<NUM_PRTS) {
"\t$$PURPLE$$1$$FG$$=RAM\n\t$$PURPLE$$2$$FG$$=ATA(Harddisk)\n"
"\t$$PURPLE$$3$$FG$$=ATAPI(CD-ROM)\nType:";
type=GetChar-'0';
NewLine;
unit=0;
if (type==BDT_ATA || type==BDT_ATAPI) {
num_hints=ATARep(,,&root);
do {
if (num_hints)
"Enter dev number or\nport with $$PURPLE$$0x$$FG$$ prefix.\n"
"I/O Port Base0:\n";
else
"Include $$PURPLE$$0x$$FG$$ prefix.\nI/O Port Base0:\n";
GetS(base0_buf,128);
} while (!A2I64(base0_buf));
if (1<=A2I64(base0_buf)<=num_hints) {
tempha=ATARepFind(root,A2I64(base0_buf));
SPrint(base0_buf,"0x%X",tempha->base0);
SPrint(base1_buf,"0x%X",tempha->base1);
unit=tempha->unit;
} else {
if (type==BDT_ATAPI)
StrCpy(base1_buf,"0");
else
do {
"I/O Port Base1:\n";
GetS(base1_buf,128);
} while (!A2I64(base1_buf));
do {
"\t$$PURPLE$$0$$FG$$=Master\n\t$$PURPLE$$1$$FG$$=Slave\nUnit:";
unit=GetChar-'0';
} while (!(0<=unit<=1));
NewLine;
}
LinkedLstDel(root);
}
if (type==BDT_RAM) {
"Addr of RAM disk ($$PURPLE$$<ENTER>$$FG$$ to MAlloc):";
GetS(addr_buf,128);
"Blks of 512 bytes:";
GetS(blks_buf,128);
}
if (BDT_NULL<type<BDT_NUM_TYPES && 0<=unit<=1) {
bdev=BlkDevNextFree(first_prt_num+'A',type);
bdev->unit=unit;
if (type==BDT_RAM) {
if (!*addr_buf) StrCpy(addr_buf,"0");
bdev->RAM_dsk=A2I64(addr_buf);
bdev->max_blk=A2I64(blks_buf)-1;
}
if (type==BDT_ATA ||
type==BDT_ATAPI) {
bdev->base0=A2I64(base0_buf);
bdev->base1=A2I64(base1_buf);
}
add=TRUE;
if (type==BDT_ATA && repartition) {
"\nReformat WHOLE drive!";
if (YorN) {
if (!BlkDevAdd(bdev,TRUE,TRUE))
"\n\n$$BK,1$$$$RED$$Operation Failed$$BK,0$$$$FG$$\n\n";
else
CallExtStr("PrtDsk",bdev->first_drv_let);
add=FALSE;
}
}
if (add && !BlkDevAdd(bdev,FALSE,TRUE))
"\n\n$$BK,1$$$$RED$$Operation Failed$$BK,0$$$$FG$$\n\n";
} else
"\n\n$$BK,1$$$$RED$$Operation Failed$$BK,0$$$$FG$$\n\n";
}
} while (0<=first_prt_num<NUM_PRTS);
}
I64 SysPmtI64()
{
U8 st[136];
StrCpy(st,"0x");
GetS(st+2,134,FALSE);
if (!st[2])
return 0;
else
return A2I64(st);
}
Bool PmtBaseUnit(CBlkDev *bdev)
{
I64 ch;
Bool probe;
" TempleOS\n\n\n";
#exe {
if (kernel_cfg->opts[CFG_DONT_PROBE])
StreamPrint("probe=FALSE;");
else
StreamPrint("probe=TRUE;");
};
if (!probe || !BootCdProbeAll(bdev)) {
"\nDon't worry. This is not a product\n"
"registration. TempleOS just needs the\n"
"I/O port numbers for the CD-ROM.\n"
"\nRetry the ports above or check Windows\n"
"system information under I/O ports for\n"
"'IDE', 'ATA' or 'SATA'.\n"
"\n\nEnter 4-digit hex I/O Port number.\n"
"CD-ROM I/O Port Base0: 0x";
bdev->base0=SysPmtI64;
bdev->base1=0;
bdev->unit =0;
if (bdev->base0) {
"\nUnit (0 or 1): ";
do ch=GetChar(,FALSE);
while (!('0'<=ch<='1'));
'' ch;
bdev->unit=ch-'0';
cdrom_boot_is_good=BootCdProbe(bdev);
return TRUE;
} else {
cdrom_boot_is_good=FALSE;
return FALSE;
}
}
return FALSE;
}
U0 BlkDevsInitAll()
{
CBlkDev *bdev;
I64 i;
sys_blkdevs=CAlloc(sizeof(CBlkDev)*NUM_BLKDEVS);
sys_prts=CAlloc(sizeof(CPrt)*NUM_PRTS);
for (i=0;i<NUM_PRTS;i++)
drv_to_prt[i]=&sys_prts[i];
sys_raw_col=0;
#exe {
if (kernel_cfg->opts[CFG_AUTO_MOUNT_IDE])
StreamPrint("AutoMountIDE;");
StreamPrint("#exe {OptOff(OPTf_WARN_PAREN);}");
StreamDoc(kernel_cfg->add_dev);
StreamPrint("#exe {OptOn(OPTf_WARN_PAREN);}");
};
PrtRep;
}
+265
View File
@@ -0,0 +1,265 @@
I64 FSize(CFile *f)
{
if (f)
return f->de.size;
else
return 0;
}
CFile *FOpen(U8 *filename,U8 *flags,I64 cnt=0)
{ //allows flags "r","w","w+". Include a "c" for contiguous.
//(It uses $LK,"StrOcc",A="MN:StrOcc"$() for 'w', 'r', '+', 'c')
CFile *f=CAlloc(sizeof(CFile));
CFileAccess *fa;
U8 *full_name;
Bool contiguous=StrOcc(flags,'c');
f->cluster=INVALID_CLUSTER;
f->fblk_num=0;
if (cnt>0)
f->max_blk=cnt-1;
else
f->max_blk=MAX_I64;
f->file_cluster_num=INVALID_CLUSTER;
full_name=FileNameAbs(filename);
f->p=Drv2Prt(*full_name);
if (f->p->type==PT_REDSEA)
contiguous=TRUE;
if (contiguous) {
f->flags|=FF_CONTIGUOUS;
if (f->p->type!=PT_REDSEA && !(FileAttr(filename) & _ATTR_CONTIGUOUS))
throw('File');
}
f->cluster_buf=CAlloc(f->p->spc<<BLK_SIZE_BITS);
if (StrOcc(flags,'w')) {
f->flags=f->flags|FF_WRITE|FF_NEEDS_WRITE;
if (StrOcc(flags,'+')) {
if (FileFind(full_name,&f->de,FUF_JUST_FILES)) {
Free(full_name);
if (contiguous)
f->max_blk=(FSize(f)+BLK_SIZE-1)>>BLK_SIZE_BITS-1;
return f;
}
} else
Del(full_name,FALSE);
f->de.full_name=full_name;
f->flags|=FF_NEW_FILE;
if (fa=FileAccessNew(full_name)) {
StrCpy(f->de.name,fa->mask);
if (cnt>0) { //We pre-alloc the whole thing.
f->de.cluster=ClustersAlloc(f->p,0,
(cnt+f->p->spc-1)/f->p->spc,contiguous);
f->de.size=cnt<<BLK_SIZE_BITS;
DirNew(fa->p,Fs->cur_dir,&f->de,TRUE);
f->flags&=~FF_NEW_FILE;
}
FileAccessDel(fa);
if (!contiguous || cnt>0)
return f;
}
} else {
if (FileFind(full_name,&f->de,FUF_JUST_FILES)) {
Free(full_name);
f->max_blk=(FSize(f)+BLK_SIZE-1)>>BLK_SIZE_BITS-1;
return f;
}
}
Free(f->cluster_buf);
Free(full_name);
Free(f);
return NULL;
}
U0 FClose(CFile *f)
{
CFileAccess *fa;
if (f) {
if (f->flags & FF_BUF_DIRTY) {
WClusters(f->p,f->cluster_buf,f->cluster,1);
f->flags&=~FF_BUF_DIRTY;
}
if (f->flags & FF_NEEDS_WRITE) {
if (fa=FileAccessNew(f->de.full_name)) {
if (!(f->flags & FF_USE_OLD_DATETIME))
f->de.datetime=Now;
if (f->flags & FF_NEW_FILE)
DirNew(fa->p,Fs->cur_dir,&f->de,TRUE);
else
DirNew(fa->p,Fs->cur_dir,&f->de,FALSE);
FileAccessDel(fa);
} else
throw('File');
}
Free(f->cluster_buf);
Free(f->de.full_name);
Free(f);
}
}
I64 FSetCluster(CFile *f,I64 c,I64 blk,Bool read)
{
CPrt *p=f->p;
I64 i;
if (f->cluster!=c) {
if (f->flags & FF_BUF_DIRTY) {
i=p->spc;
if (f->max_blk!=MAX_I64) {
i=f->max_blk+1-f->file_cluster_num*p->spc;
if (i>p->spc)
i=p->spc;
}
WClustersBlks(p,f->cluster_buf,f->cluster,i);
f->flags=f->flags & ~FF_BUF_DIRTY;
}
f->cluster=c;
f->file_cluster_num=blk/p->spc;
if (read) {
i=p->spc;
if (f->max_blk!=MAX_I64) {
i=f->max_blk+1-f->file_cluster_num*p->spc;
if (i>p->spc)
i=p->spc;
}
c=RClustersBlks(p,f->cluster_buf,c,i);
}
}
return c;
}
Bool FRBlks(CFile *f,U8 *buf,I64 blk=FFB_NEXT_BLK,I64 cnt=1)
{
CPrt *p=f->p;
I64 spc=p->spc,i,j,c=f->de.cluster;
if (!f || !p) return FALSE;
if (blk==FFB_NEXT_BLK)
blk=f->fblk_num;
if (blk+cnt-1>f->max_blk)
return FALSE;
if (cnt<=0) return TRUE;
if (f->flags & FF_CONTIGUOUS) {
RBlks(p,buf,Cluster2Blk(p,c)+blk,cnt);
blk+=cnt;
} else {
i=blk/spc;
if (0<=f->file_cluster_num<=i) {
c=f->cluster;
i-=f->file_cluster_num;
}
if (i>0)
c=ClusterNumNext(p,c,i);
if (i=blk%spc) {
c=FSetCluster(f,c,blk,TRUE);
if (cnt<spc-i)
j=cnt;
else
j=spc-i;
MemCpy(buf,f->cluster_buf+i<<BLK_SIZE_BITS,j<<BLK_SIZE_BITS);
buf+=j<<BLK_SIZE_BITS;
cnt-=j;
blk+=j;
}
while (cnt>=spc) {
c=FSetCluster(f,c,blk,TRUE);
MemCpy(buf,f->cluster_buf,spc<<BLK_SIZE_BITS);
buf+=spc<<BLK_SIZE_BITS;
cnt-=spc;
blk+=spc;
}
if (cnt>0) {
c=FSetCluster(f,c,blk,TRUE);
MemCpy(buf,f->cluster_buf,cnt<<BLK_SIZE_BITS);
buf+=cnt<<BLK_SIZE_BITS;
blk+=cnt;
}
}
f->fblk_num=blk;
return TRUE;
}
Bool FWBlks(CFile *f,U8 *buf,I64 blk=FFB_NEXT_BLK,I64 cnt=1)
{
CPrt *p=f->p;
I64 spc=p->spc,i,j,c=f->de.cluster,c1;
if (!f || !p) return FALSE;
if (blk==FFB_NEXT_BLK)
blk=f->fblk_num;
if (blk+cnt-1>f->max_blk)
return FALSE;
if (!(f->flags & FF_WRITE))
return FALSE;
if (cnt<=0) return TRUE;
if (f->flags & FF_CONTIGUOUS) {
WBlks(p,buf,Cluster2Blk(p,c)+blk,cnt);
blk+=cnt;
} else {
if (!c) {
c=ClustersAlloc(p,0,1,FALSE);
f->file_cluster_num=0;
f->cluster=c;
f->de.cluster=c;
f->flags|=FF_NEEDS_WRITE|FF_NEW_FILE;
}
i=blk/spc;
if (0<=f->file_cluster_num<=i) {
c=f->cluster;
i-=f->file_cluster_num;
}
while (i>0) {
c1=c;
c=ClusterNumNext(p,c1,1);
if (c==INVALID_CLUSTER) {
c=ClustersAlloc(p,c1,i,FALSE);
if (i>1)
c=ClusterNumNext(p,c,i-1);
break;
} else
i--;
}
if (i=blk%spc) {
FSetCluster(f,c,blk,TRUE);
if (cnt<spc-i)
j=cnt;
else
j=spc-i;
MemCpy(f->cluster_buf+BLK_SIZE*i,buf,j<<BLK_SIZE_BITS);
f->flags|=FF_BUF_DIRTY;
buf+=j<<BLK_SIZE_BITS;
cnt-=j;
blk+=j;
if (cnt>0) {
c1=c;
c=ClusterNumNext(p,c1,1);
if (c==INVALID_CLUSTER)
c=ClustersAlloc(p,c1,1,FALSE);
}
}
while (cnt>=spc) {
FSetCluster(f,c,blk,FALSE);
MemCpy(f->cluster_buf,buf,spc<<BLK_SIZE_BITS);
f->flags|=FF_BUF_DIRTY;
buf+=spc<<BLK_SIZE_BITS;
cnt-=spc;
blk+=spc;
if (cnt>0) {
c1=c;
c=ClusterNumNext(p,c1,1);
if (c==INVALID_CLUSTER)
c=ClustersAlloc(p,c1,1,FALSE);
}
}
if (cnt>0) {
FSetCluster(f,c,blk,TRUE);
MemCpy(f->cluster_buf,buf,cnt<<BLK_SIZE_BITS);
f->flags|=FF_BUF_DIRTY;
buf+=cnt<<BLK_SIZE_BITS;
blk+=cnt;
}
if (f->de.size<blk<<BLK_SIZE_BITS)
f->de.size=blk<<BLK_SIZE_BITS;
}
f->fblk_num=blk;
return TRUE;
}
+144
View File
@@ -0,0 +1,144 @@
U0 DskCacheInit(I64 size_in_U8s)
{
CCacheBlk *tempc;
I64 i,cnt;
while (LBts(&sys_semas[SYS_SEMA_DSK_CACHE],0))
Yield;
Free(sys_dsk_cache_ctrl);
Free(sys_dsk_cache_base);
Free(sys_dsk_cache_hash_table);
if (size_in_U8s<0x2000) {
sys_dsk_cache_ctrl=NULL;
sys_dsk_cache_base=NULL;
sys_dsk_cache_hash_table=NULL;
} else {
sys_dsk_cache_ctrl=ACAlloc(offset(CCacheBlk.body));
sys_dsk_cache_base=AMAlloc(size_in_U8s);
QueInit(sys_dsk_cache_ctrl);
cnt=MSize(sys_dsk_cache_base)/sizeof(CCacheBlk);
sys_dsk_cache_size=cnt*BLK_SIZE;
for (i=0;i<cnt;i++) {
tempc=sys_dsk_cache_base+i;
QueIns(tempc,sys_dsk_cache_ctrl->last_lru);
tempc->next_hash=tempc->last_hash=tempc;
tempc->p=NULL;
tempc->blk=0;
}
sys_dsk_cache_hash_table=AMAlloc(DSK_CACHE_HASH_SIZE*sizeof(U8 *)*2);
for (i=0;i<DSK_CACHE_HASH_SIZE;i++) {
tempc=sys_dsk_cache_hash_table(U8 *)+i*sizeof(U8 *)*2-offset(CCacheBlk.next_hash);
tempc->next_hash=tempc->last_hash=tempc;
}
}
LBtr(&sys_semas[SYS_SEMA_DSK_CACHE],0);
}
I64 DskCacheHash(I64 blk)
{
I64 i=blk & (DSK_CACHE_HASH_SIZE-1);
return sys_dsk_cache_hash_table(U8 *)+i<<4-offset(CCacheBlk.next_hash);
}
U0 DskCacheQueRem(CCacheBlk *tempc)
{
QueRem(tempc);
tempc->next_hash->last_hash=tempc->last_hash;
tempc->last_hash->next_hash=tempc->next_hash;
}
U0 DskCacheQueIns(CCacheBlk *tempc)
{
CCacheBlk *temp_n,*temp_l;
QueIns(tempc,sys_dsk_cache_ctrl->last_lru);
temp_l=DskCacheHash(tempc->blk);
temp_n=temp_l->next_hash;
tempc->last_hash=temp_l;
tempc->next_hash=temp_n;
temp_l->next_hash=temp_n->last_hash=tempc;
}
CCacheBlk *DskCacheFind(CPrt *p,I64 blk)
{
CCacheBlk *tempc,*tempc1=DskCacheHash(blk);
tempc=tempc1->next_hash;
while (tempc!=tempc1) {
if (tempc->p==p && tempc->blk==blk)
return tempc;
tempc=tempc->next_hash;
}
return NULL;
}
U0 DskCacheAdd(CPrt *p,U8 *buf, I64 blk, I64 cnt)
{
CCacheBlk *tempc;
if (sys_dsk_cache_base) {
while (LBts(&sys_semas[SYS_SEMA_DSK_CACHE],0))
Yield;
while (cnt-->0) {
if (!(tempc=DskCacheFind(p,blk)))
tempc=sys_dsk_cache_ctrl->next_lru;
DskCacheQueRem(tempc);
MemCpy(&tempc->body,buf,BLK_SIZE);
tempc->p=p;
tempc->blk=blk;
DskCacheQueIns(tempc);
blk++;
buf+=BLK_SIZE;
}
LBtr(&sys_semas[SYS_SEMA_DSK_CACHE],0);
}
}
U0 DskCacheInvalidate2(CPrt *p)
{
CCacheBlk *tempc,*tempc1;
if (sys_dsk_cache_base) {
while (LBts(&sys_semas[SYS_SEMA_DSK_CACHE],0))
Yield;
tempc=sys_dsk_cache_ctrl->last_lru;
while (tempc!=sys_dsk_cache_ctrl) {
tempc1=tempc->last_lru;
if (tempc->p==p) {
DskCacheQueRem(tempc);
tempc->p=NULL;
tempc->blk=0;
tempc->next_hash=tempc->last_hash=tempc;
QueIns(tempc,sys_dsk_cache_ctrl->last_lru);
}
tempc=tempc1;
}
LBtr(&sys_semas[SYS_SEMA_DSK_CACHE],0);
}
}
U0 RCache(CPrt *p,U8 **_buf, I64 *_blk, I64 *_cnt)
{
CCacheBlk *tempc;
if (sys_dsk_cache_base) {
while (LBts(&sys_semas[SYS_SEMA_DSK_CACHE],0))
Yield;
//fetch leading blks from cache
while (*_cnt>0) {
if (tempc=DskCacheFind(p,*_blk)) {
MemCpy(*_buf,&tempc->body,BLK_SIZE);
*_cnt-=1;
*_buf+=BLK_SIZE;
*_blk+=1;
} else
break;
}
//fetch trailing blks from cache
while (*_cnt>0) {
if (tempc=DskCacheFind(p,*_blk+*_cnt-1)) {
MemCpy(*_buf+(*_cnt-1)<<BLK_SIZE_BITS,&tempc->body,BLK_SIZE);
*_cnt-=1;
} else
break;
}
LBtr(&sys_semas[SYS_SEMA_DSK_CACHE],0);
}
}
+283
View File
@@ -0,0 +1,283 @@
Bool DirNew(CPrt *p,U8 *cur_dir,CDirEntry *tempde,Bool free_old_chain=TRUE)
{
switch (p->type) {
case PT_REDSEA:
return RedSeaFSDirNew(p,cur_dir,tempde,free_old_chain);
case PT_FAT32:
return FAT32DirNew(p,cur_dir,tempde,free_old_chain);
case PT_ISO9660:
PrintErr("Not Writable\n");
return FALSE;
default:
PrintErr("File System Not Supported\n");
return FALSE;
}
}
U0 DirEntryDel(CDirEntry *tempde)
{ //Doesn't Free user_data
if (tempde) {
Free(tempde->full_name);
Free(tempde);
}
}
U0 DirEntryDel2(CDirEntry *tempde)
{ //Frees user_data
if (tempde) {
Free(tempde->full_name);
Free(tempde->user_data);
Free(tempde);
}
}
U0 DirLstDel(CDirEntry *tempde)
{ //Doesn't Free user_data
CDirEntry *tempde2;
while (tempde) {
tempde2=tempde->next;
if (tempde->sub)
DirLstDel(tempde->sub);
DirEntryDel(tempde);
tempde=tempde2;
}
}
U0 DirLstDel2(CDirEntry *tempde)
{ //Frees user_data
CDirEntry *tempde2;
while (tempde) {
tempde2=tempde->next;
if (tempde->sub)
DirLstDel2(tempde->sub);
DirEntryDel2(tempde);
tempde=tempde2;
}
}
I64 DirEntryCompareName(CDirEntry *e1,CDirEntry *e2)
{
U8 buf1[CDIR_FILENAME_LEN],buf2[CDIR_FILENAME_LEN],
buf3[CDIR_FILENAME_LEN],buf4[CDIR_FILENAME_LEN];
I64 d1=0,d2=0;
if (e1->attr & _ATTR_DIR)
d1=1;
if (e2->attr & _ATTR_DIR)
d2=1;
if (d1!=d2)
return d2-d1;
else {
StrCpy(buf1,e1->name);
StrCpy(buf2,e2->name);
FileExtRem(buf1,buf3);
FileExtRem(buf2,buf4);
if (d1=StrCmp(buf3,buf4))
return d1;
return StrCmp(buf1,buf2);
}
}
I64 DirEntryCompareCluster(CDirEntry *e1,CDirEntry *e2)
{
return e1->cluster-e2->cluster;
}
#define SK_NAME 0
#define SK_CLUSTER 1
U0 DirFilesSort(CDirEntry **_tempde,I64 key)
{
I64 i,cnt=0;
CDirEntry *tempde=*_tempde,*tempde1,**sort_buf;
if (tempde) {
tempde1=tempde;
while (tempde1) {
cnt++;
tempde1=tempde1->next;
}
if (cnt>1) {
sort_buf=MAlloc(cnt*sizeof(U8 *));
i=0;
tempde1=tempde;
while (tempde1) {
sort_buf[i++]=tempde1;
tempde1=tempde1->next;
}
nobound_switch(key) {
case SK_NAME:
QSortI64(sort_buf,cnt,&DirEntryCompareName);
break;
case SK_CLUSTER:
QSortI64(sort_buf,cnt,&DirEntryCompareCluster);
break;
}
tempde=sort_buf[0];
*_tempde=tempde;
for (i=0;i<cnt-1;i++) {
tempde1=sort_buf[i];
tempde1->next=sort_buf[i+1];
}
tempde1=sort_buf[i];
tempde1->next=NULL;
Free(sort_buf);
tempde1=tempde;
while (tempde1) {
if (tempde1->sub)
DirFilesSort(&tempde1->sub,key);
tempde1=tempde1->next;
}
} else
if (tempde->sub)
DirFilesSort(&tempde->sub,key);
}
}
CDirEntry *DirFilesFlatten(CDirEntry *tempde,CDirEntry **_result,I64 fuf_flags)
{ //returns last node
CDirEntry *tempde1;
Bool del;
if (tempde)
while (TRUE) {
tempde1=tempde->next;
if (!(tempde->attr&_ATTR_DIR)||!(fuf_flags&FUF_JUST_FILES)) {
_result=*_result=tempde;
del=FALSE;
} else
del=TRUE;
if (tempde->sub) {
_result=DirFilesFlatten(tempde->sub,_result,fuf_flags);
tempde->sub=NULL;
}
if (del)
DirEntryDel(tempde);
if (tempde1)
tempde=tempde1;
else
break;
}
*_result=NULL;
return _result;
}
CDirEntry *SysFilesFind(U8 *files_find_mask,I64 fuf_flags)
{
CPrt *p=Fs->cur_prt;
CDirEntry *result=NULL;
PrtChk(p);
switch (p->type) {
case PT_REDSEA:
result=RedSeaFSFilesFind(files_find_mask,fuf_flags);
break;
case PT_FAT32:
result=FAT32FilesFind(files_find_mask,fuf_flags);
break;
case PT_ISO9660:
result=ISO1FilesFind(files_find_mask,fuf_flags);
break;
default:
PrintErr("File System Not Supported\n");
result=NULL;
}
if (result) {
DirFilesSort(&result,SK_NAME);
if (fuf_flags&(FUF_FLATTEN_TREE|FUF_JUST_FILES))
DirFilesFlatten(result,&result,fuf_flags);
if (fuf_flags&FUF_CLUSTER_ORDER)
DirFilesSort(&result,SK_CLUSTER);
}
return result;
}
U0 PutFileLink(U8 *filename,I64 line=0,Bool plain_text=FALSE)
{
U8 *buf;
if (!filename) return;
if (IsRaw) {
if (line)
"%s,%04d",filename,line;
else
"%s",filename;
} else {
buf=FileNameAbs(filename);
if (plain_text) {
if (line)
"$$LK,\"%s,%04d\",A=\"PL:%s,%d\"$$",filename,line,buf,line;
else
"$$LK,\"%s\",A=\"PI:%s\"$$",filename,buf;
} else {
if (line)
"$$LK,\"%s,%04d\",A=\"FL:%s,%d\"$$",filename,line,buf,line;
else
"$$LK,\"%s\",A=\"FI:%s\"$$",filename,buf;
}
Free(buf);
}
}
U0 PutDirLink(U8 *dirname)
{
U8 *buf;
if (!dirname) return;
if (IsRaw)
"%s",dirname;
else {
buf=DirNameAbs(dirname);
"$$MA,T=\"%s\",LM=\"Cd(\\\"%s\\\");Dir;\n\"$$",dirname,buf;
Free(buf);
}
}
I64 Dir2(U8 *files_find_mask,I64 fuf_flags,Bool full)
{
CDirEntry *tempde1=NULL,*tempde2;
U8 *st;
I64 csize=0xFFFF,c=0xFFFF,result=0;
tempde1=SysFilesFind(files_find_mask,fuf_flags);
if (!(st=CurDir))
PrintErr("Invalid Drive\n");
else {
if (tempde1) {
//Find max columns
tempde2=tempde1;
while (tempde2) {
if (tempde2->size>csize)
csize=tempde2->size;
if (tempde2->cluster>c)
c=tempde2->cluster;
tempde2=tempde2->next;
}
csize=Bsr(csize)/4+1;
c=Bsr(c)/4+1;
"$$MA,T=\"Directory\",LM=\"PopUpCd;Dir;\n\"$$ of %s\n",st;
if (full)
"__DATE__ __TIME__ %*ts %*ts\n",
csize,"SIZE",c,"CLUSTER";
else
"DATE_ TIME_ %*ts\n",csize,"SIZE";
while (tempde1) {
tempde2=tempde1->next;
result++;
if (full)
"%D %T %0*tX %0*tX ",tempde1->datetime,tempde1->datetime,
csize,tempde1->size,c,tempde1->cluster;
else
"%02d/%02d %02d:%02d %0*tX ",Month(tempde1->datetime),Day(tempde1->datetime),
Hour24(tempde1->datetime),Minute(tempde1->datetime),
csize,tempde1->size;
if (tempde1->attr & _ATTR_DIR)
PutDirLink(tempde1->name);
else
PutFileLink(tempde1->name);
NewLine;
DirEntryDel(tempde1);
tempde1=tempde2;
}
} else
"No matching entries\n";
Free(st);
}
return result;
}
+367
View File
@@ -0,0 +1,367 @@
U8 *FileExtDot(U8 *src)
{
I64 ch;
while (ch=*src++)
if (ch=='.' && *src!='/' && *src!='.')
return src-1;
return NULL;
}
U8 *FileExtRem(U8 *src,U8 *dst=NULL)
{
U8 *ptr;
if (ptr=FileExtDot(src)) {
if (dst)
StrCpy(dst,ptr+1);
*ptr=0;
} else if (dst)
*dst=0;
return dst;
}
Bool IsDotZ(U8 *filename)
{
I64 i=StrLen(filename);
if (i>6 && filename[i-1]=='Z' && filename[i-2]=='.' && filename[i-6]=='.')
return TRUE;
else
return FALSE;
}
Bool IsDotC(U8 *filename)
{
I64 i=StrLen(filename);
if (i>6 && filename[i-1]=='C' && filename[i-2]=='.' && filename[i-6]=='.')
return TRUE;
else
return FALSE;
}
Bool FilesFindMatch(U8 *test_filename,U8 *files_find_mask,I64 fuf_flags=0)
{
U8 *st1=StrNew(files_find_mask),
*st2=MAlloc(StrLen(files_find_mask)+1);
Bool result=FALSE;
while (TRUE) {
StrFirstRem(st1,";",st2);
if (*st2) {
if (*st2=='~') {
if (WildMatch(test_filename,st2+1)) {
result=FALSE;
break;
}
} else {
if (WildMatch(test_filename,st2)) {
if (Bt(&fuf_flags,FUf_JUST_TXT) && !FilesFindMatch(test_filename,FILEMASK_TXT)) {
result=FALSE;
break;
} else if (Bt(&fuf_flags,FUf_JUST_SRC) && !FilesFindMatch(test_filename,FILEMASK_SRC)) {
result=FALSE;
break;
} else if (Bt(&fuf_flags,FUf_JUST_AOT) && !FilesFindMatch(test_filename,FILEMASK_AOT)) {
result=FALSE;
break;
} else if (Bt(&fuf_flags,FUf_JUST_JIT) && !FilesFindMatch(test_filename,FILEMASK_JIT)) {
result=FALSE;
break;
} else if (Bt(&fuf_flags,FUf_JUST_GRA) && !FilesFindMatch(test_filename,FILEMASK_GRA)) {
result=FALSE;
break;
} else
result=TRUE;
}
}
} else
break;
}
Free(st1);
Free(st2);
return result;
}
U0 PrtChk(CPrt *p)
{
if (!p || p->pt_signature!=PRT_SIGNATURE_VAL)
throw('Prt');
}
U8 Prt2Drv(CPrt *p=NULL)
{
if (!p)
p=Fs->cur_prt;
PrtChk(p);
return p->drv_let;
}
CPrt *Drv2Prt(U8 drv_let=0)
{
CPrt *p;
if (!drv_let)
p=Fs->cur_prt;
else {
if (drv_let==':')
drv_let=*sys_acct;
p=drv_to_prt[ToUpper(drv_let)-'A'];
}
PrtChk(p);
return p;
}
U0 BlkDevChk(CBlkDev *bdev)
{
if (!bdev || bdev->bd_signature!=BD_SIGNATURE_VAL ||
!(BDT_NULL<bdev->type<BDT_NUM_TYPES))
throw('BlkDev');
}
CBlkDev *Drv2BlkDev(U8 drv_let=0)
{
CPrt *p=Drv2Prt(drv_let);
CBlkDev *bdev=p->bdev;
BlkDevChk(bdev);
return bdev;
}
Bool IsDrvWritable(U8 drv_let=0)
{
CBlkDev *bdev=Drv2BlkDev(drv_let);
if (bdev->flags & BDF_READ_ONLY)
return FALSE;
else
return TRUE;
}
U8 *CurDir(CTask *task=NULL,CTask *mem_task=NULL)
{
U8 *st;
if (!task) task=Fs;
if (!task->cur_dir)
return NULL;
st=MAlloc(StrLen(task->cur_dir)+3,mem_task);
*st=Prt2Drv;
st[1]=':';
StrCpy(st+2,task->cur_dir);
return st;
}
U8 *DirNameAbs(U8 *_dirname)
{
I64 maxlen;
U8 drv[3],*cur_dir,*buf2,*buf3,*buf,*dirname,*temp_name;
if (!Fs->cur_dir || !*Fs->cur_dir)
return StrNew(_dirname);
dirname=MStrUtil(_dirname,SUF_REM_LEADING|SUF_REM_TRAILING|SUF_REM_CTRL_CHARS);
temp_name=dirname;
*drv=Prt2Drv;
drv[1]=':';
drv[2]=0;
if (*dirname && dirname[1]==':') {
if (*dirname==':')
*drv=*sys_acct;
else
*drv=*dirname;
dirname=dirname+2;
cur_dir=StrNew("/");
} else
cur_dir=StrNew(Fs->cur_dir);
if (*dirname=='/') {
Free(cur_dir);
cur_dir=StrNew("/");
dirname++;
}
buf2=StrNew(dirname);
maxlen=StrLen(cur_dir)+1+StrLen(buf2)+1;
buf3=MAlloc(maxlen);
buf =MAlloc(maxlen);
StrCpy(buf3,cur_dir);
while (*buf2) {
StrFirstRem(buf2,"/",buf);
if (!*buf)
StrCpy(buf3,"/");
else if (!StrCmp(buf,"..")) {
StrLastRem(buf3,"/");
if (!*buf3)
StrCpy(buf3,"/");
} else if (!StrCmp(buf,".")) {
;
} else if (*buf) {
if (!StrCmp(buf,"HOME")) {
Free(buf3);
buf3=MAlloc(maxlen+StrLen(sys_acct));
StrCpy(buf3,sys_acct+2);
*drv=*sys_acct;
} else {
if (StrCmp(buf3,"/"))
CatPrint(buf3,"/");
CatPrint(buf3,buf);
}
}
}
Free(cur_dir);
cur_dir=MAlloc(StrLen(buf3)+3);
StrCpy(cur_dir,drv);
StrCpy(cur_dir+2,buf3);
Free(buf);
Free(buf2);
Free(buf3);
Free(temp_name);
return cur_dir;
}
U8 *FileNameAbs(U8 *_filename,I64 fuf_flags=0)
{//$LK,"FUF_Z_OR_NOT_Z",A="MN:FUF_Z_OR_NOT_Z"$, $LK,"FUF_SCAN_PARENTS",A="MN:FUF_SCAN_PARENTS"$
U8 *buf,*buf2,*buf3,*filename,*temp_name,*temp_buf;
CDirEntry de;
filename=MStrUtil(_filename,SUF_REM_LEADING|SUF_REM_TRAILING|SUF_REM_CTRL_CHARS);
temp_name=filename;
buf=StrNew(filename);
temp_buf=buf;
if (*buf && buf[1]==':') {
buf+=2;
filename+=2;
}
buf2=MAlloc(StrLen(temp_name)+1);
StrLastRem(buf,"/",buf2);
if (*filename=='/' && !*buf)
StrCpy(buf,"/");
buf3=DirNameAbs(temp_buf);
Free(temp_buf);
buf=MAlloc(StrLen(buf3)+1+StrLen(buf2)+1);
StrCpy(buf,buf3);
if (buf[StrLen(buf)-1]!='/')
CatPrint(buf,"/");
CatPrint(buf,buf2);
Free(buf2);
Free(buf3);
Free(temp_name);
if (fuf_flags&&FileFind(buf,&de,fuf_flags|FUF_JUST_FILES)) {
Free(buf);
buf=de.full_name;
}
return buf;
}
U8 *ChgExt(U8 *filename,U8 *extension)
{//Change filename extension
U8 *result=MAlloc(StrLen(filename)+1+StrLen(extension)+1);
StrCpy(result,filename);
if (FileExtDot(filename))
FileExtRem(result);
return CatPrint(result,".%s",extension);
}
U8 *DftExt(U8 *filename,U8 *extension)
{//Give extension if has none.
U8 *result=MAlloc(StrLen(filename)+1+StrLen(extension)+1);
StrCpy(result,filename);
if (!FileExtDot(filename))
CatPrint(result,".%s",extension);
return result;
}
CDirEntry *Cd2DirEntry(CDirEntry *tempde,U8 *abs_name)
{
I64 i;
while (tempde) {
i=StrLen(tempde->full_name);
if (StrNCmp(tempde->full_name,abs_name,i)||
i && tempde->full_name[i-1]!='/' && abs_name[i] && abs_name[i]!='/')
tempde=tempde->next;
else
if (StrLen(abs_name)==i)
return tempde;
else
return Cd2DirEntry(tempde->sub,abs_name);
}
return NULL;
}
I64 FileAttr(U8 *name,I64 attr=0)
{
if (IsDotZ(name))
attr|=_ATTR_COMPRESSED;
else
attr&=~_ATTR_COMPRESSED;
if (IsDotC(name))
attr|=_ATTR_CONTIGUOUS;
return attr;
}
Bool FileNameChk(U8 *filename)
{
U8 *ptr=filename;
if (!filename) return FALSE;
if (!*ptr) return FALSE;
if (*ptr=='.') {
if (!ptr[1]) return TRUE;
if (ptr[1]=='.' && !ptr[2]) return TRUE;
}
if (StrLen(filename)>=CDIR_FILENAME_LEN) return FALSE;
while (*ptr)
if (!Bt(chars_bitmap_filename,*ptr++))
return FALSE;
return TRUE;
}
U8 *DirFile(U8 *dirname,U8 *name=NULL,U8 *_extension=NULL)
{/*
Strips file from dirname, scans for file upward until found or returns default.
("/Kernel/Hash1a.CPP.Z",NULL,NULL) returns "D:/Kernel"
("/Kernel",NULL,"PRJ.Z") returns "D:/Kernel/Kernel.PRJ.Z"
("/Kernel/Dsk",NULL,"PRJ.Z") returns "D:/Kernel/Kernel.PRJ.Z"
("/Apps/MusicOrgan","Load","CPP.Z") returns "D:/Apps/MusicOrgan/Load.CPP.Z"
*/
U8 *st=DirNameAbs(dirname),*st2,*st3,*result,*dft=NULL,*ext;
if (_extension && *_extension) {
if (*_extension=='.')
ext=StrNew(_extension);
else
ext=MPrint(".%s",_extension);
} else
ext=StrNew("");
while (StrOcc(st,'/')&&!IsDir(st))
StrLastRem(st,"/");
while (StrOcc(st,'/')) {
st2=StrNew(st);
st3=StrNew(st);
StrLastRem(st2,"/",st3);
if (name)
result=MPrint("%s/%s%s",st,name,ext);
else {
if (*ext)
result=MPrint("%s/%s%s",st,st3,ext);
else
result=StrNew(st);
}
if (!dft)
dft=StrNew(result);
if (!*ext&&(!name||!*name)||FileFind(result)) {
Free(st3);
Free(st2);
Free(st);
Free(dft);
Free(ext);
return result;
}
Free(st);
st=st2;
Free(st3);
}
Free(st);
Free(ext);
return dft;
}
U8 *ToggleZorNotZ(U8 *name)
{
U8 *result;
if (IsDotZ(name)) {
result=StrNew(name);
result[StrLen(name)-2]=0;
} else
result=MPrint("%s.Z",name);
return result;
}
+964
View File
@@ -0,0 +1,964 @@
U0 CDate2Dos(U16 *t,U16 *d,CDate cdt)
{
CDateStruct ds;
Date2Struct(&ds,cdt+local_time_offset);
*d=ds.day_of_mon+(ds.mon+(ds.year-1980)<<4)<<5;
*t=ds.sec>>1+(ds.min+ds.hour<<6)<<5;
}
CDate Dos2CDate(U16 t,U16 d)
{
CDateStruct ds;
MemSet(&ds,0,sizeof(CDateStruct));
ds.day_of_mon=d&0x1F; d=d>>5;
ds.mon=d&0xF;
ds.year=d>>4+1980;
ds.sec=(t&0x1F)*2; t=t>>5;
ds.min=t&0x3F;
ds.hour=t>>6;
return Struct2Date(&ds)-local_time_offset;
}
U0 FAT32PrtInit(CPrt *p)
{
CFAT32Boot br32;
Bool unlock;
try {
unlock=PrtLock(p);
p->type=PT_FAT32;
RBlks(p,&br32,p->offset,1);
p->file_system_info_sect=p->offset+br32.file_system_info_sect;
p->map1=p->offset+br32.reserved_sects;
p->map2=p->map1+br32.sects_per_fat;
p->data=p->map2+br32.sects_per_fat-2*br32.sects_per_cluster; //Starts at Cluster 2
p->spc=br32.sects_per_cluster;
p->root_cluster=br32.root_cluster;
MapBufAlloc(p,1);
Free(p->fis);
p->fis=AMAlloc(BLK_SIZE);
RBlks(p,p->fis,p->file_system_info_sect,1);
if (unlock)
PrtUnlock(p);
} catch
if (unlock)
PrtUnlock(p);
}
Bool FAT32DrvValidate(U8 drv_let)
{
CPrt *p;
CFAT32Boot br;
Bool result=FALSE;
try {
p=Drv2Prt(drv_let);
if (p->type==PT_FAT32 &&
RBlks(p,&br,p->offset,1) &&
br.signature==0xAA55 &&
br.sects==p->size)
result=TRUE;
} catch
Fs->catch_except=TRUE;
return result;
}
U0 FAT32Fmt(U8 drv_let,Bool quick=TRUE)
{
CFAT32Boot *br=CAlloc(BLK_SIZE);
CFAT32FileInfoSect *fis=CAlloc(BLK_SIZE);
CPrt *p=Drv2Prt(drv_let);
I64 i,l;
try {
PrtLock(p);
SetDrvType(drv_let,PT_FAT32);
p->type=PT_FAT32;
br->jump_and_nop[0]=OC_JMP_REL8;
br->jump_and_nop[1]=offset(CFAT32Boot.code)-2;
br->jump_and_nop[2]=OC_NOP;
MemCpy(br->oem_name,"MSWIN4.1",8);
br->bytes_per_sect=BLK_SIZE;
if (p->size<= 500000)
br->sects_per_cluster=1;
else if (p->size<=2000000)
br->sects_per_cluster=2;
else if (p->size<=6000000)
br->sects_per_cluster=4;
else if (p->size<=12000000)
br->sects_per_cluster=8;
else if (p->size<=33000000)
br->sects_per_cluster=16;
else if (p->size<=67000000)
br->sects_per_cluster=32;
else
br->sects_per_cluster=64;
br->reserved_sects=32;
br->copies_of_fat=2;
br->media_desc=0xF8;
br->sects=p->size;
l=(br->sects/br->sects_per_cluster)>>(BLK_SIZE_BITS-2)+1;
br->sects_per_fat=l;
br->root_cluster=2;
br->file_system_info_sect=1;
br->log_drv_num=0x80;
br->ext_signature=0x29;
br->serial_num=RandU32;
MemCpy(br->vol_name,"NO NAME ",11);
MemCpy(br->fat_name,"FAT32 ",8);
br->signature=0xAA55;
fis->signature1=0x41615252;
fis->signature2=0x61417272;
fis->free_clusters=-1;
fis->most_recently_allocated=0;
fis->signature3=0xAA550000;
if (quick)
i=br->reserved_sects+2*l+4*br->sects_per_cluster;
else
i=p->size;
WZeroBlks(p,p->offset,i);
WBlks(p,fis,p->offset+br->file_system_info_sect,1);
WBlks(p,br,p->offset,1);
FAT32PrtInit(p);
ClustersAlloc(p,0,1,FALSE); //Allocate #1
br->root_cluster=ClustersAlloc(p,0,1,FALSE);
WBlks(p,br,p->offset,1);
FAT32PrtInit(p);
PrtUnlock(p);
} catch
PrtUnlock(p);
Free(br);
Free(fis);
}
Bool FATNameTo(U8 *dst,U8 *src)
{
I64 i;
MemSet(dst,CH_SPACE,11);
if (!FileNameChk(src))
return FALSE;
if (!StrCmp(src,"..")) {
*dst='.';
dst[1]='.';
return TRUE;
} else if (!StrCmp(src,".")) {
*dst='.';
return TRUE;
}
i=0;
while (i<8 && *src && *src!='.')
dst[i++]=ToUpper(*src++);
i=8;
if (*src=='.') src++;
while (*src)
if (*src!='.')
dst[i++]=ToUpper(*src++);
else
src++;
return TRUE;
}
I64 FATNameXSum(U8 *src)
{
I64 i,result=0;
for (i=0;i<11;i++)
if (result&1)
result.u8[0]=0x80+result>>1+*src++;
else
result.u8[0]=result>>1+*src++;
return result;
}
Bool FATFromName(U8 *dst,U8 *src)
{
I64 i,j,k=0;
for (j=7;j>=0 && src[j]==CH_SPACE;j--);
for(i=0;i<=j;i++)
dst[k++]=src[i];
for (j=10;j>=8 && src[j]==CH_SPACE;j--);
if (*src!='.' && j!=7)
dst[k++]='.';
for(i=8;i<=j;i++)
dst[k++]=src[i];
dst[k++]=0;
return FileNameChk(dst);
}
U8 fat_long_name_map[13]={
offset(CFAT32DirEntryLong.name1),
offset(CFAT32DirEntryLong.name1)+2,
offset(CFAT32DirEntryLong.name1)+4,
offset(CFAT32DirEntryLong.name1)+6,
offset(CFAT32DirEntryLong.name1)+8,
offset(CFAT32DirEntryLong.name2),
offset(CFAT32DirEntryLong.name2)+2,
offset(CFAT32DirEntryLong.name2)+4,
offset(CFAT32DirEntryLong.name2)+6,
offset(CFAT32DirEntryLong.name2)+8,
offset(CFAT32DirEntryLong.name2)+10,
offset(CFAT32DirEntryLong.name3),
offset(CFAT32DirEntryLong.name3)+2
};
Bool DirLongNameFill(CDirEntry *tempde,CFAT32DirEntryLong *de,I64 *xsum)
{
I64 i;
U8 *ptr=de;
if (de->ord&0x40) {
MemSet(tempde,0,sizeof(CDirEntry));
*xsum=de->xsum;
} else if (de->type || de->zero || de->xsum!=*xsum) {
MemSet(tempde,0,sizeof(CDirEntry));
*xsum=0;
return FALSE;
}
switch (de->ord&0x3F) {
case 1:
for (i=0;i<13;i++)
if (!(tempde->name[i]=ptr[fat_long_name_map[i]]))
return TRUE;
break;
case 2:
for (i=0;i<12;i++)
if (!(tempde->name[i+13]=ptr[fat_long_name_map[i]]))
return TRUE;
break;
}
return TRUE;
}
Bool FAT32CDirFill(CDirEntry *tempde,CFAT32DirEntry *de)
{
Bool result;
if (*tempde->name)
result=TRUE;
else
result=FATFromName(tempde->name,de->name);
tempde->cluster=de->cluster_lo+de->cluster_hi<<16;
tempde->size=de->size;
tempde->attr=de->attr;
tempde->datetime=Dos2CDate(de->WrtTime,de->WrtDate);
return result;
}
Bool FAT32DirFill(CFAT32DirEntry *de,CDirEntry *tempde,I64 *_de_cnt=NULL)
{ //Fill up to 3 entries and store cnt of entries.
I64 de_cnt=0,i,l,xsum,ord;
U8 *ptr,dname[16];
CFAT32DirEntryLong *ld=de;
Bool result;
MemSet(de,0,sizeof(CFAT32DirEntry));
result=FATNameTo(de->name,tempde->name);
FATFromName(dname,de->name);
if (StrCmp(dname,tempde->name)) {
ord=0x41;
xsum=FATNameXSum(de->name);
if ((l=StrLen(tempde->name))>13) {
ptr=&ld[de_cnt];
MemSet(ptr,0,sizeof(CFAT32DirEntryLong));
ld[de_cnt].attr=_ATTR_LONG_NAME;
ld[de_cnt].xsum=xsum;
ld[de_cnt].ord=0x42;
for (i=13;i<l;i++)
ptr[fat_long_name_map[i-13]]=tempde->name[i];
i++;
for (;i<26;i++)
ptr[fat_long_name_map[i-13]](U16)=0xFFFF;
ord=1;
l=13;
de_cnt++;
}
ptr=&de[de_cnt];
MemSet(ptr,0,sizeof(CFAT32DirEntryLong));
ld[de_cnt].attr=_ATTR_LONG_NAME;
ld[de_cnt].xsum=xsum;
ld[de_cnt].ord=ord;
for (i=0;i<l;i++)
ptr[fat_long_name_map[i]]=tempde->name[i];
i++;
for (;i<13;i++)
ptr[fat_long_name_map[i]](U16)=0xFFFF;
de_cnt++;
MemSet(&de[de_cnt],0,sizeof(CFAT32DirEntry));
result=FATNameTo(de[de_cnt].name,tempde->name);
}
de[de_cnt].cluster_lo=tempde->cluster.u16[0];
de[de_cnt].cluster_hi=tempde->cluster.u16[1];
if (!(tempde->attr&_ATTR_DIR))
de[de_cnt].size=tempde->size;
de[de_cnt].attr=tempde->attr;
if (!tempde->datetime)
tempde->datetime=Now;
CDate2Dos(&de[de_cnt].WrtTime,&de[de_cnt].WrtDate,tempde->datetime);
if (_de_cnt)
*_de_cnt=de_cnt+1;
return result;
}
Bool FAT32FileFind(CPrt *p,I64 cur_dir_cluster,U8 *name,CDirEntry *_result,I64 fuf_flags=0)
{ //$LK,"FUF_JUST_DIRS",A="MN:FUF_JUST_DIRS"$, $LK,"FUF_JUST_FILES",A="MN:FUF_JUST_FILES"$
Bool result=FALSE,unlock;
CFAT32DirEntry *buf;
I64 xsum=0,attr,cur_dir_entry,entries_per_cluster;
U8 dname[CDIR_FILENAME_LEN],ch;
CDirEntry long_name;
if (fuf_flags&~FUG_FILE_FIND)
throw('FUF');
MemSet(_result,0,sizeof(CDirEntry));
MemSet(&long_name,0,sizeof(CDirEntry));
PrtChk(p);
if (p->type!=PT_FAT32)
PrintErr("Not FAT32 Partition\n");
else if (!CFileNameTo(dname,name))
PrintErr("Invalid FileName.\n");
else
try {
unlock=PrtLock(p);
buf=MAlloc(BLK_SIZE*p->spc);
entries_per_cluster=p->spc<<FAT32_ENTRIES_BITS;
RClusters(p,buf,cur_dir_cluster,1);
cur_dir_entry=0;
while (ch=*buf[cur_dir_entry].name) {
attr=buf[cur_dir_entry].attr;
if (ch!=0xE5) {
if (attr&_ATTR_LONG_NAME_MASK==_ATTR_LONG_NAME)
DirLongNameFill(&long_name,&buf[cur_dir_entry],&xsum);
else {
if (!(attr&_ATTR_VOL_ID)) {
if (xsum==FATNameXSum(buf[cur_dir_entry].name))
MemCpy(_result,&long_name,sizeof(CDirEntry));
else
MemSet(_result,0,sizeof(CDirEntry));
if (!(fuf_flags&FUF_JUST_DIRS && !(attr & _ATTR_DIR)) &&
!(fuf_flags&FUF_JUST_FILES && attr & _ATTR_DIR) &&
FAT32CDirFill(_result,&buf[cur_dir_entry]) &&
!StrCmp(dname,_result->name)) {
result=TRUE;
goto exit_this;
}
}
MemSet(&long_name,0,sizeof(CDirEntry));
}
} else
MemSet(&long_name,0,sizeof(CDirEntry));
if (++cur_dir_entry==entries_per_cluster) {
cur_dir_cluster=ClusterNumNext(p,cur_dir_cluster);
if (!(0<cur_dir_cluster<0x0FFFFFF8))
break;
else {
RClusters(p,buf,cur_dir_cluster,1);
cur_dir_entry=0;
}
}
}
MemSet(_result,0,sizeof(CDirEntry));
exit_this:
Free(buf);
if (unlock)
PrtUnlock(p);
} catch
if (unlock)
PrtUnlock(p);
return result;
}
U8 *FAT32FileRead(CPrt *p,U8 *cur_dir,U8 *filename,I64 *_size,I64 *_attr)
{
U8 *buf=NULL;
CDirEntry de;
I64 c,blk_cnt,cur_dir_cluster;
PrtChk(p);
*_size=0;
*_attr=0;
if (p->type!=PT_FAT32)
PrintErr("Not FAT32 Partition\n");
else
try {
PrtLock(p);
cur_dir_cluster=Name2DirCluster(p,cur_dir);
if (FAT32FileFind(p,cur_dir_cluster,filename,&de,FUF_JUST_FILES)) {
blk_cnt=(de.size+BLK_SIZE-1)>>BLK_SIZE_BITS;
buf=MAlloc(blk_cnt<<BLK_SIZE_BITS+1);
c=de.cluster;
if (!(0<c<0x0FFFFFF8))
c=0x0FFFFFFF;
else
c=RClustersBlks(p,buf,c,blk_cnt);
buf[de.size]=0; //Terminate
*_size=de.size;
*_attr=FileAttr(de.name,de.attr);
}
PrtUnlock(p);
} catch
PrtUnlock(p);
return buf;
}
Bool FAT32Cd(U8 *name,I64 cur_dir_cluster)
{
CDirEntry de;
if (Fs->cur_prt->type!=PT_FAT32)
PrintErr("Not FAT32 Partition\n");
else if (FAT32FileFind(Fs->cur_prt,cur_dir_cluster,name,&de,FUF_JUST_DIRS))
return TRUE;
else {
"%s ",name;
PrintErr("File not found.\n");
}
return FALSE;
}
U0 FAT32FreeClusters(CPrt *p,I64 c)
{
I64 next,saved_c=c;
Bool unlock,unlock_break;
PrtChk(p);
if (!(0<c<0x0FFFFFF8)) return;
if (p->type!=PT_FAT32)
PrintErr("Not FAT32 Partition\n");
else
try {
unlock_break=BreakLock;
unlock=PrtLock(p);
CleanMAPBuf(p);
do {
SetFSBuf(p,c,0);
next=p->cur_map_blk[c&(BLK_SIZE/4-1)];
p->cur_map_blk[c&(BLK_SIZE/4-1)]=0;
LBts(p->buffered_map_dirty_bits,0);
c=next;
} while (0<c<0x0FFFFFF8);
CleanMAPBuf(p,0);
c=saved_c;
do {
SetFSBuf(p,c,1);
next=p->cur_map_blk[c&(BLK_SIZE/4-1)];
p->cur_map_blk[c&(BLK_SIZE/4-1)]=0;
LBts(p->buffered_map_dirty_bits,0);
c=next;
} while (0<c<0x0FFFFFF8);
CleanMAPBuf(p,1);
if (unlock)
PrtUnlock(p);
if (unlock_break)
BreakUnlock;
} catch {
if (unlock)
PrtUnlock(p);
if (unlock_break)
BreakUnlock;
}
}
I64 FAT32AllocClusters(CPrt *p,I64 c,I64 cnt)
{
Bool wrap_around=FALSE,unlock,unlock_break;
I64 first=INVALID_CLUSTER,j,l;
if (cnt<=0) return 0x0FFFFFFF;
try {
unlock_break=BreakLock;
unlock=PrtLock(p);
l=(p->size+p->offset-p->data)/p->spc-1;
j=p->fis->most_recently_allocated;
while (cnt-->0) {
while (TRUE) {
j++;
if (j<1) j=1;
if (j>=l) {
if (wrap_around)
Dbg;
j=1;
wrap_around=TRUE;
}
SetFSBuf(p,j);
if (!p->cur_map_blk[j&(BLK_SIZE/4-1)])
break;
}
if (!(0<first<0x0FFFFFF8))
first=j;
if (0<c<l) {
SetFSBuf(p,c);
p->cur_map_blk[c&(BLK_SIZE/4-1)]=j;
LBts(p->buffered_map_dirty_bits,0);
}
c=j;
}
if (0<c<l) {
SetFSBuf(p,c);
p->cur_map_blk[c&(BLK_SIZE/4-1)]=0x0FFFFFFF;
LBts(p->buffered_map_dirty_bits,0);
}
CleanMAPBuf(p);
p->fis->most_recently_allocated=j;
p->fis->free_clusters=-1;
WBlks(p,p->fis,p->file_system_info_sect,1);
} catch {
if (unlock)
PrtUnlock(p);
if (unlock_break)
BreakUnlock;
}
if (unlock)
PrtUnlock(p);
if (unlock_break)
BreakUnlock;
return first;
}
I64 FAT32AllocContiguousClusters(CPrt *p,I64 cnt)
{
I64 i,first=1;
Bool cont,unlock,unlock_break;
if (cnt<=0) return 0x0FFFFFFF;
try {
unlock_break=BreakLock;
unlock=PrtLock(p);
while (TRUE) {
first++;
i=0;
cont=TRUE;
while (cont && i<cnt) {
if ((first+i+1)*p->spc+p->data>p->size+p->offset)
Dbg;
SetFSBuf(p,first+i);
if (p->cur_map_blk[(first+i)&(BLK_SIZE/4-1)])
cont=FALSE;
else
i++;
}
if (!cont)
first=first+i;
else {
CleanMAPBuf(p);
for (i=0;i<cnt;i++) {
SetFSBuf(p,first+i,0);
if (i+1==cnt)
p->cur_map_blk[(first+i)&(BLK_SIZE/4-1)]=0x0FFFFFFF;
else
p->cur_map_blk[(first+i)&(BLK_SIZE/4-1)]=first+i+1;
LBts(p->buffered_map_dirty_bits,0);
}
CleanMAPBuf(p,0);
for (i=0;i<cnt;i++) {
SetFSBuf(p,first+i,1);
if (i+1==cnt)
p->cur_map_blk[(first+i)&(BLK_SIZE/4-1)]=0x0FFFFFFF;
else
p->cur_map_blk[(first+i)&(BLK_SIZE/4-1)]=first+i+1;
LBts(p->buffered_map_dirty_bits,0);
}
CleanMAPBuf(p,1);
break;
}
}
} catch {
if (unlock)
PrtUnlock(p);
if (unlock_break)
BreakUnlock;
}
if (unlock)
PrtUnlock(p);
if (unlock_break)
BreakUnlock;
return first;
}
Bool FAT32DirNew(CPrt *p,U8 *cur_dir,CDirEntry *tempde,Bool free_old_chain)
{
//See $LK,"::/Doc/CutCorners.TXT"$.
CFAT32DirEntry *buf,*last_buf,*temp_buf,de[3];
I64 i,attr,avail_cnt,de_cnt,c,
cur_dir_entry,entries_per_cluster,
cur_dir_cluster,xsum=0,last_dir_cluster=INVALID_CLUSTER;
U8 ch;
Bool written=FALSE,unlock,unlock_break;
CDirEntry long_name;
FAT32DirFill(&de,tempde,&de_cnt);
MemSet(&long_name,0,sizeof(CDirEntry));
try {
unlock_break=BreakLock;
unlock=PrtLock(p);
cur_dir_cluster=Name2DirCluster(p,cur_dir);
buf =MAlloc(BLK_SIZE*p->spc);
last_buf=CAlloc(BLK_SIZE*p->spc);
entries_per_cluster=p->spc<<FAT32_ENTRIES_BITS;
RClusters(p,buf,cur_dir_cluster,1);
cur_dir_entry=0;
while (ch=*buf[cur_dir_entry].name) {
attr=buf[cur_dir_entry].attr;
if (ch!=0xE5 && attr&_ATTR_LONG_NAME_MASK==_ATTR_LONG_NAME)
DirLongNameFill(&long_name,&buf[cur_dir_entry],&xsum);
else {
avail_cnt=FAT32_ENTRIES_PER_BLK-cur_dir_entry & (FAT32_ENTRIES_PER_BLK-1);
for (i=0;i<avail_cnt;i++)
if (*buf[cur_dir_entry+i].name!=0xE5) {
if (*buf[cur_dir_entry+i].name)
avail_cnt=i;
break;
}
if (ch==0xE5 && !written && avail_cnt>=de_cnt) {
MemCpy(&buf[cur_dir_entry],&de,de_cnt*sizeof(CFAT32DirEntry));
WBlks(p,&buf[cur_dir_entry & -FAT32_ENTRIES_PER_BLK],
p->data+cur_dir_cluster*p->spc
+cur_dir_entry>>FAT32_ENTRIES_BITS,1);
cur_dir_entry+=de_cnt-1; //gets inc'ed
written=TRUE;
} else if (ch!=0xE5 && !(attr&_ATTR_VOL_ID)) {
if (xsum!=FATNameXSum(buf[cur_dir_entry].name))
MemSet(&long_name,0,sizeof(CDirEntry));
if (!*long_name.name)
FATFromName(long_name.name,buf[cur_dir_entry].name);
//Del old entry with same name
if (!StrCmp(long_name.name,tempde->name)) {
if (free_old_chain)
FAT32FreeClusters(p,buf[cur_dir_entry].cluster_lo+
buf[cur_dir_entry].cluster_hi<<16);
if (!written) {
MemCpy(&buf[cur_dir_entry],&de[de_cnt-1],sizeof(CFAT32DirEntry));
WBlks(p,&buf[cur_dir_entry & -FAT32_ENTRIES_PER_BLK],
p->data+cur_dir_cluster*p->spc
+cur_dir_entry>>FAT32_ENTRIES_BITS,1);
written=TRUE;
} else {
*buf[cur_dir_entry].name=0xE5;
i=1;
while (i<=cur_dir_entry &&
buf[cur_dir_entry-i].attr&_ATTR_LONG_NAME_MASK==_ATTR_LONG_NAME)
*buf[cur_dir_entry-i++].name=0xE5;
i--;
WBlks(p,&buf[(cur_dir_entry-i)&-FAT32_ENTRIES_PER_BLK],
p->data+cur_dir_cluster*p->spc
+(cur_dir_entry-i)>>FAT32_ENTRIES_BITS,
(i+FAT32_ENTRIES_PER_BLK)>>FAT32_ENTRIES_BITS);
if (i==cur_dir_entry && 0<last_dir_cluster<0x0FFFFFF8) {
i=1;
while (i<=entries_per_cluster &&
last_buf[entries_per_cluster-i].attr&_ATTR_LONG_NAME_MASK==_ATTR_LONG_NAME)
*last_buf[entries_per_cluster-i++].name=0xE5;
if (--i>0)
WBlks(p,&buf[(entries_per_cluster-i)&-FAT32_ENTRIES_PER_BLK],
p->data+last_dir_cluster*p->spc
+(entries_per_cluster-i)>>FAT32_ENTRIES_BITS,
(i+FAT32_ENTRIES_PER_BLK-1)>>FAT32_ENTRIES_BITS);
}
}
break;
}
}
MemSet(&long_name,0,sizeof(CDirEntry));
}
if (++cur_dir_entry==entries_per_cluster) {
last_dir_cluster=cur_dir_cluster;
temp_buf=buf; buf=last_buf; last_buf=temp_buf;
c=ClusterNumNext(p,cur_dir_cluster);
if (!(0<c<0x0FFFFFF8)) {
c=ClustersAlloc(p,cur_dir_cluster,1,FALSE);
MemSet(buf,0,BLK_SIZE*p->spc);
WClusters(p,buf,c,1);
} else
RClusters(p,buf,c,1);
cur_dir_cluster=c;
cur_dir_entry=0;
}
}
if (!written) {
avail_cnt=FAT32_ENTRIES_PER_BLK-cur_dir_entry & (FAT32_ENTRIES_PER_BLK-1);
if (avail_cnt<de_cnt) {
for (i=0;i<avail_cnt;i++)
*buf[cur_dir_entry+i].name=0xE5;
WBlks(p,&buf[cur_dir_entry &-FAT32_ENTRIES_PER_BLK],
p->data+cur_dir_cluster*p->spc
+cur_dir_entry>>FAT32_ENTRIES_BITS,1);
cur_dir_entry+=avail_cnt;
if (cur_dir_entry==entries_per_cluster) {
last_dir_cluster=cur_dir_cluster;
temp_buf=buf; buf=last_buf; last_buf=temp_buf;
cur_dir_cluster=ClustersAlloc(p,cur_dir_cluster,1);
cur_dir_entry=0;
MemSet(buf,0,BLK_SIZE*p->spc);
WClusters(p,buf,cur_dir_cluster,1);
}
}
MemCpy(&buf[cur_dir_entry],&de,de_cnt*sizeof(CFAT32DirEntry));
WBlks(p,&buf[cur_dir_entry &-FAT32_ENTRIES_PER_BLK],
p->data+cur_dir_cluster*p->spc+
cur_dir_entry>>FAT32_ENTRIES_BITS,1);
cur_dir_entry+=de_cnt;
if (cur_dir_entry==entries_per_cluster) {
cur_dir_cluster=ClustersAlloc(p,cur_dir_cluster,1);
MemSet(buf,0,BLK_SIZE*p->spc);
WClusters(p,buf,cur_dir_cluster,1);
} else {
MemSet(&buf[cur_dir_entry],0,sizeof(CFAT32DirEntry));
WBlks(p,&buf[cur_dir_entry &-FAT32_ENTRIES_PER_BLK],
p->data+cur_dir_cluster*p->spc
+cur_dir_entry>>FAT32_ENTRIES_BITS,1);
}
}
Free(last_buf);
Free(buf);
if (unlock)
PrtUnlock(p);
if (unlock_break)
BreakUnlock;
} catch {
if (unlock)
PrtUnlock(p);
if (unlock_break)
BreakUnlock;
}
return FALSE;
}
I64 FAT32FilesDel(CPrt *p,U8 *cur_dir,U8 *files_find_mask,I64 fuf_flags,
Bool del_dir,Bool print_msg)
{
CFAT32DirEntry *buf,*last_buf,*temp_buf;
I64 i,result=0,attr,xsum=0,last_dir_cluster=INVALID_CLUSTER,
cur_dir_entry,entries_per_cluster,cur_dir_cluster;
U8 ch;
Bool unlock_break;
CDirEntry long_name;
MemSet(&long_name,0,sizeof(CDirEntry));
try {
unlock_break=BreakLock;
PrtLock(p);
cur_dir_cluster=Name2DirCluster(p,cur_dir);
buf =MAlloc(BLK_SIZE*p->spc);
last_buf=CAlloc(BLK_SIZE*p->spc);
entries_per_cluster=p->spc<<FAT32_ENTRIES_BITS;
RClusters(p,buf,cur_dir_cluster,1);
cur_dir_entry=0;
while (ch=*buf[cur_dir_entry].name) {
attr=buf[cur_dir_entry].attr;
if (ch!=0xE5 && ch!='.') {
if (attr&_ATTR_LONG_NAME_MASK==_ATTR_LONG_NAME)
DirLongNameFill(&long_name,&buf[cur_dir_entry],&xsum);
else {
if (!(attr & _ATTR_VOL_ID) &&
(del_dir || !(attr & _ATTR_DIR))) {
if (xsum!=FATNameXSum(buf[cur_dir_entry].name))
MemSet(&long_name,0,sizeof(CDirEntry));
if (!*long_name.name)
FATFromName(long_name.name,buf[cur_dir_entry].name);
if (FilesFindMatch(long_name.name,files_find_mask,fuf_flags)) {
if (!(attr & _ATTR_DIR)) result++;
if (print_msg)
"Del %s\n",long_name.name;
*buf[cur_dir_entry].name=0xE5;
i=1;
while (i<=cur_dir_entry &&
buf[cur_dir_entry-i].attr&_ATTR_LONG_NAME_MASK==_ATTR_LONG_NAME)
*buf[cur_dir_entry-i++].name=0xE5;
i--;
WBlks(p,&buf[(cur_dir_entry-i)&-FAT32_ENTRIES_PER_BLK],
p->data+cur_dir_cluster*p->spc
+(cur_dir_entry-i)>>FAT32_ENTRIES_BITS,
(i+FAT32_ENTRIES_PER_BLK)>>FAT32_ENTRIES_BITS);
if (i==cur_dir_entry && last_dir_cluster!=INVALID_CLUSTER) {
i=1;
while (i<=entries_per_cluster &&
last_buf[entries_per_cluster-i].attr&_ATTR_LONG_NAME_MASK==_ATTR_LONG_NAME)
*last_buf[entries_per_cluster-i++].name=0xE5;
if (--i>0)
WBlks(p,&buf[(entries_per_cluster-i)&-FAT32_ENTRIES_PER_BLK],
p->data+last_dir_cluster*p->spc
+(entries_per_cluster-i)>>FAT32_ENTRIES_BITS,
(i+FAT32_ENTRIES_PER_BLK-1)>>FAT32_ENTRIES_BITS);
}
FAT32FreeClusters(p,buf[cur_dir_entry].cluster_lo+
buf[cur_dir_entry].cluster_hi<<16);
}
}
MemSet(&long_name,0,sizeof(CDirEntry));
}
} else
MemSet(&long_name,0,sizeof(CDirEntry));
if (++cur_dir_entry==entries_per_cluster) {
last_dir_cluster=cur_dir_cluster;
cur_dir_cluster=ClusterNumNext(p,cur_dir_cluster,1);
temp_buf=buf; buf=last_buf; last_buf=temp_buf;
RClusters(p,buf,cur_dir_cluster,1);
cur_dir_entry=0;
}
}
Free(buf);
Free(last_buf);
PrtUnlock(p);
if (unlock_break)
BreakUnlock;
} catch {
PrtUnlock(p);
if (unlock_break)
BreakUnlock;
}
return result;
}
I64 FAT32FileWrite(CPrt *p,U8 *cur_dir,U8 *name,U8 *buf,I64 size,
CDate cdt,I64 attr)
{
CDirEntry de;
I64 c=0,blk_cnt;
Bool contiguous;
MemSet(&de,0,sizeof(CDirEntry));
if (size<0) size=0;
if (p->type!=PT_FAT32)
PrintErr("Not FAT32 Partition\n");
else if (!CFileNameTo(de.name,name))
PrintErr("Invalid FileName.\n");
else {
FAT32FilesDel(p,cur_dir,de.name,0,FALSE,FALSE);
if (attr & _ATTR_CONTIGUOUS)
contiguous=TRUE;
else
contiguous=FALSE;
de.size=size;
if (blk_cnt=(size+BLK_SIZE-1)>>BLK_SIZE_BITS)
c=ClustersAlloc(p,0,(blk_cnt+p->spc-1)/p->spc,contiguous);
else
c=0x0FFFFFFF;
de.cluster=c;
de.attr=attr;
de.datetime=cdt;
if (blk_cnt)
WClustersBlks(p,buf,c,blk_cnt);
FAT32DirNew(p,cur_dir,&de,TRUE);
}
return c;
}
CDirEntry *FAT32FilesFind(U8 *files_find_mask,I64 fuf_flags,CDirEntry *parent=NULL,I64 *_dir_size=NULL)
{
CPrt *p=Fs->cur_prt;
CFAT32DirEntry *buf;
I64 attr,xsum=0,dir_size=0,sub_dir_size,
cur_dir_cluster,cur_dir_entry,entries_per_cluster;
U8 ch;
CDirEntry *result=NULL,*tempde,long_name;
if (fuf_flags&~FUG_FILES_FIND)
throw('FUF');
try {
MemSet(&long_name,0,sizeof(CDirEntry));
PrtLock(p);
cur_dir_cluster=Name2DirCluster(p,Fs->cur_dir);
buf=MAlloc(BLK_SIZE*p->spc);
entries_per_cluster=p->spc<<FAT32_ENTRIES_BITS;
RClusters(Fs->cur_prt,buf,cur_dir_cluster,1);
dir_size+=Fs->cur_prt->spc*BLK_SIZE;
cur_dir_entry=0;
while (ch=*buf[cur_dir_entry].name) {
attr=buf[cur_dir_entry].attr;
if (ch!=0xE5) {
if (attr&_ATTR_LONG_NAME_MASK==_ATTR_LONG_NAME)
DirLongNameFill(&long_name,&buf[cur_dir_entry],&xsum);
else {
if (!(attr&_ATTR_VOL_ID)) {
tempde=MAlloc(sizeof(CDirEntry));
if (xsum==FATNameXSum(buf[cur_dir_entry].name))
MemCpy(tempde,&long_name,sizeof(CDirEntry));
else
MemSet(tempde,0,sizeof(CDirEntry));
if (FAT32CDirFill(tempde,&buf[cur_dir_entry])) {
tempde->parent=parent;
if (Bt(&fuf_flags,FUf_RECURSE) && attr&_ATTR_DIR && *tempde->name!='.') {
tempde->next=result;
result=tempde;
tempde->full_name=DirNameAbs(tempde->name);
PrtUnlock(p);
if (Cd(tempde->name)) {
tempde->sub=FAT32FilesFind(files_find_mask,fuf_flags,tempde,&sub_dir_size);
tempde->size=sub_dir_size;
Cd("..");
}
PrtLock(p);
} else if ((attr&_ATTR_DIR || !Bt(&fuf_flags,FUf_JUST_DIRS)) &&
!(Bt(&fuf_flags,FUf_RECURSE) && *tempde->name=='.' && attr&_ATTR_DIR) &&
FilesFindMatch(tempde->name,files_find_mask,fuf_flags)) {
tempde->next=result;
result=tempde;
tempde->full_name=FileNameAbs(tempde->name);
} else
DirEntryDel(tempde);
} else
DirEntryDel(tempde);
}
MemSet(&long_name,0,sizeof(CDirEntry));
}
} else
MemSet(&long_name,0,sizeof(CDirEntry));
if (++cur_dir_entry==entries_per_cluster) {
cur_dir_cluster=ClusterNumNext(p,cur_dir_cluster);
if (cur_dir_cluster==INVALID_CLUSTER)
break;
else {
RClusters(p,buf,cur_dir_cluster,1);
dir_size+=Fs->cur_prt->spc*BLK_SIZE;
cur_dir_entry=0;
}
}
}
Free(buf);
PrtUnlock(p);
} catch
PrtUnlock(p);
if (_dir_size)
*_dir_size=dir_size;
return result;
}
Bool FAT32MkDir(CPrt *p,U8 *cur_dir,U8 *name)
{
I64 size=p->spc<<BLK_SIZE_BITS,c,
cur_dir_cluster=Name2DirCluster(p,cur_dir);
U8 *buf=CAlloc(size);
CDirEntry d_native;
CFAT32DirEntry *dFAT=buf;
Bool unlock_break;
try {
unlock_break=BreakLock;
c=FileWrite(name,buf,size,0,_ATTR_DIR,FALSE);
MemSet(&d_native,0,sizeof(CDirEntry));
d_native.attr=_ATTR_DIR;
*d_native.name='.';
d_native.name[1]=0;
d_native.cluster=c;
d_native.size=0;
d_native.datetime=Now;
FAT32DirFill(dFAT,&d_native);
dFAT++;
MemSet(&d_native,0,sizeof(CDirEntry));
d_native.attr=_ATTR_DIR;
*d_native.name='.';
d_native.name[1]='.';
d_native.name[2]=0;
d_native.cluster=cur_dir_cluster;
d_native.size=0;
d_native.datetime=Now;
FAT32DirFill(dFAT,&d_native);
WClusters(p,buf,c,1);
Free(buf);
if (unlock_break)
BreakUnlock;
} catch
if (unlock_break)
BreakUnlock;
return TRUE;
}
+283
View File
@@ -0,0 +1,283 @@
//ISO1 is ISO9660
//ISO2 is ISO13490
//ISO3 is ISO13346
Bool ISOPrtInit(CPrt *p,I64 blk)
{
CBlkDev *bdev=p->bdev;
I64 spc=bdev->blk_size>>BLK_SIZE_BITS,i=blk/spc;
CISO1PriDesc *iso=MAlloc(bdev->blk_size);
CISO1DirEntry *de;
Bool unlock,result=FALSE;
U8 buf[8];
try {
unlock=PrtLock(p);
p->type=PT_ISO9660; //default
p->spc=spc;
p->offset=p->data=p->root_cluster=p->size=0;
while (TRUE) {
p->size=MaxI64(p->size,(i+1)*spc);
RBlks(p,iso,i*spc,spc);
buf[0](U32)=iso->id[0](U32);
buf[4](U16)=iso->id[4](U8);
switch (LstMatch(buf,"CD001\0CDW02\0BEA01\0BOOT2\0NSR02\0NSR03\0TEA01\0",LMF_EXACT)) {
case 0:
p->type=PT_ISO9660;
switch (iso->type) {
case ISO1T_SUPPLEMENTARY_DESC:
p->data=0;
de=&iso->root_dir_record;
p->root_cluster=de->loc.little;
p->size=iso->vol_space_size.little*bdev->blk_size>>BLK_SIZE_BITS;
result=TRUE;
goto ipi_done;
case ISO1T_TERMINATOR:
throw('Prt');
}
break;
default: //Its normal for ISO13346 to read NULL blk as terminator
PrintErr("File System Not Supported\n");
throw('Prt');
}
i++;
}
ipi_done:
Free(iso);
if (unlock)
PrtUnlock(p);
} catch {
p->type=PT_ISO9660;
p->spc=spc;
p->offset=p->data=p->root_cluster=0;
Free(iso);
if (unlock)
PrtUnlock(p);
}
return result;
}
U0 Date2ISO1(CISO1Date *dst,CDate cdt)
{
CDateStruct ds;
Date2Struct(&ds,cdt);
dst->year=ds.year-ISO1_BASE_YEAR;
dst->mon=ds.mon;
dst->day=ds.day_of_mon;
dst->hour=ds.hour;
dst->min=ds.min;
dst->sec=ds.sec;
dst->sec100=ds.sec100;
}
CDate ISO1DateStruct2CDate(CISO1Date *dt)
{
CDateStruct ds;
MemSet(&ds,0,sizeof(CDateStruct));
ds.day_of_mon=dt->day;
ds.mon=dt->mon;
ds.year=dt->year+ISO1_BASE_YEAR;
ds.sec100=dt->sec100;
ds.sec=dt->sec;
ds.min=dt->min;
ds.hour=dt->hour;
return Struct2Date(&ds);
}
Bool ISO1FromName(U8 *dst,U8 *src)
{
I64 i,j,n;
MemSet(dst,0,CDIR_FILENAME_LEN);
n=*src++;
if (n==1 && !*src) {
*dst='.';
} else if (n==1 && *src==1) {
*dst='.';
dst[1]='.';
} else {
n>>=1;
j=0;
for (i=0;i<n;i++) {
src++;
if (*src==';')
break;
if (Bt(chars_bitmap_filename,*src)) {
if (j>=CDIR_FILENAME_LEN-1)
return FALSE;
dst[j++]=*src++;
} else
return FALSE;
}
}
return FileNameChk(dst);
}
Bool ISO1CDirFill(CDirEntry *tempde,CISO1DirEntry *de)
{
Bool result;
MemSet(tempde,0,sizeof(CDirEntry));
result=ISO1FromName(tempde->name,&de->name_len);
tempde->cluster=de->loc.little;
tempde->size=de->size.little;
tempde->attr=FileAttr(tempde->name);
if (de->flags & ISO1_ATTR_DIR)
tempde->attr|=_ATTR_DIR;
tempde->datetime=ISO1DateStruct2CDate(&de->date);
return result;
}
Bool ISO1FileFind(CPrt *p,I64 cur_dir_cluster,U8 *name,CDirEntry *_result,I64 fuf_flags=0)
{ //$LK,"FUF_JUST_DIRS",A="MN:FUF_JUST_DIRS"$, $LK,"FUF_JUST_FILES",A="MN:FUF_JUST_FILES"$
CISO1DirEntry *isoptr,*buf;
U8 dname[CDIR_FILENAME_LEN];
Bool result=FALSE,unlock;
I64 i;
if (fuf_flags&~FUG_FILE_FIND)
throw('FUF');
PrtChk(p);
if (p->type!=PT_ISO9660)
PrintErr("Not ISO9660 Partition\n");
else
try {
unlock=PrtLock(p);
isoptr=MAlloc(p->spc<<BLK_SIZE_BITS);
RClusters(Fs->cur_prt,isoptr,cur_dir_cluster,1);
if (isoptr->name_len==1 && !isoptr->name) { //curdir
i=(isoptr->size.little+p->spc<<BLK_SIZE_BITS-1)/p->spc<<BLK_SIZE_BITS;
buf=MAlloc(p->spc<<BLK_SIZE_BITS*i);
RClusters(Fs->cur_prt,buf,cur_dir_cluster,i);
Free(isoptr);
} else {
buf=isoptr;
i=1;
}
i*=p->spc<<BLK_SIZE_BITS;
isoptr=buf;
while (i>0) {
if (!isoptr->len) {
isoptr(U8 *)++;
i--;
} else {
ISO1FromName(dname,&isoptr->name_len);
if (*dname) {
if (!StrCmp(name,dname)) {
result=ISO1CDirFill(_result,isoptr);
if (result &&
!(fuf_flags&FUF_JUST_DIRS && !(_result->attr & _ATTR_DIR)) &&
!(fuf_flags&FUF_JUST_FILES && _result->attr & _ATTR_DIR) )
goto exit_this;
else
result=FALSE;
}
}
i-=isoptr->len;
isoptr(U8 *)+=isoptr->len;
}
}
exit_this:
Free(buf);
if (unlock)
PrtUnlock(p);
} catch
if (unlock)
PrtUnlock(p);
return result;
}
U8 *ISO1FileRead(CPrt *p,U8 *cur_dir,U8 *filename,I64 *_size,I64 *_attr)
{
U8 *buf=NULL;
CDirEntry de;
I64 c,blk_cnt,cur_dir_cluster;
PrtChk(p);
*_size=0;
*_attr=0;
if (p->type!=PT_ISO9660)
PrintErr("Not ISO9660 Partition\n");
else
try {
PrtLock(p);
cur_dir_cluster=Name2DirCluster(p,cur_dir);
if (ISO1FileFind(p,cur_dir_cluster,filename,&de,FUF_JUST_FILES)) {
blk_cnt=(de.size+BLK_SIZE-1)>>BLK_SIZE_BITS;
buf=MAlloc(blk_cnt<<BLK_SIZE_BITS+1);
c=de.cluster;
c=RClustersBlks(p,buf,c,blk_cnt);
buf[de.size]=0; //Terminate
*_size=de.size;
*_attr=FileAttr(de.name,de.attr);
}
PrtUnlock(p);
} catch
PrtUnlock(p);
return buf;
}
Bool ISO1Cd(U8 *name,I64 cur_dir_cluster)
{
CDirEntry de;
if (Fs->cur_prt->type!=PT_ISO9660)
PrintErr("Not ISO9660 Partition\n");
else if (ISO1FileFind(Fs->cur_prt,cur_dir_cluster,name,&de,FUF_JUST_DIRS))
return TRUE;
else {
"%s ",name;
PrintErr("File not found.\n");
}
return FALSE;
}
CDirEntry *ISO1FilesFind(U8 *files_find_mask,I64 fuf_flags,CDirEntry *parent=NULL)
{
CPrt *p=Fs->cur_prt;
CISO1DirEntry *buf,*buf2,*isoptr;
I64 i,cur_dir_cluster=Name2DirCluster(p,Fs->cur_dir);
CDirEntry *result=NULL,*tempde;
if (fuf_flags&~FUG_FILES_FIND)
throw('FUF');
isoptr=MAlloc(p->spc<<BLK_SIZE_BITS);
RClusters(Fs->cur_prt,isoptr,cur_dir_cluster,1);
if (isoptr->name_len==1 && !isoptr->name) { //curdir
i=(isoptr->size.little+p->spc<<BLK_SIZE_BITS-1)/p->spc<<BLK_SIZE_BITS;
buf=MAlloc(p->spc<<BLK_SIZE_BITS*i);
RClusters(Fs->cur_prt,buf,cur_dir_cluster,i);
Free(isoptr);
} else {
buf=isoptr;
i=1;
}
buf2=buf;
i*=p->spc<<BLK_SIZE_BITS;
while (i>0) {
if (!buf->len) {
buf(U8 *)++;
i--;
} else {
tempde=MAlloc(sizeof(CDirEntry));
if (ISO1CDirFill(tempde,buf)) {
tempde->parent=parent;
if (Bt(&fuf_flags,FUf_RECURSE) && tempde->attr&_ATTR_DIR && *tempde->name!='.') {
tempde->next=result;
result=tempde;
tempde->full_name=DirNameAbs(tempde->name);
if (Cd(tempde->name)) {
tempde->sub=ISO1FilesFind(files_find_mask,fuf_flags,tempde);
Cd("..");
}
} else if ((tempde->attr & _ATTR_DIR || !Bt(&fuf_flags,FUf_JUST_DIRS)) &&
!(Bt(&fuf_flags,FUf_RECURSE) && *tempde->name=='.' && tempde->attr&_ATTR_DIR) &&
FilesFindMatch(tempde->name,files_find_mask,fuf_flags)) {
tempde->next=result;
result=tempde;
tempde->full_name=FileNameAbs(tempde->name);
} else
DirEntryDel(tempde);
} else
DirEntryDel(tempde);
i-=buf->len;
buf(U8 *)+=buf->len;
}
}
Free(buf2);
return result;
}
+632
View File
@@ -0,0 +1,632 @@
// See $LK,"RedSea File System",A="FI:::/Doc/RedSea.TXT"$
U0 RedSeaFSFreeFreeLst(CPrt *p)
{
CFreeLst *tempf,*tempf1;
Bool unlock;
try {
unlock=PrtLock(p);
if (tempf=p->next_free) {
while (tempf!=&p->next_free) {
tempf1=tempf->next;
Free(tempf);
tempf=tempf1;
}
}
p->next_free=NULL;
if (unlock)
PrtUnlock(p);
} catch
if (unlock)
PrtUnlock(p);
}
U0 RedSeaFSFreeLstBuild(CPrt *p)
{
Bool unlock;
CFreeLst *tempf;
I64 i,first=0,max_cluster=p->size+p->offset-p->data;
try {
unlock=PrtLock(p);
if (p->next_free)
RedSeaFSFreeFreeLst(p);
QueInit(&p->next_free);
while (first<max_cluster) {
i=0; //count free clusters
while (first+i<max_cluster) {
SetFSBuf(p,first+i);
if (Bt(p->cur_map_blk,(first+i)&(BLK_SIZE<<3-1)))
break;
else
i++;
}
if (i) {
tempf=AMAlloc(sizeof(CFreeLst));
tempf->size=i;
tempf->start=first;
QueIns(tempf,p->last_free);
}
first+=i+1;
}
if (unlock)
PrtUnlock(p);
} catch
if (unlock)
PrtUnlock(p);
}
U0 RedSeaFSPrtInit(CPrt *p)
{
CBootStruct br;
Bool unlock;
try {
unlock=PrtLock(p);
RBlks(p,&br,p->offset,1);
if (br.signature!=MBR_PT_REDSEA || br.signature2!=0xAA55)
throw('Prt');
p->type=PT_REDSEA;
RedSeaFSFreeFreeLst(p);
p->spc=1;
p->size=br.sects;
p->data=p->offset+br.bitmap_sects;
p->root_cluster=br.root_cluster;
p->map1=p->map2=p->offset+1;
MapBufAlloc(p,1);
if (unlock)
PrtUnlock(p);
} catch
if (unlock)
PrtUnlock(p);
}
Bool RedSeaFSDrvValidate(U8 drv_let)
{
CPrt *p;
CBootStruct br;
Bool result=FALSE;
try {
p=Drv2Prt(drv_let);
if (p->type==PT_REDSEA && RBlks(p,&br,p->offset,1) &&
br.signature==MBR_PT_REDSEA && br.signature2==0xAA55 &&
br.sects==p->size)
result=TRUE;
} catch
Fs->catch_except=TRUE;
return result;
}
U0 RedSeaFSFmt(U8 drv_let,Bool quick=TRUE)
{
U8 *root_dir;
CDirEntry *d_native;
CBootStruct *br=CAlloc(BLK_SIZE);
CPrt *p=Drv2Prt(drv_let);
I64 i,n;
try {
PrtLock(p);
// SetDrvType(drv_let,PT_REDSEA);
SetDrvType(drv_let,PT_FAT32);
p->type=PT_REDSEA;
br->signature=MBR_PT_REDSEA;
br->signature2=0xAA55;
br->sects=p->size;
n=(br->sects+BLK_SIZE<<3-1)/BLK_SIZE<<3;
br->bitmap_sects=n;
br->unique_id=GetTSC^Now()(U64);
br->root_cluster=0;
if (quick)
i=n+1;
else
i=p->size;
WZeroBlks(p,p->offset,i);
WBlks(p,br,p->offset,1);
RedSeaFSPrtInit(p);
ClustersAlloc(p,0,1,FALSE); //Alloc #1
br->root_cluster=ClustersAlloc(p,0,1,FALSE);
WBlks(p,br,p->offset,1);
root_dir=CAlloc(BLK_SIZE);
d_native=root_dir-offset(CDirEntry.start);
d_native->attr=_ATTR_DIR|_ATTR_CONTIGUOUS;
*d_native->name='.';
d_native->cluster=br->root_cluster;
d_native->size=BLK_SIZE;
d_native->datetime=Now;
d_native(U8 *)+=CDIR_SIZE;
*d_native->name='.';
d_native->name[1]='.';
d_native->attr=_ATTR_DIR|_ATTR_CONTIGUOUS;
d_native->cluster=br->root_cluster;
d_native->datetime=Now;
WBlks(p,root_dir,p->data+br->root_cluster,1);
RedSeaFSPrtInit(p);
PrtUnlock(p);
} catch
PrtUnlock(p);
Free(br);
Free(root_dir);
}
Bool RedSeaFSFileFind(CPrt *p,I64 cur_dir_cluster,U8 *name,CDirEntry *_result,I64 fuf_flags=0)
{ //$LK,"FUF_JUST_DIRS",A="MN:FUF_JUST_DIRS"$, $LK,"FUF_JUST_FILES",A="MN:FUF_JUST_FILES"$
CDirEntry *buf,*buf2,*ptr;
U8 dname[CDIR_FILENAME_LEN];
I64 ch;
Bool result=FALSE,unlock;
if (fuf_flags&~FUG_FILE_FIND)
throw('FUF');
MemSet(_result,0,sizeof(CDirEntry));
PrtChk(p);
if (p->type!=PT_REDSEA)
PrintErr("Not RedSea Partition\n");
else if (!CFileNameTo(dname,name))
PrintErr("Invalid FileName.\n");
else
try {
unlock=PrtLock(p);
buf2=MAlloc(BLK_SIZE);
RClusters(p,buf2,cur_dir_cluster,1);
ptr=buf2(U8 *)-offset(CDirEntry.start);
buf=MAlloc(ptr->size);
RClustersBlks(p,buf,cur_dir_cluster,ptr->size>>BLK_SIZE_BITS);
Free(buf2);
ptr=buf(U8 *)-offset(CDirEntry.start);
*ptr->name='.';
ptr->name[1]=0;
while (TRUE) {
if (!(ch=*ptr->name))
break;
else if (!(ptr->attr & _ATTR_DELETED) &&
!(fuf_flags&FUF_JUST_DIRS && !(ptr->attr & _ATTR_DIR)) &&
!(fuf_flags&FUF_JUST_FILES && ptr->attr & _ATTR_DIR) &&
!StrCmp(dname,ptr->name)) {
MemCpy(&_result->attr,&ptr->attr,CDIR_SIZE);
result=TRUE;
goto exit_this;
}
ptr(U8 *)+=CDIR_SIZE;
}
exit_this:
Free(buf);
if (unlock)
PrtUnlock(p);
} catch
if (unlock)
PrtUnlock(p);
return result;
}
U8 *RedSeaFSFileRead(CPrt *p,U8 *cur_dir,U8 *filename,I64 *_size,I64 *_attr)
{
U8 *buf=NULL;
CDirEntry de;
I64 c,blk_cnt,cur_dir_cluster;
PrtChk(p);
*_size=0;
*_attr=0;
if (p->type!=PT_REDSEA)
PrintErr("Not RedSea Partition\n");
else
try {
PrtLock(p);
cur_dir_cluster=Name2DirCluster(p,cur_dir);
if (RedSeaFSFileFind(p,cur_dir_cluster,filename,&de,FUF_JUST_FILES)) {
blk_cnt=(de.size+BLK_SIZE-1)>>BLK_SIZE_BITS;
buf=MAlloc(blk_cnt<<BLK_SIZE_BITS+1);
c=de.cluster;
c=RClustersBlks(p,buf,c,blk_cnt);
buf[de.size]=0; //Terminate
*_size=de.size;
*_attr=FileAttr(de.name,de.attr);
}
PrtUnlock(p);
} catch
PrtUnlock(p);
return buf;
}
Bool RedSeaFSCd(U8 *name,I64 cur_dir_cluster)
{
CDirEntry de;
if (Fs->cur_prt->type!=PT_REDSEA)
PrintErr("Not RedSea Partition\n");
else if (RedSeaFSFileFind(Fs->cur_prt,cur_dir_cluster,name,&de,FUF_JUST_DIRS))
return TRUE;
else {
"%s ",name;
PrintErr("File not found.\n");
}
return FALSE;
}
U0 RedSeaFSFreeClusters(CPrt *p,I64 c,I64 cnt)
{
CFreeLst *tempf;
Bool found=FALSE,unlock,unlock_break;
PrtChk(p);
if (!c) return;
if (p->type!=PT_REDSEA)
PrintErr("Not RedSea Partition\n");
else
try {
unlock_break=BreakLock;
unlock=PrtLock(p);
if (!p->next_free)
RedSeaFSFreeLstBuild(p);
tempf=p->next_free;
while (!found && tempf!=&p->next_free) {
if (tempf->start+tempf->size==c) {
tempf->size+=cnt;
found=TRUE;
} else if (c+cnt==tempf->start) {
tempf->size+=cnt;
tempf->start=c;
found=TRUE;
}
tempf=tempf->next;
}
if (!found) {
tempf=AMAlloc(sizeof(CFreeLst));
tempf->size=cnt;
tempf->start=c;
QueIns(tempf,p->last_free);
}
while (cnt-->0) {
SetFSBuf(p,c);
LBtr(p->cur_map_blk,c&(BLK_SIZE<<3-1));
LBts(p->buffered_map_dirty_bits,0);
c++;
}
CleanMAPBuf(p);
if (unlock)
PrtUnlock(p);
if (unlock_break)
BreakUnlock;
} catch {
if (unlock)
PrtUnlock(p);
if (unlock_break)
BreakUnlock;
}
}
I64 RedSeaFSAllocClusters(CPrt *p,I64 cnt)
{
CFreeLst *tempf,*best_free=NULL;
I64 i,first,best_size=MAX_I64;
Bool unlock,unlock_break;
if (cnt<=0)
Dbg;
try {
unlock_break=BreakLock;
unlock=PrtLock(p);
if (!p->next_free)
RedSeaFSFreeLstBuild(p);
tempf=p->next_free;
while (tempf!=&p->next_free) {
if (tempf->size>=cnt && tempf->size<best_size) {
best_free=tempf;
best_size=tempf->size;
if (tempf->size==cnt)
break;
}
tempf=tempf->next;
}
if (!best_free)
Dbg;
first=best_free->start;
for (i=0;i<cnt;i++) {
SetFSBuf(p,first+i);
LBts(p->cur_map_blk,(first+i)&(BLK_SIZE<<3-1));
LBts(p->buffered_map_dirty_bits,0);
}
CleanMAPBuf(p);
if (best_free->size-=cnt)
best_free->start+=cnt;
else {
QueRem(best_free);
Free(best_free);
}
if (unlock)
PrtUnlock(p);
if (unlock_break)
BreakUnlock;
} catch {
if (unlock)
PrtUnlock(p);
if (unlock_break)
BreakUnlock;
}
return first;
}
Bool RedSeaFSDirNew(CPrt *p,U8 *cur_dir,CDirEntry *de,Bool free_old_chain)
{
CDirEntry *buf,*buf2,*ptr,de2;
CBootStruct *br;
I64 c,ch,i=1,j=0,n=BLK_SIZE/CDIR_SIZE,dir_size,cur_dir_cluster;
Bool written=FALSE,unlock,unlock_break;
U8 *temp,*parent_dir;
try {
unlock_break=BreakLock;
de->attr|=_ATTR_CONTIGUOUS;
unlock=PrtLock(p);
cur_dir_cluster=Name2DirCluster(p,cur_dir);
buf2=MAlloc(BLK_SIZE);
RClusters(p,buf2,cur_dir_cluster,1);
ptr=buf2(U8 *)-offset(CDirEntry.start);
buf=MAlloc(ptr->size);
RClustersBlks(p,buf,cur_dir_cluster,ptr->size>>BLK_SIZE_BITS);
dir_size=ptr->size;
ptr=buf(U8 *)-offset(CDirEntry.start)+CDIR_SIZE;
Free(buf2);
while (TRUE) {
if (!(ch=*ptr->name)) {
if (!written)
MemCpy(&ptr->start,&de->start,CDIR_SIZE);
if ((i+1)*CDIR_SIZE+j<<BLK_SIZE_BITS<dir_size)
WBlks(p,buf(U8 *)+j<<BLK_SIZE_BITS,p->data+cur_dir_cluster+j,1);
else {
buf2=CAlloc(dir_size+BLK_SIZE);
MemCpy(buf2,buf,dir_size);
RedSeaFSFreeClusters(p,cur_dir_cluster,dir_size>>BLK_SIZE_BITS);
dir_size+=BLK_SIZE;
c=ClustersAlloc(p,0,dir_size>>BLK_SIZE_BITS,TRUE);
Free(buf);
buf=buf2;
ptr=buf(U8 *)-offset(CDirEntry.start);
ptr->size=dir_size;
ptr->cluster=c;
WClustersBlks(p,buf,c,dir_size>>BLK_SIZE_BITS);
if (cur_dir_cluster==p->root_cluster) {
br=CAlloc(BLK_SIZE);
RBlks(p,br,p->offset,1);
br->root_cluster=c;
WBlks(p,br,p->offset,1);
Free(br);
p->root_cluster=c;
} else {
temp=StrNew(cur_dir);
parent_dir=StrNew(cur_dir);
StrLastRem(parent_dir,"/",temp);
if (!*parent_dir) {
Free(parent_dir);
parent_dir=StrNew("/");
}
if (RedSeaFSFileFind(p,Name2DirCluster(p,parent_dir),
temp,&de2,FUF_JUST_DIRS)) {
de2.cluster=c;
de2.size=dir_size;
RedSeaFSDirNew(p,parent_dir,&de2,FALSE);
} else
Dbg;
Free(temp);
Free(parent_dir);
}
}
break;
} else if (ptr->attr & _ATTR_DELETED) {
if (!written) {
MemCpy(&ptr->start,&de->start,CDIR_SIZE);
WBlks(p,buf(U8 *)+j<<BLK_SIZE_BITS,p->data+cur_dir_cluster+j,1);
written=TRUE;
}
} else {
if (!StrCmp(de->name,ptr->name)) {
if (free_old_chain)
RedSeaFSFreeClusters(p,ptr->cluster,
(ptr->size+BLK_SIZE-1)>>BLK_SIZE_BITS);
if (!written)
MemCpy(&ptr->start,&de->start,CDIR_SIZE);
else
ptr->attr|=_ATTR_DELETED;
WBlks(p,buf(U8 *)+j<<BLK_SIZE_BITS,p->data+cur_dir_cluster+j,1);
break;
}
}
ptr(U8 *)+=CDIR_SIZE;
if (++i>=n) {
j++;
i=0;
}
}
Free(buf);
if (unlock)
PrtUnlock(p);
if (unlock_break)
BreakUnlock;
} catch {
if (unlock)
PrtUnlock(p);
if (unlock_break)
BreakUnlock;
}
return FALSE;
}
I64 RedSeaFSFilesDel(CPrt *p,U8 *cur_dir,U8 *files_find_mask,I64 fuf_flags,
Bool del_dir,Bool print_msg)
{
CDirEntry *buf,*buf2,*ptr;
I64 i=0,result=0,ch,j=0,n=BLK_SIZE/CDIR_SIZE,cur_dir_cluster;
Bool unlock_break;
try {
unlock_break=BreakLock;
PrtLock(p);
cur_dir_cluster=Name2DirCluster(p,cur_dir);
buf2=MAlloc(BLK_SIZE);
RClusters(p,buf2,cur_dir_cluster,1);
ptr=buf2(U8 *)-offset(CDirEntry.start);
buf=MAlloc(ptr->size);
RClustersBlks(p,buf,cur_dir_cluster,ptr->size>>BLK_SIZE_BITS);
Free(buf2);
ptr=buf(U8 *)-offset(CDirEntry.start);
*ptr->name='.';
ptr->name[1]=0;
while (TRUE) {
if (!(ch=*ptr->name))
break;
else if (!(ptr->attr & _ATTR_DELETED) && ch!='.' && (del_dir ||
!(ptr->attr & _ATTR_DIR)) &&
FilesFindMatch(ptr->name,files_find_mask,fuf_flags)) {
if (!(ptr->attr & _ATTR_DIR)) result++;
if (print_msg)
"Del %s\n",ptr->name;
ptr->attr|=_ATTR_DELETED;
WBlks(p,buf(U8 *)+j<<BLK_SIZE_BITS,p->data+cur_dir_cluster+j,1);
RedSeaFSFreeClusters(p,ptr->cluster,(ptr->size+BLK_SIZE-1)>>BLK_SIZE_BITS);
}
ptr(U8 *)+=CDIR_SIZE;
if (++i>=n) {
j++;
i=0;
}
}
Free(buf);
PrtUnlock(p);
if (unlock_break)
BreakUnlock;
} catch {
PrtUnlock(p);
if (unlock_break)
BreakUnlock;
}
return result;
}
I64 RedSeaFSFileWrite(CPrt *p,U8 *cur_dir,U8 *name,U8 *buf,I64 size,
CDate cdt,I64 attr)
{
CDirEntry de;
I64 c=0,blk_cnt;
MemSet(&de,0,sizeof(CDirEntry));
if (size<0) size=0;
if (p->type!=PT_REDSEA)
PrintErr("Not RedSea Partition\n");
else if (!CFileNameTo(de.name,name))
PrintErr("Invalid FileName.\n");
else {
RedSeaFSFilesDel(p,cur_dir,de.name,0,FALSE,FALSE);
de.size=size;
if (blk_cnt=(size+BLK_SIZE-1)>>BLK_SIZE_BITS)
c=ClustersAlloc(p,0,blk_cnt,TRUE); //Always contiguous
else
c=INVALID_CLUSTER;
de.cluster=c;
de.attr=attr|_ATTR_CONTIGUOUS;
de.datetime=cdt;
if (blk_cnt)
WClustersBlks(p,buf,c,blk_cnt);
RedSeaFSDirNew(p,cur_dir,&de,TRUE);
}
return c;
}
CDirEntry *RedSeaFSFilesFind(U8 *files_find_mask,I64 fuf_flags,CDirEntry *parent=NULL)
{
CPrt *p=Fs->cur_prt;
CDirEntry *buf,*buf2,*ptr,*result=NULL,*tempde;
I64 ch,cur_dir_cluster;
if (fuf_flags&~FUG_FILES_FIND)
throw('FUF');
try {
PrtLock(p);
cur_dir_cluster=Name2DirCluster(p,Fs->cur_dir);
buf2=MAlloc(BLK_SIZE);
RClusters(p,buf2,cur_dir_cluster,1);
ptr=buf2(U8 *)-offset(CDirEntry.start);
buf=MAlloc(ptr->size);
RClustersBlks(p,buf,cur_dir_cluster,ptr->size>>BLK_SIZE_BITS);
Free(buf2);
ptr=buf(U8 *)-offset(CDirEntry.start);
*ptr->name='.';
ptr->name[1]=0;
ptr(U8 *)+=CDIR_SIZE;
ptr->cluster=Name2ParentDirCluster(p,Fs->cur_dir);
ptr(U8 *)-=CDIR_SIZE;
while (TRUE) {
if (!(ch=*ptr->name))
break;
else if (!(ptr->attr & _ATTR_DELETED)) {
tempde=CAlloc(sizeof(CDirEntry));
MemCpy(&tempde->start,&ptr->start,CDIR_SIZE);
tempde->parent=parent;
if (Bt(&fuf_flags,FUf_RECURSE) && tempde->attr&_ATTR_DIR && *tempde->name!='.') {
tempde->next=result;
result=tempde;
tempde->full_name=DirNameAbs(tempde->name);
PrtUnlock(p);
if (Cd(tempde->name)) {
tempde->sub=RedSeaFSFilesFind(files_find_mask,fuf_flags,tempde);
Cd("..");
}
PrtLock(p);
} else if ((tempde->attr&_ATTR_DIR || !Bt(&fuf_flags,FUf_JUST_DIRS)) &&
!(Bt(&fuf_flags,FUf_RECURSE) && *tempde->name=='.' && tempde->attr&_ATTR_DIR) &&
FilesFindMatch(tempde->name,files_find_mask,fuf_flags)) {
tempde->next=result;
result=tempde;
tempde->full_name=FileNameAbs(tempde->name);
} else
DirEntryDel(tempde);
}
ptr(U8 *)+=CDIR_SIZE;
}
Free(buf);
PrtUnlock(p);
} catch
PrtUnlock(p);
return result;
}
Bool RedSeaFSMkDir(CPrt *p,U8 *cur_dir,U8 *name)
{
I64 size=BLK_SIZE,c,cur_dir_cluster=Name2DirCluster(p,cur_dir);
U8 *buf=CAlloc(size);
CDirEntry *d_native=buf-offset(CDirEntry.start);
Bool unlock_break;
try {
unlock_break=BreakLock;
c=FileWrite(name,buf,size,0,_ATTR_DIR,FALSE);
d_native->attr=_ATTR_DIR|_ATTR_CONTIGUOUS;
StrCpy(d_native->name,name);
d_native->cluster=c;
d_native->size=size;
d_native->datetime=Now;
d_native(U8 *)+=CDIR_SIZE;
d_native->attr=_ATTR_DIR|_ATTR_CONTIGUOUS;
*d_native->name='.';
d_native->name[1]='.';
d_native->name[2]=0;
d_native->cluster=cur_dir_cluster;
d_native->size=0;
d_native->datetime=Now;
WClusters(p,buf,c,1);
Free(buf);
if (unlock_break)
BreakUnlock;
} catch
if (unlock_break)
BreakUnlock;
return TRUE;
}
+340
View File
@@ -0,0 +1,340 @@
class CLine
{
CLine *next,*last;
U8 *line;
};
U0 EdLiteUpdate(CLine *root,CLine *cur_line,I64 cur_col,I64 line_start_col)
{
I64 ch,i,j,k,k2,cursor_col,cursor_row=-1;
U8 *st;
CLine *templ=cur_line;
Bool done_eof=FALSE;
sys_raw_col=0;
for (i=0;i<text_rows/2;i++)
if (templ->last!=root)
templ=templ->last;
for (i=0;i<text_rows;i++) {
if (cursor_row<0 && templ==cur_line) {
k=0;
for (j=0;j<cur_col;j++)
if (templ->line[j]=='\t')
k=(k+8)&~7;
else
k++;
cursor_col=k;
cursor_row=i;
}
if (templ!=root) {
st=templ->line;
k=0;
j=0;
while (ch=*st++) {
if (ch=='\t')
k2=(k+8)&~7;
else
k2=k+1;
if (line_start_col<=k<line_start_col+text_cols) {
'' ch;
j=k2-line_start_col;
}
k=k2;
}
if (j<text_cols)
NewLine;
templ=templ->next;
} else {
if (!done_eof) {
"<EOF>";
done_eof=TRUE;
}
NewLine;
}
}
sys_raw_col=text_cols*cursor_row+cursor_col-line_start_col;
RawPutChar(0x7F);
}
U0 EdLite(U8 *filename,I64 num=1)
{
//Light weight text editor for debugging
U8 *src,*src2,*src3,*dst,*buf,*bin_data=NULL;
I64 i,cnt=0,ch,sc,size,bin_size=0,line_start_col=0,cur_col=0,
old_raw_flags=sys_raw_flags;
CLine root,*templ,*templ1,*cur_line;
Bool old_raw=Raw(ON),
old_debug=InDbg(ON),
old_single=SingleUser(ON);
if (!filename) filename=sys_temp_filename;
buf=FileRead(filename,&size);
PUSHFD
CLI
sys_raw_flags=sys_raw_flags&~RWF_SCROLL|RWF_SHOW_DOLLAR;
sys_cur_scan_code=0;
QueInit(&root);
root.line=StrNew("");
if (buf) {
src=buf;
while (*src) {
src2=src;
while ((ch=*src++) && ch!='\r' && ch!='\n');
src--;
*src++=0;
if (!ch)
src--;
while (ch=='\r' && *src=='\n' || *src==CH_CURSOR)
src++;
dst=src3=src2;
while (ch=*src3++)
if (ch!='\n' && ch!=CH_CURSOR)
*dst++=ch;
*dst=0;
templ=MAlloc(sizeof(CLine));
templ->line=StrNew(src2);
QueIns(templ,root.last);
cnt++;
}
if (src+1-buf<size) {
bin_data=MAlloc(bin_size=size-(src-buf));
MemCpy(bin_data,src,bin_size);
}
Free(buf);
}
cur_line=root.next;
if (0<--num) {
if (num<cnt)
while (num--)
cur_line=cur_line->next;
else
cur_line=&root;
}
do {
if (cur_line==&root)
cur_col=0;
while (cur_col-line_start_col<0)
line_start_col-=8;
while (cur_col-line_start_col>=text_cols)
line_start_col+=8;
EdLiteUpdate(&root,cur_line,cur_col,line_start_col);
switch (ch=GetKey(&sc,FALSE,TRUE)) {
case 0:
switch (sc.u8[0]) {
case SC_CURSOR_UP:
if (cur_line->last!=&root)
cur_line=cur_line->last;
if (cur_col>StrLen(cur_line->line))
cur_col=StrLen(cur_line->line);
break;
case SC_CURSOR_DOWN:
if (cur_line!=&root)
cur_line=cur_line->next;
if (cur_col>StrLen(cur_line->line))
cur_col=StrLen(cur_line->line);
break;
case SC_CURSOR_RIGHT:
cur_col++;
if (cur_col>StrLen(cur_line->line)) {
templ=cur_line->next;
if (templ!=&root) {
cur_col=0;
cur_line=templ;
} else
cur_col=StrLen(cur_line->line);
}
break;
case SC_CURSOR_LEFT:
if (cur_col)
cur_col--;
else {
templ=cur_line->last;
if (templ!=&root) {
cur_line=templ;
cur_col=StrLen(templ->line);
}
}
break;
case SC_PAGE_UP:
for (i=1;i<text_rows;i++) {
if (cur_line->last!=&root)
cur_line=cur_line->last;
if (cur_col>StrLen(cur_line->line))
cur_col=StrLen(cur_line->line);
}
break;
case SC_PAGE_DOWN:
for (i=1;i<text_rows;i++) {
if (cur_line!=&root)
cur_line=cur_line->next;
if (cur_col>StrLen(cur_line->line))
cur_col=StrLen(cur_line->line);
}
break;
case SC_DELETE:
if (cur_col==StrLen(cur_line->line)) {
templ=cur_line->next;
if (cur_line!=&root && templ!=&root) {
src=MPrint("%s%s",cur_line->line,templ->line);
Free(cur_line->line);
Free(templ->line);
cur_line->line=src;
QueRem(templ);
Free(templ);
}
} else
StrCpy(cur_line->line+cur_col,cur_line->line+cur_col+1);
break;
}
break;
case '\n':
case '\r':
templ=MAlloc(sizeof(CLine));
templ->line=StrNew(cur_line->line+cur_col);
cur_line->line[cur_col]=0;
QueIns(templ,cur_line);
cur_line=templ;
cur_col=0;
break;
case CH_BACKSPACE:
if (cur_col) {
StrCpy(cur_line->line+cur_col-1,cur_line->line+cur_col);
cur_col--;
} else if (cur_line!=&root && cur_line->last!=&root) {
templ=cur_line->last;
src=MPrint("%s%s",templ->line,cur_line->line);
cur_col=StrLen(templ->line);
Free(cur_line->line);
Free(templ->line);
templ->line=src;
QueRem(cur_line);
Free(cur_line);
cur_line=templ;
}
break;
case CH_CTRLY:
if (cur_line!=&root) {
templ=cur_line;
cur_line=cur_line->next;
QueRem(templ);
Free(templ->line);
Free(templ);
cur_col=0;
}
break;
default:
if (Bt(chars_bitmap_getkey,ch)) {
if (cur_line==&root) {
cur_line=MAlloc(sizeof(CLine));
cur_line->line=StrNew("");
QueIns(cur_line,root.last);
}
src=MAlloc(StrLen(cur_line->line)+2);
MemCpy(src,cur_line->line,cur_col);
src[cur_col]=ch;
if (cur_col<StrLen(cur_line->line))
StrCpy(src+cur_col+1,cur_line->line+cur_col);
else
src[cur_col+1]=0;
Free(cur_line->line);
cur_line->line=src;
cur_col++;
}
}
} while (ch!=CH_SHIFT_ESC && ch!=CH_ESC);
if (ch==CH_ESC) {
size=bin_size;
templ=root.next;
while (templ!=&root) {
size+=StrLen(templ->line)+1;
templ=templ->next;
}
buf=dst=MAlloc(size);
templ=root.next;
while (templ!=&root) {
i=StrLen(templ->line);
MemCpy(dst,templ->line,i);
dst+=i;
*dst++='\n';
templ=templ->next;
}
if (bin_data)
MemCpy(dst,bin_data,bin_size);
FileWrite(filename,buf,size);
Free(buf);
}
templ=root.next;
while (templ!=&root) {
templ1=templ->next;
QueRem(templ);
Free(templ->line);
Free(templ);
templ=templ1;
}
Free(root.line);
Free(bin_data);
Raw(old_raw);
InDbg(old_debug);
SingleUser(old_single);
sys_raw_flags=sys_raw_flags&~RWF_SHOW_DOLLAR|old_raw_flags&RWF_SHOW_DOLLAR;
POPFD
}
U0 ToFileLine(U8 *_fl_file_line,U8 **_filename,I64 *_linenum)
{
U8 *st,*fl_file_line=StrNew(_fl_file_line);
I64 linenum;
StrFirstRem(fl_file_line,":");
st=StrNew(fl_file_line);
StrLastRem(fl_file_line,",",st);
linenum=A2I64(st);
Free(st);
*_filename=fl_file_line;
*_linenum=linenum;
}
U0 EdLiteFileLine(U8 *fl_file_line)
{
U8 *filename;
I64 linenum;
ToFileLine(fl_file_line,&filename,&linenum);
EdLite(filename,linenum);
Free(filename);
}
U0 SetFix(U8 *filename,I64 line)
{//Compiler calls this to set file line for Fix
U8 *st=MPrint("FL:%s,%d",filename,line);
while (LBts(&sys_semas[SYS_SEMA_FIX],0))
Yield;
Free(sys_fix_file_line);
sys_fix_file_line=AStrNew(st);
LBtr(&sys_semas[SYS_SEMA_FIX],0);
}
U0 Fix()
{//Fix last compile err
U8 *st;
while (LBts(&sys_semas[SYS_SEMA_FIX],0))
Yield;
st=StrNew(sys_fix_file_line);
LBtr(&sys_semas[SYS_SEMA_FIX],0);
if (st) {
if (IsRaw)
EdLiteFileLine(st);
else
Ed(st);
}
Free(st);
}
+154
View File
@@ -0,0 +1,154 @@
asm {
USE64
#assert !((REG_NON_PTR_MASK|REG_VARS_MASK)&~0xFCC0)
_TEST_EXCEPT::
XOR RAX,RAX
MOV RAX,FS:U64 CTask.last_except[RAX]
MOV RBP,U64 CExcept.rbp[RAX]
MOV RSI,U64 CExcept.rsi[RAX]
MOV RDI,U64 CExcept.rdi[RAX]
MOV R10,U64 CExcept.r10[RAX]
MOV R11,U64 CExcept.r11[RAX]
MOV R12,U64 CExcept.r12[RAX]
MOV R13,U64 CExcept.r13[RAX]
MOV R14,U64 CExcept.r14[RAX]
MOV R15,U64 CExcept.r15[RAX]
PUSH U64 CExcept.rflags[RAX]
POPFD
JMP U64 CExcept.handler_catch[RAX]
_TAKE_EXCEPT::
XOR RAX,RAX
MOV RAX,FS:U64 CTask.last_except[RAX]
MOV RSP,U64 CExcept.rsp[RAX]
JMP U64 CExcept.handler_untry[RAX]
_SAVE_EXCEPT_REGS::
PUSH RBP
MOV RBP,RSP
MOV RAX,U64 SF_ARG1[RBP]
MOV U64 CExcept.rsi[RAX],RSI
MOV U64 CExcept.rdi[RAX],RDI
MOV U64 CExcept.r10[RAX],R10
MOV U64 CExcept.r11[RAX],R11
MOV U64 CExcept.r12[RAX],R12
MOV U64 CExcept.r13[RAX],R13
MOV U64 CExcept.r14[RAX],R14
MOV U64 CExcept.r15[RAX],R15
POP RBP
RET1 8
}
_extern _TEST_EXCEPT U0 TestExcept();
_extern _TAKE_EXCEPT U0 TakeExcept();
_extern _SAVE_EXCEPT_REGS U0 SaveExceptRegs(CExcept *t);
U0 PutExcept(Bool catch_it=TRUE)
{
"Except:%c:%P:%P\n",Fs->except_ch,Fs->except_caller1,Fs->except_caller2;
Fs->catch_except=catch_it;
}
#exe {OptOn(OPTf_NO_REG_VAR);};
class CTryStk
{
I64 rbp;
I64 ret_rip;
I64 arg1;
I64 arg2;
};
U0 SysTry(U8 *catch_start,U8 *untry_start)
{
I64 *rbp=GetRBP;
CExcept *tempt=MAlloc(sizeof(CExcept));
tempt->handler_catch=catch_start;
tempt->handler_untry=untry_start;
tempt->rsp=rbp(U8 *)+sizeof(CTryStk);
tempt->rbp=*rbp;
tempt->rflags=GetRFlags;
SaveExceptRegs(tempt);
QueIns(tempt,Fs->last_except);
}
U0 SysUntry()
{
CExcept *tempt=Fs->last_except;
QueRem(tempt);
Free(tempt);
}
U0 throw(I64 ch=0,Bool no_log=FALSE)
{
CExcept *tempt=Fs->last_except;
Bool was_raw;
Fs->except_ch=ch;
Fs->except_caller1=Caller(1);
Fs->except_caller2=Caller(2);
Fs->except_rbp=GetRBP;
Fs->catch_except=FALSE;
if (!no_log)
AdamLog("Except:%c:%p:%p\n",ch,Fs->except_caller1,Fs->except_caller2);
while (Fs->next_except!=&Fs->next_except) {
TestExcept;
if (Fs->catch_except)
TakeExcept;
SetRBP(Fs->except_rbp);
tempt=Fs->last_except;
QueRem(tempt);
Free(tempt);
}
was_raw=Raw(ON);
PutExcept(FALSE);
Dbg("Unhandled Exception");
Raw(was_raw);
}
#exe {OptOff(OPTf_NO_REG_VAR);};
U0 SysThrowBreak()
{
if (Bt(&Fs->task_flags,TASKf_BREAK_TO_SHIFT_ESC))
Msg(MSG_KEY_DOWN,CH_SHIFT_ESC,0x20100000201);
else { //TODO: Might want lock
Fs->wake_jiffy=0;
TaskRstAwaitingMsg;
PrtsRelease();
BlkDevsRelease();
FlushMsgs;
throw('Break');
}
}
//This can be used to exit an app, but not a task.
U0 ThrowBreak(CTask *task=NULL)
{
if (task && task!=Fs) {
if (!TaskValidate(task)) return;
//TODO: Might want lock
sys_focus_task=task;
LBts(sys_ctrl_alt_flags,SYSf_CTRL_ALT_C);
} else
SysThrowBreak;
}
Bool BreakLock(CTask *task=NULL)
{ //This disables CTRL-ALT-C
if (!task) task=Fs;
return !LBts(&task->task_flags,TASKf_BREAK_LOCKED);
}
Bool BreakUnlock(CTask *task=NULL)
{
Bool result;
if (!task) task=Fs;
result=LBtr(&task->task_flags,TASKf_BREAK_LOCKED);
if (LBtr(&task->task_flags,TASKf_PENDING_BREAK)) {
if (task==Fs)
ThrowBreak;
else
task->rip=&ThrowBreak;
}
return result;
}
+260
View File
@@ -0,0 +1,260 @@
//See $LK,"::/Doc/Acknowledgements.TXT"$.
U8 sys_font_8x8[256*8]= {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,//
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//
0x18,0x3C,0x3C,0x18,0x18,0x00,0x18,0x00,//!
0x36,0x36,0x36,0x00,0x00,0x00,0x00,0x00,//"
0x6C,0x6C,0xFE,0x6C,0xFE,0x6C,0x6C,0x00,//#
0x30,0xFC,0x16,0x7C,0xD0,0x7E,0x18,0x00,//$$
0x06,0x66,0x30,0x18,0x0C,0x66,0x60,0x00,//%
0x1C,0x36,0x36,0x1C,0xB6,0x66,0xDC,0x00,//&
0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00,//'
0x30,0x18,0x0C,0x0C,0x0C,0x18,0x30,0x00,//(
0x0C,0x18,0x30,0x30,0x30,0x18,0x0C,0x00,//)
0x00,0x18,0x7E,0x3C,0x7E,0x18,0x00,0x00,//*
0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,//+
0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x0C,//,
0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,//-
0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,//.
0x00,0x60,0x30,0x18,0x0C,0x06,0x00,0x00,///
0x3C,0x66,0x76,0x7E,0x6E,0x66,0x3C,0x00,//0
0x18,0x1C,0x18,0x18,0x18,0x18,0x7E,0x00,//1
0x3C,0x66,0x60,0x30,0x18,0x0C,0x7E,0x00,//2
0x3C,0x66,0x60,0x38,0x60,0x66,0x3C,0x00,//3
0x30,0x38,0x3C,0x36,0x7E,0x30,0x30,0x00,//4
0x7E,0x06,0x3E,0x60,0x60,0x66,0x3C,0x00,//5
0x38,0x0C,0x06,0x3E,0x66,0x66,0x3C,0x00,//6
0x7E,0x60,0x30,0x18,0x0C,0x0C,0x0C,0x00,//7
0x3C,0x66,0x66,0x3C,0x66,0x66,0x3C,0x00,//8
0x3C,0x66,0x66,0x7C,0x60,0x30,0x1C,0x00,//9
0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x00,//:
0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x0C,//;
0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x00,//<
0x00,0x00,0x7E,0x00,0x7E,0x00,0x00,0x00,//=
0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x00,//>
0x3C,0x66,0x30,0x18,0x18,0x00,0x18,0x00,//?
0x3C,0x66,0x76,0x56,0x76,0x06,0x3C,0x00,//@
0x3C,0x66,0x66,0x7E,0x66,0x66,0x66,0x00,//A
0x3E,0x66,0x66,0x3E,0x66,0x66,0x3E,0x00,//B
0x3C,0x66,0x06,0x06,0x06,0x66,0x3C,0x00,//C
0x1E,0x36,0x66,0x66,0x66,0x36,0x1E,0x00,//D
0x7E,0x06,0x06,0x3E,0x06,0x06,0x7E,0x00,//E
0x7E,0x06,0x06,0x3E,0x06,0x06,0x06,0x00,//F
0x3C,0x66,0x06,0x76,0x66,0x66,0x3C,0x00,//G
0x66,0x66,0x66,0x7E,0x66,0x66,0x66,0x00,//H
0x7E,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,//I
0x7C,0x30,0x30,0x30,0x30,0x36,0x1C,0x00,//J
0x66,0x36,0x1E,0x0E,0x1E,0x36,0x66,0x00,//K
0x06,0x06,0x06,0x06,0x06,0x06,0x7E,0x00,//L
0xC6,0xEE,0xFE,0xD6,0xD6,0xC6,0xC6,0x00,//M
0x66,0x66,0x6E,0x7E,0x76,0x66,0x66,0x00,//N
0x3C,0x66,0x66,0x66,0x66,0x66,0x3C,0x00,//O
0x3E,0x66,0x66,0x3E,0x06,0x06,0x06,0x00,//P
0x3C,0x66,0x66,0x66,0x56,0x36,0x6C,0x00,//Q
0x3E,0x66,0x66,0x3E,0x36,0x66,0x66,0x00,//R
0x3C,0x66,0x06,0x3C,0x60,0x66,0x3C,0x00,//S
0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x00,//T
0x66,0x66,0x66,0x66,0x66,0x66,0x3C,0x00,//U
0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x00,//V
0xC6,0xC6,0xD6,0xD6,0xFE,0xEE,0xC6,0x00,//W
0x66,0x66,0x3C,0x18,0x3C,0x66,0x66,0x00,//X
0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x00,//Y
0x7E,0x60,0x30,0x18,0x0C,0x06,0x7E,0x00,//Z
0x3E,0x06,0x06,0x06,0x06,0x06,0x3E,0x00,//[
0x00,0x06,0x0C,0x18,0x30,0x60,0x00,0x00,//\
0x7C,0x60,0x60,0x60,0x60,0x60,0x7C,0x00,//]
0x3C,0x66,0x00,0x00,0x00,0x00,0x00,0x00,//^
0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,//_
0x0C,0x18,0x30,0x00,0x00,0x00,0x00,0x00,//`
0x00,0x00,0x3C,0x60,0x7C,0x66,0x7C,0x00,//a
0x06,0x06,0x3E,0x66,0x66,0x66,0x3E,0x00,//b
0x00,0x00,0x3C,0x66,0x06,0x66,0x3C,0x00,//c
0x60,0x60,0x7C,0x66,0x66,0x66,0x7C,0x00,//d
0x00,0x00,0x3C,0x66,0x7E,0x06,0x3C,0x00,//e
0x38,0x0C,0x0C,0x3E,0x0C,0x0C,0x0C,0x00,//f
0x00,0x00,0x7C,0x66,0x66,0x7C,0x60,0x3C,//g
0x06,0x06,0x3E,0x66,0x66,0x66,0x66,0x00,//h
0x18,0x00,0x1C,0x18,0x18,0x18,0x3C,0x00,//i
0x18,0x00,0x1C,0x18,0x18,0x18,0x18,0x0E,//j
0x06,0x06,0x66,0x36,0x1E,0x36,0x66,0x00,//k
0x1C,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,//l
0x00,0x00,0x6C,0xFE,0xD6,0xD6,0xC6,0x00,//m
0x00,0x00,0x3E,0x66,0x66,0x66,0x66,0x00,//n
0x00,0x00,0x3C,0x66,0x66,0x66,0x3C,0x00,//o
0x00,0x00,0x3E,0x66,0x66,0x3E,0x06,0x06,//p
0x00,0x00,0x7C,0x66,0x66,0x7C,0x60,0xE0,//q
0x00,0x00,0x36,0x6E,0x06,0x06,0x06,0x00,//r
0x00,0x00,0x7C,0x06,0x3C,0x60,0x3E,0x00,//s
0x0C,0x0C,0x3E,0x0C,0x0C,0x0C,0x38,0x00,//t
0x00,0x00,0x66,0x66,0x66,0x66,0x7C,0x00,//u
0x00,0x00,0x66,0x66,0x66,0x3C,0x18,0x00,//v
0x00,0x00,0xC6,0xD6,0xD6,0xFE,0x6C,0x00,//w
0x00,0x00,0x66,0x3C,0x18,0x3C,0x66,0x00,//x
0x00,0x00,0x66,0x66,0x66,0x7C,0x60,0x3C,//y
0x00,0x00,0x7E,0x30,0x18,0x0C,0x7E,0x00,//z
0x30,0x18,0x18,0x0E,0x18,0x18,0x30,0x00,//{
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,//|
0x0C,0x18,0x18,0x70,0x18,0x18,0x0C,0x00,//}
0x8C,0xD6,0x62,0x00,0x00,0x00,0x00,0x00,//~
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0x1E,0x33,0x03,0x33,0x1E,0x18,0x30,0x1E,//€
0x00,0x33,0x00,0x33,0x33,0x33,0x7E,0x00,//�
0x38,0x00,0x1E,0x33,0x3F,0x03,0x1E,0x00,//‚
0x7E,0xC3,0x3C,0x60,0x7C,0x66,0xFC,0x00,//ƒ
0x33,0x00,0x1E,0x30,0x3E,0x33,0x7E,0x00,//„
0x07,0x00,0x1E,0x30,0x3E,0x33,0x7E,0x00,//…
0x0C,0x0C,0x1E,0x30,0x3E,0x33,0x7E,0x00,//†
0x00,0x00,0x3E,0x03,0x03,0x3E,0x60,0x3C,//‡
0x7E,0xC3,0x3C,0x66,0x7E,0x06,0x3C,0x00,//ˆ
0x33,0x00,0x1E,0x33,0x3F,0x03,0x1E,0x00,//‰
0x07,0x00,0x1E,0x33,0x3F,0x03,0x1E,0x00,//Š
0x33,0x00,0x0E,0x0C,0x0C,0x0C,0x1E,0x00,//‹
0x3E,0x63,0x1C,0x18,0x18,0x18,0x3C,0x00,//Œ
0x07,0x00,0x0E,0x0C,0x0C,0x0C,0x1E,0x00,//�
0x33,0x0C,0x1E,0x33,0x33,0x3F,0x33,0x00,//Ž
0x0C,0x0C,0x00,0x1E,0x33,0x3F,0x33,0x00,//�
0x38,0x00,0x3F,0x06,0x1E,0x06,0x3F,0x00,//�
0x00,0x00,0xFE,0x30,0xFE,0x33,0xFE,0x00,//‘
0x7C,0x36,0x33,0x7F,0x33,0x33,0x73,0x00,//’
0x1E,0x33,0x00,0x1E,0x33,0x33,0x1E,0x00,//“
0x00,0x33,0x00,0x1E,0x33,0x33,0x1E,0x00,//”
0x00,0x07,0x00,0x1E,0x33,0x33,0x1E,0x00,//•
0x1E,0x33,0x00,0x33,0x33,0x33,0x7E,0x00,//–
0x00,0x07,0x00,0x33,0x33,0x33,0x7E,0x00,//—
0x00,0x33,0x00,0x33,0x33,0x3F,0x30,0x1F,//˜
0x63,0x1C,0x3E,0x63,0x63,0x3E,0x1C,0x00,//™
0x33,0x00,0x33,0x33,0x33,0x33,0x1E,0x00,//š
0x18,0x18,0x7E,0x03,0x03,0x7E,0x18,0x18,//›
0x1C,0x36,0x26,0x0F,0x06,0x67,0x3F,0x00,//œ
0x33,0x33,0x1E,0x3F,0x0C,0x3F,0x0C,0x00,//�
0x0F,0x1B,0x1B,0x2F,0x33,0x7B,0x33,0x70,//ž
0x70,0xD8,0x18,0x7E,0x18,0x18,0x1B,0x0E,//Ÿ
0x38,0x00,0x1E,0x30,0x3E,0x33,0x7E,0x00,// 
0x1C,0x00,0x0E,0x0C,0x0C,0x0C,0x1E,0x00,//¡
0x00,0x38,0x00,0x1E,0x33,0x33,0x1E,0x00,//¢
0x00,0x38,0x00,0x33,0x33,0x33,0x7E,0x00,//£
0x00,0x1F,0x00,0x1F,0x33,0x33,0x33,0x00,//¤
0x3F,0x00,0x33,0x37,0x3F,0x3B,0x33,0x00,//¥
0x3C,0x36,0x36,0x7C,0x00,0x7E,0x00,0x00,//¦
0x3C,0x66,0x66,0x3C,0x00,0x7E,0x00,0x00,//§
0x0C,0x00,0x0C,0x06,0x03,0x33,0x1E,0x00,//¨
0x00,0x00,0x00,0x3F,0x03,0x03,0x00,0x00,//©
0x00,0x00,0x00,0x3F,0x30,0x30,0x00,0x00,//ª
0x63,0x33,0x1B,0x7C,0xC6,0x73,0x19,0xF8,//«
0x63,0x33,0x1B,0xCF,0xE6,0xF3,0xF9,0xC0,//¬
0x00,0x18,0x00,0x18,0x18,0x3C,0x3C,0x18,//­
0x00,0xCC,0x66,0x33,0x66,0xCC,0x00,0x00,//®
0x00,0x33,0x66,0xCC,0x66,0x33,0x00,0x00,//¯
0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,//°
0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,//±
0xBB,0xEE,0xBB,0xEE,0xBB,0xEE,0xBB,0xEE,//²
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,//³
0x18,0x18,0x18,0x18,0x1F,0x18,0x18,0x18,//´
0x18,0x18,0x1F,0x18,0x1F,0x18,0x18,0x18,//µ
0x6C,0x6C,0x6C,0x6C,0x6F,0x6C,0x6C,0x6C,//¶
0x00,0x00,0x00,0x00,0x7F,0x6C,0x6C,0x6C,//·
0x00,0x00,0x1F,0x18,0x1F,0x18,0x18,0x18,//¸
0x6C,0x6C,0x6F,0x60,0x6F,0x6C,0x6C,0x6C,//¹
0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,//º
0x00,0x00,0x7F,0x60,0x6F,0x6C,0x6C,0x6C,//»
0x6C,0x6C,0x6F,0x60,0x7F,0x00,0x00,0x00,//¼
0x6C,0x6C,0x6C,0x6C,0x7F,0x00,0x00,0x00,//½
0x18,0x18,0x1F,0x18,0x1F,0x00,0x00,0x00,//¾
0x00,0x00,0x00,0x00,0x1F,0x18,0x18,0x18,//¿
0x18,0x18,0x18,0x18,0xF8,0x00,0x00,0x00,//À
0x18,0x18,0x18,0x18,0xFF,0x00,0x00,0x00,//Á
0x00,0x00,0x00,0x00,0xFF,0x18,0x18,0x18,//Â
0x18,0x18,0x18,0x18,0xF8,0x18,0x18,0x18,//Ã
0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,//Ä
0x18,0x18,0x18,0x18,0xFF,0x18,0x18,0x18,//Å
0x18,0x18,0xF8,0x18,0xF8,0x18,0x18,0x18,//Æ
0x6C,0x6C,0x6C,0x6C,0xEC,0x6C,0x6C,0x6C,//Ç
0x6C,0x6C,0xEC,0x0C,0xFC,0x00,0x00,0x00,//È
0x00,0x00,0xFC,0x0C,0xEC,0x6C,0x6C,0x6C,//É
0x6C,0x6C,0xEF,0x00,0xFF,0x00,0x00,0x00,//Ê
0x00,0x00,0xFF,0x00,0xEF,0x6C,0x6C,0x6C,//Ë
0x6C,0x6C,0xEC,0x0C,0xEC,0x6C,0x6C,0x6C,//Ì
0x00,0x00,0xFF,0x00,0xFF,0x00,0x00,0x00,//Í
0x6C,0x6C,0xEF,0x00,0xEF,0x6C,0x6C,0x6C,//Î
0x18,0x18,0xFF,0x00,0xFF,0x00,0x00,0x00,//Ï
0x6C,0x6C,0x6C,0x6C,0xFF,0x00,0x00,0x00,//Ð
0x00,0x00,0xFF,0x00,0xFF,0x18,0x18,0x18,//Ñ
0x00,0x00,0x00,0x00,0xFF,0x6C,0x6C,0x6C,//Ò
0x6C,0x6C,0x6C,0x6C,0xFC,0x00,0x00,0x00,//Ó
0x18,0x18,0xF8,0x18,0xF8,0x00,0x00,0x00,//Ô
0x00,0x00,0xF8,0x18,0xF8,0x18,0x18,0x18,//Õ
0x00,0x00,0x00,0x00,0xFC,0x6C,0x6C,0x6C,//Ö
0x6C,0x6C,0x6C,0x6C,0xEF,0x6C,0x6C,0x6C,//×
0x18,0x18,0xFF,0x00,0xFF,0x18,0x18,0x18,//Ø
0x18,0x18,0x18,0x18,0x1F,0x00,0x00,0x00,//Ù
0x00,0x00,0x00,0x00,0xF8,0x18,0x18,0x18,//Ú
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,//Û
0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,//Ü
0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,//Ý
0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,//Þ
0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,//ß
0x00,0x00,0x6E,0x3B,0x13,0x3B,0x6E,0x00,//à
0x00,0x1E,0x33,0x1F,0x33,0x1F,0x03,0x03,//á
0x00,0x7F,0x63,0x03,0x03,0x03,0x03,0x00,//â
0x00,0x7F,0x36,0x36,0x36,0x36,0x36,0x00,//ã
0x7F,0x66,0x0C,0x18,0x0C,0x66,0x7F,0x00,//ä
0x00,0x00,0x7E,0x33,0x33,0x33,0x1E,0x00,//å
0x00,0x66,0x66,0x66,0x66,0x3E,0x06,0x03,//æ
0x00,0x6E,0x3B,0x18,0x18,0x18,0x18,0x00,//ç
0x3F,0x0C,0x1E,0x33,0x33,0x1E,0x0C,0x3F,//è
0x1C,0x36,0x63,0x7F,0x63,0x36,0x1C,0x00,//é
0x1C,0x36,0x63,0x63,0x36,0x36,0x77,0x00,//ê
0x38,0x0C,0x18,0x3E,0x33,0x33,0x1E,0x00,//ë
0x00,0x00,0x7E,0xDB,0xDB,0x7E,0x00,0x00,//ì
0x60,0x30,0x7E,0xDB,0xDB,0x7E,0x06,0x03,//í
0x3C,0x06,0x03,0x3F,0x03,0x06,0x3C,0x00,//î
0x1E,0x33,0x33,0x33,0x33,0x33,0x33,0x00,//ï
0x00,0x3F,0x00,0x3F,0x00,0x3F,0x00,0x00,//ð
0x0C,0x0C,0x3F,0x0C,0x0C,0x00,0x3F,0x00,//ñ
0x06,0x0C,0x18,0x0C,0x06,0x00,0x3F,0x00,//ò
0x18,0x0C,0x06,0x0C,0x18,0x00,0x3F,0x00,//ó
0x70,0xD8,0xD8,0x18,0x18,0x18,0x18,0x18,//ô
0x18,0x18,0x18,0x18,0x18,0x1B,0x1B,0x0E,//õ
0x0C,0x0C,0x00,0x3F,0x00,0x0C,0x0C,0x00,//ö
0x00,0x4E,0x39,0x00,0x4E,0x39,0x00,0x00,//÷
0x1C,0x36,0x36,0x1C,0x00,0x00,0x00,0x00,//ø
0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,//ù
0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,//ú
0xF0,0x30,0x30,0x30,0x37,0x36,0x3C,0x38,//û
0x1E,0x36,0x36,0x36,0x36,0x00,0x00,0x00,//ü
0x1E,0x30,0x1C,0x06,0x3E,0x00,0x00,0x00,//ý
0x00,0x00,0x3C,0x3C,0x3C,0x3C,0x00,0x00,//þ
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//ÿ
};
BIN
View File
Binary file not shown.
+457
View File
@@ -0,0 +1,457 @@
I64 HashTypeNum(CHash *temph)
{
if (temph)
return Bsf(temph->type&HTG_TYPE_MASK);
else
return -1;
}
I64 HashVal(CHash *temph)
{
nobound_switch (HashTypeNum(temph)) {
case HTt_EXPORT_SYS_SYM:
return temph(CHashExport *)->val;
case HTt_IMPORT_SYS_SYM:
return temph(CHashImport *)->module_base;
case HTt_DEFINE_STR:
case HTt_CLASS:
case HTt_INTERNAL_TYPE:
case HTt_WORD:
case HTt_DICT_WORD:
case HTt_OPCODE:
case HTt_HELP_FILE:
return temph;
case HTt_GLBL_VAR:
if (temph(CHashGlblVar *)->flags&GVF_EXTERN)
return &temph(CHashGlblVar *)->data_addr;
else
return temph(CHashGlblVar *)->data_addr;
case HTt_FUN:
if (Bt(&temph(CHashFun *)->flags,Cf_EXTERN))
return temph;
else
return temph(CHashFun *)->executable_addr;
case HTt_REG:
return temph(CHashReg *)->reg_num|temph(CHashReg *)->reg_type<<8;
case HTt_KEYWORD:
case HTt_ASM_KEYWORD:
case HTt_MODULE:
case HTt_FILE:
case HTt_FRAME_PTR:
return temph(CHashGeneric *)->user_data0;
case -1: //nobound_switch
case HTt_NUM_TYPES: //nobound_switch
default:
return 0;
}
}
CHashTable *HashTableNew(I64 size,CTask *mem_task=NULL)
{
CHashTable *tempht;
tempht=CAlloc(sizeof(CHashTable),mem_task);
tempht->body=CAlloc(size<<3,mem_task);
tempht->mask=size-1;
tempht->next_added=tempht->last_added=tempht;
return tempht;
}
U0 HashDel(CHashSrcSym *temph)
{
if (!temph) return;
if (!(temph->type&HTT_DICT_WORD))
Free(temph->str);
if (temph->type & HTG_SRC_SYM) {
Free(temph->src_link);
Free(temph->index);
Free(temph->import_name);
LinkedLstDel(temph->ie_lst);
if (temph->type & (HTT_FUN | HTT_EXPORT_SYS_SYM))
Free(temph->debug);
if (temph->type & (HTT_FUN | HTT_CLASS))
//Assumes code not on heap, so doesn't Free.
//$LK,"MemberLstDel",A="MN:MemberLstDel"$() is an import to the Kernel module
MemberLstDel(temph);
else if (temph->type&HTT_DEFINE_STR)
Free(temph(CHashDefineStr *)->data);
else if (temph->type & HTT_GLBL_VAR) {
if (!(temph(CHashGlblVar *)->flags&GVF_ALIAS))
Free(temph(CHashGlblVar *)->data_addr);
LinkedLstDel(temph(CHashGlblVar *)->dim.next);
if (temph(CHashGlblVar *)->fun_ptr)
HashDel(temph(CHashGlblVar *)->fun_ptr-temph(CHashGlblVar *)->fun_ptr->ptr_cnt);
}
} else if (temph->type & HTT_FILE)
Free(temph(CHashGeneric *)->user_data0);
Free(temph);
}
U0 HashTableDel(CHashTable *tempht)
{
CHashSrcSym *temph,*temph1;
if (!tempht) return;
temph=tempht->next_added;
while (temph!=tempht) {
temph1=temph->next_added;
HashDel(temph);
temph=temph1;
}
Free(tempht->body);
Free(tempht);
}
I64 HashTablePurge(CHashTable *tempht)
{
I64 result=0;
CHashSrcSym *temph,*temph1,*temph2;
if (!tempht) return 0;
PUSHFD
CLI //Precaution
temph=tempht->next_added;
while (temph!=tempht) {
temph1=temph->next_added; //We delete only older ones
if (temph->type&(HTT_FUN|HTT_GLBL_VAR)) {
temph2=temph->next; //Older always later in chain
while (temph2) {
if ((temph2->type&HTT_EXPORT_SYS_SYM || temph2->type&HTG_TYPE_MASK==HTT_INVALID) &&
!StrCmp(temph2->str,temph->str)) {
if (temph2->type&HTG_TYPE_MASK==HTT_INVALID)
temph2->type=HTT_KEYWORD;//Won't delete HTT_INVALID
HashRemDel(temph2,tempht);
result++;
break;
}
temph2=temph2->next;
}
}
temph=temph1;
}
POPFD
return result;
}
CHashGeneric *HashGenericAdd(U8 *name,I64 type,I64 u0=0,I64 u1=0,I64 u2=0,CTask *task=NULL)
{
if (!task) task=Fs;
CHashGeneric *result=CAlloc(sizeof(CHashGeneric),task);
result->type=type;
result->user_data0=u0;
result->user_data1=u1;
result->user_data2=u2;
result->str=StrNew(name,task);
HashAdd(result,task->hash_table);
return result;
}
U0 SetSrcFileInfo(CLex *lx,CHashSrcSym *h)
{
CLexFile *tempf=lx->cur_lfn;
h->src_link=MPrint("FL:%s,%d",tempf->name,tempf->line_num);
if (Bt(&lx->opts,OPTf_KEEP_PRIVATE))
h->type|=HTF_PRIVATE;
if (lx->cur_index)
h->index=StrNew(lx->cur_index);
else
h->index=NULL;
}
CHashGeneric *HashPublic(U8 *st,I64 mask,Bool val=TRUE)
{
CHashGeneric *result;
if (result=HashFind(st,Fs->hash_table,mask)) {
if (val)
result->type|=HTF_PUBLIC;
else
result->type&=~HTF_PUBLIC;
if (result->type&HTG_SRC_SYM)
SetSrcFileInfo(Fs->last_lex,result);
return result;
} else
return NULL;
}
I64 HashLstAdd(U8 *lst,I64 type,CHashTable *table)
{//Add a list to a hash table.
I64 i=0;
CHashGeneric *temph;
if (lst) {
while (*lst) {
if (*lst=='@')
lst++;
else
i++;
temph=CAlloc(sizeof(CHashGeneric));
temph->user_data0=i-1;
temph->str=StrNew(lst);
temph->type=type;
HashAdd(temph,table);
while (*lst++);
}
}
return i;
}
I64 HashDefineLstAdd(U8 *name,I64 type,CHashTable *table)
{//Add a define list to a hash table.
CHashDefineStr *temph;
if (temph=HashFind(name,Fs->hash_table,HTT_DEFINE_STR))
return HashLstAdd(temph->data,type,table);
else
return 0;
}
I64 FramePtr(U8 *name,CTask *task=NULL)
{
CHashGeneric *temph;
if (!task) task=Fs;
if (temph=HashFind(name,task->hash_table,HTT_FRAME_PTR))
return temph->user_data0;
else
return 0;
}
CHashGeneric *FramePtrAdd(U8 *name,I64 val,CTask *task=NULL)
{
return HashGenericAdd(name,HTT_FRAME_PTR,val,0,0,task);
}
I64 FramePtrSet(U8 *name,I64 val,CTask *task=NULL)
{
CHashGeneric *temph;
if (!task) task=Fs;
if (temph=HashFind(name,task->hash_table,HTT_FRAME_PTR))
return LXchgU64(&temph->user_data0,val);
else
return 0;
}
I64 FramePtrDel(U8 *name,CTask *task=NULL)
{
CHashGeneric *temph;
I64 result=0;
if (!task) task=Fs;
if (temph=HashFind(name,task->hash_table,HTT_FRAME_PTR)) {
result=temph->user_data0;
HashRemDel(temph,task->hash_table);
}
return result;
}
U0 LoadOneImport(U8 **_src,U8 *module_base,I64 ld_flags)
{
U8 *src=*_src,*ptr2,*st_ptr;
I64 i,etype;
CHashExport *tempex=NULL;
CHashImport *tempiss;
Bool first=TRUE;
while (etype=*src++) {
i=*src(U32 *)++;
st_ptr=src;
src+=StrLen(st_ptr)+1;
if (*st_ptr) {
if (!first) {
*_src=st_ptr-5;
return;
} else {
first=FALSE;
if (!(tempex=HashFind(st_ptr,Fs->hash_table,HTG_ALL-HTT_IMPORT_SYS_SYM))) {
if (!(ld_flags & LDF_SILENT))
"Unresolved Reference:%s\n",st_ptr;
tempiss=CAlloc(sizeof(CHashImport));
tempiss->str=StrNew(st_ptr);
tempiss->type=HTT_IMPORT_SYS_SYM;
tempiss->module_header_entry=st_ptr-5;
tempiss->module_base=module_base;
HashAdd(tempiss,Fs->hash_table);
}
}
}
if (tempex) {
ptr2=module_base+i;
if (tempex->type & HTT_FUN)
i=tempex(CHashFun *)->executable_addr;
else if (tempex->type & HTT_GLBL_VAR)
i=tempex(CHashGlblVar *)->data_addr;
else
i=tempex->val;
switch (etype) {
case EIT_REL_I8: *ptr2(U8 *) =i-ptr2-1; break;
case EIT_IMM_U8: *ptr2(U8 *) =i; break;
case EIT_REL_I16: *ptr2(U16 *)=i-ptr2-2; break;
case EIT_IMM_U16: *ptr2(U16 *)=i; break;
case EIT_REL_I32: *ptr2(U32 *)=i-ptr2-4; break;
case EIT_IMM_U32: *ptr2(U32 *)=i; break;
case EIT_REL_I64: *ptr2(I64 *)=i-ptr2-8; break;
case EIT_IMM_U64: *ptr2(I64 *)=i; break;
}
}
}
*_src=src-1;
}
U0 SysSymImportsResolve(U8 *st_ptr,I64 ld_flags)
{
CHashImport *tempiss;
U8 *ptr;
while (tempiss=HashSingleTableFind(st_ptr,Fs->hash_table,HTT_IMPORT_SYS_SYM)) {
ptr=tempiss->module_header_entry;
LoadOneImport(&ptr,tempiss->module_base,ld_flags);
tempiss->type=HTT_INVALID;
}
}
U0 LoadPass1(U8 *src,U8 *module_base,I64 ld_flags)
{
U8 *ptr2,*ptr3,*st_ptr;
I64 i,j,cnt,etype;
CHashExport *tempex=NULL;
while (etype=*src++) {
i=*src(U32 *)++;
st_ptr=src;
src+=StrLen(st_ptr)+1;
switch (etype) {
case EIT_REL_EXPORT:
case EIT_IMM_EXPORT:
tempex=CAlloc(sizeof(CHashExport));
tempex->str=StrNew(st_ptr);
tempex->type=HTT_EXPORT_SYS_SYM|HTF_IMM;
if (etype==EIT_IMM_EXPORT)
tempex->val=i;
else
tempex->val=i+module_base;
HashAdd(tempex,Fs->hash_table);
SysSymImportsResolve(st_ptr,ld_flags);
break;
case EIT_REL_I8...EIT_IMM_U64:
src=st_ptr-5;
LoadOneImport(&src,module_base,ld_flags);
break;
case EIT_ABS_ADDR:
if (ld_flags & LDF_NO_ABSS)
src+=i*sizeof(U32);
else {
cnt=i;
for (j=0;j<cnt;j++) {
ptr2=module_base+*src(U32 *)++;
*ptr2(U32 *)+=module_base;
}
}
break;
case EIT_HEAP_GLBL:
ptr3=MAlloc(*src(I64 *)++);
if (*st_ptr) {
tempex=CAlloc(sizeof(CHashExport));
tempex->str=StrNew(st_ptr);
tempex->type=HTT_EXPORT_SYS_SYM|HTF_IMM;
tempex->val=ptr3;
HashAdd(tempex,Fs->hash_table);
}
cnt=i;
for (j=0;j<cnt;j++) {
ptr2=module_base+*src(U32 *)++;
*ptr2(I64 *)+=ptr3;
}
break;
}
}
}
U0 LoadPass2(U8 *src,U8 *module_base,I64)
{
U8 *st_ptr;
I64 i,etype;
while (etype=*src++) {
i=*src(U32 *)++;
st_ptr=src;
src+=StrLen(st_ptr)+1;
switch (etype) {
case EIT_MAIN:
Call(i+module_base);
break;
case EIT_ABS_ADDR:
src+=sizeof(U32)*i;
break;
case EIT_HEAP_GLBL:
src+=8+sizeof(U32)*i;
break;
}
}
}
U8 *Load(U8 *filename,I64 ld_flags=0,CBinFile *bfh_addr=INVALID_PTR)
{ //See $LK,"BinRep",A="MN:BinRep"$().
//bfh_addr==INVALID_PTR means don't care what load addr.
U8 *fbuf,*module_base,*absname;
I64 size,module_alignment,module_org;
CBinFile *bfh;
CBinFilePatchTableWithOrg *bfpt;
fbuf=DftExt(filename,"BIN.Z");
if (!(bfh=FileRead(fbuf,&size))) {
Free(fbuf);
return NULL;
}
//See $LK,"Loader Patch Table Generation",A="FF:::/Compiler/CmpMain.CPP,EIT_MODULE_ALIGNMENT"$
bfpt=bfh(U8 *)+bfh->loader_patch_table_offset;
module_alignment=bfpt->module_alignment;
if (bfpt->eit_module_org==EIT_MODULE_ORG)
module_org=bfpt->module_org;
else
module_org=INVALID_PTR;
if (!module_alignment || Bsf(module_alignment)!=Bsr(module_alignment))
throw('BinModul');
#assert sizeof(CBinFile)==16
if (bfh_addr==INVALID_PTR) {
if (module_org==INVALID_PTR) {
if (Fs->code_heap!=Fs->data_heap) {
if (module_alignment<16)
module_alignment=16;
bfh_addr=MAllocAligned(size,module_alignment,Fs->code_heap,module_alignment-sizeof(CBinFile));
} else if (module_alignment>8)
bfh_addr=MAllocAligned(size,module_alignment,NULL,module_alignment-sizeof(CBinFile));
else { //Less than 2Gig system memory
bfh_addr=bfh;
goto lo_skip; //File is already in code heap area, don't copy.
}
} else
bfh_addr=module_org;
}
MemCpy(bfh_addr,bfh,size);
Free(bfh);
lo_skip:
module_base=bfh_addr(U8 *)+sizeof(CBinFile);
absname=FileNameAbs(fbuf);
Free(fbuf);
fbuf=StrNew(absname);
FileExtRem(fbuf);
if (fbuf[1]==':' && StrLen(fbuf)>2)
HashGenericAdd(fbuf+2,HTT_MODULE|HTF_PUBLIC,bfh_addr);
Free(fbuf);
LoadPass1(bfh_addr(U8 *)+bfh_addr->loader_patch_table_offset,module_base,ld_flags);
if (!(ld_flags&LDF_JUST_LOAD))
LoadPass2(bfh_addr(U8 *)+bfh_addr->loader_patch_table_offset,module_base,ld_flags);
Free(absname);
return bfh_addr;
}
U0 LoadKernel()
{
HashGenericAdd(KERNEL_MODULE_NAME,HTT_MODULE|HTF_PUBLIC,sys_boot_base-sizeof(CBinFile));
//Abs patches done here $LK,"CBinFilePatchTableWithoutOrg",A="FF:D:/Kernel/KStart.CPP,CBinFilePatchTableWithoutOrg"$.
LoadPass1(sys_boot_patch_table_base,sys_boot_base,LDF_NO_ABSS|LDF_SILENT);
//No main routines
// LoadPass2(sys_boot_patch_table_base,sys_boot_base,0);
}
+206
View File
@@ -0,0 +1,206 @@
asm {
USE64
SYS_MP_CRASH_HANDLER_ADDR:: //forward reference to work around compiler
DU32 &MPCrash;
SYS_WAKE_HANDLER::
PUSH RAX
MOV EAX,U32 LAPIC_EOI
MOV U32 [RAX],0
POP RAX
IRET
//I_TIMER
SYS_TIMER_HANDLER::
CALL TASK_CONTEXT_SAVE //PREEMPTIVE
CLD
MOV RBP,RSP
MOV RBX,U64 [RBP]
MOV U64 CTask.rip[RSI],RBX
MOV RAX,U64 16[RBP]
MOV U64 CTask.rflags[RSI],RAX
MOV RAX,U64 24[RBP]
MOV U64 CTask.rsp[RSI],RAX
XOR RAX,RAX
MOV RDI,U64 GS:CCPU.addr[RAX]
LOCK
INC U64 CCPU.total_jiffies[RDI]
BT U64 CTask.task_flags[RSI],TASKf_IDLE
JNC @@05
LOCK
INC U64 CCPU.idle_pt_hits[RDI]
@@05: MOV RAX,U64 CCPU.timer_irq_chain[RDI]
TEST RAX,RAX
JZ @@10
PUSH RSI
CALL RAX
JMP @@15
@@10: ADD RSP,8
@@15: CLI
MOV RAX,U64 CCPU.num[RDI]
TEST RAX,RAX
JZ @@20
MOV EAX,U32 LAPIC_EOI
MOV U32 [RAX],0
JMP @@25
@@20: MOV AL,0x20 //ACKNOWLEDGE INTERRUPT
OUT 0x20,AL
@@25: TEST U8 [SYS_SEMAS+SYS_SEMA_SINGLE_USER*SEMA_STRUCT_SIZE],1
JNZ @@30
BT U64 CTask.task_flags[RSI],TASKf_PREEMPT
JC I32 RESTORE_NEXT_RSI_TASK
@@30: JMP I32 RESTORE_RSI_NO_PREEMPT_TASK
// ************************************
SYS_IRQ_FAULT::
PUSH RBX
MOV RBX,U64 8[RSP]
PUSH RAX
XOR RAX,RAX
MOV FS:U32 CTask.fault_num[RAX],EBX
POP RAX
POP RBX
ADD RSP,8
CALL TASK_CONTEXT_SAVE
XOR RDX,RDX
MOV U64 CTask.fault_err_code[RSI],RDX
MOV EDX,U32 CTask.fault_num[RSI]
BT U64 [SYS_FAULT_ERR_CODE_BITMAP],RDX
JNC @@1
POP U64 CTask.fault_err_code[RSI]
@@1: MOV RBP,RSP
MOV RAX,U64 [RBP]
MOV U64 CTask.rip[RSI],RAX
MOV RAX,U64 16[RBP]
MOV U64 CTask.rflags[RSI],RAX
MOV RAX,U64 24[RBP]
MOV U64 CTask.rsp[RSI],RAX
MOV RSP,RAX
MOV RBP,CTask.rbp[RSI]
PUSH U64 CTask.fault_err_code[RSI]
PUSH U64 CTask.fault_num[RSI]
MOV RSI,CTask.rsi[RSI]
CALL &Fault2 //See $LK,"Fault2",A="FF:::/Kernel/Dbg1a.CPP,Fault2"$
JMP I32 RESTORE_FS_TASK_WITH_KEY_CHECK
SYS_FAULT_ERR_CODE_BITMAP::
DU32 0x00027D00,0,0,0,0,0,0,0;
}
U8 *IntEntryGet(I64 irq)
{
U8 *result;
I64 *src;
src=sys_idt(U8 *)+irq*16;
result(I64).u16[0]=*src(U16 *);
src(U8 *)+=6;
result(I64).u16[1]=*src(U16 *)++;
result(I64).u32[1]=*src(U32 *);
return result;
}
U8 *IntEntrySet(I64 irq,U0 (*fp_new_handler)(),I64 type=IDTET_IRQ,I64 dpl=0)
{
//See $LK,"IDTET_IRQ",A="MN:IDTET_IRQ"$
//See $LK,"::/Demo/Lectures/InterruptDemo.CPP"$
//See $LK,"::/Demo/MultiCore/Interrupts.CPP"$
I64 fp=fp_new_handler;
U8 *result,*dst;
result=IntEntryGet(irq);
dst=sys_idt(U8 *)+irq*16;
PUSHFD
CLI
*dst(U16 *)++=fp.u16[0];
*dst(U16 *)++=offset(CGDT.cs64);
*dst(U16 *)++=0x8000+type<<8+dpl<<13;
*dst(U16 *)++=fp.u16[1];
*dst(U32 *)++=fp.u32[1];
*dst(U32 *)=0;
POPFD
return result;
}
U0 IntsInit()
{
//Init 8259
OutU8(0x20,0x11); //IW1
OutU8(0xA0,0x11); //IW1
OutU8(0x21,0x20); //IW2
OutU8(0xA1,0x28); //IW2
OutU8(0x21,0x04); //IW3
OutU8(0xA1,0x02); //IW3
OutU8(0x21,0x0D); //IW4
OutU8(0xA1,0x09); //IW4
OutU8(0x21,0xFA); //Mask all but IRQ0 (timer) and IRQ2 Cascade
OutU8(0xA1,0xFF);
}
interrupt U0 IntNop()
{ //Make unplanned IRQs stop by all means!
OutU8(0xA0,0x20);
OutU8(0x20,0x20);
*LAPIC_EOI(U32 *)=0;
}
U8 *IntFaultHandlersNew()
{
I64 i;
U8 *result=MAlloc(256*10,Fs->code_heap),*dst=result;
for (i=0;i<256;i++) {
*dst++=0x68; //PUSH I32 xxxxxxxx
*dst(I32 *)++=i;
*dst++=0xE9; //JMP I32 xxxxxxxx
*dst(I32 *)=SYS_IRQ_FAULT-dst-4;
dst+=4;
}
return result;
}
U0 IntInit1()
{ //Interrupt descriptor table part1
I64 i,temp_ptr[2];
U32 *ptr;
if (!Gs->num) { //Gs cur $LK,"CCPU",A="MN:CCPU"$ struct
sys_idt=CAlloc(16*256);
for (i=0;i<256;i++)
IntEntrySet(i,&IntNop);
}
ptr=temp_ptr;
*ptr(U16 *)++=256*16-1; //Typecasting is postfix
*ptr(I64 *)++=sys_idt;
*ptr(U16 *)=0;
SetRAX(temp_ptr);
LIDT U64 [RAX]
}
U0 IntInit2()
{ //Interrupt descriptor table part2: Core 0 Only
I64 i;
PUSHFD
CLI
for (i=0;i<0x20;i++)
IntEntrySet(i,&sys_fault_handlers_code[10*i]);
/*
In theory, we use the PIC mask reg to insure we don't get
anything but keyboard, mouse and timer IRQs. In practice, I've
gotten IRQ 0x27, perhaps because I didn't initialize the APIC.
I go ahead and ACK PIC in $LK,"IntNop",A="MN:IntNop"$().
I have no idea why I got a IRQ 0x27.
*/
IntEntrySet(I_NMI,_SYS_HLT);
IntEntrySet(I_TIMER,SYS_TIMER_HANDLER);
IntEntrySet(I_MP_CRASH,*SYS_MP_CRASH_HANDLER_ADDR(U32 *));
IntEntrySet(I_WAKE,SYS_WAKE_HANDLER);
IntEntrySet(I_DBG,&sys_fault_handlers_code[10*I_DBG]);
POPFD
}
+252
View File
@@ -0,0 +1,252 @@
//This is run in a #exe{}.
U8 *kernel_cfg_options="MemInit\0HeapInit\0VarInit\0"
"NoMP\0TextMode\0GrMode\0DontProbe\0AutoMountIDE\0BootDrv\0Help\0";
#define CFG_MEM_INIT 0
#define CFG_HEAP_INIT 1
#define CFG_VAR_INIT 2
#define CFG_NO_MP 3
#define CFG_TEXT_MODE 4
#define CFG_GR_MODE 5
#define CFG_DONT_PROBE 6
#define CFG_AUTO_MOUNT_IDE 7
#define CFG_BOOT_DRV 8
#define CFG_NUM_OPTIONS 9
#define CFG_HELP 9
class CKernelCfg
{
I64 bios_gr_mode;
U8 *acct_name;
U8 *dsk_cache_size_exp;
CDoc *add_dev;
U8 *boot_drv_file,*boot_drv_start;
Bool opts[CFG_NUM_OPTIONS];
U8 mem_init_val,heap_init_val,var_init_val,
sys_acct_drv,auto_mount_ide_hd_let,auto_mount_ide_cd_let;
Bool cdrom_ports_pmt;
};
CDoc *KernelCfgAddDev(CKernelCfg *c)
{
I64 ch,num_hints,first_prt_num,type,unit,cnt=0;
U8 blks_buf[256],addr_buf[256],base0_buf[128],base1_buf[128];
CATARep *root=NULL,*tempha;
CDoc *doc=DocNew;
Bool make_free;
"\n\nIn anticipation of the drives you will\n"
"define shortly, enter the drive letter\n"
"of the drive with the account directory.\n"
"\n($$PURPLE$$<ENTER>$$FG$$ for cur drv) Acct Drv:";
ch=ToUpper(GetChar);
if ('A'<=ch<='Z')
c->sys_acct_drv=ch;
else
c->sys_acct_drv=Fs->cur_prt->drv_let;
"\n\n$$BK,1$$$$PURPLE$$Mount drives so they will be present when "
"you boot.$$FG$$$$BK,0$$\n";
do {
"\n****** Mount Drives ******\n"
"The first drive letter is the letter\n"
"of the first partition. If adding\n"
"a hard drive, you should pick 'C'.\n"
"If more than one partition is present\n"
"they will be lettered in sequence.\n"
"\nFirst Drive Letter ($$PURPLE$$<ENTER>$$FG$$ to exit):";
first_prt_num=ToUpper(GetChar)-'A';
NewLine;
if (0<=first_prt_num<NUM_PRTS) {
"\t$$PURPLE$$1$$FG$$=RAM\n\t$$PURPLE$$2$$FG$$=ATA(Harddisk)\n"
"\t$$PURPLE$$3$$FG$$=ATAPI(CD-ROM)\nType:";
type=GetChar-'0';
NewLine;
unit=0;
if (type==BDT_RAM) {
"Addr of RAM disk ($$PURPLE$$<ENTER>$$FG$$ to MAlloc):";
GetS(addr_buf,256);
"Blks of 512 bytes:";
GetS(blks_buf,256);
} else if (type==BDT_ATA ||
type==BDT_ATAPI) {
num_hints=ATARep(,,&root);
if (type==BDT_ATAPI) {
"<ENTER> to use booted CD-ROM\n";
if (num_hints)
"Enter dev number or\nport with $$PURPLE$$0x$$FG$$ prefix.\n"
"I/O Port Base0:\n";
else
"Include $$PURPLE$$0x$$FG$$ prefix.\nI/O Port Base0:\n";
GetS(base0_buf,128);
} else
do {
if (num_hints)
"Enter dev number or\nport with $$PURPLE$$0x$$FG$$ prefix.\n"
"I/O Port Base0:\n";
else
"Include $$PURPLE$$0x$$FG$$ prefix.\nI/O Port Base0:\n";
GetS(base0_buf,128);
} while (!A2I64(base0_buf));
if (1<=A2I64(base0_buf)<=num_hints) {
tempha=ATARepFind(root,A2I64(base0_buf));
SPrint(base0_buf,"0x%X",tempha->base0);
SPrint(base1_buf,"0x%X",tempha->base1);
unit=tempha->unit;
} else if (type!=BDT_ATAPI || *base0_buf) {
if (type==BDT_ATAPI)
StrCpy(base1_buf,"0");
else
do {
"I/O Port Base1:\n";
GetS(base1_buf,128);
} while (!A2I64(base1_buf));
do {
"\t$$PURPLE$$0$$FG$$=Master\n\t$$PURPLE$$1$$FG$$=Slave\nUnit:";
unit=GetChar-'0';
} while (!(0<=unit<=1));
NewLine;
}
LinkedLstDel(root);
}
if (BDT_NULL<type<BDT_NUM_TYPES && 0<=unit<=1) {
DocPrint(doc,"bdev=BlkDevNextFree(%d,%d);"
"bdev->unit=%d;",first_prt_num+'A',type,unit);
if (type==BDT_RAM) {
if (!*addr_buf) StrCpy(addr_buf,"0");
DocPrint(doc,"bdev->RAM_dsk=%s;",addr_buf);
DocPrint(doc,"bdev->max_blk=(%s)-1;",blks_buf);
}
make_free=FALSE;
if (type==BDT_ATA || type==BDT_ATAPI) {
if (type==BDT_ATAPI && !*base0_buf) {
c->cdrom_ports_pmt=TRUE;
DocPrint(doc,"boot_drv_pmt=PmtBaseUnit(bdev);");
if (first_prt_num+'A'==c->sys_acct_drv)
make_free=TRUE;
} else
DocPrint(doc,"bdev->base0=%s;bdev->base1=%s;",
base0_buf,base1_buf);
}
DocPrint(doc,"BlkDevAdd(bdev,FALSE,%d);",make_free);
cnt++;
} else
"\n\n$$BK,1$$$$RED$$Operation Failed$$BK,0$$$$FG$$\n\n";
}
} while (!cnt || 0<=first_prt_num<NUM_PRTS);
return doc;
}
U0 KernelCfgOptions(CKernelCfg *c)
{
I64 i;
U8 *st=NULL;
Bool state;
do {
Free(st);
for (i=0;i<CFG_NUM_OPTIONS;i++)
"$$PURPLE$$%13tz$$FG$$:%Z\n",i,kernel_cfg_options,c->opts[i],"ST_OFF_ON";
"\nType '$$PURPLE$$Help$$FG$$' for help.\n";
st=PmtStr("Option ($$PURPLE$$<ENTER>$$FG$$ when done):","");
i=LstMatch(st,kernel_cfg_options,LMF_IGNORE_CASE);
if (i==CFG_HELP)
"\n"
"$$PURPLE$$MemInit$$FG$$ Initializes memory above 0x100000 to a val at boot.\n"
"$$PURPLE$$HeapInit$$FG$$ Initializes MAlloc() memory to a val.\n"
"$$PURPLE$$VarInit$$FG$$ Initializes glbl var memory to a val.\n"
"$$PURPLE$$NoMP$$FG$$ No multicore.\n"
"$$PURPLE$$TextMode$$FG$$ Text Mode (requires hard reboot).\n"
"$$PURPLE$$GrMode$$FG$$ Graphics Mode (requires hard reboot).\n"
"$$PURPLE$$DontProbe$$FG$$ Just prompt CD-ROM ports, don't probe.\n"
"$$PURPLE$$AutoMountIDE$$FG$$ AutoMount IDE drives to 'C' and 'T'.\n"
"$$PURPLE$$BootDrv$$FG$$ Include RAM Drv in Kernel.BIN.\n"
"\n";
else
if (0<=i<CFG_NUM_OPTIONS) {
state=c->opts[i]=!c->opts[i];
switch (i) {
case CFG_MEM_INIT:
if (state)
c->mem_init_val=PmtI64("Val (0-255):",255,0,255);
break;
case CFG_HEAP_INIT:
if (state)
c->heap_init_val=PmtI64("Val (0-255):",255,0,255);
break;
case CFG_VAR_INIT:
if (state)
c->var_init_val=PmtI64("Val (0-255):",255,0,255);
break;
case CFG_GR_MODE:
if (state)
c->bios_gr_mode=PmtI64(
"0x12 640x480x4\n"
"0x6A 800x600x4\n\n"
"BIOS Graphic Mode (0x%0X):",c->bios_gr_mode);
break;
case CFG_AUTO_MOUNT_IDE:
if (state) {
"First HD Drive Let:";
c->auto_mount_ide_hd_let=ToUpper(GetChar);
if (!('A'<=c->auto_mount_ide_hd_let<='Z'))
c->auto_mount_ide_hd_let=0;
NewLine;
if (c->auto_mount_ide_hd_let)
"First HD Drive:%C\n",c->auto_mount_ide_hd_let;
else
"First HD Drive:%C\n",'C';
"First CD Drive Let:";
c->auto_mount_ide_cd_let=ToUpper(GetChar);
if (!('A'<=c->auto_mount_ide_cd_let<='Z'))
c->auto_mount_ide_cd_let=0;
NewLine;
if (c->auto_mount_ide_cd_let)
"First CD Drive:%C\n",c->auto_mount_ide_cd_let;
else
"First CD Drive:%C\n",'T';
} else {
c->auto_mount_ide_hd_let=0;
c->auto_mount_ide_cd_let=0;
}
break;
case CFG_BOOT_DRV:
Free(c->boot_drv_file);
c->boot_drv_file=0;
c->boot_drv_start=0;
if (state) {
c->boot_drv_file=PmtStr("Boot Drv File:");
c->boot_drv_start=PmtI64("Boot Drv Start:");
}
break;
}
}
} while (*st);
Free(st);
}
CKernelCfg *KernelCfgNew()
{
CKernelCfg *c=CAlloc(sizeof(CKernelCfg));
c->add_dev=KernelCfgAddDev(c);
c->acct_name=PmtStr("Start-up Acct ($$PURPLE$$<ENTER>$$FG$$ will prompt):");
c->dsk_cache_size_exp=PmtStr("Disk Cache Size in Bytes, gets rounded-up funny, ($$PURPLE$$<ENTER>$$FG$$ will use default of $$PURPLE$$%s$$FG$$ Bytes):",
"Scale2Mem(0x80000,0x8000000)");
c->bios_gr_mode=0x12; //0x12=640x480x4 0x6A=800x600x4
KernelCfgOptions(c);
return c;
}
U0 KernelCfgDel(CKernelCfg *c)
{
DocDel(c->add_dev);
Free(c->boot_drv_file);
Free(c->acct_name);
Free(c->dsk_cache_size_exp);
Free(c);
}
+248
View File
@@ -0,0 +1,248 @@
U0 SysGlblsInit()
{
I64 i,j;
U8 *m;
CRAXRBCRCXRDX ee;
CPUId(0x1,&ee);
sys_cache_line_width=ee.rbx.u8[1]*8;
QueInit(&sys_pci_dev_root);
sys_rnd_seed = 93186752^GetTSC;
sys_focus_task=Fs;
QueInit(&sys_macro_root);
sys_dft_iso_name="::/Temp/CDDVD.ISO";
MemSet(mp_apic_ids,0,MP_MAX_PROCESSORS*sizeof(U8));
InDbg(ON);
reverse_bits_table=CAlloc(256);
for (i=0;i<256;i++)
for (j=0;j<8;j++)
if (Bt(&i,7-j))
LBts(reverse_bits_table+i,j);
set_bits_table=CAlloc(256);
for (i=0;i<256;i++)
for (j=0;j<8;j++)
if (Bt(&i,j))
set_bits_table[i]++;
ext=CAlloc(EXT_NUM_ENTRIES*sizeof(U8 *));
fp_mgets=&SysMGetS;
fp_ctrl_alt_let_cbs=CAlloc(26*sizeof(U8 *));
ctrl_alt_let_descs=CAlloc(26*sizeof(U8 *));
ctrl_alt_let_in_irq_flags=0;
psect_cache=CAlloc(PSECT_CACHE_SIZE*sizeof(CPSectCache));
psect_cache_index=0;
StrCpy(sys_temp_filename,"HOME/Temp.TXT.Z");
MemSet(&sys_put_key_root,0,sizeof(CKeyDev));
QueInit(&sys_put_key_root);
KeyDevAdd(&KDInputFilterPutKey,&KDInputFilterPutS,0x40000000,FALSE);
KeyDevAdd(&KDRawDisplayPutKey,&KDRawDisplayPutS,0x60000000,FALSE);
#exe {
if (*kernel_cfg->acct_name)
StreamPrint("sys_acct=StrNew(\"%C:/Accts/%s\");",kernel_cfg->sys_acct_drv,kernel_cfg->acct_name);
else
StreamPrint("sys_acct=StrNew(\"%C:/Accts\");",kernel_cfg->sys_acct_drv);
StreamPrint("#exe{OptOff(OPTf_WARN_PAREN);}");
StreamPrint("DskCacheInit(%s);",kernel_cfg->dsk_cache_size_exp);
StreamPrint("#exe{OptOn(OPTf_WARN_PAREN);}");
};
pow10_I64=CAlloc(sizeof(F64)*(308+308+1));
for (i=-308;i<309;i++)
pow10_I64[i+309]=Pow10(i);
QueInit(&snd_record_root);
snd_record_root.freq=0;
snd_record_root.time_stamp=tS;
//$AN,"Independent Heap Ctrl Example",A="Independent Heap Ctrl Example"$
i=1; //Rqst 1 blk, we might get more.
m=MemBlksUncachedAlloc(&i,sys_code_bp);
sys_uncached_heap=HeapCtrlBPInit(m,i*0x200000/0x200);
ProgressBarsRst;
sys_fault_handlers_code=IntFaultHandlersNew;
}
U0 SysGrInit()
{
//See $LK,"SYS_BIOS_GR_MODE",A="FF:D:/Kernel/KStart.CPP,SYS_BIOS_GR_MODE:2"$
//See $LK,"GR_WIDTH",A="FF:::/Adam/Gr/GrGlbls.CPP.Z,GR_WIDTH"$
gr_font=sys_font_8x8;
if (bios_gr_mode==0x12 || bios_gr_mode==0x6A) {
text_mode=FALSE;
/*
Mode must be multiple of 32 wide
$LK,"GrUpdateLine32",A="MN:GrUpdateLine32"$().
*/
if (bios_gr_mode==0x6A) {
gr_width =800;
gr_height=600;
} else {
gr_width =640;
gr_height=480;
}
text_cols=gr_width/FONT_WIDTH;
text_rows=gr_height/FONT_HEIGHT;
OutU8(VGA_SC_INDEX,VGA_MAP_MASK);
OutU8(VGA_SC_DATA,0x0F);
MemSet(VGA_GRAPHIC_MEM_BASE,0,gr_width*gr_height>>3);
sys_raw_screen_image=CAlloc(gr_width*gr_height/8);
} else {
text_mode=TRUE;
gr_width =640;
gr_height=480;
text_cols=80;
text_rows=25;
MemSet(VGA_TEXT_MEM_BASE,0,text_rows*text_cols<<1);
}
}
U0 TimersInit()
{
I64 i,*_q;
U32 *_d;
OutU8(0x43,0x34);
OutU8(0x40,SYS_TIMER0_PERIOD);
OutU8(0x40,SYS_TIMER0_PERIOD>>8);
// High Precision Event Timer
if (PCIReadU16(0,31,0,0)==0x8086) { //Intel?
//D31 F0, cfg 0xF0=RCBA of PCI-LPC Bridge
_d=PCIReadU32(0,31,0,0xF0)(U8 *)&~0x3FFF+0x3404; //HPET cfg
//7 enable
//1:0 HPET is at 0xFED00000,0xFED01000, 0xFED02000 or 0xFED03000.
*_d=*_d&3|0x80;
}
_q=HPET_GCAP_ID;
i=*_q; //i.u32[1]= period in femtoS (10e-15)
if (100000<i.u32[1]<1000000000) {
HPET_freq =1000000000000000/i.u32[1];
HPET_kHz_freq=1000000000000/i.u32[1];
_q=HPET_GEN_CONF;
*_q|=1; //Enable counting
HPET_initial=HPET;
} else {
HPET_freq=0;
HPET_kHz_freq=0;
HPET_initial=0;
}
}
U0 Reboot()
{
U16 *_w=0x472;
CLI
if (mp_cnt>1)
MPHalt;
MemPagePresentMark(_w,TRUE);
*_w=0;
OutU8(0x70,0x8F);
OutU8(0x71,0x00);
OutU8(0x70,0x00);
OutU8(0x92,InU8(0x92)|1);
SysHlt;
}
U0 KernelMain()
{ //Continued from $LK,"Kernel",A="FF:::/Kernel/KStart.CPP,I32 &Kernel"$
adam_task=Fs;
HeapsInit;
LBts(&sys_run_level,RLf_FULL_HEAP);
Fs->hash_table=HashTableNew(ADAM_HASH_SIZE,Fs);
SysGlblsInit;
Mem32DevInit;
MemPagesNotPresentMark;
LoadKernel;
SysGrInit;
StrCpy(Fs->task_name,"Adam Task CPU#0");
StrCpy(Fs->task_title,Fs->task_name);
Fs->title_src=TTS_TASK_NAME;
Fs->win_right=text_cols-2;
Fs->win_top++;
TaskDerivedValsUpdate;
SysDefinesLoad;
MPInit;
IntInit1;
//Before this point use $LK,"Snd",A="MN:Snd"$() and $LK,"BusyWait",A="MN:BusyWait"$()
//to debug. After this point, use $LK,"RawPrint",A="MN:RawPrint"$()
LBts(&sys_run_level,RLf_RAW);
if (BIOSTotalMem<250*0x100000)
Dbg("Requires 256 Meg of RAM Memory");
TimersInit;
IntsInit;
"Enable IRQ's\n";
SetRFlags(SYS_NORMAL_RFLAGS);
BusyWait(2000);
IntInit2;
LBts(&sys_run_level,RLf_INTERRUPTS);
TimeStampFreqCal;
Preempt(ON);
#exe {
if (!kernel_cfg->opts[CFG_NO_MP])
StreamPrint("\"MultiCore Start\\n\\n\";"
"MPStart;");
};
LBts(&sys_run_level,RLf_MP);
KbdMouseVarsInit;
IPVarsInit;
KbdInit;
if (mp_cnt<2)
Spawn(&MouseDriverInstall);
else
Spawn(&MouseDriverInstall,,,1);
"BlkDevsInitAll\n";
BlkDevsInitAll;
"BlkDevsInitAll Done\n";
#exe {
if (kernel_cfg->cdrom_ports_pmt)
StreamPrint("if (boot_drv_pmt) \"%%S\",\"ST_CDROM_PORTS_PMT2\";");
};
ChgDsk(':');
LBts(&sys_run_level,RLf_DSK);
"Loading Compiler\n";
Cd("/Compiler");
Load("Compiler",LDF_SILENT);
LBts(&sys_run_level,RLf_COMPILER);
InDbg(OFF);
time_stamp_freq_initial=TimeStampFreqCal;
Cd("/Kernel");
try
ExeFile("Adam1"); //Continues $LK,"/Kernel/Adam1.CPP",A="FL:/Kernel/Adam1.CPP,1"$
catch {
Raw(ON);
PutExcept;
Dbg;
}
LBts(&sys_run_level,RLf_ADAM_SERVER);
SrvTaskCont; //Never to return
}
asm { ALIGN 16,OC_NOP
SYS_KERNEL_END::
#exe {
if (kernel_cfg->opts[CFG_BOOT_DRV]) {
StreamPrint("DU8 0x%X-(SYS_KERNEL_END-SYS_KERNEL_START1+0x7C10) DUP (0);"
"BINFILE \"%s\";",kernel_cfg->boot_drv_start,kernel_cfg->boot_drv_file);
}
};
}
+105
View File
@@ -0,0 +1,105 @@
/*
If you are sure a fun won't be called
before import is resolved, you can use
"import". Otherwise, use a fun pointer
var and check it before calling.
*/
import U0 MemberLstDel(CHashClass *tempc);
import I64 ExePrint(U8 *fmt,...);
import I64 ExeFile(U8 *name,Bool just_load=FALSE);
import Bool DocUnlock(CDoc *doc);
import Bool Ed(U8 *link_st,I64 ed_flags=0);
import I64 PopUp(U8 *msg,CTask *parent=NULL,CTask **_pu_task=NULL);
extern U0 throw(I64 ch=0,Bool no_log=FALSE);
extern U8 *FileNameAbs(U8 *name,I64 fuf_flags=0);
extern U8 *DftExt(U8 *name,U8 *extension);
extern Bool Cd(U8 *name,Bool make_dirs=FALSE);
extern Bool MkDir(U8 *filename);
extern U0 Msg(I64 code,I64 p1,I64 p2,I64 flags=0);
extern Bool BlkDevLock(CBlkDev *bdev);
extern Bool BlkDevUnlock(CBlkDev *bdev,Bool rst=FALSE);
extern Bool RBlks(CPrt *p,U8 *buf, I64 blk, I64 cnt);
extern Bool WBlks(CPrt *p,U8 *buf, I64 blk, I64 cnt);
extern U0 DskCacheInvalidate(CPrt *p);
extern Bool Drv(U8 drv_let);
extern U0 BlkDevsRelease();
extern U0 PrtsRelease();
extern CBlkDev *BlkDevNextFree(U8 first_drv_let,I64 type);
extern I64 BlkDevAdd(CBlkDev *bdev,Bool one_prt,Bool make_free);
extern Bool IsRaw();
extern U0 MPInt(I64 num,I64 cpu_num=1);
extern U0 XTalk(CTask *task,U8 *fmt,...);
extern Bool Suspend(CTask *task=NULL,Bool state=TRUE);
extern U0 SrvCmdDel(CSrvCmd *tempc);
extern U0 SrvCmdQueDel(CSrvCmd *root);
extern U0 SrvCtrlInit(CSrvCtrl *ctrl);
extern Bool TaskValidate(CTask *task);
extern U8 *FileExtRem(U8 *src,U8 *dst=NULL);
extern Bool IsDir(U8 *dir_name);
extern Bool FileFind(U8 *filename,CDirEntry *_de=NULL,I64 fuf_flags=0);
extern Bool ISOPrtInit(CPrt *p,I64 blk);
extern Bool ISO1FileFind(CPrt *p,I64 cur_dir_cluster,U8 *name,CDirEntry *_result,I64 fuf_flags=0);
extern CDirEntry *ISO1FilesFind(U8 *files_find_mask,I64 fuf_flags,CDirEntry *parent=NULL);
extern U0 RedSeaFSFreeFreeLst(CPrt *p);
extern U0 RedSeaFSPrtInit(CPrt *p);
extern U0 FAT32PrtInit(CPrt *p);
extern Bool RedSeaFSDrvValidate(U8 drv_let);
extern U0 RedSeaFSFmt(U8 drv_let,Bool quick=TRUE);
extern Bool RedSeaFSFileFind(CPrt *p,I64 cur_dir_cluster,U8 *name,CDirEntry *_result,I64 fuf_flags=0);
extern Bool FAT32FileFind(CPrt *p,I64 cur_dir_cluster,U8 *name,CDirEntry *_result,I64 fuf_flags=0);
extern U8 *FileRead(U8 *filename,I64 *_size=NULL,I64 *_attr=NULL,Bool raw=FALSE);
extern I64 RedSeaFSAllocClusters(CPrt *p,I64 cnt);
extern I64 FAT32AllocClusters(CPrt *p,I64 c,I64 cnt);
extern I64 FAT32AllocContiguousClusters(CPrt *p,I64 cnt);
extern Bool RedSeaFSDirNew(CPrt *p,U8 *cur_dir,CDirEntry *tempdee,Bool free_old_chain);
extern Bool FAT32DirNew(CPrt *p,U8 *cur_dir,CDirEntry *tempdee,Bool free_old_chain);
extern CDirEntry *RedSeaFSFilesFind (U8 *files_find_mask,I64 fuf_flags,CDirEntry *parent=NULL);
extern CDirEntry *FAT32FilesFind(U8 *files_find_mask,I64 fuf_flags,CDirEntry *parent=NULL,I64 *_dir_size=NULL);
extern I64 FileWrite(U8 *filename,U8 *fbuf,
I64 size,CDate cdt=0,I64 attr=0,Bool raw=FALSE);
extern U0 Exit();
extern U0 AdamLog(U8 *fmt,...);
extern U0 Dbg(U8 *msg=NULL,I64 msg_num=0);
extern Bool BptS(U8 *addr,CTask *task=NULL,Bool live=TRUE);
extern U0 DbgHelp();
extern U8 *Caller(I64 num=1);
extern CTask *SpawnQue(U0 (*fp_addr)(U8 *data),U8 *data=NULL,
U8 *task_name=NULL,
I64 target_cpu,
CTask *parent=NULL, //NULL means adam
I64 stk_size=0,I64 flags=1<<SVCf_ADD_TO_QUE);
extern CTask *SpawnUser(U8 *fmt=NULL,...);
extern U0 TaskRstAwaitingMsg(CTask *task=NULL);
extern CSrvCmd *TaskMsg(CTask *_srv,CTask *master,
I64 code,I64 p1,I64 p2,I64 flags);
extern U0 TaskWait(CTask *task=NULL);
extern I64 SrvCmdsHandler(CTask *task=NULL);
extern U0 Print(U8 *fmt,...);
extern U8 *SPrint(U8 *dst,U8 *fmt,...);
extern U8 *MPrint(U8 *fmt,...);
extern U8 *Define(U8 *name);
extern U8 *DefineSub(I64 sub,U8 *name);
extern I64 DefineMatch(U8 *needle,U8 *haystack_lst_name,I64 flags=0);
extern U0 PutS(U8 *st); //Use $LK,"Print",A="MN:Print"$()
extern U0 PutChars(U64 ch);
extern I64 GetChar(I64 *scancode=NULL,Bool echo=TRUE,Bool raw_cursor=FALSE);
extern Bool IsDbg();
extern I64 FlushMsgs(CTask *task=NULL);
extern U0 SetMouseIP(I64 x,I64 y,I64 z,I64 l,I64 r,I64 c);
extern U0 SPrintPSect(U8 *buf,I64 addr,I64 field_len);
extern U8 *CatPrint(U8 *dst,U8 *fmt,...);
extern I64 GetS(U8 *buf,I64 size,Bool allow_ext=TRUE);
extern U0 UserTaskCont();
#exe {
OptOn(OPTf_KEEP_PRIVATE);
OptOn(OPTf_EXTERNS_TO_IMPORTS);
};
#include "/Compiler/Cmp.HPP"
#exe {
OptOff(OPTf_EXTERNS_TO_IMPORTS);
OptOff(OPTf_KEEP_PRIVATE);
};
+132
View File
@@ -0,0 +1,132 @@
U8 sys_temp_filename[136];
CSrvCmd sys_macro_root;
CKeyDev sys_put_key_root;
CTask *sys_macro_util_task=NULL,
*sys_dbg_focus_task=NULL;
U8 *sys_dbg_msg=NULL;
I64 sys_dbg_msg_num=0;
CMPCrash *mp_crash=NULL;
U8 mp_apic_ids[MP_MAX_PROCESSORS];
I64 *sys_idt=NULL;
CTask *adam_task;
I64 sys_num_spawned_tasks=0;
U8 *sys_fault_handlers_code;
CCacheBlk *sys_dsk_cache_base=NULL,*sys_dsk_cache_ctrl=NULL;
CCacheBlk **sys_dsk_cache_hash_table=NULL;
I64 sys_dsk_cache_size;
I64 sys_raw_col=0,sys_raw_flags=0;
U8 *sys_raw_screen_image;
Bool text_mode;
I64 text_rows,text_cols, //Use TEXT_ROWS,TEXT_COLS
gr_width,gr_height; //Use GR_WIDTH,GR_HEIGHT
U8 *gr_font;
U8 *sys_fix_file_line=NULL;
CTask *sys_winmgr_task=NULL,
*sys_task_being_screen_updated=NULL;
I64 sys_rnd_seed;
CDoc *sys_clipboard_doc;
U8 *sys_dft_iso_name;
I64 sys_dsk_reads,sys_dsk_writes;
CBlkDev *sys_blkdevs;
CPrt *sys_prts;
I64 sys_auto_mount_ide_cnt=0;
#exe {
if (!kernel_cfg->auto_mount_ide_hd_let)
kernel_cfg->auto_mount_ide_hd_let='C';
if (!kernel_cfg->auto_mount_ide_cd_let)
kernel_cfg->auto_mount_ide_cd_let='T';
StreamPrint("U8 sys_first_hd_drv_let=%d,sys_first_cd_drv_let=%d;",
kernel_cfg->auto_mount_ide_hd_let,kernel_cfg->auto_mount_ide_cd_let);
}
Bool boot_drv_pmt=FALSE,cdrom_boot_is_good=TRUE;
CPrt *drv_to_prt[32];
U8 *sys_acct;
U8 *reverse_bits_table,*set_bits_table;
U0 (**fp_ctrl_alt_let_cbs)(I64 sc);
I64 ctrl_alt_let_in_irq_flags;
I64 **ctrl_alt_let_ret_addr; //addr of ret addr on stack in kbd irq
U8 **ctrl_alt_let_descs;
CDate local_time_offset=0;
Bool time_stamp_freq_calibrated=FALSE;
I64 HPET_freq=0,HPET_kHz_freq=0,HPET_initial=0,
time_stamp_freq=2676302000,
time_stamp_kHz_freq=2676302,
time_stamp_freq_initial=2676302000,
mouse_evt_time=0,kbd_evt_time=0,mouse_pkt_size=3;
I64 sys_cur_scan_code=0;
U8 key_desc[128];
Bool kbd_irqs_working;
U8 *key_handler;
CPCIDev sys_pci_dev_root;
CMemRange sys_mem32_dev_root;
U8 *sys_mem64_dev_ptr=MEM_MAPPED_SPACE;
F64 snd_freq=0;
Bool snd_record=FALSE;
F64 *pow10_I64;
CHeapCtrl *sys_uncached_heap;
I64 ipx,ipy,ipz,ip_throttle,ip_throttle_step; //Throttle is [MIN_I32,MAX_I32]
I64 ipx_presnap,ipy_presnap,ipz_presnap;
I64 ipx_offset,ipy_offset,ipz_offset;
F64 ipx_scale,ipy_scale,ipz_scale;
F64 ip_speed;
I64 ip_dev;
I64 iptx,ipty;
Bool ip_on, //Show or hide cursor
ip_lb_last,ip_cb_last,ip_rb_last,
ip_lb,ip_cb,ip_rb;
Bool ip_has_wheel;
F64 ip_last_move_time;
CGrid ip_grid;
F64 mxx_scale,myy_scale,mzz_scale;
//These are the coordinates before
//they get scaled.
I64 mxx_prescale,myy_prescale,mzz_prescale;
I64 mxx,myy,mzz;
F64 mouse_speed;
I64 old_mxx,old_myy,old_mzz;
Bool mouse_buttons[5];
Bool mouse_has_wheel,
mouse_has_ext_buttons,
mouse_evt,
mouse_installed,
mouse_install_attempt_in_progress,
kbdmouse_rst,
mouse_irqs_working;
CFifoI64 *scan_code_fifo;
CFifoU8 *kbd_fifo,*kbd2_fifo,
*mouse_fifo,*mouse2_fifo;
I64 sys_key_cnt,
sys_last_down_scan_code,
mouse_install_attempts,
mouse_last_evt_time;
//BitTest, $LK,"Bt",A="MN:Bt"$(), with a merged scan code.
//(Left and right shift merged, for example.)
U32 key_down_bitmap[8];
//BitTest, $LK,"Bt",A="MN:Bt"$(), with an unmerged scan code.
U32 key_down_bitmap2[8];
CSndData snd_record_root;
U8 *(*fp_mgets)(I64 flags=0)=NULL;
U0 (*fp_update_ctrls)(CTask *task)=NULL;
CDoc *(*fp_doc_put)(CTask *task=NULL)=NULL;
U0 (*fp_set_std_palette)()=NULL;
CPSectCache *psect_cache;
I64 psect_cache_index;
+442
View File
@@ -0,0 +1,442 @@
asm {/*
See $LK,"::/Doc/Boot.TXT"$ for how booting works.
This file calls some BIOS routines before
switching to 32 bit, and then, 64 bit modes.
It continues here: $LK,"Kernel",A="FF:::/Kernel/KEnd.CPP,U0 Kernel"$.
The boot loader jumps here, in real-mode (16-bit).
It actually jumps to the $LK,"CBinFile",A="MN:CBinFile"$ which is placed
just before this $LK,"generated by the compiler",A="FF:::/Compiler/CmpMain.CPP,16 ALIGN"$.
The header begins with a short jmp to
the start of this file's code which begins
with the following small jump past some data.
This file is first in the Kernel image
because it is #included first. $LK,"Kernel.PRJ",A="FF:::/Kernel/Kernel.PRJ,KStart:1"$
*/
USE16
SYS_KERNEL_START1:: //This must match $LK,"CKernel",A="MN:CKernel"$.
JMP U16 SYS_KERNEL_START2
// ************************************
// ASM Global vars required for 16-bit start-up
ALIGN 4,OC_NOP
SYS_BOOT_BASE:: DU32 0; //Fixed offset from start used by reboot
SYS_BOOT_PATCH_TABLE_BASE:: DU32 0;
#exe {StreamPrint("SYS_COMPILE_TIME:: DU64 0x%X;",Now);}
//See $LK,"BootCdProbe",A="MN:BootCdProbe"$
#assert SYS_COMPILE_TIME+8+16<CD_BLK_SIZE
SYS_OS_32START:: DU32 SYS_INIT_OS;
SYS_BOOT_CODE:: DU32 0xFF;
SYS_MEM_E801:: DU16 0,0;
SYS_MEM_E820:: DU8 MEM_NUM_E820_ENTRIES*MEM_E820_ENTRY_SIZE DUP (0);
ALIGN 16,OC_NOP
SYS_GDT:: //See $LK,"CGDT",A="MN:CGDT"$
GDT_NULL: DU64 0,0;
GDT_BOOT_DS: DU64 0,0; //Gets filled-in
GDT_BOOT_CS: DU64 0,0; //Gets filled-in
GDT_CS32: DU64 0x00CF9A000000FFFF,0;
GDT_CS64: DU64 0x00209A0000000000,0; //The $LK,"Charter",A="FI:::/Doc/Charter.TXT"$ says just ring0.
GDT_CS64_RING3: DU64 0x0020FA0000000000,0; //$LK,"Ring3",A="FI:::/Demo/Lectures/Ring3.CPP"$, in case you want to play around.
GDT_DS: DU64 0x00CF92000000FFFF,0;
GDT_DS_RING3: DU64 0x00CFF2000000FFFF,0;
GDT_TR: DU8 MP_MAX_PROCESSORS*16 DUP(0);
GDT_TR_RING3: DU8 MP_MAX_PROCESSORS*16 DUP(0);
#assert $$-SYS_GDT==sizeof(CGDT)
SYS_BIOS_GR_MODE:: DU16 0;
SYS_PCI_BUSSES:: DU16 0;
#assert $$-SYS_KERNEL_START1==sizeof(CKernel)-sizeof(CBinFile)
SYS_RUN_LEVEL:: DU32 0;
SYS_TEMP_PTR:: DU16 0;
DU64 0;
// ************************************
//EBX is SYS_BOOT_CODE (val passed from boot blk)
SYS_KERNEL_START2::
MOV AX,(BOOT_RAM_LIMIT-BOOT_STK_SIZE)/16
MOV SS,AX
MOV SP,BOOT_STK_SIZE
PUSH EBX //will be SYS_BOOT_CODE
MOV AX,VGA_TEXT_MEM_BASE/16
MOV ES,AX
MOV U32 ES:[0],'O'+BLUE<<12+('S'+GREEN<<12)<<16
CALL U16 GET_IP
GET_IP: POP BX
SUB BX,GET_IP
SHR BX,4
MOV AX,CS
ADD AX,BX
PUSH AX
PUSH U16 TEMPLEOS_CONT_START
RETF
TEMPLEOS_CONT_START:
STI
MOV AX,CS
MOV DS,AX
MOV U32 [SYS_RUN_LEVEL],RLF_16BIT
#exe {StreamPrint("MOV BX,%d\n",kernel_cfg->bios_gr_mode);};
MOV U16 [SYS_BIOS_GR_MODE],BX
MOV AX,0x4F02
#exe {
if (!kernel_cfg->opts[CFG_TEXT_MODE])
StreamPrint("INT 0x10"); //Enable VGA
};
CMP AX,0x004F
JE @@10
MOV U16 [SYS_BIOS_GR_MODE],0 //failed
@@10:
/**** This doesn't help
//Enable mouse
MOV AX,0xC200 //Enable
MOV BX,0x0100
INT 0x15
MOV AX,0xC201 //Rst
INT 0x15
MOV AX,0xC200 //Enable
MOV BX,0x0100
INT 0x15
MOV AX,0xC202 //Sample
MOV BX,0x0500 //100
INT 0x15
MOV AX,0xC203 //Resolution
MOV BX,0x0300 //8 per mm
INT 0x15
MOV AX,0xC205 //pkt size
MOV BX,0x0300
INT 0x15
MOV AX,0xC200 //Enable
MOV BX,0x0100
INT 0x15
****/
//Get mem maps
MOV AX,0xE801
INT 0x15
MOV U16 [SYS_MEM_E801],CX
MOV U16 [SYS_MEM_E801+2],DX
MOV CX,MEM_NUM_E820_ENTRIES-1 //Leave one to terminate
XOR EBX,EBX
MOV AX,DS
MOV ES,AX
MOV DI,SYS_MEM_E820
@@15: PUSH CX
MOV EAX,0xE820
MOV ECX,MEM_E820_ENTRY_SIZE
MOV EDX,'PAMS'
INT 0x15
JC @@20
CMP EAX,'PAMS'
JNE @@20
TEST EBX,EBX
JZ @@20
ADD DI,MEM_E820_ENTRY_SIZE
POP CX
LOOP @@15
JMP @@25
@@20: ADD SP,2
//Get PCI Bus Info
@@25: MOV U16 [SYS_PCI_BUSSES],256
XOR DX,DX
MOV AX,0xB101
INT 0x1A
CMP DX,'PC'
JNE @@30
MOV CH,0
INC CX
MOV U16 [SYS_PCI_BUSSES],CX
@@30:
CLI
//Enable A20
IN AL,0x92
OR AL,2
OUT 0x92,AL
CLD //Start with known regs
MOV AX,CS
MOV DS,AX
MOV ES,AX
MOV FS,AX
MOV GS,AX
XOR EAX,EAX
XOR EBX,EBX
XOR ECX,ECX
XOR EDX,EDX
XOR ESI,ESI
XOR EDI,EDI
XOR EBP,EBP
XOR EAX,EAX
MOV AX,CS
SHL EAX,4
MOV U32 [SYS_BOOT_BASE],EAX
POP U32 [SYS_BOOT_CODE]
MOV BX,CS
DEC BX
#assert sizeof(CBinFile)==16
MOV GS,BX
MOV EBX,U32 GS:[CBinFile.loader_patch_table_offset]
ADD EAX,EBX
SUB EAX,16
MOV U32 [SYS_BOOT_PATCH_TABLE_BASE],EAX
MOV U32 [GDT_BOOT_DS],0x0000FFFF
MOV U32 [GDT_BOOT_DS+4],0x0CF9200
MOV U32 [GDT_BOOT_CS],0x0000FFFF
MOV U32 [GDT_BOOT_CS+4],0x0CF9A00
MOV EAX,U32 [SYS_BOOT_BASE]
ADD U32 [GDT_BOOT_DS+2],EAX
ADD U32 [GDT_BOOT_CS+2],EAX
// Set-up ptr to limit and base
//of GDT.
MOV U16 [SYS_TEMP_PTR],sizeof(CGDT)-1
MOV EAX,U32 [SYS_BOOT_BASE]
ADD EAX,SYS_GDT
MOV U32 [SYS_TEMP_PTR+2],EAX
MOV U16 [SYS_TEMP_PTR+6],0
LGDT U32 [SYS_TEMP_PTR]
MOV EAX,SYS_START_CR0
MOV_CR0_EAX
/*
The assembler doesn't support far jumps so we hand code it.
16-bit code is not important enough for me to implement
16-bit mode in the assembler fully.
To complete the switch to 32-bit mode, we have to load
the code segment with a far jump.
*/
DU8 0x66,0xEA; //JMP CGDT.boot_cs:SYS_INIT_OS
DU32 SYS_INIT_OS;
DU16 CGDT.boot_cs;
#assert $$+16<=0xFFFF
USE32
// ************************************
// ASM Global vars not required for 16-bit start-up
ALIGN 8,OC_NOP
SYS_HEAP_BASE:: DU64 SYS_FIXED_AREA+sizeof(CSysFixedArea);
SYS_HEAP_LIMIT:: DU64 0;
#exe {
StreamPrint(
"SYS_MEM_INIT_FLAG:: DU8 %d;"
"SYS_MEM_INIT_VAL:: DU8 %d;"
"SYS_HEAP_INIT_FLAG:: DU8 %d;"
"SYS_HEAP_INIT_VAL:: DU8 %d;"
"SYS_VAR_INIT_FLAG:: DU8 %d;"
"SYS_VAR_INIT_VAL:: DU8 %d;",
kernel_cfg->opts[CFG_MEM_INIT], kernel_cfg->mem_init_val,
kernel_cfg->opts[CFG_HEAP_INIT],kernel_cfg->heap_init_val,
kernel_cfg->opts[CFG_VAR_INIT], kernel_cfg->var_init_val);
};
SYS_HEAP_DBG_FLAG:: DU8 _CFG_HEAP_DBG;
ALIGN 8,0
SYS_CTRL_ALT_FLAGS:: DU64 0;
SYS_EXTERN_TABLE:: DU64 0;
SYS_CODE_BP:: DU64 0;
SYS_DATA_BP:: DU64 0;
SYS_PROGRESSES::
SYS_PROGRESS1:: DU64 0;
SYS_PROGRESS1_MAX:: DU64 0;
SYS_PROGRESS1_DESC:: DU8 PROGRESS_DESC_LEN+1 DUP(0);
SYS_PROGRESS2:: DU64 0;
SYS_PROGRESS2_MAX:: DU64 0;
SYS_PROGRESS2_DESC:: DU8 PROGRESS_DESC_LEN+1 DUP(0);
SYS_PROGRESS3:: DU64 0;
SYS_PROGRESS3_MAX:: DU64 0;
SYS_PROGRESS3_DESC:: DU8 PROGRESS_DESC_LEN+1 DUP(0);
SYS_PROGRESS4:: DU64 0;
SYS_PROGRESS4_MAX:: DU64 0;
SYS_PROGRESS4_DESC:: DU8 PROGRESS_DESC_LEN+1 DUP(0);
#assert $$-SYS_PROGRESSES==sizeof(CProgress)*4
SYS_FOCUS_TASK:: DU64 0;
SYS_TIMER:: DU64 0;
SYS_JIFFIES:: DU64 1;
SYS_CPU_STRUCTS:: DU64 0;
SYS_MP_CNT:: DU64 1;
SYS_MP_CNT_INITIAL:: DU64 1;
SYS_MP_CNT_LOCK:: DU64 1;
ALIGN DFT_CACHE_LINE_WIDTH,OC_NOP
SYS_CACHE_LINE_WIDTH:: DU64 DFT_CACHE_LINE_WIDTH;
DU8 DFT_CACHE_LINE_WIDTH-sizeof(CBinFile)-8 DUP(0);
SYS_SEMAS:: DU8 NUM_SYS_SEMAS*SEMA_STRUCT_SIZE DUP(0);
// ************************************
ALIGN 16,OC_NOP
SYS_INIT_OS:: //Entry point for RAM reboots.
PUSH U32 SYS_START_RFLAGS
POPFD
MOV EAX,SYS_START_CR0
MOV_CR0_EAX
MOV AX,CGDT.boot_ds //LOAD DS SELECTOR
MOV DS,AX
MOV ES,AX
MOV EAX,U32 [SYS_RUN_LEVEL]
AND EAX,RLF_16BIT
OR EAX,RLF_32BIT
MOV U32 [SYS_RUN_LEVEL],EAX
//Patch abs addresses
MOV ESI,U32 [SYS_BOOT_PATCH_TABLE_BASE]
MOV EDI,U32 [SYS_BOOT_BASE]
MOV AX,CGDT.ds
MOV DS,AX
MOV ES,AX
MOV ECX,U32 CBinFilePatchTableWithoutOrg.abs_addres_cnt[ESI]
LEA ESI,U32 CBinFilePatchTableWithoutOrg.abs_addres[ESI]
@@05: LODSD
ADD EAX,EDI
ADD U32 [EAX],EDI
LOOP @@05
MOV AX,CGDT.ds
MOV DS,AX
MOV ES,AX
MOV FS,AX
MOV GS,AX
MOV SS,AX
MOV ESP,BOOT_RAM_LIMIT //Temp Stk
DU8 0xEA; //JMP CGDT.cs32:SYS_CONT_INIT_OS
DU32 SYS_CONT_INIT_OS;
DU16 CGDT.cs32;
SYS_CONT_INIT_OS::
LOCK
BTS U32 [SYS_RUN_LEVEL],RLf_PATCHED
CALL SYS_FIND_BIOS32_SERVICE_DIR
CALL SYS_FIND_PCI_SERVICES
MOV U32 [SYS_HEAP_BASE],SYS_FIXED_AREA+sizeof(CSysFixedArea)
CALL SYS_INIT_MEM
PUSH U32 0
CALL INIT_EM64T
USE64
LOCK
BTS U32 [SYS_RUN_LEVEL],RLf_64BIT
FNINIT
MOV RAX,SYS_FIXED_AREA+CSysFixedArea.init_fpu_mmx
FXSAVE U64 [RAX]
//Init CPU0 Struct
PUSH SYS_FIXED_AREA+CSysFixedArea.adam
PUSH SYS_FIXED_AREA+CSysFixedArea.boot_cpu
PUSH 0
CALL &CPUStructInit
CALL SET_GS_BASE
//Init Adam heap ctrl
MOV EDI,U32 SYS_FIXED_AREA+CSysFixedArea.adam_hc
MOV EAX,U32 SYS_FIXED_AREA+CSysFixedArea.adam_bp
MOV U64 CHeapCtrl.bp[RDI],RAX
MOV U32 CHeapCtrl.hc_signature[RDI],HEAP_CTRL_SIGNATURE_VAL
LEA RAX,U64 CHeapCtrl.next_um-CMemUsedAllocated.next[RDI]
MOV U64 CHeapCtrl.next_um[RDI],RAX
MOV U64 CHeapCtrl.last_um[RDI],RAX
MOV EAX,U32 SYS_FIXED_AREA+CSysFixedArea.adam
MOV U64 CHeapCtrl.mem_task[RDI],RAX
MOV U64 CTask.code_heap[RAX],RDI
MOV U64 CTask.data_heap[RAX],RDI
MOV U32 CTask.task_signature[RAX],TASK_SIGNATURE_VAL
MOV U32 CTask.task_in_que_signature[RAX],TASK_IN_QUE_SIGNATURE_VAL
LOCK
BTS U32 [SYS_RUN_LEVEL],RLf_BOOT_HEAP
PUSH ADAM_STK
PUSH U32 SYS_FIXED_AREA+CSysFixedArea.adam
CALL &TaskInit
CALL SET_FS_BASE
MOV RSP,U64 CTask.rsp[RAX]
JMP I32 &KernelMain
// ************************************
USE32
INIT_EM64T:
MOV_EAX_CR4
OR EAX,0xB0
MOV_CR4_EAX
MOV EAX,SYS_FIXED_AREA+CSysFixedArea.pml4
MOV_CR3_EAX
MOV ECX,IA32_EFER
XOR EDX,EDX
MOV EAX,IA32F_LME
WRMSR
MOV_EAX_CR0
BTS EAX,31 //enable paging (required for 64-bit mode)
MOV_CR0_EAX
DU8 0xEA; //JMP CGDT.cs64:EM64T_PART3
DU32 EM64T_PART3;
DU16 CGDT.cs64;
USE64
EM64T_PART3:
RET
// ************************************
SYS_RESTART_KERNEL::
XOR RDI,RDI
MOV EDI,U32 SYS_BOOT_BASE
MOV EDI,U32 [RDI]
XOR RSI,RSI
MOV ESI,U32 SYS_OS_32START
MOV ESI,U32 [RSI]
ADD ESI,EDI
PUSH U32 CGDT.ds //stk seg
PUSH U32 BOOT_RAM_LIMIT //stk
PUSH U32 0 //flags
PUSH U32 CGDT.cs32
LEA RAX,[@@10]
PUSH RAX
IRET
USE32
@@10:
WBINVD
//disable paging
MOV_EAX_CR0
BTR EAX,31
MOV_CR0_EAX
MOV ECX,IA32_EFER
XOR EDX,EDX
XOR EAX,EAX
WRMSR
MOV EBX,BOOT_CODE_RAM
JMP ESI
USE64
SYS_RESTART_KERNEL_END::
}
+99
View File
@@ -0,0 +1,99 @@
U0 GridInit()
{
ip_grid.x=ip_grid.y=ip_grid.z=8;
ip_grid.x_offset=ip_grid.y_offset=ip_grid.z_offset=0;
ip_grid.x_speed =ip_grid.y_speed =ip_grid.z_speed =1;
ip_grid.show=ip_grid.snap=FALSE;
}
U0 IPVarsUpdate(I64 x,I64 y,I64 z,Bool l,Bool c,Bool r)
{
ipx_presnap=ToI64(ipx_scale*x)+ipx_offset;
ipy_presnap=ToI64(ipy_scale*y)+ipy_offset;
ipz_presnap=ToI64(ipz_scale*z)+ipz_offset;
if (ip_grid.snap) {
ipx=Trunc(ipx_presnap/ip_grid.x)*ip_grid.x+ip_grid.x_offset;
ipy=Trunc(ipy_presnap/ip_grid.y)*ip_grid.y+ip_grid.y_offset;
ipz=Trunc(ipz_presnap/ip_grid.z)*ip_grid.z+ip_grid.z_offset;
} else {
ipx=ipx_presnap;
ipy=ipy_presnap;
ipz=ipz_presnap;
}
ipx=ClampI64(ipx,0,gr_width-1);
ipy=ClampI64(ipy,0,gr_height-1);
ip_throttle=ClampI64(ip_throttle,MIN_I32,MAX_I32);
iptx=ipx/FONT_WIDTH;
if (iptx>=text_cols) {
iptx=text_cols-1;
ipx=text_cols*FONT_WIDTH-1;
}
ipty=ipy/FONT_HEIGHT;
if (ipty>=text_rows) {
ipty=text_rows-1;
ipy=text_rows*FONT_HEIGHT-1;
}
ip_lb=l;
ip_cb=c;
ip_rb=r;
LBEqu(&sys_cur_scan_code,SCf_IP_L_DOWN,ip_lb);
LBEqu(&sys_cur_scan_code,SCf_IP_R_DOWN,ip_rb);
}
U0 SetIP(I64 x=MAX_I64,I64 y=MAX_I64,I64 z=MAX_I64,I64 l=MAX_I64,I64 r=MAX_I64,I64 c=MAX_I64)
{ //Note: Generates a message.
Bool old_preempt=Preempt(OFF);
if (!(0<=x<gr_width))
x=ipx;
if (!(0<=y<gr_height))
y=ipy;
if (z==MAX_I64)
z=ipz;
if (!(FALSE<=l<=TRUE))
l=ip_lb;
if (!(FALSE<=c<=TRUE))
c=ip_cb;
if (!(FALSE<=r<=TRUE))
r=ip_rb;
x=(x-ipx_offset)/ipx_scale;
y=(y-ipy_offset)/ipy_scale;
z=(z-ipz_offset)/ipz_scale;
IPVarsUpdate(x,y,z,l,c,r);
switch (ip_dev) {
case IP_MOUSE:
SetMouseIP(x,y,z,l,c,r);
break;
}
Preempt(old_preempt);
}
U0 IPVarsInit()
{
ipx=0;
ipy=0;
ipz=0;
ip_throttle=0;
ip_throttle_step=(MAX_I32+1)>>3;
ipx_offset=0;
ipy_offset=0;
ipz_offset=0;
ipx_scale=1.0;
ipy_scale=1.0;
ipz_scale=1.0;
ip_speed=0;
ip_dev=IP_NULL;
iptx=ipx/FONT_WIDTH;
ipty=ipy/FONT_HEIGHT;
ip_on=TRUE;
ip_lb_last=FALSE;
ip_rb_last=FALSE;
ip_lb=FALSE;
ip_cb=FALSE;
ip_rb=FALSE;
ip_has_wheel=FALSE;
ip_last_move_time=tS;
GridInit;
}
+518
View File
@@ -0,0 +1,518 @@
asm {
NORMAL_KEY_SCAN_DECODE_TABLE::
DU8 0,CH_ESC,"1234567890-=",CH_BACKSPACE,'\t';
DU8 "qwertyuiop[]",'\n',0,"as";
DU8 "dfghjkl;'\`",0,"\\zxcv";
DU8 "bnm,./",0,'*',0,CH_SPACE,0,0,0,0,0,0;
DU8 0,0,0,0,0,0,0,0,0,0,'-',0,0,0,'+',0;
SHIFT_KEY_SCAN_DECODE_TABLE::
DU8 0,CH_SHIFT_ESC,"!@#$$%^&*()_+",CH_BACKSPACE,'\t';
DU8 "QWERTYUIOP{}",'\n',0,"AS";
DU8 "DFGHJKL:\"~",0,"|ZXCV";
DU8 "BNM<>?",0,'*',0,CH_SHIFT_SPACE,0,0,0,0,0,0;
DU8 0,0,0,0,0,0,0,0,0,0,'-',0,0,0,'+',0;
CTRL_KEY_SCAN_DECODE_TABLE::
DU8 0,CH_ESC,"1234567890-=",CH_BACKSPACE,'\t';
DU8 CH_CTRLQ,CH_CTRLW,CH_CTRLE,CH_CTRLR,CH_CTRLT,CH_CTRLY,CH_CTRLU,CH_CTRLI,CH_CTRLO,CH_CTRLP,"[]",'\n',0,CH_CTRLA,CH_CTRLS;
DU8 CH_CTRLD,CH_CTRLF,CH_CTRLG,CH_CTRLH,CH_CTRLJ,CH_CTRLK,CH_CTRLL,";'\`",0,"\\",CH_CTRLZ,CH_CTRLX,CH_CTRLC,CH_CTRLV;
DU8 CH_CTRLB,CH_CTRLN,CH_CTRLM,",./",0,'*',0,CH_SPACE,0,0,0,0,0,0;
DU8 0,0,0,0,0,0,0,0,0,0,'-',0,0,0,'+',0;
}
U0 KbdCmdSend(I64 port, U8 val)
{
F64 timeout=tS+0.125;
while (tS<timeout) {
if (!(InU8(KBD_CTRL)&2)) {
OutU8(port,val);
return;
}
}
throw;
}
I64 KbdCmdRead()
{
F64 timeout=tS+0.125;
while (tS<timeout)
if (InU8(KBD_CTRL)&1)
return InU8(KBD_PORT);
throw;
}
U0 KbdCmdFlush()
{
F64 timeout=tS+0.03;
while (tS<timeout)
InU8(KBD_PORT);
}
U0 KbdSetLEDs(I64 sc)
{
Bool old_preempt=Preempt(OFF);
U8 v=0;
BEqu(&v,0,Bt(&sc,SCf_SCROLL));
BEqu(&v,1,Bt(&sc,SCf_NUM));
BEqu(&v,2,Bt(&sc,SCf_CAPS));
try {
KbdCmdSend(KBD_PORT,0xED);
KbdCmdSend(KBD_PORT,v);
} catch
Fs->catch_except=TRUE;
Preempt(old_preempt);
}
U0 KbdMouseCmdAck(U8 val)
{
I64 ack,timeout=5;
do {
ack=0;
try {
KbdCmdSend(KBD_CTRL,0xD4);
KbdCmdSend(KBD_PORT,val);
ack=KbdCmdRead;
} catch {
KbdCmdFlush;
Fs->catch_except=TRUE;
}
} while (ack!=0xFA && --timeout);
if (!timeout)
throw;
}
U0 SetTypeMatic(U8 delay)
{
try {
KbdCmdSend(KBD_CTRL,0xA7); //Disable Mouse
KbdCmdSend(KBD_CTRL,0xAE); //Enable Keyboard
KbdCmdSend(KBD_PORT,0xF3);
KbdCmdSend(KBD_PORT,delay); //Typematic rate
KbdCmdSend(KBD_CTRL,0xA8); //Enable Mouse
} catch {
KbdCmdFlush;
Fs->catch_except=TRUE;
}
}
I64 A2ScanCode(I64 ch,I64 sc_flags=0)
{ //ASCII val to scan code (Slow)
I64 i;
U8 *table;
if (sc_flags) {
table=NORMAL_KEY_SCAN_DECODE_TABLE;
if (sc_flags & SCF_CTRL || ch<26)
table=CTRL_KEY_SCAN_DECODE_TABLE;
else if (sc_flags & SCF_SHIFT || 'A'<=ch<='Z') {
if (!(sc_flags & SCF_CAPS))
table=SHIFT_KEY_SCAN_DECODE_TABLE;
} else {
if (sc_flags & SCF_CAPS)
table=SHIFT_KEY_SCAN_DECODE_TABLE;
}
for (i=0;i<0x50;i++)
if (table[i]==ch)
return i|sc_flags;
return sc_flags;
} else {
table=NORMAL_KEY_SCAN_DECODE_TABLE;
for (i=0;i<0x50;i++)
if (table[i]==ch)
return i;
table=SHIFT_KEY_SCAN_DECODE_TABLE;
for (i=0;i<0x50;i++)
if (table[i]==ch)
return i|SCF_SHIFT;
table=CTRL_KEY_SCAN_DECODE_TABLE;
for (i=0;i<0x50;i++)
if (table[i]==ch)
return i|SCF_CTRL;
return 0;
}
}
U8 ScanCode2A(I64 sc)
{//Scan Code to ASCII val
U8 *table=NORMAL_KEY_SCAN_DECODE_TABLE;
if (sc & SCF_E0_PREFIX)
return 0;
if (sc & SCF_CTRL)
table=CTRL_KEY_SCAN_DECODE_TABLE;
else if (sc & SCF_SHIFT) {
if (!(sc & SCF_CAPS))
table=SHIFT_KEY_SCAN_DECODE_TABLE;
} else {
if (sc & SCF_CAPS)
table=SHIFT_KEY_SCAN_DECODE_TABLE;
}
sc&=0x7F;
if (sc>=0x50)
return 0;
else
return table[sc];
}
U8 scan_code_map[0x100]={
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,SC_SHIFT,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,SC_ENTER,SC_CTRL,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0x35,0,0,SC_ALT,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,SC_HOME,SC_CURSOR_UP,SC_PAGE_UP,0,SC_CURSOR_LEFT,0,SC_CURSOR_RIGHT,0,SC_END,
SC_CURSOR_DOWN,SC_PAGE_DOWN,SC_INS,SC_DELETE,0,0,0,0,0,0,0,0,SC_GUI,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
};
U8 num_lock_map[0x100]={
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,8,9,10,0,5,6,7,0,2,
3,4,11,0x34,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,SC_ENTER,SC_CTRL,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0x35,0,0,SC_ALT,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,SC_HOME,SC_CURSOR_UP,SC_PAGE_UP,0,SC_CURSOR_LEFT,0,SC_CURSOR_RIGHT,0,SC_END,
SC_CURSOR_DOWN,SC_PAGE_DOWN,SC_INS,SC_DELETE,0,0,0,0,0,0,0,0,SC_GUI,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
};
U8 *A2KeyName(I64 ch,Bool include_ctrl=TRUE)
{//ASCII val to key name
I64 i;
U8 buf[136];
if (ch<=CH_SPACE) {
nobound_switch (ch) {
case '\n':
StrCpy(buf,"ENTER");
break;
case CH_BACKSPACE:
StrCpy(buf,"BACKSPACE");
break;
case '\t':
StrCpy(buf,"TAB");
break;
case CH_ESC:
StrCpy(buf,"ESC");
break;
case CH_SHIFT_ESC:
StrCpy(buf,"SHIFT_ESC");
break;
case 0: //nobound_switch
case 29:
case 30:
*buf=0;
break;
case CH_SHIFT_SPACE:
StrCpy(buf,"SHIFT_SPACE");
break;
case CH_SPACE:
StrCpy(buf,"SPACE");
break;
default:
if (include_ctrl)
StrCpy(buf,"CTRL ");
buf[i=StrLen(buf)]=ch-1+'a';
buf[i+1]=0;
break;
}
} else if (Bt(chars_bitmap_printable,ch)) {
*buf=ch;
buf[1]=0;
} else
*buf=0;
return StrNew(buf);
}
U8 *ScanCode2KeyName(I64 sc)
{
I64 ch;
U8 buf[136],*st;
*buf=0;
if (sc&SCF_CTRL)
CatPrint(buf,"CTRL ");
if (sc&SCF_ALT)
CatPrint(buf,"ALT ");
if (sc&SCF_SHIFT)
CatPrint(buf,"SHIFT ");
if (ch=ScanCode2A(sc&255)) {
st=A2KeyName(ch,FALSE);
StrCpy(buf+StrLen(buf),st);
Free(st);
} else {
switch (sc&255) {
case SC_BACKSPACE:CatPrint(buf,"BACK"); break;
case SC_CAPS: CatPrint(buf,"CAPS"); break;
case SC_NUM: CatPrint(buf,"NUM"); break;
case SC_SCROLL: CatPrint(buf,"SCROLL"); break;
case SC_CURSOR_UP:CatPrint(buf,"UP"); break;
case SC_CURSOR_DOWN:CatPrint(buf,"DOWN"); break;
case SC_CURSOR_LEFT:CatPrint(buf,"LEFT"); break;
case SC_CURSOR_RIGHT:CatPrint(buf,"RIGHT"); break;
case SC_PAGE_UP: CatPrint(buf,"PAGE_UP"); break;
case SC_PAGE_DOWN:CatPrint(buf,"PAGE_DOWN");break;
case SC_HOME: CatPrint(buf,"HOME"); break;
case SC_END: CatPrint(buf,"END"); break;
case SC_INS: CatPrint(buf,"INS"); break;
case SC_DELETE: CatPrint(buf,"DELETE"); break;
case SC_F1: CatPrint(buf,"F1"); break;
case SC_F2: CatPrint(buf,"F2"); break;
case SC_F3: CatPrint(buf,"F3"); break;
case SC_F4: CatPrint(buf,"F4"); break;
case SC_F5: CatPrint(buf,"F5"); break;
case SC_F6: CatPrint(buf,"F6"); break;
case SC_F7: CatPrint(buf,"F7"); break;
case SC_F8: CatPrint(buf,"F8"); break;
case SC_F9: CatPrint(buf,"F9"); break;
case SC_F10: CatPrint(buf,"F10"); break;
case SC_F11: CatPrint(buf,"F11"); break;
case SC_F12: CatPrint(buf,"F12"); break;
case SC_GUI: CatPrint(buf,"WINDOWS"); break;
case SC_PRTSCRN1: CatPrint(buf,"PRTSCRN1"); break;
case SC_PRTSCRN2: CatPrint(buf,"PRTSCRN2"); break;
}
}
return StrNew(buf);
}
I64 KbdBuildSC(U8 raw_byte,U8 *_last_raw_byte,I64 *_last_sc,
Bool *_set_LEDs,Bool *_ctrl_alt)
{
I64 sc_flags,sc,sc2,sc_raw;
*_set_LEDs=FALSE;
*_ctrl_alt=FALSE;
if (raw_byte==0xE0) {
*_last_raw_byte=raw_byte;
return 0;
} else {
sc=raw_byte;
BEqu(&sc,SCf_E0_PREFIX,*_last_raw_byte==0xE0);
BEqu(&sc,SCf_KEY_UP,raw_byte & 0x80);
*_last_raw_byte=raw_byte;
}
sc_flags=_last_sc->u32[0]&~0x1FF;
sc_raw=sc;
if (sc_flags & SCF_NUM) {
if (sc2=num_lock_map[sc.u8[0]])
sc.u8[0]=sc2;
} else {
if (sc2=scan_code_map[sc.u8[0]])
sc.u8[0]=sc2;
}
if (sc&SCF_KEY_UP)
switch (sc&~SCF_KEY_UP) {
case SC_SHIFT: sc_flags&=~SCF_SHIFT; goto new_key_done;
case SC_CTRL: sc_flags&=~SCF_CTRL; goto new_key_done;
case SC_ALT: sc_flags&=~SCF_ALT; goto new_key_done;
case SC_DELETE: sc_flags&=~SCF_DELETE; goto new_key_done;
case SC_INS: sc_flags&=~SCF_INS; goto new_key_done;
case SC_CAPS:
sc_flags^=SCF_CAPS;
*_set_LEDs=TRUE;
goto new_key_done;
case SC_NUM:
sc_flags^=SCF_NUM;
*_set_LEDs=TRUE;
goto new_key_done;
case SC_SCROLL:
sc_flags^=SCF_SCROLL;
*_set_LEDs=TRUE;
goto new_key_done;
}
else
switch (sc) {
case SC_SHIFT: sc_flags|=SCF_SHIFT; goto new_key_done;
case SC_CTRL: sc_flags|=SCF_CTRL; goto new_key_done;
case SC_ALT: sc_flags|=SCF_ALT; goto new_key_done;
case SC_DELETE: sc_flags|=SCF_DELETE; goto new_key_done;
case SC_INS: sc_flags|=SCF_INS; goto new_key_done;
case SC_CAPS: goto new_key_done;
case SC_NUM: goto new_key_done;
case SC_SCROLL: goto new_key_done;
}
if (sc_flags & SCF_CTRL && sc_flags & SCF_ALT) {
sc_flags&=~SCF_NEW_KEY;
*_ctrl_alt=TRUE;
} else {
new_key_done:
sc_flags|=SCF_NEW_KEY;
}
return *_last_sc=sc_flags|sc|(sc_flags|sc_raw)<<32;
}
U0 KbdPktRead()
{
static U8 last_raw_byte=0;
static I64 last_sc=0;
U8 raw_byte;
I64 ch,sc;
Bool set_LEDs,ctrl_alt;
if (GetTSC>kbd_evt_time+time_stamp_freq>>3)
FifoU8Flush(kbd_fifo);
kbd_evt_time=GetTSC;
raw_byte=InU8(KBD_PORT);
sc=KbdBuildSC(raw_byte,&last_raw_byte,&last_sc,&set_LEDs,&ctrl_alt);
if (ctrl_alt && sc) {
if (!(sc & SCF_KEY_UP)) {
if (sc&255==SC_DELETE)
CtrlAltDel(last_sc);
else {
if (sc&255==SC_ESC)
ch='e';
else if (sc&255==SC_TAB)
ch='t';
else
ch=ScanCode2A(sc&255);
if ('a'<=ch<='z' && fp_ctrl_alt_let_cbs[ch-'a'] &&
Bt(&ctrl_alt_let_in_irq_flags,ch-'a')) {
(*fp_ctrl_alt_let_cbs[ch-'a'])(last_sc);
return;
}
}
}
}
if (!FifoU8Cnt(kbd_fifo)) {
FifoU8Ins(kbd_fifo,raw_byte);
if (raw_byte!=0xE0) {
while (FifoU8Rem(kbd_fifo,&raw_byte))
FifoU8Ins(kbd2_fifo,raw_byte);
}
} else {
FifoU8Ins(kbd_fifo,raw_byte);
while (FifoU8Rem(kbd_fifo,&raw_byte))
FifoU8Ins(kbd2_fifo,raw_byte);
}
}
interrupt U0 KbdIntHandler()
{
CLD
OutU8(0x20,0x20);
kbd_irqs_working=TRUE;
if (mouse_install_attempt_in_progress) {
kbdmouse_rst=TRUE;
return;
}
ctrl_alt_let_ret_addr=GetRBP()(I64)+8;
KbdPktRead;
}
U0 KbdInit()
{
try {
KbdCmdFlush;
KbdCmdSend(KBD_CTRL,0xA7); //Disable Mouse
KbdCmdSend(KBD_CTRL,0xAE); //Enable Keyboard
KbdCmdSend(KBD_PORT,0xF0);
KbdCmdSend(KBD_PORT,0x02);
KbdSetLEDs(sys_cur_scan_code);
} catch {
KbdCmdFlush;
Fs->catch_except=TRUE;
}
IntEntrySet(0x21,&KbdIntHandler);
OutU8(0x21,InU8(0x21)&~2);
SetCtrlAltLetCB('C',&CtrlAltC,"Sys/Break Execution",TRUE);
SetCtrlAltLetCB('D',&CtrlAltD,"Sys/Enter Debugger",TRUE);
SetCtrlAltLetCB('E',&CtrlAltE,"Sys/Spawn New User Task");
SetCtrlAltLetCB('F',&CtrlAltF,"Sys/VGA Flush",TRUE);
SetCtrlAltLetCB('M',&CtrlAltM,"Sys/Toggle Mute");
SetCtrlAltLetCB('T',&CtrlAltT,"Sys/Switch Focus to Next Task",TRUE);
SetCtrlAltLetCB('X',&CtrlAltX,"Sys/Kill Focused Task",TRUE);
}
U0 KbdHandler()
{
static U8 last_raw_byte=0;
U8 raw_byte;
Bool set_LEDs,ctrl_alt;
I64 ch,sc;
FifoU8Rem(kbd2_fifo,&raw_byte);
sc=KbdBuildSC(raw_byte,&last_raw_byte,&sys_cur_scan_code,&set_LEDs,&ctrl_alt);
if (set_LEDs)
KbdSetLEDs(sc);
if (raw_byte==0xE0) {
FifoU8Rem(kbd2_fifo,&raw_byte);
sc=KbdBuildSC(raw_byte,&last_raw_byte,&sys_cur_scan_code,&set_LEDs,&ctrl_alt);
if (set_LEDs)
KbdSetLEDs(sc);
}
if (ctrl_alt) {
if (!(sc & SCF_KEY_UP)) {
if (sc&255==SC_ESC)
ch='e';
else if (sc&255==SC_TAB)
ch='t';
else
ch=ScanCode2A(sc&255);
if ('a'<=ch<='z' && fp_ctrl_alt_let_cbs[ch-'a'] &&
!Bt(&ctrl_alt_let_in_irq_flags,ch-'a'))
(*fp_ctrl_alt_let_cbs[ch-'a'])(sys_cur_scan_code);
}
return;
}
if (Btr(&sys_cur_scan_code,SCf_NEW_KEY)) {
Btr(&sys_cur_scan_code,32+SCf_NEW_KEY);
FifoI64Ins(scan_code_fifo,sys_cur_scan_code);
sys_key_cnt++;
if (!(sys_cur_scan_code&SCF_KEY_UP)) {
sys_last_down_scan_code=sys_cur_scan_code;
Bts(key_down_bitmap,sys_cur_scan_code.u8[0]);
Bts(key_down_bitmap2,sys_cur_scan_code.u8[4]);
} else {
Btr(key_down_bitmap,sys_cur_scan_code.u8[0]);
Btr(key_down_bitmap2,sys_cur_scan_code.u8[4]);
}
}
}
I64 KbdMsgsQue()
{
I64 p1,p2,msg_code=MSG_NULL;
CTask *task_focus;
if (task_focus=sys_focus_task) {
while (FifoI64Rem(scan_code_fifo,&p2)) {
p1=ScanCode2A(p2);
if (p2 & SCF_KEY_UP) {
TaskMsg(task_focus,0,
MSG_KEY_UP,p1,p2,0);
msg_code=MSG_KEY_UP;
} else {
TaskMsg(task_focus,0,
MSG_KEY_DOWN,p1,p2,0);
msg_code=MSG_KEY_DOWN;
}
}
}
return msg_code;
}
I64 KbdMouseEvtTime()
{
if (mouse_evt_time>kbd_evt_time)
return mouse_evt_time;
else
return kbd_evt_time;
}
+227
View File
@@ -0,0 +1,227 @@
U0 InputFilterTask()
{
CSrvCmd *tempc,*tempc1;
Bool old_filter;
I64 old_flags=GetRFlags;
Fs->win_inhibit=WIG_USER_TASK_DFT;
LBts(&Fs->task_flags,TASKf_INPUT_FILTER_TASK);
old_filter=LBts(&Fs->last_input_filter_task->task_flags,TASKf_FILTER_INPUT);
LBEqu(&Fs->task_flags,TASKf_FILTER_INPUT,old_filter);
while (TRUE) {
SrvCmdsHandler;
CLI
tempc1=&Fs->srv_ctrl.next_waiting;
tempc=tempc1->next;
if (tempc==tempc1)
break;
else {
if (tempc->cmd_code==SVCT_TEXT_INPUT) {
QueRem(tempc);
SetRFlags(old_flags);
Preempt(ON);
try
ExePrint("%s",tempc->aux_str);
catch
Fs->catch_except=TRUE;
Preempt(OFF);
SrvCmdDel(tempc);
} else
break;
}
}
Fs->next_input_filter_task->last_input_filter_task=Fs->last_input_filter_task;
Fs->last_input_filter_task->next_input_filter_task=Fs->next_input_filter_task;
if (!old_filter)
LBtr(&Fs->last_input_filter_task->task_flags,TASKf_FILTER_INPUT);
SetRFlags(old_flags);
}
I64 ScanMsg(I64 *_p1=NULL,I64 *_p2=NULL,I64 mask=~1,CTask *task=NULL)
{
I64 result,old_flags;
CSrvCmd *tempc,*tempc1;
if (!task) task=Fs;
old_flags=GetRFlags;
tempc1=&task->srv_ctrl.next_waiting;
while (TRUE) {
if (task==Fs)
SrvCmdsHandler;
CLI
tempc=tempc1->next;
if (tempc==tempc1)
break;
else {
if (tempc->cmd_code==SVCT_MSG) {
QueRem(tempc);
SetRFlags(old_flags);
result=tempc->msg_code;
if (_p1)
*_p1=tempc->aux1;
if (_p2)
*_p2=tempc->aux2;
SrvCmdDel(tempc);
if ((result!=MSG_KEY_DOWN || !(tempc->aux2&SCF_KEY_DESC) ||
Bt(&mask,MSGF_ALLOW_KEY_DESC)) && Bt(&mask,result))
goto sm_done;
}
}
SetRFlags(old_flags);
}
result=MSG_NULL;
if (_p1)
*_p1=0;
if (_p2)
*_p2=0;
if (task->parent_task&&task->parent_task->popup_task==task) {
SetRFlags(old_flags);
return ScanMsg(_p1,_p2,mask,task->parent_task);
}
sm_done:
SetRFlags(old_flags);
return result;
}
I64 FlushMsgs(CTask *task=NULL)
{
I64 result=0,p1,p2;
while (ScanMsg(&p1,&p2,~1,task))
result++;
return result;
}
I64 GetMsg(I64 *_p1=NULL,I64 *_p2=NULL,I64 mask=~1,CTask *task=NULL)
{
I64 result;
Bool old_preempt=Preempt(OFF);
if (!task) task=Fs;
LBtr(&task->task_flags,TASKf_IDLE);
while (!(result=ScanMsg(_p1,_p2,mask,task))) {
LBts(&task->task_flags,TASKf_IDLE);
Yield;
}
LBtr(&task->task_flags,TASKf_IDLE);
Preempt(old_preempt);
return result;
}
I64 ScanChar()
{
I64 p1a,p2a,p1b,p2b;
if (!ScanMsg(&p1a,&p2a,1<<MSG_KEY_DOWN)||!p1a)
return 0;
else
do GetMsg(&p1b,&p2b,1<<MSG_KEY_UP);
while (!p1b);
return p1a;
}
Bool ScanKey(I64 *_ch=NULL,I64 *_scancode=NULL,Bool echo=FALSE)
{
I64 ch=0,sc=0;
if (ScanMsg(&ch,&sc,1<<MSG_KEY_DOWN)) {
if (_ch) *_ch=ch;
if (_scancode) *_scancode=sc;
if (echo)
PutKey(ch,sc);
return TRUE;
} else {
if (_ch) *_ch=0;
if (_scancode) *_scancode=0;
return FALSE;
}
}
I64 GetKey(I64 *_scancode=NULL,Bool echo=FALSE,Bool raw_cursor=FALSE)
{
I64 ch,sc;
Bool old_preempt=Preempt(OFF),cursor_on=FALSE;
while (!ScanKey(&ch,&sc,FALSE)) {
if (IsRaw && raw_cursor) {
if (!cursor_on && ToI64(GetTSC*5/time_stamp_freq)&1) {
'Û';
cursor_on=TRUE;
} else if (cursor_on && !(ToI64(GetTSC*5/time_stamp_freq)&1)) {
'' CH_BACKSPACE;
cursor_on=FALSE;
}
}
LBts(&Fs->task_flags,TASKf_IDLE);
if (IsDbg) {
//We don't want interrupt-driven keyboard when in debugger
//because that could have side-effects or crash, so we poll
//keyboard when in debugger with interrupts off.
PUSHFD
CLI
KbdMouseHandler(TRUE,FALSE);
KbdMsgsQue;
POPFD
if (old_preempt && GetRFlags&1<<RFLAGf_INT)
Yield;
} else {
LBts(&Fs->task_flags,TASKf_AWAITING_MSG);
Yield;
}
LBtr(&Fs->task_flags,TASKf_IDLE);
}
if (IsRaw && raw_cursor && cursor_on)
'' CH_BACKSPACE;
Preempt(old_preempt);
if (echo)
PutKey(ch,sc);
if (_scancode) *_scancode=sc;
return ch;
}
I64 GetChar(I64 *_scancode=NULL,Bool echo=TRUE,Bool raw_cursor=FALSE)
{
I64 ch1;
do ch1=GetKey(_scancode,FALSE,raw_cursor);
while (!ch1);
if (echo)
"$$PT$$%c$$FG$$",ch1;
return ch1;
}
U8 *MGetS(I64 flags=0)
//$LK,"Flags",A="MN:GETSF_SHIFT_ESC_EXIT"$
{
//Returns a $LK,"MAlloc",A="MN:MAlloc"$()ed prompted string.
return (*fp_mgets)(flags);
}
I64 GetS(U8 *buf,I64 size,Bool allow_ext=TRUE)
{
U8 *st;
I64 ch,i=0;
if (!size || !buf) return 0;
if (allow_ext) {
st=MGetS;
if (StrLen(st)>size-1) {
MemCpy(buf,st,size-1);
buf[size-1]=0;
} else
StrCpy(buf,st);
i=StrLen(buf);
Free(st);
} else {
while (TRUE) {
ch=GetChar(,FALSE,IsDbg);
if (ch=='\n') {
'' ch;
break;
} else if (ch==CH_BACKSPACE) {
if (i>0) {
i--;
'' ch;
}
} else {
if (i<size-1) {
buf[i++]=ch;
'' ch;
}
}
}
buf[i]=0;
}
return i;
}
+334
View File
@@ -0,0 +1,334 @@
U0 MousePktRead()
{
U8 j;
if (GetTSC>mouse_evt_time+time_stamp_freq>>3)
FifoU8Flush(mouse_fifo);
mouse_evt_time=GetTSC;
FifoU8Ins(mouse_fifo,InU8(KBD_PORT));
if (FifoU8Cnt(mouse_fifo)==mouse_pkt_size)
while (FifoU8Rem(mouse_fifo,&j))
FifoU8Ins(mouse2_fifo,j);
}
interrupt U0 MouseIntHandler()
{
CLD
OutU8(0xA0,0x20);
OutU8(0x20,0x20);
mouse_irqs_working=TRUE;
if (mouse_install_attempt_in_progress || !mouse_installed) {
kbdmouse_rst=TRUE;
return;
}
MousePktRead;
}
U0 MouseGetDevType()
{
I64 b;
KbdMouseCmdAck(0xF2);
b=KbdCmdRead;
if (b==3)
mouse_has_wheel=TRUE;
else if (b==4)
mouse_has_ext_buttons=TRUE;
}
Bool MouseRst()
{
U8 b,*_b;
U16 *_w;
F64 timeout;
Bool result=FALSE,present;
mouse_has_wheel=FALSE;
mouse_has_ext_buttons=FALSE;
_w=0x40E;
present=MemPagePresentMark(_w,TRUE);
if (*_w==0x9FC0) {
_b=0x9FC00+0x30;
*_b=1; //This enables my mouse. It might be for one machine.
//USB DMA packets, set-up by BIOS to make legacy PS/2?
}
if (!present)
MemPagePresentMark(_w,FALSE);
try {
KbdCmdFlush;
KbdCmdSend(KBD_CTRL,0xAD); //Disable Kbd
KbdCmdSend(KBD_CTRL,0xA8); //Enable Mouse
KbdMouseCmdAck(0xFF); //Rst
timeout=tS+10.0;
do
try {
KbdCmdRead;
timeout=0; //force exit
} catch
Fs->catch_except=TRUE;
while (tS<timeout);
try
KbdCmdRead;
catch
Fs->catch_except=TRUE;
KbdMouseCmdAck(0xF3);
KbdMouseCmdAck(200);
KbdMouseCmdAck(0xF3); // enable Mouse
KbdMouseCmdAck(100); // Set Rate
KbdMouseCmdAck(0xF3);
KbdMouseCmdAck(80); //Resolution
MouseGetDevType; // enable Mouse
KbdMouseCmdAck(0xF3);
KbdMouseCmdAck(10);
MouseGetDevType; // enable Mouse
KbdMouseCmdAck(0xE8); //Resolution
KbdMouseCmdAck(0x03);
KbdMouseCmdAck(0xE6);
KbdMouseCmdAck(0xF3); // Set Rate
KbdMouseCmdAck(100);
KbdMouseCmdAck(0xF4); // enable Mouse
result=TRUE;
//Enable IRQ 12
KbdCmdSend(KBD_CTRL,0x20);
b=KbdCmdRead;
KbdCmdSend(KBD_CTRL,0x60);
KbdCmdSend(KBD_PORT,(b|2)&~0x20);
} catch
Fs->catch_except=TRUE;
//This is been added to override failure
//because the mouse sometimes still works.
result=TRUE;
try
KbdCmdSend(KBD_CTRL,0xAE); //Enable Keyboard
catch
Fs->catch_except=TRUE;
if (mouse_has_wheel || mouse_has_ext_buttons)
mouse_pkt_size=4;
else
mouse_pkt_size=3;
if (!result)
try
KbdCmdSend(KBD_CTRL,0xA7); //Disable Mouse
catch
Fs->catch_except=TRUE;
return result;
}
U0 SetMouseSpeed()
{
I64 dd,temp;
if ((dd=SqrI64(old_mxx-mxx)+SqrI64(old_myy-myy)) &&
(temp=mouse_evt_time-mouse_last_evt_time))
mouse_speed=Sqrt(dd)*time_stamp_freq/temp;
mouse_last_evt_time=mouse_evt_time;
}
U0 MouseUpdatePre(Bool *old_buttons)
{
I64 i;
old_mxx=mxx; old_myy=myy; old_mzz=mzz;
for (i=0;i<5;i++)
old_buttons[i]=mouse_buttons[i];
}
U0 MouseUpdatePost(Bool *old_buttons)
{
I64 i;
mxx=mxx_prescale*mxx_scale*ip_grid.x_speed;
myy=myy_prescale*myy_scale*ip_grid.y_speed;
mzz=mzz_prescale*mzz_scale*ip_grid.z_speed;
i=Trunc(ipx_scale*mxx/ip_grid.x)*ip_grid.x+ipx_offset; //TODO ip_grid.x_offset?
if (i<0)
ipx_offset-=i;
else if (i>=gr_width)
ipx_offset+=gr_width-1-i;
i=Trunc(ipy_scale*myy/ip_grid.y)*ip_grid.y+ipy_offset;
if (i<0)
ipy_offset-=i;
else if (i>=gr_height)
ipy_offset+=gr_height-1-i;
if (mxx!=old_mxx||myy!=old_myy||mzz!=old_mzz) {
mouse_evt=TRUE;
SetMouseSpeed;
} else
for (i=0;i<5;i++)
if (mouse_buttons[i]!=old_buttons[i]) {
mouse_evt=TRUE;
break;
}
}
U0 MouseHandler()
{
I64 i,dx,dy,dz;
U8 mouse_buf[4];
Bool old_buttons[5];
MouseUpdatePre(old_buttons);
for (i=0;i<4;i++)
mouse_buf[i]=0;
for (i=0;i<mouse_pkt_size;i++)
if (!FifoU8Rem(mouse2_fifo,&mouse_buf[i]))
mouse_buf[i]=0;
mouse_buttons[0] = mouse_buf[0] & 1;
mouse_buttons[1] = (mouse_buf[0] & 2) >> 1;
mouse_buttons[2] = (mouse_buf[0] & 4) >> 2;
mouse_buttons[3] = (mouse_buf[3] & 0x10) >> 4;
mouse_buttons[4] = (mouse_buf[3] & 0x20) >> 5;
if (mouse_buf[0] & 0x10)
dx=mouse_buf[1]-256;
else
dx=mouse_buf[1];
if (mouse_buf[0] & 0x20)
dy=256-mouse_buf[2];
else
dy=-mouse_buf[2];
if (mouse_buf[3] & 0x08)
dz=mouse_buf[3]&7-8;
else
dz=mouse_buf[3]&7;
mxx_prescale+=dx;
myy_prescale+=dy;
mzz_prescale+=dz;
MouseUpdatePost(old_buttons);
}
U0 SetMouseIP(I64 x,I64 y,I64 z,I64 l,I64 r,I64 c)
{
Bool old_buttons[5];
mouse_evt_time=GetTSC;
MouseUpdatePre(old_buttons);
mxx_prescale=x/mxx_scale/ip_grid.x_speed;
myy_prescale=y/myy_scale/ip_grid.y_speed;
mzz_prescale=z/mzz_scale/ip_grid.z_speed;
mouse_buttons[0]=l;
mouse_buttons[1]=r;
mouse_buttons[2]=c; //unsure which one
MouseUpdatePost(old_buttons);
}
U0 KbdMouseRst()
{
KbdCmdFlush;
FifoU8Flush(kbd2_fifo);
FifoU8Flush(mouse2_fifo);
FifoI64Flush(scan_code_fifo);
sys_cur_scan_code=0;
kbdmouse_rst=FALSE;
}
Bool MouseDriverInstall(I64 dummy=0) //can be spawned
{
nounusedwarn dummy;
I64 i;
Bool old_preempt=IsPreempt;
Preempt(ON);
mouse_install_attempt_in_progress=TRUE;
OutU8(0xA1,InU8(0xA1)|0x10);
mouse_installed=mouse_irqs_working=FALSE;
IntEntrySet(0x2C,&MouseIntHandler);
for(i=0;i<5;i++)
mouse_buttons[i]=0;
if (i=MouseRst)
OutU8(0xA1,InU8(0xA1)&~0x10);
KbdMouseRst;
mouse_install_attempts++;
mouse_installed=mouse_evt=i;
mouse_install_attempt_in_progress=FALSE;
Preempt(old_preempt);
return mouse_installed;
}
U0 KbdMouseHandler(Bool poll_kbd,Bool poll_mouse)
{
if (mouse_install_attempt_in_progress) {
Yield;
return;
}
if (kbdmouse_rst)
KbdMouseRst;
else {
if (poll_mouse &&
mouse_installed &&
!mouse_irqs_working) {
PUSHFD
CLI
while (InU8(KBD_CTRL)&1)
MousePktRead;
POPFD
}
if (poll_kbd)
while (InU8(KBD_CTRL)&1)
KbdPktRead;
if (kbdmouse_rst)
KbdMouseRst;
else {
while (FifoU8Cnt(kbd2_fifo))
KbdHandler;
while (FifoU8Cnt(mouse2_fifo))
if (mouse_installed)
MouseHandler;
else
KbdMouseRst;
}
}
}
U0 KbdMouseVarsInit()
{
sys_key_cnt=0;
scan_code_fifo=FifoI64New(128);
kbd_fifo=FifoU8New(8);
kbd2_fifo=FifoU8New(64);
mouse_fifo=FifoU8New(8);
mouse2_fifo=FifoU8New(64);
MemSet(key_down_bitmap,0,256/8);
MemSet(key_down_bitmap2,0,256/8);
sys_last_down_scan_code=0;
sys_cur_scan_code=0;
kbdmouse_rst=FALSE;
kbd_irqs_working=FALSE;
mouse_irqs_working=FALSE;
mxx_scale=0.5;
myy_scale=0.5;
mzz_scale=1.0;
mxx_prescale=gr_width/mxx_scale/2.0;
myy_prescale=gr_height/myy_scale/2.0;
mzz_prescale=0/mzz_scale;
mxx=gr_width>>1;
myy=gr_height>>1;
mzz=0;
mouse_speed=0.0;
old_mxx=mxx;
old_myy=myy;
old_mzz=mzz;
mouse_installed=FALSE;
mouse_install_attempts=0;
mouse_last_evt_time=0;
mouse_has_wheel=FALSE;
mouse_has_ext_buttons=FALSE;
mouse_evt=FALSE;
}
+3310
View File
File diff suppressed because it is too large. Load diff
+74
View File
@@ -0,0 +1,74 @@
//You should compile this by calling
//$LK,"MakeOSPrtBootInstall",A="MN:MakeOSPrtBootInstall"$(), not doing it directly.
//See $LK,"Cmp(\"Kernel\")",A="FF:::/Adam/Boot/InsBoot.CPP,Cmp(\"Kernel\""$.
#exe {
OptOn(OPTf_WARN_PAREN);
OptOn(OPTf_WARN_DUP_TYPES);
#include "KCfg"
CKernelCfg *kernel_cfg;
kernel_cfg=KernelCfgNew;
};
#include "Adam1a.HPP"
#include "KStart"
#include "Utils1a"
#include "Math1a"
#include "/Compiler/CmpDefs.HPP"
#include "Adam1b.HPP"
#include "KExts"
#include "Str1a"
#include "Mem1a"
#include "KGlbls"
#include "Mem1b"
#include "Math1b"
#include "Scheduler"
#include "Mem1c"
#include "Font8x8"
#include "Hash1a"
#include "Str1b"
#include "Interrupts"
#include "DataTypes1a"
#include "Compress"
#include "Hash1b"
#include "Date"
#include "StrPrint"
#include "StrScan"
#include "Define1a"
#include "Display"
#include "Misc1a"
#include "Dbg1a"
#include "Except"
#include "KbdMouse/InputPointer"
#include "KbdMouse/Keyboard"
#include "KbdMouse/Mouse"
#include "KbdMouse/Message"
#include "QSort"
#include "Task1a"
#include "SrvCmd"
#include "BIOS32"
#exe {Cd("Dsk");};
#include "DskStr"
#include "DskCache"
#include "ATADef.HPP"
#include "DskATA"
#include "Dsk1a"
#include "DskAddDev"
#include "DskDir"
#include "FileSysISO1"
#include "FileSysRedSea"
#include "FileSysFAT"
#include "Dsk1b"
#include "DskCFile"
#include "Dsk1c"
#exe {Cd("..");};
#include "MultiProc"
#include "EdLite"
#include "PSect"
#include "KEnd"
#exe {KernelCfgDel(kernel_cfg);};
+665
View File
@@ -0,0 +1,665 @@
asm {
USE64
// ************************************
_D3_NORM::
PUSH RBP
MOV RBP,RSP
MOV RDX,U64 SF_ARG1[RBP]
FLD U64 [RDX]
FMUL ST0,ST0
FLD U64 8[RDX]
FMUL ST0,ST0
FADDP ST1,ST0
FLD U64 16[RDX]
FMUL ST0,ST0
FADDP ST1,ST0
FSQRT
FSTP U64 SF_ARG1[RBP]
MOV RAX,U64 SF_ARG1[RBP]
POP RBP
RET1 8
// ************************************
_D3_SQR_NORM::
PUSH RBP
MOV RBP,RSP
MOV RDX,U64 SF_ARG1[RBP]
FLD U64 [RDX]
FMUL ST0,ST0
FLD U64 8[RDX]
FMUL ST0,ST0
FADDP ST1,ST0
FLD U64 16[RDX]
FMUL ST0,ST0
FADDP ST1,ST0
FSTP U64 SF_ARG1[RBP]
MOV RAX,U64 SF_ARG1[RBP]
POP RBP
RET1 8
// ************************************
_D3_DIST::
PUSH RBP
MOV RBP,RSP
MOV RDX,U64 SF_ARG1[RBP]
MOV RBX,U64 SF_ARG2[RBP]
FLD U64 [RDX]
FSUB ST0,U64 [RBX]
FMUL ST0,ST0
FLD U64 8[RDX]
FSUB ST0,U64 8[RBX]
FMUL ST0,ST0
FADDP ST1,ST0
FLD U64 16[RDX]
FSUB ST0,U64 16[RBX]
FMUL ST0,ST0
FADDP ST1,ST0
FSQRT
FSTP U64 SF_ARG1[RBP]
MOV RAX,U64 SF_ARG1[RBP]
POP RBP
RET1 16
// ************************************
_D3_SQR_DIST::
PUSH RBP
MOV RBP,RSP
MOV RDX,U64 SF_ARG1[RBP]
MOV RBX,U64 SF_ARG2[RBP]
FLD U64 [RDX]
FSUB ST0,U64 [RBX]
FMUL ST0,ST0
FLD U64 8[RDX]
FSUB ST0,U64 8[RBX]
FMUL ST0,ST0
FADDP ST1,ST0
FLD U64 16[RDX]
FSUB ST0,U64 16[RBX]
FMUL ST0,ST0
FADDP ST1,ST0
FSTP U64 SF_ARG1[RBP]
MOV RAX,U64 SF_ARG1[RBP]
POP RBP
RET1 16
// ************************************
_D3_CROSS::
PUSH RBP
MOV RBP,RSP
MOV RDX,U64 SF_ARG1[RBP]
MOV RBX,U64 SF_ARG2[RBP]
MOV RAX,U64 SF_ARG3[RBP]
FLD U64 8[RDX]
FMUL ST0,U64 16[RBX]
FLD U64 16[RDX]
FMUL ST0,U64 8[RBX]
FSUBP ST1,ST0
FSTP U64 [RAX]
FLD U64 [RDX]
FMUL ST0,U64 16[RBX]
FLD U64 16[RDX]
FMUL ST0,U64 [RBX]
FSUBRP ST1,ST0
FSTP U64 8[RAX]
FLD U64 [RDX]
FMUL ST0,U64 8[RBX]
FLD U64 8[RDX]
FMUL ST0,U64 [RBX]
FSUBP ST1,ST0
FSTP U64 16[RAX]
POP RBP
RET1 24
// ************************************
_D3_DOT::
PUSH RBP
MOV RBP,RSP
MOV RDX,U64 SF_ARG1[RBP]
MOV RBX,U64 SF_ARG2[RBP]
FLD U64 [RDX]
FMUL ST0,U64 [RBX]
FLD U64 8[RDX]
FMUL ST0,U64 8[RBX]
FADDP ST1,ST0
FLD U64 16[RDX]
FMUL ST0,U64 16[RBX]
FADDP ST1,ST0
FSTP U64 SF_ARG1[RBP]
MOV RAX,U64 SF_ARG1[RBP]
POP RBP
RET1 16
// ************************************
_D3_ADD::
PUSH RBP
MOV RBP,RSP
MOV RDX,U64 SF_ARG1[RBP]
MOV RBX,U64 SF_ARG2[RBP]
MOV RAX,U64 SF_ARG3[RBP]
FLD U64 [RDX]
FADD ST0,U64 [RBX]
FSTP U64 [RAX]
FLD U64 8[RDX]
FADD ST0,U64 8[RBX]
FSTP U64 8[RAX]
FLD U64 16[RDX]
FADD ST0,U64 16[RBX]
FSTP U64 16[RAX]
POP RBP
RET1 24
// ************************************
_D3_SUB::
PUSH RBP
MOV RBP,RSP
MOV RDX,U64 SF_ARG1[RBP]
MOV RBX,U64 SF_ARG2[RBP]
MOV RAX,U64 SF_ARG3[RBP]
FLD U64 [RDX]
FSUB ST0,U64 [RBX]
FSTP U64 [RAX]
FLD U64 8[RDX]
FSUB ST0,U64 8[RBX]
FSTP U64 8[RAX]
FLD U64 16[RDX]
FSUB ST0,U64 16[RBX]
FSTP U64 16[RAX]
POP RBP
RET1 24
// ************************************
_D3_MUL::
PUSH RBP
MOV RBP,RSP
MOV RBX,U64 SF_ARG2[RBP]
MOV RAX,U64 SF_ARG3[RBP]
FLD U64 SF_ARG1[RBP]
FLD ST0
FMUL ST0,U64 [RBX]
FSTP U64 [RAX]
FLD ST0
FMUL ST0,U64 8[RBX]
FSTP U64 8[RAX]
FMUL ST0,U64 16[RBX]
FSTP U64 16[RAX]
POP RBP
RET1 24
// ************************************
_D3_DIV::
PUSH RBP
MOV RBP,RSP
MOV RBX,U64 SF_ARG2[RBP]
MOV RAX,U64 SF_ARG3[RBP]
FLD U64 SF_ARG1[RBP]
FLD ST0
FDIVR ST0,U64 [RBX]
FSTP U64 [RAX]
FLD ST0
FDIVR ST0,U64 8[RBX]
FSTP U64 8[RAX]
FDIVR ST0,U64 16[RBX]
FSTP U64 16[RAX]
POP RBP
RET1 24
// ************************************
_D3_ZERO::
PUSH RBP
MOV RBP,RSP
MOV RAX,U64 SF_ARG1[RBP]
XOR RDX,RDX
MOV U64 [RAX],RDX
MOV U64 8[RAX],RDX
MOV U64 16[RAX],RDX
POP RBP
RET1 8
// ************************************
_D3_COPY::
PUSH RBP
MOV RBP,RSP
MOV RAX,U64 SF_ARG1[RBP]
MOV RBX,U64 SF_ARG2[RBP]
MOV RDX,U64 [RBX]
MOV U64 [RAX],RDX
MOV RDX,U64 8[RBX]
MOV U64 8[RAX],RDX
MOV RDX,U64 16[RBX]
MOV U64 16[RAX],RDX
POP RBP
RET1 16
// ************************************
_D3_EQU::
PUSH RBP
MOV RBP,RSP
MOV RAX,U64 SF_ARG1[RBP]
MOV RDX,U64 SF_ARG2[RBP]
MOV U64 [RAX],RDX
MOV RDX,U64 SF_ARG3[RBP]
MOV U64 8[RAX],RDX
MOV RDX,U64 SF_ARG4[RBP]
MOV U64 16[RAX],RDX
POP RBP
RET1 32
// ************************************
_D3_ADD_EQU::
PUSH RBP
MOV RBP,RSP
MOV RAX,U64 SF_ARG1[RBP]
MOV RBX,U64 SF_ARG2[RBP]
FLD U64 [RAX]
FADD ST0,U64 [RBX]
FSTP U64 [RAX]
FLD U64 8[RAX]
FADD ST0,U64 8[RBX]
FSTP U64 8[RAX]
FLD U64 16[RAX]
FADD ST0,U64 16[RBX]
FSTP U64 16[RAX]
POP RBP
RET1 16
// ************************************
_D3_SUB_EQU::
PUSH RBP
MOV RBP,RSP
MOV RAX,U64 SF_ARG1[RBP]
MOV RBX,U64 SF_ARG2[RBP]
FLD U64 [RAX]
FSUB ST0,U64 [RBX]
FSTP U64 [RAX]
FLD U64 8[RAX]
FSUB ST0,U64 8[RBX]
FSTP U64 8[RAX]
FLD U64 16[RAX]
FSUB ST0,U64 16[RBX]
FSTP U64 16[RAX]
POP RBP
RET1 16
// ************************************
_D3_MUL_EQU::
PUSH RBP
MOV RBP,RSP
MOV RAX,U64 SF_ARG1[RBP]
FLD U64 SF_ARG2[RBP]
FLD ST0
FMUL ST0,U64 [RAX]
FSTP U64 [RAX]
FLD ST0
FMUL ST0,U64 8[RAX]
FSTP U64 8[RAX]
FMUL ST0,U64 16[RAX]
FSTP U64 16[RAX]
POP RBP
RET1 16
// ************************************
_D3_DIV_EQU::
PUSH RBP
MOV RBP,RSP
MOV RAX,U64 SF_ARG1[RBP]
FLD U64 SF_ARG2[RBP]
FLD ST0
FDIVR ST0,U64 [RAX]
FSTP U64 [RAX]
FLD ST0
FDIVR ST0,U64 8[RAX]
FSTP U64 8[RAX]
FDIVR ST0,U64 16[RAX]
FSTP U64 16[RAX]
POP RBP
RET1 16
// ************************************
_D3_UNIT::
PUSH RBP
MOV RBP,RSP
MOV RDX,U64 SF_ARG1[RBP]
FLD U64 [RDX]
FMUL ST0,ST0
FLD U64 8[RDX]
FMUL ST0,ST0
FADDP ST1,ST0
FLD U64 16[RDX]
FMUL ST0,ST0
FADDP ST1,ST0
FSQRT
FST U64 SF_ARG1[RBP]
MOV RBX,SF_ARG1[RBP]
TEST RBX,RBX
JZ @@05
FLD ST0
FDIVR ST0,U64 [RAX]
FSTP U64 [RAX]
FLD ST0
FDIVR ST0,U64 8[RAX]
FSTP U64 8[RAX]
FDIVR ST0,U64 16[RAX]
FSTP U64 16[RAX]
POP RBP
RET1 8
@@05: FFREE ST0
FINCSTP
POP RBP
RET1 8
// ************************************
_SQR::
PUSH RBP
MOV RBP,RSP
FLD U64 SF_ARG1[RBP]
FMUL ST0,ST0
FSTP U64 SF_ARG1[RBP]
MOV RAX,U64 SF_ARG1[RBP]
POP RBP
RET1 8
// ************************************
_SIGN::
PUSH RBP
MOV RBP,RSP
FLD U64 SF_ARG1[RBP]
FTST
FSTSW
FFREE ST0
FINCSTP
MOV RDX,RAX
XOR RAX,RAX
BT RDX,14
JC @@05
MOV RAX,1.0
BT RDX,8
JNC @@05
MOV RAX,-1.0
@@05: POP RBP
RET1 8
// ************************************
_ARG::
PUSH RBP
MOV RBP,RSP
FLD U64 SF_ARG2[RBP]
FLD U64 SF_ARG1[RBP]
@@05: FPATAN
FSTSW
TEST AX,0x400
JNZ @@05
FSTP U64 SF_ARG1[RBP]
MOV RAX,U64 SF_ARG1[RBP]
POP RBP
RET1 16
// ************************************
_ROUND::
PUSH RBP
MOV RBP,RSP
SUB RSP,8
FSTCW U16 -8[RBP]
MOV AX,U16 -8[RBP]
MOV U16 -6[RBP],AX
AND AX,~0x0C00
MOV U16 -8[RBP],AX
FLDCW U16 -8[RBP]
FLD U64 SF_ARG1[RBP]
FRNDINT
FSTP U64 SF_ARG1[RBP]
MOV RAX,U64 SF_ARG1[RBP]
FLDCW U16 -6[RBP]
LEAVE
RET1 8
// ************************************
_TRUNC::
PUSH RBP
MOV RBP,RSP
SUB RSP,8
FSTCW U16 -8[RBP]
MOV AX,U16 -8[RBP]
MOV U16 -6[RBP],AX
OR AX,0x0C00
MOV U16 -8[RBP],AX
FLDCW U16 -8[RBP]
FLD U64 SF_ARG1[RBP]
FRNDINT
FSTP U64 SF_ARG1[RBP]
MOV RAX,U64 SF_ARG1[RBP]
FLDCW U16 -6[RBP]
LEAVE
RET1 8
// ************************************
_FLOOR::
PUSH RBP
MOV RBP,RSP
SUB RSP,8
FSTCW U16 -8[RBP]
MOV AX,U16 -8[RBP]
MOV U16 -6[RBP],AX
AND AX,~0x0C00
OR AX,0x0400
MOV U16 -8[RBP],AX
FLDCW U16 -8[RBP]
FLD U64 SF_ARG1[RBP]
FRNDINT
FSTP U64 SF_ARG1[RBP]
MOV RAX,U64 SF_ARG1[RBP]
FLDCW U16 -6[RBP]
LEAVE
RET1 8
// ************************************
_CEIL::
PUSH RBP
MOV RBP,RSP
SUB RSP,8
FSTCW U16 -8[RBP]
MOV AX,U16 -8[RBP]
MOV U16 -6[RBP],AX
AND AX,~0x0C00
OR AX,0x0800
MOV U16 -8[RBP],AX
FLDCW U16 -8[RBP]
FLD U64 SF_ARG1[RBP]
FRNDINT
FSTP U64 SF_ARG1[RBP]
MOV RAX,SF_ARG1[RBP]
FLDCW U16 -6[RBP]
LEAVE
RET1 8
// ************************************
SYS_POW::
// RAX=RDX`RAX
PUSH RBP
MOV RBP,RSP
SUB RSP,24
TEST RAX,RAX //To power of zero?
JNZ @@05
MOV RAX,1.0
JMP @@20
@@05: TEST RDX,RDX //zero to a power?
JNZ @@10
XOR RAX,RAX
JMP @@20
@@10: MOV RCX,RAX //RCX=pow
MOV U64 -8[RBP],RDX
MOV U64 -16[RBP],RAX
FSTCW U16 -24[RBP]
MOV AX,U16 -24[RBP]
MOV U16 -22[RBP],AX
OR AX,0x0C00
MOV U16 -24[RBP],AX
FLDCW U16 -24[RBP]
FLD U64 -16[RBP]
FLD U64 -8[RBP]
FABS //base should be pos
FYL2X // y*log2(x)
FST U64 -8[RBP]
FRNDINT
FLD U64 -8[RBP]
FSUBRP ST1,ST0
F2XM1
FLD1
FADDP ST1,ST0
FSTP U64 -16[RBP]
FLD U64 -8[RBP]
FLD U64 -16[RBP]
FSCALE // ST0<<ST1
TEST RDX,RDX //was base neg?
JGE @@15
MOV U64 -16[RBP],RCX
FLD U64 -16[RBP]
FISTTP U64 -16[RBP]
TEST U64 -16[RBP],1
JZ @@15 //was pow odd?
FCHS
@@15: FSTP U64 -8[RBP]
FFREE ST0
FINCSTP
FLDCW U16 -22[RBP]
MOV RAX,U64 -8[RBP]
@@20: LEAVE
RET
// ************************************
_POW::
PUSH RBP
MOV RBP,RSP
MOV RAX,U64 SF_ARG2[RBP]
MOV RDX,U64 SF_ARG1[RBP]
CALL SYS_POW
POP RBP
RET1 16
// ************************************
_POW10::
PUSH RBP
MOV RBP,RSP
SUB RSP,16
FSTCW U16 -8[RBP]
MOV AX,U16 -8[RBP]
MOV U16 -6[RBP],AX
OR AX,0x0C00
MOV U16 -8[RBP],AX
FLDCW U16 -8[RBP]
FLDL2T
FLD U64 SF_ARG1[RBP]
FMULP ST1,ST0
FST U64 SF_ARG1[RBP]
FRNDINT
FLD U64 SF_ARG1[RBP]
FSUBRP ST1,ST0
F2XM1
FLD1
FADDP ST1,ST0
FSTP U64 -16[RBP]
FLD U64 SF_ARG1[RBP]
FLD U64 -16[RBP]
FSCALE // ST0<<ST1
FSTP U64 -16[RBP]
FFREE ST0
FINCSTP
FLDCW U16 -6[RBP]
MOV RAX,U64 -16[RBP]
LEAVE
RET1 8
// ************************************
_EXP::
PUSH RBP
MOV RBP,RSP
SUB RSP,16
FSTCW U16 -8[RBP]
MOV AX,U16 -8[RBP]
MOV U16 -6[RBP],AX
OR AX,0x0C00
MOV U16 -8[RBP],AX
FLDCW U16 -8[RBP]
FLDL2E
FLD U64 SF_ARG1[RBP]
FMULP ST1,ST0
FST U64 SF_ARG1[RBP]
FRNDINT
FLD U64 SF_ARG1[RBP]
FSUBRP ST1,ST0
F2XM1
FLD1
FADDP ST1,ST0
FSTP U64 -16[RBP]
FLD U64 SF_ARG1[RBP]
FLD U64 -16[RBP]
FSCALE // ST0<<ST1
FSTP U64 -16[RBP]
FFREE ST0
FINCSTP
FLDCW U16 -6[RBP]
MOV RAX,U64 -16[RBP]
LEAVE
RET1 8
// ************************************
_LOG10::
PUSH RBP
MOV RBP,RSP
FLDLG2
FLD U64 SF_ARG1[RBP]
FYL2X // y*log2(x)
FSTP U64 SF_ARG1[RBP]
MOV RAX,U64 SF_ARG1[RBP]
POP RBP
RET1 8
// ************************************
_LOG2::
PUSH RBP
MOV RBP,RSP
FLD1
FLD U64 SF_ARG1[RBP]
FYL2X // y*log2(x)
FSTP U64 SF_ARG1[RBP]
MOV RAX,U64 SF_ARG1[RBP]
POP RBP
RET1 8
// ************************************
_LN::
PUSH RBP
MOV RBP,RSP
FLDLN2
FLD U64 SF_ARG1[RBP]
FYL2X // y*log2(x)
FSTP U64 SF_ARG1[RBP]
MOV RAX,U64 SF_ARG1[RBP]
POP RBP
RET1 8
// ************************************
_FLDCW::
PUSH RBP
MOV RBP,RSP
FLDCW U16 SF_ARG1[RBP]
POP RBP
RET1 8
// ************************************
_FSTCW::
PUSH RBP
MOV RBP,RSP
SUB RSP,8
FSTCW U16 -8[RBP]
MOVZX RAX,U16 -8[RBP]
LEAVE
RET
// ************************************
_FSTSW::
XOR RAX,RAX
FSTSW
RET
// ************************************
_FCLEX::
FCLEX
RET
// ************************************
_FXSAVE::
PUSH RBP
MOV RBP,RSP
MOV RAX,U64 SF_ARG1[RBP]
FXSAVE U64 [RAX]
POP RBP
RET1 8
// ************************************
_FXRSTOR::
PUSH RBP
MOV RBP,RSP
MOV RAX,U64 SF_ARG1[RBP]
FXRSTOR U64 [RAX]
POP RBP
RET1 8
}
+178
View File
@@ -0,0 +1,178 @@
F64 Clamp(F64 num,F64 lo,F64 hi)
{
if (num<lo)
return lo;
if (num>hi)
return hi;
return num;
}
F64 Min(F64 n1,F64 n2)
{
if (n1<=n2)
return n1;
else
return n2;
}
F64 Max(F64 n1,F64 n2)
{
if (n1>=n2)
return n1;
else
return n2;
}
F64 Pow10I64(I64 i)
{
if (i>308)
return ì;
else if (i<-308)
return 0.0;
else
return pow10_I64[i+309];
}
U64 FloorU64(U64 num,U64 to)
{
return num-num%to;
}
U64 CeilU64(U64 num,U64 to)
{
num+=to-1;
return num-num%to;
}
I64 RoundI64(I64 num,I64 to)
{
return num-num%to;
}
I64 FloorI64(I64 num,I64 to)
{
if (num>=0)
return num-num%to;
else {
num++;
return num-num%to-to;
}
}
I64 CeilI64(I64 num,I64 to)
{
if (num>=0) {
num+=to-1;
return num-num%to;
} else {
num+=to-1;
return num-num%to-to;
}
}
//See $LK,"::/Doc/Acknowledgements.TXT"$.
U16 RandU16()
{
sys_rnd_seed.i32[0]=(1664525*sys_rnd_seed.i32[0]+1013904223)^GetTSC>>4;
return sys_rnd_seed.u16[0];
}
I16 RandI16()
{
sys_rnd_seed.i32[0]=(1664525*sys_rnd_seed.i32[0]+1013904223)^GetTSC>>4;
return sys_rnd_seed.i16[0];
}
U32 RandU32()
{
sys_rnd_seed.i32[0]=(1664525*sys_rnd_seed.i32[0]+1013904223)^GetTSC>>4;
return sys_rnd_seed.u32[0];
}
I32 RandI32()
{
sys_rnd_seed.i32[0]=(1664525*sys_rnd_seed.i32[0]+1013904223)^GetTSC>>4;
return sys_rnd_seed.i32[0];
}
U64 RandU64()
{
U64 result;
result.u32[0]=sys_rnd_seed.i32[0]=(1664525*sys_rnd_seed.i32[0]+1013904223)^GetTSC>>4;
result.u32[1]=sys_rnd_seed.i32[0]= 1664525*sys_rnd_seed.i32[0]+1013904223;
return result;
}
I64 RandI64()
{
I64 result;
result.u32[0]=sys_rnd_seed.i32[0]=(1664525*sys_rnd_seed.i32[0]+1013904223)^GetTSC>>4;
result.u32[1]=sys_rnd_seed.i32[0]= 1664525*sys_rnd_seed.i32[0]+1013904223;
return result;
}
F64 Rand()
{ //0.0<=x<1.0
I64 result;
result.u32[0]=sys_rnd_seed.i32[0]=(1664525*sys_rnd_seed.i32[0]+1013904223)^GetTSC>>4;
result.u32[1]=sys_rnd_seed.i32[0]= 1664525*sys_rnd_seed.i32[0]+1013904223;
result&=0x3FFFFFFFFFFFFFFF;
return result/ToF64(0x4000000000000000);
}
U16 Rand2U16()
{
Fs->rnd_seed.i32[0]=1664525*Fs->rnd_seed.i32[0]+1013904223;
return Fs->rnd_seed.u16[0];
}
I16 Rand2I16()
{
Fs->rnd_seed.i32[0]=1664525*Fs->rnd_seed.i32[0]+1013904223;
return Fs->rnd_seed.i16[0];
}
U32 Rand2U32()
{
Fs->rnd_seed.i32[0]=1664525*Fs->rnd_seed.i32[0]+1013904223;
return Fs->rnd_seed.u32[0];
}
I32 Rand2I32()
{
Fs->rnd_seed.i32[0]=1664525*Fs->rnd_seed.i32[0]+1013904223;
return Fs->rnd_seed.i32[0];
}
U64 Rand2U64()
{
U64 result;
result.u32[0]=Fs->rnd_seed.i32[0]= 1664525*Fs->rnd_seed.i32[0]+1013904223;
result.u32[1]=Fs->rnd_seed.i32[0]= 1664525*Fs->rnd_seed.i32[0]+1013904223;
return result;
}
I64 Rand2I64()
{
I64 result;
result.u32[0]=Fs->rnd_seed.i32[0]= 1664525*Fs->rnd_seed.i32[0]+1013904223;
result.u32[1]=Fs->rnd_seed.i32[0]= 1664525*Fs->rnd_seed.i32[0]+1013904223;
return result;
}
F64 Rand2()
{ //0.0<=x<1.0
I64 result;
result.u32[0]=Fs->rnd_seed.i32[0]= 1664525*Fs->rnd_seed.i32[0]+1013904223;
result.u32[1]=Fs->rnd_seed.i32[0]= 1664525*Fs->rnd_seed.i32[0]+1013904223;
result&=0x3FFFFFFFFFFFFFFF;
return result/ToF64(0x4000000000000000);
}
U0 Randomize(I64 seed=0)
{ //Randomizes seed.
if (seed)
Fs->rnd_seed=seed;
else
Fs->rnd_seed=GetTSC>>4;
}
+540
View File
@@ -0,0 +1,540 @@
asm {
/*
See $LK,"::/Doc/Acknowledgements.TXT"$.
See $LK,"::/Doc/Mem.TXT"$
*/
USE32
SYS_INIT_MEM::
//Set page tables to identity map everything.
MOV EDI,SYS_FIXED_AREA
XOR EAX,EAX
MOV ECX,sizeof(CSysFixedArea)/4
REP_STOSD
//PML1
MOV EAX,0x107
XOR EDX,EDX
MOV EDI,SYS_FIXED_AREA+CSysFixedArea.pml1
MOV ECX,MEM_NUM_PML1*0x200
@@05: MOV U32 [EDI],EAX
ADD EDI,4
MOV U32 [EDI],EDX
ADD EDI,4
ADD EAX,0x1000
ADC EDX,0
LOOP @@05
//video ram=write through
//0xA0000-0xBFFFF
MOV EAX,0xF
XOR EDX,EDX
MOV EDI,SYS_FIXED_AREA+CSysFixedArea.pml1+0xA0*8
MOV ECX,0xC0-0xA0
@@10: OR U32 [EDI],EAX
ADD EDI,4
OR U32 [EDI],EDX
ADD EDI,4
LOOP @@10
//PML2
MOV EAX,SYS_FIXED_AREA+CSysFixedArea.pml1+7
XOR EDX,EDX
MOV EDI,SYS_FIXED_AREA+CSysFixedArea.pml2
MOV ECX,MEM_NUM_PML1
@@15: MOV U32 [EDI],EAX
ADD EDI,4
MOV U32 [EDI],EDX
ADD EDI,4
ADD EAX,0x1000
ADC EDX,0
LOOP @@15
MOV EAX,MEM_NUM_PML1*0x200000+0x87 //bit 7 is page size (1==2Meg)
XOR EDX,EDX
MOV EDI,SYS_FIXED_AREA+CSysFixedArea.pml2+8*MEM_NUM_PML1
MOV ECX,MEM_NUM_PML2*0x200-MEM_NUM_PML1
@@20: MOV U32 [EDI],EAX
ADD EDI,4
MOV U32 [EDI],EDX
ADD EDI,4
ADD EAX,0x200000
ADC EDX,0
LOOP @@20
//PCI Devs
//0xE0000000-0xFFFFFFFF
MOV EAX,0x17 //Cache disabled
XOR EDX,EDX
MOV EDI,SYS_FIXED_AREA+CSysFixedArea.pml2+8*0x700
MOV ECX,0x800-0x700
@@25: OR U32 [EDI],EAX
ADD EDI,4
OR U32 [EDI],EDX
ADD EDI,4
LOOP @@25
//PML3
MOV EAX,SYS_FIXED_AREA+CSysFixedArea.pml2+7
XOR EDX,EDX
MOV EDI,SYS_FIXED_AREA+CSysFixedArea.pml3
MOV ECX,MEM_NUM_PML2
@@30: MOV U32 [EDI],EAX
ADD EDI,4
MOV U32 [EDI],EDX
ADD EDI,4
ADD EAX,0x1000
ADC EDX,0
LOOP @@30
//PML4
MOV EAX,SYS_FIXED_AREA+CSysFixedArea.pml3+7
XOR EDX,EDX
MOV EDI,SYS_FIXED_AREA+CSysFixedArea.pml4
MOV ECX,MEM_NUM_PML3
@@35: MOV U32 [EDI],EAX
ADD EDI,4
MOV U32 [EDI],EDX
ADD EDI,4
ADD EAX,0x1000
ADC EDX,0
LOOP @@35
MOV U32 [SYS_CODE_BP],SYS_FIXED_AREA+CSysFixedArea.adam_bp
MOV U32 [SYS_CODE_BP+4],0
MOV U32 [SYS_DATA_BP],0
MOV U32 [SYS_DATA_BP+4],0
XOR EAX,EAX
MOV AX,U16 [SYS_MEM_E801] //1 Kb blks between 1M and 16M
SHL EAX,10
ADD EAX,0x100000
MOV EBX,U32 [SYS_HEAP_BASE] //SYS_FIXED_AREA+sizeof(CSysFixedArea)
SUB EAX,EBX
/*$AN,"ExpandHeap",A="ExpandHeap"$
TempleOS initializes the heap to the val
of the BIOS E801 lowest 16Meg val. It
later adds the rest to the heap. There
are a few allocations which occur while
it is set to this small val.
At some point, it might be nice to
initialize to the full val but it is a
pain without MAlloc up-and-running.
*/
#define CONSERVATIVE_16MEG_SIZE 0xF00000
#define ESTIMATED_MISC_ALLOCS 0x100000
#assert CONSERVATIVE_16MEG_SIZE-(SYS_FIXED_AREA+sizeof(CSysFixedArea))>ADAM_STK+ESTIMATED_MISC_ALLOCS
//EBX=BASE EAX=SIZE
TEST U8 [SYS_MEM_INIT_FLAG],1
JZ @@40
PUSH EAX
MOV EDI,EBX
MOV ECX,EAX
MOV AL,U8 [SYS_MEM_INIT_VAL]
REP_STOSB
POP EAX
@@40: SHR EAX,PAGE_BITS
MOV ESI,SYS_FIXED_AREA+CSysFixedArea.adam_bp
MOV EDI,U32 CBlkPool.mem_free_lst[ESI]
MOV U32 CMemBlk.next[EBX],EDI
MOV U32 CMemBlk.next+4[EBX],0
MOV U32 CBlkPool.mem_free_lst[ESI],EBX
MOV U32 CBlkPool.mem_free_lst+4[ESI],0
MOV U32 CMemBlk.mb_signature[EBX],MBS_UNUSED_SIGNATURE_VAL
MOV U32 CMemBlk.pages[EBX],EAX
ADD U32 CBlkPool.size[ESI],EAX
RET
}
U0 SysBadFree(I64 *ptr)
{
Dbg("Bad Free:",ptr);
}
U0 SysBadMAlloc(I64 *ptr)
{
Dbg("Bad MAlloc:",ptr);
}
I64 MemPageSize(U8 *a)
{
if (a<MEM_NUM_PML1*0x1000*0x200)
return 0x1000;
else
return 0x200000;
}
I64 *MemPageTable(U8 *a)
{
if (a<MEM_NUM_PML1*0x1000*0x200)
return SYS_FIXED_AREA+offset(CSysFixedArea.pml1)+a>>12*8;
else
return SYS_FIXED_AREA+offset(CSysFixedArea.pml2)+a>>21*8;
}
Bool MemPagePresentMark(U8 *a,Bool val)
{
I64 *pte=MemPageTable(a);
Bool result=*pte&1;
if (val)
*pte=*pte|1; //Mark present
else
*pte=*pte&~1; //Mark not present
InvlPg(a);
return result;
}
U8 *MemBlksIndependentAlloc(I64 *_pages512,CBlkPool *bp=NULL)
//This will allocate a 512 byte pages from
//and not link them to any task. (Linking to a task
//means it will be freed when the task
//dies.)
//It might give you more than you asked for
//so a ptr to a page count is passed.
//
//Returns NULL if out of memory
{
CMemBlk *result=NULL,*m;
I64 i,num=*_pages512;
if (!bp) bp=sys_code_bp;
PUSHFD
CLI
while (LBts(&bp->locked_flags,BPlf_LOCKED))
PAUSE
if (num<FREE_PAGE_HASH_SIZE) {
if (result=bp->free_page_hash[num]) {
bp->free_page_hash[num]=result->next;
goto at_done;
}
i=Bsr(FREE_PAGE_HASH_SIZE)+1;
} else {
//We'll now round-up to a power of two.
//There is some overhead on allocations and
//we wouldn't want to round to the next
//power of two if a power of two was requested.
//So we use a little more than a power of two.
num-=2;
i=Bsr(num)+1;
num=1<<i+2;
if (result=bp->free_page_hash2[i]) {
bp->free_page_hash2[i]=result->next;
goto at_done;
}
}
m=&bp->mem_free_lst;
while (TRUE) {
if (!(result=m->next)) {
//We're probably out of luck, but lets search for a
//freed larger size block... and, screw-it, return the whole thing.
do {
if (result=bp->free_page_hash2[++i]) {
num=1<<i+2;
bp->free_page_hash2[i]=result->next;
goto at_done;
}
} while (i<64-PAGE_BITS-1);
num=0;
result=NULL; //Out of memory
goto at_done;
}
if (result->pages<num)
m=result;
else {
if (result->pages==num) {
m->next=result->next;
goto at_done;
} else {
result->pages-=num;
result(U8 *)+=result->pages<<PAGE_BITS;
result->pages=num;
goto at_done;
}
}
}
at_done:
*_pages512=num;
bp->allocated_u8s+=num<<PAGE_BITS;
LBtr(&bp->locked_flags,BPlf_LOCKED);
POPFD
return result;
}
U0 MemBlksNonTaskFree(CMemBlk *m,I64 pages512,CBlkPool *bp=NULL)
{
I64 i;
if (m) {
if (!bp) bp=sys_code_bp;
PUSHFD
CLI
while (LBts(&bp->locked_flags,BPlf_LOCKED))
PAUSE
m->mb_signature=MBS_UNUSED_SIGNATURE_VAL;
m->pages=pages512;
bp->allocated_u8s-=pages512<<PAGE_BITS;
if (pages512<FREE_PAGE_HASH_SIZE) {
m->next=bp->free_page_hash[pages512];
bp->free_page_hash[pages512]=m;
} else {
//We'll now round-up to a power of two.
//There is some overhead on allocations and
//we wouldn't want to round to the next
//power of two if a power of two was requested.
//So we use a little more than a power of two.
pages512-=2;
i=Bsr(pages512);
m->next=bp->free_page_hash2[i];
bp->free_page_hash2[i]=m;
}
LBtr(&bp->locked_flags,BPlf_LOCKED);
POPFD
}
}
U8 *MemBlks2MegAlloc(I64 *_pages2Meg,CBlkPool *bp=NULL)
//This will allocate 2Meg pages and not
//link it to any task. (Linking to a task
//means they will be freed when the task
//dies.)
//It might give you more than you asked for
//so a ptr to a page count is passed.
//
//Returns NULL if out of memory
{
I64 i,j,*pte,num=*_pages2Meg;
CMemBlk *result=NULL,*m,*m1;
if (!bp) bp=sys_code_bp;
PUSHFD
CLI
while (LBts(&bp->locked_flags,BPlf_LOCKED))
PAUSE
num<<=21-PAGE_BITS;
m=&bp->mem_free_2meg_lst;
while (TRUE) {
if (!(result=m->next))
break;
if (result->pages<num)
m=result;
else {
if (result->pages==num) {
m->next=result->next;
goto am_done;
} else {
result->pages-=num;
result(U8 *)+=result->pages<<PAGE_BITS;
result->pages=num;
goto am_done;
}
}
}
m=&bp->mem_free_lst;
while (TRUE) {
if (!(result=m->next)) {
num=0;
result=NULL; //Out of memory
goto am_done;
}
if (result->pages<num)
m=result;
else {
if (result->pages==num) {
if (result(U8 *)&0x1FFFFF)
m=result;
else {
m->next=result->next;
goto am_done;
}
} else {
if (i=(result(U8 *)&0x1FFFFF)>>PAGE_BITS) {
j=1<<(21-PAGE_BITS)-i;
if (result->pages<num+j)
m=result;
else if (result->pages==num+j) {
result->pages-=num;
result(U8 *)+=result->pages<<PAGE_BITS;
result->pages=num;
goto am_done;
} else {
m1=result;
result(U8 *)+=j<<PAGE_BITS;
result->pages=num;
m=result(U8 *)+num<<PAGE_BITS;
m->pages=m1->pages-num-j;
m1->pages=j;
m->next=m1->next;
m1->next=m;
m->mb_signature=MBS_UNUSED_SIGNATURE_VAL;
goto am_done;
}
} else {
m=m->next=result(U8 *)+num<<PAGE_BITS;
m->next=result->next;
m->pages=result->pages-num;
m->mb_signature=MBS_UNUSED_SIGNATURE_VAL;
result->pages=num;
goto am_done;
}
}
}
}
am_done:
i=num<<PAGE_BITS;
bp->allocated_u8s+=i;
num>>=21-PAGE_BITS;
*_pages2Meg=num;
m=result;
m1=m(U8 *)+i;
while (m<m1) {
pte=MemPageTable(m);
*pte &= ~0x18;
InvlPg(m);
m(U8 *)+=MemPageSize(m);
}
LBtr(&bp->locked_flags,BPlf_LOCKED);
POPFD
return result;
}
U8 *MemBlksUncachedAlloc(I64 *_pages2Meg,CBlkPool *bp=NULL)
//This will allocate 2Meg pages from
//and not link them to any task. (Linking to a task
//means it will be freed when the task
//dies.) It will be marked uncached.
//It might give you more than you asked for
//so a ptr to a page count is passed.
//
//Returns NULL if out of memory
{
CMemBlk *result,*m,*m1;
I64 num=*_pages2Meg,*pte;
if (result=MemBlks2MegAlloc(_pages2Meg,bp)) {
num=*_pages2Meg;
m=result;
m1=m(U8 *)+num<<21;
while (m<m1) {
pte=MemPageTable(m);
*pte= *pte& ~0x18 |0x10;
InvlPg(m);
m(U8 *)+=MemPageSize(m);
}
}
return result;
}
U8 *MemBlksWriteThroughAlloc(I64 *_pages2Meg,CBlkPool *bp=NULL)
//This will allocate 2Meg pages from
//and not link them to any task. (Linking to a task
//means they will be freed when the task
//dies.) It will be marked write-through.
//It might give you more than you asked for
//so a ptr to a page count is passed.
//
//Returns NULL if out of memory
{
CMemBlk *result,*m,*m1;
I64 num=*_pages2Meg,*pte;
if (result=MemBlks2MegAlloc(_pages2Meg,bp)) {
num=*_pages2Meg;
m=result;
m1=m(U8 *)+num<<21;
while (m<m1) {
pte=MemPageTable(m);
*pte= *pte& ~0x18 |8;
InvlPg(m);
m(U8 *)+=MemPageSize(m);
}
}
return result;
}
U0 MemBlks2MegFree(CMemBlk *m,I64 pages2Meg,CBlkPool *bp=NULL)
{
I64 *pte;
CMemBlk *m1,*m2;
if (m) {
if (!bp) bp=sys_code_bp;
m2=m;
m1=m(U8 *)+pages2Meg<<21;
while (m2<m1) {
pte=MemPageTable(m2);
*pte=*pte & ~0x18;
InvlPg(m2);
m2(U8 *)+=MemPageSize(m2);
}
PUSHFD
CLI
while (LBts(&bp->locked_flags,BPlf_LOCKED))
PAUSE
m->mb_signature=MBS_UNUSED_SIGNATURE_VAL;
m->pages=pages2Meg<<(21-PAGE_BITS);
bp->allocated_u8s-=pages2Meg<<21;
m->next=bp->mem_free_2meg_lst;
bp->mem_free_2meg_lst=m;
LBtr(&bp->locked_flags,BPlf_LOCKED);
POPFD
}
}
CMemBlk *MemBlksAlloc(I64 *_pages512,CHeapCtrl *hc)
{
//hc must be locked. Interrupts should probably be off
//Currently, this is only called from $LK,"MAlloc",A="MN:MAlloc"$().
//
//Returns NULL if out of memory
CMemBlk *result;
I64 threshold,cnt,size;
CMemUnusedAllocated *uum,**_uum,**_ptr;
if (result=MemBlksIndependentAlloc(_pages512,hc->bp)) {
QueIns(result,hc->last_mem_blk);
result->mb_signature=MBS_USED_SIGNATURE_VAL;
//Tidy-up free lst (Move into heap hash)
//because if free lst gets long, delay causes crash
threshold=HEAP_HASH_SIZE>>4;
#assert HEAP_HASH_SIZE>>4>=sizeof(U8 *)
do {
cnt=0;
_uum=&hc->malloc_free_lst;
while (uum=*_uum) {
#assert !offset(CMemUnusedAllocated.next)
size=uum->size;
if (size<threshold) {
*_uum=uum->next;
_ptr=(&hc->heap_hash)(U8 *)+size;
uum->next=*_ptr;
*_ptr=uum;
} else {
cnt++;
_uum=uum;
}
}
threshold<<=1;
} while (cnt>8 && threshold<=HEAP_HASH_SIZE);
}
return result;
}
U0 MemBlksFree(CMemBlk *m,CHeapCtrl *hc)
{ //hc must be locked
if (m) {
PUSHFD
CLI
if (m->mb_signature!=MBS_USED_SIGNATURE_VAL)
SysBadFree(m);
else {
QueRem(m);
MemBlksNonTaskFree(m,m->pages,hc->bp);
}
POPFD
}
}
+450
View File
@@ -0,0 +1,450 @@
asm {
USE64
// ************************************
// Throws 'OutMem'
_MALLOC::
PUSH RBP
MOV RBP,RSP
PUSH RSI
PUSH RDI
XOR RBX,RBX
MOV RDX,U64 SF_ARG2[RBP]
TEST RDX,RDX
JNZ @@05
MOV RDX,U64 FS:CTask.addr[RBX]
@@05: CMP U32 CTask.task_signature[RDX],TASK_SIGNATURE_VAL
#assert CTask.task_signature==CHeapCtrl.hc_signature //location of signature matches
JNE @@10
MOV RDX,U64 CTask.data_heap[RDX]
@@10: CMP U32 CHeapCtrl.hc_signature[RDX],HEAP_CTRL_SIGNATURE_VAL
JE @@15
PUSH RDX
CALL &SysBadMAlloc
JMP I32 _SYS_HLT
@@15: MOV RAX,U64 SF_ARG1[RBP]
PUSHFD
ADD RAX,CMemUsedAllocated.start+7 //round-up to I64
AND AL,0xF8
#assert CMemUsedAllocated.start>=sizeof(CMemUnusedAllocated)
CMP RAX,CMemUsedAllocated.start
JAE @@20
MOV RAX,CMemUsedAllocated.start
@@20:
CLI
@@25: LOCK
BTS U32 CHeapCtrl.locked_flags[RDX],HClf_LOCKED
PAUSE //don't know if this instruction helps
JC @@25
CMP RAX,HEAP_HASH_SIZE
JAE @@30
MOV RSI,U64 CHeapCtrl.heap_hash[RAX+RDX]
TEST RSI,RSI
JZ @@35
MOV RCX,U64 CMemUnusedAllocated.next[RSI]
MOV U64 CHeapCtrl.heap_hash[RAX+RDX],RCX
JMP I32 MALLOC_ALMOST_DONE
//Big allocation
@@30: ADD RAX,sizeof(CMemBlk)+PAGE_SIZE-1
SHR RAX,PAGE_BITS
PUSH RDX //preserve heap ctrl
PUSH RAX //num blks (we must pass address of this)
MOV RAX,RSP
PUSH RDX
PUSH RAX //addr of num blks
CALL &MemBlksAlloc
MOV RSI,RAX
POP RAX //blks that were allocated
POP RDX
TEST RSI,RSI
JZ @@45 //Out of memory
SHL RAX,PAGE_BITS
SUB RAX,sizeof(CMemBlk)
ADD RSI,sizeof(CMemBlk)
JMP I32 MALLOC_ALMOST_DONE
//Little allocation, chunk-off piece from free lst chunks
@@35: LEA RSI,U64 CHeapCtrl.malloc_free_lst-CMemUnusedAllocated.next[RDX]
@@40: MOV RBX,RSI
MOV RSI,U64 CMemUnusedAllocated.next[RBX]
TEST RSI,RSI
JNZ @@55
PUSH RAX //-**** save byte size
ADD RAX,16*PAGE_SIZE-1
SHR RAX,PAGE_BITS
PUSH RDX //preserve heap ctrl
PUSH RAX //num blks (we must pass address of this)
MOV RAX,RSP
PUSH RDX
PUSH RAX //addr of num blks
CALL &MemBlksAlloc
MOV RSI,RAX
POP RAX //blks that were allocated
POP RDX
TEST RSI,RSI
JNZ @@50
//Out of memory
@@45: LOCK
BTR U32 CHeapCtrl.locked_flags[RDX],HClf_LOCKED
POPFD
PUSH TRUE
MOV RAX,'OutMem'
PUSH RAX
CALL I32 &throw
JMP I32 MALLOC_FINAL_EXIT //Never gets here, hopefully.
@@50: LEA RSI,U64 sizeof(CMemBlk)[RSI]
SHL RAX,PAGE_BITS
SUB RAX,sizeof(CMemBlk)
LEA RBX,U64 CHeapCtrl.malloc_free_lst-CMemUnusedAllocated.next[RDX]
MOV RDI,U64 CMemUnusedAllocated.next[RBX]
MOV U64 CMemUnusedAllocated.next[RSI],RDI
MOV U64 CMemUnusedAllocated.size[RSI],RAX
MOV U64 CMemUnusedAllocated.next[RBX],RSI
POP RAX //+****
JMP @@65
@@55: CMP U64 CMemUnusedAllocated.size[RSI],RAX
JB @@40
JNE @@65
@@60: MOV RDI,U64 CMemUnusedAllocated.next[RSI]
MOV U64 CMemUnusedAllocated.next[RBX],RDI
JMP MALLOC_ALMOST_DONE
@@65: SUB U64 CMemUnusedAllocated.size[RSI],RAX //UPDATE FREE ENTRY
CMP U64 CMemUnusedAllocated.size[RSI],sizeof(CMemUnusedAllocated)
JAE @@70 //take from top of block
ADD U64 CMemUnusedAllocated.size[RSI],RAX //doesn't fit, undo
JMP I32 @@40
@@70: ADD RSI,U64 CMemUnusedAllocated.size[RSI]
MALLOC_ALMOST_DONE:
//RSI=result-CMemUsedAllocated.size
//RAX=size+CMemUsedAllocated.size
//RDX=heap ctrl
ADD U64 CHeapCtrl.used_u8s[RDX],RAX
#if _CFG_HEAP_DBG
//QueIns
MOV RDI,U64 CHeapCtrl.last_um[RDX]
MOV U64 CMemUsedAllocated.next[RDI],RSI
MOV U64 CHeapCtrl.last_um[RDX],RSI
MOV U64 CMemUsedAllocated.last[RSI],RDI
LEA RDI,U64 CHeapCtrl.next_um-CMemUsedAllocated.next[RDX]
MOV U64 CMemUsedAllocated.next[RSI],RDI
//Caller1/Caller2
PUSH RDX
MOV RDX,U64 [SYS_HEAP_LIMIT]
MOV RDI,U64 SF_RIP[RBP]
CMP RDI,RDX
JB @@75
XOR RDI,RDI
MOV U64 CMemUsedAllocated.caller1[RSI],RDI
JMP @@85
@@75: MOV U64 CMemUsedAllocated.caller1[RSI],RDI
MOV RDI,U64 SF_RBP[RBP]
CMP RDI,RDX
JB @@80
XOR RDI,RDI
JMP @@85
@@80: MOV RDI,U64 SF_RIP[RDI]
CMP RDI,RDX
JB @@85
XOR RDI,RDI
@@85: MOV U64 CMemUsedAllocated.caller2[RSI],RDI
POP RDX
#endif
LOCK
BTR U32 CHeapCtrl.locked_flags[RDX],HClf_LOCKED
POPFD
MOV U64 CMemUsedAllocated.size[RSI],RAX
MOV U64 CMemUsedAllocated.hc[RSI],RDX
LEA RAX,U64 CMemUsedAllocated.start[RSI]
TEST U8 [SYS_SEMAS+SYS_SEMA_HEAPLOG_ACTIVE*SEMA_STRUCT_SIZE],1
JZ @@100
PUSH RAX
PUSH RAX
MOV RAX,U64 [SYS_EXTERN_TABLE]
MOV RAX,U64 EXT_HEAPLOG_MALLOC*8[RAX]
TEST RAX,RAX
JZ @@90
CALL RAX
JMP @@95
@@90: ADD RSP,8
@@95: POP RAX
@@100: TEST U8 [SYS_HEAP_INIT_FLAG],1
JZ MALLOC_FINAL_EXIT
PUSH RAX
MOV RCX,U64 CMemUsedAllocated.size-CMemUsedAllocated.start[RAX]
SUB RCX,CMemUsedAllocated.start
MOV RDI,RAX
MOV AL,U8 [SYS_HEAP_INIT_VAL]
REP_STOSB
POP RAX
MALLOC_FINAL_EXIT:
POP RDI
POP RSI
POP RBP
RET1 16
// ************************************
_FREE::
//Be aware of $LK,"heap_hash",A="FF:::/Kernel/Mem1b.CPP,heap_hash"$ in $LK,"MemBlksAlloc",A="MN:MemBlksAlloc"$().
PUSH RBP
MOV RBP,RSP
PUSH RSI
PUSH RDI
TEST U8 [SYS_SEMAS+SYS_SEMA_HEAPLOG_ACTIVE*SEMA_STRUCT_SIZE],1
JZ @@15
MOV RBX,U64 SF_ARG1[RBP]
TEST RBX,RBX
JZ @@05
MOV RAX,U64 CMemUsedAllocated.size-CMemUsedAllocated.start[RBX]
TEST RAX,RAX
JGE @@05 //Aligned alloced chunks have neg size
ADD RBX,RAX
@@05: PUSH RBX
MOV RAX,U64 [SYS_EXTERN_TABLE]
MOV RAX,U64 EXT_HEAPLOG_FREE*8[RAX]
TEST RAX,RAX
JZ @@10
CALL RAX
JMP @@15
@@10: ADD RSP,8
@@15: MOV RSI,U64 SF_ARG1[RBP]
TEST RSI,RSI
#if _CFG_HEAP_DBG
JZ I32 FREE_DONE
#else
JZ FREE_DONE
#endif
MOV RAX,U64 CMemUsedAllocated.size-CMemUsedAllocated.start[RSI]
TEST RAX,RAX
JGE @@20 //Aligned alloced chunks have neg size.
//The neg size is offset to start of $LK,"CMemUsedAllocated",A="MN:CMemUsedAllocated"$ struct.
ADD RSI,RAX
@@20: PUSHFD
SUB RSI,CMemUsedAllocated.start
MOV RDX,U64 CMemUsedAllocated.hc[RSI]
CMP U32 CHeapCtrl.hc_signature[RDX],HEAP_CTRL_SIGNATURE_VAL
JE @@25
ADD RSI,CMemUsedAllocated.start
PUSH RSI
CALL &SysBadFree
JMP I32 _SYS_HLT
@@25: MOV RAX,U64 CMemUsedAllocated.size[RSI]
SUB U64 CHeapCtrl.used_u8s[RDX],RAX
CLI
@@30: LOCK
BTS U32 CHeapCtrl.locked_flags[RDX],HClf_LOCKED
PAUSE
JC @@30
#if _CFG_HEAP_DBG
//QueRem
MOV RDX,U64 CMemUsedAllocated.next[RSI]
MOV RDI,U64 CMemUsedAllocated.last[RSI]
MOV U64 CMemUsedAllocated.last[RDX],RDI
MOV U64 CMemUsedAllocated.next[RDI],RDX
//Caller1/Caller2
MOV RDX,U64 [SYS_HEAP_LIMIT]
MOV RDI,U64 SF_RIP[RBP]
CMP RDI,RDX
JB @@35
XOR RDI,RDI
MOV U64 CMemUnusedAllocated.caller1[RSI],RDI
JMP @@45
@@35: MOV U64 CMemUnusedAllocated.caller1[RSI],RDI
MOV RDI,U64 SF_RBP[RBP]
CMP RDI,RDX
JB @@40
XOR RDI,RDI
JMP @@45
@@40: MOV RDI,U64 SF_RIP[RDI]
CMP RDI,RDX
JB @@45
XOR RDI,RDI
@@45: MOV U64 CMemUnusedAllocated.caller2[RSI],RDI
MOV RDX,U64 CMemUsedAllocated.hc[RSI]
#endif
CMP RAX,HEAP_HASH_SIZE
JAE @@50
#assert CMemUnusedAllocated.size==CMemUsedAllocated.size
// MOV U64 CMemUnusedAllocated.size[RSI],RAX
MOV RBX,U64 CHeapCtrl.heap_hash[RAX+RDX]
MOV U64 CMemUnusedAllocated.next[RSI],RBX
MOV U64 CHeapCtrl.heap_hash[RAX+RDX],RSI
JMP @@55
@@50: SUB RSI,sizeof(CMemBlk)
PUSH RDX
PUSH RDX
PUSH RSI
CALL &MemBlksFree
POP RDX
@@55: LOCK
BTR U32 CHeapCtrl.locked_flags[RDX],HClf_LOCKED
POPFD
FREE_DONE:
POP RDI
POP RSI
POP RBP
RET1 8
// ************************************
_MSIZE::
PUSH RBP
MOV RBP,RSP
MOV RBX,U64 SF_ARG1[RBP]
XOR RAX,RAX
TEST RBX,RBX
JZ @@10
MOV RAX,U64 CMemUsedAllocated.size-CMemUsedAllocated.start[RBX]
TEST RAX,RAX
JGE @@05 //Aligned alloced chunks have neg size
ADD RBX,RAX
MOV RAX,U64 CMemUsedAllocated.size-CMemUsedAllocated.start[RBX]
@@05: SUB RAX,CMemUsedAllocated.start
@@10: POP RBP
RET1 8
// ************************************
_MSIZE2::
PUSH RBP
MOV RBP,RSP
MOV RBX,U64 SF_ARG1[RBP]
XOR RAX,RAX
TEST RBX,RBX
JZ @@10
MOV RAX,U64 CMemUsedAllocated.size-CMemUsedAllocated.start[RBX]
TEST RAX,RAX
JGE @@05 //Aligned alloced chunks have neg size
ADD RBX,RAX
@@05: MOV RAX,U64 CMemUsedAllocated.size-CMemUsedAllocated.start[RBX]
@@10: POP RBP
RET1 8
// ************************************
_MHEAP_CTRL::
PUSH RBP
MOV RBP,RSP
MOV RBX,U64 SF_ARG1[RBP]
XOR RAX,RAX
TEST RBX,RBX
JZ @@10
MOV RAX,U64 CMemUsedAllocated.size-CMemUsedAllocated.start[RBX]
TEST RAX,RAX
JGE @@05 //Aligned alloced chunks have neg size
ADD RBX,RAX
@@05: MOV RAX,U64 CMemUsedAllocated.hc-CMemUsedAllocated.start[RBX]
@@10: POP RBP
RET1 8
}
_extern _FREE U0 Free(U8 *addr);
_extern _MSIZE I64 MSize(U8 *src); //size of heap object
_extern _MSIZE2 I64 MSize2(U8 *src); //Internal size
_extern _MHEAP_CTRL CHeapCtrl *MHeapCtrl(U8 *src); //$LK,"CHeapCtrl",A="MN:CHeapCtrl"$ of object
//Accepts a $LK,"CTask",A="MN:CTask"$ or $LK,"CHeapCtrl",A="MN:CHeapCtrl"$. NULL allocs off current task's heap.
_extern _MALLOC U8 *MAlloc(I64 size,CTask *mem_task=NULL);
U8 *AMAlloc(I64 size)
{
return MAlloc(size,adam_task);
}
U8 *CAlloc(I64 size,CTask *mem_task=NULL)
{//Accepts a $LK,"CTask",A="MN:CTask"$ or $LK,"CHeapCtrl",A="MN:CHeapCtrl"$. NULL allocs off current task's heap.
U8 *result=MAlloc(size,mem_task);
MemSet(result,0,size);
return result;
}
U8 *ACAlloc(I64 size)
{
return CAlloc(size,adam_task);
}
U8 *MAllocIdentical(U8 *src,CTask *mem_task=NULL)
{//Accepts a $LK,"CTask",A="MN:CTask"$ or $LK,"CHeapCtrl",A="MN:CHeapCtrl"$. NULL allocs off current task's heap.
U8 *result;
I64 size;
if (!src) return NULL;
size=MSize(src);
result=MAlloc(size,mem_task);
MemCpy(result,src,size);
return result;
}
U8 *AMAllocIdentical(U8 *src)
{
return MAllocIdentical(src,adam_task);
}
U8 *MAllocAligned(I64 size,I64 alignment,CTask *mem_task=NULL,I64 misalignment=0)
{ //only powers of two alignment. This is awful.
I64 mask=alignment-1;
U8 *ptr=MAlloc(size+mask+sizeof(I64)+misalignment,mem_task),
*result=(ptr+sizeof(I64)+mask)&~mask+misalignment;
result(I64 *)[-1]=ptr-result;
#assert offset(CMemUsedAllocated.size)==offset(CMemUsedAllocated.start)-sizeof(I64)
return result;
}
U8 *CAllocAligned(I64 size,I64 alignment,CTask *mem_task=NULL,I64 misalignment=0)
{ //only powers of two alignment. This is awful.
I64 mask=alignment-1;
U8 *ptr=MAlloc(size+mask+sizeof(I64)+misalignment,mem_task),
*result=(ptr+sizeof(I64)+mask)&~mask+misalignment;
result(I64 *)[-1]=ptr-result;
#assert offset(CMemUsedAllocated.size)==offset(CMemUsedAllocated.start)-sizeof(I64)
MemSet(result,0,size);
return result;
}
U8 *StrNew(U8 *buf,CTask *mem_task=NULL)
{//Accepts a $LK,"CTask",A="MN:CTask"$ or $LK,"CHeapCtrl",A="MN:CHeapCtrl"$. NULL allocs off current task's heap.
U8 *result;
I64 size;
if (buf) {
size=StrLen(buf)+1;
result=MAlloc(size,mem_task);
MemCpy(result,buf,size);
} else {
result=MAlloc(1,mem_task);
*result=0;
}
return result;
}
U8 *AStrNew(U8 *buf)
{
return StrNew(buf,adam_task);
}
+313
View File
@@ -0,0 +1,313 @@
U0 BlkPoolAdd(CBlkPool *bp,CMemBlk *m,I64 pages512)
{
if (sys_mem_init_flag)
MemSet(m,sys_mem_init_val,pages512*512);
PUSHFD
CLI
while (LBts(&bp->locked_flags,BPlf_LOCKED))
PAUSE
m->next=bp->mem_free_lst;
m->pages=pages512;
m->mb_signature=MBS_UNUSED_SIGNATURE_VAL;
bp->size+=pages512;
bp->mem_free_lst=m;
LBtr(&bp->locked_flags,BPlf_LOCKED);
POPFD
}
U0 BlkPoolInit(CBlkPool *bp,I64 pages512)
{
I64 num;
CMemBlk *m;
MemSet(bp,0,sizeof(CBlkPool));
m=(bp(U8 *)+sizeof(CBlkPool)+PAGE_SIZE-1)&~(PAGE_SIZE-1);
num=(bp(U8 *)+pages512<<PAGE_BITS-m(U8 *))>>PAGE_BITS;
bp->size=pages512-num; //compensate before num added.
BlkPoolAdd(bp,m,num);
}
CHeapCtrl *HeapCtrlInit(CHeapCtrl *hc=NULL,CTask *task=NULL,CBlkPool *bp)
{
//$LK,"Adam Task",A="FF:::/Kernel/KStart.CPP,CHeapCtrl.bp"$
if (!hc)
hc=ACAlloc(sizeof(CHeapCtrl));
hc->hc_signature=HEAP_CTRL_SIGNATURE_VAL;
hc->mem_task=task;
hc->bp=bp;
QueInit(&hc->next_mem_blk);
hc->next_um=hc->last_um=(&hc->next_um)(U8 *)-offset(CMemUsedAllocated.next);
return hc;
}
CHeapCtrl *HeapCtrlBPInit(CBlkPool *bp,I64 pages512)
{
I64 num;
CMemBlk *m;
CHeapCtrl *hc;
MemSet(bp,0,sizeof(CBlkPool)+sizeof(CHeapCtrl));
hc=HeapCtrlInit(bp(U8 *)+sizeof(CBlkPool),,bp);
m=(bp(U8 *)+sizeof(CBlkPool)+sizeof(CHeapCtrl)+PAGE_SIZE-1)&~(PAGE_SIZE-1);
num=(bp(U8 *)+pages512<<PAGE_BITS-m(U8 *))>>PAGE_BITS;
bp->size=pages512-num;
BlkPoolAdd(bp,m,num);
return hc;
}
U0 HeapCtrlDel(CHeapCtrl *hc)
{
CMemBlk *m,*m1;
if (hc) {
PUSHFD
CLI
while (LBts(&hc->locked_flags,HClf_LOCKED))
PAUSE
m=hc->next_mem_blk;
while (m!=&hc->next_mem_blk) {
m1=m->next;
MemBlksFree(m,hc);
m=m1;
}
LBtr(&hc->locked_flags,HClf_LOCKED);
POPFD
Free(hc);
}
}
Bool Mem32DevIns(CMemRange *tempmr)
{
CMemRange *tempmr1=sys_mem32_dev_root.next,*tempmr2;
while (tempmr1!=&sys_mem32_dev_root) {
if (!tempmr1->type && tempmr->base>=tempmr1->base &&
tempmr->base+tempmr->size<=tempmr1->base+tempmr1->size) {
if (tempmr->base>tempmr1->base) {
tempmr2=AMAlloc(sizeof(CMemRange));
tempmr2->type=MRT_UNUSED;
tempmr2->flags=0;
tempmr2->base=tempmr1->base;
tempmr2->size=tempmr->base-tempmr1->base;
QueInsRev(tempmr2,tempmr1);
}
QueInsRev(tempmr,tempmr1);
tempmr1->size=tempmr1->base+tempmr1->size-
(tempmr->base+tempmr->size);
tempmr1->base=tempmr->base+tempmr->size;
if (!tempmr1->size) {
QueRem(tempmr1);
Free(tempmr1);
}
return TRUE;
}
tempmr1=tempmr1->next;
}
return FALSE;
}
U0 Mem32DevInit()
{
CMemRange *tempmr;
CMemE820 *m20=SYS_MEM_E820;
QueInit(&sys_mem32_dev_root);
tempmr=AMAlloc(sizeof(CMemRange));
tempmr->type=MRT_UNUSED;
tempmr->flags=0;
//Maybe !!! Change this to 0xE0000000 !!!
tempmr->base=0xF0000000;
tempmr->size=0x10000000;
QueIns(tempmr,sys_mem32_dev_root.last);
if (m20->type) {
while (m20->type) {
tempmr=AMAlloc(sizeof(CMemRange));
tempmr->type=m20->type;
tempmr->flags=0;
tempmr->base=m20->base;
tempmr->size=m20->len;
if (!Mem32DevIns(tempmr))
Free(tempmr);
m20++;
}
}
}
Bool MemLowPagesProtect(Bool val=TRUE)
{ //FALSE if any were not protected
U8 *a=0;
Bool result=TRUE;
while (a<=MEM_PROTECTED_LOW_LIMIT) {
result&=!MemPagePresentMark(a,!val);
a+=MemPageSize(a);
}
return result;
}
U0 MemPagesNotPresentMark()
{
U8 *a,*max_physical=NULL;
U16 *m01=SYS_MEM_E801;
CMemE820 *m20=SYS_MEM_E820;
MemLowPagesProtect;
while (m20->type) {
a=m20->base+m20->len;
if (a>max_physical)
max_physical=a;
m20++;
}
if (max_physical>=0x1000000+m01[1]<<16) {
a=(max_physical+0x1FFFFF)&~0x1FFFFF;
while (a<MEM_MAPPED_SPACE) {
MemPagePresentMark(a,FALSE);
a+=MemPageSize(a);
}
}
}
U8 *Mem32DevAlloc(I64 size,I64 alignment)
{//This doesn't work
U8 *base,*limit;
CMemRange *tempmr,*tempmr1;
while (LBts(&sys_semas[SYS_SEMA_DEV_MEM],0))
Yield;
tempmr1=sys_mem32_dev_root.next;
while (tempmr1!=&sys_mem32_dev_root) {
base=(tempmr1->base+alignment-1)&~(alignment-1);
limit=base+size-1;
if (!tempmr1->type &&
limit<tempmr1->base+tempmr1->size) {
tempmr=AMAlloc(sizeof(CMemRange));
tempmr->type=MRT_DEV;
tempmr->flags=0;
tempmr->base=base;
tempmr->size=size;
if (!Mem32DevIns(tempmr)) {
Free(tempmr);
LBtr(&sys_semas[SYS_SEMA_DEV_MEM],0);
return NULL;
}
LBtr(&sys_semas[SYS_SEMA_DEV_MEM],0);
return tempmr->base;
}
tempmr1=tempmr1->next;
}
LBtr(&sys_semas[SYS_SEMA_DEV_MEM],0);
return NULL;
}
U0 Mem32DevFree(U8 *base)
{
CMemRange *tempmr;
if (!base) return;
while (LBts(&sys_semas[SYS_SEMA_DEV_MEM],0))
Yield;
tempmr=sys_mem32_dev_root.next;
while (tempmr!=&sys_mem32_dev_root) {
if (tempmr->base==base) {
tempmr->type=MRT_UNUSED;
break;
}
tempmr=tempmr->next;
}
LBtr(&sys_semas[SYS_SEMA_DEV_MEM],0);
}
U8 *Mem64DevAlloc(I64 *_pages2Meg)
{
U8 *result;
I64 i=*_pages2Meg,*pte;
while (LBts(&sys_semas[SYS_SEMA_DEV_MEM],0))
Yield;
while (i--) {
sys_mem64_dev_ptr-=0x200000;
pte=MemPageTable(sys_mem64_dev_ptr);
*pte=*pte&~0x18 |0x11; //Uncached and present
InvlPg(sys_mem64_dev_ptr);
}
result=sys_mem64_dev_ptr;
LBtr(&sys_semas[SYS_SEMA_DEV_MEM],0);
return result;
}
U0 Mem64DevFree(U8 *base,I64 pages2Meg)
{
if (!base) return;
while (LBts(&sys_semas[SYS_SEMA_DEV_MEM],0))
Yield;
if (base==sys_mem64_dev_ptr)
sys_mem64_dev_ptr+=pages2Meg*0x200000;
//else not freed
LBtr(&sys_semas[SYS_SEMA_DEV_MEM],0);
}
I64 BIOSTotalMem()
{
I64 r01,r20;
U16 *m01=SYS_MEM_E801;
CMemE820 *m20=SYS_MEM_E820;
r01=0x100000+m01[0]<<10+m01[1]<<16;
r20=0;
if (m20->type) {
while (m20->type) {
if (m20->type==1)
r20+=m20->len;
m20++;
}
}
return MaxI64(r01,r20);
}
U0 HeapsInit()
{
I64 i,total,lo,hi,code_heap_limit;
CMemE820 *m20=SYS_MEM_E820;
Bool first=TRUE;
total=BIOSTotalMem;
if (total<=0x80000000)
code_heap_limit=total;
else if (total<=0x100000000)
code_heap_limit=total/4;
else
code_heap_limit=0x80000000;
i=code_heap_limit-0x1000000;
BlkPoolAdd(sys_code_bp,0x1000000,i>>PAGE_BITS);
sys_heap_limit=i+0x1000000-1;
if (code_heap_limit<total) {
while (m20->type) {
if (m20->type==1) {
lo=m20->base;
hi=m20->base+m20->len;
if (lo<code_heap_limit) {
if (hi>code_heap_limit)
lo=code_heap_limit;
else
hi=lo; //cancel
}
if (code_heap_limit<=lo<hi) {
if (first) {
BlkPoolInit(lo,(hi-lo)>>PAGE_BITS);
sys_data_bp=lo;
Fs->data_heap=HeapCtrlInit(,Fs,sys_data_bp);
first=FALSE;
} else
BlkPoolAdd(sys_data_bp,lo,(hi-lo)>>PAGE_BITS);
}
}
m20++;
}
}
}
I64 Scale2Mem(I64 min,I64 max,I64 limit=2*1024*1024*1024)
//This function is nice for scaling-back allocations if less than 2048 Meg.
//Disk cache and RAM Drive expressions can include this function.
{
I64 i=sys_code_bp->size<<PAGE_BITS;
if (i>=limit)
return max;
else
return min+(max-min)*i/limit;
}
+324
View File
@@ -0,0 +1,324 @@
U0 PortNop()
{
InU8(0x21); //This is an innoculous (reads IRQ Mask)
//access which should take
//fixed time because it's an ISA-bus standard.
//It takes 1.0uS-2.0uS
}
U16 EndianU16(U16 d)
{
I64 result=0;
result.u8[1]=d.u8[0];
result.u8[0]=d.u8[1];
return result;
}
U32 EndianU32(U32 d)
{
I64 result=0;
result.u8[3]=d.u8[0];
result.u8[2]=d.u8[1];
result.u8[1]=d.u8[2];
result.u8[0]=d.u8[3];
return result;
}
U64 EndianU64(U64 d)
{
U64 result;
result.u8[7]=d.u8[0];
result.u8[6]=d.u8[1];
result.u8[5]=d.u8[2];
result.u8[4]=d.u8[3];
result.u8[3]=d.u8[4];
result.u8[2]=d.u8[5];
result.u8[1]=d.u8[6];
result.u8[0]=d.u8[7];
return result;
}
I64 BCnt(I64 d)
{
I64 result=0,i;
for (i=0;i<8;i++)
result+=set_bits_table[d.u8[i]];
return result;
}
U0 IntSimpleTimer(CTask *)
{
I64 i;
if (mp_cnt>1)
while (LBts(&sys_semas[SYS_SEMA_SYS_TIMER],0))
PAUSE
lock sys_jiffies++;
sys_timer+=SYS_TIMER0_PERIOD+1;
LBtr(&sys_semas[SYS_SEMA_SYS_TIMER],0);
for (i=1;i<mp_cnt;i++)
MPInt(I_TIMER,i);
}
I64 SysTimerRead()
{
I64 i,result;
PUSHFD
CLI
if (mp_cnt>1)
while (LBts(&sys_semas[SYS_SEMA_SYS_TIMER],0))
PAUSE
OutU8(0x43,0); //Latch Timer0
if ((i=InU8(0x40)+InU8(0x40)<<8)==SYS_TIMER0_PERIOD) {
if (InU8(0x20) & 1)
i=-1;
}
result=sys_timer+SYS_TIMER0_PERIOD-i;
LBtr(&sys_semas[SYS_SEMA_SYS_TIMER],0);
POPFD
return result;
}
I64 TaskTotalTime()
{
return GetTSC-Fs->time_slice_start+Fs->total_time;
}
I64 TimeStampFreqCal()
{
static I64 time_stamp_start=0,timer_start=0,HPET_start=0;
I64 i;
if (time_stamp_start) {
PUSHFD
CLI
if (HPET_start) {
time_stamp_freq=HPET_freq*(GetTSC-time_stamp_start);
i=HPET-HPET_start;
} else {
time_stamp_freq=SYS_TIMER_FREQ*(GetTSC-time_stamp_start);
i=SysTimerRead-timer_start;
}
if (!i)
Dbg("Timer Cal Error");
time_stamp_freq/=i;
time_stamp_kHz_freq=time_stamp_freq/1000;
POPFD
time_stamp_freq_calibrated=TRUE;
}
PUSHFD
CLI
if (HPET_freq) {
timer_start=0;
HPET_start=HPET;
} else {
timer_start=SysTimerRead;
HPET_start=0;
}
time_stamp_start=GetTSC;
POPFD
return time_stamp_freq;
}
F64 tS()
//Time since boot in seconds as a float
{ //This is slow, but accurate even if no HPET.
if (HPET_freq)
return ToF64(HPET-HPET_initial)/HPET_freq;
else
return SysTimerRead/ToF64(SYS_TIMER_FREQ);
}
Bool Blink(F64 Hz=2.5)
{
if (!Hz) return 0;
return ToI64(sys_jiffies*2*Hz/JIFFY_FREQ)&1;
}
U0 BusyWait(I64 æS) //Loosely timed
{
I64 i;
for (i=0;i<æS;i++)
PortNop;
}
U0 SleepUntil(I64 wake_jiffy)
//This routine is not for power-saving
//it is to make a program pause without
//hogging the CCPU.
{
Bool old_idle=LBts(&Fs->task_flags,TASKf_IDLE);
Fs->wake_jiffy=wake_jiffy;
Yield;
LBEqu(&Fs->task_flags,TASKf_IDLE,old_idle);
}
U0 Sleep(I64 mS)
//This routine is not for power-saving
//it is to make a program pause without
//hogging the CCPU.
{
if (!mS)
Yield;
else
SleepUntil(sys_jiffies+mS*JIFFY_FREQ/1000);
}
U0 Snd(F64 freq)
{
I64 p;
CSndData *d;
if (!Bt(&sys_semas[SYS_SEMA_MUTE],0) &&
!LBts(&sys_semas[SYS_SEMA_SND],0)) {
if (freq!=snd_freq) {
snd_freq=freq;
if (0<freq<=20000) {
p=SYS_TIMER_FREQ/freq;
OutU8(0x43,0xB6);
OutU8(0x42,p);
OutU8(0x42,p.u8[1]);
OutU8(0x61,3|InU8(0x61));
} else
OutU8(0x61,InU8(0x61)&~3);
}
if (!IsDbg && snd_record) {
d=ACAlloc(sizeof(CSndData));
d->freq=freq;
d->time_stamp=tS;
QueIns(d,snd_record_root.last);
}
LBtr(&sys_semas[SYS_SEMA_SND],0);
}
}
U0 Beep(I64 freq=500,Bool busy=FALSE)
{
Snd(freq);
if (busy)
BusyWait(500000);
else
Sleep(500);
Snd(0);
if (busy)
BusyWait(200000);
else
Sleep(200);
}
Bool Mute(Bool val)
{
Bool result;
if (val) {
PUSHFD
CLI
Snd(0);
result=LBts(&sys_semas[SYS_SEMA_MUTE],0);
POPFD
} else
result=LBtr(&sys_semas[SYS_SEMA_MUTE],0);
return result;
}
Bool IsMute() {
return Bt(&sys_semas[SYS_SEMA_MUTE],0);
}
Bool Silent(Bool val) {
//This turns-off console output, not sound.
return LBEqu(&Fs->display_flags,DISPLAYf_SILENT,val);
}
Bool IsSilent() {
return Bt(&Fs->display_flags,DISPLAYf_SILENT);
}
Bool IsPreempt() {
return Bt(&Fs->task_flags,TASKf_PREEMPT);
}
Bool SysDbg(Bool val) {
//Sets or rsts a bit which you can
//use while debugging.
return LBEqu(&sys_semas[SYS_SEMA_DEBUG],0,val);
}
Bool IsSysDbg() {
return Bt(&sys_semas[SYS_SEMA_DEBUG],0);
}
Bool Raw(Bool val) {
//Switches to direct screen output
//mode for when you don't have
//a working window.
if (!val)
VGAFlush;
return !LBEqu(&Fs->task_flags,TASKf_NOT_RAW,!val);
}
Bool IsRaw() {
return !Bt(&Fs->task_flags,TASKf_NOT_RAW);
}
Bool SingleUser(Bool val) {
return LBEqu(&sys_semas[SYS_SEMA_SINGLE_USER],0,val);
}
Bool IsSingleUser() {
return Bt(&sys_semas[SYS_SEMA_SINGLE_USER],0);
}
Bool InDbg(Bool val) {
return LBEqu(&sys_semas[SYS_SEMA_IN_DEBUGGER],0,val);
}
Bool IsDbg() {
return Bt(&sys_semas[SYS_SEMA_IN_DEBUGGER],0);
}
U0 ProgressBarsRst()
{
MemSet(sys_progresses,0,sizeof(sys_progresses));
}
U0 CtrlAltDel(I64)
{
LBts(sys_ctrl_alt_flags,SYSf_CTRL_ALT_DEL);
}
U0 CtrlAltC(I64)
{
LBts(sys_ctrl_alt_flags,SYSf_CTRL_ALT_C);
}
U0 CtrlAltD(I64)
{
if (!IsDbg) {
if (Fs==Gs->idle_task)
BptS(sys_winmgr_task->rip,sys_winmgr_task);
else
BptS(*ctrl_alt_let_ret_addr);
}
}
U0 CtrlAltE(I64)
{
SpawnUser;
}
U0 CtrlAltF(I64)
{
VGAFlush;
}
U0 CtrlAltM(I64)
{
Mute(!IsMute);
}
U0 CtrlAltT(I64)
{
LBts(sys_ctrl_alt_flags,SYSf_CTRL_ALT_TAB);
}
U0 CtrlAltX(I64)
{
LBts(sys_ctrl_alt_flags,SYSf_CTRL_ALT_X);
}
+423
View File
@@ -0,0 +1,423 @@
asm {
ALIGN 16,OC_NOP
USE16
//See $LK,"TempleOS MultiCore",A="FI:::/Doc/MultiCore.TXT"$.
//This code gets copied to $LK,"MP_VECT_ADDR",A="MN:MP_VECT_ADDR"$.
//See $LK,"MemCpy(MP_VECT_ADDR",A="FF:::/Kernel/MultiProc.CPP,MemCpy(mp:2"$.
SYS_MP_INIT_START::
JMP MP2_START2
ALIGN 4,OC_NOP
MP2_SYS_TEMP_PTR: DU32 0,0;
MP2_START2:
CLI
WBINVD
MOV AX,MP_VECT_ADDR/16
MOV DS,AX
//See $LK,"mp->sys_temp_ptr",A="FF:::/Kernel/MultiProc.CPP,mp->sys_temp_ptr:2"$
#assert MP2_SYS_TEMP_PTR-SYS_MP_INIT_START==CMPMain.sys_temp_ptr
LGDT U32 [CMPMain.sys_temp_ptr]
MOV EAX,SYS_START_CR0
MOV_CR0_EAX
DU8 0x66,0xEA; //JMP CGDT.cs32:MP_INIT_OS
DU32 MP_INIT_OS;
DU16 CGDT.cs32;
SYS_MP_INIT_END::
USE32
MP_INIT_OS:
MOV AX,CGDT.ds
MOV DS,AX
MOV ES,AX
MOV FS,AX
MOV GS,AX
MOV SS,AX
@@05: LOCK
BTS U32 [SYS_MP_CNT_LOCK],0
JC @@05
MOV ESI,U32 [SYS_MP_CNT_INITIAL]
LOCK
INC U32 [SYS_MP_CNT_INITIAL]
LOCK
BTR U32 [SYS_MP_CNT_LOCK],0
CMP ESI,MP_MAX_PROCESSORS
JAE I32 _SYS_HLT
IMUL2 ESI,sizeof(CCPU)
ADD ESI,U32 [SYS_CPU_STRUCTS]
LEA ESP,U32 CCPU.start_stk+sizeof(CCPU.start_stk)[ESI]
PUSH U32 SYS_START_RFLAGS
POPFD
PUSH U32 0
CALL INIT_EM64T
USE64
FNINIT
MOV RAX,RSI
CALL SET_GS_BASE
@@10: MOV RAX,U64 CCPU.seth_task[RSI]
TEST RAX,RAX
JZ @@10
MOV U64 CTask.gs[RAX],RSI
CALL SET_FS_BASE
JMP I32 _TASK_CONTEXT_RESTORE
}
U0 TSSBusy(I64 tr,Bool val=OFF)
{ //See $LK,"::/Demo/Lectures/Ring3.CPP"$.
LBEqu((&sys_gdt)(U8 *)+tr+4,9,val);
}
CTSS *TSSNew(I64 cpu_num)
{
U32 *d,*d1;
CTSS *tss=CAlloc(sizeof(CTSS));
tss->io_map_offset=offset(CTSS.io_map);
MemSet(tss->io_map,0xFF,0x10000/8);
tss->st0=MAlloc(INTERRUPT_STK);
tss->rsp0=tss->st0(U8 *)+MSize(tss->st0);
tss->st1=MAlloc(INTERRUPT_STK);
tss->rsp1=tss->st1(U8 *)+MSize(tss->st1);
tss->st2=MAlloc(INTERRUPT_STK);
tss->rsp2=tss->st2(U8 *)+MSize(tss->st2);
tss->tr =offset(CGDT.tr)+cpu_num*16;
tss->tr_ring3=offset(CGDT.tr_ring3)+cpu_num*16;
d=(&sys_gdt)(U8 *)+tss->tr;
d1=d(U8 *)+4;
*d =0x0000FFFF;
*d1=0x008F8900;
d(U8 *)+=2;
*d|=tss & 0x00FFFFFF;
*d1++|=tss & 0xFF000000;
*d1++=tss>>32;
*d1=0;
d=(&sys_gdt)(U8 *)+tss->tr_ring3;
d1=d(U8 *)+4;
*d =0x0000FFFF;
*d1=0x008FE900;
d(U8 *)+=2;
*d|=tss & 0x00FFFFFF;
*d1++|=tss & 0xFF000000;
*d1++=tss>>32;
*d1=0;
return tss;
}
CCPU *CPUStructInit(I64 num,CCPU *c,CTask *seth_task)
{//seth is null when called by adam on CSysFixedArea.boot_cpu0
MemSet(c,0,sizeof(CCPU));
c->addr=c;
c->num=num;
c->idle_factor=0.01;
if (!num)
c->timer_irq_chain=&IntSimpleTimer;
if (Bt(&sys_run_level,RLf_BOOT_HEAP)) {
c->idle_task=Spawn(0,NULL,"Idle Task",,Fs,,0);
Bts(&c->idle_task->task_flags,TASKf_IDLE);
c->tss=TSSNew(num);
}
c->seth_task=seth_task;// It waits for this to be filled-in: $LK,"seth_task",A="FF:::/Kernel/MultiProc.CPP,seth_task"$
return c;
}
U0 MPInt(U8 num,I64 cpu_num=1)
{
if (cpu_num>=mp_cnt) {
if (!Bt(&sys_run_level,RLf_MP))
return;
else
throw('MultCore');
}
PUSHFD
CLI //multitasking safe because each core has a local apic and IRQ's are off
while (*LAPIC_ICR_LOW(U32 *)&0x1000)
PAUSE
*LAPIC_ICR_HIGH(U32 *)=mp_apic_ids[cpu_num]<<24;
*LAPIC_ICR_LOW(U32 *)=0x4000+num;
POPFD
}
U0 MPIntAll(U8 num)
{ //(All but self)
PUSHFD
CLI //multitasking safe because each core has a local apic and IRQ's are off
while (*LAPIC_ICR_LOW(U32 *)&0x1000)
PAUSE
*LAPIC_ICR_LOW(U32 *)=0xC4800+num;
POPFD
}
U0 MPNMInt()
{
*LAPIC_ICR_LOW(U32 *)=0xC4400;
}
U0 MPHalt()
{
mp_cnt=1;
MPNMInt; //Hlt All other processors
BusyWait(10000);
}
U0 MPWake(I64 target_cpu)
{
if (0<=target_cpu<mp_cnt) {
PUSHFD
CLI
if (Bt(&cpu_structs[target_cpu].cpu_flags,CPUf_SETH_SLEEP))
cpu_structs[target_cpu].seth_task->wake_jiffy=0;
if (!target_cpu)
LBtr(&adam_task->task_flags,TASKf_AWAITING_MSG);
MPInt(I_WAKE,target_cpu);
if (!target_cpu)
LBtr(&adam_task->task_flags,TASKf_AWAITING_MSG);
if (Bt(&cpu_structs[target_cpu].cpu_flags,CPUf_SETH_SLEEP)) //In case went back to sleep
cpu_structs[target_cpu].seth_task->wake_jiffy=0;
POPFD
}
}
U0 MPAPICInit()
{ //Called by adam during start-up
//and other cores during initialization
//after $LK,"MPStart",A="MN:MPStart"$().
*LAPIC_SVR(U32 *)|=LAPICF_APIC_ENABLED;
mp_apic_ids[Gs->num]=*LAPIC_APIC_ID(U32 *)>>24;
*LAPIC_LDR(U32 *)=mp_apic_ids[Gs->num]<<24;
*LAPIC_DFR(U32 *)=0xF0000000;
/*
MemSet(LAPIC_IRR,0,0x20);
MemSet(LAPIC_ISR,0,0x20);
MemSet(LAPIC_TMR,0,0x20);
*/
SetRAX(Gs->tss->tr);
LTR AX
if (Gs->num) {
IntInit1;
SetRFlags(SYS_NORMAL_RFLAGS);
}
}
#assert !offset(CSrvCtrl.next_waiting)
U0 MPSethServerTask()
{
CSrvCtrl *my_ctrl=&Fs->srv_ctrl;
CSrvCmd *tempc,*tempc1=&my_ctrl->next_waiting;
STI
while (TRUE) {
TaskFinishOffDying;
if (!LBts(&my_ctrl->flags,SVCRf_LOCKED)) {
tempc=tempc1->next;
//Jobs for this core are highest priority.
if (tempc==tempc1 || !SrvCmdRun(tempc,GetRFlags)) {
LBtr(&my_ctrl->flags,SVCRf_LOCKED) ;
if (my_ctrl->next_waiting==my_ctrl) {
Bts(&Gs->cpu_flags,CPUf_SETH_SLEEP);
Sleep(20);
Btr(&Gs->cpu_flags,CPUf_SETH_SLEEP);
}
}
}
}
}
CSrvCmd *JobQue(I64 (*fp_addr)(U8 *data),U8 *data=NULL,
I64 target_cpu=1,I64 flags=1<<SVCf_FREE_ON_COMPLETE,
I64 cmd_code=SVCT_CALL,U8 *aux_str=NULL,I64 aux1=0,I64 aux2=0)
//This is to queue multicore jobs, handled by Seth tasks.
//Set flags to zero if you wish to get the result.
{
CSrvCtrl *ctrl;
CSrvCmd *tempc;
if (!(0<=target_cpu<mp_cnt))
throw('MultCore');
tempc=ACAlloc(sizeof(CSrvCmd));
if (aux_str)
tempc->aux_str=AStrNew(aux_str);
tempc->cmd_code=cmd_code;
tempc->addr=fp_addr;
tempc->fun_arg=data;
tempc->target_cpu=target_cpu;
tempc->flags=flags;
tempc->aux1=aux1;
tempc->aux2=aux2;
tempc->ctrl=ctrl=&cpu_structs[target_cpu].seth_task->srv_ctrl;
PUSHFD
CLI
while (LBts(&ctrl->flags,SVCRf_LOCKED))
Yield;
QueIns(tempc,ctrl->last_waiting);
LBtr(&ctrl->flags,SVCRf_LOCKED);
POPFD
MPWake(target_cpu);
return tempc;
}
CTask *SpawnQue(U0 (*fp_addr)(U8 *data),U8 *data=NULL,
U8 *task_name=NULL,
I64 target_cpu,
CTask *parent=NULL, //NULL means adam
I64 stk_size=0,I64 flags=1<<SVCf_ADD_TO_QUE)
{
CTask *result;
CSrvCmd *tempc=JobQue(fp_addr,data,target_cpu,flags,SVCT_SPAWN_TASK,task_name,parent,stk_size);
CSrvCtrl *ctrl;
while (!Bt(&tempc->flags,SVCf_DONE)) {
LBts(&Fs->task_flags,TASKf_IDLE);
Yield;
}
LBtr(&Fs->task_flags,TASKf_IDLE);
result=tempc->spawned_task;
ctrl=tempc->ctrl;
PUSHFD
CLI
while (LBts(&ctrl->flags,SVCRf_LOCKED))
Yield;
QueRem(tempc);
LBtr(&ctrl->flags,SVCRf_LOCKED);
POPFD
SrvCmdDel(tempc);
return result;
}
U0 MPCPUTaskInit()
{ //Called by multicore's seth task after $LK,"MPStart",A="MN:MPStart"$()
//as the first thing a CPU does before waiting for jobs
MPAPICInit;
Fs->rip=&MPSethServerTask;
Fs->time_slice_start=GetTSC;
TaskContextRestore;
}
U0 MPStart()
{ //Called by adam during start-up
//and can be called again to rst multicores.
//Doesn't always work when rstting. Kill all tasks, first.
//Must be called from core#0.
CTask *task;
U8 buf[128];
CMPMain *mp=MP_VECT_ADDR;
CCPU *c;
I64 i,my_mp_cnt;
CRAXRBCRCXRDX ee;
CPUId(0x1,&ee);
if (!Bt(&ee.rdx,9))
return;
PUSHFD
CLI
if (mp_cnt>1) {
my_mp_cnt=mp_cnt;
MPHalt; //sets mp_cnt to 1
for (i=1;i<my_mp_cnt;i++) {
c=&cpu_structs[i];
SrvCmdQueDel(&c->seth_task->srv_ctrl.next_waiting);
SrvCmdQueDel(&c->seth_task->srv_ctrl.next_done);
}
}
MemSet(&cpu_structs[1],0,sizeof(CCPU)*(MP_MAX_PROCESSORS-1));
//When you start-up other cores, they jump to an addr
//specified by a byte vect number, $LK,"MPN_VECT",A="MN:MPN_VECT"$ which corresponds
//to a location 4096*vect number, $LK,"MP_VECT_ADDR",A="MN:MP_VECT_ADDR"$$WW,0$.
MemCpy(mp,SYS_MP_INIT_START,SYS_MP_INIT_END-SYS_MP_INIT_START);
mp->sys_temp_ptr=sizeof(CGDT)-1+(&sys_gdt)(U8 *)<<16;
mp_cnt_initial=mp_cnt=1;
mp_cnt_lock=0;
*LAPIC_LVT_ERR(U32 *)=*LAPIC_LVT_ERR(U32 *)&0xFFFFFF00+MPN_VECT;
WBINVD //Not sure why this is needed. Might just need delay. $LK,"MemCpy",A="MN:MemCpy"$ above?
*LAPIC_ICR_LOW(U32 *)=0xC4500; //assert init IPI
BusyWait(10000);
*LAPIC_ICR_LOW(U32 *)=0xC4600+MPN_VECT; //start-up
BusyWait(200);
*LAPIC_ICR_LOW(U32 *)=0xC4600+MPN_VECT;
BusyWait(100000);
for (i=0;i<10000;i++)
LBts(&mp_cnt_lock,0); //Don't let more through
my_mp_cnt=mp_cnt_initial;
if (my_mp_cnt>MP_MAX_PROCESSORS)
my_mp_cnt=MP_MAX_PROCESSORS;
for (i=1;i<my_mp_cnt;i++) {
SPrint(buf,"Seth Task CPU#%d",i);
task=Spawn(&MPCPUTaskInit,NULL,buf,,,SETH_STK,0);
task->rflags=SYS_START_RFLAGS;
//$LK,"CTask",A="MN:CTask"$ allocated off this core's seth_task's heap (Which is Adam)
task->task_in_que_signature=TASK_IN_QUE_SIGNATURE_VAL;
CPUStructInit(i,&cpu_structs[i],task);
WBINVD //Not sure why this is needed. Might just need delay.
}
//Make sure they're all up-and-running
for (i=1;i<my_mp_cnt;i++) {
c=&cpu_structs[i];
while (!Bt(&c->cpu_flags,CPUf_SETH_SLEEP))
PAUSE
}
POPFD
mp_cnt=my_mp_cnt; //Finalize cnt
}
U0 MPInit()
{ //Called by adam during start-up
CRAXRBCRCXRDX ee;
CPUId(0x1,&ee);
mp_cnt_initial=mp_cnt=1;
mp_cnt_lock=0;
mp_crash=ACAlloc(sizeof(CMPCrash));
//Must be in code heap because init code uses 32 bit addr of cpu_struct
adam_task->gs=cpu_structs=CAlloc(sizeof(CCPU)*MP_MAX_PROCESSORS,Fs->code_heap);
adam_task->time_slice_start=GetTSC;
CPUStructInit(0,cpu_structs,adam_task);
asm { //RAX has GS
IMPORT SET_GS_BASE;
CALL SET_GS_BASE
}
if (Bt(&ee.rdx,9)) {
//Unnecessary?
// SetMSR(IA32_LAPIC_BASE,LAPIC_BASE+0x900);
MPAPICInit;
}
}
U0 MPCrash()
{ //Entering the debugger from another core causes an interrupt on core#0
//Which calls this routine.
*LAPIC_EOI(U32 *)=0;
mp_cnt=1;
Raw(ON);
sys_raw_flags|=RWF_SHOW_DOLLAR;
"MP Crash CPU#%02X Task:%08X\n",mp_crash->cpu_num,mp_crash->task;
Dbg(mp_crash->msg,mp_crash->msg_num);
}
+298
View File
@@ -0,0 +1,298 @@
I64 HasLower(U8 *src)
{
I64 ch;
while (ch=*src++)
if ('a'<=ch<='z')
return TRUE;
return FALSE;
}
CHash *PSectFind(U8 *addr,I64 *_offset)
{ //See $LK,"::/Kernel/Hash1a.CPP",A="FL:::/Kernel/Hash1a.CPP,1"$
CHash *result=NULL;
CHashExport *tempex;
Bool has_lower=FALSE;
CHashTable *h=Fs->hash_table;
U64 best=0xFFFF,j;
if (!ChkCodePtr(addr)) {
*_offset=best;
return NULL;
}
while (h) {
tempex=h->next_added;
while (tempex!=h) {
j=0;
if (tempex->type&HTT_FUN) {
if (!Bt(&tempex(CHashFun *)->flags,Cf_EXTERN) &&
!Bt(&tempex(CHashFun *)->flags,Ff_INTERNAL))
j=tempex(CHashFun *)->executable_addr;
} else if (tempex->type&HTT_EXPORT_SYS_SYM)
j=tempex->val;
if (j) {
j=addr(I64)-j;
if (0<=j<=best) {
if (tempex->type&HTT_EXPORT_SYS_SYM) {
if (j<best || j==best && !has_lower) {
has_lower=HasLower(tempex->str);
best=j;
result=tempex;
}
} else if (tempex->type&HTT_FUN) {
if (j<best || j==best &&
(result && result->type&HTT_EXPORT_SYS_SYM||!has_lower)) {
has_lower=HasLower(tempex->str);
best=j;
result=tempex;
}
}
}
}
tempex=tempex->next_added;
}
h=h->next;
}
*_offset=best;
return result;
}
U0 PSectCacheAdd(CHash *temps,U8 *addr)
{
I64 i;
CDbgInfo *dbg;
Bool old_preempt;
CPSectCache *temppc;
if (temps && temps->type&HTT_FUN &&
(dbg=temps(CHashFun *)->debug)) {
old_preempt=Preempt(OFF);
lock {i=psect_cache_index++;}
temppc=&psect_cache[i&(PSECT_CACHE_SIZE-1)];
temppc->base=dbg->body[0];
if (addr<temppc->base)
temppc->base=addr;
temppc->limit=dbg->body[dbg->max_line+1-dbg->min_line];
if (addr>=temppc->limit)
temppc->limit=addr+1;
i=MinI64(StrLen(temps->str),PSECT_CACHE_STR_LEN-1);
MemCpy(temppc->str,temps->str,i);
temppc->str[i]=0;
temppc->time_stamp=tS;
Preempt(old_preempt);
}
}
U8 *PSectCacheFind(U8 *addr,I64 *_offset)
{
I64 i;
F64 timeout;
CPSectCache *temppc=psect_cache;
if (addr==SYS_IDLE_PT) {
*_offset=0;
return "SYS_IDLE_PT";
} else {
timeout=tS+8.0;
for (i=0;i<PSECT_CACHE_SIZE;i++,temppc++)
if (temppc->base<=addr<temppc->limit &&
temppc->time_stamp>timeout) {
*_offset=addr-temppc->base;
return temppc->str;
}
return NULL;
}
}
U0 SPrintPSect(U8 *buf,I64 addr,I64 field_len)
{
I64 offset;
CHashExport *tempex;
U8 *str,*str2;
Bool is_fun=FALSE;
if (addr) {
if (str=PSectCacheFind(addr,&offset)) {
if (addr!=SYS_IDLE_PT)
is_fun=TRUE;
} else {
if (tempex=PSectFind(addr,&offset)) {
if (tempex->type&HTT_FUN)
is_fun=TRUE;
PSectCacheAdd(tempex,addr);
str=tempex->str;
}
}
if (str) {
if (offset>0xFFFF) offset=0xFFFF;
if (is_fun) {
str2=MPrint("&%s",str);
if (field_len>7)
SPrint(buf,"%*ts+0x%04X",field_len-7,str2,offset);
else
SPrint(buf,"%s+0x%04X",str2,offset);
Free(str2);
} else {
if (field_len>7)
SPrint(buf,"%*ts+0x%04X",field_len-7,str,offset);
else
SPrint(buf,"%s+0x%04X",str,offset);
}
return;
}
}
if (field_len)
SPrint(buf,"%*tX",field_len,addr);
else
SPrint(buf,"%X",addr);
}
I64 SrcLineNum(U8 *addr,I64 cnt=1)
{
CHashSrcSym *temph;
I64 cur_line,first_line,last_line,num_lines,offset;
CDbgInfo *dbg;
U32 *body;
U8 *src,*src2;
if (temph=PSectFind(addr,&offset)) {
if (temph->type&(HTT_FUN|HTT_EXPORT_SYS_SYM)) {
if (dbg=temph->debug) {
num_lines=dbg->max_line-dbg->min_line+1;
body=dbg->body;
//find first nonzero
first_line=0;
while (!body[first_line]) {
first_line++;
if (first_line>=num_lines)
return -1;
}
//find last nonzero
last_line=num_lines-1;
while (!body[last_line] && last_line>first_line)
last_line--;
//interpolate to guess line num
cur_line=ClampI64(ToF64(addr-body[first_line])*(last_line-first_line+1)/
(body[last_line]-body[first_line]+1),first_line,last_line);
//retreat while too high
while ((!body[cur_line] || body[cur_line]>=addr) && cur_line>first_line)
cur_line--;
//advance while to low
while ((!body[cur_line] || body[cur_line]<addr) && cur_line<last_line)
cur_line++;
if (addr<body[cur_line]+cnt)
return cur_line+dbg->min_line;
} else if (temph->src_link) {
src =StrNew(temph->src_link);
src2=StrNew(temph->src_link);
StrLastRem(src,",",src2);
cur_line=A2I64(src2);
Free(src);
Free(src2);
return cur_line;
}
}
}
return -1;
}
U8 *SrcFileName(U8 *addr,I64 cnt=1,CTask *mem_task=NULL)
{
CHashSrcSym *temph;
I64 i,j,ii,offset,best=NULL,d,best_d;
U32 *body;
CDbgInfo *dbg;
U8 *src;
if ((temph=PSectFind(addr,&offset)) &&
temph->type&(HTT_FUN|HTT_EXPORT_SYS_SYM)) {
if (dbg=temph->debug) {
j=dbg->max_line-dbg->min_line+1;
body=dbg->body;
best_d=MAX_I64;
for (i=0;i<j;i++) {
if (0<body[i]<=addr<body[i]+cnt) {
ii=i+1;
while (!body[ii])
ii++;
if (addr<body[ii]) {
d=addr(I64)-body[i];
if (d<best_d) {
best_d=d;
best=temph->src_link;
}
}
}
}
} else
best=temph->src_link;
}
if (best) {
src=StrNew(best,mem_task);
StrFirstRem(src,":");
StrLastRem(src,",");
return src;
} else
return NULL;
}
U8 *SrcEdLink(U8 *addr,I64 cnt=1,CTask *mem_task=NULL)
{
U8 *filename,*st,*st2;
I64 linenum;
if (filename=SrcFileName(addr,cnt)) {
linenum=SrcLineNum(addr,cnt);
if (linenum<1)
linenum=1;
st2=MPrint("FL:%s,%d",filename,linenum);
Free(filename);
st=StrNew(st2,mem_task);
Free(st2);
return st;
}
return NULL;
}
Bool PutSrcLink(U8 *addr,I64 cnt=1,U8 *buf=NULL)
{
U8 *src;
if (src=SrcEdLink(addr,cnt)) {
if (buf)
SPrint(buf,"$$LK,\"%p\",A=\"%s\"$$",addr,src);
else
"$$LK,\"%p\",A=\"%s\"$$",addr,src;
Free(src);
return TRUE;
} else if (buf)
*buf=0;
return FALSE;
}
U0 E(U8 *addr,I64 cnt=512,I64 ed_flags=0)
{//Edit src at addr
U8 *st;
if (st=SrcEdLink(addr,cnt)) {
if (IsRaw)
EdLiteFileLine(st);
else
Ed(st,ed_flags);
Free(st);
}
}
U0 Man(U8 *st)
//Edit src code for sym
{
U8 **st2;
CHashSrcSym *temph;
if (IsRaw) {
if ((temph=HashFind(st,Fs->hash_table,HTG_SRC_SYM)) && temph->src_link)
EdLiteFileLine(temph->src_link);
} else {
st2=MPrint("MN:%s",st);
Ed(st2);
Free(st2);
}
}
+245
View File
@@ -0,0 +1,245 @@
U0 QSortI64(I64 *base,I64 num, I64 (*fp_compare)(I64 e1,I64 e2))
{/*
For assending strings: Compare can return StrCmp(e1,e2);
For assending ints : Compare can return e1-e2;
Don't use e1-e2 if numbers can overflow, return -1,0 or 1 with if's.
Maybe, look at $LK,"::/Demo/MultiCore/RadixSort.CPP"$.
*/
I64 i,*less,*greater,pivot;
if (num>1) {
do {
less=base;
greater=base+num;
pivot=base[num/2];
while (less<greater) {
if ((*fp_compare)(*less,pivot)<=0)
less++;
else {
greater--;
SwapU64(less,greater);
}
}
i=less-base;
if (i==num) { //All less or equal to pivot
//Point greater to first less
do greater--;
while (--i && !(*fp_compare)(*greater,pivot));
if (i) {
less=base+num/2; //Pivot was not moved, point to it
if (less<greater)
SwapU64(less,greater);
num=i;
} else //All equal
break;
} else if (i<num/2) {
QSortI64(base,i,fp_compare);
num-=i;
base=greater;
} else {
QSortI64(greater,num-i,fp_compare);
num=i;
}
} while (num>1);
}
}
U0 QSort2a(U8 **_base,I64 num,I64 (*fp_compare)(U8 **_e1,U8 **_e2))
{//Not public, for case of width=size(U8 *)
I64 i;
U8 **_less,**_greater,*pivot;
do {
_less=_base;
_greater=_base+num;
pivot=_base[num/2];
while (_less<_greater) {
if ((*fp_compare)(_less,&pivot)<=0)
_less++;
else {
_greater--;
SwapU64(_less,_greater);
}
}
i=_less-_base;
if (i==num) { //All less or equal to pivot
//Point greater to first less
do _greater--;
while (--i && !(*fp_compare)(_greater,&pivot));
if (i) {
_less=_base+num/2; //Pivot was not moved, point to it
if (_less<_greater)
SwapU64(_less,_greater);
num=i;
} else //All equal
break;
} else if (i<num/2) {
if (i>1)
QSort2a(_base,i,fp_compare);
num-=i;
_base=_greater;
} else {
if (num-i>1)
QSort2a(_greater,num-i,fp_compare);
num=i;
}
} while (num>1);
}
U0 QSort2b(U8 *base,I64 num, I64 width, I64 (*fp_compare)(U8 *e1,U8 *e2),U8 *temp)
{//Not public
I64 i;
U8 *less,*greater,*pivot;
pivot=temp+width;
do {
less=base;
greater=base+num*width;
MemCpy(pivot,base+num/2*width,width);
while (less<greater) {
if ((*fp_compare)(less,pivot)<=0)
less+=width;
else {
greater-=width;
MemCpy(temp,greater,width);
MemCpy(greater,less,width);
MemCpy(less,temp,width);
}
}
i=(less-base)/width;
if (i==num) { //All less or equal to pivot
//Point greater to first less
do greater-=width;
while (--i && !(*fp_compare)(greater,pivot));
if (i) {
less=base+num/2*width; //Pivot was not moved, point to it
if (less<greater) {
MemCpy(temp,greater,width);
MemCpy(greater,less,width);
MemCpy(less,temp,width);
}
num=i;
} else //All equal
break;
} else if (i<num/2) {
if (i>1)
QSort2b(base,i,width,fp_compare,temp);
num-=i;
base=greater;
} else {
if (num-i>1)
QSort2b(greater,num-i,width,fp_compare,temp);
num=i;
}
} while (num>1);
}
U0 QSort(U8 *base,I64 num, I64 width, I64 (*fp_compare)(U8 *e1,U8 *e2))
{/*
For assending strings: Compare can return StrCmp(*e1,*e2);
For assending ints : Compare can return *e1-*e2;
Don't use e1-e2 if numbers can overflow, return -1,0 or 1 with if's.
Maybe, look at $LK,"::/Demo/MultiCore/RadixSort.CPP"$.
*/
I64 i;
U8 *less,*greater,*temp,*pivot;
if (width && num>1) {
if (width==sizeof(U8 *)) { //assign instead of MemCpy for width 8
do {
less=base;
greater=base+num*sizeof(U8 *);
pivot(U8 *)=base(U8 **)[num/2];
while (less<greater) {
if ((*fp_compare)(less,&pivot)<=0)
less+=sizeof(U8 *);
else {
greater-=sizeof(U8 *);
SwapU64(less,greater);
}
}
i=(less-base)/sizeof(U8 *);
if (i==num) { //All less or equal to pivot
//Point greater to first less
do greater-=sizeof(U8 *);
while (--i && !(*fp_compare)(greater,&pivot));
if (i) {
less=base+num/2*sizeof(U8 *); //Pivot was not moved, point to it
if (less<greater)
SwapU64(less,greater);
num=i;
} else //All equal
break;
} else if (i<num/2) {
if (i>1)
QSort2a(base,i,fp_compare);
num-=i;
base=greater;
} else {
if (num-i>1)
QSort2a(greater,num-i,fp_compare);
num=i;
}
} while (num>1);
} else {
temp=MAlloc(width*2);
pivot=temp+width;
do {
less=base;
greater=base+num*width;
MemCpy(pivot,base+num/2*width,width);
while (less<greater) {
if ((*fp_compare)(less,pivot)<=0)
less+=width;
else {
greater-=width;
MemCpy(temp,greater,width);
MemCpy(greater,less,width);
MemCpy(less,temp,width);
}
}
i=(less-base)/width;
if (i==num) { //All less or equal to pivot
//Point greater to first less
do greater-=width;
while (--i && !(*fp_compare)(greater,pivot));
if (i) {
less=base+num/2*width; //Pivot was not moved, point to it
if (less<greater) {
MemCpy(temp,greater,width);
MemCpy(greater,less,width);
MemCpy(less,temp,width);
}
num=i;
} else //All equal
break;
} else if (i<num/2) {
if (i>1)
QSort2b(base,i,width,fp_compare,temp);
num-=i;
base=greater;
} else {
if (num-i>1)
QSort2b(greater,num-i,width,fp_compare,temp);
num=i;
}
} while (num>1);
Free(temp);
}
}
}
+388
View File
@@ -0,0 +1,388 @@
/*
See $LK,"TempleOS MultiTasking",A="FI:::/Doc/MultiTasking.TXT"$.
Tasks are ordered in a circular queue
by front-to-back window stack order with
the window mgr as the head (paints
the wallpaper). The scheduler is
round-robin. It checking if a task
is ready and runs it or skips it.
Swapping tasks just involves storing and
restoring regs (no disk I/O for virtual
memory and no addr map changes). It is
always fully identity-mapped on all cores.
Tasks can be switched in half a microsecond.
The scheduler checks if a task is
waiting for a certain time or waiting
on a message and skips if not ready.
A task runs until it voluntarily yields
ctrl with a call to $LK,"Yield",A="MN:Yield"$() or gets
preempted by the fixed 1kHz $LK,"JIFFY_FREQ",A="MN:JIFFY_FREQ"$
timer interrupt. See $LK,"SYS_TIMER_HANDLER",A="MN:SYS_TIMER_HANDLER"$.
Tasks can ask not to be preempted with
$LK,"Preempt",A="MN:Preempt"$(ON/OFF). Tasks waiting on I/O
often loop, checking for a status and
$LK,"Yield",A="MN:Yield"$ing. This does not really degrade
performance, but pegs the CPU Load.
The scheduler checks for a few critical
key-strokes such as <CTRL-ALT-X>, which
kills a task; <CTRL-ALT-DEL>, which reboots;
<CTRL-ALT-T>, which changes focus and
<CTRL-ALT-C>, which breaks execution
of a program.
Each core has its own circular task queue.
For AP processors, they have a "Seth" task
which stays in a loop waiting for jobs or
requests to spawn tasks. See $LK,"MPSethServerTask",A="MN:MPSethServerTask"$().
$HL,1$*/
asm {
USE64
// ************************************
TASK_CONTEXT_SAVE::
//OUT: RSI=FS
PUSH RSI
PUSHFD
XOR RSI,RSI
MOV RSI,FS:CTask.addr[RSI]
POP U64 CTask.rflags[RSI]
POP U64 CTask.rsi[RSI]
MOV U64 CTask.rax[RSI],RAX
/*
We divert the stk to the Task memory
and push onto it and divert it back.
It's a little faster.
*/
MOV RAX,RSP
LEA RSP,U64 CTask.r15+8[RSI]
PUSH R15
PUSH R14
PUSH R13
PUSH R12
PUSH R11
PUSH R10
PUSH R9
PUSH R8
PUSH RDI
PUSH RBP
PUSH RBX
PUSH RDX
PUSH RCX
MOV RSP,RAX
RDTSC
SHL RDX,32
ADD RAX,RDX
SUB RAX,U64 CTask.time_slice_start[RSI]
ADD U64 CTask.total_time[RSI],RAX
MOV RAX,U64 CTask.fpu_mmx[RSI]
FXSAVE U64 [RAX]
MOV RDX,U64 CTask.bpt_lst[RSI]
@@05: TEST RDX,RDX
JZ @@10
MOV RDI,U64 CBpt.addr[RDX]
MOV AL,U8 CBpt.val[RDX]
MOV U8 [RDI],AL
MOV RDX,U64 CBpt.next[RDX]
JMP @@05
@@10: RET
// ************************************
_TASK_CONTEXT_RESTORE::
XOR RAX,RAX
INC U64 GS:CCPU.swap_cnter[RAX]
MOV RSI,FS:CTask.addr[RAX]
BT U32 CTask.rflags[RSI],RFLAGf_INT
JNC @@05
BTS U32 GS:CCPU.cpu_flags[RAX],CPUf_RAN_A_TASK
@@05: BT U64 CTask.task_flags[RSI],TASKf_DISABLE_BPTS
JC @@15
MOV RDX,U64 CTask.bpt_lst[RSI]
@@10: TEST RDX,RDX
JZ @@15
MOV RDI,U64 CBpt.addr[RDX]
MOV U8 [RDI],OC_BPT
MOV RDX,U64 CBpt.next[RDX]
JMP @@10
@@15: INC U64 CTask.swap_cnter[RSI]
MOV RAX,U64 CTask.fpu_mmx[RSI]
FXRSTOR U64 [RAX]
RDTSC
SHL RDX,32
ADD RAX,RDX
MOV U64 CTask.time_slice_start[RSI],RAX
MOV RAX,RSP
LEA RSP,U64 CTask.rcx[RSI]
POP RCX
POP RDX
POP RBX
POP RBP
POP RDI
POP R8
POP R9
POP R10
POP R11
POP R12
POP R13
POP R14
POP R15
MOV RSP,RAX
MOV RAX,U64 CTask.rax[RSI]
PUSH CGDT.ds
PUSH U64 CTask.rsp[RSI]
PUSH U64 CTask.rflags[RSI]
PUSH CGDT.cs64
PUSH U64 CTask.rip[RSI]
MOV RSI,U64 CTask.rsi[RSI]
IRET
// ************************************
END_RSI_TASK:
MOV RAX,RSI
CALL SET_FS_BASE
_TASK_END_NOW::
CALL &TaskEnd
MOV RSI,RAX
CALL SET_FS_BASE
JMP I8 RESTORE_RSI_TASK_WITH_KEY_CHECK
RESTORE_RSI_NO_PREEMPT_TASK:
BT U32 [SYS_CTRL_ALT_FLAGS],SYSf_CTRL_ALT_DEL
JC I32 HANDLE_SWAP_KEY_EVENT
XOR RAX,RAX
CMP U64 GS:CCPU.idle_task[RAX],RSI //IDLE TASK HAS PREEMPT-OFF
JNE RESTORE_RSI_TASK_NO_KEY_CHECK
JMP I32 SWAP_IN_SETH_TASK_IF_READY
_YIELD::
PUSHFD
TEST U8 [SYS_SEMAS+SYS_SEMA_SINGLE_USER*SEMA_STRUCT_SIZE],1
JNZ @@05 //If single user, don't change task.
CLI
PUSH RSI
XOR RSI,RSI
MOV RSI,FS:CTask.addr[RSI]
CMP U64 CTask.next_task[RSI],RSI
JNE @@15 //Jmp if not just one task on core.
PUSH RAX
MOV RAX,U64 [SYS_JIFFIES]
CMP U64 CTask.wake_jiffy[RSI],RAX
JG @@10 //If needs to sleep, jmp and swap-out.
POP RAX
POP RSI
@@05: POPFD
RET
@@10: POP RAX
@@15: POP RSI
CALL TASK_CONTEXT_SAVE
MOV EBX,U32 _RET
MOV U64 CTask.rip[RSI],RBX
POP U64 CTask.rflags[RSI]
MOV U64 CTask.rsp[RSI],RSP
RESTORE_NEXT_RSI_TASK:
MOV RSI,U64 CTask.next_task[RSI]
RESTORE_RSI_TASK_WITH_KEY_CHECK:
TEST U64 [SYS_CTRL_ALT_FLAGS],1<<SYSf_CTRL_ALT_DEL|
1<<SYSf_CTRL_ALT_TAB|1<<SYSf_CTRL_ALT_X|1<<SYSf_CTRL_ALT_C
JNZ HANDLE_SWAP_KEY_EVENT
RESTORE_RSI_TASK_NO_KEY_CHECK:
@@20: BT U64 CTask.task_flags[RSI],TASKf_KILL_TASK
JC I32 END_RSI_TASK
TEST U64 CTask.task_flags[RSI],1<<TASKf_AWAITING_MSG|1<<TASKf_SUSPENDED
JNZ @@25
MOV RAX,U64 [SYS_JIFFIES]
CMP U64 CTask.wake_jiffy[RSI],RAX
JG @@25 //Jmp if not ready, yet.
CMP U32 CTask.task_in_que_signature[RSI],TASK_IN_QUE_SIGNATURE_VAL
JNE SWAP_IN_SETH_TASK_IF_READY
MOV RAX,RSI
CALL SET_FS_BASE
JMP I32 _TASK_CONTEXT_RESTORE
@@25: MOV RSI,U64 CTask.next_task[RSI]
XOR RAX,RAX
CMP U64 GS:CCPU.seth_task[RAX],RSI
JNE @@20 //Jmp if not Seth
BTR U32 GS:CCPU.cpu_flags[RAX],CPUf_RAN_A_TASK
JC @@20 //Jmp if had chance for IRQ already
MOV RAX,U64 GS:CCPU.idle_task[RAX]
MOV RSP,U64 CTask.stk[RAX]
ADD RSP,DFT_STK+CTaskStk.stk_base //Rst to top
CALL SET_FS_BASE
STI //Swap-in idle task so we can unmask IRQs.
HLT
SYS_IDLE_PT::
CLI
SWAP_IN_SETH_TASK_IF_READY:
XOR RAX,RAX
MOV RSI,GS:CCPU.seth_task[RAX]
JMP I32 RESTORE_RSI_TASK_WITH_KEY_CHECK
HANDLE_SWAP_KEY_EVENT:
MOV RAX,RSI
CALL SET_FS_BASE
XOR RAX,RAX
MOV RAX,GS:CCPU.num[RAX]
TEST RAX,RAX
JNZ I32 RESTORE_RSI_TASK_NO_KEY_CHECK
MOV EAX,U32 SYS_CTRL_ALT_FLAGS
LOCK
BTR U32 [RAX],SYSf_CTRL_ALT_DEL
JC I32 &Reboot
LOCK
BTR U32 [RAX],SYSf_CTRL_ALT_TAB
JNC @@05
PUSH RSI
MOV RSI,U64 [SYS_FOCUS_TASK]
MOV U64 [SYS_FOCUS_TASK],0
CALL FOCUS_RSI_NEXT_USER
POP RSI
JMP I32 RESTORE_FS_TASK_WITH_KEY_CHECK
@@05: LOCK
BTR U32 [RAX],SYSf_CTRL_ALT_X
JC END_FOCUS_USER
LOCK
BTR U32 [RAX],SYSf_CTRL_ALT_C
JNC I32 RESTORE_RSI_TASK_WITH_KEY_CHECK
BREAK_FOCUS_USER:
MOV RSI,U64 [SYS_FOCUS_TASK]
TEST RSI,RSI
JZ SWAP_IN_SETH_TASK_IF_READY
BT U64 CTask.win_inhibit[RSI],WIf_FOCUS
JC I32 RESTORE_RSI_TASK_NO_KEY_CHECK
LOCK
BTR U64 CTask.task_flags[RSI],TASKf_BREAK_LOCKED
JNC @@10
LOCK
BTS U64 CTask.task_flags[RSI],TASKf_PENDING_BREAK
JMP I32 RESTORE_RSI_TASK_NO_KEY_CHECK
@@10: MOV RAX,&SysThrowBreak
MOV U64 CTask.rip[RSI],RAX
BT U64 CTask.task_flags[RSI],TASKf_BREAK_TO_SHIFT_ESC
JC @@15
//We do these two now, in case interrupt happens
MOV U64 CTask.wake_jiffy[RSI],0
PUSH RSI
CALL &TaskRstAwaitingMsg
@@15: JMP I32 RESTORE_RSI_TASK_NO_KEY_CHECK
END_FOCUS_USER:
MOV RSI,U64 [SYS_FOCUS_TASK]
MOV U64 [SYS_FOCUS_TASK],0
PUSH RSI
CALL FOCUS_RSI_NEXT_USER
POP RSI
TEST RSI,RSI
JZ I32 SWAP_IN_SETH_TASK_IF_READY
MOV RAX,RSI
CALL SET_FS_BASE
BT U64 CTask.win_inhibit[RSI],WIf_FOCUS
JC I32 RESTORE_RSI_TASK_WITH_KEY_CHECK
LOCK
BTS U64 CTask.task_flags[RSI],TASKf_KILL_TASK
JMP I32 END_RSI_TASK
RESTORE_FS_TASK_WITH_KEY_CHECK:
XOR RSI,RSI
MOV RSI,FS:CTask.addr[RSI]
JMP I32 RESTORE_RSI_TASK_WITH_KEY_CHECK
FOCUS_RSI_NEXT_USER:
TEST RSI,RSI
JNZ @@20
MOV ESI,U32 SYS_FIXED_AREA+CSysFixedArea.adam
@@20: MOV RDI,RSI
MOV RSI,U64 CTask.next_task[RSI]
@@25: BT U64 CTask.win_inhibit[RSI],WIf_FOCUS
JC @@30
CMP U64 [SYS_FOCUS_TASK],RSI
JE @@30
MOV U64 [SYS_FOCUS_TASK],RSI
MOV RAX,U64 [SYS_EXTERN_TABLE]
MOV RAX,U64 EXT_WIN_TO_TOP*8[RAX]
TEST RAX,RAX
JZ @@35
PUSH TRUE
PUSH RSI
CALL RAX
JMP @@35
@@30: MOV RSI,U64 CTask.next_task[RSI]
CMP RSI,RDI
JNE @@25
MOV U64 [SYS_FOCUS_TASK],0
@@35: RET
}
_extern _TASK_CONTEXT_RESTORE U0 TaskContextRestore();
_extern _YIELD U0 Yield();
_extern _TASK_END_NOW U0 TaskEndNow();
U0 TaskQueIns(CTask *task,CTask *pred=NULL)
{//Insert a task in the scheduler running task queue.
//You have no business with this, probably.
CTask *last;
PUSHFD
CLI
if (!pred) pred=Fs;
last=pred->last_task;
last->next_task=pred->last_task=task;
task->last_task=last;
task->next_task=pred;
task->task_in_que_signature=TASK_IN_QUE_SIGNATURE_VAL;
POPFD
}
U0 TaskQueRem(CTask *task)
{//Remove a task from the scheduler running task queue.
//Use $LK,"Suspend",A="MN:Suspend"$().
CTask *next,*last;
PUSHFD
CLI
task->task_in_que_signature=0;
next=task->next_task;
last=task->last_task;
last->next_task=next;
next->last_task=last;
POPFD
}
U0 TaskQueInsChild(CTask *task)
{
CTask *last,*pred;
PUSHFD
CLI
pred=task->parent_task->last_child_task;
last=pred->last_sibling_task;
last->next_sibling_task=pred->last_sibling_task=task;
task->last_sibling_task=last;
task->next_sibling_task=pred;
POPFD
}
+514
View File
@@ -0,0 +1,514 @@
U0 SrvCmdDel(CSrvCmd *tempc)
{
Free(tempc->aux_str);
Free(tempc);
}
U0 SrvCmdQueDel(CSrvCmd *root)
{
CSrvCmd *tempc=root->next,*tempc1;
while (tempc!=root) {
tempc1=tempc->next;
QueRem(tempc);
SrvCmdDel(tempc);
tempc=tempc1;
}
}
U0 SrvCtrlInit(CSrvCtrl *ctrl)
{
QueInit(&ctrl->next_waiting);
QueInit(&ctrl->next_done);
ctrl->flags=0;
}
U0 TaskRstAwaitingMsg(CTask *task=NULL)
{ //Pop-ups get parent messages so wake-up our pop-ups if we got a msg.
if (!task) task=Fs;
PUSHFD
CLI
do {
if (TaskValidate(task))
LBtr(&task->task_flags,TASKf_AWAITING_MSG);
else
break;
} while (task=task->popup_task);
POPFD
}
CSrvCmd *TaskExe(CTask *srv,CTask *master,U8 *data,I64 flags)
{//This queues a request to compile and execute text.
CSrvCmd *result;
if (!data || !TaskValidate(srv) ||
master && !TaskValidate(master) ||
srv->popup_task && !Bt(&srv->task_flags,TASKf_FILTER_INPUT))
return NULL;
result=ACAlloc(sizeof(CSrvCmd));
result->master_task=master;
result->cmd_code=SVCT_EXE_STR;
result->flags=flags;
result->aux_str=AStrNew(data);
result->ctrl=&srv->srv_ctrl;
PUSHFD
CLI
while (LBts(&srv->srv_ctrl.flags,SVCRf_LOCKED))
PAUSE
if (!TaskValidate(srv)) {
POPFD
SrvCmdDel(result);
return NULL;
} else {
LBtr(&srv->task_flags,TASKf_IDLE);
TaskRstAwaitingMsg(srv);
QueIns(result,srv->srv_ctrl.last_waiting);
LBtr(&srv->srv_ctrl.flags,SVCRf_LOCKED);
if (Bt(&flags,SVCf_WAKE_MASTER)) {
Suspend(master);
Yield;
}
}
POPFD
return result;
}
CSrvCmd *TaskText(CTask *srv,CTask *master,
U8 *data,I64 flags)
{
CSrvCmd *result;
Bool old_preempt=Preempt(OFF);
CTask *task;
if (!data || !TaskValidate(srv) ||
master && !TaskValidate(master) ||
srv->popup_task && !Bt(&srv->task_flags,TASKf_FILTER_INPUT)) {
Preempt(old_preempt);
return NULL;
}
result=ACAlloc(sizeof(CSrvCmd));
result->master_task=master; //in case somebody cares
result->cmd_code=SVCT_TEXT_INPUT;
result->flags=flags;
result->aux_str=AStrNew(data);
PUSHFD
task=srv->last_input_filter_task;
if (Bt(&flags,SVCf_HIGHEST_PRIORITY) || task==srv) {
if (task!=srv)
TaskWait(srv);
task=Spawn(&InputFilterTask,NULL,"Input Filter",,srv);
CLI
task->next_input_filter_task=srv->next_input_filter_task;
task->last_input_filter_task=srv;
srv->next_input_filter_task=task;
task->next_input_filter_task->last_input_filter_task=task;
} else {
CLI
task=srv->next_input_filter_task;
}
result->ctrl=&task->srv_ctrl;
while (LBts(&task->srv_ctrl.flags,SVCRf_LOCKED))
PAUSE
if (!TaskValidate(task)) {
SrvCmdDel(result);
result=NULL;
} else {
LBtr(&task->task_flags,TASKf_IDLE);
TaskRstAwaitingMsg(task);
QueIns(result,task->srv_ctrl.last_waiting);
LBtr(&task->srv_ctrl.flags,SVCRf_LOCKED);
}
POPFD
Preempt(old_preempt);
return result;
}
CSrvCmd *TaskMsg(CTask *_srv,CTask *master,
I64 msg_code,I64 p1,I64 p2,I64 flags)
{
CSrvCmd *tempc1,*tempc;
CTask *srv=_srv;
if (!TaskValidate(srv) ||
master && !TaskValidate(master)||
srv->popup_task && !Bt(&srv->task_flags,TASKf_FILTER_INPUT))
return NULL;
tempc=ACAlloc(sizeof(CSrvCmd));
tempc->master_task=master;
tempc->cmd_code=SVCT_MSG;
tempc->msg_code=AbsI64(msg_code); //negative means do a down and up
tempc->aux1=p1;
tempc->aux2=p2;
tempc->flags=flags;
PUSHFD
if (Bt(&sys_semas[SYS_SEMA_RECORD_MACRO],0) &&
srv!=sys_macro_util_task &&
msg_code==MSG_KEY_DOWN) {
tempc1=AMAllocIdentical(tempc);
CLI
QueIns(tempc1,sys_macro_root.last);
}
CLI
while (Bt(&srv->task_flags,TASKf_FILTER_INPUT) &&
!Bt(&flags,SVCf_DONT_FILTER))
srv=srv->next_input_filter_task;
tempc->ctrl=&srv->srv_ctrl;
while (LBts(&srv->srv_ctrl.flags,SVCRf_LOCKED))
PAUSE
if (!TaskValidate(srv)) {
SrvCmdDel(tempc);
tempc=NULL;
} else {
LBtr(&srv->task_flags,TASKf_IDLE);
TaskRstAwaitingMsg(srv);
QueIns(tempc,srv->srv_ctrl.last_waiting);
LBtr(&srv->srv_ctrl.flags,SVCRf_LOCKED);
}
POPFD
if (msg_code<0) //Down-Up
TaskMsg(_srv,master,-msg_code+1,p1,p2,flags);
return tempc;
}
Bool ScanResult(CSrvCmd *rqst=NULL,I64 *_result=NULL)
{
CSrvCtrl *ctrl;
CSrvCmd *tempc,*tempc1;
if (!rqst || Bt(&rqst->flags,SVCf_DONE)) {
if (!rqst || rqst->master_task)
ctrl=&Fs->srv_ctrl;
else
ctrl=rqst->ctrl;
PUSHFD
CLI
while (LBts(&ctrl->flags,SVCRf_LOCKED))
PAUSE
tempc1=&ctrl->next_done;
tempc=tempc1->next;
while (tempc!=tempc1) {
if (!rqst || rqst==tempc) {
QueRem(tempc);
LBtr(&ctrl->flags,SVCRf_LOCKED);
POPFD
if (_result)
*_result=tempc->result;
SrvCmdDel(tempc);
return TRUE;
}
tempc=tempc->next;
}
LBtr(&ctrl->flags,SVCRf_LOCKED);
POPFD
}
if (_result)
*_result=0;
return FALSE;
}
I64 GetResult(CSrvCmd *rqst=NULL)
{
I64 result;
CSrvCmd *tempc1;
if (!rqst) {
tempc1=&Fs->srv_ctrl.next_done;
while (tempc1==tempc1->next) {
LBts(&Fs->task_flags,TASKf_IDLE);
Yield;
}
} else {
while (!Bt(&rqst->flags,SVCf_DONE)) {
LBts(&Fs->task_flags,TASKf_IDLE);
Yield;
}
}
LBtr(&Fs->task_flags,TASKf_IDLE);
//Could get taken by someone else.
ScanResult(rqst,&result);
return result;
}
U0 TaskWait(CTask *task=NULL)
{//Wait for idle
CTask *task1;
CSrvCmd *tempc1;
if (!task) task=Fs;
if (TaskValidate(task)) {
PUSHFD
CLI
while (TRUE) {
task1=task->last_input_filter_task;
tempc1=&task1->srv_ctrl.next_waiting;
if (task1==Fs || !TaskValidate(task1) ||
tempc1==tempc1->next && Bt(&task1->task_flags,TASKf_IDLE))
break;
Yield;
}
POPFD
}
}
U0 PostMsg(CTask *task,I64 msg_code,I64 p1,I64 p2,I64 flags=0)
{
if (TaskValidate(task)) {
if (Bt(&task->task_flags,TASKf_INPUT_FILTER_TASK))
TaskMsg(task->last_input_filter_task,NULL,msg_code,p1,p2,
flags|1<<SVCf_DONT_FILTER);
else
TaskMsg(task,NULL,msg_code,p1,p2,flags);
}
}
U0 SendMsg(CTask *task,I64 msg_code,I64 p1,I64 p2,I64 flags=0)
{
PostMsg(task,msg_code,p1,p2,flags);
TaskWait(task);
}
U0 Msg(I64 msg_code,I64 p1,I64 p2,I64 flags=0)
{
PostMsg(Fs,msg_code,p1,p2,flags);
}
#define SCR_DONE 0
#define SCR_CONT 1
#define SCR_EXIT 2
I64 SrvCmdRun(CSrvCmd *tempc,I64 old_flags)
{
CSrvCtrl *ctrl=tempc->ctrl;
CTask *master;
Bool old_preempt=IsPreempt;
I64 result,flags=tempc->flags;
if (Bt(&flags,SVCf_EXIT_ON_COMPLETE))
result=SCR_EXIT;
else
result=SCR_CONT;
switch (tempc->cmd_code) {
case SVCT_SPAWN_TASK:
QueRem(tempc);
LBts(&tempc->flags,SVCf_DISPATCHED);
tempc->servant_cpu_num=Gs->num;
LBtr(&ctrl->flags,SVCRf_LOCKED);
if (tempc->aux_str)
tempc->spawned_task=Spawn(tempc->addr,tempc->fun_arg,tempc->aux_str,,tempc->aux1,tempc->aux2,tempc->flags);
else
tempc->spawned_task=Spawn(tempc->addr,tempc->fun_arg,"Unnamed",,tempc->aux1,tempc->aux2,tempc->flags);
break;
case SVCT_CALL:
QueRem(tempc);
LBts(&tempc->flags,SVCf_DISPATCHED);
tempc->servant_cpu_num=Gs->num;
LBtr(&ctrl->flags,SVCRf_LOCKED);
SetRFlags(old_flags);
LBtr(&Fs->task_flags,TASKf_IDLE);
try
tempc->result=(*tempc->addr)(tempc->fun_arg);
catch
Fs->catch_except=TRUE;
SetRFlags(old_flags);
break;
case SVCT_EXE_STR:
QueRem(tempc);
LBts(&tempc->flags,SVCf_DISPATCHED);
tempc->servant_cpu_num=Gs->num;
LBtr(&ctrl->flags,SVCRf_LOCKED);
SetRFlags(old_flags);
LBtr(&Fs->task_flags,TASKf_IDLE);
try
tempc->result=ExePrint("%s",tempc->aux_str);
catch
Fs->catch_except=TRUE;
SetRFlags(old_flags);
break;
default:
result=SCR_DONE;
}
if (result) {
if (master=tempc->master_task) {
if (!Bt(&flags,SVCf_FREE_ON_COMPLETE)) {
CLI
while (LBts(&master->srv_ctrl.flags,SVCRf_LOCKED))
PAUSE
QueIns(tempc,master->srv_ctrl.last_done);
LBts(&tempc->flags,SVCf_DONE);
LBtr(&master->srv_ctrl.flags,SVCRf_LOCKED);
SetRFlags(old_flags);
}
if (Bt(&flags,SVCf_FOCUS_MASTER) &&
!Bt(&master->win_inhibit,WIf_FOCUS))
sys_focus_task=master;
if (Bt(&flags,SVCf_WAKE_MASTER))
Suspend(master,FALSE);
}
if (Bt(&flags,SVCf_FREE_ON_COMPLETE))
SrvCmdDel(tempc);
else if (!master) {
CLI
while (LBts(&ctrl->flags,SVCRf_LOCKED))
Yield;
QueIns(tempc,ctrl->last_done);
LBts(&tempc->flags,SVCf_DONE);
LBtr(&ctrl->flags,SVCRf_LOCKED);
SetRFlags(old_flags);
}
}
Preempt(old_preempt);
return result;
}
I64 SrvCmdsHandler(CTask *task=NULL)
{
I64 cnt=0,old_flags=GetRFlags;
CSrvCmd *tempc,*tempc1;
if (!task) task=Fs;
while (TRUE) {
CLI
while (LBts(&task->srv_ctrl.flags,SVCRf_LOCKED))
PAUSE
tempc1=&task->srv_ctrl.next_waiting;
tempc=tempc1->next;
if (tempc==tempc1)
goto sch_done;
else
switch (SrvCmdRun(tempc,old_flags)) {
case SCR_CONT:
cnt++;
break;
case SCR_EXIT:
Exit;
case SCR_DONE:
goto sch_done;
}
}
sch_done:
LBtr(&task->srv_ctrl.flags,SVCRf_LOCKED);
SetRFlags(old_flags);
return cnt;
}
I64 SrvUser(U8 *fmt,...)
//Spawns a visible task and sends text
//which gets compiled and run.
{
U8 *buf=SPrintJoin(NULL,fmt,argc,argv);
I64 result=0;
CSrvCmd *tempc;
CTask *task=Spawn(&SrvUserCmdLine,NULL,"Servant",,Fs);
Fs->popup_task=task;
tempc=TaskExe(task,Fs,buf,1<<SVCf_WAKE_MASTER|1<<SVCf_FOCUS_MASTER);
ScanResult(tempc,&result);
Fs->popup_task=NULL;
Kill(task,FALSE);
Free(buf);
return result;
}
I64 Adam(U8 *fmt,...)
//Sends text to the adam task which gets
//compiled and run.
{
I64 result;
U8 *buf=SPrintJoin(NULL,fmt,argc,argv);
Bool old_preempt=Preempt(OFF);
CSrvCmd *tempc;
if (Fs==adam_task) {
tempc=TaskExe(adam_task,Fs,buf,0);
SrvCmdsHandler;
} else {
TaskWait(adam_task);
tempc=TaskExe(adam_task,Fs,buf,1<<SVCf_WAKE_MASTER);
}
Preempt(old_preempt);
ScanResult(tempc,&result);
Free(buf);
return result;
}
U0 AdamLog(U8 *fmt,...)
//Sends text to the adam task which gets
//displayed.
{
U8 *buf=SPrintJoin(NULL,fmt,argc,argv);
if (Fs==adam_task)
"%s",buf;
else if (!IsSingleUser)
Adam("\"%%s\",%d;",buf);
Free(buf);
}
U0 AdamErr(U8 *fmt,...)
//Sends text to the adam task which gets
//displayed as red and blinking.
{
U8 *buf=SPrintJoin(NULL,fmt,argc,argv),
*st=MPrint(ST_ERR_ST "%s",buf);
if (Fs==adam_task)
"%s",st;
else if (!IsSingleUser)
Adam("\"%%s\",%d;",st);
Free(st);
Free(buf);
}
U0 XTalk(CTask *task,U8 *fmt,...)
//Sends text to another task's input
//buffer.
{
U8 *buf=SPrintJoin(NULL,fmt,argc,argv),*st=AStrNew(buf),
*st2=MPrint("\"%%s\",%d;Free(%d);",st,st);
TaskText(task,0,st2,0);
Free(st2);
Free(buf);
}
U0 XTalkWait(CTask *task,U8 *fmt,...)
{
U8 *buf=SPrintJoin(NULL,fmt,argc,argv),*st=AStrNew(buf),
*st2=MPrint("\"%%s\",%d;Free(%d);",st,st);
TaskText(task,0,st2,0);
Free(st2);
Free(buf);
TaskWait(task);
}
U0 AutoStr(U8 *fmt,...)
//Sends text in the nature of an AutoFile to one's
//own input buffer.
{
U8 *buf=SPrintJoin(NULL,fmt,argc,argv);
if (Bt(&Fs->task_flags,TASKf_INPUT_FILTER_TASK))
ExePrint("%s",buf);
else
TaskText(Fs,0,buf,1<<SVCf_HIGHEST_PRIORITY);
Free(buf);
}
U0 AutoFile(U8 *filename)
{
U8 *name=DftExt(filename,"AUT.Z");
AutoStr("%F",name);
Free(name);
}
U0 Auto(U8 *fmt,...)
//Sends text to one's own input buffer
{
U8 *buf=SPrintJoin(NULL,fmt,argc,argv),*st=AStrNew(buf);
AutoStr("\"%%s\",%d;Free(%d);",st,st);
Free(buf);
}
//This sends text of an AutoFile nature to a
//task's input buffer.
U0 XTalkStr(CTask *task,U8 *fmt,...)
{
U8 *buf=SPrintJoin(NULL,fmt,argc,argv);
TaskText(task,0,buf,0);
Free(buf);
}
U0 XTalkStrWait(CTask *task,U8 *fmt,...)
{
U8 *buf=SPrintJoin(NULL,fmt,argc,argv);
TaskText(task,0,buf,0);
Free(buf);
TaskWait(task);
}
+676
View File
@@ -0,0 +1,676 @@
U8 hex_digits[16]="0123456789ABCDEF";
U8 *Bin2Hex(U8 *dst,I64 n;I64 width)
{
U8 *result=dst+width;
dst=result;
while (width--) {
*--dst=hex_digits[n&15];
n>>=4;
}
return result;
}
U0 PutHex(I64 n,I64 width)
{
U8 buf[17];
if (width>16) width=16;
*Bin2Hex(buf,n,width)=0;
"%s",buf;
}
asm {
USE64
// ************************************
// IN: RAX=NUM TO PRINT
PUT_HEX_U64::
PUSH_C_REGS
PUSH 16
PUSH RAX
CALL &PutHex
POP_C_REGS
RET
PUT_HEX::
PUT_HEX_U32::
PUSH_C_REGS
PUSH 8
PUSH RAX
CALL &PutHex
POP_C_REGS
RET
PUT_HEX_U16::
PUSH_C_REGS
PUSH 4
PUSH RAX
CALL &PutHex
POP_C_REGS
RET
PUT_HEX_U8::
PUSH_C_REGS
PUSH 2
PUSH RAX
CALL &PutHex
POP_C_REGS
RET
// ************************************
PUT_CHARS::
// IN: RAX=Char
PUSH_C_REGS
PUSH RAX
CALL &PutChars
POP_C_REGS
RET
PUT_STR::
// IN: RSI=String
PUSH_C_REGS
PUSH RSI
CALL &PutS
POP_C_REGS
RET
// ************************************
_STRCPY::
PUSH RBP
MOV RBP,RSP
PUSH RSI
PUSH RDI
MOV RDI,U64 SF_ARG1[RBP]
TEST RDI,RDI
JZ @@15
MOV RSI,U64 SF_ARG2[RBP]
TEST RSI,RSI
JNZ @@05
XOR RAX,RAX
JMP @@10
@@05: LODSB
@@10: STOSB
TEST AL,AL
JNZ @@05
@@15: POP RDI
POP RSI
POP RBP
RET1 16
// ************************************
_STRCMP::
PUSH RBP
MOV RBP,RSP
PUSH RSI
PUSH RDI
MOV RSI,U64 SF_ARG2[RBP]
MOV RDI,U64 SF_ARG1[RBP]
@@05: LODSB
TEST AL,AL
JZ @@20
SCASB
JE @@05
JA @@15
@@10: MOV RAX,1
JMP @@25
@@15: MOV RAX,-1
JMP @@25
@@20: SCASB
JNE @@10
XOR RAX,RAX
@@25: POP RDI
POP RSI
POP RBP
RET1 16
// ************************************
TO_UPPER::
CMP AL,'a'
JB @@05
CMP AL,'z'
JA @@05
ADD AL,'A'-'a'
@@05: RET
// ************************************
_STRICMP::
PUSH RBP
MOV RBP,RSP
PUSH RSI
PUSH RDI
MOV RSI,U64 SF_ARG2[RBP]
MOV RDI,U64 SF_ARG1[RBP]
@@05: LODSB
TEST AL,AL
JZ @@30
CMP AL,'a'
JB @@10
CMP AL,'z'
JA @@10
ADD AL,'A'-'a'
@@10: MOV BL,U8 [RDI]
INC RDI
CMP BL,'a'
JB @@15
CMP BL,'z'
JA @@15
ADD BL,'A'-'a'
@@15: CMP AL,BL
JE @@05
JA @@25
@@20: MOV RAX,1
JMP @@35
@@25: MOV RAX,-1
JMP @@35
@@30: MOV BL,U8 [RDI]
TEST BL,BL
JNE @@20
XOR RAX,RAX
@@35: POP RDI
POP RSI
POP RBP
RET1 16
// ************************************
_STRNCMP::
PUSH RBP
MOV RBP,RSP
PUSH RSI
PUSH RDI
MOV RCX,U64 SF_ARG3[RBP]
MOV RSI,U64 SF_ARG2[RBP]
MOV RDI,U64 SF_ARG1[RBP]
@@05: TEST RCX,RCX
JZ @@25
DEC RCX
LODSB
TEST AL,AL
JZ @@20
SCASB
JE @@05
JA @@15
@@10: MOV RAX,1
JMP @@30
@@15: MOV RAX,-1
JMP @@30
@@20: MOV BL,U8 [RDI]
TEST BL,BL
JNE @@10
@@25: XOR RAX,RAX
@@30: POP RDI
POP RSI
POP RBP
RET1 24
// ************************************
_STRNICMP::
PUSH RBP
MOV RBP,RSP
PUSH RSI
PUSH RDI
MOV RCX,U64 SF_ARG3[RBP]
MOV RSI,U64 SF_ARG2[RBP]
MOV RDI,U64 SF_ARG1[RBP]
@@05: TEST RCX,RCX
JZ @@35
DEC RCX
LODSB
TEST AL,AL
JZ @@30
CMP AL,'a'
JB @@10
CMP AL,'z'
JA @@10
ADD AL,'A'-'a'
@@10: MOV BL,U8 [RDI]
INC RDI
CMP BL,'a'
JB @@15
CMP BL,'z'
JA @@15
ADD BL,'A'-'a'
@@15: CMP AL,BL
JE @@05
JA @@25
@@20: MOV RAX,1
JMP @@40
@@25: MOV RAX,-1
JMP @@40
@@30: SCASB
JNE @@20
@@35: XOR RAX,RAX
@@40: POP RDI
POP RSI
POP RBP
RET1 24
// ************************************
_STRMATCH::
PUSH RBP
MOV RBP,RSP
PUSH RSI
PUSH RDI
MOV RSI,U64 SF_ARG2[RBP]
TEST RSI,RSI
JZ @@25
MOV RDI,U64 SF_ARG1[RBP]
TEST RDI,RDI
JZ @@25
MOV DL,U8 [RDI]
TEST DL,DL
JZ @@20
JMP @@10
@@05: INC RSI
@@10: LODSB
TEST AL,AL
JZ @@25
CMP AL,DL
JNE @@10
DEC RSI
MOV RCX,1
@@15: MOV AL,U8 [RDI+RCX]
TEST AL,AL
JZ @@20
CMP AL,U8 [RSI+RCX]
JNE @@05
INC RCX
JMP @@15
DEC RSI
@@20: MOV RAX,RSI
JMP @@30
@@25: XOR RAX,RAX
@@30: POP RDI
POP RSI
POP RBP
RET1 16
// ************************************
_STRIMATCH::
PUSH RBP
MOV RBP,RSP
PUSH RSI
PUSH RDI
MOV RSI,U64 SF_ARG2[RBP]
TEST RSI,RSI
JZ @@25
MOV RDI,U64 SF_ARG1[RBP]
TEST RDI,RDI
JZ @@25
MOV AL,U8 [RDI]
CALL TO_UPPER
MOV DL,AL
TEST DL,DL
JZ @@20
JMP @@10
@@05: INC RSI
@@10: LODSB
CALL TO_UPPER
TEST AL,AL
JZ @@25
CMP AL,DL
JNE @@10
DEC RSI
MOV RCX,1
@@15: MOV AL,U8 [RDI+RCX]
CALL TO_UPPER
TEST AL,AL
JZ @@20
MOV BL,U8 [RSI+RCX]
XCHG AL,BL
CALL TO_UPPER
CMP AL,BL
JNE @@05
INC RCX
JMP @@15
DEC RSI
@@20: MOV RAX,RSI
JMP @@30
@@25: XOR RAX,RAX
@@30: POP RDI
POP RSI
POP RBP
RET1 16
}
_extern _STRCMP I64 StrCmp(U8 *st1,U8 *st2);
_extern _STRICMP I64 StrICmp(U8 *st1,U8 *st2);
_extern _STRNCMP I64 StrNCmp(U8 *st1,U8 *st2,I64 n);
_extern _STRNICMP I64 StrNICmp(U8 *st1,U8 *st2,I64 n);
_extern _STRMATCH U8 *StrMatch(U8 *needle,U8 *haystack_str);
_extern _STRIMATCH U8 *StrIMatch(U8 *needle,U8 *haystack_str);
_extern _STRCPY U0 StrCpy(U8 *dst,U8 *src);
/*
These bitmaps go to 0-511 so that
$LK,"Lex",A="MN:Lex"$() can use them with $LK,"Token Codes",A="MN:TK_EOF"$.
*/
U32 chars_bitmap_alpha[16]=
{0x0000000,0x00000000,0x87FFFFFF,0x07FFFFFE,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
0,0,0,0,0,0,0,0};
U32 chars_bitmap_alpha_numeric[16]=
{0x0000000,0x03FF0000,0x87FFFFFF,0x07FFFFFE,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
0,0,0,0,0,0,0,0};
U32 chars_bitmap_alpha_numeric_no_at[16]=
{0x0000000,0x03FF0000,0x87FFFFFE,0x07FFFFFE,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
0,0,0,0,0,0,0,0};
U32 chars_bitmap_word[16]=
{0x0000000,0x03FF0080,0x87FFFFFE,0x07FFFFFE,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
0,0,0,0,0,0,0,0};
U32 chars_bitmap_filename[16]=
{0x0000000,0x03FF73FB,0xEFFFFFFF,0x2FFFFFFF,0,0,0,0,
0,0,0,0,0,0,0,0};
U32 chars_bitmap_dec_numeric[16]=
{0x0000000,0x03FF0000,0,0,0,0,0,0,
0,0,0,0,0,0,0,0};
U32 chars_bitmap_hex_numeric[16]=
{0x0000000,0x03FF0000,0x7E,0x7E,0,0,0,0,
0,0,0,0,0,0,0,0};
U32 chars_bitmap_white_space[16]=
{0x80003600,1,0,0,0,0,0,0,
0,0,0,0,0,0,0,0};
U32 chars_bitmap_non_eol_white_space[16]=
{0x80001200,1,0,0,0,0,0,0,
0,0,0,0,0,0,0,0};
U32 chars_bitmap_zero_cr_nl_cursor[16]=
{0x00002421,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0};
U32 chars_bitmap_zero_tab_ff_cr_nl_cursor[16]=
{0x00003621,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0};
U32 chars_bitmap_zero_tab_ff_cr_nl_cursor_dollar[16]=
{0x00003621,0x10,0,0,0,0,0,0,
0,0,0,0,0,0,0,0};
U32 chars_bitmap_getkey[16]=
{0x80002600,0xFFFFFFFF,0xFFFFFFFF,0x7FFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
0,0,0,0,0,0,0,0};
U32 chars_bitmap_printable[16]=
{0x80003600,0xFFFFFFFF,0xFFFFFFFF,0x7FFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
0,0,0,0,0,0,0,0};
U32 chars_bitmap_displayable[16]=
{0x80000000,0xFFFFFFFF,0xFFFFFFFF,0x7FFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
0,0,0,0,0,0,0,0};
U32 chars_bitmap_safe_dollar[16]=
{0x80000000,0xFFFFFFEF,0xFFFFFFFF,0x7FFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
0,0,0,0,0,0,0,0};//same but no dollar sign
U32 chars_bitmap_non_eol[16]=
{0xFFFFDBFE,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF};
U8 *LstSub(I64 sub, U8 *lst)
{//Point to lst entry.
//Not especially efficient but handy. Use an array of U8*'s for efficiency.
if (!lst) return NULL;
while (*lst && sub>0) {
while (*lst) // Advance to end of cur entry.
lst++;
lst++; // Skip trailing zero
if (*lst=='@') // Check for '@' alias lst entry
lst++;
else
sub--;
}
if (sub||!*lst)
return NULL;
else
return lst;
}
I64 LstMatch(U8 *needle, U8 *haystack_lst,I64 flags=0)
// RETURNS: -2 if Ambiguous, -1 if not found, else entry num
{ //Not especially efficient but handy. Use hash tables for efficiency.
I64 n,sub=0,result=-1;
U8 *ptr;
Bool exact_match=FALSE;
if (!haystack_lst) return -1;
n=StrLen(needle);
while (*haystack_lst) {
if (*haystack_lst=='@') { //Check for '@' alias haystack_lst entry
sub--;
haystack_lst++;
}
ptr=needle;
if (flags & LMF_IGNORE_CASE)
while (*ptr && ToUpper(*ptr)==ToUpper(*haystack_lst)) {
ptr++;
haystack_lst++;
}
else
while (*ptr && *ptr==*haystack_lst) {
ptr++;
haystack_lst++;
}
if (!*ptr) { // Did we reach end of needle
if (!*haystack_lst) // Did we reach end of haystack_lst entrycount
return sub; // Found Exact match
else {
if (result!=-1) {
if (!exact_match)
result=-2; // AMBIGUOUS RESPONSE unless later exact match
} else {
if (!(flags & LMF_EXACT))
result=sub;
}
}
}
while (*haystack_lst) // Advance to end of cur entry.
haystack_lst++;
haystack_lst++; // Skip trailing zero
sub++;
}
return result;
}
I64 StrOcc(U8 *src, I64 ch)
{
I64 i=0;
if (!src) return 0;
while (*src)
if (*src++==ch)
i++;
return i;
}
I64 Spaces2Tabs(U8 *dst,U8 *src)
{
U8 *src2;
I64 chged=0,space_cnt,space_cnt2,col=0;
if (*src)
while (TRUE) {
src2=src;
while (*src2==CH_SPACE)
src2++;
space_cnt=src2-src;
while (col+space_cnt>=8) {
space_cnt2=8-col;
if (space_cnt2==1)
*dst++=CH_SPACE;
else {
*dst++='\t';
chged+=space_cnt2-1;
}
space_cnt-=space_cnt2;
col=0;
}
if (*src2=='\t') {
if (space_cnt==1 && col==7)
*dst++=CH_SPACE;
else
chged+=space_cnt;
*dst++='\t';
col=0;
} else {
while (space_cnt--) {
*dst++=CH_SPACE;
if (++col==8)
col=0;
}
if (*src2) {
*dst++=*src2;
if (++col==8)
col=0;
} else
break;
}
src=++src2;
}
*dst=0;
return chged;
}
U8 *StrUtil(U8 *_src,I64 flags)
{//See $LK,"flags",A="MN:SUF_REM_SPACES"$
U8 *src=_src,*dst=_src;
I64 ch;
if (flags & SUF_REM_LEADING)
while (Bt(chars_bitmap_white_space,*src))
src++;
while (ch=*src++)
if (Bt(chars_bitmap_white_space,ch)) {
if (!(flags & SUF_REM_SPACES)) {
if (flags & SUF_SINGLE_SPACE) {
*dst++ = CH_SPACE;
while ((ch=*src++) && Bt(chars_bitmap_white_space,ch));
src--;
} else
*dst++ = ch;
}
} else if (!(flags & SUF_REM_CTRL_CHARS) || ch>=CH_SHIFT_SPACE)
*dst++=ch;
*dst=0;
if (flags & SUF_REM_TRAILING)
while (dst!=_src && (!*dst || Bt(chars_bitmap_white_space,*dst)))
*dst-- =0;
if (flags & SUF_TO_UPPER)
for (dst=_src;*dst;dst++) {
ch=*dst;
if ('a'<=ch<='z')
*dst=ch-0x20;
}
if (flags & SUF_TO_LOWER)
for (dst=_src;*dst;dst++) {
ch=*dst;
if ('A'<=ch<='Z')
*dst=ch+0x20;
}
if (flags & SUF_SAFE_DOLLAR)
for (dst=_src;*dst;dst++) {
ch=*dst;
if (!Bt(chars_bitmap_safe_dollar,*dst))
*dst='.';
}
if (flags & SUF_S2T)
Spaces2Tabs(_src,_src);
return _src;
}
U8 *StrFirstOcc(U8 *src,U8 *marker)
{
I64 ch;
while ((ch=*src++) && !StrOcc(marker,ch));
if (ch)
return src-1;
else
return NULL;
}
U8 *StrFirstRem(U8 *src,U8 *marker,U8 *dst=NULL)
{
I64 ch;
U8 *ptr=src,*result=dst;
if (dst) {
while ((ch=*ptr++) && !StrOcc(marker,ch))
*dst++=ch;
*dst=0;
} else
while ((ch=*ptr++) && !StrOcc(marker,ch));
if (ch)
StrCpy(src,ptr);
else
*src=0;
return result;
}
U8 *StrLastOcc(U8 *src,U8 *marker)
{
I64 ch;
U8 *result=NULL;
while (ch=*src++)
if (StrOcc(marker,ch))
result=src-1;
return result;
}
U8 *StrLastRem(U8 *src,U8 *marker,U8 *dst=NULL)
{
U8 *ptr;
if (ptr=StrLastOcc(src,marker)) {
if (dst)
StrCpy(dst,ptr+1);
*ptr=0;
} else {
if (dst)
StrCpy(dst,src);
*src=0;
}
return dst;
}
U8 *StrFind(U8 *needle,U8 *haystack_str,I64 flags=0)
{
Bool cont;
U8 *saved_haystack_str=haystack_str;
I64 plen=StrLen(needle);
do {
cont=FALSE;
if (flags & SFF_IGNORE_CASE)
haystack_str=StrIMatch(needle,haystack_str);
else
haystack_str=StrMatch(needle,haystack_str);
if (haystack_str && flags & SFF_WHOLE_LABELS_BEFORE) {
if (haystack_str!=saved_haystack_str) {
if (Bt(chars_bitmap_alpha_numeric,*(haystack_str-1))) {
haystack_str++;
if (*haystack_str)
cont=TRUE;
else
haystack_str=NULL;
}
}
}
if (haystack_str && flags & SFF_WHOLE_LABELS_AFTER) {
if (Bt(chars_bitmap_alpha_numeric,*(haystack_str+plen))) {
haystack_str++;
if (*haystack_str)
cont=TRUE;
else
haystack_str=NULL;
}
}
} while (cont);
return haystack_str;
}
Bool WildMatch(U8 *test_str,U8 *wild_str)
{
I64 ch1,ch2;
U8 *fall_back_src=NULL,*fall_back_wild=NULL;
while (TRUE) {
if (!(ch1=*test_str++)) {
if (*wild_str && *wild_str!='*')
return FALSE;
else
return TRUE;
} else {
if (!(ch2=*wild_str++))
return FALSE;
else {
if (ch2=='*') {
fall_back_wild=wild_str-1;
fall_back_src=test_str;
if (!(ch2=*wild_str++))
return TRUE;
while (ch2!=ch1)
if (!(ch1=*test_str++))
return FALSE;
} else
if (ch2!='?' && ch1!=ch2) {
if (fall_back_wild) {
wild_str=fall_back_wild;
test_str=fall_back_src;
fall_back_wild=NULL;
fall_back_src=NULL;
} else
return FALSE;
}
}
}
}
}
+192
View File
@@ -0,0 +1,192 @@
U8 *Tabs2Spaces(U8 *src)
{
I64 ch,i,j,l=StrLen(src)<<1+2,col=0;
U8 *dst=MAlloc(l),*temp;
while (ch=*src++) {
if (ch=='\t') {
j=(col+8) & ~7;
for (i=col;i<j;i++) {
dst[i]=CH_SPACE;
if (i>=l-2) {
temp=MAlloc(l<<1);
MemCpy(temp,dst,i+1);
Free(dst);
l<<=1;
dst=temp;
}
}
col=j;
} else {
dst[col]=ch;
if (col>=l-2) {
temp=MAlloc(l<<1);
MemCpy(temp,dst,col+1);
Free(dst);
l<<=1;
dst=temp;
}
col++;
}
}
dst[col]=0;
return dst;
}
U8 *ScaleIndent(U8 *src,F64 indent_scale_factor)
{
I64 ch,i,col=0;
U8 *dst,*dst2;
while (ch=*src++) {
if (ch=='\t')
col=(col+8) & -0x8;
else if (ch==CH_SPACE)
col++;
else
break;
}
src--;
col=Round(indent_scale_factor*col);
dst=dst2=MAlloc(StrLen(src)+col/8+col&7+1);
for (i=col/8;i>0;i--)
*dst2++='\t';
for (i=col&7;i>0;i--)
*dst2++=CH_SPACE;
StrCpy(dst2,src);
return dst;
}
U8 *MStrUtil(U8 *src,I64 flags,F64 indent_scale_factor=0)
//Return a $LK,"MAlloc",A="MN:MAlloc"$()ed result from StrUtil
{
U8 *dst=StrNew(src),*dst2,*temp;
StrUtil(dst,flags);
if (flags & SUF_T2S) {
temp=Tabs2Spaces(dst);
Free(dst);
dst=temp;
}
if (flags & SUF_SCALE_INDENT)
dst2=ScaleIndent(dst,indent_scale_factor);
else
dst2=StrNew(dst); //Shorten
Free(dst);
return dst2;
}
U0 GetOutOfDollar()
{
CDoc *doc;
if (IsRaw) {
if (sys_raw_flags&RWF_IN_DOLLAR)
'$$';
} else {
if (fp_doc_put && (doc=(*fp_doc_put)(Fs)) && doc->flags&DOCF_IN_DOLLAR)
'$$';
}
}
U0 NewLine(I64 cnt=1)
{
while (cnt-->0)
'\n';
}
U0 Spaces(I64 cnt=1)
{
while (cnt-->0)
'' CH_SPACE;
}
Bool YorN()
{
I64 ch;
"(y or n)? ";
while (TRUE) {
ch=ToUpper(GetChar(,FALSE));
if (ch=='Y') {
"$$PT$$YES$$FG$$\n";
return TRUE;
} else if (ch=='N') {
"$$PT$$NO$$FG$$\n";
return FALSE;
}
}
}
I64 PressAKey()
{
"$$BK,1$$PRESS A KEY$$BK,0$$\n";
return GetChar(,FALSE);
}
Bool AreYouSure()
{
"ARE YOU SURE ";
return YorN;
}
U0 Help()
{
if (IsDbg)
DbgHelp;
else
PopUp("Type(\"::/Doc/HelpIndex.TXT\");DocHome;View;");
}
U0 ScanFlags(U8 *f,U8 *lst,U8 *st)
{
I64 i;
U8 *st2,*ptr;
if (st) {
st2=MAlloc(StrLen(st)+1);
while (*st) {
while (*st && *st!='+' && *st!='-')
st++;
if (*st=='+') {
st++;
if (*st) {
ptr=st2;
while (*st && *st!='+' && *st!='-' && *st!=CH_SPACE && *st!=CH_SHIFT_SPACE)
*ptr++=*st++;
*ptr=0;
i=LstMatch(st2,lst);
if (i>=0)
LBts(f,i);
else {
Free(st2);
throw('ScanFlag');
}
}
} else if (*st=='-') {
st++;
if (*st) {
ptr=st2;
while (*st && *st!='+' && *st!='-' && *st!=CH_SPACE && *st!=CH_SHIFT_SPACE)
*ptr++=*st++;
*ptr=0;
i=LstMatch(st2,lst);
if (i>=0)
LBtr(f,i);
else {
Free(st2);
throw('ScanFlag');
}
}
}
}
Free(st2);
}
}
U8 *SPrintFlags(U8 *dst,U8 *lst,I64 flags)
{
I64 i;
*dst=0;
while (flags) {
i=Bsf(flags);
Btr(&flags,i);
CatPrint(dst,"+%z",i,lst);
}
return dst;
}
+976
View File
@@ -0,0 +1,976 @@
#define SPF_PAD_ZERO 0x001
#define SPF_LEFT_JUSTIFY 0x002
#define SPF_TRUNCATE 0x004
#define SPF_COMMA 0x008
#define SPF_DOLLAR 0x010
#define SPF_SLASH 0x020
#define SPF_QUESTION 0x040
#define SPF_SUB_FMT 0x080
#define SPF_DECIMAL 0x100
#define SPF_NEG 0x200
#define SPF_NEG_E 0x400
#define SPF_NEG_SUB_FMT 0x800
U0 SPutChar(U8 **_dst,U8 ch,U8 **_buf)
{
I64 i;
U8 *dst=*_dst,*buf;
if (_buf) {
buf=*_buf;
i=dst-buf;
if (i>=MSize(buf)) {
buf=MAlloc(i<<1+1);
MemCpy(buf,*_buf,i);
dst=buf+i;
*_buf=buf;
}
}
*dst++=ch;
*_dst=dst;
}
U0 OutStr(U8 *ptr,U8 **_buf,U8 **_dst,I64 len,I64 flags)
{
I64 i,j;
if (!ptr)
i=0;
else
i=StrLen(ptr);
if (flags&SPF_TRUNCATE && i>len)
i=len;
if (flags&SPF_LEFT_JUSTIFY) {
for (j=0;j<i;j++)
SPutChar(_dst,*ptr++,_buf);
for (j=0;j<len-i;j++)
SPutChar(_dst,CH_SPACE,_buf);
} else {
for (j=0;j<len-i;j++)
SPutChar(_dst,CH_SPACE,_buf);
for (j=len-i;j<len;j++)
SPutChar(_dst,*ptr++,_buf);
}
}
U8 *MPrintTime(CDate cdt)
{
CDateStruct ds;
Date2Struct(&ds,cdt+local_time_offset);
return MPrint("%02d:%02d:%02d",ds.hour,ds.min,ds.sec);
}
U8 *MPrintDate(CDate cdt)
{
CDateStruct ds;
Date2Struct(&ds,cdt+local_time_offset);
return MPrint("%02d/%02d/%02d",ds.mon,ds.day_of_mon,ds.year%100);
}
U8 *MPrintQ(U8 *ptr,I64 flags)
{
U8 **_buf,*buf,**_dst,*dst;
I64 ch;
buf=MAlloc(128);
_buf=&buf;
dst=buf;
_dst=&dst;
if (ptr)
while (ch=*ptr++) {
switch (ch) {
case '$$':
if (flags&SPF_DOLLAR) {
SPutChar(_dst,'\\',_buf);
SPutChar(_dst,'$$'>>6&7+'0',_buf);
SPutChar(_dst,'$$'>>3&7+'0',_buf);
SPutChar(_dst,'$$'&7+'0',_buf);
} else {
SPutChar(_dst,ch,_buf);
SPutChar(_dst,ch,_buf);
}
break;
case '%':
SPutChar(_dst,ch,_buf);
if (flags&SPF_SLASH)
SPutChar(_dst,ch,_buf);
break;
case '\n':
SPutChar(_dst,'\\',_buf);
SPutChar(_dst,'n',_buf);
break;
case '\r':
SPutChar(_dst,'\\',_buf);
SPutChar(_dst,'r',_buf);
break;
case '\t':
SPutChar(_dst,'\\',_buf);
SPutChar(_dst,'t',_buf);
break;
case '"':
case '\\':
SPutChar(_dst,'\\',_buf);
SPutChar(_dst,ch,_buf);
break;
default:
if (CH_SHIFT_SPACE<=ch<=0x7F) {
SPutChar(_dst,ch,_buf);
} else {
SPutChar(_dst,'\\',_buf);
SPutChar(_dst,ch>>6&7+'0',_buf);
SPutChar(_dst,ch>>3&7+'0',_buf);
SPutChar(_dst,ch&7+'0',_buf);
}
}
}
SPutChar(_dst,0,_buf);
return buf;
}
U8 *MPrintq(U8 *ptr,I64 flags)
{
U8 **_buf,*buf,**_dst,*dst;
I64 i,ch,ch1;
buf=MAlloc(128);
_buf=&buf;
dst=buf;
_dst=&dst;
if (ptr)
while (ch=*ptr++) {
ch1=*ptr;
switch (ch) {
case '\\':
switch (ch1) {
sub_switch_start:
case 'n':
SPutChar(_dst,'\n',_buf);
break;
case 'r':
SPutChar(_dst,'\r',_buf);
break;
case '"':
SPutChar(_dst,'"',_buf);
break;
case '\'':
SPutChar(_dst,'\'',_buf);
break;
case '\`':
SPutChar(_dst,'\`',_buf);
break;
case '\\':
SPutChar(_dst,'\\',_buf);
break;
case 't':
SPutChar(_dst,'\t',_buf);
break;
sub_switch_end:
ptr++;
break;
sub_switch_start:
case 'x':
case 'X':
i=0;
ptr++;
while (TRUE) {
ch1=ToUpper(*ptr++);
if (Bt(chars_bitmap_hex_numeric,ch1)) {
if (ch1<='9')
i=i<<4+ch1-'0';
else
i=i<<4+ch1-'A'+10;
} else
break;
}
break;
case 'b':
case 'B':
i=0;
ptr++;
while (TRUE) {
ch1=*ptr++;
if ('0'<=ch1<='1')
i=i<<1+ch1-'0';
else
break;
}
break;
case 'o':
case 'O':
i=0;
ptr++;
goto sq_octal;
case '0'...'7':
i=ch1-'0';
ptr++;
sq_octal:
while (TRUE) {
ch1=*ptr++;
if ('0'<=ch1<='7')
i=i<<3+ch1-'0';
else
break;
}
break;
sub_switch_end:
SPutChar(_dst,i,_buf);
ptr--;
break;
default:
SPutChar(_dst,ch,_buf);
}
break;
case '$$':
SPutChar(_dst,ch,_buf);
if (ch1=='$$')
ptr++;
break;
case '%':
SPutChar(_dst,ch,_buf);
if (flags&SPF_SLASH && ch1=='%')
ptr++;
break;
default:
SPutChar(_dst,ch,_buf);
}
}
SPutChar(_dst,0,_buf);
return buf;
}
U8 *sys_pos_powers_lets=" KMGTPEZY",
*sys_neg_powers_lets=" mænpfazy",
*sys_pos_powers_lst="kilo\0mega\0giga\0tera\0peta\0exa\0zetta\0yotta\0",
*sys_neg_powers_lst="milli\0micro\0nano\0pico\0femto\0atto\0zepto\0yocto\0";
#define TEMP_BUF_LEN 256
#define SLOP 8
U8 *SPrintJoin(U8 *dst,U8 *src,I64 argc,I64 *argv)
{//$LK,"Print Extended Codes",A="FA:::/Doc/HolyC.TXT,SPrintCodes"$
// In float formatting, do not exceed 18-digits
// before or after the decimal point
// because the numbers before and after
// the decimal point are stored
// in 64-bits. Use exponentiated forms
// to avoid this.
I64 i,j,l,ch,k,k0,n,n0,len,dec_len,flags,
sub_fmt,comma_cnt,comma_fmt_cnt,cur_arg=0;
U64 m;
F64 d,d1;
U8 *ptr,**_buf,*buf,**_dst,temp_buf[TEMP_BUF_LEN],temp_buf2[TEMP_BUF_LEN*2];
if (!src)
throw('SPrint');
if (dst) {
_buf=NULL;
buf=dst;
} else {
buf=MAlloc(128);
_buf=&buf;
dst=buf;
}
_dst=&dst;
while (ch = *src++) {
if (ch=='%') {
flags=0;
if (*src=='-') {
flags|=SPF_LEFT_JUSTIFY;
src++;
}
if (*src=='0') {
flags|=SPF_PAD_ZERO;
src++;
}
len=0;
while ('0'<=*src<='9')
len=len*10+ *src++ -'0';
if (*src=='*') {
src++;
if (cur_arg>=argc)
throw('SPrint');
len=argv[cur_arg++];
}
dec_len=0;
if (*src=='.') {
src++;
while ('0'<=*src<='9')
dec_len=dec_len*10+ *src++ -'0';
if (*src=='*') {
src++;
if (cur_arg>=argc)
throw('SPrint');
dec_len=argv[cur_arg++];
}
flags|=SPF_DECIMAL;
}
while (TRUE) {
switch (*src) {
sub_switch_start:
case '$$':
flags|=SPF_DOLLAR;
break;
case '/':
flags|=SPF_SLASH;
break;
case ',':
flags|=SPF_COMMA;
break;
case 't':
flags|=SPF_TRUNCATE;
break;
case 'l': //harmless
break;
sub_switch_end:
src++;
break;
default:
goto sp_in_sub_fmt;
}
}
sp_in_sub_fmt:
sub_fmt=0;
if (*src=='h') {
src++;
flags|=SPF_SUB_FMT;
if (*src=='?') {
src++;
flags|=SPF_QUESTION;
} else {
if (*src=='*') {
src++;
if (cur_arg>=argc)
throw('SPrint');
sub_fmt=argv[cur_arg++];
} else {
if (*src=='-') {
src++;
flags|=SPF_NEG_SUB_FMT;
}
while ('0'<=*src<='9')
sub_fmt=sub_fmt*10+ *src++ -'0';
if (flags&SPF_NEG_SUB_FMT)
sub_fmt=-sub_fmt;
}
}
}
k=0;
switch (*src++) {
sub_switch_start:
case 'F':
if (cur_arg>=argc)
throw('SPrint');
ptr=FileRead(argv[cur_arg++]);
break;
case 'Q':
if (cur_arg>=argc)
throw('SPrint');
ptr=MPrintQ(argv[cur_arg++],flags);
break;
case 'q':
if (cur_arg>=argc)
throw('SPrint');
ptr=MPrintq(argv[cur_arg++],flags);
break;
case 'D':
if (cur_arg>=argc)
throw('SPrint');
ptr=MPrintDate(argv[cur_arg++]);
break;
case 'T':
if (cur_arg>=argc)
throw('SPrint');
ptr=MPrintTime(argv[cur_arg++]);
break;
sub_switch_end:
OutStr(ptr,_buf,_dst,len,flags);
Free(ptr);
break;
sub_switch_start:
case 's':
if (cur_arg>=argc)
throw('SPrint');
ptr=argv[cur_arg++];
break;
case 'S':
if (cur_arg>=argc)
throw('SPrint');
ptr=Define(argv[cur_arg++]);
break;
case 'z':
if (cur_arg+1>=argc)
throw('SPrint');
ptr=LstSub(argv[cur_arg],argv[cur_arg+1]);
cur_arg=cur_arg+2;
break;
case 'Z':
if (cur_arg+1>=argc)
throw('SPrint');
ptr=DefineSub(argv[cur_arg],argv[cur_arg+1]);
cur_arg=cur_arg+2;
break;
sub_switch_end:
OutStr(ptr,_buf,_dst,len,flags);
break;
sub_switch_start:
case 'c':
if (cur_arg>=argc)
throw('SPrint');
temp_buf[0](I64)=argv[cur_arg++];
temp_buf[8]=0;
break;
case 'C':
if (cur_arg>=argc)
throw('SPrint');
temp_buf[0](I64)=argv[cur_arg++];
temp_buf[8]=0;
ptr=temp_buf;
while (*ptr) {
*ptr=ToUpper(*ptr);
ptr++;
}
break;
case 'p':
if (cur_arg>=argc)
throw('SPrint');
if (flags&SPF_TRUNCATE)
SPrintPSect(temp_buf,argv[cur_arg++],len);
else
SPrintPSect(temp_buf,argv[cur_arg++],0);
break;
sub_switch_end:
OutStr(temp_buf,_buf,_dst,len,flags);
break;
case 'P':
if (cur_arg>=argc)
throw('SPrint');
if (flags&SPF_TRUNCATE)
SPrintPSect(temp_buf,argv[cur_arg],len);
else
SPrintPSect(temp_buf,argv[cur_arg],0);
if (!IsRaw || !_buf) {
SPrint(temp_buf2,"$$LK,\"%s\",A=\"AD:0x%X\"$$",temp_buf,argv[cur_arg]);
OutStr(temp_buf2,_buf,_dst,len,flags);
} else
OutStr(temp_buf,_buf,_dst,len,flags);
cur_arg++;
break;
case 'd':
if (cur_arg>=argc)
throw('SPrint');
m=argv[cur_arg++];
if (m(I64)<0) {
flags|=SPF_NEG;
m=-m;
}
sp_out_dec:
if (flags&SPF_SUB_FMT) {
if (!len) len=12;
d=m;
goto sp_out_eng;
}
if (flags&SPF_COMMA) {
comma_fmt_cnt=comma_cnt=3;
do {
temp_buf[k++]=ModU64(&m,10)+'0';
if (!m) break;
if (!--comma_cnt) {
temp_buf[k++]=',';
comma_cnt=3;
}
} while (k<TEMP_BUF_LEN-SLOP);
sp_out_comma_num:
if (flags&SPF_NEG)
i=1;
else
i=0;
if (len<0)
len=0;
if (flags&SPF_TRUNCATE && k+i>len)
k=len-i;
if (k<0)
k=0;
if (flags&SPF_PAD_ZERO) {
if (flags&SPF_NEG)
SPutChar(_dst,'-',_buf);
comma_cnt=(len-k-i+comma_fmt_cnt-comma_cnt+1)%(comma_fmt_cnt+1)+1;
for (;i<len-k;i++) {
if (!--comma_cnt) {
SPutChar(_dst,',',_buf);
comma_cnt=comma_fmt_cnt;
if (++i>=len-k)
break;
}
SPutChar(_dst,'0',_buf);
}
} else {
for (;i<len-k;i++)
SPutChar(_dst,CH_SPACE,_buf);
if (flags&SPF_NEG)
SPutChar(_dst,'-',_buf);
}
} else {
do {
temp_buf[k++]=ModU64(&m,10)+'0';
if (!m) break;
} while (k<TEMP_BUF_LEN-SLOP);
sp_out_num:
if (flags&SPF_NEG)
i=1;
else
i=0;
if (len<0)
len=0;
if (flags&SPF_TRUNCATE && k+i>len)
k=len-i;
if (k<0)
k=0;
if (flags&SPF_PAD_ZERO) {
if (flags&SPF_NEG)
SPutChar(_dst,'-',_buf);
for (;i<len-k;i++)
SPutChar(_dst,'0',_buf);
} else {
for (;i<len-k;i++)
SPutChar(_dst,CH_SPACE,_buf);
if (flags&SPF_NEG)
SPutChar(_dst,'-',_buf);
}
}
for (i=k-1;i>=0;i--)
SPutChar(_dst,temp_buf[i],_buf);
break;
case 'u':
if (cur_arg>=argc)
throw('SPrint');
m=argv[cur_arg++];
goto sp_out_dec;
case 'f':
if (cur_arg>=argc)
throw('SPrint');
d=argv[cur_arg++](F64);
if (d<0) {
flags|=SPF_NEG;
d=-d;
}
if (d==ì) {
sp_out_inf:
if (flags&SPF_NEG)
i=1;
else
i=0;
k=1;
if (len<0)
len=0;
if (flags&SPF_TRUNCATE && k+i>len)
k=len-i;
if (k<0)
k=0;
for (;i<len-k;i++)
SPutChar(_dst,CH_SPACE,_buf);
if (flags&SPF_NEG)
SPutChar(_dst,'-',_buf);
for (i=0;i<k;i++)
SPutChar(_dst,'ì',_buf);
break;
}
sp_out_f:
if (dec_len<0)
dec_len=0;
n=Log10(d);
if (i=dec_len) {
if (flags&SPF_COMMA)
i=i-i/4;
if (n+i>17) {
n+=i-17;
d*=Pow10I64(i-n);
} else {
n=0;
d*=Pow10I64(i);
}
i=dec_len;
} else if (n>17) {
n-=17;
d*=Pow10I64(-n);
} else
n=0;
m=Round(d);
if (flags&SPF_COMMA) {
comma_cnt=i&3;
while (i-- && k<TEMP_BUF_LEN-SLOP) {
if (i>2 && !comma_cnt--) {
temp_buf[k++]=',';
comma_cnt=2;
if (!--i) break;
}
if (n) {
n--;
temp_buf[k++]='0';
} else
temp_buf[k++]=ModU64(&m,10)+'0';
if (!i) break;
}
} else {
while (i-- && k<TEMP_BUF_LEN-SLOP) {
if (n) {
n--;
temp_buf[k++]='0';
} else
temp_buf[k++]=ModU64(&m,10)+'0';
}
}
if (dec_len)
temp_buf[k++]='.';
if (flags&SPF_COMMA) {
comma_cnt=3;
do {
if (n) {
n--;
temp_buf[k++]='0';
} else
temp_buf[k++]=ModU64(&m,10)+'0';
if (!m) break;
if (!--comma_cnt) {
temp_buf[k++]=',';
comma_cnt=3;
}
} while (k<TEMP_BUF_LEN-SLOP);
} else {
do {
if (n) {
n--;
temp_buf[k++]='0';
} else
temp_buf[k++]=ModU64(&m,10)+'0';
if (!m) break;
} while (k<TEMP_BUF_LEN-SLOP);
}
goto sp_out_num;
case 'e':
if (!len) len=12;
flags|=SPF_TRUNCATE;
if (cur_arg>=argc)
throw('SPrint');
d=argv[cur_arg++](F64);
if (d<0) {
flags|=SPF_NEG;
d=-d;
}
if (d==ì) goto sp_out_inf;
if (d)
n=Floor(Log10(d));
else
n=0;
sp_out_e:
d/=Pow10I64(n);
k0=k;
for (l=0;l<2;l++) {
n0=n;
if (n<0) {
n=-n;
flags|=SPF_NEG_E;
} else
flags&=~SPF_NEG_E;
i=3;
do temp_buf[k++]=ModU64(&n,10)+'0';
while (n && i--);
if (flags&SPF_NEG_E)
temp_buf[k++]='-';
temp_buf[k++]='e';
dec_len=len-k-2;
if (flags&SPF_NEG)
dec_len--;
if (d) {
d1=d+Pow10I64(-dec_len)/2;
if (d1<1.0) {
d*=10;
n=n0-1;
k=k0;
} else if (d1>=10) {
d/=10;
n=n0+1;
k=k0;
} else
break;
} else
break;
}
goto sp_out_f;
case 'g':
if (!len) len=12;
flags|=SPF_TRUNCATE;
if (cur_arg>=argc)
throw('SPrint');
d=argv[cur_arg++](F64);
if (d<0) {
flags|=SPF_NEG;
d=-d;
}
if (d==ì) goto sp_out_inf;
if (d)
n=Floor(Log10(d));
else
n=0;
if (n>=len-1-dec_len || n<-(dec_len-1))
goto sp_out_e;
else
goto sp_out_f;
case 'n':
if (!len) len=12;
flags|=SPF_TRUNCATE;
if (cur_arg>=argc)
throw('SPrint');
d=argv[cur_arg++](F64);
if (d<0) {
flags|=SPF_NEG;
d=-d;
}
sp_out_eng: //Engineering notation
if (d==ì) goto sp_out_inf;
if (d)
n=FloorI64(Floor(Log10(d)),3);
else
n=0;
d/=Pow10I64(n);
if (n<0) {
n=-n;
flags|=SPF_NEG_E;
}
if (flags&SPF_SUB_FMT && -24<=n<=24) {
if (flags&SPF_QUESTION) {
if (flags&SPF_NEG_E)
i=-n/3;
else
i=n/3;
j=0;
} else {
if (flags&SPF_NEG_E)
j=-n-sub_fmt;
else
j=n-sub_fmt;
d*=Pow10I64(j);
i=sub_fmt/3;
}
if (i<0)
temp_buf[k++]=sys_neg_powers_lets[-i];
else if (i>0)
temp_buf[k++]=sys_pos_powers_lets[i];
else if (len!=0)
temp_buf[k++]=CH_SPACE;
if (!(flags&SPF_DECIMAL)) {
dec_len=len-k-2;
if (flags&SPF_NEG)
dec_len--;
if (j>0) {
if (flags&SPF_COMMA)
dec_len-=4*j/3;
else
dec_len-=j;
}
d1=d+Pow10I64(-dec_len+1)/2;
if (d1>=10) {
dec_len--;
if (d1>=100)
dec_len--;
}
}
} else {
i=3;
do temp_buf[k++]=ModU64(&n,10)+'0';
while (n && i--);
if (flags&SPF_NEG_E)
temp_buf[k++]='-';
temp_buf[k++]='e';
if (!dec_len) {
dec_len=len-k-2;
if (flags&SPF_NEG)
dec_len--;
d1=d+Pow10I64(-dec_len+1)/2;
if (d1>=10) {
dec_len--;
if (d1>=100)
dec_len--;
}
}
}
if (flags&SPF_COMMA) {
if (len && dec_len>0 && !(dec_len&3))
temp_buf[k++]=',';
dec_len-=dec_len/4;
}
goto sp_out_f;
case 'X':
if (cur_arg>=argc)
throw('SPrint');
m=argv[cur_arg++];
if (flags&SPF_COMMA) {
comma_fmt_cnt=comma_cnt=4;
do {
temp_buf[k]= m&15 +'0';
if (temp_buf[k]>'9') temp_buf[k]+='A'-0x3A;
k++;
m>>=4;
if (!m) break;
if (!--comma_cnt) {
temp_buf[k++]=',';
comma_cnt=4;
}
} while (k<TEMP_BUF_LEN-SLOP);
goto sp_out_comma_num;
} else {
do {
temp_buf[k]= m&15 +'0';
if (temp_buf[k]>'9') temp_buf[k]+='A'-0x3A;
k++;
m>>=4;
} while (m && k<TEMP_BUF_LEN-SLOP);
goto sp_out_num;
}
case 'x':
if (cur_arg>=argc)
throw('SPrint');
m=argv[cur_arg++];
if (flags&SPF_COMMA) {
comma_fmt_cnt=comma_cnt=4;
do {
temp_buf[k]= m&15 +'0';
if (temp_buf[k]>'9') temp_buf[k]+='a'-0x3A;
k++;
m>>=4;
if (!m) break;
if (!--comma_cnt) {
temp_buf[k++]=',';
comma_cnt=4;
}
} while (k<TEMP_BUF_LEN-SLOP);
goto sp_out_comma_num;
} else {
do {
temp_buf[k]= m&15 +'0';
if (temp_buf[k]>'9') temp_buf[k]+='a'-0x3A;
k++;
m>>=4;
} while (m && k<TEMP_BUF_LEN-SLOP);
goto sp_out_num;
}
case 'b':
case 'B':
if (cur_arg>=argc)
throw('SPrint');
m=argv[cur_arg++];
if (flags&SPF_COMMA) {
comma_fmt_cnt=comma_cnt=4;
do {
temp_buf[k++]= m&1 +'0';
m>>=1;
if (!m) break;
if (!--comma_cnt) {
temp_buf[k++]=',';
comma_cnt=4;
}
} while (k<TEMP_BUF_LEN-SLOP);
goto sp_out_comma_num;
} else {
do {
temp_buf[k++]= m&1 +'0';
m>>=1;
} while (m && k<TEMP_BUF_LEN-SLOP);
goto sp_out_num;
}
case 'o':
case 'O':
if (cur_arg>=argc)
throw('SPrint');
m=argv[cur_arg++];
if (flags&SPF_COMMA) {
comma_fmt_cnt=comma_cnt=3;
do {
temp_buf[k++]= m&7 +'0';
m>>=3;
if (!m) break;
if (!--comma_cnt) {
temp_buf[k++]=',';
comma_cnt=3;
}
} while (k<TEMP_BUF_LEN-SLOP);
goto sp_out_comma_num;
} else {
do {
temp_buf[k++]= m&7 +'0';
m>>=3;
} while (m && k<TEMP_BUF_LEN-SLOP);
goto sp_out_num;
}
case '%':
SPutChar(_dst,'%',_buf);
break;
}
} else
SPutChar(_dst,ch,_buf);
}
SPutChar(_dst,0,_buf);
return buf;
}
U8 *SPrint(U8 *dst,U8 *fmt,...)
{ //See $LK,"SPrintJoin",A="MN:SPrintJoin"$()
return SPrintJoin(dst,fmt,argc,argv);
}
U8 *CatPrint(U8 *_dst,U8 *fmt,...)
{ //StrCat(). See $LK,"SPrintJoin",A="MN:SPrintJoin"$()
U8 *dst=_dst;
while (*dst)
dst++;
SPrintJoin(dst,fmt,argc,argv);
return _dst;
}
U0 Print(U8 *fmt,...)
{//$LK,"Print Extended Codes",A="FA:::/Doc/HolyC.TXT,SPrintCodes"$
//See $LK,"SPrintJoin",A="MN:SPrintJoin"$()
U8 *buf=SPrintJoin(NULL,fmt,argc,argv);
PutS(buf);
Free(buf);
}
U8 *MPrint(U8 *fmt,...)
{ //See $LK,"SPrintJoin",A="MN:SPrintJoin"$()
U8 *result,*buf=SPrintJoin(NULL,fmt,argc,argv);
result=StrNew(buf);
Free(buf);
return result;
}
U0 PrintErr(U8 *fmt,...)
{
U8 *buf=SPrintJoin(NULL,fmt,argc,argv);
GetOutOfDollar;
ST_ERR_ST "%s",buf;
Free(buf);
}
U0 PrintWarn(U8 *fmt,...)
{
U8 *buf=SPrintJoin(NULL,fmt,argc,argv);
GetOutOfDollar;
ST_WARN_ST "%s",buf;
Free(buf);
}
+355
View File
@@ -0,0 +1,355 @@
I64 A2I64(U8 *st,I64 radix=10,U8 **_end_ptr=NULL)
{//ASCII to I64. Similar to strtoul().
//Allows radix change with "0x20" "0b1010" "0d123" "0o18".
//Be careful of A2I64("0b101",16)-->0xB101.
Bool neg=FALSE;
I64 ch,result=0;
if (!st || !(2<=radix<=36)) {
if (_end_ptr) *_end_ptr=st;
return 0;
}
while (Bt(chars_bitmap_white_space,*st))
st++;
while (TRUE)
switch (*st) {
case '-':
st++;
neg=!neg;
break;
case '+':
st++;
break;
case '0':
st++;
ch=ToUpper(*st);
if (ch>='B' && (radix<=10 || ch>'A'+radix-11))
switch (ch) {
case 'B': radix=2; st++; break;
case 'O': radix=8; st++; break;
case 'D': radix=10; st++; break;
case 'X': radix=16; st++; break;
}
default:
goto ai_cont;
}
ai_cont:
while (ch=ToUpper(*st++)) {
if (radix>10) {
if ('0'<=ch<='9')
result=result*radix+ch-'0';
else if ('A'<=ch<='A'+radix-11)
result=result*radix+ch-'A'+10;
else
break;
} else if ('0'<=ch<='0'+radix-1)
result=result*radix+ch-'0';
else
break;
}
if (_end_ptr) *_end_ptr=st-1;
if (neg)
return -result;
else
return result;
}
F64 A2F64(U8 *src,U8 **_end_ptr=NULL)
{/*ASCII string to F64.
Does not allow more than 18-digits
before or after the decimal point
because the numbers before and after
the decimal point are stored
in 64-bits. Use exponentiated forms
to avoid this.
*/
I64 i,j,k,ch;
F64 d;
Bool neg=FALSE,neg_e=FALSE;
ch=*src++;
while (Bt(chars_bitmap_white_space,ch))
ch=*src++;
if (ch=='-') {
neg=TRUE;
ch=*src++;
}
if (!StrNCmp(src-1,"inf",3)) {
d=ì;
src+=3;
goto a2f_end;
}
if (*src=='ì') {
d=ì;
src++;
goto a2f_end;
}
i=0;
while (TRUE) {
if (Bt(chars_bitmap_dec_numeric,ch))
i=i*10+ch-'0';
else {
if (ch=='.' || ch=='e' || ch=='E')
break;
d=i;
goto a2f_end;
}
ch=*src++;
}
if (ch=='.')
ch=*src++;
k=0;
while (TRUE) {
if (Bt(chars_bitmap_dec_numeric,ch)) {
i=i*10+ch-'0';
k++;
} else {
if (ch=='e' || ch=='E')
break;
d=i*Pow10I64(-k);
goto a2f_end;
}
ch=*src++;
}
ch=*src++;
if (ch=='-') {
neg_e=TRUE;
ch=*src++;
}
j=0;
while (TRUE) {
if (Bt(chars_bitmap_dec_numeric,ch))
j=j*10+ch-'0';
else {
if (neg_e)
d=i*Pow10I64(-j-k);
else
d=i*Pow10I64(j-k);
goto a2f_end;
}
ch=*src++;
}
a2f_end:
if (_end_ptr) *_end_ptr=src-1;
if (neg)
return -d;
else
return d;
}
/*
A2Date()
This routine recognizes the following formats:
1) "*+nnnn" "*-nnnn"
2) mm/dd
3) mm/dd/yy
It also supports some funs
SM() start of mon
EM() end of mon
SM() start of year
EY() end of year
Full expressions are not implimented
but you can do stuff like SM(*-7)+3
and it will return the 3rd day after
the start of mon for seven days before
today.
*/
CDate A2Date(U8 *_src)
//ASCII date to CDate
{
CDate result=0;
CDateStruct ds;
U8 *src=MStrUtil(_src,SUF_REM_SPACES|SUF_TO_UPPER),
*v=StrNew(src),
*p1=src;
Bool start_mon=FALSE,end_mon=FALSE,
start_year=FALSE,end_year=FALSE;
MemSet(&ds,0,sizeof(CDateStruct));
if (!StrNCmp(p1,"SM(",3)) {
p1+=3;
start_mon=TRUE;
} else if (!StrNCmp(p1,"EM(",3)) {
p1+=3;
end_mon=TRUE;
} else if (!StrNCmp(p1,"SY(",3)) {
p1+=3;
start_year=TRUE;
} else if (!StrNCmp(p1,"EY(",3)) {
p1+=3;
end_year=TRUE;
}
if (*p1=='*') {
p1++;
if (*p1=='+' || *p1=='-')
result.date=A2I64(p1,,&p1);
result+=Now+local_time_offset;
} else {
StrFirstRem(p1,"/",v); //Put mon into v
ds.mon=A2I64(v);
if (StrOcc(p1,'/')) {
StrFirstRem(p1,"/",v); //Put day into v leaving year in p1
ds.day_of_mon=A2I64(v);
ds.year=A2I64(p1,,&p1);
if (ds.year<100) //if not 4 digit year
ds.year+=2000;
} else {
ds.day_of_mon=A2I64(p1,,&p1);
ds.year=Year;
}
result=Struct2Date(&ds);
}
if (*p1==')') p1++;
if (start_mon)
result.date=FirstDayOfMon(result.date);
else if (end_mon)
result.date=LastDayOfMon(result.date);
else if (start_year)
result.date=FirstDayOfYear(result.date);
else if (end_year)
result.date=LastDayOfYear(result.date);
if (*p1=='+' || *p1=='-')
result.date+=A2I64(p1);
Free(src);
Free(v);
return result-local_time_offset;
}
U8 *ScanJoin(U8 *src,U8 *fmt,I64i argc,I64i *argv)
//Pass ptr to data,
//For %s pass ptr to ptr (be careful because addr
//of array is the same as array--create ptr to array and take addr
{
U8 ch,*buf,*ptr,**pptr;
Bool left_justify=FALSE;
I64 cur_arg=0,i,len,*i_ptr,dec_len;
F64 *d_ptr;
if (!fmt)
throw('Scan');
while (ch = *fmt++) {
if (ch=='%') {
if (*fmt=='%') {
src++;
fmt++;
} else {
if (*fmt=='-') {
left_justify=TRUE;
fmt++;
} else
left_justify=FALSE;
len=0;
while ('0'<=*fmt<='9')
len=len*10+ (*fmt++ -'0');
if (*fmt=='*') {
fmt++;
if (cur_arg>=argc)
throw('Scan');
len=argv[cur_arg++];
}
ch=*fmt++;
if (ch && !len) {
ptr=src;
while (*ptr && *ptr!=*fmt)
ptr++;
len=ptr-src;
} else {
if (ch=='.') {
dec_len=0;
while ('0'<=*fmt<='9')
dec_len=dec_len*10+ (*fmt++-'0');
if (*fmt=='*') {
fmt++;
if (cur_arg>=argc)
throw('Scan');
dec_len=argv[cur_arg++];
}
ch=*fmt++;
}
}
buf=MAlloc(len+1);
for (i=0;i<len;i++)
buf[i]=*src++;
buf[i]=0;
switch (ch) {
case 's':
if (cur_arg>=argc)
throw('Scan');
pptr=argv[cur_arg++];
StrCpy(*pptr,buf);
break;
case 'c':
if (cur_arg>=argc)
throw('Scan');
ptr=argv[cur_arg++];
*ptr=*buf;
break;
case 'C':
if (cur_arg>=argc)
throw('Scan');
ptr=argv[cur_arg++];
*ptr=ToUpper(*buf);
break;
case 'z':
if (cur_arg+1>=argc)
throw('Scan');
i_ptr=argv[cur_arg++];
*i_ptr=LstMatch(buf,argv[cur_arg++]);
break;
case 'Z':
if (cur_arg+1>=argc)
throw('Scan');
i_ptr=argv[cur_arg++];
*i_ptr=DefineMatch(buf,argv[cur_arg++]);
break;
case 'd':
if (cur_arg>=argc)
throw('Scan');
i_ptr=argv[cur_arg++];
*i_ptr=A2I64(buf);
break;
case 'X':
if (cur_arg>=argc)
throw('Scan');
i_ptr=argv[cur_arg++];
*i_ptr=A2I64(buf,16);
break;
case 'b':
if (cur_arg>=argc)
throw('Scan');
i_ptr=argv[cur_arg++];
*i_ptr=A2I64(buf,2);
break;
case 'e':
case 'f':
case 'g':
case 'n':
if (cur_arg>=argc)
throw('Scan');
d_ptr=argv[cur_arg++];
*d_ptr=A2F64(buf);
break;
case 'D':
if (cur_arg>=argc)
throw('Scan');
i_ptr=argv[cur_arg++];
*i_ptr=A2Date(buf);
break;
}
Free(buf);
}
} else
src++;
}
return src;
}
U8 *Scan(U8 *src,U8 *fmt,...)
//Pass ptr to data,
//For %s pass ptr to ptr (be careful because addr
//of array is the same as array--create ptr to array and take addr
{
return ScanJoin(src,fmt,argc,argv);
}
+526
View File
@@ -0,0 +1,526 @@
U0 Exit()
{
if (Fs==sys_focus_task && IsDbg) {
LBts(&Fs->task_flags,TASKf_KILL_AFTER_DBG);
G;
} else {
if (!Gs->num && !IsDbg)
SingleUser(OFF);
Fs->rflags=GetRFlags;
Fs->rsp=GetRSP;
Fs->rbp=GetRBP;
Fs->rip=$$;
CLI
LBts(&Fs->task_flags,TASKf_KILL_TASK);
TaskEndNow;
}
}
Bool TaskValidate(CTask *task)
{
if (!(0<task<=MAX_I32) || task->addr!=task ||
task->task_signature(I64)!=TASK_COMBINED_SIGNATURE_VAL)
return FALSE;
else
return TRUE;
}
U0 Kill(CTask *task,Bool wait=TRUE)
{
I64 i;
CCPU *c;
Bool found,old_preempt=Preempt(OFF);
if (TaskValidate(task)) {
if (task==sys_winmgr_task)
found=TRUE;
else
found=FALSE;
for (i=0;i<mp_cnt;i++) {
c=&cpu_structs[i];
if (task==c->seth_task)
found=TRUE;
}
if (!found) {
LBts(&task->task_flags,TASKf_KILL_TASK);
if (wait) {
do Yield;
while (TaskValidate(task) && Bt(&task->task_flags,TASKf_KILL_TASK));
}
}
}
Preempt(old_preempt);
}
Bool Suspend(CTask *task=NULL,Bool state=TRUE)
{
Bool result;
if (!task) task=Fs;
PUSHFD
CLI
if (TaskValidate(task))
result=LBEqu(&task->task_flags,TASKf_SUSPENDED,state);
else
result=FALSE;
POPFD
return result;
}
Bool IsSuspended(CTask *task=NULL)
{//You might use this in a DrawIt() or Animatetask().
if (!task) task=Fs;
if (TaskValidate(task))
return Bt(&task->task_flags,TASKf_SUSPENDED);
else
return FALSE;
}
CTaskStk *TaskStkNew(I64 stk_size,CTask *task)
{
CTaskStk *temps=MAlloc(stk_size+offset(CTaskStk.stk_base),task);
temps->next_stk=NULL;
temps->stk_ptr=NULL;
temps->stk_size=MSize(temps)-offset(CTaskStk.stk_base);
return temps;
}
#exe {OptOn(OPTf_NO_REG_VAR);};
//fp_addr can have any fixed number of arguments.
argpop I64 CallStkGrow(I64 stk_size_threshold,I64 stk_size,/*argpop*/I64 (*fp_addr)(...),...)
{
CTaskStk *temps,*temps2,**_stk;
I64 result,*rsp,*rsp2,*old_stk;
if (UnusedStk>=stk_size_threshold) {
asm {
LEAVE
POP RAX //return addr
ADD RSP,16 //pop threshold,stk_size
POP RBX // *f
ADD RSP,8 //pop ARGC
PUSH RAX
JMP RBX //CALL fp_addr()
};
} else {
temps2=TaskStkNew(stk_size,Fs);
temps2->next_stk=temps=Fs->stk;
rsp2=(&temps2->stk_base)(U8 *)+temps2->stk_size;
old_stk=rsp=&argv[argc];
while (argc-->0)
*--rsp2=*--rsp;
_stk=&Fs->stk;
temps->stk_ptr=rsp=GetRSP;
asm {
IMPORT _FREE; //We are in a function, not at glbl scope.
//The compiler treats these in isolation.
PUSHFD
POP RDX //flags
CLI
MOV RBX,U64 &temps2[RBP]
MOV RAX,&_stk[RBP]
MOV U64 [RAX],RBX //Fs->stk=temps2
MOV RSP,U64 &rsp2[RBP]
PUSH RDX
POPFD
CALL U64 &fp_addr[RBP]
MOV U64 &result[RBP],RAX
PUSHFD
POP RDX //flags
CLI
MOV RBX,U64 &temps[RBP]
MOV RAX,&_stk[RBP]
MOV U64 [RAX],RBX //Fs->stk=temps
MOV RSP,U64 &rsp[RBP]
PUSH RDX
POPFD
PUSH U64 &temps2[RBP]
CALL _FREE
MOV RDX,U64 &old_stk[RBP]
MOV RBX,U64 8[RBP]
MOV RAX,U64 &result[RBP]
MOV RBP,U64 [RBP]
MOV RSP,RDX
JMP RBX //return
};
}
return 0; //dummy to get rid of warning
}
;
#exe {OptOff(OPTf_NO_REG_VAR);};
I64 TaskInit(CTask *task,I64 stk_size)
{ //Returns Fs of task
CTaskStk *temps;
QueInit(&task->code_heap->next_mem_blk);
if (task->code_heap!=task->data_heap)
QueInit(&task->data_heap->next_mem_blk);
task->addr=task->next_task=task->last_task=
task->next_input_filter_task=task->last_input_filter_task=
task;
task->task_num=sys_num_spawned_tasks++;
task->rflags=SYS_NORMAL_RFLAGS;
task->win_inhibit=WIG_TASK_DFT;
task->win_max_refresh=WIN_DFT_MAX_REFRESH;
task->next_child_task=task->last_child_task=
(&task->next_child_task)(U8 *)-offset(CTask.next_sibling_task);
SrvCtrlInit(&task->srv_ctrl);
QueInit(&task->next_lex);
QueInit(&task->next_except);
QueInit(&task->next_ctrl);
QueInit(&task->next_ode);
task->fpu_mmx=MAllocAligned(sizeof(CFPU),0x10,task);
MemCpy(task->fpu_mmx,SYS_FIXED_AREA+offset(CSysFixedArea.init_fpu_mmx),sizeof(CFPU));
if (task==SYS_FIXED_AREA+offset(CSysFixedArea.adam)) {
// Delayed until heap expanded. See $LK,"Expand Heap",A="FA:::/Kernel/Mem1a.CPP,ExpandHeap"$
// task->hash_table=HashTableNew(ADAM_HASH_SIZE,task);
} else {
if (!Gs->num)
task->hash_table=HashTableNew(STD_HASH_SIZE,task);
else
task->hash_table=HashTableNew(MP_STD_HASH_SIZE,task);
}
if (!stk_size) {
if (!Gs->num)
stk_size=DFT_STK;
else
stk_size=MP_DFT_STK;
}
task->stk=temps=TaskStkNew(stk_size,task);
task->rsp=(&temps->stk_base)(U8 *)+temps->stk_size;
task->answers_displayed=1; //from 0-3
task->text_attr =TERM_ATTR_TEXT;
task->border_attr =TERM_ATTR_BORDER;
task->border_src =BDS_CONST;
task->title_src =TTS_CONST;
task->win_left =1;
task->win_right =text_cols-2;
task->win_top =13;
task->win_bottom =text_rows-2;
//Beware Adam $LK,"TaskInit",A="FF:::/Kernel/KStart.CPP,TaskInit"$ gets NULL. Okay, I guess, until $LK,"ChgDsk",A="FF:::/Kernel/KEnd.CPP,ChgDsk"$().
task->cur_prt=drv_to_prt[ToUpper(*sys_acct)-'A'];
task->cur_dir=StrNew(sys_acct+2,task);
return task;
}
CTask *Spawn(U0 (*fp_start_addr)(U8 *data),U8 *data=NULL,
U8 *task_name=NULL,
I64 target_cpu=-1, //-1 means current CPU
CTask *parent=NULL, //NULL means adam
I64 stk_size=0, //0=default
I64 flags=1<<SVCf_ADD_TO_QUE)
{
//We alloc from code heap so addr will be short
//Could be allocated off of data heap
CTask *task;
if (target_cpu>=0)
return SpawnQue(fp_start_addr,data,task_name,target_cpu,parent,stk_size,flags);
task=CAlloc(sizeof(CTask),adam_task->code_heap);
task->task_signature=TASK_SIGNATURE_VAL;
if (!task_name) task_name="Unnamed Task";
if (!parent) parent=Gs->seth_task;
task->parent_task=parent;
task->gs=parent->gs;
if (sys_code_bp)
task->code_heap=HeapCtrlInit(,task,sys_code_bp);
if (sys_data_bp)
task->data_heap=HeapCtrlInit(,task,sys_data_bp);
else
task->data_heap=task->code_heap;
TaskInit(task,stk_size);
task->rip=fp_start_addr;
task->rsp(U8 *)-=8;
*task->rsp=data;
task->rsp(U8 *)-=8;
*task->rsp=&Exit;
task->hash_table->next=parent->hash_table;
MemCpy(task->task_name,task_name,TASK_NAME_LEN+1);
StrCpy(task->task_title,task->task_name);
task->title_src=TTS_TASK_NAME;
PUSHFD
CLI
if (Bt(&flags,SVCf_ADD_TO_QUE)) {
TaskQueInsChild(task);
TaskQueIns(task);
}
POPFD
return task;
}
U0 TaskDerivedValsUpdate(CTask *task=NULL,Bool update_z_buf=TRUE)
{
if (!task) task=Fs;
PUSHFD
CLI
while (LBts(&task->locked_flags,TASKLf_TASK_LOCK))
PAUSE
WinDerivedValsUpdate(task);
if (fp_update_ctrls)
(*fp_update_ctrls)(task);
if (update_z_buf && Bt(&task->display_flags,DISPLAYf_SHOW))
LBts(&sys_semas[SYS_SEMA_UPDATE_WIN_Z_BUF],0);
LBtr(&task->locked_flags,TASKLf_TASK_LOCK);
POPFD
}
I64 ExeCmdLine(CLex *lx)
{
I64 result=0,i,type,old_title_src=Fs->title_src;
U8 *ptr,*ptr2,*ptr3,*ex,*old_task_title=StrNew(Fs->task_title);
F64 t0;
CDocEntry *doc_e;
CDoc *doc;
if (Fs->title_src!=TTS_LOCKED_CONST)
Fs->title_src=TTS_CUR_LEX;
while (lx->token &&
(lx->token!='}' || !(lx->flags & LF_EXE_BLK)) ) {
if (Fs->title_src==TTS_CUR_LEX) {
ptr2=&Fs->task_title;
ptr3=ptr2+TASK_TITLE_LEN;
if (lx->cur_lfn->flags & LFSF_DOC) {
doc_e=lx->cur_lfn->cur_entry;
doc=lx->cur_lfn->doc;
while (doc_e!=doc && ptr2<ptr3) {
switch (doc_e->type_u8) {
case DOCT_TEXT:
ptr=doc_e->tag;
while (*ptr && ptr2<ptr3)
*ptr2++=*ptr++;
break;
case DOCT_TAB:
case DOCT_NEW_LINE:
*ptr2++='.';
break;
}
doc_e=doc_e->next;
}
if (ptr2<ptr3) *ptr2=0;
} else
if ((ptr=lx->cur_lfn->line_start) && *ptr)
MemCpy(ptr2,ptr,TASK_TITLE_LEN);
}
lx->flags&=~LF_HAS_MISC_DATA;
ex=LexStatement2Bin(lx,&type);
if (ex!=INVALID_PTR) {
if (!(lx->flags&LF_JUST_LOAD)) {
t0=tS;
result=Call(ex);
for (i=2;i>=0;i--) {
Fs->answers[i+1]=Fs->answers[i];
Fs->answer_types[i+1]=Fs->answer_types[i];
Fs->answer_times[i+1]=Fs->answer_times[i];
}
Fs->answers[0]=result;
Fs->answer_types[0]=type;
Fs->answer_times[0]=tS-t0;
}
if (!(lx->flags&LF_HAS_MISC_DATA))
Free(ex);
}
}
if (Fs->title_src!=TTS_LOCKED_CONST) {
Fs->title_src=old_title_src;
StrCpy(Fs->task_title,old_task_title);
}
Free(old_task_title);
if (lx->flags&LF_JUST_LOAD) {
if (lx->error_cnt)
return FALSE;
else
return TRUE;
} else
return result;
}
U0 UserTaskCont()
{
CLex *lx;
CDoc *doc;
Bool cont=TRUE;
do {
lx=LexNew(,LF_PMT);
QueIns(lx,Fs->last_lex);
try {
Lex(lx);
ExeCmdLine(lx);
cont=Bt(&lx->flags,Lf_PMT);
QueRem(lx);
LexDel(lx);
} catch {
if ((doc=Fs->put_doc) && doc->doc_signature==DOC_SIGNATURE_VAL)
DocUnlock(doc);
PutExcept;
}
} while (cont);
}
U0 UserCmdLine(I64 dummy=0)
{//A user task ends-up calling this.
nounusedwarn dummy;
Fs->win_inhibit=WIG_USER_TASK_DFT;
if (HashFind("UserStartUp",adam_task->hash_table,HTT_FUN))
CallExtStr("UserStartUp");
if (!LBts(&Fs->display_flags,DISPLAYf_SHOW))
Dbg;
UserTaskCont;
}
CTask *SpawnUser(U8 *fmt=NULL,...)
{
U8 *st;
CTask *task=Spawn(&UserCmdLine);
TaskWait(task);
if (fmt) {
st=SPrintJoin(NULL,fmt,argc,argv);
XTalk(task,st);
Free(st);
}
return task;
}
U0 SrvTaskCont()
{
FlushMsgs;
while (TRUE) {
if (SrvCmdsHandler && Fs->title_src==TTS_TASK_NAME)
MemCpy(Fs->task_title,Fs->task_name,TASK_NAME_LEN+1);
FlushMsgs;
LBts(&Fs->task_flags,TASKf_IDLE);
LBts(&Fs->task_flags,TASKf_AWAITING_MSG);
Yield;
}
}
U0 SrvUserCmdLine(I64 dummy=0)
{
nounusedwarn dummy;
Fs->win_inhibit=WIG_USER_TASK_DFT;
if (HashFind("SrvStartUp",adam_task->hash_table,HTT_FUN))
CallExtStr("SrvStartUp");
SrvTaskCont;
}
U0 TaskFinishOff(CTask *task)
{ //We delay freeing in case lingering ptr to reincarnated.
HeapCtrlDel(task->code_heap);
if (task->data_heap!=task->code_heap)
HeapCtrlDel(task->data_heap);
Free(task);
}
I64 TaskEnd()
{ //called with irq's off
CTask *task=Fs,*tempt,*tempt1;
if (task==sys_task_being_screen_updated) {
LBts(&task->task_flags,TASKf_KILL_TASK);
return task->next_task;
}
if (task->task_end_cb) {
task->wake_jiffy=0;
LBtr(&task->task_flags,TASKf_KILL_TASK);
TaskRstAwaitingMsg(task);
Suspend(task,FALSE);
task->rip=task->task_end_cb;
task->task_end_cb=NULL;
return task;
}
if (task->parent_task && task->parent_task->popup_task==task) {
task->parent_task->popup_task=NULL;
Kill(task->parent_task,FALSE);
return task->parent_task;
}
PrtsRelease;
BlkDevsRelease;
tempt1=(&task->next_child_task)(U8 *)-offset(CTask.next_sibling_task);
tempt=tempt1->next_sibling_task;
if (tempt!=tempt1) {
do {
LBts(&tempt->task_flags,TASKf_KILL_TASK);
tempt=tempt->next_sibling_task;
} while (tempt!=tempt1);
return task->next_task;
}
if (LBtr(&task->display_flags,DISPLAYf_SHOW))
LBts(&sys_semas[SYS_SEMA_UPDATE_WIN_Z_BUF],0);
while (LBts(&task->locked_flags,TASKLf_TASK_LOCK))
PAUSE
while (LBts(&task->srv_ctrl.flags,SVCRf_LOCKED))
PAUSE
SrvCmdQueDel(&task->srv_ctrl.next_waiting);
SrvCmdQueDel(&task->srv_ctrl.next_done);
if (IsRaw)
VGAFlush;
if (sys_focus_task==task) {
if (!Gs->num)
SingleUser(OFF);
sys_focus_task=NULL;
if (fp_set_std_palette)
(*fp_set_std_palette)();
}
//QueRem
task->task_signature(I64)=0;
tempt =task->next_input_filter_task;
tempt1=task->last_input_filter_task;
tempt1->next_input_filter_task=tempt;
tempt ->last_input_filter_task=tempt1;
tempt =task->next_sibling_task;
tempt1=task->last_sibling_task;
tempt1->next_sibling_task=tempt;
tempt ->last_sibling_task=tempt1;
tempt =task->next_task; //save to return
TaskQueRem(task);
LBtr(&task->srv_ctrl.flags,SVCRf_LOCKED);
LBtr(&task->locked_flags,TASKLf_TASK_LOCK);
if (sys_winmgr_task) {
task->next_task=Gs->dying_task_lst;
Gs->dying_task_lst=task;
} else
TaskFinishOff(task); //dangerous (stk in use)
//Never happens--winmgr exists except during boot and no tasks die during boot
//currently, though this has been different and might be different in future.
//Would have to be multicore task getting this task's memory
//because IRQs are off, so no tasks on this core run.
return tempt;
}
U0 TaskFinishOffDying()
{//Called by Seth tasks. Delay freeing in case lingering ptr to reincarnated.
CTask *task1,*task2;
if (task1=XchgU64(&Gs->dying_task_lst,NULL)) {
do {
task2=task1->next_task;
TaskFinishOff(task1);
task1=task2;
} while (task1);
}
}
+498
View File
@@ -0,0 +1,498 @@
asm {
USE64
// ************************************
_MEMSET::
PUSH RBP
MOV RBP,RSP
PUSH RDI
CLD
MOV RDI,U64 SF_ARG1[RBP]
MOV RAX,U64 SF_ARG2[RBP]
MOV RCX,U64 SF_ARG3[RBP]
REP_STOSB
MOV RAX,RDI
POP RDI
POP RBP
RET1 24
// ************************************
_MEMSET_U16::
PUSH RBP
MOV RBP,RSP
PUSH RDI
CLD
MOV RDI,U64 SF_ARG1[RBP]
MOV RAX,U64 SF_ARG2[RBP]
MOV RCX,U64 SF_ARG3[RBP]
REP_STOSW
MOV RAX,RDI
POP RDI
POP RBP
RET1 24
// ************************************
_MEMSET_U32::
PUSH RBP
MOV RBP,RSP
PUSH RDI
CLD
MOV RDI,U64 SF_ARG1[RBP]
MOV RAX,U64 SF_ARG2[RBP]
MOV RCX,U64 SF_ARG3[RBP]
REP_STOSD
MOV RAX,RDI
POP RDI
POP RBP
RET1 24
// ************************************
_MEMSET_U64::
PUSH RBP
MOV RBP,RSP
PUSH RDI
CLD
MOV RDI,U64 SF_ARG1[RBP]
MOV RAX,U64 SF_ARG2[RBP]
MOV RCX,U64 SF_ARG3[RBP]
REP_STOSQ
MOV RAX,RDI
POP RDI
POP RBP
RET1 24
// ************************************
_MEMCPY::
PUSH RBP
MOV RBP,RSP
PUSH RSI
PUSH RDI
CLD
MOV RDI,U64 SF_ARG1[RBP]
MOV RSI,U64 SF_ARG2[RBP]
MOV RCX,U64 SF_ARG3[RBP]
REP_MOVSB
MOV RAX,RDI
POP RDI
POP RSI
POP RBP
RET1 24
// ************************************
_MEMCMP::
PUSH RBP
MOV RBP,RSP
PUSH RSI
PUSH RDI
CLD
MOV RSI,U64 SF_ARG1[RBP]
MOV RDI,U64 SF_ARG2[RBP]
MOV RCX,U64 SF_ARG3[RBP]
XOR RAX,RAX
REPE_CMPSB
JZ @@05
MOV AL,1
JA @@05
MOV RAX,-1
@@05: POP RDI
POP RSI
POP RBP
RET1 24
// ************************************
_BEQU::
PUSH RBP
MOV RBP,RSP
XOR RAX,RAX
MOV RDX,U64 SF_ARG3[RBP]
MOV RBX,U64 SF_ARG1[RBP]
MOV RCX,U64 SF_ARG2[RBP]
TEST RDX,RDX
JZ @@5
BTS U64 [RBX],RCX
JMP @@10
@@5: BTR U64 [RBX],RCX
@@10: ADC AL,0
POP RBP
RET1 24
// ************************************
_LBEQU::
PUSH RBP
MOV RBP,RSP
XOR RAX,RAX
MOV RDX,U64 SF_ARG3[RBP]
MOV RBX,U64 SF_ARG1[RBP]
MOV RCX,U64 SF_ARG2[RBP]
TEST RDX,RDX
JZ @@5
LOCK
BTS U64 [RBX],RCX
JMP @@10
@@5: LOCK
BTR U64 [RBX],RCX
@@10: ADC AL,0
POP RBP
RET1 24
// ************************************
_CLAMP_I64::
PUSH RBP
MOV RBP,RSP
MOV RAX,U64 SF_ARG1[RBP]
MOV RCX,U64 SF_ARG2[RBP]
MOV RDX,U64 SF_ARG3[RBP]
CMP RAX,RCX
CMOVL RAX,RCX
CMP RAX,RDX
CMOVG RAX,RDX
POP RBP
RET1 24
// ************************************
_CLAMP_U64::
PUSH RBP
MOV RBP,RSP
MOV RAX,U64 SF_ARG1[RBP]
MOV RCX,U64 SF_ARG2[RBP]
MOV RDX,U64 SF_ARG3[RBP]
CMP RAX,RCX
CMOVB RAX,RCX
CMP RAX,RDX
CMOVA RAX,RDX
POP RBP
RET1 24
// ************************************
_CALL::
PUSH RBP
MOV RBP,RSP
MOV RAX,U64 SF_ARG1[RBP]
TEST RAX,RAX
JZ @@05
CALL RAX
@@05: POP RBP
RET1 8
// ************************************
_BIT_FIELD_OR_U32::
PUSH RBP
MOV RBP,RSP
MOV RBX,U64 SF_ARG2[RBP]
SHR RBX,3
ADD RBX,U64 SF_ARG1[RBP]
MOV RAX,U64 SF_ARG3[RBP]
MOV RCX,U64 SF_ARG2[RBP]
AND CL,7
SHL RAX,CL
OR U64 [RBX],RAX
POP RBP
RET1 24
// ************************************
_BIT_FIELD_EXTRACT_U32::
PUSH RBP
MOV RBP,RSP
MOV RBX,U64 SF_ARG2[RBP]
MOV RCX,RBX
SHR RBX,3
ADD RBX,U64 SF_ARG1[RBP]
MOV RDX,U64 [RBX]
AND CL,7
SHR RDX,CL
MOV RCX,U64 SF_ARG3[RBP]
MOV RAX,1
SHL RAX,CL
DEC RAX
AND RAX,RDX
POP RBP
RET1 24
// ************************************
_XCHG_U64::
PUSH RBP
MOV RBP,RSP
MOV RDX,U64 SF_ARG1[RBP]
MOV RAX,U64 SF_ARG2[RBP]
XCHG U64 [RDX],RAX
POP RBP
RET1 16
_XCHG_U32::
PUSH RBP
MOV RBP,RSP
MOV RDX,U64 SF_ARG1[RBP]
MOV EAX,U32 SF_ARG2[RBP]
XCHG U32 [RDX],EAX
POP RBP
RET1 16
_XCHG_U16::
PUSH RBP
MOV RBP,RSP
MOV RDX,U64 SF_ARG1[RBP]
MOVZX RAX,U16 SF_ARG2[RBP]
XCHG U16 [RDX],AX
POP RBP
RET1 16
_XCHG_U8::
PUSH RBP
MOV RBP,RSP
MOV RDX,U64 SF_ARG1[RBP]
MOVZX RAX,U8 SF_ARG2[RBP]
XCHG U8 [RDX],AL
POP RBP
RET1 16
_LXCHG_U64::
PUSH RBP
MOV RBP,RSP
MOV RDX,U64 SF_ARG1[RBP]
MOV RAX,U64 SF_ARG2[RBP]
LOCK
XCHG U64 [RDX],RAX
POP RBP
RET1 16
_LXCHG_U32::
PUSH RBP
MOV RBP,RSP
MOV RDX,U64 SF_ARG1[RBP]
MOV EAX,U32 SF_ARG2[RBP]
LOCK
XCHG U32 [RDX],EAX
POP RBP
RET1 16
_LXCHG_U16::
PUSH RBP
MOV RBP,RSP
MOV RDX,U64 SF_ARG1[RBP]
MOVZX RAX,U16 SF_ARG2[RBP]
LOCK
XCHG U16 [RDX],AX
POP RBP
RET1 16
_LXCHG_U8::
PUSH RBP
MOV RBP,RSP
MOV RDX,U64 SF_ARG1[RBP]
MOVZX RAX,U8 SF_ARG2[RBP]
LOCK
XCHG U8 [RDX],AL
POP RBP
RET1 16
// ************************************
_REP_IN_U32::
PUSH RBP
MOV RBP,RSP
PUSH RDI
MOV RDI,U64 SF_ARG1[RBP]
MOV RDX,U64 SF_ARG3[RBP]
MOV RCX,U64 SF_ARG2[RBP]
REP_INSD
POP RDI
POP RBP
RET1 24
_REP_IN_U16::
PUSH RBP
MOV RBP,RSP
PUSH RDI
MOV RDI,U64 SF_ARG1[RBP]
MOV RDX,U64 SF_ARG3[RBP]
MOV RCX,U64 SF_ARG2[RBP]
REP_INSW
POP RDI
POP RBP
RET1 24
_REP_IN_U8::
PUSH RBP
MOV RBP,RSP
PUSH RDI
MOV RDI,U64 SF_ARG1[RBP]
MOV RDX,U64 SF_ARG3[RBP]
MOV RCX,U64 SF_ARG2[RBP]
REP_INSB
POP RDI
POP RBP
RET1 24
_REP_OUT_U32::
PUSH RBP
MOV RBP,RSP
PUSH RSI
MOV RSI,U64 SF_ARG1[RBP]
MOV RDX,U64 SF_ARG3[RBP]
MOV RCX,U64 SF_ARG2[RBP]
REP_OUTSD
POP RSI
POP RBP
RET1 24
_REP_OUT_U16::
PUSH RBP
MOV RBP,RSP
PUSH RSI
MOV RSI,U64 SF_ARG1[RBP]
MOV RDX,U64 SF_ARG3[RBP]
MOV RCX,U64 SF_ARG2[RBP]
REP_OUTSW
POP RSI
POP RBP
RET1 24
_REP_OUT_U8::
PUSH RBP
MOV RBP,RSP
PUSH RSI
MOV RSI,U64 SF_ARG1[RBP]
MOV RDX,U64 SF_ARG3[RBP]
MOV RCX,U64 SF_ARG2[RBP]
REP_OUTSB
POP RSI
POP RBP
RET1 24
// ************************************
_CPUID::
PUSH RBP
MOV RBP,RSP
PUSH RSI
MOV RAX,U64 SF_ARG1[RBP]
CPUID
MOV RSI,U64 SF_ARG2[RBP]
MOV U64 [RSI],RAX
MOV U64 8[RSI],RBX
MOV U64 16[RSI],RCX
MOV U64 24[RSI],RDX
POP RSI
POP RBP
RET1 16
// ************************************
_CALLIND::
PUSH RBP
MOV RBP,RSP
PUSH RSI
PUSH RDI
MOV RDX,U64 SF_ARG1[RBP]
MOV RCX,U64 SF_ARG2[RBP] //argc
LEA RSI,U64 SF_ARG3[RBP] //argv
SHL RCX,3
SUB RSP,RCX
MOV RDI,RSP
REP_MOVSB
TEST RDX,RDX
JZ @@05
CALL RDX
POP RDI
POP RSI
POP RBP
RET
@@05: XOR RAX,RAX
MOV RCX,U64 SF_ARG2[RBP] //argc
SHL RCX,3
ADD RSP,RCX
POP RDI
POP RSI
POP RBP
RET
// ************************************
_CALLEXTNUM::
PUSH RBP
MOV RBP,RSP
PUSH RSI
PUSH RDI
MOV RDX,U64 SF_ARG1[RBP]
MOV RCX,U64 SF_ARG2[RBP] //argc
LEA RSI,U64 SF_ARG3[RBP] //argv
SHL RCX,3
SUB RSP,RCX
MOV RDI,RSP
REP_MOVSB
MOV RAX,U64 [SYS_EXTERN_TABLE]
MOV RAX,U64 [RAX+RDX*8]
TEST RAX,RAX
JZ @@05
CALL RAX
POP RDI
POP RSI
POP RBP
RET
@@05: XOR RAX,RAX
MOV RCX,U64 SF_ARG2[RBP] //argc
SHL RCX,3
ADD RSP,RCX
POP RDI
POP RSI
POP RBP
RET
// ************************************
_CALLEXTSTR::
PUSH RBP
MOV RBP,RSP
PUSH RSI
PUSH RDI
MOV RCX,U64 SF_ARG2[RBP] //argc
LEA RSI,U64 SF_ARG3[RBP] //argv
SHL RCX,3
SUB RSP,RCX
MOV RDI,RSP
REP_MOVSB
MOV RSI,U64 SF_ARG1[RBP]
MOV RCX,1
XOR RAX,RAX
MOV RDI,U64 FS:CTask.hash_table[RAX]
MOV RBX,HTT_FUN|HTT_EXPORT_SYS_SYM
CALL SYS_HASH_FIND
JZ @@15
TEST U32 CHash.type[RAX],HTT_FUN
JZ @@05
MOV RAX,U64 CHashFun.executable_addr[RAX]
JMP @@10
@@05: MOV RAX,U64 CHashExport.val[RAX]
@@10: TEST RAX,RAX
JZ @@15
CALL RAX
POP RDI
POP RSI
POP RBP
RET
@@15: MOV RCX,U64 SF_ARG2[RBP] //argc
SHL RCX,3
ADD RSP,RCX
POP RDI
POP RSI
POP RBP
RET
// ************************************
SET_GS_BASE::
PUSH RAX
PUSH RCX
PUSH RDX
MOV RDX,RAX
SHR RDX,32
MOV ECX,IA32_GS_BASE
WRMSR
POP RDX
POP RCX
POP RAX
RET
SET_FS_BASE::
PUSH RAX
PUSH RCX
PUSH RDX
MOV RDX,RAX
SHR RDX,32
MOV ECX,IA32_FS_BASE
WRMSR
POP RDX
POP RCX
POP RAX
_RET::
RET
_SET_MSR::
PUSH RBP
MOV RBP,RSP
MOV RAX,SF_ARG2[RBP]
MOV RDX,RAX
SHR RDX,32
MOV RCX,SF_ARG1[RBP]
WRMSR
POP RBP
RET1 16
_SYS_HLT::
CLI
@@05: HLT
JMP @@05
}