|
Post by gsteemso on Nov 29, 2014 1:48:18 GMT
I’ve been thinking about this some more, and some of the points people have raised make a lot of sense. In no particular order, some observations:
(1) The “same binaries on C64 as on C128” thing, I now realize, only works if you intentionally ignore (i.e., refrain from using) many of the 128’s features. Realistically, a proper text processor for actual productive use is probably going to need the VDC anyway, so I’m now back to thinking in 128-specific terms.
(2) The “able to run existing software” thing is a red herring. The (for lack of a better term) “standard” way to run really large or elaborate Commodore programs one after another is to reset the machine in between them, because they usually bypass the [run/stop]-[restore] key combination, so nothing I implement is going to be clunkier than that. Plus, it is inherent in developing the new system that it be capable of things (and thus require other things) that do not currently exist. New software is inevitable. For stuff that already exists, just run it the traditional way.
(3) One drawback to the Commodore DOS is that, with limited exceptions, there is no way to access the middle or end of a file save by first reading through all the stuff that comes before it. User files can be designed to get around that but require manual disk-block management, which can be destroyed by validating the disk. Relative files only work with a fixed record size, and cannot contain arbitrary data.
GEOS improved matters slightly by introducing the VLIR file structure. Basically it expands the concept of a sequential file into the concept of a bundle of sequential files. It has a lot in common with the Mac HFS idea of file forks, except the forks are not named and the structure efficiently accommodates up to 127 of them instead of just two. I think of this as “VLIR 1,” because of the “File Structure” flag stored in the file’s directory entry which always has this value.
An obvious improvement I could invent is “VLIR 2” files, which are basically an extension of VLIR to allow convenient use of and random access to very large documents. The “File Structure” flags in the directory entry and GEOS info sector would be set to $02 instead of $01.
Recall that original, VLIR 1 files are basically an adaptation of a standard sequential file, allowing up to 127 sequential-file “forks” (“records” in GEOS terminology, which is confusing enough when involving relative files in the conversation that I have opted to ignore the precedent). This limit is inconvenient because no facility is provided for random access within a fork, thus influencing developers to use the forks directly instead of using structures within them — and while few applications would need more than three or four forks if each contained a complete set of data, even using all 127 does not allow enough individual data structures for a large file.
VLIR 2 files are to REL files as VLIR 1 files are to SEQ files. Basically, a standard REL-type side-sector structure is constructed and stored for each VLIR-fork chain, including a one-block “hyper side sector” which gives the track and sector of the first side sector (1541/1571) or of the super side sector (1581 and up) for each VLIR-fork chain; if a given entry is unused it is set to a 16-bit zero value. Since the usual directory entry location that would point to the side-sector structure in a real REL file is instead used to point to the info sector, the hyper side sector is stored as block two of the info sector’s chain. There is no notion of “record size,” as there would be with a real REL file. REL files work by being able to tell how many blocks into the data to start looking for a given record, and a VLIR 2 fork works the same way; assuming you know the numeric index into the file of whatever you’re after, dividing by the 254-byte block size will always tell you what sector to look up.
(4) Returning to the target-platform question for a moment, I also cannot help observing that there are a much wider selection of special keys to be had on a C128 than on a C64. If I am to have special hot-key combinations to switch back and forth between the command-line focus and the GUI focus, it is made much more practical with the wider key selection on a C128 keyboard.
(5) The GUI, as has been pointed out, doesn’t work so well at 1 MHz. It’s just too much for a stock machine to do useful work and make it look pretty through pixmap manipulation at the same time. This means that, except for special purposes, a text-mode “pseudo-GUI” is as close as I’m going to get while still having it be useable. Happily, the 80-column screen is EXTREMELY customizable. There are tricks to make stuff look fancier without doing a huge amount of calculation all the time.
|
|
|
Post by gsteemso on Nov 12, 2014 22:54:29 GMT
I'm owner of Comet64, but really when I tried to be online, never, really never it was succesfull. I have it only connected to my DCR... That would be because the Comet relies on a special program called V1541 being run to modify the Kernal. That program only works in 64 mode.
|
|
|
Post by gsteemso on Nov 8, 2014 22:09:28 GMT
Several years ago, when the only licensed distributor of JD was Maurice Randall and the official version was therefore unobtainium, I bought bootleg copies for several of my machines from a helpful fellow on Lemon 64. Unfortunately, the copy in my 128 must have been burnt from a corrupt image, for some aspects of it are not working at all. Has anyone else encountered this sort of problem?
I’m giving serious thought to developing my own custom ROMset based on JD. Provided I buy a real copy and do not distribute anything, there shouldn’t be any legal issues AIUI. The big hurdle is of course finding time to do it. I once asked this question over on The Forum That Vanished and didn’t get much response, but if you could alter your 128’s behaviour or fix ROM bugs/oversights, what would you change? The fellow who extended the KEY function over in the Programming subforum is on the right track, and I recall someone else fiddled his ROM to disable the drive 8 autoboot on power-on, so what else is there? At the extreme end of the range we have BASIC 8; we probably don’t need to go to that length, but it illustrates the possibilities.
|
|
|
Post by gsteemso on Nov 5, 2014 23:26:19 GMT
I hadn’t heard of DOSShell before your post. I’ll look that up.
An “interstitial” type of OS that sits between BASIC and a regular Commodore program suffers from the rather severe problem that all but the most trivial such regular programs expect to have access to every scrap of the machine, leaving no place for the interposed shell to hide. That’s why you can launch a BASIC program from GEOS but you have to reload GEOS from scratch afterwards. Otherwise, not a bad idea.
I must point out that one reason for writing a new OS is to make services available that existing programs do not have access to. Obviously, taking advantage of such services will need new software.
|
|
|
Post by gsteemso on Nov 2, 2014 16:10:02 GMT
I agree with you about multitasking, but only up to a point. I think that thread support allows much more natural program structure in some cases, which is a form of lightweight multitasking. It is annoying to be writing something in one document and have to exit the editing session in order to check something else, so at least a small degree of actual multiprogramming is desirable too. Also, of course, interrupt handling is a form of multitasking, how much so depending on design choices.
On the other hand, we are dealing with a 1MHz machine here. Context switches are expensive. I’d say as a practical limit no more than two to four programs, each having up to, say, 4-8 internal threads would make sense as a limit. Nested unitasking à la Craig Bruce’s ACE should be ample for a lot of things, and having background processes be suspended entirely until they regain the foreground would make sense except for certain types of UI widgets, like alarm clocks and the like.
|
|
|
Post by gsteemso on Nov 2, 2014 16:02:41 GMT
I am embarrassed to say this, but I have never actually seen someone invoke the command line on an Amiga. (I had an Amiga 1000 for a short time, years ago, but never acquired a boot disk or a keyboard for it, so I can’t claim much experience.) What flavour of integration does the command line have with the GUI? Can you have both active at the same time such that actions in the GUI view of the filesystem define the target of the command line, and vice versa? That use case is one of the driving factors behind my UI ideas.
|
|
|
Post by gsteemso on Nov 2, 2014 5:38:13 GMT
All right. I was, in the back of my head, kind of hoping there would be more opinions or other discussion brought forward, but I guess it’s kind of hard to have an opinion on stuff no one’s really described yet.
There are a large number of notional axes along which to plot the position of an alternate OS for Commodores. They range from ostensibly simple considerations of how hardware-specific to make the thing (supporting both C64s and C128s with the same program binaries is a great idea in theory, but makes it very hard to really take advantage of the more advanced underpinnings of the C128 hardware and Kernal without crippling the programming environment on an unexpanded C64), through to the really abstract stuff like what sort of workflow it’s designed to support (user-port homebrew device control? Serial interfacing à la LUnix? WYSIWYG desktop publishing like GEOS?) and what sort of user interface experience you want.
I should expand a bit on that last point. Command-line UNIX has historically been very successful simply because it offered a good compromise between ubiquity, simplicity of UI design, and power of its command expressions… but I personally do not have a good enough memory to use it without having to keep referring back to the man pages for things like the exact syntax of command-line options, even for functions I use quite often. I can’t really say that’s the sort of user experience I want to aim for, though the example of the old A/UX “Commando” utility shows that it can be greatly mitigated (albeit with a lot of effort).
Conversely, the original Mac OS (actually a brutally reduced reincarnation of the Lisa Office System) was excellent (well, for its time anyway) at being straightforward for new users, but the decision to completely omit any sort of command line (or other system with similar functionality, like the Mac OS X Automator could be in modern times if its effectiveness were improved to match its potential) basically killed any initial hope of its effective use by power users; even Apple’s own engineers found it necessary to write a standalone command shell to get real programming done on a Mac. (It was called Macintosh Programmer’s Workbench (MPW), and at one point sold for about a thousand dollars to commercial developers. Of course, much later on, they eventually twigged to the fact that making it inaccessible to write software for their platform wasn’t doing them any favours, and gave it away free online.)
These experiences are illuminating because they make clear some of the approaches I don’t want to take. But I digress; I was listing the dimensions along which an alternate OS for Commodores may be laid out or measured. We have the whole can of worms labelled “compatibility,” in aspects of both hardware and software — for example, should we try to support the execution of programs designed for other environments, such as the popular but rather limiting GEOS, or André Fachat’s admirable cross-OS lib6502? What about all the myriad incompatible disk-drive-type devices or flavours of RAM expansion?
Then we have the issue of supporting end-user programming, or at least scripting. The stock Commodore BASIC-in-ROM doesn’t really support much else, and systems like PROMAL are almost entirely designed around it as well. Obviously, making it difficult or inconvenient would be a huge step backwards and encourage people not to use the new OS. So, we want something at least as powerful as PROMAL, and ideally even more so like in a UNIX shell; and we want it easy enough to write that you don’t have obscure punctuation errors hindering your progress for an hour while you try to track it down. Basically, something like an unholy fusion of Perl (for power) and Lua (for textual simplicity) would be a good place to start. A really powerful default command-line editor would be an obvious feature to require as well.
I suppose, having mentioned all of these dimensions of the OS design space (there are many others I can’t recall just now, too!), I should mention my preferred answers to the design questions they pose, and give some explanations as to why I settled on them.
The first thing I mentioned above was, “What hardware should it run on?” Initially my thought was to make it C128-specific, as having a minimum of 144 KiB of RAM available is far preferable to having 64 KiB or less, as all the other commonly-encountered Commodore 8-bit machines do. (I know things like the B-series, the SuperPET, and the CBM 8x96 can do better than 64 KiB, but they are relatively rare—I certainly don’t own any of them!—and it is very difficult to design to a common subset of them and the C128, especially given the others’ lack of a bitmapped display mode.) However, after recalling just how pleased I was on encountering Craig Bruce’s ACE and the notion of having a software collection that honestly didn’t care whether I ran it on a C64 or a C128, I’ve come to the opinion that I should transparently support at least those two platforms as a minimum. Others would be nice in theory, but not having a VIC-II/IIe available would severely hamper UI portability to any other device, I think (not in terms of the OS itself, but it would make it very hard to write things like cross-CBM-platform games, for example). I’d love to be proven wrong about that—anyone?
Next we have, “What sort of workflow is it to support?” This one, at least, I am quite clear on. My original motivation for writing my own OS was that I wanted a GUI text editor suitable for writing stories, but I didn’t want my creative process (such as it is) to be easily interruptible by things like IRC, email or instant messaging. A custom GEOS program was the obvious initial vehicle to provide this service, but alas, GEOS is pretty much incapable of properly supporting a 400+-raster VDC screen, such as would be most useful for serious word processing; 8-bit Y-coördinates (that can’t exceed 255) are pretty much set in stone throughout that OS. (Literally, if we consider that computer chips are made of silicon.) So, if I had to rewrite pretty much everything to do the job and knew for a fact that I had a C128 available to do it with, I might as well completely skip over a lot of aspects of GEOS that were—for example—compromises due to the limited capacity of a C64, or required for things like printers that very few people make extensive use of at home any more. Ergo, a new OS. So, to state it plainly: I want powerful facilities to create, edit, transform (e.g. by running some sort of custom programming on), and transmit (to the Internet, ideally) text-based documents of various types. A sharp eye will note that these steps to the publication of a story or article look quite startlingly congruent to the steps for compiling and then distributing a new computer program, which after all starts off as linear text in almost all programming paradigms. Ta-daa!
Third: “What sort of UI should it have?” This one is extremely subjective. After extensively reading up on OS and UI design, I came to the conclusion that I wanted the ease-of-use of a spatial GUI, and I wanted the power of a command line, and I wanted them so tightly integrated that neither would be a “subshell” (for lack of a better word) of the other. What am I talking about, you ask? Well, Windows 3.x had its GUI as just a rather limited program that executed within the DOS command line environment. The classic Mac OS required a separate, non-OS program to be run if you wanted a command line, and even then it was barely integrated with the rest of the OS at all unless you did a lot of support work yourself. Plainly, neither of these was especially useful for serious development; but the modern approach, which basically has a GUI that you get a command line in by running a much-better-integrated but still separate program, is not really all that much better, IMO. Drag-and-Drop and copy/paste functions can mitigate the disconnect somewhat, but you basically still have two completely unrelated access methods into the guts of the OS that almost completely fail to interact, much like oil and vinegar.
There is another way, and you’ve seen it before. Around 30 years ago, the microcomputer-assisted spreadsheet program was born, and either at that time or shortly thereafter, some bright spark figured out that having an editing area for the current cell that was disconnected from its displayed location on the virtual spreadsheet made a lot of things easier, especially in the days of sharply limited screen size. (That last point seems strangely relevant to programming on an 8-bit Commodore machine, doesn’t it? What a coincidence.) So, if you have suitable user interface functionality to allow manipulation of both a visual display and a command line, you can have them both active at once, switching the keyboard focus back and forth at the tap of a key or the click of a mouse button. If you’re doing something purely visual like playing a game, the command line can slide off the screen until you or your program summons it again. If you’re constructing a lengthy command line in the “outermost” shell environment, the area occupied by it on screen can grow as necessary—even with word-wrap and so forth, if you want it. Strangely, I have never seen an OS that used this approach (which, lacking a better name for, I have dubbed the “Hybrid Paradigm Interface” or HPI, by analogy to CLI and GUI), and even many spreadsheets have rather poor integration betwixt the two modes, which seems quite pathetic after 30 years of continuous development.
Fourth and fifth, “What software should it be compatible with?” and “What hardware should it be compatible with?” The former is pretty straightforward; almost no existing software fits well with the HPI model, but we could fake it if there’s a reason to. The existence and surprisingly wide adoption of lib6502 seems like a good reason to, IMO, but I don’t think there are many others I can say the same for. Native CBM programs, for example (whether assembled or in BASIC), are usually extremely platform-dependent, and also tend to consume resources that an alternative OS would normally reserve to itself. That said, the GEOS disk format has possibilities. More on that in a future post. As to the question of hardware, that one’s a no-brainer; if I can contrive a way to test with a given bit of gear, I should make it work! Memo to self, acquire a cartridge-port expander.
Sixth, “How should it support user programming?” There are a heck of a lot of ways to answer that one. It’s really two questions in one; namely, “What programming paradigm and language(s) should it be designed for?” and “What sort of editor should it have?” Even Commodore vaguely knew the editor was important, not that they actually put that much effort into it until the C128 came about.
The question about programming paradigms has as many answers as there are programmers in the world, and some of them even agree with one another. I’m inclined to postpone discussion of that one until I hear some arguments one way or another, though as a default position to be swayed from, I think a more user-tolerant version of a UNIX shell would be a good place to start.
The other question, about the nature of the editor, is pretty straightforward; basically, I want it as user-friendly as the TOPS-20 excutive (which I have seen described as “A great improvement over its successors”) and to have at least as much power, flexibility, and command support as the well-known Mac text editor, BBEdit (more accurately, its free cousin TextWrangler; I haven’t been able to afford the actual BBEdit since the 68K Mac days). Among other things, this implies multiple open editing/command sessions at a time, and the ability to scroll up to look at stuff that has already gone past. It also implies a variety of powerful hotkeys for transforming the text and moving around in it, as well as at least rudimentary extended character set (e.g. Unicode) support. (I was thinking the various Latin, math and punctuation blocks would be enough; maybe Greek and Cyrillic too, if there was spare capacity—if nothing else, Western Latin plus one user-selectable other set of blocks at a time would work, such as African or Vietnamese Latin, Korean combining jamo or Japanese kana, though I’d imagine actual kanji etc would be infeasible without both a SuperCPU and a very large storage drive. I, like most, don’t own a SuperCPU, and my µIEC is inoperative.)
So… Thoughts?
|
|
|
Post by gsteemso on Nov 1, 2014 4:14:21 GMT
We all know about CP/M and GEOS. I believe that’s almost entirely because those are the ones that you could buy bundled with your Commodore. Of course, we also know about Miro’s new ACE OS that hasn’t reached its initial release yet, but that is far from all there is to discuss in this section of the forum. There were a large number of other OSes made for Commodore machines “back in the day,” most of them amateur efforts, but since most people had no realistic way of getting a copy at the time (and the commercial ones all cost far too much besides), none of them ever really caught on. Probably the most complete and useful ones, at least that ran natively in 128 mode, were (1) the original ACE OS by Craig Bruce and (2) LUnix by Daniel Dallman et al. Release #16 of ACE is still available on Craig Bruce’s website at www.csbruce.com/~csbruce/cbm/ace/. I’ve run it, it works well, but apart from the Zed text editor and maybe the native assembler that runs on it, there is little benefit to be had in doing so, because no one else seems to have written anything for it. Still, some of the underlying technologies are very impressive, even if few people seem to have made any use of them. I especially like the way binaries for that OS run unmodified on both C64 and C128. I wish more software systems allowed that. LUnix (the “Little UNIX”—see lng.sourceforge.net/) was more recently updated and is very capable in terms of RS232 communications, but has apparently stalled at version 0.21. I haven’t tried it yet, though there does seem to have been a little more software written for it than there was for ACE. Its home page is silent on whether the same program binaries will run under both the 64 and the 128 versions. There were about twice or thrice as many of these alternate OSes available for the C64 as there were for any other Commodore 8-bitter, presumably due mostly to the 64 simply outnumbering all the others—all the others combined, as I understand it, though I don’t have any hard numbers on hand to back that up. Notable examples include He-Who-Must-Not-Be-Named’s successor to GEOS, Wheels, which is supposed to have been pretty good from what I hear but required RAM expansion… pretty much a non-starter for most people, due to how hard it is to get hold of either a genuine REU or one of the modern imitations. There were several others, of course, though I am only aware of one such that was relatively complete: PROMAL. ShadowM has an entire page devoted to PROMAL over at www.lyonlabs.org/commodore/onrequest/PROMAL/index.html. It was a remarkable achievement for its time, but unfortunately only runs in 64 mode, and needs some minor tweaking to play well with multiple serial devices and/or JiffyDOS. As can be seen from the links on ShadowM’s site, jbevren has been rooting around in the guts of PROMAL to see how it works, and discovered some very clever assembly-language programming techniques in use. I harbour the faint hope that this exploratory surgery will, in time, allow PROMAL to be run on a C128 in 128 mode—even though I’ve only thus far managed to make it run in VICE and not on real hardware, I find it a very user- and programmer-friendly OS. I imagine those who have seen me mention it before will be heartily sick of its vaporous nature, but I will close with mention of my own alternate OS project, designed entirely to aid writers (whether of code or of prose). It doesn’t exist yet except as several long-winded and obnoxiously theoretical pages of notes, but I’ve had some (I think) original ideas on how to combine graphical and command-line user interface design into a harmonious whole. Would anyone out there care at all to hear more about it? I’ve not had any time to devote to it lately and it is still classified in my master project index as an “Impractical Pipe Dream” that I do not expect to ever achieve, but that could change if I start seriously bouncing ideas off people.
|
|
|
Post by gsteemso on Oct 25, 2014 4:31:45 GMT
Hi Miro, I've seen on your website that you still plan to support Dallas Smartwatch (DS1216E) as a solution for RTC: have you already done some work for it? I own one (bought new from DigiKey), I plugged it into the internal function rom socket U36 and wrote some (ugly) assembly code to support reading and setting time, but It never worked; I don't know if I'm doing something wrong (which could certainly be the case due to my limited skill with 8502 assembler) or if the IC just doesn't work. I can think of two sources of trouble there—one each hard- and software. In hardware, those things have an internal battery. After 25 years+ they are no good any more. Fixable? Derned if I know. In software, AFAIK the function ROM socket doesn’t have a Read/Write signal connected. Makes it tricky to write to it. If anyone out there can say I am mistaken in that latter point I would appreciate a correction.
|
|
|
Post by gsteemso on Oct 19, 2014 4:38:06 GMT
Okay, I just had to do this properly now that I’ve had some time to consider it. I believe the assembly code to implement my two representative algorithms would look vaguely like this…
Algorithm the first:
INIT1: ; Here we set up things like what bank we're using (to keep it simple, ; we'll say RAM 0 with Kernal ROM in context, so bank 15), and what ; serial bus unit and what drive/partition we are accessing. We will ; keep the latter in locations THE_UNIT and THE_DRIVE, respectively. ; THE_DRIVE might more usefully be kept as a one- to three-character ; string, since it only ever gets used in the command string sent to ; THE_UNIT. Do as you like with that one. ; We will need a working storage location in RAM for intermediate ; results, such as the lengths of filename fragments. Call it TEMP. ; We will set two constants WORK_LFN and WORK_CHANNEL to make the code ; more readable. ; We will also set aside two RAM locations called ACE_FILE_TYPE and ; ACE_FILE_SUBTYPE for the results that we're doing all this for.
LOOP1: ; Assume this part does the initial work of loading and parsing a ; directory entry. Treat the directory entry as loaded into a 30-byte ; buffer at DIR_BUFFER. Then the filename is at DIR_BUFFER+3 through ; DIR_BUFFER+18. The following bit of code determines how long the ; filename actually is within that buffer: LDA #$A0 ; Shifted space char (bit 7 set): filename padding LDX #16 ; Filename length counter (local loop variable) - CMP DIR_BUFFER+2,X ; Is current character just padding? BNE + ; If we didn't find padding, break out of loop DEX ; We found padding, index backwards within name BNE - ; If we haven't run out of filename, loop BEQ [error handler -- we ran out of name] + STX TEMP
; Now assume we have copied THE_DRIVE as a string to the start of the ; 22-byte FILENAME_BUFFER (followed by a colon), with the offset to ; the 1st unused byte in that buffer left in index register Y (it ; will be 2, 3 or 4). Then we only need to do this: LDX #0 - INX LDA DIR_BUFFER+2,X STA FILENAME_BUFFER,Y INY CPX TEMP BNE - ; if we haven't run out of filename, loop LDA #',' STA FILENAME_BUFFER,Y INY LDA #'R' STA FILENAME_BUFFER,Y INY
; At this point Y contains the length of the filename we'll actually be ; sending to THE_UNIT: STY TEMP
; Set up our logical file: LDA #WORK_LFN LDX THE_UNIT LDY #WORK_CHANNEL JSR JSETLFS ; $FFBA
; We'll be using Bank 15 exclusively, so we will have already called ; SETBNK with that value once in the initialization code... and so we ; will not need to keep calling it here in the loop.
; Point to the file name: LDA TEMP ; Length of filename goes in A LDX <FILENAME_BUFFER ; LSB of address goes in X LDY >FILENAME_BUFFER ; MSB of address goes in Y JSR JSETNAM ; $FFBD
; Tell the Kernal to open a logical file: JSR JOPEN ; $FFC0 BCS [file error handling routine] LDA $90 ; Check the serial status flag is clear BNE [serial error handling routine]
LDX #WORK_LFN JSR JCHKIN ; Triggers the actual OPEN command on the serial bus ; Everything before this point is just bookkeeping to ; keep the Kernal from getting confused.
LDA $90 ; Check the serial status flag is clear BNE [serial error handling routine]
; Here's where we actually get our target data: JSR JACPTR ; Get the 1st data byte (the Ace file subtype (type?)) LDA $90 ; Check the serial status flag is clear BNE [serial error handling routine] STA ACE_FILE_SUBTYPE JSR JACPTR ; Get the 2nd data byte (the Ace file type (subtype?)) LDA $90 ; Check the serial status flag is clear BNE [serial error handling routine] STA ACE_FILE_TYPE
; OK, got what we wanted, abort the read: JSR JUNTLK ; $FFAB LDA #WORK_LFN JSR JCLOSE ; $FFC3
; We've finished with this directory entry. Go do whatever it is we're ; doing with the filetype data and then loop: JSR [whatever we're doing with the file type and subtype] JMP LOOP1
Algorithm the second (note that my BASIC version above forgot to set the buffer pointer, though it's faster to just read and discard the two-byte track/sector link at the beginning):
BY2STR: ; This is a utility function. If I had a real assembler it would be a ; macro. It takes the value in A, converts it to decimal, and outputs ; the string equivalent to COMMAND_BUFFER,Y. Because an unsigned ; value is never negative, the first character output is always a ; space. ; The routine both expects and leaves Y pointing at the next unused ; byte in COMMAND_BUFFER. ; Uses one byte on the stack beyond the return address. LDX #' ' STX COMMAND_BUFFER,Y INY CMP #100 ; How many digits? BCS + ; If 3, skip ahead to hundreds handling CMP #10 BCS ++ ; If 2, skip further ahead to tens handling BCC +++ ; If 1, skip to ones handling + LDX #0 ; This will be our hundreds digit - SBC #100 ; Carry is already set at this point INX CMP #100 ; Are we done counting hundreds yet? BCS - ; If not, loop PHA TXA ORA #'0' ; If so, convert to a digit character STA COMMAND_BUFFER,Y INY ; And save the digit PLA ++ LDX #0 ; This will be our tens digit CMP #10 ; Are there any tens? BCC + ; If not, skip ahead - SBC #10 ; Carry is already set at this point INX CMP #10 ; Are we done counting tens yet? BCS - ; If not, loop + PHA TXA ORA #'0' ; If so, convert to a digit character STA COMMAND_BUFFER,Y INY ; And save the digit PLA +++ LDX #0 ; This will be our ones digit CMP #1 ; Are there any ones? BCC + ; If not, skip ahead - SBC #1 ; Carry is already set at this point INX CMP #1 ; Are we done counting tens yet? BCS - ; If not, loop + TXA ORA #'0' ; If so, convert to a digit character STA COMMAND_BUFFER,Y INY ; And save the digit RTS
INIT2: ; Once again we will assume and set bank 15, and set up what serial bus ; unit and what drive/partition we are accessing. We will again keep ; the latter in locations THE_UNIT and THE_DRIVE, respectively. ; Again, THE_DRIVE might more usefully be kept as a one- to three- ; character string, since it only ever gets used in the command ; string sent to THE_UNIT. ; We will set four constants COMMAND_LFN, COMMAND_CHANNEL=15, WORK_LFN ; and WORK_CHANNEL to make the code more readable. ; We will construct our disk commands in COMMAND_BUFFER and use memory ; location INDEX for storage between loops. ; We will also set aside two locations called ACE_FILE_TYPE and ; ACE_FILE_SUBTYPE for the results that we're doing all this for.
; Set up the command channel logical file: LDA #COMMAND_LFN LDX THE_UNIT LDY #COMMAND_CHANNEL JSR JSETLFS ; $FFBA
; We already SETBNK'd with both values=15
; set a null filename: LDA #0 TAX TAY JSR JSETNAM ; $FFBD
; Tell the Kernal to open a logical file: JSR JOPEN ; $FFC0 BCS [file error handling routine] LDA $90 ; Check the serial status flag is clear BNE [serial error handling routine]
; Set up the data buffer logical file: LDA #WORK_LFN LDX THE_UNIT LDY #WORK_CHANNEL JSR JSETLFS ; $FFBA
; We already SETBNK'd with both values=15
; set a one-character filename '#': LDA #'#' STA COMMAND_BUFFER LDA #1 ; Length of string goes in A LDX <COMMAND_BUFFER ; LSB of address goes in X LDY >COMMAND_BUFFER ; MSB of address goes in Y JSR JSETNAM ; $FFBD
; Tell the Kernal to open a logical file: JSR JOPEN ; $FFC0 BCS [file error handling routine] LDA $90 ; Check the serial status flag is clear BNE [serial error handling routine]
; Construct the invariant part of the command string: LDA #'U' STA COMMAND_BUFFER LDA #'1' STA COMMAND_BUFFER+1 LDA #WORK_CHANNEL LDY #2 JSR BY2STR LDA THE_DRIVE JSR BY2STR STY INDEX ; Stash the current string position for next time ; through the loop
LOOP2: ; Assume this part does the initial work of loading and parsing a ; directory entry. (If we've finished them all then JMP to CLEANUP2.) ; Treat the directory entry as loaded into a 30-byte buffer at ; DIR_BUFFER. Then the first block of the file is at track ; DIR_BUFFER+1 and sector DIR_BUFFER+2.
; Now we finish building the DOS command string in COMMAND_BUFFER: LDA DIR_BUFFER+1 JSR BY2STR LDA DIR_BUFFER+2 JSR BY2STR LDA #13 ; end the command string with a carriage return ; -- can't recall if this is important or not STA COMMAND_BUFFER,Y INY ; At this point Y = length of the command string
; Set the command-channel file as our output destination: LDX #COMMAND_LFN JSR JCKOUT ; $FFC9 BCS [file error handling routine] LDA $90 ; Check the serial status flag is clear BNE [serial error handling routine]
; Actually write the command string: LDX #0 ; loop counter variable INY ; We want to start with Y = (length + 1) - LDA COMMAND_BUFFER,X JSR JCIOUT ; $FFA8 LDA $90 ; Check the serial status flag is clear BNE [serial error handling routine] INX ; Bump the DEY ; counters BNE - ; When Y=0, we have run out of command string
; OK, we said our piece, we can unlisten the bus now: JSR JUNLSN ; $FFAE
; Set the buffer file as our input source: LDX #WORK_LFN JSR JCHKIN ; $FFC6 BCS [file error handling routine] LDA $90 ; Check the serial status flag is clear BNE [serial error handling routine]
; Read and discard the two bytes at the start of the buffer (it's the ; track/sector link to the next block, not part of the file data): JSR JACPTR ; $FFA5 -- Get, ignore the track byte LDA $90 ; Check the serial status flag is clear BNE [serial error handling routine] JSR JACPTR ; Get, ignore the sector byte LDA $90 ; Check the serial status flag is clear BNE [serial error handling routine]
; Here's where we actually get our target data: JSR JACPTR ; Get the 1st data byte (the Ace file subtype (type?)) LDX $90 ; Check the serial status flag is clear BNE [serial error handling routine] STA ACE_FILE_SUBTYPE JSR JACPTR ; Get the 2nd data byte (the Ace file type (subtype?)) LDX $90 ; Check the serial status flag is clear BNE [serial error handling routine] STA ACE_FILE_TYPE
; OK, got what we wanted, abort the read: JSR JUNTLK ; $FFAB
; We've finished with this directory entry. Go do whatever it is we're ; doing with the filetype data and then loop: JSR [whatever we're doing with the file type and subtype] LDY INDEX ; restore command-string position JMP LOOP2
CLEANUP2: ; At this point we would close the WORK_LFN, and possibly the ; COMMAND_LFN depending on what else we have left to do.
As I don’t have any idea what all of this would be hooked up to / embedded in, I can’t really test the two versions of the code for relative speed or efficiency. It does look like the one with the buffer channel is clunkier though. Darn.
|
|