; path.asm ; Putting a name together with the place another thing is in. ; ; DP0 = a path, DP1 = a name, DP2 = where the answer goes, B = how much room, counting ; the zero on the end ; CALL pathBeside Q is zero if the whole of it fitted ; ; Written by Anachronaut ; ; ---- What this is for ---- ; ; A program asks the system where it came from - SWI osWhereAmI - and is handed the path it ; was loaded from. What it actually wants is the path of something NEXT TO that: its tune, ; its tiles, its saved state. This is that one step, and it is a library rather than a ; service because it is arithmetic on two strings and touches nothing the system owns. ; ; That split is the whole reason osWhereAmI hands back a path instead of opening files on a ; program's behalf. A service that opened a file relative to the program would need a twin ; for every file operation there is; a path composes with all of them, and the joining ; happens once, here, on a machine that has no string library to do it in each program. ; ; ---- Everything up to the last separator ---- ; ; The place a thing is in is everything up to and INCLUDING the last separator in its path, ; so joining is a copy and not a search backwards from the end. A path with no separator in ; it names something in the working directory, and the answer is then the name on its own - ; which means exactly the same thing, in the same place, and needs no special case. ; ; /Packages/app.Lander/Lander + splash.tune = /Packages/app.Lander/splash.tune ; /Lander.sbx + splash.tune = /splash.tune ; Lander.sbx + splash.tune = splash.tune ; ; ---- The room is counted once, in one place ---- ; ; Both halves go through pathPut, which counts the room down and always keeps a byte back ; for the zero. So an answer that did not fit is still a STRING, endable and printable, and ; a caller that ignores Q gets a short path rather than a walk off the end of its buffer. ; It gets a wrong answer, which is why Q exists - but not a broken machine. ; ; The answer is built through a stored pointer rather than DP2, because a CALL puts DP0 to ; DP2 back the way it found them and pathPut would otherwise write the same byte every time. #Program pathBeside: SETD.3 PathPut STD.2.3 SETD.3 PathRoom STB.3 ; ---- How much of the path is the place it is in ---- ; ; Counted rather than pointed at, because what is wanted is a NUMBER OF BYTES TO COPY and ; a pointer would have to be turned into one. The count is set afresh at every separator, ; so what it holds at the end is the last one - which is the one that matters. PSHD.0 ; The front of the path, to come back to. RSTA SETD.3 PathCut STA.3 SETD.3 PathAt STA.3 pathScan: LDA.0 BRA pathScanned INIB 0x2F CCF SUB BNQ pathScanStep ; A separator, so everything up to and including it is the place. SETD.3 PathAt LDA.3 INCA SETD.3 PathCut STA.3 pathScanStep: SETD.3 PathAt LDA.3 INCA STA.3 INCD.0 BRI pathScan pathScanned: POPD.0 SETD.3 PathCut LDA.3 SETD.3 PathLeft STA.3 pathPlace: SETD.3 PathLeft LDA.3 BRA pathName ; All of the place is written, or there was none of it. DECA STA.3 LDA.0 CALL pathPut BNQ pathNoRoom INCD.0 BRI pathPlace pathName: PSHD.1 POPD.0 pathNameChar: LDA.0 BRA pathMade CALL pathPut BNQ pathNoRoom INCD.0 BRI pathNameChar pathMade: CALL pathEnd RSTA RSTB CCF ADD ; Q is zero: the whole of it fitted. RET pathNoRoom: CALL pathEnd INIA 0x01 RSTB CCF ADD RET ; The zero that makes it a string. There is always room for it: pathPut refuses the byte ; that would have taken the last one. pathEnd: SETD.3 PathPut LDD.2.3 RSTA STA.2 RET ; A holds a character. Puts it where the answer has got to and steps that on. Q is one if ; there is no room for it. pathPut: SETD.3 PathHold STA.3 ; The character, across the pointer being fetched and put back. SETD.3 PathRoom LDB.3 DECB BRB pathPutFull ; Only the zero's worth left, so this byte cannot be written. STB.3 SETD.3 PathPut LDD.2.3 SETD.3 PathHold LDA.3 STA.2 INCD.2 SETD.3 PathPut STD.2.3 RSTA RSTB CCF ADD RET pathPutFull: INIA 0x01 RSTB CCF ADD RET #Data ; Where the answer has got to, and how much room is left in it. PathPut: 0x00 0x00 PathRoom: 0x00 ; How much of the path is the place it is in, how far the scan has got, and how much of the ; place is still to be written. PathCut: 0x00 PathAt: 0x00 PathLeft: 0x00 ; One character, across the fetching and putting back of the pointer it is written through. PathHold: 0x00