• Commodore Free Magazine, Issue 80 - Part 8

    From Stephen Walsh@39:901/280 to All on Sat May 17 18:24:05 2014
    ng sprite! Look!
    Some enemies! Look! A scroller." Well, I had to test it myself at first,
    but as soon as Pulse got sound I turned up the stereo to its max, and
    everybody and their mothers squatted the joypad for at least an hour each.
    I just took care that the collision detection was accurate or at least forgiving. It had to be a fair game. My flatmate scored 4271 points, by
    the way.

    - - - - - - - - - -

    Q. Apart from Commodore Free have you had any other comments about the
    game?

    A. The folks at the VIC-20 Denial forum blew my hair back with their encouraging comments. Love you, too! They made me continue working on it
    when it had no score counters or sound. I expected this to be another
    piece of software of mine that'd get dumped into oblivion. But then I got cartloads of positive comments by very excited people and that was totally unexpected and scary. Pulse got a 100% rating on pouet.net. The Micro
    Mart magazine, which is printed in Britain, told me that they'll publish a
    news piece about it this week. I didn't read it yet but they already let
    me know that they find the game most impressive. This thing went totally
    out of control and beyond wildest dreams on special medication. This
    possibly cannot happen again. That depression I mentioned is cured for
    sure, though.

    - - - - - - - - - -

    Q. Imagine you could go back in time and were given the option to change
    one part of the VIC. What would you change?

    A. Full documentation and an assembler shipped with it instead of just a
    BASIC handbook. It would still be a great educational toy for kids today
    like that.

    - - - - - - - - - -

    Q. Do you have any question you would have liked to have been asked?

    A. Not really. Thank you very much!




    *************************************
    OPTIMIZING CC65 CODE
    What the Author Didn't Tell You
    By Joseph Rose (a.k.a. Harry Potter)
    *************************************

    INTRO

    Welcome to my cc65 C optimization documentation! Here, you will find some tricks and techniques to produce the best C code under cc65. Most of the techniques here will work for other 6502 targets, other C compilers, and
    even other compilers and interpreters. I'm not yet an advanced programmer,
    but I believe these optimizations to be useful. Some of these techniques
    may be obvious to some, but you may still find something useful. This
    document is organized into sections; each describes one technique. The individual techniques follow:

    MIDDLEMAN

    If your code needs to call the same function or group of functions, in
    order and with some of the same parameters, you can use a "middleman,"
    where the middleman will accept the call, and call the base function or functions for the callee and supply the constant parameters. This will
    require some parameters to be passed only once in your code, making for
    smaller code. An example follows:

    Instead of:

    extern int i[10];
    int func2 (int ramcount,
    enum machine m,
    char* language)
    {
    ...
    }
    void func (void) {
    {
    i[0]=func2 (64, machC64, "c");
    i[1]=func2 (64, machC64, "BASIC");
    i[2]=func2 (64, machC64, "assembler
    ");
    i[3]=func2 (64, machC64, "FORTH");
    i[4]=func2 (64, machC64, "Pascal");
    }

    Try:

    extern int i[10];
    int func2 (int ramcount,
    enum machine m,
    char* language)
    {
    ...
    }
    int func2a (char* language)
    { return func2(64, machC64, language)
    ;}
    void func (void)
    {
    i[0]=func2a ("c");
    i[1]=func2a ("BASIC");
    i[2]=func2a ("assembler");
    i[3]=func2a ("FORTH");
    i[4]=func2a ("Pascal");
    }

    CACHING VARIABLES

    If you need a particular element in, for example, a multi-subscript array
    of structs many times in your code, it is a good idea to read it once,
    store the value in a local variable and access that instead. If you need
    to access different members of the struct, assign the struct's address to a local pointer and use that to access the struct. This is made even better
    if you use a zeropage variable.

    MINIMIZE FUNCTION USAGE

    Don't use functions you don't need. If you don't need the services of mprintf(), don't use it.

    Examples follow:

    My CBMSIMPIO library simplifies displaying text and numbers on the screen.
    If you don't need the services of the standard screen output library and CBMSIMPIO can do the job, use CBMSIMPIO instead. This can save 2-3k in
    your program.

    If you need to copy memory from one location to another and the two never overlap, don't use memmove(). memmove() requires more overhead, and
    memcpy() can do the job.

    SYSTEM-SPECIFIC FUNCTIONS

    If you're writing code for a specific target, use functions made for that target. This requires less overhead for conversion and otherwise makes for better code in general. An example is if you use file access with a CBM
    model, using the CBM OS functions to access the OS directly.

    CBM CONTROL CODES

    The good thing about CBM screen output is that it can contain control codes
    to perform functions such as change color or clear screen. If you need to,
    for example, clear the screen before writing some text, including a clear screen code in the text can save from an explicit clrscr() call and shave 4 bytes from your code.

    ASSEMBLER

    Most programs can be created solely in C. However, some programs may
    require at least some assembler. When deciding to use assembler in your
    code and where, keep the following in mind:

    * C is a medium-level and is good for calculations and program flow.

    * Assembler is a low-level language and is good for data-crunching, hardware-manipulation and OS calls.

    * If C can do the job immediately, you should use C.

    * If C needs to do a work-around to do the job, you may want to use
    assembler.

    * If you want or need full control over hardware or the computer, you
    should use assembler.

    Don't be afraid to use assembler. It can be beneficial if used properly.

    ASSUMING PARAMETERS

    This is similar to the Middleman optimization. If a function only needs
    one value for a particular parameter, remove the parameter and replace it
    with the value. Then, remove the parameter in the declaration, definition,
    and calls to the function.

    TOKENIZING CALCULATIONS

    If you need to use the same calculations over and over, store the calculation(s) in one function each and call the function(s) as needed.

    OPTIMIZING LONGS

    On an 8-bit computer, longs are very slow and require a lot of code.

    Fortunately, using pointers to longs seems to produce tighter code. I
    think this is because it allows your program to handle words, while the compiler provides the routines to handle the longs referenced. This,
    however, should slow down your code even more.

    CALCULATE ONCE

    If you need the result of a particular calculation several times, perform
    it once.

    USE SWITCHES

    Switches are good for many possibilities. Switches load the value once and perform several comparisons on it, saving from the extra loads necessary
    with ifs. The exception to this rule is a true/false case which works
    better on ifs.

    INCREMENTAL SWITCH RETURNS

    When you use a switch to return an incremental value where each condition returns one more (or less) than the previous, reorganize the code by
    putting the highest (or lowest if less than the previous), using an increment/decrement instead and remove the breaks on all except the last if necessary. An example follows:

    Instead of:

    char c=0, d;
    switch (c) {
    case 1: d=1; break;
    case 3: d=2; break;
    case 2: d=3; break;
    case 4: d=4; break;
    }

    Try:

    char c=0, d=0;
    switch (c) {
    case 4: ++d;
    case 2: ++d;
    case 3: ++d;
    case 1: ++d; break;
    }

    TOGGLING BOOLS

    If you know that, for example, b is a bool and either 1 or 0, toggling b
    using b^1 is shorter and probably also faster than !b.

    IFS WITHOUT ELSES

    If you have a series of ifs, all of which are mutually exclusive (i.e.
    only one will work anyway), exclude the elses. In this way, you avoid the extra jump over the next elses.

    ASSIGNING

    Assigning a value when it's first used can save an explicit load. Ex:

    Instead of:

    --- MBSE BBS v1.0.01 (GNU/Linux-i386)
    * Origin: Dragon's Lair ---:- bbs.vk3heg.net -:--- (39:901/280)