Trivial Solutions
                    The LoseThos 64-bit PC Operating System
File:/LT/OSMain/Misc1a.CPZ
This, and all LoseThos files, are public domain.  Do whatever you like.
God is watching; God is just; God is never out-done in generosity.  He talks!

LoseThos code compiles with the 64-bit LoseThos compiler/assembler I wrote.
Boot the LoseThos CD and you can compile it.  Not in Kansas anymore!

Click here for preliminary compiler information you need.

Project: OSMain
F64 Limit(F64 p,F64 lo,F64 hi)
{
  if (p<lo)
    return lo;
  if (p>hi)
    return hi;
  return p;
}

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 inf;
  else if (i<-308)
    return 0.0;
  else
    return pow10_I64[i+309];
}

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 BigEndianU16(U16 d)
{
  U16 r;
  r.u8[1]=d.u8[0];
  r.u8[0]=d.u8[1];
  return r;
}

U32 BigEndianU32(U32 d)
{
  U32 r;
  r.u8[3]=d.u8[0];
  r.u8[2]=d.u8[1];
  r.u8[1]=d.u8[2];
  r.u8[0]=d.u8[3];
  return r;
}

U64 BigEndianU64(U64 d)
{
  U64 r;
  r.u8[7]=d.u8[0];
  r.u8[6]=d.u8[1];
  r.u8[5]=d.u8[2];
  r.u8[4]=d.u8[3];
  r.u8[3]=d.u8[4];
  r.u8[2]=d.u8[5];
  r.u8[1]=d.u8[6];
  r.u8[0]=d.u8[7];
  return r;
}

I64 BCnt(U64 d)
{
  I64 result=0,i;
  for (i=0;i<8;i++)
    result+=set_bits_table[d.u8[i]];
  return result;
}

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;
  }
}

U0 IntSimpleTimer(TaskStruct *task)
{
  nounusedwarn task;
  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);
}

U64 SysTimerRead()
{
  I64 i;
  U64 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;
}

U64 TaskTotalTime()
{
  return GetTimeStamp-Fs->time_slice_start+Fs->total_time;
}

LTDate BootTime()
//Roughly 49,710ths of a second since boot
{
  return SysTimerRead<<14/(1833333*3*3*3/125);
}

U64 TimeStampFreqCal()
{
  static U64 time_stamp_start=0,timer_start=0,HPET_start=0;
  U64 i;
  if (time_stamp_start) {
    PushFD;
    Cli;
    if (HPET_start) {
      time_stamp_freq=HPET_freq*(GetTimeStamp-time_stamp_start);
      i=HPET-HPET_start;
    } else {
      time_stamp_freq=SYS_TIMER_FREQ*(GetTimeStamp-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 {
    HPET_start=0;
    timer_start=SysTimerRead;
  }
  time_stamp_start=GetTimeStamp;
  PopFD;
  return time_stamp_freq;
}

F64 tNP()
//Time since boot in seconds as a float
{
  static U64 last_time_stamp=0;
  static F64 last_result=0;
  U64 time_stamp;
  if (HPET_freq)
    return ToF64(HPET)/HPET_freq;
  else { //Monotonically incresing,calibrated.
    PushFD;
    Cli;
    if (mp_cnt>1)
      while (LBts(&sys_semas[SYS_SEMA_TNP],0))
        Pause;
    time_stamp=GetTimeStamp;
    last_result+=ToF64(time_stamp-last_time_stamp)/time_stamp_freq;
    last_time_stamp=time_stamp;
    LBtr(&sys_semas[SYS_SEMA_TNP],0);
    PopFD;
    return last_result;
  }
}

F64 tP(TaskStruct *task=NULL)
{ //Time in seconds, stopped during pauses
  F64 result;
  BoolI8 old_preempt=Preempt(OFF);
  if (!task) task=Fs;
  if (TaskValidate(task)) {
    if (Bt(&task->task_flags,TASKf_PAUSED))
      result=task->pause_start-task->pause_total;
    else
      result=tNP-task->pause_total;
    Preempt(old_preempt);
    return result;
  }
  Preempt(old_preempt);
  return tNP;
}

F64 tJ()
{
  return sys_jiffies/ToF64(JIFFY_FREQ);
}

F64 tS()
{
  return SysTimerRead/ToF64(SYS_TIMER_FREQ);
}

BoolI64 Blink(F64 Hz=2.5,F64 t=0)
{
  if (!Hz) return 0;
  if (t)
    return ToI64(t*2*Hz)&1;
  else
    return ToI64(sys_jiffies*2*Hz/JIFFY_FREQ)&1;
}

U0 BusyWait(U64 uS) //Loosely timed
{
  U64 i=GetTimeStamp;
  if (time_stamp_freq_calibrated) {
    i+=time_stamp_freq*uS/1000000;
    while (GetTimeStamp<i)
      Pause;
  } else {
    uS=uS<<1/3;
    for (i=0;i<uS;i++) {
      PortNop;
      Pause;
    }
  }
}

U0 SleepUntil(U64 wake_jiffy)
//This routine is not for power-saving
//it is to make a program pause without
//hogging the CPU.
{
  BoolI8 old_idle=LBts(&Fs->task_flags,TASKf_IDLE);
  Fs->wake_jiffy=wake_jiffy;
  Yield;
  LBEqu(&Fs->task_flags,TASKf_IDLE,old_idle);
}

U0 Sleep(U64 mS)
//This routine is not for power-saving
//it is to make a program pause without
//hogging the CPU.
{
  if (!mS)
    Yield;
  else
    SleepUntil(sys_jiffies+mS*JIFFY_FREQ/1000);
}

//See ::/LT/Doc/Acknowledgements.TXZ (6).

U16 RandU16()
{
  sys_rnd_seed.i32[0]=(1664525*sys_rnd_seed.i32[0]+1013904223)^GetTimeStamp>>4;
  return sys_rnd_seed.u16[0];
}

U16 Rand2U16()
{
  sys_rnd_seed.i32[0]=1664525*sys_rnd_seed.i32[0]+1013904223;
  return sys_rnd_seed.u16[0];
}

I16 RandI16()
{
  sys_rnd_seed.i32[0]=(1664525*sys_rnd_seed.i32[0]+1013904223)^GetTimeStamp>>4;
  return sys_rnd_seed.i16[0];
}

I16 Rand2I16()
{
  sys_rnd_seed.i32[0]=1664525*sys_rnd_seed.i32[0]+1013904223;
  return sys_rnd_seed.i16[0];
}

U32 RandU32()
{
  sys_rnd_seed.i32[0]=(1664525*sys_rnd_seed.i32[0]+1013904223)^GetTimeStamp>>4;
  return sys_rnd_seed.u32[0];
}

U32 Rand2U32()
{
  sys_rnd_seed.i32[0]=1664525*sys_rnd_seed.i32[0]+1013904223;
  return sys_rnd_seed.u32[0];
}

I32 RandI32()
{
  sys_rnd_seed.i32[0]=(1664525*sys_rnd_seed.i32[0]+1013904223)^GetTimeStamp>>4;
  return sys_rnd_seed.i32[0];
}

I32 Rand2I32()
{
  sys_rnd_seed.i32[0]=1664525*sys_rnd_seed.i32[0]+1013904223;
  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)^GetTimeStamp>>4;
  result.u32[1]=sys_rnd_seed.i32[0]= 1664525*sys_rnd_seed.i32[0]+1013904223;
  return result;
}

U64 Rand2U64()
{
  U64 result;
  result.u32[0]=sys_rnd_seed.i32[0]= 1664525*sys_rnd_seed.i32[0]+1013904223;
  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)^GetTimeStamp>>4;
  result.u32[1]=sys_rnd_seed.i32[0]= 1664525*sys_rnd_seed.i32[0]+1013904223;
  return result;
}

I64 Rand2I64()
{
  I64 result;
  result.u32[0]=sys_rnd_seed.i32[0]= 1664525*sys_rnd_seed.i32[0]+1013904223;
  result.u32[1]=sys_rnd_seed.i32[0]= 1664525*sys_rnd_seed.i32[0]+1013904223;
  return result;
}

F64 Rand()
{ //0.0<=x<1.0
  U64 result;
  result.u32[0]=sys_rnd_seed.i32[0]=(1664525*sys_rnd_seed.i32[0]+1013904223)^GetTimeStamp>>4;
  result.u32[1]=sys_rnd_seed.i32[0]= 1664525*sys_rnd_seed.i32[0]+1013904223;
  result&=0x3FFFFFFFFFFFFFFF;
  return result/ToF64(0x4000000000000000);
}

F64 Rand2()
{ //0.0<=x<1.0
  U64 result;
  result.u32[0]=sys_rnd_seed.i32[0]= 1664525*sys_rnd_seed.i32[0]+1013904223;
  result.u32[1]=sys_rnd_seed.i32[0]= 1664525*sys_rnd_seed.i32[0]+1013904223;
  result&=0x3FFFFFFFFFFFFFFF;
  return result/ToF64(0x4000000000000000);
}

U0 Randomize(U64 seed=0)
{ //Randomizes seed.
  if (seed)
    sys_rnd_seed=seed;
  else
    sys_rnd_seed^=GetTimeStamp>>4;
}

U0 Snd(F64 freq,U64 waveform=WF_SQUARE,F64 amp=1.0)
// The internal PC speaker only does square waves.
// waveform and amp are for HDAudio.
// Use SndFilePlay() or ::/LT/Demo/Snd/PolyPhonic.CPZ as a template for
// doing polyphonic or fancy HD Audio snd.
{
  U64 p;
  if (!Bt(&sys_semas[SYS_SEMA_MUTE],0) && snd_vol &&
      !LBts(&sys_semas[SYS_SEMA_SND],0)) {
    if (!IsInDbg && snd_dev!=SD_PC_SPEAKER) {
      snd_freq=freq;
      if (fp_snd)
        (*fp_snd)(freq,waveform,amp);
    } else {
      if (freq!=snd_freq) {
        snd_freq=freq;
        if (freq) {
          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 (!IsInDbg && snd_record && fp_snd_record)
      (*fp_snd_record)(freq,waveform,amp);
    LBtr(&sys_semas[SYS_SEMA_SND],0);
  }
}

U0 Beep(U64 freq=500,BoolI8 busy=FALSE)
{
  Snd(freq);
  if (busy) BusyWait(500000);
    else Sleep(500);
  Snd(0);
  if (busy) BusyWait(200000);
    else Sleep(200);
}

BoolI64 Mute(BoolI8 val)
{
  BoolI8 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;
}

BoolI64 IsMute() {
  return Bt(&sys_semas[SYS_SEMA_MUTE],0);
}

BoolI64 Silent(BoolI8 val) {
//This turns-off console output, not sound.
  return LBEqu(&Fs->display_flags,DISPLAYf_SILENT,val);
}

BoolI64 IsSilent() {
  return Bt(&Fs->display_flags,DISPLAYf_SILENT);
}

BoolI64 IOSnd(BoolI8 val) {
  BoolI8 result=!LBEqu(&sys_semas[SYS_SEMA_NO_IO_SND],0,!val);
  Snd(0);
  return result;
}

BoolI64 IsPreempt() {
  return Bt(&Fs->task_flags,TASKf_PREEMPT);
}

BoolI64 SysDbg(BoolI8 val) {
//Sets or rsts a bit which you can
//use while debugging.
  return LBEqu(&sys_semas[SYS_SEMA_DEBUG],0,val);
}

BoolI64 IsSysDbg() {
//Returns the val of the debug
//bit.
  return Bt(&sys_semas[SYS_SEMA_DEBUG],0);
}

BoolI64 Raw(BoolI8 val) {
//Switches to direct screen output
//mode for when you don't have
//a working window.
  if (!val)
    LBts(&sys_semas[SYS_SEMA_FLUSH_VGA_IMAGE],0);
  return !LBEqu(&Fs->task_flags,TASKf_NOT_RAW,!val);
}

BoolI64 IsRaw() {
  return !Bt(&Fs->task_flags,TASKf_NOT_RAW);
}

BoolI64 SingleUser(BoolI8 val) {
  return LBEqu(&sys_semas[SYS_SEMA_SINGLE_USER],0,val);
}

BoolI64 IsSingleUser() {
  return Bt(&sys_semas[SYS_SEMA_SINGLE_USER],0);
}

BoolI64 InDbg(BoolI8 val) {
  return LBEqu(&sys_semas[SYS_SEMA_IN_DEBUGGER],0,val);
}

BoolI64 IsInDbg() {
  return Bt(&sys_semas[SYS_SEMA_IN_DEBUGGER],0);
}

U0 ProgressBarsRst()
{
  I64 i;
  for (i=0;i<NUM_PROGRESS_BARS;i++) {
    progress_vals[i]=0;
    progress_maxes[i]=0;
    *progress_descs[i]=0;
  }
}

U0 CtrlAltDel(U64 sc)
{
  nounusedwarn sc;
  LBts(sys_ctrl_alt_flags,SYSf_CTRL_ALT_DEL);
}

U0 CtrlAltC(U64 sc)
{
  nounusedwarn sc;
  LBts(sys_ctrl_alt_flags,SYSf_CTRL_ALT_C);
}

U0 CtrlAltD(U64 sc)
{
  nounusedwarn sc;
  Dbg;
}

U0 CtrlAltE(U64 sc)
{
  nounusedwarn sc;
  SpawnUser;
}

U0 CtrlAltM(U64 sc)
{
  nounusedwarn sc;
  Mute(!IsMute);
}

U0 CtrlAltP(U64 sc)
{
  nounusedwarn sc;
  if (sys_cur_focus_task)
    TaskPause(sys_cur_focus_task,!Bt(&sys_cur_focus_task->task_flags,TASKf_PAUSED));
}

U0 CtrlAltT(U64 sc)
{
  nounusedwarn sc;
  LBts(sys_ctrl_alt_flags,SYSf_CTRL_ALT_TAB);
}

U0 CtrlAltX(U64 sc)
{
  nounusedwarn sc;
  LBts(sys_ctrl_alt_flags,SYSf_CTRL_ALT_X);
}
Historical capture: 2011-11-26. Home | Power on LoseThos | Sources and changes