Page 1 of 1

Calling Amstrad firmware routines

Posted: Thu May 21, 2020 7:26 pm
by Juan Luis
I'm trying to call several Amstrad firmware routines from C code, but the call is unsuccessful. After calling set_move Amstrad CPC is reset.

Is it possible to call to Amstrad firmware routines?

The code is compiled with following command:
zcc +cpc -lndos -create-app -o gfx.bin main.c

Code: Select all

#include <conio.h>

#define SCR_SET_MODE                 0xBC0E        // A=mode (0, 1, 2)
#define GRA_MOVE_ABSOLUTE        0xBBC0        // DE=x, HL=y
#define GRA_LINE_ABSOLUTE        0xBBF6        // DE=x, HL=y
#define GRA_LINE_RELATIVE        0xBBF9        // DE=x, HL=y
#define GRA_SET_ORIGIN                0xBBC9         // DE=x, HL=y

void set_mode(unsigned m) {
#asm
        // m parameter SP+2
        //ld hl,2
        //add hl,sp
        //ld a,(hl)
        ld a,2                         // Forcing mode 2
        
        // in : A = mode (0=160x200x16, 1=320x200x4, 2=640x200x2)
        // out: A = mode
        call SCR_SET_MODE
#endasm
}

void move(int x, int y) {
#asm
        // x parameter SP+4
        // y parameter SP+2        
        ld hl,4
        add hl,sp
        ld e,(hl)
        inc hl
        ld d,(hl)        // DE = x

        ld hl,2
        add hl,sp
        ld c,(hl)
        inc hl
        ld b,(hl)        // BC = y
        ld l,c
        ld h,b                // HL = BC = y
        call GRA_MOVE_ABSOLUTE
#endasm
}

void line(int x, int y) {
#asm
        // x parameter SP+4
        // y parameter SP+2        
        ld hl,4
        add hl,sp
        ld e,(hl)
        inc hl
        ld d,(hl)        // DE = x

        ld hl,2
        add hl,sp
        ld c,(hl)
        inc hl
        ld b,(hl)        // BC = y
        ld l,c
        ld h,b                // HL = BC = y
        call GRA_LINE_ABSOLUTE
#endasm
}

void main() {
        set_mode(2); // Fails in this call. Video mode is not set
        move(0,0);
        line(100,100);
        
        while (!kbhit());
}

Posted: Thu May 21, 2020 7:50 pm
by dom
The crt0 exposes a function called "firmware" that should restore the registers to values that the firmware requires. Use it as follows:

Code: Select all

EXTERN firmware
; Setup registers
call firmware
defw FIRMWARE_ADDRESS

Posted: Thu May 21, 2020 10:19 pm
by Juan Luis
dom wrote:The crt0 exposes a function called "firmware" that should restore the registers to values that the firmware requires. Use it as follows:

Code: Select all

EXTERN firmware
; Setup registers
call firmware
defw FIRMWARE_ADDRESS
Ok. It works find as you have written. I have modified my code setting SRC_SET_MODE as FIRMWARE_ADDRESS, and an equivalent thing in the other functions:

Code: Select all

...
void set_mode(unsigned m) {
#asm
        // m parameter SP+2
        ld hl,2
        add hl,sp
        ld a,(hl)
        
        // in : A = mode (0=160x200x16, 1=320x200x4, 2=640x200x2)
        // out: A = mode
        EXTERN firmware
        call firmware
        defw SCR_SET_MODE
#endasm
}
...
Thanks for your help.

Posted: Mon May 25, 2020 11:23 am
by stefano
You should also have some of them ready made , e.g. cpc_SetMode
We imported the cpcsrlib but some advanced option which was recently introduced.