My First Steps with the X16: Questions and goals!
My First Steps with the X16: Questions and goals!
Hey guys!
Yes, for sure it will not be the same as compiled BASIC. But it helps me getting rid of the gap I have between my knowledge of BASIC and the understanding of the X16 architecture. It may not be my default go-to in the future, but as for now, it is the best angle from which I can start creating some working stuff.
My First Steps with the X16: Questions and goals!
That is a good approach. Just wanted to make you aware of the fact of limitations of the Architecture in regards of high languages. Where the Amiga was optimal to use for C the C64 never was and the X16 compensates a bit by processor speed with factor of 8 but has the same limitations.
The compiled BASIC was just a reference for comparison. It was not meant as a recommendation to go that way. Compiled Basic is for my point of view the way to go, if you really do not want to dive into Assembler. But it is still very slow.
For serious game development IMO Assembler is still required. Maybe the main game loop can be written in C, but the intensive math and graphics routines should then be done directly in Assembler to avoid C functioncalls.
My First Steps with the X16: Questions and goals!
On 9/27/2020 at 2:10 PM, SerErris said:
However I assume (not tested) that compiled basic would be faster than any C code.
This was unexpected to hear. I'm not a fan of cc65, but I had better thoughts about it. I actualy thought cc65 compiles code that is closer to assembly code in terms of speed. And BASIC code, even compiled, always much slower than assembly. Am I wrong?
Dear All, please share you knowlege about this.
- desertfish
- Posts: 1096
- Joined: Tue Aug 25, 2020 8:27 pm
- Location: Netherlands
My First Steps with the X16: Questions and goals!
Disclaimer: I'm far from a compiler writer expert. That said, I know that the execution model of C and C-like languages depend on calling subroutines, that have their own variables including the subroutine's parameters. These are usually allocated on the stack or dynamically in the global memory heap. So that for every call to a subroutine, a new "frame" is created to contain those variables, and that "frame" is freed once the subroutine returns to its caller. This ensures the subroutine has its own private piece of memory for its own variables to work with and that it doesn't clobber variables elsewhere in the program.
That mechanism doesn't exist in Basic. All basics I know have only a pool of global variables and a subroutine is no more than a gosub to a different line in the program -- all variables are shared across the whole program.
The latter is much easier for the 6502 cpu to deal with because it has only very few registers and instructions and very limited instructions to handle the stack. So compilers for C-like languages have to jump through quite a few hoops to create that stack based execution model for their programs. Which I think is what is causing the biggest problems for those compilers.
So yeah I agree that compiled basic can potentially be faster than compiled C however this will heavily depend on the code itself too. Some things are very awkward to express in basic as well and will likely result in massively inefficient assembly code even when compiled....
edit: for Prog8 (which is more or less a C-like language) I'm struggling with that stack based execution model too. In an attempt to optimize the generated code Prog8 has a limitation on how the variables and parameters for subroutines are allocated (namely: only once, statically placed in memory somewhere). With that we loose the ability to write recursive function calls unfortunately.
My First Steps with the X16: Questions and goals!
My statement was more based around expectations to say what to expect.
@desertfish is pretty much right on it and the reasons why C is pretty much inefficient on the 6502. BASIC has its own inefficiencies and is even compiled not considered fast.
What I wanted to say is - If you need speed, Assembler is the only performance efficient way to do it. If it comes to complex calculations Basic can get you started, C can get you also the fragments going, but if you want to optimize on performance you need to write some assembly code.
It would be great if we would have a debugger in the emulator that also can do profiling (how many cycles in which part of the program). If that would exist, you could then optimize the code where it makes the biggest impact and ignore the code you are just calling once or where you spend in total very few amount of time (in percent). The typical consideration is: 90% of execution time is spend in 10% of the code. That is what you want to optimize.
So C with hand crafted Assembly routines optimized for speed might be a good and efficient procedure. However without a profiler you will never know.
My First Steps with the X16: Questions and goals!
17 hours ago, SerErris said:
So C with hand crafted Assembly routines optimized for speed might be a good and efficient procedure. However without a profiler you will never know.
I fully agree on this statement. I use C with some assembler. But even without profiler you can get some indications by looking at the generated assembler code. I do this in case I run into a performance issue. Which until now were surprisingly few. Even though "Invaderz" handles a lot of sprites at the same time, including movements and collision detection, until now these parts didn't require assembler optimisations. Ok - I always consider what the compiler will do with C code I write. So I probably optimise anyway.
Until now I only coded the interrupt handlers in assembler - for Vera hardware collision detection and for sound effects.
My First Steps with the X16: Questions and goals!
On 10/3/2020 at 5:56 PM, desertfish said:
That mechanism doesn't exist in Basic. All basics I know have only a pool of global variables and a subroutine is no more than a gosub to a different line in the program -- all variables are shared across the whole program.
QBasic (two steps after the CBM V2 generation of Microsoft Basic) has variables that are local to procedures and subroutines. However, I do not know whether there was a local variable stack, or whether that was just a private namespace.
On approach is to have a distinct recurse() function which copies the functions current local variables to a frame stack, uses the local variables for the call, gets the return value, and then copies the local variables from the frame stack. So then code that wants to pay the cost of re-entrant code can do so, without forcing all code to pay that cost.
My First Steps with the X16: Questions and goals!
Hi everyone!
I finished reviewing BASIC and will start writing the first pages of the Wiki. I hope it renders some aid to anyone new to the system as I am ?
Here's the link if you want to check out the examples! https://github.com/sebassco-dp/x16tutorial/tree/master/BASIC
I will appreciate your comments!
My First Steps with the X16: Questions and goals!
On 10/3/2020 at 4:56 AM, desertfish said:
edit: for Prog8 (which is more or less a C-like language) I'm struggling with that stack based execution model too. In an attempt to optimize the generated code Prog8 has a limitation on how the variables and parameters for subroutines are allocated (namely: only once, statically placed in memory somewhere). With that we loose the ability to write recursive function calls unfortunately.
Haven't thought this through fully, but perhaps that's one reason why tail recursion is so important to those LISP fanatics...