Jump to content


  • Posts

  • Joined

  • Last visited

  • Days Won


Everything posted by svenvandevelde

  1. REL files used to be loadable in segments, but cannot recall a file that can be "seeked" like in other systems.
  2. @Stefando you have an example of such a trampoline program in low ram?
  3. JSRFAR does basically the same thing your code does, it's just more complicated because it needs to be more general purpose. I'm sorry but this feedback is not completely correct. It will run in main memory but cannot work in a bank. When calling code from bank in an other bank, jsrfar must be used
  4. Now I get it! That is an answer. So when in bank 1, you cannot switch to bank 2 easily running code in bank 1. Once sta 0 is executed with accumulator value 2, the jsr will never be executed... damn .... complicated! This needs a much better explanation on the cx16 manual!
  5. Also .. why is there one jsrfar routine in the kernal and no two? One for calling ram banked code and one for calling rom banked code? It would save some branches and logic. Also would add one input parameter whether to preserve registers or not ... like setting the decimal flag and if set, not register preservation using stack would be done in jsrfar? I mean, when you call normal kernal routines, registers are neither preserved ... or maybe in doing understand the jsrfar enough ...
  6. So the method I outlined earlier is not suitable for assembler generated by a compiler as easily inline bank hopping logic won't work.
  7. I need to start moving code into banks as lots of low memory gets exhausted. Im hitting the $9200 boundary already... This code, for example, addresses routines like a hash table that is called 60 times multiplied by the amount of objects on the canvas., per second. Or level specific code to move objects over the screen in specific patterns or behave in specific ai logic. So yes it needs to be fast. There are also slower routines possible like level loading which can take more time. But I don't really need jsrfar at all(I think). A call into rom is simply setting zp 1 and jsr the rom function address, which works well. Upon rts I just reset the zp 1. A call from one RAM bank to an other RAM bank is perfectly possible by setting zp 0 and then jsr the address. Upon rts I just reset the zp 0. So what is about this jsrfar?
  8. Why is jsrfar needed at all for switching running code between ram banks ... Isn't it enough to just lda $00 pha lda #bank sta $00 jsr address pla sta $00 Why is JSRFAR needed really?
  9. And this jumping between banks is too be avoided. But jumping from low ram to code in a bank and back should not be such a hard thing to do, right?
  10. It all comes down to selecting which of the routines you would position as "far" and which routines need to be kept in low memory. Also to run code in banks, this requires to have the data used by the code in the bank to be "in" the bank. So running code in a bank requires to have the data for the code either in the same bank, or in an other bank. In other words, having a logic that runs in ram banks, and switching between ram banks can become very tricky. But if the code and the data to run the code is in the same bank or in low memory, then it should be fine, right?
  11. Thanks Ed. Note that it is not only the code of switching but also the code of returning from the switch?
  12. How many extra cycles does a JSRFAR call add compared to a normal jsr in low memory? I need to know this because want to use JSRFAR calls within logic to move sprites around 60 times per second.
  13. My condolences. May he rest in peace and he will be remembered through his retro projects.
  14. the cheat sheet contains an error PLA is not a subtract command, it is pull accumulator. Subtract is SBC. Please update it.
  15. cheatsheet mentioned, but now in hyperlink ...
  16. Hello all, In this article I would like to spend some time with you on some C coding techniques, so that your C program uses the 65C02 CPU most efficiently. The principles outlined below also apply to other languages (probably). The subject of this thread is about how to combine arrays and structure C language constructs. There are two distinguished ways how arrays and structures can be combined, which are known in the software world as Arrays of Structures (AoS) compared to Structure of Arrays (SoA) . Please see below the following example: The above compares two different ways of how Arrays and Structures can be combined. On the left, the AoS variable is an Array of Structures. The type definition struct_t only contains scalar data types, while in the variable declaration, AoS is dimensioned as an Array (of Structures). On the right side, you see the other alternative, where the SoA variable is a Structure of Arrays. The type definition struct_t contains the arrays inside the struct (thus, a Structure of Arrays), with the variable declation of SoA being a simple structure declaration. The initialization of the data contents between AoS and SoA is different, the AoS fills out the structure completely one by one, while the SoA fills out the field array completely within the structure. As a result, observe the memory layout in the ligher boxes on the picture, how different the memory is arranged between AoS and SoA. Both variables have the same total size, but the bytes have a different order. And this is very important regarding the 6502 CPU addressing modes. The 6502 supports various addressing modes, which you can find documentation here on the X16 forums, and all over the internet, just google. Since structures are addressed in a linear mode in memory, the most optimal addressing mode to be used are the absolute,x or absolute,y addressing modes (if possible). Of course, absolute,x or y addressing can only be used if the location of the structure is fixed in memory, otherwise indirect indexed addressing or other types of addressing could be used (indexed indirect or self modifying?). However, indirect indexed addressing modes should be avoided as much as possible to my experience, as these constructs clutter code and also consume much more cycles, but more on that in an other post when we discuss pointers and further deep dive into this subject of AoS versus SoA. Let us first compare how the C compiler generates the assembler, utilizing the AoS versus SoA variables, in a simple example below. The examples speak for itself, so let us focus on the resulting assembler, because there is a clear distinction! Note that in this example, both variables are addressed using the index variable, which is an 8-bit value (char). This is important, since the 6502 absolute,x and absolute,y addressing modes require the x or y register to be populated with an 8-bit value. Using 16-bit index values to address arrays is possible, but through completely other assembler contructs (see in later post). In the AoS case, the C compiler has chosen to use the x register for the absolute indexed addressing. Although this solution looks elegant, one can observe that the total assembler code required is a bit longer than the SoA variation. But more importantly, the "reach" of the x register to address the AoS array is far more limited than in the SoA case. The AoS variable can only address 51 elements (256 divided by 5 bytes, floored), while the SoA variable is able to address each field individually, - 128 elements, in case the field has a type containing 2 bytes, like pointers, int, - 256 elements for 8 bit data types like char! - 64 elements if your variable is a 4 bytes in size, like the type long ... (not recommended on 8bit computers). This is a major distrinction. To create data structures for C programs using the 6502 CPU, the Structure of Arrays technique is a preferred technique, compared to Arrays of Structures. Hopefully this topic is useful for others. Please leave your comments or remarks regarding this subject. If you have other ideas or other experiences you want to share about this topic, by all means, feel free to do so for others to pick this up and make better software for the X16. I might edit this first post, and update the text here with your reference if the addition is very useful and adds to the subject. Thanks, Sven
  17. I really liked the song of this when I was a kid. Mesmerising ...
  18. For basic in the vanilla x16 setup? For ram banks? Why would an nmi or other interrupts interfere with basic code like this. I would say that these interrupt routines should be agnostic to basic, no?
  19. Please allow me to quote on this. Since the commander x16 is for educational purposes, it is a requirement that bank switching in basic of the RAM banks needs to be allowed. Functions should be available to allow this switching and it should be reliable. The banks are a key selling point for the x16.
  20. Switching banks is not really expensive. It takes one read in various ways and one write to zero page. Typically in functions, you'll want to set the bank and upon return restore the previous bank. You can do this using the stack. routine: lda $00 pha lda bank sta $00 Upon return... pla sta $00 rts So ... not so expensive actually. It creates a bit of planning using the banks but that's the fun part of it all ... Sven
  21. Sorry, I corrected the link here: Commander X16 ROM Flash Utility: cx16-rom-flash.c (flightcontrol-user.github.io)
  • Create New...

Important Information

Please review our Terms of Use