Jump to content
sebassco

My First Steps with the X16: Questions and goals!

Recommended Posts

Hey guys!

So, I am starting to upload my code here: https://github.com/sebassco-dp/x16tutorial

I have not started with the wiki section, but I hope to do so after I finish the BASIC guide. Since I ran into some trouble at work, my throughput has been a little affected, but hopefully I can make up for that this week.

You will see most of the source files have the same examples than the ones on the C64 guide, but I have made some twists to some of them. After finishing to understand memory management, I will upload some stuff of my own there 🙂

 

Hope you like it!

  • Like 2

Share this post


Link to post
Share on other sites

Sounds good! I hope you're going to explore the C (CC65) route -- for some reason, that's the route that seems best to me. When I dive into this, that's probably the route I'll go. I need some good tutorials though to get started.

  • Like 1

Share this post


Link to post
Share on other sites

Hi @maktos!

Yes, I will! In fact, if everything goes as expected, October will be the month I start looking into C. And yes, that seems the best route for me too, but I wanted to explore the world of BASIC first, and understand a little bit on how to operate this machine in particular.

At the moment, I am taking a final look at some graphics tutorials on https://www.8bitcoding.com (Thanks @SerErris for the tip!) and will start writing the BASIC 'noob' tutorial. After finishing that, cc65 is what comes next!

You can take a look at my latest code additions here 🙂

Share this post


Link to post
Share on other sites

Be aware that C is not a good language for the C64/X16/6502 in general. It is very heavy on all the calls and context switches, where the 6502 is not very good at. The stack is also only 8 bit and only 256 bytes in total and cannot get extended. So you need to create a software stack (which is exactly what cc65 is doing) and that is really slow to use. 

Yes you can program in high languages - and it will be faster than interpreted basic. However I assume (not tested) that compiled basic would be faster than any C code.

Edited by SerErris
  • Like 2

Share this post


Link to post
Share on other sites

Yeah I learned this while creating my Prog8 language too.  I think it has the potential (1) to be faster than compiled C on the 6502, because it includes some high level concepts that it can translate to quite optimized assembly (such as iterating over the elements of an array or string, a repeat statement, and several builtin functions tweaked for the 6502). But the thing that is slowing it down the most is the support for evaluating arbitrary expressions.   I've made several optimizations recently but the majority of non-trivial expressions have to be evaluated via a software stack and that is indeed very slow compared to directly calculating things in-place.

 

edit actually, my current development version of Prog8 has actually become slightly faster than cc65 at a couple of silly benchmarks .  While that's nice and all, it's still quite a bit slower at others.

 

1):  I'm a noob at writing compilers so my code generator is probably nowhere near as advanced as the one from a proper  C compiler. But I'm purely looking at the language itself and how it is structured

Edited by desertfish
  • Like 1

Share this post


Link to post
Share on other sites

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.

Edited by sebassco

Share this post


Link to post
Share on other sites

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.

Edited by SerErris
  • Like 1

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Posted (edited)

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.

Edited by desertfish
  • Thanks 1

Share this post


Link to post
Share on other sites

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.

  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites
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.

  • Thanks 1

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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...

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...

Important Information

Please review our Terms of Use