Jump to content

Sprite and Sound APIs


rje
 Share

Recommended Posts

1 hour ago, ZeroByte said:

The VERA registers are the VRAM interface. The bit packing / shifting does get crazy. I just made some macros to convert between the various formats.

// Macros to convert VRAM addresses into Hi/Low Addr bytes in SPR regs.

#define SPRlo(a)    ((a)>>5  & 0xff)
#define SPRhi(a)    ((a)>>13 & 0x0f)
#define SPRadr(a)    (SPRlo(a) | SPRhi(a) << 8 )

Heck, I was thinking about using a bitfield struct.  Macros work, too.

 

Link to comment
Share on other sites

there would be plenty of benefits to using a bitfield struct as well. Your program would be able to just use the various fields directly w/o having to bit-pack / unpack all the time. I knew my game wasn't going to require tons of performance, so I didn't bother optimizing that much for speed. I mean, I tried to be conscious of it (I couldn't help myself) but in the end, I was more concerned with doing useful abstractions / generalizations.

Link to comment
Share on other sites

37 minutes ago, ZeroByte said:

there would be plenty of benefits to using a bitfield struct as well. Your program would be able to just use the various fields directly w/o having to bit-pack / unpack all the time. I knew my game wasn't going to require tons of performance, so I didn't bother optimizing that much for speed. I mean, I tried to be conscious of it (I couldn't help myself) but in the end, I was more concerned with doing useful abstractions / generalizations.

There is a lot to be said for source code quality and convenience of using bit fields, but remember that the compiler will be doing packing and unpacking of the fields just like you would have to. That's not a reason to avoid using that feature, but it isn't likely to improve performance (assuming the same technique is used in manually written code as is used in compiler generated code).

Link to comment
Share on other sites

44 minutes ago, Scott Robison said:

There is a lot to be said for source code quality and convenience of using bit fields, but remember that the compiler will be doing packing and unpacking of the fields just like you would have to. That's not a reason to avoid using that feature, but it isn't likely to improve performance (assuming the same technique is used in manually written code as is used in compiler generated code).

This is true - the assembly that cc65 generates to reference/index into arrays and structs and so forth isn't exactly free from clutter - there're several JSRs to little routines it uses, and if your data structure isn't sized in power-of-two-sized chunks, then it gets ugly under the hood.
The most efficient data structures (as I read somewhere) are structs of arrays instead of arrays of structs - at least for 6502 targets.

But if you do a good bit of dipping into the various values of bit-packed / shifted fields, but store them as arrays of uint8_t bytes, then you potentially only have to pack them once per screen update. It depends on how your code does things, obviously.

  • Like 1
Link to comment
Share on other sites

Posted (edited)

Okay, then,

ASSUME I have to use the registers, 
THEN I'm thinking of these functions:
 

void sprite_define(
        int8_t  spritenum,
        int8_t  mode,
        int16_t block,
        int8_t  collision_mask,
        int8_t  layer,
        int8_t  height,
        int8_t  width);

void sprite_palette(
        int8_t spritenum,
        int8_t  palette_offset );

void sprite_vflip(int8_t spritenum);
void sprite_hflip(int8_t spritenum);

void sprite_move(
        int8_t spritenum,
        int16_t x,
        int16_t y);

 

Edited by rje
Link to comment
Share on other sites

Posted (edited)
46 minutes ago, Scott Robison said:

One thing that I think might be better for an API (esp on 6502) would be to pass a pointer to a structure instead of a bunch of individual values.

I totally grok that, good catch, thank you.


 

Edited by rje
Link to comment
Share on other sites

Posted (edited)

Now I'm looking at Matt's tutorial to see how he addresses VERA RAM.

I. IMAGE DATA LOAD

At least I can bypass his load code, since (I think) I can load straight to VERA, e.g.:

   cbm_k_setnam("xebec-32x32.bin");
   cbm_k_setlfs(0,8,0);
   cbm_k_load(TO_VERA, 0x4000);

 

II.  SPRITE CONFIG

OK.  Ok.  

GIVEN a target memory address "address" for VERA, and data "the_byte" to move in there:

uint8_t low = address & 0xff;     
uint8_t high = (address >> 8 ) & 0xff;

POKE( 0x9f20, low );
POKE( 0x9f21, high );
POKE( 0x9f22, 1 );
POKE( 0x9f23, the_byte );
 

Edited by rje
Link to comment
Share on other sites

Posted (edited)

So the cumbersomeness of addressing VERA makes me want to split up the API differently:

spr_define(s,*cfg) -- sets mode and address, height, width, palette offset (bytes 0, 1, 6, and 7).
spr_pos(s,*pos) -- sets x, y position (bytes 2, 3, 4, 5).
spr_vflip(s), spr_hflip(s) -- flips along x or y axis (byte 6)
 

Edited by rje
  • Like 1
Link to comment
Share on other sites

1 hour ago, rje said:

Now, I'm looking at Matt's tutorial to see how he addresses VERA RAM.

II.  SPRITE CONFIG

OK.  OK.  

GIVEN a target memory address "address" for VERA, and data "the_byte" to move in there:

uint8_t low = address & 0xff;     
uint8_t high = (address >> 8 ) & 0xff;

POKE( 0x9f20, low );
POKE( 0x9f21, high );
POKE( 0x9f22, 1 );
POKE( 0x9f23, the_byte );

#include <cx16.h>
...
VERA.control = 0;
VERA.address = address;
VERA.address_hi = 1;
VERA.data0 = the_byte;

It compiles to the same Assembly code.  But, it looks more C-like, less BASIC-like.

cc65 also has vpeek() and vpoke() functions.  They directly touch VRAM and internal registers.

  • Thanks 1
Link to comment
Share on other sites

Posted (edited)
3 minutes ago, Greg King said:

#include <cx16.h>
...
VERA.control = 0;
VERA.address = address;
VERA.address_hi = 1;
VERA.data0 = the_byte;

It compiles to the same Assembly code.  But, it looks more C-like, less BASIC-like.

cc65 also has vpeek() and vpoke() functions.  They directly touch VRAM and internal registers.

 

First: beautiful, thank you.  I assume there's a way to set the auto-increment?

 

Second: why aren't these functions in the DOCUMENTATION?  Am I looking in the wrong place?? https://cc65.github.io/doc/funcref.html

 

Edited by rje
Link to comment
Share on other sites

4 minutes ago, Greg King said:

cc65 also has vpeek() and vpoke() functions.  They directly touch VRAM and internal registers.

 

Oh heck, cx16.h has ALL KINDS OF GOOD STUFF.

That's what I get for not reading the header file....  Silly me for relying on documentation.

 

Link to comment
Share on other sites

14 minutes ago, rje said:

First: beautiful, thank you.  I assume there's a way to set the auto-increment?

Second: why aren't these functions in the DOCUMENTATION?  Am I looking in the wrong place?? https://cc65.github.io/doc/funcref.html

Currently, the increment/decrement must be or'ed into the address expression that's given to vpeek() and vpoke().

No one has taken the time to document a lot of the functions that are available in cc65's libraries.  (Usually, someone finds a function in a header, learns that it's very useful to him, notices that it's not in the doc, then submits a patch to "funcref.sgml".)

28 minutes ago, rje said:

Oh heck, cx16.h has ALL KINDS OF GOOD STUFF.

Yep.  But, it isn't complete.  For example, there are no constants for configuring sprites.  "cx16.inc" (for Assembly programming) has much more of that stuff in it.

  • Thanks 1
Link to comment
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.

 Share

×
×
  • Create New...

Important Information

Please review our Terms of Use