 day five Let's try and make the ctp do stuff, but first let's fix a bug so During the off-time I put in the jump table for all the VDOS entry points because that's just boring cut and pasting and not particularly interesting and An interesting thing well the only interesting thing about it the table is uninteresting the consequences of the table are interesting Anyway, when I run it it crashes It has Printed a couple of numbers and stopped as you can see that's not an error It's just got confused and died and the reason for that is dead simple. So our ccp Does nothing other than exit What does the exit entry point to do? well It's here and it loads the ccp So why hasn't it reloaded it correctly? Well, the answer is because The the FCB we're using to refer to the ccp Has its various fields set up from reading the last ccp So open file does work. It opens the file We then try to read a sector from it But it's already at the end of the file So it terminates immediately We patch it. We relocate it again This mangles all the fix-ups in the ccp and then we try to run it. It does a hyperspace jump into nowhere So we need to be resetting the relevant fields in the ccp Which Honestly, I think that the open call should be doing this. I think it should reset Well, we have to reset the extent the current record and s to but It doesn't so there you go FCB comma hang on a second Ccp FCB is a 16 bit value. So there's no point doing any of our indexing. We can just do whoops Do that again, but pressing the right keys this time. You just do early zero plus FCB extent byte s to By S to the module number should be a document here on the disk formats This one contains the description of what the various fields in the FCB do you go s to the one we want? Yep and Current record Okay, so now when we run it it should Not do that extent counter extent counter It's also going to mangle the drive number whoops, and that should be a one Okay, I am confused now So let's use the debugger. So we are going to one nine oh four continue Run Okay reset the disk system. We're here clear the relevant bytes in the FCB Load the address of the FCB into one E one C So when we dump that we can see drive one file name everything else is zeros and We're now about to open the file. So let's dash another break point there And continue and it crashes immediately So it's trying to print an error intriguing Okay, open the file Carry is clear that means the file is correctly opened Yeah, I can't step over that bcc Do that again And we get already open Actually, I will do something about that right now so the reason why The file is already open Is because it's referring to the cpmfs file that we've opened here a soft reset hitting break It's not close all files, which doesn't make any sense, but That's mos for you. It's a decent 8-bit operating system, but it does have holes in it And this is one of them Uh, so all we have to do is call The system core to close all open files mos api It's os find doing this There we go close the file specified by the handle Uh, if function is zero handle is in y and x is ignored so Like so so now we hit break we hit shift break And it actually runs. We haven't done a hard reset On the bbc micro you do a hard reset with control break and that resets a whole bunch more stuff Open the file Yeah, carry clear Get the tpa address into user dma e49 Which is 001f Our bdos is bigger now. So we've it's claimed another page Start reading The file. So if you now look at 1f. Oh, oh, we see The wrong file. I know what's gone wrong Some of the stuff I did offline was In the bios here. I wrote this huge terrifying macro To alec to compute the dph and dpd So You give it the disk parameters. So 40 by 32 Sectors 2k blocks 64 Directory entries no reserve sectors And I bet that this Is Yep This is configured for a block size of 24. This is cpm tools definition of the disk I'm using this to create the file system And he's using a block size of 1024 So we just go up here and change this back to 1024 which I must have left in for debugging And now it should work Okay, it should now be spinning loading the ccp over and over again So let's actually make the ccp do something So here is our system call table twice low byte and high byte the same as we did for the bidos And we're going to put in console Well one console routine con in No con out entry con out So what this does is I just don't want to check to make sure that I put Bios con out that's in lower case That should be an upper case and Bios set tpa Likewise be Get tpa Okay, so all this will do is on entry So we should theoretically just be able to do jump bios con out Or even just put bios con out directly here but Uh, I don't think we can because console output Send the character to the screen tabs are expanded to spaces I think it may also turn Carriage returns to new lines So con out ends up actually being quite Big Right the character What's this doing? You can also you it'll also It does X or X off Uh pausing Not sure Yeah, this is Wait a minute. This is the That's not the user typing on the keyboard. That's the the character being sent from the program to the console So i'm not sure how that's actually supposed to work Comp call is true if we're computing the column position because we have to keep track of that to expand tabs Okay, well, let's Let's define a byte to put the column position in Uh, it will also potentially copy to the printer, but we have no printer in cpm 65 so This is the Column stuff it also handles backspaces Sends the character in e to the screen Taps expanded spaces up can be paused with ctrl s and restarted with ctrl q That sounds like it's the user typing on the keyboard. I'm going to find the original documentation So here's the original cpm 2 interface guide. Yes ctrl s and ctrl q are Typed on the keyboard and this is checking for Starting stopping the scrolling the thing is that There is no way for the bdos to buffer Incoming text So I would expect that It's more on receipt of a ctrl s on the on the keyboard Then we would end up blocking in the console input routine Rather than console output So what does con brook do? Here we go Check for character ready Okay, so this actually seems to be doing the blocking in con out rather than con in Which is weird Anyway, so the input character isn't a So on this info to you can use the bit instruction to test flags So we're going to say bit output paused What that will do is it will read the value Set the n and v flags Based on the value It then sets the zero flag to that value anded with the accumulator We don't care about that and we're going to be using the top bit So that when we're paused It'll be negative So now we want to compute the column position so if a is A backspace Which is ASCII 8 or ASCII 127 We want to Decrement Column position If it is negative zero it if it is a Tab Wait a minute Comp cold is true if we are computing the column position. Why would we not be computing the column position? This is the code That prints the character Yeah, why would comp cold be false? This is the buffered read routine I was expecting these routines to be dead simple actually, but they really aren't True if computing column position So the only place it seems to be being set is in the read routine so This is the buffered read routine. It reads a line from the keyboard with simple line editing Really simple line editing So we have Carriage return line feed backspace This is all the backspace code Comp cold greater than zero marks repeat as length compute whatever that means Yes, I don't know what that does So let's ignore it for now I think it has to do with being able to set this to zero And then you can write lots of stuff with con out and it will compute the column that it will have been at I don't know why anyway So this is actually going to print the character first Are we going to Are we relying on the terminal to do tab expansion? Well, here are the comparison routines in this and there's backspace space It's doing that to check for control characters And Backspace Again a different backspace no column change if nulls These comments are not terribly helpful. Okay. Well, so we print the character and now we compute the uh Column position which we're going to do the easy way It's actually cheaper to do it like this than it is to um And I just want to check to see I think decrement absolute Yeah, all the decrements set the negative and zero bits so we can do if negative lda zero sda Column position reset column position to zero and exit so branch if equal to backspace Branch if equal to Backspace Is it a tab? If yes, then we want to Advance to the next eight character boundary so They carry and one Okay And if it's a control code That is smaller than space then I think as a simplifying assumption I think it's a simplifying assumption for all control codes which includes new lines We are just going to Uh zero the column position. So what should this be? so if So we are subtracting position minus 32 so if Char minus 32 so if the character is 31 We will get a A result of minus one carry will be set if Char is 32 then we forget as a result of zero and as we discovered last time the carry will be set So we're going to set that to 31 one less And do a branch if carry set to zero column in all other cases We are going to increment the column position and exit And there is actually one other thing we want to do Which is up here somewhere Well, I can't find it, but it's something we have to do Which is to Mask off the top bit because cpm is not 8 bit safe Although given that we're not actually going to be running any real cpm code Let's make it 8 bit safe All right And I actually I think I can do slightly better than this Load the column position into x Then this means that Because this is three bytes So you want to increase the column position inks and it with not seven and store and exit Here we just want to increase the column position store and exit In fact, we're going to want to do a lot of storing and exiting So decrease the column position is dex Zero column is a simple ldx zero And here we actually want to store x and exit Which means that we can't actually put a jump exit in there. We do want to store a We could put it back into x and jump down here, but that's four bytes, which is what this costs So it's all the same Okay, so basically it will do a cheap and easy a Count of what what column we're at Assuming that the terminal is going to expand to tabs, which I think it does on the bbc micro um And whenever there's a control code normally the user has Done a return Then it'll reset the column position to zero and here We are going to Check to see if the user has restarted output So to do that we are going to Push the character as it's dash the character that the user's trying to Let's do that here actually We want to Read a character that the user has typed This is This is calling console status Return if no char ready Check for character ready Oh, I see what it's doing I see what it's doing It's checking the status on the output so that if the user is typing while text is going out It will process the key. I did not know it did that Huh Okay So stash the character being read um Check to see if there is a character ready our bios is Where's const We're turning zero or non zero for no ordinary boolean value So I'm in Check for stop screen function. That's control s found control s Yeah So we're going to compare with control s is x off which Is not on this List n o p q r s 19 um If the user's typed to control c Then we immediately reboot the system That is restart the bedos and the ccp Thus exiting the current program So if you if we are pausing If we are pausing then we just block for another key discard it And then continue on So we don't need that anymore right 294 minus eight why okay Zero column is defined inside a scope so we can't actually Do that okay, so we need to do branch if positive to exit pause is undefined eq Right now we want bios con in and const And we're putting our bios calls down here con in con out cons Data's This is too far. We can't we can't Jump this far I could probably do it if I put the console stuff above the jump table So let's just do that 6502 short branches have a eight-bit displacement Now this is just too big Okay, well, let's put that back where it was And this has to turn into if equal jump to Exit Okay, so this should run but nothing will actually happen because we're not doing anything in it here So let's just do a as if on here LDA q Y dos All output jsr b dos In loop Right, and let's see what it does Okay, we successfully print a q and then we stop and I know why we stop that halt message was coming from Here because we aren't returning from the from after our system call So we could just put a rts in and then it should work There we go Our ccp is now printing lots of cues and Because of the magic of moss I can switch to a high res screen mode And everything should still work And you can see the speed at which is actually doing The things which isn't brilliant. So there's quite a lot of overhead But anyway, that's the way it is Okay, so we now have our console working. Oh, yes, there was actually one other thing I wanted to try Okay, it's running I said control c Nope control s Nope Am I using the right control key? Yes, I believe I am Okay inki is wrong Uh inki is the system call we're using to actually do the console status Stuff just wondering how to step this Actually, one thing I can do is Do that Okay, that is actually typing the word key So we know we've reached this point So we read the key And then we test it I bet con in is not working right So con in If There is no pending key called read char. Oh, this is this code is broken Well, that should be a jump for a start So if there is no key pending called uh osrudge And then exit immediately. That's why that's a jump otherwise Return the pending key. We've read the pending key into a so we clear the flag here and exit So here If there is a pending Key Then Say yes Otherwise Check to see if there are any keys pending from the operating system By trying to read one with the timeout If there are none Then no Otherwise Store the key And exit Yeah, let's try that Okay, not a control s. That's still not working in control c Yes, I can't actually tell if that's doing anything. I don't think it is I think it's just printing the word key in stopping So we're going to have to debug this and we are loading at 40 o If you want to debug the bios we continue Okay, it's loaded That is the table we're looking at here This garbage is ascii text and here Is where we're going for a one Okay So let's press a key and hopefully const will have done its work And we should get a break We got a break So read the key And it was eight one. That's not a valid key Osbyte Osbyte eight one returns the key in X I bet Read key with time limits on exit X is the character So that should be sdx pending key But anyway, it thinks there's a key pending So We skip the call to rudge And we try to return the key Yeah And return now we're back in The bedos and of course that key is not any of the values here because it's garbage So it's not a return So it's not a control s It's not a through it's not a control c So we just continue on Okay, let's try that again control s Oh It's not working control c No So we are trying to get two for a one So let's type a control s Okay Is there a key pending? Yes, there is And it's eight one again On exit X is the character Did I remember to save this? Okay control s Right Right, okay. Yeah, I forgot to save it. That was what the problem was So we now have a control s character in a So reset yeah, yeah is a Uh, it is a control s. So now we Pause waiting for a key like press the key Oh, we're still broken press the key I said Press the key Okay, so it's the second time we're in we've gone through con in So this should now be blocked waiting for the user to type something So we look for the key press the key press is zero. There is no pending key and of course Osrudge I bet Returns It's key in I thought I was going to return it in x again control s continue once Okay, so this is the operating system doing its thing. It's checking all its various Bits you don't want that one Yeah, I think that it's now blocked waiting for a key press I'm going to change this to this Because this will allow me to Step over This First time Second time step over Press key Oh The operating system is not picking up So why is it doing that? Our operating system call is not returning I don't know why FFE zero is the right address. Yeah intriguing Well, I did make it work. So I can do control s And it stops typing and I can do any other key and it continues typing and I can do control c And it reboots You can't actually see anything happening when it reboots except if you go up here into the memory view This noise here Is the bios and the bedos being loaded And what I did was I changed the call to osrudge to a call to osbyte 81 the same one that we're using to Test for a key press I just gave it a high time out And this works and I don't know why this works and osrudge doesn't But anyway So we should now have a console more or less working We've got con out we don't have con in But Let's just skip ahead slightly and do This one as this is a useful routine Oh, yeah, I also want to move these down into Our transient state table because we want it all to be zero initialized When the bedos really starts So what this does is it writes the parameter So the first thing we need to do is get the parameter into a pointer and This brings up another point All our entry points so far well except for con out And exit like a sum of our entry points open file and read sequential They take a 16 bit parameter which is a pointer to the fcb Now all the bedos entry points take 16 bit parameters So rather than stick the code to copy this into a pointer Because they're nearly all always pointers in the entry point itself We are going to do it here So our fcb Uh Variable this is just going to be a general purpose Parameter variable we didn't want to do that just trying to remember what the vim end of word Escape is Angle brackets fcb becomes Param Okay, and we didn't want to change these or that We did want to change that Just line up to these spaces I'll fix the rest of the alignment later. Can't be bothered to do it now. Wow. I did use that fcb name space a lot Okay so We're using these are old user fcb and new user fcb routines to actually store the parameter so we are Not in fact This that routine goes away completely and this becomes a fall through it's for read sequential Okay, we want to leave it our old user fcb has gone away. So this becomes select fcb Drive we're actually going to turn this tune to select fcb drive convert user fcb okay, so this actually wants to store The ccp fcb value in param so that will be low bytes sdp param plus zero high bytes param plus one And now we can use indexing cheaply here Actually, is it cheap if we use indexing it would be two bytes to load y two bytes to do the store and These are three bytes. So it's not actually cheaper. So let's just Shump this down here Open file, okay and param remain set Here okay, so now we come down to the BIOS entry point So the first thing we want to do is to stash the parameter which got passed in in registers So we now no longer care about the value of a so we don't need to push and pop around there We just need to find our console routine Uh, again We don't need to push and pop here So that is just going to be a load the low byte of the parameter Uh reset ignores the parameter open file uses it new, uh Read sequential uses it And I believe that's all we've got so it does this work. No, it doesn't okay. It loads And it reboots And it stops and I also remember now that there is a thing. We're missing which is if the if the user actually typed a control c We want to reboot so that Is going to take this out of line Put it down here Or can we be clever? I think we can No, we still have to I was just thinking there was a way to get rid of that jump, but there isn't Okay So the reason this comes up is because now on entry to write string param is set to the appropriate parameter So all we need to do is Do a loop load The value And And I don't think we want to do that with indexing The reason for not using indexing is indexing would limit us to to 256 bytes in the string And I don't want to do that So it's a handful more bytes So we can do load param comma y Okay Is it a dollar sign? If yes, stop Is it zero? This is an extension used by our uh dialect because in c zero length strings are so much more common And because we just want to check zero bit and that is set by the load we can put that there So and all we do is bios con out increment param plus zero if rolled over in param plus one like so And now in our ccp We're going to add our first utility function, which is bedos right string right string jump bedos And instead of Instead of just printing a queue We are going to ld a is the low byte ld x is the high byte jsrb dos right string Okay, and when we run it We get hello world and control s Should work Don't think it did anything Control c should work That does not look right to be honest Here is our ccp code so 1f07 is where our loop goes so break there continue Okay, it does actually seem to be working Yeah If you look at the memory view Because this shows zero at the top and ff at the bottom Uh this line The red represents right. This is the video memory Uh this Blue means execute green is read I bet this is the string and these are The that that will be the bit of the bios that we're currently running from to print the message And this will be these two blue lines here. This will be the bedos entry point code and the actual Um Printing loop so Good that works So this gives us the ability to print Things let's just do con in So con in should actually be simpler which should just be Yes read keyboard character to a It does actually seem to be buffering One character Oh interesting That's the character red elsewhere That's this character This is so that if you press a key that's not a control s or a control c It gets buffered ready to read later So we're going to have to put that in So this is actually the same code we're using in the bios Load buffered key If it is zero read it otherwise Clear it and here If it's not a reboot Then we actually want to store the key in Buffered key So what if you type two characters while something is being Listed Then You'll lose the first one. I think that's good enough Okay, so let's go to our ccp con in So input Beados Beados con out all output jump Beados So let us print Then oh that didn't work What's this complaining about A local scope was not closed I didn't put an n proc in better Okay, let's try that And run Type something Good good good control s Yeah, that eats That eats several characters. Why is it eaten several characters? Oh, I know what's happening. We are printing the control s and it's being interpreted as a bbc micro Uh escape sequence Okay, let's try control c Is that working? That's not working Uh Because control c is not interpreted in con in it's only interpreting con out Okay, anyway, let's change to higher s text mode Manually with the star key gone Manually run the thing. So if I type control s control a a Then three more a's Yep I remember that from times past vdu 19 The control code 19 otherwise known as control s Is the the code for redefining the palette. So I turned uh Logical color one which this mode is monochrome. So that's white Into Physical color one which is red Anyway, that was a thing That works good So If I look at con in it's Not parsing the character Wait a minute. There's actually a lot more to this. This is a fall through Right it gets the character and then it prints it No, there's a jump. It does not print it But it doesn't parse it either Uh There's two entry points one does not print it One does print it Which one Are we looking at here? console output console input Uh, it reads the next console character to register a Graphic characters along with character turn line feedback says our ecode Yeah, so con in here is actually con ec In the in the original code con in is used elsewhere There's the error handling routine It's used by con ecco And it's used by The live the buffered read routine So this is actually going to Not fall through to print the character Uh, we want to Hmm We want to print it, but we also want to return it in a or do we want to return it in a So this entry code on entry we are putting the value into Param zero and one I think we should do the same thing on exit. So we return the input parameter so that exiting from The actual entry point We are then going to want to reload These and return So the only thing we've got so far that returns anything Other than the carry flag on error, which is important is this See now this will just work Open file can return an error. It should return an error code Uh, I think find first is doing it This is read sequential. This is returning an error. I think we now need to put this in param plus zero And set the carry flag Not there. This is also No, this is an internal So that's fine And I don't think we're doing this anywhere else Yeah, okay So We should be good We also want to change our ccp Let's just Just increment a Okay run So if I press an a That's not what I wanted Interesting I am pressing the same k key the same key each time that should be an a So I'm guessing that these values are not being read in and out correctly That will be a Entry point thing so we are storing The thing in a x in the parameter And once we've done that we are loading the thing from the parameter into a x So con in this wants to be a Jump exit We go press a There we go So we get the a that's echoed From the first key And the b that's comes from the ccp after it returns the value so Good and if I do a control c it should restart ccp Of course it didn't Why did it not do that? because This has I think Yes Because this has put the wrong value into x into param zero I don't even know why that worked to be honest con in Returns its value in a so we want to put that into x That's that's not great code So that's working control c Did I say this was supposed to be easy This is just a Frigging console it should be straightforward transfer a to x jump to exit This dx param plus zero Jumped entry con out. She's here check the console status. Yeah, yeah interesting So the key being pressed by con in Is put straight into the parameter But this is not reading from that this is reading directly from the console and of course there is nothing pending So read character with echo call con in call echo c To echo the character which does this bit So if it's a If it's a control character we know about Ignore it If it's any other graphic character ignore it I'm not sure why this needs to be that ret here is wrong No, it's not wrong. That is just setting the carry flag on exit This isn't falling through even though it kind of looks like it is So carry set if not graphic So return if carry is set. So if it graphics then We do this Character must be echoed before return. So we only echo graphic characters If this logic is weird So that calls tab out to do the work Which expands tabs? Uh But con out Does not expand tabs control out expand Does con out call control out? No Does tab out call con out? Yes So if the user calls console out Tabs are not expanded But it says here that tabs are expanded. So again, is it relying on the terminal to expand the tabs? I'm very confused at the semantics of the logic here and also console input graphic characters Echoed tab characters are expanded Check is made for start stop and start stop printer Okay, this is weird I don't quite follow the logic of what's going on. So let's simplify for now So we read a key. I do think I want to check for control c in the input path that's the Hmm No, actually, I don't think I will Uh, so let's just simplify con in so it actually makes sense Yeah, I think that will do uh honestly Let's just if we compare x with minus one and if Carrie is set It's a graphic character So carry clear meaning it's not a graphic character. So print it Otherwise just exit So we only echo Non graphic characters So control c won't work, but I actually I think that's not going to be a problem. So if I do control g That beeps. Why is that beeping? Shouldn't be beeping So we read the key Put it in x go down here I'm going to have to step through this This is ridiculous. I'm getting myself incredibly muddled So here is our jump table Therefore we want the first thing after it which will be here At four five six seven eight nine a b c d e f one eight two f Which is there Break one eight two f continue Okay It wants us to type something step step Con in We're blocked type of control g Okay so A contains seven that's the what that's the the beep character control g So step we put it in x Jump to here We're putting it in the parameter Is it less than one f? I have the sense of this Wrong, that's why okay control g Good it didn't beep, but it did move the cursor back left. That's because uh This is receiving a seven not echoing it returning it to the ccp The ccp is adding one to seven to get an eight which is the backspace character and calling con out Good, that is what we want right Next one this one's going to be moderately exciting We're doing read a line This is the the line Editor This finger quotes around editor there. Uh, this is the thing that Reads a line of text from the keyboard with the ability to Uh, do basic editing So read a line from the keyboard Buffer is at param Size at param Plus zero so Go to the ccp We want a buffer and it's going to Start with the size of the buffer which is going to be 128 for us And then we're going to reserve some bytes for it Here We Here we Set the size. Let me just check to see whether this is whether the size byte includes The maximum number of characters the buffer will hold So I think that does not include The size byte itself So this is going to need to be a one two seven Store it in buffer Okay So on entry we already have the buffer set up with the length in param plus zero so This is the description of the various control codes Certain functions which return the carriage to the leftmost position Do so only to the column position where the prompt ended So this is one of the reasons we need the column position Starting column position is a byte so lda Column position sda Start column position And this is basically A big loop we want to Start with The length And we're going to store that at 10 plus zero Actually, we can do So essentially what this will be is Reading a character Then we type Then we echo the character So it's using con in Ah, yes, that's why we that's why this is using this rather than The bios because we want to honor the existing buffered key Okay, well So read a key without echo easy to graphic character And we know from up here That we want character set so If we are already at The last Position in the buffer or then do nothing So If it's not equal to that then We want to You want to write that to the buffer and increment the buffer position and Echo Which we are going to do using the bios Like so Have not done said continue Yeah, I don't like using a jump there But that will at least work In fact, we've just fall through there Okay, so let's see what this does Type something good Let's actually just change the ccp to make that buffer a lot smaller And see if that reaches the end of the buffer No, it doesn't there we go so Our buffer is eight bytes wide Our pointer starts at one two three four five six seven So we can actually enter that last one Console input is terminated. Oh when either the input buffer overflows When either the input buffer overflows, there should be an or presumably when someone presses return so Mx is the number of characters which the buffer can hold So our buffer is ostensibly eight wides. That's zero to seven So mx should be seven. So we should be able to store one extra character So this should not be a not equals This should be a carry Clear carry set It must be carry clear But I think we're doing this comparison the wrong way around Yeah um We actually want to compare with one plus The easiest thing to do is to swap max and pause, but of course that won't put the value in y that we need for here No, well, there we go seven characters Terminate with either a new line or a return So on exit We want to store the buffer length in the parameter buffer And exit with other things which are Which we can do are control h for backspace But we are also going To support 127 Because otherwise life gets so annoying so this Will be Just thinking how can I do an ore here in a reasonably sane way? The scoping is not making my life easier. I have to say I mean these structured macros are making my life a lot easier But trying to jump into one is tricky so if If the buffer position is not one The buffer position is set to the The next character That we're going to write So yes, if the buffer position is not one Then x is the maximum number of characters in the buffer and sees the number of characters read So that's actually going to be one less than the buffer position Uh, we want to make uh, we want to have y be the buffer position Because we want to index into param and we want to skip that first byte So if it's not one Then we are clear to Delete one character So that will be deck buffer pause Print the The delete character Which will move left one and arrays and loop Otherwise do nothing. Uh, it's not what I wanted. Right Uh, that I believe was deleting back to the beginning of the line, but then buffer position was one So it was skipping this and going through and It was that was a graphic character. Therefore, it shouldn't have been printed That's better And if I press return Then we turn back to the ccp and it loops So what else can we do? Reboot If we're at the beginning of the line boot Otherwise abandon the character. In fact A z continue turns up a jump. So it's actually much cheaper to just uh Load a with a value that's a graphic character and let it fall through the rest of this conditional Well much cheaper being two bytes So If I press ctrl c here Nothing happens. If I backspace to here and press ctrl c It reboots good ctrl r is No, I can do this the easy way. Uh, and r is Is 82 82 minus 64 is 18 So if it's a retight then We want to print a new line We then want to print spaces Until we reach the column position that we started at Uh, we can do better than this We now want to print the string It'd be nice if we could just call the print string function, but we can't so So we compare with buffer max break if it is Equal have we run out of temp that we haven't So the problem here is we're about to call Um Bios con out which will corrupt Why we start that with zero Increment it here and save ourselves a little bit of Pain And what does this do so I type a ctrl r Well, that wasn't right. Okay debug time and we want to break out one out of four Start it We didn't want to break it one effort for but never mind Uh So that is con in This looks Like I think we're here No, we're not Here we are. Uh, this is this piece of code here. Okay, so Delete Reboot The next one here Is retype 1b o 1 So print a new line Okay Load the column position Which is zero because we've just printed a new line Wait We printed a new line with The bios We're doing all this with the bios. We're not updating the Column position So in fact the column position should be z should be Set from the end of the string Wait a second This is using the Blasted Um Bios we want to call here So we are going to put our pha in pla back there And we're going to put A We're going to put an internal con out here So that here we can call Internal con out and it will type it using this code But we don't want to do that here because we don't want these things to be interpreted So in fact Whenever we call con out we want to also increment Column Position or in this case we want to decrement column position to make sure the column position is still kept current so retype line increment column position and Likewise here we want to increment the column position And the count and here we want to increment the column position Apparently we've just used another another page a controller Well, that's still not working, but it's now at least breaking differently. So this looks like Compared with 12 that is 16 17 18 retype line. So break 4 print a new line And you see the cursor has just moved down to there Load the column position, which is 6 Is that correct very much Not correct. I don't believe that right string here Has incremented the column position. It should have but I don't think it has Well, anyway, let's just see where we Let's see it Pipe more I'm going to have to give up on this session soon. I'm tired and going a little bit horse 10 What's at 10 10 as I start in column position is zero yet. So in fact, this should do nothing. This should break immediately Which it did not The column position is bigger than start column position Start column position is zero Yes calling new line should have reset the column position column position is in one f 8 2 Which is seven that's the the characters I've typed So we call new line back. Let's Just put that right here if we need another new line. I can In fact, we do need another new line But that's going to go here because it's part of the console stuff And I'm just thinking that the other place we want it is actually up here to In void No, it's not it's In It's here Yeah, so there we get our extra new line. I'll take out the extra one in the bios in a moment. So control r But now where did we put the bios? Banner, um, I managed to save a byte by reversing the string Okay, well I go on 1b o 9 is where you want to be Okay, so we're here We need to the column position Which is seven. Yeah, it's still wrong. It's at 10 10 is zero start column position is Yeah, I I'm losing it It's late. Okay, so New line. Yes, we're on a new line Load the column position Which is nine. Why is that nine? This should be this is calling internal con out Which is hitting This code is this wrong. I think this is wrong. So if Uh, if the character is 32, then we get zero and the carry is set if the character is 31 minus 32 that's negative and the carry is Set Yes, this should be B bcs that is correct probably Okay, so we go into the new line we print a 13 We are here and in fact, I don't think you want to go through this code at all Not from the editor So we test the key Nothing is pressed. So we go to here PLAA is a 13 print it Read the column position to x x is seven Was the character an eight? No. Was it a backspace? No Was it a tab? No Compare with 31 carry is clear 13 minus 31 Is negative So why isn't the carry set? Well, that's just going to increment the counter Yeah, we we do not want To call con out here and that code was wasn't working anyway um We do want to call it from right string hmm So when in doubt look it up and this does say that if Uh, a is less than operand Carry is clear So Anyway And now we have problems Here because that we have too much code Um, we are actually going to need to put something else in so Uh Let's just bail out to a function. This will cost us three bytes four bytes rather Because we've got the three bytes for the call and one byte for the Return here But it does make the code easier to read which is more important. It still doesn't work Okay bugger 1b34 we want to go to Okay run type control r Okay print A carriage return using the bios clear The column position and let's just look see what the column position is The column position is zero still load column position back in Compare it with the value at 10 which is 16 That was where we started zero one two three four five six seven eight nine ten 11 12 13 14 15 16 Okay Start column position is correct. Something we've done is reset column position in here I don't know what I'll be probably calling uh The wrong thing Actually we want to leave that because that's used by the startup code. Anyway, um Okay, so we should now print spaces So we print a space There we go cursor has moved on one increment the column count and continue and the column count is Yeah, I think this is actually going to print the right number of spaces So let's break at five and continue Right, where's the cursor cursor is in the right place Okay So now we are We are going to print seven characters. I hope but We actually want to start at one not zero Because so this is going to actually print garbage at the beginning But it should at least print some characters. So let's give this a try So a is seven that's the length of our buffer We're going to print this and it's incorrect So we increment the column position and the count Go back to the loop And continue So this should be our first character It's a 10. Why is it a 10? oh a 2047 Does not look like a valid Buffer pointer Um, I know what's happening We are not writing Yeah, we've done the same thing here We have not Um We're not actually writing anything to the buffer. So the buffer is still full of relocation bytes Or no If a is less If a is greater than or equal to The parameter if it's greater than equal to 32 Okay. Yeah, we are actually printing it here. Therefore, we must be advancing Column position and buffer pos But that's buffer max. We're always writing to the end of the buffer Which is presumably where this eight down here comes from And this should also be buffer pos Buffer pos because we want to only print up to where the cursor is Wow, this is garbage Okay, control r It did it it beeps, but it did it That's because I didn't advance this So we're printing the seven at the beginning of the line There we go So control r retypes It's if the terminal gets garbled Okay, anyway, uh, we've got one more to do which should be fairly straightforward Which is control u and u is 85 64 is 21 Yeah, really we should just be jumping to the To the relevant code and then jumping back again to the loop Rather than doing a call That would save us uh That would save us one byte because You would still this would be a jump that would be three bytes still Uh We would get rid of this three bytes But we would gain three bytes here instead of the rts So nothing there. So the only thing we're doing is losing the rts, which is one byte So it's really not worth it. Anyway, delete line. Delete line is actually similar to retype Code wise in that we print a new line We print spaces However We actually want to print one fewer space Do we Just trying to remember how cpm actually does it removes current line after new line They're just thinking what happens if we're at the beginning of the Uh Beginning of the line. It's not going to work. Sorry. Let me say that more clearly Uh, what I've seen cpm do when you do a control u is it new lines it indents One fewer character than retype did and it types a backslash indicates that you've cleared the line Uh, of course, if you're at the beginning of the line, that's not going to work anyway, um so column position Is in a if column position is less than starting column position Continue so if it's if column position is greater than or equal to no, no See, I'm hoping I can get my one different here somehow But I don't think I can because I want to I want to break if greater than or equal to For which I need to test two bits rather than one So actually I might as well just just Might as well just do it like this Uh If the column position is not zero print the backspace then print the backslash And then we lose all this code instead Resetting buffer paths back to one where it was originally One of those. Okay run that Control you Yes, that worked And the reason why it's type is printing a half sign here rather than Anything that we would that's a control r That's the control you the reason for the half is because in the bbc micros mode seven text mode you actually get the Uh, the teletext character set which has got interesting symbols like Uh You see Arrows half quarter and so on if I go back into mode three And I run cpm And now I do control you Now we get the backslash In fact, I now Oh, yeah and return works, which is nice I'm now actually unconvinced that backslash is the right character So I'll have to check that up But I believe the line editor works. There is actually one thing I need to do Which is? I want to print the um Print the string Which is more annoying than it sounds. Uh, let's this has to go up here so lda So this should be the length of the string and compare with The maximum length of the buffer Break if they're equal load the um Load the byte print it increment the count and New line so Now I type something and press return That beep means that we have done this wrong once again And in fact, we don't want to check for equality here Because we do want to print the last one. We only want to break We only want to break out if count is greater than the buffer length. So we want to We want carry set but z not set So we do it Yeah, that will do This is just test code. I can't be bothered making it small Okay, that wasn't right So this should be Loading the value Yeah, this should be correct Then we increment Let me go around again Sadly our bedos entry points due to the way they work cannot preserve registers The moss entry points do preserve registers. It's so much easier to work with Are we correctly setting the value After a loop buffer pause Decrement by one Stick it in the first byte Looks okay. Okay, break one f o four So this should break In the bedos except it didn't Presumably because we want to break at two oh oh four There we go We've just used another page so No, I wanted to break at two Oh seven That's better Two oh four is the wrong address. That was where the bedos entry point was So low print the banner done our buffer is in two zero seven zero So Read a line Okay So let's see what we got Two zero seven zero And we see There are indeed seven bytes And a seven at the beginning of the line So yeah, that is doing everything just right So print a new line Now we start counting Oh, interesting. There isn't a zero page form of ldy That makes some of my code rather less efficient And there isn't there is one for Wait, there is one for ldy and it knows it's in zero page. Why is that not done the right thing? odd odd Anyway, um, okay, you get the first byte. Why is now one? Load it There we go five three print it increment count I stepped when I should have nexted Okay Yes, I have completely completely mangled that step, but at least we can go through it again Okay Type something There should be four New line That's a character print increment jump Go through again for the next one increment load character it is print increment Jump did I type x twice? I did xxdv increment load a character 4 4 print Jump Last one we got a 4 4 again That's wrong xxdv it should be Oh, I haven't loaded it yet. That's why there we go. Okay print jump load So this comparison should fail carry is set uh wait Zero is not set So what is in one nine one nine contains a four 2070 contains a four Okay, good right that works Took long enough, but that works So Okay, well that is kind of where I expected to get this time though. I was hoping to do a little bit of actual ccp stuff uh next time we will print a prompt and start parsing the command line Which is annoying It's the ccp's job to parse file names into fcb's Which is kind of grim, but this was kind of grim too. So I suppose Now I'm used to it. Let's just take a quick look how big my bios is My vdos is rather 2k Hmm There are some strings Just see how much relocation there is Quite a lot of relocation actually We are eight five Six no seven minus Probably here Call that 63 Yeah, we have a nearly a nearly 400 bytes of relocation So it's not quite as bad as it looks still quite bad that line editor was a surprising amount of code um When I'm not talking on the microphone I might try and Clean it up a little Yeah Okay So that's that then see you next time