Just an idea: a CP/M alike OS for the 6502?
Just an idea: a CP/M alike OS for the 6502?
Hallo allemaal,
CP/M enabled a lot of people to run the same software on may different computers as long as they were equiped with a Z80 or Intel 8080. There are many 6502 (or equivalent) equiped computers around. Some of you are even building new ones. What would be nicer then building a new computer and having tons of software available right from the start?
Is this worth a discussion?
I'm awaiting your comment.
CP/M enabled a lot of people to run the same software on may different computers as long as they were equiped with a Z80 or Intel 8080. There are many 6502 (or equivalent) equiped computers around. Some of you are even building new ones. What would be nicer then building a new computer and having tons of software available right from the start?
Is this worth a discussion?
I'm awaiting your comment.
Code: Select all
___
/ __|__
/ / |_/ Groetjes, Ruud
\ \__|_\
\___| URL: www.baltissen.org
asmlang_6 wrote:
The Z80 and 8080 processors are 8 bits. That would make it easy to port to the 6502. If anyone could find the assembly source for CP/M for the 8080, I could probably port it.
The idea of this OS (a nice name, anyone?) is that it should run on various existing hardware and hardware yet to be build. CP/M requires a minimum of at least 16 KB AFAIK. 3.0 needs at least 48 KB. And my VIC-20 only has 5 KB on board.....
But CP/M needs the RAM to be able to load the OS from disk. So one goal can be to support ROM versions of the OS, either in the forms of ROMs that replace the original ones or ROMs that are added to system using a free socket (like the C= CBM's have) or a cartridge (C64, C128, VIC-20).
If a CP/M program wants to output a byte to the floppydisk, harddisk, videoscreen or whatever, it stores the byte somewhere and calls a vector. This vector then leads to the machine dependant part that does the wanted actions. What has to be done is to define all needed vectors. We can use CP/M as base but DOS has many more then CP/M and therefor is a better base to start with. Do we need all those vectors DOS is using? I don't know and in fact I don't care. The idea is to dreamup a mechanism that allows me to use various number of vectors. (OTOH, 65536 vectors should be enough IMHO)
But supporting a lot of vectors means a big OS, one may think. A text only computer (like the C= CBM 8032) doesn't need OS support for a GUI. IMHO it is just a matter using some directives that tell the assembler what parts to include or not. Another idea, load the needed part from disk (or whatever) execute it and discard it again (like DOS does).
CP/M has its own filesystem. Should we define our own one as well? Yes and no. No because, for example, I want to be able to play my C64 games under the new OS as well. In case of Commodore an extra problem is that it is not the computer but the drive that defines how and where data is stored on a disk. It is possible to define your own layout but IMHO it is not worth the trouble. Certainly if you know that, for example, a Acorn BBC or Electron is unable to read the floppies of a C= (and vica versa).
Yes, because we should be able to exchange data. My idea: most computers I know off have a RS-232 port. We can program the OS so that it treats this particular port as another drive. We connect a PC to this port that runs a program that emulates a (hard)disk using an image. And we need this Filesystem for this emulated disk.
Points to discuss:
- vectors
- filesystem
- handling of the available memory
- page swapping
- ???
Now you may shoot :)
Code: Select all
___
/ __|__
/ / |_/ Groetjes, Ruud
\ \__|_\
\___| URL: www.baltissen.org
Ruud wrote:
And a 6502 isn't a Z80. CP/M 3.0 is supports memory banking but it can only handle 15 extra banks of 32 KB and the way it is done doesn't cheer me up either, certainly if seen from the point of view of a 6502.
Quote:
The idea of this OS (a nice name, anyone?) is that it should run on various existing hardware and hardware yet to be build. CP/M requires a minimum of at least 16 KB AFAIK. 3.0 needs at least 48 KB. And my VIC-20 only has 5 KB on board.....
Quote:
If a CP/M program wants to output a byte to the floppydisk, harddisk, videoscreen or whatever, it stores the byte somewhere and calls a vector. This vector then leads to the machine dependant part that does the wanted actions. What has to be done is to define all needed vectors. We can use CP/M as base but DOS has many more then CP/M and therefor is a better base to start with.
* Fewer OS calls means it's smaller, and therefore more ROM friendly.
* Fewer OS calls and semantics means fewer bugs, and therefore, less ROM revisions.
* Fewer OS calls makes for a more flexible architecture, if the OS calls are orthogonal with respect to each other. For example, the OS called Plan-9 is able to do nearly EVERYTHING that it does using only open(), read(), write(), and close(). There are a few other system calls, but they're used far less often. Even graphics are handled this way.
Quote:
Do we need all those vectors DOS is using? I don't know and in fact I don't care. The idea is to dreamup a mechanism that allows me to use various number of vectors. (OTOH, 65536 vectors should be enough IMHO)
Code: Select all
; First, open the library, so that we can access it
; elsewhere.
lda #<libName
sta $00
lda #>libName
sta $01
lda #libVersion
sta $02
jsr SysOpenLibrary ; one of the few global OS calls
bcc couldNotOpenLibraryForSomeReason
lda libBase
sta myLibBase+1
lda libBase+1
sta myLibBase+2
; Now let's make a few calls to it.
... ; load parameters somehow here.
ldx #MYLIB_FUNC_1
jsr myLibBase
ldx #MYLIB_FUNC_2
jsr myLibBase
; Here's where we store the library "entry points", so to speak.
myLibBase:
jmp $0000
yourLibBase:
jmp $0000
...
Code: Select all
ORG LibraryLoadAddress
entryPoint:
jmp (myTable,X)
myTable:
dw func1
dw func2
dw func3
...etc...
Quote:
CP/M has its own filesystem. Should we define our own one as well?
Quote:
No because, for example, I want to be able to play my C64 games under the new OS as well. In case of Commodore an extra problem is that it is not the computer but the drive that defines how and where data is stored on a disk. It is possible to define your own layout but IMHO it is not worth the trouble.
The only thing that Commodore DID get right is the placement of the root directory blocks and the BAM on the center cylinder.
Quote:
- vectors
A better solution still might be instead to make use of message passing between multiple tasks in a (perhaps cooperatively) multitasking system, and build the core operating system as a microkernel.
However, the problem with this approach is that you're providing a leaky abstraction: you're trying to convince the programmer that his code more or less has ownership of the machine as a whole, and therefore, every program tends to be written as if it were initializing itself, running its own event loop, etc. This leads to *MASSIVE* code replication -- something a 6502 system can do without!
Instead, building an event-driven architecture is perhaps the best overall choice. Code written for the OS takes the form of a large collection of callbacks, which are invoked by the OS in response to certain stimuli. The benefits of this are many:
* A single, system-wide event queue and kernel dispatcher, which eliminates all the duplication from all the other programs designed to run under it.
* Can "multitask" without explicit support for multitasking. It can do this because the system-wide event queue can interleave events for multiple programs. The performance will be comparable to cooperative multitasking, without all the overhead of task switching. Sophisticated kernels can even profile how long it takes to handle a specific event handler, and can implement fairness algorithms based on this if necessary (probably only on a 65816, where enough memory can exist to support this). Kernels optimized for more sophisticated processors (e.g., a 65816, or an emulated 6502/65816 environment hosted on a more sophisticated processor) can provide real multitasking easily enough.
* 80% of all software today spend 80% of their time waiting for something to happen. Remember that back when Unix and VMS were invented, computers were built for batch-processing of work, not human interaction. Today, the situation is reversed. Therefore, it seems that optimizing the OS to support the most common occurance will make for a more space- and time-efficient OS architecture. GEOS/64 proved this quite nicely!
* Compute-heavy tasks can be supported by a number of mechanisms:
+ Submit an event for a single loop iteration to kick off the loop. The loop iteration handler then will, if necessary, submit another event for itself. Thus, the loop self-perpetuates until such time it is done (in which case it just doesn't re-issue its own event).
+ Register an Idle handler so that the OS periodically calls it while waiting for something to arrive in the event queue.
+ Support true multitasking of some sort, and run the compute-heavy tasks as background processes.
* Event-driven architectures can scale to multitasking or multiple processor architectures relatively easy. OS-supplied shims can be inserted transparently between the application and the core kernel to support these features transparently. Commercial distributed object middleware libraries and standards like DCOM, MTS, and CORBA make regular use of things called "thread pools," which satisfies all the requirements for an event-driven architecture of this nature.
As a clear example of this style of OS, look no further than GEOS/64. GEOS API is big and bulky, but nonetheless demonstrates the power of having a system-wide event queue. I wish I had another example, but unfortunately a design prototype I implemented in Linux one day can't be found. As far as commercial examples, look at some of the more sophisticated Enterprise JavaBeans implementations, or CORBA or DCOM/MTS "thread pools" implementations.
Quote:
- filesystem
Quote:
- handling of the available memory
- page swapping
- page swapping
Hopefully, I've provided food for thought on this issue. I strongly advocate a consistent OS architecture. While I am a huge fan of Forth for OS-level interaction, I recognize that not everyone wants this. If I were to accept a more traditional OS architecture, this is what I'd want to see.
Note, however, that a microkernel approach, where multiple tasks exchange messages with each other, is perhaps *the* ideal solution, but it requires support for preemptive multitasking, at the very least. I strongly urge folks to study the L4 microkernel for inspiration in this area. It has something like 12 to 14 system calls, and that is it. The two most frequently used are SEND and RECEIVE, used to send and receive a message, respectively.
SEND will block the calling task until its message is received. RECEIVE will block until a message becomes available. No message queues -- you send directly to task IDs. Thus, memory consumption is *constant* (unlike the event driven architecture I pointed out above), and if you can load a program into memory, you can NEVER run out of memory due to excessive message passing.
But, again, it requires preemptive multitasking at the very least.
asmlang_6 wrote:
The Z80 and 8080 processors are 8 bits. That would make it easy to port to the 6502. If anyone could find the assembly source for CP/M for the 8080, I could probably port it.
Yes, all three processors are 8-bit and have a 64k address space but there are several critical differences which will make direct translation almost impossible:
Stack: the 6502 has the stack in a fixed location and a fixed size. The 8080/Z80 stack can be initialized to any address and can grow beyond 256 bytes.
Vectors: the 8080/Z80 have 8 software vectors called restart vectors (RST0 to RST7) which occupy the first 64 bytes of the address space. One can place a short routine in each and execute it by issuing the one-byte RST instruction.
Instructions: the 8080/Z80 has many instructions which have no analogue in the 6502 (the RST instruction is a good example)
Registers: the 8080/Z80 have four pairs of 16-bit registers (AF, BC, DE, HL) which are also byte-addressible, in addition to the stack pointer and instruction registers. The Z80 adds two index registers and a number of "prime" registers (i.e., BC') in the same number as the base registers. I confess that I'm not as well-versed on the Z80 as I am with the 8080 but the fact remains that the 8080/Z80 have way many more registers than the 6502.
I/O: The 8080/Z80 use port-mapped I/O while the 6502 is memory mapped I/O.
Examining the CP/M sources, it becomes evident that since CP/M uses many of the things that comprise the differences between the two processor architectures, direct translation would be impossible.
Now, one solution would be to design a standard Z80 daughter card and software like the Commodore Z80 cartridge or the Apple Z80 Card that can be used with homebrew designs.
Rich
Rich Cini
http://cini.classiccmp.org
http://altair32.classiccmp.org
GitHub Repro: https://github.com/RichCini
http://cini.classiccmp.org
http://altair32.classiccmp.org
GitHub Repro: https://github.com/RichCini
RichCini wrote:
Although I haven't done an exhaustive comparison of the two processors, I believe that just translating the CP/M sources won't work.
Quote:
Stack: the 6502 has the stack in a fixed location and a fixed size. The 8080/Z80 stack can be initialized to any address and can grow beyond 256 bytes.
Quote:
Vectors: the 8080/Z80 have 8 software vectors called restart vectors (RST0 to RST7) which occupy the first 64 bytes of the address space. One can place a short routine in each and execute it by issuing the one-byte RST instruction.
However, this is irrelavent, as CP/M applications tend not to use RST vectors, but rather load parameters into registers and issue a CALL 5 instruction. The 6502 can do the same, loading X with the offset of a jump table, and issuing something like a JSR $0000.
Quote:
Instructions: the 8080/Z80 has many instructions which have no analogue in the 6502 (the RST instruction is a good example)
Quote:
Registers: the 8080/Z80 have four pairs of 16-bit registers (AF, BC, DE, HL) which are also byte-addressible, in addition to the stack pointer and instruction registers. The Z80 adds two index registers and a number of "prime" registers (i.e., BC') in the same number as the base registers. I confess that I'm not as well-versed on the Z80 as I am with the 8080 but the fact remains that the 8080/Z80 have way many more registers than the 6502.
Quote:
I/O: The 8080/Z80 use port-mapped I/O while the 6502 is memory mapped I/O.
And remember, the 68000 also lacks port I/O, relying also on memory-mapped I/O. I believe that the majority of the Commodore 128's I/O were also port-mapped, even when using CP/M mode.
Quote:
Examining the CP/M sources, it becomes evident that since CP/M uses many of the things that comprise the differences between the two processor architectures, direct translation would be impossible.
Quote:
Now, one solution would be to design a standard Z80 daughter card and software like the Commodore Z80 cartridge or the Apple Z80 Card that can be used with homebrew designs.
However, CP/M is a pretty poor example OS to follow anyway. While architecturally trivial, it is equally self-limiting. All the major advancements in CP/M required major kernel rewritings, and those introduced software incompatibilities for all but the most rigorously CP/M 1.0-compliant programs.
If you want a good quality OS architecture, use a microkernel, and implement a few, basic primitives that are easy to implement and quite orthogonal. On top of the microkernel, a proper subset of the POSIX API would be a good point for inspiration. While not many people might agree that "everything can be treated as a file," it nonetheless has proven itself time and time again, from OSes like OS-9 to Lunix. open() can connect your program with another, read() and write() are used to communicate with said program, and close() is used to terminate that connection. poll() can be used to monitor multiple connections if you choose to implement asynchronous interprocess communications. Alternatively, you can implement a fleet of threads, one per source of input, and coordinate with a master thread. The advantage of the latter, synchronous system is that memory consumption is predictable and has hard limits, and it's easier to preserve message boundaries when sending data between running programs. This latter approach is more useful for 65816 systems, however, where more memory to support the larger thread pool is allowed.
kc5tja wrote:
Quote:
Vectors: the 8080/Z80 have 8 software vectors called restart vectors (RST0 to RST7) which occupy the first 64 bytes of the address space. One can place a short routine in each and execute it by issuing the one-byte RST instruction.
The 6502 has a BRK instruction which can, under software control, take a one-byte operand, thus offering up to 256 software-dispatched vectors.
The 6502 has a BRK instruction which can, under software control, take a one-byte operand, thus offering up to 256 software-dispatched vectors.
Quote:
Instructions: the 8080/Z80 has many instructions which have no analogue in the 6502 (the RST instruction is a good example)
RST is a poor example; BRK is its analog.
RST is a poor example; BRK is its analog.
Quote:
Registers: the 8080/Z80 have four pairs of 16-bit registers (AF, BC, DE, HL) which are also byte-addressible, in addition to the stack pointer and instruction registers. The Z80 adds two index registers and a number of "prime" registers (i.e., BC') in the same number as the base registers. I confess that I'm not as well-versed on the Z80 as I am with the 8080 but the fact remains that the 8080/Z80 have way many more registers than the 6502.
Irrelavent as CP/M tended to store 90% of its function call parameters in memory in the form of various "control blocks." Additionally, the 6502's zero page is usually used and is treated as if it were a set of 256 8-bit wide registers, which can be paired up to 128 16-bit wide registers. With proper coding practices, the (dp,X) addressing mode can provide a method for invoking OS functions re-entrantly. CP/M is not reentrant.
Irrelavent as CP/M tended to store 90% of its function call parameters in memory in the form of various "control blocks." Additionally, the 6502's zero page is usually used and is treated as if it were a set of 256 8-bit wide registers, which can be paired up to 128 16-bit wide registers. With proper coding practices, the (dp,X) addressing mode can provide a method for invoking OS functions re-entrantly. CP/M is not reentrant.
Quote:
I/O: The 8080/Z80 use port-mapped I/O while the 6502 is memory mapped I/O.
False; the 8080/Z80 *CAN* use port-mapped I/O, but often times also uses memory-mapped I/O (TRS-80 anyone?). Moreover, you're not going to use port-mapped I/O to stuff the video frame buffer, now are you?
False; the 8080/Z80 *CAN* use port-mapped I/O, but often times also uses memory-mapped I/O (TRS-80 anyone?). Moreover, you're not going to use port-mapped I/O to stuff the video frame buffer, now are you?
Quote:
Examining the CP/M sources, it becomes evident that since CP/M uses many of the things that comprise the differences between the two processor architectures, direct translation would be impossible.
Also false. The BDOS module is quite possible to port, as only the BIOS is responsible for hardware-specific system interaction.
Also false. The BDOS module is quite possible to port, as only the BIOS is responsible for hardware-specific system interaction.
Quote:
Now, one solution would be to design a standard Z80 daughter card and software like the Commodore Z80 cartridge or the Apple Z80 Card that can be used with homebrew designs.
Thus defeating the whole purpose of the exercise. If we wanted a Z-80 running the OS of the system, we'll build our systems with Z-80s, and circumvent the whole 6502 architecture completely. As it is, we're interested in the 6502, not the Z-80.
Thus defeating the whole purpose of the exercise. If we wanted a Z-80 running the OS of the system, we'll build our systems with Z-80s, and circumvent the whole 6502 architecture completely. As it is, we're interested in the 6502, not the Z-80.
Rich Cini
http://cini.classiccmp.org
http://altair32.classiccmp.org
GitHub Repro: https://github.com/RichCini
http://cini.classiccmp.org
http://altair32.classiccmp.org
GitHub Repro: https://github.com/RichCini
Ruud wrote:
You'll find sources at http://www.gaby.de/ but if it is just a matter of translating sources, I or anyone else could have done it years ago. The way files are loaded in memory and how the memory is treaten has everything to do how a Z80 handles memory. And a 6502 isn't a Z80. CP/M 3.0 is supports memory banking but it can only handle 15 extra banks of 32 KB and the way it is done doesn't cheer me up either, certainly if seen from the point of view of a 6502.
Ruud wrote:
The idea of this OS (a nice name, anyone?) is that it should run on various existing hardware and hardware yet to be build. CP/M requires a minimum of at least 16 KB AFAIK. 3.0 needs at least 48 KB. And my VIC-20 only has 5 KB on board.....
Sam
---
"OK, let's see, A0 on the 6502 goes to the ROM. Now where was that reset vector?"
---
"OK, let's see, A0 on the 6502 goes to the ROM. Now where was that reset vector?"
Quote:
I'm familiar with the existence of the BRK instruction but wasn't aware of the "operand" capability.
Quote:
I agree with CP/M's non-reentrancy. I don't know about your statement regarding the use of Z-page memory. My point of reference is the early Commodore machines which by in large did not utilize the space that way. Maybe the later ones did.
A common practice on the 65816 is to overlap the stack and direct page, which opens up still more interesting possibilities for high-level languages like C and Pascal/Oberon. When used in this mode, the D register forms the equivalent of a frame base pointer register, while the S register continues to serve as the regular stack pointer, leaving X open for application use. Pretty slick stuff.
Quote:
OK. I was attacking it from the point that it would be more difficult to re-write the BIOS, which was written for a different architecture, to fit another, than it would be to create a small daughter board and use a stock CP/M 2.2 distribution with I/O customization the same way one would modify the stock BIOS to work with his particular hardware configuration.
The only thing that would remain to be designed from scratch would be the disk I/O interface, but even here, IDE drivers are usually very (trivially, even) simple to implement for polled I/O. 6502.org has a few IDE interface projects that include sample code too.
Personally, I think the hardest part of the OS architecture will be identifying devices by name, and choosing between single-letter names (e.g., A:, B:, etc), multi-letter names (e.g., CON:, PRT:), or using a unified namespace (e.g., /dev/con, /MyDisk/MyDir/MyFile.txt). I'm generally a fan of the unified approach, but my AmigaOS background allows me to accept the multi-character label approach too. I really am not a fan of single-letter IDs for things.
Hallo kc5tja,
> The question is, however, does anyone *WANT* such an OS?
I merely see it as a FUN project.
> I wager to think no, or else someone would have provided one.
I can imagine there was no need in those days for whatever reason. But with not so many 6502 machines around these days, it means that with writing an application under such an OS you reach more people then writing an application for a specific machine.
> I strongly recommend using a microkernel-like architecture,
Haven't any idea what this means. I grew up with Commodore and MS-DOS so I'm a bit norrow minded.
> If you're so hell-bent on having a huge proliferation of vectors,
I called it "vector" as used by Commodore by lack of another name.
> I recommend instead the AmigaOS-style library system, where libraries
> supply their own vectors. To call a function:
IMHO just calling a vector inside another vector. Like calling a subfunction of INT $10, the software interrupt that handles all things that have to do with video under MS-DOS. Inserting a VGA card means that the system will use the routines provided by the card rather then the ones provided by the BIOS.
Hmm, a better example would be using INT $21, the MS-DOS interrupt.
> This way, vectors are kept library-specific, and take up space only for the
> modules that are currently loaded.
I want a compact OS, not one that needs to load a certain library if the circumstances require that. With the VIC-20 in mind: using a ROM based OS you cannot load another library when needed. OTOH, Commodore always provide a JMP ($xxxx) in their vectors where $xxxx is situated in RAM. This enables a program to bend/use a vector for its own purposes. CP/M and DOS placed their vectors in RAM as well enabling programs to do the same trick.
> MUCH more important is not the filesystem proper, but the interface to a
> filesystem.
Agreed. I had the own FS puely in mind for exchanging data through a PC. But even that is important. I use a PC as an external drive for my Commodores. The only commands a C= issues are commands like "LOAD", "SAVE", "PUT", "GET" etc., all FS independant commands. In these commands you have the interface you are looking for. And that enabled me to attach an 80 GB floppydrive to my CBM 8032 :)
FYI: I must admit that it is possible to target specific tracks and sectors on a floppy. Simulating the C= FS this is possible for 'floppies' up to 16 MB. When accessing a bigger drive, my simulator ignores this command.
> Also, its layout does not permit subdirectories,
Wrong, the FS itself permits it but that most drive don't support it, that's something else. If you want to know more about it, ask me.
> Instead, building an event-driven architecture is perhaps the best overall
> choice.
+
> As a clear example of this style of OS, look no further than GEOS/64.
> GEOS API is big and bulky,
IMHO indeed too bulky.
It is not that I only want an universal OS for the 6502, I also want to learn from it. I intend to start with "MS-DOS 1.0" and grow to "Windows XP" gradually (learning from the errors MS made of course).
> ... allocating space in a disk file to emulate memory.
Virtual memory, haven't thought about that as so yet. But OTOH VM can be seen as a special form of bankswitching: instead of swapping memory, data is swapped between memory and drive.
> Hopefully, I've provided food for thought on this issue.
Yep, you did :)
> If you want a good quality OS architecture, use a microkernel, and ....
> ..... poll() can be used ...
Sounds a bit like the IEEE protocol the Commodores use to exchange data with their peripherals what I'm familiar with. And therefor sounds good :)
> Personally, I think the hardest part of the OS architecture will be
> identifying devices by name, and choosing between single-letter names
> (e.g., A:, B:, etc), multi-letter names (e.g., CON:, PRT:), or using a
> unified namespace (e.g., /dev/con, /MyDisk/MyDir/MyFile.txt). I'm generally
> a fan of the unified approach, but my AmigaOS background allows me to
> accept the multi-character label approach too. I really am not a fan of
> single-letter IDs for things.
Never thought about this. But I tend to choose for the unified approach as well.
Hallo Sam,
> And I'll call the 6502 version CP/M-65.
I have thought about that as well but then a user will expect commands like DIR, PIP, ED etc. and the looks of CP/M like a A> prompt etc. Anyway thanks for the input.
> A good system to port to would be the Apple ][, ... and has quite a bit of
> memory from the start.
I want it to be able to run systems with just a bit of memory, maybe as low as 2 KB.
> The question is, however, does anyone *WANT* such an OS?
I merely see it as a FUN project.
> I wager to think no, or else someone would have provided one.
I can imagine there was no need in those days for whatever reason. But with not so many 6502 machines around these days, it means that with writing an application under such an OS you reach more people then writing an application for a specific machine.
> I strongly recommend using a microkernel-like architecture,
Haven't any idea what this means. I grew up with Commodore and MS-DOS so I'm a bit norrow minded.
> If you're so hell-bent on having a huge proliferation of vectors,
I called it "vector" as used by Commodore by lack of another name.
> I recommend instead the AmigaOS-style library system, where libraries
> supply their own vectors. To call a function:
IMHO just calling a vector inside another vector. Like calling a subfunction of INT $10, the software interrupt that handles all things that have to do with video under MS-DOS. Inserting a VGA card means that the system will use the routines provided by the card rather then the ones provided by the BIOS.
Hmm, a better example would be using INT $21, the MS-DOS interrupt.
> This way, vectors are kept library-specific, and take up space only for the
> modules that are currently loaded.
I want a compact OS, not one that needs to load a certain library if the circumstances require that. With the VIC-20 in mind: using a ROM based OS you cannot load another library when needed. OTOH, Commodore always provide a JMP ($xxxx) in their vectors where $xxxx is situated in RAM. This enables a program to bend/use a vector for its own purposes. CP/M and DOS placed their vectors in RAM as well enabling programs to do the same trick.
> MUCH more important is not the filesystem proper, but the interface to a
> filesystem.
Agreed. I had the own FS puely in mind for exchanging data through a PC. But even that is important. I use a PC as an external drive for my Commodores. The only commands a C= issues are commands like "LOAD", "SAVE", "PUT", "GET" etc., all FS independant commands. In these commands you have the interface you are looking for. And that enabled me to attach an 80 GB floppydrive to my CBM 8032 :)
FYI: I must admit that it is possible to target specific tracks and sectors on a floppy. Simulating the C= FS this is possible for 'floppies' up to 16 MB. When accessing a bigger drive, my simulator ignores this command.
> Also, its layout does not permit subdirectories,
Wrong, the FS itself permits it but that most drive don't support it, that's something else. If you want to know more about it, ask me.
> Instead, building an event-driven architecture is perhaps the best overall
> choice.
+
> As a clear example of this style of OS, look no further than GEOS/64.
> GEOS API is big and bulky,
IMHO indeed too bulky.
It is not that I only want an universal OS for the 6502, I also want to learn from it. I intend to start with "MS-DOS 1.0" and grow to "Windows XP" gradually (learning from the errors MS made of course).
> ... allocating space in a disk file to emulate memory.
Virtual memory, haven't thought about that as so yet. But OTOH VM can be seen as a special form of bankswitching: instead of swapping memory, data is swapped between memory and drive.
> Hopefully, I've provided food for thought on this issue.
Yep, you did :)
> If you want a good quality OS architecture, use a microkernel, and ....
> ..... poll() can be used ...
Sounds a bit like the IEEE protocol the Commodores use to exchange data with their peripherals what I'm familiar with. And therefor sounds good :)
> Personally, I think the hardest part of the OS architecture will be
> identifying devices by name, and choosing between single-letter names
> (e.g., A:, B:, etc), multi-letter names (e.g., CON:, PRT:), or using a
> unified namespace (e.g., /dev/con, /MyDisk/MyDir/MyFile.txt). I'm generally
> a fan of the unified approach, but my AmigaOS background allows me to
> accept the multi-character label approach too. I really am not a fan of
> single-letter IDs for things.
Never thought about this. But I tend to choose for the unified approach as well.
Hallo Sam,
> And I'll call the 6502 version CP/M-65.
I have thought about that as well but then a user will expect commands like DIR, PIP, ED etc. and the looks of CP/M like a A> prompt etc. Anyway thanks for the input.
> A good system to port to would be the Apple ][, ... and has quite a bit of
> memory from the start.
I want it to be able to run systems with just a bit of memory, maybe as low as 2 KB.
Code: Select all
___
/ __|__
/ / |_/ Groetjes, Ruud
\ \__|_\
\___| URL: www.baltissen.org
Quote:
IMHO just calling a vector inside another vector. Like calling a subfunction of INT $10, the software interrupt that handles all things that have to do with video under MS-DOS. Inserting a VGA card means that the system will use the routines provided by the card rather then the ones provided by the BIOS.
Hmm, a better example would be using INT $21, the MS-DOS interrupt.
Hmm, a better example would be using INT $21, the MS-DOS interrupt.
The advantage of libraries is that anyone can write them and, upon loading, are treated precisely the same way as OS-standard libraries.
However, since the 6502 lacks memory protection hardware, you can probably get the same level of performance by creating virtual devices that programs can just open(), read(), write(), and close(). For example:
Code: Select all
; I'm avoiding showing error checking because it's irrelavent
; to the expression of my idea.
; Open the clock handler
lda #<ClockName
ldx #>ClockName
ldy #OpenFlags
jsr Open
sta clockHandle
; Ask it for the current wall clock time
tax
lda #'G ; "G"et current time
jsr WChar
; Now we receive the results.
lda clockHandle
ldx #<resultBuffer
ldy #>resultBuffer
jsr SetBuffer
ldx #<bufferLength
ldy #>bufferLength
jsr SetLength
jsr RBuffer
; We're done, so we might as well just close the clock device
lda clockHandle
jsr Close
Quote:
> This way, vectors are kept library-specific, and take up space only for the
> modules that are currently loaded.
I want a compact OS, not one that needs to load a certain library if the circumstances require that. With the VIC-20 in mind: using a ROM based OS you cannot load another library when needed.
> modules that are currently loaded.
I want a compact OS, not one that needs to load a certain library if the circumstances require that. With the VIC-20 in mind: using a ROM based OS you cannot load another library when needed.
Granted, though, I doublt you'll be able to pull this off in any meaningful way with only 2KB RAM available. Here, you'll need to make a tradeoff between expressive power versus compactness.
Quote:
OTOH, Commodore always provide a JMP ($xxxx) in their vectors where $xxxx is situated in RAM. This enables a program to bend/use a vector for its own purposes. CP/M and DOS placed their vectors in RAM as well enabling programs to do the same trick.
But, this is pretty much academic at this point. If your target computer is a VIC-20, then you'll want to go with a file-structured interface and support installable, virtual files and maybe even virtual directories if you've got the space for it.
Quote:
FYI: I must admit that it is possible to target specific tracks and sectors on a floppy. Simulating the C= FS this is possible for 'floppies' up to 16 MB. When accessing a bigger drive, my simulator ignores this command.
Quote:
> Also, its layout does not permit subdirectories,
Wrong, the FS itself permits it but that most drive don't support it, that's something else. If you want to know more about it, ask me.
Wrong, the FS itself permits it but that most drive don't support it, that's something else. If you want to know more about it, ask me.
Quote:
It is not that I only want an universal OS for the 6502, I also want to learn from it. I intend to start with "MS-DOS 1.0" and grow to "Windows XP" gradually (learning from the errors MS made of course).
What I was saying is to make an OS with a centralized event management and distribution system. GEOS is an example of this kind of philosophy. It is not the end-all, be-all of such operating systems. I've already outlined other examples, including CORBA and DCOM/MTS, which are domain-specific implementations of the concept.
GEOS is bulky because it's not orthogonal. It is lumping GUI code, FS code, and event management code, all into a single, static, monolithic kernel. If you want a system that is easy to learn, easy to hack, easy to maintain, then you need to use a microkernel. Keep the kernel small, efficient, and managable. Everything else is implemented as loaded or ROM-resident modules that is *clearly* distinct from the core kernel. Yes, it takes up some extra space for the linkage, but you'll be MUCH happier with the result.
If it's one thing I've learned, OSes are NOT simple programs.
Quote:
Virtual memory, haven't thought about that as so yet. But OTOH VM can be seen as a special form of bankswitching: instead of swapping memory, data is swapped between memory and drive.
Note to Forth programmers: Lock() is analogous to BLOCK. Dirty() is analogous to UPDATE. There is no precise mapping of Unlock() to Forth, because Forth requires the application to use BLOCK to get its base address at all times; hence, blocks are inherently "unlocked" in Forth. Fortunately, most Forth systems are cooperatively multitasking at best, and so do not require explicit locking of blocks. However, if anything, FLUSH is the closest relative to Unlock(). Forth has no dynamically allocated blocks by default, so no standard analogs of Allocate() and Free() either.
Quote:
Sounds a bit like the IEEE protocol the Commodores use to exchange data with their peripherals what I'm familiar with. And therefor sounds good 
For an OS, are you all familiar with Contiki? http://www.sics.se/~adam/contiki/
I would try to use it if I was able to compile an NES version with cc65.
I think that's a great idea. I've been wanting to create a setup just like this (except using the PC's native filesystem rather than a disk image, but that's mostly because I thought it'd be easier). I wrote out a little spec sheet last year with various commands for controlling it, I'll try to find it if you want to see my take on the idea. But I'm not sure how to write it as a PC program. I'd be willing to help write the 6502-side of something like this though, definitely.
For now I'm simply using XMODEM, which works well, but it's not usually fun to switch constantly between using my PC and my 8-bit. At least if I use YMODEM I think I won't have to type filenames anymore, but it still requires some human intervention.
I would try to use it if I was able to compile an NES version with cc65.
Ruud wrote:
My idea: most computers I know off have a RS-232 port. We can program the OS so that it treats this particular port as another drive. We connect a PC to this port that runs a program that emulates a (hard)disk using an image. And we need this Filesystem for this emulated disk.
For now I'm simply using XMODEM, which works well, but it's not usually fun to switch constantly between using my PC and my 8-bit. At least if I use YMODEM I think I won't have to type filenames anymore, but it still requires some human intervention.
Quote:
My idea: most computers I know off have a RS-232 port. We can program the OS so that it treats this particular port as another drive.
bogax wrote:
Quote:
My idea: most computers I know off have a RS-232 port. We can program the OS so that it treats this particular port as another drive.
In light of the fact that a 6502 system contains zero memory protection features, and in light of the fact that there is an increasing trend towards multitasking operating systems for 6502 and 65816 systems, it seems appropriate to reference this document at this time:
http://www.stanford.edu/~candea/papers/ ... honly.html
Very interesting read. They discuss the issue from a web/internet perspective, but the general concepts apply universally. This paper might give you some ideas.
http://www.stanford.edu/~candea/papers/ ... honly.html
Very interesting read. They discuss the issue from a web/internet perspective, but the general concepts apply universally. This paper might give you some ideas.