PEEK and POKE

I want to write programs for my <insert name of cool 6502 based machine here>, but I need something similar to the BASIC PEEK and POKE commands to do anything useful.

There are several possible ways to achieve what you want. The basic method is always to use addresses cast to pointers of the needed type:

    typedef unsigned char byte;
    typedef unsigned word;
    byte B;
    word W;
 
    *(byte*) 0xD800 = 0x12;    /* Store a byte to address $D800 */
    *(word*) 0xC000 = 0x1234;  /* Store a word to address $C000 */
    B = *(byte*) 0xD800;       /* Read a byte from address $D800 */
    W = *(word*) 0xC000;       /* Read a word from address $C000 */

For better readability, you may want to use macros:

    #define POKE(addr,val)     (*(unsigned char*) (addr) = (val))
    #define POKEW(addr,val)    (*(unsigned*) (addr) = (val))
    #define PEEK(addr)         (*(unsigned char*) (addr))
    #define PEEKW(addr)        (*(unsigned*) (addr))

Using the macros above, PEEK and POKE behave very similar to their BASIC counterparts:

    unsigned char B;
    unsigned W;
 
    POKE(0xD800, 0x12);        /* Store a byte to address $D800 */
    POKEW(0xC000,0x1234);      /* Store a word to address $C000 */
    B = PEEK(0xD800);          /* Read a byte from address $D800 */
    W = PEEKW(0xC000);         /* Read a word from address $C000 */

Please note, that the addresses used must not necessarily be constant (as in the examples above). However, while the code generated by the compiler for constant addresses is quite good (they get translated into a series of load and store instructions), for non constant addresses a subroutine is called, so this is a lot slower.

For most platforms, there is even a better way, provided that you're accessing standard I/O chips from your C program. The main include directory contains a header file for each platform that defines in memory structs for the I/O locations. The struct members are usually the registers of the I/O chip, and they do already have the correct type. Accessing the SID (sound interface device) on the C64 using the predefined SID struct would read like this:

    #include <c64.h>
 
    static void StartNoise (void)
    /* Start noise if configured */
    {
	/* Configure noise on voice three if requested */
	if (Effects & efNoise) {
	    SID.v3.freq  = 0x4000;
	    SID.v3.ad    = 0x00;
	    SID.v3.sr    = 0xA8;
	    SID.flt_freq = 0xA000;
	    SID.flt_ctrl = 0x44;
	    SID.amp      = 0x1F;
	    SID.v3.ctrl  = 0x81;
	}
    }

As you can see, using the predefined structs makes your program even more readable.

Note: Newer cc65 versions do come with an include file named peekpoke.h that defines the PEEK, POKE, PEEKW and POKEW macros as shown in the answer above. You may want to look for this file and use it, if present.

cc65/peek_and_poke.txt · Last modified: 2010-06-16 00:33 by silverdr
 
Except where otherwise noted, content on this wiki is licensed under the following license: CC Attribution 3.0 Unported
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki