FCM Insights and Experimentation

For developers wanting to explore FCM (full-colour mode), it can be quite a daunting journey initially, so here’s some pointers along with an ‘experimentation’ walkthrough that will let you peek and poke your way to a better understanding of FCM

 

The gist of FCM/NCM modes

For FCM, each character on the screen is represented by 4 bytes (32-bits worth of information)

  • Two of those bytes are in screen memory (where we'd traditionally put our characters. e.g. at $0800)

  • Two of those bytes are in colour memory (e.g. at $ff80000)

For NCM (nibble colour mode), each two screen characters are defined by these 32-bits)

From here-on in, I’ll refer to the concept of “two of those bytes” as “byte-pairs”.

Where to read about it in the docs?

The section of interest is in "Appendix M >> New Modes >> Displaying more than 256 unique characters via "Super-Extended Attribute Mode"

 

Of particular interest are the two tables shown there. They describe how the bit-fields within the screen byte-pair and the colour byte-pair are defined.

Common Tripping points

The meaning of the byte-pairs change depending on the GOTOX bit!

The major gotchya that trips up newcomers is that the definition of these bit-fields varies depending on whether a certain bit within the colour byte-pair is set or cleared, the GOTOX bit.

That’s why there are two tables:

  • one table for when this GOTOX bit is cleared

  • the other table for when this GOTOX bit is set

Why is it called the GOTOX bit?

Another point of confusion is that you have this bit called “GOTOX”, and you’d be forgiven for thinking that is relates to some re-positioning of characters to a new x-position.

  • Perhaps there was a time (earlier in the project) when the bit's sole purpose was to alter the purpose of screen-byte-pair to specify a new x-position, and in those days it made sense to call the bit GOTOX

  • But now, setting this bit does way more than that, it modifies the purpose of other bit-fields do to other things (y-offsets for chars, rowmask, foreground/background rendering, etc)

So given that it does more than just 'gotox', maybe it needs a new name too, I'm not sure what yet. TOGGLE_FIELDS? ALT_FIELDS?

 

Where is character data located?

Newcomers usually get muddled up at the location where FCM characters get defined, assuming that is from some offset in memory from where all character data is defined.

In reality though, it turns out that that the entire address-space can be used to define character (i.e., think of character data starting at a memory offset of zero!).

This of-course feels a bit silly, as no doubt we don’t want to define characters in the zero-page, and if we want to play nice with BASIC 65’s ram usage, we probably don’t want define characters anywhere within bank 0 or bank 1 either.

Bank 3+4 are locked as read-only for the kernal, but for keen assembly coders that don’t need the kernal, you could potentially unlock this memory and make it writable, and put character data there.

For BASIC coders, that won’t be an option though, so you might instead want to settle for a location within BANK 4 or 5.

It’s not possible to make use of attic ram from the VIC-IV (and the 13-bit character indexes can only access the first 512KB of memory (64 bytes per char x 2^13 = 512KB)

Example:

So let’s say I want to use BANK4, i.e., $4,0000.

  • I need to divide this by 64 bytes ($40) to get the char index
    (since each pixel within the 8x8 character needs one byte in FCM mode)

    • I.e., $4,0000 / $40 = $1000

  • So you need to set:

    • Screen RAM byte 0 to $00

    • Screen RAM byte 1 to $10

 

What’s all this about 16-bit character numbers?!

I feel another tripping point that causes initial confusion is the term used for the bitfield “CHR16”:

 

The docs for CHR16 say it enables "16-bit character numbers", when in reality, it enables “13-bit character numbers” (i.e., bits 0-12 defined in the two fields above)

Whether it's worth changing the name to CHR13 at this stage, I'd lean towards yes, it ought to change to reflect the reality and not mislead, but maybe others might feel the name is locked in now that it has gone to print 😄

Then again, the mega65-book didn't go to print yet, just the user-guide, so maybe there's hope.

 

So, how many unique characters/tiles do I really have?

The documentation describes it as “Support for up to 8192 unique characters”:

Theoretically, that is true. We learnt earlier that we can refer to “13-bit character numbers”, which means we have 2^13 unique characters = 8192.

But in reality this isn’t possible.

  • To get 8192 tiles, that'd mean you'd need the first 512KB of ram available purely to hold character data
    (64 bytes_per_char x 8192 chars = 512KB)

  • …but the MEGA65 is only fitted with 384KB of chip ram, so that gives us a max of 6144 tiles
    (384KB / 64 = 6144)

  • …and some of that ram is going to be needed for the program's code and data, maybe kernal/basic needs too, so would likely end up less than that remaining too

  • Ok, I can now see why some folks here discussed in the past how fcm was a bit of a luxury and why many of them were more inclined to ncm mode 🙂

How many unique tiles/characters do I need to fill the screen?

So in FCM-mode:

  • To fill a 320x200 screen with unique tiles, you'd need 1000 tiles, sounds do-able 🙂

  • To fill a 640x400 screen with unique tiles, you'd need 4000 tiles, a bit more challenging, probably would be an 'assembly-only' thing, consuming BANKS 2,3,4,5 with character data. (no chance in basic)

For NCM-mode, I think all those stats halve and you get more breathing room.

FCM Experimentation via the UART monitor

In this section, I share my experimentation notes, all of my past attempts to peek and poke various registers in order to learn how these byte-pairs (and the bit-fields within them worked).

My notes feature a lot of screenshots, and follow this approach:

  • Try this, observe that…

  • Try this, observe that…

  • rinse/repeat

…so I feel it will be relatively easy for someone to simply repeat the steps I tried and gain similar understanding and insights.

How to access the UART monitor on a real MEGA65

If you’re working on real hardware, you have two options:

  • OK OPTION
    - You can press MEGA+TAB keys to reveal the matrix debugger and type monitor commands within there

    • PROS: in-built option all owners have available to them from the get-go

    • CONS: The monitor is shown as an overlay over the original screen, so you will be jumping in-and-out after each command you type, and this may limit your ability to view the impact of the change in real-time.

  • BETTER OPTION
    - If you have a JTAG/serial adapter connected to your MEGA65, you then debug via USB-serial on your PC using either a serial terminal program like putty, or you could use a fully-fledged debugging tool like m65dbg.

How to access the UART monitor in XEMU

In xemu:

  • right click for context menu

  • Go to "Debug/Advanced >> Start umon on :4510"

  • Then in a console (or in a tool like putty), telnet to localhost on port 4510. E.g.:
    telnet localhost 4510

  • You can then type monitor commands within this telnet session

How to use the UART monitor

For ‘peek’ing, you can use the 'm' command:

m<addr>

 

For ‘poke’ing, you can use the 's' command (it can take multiple values if you want to write several bytes to successive addresses):

s<addr> <val1> [<val2> <val3> ...]

 

So, where can I find your FCM experimentation notes then?

My notes are available as a google doc here:

Gurce's "FCM Experimentation" notes