Initial (manual) import
This commit is contained in:
1 parent
f39611c506
commit
895fe109de
661 files changed
+245862
No files matched your search
@@ -0,0 +1,188 @@
|
||||
#define BOOT_HIGH_LOC_DVD ((BOOT_RAM_LIMIT-\
|
||||
(BOOT_STK_SIZE+DVD_BOOT_LOADER_SIZE))>>4)
|
||||
|
||||
DefinePrint(
|
||||
"DD_BOOT_HIGH_LOC_DVD","%08X",BOOT_HIGH_LOC_DVD<<4);
|
||||
DefinePrint(
|
||||
"DD_BOOT_HIGH_LOC_DVD_END","%08X",BOOT_RAM_LIMIT-1);
|
||||
|
||||
asm {
|
||||
USE16
|
||||
BDVD_START::
|
||||
//DL is supposed to have the BIOS drive number
|
||||
CLD
|
||||
MOV AX,BOOT_HIGH_LOC_DVD
|
||||
MOV ES,AX
|
||||
|
||||
CLI
|
||||
MOV SS,AX
|
||||
MOV SP,BOOT_STK_SIZE+DVD_BOOT_LOADER_SIZE
|
||||
STI
|
||||
|
||||
CALL BDVD_GET_RIP
|
||||
BDVD_GET_RIP:
|
||||
POP BX
|
||||
SUB BX,BDVD_GET_RIP-BDVD_START
|
||||
SHR BX,4
|
||||
//This copies this bootloader's code to 0x$TX,"00096600",D="DD_BOOT_HIGH_LOC_DVD"$
|
||||
MOV AX,CS
|
||||
ADD AX,BX
|
||||
MOV DS,AX
|
||||
MOV CX,DVD_BOOT_LOADER_SIZE
|
||||
XOR SI,SI
|
||||
XOR DI,DI
|
||||
REP_MOVSB
|
||||
|
||||
MOV AX,BOOT_HIGH_LOC_DVD
|
||||
MOV DS,AX
|
||||
|
||||
//My assembler doesn't support 16-bit very well.
|
||||
DU8 0xEA; //JMP BOOT_HIGH_LOC_DVD:BDVD_MAIN
|
||||
DU16 BDVD_MAIN-BDVD_START,BOOT_HIGH_LOC_DVD;
|
||||
|
||||
BDVD_BIOS_DRV_NUM: DU8 0;
|
||||
BDVD_PAGE: DU8 0;
|
||||
|
||||
BDVD_DAP: DU8 16,0,1,0; //One blk at a time
|
||||
BDVD_DAP_BUF: DU16 0,0;
|
||||
BDVD_DAP_BLK: DU64 0;
|
||||
|
||||
BDVD_TEMPLEOS_MSG:
|
||||
DU8 "Loading TempleOS",0;
|
||||
|
||||
BDVD_NOT64_MSG:
|
||||
DU8 "TempleOS requires a 64-bit capable processor.\n\r",0;
|
||||
|
||||
//These get patched.
|
||||
BDVD_BLK_LO:: DU16 0;
|
||||
BDVD_BLK_HI:: DU16 0;
|
||||
BDVD_BLK_CNT:: DU16 0;
|
||||
BDVD_SHIFT_BLKS:: DU16 0;
|
||||
BDVD_PROGRESS_STEP:: DU32 0;
|
||||
BDVD_PROGRESS_VAL:: DU32 0;
|
||||
|
||||
BDVD_PUT_CHAR::
|
||||
MOV AH,0xE
|
||||
MOV BL,7 //Might be foreground color on some BIOS's
|
||||
MOV BH,U8 [BDVD_PAGE-BDVD_START]
|
||||
INT 0x10
|
||||
BDVD_RET::
|
||||
RET
|
||||
BDVD_PUTS::
|
||||
@@1: LODSB
|
||||
TEST AL,AL
|
||||
JZ BDVD_RET
|
||||
CALL BDVD_PUT_CHAR
|
||||
JMP @@1
|
||||
|
||||
BDVD_MAIN::
|
||||
MOV U8 [BDVD_BIOS_DRV_NUM-BDVD_START],DL //Passed in by BIOS
|
||||
|
||||
MOV AH,0xF
|
||||
INT 0x10
|
||||
MOV U8 [BDVD_PAGE-BDVD_START],BH //Video page
|
||||
|
||||
MOV EAX,0x80000000
|
||||
CPUID
|
||||
CMP EAX,0x80000001
|
||||
JB @@05
|
||||
|
||||
MOV EAX,0x80000001
|
||||
CPUID
|
||||
BT EDX,29
|
||||
JC @@15
|
||||
@@05: MOV SI,BDVD_NOT64_MSG-BDVD_START
|
||||
CALL BDVD_PUTS
|
||||
@@10: JMP @@10
|
||||
|
||||
@@15: MOV SI,BDVD_TEMPLEOS_MSG-BDVD_START
|
||||
CALL BDVD_PUTS
|
||||
|
||||
MOV AX,BOOT_RAM_BASE/16
|
||||
MOV ES,AX
|
||||
XOR ECX,ECX
|
||||
MOV CX,U16 [BDVD_BLK_CNT-BDVD_START]
|
||||
|
||||
MOV EAX,(80-7-9)*65536 //80 columns
|
||||
XOR EDX,EDX
|
||||
DIV ECX
|
||||
MOV U32 [BDVD_PROGRESS_STEP-BDVD_START],EAX
|
||||
MOV U32 [BDVD_PROGRESS_VAL-BDVD_START],0
|
||||
|
||||
MOV AX,U16 [BDVD_BLK_LO-BDVD_START]
|
||||
MOV DX,U16 [BDVD_BLK_HI-BDVD_START]
|
||||
|
||||
@@20: PUSH CX //Blk cnt
|
||||
|
||||
//READ BLK
|
||||
PUSH AX //Blk lo
|
||||
PUSH DX //Blk hi
|
||||
PUSH ES //Buf seg
|
||||
MOV U16 [BDVD_DAP_BLK-BDVD_START],AX
|
||||
MOV U16 [BDVD_DAP_BLK+2-BDVD_START],DX
|
||||
MOV AX,ES
|
||||
MOV U16 [BDVD_DAP_BUF+2-BDVD_START],AX //ES:0000
|
||||
MOV SI,BDVD_DAP-BDVD_START //DS:SI=DAP
|
||||
MOV AH,0x42
|
||||
MOV DL,U8 [BDVD_BIOS_DRV_NUM-BDVD_START]
|
||||
INT 0x13
|
||||
|
||||
POP AX //ES
|
||||
ADD AX,DVD_BLK_SIZE/16
|
||||
MOV ES,AX
|
||||
POP DX
|
||||
POP AX
|
||||
INC AX
|
||||
JNZ @@25
|
||||
INC DX
|
||||
|
||||
@@25: PUSH AX
|
||||
MOV BX,U16 [BDVD_PROGRESS_VAL+2-BDVD_START]
|
||||
MOV EAX,U32 [BDVD_PROGRESS_STEP-BDVD_START]
|
||||
ADD U32 [BDVD_PROGRESS_VAL-BDVD_START],EAX
|
||||
CMP U16 [BDVD_PROGRESS_VAL+2-BDVD_START],BX
|
||||
JE @@30
|
||||
MOV AL,'.'
|
||||
CALL BDVD_PUT_CHAR
|
||||
@@30: POP AX
|
||||
|
||||
POP CX
|
||||
LOOP @@20
|
||||
|
||||
//Shift backward to align
|
||||
PUSH DS
|
||||
MOV BX,U16 [BDVD_SHIFT_BLKS-BDVD_START]
|
||||
SHL BX,BLK_SIZE_BITS-4
|
||||
MOV CX,U16 [BDVD_BLK_CNT-BDVD_START]
|
||||
MOV AX,BOOT_RAM_BASE/16
|
||||
MOV ES,AX
|
||||
ADD AX,BX
|
||||
MOV DS,AX
|
||||
@@35: PUSH CX
|
||||
XOR SI,SI
|
||||
XOR DI,DI
|
||||
MOV CX,DVD_BLK_SIZE/4
|
||||
REP_MOVSD
|
||||
MOV AX,DS
|
||||
ADD AX,DVD_BLK_SIZE/16
|
||||
MOV DS,AX
|
||||
MOV AX,ES
|
||||
ADD AX,DVD_BLK_SIZE/16
|
||||
MOV ES,AX
|
||||
POP CX
|
||||
LOOP @@35
|
||||
POP DS
|
||||
|
||||
//See $LK,"BootDVDProbe",A="MN:BootDVDProbe"$().
|
||||
MOV EBX,U32 [BDVD_BLK_LO-BDVD_START]
|
||||
MOV AX,U16 [BDVD_SHIFT_BLKS-BDVD_START]
|
||||
SHL EAX,16
|
||||
MOV AX,BOOT_SRC_DVD //$MA-X+PU,"See sys_boot_src",LM="Find(\"sys_boot_src\",\"/*\");View;\n"$
|
||||
|
||||
//My assembler doesn't support 16-bit very well.
|
||||
DU8 0xEA; //JMP BOOT_RAM_BASE:0000
|
||||
DU16 0,BOOT_RAM_BASE/16;
|
||||
//Continues here $LK,"::/Kernel/KStart16.HC",A="FL:::/Kernel/KStart16.HC,1"$
|
||||
BDVD_END::
|
||||
#assert BDVD_END-BDVD_START<DVD_BOOT_LOADER_SIZE
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
//See $LK,"Install Documentation",A="FI:::/Doc/Install.DD"$ or $LK,"Upgrading Documentation",A="FI:::/Doc/Upgrade.DD"$.
|
||||
//Study my account examples: $LK,"Cfg Strs",A="FL:::/Demo/AcctExample/TOS/TOSCfg.HC,1"$, $LK,"Update Funs",A="FL:::/Demo/AcctExample/TOS/TOSDistro.HC,1"$
|
||||
|
||||
#include "BootDVD"
|
||||
#include "DskISORedSea"
|
||||
#include "DskISO9660"
|
||||
|
||||
#help_index "Install"
|
||||
|
||||
#define KERNEL_BIN_C "Kernel.BIN.C"
|
||||
#define BOOT_DIR "/0000Boot"
|
||||
#define BOOT_DIR_KERNEL_BIN_C BOOT_DIR "/0000" KERNEL_BIN_C
|
||||
|
||||
U0 MakeAll()
|
||||
{
|
||||
if (Cmp("/Compiler/Compiler","Compiler",,':'))
|
||||
throw;
|
||||
if (Cmp("/Kernel/Kernel","Kernel",,':'))
|
||||
throw;
|
||||
}
|
||||
|
||||
public U0 BootDVDIns(U8 drv_let=0)
|
||||
{//See $LK,"::/Misc/DoDistro.HC"$.
|
||||
try {
|
||||
if (!Drv(drv_let))
|
||||
throw;
|
||||
MakeAll;
|
||||
Move("/Kernel/Kernel.BIN.Z",BOOT_DIR_KERNEL_BIN_C);
|
||||
} catch {
|
||||
PutExcept;
|
||||
Beep;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
#define MODULE_SIZE 1*BLK_SIZE
|
||||
#define BOOT_HIGH_LOC_HD ((BOOT_RAM_LIMIT-\
|
||||
(BOOT_STK_SIZE+MODULE_SIZE))>>4)
|
||||
|
||||
DefinePrint(
|
||||
"DD_BOOT_HIGH_LOC_HD","%08X",BOOT_HIGH_LOC_HD<<4);
|
||||
|
||||
asm {
|
||||
USE16
|
||||
BHD_CODE::
|
||||
|
||||
#define BHD_START (BHD_CODE-offset(CFAT32Boot.code))
|
||||
|
||||
CLD
|
||||
|
||||
MOV AX,BOOT_HIGH_LOC_HD
|
||||
MOV ES,AX
|
||||
|
||||
CLI
|
||||
MOV SS,AX
|
||||
MOV SP,BOOT_STK_SIZE+MODULE_SIZE
|
||||
STI
|
||||
|
||||
CALL BHD_GET_RIP
|
||||
BHD_GET_RIP:
|
||||
POP BX
|
||||
SUB BX,BHD_GET_RIP-BHD_START
|
||||
SHR BX,4
|
||||
//This copies this bootloader's code to 0x$TX,"00096C00",D="DD_BOOT_HIGH_LOC_HD"$
|
||||
MOV AX,CS
|
||||
ADD AX,BX
|
||||
MOV DS,AX
|
||||
MOV CX,MODULE_SIZE
|
||||
XOR SI,SI
|
||||
XOR DI,DI
|
||||
REP_MOVSB
|
||||
|
||||
MOV AX,BOOT_HIGH_LOC_HD
|
||||
MOV DS,AX
|
||||
|
||||
//My assembler doesn't support 16-bit very well.
|
||||
DU8 0xEA; //JMP BOOT_HIGH_LOC_HD:BHD_HISTART
|
||||
DU16 BHD_HISTART-BHD_START,BOOT_HIGH_LOC_HD;
|
||||
|
||||
BHD_BIOS_DRV_NUM: DU8 0;
|
||||
|
||||
//Gets patched by $LK,"BootHDIns",A="MN:BootHDIns"$().
|
||||
BHD_BLK_CNT:: DU16 0;
|
||||
|
||||
BHD_DAP: DU8 16,0,1,0; //One blk at a time
|
||||
BHD_DAP_BUF: DU16 0,0;
|
||||
//Gets patched by $LK,"BootHDIns",A="MN:BootHDIns"$().
|
||||
BHD_DAP_BLK:: //64-bit
|
||||
BHD_DAP_BLK_LO: DU32 0;
|
||||
BHD_DAP_BLK_HI: DU32 0;
|
||||
|
||||
BHD_HISTART:
|
||||
MOV U8 [BHD_BIOS_DRV_NUM-BHD_START],DL //Passed in by BIOS
|
||||
MOV AX,BOOT_RAM_BASE/16
|
||||
MOV ES,AX
|
||||
XOR ECX,ECX
|
||||
MOV CX,U16 [BHD_BLK_CNT-BHD_START]
|
||||
|
||||
@@05: PUSH CX //Blk cnt
|
||||
|
||||
//READ BLK
|
||||
PUSH ES //Buf seg
|
||||
MOV AX,ES
|
||||
MOV U16 [BHD_DAP_BUF+2-BHD_START],AX //ES:0000
|
||||
MOV SI,BHD_DAP-BHD_START //DS:SI=DAP
|
||||
MOV AH,0x42
|
||||
MOV DL,U8 [BHD_BIOS_DRV_NUM-BHD_START]
|
||||
INT 0x13
|
||||
|
||||
POP AX //ES
|
||||
ADD AX,BLK_SIZE/16
|
||||
MOV ES,AX
|
||||
INC U32 [BHD_DAP_BLK_LO-BHD_START]
|
||||
JNZ @@10
|
||||
INC U32 [BHD_DAP_BLK_HI-BHD_START]
|
||||
|
||||
@@10: POP CX
|
||||
LOOP @@05
|
||||
|
||||
XOR EBX,EBX
|
||||
MOV EAX,BOOT_SRC_HARDDRV //$MA-X+PU,"See sys_boot_src",LM="Find(\"sys_boot_src\",\"/*\");View;\n"$
|
||||
//My assembler doesn't support 16-bit very well.
|
||||
DU8 0xEA; //JMP BOOT_RAM_BASE:0000
|
||||
DU16 0,BOOT_RAM_BASE/16;
|
||||
//Continues here $LK,"::/Kernel/KStart16.HC",A="FL:::/Kernel/KStart16.HC,1"$
|
||||
BHD_END::
|
||||
#assert BHD_END-BHD_START<MODULE_SIZE-2
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
//See $LK,"Install Documentation",A="FI:::/Doc/Install.DD"$ or $LK,"Upgrading Documentation",A="FI:::/Doc/Upgrade.DD"$.
|
||||
//Study my account examples: $LK,"Cfg Strs",A="FL:::/Demo/AcctExample/TOS/TOSCfg.HC,1"$, $LK,"Update Funs",A="FL:::/Demo/AcctExample/TOS/TOSDistro.HC,1"$
|
||||
|
||||
#include "BootHD"
|
||||
|
||||
#help_index "Install"
|
||||
|
||||
#define KERNEL_BIN_C "Kernel.BIN.C"
|
||||
|
||||
U0 MakeAll()
|
||||
{
|
||||
if (Cmp("/Compiler/Compiler","Compiler",,':'))
|
||||
throw;
|
||||
if (Cmp("/Kernel/Kernel","Kernel",,':'))
|
||||
throw;
|
||||
}
|
||||
|
||||
public U0 BootHDIns(U8 drv_let=0)
|
||||
{//$LK,"MakeAll",A="MN:MakeAll"$ and install new boot-loader.
|
||||
CDrv *dv;
|
||||
CFAT32Boot br;
|
||||
CDirEntry de;
|
||||
I64 i;
|
||||
try {
|
||||
if (!Drv(drv_let))
|
||||
throw;
|
||||
dv=Fs->cur_dv;
|
||||
MakeAll;
|
||||
switch (Let2BlkDevType(dv->drv_let)) {
|
||||
case BDT_RAM:
|
||||
case BDT_ATA:
|
||||
Move("/Kernel/Kernel.BIN.Z","/" KERNEL_BIN_C);
|
||||
if (!FileFind("/" KERNEL_BIN_C,&de,FUF_JUST_FILES))
|
||||
"No Kernel.BIN.C\n";
|
||||
else {
|
||||
Free(de.full_name);
|
||||
"Modifying partition boot record.\n";
|
||||
RBlks(dv,&br,dv->drv_offset,1);
|
||||
br.jump_and_nop[0]=OC_JMP_REL8;
|
||||
br.jump_and_nop[1]=offset(CFAT32Boot.code)-2;
|
||||
#assert offset(CFAT32Boot.code)>=offset(CRedSeaBoot.code)
|
||||
br.jump_and_nop[2]=OC_NOP;
|
||||
*BHD_BLK_CNT(U16 *)=(de.size+BLK_SIZE-1)>>BLK_SIZE_BITS;
|
||||
*BHD_DAP_BLK(I64 *)=Cluster2Blk(dv,de.cluster);
|
||||
for (i=0;i<BHD_END-BHD_CODE;i++)
|
||||
br.code[i]=BHD_CODE(U8 *)[i];
|
||||
#assert sizeof(CFAT32Boot.code)>=BHD_END-BHD_CODE
|
||||
for (;i<sizeof(CFAT32Boot.code);i++)
|
||||
br.code[i]=0;
|
||||
WBlks(dv,&br,dv->drv_offset,1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw;
|
||||
}
|
||||
} catch {
|
||||
PutExcept;
|
||||
Beep;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
#define MODULE_SIZE 1*BLK_SIZE
|
||||
#define BOOT_HIGH_LOC_MHD ((BOOT_RAM_LIMIT-\
|
||||
(BOOT_STK_SIZE+MODULE_SIZE))>>4)
|
||||
|
||||
DefinePrint(
|
||||
"DD_BOOT_HIGH_LOC_MHD","%08X",BOOT_HIGH_LOC_MHD<<4);
|
||||
|
||||
asm {
|
||||
USE16
|
||||
BMHD_START::
|
||||
BMHD_CODE::
|
||||
CLD
|
||||
|
||||
MOV AX,BOOT_HIGH_LOC_MHD
|
||||
|
||||
CLI
|
||||
MOV SS,AX
|
||||
MOV SP,BOOT_STK_SIZE+MODULE_SIZE
|
||||
STI
|
||||
|
||||
PUSHFW
|
||||
PUSH DS
|
||||
PUSH ES
|
||||
PUSH FS
|
||||
PUSH GS
|
||||
PUSH ECX
|
||||
PUSH EBX
|
||||
PUSH EDX
|
||||
PUSH EBP
|
||||
|
||||
MOV ES,AX
|
||||
|
||||
CALL BMHD_GET_RIP
|
||||
BMHD_GET_RIP:
|
||||
POP BX
|
||||
SUB BX,BMHD_GET_RIP-BMHD_START
|
||||
MOV CX,BX
|
||||
SHR BX,4
|
||||
//This copies this bootloader's code to 0x$TX,"00096C00",D="DD_BOOT_HIGH_LOC_MHD"$
|
||||
MOV AX,CS
|
||||
PUSH AX
|
||||
ADD AX,BX
|
||||
MOV DS,AX
|
||||
MOV U16 [BMHD_OLD_CS_RIP-BMHD_START],CX
|
||||
POP U16 [BMHD_OLD_CS_RIP+2-BMHD_START]
|
||||
|
||||
MOV CX,MODULE_SIZE
|
||||
XOR SI,SI
|
||||
XOR DI,DI
|
||||
REP_MOVSB
|
||||
|
||||
MOV AX,BOOT_HIGH_LOC_MHD
|
||||
MOV DS,AX
|
||||
|
||||
//My assembler doesn't support 16-bit very well.
|
||||
DU8 0xEA; //JMP BOOT_HIGH_LOC_MHD:BMHD_HISTART
|
||||
DU16 BMHD_HISTART-BMHD_START,BOOT_HIGH_LOC_MHD;
|
||||
|
||||
BMHD_BIOS_DRV_NUM: DU8 0;
|
||||
BMHD_OLD_CS_RIP: DU16 0,0;
|
||||
//Gets patched by $LK,"BootHDIns",A="MN:BootHDIns"$().
|
||||
BMHD_BLK_CNT:: DU16 0;
|
||||
|
||||
BMHD_DAP: DU8 16,0,1,0; //One blk at a time
|
||||
BMHD_DAP_BUF: DU16 0,0;
|
||||
//Gets patched by $LK,"BootHDIns",A="MN:BootHDIns"$().
|
||||
BMHD_DAP_BLK:: //64-bit
|
||||
BMHD_DAP_BLK_LO: DU32 0;
|
||||
BMHD_DAP_BLK_HI: DU32 0;
|
||||
|
||||
BMHD_HISTART:
|
||||
MOV U8 [BMHD_BIOS_DRV_NUM-BMHD_START],DL //Passed in by BIOS
|
||||
MOV AX,BOOT_RAM_BASE/16
|
||||
MOV ES,AX
|
||||
XOR ECX,ECX
|
||||
MOV CX,U16 [BMHD_BLK_CNT-BMHD_START]
|
||||
|
||||
@@05: PUSH CX //Blk cnt
|
||||
|
||||
//READ BLK
|
||||
PUSH ES //Buf seg
|
||||
MOV AX,ES
|
||||
MOV U16 [BMHD_DAP_BUF+2-BMHD_START],AX //ES:0000
|
||||
MOV SI,BMHD_DAP-BMHD_START //DS:SI=DAP
|
||||
MOV AH,0x42
|
||||
MOV DL,U8 [BMHD_BIOS_DRV_NUM-BMHD_START]
|
||||
INT 0x13
|
||||
|
||||
POP AX //ES
|
||||
ADD AX,BLK_SIZE/16
|
||||
MOV ES,AX
|
||||
INC U32 [BMHD_DAP_BLK_LO-BMHD_START]
|
||||
JNZ @@10
|
||||
INC U32 [BMHD_DAP_BLK_HI-BMHD_START]
|
||||
|
||||
@@10: POP CX
|
||||
LOOP @@05
|
||||
|
||||
MOV DL,U8 [BMHD_BIOS_DRV_NUM-BMHD_START]
|
||||
MOV EBX,U32 [BMHD_OLD_CS_RIP-BMHD_START]
|
||||
//My assembler doesn't support 16-bit very well.
|
||||
DU8 0xEA; //JMP BOOT_RAM_BASE:0000
|
||||
DU16 0,BOOT_RAM_BASE/16;
|
||||
//Continues here $LK,"BMHD2_START",A="FF:::/Adam/Opt/Boot/BootMHD2.HC,BMHD2_START"$
|
||||
BMHD_END::
|
||||
#assert BMHD_END-BMHD_START<=440
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
#define MODULE_SIZE 2*BLK_SIZE
|
||||
#define BOOT_HIGH_LOC_MHD2 ((BOOT_RAM_LIMIT-\
|
||||
(BOOT_STK_SIZE+MODULE_SIZE))>>4)
|
||||
|
||||
DefinePrint(
|
||||
"DD_BOOT_HIGH_LOC_MHD2","%08X",BOOT_HIGH_LOC_MHD2<<4);
|
||||
|
||||
asm {
|
||||
USE16
|
||||
BMHD2_START::
|
||||
MOV U32 FS:[0],'B'+0x2000+('2'+0x2000)<<16
|
||||
|
||||
MOV AX,BOOT_HIGH_LOC_MHD2
|
||||
MOV ES,AX
|
||||
//This copies this bootloader's code to 0x$TX,"00096A00",D="DD_BOOT_HIGH_LOC_MHD2"$
|
||||
MOV AX,CS
|
||||
MOV DS,AX
|
||||
MOV U32 [BMHD2_OLD_CS_RIP-BMHD2_START],EBX
|
||||
MOV U8 [BMHD2_BIOS_DRV_NUM-BMHD2_START],DL
|
||||
|
||||
MOV CX,MODULE_SIZE
|
||||
XOR SI,SI
|
||||
XOR DI,DI
|
||||
REP_MOVSB
|
||||
|
||||
MOV AX,BOOT_HIGH_LOC_MHD2
|
||||
MOV DS,AX
|
||||
|
||||
//My assembler doesn't support 16-bit very well.
|
||||
DU8 0xEA; //JMP BOOT_HIGH_LOC_MHD2:BMHD2_HISTART
|
||||
DU16 BMHD2_HISTART-BMHD2_START,BOOT_HIGH_LOC_MHD2;
|
||||
|
||||
BMHD2_BOOT_MSG::
|
||||
DU8 256 DUP(0);
|
||||
|
||||
BMHD2_BIOS_DRV_NUM: DU8 0;
|
||||
BMHD2_PAGE: DU8 0;
|
||||
BMHD2_BLK_ARRAY:: DU64 8 DUP(0);
|
||||
|
||||
BMHD2_DAP: DU8 16,0,1,0; //One blk at a time
|
||||
BMHD2_DAP_BUF: DU16 0,0;
|
||||
BMHD2_DAP_BLK:: //64-bit
|
||||
BMHD2_DAP_BLK_LO: DU32 0;
|
||||
BMHD2_DAP_BLK_HI: DU32 0;
|
||||
|
||||
BMHD2_PUT_CHAR::
|
||||
MOV AH,0xE
|
||||
MOV BL,7 //Might be foreground color on some BIOS's
|
||||
MOV BH,U8 [BMHD2_PAGE-BMHD2_START]
|
||||
INT 0x10
|
||||
BMHD2_RET::
|
||||
RET
|
||||
BMHD2_PUTS::
|
||||
@@1: LODSB
|
||||
TEST AL,AL
|
||||
JZ BMHD2_RET
|
||||
CALL BMHD2_PUT_CHAR
|
||||
JMP @@1
|
||||
|
||||
BMHD2_GETCHAR:
|
||||
XOR AH,AH
|
||||
INT 0x16
|
||||
PUSH AX
|
||||
MOV AH,0x0E
|
||||
MOV BX,0x07
|
||||
INT 0x10
|
||||
POP AX
|
||||
RET
|
||||
|
||||
BMHD2_HISTART:
|
||||
MOV AH,0xF
|
||||
INT 0x10
|
||||
MOV U8 [BMHD2_PAGE-BMHD2_START],BH //Video page
|
||||
|
||||
MOV U32 FS:[0],0
|
||||
@@5: MOV SI,BMHD2_BOOT_MSG-BMHD2_START
|
||||
CALL BMHD2_PUTS
|
||||
CALL BMHD2_GETCHAR
|
||||
CMP AL,'0'
|
||||
JB @@5
|
||||
CMP AL,'8'
|
||||
JAE @@5
|
||||
AND EAX,7
|
||||
|
||||
MOV EBX,U32 BMHD2_BLK_ARRAY-BMHD2_START[EAX*8]
|
||||
MOV EAX,U32 BMHD2_BLK_ARRAY+4-BMHD2_START[EAX*8]
|
||||
|
||||
TEST EBX,EBX
|
||||
JNZ @@10
|
||||
TEST EAX,EAX
|
||||
JZ @@5
|
||||
|
||||
@@10: MOV U32 [BMHD2_DAP_BLK_LO-BMHD2_START],EBX
|
||||
MOV U32 [BMHD2_DAP_BLK_HI-BMHD2_START],EAX
|
||||
|
||||
MOV AX,U16 [BMHD2_OLD_CS_RIP-BMHD2_START]
|
||||
SHR AX,4
|
||||
ADD AX,U16 [BMHD2_OLD_CS_RIP+2-BMHD2_START]
|
||||
MOV U16 [BMHD2_DAP_BUF+2-BMHD2_START],AX //ES:0000
|
||||
MOV SI,BMHD2_DAP-BMHD2_START //DS:SI=DAP
|
||||
MOV DL,U8 [BMHD2_BIOS_DRV_NUM-BMHD2_START]
|
||||
MOV AH,0x42
|
||||
INT 0x13
|
||||
|
||||
POP EBP
|
||||
POP EDX
|
||||
POP EBX
|
||||
POP ECX
|
||||
XOR EAX,EAX
|
||||
POP GS
|
||||
POP FS
|
||||
POP ES
|
||||
POP DS
|
||||
POPFW
|
||||
|
||||
//My assembler doesn't support 16-bit very well.
|
||||
DU8 0xEA; //JMP xxxx:yyyy
|
||||
BMHD2_OLD_CS_RIP:
|
||||
DU16 0,0;
|
||||
BMHD2_END::
|
||||
//Continues here $LK,"::/Adam/Opt/Boot/BootHD.HC",A="FF:::/Adam/Opt/Boot/BootHD.HC,START"$
|
||||
#assert BMHD2_END-BMHD2_START<MODULE_SIZE
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
//See $LK,"Install Documentation",A="FI:::/Doc/Install.DD"$ or $LK,"Upgrading Documentation",A="FI:::/Doc/Upgrade.DD"$.
|
||||
//Study my account examples: $LK,"Cfg Strs",A="FL:::/Demo/AcctExample/TOS/TOSCfg.HC,1"$, $LK,"Update Funs",A="FL:::/Demo/AcctExample/TOS/TOSDistro.HC,1"$
|
||||
|
||||
#include "BootMHD"
|
||||
#include "BootMHD2"
|
||||
|
||||
#help_index "Install"
|
||||
|
||||
#define BOOT_DIR "/0000Boot"
|
||||
//Stage 2 of master boot loader
|
||||
#define BOOT_DIR_BOOTMHD2_BIN_C BOOT_DIR "/BootMHD2.BIN.C"
|
||||
//Old master boot record
|
||||
#define BOOT_DIR_OLDMBR_BIN_C BOOT_DIR "/OldMBR.BIN.C"
|
||||
|
||||
public U0 BootMHDOldRead(U8 src_drv,U8 dst_drv)
|
||||
{//Reads MBR from disk drive containing src partition.
|
||||
//Writes a single blk file to dst BOOT_DIR.
|
||||
CBlkDev *bd=Let2BlkDev(src_drv);
|
||||
CDrv *dv;
|
||||
CMasterBoot mbr;
|
||||
Drv(dst_drv);
|
||||
dv=Fs->cur_dv;
|
||||
if (dv->fs_type!=FSt_REDSEA && dv->fs_type!=FSt_FAT32)
|
||||
PrintErr("File System Not Supported\n");
|
||||
else {
|
||||
//Bypass partition bounds-checking
|
||||
BlkDevLock(bd);
|
||||
ATAReadBlks(bd,&mbr,0,1);
|
||||
BlkDevUnlock(bd);
|
||||
|
||||
Drv(dst_drv);
|
||||
MkDir(BOOT_DIR);
|
||||
FileWrite(BOOT_DIR_OLDMBR_BIN_C,&mbr,BLK_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
public U0 BootMHDOldWrite(U8 src_drv,U8 dst_drv)
|
||||
{//Reads OldMBR from src drive BOOT_DIR.
|
||||
//writes it to the MBR of the drive with dst partition.
|
||||
CBlkDev *bd=Let2BlkDev(dst_drv);
|
||||
CMasterBoot *mbr;
|
||||
Drv(src_drv);
|
||||
if (mbr=FileRead(BOOT_DIR_OLDMBR_BIN_C)) {
|
||||
//Bypass partition bounds-checking
|
||||
BlkDevLock(bd);
|
||||
ATAWriteBlks(bd,mbr,0,1);
|
||||
BlkDevUnlock(bd);
|
||||
}
|
||||
Free(mbr);
|
||||
}
|
||||
|
||||
public U0 BootMHDZero(U8 dst_drv)
|
||||
{//Set MBR of disk with dst partition to zero.
|
||||
|
||||
//This is dangerous!!
|
||||
//The TempleOS partitioner doesn't play well
|
||||
//with other operating systems at this time and you need
|
||||
//to do this on a drive partitioned by TempleOS
|
||||
//if you wish to partition with another operating system.
|
||||
CBlkDev *bd=Let2BlkDev(dst_drv);
|
||||
CMasterBoot mbr;
|
||||
MemSet(&mbr,0,BLK_SIZE);
|
||||
//Bypass partition bounds-checking
|
||||
BlkDevLock(bd);
|
||||
ATAWriteBlks(bd,&mbr,0,1);
|
||||
BlkDevUnlock(bd);
|
||||
}
|
||||
|
||||
public Bool BootMHDIns(U8 drv_let,U8 *drv_lst=NULL)
|
||||
{//Create new MBR on the disk that has drv_let as a partition.
|
||||
//Puts stage 2 in BOOT_DIR of drv_let.
|
||||
CBlkDev *bd,*bd1;
|
||||
CDrv *dv,*p1;
|
||||
CMasterBoot mbr;
|
||||
CDirEntry de;
|
||||
I64 i,j,size,*_q;
|
||||
U8 *menu_ptr,*ptr,ch,buf[STR_LEN];
|
||||
Bool res=FALSE;
|
||||
|
||||
try {
|
||||
if (drv_lst) {
|
||||
StrCpy(buf,drv_lst);
|
||||
StrUtil(buf,SUF_TO_UPPER);
|
||||
} else {
|
||||
j=0;
|
||||
for (i='A';i<='Z';i++)
|
||||
buf[j++]=i;
|
||||
buf[j++]=0;
|
||||
}
|
||||
Drv(drv_let);
|
||||
dv=Fs->cur_dv;
|
||||
if (dv->fs_type!=FSt_REDSEA && dv->fs_type!=FSt_FAT32)
|
||||
PrintErr("File System Not Supported\n");
|
||||
else {
|
||||
bd=dv->bd;
|
||||
if (!FileFind(BOOT_DIR_OLDMBR_BIN_C,,FUF_JUST_FILES))
|
||||
BootMHDOldRead(drv_let,drv_let);
|
||||
|
||||
_q=BMHD2_BLK_ARRAY;
|
||||
MemSet(_q,0,sizeof(I64)*8);
|
||||
menu_ptr=BMHD2_BOOT_MSG;
|
||||
StrPrint(menu_ptr,"\n\r\n\rTempleOS Boot Loader\n\r\n\r");
|
||||
j=0;
|
||||
if (FileFind(BOOT_DIR_OLDMBR_BIN_C,&de,FUF_JUST_FILES)) {
|
||||
Free(de.full_name);
|
||||
*_q++=Cluster2Blk(dv,de.cluster);
|
||||
CatPrint(menu_ptr,"0. Old Boot Record\n\r");
|
||||
j++;
|
||||
}
|
||||
|
||||
ptr=buf;
|
||||
while (ch=*ptr++) {
|
||||
if ((p1=Let2Drv(ch,FALSE)) && (bd1=p1->bd) && bd1==bd) {
|
||||
*_q=p1->drv_offset;
|
||||
"Drive %C:%16X\n",Drv2Let(p1),*_q;
|
||||
CatPrint(menu_ptr,"%d. Drive %C\n\r",j++,Drv2Let(p1));
|
||||
_q++;
|
||||
}
|
||||
}
|
||||
CatPrint(menu_ptr,"\n\rSelection:");
|
||||
|
||||
size=BMHD2_END-BMHD2_START;
|
||||
FileWrite(BOOT_DIR_BOOTMHD2_BIN_C,BMHD2_START,size);
|
||||
|
||||
if (!FileFind(BOOT_DIR_BOOTMHD2_BIN_C,&de,FUF_JUST_FILES))
|
||||
"No Boot Loader Image\n";
|
||||
else {
|
||||
Free(de.full_name);
|
||||
*BMHD_BLK_CNT(U16 *)=(size+BLK_SIZE-1)>>BLK_SIZE_BITS;
|
||||
*BMHD_DAP_BLK(I64 *)=Cluster2Blk(dv,de.cluster);
|
||||
//Bypass partition bounds-checking
|
||||
BlkDevLock(bd);
|
||||
ATAReadBlks(bd,&mbr,0,1);
|
||||
for (i=0;i<BMHD_END-BMHD_CODE;i++)
|
||||
mbr.code[i]=BMHD_CODE(U8 *)[i];
|
||||
#assert sizeof(CMasterBoot.code)>=BMHD_END-BMHD_CODE
|
||||
for (;i<sizeof(CMasterBoot.code);i++)
|
||||
mbr.code[i]=0;
|
||||
if (!mbr.media_id)
|
||||
mbr.media_id=RandU32;
|
||||
mbr.zero=0;
|
||||
mbr.signature=0xAA55;
|
||||
|
||||
ATAWriteBlks(bd,&mbr,0,1);
|
||||
BlkDevUnlock(bd);
|
||||
res=TRUE;
|
||||
}
|
||||
}
|
||||
} catch
|
||||
PutExcept;
|
||||
return res;
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
#help_index "Call"
|
||||
asm {
|
||||
_HI_CALL::
|
||||
PUSH RBP
|
||||
MOV RBP,RSP
|
||||
MOV RAX,U64 16[RBP]
|
||||
TEST RAX,RAX
|
||||
JZ @@05
|
||||
CALL RAX
|
||||
@@05: POP RBP
|
||||
RET1 8
|
||||
//************************************
|
||||
_HI_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
|
||||
}
|
||||
_extern _HI_CALL I64 HiCall(U8 *machine_code);
|
||||
_extern _HI_MEMCPY U8 *HiMemCpy(U8 *dst,U8 *src,I64 cnt);
|
||||
|
||||
#help_index "Boot"
|
||||
public U0 BootRAM(U8 *filename=NULL)
|
||||
{//Softboot Kernel.BIN file. No hardware reset.
|
||||
I64 size;
|
||||
CKernel *hi_image,*lo_image=mem_boot_base-sizeof(CBinFile),
|
||||
reg *sys_ram_reboot;
|
||||
if (!filename)
|
||||
filename="::/" KERNEL_BIN_C;
|
||||
do if (!(hi_image=FileRead(filename,&size))) return;
|
||||
while (hi_image<0x100000); //If alloc from low 640K, just get another copy.
|
||||
|
||||
do sys_ram_reboot=MAlloc(SYS_RAM_REBOOT_END-SYS_RAM_REBOOT,Fs->code_heap);
|
||||
while (sys_ram_reboot<0x100000);
|
||||
|
||||
hi_image->boot_src=BOOT_SRC_RAM;
|
||||
hi_image->boot_blk=0;
|
||||
hi_image->boot_patch_table_base=lo_image(U8 *)+hi_image->h.patch_table_offset;
|
||||
hi_image->sys_run_level =lo_image->sys_run_level&(RLF_VGA|RLF_16BIT);
|
||||
MemCpy(&hi_image->start,&lo_image->start,
|
||||
sizeof(CKernel)-offset(CKernel.start));
|
||||
|
||||
CLI
|
||||
if (mp_cnt>1)
|
||||
MPHalt;
|
||||
|
||||
HiMemCpy(sys_ram_reboot,SYS_RAM_REBOOT,SYS_RAM_REBOOT_END-SYS_RAM_REBOOT);
|
||||
HiMemCpy(lo_image,hi_image,size);
|
||||
HiCall(sys_ram_reboot);
|
||||
}
|
||||
@@ -0,0 +1,506 @@
|
||||
#help_index "File/CD DVD"
|
||||
|
||||
class CCDVDUserData //Create DVD
|
||||
{
|
||||
I64 loc,path_entry_num,
|
||||
short_dir_blks,long_dir_blks;
|
||||
};
|
||||
|
||||
I64 DVDFileCreate2(CFile *out_file,CDirEntry *tmpde,CISO1DirEntry *tmpi,
|
||||
CISO1DirEntry *tmpi2,I64 *_cur_blk,CDirEntry *parent,Bool write,
|
||||
U8 *stage2_filename,I64 *_stage2_blk)
|
||||
{
|
||||
CCDVDUserData *tmpc;
|
||||
CDirEntry *tmpde1,*tmpde2;
|
||||
CFile *in_file;
|
||||
U8 *buf=MAlloc(DVD_BLK_SIZE),*ptr1,*ptr2;
|
||||
CISO1DirEntry *dir_blk_buf =CAlloc(DVD_BLK_SIZE*128),
|
||||
*de =dir_blk_buf, *de1,
|
||||
*dir_blk_buf2=CAlloc(DVD_BLK_SIZE*128),
|
||||
*de2=dir_blk_buf2,*de12;
|
||||
I64 i,n;
|
||||
|
||||
tmpc=parent->user_data;
|
||||
|
||||
de->len=sizeof(CISO1DirEntry)-1;
|
||||
de->ext_attr_len=0;
|
||||
FillU16Palindrome(&de->vol_seq_num,1);
|
||||
Date2ISO1(&de->date,tmpde->datetime);
|
||||
de->flags=ISO1_ATTR_DIR;
|
||||
de->name_len=1;
|
||||
de->name=0;
|
||||
de->len+=de->name_len;
|
||||
de(U8 *)+=de->len;
|
||||
|
||||
de->len=sizeof(CISO1DirEntry)-1;
|
||||
de->ext_attr_len=0;
|
||||
FillU32Palindrome(&de->loc,tmpc->loc);
|
||||
FillU32Palindrome(&de->size,tmpc->short_dir_blks*DVD_BLK_SIZE);
|
||||
FillU16Palindrome(&de->vol_seq_num,1);
|
||||
Date2ISO1(&de->date,parent->datetime);
|
||||
de->flags=ISO1_ATTR_DIR;
|
||||
de->name_len=1;
|
||||
de->name=1;
|
||||
de->len+=de->name_len;
|
||||
de(U8 *)+=de->len;
|
||||
|
||||
de2->len=sizeof(CISO1DirEntry)-1;
|
||||
de2->ext_attr_len=0;
|
||||
FillU16Palindrome(&de2->vol_seq_num,1);
|
||||
Date2ISO1(&de2->date,tmpde->datetime);
|
||||
de2->flags=ISO1_ATTR_DIR;
|
||||
de2->name_len=1;
|
||||
de2->name=0;
|
||||
de2->len+=de2->name_len;
|
||||
de2(U8 *)+=de2->len;
|
||||
|
||||
de2->len=sizeof(CISO1DirEntry)-1;
|
||||
de2->ext_attr_len=0;
|
||||
FillU32Palindrome(&de2->loc,tmpc->loc+tmpc->short_dir_blks);
|
||||
FillU32Palindrome(&de2->size,tmpc->long_dir_blks*DVD_BLK_SIZE);
|
||||
FillU16Palindrome(&de2->vol_seq_num,1);
|
||||
Date2ISO1(&de2->date,parent->datetime);
|
||||
de2->flags=ISO1_ATTR_DIR;
|
||||
de2->name_len=1;
|
||||
de2->name=1;
|
||||
de2->len+=de2->name_len;
|
||||
de2(U8 *)+=de2->len;
|
||||
|
||||
tmpde1=tmpde->sub;
|
||||
while (tmpde1) {
|
||||
tmpde2=tmpde1->next;
|
||||
if (!write) tmpde1->user_data=CAlloc(sizeof(CCDVDUserData));
|
||||
de1=de;
|
||||
de12=de2;
|
||||
if (tmpde1->attr & RS_ATTR_DIR) {
|
||||
n=DVDFileCreate2(out_file,tmpde1,de,de2,_cur_blk,
|
||||
tmpde,write,stage2_filename,_stage2_blk);
|
||||
de(U8 *)+=sizeof(CISO1DirEntry)-1+n;
|
||||
de2(U8 *)+=sizeof(CISO1DirEntry)-1+n<<1;
|
||||
} else {
|
||||
tmpc=tmpde1->user_data;
|
||||
de->len=sizeof(CISO1DirEntry)-1;
|
||||
de->ext_attr_len=0;
|
||||
FillU32Palindrome(&de->loc,*_cur_blk);
|
||||
tmpc->loc=*_cur_blk;
|
||||
if (write) {
|
||||
if (stage2_filename && !StrCmp(tmpde1->full_name,stage2_filename)) {
|
||||
"$$RED$$!!! Boot Stage 2 !!!$$FG$$\n";
|
||||
if (_stage2_blk) *_stage2_blk=*_cur_blk;
|
||||
}
|
||||
"%X:%s\n",*_cur_blk,tmpde1->full_name;
|
||||
}
|
||||
FillU32Palindrome(&de->size,tmpde1->size);
|
||||
FillU16Palindrome(&de->vol_seq_num,1);
|
||||
Date2ISO1(&de->date,tmpde1->datetime);
|
||||
de->flags=0;
|
||||
de->name_len=StrLen(tmpde1->name);
|
||||
StrCpy(&de->name,tmpde1->name);
|
||||
de->len=de->len+de->name_len;
|
||||
de(U8 *)+=de->len;
|
||||
|
||||
de2->len=sizeof(CISO1DirEntry)-1;
|
||||
de2->ext_attr_len=0;
|
||||
FillU32Palindrome(&de2->loc,*_cur_blk);
|
||||
FillU32Palindrome(&de2->size,tmpde1->size);
|
||||
FillU16Palindrome(&de2->vol_seq_num,1);
|
||||
Date2ISO1(&de2->date,tmpde1->datetime);
|
||||
de2->flags=0;
|
||||
de2->name_len=StrLen(tmpde1->name)<<1;
|
||||
ptr1=&de2->name;
|
||||
ptr2=&tmpde1->name;
|
||||
for (i=0;i<de2->name_len;i=i+2) {
|
||||
ptr1++;
|
||||
*ptr1++=*ptr2++;
|
||||
}
|
||||
de2->len+=de2->name_len;
|
||||
de2(U8 *)+=de2->len;
|
||||
|
||||
in_file=FOpen(tmpde1->full_name,"r");
|
||||
for (i=0;i<(FSize(in_file)+DVD_BLK_SIZE-1)/DVD_BLK_SIZE;i++) {
|
||||
n=4;
|
||||
if ((i+1)<<2>(FSize(in_file)+BLK_SIZE-1)>>BLK_SIZE_BITS) {
|
||||
n=(FSize(in_file)+BLK_SIZE-1)>>BLK_SIZE_BITS&3;
|
||||
MemSet(buf,0,DVD_BLK_SIZE);
|
||||
}
|
||||
if (write) {
|
||||
FRBlks(in_file,buf,i<<2,n);
|
||||
FWBlks(out_file,buf,*_cur_blk<<2,n);
|
||||
}
|
||||
*_cur_blk+=1;
|
||||
}
|
||||
FClose(in_file);
|
||||
}
|
||||
if ((de1(U8 *)-dir_blk_buf(U8 *))/DVD_BLK_SIZE!=
|
||||
(de(U8 *) -dir_blk_buf(U8 *))/DVD_BLK_SIZE) {
|
||||
i=de1->len;
|
||||
MemCpy(buf,de1,i);
|
||||
MemSet(de1,0,i);
|
||||
de=dir_blk_buf(U8 *)+(de(U8 *)
|
||||
-dir_blk_buf(U8 *))/DVD_BLK_SIZE*DVD_BLK_SIZE;
|
||||
MemCpy(de,buf,i);
|
||||
de(U8 *)+=i;
|
||||
}
|
||||
if ((de12(U8 *)-dir_blk_buf2(U8 *))/DVD_BLK_SIZE!=
|
||||
(de2(U8 *) -dir_blk_buf2(U8 *))/DVD_BLK_SIZE) {
|
||||
i=de12->len;
|
||||
MemCpy(buf,de12,i);
|
||||
MemSet(de12,0,i);
|
||||
de2(U8 *)=dir_blk_buf2(U8 *)+(de2(U8 *)
|
||||
-dir_blk_buf2(U8 *))/DVD_BLK_SIZE*DVD_BLK_SIZE;
|
||||
MemCpy(de2,buf,i);
|
||||
de2(U8 *)+=i;
|
||||
}
|
||||
tmpde1=tmpde2;
|
||||
}
|
||||
|
||||
tmpc=tmpde->user_data;
|
||||
|
||||
tmpi->len=sizeof(CISO1DirEntry)-1;
|
||||
tmpi->ext_attr_len=0;
|
||||
tmpi->flags=ISO1_ATTR_DIR;
|
||||
if (!tmpde->name[0]) {
|
||||
tmpi->name_len=1;
|
||||
tmpi->name=1;
|
||||
} else {
|
||||
tmpi->name_len=StrLen(tmpde->name);
|
||||
StrCpy(&tmpi->name,tmpde->name);
|
||||
}
|
||||
tmpi->len+=tmpi->name_len;
|
||||
|
||||
n=de(U8 *)+1-dir_blk_buf(U8 *);
|
||||
n=(n+DVD_BLK_SIZE-1)/DVD_BLK_SIZE;
|
||||
FillU32Palindrome(&tmpi->size,n*DVD_BLK_SIZE);
|
||||
FillU32Palindrome(&tmpi->loc,*_cur_blk);
|
||||
tmpc->short_dir_blks=n;
|
||||
tmpc->loc=*_cur_blk;
|
||||
FillU32Palindrome(&dir_blk_buf->size,n*DVD_BLK_SIZE);
|
||||
FillU32Palindrome(&dir_blk_buf->loc,*_cur_blk);
|
||||
FillU16Palindrome(&tmpi->vol_seq_num,1);
|
||||
Date2ISO1(&tmpi->date,tmpde->datetime);
|
||||
if (write)
|
||||
"%X:%s\n",*_cur_blk,tmpde->full_name;
|
||||
if (write)
|
||||
FWBlks(out_file,dir_blk_buf,*_cur_blk<<2,n<<2);
|
||||
*_cur_blk+=n;
|
||||
|
||||
tmpi2->len=sizeof(CISO1DirEntry)-1;
|
||||
tmpi2->ext_attr_len=0;
|
||||
tmpi2->flags=ISO1_ATTR_DIR;
|
||||
if (!tmpde->name[0]) {
|
||||
tmpi2->name_len=1;
|
||||
tmpi->name=1;
|
||||
} else {
|
||||
tmpi2->name_len=StrLen(tmpde->name)<<1;
|
||||
ptr1=&tmpi2->name;
|
||||
ptr2=&tmpde->name;
|
||||
for (i=0;i<tmpi2->name_len;i=i+2) {
|
||||
ptr1++;
|
||||
*ptr1++=*ptr2++;
|
||||
}
|
||||
}
|
||||
tmpi2->len+=tmpi2->name_len;
|
||||
n=de2(U8 *)+1-dir_blk_buf2(U8 *);
|
||||
n=(n+DVD_BLK_SIZE-1)/DVD_BLK_SIZE;
|
||||
FillU32Palindrome(&tmpi2->size,n*DVD_BLK_SIZE);
|
||||
FillU32Palindrome(&tmpi2->loc,*_cur_blk);
|
||||
tmpc->long_dir_blks=n;
|
||||
FillU32Palindrome(&dir_blk_buf2->size,n*DVD_BLK_SIZE);
|
||||
FillU32Palindrome(&dir_blk_buf2->loc,*_cur_blk);
|
||||
FillU16Palindrome(&tmpi2->vol_seq_num,1);
|
||||
Date2ISO1(&tmpi2->date,tmpde->datetime);
|
||||
if (write)
|
||||
"%X:%s\n",*_cur_blk,tmpde->full_name;
|
||||
if (write)
|
||||
FWBlks(out_file,dir_blk_buf2,*_cur_blk<<2,n<<2);
|
||||
*_cur_blk+=n;
|
||||
|
||||
Free(dir_blk_buf);
|
||||
Free(dir_blk_buf2);
|
||||
Free(buf);
|
||||
return tmpi->name_len;
|
||||
}
|
||||
|
||||
I64 DVDTableLen(CDirEntry *tmpde,I64 *size1,I64 *size2,I64 cur_depth)
|
||||
{//Returns depth
|
||||
CDirEntry *tmpde1=tmpde->sub;
|
||||
I64 max_depth=cur_depth,i;
|
||||
while (tmpde1) {
|
||||
if (tmpde1->attr & RS_ATTR_DIR) {
|
||||
*size1+=sizeof(CISO1PathEntry)-2+ (StrLen(tmpde1->name)+1)&-0x2;
|
||||
*size2+=sizeof(CISO1PathEntry)-2+StrLen(tmpde1->name)<<1;
|
||||
i=DVDTableLen(tmpde1,size1,size2,cur_depth+1);
|
||||
if (i>max_depth) max_depth=i;
|
||||
}
|
||||
tmpde1=tmpde1->next;
|
||||
}
|
||||
return max_depth;
|
||||
}
|
||||
|
||||
U0 DVDFillPathTable(CDirEntry *tmpde,
|
||||
CISO1PathEntry **_itabbuf,CISO1PathEntry **_itabbuf2,
|
||||
I64 parent_entry_num,Bool big_endian,I64 *first_free,
|
||||
I64 cur_level,I64 output_level)
|
||||
{
|
||||
U8 *ptr1,*ptr2;
|
||||
I64 i;
|
||||
CISO1PathEntry *tabbuf=*_itabbuf,*tabbuf2=*_itabbuf2;
|
||||
CDirEntry *tmpde1=tmpde->sub,*tmpde2;
|
||||
CCDVDUserData *tmpc;
|
||||
|
||||
if (cur_level==output_level) {
|
||||
while (tmpde1) {
|
||||
if (tmpde1->attr & RS_ATTR_DIR) {
|
||||
tmpc=tmpde1->user_data;
|
||||
tmpc->path_entry_num=*first_free;
|
||||
tabbuf->name_len=StrLen(tmpde1->name);
|
||||
if (big_endian) {
|
||||
tabbuf->blk=EndianU32(tmpc->loc);
|
||||
tabbuf->parent_entry_num=EndianU16(parent_entry_num);
|
||||
} else {
|
||||
tabbuf->blk=tmpc->loc;
|
||||
tabbuf->parent_entry_num=parent_entry_num;
|
||||
}
|
||||
StrCpy(&tabbuf->name,tmpde1->name);
|
||||
|
||||
tabbuf(U8 *)+=sizeof(CISO1PathEntry)-2+
|
||||
(StrLen(tmpde1->name)+1) & -0x2;
|
||||
|
||||
tabbuf2->name_len=StrLen(tmpde1->name)<<1;
|
||||
if (big_endian) {
|
||||
tabbuf2->blk=EndianU32(tmpc->loc+tmpc->short_dir_blks);
|
||||
tabbuf2->parent_entry_num=EndianU16(parent_entry_num);
|
||||
} else {
|
||||
tabbuf2->blk=tmpc->loc+tmpc->short_dir_blks;
|
||||
tabbuf2->parent_entry_num=parent_entry_num;
|
||||
}
|
||||
ptr1=&tabbuf2->name;
|
||||
ptr2=&tmpde1->name;
|
||||
for (i=0;i<tabbuf2->name_len;i=i+2) {
|
||||
ptr1++;
|
||||
*ptr1++=*ptr2++;
|
||||
}
|
||||
tabbuf2(U8 *)+=sizeof(CISO1PathEntry)-2+
|
||||
StrLen(tmpde1->name)<<1;
|
||||
*first_free+=1;
|
||||
}
|
||||
tmpde1=tmpde1->next;
|
||||
}
|
||||
*_itabbuf=tabbuf;
|
||||
*_itabbuf2=tabbuf2;
|
||||
}
|
||||
tmpde1=tmpde->sub;
|
||||
while (tmpde1) {
|
||||
tmpde2=tmpde1->next;
|
||||
if (tmpde1->attr & RS_ATTR_DIR) {
|
||||
tmpc=tmpde1->user_data;
|
||||
DVDFillPathTable(tmpde1,_itabbuf,_itabbuf2,tmpc->path_entry_num,
|
||||
big_endian,first_free,cur_level+1,output_level);
|
||||
}
|
||||
tmpde1=tmpde2;
|
||||
}
|
||||
}
|
||||
|
||||
public I64 ISO9660ISO(U8 *_filename=NULL,U8 *src_files_find_mask,
|
||||
U8 *fu_flags=NULL,U8 *_stage2_filename=NULL)
|
||||
{//See $LK,"::/Misc/DoDistro.HC"$
|
||||
//Use "C:/Distro/*" if you want all files in the C:/Distro directory.
|
||||
//Default flags are "+r" recurse.
|
||||
CISO1PriDesc *iso_pri=CAlloc(DVD_BLK_SIZE),
|
||||
*iso_boot=CAlloc(DVD_BLK_SIZE),
|
||||
*iso_sup=CAlloc(DVD_BLK_SIZE),
|
||||
*iso_term=CAlloc(DVD_BLK_SIZE);
|
||||
CDirEntry *headdir=CAlloc(sizeof(CDirEntry));
|
||||
I64 i,j,stage2_blk=(20<<2+1<<2+DVD_BOOT_LOADER_SIZE/BLK_SIZE)>>2,
|
||||
stage2_size,cur_blk=0,tabsize,tabsize2,first_free,max_depth,fuf_flags=0;
|
||||
U32 *d;
|
||||
CElTorito *et=CAlloc(DVD_BLK_SIZE);
|
||||
U8 *filename,*stage2_filename,
|
||||
*stage1_buf=CAlloc(DVD_BOOT_LOADER_SIZE),
|
||||
*zero_buf=CAlloc(DVD_BLK_SIZE);
|
||||
CISO1PathEntry *tabbuf=NULL,*tabbuf2=NULL,*itabbuf,*itabbuf2;
|
||||
CFile *out_file=NULL;
|
||||
CISO1DirEntry *tmpi;
|
||||
CCDVDUserData *tmpc;
|
||||
|
||||
ScanFlags(&fuf_flags,Define("ST_FILE_UTIL_FLAGS"),"+r");
|
||||
ScanFlags(&fuf_flags,Define("ST_FILE_UTIL_FLAGS"),fu_flags);
|
||||
|
||||
if (!_filename)
|
||||
_filename=blkdev.dft_iso_filename;
|
||||
filename=DftExt(_filename,"ISO");
|
||||
|
||||
if (_stage2_filename)
|
||||
stage2_filename=FileNameAbs(_stage2_filename);
|
||||
else
|
||||
stage2_filename=NULL;
|
||||
|
||||
headdir->attr=RS_ATTR_DIR;
|
||||
headdir->sub=FilesFind(src_files_find_mask,fuf_flags);
|
||||
headdir->datetime=Now;
|
||||
headdir->user_data=CAlloc(sizeof(CCDVDUserData));
|
||||
tmpc=headdir->user_data;
|
||||
tmpc->path_entry_num=1;
|
||||
|
||||
cur_blk=20<<2>>2;
|
||||
if (stage2_filename) //preboot and bootloader
|
||||
cur_blk+=1+DVD_BOOT_LOADER_SIZE/DVD_BLK_SIZE;
|
||||
DVDFileCreate2(out_file,headdir,&iso_pri->root_dir_record,
|
||||
&iso_sup->root_dir_record,&cur_blk,headdir,FALSE,
|
||||
stage2_filename,&stage2_blk);
|
||||
tabsize=sizeof(CISO1PathEntry);
|
||||
tabsize2=sizeof(CISO1PathEntry);
|
||||
max_depth=DVDTableLen(headdir,&tabsize,&tabsize2,1);
|
||||
FillU32Palindrome(&iso_pri->path_table_size,tabsize);
|
||||
FillU32Palindrome(&iso_sup->path_table_size,tabsize2);
|
||||
tabsize=(tabsize+DVD_BLK_SIZE-1)/DVD_BLK_SIZE;
|
||||
cur_blk+=tabsize<<1;
|
||||
tabsize2=(tabsize2+DVD_BLK_SIZE-1)/DVD_BLK_SIZE;
|
||||
cur_blk+=tabsize2<<1;
|
||||
|
||||
if (FileAttr(filename) & RS_ATTR_CONTIGUOUS)
|
||||
out_file=FOpen(filename,"wc",cur_blk<<2);
|
||||
else
|
||||
out_file=FOpen(filename,"w",cur_blk<<2);
|
||||
cur_blk=0;
|
||||
if (!out_file)
|
||||
goto cf_done;
|
||||
|
||||
while (cur_blk<20<<2>>2)
|
||||
FWBlks(out_file,zero_buf,cur_blk++<<2,4);
|
||||
|
||||
iso_pri->type=ISO1T_PRI_VOL_DESC;
|
||||
StrCpy(iso_pri->id,"CD001");
|
||||
iso_pri->version=1;
|
||||
FillU16Palindrome(&iso_pri->vol_set_size,1);
|
||||
FillU16Palindrome(&iso_pri->vol_seq_num,1);
|
||||
FillU16Palindrome(&iso_pri->log_block_size,DVD_BLK_SIZE);
|
||||
iso_pri->file_structure_version=1;
|
||||
|
||||
iso_sup->type=ISO1T_SUPPLEMENTARY_DESC;
|
||||
StrCpy(iso_sup->id,"CD001");
|
||||
iso_sup->version=1;
|
||||
FillU16Palindrome(&iso_sup->vol_set_size,1);
|
||||
FillU16Palindrome(&iso_sup->vol_seq_num,1);
|
||||
FillU16Palindrome(&iso_sup->log_block_size,DVD_BLK_SIZE);
|
||||
iso_sup->file_structure_version=1;
|
||||
|
||||
iso_boot->type=ISO1T_BOOT_RECORD;
|
||||
StrCpy(iso_boot->id,"CD001");
|
||||
iso_boot->version=1;
|
||||
StrCpy(iso_boot(U8 *)+7,"EL TORITO SPECIFICATION");
|
||||
|
||||
cur_blk=20<<2>>2;
|
||||
|
||||
if (stage2_filename) {
|
||||
d=iso_boot(U8 *)+0x47;
|
||||
*d=cur_blk;
|
||||
et->w[0]=1;
|
||||
StrCpy(&et->w[2],"TempleOS");
|
||||
et->w[15]=0xAA55;
|
||||
j=0;
|
||||
for (i=0;i<16;i++) //Checksum
|
||||
j+=et->w[i];
|
||||
et->w[14]=-j;
|
||||
et->bootable=0x88;
|
||||
et->media_type=0;//0=no emu 2=1.44meg 4=hard drive
|
||||
et->sect_cnt=4; //5 seems like the limit, 4 is safer
|
||||
et->load_rba=cur_blk+1;
|
||||
"%X: Pre Boot Blk\n",cur_blk;
|
||||
FWBlks(out_file,et,cur_blk++<<2,4);
|
||||
"%X: Boot Stage 1\n",cur_blk;
|
||||
cur_blk+=DVD_BOOT_LOADER_SIZE/DVD_BLK_SIZE;
|
||||
}
|
||||
|
||||
DVDFileCreate2(out_file,headdir,&iso_pri->root_dir_record,
|
||||
&iso_sup->root_dir_record,&cur_blk,headdir,TRUE,
|
||||
stage2_filename,&stage2_blk);
|
||||
|
||||
tabbuf=CAlloc(tabsize*DVD_BLK_SIZE);
|
||||
iso_pri->type_l_path_table=cur_blk;
|
||||
tabbuf->name_len=2; //Fill-in adam entry
|
||||
tmpi=&iso_pri->root_dir_record;
|
||||
tabbuf->blk=tmpi->loc.little;
|
||||
tabbuf->parent_entry_num=1;
|
||||
tabbuf2=CAlloc(tabsize2*DVD_BLK_SIZE);
|
||||
iso_sup->type_l_path_table=cur_blk+tabsize;
|
||||
tabbuf2->name_len=2; //Fill-in adam entry
|
||||
tmpi=&iso_sup->root_dir_record;
|
||||
tabbuf2->blk=tmpi->loc.little;
|
||||
tabbuf2->parent_entry_num=1;
|
||||
itabbuf=tabbuf+1;
|
||||
itabbuf2=tabbuf2+1;
|
||||
first_free=2;
|
||||
for (i=1;i<=max_depth;i++)
|
||||
DVDFillPathTable(headdir,&itabbuf,&itabbuf2,1,FALSE,&first_free,1,i);
|
||||
"%X: Path Table 0\n",cur_blk;
|
||||
FWBlks(out_file,tabbuf,cur_blk<<2,tabsize<<2);
|
||||
cur_blk+=tabsize;
|
||||
"%X: Path Table 1\n",cur_blk;
|
||||
FWBlks(out_file,tabbuf2,cur_blk<<2,tabsize2<<2);
|
||||
cur_blk+=tabsize2;
|
||||
|
||||
MemSet(tabbuf,0,tabsize*DVD_BLK_SIZE);
|
||||
iso_pri->type_m_path_table=EndianU32(cur_blk);
|
||||
tabbuf->name_len=2; //Fill-in adam entry
|
||||
tmpi=&iso_pri->root_dir_record;
|
||||
tabbuf->blk=tmpi->loc.big;
|
||||
tabbuf->parent_entry_num=EndianU16(1);
|
||||
MemSet(tabbuf2,0,tabsize2*DVD_BLK_SIZE);
|
||||
iso_sup->type_m_path_table=EndianU32(cur_blk+tabsize);
|
||||
tabbuf2->name_len=2; //Fill-in adam entry
|
||||
tmpi=&iso_sup->root_dir_record;
|
||||
tabbuf2->blk=tmpi->loc.big;
|
||||
tabbuf2->parent_entry_num=EndianU16(1);
|
||||
itabbuf=tabbuf+1;
|
||||
itabbuf2=tabbuf2+1;
|
||||
first_free=2;
|
||||
for (i=1;i<=max_depth;i++)
|
||||
DVDFillPathTable(headdir,&itabbuf,&itabbuf2,1,TRUE,&first_free,1,i);
|
||||
"%X: Path Table 2\n",cur_blk;
|
||||
FWBlks(out_file,tabbuf,cur_blk<<2,tabsize<<2);
|
||||
cur_blk+=tabsize;
|
||||
"%X: Path Table 3\n",cur_blk;
|
||||
FWBlks(out_file,tabbuf2,cur_blk<<2,tabsize2<<2);
|
||||
cur_blk+=tabsize2;
|
||||
|
||||
DirTreeDel2(headdir);
|
||||
FillU32Palindrome(&iso_pri->vol_space_size,cur_blk);
|
||||
FillU32Palindrome(&iso_sup->vol_space_size,cur_blk);
|
||||
FWBlks(out_file,iso_pri,16<<2,4);
|
||||
|
||||
iso_term->type=ISO1T_TERMINATOR;
|
||||
StrCpy(iso_term->id,"CD001");
|
||||
iso_term->version=1;
|
||||
if (stage2_filename) {
|
||||
FWBlks(out_file,iso_boot,17<<2,4);
|
||||
FWBlks(out_file,iso_sup,18<<2,4);
|
||||
FWBlks(out_file,iso_term,19<<2,4);
|
||||
stage2_size=(Size(stage2_filename,"+s")+DVD_BLK_SIZE-1)/DVD_BLK_SIZE;
|
||||
MemCpy(stage1_buf,BDVD_START,BDVD_END-BDVD_START);
|
||||
*(BDVD_BLK_CNT-BDVD_START+stage1_buf)(U16 *)=stage2_size;
|
||||
*(BDVD_BLK_LO -BDVD_START+stage1_buf)(U32 *)=stage2_blk;
|
||||
"$$RED$$!!! Boot Stage 2 !!! %X-%X$$FG$$\n",
|
||||
stage2_blk,stage2_blk+stage2_size-1;
|
||||
FWBlks(out_file,stage1_buf,
|
||||
20<<2+1<<2,DVD_BOOT_LOADER_SIZE/BLK_SIZE);
|
||||
} else {
|
||||
FWBlks(out_file,iso_sup,17<<2,4);
|
||||
FWBlks(out_file,iso_term,18<<2,4);
|
||||
}
|
||||
|
||||
cf_done:
|
||||
FClose(out_file);
|
||||
Free(tabbuf);
|
||||
Free(tabbuf2);
|
||||
Free(stage2_filename);
|
||||
Free(filename);
|
||||
Free(zero_buf);
|
||||
Free(stage1_buf);
|
||||
Free(et);
|
||||
Free(iso_pri);
|
||||
Free(iso_boot);
|
||||
Free(iso_sup);
|
||||
Free(iso_term);
|
||||
return cur_blk;
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
#help_index "File/CD DVD"
|
||||
|
||||
U0 FillU16Palindrome(CPalindromeU16 *dst,U16 w)
|
||||
{
|
||||
dst->big=EndianU16(w);
|
||||
dst->little=w;
|
||||
}
|
||||
|
||||
U0 FillU32Palindrome(CPalindromeU32 *dst,I64 d)
|
||||
{
|
||||
dst->big=EndianU32(d);
|
||||
dst->little=d;
|
||||
}
|
||||
|
||||
class CElTorito
|
||||
{
|
||||
U16 w[16];
|
||||
U8 bootable; //88=bootable 00=not bootable
|
||||
U8 media_type; //0=no emulation 4=hard disk
|
||||
U16 load_seg; //0000->07C0
|
||||
U8 sys_type;
|
||||
U8 zero;
|
||||
U16 sect_cnt;
|
||||
U32 load_rba; //start addr of virtual disk
|
||||
U8 zero2[20];
|
||||
};
|
||||
|
||||
U0 RedSeaISO9660Stage1(U8 *iso_filename,U8 *stage2_filename)
|
||||
{
|
||||
CDirEntry de;
|
||||
CFile *out_file=NULL;
|
||||
U8 *stage1_buf=CAlloc(DVD_BOOT_LOADER_SIZE);
|
||||
if (FileFind(stage2_filename,&de) && (out_file=FOpen(iso_filename,"wc+"))) {
|
||||
MemCpy(stage1_buf,BDVD_START,BDVD_END-BDVD_START);
|
||||
*(BDVD_BLK_LO -BDVD_START+stage1_buf)(U32 *)=de.cluster>>2;
|
||||
*(BDVD_BLK_CNT -BDVD_START+stage1_buf)(U16 *)=
|
||||
(de.size+DVD_BLK_SIZE-1)>>(BLK_SIZE_BITS+2);
|
||||
*(BDVD_SHIFT_BLKS -BDVD_START+stage1_buf)(U16 *)=de.cluster&3;
|
||||
if (de.cluster&3)
|
||||
*(BDVD_BLK_CNT -BDVD_START+stage1_buf)(U16 *)+=1;
|
||||
FWBlks(out_file,stage1_buf,
|
||||
20<<2+1<<2,DVD_BOOT_LOADER_SIZE/BLK_SIZE);
|
||||
FClose(out_file);
|
||||
}
|
||||
Free(stage1_buf);
|
||||
}
|
||||
|
||||
U0 RedSeaISO9660(U8 *iso_filename,U8 drv_let)
|
||||
{
|
||||
CDrv *dv=Let2Drv(drv_let);
|
||||
CISO1PriDesc *iso_pri=CAlloc(DVD_BLK_SIZE),
|
||||
*iso_boot=CAlloc(DVD_BLK_SIZE),
|
||||
*iso_sup=CAlloc(DVD_BLK_SIZE),
|
||||
*iso_term=CAlloc(DVD_BLK_SIZE);
|
||||
I64 iso_size=0,i,j;
|
||||
U32 *d;
|
||||
CElTorito *et=CAlloc(DVD_BLK_SIZE);
|
||||
U8 *zero_buf=CAlloc(DVD_BLK_SIZE);
|
||||
CFile *out_file=NULL;
|
||||
|
||||
if (out_file=FOpen(iso_filename,"wc+")) {
|
||||
iso_size=FSize(out_file)/DVD_BLK_SIZE;
|
||||
for (i=0;i<dv->bd->drv_offset;i+=4)
|
||||
FWBlks(out_file,zero_buf,i,4);
|
||||
|
||||
iso_pri->type=ISO1T_PRI_VOL_DESC;
|
||||
StrCpy(iso_pri->id,"CD001");
|
||||
iso_pri->version=1;
|
||||
FillU16Palindrome(&iso_pri->vol_set_size,1);
|
||||
FillU16Palindrome(&iso_pri->vol_seq_num,1);
|
||||
FillU16Palindrome(&iso_pri->log_block_size,DVD_BLK_SIZE);
|
||||
FillU32Palindrome(&iso_pri->vol_space_size,iso_size);
|
||||
FillU32Palindrome(&iso_pri->root_dir_record,dv->root_cluster);
|
||||
iso_pri->file_structure_version=1;
|
||||
StrCpy(iso_pri->publisher_id,"TempleOS RedSea");
|
||||
|
||||
MemCpy(iso_sup,iso_pri,DVD_BLK_SIZE);
|
||||
iso_sup->type=ISO1T_SUPPLEMENTARY_DESC;
|
||||
|
||||
iso_boot->type=ISO1T_BOOT_RECORD;
|
||||
StrCpy(iso_boot->id,"CD001");
|
||||
iso_boot->version=1;
|
||||
StrCpy(iso_boot(U8 *)+7,"EL TORITO SPECIFICATION");
|
||||
|
||||
FWBlks(out_file,iso_pri,16<<2,4);
|
||||
iso_term->type=ISO1T_TERMINATOR;
|
||||
StrCpy(iso_term->id,"CD001");
|
||||
iso_term->version=1;
|
||||
|
||||
d=iso_boot(U8 *)+0x47;
|
||||
*d=20<<2>>2;
|
||||
FWBlks(out_file,iso_boot,17<<2,4);
|
||||
|
||||
FWBlks(out_file,iso_sup,18<<2,4);
|
||||
FWBlks(out_file,iso_term,19<<2,4);
|
||||
|
||||
et->w[0]=1;
|
||||
StrCpy(&et->w[2],"TempleOS");
|
||||
et->w[15]=0xAA55;
|
||||
j=0;
|
||||
for (i=0;i<16;i++) //Checksum
|
||||
j+=et->w[i];
|
||||
et->w[14]=-j;
|
||||
et->bootable=0x88;
|
||||
et->media_type=0;//0=no emu 2=1.44meg 4=hard drive
|
||||
et->sect_cnt=4; //5 seems like the limit, 4 is safer
|
||||
et->load_rba=20<<2>>2+1;
|
||||
FWBlks(out_file,et,20<<2,4);
|
||||
FClose(out_file);
|
||||
}
|
||||
Free(zero_buf);
|
||||
Free(et);
|
||||
Free(iso_pri);
|
||||
Free(iso_boot);
|
||||
Free(iso_sup);
|
||||
Free(iso_term);
|
||||
}
|
||||
|
||||
I64 RedSeaISOPass1(CDirEntry *tmpde)
|
||||
{
|
||||
I64 dir_entry_cnt=3+LinkedLstCnt(tmpde),res=0;
|
||||
while (tmpde) {
|
||||
if (tmpde->attr & RS_ATTR_DIR) {
|
||||
if (tmpde->sub)
|
||||
res+=RedSeaISOPass1(tmpde->sub);
|
||||
else
|
||||
res+=BLK_SIZE; //Empty dir
|
||||
} else
|
||||
res+=CeilU64(tmpde->size,BLK_SIZE);
|
||||
tmpde=tmpde->next;
|
||||
}
|
||||
res+=CeilU64(dir_entry_cnt<<6,BLK_SIZE); //Size in bytes
|
||||
#assert CDIR_SIZE==64
|
||||
return res;
|
||||
}
|
||||
public I64 RedSeaISO(U8 *_iso_filename=NULL,U8 *_src_dir,
|
||||
U8 *_stage2_filename=NULL)
|
||||
{//See $LK,"::/Misc/DoDistro.HC"$. Must be ISO.C
|
||||
I64 i,res,root_cnt,root_dir_blks,bitmap_blks,bitmap_blks1;
|
||||
CDirEntry *tmpde;
|
||||
U8 buf[STR_LEN],*iso_filename,*src_dir,*stage2_filename;
|
||||
CDrv *dv=DrvMakeFreeSlot(DrvNextFreeLet('Q')); //First $LK,"BDT_ISO_FILE_WRITE",A="MN:BDT_ISO_FILE_WRITE"$
|
||||
CBlkDev *bd=BlkDevNextFreeSlot(dv->drv_let,BDT_ISO_FILE_WRITE);
|
||||
|
||||
if (!IsDir(_src_dir))
|
||||
PrintErr("'%s' is not a dir.\n",_src_dir);
|
||||
else {
|
||||
if (!_iso_filename)
|
||||
_iso_filename=blkdev.dft_iso_c_filename;
|
||||
iso_filename=ChgExt(_iso_filename,"ISO.C");
|
||||
src_dir=DirNameAbs(_src_dir);
|
||||
if (_stage2_filename) {
|
||||
stage2_filename=FileNameAbs(_stage2_filename);
|
||||
*stage2_filename=dv->drv_let;
|
||||
i=StrLen(src_dir);
|
||||
if (i!=3) //If not root
|
||||
i++; //Skip slash
|
||||
StrCpy(stage2_filename+3,stage2_filename+i);
|
||||
} else
|
||||
stage2_filename=NULL;
|
||||
tmpde=FilesFind(src_dir,FUF_RECURSE);
|
||||
root_cnt=LinkedLstCnt(tmpde)+3;
|
||||
root_dir_blks=CeilU64(root_cnt<<6,BLK_SIZE)>>BLK_SIZE_BITS;
|
||||
if (res=RedSeaISOPass1(tmpde)>>BLK_SIZE_BITS) {
|
||||
bd->drv_offset=19<<2+(DVD_BLK_SIZE*2+DVD_BOOT_LOADER_SIZE)/BLK_SIZE;
|
||||
bitmap_blks=1;
|
||||
do {
|
||||
bitmap_blks1=bitmap_blks;
|
||||
bitmap_blks=(res+bitmap_blks+BLK_SIZE<<3-1)/BLK_SIZE<<3;
|
||||
} while (bitmap_blks!=bitmap_blks1);
|
||||
|
||||
bd->max_blk=CeilI64(bd->drv_offset+1+bitmap_blks+res,4);
|
||||
bd->max_blk--; //Inclusive.
|
||||
bd->file_dsk_name=AStrNew(iso_filename);
|
||||
bd->init_root_dir_blks=root_dir_blks;
|
||||
BlkDevAdd(bd,,TRUE,TRUE);
|
||||
StrPrint(buf,"%C:/",dv->drv_let);
|
||||
CopyTree(src_dir,buf,TRUE);
|
||||
RedSeaISO9660Stage1(iso_filename,stage2_filename);
|
||||
DrvDel(dv);
|
||||
BlkDevDel(bd);
|
||||
}
|
||||
Free(stage2_filename);
|
||||
Free(src_dir);
|
||||
Free(iso_filename);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
Cd(__DIR__);;
|
||||
#include "BootDVDIns"
|
||||
#include "BootHDIns"
|
||||
#include "BootMHDIns"
|
||||
#include "BootRAM"
|
||||
Cd("..");;
|
||||
@@ -0,0 +1,353 @@
|
||||
#help_index "Cmd Line (Typically)"
|
||||
|
||||
#define DS_USE_FILE1 0
|
||||
#define DS_USE_FILE2 1
|
||||
#define DS_REMAINDER_1 2
|
||||
#define DS_REMAINDER_2 3
|
||||
#define DS_ABORT_FILE 4
|
||||
|
||||
I64 PopUpDiffMenu()
|
||||
{
|
||||
I64 i;
|
||||
CDoc *doc=DocNew;
|
||||
DocPrint(doc,"$$CM+LX,2,4$$$$FG$$$$BT,\"USE FILE1\",LE=DS_USE_FILE1$$"
|
||||
"$$CM+LX,24,0$$$$CYAN$$$$BT,\"USE FILE2\",LE=DS_USE_FILE2$$"
|
||||
"$$CM+LX,2,4$$$$FG$$$$BT,\"REMAINDER ALL FILE1\",LE=DS_REMAINDER_1$$"
|
||||
"$$CM+LX,24,0$$$$CYAN$$$$BT,\"REMAINDER ALL FILE2\",LE=DS_REMAINDER_2$$"
|
||||
"$$CM+LX,2,4$$$$FG$$$$BT,\"ABORT FILE\",LE=DS_ABORT_FILE$$"
|
||||
"$$CM+LX,24,0$$$$FG$$$$BT,\"ABORT ALL FILES\",LE=DOCM_CANCEL$$\n");
|
||||
i=PopUpMenu(doc);
|
||||
DocDel(doc);
|
||||
return i;
|
||||
}
|
||||
|
||||
I64 DiffEntriesCompare(CDocEntry *doc_e1,CDocEntry *doc_e2)
|
||||
{
|
||||
return StrCmp(doc_e1->tag,doc_e2->tag);
|
||||
}
|
||||
|
||||
#define DF_MODIFIED 0x01
|
||||
#define DF_DONT_MODIFIED 0x02
|
||||
#define DF_REMAINDER_ALL_FILE1 0x04
|
||||
#define DF_REMAINDER_ALL_FILE2 0x08
|
||||
#define DF_ABORT_FILE 0x10
|
||||
#define DF_ABORT_ALL_FILES 0x20
|
||||
#define DF_NO_MORE_PMTS_THIS_FILE 0x40
|
||||
|
||||
U0 DiffSel(CDoc *doc,I64 *_df_flags,I64 j1_lo,I64 j1_hi,
|
||||
I64 j2_lo,I64 j2_hi,I64 cnt1,I64 cnt2,
|
||||
CDocEntry **doc_unsorted1,CDocEntry **doc_unsorted2)
|
||||
{
|
||||
CDocEntry *doc_e,*doc_e1,*doc_e2;
|
||||
Bool use_file1;
|
||||
I64 i,old_flags;
|
||||
CDoc *cur_l;
|
||||
if (!(*_df_flags & (DF_ABORT_FILE|DF_ABORT_ALL_FILES))) {
|
||||
"$$RED$$";
|
||||
if (0<=j1_lo<cnt1)
|
||||
"%d,",doc_unsorted1[j1_lo]->y+1;
|
||||
else if (0<=j1_hi-1<cnt1)
|
||||
"%d,",doc_unsorted1[j1_hi-1]->y+1;
|
||||
else
|
||||
"***,";
|
||||
if (0<=j2_lo<cnt2)
|
||||
"%d",doc_unsorted2[j2_lo]->y+1;
|
||||
else if (0<=j2_hi-1<cnt2)
|
||||
"%d",doc_unsorted2[j2_hi-1]->y+1;
|
||||
else
|
||||
"***";
|
||||
"---------------------$$FG$$\n";
|
||||
if (j1_lo<=0)
|
||||
i=0;
|
||||
else
|
||||
i=j1_lo-1;
|
||||
while (i<j1_hi) {
|
||||
if (cur_l=DocPut) {
|
||||
old_flags=cur_l->flags&DOCF_PLAIN_TEXT;
|
||||
cur_l->flags|=DOCF_PLAIN_TEXT;
|
||||
}
|
||||
"%s",doc_unsorted1[i++]->tag;
|
||||
if (cur_l)
|
||||
cur_l->flags= cur_l->flags&~DOCF_PLAIN_TEXT |old_flags;
|
||||
'\n';
|
||||
}
|
||||
"$$CYAN$$";
|
||||
if (j2_lo<=0)
|
||||
i=0;
|
||||
else
|
||||
i=j2_lo-1;
|
||||
while (i<j2_hi) {
|
||||
if (cur_l=DocPut) {
|
||||
old_flags=cur_l->flags&DOCF_PLAIN_TEXT;
|
||||
cur_l->flags|=DOCF_PLAIN_TEXT;
|
||||
}
|
||||
"%s",doc_unsorted2[i++]->tag;
|
||||
if (cur_l)
|
||||
cur_l->flags= cur_l->flags&~DOCF_PLAIN_TEXT |old_flags;
|
||||
'\n';
|
||||
}
|
||||
"$$FG$$";
|
||||
|
||||
use_file1=TRUE;
|
||||
if (!(*_df_flags & DF_NO_MORE_PMTS_THIS_FILE)) {
|
||||
switch (PopUpDiffMenu) {
|
||||
case DS_USE_FILE1:
|
||||
break;
|
||||
case DS_USE_FILE2:
|
||||
use_file1=FALSE;
|
||||
break;
|
||||
case DS_REMAINDER_1:
|
||||
*_df_flags=*_df_flags&~DF_REMAINDER_ALL_FILE2|
|
||||
DF_REMAINDER_ALL_FILE1|DF_NO_MORE_PMTS_THIS_FILE;
|
||||
break;
|
||||
case DS_REMAINDER_2:
|
||||
*_df_flags=*_df_flags&~DF_REMAINDER_ALL_FILE1|
|
||||
DF_REMAINDER_ALL_FILE2|DF_NO_MORE_PMTS_THIS_FILE;
|
||||
break;
|
||||
case DS_ABORT_FILE:
|
||||
*_df_flags|=DF_DONT_MODIFIED|DF_ABORT_FILE|
|
||||
DF_NO_MORE_PMTS_THIS_FILE;
|
||||
break;
|
||||
default:
|
||||
*_df_flags|=DF_DONT_MODIFIED|DF_ABORT_ALL_FILES|
|
||||
DF_NO_MORE_PMTS_THIS_FILE;
|
||||
}
|
||||
}
|
||||
if (*_df_flags & DF_REMAINDER_ALL_FILE2 &&
|
||||
!(*_df_flags & (DF_DONT_MODIFIED|DF_REMAINDER_ALL_FILE1)))
|
||||
use_file1=FALSE;
|
||||
if (!use_file1) {
|
||||
*_df_flags|=DF_MODIFIED;
|
||||
doc_e1=doc_unsorted1[j1_lo]->last;
|
||||
if (j1_lo<j1_hi) {
|
||||
doc_e=doc_unsorted1[j1_lo];
|
||||
while (doc_e!=doc_unsorted1[j1_hi]) {
|
||||
doc_e2=doc_e->next;
|
||||
DocEntryDel(doc,doc_e);
|
||||
doc_e=doc_e2;
|
||||
}
|
||||
}
|
||||
if (j2_lo<j2_hi) {
|
||||
doc_e=doc_unsorted2[j2_lo];
|
||||
while (doc_e!=doc_unsorted2[j2_hi]) {
|
||||
doc_e2=DocEntryCopy(doc,doc_e);
|
||||
QueIns(doc_e2,doc_e1);
|
||||
doc_e1=doc_e2;
|
||||
doc_e=doc_e->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Bool DiffSub(CDoc *doc,I64 *_df_flags,I64 j1_lo,I64 j1_hi,I64 j2_lo,I64 j2_hi,
|
||||
I64 cnt1,I64 cnt2,CDocEntry **doc_sorted1,CDocEntry **doc_sorted2,
|
||||
CDocEntry **doc_unsorted1,CDocEntry **doc_unsorted2)
|
||||
{
|
||||
I64 i,i1=0,i2=0,i2b,j1,j2,n,
|
||||
best_j1,best_j2,best_score=0,score;
|
||||
Bool res=FALSE;
|
||||
|
||||
if (j1_lo>=j1_hi || j2_lo>=j2_hi) {
|
||||
if (j1_lo<j1_hi || j2_lo<j2_hi) {
|
||||
DiffSel(doc,_df_flags,j1_lo,j1_hi,j2_lo,j2_hi,cnt1,cnt2,
|
||||
doc_unsorted1,doc_unsorted2);
|
||||
return TRUE;
|
||||
} else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//Locate longest matching str in intervals
|
||||
while (i1<cnt1 && i2<cnt2) {
|
||||
if (!(j1_lo<=doc_sorted1[i1]->user_data<j1_hi)) //user_data is the new y
|
||||
i1++;
|
||||
else if (!(j2_lo<=doc_sorted2[i2]->user_data<j2_hi)) //user_data is new y
|
||||
i2++;
|
||||
else {
|
||||
i=StrCmp(doc_sorted1[i1]->tag,doc_sorted2[i2]->tag);
|
||||
if (i>0)
|
||||
i2++;
|
||||
else if (i<0)
|
||||
i1++;
|
||||
else {
|
||||
i2b=i2;
|
||||
while (!StrCmp(doc_sorted1[i1]->tag,doc_sorted2[i2]->tag)) {
|
||||
if (j2_lo<=doc_sorted2[i2]->user_data<j2_hi) {//user_data is the new y
|
||||
score=0;
|
||||
j1=doc_sorted1[i1]->user_data; //user_data is the new y
|
||||
j2=doc_sorted2[i2]->user_data; //user_data is the new y
|
||||
n=j1_hi-j1;
|
||||
if (j2_hi-j2<n)
|
||||
n=j2_hi-j2;
|
||||
while (score<n) {
|
||||
if (!StrCmp(doc_unsorted1[j1+score]->tag,
|
||||
doc_unsorted2[j2+score]->tag))
|
||||
score++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (score>best_score) {
|
||||
best_score=score;
|
||||
best_j1=j1;
|
||||
best_j2=j2;
|
||||
}
|
||||
}
|
||||
i2++;
|
||||
if (i2>=cnt2)
|
||||
break;
|
||||
}
|
||||
i2=i2b;
|
||||
i1++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!best_score) {
|
||||
DiffSel(doc,_df_flags,j1_lo,j1_hi,j2_lo,j2_hi,cnt1,cnt2,
|
||||
doc_unsorted1,doc_unsorted2);
|
||||
return TRUE;
|
||||
} else {
|
||||
if (DiffSub(doc,_df_flags,j1_lo,best_j1,j2_lo,best_j2,cnt1,cnt2,
|
||||
doc_sorted1,doc_sorted2,doc_unsorted1,doc_unsorted2))
|
||||
res=TRUE;
|
||||
if (DiffSub(doc,_df_flags,best_j1+best_score,j1_hi,best_j2+best_score,
|
||||
j2_hi,cnt1,cnt2,
|
||||
doc_sorted1,doc_sorted2,doc_unsorted1,doc_unsorted2))
|
||||
res=TRUE;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
Bool DiffBins(CDoc *doc1,CDoc *doc2)
|
||||
{
|
||||
CDocBin *tmpb1=doc1->bin_head.next,
|
||||
*tmpb2=doc2->bin_head.next;
|
||||
|
||||
if (tmpb1->last->last->num!=tmpb2->last->last->num)
|
||||
return TRUE;
|
||||
while (tmpb1!=&doc1->bin_head) {
|
||||
if (tmpb1->size!=tmpb2->size ||
|
||||
MemCmp(tmpb1->data,tmpb2->data,tmpb1->size))
|
||||
return TRUE;
|
||||
tmpb1=tmpb1->next;
|
||||
tmpb2=tmpb2->next;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
public Bool Diff(U8 *dst_file,U8 *src_file,I64 *_df_flags=NULL)
|
||||
{//Report differences between two files and merge differences
|
||||
//from src_file to dst_file. Don't use _df_flags arg. (Used by $LK,"Merge",A="MN:Merge"$().)
|
||||
CDoc *doc1=DocRead(dst_file,DOCF_PLAIN_TEXT_TABS|DOCF_NO_CURSOR),
|
||||
*doc2=DocRead(src_file,DOCF_PLAIN_TEXT_TABS|DOCF_NO_CURSOR);
|
||||
CDocEntry *doc_e,**doc_sorted1,**doc_sorted2,**doc_unsorted1,**doc_unsorted2;
|
||||
I64 i,cnt1=0,cnt2=0,df_flags;
|
||||
Bool res=FALSE;
|
||||
|
||||
if (_df_flags)
|
||||
df_flags=*_df_flags;
|
||||
else
|
||||
df_flags=0;
|
||||
df_flags&=DF_ABORT_ALL_FILES;
|
||||
|
||||
doc_e=doc1->head.next;
|
||||
while (doc_e!=doc1) {
|
||||
if (doc_e->type_u8==DOCT_TEXT)
|
||||
doc_e->user_data=cnt1++; //user_data is the new y
|
||||
doc_e=doc_e->next;
|
||||
}
|
||||
|
||||
doc_e=doc2->head.next;
|
||||
while (doc_e!=doc2) {
|
||||
if (doc_e->type_u8==DOCT_TEXT)
|
||||
doc_e->user_data=cnt2++; //user_data is the new y
|
||||
doc_e=doc_e->next;
|
||||
}
|
||||
|
||||
doc_sorted1=MAlloc(cnt1*sizeof(CDocEntry *));
|
||||
doc_unsorted1=MAlloc((cnt1+1)*sizeof(CDocEntry *));
|
||||
i=0;
|
||||
doc_e=doc1->head.next;
|
||||
while (doc_e!=doc1) {
|
||||
if (doc_e->type_u8==DOCT_TEXT) {
|
||||
doc_sorted1[i]=doc_e;
|
||||
doc_unsorted1[i++]=doc_e;
|
||||
}
|
||||
doc_e=doc_e->next;
|
||||
}
|
||||
doc_unsorted1[i]=doc1;
|
||||
QSortI64(doc_sorted1,cnt1,&DiffEntriesCompare);
|
||||
|
||||
doc_sorted2=MAlloc(cnt2*sizeof(CDocEntry *));
|
||||
doc_unsorted2=MAlloc((cnt2+1)*sizeof(CDocEntry *));
|
||||
i=0;
|
||||
doc_e=doc2->head.next;
|
||||
while (doc_e!=doc2) {
|
||||
if (doc_e->type_u8==DOCT_TEXT) {
|
||||
doc_sorted2[i]=doc_e;
|
||||
doc_unsorted2[i++]=doc_e;
|
||||
}
|
||||
doc_e=doc_e->next;
|
||||
}
|
||||
doc_unsorted2[i]=doc2;
|
||||
QSortI64(doc_sorted2,cnt2,&DiffEntriesCompare);
|
||||
|
||||
res=DiffSub(doc1,&df_flags,0,cnt1,0,cnt2,cnt1,cnt2,
|
||||
doc_sorted1,doc_sorted2,doc_unsorted1,doc_unsorted2);
|
||||
if (df_flags&DF_MODIFIED && !(df_flags&DF_DONT_MODIFIED))
|
||||
DocWrite(doc1);
|
||||
|
||||
if (DiffBins(doc1,doc2)) {
|
||||
"$$RED$$Bin Data is Different$$FG$$\n";
|
||||
res=TRUE;
|
||||
}
|
||||
|
||||
DocDel(doc1);
|
||||
DocDel(doc2);
|
||||
Free(doc_sorted1);
|
||||
Free(doc_sorted2);
|
||||
Free(doc_unsorted1);
|
||||
Free(doc_unsorted2);
|
||||
if (_df_flags)
|
||||
*_df_flags=df_flags;
|
||||
return res;
|
||||
}
|
||||
|
||||
#help_index "Cmd Line (Typically);Info"
|
||||
I64 ZRepCompare(CDirEntry *e1,CDirEntry *e2)
|
||||
{
|
||||
return SignI64(e2->user_data(F64)-e1->user_data(F64));
|
||||
}
|
||||
public U0 ZipRep(U8 *files_find_mask="/*",U8 *fu_flags=NULL,
|
||||
Bool just_text_not_graphics=TRUE)
|
||||
{//Report file compressibility.
|
||||
//Dft is just src files. (Used to spot
|
||||
//src files with redundancy in them.)
|
||||
I64 i=0,cnt,size,fuf_flags=0;
|
||||
CDirEntry *tmpde,*tmpde1,**sort_buf;
|
||||
U8 *buf;
|
||||
CArcCompress *arc;
|
||||
ScanFlags(&fuf_flags,Define("ST_FILE_UTIL_FLAGS"),"+r+F+S");
|
||||
ScanFlags(&fuf_flags,Define("ST_FILE_UTIL_FLAGS"),fu_flags);
|
||||
tmpde=tmpde1=FilesFind(files_find_mask,fuf_flags);
|
||||
cnt=FileCnt(tmpde);
|
||||
sort_buf=MAlloc(sizeof(CDirEntry *)*cnt);
|
||||
while (tmpde) {
|
||||
sort_buf[i++]=tmpde;
|
||||
buf=FileRead(tmpde->full_name,&size);
|
||||
if (just_text_not_graphics)
|
||||
size=StrLen(buf);
|
||||
arc=CompressBuf(buf,size);
|
||||
Free(buf);
|
||||
tmpde->user_data(F64)=100.0*arc->compressed_size/arc->expanded_size;
|
||||
Free(arc);
|
||||
tmpde=tmpde->next;
|
||||
}
|
||||
QSortI64(sort_buf,cnt,&ZRepCompare);
|
||||
for (i=0;i<cnt;i++) {
|
||||
"%4.1f%% %04X ",sort_buf[i]->user_data,sort_buf[i]->size;
|
||||
PutFileLink(sort_buf[i]->full_name);
|
||||
'\n';
|
||||
}
|
||||
Free(sort_buf);
|
||||
DirTreeDel(tmpde1);
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
#help_index "DolDoc/Cmd Line (Typically)"
|
||||
|
||||
U0 CursorRemFile(U8 *filename)
|
||||
{//Rem ASCII 5 cursor from one file.
|
||||
CDoc *doc=DocRead(filename,DOCF_PLAIN_TEXT|DOCF_NO_CURSOR);
|
||||
DocWrite(doc);
|
||||
DocDel(doc);
|
||||
}
|
||||
public U0 CursorRem(U8 *files_find_mask="*")
|
||||
{//Rem ASCII 5 cursor.
|
||||
I64 fuf_flags=0;
|
||||
ScanFlags(&fuf_flags,Define("ST_FILE_UTIL_FLAGS"),"+r+T+f+F+O");
|
||||
CDirEntry *tmpde=FilesFind(files_find_mask,fuf_flags),*tmpde1=tmpde;
|
||||
while (tmpde) {
|
||||
CursorRemFile(tmpde->full_name);
|
||||
Touch(tmpde->full_name,"",,tmpde->datetime);
|
||||
tmpde=tmpde->next;
|
||||
}
|
||||
DirTreeDel(tmpde1);
|
||||
}
|
||||
|
||||
U0 CollapseFile(U8 *filename,Bool collapse=TRUE)
|
||||
{//Collapse $LK,"DolDoc",A="FI:::/Doc/DolDocOverview.DD"$ trees in one file.
|
||||
CDoc *doc=DocRead(filename,DOCF_NO_CURSOR);
|
||||
DocCollapse(collapse,doc);
|
||||
DocWrite(doc);
|
||||
DocDel(doc);
|
||||
}
|
||||
public U0 Collapse(U8 *files_find_mask="*",
|
||||
Bool collapse=TRUE,U8 *fu_flags=NULL)
|
||||
{//Collapse $LK,"DolDoc",A="FI:::/Doc/DolDocOverview.DD"$ trees.
|
||||
I64 fuf_flags=0;
|
||||
ScanFlags(&fuf_flags,Define("ST_FILE_UTIL_FLAGS"),"+r+f+F+$$+O");
|
||||
ScanFlags(&fuf_flags,Define("ST_FILE_UTIL_FLAGS"),fu_flags);
|
||||
CDirEntry *tmpde=FilesFind(files_find_mask,fuf_flags),*tmpde1=tmpde;
|
||||
while (tmpde && !Bt(&fuf_flags,FUf_CANCEL)) {
|
||||
CollapseFile(tmpde->full_name,collapse);
|
||||
Touch(tmpde->full_name,"",,tmpde->datetime);
|
||||
tmpde=tmpde->next;
|
||||
}
|
||||
DirTreeDel(tmpde1);
|
||||
}
|
||||
|
||||
I64 DocOptEntry(CDoc *,CDocEntry *doc_e,I64 fuf_flags)
|
||||
{
|
||||
U8 *st,*st2,**_dst;
|
||||
I64 i,res=0;
|
||||
|
||||
if (doc_e->de_flags&DOCEF_LINK && doc_e->de_flags&(DOCEF_AUX_STR|DOCEF_TAG)) {
|
||||
if (doc_e->de_flags & DOCEF_AUX_STR && doc_e->de_flags & DOCEF_TAG &&
|
||||
!MemCmp(doc_e->aux_str,"FI:",3) &&
|
||||
!StrCmp(doc_e->aux_str+3,doc_e->tag)) {
|
||||
Free(doc_e->aux_str);
|
||||
doc_e->aux_str=NULL;
|
||||
doc_e->de_flags&=~DOCEF_AUX_STR;
|
||||
res++;
|
||||
}
|
||||
if (doc_e->de_flags & DOCEF_AUX_STR)
|
||||
_dst=&doc_e->aux_str;
|
||||
else
|
||||
_dst=&doc_e->tag;
|
||||
if (StrMatch(".Z",*_dst)) {
|
||||
st=DocLinkFile(*_dst);
|
||||
if (FileFind(st)) {
|
||||
if (IsDotZ(st))
|
||||
st[StrLen(st)-2]=0;
|
||||
i=StrLen(st);
|
||||
if ((st2=StrMatch(st,*_dst)) && st2[i]=='.' && st2[i+1]=='Z') {
|
||||
StrCpy(st2+i,st2+i+2);
|
||||
res++;
|
||||
}
|
||||
}
|
||||
Free(st);
|
||||
}
|
||||
if (fuf_flags&FUF_RISKY) {
|
||||
if (doc_e->de_flags & DOCEF_AUX_STR) {
|
||||
if (st=StrMatch(".Z",doc_e->aux_str)) {
|
||||
StrCpy(st,st+2);
|
||||
res++;
|
||||
}
|
||||
}
|
||||
if (doc_e->de_flags&DOCEF_TAG) {
|
||||
if (st=StrMatch(".Z",doc_e->tag)) {
|
||||
StrCpy(st,st+2);
|
||||
res++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
I64 DocOptDoc(CDoc *doc,I64 fuf_flags)
|
||||
{//Optimize Doc.
|
||||
Bool unlock=DocLock(doc);
|
||||
I64 res=0;
|
||||
CDocEntry *doc_e,*doc_e1,*doc_e_last;
|
||||
DocRecalc(doc);
|
||||
doc_e_last=NULL;
|
||||
doc_e=doc->head.next;
|
||||
while (doc_e!=doc) {
|
||||
doc_e1=doc_e->next;
|
||||
if (res+=DocOptEntry(doc,doc_e,fuf_flags))
|
||||
res+=DocOptEntry(doc,doc_e,fuf_flags);
|
||||
if (doc_e_last && doc_e_last->type&~0xFF00==doc_e->type&~0xFF00 &&
|
||||
doc_e_last->de_flags==doc_e->de_flags &&
|
||||
Bt(doldoc.type_flags_chk_dup,doc_e->type_u8) &&
|
||||
doc_e_last->attr==doc_e->attr) {
|
||||
DocEntryDel(doc,doc_e);
|
||||
res++;
|
||||
} else
|
||||
doc_e_last=doc_e;
|
||||
doc_e=doc_e1;
|
||||
}
|
||||
DocRecalc(doc);
|
||||
if (unlock)
|
||||
DocUnlock(doc);
|
||||
return res;
|
||||
}
|
||||
I64 DocOptFile(U8 *filename,I64 fuf_flags)
|
||||
{//Optimize file.
|
||||
I64 res;
|
||||
CDoc *doc=DocRead(filename);
|
||||
if (res=DocOptDoc(doc,fuf_flags)) {
|
||||
"-%d:%s\n",res,doc->filename.name;
|
||||
DocWrite(doc);
|
||||
}
|
||||
DocDel(doc);
|
||||
return res;
|
||||
}
|
||||
I64 DocOptLst(CDirEntry *tmpde,I64 fuf_flags)
|
||||
{
|
||||
I64 res=0;
|
||||
CDirEntry *tmpde1;
|
||||
while (tmpde) {
|
||||
tmpde1=tmpde->next;
|
||||
if (tmpde->attr & RS_ATTR_DIR) {
|
||||
if (tmpde->sub) {
|
||||
"Scanning Directory: %s\n",tmpde->full_name;
|
||||
res+=DocOptLst(tmpde->sub,fuf_flags);
|
||||
}
|
||||
} else
|
||||
res+=DocOptFile(tmpde->full_name,fuf_flags);
|
||||
DirEntryDel(tmpde);
|
||||
tmpde=tmpde1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
public I64 DocOpt(U8 *files_find_mask="*",U8 *fu_flags=NULL)
|
||||
{//Optimize $LK,"DolDoc",A="FI:::/Doc/DolDocOverview.DD"$ files, eliminating aux_str's and .Z's.
|
||||
//+R flag for aggressively risky.
|
||||
I64 fuf_flags=0;
|
||||
ScanFlags(&fuf_flags,Define("ST_FILE_UTIL_FLAGS"),"+r+$$");
|
||||
ScanFlags(&fuf_flags,Define("ST_FILE_UTIL_FLAGS"),fu_flags);
|
||||
return DocOptLst(FilesFind(files_find_mask,fuf_flags&FUG_FILES_FIND),
|
||||
fuf_flags&~FUG_FILES_FIND);
|
||||
}
|
||||
@@ -0,0 +1,343 @@
|
||||
#help_index "Graphics/Windows BMP Files"
|
||||
|
||||
#define BMP_COLORS_NUM 16
|
||||
|
||||
class CFileBMP
|
||||
{
|
||||
U16 type;
|
||||
U32 file_size;
|
||||
U32 reserved;
|
||||
U32 data_offset;
|
||||
|
||||
U32 header_size;
|
||||
U32 width;
|
||||
U32 height;
|
||||
U16 planes;
|
||||
U16 bit_cnt;
|
||||
U32 compression;
|
||||
U32 image_size;
|
||||
U32 x_pixs_per_meter;
|
||||
U32 y_pixs_per_meter;
|
||||
U32 colors_used;
|
||||
U32 important_colors;
|
||||
|
||||
U0 end;
|
||||
|
||||
CBGR24 palette[BMP_COLORS_NUM];
|
||||
};
|
||||
|
||||
public CFileBMP *BMP4To(CDC *dc)
|
||||
{//To Windows 4-bit BMP.
|
||||
U8 *src,*ptr;
|
||||
CBGR48 palette[COLORS_NUM];
|
||||
I64 i,x,y,w=dc->width>>1,
|
||||
size=sizeof(CFileBMP)+dc->width*dc->height>>1;
|
||||
CFileBMP *bmp =CAlloc(size);
|
||||
bmp->type ='BM';
|
||||
bmp->planes =1;
|
||||
bmp->file_size =size;
|
||||
bmp->data_offset=sizeof(CFileBMP);
|
||||
bmp->header_size=offset(CFileBMP.end)-offset(CFileBMP.header_size);
|
||||
bmp->width =dc->width;
|
||||
bmp->height =dc->height;
|
||||
bmp->bit_cnt =4;
|
||||
bmp->image_size =dc->width*dc->height>>1;
|
||||
GrPaletteGet(palette);
|
||||
#assert COLORS_NUM==BMP_COLORS_NUM
|
||||
for (i=0;i<BMP_COLORS_NUM;i++) {
|
||||
bmp->palette[i].b=palette[i].b>>8;
|
||||
bmp->palette[i].g=palette[i].g>>8;
|
||||
bmp->palette[i].r=palette[i].r>>8;
|
||||
bmp->palette[i].pad=0;
|
||||
}
|
||||
ptr=bmp(U8 *)+bmp->data_offset;
|
||||
for (y=dc->height-1;y>=0;y--) {
|
||||
src=y*dc->width_internal+dc->body;
|
||||
for (x=0;x<w;x++) {
|
||||
*ptr|=(*src++&15)<<4;
|
||||
*ptr|=*src++&15;
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
return bmp;
|
||||
}
|
||||
|
||||
public CFileBMP *BMPRLE4To(CDC *dc)
|
||||
{//To Windows RLE4 bit BMP.
|
||||
U8 *src,*ptr,*start;
|
||||
I64 i,x,y,w=dc->width,cnt,pattern;
|
||||
CBGR48 palette[COLORS_NUM];
|
||||
CFileBMP *bmp =CAlloc(sizeof(CFileBMP)+2*(dc->width+1)*dc->height);
|
||||
bmp->type ='BM';
|
||||
bmp->planes =1;
|
||||
bmp->data_offset=sizeof(CFileBMP);
|
||||
bmp->header_size=offset(CFileBMP.end)-offset(CFileBMP.header_size);
|
||||
bmp->width =dc->width;
|
||||
bmp->height =dc->height;
|
||||
bmp->bit_cnt =4;
|
||||
bmp->compression=2; //RLE4
|
||||
GrPaletteGet(palette);
|
||||
#assert COLORS_NUM==BMP_COLORS_NUM
|
||||
for (i=0;i<BMP_COLORS_NUM;i++) {
|
||||
bmp->palette[i].b=palette[i].b>>8;
|
||||
bmp->palette[i].g=palette[i].g>>8;
|
||||
bmp->palette[i].r=palette[i].r>>8;
|
||||
bmp->palette[i].pad=0;
|
||||
}
|
||||
start=ptr=bmp(U8 *)+bmp->data_offset;
|
||||
for (y=dc->height-1;y>=0;y--) {
|
||||
src=y*dc->width_internal+dc->body;
|
||||
x=0;
|
||||
while (x<w) {
|
||||
pattern=(src[0]&15)<<4+src[1]&15;
|
||||
if (x+1<w && src[0]&15==src[1]&15) {
|
||||
src+=2;
|
||||
cnt=2;
|
||||
x+=2;
|
||||
while (x<w && cnt<U8_MAX) {
|
||||
if (*src&15==pattern&15) {
|
||||
src++;
|
||||
cnt++;
|
||||
x++;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
src+=2;
|
||||
if (x+1<w)
|
||||
cnt=2;
|
||||
else
|
||||
cnt=1;
|
||||
x+=2;
|
||||
}
|
||||
*ptr++=cnt;
|
||||
*ptr++=pattern;
|
||||
}
|
||||
*ptr(U16 *)++=0;
|
||||
}
|
||||
bmp->image_size=ptr-start;
|
||||
bmp->file_size=sizeof(CFileBMP)+bmp->image_size;
|
||||
return bmp;
|
||||
}
|
||||
|
||||
public CFileBMP *BMP24To(CDC *dc)
|
||||
{//To Windows 24-bit BMP.
|
||||
U8 *src;
|
||||
I64 i,x,y,size=offset(CFileBMP.end)+dc->width*dc->height*sizeof(CBGR24);
|
||||
CBGR24 *bgr;
|
||||
CFileBMP *bmp =CAlloc(size);
|
||||
bmp->type ='BM';
|
||||
bmp->planes =1;
|
||||
bmp->file_size =size;
|
||||
bmp->data_offset=offset(CFileBMP.end);
|
||||
bmp->header_size=offset(CFileBMP.end)-offset(CFileBMP.header_size);
|
||||
bmp->width =dc->width;
|
||||
bmp->height =dc->height;
|
||||
bmp->bit_cnt =32;
|
||||
bmp->image_size =dc->width*dc->height<<2;
|
||||
|
||||
bgr=bmp(U8 *)+bmp->data_offset;
|
||||
for (y=dc->height-1;y>=0;y--) {
|
||||
src=y*dc->width_internal+dc->body;
|
||||
for (x=0;x<dc->width;x++) {
|
||||
i=*src++;
|
||||
if (i&BLUE) bgr->b=0x7F;
|
||||
if (i&GREEN) bgr->g=0x7F;
|
||||
if (i&RED) bgr->r=0x7F;
|
||||
if (i&8) {
|
||||
if (bgr->b) bgr->b=0xFF;
|
||||
if (bgr->g) bgr->g=0xFF;
|
||||
if (bgr->r) bgr->r=0xFF;
|
||||
}
|
||||
bgr(U8 *)+=4;
|
||||
}
|
||||
}
|
||||
return bmp;
|
||||
}
|
||||
|
||||
public I64 BMPWrite(U8 *filename,CDC *dc,I64 bits=4)
|
||||
{//Window's BMP Files.
|
||||
I64 size;
|
||||
CFileBMP *bmp;
|
||||
if (bits==4) {
|
||||
if (IsDotZ(filename)) //.Z compression is better than RLE
|
||||
bmp=BMP4To(dc);
|
||||
else {
|
||||
bmp=BMPRLE4To(dc);
|
||||
if (bmp->file_size>sizeof(CFileBMP)+dc->width*dc->height>>1) {
|
||||
Free(bmp);
|
||||
bmp=BMP4To(dc);
|
||||
}
|
||||
}
|
||||
} else if (bits==24)
|
||||
bmp=BMP24To(dc);
|
||||
else {
|
||||
"Format Not Supported.\n";
|
||||
return 0;
|
||||
}
|
||||
size=bmp->file_size;
|
||||
FileWrite(filename,bmp,bmp->file_size);
|
||||
Free(bmp);
|
||||
return size;
|
||||
}
|
||||
|
||||
U8 *BMPPaletteNew(CFileBMP *bmp)
|
||||
{
|
||||
I64 i,j,best,score,best_score;
|
||||
CBGR48 palette[COLORS_NUM];
|
||||
U8 *res=CAlloc(BMP_COLORS_NUM*sizeof(U8));
|
||||
GrPaletteGet(palette);
|
||||
#assert COLORS_NUM==BMP_COLORS_NUM
|
||||
for (i=0;i<BMP_COLORS_NUM;i++) {
|
||||
best=i;
|
||||
best_score=I64_MAX;
|
||||
for (j=0;j<BMP_COLORS_NUM;j++) {
|
||||
score=SqrI64(bmp->palette[i].r-palette[j].r>>8)+
|
||||
SqrI64(bmp->palette[i].g-palette[j].g>>8)+
|
||||
SqrI64(bmp->palette[i].b-palette[j].b>>8);
|
||||
if (score<best_score) {
|
||||
best=j;
|
||||
best_score=score;
|
||||
}
|
||||
}
|
||||
res[i]=best;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
U8 ms_paint_palette[BMP_COLORS_NUM]={0,4,2,6,1,5,3,8,7,12,10,14,9,13,11,15};
|
||||
|
||||
I64 BMP24Color(CBGR24 *ptr,Bool dither_probability)
|
||||
{
|
||||
I64 res,k;
|
||||
if (dither_probability) {
|
||||
k=RandU32;
|
||||
if (SqrI64(ptr->r)+SqrI64(ptr->g)+SqrI64(ptr->b)>=3*SqrI64(k.u8[0]))
|
||||
res=8;
|
||||
else
|
||||
res=0;
|
||||
if (ptr->r>=k.u8[1]) res|=RED;
|
||||
if (ptr->g>=k.u8[2]) res|=GREEN;
|
||||
if (ptr->b>=k.u8[3]) res|=BLUE;
|
||||
} else {
|
||||
if (SqrI64(ptr->r)+SqrI64(ptr->g)+SqrI64(ptr->b)>=SqrI64(0x80)) {
|
||||
res=8;
|
||||
if (ptr->r>=0x80) res|=RED;
|
||||
if (ptr->g>=0x80) res|=GREEN;
|
||||
if (ptr->b>=0x80) res|=BLUE;
|
||||
} else {
|
||||
res=0;
|
||||
if (ptr->r>=0x40) res|=RED;
|
||||
if (ptr->g>=0x40) res|=GREEN;
|
||||
if (ptr->b>=0x40) res|=BLUE;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public CDC *BMPRead(U8 *filename,Bool dither_probability=FALSE,
|
||||
Bool use_ms_paint_palette=FALSE)
|
||||
{//Window's BMP Files.
|
||||
I64 i,j,cnt;
|
||||
U8 *palette_map,*ptr;
|
||||
Bool rle;
|
||||
CFileBMP *bmp;
|
||||
CDC *res=NULL;
|
||||
if (ptr=FileRead(filename)) {
|
||||
bmp=ptr;
|
||||
if (0<bmp->width<I32_MAX && 0<bmp->height<I32_MAX) {
|
||||
res=DCNew(bmp->width,bmp->height);
|
||||
ptr+=bmp->data_offset;
|
||||
if (bmp->compression==2)
|
||||
rle=TRUE;
|
||||
else
|
||||
rle=FALSE;
|
||||
if (use_ms_paint_palette)
|
||||
palette_map=ms_paint_palette;
|
||||
else
|
||||
palette_map=BMPPaletteNew(bmp);
|
||||
if (bmp->bit_cnt==4) {
|
||||
for (i=bmp->height-1;i>=0;i--)
|
||||
if (rle) {//We don't support full RLE4, just our own subset
|
||||
j=0;
|
||||
while (cnt=*ptr++) {
|
||||
if (cnt==1) {
|
||||
res->color=palette_map[*ptr++&15];
|
||||
GrPlot(res,j++,i);
|
||||
} else {
|
||||
if (cnt==2 && *ptr>>4!=*ptr&15) {
|
||||
res->color=palette_map[*ptr&15];
|
||||
GrPlot(res,j+1,i);
|
||||
res->color=palette_map[*ptr>>4];
|
||||
GrPlot(res,j,i);
|
||||
ptr++;
|
||||
j+=2;
|
||||
} else {
|
||||
res->color=palette_map[*ptr++&15];
|
||||
while (cnt--)
|
||||
GrPlot(res,j++,i);
|
||||
}
|
||||
}
|
||||
}
|
||||
ptr++;
|
||||
} else
|
||||
for (j=0;j<(bmp->width+7)&~7;) {
|
||||
res->color=palette_map[*ptr&15];
|
||||
GrPlot(res,j+1,i);
|
||||
res->color=palette_map[*ptr>>4];
|
||||
GrPlot(res,j,i);
|
||||
ptr++;
|
||||
j+=2;
|
||||
}
|
||||
if (!use_ms_paint_palette)
|
||||
Free(palette_map);
|
||||
} else if (bmp->bit_cnt==24) {
|
||||
for (i=bmp->height-1;i>=0;i--) {
|
||||
for (j=0;j<bmp->width;j++,ptr+=3) {
|
||||
res->color=BMP24Color(ptr,dither_probability);
|
||||
GrPlot(res,j,i);
|
||||
}
|
||||
ptr+=bmp->width&3;
|
||||
}
|
||||
if (!use_ms_paint_palette)
|
||||
Free(palette_map);
|
||||
} else if (bmp->bit_cnt>=32) {
|
||||
for (i=bmp->height-1;i>=0;i--)
|
||||
for (j=0;j<bmp->width;j++,ptr+=4) {
|
||||
res->color=BMP24Color(ptr,dither_probability);
|
||||
GrPlot(res,j,i);
|
||||
}
|
||||
if (!use_ms_paint_palette)
|
||||
Free(palette_map);
|
||||
} else {
|
||||
"Format Not Supported.\n";
|
||||
DCDel(res);
|
||||
res=NULL;
|
||||
}
|
||||
} else
|
||||
"Invalid BMP File\n";
|
||||
Free(bmp);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
#help_index "Graphics/Sprite;Graphics/Windows BMP Files;"\
|
||||
"DolDoc/Output;StdOut/DolDoc"
|
||||
public U0 DocBMP(CDoc *doc=NULL,U8 *filename,Bool dither_probability=FALSE,
|
||||
Bool use_ms_paint_palette=FALSE)
|
||||
{//Put a BMP file into a document as a sprite.
|
||||
CDC *dc=BMPRead(filename,dither_probability,use_ms_paint_palette);
|
||||
U8 *elems=DC2Sprite(dc);
|
||||
DocSprite(doc,elems);
|
||||
Free(elems);
|
||||
DCDel(dc);
|
||||
}
|
||||
|
||||
#help_index "Graphics/Windows BMP Files;Graphics/Scrn"
|
||||
public I64 BMPScrnCapture(U8 *filename,I64 bits=4,Bool include_zoom=TRUE)
|
||||
{//Capture scrn as BMP file.
|
||||
CDC *dc=DCScrnCapture(include_zoom);
|
||||
I64 size=BMPWrite(filename,dc,bits);
|
||||
DCDel(dc);
|
||||
return size;
|
||||
}
|
||||
@@ -0,0 +1,257 @@
|
||||
#help_index "Cmd Line (Typically)"
|
||||
|
||||
#define FND_REPLACE 0
|
||||
#define FND_SKIP 1
|
||||
#define FND_ALL 2
|
||||
#define FND_ED 3
|
||||
#define FND_ABORT_FILE 4
|
||||
#define FND_SKIP_FILE 5
|
||||
|
||||
I64 PopUpFindMenu()
|
||||
{
|
||||
I64 i;
|
||||
CDoc *doc=DocNew;
|
||||
DocPrint(doc,"$$CM+LX,2,4$$$$BT,\"REPLACE\",LE=FND_REPLACE$$"
|
||||
"$$CM+LX,22,0$$$$BT,\"SKIP\",LE=FND_SKIP$$"
|
||||
"$$CM+LX,2,4$$$$BT,\"ALL\",LE=FND_ALL$$"
|
||||
"$$CM+LX,22,0$$$$BT,\"ABORT ALL\",LE=DOCM_CANCEL$$"
|
||||
"$$CM+LX,2,4$$$$BT,\"EDIT\",LE=FND_ED$$"
|
||||
"$$CM+LX,22,0$$$$BT,\"ABORT FILE\",LE=FND_ABORT_FILE$$"
|
||||
"$$CM+LX,2,4$$$$BT,\"SKIP FILE\",LE=FND_SKIP_FILE$$\n");
|
||||
i=PopUpMenu(doc);
|
||||
DocDel(doc);
|
||||
return i;
|
||||
}
|
||||
|
||||
I64 FindFile(U8 *needle_str,U8 *haystack_filename,
|
||||
I64 *_fuf_flags,U8 *replace_text)
|
||||
{//Have you confused with $LK,"FileFind",A="MN:FileFind"$()?
|
||||
Bool first_on_line,write_this_file=FALSE,cont=!Bt(_fuf_flags,FUf_CANCEL);
|
||||
U8 *src,*dst,*dst2,*name_buf=NULL;
|
||||
I64 i,j,plen,rlen,dlen,cnt=0,old_flags,ss_flags;
|
||||
CDoc *cur_l,*doc=DocRead(haystack_filename,
|
||||
DOCF_PLAIN_TEXT_TABS|DOCF_NO_CURSOR);
|
||||
CDocEntry *doc_e;
|
||||
|
||||
if (Bt(_fuf_flags,FUf_IGNORE))
|
||||
ss_flags=SFF_IGNORE_CASE;
|
||||
else
|
||||
ss_flags=0;
|
||||
if (Bt(_fuf_flags,FUf_WHOLE_LABELS))
|
||||
ss_flags|=SFG_WHOLE_LABELS;
|
||||
if (Bt(_fuf_flags,FUf_WHOLE_LABELS_BEFORE))
|
||||
ss_flags|=SFF_WHOLE_LABELS_BEFORE;
|
||||
if (Bt(_fuf_flags,FUf_WHOLE_LABELS_AFTER))
|
||||
ss_flags|=SFF_WHOLE_LABELS_AFTER;
|
||||
|
||||
plen=StrLen(needle_str);
|
||||
if (replace_text)
|
||||
rlen=StrLen(replace_text);
|
||||
doc_e=doc->head.next;
|
||||
while (doc_e!=doc && cont) {
|
||||
if (doc_e->type_u8==DOCT_TEXT) {
|
||||
src=doc_e->tag;
|
||||
first_on_line=TRUE;
|
||||
while (src && cont) {
|
||||
if (src=StrFind(needle_str,src,ss_flags)) {
|
||||
cnt++;
|
||||
if (first_on_line || Bt(_fuf_flags,FUf_REPLACE)) {
|
||||
first_on_line=FALSE;
|
||||
PutFileLink(haystack_filename,,doc_e->y+1,TRUE);
|
||||
name_buf=MStrPrint("%s,%d",haystack_filename,doc_e->y+1);
|
||||
if (cur_l=DocPut) {
|
||||
old_flags=cur_l->flags&DOCF_PLAIN_TEXT;
|
||||
cur_l->flags|=DOCF_PLAIN_TEXT;
|
||||
}
|
||||
" %s\n",doc_e->tag;
|
||||
if (cur_l)
|
||||
cur_l->flags= cur_l->flags&~DOCF_PLAIN_TEXT |old_flags;
|
||||
}
|
||||
if (Bt(_fuf_flags,FUf_REPLACE)) {
|
||||
if (Bt(_fuf_flags,FUf_ALL))
|
||||
i=FND_ALL;
|
||||
else {
|
||||
i=PopUpFindMenu;
|
||||
if (i<0) {
|
||||
LBts(_fuf_flags,FUf_CANCEL);
|
||||
cont=FALSE;
|
||||
write_this_file=FALSE;
|
||||
} else if (i==FND_ALL)
|
||||
LBts(_fuf_flags,FUf_ALL);
|
||||
else if (i==FND_ABORT_FILE) {
|
||||
cont=FALSE;
|
||||
write_this_file=FALSE;
|
||||
} else if (i==FND_SKIP_FILE)
|
||||
cont=FALSE;
|
||||
}
|
||||
if (i==FND_REPLACE || i==FND_ALL) {
|
||||
dlen=StrLen(doc_e->tag);
|
||||
dst=MAlloc(dlen+1+rlen-plen);
|
||||
dst2=dst;
|
||||
j=src-doc_e->tag;
|
||||
for (i=0;i<j;i++)
|
||||
*dst++=doc_e->tag[i];
|
||||
for (i=0;i<rlen;i++)
|
||||
*dst++=replace_text[i];
|
||||
src=dst;
|
||||
for (i=j+plen;i<=dlen;i++)
|
||||
*dst++=doc_e->tag[i];
|
||||
Free(doc_e->tag);
|
||||
doc_e->tag=dst2;
|
||||
if (cur_l=DocPut) {
|
||||
old_flags=cur_l->flags&DOCF_PLAIN_TEXT;
|
||||
cur_l->flags|=DOCF_PLAIN_TEXT;
|
||||
}
|
||||
"%12s,%04d*%s\n",haystack_filename,doc_e->y+1,dst2;
|
||||
if (cur_l)
|
||||
cur_l->flags= cur_l->flags&~DOCF_PLAIN_TEXT |old_flags;
|
||||
write_this_file=TRUE;
|
||||
} else {
|
||||
src++;
|
||||
if (i==FND_ED) {
|
||||
Free(name_buf);
|
||||
name_buf=StrNew(doc->filename.name);
|
||||
doc->flags&=~DOCF_NO_CURSOR;
|
||||
doc->cur_entry=doc_e;
|
||||
doc->cur_col=doc_e->min_col;
|
||||
DocWrite(doc);
|
||||
DocDel(doc);
|
||||
"Wrote:%s\n",name_buf;
|
||||
Ed(name_buf);
|
||||
doc=DocRead(name_buf, DOCF_PLAIN_TEXT_TABS);
|
||||
doc_e=doc->cur_entry;
|
||||
if (doc_e->last!=doc) doc_e=doc_e->last;
|
||||
src=NULL;
|
||||
write_this_file=FALSE;
|
||||
}
|
||||
}
|
||||
} else
|
||||
src++;
|
||||
Free(name_buf);
|
||||
name_buf=NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
doc_e=doc_e->next;
|
||||
}
|
||||
if (write_this_file) {
|
||||
DocWrite(doc);
|
||||
"Wrote:%s\n",doc->filename.name;
|
||||
}
|
||||
DocDel(doc);
|
||||
return cnt;
|
||||
}
|
||||
|
||||
public I64 Find(U8 *needle_str,U8 *files_find_mask="*",
|
||||
U8 *fu_flags=NULL,U8 *replace_text=NULL)
|
||||
{/*Find occurrences of a string in files.
|
||||
This does not do regular expressions.
|
||||
Anyway, it's good for searching and replacing.
|
||||
Let's say it stands for global replace ;-)
|
||||
|
||||
"+r" =recurse
|
||||
"+i" =ignore case
|
||||
"+l" =whole labels only.
|
||||
This will check for a nonlabel character before
|
||||
and after. If you have a var, "dd" and don't
|
||||
want to match words like "Add", you
|
||||
set this flag and it will see that the characters
|
||||
before or after "dd" are label characters.
|
||||
"+lb"=only checks for label chars before.
|
||||
"+la"=only checks for label chars after.
|
||||
*/
|
||||
I64 cnt=0,fuf_flags=0;
|
||||
CDirEntry *tmpde,*tmpde1;
|
||||
ScanFlags(&fuf_flags,Define("ST_FILE_UTIL_FLAGS"),"+r+i+f+F+T");
|
||||
ScanFlags(&fuf_flags,Define("ST_FILE_UTIL_FLAGS"),fu_flags);
|
||||
if (fuf_flags&~(FUG_FILES_FIND|FUF_IGNORE|FUF_ALL|
|
||||
FUF_WHOLE_LABELS|FUF_WHOLE_LABELS_BEFORE|FUF_WHOLE_LABELS_AFTER))
|
||||
throw('FUF');
|
||||
LBEqu(&fuf_flags,FUf_REPLACE,replace_text);
|
||||
tmpde=tmpde1=FilesFind(files_find_mask,fuf_flags&FUG_FILES_FIND);
|
||||
fuf_flags&=FUF_ALL|FUF_REPLACE|FUF_IGNORE|FUF_WHOLE_LABELS|
|
||||
FUF_WHOLE_LABELS_BEFORE|FUF_WHOLE_LABELS_AFTER;
|
||||
while (tmpde && !Bt(&fuf_flags,FUf_CANCEL)) {
|
||||
cnt+=FindFile(needle_str,tmpde->full_name,&fuf_flags,replace_text);
|
||||
tmpde=tmpde->next;
|
||||
}
|
||||
DirTreeDel(tmpde1);
|
||||
return cnt;
|
||||
}
|
||||
|
||||
public I64 FileOcc(U8 *needle_str,
|
||||
U8 *files_find_mask="*",U8 *fu_flags="+r+i+l")
|
||||
{/*Silently return occurrences of a string in files.
|
||||
"+r"=recurse
|
||||
"+i"=ignore case
|
||||
"+l"=whole labels only.
|
||||
"+lb"=only checks for label chars before.
|
||||
"+la"=only checks for label chars after.
|
||||
*/
|
||||
I64 cnt=0;
|
||||
Bool old_silent=Silent(TRUE);
|
||||
cnt=Find(needle_str,files_find_mask,fu_flags);
|
||||
Silent(old_silent);
|
||||
return cnt;
|
||||
}
|
||||
|
||||
class CFind
|
||||
{
|
||||
U8 find_text[STR_LEN] fmtstr "$$DA-P,"
|
||||
"A=\"FIND :%s\"$$\n";
|
||||
U8 replace_text[STR_LEN] fmtstr "$$DA-P,"
|
||||
"A=\"REPLACE :%s\"$$\n";
|
||||
Bool replace fmtstr "$$CB,\"REPLACE\"$$\n";
|
||||
Bool match_case fmtstr "$$CB,\"MATCH CASE\"$$\n";
|
||||
Bool whole_labels fmtstr "$$CB,\"WHOLE LABELS\"$$\n";
|
||||
U8 filemask[STR_LEN] fmtstr "$$DA-P,A=\"FILE MASK :%s\"$$\n";
|
||||
Bool recurse fmtstr "$$CB,\"RECURSE\"$$\n";
|
||||
};
|
||||
|
||||
I64 FindWiz()
|
||||
{
|
||||
CDoc *doc;
|
||||
U8 buf[32],*dir,*st;
|
||||
CFind *g=CAlloc(sizeof(CFind));
|
||||
I64 res=0;
|
||||
g->recurse=TRUE;
|
||||
StrCpy(g->filemask,FILEMASK_TXT);
|
||||
if (doc=DocPut) {
|
||||
StrCpy(g->find_text,doc->find_replace->find_text);
|
||||
StrCpy(g->replace_text,doc->find_replace->replace_text);
|
||||
g->replace=doc->find_replace->replace;
|
||||
g->match_case=doc->find_replace->match_case;
|
||||
g->whole_labels=doc->find_replace->whole_labels;
|
||||
}
|
||||
if (DocForm(g,,0,"$$PURPLE$$$$TX+CX,\"Find\"$$\n$$FG$$")) {
|
||||
if (doc) {
|
||||
StrCpy(doc->find_replace->find_text,g->find_text);
|
||||
StrCpy(doc->find_replace->replace_text,g->replace_text);
|
||||
doc->find_replace->replace=g->replace;
|
||||
doc->find_replace->match_case=g->match_case;
|
||||
doc->find_replace->whole_labels=g->whole_labels;
|
||||
}
|
||||
dir=PopUpPickDir;
|
||||
if (*dir) {
|
||||
*buf=0;
|
||||
if (g->match_case)
|
||||
CatPrint(buf,"-i");
|
||||
if (!g->recurse)
|
||||
CatPrint(buf,"-r");
|
||||
if (g->whole_labels)
|
||||
CatPrint(buf,"+l");
|
||||
if (g->replace)
|
||||
st=MStrPrint("\"$$$$WW+H,1$$$$\";Cd(\"%s\");"
|
||||
"Find(\"%Q\",\"%Q\",\"%Q\",\"%Q\");UserTaskCont;",
|
||||
dir,g->find_text,g->filemask,buf,g->replace_text);
|
||||
else
|
||||
st=MStrPrint("\"$$$$WW+H,1$$$$\";Cd(\"%s\");"
|
||||
"Find(\"%Q\",\"%Q\",\"%Q\");UserTaskCont;",
|
||||
dir,g->find_text,g->filemask,buf);
|
||||
res=PopUp(st);
|
||||
}
|
||||
Free(dir);
|
||||
}
|
||||
Free(g);
|
||||
return res;
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
#help_index "Debugging/Heap;Memory/Debugging"
|
||||
#help_file "::/Doc/HeapDbg"
|
||||
|
||||
#define HL_CALLER_DEPTH 5 //Feel free to change this.
|
||||
#define HL_HASH_SIZE 0x1000
|
||||
|
||||
class CHeapLog
|
||||
{
|
||||
CHeapLog *next,*last;
|
||||
union {
|
||||
U8 *addr;
|
||||
I64 size;
|
||||
}
|
||||
I64 cnt;
|
||||
U8 *caller[HL_CALLER_DEPTH];
|
||||
};
|
||||
|
||||
class CHeapLogHash
|
||||
{
|
||||
CHeapLog *next,*last;
|
||||
};
|
||||
|
||||
CHeapCtrl *heaplog_hc_watched,*heaplog_hc=NULL;
|
||||
CHeapLogHash *heaplog_head=NULL;
|
||||
|
||||
U0 HeapLogMAlloc(U8 *addr)
|
||||
{
|
||||
CHeapLog *tmphl;
|
||||
I64 i;
|
||||
if (MHeapCtrl(addr)==heaplog_hc_watched) {
|
||||
tmphl=MAlloc(sizeof(CHeapLog),heaplog_hc);
|
||||
tmphl->addr=addr;
|
||||
for (i=0;i<HL_CALLER_DEPTH;i++)
|
||||
tmphl->caller[i]=Caller(i+2);
|
||||
i=addr>>3 &(HL_HASH_SIZE-1);
|
||||
PUSHFD
|
||||
CLI
|
||||
while (LBts(&sys_semas[SEMA_HEAPLOG_LOCK],0))
|
||||
PAUSE
|
||||
QueIns(tmphl,heaplog_head[i].last);
|
||||
LBtr(&sys_semas[SEMA_HEAPLOG_LOCK],0);
|
||||
POPFD
|
||||
}
|
||||
}
|
||||
|
||||
U0 HeapLogFree(U8 *addr)
|
||||
{
|
||||
I64 i;
|
||||
CHeapLog *tmphl;
|
||||
if (!addr) return;
|
||||
if (MHeapCtrl(addr)==heaplog_hc_watched) {
|
||||
i=addr>>3 &(HL_HASH_SIZE-1);
|
||||
PUSHFD
|
||||
CLI
|
||||
while (LBts(&sys_semas[SEMA_HEAPLOG_LOCK],0))
|
||||
PAUSE
|
||||
tmphl=heaplog_head[i].next;
|
||||
while (tmphl!=&heaplog_head[i]) {
|
||||
if (addr==tmphl->addr) {
|
||||
QueRem(tmphl);
|
||||
LBtr(&sys_semas[SEMA_HEAPLOG_LOCK],0);
|
||||
POPFD
|
||||
Free(tmphl);
|
||||
return;
|
||||
}
|
||||
tmphl=tmphl->next;
|
||||
}
|
||||
LBtr(&sys_semas[SEMA_HEAPLOG_LOCK],0);
|
||||
POPFD
|
||||
}
|
||||
}
|
||||
|
||||
public Bool HeapLog(Bool val=ON,CTask *task=NULL)
|
||||
{//Turn on. Collect data. Call $LK,"HeapLogAddrRep",A="MN:HeapLogAddrRep"$() or $LK,"HeapLogSizeRep",A="MN:HeapLogSizeRep"$().
|
||||
I64 i;
|
||||
if (val) {
|
||||
if (Bt(&sys_semas[SEMA_HEAPLOG_ACTIVE],0)) {
|
||||
"HeapLog Already Active\n";
|
||||
return TRUE;
|
||||
} else {
|
||||
if (!task) task=Fs;
|
||||
if (TaskValidate(task))
|
||||
heaplog_hc_watched=task->data_heap;
|
||||
else
|
||||
heaplog_hc_watched=task;//Actually, not a task, must be a HeapCtrl.
|
||||
PUSHFD
|
||||
CLI
|
||||
while (LBts(&sys_semas[SEMA_HEAPLOG_LOCK],0))
|
||||
PAUSE
|
||||
heaplog_hc=HeapCtrlInit(,,sys_data_bp);
|
||||
ext[EXT_HEAPLOG_MALLOC]=&HeapLogMAlloc;
|
||||
ext[EXT_HEAPLOG_FREE]=&HeapLogFree;
|
||||
heaplog_head=MAlloc(sizeof(CHeapLogHash)*HL_HASH_SIZE,heaplog_hc);
|
||||
for (i=0;i<HL_HASH_SIZE;i++)
|
||||
QueInit(&heaplog_head[i]);
|
||||
LBtr(&sys_semas[SEMA_HEAPLOG_LOCK],0);
|
||||
POPFD
|
||||
LBts(&sys_semas[SEMA_HEAPLOG_ACTIVE],0);
|
||||
return FALSE;
|
||||
}
|
||||
} else {
|
||||
if (!LBtr(&sys_semas[SEMA_HEAPLOG_ACTIVE],0)) {
|
||||
"HeapLog Not Active\n";
|
||||
return FALSE;
|
||||
} else {
|
||||
HeapCtrlDel(heaplog_hc);
|
||||
heaplog_head=heaplog_hc=NULL;
|
||||
ext[EXT_HEAPLOG_MALLOC]=NULL;
|
||||
ext[EXT_HEAPLOG_FREE]=NULL;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public U0 HeapLogAddrRep(Bool leave_it=OFF)
|
||||
{//Call $LK,"HeapLog",A="MN:HeapLog"$() first and collect data.
|
||||
I64 i,j,total=0;
|
||||
CHeapLog *tmphl,hl;
|
||||
if (!LBtr(&sys_semas[SEMA_HEAPLOG_ACTIVE],0)) {
|
||||
"HeapLog Not Active\n";
|
||||
return;
|
||||
}
|
||||
"$$WW,0$$";
|
||||
while (LBts(&sys_semas[SEMA_HEAPLOG_LOCK],0))
|
||||
PAUSE
|
||||
for (i=0;i<HL_HASH_SIZE;i++) {
|
||||
tmphl=heaplog_head[i].next;
|
||||
while (tmphl!=&heaplog_head[i]) {
|
||||
//Take snapshot in case modified. (while we work)
|
||||
MemCpy(&hl,tmphl,sizeof(CHeapLog));
|
||||
"$$PURPLE$$%08X$$FG$$ %08X",MSize(hl.addr),hl.addr;
|
||||
for (j=0;j<HL_CALLER_DEPTH;j++)
|
||||
" %P",hl.caller[j];
|
||||
'\n';
|
||||
total+=MSize(hl.addr);
|
||||
tmphl=hl.next;
|
||||
}
|
||||
}
|
||||
LBtr(&sys_semas[SEMA_HEAPLOG_LOCK],0);
|
||||
"\n$$LTRED$$Total:%08X$$FG$$\n",total;
|
||||
LBts(&sys_semas[SEMA_HEAPLOG_ACTIVE],0);
|
||||
if (!leave_it)
|
||||
HeapLog(OFF);
|
||||
}
|
||||
|
||||
public U0 HeapLogSizeRep(Bool leave_it=OFF)
|
||||
{//Call $LK,"HeapLog",A="MN:HeapLog"$() first and collect data.
|
||||
I64 i,j,k,total=0;
|
||||
CHeapLog *tmphla,hla,*tmphls,*tmphls1;
|
||||
CHeapLogHash *size_head;
|
||||
if (!LBtr(&sys_semas[SEMA_HEAPLOG_ACTIVE],0)) {
|
||||
"HeapLog Not Active\n";
|
||||
return;
|
||||
}
|
||||
|
||||
size_head=MAlloc(sizeof(CHeapLogHash)*HL_HASH_SIZE,heaplog_hc);
|
||||
for (i=0;i<HL_HASH_SIZE;i++)
|
||||
QueInit(&size_head[i]);
|
||||
|
||||
"$$WW,0$$";
|
||||
while (LBts(&sys_semas[SEMA_HEAPLOG_LOCK],0))
|
||||
PAUSE
|
||||
for (i=0;i<HL_HASH_SIZE;i++) {
|
||||
tmphla=heaplog_head[i].next;
|
||||
while (tmphla!=&heaplog_head[i]) {
|
||||
//Take snapshot in case modified. (while we work)
|
||||
MemCpy(&hla,tmphla,sizeof(CHeapLog));
|
||||
k=(MSize(hla.addr)>>3+hla.caller[0])&(HL_HASH_SIZE-1);
|
||||
tmphls=size_head[k].next;
|
||||
while (tmphls!=&size_head[k]) {
|
||||
if (MSize(hla.addr)==tmphls->size) {
|
||||
for (j=0;j<HL_CALLER_DEPTH;j++)
|
||||
if (hla.caller[j]!=tmphls->caller[j])
|
||||
goto hl_next;
|
||||
tmphls->cnt++;
|
||||
goto hl_found;
|
||||
}
|
||||
hl_next:
|
||||
tmphls=tmphls->next;
|
||||
}
|
||||
tmphls=MAlloc(sizeof(CHeapLog),heaplog_hc);
|
||||
MemCpy(tmphls,&hla,sizeof(CHeapLog));
|
||||
tmphls->cnt=1;
|
||||
tmphls->size=MSize(hla.addr);
|
||||
QueIns(tmphls,size_head[k].last);
|
||||
hl_found:
|
||||
tmphla=hla.next;
|
||||
}
|
||||
}
|
||||
LBtr(&sys_semas[SEMA_HEAPLOG_LOCK],0);
|
||||
|
||||
for (i=0;i<HL_HASH_SIZE;i++) {
|
||||
tmphls=size_head[i].next;
|
||||
while (tmphls!=&size_head[i]) {
|
||||
tmphls1=tmphls->next;
|
||||
"%08X*%08X=%08X",tmphls->size,tmphls->cnt,tmphls->size*tmphls->cnt;
|
||||
for (j=0;j<HL_CALLER_DEPTH;j++)
|
||||
" %P",tmphls->caller[j];
|
||||
'\n';
|
||||
total+=tmphls->size*tmphls->cnt;
|
||||
Free(tmphls);
|
||||
tmphls=tmphls1;
|
||||
}
|
||||
}
|
||||
Free(size_head);
|
||||
|
||||
"\n$$LTRED$$Total:%08X$$FG$$\n",total;
|
||||
LBts(&sys_semas[SEMA_HEAPLOG_ACTIVE],0);
|
||||
if (!leave_it)
|
||||
HeapLog(OFF);
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
#help_index "Cmd Line (Typically)"
|
||||
|
||||
I64 LineRep1(CDirEntry *tmpde)
|
||||
{
|
||||
CDoc *doc;
|
||||
I64 res=0,i;
|
||||
while (tmpde) {
|
||||
i=0;
|
||||
if (tmpde->attr&RS_ATTR_DIR)
|
||||
i=LineRep1(tmpde->sub);
|
||||
else {
|
||||
doc=DocRead(tmpde->full_name);
|
||||
if (doc->head.next!=doc)
|
||||
i=doc->head.last->y+2;
|
||||
DocDel(doc);
|
||||
}
|
||||
tmpde->user_data=i;
|
||||
res+=i;
|
||||
tmpde=tmpde->next;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
U0 LineRep2(CDoc *doc,CDirEntry *tmpde)
|
||||
{
|
||||
while (tmpde) {
|
||||
if (tmpde->attr&RS_ATTR_DIR) {
|
||||
DocPrint(doc,"%8,d $$TR+C,\"%s\"$$\n$$ID,2$$",tmpde->user_data,tmpde->name);
|
||||
LineRep2(doc,tmpde->sub);
|
||||
DocPrint(doc,"$$ID,-2$$");
|
||||
} else
|
||||
DocPrint(doc,"%8,d $$LK,\"%s\",A=\"FI:%s\"$$\n",
|
||||
tmpde->user_data,tmpde->name,tmpde->full_name);
|
||||
tmpde=tmpde->next;
|
||||
}
|
||||
}
|
||||
public I64 LineRep(U8 *files_find_mask="/*",U8 *fu_flags=NULL)
|
||||
{//Source line-of-code count report.
|
||||
I64 fuf_flags=0,res=0;
|
||||
CDoc *doc=DocNew;
|
||||
CDirEntry *tmpde1=NULL;
|
||||
ScanFlags(&fuf_flags,Define("ST_FILE_UTIL_FLAGS"),"+r+S");
|
||||
ScanFlags(&fuf_flags,Define("ST_FILE_UTIL_FLAGS"),fu_flags);
|
||||
if (tmpde1=FilesFind(files_find_mask,fuf_flags)) {
|
||||
res=LineRep1(tmpde1);
|
||||
DocPrint(doc,"%8,d $$TR+C,\"%s\"$$\n$$ID,2$$",res,files_find_mask);
|
||||
LineRep2(doc,tmpde1);
|
||||
DocPrint(doc,"$$ID,-2$$");
|
||||
DirTreeDel(tmpde1);
|
||||
}
|
||||
DocInsDoc(DocPut,doc);
|
||||
DocDel(doc);
|
||||
return res;
|
||||
}
|
||||
|
||||
I64 SizeRep1(CDirEntry *tmpde,I64 *_fuf_flags)
|
||||
{
|
||||
I64 res=0,i;
|
||||
U8 buf[BLK_SIZE];
|
||||
CDrv *dv;
|
||||
while (tmpde) {
|
||||
if (tmpde->attr&RS_ATTR_DIR)
|
||||
i=SizeRep1(tmpde->sub,_fuf_flags);
|
||||
else if ((i=tmpde->size) && Bt(_fuf_flags,FUf_EXPAND) &&
|
||||
FileAttr(tmpde->name)&RS_ATTR_COMPRESSED) {
|
||||
dv=Let2Drv(*tmpde->full_name);
|
||||
RBlks(dv,buf,Cluster2Blk(dv,tmpde->cluster),1);
|
||||
i=(&buf)(CArcCompress *)->expanded_size;
|
||||
}
|
||||
tmpde->user_data=i;
|
||||
res+=i;
|
||||
tmpde=tmpde->next;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
U0 SizeRep2(CDoc *doc,CDirEntry *tmpde)
|
||||
{
|
||||
while (tmpde) {
|
||||
if (tmpde->attr&RS_ATTR_DIR) {
|
||||
DocPrint(doc,"%10,d $$TR+C,\"%s\"$$\n$$ID,2$$",
|
||||
tmpde->user_data,tmpde->name);
|
||||
SizeRep2(doc,tmpde->sub);
|
||||
DocPrint(doc,"$$ID,-2$$");
|
||||
} else {
|
||||
DocPrint(doc,"%10,d ",tmpde->user_data);
|
||||
DocPrint(doc,"$$LK,\"%s\",A=\"FI:%s\"$$\n",
|
||||
tmpde->name,tmpde->full_name);
|
||||
}
|
||||
tmpde=tmpde->next;
|
||||
}
|
||||
}
|
||||
public I64 SizeRep(U8 *files_find_mask="/*",U8 *fu_flags=NULL)
|
||||
{//Report file sizes. "+x" for expanded size of compressed files.
|
||||
I64 fuf_flags=0,res=0;
|
||||
CDoc *doc=DocNew;
|
||||
CDirEntry *tmpde1=NULL;
|
||||
ScanFlags(&fuf_flags,Define("ST_FILE_UTIL_FLAGS"),"+r");
|
||||
ScanFlags(&fuf_flags,Define("ST_FILE_UTIL_FLAGS"),fu_flags);
|
||||
if (tmpde1=FilesFind(files_find_mask,fuf_flags&FUG_FILES_FIND)) {
|
||||
fuf_flags&=FUF_EXPAND;
|
||||
res=SizeRep1(tmpde1,&fuf_flags);
|
||||
DocPrint(doc,"%10,d $$TR+C,\"%s\"$$\n$$ID,2$$",res,files_find_mask);
|
||||
SizeRep2(doc,tmpde1);
|
||||
DocPrint(doc,"$$ID,-2$$");
|
||||
DirTreeDel(tmpde1);
|
||||
}
|
||||
DocInsDoc(DocPut,doc);
|
||||
DocDel(doc);
|
||||
return res;
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
#help_index "Debugging;Cmd Line (Typically)"
|
||||
|
||||
I64 LinkChkDoc(CDoc *doc,I64 *_fuf_flags)
|
||||
{
|
||||
U8 *st;
|
||||
Bool found,unlock=DocLock(doc);
|
||||
CDoc *old_doc;
|
||||
CDocEntry *doc_e=doc->head.next;
|
||||
I64 res=0;
|
||||
while (doc_e!=doc) {
|
||||
if (ScanKey) {
|
||||
LBts(_fuf_flags,FUf_CANCEL);
|
||||
break;
|
||||
}
|
||||
if (st=DocEntryLink(doc,doc_e)) {
|
||||
old_doc=DocPut;
|
||||
DocLock(old_doc);
|
||||
Fs->put_doc=doc;
|
||||
found=DocLinkChk(doc,st);
|
||||
Fs->put_doc=old_doc;
|
||||
DocUnlock(old_doc);
|
||||
if (!found) {
|
||||
PutFileLink(doc->filename.name,,doc_e->y);
|
||||
"$$RED$$ %04d:%s\n$$FG$$",doc_e->y,st;
|
||||
res++;
|
||||
}
|
||||
Free(st);
|
||||
} else if (doc_e->type_u8==DOCT_ERROR) {
|
||||
PutFileLink(doc->filename.name,,doc_e->y);
|
||||
"$$RED$$ Doc Error\n$$FG$$";
|
||||
res++;
|
||||
}
|
||||
doc_e=doc_e->next;
|
||||
}
|
||||
if (unlock) DocUnlock(doc);
|
||||
return res;
|
||||
}
|
||||
|
||||
I64 LinkChkFile(U8 *filename,I64 *_fuf_flags)
|
||||
{
|
||||
I64 res;
|
||||
CDoc *doc=DocRead(filename,DOCF_NO_CURSOR);
|
||||
res=LinkChkDoc(doc,_fuf_flags);
|
||||
DocDel(doc);
|
||||
return res;
|
||||
}
|
||||
public I64 LinkChk(U8 *files_find_mask="/*",U8 *fu_flags=NULL)
|
||||
{//Check documents for broken file links.
|
||||
I64 fuf_flags=0,res=0;
|
||||
CDirEntry *tmpde,*tmpde1;
|
||||
U8 *st;
|
||||
progress2_max=1;
|
||||
ScanFlags(&fuf_flags,Define("ST_FILE_UTIL_FLAGS"),"+r+$$+f+F+O");
|
||||
ScanFlags(&fuf_flags,Define("ST_FILE_UTIL_FLAGS"),fu_flags);
|
||||
tmpde=tmpde1=FilesFind(files_find_mask,fuf_flags);
|
||||
while (tmpde && !Bt(&fuf_flags,FUf_CANCEL)) {
|
||||
|
||||
st=MStrPrint("Before %s Broke:%d",tmpde->full_name,res);
|
||||
if (StrLen(st)>PROGRESS_DESC_LEN-1)
|
||||
st[PROGRESS_DESC_LEN-1]=0;
|
||||
StrCpy(progress2_desc,st);
|
||||
Free(st);
|
||||
Yield;
|
||||
|
||||
res+=LinkChkFile(tmpde->full_name,&fuf_flags);
|
||||
|
||||
st=MStrPrint("After %s Broke:%d",tmpde->full_name,res);
|
||||
if (StrLen(st)>PROGRESS_DESC_LEN-1)
|
||||
st[PROGRESS_DESC_LEN-1]=0;
|
||||
StrCpy(progress2_desc,st);
|
||||
Free(st);
|
||||
Yield;
|
||||
|
||||
tmpde=tmpde->next;
|
||||
}
|
||||
DirTreeDel(tmpde1);
|
||||
progress2_max=0;
|
||||
return res;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
Cd(__DIR__);;
|
||||
#include "Diff"
|
||||
#include "FileBMP"
|
||||
#include "Find"
|
||||
#include "HeapLog"
|
||||
#include "LineRep"
|
||||
#include "LinkChk"
|
||||
#include "MemRep"
|
||||
#include "Merge"
|
||||
#include "Profiler"
|
||||
#include "StrUtils"
|
||||
#include "DocUtils"
|
||||
#include "ToDolDoc"
|
||||
#include "ToTXT"
|
||||
#include "TOS"
|
||||
Cd("..");;
|
||||
@@ -0,0 +1,232 @@
|
||||
#help_index "Info;Memory/Info;Cmd Line (Typically)"
|
||||
|
||||
I64 TSSSize(CTSS *tss)
|
||||
{
|
||||
return MSize2(tss)+MSize2(tss->st0)+MSize2(tss->st1)+MSize2(tss->st2);
|
||||
}
|
||||
|
||||
I64 PenBrushesSize()
|
||||
{
|
||||
I64 res=0,i;
|
||||
for (i=0;i<GR_PEN_BRUSHES_NUM;i++)
|
||||
res+=DCSize(gr.pen_brushes[i])+DCSize(gr.collision_pen_brushes[i])+
|
||||
DCSize(gr.even_pen_brushes[i])+DCSize(gr.odd_pen_brushes[i]);
|
||||
return res;
|
||||
}
|
||||
|
||||
I64 ScrnZoomTablesSize()
|
||||
{
|
||||
I64 res=0,i;
|
||||
for (i=1;i<=GR_SCRN_ZOOM_MAX;i++)
|
||||
res+=MSize2(gr.scrn_zoom_tables[i]);
|
||||
return res;
|
||||
}
|
||||
|
||||
I64 TaskStkSize(CTask *task)
|
||||
{
|
||||
CTaskStk *tmps=task->stk;
|
||||
I64 res=0;
|
||||
while (tmps) {
|
||||
res+=MSize2(tmps);
|
||||
tmps=tmps->next_stk;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
I64 TaskQueSize(CTask *task)
|
||||
{
|
||||
CJob *tmpc,*tmpc1;
|
||||
I64 res=0;
|
||||
PUSHFD
|
||||
CLI
|
||||
while (LBts(&task->srv_ctrl.flags,JOBCf_LOCKED))
|
||||
PAUSE
|
||||
|
||||
tmpc1=&task->srv_ctrl.next_waiting;
|
||||
tmpc=tmpc1->next;
|
||||
while (tmpc!=tmpc1) {
|
||||
res+=MSize2(tmpc)+MSize2(tmpc->aux_str);
|
||||
tmpc=tmpc->next;
|
||||
}
|
||||
|
||||
tmpc1=&task->srv_ctrl.next_done;
|
||||
tmpc=tmpc1->next;
|
||||
while (tmpc!=tmpc1) {
|
||||
res+=MSize2(tmpc)+MSize2(tmpc->aux_str);
|
||||
tmpc=tmpc->next;
|
||||
}
|
||||
|
||||
LBtr(&task->srv_ctrl.flags,JOBCf_LOCKED);
|
||||
POPFD
|
||||
return res;
|
||||
}
|
||||
|
||||
I64 BlkDevsSize()
|
||||
{
|
||||
I64 i,j,res=MSize2(blkdev.blkdevs);
|
||||
CBlkDev *bd;
|
||||
for (i=0;i<BLKDEVS_NUM;i++) {
|
||||
bd=&blkdev.blkdevs[i];
|
||||
if (bd->bd_signature==BD_SIGNATURE_VAL) {
|
||||
j=(bd->max_blk+1)<<BLK_SIZE_BITS;
|
||||
if (bd->type==BDT_RAM)
|
||||
"RAMDsk %C\t:%010X/%010X\n",
|
||||
bd->first_drv_let,j-UnusedDrvSpace(bd->first_drv_let),j;
|
||||
res+=MSize2(bd->dev_id_record);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
I64 DrvsSize()
|
||||
{
|
||||
I64 i,res=MSize2(blkdev.drvs);
|
||||
for (i=0;i<DRVS_NUM;i++)
|
||||
res+=MSize2(blkdev.drvs[i].cur_fat_blk)+MSize2(blkdev.drvs[i].fis);
|
||||
return res;
|
||||
}
|
||||
|
||||
Bool MemRepTask(CTask *task,Bool override_validate=FALSE)
|
||||
{
|
||||
I64 i,j,k,m,n;
|
||||
U8 *st;
|
||||
CDoc *pdoc,*ddoc,*bdoc;
|
||||
CCmpCtrl *cc;
|
||||
CMathODE *o;
|
||||
CCPU *c;
|
||||
CTask *task1;
|
||||
|
||||
if (!override_validate && !TaskValidate(task))
|
||||
return FALSE;
|
||||
if (task==Fs)
|
||||
task->rsp=GetRSP;
|
||||
st=MStrUtil(task->task_title,SUF_REM_CTRL_CHARS|SUF_SAFE_DOLLAR);
|
||||
"$$BLACK$$%-27ts#%08X$$FG$$\n$$ID,2$$",st,task;
|
||||
Free(st);
|
||||
"Heap\t:%010X/%010X\n",TaskMemUsed(task,override_validate),
|
||||
TaskMemAlloced(task,override_validate);
|
||||
|
||||
i=UnusedStk(task);
|
||||
j=TaskStkSize(task);
|
||||
if (0<=i<=task->stk->stk_size)
|
||||
"Stk\t\t:%010X/%010X\n",j-i,j;
|
||||
else
|
||||
"Stk\t\t:$$RED$$$$BK,1$$Overflow$$BK,0$$$$FG$$/%010X\n",j;
|
||||
|
||||
"HashTable\t:%010X\n",HashTableSize2(task->hash_table);
|
||||
"FPU\t\t:%010X\n",MSize2(task->fpu_mmx);
|
||||
"CurDir\t:%010X\n",MSize2(task->cur_dir);
|
||||
|
||||
if (pdoc=DocPut(task))
|
||||
"PutDoc\t:%010X\n",DocSize(pdoc);
|
||||
if ((ddoc=DocDisplay(task)) && pdoc!=ddoc)
|
||||
"DisplayDoc\t:%010X\n",DocSize(ddoc);
|
||||
if (bdoc=DocBorder(task))
|
||||
"BorderDoc\t:%010X\n",DocSize(bdoc);
|
||||
|
||||
cc=task->next_cc;
|
||||
while (cc!=&task->next_cc) {
|
||||
"CmpCtrl\t:%010X\n",CmpCtrlSize(cc);
|
||||
cc=cc->next;
|
||||
}
|
||||
|
||||
o=task->next_ode;
|
||||
while (o!=&task->next_ode) {
|
||||
"CMathODE\t:%010X\n",ODESize(o);
|
||||
o=o->next;
|
||||
}
|
||||
|
||||
if (task==sys_winmgr_task) {
|
||||
"gr.pen_brushes\t:%010X\n",PenBrushesSize;
|
||||
"gr.scrn_zoom_tbles\t:%010X\n",ScrnZoomTablesSize;
|
||||
} else if (task==adam_task) {
|
||||
j=0;k=0;m=0;n=0;
|
||||
for (i=0;i<mp_cnt;i++) {
|
||||
c=&cpu_structs[i];
|
||||
k+=TSSSize(c->tss);
|
||||
task1=c->seth_task;
|
||||
do {
|
||||
if (task1!=adam_task) {//adam task located in Kernel mem
|
||||
j+=MSize2(task1);
|
||||
m+=MSize2(task1->code_heap);
|
||||
if (task1->data_heap!=task1->code_heap)
|
||||
m+=MSize2(task1->code_heap);
|
||||
}
|
||||
n+=TaskQueSize(task1);
|
||||
task1=task1->next_task;
|
||||
} while (task1!=c->seth_task);
|
||||
task1=c->idle_task;
|
||||
j+=MSize2(task1);
|
||||
m+=MSize2(task1->code_heap);
|
||||
if (task1->data_heap!=task1->code_heap)
|
||||
m+=MSize2(task1->code_heap);
|
||||
}
|
||||
"TaskStructs\t:%010X\n",j;
|
||||
"TSSes\t:%010X\n",k;
|
||||
"HeapCtrls\t:%010X\n",m;
|
||||
if (n)
|
||||
"TaskQues\t:%010X\n",n;
|
||||
"BlkDevs\t:%010X\n",BlkDevsSize;
|
||||
"Drvs\t:%010X\n",DrvsSize;
|
||||
if (blkdev.cache_base)
|
||||
"DskCache\t:%010X\n",
|
||||
MSize2(blkdev.cache_base)+MSize2(blkdev.cache_hash_table)+
|
||||
MSize2(blkdev.cache_ctrl);
|
||||
"Clipboard\t:%010X\n",DocSize(sys_clipboard_doc);
|
||||
"AutoComplete:%010X\n",CallExtStr("AutoCompleteSize");
|
||||
"gr.to_8_bits\t:%010X\n",MSize2(gr.to_8_bits);
|
||||
"gr.to_8_colors\t:%010X\n",MSize2(gr.to_8_colors);
|
||||
"gr.text_base\t:%010X\n",MSize2(gr.text_base);
|
||||
"gr.vga_text_cache\t:%010X\n",MSize2(gr.vga_text_cache);
|
||||
"gr.win_z_buf\t:%010X\n",MSize2(gr.win_z_buf)+
|
||||
MSize2(gr.win_uncovered_bitmap);
|
||||
"gr.dc\t\t:%010X\n",DCSize(gr.dc);
|
||||
"gr.dc1\t\t:%010X\n",DCSize(gr.dc1);
|
||||
"gr.dc2\t\t:%010X\n",DCSize(gr.dc2);
|
||||
"gr.dc_cache\t\t:%010X\n",DCSize(gr.dc_cache);
|
||||
"gr.scrn_image\t:%010X\n",DCSize(gr.scrn_image);
|
||||
"gr.zoomed_dc\t:%010X\n",DCSize(gr.zoomed_dc);
|
||||
}
|
||||
"$$ID,-2$$";
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
public U0 MemRep()
|
||||
{//Memory usage report.
|
||||
I64 i;
|
||||
CTask *task;
|
||||
CCPU *c;
|
||||
CBinFile *bfh=mem_boot_base-sizeof(CBinFile);
|
||||
bfh(I64)+=bfh->file_size-1;
|
||||
|
||||
"$$BLACK$$Low Memory\t:0000100000$$FG$$\n$$ID,2$$";
|
||||
"Kernel\t:%010X-%010X\n",mem_boot_base-sizeof(CBinFile),bfh;
|
||||
|
||||
"VGA\t\t:00000A0000-00000BFFFF\n";
|
||||
"$$ID,-2$$$$BLACK$$High Memory\t:0000100000-%010X$$FG$$\n",
|
||||
mem_heap_limit;
|
||||
"$LK,"SYS_FIXED_AREA",A="MN:CSysFixedArea"$\t:%010X-%010X\n",
|
||||
SYS_FIXED_AREA,SYS_FIXED_AREA+sizeof(CSysFixedArea)-1;
|
||||
|
||||
if (sys_data_bp) {
|
||||
"$$BLACK$$Code Heap\t:%010X/%010X$$FG$$\n",
|
||||
sys_code_bp->used_u8s,sys_code_bp->alloced_u8s;
|
||||
"$$BLACK$$Data Heap\t:%010X/%010X$$FG$$\n",
|
||||
sys_data_bp->used_u8s,sys_data_bp->alloced_u8s;
|
||||
} else
|
||||
"$$BLACK$$Code/Data Heap\t:%010X/%010X$$FG$$\n",
|
||||
sys_code_bp->used_u8s,sys_code_bp->alloced_u8s;
|
||||
|
||||
for (i=0;i<mp_cnt;i++) {
|
||||
c=&cpu_structs[i];
|
||||
"$$PURPLE$$CPU%d$$FG$$\n$$ID,2$$",i;
|
||||
task=c->seth_task;
|
||||
do {
|
||||
if (!MemRepTask(task))
|
||||
break;
|
||||
task=task->next_task;
|
||||
} while (task!=c->seth_task);
|
||||
MemRepTask(c->idle_task,TRUE);
|
||||
"$$ID,-2$$";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
#help_index "Cmd Line (Typically)"
|
||||
|
||||
CDirEntry MGFind(CDirEntry *needle_entry,CDirEntry *haystack_lst)
|
||||
{
|
||||
while (haystack_lst) {
|
||||
if (!StrCmp(needle_entry->name,haystack_lst->name))
|
||||
return haystack_lst;
|
||||
haystack_lst=haystack_lst->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
U0 Merge2(CDirEntry *tmpde1,CDirEntry *tmpde2,I64 *_fuf_flags,I64 *_df_flags)
|
||||
{
|
||||
CDirEntry *tmpde;
|
||||
while (tmpde1 && !(*_df_flags & DF_ABORT_ALL_FILES)) {
|
||||
tmpde=MGFind(tmpde1,tmpde2);
|
||||
if (!tmpde)
|
||||
"$$BROWN$$Does Not Exist:%s$$FG$$\n",tmpde1->full_name;
|
||||
else {
|
||||
if (tmpde1->attr & RS_ATTR_DIR)
|
||||
Merge2(tmpde1->sub,tmpde->sub,_fuf_flags,_df_flags);
|
||||
else {
|
||||
if (AbsI64(tmpde1->datetime-tmpde->datetime)>CDATE_FREQ*2) {//slop
|
||||
"%s",tmpde1->full_name;
|
||||
'\n';
|
||||
if (Bt(_fuf_flags,FUf_DIFF)) {
|
||||
if (FilesFindMatch(tmpde1->full_name,FILEMASK_TXT))
|
||||
Diff(tmpde->full_name,tmpde1->full_name,_df_flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
tmpde1=tmpde1->next;
|
||||
}
|
||||
}
|
||||
public U0 Merge(U8 *dst_files_find_mask="/*",U8 *src_files_find_mask="/*",
|
||||
U8 *fu_flags=NULL)
|
||||
{/*Merge text files from one list into another.
|
||||
Report files whos date/time is different.
|
||||
|
||||
"+d" will do $LK,"Diff",A="MN:Diff"$() on files and prompt to
|
||||
merge changes from source files into
|
||||
destination files.
|
||||
*/
|
||||
I64 df_flags=0,fuf_flags=0;
|
||||
CDirEntry *tmpde1=NULL,*tmpde2=NULL;
|
||||
ScanFlags(&fuf_flags,Define("ST_FILE_UTIL_FLAGS"),"+r");
|
||||
ScanFlags(&fuf_flags,Define("ST_FILE_UTIL_FLAGS"),fu_flags);
|
||||
if (fuf_flags&~(FUG_FILES_FIND|FUF_DIFF))
|
||||
throw('FUF');
|
||||
PrintWarn("This is based strictly on file dates.\n");
|
||||
tmpde1=FilesFind(src_files_find_mask,fuf_flags&FUG_FILES_FIND);
|
||||
tmpde2=FilesFind(dst_files_find_mask,fuf_flags&FUG_FILES_FIND);
|
||||
fuf_flags&=FUF_DIFF;
|
||||
Merge2(tmpde1,tmpde2,&fuf_flags,&df_flags);
|
||||
DirTreeDel(tmpde1);
|
||||
DirTreeDel(tmpde2);
|
||||
}
|
||||
|
||||
#help_index "Utils;Cmd Line (Typically)"
|
||||
|
||||
public U0 NewFiles(U8 *files_find_mask="/*",CDate cdt=0,U8 *fu_flags=NULL)
|
||||
{//Report files newer than a certain date.
|
||||
I64 fuf_flags=0;
|
||||
CDirEntry *tmpde,*tmpde1;
|
||||
if (!cdt) cdt=sys_compile_time;
|
||||
ScanFlags(&fuf_flags,Define("ST_FILE_UTIL_FLAGS"),"+r+F");
|
||||
ScanFlags(&fuf_flags,Define("ST_FILE_UTIL_FLAGS"),fu_flags);
|
||||
tmpde=tmpde1=FilesFind(files_find_mask,fuf_flags);
|
||||
while (tmpde) {
|
||||
if (tmpde->datetime>cdt)
|
||||
"%s\n",tmpde->full_name;
|
||||
tmpde=tmpde->next;
|
||||
}
|
||||
DirTreeDel(tmpde1);
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
#help_index "Debugging/Profiler;Profiler;Cmd Line (Typically)/Profiler"
|
||||
#help_file "::/Doc/Profiler"
|
||||
|
||||
#define PF_ARRAY_CNT 0x100000
|
||||
I64 pf_jiffy_start,pf_jiffy_end;
|
||||
I64 *pf_array=NULL;
|
||||
I64 pf_cpu=0;
|
||||
I64 pf_buf_in_ptr=0,pf_depth;
|
||||
I64 pf_prof_active=0;
|
||||
|
||||
U0 ProfTimerInt(CTask *task)
|
||||
{//See $LK,"profiler_timer_irq",A="FF:::/Kernel/KInts.HC,profiler_timer_irq"$.
|
||||
I64 i,k;
|
||||
if (Bt(&pf_prof_active,0))
|
||||
for (k=0;k<=pf_depth;k++) {
|
||||
if (task==Gs->idle_task)
|
||||
i=SYS_IDLE_PT;
|
||||
else
|
||||
i=TaskCaller(task,k,TRUE);
|
||||
if (pf_buf_in_ptr<PF_ARRAY_CNT) {
|
||||
pf_array[pf_buf_in_ptr++]=i;
|
||||
pf_jiffy_end=cnts.jiffies;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public U0 Prof(I64 depth=0,I64 cpu_num=0)
|
||||
{/*Start collecting profiler statistics.
|
||||
Profilers report where time is spent
|
||||
by sampling RIP during the $TX,"1000Hz",D="DD_JIFFY_HZ"$
|
||||
timer interrupt.
|
||||
|
||||
Do a $LK,"ProfRep",A="MN:ProfRep"$(), (profiler report)
|
||||
after you have collected data.
|
||||
*/
|
||||
if (!(0<=cpu_num<mp_cnt))
|
||||
ST_ERR_ST "Invalid CPU\n";
|
||||
else {
|
||||
cpu_structs[pf_cpu].profiler_timer_irq=NULL;
|
||||
pf_cpu=cpu_num;
|
||||
|
||||
pf_depth=depth;
|
||||
pf_buf_in_ptr=0;
|
||||
if (!pf_array)
|
||||
pf_array=AMAlloc(sizeof(I64)*PF_ARRAY_CNT);
|
||||
pf_jiffy_end=pf_jiffy_start=cnts.jiffies;
|
||||
LBts(&pf_prof_active,0);
|
||||
cpu_structs[pf_cpu].profiler_timer_irq=&ProfTimerInt;
|
||||
}
|
||||
}
|
||||
|
||||
I64 ProfCompare(U8 *i1,U8 *i2)
|
||||
{
|
||||
return i1-i2;
|
||||
}
|
||||
|
||||
public U0 ProfRep(I64 filter_cnt=1,Bool leave_it=OFF)
|
||||
{//Profiler report. Call $LK,"Prof",A="MN:Prof"$() first and collect data.
|
||||
I64 i,hits,rip,last_rip=0,routine_total=0;
|
||||
F64 total_time;
|
||||
U8 buf[256],buf2[256],last_buf[256];
|
||||
if (!LBtr(&pf_prof_active,0))
|
||||
"Profiler Not Active\n";
|
||||
if (!pf_buf_in_ptr)
|
||||
"No Profiler Statistic\n";
|
||||
else {
|
||||
if (!(total_time=pf_jiffy_end-pf_jiffy_start))
|
||||
total_time=1;
|
||||
QSortI64(pf_array,pf_buf_in_ptr,&ProfCompare);
|
||||
*last_buf=0;
|
||||
for (i=0;i<pf_buf_in_ptr;i+=hits) {
|
||||
rip=pf_array[i];
|
||||
hits=0;
|
||||
do hits++;
|
||||
while (i+hits<pf_buf_in_ptr && pf_array[i+hits]==rip);
|
||||
|
||||
StrPrint(buf,"%p",rip);
|
||||
StrFirstRem(buf,"+",buf2);
|
||||
if (StrCmp(buf2,last_buf)) {
|
||||
if (*last_buf && routine_total>=filter_cnt)
|
||||
"$$GREEN$$%6.2f %08X:%s\n$$FG$$",100*routine_total/total_time,
|
||||
routine_total,last_buf;
|
||||
StrCpy(last_buf,buf2);
|
||||
routine_total=0;
|
||||
}
|
||||
routine_total+=hits;
|
||||
if (hits>=filter_cnt) {
|
||||
"%6.2f %08X:%P\n",100*hits/total_time,hits,rip;
|
||||
last_rip=rip;
|
||||
}
|
||||
}
|
||||
if (*last_buf && routine_total>=filter_cnt)
|
||||
"$$GREEN$$%6.2f %08X:%s\n$$FG$$",100*routine_total/total_time,
|
||||
routine_total,last_buf;
|
||||
"Total Time:%0.6fs\n",total_time/JIFFY_FREQ;
|
||||
if (leave_it) {
|
||||
cpu_structs[pf_cpu].profiler_timer_irq=&ProfTimerInt;
|
||||
LBts(&pf_prof_active,0);
|
||||
} else
|
||||
cpu_structs[pf_cpu].profiler_timer_irq=NULL;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,206 @@
|
||||
#help_index "Cmd Line (Typically)"
|
||||
|
||||
I64 DEPtrCompare(CDocEntry **e1,CDocEntry **e2)
|
||||
{
|
||||
return StrCmp((*e1)->tag,(*e2)->tag);
|
||||
}
|
||||
|
||||
public I64 Sort(U8 *_in_name,U8 *_out_name=NULL,
|
||||
I64 entry_lines=1,Bool unique=FALSE)
|
||||
{//Sort lines of a text file. Removes blank lines.
|
||||
U8 *in_name,*out_name,*st;
|
||||
CDoc *doc;
|
||||
CDocEntry *doc_e,*doc_e1,**a;
|
||||
I64 i,j,cnt=0,res;
|
||||
|
||||
if (!_in_name) return 0;
|
||||
in_name=DftExt(_in_name,"DD.Z");
|
||||
if (_out_name)
|
||||
out_name=DftExt(_out_name,"DD.Z");
|
||||
else
|
||||
out_name=StrNew(in_name);
|
||||
|
||||
doc=DocRead(in_name,DOCF_PLAIN_TEXT_TABS|DOCF_NO_CURSOR);
|
||||
doc_e=doc->head.next;
|
||||
while (doc_e!=doc) {
|
||||
if (doc_e->type_u8==DOCT_TEXT)
|
||||
cnt++;
|
||||
doc_e=doc_e->next;
|
||||
}
|
||||
a=MAlloc(cnt*sizeof(CDocEntry *));
|
||||
doc_e=doc->head.next;
|
||||
i=0;
|
||||
while (doc_e!=doc) {
|
||||
doc_e1=doc_e->next;
|
||||
if (doc_e->type_u8==DOCT_TEXT) {
|
||||
QueRem(doc_e);
|
||||
a[i++]=doc_e;
|
||||
} else
|
||||
DocEntryDel(doc,doc_e);
|
||||
doc_e=doc_e1;
|
||||
}
|
||||
QSort(a,cnt/entry_lines,entry_lines*sizeof(CDocEntry *),&DEPtrCompare);
|
||||
|
||||
res=0;
|
||||
st=NULL;
|
||||
for (i=0;i<cnt;) {
|
||||
if (!unique || !st || StrCmp(a[i]->tag,st)) {
|
||||
st=a[i]->tag;
|
||||
for (j=0;j<entry_lines && i<cnt;j++,i++) {
|
||||
QueIns(a[i],doc->head.last);
|
||||
doc->cur_entry=&doc->head;
|
||||
doc->cur_col=0;
|
||||
DocPrint(doc,"\n");
|
||||
}
|
||||
res++;
|
||||
} else
|
||||
for (j=0;j<entry_lines && i<cnt;j++,i++) {
|
||||
QueIns(a[i],doc->head.last);
|
||||
DocEntryDel(doc,a[i]);
|
||||
}
|
||||
}
|
||||
StrCpy(doc->filename.name,out_name);
|
||||
DocWrite(doc);
|
||||
|
||||
Free(a);
|
||||
DocDel(doc);
|
||||
Free(in_name);
|
||||
Free(out_name);
|
||||
return res; //Num Entries
|
||||
}
|
||||
|
||||
I64 DocWordsFile(CDoc *doc_out=NULL,U8 *filename,U32 *char_bmp)
|
||||
{
|
||||
U8 *ptr,*ptr2;
|
||||
I64 res=0,ch;
|
||||
CDoc *doc_in=DocRead(filename);
|
||||
CDocEntry *doc_e=doc_in->head.next;
|
||||
while (doc_e!=doc_in) {
|
||||
if (doc_e->de_flags & DOCEF_TAG) {
|
||||
ptr=doc_e->tag;
|
||||
while (*ptr) {
|
||||
while (*ptr && !Bt(char_bmp,*ptr))
|
||||
ptr++;
|
||||
|
||||
ptr2=ptr;
|
||||
while (*ptr && Bt(char_bmp,*ptr))
|
||||
ptr++;
|
||||
|
||||
ch=*ptr;
|
||||
*ptr=0;
|
||||
if (*ptr2) {
|
||||
DocPrint(doc_out,"%s\n",ptr2);
|
||||
res++;
|
||||
}
|
||||
*ptr=ch;
|
||||
}
|
||||
}
|
||||
doc_e=doc_e->next;
|
||||
}
|
||||
DocDel(doc_in);
|
||||
return res;
|
||||
}
|
||||
public I64 Words(U8 *files_find_mask="*",U32 *char_bmp=char_bmp_alpha,
|
||||
U8 *fu_flags=NULL)
|
||||
{//Break file into list of not-unique words.
|
||||
I64 fuf_flags=0,res=0;
|
||||
CDoc *doc_out=DocNew;
|
||||
CDirEntry *tmpde,*tmpde1;
|
||||
ScanFlags(&fuf_flags,Define("ST_FILE_UTIL_FLAGS"),"+r+f+F+T");
|
||||
ScanFlags(&fuf_flags,Define("ST_FILE_UTIL_FLAGS"),fu_flags);
|
||||
tmpde=tmpde1=FilesFind(files_find_mask,fuf_flags);
|
||||
while (tmpde) {
|
||||
res+=DocWordsFile(doc_out,tmpde->full_name,char_bmp);
|
||||
tmpde=tmpde->next;
|
||||
}
|
||||
DirTreeDel(tmpde1);
|
||||
DocInsDoc(NULL,doc_out);
|
||||
DocDel(doc_out);
|
||||
return res;
|
||||
}
|
||||
|
||||
I64 LongLinesFile(U8 *filename,I64 cols)
|
||||
{
|
||||
I64 res=0;
|
||||
CDoc *doc=DocRead(filename);
|
||||
CDocEntry *doc_e=doc->head.next;
|
||||
while (doc_e!=doc) {
|
||||
if (doc_e->type_u8==DOCT_NEW_LINE && doc_e->x>=cols+1)
|
||||
res++;
|
||||
doc_e=doc_e->next;
|
||||
}
|
||||
DocDel(doc);
|
||||
if (res) {
|
||||
"%04d ",res;
|
||||
PutFileLink(filename);
|
||||
'\n';
|
||||
}
|
||||
return res;
|
||||
}
|
||||
public I64 LongLines(U8 *files_find_mask="*",I64 cols=80,U8 *fu_flags=NULL)
|
||||
{//Report files with lines of too many cols.
|
||||
I64 res=0,fuf_flags=0;
|
||||
CDirEntry *tmpde,*tmpde1;
|
||||
ScanFlags(&fuf_flags,Define("ST_FILE_UTIL_FLAGS"),"+r+f+F+S");
|
||||
ScanFlags(&fuf_flags,Define("ST_FILE_UTIL_FLAGS"),fu_flags);
|
||||
tmpde=tmpde1=FilesFind(files_find_mask,fuf_flags);
|
||||
while (tmpde) {
|
||||
if (LongLinesFile(tmpde->full_name,cols))
|
||||
res++;
|
||||
tmpde=tmpde->next;
|
||||
}
|
||||
DirTreeDel(tmpde1);
|
||||
return res;
|
||||
}
|
||||
|
||||
U0 SUFile(U8 *filename,I64 suf_flags,F64 indent_scale_factor)
|
||||
{//String utility on a single file
|
||||
//See $LK,"SU Flags",A="MN:SUF_SINGLE_SPACE"$
|
||||
U8 *dst;
|
||||
Bool chged=FALSE;
|
||||
I64 reduced=0;
|
||||
CDoc *doc=DocRead(filename,DOCF_PLAIN_TEXT_TABS|DOCF_NO_CURSOR);
|
||||
CDocEntry *doc_e=doc->head.next;
|
||||
while (doc_e!=doc) {
|
||||
if (doc_e->type_u8==DOCT_TEXT) {
|
||||
dst=MStrUtil(doc_e->tag,suf_flags,indent_scale_factor);
|
||||
if (StrCmp(dst,doc_e->tag)) {
|
||||
reduced+=StrLen(doc_e->tag)-StrLen(dst);
|
||||
chged=TRUE;
|
||||
Free(doc_e->tag);
|
||||
doc_e->tag=dst;
|
||||
} else
|
||||
Free(dst);
|
||||
}
|
||||
doc_e=doc_e->next;
|
||||
}
|
||||
if (chged) {
|
||||
"Reduced %s by %d chars\n",filename,reduced;
|
||||
DocWrite(doc);
|
||||
}
|
||||
DocDel(doc);
|
||||
}
|
||||
public U0 SU(U8 *files_find_mask,I64 suf_flags,U8 *fu_flags=NULL,
|
||||
F64 indent_scale_factor=0)
|
||||
{//Apply $LK,"StrUtil",A="MN:StrUtil"$() on files
|
||||
//You can convert spaces to tabs, for example,
|
||||
//or removing trailing spaces on lines.
|
||||
//See $LK,"SUF Flags",A="MN:SUF_SINGLE_SPACE"$.
|
||||
I64 fuf_flags=0;
|
||||
CDirEntry *tmpde,*tmpde1;
|
||||
ScanFlags(&fuf_flags,Define("ST_FILE_UTIL_FLAGS"),"+f+F+T");
|
||||
ScanFlags(&fuf_flags,Define("ST_FILE_UTIL_FLAGS"),fu_flags);
|
||||
tmpde=tmpde1=FilesFind(files_find_mask,fuf_flags);
|
||||
while (tmpde) {
|
||||
SUFile(tmpde->full_name,suf_flags,indent_scale_factor);
|
||||
tmpde=tmpde->next;
|
||||
}
|
||||
DirTreeDel(tmpde1);
|
||||
}
|
||||
|
||||
public U0 S2T(U8 *files_find_mask,U8 *fu_flags=NULL)
|
||||
{//Spaces to tabs.
|
||||
//Use "Hard Space" (SHIFT-SPACE) for spaces
|
||||
//in string consts in your code.
|
||||
SU(files_find_mask,SUF_S2T|SUF_REM_TRAILING,fu_flags);
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
#help_index "Misc/TOS"
|
||||
|
||||
U0 TOSStaffIns()
|
||||
{//Completes TOS install from TempleOSStaff.ISO
|
||||
SettingsPush; //See $LK,"SettingsPush",A="MN:SettingsPush"$
|
||||
AutoComplete;
|
||||
WinBorder;
|
||||
WinMax;
|
||||
DocClear;
|
||||
"$$PURPLE$$$$TX+CX,\"Complete TOS install from TempleOSStaff.ISO\"$$$$FG$$\n\n\n\n";
|
||||
InsRereg;
|
||||
|
||||
"\nDownload TempleOSSup1.ISO.C\tfrom http://www.templeos.org AppStore.\n"
|
||||
"Download TempleOSBooks1.ISO.C\tfrom http://www.templeos.org AppStore.\n"
|
||||
"Download TempleOSBooks2.ISO.C\tfrom http://www.templeos.org AppStore.\n\n";
|
||||
|
||||
if (PressAKey!=CH_SHIFT_ESC) {
|
||||
if (HostChgDsk("/home/tad/TempleOSSup1.ISO.C"))
|
||||
CopyTree("T:/","~/Sup1");
|
||||
if (HostChgDsk("/home/tad/TempleOSBooks1.ISO.C"))
|
||||
CopyTree("T:/","~/Books1");
|
||||
if (HostChgDsk("/home/tad/TempleOSBooks2.ISO.C"))
|
||||
CopyTree("T:/","~/Books2");
|
||||
|
||||
Once("TOSBootHDIns;");
|
||||
"\nDo you wish to run >$FG,2$TOSRegen;$FG$ to generate\n the "
|
||||
"distro ISO's and the website image, $FG,2$D:/Wb$FG$ ";
|
||||
if (YorN) {
|
||||
Once("TOSRegen;");
|
||||
BootRAM("C:/" KERNEL_BIN_C); //Boot so TOSRegen cmd is available.
|
||||
} else {
|
||||
"\nReboot ";
|
||||
if (YorN)
|
||||
Reboot;
|
||||
}
|
||||
}
|
||||
SettingsPop;
|
||||
}
|
||||
|
||||
public U0 TOSStdIns()
|
||||
{//Completes TOS install from TempleOSCD.ISO
|
||||
SettingsPush; //See $LK,"SettingsPush",A="MN:SettingsPush"$
|
||||
AutoComplete;
|
||||
WinBorder;
|
||||
WinMax;
|
||||
DocClear;
|
||||
"$$PURPLE$$$$TX+CX,\"Complete TOS install from TempleOSCD.ISO\"$$$$FG$$\n\n\n\n";
|
||||
InsRereg;
|
||||
|
||||
"\nDownload TempleOSSup1.ISO.C\tfrom http://www.templeos.org AppStore.\n"
|
||||
"Download TempleOSWeb.ISO.C\tfrom http://www.templeos.org AppStore.\n"
|
||||
"Download TempleOSBooks1.ISO.C\tfrom http://www.templeos.org AppStore.\n"
|
||||
"Download TempleOSBooks2.ISO.C\tfrom http://www.templeos.org AppStore.\n\n";
|
||||
|
||||
if (PressAKey!=CH_SHIFT_ESC) {
|
||||
if (FileFind("/Demo/AcctExample"))
|
||||
CopyTree("::/Demo/AcctExample","~");
|
||||
if (HostChgDsk("/home/tad/Downloads/TempleOSSup1.ISO.C"))
|
||||
CopyTree("T:/","~/Sup1");
|
||||
if (HostChgDsk("/home/tad/Downloads/TempleOSWeb.ISO.C"))
|
||||
CopyTree("T:/","~/Web");
|
||||
if (HostChgDsk("/home/tad/Downloads/TempleOSBooks1.ISO.C"))
|
||||
CopyTree("T:/","~/Books1");
|
||||
if (HostChgDsk("/home/tad/Downloads/TempleOSBooks2.ISO.C"))
|
||||
CopyTree("T:/","~/Books2");
|
||||
|
||||
Once("TOSBootHDIns;");
|
||||
"\nDo you wish to run >$FG,2$TOSRegen;$FG$ to generate\n the "
|
||||
"distro ISO's and the website image, $FG,2$D:/Wb$FG$ ";
|
||||
if (YorN) {
|
||||
Once("TOSRegen;");
|
||||
BootRAM("C:/" KERNEL_BIN_C); //Boot so TOSRegen cmd is available.
|
||||
} else {
|
||||
"\nReboot ";
|
||||
if (YorN)
|
||||
Reboot;
|
||||
}
|
||||
}
|
||||
SettingsPop;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#help_index "Cmd Line (Typically);DolDoc/Conversion;DolDoc/Cmd Line (Typically)"
|
||||
|
||||
public U0 ToDolDoc(U8 *files_find_mask,U8 *fu_flags=NULL)
|
||||
{//Convert text file to $LK,"DolDoc",A="FI:::/Doc/DolDocOverview.DD"$ by making double $$'s.
|
||||
CDoc *doc;
|
||||
I64 fuf_flags=0;
|
||||
CDirEntry *tmpde,*tmpde1;
|
||||
ScanFlags(&fuf_flags,Define("ST_FILE_UTIL_FLAGS"),"+r+f+F");
|
||||
ScanFlags(&fuf_flags,Define("ST_FILE_UTIL_FLAGS"),fu_flags);
|
||||
tmpde=tmpde1=FilesFind(files_find_mask,fuf_flags);
|
||||
while (tmpde) {
|
||||
"%s\n",tmpde->full_name;
|
||||
doc=DocRead(tmpde->full_name,DOCF_PLAIN_TEXT|DOCF_DBL_DOLLARS);
|
||||
DocWrite(doc);
|
||||
DocDel(doc);
|
||||
tmpde=tmpde->next;
|
||||
}
|
||||
DirTreeDel(tmpde1);
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
#help_index "DolDoc/Conversion"
|
||||
|
||||
U0 TXTPutS(CDoc *doc,U8 *st,I64 *_col)
|
||||
{
|
||||
U8 *ch,*ptr;
|
||||
while (ch=*st++) {
|
||||
switch (ch) {
|
||||
case '\t':
|
||||
do {
|
||||
DocPutKey(doc,CH_SPACE,0);
|
||||
*_col=*_col+1;
|
||||
} while (*_col&7);
|
||||
break;
|
||||
|
||||
start:
|
||||
case 'ã': ptr="pi"; break;
|
||||
case 'é': ptr="theta"; break;
|
||||
case 'è': ptr="phi"; break;
|
||||
case 'ê': ptr="omega"; break;
|
||||
case 'ì': ptr="inf"; break;
|
||||
case 'æ': ptr="u"; break;
|
||||
case CH_SHIFT_SPACE: ptr=" "; break;
|
||||
end:
|
||||
DocPrint(doc,ptr);
|
||||
*_col=*_col+StrLen(ptr);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (CH_SPACE<=ch<0x7F || ch=='\n')
|
||||
DocPutKey(doc,ch,0);
|
||||
else
|
||||
DocPrint(doc,".");
|
||||
*_col=*_col+1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public CDoc *Doc2TXT(CDoc *doc_in)
|
||||
{//Cvt $LK,"DolDoc",A="FI:::/Doc/DolDocOverview.DD"$ doc to plain text.
|
||||
CDocEntry *doc_e,*doc_e2;
|
||||
I64 y,col;
|
||||
CDoc *doc_out=DocNew;
|
||||
Bool unlock_doc_in=DocLock(doc_in),no_bwd,line_has_html_code=FALSE;
|
||||
DocRecalc(doc_in);
|
||||
|
||||
doc_out->flags|=DOCF_PLAIN_TEXT|DOCF_NO_CURSOR;
|
||||
|
||||
doc_e=doc_in->head.next;
|
||||
col=doc_e->x;
|
||||
y=doc_e->y;
|
||||
while (doc_e!=doc_in) {
|
||||
if (!(doc_e->de_flags&DOCEF_SKIP)) {
|
||||
while (y<doc_e->y) {
|
||||
TXTPutS(doc_out,"\n",&col);
|
||||
y++;
|
||||
col=0;
|
||||
line_has_html_code=FALSE;
|
||||
}
|
||||
if (doc_e->type_u8==DOCT_HTML_CODE)
|
||||
line_has_html_code=TRUE;
|
||||
|
||||
no_bwd=TRUE;
|
||||
doc_e2=doc_e->next;
|
||||
while (doc_e2!=doc_in && doc_e2->y==doc_e->y) {
|
||||
if (doc_e2->x<doc_e->x) {
|
||||
no_bwd=FALSE;
|
||||
break;
|
||||
}
|
||||
doc_e2=doc_e2->next;
|
||||
}
|
||||
if (no_bwd && !(doc_e->type_u8==DOCT_NEW_LINE && line_has_html_code))
|
||||
while (col<doc_e->x)
|
||||
TXTPutS(doc_out," ",&col);
|
||||
|
||||
switch (doc_e->type_u8) {
|
||||
case DOCT_TEXT:
|
||||
TXTPutS(doc_out,doc_e->tag,&col);
|
||||
break;
|
||||
case DOCT_TAB:
|
||||
TXTPutS(doc_out,"\t",&col);
|
||||
break;
|
||||
case DOCT_HTML_CODE:
|
||||
break;
|
||||
case DOCT_SPRITE:
|
||||
break;
|
||||
default:
|
||||
if (doc_e->de_flags&DOCEF_TAG)
|
||||
TXTPutS(doc_out,doc_e->tag,&col);
|
||||
}
|
||||
}
|
||||
doc_e=doc_e->next;
|
||||
}
|
||||
while (y<doc_e->y) {
|
||||
TXTPutS(doc_out,"\n",&col);
|
||||
y++;
|
||||
col=0;
|
||||
}
|
||||
doc_out->cur_entry=&doc_out->head;
|
||||
DocRecalc(doc_out);
|
||||
|
||||
if (unlock_doc_in)
|
||||
DocUnlock(doc_in);
|
||||
return doc_out;
|
||||
}
|
||||
|
||||
#help_index "Cmd Line (Typically);DolDoc/Conversion;DolDoc/Cmd Line (Typically)"
|
||||
public U0 ToTXT(U8 *_in_name,U8 *_out_name=NULL,I64 width=70)
|
||||
{//Convert $LK,"DolDoc",A="FI:::/Doc/DolDocOverview.DD"$file to plain text.
|
||||
U8 *in_name,*out_name;
|
||||
CDoc *doc_in,*doc_out;
|
||||
|
||||
SettingsPush; //See $LK,"SettingsPush",A="MN:SettingsPush"$
|
||||
WinHorz(0,width-1); //Sets doc width for word wrap.
|
||||
|
||||
in_name=DftExt(_in_name,"DD.Z");
|
||||
if (_out_name)
|
||||
out_name=DftExt(_out_name,"TXT");
|
||||
else
|
||||
out_name=ChgExt(_in_name,"TXT");
|
||||
|
||||
doc_in=DocRead(in_name);
|
||||
doc_out=Doc2TXT(doc_in);
|
||||
StrCpy(&doc_out->filename.name,out_name);
|
||||
|
||||
SettingsPop;
|
||||
|
||||
DocWrite(doc_out);
|
||||
DocDel(doc_in);
|
||||
DocDel(doc_out);
|
||||
Free(in_name);
|
||||
Free(out_name);
|
||||
}
|
||||
Reference in new issue
Block a user