0001                                    User-Guide
0002 
0003                            Runtime Part 1:Graphics I
0004 
0005   Use the Fs->draw_it callback to draw something to the current window
0006 
0007 
0008 U0 DrawIt(CTask *,CDC *dc) {
0009   dc->color=BLUE;
0010   GrRect(dc,0,0,100,100);
0011 }
0012 Fs->draw_it=&DrawIt;
0013 
0014 
0015 
0016   The first argument is a pointer to the CTask being drawn,and the second 
0017 argument is a CDC drawing context,use some primitives to draw to the screen.
0018 
0019 -] GrRect
0020   
0021   GrRect(dc,200,200,100,100);
0022 
0023 -] GrPlot(single pixel)
0024   
0025   GrPlot(dc,200,200);
0026 
0027 -] GrFillCircle
0028   
0029   GrFillCircle(dc,100,100,50);
0030 
0031 -] GrCircle
0032   
0033   GrCircle(dc,100,100,50);
0034 
0035 -] GrLine
0036   
0037   GrLine(dc,100,100,0,0);
0038 
0039 -] GrPrint
0040   
0041   GrPrint(dc,100,100,"Hello World");
0042 
0043 -] GrBlot(copy dc to other dc)
0044   
0045   GrBlot(dc,100,100,new);
0046 
0047 -] DCClear
0048   
0049   DCClear(dc); //Resets Z buffer
0050 
0051 -] DCFill
0052   
0053   DCFill(dc,COLOR);
0054 
0055 
0056             Runtime Part 1:Graphics Transformations and 3D graphics
0057 
0058   TempleOS lets you do sexy stuff with the graphics like 3D graphics. At the 
0059 heart of this is a transformation matrix. Im not a math genius but luckily for 
0060 me there are functions for managing the math for me. Before we can use a 
0061 transformation matrix,we need to set the DCF_TRANSFORMATION flag in CDC->flags. 
0062 After wards you can use matrix functions to rotate your drawing things 
0063 cordanates
0064 
0065 
0066 CDC *dc=DCNew(100,100);
0067 Mat4x4IdentEqu(dc->r); //Assign a identity matrix(No transformation)
0068 DCFill;
0069 dc->flags|=DCF_TRANSFORMATION;
0070 F64 rotx=0;
0071 for(;rotx<=2*pi;rotx+=(2*pi/100.)) {
0072   DCFill(dc);
0073   Mat4x4IdentEqu(dc->r); //Reset our transformation
0074   Mat4x4RotZ(dc->r,rotx);
0075   Mat4x4TranslationEqu(dc->r,50,50,0);
0076   dc->color=YELLOW;
0077   GrRect3(dc,0,0,0,50,50); 
0078   DCFill;
0079   GrBlot(,100,100,dc);
0080   Sleep(33);
0081 }
0082 DCDel(dc);
0083 DCFill;
0084 
0085 
0086 Here are a list of (transformation) matrix goodies:
0087 -] Mat4x4RotX
0088   
0089   //Rotates around the X axis,used for Y-flipping
0090 
0091 -] Mat4x4RotY
0092   
0093   //Rotates around the Y axis,used for X-flipping
0094 
0095 -] Mat4x4RotZ
0096   
0097   //Rotates around the Z axis,use general 2D rotations
0098 
0099 -] Mat4x4Scale
0100   
0101   //Zooms a matrix
0102 
0103 -] Mat4x4TranslationEqu
0104   
0105   Mat4x4TranslationEqu(mat,x,y,z); //Sets the cordantes of a matrix
0106 
0107 -] Mat4x4TranslationAdd
0108   
0109   Mat4x4TranslationAdd(mat,x,y,z); //Add to the cordantes of a matrix
0110 
0111 -] Mat4x4MulXYZ
0112   
0113   Mat4x4MulXYZ(mat,&x,&y,&z); //THIS WILL TRANSFORM THE CORDANTES BY THE MATRIX
0114 
0115 
0116 You may want to do general math on matricies too:
0117 -] Mat4x4IdentEqu
0118   
0119   Mat4x4IdentEqu(mat); //This makes a normal matrix that doesnt do 
0120   transofrmations
0121 
0122 -] Mat4x4IdentNew
0123   
0124   I64 *malloced=Mat4x4IdentNew; //This makes a normal matrix that doesnt do 
0125   transofrmations
0126 
0127 -] Mat4x4MulMat4x4Equ
0128   
0129   Mat4x4MulMat4x4Equ(dst,a,b); //Multiplies a matrix to another matrix,ask a 
0130   genius what this actually does
0131 
0132 -] Mat4x4MulMat4x4New
0133   
0134   I64 *malloced=Mat4x4MulMat4x4Nw(a,b); //Same as above but MAlloced
0135 
0136 
0137   Sometimes in your 3D adventures you may want to make sure you draw things in 
0138 the distacne behind the things in the front. This is called Z-buffering. In 
0139 TempleOS this is easy-peasy. Just call DCDepthBufAlloc(dc). This will handle 
0140 your depths for you.
0141 
0142 Here is a cube thing for you:
0143 
0144 
0145 CD3I32 poly[4]= 
0146 {{-100,-100,-100},{100,-100,-100},{100,100,-100},{-100,100,-100}};
0147 I64 colors[4]= {BLUE,YELLOW,GREEN,CYAN};
0148 CDC *dc=DCNew(200,200);
0149 dc->r=Mat4x4IdentNew;
0150 DCDepthBufAlloc(dc);
0151 DCFill;
0152 dc->flags|=DCF_TRANSFORMATION;
0153 F64 rotx=0,roty;
0154 CD3I32 cube[6][6];
0155 I64 i=0,i2=0;
0156 I64 *trans=Mat4x4IdentNew; 
0157 for(rotx=0.; rotx<=(2.*pi)-1.; rotx+=2*pi/4.) {
0158   Mat4x4IdentEqu(trans);
0159   Mat4x4RotX(trans,rotx);
0160   Mat4x4RotY(trans,roty);
0161   for(i2=0; i2!=4; i2++) {
0162     MemCpy(&cube[i][i2],&poly[i2],sizeof(CD3I32));
0163     Mat4x4MulXYZ(trans,&cube[i][i2].x,&cube[i][i2].y,&cube[i][i2].z);
0164   }
0165   i++;
0166 }
0167 for(rotx=0; rotx<=2*pi; rotx+=(2*pi/100.)) {
0168   DCFill(dc);
0169   DCDepthBufRst(dc);
0170   Mat4x4IdentEqu(dc->r);
0171   Mat4x4RotX(dc->r,rotx);
0172   Mat4x4RotY(dc->r,rotx);
0173   Mat4x4RotZ(dc->r,rotx);
0174   Mat4x4Scale(dc->r,.5);
0175   Mat4x4TranslationEqu(dc->r,0,0,3000);
0176   for(i2=0; i2!=6; i2++) {
0177     dc->color=colors[i2];
0178     GrFillPoly3(dc,4,cube[i2]);
0179    }
0180    DCFill;
0181    GrBlot(,100,100,dc);
0182    Sleep(33);
0183 }
0184 DCDel(dc);
0185 DCFill;
0186 
0187 
0188   If you ran the above example,the cube looks flat,THIS IS BECUASE YOU NEED TO 
0189 MAKE THINGS SHRINK IN THE DISTANCE
0190 
0191   Let me introduce the CDC->transform callback: This callback will be called for 
0192 every point that is rendered when DCF_TRANSFORMATION is enabled. To acheive the 
0193 epic "shrinking effect",divide the X/Y coordinates by the Z coordanate times a 
0194 scale distance Let's see an example:
0195 Heres an example:
0196 
0197 
0198 #define SCRN_SCALE 512
0199 U0 Transform(CDC *dc,I64 *x,I64 *y,I64 *z)
0200 {
0201   I64 zz;
0202   Mat4x4MulXYZ(dc->r,x,y,z);
0203   zz=SCRN_SCALE/3+*z;
0204   if (zz<1) zz=1;
0205   *x=SCRN_SCALE/2* *x/zz;
0206   *y=SCRN_SCALE/2* (*y)/zz;
0207   *x+=dc->x;
0208   *y+=dc->y;
0209   *z+=dc->z;
0210 }
0211 CDC *dc=DCAlias;
0212 dc->transform=&Transform;
0213 dc->flags|=DCF_TRANSFORMATION;
0214 I64 dist=0;
0215 dc->z=-60;
0216 for(dist=0;dist!=100;dist++) { 
0217   Mat4x4TranslationEqu(dc->r,0,0,dist);
0218   dc->color=LTRED;
0219   GrRect3(dc,0,0,0,100,100);
0220   Refresh;
0221   DCFill;
0222 } 
0223 
0224                    Runtime Part 1:Graphics Raster Operations
0225 
0226   In TempleOS there are 16 colors,but you can mix them to make "new" colors. 
0227 This is called dithering. To use dithering to use raster operations. This allows 
0228 us to do things like make shading or invert the colors below what your drawing. 
0229 Let's get started
0230 
0231 
0232 CDC *dc=DCAlias;
0233 I64 cnt;
0234 for(cnt=0;cnt!=100;cnt++) { 
0235   dc->color=LTRED+YELLOW<<16+ROPF_DITHER; //Mix LTRED+YELLOW for Orange-ish 
0236 color
0237   GrRect3(dc,0,0,0,100,100);
0238   Refresh;
0239   DCFill;
0240 }
0241  
0242 
0243   If you though that was cool,check out probability dithering. This will make a 
0244 shading effect. You can change the percentage of what color gets used to make a 
0245 shading of your choice.The CDC->dither_probability_u16 is a 16bit percentage of 
0246 the the colors being used. If the dither_probability_u16 is 0,it will use 
0247 dc->color,otherwise it will use dc->color.u8[2] if the probability is U16_MAX;
0248 
0249 Let's rock(.u8[2] is 16 bits over):
0250 
0251 CDC *dc=DCAlias;
0252 I64 cnt;
0253 for(cnt=0;cnt!=100;cnt++) {
0254   dc->color=BLACK; 
0255   GrRect(dc,0,0,100,100);
0256   dc->color=LTRED+YELLOW<<16+ROPF_PROBABILITY_DITHER;
0257   dc->dither_probability_u16=U16_MAX*ToF64(cnt)/100.;
0258   GrFloodFill(dc,10,10);
0259   Refresh;
0260   DCFill;
0261 }
0262 DCDel(dc);
0263 
0264                          Runtime Part 2: Making Noises
0265 
0266   TempleOS makes sounds that will bring you back to the days of Atari games. The 
0267 simplest way to make a tone is Snd(23);(This higher the number the higher the 
0268 pitch). Call "Snd;" to cancel the sound.
0269 
0270   If you want to go the extra mile and make a bodacious explosioon sound,use  No
0271 ise(milliseconds,min_pitch,max_pitch);. Or if you want a jumping sound,use Sweep
0272 .
0273 
0274                           Runtime Part 3: Making Music
0275 
0276   TempleOS let's you make some epic jams. To do this,we use the Music
0277 
0278 A simple song looks like this:
0279 
0280  Play("wChDqEeFwGwAwB");
0281 
0282 
0283   There are special charactors that change the duration/properties of the 
0284 notes,so without further ado,here is a list
0285 -] #
0286   
0287   Make a note sharp(comes after the note)
0288 
0289 -] w
0290   
0291   When before a note,it makes it a whole note
0292 
0293 -] h
0294   
0295   Makes a half note
0296 
0297 -] q
0298   
0299   Makes a 1/4 note
0300 
0301 -] e
0302   
0303   Makes a tiny eigth note
0304 
0305 
0306   You can change the tempo of the music via the global vairable music.tempo(Be 
0307 sure to reset the music's settings via MusicSettingsRst)
0308 
0309 Try this:
0310 
0311 
0312 music.tempo=8;
0313 Play(
0314     "hEhEwEhChEwGqG"
0315     "wCqGqEqAqBqA#qAqGhEhGwAhFhGwEhChDqB"
0316    "wCqGqEqAqBqA#qAqGhEhGwAhFhGwEhChDqB"
0317      "hGhF#hFhD#wEqG#qAhCqAhChD"
0318     "hGhF#hFhD#wE.wC.wC.wC"
0319     "hGhF#hFhD#wEqG#qAhCqAhChDwD#wDwC"
0320     "hGhF#hFhD#wEqG#qAhCqAhChD"
0321     "hGhF#hFhD#wE.wC.wC.wC"
0322     "hGhF#hFhD#wEqG#qAhCqAhChDwD#wDwC"
0323 );
0324 MusicSettingsRst;
0325 
0326                     Runtime Part 4: Meta-data and Reflection
0327 
0328   HolyC is a mainly just in time language. This means when the code gets 
0329 compiled,the information about the code is still in memory. This is great for 
0330 having the code reflect on itself and saves a lot of time doing meanial things 
0331 like serializing a class. The primary way to do this is via MetaData. This means 
0332 data about the self.
0333 
0334   To get the metadata of a class out of the compiler,we must use the CTask's 
0335 hash table and do these steps
0336  
0337 -] Step 1
0338   
0339   Lookup the class by it's name CHashClass 
0340   *findc=HashFind(cls,Fs->hash_table,HTT_CLASS);
0341 
0342 -] Step 2
0343   
0344   Lookup the class by it's name CMemberLst 
0345   *member=MemberFind("member_name",findc);
0346 
0347 -] Step 3
0348   
0349   Lookup the meta data I64 meta_data=MemberMeta("META_DATA",member);
0350 
0351 
0352 
0353 Perhaps an example will help:
0354 
0355 class CMeta {
0356   I64 a fmt "A:%d\n";
0357   I64 b fmt "B:%d\n";
0358   F64 c fmt "C:%n\n";
0359 };
0360 CMeta abc={1,2,3};
0361 U0 Main(U8 *ptr,U8 *cls=lastclass) {
0362   CHashClass *findc=HashFind(cls,Fs->hash_table,HTT_CLASS);
0363   CMemberLst *ml;
0364   U64 sf;
0365   if(!findc) return;
0366   ml=MemberFind("a",findc);
0367   sf=(ptr+ml->offset)[0](U64);
0368   if(MemberMetaFind("fmt",ml)) {
0369     Print(MemberMetaData("fmt",ml),sf);
0370   } 
0371 }
0372 Main(&abc); //Here we use lastclass to get the class of abc
0373 
0374 
0375   If you want to make a form using meta data,you can use PopUpForm
0376 
0377 
0378 class CInput {
0379   //Be sure to use -P with strings
0380   U8 name[STR_LEN] format "\n";
0381   I64 age format "\n";
0382   Bool is_tall format "\n";
0383 };
0384 CInput inp;
0385 PopUpForm(&inp);
0386 "%s is %d years old\n",inp.name,inp.age;
0387 if(inp.is_tall)
0388   "Tall!\n";
0389 
0390 
0391                            Runtime Part 5: Filesystem
0392 
0393   If you are used to using TempleOS,use the Cd("Folder"); to move into a folder. 
0394 You can list the contents of the directory via Dir(".");("." is the current 
0395 folder). Sometimes you want your programs to be aware of the folders. Luckily 
0396 for you,you have come to the right place
0397 
0398   In TempleOS,each task has a current directory path in Fs->cur_dir(this doesnt 
0399 include the drive letter). If you want the full path,use DirCur.
0400 
0401   To make a file,use FileWrite("filename","text",4 /*text length*/);. When you 
0402 want to read it use FilleRead("filename",&len); FileRead will always put a NULL 
0403 terminator at the end of the file for your,so you can use it like a string.
0404 
0405   Like C,in TempleOS you can read files in a stream,But in TempleOS,all file 
0406 reads/writes act directly on the Hard-Disks sectors(Which are BLK_SIZE bytes 
0407 big). You FOpen("filename","w") for writing FOpen("filename","r") for reading. 
0408 To open a file for adding more data to it,use FOpen("filename","w+"). Lets see 
0409 an example
0410 
0411 
0412 //
0413 // Files opened with FOpen MUST WRITE BLK_SIZE bytes at once
0414 // A BLK is the size of a hard-disk sector
0415 //
0416 CFile *file=FOpen("Database.BIN","w");
0417 class CFileEnt {
0418   U8 name[STR_LEN];
0419   U8 password[STR_LEN];
0420 };
0421 #assert sizeof(CFileEnt)<=BLK_SIZE
0422 CFileEnt clayton={"Clayton","123"};
0423 CFileEnt root={"Root","toor"};
0424 U8 buffer[BLK_SIZE];
0425 MemCpy(buffer,&root,sizeof(CFileEnt));
0426 FBlkWrite(file,buffer,0,1); //Write 1 blk at the first block(blk 0)
0427 MemCpy(buffer,&clayton,sizeof(CFileEnt));
0428 FBlkWrite(file,buffer,1,1); //Write 1 blk at the second block(blk 1)
0429 FClose(file);
0430 //
0431 // Now we read
0432 //
0433 file=FOpen("Database.BIN","r");
0434 CFileEnt user;
0435 while(FBlkRead(file,buffer,,1)) {
0436   MemCpy(&user,buffer,sizeof(CFileEnt));
0437   "Got  user \"%s\" with password \"%s\"\n",user.name,user.password;
0438 }
0439 FClose(file);
0440 
0441 
0442   Making and reading files is fun,but first you need to figure out where a file 
0443 is. To do this use, . This will return a CDirEntry of the results(which may be 
0444 multiple files). Assuming you are familiar with wildcards from Linux,DOS and 
0445 CP/M. Look at this example
0446 
0447 
0448 FileWrite("abc.TXT","abc",3);
0449 FileWrite("def.TXT","def",3);
0450 FileWrite("ghi.TXT","ghi",3);
0451 CDirEntry *cur,*root=FilesFind("*.TXT",FUF_JUST_FILES);
0452 for(cur=root;cur!=NULL;cur=cur->next) {
0453   "I Found %s\n",cur->full_name;
0454 }
0455 DirEntryDel(root);
0456 
0457 
0458   A CDirEntry has much information about the directory structure. The most 
0459 important is full_name which tells you the full name of the file as you may 
0460 expect(name is the filename without the path). When you are done with a CDirEntr
0461 y be sure to free the root data with .
0462 
0463   To check if a file exists,you can use FileFind("file.HC") to check if a file 
0464 exists.
0465 
0466   Time to get to the nitty gritty. Has some epic flags you can use.Im not going 
0467 to waste time with exposiiton,rather I will give you a table of flags
0468 
0469 
0470 -] FUF_RECURSE
0471   
0472   This will search in the child folders for the pattern too
0473 
0474 -] FUF_JUST_DIRS
0475   
0476   Chooses only directories(folders)
0477 
0478 -] FUF_JUST_FILES
0479   
0480   Chooses only files
0481 
0482 -] FUF_JUST_TXT
0483   
0484   Chooses only text files
0485 
0486 -] FUF_JUST_DD
0487   
0488   Chooses only DolDoc files
0489 
0490 -] FUF_JUST_SRC
0491   
0492   Chooses only source files
0493 
0494 -] FUF_Z_OR_NOT_Z
0495   
0496   This will ignore Ziped named of files and just check as normal
0497 
0498 -] FUF_FLATTEN_TREE
0499   
0500   This will flatten a FUF_RECURSE tree for you conveince
0501 
0502 
0503   If you want to delete files,use DelTree("folder/files");,or if you just want 
0504 to remove a fule use Del("file");
0505 
0506   There are 2 ways to make a folder,use Cd("a/b/c/d/e",TRUE); to make a path,or 
0507 make a folder one at a time via DirMk("folder_name");. Copy your stuff via CopyT
0508 ree("old","new") or just a file via  Copy("old","new").
0509 
0510   And by the way you can open a file chooser via PopUpPickFile("T:/"); 
0511 
0512                     Runtime Part 6: Data structures(1 CQue)
0513 
0514   TempleOS comes loaded with useful data structures but it may be confusing at 
0515 first. The most important one is a CQue. This means a Circular Queue. It's likle 
0516 a loop,ill draw a picture for you.
0517 
0518 
0519 
0520 <1>
0521 0522 0523 0524 0525 0526 0527 0528 0529 0530 As you can see(poorly drawn) is that each item has 2 pointers( the CQue->last 0531 and the CQue->next).The ->last pointer is the previous item in the chain,not the 0532 "last" one. 0533 0534 To make a new CQue,use QueInit on the item make both pointers point to the 0535 item,which means an empty CQue. You can insert items into the CQue via QueIns(to 0536 _insert,at). Perhaps an example will help you. 0537 0538 In our below example,I start at head and also end at head as the queue is 0539 ciruclar 0540 0541 0542 CQue *head=MAlloc(sizeof CQue),*one=MAlloc(sizeof CQue),*two=MAlloc(sizeof 0543 CQue),*cur; 0544 QueInit(head); 0545 QueIns(one,head); 0546 QueIns(two,one); 0547 for(cur=head->next;cur!=head;cur=cur->next) 0548 "Current element(excuding HEAD):%P\n",cur; 0549 QueDel(head); //Remove all items in the CQue 0550 Free(head); //QueDel doesnt Free the head 0551 0552 0553 To get the count of items in your queue use QueCnt(head). And to remove an 0554 item form the queue(not Free it),use QueRem which will detach the item from a 0555 queue 0556 0557 0558 CQue *head=MAlloc(sizeof CQue),*one=MAlloc(sizeof CQue),*two=MAlloc(sizeof 0559 CQue),*cur; 0560 QueInit(head); 0561 QueIns(one,head); 0562 QueIns(two,one); 0563 QueRem(one); //Detach one from the CQue 0564 Free(one); //Free it's data 0565 for(cur=head->next;cur!=head;cur=cur->next) 0566 "Current element(excuding HEAD):%P\n",cur; 0567 QueDel(head); //Remove all items in the CQue 0568 Free(head); //QueDel doesnt Free the head 0569 0570 0571 You can insert get the item count of the QueCnt(head) 0572 0573 Here is a reference section: 0574 -] QueInit(head) 0575 0576 Intialize the head of a queue 0577 0578 -] QueIns(to_ins,elem) 0579 0580 Insert an item after the elem 0581 0582 -] QueInsRev(to_ins,elem) 0583 0584 Insert an item before the elem 0585 0586 -] QueRem(elem) 0587 0588 Detach an item from the queue(doesnt free it) 0589 0590 -] QueDel(head) 0591 0592 Frees all items in the queue 0593 0594 -] QueCnt(head) 0595 0596 How many items in the queue(excluding the head) 0597 0598 0599 Runtime Part 7: Data structures 2(HashTable) 0600 0601 Hash tables are like dictionary data structures and each task has one in Fs->h 0602 ash_table. Each CHash has a type and a str. 0603 0604 When you look up a hash from a hash-table you will need the type. For 0605 example,if we want to grab a define(HTT_DEFINE_STR) from our current task,we do: 0606 0607 #define FOO 123 0608 CHashDefineStr *def=HashFind("FOO",Fs->hash_table,HTT_DEFINE_STR); 0609 if(def) 0610 "%s\n",def->data; 0611 0612 We looked up foo with type HTT_DEFINE_STR. Sometimes we want to add things to 0613 a CHashTable. To do this we need to use HashAdd. 0614 0615 CHashDefineStr *d=CAlloc(sizeof(CHashDefineStr)); 0616 d->str=StrNew("Hello"); //Must allocate string on heap 0617 d->type=HTT_DEFINE_STR; 0618 d->data=StrNew("10"); 0619 HashAdd(d,Fs->hash_table); 0620 //We added the macro Hello into the hash table 0621 "%d\n",Hello; 0622 0623 0624 Sometimes you want to make your own hashtables. You can do this via HashTableN 0625 ew(size). size MUST BE A POWER OF 2. 0626 0627 Any generic data in the hashtable should use type HTT_FRAME_PTR as HashTableDe 0628 l doesnt try to make assuptions on how to free the data 0629 0630 Perhaps an example will help: 0631 0632 CHashTable *ht=HashTableNew(0x100); 0633 CHashGeneric *ent=CAlloc(sizeof CHashGeneric); 0634 ent->user_data0=1; 0635 ent->user_data1=2; 0636 ent->user_data2=3; 0637 ent->type=HTT_FRAME_PTR; 0638 ent->str=StrNew("look"); 0639 HashAdd(ent,ht); 0640 CHashGeneric *g=HashFind("look",ht,HTT_FRAME_PTR); 0641 "%d,%d,%d\n",g->user_data0,g->user_data1,g->user_data2; 0642 HashTableDel(ht); 0643 0644 0645 Here is a reference of hash table functions 0646 0647 -] HashAdd(item,table) 0648 0649 Adds an item to the hash table 0650 0651 -] HashRemDel(item,table) 0652 0653 Delete an item from the hash table 0654 0655 -] HashFind(str,table,type) 0656 0657 Find an item in the table 0658 0659 -] HashSingleTableFind(str,table) 0660 0661 Find an item in the table,but dont check parent task's thing 0662 0663 -] HashTableNew(sz) 0664 0665 Make new hashtable,sz must be a power of 2 0666 0667 0668 Runtime Part 8: Data structures 3(Fifo) 0669 0670 Fifo's mean "First In First Out" and do things like store key presses. The 0671 first key you press is the the first one you get out. They also have a maximum 0672 size,which means that if you get too many keys,the old ones will be discarded 0673 0674 It looks like this: 0675 <2>
0676 0677 0678 0679 0680 0681 0682 0683 0684 0685 0686 0687 0688 0689 0690 0691 First create a FIFO with FifoI64New,Size must be a power of 2 0692 0693 CFifoI64 *fifoI64=FifoI64New(4); 0694 FifoI64Ins(fifoI64,1); 0695 FifoI64Ins(fifoI64,2); 0696 FifoI64Ins(fifoI64,3); 0697 0698 You can remove an item with FifoI64Rem. This takes a pointer and returns TRUE 0699 0700 CFifoI64 *fifoI64=FifoI64New(4); 0701 FifoI64Ins(fifoI64,1); 0702 FifoI64Ins(fifoI64,2); 0703 FifoI64Ins(fifoI64,3); 0704 I64 val; 0705 while(FifoI64Rem(fifoI64,&val)) 0706 "Got a %d\n",val; 0707 0708 0709 Here is a reference section 0710 0711 -] FifoI64New(sz) 0712 0713 Make a new fifo,sz must be a power of 2 0714 0715 -] FifoI64Flush(f) 0716 0717 Remove all the items from the fifo 0718 0719 -] FifoI64Cnt(f) 0720 0721 Get a count of all the items in the fifo 0722 0723 -] FifoI64Peek(f,&val) 0724 0725 Look at the next item in the fifo without removing it 0726 0727 -] FifoI64Del(f) 0728 0729 Free the fifo 0730 0731 -] FifoI64Rem(f,&val) 0732 0733 Remove an item from the fifo 0734 0735 -] FifoI64Ins(f,val) 0736 0737 Insert an item into the fifo 0738 0739 -] FifoU8Flush(f) 0740 0741 Remove all the items from the fifo 0742 0743 -] FifoU8Cnt(f) 0744 0745 Get a count of all the items in the fifo 0746 0747 -] FifoU8Peek(f,&val) 0748 0749 Look at the next item in the fifo without removing it 0750 0751 -] FifoU8Del(f) 0752 0753 Free the fifo 0754 0755 -] FifoU8Rem(f,&val) 0756 0757 Remove an item from the fifo 0758 0759 -] FifoU8Ins(f,val) 0760 0761 Insert an item into the fifo 0762 0763 -] FifoU8New(sz) 0764 0765 Make a new fifo,sz must be a power of 2 0766 0767 0768 Runtime Part 9: User Input 0769 0770 TempleOS lets you do lit stuff like click on things and use the keyboard. 0771 These events are passed through messages. We use GetMsg to get the 0772 messages,along with a message mask. 0773 0774 I64 x,y; 0775 U0 DrawIt(CTask *t,CDC *dc) { 0776 dc->color=RED; 0777 GrRect(dc,x,y,100,100); 0778 } 0779 U0 Run() { 0780 Fs->draw_it=&DrawIt; 0781 I64 m,x2,y2; 0782 while(TRUE) { 0783 m=GetMsg(&x2,&y2,1<<MSG_MS_MOVE+1<<MSG_MS_R_DOWN); 0784 if(m==MSG_MS_R_DOWN) 0785 break; 0786 x=x2; 0787 y=y2; 0788 Refresh; 0789 } 0790 } 0791 Run; 0792 0793 0794 Keyboard messages can be gotten via ScanKey(&ch,&sc). The first argument is 0795 the ASCII charactor,and the second one is the scancode. The scancode is the raw 0796 key being pressed and has flags in it. I'll give an example usage of the 0797 function first before I dive into details. 0798 0799 I64 x,y; 0800 U0 DrawIt(CTask*,CDC*dc) { 0801 dc->color=GREEN; 0802 GrRect(dc,x,y,100,100); 0803 } 0804 U0 Run() { 0805 Fs->draw_it=&DrawIt; 0806 I64 msg,sc,ch; 0807 for(;TRUE;) { 0808 if(ScanKey(&ch,&sc)) { 0809 if(sc&0xff==SC_ESC) break; 0810 if(sc&0xff==SC_CURSOR_UP) { 0811 y-=3; 0812 } else if(sc&0xff==SC_CURSOR_DOWN) { 0813 y+=3; 0814 } else if(sc&0xff==SC_CURSOR_LEFT) { 0815 x-=3; 0816 } else if(sc&0xff==SC_CURSOR_RIGHT) { 0817 x+=3; 0818 } 0819 } else { 0820 Refresh; 0821 } 0822 } 0823 } 0824 Run; 0825 0826 As you can see,I check the first 8 bits(0xff) of the scan code to test what 0827 key it is. There also flags on the scancode that tell you things like if the 0828 shift key is down etc. 0829 0830 The first byte of scancode is the key code,but the other bytes are flags which 0831 can be tested via the "&" operator 0832 0833 0834 I64 x,y; 0835 I64 color=GREEN; 0836 U0 DrawIt(CTask*,CDC*dc) { 0837 dc->color=color; 0838 GrRect(dc,x,y,100,100); 0839 dc->color=RED; 0840 } 0841 U0 Run() { 0842 Fs->draw_it=&DrawIt; 0843 I64 msg,sc,ch; 0844 for(;TRUE;) { 0845 if(ScanMsg(&ch,&sc,1<<MSG_KEY_UP|1<<MSG_KEY_DOWN)) { 0846 if(sc.u8[0]==SC_ESC) break; 0847 if(sc.u8[0]==SC_CURSOR_UP) { 0848 y-=3; 0849 } else if(sc.u8[0]==SC_CURSOR_DOWN) { 0850 y+=3; 0851 } else if(sc.u8[0]==SC_CURSOR_LEFT) { 0852 x-=3; 0853 } else if(sc.u8[0]==SC_CURSOR_RIGHT) { 0854 x+=3; 0855 } 0856 if(sc&SCF_CTRL) 0857 color=RED; 0858 else if(sc&SCF_SHIFT) 0859 color=YELLOW; 0860 else 0861 color=GREEN; 0862 } else { 0863 Refresh; 0864 } 0865 } 0866 } 0867 Run; 0868 0869 0870 Here's a list of scancode flags: 0871 0872 -] SCF_KEY_UP 0873 0874 The key was released 0875 0876 -] SCF_CTRL 0877 0878 The Ctrl key is down 0879 0880 -] SCF_SHIFT 0881 0882 The shift key is down 0883 0884 -] SCF_ALT 0885 0886 The alt key is down 0887 0888 -] SCF_CAPS 0889 0890 The Caps lock key is down 0891 0892 -] SCF_NUM 0893 0894 The NumLock key is kdown 0895 0896 -] SCF_SCROLL 0897 0898 Scroll Lock key is down 0899 0900 -] SCF_MS_L_DOWN 0901 0902 The left mouse is down 0903 0904 -] SCF_MS_R_DOWN 0905 0906 The right mouse is down 0907 0908 -] SCF_NO_SHIFT 0909 0910 There is no shift 0911 0912 0913 Here's a list of scancode keys: 0914 0915 -] SC_ESC 0916 0917 The escape key 0918 0919 -] SC_BACKSPACE 0920 0921 The backspace key 0922 0923 -] SC_TAB 0924 0925 The tab key 0926 0927 -] SC_ENTER 0928 0929 The enter key 0930 0931 -] SC_CTRL 0932 0933 The ctrl key 0934 0935 -] SC_ALT 0936 0937 The alt key 0938 0939 -] SC_CAPS 0940 0941 The caps lock key 0942 0943 -] SC_NUM 0944 0945 The num lock key 0946 0947 -] SC_SCROLL 0948 0949 The scroll lock key 0950 0951 -] SC_CURSOR_UP 0952 0953 The up key 0954 0955 -] SC_CURSOR_DOWN 0956 0957 The down key 0958 0959 -] SC_CURSOR_LEFT 0960 0961 The left key 0962 0963 -] SC_CURSOR_RIGHT 0964 0965 The right key 0966 0967 -] SC_PAGE_DOWN 0968 0969 The page down key 0970 0971 -] SC_PAGE_UP 0972 0973 The page up key 0974 0975 -] SC_HOME 0976 0977 The home key 0978 0979 -] SC_END 0980 0981 The end key 0982 0983 -] SC_INS 0984 0985 The insert key 0986 0987 -] SC_DELETE 0988 0989 The delete key 0990 0991 -] SC_F1-SC_F12 0992 0993 The Fxx keys 0994 0995 -] SC_PAUSE 0996 0997 The pause key 0998 0999 -] SC_GUI 1000 1001 The logo key 1002 1003 -] SC_PRTSCRN1 1004 1005 The print screen key 1006 1007 -] SC_PRTSCRN2 1008 1009 The print screen key 1010 1011 1012 I mentioned eariler about GetMsg,and I used ScanMsg. GetMsg waits for an 1013 event,but ScanMsg doesn't. There are also message codes 1014 1015 -] MSG_KEY_DOWN(ch,scancode) 1016 1017 A Key is put down 1018 1019 -] MSG_KEY_UP(ch,scancode) 1020 1021 A Key is release 1022 1023 -] MSG_MS_MOVE(x,y) 1024 1025 The mouse is moved 1026 1027 -] MSG_MS_L_DOWN(x,y) 1028 1029 The left button is down 1030 1031 -] MSG_MS_L_UP(x,y) 1032 1033 The left button is down 1034 1035 -] MSG_MS_R_DOWN(x,y) 1036 1037 The right button is down 1038 1039 -] MSG_MS_R_UP(x,y) 1040 1041 The right button is down 1042 1043 1044 Runtime Part 9: Multithreading 1045 1046 TempleOS is non-premptive. This means each Task has to manually tell the 1047 computer when to context swap. The way to do this and prevent freezing is to Yie 1048 ld 1049 1050 In TempleOS,spawning task's is easy,use the Spawn function 1051 1052 1053 U0 Foo(U8 *data) { 1054 Beep; 1055 } 1056 Spawn(&Foo,"Some_data","TaskName"); 1057 1058 1059 You can make a user terminal via User. You can talk to that task via XTalk 1060 1061 1062 CTask *u=User; 1063 XTalk(u,"\"Exiting in 5 seconds\\n\";\n"); //Be sure to put a semi-colon at the 1064 end as we are "the-user". 1065 Sleep(5000); 1066 XTalk(u,"Exit;\n"); 1067 1068 1069 Sometimes you want to wait for a task to die,to do this use DeathWait 1070 1071 1072 CTask *t=User; 1073 DeathWait(&t); //Note address of t 1074 Beep; //Will beep when you exit the User task 1075 1076 1077 There is also a BirthWait 1078 1079 1080 CTask *t=User; 1081 BirthWait(&t); //Note address of t 1082 Beep; //Will beep when you exit the User task 1083 1084 1085 To avoid race conditions we use locks. In TempleOS this is acheived through 1086 locked bit instructions with spinlocks. How it works is LBts will set the 1087 bit,and return the old value of the bit. We keep on setting the bit. If the old 1088 value is not set,it means we have access to the lock,otherwise we keep on 1089 looping. Be sure to reset the bit when you are done with LBtr. 1090 1091 1092 I64 beep_lock=0; 1093 U0 OneThread(I64 snd) { 1094 //This will spin until bit 0 is reset(look at the end of the function) 1095 while(LBts(&beep_lock,0)) //LBts has a side effect of setting the bit after it 1096 is checked 1097 Yield; //We are going to be beeping for awhile so Yield out control to other 1098 tasks 1099 Beep(snd); 1100 //We reset bit 0 of beep_lock to signify we are done with it. 1101 LBtr(&beep_lock,0); 1102 } 1103 I64 i; 1104 for(i;i!=10;i++) { 1105 Spawn(&OneThread,i*7+10); 1106 "Spawned a thread!!\n"; 1107 } 1108 1109 Runtime Part 10: Jobs 1110 1111 In TempleOS,each core has a seth_task. This task does lit stuff like run Jobs 1112 which can be created via TaskExe and you get the results via JobResGet 1113 1114 1115 CJob *job=TaskExe(Gs->seth_task,Fs,"1+1;;;",0); 1116 res=JobResGet(job); 1117 Kill(jobber); 1118 "I got %d\n",res; 1119 1120 With cpu_structs,you can spawn jobs on other cores 1121 1122 1123 CTask *parent_task=Fs; 1124 I64 core=0; 1125 //mp_cnt is the number of cpus 1126 CJob *jobs[mp_cnt]; 1127 for(core=0;core!=mp_cnt;core++) { 1128 jobs[core]=TaskExe(cpu_structs[core].seth_task,Fs, 1129 "Sleep(RandI64%1000);" 1130 "Gs->num;;", //Gs is the current CCPU for the core,->num is the cpu number 1131 0); 1132 } 1133 for(core=0;core!=mp_cnt;core++) { 1134 "Core %d return %d\n",core,JobResGet(jobs[core]); 1135 } 1136 1137 1138 If you want to have the parent task wait while a job runs,you can use the JOBf 1139 _WAKE_MASTER flag. 1140 1141 1142 CTask *parent_task=Fs; 1143 //Things ending in a lowecase f as bits(and need to be shifted to be flags) 1144 TaskExe(Gs->seth_task,parent_task,"Play(\"EGBDF\");",(1<<JOBf_WAKE_MASTER)); 1145 1146 Runtime Part 11: DolDoc 1147 1148 Most of the text you see on screen is from the DolDoc layout engine. It uses a 1149 series of dollar signs to set things like the text color and make elements. The 1150 are stored as a circular queue of CDocEntry's. The easyiest way to make a DolDoc 1151 element is to use DocPrint,use DocPut to get the current task's document. 1152 1153 1154 //BT is a button 1155 CDocEntry *de=DocPrint(DocPut,"\n\n$BT,\"Hello\"$\n\n"); 1156 1157 1158 As you can see,the DolDoc entries have a type and argument. They are 1159 surrounded by $'s. They can also have flags too. This let's you do things like 1160 center the text. Lets see an example: 1161 1162 1163 //TX is a text,+CX is the center flag 1164 CDocEntry *de=DocPrint(DocPut,"\n\n$TX+CX,\"Hello\"$\n\n"); 1165 1166 1167 DolDoc entries can also take an argument,Links use this to figure out where to 1168 go when you click them. Arguments for DolDoc entries come after the comma,some 1169 of the arguments are named and have the format "name=value" 1170 1171 1172 CDocEntry 1173 *de=DocPrint(DocPut,"\n\n$LK,\"Text\",A=\"FL:/PersonalMenu.DD\"$\n\n"); 1174 1175 1176 You can interact directly with the generated CDocEntrys. You can put things 1177 like callbacks into them. In our below example I set the left_cb function 1178 pointer to Beep2 and I tell the entry that it has a callback with DOCEF_LEFT_CB. 1179 1180 1181 I64 Beep2(CDoc *,CDocEntry *) { 1182 Beep; 1183 } 1184 CDocEntry *de=DocPrint(DocPut,"\n\n$BT+CX,\"Hello\"$\n\n"); 1185 de->de_flags|=DOCEF_LEFT_CB; 1186 de->left_cb=&Beep2; 1187 1188 1189 You can use the DocMenu function to get a value from your document. I use the 1190 LE for a left-click-expression. 1191 1192 1193 U0 CreateDialog() { 1194 CDocEntry *nums[3]; 1195 I64 i; 1196 DocClear(DocPut); 1197 "$TX+CX,\"Pick a number:\"$\n"; 1198 for(i=0;i!=3;i++) { 1199 nums[i]=DocPrint(DocPut,"\n\n$BT+CX,\"%d\",LE=%d$\n\n",i,i); 1200 } 1201 DocBottom(DocPut); 1202 switch(DocMenu(DocPut)) { 1203 start: 1204 DocClear(DocPut); 1205 case 0: 1206 "You picked nothing lol.\n"; 1207 break; 1208 case 1: 1209 "One is the one\n"; 1210 break; 1211 case 2: 1212 "Two is too good\n"; 1213 break; 1214 end: 1215 } 1216 } 1217 CreateDialog; 1218 1219 1220 You can use PopUpForm to use a class's meta data for making a menu. 1221 1222 1223 U0 CreateDialog() { 1224 class CInput { 1225 //Be sure to use -P with strings 1226 U8 name[STR_LEN] format "\n"; 1227 I64 age format "\n"; 1228 Bool is_tall format "\n"; //CB is a Check box 1229 }; 1230 CInput inp; 1231 PopUpForm(&inp); 1232 "%s is %d years old\n",inp.name,inp.age; 1233 if(inp.is_tall) 1234 "Tall!\n"; 1235 1236 1237 Yeah time for some reference section ehh: 1238 1239 -] TX 1240 1241 Text 1242 1243 -] CR 1244 1245 Newline 1246 1247 -] CU 1248 1249 Cursor pos,normally a ASCII #5 1250 1251 -] TB 1252 1253 Tab 1254 1255 -] CL 1256 1257 Clears all elements without the "+H" flag 1258 1259 -] PB 1260 1261 Page break 1262 1263 -] PL 1264 1265 Page length 1266 1267 -] LM 1268 1269 Left margin 1270 1271 -] RM 1272 1273 Right margin 1274 1275 -] HD 1276 1277 Header margin 1278 1279 -] FO 1280 1281 Footer margin 1282 1283 -] ID 1284 1285 Indent,use wit tree elements,and use with a negative number to un-indent 1286 1287 -] FD 1288 1289 Forground default color 1290 1291 -] BD 1292 1293 Background default color 1294 1295 -] PT 1296 1297 Command Line Prompt 1298 1299 -] WW 1300 1301 Use 1 to enable word wrap,use 0 to disable 1302 1303 -] UL 1304 1305 Use 1/0 to enable/disable underline 1306 1307 -] IV 1308 1309 Disable/enable Inverting of colors 1310 1311 -] BK 1312 1313 Burger Kind,just kidding,it's actually for blinking 1314 1315 -] SX 1316 1317 Shift the text by a amount of pixels 1318 1319 -] SY 1320 1321 Shift the text up/down by an amount of pixels 1322 1323 -] CB 1324 1325 Checkbox 1326 1327 -] LS 1328 1329 Major Lit Alert 1330 Use with the "D" argument to make a list(from a DefineListLoad),do this 1331 $LS,"potato",D="ST_BIBLE_BOOKS"$ 1332 Clicking on this will make a menu to pick an item from the list 1333 1334 -] MA 1335 1336 A macro,clicking on this will insert LM into the command line prompt 1337 1338 -] TR 1339 1340 A Tree wigdet,use this with ID to nest the tree's 1341 1342 -] HL 1343 1344 Turn HolyC syntax highting on/off 1345 1346 1347 Here is a reference section for the flags,they can be added/removed with 1348 +/-(For example you can do "$TX+CX+H,\"I have CX and H flags.\"$\n";) 1349 1350 -] H 1351 1352 Hold,this will prevent CL from deleting this element 1353 1354 -] L 1355 1356 This will make the element act as a link 1357 1358 -] TR 1359 1360 This will make the element act as a tree 1361 1362 -] LS 1363 1364 This will make the element act as a list 1365 1366 -] PU 1367 1368 This will make a macro run in a popup window 1369 1370 -] C 1371 1372 This will collapse a tree,use -C to uncollapse the tree 1373 1374 -] X 1375 1376 This will save and Exit after the macro is done 1377 1378 -] UD 1379 1380 Update data on typing 1381 1382 1383 Here is a reference section for the argument codes,use them like "$TX,T=\"123\"$ 1384 " 1385 1386 -] T 1387 1388 Tag text,this is the text that gets displayed. 1389 1390 -] LEN 1391 1392 Sets the length of the DA element. 1393 1394 -] A 1395 1396 Sets the link location 1397 1398 -] LE 1399 1400 Left expression,runs an expression on left click 1401 1402 -] RE 1403 1404 Right expression,runs an expression on right click 1405 1406 -] LM 1407 1408 Left macro,runs text on left click 1409 1410 -] RM 1411 1412 Right macro,runs text on right click 1413 1414 -] RT 1415 1416 Raw type of DA 1417 1418 -] U 1419 1420 User data 1421 1422 -] SCX 1423 1424 Scroll x columns Makes a amazing scrolling effect 1425 1426 -] SX 1427 1428 Scroll x pixels 1429 1430 -] SY 1431 1432 Scroll y pixels 1433 1434 1435 Making links is easy,to do this we use "$LK,\"text\",A=\"BF:Acts,2:3\"$"; Here 1436 is a reference for the link codes: 1437 1438 -] FI 1439 1440 File index,FI="file" or FI="file,line" 1441 1442 -] FF 1443 1444 File Find,FF="file,text" 1445 1446 -] BF 1447 1448 Bible Find,BF="book,text". "text" can be a chapter/verse 1449 1450 -] HI 1451 1452 Help Index,HI="Help Index". Make help indexes via #help_index 1453 1454 -] A 1455 1456 Symbol address, takes a pointer A="0x11223344" 1457 1458 1459 Now a function reference: 1460 1461 -] DocBottom 1462 1463 Move to the bottom of the document 1464 1465 -] DocCenter 1466 1467 Make ->cur_entry be in the viewport 1468 1469 -] DocClear 1470 1471 Clear all elements except those with the +H flag 1472 1473 -] DocCollapse(collapsed,doc) 1474 1475 Collapse or un-collapse all trees in the document 1476 1477 -] DocDel 1478 1479 Delete a documents memory 1480 1481 -] DocEntryDel(doc,elem) 1482 1483 Deletes a document entry 1484 1485 -] DocEntryCopy(doc,elem) 1486 1487 Copy an element 1488 1489 -] DocInsDoc(to,from) 1490 1491 Insert a document into an other document 1492 1493 -] DocLock 1494 1495 Lock a document 1496 1497 -] DocUnlock 1498 1499 Unlock a document 1500 1501 -] DocRst 1502 1503 Reset the document 1504 1505 -] DocTop 1506 1507 Go to the top of the document 1508 1509 -] DocLineRead(filename,line) 1510 1511 Read a line from a file 1512 1513 -] DocLineWrite(filename,line,text) 1514 1515 Write a line into a file 1516 1517 -] DocRead(filename) 1518 1519 Read a document from a file 1520 1521 -] DocLoad(into_doc,ptr,len) 1522 1523 Read a document from memory into a docuemnt 1524 1525 -] DocSave(doc,len_ptr) 1526 1527 Save a document into memory 1528 1529 -] DocWrite(doc) 1530 1531 Save a document to disk. Filename is detirmnined by DocNew("filename"); 1532 1533 -] DocMenu 1534 1535 Interact with a document until a value is found 1536 1537 -] DocForm 1538 1539 Use a class's meta-data to make a form for you to fill out 1540 1541 -] DocNew(filename) 1542 1543 Make a new document that will be saved to filename 1544 1545 -] DocGR(doc,filename.GR) 1546 1547 Insert a .GR file into a document 1548 1549 -] DocPrint 1550 1551 Print text into a document 1552 1553 -] DocPut 1554 1555 Get the current document for a task 1556 1557 -] DocType(doc,filename) 1558 1559 Type a file into a document