Calling libraries from C

This article explains how to compile and link a C program with an Assembly library, and why you might want to do this in the first place.

Writing game logic in a high level language is easier, quicker, and less error prone then it would be in Assembly. Since most game logic doesn’t really take all that much CPU power, there isn’t much need for the raw speed you get with Assembly. In the case of the Color Computer, C is great high level (or some would say middle level) language to use. It’s fast, very easy to talk directly to the hardware, and is easy to integrate with Assembly.

Writing graphics routines in a high level language would be pretty slow. It is here that Assembly really shines. Squeeze all the speed out of your CPU by using assembly.

The other point I want to mention is that I want to build one set of libraries that can be used by both C and Assembly. Build once, and use many times. This way I can write a game in C using the libraries, or if I wanted to write it completely in Assembly, I can use the same libraries that I know to work.

In this article I will be talking about building a graphics library. However the practice can be used for any project that requires libraries in assembly.

Inline assembly

I just wanted to quickly talk about inline assembly. Inline assembly is a way to embed assembly code in your C program. For example, I used both C and assembly in a function here (C was just setting up variables for the asm section):

void showLevelSection(int offset)
{
    //pdisp is the destination, the double buffer or display
    //plevel contains bytes, each byte being a block type in the level
    //each block is an index into the block colors
    //the block color is then output to the dest buffer
    //we are only blitting a screen full from the level

    byte* pbuffer = doubleBuffer;                 //needed for asm to see a byte* correctly
    byte* plevel = level->data+offset;
    asm
    {
        ldx     plevel
        ldy     pbuffer
        ldb     #BLIT_HEIGHT
        
loop:
        lda     ,x+             read from level
        cmpa    #INVISIBLE      should this be drawn?
        bne     drawfromlevel   not invisible, draw using level data
        lda     #BLACK          replace color with black tile
drawfromlevel:
        sta     ,y+             blit to buffer
        dec     xcount
        bne     loop
        
        leax    49,x            point to next line in level
        lda     #DISP_WIDTH     reset x counter
        sta     xcount
        decb                    height loop counter...
        bne     loop            ...keep going
        bra     done
xcount  fcb     32
done:
    }
}

Inline will work great for specific applications. But two important things to consider:

  1. You can’t use the routines from assembly. Well, that’s not entirely true. You can, if you modularize your code properly.
  2. Your app logic will not be portable.

So we are going to toss out inline for this discussion.

Creating the library

Let’s create a library that will have two functions. One returns a number, the other adds the number with itself and returns the result.

Note that when you define a function in assembly that C calls, you have to put an underscore in front of it, ie: _addNum.

All source is at the end of this article.

Not using library

First, examples of compiling without creating a library.

C calling C functions

Note, I use cnumber.c so we don’t clobber assembly example.

cmoc greet1.c cnumber.c

C calling assembly functions

cmoc greet1.c number.asm

Assembly calling assembly functions

Creates greet2.bin

lwasm -9 -b -f obj -o number.o number.asm 
lwasm -9 -b -f obj -o greet2.o greet2.asm
lwlink -o greet2.bin -b -f decb greet2.o number.o

Compiling and using library

Examples of compiling library code, then compiling and linking with the library.

Create a C library

cmoc -c cnumber.c
lwar -c libcnumber.a cnumber.o

Create an assembly library

lwasm -9 -b -f obj -o number.o number.asm
lwar -c libnumber.a number.o

Link to the library and run

Note I haven’t got the syntax write when linking assembly to a library.

Compile and link to C lib and assembly lib.

cmoc -o greet1c.bin greet1.c -L. -lcnumber
cmoc -o greet1.bin greet1.c -L. -lnumber

Compile assembly calling assembly.

lwasm -9 -b -f obj -o number.o number.asm
lwasm -9 -b -f obj -o greet2.o greet2.asm
lwlink -o greet2.bin -b -f decb greet2.o number.o

Toss bin files onto a disk image.

writecocofile -b casm.dsk greet1.bin
writecocofile -b casm.dsk greet1c.bin
writecocofile -b casm.dsk greet2.bin


Source

greet1.c

#ifndef _COCO_BASIC_
#error This program must be compiled for a CoCo Disk Basic environment.
#endif

#include "coco.h"
#include "stdarg.h"

//external function
int getNum();       //function with no params
int addNum(int a);  //function with a param

int main() {
    int a = getNum();
    int b = addNum(a);
    printf("NUMBER=%d ADDNUM=%d\n",a,b);
    return 0;
}

cnumber.c

int getNum() {
    return 5;
}

int addNum(int n) {
    return n+n;
}

number.asm

_getNum EXPORT
_addNum EXPORT

    SECTION     code
    
_getNum ldd #42
    rts

num equ 2   ; where on the stack the number will be
_addNum ldd num,s
    addd    num,s
    rts

    ENDSECTION

greet2.asm

printm          macro                           ; define the macro
                pshs            d,x,y,u
                ldx             \1
                jsr             print
                puls            u,y,x,b,a
                endm

                org             $5800
_getNum         IMPORT
_addNum         IMPORT 

num             equ             42

                SECTION         code
start           printm          #helloworld

                lbsr            _getNum         ;call _getNum, D will contain the return value
                
                bsr             printnum        ;now to print the value, call routine to print value in D to screen
                lda             #' '            ;space out the output so we can print more test results
                jsr             [cbchrout]      ;print char using stdout hook

                ; call _addNum(42)
                ldd             #num            ;value to pass
                pshs            b,a             ;push value onto stack, which _addNum uses
                lbsr            _addNum         ;make the call
                leas            2,s             ;pop param off the stack, we don't need it anymore

                bsr             printnum        ;now to print the value, call routine to print value in D to screen
                lda             #' '            ;space out the output so we can print more test results
                jsr             [cbchrout]      ;print char using stdout hook
                
                ; call _addNum(temp) where temp is a 'variable' in assembly, pointer to memory
                ldd             temp            ;grab temp value
                pshs            b,a             ;put D on stack
                lbsr            _addNum         ;make the call, D will have return value
                leas            2,s             ;pop params
                bsr             printnum        ;now to print the value, call routine to print value in D to screen
                lda             #' '            ;space out the output so we can print more test results
                jsr             [cbchrout]      ;print char using stdout hook
                
                rts

*******************************************************************************
* Display 2's complement number in D.
* All registers are saved and restored
*******************************************************************************
printnum        pshs            u,y,x,d
                jsr             cbprintnum
                puls            d,x,y,u
                rts
*******************************************************************************
* Display a null terminated string using the stdout hook.
* Modifies A,X. Maybe others in teh CHROUT BASIC routine.
*******************************************************************************
print           lda             ,x+             ;grab a character from string
                beq             doneloop@       ;null at end of string?
                jsr             [cbchrout]      ;print char using stdout hook
                bra             print           ;keep printing
doneloop@       rts                             ;return to caller

cbprintstring   jsr             $b99c
                rts
                                
temp            fdb             255
helloworld      fcc             "HELLO WORLD"
                fcb             13,0

                                
                ENDSECTION

cbchrout        equ             $a002
cbprintnum      equ             $bdcc

                end

Robot Minefield C Port

After typing in the BASIC version of Robot Minefield, then porting it to Assembly, I decided to round things out by doing a C version as well. The C version was the fastest to port. I learned a lot doing the assembly version, and had a blast. The assembly was the most fun, but the most frustrating to write. My assembly foo just isn’t very strong at this point. Thinking in assembly still takes a while, but worse is not knowing all those pesky mnemonics!

Continue reading Robot Minefield C Port

Robot Minefield Day 4

It is now day 4 of my Robot Minefield conversion to assembly. Last night was my first night I dreamed in assembly. I remember working on some problem, and assembly was involved. You know you have your head in the game when you dream about it. So far so good. I have the minefield randomly populating with mines and robots, and randomly placing the human somewhere on the field. Steve Bjork was kind enough to provide a random number generator in assembly, which was very easy to adapt. You can run the human around the minefield, and will die if you touch a mine or a robot. I just started working on the robot movement AI. You can view my initial post.

Continue reading Robot Minefield Day 4

Robot Minefield

Robot Minefield is a BASIC game I typed in from Tim Hartnell’s Giant Book Of Computer Games book. Neat game, and a simple enough game I’m using it as an exercise to write it in assembly. The game is a little like Rogue in that the computer doesn’t move until you do. But what’s most interesting about this game, is that it is a remake of a game called Robots and mines on the Commodore PET, and was one of the games that inspired the arcade shooter Robotron 2084.

Continue reading Robot Minefield

Bouncy Ball NG Announcement

Updates:
November 27, 2017: Announcement
December 6, 2017: Progress report 1
December 31, 2017: Progress report 2 Apple TV
January 17, 2018: Progress report 3 the home stretch!
January 24, 2018: Progress report 4 signing the certs!
January 29, 2018: Progress report 5 Submitted to the app store!

I really had an itch to play Bouncy Ball, the Color Computer game I wrote back in 2016. I also needed to learn SpriteKit for iOS and macOS. So I put the two needs together and created Bouncy Ball NextGen for iPad, iPhone and Mac. Everything from the original is intact, only getting an update to the UI, level flow, and sounds.

When playing it on the Coco, I always thought the game worked really well using a joystick. Now on the iPad, touching the left and right side of the screen to make it scroll is a perfect replacement. It just feels right, especially with the buttery smooth scrolling.

I wanted to keep you in the game longer, and not break the action. So progression from level to level, and death no longer requires user input, and just jumps right back into the game.

You can check out my promo video below.

November 27, 2017

6809 CPU Emulator project started

CpuEmulator is a CPU emulator project that aims to emulate a CPU (the 6809 to start with), it’s registers, and system memory. It will allow you to monitor registers, flags and memory as you step through code. Having done SharpiEmu for the Sharp PC–1360 Pocket Computer, the concept seems pretty simple. The 6809 has a number of addressing modes, and different opcodes for the same mnemonic. So I’m expecting it to be somewhat more of a challenge.

Initial version will emulate the CPU, memory, and text video mode.

Features

  • Emulate 6809 instructions
  • Emulate 32×16 & 80×24 text modes
  • Emulate the Coco3’s MMU
  • 4K all the way up to 512KB memory options
  • Debugger that steps through code, shows current state of registers, selected memory block, and source code from a listing file.
  • Break points. They are remembered between runs.
  • Memory watcher. When memory at a certain addresses are modified, a breakpoint is triggered so you can see what modified it.

Continue reading 6809 CPU Emulator project started

Bouncy Ball 2 Progress Report #1

Bouncy Ball 2 Progress Report 1. First things first. We need to get the Coco 3 into it’s high resolution graphics mode, then display a little something. To start out small, I decided to create a program that sets the video mode, uses the MMU to map in the video memory, then clears the screen. That part was easy, although understanding the MMU was a little whacky.

Continue reading Bouncy Ball 2 Progress Report #1

Bouncy Ball 2 Announcement

I’m happy to announce that Bouncy Ball 2 development has started! Design is underway, and the sound system already sounds awesome. We have been able to make the Orchestra 90 sound mad. It’s using full stereo sound, mixing 4 channels, and uses hardly any CPU. We have a lot to learn about the Coco 3. Join us every week or two on the BB2 development blog to watch our progress. We are Lee, Simon, and Paul.

Orchestra 90 CC Stereo Music Synthesizer

Radio Shack Catalog Number 26–3143. The Orchestra–90 CC is a stereo 8-bit audio player for the Color Computer. It works by mapping two addresses in the Coco’s address space to two 8-bit DACs. $FF7A is for left, and $FF7B is for the right. This is the first time I have been able to use this cart, never mind program it! So far, it’s pretty easy to program.

Continue reading Orchestra 90 CC Stereo Music Synthesizer

Bouncy Ball Version 1 Available

Bouncy Ball version 1.0 has been released, and in time for the 2016 25th Cocofest. I was working on a timer bug, and RGB mapping, while Simon was working on the end game sequence. I owe him a case of beer for his efforts, staying up till 2am his time, on a work day! I am so looking forward to watching people play on my Coco 3.

Continue reading Bouncy Ball Version 1 Available

Optimizing an Imaginary Sprite

There was an interesting thread on Facebook this week that was talking about optimization. They took an imaginary sprite routine and optimized the crap out of it. In this article I’m going walk through the various stages of optimization and provide my own analysis of why the changes were made, and why (or if) the optimization was any good.

I’m going to assume you know how, or are familiar with some arcane programming language, and are either somewhat familiar with assembly or enjoy punishing your brain.

You might be surprised with the results of version 5 and 5p. Sometimes less instructions doesn’t always mean faster.

Continue reading Optimizing an Imaginary Sprite

Bouncy Ball Public Beta 1

Bouncy Ball Beta 1 is here. See the downloads. This has the lightening fast rendering routine that Simon and myself optimized. Originally a 7 fps C routine to a 50 fps inline assembly routine. I am now running at the Coco’s stock speed of (just under) 1MHz instead of using the 2X speed up on the Coco 3. This also means Bouncy Ball should run on a Coco 2, but I have not tested it yet. The frame rate is buttery smooth but not vsync’ed yet. Some sounds have been added to the game, but in game ball bounce sound is not there yet. And best of all you can now use the keyboard to play!

Continue reading Bouncy Ball Public Beta 1