Some cc65 compiler questions

Get technical support from the community & developers with specific X16 programs if you can't find the solution elsewhere
(for general non-support related chat about programs please comment directly under the program in the software library)
Johan Kårlin
Posts: 286
Joined: Wed Jun 03, 2020 11:33 am
Location: Kalmar, Sweden

Some cc65 compiler questions

Post by Johan Kårlin »

I have just started with cc65. There is a thorough documentation, fantastic. But here's some questions. Maybe you know the answer to one or some of them? I have v 2.19 for Windows 64-bit downloaded today, nov 13.

1. How stable is the compiler? There are no proper releases, just what seems to be daily builds on sourceforge.net. Is this something to worry about?

2. The generated BASIC stub is "531 SYS 2061". Is something wrong or why "531"?

3. The generated code starts with switching to lower character mode. I can't find a way to avoid this. Is it possible? Of course, I can just switch back, but I think it is worth a question.

4. I tried to make a hello-world-program with just one line of code, a call to print(). I can run it once without any problems. The second time it crashes and I end up in the monitor. Is this how it should be? Can you just run the compiled programs once?

5. I tried to load a file by calling the kernal LOAD. It works fine. If I remove the file, it works too, my code handles the error, but I get a short blinking red line in the upper right corner of the screen. It is not part of the text layer and layer 0 is disabled so it must be something the emulator comes up with on its own? The strange thing is that the same assembly code works in ACME without any red line turning up.
Microdriver
Posts: 14
Joined: Tue Sep 19, 2023 9:58 pm

Re: Some cc65 compiler questions

Post by Microdriver »

Johan Kårlin wrote: Mon Nov 13, 2023 1:54 pm3. The generated code starts with switching to lower character mode. I can't find a way to avoid this. Is it possible? Of course, I can just switch back, but I think it is worth a question.
Yeah, noticed that too. Don't know how to avoid it yet. In this demo, he does:

Code: Select all

// Switch back to the uppercase character set.
cbm_k_bsout(CH_FONT_UPPER);
Johan Kårlin wrote: Mon Nov 13, 2023 1:54 pm4. I tried to make a hello-world-program with just one line of code, a call to print(). I can run it once without any problems. The second time it crashes and I end up in the monitor. Is this how it should be? Can you just run the compiled programs once?
No, you should be able to run it several times. Did you call "printf()" or "puts()"? Better show the exact code.
Johan Kårlin
Posts: 286
Joined: Wed Jun 03, 2020 11:33 am
Location: Kalmar, Sweden

Re: Some cc65 compiler questions

Post by Johan Kårlin »

Microdriver wrote: Mon Nov 13, 2023 4:24 pm No, you should be able to run it several times. Did you call "printf()" or "puts()"? Better show the exact code.

Code: Select all

#include <stdio.h>

void main() {
    printf("Hello world!");
}
This is the code. I tried with puts() too, it made no difference. I compile with: "cl65 -t cx16 main.c -o main.prg". Strange, it shouldn't just be me having this problem. Maybe all Windows users have it or something. Maybe cc65 isn't updated for r46. The header file x16.h says it is for r39.
Microdriver
Posts: 14
Joined: Tue Sep 19, 2023 9:58 pm

Re: Some cc65 compiler questions

Post by Microdriver »

I'm compiling on Linux and have that problem too. Also, when I return 0 from main().
Well, maybe when running the assembly code that was compiled from the C code, it changes something in the memory, so when the memory address is called again, it finds different bytes and does something unexpected. Just a guess.
Johan Kårlin
Posts: 286
Joined: Wed Jun 03, 2020 11:33 am
Location: Kalmar, Sweden

Re: Some cc65 compiler questions

Post by Johan Kårlin »

Ok, at least it's not just me then. Yes the code seems to change something that cannot be left in another state.

When it comes to the mystic "531" row number, I have discovered something: If I get it right you can define the BASIC stub yourself. It is done in the demo for ZSMKit. First, a segment is defined in the configuration file, then the content of the segment is defined in the source code. https://github.com/mooinglemur/zsmkit/b ... src/main.s
kelli217
Posts: 517
Joined: Sun Jul 05, 2020 11:27 pm

Re: Some cc65 compiler questions

Post by kelli217 »

cc65 is notorious for not leaving the machine set up correctly to run BASIC; it trashes various system variables and vectors when doing its own runtime setup. You pretty much have to call for a full system reset on exiting your program.
DragWx
Posts: 318
Joined: Tue Mar 07, 2023 9:07 pm

Re: Some cc65 compiler questions

Post by DragWx »

I have the same issue, every time I've used cc65 to make even simple test programs, it crashes to monitor if I try to run them a second time. The X16 doesn't have any standard way of actually terminating a program, and even the C64 usually required you to press the reset button to exit a program, so I just figured ASM programs "cleanly" terminating to BASIC was going to be an exception rather than a rule. :P

Getting a nightly build seems to be fine, I don't think the X16 portion of cc65 is changing very much unless it's one of us doing a pull request or something. :P
User avatar
AndyMt
Posts: 326
Joined: Sun Jun 21, 2020 3:02 pm
Location: Switzerland

Re: Some cc65 compiler questions

Post by AndyMt »

Johan Kårlin wrote: Mon Nov 13, 2023 1:54 pm 5. I tried to load a file by calling the kernal LOAD. It works fine. If I remove the file, it works too, my code handles the error, but I get a short blinking red line in the upper right corner of the screen. It is not part of the text layer and layer 0 is disabled so it must be something the emulator comes up with on its own? The strange thing is that the same assembly code works in ACME without any red line turning up.
I think that's just on the emulator, isn't it? It simulates the light on the disk drive. If you look closely you will see that it also lights up very briefly when you access a file successfully. If there is a file error of any kind, the light will blink. You have to reset the error state for it to disappear.
I haven't found out how myself, though... using READST etc. doesn't do anything. I assume using the command channel (15) could solve this.
Johan Kårlin
Posts: 286
Joined: Wed Jun 03, 2020 11:33 am
Location: Kalmar, Sweden

Re: Some cc65 compiler questions

Post by Johan Kårlin »

kelli217 wrote: Mon Nov 13, 2023 9:56 pm cc65 is notorious for not leaving the machine set up correctly to run BASIC; it trashes various system variables and vectors when doing its own runtime setup. You pretty much have to call for a full system reset on exiting your program.
Thanks for telling me. Then I can let this go. It is not a big deal, it is just that I am - quite unnecessary - attached to the idea of returning the machine in an uncorrupted state. I guess this marks the end of making games with a "quit game" option ;).
DragWx wrote: Tue Nov 14, 2023 12:49 am Getting a nightly build seems to be fine, I don't think the X16 portion of cc65 is changing very much unless it's one of us doing a pull request or something. :P
Good to hear. Hopefully, there will be no problems. The compiler has been around for such a long time, so I guess breaking changes are unlikely. But still, I would prefer official releases.
AndyMt wrote: Tue Nov 14, 2023 7:06 am I think that's just on the emulator, isn't it? It simulates the light on the disk drive. If you look closely you will see that it also lights up very briefly when you access a file successfully. If there is a file error of any kind, the light will blink. You have to reset the error state for it to disappear.
That must be it. It feels like I should have thought about that myself, but it was a long time since I used a disk drive. Great, I can check that off the list of things to sort out.
voidstar
Posts: 402
Joined: Thu Apr 15, 2021 8:05 am

Re: Some cc65 compiler questions

Post by voidstar »

Good questions. I've been using cc65 for a while (few years), including the PET, Apple2, C64, and X16 target platforms (with Windows, can't speak to how it handles on other platforms). [ see destinyhunter.org ]
Johan Kårlin wrote: Mon Nov 13, 2023 1:54 pm 1. How stable is the compiler? There are no proper releases, just what seems to be daily builds on sourceforge.net. Is this something to worry about?
Support for float or double was never added. On lemon64.com I ran into a contact that had a branch of cc65 that did include float-type support. There was talk of rolling that into the main baseline, but I've not seen action on it. The specific use case we were doing that solar system modeling, where anything dealing with astronomical modeling ends up with very large numbers. Without getting to sidetracked: there are many situations when one thinks they need floating point, but really don't (even when dealing with currency, there are other ways to re-think a solution {like just work in units of cents, etc.}).

On github there are cc65 folks that will respond to Issues. One of the last Issues I raised is they don't really support the original PET 2001 as a target platform (there are zeropage differences with that systems original ROMs). They recognized the issue, and summarized what fixes would be needed, but the "user base" on that platform is very small I don't think an official fix was merged in. But I was content enough to have it verified there was an issue and not something I was just doing wrong. I wouldn't go demand/requesting "upgrading" or modernizing the C language support that it has.

I don't think I've actually done nested/recursive calls in cc65. That's a "C thing to do" but I generally avoid such solutions and stick with iterative ones. But aside from that, the coverage of C language support seems "pretty stable." You can do loops, functions even with variable number of arguments, records, pointers, inline assembly.

But there can be some confusion on where one gets their cc65 build from. You mentioned sourceforge? I haven't actively looked recently, but those prebuilds could be different than what is offered on github. Not necessarily bad, but just be aware that "someone else's cc65 might not be exactly like yours" kind of stuff can happen.

Quick note while thinking of it: in cx16.cfg (when using the Commander X16 as target), the "baseline" stack reserve may be set at $2000 which can be way more than most people need. So to get more codespace/RAM, one quick easy thing to do is to reduce that down. If you're not calling a lot of functions or they don't have many passed arguments, you could drop it to even under $100.

Johan Kårlin wrote: Mon Nov 13, 2023 1:54 pm 2. The generated BASIC stub is "531 SYS 2061". Is something wrong or why "531"?
I've noticed this also and never really questioned it or had it bother me. Reasonable question at the github Issues or Discussions item, or searching if they already have an answer. Can't recall if they do this same 531 on the other platforms or if this was some arbitrary CX16 decision (or a side effect of how the CX16 has evolved from when CX16 support was originally added into cc65).

Johan Kårlin wrote: Mon Nov 13, 2023 1:54 pm 3. The generated code starts with switching to lower character mode. I can't find a way to avoid this. Is it possible? Of course, I can just switch back, but I think it is worth a question.
On the cc65 I have, I think this is a side effect of bringing in cx16.lib . They'll have their own entry point to do things like parse "command line arguments" and initialize their runtime, which from there then jumps into your actual _main on wherever it ended up placed by the linker. I've not recompiled/built that cx16.lib (I'm not a die hard open-source fanatic; not a bad thing, just some do insist on only running things that they can or have prebuilt themselves and I can appreciate the philosophy of that). I think all the necessary .s files are there to do a build of the cx16.lib (in a libsrc folder). X16 makes it easy to change text modes, so for example in cc65 you can do this:

#define ENABLE_ISO_MODE \ __asm__("lda #$0F"); \ __asm__("jsr $FFD2");

Just find the character code that corresponds to the text mode you prefer. The main issue is really that by the time you get to your _main, you've lost the "original mode" that the user started your program in. There is an address to query what the current text mode or screen mode is, but as you mentioned, the cc65 core has changed/set it by the time you're able to query that. So the elaborate workaround is a pre-loader or modified autoboot.x16 that queries this, stores it somewhere, before loading your main .PRG, etc. Not fun.

But then, it gets a little worse: keyboard scan codes, display codes, and what "character set" the file I/O routines use. Every compile has to deal with this (the "character set"). Loosely we can say cc65 all uses PETSCII and the upper/grx variety. But you may eventually just run into frustrations (like what values to use in case statements while polling keyboard input, versus parsing file input). One could probably write a book on it, and each users use-case may be a little different (relative to keyboards being used, international systems, etc). So it just takes some trial and error to "dial in" what works for you. This could be why the core cc65 switches to that mode, as everything is setup to "just work" with that. So while you can change that behavior, it could have some unexpected ripple effects elsewhere.

NOTE: but bottom line is, eventually for performance reasons, you'll want to learn about "display codes." All the built in C library stuff isn't designed around display codes, so they are inherently slow for that reason. I can share the "library" (not an actual .lib, but just a .h with a bunch of #define macros) that I help to speed navigation and interaction with the text screen (and timers) a bit faster -- but in general I think most developers build up their own tailored equivalent of that. Attached is a simple starter example.



I guess to answer your specific question, short of rebuilding cx16.lib, no I don't think the mode switch can be avoided by a setting or simple .cfg change somewhere.

Johan Kårlin wrote: Mon Nov 13, 2023 1:54 pm 4. I tried to make a hello-world-program with just one line of code, a call to print(). I can run it once without any problems. The second time it crashes and I end up in the monitor. Is this how it should be? Can you just run the compiled programs once?
Yep, same experience here. However, pay attention to your #includes. I've found that if you #include nothing (which then means your _main is basically doing nothing, except maybe a for-loop and simple integer calculations-- maybe a POKE) - in that case, I've found that I can re-run the PRG without issue (i.e. RUN, program "naturally exits", then I can RUN again). So it's not an inherent problem about cc65, but something influenced by one of the #incude's. I can't recall which specific one. The system is sensitive to a few address regions (zero page, kernal reserved, then BASIC itself has a few sensitive addresses). That's a thing of C, various ways to get code executed before your _main entry point (like even just by initializing global variables, it can be an inherit part of your laded .PRG but arranged in a way that blasts over an important system region).

The other thing I've noticed is that you don't have to do a full reboot. CTRL+ALT+RESTORE, then just re-loading your .PRG is often good enough to be able to RUN again. On the hardware, there is one type of reset that you can hear (causes a relay to click), the other is a "soft" reset that doesn't clear/alter as much of the memory (and you won't hear that relay click). The system is still stable enough to at least issue another LOAD.

But anyhow, yes it is an issue - and again it could just be how the CX16 system has evolved since the cx16 target support was initially added into cc65 (which I think it is amazing that cc65 still mostly works with the cx16, but the "startup sequence" probably does need a good dusting off. There may be some clever way to inject some .s to get ran before your _main and maybe save more of the machine state, and have your exit code use that to revert the state. This issue does make convenient utilities difficult to develop.



Johan Kårlin wrote: Mon Nov 13, 2023 1:54 pm 5. I tried to load a file by calling the kernal LOAD. It works fine. If I remove the file, it works too, my code handles the error, but I get a short blinking red line in the upper right corner of the screen. It is not part of the text layer and layer 0 is disabled so it must be something the emulator comes up with on its own? The strange thing is that the same assembly code works in ACME without any red line turning up.
This caught me too. I haven't read through all the other replies so this was probably already answered... The emulator uses this flashing red to simulate the hardware light that is around the reset switch (David once briefly mentioned his preference of changing that light to red on the hardware, as the Lazer3D case chose to use blue lights instead). This was a C64 behavior (where they probably used red), so the disk drive can give status that something didn't work quite right on the last operation. It's a little annoying (in reality) where you might get that stuck flashing for a long time, there is no timeout about it. There is probably some kernal call to clear the last error (probably just a CLOSE command in BASIC), or just issue a correct OPEN (valid filename, etc). There has been a lot of discussion repeated in Discord about the need to check Device 15 for actual OPEN status.

In my XINFO project, I'm at a point of using the cbm.h stuff in cc65 to do cbm_open/read/close for File IO and checking the status - so I can refer to that as an example. But similar to working with the display: for performance, the OPEN KERNAL call is probably the way to go, so most "shops" (independent developers) will probably want to build up their own #define repository to help with those calls. stdio.h and fopen does work relatively fine, but will also be slow and have certain limitations (like filenames limited to 16 characters was one limitation I ran into with it, whereas the cbm.h stuff was not limited {well, probably 255 char limited}).


So your questions are good, and mostly yes: that's just the state of cc65 currently on the cx16. It's not bad, you can quickly develop up some interesting things. But there are certainly limitations. You don't want to stay on the C standard library stuff for very long - although things like malloc, printf, sscanf, etc. all do work. I've only just started looking into bank switching from within cc65 - it won't have any provisions for this "automatically" so the code space is limited to ~30K for the time being. You can manually switch banks and POKE (or "binary load") some code, and JSR over to it -- nothing prevents that. Just the cc65 linker won't do this "automagically" for you.

A "graceful exit" back to a working system is a hallmark of a professional and well developed application and polished development environment. I think the cx16.lib is close to being able to do that, it's not an inherent fault of cc65. And like the cx16, all the cc65 development is worldwide volunteers - as more interest in this target comes about, the right expert to resolve some of this may come about.
Attachments
core_x16.h
(10.07 KiB) Downloaded 382 times
Post Reply