Jump to content

vpoke() for cc65


rje
 Share

Recommended Posts

Painful, I know.  If I shoved this into asm() statements would it be better?

#include <peekpoke.h>
#include "vpoke.h"

void vpoke(uint16_t address, uint8_t value)
{
    POKE( 0x9f20, address & 0xff ); // LSB
    address >>= 8;
    POKE( 0x9f21, address & 0x0f ); // 4 low bits of the MSB
    POKE( 0x9f22, 1 );              // VERA "bank 1"
    POKE( 0x9f23, value );
}
Edited by rje
Link to comment
Share on other sites

31 minutes ago, rje said:

If I shoved this into asm() statements would it be better?

Unless cc65 is smart enough to optimize out the bit shifts and AND operations (which is unlikely), an assembly version of this function would be much faster, as the MSB and LSB of the address could easily be accessed separately.

34 minutes ago, rje said:

POKE( 0x9f21, address & 0x0f ); // 4 low bits of the MSB

I don't understand why the code is masking off the upper bits of the MSB, as VERA addresses are 17 bits (8 bit LSB + 8 bit MSB + 1 bit bank selection).

Link to comment
Share on other sites

Posted (edited)
2 minutes ago, Elektron72 said:

I don't understand why the code is masking off the upper bits of the MSB, as VERA addresses are 17 bits (8 bit LSB + 8 bit MSB + 1 bit bank selection).

VERA addresses are indeed 17 bits; however, we have to set those 17 bits across three bytes: 0x9f20 gets the LSB, 0x9f21 gets the "middle", and 0x9f22 gets the bank.  That points us at our destination address in VERA.  THEN we can write the byte.

Edited by rje
Link to comment
Share on other sites

1 minute ago, rje said:

VERA addresses are indeed 17 bits; however, we have to set those 17 bits across three bytes: 0x9f20 gets the LSB, 0x9f21 gets the "middle", and 0x9f22 gets the bank.  That points us at our destination address in VERA.  THEN we can write the byte.

$9F21 accepts 8 address bits; ANDing the MSB with 0x0f would discard bits 12-15 of the address.

Link to comment
Share on other sites

I don’t know what poke and peek compile to in assembly, but here’s a way to make it be simple under the hood:

(*(uint8_t*)0x9F40) = 0x08

= POKE $9F40,8

If you use an explicit address a lot, then you can “name” it with a #define

#define YMreg (*(uint8_t*)0x9F40)

YMreg = 8;
 

Of course, common system things like VERA, VIA, etc already have these in cx16.h but if there’s a particular address you want to access that’s not already defined in a macro for you, that’s how to do it.

 

Link to comment
Share on other sites

Posted (edited)

Yeah, that's basically how cc65 does it.

 

Just so I can practice thinking about it, here's how cc65 does it.  The header file cx16.h has a nice pile of VERA stuff defined.  The main bit starts here:

#define VERA    (*(volatile struct __vera *)0x9F20)

So it impresses the struct __vera onto the VERA registers.  That structure is really nice, basically laying out the registers so we can simply assign to them directly.  It starts like this (and goes on and on):

/* A structure with the Video Enhanced Retro Adapter's external registers */
struct __vera {
    unsigned short      address;        /* Address for data ports */
    unsigned char       address_hi;
    unsigned char       data0;          /* Data port 0 */
    unsigned char       data1;          /* Data port 1 */
    unsigned char       control;        /* Control register */
...

 

So for example if I wanted to store a byte on VERA at $1FC10, I'd do this (thank you @Greg King!)

VERA.control = 0;               // point to Data port 0.
VERA.address = 0xfc10;          // the address inside VERA.
VERA.address_hi = 1;            // + the "bank" address inside VERA ($10000)
VERA.data0 = the_byte;          // my data on Data port 0.

 

NOTE: the .address_hi field is also where you would set the auto increment.  So it's not 100% clean... but it's very helpful.

Edited by rje
Link to comment
Share on other sites

1 hour ago, rje said:

Yeah, that's basically how cc65 does it.

 

Just so I can practice thinking about it, here's how cc65 does it.  The header file cx16.h has a nice pile of VERA stuff defined.  The main bit starts here:


#define VERA    (*(volatile struct __vera *)0x9F20)

So it impresses the struct __vera onto the VERA registers.  That structure is really nice, basically laying out the registers so we can simply assign to them directly.  It starts like this (and goes on and on):


/* A structure with the Video Enhanced Retro Adapter's external registers */
struct __vera {
    unsigned short      address;        /* Address for data ports */
    unsigned char       address_hi;
    unsigned char       data0;          /* Data port 0 */
    unsigned char       data1;          /* Data port 1 */
    unsigned char       control;        /* Control register */
...

 

So for example if I wanted to store a byte on VERA at $1FC10, I'd do this (thank you @Greg King!)


VERA.control = 0;               // point to Data port 0.
VERA.address = 0xfc10;          // the address inside VERA.
VERA.address_hi = 1;            // + the "bank" address inside VERA ($10000)
VERA.data0 = the_byte;          // my data on Data port 0.

 

NOTE: the .address_hi field is also where you would set the auto increment.  So it's not 100% clean... but it's very helpful.

This obviously could use a helper function to convert the increment, bank number, and channel number to the correct data values to go in the structure. Using this structure is only mildly better than simply brute forcing it, as you did with your first function (although it needs a bank parameter, which I'm sure you already know.)

Remember, there are 2 data channels in VERA, and using both of them together is a good way to solve certain problems. So that bit needs to be added to any routine that builds the bit masked control data for writes to or reads from VERA.

Edited by TomXP411
  • Like 2
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