TempleOS V5.03 Nightly (ISO SHA-1 54758c6)

This commit is contained in:
Terry A. Davis authored and TempleOS-bot committed 2018-09-09 11:35:00 +02:00
1 parent 6028804a5a
commit 66b9e3183f
30 files changed
+9711 -3

No files matched your search

+444
View File
@@ -0,0 +1,444 @@
#help_index "Info;File/Cmd Line (Typically);Cmd Line (Typically)"
Bool ChkDskConfirm(Bool *_fix,Bool *_confirm)
{
if (*_fix && *_confirm) {
"Fix ";
if (!YorN)
*_fix=FALSE;
*_confirm=FALSE;
}
return *_fix;
}
I64 RedSeaChkDskLst(CDrv *dv,CDirEntry *tmpde1,
U8 *bits,U8 *bits2,I64 size,I64 bpc)
{
CDirEntry *tmpde2;
I64 i,j,errs=0;
while (tmpde1) {
tmpde2=tmpde1->next;
if (tmpde1->attr & RS_ATTR_DIR && tmpde1->sub)
errs+=RedSeaChkDskLst(dv,tmpde1->sub,bits,bits2,size,bpc);
j=(tmpde1->size+bpc-1)/bpc;
for (i=0;i<j;i++) {
if (i+tmpde1->cluster-dv->data_area>size) {
PrintErr("Invalid Cluster:%s Cluster:%X\n",tmpde1->full_name,
i+tmpde1->cluster);
errs++;
break;
}
if (LBts(bits,i+tmpde1->cluster-dv->data_area)) {
PrintErr("Dbl Alloc:%s Cluster:%X\n",tmpde1->full_name,
i+tmpde1->cluster);
errs++;
}
if (!LBtr(bits2,i+tmpde1->cluster-dv->data_area)) {
PrintErr("UnAlloc:%s Cluster:%X\n",tmpde1->full_name,
i+tmpde1->cluster);
errs++;
}
}
DirEntryDel(tmpde1);
tmpde1=tmpde2;
}
return errs;
}
I64 RedSeaChkDsk(U8 drv_let,Bool *_fix,Bool *_confirm)
{
I64 i,j,bpc,size,errs=0;
CDrv *dv=Let2Drv(drv_let),*old_dv=Fs->cur_dv;
U8 *files_find_mask=MStrPrint("%c:/*",Drv2Let(dv)),
*old_dir=StrNew(Fs->cur_dir),
*bits,*bits2;
CDirEntry *ptr,*ptr2;
Drv(drv_let);
"Scanning...\n";
size=(dv->size-(dv->data_area-dv->drv_offset))/dv->spc;
bpc=dv->spc<<BLK_SIZE_BITS;
bits=CAlloc((size+7)>>3);
bits2=CAlloc((size+7)>>3+BLK_SIZE);
RBlks(dv,bits2,dv->fat1,((size+7)>>3+BLK_SIZE-1)>>BLK_SIZE_BITS);
//Get Root Dir size
ptr2=MAlloc(bpc);
RBlks(dv,ptr2,dv->root_cluster,1);
ptr=ptr2(U8 *)-offset(CDirEntry.start);
j=(ptr->size+bpc-1)/bpc;
Free(ptr2);
for (i=0;i<j;i++) {
if (i+dv->root_cluster-dv->data_area>size) {
PrintErr("Invalid Cluster: RootDir Cluster:%X\n",i+dv->root_cluster);
errs++;
break;
}
if (LBts(bits,i+dv->root_cluster-dv->data_area)) {
PrintErr("Dbl Alloc: RootDir Cluster:%X\n",i+dv->root_cluster);
errs++;
}
if (!LBtr(bits2,i+dv->root_cluster-dv->data_area)) {
PrintErr("UnAlloc: RootDir Cluster:%X\n",i+dv->root_cluster);
errs++;
}
}
errs+=RedSeaChkDskLst(dv,FilesFind(files_find_mask,FUF_RECURSE),
bits,bits2,size,bpc);
for (i=1;i<size;i++)
if (Bt(bits2,i)) {
PrintWarn("Shouldn't Alloc Cluster:%0X\n",i+dv->data_area);
errs++;
if (ChkDskConfirm(_fix,_confirm))
RedSeaFreeClusters(dv,i+dv->data_area,1);
}
Free(files_find_mask);
Free(bits);
Free(bits2);
Drv(Drv2Let(old_dv));
Cd(old_dir);
Free(old_dir);
return errs;
}
I64 FAT32ChkDskLst(CDrv *dv,CDirEntry *tmpde1,
U8 *bits,U32 *bits2,I64 size,I64 bpc)
{
CDirEntry *tmpde2;
I64 i,c,errs=0;
while (tmpde1) {
tmpde2=tmpde1->next;
if (tmpde1->attr & RS_ATTR_DIR && tmpde1->sub)
errs+=FAT32ChkDskLst(dv,tmpde1->sub,bits,bits2,size,bpc);
i=0;
c=tmpde1->cluster;
while (0<c<0x0FFFFFF8) {
if (c>size) {
PrintErr("Invalid Cluster:%s Cluster:%X\n",tmpde1->full_name,c);
errs++;
break;
}
if (LBts(bits,c)) {
PrintErr("Dbl Alloc:%s Cluster:%X\n",tmpde1->full_name,c);
errs++;
}
if (!bits2[c]) {
PrintErr("UnAlloc:%s Cluster:%X\n",tmpde1->full_name,c);
errs++;
} else
bits2[c]=0;
c=ClusterNumNext(dv,c);
i++;
}
if (!(tmpde1->attr & RS_ATTR_DIR)) {
i*=bpc;
if (tmpde1->size>i) {
PrintErr("Alloced File Too Short:%s\n",tmpde1->full_name);
errs++;
}
if (i>tmpde1->size+bpc-1) {
PrintWarn("Alloced File Too Long:%s\n",tmpde1->full_name);
errs++;
}
}
DirEntryDel(tmpde1);
tmpde1=tmpde2;
}
return errs;
}
I64 FAT32ChkDsk(U8 drv_let,Bool *_fix,Bool *_confirm)
{
I64 i,bpc,size,c,errs=0;
CDrv *dv=Let2Drv(drv_let),*old_dv=Fs->cur_dv;
U8 *files_find_mask=MStrPrint("%c:/*",Drv2Let(dv)),
*old_dir=StrNew(Fs->cur_dir),
*bits;
U32 *bits2;
Drv(drv_let);
"Scanning...\n";
size=(dv->size-(dv->data_area-dv->drv_offset))/dv->spc;
bpc=dv->spc<<BLK_SIZE_BITS;
bits=CAlloc((size+7)>>3);
bits2=CAlloc(size*4+BLK_SIZE);
RBlks(dv,bits2,dv->fat1,(size*4+BLK_SIZE-1)>>BLK_SIZE_BITS);
c=dv->root_cluster;
while (0<c<0x0FFFFFF8) {
if (c>size) {
PrintErr("Invalid Cluster: RootDir Cluster:%X\n",c);
errs++;
break;
}
if (LBts(bits,c)) {
PrintErr("Dbl Alloc: RootDir Cluster:%X\n",c);
errs++;
}
if (!bits2[c]) {
PrintErr("UnAlloc: RootDir Cluster:%X\n",c);
errs++;
} else
bits2[c]=0;
c=ClusterNumNext(dv,c);
}
errs+=FAT32ChkDskLst(dv,FilesFind(files_find_mask,FUF_RECURSE),
bits,bits2,size,bpc);
bits2[1]=0; //See $LK,"FAT32Fmt",A="MN:FAT32Fmt"$()
for (i=1;i<size;i++)
if (bits2[i]) {
PrintWarn("Shouldn't Alloc Cluster:%0X\n",i);
errs++;
if (ChkDskConfirm(_fix,_confirm))
FAT32FreeClusters(dv,i);
}
Free(files_find_mask);
Free(bits);
Free(bits2);
Drv(Drv2Let(old_dv));
Cd(old_dir);
Free(old_dir);
return errs;
}
public I64 ChkDsk(U8 drv_let=0,Bool fix=FALSE,Bool confirm=TRUE)
{//Check disk for allocation errors and, optionally, fix.
//You probably want to reformat and reinstall.
I64 errs=0;
CDrv *dv=Let2Drv(drv_let);
switch (dv->fs_type) {
case FSt_REDSEA:
errs=RedSeaChkDsk(drv_let,&fix,&confirm);
break;
case FSt_FAT32:
errs=FAT32ChkDsk(drv_let,&fix,&confirm);
break;
default:
PrintErr("File System Not Supported\n");
}
if (errs) {
if (fix)
"It might be a little better. ";
"Copy files to another partition or CD/DVD, "
"reformat, and copy back. "
"Or, copy from a back-up.\n";
}
return errs;
}
U0 RedSeaDrvView(U8 drv_let=0)
{
CDrv *dv=Let2Drv(drv_let);
I64 lohi,c1,i,x,y,l=(GR_HEIGHT-3*FONT_HEIGHT)*(GR_WIDTH-FONT_WIDTH<<1),
s=dv->size+dv->drv_offset-dv->data_area;
U8 *bitmap;
CDC *dc=DCAlias;
SettingsPush; //See $LK,"SettingsPush",A="MN:SettingsPush"$
WinMax;
WinBorder(ON);
DocCursor;
DocClear;
DCFill;
try {
i=((s+7)>>3+BLK_SIZE-1)>>BLK_SIZE_BITS;
bitmap=MAlloc(i<<BLK_SIZE_BITS);
RBlks(dv,bitmap,dv->fat1,i);
i=0;
for (y=0;y<GR_HEIGHT-3*FONT_HEIGHT;y++) {
if (ScanKey)
break;
for (x=0;x<GR_WIDTH-FONT_WIDTH<<1;x++) {
lohi=i*s;
c1=lohi/l;
if (Bt(bitmap,c1))
dc->color=ROP_XOR+BLUE^TRANSPARENT;
else
dc->color=ROP_XOR+WHITE^TRANSPARENT;
GrPlot(dc,x,y);
i++;
}
}
Free(bitmap);
} catch
DrvUnlock(dv);
GetChar;
SettingsPop;
DCFill;
DCDel(dc);
}
U0 FAT32DrvView(U8 drv_let=0)
{
CDrv *dv=Let2Drv(drv_let);
I64 lohi,c1,i,x,y,l=(GR_HEIGHT-3*FONT_HEIGHT)*(GR_WIDTH-FONT_WIDTH<<1),
s=(dv->size+dv->spc-1)/dv->spc-(2+dv->data_area-dv->drv_offset);
U32 *bitmap;
CDC *dc=DCAlias;
SettingsPush; //See $LK,"SettingsPush",A="MN:SettingsPush"$
WinMax;
WinBorder(ON);
DocCursor;
DocClear;
DCFill;
try {
i=(s*4+BLK_SIZE-1)>>BLK_SIZE_BITS;
bitmap=MAlloc(i<<BLK_SIZE_BITS);
RBlks(dv,bitmap,dv->fat1,i);
i=0;
for (y=0;y<GR_HEIGHT-3*FONT_HEIGHT;y++) {
if (ScanKey)
break;
for (x=0;x<GR_WIDTH-FONT_WIDTH<<1;x++) {
lohi=i*s;
c1=lohi/l;
if (bitmap[c1])
dc->color=ROP_XOR+BLUE^TRANSPARENT;
else
dc->color=ROP_XOR+WHITE^TRANSPARENT;
GrPlot(dc,x,y);
i++;
}
}
Free(bitmap);
} catch
DrvUnlock(dv);
GetChar;
SettingsPop;
DCFill;
DCDel(dc);
}
public U0 DrvView(U8 drv_let=0)
{//Drive view. Graph the allocation map's fragmentation.
CDrv *dv=Let2Drv(drv_let),*old_dv=Fs->cur_dv;
Drv(drv_let);
switch (dv->fs_type) {
case FSt_REDSEA:
RedSeaDrvView(drv_let);
break;
case FSt_FAT32:
FAT32DrvView(drv_let);
break;
default:
PrintErr("File System Not Supported\n");
}
Drv(Drv2Let(old_dv));
}
public U0 DskView(U8 drv_let=0)
{//Disk view. Pie chart of partition sizes.
I64 i,j,attr,
h=Fs->pix_width,
v=Fs->pix_height,
radius;
CDrv *dv;
CBlkDev *bd=Let2BlkDev(drv_let);
CDC *dc=DCAlias;
F64 sect_start,sect_end;
SettingsPush; //See $LK,"SettingsPush",A="MN:SettingsPush"$
DocCursor;
DocClear;
DCFill;
if (h<v)
radius=0.4*h;
else
radius=0.4*v;
dc->color=BLACK;
GrCircle(dc,h>>1,v>>1,radius);
j=1;
for (i=0;i<DRVS_NUM;i++) {
dv=&blkdev.drvs[i];
if (bd==dv->bd && dv->fs_type) {
sect_start=-(dv->drv_offset*2*ã/(bd->max_blk+1));
sect_end =-((dv->drv_offset+dv->size)*2*ã/(bd->max_blk+1));
dc->color=BLACK;
GrLine(dc,h>>1,v>>1,
h>>1+radius*Cos(sect_start),
v>>1+radius*Sin(sect_start));
GrLine(dc,h>>1,v>>1,
h>>1+radius*Cos(sect_end),
v>>1+radius*Sin(sect_end));
attr=DrvTextAttrGet(Drv2Let(dv));
dc->color=attr&15;
GrPrint(dc,0,v-FONT_HEIGHT*j,"%C %-8Z",Drv2Let(dv),
dv->fs_type,"ST_DRV_TYPES");
dc->color.c1=attr>>4;
dc->color|=ROPF_DITHER;
GrFloodFill(dc,
h>>1+(radius-4)*Cos((sect_start+sect_end)/2),
v>>1+(radius-4)*Sin((sect_start+sect_end)/2),FALSE);
j++;
}
}
GetChar(,FALSE);
SettingsPop;
DCFill;
DCDel(dc);
}
I64 RedSeaUnusedDrvSpace(U8 drv_let=0)
{
CDrv *dv=Let2Drv(drv_let);
I64 res=0,i,l;
U8 *bitmap;
try {
l=dv->size+dv->drv_offset-dv->data_area;
i=((l+7)>>3+BLK_SIZE-1)>>BLK_SIZE_BITS;
bitmap=MAlloc(i<<BLK_SIZE_BITS);
RBlks(dv,bitmap,dv->fat1,i);
for (i=0;i<l;i++)
if (!Bt(bitmap,i))
res++;
Free(bitmap);
} catch
DrvUnlock(dv);
return res*BLK_SIZE*dv->spc;
}
I64 FAT32UnusedDrvSpace(U8 drv_let=0)
{
CDrv *dv=Let2Drv(drv_let);
I64 res=0,i,l;
U32 *bitmap;
try {
l=(dv->size+dv->spc-1)/dv->spc-(2+dv->data_area-dv->drv_offset);
i=(l*4+BLK_SIZE-1)>>BLK_SIZE_BITS;
bitmap=MAlloc(i<<BLK_SIZE_BITS);
RBlks(dv,bitmap,dv->fat1,i);
for (i=0;i<l;i++)
if (!bitmap[i])
res++;
Free(bitmap);
} catch
DrvUnlock(dv);
return res*BLK_SIZE*dv->spc;
}
public I64 UnusedDrvSpace(U8 drv_let=0)
{//Returns unused size in bytes.
CDrv *dv=Let2Drv(drv_let),*old_dv=Fs->cur_dv;
U8 *old_dir=StrNew(Fs->cur_dir);
I64 res=0;
Drv(drv_let);
switch (dv->fs_type) {
case FSt_REDSEA:
res=RedSeaUnusedDrvSpace(drv_let);
break;
case FSt_FAT32:
res=FAT32UnusedDrvSpace(drv_let);
break;
default:
PrintErr("File System Not Supported\n");
}
Drv(Drv2Let(old_dv));
Cd(old_dir);
Free(old_dir);
return res;
}
+167
View File
@@ -0,0 +1,167 @@
#help_index "Install;File/Cmd Line (Typically);Cmd Line (Typically)"
#define ROUND_DRV_TO (63*255)
#define DRV_HEADER 63
class CPlannedDrv
{
CPlannedDrv *next,*last;
I64 size;
Bool pri;
};
public I64 PrtDsk(U8 drv_let=0,...)
{/*Partition the disk containing partition drv_let.
drv_let=0 means add new drive that is not already mounted.
>PrtDsk('C',0.5,0.25,0.25); //Make three. 50% C, 25% D, 25% E, round-up to blk.
*/
CBlkDev *bd;
CPlannedDrv head,*tmppp;
CMasterBoot mbr;
Bool pri=TRUE;
I64 ext_base,drv_let2,pri_cnt=0,i,start_offset,offset,
total,remaining,cur_arg=0;
"This command does not play well\n"
"with other operating systems.\n"
"You really should use another\n"
"operating system's partitioner.\n"
"If you use this, it may, in fact,\n"
"make your hard drive impossible\n"
"to repartition with other operating\n"
"until you set block zero to zero\n"
"with $$LK,\"BootMHDZero\",\"MN:BootMHDZero\"$$()\n\n\n"
"Continue";
if (argc<=cur_arg && !YorN)
return 0;
'\n';
if (drv_let && !Let2BlkDev(drv_let,FALSE))
drv_let=0;
if (!drv_let && !(drv_let=Mount(TRUE)) ||
!(bd=Let2BlkDev(drv_let,FALSE)) || bd->type!=BDT_ATA)
return 0;
total=bd->max_blk+1;
QueInit(&head);
drv_let2=bd->first_drv_let;
remaining=FloorU64(bd->max_blk+1,ROUND_DRV_TO);
while (FloorU64(remaining,ROUND_DRV_TO)>=ROUND_DRV_TO) {
tmppp=MAlloc(sizeof(CPlannedDrv));
do {
"$$RED$$Partition %C$$FG$$\n",drv_let2;
tmppp->pri=FALSE;
if (pri) {
"Primary Partition";
if (argc>cur_arg || YorN) {
pri_cnt++;
tmppp->pri=TRUE;
if (pri_cnt==3)
pri=FALSE;
} else
pri=FALSE;
}
"\nBlocks Remaining:%d (0x%X)\n",
remaining-DRV_HEADER,remaining-DRV_HEADER;
if (argc>cur_arg)
tmppp->size=MinI64(CeilU64(MaxI64(remaining,DRV_HEADER),ROUND_DRV_TO),
CeilU64(argv[cur_arg++](F64)*total,ROUND_DRV_TO));
else
tmppp->size=CeilU64(GetI64("Size in Blocks :",
remaining-DRV_HEADER)+DRV_HEADER,ROUND_DRV_TO);
} while (!(ROUND_DRV_TO<=tmppp->size<=FloorU64(remaining,ROUND_DRV_TO)));
QueIns(tmppp,head.last);
remaining-=tmppp->size;
drv_let2++;
}
"\n\n!!! Repartition Drive !!!\n\n";
tmppp=head.next;
drv_let2=bd->first_drv_let;
while (tmppp!=&head) {
"Drive %C:%08X ",drv_let2,tmppp->size;
if (tmppp->pri)
"Primary\n";
else
"Logical\n";
tmppp=tmppp->next;
drv_let2++;
}
if (!argc && !AreYouSure)
goto pd_done;
remaining=FloorU64(bd->max_blk+1,ROUND_DRV_TO)-ROUND_DRV_TO;
tmppp=head.next;
MemSet(&mbr,0,BLK_SIZE);
mbr.signature=0xAA55;
offset=0;
for (i=0;i<pri_cnt;i++) {
mbr.p[i].active=0x80;
mbr.p[i].start_head=0;
mbr.p[i].start_cyl=0x101;
mbr.p[i].type=1; //Will get set different.
mbr.p[i].end_head=0xFE;
mbr.p[i].end_cyl=0xFFFF;
mbr.p[i].offset=DRV_HEADER+offset;
mbr.p[i].size=tmppp->size-DRV_HEADER;
offset+=tmppp->size;
remaining-=tmppp->size;
tmppp=tmppp->next;
}
if (!i) i++;
if (tmppp!=&head) {
mbr.p[i].active=0x80;
mbr.p[i].start_head=0;
mbr.p[i].start_cyl=0x101;
mbr.p[i].type=0xF;
mbr.p[i].end_head=0xFE;
mbr.p[i].end_cyl=0xFFFF;
mbr.p[i].offset=offset;
mbr.p[i].size=remaining;
ext_base=offset;
}
ATAWriteBlks(bd,&mbr,0,1);
while (tmppp!=&head) {
start_offset=offset;
MemSet(&mbr,0,BLK_SIZE);
mbr.signature=0xAA55;
mbr.p[0].active=0x80;
mbr.p[0].start_head=1;
mbr.p[0].start_cyl=0x101;
mbr.p[0].type=1; //Will get set different.
mbr.p[0].end_head=0xFE;
mbr.p[0].end_cyl=0xFFFF;
mbr.p[0].offset=DRV_HEADER;
mbr.p[0].size=tmppp->size-DRV_HEADER;
offset+=tmppp->size;
tmppp=tmppp->next;
if (tmppp!=&head) {
mbr.p[1].active=0x80;
mbr.p[1].start_head=0;
mbr.p[1].start_cyl=0x101;
mbr.p[1].type=5;
mbr.p[1].end_head=0xFE;
mbr.p[1].end_cyl=0xFFFF;
mbr.p[1].offset=offset-ext_base;
mbr.p[1].size=tmppp->size;
}
ATAWriteBlks(bd,&mbr,start_offset,1);
}
bd->flags&=~(BDF_INITIALIZED | BDF_INIT_IN_PROGRESS);
BlkDevAdd(bd,,FALSE,TRUE);
for (i=bd->first_drv_let;i<drv_let2;i++)
Fmt(i,,FALSE);
pd_done:
while (head.next!=&head) {
tmppp=head.next;
QueRem(tmppp);
Free(tmppp);
}
return total;
}
+409
View File
@@ -0,0 +1,409 @@
#help_index "Snd"
public U0 SndTaskEndCB()
{//Will turn-off snd when a task gets killed.
Snd;
Exit;
}
#help_index "Snd/Math;Math"
public F64 Saw(F64 t,F64 period)
{//Sawtooth. 0.0 - 1.0 think "(Sin+1)/2"
if (period) {
if (t>=0.0)
return t%period/period;
else
return 1.0+t%period/period;
} else
return 0.0;
}
public F64 FullSaw(F64 t,F64 period)
{//Plus&Minus Sawtooth. 1.0 - -1.0 think "Sin"
if (period) {
if (t>=0.0)
return 2.0*(t%period/period)-1.0;
else
return 2.0*(t%period/period)+1.0;
} else
return 0.0;
}
public F64 Caw(F64 t,F64 period)
{//Cawtooth. 1.0 - 0.0 think "(Cos+1)/2"
if (period) {
if (t>=0.0)
return 1.0-t%period/period;
else
return -(t%period)/period;
} else
return 1.0;
}
public F64 FullCaw(F64 t,F64 period)
{//Plus&Minus Cawtooth. 1.0 - -1.0 think "Cos"
if (period) {
if (t>=0.0)
return -2.0*(t%period/period)+1.0;
else
return -2.0*(t%period/period)-1.0;
} else
return 1.0;
}
public F64 Tri(F64 t,F64 period)
{//Triangle waveform. 0.0 - 1.0 - 0.0
if (period) {
t=2.0*(Abs(t)%period)/period;
if (t<=1.0)
return t;
else
return 2.0-t;
} else
return 0.0;
}
public F64 FullTri(F64 t,F64 period)
{//Plus&Minus Triangle waveform. 0.0 - 1.0 - 0.0 - -1.0 -0.0
if (period) {
t=4.0*(t%period)/period;
if (t<=-1.0) {
if (t<=-3.0)
return t+4.0;
else
return -2.0-t;
} else {
if (t<=1.0)
return t;
else if (t<=3.0)
return 2.0-t;
else
return t-4.0;
}
} else
return 0.0;
}
#help_index "Snd/Music"
public class CMusicGlbls
{
U8 *cur_song;
CTask *cur_song_task;
I64 octave;
F64 note_len;
U8 note_map[7];
Bool mute;
I64 meter_top,meter_bottom;
F64 tempo,stacatto_factor;
//If you wish to sync with a
//note in a Play() string. 0 is the start
I64 play_note_num;
F64 tM_correction,last_Beat,last_tM;
} music={NULL,NULL,4,1.0,{0,2,3,5,7,8,10},FALSE,4,4,2.5,0.9,0,0,0,0};
#help_index "Snd/Music;Time/Seconds"
public F64 tM()
{//Time in seconds synced to music subsystem.
return (cnts.jiffies+music.tM_correction)/JIFFY_FREQ;
}
public F64 Beat()
{//Time in music beats.
F64 res,cur_tM;
PUSHFD
CLI
if (mp_cnt>1)
while (LBts(&sys_semas[SEMA_TMBEAT],0))
PAUSE
cur_tM=tM;
res=music.last_Beat;
if (music.tempo)
res+=(cur_tM-music.last_tM)*music.tempo;
music.last_tM=cur_tM;
music.last_Beat=res;
LBtr(&sys_semas[SEMA_TMBEAT],0);
POPFD
return res;
}
#help_index "Snd/Music"
U8 *MusicSetOctave(U8 *st)
{
I64 ch;
ch=*st++;
while ('0'<=ch<='9') {
music.octave=ch-'0';
ch=*st++;
}
return --st;
}
U8 *MusicSetMeter(U8 *st)
{
I64 ch;
ch=*st++;
while (ch=='M') {
ch=*st++;
if ('0'<=ch<='9') {
music.meter_top=ch-'0';
ch=*st++;
}
if (ch=='/')
ch=*st++;
if ('0'<=ch<='9') {
music.meter_bottom=ch-'0';
ch=*st++;
}
}
return --st;
}
U8 *MusicSetNoteLen(U8 *st)
{
Bool cont=TRUE;
do {
switch (*st++) {
case 'w': music.note_len=4.0; break;
case 'h': music.note_len=2.0; break;
case 'q': music.note_len=1.0; break;
case 'e': music.note_len=0.5; break;
case 's': music.note_len=0.25; break;
case 't': music.note_len=2.0*music.note_len/3.0; break;
case '.': music.note_len=1.5*music.note_len; break;
default:
st--;
cont=FALSE;
}
} while (cont);
return st;
}
public I8 Note2Ona(I64 note,I64 octave=4)
{//Note to ona. Mid C is ona=51, note=3 and octave=4.
if (note<3)
return (octave+1)*12+note;
else
return octave*12+note;
}
public I8 Ona2Note(I8 ona)
{//Ona to note in octave. Mid C is ona=51, note=3 and octave=4.
return ona%12;
}
public I8 Ona2Octave(I8 ona)
{//Ona to octave. Mid C is ona=51, note=3 and octave=4.
I64 note=ona%12,octave=ona/12;
if (note<3)
return octave-1;
else
return octave;
}
public U0 Play(U8 *st,U8 *words=NULL)
{/* Notes are entered with a capital letter.
Octaves are entered with a digit and
stay set until changed. Mid C is octave 4.
Durations are entered with
'w' whole note
'h' half note
'q' quarter note
'e' eighth note
't' sets to 2/3rds the current duration
'.' sets to 1.5 times the current duration
durations stay set until changed.
'(' tie, placed before the note to be extended
$LK,"music.meter_top",A="MN:CMusicGlbls"$,$LK,"music.meter_bottom",A="MN:CMusicGlbls"$ is set with
"M3/4"
"M4/4"
etc.
Sharp and flat are done with '#' or 'b'.
The var music.stacatto_factor can
be set to a range from 0.0 to 1.0.
The var music.tempo is quarter-notes
per second. It defaults to
2.5 and gets faster when bigger.
*/
U8 *word,*last_st;
I64 note,octave,i=0,ona,timeout_val,timeout_val2;
Bool tie;
F64 d,on_jiffies,off_jiffies;
music.play_note_num=0;
while (*st) {
timeout_val=cnts.jiffies;
tie=FALSE;
do {
last_st=st;
if (*st=='(') {
tie=TRUE;
st++;
} else {
st=MusicSetMeter(st);
st=MusicSetOctave(st);
st=MusicSetNoteLen(st);
}
} while (st!=last_st);
if (!*st) break;
note=*st++-'A';
if (note<7) {
note=music.note_map[note];
octave=music.octave;
if (*st=='b') {
note--;
if (note==2)
octave--;
st++;
} else if (*st=='#') {
note++;
if (note==3)
octave++;
st++;
}
ona=Note2Ona(note,octave);
} else
ona=0;
if (words && (word=LstSub(i++,words)) && StrCmp(word," "))
"%s",word;
d=JIFFY_FREQ*music.note_len/music.tempo;
on_jiffies =d*music.stacatto_factor;
off_jiffies =d*(1.0-music.stacatto_factor);
timeout_val+=on_jiffies;
timeout_val2=timeout_val+off_jiffies;
if (!music.mute)
Snd(ona);
SleepUntil(timeout_val);
music.tM_correction+=on_jiffies-ToI64(on_jiffies);
if (!music.mute && !tie)
Snd;
SleepUntil(timeout_val2);
music.tM_correction+=off_jiffies-ToI64(off_jiffies);
music.play_note_num++;
}
}
U0 MusicSettingsRst()
{
music.play_note_num=0;
music.stacatto_factor=0.9;
music.tempo=2.5;
music.octave=4;
music.note_len=1.0;
music.meter_top=4;
music.meter_bottom=4;
SndRst;
PUSHFD
CLI
if (mp_cnt>1)
while (LBts(&sys_semas[SEMA_TMBEAT],0))
PAUSE
music.last_tM=tM;
music.last_Beat=0.0;
LBtr(&sys_semas[SEMA_TMBEAT],0);
POPFD
}
MusicSettingsRst;
U0 CurSongTask()
{
Fs->task_end_cb=&SndTaskEndCB;
while (TRUE)
Play(music.cur_song);
}
#help_index "Snd"
#define SE_NOISE 0
#define SE_SWEEP 1
class CSoundEffectFrame
{
I32 type;
I8 ona1,ona2;
F64 duration;
};
U0 SoundEffectEndTaskCB()
{
Free(FramePtr("CSoundEffectFrame"));
music.mute--;
SndTaskEndCB;
}
U0 SoundEffectTask(CSoundEffectFrame *ns)
{
I64 i,ona;
F64 t0=tS,t,timeout=t0+ns->duration;
FramePtrAdd("CSoundEffectFrame",ns);
Fs->task_end_cb=&SoundEffectEndTaskCB;
switch (ns->type) {
case SE_NOISE:
i=MaxI64(ns->ona2-ns->ona1,1);
while (tS<timeout) {
ona=RandU16%i+ns->ona1;
Snd(ona);
t=Clamp(3000.0/Ona2Freq(ona),1.0,50.0);
if (t+tS>timeout)
t=timeout-tS;
Sleep(t);
}
break;
case SE_SWEEP:
while (tS<timeout) {
t=(tS-t0)/ns->duration;
ona=(1.0-t)*ns->ona1+t*ns->ona2;
Snd(ona);
t=Clamp(3000.0/Ona2Freq(ona),1.0,50.0);
if (t+tS>timeout)
t=timeout-tS;
Sleep(t);
}
break;
}
}
public CTask *Noise(I64 mS,F64 min_ona,F64 max_ona)
{//Make white noise for given number of mS.
CSoundEffectFrame *ns;
if (mS>0) {
ns=MAlloc(sizeof(CSoundEffectFrame));
ns->type=SE_NOISE;
ns->duration=mS/1000.0;
ns->ona1=min_ona;
ns->ona2=max_ona;
music.mute++;
return Spawn(&SoundEffectTask,ns,"Noise",,Fs);
} else
return NULL;
}
public CTask *Sweep(I64 mS,F64 ona1,F64 ona2)
{//Sweep through freq range in given number of mS.
CSoundEffectFrame *ns;
if (mS>0) {
ns=MAlloc(sizeof(CSoundEffectFrame));
ns->type=SE_SWEEP;
ns->duration=mS/1000.0;
ns->ona1=ona1;
ns->ona2=ona2;
music.mute++;
return Spawn(&SoundEffectTask,ns,"Noise",,Fs);
} else
return NULL;
}
+58
View File
@@ -0,0 +1,58 @@
#help_index "Graphics/Device Contexts;Graphics/GR Files"
#define MV_FILE_MAX 0x007FF000
public I64 GR2MV(U8 *print_fmt="VID%03d.MV",
U8 *files_find_mask,U8 *fu_flags=NULL)
{/*Merge GR lst to MV file.
"+d" will delete GR list files.
*/
I64 fuf_flags=0,file_num=0,size;
CDirEntry *tmpde,*tmpde1;
U8 *base,*dst,*src,*st;
CDC *dc,*dc_base=DCNew(GR_WIDTH,GR_HEIGHT);
CDate cdt;
Bool old_silent;
ScanFlags(&fuf_flags,Define("ST_FILE_UTIL_FLAGS"),"+f+F");
ScanFlags(&fuf_flags,Define("ST_FILE_UTIL_FLAGS"),fu_flags);
tmpde=tmpde1=FilesFind(files_find_mask,fuf_flags&FUG_FILES_FIND);
if (progress1_max=LinkedLstCnt(tmpde1)) {
dst=base=MAlloc(MV_FILE_MAX);
while (tmpde) {
dc=GRRead(tmpde->full_name);
GrBlot(dc_base,dc->x0,dc->y0,dc);
if (dst+GR_FILE_MAX>base+MV_FILE_MAX) {
st=MStrPrint(print_fmt,file_num++);
FileWrite(st,base,dst-base);
Free(st);
dst=base;
cdt=dc->cdt;
dc=DCCopy(dc_base);
dc->cdt=cdt;
}
src=DCSave(dc,&size);
DCDel(dc);
MemCpy(dst,src,size);
dst+=size;
Free(src);
if (fuf_flags&FUF_DEL) {
old_silent=Silent;
Del(tmpde->full_name);
Silent(old_silent);
}
progress1++;
tmpde=tmpde->next;
}
if (dst>base) {
st=MStrPrint(print_fmt,file_num++);
FileWrite(st,base,dst-base);
Free(st);
}
Free(base);
}
progress1=progress1_max=0;
DirTreeDel(tmpde1);
DCDel(dc_base);
return file_num;
}
+96
View File
@@ -0,0 +1,96 @@
#help_index "ScrnCast;Graphics/Device Contexts;Graphics/GR Files"
#define MV_FILE_MAX 0x007FF000
public I64 GR2MV(U8 *print_fmt="VID%03d.MV",
U8 *files_find_mask,U8 *fu_flags=NULL)
{/*Merge GR lst to MV file.
"+d" will delete GR list files.
*/
I64 fuf_flags=0,file_num=0,size;
CDirEntry *tmpde,*tmpde1;
U8 *base,*dst,*src,*st;
CDC *dc,*dc_base=DCNew(GR_WIDTH,GR_HEIGHT);
CDate cdt;
Bool old_silent;
ScanFlags(&fuf_flags,Define("ST_FILE_UTIL_FLAGS"),"+f+F");
ScanFlags(&fuf_flags,Define("ST_FILE_UTIL_FLAGS"),fu_flags);
tmpde=tmpde1=FilesFind(files_find_mask,fuf_flags&FUG_FILES_FIND);
if (progress1_max=LinkedLstCnt(tmpde1)) {
dst=base=MAlloc(MV_FILE_MAX);
while (tmpde) {
dc=GRRead(tmpde->full_name);
GrBlot(dc_base,dc->x0,dc->y0,dc);
if (dst+GR_FILE_MAX>base+MV_FILE_MAX) {
st=MStrPrint(print_fmt,file_num++);
FileWrite(st,base,dst-base);
Free(st);
dst=base;
cdt=dc->cdt;
dc=DCCopy(dc_base);
dc->cdt=cdt;
}
src=DCSave(dc,&size);
DCDel(dc);
MemCpy(dst,src,size);
dst+=size;
Free(src);
if (fuf_flags&FUF_DEL) {
old_silent=Silent;
Del(tmpde->full_name);
Silent(old_silent);
}
progress1++;
tmpde=tmpde->next;
}
if (dst>base) {
st=MStrPrint(print_fmt,file_num++);
FileWrite(st,base,dst-base);
Free(st);
}
Free(base);
}
progress1=progress1_max=0;
DirTreeDel(tmpde1);
DCDel(dc_base);
return file_num;
}
#help_index "ScrnCast;Snd/AU Files"
public U0 SndShift(CSndData *head,F64 dt=0)
{//Shift CSndData in time.
CSndData *tmpsd,*tmpsd1;
if (dt) {
tmpsd=head->next;
while (tmpsd!=head) {
tmpsd1=tmpsd->next;
tmpsd->tS-=dt;
if (tmpsd->tS<tmpsd->last->tS) {
QueRem(tmpsd);
Free(tmpsd);
}
tmpsd=tmpsd1;
}
}
}
public I64 AUWrite(U8 *filename,CSndData *head,CDate *t0_now,F64 t0_tS)
{//Write AU file.
CSndData *tmpsd;
CAUData *base,*dst;
I64 size=(1+QueCnt(head))*sizeof(CAUData);
U8 *st=ExtDft(filename,"AU");
base=dst=MAlloc(size);
tmpsd=head;
do {
dst->cdt=t0_now(I64)+ToI64(CDATE_FREQ*(tmpsd->tS-t0_tS));
dst->ona=tmpsd->ona;
dst++;
tmpsd=tmpsd->next;
} while (tmpsd!=head);
FileWrite(st,base,dst(U8 *)-base(U8 *));
Free(base);
Free(st);
return size;
}