summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--DskImg.HC67
-rw-r--r--Floppy.HH98
-rw-r--r--KStart32.HC118
-rw-r--r--Kernel.PRJ63
-rw-r--r--KernelC.HH787
-rw-r--r--NewFloppy.HC477
-rw-r--r--ReadMe.TXT27
7 files changed, 1637 insertions, 0 deletions
diff --git a/DskImg.HC b/DskImg.HC
new file mode 100644
index 0000000..077a986
--- /dev/null
+++ b/DskImg.HC
@@ -0,0 +1,67 @@
+#define CYLINDERS 80
+#define SECTORS 18
+#define BASE 0x03F0
+#define IMG_SIZE 1474560
+
+/*
+
+ Make sure IRQ6 is on and
+ pointed to the correct handler!
+
+*/
+
+U8 DskImg()
+{
+ U64 i;
+
+ // Open image file for writing
+ CFile *img = FOpen("Floppy.IMG","w",IMG_SIZE/BLK_SIZE);
+
+ // Initialize the controller
+ FDCReset(BASE);
+ Sleep(100);
+
+ /*
+
+ Loop through each sector,
+ reading each into the buffer,
+ then writing it into the file
+
+ */
+
+ for (i = 0; i < CYLINDERS; i++) {
+ "Track %d\n", i;
+ if (FDCSeek(BASE, i, 0)) {
+ FDCReset(BASE);
+ FClose(img);
+ return 1;
+ }
+ if (FDCSeek(BASE, i, 1)) {
+ FDCReset(BASE);
+ FClose(img);
+ return 1;
+ }
+ FDCReadMulti(BASE, i, 0, 1, 18);
+ FBlkWrite(img, &FDC_DMA, 36 * i, 36);
+ }
+
+ // Return to track 0
+ "Returning to track 0...\n";
+ if (FDCSeek(BASE, 0, 0)) {
+ FDCReset(BASE);
+ FClose(img);
+ return 1;
+ }
+ if (FDCSeek(BASE, 0, 1)) {
+ FDCReset(BASE);
+ FClose(img);
+ return 1;
+ }
+
+ // Close the image file
+ FClose(img);
+
+ return 0;
+}
+
+DskImg; \ No newline at end of file
diff --git a/Floppy.HH b/Floppy.HH
new file mode 100644
index 0000000..4e5cfdb
--- /dev/null
+++ b/Floppy.HH
@@ -0,0 +1,98 @@
+// FDC uses IRQ6 = int 26h
+#define I_FDC 0x26
+#define IRQ_FDC 6
+
+// FDC regs (primary ctrlr)
+#define FDC_STAT_A 0x0
+#define FDC_STAT_B 0x1
+#define FDC_DOR 0x2
+#define FDC_TAPE 0x3
+#define FDC_MSR_DSR 0x4
+#define FDC_DATA 0x5
+#define FDC_CCR_DIR 0x7
+
+// FDC cmds
+#define FDC_READ_TRACK 0x02
+#define FDC_SPECIFY 0x03
+#define FDC_SENSE_STAT 0x04
+#define FDC_WRITE_DATA 0x05
+#define FDC_READ_DATA 0x06
+#define FDC_RECALIBRATE 0x07
+#define FDC_SENSE_INTR 0x08
+#define FDC_WRITE_DEL 0x09
+#define FDC_READ_ID 0x0A
+#define FDC_READ_DEL 0x0C
+#define FDC_FMT_TRACK 0x0D
+#define FDC_DUMP_REG 0x0E
+#define FDC_SEEK 0x0F
+#define FDC_VERSION 0x10
+#define FDC_SCAN_EQL 0x11
+#define FDC_PERP_MODE 0x12
+#define FDC_CONFIGURE 0x13
+#define FDC_LOCK 0x14
+#define FDC_VERIFY 0x16
+#define FDC_SCAN_LO_EQL 0x19
+#define FDC_SCAN_HI_EQL 0x1D
+
+// Motor stuff
+#define FDC_MOTOR_OFF 0
+#define FDC_MOTOR_ON 1
+#define FDC_MOTOR_WAIT 2
+
+// Read/write directions
+#define FDC_DIR_READ 0
+#define FDC_DIR_WRITE 1
+
+// Digital Output Register (DOR) flags
+
+// DOR motor control flags: 1 = on, 0 = off
+#define FDC_DOR_MOTD 0x80 // Drive D
+#define FDC_DOR_MOTC 0x40 // Drive C
+#define FDC_DOR_MOTB 0x20 // Drive B
+#define FDC_DOR_MOTA 0x10 // Drive A
+
+// other DOR flags
+#define FDC_DOR_DMA 0x08 // DMA2/IRQ6 On/Off
+#define FDC_DOR_REST 0x04 // Controller Reset: this is active low; 1 = normal, 0 = reset
+
+// DOR drive select (DOR & 0x03): selects drive 0-3
+
+// Main Status Register (MSR) flags
+#define FDC_MSR_RQM 0x80 // Main Request: 1 = ready, 0 = not ready
+#define FDC_MSR_DIO 0x40 // Data In/Out: 1 = FDC -> PC, 0 = PC -> FDC
+#define FDC_MSR_NDMA 0x20 // Non-DMA: 1 = DMA off, 0 = DMA on
+#define FDC_MSR_BUSY 0x10 // Device busy: self-explanatory
+
+// MSR drive seek flags: 1 = seeking, 0 = idle
+#define FDC_MSR_ACTD 0x08 // Drive D
+#define FDC_MSR_ACTC 0x04 // Drive C
+#define FDC_MSR_ACTB 0x02 // Drive B
+#define FDC_MSR_ACTA 0x01 // Drive A
+
+// Status Register 0 (ST0) flags
+
+/* ST0 interrupt code (ST0 & 0xC0):
+ 00 = normal termination
+ 01 = abnormal termination
+ 10 = invalid cmd
+ 11 = abnormal termination by poilling (drive became not ready)
+*/
+
+#define FDC_ST0_SEEK_END 0x20 // Seek End: seek/calibration completed
+#define FDC_ST0_UNIT_CHK 0x10 // Unit Check: drive encountered a fault or recalibration failed
+#define FDC_ST0_NOT_RDY 0x08 // Not Ready: self-explanatory
+#define FDC_ST0_HEAD 0x04 // Active Head
+
+// ST0 unit select (ST0 & 0x03): same fmt as DOR drive select
+
+// Status Register 1 (ST1) flags
+#define FDC_ST1_END_CYL 0x80 // End of Cylinder: set when sector count > sectors on track
+// 0x40 is unused
+#define FDC_ST1_DATA_ERR 0x20 // Data Error: set when an error is detected in a sector's data or ID fields
+#define FDC_ST1_TIMEOUT 0x10 // Timeout: set when a data overrun occurs (i.e. the system is not reading data fast enough)
+// 0x08 is unused
+#define FDC_ST1_NO_DATA 0x04 // No Data: set when either a sector cannot be read, or an ID cannot be successfully read, or if the sector sequence cannot be determined
+#define FDC_ST1_NO_WRITE 0x02 // Not Writable: set when attempting to write to a write-protected disk
+#define FDC_ST1_NO_ID 0x01 // No Addr. Mark: set when an ID/(deleted) data address mark cannot be found.
+
+// Status Register 2 (ST2) flags \ No newline at end of file
diff --git a/KStart32.HC b/KStart32.HC
new file mode 100644
index 0000000..ec8f67b
--- /dev/null
+++ b/KStart32.HC
@@ -0,0 +1,118 @@
+asm {
+USE32
+//************************************
+// ASM Global vars not required for 16-bit start-up
+ ALIGN 8,OC_NOP
+MEM_HEAP_BASE:: DU64 0;
+MEM_HEAP_LIMIT:: DU64 0;
+MEM_PAGE_SIZE:: DU64 0;
+MEM_MAPPED_SPACE:: DU64 0;
+MEM_2MEG_NUM:: DU64 0;
+MEM_1GIG_NUM:: DU64 0;
+MEM_512GIG_NUM:: DU64 0;
+MEM_PML2:: DU64 0;
+MEM_PML3:: DU64 0;
+MEM_PML4:: 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;"
+"SYS_STAFF_MODE_FLAG:: 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,
+kernel_cfg->opts[CFG_STAFF_MODE]);
+};
+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_T0:: DU64 0;
+SYS_PROGRESS1_TF:: DU64 0;
+SYS_PROGRESS1_DESC:: DU8 PROGRESS_DESC_LEN DUP(0);
+SYS_PROGRESS2:: DU64 0;
+SYS_PROGRESS2_MAX:: DU64 0;
+SYS_PROGRESS2_T0:: DU64 0;
+SYS_PROGRESS2_TF:: DU64 0;
+SYS_PROGRESS2_DESC:: DU8 PROGRESS_DESC_LEN DUP(0);
+SYS_PROGRESS3:: DU64 0;
+SYS_PROGRESS3_MAX:: DU64 0;
+SYS_PROGRESS3_T0:: DU64 0;
+SYS_PROGRESS3_TF:: DU64 0;
+SYS_PROGRESS3_DESC:: DU8 PROGRESS_DESC_LEN DUP(0);
+SYS_PROGRESS4:: DU64 0;
+SYS_PROGRESS4_MAX:: DU64 0;
+SYS_PROGRESS4_T0:: DU64 0;
+SYS_PROGRESS4_TF:: DU64 0;
+SYS_PROGRESS4_DESC:: DU8 PROGRESS_DESC_LEN DUP(0);
+#assert $$-SYS_PROGRESSES==sizeof(CProgress)*4
+
+SYS_FOCUS_TASK:: DU64 0;
+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 SEMA_SEMAS_NUM*DFT_CACHE_LINE_WIDTH DUP(0);
+//************************************
+ ALIGN 16,OC_NOP
+CORE0_32BIT_INIT:: //Entry point for $LK,"BootRAM",A="MN:BootRAM"$.
+ PUSH U32 RFLAGG_START
+ POPFD
+ MOV EAX,SYS_START_CR0
+ MOV_CR0_EAX
+
+ MOV AX,CGDT.boot_ds //LOAD DS SELECTOR
+ MOV DS,AX
+ BTS U32 [SYS_RUN_LEVEL],RLf_32BIT
+ MOV ESI,U32 [SYS_BOOT_PATCH_TABLE_BASE]
+ MOV EDI,U32 [MEM_BOOT_BASE]
+
+ MOV AX,CGDT.ds
+ MOV DS,AX
+ MOV ES,AX
+ MOV FS,AX
+ MOV GS,AX
+ MOV SS,AX
+ MOV ESP,BOOT_RAM_LIMIT //Tmp Stk
+
+//Patch abs addresses
+ MOV ECX,U32 CPatchTableAbsAddr.abs_addres_cnt[ESI]
+ LEA ESI,U32 CPatchTableAbsAddr.abs_addres[ESI]
+@@05: LODSD
+ ADD EAX,EDI
+ ADD U32 [EAX],EDI
+ LOOP @@05
+
+ DU8 0xEA; //JMP CGDT.cs32:@@10
+ DU32 @@10;
+ DU16 CGDT.cs32;
+
+@@10: BTS U32 [SYS_RUN_LEVEL],RLf_PATCHED
+
+ CALL SYS_FIND_PCIBIOS_SERVICE_DIR
+ CALL SYS_FIND_PCI_SERVICES
+ CALL SYS_INIT_PAGE_TABLES
+ CALL SYS_INIT_16MEG_SYS_CODE_BP
+ PUSH U32 0 //Return from next call will be 64-bit
+ CALL SYS_ENTER_LONG_MODE
+
+ //We fall-thou to $LK,"KStart64",A="FL:::/Kernel/KStart64.HC,1"$, next.
+}
+U8 FDC_DMA[0x4800]; // Floppy DMA buffer \ No newline at end of file
diff --git a/Kernel.PRJ b/Kernel.PRJ
new file mode 100644
index 0000000..158b096
--- /dev/null
+++ b/Kernel.PRJ
@@ -0,0 +1,63 @@
+//Compile this by calling $LK,"BootHDIns",A="MN:BootHDIns"$().
+//Don't do it directly. See $LK,"Cmp(\"/Kernel/Kernel\")",A="FF:::/Adam/Opt/Boot/BootHDIns.HC,Cmp(\"/Kernel/Kernel\""$.
+
+#exe {
+ Cd(__DIR__);;
+ Option(OPTf_WARN_PAREN,ON);
+ Option(OPTf_WARN_DUP_TYPES,ON);
+ #include "KCfg"
+ CKCfg *kernel_cfg;
+ kernel_cfg=KCfgNew;
+};
+
+#include "KernelA.HH"
+#include "KStart16"
+#include "KStart32"
+#include "KStart64"
+#include "KMathA"
+#include "KUtils"
+#exe {Option(OPTf_KEEP_PRIVATE,ON);};
+#include "/Compiler/CompilerA.HH"
+#exe {Option(OPTf_EXTERNS_TO_IMPORTS,ON);};
+#include "/Compiler/CompilerB.HH"
+#exe {Option(OPTf_EXTERNS_TO_IMPORTS,OFF);};
+#exe {Option(OPTf_KEEP_PRIVATE,OFF);};
+#include "KernelB.HH"
+#include "KExts"
+#include "StrA"
+#include "KGlbls"
+#include "KMathB"
+#include "Sched"
+#include "Mem/MakeMem"
+#include "FontStd"
+#include "FontCyrillic"
+#include "StrB"
+#include "KHashA"
+#include "KInts"
+#include "KDataTypes"
+#include "Compress"
+#include "KHashB"
+#include "KLoad"
+#include "KDate"
+#include "StrPrint"
+#include "StrScan"
+#include "KDefine"
+#include "Display"
+#include "KMisc"
+#include "KDbg"
+#include "KeyDev"
+#include "KExcept"
+#include "SerialDev/MakeSerialDev"
+#include "QSort"
+#include "KTask"
+#include "Job"
+#include "PCIBIOS"
+#include "MultiProc"
+#include "EdLite"
+#include "BlkDev/MakeBlkDev"
+#include "FunSeg"
+#include "KMain"
+#include "Floppy.HH"
+#include "NewFloppy"
+
+#exe {KCfgDel(kernel_cfg);};
diff --git a/KernelC.HH b/KernelC.HH
new file mode 100644
index 0000000..ffa7c8b
--- /dev/null
+++ b/KernelC.HH
@@ -0,0 +1,787 @@
+#help_index "AutoComplete"
+#help_file "::/Doc/AutoComplete"
+public extern CAutoCompleteGlbls ac;
+
+#help_index "AutoComplete/Dictionary"
+public extern CAutoCompleteDictGlbls acd;
+
+#help_index "Bit"
+public extern I64 BCnt(I64 d);
+public extern U8 *rev_bits_table,*set_bits_table;
+
+#help_index "Boot"
+#help_file "::/Doc/Boot"
+public extern U0 Reboot();
+
+#help_index "Call"
+public argpop extern I64 CallStkGrow(I64 stk_size_threshold,I64 stk_size,
+ /*argpop*/I64 (*fp_addr)(...),...);
+//fp_addr can have any fixed number of arguments.
+
+#help_index "Call/FarCall32"
+public _extern _FAR_CALL32 Bool FarCall32(U0 (*fp_addr)());//Not reentrant
+public _extern C32_EAX U32 c32_eax;
+public _extern C32_EBX U32 c32_ebx;
+public _extern C32_ECX U32 c32_ecx;
+public _extern C32_EDI U32 c32_edi;
+public _extern C32_EDX U32 c32_edx;
+public _extern C32_EFLAGS U32 c32_eflags;
+public _extern C32_ESI U32 c32_esi;
+
+#help_index "Char/BitMaps"
+public extern U32 char_bmp_alpha[16],char_bmp_alpha_numeric[16],
+char_bmp_alpha_numeric_no_at[16], char_bmp_word[16],
+char_bmp_dec_numeric[16], char_bmp_hex_numeric[16],
+char_bmp_white_space[16], char_bmp_non_eol_white_space[16],
+char_bmp_zero_cr_nl_cursor[16], char_bmp_zero_tab_cr_nl_cursor[16],
+char_bmp_zero_tab_cr_nl_cursor_dollar[16],
+char_bmp_macro[16], char_bmp_printable[16],
+char_bmp_displayable[16], char_bmp_safe_dollar[16],
+char_bmp_filename[16], char_bmp_non_eol[16];
+
+#help_index "Char/Conversion"
+public extern U8 *Char2KeyName(I64 ch,Bool include_ctrl=TRUE);
+public extern I64 Char2ScanCode(I64 ch,I64 sc_flags=0);
+public extern U8 ScanCode2Char(I64 sc);
+public extern U8 *ScanCode2KeyName(I64 sc);
+public extern F64 Str2F64(U8 *src,U8 **_end_ptr=NULL);
+public extern I64 Str2I64(U8 *st,I64 radix=10,U8 **_end_ptr=NULL);
+public extern U8 *StrScan(U8 *src,U8 *fmt,...);
+
+#help_index "Char/Conversion;Time/Date/CDate;Date/CDate"
+public extern CDate Str2Date(U8 *src);
+
+#help_index "Char/Flags"
+public extern U0 ScanFlags(U8 *_dst_flags,U8 *lst,U8 *src);
+public extern U8 *StrPrintFlags(U8 *dst,U8 *lst,I64 flags);
+
+#help_index "Char/Lists"
+public extern I64 LstMatch(U8 *needle, U8 *haystack_lst,I64 flags=0);
+public extern U8 *LstSub(I64 sub, U8 *lst);
+
+#help_index "Char/Operations"
+public extern U8 *MStrPrint(U8 *fmt,...);
+public extern U8 *MStrUtil(U8 *src,I64 flags,F64 indent_scale_factor=0);
+public extern U8 *ScaleIndent(U8 *src,F64 indent_scale_factor);
+public extern I64 Spaces2Tabs(U8 *dst,U8 *src);
+public _extern _STRCMP I64 StrCmp(U8 *st1,U8 *st2);
+public _extern _STRCPY U0 StrCpy(U8 *dst,U8 *src);
+public extern U8 *StrFind(U8 *needle,U8 *haystack_str,I64 flags=0);
+public extern U8 *StrFirstOcc(U8 *src,U8 *marker);
+public extern U8 *StrFirstRem(U8 *src,U8 *marker,U8 *dst=NULL);
+public _extern _STRICMP I64 StrICmp(U8 *st1,U8 *st2);
+public _extern _STRIMATCH U8 *StrIMatch(U8 *needle,U8 *haystack_str);
+public extern U8 *StrLastOcc(U8 *src,U8 *marker);
+public extern U8 *StrLastRem(U8 *src,U8 *marker,U8 *dst=NULL);
+public _extern _STRMATCH U8 *StrMatch(U8 *needle,U8 *haystack_str);
+public _extern _STRNCMP I64 StrNCmp(U8 *st1,U8 *st2,I64 n);
+public _extern _STRNICMP I64 StrNICmp(U8 *st1,U8 *st2,I64 n);
+public extern I64 StrOcc(U8 *src, U8 ch);
+public extern U8 *StrPrint(U8 *dst,U8 *fmt,...);
+public extern U8 *StrPrintJoin(U8 *dst,U8 *fmt,I64 argc,I64 *argv);
+public extern U8 *StrUtil(U8 *_src,I64 flags);
+public extern U8 *Tabs2Spaces(U8 *src);
+public extern Bool WildMatch(U8 *test_str,U8 *wild_str);
+
+#help_index "Char/Operations;Memory"
+public extern U8 *CatPrint(U8 *dst,U8 *fmt,...);
+
+#help_index "Char/Operations;Memory/Adam Heap"
+public extern U8 *AStrNew(U8 *buf);
+
+#help_index "Char/Operations;Memory/Heap"
+public extern U8 *StrNew(U8 *buf,CTask *mem_task=NULL);
+
+#help_index "Char/Output;StdOut"
+public extern U0 GetOutOfDollar();
+public extern Bool IsSilent();
+public extern U0 Print(U8 *fmt,...);
+public extern U0 PrintErr(U8 *fmt,...);
+public extern U0 PrintWarn(U8 *fmt,...);
+public extern U0 PutChars(U64 ch);
+extern U0 PutHex(I64 num,I64 width);
+public extern U0 PutKey(I64 ch=0,I64 sc=0);
+extern U0 PutS(U8 *st); //Use $LK,"Print",A="MN:Print"$()
+public extern Bool Silent(Bool val=ON);
+extern U8 *StrPrintHex(U8 *dst,I64 num;I64 width);
+
+#help_index "Char;Debugging/Raw Output;TextBase Layer/Char"
+public extern CTextGlbls text;
+
+#help_index "Compiler/Lex"
+public extern U0 HashSrcFileSet(CCmpCtrl *cc,
+ CHashSrcSym *h,I64 line_num_offset=0);
+
+#help_index "Compiler;Cmd Line (Typically)"
+extern U8 *Load(U8 *filename,I64 ld_flags=0,
+ CBinFile *bfh_addr=INVALID_PTR); //INVALID_PTR=don't care what load addr
+
+#help_index "Compression"
+public extern CArcCompress *CompressBuf(U8 *src,I64 size,CTask *mem_task=NULL);
+public extern U8 *ExpandBuf(CArcCompress *arc,CTask *mem_task=NULL);
+
+#help_index "Compression/Piece by Piece"
+public extern U0 ArcCompressBuf(CArcCtrl *c);
+public extern U0 ArcCtrlDel(CArcCtrl *c);
+public extern CArcCtrl *ArcCtrlNew(Bool expand,I64 compression_type=CT_8_BIT);
+public extern U0 ArcExpandBuf(CArcCtrl *c);
+public extern Bool ArcFinishCompression(CArcCtrl *c);
+
+#help_index "Data Types/Circular Queue"
+public extern I64 QueCnt(CQue *head);
+public extern CQue *QueCopy(CQue *head,CTask *mem_task=NULL);
+public extern U0 QueDel(CQue *head,Bool querem=FALSE);
+public extern I64 QueSize(CQue *head);
+
+#help_index "Data Types/Fifo"
+public extern I64 FifoI64Cnt(CFifoI64 *f);
+public extern U0 FifoI64Del(CFifoI64 *f);
+public extern U0 FifoI64Flush(CFifoI64 *f);
+public extern Bool FifoI64Ins(CFifoI64 *f,I64 q);
+public extern CFifoI64 *FifoI64New(I64 size,CTask *mem_task=NULL);
+public extern Bool FifoI64Peek(CFifoI64 *f,I64 *_q);
+public extern Bool FifoI64Rem(CFifoI64 *f,I64 *_q);
+public extern I64 FifoU8Cnt(CFifoU8 *f);
+public extern U0 FifoU8Del(CFifoU8 *f);
+public extern U0 FifoU8Flush(CFifoU8 *f);
+public extern Bool FifoU8Ins(CFifoU8 *f,U8 b);
+public extern CFifoU8 *FifoU8New(I64 size,CTask *mem_task=NULL);
+public extern Bool FifoU8Peek(CFifoU8 *f,U8 *_b);
+public extern Bool FifoU8Rem(CFifoU8 *f,U8 *_b);
+
+#help_index "Data Types/Linked List"
+public extern I64 LinkedLstCnt(U8 **_lst);
+public extern U8 *LinkedLstCopy(U8 **_lst,CTask *mem_task=NULL);
+public extern U0 LinkedLstDel(U8 **_lst);
+public extern I64 LinkedLstSize(U8 **_lst);
+
+#help_index "Data Types/Queue Vector"
+public extern U0 QueVectU8Del(CQueVectU8 *v);
+public extern I64 QueVectU8Get(CQueVectU8 *v,I64 idx);
+public extern CQueVectU8 *QueVectU8New(I64 min_idx=0);
+public extern U0 QueVectU8Put(CQueVectU8 *v,I64 idx,U8 ch);
+
+#help_index "Debugging"
+public extern U8 *Caller(I64 num=1);
+public extern Bool ChkCodePtr(U8 *ptr);
+public extern Bool ChkOnStk(U8 *ptr,CTask *task=NULL);
+public extern Bool ChkPtr(U8 *ptr);
+public extern Bool IsSingleUser();
+public extern Bool IsSysDbg();
+public extern Bool SingleUser(Bool val);
+public extern Bool SysDbg(Bool val);
+public extern U8 *TaskCaller(CTask *task=NULL,
+ I64 num=0,Bool saved_context=FALSE);
+public extern I64 UnusedStk(CTask *task=NULL);
+public extern CDbgGlbls dbg;
+
+#help_index "Debugging/Debugger"
+public extern Bool B(U8 *addr,CTask *task=NULL,Bool live=TRUE) //Toggle bpt.
+public extern I64 B2(CTask *task=NULL,Bool live=TRUE);
+extern CBpt *BptFind(U8 *needle_addr,CTask *haystack_task=NULL,Bool rem=FALSE);
+public extern Bool BptR(U8 *addr,CTask *task=NULL,Bool live=TRUE,Bool rem=TRUE);
+public extern Bool BptS(U8 *addr,CTask *task=NULL,Bool live=TRUE);
+public extern Bool DbgMode(Bool val);
+public extern Bool E(U8 *addr,I64 cnt=512,I64 edf_dof_flags=0);
+public extern Bool EdLite(U8 *filename,I64 num=1,I64 edf_dof_flags=0);
+extern Bool EdLiteFileLine(U8 *fl_file_line,I64 edf_dof_flags=0);
+public extern Bool Fix(I64 edf_dof_flags=0);
+public extern U0 FixSet(U8 *filename,I64 line);
+public extern U0 G(U8 *ms=INVALID_PTR,CTask *task=NULL);
+public extern U0 G2(U8 *ms=INVALID_PTR,CTask *task=NULL);
+public extern Bool IsDbgMode();
+public extern U0 S(U8 *ms=INVALID_PTR,CTask *task=NULL);
+
+#help_index "Debugging/Debugger;DolDoc/Cmd Line (Typically);"\
+ "Cmd Line (Typically);Help System"
+public extern Bool Man(U8 *st,I64 edf_dof_flags=0);
+
+#help_index "Debugging/Dump"
+public extern U0 CallerRep(U8 **rbp=NULL,CTask *task=NULL);
+public extern U0 D(U8 *addr,I64 cnt=0x80,Bool show_offset=TRUE);
+public extern U0 Da(U8 **addr,I64 cnt=0x10);
+public extern U0 Dm(U8 *addr,I64 cnt=0x80);
+public extern U0 Dr(CTask *task=NULL);
+public extern U0 StkRep(CTask *task=NULL);
+extern I64 *TaskRegAddr(CTask *task,I64 reg_num);
+
+#help_index "Debugging/FunSeg"
+#help_file "::/Doc/DbgFunSeg"
+public extern Bool PutSrcLink(U8 *addr,I64 cnt=1,U8 *buf=NULL);
+public extern U8 *SrcEdLink(U8 *addr,I64 cnt=1,CTask *mem_task=NULL);
+public extern U8 *SrcFileName(U8 *addr,I64 cnt=1,CTask *mem_task=NULL);
+public extern I64 SrcLineNum(U8 *addr,I64 cnt=1);
+
+#help_index "Debugging/FunSeg;Hash/System"
+public extern CHash *FunSegFind(U8 *addr,I64 *_offset);
+
+#help_index "Debugging/Raw Output"
+public extern Bool IsRaw();
+public extern Bool Raw(Bool val);
+public extern U0 RawD(I64 mS=100,U8 *addr,I64 cnt=0x80);
+public extern U0 RawDm(I64 mS=100,U8 *addr,I64 cnt=0x80);
+extern U0 RawDr(CTask *task=NULL);
+public extern U0 RawPrint(I64 mS=100,U8 *fmt,...);
+public extern U0 RawPutChar(I64 ch);
+public extern U0 VGAFlush();
+
+#help_index "Debugging;Debugging/Debugger"
+public extern U0 Dbg(U8 *msg=NULL,I64 msg_num=0);
+public extern U0 Panic(U8 *msg=NULL,I64 msg_num=0,Bool panic=TRUE);
+
+#help_index "Define;Char/Define"
+#help_file "::/Doc/Define"
+public extern U8 *Define(U8 *dname);
+public extern CHashDefineStr *DefineLoad(U8 *dname,U8 *st);
+public extern U0 DefinePrint(U8 *dname,U8 *src,...);
+
+#help_index "Define;Char/Define;Char/Lists"
+public extern I64 DefineCnt(U8 *dname);
+public extern CHashDefineStr *DefineLstLoad(U8 *dname,U8 *lst);
+public extern I64 DefineMatch(U8 *needle,U8 *haystack_lst_dname,I64 flags=0);
+public extern U8 *DefineSub(I64 sub,U8 *dname);
+
+#help_index "Devices;Memory/Page Tables"
+public extern U8 *Mem32DevAlloc(I64 size,I64 alignment);
+public extern U0 Mem32DevFree(U8 *base);
+public extern U8 *Mem64DevAlloc(I64 *_pages1Gig);
+public extern U0 Mem64DevFree(U8 *base,I64 pages1Gig);
+public extern CDevGlbls dev;
+
+#help_index "DolDoc/Clip"
+public extern CDoc *sys_clip_doc;
+
+#help_index "DolDoc/Task;StdOut/Task"
+#help_file "::/Doc/StdOutTask"
+extern CDoc *(*fp_doc_put)(CTask *task=NULL);
+
+#help_index "Exceptions"
+public extern U0 Break();
+public extern Bool BreakLock(CTask *task=NULL);
+public extern Bool BreakUnlock(CTask *task=NULL);
+public extern U0 PutExcept(Bool catch_it=TRUE);
+extern U0 SysTry(U8 *start_label,U8 *skip_label);
+extern U0 SysUntry();
+public extern U0 throw(I64 ch=0,Bool no_log=FALSE);
+
+#help_index "File/CD DVD"
+public extern U0 DVDImageRead(U8 dvd_drv_let,U8 *out_name);
+public extern U0 DVDImageWrite(U8 dvd_drv_let,
+ U8 *in_name=NULL,I64 media_type=MT_DVD);
+
+#help_index "File/CFile"
+public extern Bool FBlkRead(CFile *f,U8 *buf,I64 blk=FFB_NEXT_BLK,I64 cnt=1);
+public extern Bool FBlkWrite(CFile *f,U8 *buf,I64 blk=FFB_NEXT_BLK,I64 cnt=1);
+public extern U0 FClose(CFile *f);
+public extern CFile *FOpen(U8 *filename,U8 *flags,I64 cnt=0);
+public extern I64 FSize(CFile *f);
+
+#help_index "File/Cmd Line (Typically);Cmd Line (Typically)"
+public extern Bool Cd(U8 *dirname=NULL,Bool make_dirs=FALSE);
+public extern I64 Del(U8 *files_find_mask,Bool make_mask=FALSE,
+ Bool del_dir=FALSE,Bool print_msg=TRUE);
+public extern I64 Dir(U8 *files_find_mask="*",Bool full=FALSE);
+public extern Bool DirMk(U8 *filename,I64 entry_cnt=0);
+public extern Bool Drv(U8 drv_let);
+public extern U0 DskChg(U8 drv_let=0);
+public extern U0 HomeSet(U8 *dirname);
+
+#help_index "File/Cmd Line (Typically);Cmd Line (Typically);Install"
+public extern Bool DrvMap(U8 drv_let,CDrv *dv);
+
+#help_index "File/FileNames"
+extern CDirEntry *Cd2DirEntry(CDirEntry *tmpde,U8 *abs_name);
+public extern U8 *DirCur(CTask *task=NULL,CTask *mem_task=NULL);
+public extern U8 *DirFile(U8 *dirname,U8 *name=NULL,U8 *_extension=NULL);
+public extern U8 *DirNameAbs(U8 *dirname);
+public extern CBlkDev *DrvIsWritable(U8 drv_let=0,Bool except=FALSE);
+public extern U8 *ExtChg(U8 *filename,U8 *extension);
+public extern U8 *ExtDft(U8 *filename,U8 *extension);
+public extern U8 *FileExtDot(U8 *src);
+public extern U8 *FileExtRem(U8 *src,U8 *dst=NULL);
+public extern U8 *FileNameAbs(U8 *filename,I64 fuf_flags=0);
+public extern Bool FileNameChk(U8 *filename);
+public extern Bool FilesFindMatch(U8 *_test_name,
+ U8 *files_find_mask,I64 fuf_flags=0);
+public extern Bool IsDir(U8 *dir_name);
+public extern Bool IsDotC(U8 *filename);
+public extern Bool IsDotZ(U8 *filename);
+public extern U0 PutDirLink(U8 *dirname,U8 *full_name=NULL);
+public extern U0 PutFileLink(U8 *filename,U8 *full_name=NULL,
+ I64 line=0,Bool plain_text=FALSE);
+public extern U0 ToFileLine(U8 *_fl_file_line,U8 **_filename,I64 *_linenum);
+public extern U8 *ToggleZorNotZ(U8 *name);
+
+#help_index "File/FileNames;Misc"
+public extern U8 *FileNameTmpTxt();
+
+#help_index "File/Internal"
+public extern U0 DirContextDel(CDirContext *dirc,Bool restore=TRUE);
+public extern CDirContext *DirContextNew(U8 *mask,
+ Bool make_mask=FALSE,Bool make_dirs=FALSE,Bool no_mask=FALSE);
+public extern Bool DirNew(CDrv *dv,U8 *cur_dir,
+ CDirEntry *tmpde,Bool free_old_chain=TRUE);
+extern I64 FileAttr(U8 *name,I64 old_attr=0);
+
+#help_index "File/Low Level"
+#help_file "::/Doc/FileLowLevel"
+public extern CBlkDev *BlkDevChk(CBlkDev *bd,Bool except=TRUE);
+public extern U0 BlkDevDel(CBlkDev *bd);
+public extern Bool BlkDevLock(CBlkDev *bd);
+public extern CBlkDev *BlkDevNextFreeSlot(U8 first_drv_let,I64 type);
+public extern Bool BlkDevUnlock(CBlkDev *bd,Bool rst=FALSE);
+public extern U0 BlkDevsRelease();
+public extern Bool BlkRead(CDrv *dv,U8 *buf, I64 blk, I64 cnt);
+public extern Bool BlkWrite(CDrv *dv,U8 *buf, I64 blk, I64 cnt);
+public extern U0 BlkWriteZero(CDrv *dv,I64 blk,I64 cnt);
+public extern I64 Clus2Blk(CDrv *dv,I64 c);
+public extern I64 ClusAlloc(CDrv *dv,I64 c=0,
+ I64 cnt=1,Bool contiguous=FALSE);
+public extern I64 ClusBlkRead(CDrv *dv,U8 *buf,I64 c,I64 blks);
+public extern I64 ClusBlkWrite(CDrv *dv,U8 *buf,I64 c,I64 blks);
+public extern I64 ClusNumNext(CDrv *dv,I64 c,I64 cnt=1);
+public extern I64 ClusRead(CDrv *dv,U8 *buf,I64 c,I64 cnt);
+public extern I64 ClusWrite(CDrv *dv,U8 *buf,I64 c,I64 cnt);
+extern Bool CopySingle(U8 *f1,U8 *f2); //Just one file
+public extern U8 Drv2Let(CDrv *dv=NULL);
+public extern CDrv *DrvChk(CDrv *dv,Bool except=TRUE);
+public extern U0 DrvDel(CDrv *dv);
+public extern Bool DrvLock(CDrv *dv);
+public extern CDrv *DrvMakeFreeSlot(U8 drv_let);
+public extern U8 *DrvModelNum(U8 drv_let=0);
+public extern U8 DrvNextFreeLet(U8 first_drv_let='C');
+public extern U8 *DrvSerialNum(U8 drv_let=0);
+public extern U8 DrvTextAttrGet(U8 drv_let=0);
+public extern Bool DrvUnlock(CDrv *dv,Bool rst=FALSE);
+public extern U0 DrvsRelease();
+extern U0 FAT32FreeClus(CDrv *dv,I64 c);
+public extern CBlkDev *Let2BlkDev(U8 drv_let=0,Bool except=TRUE);
+public extern I64 Let2BlkDevType(U8 drv_let);
+public extern CDrv *Let2Drv(U8 drv_let=0,Bool except=TRUE);
+public extern U8 Let2Let(U8 drv_let=0);
+extern I64 Name2DirClus(CDrv *dv,U8 *dirname);
+extern I64 Name2ParentDirClus(CDrv *dv,U8 *dirname);
+extern U0 RedSeaFreeClus(CDrv *dv,I64 c,I64 cnt);
+
+#help_index "File/Program Routines"
+public extern U0 DirEntryDel(CDirEntry *tmpde);
+public extern U0 DirEntryDel2(CDirEntry *tmpde);
+public extern U0 DirTreeDel(CDirEntry *tmpde);
+public extern U0 DirTreeDel2(CDirEntry *tmpde);
+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);
+public extern I64 FileWrite(U8 *filename,
+ U8 *fbuf,I64 size,CDate cdt=0,I64 attr=0);
+
+#help_index "File/Program Routines;File/FileNames"
+public extern CDirEntry *FilesFind(U8 *files_find_mask,I64 fuf_flags=0);
+
+#help_index "File/System"
+public extern CATARep *ATAIDDrvs(CATARep *head,CATARep **_ata_drv,
+ CATARep **_atapi_drv);
+extern CBlkDev *ATAMount(U8 first_drv_let,
+ I64 type,I64 base0,I64 base1,I64 unit);
+extern Bool ATAPIStartStop(CBlkDev *bd,F64 timeout,Bool start);
+extern I64 ATAProbe(I64 base0,I64 base1,I64 unit);
+extern U0 ATAReadBlks(CBlkDev *bd,U8 *buf, I64 blk, I64 cnt);
+extern U0 ATAWriteBlks(CBlkDev *bd,U8 *buf, I64 blk, I64 cnt);
+extern I64 BlkDevAdd(CBlkDev *bd,I64 prt_num=I64_MIN,
+ Bool whole_drv,Bool make_free);
+extern U0 DskCacheInit(I64 size_in_U8s);
+public extern U0 DskCacheInvalidate(CDrv *dv);
+public extern I64 MountIDEAuto();
+public extern CBlkDevGlbls blkdev;
+
+#help_index "Graphics/Color"
+extern U0 (*fp_set_std_palette)();
+public extern U8 *Color2Str(U8 *buf,CColorROPU32 c);
+public extern CColorROPU16 Str2ColorU16(U8 *st);
+public extern CColorROPU32 Str2ColorU32(U8 *st);
+
+#help_index "Hash"
+#help_file "::/Doc/Hash"
+public _extern _HASH_ADD U0 HashAdd(CHash *tmph,CHashTable *table);
+public _extern _HASH_ADD_AFTER U0 HashAddAfter(CHash *tmph,
+ CHash *pred,CHashTable *table); //Add hash entry after entry.
+public _extern _HASH_BUCKET_FIND CHash **HashBucketFind(
+ U8 *needle_str,CHashTable *haystack_table);
+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_STR I64 HashStr(U8 *st);
+public extern CHashTable *HashTableNew(I64 size,CTask *mem_task=NULL);
+
+#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=0,CTask *task=NULL);
+public extern I64 FramePtrDel(U8 *name,CTask *task=NULL);
+public extern I64 FramePtrSet(U8 *name,I64 val,CTask *task=NULL);
+
+#help_index "Hash/System"
+public extern U0 HashDel(CHashSrcSym *tmph);
+public extern CHashGeneric *HashGenericAdd(U8 *name,
+ I64 type,I64 val=0,I64 u8=0,I64 u16=0,CTask *task=NULL);
+public extern CHashGeneric *HashPublic(U8 *st,I64 mask,Bool val=TRUE);
+public _extern _HASH_REM_DEL Bool HashRemDel(CHash *tmph,CHashTable *table,
+ I64 instance=1);//instance must match tmph's
+public extern U0 HashTableDel(CHashTable *table);
+public extern I64 HashTablePurge(CHashTable *table);
+public extern I64 HashTypeNum(CHash *tmph);
+public extern I64 HashVal(CHash *tmph);
+extern U0 SysSymImportsResolve(U8 *sptr,I64 ld_flags=0);
+
+#help_index "Hash/System;Char/Lists"
+public extern I64 HashLstAdd(U8 *lst,I64 type,CHashTable *table);
+
+#help_index "Hash/System;Define;Char/Define;Char/Lists"
+public extern I64 HashDefineLstAdd(U8 *dname,I64 type,CHashTable *table);
+
+#help_index "Help System;Debugging/Debugger"
+public extern U0 Help();
+
+#help_index "Info;File/Cmd Line (Typically);Cmd Line (Typically);Install"
+public extern U0 DrvRep();
+
+#help_index "Install"
+#help_file "::/Doc/Install"
+extern CATARep *ATARepFind(CATARep *haystack_head,I64 needle_num);
+public extern Bool DrvEnable(U8 drv_let,Bool val);
+
+#help_index "Install;File/Cmd Line (Typically);Cmd Line (Typically);"
+public extern U0 Fmt(U8 drv_let,Bool quick=TRUE,
+ Bool confirm=TRUE,I64 type=FSt_FAT32);
+
+#help_index "Install;Memory/BlkPool"
+public extern I64 Scale2Mem(I64 min,I64 max,I64 limit=2*1024*1024*1024);
+
+#help_index "Job/Exe;Task/Job/Exe"
+public extern U0 AdamErr(U8 *fmt,...);
+public extern U0 AdamLog(U8 *fmt,...);
+public extern I64 ExeCmdLine(CCmpCtrl *cc);
+public extern U0 JobDel(CJob *tmpc);
+public extern I64 JobsHndlr(I64 run_flags,CTask *task=NULL);
+extern U0 SrvCmdLine();
+public extern U0 SrvTaskCont();
+public extern CJob *TaskExe(CTask *srv,CTask *master,U8 *data,I64 flags);
+public extern U0 TaskRstAwaitingMsg(CTask *task=NULL);
+public extern U0 UserTaskCont();
+
+#help_index "Job/Exe;Task/Job/Exe;Compiler"
+public extern I64 Adam(U8 *fmt,...);
+public extern I64 PopUp(U8 *buf,CTask *parent=NULL,CTask **_pu_task=NULL);
+public extern I64 PopUpPrint(U8 *fmt,...);
+
+#help_index "Job/Exe;Task/Job/Exe;MultiCore"
+public extern I64 JobResGet(CJob *rqst=NULL);
+public extern Bool JobResScan(CJob *rqst=NULL,I64 *_res=NULL);
+
+#help_index "Job/Text & Msgs;Task/Job/Text & Msgs"
+public extern CJob *TaskText(CTask *srv,CTask *master,U8 *data,I64 flags);
+
+#help_index "Job/Text & Msgs;Task/Job/Text & Msgs;InFile;StdIn/InFile"
+public extern U0 In(U8 *fmt,...);
+public extern U0 InFile(U8 *filename);
+public extern U0 InStr(U8 *fmt,...);
+public extern U0 XTalk(CTask *task,U8 *fmt,...);
+public extern U0 XTalkStr(CTask *task,U8 *fmt,...);
+public extern U0 XTalkStrWait(CTask *task,U8 *fmt,...);
+public extern U0 XTalkWait(CTask *task,U8 *fmt,...);
+
+#help_index "Job/Text & Msgs;Task/Job/Text & Msgs;Messages"
+public extern U0 Msg(I64 msg_code,I64 arg1,I64 arg2,I64 flags=0);
+public extern U0 PostMsg(CTask *task,
+ I64 msg_code,I64 arg1,I64 arg2,I64 flags=0);
+public extern U0 PostMsgWait(CTask *task,I64 msg_code,
+ I64 arg1,I64 arg2,I64 flags=0);
+public extern CJob *TaskMsg(CTask *srv,CTask *master,
+ I64 msg_code,I64 arg1,I64 arg2,I64 flags);
+
+#help_index "Job;Task/Job"
+#help_file "::/Doc/Job"
+
+#help_index "Keyboard Devices/System;Char/System"
+#help_file "::/Doc/KeyDev"
+public extern U0 CtrlAltCBSet(U8 ch,U0 (*fp_hndlr)(I64 sc),
+ U8 *no_shift_desc=NULL,U8 *shift_desc=NULL,Bool in_irq=FALSE);
+public extern U0 KeyDescSet(U8 *fmt,...);
+public extern CKeyDevEntry *KeyDevAdd(Bool (*fp_put_key)(I64 ch,I64 sc),
+ Bool (*fp_puts)(U8 *st),I64 priority,Bool key_descs=FALSE);
+public extern U0 KeyDevRem(CKeyDevEntry *tmpk);
+extern CKeyDevGlbls keydev;
+extern CJob sys_macro_head;
+extern CTask *sys_macro_task;
+
+#help_index "Keyboard Devices;Char/Input;StdIn"
+extern U8 *(*fp_getstr2)(I64 flags=0); //GetStr $LK,"Flags",A="MN:GSF_SHIFT_ESC_EXIT"$
+public extern Bool AreYouSure();
+public extern I64 GetChar(I64 *_scan_code=NULL,Bool echo=TRUE,
+ Bool raw_cursor=FALSE);
+public extern I64 GetKey(I64 *_scan_code=NULL,Bool echo=FALSE,
+ Bool raw_cursor=FALSE);
+public extern I64 GetS(U8 *buf,I64 size,Bool allow_ext=TRUE);
+public extern U8 *GetStr(U8 *msg=NULL,U8 *dft=NULL,I64 flags=0);
+extern U0 KbdInit();
+public extern I64 KbdMsEvtTime();
+extern U0 KbdMsHndlr(Bool poll_kbd,Bool poll_ms);
+extern U0 KbdMsInit();
+extern I64 KbdMsgsQue();
+public extern U0 KbdTypeMatic(U8 delay);
+extern Bool MsHardDrvrInstall();
+public extern I64 PressAKey();
+public extern I64 ScanChar();
+public extern Bool ScanKey(I64 *_ch=NULL,I64 *_scan_code=NULL,Bool echo=FALSE);
+public extern Bool YorN();
+public extern CKbdStateGlbls kbd;
+
+#help_index "Math"
+public extern I64 CeilI64(I64 num,I64 to);
+public extern U64 CeilU64(U64 num,U64 to);
+public extern F64 Clamp(F64 d,F64 lo,F64 hi);
+public extern I64 FloorI64(I64 num,I64 to);
+public extern U64 FloorU64(U64 num,U64 to);
+public extern F64 Max(F64 n1,F64 n2);
+public extern F64 Min(F64 n1,F64 n2);
+public extern F64 Pow10I64(I64 i);
+public extern F64 Rand(); //With timestamp
+public extern I16 RandI16();
+public extern I32 RandI32();
+public extern I64 RandI64();
+public extern U16 RandU16();
+public extern U32 RandU32();
+public extern U64 RandU64();
+public extern I64 RoundI64(I64 num,I64 to);
+public extern I64 Seed(I64 seed=0,CTask *task=NULL);
+
+#help_index "Memory/Adam Heap"
+public extern U8 *ACAlloc(I64 size);
+public extern U8 *AMAlloc(I64 size);
+public extern U8 *AMAllocIdent(U8 *src);
+
+#help_index "Memory/BlkPool"
+public extern U0 BlkPoolAdd(CBlkPool *bp,CMemBlk *m,I64 pags);
+public extern U0 BlkPoolInit(CBlkPool *bp,I64 pags);
+public extern U8 *MemPagAlloc(I64 pags,CBlkPool *bp=NULL);
+public extern U0 MemPagFree(CMemBlk *m,CBlkPool *bp=NULL);
+
+#help_index "Memory/Heap"
+public extern U8 *CAlloc(I64 size,CTask *mem_task=NULL);
+public extern U8 *CAllocAligned(I64 size,I64 alignment,
+ CTask *mem_task=NULL,I64 misalignment=0);
+public _extern _FREE U0 Free(U8 *addr);
+public _extern _MALLOC U8 *MAlloc(I64 size,CTask *mem_task=NULL);
+public extern U8 *MAllocAligned(I64 size,I64 alignment,
+ CTask *mem_task=NULL,I64 misalignment=0);
+public extern U8 *MAllocIdent(U8 *src,CTask *mem_task=NULL);
+public _extern _MHEAP_CTRL CHeapCtrl *MHeapCtrl(U8 *src);
+public _extern _MSIZE I64 MSize(U8 *src); //size of heap object
+public _extern _MSIZE2 I64 MSize2(U8 *src); //Internal size
+
+#help_index "Memory/HeapCtrl"
+public extern U0 HeapCtrlDel(CHeapCtrl *hc);
+public extern CHeapCtrl *HeapCtrlInit(CHeapCtrl *hc=NULL,
+ CTask *task=NULL,CBlkPool *bp);
+
+#help_index "Memory/Page Tables"
+public extern I64 *MemPageTable(U8 *a);
+
+#help_index "Messages"
+#help_file "::/Doc/Msgs"
+public extern I64 FlushMsgs(CTask *task=NULL);
+public extern I64 GetMsg(I64 *_arg1=NULL,I64 *_arg2=NULL,
+ I64 mask=~1,CTask *task=NULL);
+extern U0 InputFilterTask();
+public extern I64 ScanMsg(I64 *_arg1=NULL,I64 *_arg2=NULL,
+ I64 mask=~1,CTask *task=NULL);
+
+#help_index "Misc"
+public extern I64 EndianI64(I64 d);
+public extern U16 EndianU16(U16 d);
+public extern U32 EndianU32(U32 d);
+public extern U0 QSort(U8 *base,I64 num, I64 width,
+ I64 (*fp_compare)(U8 *e1,U8 *e2));
+public extern U0 QSortI64(I64 *base,I64 num,
+ I64 (*fp_compare)(I64 e1,I64 e2));
+public extern F64 sys_os_version;
+
+#help_index "Misc/Progress Bars"
+public extern U0 ProgressBarsRst(U8 *path=NULL);
+
+#help_index "Mouse"
+#help_file "::/Doc/Mouse"
+public extern U0 GridInit();
+public extern U0 MsSet(I64 x=I64_MAX,I64 y=I64_MAX,I64 z=I64_MAX,
+ I64 l=I64_MAX,I64 r=I64_MAX);
+public extern CMsStateGlbls ms;
+public extern CGridGlbls ms_grid;
+public extern CMsHardStateGlbls ms_hard;
+extern CMsHardStateGlbls ms_hard_last;
+extern CMsStateGlbls ms_last;
+
+#help_index "Mouse/Ptr"
+extern U0 MsInit();
+extern U0 MsUpdate(I64 x,I64 y,I64 z,Bool l,Bool r);
+
+#help_index "MultiCore"
+extern U0 Core0StartMP();
+extern U0 CoreAPSethTask();
+public extern U0 MPInt(U8 num,I64 cpu_num=1);
+public extern U0 MPIntAll(U8 num);
+public extern U0 MPNMInt();
+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<<JOBf_ADD_TO_QUE);
+
+#help_index "MultiCore;Boot"
+public extern U0 MPHalt();
+
+#help_index "MultiCore;Job/Exe;Task/Job/Exe"
+public extern CJob *JobQue(I64 (*fp_addr)(U8 *data),U8 *data=NULL,
+ I64 target_cpu=1,I64 flags=1<<JOBf_FREE_ON_COMPLETE,
+ I64 job_code=JOBT_CALL,U8 *aux_str=NULL,I64 aux1=0,I64 aux2=0);
+
+#help_index "PCI"
+public extern I64 PCIClassFind(I64 class_code,I64 n);
+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 U8 PCIReadU8(I64 bus,I64 dev,I64 fun,I64 rg);
+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 U0 PCIWriteU8(I64 bus,I64 dev,I64 fun,I64 rg,I64 val);
+public _extern SYS_PCIBIOS_SERVICE_DIR
+ U32 sys_PCIBIOS_service_dir;//Far call routine in the BIOS
+public _extern SYS_PCI_SERVICES
+ U32 sys_pci_services;//Far call routine in the BIOS
+
+#help_index "PCI;Info;File/System;Devices"
+public extern I64 ATARep(Bool pmt=TRUE,
+ Bool just_ide=FALSE,CATARep **_head=NULL);
+
+#help_index "Processor"
+public extern U8 *IntEntryGet(I64 irq);
+public extern U8 *IntEntrySet(I64 irq,
+ U0 (*fp_new_hndlr)(),I64 type=IDTET_IRQ,I64 dpl=0);
+
+#help_index "ScrnCast;Cmd Line (Typically)"
+public extern Bool ScrnCast(Bool val=ON,Bool just_audio=FALSE,
+ U8 *print_fmt="B:/Tmp/%X.GR")
+public extern CScrnCastGlbls scrncast;
+
+#help_index "Snd"
+#help_file "::/Doc/Snd"
+public extern U0 Beep(I8 ona=62,Bool busy=FALSE);
+public extern I8 Freq2Ona(F64 freq);
+public extern Bool IsMute();
+public extern Bool Mute(Bool val);
+public extern F64 Ona2Freq(I64 ona);
+public extern U0 Snd(I8 ona=0);
+public extern U0 SndRst();
+
+#help_index "StdIn"
+#help_file "::/Doc/Streams"
+
+#help_index "StdOut"
+#help_file "::/Doc/Streams"
+
+#help_index "Task"
+public extern I64 BirthWait(CTask **_task,I64 task_num=-1);
+public extern U0 DeathWait(CTask **_task,Bool send_exit=FALSE);
+public extern U0 Exit();
+public extern Bool IsSuspended(CTask *task=NULL);
+public extern Bool Kill(CTask *task,Bool wait=TRUE,Bool just_break=FALSE);
+public extern Bool Suspend(CTask *task=NULL,Bool state=TRUE);
+_extern _TASK_CONTEXT_RESTORE U0 TaskContextRestore();
+_extern _TASK_END_NOW U0 TaskEndNow();
+extern U0 TaskKillDying();
+public extern U0 TaskQueIns(CTask *task,CTask *pred=NULL);
+public extern U0 TaskQueRem(CTask *task);
+public extern Bool TaskValidate(CTask *task);
+public extern U0 TaskWait(CTask *task=NULL,Bool cmd_line_pmt=FALSE);
+public extern CTask *User(U8 *fmt=NULL,...);
+public extern U0 UserCmdLine();
+public _extern _YIELD U0 Yield();
+public extern CTask *adam_task;
+public extern I64 sys_num_spawned_tasks;
+extern CTask *sys_winmgr_task,*sys_task_being_scrn_updated;
+
+#help_index "Task/Delay;Time/CPU Cycles"
+public extern U0 Busy(I64 ęS); //Loosely timed
+public extern U0 PortNop(); //On the order of 1uS
+extern I64 TimeCal();
+
+#help_index "Task/Delay;Time/Jiffies"
+public extern U0 Sleep(I64 mS);
+public extern U0 SleepUntil(I64 wake_jiffy);
+
+#help_index "Task/Misc"
+extern U0 (*fp_update_ctrls)(CTask *task);
+public extern U0 TSSBusy(I64 tr,Bool val=OFF);
+public extern U0 TaskDerivedValsUpdate(CTask *task=NULL,Bool update_z_buf=TRUE);
+public extern U0 WinDerivedValsUpdate(CTask *task);
+
+#help_index "Task;Job/Exe;Task/Job/Exe;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<<JOBf_ADD_TO_QUE);
+
+#help_index "Time/CPU Cycles;Time/HPET;Time/Jiffies"
+public extern CCntsGlbls cnts;
+
+#help_index "Time/Date/CDate;Date/CDate"
+#help_file "::/Doc/TimeDate"
+public extern U0 Date2Struct(CDateStruct *_ds,CDate cdt);
+extern U8 *MPrintDate(CDate cdt);
+extern U8 *MPrintTime(CDate cdt);
+public extern CDate Now();
+public extern CDate Struct2Date(CDateStruct *_ds);
+public extern CDate local_time_offset;
+
+#help_index "Time/Date;Date"
+#help_file "::/Doc/Date"
+public extern I64 DayOfWeek(I64 i);
+public extern I64 FirstDayOfMon(I64 i);
+public extern I64 FirstDayOfYear(I64 i);
+public extern I64 LastDayOfMon(I64 i);
+public extern I64 LastDayOfYear(I64 i);
+public extern I64 YearStartDate(I64 year);
+public extern U16 mon_start_days1[12];
+public extern U16 mon_start_days2[12];
+
+#help_index "Time/HPET"
+#help_file "::/Doc/TimeHPET"
+public extern I64 HPET();
+
+#help_index "Time/Jiffies"
+#help_file "::/Doc/TimeJiffy"
+public extern I64 SysTimerRead();//18.33333*65536Hz (SYS_TIMER_FREQ)
+
+#help_index "Time/Seconds"
+public extern Bool Blink(F64 Hz=2.5);
+public extern F64 tS(); //From SysTimerFreq.
+
+#help_index "Windows"
+public extern Bool WinInside(I64 x,I64 y,CTask *task=NULL,I64 border=0);
+
+#help_index ""
+// headers for floppy driver
+public extern Bool FDCIrq;
+public extern U16 fdc_base;
+public extern U0 CMOSGetFloppyDrives();
+public extern U0 FDCSendCmd(U16 base, U8 cmd);
+public extern U8 FDCReadData(U16 base);
+public extern U0 FDCCheckInt(U16 base, U8 *st0, U8 *cyl);
+public extern I16 fdc_mtr_ticks;
+public extern U8 fdc_mtr_state;
+public extern U0 FDCMotorOff(U16 base);
+public extern U0 FDCMotorPwrOffTimer();
+public extern U0 FDCMotorCtrl(U16 base, Bool onoff);
+public extern I8 FDCRecalibrate(U16 base);
+public extern I8 FDCReset(U16 base);
+public extern I8 FDCSeek(U16 base, U8 cyli, U8 head);
+public extern U0 FDCRead(U16 base, U8 cyl, U8 head, U8 sect, U8 trklen);
+public extern U0 FDCReadMulti(U16 base, U8 cyl, U8 head, U8 sect, U8 trklen);
+public extern U0 FDCWrite(U16 base, U8 cyl, U8 head, U8 sect, U8 trklen);
+public extern U0 FDCWriteMulti(U16 base, U8 cyl, U8 head, U8 sect, U8 trklen); \ No newline at end of file
diff --git a/NewFloppy.HC b/NewFloppy.HC
new file mode 100644
index 0000000..9e67467
--- /dev/null
+++ b/NewFloppy.HC
@@ -0,0 +1,477 @@
+/*
+ New, (hopefully) Less Messy Floppy Driver
+ Copyright (C) 2025 Yoshi128k.
+ Licensed under version 2 of the Do What The Fuck You Want To Public License
+ See COPYING for details.
+*/
+
+Bool FDCIrq = FALSE;
+
+U0 FDCDMAInit(U16 len)
+{
+ U64 /*buf_lo, buf_hi, page,*/ cnt_lo, cnt_hi;
+
+// buf_lo = &FDC_DMA & 0xFF;
+// buf_hi = &FDC_DMA >> 8;
+// page = &FDC_DMA >> 16;
+ cnt_lo = (len - 1) & 0xFF;
+ cnt_hi = (len - 1) >> 8;
+
+ OutU8(0x0A, 6); // mask ch 0 and 2
+ Sleep(1);
+ OutU8(0x0C, -1); // reset flip flop
+ Sleep(1);
+ OutU8(0x04, 0x75); // buf low byte
+ Sleep(1);
+ OutU8(0x04, 0x9F); // buf high byte
+ Sleep(1);
+ OutU8(0x0C, -1); // reset flip flop again
+ Sleep(1);
+ OutU8(0x05, cnt_lo); // cntr low byte
+ Sleep(1);
+ OutU8(0x05, cnt_hi); // cntr high byte
+ Sleep(1);
+ OutU8(0x81, 0); // page
+ Sleep(1);
+ OutU8(0x0A, 2); // unmask ch 0 and 2
+ Sleep(1);
+}
+
+U0 FDCDMAPrepWrite()
+{
+ OutU8(0x0A, 6); // mask ch 0 and 2
+ Sleep(1);
+ OutU8(0x0B, 0x5A); // single xfer, addr inc, auto init, write, ch 2
+ Sleep(1);
+ OutU8(0x0A, 2); // unmask ch 0 and 2
+ Sleep(1);
+}
+
+U0 FDCDMAPrepRead()
+{
+ OutU8(0x0A, 6); // mask ch 0 and 2
+ Sleep(1);
+ OutU8(0x0B, 0x56); // single xfer, addr inc, auto init, read, ch 2
+ Sleep(1);
+ OutU8(0x0A, 2); // unmask ch 0 and 2
+ Sleep(1);
+}
+
+interrupt U0 FDCIrqHandler() {
+ OutU8(0x20, 0x20); // EOI
+ FDCIrq = TRUE;
+}
+
+U16 fdc_base = 0x03F0;
+
+static U8 *fd_types[8] = {
+ "none",
+ "360kB 5.25\"",
+ "1.2MB 5.25\"",
+ "720kB 3.5\"",
+
+ "1.44MB 3.5\"",
+ "2.88MB 3.5\"",
+ "unknown type",
+ "unknown type"
+};
+
+U0 CMOSGetFloppyDrives()
+{
+ OutU8(0x70, 0x10);
+ Sleep(1);
+
+ U64 drives = InU8(0x71);
+
+ AdamLog("Floppy Drive 0: %s\n", fd_types[drives >> 4]);
+ AdamLog("Floppy Drive 1: %s\n", fd_types[drives & 0xF]);
+}
+
+U0 FDCSendCmd(U16 base, U8 cmd)
+{
+ // Send a command to the floppy controller
+
+ // 60 sec timeout
+ U64 i;
+ for (i = 0; i < 600; i++) {
+ Sleep(10);
+ if (0x80 & InU8(base + FDC_MSR_DSR)) {
+ OutU8(base + FDC_DATA, cmd);
+ Sleep(1);
+ return;
+ }
+ }
+ AdamErr("FDC Command TimeOut");
+}
+
+U8 FDCReadData(U16 base)
+{
+ // Read data from the floppy controller
+
+ // 60 sec timeout
+ U64 i;
+ for (i=0;i<600;i++) {
+ Sleep(10);
+ if (0x80 & InU8(base + FDC_MSR_DSR)) {
+ return InU8(base + FDC_DATA);
+ }
+ }
+ AdamErr("FDC Read TimeOut");
+}
+
+U0 FDCCheckInt(U16 base, U8 *st0, U8 *cyl)
+{
+ FDCSendCmd(base, FDC_SENSE_INTR);
+
+ *st0 = FDCReadData(base);
+ *cyl = FDCReadData(base);
+}
+
+I16 fdc_mtr_ticks = 0;
+U8 fdc_mtr_state = FDC_MOTOR_OFF;
+
+U0 FDCMotorOff(U16 base)
+{
+ OutU8(base + FDC_DOR, 0x0C);
+ fdc_mtr_state = FDC_MOTOR_OFF;
+}
+
+U0 FDCMotorPwrOffTimer()
+{
+ // You're supposed to run this function as a separate CTask. It will exit when the motor
+ // exits the "wait" state (either because it has turned off or because something needs it to be on).
+ // The driver only spawns this when the motor is moved from "on" to "wait".
+ while (fdc_mtr_state == FDC_MOTOR_WAIT) {
+ // Sanity check for if something wants the motor on at the last second
+ if (fdc_mtr_state == FDC_MOTOR_ON) break;
+
+ Sleep(500);
+
+ fdc_mtr_ticks -= 50;
+ if (fdc_mtr_ticks <= 0) {
+ FDCMotorOff(fdc_base);
+ }
+ Yield; // Give control back to the scheduler
+ }
+}
+
+U0 FDCMotorCtrl(U16 base, Bool onoff)
+{
+ U64 prev_mtr_state;
+ if (onoff) {
+ if (!fdc_mtr_state) {
+ // Turn on motor
+ OutU8(base + FDC_DOR, 0x1C);
+ Sleep(500); // Wait 500 ms to allow drive to spin up
+ }
+ fdc_mtr_state = FDC_MOTOR_ON;
+ } else {
+ prev_mtr_state = fdc_mtr_state;
+ if (fdc_mtr_state == FDC_MOTOR_WAIT) {
+ AdamLog("FDC: Motor PowerOff Already Pending\n");
+ }
+ fdc_mtr_ticks = 300; // 3 sec timeout before motor turns off
+ fdc_mtr_state = FDC_MOTOR_WAIT;
+ // Only spawn the timer task of the motor is currently on; infinitely-looping tasks peg the CPU
+ if (prev_mtr_state != FDC_MOTOR_WAIT) Spawn(&FDCMotorPwrOffTimer,,"FDCMotorPwrOffTimer");
+ }
+}
+
+I8 FDCRecalibrate(U16 base)
+{
+ FDCIrq = FALSE;
+
+ U64 i;
+ U8 st0, cyl;
+
+ FDCMotorCtrl(base, FDC_MOTOR_ON);
+
+ for (i=0;i<10;i++) {
+ FDCSendCmd(base, FDC_RECALIBRATE);
+ FDCSendCmd(base, 0);
+
+ // Wait for an interrupt, then get the status
+ while (!FDCIrq) Yield;
+ FDCCheckInt(base, &st0, &cyl);
+ AdamLog("ST0: %d Cyl: %d\n",st0,cyl);
+
+ if (st0 & 0xC0) {
+ static U8 * status[4] = {0, "error", "invalid", "drive"};
+ AdamLog("Calibration Status: %s\n", status[st0 >> 6]);
+ }
+
+ if (!cyl) {
+ FDCMotorCtrl(base, FDC_MOTOR_OFF);
+ return 0;
+ }
+ }
+
+ AdamErr("FDC ReCalibrate TimeOut");
+ FDCMotorCtrl(base, FDC_MOTOR_OFF);
+ return -1;
+}
+
+I8 FDCReset(U16 base)
+{
+ FDCIrq = FALSE;
+
+ OutU8(base + FDC_DOR, 0x00);
+ Sleep(1);
+ OutU8(base + FDC_DOR, 0x0C);
+ Sleep(1);
+
+ while (!FDCIrq) Yield;
+
+ // Ignore this
+ U64 i, lck;
+ U8 st0, cyl;
+ for (i=0;i<4;i++) {
+ FDCCheckInt(base, &st0, &cyl);
+ }
+
+ // Set xfer rate to 500kbps
+ OutU8(base + FDC_CCR_DIR, 0x00);
+ Sleep(1);
+
+ // Set the mechanical params and disable DMA (Terry didn't use it)
+ FDCSendCmd(base, FDC_SPECIFY);
+ FDCSendCmd(base, 0b10000000); // SRT = 8 (8 ms), HUT = 0 (256 ms)
+ FDCSendCmd(base, 0b00011110); // HLT = 15 (30 ms), NDMA = 0 (DMA enabled)
+
+ // Configure the FIFO
+ FDCSendCmd(base, FDC_CONFIGURE);
+ FDCSendCmd(base, 0x00); // 1st param is a 0
+ FDCSendCmd(base, 0b01011011); // 2nd param: Implied seek on, FIFO on, Drive polling disabled, threshold = 12
+ FDCSendCmd(base, 0x00); // 3rd param: write precomp = 0
+
+ // Lock the configuration
+ FDCSendCmd(base, 0x94);
+ lck = FDCReadData(base); // Result: lock status
+
+ // contingency
+ if (FDCRecalibrate(base)) return -1;
+
+ return 0;
+}
+
+I8 FDCSeek(U16 base, U8 cyli, U8 head)
+{
+ U64 i;
+ U8 st0, cyl;
+ FDCIrq = FALSE;
+
+ FDCMotorCtrl(base, FDC_MOTOR_ON);
+
+ for (i=0;i<10;i++) {
+ // Attempt to move to given cyl
+ // 1: X X X X X HD D1 D0
+ // 2: Cyl No
+ FDCSendCmd(base, FDC_SEEK);
+ FDCSendCmd(base, head<<2);
+ FDCSendCmd(base, cyli);
+
+ while (!FDCIrq) Yield;
+ FDCCheckInt(base, &st0, &cyl);
+ AdamLog("ST0: %d Cyl: %d\n",st0,cyl);
+
+ if (st0 & 0xC0) {
+ static U8 * status[4] = {0, "error", "invalid", "drive"};
+ AdamLog("Seek Status: %s\n", status[st0 >> 6]);
+ }
+
+ if (cyl == cyli) {
+ FDCMotorCtrl(base, FDC_MOTOR_OFF);
+ return 0;
+ }
+ }
+
+ AdamErr("FDC Seek TimeOut");
+ FDCMotorCtrl(base, FDC_MOTOR_OFF);
+ return -1;
+}
+
+U0 FDCRead(U16 base, U8 cyl, U8 head, U8 sect, U8 trklen)
+{
+ // Read data from disk (single-track)
+ static U8 flags;
+ flags = 0x40; // Multi-track off, MFM modulation
+ static U64 cmd;
+ cmd = FDC_READ_DATA | flags;
+ FDCIrq = FALSE;
+
+ U64 st0, st1, st2, rcyl, rhd, rsect, rsectsize;
+
+ FDCMotorCtrl(base, FDC_MOTOR_ON);
+
+ AdamLog("Cmd: %d\nParams: %d %d %d %d %d %d %d %d\n",cmd,head<<2,cyl,head,sect,2,trklen,0x1B,0xFF);
+
+ // Prepare the DMA controller
+ AdamLog("Preparing DMA\n");
+ FDCDMAInit(512*(trklen - sect + 1));
+ FDCDMAPrepRead();
+
+ FDCSendCmd(base, cmd);
+ FDCSendCmd(base, head << 2); // Drive 0, specified head
+ FDCSendCmd(base, cyl);
+ FDCSendCmd(base, head);
+ FDCSendCmd(base, sect);
+ FDCSendCmd(base, 2); // Sector size = 2 = 512 bytes
+ FDCSendCmd(base, trklen); // Track Length/Max Sector No.
+ FDCSendCmd(base, 0x1B); // GAP3 Length = 27 (3.5")
+ FDCSendCmd(base, 0xFF); // Data Length (irrelevant)
+
+ // Wait for xfer to complete
+ while (!FDCIrq) Yield;
+
+ st0 = FDCReadData(base);
+ st1 = FDCReadData(base);
+ st2 = FDCReadData(base);
+ rcyl = FDCReadData(base);
+ rhd = FDCReadData(base);
+ rsect = FDCReadData(base);
+ rsectsize = FDCReadData(base);
+
+ AdamLog("Read Results:\nST0: %d\nST1: %d\nST2: %d\nCyl: %d\nHead: %d\nSect: %d\nSect Size: %d\n",st0,st1,st2,rcyl,rhd,rsect,rsectsize);
+
+ FDCMotorCtrl(base, FDC_MOTOR_OFF);
+}
+
+
+U0 FDCReadMulti(U16 base, U8 cyl, U8 head, U8 sect, U8 trklen)
+{
+ // Read data from disk (multi-track)
+ static U8 flags;
+ flags = 0xC0; // Multi-track on, MFM modulation
+ static U64 cmd;
+ cmd = FDC_READ_DATA | flags;
+ FDCIrq = FALSE;
+
+ U64 st0, st1, st2, rcyl, rhd, rsect, rsectsize;
+
+ FDCMotorCtrl(base, FDC_MOTOR_ON);
+
+ AdamLog("Cmd: %d\nParams: %d %d %d %d %d %d %d %d\n",cmd,head<<2,cyl,head,sect,2,trklen,0x1B,0xFF);
+
+ // Prepare the DMA controller
+ AdamLog("Preparing DMA\n");
+ FDCDMAInit(512*(trklen - sect + 1)*2);
+ FDCDMAPrepRead();
+
+ FDCSendCmd(base, cmd);
+ FDCSendCmd(base, head << 2); // Drive 0, specified head
+ FDCSendCmd(base, cyl);
+ FDCSendCmd(base, head);
+ FDCSendCmd(base, sect);
+ FDCSendCmd(base, 2); // Sector size = 2 = 512 bytes
+ FDCSendCmd(base, trklen); // Track Length/Max Sector No.
+ FDCSendCmd(base, 0x1B); // GAP3 Length = 27 (3.5")
+ FDCSendCmd(base, 0xFF); // Data Length (irrelevant)
+
+ // Wait for the xfer to complete
+ while (!FDCIrq) Yield;
+
+ st0 = FDCReadData(base);
+ st1 = FDCReadData(base);
+ st2 = FDCReadData(base);
+ rcyl = FDCReadData(base);
+ rhd = FDCReadData(base);
+ rsect = FDCReadData(base);
+ rsectsize = FDCReadData(base);
+
+ AdamLog("Read Results:\nST0: %d\nST1: %d\nST2: %d\nCyl: %d\nHead: %d\nSect: %d\nSect Size: %d\n",st0,st1,st2,rcyl,rhd,rsect,rsectsize);
+
+ FDCMotorCtrl(base, FDC_MOTOR_OFF);
+}
+
+U0 FDCWrite(U16 base, U8 cyl, U8 head, U8 sect, U8 trklen)
+{
+ // Write data to disk (single-track)
+ static U8 flags;
+ flags = 0x40; // Multi-track off, MFM modulation
+ static U64 cmd;
+ cmd = FDC_WRITE_DATA | flags;
+ FDCIrq = FALSE;
+
+ U64 st0, st1, st2, rcyl, rhd, rsect, rsectsize;
+
+ FDCMotorCtrl(base, FDC_MOTOR_ON);
+
+ AdamLog("Cmd: %d\nParams: %d %d %d %d %d %d %d %d\n",cmd,head<<2,cyl,head,sect,2,trklen,0x1B,0xFF);
+
+ // Prepare the DMA controller
+ AdamLog("Preparing DMA\n");
+ FDCDMAInit(512*(trklen - sect + 1));
+ FDCDMAPrepWrite();
+
+ FDCSendCmd(base, cmd);
+ FDCSendCmd(base, head << 2); // Drive 0, specified head
+ FDCSendCmd(base, cyl);
+ FDCSendCmd(base, head);
+ FDCSendCmd(base, sect);
+ FDCSendCmd(base, 2); // Sector size = 2 = 512 bytes
+ FDCSendCmd(base, trklen); // Track Length/Max Sector No.
+ FDCSendCmd(base, 0x1B); // GAP3 Length = 27 (3.5")
+ FDCSendCmd(base, 0xFF); // Data Length (irrelevant)
+
+ // Wait for xfer to complete
+ while (!FDCIrq) Yield;
+
+ st0 = FDCReadData(base);
+ st1 = FDCReadData(base);
+ st2 = FDCReadData(base);
+ rcyl = FDCReadData(base);
+ rhd = FDCReadData(base);
+ rsect = FDCReadData(base);
+ rsectsize = FDCReadData(base);
+
+ AdamLog("Read Results:\nST0: %d\nST1: %d\nST2: %d\nCyl: %d\nHead: %d\nSect: %d\nSect Size: %d\n",st0,st1,st2,rcyl,rhd,rsect,rsectsize);
+
+ FDCMotorCtrl(base, FDC_MOTOR_OFF);
+}
+
+
+U0 FDCWriteMulti(U16 base, U8 cyl, U8 head, U8 sect, U8 trklen)
+{
+ // Write data to disk (multi-track)
+ static U8 flags;
+ flags = 0xC0; // Multi-track on, MFM modulation
+ static U64 cmd;
+ cmd = FDC_WRITE_DATA | flags;
+ FDCIrq = FALSE;
+
+ U64 st0, st1, st2, rcyl, rhd, rsect, rsectsize;
+
+ FDCMotorCtrl(base, FDC_MOTOR_ON);
+
+ AdamLog("Cmd: %d\nParams: %d %d %d %d %d %d %d %d\n",cmd,head<<2,cyl,head,sect,2,trklen,0x1B,0xFF);
+
+ // Prepare the DMA controller
+ AdamLog("Preparing DMA\n");
+ FDCDMAInit(512*(trklen - sect + 1)*2);
+ FDCDMAPrepRead();
+
+ FDCSendCmd(base, cmd);
+ FDCSendCmd(base, head << 2); // Drive 0, specified head
+ FDCSendCmd(base, cyl);
+ FDCSendCmd(base, head);
+ FDCSendCmd(base, sect);
+ FDCSendCmd(base, 2); // Sector size = 2 = 512 bytes
+ FDCSendCmd(base, trklen); // Track Length/Max Sector No.
+ FDCSendCmd(base, 0x1B); // GAP3 Length = 27 (3.5")
+ FDCSendCmd(base, 0xFF); // Data Length (irrelevant)
+
+ // Wait for the xfer to complete
+ while (!FDCIrq) Yield;
+
+ st0 = FDCReadData(base);
+ st1 = FDCReadData(base);
+ st2 = FDCReadData(base);
+ rcyl = FDCReadData(base);
+ rhd = FDCReadData(base);
+ rsect = FDCReadData(base);
+ rsectsize = FDCReadData(base);
+
+ AdamLog("Read Results:\nST0: %d\nST1: %d\nST2: %d\nCyl: %d\nHead: %d\nSect: %d\nSect Size: %d\n",st0,st1,st2,rcyl,rhd,rsect,rsectsize);
+
+ FDCMotorCtrl(base, FDC_MOTOR_OFF);
+} \ No newline at end of file
diff --git a/ReadMe.TXT b/ReadMe.TXT
new file mode 100644
index 0000000..9e2970a
--- /dev/null
+++ b/ReadMe.TXT
@@ -0,0 +1,27 @@
+These files contain the code required for the low-level floppy disk driver.
+Currently, there is no block device code that implements this driver.
+
+System source files from my system are included as a reference.
+
+To install the driver:
+1. Copy Floppy.HC and Floppy.HH to the Kernel directory
+2. Copy the headers at the bottom of the provided KernelC.HC into *your* KernelC.
+3. Add "U8 FDC_DMA[0x4800];" to the bottom of KStart32.HC; This is the DMA buffer for the floppy disk (yeah, I know, DMA = blasphemy, but it's more reliable than PIO while being just as simple).
+4. Add Floppy.HC and Floppy.HH to Kernel.PRJ so that they will be compiled into the kernel.
+
+On startup, you will have to unmask IRQ6 and point its int to the IRQ handler, FDCIrqHandler.
+To do this, write 0xB8 to port 0x21, then use IntEntrySet to set the vector for the aforementioned int.
+In HolyC, that would be:
+OutU8(0x21,0xB8);
+IntEntrySet(0x26,&FDCIrqHandler,IDTET_IRQ);
+
+Use FDCReset to initialize the drive (make sure a disk is inserted; it does not test for one before doing things)
+
+FDCSeek does what it says.
+
+FDCRead/FDCReadMulti will read data from the disk.
+FDCWrite/FDCWriteMulti will write data to the disk.
+Data that has been read or is to be written goes in FDC_DMA.
+(The FDC*Multi funs use multi-track mode; data will be read from both heads)
+
+The result of seeks, recalibrations, and data xfers will be displayed in the Adam Task.