#!/bin/bash
cat > crt0_cpc.s <<'EOF'
;; FILE: crt0.s
;; Generic crt0.s for a Z80
;; From SDCC..
;; Modified to suit execution on the Amstrad CPC!
;; by H. Hansen 2003

  .module crt0
	.globl	_main

	.area _HEADER (ABS)
;; Reset vector
	.org 	0x1200
	jp	init
	
	.org	0x1210

init:

;; Initialise global variables
  call    gsinit
	call	_main
	jp	_exit

	;; Ordering of segments for the linker.
	.area	_HOME
	.area	_CODE
  .area   _GSINIT
  .area   _GSFINAL
        
	.area	_DATA
  .area   _BSS
  .area   _HEAP

  .area   _CODE
__clock::
	ret
	
_exit::
	ret
	
	.area   _GSINIT
gsinit::	

.area   _GSFINAL
    	ret
EOF
sdasz80 -o crt0_cpc.s
cat > putchar.s <<'EOF'
;; FILE: putchar.s
;; Modified to suit execution on the Amstrad CPC
;; by H. Hansen 2003
;; adjusted for new calling convention by karme
;; 2025
	.area _CODE
_putchar::       
_putchar_rr_s:: 
        	; ld      hl,#2
        	; add     hl,sp
        	; ld      a,(hl)
		ld      a,l
        	call    0xBB5A
        	ret
           
_putchar_rr_dbs::
        	ld      a,e
        	call    0xBB5A
        	ret
EOF
sdasz80 -o putchar.s

cat > c.c <<'EOF'
#include <stdio.h>
typedef unsigned uint;
typedef unsigned char uchar;

void ink(int p, int c);
void setpixel(uchar x, uchar y, uchar c);
uint getTime();

int main()
{
  // mode 0: 160x200
  __asm
    ld  a, #0
    call  #0xbc0e
  __endasm;

  uchar i,x,y,o=0;
  uint f=0;

  __asm
	call #0xbd19
  __endasm;

  for (i=0;i<16;++i) ink(i,(i+o)%16);

  for (y=0;y<200;++y)
  {
    for (x=0;x<160;++x) {
	setpixel(x,y,x%16);
    }
  }

  uint s = getTime();
  f=0;
  while(getTime()-s<3000) {
    f=f+1;  			    			  
    o=(o-1)%16;
    __asm
	call #0xbd19
    __endasm;

    for (i=0;i<16;++i) ink(i,(i+o)%16);
  }
  printf("%dframes/s",f/10);
  __asm
	call #0xbb18
  __endasm;
  return 0;
}

void
setpixel(uchar x, uchar y, uchar c)
{
        char* a=((char *)0xc000) + (80 * (y / 8))
	        + (2048 * (y % 8)) + x/2;
        uchar p=*a;
	if (!(x%2)) {
           p=((c&1) ? 128 : 0) | ((c&4) ? 32 : 0)
	     | ((c&2) ? 8 : 0) | ((c&8) ? 2 : 0)
             | (p & 0b01010101);
	}else{
	   p=((c&1) ?  64 : 0) | ((c&4) ? 16 : 0)
             | ((c&2) ? 4 : 0) | ((c&8) ? 1 : 0)
             | (p & 0b10101010);
        }
        *a=p;
}

void
ink(int p, int c)
{
  p;c;
  __asm
  push af
  push bc
  push hl
  push de
  ld a,e
  ld b,l
  ld c,b
  call #0xbc32
  pop de
  pop hl
  pop bc
  pop af
  __endasm;
}

uchar char3,char4;

uint getTime()
{
	uint r = 0;
	__asm
		call #0xbd0d ;kl time please
		push hl
		pop de
		ld hl, #_char3
		ld (hl), d
		ld hl, #_char4
		ld (hl), e
	__endasm;
	r = (char3 << 8) + char4;
	return r;
}

EOF
sdcc -mz80 --code-loc 0x1238 --data-loc 0 \
--no-std-crt0 crt0_cpc.rel putchar.rel c.c
makebin -p c.ihx|tail -c +4609>c.bin
iDSK c.dsk -n -i c.bin -e 1200 -c 1200
mame cpc664 -flop1 c.dsk -skip_gameinfo \
-ab '\n\nrun "c\n' \
-snapsize 768x544 -aviwrite /tmp/h.avi -str 35
ffmpeg -ss 0.5 -y -i /tmp/h.avi \
-pix_fmt yuv420p /tmp/c2.mp4
