Jump to content


  • Posts

  • Joined

  • Last visited

Everything posted by hth313

  1. My 6502 C compiler tool chain as an early release. Send a private request to me for details on how to download it if you are interested. Documentation is available here: https://drive.google.com/file/d/1Eai87NQhPZ_XoTtgwmo-g_Upk0xDAyx0/view?usp=sharing I have installers for macOS, Arch and Debian Linux (x86_64). Highlights: ISO C 99 compiler for 6502/65C02. This is a freestanding implementation with many features you will typically find in a hosted compiler. Fully reentrant code model. Support for all integer types up to 64 bits 'long long'. Floating point supported (32 bits IEEE-754). Full support for struct, union, typedef and what you expect to find in C. The C stack is located outside the zero page, which means it can be as large as available memory (in the full 64K address range). Support for (stack allocated) variable sized arrays. Run-time model based on using pseudo registers in the zero page. Parameter passing uses A and pseudo zero page registers (up to 8 bytes). Any remaining arguments are passed on the stack. The compiler utilizes zero page as much as possible for local and temporary variables. Optimizing compiler that can output source level debugging information. Source code debugger included. Support for ELF/DWARF, hex output as well as RAW and PRG (Commodore) style program files.
  2. About Swedish computers... The ABC-80 was popular at the time, though a little bit pricey. It was often found in schools. It was later "replaced" with the ABC-800 series, which was more for professional use. These are BASIC machines, much like C64 and such. The ABC-800 was really built like a tank, I think it would survive in a real battlefield, the ABC-80 less so, but it was totally decent. The Jet-80 was also around, it used CP/M 3 and was a very nice machine. Full Z80 chip set including DMA and banking to provide more TPA (larger application program area, I think you got 60-61K). All the above used Z80. DIAB (who produced the ABC-80) later also made the DS90 which was a UNIX machine (DNIX). These were 68k based. There was also the Compis ("Kompis" means pal or friend in Swedish, so it got a C for Computer, I think) which was intended as a school computer, running the futuristic 80186. This one was not so successful.
  3. Very promising, however I find the high pitched fragile synthetic tone (I do not know how to describe it) very annoying. I want more a heavy metal tune.
  4. "SysReq/PrtSc, Scroll Lock and Pause/Break", I have never used those keys and in most cases cannot imagine what they do, LOL The only thing that bothers me is that it puts the CTRL key down in the corner, which is a stupidity introduced by PC. Old UNIX keyboards (terminals) and my current (Happy Hacking) keyboard put it where the never used SHIFT LOCK is located on the X16 keyboard. Even the Commodore 64 got it in a better position (TAB) than down in the corner. Having it down there means I need to twist my hand to reach it, and I use that key a lot. It is actually very annoying to me, but I guess that I am the minority. (Rant off)
  5. I do not care so much of having CP/M on the X16, I would get a dedicated machine for that and they are not too pricey. What I do care about is having a proper serial port. Not having that is a huge turnoff for me. Would at least be possible to have it in the motherboard design even if it is not populated? I have one or two 6551 in my stash, there are new serial adapters using Rockwell 6551 sold on Ebay for the C64, not sure where they are sourced from.
  6. I used the BASIC that came with the C64 and C128 back in the day and while they can be used for various things, they quickly fall short and I abandoned them for Forth and assembly. With the X16 I will not even bother to try the BASIC, I will go to C and assembly instead. I wish it could boot into Forth and I could choose to play in that environment, or just load (C or assembly) software, then I would be very happy. Another alternative would be Scheme, I am not sure how feasible that is? My little 8-bit Lisp machine..
  7. Is there some special considerations to be made if I want to pick up some YM2151 chips online? Given the shipping cost it seems sensible to buy at least 10. The reason for buying them is to ensure I have some spares if the stocks run out or low causing price to go up significantly.
  8. @desertfishThank you for the suggested way of going back to the Kernal. I have added that as the fallback way of doing explicit exit(), which is useful if the program has messed things up too much and want to exit back to a clean machine.
  9. I changed the C startup code to simply use the existing stack as-is. This solves the problem and I now get back to the blinking prompt when main() returns. I also took the opportunity to optimize it to the metal, more or less. I still have a proper C startup for the X16, but I changed the C code to be more like how I would write a Hello World in assembly, using a loop to send it to a character out routine, no printf() or stream related functions dragged in from the C library, no 0 exit code return either. The result is a C program that when compiled and linked results in a .PRG file that is 88 bytes.
  10. To be honest, an 8-bit like the 6502 is not at all about compact code, perhaps not even elegant. You will get much nicer instruction set if you move to the MSP430 or 68000. Even something like the RISC-V may be considered elegant compared to the 6502. An interesting approach would be to join something like Vera with a nice 16 or 32-bit based instruction set CPU. However, you would have to start from scratch with the "operating system" and the group of people interested in a 6502 computer would have to learn a new ISA, and somehow I think you would lose most of the audience along the road. I am not saying it is a bad idea. If the X16 is successful, it may make sense to produce a follow up going to a more modern ISA. It could have the same chipset (more or less). If people avoid 6502 assembly as an implementation language (there are BASIC, C, Forth etc), some software may be possible to migrate with reasonable effort.
  11. The problem is that I take over and set my own stack. I also put some stuff in zero page, but that should be in permitted and safe area (so far). What I am looking for is some soft-reset entry point back to BASIC that leaves the display and program. It should perhaps clear variables and sets up the stack again. Perhaps I should not touch the CPU stack at all?
  12. I just got my first output from my (own) C compiler and it was also among the first times I ever played with the X16 emulator, so I want to share my (minor) success. How should I exit from the program back to the system? Sorry if this is really a stupid question, but it was a long time ago since I programmed a Commodore 8-bit machine.
  13. Moving the bank registers to zero page only makes sense if it is also possible to read them. It is useful to allow calls between banks using a trampoline (bank switcher) in non-banked memory. Such trampoline needs to push the bank number together with the return address so that it later can return via another trampoline to the caller (switching the bank back). If reading is not possible, a shadow bank number could be written to RAM, but that would mean writing the bank twice which defeats the gain of having it in zero page.
  14. If seeking is not available then ELF is out. I do not think is practical to read several program header structures, not knowing how many they are. I still think it is a good idea to be able to load a file into memory and have banks populated automatically. Can someone explain how GEOS helps to load a banked program at power on when I get the READY prompt?
  15. I think a load format for banked data is very useful and it should be in the ROM. That way we can just load a file and have it placed in memory without having to re-invent the wheel by providing custom loaders. Does it prevent anyone from rolling their own? Not at all, you are free to load a plain binary and load data and program chunks from the file system as you see fit. I on my side prefer to have a binary file created by a tool and not need to bother how it gets loaded into memory, even when I need to use the bank system. I like the ELF format myself as it rather simple to use when the requirements are simple, yet it provides a lot of flexibility and can be quite expressive when needed. Most of the complexity comes when adding debug sections or linkable sections, but that is not what we are doing here. I will describe it a bit below to give an idea what it is and show that it actually have a lot of similarities to the proposed format. An ELF file has an ELF header that starts with a magic number (actually the string ELF) that identifies it as ELF. You only need to sanity check that it is 32-bit ELF, inspect the processor type and values related to program headers that describe where the program headers are in the file, their size and how many they are. Each program header describes a chunk of memory to be loaded. The headers appear after each other. A header can describe an area to be cleared, or it can point to actual raw data to be loaded and it can specify a start address. Thus, in a file you have: ----------------- ELF Header --------------- Program header 1 ---------------- Program header 2 ---------------- ... ---------------- Program header n ---------------- Load data ---------------- The file can also contain sections, mainly for debug or vendor specific stuff, but you totally ignore them. Even if sections are in the file, you will automatically ignore them when you use the file offsets to locate the program headers and data. For a banked system you could use a program header for each bank. The address is 32-bit so you can easily combine a bank number with the lower address. If you compare this to the proposed format you will see that the structure is very similar. The ELF header is 52 bytes (in 32-bit ELF) compared to 64 in the proposed format. Each program header is 32 bytes in ELF and 8 in the proposed format. The main difference is that in ELF the program headers are located after each other and contains a field that gives the file offset of the actual data. A loader can interpret relevant fields and do some simple sanity checking, it does not need to be any more complicated. Here is a rough load algorithm: Open file, read ELF header and check the magic number, sanity check some fields in the ELF header to see that it is 32-bit ELF, for 6502 and that there is at least one program header. Store number of program headers, the size and keep a pointer to the current one, initialize it with the offset of the first program header as given in the ELF header. Seek to the next program header, load it and inspect type, read start address (if program type), size, offset in file to actual data. Load raw data from file, if the specified area is larger than what is in file, fill the rest with zero. Step to next program header, decrement header counter, if more program headers then go to 2. Jump to the start address of the program. The main advantage of using an existing format like ELF is that it makes it possible to use other tools for inspecting and altering the executable file. It also avoids re-inventing the wheel again as someone already gave this some thought. We only need to specify how we use the format for the CX16.
  16. I think it would be a good idea to have a loader in ROM so that the machine natively can load large binaries as single files. Without looking much into it, my gut feeling is that unless there is a good reason for it, it is better to use an existing format, or a subset of one. One advantage is that we do not need to invent something new, we just have to specify (supplement) how an existing format is used for this purpose. Second, we can use already existing tools to inspect and do things with such files. For example, I use the ELF format in my tools and as a result I can use tools such as 'objdump' to visualize and inspect the files, and 'strip' to prune them afterwards.
  17. Did you base that on some existing format? I can think of a.out, COFF, ELF and Hunk without going out searching. There are probably more to choose from if you look around. In any case, it would be great to have a format so that large multi-segment programs can be loaded.
  18. For a C or assembly project, I wonder how the PRG file format looks. Is it the same as on the Commodore 64, that it should start at 0x0801 where you can have a tokenized 'SYS address' and the first two bytes in the file are the 01-08 which are just the load address and otherwise ignored (not written to memory)? Second, is there a format so that a file can contain multiple segments to be loaded? For example, one segment is loaded to unbanked memory (like a normal PRG file), then other segments follow in the same file that are automatically loaded into (specified) banks?
  19. I wonder if there is a serial port planned for the Commander X16? It does not seem so from what I have seen, but maybe there is something for the expansion bus? The main reason that I want a serial port is for remote debugging.
  20. I should add that I appreciate having the computer in a separate box. I never liked the computer in a keyboard design (having owned C64 breadbin and Amiga 500). The thing with less memory and slower computer is that you have to work with what you have. That can give a lot of satisfaction getting it to work within constraints. But, yes, you have good points. The 40 column display is annoying and the VERA may be interesting to have. I see myself as mostly using it for remote debugging. If I ever sit down to do things it would be using Forth and in such case I would surely appreciate having 64 or 80 columns. I wish there was a 6551 serial port included, or least a socket for one, but I suppose it would not handle 8MHz anyway. It would be very useful for remote debugging. I will definitely follow the Commander X16 and the alternatives to see how it goes, no decisions on my side yet. Well, I already have an Amiga that gathers dust most of the time, so I do not think I will get the Vampire in the near future at least.
  21. To be honest, for me the main advantage of the Commander X16 over the Mega 65 is the simplicity. It is a standard 6502 (well 65C02) with a simple memory model. However, I think that I will actually just get a new Commodore 64 over any of these machines as it does everything I want. I would just go and buy an Ultimate-64 if I could get a new keyboard for it, but I can't. Thus, I wait and see if the Mega 65 comes out and if the price is not over the top, then I will probably get one and basically see it as a variant of the Ultimate-64. The limitations of the C64 is actually a benefit as if I want to do something myself, as I have to work inside the constraints. It is probably just as fun and also avoids feature creep, making it more likely that I actually have time to finish something. If I wanted something more, then I think I would just do like I did 1987 when I sold my C128D and replaced it with an Amiga. The Vampire Standalone is not that over the top in price and offers a lot more. I prefer that over the Mega 65 when it comes to the extra abilities.
  22. It depends on the run-time model of the compiler how it arranges the stack or stacks. If you have a model with a C stack out in 64K memory, you have plenty of stack. The call stack is still 256 bytes, which translates to 100+ levels or so. That is a lot unless you are into really deep recursive calls. With a decent run-time model based on such ideas you will not gain much by making things global, in fact it is more likely to make things worse. You are best off passing pointers rather than structures by value, otherwise favor local variables and avoid global variables as much as possible. Also, with a stack in the 64K memory there is no problem to allocate things on the stack and pass around as it is just a pointer (just do not let them go out of scope and still use them). The reason that global variables make things worse is that they are subject to aliasing. The compiler cannot know how called functions, interrupts and even arbitrary pointer accesses may affect global variables and is likely to take a conservative approach. With local variables the current function "owns" the variable and the compiler will now more about how it is used and can act on that knowledge. Also, global variables tend to make the code more complicated, especially if the global variables are used in a haphazard way, leading to code that is hard to read, hard to maintain and bugs.
  23. Looks good, I have a cc65-chess to. I should do fine with that, thanks!
  24. I am working on a C compiler for the 6502 and wonder if someone can point me to a suitable C project for the X16? I would like to try my own stuff out and compare generated code a bit.
  • Create New...

Important Information

Please review our Terms of Use