 Day 10 let us try and make extents work So extents are how CPM handles files, which are bigger than 16k So if we take a look at our directory, which is full of junk because I haven't rebuilt it since the last time I did a build You can see Here we go. Here's the CCP You've got the file name and so on for the directory entry and here in the next line we have the Allocation map this tells the system what disk blocks contain the data for this file and there's enough space in 8 of these for 16 k's worth of data One of these 16 k's is called an extent and there are a couple of bytes Here and here which I use to track what extent it's in now. We just have small files currently So let's put a big file in I'm going to use the BDoS source code Okay, so if I then force the image to be rebuilt Like so So here we see that we now have the OS 3 BDoS file and there are four directory entries for it these are the These are the Four that's interesting. These numbers are not what I was expecting So this is and we find the documentation This format to So here is a directory entry the first byte after the file name is The extent number now. This is a this is a small disk This means there are fewer than 256 blocks on the disk and therefore you can store each Block number in a single byte There are 16 bytes in the allocation map So for a small disk you can fit 16 blocks worth in I Was Expecting Oh, sorry, sorry I changed the block size to 1k so 16 blocks is 16k and therefore one extent right so you can see the extent number Goes up by one each time If I had be if I was using 2k blocks, then eight Blocks Would be 16k therefore all of this would be 32k Therefore to extent so we will be seeing zero zero. No, we'll be seeing zero one zero three zero five Well, actually it only goes up to four. This is the three rather four Yes, four directory entries So the highest extent value is three zero one two and three on a big disk when there are multiple extents in a single directory entry this byte stores the largest extent in the directory entry So we cannot actually do anything with that file because I haven't done any of the code to handle files bigger than one extent So let's fiddle with our make program We are going to We are going to just read all the blocks from the file until Carry set read sequential return carry set at end of files that should be a repeat Okay, we build the program This is our make comm see all of these are tiny files the The biggest one here is the CCP itself, which is a mere two blocks. Was he have it under 2k? Okay So let's fire up and let's try reading a small file Let's just change this to open Open the file not Open Okay, now we're gonna fire it up Okay, so that read all the sectors on the in the file. There's like one I think And now dumps a bit bigger than that's maybe two or three Let's just try the CCP. That's a bigger file. Let's try with the right command okay No time is taken to do anything because the virtual file system in this emulator is stupidly fast so now let's Try and read the big file That wasn't supposed to happen that was supposed to produce an error Right, I don't think this is working Com right And the CCD dot sis Right, it's printing a dot for every 128 byte record 3b dust as a hmm That's three forties plus nine Right, it has read one extent and stopped So let's figure out what's going on that should be in reed sequential Which is here Okay, that's because this code is junk So what we're doing at the beginning is we read the current record value into a We compare it to the record count in the FCB Yeah If they're equal Then we check to see whether the record count is 128, which means a full extent Except using the wrong Register so it always thinks it's reached the end of the file and I will add The record count value in the FCB is not the one in the Durant the record count value is faked if You're on a extent. That's not the last one in the Durant because if the Durant is handling like for Extents, then you know that extent zero one and two must be full and therefore will have a length of 128 So make Come Make OS 3d dust as an end of extent. Good. That is what we wanted So what do we do here? well We need to close the extent This will flush any changes the user may have made to disk advance the extent index and Open the new extent So that's going to become What is that going to become Well, let's do the close first So close file is the code that actually does Closing an extent so we want to put in Internal entry point that doesn't convert the FCB so here we close it we want to Increment the Extent pointer and we have to load that into a register There are a maximum of the extent counter is Zero to thirty one write that back If it's zero then it's rolled over Therefore we want to increment S2 S2 also contains the The File has not been modded the FCB has not been modified bit so first We're going to load it Then We are going to check to make sure that it's not going to roll over Now we need to take the bit off If it is 7f then we're at the end of the file because the file can't be any bigger so now we are going to Increment it and write it back so now Our FCB should be updated to point at The beginning of the next extent but There is one additional thing we want to do which is we need to Clear the current record pointer because we want to point at the beginning of the extent and currently We are pointing at the end of it Okay Now we want to open this so that's going to be a Call to internal open file which do all the work. I just want to check to make sure that I'm doing this right Yeah, this is the code that That does it if there's more than one extent in a directory entry Then this code make sure that we find the right one okay, so now We want to open it and If Carrie is set meaning that we can't open it we are at the end of the file, okay So what is this going to do? We are going to spin forever because it's not working. That's what we're going to do so let's Debug our way through as usual Okay, we've read the first extent we stop I'm using the jump to get the address I wish there's a easier way to do that But of course the debugger doesn't know where all of this code is loaded anyway so we are Loading the extent number into a which is a zero increment Mask the only way this can be zero is If is if we were on extent 31 and we've rolled around to zero so We should have just stored the Updated extent we now update the current record so our FCB is a 2 3 B4 So we see that This is the extent number. It's been updated to 1 This is the record count which is 128 because this extent is full This is the current record which is zero Okay, we now try to open the next one take take a look at the FCB again Yeah, that has loaded extent zero again So that has become a zero Okay Question is why so let's find out we are at Internal Open file this will be a find first bug so we home the drive reset the directory pointer Read a directory entry. Are we at the end of the the list? No, we're not Did the user want to see deleted files? Actually, I'm going to guess that all this code works So we're now working through here Okay, we're here. We'll actually want to compare current dear end with the FCB. I think that this Is is the extent comparison code? This is the bit that's gone wrong, and I bet the extent mask is wrong so That starts here Right load the extent mask extent mask is zero because We are using one extent per directory entry so that inverts it to ff save and The FCB extent number Into a that gives us one. That's the extent. We're looking for dash Pull the byte currently under Consideration Yeah, okay. A is now the that's not the byte current under consideration that is the Inverted extent mask, okay So we now and the same byte from the deer ent the deer ent which we're looking at is at 0610 So we're looking at the first one With an extent of zero so after adding that to zero. That's what we would expect We compare it with the one From the FCB they are not the same and this code is rubbish We don't want to do a Compare we want to do a subtract as we care about the result Okay, let's try this one more time Make os3b dot asm so We are here the result is Zero right. We're looking for the first one. So we continue Now we are looking for the file Okay, now we're looking for the second one. We see we've printed the dots. We loaded the program We opened the first extent of the file We read it now. We're on the second extent of the file a is ff which means it was not a match and The result not zero therefore we go around again right second time through Zero we have found the second extent So we continue and nothing happened. That didn't work. So I think something else has gone wrong so let's Go through that again Okay, that has branch that's the first time second time that has not Brant wait a minute Okay, and oh I'm here Right. We're falling through into the old code For doing normal character comparison, which is wrong We actually want at this point. We know that the byte is correct. So we just want to go to same characters to indicate that We have found a successful byte match and so we want to Continue on with additional bytes I First time second time So we're now looking at extent zero one Do the comparison? mask branch found the right stuff So we're here. We go on to the next character the next bite of the to compare Reach the end of the string No, we haven't so we go and do the next one The next bite is s1, which we just ignore So we read it. Is it a question mark? No, are we on s1? Yes, go around again Now we are comparing the s2 bite. This is the last one It's the question mark. No, are we on the s1 bite? No Are we on the ex bite needs special treatment? No, so we now do a normal bite comparison cc deer ant Nor top bit They are the same good Go on to the next bite. We run out of bite. So we're here. We have found a successful file So continue more dots Third time lucky more dots fourth time lucky More dots There were Four extents we should have reached the end. We should we should have Failed this comparison. I mean we printed all the dots. Ah It just so happens that our file perfectly fills all four extents So that's fine that worked We have successfully read the entire file so I can if I can type it This is then listing all the 8080 BDOS source code Which has 64k so this may take a little while But I can do a control s and pause it so we are at Open we're most of the way through but this is good because the data seems to be correct and we are Well into the second or third extent there we go and we hit the end and You know, it's the end because it says end good Okay, we are successfully reading multi-extent files Now we need to do the same thing for rights. So Let's go to our make We are going to Create another FCB Drive for one two three four File name Okay, so we're going to open the input file now. We want to try and open the output file If the carrier set that's because the output file doesn't exist Okay, so we have now managed to create or open an output file So we do our read We set the buffer we do our read We stop if we read if carriers set we reach the end of the file We are now going to Do a right Bail if the carriers set that would mean a right error or a disc full Okay So we now have a Very primitive file copier In fact, it's going to read and write a sector at a time with no buffering So it's not anything that anyone would want to use in real life So let's see if it works So I'm going to make dump dot com Right that should have created a output dot that file But but but you forgot to close it. Well, then now I think about it that didn't actually Create an output dot that file. Did it? Too late now. Anyway, let's see what happens. Oh interesting Why are we on user 80? We're on user 80 because I forgot to put the the X FCB stuff So that should be four more bites and a user bite Did it do anything? There we go, and it right is put it in the wrong user. So we're now on user 128 There is no such thing as user 128, but if I go to user zero you see the output dot that isn't there if I Look at the file system. I don't see a Output dot that File okay. Oh, I saved this and it rebuilt it to nuke the file system. Let's do that again Okay, there is the output dot that an output dot that and make comm should be identical In fact if I try and run it We get a syntax error Because that's what happens if you do make without a far name good Let's try that with a different file to make sure it can handle overwriting It can Let's try it on the big file So again not what I was expecting and of course part of the problem is this Comparison is also wrong. So it Was just rewriting the same extent over and over again And again that should be a End of extent good so What do we do here? Well a lot of it is the same code as we had for Read sequential, so let's pull some of that out so this Goes here Extend and move to next one ECSUF Okay So in our right code, we're actually going to be doing Exactly the same thing But this is going to be different So that's going to be Internal open file internal create Haven't done that one yet So essentially at this point we want to create a new directory entry Which we can write to Create File and if that doesn't work that means the directory is full and we fail with an error and I'm just going to find out How this works? Values returned in a yeah, we are actually going to have to set the right thing here Internal create file should set a appropriately and in fact it will also set Carry flag appropriately, so we just go to exit the error code. We're returning are going to be wrong in so many places so Check see if the file exists. This one is going to want to be Make file returns. Oh It's a different error code. Oh Yes, I remember this Yeah, this is what happens if the file Already exists, right? So so branch if carry clear to Error branch if carry clear to error so this will return um FF on error, so actually we want to set for here the actual error code which is write record directory full and actually instead of EOF for Instead of EOF here, we want to return Disc full Now we can set a before the branch because we're not using a doesn't matter if we corrupt it And that makes the code slightly less bad So we don't need EOF anymore. Okay Right, let's see what this does So make OS 3 B DOS asm No, that didn't work in fact No, that's right. That's right Move to the next record by closing it Yes Okay, so And we break and I didn't save that so that didn't actually help. Okay Close extent and move to the next one It should have happened carry is clear Therefore we do not go through the error. We now try to open the next extent Because we don't know that it doesn't exist. In fact in this case it will exist Because be Yeah, I don't know how long that file is anyway, let's do that and Carry is set So we're going to try to create it Carry is still set the create failed Yes, there's no way to get the size of a file yet so close Open let's step into this one So we're going to try to find the first Entry this is the thing that must be Failing We're not returning the correct error code here. So Read directory entry Check the position Okay, so the FCB is at 2309. We are looking for output dot dat with Oh one in the extent field So we should now be looking at the first Directory entry check to see if there are any more files There are Start doing the comparison I'm just going to speak into the directory buffer, which is stored at two six one oh Here is our directory buffer. So we see that none of these files match so Let's skip ahead to the ex code Okay, we found a Directory entry Here is our Directory buffer we see there is in fact no Output dot that with an extent value of one. So this is going to fail the comparison Yeah, he is ff it means does not exist We have branched to find next we're going around again. So this in fact should Read a directory entry Check to see if there are any more files and Z is clear So it clearly thinks there are more files Which is surprising. Oh, right. That's because we haven't hit the end of the physical directory, but these comparisons here should fail Yep, we now hit the end. We clear this and We return back to Right sequential We are here So Carrie is set Wait, why is That's not right. I think we were in internal open file there Yes, we were okay. We've just bailed to here so we return now we are in Right sequential I wish I had a symbol table make life so much easier Okay, so We now try to create the file So we checked see if the disk is writable We attempt to open it Carrie is Clear that means it found it right Okay, this is I See what the problem is This value I give past in here is The number of bytes which find first users for comparison. I've supplied t3 plus one That's means it is only comparing these bytes So this is correctly finding that we already have an existing extent. I Think I want to make this s2 plus one So that it compares these bytes This means that this one this routine will not work properly unless the user when making a file Set to these three bytes to zero But I actually think that's correct so make As in 3d dos as a Cannot open file. So what's actually in our file system? You've got an output dot that We'd extend zero. So we've tried to open the file This should be FCB s Hang on s2 Do I need to plus one? I think I do need the s2 plus one. Okay. Well, we can still open files, which is a good thing Oh s3d. Awesome Well, it read it that time But it's still not advancing to the next extent. Okay, we hang 1c19 Okay So at this point we should be trying to create the second extent So we managed to find it Carry is set. We did not manage to find it. That's a good thing Okay Clear the allocation buffer Yes, I know this will work And we can see the allocation buffer that we're trying to make in The FCB we're trying to make in output dot that so there we have Extent oh one that record count should be a zero Won't make any difference for this, but we should set that So search for an empty deer int We set the drive to e5 to indicate. I want to do that find first Carry is clear the directory buffer is now the current deer int is now set to the address of an empty deer int BCS error. I did test writing files Didn't I? Yes, I did. How did that ever work? Find first must be returning the wrong value Okay, well, let's reboot Go as 3v lost as a Okay, you can you Can you second extent? third extent Fourth extent an exit good good good and we should be able to type output dot that and There is another copy of our file fantastic Okay, well Let's Go to write sequential we want to clear the record count Because the new extent is going to be empty Excellent, and I believe that is working And you should be able to see that our cpm fester image is now quite big Because it's got two copies of that huge file in it Here is the here is the file there Good, okay, just for fun I'm going to fire up I am going to force Recreation of the image then I'm going to I can type create a copy of the Moss DFS disk image and Fire it up in the mess emulator to get realistic timings So there is our OS 3b Dostasm. I run bitmap We can see that this much disk is used and then we've got all this Free space So let's try copying a file Well, that's embarrassingly slow Yeah, I was going to try copying the big file, but I don't think I want to do that. I will try typing it So there should be a longer pause as it hits the end of the extent wherever it is There it went but that was it changing extents good Okay, just control seeded Okay, I believe that's working so let's Let's commit to that we haven't tried it with Very big files that is files that extend beyond the I think it's Well, it's 32 by 16k Anything above half a megabyte starts using the S2 bite for the high bite of the extent But I don't have enough, you know space on my disc for that. Okay, there is one thing I do want to do So if I change the disc format to use a block size of 2048 and I'm also going to have to go into the BIOS configuration and change this to match And touch yep, so that will recreate the File system So with 2k block sizes we now have multi We now have directory entries with the two extents in them So this one We can see me now. We now only have two directory entries for our file. This one spans Extents zero to one and this one is two to three So This should work just as before So make BDoS to asm Whoo, that wasn't good there should be more dots there. Okay, that's that's a bug So what's this actually gone and done? It's created the output dot dat But it is allocated no blocks for it Hmm the fact that it suddenly exited Suggests to me that something failed with an error Probably Well, it'll be something here in right sequential So use your plan Right, it's never even getting to write sequential This means that read sequential Must be failing This is the first time that we are reading from a multi-extent file But we know that we must have opened the file otherwise you wouldn't have got to this point So what is going on? Oh, yeah, this is it trying to open the ccp in the CA6 Reset jump Continue restart Continue just loading all the ccp sectors okay Make OS 3 BDoS to asm So this is currently loading make we should see a dot when it there we go so now we should be trying to open our file and We can look at 2 4 oh e OS 3 BDoS to asm and That is a one that's not supposed to be a one that should be a zero because this is the FCB Right, I know what's happened here Which is that open file up here has not reset the extent To match the value the user gave Yeah, so we load okay. What's happening here is the user has supplied a Extent value of zero because they want to they want to start reading from the beginning of the file We have fetched The directory entry for that extent, but the value in the directory entry is one Because that directory entry contains extents zero and one so we've overwritten that value in The users FCB which we don't want to do that because it is one of those cases where the FCB and the directory entry Are different things? so in fact here We want to We do that so why has this failed so if Read sequential has So surely all of this all this will have done is To make the user think make the user program think it was reading extent one So we see current record is zero Yeah, let's step through this and see what's going on so we've compared current record with the record count the record count is Zero extent one no records Thinks the files empty so it is correctly Stopping so they are the same. So yes, we drop through to here is the extent fool. No That means that we must be the end of the file. So we jump to EOF which is here and it stops But we see that our two files here both have record counts of eight zero so in our Open file copy the dear end to the FCB mm-hmm Set bit seven of s2. I did actually see that it had done that dear end extent minus CB extent. Yeah, we wanted to see if it's zero on oh Wait a minute. Didn't I write this code before I realized how six of O2 comparisons work? Let me double check that So here's the table See is set if a is greater than equal to temp B and a is EX so if they're not equal if Carry is set then the user extent is smaller that means Temp B is the user extent We saved it up there Right Yeah, okay. I understand what's what's happened this code Has it's decided it's followed this code path. It thinks we're after the end of the file So it set the record count to zero and that combined with the invalid Extent byte was making it go wrong. So make OS 3 B Dost asm and that should have Worked this looks like text to me good, okay Next thing we want to do is we can create files. We do need to get rid of them again This is actually fairly straightforward We are going to go to the CCP because we need to add the command for it That is you are which is here So this takes a FCB so we pass it This code is being repeated lots of times. So we can probably actually Comment it out. See we're doing it here again. In fact, we can do that here BCS invalid file name that we know is going to be in range because it's like the next function down So this becomes As valid user FCB FCB we then want to well What I'm what I'm actually going to do is to just call the The B DOS a raise Entry point which is here delete file this takes a wildcard FCB and and Scans the entire directory nuking every directory entry that matches the wildcard now If I go and find the implementation in the CPM 80 CCP then it's actually got a bunch of Tests to make sure that you don't do this by accident, you know like a prompt We're not going to do that for the time being. So, yeah, that's the entire piece of code so we're going to add a Arrays function. We are going to copy Open and need that Or get or set We do need prepare. We don't need clear We just want that and we do need to make sure we are exporting that. Oh, yeah We want to Do that cool So that's the CCP side of things So we should be able to actually Do that. So we're going to arrays read me dot text Unimplemented so back into the VDOS is a table delete file Create file close file Let's put that here Also, I was just thinking that I forgot to do a thing with closing the file, but I didn't that actually worked out I'll explain more about that later so delete file Convert user FCB usual We are now going to search for all files And destroy all files matching the file name so that's going to be C3 plus 1 because In this situation we do Only want to match The file name part so it doesn't matter what these bytes are set to we want to destroy them all So if you want to delete one file, it will find all the All the matching Directory entries that make up that file and remove every one of them so we We are going to have to call find Next multiple times. Okay, so if carry is clear that is, you know, if we found at least one File that matches then We're just going to loop like that Where are we calling find next? delete file Here no, I Don't think we're calling find next from anywhere apart from Entry find next what does set up FCB for find do I Think we have to call this because we are going to want to match the wildcard stuff No, we don't no, we don't Because we don't care about the extent stuff because they're not matching those and I Don't think The special wildcard search applies here the name can contain question marks Okay, so we're not calling that Okay, so the obvious thing to do here is to simply Mark it as Deleted by just setting e5 in the drive byte and call Right sector to write it back to disk But there is another thing we want to do We have to be able to free the blocks for that been allocated for it in the internal bitmap So that's going to be a call to Well, eventually update bitmap status But I think we can do Here we go update bitmap for deer ant and it does indeed work with current deer ant So all we're going to do is call this with X to Z as zero To mark all the blocks in that Free all the blocks in the matching Deer ant of the LDX zero call update Bitmap for deer ant then we mark it as deleted and Then we continue on for the next one so If we look at the bitmap we see that we have a nice contiguous set of blocks. Let us a raise make comm Okay, and we see that one block here has been freed In fact with our 2k blocks Each of these files is one block except for this one, which is all the rest. So we've got One block for the directory That's one two three four Five that's the fifth bit from the left So that is bit three Or rather says to that the other way the other order bits Seven for the directory bit six bit five bit four Bit three that's the top bit of the bottom nibble. That is the right one They are and the file has gone good And if I now delete OS three Need us to asm All of those have gone We have one bit there That'll be read me and now if I do era star dot star There is nothing there And I can't run bitmap anymore because I've just deleted it and if we look at our file system Here are all our directory entries Or with e5 as the first bite You know that was Remarkably simple. This is actually kind of what makes the CPM file system so great It's I mean once you have the basic primitives you can do Stuff like this so easily else. Do we need to do? Well, all the unimplemented ones here. We haven't done any of the random access stuff Let's do some of the easy ones get login bitmap to the Login bitmap so this should be Login vector plus zero Login vector plus one. Let me just check to make sure that that's is actually Yep Just make sure that wasn't a pointer. Okay We haven't done the root the The read only stuff done rename file. Oh get version. Let's do that one Entry get a version return version number so This is supposed to return a two byte value with machine type in the Bottom CPM to type machine type is in the high nibble the CPM type is a bitmap field in the low nibble now There isn't a number for 6502 so We're just gonna have to make one and the CPM type is going to be Well plain CPM so and the version Number oh right. Yeah, the version number goes in the low byte. We are simulating CPM 2.2 and this is system type Done Get to read only bitmap that should be That's right protect vector Yeah I'm type right take vector to zero Right text vector plus one Okay done Set drive read only actually Actually let's do console status In which there's an annoying amount right string. Here we go Entry get console status so If there's a buffered key actually let's look at the documentation for that one A equals zero if no characters are waiting non-zero if a character is waiting So if the value in buffered key is not zero Then There is indeed a Character waiting so if it is zero then we actually need to check with the BDOS So with the BIOS that will be const and const returns FF if there's a pending key so That is just this code So that if the value in buffered key is non-zero Then it's already the right thing. We want to return here So we just fall through if it is zero we call by we call the BIOS that gives us our value and we return that easy Range error 4080 is not in Machine oh, that's a nibble Okay Better set drive read only all this does is set a bit In the read-only vector and Actually, I wonder do you have Right. We're not actually doing anything with it. The drive number is in param plus zero So all we need to do is That's this one Temporarily set the current drive the current drive to be read only Okay Good job. I checked so We do actually have a routine for doing this here so Be right protect take a pointer to the bitmap the actual bit number goes in y and we call the routine and It does say that it can fail So we should probably Actually all of these should probably have a CLC and let me just check set bit Yeah You give it the pointer in AX and it modifies it by Shifting the value in temp to three left by the right number of bits and then all ring Everything together. Okay, does it build? It does Get dpb is another trivial one a pointer to the Current drives dpb of the current drive and hey, we already have a pointer to it Okay reset disk So that's probably wants to go near Entry reset Actually, some of those things below should have been here, but Once this is done. I'm just going to go through and do a big clean up and retie D pass Okay, bit 7 of D P will be a bit is set if the corresponding drive should be reset Okay, so so what we're going to do is We have to iterate through our vector. So if the carry we look at the bottom bite of the Of the 16 bit value we get given if it is set if we Do this way that just saves a bite then we're going to do the reset then We are going to Shift the whole thing right by one increment 10 plus 0 We can now either Look to see if we've hit drive 16 which is invalid or We can all the two param values together and in fact that they are Same size, so we will do the slightly faster one So we keep going until param is zero Returns a equals zero if okay ff if error I'm not quite sure how that could fail to be honest So resetting the drive Removes its software read-only status like that's the only thing it does We can make this so much simpler because that's the only thing it does We can we can just Directly reset the bits and Exits okay. Well, that's Simple, I mean it may not work, but it is at least simple Direct IO I think we should do So direct IO simply provides a Faster way of well it provides a way to get at the the BIOS without doing Let me try that one again It provides an interface of the BIOS console IO stuff Which Understands about the buffering the BDOS is doing But doesn't echo So Actually, we don't need to support these Return a character without echoing if one is waiting zero if none is available weird Without waiting It's not equal to ff Prince it without echo so If it's not ff then Fact we can do be any Entry con out No, we don't want to do that actually because this this being direct IO We don't want to go through this stuff This will be the routine that's used by programs that we don't want to Send control sequences to the The Output terminal directly so that's just going to be BDOS con out CLC RTS So now we want to read a key if it's available So if there is a key buffered, then we return that if there's not a key buffered Check the BIOS That will return a key in a or Now that will turn the status in a if it's ff Then Ff if one is so if there is a key and Zero if no character is ready. So This can only be zero or ff if it's ff then cool con in That returns it in a otherwise a must be zero So we can just exit Okay, so what have we got left to do? Well, we've got we're not implementing these because we're not supporting IO bytes or Input an output, but we should probably stub them IO byte and And reset IO byte so the IO byte controls Redirection in CPM Poorly returns the IO byte and sets the IO byte Okay, so the IO byte allows you to specify what your input and output devices are Output devices are the printer the The tape punch and the console Tape punch is normally set to be the serial port these days Input devices are the paper tape reader Also usually set to the serial port and the console There's no way to configure any of these things so you're basically, you know Stuck with what's here and it's annoying to use and it doesn't support anything like file redirection and If you've got more than one serial port, then you're kind of stuck There are some undefined fields here, and it's just generally really confusing to use so I'm not implementing them I don't believe it's useful on current CPM machines. I do have a plan for Doing something equivalent using loadable device drivers But For now, I'm just not going to do anything with this so To get the IO bytes we're going to always return a stub value of All Not all zeros list wants to be Lpt So that's one zero punch is paper tape printer oh one reader is paper tape reader 01 Console is always going to be the tty Okay, that's all that's going to do In fact these are all going to be this So they'll all point to the same routine that just sets the carry to indicate there's an error and exits Okay So what is left? Rename file Which will be annoying mainly because of the api Set file attributes that's fairly straightforward Read random and write random which should be fairly straightforward They just do a bit of maths and then do a read sequential write sequential There's a few educators that might be irritating Compute file size compute random pointer These just do basic maths again This one does a directory scan And write random filled Which is probably going to be the most annoying of the lot because I don't think we have useful primitives there Write random with zero fill Yeah, if the right is to a newly allocated disk block the remainder of the block is filled with zeros So yes, uh I'll have to think about that one. Normally you just get garbage like whatever's left on the disk Um This is not a fast. This is not a operating system that you use if you like security Okay That is looking rather good So I am going to stop here and come back next time when we will tackle some of these big things The light is definitely at the it's definitely showing at the end of the tunnel And it's certainly not a train. It's all looks like it's working pretty well our code size The bedoss is We've got about a kilobyte spare of our I was actually going to say we've got a kilobyte spare of the three and a half k that cpm 80 is But that doesn't include the bss here That's not actually that much of it We're definitely coming in under quota Um as for the ccp which is 2k we're well under for that I mean we haven't implemented a few things but It's looking good So this actually This may be coming out dense of an Uh 8080 code Which I should not really be surprised at 8080 code is quite kind of terrible So that is Good. Okay. See you next time. Oh, yes, and we need to tackle submit and that will be exciting