It's very rudimentary and there will be improvements to this later (hopefully), may be or may not be in this thread though.
The hardest part of this is coming up with a sprite that looks good in 8x16. (And drawing it. And converting this to the cpc special colour scheme. Had to wrote a tool for that too.)
Anyway, here's some code:
Code: Select all
// test 20230418 Timmy, a simple demo of CPC mode 0
// I've built this with:
// zcc +cpc -lndos -lm -subtype=dsk -create-app -zorg=16384 -o 9 cpctest9.c
#include <cpc.h>
#include <stdio.h>
#include <strings.h>
extern const uchar sprite1[];
#asm
._sprite1
DEFB 0x00, 0x30, 0x70, 0x00
DEFB 0x40, 0x85, 0x1A, 0xA0
DEFB 0x40, 0x52, 0x0F, 0xA0
DEFB 0x81, 0xF0, 0xA5, 0x70
DEFB 0xD0, 0xF0, 0xA5, 0x70
DEFB 0xD0, 0xF0, 0xA5, 0x70
DEFB 0xD0, 0xF0, 0xA5, 0x70
DEFB 0xD0, 0xF0, 0xF0, 0x5A
DEFB 0xD0, 0xDA, 0xDA, 0x5A
DEFB 0xC5, 0xE5, 0xE5, 0x5A
DEFB 0xC5, 0xE5, 0xE5, 0x5A
DEFB 0xD0, 0xDA, 0xDA, 0x5A
DEFB 0xF0, 0xF0, 0xF0, 0xF0
DEFB 0x0F, 0x0F, 0x1E, 0x5A
DEFB 0xF0, 0x5A, 0x5A, 0xF0
DEFB 0x00, 0xF0, 0xF0, 0x00
#endasm
int __FASTCALL__ nextline(int p) __naked
// who knew making a sprite in CPC mode 0 is so hard?!!
{
#asm
ld a, h
add a, 8
jr c, overflow
ld h, a
ret
.overflow
add hl, 0xc850
ret
#endasm
}
void __FASTCALL__ putsprite2(int p) __naked
// this erases the sprite before moving
// replace all 0x00 to 0xF0 to see how this sprite looks like in reality
// 00 is the background colour
{
#asm
push hl
ld (hl), 0x00
inc hl
ld (hl), 0x00
inc hl
ld (hl), 0x00
inc hl
ld (hl), 0x00
pop hl
call _nextline
push hl
ld (hl), 0x00
inc hl
ld (hl), 0x00
inc hl
ld (hl), 0x00
inc hl
ld (hl), 0x00
pop hl
call _nextline
ld b, 12
.spr2loop
push hl
ld (hl), 0x00
inc hl
inc hl
inc hl
ld (hl), 0x00
pop hl
call _nextline
djnz spr2loop
push hl
ld (hl), 0x00
inc hl
ld (hl), 0x00
inc hl
ld (hl), 0x00
inc hl
ld (hl), 0x00
pop hl
call _nextline
ld (hl), 0x00
inc hl
ld (hl), 0x00
inc hl
ld (hl), 0x00
inc hl
ld (hl), 0x00
ret
#endasm
}
void putsprite(uchar *p)
// the c version of the putsprite3()
{
uchar *r;
uchar *q;
int x,y;
q = sprite1;
//p = 0xC4B0;
for (y=0; y<8; y++)
{
r = p;
for (x=0; x<4; x++)
{
*r++ = *q++;
}
//p += 0x800 - 4;
p = nextline(p);
}
//p = 0xC4B0 + 0x50;
for (y=0; y<8; y++)
{
r = p;
for (x=0; x<4; x++)
{
*r++ = *q++;
}
//p += 0x800 - 4;
p = nextline(p);
}
}
void __FASTCALL__ putsprite3(int p) __naked
{
#asm
ld de, _sprite1
ld b, 16
.spr3loop
push bc
push hl
ex de, hl
ldi
ldi
ldi
ldi
ex de, hl
pop hl
call _nextline
pop bc
djnz spr3loop
ret
#endasm
}
int __CALLEE__ pack2 (uchar l, uchar h) __naked __z88dk_sdccdecl
// returns: hl
{
#asm
pop bc
pop hl
push bc
ret
#endasm
}
int __CALLEE__ get_address (uchar x, uchar y) __naked __z88dk_sdccdecl
// returns: screen address
// absolutely not the most efficient way to do this, but it works for now.
{
#asm
pop bc
pop de
push bc
ld hl, 0xC000
ld a, d
and 7
or a
jr z, ga1a
ld b, a
.ga1
add hl, 0x800
djnz ga1
.ga1a
ld a, d
srl a
srl a
srl a
or a
jr z, ga2a
ld b, a
.ga2
add hl, 0x50
djnz ga2
.ga2a
ld d, 0
add hl, de
ret
#endasm
}
main(){
uchar c;
uchar *p;
int dx, dy;
uchar x,y;
cpc_DisableFirmware(); // optional
cpc_SetMode(0); // optional
p = 0xC140 + 1;
c = 0;
dx = 1; dy = 2;
y = 40; x = 10;
while (1)
{
p = get_address(x,y);
putsprite2(p);
x += dx;
y += dy;
if ((y>150) || (y<=2)) dy = -dy;
if ((x>70) || (x<=2)) dx = -dx;
p = get_address(x,y);
putsprite3(p);
// a delay routine
#asm
ei
ld b, 12
.ko
halt
djnz ko
di
#endasm
}
}