diff options
Diffstat (limited to 'gbdk/gbdk-lib/libc')
261 files changed, 34323 insertions, 0 deletions
diff --git a/gbdk/gbdk-lib/libc/Makefile b/gbdk/gbdk-lib/libc/Makefile new file mode 100644 index 00000000..d7ba3828 --- /dev/null +++ b/gbdk/gbdk-lib/libc/Makefile @@ -0,0 +1,53 @@ +# Makefile for libc + +.EXPORT_ALL_VARIABLES: + +ifeq ($(PORTS),) + PORTS = sm83 z80 +endif + +ifeq ($(PLATFORMS),) + PLATFORMS = gb ap duck gg sms msxdos +endif + +TOPDIR = .. + +CSRC = atoi.c atol.c isalpha.c isdigit.c \ + islower.c isspace.c isupper.c \ + sprintf.c printf.c puts.c scanf.c strcat.c string.c \ + strncat.c strncmp.c strncpy.c time.c \ + tolower.c toupper.c \ + __assert.c \ + _modulong.c _modslong.c _divulong.c _divslong.c _mullong.c \ + bsearch.c qsort.c atomic_flag_clear.c \ + free.c malloc.c realloc.c calloc.c + +include $(TOPDIR)/Makefile.common + +all: ports platforms + +clean: port-clean ports-clean platform-clean + +ports: + for i in $(PORTS); do make port THIS=$$i PORT=$$i; done + +platforms: + for j in $(PORTS); do for i in $(PLATFORMS); do if [ -d "targets/$$j/$$i" ]; then make -C targets/$$j/$$i platform THIS=$$i; fi done done + +# Make all the std libs +# Make all the port specific libs + +# Uses the LIB <- OBJ rule from Makefile.rules +port: port-clean $(LIB) + make -C asm/$(PORT) port + +port-clean: + rm -f $(LIBC_OBJ) $(CLEANSPEC) + +ports-clean: + for i in $(PORTS); do make -C asm/$$i clean THIS=$$i; done + +platform-clean: + for j in $(PORTS); do for i in $(PLATFORMS); do if [ -d "targets/$$j/$$i" ]; then make -C targets/$$j/$$i clean THIS=$$i; fi done done + +include Makefile.rules diff --git a/gbdk/gbdk-lib/libc/Makefile.platform b/gbdk/gbdk-lib/libc/Makefile.platform new file mode 100644 index 00000000..0f384ec5 --- /dev/null +++ b/gbdk/gbdk-lib/libc/Makefile.platform @@ -0,0 +1,8 @@ +# Shared Makefile for all the platforms. +# Provides a way of building the lib with little brains. + +all: platform + +platform: $(LIB) + +include $(TOPDIR)/libc/Makefile.rules diff --git a/gbdk/gbdk-lib/libc/Makefile.rules b/gbdk/gbdk-lib/libc/Makefile.rules new file mode 100644 index 00000000..160bc6eb --- /dev/null +++ b/gbdk/gbdk-lib/libc/Makefile.rules @@ -0,0 +1,19 @@ +ifeq ($(MODEL),small) +NEAR_CALLS = 1 +else +NEAR_CALLS = 0 +endif + +include $(TOPDIR)/libc/rules-$(ASM).mk + +clean: + rm -f $(OBJ) $(CLEANSPEC) + +set-model: + if [ -e global.s ]; then \ + sed -e "s/.NEAR_CALLS\W=\W[0-9]\+/.NEAR_CALLS = $(NEAR_CALLS)/" global.s > tmp1.txt ;\ + mv tmp1.txt global.s; \ + fi + +build-dir: + mkdir -p $(BUILD) diff --git a/gbdk/gbdk-lib/libc/__assert.c b/gbdk/gbdk-lib/libc/__assert.c new file mode 100644 index 00000000..a4404513 --- /dev/null +++ b/gbdk/gbdk-lib/libc/__assert.c @@ -0,0 +1,38 @@ +/*------------------------------------------------------------------------- + assert.c + + Copyright (C) 2000, Michael Hope + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library; see the file COPYING. If not, write to the + Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. + + As a special exception, if you link this library with other files, + some of which are compiled with SDCC, to produce an executable, + this library does not by itself cause the resulting executable to + be covered by the GNU General Public License. This exception does + not however invalidate any other reasons why the executable file + might be covered by the GNU General Public License. +-------------------------------------------------------------------------*/ + +#include <stdio.h> +#include <stdlib.h> + +void __assert(const char *expression, const char *functionname, const char *filename, unsigned int linenumber) +{ + printf("Assert(%s) failed in function %s at line %u in file %s.\n", + expression, functionname, linenumber, filename); + for(;;); +} + diff --git a/gbdk/gbdk-lib/libc/_divslong.c b/gbdk/gbdk-lib/libc/_divslong.c new file mode 100644 index 00000000..ed2ab573 --- /dev/null +++ b/gbdk/gbdk-lib/libc/_divslong.c @@ -0,0 +1,35 @@ +/*------------------------------------------------------------------------- + _divslong.c - routine for division of 32 bit long + + Copyright (C) 1999, Sandeep Dutta . sandeep.dutta@usa.net + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library; see the file COPYING. If not, write to the + Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. + + As a special exception, if you link this library with other files, + some of which are compiled with SDCC, to produce an executable, + this library does not by itself cause the resulting executable to + be covered by the GNU General Public License. This exception does + not however invalidate any other reasons why the executable file + might be covered by the GNU General Public License. +-------------------------------------------------------------------------*/ + +unsigned long _divulong (unsigned long a, unsigned long b); + +long _divslong (long a, long b) { + long r; + r = _divulong((a < 0 ? -a : a), (b < 0 ? -b : b)); + return ((a < 0) ^ (b < 0)) ? -r : r; +} diff --git a/gbdk/gbdk-lib/libc/_divulong.c b/gbdk/gbdk-lib/libc/_divulong.c new file mode 100644 index 00000000..f98eb857 --- /dev/null +++ b/gbdk/gbdk-lib/libc/_divulong.c @@ -0,0 +1,351 @@ +/*------------------------------------------------------------------------- + _divulong.c - routine for division of 32 bit unsigned long + + Ecrit par - Jean-Louis Vern . jlvern@writeme.com (1999) + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this program; if not, write to the Free Software + Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + In other words, you are welcome to use, share and improve this program. + You are forbidden to forbid anyone else to use, share and improve + what you give them. Help stamp out software-hoarding! +-------------------------------------------------------------------------*/ + +/* Assembler-functions are provided for: + mcs51 small + mcs51 small stack-auto +*/ + +#if !defined(SDCC_USE_XSTACK) && !defined(_SDCC_NO_ASM_LIB_FUNCS) +# if defined(SDCC_mcs51) +# if defined(SDCC_MODEL_SMALL) +# if defined(SDCC_STACK_AUTO) +# define _DIVULONG_ASM_SMALL_AUTO +# else +# define _DIVULONG_ASM_SMALL +# endif +# endif +# endif +#endif + +#if defined _DIVULONG_ASM_SMALL + +static void +_divlong_dummy (void) _naked +{ + _asm + + .globl __divulong + + __divulong: + + #define count r2 + + #define a0 dpl + #define a1 dph + #define a2 b + #define a3 r3 + + #define reste0 r4 + #define reste1 r5 + #define reste2 r6 + #define reste3 r7 + +#if defined(SDCC_NOOVERLAY) + .area DSEG (DATA) +#else + .area OSEG (OVR,DATA) +#endif + + .globl __divulong_PARM_2 + .globl __divslong_PARM_2 + + __divulong_PARM_2: + __divslong_PARM_2: + .ds 4 + + .area CSEG (CODE) + + #define b0 (__divulong_PARM_2) + #define b1 (__divulong_PARM_2 + 1) + #define b2 (__divulong_PARM_2 + 2) + #define b3 (__divulong_PARM_2 + 3) + + ; parameter a comes in a, b, dph, dpl + mov a3,a ; save parameter a3 + + mov count,#32 + clr a + mov reste0,a + mov reste1,a + mov reste2,a + mov reste3,a + + ; optimization loop in lp0 until the first bit is shifted into rest + + lp0: mov a,a0 ; a <<= 1 + add a,a0 + mov a0,a + mov a,a1 + rlc a + mov a1,a + mov a,a2 + rlc a + mov a2,a + mov a,a3 + rlc a + mov a3,a + + jc in_lp + djnz count,lp0 + + sjmp exit + + loop: mov a,a0 ; a <<= 1 + add a,a0 + mov a0,a + mov a,a1 + rlc a + mov a1,a + mov a,a2 + rlc a + mov a2,a + mov a,a3 + rlc a + mov a3,a + + in_lp: mov a,reste0 ; reste <<= 1 + rlc a ; feed in carry + mov reste0,a + mov a,reste1 + rlc a + mov reste1,a + mov a,reste2 + rlc a + mov reste2,a + mov a,reste3 + rlc a + mov reste3,a + + mov a,reste0 ; reste - b + subb a,b0 ; carry is always clear here, because + ; reste <<= 1 never overflows + mov a,reste1 + subb a,b1 + mov a,reste2 + subb a,b2 + mov a,reste3 + subb a,b3 + + jc minus ; reste >= b? + + ; -> yes; reste -= b; + mov a,reste0 + subb a,b0 ; carry is always clear here (jc) + mov reste0,a + mov a,reste1 + subb a,b1 + mov reste1,a + mov a,reste2 + subb a,b2 + mov reste2,a + mov a,reste3 + subb a,b3 + mov reste3,a + + orl a0,#1 + + minus: djnz count,loop ; -> no + + exit: mov a,a3 ; prepare the return value + ret + + _endasm ; +} + +#elif defined _DIVULONG_ASM_SMALL_AUTO + +static void +_divlong_dummy (void) _naked +{ + _asm + + .globl __divulong + + __divulong: + + #define count r2 + + #define a0 dpl + #define a1 dph + #define a2 b + #define a3 r3 + + #define reste0 r4 + #define reste1 r5 + #define reste2 r6 + #define reste3 r7 + + .globl __divlong ; entry point for __divslong + + #define b0 r1 + + ar0 = 0 ; BUG register set is not considered + ar1 = 1 + + ; parameter a comes in a, b, dph, dpl + mov a3,a ; save parameter a3 + + mov a,sp + add a,#-2-3 ; 2 bytes return address, 3 bytes param b + mov r0,a ; r0 points to b0 + + __divlong: ; entry point for __divslong + + mov ar1,@r0 ; load b0 + inc r0 ; r0 points to b1 + + mov count,#32 + clr a + mov reste0,a + mov reste1,a + mov reste2,a + mov reste3,a + + ; optimization loop in lp0 until the first bit is shifted into rest + + lp0: mov a,a0 ; a <<= 1 + add a,a0 + mov a0,a + mov a,a1 + rlc a + mov a1,a + mov a,a2 + rlc a + mov a2,a + mov a,a3 + rlc a + mov a3,a + + jc in_lp + djnz count,lp0 + + sjmp exit + + loop: mov a,a0 ; a <<= 1 + add a,a0 + mov a0,a + mov a,a1 + rlc a + mov a1,a + mov a,a2 + rlc a + mov a2,a + mov a,a3 + rlc a + mov a3,a + + in_lp: mov a,reste0 ; reste <<= 1 + rlc a ; feed in carry + mov reste0,a + mov a,reste1 + rlc a + mov reste1,a + mov a,reste2 + rlc a + mov reste2,a + mov a,reste3 + rlc a + mov reste3,a + + mov a,reste0 ; reste - b + subb a,b0 ; carry is always clear here, because + ; reste <<= 1 never overflows + mov a,reste1 + subb a,@r0 ; b1 + mov a,reste2 + inc r0 + subb a,@r0 ; b2 + mov a,reste3 + inc r0 + subb a,@r0 ; b3 + dec r0 + dec r0 + + jc minus ; reste >= b? + + ; -> yes; reste -= b; + mov a,reste0 + subb a,b0 ; carry is always clear here (jc) + mov reste0,a + mov a,reste1 + subb a,@r0 ; b1 + mov reste1,a + mov a,reste2 + inc r0 + subb a,@r0 ; b2 + mov reste2,a + mov a,reste3 + inc r0 + subb a,@r0 ; b3 + mov reste3,a + dec r0 + dec r0 + + orl a0,#1 + + minus: djnz count,loop ; -> no + + exit: mov a,a3 ; prepare the return value + ret + + _endasm ; +} + +#else // _DIVULONG_ASM + +#define MSB_SET(x) ((x >> (8*sizeof(x)-1)) & 1) + +unsigned long +_divulong (unsigned long a, unsigned long b) +{ + unsigned long reste = 0L; + unsigned char count = 32; + #if defined(__SDCC_STACK_AUTO) || defined(__SDCC_z80) || defined(__SDCC_sm83) + char c; + #else + bit c; + #endif + + do + { + // reste: a <- 0; + c = MSB_SET(a); + a <<= 1; + reste <<= 1; + if (c) + reste |= 1L; + + if (reste >= b) + { + reste -= b; + // a <- (result = 1) + a |= 1L; + } + } + while (--count); + return a; +} + +#endif // _DIVULONG_ASM diff --git a/gbdk/gbdk-lib/libc/_modslong.c b/gbdk/gbdk-lib/libc/_modslong.c new file mode 100644 index 00000000..ad75c0ad --- /dev/null +++ b/gbdk/gbdk-lib/libc/_modslong.c @@ -0,0 +1,35 @@ +/*------------------------------------------------------------------------- + _modslong.c - routine for modulus of 32 bit signed long + + Copyright (C) 1999, Sandeep Dutta . sandeep.dutta@usa.net + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library; see the file COPYING. If not, write to the + Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. + + As a special exception, if you link this library with other files, + some of which are compiled with SDCC, to produce an executable, + this library does not by itself cause the resulting executable to + be covered by the GNU General Public License. This exception does + not however invalidate any other reasons why the executable file + might be covered by the GNU General Public License. +-------------------------------------------------------------------------*/ + +unsigned long _modulong (unsigned long a, unsigned long b); + +long _modslong (long a, long b) { + long r; + r = _modulong((a < 0 ? -a : a), (b < 0 ? -b : b)); + return ( (a < 0) ^ (b < 0)) ? -r : r; +} diff --git a/gbdk/gbdk-lib/libc/_modulong.c b/gbdk/gbdk-lib/libc/_modulong.c new file mode 100644 index 00000000..360e4d63 --- /dev/null +++ b/gbdk/gbdk-lib/libc/_modulong.c @@ -0,0 +1,55 @@ +/*------------------------------------------------------------------------- + _modulong.c - routine for modulus of 32 bit unsigned long + + Copyright (C) 1999, Sandeep Dutta . sandeep.dutta@usa.net + Bug fixes by Martijn van Balen, aed@iae.nl + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library; see the file COPYING. If not, write to the + Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. + + As a special exception, if you link this library with other files, + some of which are compiled with SDCC, to produce an executable, + this library does not by itself cause the resulting executable to + be covered by the GNU General Public License. This exception does + not however invalidate any other reasons why the executable file + might be covered by the GNU General Public License. +-------------------------------------------------------------------------*/ + +#define MSB_SET(x) ((x >> (8*sizeof(x)-1)) & 1) + +unsigned long _modulong (unsigned long a, unsigned long b) +{ + unsigned char count = 0; + + while (!MSB_SET(b)) + { + b <<= 1; + if (b > a) + { + b >>=1; + break; + } + count++; + } + do + { + if (a >= b) + a -= b; + b >>= 1; + } + while (count--); + + return a; +} diff --git a/gbdk/gbdk-lib/libc/_mullong.c b/gbdk/gbdk-lib/libc/_mullong.c new file mode 100644 index 00000000..41181587 --- /dev/null +++ b/gbdk/gbdk-lib/libc/_mullong.c @@ -0,0 +1,91 @@ +/*------------------------------------------------------------------------- + _mullong.c - routine for multiplication of 32 bit (unsigned) long + + Copyright (C) 1999, Sandeep Dutta . sandeep.dutta@usa.net + Copyright (C) 1999, Jean Louis VERN jlvern@writeme.com + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library; see the file COPYING. If not, write to the + Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. + + As a special exception, if you link this library with other files, + some of which are compiled with SDCC, to produce an executable, + this library does not by itself cause the resulting executable to + be covered by the GNU General Public License. This exception does + not however invalidate any other reasons why the executable file + might be covered by the GNU General Public License. +-------------------------------------------------------------------------*/ + + +struct some_struct { + short a ; + char b; + long c ;}; +union bil { + struct {unsigned char b0,b1,b2,b3 ;} b; + struct {unsigned short lo,hi ;} i; + unsigned long l; + struct { unsigned char b0; unsigned short i12; unsigned char b3;} bi; +} ; + +#define bcast(x) ((union bil *)&(x)) + +/* + 3 2 1 0 + X 3 2 1 0 + ---------------------------- + 0.3 0.2 0.1 0.0 + 1.3 1.2 1.1 1.0 + 2.3 2.2 2.1 2.0 + 3.3 3.2 3.1 3.0 + ---------------------------- + |3.3|1.3|0.2|0.0| A + |2.3|0.3|0.1| B + |3.2|1.2|1.0| C + |2.2|1.1| D + |3.1|2.0| E + |2.1| F + |3.0| G + |-------> only this side 32 x 32 -> 32 +*/ + +/* 32x32->32 multiplication to be used + if 16x16->16 is faster than three 8x8->16. + 2009, by M.Bodrato ( http://bodrato.it/ ) + + z80 and sm83 don't have any hardware multiplication. + r2k and r3k have 16x16 hardware multiplication. + */ +long _mullong (long a, long b) +{ + unsigned short i12; + + bcast(a)->i.hi *= bcast(b)->i.lo; + bcast(a)->i.hi += bcast(b)->i.hi * bcast(a)->i.lo; + + /* only (a->i.lo * b->i.lo) 16x16->32 to do. asm? */ + bcast(a)->i.hi += bcast(a)->b.b1 * bcast(b)->b.b1; + + i12 = bcast(b)->b.b0 * bcast(a)->b.b1; + bcast(b)->bi.i12 = bcast(a)->b.b0 * bcast(b)->b.b1; + + /* add up the two partial result, store carry in b3 */ + bcast(b)->b.b3 = ((bcast(b)->bi.i12 += i12) < i12); + + bcast(a)->i.lo = bcast(a)->b.b0 * bcast(b)->b.b0; + + bcast(b)->bi.b0 = 0; + + return a + b; +} diff --git a/gbdk/gbdk-lib/libc/asm/Makefile.port b/gbdk/gbdk-lib/libc/asm/Makefile.port new file mode 100644 index 00000000..355e2f96 --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/Makefile.port @@ -0,0 +1,11 @@ +# Shared Makefile for all the ports. +# Provides a way of building the lib with little brains. + +LIB_APPEND = 1 + +all: port + +include $(TOPDIR)/libc/Makefile.rules + +port: $(LIB) + diff --git a/gbdk/gbdk-lib/libc/asm/sm83/Makefile b/gbdk/gbdk-lib/libc/asm/sm83/Makefile new file mode 100644 index 00000000..3506a104 --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/sm83/Makefile @@ -0,0 +1,22 @@ +# sm83 specific Makefile + +TOPDIR = ../../.. + +THIS = sm83 + +ASSRC = __sdcc_call_hl.s abs.s mul.s div.s shift.s crt0_rle.s \ + itoa.s strlen.s reverse.s labs.s ltoa.s \ + setjmp.s atomic_flag_test_and_set.s \ + memcpy.s _memset.s _strcmp.s _strcpy.s _memcmp.s \ + rand.s arand.s \ + bcd.s + +CSRC = _memmove.c + +include $(TOPDIR)/Makefile.common + +AS = $(AS_SM83) + +include ../Makefile.port + + diff --git a/gbdk/gbdk-lib/libc/asm/sm83/__sdcc_call_hl.s b/gbdk/gbdk-lib/libc/asm/sm83/__sdcc_call_hl.s new file mode 100644 index 00000000..d8686b29 --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/sm83/__sdcc_call_hl.s @@ -0,0 +1,38 @@ +;-------------------------------------------------------------------------- +; crtcall.s +; +; Copyright (C) 2011, Maarten Brock +; +; This library is free software; you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by the +; Free Software Foundation; either version 2, or (at your option) any +; later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this library; see the file COPYING. If not, write to the +; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, +; MA 02110-1301, USA. +; +; As a special exception, if you link this library with other files, +; some of which are compiled with SDCC, to produce an executable, +; this library does not by itself cause the resulting executable to +; be covered by the GNU General Public License. This exception does +; not however invalidate any other reasons why the executable file +; might be covered by the GNU General Public License. +;-------------------------------------------------------------------------- + + .module call_hl + + .area _HOME + + .globl ___sdcc_call_hl + +; The Z80 has the jp (hl) instruction, which is perfect for implementing function pointers. + +___sdcc_call_hl: + jp (hl) diff --git a/gbdk/gbdk-lib/libc/asm/sm83/_memcmp.s b/gbdk/gbdk-lib/libc/asm/sm83/_memcmp.s new file mode 100644 index 00000000..40c76fc1 --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/sm83/_memcmp.s @@ -0,0 +1,45 @@ + .module strcmp + + .area _HOME + +; int memcmp(const void *buf1, const void *buf2, size_t count) +_memcmp:: + lda hl,7(sp) + ld a,(hl-) + ld b, a + ld a,(hl-) + ld c, a + ld a,(hl-) + ld d, a + ld a,(hl-) + ld e, a + ld a,(hl-) + ld l,(hl) + ld h,a + + inc b + inc c + jr 3$ + +1$: + ld a,(de) + sub (hl) ; s1[i]==s2[i]? + jr nz, 2$ ; -> Different + + inc de + inc hl +3$: + dec c + jr nz, 1$ + dec b + jr nz, 1$ + + ld de, #0 + ret + +2$: + ld de,#1 + ret c + + ld de,#-1 + ret
\ No newline at end of file diff --git a/gbdk/gbdk-lib/libc/asm/sm83/_memmove.c b/gbdk/gbdk-lib/libc/asm/sm83/_memmove.c new file mode 100644 index 00000000..f30be660 --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/sm83/_memmove.c @@ -0,0 +1,54 @@ +/*------------------------------------------------------------------------- + _memmove.c - part of string library functions + + Copyright (C) 1999, Sandeep Dutta . sandeep.dutta@usa.net + Adapted By - Erik Petrich . epetrich@users.sourceforge.net + from _memcpy.c which was originally + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library; see the file COPYING. If not, write to the + Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. + + As a special exception, if you link this library with other files, + some of which are compiled with SDCC, to produce an executable, + this library does not by itself cause the resulting executable to + be covered by the GNU General Public License. This exception does + not however invalidate any other reasons why the executable file + might be covered by the GNU General Public License. +-------------------------------------------------------------------------*/ +#include <string.h> +#include <stdint.h> + +void *memmove (void *dst, const void *src, size_t size) +{ + size_t c = size; + if (c == 0) + return dst; + + char *d = dst; + const char *s = src; + if (s < d) { + d += c; + s += c; + do { + *--d = *--s; + } while (--c); + } else { + do { + *d++ = *s++; + } while (--c); + } + + return dst; +} diff --git a/gbdk/gbdk-lib/libc/asm/sm83/_memset.s b/gbdk/gbdk-lib/libc/asm/sm83/_memset.s new file mode 100644 index 00000000..9b9f4387 --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/sm83/_memset.s @@ -0,0 +1,52 @@ + .module memset + + .area _HOME + +; void *memset (void *s, int c, size_t n) +_memset:: + lda hl,7(sp) + ld a,(hl-) + ld d, a + ld a,(hl-) + ld e, a + or d + jr z,6$ + + dec hl + ld a,(hl-) + push af + ld a,(hl-) + ld l,(hl) + ld h,a + pop af + + srl d + rr e + jr nc,4$ + ld (hl+),a +4$: + srl d + rr e + jr nc,5$ + ld (hl+),a + ld (hl+),a +5$: + inc d + inc e + jr 2$ +1$: + ld (hl+),a + ld (hl+),a + ld (hl+),a + ld (hl+),a +2$: + dec e + jr nz,1$ + dec d + jr nz,1$ +6$: + lda hl,2(sp) + ld a,(hl+) + ld e,a + ld d,(hl) + ret diff --git a/gbdk/gbdk-lib/libc/asm/sm83/_strcmp.s b/gbdk/gbdk-lib/libc/asm/sm83/_strcmp.s new file mode 100644 index 00000000..5725b168 --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/sm83/_strcmp.s @@ -0,0 +1,35 @@ + .module strcmp + + .area _HOME + +; int strcmp(const char *s1, const char *s2) +_strcmp:: + lda hl,2(sp) + ld a,(hl+) + ld e, a + ld a,(hl+) + ld d, a + ld a,(hl+) + ld h,(hl) + ld l,a +1$: + ld a,(de) + sub (hl) ; s1[i]==s2[i]? + jr nz, 2$ ; -> Different + ;; A == 0 + cp (hl) ; s1[i]==s2[i]==0? + + inc de + inc hl + jr nz, 1$ ; ^ Didn't reach a null character. Loop. + + ; Yes. return 0; + ld d, a ; Since a == 0 this is faster than a 16 bit immediate load. + ld e, a + ret +2$: + ld de,#-1 + ret c + + ld de,#1 + ret
\ No newline at end of file diff --git a/gbdk/gbdk-lib/libc/asm/sm83/_strcpy.s b/gbdk/gbdk-lib/libc/asm/sm83/_strcpy.s new file mode 100644 index 00000000..748a0e5e --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/sm83/_strcpy.s @@ -0,0 +1,26 @@ + .module strcpy + + .area _HOME + +; char *strcpy(char *dest, const char *source) +_strcpy:: + lda hl,2(sp) + ld a,(hl+) + ld e, a + ld a,(hl+) + ld d, a + ld a,(hl+) + ld h,(hl) + ld l,a + + push de +1$: + ld a,(hl+) + ld (de),a + inc de + or a,a + jr nz,1$ + + pop de + ret +
\ No newline at end of file diff --git a/gbdk/gbdk-lib/libc/asm/sm83/abs.s b/gbdk/gbdk-lib/libc/asm/sm83/abs.s new file mode 100644 index 00000000..da139bdf --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/sm83/abs.s @@ -0,0 +1,19 @@ + .module abs + + .area _HOME + +; int abs(int) +_abs:: + lda HL, 3(SP) ; 3 + ld A,(HL-) ; 2 Load high byte. + ld D,A ; 1 + ld E,(HL) ; 2 Load low byte + add A,A ; 1 Sign check. + ret nc ; 5/2 Return if positive. + xor A ; 1 A=0. + sub E ; 1 Calculate 0-(low byte). + ld E,A ; 1 + ld A,#0 ; 2 A=0. Can't use xor A because carry flag needs to be preserved. + sbc D ; 1 Calculate 0-(high byte)-carry. + ld D,A ; 1 + ret ; 4 diff --git a/gbdk/gbdk-lib/libc/asm/sm83/arand.s b/gbdk/gbdk-lib/libc/asm/sm83/arand.s new file mode 100644 index 00000000..34dfd3d5 --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/sm83/arand.s @@ -0,0 +1,116 @@ +;/*************************************************************************** +; * * +; * Module : arand.s * +; * * +; * Purpose : A random number generator using the lagged additive method * +; * * +; * Version : 1, January 11 1998 * +; * * +; * Author : Luc Van den Borre ( Homepage : NOC.BASE.ORG ) * +; * * +; **************************************************************************/ + + .globl .initrand + .globl _rand + + .area _DATA + +.randarr: + .ds 55 +.raxj: + .ds 0x01 +.raxk: + .ds 0x01 + + .area _CODE + + ;; arand() operates on an array of 55 arbitrary values (here : bytes). + ;; It adds two values of the array together, replaces one of the values + ;; with the result, and returns the result. + ;; At start, the indices into the array refer to the 55th and 24th element. + ;; After each call, each index is decreased, and looped around if necessary. + ;; This kind of works, but the values produces are less good than those by + ;; rand(), mainly because it operates on bytes instead of words. + ;; Ref : D. E. Knuth, "The Art of Computer Programming" , Volume 2 + ;; + ;; Exit conditions + ;; DE = Random number (byte!) + ;; + ;; Registers used: + ;; all + ;; +_arand:: ; Banked + PUSH BC + LD D,#0 + LD HL,#.randarr-1 + LD A,(.raxj) + LD E,A + DEC A ; Decrease the pointer + JR NZ,1$ + LD A,#55 +1$: + LD (.raxj),A + ADD HL,DE + LD B,(HL) + + LD HL,#.randarr-1 ; Ooh... + LD A,(.raxk) + LD E,A + DEC A ; Decrease the pointer + JR NZ,2$ + LD A,#55 +2$: + LD (.raxk),A + ADD HL,DE + LD A,(HL) + + ADD B + LD (HL),A ; Store new value + + POP BC + + LD D,#0 + LD E,A + + RET + + ;; _initarand calls the _rand function to fill the array with random values + ;; Note that this also sets the seed value of the _rand function first, + ;; like _initrand + ;; + ;; Exit conditions + ;; None + ;; + ;; Registers used: + ;; all + ;; +_initarand:: ; Banked + LDA HL,2(SP) + CALL .initrand + + PUSH BC + LD A,#55 + LD HL,#.randarr +1$: + DEC A + LD (.raxj),A + LD B,H + LD C,L + CALL _rand + LD H,B + LD L,C + + LD A, E + LD (HL+),A + + LD A,(.raxj) + CP #0 + JR NZ,1$ + + LD A,#24 ; Now the array has been filled,set the pointers + LD (.raxj),A + LD A,#55 + LD (.raxk),A + + POP BC + RET diff --git a/gbdk/gbdk-lib/libc/asm/sm83/atomic_flag_test_and_set.s b/gbdk/gbdk-lib/libc/asm/sm83/atomic_flag_test_and_set.s new file mode 100644 index 00000000..f1a09726 --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/sm83/atomic_flag_test_and_set.s @@ -0,0 +1,46 @@ +;-------------------------------------------------------------------------- +; atomic_flag_test_and_set.s +; +; Copyright (C) 2020, Philipp Klaus Krause +; +; This library is free software; you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by the +; Free Software Foundation; either version 2, or (at your option) any +; later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this library; see the file COPYING. If not, write to the +; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, +; MA 02110-1301, USA. +; +; As a special exception, if you link this library with other files, +; some of which are compiled with SDCC, to produce an executable, +; this library does not by itself cause the resulting executable to +; be covered by the GNU General Public License. This exception does +; not however invalidate any other reasons why the executable file +; might be covered by the GNU General Public License. +;-------------------------------------------------------------------------- + + .module atomic + + .area _HOME + + .globl _atomic_flag_test_and_set + +_atomic_flag_test_and_set: + pop de + pop hl + push hl + push de + xor a, a + srl (hl) + ccf + rla + ld e, a + ret + diff --git a/gbdk/gbdk-lib/libc/asm/sm83/bcd.s b/gbdk/gbdk-lib/libc/asm/sm83/bcd.s new file mode 100644 index 00000000..238dd1b2 --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/sm83/bcd.s @@ -0,0 +1,233 @@ +;-------------------------------------------------------------------------- +; bcd.s +; +; Copyright (C) 2020, Tony Pavlov +; +; This library is free software; you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by the +; Free Software Foundation; either version 2, or (at your option) any +; later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this library; see the file COPYING. If not, write to the +; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, +; MA 02110-1301, USA. +; +; As a special exception, if you link this library with other files, +; some of which are compiled with SDCC, to produce an executable, +; this library does not by itself cause the resulting executable to +; be covered by the GNU General Public License. This exception does +; not however invalidate any other reasons why the executable file +; might be covered by the GNU General Public License. +;-------------------------------------------------------------------------- + + .module bcd + + .area _HOME + +; void uint2bcd(uint16_t i, BCD * value) __naked +_uint2bcd:: + lda HL, 2(SP) + ld A, (HL+) ; DE: uint + ld E, A + ld A, (HL+) + ld D, A + ld A, (HL+) + ld H, (HL) + ld L, A ; HL: dest + + push BC + + ; clear value + xor A + ld BC, #-4 + + ld (HL+), A + ld (HL+), A + ld (HL+), A + ld (HL+), A + add HL, BC + + ld B, #16 +1$: + sla E + rl D + + ld A, (HL) + adc A + daa + ld (HL+), A + ld A, (HL) + adc A + daa + ld (HL+), A + ld A, (HL) + adc A + daa + ld (HL-), A + + dec HL + + dec B + jr NZ, 1$ + + pop BC + ret + +;void bcd_add(BCD * sour, BCD * value) __naked +_bcd_add:: + lda HL, 5(SP) + ld D, (HL) + dec HL + ld E, (HL) ; DE: value + dec HL + ld A, (HL-) + ld L, (HL) + ld H, A ; HL: sour + + or A ; clear C, HC + + ld A,(DE) + add (HL) + daa + ld (HL+), A + inc DE + + ld A,(DE) + adc (HL) + daa + ld (HL+), A + inc DE + + ld A,(DE) + adc (HL) + daa + ld (HL+), A + inc DE + + ld A,(DE) + adc (HL) + daa + ld (HL+), A + + ret + +; void bcd_sub(BCD * sour, BCD * value) __naked +_bcd_sub:: + lda HL, 2(SP) + ld E, (HL) + inc HL + ld D, (HL) ; DE: sour + inc HL + ld A, (HL+) + ld H, (HL) + ld L, A ; HL: value + + or A ; clear C, HC + + ld A,(DE) + sub (HL) + daa + ld (DE), A + inc DE + inc HL + + ld A,(DE) + sbc (HL) + daa + ld (DE), A + inc DE + inc HL + + ld A,(DE) + sbc (HL) + daa + ld (DE), A + inc DE + inc HL + + ld A,(DE) + sbc (HL) + daa + ld (DE), A + + ret + +;uint8_t bcd2text(BCD * bcd, uint8_t tile_offset, uint8_t * buffer) __naked +_bcd2text:: + push BC + + lda HL, 4(SP) + ld E, (HL) + inc HL + ld D, (HL) ; DE: bcd + inc HL + ld C, (HL) ; C: digit offset + inc HL + ld A, (HL+) + ld H, (HL) + ld L, A ; HL: buffer + + inc DE + inc DE + inc DE + + ld B, #0x0f + + ld A, (DE) + swap A + and B + add C + ld (HL+), A + ld A, (DE) + and B + add C + ld (HL+), A + dec DE + + ld A, (DE) + swap A + and B + add C + ld (HL+), A + ld A, (DE) + and B + add C + ld (HL+), A + dec DE + + ld A, (DE) + swap A + and B + add C + ld (HL+), A + ld A, (DE) + and B + add C + ld (HL+), A + dec DE + + ld A, (DE) + swap A + and B + add C + ld (HL+), A + ld A, (DE) + and B + add C + ld (HL+), A + dec DE + + xor A + ld (HL+), A + + ld D, A + ld E, #0x08 + + pop BC + ret diff --git a/gbdk/gbdk-lib/libc/asm/sm83/crt0_rle.s b/gbdk/gbdk-lib/libc/asm/sm83/crt0_rle.s new file mode 100644 index 00000000..e3bdabcb --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/sm83/crt0_rle.s @@ -0,0 +1,69 @@ +;-------------------------------------------------------------------------- +; __initrleblock.s +; +; Copyright (C) 2001, Michael Hope +; Copyright (C) 2020, Sergey Belyashov +; +; This library is free software; you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by the +; Free Software Foundation; either version 2, or (at your option) any +; later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this library; see the file COPYING. If not, write to the +; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, +; MA 02110-1301, USA. +; +; As a special exception, if you link this library with other files, +; some of which are compiled with SDCC, to produce an executable, +; this library does not by itself cause the resulting executable to +; be covered by the GNU General Public License. This exception does +; not however invalidate any other reasons why the executable file +; might be covered by the GNU General Public License. +;-------------------------------------------------------------------------- + + .module rledecompress + + .area _HOME + + ;; Special RLE decoder used for initing global data + ;; input: DE - destination address +__initrleblock:: + ;; Pop the return address + pop hl +1$: + ;; Fetch the run + ld c, (hl) + inc hl + ;; Negative means a run + bit 7, c + jr Z, 2$ + ;; Expanding a run + ld a, (hl+) +3$: + ld (de), a + inc de + inc c + jr NZ, 3$ + jr 1$ +2$: + ;; Zero means end of a block + inc c + dec c + jr Z, 4$ + ;; Expanding a block +5$: + ld a, (hl+) + ld (de), a + inc de + dec c + jr NZ, 5$ + jr 1$ +4$: + ;; Return back + jp (hl)
\ No newline at end of file diff --git a/gbdk/gbdk-lib/libc/asm/sm83/div.s b/gbdk/gbdk-lib/libc/asm/sm83/div.s new file mode 100644 index 00000000..8e2df66a --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/sm83/div.s @@ -0,0 +1,339 @@ +;-------------------------------------------------------------------------- +; div.s +; +; Copyright (C) 2000, Michael Hope +; Copyright (C) 2021, Sebastian 'basxto' Riedel (sdcc@basxto.de) +; Copyright (c) 2021, Philipp Klaus Krause +; +; This library is free software; you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by the +; Free Software Foundation; either version 2, or (at your option) any +; later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this library; see the file COPYING. If not, write to the +; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, +; MA 02110-1301, USA. +; +; As a special exception, if you link this library with other files, +; some of which are compiled with SDCC, to produce an executable, +; this library does not by itself cause the resulting executable to +; be covered by the GNU General Public License. This exception does +; not however invalidate any other reasons why the executable file +; might be covered by the GNU General Public License. +;-------------------------------------------------------------------------- + + ;; Originally from GBDK by Pascal Felber. + .module divmod + .area _CODE +.globl __divsuchar +.globl __modsuchar +.globl __divuschar +.globl __moduschar +.globl __divschar +.globl __modschar +.globl __divsint +.globl __modsint +.globl __divuchar +.globl __moduchar +.globl __divuint +.globl __moduint + +__divsuchar: + ld c, a + ld b, #0 + + jp signexte + +__modsuchar: + ld c, a + ld b, #0 + + call signexte + + ld c, e + ld b, d + + ret + +__divuschar: + ld d, #0 + + ld c, a ; Sign extend + rlca + sbc a + ld b,a + + jp .div16 + +__moduschar: + ld e, a + ld d, #0 + + ld a,c ; Sign extend + rlca + sbc a + ld b,a + + call .div16 + + ld c, e + ld b, d + + ret + +__divschar: + ld c, a + + call .div8 + + ret + +__modschar: + ld c, a + + call .div8 + + ld c, e + ld b, d + + ret + +__divsint: + ld a, e + ld e, c + ld c, a + + ld a, d + ld d, b + ld b, a + + jp .div16 + +__modsint: + ld a, e + ld e, c + ld c, a + + ld a, d + ld d, b + ld b, a + + call .div16 + + ld c, e + ld b, d + + ret + + ;; Unsigned +__divuchar: + ld c, a + + call .divu8 + + ret + +__moduchar: + ld c, a + + call .divu8 + + ld c, e + ld b, d + + ret + +__divuint: + ld a, e + ld e, c + ld c, a + + ld a, d + ld d, b + ld b, a + + jp .divu16 + +__moduint: + ld a, e + ld e, c + ld c, a + + ld a, d + ld d, b + ld b, a + + call .divu16 + + ld c, e + ld b, d + + ret + +.div8:: +.mod8:: + ld a,c ; Sign extend + rlca + sbc a + ld b,a +signexte: + ld a, e ; Sign extend + rlca + sbc a + ld d, a + + ; Fall through to .div16 + + ;; 16-bit division + ;; + ;; Entry conditions + ;; BC = dividend + ;; DE = divisor + ;; + ;; Exit conditions + ;; BC = quotient + ;; DE = remainder + ;; If divisor is non-zero, carry=0 + ;; If divisor is 0, carry=1 and both quotient and remainder are 0 + ;; + ;; Register used: AF,BC,DE,HL +.div16:: +.mod16:: + ;; Determine sign of quotient by xor-ing high bytes of dividend + ;; and divisor. Quotient is positive if signs are the same, negative + ;; if signs are different + ;; Remainder has same sign as dividend + ld a,b ; Get high byte of dividend + push af ; Save as sign of remainder + xor d ; Xor with high byte of divisor + push af ; Save sign of quotient + + ;; Take absolute value of divisor + bit 7,d + jr Z,.chkde ; Jump if divisor is positive + sub a ; Substract divisor from 0 + sub e + ld e,a + sbc a ; Propagate borrow (A=0xFF if borrow) + sub d + ld d,a + ;; Take absolute value of dividend +.chkde: + bit 7,b + jr Z,.dodiv ; Jump if dividend is positive + sub a ; Substract dividend from 0 + sub c + ld c,a + sbc a ; Propagate borrow (A=0xFF if borrow) + sub b + ld b,a + ;; Divide absolute values +.dodiv: + call .divu16 + jr C,.exit ; Exit if divide by zero + ;; Negate quotient if it is negative + pop af ; recover sign of quotient + and #0x80 + jr Z,.dorem ; Jump if quotient is positive + sub a ; Substract quotient from 0 + sub c + ld c,a + sbc a ; Propagate borrow (A=0xFF if borrow) + sub b + ld b,a +.dorem: + ;; Negate remainder if it is negative + pop af ; recover sign of remainder + and #0x80 + ret Z ; Return if remainder is positive + sub a ; Substract remainder from 0 + sub e + ld e,a + sbc a ; Propagate remainder (A=0xFF if borrow) + sub d + ld d,a + ret +.exit: + pop af + pop af + ret + +.divu8:: +.modu8:: + ld b,#0x00 + ld d,b + ; Fall through to divu16 + +.divu16:: +.modu16:: + ;; Check for division by zero + ld a,e + or d + jr NZ,.divide ; Branch if divisor is non-zero + ld bc,#0x00 ; Divide by zero error + ld d,b + ld e,c + scf ; Set carry, invalid result + ret +.divide: + ld l,c ; L = low byte of dividend/quotient + ld h,b ; H = high byte of dividend/quotient + ld bc,#0x00 ; BC = remainder + or a ; Clear carry to start + ld a,#16 ; 16 bits in dividend +.dvloop: + ;; Shift next bit of quotient into bit 0 of dividend + ;; Shift next MSB of dividend into LSB of remainder + ;; BC holds both dividend and quotient. While we shift a bit from + ;; MSB of dividend, we shift next bit of quotient in from carry + ;; HL holds remainder + ;; Do a 32-bit left shift, shifting carry to L, L to H, + ;; H to C, C to B + push af ; save number of bits remaining + rl l ; Carry (next bit of quotient) to bit 0 + rl h ; Shift remaining bytes + rl c + rl b ; Clears carry since BC was 0 + ;; If remainder is >= divisor, next bit of quotient is 1. This + ;; bit goes to carry + push bc ; Save current remainder + ld a,c ; Substract divisor from remainder + sbc e + ld c,a + ld a,b + sbc d + ld b,a + ccf ; Complement borrow so 1 indicates a + ; successful substraction (this is the + ; next bit of quotient) + jr C,.drop ; Jump if remainder is >= dividend + pop bc ; Otherwise, restore remainder + pop af ; recover # bits remaining, carry flag destroyed + dec a + or a ; restore (clear) the carry flag + jr NZ,.dvloop + jr .nodrop +.drop: + pop af ; faster and smaller than 2x inc sp + pop af ; recover # bits remaining, carry flag destroyed + dec a + scf ; restore (set) the carry flag + jr NZ,.dvloop + jr .nodrop +.nodrop: + ;; Shift last carry bit into quotient + ld d,b ; DE = remainder + ld e,c + rl l ; Carry to L + ld c,l ; C = low byte of quotient + rl h + ld b,h ; B = high byte of quotient + or a ; Clear carry, valid result + ret + diff --git a/gbdk/gbdk-lib/libc/asm/sm83/itoa.s b/gbdk/gbdk-lib/libc/asm/sm83/itoa.s new file mode 100644 index 00000000..0e983441 --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/sm83/itoa.s @@ -0,0 +1,190 @@ +;-------------------------------------------------------------------------- +; itoa.s +; +; Copyright (C) 2020, Tony Pavlov +; +; This library is free software; you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by the +; Free Software Foundation; either version 2, or (at your option) any +; later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this library; see the file COPYING. If not, write to the +; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, +; MA 02110-1301, USA. +; +; As a special exception, if you link this library with other files, +; some of which are compiled with SDCC, to produce an executable, +; this library does not by itself cause the resulting executable to +; be covered by the GNU General Public License. This exception does +; not however invalidate any other reasons why the executable file +; might be covered by the GNU General Public License. +;-------------------------------------------------------------------------- + + .module itoa + + .area _HOME + +_uitoa:: + push BC + lda HL, 4(SP) + ld A, (HL+) + ld E, A + ld A, (HL+) + ld D, A ; DE: uint + ld A, (HL+) + ld C, A + ld B, (HL) ; BC: dest + call .utoa + pop BC + ret + +_itoa:: + push BC + lda HL, 4(SP) + ld A, (HL+) + ld E, A + ld A, (HL+) + ld D, A ; DE: int + ld A, (HL+) + ld C, A + ld B, (HL) ; BC: dest + call .itoa + pop BC + ret + +.itoa:: ; convert int into ascii + ld A, D + add A, A + jr NC, .utoa + + rra ; DE = abs(DE) + cpl + ld D, A + ld A, E + cpl + ld E, A + inc DE + + ld A, #'-' + ld (BC), A + inc BC + + call .utoa + dec DE + ret + +.utoa:: ; convert unsigned int into ascii + add SP, #-3 + lda HL, 2(SP) + + xor A ; clear value + ld (HL-), A + ld (HL-), A + ld (HL), A + + push BC + ld B, #8 +1$: + sla E + rl D + + ld A, (HL) + adc A + daa + ld (HL+), A + ld A, (HL) + adc A + daa + ld (HL+), A + ld A, (HL) + adc A + daa + ld (HL-), A + dec HL + + sla E + rl D + + ld A, (HL) + adc A + daa + ld (HL+), A + ld A, (HL) + adc A + daa + ld (HL+), A + ld A, (HL) + adc A + daa + ld (HL-), A + dec HL + + dec B + jr NZ, 1$ + + pop BC + push BC + + ld DE, #'0' + lda HL, 4(SP) + + ld A, (HL-) + and #0x0f + or A + jr Z, 3$ + add A, E + ld D, #1 ; make D nonzero + ld (BC), A + inc BC +3$: + ld A, (HL) + swap A + and #0x0f + add D + jr Z, 4$ + sub D + add A, E + ld D, #1 ; make D nonzero + ld (BC), A + inc BC +4$: + ld A, (HL-) + and #0x0f + add D + jr Z, 5$ + sub D + add A, E + ld D, #1 ; make D nonzero + ld (BC), A + inc BC +5$: + ld A, (HL) + swap A + and #0x0f + add D + jr Z, 6$ + sub D + add A, E + ld (BC), A + inc BC +6$: + ld A, (HL) + and #0x0f + add A, E + ld (BC), A + inc BC + + xor A + ld (BC), A ; write trailing #0 + + pop DE + + add sp, #3 + + ret diff --git a/gbdk/gbdk-lib/libc/asm/sm83/labs.s b/gbdk/gbdk-lib/libc/asm/sm83/labs.s new file mode 100644 index 00000000..390e925b --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/sm83/labs.s @@ -0,0 +1,70 @@ +;-------------------------------------------------------------------------- +; labs.s +; +; Copyright (C) 2020, Tony Pavlov +; +; This library is free software; you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by the +; Free Software Foundation; either version 2, or (at your option) any +; later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this library; see the file COPYING. If not, write to the +; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, +; MA 02110-1301, USA. +; +; As a special exception, if you link this library with other files, +; some of which are compiled with SDCC, to produce an executable, +; this library does not by itself cause the resulting executable to +; be covered by the GNU General Public License. This exception does +; not however invalidate any other reasons why the executable file +; might be covered by the GNU General Public License. +;-------------------------------------------------------------------------- + + .module labs + + .area _HOME + +;long labs(long num) +_labs:: + lda HL, 2(SP) + ld A, (HL+) + ld E, A + ld A, (HL+) + ld D, A + ld A, (HL+) + ld H, (HL) + ld L, A ; DEHL = num + +.labs:: + ld A, H + add A, A + ret NC + +1$: + ld A, E + cpl + add #1 + ld E, A + + ld A, D + cpl + adc #0 + ld D, A + + ld A, L + cpl + adc #0 + ld L, A + + ld A, H + cpl + adc #0 + ld H, A + + ret diff --git a/gbdk/gbdk-lib/libc/asm/sm83/ltoa.s b/gbdk/gbdk-lib/libc/asm/sm83/ltoa.s new file mode 100644 index 00000000..5a4da145 --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/sm83/ltoa.s @@ -0,0 +1,222 @@ +;-------------------------------------------------------------------------- +; ltoa.s +; +; Copyright (C) 2020, Tony Pavlov +; +; This library is free software; you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by the +; Free Software Foundation; either version 2, or (at your option) any +; later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this library; see the file COPYING. If not, write to the +; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, +; MA 02110-1301, USA. +; +; As a special exception, if you link this library with other files, +; some of which are compiled with SDCC, to produce an executable, +; this library does not by itself cause the resulting executable to +; be covered by the GNU General Public License. This exception does +; not however invalidate any other reasons why the executable file +; might be covered by the GNU General Public License. +;-------------------------------------------------------------------------- + + .module ltoa + + .area _HOME + +_ultoa:: + push BC + + lda HL, 8(SP) + ld A, (HL+) + ld C, A + ld B, (HL) ; BC: dest + + lda HL, 4(SP) + ld E, L + ld D, H ; DE : ulong * + + call .ultoa + + pop BC + ret + +_ltoa:: + push BC + + lda HL, 8(SP) + ld A, (HL+) + ld C, A + ld B, (HL) ; BC: dest + + lda HL, 4(SP) + ld E, L + ld D, H ; DE : ulong * + + call .ltoa + + pop BC + ret + +.ltoa:: + push DE + + ld A, #3 + add E + ld E, A + adc D + sub E + ld D, A + + ld A, (DE) + add A, A + pop DE + jr NC, .ultoa + +1$: + push DE + ld A, (DE) + cpl + add #1 + ld (DE), A + inc DE + + ld A, (DE) + cpl + adc #0 + ld (DE), A + inc DE + + ld A, (DE) + cpl + adc #0 + ld (DE), A + inc DE + + ld A, (DE) + cpl + adc #0 + ld (DE), A + + pop DE + + ld A, #'-' + ld (BC), A + inc BC + + call .ultoa + dec DE + ret + +.ultoa:: ; convert unsigned int into ascii + add SP, #-5 + lda HL, 4(SP) + + xor A ; clear value + ld (HL-), A + ld (HL-), A + ld (HL-), A + ld (HL-), A + ld (HL), A + + push BC + ld B, #32 +1$: + ld H, D + ld L, E + + sla (HL) + inc HL + rl (HL) + inc HL + rl (HL) + inc HL + rl (HL) + + rra + lda HL, 2(SP) + rla + + ld A, (HL) + adc A + daa + ld (HL+), A ; #0 + ld A, (HL) + adc A + daa + ld (HL+), A ; #1 + ld A, (HL) + adc A + daa + ld (HL+), A ; #2 + ld A, (HL) + adc A + daa + ld (HL+), A ; #3 + ld A, (HL) + adc A + daa + ld (HL), A ; #4 + + dec B + jr NZ, 1$ + + pop BC + push BC + + ld DE, #((5 << 8) | '0') + lda HL, 6(SP) + + scf + ccf + +3$: + rl D + ld A, (HL) + swap A + and #0x0f + bit 0, D + jr NZ, 6$ + or A + jr Z, 4$ +6$: + add A, E + ld (BC), A + set 0, D + inc BC +4$: + ld A, (HL-) + and #0x0f + bit 0, D + jr NZ, 7$ + or A + jr Z, 5$ +7$: + add A, E + ld (BC), A + set 0, D + inc BC +5$: + rr D + dec D + jr NZ, 3$ + jr C, 8$ + + ld A, #'0' ; n == 0 + ld (BC), A + inc BC +8$: + xor A + ld (BC), A ; write trailing #0 + + pop DE + + add sp, #5 + + ret diff --git a/gbdk/gbdk-lib/libc/asm/sm83/memcpy.s b/gbdk/gbdk-lib/libc/asm/sm83/memcpy.s new file mode 100644 index 00000000..83357b5c --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/sm83/memcpy.s @@ -0,0 +1,94 @@ +;-------------------------------------------------------------------------- +; memcpy.s +; +; Copies in groups of four. Algorithm is Duff's device. +; +; Copyright (c) 2021, Philipp Klaus Krause +; Copyright (c) 2022, Sebastian 'basxto' Riedel <sdcc@basxto.de> +; +; This library is free software; you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by the +; Free Software Foundation; either version 2, or (at your option) any +; later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this library; see the file COPYING. If not, write to the +; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, +; MA 02110-1301, USA. +; +; As a special exception, if you link this library with other files, +; some of which are compiled with SDCC, to produce an executable, +; this library does not by itself cause the resulting executable to +; be covered by the GNU General Public License. This exception does +; not however invalidate any other reasons why the executable file +; might be covered by the GNU General Public License. +;-------------------------------------------------------------------------- + + .area _CODE + + .globl _memcpy + .globl ___memcpy + + ; gets called by memmove for (s >= d) + ; bigger than the old algorithm but faster for n>=5 +_memcpy:: +___memcpy:: + ;dest in de + ;src in bc + ;n in sp+2,sp+3 + push de + ldhl sp, #5 + ld a, (hl-) + ld l, (hl) + ld h, b + ld b, a + ld a, l + ld l, c + srl b + rra + ld c, a + ;dest in de (backup in sp+0,sp+1) + ;src in hl + ;n/2 in bc + ;LSB of bc in carry + jr nc, skip_one + ld a, (hl+) + ld (de), a + inc de +skip_one: + ;n/2 in bc + ;shift second LSB to carry + srl b + rr c + ;n/4 in bc + inc b + inc c + jr nc, test + jr copy_two +.irp idx,copy_four,copy_two + idx: + .rept 2 + ld a, (hl+) + ld (de), a + inc de + .endm +.endm +test: +.irp idx,c,b + dec idx + jr nz, copy_four +.endm + +end: + ;restore dest + pop bc + ;get return address + pop hl + ;throw away n + pop af + jp (hl)
\ No newline at end of file diff --git a/gbdk/gbdk-lib/libc/asm/sm83/mul.s b/gbdk/gbdk-lib/libc/asm/sm83/mul.s new file mode 100644 index 00000000..4d451208 --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/sm83/mul.s @@ -0,0 +1,158 @@ +;-------------------------------------------------------------------------- +; mul.s +; +; Copyright (C) 2000, Michael Hope +; Copyright (C) 2021-2022, Sebastian 'basxto' Riedel (sdcc@basxto.de) +; Copyright (c) 2021, Philipp Klaus Krause +; +; This library is free software; you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by the +; Free Software Foundation; either version 2, or (at your option) any +; later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this library; see the file COPYING. If not, write to the +; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, +; MA 02110-1301, USA. +; +; As a special exception, if you link this library with other files, +; some of which are compiled with SDCC, to produce an executable, +; this library does not by itself cause the resulting executable to +; be covered by the GNU General Public License. This exception does +; not however invalidate any other reasons why the executable file +; might be covered by the GNU General Public License. +;-------------------------------------------------------------------------- + + ;; Originally from GBDK by Pascal Felber. + + .module mul + .area _CODE + +.globl __mulsuchar +.globl __muluschar +.globl __mulschar +.globl __muluchar +.globl __mulint + +; operands with different sign + +__mulsuchar: + ld c, a + jr signexte + +__muluschar: + ld c, e + ld e, a + +signexte: + ld a,e + rla + sbc a,a + ld d,a + + xor a + jr .mul8 + +__mulschar: + ; Sign-extend before going in. + ld c,a + + rla + sbc a,a + ld b,a + + ld a,e + rla + sbc a,a + ld d,a + +__mulint: + ;; 16-bit multiplication + ;; + ;; Entry conditions + ;; BC = multiplicand + ;; DE = multiplier + ;; + ;; Exit conditions + ;; BC = less significant word of product + ;; + ;; Register used: AF,BC,DE,HL +.mul16: + ;; Let the smaller number loop + ld a,b + cp a,d + jr c, keep + ;; d <= b + ld a, e + ld e, c + ld c, a + ld a, d + ld d, b + ld b, a +keep: + ;; Optimise for the case when this side has 8 bits of data or + ;; less. This is often the case with support address calls. + or a + jp Z, .mul8 + + ld l,#0 + ld b,#16 +loop16: + ;; Taken from z88dk, which originally borrowed from the + ;; Spectrum rom. + add hl,hl + rl c + rla ;DLE 27/11/98 + jr NC,skip16 + add hl,de +skip16: + dec b + jr NZ,loop16 + + ;; Return in bc + ld c,l + ld b,h + + ret + +__muluchar: + ld c, a + xor a + ;; Clear the top + ld d, a + + ;; Version that uses an 8bit multiplicand + ;; + ;; Entry conditions + ;; C = multiplicand + ;; DE = multiplier + ;; A = 0 + ;; + ;; Exit conditions + ;; BC = less significant word of product + ;; + ;; Register used: AF,BC,DE,HL +.mul8: + ld l,a + ld b,#8 + ld a,c +loop8: + add hl,hl + rla + jr NC,skip8 + add hl,de +skip8: + dec b + jr NZ,loop8 + + ;; Return in bc + ld c,l + ld b,h + + ret + diff --git a/gbdk/gbdk-lib/libc/asm/sm83/rand.s b/gbdk/gbdk-lib/libc/asm/sm83/rand.s new file mode 100644 index 00000000..da51378b --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/sm83/rand.s @@ -0,0 +1,117 @@ +;/*************************************************************************** +; * * +; * Module : rand.s * +; * * +; * Purpose : A rand() generator using the linear congruential method * +; * * +; * Version : 1.01, January 7 1998 * +; * Added _initrand to set seed without recompiling * +; * 1, January 6 1998 * +; * * +; * Author : Luc Van den Borre ( Homepage : NOC.BASE.ORG ) * +; * * +; **************************************************************************/ + + ;; Why use an algorithm for generating random numbers? + ;; + ;; - Given a certain seed value, the same sequence of random numbers is generated + ;; every time. This is a good thing when debugging (reproducible). On the other + ;; hand, you've got 2^16 seed values, each of which will produce a sequence of + ;; numbers that stays different for any of the other sequences for 'an appreciable + ;; time.' (I can't say how long exactly.) + ;; + ;; - The linear congruential method is one of the 'best' random number generators + ;; around. However, this implementation uses a 16 bit accumulator, while at least + ;; 32 bits are needed for a generator that passes all the statistical tests. + ;; Still, I'm relatively confident that this is random enough for even the most + ;; demanding game. + ;; + ;; Compare this to getting random values from one of the hardware registers + ;; (not reproducible, might not have all values). An array might be the best bet + ;; if you don't need a lot of values (or have lots of memory spare), + ;; or if you want values to be within a certain range. + ;; And both would be faster than this. Also, this definitely isn't the fastest + ;; algorithm I know, and certainly for games less strict algorithms might be + ;; appropriate (shift and xor ?). + ;; It's your choice - but if you're doing Monte Carlo physics simulations on the + ;; GameBoy, this is a safe bet! + + .area _DATA +___rand_seed:: +.randlo: ; Storage for last random number (or seed) + .ds 0x01 +.randhi: + .ds 0x01 + + .area _HOME + + ;; Random number generator using the linear congruential method + ;; X(n+1) = (a*X(n)+c) mod m + ;; with a = 17, m = 16 and c = $5c93 (arbitrarily) + ;; The seed value is also chosen arbitrarily as $a27e + ;; Ref : D. E. Knuth, "The Art of Computer Programming" , Volume 2 + ;; + ;; Exit conditions + ;; DE = Random number [0,2^16-1] + ;; + ;; Registers used: + ;; A, HL (need not be saved) and DE (return register) + ;; + +_rand:: ; Banked +_randw:: ; Banked + LD A,(.randlo) + LD L,A + LD E,A ; Save randlo + LD A,(.randhi) + LD D,A ; Save randhi + + SLA L ; * 16 + RLA + SLA L + RLA + SLA L + RLA + SLA L + RLA + LD H,A ; Save randhi*16 + + LD A,E ; Old randlo + ADD A,L ; Add randlo*16 + LD L,A ; Save randlo*17 + + LD A,H ; randhi*16 + ADC A,D ; Add old randhi + LD H,A ; Save randhi*17 + + LD A,L ; randlo*17 + ADD A,#0x93 + LD (.randlo),A + LD D,A ; Return register + LD A,H ; randhi*17 + ADC A,#0x5c + LD (.randhi),A + LD E,A ; Return register + + ;; Note D is the low byte,E the high byte. This is intentional because + ;; the high byte can be slightly 'more random' than the low byte, and I presume + ;; most will cast the return value to a uint8_t. As if someone will use this, tha! + RET + + ;; This sets the seed value. Call it whenever you like + ;; + ;; Exit conditions + ;; None + ;; + ;; Registers used: + ;; A, HL (need not be saved) and DE (return register) + ;; + +_initrand:: + LDA HL,2(SP) +.initrand:: + LD A,(HL+) + LD (.randlo),A + LD A,(HL) + LD (.randhi),A + RET diff --git a/gbdk/gbdk-lib/libc/asm/sm83/reverse.s b/gbdk/gbdk-lib/libc/asm/sm83/reverse.s new file mode 100644 index 00000000..37e4a280 --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/sm83/reverse.s @@ -0,0 +1,84 @@ +;-------------------------------------------------------------------------- +; reverse.s +; +; Copyright (C) 2020, Tony Pavlov +; +; This library is free software; you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by the +; Free Software Foundation; either version 2, or (at your option) any +; later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this library; see the file COPYING. If not, write to the +; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, +; MA 02110-1301, USA. +; +; As a special exception, if you link this library with other files, +; some of which are compiled with SDCC, to produce an executable, +; this library does not by itself cause the resulting executable to +; be covered by the GNU General Public License. This exception does +; not however invalidate any other reasons why the executable file +; might be covered by the GNU General Public License. +;-------------------------------------------------------------------------- + + .module reverse + + .area _HOME + +_reverse:: + lda HL, 2(SP) + ld A, (HL+) + ld H, (HL) + ld L, A ; HL: s + + push BC + ld B, H + ld C, L ; BC: s + + ld DE, #0 +1$: ld A, (HL+) + or A + jr Z, 2$ + inc DE + jr 1$ + +2$: + srl D + rr E + + ld A, E + or D + jr Z, 3$ + + dec HL + dec HL + + inc D + inc E + jr 5$ +4$: + ld A, (HL) + push AF + ld A, (BC) + ld (HL-), A + pop AF + ld (BC), A + inc BC +5$: + dec E + jr NZ, 4$ + dec D + jr NZ, 4$ + +3$: + pop BC + lda HL, 2(SP) + ld E, (HL) + inc HL + ld D, (HL) + ret diff --git a/gbdk/gbdk-lib/libc/asm/sm83/setjmp.s b/gbdk/gbdk-lib/libc/asm/sm83/setjmp.s new file mode 100644 index 00000000..a17538e7 --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/sm83/setjmp.s @@ -0,0 +1,105 @@ +;-------------------------------------------------------------------------- +; setjmp.s +; +; Copyright (C) 2011-2014, Philipp Klaus Krause +; +; This library is free software; you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by the +; Free Software Foundation; either version 2, or (at your option) any +; later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this library; see the file COPYING. If not, write to the +; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, +; MA 02110-1301, USA. +; +; As a special exception, if you link this library with other files, +; some of which are compiled with SDCC, to produce an executable, +; this library does not by itself cause the resulting executable to +; be covered by the GNU General Public License. This exception does +; not however invalidate any other reasons why the executable file +; might be covered by the GNU General Public License. +;-------------------------------------------------------------------------- + + .module longjmp + + .area _HOME + + .globl ___setjmp + +___setjmp: + pop bc + pop de + push de + push bc + + ; Store stack pointer. + ldhl sp, #0 + push de + push hl + pop de + pop hl + ld (hl), e + inc hl + ld (hl), d + inc hl + + ; Store return address. + ld (hl), c + inc hl + ld (hl), b + + ; Return 0. + xor a, a + ld e, a + ld d, a + ret + +.globl _longjmp + +_longjmp: + pop af + pop hl + pop de + + ; Ensure that return value is non-zero. + ld a, e + or a, d + jr NZ, 0001$ + inc de +0001$: + + ; Get stack pointer. + ld c, (hl) + inc hl + ld b, (hl) + inc hl + + ; Adjust stack pointer. + push hl + push bc + pop hl + pop bc + ld sp, hl + push bc + pop hl + + ; Get return address. + ld c, (hl) + inc hl + ld b, (hl) + + ; Set return address. + pop af + push bc + + ; Return value is in de. + + ; Jump. + ret + diff --git a/gbdk/gbdk-lib/libc/asm/sm83/shift.s b/gbdk/gbdk-lib/libc/asm/sm83/shift.s new file mode 100644 index 00000000..d7b6d55a --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/sm83/shift.s @@ -0,0 +1,89 @@ + .module shift + + .area _HOME + + ;; +__rrulong_rrx_s:: + ld hl,#2 + add hl,sp + + ld a,(hl+) + ld e, a + ld a,(hl+) + ld d, a + ld a,(hl+) + ld c, a + ld a,(hl+) + ld b, a + ld a,(hl) + + ld l,c + ld h,b +1$: + or a,a + ret z + + rr h + rr l + rr d + rr e + + dec a + jp 1$ + +__rrslong_rrx_s:: + ld hl,#2 + add hl,sp + + ld a,(hl+) + ld e, a + ld a,(hl+) + ld d, a + ld a,(hl+) + ld c, a + ld a,(hl+) + ld b, a + ld a,(hl) + + ld l,c + ld h,b +1$: + or a,a + ret z + + sra h + rr l + rr d + rr e + + dec a + jp 1$ + +__rlslong_rrx_s:: +__rlulong_rrx_s:: + ld hl,#2 + add hl,sp + + ld a,(hl+) + ld e, a + ld a,(hl+) + ld d, a + ld a,(hl+) + ld c, a + ld a,(hl+) + ld b, a + ld a,(hl) + + ld l,c + ld h,b +1$: + or a,a + ret z + + rl e + rl d + rl l + rl h + + dec a + jp 1$ diff --git a/gbdk/gbdk-lib/libc/asm/sm83/strlen.s b/gbdk/gbdk-lib/libc/asm/sm83/strlen.s new file mode 100644 index 00000000..61fa9572 --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/sm83/strlen.s @@ -0,0 +1,44 @@ +;-------------------------------------------------------------------------- +; strlen.s +; +; Copyright (C) 2020, Tony Pavlov +; +; This library is free software; you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by the +; Free Software Foundation; either version 2, or (at your option) any +; later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this library; see the file COPYING. If not, write to the +; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, +; MA 02110-1301, USA. +; +; As a special exception, if you link this library with other files, +; some of which are compiled with SDCC, to produce an executable, +; this library does not by itself cause the resulting executable to +; be covered by the GNU General Public License. This exception does +; not however invalidate any other reasons why the executable file +; might be covered by the GNU General Public License. +;-------------------------------------------------------------------------- + + .module strlen + + .area _HOME + +_strlen:: + lda HL, 2(SP) + ld A, (HL+) + ld H, (HL) + ld L, A +.strlen:: + ld DE, #0 +1$: ld A, (HL+) + or A + ret Z + inc DE + jr 1$ diff --git a/gbdk/gbdk-lib/libc/asm/z80/Makefile b/gbdk/gbdk-lib/libc/asm/z80/Makefile new file mode 100644 index 00000000..4fd41fc6 --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/z80/Makefile @@ -0,0 +1,27 @@ +# z80 specific Makefile + +TOPDIR = ../../.. + +THIS = z80 + +ASSRC = __strreverse.s strcpy.s strlen.s \ + divmixed.s divsigned.s divunsigned.s \ + modsigned.s modunsigned.s modmixed.s \ + mul.s mulchar.s \ + __itoa.s __ltoa.s \ + __uitobcd.s __ultobcd.s \ + memcpy.s memmove.s memset.s memcmp.s \ + setjmp.s \ + abs.s \ + rand.s arand.s \ + __sdcc_call_hl.s __sdcc_call_iy.s \ + atomic_flag_test_and_set.s __sdcc_critical.s \ + crtenter.s + +include $(TOPDIR)/Makefile.common + +AS = $(AS_Z80) + +include ../Makefile.port + + diff --git a/gbdk/gbdk-lib/libc/asm/z80/__itoa.s b/gbdk/gbdk-lib/libc/asm/z80/__itoa.s new file mode 100644 index 00000000..a22cb1af --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/z80/__itoa.s @@ -0,0 +1,231 @@ +;-------------------------------------------------------------------------- +; __itoa.s +; +; Copyright (C) 2020, Sergey Belyashov +; +; This library is free software; you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by the +; Free Software Foundation; either version 2, or (at your option) any +; later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this library; see the file COPYING. If not, write to the +; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, +; MA 02110-1301, USA. +; +; As a special exception, if you link this library with other files, +; some of which are compiled with SDCC, to produce an executable, +; this library does not by itself cause the resulting executable to +; be covered by the GNU General Public License. This exception does +; not however invalidate any other reasons why the executable file +; might be covered by the GNU General Public License. +;-------------------------------------------------------------------------- + + .area _CODE + + .globl _itoa + .globl _uitoa +; +;void __itoa(int value, char *string, unsigned char radix); +; +_itoa:: + push ix + ld ix, #0 + add ix, sp +; +; 4(ix) - value +; 6(ix) - string +; 8(ix) - radix +; + ld e, 4 (ix) + ld d, 5 (ix) + bit 7, d + jr Z, ___uitoa_de +;positive/negative numbers are supported only for radix=10 + ld a, 8 (ix) + cp a, #10 + jr NZ, ___uitoa_de +;add minus sign to result and inverse value + ld hl, #0 + or a, a + sbc hl, de + ex de, hl + ld l, 6 (ix) + ld h, 7 (ix) + ld (hl), #0x2D ;minus symbol + inc hl + ld 6 (ix), l + ld 7 (ix), h + jr ___uitoa_dehl +; +;void __uitoa(unsigned int value, char *string, unsigned char radix); +; +_uitoa:: + push ix + ld ix, #0 + add ix, sp +; +; 4(ix) - value +; 6(ix) - string +; 8(ix) - radix +; + ld e, 4 (ix) + ld d, 5 (ix) +; +___uitoa_de: + ld l, 6 (ix) + ld h, 7 (ix) +; +___uitoa_dehl: + ld a, e + or a, d + jr NZ, 100$ +; + ld (hl), #0x30 + inc hl + jp 190$ +100$: + ld a, 8 (ix) + cp a, #10 ;most popular radix + jr NZ, 110$ +; +;-------- decimal convertion +; this algorithm up to 2 times faster than generic +; + ld c, l + ld b, h + ld hl, #-4 + add hl, sp + ld sp, hl + push bc + push hl + push de + call ___uitobcd + ld hl, #4 + add hl, sp + ld sp, hl + pop de ;DE - pointer to string + inc hl + inc hl ;HL - pointer to BCD value + ld b, #3 ;number of bytes in BCD value + ld a, #0x30 ;ASCII code of '0' +103$: + rrd + ld (de), a + inc de + rrd + ld (de), a + inc de + inc hl + djnz 103$ +; +; pop af +; pop af +;skip trailing zeroes + ld b, #5 ;real BCD number is at most 5 digits + dec de ;so always skip last zero +105$: + dec de + ld a, (de) + cp a, #0x30 + jr NZ, 107$ ;break loop if non-zero found + djnz 105$ +107$: + inc de ;always point to symbol next to last significant + ex de, hl + jr 190$ +; +;--------------------------- +; +110$: + cp a, #2 + jr C, 190$ ;radix is less than 2 +; + ld c, a + dec c + and a, c + jr NZ, 150$ +; +;-------- radix is power of 2 +; +; DE - value, HL - pointer to string, C - mask +120$: + ld a, e + ld b, c +125$: + srl d + rr e + srl b + jr NZ, 125$ +; + and a, c + add a, #0x30 + cp a, #0x3A ;convert to 0...9A...Z + jr C, 130$ + add a, #7 +130$: + ld (hl), a + inc hl + ld a, e + or a, d + jr NZ, 120$ + jr 190$ +; +;--------------------------- +; +;-------- custom radix (generic algorithm) +; +150$: + ex de, hl +160$: + ld c, 8 (ix) + call ___divu16_8 + add a, #0x30 + cp a, #0x3A + jr C, 165$ + add a, #7 +165$: + ld (de), a + inc de + ld a, l + or h + jr NZ, 160$ + ex de, hl +; jr 190$ +; +;--------------------------- +; +;-------- finish string and reverse order +190$: + ld (hl), #0 + ld e, 6 (ix) + ld d, 7 (ix) + call ___strreverse_reg + ld sp, ix + pop ix + ret +; +; +;in: HL - divident, C - divisor +;out: HL - quotient, A - remainder +___divu16_8: + xor a, a + ld b, #16 +100$: + add hl, hl + rla + jr c, 110$ + cp a, c + jr c, 120$ +110$: + sub a, c + inc l +120$: + djnz 100$ + ret + diff --git a/gbdk/gbdk-lib/libc/asm/z80/__ltoa.s b/gbdk/gbdk-lib/libc/asm/z80/__ltoa.s new file mode 100644 index 00000000..8b7ea11c --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/z80/__ltoa.s @@ -0,0 +1,254 @@ +;-------------------------------------------------------------------------- +; __ltoa.s +; +; Copyright (C) 2020, Sergey Belyashov +; +; This library is free software; you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by the +; Free Software Foundation; either version 2, or (at your option) any +; later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this library; see the file COPYING. If not, write to the +; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, +; MA 02110-1301, USA. +; +; As a special exception, if you link this library with other files, +; some of which are compiled with SDCC, to produce an executable, +; this library does not by itself cause the resulting executable to +; be covered by the GNU General Public License. This exception does +; not however invalidate any other reasons why the executable file +; might be covered by the GNU General Public License. +;-------------------------------------------------------------------------- + + .area _CODE + + .globl _ltoa + .globl _ultoa +; +;void __itoa(long value, char *string, unsigned char radix); +; +_ltoa:: + push ix + ld ix, #0 + add ix, sp +; +; 4(ix) - value +; 8(ix) - string +; 10(ix) - radix +; + ld e, 4 (ix) + ld d, 5 (ix) + bit 7, 7 (ix) + jr Z, ___ultoa_de +;positive/negative numbers are supported only for radix=10 + ld a, 10 (ix) + cp a, #10 + jr NZ, ___ultoa_de +;add minus sign to result and inverse value + ld hl, #0 + or a, a + sbc hl, de + ex de, hl + ld hl, #0 + ld c, 6 (ix) + ld b, 7 (ix) + sbc hl, bc + ld 6 (ix), l + ld 7 (ix), h + ld l, 8 (ix) + ld h, 9 (ix) + ld (hl), #0x2D ;minus symbol + inc hl + ld 8 (ix), l + ld 9 (ix), h + jr ___ultoa_dehl +; +;void __uitoa(unsigned int value, char *string, unsigned char radix); +; +_ultoa:: + push ix + ld ix, #0 + add ix, sp +; +; 4(ix) - value +; 8(ix) - string +; 10(ix) - radix +; + ld e, 4 (ix) + ld d, 5 (ix) +; +___ultoa_de: + ld l, 8 (ix) + ld h, 9 (ix) +; +___ultoa_dehl: + ld a, e + or a, d + or a, 6 (ix) + or a, 7 (ix) + jr NZ, 100$ +; + ld (hl), #0x30 + inc hl + jp 190$ +100$: + ld a, 10 (ix) + cp a, #10 ;most popular radix + jr NZ, 110$ +; +;-------- decimal convertion +;this algorithm is 20% faster than generic one +; + ld c, l + ld b, h + ld hl, #-5 + add hl, sp + ld sp, hl + push bc + push hl + ld c, 6 (ix) + ld b, 7 (ix) + push bc + push de + call ___ultobcd + ld hl, #6 + add hl, sp + ld sp, hl + pop de ;DE - pointer to string + inc hl + inc hl ;HL - pointer to BCD value + ld b, #5 ;number of bytes in BCD value + ld a, #0x30 ;ASCII code of '0' +103$: + rrd + ld (de), a + inc de + rrd + ld (de), a + inc de + inc hl + djnz 103$ +; +; ld sp, hl +;skip trailing zeroes + ld b, #10 ;real decimal number is at most 10 digits +105$: + dec de + ld a, (de) + cp a, #0x30 + jr NZ, 107$ ;break loop if non-zero found + djnz 105$ +107$: + inc de ;always point to symbol next to last significant + ex de, hl + jr 190$ +; +;--------------------------- +; +110$: + cp a, #2 + jr C, 190$ ;radix is less than 2 +; + ld c, a + dec c + and a, c + jr NZ, 150$ +; +;-------- radix is power of 2 +; +; DE - lower 16 bits of value, HL - pointer to string, C - mask +120$: + ld a, e + ld b, c +125$: + srl 7 (ix) + rr 6 (ix) + rr d + rr e + srl b + jr NZ, 125$ +; + and a, c + add a, #0x30 + cp a, #0x3A ;convert to 0...9A...Z + jr C, 130$ + add a, #7 +130$: + ld (hl), a + inc hl + ld a, e + or a, d + or a, 6 (ix) + or a, 7 (ix) + jr NZ, 120$ + jr 190$ +; +;--------------------------- +; +;-------- custom radix (generic algorithm) +; +150$: + ex de, hl + ld c, e + ld b, d + ld e, 6 (ix) + ld d, 7 (ix) +160$: + push bc + ld c, 10 (ix) + call ___divu32_8 + pop bc + add a, #0x30 + cp a, #0x3A + jr C, 165$ + add a, #7 +165$: + ld (bc), a + inc bc + ld a, l + or a, h + or a, e + or a, d + jr NZ, 160$ + ld l, c + ld h, b +; jr 190$ +; +;--------------------------- +; +;-------- finish string and reverse order +190$: + ld (hl), #0 + ld e, 8 (ix) + ld d, 9 (ix) + call ___strreverse_reg + ld sp, ix + pop ix + ret +; +;in: DEHL - divident, C - divisor +;out: DEHL - quotient, A - remainder +___divu32_8: + xor a, a + ld b, #32 +100$: + add hl, hl + rl e + rl d + rla + jr c, 110$ + cp a, c + jr c, 120$ +110$: + sub a, c + inc l +120$: + djnz 100$ + ret + diff --git a/gbdk/gbdk-lib/libc/asm/z80/__sdcc_call_hl.s b/gbdk/gbdk-lib/libc/asm/z80/__sdcc_call_hl.s new file mode 100644 index 00000000..9086c7b8 --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/z80/__sdcc_call_hl.s @@ -0,0 +1,37 @@ +;-------------------------------------------------------------------------- +; crtcall.s +; +; Copyright (C) 2011, Maarten Brock +; +; This library is free software; you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by the +; Free Software Foundation; either version 2, or (at your option) any +; later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this library; see the file COPYING. If not, write to the +; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, +; MA 02110-1301, USA. +; +; As a special exception, if you link this library with other files, +; some of which are compiled with SDCC, to produce an executable, +; this library does not by itself cause the resulting executable to +; be covered by the GNU General Public License. This exception does +; not however invalidate any other reasons why the executable file +; might be covered by the GNU General Public License. +;-------------------------------------------------------------------------- + + .area _CODE + + .globl ___sdcc_call_hl + +; The Z80 has the jp (hl) instruction, which is perfect for implementing function pointers. + +___sdcc_call_hl: + jp (hl) + diff --git a/gbdk/gbdk-lib/libc/asm/z80/__sdcc_call_iy.s b/gbdk/gbdk-lib/libc/asm/z80/__sdcc_call_iy.s new file mode 100644 index 00000000..8941745d --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/z80/__sdcc_call_iy.s @@ -0,0 +1,37 @@ +;-------------------------------------------------------------------------- +; crtcall.s +; +; Copyright (C) 2011, Maarten Brock, 2015 Philipp Klaus Krause +; +; This library is free software; you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by the +; Free Software Foundation; either version 2, or (at your option) any +; later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this library; see the file COPYING. If not, write to the +; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, +; MA 02110-1301, USA. +; +; As a special exception, if you link this library with other files, +; some of which are compiled with SDCC, to produce an executable, +; this library does not by itself cause the resulting executable to +; be covered by the GNU General Public License. This exception does +; not however invalidate any other reasons why the executable file +; might be covered by the GNU General Public License. +;-------------------------------------------------------------------------- + + .area _CODE + + .globl ___sdcc_call_iy + +; The Z80 has the jp (iy) instruction, which is perfect for implementing function pointers. + +___sdcc_call_iy: + jp (iy) + diff --git a/gbdk/gbdk-lib/libc/asm/z80/__sdcc_critical.s b/gbdk/gbdk-lib/libc/asm/z80/__sdcc_critical.s new file mode 100644 index 00000000..ead5e02c --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/z80/__sdcc_critical.s @@ -0,0 +1,54 @@ +;-------------------------------------------------------------------------- +; __sdcc_critical.s +; +; Copyright (C) 2020, Sergey Belyashov +; +; This library is free software; you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by the +; Free Software Foundation; either version 2, or (at your option) any +; later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this library; see the file COPYING. If not, write to the +; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, +; MA 02110-1301, USA. +; +; As a special exception, if you link this library with other files, +; some of which are compiled with SDCC, to produce an executable, +; this library does not by itself cause the resulting executable to +; be covered by the GNU General Public License. This exception does +; not however invalidate any other reasons why the executable file +; might be covered by the GNU General Public License. +;-------------------------------------------------------------------------- + + .area _CODE + + .globl ___sdcc_critical_enter +; +; NMOS Z80 compatible +; this function cannot be placed at 0x0000...0x00ff addresses +; +___sdcc_critical_enter:: + xor a, a + push af + pop af + ld a, i + di + ret pe ;enabled interrupts + dec sp + dec sp + pop af + or a, a ;A = 0 if interrupts disabled + jr NZ, 00100$ +;inetrrupts disabled + sub a, a ;force P/V = 0 + ret +;interrupts enabled +00100$: + xor a, a ;force P/V = 1 + ret diff --git a/gbdk/gbdk-lib/libc/asm/z80/__strreverse.s b/gbdk/gbdk-lib/libc/asm/z80/__strreverse.s new file mode 100644 index 00000000..8372c5d5 --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/z80/__strreverse.s @@ -0,0 +1,63 @@ +;-------------------------------------------------------------------------- +; __strreverse.s +; +; Copyright (C) 2020, Sergey Belyashov +; +; This library is free software; you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by the +; Free Software Foundation; either version 2, or (at your option) any +; later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this library; see the file COPYING. If not, write to the +; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, +; MA 02110-1301, USA. +; +; As a special exception, if you link this library with other files, +; some of which are compiled with SDCC, to produce an executable, +; this library does not by itself cause the resulting executable to +; be covered by the GNU General Public License. This exception does +; not however invalidate any other reasons why the executable file +; might be covered by the GNU General Public License. +;-------------------------------------------------------------------------- + + .area _CODE + + .globl ___strreverse + .globl ___strreverse_reg +; +;char * __reverse(char *beg, char *end); +; +___strreverse:: + pop bc + pop de + pop hl + push hl + push de + push bc + +;in: HL - pointer to end of string (null symbol), DE - pointer to start of string +; +___strreverse_reg:: + push de + jr 110$ +100$: + add hl, de + ld a, (de) + ld c, (hl) + ld (hl), a + ld a, c + ld (de), a + inc de +110$: + dec hl + or a, a + sbc hl, de + jr NC, 100$ + pop hl + ret diff --git a/gbdk/gbdk-lib/libc/asm/z80/__uitobcd.s b/gbdk/gbdk-lib/libc/asm/z80/__uitobcd.s new file mode 100644 index 00000000..52db719e --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/z80/__uitobcd.s @@ -0,0 +1,87 @@ +;-------------------------------------------------------------------------- +; __uitobcd.s +; +; Copyright (C) 2020, Sergey Belyashov +; +; This library is free software; you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by the +; Free Software Foundation; either version 2, or (at your option) any +; later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this library; see the file COPYING. If not, write to the +; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, +; MA 02110-1301, USA. +; +; As a special exception, if you link this library with other files, +; some of which are compiled with SDCC, to produce an executable, +; this library does not by itself cause the resulting executable to +; be covered by the GNU General Public License. This exception does +; not however invalidate any other reasons why the executable file +; might be covered by the GNU General Public License. +;-------------------------------------------------------------------------- + + .area _CODE + + .globl ___uitobcd +; +; void __uitobcd (unsigned int v, unsigned char bcd[3]) +; __uitobcd converts v to BCD representation to the bcd. +; bcd[] will contain BCD value. +; +___uitobcd: + push ix + ld ix, #0 + add ix, sp +; + ld bc, #0x1000 + ld d, c + ld e, c + ld l, 4 (ix) + ld h, 5 (ix) +; +;--- begin speed optimization +; + ld a, h + or a, a + jr NZ, 100$ +; + ld h, l + srl b +; +;--- end speed optimization +; +; HL - binary value +; CDE - future BCD value +; B - bits count (16) +100$: + add hl, hl + ld a, e + adc a, a + daa + ld e, a + ld a, d + adc a, a + daa + ld d, a + ld a, c + adc a, a + daa + ld c, a + djnz 100$ +; + ld l, 6 (ix) + ld h, 7 (ix) + ld (hl), e + inc hl + ld (hl), d + inc hl + ld (hl), c +; + pop ix + ret diff --git a/gbdk/gbdk-lib/libc/asm/z80/__ultobcd.s b/gbdk/gbdk-lib/libc/asm/z80/__ultobcd.s new file mode 100644 index 00000000..8d4cf33c --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/z80/__ultobcd.s @@ -0,0 +1,122 @@ +;-------------------------------------------------------------------------- +; __ultobcd.s +; +; Copyright (C) 2020, Sergey Belyashov +; +; This library is free software; you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by the +; Free Software Foundation; either version 2, or (at your option) any +; later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this library; see the file COPYING. If not, write to the +; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, +; MA 02110-1301, USA. +; +; As a special exception, if you link this library with other files, +; some of which are compiled with SDCC, to produce an executable, +; this library does not by itself cause the resulting executable to +; be covered by the GNU General Public License. This exception does +; not however invalidate any other reasons why the executable file +; might be covered by the GNU General Public License. +;-------------------------------------------------------------------------- + + .area _CODE + + .globl ___ultobcd +; +; void __ultobcd (unsigned long v, unsigned char bcd[5]) +; __ultobcd converts v to BCD representation to the bcd. +; bcd[] will contain BCD value. +; +___ultobcd: + push ix + ld ix, #0 + add ix, sp + ld bc, #0x2000 +; +;--- begin speed optimization +; + ld l, 4 (ix) + ld h, 5 (ix) + ld e, 6 (ix) + ld d, 7 (ix) + ld a, e + or a, d + jr NZ, 101$ +;high 2 bytes are zero + ld b, #0x10 + ex de, hl +101$: + ld a, d + or a, a + jr NZ, 102$ +;high byte is zero + ld d, e + ld e, h + ld h, l + ld a, #-8 + add a, b + ld b, a +102$: + ld 4 (ix), l + ld 5 (ix), h + ld 6 (ix), e + ld 7 (ix), d +; +;--- end speed optimization +; + ld hl, #0x0000 + ld e, l + ld d, h +; (ix+0)..(ix+3) - binary value +; CDEHL - future BCD value +; B - bits count (32) +103$: + sla 4 (ix) + rl 5 (ix) + rl 6 (ix) + rl 7 (ix) + ld a, l + adc a, a + daa + ld l, a + ld a, h + adc a, a + daa + ld h, a + ld a, e + adc a, a + daa + ld e, a + ld a, d + adc a, a + daa + ld d, a + ld a, c + adc a, a + daa + ld c, a + djnz 103$ +; + ld b, l + ld a, h + ld l, 8 (ix) + ld h, 9 (ix) + ld (hl), b + inc hl + ld (hl), a + inc hl + ld (hl), e + inc hl + ld (hl), d + inc hl + ld (hl), c +; + pop ix + ret diff --git a/gbdk/gbdk-lib/libc/asm/z80/abs.s b/gbdk/gbdk-lib/libc/asm/z80/abs.s new file mode 100644 index 00000000..2aaa5412 --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/z80/abs.s @@ -0,0 +1,61 @@ +;-------------------------------------------------------------------------- +; abs.s +; +; Copyright (C) 2010, Philipp Klaus Krause +; +; This library is free software; you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by the +; Free Software Foundation; either version 2, or (at your option) any +; later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this library; see the file COPYING. If not, write to the +; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, +; MA 02110-1301, USA. +; +; As a special exception, if you link this library with other files, +; some of which are compiled with SDCC, to produce an executable, +; this library does not by itself cause the resulting executable to +; be covered by the GNU General Public License. This exception does +; not however invalidate any other reasons why the executable file +; might be covered by the GNU General Public License. +;-------------------------------------------------------------------------- + + .area _CODE + + .globl _abs + +; 12B; 86T for nonnegative arguments, 78T for negative. +_abs: + pop hl + pop de + push de + push hl + xor a, a + ld l, a + ld h, a + sbc hl, de + ret P + ex de, hl + ret + +; 14B; 59T for nonegative arguments, 94T for negative: +;_abs: +; pop de +; pop hl +; push hl +; push de +; bit 7, h +; ret Z +; xor a, a +; ld e, a +; ld d, a +; ex de, hl +; sbc hl, de +; ret + diff --git a/gbdk/gbdk-lib/libc/asm/z80/arand.s b/gbdk/gbdk-lib/libc/asm/z80/arand.s new file mode 100644 index 00000000..a798cc3a --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/z80/arand.s @@ -0,0 +1,78 @@ + .module Random + + .globl .initrand + .globl _rand + + .area _DATA + +.randarr: + .ds 55 +.raxj: + .ds 0x01 +.raxk: + .ds 0x01 + + .area _CODE + +_arand:: ; Banked + PUSH BC + LD D, #0 + LD HL, #(.randarr - 1) + LD A, (.raxj) + LD E, A + DEC A ; Decrease the pointer + JR NZ, 1$ + LD A, #55 +1$: + LD (.raxj), A + ADD HL, DE + LD B, (HL) + + LD HL, #(.randarr - 1) ; Ooh... + LD A, (.raxk) + LD E, A + DEC A ; Decrease the pointer + JR NZ, 2$ + LD A, #55 +2$: + LD (.raxk), A + ADD HL, DE + LD A, (HL) + + ADD B + LD (HL), A ; Store new value + + POP BC + + LD H, #0 + LD L, A + + RET + +_initarand:: ; Banked + CALL .initrand + + LD A, #55 + LD HL, #.randarr +1$: + DEC A + LD (.raxj), A + LD B, H + LD C, L + CALL _rand + LD H, B + LD L, C + + LD (HL), E + INC HL + + LD A, (.raxj) + CP #0 + JP NZ, 1$ + + LD A, #24 ; Now the array has been filled,set the pointers + LD (.raxj), A + LD A, #55 + LD (.raxk), A + + RET diff --git a/gbdk/gbdk-lib/libc/asm/z80/atomic_flag_test_and_set.s b/gbdk/gbdk-lib/libc/asm/z80/atomic_flag_test_and_set.s new file mode 100644 index 00000000..074b5360 --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/z80/atomic_flag_test_and_set.s @@ -0,0 +1,44 @@ +;-------------------------------------------------------------------------- +; atomic_flag_test_and_set.s +; +; Copyright (C) 2020, Philipp Klaus Krause +; +; This library is free software; you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by the +; Free Software Foundation; either version 2, or (at your option) any +; later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this library; see the file COPYING. If not, write to the +; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, +; MA 02110-1301, USA. +; +; As a special exception, if you link this library with other files, +; some of which are compiled with SDCC, to produce an executable, +; this library does not by itself cause the resulting executable to +; be covered by the GNU General Public License. This exception does +; not however invalidate any other reasons why the executable file +; might be covered by the GNU General Public License. +;-------------------------------------------------------------------------- + + .area _CODE + + .globl _atomic_flag_test_and_set + +_atomic_flag_test_and_set: + pop de + pop hl + push hl + push de + xor a, a + srl (hl) + ccf + rla + ld l, a + ret + diff --git a/gbdk/gbdk-lib/libc/asm/z80/crtenter.s b/gbdk/gbdk-lib/libc/asm/z80/crtenter.s new file mode 100644 index 00000000..0be714a8 --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/z80/crtenter.s @@ -0,0 +1,41 @@ +;-------------------------------------------------------------------------- +; crtenter.s +; +; Copyright (C) 2015, Alan Cox, Philipp Klaus Krause +; +; This library is free software; you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by the +; Free Software Foundation; either version 2, or (at your option) any +; later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this library; see the file COPYING. If not, write to the +; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, +; MA 02110-1301, USA. +; +; As a special exception, if you link this library with other files, +; some of which are compiled with SDCC, to produce an executable, +; this library does not by itself cause the resulting executable to +; be covered by the GNU General Public License. This exception does +; not however invalidate any other reasons why the executable file +; might be covered by the GNU General Public License. +;-------------------------------------------------------------------------- + + .area _CODE + + .globl ___sdcc_enter_ix + +; Factor out some start of function code to reduce code size + +___sdcc_enter_ix: + pop hl ; return address + push ix ; save frame pointer + ld ix, #0 + add ix, sp ; set ix to the stack frame + jp (hl) ; and return + diff --git a/gbdk/gbdk-lib/libc/asm/z80/divmixed.s b/gbdk/gbdk-lib/libc/asm/z80/divmixed.s new file mode 100644 index 00000000..8c60fc21 --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/z80/divmixed.s @@ -0,0 +1,49 @@ +;-------------------------------------------------------------------------- +; divmixed.s +; +; Copyright (C) 2010-2021, Philipp Klaus Krause +; +; This library is free software; you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by the +; Free Software Foundation; either version 2, or (at your option) any +; later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this library; see the file COPYING. If not, write to the +; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, +; MA 02110-1301, USA. +; +; As a special exception, if you link this library with other files, +; some of which are compiled with SDCC, to produce an executable, +; this library does not by itself cause the resulting executable to +; be covered by the GNU General Public License. This exception does +; not however invalidate any other reasons why the executable file +; might be covered by the GNU General Public License. +;-------------------------------------------------------------------------- + +.globl __divsuchar +.globl __divuschar + +__divsuchar: + ld e, l + ld l, a + ld h, #0 + + jp __div_signexte + +__divuschar: + ld e, l + ld d, #0 + ld l, a + + rlca ; Sign extend + sbc a, a + ld h, a + + jp __div16 + diff --git a/gbdk/gbdk-lib/libc/asm/z80/divsigned.s b/gbdk/gbdk-lib/libc/asm/z80/divsigned.s new file mode 100644 index 00000000..7f1949d4 --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/z80/divsigned.s @@ -0,0 +1,124 @@ +;-------------------------------------------------------------------------- +; divsigned.s +; +; Copyright (C) 2000-2021, Michael Hope, Philipp Klaus Krause +; +; This library is free software; you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by the +; Free Software Foundation; either version 2, or (at your option) any +; later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this library; see the file COPYING. If not, write to the +; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, +; MA 02110-1301, USA. +; +; As a special exception, if you link this library with other files, +; some of which are compiled with SDCC, to produce an executable, +; this library does not by itself cause the resulting executable to +; be covered by the GNU General Public License. This exception does +; not however invalidate any other reasons why the executable file +; might be covered by the GNU General Public License. +;-------------------------------------------------------------------------- + +.area _CODE + +.globl __divsint +.globl __divschar + +__divschar: + ld e, l + ld l, a + +__div8:: + ld a, l ; Sign extend + rlca + sbc a,a + ld h, a +__div_signexte:: + ld a, e ; Sign extend + rlca + sbc a, a + ld d, a + ; Fall through to __div16 + + ;; signed 16-bit division + ;; + ;; Entry conditions + ;; HL = dividend + ;; DE = divisor + ;; + ;; Exit conditions + ;; DE = quotient + ;; HL = remainder + ;; + ;; Register used: AF,B,DE,HL +__divsint: +__div16:: + ;; Determine sign of quotient by xor-ing high bytes of dividend + ;; and divisor. Quotient is positive if signs are the same, negative + ;; if signs are different + ;; Remainder has same sign as dividend + ld a, h ; Get high byte of dividend + xor a, d ; Xor with high byte of divisor + rla ; Sign of quotient goes into the carry + ld a, h ; Get high byte of dividend + push af ; Save sign of both quotient and reminder + + ; Take absolute value of dividend + rla + jr NC, .chkde ; Jump if dividend is positive + sub a, a ; Substract dividend from 0 + sub a, l + ld l, a + sbc a, a ; Propagate borrow (A=0xFF if borrow) + sub a, h + ld h, a + + ; Take absolute value of divisor +.chkde: + bit 7, d + jr Z, .dodiv ; Jump if divisor is positive + sub a, a ; Subtract divisor from 0 + sub a, e + ld e, a + sbc a, a ; Propagate borrow (A=0xFF if borrow) + sub a, d + ld d, a + + ; Divide absolute values +.dodiv: + call __divu16 + +.fix_quotient: + ; Negate quotient if it is negative + pop af ; recover sign of quotient + ret NC ; Jump if quotient is positive + ld b, a + sub a, a ; Subtract quotient from 0 + sub a, e + ld e, a + sbc a, a ; Propagate borrow (A=0xFF if borrow) + sub a, d + ld d, a + ld a, b + ret + +__get_remainder:: + ; Negate remainder if it is negative. + rla + ex de, hl + ret NC ; Return if remainder is positive + sub a, a ; Subtract quotient from 0 + sub a, e + ld e, a + sbc a, a ; Propagate borrow (A=0xFF if borrow) + sub a, d + ld d, a + ret + diff --git a/gbdk/gbdk-lib/libc/asm/z80/divunsigned.s b/gbdk/gbdk-lib/libc/asm/z80/divunsigned.s new file mode 100644 index 00000000..92e46fcc --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/z80/divunsigned.s @@ -0,0 +1,131 @@ +;-------------------------------------------------------------------------- +; divunsigned.s +; +; Copyright (C) 2000-2021, Michael Hope, Philipp Klaus Krause, Marco Bodrato +; +; This library is free software; you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by the +; Free Software Foundation; either version 2, or (at your option) any +; later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this library; see the file COPYING. If not, write to the +; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, +; MA 02110-1301, USA. +; +; As a special exception, if you link this library with other files, +; some of which are compiled with SDCC, to produce an executable, +; this library does not by itself cause the resulting executable to +; be covered by the GNU General Public License. This exception does +; not however invalidate any other reasons why the executable file +; might be covered by the GNU General Public License. +;-------------------------------------------------------------------------- + + ;; Originally from GBDK by Pascal Felber. + +.area _CODE + +.globl __divuint +.globl __divuchar + + +__divuchar: + ld e, l + ld l, a + + ;; Fall through +__divu8:: + ld h,#0x00 + ld d,h + ; Fall through to __divu16 + + ;; unsigned 16-bit division + ;; + ;; Entry conditions + ;; HL = dividend + ;; DE = divisor + ;; + ;; Exit conditions + ;; DE = quotient + ;; HL = remainder + ;; carry = 0 + ;; If divisor is 0, quotient is set to "infinity", i.e HL = 0xFFFF. + ;; + ;; Register used: AF,B,DE,HL +__divuint: +__divu16:: + ;; Two algorithms: one assumes divisor <2^7, the second + ;; assumes divisor >=2^7; choose the applicable one. + ld a,e + and a,#0x80 + or a,d + jr NZ,.morethan7bits + ;; Both algorithms "rotate" 24 bits (H,L,A) but roles change. + + ;; unsigned 16/7-bit division +.atmost7bits: + ld b,#16 ; bits in dividend and possible quotient + ;; Carry cleared by AND/OR, this "0" bit will pass trough HL.[*] + adc hl,hl +.dvloop7: + ;; HL holds both dividend and quotient. While we shift a bit from + ;; MSB of dividend, we shift next bit of quotient in from carry. + ;; A holds remainder. + rla + + ;; If remainder is >= divisor, next bit of quotient is 1. We try + ;; to compute the difference. + sub a,e + jr NC,.nodrop7 ; Jump if remainder is >= dividend + add a,e ; Otherwise, restore remainder + ;; The add above sets the carry, because sbc a,e did set it. +.nodrop7: + ccf ; Complement borrow so 1 indicates a + ; successful substraction (this is the + ; next bit of quotient) + adc hl,hl + djnz .dvloop7 + ;; Carry now contains the same value it contained before + ;; entering .dvloop7[*]: "0" = valid result. + ld e,a ; DE = remainder, HL = quotient + ex de, hl + ret + +.morethan7bits: + ld b,#9 ; at most 9 bits in quotient. + ld a,l ; precompute the first 7 shifts, by + ld l,h ; doing 8 + ld h,#0 + rr l ; undoing 1 +.dvloop: + ;; Shift next bit of quotient into bit 0 of dividend + ;; Shift next MSB of dividend into LSB of remainder + ;; A holds both dividend and quotient. While we shift a bit from + ;; MSB of dividend, we shift next bit of quotient in from carry + ;; HL holds remainder + adc hl,hl ; HL < 2^(7+9), no carry, ever. + + ;; If remainder is >= divisor, next bit of quotient is 1. We try + ;; to compute the difference. + sbc hl,de + jr NC,.nodrop ; Jump if remainder is >= dividend + add hl,de ; Otherwise, restore remainder + ;; The add above sets the carry, because sbc hl,de did set it. +.nodrop: + ccf ; Complement borrow so 1 indicates a + ; successful substraction (this is the + ; next bit of quotient) + rla + djnz .dvloop + ;; Take care of the ninth quotient bit! after the loop B=0. + rl b ; BA = quotient + ;; Carry now contains "0" = valid result. + ld d,b + ld e,a ; DE = quotient, HL = remainder + ret + diff --git a/gbdk/gbdk-lib/libc/asm/z80/memcmp.s b/gbdk/gbdk-lib/libc/asm/z80/memcmp.s new file mode 100644 index 00000000..7497e86d --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/z80/memcmp.s @@ -0,0 +1,38 @@ + .module strcmp + + .area _HOME + +; int memcmp(const void *buf1, const void *buf2, size_t count) +_memcmp:: + pop hl + pop de + pop bc + ex (sp), hl + ex de, hl + + inc d + inc e + jr 3$ + +1$: + ld a,(bc) + sub (hl) ; s1[i]==s2[i]? + jr nz, 2$ ; -> Different + + inc bc + inc hl +3$: + dec e + jr nz, 1$ + dec d + jr nz, 1$ + + ld hl, #0 + ret + +2$: + ld hl,#1 + ret c + + ld hl,#-1 + ret
\ No newline at end of file diff --git a/gbdk/gbdk-lib/libc/asm/z80/memcpy.s b/gbdk/gbdk-lib/libc/asm/z80/memcpy.s new file mode 100644 index 00000000..5945e3a5 --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/z80/memcpy.s @@ -0,0 +1,49 @@ +;-------------------------------------------------------------------------- +; memcpy.s +; +; Copyright (C) 2020, Sergey Belyashov +; Copyright (c) 2021, Philipp Klaus Krause +; +; This library is free software; you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by the +; Free Software Foundation; either version 2, or (at your option) any +; later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this library; see the file COPYING. If not, write to the +; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, +; MA 02110-1301, USA. +; +; As a special exception, if you link this library with other files, +; some of which are compiled with SDCC, to produce an executable, +; this library does not by itself cause the resulting executable to +; be covered by the GNU General Public License. This exception does +; not however invalidate any other reasons why the executable file +; might be covered by the GNU General Public License. +;-------------------------------------------------------------------------- + + .area _CODE + + .globl _memcpy + .globl ___memcpy + +; The Z80 has the ldir instruction, which is perfect for implementing memcpy(). +_memcpy: +___memcpy: + ex de, hl + pop iy + pop bc + ld a, c + or a, b + jr Z, end + push de + ldir + pop de +end: + jp (iy) + diff --git a/gbdk/gbdk-lib/libc/asm/z80/memmove.s b/gbdk/gbdk-lib/libc/asm/z80/memmove.s new file mode 100644 index 00000000..0e03e958 --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/z80/memmove.s @@ -0,0 +1,65 @@ +;-------------------------------------------------------------------------- +; memmove.s +; +; Copyright (C) 2008-2009, Philipp Klaus Krause, Marco Bodrato +; +; This library is free software; you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by the +; Free Software Foundation; either version 2, or (at your option) any +; later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this library; see the file COPYING. If not, write to the +; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, +; MA 02110-1301, USA. +; +; As a special exception, if you link this library with other files, +; some of which are compiled with SDCC, to produce an executable, +; this library does not by itself cause the resulting executable to +; be covered by the GNU General Public License. This exception does +; not however invalidate any other reasons why the executable file +; might be covered by the GNU General Public License. +;-------------------------------------------------------------------------- + + .area _CODE + + .globl _memmove + +; The Z80 has the ldir and lddr instructions, which are perfect for implementing memmove(). + +_memmove: + pop af + pop hl + pop de + pop bc + push bc + push de + push hl + push af + ld a, c + or a, b + ret Z + push hl + sbc hl, de ; or above cleared carry. + add hl, de ; same carry as the line before + jr C, memmove_up +memmove_down: + dec bc + add hl, bc + ex de, hl + add hl, bc + inc bc + lddr + pop hl + ret +memmove_up: + ex de, hl + ldir + pop hl + ret + diff --git a/gbdk/gbdk-lib/libc/asm/z80/memset.s b/gbdk/gbdk-lib/libc/asm/z80/memset.s new file mode 100644 index 00000000..ce48480b --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/z80/memset.s @@ -0,0 +1,30 @@ + .area _CODE + +;; void *memset (void *s, int c, size_t n) __z88dk_callee; +_memset:: + pop af + pop hl + pop de + pop bc + push af + + ld a, b + or c + ret z + + ld (hl), e + dec bc + + ld a, b + or c + ret z + + push hl + ld d, h + ld e, l + inc de + + ldir + pop hl + ret + diff --git a/gbdk/gbdk-lib/libc/asm/z80/modmixed.s b/gbdk/gbdk-lib/libc/asm/z80/modmixed.s new file mode 100644 index 00000000..f940662a --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/z80/modmixed.s @@ -0,0 +1,53 @@ +;-------------------------------------------------------------------------- +; modmixed.s +; +; Copyright (C) 2010-2021, Philipp Klaus Krause +; +; This library is free software; you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by the +; Free Software Foundation; either version 2, or (at your option) any +; later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this library; see the file COPYING. If not, write to the +; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, +; MA 02110-1301, USA. +; +; As a special exception, if you link this library with other files, +; some of which are compiled with SDCC, to produce an executable, +; this library does not by itself cause the resulting executable to +; be covered by the GNU General Public License. This exception does +; not however invalidate any other reasons why the executable file +; might be covered by the GNU General Public License. +;-------------------------------------------------------------------------- + +.globl __modsuchar +.globl __moduschar + +__modsuchar: + ld e, l + ld l, a + ld h, #0 + + call __div_signexte + + jp __get_remainder + +__moduschar: + ld e, l + ld d, #0 + ld l, a + + rlca ; Sign extend + sbc a, a + ld h, a + + call __div16 + + jp __get_remainder + diff --git a/gbdk/gbdk-lib/libc/asm/z80/modsigned.s b/gbdk/gbdk-lib/libc/asm/z80/modsigned.s new file mode 100644 index 00000000..70c0a076 --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/z80/modsigned.s @@ -0,0 +1,46 @@ +;-------------------------------------------------------------------------- +; modsigned.s +; +; Copyright (C) 2009-2021, Philipp Klaus Krause +; +; This library is free software; you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by the +; Free Software Foundation; either version 2, or (at your option) any +; later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this library; see the file COPYING. If not, write to the +; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, +; MA 02110-1301, USA. +; +; As a special exception, if you link this library with other files, +; some of which are compiled with SDCC, to produce an executable, +; this library does not by itself cause the resulting executable to +; be covered by the GNU General Public License. This exception does +; not however invalidate any other reasons why the executable file +; might be covered by the GNU General Public License. +;-------------------------------------------------------------------------- + +.area _CODE + +.globl __modschar +.globl __modsint + +__modschar: + ld e, l + ld l, a + + call __div8 + + jp __get_remainder + +__modsint: + call __div16 + + jp __get_remainder + diff --git a/gbdk/gbdk-lib/libc/asm/z80/modunsigned.s b/gbdk/gbdk-lib/libc/asm/z80/modunsigned.s new file mode 100644 index 00000000..83a984a6 --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/z80/modunsigned.s @@ -0,0 +1,46 @@ +;-------------------------------------------------------------------------- +; modunsigned.s +; +; Copyright (C) 2009-2010, Philipp Klaus Krause +; +; This library is free software; you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by the +; Free Software Foundation; either version 2, or (at your option) any +; later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this library; see the file COPYING. If not, write to the +; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, +; MA 02110-1301, USA. +; +; As a special exception, if you link this library with other files, +; some of which are compiled with SDCC, to produce an executable, +; this library does not by itself cause the resulting executable to +; be covered by the GNU General Public License. This exception does +; not however invalidate any other reasons why the executable file +; might be covered by the GNU General Public License. +;-------------------------------------------------------------------------- + +.area _CODE + +.globl __moduchar +.globl __moduint + +__moduchar: + ld e, l + ld l, a + + call __divu8 + ex de, hl + ret + +__moduint: + call __divu16 + ex de, hl + ret + diff --git a/gbdk/gbdk-lib/libc/asm/z80/mul.s b/gbdk/gbdk-lib/libc/asm/z80/mul.s new file mode 100644 index 00000000..a5895d3c --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/z80/mul.s @@ -0,0 +1,72 @@ +;-------------------------------------------------------------------------- +; mul.s +; +; Copyright (C) 2000, Michael Hope +; Copyright (C) 2021, Philipp Klaus Krause +; +; This library is free software; you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by the +; Free Software Foundation; either version 2, or (at your option) any +; later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this library; see the file COPYING. If not, write to the +; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, +; MA 02110-1301, USA. +; +; As a special exception, if you link this library with other files, +; some of which are compiled with SDCC, to produce an executable, +; this library does not by itself cause the resulting executable to +; be covered by the GNU General Public License. This exception does +; not however invalidate any other reasons why the executable file +; might be covered by the GNU General Public License. +;-------------------------------------------------------------------------- + +.area _CODE + +.globl __mulint + +__mulint: + ld c, l + ld b, h + + ;; 16-bit multiplication + ;; + ;; Entry conditions + ;; bc = multiplicand + ;; de = multiplier + ;; + ;; Exit conditions + ;; de = less significant word of product + ;; + ;; Register used: AF,BC,DE,HL +__mul16:: + xor a,a + ld l,a + or a,b + ld b,#16 + + ;; Optimise for the case when this side has 8 bits of data or + ;; less. This is often the case with support address calls. + jr NZ,2$ + ld b,#8 + ld a,c +1$: + ;; Taken from z88dk, which originally borrowed from the + ;; Spectrum rom. + add hl,hl +2$: + rl c + rla ;DLE 27/11/98 + jr NC,3$ + add hl,de +3$: + djnz 1$ + ex de, hl + ret + diff --git a/gbdk/gbdk-lib/libc/asm/z80/mulchar.s b/gbdk/gbdk-lib/libc/asm/z80/mulchar.s new file mode 100644 index 00000000..9398dc93 --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/z80/mulchar.s @@ -0,0 +1,68 @@ +;-------------------------------------------------------------------------- +; mulchar.s +; +; Copyright (c) 2017-2021, Philipp Klaus Krause +; +; This library is free software; you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by the +; Free Software Foundation; either version 2, or (at your option) any +; later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this library; see the file COPYING. If not, write to the +; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, +; MA 02110-1301, USA. +; +; As a special exception, if you link this library with other files, +; some of which are compiled with SDCC, to produce an executable, +; this library does not by itself cause the resulting executable to +; be covered by the GNU General Public License. This exception does +; not however invalidate any other reasons why the executable file +; might be covered by the GNU General Public License. +;-------------------------------------------------------------------------- + +.area _CODE + +; unsigned char x unsigned char multiplication is done by code generation. + +.globl __mulsuchar +.globl __muluschar +.globl __mulschar + +; operands have different sign + +__muluschar: + ld e, a + ld c, l + ld b, #0 + + jr signexte + +__mulsuchar: + ld c, a + ld b, #0 + ld e, l + + jr signexte + +__mulschar: + ld e, l + ld c, a + + ;; Need to sign extend before going in. + rla + sbc a, a + ld b, a +signexte: + ld a, e + rla + sbc a, a + ld d, a + + jp __mul16 + diff --git a/gbdk/gbdk-lib/libc/asm/z80/rand.s b/gbdk/gbdk-lib/libc/asm/z80/rand.s new file mode 100644 index 00000000..1edbcf27 --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/z80/rand.s @@ -0,0 +1,52 @@ + .module Random + + .area _DATA + +___rand_seed:: +.randval: + .ds 0x02 + + .area _CODE + +_rand:: +_randw:: + + LD HL, (.randval) + EX DE, HL + LD L, E + LD A, D + + SLA L ; * 16 + RLA + SLA L + RLA + SLA L + RLA + SLA L + RLA + LD H, A ; Save randhi*16 + + LD A, E ; Old randlo + ADD A, L ; Add randlo*16 + LD L, A ; Save randlo*17 + + LD A, H ; randhi*16 + ADC A, D ; Add old randhi + LD H, A ; Save randhi*17 + + LD A, L ; randlo*17 + ADD A, #0x93 + LD L, A + LD A, H ; randhi*17 + ADC A, #0x5c + LD H, A + LD (.randval), HL + LD H, L + LD L, A + + RET + +_initrand:: ; Non banked +.initrand:: + LD (.randval), HL + RET diff --git a/gbdk/gbdk-lib/libc/asm/z80/setjmp.s b/gbdk/gbdk-lib/libc/asm/z80/setjmp.s new file mode 100644 index 00000000..3cc2bfb6 --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/z80/setjmp.s @@ -0,0 +1,95 @@ +;-------------------------------------------------------------------------- +; setjmp.s +; +; Copyright (C) 2011-2014, Philipp Klaus Krause +; +; This library is free software; you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by the +; Free Software Foundation; either version 2, or (at your option) any +; later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this library; see the file COPYING. If not, write to the +; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, +; MA 02110-1301, USA. +; +; As a special exception, if you link this library with other files, +; some of which are compiled with SDCC, to produce an executable, +; this library does not by itself cause the resulting executable to +; be covered by the GNU General Public License. This exception does +; not however invalidate any other reasons why the executable file +; might be covered by the GNU General Public License. +;-------------------------------------------------------------------------- + + .area _CODE + + .globl ___setjmp + +___setjmp: + pop hl + pop iy + push af + push hl + + ; Store return address. + ld 0(iy), l + ld 1(iy), h + + ; Store stack pointer. + xor a, a + ld l, a + ld h, a + add hl, sp + ld 2(iy), l + ld 3(iy), h + + ; Store frame pointer. + push ix + pop hl + ld 4(iy), l + ld 5(iy), h + + ; Return 0. + ld l, a + ld h, a + ret + +.globl _longjmp + +_longjmp: + pop af + pop iy + pop de + + ; Ensure that return value is non-zero. + ld a, e + or a, d + jr NZ, jump + inc de +jump: + + ; Restore frame pointer. + ld l, 4(iy) + ld h, 5(iy) + push hl + pop ix + + ; Adjust stack pointer. + ld l, 2(iy) + ld h, 3(iy) + ld sp, hl + pop hl + + ; Move return value into hl. + ex de, hl + + ; Jump. + ld c, 0(iy) + ld b, 1(iy) + push bc + ret diff --git a/gbdk/gbdk-lib/libc/asm/z80/strcpy.s b/gbdk/gbdk-lib/libc/asm/z80/strcpy.s new file mode 100644 index 00000000..933f41b0 --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/z80/strcpy.s @@ -0,0 +1,48 @@ +;-------------------------------------------------------------------------- +; strcpy.s +; +; Copyright (C) 2012, Philipp Klaus Krause +; +; This library is free software; you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by the +; Free Software Foundation; either version 2, or (at your option) any +; later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this library; see the file COPYING. If not, write to the +; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, +; MA 02110-1301, USA. +; +; As a special exception, if you link this library with other files, +; some of which are compiled with SDCC, to produce an executable, +; this library does not by itself cause the resulting executable to +; be covered by the GNU General Public License. This exception does +; not however invalidate any other reasons why the executable file +; might be covered by the GNU General Public License. +;-------------------------------------------------------------------------- + + .area _CODE + + .globl _strcpy + +_strcpy: + pop bc + pop de + pop hl + push hl + push de + push bc + push de + xor a, a +loop: + cp a, (hl) + ldi + jr NZ, loop + pop hl + ret + diff --git a/gbdk/gbdk-lib/libc/asm/z80/strlen.s b/gbdk/gbdk-lib/libc/asm/z80/strlen.s new file mode 100644 index 00000000..64f37da5 --- /dev/null +++ b/gbdk/gbdk-lib/libc/asm/z80/strlen.s @@ -0,0 +1,47 @@ +;-------------------------------------------------------------------------- +; strlen.s +; +; Copyright (C) 2008-2009, Philipp Klaus Krause +; +; This library is free software; you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by the +; Free Software Foundation; either version 2, or (at your option) any +; later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this library; see the file COPYING. If not, write to the +; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, +; MA 02110-1301, USA. +; +; As a special exception, if you link this library with other files, +; some of which are compiled with SDCC, to produce an executable, +; this library does not by itself cause the resulting executable to +; be covered by the GNU General Public License. This exception does +; not however invalidate any other reasons why the executable file +; might be covered by the GNU General Public License. +;-------------------------------------------------------------------------- + + .area _CODE + + .globl _strlen + +; The Z80 has the cpir instruction, which is perfect for implementing strlen(). + +_strlen: + pop bc + pop hl + push hl + push bc + xor a, a + ld b, a + ld c, a + cpir + ld hl, #-1 + sbc hl, bc ; C flag still cleared from xor above. + ret + diff --git a/gbdk/gbdk-lib/libc/atoi.c b/gbdk/gbdk-lib/libc/atoi.c new file mode 100644 index 00000000..a363baac --- /dev/null +++ b/gbdk/gbdk-lib/libc/atoi.c @@ -0,0 +1,31 @@ +#include <stdint.h> +#include <stdlib.h> +#include <types.h> +#include <ctype.h> + +inline bool _isdigit(char c) { + return ((uint8_t)((uint8_t)c - '0') < 10u) ? true : false; +} + +int atoi(const char *s) NONBANKED +{ + bool sign = false; + int n; + + const uint8_t * pc = (const uint8_t *)s; + + for(; ((*pc == ' ') || (*pc == '\t') || (*pc == '\n')); ++pc); + + switch(*pc) { + case '-': + sign = true; + /* and fall through */ + case '+': + ++pc; + break; + } + + for(n = 0; _isdigit(*pc); ++pc) n = 10 * n + (*pc - '0'); + + return (sign == 0 ? n : -n); +} diff --git a/gbdk/gbdk-lib/libc/atol.c b/gbdk/gbdk-lib/libc/atol.c new file mode 100644 index 00000000..16114378 --- /dev/null +++ b/gbdk/gbdk-lib/libc/atol.c @@ -0,0 +1,28 @@ +#include <stdint.h> +#include <stdbool.h> + +inline bool _isdigit(char c) { + return ((uint8_t)((uint8_t)c - '0') < 10u) ? true : false; +} + +long atol(const char *s) { + bool sign = false; + long n; + + const uint8_t * pc = (const uint8_t *)s; + + for(; ((*pc == ' ') || (*pc == '\t') || (*pc == '\n')); ++pc); + + switch(*pc) { + case '-': + sign = true; + /* and fall through */ + case '+': + ++pc; + break; + } + + for(n = 0; _isdigit(*pc); ++pc) n = 10 * n + (*pc - '0'); + + return (sign == 0 ? n : -n); +} diff --git a/gbdk/gbdk-lib/libc/atomic_flag_clear.c b/gbdk/gbdk-lib/libc/atomic_flag_clear.c new file mode 100644 index 00000000..4fc820c3 --- /dev/null +++ b/gbdk/gbdk-lib/libc/atomic_flag_clear.c @@ -0,0 +1,41 @@ +/*------------------------------------------------------------------------- + atomic_flag_clear.c + + Philipp Klaus Krause, pkk@spth.de 2020 + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library; see the file COPYING. If not, write to the + Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. + + As a special exception, if you link this library with other files, + some of which are compiled with SDCC, to produce an executable, + this library does not by itself cause the resulting executable to + be covered by the GNU General Public License. This exception does + not however invalidate any other reasons why the executable file + might be covered by the GNU General Public License. +-------------------------------------------------------------------------*/ + +#include <stdatomic.h> + +void atomic_flag_clear(volatile atomic_flag *object) +{ +#if defined(__SDCC_z80) || defined(__SDCC_z180) || defined(__SDCC_ez80_z80) || defined(__SDCC_sm83) || defined(__SDCC_r2k) || defined(__SDCC_r3ka) || defined(__SDCC_stm8) || defined(__SDCC_hc08) || defined(__SDCC_s08) + object->flag = 1; +#elif defined(__SDCC_mcs51) + object->flag = 0; +#else +#error Support for atomic_flag not implemented +#endif +} + diff --git a/gbdk/gbdk-lib/libc/bsearch.c b/gbdk/gbdk-lib/libc/bsearch.c new file mode 100644 index 00000000..3529796d --- /dev/null +++ b/gbdk/gbdk-lib/libc/bsearch.c @@ -0,0 +1,51 @@ +/*--------------------------------------------------------------------- + bsearch() - search a sorted array + + Copyright (C) 2018, Philipp Klaus Krause . pkk@spth.de + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library; see the file COPYING. If not, write to the + Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. + + As a special exception, if you link this library with other files, + some of which are compiled with SDCC, to produce an executable, + this library does not by itself cause the resulting executable to + be covered by the GNU General Public License. This exception does + not however invalidate any other reasons why the executable file + might be covered by the GNU General Public License. +-------------------------------------------------------------------------*/ + +#include <stdlib.h> + +void *bsearch(const void *key, const void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *) __reentrant) +{ + for(const char *left = base; nmemb;) + { + const char *middle = left + nmemb / 2 * size; + int c = (*compar)(key, middle); + + if(c < 0) + nmemb = nmemb / 2; + else if(c > 0) + { + left = middle + size; + nmemb = (nmemb - 1) / 2; + } + else + return(middle); + } + + return(0); +} + diff --git a/gbdk/gbdk-lib/libc/calloc.c b/gbdk/gbdk-lib/libc/calloc.c new file mode 100644 index 00000000..a5cab07c --- /dev/null +++ b/gbdk/gbdk-lib/libc/calloc.c @@ -0,0 +1,62 @@ +/*------------------------------------------------------------------------- + calloc.c - allocate memory. + + Copyright (C) 2015, Philipp Klaus Krause, pkk@spth.de + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library; see the file COPYING. If not, write to the + Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. + + As a special exception, if you link this library with other files, + some of which are compiled with SDCC, to produce an executable, + this library does not by itself cause the resulting executable to + be covered by the GNU General Public License. This exception does + not however invalidate any other reasons why the executable file + might be covered by the GNU General Public License. +-------------------------------------------------------------------------*/ + +#include <stdlib.h> +#include <string.h> +#include <stdint.h> + +#if defined(__SDCC_mcs51) || defined(__SDCC_ds390) || defined(__SDCC_ds400) +#define HEAPSPACE __xdata +#elif defined(__SDCC_pdk13) || defined(__SDCC_pdk14) || defined(__SDCC_pdk15) +#define HEAPSPACE __near +#else +#define HEAPSPACE +#endif + +#if defined(__SDCC_mcs51) || defined(__SDCC_ds390) || defined(__SDCC_ds400) +void HEAPSPACE *calloc (size_t nmemb, size_t size) +#else +void *calloc (size_t nmemb, size_t size) +#endif +{ + void HEAPSPACE *ptr; + + unsigned long msize = (unsigned long)nmemb * (unsigned long)size; + + _Static_assert(sizeof(unsigned long) >= sizeof(size_t) * 2, + "size_t too large wrt. unsigned long for overflow check"); + + if (msize > SIZE_MAX) + return(0); + + if (ptr = malloc(msize)) + memset(ptr, 0, msize); + + return(ptr); +} + diff --git a/gbdk/gbdk-lib/libc/free.c b/gbdk/gbdk-lib/libc/free.c new file mode 100644 index 00000000..bf1fdcd2 --- /dev/null +++ b/gbdk/gbdk-lib/libc/free.c @@ -0,0 +1,80 @@ +/*------------------------------------------------------------------------- + free.c - deallocate memory. + + Copyright (C) 2015, Philipp Klaus Krause, pkk@spth.de + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library; see the file COPYING. If not, write to the + Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. + + As a special exception, if you link this library with other files, + some of which are compiled with SDCC, to produce an executable, + this library does not by itself cause the resulting executable to + be covered by the GNU General Public License. This exception does + not however invalidate any other reasons why the executable file + might be covered by the GNU General Public License. +-------------------------------------------------------------------------*/ + +#include <stdlib.h> +#include <stddef.h> + +#if defined(__SDCC_mcs51) || defined(__SDCC_ds390) || defined(__SDCC_ds400) +#define HEAPSPACE __xdata +#elif defined(__SDCC_pdk13) || defined(__SDCC_pdk14) || defined(__SDCC_pdk15) +#define HEAPSPACE __near +#else +#define HEAPSPACE +#endif + +typedef struct header HEAPSPACE header_t; + +struct header +{ + header_t *next; + header_t *next_free; +}; + +extern header_t *HEAPSPACE __sdcc_heap_free; + +void free(void *ptr) +{ + header_t *h, *next_free, *prev_free; + header_t *HEAPSPACE *f; + + if(!ptr) + return; + + prev_free = 0; + for(h = __sdcc_heap_free, f = &__sdcc_heap_free; h && h < ptr; prev_free = h, f = &(h->next_free), h = h->next_free); // Find adjacent blocks in free list + next_free = h; + + h = (void HEAPSPACE *)((char HEAPSPACE *)(ptr) - offsetof(struct header, next_free)); + + // Insert into free list. + h->next_free = next_free; + *f = h; + + if(next_free == h->next) // Merge with next block + { + h->next_free = h->next->next_free; + h->next = h->next->next; + } + + if (prev_free && prev_free->next == h) // Merge with previous block + { + prev_free->next = h->next; + prev_free->next_free = h->next_free; + } +} + diff --git a/gbdk/gbdk-lib/libc/isalpha.c b/gbdk/gbdk-lib/libc/isalpha.c new file mode 100644 index 00000000..04ab5f3a --- /dev/null +++ b/gbdk/gbdk-lib/libc/isalpha.c @@ -0,0 +1,7 @@ +#include <ctype.h> +#include <stdbool.h> +#include <stdint.h> + +bool isalpha(char c) { + return ((((uint8_t)((uint8_t)c - 'a') < ('z' - 'a' + 1))) || ((uint8_t)((uint8_t)c - 'A') < ('Z' - 'A' + 1))) ? true : false; +} diff --git a/gbdk/gbdk-lib/libc/isdigit.c b/gbdk/gbdk-lib/libc/isdigit.c new file mode 100644 index 00000000..73e9ef61 --- /dev/null +++ b/gbdk/gbdk-lib/libc/isdigit.c @@ -0,0 +1,7 @@ +#include <ctype.h> +#include <stdbool.h> +#include <stdint.h> + +bool isdigit(char c) { + return ((uint8_t)((uint8_t)c - '0') < 10u) ? true : false; +} diff --git a/gbdk/gbdk-lib/libc/islower.c b/gbdk/gbdk-lib/libc/islower.c new file mode 100644 index 00000000..a3165f9f --- /dev/null +++ b/gbdk/gbdk-lib/libc/islower.c @@ -0,0 +1,7 @@ +#include <ctype.h> +#include <stdbool.h> +#include <stdint.h> + +bool islower(char c) { + return ((uint8_t)((uint8_t)c - 'a') < ('z' - 'a' + 1)) ? true : false; +} diff --git a/gbdk/gbdk-lib/libc/isspace.c b/gbdk/gbdk-lib/libc/isspace.c new file mode 100644 index 00000000..cbb0dce2 --- /dev/null +++ b/gbdk/gbdk-lib/libc/isspace.c @@ -0,0 +1,7 @@ +#include <ctype.h> +#include <stdbool.h> +#include <stdint.h> + +bool isspace(char c) { + return (((uint8_t)c == ' ') || ((uint8_t)c == '\t') || ((uint8_t)c == '\n')) ? true : false; +} diff --git a/gbdk/gbdk-lib/libc/isupper.c b/gbdk/gbdk-lib/libc/isupper.c new file mode 100644 index 00000000..75fe33bf --- /dev/null +++ b/gbdk/gbdk-lib/libc/isupper.c @@ -0,0 +1,7 @@ +#include <ctype.h> +#include <stdbool.h> +#include <stdint.h> + +bool isupper(char c) { + return ((uint8_t)((uint8_t)c - 'A') < ('Z' - 'A' + 1)) ? true : false; +} diff --git a/gbdk/gbdk-lib/libc/malloc.c b/gbdk/gbdk-lib/libc/malloc.c new file mode 100644 index 00000000..965e47dd --- /dev/null +++ b/gbdk/gbdk-lib/libc/malloc.c @@ -0,0 +1,114 @@ +/*------------------------------------------------------------------------- + malloc.c - allocate memory. + + Copyright (C) 2015, Philipp Klaus Krause, pkk@spth.de + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library; see the file COPYING. If not, write to the + Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. + + As a special exception, if you link this library with other files, + some of which are compiled with SDCC, to produce an executable, + this library does not by itself cause the resulting executable to + be covered by the GNU General Public License. This exception does + not however invalidate any other reasons why the executable file + might be covered by the GNU General Public License. +-------------------------------------------------------------------------*/ + +#include <stdlib.h> +#include <stddef.h> + +#if defined(__SDCC_mcs51) || defined(__SDCC_ds390) || defined(__SDCC_ds400) +#define HEAPSPACE __xdata +#elif defined(__SDCC_pdk13) || defined(__SDCC_pdk14) || defined(__SDCC_pdk15) +#define HEAPSPACE __near +#else +#define HEAPSPACE +#endif + +typedef struct header HEAPSPACE header_t; + +struct header +{ + header_t *next; // Next block. Linked list of all blocks, terminated by pointer to end of heap (or to the byte beyond the end of the heap). + header_t *next_free; // Next free block. Used in free blocks only. Overlaps with user data in non-free blocks. Linked list of free blocks, 0-terminated. +}; + +header_t *HEAPSPACE __sdcc_heap_free; // First free block, 0 if no free blocks. + +extern header_t __sdcc_heap; +#define HEAP_START &__sdcc_heap + +#if defined(__SDCC_mcs51) || defined(__SDCC_ds390) || defined(__SDCC_ds400) || defined(__SDCC_hc08) || defined(__SDCC_s08) + +extern const unsigned int __sdcc_heap_size; +#define HEAP_END (struct header HEAPSPACE *)((char HEAPSPACE *)&__sdcc_heap + (__sdcc_heap_size - 1)) // -1 To be sure that HEAP_END is bigger than HEAP_START. + +#else + +extern header_t __sdcc_heap_end; // Just beyond the end of the heap. Must be higher in memory than _sdcc_heap_start. +#define HEAP_END &__sdcc_heap_end + +#endif + +void __sdcc_heap_init(void) +{ + __sdcc_heap_free = HEAP_START; + __sdcc_heap_free->next = HEAP_END; + __sdcc_heap_free->next_free = 0; +} + +#if defined(__SDCC_mcs51) || defined(__SDCC_ds390) || defined(__SDCC_ds400) +void HEAPSPACE *malloc(size_t size) +#else +void *malloc(size_t size) +#endif +{ + header_t *h; + header_t *HEAPSPACE *f; + +#if defined(__SDCC_mcs51) || defined(__SDCC_ds390) || defined(__SDCC_ds400) || defined(__SDCC_hc08) || defined(__SDCC_s08) + if(!__sdcc_heap_free) + __sdcc_heap_init(); +#endif + + if(!size || size + offsetof(struct header, next_free) < size) + return(0); + size += offsetof(struct header, next_free); + if(size < sizeof(struct header)) // Requiring a minimum size makes it easier to implement free(), and avoid memory leaks. + size = sizeof(struct header); + + for(h = __sdcc_heap_free, f = &__sdcc_heap_free; h; f = &(h->next_free), h = h->next_free) + { + size_t blocksize = (char HEAPSPACE *)(h->next) - (char HEAPSPACE *)h; + if(blocksize >= size) // Found free block of sufficient size. + { + if(blocksize >= size + sizeof(struct header)) // It is worth creating a new free block + { + header_t *const newheader = (header_t *const)((char HEAPSPACE *)h + size); + newheader->next = h->next; + newheader->next_free = h->next_free; + *f = newheader; + h->next = newheader; + } + else + *f = h->next_free; + + return(&(h->next_free)); + } + } + + return(0); +} + diff --git a/gbdk/gbdk-lib/libc/printf.c b/gbdk/gbdk-lib/libc/printf.c new file mode 100644 index 00000000..73382cb4 --- /dev/null +++ b/gbdk/gbdk-lib/libc/printf.c @@ -0,0 +1,11 @@ +#include <stdio.h> +#include <stdarg.h> + +void __printf(const char *format, void *emitter, char **pData, va_list va); + +void printf(const char *format, ...) OLDCALL { + va_list va; + va_start(va, format); + + __printf(format, (void *)putchar, NULL, va); +} diff --git a/gbdk/gbdk-lib/libc/puts.c b/gbdk/gbdk-lib/libc/puts.c new file mode 100644 index 00000000..1a661338 --- /dev/null +++ b/gbdk/gbdk-lib/libc/puts.c @@ -0,0 +1,12 @@ +#include <stdio.h> + +extern const char *__crlf; + +void puts(const char *s) NONBANKED +{ + while (*s) + putchar(*s++); + + for (s = __crlf; (*s); ) + putchar(*s++); +} diff --git a/gbdk/gbdk-lib/libc/qsort.c b/gbdk/gbdk-lib/libc/qsort.c new file mode 100644 index 00000000..b4ac1f87 --- /dev/null +++ b/gbdk/gbdk-lib/libc/qsort.c @@ -0,0 +1,61 @@ +/*--------------------------------------------------------------------- + qsort() - sort an array + + Copyright (C) 2018, Philipp Klaus Krause . krauseph@informatik.uni-freiburg.de + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library; see the file COPYING. If not, write to the + Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. + + As a special exception, if you link this library with other files, + some of which are compiled with SDCC, to produce an executable, + this library does not by itself cause the resulting executable to + be covered by the GNU General Public License. This exception does + not however invalidate any other reasons why the executable file + might be covered by the GNU General Public License. +-------------------------------------------------------------------------*/ + +#include <stdlib.h> + +// Despite the name, this is an insertion sort, since it tends to be smaller in code size. + +static void swap(void *restrict dst, void *restrict src, size_t n) +{ + unsigned char *restrict d = dst; + unsigned char *restrict s = src; + + while(n--) + { + unsigned char tmp = *d; + *d = *s; + *s = tmp; + d++; + s++; + } +} + +void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *) __reentrant) +{ + unsigned char *b = base; + + if(nmemb <= 1) + return; + + for(unsigned char *i = base; i < b + nmemb * size; i += size) + { + for(unsigned char *j = i; (j > b) && (*compar)(j, j - size) < 0; j -= size) + swap(j, j - size, size); + } +} + diff --git a/gbdk/gbdk-lib/libc/realloc.c b/gbdk/gbdk-lib/libc/realloc.c new file mode 100644 index 00000000..41fa4944 --- /dev/null +++ b/gbdk/gbdk-lib/libc/realloc.c @@ -0,0 +1,139 @@ +/*------------------------------------------------------------------------- + realloc.c - allocate memory. + + Always behaves according to C90 (i.e. does not take advantage of + undefined behaviour introduced in C2X or implementation-defined + behaviour introduced in C17. + + Copyright (C) 2015-2020, Philipp Klaus Krause, pkk@spth.de + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library; see the file COPYING. If not, write to the + Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. + + As a special exception, if you link this library with other files, + some of which are compiled with SDCC, to produce an executable, + this library does not by itself cause the resulting executable to + be covered by the GNU General Public License. This exception does + not however invalidate any other reasons why the executable file + might be covered by the GNU General Public License. +-------------------------------------------------------------------------*/ + +#include <stdlib.h> +#include <stddef.h> +#include <string.h> + +#if defined(__SDCC_mcs51) || defined(__SDCC_ds390) || defined(__SDCC_ds400) +#define HEAPSPACE __xdata +#elif defined(__SDCC_pdk13) || defined(__SDCC_pdk14) || defined(__SDCC_pdk15) +#define HEAPSPACE __near +#else +#define HEAPSPACE +#endif + +typedef struct header HEAPSPACE header_t; + +struct header +{ + header_t *next; + header_t *next_free; +}; + +extern header_t *HEAPSPACE __sdcc_heap_free; + +void __sdcc_heap_init(void); + +#if defined(__SDCC_mcs51) || defined(__SDCC_ds390) || defined(__SDCC_ds400) +void HEAPSPACE *realloc(void *ptr, size_t size) +#else +void *realloc(void *ptr, size_t size) +#endif +{ + void HEAPSPACE *ret; + header_t *h, *next_free, *prev_free; + header_t *HEAPSPACE *f, *HEAPSPACE *pf; + size_t blocksize, oldblocksize, maxblocksize; + +#if defined(__SDCC_mcs51) || defined(__SDCC_ds390) || defined(__SDCC_ds400) || defined(__SDCC_hc08) || defined(__SDCC_s08) + if(!__sdcc_heap_free) + __sdcc_heap_init(); +#endif + + if(!ptr) + return(malloc(size)); + + if(!size) + { + free(ptr); + return(0); + } + + prev_free = 0, pf = 0; + for(h = __sdcc_heap_free, f = &__sdcc_heap_free; h && h < ptr; prev_free = h, pf = f, f = &(h->next_free), h = h->next_free); // Find adjacent blocks in free list + next_free = h; + + if(size + offsetof(struct header, next_free) < size) // Handle overflow + return(0); + blocksize = size + offsetof(struct header, next_free); + if(blocksize < sizeof(struct header)) // Requiring a minimum size makes it easier to implement free(), and avoid memory leaks. + blocksize = sizeof(struct header); + + h = (void HEAPSPACE *)((char HEAPSPACE *)(ptr) - offsetof(struct header, next_free)); + oldblocksize = (char HEAPSPACE *)(h->next) - (char HEAPSPACE *)h; + + maxblocksize = oldblocksize; + if(prev_free && prev_free->next == h) // Can merge with previous block + maxblocksize += (char HEAPSPACE *)h - (char HEAPSPACE *)prev_free; + if(next_free == h->next) // Can merge with next block + maxblocksize += (char HEAPSPACE *)(next_free->next) - (char HEAPSPACE *)next_free; + + if(blocksize <= maxblocksize) // Can resize in place. + { + if(prev_free && prev_free->next == h) // Always move into previous block to defragment + { + memmove(prev_free, h, blocksize <= oldblocksize ? blocksize : oldblocksize); + h = prev_free; + *pf = next_free; + f = pf; + } + + if(next_free && next_free == h->next) // Merge with following block + { + h->next = next_free->next; + *f = next_free->next_free; + } + + if(maxblocksize >= blocksize + sizeof(struct header)) // Create new block from free space + { + header_t *const newheader = (header_t *const)((char HEAPSPACE *)h + blocksize); + newheader->next = h->next; + newheader->next_free = *f; + *f = newheader; + h->next = newheader; + } + + return(&(h->next_free)); + } + + if(ret = malloc(size)) + { + size_t oldsize = oldblocksize - offsetof(struct header, next_free); + memcpy(ret, ptr, size <= oldsize ? size : oldsize); + free(ptr); + return(ret); + } + + return(0); +} + diff --git a/gbdk/gbdk-lib/libc/rules-asxxxx.mk b/gbdk/gbdk-lib/libc/rules-asxxxx.mk new file mode 100644 index 00000000..eaebb9a2 --- /dev/null +++ b/gbdk/gbdk-lib/libc/rules-asxxxx.mk @@ -0,0 +1,18 @@ +$(LIB): pre $(OBJ) + for file in $(filter-out %/crt0.o,$(OBJ)) ; do \ + $(SDAR) -ru $(LIB) $${file} ; \ + done + +pre: set-model build-dir + +$(BUILD)/%.o: ../%.c + $(CC) $(CFLAGS) -c -o $@ $< + +$(BUILD)/%.o: %.c + $(CC) $(CFLAGS) -c -o $@ $< + +$(BUILD)/%.o: ../%.s + $(AS) -plosgff $@ $< + +$(BUILD)/%.o: %.s + $(AS) -plosgff $@ $< diff --git a/gbdk/gbdk-lib/libc/scanf.c b/gbdk/gbdk-lib/libc/scanf.c new file mode 100644 index 00000000..d1b5317b --- /dev/null +++ b/gbdk/gbdk-lib/libc/scanf.c @@ -0,0 +1,153 @@ +#include <stdint.h> +#include <stdio.h> +#include <stdarg.h> +#include <ctype.h> + +static unsigned char scan_skip(char *s, unsigned char i) +{ +oncemore: + while(isspace(s[i])) + i++; + if(s[i] == 0) { + gets(s); + i = 0; + goto oncemore; + } + return i; +} + +static unsigned char scan_int(char *s, unsigned char i, unsigned char base, char *nb) +{ + char n = 0; + unsigned char j, sign = 0; + + switch(s[i]) + { + case '-': + sign++; + /* and fall through */ + case '+': + ++i; + break; + } + while(1) { + if(isdigit(s[i])) + j = s[i] - '0'; + else if(isalpha(s[i])) + j = toupper(s[i]) - 'A' + 10; + else + break; + if(j >= base) + break; + n = base * n + j; + i++; + } + *nb = (sign == 0 ? n : -n); + return i; +} + +static unsigned char scan_long(char *s, unsigned char i, unsigned char base, int *nb) +{ + int n = 0; + unsigned char j, sign = 0; + + switch(s[i]) + { + case '-': + sign++; + /* and fall through */ + case '+': + ++i; + break; + } + while(1) { + if(isdigit(s[i])) + j = s[i] - '0'; + else if(isalpha(s[i])) + j = toupper(s[i]) - 'A' + 10; + else + break; + if(j >= base) + break; + n = base * n + j; + i++; + } + *nb = (sign == 0 ? n : -n); + return i; +} + +char scanf(char *fmt, ...) +{ + va_list ap; + char s[64]; + unsigned char i = 0; + char nb = 0; + + gets(s); + va_start(ap, fmt); + for(; *fmt; fmt++) { + if(isspace(*fmt)) + continue; + i = scan_skip(s, i); + if(*fmt == '%') { + switch(*++fmt) { + case 'c': + /* char */ + *va_arg(ap, char *) = s[i++]; + break; + case 'd': + /* decimal int */ + case 'u': + /* unsigned int */ + i = scan_int(s, i, 10, va_arg(ap, char *)); + break; + case 'o': + /* octal int */ + i = scan_int(s, i, 8, va_arg(ap, char *)); + break; + case 'x': + /* hexadecimal int */ + i = scan_int(s, i, 16, va_arg(ap, char *)); + break; + case 's': + /* string */ + { + char j = 0; + char *d = va_arg(ap, char *); + while((d[j++] = s[i++]) != 0) + ; + } + break; + case 'l': + /* long */ + switch(*++fmt) { + case 'd': + /* decimal long */ + case 'u': + /* unsigned long */ + i = scan_long(s, i, 10, va_arg(ap, int *)); + break; + case 'o': + /* octal long */ + i = scan_long(s, i, 8, va_arg(ap, int *)); + break; + case 'x': + /* hexadecimal long */ + i = scan_long(s, i, 16, va_arg(ap, int *)); + break; + } + break; + default: + if(s[i] != *fmt) + return -1; + break; + } + nb++; + } else + if(s[i] != *fmt) + return -1; + } + va_end(ap); + + return nb; +} diff --git a/gbdk/gbdk-lib/libc/sprintf.c b/gbdk/gbdk-lib/libc/sprintf.c new file mode 100644 index 00000000..c8e23acd --- /dev/null +++ b/gbdk/gbdk-lib/libc/sprintf.c @@ -0,0 +1,112 @@ +#include <types.h> +#include <stdio.h> +#include <stdarg.h> +#include <stdlib.h> +#include <stdint.h> + +typedef void (*emitter_t)(char, char **) OLDCALL; + +static const char _hex[] = "0123456789ABCDEF"; + +inline void _printhex(uint16_t u, emitter_t emitter, char ** pData) +{ + (*emitter)(_hex[(uint8_t)(u >> 8) >> 4], pData); + (*emitter)(_hex[(uint8_t)(u >> 8) & 0x0fu], pData); + (*emitter)(_hex[((uint8_t)u >> 4) & 0x0fu], pData); + (*emitter)(_hex[(uint8_t)u & 0x0fu], pData); +} + +inline void _printhexbyte(uint8_t u, emitter_t emitter, char ** pData) +{ + (*emitter)(_hex[u >> 4], pData); + (*emitter)(_hex[u & 0x0fu], pData); +} + +static void _printbuf(char * buf, emitter_t emitter, char ** pData) { + for (char *s = buf; *s; s++) (*emitter)(*s, pData); +} + +void __printf(const char *format, emitter_t emitter, char **pData, va_list va) +{ + char buf[16]; + while ((uint8_t)(*format)) { + if ((uint8_t)(*format) == '%') { + format++; + + // 0 Padding is not supported, ignore + if ((uint8_t)(*format) == '0') format++; + + // Width Specifier is not supported, ignore 1 digit worth + if ((uint8_t)((uint8_t)(*format) - '1') < 9u) format++; + + switch ((uint8_t)(*format)) { + case 'h': { + switch ((uint8_t)(*++format)) { + case 'X' : + case 'x' : { + _printhexbyte(va_arg(va, char), emitter, pData); + break; + } + case 'u': + { + uitoa((unsigned char)va_arg(va, char), buf, 10); + _printbuf(buf, emitter, pData); + break; + } + case 'd': + { + itoa((signed char)va_arg(va, char), buf, 10); + _printbuf(buf, emitter, pData); + break; + } + } + break; + } + case 'c': { + char c = va_arg(va, char); + (*emitter)(c, pData); + break; + } + case 'u': + { + uitoa(va_arg(va, int), buf, 10); + _printbuf(buf, emitter, pData); + break; + } + case 'd': + { + itoa(va_arg(va, int), buf, 10); + _printbuf(buf, emitter, pData); + break; + } + case 'X': + case 'x': + { + _printhex(va_arg(va, int), emitter, pData); + break; + } + case 's': + { + _printbuf(va_arg(va, char *), emitter, pData); + break; + } + } + } else { + (*emitter)(*format, pData); + } + format++; + } +} + +static void _sprintf_emitter(char c, char ** pData) OLDCALL { + **pData = c; + (*pData)++; +} + +void sprintf(char *into, const char *format, ...) OLDCALL { + va_list va; + va_start(va, format); + + __printf(format, _sprintf_emitter, &into, va); + _sprintf_emitter('\0', &into); +} diff --git a/gbdk/gbdk-lib/libc/strcat.c b/gbdk/gbdk-lib/libc/strcat.c new file mode 100644 index 00000000..a2088b07 --- /dev/null +++ b/gbdk/gbdk-lib/libc/strcat.c @@ -0,0 +1,14 @@ +#include <string.h> + +/* + * Concatenate s2 on the end of s1. s1 must be large enough. + * Return s1. + */ + +char *strcat(char *s1, const char *s2) { + char *os1 = s1; + while (*s1++) ; + --s1; + while (*s1++ = *s2++) ; + return os1; +} diff --git a/gbdk/gbdk-lib/libc/string.c b/gbdk/gbdk-lib/libc/string.c new file mode 100644 index 00000000..c1f8198a --- /dev/null +++ b/gbdk/gbdk-lib/libc/string.c @@ -0,0 +1,36 @@ +/** Dumb strings hack. +*/ +#include <string.h> +#include <gbdk/gbdk-lib.h> + +#if USE_C_STRCPY +char *strcpy(char *dest, const char *source) NONBANKED +{ + char *d = dest; + const char *s = source; + while (*d = *s) d++, s++; + return dest; +} +#endif + +#if USE_C_MEMCPY +void *memcpy(void *dest, const void *source, size_t count) NONBANKED +{ + char *d = dest; + const char *s = source; + while (count--) { + *d = *s; + d++; + s++; + } + return dest; +} +#endif + +#if USE_C_STRCMP +int strcmp(const char *s1, const char *s2) { + char ret = 0; + while (!(ret = *s1 - *s2) && *s2) ++s1, ++s2; + return (ret < 0) ? -1 : ((ret > 0) ? 1 : 0); +} +#endif diff --git a/gbdk/gbdk-lib/libc/strncat.c b/gbdk/gbdk-lib/libc/strncat.c new file mode 100644 index 00000000..6bfdb30e --- /dev/null +++ b/gbdk/gbdk-lib/libc/strncat.c @@ -0,0 +1,21 @@ +#include <string.h> + +/* + * Concatenate s2 on the end of s1. s1 must be large enough. + * At most n characters are moved. + * Return s1. + */ + +char *strncat(char *s1, const char *s2, int n) { + char *os1 = s1; + while (*s1++) ; + --s1; + while (*s1++ = *s2++) { + if (n == 0) { + *--s1 = '\0'; + break; + } + n--; + } + return os1; +} diff --git a/gbdk/gbdk-lib/libc/strncmp.c b/gbdk/gbdk-lib/libc/strncmp.c new file mode 100644 index 00000000..1f0eaa43 --- /dev/null +++ b/gbdk/gbdk-lib/libc/strncmp.c @@ -0,0 +1,16 @@ +#include <string.h> + +/* + * Compare strings (at most n bytes): + * s1>s2: >0 + * s1==s2: 0 + * s1<s2: <0 + */ + +int strncmp(const char *s1, const char *s2, int n) { + while ((n > 0) && (*s1 == *s2++)) { + if (*s1++ == '\0') return 0; + n--; + } + return (n == 0 ? 0 : *s1 - *--s2); +} diff --git a/gbdk/gbdk-lib/libc/strncpy.c b/gbdk/gbdk-lib/libc/strncpy.c new file mode 100644 index 00000000..6d6428a1 --- /dev/null +++ b/gbdk/gbdk-lib/libc/strncpy.c @@ -0,0 +1,18 @@ +#include <string.h> + +/* + * Copy s2 to s1, truncating or null-padding to always copy n bytes. + * Return s1. + */ + +char *strncpy(char *s1, const char *s2, int n) { + int i; + char *os1 = s1; + for (i = 0; i < n; i++) { + if ((*s1++ = *s2++) == '\0') { + while (++i < n) *s1++ = '\0'; + return os1; + } + } + return os1; +} diff --git a/gbdk/gbdk-lib/libc/targets/sm83/___sdcc_bcall.s b/gbdk/gbdk-lib/libc/targets/sm83/___sdcc_bcall.s new file mode 100644 index 00000000..a6aa2ff3 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/___sdcc_bcall.s @@ -0,0 +1,27 @@ + .include "global.s" + + .area _HOME + +___sdcc_bcall:: +banked_call:: ; Performs a long call. + pop hl ; Get the return address + ldh a,(__current_bank) + push af ; Push the current bank onto the stack + ld a,(hl+) ; Fetch the call address + ld e, a + ld a,(hl+) + ld d, a + ld a,(hl+) ; ...and page + inc hl ; Yes this should be here + push hl ; Push the real return address + ldh (__current_bank),a + ld (.MBC_ROM_PAGE),a ; Perform the switch + ld l,e + ld h,d + rst 0x20 +banked_ret:: + pop hl ; Get the return address + pop af ; Pop the old bank + ldh (__current_bank),a + ld (.MBC_ROM_PAGE),a + jp (hl) diff --git a/gbdk/gbdk-lib/libc/targets/sm83/___sdcc_bcall_ehl.s b/gbdk/gbdk-lib/libc/targets/sm83/___sdcc_bcall_ehl.s new file mode 100644 index 00000000..e67ebce0 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/___sdcc_bcall_ehl.s @@ -0,0 +1,15 @@ + .include "global.s" + + .area _HOME + +___sdcc_bcall_ehl:: ; Performs a long call. + ldh a,(__current_bank) + push af ; Push the current bank onto the stack + ld a, e + ldh (__current_bank),a + ld (.MBC_ROM_PAGE),a ; Perform the switch + rst 0x20 + pop af ; Pop the old bank + ldh (__current_bank),a + ld (.MBC_ROM_PAGE),a + ret
\ No newline at end of file diff --git a/gbdk/gbdk-lib/libc/targets/sm83/ap/Makefile b/gbdk/gbdk-lib/libc/targets/sm83/ap/Makefile new file mode 100644 index 00000000..f8201547 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/ap/Makefile @@ -0,0 +1,47 @@ +# GB specific Makefile + +TOPDIR = ../../../.. + +THIS = ap +PORT = sm83 + +CSRC = crlf.c digits.c gprint.c gprintf.c gprintln.c gprintn.c + +ASSRC = cgb.s cgb_palettes.s cgb_compat.s \ + cpy_data.s \ + drawing.s drawing_isr.s color.s \ + f_ibm_full.s f_ibm_sh.s f_italic.s f_min.s f_spect.s \ + get_bk_t.s get_data.s get_tile.s \ + get_wi_t.s get_xy_t.s \ + get_addr.s \ + hiramcpy.s init_tt.s input.s \ + pad.s \ + serial.s set_bk_t.s set_tile.s \ + set_data.s set_prop.s set_spr.s set_wi_t.s set_xy_t.s \ + set_1bit_data.s \ + sgb.s font.s font_color.s delay.s \ + emu_debug.s emu_debug_printf.s \ + nowait.s far_ptr.s \ + lcd.s joy.s tim.s tim_nested.s tim_common.s \ + crash_handler.s \ + ___sdcc_bcall_ehl.s ___sdcc_bcall.s \ + mv_spr.s \ + pad_ex.s \ + mode.s clock.s \ + get_t.s set_t.s init_vram.s \ + fill_rect.s fill_rect_bk.s fill_rect_wi.s \ + metasprites.s metasprites_flip.s metasprites_hide.s metasprites_hide_spr.s \ + set_tile_submap.s set_win_tile_submap.s \ + gb_decompress.s gb_decompress_tiles.s \ + rle_decompress.s \ + heap.s \ + sfr.s \ + crt0.s + +CRT0 = crt0.s + +include $(TOPDIR)/Makefile.common + +AS = $(AS_SM83) + +include ../../../Makefile.platform diff --git a/gbdk/gbdk-lib/libc/targets/sm83/ap/crash_handler.s b/gbdk/gbdk-lib/libc/targets/sm83/ap/crash_handler.s new file mode 100644 index 00000000..ec08a7f8 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/ap/crash_handler.s @@ -0,0 +1,481 @@ +; Crash handler support +; Original code by ISSOtm +; Adapted by Toxa from gb-starter-kit: https://github.com/ISSOtm/gb-starter-kit + + .include "global.s" + + .globl _font_ibm + + SCRN_X = 160 ; Width of screen in pixels + SCRN_Y = 144 ; Height of screen in pixels + SCRN_X_B = 20 ; Width of screen in bytes + SCRN_Y_B = 18 ; Height of screen in bytes + + SCRN_VX = 256 ; Virtual width of screen in pixels + SCRN_VY = 256 ; Virtual height of screen in pixels + SCRN_VX_B = 32 ; Virtual width of screen in bytes + SCRN_VY_B = 32 ; Virtual height of screen in bytes + + + .area _CRASH_HEADER(ABS) + + .org 0x00 + nop + nop + rst 0x38 + + .org 0x38 + di + jp ___HandleCrash + + + .area _HOME + +___HandleCrash:: + + ; We will use VRAM as scratch, since we are going to overwrite it for + ; screen output anyways. The thing is, we need to turn the LCD off + ; *without* affecting flags... fun task, eh? + + ; Note: it's assumed that this was jumped to with IME off. + ; Don't call this directly, use `rst Crash`. + + ld (wCrashA), a ; We need to have at least one working register, so... + ldh a, (.IE) ; We're also going to overwrite this + ld (wCrashIE), a + ldh a, (.LCDC) + ld (wCrashLCDC), a + ld a, #LCDCF_ON ; LCDCF_ON Make sure the LCD is turned on to avoid waiting infinitely + ldh (.LCDC), a + ld a, #IEF_VBLANK ; IEF_VBLANK + ld (.IE), a + ld a, #0 ; `xor a` would overwrite flags + ld (.IF), a ; No point in backing up that register, it's always changing + halt ; With interrupts disabled, this will exit when `IE & IF != 0` + nop ; Handle hardware bug if it becomes true *before* starting to execute the instruction (1-cycle window) + + ; We're now in VBlank! So we can now use VRAM as scratch for some cycles + ld a, #0 + ldh (.LCDC), a ; Turn off LCD so VRAM can always be safely accessed + ; Save regs + ld (vCrashSP), sp + ld sp, #vCrashSP + push hl + push de + push bc + ld a, (wCrashA) + push af + + ; We need to have all the data in bank 0, but we can't guarantee we were there + ldh a, (.VBK) + ld e, a + bit #0, a + jr z, .bank0 + ; Oh noes. We need to copy the data across banks! + ld hl, #vCrashAF + ld c, #(5 * 2) +.copyAcross: + ld b, (hl) + xor a + ldh (.VBK), a + ld (hl), b + inc l ; inc hl + inc a ; ld a, 1 + ldh (.VBK), a + dec c + jr nz, .copyAcross +.bank0: + xor a + ldh (.NR52), a ; Kill sound for this screen + + ldh (.VBK), a + ld a, e + ld (vCrashVBK), a ; copy vCrashVBK across banks + + ld a, #1 + ldh (.VBK), a + ld hl, #vCrashDumpScreen + ld b, #SCRN_Y_B +.writeAttrRow: + xor a + ld c, #(SCRN_X_B + 1) + rst #0x28 ; .MemsetSmall + ld a, l + add a, #(SCRN_VX_B - SCRN_X_B - 1) + ld l, a + dec b + jr nz, .writeAttrRow + xor a + ldh (.VBK), a + + ; Load palettes + ld a, #0x03 + ldh (.BGP), a + ld a, #0x80 + ldh (.BCPS), a + xor a + ld c, #.BCPD + ldh (c), a + ldh (c), a + dec a ; ld a, $FF + ldh (c), a + ldh (c), a + ldh (c), a + ldh (c), a + ldh (c), a + ldh (c), a + + ld a, #(SCRN_VY - SCRN_Y) + ldh (.SCY), a + ld a, #(SCRN_VX - SCRN_X - 4) + ldh (.SCX), a + + call loadfont + + ; Copy the registers to the dump viewers + ld hl, #vDumpHL + ld de, #vCrashHL + ld c, #4 + rst #0x30 ; .MemcpySmall + + ; We're now going to draw the screen, top to bottom + ld hl, #vCrashDumpScreen + + ; First 3 lines of text + ld de, #.header + ld b, #3 +.writeHeaderLine: + ld a, #0x20 ; " " + ld (hl+), a + ld c, #19 + rst #0x30 ; .MemcpySmall + ld a, #0x20 ; " " + ld (hl+), a + ld a, l + add a, #(SCRN_VX_B - SCRN_X_B - 1) + ld l, a + dec b + jr nz, .writeHeaderLine + + ; Blank line + ld a, #0x20 ; " " + ld c, #(SCRN_X_B + 1) + rst #0x28 ; .MemsetSmall + + ; AF and console model + ld l, #<vCrashDumpScreenRow4 + ld c, #4 + rst #0x30 ; .MemcpySmall + pop bc + call .printHexBC + ld c, #8 + rst #0x30 ; .MemcpySmall + ld a, (__cpu) + call .printHexA + ld a, #0x20 ; " " + ld (hl+), a + ld (hl+), a + ld (hl+), a + + ; BC and DE + ld l, #<vCrashDumpScreenRow5 + ld c, #4 + rst #0x30 ; .MemcpySmall + pop bc + call .printHexBC + ld c, #6 + rst #0x30 ; .MemcpySmall + pop bc + call .printHexBC + ld a, #0x20 + ld (hl+), a + ld (hl+), a + ld (hl+), a + + ; Now, the two memory dumps +.writeDump: + ld a, l + add a, #(SCRN_VX_B - SCRN_X_B - 1) + ld l, a + ld c, #4 + rst #0x30 ; .MemcpySmall + pop bc + push bc + call .printHexBC + ld de, #.viewStr + ld c, #7 + rst #0x30 ; .MemcpySmall + pop de + call .printDump + ld de, #.spStr + bit #7, l + jr z, .writeDump + + ld de, #.hwRegsStrs + ld l, #<vCrashDumpScreenRow14 + ld c, #6 + rst #0x30 ; .MemcpySmall + ld a, (wCrashLCDC) + call .printHexA + ld c, #4 + rst #0x30 ; .MemcpySmall + ldh a, (.KEY1) + call .printHexA + ld c, #4 + rst #0x30 ; .MemcpySmall + ld a, (wCrashIE) + call .printHexA + ld (hl), #0x20 ; " " + + ld l, #<vCrashDumpScreenRow15 + ld c, #7 + rst #0x30 ; .MemcpySmall +.writeBank: + ld a, #0x20 ; " " + ld (hl+), a + ld a, (de) + inc de + ld (hl+), a + cp #0x20 ; " " + jr z, .banksDone + ld a, (de) + inc de + ld c, a + ld a, (de) + inc de + ld b, a + ld a, (bc) + call .printHexA + jr .writeBank +.banksDone: + + ; Start displaying + ld a, #(LCDCF_ON | LCDCF_BG9C00 | LCDCF_BGON) + ldh (.LCDC), a + +.loop: + ; The code never lags, and IE is equal to IEF_VBLANK + xor a + ldh (.IF), a + halt + + jr .loop + +.printHexBC: + call .printHexB + ld a, c +.printHexA: + ld b, a +.printHexB: + ld a, b + and #0xF0 + swap a + add a, #0x30 + cp #0x3a + jr c, 1$ + add a, #(0x41 - 0x3a) +1$: ld (hl+), a + ld a, b + and #0x0F + add a, #0x30 + cp #0x3a + jr c, 2$ + add a, #(0x41 - 0x3a) +2$: ld (hl+), a + ret + +.printDump: + ld b, d + ld c, e + call .printHexBC + ld a, #0x20 ; " " + ld (hl+), a + ld (hl+), a + ld a, e + sub #8 + ld e, a + ld a, d + sbc #0 + ld d, a +.writeDumpLine: + ld a, l + add a, #(SCRN_VX_B - SCRN_X_B - 1) + ld l, a + ld a, #0x20 ; " " + ld (hl+), a +.writeDumpWord: + ld a, (de) + inc de + call .printHexA + ld a, (de) + inc de + call .printHexA + ld a, #0x20 ; " " + ld (hl+), a + bit 4, l + jr nz, .writeDumpWord + ld a, l + and #0x7F + jr nz, .writeDumpLine + ret + +loadfont: + xor a + cpl + ld hl, #0x9000 + ld c, #16 + rst #0x28 ; .MemsetSmall + ld hl, #(0x9000 + ' ' * 16) + ld c, #16 + rst #0x28 ; .MemsetSmall + + ld de, #(_font_ibm + 2 + '0') ; recode table + ld hl, #(0x9000 + '0' * 16) ; destination + push hl + ld c, #(16 * 3) +1$: + ld a, (de) + inc de + push de + + swap a + ld l, a + and #0x0f + ld h, a + ld a, l + and #0xf0 + srl h + rra + ld l, a + ld de, #(_font_ibm + 2 + 128) + add hl, de + + ld d, h + ld e, l + + ldhl sp, #2 + ld a, (hl+) + ld h, (hl) + ld l, a + + ld b, #8 +2$: + ld a, (de) + cpl + inc de + ld (hl+), a + ld (hl+), a + + dec b + jr nz, 2$ + + ld d, h + ld a, l + ldhl sp, #2 + ld (hl+), a + ld (hl), d + + pop de + + dec c + jr nz, 1$ + + add sp, #2 + ret + +.header: + ; 0123456789ABCDEFGHI 19 chars + .ascii "KERNEL PANIC PLEASE" + .ascii "SEND A CLEAR PIC OF" + .ascii "THIS SCREEN TO DEVS" + .ascii " AF:" + .ascii " MODEL:" + .ascii " BC:" + .ascii " DE:" + .ascii " HL:" +.viewStr: + .ascii " VIEW:" +.spStr: + .ascii " SP:" +.hwRegsStrs: + .ascii " LCDC:" + .ascii " K1:" + .ascii " IE:" + .ascii " BANK:" + .ascii "R" + .dw __current_bank + .ascii "V" + .dw vCrashVBK + .ascii "W" + .db .SVBK, 0xff + .ascii " " + + + .area _DATA + +wCrashA: + .ds 1 ; We need at least one working register, and A allows accessing memory +wCrashIE: + .ds 1 +wCrashLCDC: + .ds 1 + + + .area _CRASH_SCRATCH(ABS) + + .org 0x9C00 + + ; Put the crash dump screen at the bottom-right of the 9C00 tilemap, since that tends to be unused space + .ds SCRN_VX_B * (SCRN_VY_B - SCRN_Y_B - 2) ; 2 rows reserved as scratch space + + .ds SCRN_X_B ; Try not to overwrite the window area + .ds 2 * 1 ; Free stack entries (we spill into the above by 1 entry, though :/) + ; These are the initial values of the registers + ; They are popped off the stack when printed, freeing up stack space + +vCrashAF: + .ds 2 +vCrashBC: + .ds 2 +vCrashDE: + .ds 2 +vCrashHL: + .ds 2 +vCrashSP: + .ds 2 + + .ds SCRN_X_B +vHeldKeys: + .ds 1 ; Keys held on previous frame +vUnlockCounter: + .ds 1 ; How many frames until dumps are "unlocked" +vWhichDump: + .ds 1 +vDumpHL: + .ds 2 +vDumpSP: + .ds 2 +vCrashVBK: + .ds 1 + .ds 4 ; Unused + + .ds SCRN_VX_B - SCRN_X_B - 1 +vCrashDumpScreen: +vCrashDumpScreenRow0 = vCrashDumpScreen + 1 * SCRN_VX_B +vCrashDumpScreenRow1 = vCrashDumpScreen + 2 * SCRN_VX_B +vCrashDumpScreenRow2 = vCrashDumpScreen + 3 * SCRN_VX_B +vCrashDumpScreenRow3 = vCrashDumpScreen + 4 * SCRN_VX_B +vCrashDumpScreenRow4 = vCrashDumpScreen + 5 * SCRN_VX_B +vCrashDumpScreenRow5 = vCrashDumpScreen + 6 * SCRN_VX_B +vCrashDumpScreenRow6 = vCrashDumpScreen + 7 * SCRN_VX_B +vCrashDumpScreenRow7 = vCrashDumpScreen + 8 * SCRN_VX_B +vCrashDumpScreenRow8 = vCrashDumpScreen + 9 * SCRN_VX_B +vCrashDumpScreenRow9 = vCrashDumpScreen + 10 * SCRN_VX_B +vCrashDumpScreenRow10 = vCrashDumpScreen + 11 * SCRN_VX_B +vCrashDumpScreenRow11 = vCrashDumpScreen + 12 * SCRN_VX_B +vCrashDumpScreenRow12 = vCrashDumpScreen + 13 * SCRN_VX_B +vCrashDumpScreenRow13 = vCrashDumpScreen + 14 * SCRN_VX_B +vCrashDumpScreenRow14 = vCrashDumpScreen + 15 * SCRN_VX_B +vCrashDumpScreenRow15 = vCrashDumpScreen + 16 * SCRN_VX_B +vCrashDumpScreenRow16 = vCrashDumpScreen + 17 * SCRN_VX_B +vCrashDumpScreenRow17 = vCrashDumpScreen + 18 * SCRN_VX_B diff --git a/gbdk/gbdk-lib/libc/targets/sm83/ap/crt0.s b/gbdk/gbdk-lib/libc/targets/sm83/ap/crt0.s new file mode 100644 index 00000000..4553105d --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/ap/crt0.s @@ -0,0 +1,529 @@ + .include "global.s" + + ;; **************************************** + ;; Beginning of module + ;; BANKED: checked + .title "Runtime" + .module Runtime + .area _HEADER (ABS) + + ;; RST vectors +; .org 0x00 ; Trap, utilized by crash_handler.h + +; .org 0x08 ; --profile handler utilized by emu_debug.h + +; .org 0x10 ; empty + +; .org 0x18 ; empty + + .org 0x20 ; RST 0x20 == call HL +.call_hl:: + JP (HL) + + .org 0x28 ; zero up to 256 bytes in C pointed by HL +.MemsetSmall:: + LD (HL+),A + DEC C + JR NZ,.MemsetSmall + ret + + .org 0x30 ; copy up to 256 bytes in C from DE to HL +.MemcpySmall:: + LD A, (DE) + LD (HL+), A + INC DE + DEC C + JR NZ,.MemcpySmall + RET + +; .org 0x38 ; crash handler utilized by crash_handler.h + + ;; Hardware interrupt vectors + .org 0x40 ; VBL +.int_VBL: + PUSH AF + PUSH HL + LD HL,#.int_0x40 + JP .int + +; .org 0x48 ; LCD + +; .org 0x50 ; TIM + +; .org 0x58 ; SIO + +; .org 0x60 ; JOY + +; .org 0x70 + ;; space for drawing.s bit table + + .org 0x80 +.int:: + PUSH BC + PUSH DE +1$: + LD A,(HL+) + OR (HL) + JR Z,.int_tail + PUSH HL + LD A,(HL-) + LD L,(HL) + LD H,A + RST 0x20 ; .call_hl + POP HL + INC HL + JR 1$ +_wait_int_handler:: + ADD SP,#4 +.int_tail: + POP DE + POP BC + POP HL + + ;; we return at least at the beginning of mode 2 + WAIT_STAT + + POP AF + RETI + + ;; VBlank default interrupt routine +__standard_VBL_handler:: +.std_vbl: + LD HL,#.sys_time + INC (HL) + JR NZ,2$ + INC HL + INC (HL) +2$: + CALL .refresh_OAM + + LD A, #1 + LDH (.vbl_done),A + RET + +_refresh_OAM:: + WAIT_STAT + LD A, #>_shadow_OAM + JP .refresh_OAM + (.refresh_OAM_DMA - .start_refresh_OAM) + +.clear_WRAM: + PUSH DE + XOR A + LD BC, #l__DATA + LD HL, #s__DATA + CALL .memset_simple + + LD A, #>_shadow_OAM + LDH (__shadow_OAM_base), A + LD H, A + XOR A + LD L, A + LD C, #(40 << 2) ; 40 entries 4 bytes each + RST 0x28 + POP DE + RET + + ;; GameBoy Header + + ;; DO NOT CHANGE... + .org 0x100 +.header: + JR .code_start + + ;; Nintendo logo + .org 0x104 + .byte 0x01,0x10,0xCE,0xEF,0x00,0x00,0x44,0xAA + .byte 0x00,0x74,0x00,0x18,0x11,0x95,0x00,0x34 + .byte 0x00,0x1A,0x00,0xD5,0x00,0x22,0x00,0x69 + .byte 0x6F,0xF6,0xF7,0x73,0x09,0x90,0xE1,0x10 + .byte 0x44,0x40,0x9A,0x90,0xD5,0xD0,0x44,0x30 + .byte 0xA9,0x21,0x5D,0x48,0x22,0xE0,0xF8,0x60 + + ;; Title of the game + .org 0x134 + .asciz "Title" + + .org 0x144 + .byte 0,0,0 + + ;; Cartridge type is ROM only + .org 0x147 + .byte 0 + + ;; ROM size is 32kB + .org 0x148 + .byte 0 + + ;; RAM size is 0kB + .org 0x149 + .byte 0 + + ;; Maker ID + .org 0x14A + .byte 0x00,0x00 + + ;; Version number + .org 0x14C + .byte 0x01 + + ;; Complement check + .org 0x14D + .byte 0x00 + + ;; Checksum + .org 0x14E + .byte 0x00,0x00 + + ;; **************************************** + .org 0x150 + + ;; soft reset: falldown to .code_start +.reset:: +_reset:: + LD A, (__is_GBA) + LD B, A + LD A, (__cpu) + + ;; Initialization code +.code_start:: + DI ; Disable interrupts + LD D, A ; Store CPU type in D + LD E, B + ;; Initialize the stack + LD SP, #.STACK + + CALL .clear_WRAM + +; LD (.mode),A ; Clearing (.mode) is performed when clearing RAM + + ;; Store CPU type + LD A, D + LD (__cpu), A + CP #.CGB_TYPE + JR NZ, 1$ + XOR A + SRL E + RLA + LD (__is_GBA), A +1$: + + ;; Turn the screen off + CALL .display_off + + XOR A + ;; Initialize the display + LDH (.SCY),A + LDH (.SCX),A + LDH (.STAT),A + LDH (.WY),A + LD A,#0x07 + LDH (.WX),A + + ;; Copy refresh_OAM routine to HRAM + LD DE,#.start_refresh_OAM ; source + LD HL,#.refresh_OAM ; dest + LD C,#(.end_refresh_OAM - .start_refresh_OAM) ; size + RST 0x30 ; call .MemcpySmall + + ;; Clear the OAM by calling refresh_OAM + CALL .refresh_OAM + + ;; Install interrupt routines + LD BC,#.std_vbl + CALL .add_VBL + + ;; Standard color palettes + LD A,#0b11100100 ; Grey 3 = 11 (Black) + ; Grey 2 = 10 (Dark grey) + ; Grey 1 = 01 (Light grey) + ; Grey 0 = 00 (Transparent) + LDH (.BGP),A + LDH (.OBP0),A + LD A,#0b00011011 + LDH (.OBP1),A + + ;; Turn the screen on + LD A,#(LCDCF_ON | LCDCF_WIN9C00 | LCDCF_WINOFF | LCDCF_BG8800 | LCDCF_BG9800 | LCDCF_OBJ8 | LCDCF_OBJOFF | LCDCF_BGOFF) + LDH (.LCDC),A + XOR A + LDH (.IF),A + LD A,#.VBL_IFLAG ; switch on VBlank interrupt only + LDH (.IE),A + + LDH (__current_bank),A ; current bank is 1 at startup + + XOR A + + LD HL,#.sys_time + LD (HL+),A + LD (HL),A + + LDH (.NR52),A ; Turn sound off + + CALL gsinit + + EI ; Enable interrupts + + ;; Call the main function + CALL _main +_exit:: +99$: + HALT + NOP + JR 99$ ; Wait forever + +_set_interrupts:: + DI + LDA HL,2(SP) ; Skip return address + XOR A + LDH (.IF),A ; Clear pending interrupts + LD A,(HL) + EI ; Enable interrupts + LDH (.IE),A ; interrupts are still disabled here + RET + + ;; Copy OAM data to OAM RAM +.start_refresh_OAM: + LDH A,(__shadow_OAM_base) + OR A + RET Z +.refresh_OAM_DMA: + LDH (.DMA),A ; Put A into DMA registers + LD A,#0x28 ; We need to wait 160 ns +1$: + DEC A + JR NZ,1$ + RET +.end_refresh_OAM: + + .org .MODE_TABLE + ;; Jump table for modes + RET + + ;; **************************************** + + ;; Ordering of segments for the linker + ;; Code that really needs to be in bank 0 + .area _HOME + ;; Similar to _HOME + .area _BASE + ;; Code + .area _CODE + ;; #pragma bank 0 workaround + .area _CODE_0 + ;; Constant data + .area _LIT +; ;; since _CODE_1 area base address is pre-defined in the linker from 0x4000, +; ;; that moves initializer code and tables out of bank 0 +; .area _CODE_1 + ;; Constant data, used to init _DATA + .area _INITIALIZER + ;; Code, used to init _DATA + .area _GSINIT + .area _GSFINAL + ;; Uninitialised ram data + .area _DATA + .area _BSS + ;; Initialised in ram data + .area _INITIALIZED + ;; For malloc + .area _HEAP + .area _HEAP_END + + .area _DATA +__cpu:: + .ds 0x01 ; GB type (GB, PGB, CGB) +__is_GBA:: + .ds 0x01 ; detect GBA +.mode:: + .ds 0x01 ; Current mode +.sys_time:: +_sys_time:: + .ds 0x02 ; System time in VBL units +.int_0x40:: + .blkw 0x0A ; 4 interrupt handlers (built-in + user-defined) + + .area _HRAM (ABS) + + .org 0xFF90 +__current_bank:: ; Current bank + .ds 0x01 +.vbl_done: + .ds 0x01 ; Is VBL interrupt finished? +__shadow_OAM_base:: + .ds 0x01 + + ;; Runtime library + .area _GSINIT +gsinit:: + ;; initialize static storage variables + LD BC, #l__INITIALIZER + LD HL, #s__INITIALIZER + LD DE, #s__INITIALIZED + call .memcpy_simple + + .area _GSFINAL + ret + + .area _HOME + + ;; fills memory at HL of length BC with A, clobbers DE +.memset_simple:: + LD E, A + LD A, B + OR C + RET Z + LD (HL), E + DEC BC + LD D, H + LD E, L + INC DE + + ;; copies BC bytes from HL into DE +.memcpy_simple:: + LD A, B + OR C + RET Z + + SRL B + RR C + JR NC,3$ + LD A, (HL+) + LD (DE), A + INC DE +3$: + INC B + INC C + JR 2$ +1$: + LD A, (HL+) + LD (DE), A + INC DE + LD A, (HL+) + LD (DE), A + INC DE +2$: + DEC C + JR NZ,1$ + DEC B + JR NZ,1$ +4$: + RET + + ;; Remove interrupt routine in BC from the VBL interrupt list + ;; falldown to .remove_int +.remove_VBL:: + LD HL,#.int_0x40 + + ;; Remove interrupt BC from interrupt list HL if it exists + ;; Abort if a 0000 is found (end of list) +.remove_int:: +1$: + LD A,(HL+) + LD E,A + LD D,(HL) + INC HL + OR D + RET Z ; No interrupt found + + LD A,E + CP C + JR NZ,1$ + LD A,D + CP B + JR NZ,1$ + + LD D,H + LD E,L + DEC DE + DEC DE + + ;; Now do a memcpy from here until the end of the list +2$: + LD A,(HL+) + LD (DE),A + LD B,A + INC DE + LD A,(HL+) + LD (DE),A + INC DE + OR B + RET Z + JR 2$ + + ;; Add interrupt routine in BC to the VBL interrupt list + ;; falldown to .add_int +.add_VBL:: + LD HL,#.int_0x40 + + ;; Add interrupt routine in BC to the interrupt list in HL +.add_int:: +1$: + LD A,(HL+) + OR (HL) + JR Z,2$ + INC HL + JR 1$ +2$: + LD A,B + LD (HL-),A + LD (HL),C + RET + + ;; Wait for VBL interrupt to be finished +.wait_vbl_done:: +_wait_vbl_done:: + ;; Check if the screen is on + LDH A,(.LCDC) + AND #LCDCF_ON + RET Z ; Return if screen is off + XOR A + LDH (.vbl_done),A ; Clear any previous sets of vbl_done +1$: + HALT ; Wait for any interrupt + NOP ; HALT sometimes skips the next instruction + LDH A,(.vbl_done) ; Was it a VBlank interrupt? + ;; Warning: we may lose a VBlank interrupt, if it occurs now + OR A + JR Z,1$ ; No: back to sleep! + RET + +.display_off:: +_display_off:: + ;; Check if the screen is on + LDH A,(.LCDC) + AND #LCDCF_ON + RET Z ; Return if screen is off +1$: ; We wait for the *NEXT* VBL + LDH A,(.LY) + CP #0x92 ; Smaller than or equal to 0x91? + JR NC,1$ ; Loop until smaller than or equal to 0x91 +2$: + LDH A,(.LY) + CP #0x91 ; Bigger than 0x90? + JR C,2$ ; Loop until bigger than 0x90 + + LDH A,(.LCDC) + AND #~LCDCF_ON + LDH (.LCDC),A ; Turn off screen + RET + +_remove_VBL:: + PUSH BC + LDA HL,4(SP) ; Skip return address and registers + LD A,(HL+) + LD C,A + LD B,(HL) + CALL .remove_VBL + POP BC + RET + +_add_VBL:: + PUSH BC + LDA HL, 4(SP) ; Skip return address and registers + LD A,(HL+) + LD C,A + LD B,(HL) + CALL .add_VBL + POP BC + RET diff --git a/gbdk/gbdk-lib/libc/targets/sm83/ap/global.s b/gbdk/gbdk-lib/libc/targets/sm83/ap/global.s new file mode 100644 index 00000000..19d10ae3 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/ap/global.s @@ -0,0 +1,533 @@ + .NEAR_CALLS = 1 ; <near_calls> - tag so that sed can change this + + _VRAM = 0x8000 ; $8000->$9FFF + _VRAM8000 = 0x8000 + _VRAM8800 = 0x8800 + _VRAM9000 = 0x9000 + _SCRN0 = 0x9800 ; $9800->$9BFF + _SCRN1 = 0x9C00 ; $9C00->$9FFF + _SRAM = 0xA000 ; $A000->$BFFF + _RAM = 0xC000 ; $C000->$CFFF / $C000->$DFFF + _RAMBANK = 0xD000 ; $D000->$DFFF + _OAMRAM = 0xFE00 ; $FE00->$FE9F + _IO = 0xFF00 ; $FF00->$FF7F,$FFFF + _AUD3WAVERAM = 0xFF30 ; $FF30->$FF3F + _HRAM = 0xFF80 ; $FF80->$FFFE + + ;; MBC Equates + + .MBC1_ROM_PAGE = 0x2000 ; Address to write to for MBC1 switching + .MBC_ROM_PAGE = 0x2000 ; Default platform MBC rom switching address + + rRAMG = 0x0000 ; $0000->$1fff + rROMB0 = 0x2000 ; $2000->$2fff + rROMB1 = 0x3000 ; $3000->$3fff - If more than 256 ROM banks are present. + rRAMB = 0x4000 ; $4000->$5fff - Bit 3 enables rumble (if present) + + ;; Keypad + .START = 0x80 + .SELECT = 0x40 + .B = 0x20 + .A = 0x10 + .DOWN = 0x08 + .UP = 0x04 + .LEFT = 0x02 + .RIGHT = 0x01 + + .P14 = 0x10 + .P15 = 0x20 + + ;; Screen dimensions + .MAXCURSPOSX = 0x13 ; In tiles + .MAXCURSPOSY = 0x11 + + .SCREENWIDTH = 0xA0 + .SCREENHEIGHT = 0x90 + .MINWNDPOSX = 0x07 + .MINWNDPOSY = 0x00 + .MAXWNDPOSX = 0xA6 + .MAXWNDPOSY = 0x8F + + ;; Hardware registers + + .P1 = 0x00 ; Joystick: 1.1.P15.P14.P13.P12.P11.P10 + rP1 = 0xFF00 + + P1F_5 = 0b00100000 ; P15 out port, set to 0 to get buttons + P1F_4 = 0b00010000 ; P14 out port, set to 0 to get dpad + P1F_3 = 0b00001000 ; P13 in port + P1F_2 = 0b00000100 ; P12 in port + P1F_1 = 0b00000010 ; P11 in port + P1F_0 = 0b00000001 ; P10 in port + + P1F_GET_DPAD = 0b00100000 + P1F_GET_BTN = 0b00010000 + P1F_GET_NONE = 0b00110000 + + .SB = 0x01 ; Serial IO data buffer + rSB = 0xFF01 + + .SC = 0x02 ; Serial IO control register + rSC = 0xFF02 + + .DIV = 0x04 ; Divider register + rDIV = 0xFF04 + + .TIMA = 0x05 ; Timer counter + rTIMA = 0xFF05 + + .TMA = 0x06 ; Timer modulo + rTMA = 0xFF06 + + .TAC = 0x07 ; Timer control + rTAC = 0xFF07 + + TACF_START = 0b00000100 + TACF_STOP = 0b00000000 + TACF_4KHZ = 0b00000000 + TACF_16KHZ = 0b00000011 + TACF_65KHZ = 0b00000010 + TACF_262KHZ = 0b00000001 + + .IF = 0x0F ; Interrupt flags: 0.0.0.JST.SIO.TIM.LCD.VBL + rIF = 0xFF0F + + .NR10 = 0x10 ; Sound register + rNR10 = 0xFF10 + rAUD1SWEEP = 0xFF10 + + AUD1SWEEP_UP = 0b00000000 + AUD1SWEEP_DOWN = 0b00001000 + + .NR11 = 0x11 ; Sound register + rNR11 = 0xFF11 + rAUD1LEN = 0xFF11 + + .NR12 = 0x12 ; Sound register + rNR12 = 0xFF12 + rAUD1ENV = 0xFF12 + + .NR13 = 0x13 ; Sound register + rNR13 = 0xFF13 + rAUD1LOW = 0xFF13 + + .NR14 = 0x14 ; Sound register + rNR14 = 0xFF14 + rAUD1HIGH = 0xFF14 + + .NR21 = 0x16 ; Sound register + rNR21 = 0xFF16 + rAUD2LEN = 0xFF16 + + .NR22 = 0x17 ; Sound register + rNR22 = 0xFF17 + rAUD2ENV = 0xFF17 + + .NR23 = 0x18 ; Sound register + rNR23 = 0xFF18 + rAUD2LOW = 0xFF18 + + .NR24 = 0x19 ; Sound register + rNR24 = 0xFF19 + rAUD2HIGH = 0xFF19 + + .NR30 = 0x1A ; Sound register + rNR30 = 0xFF1A + rAUD3ENA = 0xFF1A + + .NR31 = 0x1B ; Sound register + rNR31 = 0xFF1B + rAUD3LEN = 0xFF1B + + .NR32 = 0x1C ; Sound register + rNR32 = 0xFF1C + rAUD3LEVEL = 0xFF1C + + .NR33 = 0x1D ; Sound register + rNR33 = 0xFF1D + rAUD3LOW = 0xFF1D + + .NR34 = 0x1E ; Sound register + rNR34 = 0xFF1E + rAUD3HIGH = 0xFF1E + + .NR41 = 0x20 ; Sound register + rNR41 = 0xFF20 + rAUD4LEN = 0xFF20 + + .NR42 = 0x21 ; Sound register + rNR42 = 0xFF21 + rAUD4ENV = 0xFF21 + + .NR43 = 0x22 ; Sound register + rNR43 = 0xFF22 + rAUD4POLY = 0xFF22 + + .NR44 = 0x23 ; Sound register + rNR44 = 0xFF23 + rAUD4GO = 0xFF23 + + .NR50 = 0x24 ; Sound register + rNR50 = 0xFF24 + rAUDVOL = 0xFF24 + + AUDVOL_VIN_LEFT = 0b10000000 ; SO2 + AUDVOL_VIN_RIGHT = 0b00001000 ; SO1 + + .NR51 = 0x25 ; Sound register + rNR51 = 0xFF25 + rAUDTERM = 0xFF25 + + AUDTERM_4_LEFT = 0b10000000 + AUDTERM_3_LEFT = 0b01000000 + AUDTERM_2_LEFT = 0b00100000 + AUDTERM_1_LEFT = 0b00010000 + AUDTERM_4_RIGHT = 0b00001000 + AUDTERM_3_RIGHT = 0b00000100 + AUDTERM_2_RIGHT = 0b00000010 + AUDTERM_1_RIGHT = 0b00000001 + + .NR52 = 0x26 ; Sound register + rNR52 = 0xFF26 + rAUDENA = 0xFF26 + + AUDENA_ON = 0b10000000 + AUDENA_OFF = 0b00000000 ; sets all audio regs to 0! + + .LCDC = 0x4E ; LCD control + rLCDC = 0xFF4E + + LCDCF_OFF = 0b00000000 ; LCD Control Operation + LCDCF_ON = 0b00000001 ; LCD Control Operation + LCDCF_WIN9800 = 0b00000000 ; Window Tile Map Display Select + LCDCF_WIN9C00 = 0b00000010 ; Window Tile Map Display Select + LCDCF_WINOFF = 0b00000000 ; Window Display + LCDCF_WINON = 0b00000100 ; Window Display + LCDCF_BG8800 = 0b00000000 ; BG & Window Tile Data Select + LCDCF_BG8000 = 0b00001000 ; BG & Window Tile Data Select + LCDCF_BG9800 = 0b00000000 ; BG Tile Map Display Select + LCDCF_BG9C00 = 0b00010000 ; BG Tile Map Display Select + LCDCF_OBJ8 = 0b00000000 ; OBJ Construction + LCDCF_OBJ16 = 0b00100000 ; OBJ Construction + LCDCF_OBJOFF = 0b00000000 ; OBJ Display + LCDCF_OBJON = 0b01000000 ; OBJ Display + LCDCF_BGOFF = 0b00000000 ; BG Display + LCDCF_BGON = 0b10000000 ; BG Display + LCDCF_B_ON = 0 + LCDCF_B_WIN9C00 = 1 + LCDCF_B_WINON = 2 + LCDCF_B_BG8000 = 3 + LCDCF_B_BG9C00 = 4 + LCDCF_B_OBJ16 = 5 + LCDCF_B_OBJON = 6 + LCDCF_B_BGON = 7 + + .STAT = 0x41 ; LCD status + rSTAT = 0xFF41 + + STATF_LYC = 0b00000010 ; LYC=LY Coincidence (Selectable) + STATF_MODE10 = 0b00000100 ; Mode 10 + STATF_MODE01 = 0b00001000 ; Mode 01 (V-Blank) + STATF_MODE00 = 0b00010000 ; Mode 00 (H-Blank) + STATF_LYCF = 0b00100000 ; Coincidence Flag + STATF_HBL = 0b00000000 ; H-Blank + STATF_VBL = 0b10000000 ; V-Blank + STATF_OAM = 0b01000000 ; OAM-RAM is used by system + STATF_LCD = 0b11000000 ; Both OAM and VRAM used by system + STATF_BUSY = 0b01000000 ; When set, VRAM access is unsafe + STATF_B_LYC = 1 + STATF_B_MODE10 = 2 + STATF_B_MODE01 = 3 + STATF_B_MODE00 = 4 + STATF_B_LYCF = 5 + STATF_B_VBL = 7 + STATF_B_OAM = 6 + STATF_B_BUSY = 6 + + .SCY = 0x42 ; Scroll Y + rSCY = 0xFF42 + + .SCX = 0x43 ; Scroll X + rSCX = 0xFF43 + + .LY = 0x44 ; LCDC Y-coordinate + rLY = 0xFF44 + + .LYC = 0x45 ; LY compare + rLYC = 0xFF45 + + .DMA = 0x46 ; DMA transfer + rDMA = 0xFF46 + + .BGP = 0x47 ; BG palette data + rBGP = 0xFF47 + + .OBP0 = 0x48 ; OBJ palette 0 data + rOBP0 = 0xFF48 + + .OBP1 = 0x49 ; OBJ palette 1 data + rOBP1 = 0xFF49 + + .WY = 0x4A ; Window Y coordinate + rWY = 0xFF4A + + .WX = 0x4B ; Window X coordinate + rWX = 0xFF4B + + .KEY1 = 0x4D ; CPU speed + rKEY1 = 0xFF4D + rSPD = 0xFF4D + + KEY1F_DBLSPEED = 0b10000000 ; 0=Normal Speed, 1=Double Speed (R) + KEY1F_PREPARE = 0b00000001 ; 0=No, 1=Prepare (R/W) + + .VBK = 0x4F ; VRAM bank + rVBK = 0xFF4F + + .HDMA1 = 0x51 ; DMA control 1 + rHDMA1 = 0xFF51 + + .HDMA2 = 0x52 ; DMA control 2 + rHDMA2 = 0xFF52 + + .HDMA3 = 0x53 ; DMA control 3 + rHDMA3 = 0xFF53 + + .HDMA4 = 0x54 ; DMA control 4 + rHDMA4 = 0xFF54 + + .HDMA5 = 0x55 ; DMA control 5 + rHDMA5 = 0xFF55 + + HDMA5F_MODE_GP = 0b00000000 ; General Purpose DMA (W) + HDMA5F_MODE_HBL = 0b10000000 ; HBlank DMA (W) + + HDMA5F_BUSY = 0b10000000 ; 0=Busy (DMA still in progress), 1=Transfer complete (R) + + .RP = 0x56 ; IR port + rRP = 0xFF56 + + RPF_ENREAD = 0b11000000 + RPF_DATAIN = 0b00000010 ; 0=Receiving IR Signal, 1=Normal + RPF_WRITE_HI = 0b00000001 + RPF_WRITE_LO = 0b00000000 + + .BCPS = 0x68 ; BG color palette specification + rBCPS = 0xFF68 + + BCPSF_AUTOINC = 0b10000000 ; Auto Increment (0=Disabled, 1=Increment after Writing) + + .BCPD = 0x69 ; BG color palette data + rBCPD = 0xFF69 + + .OCPS = 0x6A ; OBJ color palette specification + rOCPS = 0xFF6A + + OCPSF_AUTOINC = 0b10000000 ; Auto Increment (0=Disabled, 1=Increment after Writing) + + .OCPD = 0x6B ; OBJ color palette data + rOCPD = 0xFF6B + + .SVBK = 0x70 ; WRAM bank + rSVBK = 0xFF70 + rSMBK = 0xFF70 + + rPCM12 = 0xFF76 + + rPCM34 = 0xFF77 + + .IE = 0xFF ; Interrupt enable + rIE = 0xFFFF + + .VBL_IFLAG = 0x01 + .LCD_IFLAG = 0x02 + .TIM_IFLAG = 0x04 + .SIO_IFLAG = 0x08 + .JOY_IFLAG = 0x10 + + IEF_HILO = 0b00010000 ; Transition from High to Low of Pin number P10-P13 + IEF_SERIAL = 0b00001000 ; Serial I/O transfer end + IEF_TIMER = 0b00000100 ; Timer Overflow + IEF_STAT = 0b00000010 ; STAT + IEF_VBLANK = 0b00000001 ; V-Blank + + ;; Flags common to multiple sound channels + + AUDLEN_DUTY_12_5 = 0b00000000 ; 12.5% + AUDLEN_DUTY_25 = 0b01000000 ; 25% + AUDLEN_DUTY_50 = 0b10000000 ; 50% + AUDLEN_DUTY_75 = 0b11000000 ; 75% + + AUDENV_UP = 0b00001000 + AUDENV_DOWN = 0b00000000 + + AUDHIGH_RESTART = 0b10000000 + AUDHIGH_LENGTH_ON = 0b01000000 + AUDHIGH_LENGTH_OFF = 0b00000000 + + ;; OAM related constants + + OAM_COUNT = 40 ; number of OAM entries in OAM RAM + + OAMF_PRI = 0b10000000 ; Priority + OAMF_YFLIP = 0b01000000 ; Y flip + OAMF_XFLIP = 0b00100000 ; X flip + OAMF_PAL0 = 0b00000000 ; Palette number; 0,1 (DMG) + OAMF_PAL1 = 0b00010000 ; Palette number; 0,1 (DMG) + OAMF_BANK0 = 0b00000000 ; Bank number; 0,1 (GBC) + OAMF_BANK1 = 0b00001000 ; Bank number; 0,1 (GBC) + + OAMF_PALMASK = 0b00000111 ; Palette (GBC) + + OAMB_PRI = 7 ; Priority + OAMB_YFLIP = 6 ; Y flip + OAMB_XFLIP = 5 ; X flip + OAMB_PAL1 = 4 ; Palette number; 0,1 (DMG) + OAMB_BANK1 = 3 ; Bank number; 0,1 (GBC) + + ;; SGB packets + .PAL_01 = 0x00 + .PAL_23 = 0x01 + .PAL_03 = 0x02 + .PAL_12 = 0x03 + .ATTR_BLK = 0x04 + .ATTR_LIN = 0x05 + .ATTR_DIV = 0x06 + .ATTR_CHR = 0x07 + .SOUND = 0x08 + .SOU_TRN = 0x09 + .PAL_SET = 0x0A + .PAL_TRN = 0x0B + .ATRC_EN = 0x0C + .TEST_EN = 0x0D + .ICON_EN = 0x0E + .DATA_SND = 0x0F + .DATA_TRN = 0x10 + .MLT_REQ = 0x11 + .JUMP = 0x12 + .CHR_TRN = 0x13 + .PCT_TRN = 0x14 + .ATTR_TRN = 0x15 + .ATTR_SET = 0x16 + .MASK_EN = 0x17 + .OBJ_TRN = 0x18 + + ;; CPU detection + .DMG_TYPE = 0x01 ; Original GB or Super GB + .MGB_TYPE = 0xFF ; Pocket GB or Super GB 2 + .CGB_TYPE = 0x11 ; Color GB + + ;; GBDK library screen modes + + .G_MODE = 0x01 ; Graphic mode + .T_MODE = 0x02 ; Text mode (bit 2) + .T_MODE_OUT = 0x02 ; Text mode output only + .T_MODE_INOUT = 0x03 ; Text mode with input + .M_NO_SCROLL = 0x04 ; Disables scrolling of the screen in text mode + .M_NO_INTERP = 0x08 ; Disables special character interpretation + + ;; Status codes for IO + .IO_IDLE = 0x00 + .IO_SENDING = 0x01 + .IO_RECEIVING = 0x02 + .IO_ERROR = 0x04 + + ;; Type of IO data + .DT_IDLE = 0x66 + .DT_RECEIVING = 0x55 + + ;; Table of routines for modes + .MODE_TABLE = 0x01E0 + + ;; C related + ;; Overheap of a banked call. Used for parameters + ;; = ret + real ret + bank + + .if .NEAR_CALLS + .BANKOV = 2 + + .else + .BANKOV = 6 + + .endif + + .globl __current_bank + .globl __shadow_OAM_base + + ;; Global variables + .globl .mode + + .globl __cpu + .globl __is_GBA + + ;; Global routines +; .globl .set_mode ;; don't link mode.o by default + + .globl .reset + + .globl .display_off + + .globl .wait_vbl_done + + ;; Interrupt routines + .globl .add_VBL +; .globl .add_LCD ;; don't link LCD.o by default +; .globl .add_TIM ;; don't link TIM.o by default +; .globl .add_SIO ;; don't link serial.o by default +; .globl .add_JOY ;; don't link JOY.o by default + + ;; Symbols defined at link time + .globl .STACK + .globl _shadow_OAM + .globl .refresh_OAM + + ;; Main user routine + .globl _main + + ;; Macro definitions + +.macro WAIT_STAT ?lbl +lbl: LDH A, (.STAT) + AND #STATF_BUSY ; Check if in LCD modes 0 or 1 + JR NZ, lbl +.endm + +.macro ADD_A_REG16 regH regL + ADD regL + LD regL, A + ADC regH + SUB regL + LD regH, A +.endm + +.macro SIGNED_ADD_A_REG16 regH regL ?lbl + ; If A is negative, we need to subtract 1 from upper byte of 16-bit value + BIT 7, A ; set z if a signed bit is 0 + JR Z, lbl ; if z is set jump to positive + dec regH ; if negative decrement upper byte +lbl: + ADD_A_REG16 regH, regL +.endm + +.macro SIGNED_SUB_A_REG16 regH regL ?lbl + ; negate A then add to 16-bit value + CPL + INC A + SIGNED_ADD_A_REG16 regH, regL +.endm + +.macro MUL_DE_BY_A_RET_HL ?lbl1 ?lbl2 ?lbl3 + ; Multiply DE by A, return result in HL; preserves: BC + LD HL, #0 +lbl1: + SRL A + JR NC, lbl2 + ADD HL, DE +lbl2: + JR Z, lbl3 + SLA E + RL D + JR lbl1 +lbl3: +.endm + diff --git a/gbdk/gbdk-lib/libc/targets/sm83/ap/sfr.s b/gbdk/gbdk-lib/libc/targets/sm83/ap/sfr.s new file mode 100644 index 00000000..98585886 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/ap/sfr.s @@ -0,0 +1,111 @@ +__VRAM = 0x8000 +__VRAM8000 = 0x8000 +__VRAM8800 = 0x8800 +__VRAM9000 = 0x9000 +__SCRN0 = 0x9800 +__SCRN1 = 0x9C00 +__SRAM = 0xA000 +__RAM = 0xC000 +__RAMBANK = 0xD000 +__OAMRAM = 0xFE00 +__IO = 0xFF00 +__AUD3WAVERAM = 0xFF30 +__HRAM = 0xFF80 + +.globl __VRAM, __VRAM8000, __VRAM8800, __VRAM9000, __SCRN0, __SCRN1, __SRAM, __RAM, __RAMBANK, __OAMRAM, __IO, __AUD3WAVERAM, __HRAM + +_rRAMG = 0x0000 +_rROMB0 = 0x2000 +_rROMB1 = 0x3000 +_rRAMB = 0x4000 + +.globl _rRAMG, _rROMB0, _rROMB1, _rRAMB + +_P1_REG = 0xFF00 ; Joystick: 1.1.P15.P14.P13.P12.P11.P10 +_SB_REG = 0xFF01 ; Serial IO data buffer +_SC_REG = 0xFF02 ; Serial IO control register +_DIV_REG = 0xFF04 ; Divider register +_TIMA_REG = 0xFF05 ; Timer counter +_TMA_REG = 0xFF06 ; Timer modulo +_TAC_REG = 0xFF07 ; Timer control +_IF_REG = 0xFF0F ; Interrupt flags: 0.0.0.JOY.SIO.TIM.LCD.VBL +_NR10_REG = 0xFF10 ; Sound register +_NR11_REG = 0xFF11 ; Sound register +_NR12_REG = 0xFF12 ; Sound register +_NR13_REG = 0xFF13 ; Sound register +_NR14_REG = 0xFF14 ; Sound register +_NR21_REG = 0xFF16 ; Sound register +_NR22_REG = 0xFF17 ; Sound register +_NR23_REG = 0xFF18 ; Sound register +_NR24_REG = 0xFF19 ; Sound register +_NR30_REG = 0xFF1A ; Sound register +_NR31_REG = 0xFF1B ; Sound register +_NR32_REG = 0xFF1C ; Sound register +_NR33_REG = 0xFF1D ; Sound register +_NR34_REG = 0xFF1E ; Sound register +_NR41_REG = 0xFF20 ; Sound register +_NR42_REG = 0xFF21 ; Sound register +_NR43_REG = 0xFF22 ; Sound register +_NR44_REG = 0xFF23 ; Sound register +_NR50_REG = 0xFF24 ; Sound register +_NR51_REG = 0xFF25 ; Sound register +_NR52_REG = 0xFF26 ; Sound register +_PCM_SAMPLE = 0xFF30 ; PCM wave pattern +_AUD3WAVE = 0xFF30 ; PCM wave pattern +_LCDC_REG = 0xFF4E ; LCD control +_STAT_REG = 0xFF41 ; LCD status +_SCY_REG = 0xFF42 ; Scroll Y +_SCX_REG = 0xFF43 ; Scroll X +_LY_REG = 0xFF44 ; LCDC Y-coordinate +_LYC_REG = 0xFF45 ; LY compare +_DMA_REG = 0xFF46 ; DMA transfer +_BGP_REG = 0xFF47 ; BG palette data +_OBP0_REG = 0xFF48 ; OBJ palette 0 data +_OBP1_REG = 0xFF49 ; OBJ palette 1 data +_WY_REG = 0xFF4A ; Window Y coordinate +_WX_REG = 0xFF4B ; Window X coordinate +_KEY1_REG = 0xFF4D ; CPU speed +_VBK_REG = 0xFF4F ; VRAM bank +_HDMA1_REG = 0xFF51 ; DMA control 1 +_HDMA2_REG = 0xFF52 ; DMA control 2 +_HDMA3_REG = 0xFF53 ; DMA control 3 +_HDMA4_REG = 0xFF54 ; DMA control 4 +_HDMA5_REG = 0xFF55 ; DMA control 5 +_RP_REG = 0xFF56 ; IR port +_BCPS_REG = 0xFF68 ; BG color palette specification +_BCPD_REG = 0xFF69 ; BG color palette data +_OCPS_REG = 0xFF6A ; OBJ color palette specification +_OCPD_REG = 0xFF6B ; OBJ color palette data +_SVBK_REG = 0xFF70 ; WRAM bank +_PCM12_REG = 0xFF76 ; Sound channel 1&2 PCM amplitude (R) +_PCM34_REG = 0xFF77 ; Sound channel 3&4 PCM amplitude (R) +_IE_REG = 0xFFFF ; Interrupt enable + +.globl _P1_REG +.globl _SB_REG, _SC_REG +.globl _DIV_REG +.globl _TIMA_REG, _TMA_REG, _TAC_REG +.globl _IF_REG +.globl _NR10_REG, _NR11_REG, _NR12_REG, _NR13_REG, _NR14_REG +.globl _NR21_REG, _NR22_REG, _NR23_REG, _NR24_REG +.globl _NR30_REG, _NR31_REG, _NR32_REG, _NR33_REG, _NR34_REG +.globl _NR41_REG, _NR42_REG, _NR43_REG, _NR44_REG +.globl _NR50_REG, _NR51_REG, _NR52_REG +.globl _PCM_SAMPLE, _AUD3WAVE +.globl _LCDC_REG +.globl _STAT_REG +.globl _SCY_REG, _SCX_REG +.globl _LY_REG, _LYC_REG +.globl _DMA_REG +.globl _BGP_REG +.globl _OBP0_REG, _OBP1_REG +.globl _WY_REG, _WX_REG +.globl _KEY1_REG +.globl _VBK_REG +.globl _HDMA1_REG, _HDMA2_REG, _HDMA3_REG, _HDMA4_REG, _HDMA5_REG +.globl _RP_REG +.globl _BCPS_REG, _BCPD_REG +.globl _OCPS_REG, _OCPD_REG +.globl _SVBK_REG +.globl _PCM12_REG, _PCM34_REG +.globl _IE_REG
\ No newline at end of file diff --git a/gbdk/gbdk-lib/libc/targets/sm83/cgb.s b/gbdk/gbdk-lib/libc/targets/sm83/cgb.s new file mode 100644 index 00000000..790097b7 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/cgb.s @@ -0,0 +1,37 @@ + .include "global.s" + + .title "CGB support" + .module CGB + + .area _CODE +_cpu_slow:: ; Banked + LDH A,(.KEY1) + AND #0x80 ; Is GBC in double speed mode? + RET Z ; No, already in single speed + +.shift_speed: + LDH A,(.IE) + PUSH AF + + XOR A ; A = 0 + LDH (.IE),A ; Disable interrupts + LDH (.IF),A + + LD A,#0x30 + LDH (.P1),A + + LD A,#0x01 + LDH (.KEY1),A + + STOP + + POP AF + LDH (.IE),A + + RET + +_cpu_fast:: ; Banked + LDH A,(.KEY1) + AND #0x80 ; Is GBC in double speed mode? + RET NZ ; Yes, exit + JR .shift_speed diff --git a/gbdk/gbdk-lib/libc/targets/sm83/cgb_compat.s b/gbdk/gbdk-lib/libc/targets/sm83/cgb_compat.s new file mode 100644 index 00000000..11313d11 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/cgb_compat.s @@ -0,0 +1,21 @@ + .include "global.s" + + .title "CGB support" + .module CGB + + .globl _set_sprite_palette, _set_bkg_palette + + .area _CODE + +_cgb_compatibility:: +_set_default_palette:: + LD HL, #1$ + PUSH HL + LD HL, #0x0100 + PUSH HL + CALL _set_sprite_palette + CALL _set_bkg_palette + ADD SP, #4 + RET +1$: + .DW 0xFF7F, 0x56B5, 0x294A, 0x0000 diff --git a/gbdk/gbdk-lib/libc/targets/sm83/cgb_palettes.s b/gbdk/gbdk-lib/libc/targets/sm83/cgb_palettes.s new file mode 100644 index 00000000..830d218b --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/cgb_palettes.s @@ -0,0 +1,78 @@ + .include "global.s" + + .title "CGB support" + .module CGB + + .area _CODE + +_set_sprite_palette:: ; Non-banked + PUSH BC + LD C,#.OCPS + JR .set_palette + +_set_bkg_palette:: ; Non-banked + PUSH BC + LD C,#.BCPS + +.set_palette:: + LDA HL,4(SP) ; Skip return address and registers + LD A,(HL+) ; first_palette + ADD A ; A *= 8 + ADD A + ADD A + OR #0x80 ; Set auto-increment + LDH (C),A + INC C + LD A,(HL+) ; D = nb_palettes + ADD A ; A *= 8 + ADD A + ADD A + LD B,A ; Number of bytes + LD A,(HL+) ; rgb_data + LD H,(HL) + LD L,A +1$: + WAIT_STAT + + LD A,(HL+) + LDH (C),A + DEC B + JR NZ,1$ + + POP BC + RET + +_set_sprite_palette_entry:: ; Banked + PUSH BC + LD C,#.OCPS + JR .set_palette_entry + +_set_bkg_palette_entry:: ; Banked + PUSH BC + LD C,#.BCPS + +.set_palette_entry:: + LDA HL,4(SP); Skip return address and registers + LD A,(HL+) ; first_palette + ADD A ; A *= 4 + ADD A + LD B,A + LD A,(HL+) ; pal_entry + ADD B ; A += first_palette * 4 + ADD A ; A *= 2 + OR #0x80 ; Set auto-increment + LDH (C),A + INC C + LD A,(HL+) ; rgb_data + LD H,(HL) + LD L,A + + WAIT_STAT + + LD A,L + LDH (C),A + LD A,H + LDH (C),A + + POP BC + RET diff --git a/gbdk/gbdk-lib/libc/targets/sm83/clock.s b/gbdk/gbdk-lib/libc/targets/sm83/clock.s new file mode 100644 index 00000000..f8d9aad5 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/clock.s @@ -0,0 +1,16 @@ + .include "global.s" + + .title "System clock" + .module Clock + + ;; BANKED: checked + .area _HOME + +_clock:: + LD HL,#.sys_time + DI + LD A,(HL+) + EI ;; Interrupts are disabled for the next instruction... + LD D,(HL) + LD E,A + RET diff --git a/gbdk/gbdk-lib/libc/targets/sm83/color.s b/gbdk/gbdk-lib/libc/targets/sm83/color.s new file mode 100644 index 00000000..632a76ed --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/color.s @@ -0,0 +1,32 @@ + .include "global.s" + + ;; Data + .area _INITIALIZED +__current_1bpp_colors:: + ;; Foreground drawing colour +.fg_colour:: + .ds 1 + ;; Background drawing colour +.bg_colour:: + .ds 1 + ;; Drawing mode (.SOILD etc) +.draw_mode:: + .ds 1 + + .area _INITIALIZER + + .db 0x03 ; .fg_colour + .db 0x00 ; .bg_color + .db 0x00 ; .draw_mode + + .area _HOME +_set_1bpp_colors_ex:: +_color:: + LDA HL,2(SP) ; Skip return address and registers + LD A,(HL+) ; A = Foreground + LD (.fg_colour),a + LD A,(HL+) + LD (.bg_colour),a + LD A,(HL) + LD (.draw_mode),a + RET diff --git a/gbdk/gbdk-lib/libc/targets/sm83/cpy_data.s b/gbdk/gbdk-lib/libc/targets/sm83/cpy_data.s new file mode 100644 index 00000000..a709ece8 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/cpy_data.s @@ -0,0 +1,44 @@ + .include "global.s" + + .area _HOME + + ;; Copy part (size = DE) of the VRAM from (BC) to (HL) +.copy_vram:: + INC D + INC E + JR 2$ +1$: + WAIT_STAT + + LD A,(BC) + LD (HL+),A + INC BC +2$: + DEC E + JR NZ, 1$ + DEC D + JR NZ, 1$ + RET + +_vmemcpy:: +_set_data:: +_get_data:: + PUSH BC + + LDA HL,9(SP) ; Skip return address and registers + LD A,(HL-) ; DE = len + LD D, A + LD A,(HL-) + LD E, A + LD A,(HL-) ; BC = src + LD B, A + LD A,(HL-) + LD C, A + LD A,(HL-) ; HL = dst + LD L,(HL) + LD H,A + + CALL .copy_vram + + POP BC + RET diff --git a/gbdk/gbdk-lib/libc/targets/sm83/crlf.c b/gbdk/gbdk-lib/libc/targets/sm83/crlf.c new file mode 100644 index 00000000..aca6ec82 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/crlf.c @@ -0,0 +1 @@ +const char * const __crlf = "\n";
\ No newline at end of file diff --git a/gbdk/gbdk-lib/libc/targets/sm83/delay.s b/gbdk/gbdk-lib/libc/targets/sm83/delay.s new file mode 100644 index 00000000..19c862fb --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/delay.s @@ -0,0 +1,73 @@ + .include "global.s" + + .area _HOME + + ;; Delay DE milliseconds + ;; + ;; Entry conditions + ;; DE = number of milliseconds to delay (1 to 65536, 0 = 65536) + ;; + ;; Register used: AF, DE + .CPMS = 4194/4 ; 4.194304 MHz + +_delay:: + LDA HL,2(SP) ; Skip return address + LD E,(HL) ; DE = delay + INC HL + LD D,(HL) + +.delay:: ; 6 cycles for the CALL + PUSH BC ; 4 cycles + CALL .dly ; 12 cycles to return from .dly (6+1+5) + LD B,#.CPMS/20-2 ; 2 cycles + ; ========= + ; 24 cycles +.ldlp: + PUSH BC ; 4 cycles + POP BC ; 3 cycles + PUSH BC ; 4 cycles + POP BC ; 3 cycles + NOP ; 1 cycles +5$: DEC B ; 1 cycles + JP NZ,.ldlp ; 3 cycles (if TRUE: 4 cycles) + NOP ; 1 cycles + ; ========= + ; 20 cycles + ;; Exit in 16 cycles + POP BC ; 3 cycles + PUSH BC ; 4 cycles + POP BC ; 3 cycles + NOP ; 1 cycles + NOP ; 1 cycles + RET ; 4 cycles + ; ========= + ; 16 cycles + + ;; Delay all but last millisecond +.dly: + DEC DE ; 2 cycles + LD A,E ; 1 cycles + OR D ; 1 cycles + RET Z ; 2 cycles (upon return: 5 cycles) + LD B,#.CPMS/20-1 ; 2 cycles + ; ========= + ; 8 cycles +.dlp: + PUSH BC ; 4 cycles + POP BC ; 3 cycles + PUSH BC ; 4 cycles + POP BC ; 3 cycles + NOP ; 1 cycles + DEC B ; 1 cycles + JP NZ,.dlp ; 3 cycles (if TRUE: 4 cycles) + NOP ; 1 cycles + ; ========= + ; 20 cycles + ;; Exit in 15 cycles + PUSH BC ; 4 cycles + POP BC ; 3 cycles + NOP ; 1 cycles + NOP ; 1 cycles + JR .dly ; 3 cycles + ; ========= + ; 12 cycles diff --git a/gbdk/gbdk-lib/libc/targets/sm83/digits.c b/gbdk/gbdk-lib/libc/targets/sm83/digits.c new file mode 100644 index 00000000..4668f154 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/digits.c @@ -0,0 +1 @@ +const char * const digits = "0123456789ABCDEF"; diff --git a/gbdk/gbdk-lib/libc/targets/sm83/drawing.s b/gbdk/gbdk-lib/libc/targets/sm83/drawing.s new file mode 100644 index 00000000..cc774806 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/drawing.s @@ -0,0 +1,1767 @@ +;; Optimised Drawing library +;; By Jon Fuge (jonny@q-continuum.demon.co.uk) based on original file +;; Updates +;; 990223 Michael Removed mod_col, splitting it up into +;; fg_colour, bg_colour, and draw_mode +;; Note: some optimisations are available with unneded PUSH DE/POP DE's + + .include "global.s" + + .globl .init_vram + .globl .copy_vram + + .globl .drawing_lcd, .drawing_vbl + .globl .bg_colour, .fg_colour, .draw_mode + + .M_SOLID = 0x00 + .M_OR = 0x01 + .M_XOR = 0x02 + .M_AND = 0x03 + + ;; Format of mod_col + ;; 7 6 5 4 3 2 1 0 + ;; mode fg bg + + .area _DRAW_HEADER (ABS) + + .org 0x70 +.drawing_bits_tbl:: + .byte 0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01 + .byte 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80 + + .org .MODE_TABLE+4*.G_MODE + JP .gmode + + .module Drawing1 + + .area _DATA + + ;; Fill style +.style: + .ds 0x01 + ;; Various varibles +.x_s: + .ds 2 +.y_s: + .ds 2 +.delta_x: + .ds 1 +.delta_y: + .ds 1 +.l_inc: + .ds 1 +.l_d: + .ds 2 +.dinc1: + .ds 2 +.dinc2: + .ds 2 +.tx: + .ds 1 +.ty: + .ds 1 + + .area _HOME + + ;; Enter graphic mode +.gmode:: + DI ; Disable interrupts + + ;; Turn the screen off + LDH A,(.LCDC) + AND #LCDCF_ON + JR Z,1$ + + ;; Turn the screen off + CALL .display_off +1$: + LD HL,#0x8000+0x10*0x10 + LD DE,#0x1800-0x18*0x10 + LD B,#0x00 + CALL .init_vram ; Init the charset at 0x8000 + + ;; Install interrupt routines + LD BC,#.drawing_vbl + CALL .add_VBL + LD BC,#.drawing_lcd + CALL .add_LCD + + LD A,#72 ; Set line at which LCD interrupt occurs + LDH (.LYC),A + + LD A,#STATF_LYC + LDH (.STAT),A + + LDH A,(.IE) + OR #.LCD_IFLAG ; Enable LCD interrupt + LDH (.IE),A + + ;; (9*20) = 180 tiles are used in the upper part of the screen + ;; (9*20) = 180 tiles are used in the lower part of the screen + ;; => We have 24 tiles free + ;; We keep 16 at 0x8000->0x80FF, and 8 at 0x9780->97FF + + LD HL,#0x9800 + LD A,#0x10 ; Keep 16 tiles free + LD BC,#12 ; 12 unused columns + LD E,#18 ; 18 lines +2$: + LD D,#20 ; 20 used columns +3$: + LD (HL+),A + INC A + DEC D + JR NZ,3$ + ADD HL,BC + DEC E + JR NZ,2$ + + ;; Turn the screen on + LDH A,(.LCDC) + OR #(LCDCF_ON | LCDCF_BG8000 | LCDCF_BGON) + AND #~LCDCF_BG9C00 ; BG Bank = 0x9800 + LDH (.LCDC),A + + LD A,#.G_MODE + LD (.mode),A + + ;; Setup the default colours and draw modes + LD A,#.M_SOLID + LD (.draw_mode),A + LD A,#0x03 ; Black + LD (.fg_colour),A + LD A,#0x00 ; White + LD (.bg_colour),A + + EI ; Enable interrupts + + RET + + ;; Draw a full-screen image at (BC) +.draw_image:: + LD HL,#0x8000+0x10*0x10 + LD DE,#0x1680 + CALL .copy_vram ; Move the charset + RET + + ;; Replace tile data at (B,C) with data at DE and store old value at HL +.switch_data:: + PUSH DE ; Save src + PUSH HL ; Save dst + LD L,B + SLA L + SLA L + SLA L + LD H,#0x00 + ADD HL,HL + LD D,H + LD E,L + + LD HL,#.y_table + SLA C + SLA C + SLA C + LD B,#0x00 + ADD HL,BC + ADD HL,BC + LD A,(HL+) + LD H,(HL) + LD L,A + ADD HL,DE + + LD B,H ; BC = src + LD C,L + POP HL ; HL = dst + PUSH BC ; Save dst + LD A,H + OR L + JR Z,1$ + LD DE,#0x10 + CALL .copy_vram +1$: + POP HL ; HL = dst + POP BC ; BC = src + LD A,B + OR C + JR Z,2$ + LD DE,#0x10 + CALL .copy_vram +2$: + RET + + ;; Advance the cursor +.adv_gcurs:: + PUSH HL + LD HL,#.tx ; X coordinate + LD A,#.MAXCURSPOSX + CP (HL) + JR Z,1$ + INC (HL) + JR 99$ +1$: + LD (HL),#0x00 + LD HL,#.ty ; Y coordinate + LD A,#.MAXCURSPOSY + CP (HL) + JR Z,2$ + INC (HL) + JR 99$ +2$: + LD (HL),#0x00 +99$: + POP HL + RET + + ;; Draw a circle from (B,C) with radius D +.circle:: + LD A,B ;Store center values + LD (.x_s),A + LD A,C + LD (.y_s),A + + XOR A + LD (.x_s+1),A + LD A,D + LD (.y_s+1),A + CPL + LD L,A + LD H,#0xFF + INC HL + LD BC,#0 + ADD HL,BC + LD A,L + LD (.l_d+1),A + LD A,H + LD (.l_d),A + +cloop$: + LD A,(.x_s+1) + LD B,A + LD A,(.y_s+1) + SUB B + RET C + + LD A,(.style) + OR A + CALL Z,.circplot + + LD A,(.l_d) + BIT 7,A + JR Z,ycirc$ + + LD A,(.style) + OR A + CALL NZ,.horlin + LD A,(.x_s+1) + INC A + LD (.x_s+1),A + LD A,(.l_d) + LD B,A + LD A,(.l_d+1) + LD C,A + LD H,#0 + LD A,(.x_s+1) + LD L,A + ADD HL,HL + ADD HL,HL + ADD HL,BC + LD BC,#6 + ADD HL,BC + LD A,H + LD (.l_d),A + LD A,L + LD (.l_d+1),A + JR cloop$ +ycirc$: + LD A,(.style) + OR A + CALL NZ,.verlin + LD A,(.x_s+1) + INC A + LD (.x_s+1),A + LD B,#0 + LD A,(.x_s+1) + LD C,A + LD H,#0xFF + LD A,(.y_s+1) + CPL + LD L,A + INC HL + ADD HL,BC + LD A,(.l_d) + LD B,A + LD A,(.l_d+1) + LD C,A + ADD HL,HL + ADD HL,HL + ADD HL,BC + LD BC,#10 + ADD HL,BC + LD A,H + LD (.l_d),A + LD A,L + LD (.l_d+1),A + LD A,(.y_s+1) + DEC A + LD (.y_s+1),A + JP cloop$ + +.horlin:: + LD A,(.x_s) + LD B,A + LD A,(.y_s) + LD C,A + LD A,(.x_s+1) + LD D,A + LD A,(.y_s+1) + LD E,A + PUSH BC + PUSH DE + LD A,B + SUB E + LD H,A + LD A,B + ADD E + LD B,A + LD A,C + ADD D + LD C,A + LD D,H + LD E,C + CALL .line + POP DE + POP BC + LD A,D + OR A + RET Z + PUSH BC + PUSH DE + LD A,B + SUB E + LD H,A + LD A,B + ADD E + LD B,A + LD A,C + SUB D + LD C,A + LD D,H + LD E,C + CALL .line + POP DE + POP BC + RET + +.verlin:: + LD A,(.x_s) + LD B,A + LD A,(.y_s) + LD C,A + LD A,(.x_s+1) + LD D,A + LD A,(.y_s+1) + LD E,A + PUSH BC + PUSH DE + LD A,B + SUB E + LD H,A + LD A,B + ADD E + LD B,A + LD A,C + ADD D + LD C,A + LD D,H + LD E,C + CALL .line + POP DE + POP BC + PUSH BC + PUSH DE + LD A,B + SUB E + LD H,A + LD A,B + ADD E + LD B,A + LD A,C + SUB D + LD C,A + LD D,H + LD E,C + CALL .line + POP DE + POP BC + LD A,D + SUB E + RET Z + PUSH BC + PUSH DE + LD A,B + SUB D + LD H,A + LD A,B + ADD D + LD B,A + LD A,C + SUB E + LD C,A + LD D,H + LD E,C + CALL .line + POP DE + POP BC + PUSH BC + PUSH DE + LD A,B + SUB D + LD H,A + LD A,B + ADD D + LD B,A + LD A,C + ADD E + LD C,A + LD D,H + LD E,C + CALL .line + POP DE + POP BC + RET + +.circplot:: + LD A,(.x_s) + LD B,A + LD A,(.y_s) + LD C,A + LD A,(.x_s+1) + LD D,A + LD A,(.y_s+1) + LD E,A + PUSH BC + PUSH DE + LD A,B + ADD D + LD B,A + LD A,C + SUB E + LD C,A + CALL .plot + POP DE + POP BC + PUSH BC + PUSH DE + LD A,B + SUB E + LD B,A + LD A,C + SUB D + LD C,A + CALL .plot + POP DE + POP BC + PUSH BC + PUSH DE + LD A,B + SUB D + LD B,A + LD A,C + ADD E + LD C,A + CALL .plot + POP DE + POP BC + PUSH BC + PUSH DE + LD A,B + ADD E + LD B,A + LD A,C + ADD D + LD C,A + CALL .plot + POP DE + POP BC + + LD A,D + OR A + RET Z + SUB E + RET Z + + PUSH BC + PUSH DE + LD A,B + SUB D + LD B,A + LD A,C + SUB E + LD C,A + CALL .plot + POP DE + POP BC + PUSH BC + PUSH DE + LD A,B + SUB E + LD B,A + LD A,C + ADD D + LD C,A + CALL .plot + POP DE + POP BC + PUSH BC + PUSH DE + LD A,B + ADD D + LD B,A + LD A,C + ADD E + LD C,A + CALL .plot + POP DE + POP BC + PUSH BC + PUSH DE + LD A,B + ADD E + LD B,A + LD A,C + SUB D + LD C,A + CALL .plot + POP DE + POP BC + RET + + ;; Draw a box between (B,C) and (D,E) +.box:: + LD A,(.x_s) + LD B,A + LD A,(.x_s+1) + LD C,A + SUB B + JR NC,ychk$ + LD A,C + LD (.x_s),A + LD A,B + LD (.x_s+1),A +ychk$: + LD A,(.y_s) + LD B,A + LD A,(.y_s+1) + LD C,A + SUB B + JR NC,dbox$ + LD A,C + LD (.y_s),A + LD A,B + LD (.y_s+1),A +dbox$: + LD A,(.x_s) + LD B,A + LD D,A + LD A,(.y_s) + LD C,A + LD A,(.y_s+1) + LD E,A + CALL .line + LD A,(.x_s+1) + LD B,A + LD D,A + LD A,(.y_s) + LD C,A + LD A,(.y_s+1) + LD E,A + CALL .line + LD A,(.x_s) + INC A + LD (.x_s),A + LD A,(.x_s+1) + DEC A + LD (.x_s+1),A + LD A,(.x_s) + LD B,A + LD A,(.x_s+1) + LD D,A + LD A,(.y_s) + LD C,A + LD E,A + CALL .line + LD A,(.x_s) + LD B,A + LD A,(.x_s+1) + LD D,A + LD A,(.y_s+1) + LD C,A + LD E,A + CALL .line + LD A,(.style) + OR A + RET Z + LD A,(.x_s) + LD B,A + LD A,(.x_s+1) + SUB B + RET C + LD A,(.y_s) + INC A + LD (.y_s),A + LD A,(.y_s+1) + DEC A + LD (.y_s+1),A + LD A,(.y_s) + LD B,A + LD A,(.y_s+1) + SUB B + RET C + + .if 0 + LD A,(.mod_col) ;Swap fore + back colours. + LD D,A + AND #0xF0 + LD C,A ;Preserve Style + LD A,D + AND #0x0C + RRCA + RRCA + OR C ;Foreground->background + style + LD C,A + LD A,D + AND #0x03 + RLCA + RLCA + OR C + LD (.mod_col),A + .else + LD A,(.fg_colour) + LD C,A + LD A,(.bg_colour) + LD (.fg_colour),A + LD A,C + LD (.bg_colour),A + .endif +filllp$: + LD A,(.x_s) + LD B,A + LD A,(.x_s+1) + LD D,A + LD A,(.y_s) + LD C,A + LD E,A + CALL .line + LD A,(.y_s+1) + LD B,A + LD A,(.y_s) + CP B + JR Z,swap$ + INC A + LD (.y_s),A + JR filllp$ +swap$: + .if 0 + LD A,(.mod_col) ;Swap fore + back colours. + LD D,A + AND #0xF0 + LD C,A ;Preserve Style + LD A,D + AND #0x0C + RRCA + RRCA + OR C ;Foreground->background + style + LD C,A + LD A,D + AND #0x03 + RLCA + RLCA + OR C + LD (.mod_col),A + .else + LD A,(.fg_colour) + LD C,A + LD A,(.bg_colour) + LD (.fg_colour),A + LD A,C + LD (.bg_colour),A + .endif + RET + + ;; Draw a line between (B,C) and (D,E) +.line:: + LD A,C ;Calculate Delta Y + SUB E + JR NC,s1$ + CPL + INC A + +s1$: LD (.delta_y),A + LD H,A + + LD A,B ;Calculate Delta X + SUB D + JR NC,s2$ + CPL + INC A + +s2$: LD (.delta_x),A + + SUB H + JP C,y1 + + ;; Use Delta X + + LD A,B + SUB D + JP NC,x2$ + + LD A,C + SUB E + JR Z,x3$ + LD A,#0x00 + JR NC,x3$ + LD A,#0xFF + JR x3$ + +x2$: + LD A,E + SUB C + JR Z,x2a$ + LD A,#0x00 + JR NC,x2a$ + LD A,#0xFF + +x2a$: + LD B,D + LD C,E ;BC holds start X,Y +x3$: + LD (.l_inc),A ;Store Y increment + LD HL,#.y_table + LD D,#0x00 + LD E,C + ADD HL,DE + ADD HL,DE + LD A,(HL+) + LD H,(HL) + LD L,A + + LD A,B + AND #0xf8 + LD E,A + ADD HL,DE + ADD HL,DE + + LD A,(.delta_y) + OR A + JP Z,.xonly + + ;; Got to do it the hard way. + + ; Calculate (2*deltay) -> dinc1 + + PUSH HL + LD H,#0x00 + LD L,A + ADD HL,HL + LD A,H + LD (.dinc1),A + LD A,L + LD (.dinc1+1),A + + ; Calculate (2*deltay)-deltax -> d + + + LD D,H + LD E,L + LD A,(.delta_x) + CPL + LD L,A + LD H,#0xFF + INC HL +dx1$: + ADD HL,DE + LD A,H + LD (.l_d),A + LD A,L + LD (.l_d+1),A + + ; Calculate (deltay-deltax)*2 -> dinc2 + + LD A,(.delta_x) + CPL + LD L,A + LD H,#0xFF + INC HL + LD A,(.delta_y) + LD D,#0x00 + LD E,A + ADD HL,DE + ADD HL,HL + + LD A,H + LD (.dinc2),A + LD A,L + LD (.dinc2+1),A + + POP HL + + .if 0 + LD A,(.mod_col) + LD D,A + .endif + + LD A,(.delta_x) + LD E,A + + LD A,B + AND #7 + ADD #<.drawing_bits_tbl ; Table of bits is located at 0x0070 + LD C,A + LD B,#0x00 + LD A,(BC) ; Get start bit + LD B,A + LD C,A + +xloop$: + RRC C + LD A,(.l_d) + BIT 7,A + JR Z,ychg$ + PUSH DE + BIT 7,C + JR Z,nbit$ + LD A,B + CPL + LD C,A + CALL .wrbyte + DEC HL + LD C,#0x80 + LD B,C +nbit$: + LD A,(.l_d+1) + LD D,A + LD A,(.dinc1+1) + ADD D + LD (.l_d+1),A + LD A,(.l_d) + LD D,A + LD A,(.dinc1) + ADC D + LD (.l_d),A + POP DE + JR nchg$ +ychg$: + PUSH DE + PUSH BC + LD A,B + CPL + LD C,A + CALL .wrbyte + LD A,(.l_inc) + OR A + JR Z,ydown$ + INC HL + LD A,L + AND #0x0F + JR NZ,bound$ + LD DE,#0x0130 + ADD HL,DE ;Correct screen address + JR bound$ +ydown$: + DEC HL + DEC HL + DEC HL + LD A,L + AND #0x0F + XOR #0x0E + JR NZ,bound$ + LD DE,#0xFED0 + ADD HL,DE ;Correct screen address +bound$: + LD A,(.l_d+1) + LD D,A + LD A,(.dinc2+1) + ADD D + LD (.l_d+1),A + LD A,(.l_d) + LD D,A + LD A,(.dinc2) + ADC D + LD (.l_d),A + POP BC + LD B,C + POP DE +nchg$: + BIT 7,C + JR Z,nadj$ + PUSH DE + LD DE,#0x0010 + ADD HL,DE ;Correct screen address + POP DE + LD B,C +nadj$: + LD A,B + OR C + LD B,A + DEC E + JP NZ,xloop$ + LD A,B + CPL + LD C,A + JP .wrbyte + +.xonly:: + ;; Draw accelerated horizontal line + .if 0 + ;; xxx needed? + LD A,(.mod_col) + LD D,A + .endif + + LD A,(.delta_x) + LD E,A + INC E + + LD A,B ;check X + AND #7 ;just look at bottom 3 bits + JR Z,2$ + PUSH HL + ADD #<.drawing_bits_tbl ;Table of bits is located at 0x0070 + LD L,A + LD H,#0x00 + LD C,(HL) + POP HL + XOR A ;Clear A +1$: RRCA ;Shift data right 1 + OR C + DEC E + JR Z,3$ + BIT 0,A + JR Z,1$ + JR 3$ +2$: + LD A,E + DEC A + AND #0xF8 + JR Z,4$ + JR 8$ +3$: + LD B,A + CPL + LD C,A + PUSH DE + CALL .wrbyte + LD DE,#0x0F + ADD HL,DE ;Correct screen address + POP DE + +8$: LD A,E + OR A + RET Z + AND #0xF8 + JR Z,4$ + + XOR A + LD C,A + CPL + LD B,A + + PUSH DE + CALL .wrbyte + LD DE,#0x0F + ADD HL,DE ;Correct screen address + POP DE + LD A,E + SUB #8 + RET Z + LD E,A + JR 8$ + +4$: LD A,#0x80 +5$: DEC E + JR Z,6$ + SRA A + JR 5$ +6$: LD B,A + CPL + LD C,A + JP .wrbyte + + ;; Use Delta Y +y1: + LD A,C + SUB E + JP NC,y2$ + + LD A,B + SUB D + JR Z,y3$ + LD A,#0x00 + JR NC,y3$ + LD A,#0xFF + JR y3$ + +y2$: + LD A,C + SUB E + JR Z,y2a$ + LD A,#0x00 + +; JR NC,y2a$ ; old code; fix draw to up-left below +; LD A,#0xFF + + LD L,A ; invert delta if x1 less than x2 + LD A,B + SUB D + LD A,L + JR C,y2a$ + CPL + +y2a$: + LD B,D + LD C,E ;BC holds start X,Y + +y3$: + LD (.l_inc),A ;Store X increment + LD HL,#.y_table + LD D,#0x00 + LD E,C + ADD HL,DE + ADD HL,DE + LD A,(HL+) + LD H,(HL) + LD L,A + + LD A,B + AND #0xf8 + LD E,A + ADD HL,DE + ADD HL,DE + + .if 0 + ;; Trashed by later instructions + LD A,(.mod_col) + LD D,A + .endif + + LD A,(.delta_y) + LD E,A + INC E + + LD A,(.delta_x) + OR A + JP Z,.yonly + + ;; Got to do it the hard way. + + ; Calculate (2*deltax) -> dinc1 + + PUSH HL + LD H,#0x00 + LD L,A + ADD HL,HL + LD A,H + LD (.dinc1),A + LD A,L + LD (.dinc1+1),A + + ; Calculate (2*deltax)-deltay -> d + + + LD D,H + LD E,L + LD A,(.delta_y) + CPL + LD L,A + LD H,#0xFF + INC HL +dy1$: + ADD HL,DE + LD A,H + LD (.l_d),A + LD A,L + LD (.l_d+1),A + + ; Calculate (deltax-deltay)*2 -> dinc2 + + LD A,(.delta_y) + CPL + LD L,A + LD H,#0xFF + INC HL + LD A,(.delta_x) + LD D,#0x00 + LD E,A + ADD HL,DE + ADD HL,HL + + LD A,H + LD (.dinc2),A + LD A,L + LD (.dinc2+1),A + + POP HL + + .if 0 + ;; xxx Not used? + LD A,(.mod_col) + LD D,A + .endif + + LD A,(.delta_y) + LD E,A + + LD A,B + AND #7 + ADD #<.drawing_bits_tbl ; Table of bits is located at 0x0070 + LD C,A + LD B,#0x00 + LD A,(BC) ; Get start bit + LD B,A + LD C,A + +yloop$: + PUSH DE + PUSH BC + LD A,B + CPL + LD C,A + CALL .wrbyte + INC HL + LD A,L + AND #0x0F + JR NZ,nybound$ + LD DE,#0x0130 + ADD HL,DE ;Correct screen address +nybound$: + POP BC + LD A,(.l_d) + BIT 7,A + JR Z,xchg$ + LD A,(.l_d+1) + LD D,A + LD A,(.dinc1+1) + ADD D + LD (.l_d+1),A + LD A,(.l_d) + LD D,A + LD A,(.dinc1) + ADC D + LD (.l_d),A + JR nchgy$ +xchg$: + LD A,(.l_inc) + OR A + JR NZ,yright$ + RLC B + BIT 0,B + JR Z,boundy$ + LD DE,#0xFFF0 + ADD HL,DE ;Correct screen address + JR boundy$ +yright$: + RRC B + BIT 7,B + JR Z,boundy$ + LD DE,#0x0010 + ADD HL,DE ;Correct screen address +boundy$: + LD A,(.l_d+1) + LD D,A + LD A,(.dinc2+1) + ADD D + LD (.l_d+1),A + LD A,(.l_d) + LD D,A + LD A,(.dinc2) + ADC D + LD (.l_d),A +nchgy$: + POP DE + DEC E + JR NZ,yloop$ + LD A,B + CPL + LD C,A + JP .wrbyte + +.yonly:: + ;; Draw accelerated vertical line + LD A,B ;check X + AND #7 ;just look at bottom 3 bits + PUSH HL + ADD #<.drawing_bits_tbl ;Table of bits is located at 0x0070 + LD L,A + LD H,#0x00 + LD A,(HL) ;Get mask bit + POP HL + LD B,A + CPL + LD C,A + +1$: PUSH DE + CALL .wrbyte + INC HL ;Correct screen address + LD A,L + AND #0x0F + JR NZ,2$ + LD DE,#0x0130 + ADD HL,DE +2$: POP DE + DEC E + RET Z + JR 1$ + + ;; Draw a point at (B,C) with mode and color D +.plot:: + + LD HL,#.y_table + LD D,#0x00 + LD E,C + ADD HL,DE + ADD HL,DE + LD A,(HL+) + LD H,(HL) + LD L,A + + LD A,B + AND #0xf8 + LD E,A + ADD HL,DE + ADD HL,DE + + LD A,B + + AND #7 + ADD #<.drawing_bits_tbl ; Table of bits is located at 0x0070 + LD C,A + LD B,#0x00 + LD A,(BC) + LD B,A + CPL + LD C,A + +.wrbyte:: + .if 0 + LD A,(.mod_col) ; Restore color and mode + LD D,A + + BIT 5,D + JR NZ,10$ + BIT 6,D + JR NZ,20$ + BIT 7,D + JR NZ,30$ + .else + LD A,(.fg_colour) + LD D,A + LD A,(.draw_mode) + CP #.M_OR + JR Z,10$ + CP #.M_XOR + JR Z,20$ + CP #.M_AND + JR Z,30$ + .endif + + ; Fall through to SOLID by default +1$: + ;; Solid + LD E,B + .if 0 + BIT 2,D + .else + BIT 0,D + .endif + JR NZ,2$ + PUSH BC + LD B,#0x00 +2$: + .if 0 + BIT 3,D + .else + BIT 1,D + .endif + JR NZ,3$ + LD E,#0x00 +3$: + WAIT_STAT + + LD A,(HL) + AND C + OR B + LD (HL+),A + + LD A,(HL) + AND C + OR E + LD (HL),A + LD A,B + OR A + RET NZ + POP BC + RET + +10$: + ;; Or + LD C,B + .if 0 + BIT 2,D + .else + BIT 0,D + .endif + JR NZ,11$ + LD B,#0x00 +11$: + .if 0 + BIT 3,D + .else + BIT 1,D + .endif + JR NZ,12$ + LD C,#0x00 +12$: + WAIT_STAT + + LD A,(HL) + OR B + LD (HL+),A + + LD A,(HL) + OR C + LD (HL),A + RET + +20$: + ;; Xor + LD C,B + .if 0 + BIT 2,D + .else + BIT 0,D + .endif + JR NZ,21$ + LD B,#0x00 +21$: + .if 0 + BIT 3,D + .else + BIT 1,D + .endif + JR NZ,22$ + LD C,#0x00 +22$: + WAIT_STAT + + LD A,(HL) + XOR B + LD (HL+),A + + LD A,(HL) + XOR C + LD (HL),A + RET + +30$: + ;; And + LD B,C + .if 0 + BIT 2,D + .else + BIT 0,D + .endif + JR Z,31$ + LD B,#0xFF +31$: + .if 0 + BIT 3,D + .else + BIT 1,D + .endif + JR Z,32$ + LD C,#0xFF +32$: + WAIT_STAT + + LD A,(HL) + AND B + LD (HL+),A + + LD A,(HL) + AND C + LD (HL),A + RET + + ;; Get color of pixel at point (B,C) returns in A +.getpix:: + LD HL,#.y_table + LD D,#0x00 + LD E,C + ADD HL,DE + ADD HL,DE + LD A,(HL+) + LD H,(HL) + LD L,A + + LD A,B + AND #0xf8 + LD E,A + ADD HL,DE + ADD HL,DE + + LD A,B + + AND #7 + ADD #<.drawing_bits_tbl ; Table of bits is located at 0x0070 + LD C,A + LD B,#0x00 + LD A,(BC) + LD C,A + + WAIT_STAT + + LD A,(HL+) + LD D,A + LD A,(HL+) + LD E,A + LD B,#0 + LD A,D + AND C + JR Z,1$ + SET 0,B +1$: LD A,E + AND C + JR Z,2$ + SET 1,B +2$: LD E,B + RET + + ;; Write character C +.wrtchr:: + LD HL,#.y_table + LD D,#0x00 + LD A,(.ty) + RLCA + RLCA + RLCA + LD E,A + ADD HL,DE + ADD HL,DE + LD A,(HL+) + LD B, A + LD H,(HL) + LD L,B + + LD A,(.tx) + RLCA + RLCA + RLCA + LD E,A + ADD HL,DE + ADD HL,DE + + LD A,C + LD B,H + LD C,L + + LD H,D + LD L,A + ADD HL,HL + ADD HL,HL + ADD HL,HL + + .if 0 + LD DE,#.tp1 + .else + .globl _font_ibm_fixed_tiles + + LD DE,#_font_ibm_fixed_tiles + .endif + + ADD HL,DE + + LD D,H + LD E,L + LD H,B + LD L,C + + .if 0 + LD A,(.mod_col) + LD C,A + .else + LD A,(.fg_colour) + LD C,A + .endif +1$: + LD A,(DE) + INC DE + PUSH DE + + .if 1 + PUSH HL + LD HL,#.bg_colour + LD L,(HL) + .endif + + LD B,A + XOR A + .if 0 + BIT 0,C + .else + BIT 0,L + .endif + JR Z,2$ + CPL +2$: OR B + .if 0 + BIT 2,C + .else + BIT 0,C + .endif + JR NZ,3$ + XOR B +3$: LD D,A + XOR A + .if 0 + BIT 1,C + .else + BIT 1,L + .endif + JR Z,4$ + CPL +4$: OR B + .if 0 + BIT 3,C + .else + BIT 1,C + .endif + JR NZ,5$ + XOR B +5$: + LD E,A + .if 1 + POP HL + .endif + + WAIT_STAT + + LD A,D + LD (HL+),A + LD A,E + LD (HL+),A + POP DE + LD A,L + AND #0x0F + JR NZ,1$ + RET + +_gotogxy:: + LDA HL,2(SP) ; Skip return address + LD A,(HL+) ; A = x + LD (.tx),A + LD A,(HL+) ; A = y + LD (.ty),A + + RET + +_wrtchr:: + PUSH BC + + LD A,(.mode) + CP #.G_MODE + CALL NZ,.gmode + + LDA HL,4(SP) ; Skip return address and registers + LD A,(HL) + LD C,A ; C = Char to print + + CALL .wrtchr + CALL .adv_gcurs + + POP BC + RET + +_getpix:: + PUSH BC + + LDA HL,4(SP) ; Skip return address and registers + LD A,(HL+) ; B = x + LD B,A + LD A,(HL+) ; C = y + LD C,A + + CALL .getpix + + POP BC + RET + +_circle:: + PUSH BC + + LD A,(.mode) + CP #.G_MODE + CALL NZ,.gmode + + LDA HL,4(SP) ; Skip return address and registers + LD A,(HL+) ; B = x + LD B,A + LD A,(HL+) ; C = y + LD C,A + LD A,(HL+) ; D = Radius + LD D,A + LD A,(HL) + LD (.style),A + + CALL .circle + + POP BC + RET + +_box:: + PUSH BC + + LD A,(.mode) + CP #.G_MODE + CALL NZ,.gmode + + LDA HL,4(SP) ; Skip return address and registers + LD A,(HL+) ; B = x1 + LD (.x_s),A + LD A,(HL+) ; C = y1 + LD (.y_s),A + LD A,(HL+) ; D = x2 + LD (.x_s+1),A + LD A,(HL+) ; E = y2 + LD (.y_s+1),A + LD A,(HL) + LD (.style),A + CALL .box + POP BC + RET + +_line:: + PUSH BC + + LD A,(.mode) + CP #.G_MODE + CALL NZ,.gmode + + LDA HL,4(SP) ; Skip return address and registers + LD A,(HL+) ; B = x1 + LD B,A + LD A,(HL+) ; C = y1 + LD C,A + LD A,(HL+) ; D = x2 + LD D,A + LD A,(HL+) ; E = y2 + LD E,A + + CALL .line + + POP BC + RET + +_plot_point:: + PUSH BC + + LD A,(.mode) + CP #.G_MODE + CALL NZ,.gmode + + LDA HL,4(SP) ; Skip return address and registers + LD A,(HL+) ; B = x + LD B,A + LD A,(HL+) ; C = y + LD C,A + + CALL .plot + + POP BC + RET + + ;; Old, compatible version of plot() +_plot:: + PUSH BC + + LD A,(.mode) + CP #.G_MODE + CALL NZ,.gmode + + LDA HL,4(SP) ; Skip return address and registers + LD A,(HL+) ; B = x + LD B,A + LD A,(HL+) ; C = y + LD C,A + LD A,(HL+) ; colour + LD (.fg_colour),A + LD A,(HL+) ; mode + LD (.draw_mode),A + + CALL .plot + + POP BC + RET + +_switch_data:: ; Non Banked as pointer + PUSH BC + + LD A,(.mode) + CP #.G_MODE + CALL NZ,.gmode + + LDA HL,4(SP) ; Skip return address and registers + LD A,(HL+) ; B = x + LD B,A + LD A,(HL+) ; C = y + LD C,A + LD A,(HL+) ; DE = src + LD E,A + LD A,(HL+) + LD D,A + LD A,(HL+) ; HL = dst + LD H,(HL) + LD L,A + + CALL .switch_data + + POP BC + RET + + +_draw_image:: ; Non banked as pointer + PUSH BC + + LD A,(.mode) + CP #.G_MODE + CALL NZ,.gmode + + LDA HL,4(SP) ; Skip return address and registers + LD A,(HL+) ; HL = data + LD C,A + LD B,(HL) + + CALL .draw_image + + POP BC + RET + +.y_table:: + .word 0x8100,0x8102,0x8104,0x8106,0x8108,0x810A,0x810C,0x810E + .word 0x8240,0x8242,0x8244,0x8246,0x8248,0x824A,0x824C,0x824E + .word 0x8380,0x8382,0x8384,0x8386,0x8388,0x838A,0x838C,0x838E + .word 0x84C0,0x84C2,0x84C4,0x84C6,0x84C8,0x84CA,0x84CC,0x84CE + .word 0x8600,0x8602,0x8604,0x8606,0x8608,0x860A,0x860C,0x860E + .word 0x8740,0x8742,0x8744,0x8746,0x8748,0x874A,0x874C,0x874E + .word 0x8880,0x8882,0x8884,0x8886,0x8888,0x888A,0x888C,0x888E + .word 0x89C0,0x89C2,0x89C4,0x89C6,0x89C8,0x89CA,0x89CC,0x89CE + .word 0x8B00,0x8B02,0x8B04,0x8B06,0x8B08,0x8B0A,0x8B0C,0x8B0E + .word 0x8C40,0x8C42,0x8C44,0x8C46,0x8C48,0x8C4A,0x8C4C,0x8C4E + .word 0x8D80,0x8D82,0x8D84,0x8D86,0x8D88,0x8D8A,0x8D8C,0x8D8E + .word 0x8EC0,0x8EC2,0x8EC4,0x8EC6,0x8EC8,0x8ECA,0x8ECC,0x8ECE + .word 0x9000,0x9002,0x9004,0x9006,0x9008,0x900A,0x900C,0x900E + .word 0x9140,0x9142,0x9144,0x9146,0x9148,0x914A,0x914C,0x914E + .word 0x9280,0x9282,0x9284,0x9286,0x9288,0x928A,0x928C,0x928E + .word 0x93C0,0x93C2,0x93C4,0x93C6,0x93C8,0x93CA,0x93CC,0x93CE + .word 0x9500,0x9502,0x9504,0x9506,0x9508,0x950A,0x950C,0x950E + .word 0x9640,0x9642,0x9644,0x9646,0x9648,0x964A,0x964C,0x964E diff --git a/gbdk/gbdk-lib/libc/targets/sm83/drawing_isr.s b/gbdk/gbdk-lib/libc/targets/sm83/drawing_isr.s new file mode 100644 index 00000000..e12a478c --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/drawing_isr.s @@ -0,0 +1,23 @@ + .include "global.s" + + .area _HOME + +.drawing_vbl:: + LDH A,(.LCDC) + OR #LCDCF_BG8000 ; Set BG Chr to 0x8000 + LDH (.LCDC),A + + LD A,#72 ; Set line at which LCD interrupt occurs + LDH (.LYC),A + + RET + + ;; Is the STAT check required, as we are already in the HBL? +.drawing_lcd:: + WAIT_STAT + + LDH A,(.LCDC) + AND #~LCDCF_BG8000 ; Set BG Chr to 0x8800 + LDH (.LCDC),A + + RET diff --git a/gbdk/gbdk-lib/libc/targets/sm83/duck/Makefile b/gbdk/gbdk-lib/libc/targets/sm83/duck/Makefile new file mode 100644 index 00000000..40007176 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/duck/Makefile @@ -0,0 +1,47 @@ +# GB specific Makefile + +TOPDIR = ../../../.. + +THIS = duck +PORT = sm83 + +CSRC = crlf.c digits.c gprint.c gprintf.c gprintln.c gprintn.c + +ASSRC = cgb.s cgb_palettes.s cgb_compat.s \ + cpy_data.s \ + drawing.s drawing_isr.s color.s \ + f_ibm_full.s f_ibm_sh.s f_italic.s f_min.s f_spect.s \ + get_bk_t.s get_data.s get_tile.s \ + get_wi_t.s get_xy_t.s \ + get_addr.s \ + hiramcpy.s init_tt.s input.s \ + pad.s \ + serial.s set_bk_t.s set_tile.s \ + set_data.s set_prop.s set_spr.s set_wi_t.s set_xy_t.s \ + set_1bit_data.s \ + sgb.s font.s font_color.s delay.s \ + emu_debug.s emu_debug_printf.s \ + nowait.s far_ptr.s \ + lcd.s joy.s tim.s tim.s tim_nested.s tim_common.s \ + crash_handler.s \ + ___sdcc_bcall_ehl.s ___sdcc_bcall.s \ + mv_spr.s \ + pad_ex.s \ + mode.s clock.s \ + get_t.s set_t.s init_vram.s \ + fill_rect.s fill_rect_bk.s fill_rect_wi.s \ + metasprites.s metasprites_flip.s metasprites_hide.s metasprites_hide_spr.s \ + set_tile_submap.s set_win_tile_submap.s \ + gb_decompress.s gb_decompress_tiles.s \ + rle_decompress.s \ + heap.s \ + sfr.s \ + crt0.s + +CRT0 = crt0.s + +include $(TOPDIR)/Makefile.common + +AS = $(AS_SM83) + +include ../../../Makefile.platform diff --git a/gbdk/gbdk-lib/libc/targets/sm83/duck/crash_handler.s b/gbdk/gbdk-lib/libc/targets/sm83/duck/crash_handler.s new file mode 100644 index 00000000..889ab300 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/duck/crash_handler.s @@ -0,0 +1,476 @@ +; Crash handler support +; Original code by ISSOtm +; Adapted by Toxa from gb-starter-kit: https://github.com/ISSOtm/gb-starter-kit + + .include "global.s" + + .globl _font_ibm + + SCRN_X = 160 ; Width of screen in pixels + SCRN_Y = 144 ; Height of screen in pixels + SCRN_X_B = 20 ; Width of screen in bytes + SCRN_Y_B = 18 ; Height of screen in bytes + + SCRN_VX = 256 ; Virtual width of screen in pixels + SCRN_VY = 256 ; Virtual height of screen in pixels + SCRN_VX_B = 32 ; Virtual width of screen in bytes + SCRN_VY_B = 32 ; Virtual height of screen in bytes + + + .area _CRASH_HEADER(ABS) + + .org 0x38 + di + jp ___HandleCrash + + + .area _HOME + +___HandleCrash:: + + ; We will use VRAM as scratch, since we are going to overwrite it for + ; screen output anyways. The thing is, we need to turn the LCD off + ; *without* affecting flags... fun task, eh? + + ; Note: it's assumed that this was jumped to with IME off. + ; Don't call this directly, use `rst Crash`. + + ld (wCrashA), a ; We need to have at least one working register, so... + ldh a, (.IE) ; We're also going to overwrite this + ld (wCrashIE), a + ldh a, (.LCDC) + ld (wCrashLCDC), a + ld a, #LCDCF_ON ; LCDCF_ON Make sure the LCD is turned on to avoid waiting infinitely + ldh (.LCDC), a + ld a, #IEF_VBLANK ; IEF_VBLANK + ld (.IE), a + ld a, #0 ; `xor a` would overwrite flags + ld (.IF), a ; No point in backing up that register, it's always changing + halt ; With interrupts disabled, this will exit when `IE & IF != 0` + nop ; Handle hardware bug if it becomes true *before* starting to execute the instruction (1-cycle window) + + ; We're now in VBlank! So we can now use VRAM as scratch for some cycles + ld a, #0 + ldh (.LCDC), a ; Turn off LCD so VRAM can always be safely accessed + ; Save regs + ld (vCrashSP), sp + ld sp, #vCrashSP + push hl + push de + push bc + ld a, (wCrashA) + push af + + ; We need to have all the data in bank 0, but we can't guarantee we were there + ldh a, (.VBK) + ld e, a + bit #0, a + jr z, .bank0 + ; Oh noes. We need to copy the data across banks! + ld hl, #vCrashAF + ld c, #(5 * 2) +.copyAcross: + ld b, (hl) + xor a + ldh (.VBK), a + ld (hl), b + inc l ; inc hl + inc a ; ld a, 1 + ldh (.VBK), a + dec c + jr nz, .copyAcross +.bank0: + xor a + ldh (.NR52), a ; Kill sound for this screen + + ldh (.VBK), a + ld a, e + ld (vCrashVBK), a ; copy vCrashVBK across banks + + ld a, #1 + ldh (.VBK), a + ld hl, #vCrashDumpScreen + ld b, #SCRN_Y_B +.writeAttrRow: + xor a + ld c, #(SCRN_X_B + 1) + rst #0x28 ; .MemsetSmall + ld a, l + add a, #(SCRN_VX_B - SCRN_X_B - 1) + ld l, a + dec b + jr nz, .writeAttrRow + xor a + ldh (.VBK), a + + ; Load palettes + ld a, #0x03 + ldh (.BGP), a + ld a, #0x80 + ldh (.BCPS), a + xor a + ld c, #.BCPD + ldh (c), a + ldh (c), a + dec a ; ld a, $FF + ldh (c), a + ldh (c), a + ldh (c), a + ldh (c), a + ldh (c), a + ldh (c), a + + ld a, #(SCRN_VY - SCRN_Y) + ldh (.SCY), a + ld a, #(SCRN_VX - SCRN_X - 4) + ldh (.SCX), a + + call loadfont + + ; Copy the registers to the dump viewers + ld hl, #vDumpHL + ld de, #vCrashHL + ld c, #4 + rst #0x30 ; .MemcpySmall + + ; We're now going to draw the screen, top to bottom + ld hl, #vCrashDumpScreen + + ; First 3 lines of text + ld de, #.header + ld b, #3 +.writeHeaderLine: + ld a, #0x20 ; " " + ld (hl+), a + ld c, #19 + rst #0x30 ; .MemcpySmall + ld a, #0x20 ; " " + ld (hl+), a + ld a, l + add a, #(SCRN_VX_B - SCRN_X_B - 1) + ld l, a + dec b + jr nz, .writeHeaderLine + + ; Blank line + ld a, #0x20 ; " " + ld c, #(SCRN_X_B + 1) + rst #0x28 ; .MemsetSmall + + ; AF and console model + ld l, #<vCrashDumpScreenRow4 + ld c, #4 + rst #0x30 ; .MemcpySmall + pop bc + call .printHexBC + ld c, #8 + rst #0x30 ; .MemcpySmall + ld a, (__cpu) + call .printHexA + ld a, #0x20 ; " " + ld (hl+), a + ld (hl+), a + ld (hl+), a + + ; BC and DE + ld l, #<vCrashDumpScreenRow5 + ld c, #4 + rst #0x30 ; .MemcpySmall + pop bc + call .printHexBC + ld c, #6 + rst #0x30 ; .MemcpySmall + pop bc + call .printHexBC + ld a, #0x20 + ld (hl+), a + ld (hl+), a + ld (hl+), a + + ; Now, the two memory dumps +.writeDump: + ld a, l + add a, #(SCRN_VX_B - SCRN_X_B - 1) + ld l, a + ld c, #4 + rst #0x30 ; .MemcpySmall + pop bc + push bc + call .printHexBC + ld de, #.viewStr + ld c, #7 + rst #0x30 ; .MemcpySmall + pop de + call .printDump + ld de, #.spStr + bit #7, l + jr z, .writeDump + + ld de, #.hwRegsStrs + ld l, #<vCrashDumpScreenRow14 + ld c, #6 + rst #0x30 ; .MemcpySmall + ld a, (wCrashLCDC) + call .printHexA + ld c, #4 + rst #0x30 ; .MemcpySmall + ldh a, (.KEY1) + call .printHexA + ld c, #4 + rst #0x30 ; .MemcpySmall + ld a, (wCrashIE) + call .printHexA + ld (hl), #0x20 ; " " + + ld l, #<vCrashDumpScreenRow15 + ld c, #7 + rst #0x30 ; .MemcpySmall +.writeBank: + ld a, #0x20 ; " " + ld (hl+), a + ld a, (de) + inc de + ld (hl+), a + cp #0x20 ; " " + jr z, .banksDone + ld a, (de) + inc de + ld c, a + ld a, (de) + inc de + ld b, a + ld a, (bc) + call .printHexA + jr .writeBank +.banksDone: + + ; Start displaying + ld a, #(LCDCF_ON | LCDCF_BG9C00 | LCDCF_BGON) + ldh (.LCDC), a + +.loop: + ; The code never lags, and IE is equal to IEF_VBLANK + xor a + ldh (.IF), a + halt + + jr .loop + +.printHexBC: + call .printHexB + ld a, c +.printHexA: + ld b, a +.printHexB: + ld a, b + and #0xF0 + swap a + add a, #0x30 + cp #0x3a + jr c, 1$ + add a, #(0x41 - 0x3a) +1$: ld (hl+), a + ld a, b + and #0x0F + add a, #0x30 + cp #0x3a + jr c, 2$ + add a, #(0x41 - 0x3a) +2$: ld (hl+), a + ret + +.printDump: + ld b, d + ld c, e + call .printHexBC + ld a, #0x20 ; " " + ld (hl+), a + ld (hl+), a + ld a, e + sub #8 + ld e, a + ld a, d + sbc #0 + ld d, a +.writeDumpLine: + ld a, l + add a, #(SCRN_VX_B - SCRN_X_B - 1) + ld l, a + ld a, #0x20 ; " " + ld (hl+), a +.writeDumpWord: + ld a, (de) + inc de + call .printHexA + ld a, (de) + inc de + call .printHexA + ld a, #0x20 ; " " + ld (hl+), a + bit 4, l + jr nz, .writeDumpWord + ld a, l + and #0x7F + jr nz, .writeDumpLine + ret + +loadfont: + xor a + cpl + ld hl, #0x9000 + ld c, #16 + rst #0x28 ; .MemsetSmall + ld hl, #(0x9000 + ' ' * 16) + ld c, #16 + rst #0x28 ; .MemsetSmall + + ld de, #(_font_ibm + 2 + '0') ; recode table + ld hl, #(0x9000 + '0' * 16) ; destination + push hl + ld c, #(16 * 3) +1$: + ld a, (de) + inc de + push de + + swap a + ld l, a + and #0x0f + ld h, a + ld a, l + and #0xf0 + srl h + rra + ld l, a + ld de, #(_font_ibm + 2 + 128) + add hl, de + + ld d, h + ld e, l + + ldhl sp, #2 + ld a, (hl+) + ld h, (hl) + ld l, a + + ld b, #8 +2$: + ld a, (de) + cpl + inc de + ld (hl+), a + ld (hl+), a + + dec b + jr nz, 2$ + + ld d, h + ld a, l + ldhl sp, #2 + ld (hl+), a + ld (hl), d + + pop de + + dec c + jr nz, 1$ + + add sp, #2 + ret + +.header: + ; 0123456789ABCDEFGHI 19 chars + .ascii "KERNEL PANIC PLEASE" + .ascii "SEND A CLEAR PIC OF" + .ascii "THIS SCREEN TO DEVS" + .ascii " AF:" + .ascii " MODEL:" + .ascii " BC:" + .ascii " DE:" + .ascii " HL:" +.viewStr: + .ascii " VIEW:" +.spStr: + .ascii " SP:" +.hwRegsStrs: + .ascii " LCDC:" + .ascii " K1:" + .ascii " IE:" + .ascii " BANK:" + .ascii "R" + .dw __current_bank + .ascii "V" + .dw vCrashVBK + .ascii "W" + .db .SVBK, 0xff + .ascii " " + + + .area _DATA + +wCrashA: + .ds 1 ; We need at least one working register, and A allows accessing memory +wCrashIE: + .ds 1 +wCrashLCDC: + .ds 1 + + + .area _CRASH_SCRATCH(ABS) + + .org 0x9C00 + + ; Put the crash dump screen at the bottom-right of the 9C00 tilemap, since that tends to be unused space + .ds SCRN_VX_B * (SCRN_VY_B - SCRN_Y_B - 2) ; 2 rows reserved as scratch space + + .ds SCRN_X_B ; Try not to overwrite the window area + .ds 2 * 1 ; Free stack entries (we spill into the above by 1 entry, though :/) + ; These are the initial values of the registers + ; They are popped off the stack when printed, freeing up stack space + +vCrashAF: + .ds 2 +vCrashBC: + .ds 2 +vCrashDE: + .ds 2 +vCrashHL: + .ds 2 +vCrashSP: + .ds 2 + + .ds SCRN_X_B +vHeldKeys: + .ds 1 ; Keys held on previous frame +vUnlockCounter: + .ds 1 ; How many frames until dumps are "unlocked" +vWhichDump: + .ds 1 +vDumpHL: + .ds 2 +vDumpSP: + .ds 2 +vCrashVBK: + .ds 1 + .ds 4 ; Unused + + .ds SCRN_VX_B - SCRN_X_B - 1 +vCrashDumpScreen: +vCrashDumpScreenRow0 = vCrashDumpScreen + 1 * SCRN_VX_B +vCrashDumpScreenRow1 = vCrashDumpScreen + 2 * SCRN_VX_B +vCrashDumpScreenRow2 = vCrashDumpScreen + 3 * SCRN_VX_B +vCrashDumpScreenRow3 = vCrashDumpScreen + 4 * SCRN_VX_B +vCrashDumpScreenRow4 = vCrashDumpScreen + 5 * SCRN_VX_B +vCrashDumpScreenRow5 = vCrashDumpScreen + 6 * SCRN_VX_B +vCrashDumpScreenRow6 = vCrashDumpScreen + 7 * SCRN_VX_B +vCrashDumpScreenRow7 = vCrashDumpScreen + 8 * SCRN_VX_B +vCrashDumpScreenRow8 = vCrashDumpScreen + 9 * SCRN_VX_B +vCrashDumpScreenRow9 = vCrashDumpScreen + 10 * SCRN_VX_B +vCrashDumpScreenRow10 = vCrashDumpScreen + 11 * SCRN_VX_B +vCrashDumpScreenRow11 = vCrashDumpScreen + 12 * SCRN_VX_B +vCrashDumpScreenRow12 = vCrashDumpScreen + 13 * SCRN_VX_B +vCrashDumpScreenRow13 = vCrashDumpScreen + 14 * SCRN_VX_B +vCrashDumpScreenRow14 = vCrashDumpScreen + 15 * SCRN_VX_B +vCrashDumpScreenRow15 = vCrashDumpScreen + 16 * SCRN_VX_B +vCrashDumpScreenRow16 = vCrashDumpScreen + 17 * SCRN_VX_B +vCrashDumpScreenRow17 = vCrashDumpScreen + 18 * SCRN_VX_B diff --git a/gbdk/gbdk-lib/libc/targets/sm83/duck/crt0.s b/gbdk/gbdk-lib/libc/targets/sm83/duck/crt0.s new file mode 100644 index 00000000..0022cc42 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/duck/crt0.s @@ -0,0 +1,468 @@ + .include "global.s" + + ;; **************************************** + ;; Beginning of module + ;; BANKED: checked + .title "Runtime" + .module Runtime + .area _HEADER (ABS) + + ;; RST vectors + .org 0x00 ; MEGADUCK entry point/reset + JP .code_start + +; .org 0x08 ; --profile handler utilized by emu_debug.h + +; .org 0x10 ; empty + +; .org 0x18 ; empty + + .org 0x20 ; RST 0x20 == call HL +.call_hl:: + JP (HL) + + .org 0x28 ; zero up to 256 bytes in C pointed by HL +.MemsetSmall:: + LD (HL+),A + DEC C + JR NZ,.MemsetSmall + ret + + .org 0x30 ; copy up to 256 bytes in C from DE to HL +.MemcpySmall:: + LD A, (DE) + LD (HL+), A + INC DE + DEC C + JR NZ,.MemcpySmall + RET + +; .org 0x38 ; crash handler utilized by crash_handler.h + + ;; Hardware interrupt vectors + .org 0x40 ; VBL +.int_VBL: + PUSH AF + PUSH HL + LD HL,#.int_0x40 + JP .int + +; .org 0x48 ; LCD + +; .org 0x50 ; TIM + +; .org 0x58 ; SIO + +; .org 0x60 ; JOY + +; .org 0x70 + ;; space for drawing.s bit table + + .org 0x80 +.int:: + PUSH BC + PUSH DE +1$: + LD A,(HL+) + OR (HL) + JR Z,.int_tail + PUSH HL + LD A,(HL-) + LD L,(HL) + LD H,A + RST 0x20 ; .call_hl + POP HL + INC HL + JR 1$ +_wait_int_handler:: + ADD SP,#4 +.int_tail: + POP DE + POP BC + POP HL + + ;; we return at least at the beginning of mode 2 + WAIT_STAT + + POP AF + RETI + + ;; VBlank default interrupt routine +__standard_VBL_handler:: +.std_vbl: + LD HL,#.sys_time + INC (HL) + JR NZ,2$ + INC HL + INC (HL) +2$: + CALL .refresh_OAM + + LD A, #1 + LDH (.vbl_done),A + RET + +_refresh_OAM:: + WAIT_STAT + LD A, #>_shadow_OAM + JP .refresh_OAM + (.refresh_OAM_DMA - .start_refresh_OAM) + +.clear_WRAM: + PUSH DE + XOR A + LD BC, #l__DATA + LD HL, #s__DATA + CALL .memset_simple + + LD A, #>_shadow_OAM + LDH (__shadow_OAM_base), A + LD H, A + XOR A + LD L, A + LD C, #(40 << 2) ; 40 entries 4 bytes each + RST 0x28 + POP DE + RET + + .org 0x150 + + ;; soft reset: falldown to .code_start +.reset:: +_reset:: + + ;; Initialization code +.code_start:: + DI ; Disable interrupts + ;; Initialize the stack + LD SP, #.STACK + + CALL .clear_WRAM + +; LD (.mode),A ; Clearing (.mode) is performed when clearing RAM + + ;; Store CPU type + LD A, #.DMG_TYPE ; MEGADUCK is always a DMG + LD (__cpu), A + XOR A + LD (__is_GBA), A ; and it is never GBA + + ;; Turn the screen off + CALL .display_off + + XOR A + ;; Initialize the display + LDH (.SCY),A + LDH (.SCX),A + LDH (.STAT),A + LDH (.WY),A + LD A,#0x07 + LDH (.WX),A + + ;; Copy refresh_OAM routine to HRAM + LD DE,#.start_refresh_OAM ; source + LD HL,#.refresh_OAM ; dest + LD C,#(.end_refresh_OAM - .start_refresh_OAM) ; size + RST 0x30 ; call .MemcpySmall + + ;; Clear the OAM by calling refresh_OAM + CALL .refresh_OAM + + ;; Install interrupt routines + LD BC,#.std_vbl + CALL .add_VBL + + ;; Standard color palettes + LD A,#0b11100100 ; Grey 3 = 11 (Black) + ; Grey 2 = 10 (Dark grey) + ; Grey 1 = 01 (Light grey) + ; Grey 0 = 00 (Transparent) + LDH (.BGP),A + LDH (.OBP0),A + LD A,#0b00011011 + LDH (.OBP1),A + + ;; Turn the screen on + LD A,#(LCDCF_ON | LCDCF_WIN9C00 | LCDCF_WINOFF | LCDCF_BG8800 | LCDCF_BG9800 | LCDCF_OBJ8 | LCDCF_OBJOFF | LCDCF_BGOFF) + LDH (.LCDC),A + XOR A + LDH (.IF),A + LD A,#.VBL_IFLAG ; switch on VBlank interrupt only + LDH (.IE),A + + LDH (__current_bank),A ; current bank is 1 at startup + + XOR A + + LD HL,#.sys_time + LD (HL+),A + LD (HL),A + + LDH (.NR52),A ; Turn sound off + + CALL gsinit + + EI ; Enable interrupts + + ;; Call the main function + CALL _main +_exit:: +99$: + HALT + NOP + JR 99$ ; Wait forever + +_set_interrupts:: + DI + LDA HL,2(SP) ; Skip return address + XOR A + LDH (.IF),A ; Clear pending interrupts + LD A,(HL) + EI ; Enable interrupts + LDH (.IE),A ; interrupts are still disabled here + RET + + ;; Copy OAM data to OAM RAM +.start_refresh_OAM: + LDH A,(__shadow_OAM_base) + OR A + RET Z +.refresh_OAM_DMA: + LDH (.DMA),A ; Put A into DMA registers + LD A,#0x28 ; We need to wait 160 ns +1$: + DEC A + JR NZ,1$ + RET +.end_refresh_OAM: + + .org .MODE_TABLE + ;; Jump table for modes + RET + + ;; **************************************** + + ;; Ordering of segments for the linker + ;; Code that really needs to be in bank 0 + .area _HOME + ;; Similar to _HOME + .area _BASE + ;; Code + .area _CODE + ;; #pragma bank 0 workaround + .area _CODE_0 + ;; Constant data + .area _LIT +; ;; since _CODE_1 area base address is pre-defined in the linker from 0x4000, +; ;; that moves initializer code and tables out of bank 0 +; .area _CODE_1 + ;; Constant data, used to init _DATA + .area _INITIALIZER + ;; Code, used to init _DATA + .area _GSINIT + .area _GSFINAL + ;; Uninitialised ram data + .area _DATA + .area _BSS + ;; Initialised in ram data + .area _INITIALIZED + ;; For malloc + .area _HEAP + .area _HEAP_END + + .area _DATA +__cpu:: + .ds 0x01 ; GB type (GB, PGB, CGB) +__is_GBA:: + .ds 0x01 ; detect GBA +.mode:: + .ds 0x01 ; Current mode +.sys_time:: +_sys_time:: + .ds 0x02 ; System time in VBL units +.int_0x40:: + .blkw 0x0A ; 4 interrupt handlers (built-in + user-defined) + + .area _HRAM (ABS) + + .org 0xFF90 +__current_bank:: ; Current bank + .ds 0x01 +.vbl_done: + .ds 0x01 ; Is VBL interrupt finished? +__shadow_OAM_base:: + .ds 0x01 + + ;; Runtime library + .area _GSINIT +gsinit:: + ;; initialize static storage variables + LD BC, #l__INITIALIZER + LD HL, #s__INITIALIZER + LD DE, #s__INITIALIZED + call .memcpy_simple + + .area _GSFINAL + ret + + .area _HOME + + ;; fills memory at HL of length BC with A, clobbers DE +.memset_simple:: + LD E, A + LD A, B + OR C + RET Z + LD (HL), E + DEC BC + LD D, H + LD E, L + INC DE + + ;; copies BC bytes from HL into DE +.memcpy_simple:: + LD A, B + OR C + RET Z + + SRL B + RR C + JR NC,3$ + LD A, (HL+) + LD (DE), A + INC DE +3$: + INC B + INC C + JR 2$ +1$: + LD A, (HL+) + LD (DE), A + INC DE + LD A, (HL+) + LD (DE), A + INC DE +2$: + DEC C + JR NZ,1$ + DEC B + JR NZ,1$ +4$: + RET + + ;; Remove interrupt routine in BC from the VBL interrupt list + ;; falldown to .remove_int +.remove_VBL:: + LD HL,#.int_0x40 + + ;; Remove interrupt BC from interrupt list HL if it exists + ;; Abort if a 0000 is found (end of list) +.remove_int:: +1$: + LD A,(HL+) + LD E,A + LD D,(HL) + INC HL + OR D + RET Z ; No interrupt found + + LD A,E + CP C + JR NZ,1$ + LD A,D + CP B + JR NZ,1$ + + LD D,H + LD E,L + DEC DE + DEC DE + + ;; Now do a memcpy from here until the end of the list +2$: + LD A,(HL+) + LD (DE),A + LD B,A + INC DE + LD A,(HL+) + LD (DE),A + INC DE + OR B + RET Z + JR 2$ + + ;; Add interrupt routine in BC to the VBL interrupt list + ;; falldown to .add_int +.add_VBL:: + LD HL,#.int_0x40 + + ;; Add interrupt routine in BC to the interrupt list in HL +.add_int:: +1$: + LD A,(HL+) + OR (HL) + JR Z,2$ + INC HL + JR 1$ +2$: + LD A,B + LD (HL-),A + LD (HL),C + RET + + ;; Wait for VBL interrupt to be finished +.wait_vbl_done:: +_wait_vbl_done:: + ;; Check if the screen is on + LDH A,(.LCDC) + AND #LCDCF_ON + RET Z ; Return if screen is off + XOR A + LDH (.vbl_done),A ; Clear any previous sets of vbl_done +1$: + HALT ; Wait for any interrupt + NOP ; HALT sometimes skips the next instruction + LDH A,(.vbl_done) ; Was it a VBlank interrupt? + ;; Warning: we may lose a VBlank interrupt, if it occurs now + OR A + JR Z,1$ ; No: back to sleep! + RET + +.display_off:: +_display_off:: + ;; Check if the screen is on + LDH A,(.LCDC) + AND #LCDCF_ON + RET Z ; Return if screen is off +1$: ; We wait for the *NEXT* VBL + LDH A,(.LY) + CP #0x92 ; Smaller than or equal to 0x91? + JR NC,1$ ; Loop until smaller than or equal to 0x91 +2$: + LDH A,(.LY) + CP #0x91 ; Bigger than 0x90? + JR C,2$ ; Loop until bigger than 0x90 + + LDH A,(.LCDC) + AND #~LCDCF_ON + LDH (.LCDC),A ; Turn off screen + RET + +_remove_VBL:: + PUSH BC + LDA HL,4(SP) ; Skip return address and registers + LD A,(HL+) + LD C,A + LD B,(HL) + CALL .remove_VBL + POP BC + RET + +_add_VBL:: + PUSH BC + LDA HL, 4(SP) ; Skip return address and registers + LD A,(HL+) + LD C,A + LD B,(HL) + CALL .add_VBL + POP BC + RET diff --git a/gbdk/gbdk-lib/libc/targets/sm83/duck/global.s b/gbdk/gbdk-lib/libc/targets/sm83/duck/global.s new file mode 100644 index 00000000..70771412 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/duck/global.s @@ -0,0 +1,533 @@ + .NEAR_CALLS = 1 ; <near_calls> - tag so that sed can change this + + _VRAM = 0x8000 ; $8000->$9FFF + _VRAM8000 = 0x8000 + _VRAM8800 = 0x8800 + _VRAM9000 = 0x9000 + _SCRN0 = 0x9800 ; $9800->$9BFF + _SCRN1 = 0x9C00 ; $9C00->$9FFF + _SRAM = 0xA000 ; $A000->$BFFF + _RAM = 0xC000 ; $C000->$CFFF / $C000->$DFFF + _RAMBANK = 0xD000 ; $D000->$DFFF + _OAMRAM = 0xFE00 ; $FE00->$FE9F + _IO = 0xFF00 ; $FF00->$FF7F,$FFFF + _AUD3WAVERAM = 0xFF30 ; $FF30->$FF3F + _HRAM = 0xFF80 ; $FF80->$FFFE + + ;; MBC Equates + + .MBC1_ROM_PAGE = 0x2000 ; Address to write to for MBC1 switching + .MBC_ROM_PAGE = 0x0001 ; Default platform MBC rom switching address + + rRAMG = 0x0000 ; $0000->$1fff + rROMB0 = 0x0001 ; $2000->$2fff + rROMB1 = 0x3000 ; $3000->$3fff - If more than 256 ROM banks are present. + rRAMB = 0x4000 ; $4000->$5fff - Bit 3 enables rumble (if present) + + ;; Keypad + .START = 0x80 + .SELECT = 0x40 + .B = 0x20 + .A = 0x10 + .DOWN = 0x08 + .UP = 0x04 + .LEFT = 0x02 + .RIGHT = 0x01 + + .P14 = 0x10 + .P15 = 0x20 + + ;; Screen dimensions + .MAXCURSPOSX = 0x13 ; In tiles + .MAXCURSPOSY = 0x11 + + .SCREENWIDTH = 0xA0 + .SCREENHEIGHT = 0x90 + .MINWNDPOSX = 0x07 + .MINWNDPOSY = 0x00 + .MAXWNDPOSX = 0xA6 + .MAXWNDPOSY = 0x8F + + ;; Hardware registers + + .P1 = 0x00 ; Joystick: 1.1.P15.P14.P13.P12.P11.P10 + rP1 = 0xFF00 + + P1F_5 = 0b00100000 ; P15 out port, set to 0 to get buttons + P1F_4 = 0b00010000 ; P14 out port, set to 0 to get dpad + P1F_3 = 0b00001000 ; P13 in port + P1F_2 = 0b00000100 ; P12 in port + P1F_1 = 0b00000010 ; P11 in port + P1F_0 = 0b00000001 ; P10 in port + + P1F_GET_DPAD = 0b00100000 + P1F_GET_BTN = 0b00010000 + P1F_GET_NONE = 0b00110000 + + .SB = 0x01 ; Serial IO data buffer + rSB = 0xFF01 + + .SC = 0x02 ; Serial IO control register + rSC = 0xFF02 + + .DIV = 0x04 ; Divider register + rDIV = 0xFF04 + + .TIMA = 0x05 ; Timer counter + rTIMA = 0xFF05 + + .TMA = 0x06 ; Timer modulo + rTMA = 0xFF06 + + .TAC = 0x07 ; Timer control + rTAC = 0xFF07 + + TACF_START = 0b00000100 + TACF_STOP = 0b00000000 + TACF_4KHZ = 0b00000000 + TACF_16KHZ = 0b00000011 + TACF_65KHZ = 0b00000010 + TACF_262KHZ = 0b00000001 + + .IF = 0x0F ; Interrupt flags: 0.0.0.JST.SIO.TIM.LCD.VBL + rIF = 0xFF0F + + .NR10 = 0x20 ; Sound register + rNR10 = 0xFF20 + rAUD1SWEEP = 0xFF20 + + AUD1SWEEP_UP = 0b00000000 + AUD1SWEEP_DOWN = 0b00001000 + + .NR11 = 0x22 ; Sound register + rNR11 = 0xFF22 + rAUD1LEN = 0xFF22 + + .NR12 = 0x21 ; Sound register + rNR12 = 0xFF21 + rAUD1ENV = 0xFF21 + + .NR13 = 0x23 ; Sound register + rNR13 = 0xFF23 + rAUD1LOW = 0xFF23 + + .NR14 = 0x24 ; Sound register + rNR14 = 0xFF24 + rAUD1HIGH = 0xFF24 + + .NR21 = 0x25 ; Sound register + rNR21 = 0xFF25 + rAUD2LEN = 0xFF25 + + .NR22 = 0x27 ; Sound register + rNR22 = 0xFF27 + rAUD2ENV = 0xFF27 + + .NR23 = 0x28 ; Sound register + rNR23 = 0xFF28 + rAUD2LOW = 0xFF28 + + .NR24 = 0x29 ; Sound register + rNR24 = 0xFF29 + rAUD2HIGH = 0xFF29 + + .NR30 = 0x2A ; Sound register + rNR30 = 0xFF2A + rAUD3ENA = 0xFF2A + + .NR31 = 0x2B ; Sound register + rNR31 = 0xFF2B + rAUD3LEN = 0xFF2B + + .NR32 = 0x2C ; Sound register + rNR32 = 0xFF2C + rAUD3LEVEL = 0xFF2C + + .NR33 = 0x2E ; Sound register + rNR33 = 0xFF2E + rAUD3LOW = 0xFF2E + + .NR34 = 0x2D ; Sound register + rNR34 = 0xFF2D + rAUD3HIGH = 0xFF2D + + .NR41 = 0x40 ; Sound register + rNR41 = 0xFF40 + rAUD4LEN = 0xFF40 + + .NR42 = 0x42 ; Sound register + rNR42 = 0xFF42 + rAUD4ENV = 0xFF42 + + .NR43 = 0x41 ; Sound register + rNR43 = 0xFF41 + rAUD4POLY = 0xFF41 + + .NR44 = 0x43 ; Sound register + rNR44 = 0xFF43 + rAUD4GO = 0xFF43 + + .NR50 = 0x44 ; Sound register + rNR50 = 0xFF44 + rAUDVOL = 0xFF44 + + AUDVOL_VIN_LEFT = 0b10000000 ; SO2 + AUDVOL_VIN_RIGHT = 0b00001000 ; SO1 + + .NR51 = 0x46 ; Sound register + rNR51 = 0xFF46 + rAUDTERM = 0xFF46 + + AUDTERM_4_LEFT = 0b10000000 + AUDTERM_3_LEFT = 0b01000000 + AUDTERM_2_LEFT = 0b00100000 + AUDTERM_1_LEFT = 0b00010000 + AUDTERM_4_RIGHT = 0b00001000 + AUDTERM_3_RIGHT = 0b00000100 + AUDTERM_2_RIGHT = 0b00000010 + AUDTERM_1_RIGHT = 0b00000001 + + .NR52 = 0x45 ; Sound register + rNR52 = 0xFF45 + rAUDENA = 0xFF45 + + AUDENA_ON = 0b10000000 + AUDENA_OFF = 0b00000000 ; sets all audio regs to 0! + + .LCDC = 0x10 ; LCD control + rLCDC = 0xFF10 + + LCDCF_OFF = 0b00000000 ; LCD Control Operation + LCDCF_ON = 0b10000000 ; LCD Control Operation + LCDCF_WIN9800 = 0b00000000 ; Window Tile Map Display Select + LCDCF_WIN9C00 = 0b00001000 ; Window Tile Map Display Select + LCDCF_WINOFF = 0b00000000 ; Window Display + LCDCF_WINON = 0b00100000 ; Window Display + LCDCF_BG8800 = 0b00000000 ; BG & Window Tile Data Select + LCDCF_BG8000 = 0b00010000 ; BG & Window Tile Data Select + LCDCF_BG9800 = 0b00000000 ; BG Tile Map Display Select + LCDCF_BG9C00 = 0b00000100 ; BG Tile Map Display Select + LCDCF_OBJ8 = 0b00000000 ; OBJ Construction + LCDCF_OBJ16 = 0b00000010 ; OBJ Construction + LCDCF_OBJOFF = 0b00000000 ; OBJ Display + LCDCF_OBJON = 0b00000001 ; OBJ Display + LCDCF_BGOFF = 0b00000000 ; BG Display + LCDCF_BGON = 0b01000000 ; BG Display + LCDCF_B_ON = 7 + LCDCF_B_WIN9C00 = 3 + LCDCF_B_WINON = 5 + LCDCF_B_BG8000 = 4 + LCDCF_B_BG9C00 = 2 + LCDCF_B_OBJ16 = 1 + LCDCF_B_OBJON = 0 + LCDCF_B_BGON = 6 + + .STAT = 0x11 ; LCD status + rSTAT = 0xFF11 + + STATF_LYC = 0b01000000 ; LYC=LY Coincidence (Selectable) + STATF_MODE10 = 0b00100000 ; Mode 10 + STATF_MODE01 = 0b00010000 ; Mode 01 (V-Blank) + STATF_MODE00 = 0b00001000 ; Mode 00 (H-Blank) + STATF_LYCF = 0b00000100 ; Coincidence Flag + STATF_HBL = 0b00000000 ; H-Blank + STATF_VBL = 0b00000001 ; V-Blank + STATF_OAM = 0b00000010 ; OAM-RAM is used by system + STATF_LCD = 0b00000011 ; Both OAM and VRAM used by system + STATF_BUSY = 0b00000010 ; When set, VRAM access is unsafe + STATF_B_LYC = 6 + STATF_B_MODE10 = 5 + STATF_B_MODE01 = 4 + STATF_B_MODE00 = 3 + STATF_B_LYCF = 2 + STATF_B_VBL = 0 + STATF_B_OAM = 1 + STATF_B_BUSY = 1 + + .SCY = 0x12 ; Scroll Y + rSCY = 0xFF12 + + .SCX = 0x13 ; Scroll X + rSCX = 0xFF13 + + .LY = 0x18 ; LCDC Y-coordinate + rLY = 0xFF18 + + .LYC = 0x19 ; LY compare + rLYC = 0xFF19 + + .DMA = 0x1A ; DMA transfer + rDMA = 0xFF1A + + .BGP = 0x1B ; BG palette data + rBGP = 0xFF1B + + .OBP0 = 0x14 ; OBJ palette 0 data + rOBP0 = 0xFF14 + + .OBP1 = 0x15 ; OBJ palette 1 data + rOBP1 = 0xFF15 + + .WY = 0x16 ; Window Y coordinate + rWY = 0xFF16 + + .WX = 0x17 ; Window X coordinate + rWX = 0xFF17 + + .KEY1 = 0x4D ; CPU speed + rKEY1 = 0xFF4D + rSPD = 0xFF4D + + KEY1F_DBLSPEED = 0b10000000 ; 0=Normal Speed, 1=Double Speed (R) + KEY1F_PREPARE = 0b00000001 ; 0=No, 1=Prepare (R/W) + + .VBK = 0x4F ; VRAM bank + rVBK = 0xFF4F + + .HDMA1 = 0x51 ; DMA control 1 + rHDMA1 = 0xFF51 + + .HDMA2 = 0x52 ; DMA control 2 + rHDMA2 = 0xFF52 + + .HDMA3 = 0x53 ; DMA control 3 + rHDMA3 = 0xFF53 + + .HDMA4 = 0x54 ; DMA control 4 + rHDMA4 = 0xFF54 + + .HDMA5 = 0x55 ; DMA control 5 + rHDMA5 = 0xFF55 + + HDMA5F_MODE_GP = 0b00000000 ; General Purpose DMA (W) + HDMA5F_MODE_HBL = 0b10000000 ; HBlank DMA (W) + + HDMA5F_BUSY = 0b10000000 ; 0=Busy (DMA still in progress), 1=Transfer complete (R) + + .RP = 0x56 ; IR port + rRP = 0xFF56 + + RPF_ENREAD = 0b11000000 + RPF_DATAIN = 0b00000010 ; 0=Receiving IR Signal, 1=Normal + RPF_WRITE_HI = 0b00000001 + RPF_WRITE_LO = 0b00000000 + + .BCPS = 0x68 ; BG color palette specification + rBCPS = 0xFF68 + + BCPSF_AUTOINC = 0b10000000 ; Auto Increment (0=Disabled, 1=Increment after Writing) + + .BCPD = 0x69 ; BG color palette data + rBCPD = 0xFF69 + + .OCPS = 0x6A ; OBJ color palette specification + rOCPS = 0xFF6A + + OCPSF_AUTOINC = 0b10000000 ; Auto Increment (0=Disabled, 1=Increment after Writing) + + .OCPD = 0x6B ; OBJ color palette data + rOCPD = 0xFF6B + + .SVBK = 0x70 ; WRAM bank + rSVBK = 0xFF70 + rSMBK = 0xFF70 + + rPCM12 = 0xFF76 + + rPCM34 = 0xFF77 + + .IE = 0xFF ; Interrupt enable + rIE = 0xFFFF + + .VBL_IFLAG = 0x01 + .LCD_IFLAG = 0x02 + .TIM_IFLAG = 0x04 + .SIO_IFLAG = 0x08 + .JOY_IFLAG = 0x10 + + IEF_HILO = 0b00010000 ; Transition from High to Low of Pin number P10-P13 + IEF_SERIAL = 0b00001000 ; Serial I/O transfer end + IEF_TIMER = 0b00000100 ; Timer Overflow + IEF_STAT = 0b00000010 ; STAT + IEF_VBLANK = 0b00000001 ; V-Blank + + ;; Flags common to multiple sound channels + + AUDLEN_DUTY_12_5 = 0b00000000 ; 12.5% + AUDLEN_DUTY_25 = 0b01000000 ; 25% + AUDLEN_DUTY_50 = 0b10000000 ; 50% + AUDLEN_DUTY_75 = 0b11000000 ; 75% + + AUDENV_UP = 0b00001000 + AUDENV_DOWN = 0b00000000 + + AUDHIGH_RESTART = 0b10000000 + AUDHIGH_LENGTH_ON = 0b01000000 + AUDHIGH_LENGTH_OFF = 0b00000000 + + ;; OAM related constants + + OAM_COUNT = 40 ; number of OAM entries in OAM RAM + + OAMF_PRI = 0b10000000 ; Priority + OAMF_YFLIP = 0b01000000 ; Y flip + OAMF_XFLIP = 0b00100000 ; X flip + OAMF_PAL0 = 0b00000000 ; Palette number; 0,1 (DMG) + OAMF_PAL1 = 0b00010000 ; Palette number; 0,1 (DMG) + OAMF_BANK0 = 0b00000000 ; Bank number; 0,1 (GBC) + OAMF_BANK1 = 0b00001000 ; Bank number; 0,1 (GBC) + + OAMF_PALMASK = 0b00000111 ; Palette (GBC) + + OAMB_PRI = 7 ; Priority + OAMB_YFLIP = 6 ; Y flip + OAMB_XFLIP = 5 ; X flip + OAMB_PAL1 = 4 ; Palette number; 0,1 (DMG) + OAMB_BANK1 = 3 ; Bank number; 0,1 (GBC) + + ;; SGB packets + .PAL_01 = 0x00 + .PAL_23 = 0x01 + .PAL_03 = 0x02 + .PAL_12 = 0x03 + .ATTR_BLK = 0x04 + .ATTR_LIN = 0x05 + .ATTR_DIV = 0x06 + .ATTR_CHR = 0x07 + .SOUND = 0x08 + .SOU_TRN = 0x09 + .PAL_SET = 0x0A + .PAL_TRN = 0x0B + .ATRC_EN = 0x0C + .TEST_EN = 0x0D + .ICON_EN = 0x0E + .DATA_SND = 0x0F + .DATA_TRN = 0x10 + .MLT_REQ = 0x11 + .JUMP = 0x12 + .CHR_TRN = 0x13 + .PCT_TRN = 0x14 + .ATTR_TRN = 0x15 + .ATTR_SET = 0x16 + .MASK_EN = 0x17 + .OBJ_TRN = 0x18 + + ;; CPU detection + .DMG_TYPE = 0x01 ; Original GB or Super GB + .MGB_TYPE = 0xFF ; Pocket GB or Super GB 2 + .CGB_TYPE = 0x11 ; Color GB + + ;; GBDK library screen modes + + .G_MODE = 0x01 ; Graphic mode + .T_MODE = 0x02 ; Text mode (bit 2) + .T_MODE_OUT = 0x02 ; Text mode output only + .T_MODE_INOUT = 0x03 ; Text mode with input + .M_NO_SCROLL = 0x04 ; Disables scrolling of the screen in text mode + .M_NO_INTERP = 0x08 ; Disables special character interpretation + + ;; Status codes for IO + .IO_IDLE = 0x00 + .IO_SENDING = 0x01 + .IO_RECEIVING = 0x02 + .IO_ERROR = 0x04 + + ;; Type of IO data + .DT_IDLE = 0x66 + .DT_RECEIVING = 0x55 + + ;; Table of routines for modes + .MODE_TABLE = 0x01E0 + + ;; C related + ;; Overheap of a banked call. Used for parameters + ;; = ret + real ret + bank + + .if .NEAR_CALLS + .BANKOV = 2 + + .else + .BANKOV = 6 + + .endif + + .globl __current_bank + .globl __shadow_OAM_base + + ;; Global variables + .globl .mode + + .globl __cpu + .globl __is_GBA + + ;; Global routines +; .globl .set_mode ;; don't link mode.o by default + + .globl .reset + + .globl .display_off + + .globl .wait_vbl_done + + ;; Interrupt routines + .globl .add_VBL +; .globl .add_LCD ;; don't link LCD.o by default +; .globl .add_TIM ;; don't link TIM.o by default +; .globl .add_SIO ;; don't link serial.o by default +; .globl .add_JOY ;; don't link JOY.o by default + + ;; Symbols defined at link time + .globl .STACK + .globl _shadow_OAM + .globl .refresh_OAM + + ;; Main user routine + .globl _main + + ;; Macro definitions + +.macro WAIT_STAT ?lbl +lbl: LDH A, (.STAT) + AND #STATF_BUSY ; Check if in LCD modes 0 or 1 + JR NZ, lbl +.endm + +.macro ADD_A_REG16 regH regL + ADD regL + LD regL, A + ADC regH + SUB regL + LD regH, A +.endm + +.macro SIGNED_ADD_A_REG16 regH regL ?lbl + ; If A is negative, we need to subtract 1 from upper byte of 16-bit value + BIT 7, A ; set z if a signed bit is 0 + JR Z, lbl ; if z is set jump to positive + dec regH ; if negative decrement upper byte +lbl: + ADD_A_REG16 regH, regL +.endm + +.macro SIGNED_SUB_A_REG16 regH regL ?lbl + ; negate A then add to 16-bit value + CPL + INC A + SIGNED_ADD_A_REG16 regH, regL +.endm + +.macro MUL_DE_BY_A_RET_HL ?lbl1 ?lbl2 ?lbl3 + ; Multiply DE by A, return result in HL; preserves: BC + LD HL, #0 +lbl1: + SRL A + JR NC, lbl2 + ADD HL, DE +lbl2: + JR Z, lbl3 + SLA E + RL D + JR lbl1 +lbl3: +.endm + diff --git a/gbdk/gbdk-lib/libc/targets/sm83/duck/sfr.s b/gbdk/gbdk-lib/libc/targets/sm83/duck/sfr.s new file mode 100644 index 00000000..e91040c7 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/duck/sfr.s @@ -0,0 +1,111 @@ +__VRAM = 0x8000 +__VRAM8000 = 0x8000 +__VRAM8800 = 0x8800 +__VRAM9000 = 0x9000 +__SCRN0 = 0x9800 +__SCRN1 = 0x9C00 +__SRAM = 0xA000 +__RAM = 0xC000 +__RAMBANK = 0xD000 +__OAMRAM = 0xFE00 +__IO = 0xFF00 +__AUD3WAVERAM = 0xFF30 +__HRAM = 0xFF80 + +.globl __VRAM, __VRAM8000, __VRAM8800, __VRAM9000, __SCRN0, __SCRN1, __SRAM, __RAM, __RAMBANK, __OAMRAM, __IO, __AUD3WAVERAM, __HRAM + +_rRAMG = 0x0000 +_rROMB0 = 0x0001 +_rROMB1 = 0x3000 +_rRAMB = 0x4000 + +.globl _rRAMG, _rROMB0, _rROMB1, _rRAMB + +_P1_REG = 0xFF00 ; Joystick: 1.1.P15.P14.P13.P12.P11.P10 +_SB_REG = 0xFF01 ; Serial IO data buffer +_SC_REG = 0xFF02 ; Serial IO control register +_DIV_REG = 0xFF04 ; Divider register +_TIMA_REG = 0xFF05 ; Timer counter +_TMA_REG = 0xFF06 ; Timer modulo +_TAC_REG = 0xFF07 ; Timer control +_IF_REG = 0xFF0F ; Interrupt flags: 0.0.0.JOY.SIO.TIM.LCD.VBL +_LCDC_REG = 0xFF10 ; LCD control +_STAT_REG = 0xFF11 ; LCD status +_SCY_REG = 0xFF12 ; Scroll Y +_SCX_REG = 0xFF13 ; Scroll X +_OBP0_REG = 0xFF14 ; OBJ palette 0 data +_OBP1_REG = 0xFF15 ; OBJ palette 1 data +_WY_REG = 0xFF16 ; Window Y coordinate +_WX_REG = 0xFF17 ; Window X coordinate +_LY_REG = 0xFF18 ; LCDC Y-coordinate +_LYC_REG = 0xFF19 ; LY compare +_DMA_REG = 0xFF1A ; DMA transfer +_BGP_REG = 0xFF1B ; BG palette data +_NR10_REG = 0xFF20 ; Sound register +_NR12_REG = 0xFF21 ; Sound register +_NR11_REG = 0xFF22 ; Sound register +_NR13_REG = 0xFF23 ; Sound register +_NR14_REG = 0xFF24 ; Sound register +_NR21_REG = 0xFF25 ; Sound register +_NR22_REG = 0xFF27 ; Sound register +_NR23_REG = 0xFF28 ; Sound register +_NR24_REG = 0xFF29 ; Sound register +_NR30_REG = 0xFF2A ; Sound register +_NR31_REG = 0xFF2B ; Sound register +_NR32_REG = 0xFF2C ; Sound register +_NR34_REG = 0xFF2D ; Sound register +_NR33_REG = 0xFF2E ; Sound register +_NR41_REG = 0xFF40 ; Sound register +_NR43_REG = 0xFF41 ; Sound register +_NR42_REG = 0xFF42 ; Sound register +_NR44_REG = 0xFF43 ; Sound register +_NR50_REG = 0xFF44 ; Sound register +_NR52_REG = 0xFF45 ; Sound register +_NR51_REG = 0xFF46 ; Sound register +_PCM_SAMPLE = 0xFF30 ; PCM wave pattern +_AUD3WAVE = 0xFF30 ; PCM wave pattern +_KEY1_REG = 0xFF4D ; CPU speed +_VBK_REG = 0xFF4F ; VRAM bank +_HDMA1_REG = 0xFF51 ; DMA control 1 +_HDMA2_REG = 0xFF52 ; DMA control 2 +_HDMA3_REG = 0xFF53 ; DMA control 3 +_HDMA4_REG = 0xFF54 ; DMA control 4 +_HDMA5_REG = 0xFF55 ; DMA control 5 +_RP_REG = 0xFF56 ; IR port +_BCPS_REG = 0xFF68 ; BG color palette specification +_BCPD_REG = 0xFF69 ; BG color palette data +_OCPS_REG = 0xFF6A ; OBJ color palette specification +_OCPD_REG = 0xFF6B ; OBJ color palette data +_SVBK_REG = 0xFF70 ; WRAM bank +_PCM12_REG = 0xFF76 ; Sound channel 1&2 PCM amplitude (R) +_PCM34_REG = 0xFF77 ; Sound channel 3&4 PCM amplitude (R) +_IE_REG = 0xFFFF ; Interrupt enable + +.globl _P1_REG +.globl _SB_REG, _SC_REG +.globl _DIV_REG +.globl _TIMA_REG, _TMA_REG, _TAC_REG +.globl _IF_REG +.globl _NR10_REG, _NR11_REG, _NR12_REG, _NR13_REG, _NR14_REG +.globl _NR21_REG, _NR22_REG, _NR23_REG, _NR24_REG +.globl _NR30_REG, _NR31_REG, _NR32_REG, _NR33_REG, _NR34_REG +.globl _NR41_REG, _NR42_REG, _NR43_REG, _NR44_REG +.globl _NR50_REG, _NR51_REG, _NR52_REG +.globl _PCM_SAMPLE, _AUD3WAVE +.globl _LCDC_REG +.globl _STAT_REG +.globl _SCY_REG, _SCX_REG +.globl _LY_REG, _LYC_REG +.globl _DMA_REG +.globl _BGP_REG +.globl _OBP0_REG, _OBP1_REG +.globl _WY_REG, _WX_REG +.globl _KEY1_REG +.globl _VBK_REG +.globl _HDMA1_REG, _HDMA2_REG, _HDMA3_REG, _HDMA4_REG, _HDMA5_REG +.globl _RP_REG +.globl _BCPS_REG, _BCPD_REG +.globl _OCPS_REG, _OCPD_REG +.globl _SVBK_REG +.globl _PCM12_REG, _PCM34_REG +.globl _IE_REG
\ No newline at end of file diff --git a/gbdk/gbdk-lib/libc/targets/sm83/emu_debug.s b/gbdk/gbdk-lib/libc/targets/sm83/emu_debug.s new file mode 100644 index 00000000..46fe66c2 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/emu_debug.s @@ -0,0 +1,20 @@ + .include "global.s" + + .title "EMU_debug" + .module EMU_debug + + .area _EMU_HEADER (ABS) + + .org 0x08 + JP _EMU_profiler_message + + .area _HOME + + ;; EMU profiler message +_EMU_profiler_message:: + LD D, D + JR 1$ + .dw 0x6464 + .dw 0 + .ascii "PROFILE,%(SP+$0)%,%(SP+$1)%,%A%,%TOTALCLKS%,%ROMBANK%,%WRAMBANK%" +1$: RET diff --git a/gbdk/gbdk-lib/libc/targets/sm83/emu_debug_printf.s b/gbdk/gbdk-lib/libc/targets/sm83/emu_debug_printf.s new file mode 100644 index 00000000..1fd5cbbe --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/emu_debug_printf.s @@ -0,0 +1,43 @@ + .include "global.s" + + .title "EMU_debug" + .module EMU_debug + + .globl _sprintf + + .area _DATA + +ret_save: + .ds 0x02 +printf_buffer: + .ds 0x80 + + .area _HOME + + ;; EMU_printf(fmt, ...) +_EMU_printf:: + di + pop de + ld hl, #ret_save + ld (hl), e + inc hl + ld (hl), d + + ld de, #printf_buffer + push de + call _sprintf + pop hl + + ld d,d + jr 1$ + .dw 0x6464 + .dw 0x0001 + .dw #printf_buffer + .dw 0 +1$: + ld hl, #ret_save + ld a, (hl+) + ld h, (hl) + ld l, a + ei + jp (hl) diff --git a/gbdk/gbdk-lib/libc/targets/sm83/f_ibm_full.s b/gbdk/gbdk-lib/libc/targets/sm83/f_ibm_full.s new file mode 100644 index 00000000..d7f09b18 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/f_ibm_full.s @@ -0,0 +1,2616 @@ +; font: font + + .area _HOME + + .globl font_load + ;; Perform tricks with banking to shift this font out of + ;; bank 0. Doesnt currently work as the encoding table + ;; must always be visible. +_font_load_ibm_fixed:: ; Banked + ld hl,#_font_ibm_fixed + call font_load + ret + +_font_ibm_fixed:: + .db 0+4 ; 256 char encoding, compressed + .db 255 ; Number of tiles + +; Encoding table + + ; Hack + .db 0x00 + .db 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08 + .db 0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10 + .db 0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18 + .db 0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20 + .db 0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28 + .db 0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,0x30 + .db 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38 + .db 0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,0x40 + .db 0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48 + .db 0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,0x50 + .db 0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58 + .db 0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F,0x60 + .db 0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68 + .db 0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,0x70 + .db 0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78 + .db 0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F,0x80 + .db 0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88 + .db 0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90 + .db 0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98 + .db 0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,0xA0 + .db 0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8 + .db 0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0 + .db 0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8 + .db 0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF,0xC0 + .db 0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8 + .db 0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0 + .db 0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8 + .db 0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,0xE0 + .db 0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8 + .db 0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0 + .db 0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8 + .db 0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF + ; Tile data + ;; Hook for the graphics routines +_font_ibm_fixed_tiles:: +; Default character (space) + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + +; Character: ? (01) + .db 0b00011000 ; oo + .db 0b00100100 ; o o + .db 0b01000010 ; o o + .db 0b10000001 ; o o + .db 0b11100111 ; ooo ooo + .db 0b00100100 ; o o + .db 0b00100100 ; o o + .db 0b00111100 ; oooo + +; Character: ? (02) + .db 0b00111100 ; oooo + .db 0b00100100 ; o o + .db 0b00100100 ; o o + .db 0b11100111 ; ooo ooo + .db 0b10000001 ; o o + .db 0b01000010 ; o o + .db 0b00100100 ; o o + .db 0b00011000 ; oo + +; Character: ? (03) + .db 0b00011000 ; oo + .db 0b00010100 ; o o + .db 0b11110010 ; oooo o + .db 0b10000001 ; o o + .db 0b10000001 ; o o + .db 0b11110010 ; oooo o + .db 0b00010100 ; o o + .db 0b00011000 ; oo + +; Character: ? (04) + .db 0b00011000 ; oo + .db 0b00101000 ; o o + .db 0b01001111 ; o oooo + .db 0b10000001 ; o o + .db 0b10000001 ; o o + .db 0b01001111 ; o oooo + .db 0b00101000 ; o o + .db 0b00011000 ; oo + +; Character: ? (05) + .db 0b11111111 ; oooooooo + .db 0b10000001 ; o o + .db 0b10000001 ; o o + .db 0b10000001 ; o o + .db 0b10000001 ; o o + .db 0b10000001 ; o o + .db 0b10000001 ; o o + .db 0b11111111 ; oooooooo + +; Character: ? (06) + .db 0b11111000 ; ooooo + .db 0b10001000 ; o o + .db 0b10001111 ; o oooo + .db 0b10001001 ; o o o + .db 0b11111001 ; ooooo o + .db 0b01000001 ; o o + .db 0b01000001 ; o o + .db 0b01111111 ; ooooooo + +; Character: ? (07) + .db 0b11111111 ; oooooooo + .db 0b10001001 ; o o o + .db 0b10001001 ; o o o + .db 0b10001001 ; o o o + .db 0b11111001 ; ooooo o + .db 0b10000001 ; o o + .db 0b10000001 ; o o + .db 0b11111111 ; oooooooo + +; Character: ? (08) + .db 0b00000001 ; o + .db 0b00000011 ; oo + .db 0b00000110 ; oo + .db 0b10001100 ; o oo + .db 0b11011000 ; oo oo + .db 0b01110000 ; ooo + .db 0b00100000 ; o + .db 0b00000000 ; + +; Character: ? (09) + .db 0b01111110 ; oooooo + .db 0b11000011 ; oo oo + .db 0b11010011 ; oo o oo + .db 0b11010011 ; oo o oo + .db 0b11011011 ; oo oo oo + .db 0b11000011 ; oo oo + .db 0b11000011 ; oo oo + .db 0b01111110 ; oooooo + +; Character: ? (0A) + .db 0b00011000 ; oo + .db 0b00111100 ; oooo + .db 0b00101100 ; o oo + .db 0b00101100 ; o oo + .db 0b01111110 ; oooooo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + +; Character: ? (0B) + .db 0b00010000 ; o + .db 0b00011100 ; ooo + .db 0b00010010 ; o o + .db 0b00010000 ; o + .db 0b00010000 ; o + .db 0b01110000 ; ooo + .db 0b11110000 ; oooo + .db 0b01100000 ; oo + +; Character: ? (0C) + .db 0b11110000 ; oooo + .db 0b11000000 ; oo + .db 0b11111110 ; ooooooo + .db 0b11011000 ; oo oo + .db 0b11011110 ; oo oooo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + +; Character: ? (0D) + .db 0b01110000 ; ooo + .db 0b11001000 ; oo o + .db 0b11011110 ; oo oooo + .db 0b11011011 ; oo oo oo + .db 0b11011011 ; oo oo oo + .db 0b01111110 ; oooooo + .db 0b00011011 ; oo oo + .db 0b00011011 ; oo oo + +; Character: ? (0E) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b11111111 ; oooooooo + .db 0b11111111 ; oooooooo + .db 0b11111111 ; oooooooo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (0F) + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + +; Character: ? (10) + .db 0b01111100 ; ooooo + .db 0b11000110 ; oo oo + .db 0b11000110 ; oo oo + .db 0b00000000 ; + .db 0b11000110 ; oo oo + .db 0b11000110 ; oo oo + .db 0b01111100 ; ooooo + .db 0b00000000 ; + +; Character: ? (11) + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00000000 ; + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00000000 ; + +; Character: ? (12) + .db 0b01111100 ; ooooo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b01111100 ; ooooo + .db 0b11000000 ; oo + .db 0b11000000 ; oo + .db 0b01111100 ; ooooo + .db 0b00000000 ; + +; Character: ? (13) + .db 0b01111100 ; ooooo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b01111100 ; ooooo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b01111100 ; ooooo + .db 0b00000000 ; + +; Character: ? (14) + .db 0b11000110 ; oo oo + .db 0b11000110 ; oo oo + .db 0b11000110 ; oo oo + .db 0b01111100 ; ooooo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00000000 ; + +; Character: ? (15) + .db 0b01111100 ; ooooo + .db 0b11000000 ; oo + .db 0b11000000 ; oo + .db 0b01111100 ; ooooo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b01111100 ; ooooo + .db 0b00000000 ; + +; Character: ? (16) + .db 0b01111100 ; ooooo + .db 0b11000000 ; oo + .db 0b11000000 ; oo + .db 0b01111100 ; ooooo + .db 0b11000110 ; oo oo + .db 0b11000110 ; oo oo + .db 0b01111100 ; ooooo + .db 0b00000000 ; + +; Character: ? (17) + .db 0b01111100 ; ooooo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00000000 ; + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00000000 ; + +; Character: ? (18) + .db 0b01111100 ; ooooo + .db 0b11000110 ; oo oo + .db 0b11000110 ; oo oo + .db 0b01111100 ; ooooo + .db 0b11000110 ; oo oo + .db 0b11000110 ; oo oo + .db 0b01111100 ; ooooo + .db 0b00000000 ; + +; Character: ? (19) + .db 0b01111100 ; ooooo + .db 0b11000110 ; oo oo + .db 0b11000110 ; oo oo + .db 0b01111100 ; ooooo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b01111100 ; ooooo + .db 0b00000000 ; + +; Character: ? (1A) + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01000110 ; o oo + .db 0b00000110 ; oo + .db 0b01111110 ; oooooo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: ? (1B) + .db 0b01111000 ; oooo + .db 0b01100110 ; oo oo + .db 0b01111101 ; ooooo o + .db 0b01100100 ; oo o + .db 0b01111110 ; oooooo + .db 0b00000011 ; oo + .db 0b00001011 ; o oo + .db 0b00000110 ; oo + +; Character: ? (1C) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00011111 ; ooooo + .db 0b00011111 ; ooooo + .db 0b00011111 ; ooooo + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + +; Character: ? (1D) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b11111100 ; oooooo + .db 0b11111100 ; oooooo + .db 0b11111100 ; oooooo + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + +; Character: ? (1E) + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + .db 0b00011111 ; ooooo + .db 0b00011111 ; ooooo + .db 0b00011111 ; ooooo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (1F) + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + .db 0b11111100 ; oooooo + .db 0b11111100 ; oooooo + .db 0b11111100 ; oooooo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: (20) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ! (21) + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + .db 0b00011000 ; oo + .db 0b00000000 ; + +; Character: " (22) + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01000100 ; o o + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: # (23) + .db 0b00000000 ; + .db 0b00100100 ; o o + .db 0b01111110 ; oooooo + .db 0b00100100 ; o o + .db 0b00100100 ; o o + .db 0b01111110 ; oooooo + .db 0b00100100 ; o o + .db 0b00000000 ; + +; Character: $ (24) + .db 0b00010100 ; o o + .db 0b00111110 ; ooooo + .db 0b01010101 ; o o o o + .db 0b00111100 ; oooo + .db 0b00011110 ; oooo + .db 0b01010101 ; o o o o + .db 0b00111110 ; ooooo + .db 0b00010100 ; o o + +; Character: % (25) + .db 0b01100010 ; oo o + .db 0b01100110 ; oo oo + .db 0b00001100 ; oo + .db 0b00011000 ; oo + .db 0b00110000 ; oo + .db 0b01100110 ; oo oo + .db 0b01000110 ; o oo + .db 0b00000000 ; + +; Character: & (26) + .db 0b01111000 ; oooo + .db 0b11001100 ; oo oo + .db 0b01100001 ; oo o + .db 0b11001110 ; oo ooo + .db 0b11001100 ; oo oo + .db 0b11001100 ; oo oo + .db 0b01111000 ; oooo + .db 0b00000000 ; + +; Character: ' (27) + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00010000 ; o + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ( (28) + .db 0b00000100 ; o + .db 0b00001000 ; o + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00001000 ; o + .db 0b00000100 ; o + +; Character: ) (29) + .db 0b00100000 ; o + .db 0b00010000 ; o + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00010000 ; o + .db 0b00100000 ; o + +; Character: * (2A) + .db 0b00000000 ; + .db 0b01010100 ; o o o + .db 0b00111000 ; ooo + .db 0b11111110 ; ooooooo + .db 0b00111000 ; ooo + .db 0b01010100 ; o o o + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: + (2B) + .db 0b00000000 ; + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b01111110 ; oooooo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: , (2C) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00110000 ; oo + .db 0b00110000 ; oo + .db 0b00100000 ; o + +; Character: - (2D) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: . (2E) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + +; Character: / (2F) + .db 0b00000011 ; oo + .db 0b00000110 ; oo + .db 0b00001100 ; oo + .db 0b00011000 ; oo + .db 0b00110000 ; oo + .db 0b01100000 ; oo + .db 0b11000000 ; oo + .db 0b00000000 ; + +; Character: 0 (30) + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01101110 ; oo ooo + .db 0b01110110 ; ooo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: 1 (31) + .db 0b00011000 ; oo + .db 0b00111000 ; ooo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + +; Character: 2 (32) + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b00001110 ; ooo + .db 0b00011100 ; ooo + .db 0b00111000 ; ooo + .db 0b01110000 ; ooo + .db 0b01111110 ; oooooo + .db 0b00000000 ; + +; Character: 3 (33) + .db 0b01111110 ; oooooo + .db 0b00001100 ; oo + .db 0b00011000 ; oo + .db 0b00111100 ; oooo + .db 0b00000110 ; oo + .db 0b01000110 ; o oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: 4 (34) + .db 0b00001100 ; oo + .db 0b00011100 ; ooo + .db 0b00101100 ; o oo + .db 0b01001100 ; o oo + .db 0b01111110 ; oooooo + .db 0b00001100 ; oo + .db 0b00001100 ; oo + .db 0b00000000 ; + +; Character: 5 (35) + .db 0b01111110 ; oooooo + .db 0b01100000 ; oo + .db 0b01111100 ; ooooo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b01000110 ; o oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: 6 (36) + .db 0b00011100 ; ooo + .db 0b00100000 ; o + .db 0b01100000 ; oo + .db 0b01111100 ; ooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: 7 (37) + .db 0b01111110 ; oooooo + .db 0b00000110 ; oo + .db 0b00001110 ; ooo + .db 0b00011100 ; ooo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + +; Character: 8 (38) + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: 9 (39) + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111110 ; ooooo + .db 0b00000110 ; oo + .db 0b00001100 ; oo + .db 0b00111000 ; ooo + .db 0b00000000 ; + +; Character: : (3A) + .db 0b00000000 ; + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + +; Character: ; (3B) + .db 0b00000000 ; + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00010000 ; o + .db 0b00000000 ; + +; Character: < (3C) + .db 0b00000110 ; oo + .db 0b00001100 ; oo + .db 0b00011000 ; oo + .db 0b00110000 ; oo + .db 0b00011000 ; oo + .db 0b00001100 ; oo + .db 0b00000110 ; oo + .db 0b00000000 ; + +; Character: = (3D) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: > (3E) + .db 0b01100000 ; oo + .db 0b00110000 ; oo + .db 0b00011000 ; oo + .db 0b00001100 ; oo + .db 0b00011000 ; oo + .db 0b00110000 ; oo + .db 0b01100000 ; oo + .db 0b00000000 ; + +; Character: ? (3F) + .db 0b00111100 ; oooo + .db 0b01000110 ; o oo + .db 0b00000110 ; oo + .db 0b00001100 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + .db 0b00011000 ; oo + +; Character: @ (40) + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01101110 ; oo ooo + .db 0b01101010 ; oo o o + .db 0b01101110 ; oo ooo + .db 0b01100000 ; oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: A (41) + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01111110 ; oooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00000000 ; + +; Character: B (42) + .db 0b01111100 ; ooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01111100 ; ooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01111100 ; ooooo + .db 0b00000000 ; + +; Character: C (43) + .db 0b00111100 ; oooo + .db 0b01100010 ; oo o + .db 0b01100000 ; oo + .db 0b01100000 ; oo + .db 0b01100000 ; oo + .db 0b01100010 ; oo o + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: D (44) + .db 0b01111100 ; ooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01111100 ; ooooo + .db 0b00000000 ; + +; Character: E (45) + .db 0b01111110 ; oooooo + .db 0b01100000 ; oo + .db 0b01100000 ; oo + .db 0b01111100 ; ooooo + .db 0b01100000 ; oo + .db 0b01100000 ; oo + .db 0b01111110 ; oooooo + .db 0b00000000 ; + +; Character: F (46) + .db 0b01111110 ; oooooo + .db 0b01100000 ; oo + .db 0b01100000 ; oo + .db 0b01111100 ; ooooo + .db 0b01100000 ; oo + .db 0b01100000 ; oo + .db 0b01100000 ; oo + .db 0b00000000 ; + +; Character: G (47) + .db 0b00111100 ; oooo + .db 0b01100010 ; oo o + .db 0b01100000 ; oo + .db 0b01101110 ; oo ooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111110 ; ooooo + .db 0b00000000 ; + +; Character: H (48) + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01111110 ; oooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00000000 ; + +; Character: I (49) + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + +; Character: J (4A) + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b01000110 ; o oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: K (4B) + .db 0b01100110 ; oo oo + .db 0b01101100 ; oo oo + .db 0b01111000 ; oooo + .db 0b01110000 ; ooo + .db 0b01111000 ; oooo + .db 0b01101100 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00000000 ; + +; Character: L (4C) + .db 0b01100000 ; oo + .db 0b01100000 ; oo + .db 0b01100000 ; oo + .db 0b01100000 ; oo + .db 0b01100000 ; oo + .db 0b01100000 ; oo + .db 0b01111100 ; ooooo + .db 0b00000000 ; + +; Character: M (4D) + .db 0b11111100 ; oooooo + .db 0b11010110 ; oo o oo + .db 0b11010110 ; oo o oo + .db 0b11010110 ; oo o oo + .db 0b11010110 ; oo o oo + .db 0b11000110 ; oo oo + .db 0b11000110 ; oo oo + .db 0b00000000 ; + +; Character: N (4E) + .db 0b01100010 ; oo o + .db 0b01110010 ; ooo o + .db 0b01111010 ; oooo o + .db 0b01011110 ; o oooo + .db 0b01001110 ; o ooo + .db 0b01000110 ; o oo + .db 0b01000010 ; o o + .db 0b00000000 ; + +; Character: O (4F) + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: P (50) + .db 0b01111100 ; ooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01111100 ; ooooo + .db 0b01100000 ; oo + .db 0b01100000 ; oo + .db 0b01100000 ; oo + .db 0b00000000 ; + +; Character: Q (51) + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b00000110 ; oo + +; Character: R (52) + .db 0b01111100 ; ooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01111100 ; ooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00000000 ; + +; Character: S (53) + .db 0b00111100 ; oooo + .db 0b01100010 ; oo o + .db 0b01110000 ; ooo + .db 0b00111100 ; oooo + .db 0b00001110 ; ooo + .db 0b01000110 ; o oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: T (54) + .db 0b01111110 ; oooooo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + +; Character: U (55) + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: V (56) + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100100 ; oo o + .db 0b01111000 ; oooo + .db 0b00000000 ; + +; Character: W (57) + .db 0b11000110 ; oo oo + .db 0b11000110 ; oo oo + .db 0b11000110 ; oo oo + .db 0b11010110 ; oo o oo + .db 0b11010110 ; oo o oo + .db 0b11010110 ; oo o oo + .db 0b11111100 ; oooooo + .db 0b00000000 ; + +; Character: X (58) + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00000000 ; + +; Character: Y (59) + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + +; Character: Z (5A) + .db 0b01111110 ; oooooo + .db 0b00001110 ; ooo + .db 0b00011100 ; ooo + .db 0b00111000 ; ooo + .db 0b01110000 ; ooo + .db 0b01100000 ; oo + .db 0b01111110 ; oooooo + .db 0b00000000 ; + +; Character: [ (5B) + .db 0b00011110 ; oooo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011110 ; oooo + .db 0b00000000 ; + +; Character: \ (5C) + .db 0b01000000 ; o + .db 0b01100000 ; oo + .db 0b00110000 ; oo + .db 0b00011000 ; oo + .db 0b00001100 ; oo + .db 0b00000110 ; oo + .db 0b00000010 ; o + .db 0b00000000 ; + +; Character: ] (5D) + .db 0b01111000 ; oooo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b01111000 ; oooo + .db 0b00000000 ; + +; Character: ^ (5E) + .db 0b00010000 ; o + .db 0b00111000 ; ooo + .db 0b01101100 ; oo oo + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: _ (5F) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b01111110 ; oooooo + .db 0b00000000 ; + +; Character: ` (60) + .db 0b00000000 ; + .db 0b11000000 ; oo + .db 0b11000000 ; oo + .db 0b01100000 ; oo + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: a (61) + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01000110 ; o oo + .db 0b00111110 ; ooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111110 ; ooooo + .db 0b00000000 ; + +; Character: b (62) + .db 0b01100000 ; oo + .db 0b01111100 ; ooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01111100 ; ooooo + .db 0b00000000 ; + +; Character: c (63) + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01100010 ; oo o + .db 0b01100000 ; oo + .db 0b01100000 ; oo + .db 0b01100010 ; oo o + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: d (64) + .db 0b00000110 ; oo + .db 0b00111110 ; ooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111110 ; ooooo + .db 0b00000000 ; + +; Character: e (65) + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01111110 ; oooooo + .db 0b01100000 ; oo + .db 0b01100010 ; oo o + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: f (66) + .db 0b00011110 ; oooo + .db 0b00110000 ; oo + .db 0b01111100 ; ooooo + .db 0b00110000 ; oo + .db 0b00110000 ; oo + .db 0b00110000 ; oo + .db 0b00110000 ; oo + .db 0b00000000 ; + +; Character: g (67) + .db 0b00000000 ; + .db 0b00111110 ; ooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111110 ; ooooo + .db 0b01000110 ; o oo + .db 0b00111100 ; oooo + +; Character: h (68) + .db 0b01100000 ; oo + .db 0b01111100 ; ooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00000000 ; + +; Character: i (69) + .db 0b00011000 ; oo + .db 0b00000000 ; + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + +; Character: j (6A) + .db 0b00000000 ; + .db 0b00001000 ; o + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b01011000 ; o oo + .db 0b00110000 ; oo + +; Character: k (6B) + .db 0b01100000 ; oo + .db 0b01100100 ; oo o + .db 0b01101000 ; oo o + .db 0b01110000 ; ooo + .db 0b01111000 ; oooo + .db 0b01101100 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00000000 ; + +; Character: l (6C) + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00001100 ; oo + .db 0b00000000 ; + +; Character: m (6D) + .db 0b00000000 ; + .db 0b11111100 ; oooooo + .db 0b11010110 ; oo o oo + .db 0b11010110 ; oo o oo + .db 0b11010110 ; oo o oo + .db 0b11010110 ; oo o oo + .db 0b11000110 ; oo oo + .db 0b00000000 ; + +; Character: n (6E) + .db 0b00000000 ; + .db 0b01111100 ; ooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00000000 ; + +; Character: o (6F) + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: p (70) + .db 0b00000000 ; + .db 0b01111100 ; ooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01111100 ; ooooo + .db 0b01100000 ; oo + .db 0b01100000 ; oo + +; Character: q (71) + .db 0b00000000 ; + .db 0b00111110 ; ooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111110 ; ooooo + .db 0b00000110 ; oo + +; Character: r (72) + .db 0b00000000 ; + .db 0b01101100 ; oo oo + .db 0b01110000 ; ooo + .db 0b01100000 ; oo + .db 0b01100000 ; oo + .db 0b01100000 ; oo + .db 0b01100000 ; oo + .db 0b00000000 ; + +; Character: s (73) + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01110010 ; ooo o + .db 0b00111000 ; ooo + .db 0b00011100 ; ooo + .db 0b01001110 ; o ooo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: t (74) + .db 0b00011000 ; oo + .db 0b00111100 ; oooo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00001100 ; oo + .db 0b00000000 ; + +; Character: u (75) + .db 0b00000000 ; + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111110 ; ooooo + .db 0b00000000 ; + +; Character: v (76) + .db 0b00000000 ; + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100100 ; oo o + .db 0b01111000 ; oooo + .db 0b00000000 ; + +; Character: w (77) + .db 0b00000000 ; + .db 0b11000110 ; oo oo + .db 0b11000110 ; oo oo + .db 0b11010110 ; oo o oo + .db 0b11010110 ; oo o oo + .db 0b11010110 ; oo o oo + .db 0b11111100 ; oooooo + .db 0b00000000 ; + +; Character: x (78) + .db 0b00000000 ; + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00000000 ; + +; Character: y (79) + .db 0b00000000 ; + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00100110 ; o oo + .db 0b00011110 ; oooo + .db 0b01000110 ; o oo + .db 0b00111100 ; oooo + +; Character: z (7A) + .db 0b00000000 ; + .db 0b01111110 ; oooooo + .db 0b00001110 ; ooo + .db 0b00011100 ; ooo + .db 0b00111000 ; ooo + .db 0b01110000 ; ooo + .db 0b01111110 ; oooooo + .db 0b00000000 ; + +; Character: { (7B) + .db 0b00001110 ; ooo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00110000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00001110 ; ooo + .db 0b00000000 ; + +; Character: | (7C) + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + +; Character: } (7D) + .db 0b01110000 ; ooo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00001100 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b01110000 ; ooo + .db 0b00000000 ; + +; Character: ~ (7E) + .db 0b00000000 ; + .db 0b01100000 ; oo + .db 0b11110010 ; oooo o + .db 0b10011110 ; o oooo + .db 0b00001100 ; oo + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (7F) + .db 0b00010000 ; o + .db 0b00010000 ; o + .db 0b00101000 ; o o + .db 0b00101000 ; o o + .db 0b01000100 ; o o + .db 0b01000100 ; o o + .db 0b10000010 ; o o + .db 0b11111110 ; ooooooo + +; Character: ? (80) + .db 0b00111100 ; oooo + .db 0b01100010 ; oo o + .db 0b01100000 ; oo + .db 0b01100000 ; oo + .db 0b01100000 ; oo + .db 0b01100010 ; oo o + .db 0b00011100 ; ooo + .db 0b00110000 ; oo + +; Character: ? (81) + .db 0b00100100 ; o o + .db 0b00000000 ; + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111110 ; ooooo + .db 0b00000000 ; + +; Character: ? (82) + .db 0b00001100 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01111110 ; oooooo + .db 0b01100000 ; oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: ? (83) + .db 0b00011000 ; oo + .db 0b01100110 ; oo oo + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b00000110 ; oo + .db 0b01111110 ; oooooo + .db 0b00111110 ; ooooo + .db 0b00000000 ; + +; Character: ? (84) + .db 0b00100100 ; o o + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01000110 ; o oo + .db 0b00111110 ; ooooo + .db 0b01000110 ; o oo + .db 0b00111110 ; ooooo + .db 0b00000000 ; + +; Character: ? (85) + .db 0b00110000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b00000110 ; oo + .db 0b01111110 ; oooooo + .db 0b00111110 ; ooooo + .db 0b00000000 ; + +; Character: ? (86) + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b00000110 ; oo + .db 0b01111110 ; oooooo + .db 0b00111110 ; ooooo + .db 0b00000000 ; + +; Character: ? (87) + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01100010 ; oo o + .db 0b01100000 ; oo + .db 0b01100010 ; oo o + .db 0b00111100 ; oooo + .db 0b00001000 ; o + .db 0b00011000 ; oo + +; Character: ? (88) + .db 0b00011000 ; oo + .db 0b00110100 ; oo o + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01111110 ; oooooo + .db 0b01100000 ; oo + .db 0b00111110 ; ooooo + .db 0b00000000 ; + +; Character: ? (89) + .db 0b00100100 ; o o + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01111110 ; oooooo + .db 0b01100000 ; oo + .db 0b00111110 ; ooooo + .db 0b00000000 ; + +; Character: ? (8A) + .db 0b00110000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01111110 ; oooooo + .db 0b01100000 ; oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: ? (8B) + .db 0b00100100 ; o o + .db 0b00000000 ; + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + +; Character: ? (8C) + .db 0b00011000 ; oo + .db 0b00100100 ; o o + .db 0b00000000 ; + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + +; Character: ? (8D) + .db 0b00010000 ; o + .db 0b00001000 ; o + .db 0b00000000 ; + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + +; Character: ? (8E) + .db 0b00100100 ; o o + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01111110 ; oooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00000000 ; + +; Character: ? (8F) + .db 0b00011000 ; oo + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01111110 ; oooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00000000 ; + +; Character: ? (90) + .db 0b00001100 ; oo + .db 0b00011000 ; oo + .db 0b01111110 ; oooooo + .db 0b01100000 ; oo + .db 0b01111100 ; ooooo + .db 0b01100000 ; oo + .db 0b01111110 ; oooooo + .db 0b00000000 ; + +; Character: ? (91) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b01111110 ; oooooo + .db 0b00011011 ; oo oo + .db 0b01111111 ; ooooooo + .db 0b11011000 ; oo oo + .db 0b01111110 ; oooooo + .db 0b00000000 ; + +; Character: ? (92) + .db 0b00111111 ; oooooo + .db 0b01111000 ; oooo + .db 0b11011000 ; oo oo + .db 0b11011110 ; oo oooo + .db 0b11111000 ; ooooo + .db 0b11011000 ; oo oo + .db 0b11011111 ; oo ooooo + .db 0b00000000 ; + +; Character: ? (93) + .db 0b00011000 ; oo + .db 0b00110100 ; oo o + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: ? (94) + .db 0b00100100 ; o o + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: ? (95) + .db 0b00110000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: ? (96) + .db 0b00011000 ; oo + .db 0b00100100 ; o o + .db 0b00000000 ; + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: ? (97) + .db 0b00110000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: ? (98) + .db 0b01100110 ; oo oo + .db 0b00000000 ; + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111110 ; ooooo + .db 0b01000110 ; o oo + .db 0b00111100 ; oooo + +; Character: ? (99) + .db 0b01100110 ; oo oo + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: ? (9A) + .db 0b01100110 ; oo oo + .db 0b00000000 ; + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: ? (9B) + .db 0b00011000 ; oo + .db 0b00111100 ; oooo + .db 0b01100010 ; oo o + .db 0b01100000 ; oo + .db 0b01100000 ; oo + .db 0b01100010 ; oo o + .db 0b00111100 ; oooo + .db 0b00011000 ; oo + +; Character: ? (9C) + .db 0b00011100 ; ooo + .db 0b00111010 ; ooo o + .db 0b00110000 ; oo + .db 0b01111100 ; ooooo + .db 0b00110000 ; oo + .db 0b00110000 ; oo + .db 0b01111110 ; oooooo + .db 0b00000000 ; + +; Character: ? (9D) + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b00011000 ; oo + .db 0b00111100 ; oooo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + +; Character: ? (9E) + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01101100 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b11101100 ; ooo oo + .db 0b00000000 ; + +; Character: ? (9F) + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + +; Character: ? (A0) + .db 0b00001100 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b00000110 ; oo + .db 0b01111110 ; oooooo + .db 0b00111110 ; ooooo + .db 0b00000000 ; + +; Character: ? (A1) + .db 0b00001100 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + +; Character: ? (A2) + .db 0b00001100 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: ? (A3) + .db 0b00001100 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111110 ; ooooo + .db 0b00000000 ; + +; Character: ? (A4) + .db 0b00110100 ; oo o + .db 0b01011000 ; o oo + .db 0b00000000 ; + .db 0b01111100 ; ooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00000000 ; + +; Character: ? (A5) + .db 0b00011010 ; oo o + .db 0b00101100 ; o oo + .db 0b01100010 ; oo o + .db 0b01110010 ; ooo o + .db 0b01011010 ; o oo o + .db 0b01001110 ; o ooo + .db 0b01000110 ; o oo + .db 0b00000000 ; + +; Character: ? (A6) + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01000110 ; o oo + .db 0b00111110 ; ooooo + .db 0b01100110 ; oo oo + .db 0b00111110 ; ooooo + .db 0b00000000 ; + .db 0b01111110 ; oooooo + +; Character: ? (A7) + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + .db 0b01111110 ; oooooo + +; Character: ? (A8) + .db 0b00000000 ; + .db 0b00011000 ; oo + .db 0b00000000 ; + .db 0b00011000 ; oo + .db 0b00110000 ; oo + .db 0b01100000 ; oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + +; Character: ? (A9) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00111110 ; ooooo + .db 0b00110000 ; oo + .db 0b00110000 ; oo + .db 0b00110000 ; oo + .db 0b00000000 ; + +; Character: ? (AA) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b01111100 ; ooooo + .db 0b00001100 ; oo + .db 0b00001100 ; oo + .db 0b00001100 ; oo + .db 0b00000000 ; + +; Character: ? (AB) + .db 0b01100010 ; oo o + .db 0b11100100 ; ooo o + .db 0b01101000 ; oo o + .db 0b01110110 ; ooo oo + .db 0b00101011 ; o o oo + .db 0b01000011 ; o oo + .db 0b10000110 ; o oo + .db 0b00001111 ; oooo + +; Character: ? (AC) + .db 0b01100010 ; oo o + .db 0b11100100 ; ooo o + .db 0b01101000 ; oo o + .db 0b01110110 ; ooo oo + .db 0b00101110 ; o ooo + .db 0b01010110 ; o o oo + .db 0b10011111 ; o ooooo + .db 0b00000110 ; oo + +; Character: ? (AD) + .db 0b00000000 ; + .db 0b00011000 ; oo + .db 0b00000000 ; + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + +; Character: ? (AE) + .db 0b00011011 ; oo oo + .db 0b00110110 ; oo oo + .db 0b01101100 ; oo oo + .db 0b11011000 ; oo oo + .db 0b01101100 ; oo oo + .db 0b00110110 ; oo oo + .db 0b00011011 ; oo oo + .db 0b00000000 ; + +; Character: ? (AF) + .db 0b11011000 ; oo oo + .db 0b01101100 ; oo oo + .db 0b00110110 ; oo oo + .db 0b00011011 ; oo oo + .db 0b00110110 ; oo oo + .db 0b01101100 ; oo oo + .db 0b11011000 ; oo oo + .db 0b00000000 ; + +; Character: ? (B0) + .db 0b00110100 ; oo o + .db 0b01011000 ; o oo + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b00000110 ; oo + .db 0b01111110 ; oooooo + .db 0b00111110 ; ooooo + .db 0b00000000 ; + +; Character: ? (B1) + .db 0b00110100 ; oo o + .db 0b01011000 ; o oo + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: ? (B2) + .db 0b00000010 ; o + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01101110 ; oo ooo + .db 0b01110110 ; ooo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b01000000 ; o + +; Character: ? (B3) + .db 0b00000000 ; + .db 0b00000010 ; o + .db 0b00111100 ; oooo + .db 0b01101110 ; oo ooo + .db 0b01110110 ; ooo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b01000000 ; o + +; Character: ? (B4) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b01111110 ; oooooo + .db 0b11011011 ; oo oo oo + .db 0b11011110 ; oo oooo + .db 0b11011000 ; oo oo + .db 0b01111111 ; ooooooo + .db 0b00000000 ; + +; Character: ? (B5) + .db 0b00000000 ; + .db 0b01111110 ; oooooo + .db 0b11011000 ; oo oo + .db 0b11011000 ; oo oo + .db 0b11111100 ; oooooo + .db 0b11011000 ; oo oo + .db 0b11011000 ; oo oo + .db 0b11011110 ; oo oooo + +; Character: ? (B6) + .db 0b00100000 ; o + .db 0b00010000 ; o + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01111110 ; oooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + +; Character: ? (B7) + .db 0b00110100 ; oo o + .db 0b01011000 ; o oo + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01111110 ; oooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + +; Character: ? (B8) + .db 0b00110100 ; oo o + .db 0b01011000 ; o oo + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + +; Character: ? (B9) + .db 0b01100110 ; oo oo + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (BA) + .db 0b00001100 ; oo + .db 0b00011000 ; oo + .db 0b00110000 ; oo + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (BB) + .db 0b00000000 ; + .db 0b00010000 ; o + .db 0b00111000 ; ooo + .db 0b00010000 ; o + .db 0b00010000 ; o + .db 0b00010000 ; o + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (BC) + .db 0b01111010 ; oooo o + .db 0b11001010 ; oo o o + .db 0b11001010 ; oo o o + .db 0b11001010 ; oo o o + .db 0b01111010 ; oooo o + .db 0b00001010 ; o o + .db 0b00001010 ; o o + .db 0b00001010 ; o o + +; Character: ? (BD) + .db 0b00111100 ; oooo + .db 0b01000010 ; o o + .db 0b10011001 ; o oo o + .db 0b10110101 ; o oo o o + .db 0b10110001 ; o oo o + .db 0b10011101 ; o ooo o + .db 0b01000010 ; o o + .db 0b00111100 ; oooo + +; Character: ? (BE) + .db 0b00111100 ; oooo + .db 0b01000010 ; o o + .db 0b10111001 ; o ooo o + .db 0b10110101 ; o oo o o + .db 0b10111001 ; o ooo o + .db 0b10110101 ; o oo o o + .db 0b01000010 ; o o + .db 0b00111100 ; oooo + +; Character: ? (BF) + .db 0b11110001 ; oooo o + .db 0b01011011 ; o oo oo + .db 0b01010101 ; o o o o + .db 0b01010001 ; o o o + .db 0b01010001 ; o o o + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (C0) + .db 0b01100110 ; oo oo + .db 0b00000000 ; + .db 0b11100110 ; ooo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b11110110 ; oooo oo + .db 0b00000110 ; oo + .db 0b00011100 ; ooo + +; Character: ? (C1) + .db 0b11110110 ; oooo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b11110110 ; oooo oo + .db 0b00000110 ; oo + .db 0b00011100 ; ooo + +; Character: ? (C2) + .db 0b00000000 ; + .db 0b01100110 ; oo oo + .db 0b01110110 ; ooo oo + .db 0b00111100 ; oooo + .db 0b01101110 ; oo ooo + .db 0b01100110 ; oo oo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (C3) + .db 0b00000000 ; + .db 0b01111100 ; ooooo + .db 0b00001100 ; oo + .db 0b00001100 ; oo + .db 0b00001100 ; oo + .db 0b01111110 ; oooooo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (C4) + .db 0b00000000 ; + .db 0b00011110 ; oooo + .db 0b00000110 ; oo + .db 0b00001110 ; ooo + .db 0b00011110 ; oooo + .db 0b00110110 ; oo oo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (C5) + .db 0b00000000 ; + .db 0b01111110 ; oooooo + .db 0b00001100 ; oo + .db 0b00001100 ; oo + .db 0b00001100 ; oo + .db 0b00001100 ; oo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (C6) + .db 0b00000000 ; + .db 0b01111100 ; ooooo + .db 0b00000110 ; oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (C7) + .db 0b00000000 ; + .db 0b00011100 ; ooo + .db 0b00001100 ; oo + .db 0b00001100 ; oo + .db 0b00001100 ; oo + .db 0b00001100 ; oo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (C8) + .db 0b00000000 ; + .db 0b00011110 ; oooo + .db 0b00001100 ; oo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (C9) + .db 0b00000000 ; + .db 0b01111110 ; oooooo + .db 0b00110110 ; oo oo + .db 0b00110110 ; oo oo + .db 0b00110110 ; oo oo + .db 0b00110110 ; oo oo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (CA) + .db 0b01100000 ; oo + .db 0b01101110 ; oo ooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01111110 ; oooooo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (CB) + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b00001100 ; oo + .db 0b00001100 ; oo + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (CC) + .db 0b00000000 ; + .db 0b00111110 ; ooooo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00111110 ; ooooo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (CD) + .db 0b01100000 ; oo + .db 0b01111110 ; oooooo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00001110 ; ooo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (CE) + .db 0b00000000 ; + .db 0b01101100 ; oo oo + .db 0b00111110 ; ooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01101110 ; oo ooo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (CF) + .db 0b00000000 ; + .db 0b00011100 ; ooo + .db 0b00001100 ; oo + .db 0b00001100 ; oo + .db 0b00001100 ; oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (D0) + .db 0b00000000 ; + .db 0b00111110 ; ooooo + .db 0b00110110 ; oo oo + .db 0b00110110 ; oo oo + .db 0b00110110 ; oo oo + .db 0b00011100 ; ooo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (D1) + .db 0b00000000 ; + .db 0b00110110 ; oo oo + .db 0b00110110 ; oo oo + .db 0b00110110 ; oo oo + .db 0b00110110 ; oo oo + .db 0b01111110 ; oooooo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (D2) + .db 0b00000000 ; + .db 0b01111110 ; oooooo + .db 0b01100110 ; oo oo + .db 0b01110110 ; ooo oo + .db 0b00000110 ; oo + .db 0b01111110 ; oooooo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (D3) + .db 0b00000000 ; + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b00001110 ; ooo + .db 0b01111110 ; oooooo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (D4) + .db 0b00000000 ; + .db 0b00111110 ; ooooo + .db 0b00000110 ; oo + .db 0b00110110 ; oo oo + .db 0b00110110 ; oo oo + .db 0b00110100 ; oo o + .db 0b00110000 ; oo + .db 0b00000000 ; + +; Character: ? (D5) + .db 0b00000000 ; + .db 0b01111000 ; oooo + .db 0b00001100 ; oo + .db 0b00001100 ; oo + .db 0b00001100 ; oo + .db 0b00001100 ; oo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (D6) + .db 0b00000000 ; + .db 0b11010110 ; oo o oo + .db 0b11010110 ; oo o oo + .db 0b11010110 ; oo o oo + .db 0b11010110 ; oo o oo + .db 0b11111110 ; ooooooo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (D7) + .db 0b00000000 ; + .db 0b01111100 ; ooooo + .db 0b01101100 ; oo oo + .db 0b01101100 ; oo oo + .db 0b01101100 ; oo oo + .db 0b11101100 ; ooo oo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (D8) + .db 0b00000000 ; + .db 0b00011100 ; ooo + .db 0b00001100 ; oo + .db 0b00001100 ; oo + .db 0b00001100 ; oo + .db 0b00001100 ; oo + .db 0b00001100 ; oo + .db 0b00000000 ; + +; Character: ? (D9) + .db 0b00000000 ; + .db 0b00111110 ; ooooo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00000000 ; + +; Character: ? (DA) + .db 0b00000000 ; + .db 0b11111110 ; ooooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01111110 ; oooooo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (DB) + .db 0b00000000 ; + .db 0b01111110 ; oooooo + .db 0b01100110 ; oo oo + .db 0b01110110 ; ooo oo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00000000 ; + +; Character: ? (DC) + .db 0b00000000 ; + .db 0b00110110 ; oo oo + .db 0b00110110 ; oo oo + .db 0b00011100 ; ooo + .db 0b00001100 ; oo + .db 0b00001100 ; oo + .db 0b00001100 ; oo + .db 0b00000000 ; + +; Character: ? (DD) + .db 0b00011100 ; ooo + .db 0b00110010 ; oo o + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b01001100 ; o oo + .db 0b00111000 ; ooo + +; Character: ? (DE) + .db 0b00000000 ; + .db 0b00010000 ; o + .db 0b00111000 ; ooo + .db 0b01101100 ; oo oo + .db 0b11000110 ; oo oo + .db 0b10000010 ; o o + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (DF) + .db 0b01100110 ; oo oo + .db 0b11110111 ; oooo ooo + .db 0b10011001 ; o oo o + .db 0b10011001 ; o oo o + .db 0b11101111 ; ooo oooo + .db 0b01100110 ; oo oo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (E0) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b01110110 ; ooo oo + .db 0b11011100 ; oo ooo + .db 0b11001000 ; oo o + .db 0b11011100 ; oo ooo + .db 0b01110110 ; ooo oo + .db 0b00000000 ; + +; Character: ? (E1) + .db 0b00011100 ; ooo + .db 0b00110110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01111100 ; ooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01111100 ; ooooo + .db 0b01100000 ; oo + +; Character: ? (E2) + .db 0b00000000 ; + .db 0b11111110 ; ooooooo + .db 0b01100110 ; oo oo + .db 0b01100010 ; oo o + .db 0b01100000 ; oo + .db 0b01100000 ; oo + .db 0b01100000 ; oo + .db 0b11111000 ; ooooo + +; Character: ? (E3) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b11111110 ; ooooooo + .db 0b01101100 ; oo oo + .db 0b01101100 ; oo oo + .db 0b01101100 ; oo oo + .db 0b01101100 ; oo oo + .db 0b01001000 ; o o + +; Character: ? (E4) + .db 0b11111110 ; ooooooo + .db 0b01100110 ; oo oo + .db 0b00110000 ; oo + .db 0b00011000 ; oo + .db 0b00110000 ; oo + .db 0b01100110 ; oo oo + .db 0b11111110 ; ooooooo + .db 0b00000000 ; + +; Character: ? (E5) + .db 0b00000000 ; + .db 0b00011110 ; oooo + .db 0b00111000 ; ooo + .db 0b01101100 ; oo oo + .db 0b01101100 ; oo oo + .db 0b01101100 ; oo oo + .db 0b00111000 ; ooo + .db 0b00000000 ; + +; Character: ? (E6) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b01101100 ; oo oo + .db 0b01101100 ; oo oo + .db 0b01101100 ; oo oo + .db 0b01101100 ; oo oo + .db 0b01111111 ; ooooooo + .db 0b11000000 ; oo + +; Character: ? (E7) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b01111110 ; oooooo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00010000 ; o + +; Character: ? (E8) + .db 0b00111100 ; oooo + .db 0b00011000 ; oo + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b00011000 ; oo + .db 0b00111100 ; oooo + +; Character: ? (E9) + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01111110 ; oooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: ? (EA) + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00100100 ; o o + .db 0b01100110 ; oo oo + .db 0b00000000 ; + +; Character: ? (EB) + .db 0b00011100 ; ooo + .db 0b00110110 ; oo oo + .db 0b01111000 ; oooo + .db 0b11011100 ; oo ooo + .db 0b11001100 ; oo oo + .db 0b11101100 ; ooo oo + .db 0b01111000 ; oooo + .db 0b00000000 ; + +; Character: ? (EC) + .db 0b00001100 ; oo + .db 0b00011000 ; oo + .db 0b00111000 ; ooo + .db 0b01010100 ; o o o + .db 0b01010100 ; o o o + .db 0b00111000 ; ooo + .db 0b00110000 ; oo + .db 0b01100000 ; oo + +; Character: ? (ED) + .db 0b00000000 ; + .db 0b00010000 ; o + .db 0b01111100 ; ooooo + .db 0b11010110 ; oo o oo + .db 0b11010110 ; oo o oo + .db 0b11010110 ; oo o oo + .db 0b01111100 ; ooooo + .db 0b00010000 ; o + +; Character: ? (EE) + .db 0b00111110 ; ooooo + .db 0b01110000 ; ooo + .db 0b01100000 ; oo + .db 0b01111110 ; oooooo + .db 0b01100000 ; oo + .db 0b01110000 ; ooo + .db 0b00111110 ; ooooo + .db 0b00000000 ; + +; Character: ? (EF) + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00000000 ; + +; Character: ? (F0) + .db 0b00000000 ; + .db 0b01111110 ; oooooo + .db 0b00000000 ; + .db 0b01111110 ; oooooo + .db 0b00000000 ; + .db 0b01111110 ; oooooo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (F1) + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b01111110 ; oooooo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + .db 0b01111110 ; oooooo + .db 0b00000000 ; + +; Character: ? (F2) + .db 0b00110000 ; oo + .db 0b00011000 ; oo + .db 0b00001100 ; oo + .db 0b00011000 ; oo + .db 0b00110000 ; oo + .db 0b00000000 ; + .db 0b01111110 ; oooooo + .db 0b00000000 ; + +; Character: ? (F3) + .db 0b00001100 ; oo + .db 0b00011000 ; oo + .db 0b00110000 ; oo + .db 0b00011000 ; oo + .db 0b00001100 ; oo + .db 0b00000000 ; + .db 0b01111110 ; oooooo + .db 0b00000000 ; + +; Character: ? (F4) + .db 0b00000000 ; + .db 0b00001110 ; ooo + .db 0b00011011 ; oo oo + .db 0b00011011 ; oo oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + +; Character: ? (F5) + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b11011000 ; oo oo + .db 0b11011000 ; oo oo + .db 0b01110000 ; ooo + .db 0b00000000 ; + +; Character: ? (F6) + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + .db 0b01111110 ; oooooo + .db 0b00000000 ; + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + +; Character: ? (F7) + .db 0b00000000 ; + .db 0b00110010 ; oo o + .db 0b01001100 ; o oo + .db 0b00000000 ; + .db 0b00110010 ; oo o + .db 0b01001100 ; o oo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (F8) + .db 0b00111000 ; ooo + .db 0b01101100 ; oo oo + .db 0b00111000 ; ooo + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (F9) + .db 0b00111000 ; ooo + .db 0b01111100 ; ooooo + .db 0b00111000 ; ooo + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (FA) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (FB) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00001111 ; oooo + .db 0b00011000 ; oo + .db 0b11011000 ; oo oo + .db 0b01110000 ; ooo + .db 0b00110000 ; oo + .db 0b00000000 ; + +; Character: ? (FC) + .db 0b00111000 ; ooo + .db 0b01101100 ; oo oo + .db 0b01101100 ; oo oo + .db 0b01101100 ; oo oo + .db 0b01101100 ; oo oo + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (FD) + .db 0b00111000 ; ooo + .db 0b01101100 ; oo oo + .db 0b00011000 ; oo + .db 0b00110000 ; oo + .db 0b01111100 ; ooooo + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (FE) + .db 0b01111000 ; oooo + .db 0b00001100 ; oo + .db 0b00111000 ; ooo + .db 0b00001100 ; oo + .db 0b01111000 ; oooo + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (FF) + .db 0b00000000 ; + .db 0b11111110 ; ooooooo + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + diff --git a/gbdk/gbdk-lib/libc/targets/sm83/f_ibm_sh.s b/gbdk/gbdk-lib/libc/targets/sm83/f_ibm_sh.s new file mode 100644 index 00000000..83e66d6b --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/f_ibm_sh.s @@ -0,0 +1,174 @@ +; ibm_fixed.ms - fixed width IBM font + + .area _HOME + + ; 898 bytes giving ' '-'0'-'@'-'A'-'Z'-'???'-'a'-'z'-127 +_font_ibm:: + .byte 1+4 ; 128 character encoding + .byte 128-32+6 ; Tiles required + + .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,96,97 ; All map to space + .byte 0,0,0,0,0,0,0,0,0,0,0,0,98,99,100,101 + .byte 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 ; 0x20 + .byte 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 + .byte 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47 ; 0x40 + .byte 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63 + .byte 64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79 ; 0x60 + .byte 80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95 + + .byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + .byte 0x18,0x18,0x18,0x18,0x18,0x00,0x18,0x00 + .byte 0x66,0x66,0x44,0x00,0x00,0x00,0x00,0x00 + .byte 0x00,0x24,0x7E,0x24,0x24,0x7E,0x24,0x00 + .byte 0x14,0x3E,0x55,0x3C,0x1E,0x55,0x3E,0x14 + .byte 0x62,0x66,0x0C,0x18,0x30,0x66,0x46,0x00 + .byte 0x78,0xCC,0x61,0xCE,0xCC,0xCC,0x78,0x00 + .byte 0x18,0x18,0x10,0x00,0x00,0x00,0x00,0x00 + .byte 0x04,0x08,0x18,0x18,0x18,0x18,0x08,0x04 + .byte 0x20,0x10,0x18,0x18,0x18,0x18,0x10,0x20 + .byte 0x00,0x54,0x38,0xFE,0x38,0x54,0x00,0x00 + .byte 0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00 + .byte 0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x20 + .byte 0x00,0x00,0x00,0x3C,0x00,0x00,0x00,0x00 + .byte 0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00 + .byte 0x03,0x06,0x0C,0x18,0x30,0x60,0xC0,0x00 + .byte 0x3C,0x66,0x6E,0x76,0x66,0x66,0x3C,0x00 + .byte 0x18,0x38,0x18,0x18,0x18,0x18,0x18,0x00 + .byte 0x3C,0x66,0x0E,0x1C,0x38,0x70,0x7E,0x00 + .byte 0x7E,0x0C,0x18,0x3C,0x06,0x46,0x3C,0x00 + .byte 0x0C,0x1C,0x2C,0x4C,0x7E,0x0C,0x0C,0x00 + .byte 0x7E,0x60,0x7C,0x06,0x06,0x46,0x3C,0x00 + .byte 0x1C,0x20,0x60,0x7C,0x66,0x66,0x3C,0x00 + .byte 0x7E,0x06,0x0E,0x1C,0x18,0x18,0x18,0x00 + .byte 0x3C,0x66,0x66,0x3C,0x66,0x66,0x3C,0x00 + .byte 0x3C,0x66,0x66,0x3E,0x06,0x0C,0x38,0x00 + .byte 0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x00 + .byte 0x00,0x18,0x18,0x00,0x18,0x18,0x10,0x00 + .byte 0x06,0x0C,0x18,0x30,0x18,0x0C,0x06,0x00 + .byte 0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00 + .byte 0x60,0x30,0x18,0x0C,0x18,0x30,0x60,0x00 + .byte 0x3C,0x46,0x06,0x0C,0x18,0x18,0x00,0x18 + .byte 0x3C,0x66,0x6E,0x6A,0x6E,0x60,0x3C,0x00 + .byte 0x3C,0x66,0x66,0x7E,0x66,0x66,0x66,0x00 + .byte 0x7C,0x66,0x66,0x7C,0x66,0x66,0x7C,0x00 + .byte 0x3C,0x62,0x60,0x60,0x60,0x62,0x3C,0x00 + .byte 0x7C,0x66,0x66,0x66,0x66,0x66,0x7C,0x00 + .byte 0x7E,0x60,0x60,0x7C,0x60,0x60,0x7E,0x00 + .byte 0x7E,0x60,0x60,0x7C,0x60,0x60,0x60,0x00 + .byte 0x3C,0x62,0x60,0x6E,0x66,0x66,0x3E,0x00 + .byte 0x66,0x66,0x66,0x7E,0x66,0x66,0x66,0x00 + .byte 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00 + .byte 0x06,0x06,0x06,0x06,0x06,0x46,0x3C,0x00 + .byte 0x66,0x6C,0x78,0x70,0x78,0x6C,0x66,0x00 + .byte 0x60,0x60,0x60,0x60,0x60,0x60,0x7C,0x00 + .byte 0xFC,0xD6,0xD6,0xD6,0xD6,0xC6,0xC6,0x00 + .byte 0x62,0x72,0x7A,0x5E,0x4E,0x46,0x42,0x00 + .byte 0x3C,0x66,0x66,0x66,0x66,0x66,0x3C,0x00 + .byte 0x7C,0x66,0x66,0x7C,0x60,0x60,0x60,0x00 + .byte 0x3C,0x66,0x66,0x66,0x66,0x66,0x3C,0x06 + .byte 0x7C,0x66,0x66,0x7C,0x66,0x66,0x66,0x00 + .byte 0x3C,0x62,0x70,0x3C,0x0E,0x46,0x3C,0x00 + .byte 0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x00 + .byte 0x66,0x66,0x66,0x66,0x66,0x66,0x3C,0x00 + .byte 0x66,0x66,0x66,0x66,0x66,0x64,0x78,0x00 + .byte 0xC6,0xC6,0xC6,0xD6,0xD6,0xD6,0xFC,0x00 + .byte 0x66,0x66,0x66,0x3C,0x66,0x66,0x66,0x00 + .byte 0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x00 + .byte 0x7E,0x0E,0x1C,0x38,0x70,0x60,0x7E,0x00 + .byte 0x1E,0x18,0x18,0x18,0x18,0x18,0x1E,0x00 + .byte 0x40,0x60,0x30,0x18,0x0C,0x06,0x02,0x00 + .byte 0x78,0x18,0x18,0x18,0x18,0x18,0x78,0x00 + .byte 0x10,0x38,0x6C,0x00,0x00,0x00,0x00,0x00 + .byte 0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00 + .byte 0x00,0xC0,0xC0,0x60,0x00,0x00,0x00,0x00 + .byte 0x00,0x3C,0x46,0x3E,0x66,0x66,0x3E,0x00 + .byte 0x60,0x7C,0x66,0x66,0x66,0x66,0x7C,0x00 + .byte 0x00,0x3C,0x62,0x60,0x60,0x62,0x3C,0x00 + .byte 0x06,0x3E,0x66,0x66,0x66,0x66,0x3E,0x00 + .byte 0x00,0x3C,0x66,0x7E,0x60,0x62,0x3C,0x00 + .byte 0x1E,0x30,0x7C,0x30,0x30,0x30,0x30,0x00 + .byte 0x00,0x3E,0x66,0x66,0x66,0x3E,0x46,0x3C + .byte 0x60,0x7C,0x66,0x66,0x66,0x66,0x66,0x00 + .byte 0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00 + .byte 0x00,0x08,0x18,0x18,0x18,0x18,0x58,0x30 + .byte 0x60,0x64,0x68,0x70,0x78,0x6C,0x66,0x00 + .byte 0x18,0x18,0x18,0x18,0x18,0x18,0x0C,0x00 + .byte 0x00,0xFC,0xD6,0xD6,0xD6,0xD6,0xC6,0x00 + .byte 0x00,0x7C,0x66,0x66,0x66,0x66,0x66,0x00 + .byte 0x00,0x3C,0x66,0x66,0x66,0x66,0x3C,0x00 + .byte 0x00,0x7C,0x66,0x66,0x66,0x7C,0x60,0x60 + .byte 0x00,0x3E,0x66,0x66,0x66,0x66,0x3E,0x06 + .byte 0x00,0x6C,0x70,0x60,0x60,0x60,0x60,0x00 + .byte 0x00,0x3C,0x72,0x38,0x1C,0x4E,0x3C,0x00 + .byte 0x18,0x3C,0x18,0x18,0x18,0x18,0x0C,0x00 + .byte 0x00,0x66,0x66,0x66,0x66,0x66,0x3E,0x00 + .byte 0x00,0x66,0x66,0x66,0x66,0x64,0x78,0x00 + .byte 0x00,0xC6,0xC6,0xD6,0xD6,0xD6,0xFC,0x00 + .byte 0x00,0x66,0x66,0x3C,0x66,0x66,0x66,0x00 + .byte 0x00,0x66,0x66,0x66,0x26,0x1E,0x46,0x3C + .byte 0x00,0x7E,0x0E,0x1C,0x38,0x70,0x7E,0x00 + .byte 0x0E,0x18,0x18,0x30,0x18,0x18,0x0E,0x00 + .byte 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18 + .byte 0x70,0x18,0x18,0x0C,0x18,0x18,0x70,0x00 + .byte 0x00,0x60,0xF2,0x9E,0x0C,0x00,0x00,0x00 + .byte 0x10,0x10,0x28,0x28,0x44,0x44,0x82,0xFE + +; Character: ? (0E) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b11111111 ; oooooooo + .db 0b11111111 ; oooooooo + .db 0b11111111 ; oooooooo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (0F) + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + +; Character: ? (1C) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00011111 ; ooooo + .db 0b00011111 ; ooooo + .db 0b00011111 ; ooooo + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + +; Character: ? (1D) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b11111100 ; oooooo + .db 0b11111100 ; oooooo + .db 0b11111100 ; oooooo + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + +; Character: ? (1E) + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + .db 0b00011111 ; ooooo + .db 0b00011111 ; ooooo + .db 0b00011111 ; ooooo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (1F) + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + .db 0b11111100 ; oooooo + .db 0b11111100 ; oooooo + .db 0b11111100 ; oooooo + .db 0b00000000 ; + .db 0b00000000 ; diff --git a/gbdk/gbdk-lib/libc/targets/sm83/f_italic.s b/gbdk/gbdk-lib/libc/targets/sm83/f_italic.s new file mode 100644 index 00000000..75e9a81e --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/f_italic.s @@ -0,0 +1,956 @@ +; font: italic + + .area _HOME +_font_italic:: + .db 1+4 ; 128 char encoding, compressed + .db 93 ; Number of tiles + +; Encoding table + + .db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + .db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + .db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + .db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + .db 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 + .db 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F + .db 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17 + .db 0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F + .db 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27 + .db 0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F + .db 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37 + .db 0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x00 + .db 0x00,0x3F,0x40,0x41,0x42,0x43,0x44,0x45 + .db 0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D + .db 0x4E,0x4F,0x50,0x51,0x52,0x53,0x54,0x55 + .db 0x56,0x57,0x58,0x59,0x5A,0x5B,0x5C,0x00 +; Tile data +; Default character (space) + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + +; Character: ! (21) + .db 0b00000000 ; + .db 0b00001000 ; o + .db 0b00001000 ; o + .db 0b00001000 ; o + .db 0b00010000 ; o + .db 0b00010000 ; o + .db 0b00000000 ; + .db 0b00100000 ; o + +; Character: " (22) + .db 0b00000000 ; + .db 0b00100100 ; o o + .db 0b00100100 ; o o + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: # (23) + .db 0b00000000 ; + .db 0b00100100 ; o o + .db 0b01111110 ; oooooo + .db 0b00100100 ; o o + .db 0b00100100 ; o o + .db 0b01111110 ; oooooo + .db 0b00100100 ; o o + .db 0b00000000 ; + +; Character: $ (24) + .db 0b00000000 ; + .db 0b00001000 ; o + .db 0b00111110 ; ooooo + .db 0b00101000 ; o o + .db 0b00111110 ; ooooo + .db 0b00001010 ; o o + .db 0b00111110 ; ooooo + .db 0b00001000 ; o + +; Character: % (25) + .db 0b00000000 ; + .db 0b01100010 ; oo o + .db 0b01100100 ; oo o + .db 0b00001000 ; o + .db 0b00010000 ; o + .db 0b00100110 ; o oo + .db 0b01000110 ; o oo + .db 0b00000000 ; + +; Character: & (26) + .db 0b00000000 ; + .db 0b00010000 ; o + .db 0b00101000 ; o o + .db 0b00010000 ; o + .db 0b00101010 ; o o o + .db 0b01000100 ; o o + .db 0b00111010 ; ooo o + .db 0b00000000 ; + +; Character: ' (27) + .db 0b00000000 ; + .db 0b00001000 ; o + .db 0b00010000 ; o + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ( (28) + .db 0b00000000 ; + .db 0b00000100 ; o + .db 0b00001000 ; o + .db 0b00001000 ; o + .db 0b00001000 ; o + .db 0b00001000 ; o + .db 0b00000100 ; o + .db 0b00000000 ; + +; Character: ) (29) + .db 0b00000000 ; + .db 0b00100000 ; o + .db 0b00010000 ; o + .db 0b00010000 ; o + .db 0b00010000 ; o + .db 0b00010000 ; o + .db 0b00100000 ; o + .db 0b00000000 ; + +; Character: * (2A) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00100100 ; o o + .db 0b00011000 ; oo + .db 0b01111110 ; oooooo + .db 0b00011000 ; oo + .db 0b00100100 ; o o + .db 0b00000000 ; + +; Character: + (2B) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00001000 ; o + .db 0b00001000 ; o + .db 0b00111110 ; ooooo + .db 0b00001000 ; o + .db 0b00001000 ; o + .db 0b00000000 ; + +; Character: , (2C) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00001000 ; o + .db 0b00001000 ; o + .db 0b00010000 ; o + +; Character: - (2D) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00111110 ; ooooo + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: . (2E) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + +; Character: / (2F) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000010 ; o + .db 0b00000100 ; o + .db 0b00001000 ; o + .db 0b00010000 ; o + .db 0b00100000 ; o + .db 0b00000000 ; + +; Character: 0 (30) + .db 0b00000000 ; + .db 0b00011100 ; ooo + .db 0b00100110 ; o oo + .db 0b01001010 ; o o o + .db 0b01010100 ; o o o + .db 0b10100100 ; o o o + .db 0b11001000 ; oo o + .db 0b01110000 ; ooo + +; Character: 1 (31) + .db 0b00000000 ; + .db 0b00011000 ; oo + .db 0b00101000 ; o o + .db 0b00001000 ; o + .db 0b00010000 ; o + .db 0b00100000 ; o + .db 0b00100000 ; o + .db 0b11111000 ; ooooo + +; Character: 2 (32) + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01000010 ; o o + .db 0b00000100 ; o + .db 0b00011000 ; oo + .db 0b01100000 ; oo + .db 0b10000000 ; o + .db 0b11111100 ; oooooo + +; Character: 3 (33) + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01000010 ; o o + .db 0b00000010 ; o + .db 0b00001100 ; oo + .db 0b00000010 ; o + .db 0b10000100 ; o o + .db 0b01111000 ; oooo + +; Character: 4 (34) + .db 0b00000000 ; + .db 0b00001100 ; oo + .db 0b00110100 ; oo o + .db 0b01000100 ; o o + .db 0b10001000 ; o o + .db 0b11111110 ; ooooooo + .db 0b00010000 ; o + .db 0b00010000 ; o + +; Character: 5 (35) + .db 0b00000000 ; + .db 0b00111110 ; ooooo + .db 0b00100000 ; o + .db 0b01000000 ; o + .db 0b01111000 ; oooo + .db 0b00000100 ; o + .db 0b10000100 ; o o + .db 0b01111000 ; oooo + +; Character: 6 (36) + .db 0b00000000 ; + .db 0b00011100 ; ooo + .db 0b00100010 ; o o + .db 0b01000000 ; o + .db 0b01111000 ; oooo + .db 0b10000100 ; o o + .db 0b10000100 ; o o + .db 0b01111000 ; oooo + +; Character: 7 (37) + .db 0b00000000 ; + .db 0b00111110 ; ooooo + .db 0b00000010 ; o + .db 0b00000100 ; o + .db 0b00001000 ; o + .db 0b00010000 ; o + .db 0b00100000 ; o + .db 0b00100000 ; o + +; Character: 8 (38) + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01000010 ; o o + .db 0b00111100 ; oooo + .db 0b01000010 ; o o + .db 0b10000100 ; o o + .db 0b10000100 ; o o + .db 0b01111000 ; oooo + +; Character: 9 (39) + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01000010 ; o o + .db 0b01000010 ; o o + .db 0b00111100 ; oooo + .db 0b00000100 ; o + .db 0b00001000 ; o + .db 0b11110000 ; oooo + +; Character: : (3A) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00001000 ; o + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00010000 ; o + .db 0b00000000 ; + +; Character: ; (3B) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00010000 ; o + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00010000 ; o + .db 0b00010000 ; o + .db 0b00100000 ; o + +; Character: < (3C) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000100 ; o + .db 0b00001000 ; o + .db 0b00010000 ; o + .db 0b00001000 ; o + .db 0b00000100 ; o + .db 0b00000000 ; + +; Character: = (3D) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00111110 ; ooooo + .db 0b00000000 ; + .db 0b01111100 ; ooooo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: > (3E) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00010000 ; o + .db 0b00001000 ; o + .db 0b00000100 ; o + .db 0b00001000 ; o + .db 0b00010000 ; o + .db 0b00000000 ; + +; Character: ? (3F) + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01000010 ; o o + .db 0b00000010 ; o + .db 0b00001100 ; oo + .db 0b00010000 ; o + .db 0b00000000 ; + .db 0b00110000 ; oo + +; Character: @ (40) + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01001010 ; o o o + .db 0b01010110 ; o o oo + .db 0b01011110 ; o oooo + .db 0b01000000 ; o + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: A (41) + .db 0b00000000 ; + .db 0b00011100 ; ooo + .db 0b00100010 ; o o + .db 0b00100010 ; o o + .db 0b01111100 ; ooooo + .db 0b01000100 ; o o + .db 0b10001000 ; o o + .db 0b10001000 ; o o + +; Character: B (42) + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b00100010 ; o o + .db 0b00111100 ; oooo + .db 0b01000010 ; o o + .db 0b01000010 ; o o + .db 0b10000100 ; o o + .db 0b11111000 ; ooooo + +; Character: C (43) + .db 0b00000000 ; + .db 0b00011100 ; ooo + .db 0b00100010 ; o o + .db 0b01000000 ; o + .db 0b01000000 ; o + .db 0b10000000 ; o + .db 0b10000100 ; o o + .db 0b01111000 ; oooo + +; Character: D (44) + .db 0b00000000 ; + .db 0b00111000 ; ooo + .db 0b00100100 ; o o + .db 0b00100010 ; o o + .db 0b01000010 ; o o + .db 0b01000100 ; o o + .db 0b10001000 ; o o + .db 0b11110000 ; oooo + +; Character: E (45) + .db 0b00000000 ; + .db 0b00111110 ; ooooo + .db 0b00100000 ; o + .db 0b01000000 ; o + .db 0b01111000 ; oooo + .db 0b01000000 ; o + .db 0b10000000 ; o + .db 0b11111000 ; ooooo + +; Character: F (46) + .db 0b00000000 ; + .db 0b00111110 ; ooooo + .db 0b00100000 ; o + .db 0b01000000 ; o + .db 0b01111000 ; oooo + .db 0b01000000 ; o + .db 0b10000000 ; o + .db 0b10000000 ; o + +; Character: G (47) + .db 0b00000000 ; + .db 0b00011100 ; ooo + .db 0b00100010 ; o o + .db 0b01000000 ; o + .db 0b01000000 ; o + .db 0b10001110 ; o ooo + .db 0b10000100 ; o o + .db 0b01111000 ; oooo + +; Character: H (48) + .db 0b00000000 ; + .db 0b00100010 ; o o + .db 0b00100010 ; o o + .db 0b01000100 ; o o + .db 0b01111100 ; ooooo + .db 0b01000100 ; o o + .db 0b10001000 ; o o + .db 0b10001000 ; o o + +; Character: I (49) + .db 0b00000000 ; + .db 0b00111110 ; ooooo + .db 0b00001000 ; o + .db 0b00001000 ; o + .db 0b00010000 ; o + .db 0b00100000 ; o + .db 0b00100000 ; o + .db 0b11111000 ; ooooo + +; Character: J (4A) + .db 0b00000000 ; + .db 0b00000010 ; o + .db 0b00000010 ; o + .db 0b00000100 ; o + .db 0b00000100 ; o + .db 0b10001000 ; o o + .db 0b10001000 ; o o + .db 0b01110000 ; ooo + +; Character: K (4B) + .db 0b00000000 ; + .db 0b00100010 ; o o + .db 0b00100100 ; o o + .db 0b01001000 ; o o + .db 0b01110000 ; ooo + .db 0b01001000 ; o o + .db 0b10001000 ; o o + .db 0b10000100 ; o o + +; Character: L (4C) + .db 0b00000000 ; + .db 0b00100000 ; o + .db 0b00100000 ; o + .db 0b01000000 ; o + .db 0b01000000 ; o + .db 0b01000000 ; o + .db 0b10000000 ; o + .db 0b11111100 ; oooooo + +; Character: M (4D) + .db 0b00000000 ; + .db 0b00110110 ; oo oo + .db 0b00101010 ; o o o + .db 0b01010100 ; o o o + .db 0b01010100 ; o o o + .db 0b01000100 ; o o + .db 0b10001000 ; o o + .db 0b10001000 ; o o + +; Character: N (4E) + .db 0b00000000 ; + .db 0b00100010 ; o o + .db 0b00110010 ; oo o + .db 0b01010100 ; o o o + .db 0b01010100 ; o o o + .db 0b01010100 ; o o o + .db 0b10011000 ; o oo + .db 0b10001000 ; o o + +; Character: O (4F) + .db 0b00000000 ; + .db 0b00011100 ; ooo + .db 0b00100010 ; o o + .db 0b01000010 ; o o + .db 0b01000100 ; o o + .db 0b10000100 ; o o + .db 0b10001000 ; o o + .db 0b01110000 ; ooo + +; Character: P (50) + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b00100010 ; o o + .db 0b01000010 ; o o + .db 0b01111100 ; ooooo + .db 0b01000000 ; o + .db 0b10000000 ; o + .db 0b10000000 ; o + +; Character: Q (51) + .db 0b00000000 ; + .db 0b00011100 ; ooo + .db 0b00100010 ; o o + .db 0b01000010 ; o o + .db 0b01000100 ; o o + .db 0b10010100 ; o o o + .db 0b10001000 ; o o + .db 0b01110100 ; ooo o + +; Character: R (52) + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b00100010 ; o o + .db 0b01000010 ; o o + .db 0b01111100 ; ooooo + .db 0b01001000 ; o o + .db 0b10000100 ; o o + .db 0b10000100 ; o o + +; Character: S (53) + .db 0b00000000 ; + .db 0b00011110 ; oooo + .db 0b00100000 ; o + .db 0b00100000 ; o + .db 0b00011000 ; oo + .db 0b00000100 ; o + .db 0b10000100 ; o o + .db 0b01111000 ; oooo + +; Character: T (54) + .db 0b00000000 ; + .db 0b11111110 ; ooooooo + .db 0b00010000 ; o + .db 0b00100000 ; o + .db 0b00100000 ; o + .db 0b00100000 ; o + .db 0b01000000 ; o + .db 0b01000000 ; o + +; Character: U (55) + .db 0b00000000 ; + .db 0b00100010 ; o o + .db 0b00100010 ; o o + .db 0b01000100 ; o o + .db 0b01000100 ; o o + .db 0b10001000 ; o o + .db 0b10001000 ; o o + .db 0b01110000 ; ooo + +; Character: V (56) + .db 0b00000000 ; + .db 0b01000010 ; o o + .db 0b01000010 ; o o + .db 0b01000100 ; o o + .db 0b01000100 ; o o + .db 0b10001000 ; o o + .db 0b10010000 ; o o + .db 0b11100000 ; ooo + +; Character: W (57) + .db 0b00000000 ; + .db 0b00100010 ; o o + .db 0b00100010 ; o o + .db 0b01000100 ; o o + .db 0b01010100 ; o o o + .db 0b10101000 ; o o o + .db 0b10101000 ; o o o + .db 0b01010000 ; o o + +; Character: X (58) + .db 0b00000000 ; + .db 0b01000010 ; o o + .db 0b00100100 ; o o + .db 0b00101000 ; o o + .db 0b00010000 ; o + .db 0b00101000 ; o o + .db 0b01001000 ; o o + .db 0b10000100 ; o o + +; Character: Y (59) + .db 0b00000000 ; + .db 0b01000010 ; o o + .db 0b00100100 ; o o + .db 0b00101000 ; o o + .db 0b00010000 ; o + .db 0b00010000 ; o + .db 0b00100000 ; o + .db 0b00100000 ; o + +; Character: Z (5A) + .db 0b00000000 ; + .db 0b01111110 ; oooooo + .db 0b00000100 ; o + .db 0b00001000 ; o + .db 0b00010000 ; o + .db 0b00100000 ; o + .db 0b01000000 ; o + .db 0b11111100 ; oooooo + +; Character: [ (5B) + .db 0b00000000 ; + .db 0b00001110 ; ooo + .db 0b00001000 ; o + .db 0b00001000 ; o + .db 0b00001000 ; o + .db 0b00001000 ; o + .db 0b00001110 ; ooo + .db 0b00000000 ; + +; Character: \ (5C) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b01000000 ; o + .db 0b00100000 ; o + .db 0b00010000 ; o + .db 0b00001000 ; o + .db 0b00000100 ; o + .db 0b00000000 ; + +; Character: ] (5D) + .db 0b00000000 ; + .db 0b01110000 ; ooo + .db 0b00010000 ; o + .db 0b00010000 ; o + .db 0b00010000 ; o + .db 0b00010000 ; o + .db 0b01110000 ; ooo + .db 0b00000000 ; + +; Character: ^ (5E) + .db 0b00000000 ; + .db 0b00010000 ; o + .db 0b00111000 ; ooo + .db 0b01010100 ; o o o + .db 0b00010000 ; o + .db 0b00010000 ; o + .db 0b00010000 ; o + .db 0b00000000 ; + +; Character: a (61) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00011100 ; ooo + .db 0b00000010 ; o + .db 0b00111110 ; ooooo + .db 0b01000100 ; o o + .db 0b00111100 ; oooo + +; Character: b (62) + .db 0b00000000 ; + .db 0b00010000 ; o + .db 0b00010000 ; o + .db 0b00100000 ; o + .db 0b00111100 ; oooo + .db 0b00100010 ; o o + .db 0b01000100 ; o o + .db 0b01111000 ; oooo + +; Character: c (63) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00011110 ; oooo + .db 0b00100000 ; o + .db 0b01000000 ; o + .db 0b01000000 ; o + .db 0b00111100 ; oooo + +; Character: d (64) + .db 0b00000000 ; + .db 0b00000010 ; o + .db 0b00000010 ; o + .db 0b00000100 ; o + .db 0b00111100 ; oooo + .db 0b01000100 ; o o + .db 0b01001000 ; o o + .db 0b00111000 ; ooo + +; Character: e (65) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00011100 ; ooo + .db 0b00100010 ; o o + .db 0b01111100 ; ooooo + .db 0b01000000 ; o + .db 0b00111000 ; ooo + +; Character: f (66) + .db 0b00000000 ; + .db 0b00001110 ; ooo + .db 0b00010000 ; o + .db 0b00010000 ; o + .db 0b00111000 ; ooo + .db 0b00100000 ; o + .db 0b01000000 ; o + .db 0b01000000 ; o + +; Character: g (67) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00011110 ; oooo + .db 0b00100010 ; o o + .db 0b01000100 ; o o + .db 0b00111100 ; oooo + .db 0b00000100 ; o + .db 0b01111000 ; oooo + +; Character: h (68) + .db 0b00000000 ; + .db 0b00010000 ; o + .db 0b00010000 ; o + .db 0b00100000 ; o + .db 0b00111100 ; oooo + .db 0b00100010 ; o o + .db 0b01000100 ; o o + .db 0b01000100 ; o o + +; Character: i (69) + .db 0b00000000 ; + .db 0b00001000 ; o + .db 0b00000000 ; + .db 0b00011000 ; oo + .db 0b00001000 ; o + .db 0b00010000 ; o + .db 0b00100000 ; o + .db 0b01110000 ; ooo + +; Character: j (6A) + .db 0b00000000 ; + .db 0b00000100 ; o + .db 0b00000000 ; + .db 0b00000100 ; o + .db 0b00000100 ; o + .db 0b01001000 ; o o + .db 0b01001000 ; o o + .db 0b00110000 ; oo + +; Character: k (6B) + .db 0b00000000 ; + .db 0b00010000 ; o + .db 0b00010000 ; o + .db 0b00100000 ; o + .db 0b00100100 ; o o + .db 0b00111000 ; ooo + .db 0b01000100 ; o o + .db 0b01000100 ; o o + +; Character: l (6C) + .db 0b00000000 ; + .db 0b00001000 ; o + .db 0b00001000 ; o + .db 0b00010000 ; o + .db 0b00010000 ; o + .db 0b00100000 ; o + .db 0b00100000 ; o + .db 0b00011000 ; oo + +; Character: m (6D) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00110100 ; oo o + .db 0b00101010 ; o o o + .db 0b00101010 ; o o o + .db 0b01010100 ; o o o + .db 0b01010100 ; o o o + +; Character: n (6E) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b00100010 ; o o + .db 0b00100010 ; o o + .db 0b01000100 ; o o + .db 0b01000100 ; o o + +; Character: o (6F) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00011100 ; ooo + .db 0b00100010 ; o o + .db 0b00100010 ; o o + .db 0b01000100 ; o o + .db 0b01000100 ; o o + .db 0b00111000 ; ooo + +; Character: p (70) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00011100 ; ooo + .db 0b00010010 ; o o + .db 0b00100010 ; o o + .db 0b00111100 ; oooo + .db 0b01000000 ; o + .db 0b01000000 ; o + +; Character: q (71) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00011110 ; oooo + .db 0b00100010 ; o o + .db 0b00100100 ; o o + .db 0b00011100 ; ooo + .db 0b00001000 ; o + .db 0b00001100 ; oo + +; Character: r (72) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00001110 ; ooo + .db 0b00010000 ; o + .db 0b00010000 ; o + .db 0b00100000 ; o + .db 0b00100000 ; o + +; Character: s (73) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00011110 ; oooo + .db 0b00100000 ; o + .db 0b00011000 ; oo + .db 0b00000100 ; o + .db 0b01111000 ; oooo + +; Character: t (74) + .db 0b00000000 ; + .db 0b00001000 ; o + .db 0b00001000 ; o + .db 0b00011100 ; ooo + .db 0b00001000 ; o + .db 0b00010000 ; o + .db 0b00010000 ; o + .db 0b00100000 ; o + +; Character: u (75) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00100010 ; o o + .db 0b00100010 ; o o + .db 0b01000100 ; o o + .db 0b01000100 ; o o + .db 0b00111000 ; ooo + +; Character: v (76) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00100010 ; o o + .db 0b00100010 ; o o + .db 0b01000100 ; o o + .db 0b01001000 ; o o + .db 0b00110000 ; oo + +; Character: w (77) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00100010 ; o o + .db 0b00101010 ; o o o + .db 0b01010100 ; o o o + .db 0b01010100 ; o o o + .db 0b00101000 ; o o + +; Character: x (78) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00100100 ; o o + .db 0b00101000 ; o o + .db 0b00011000 ; oo + .db 0b00100100 ; o o + .db 0b01000100 ; o o + +; Character: y (79) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00100010 ; o o + .db 0b00100010 ; o o + .db 0b00011100 ; ooo + .db 0b00000100 ; o + .db 0b01111000 ; oooo + +; Character: z (7A) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00111110 ; ooooo + .db 0b00000100 ; o + .db 0b00011000 ; oo + .db 0b00100000 ; o + .db 0b01111100 ; ooooo + +; Character: { (7B) + .db 0b00000000 ; + .db 0b00001110 ; ooo + .db 0b00001000 ; o + .db 0b00110000 ; oo + .db 0b00001000 ; o + .db 0b00001000 ; o + .db 0b00001110 ; ooo + .db 0b00000000 ; + +; Character: | (7C) + .db 0b00000000 ; + .db 0b00001000 ; o + .db 0b00001000 ; o + .db 0b00001000 ; o + .db 0b00001000 ; o + .db 0b00001000 ; o + .db 0b00001000 ; o + .db 0b00000000 ; + +; Character: } (7D) + .db 0b00000000 ; + .db 0b01110000 ; ooo + .db 0b00010000 ; o + .db 0b00001100 ; oo + .db 0b00010000 ; o + .db 0b00010000 ; o + .db 0b01110000 ; ooo + .db 0b00000000 ; + +; Character: ~ (7E) + .db 0b00000000 ; + .db 0b00010100 ; o o + .db 0b00101000 ; o o + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + diff --git a/gbdk/gbdk-lib/libc/targets/sm83/f_min.s b/gbdk/gbdk-lib/libc/targets/sm83/f_min.s new file mode 100644 index 00000000..1505dc07 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/f_min.s @@ -0,0 +1,356 @@ +; font_min.s + +; Text font +; Michael Hope, 1998 +; michaelh@earthling.net +; Distrubuted under the Artistic License - see www.opensource.org +; + + .module font_min + .area _HOME + +_font_min:: + .byte 1+4 ; 128 character encoding + .byte 37 ; Tiles required + + .byte 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 ; All map to space + .byte 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 ; All map to space + .byte 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 ; All map to space + .byte 01,02,03,04,05,06,07,08,09,10,00,00,00,00,00,00 + .byte 00,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25 + .byte 26,27,28,29,30,31,32,33,34,35,36,00,00,00,00,00 + .byte 00,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25 + .byte 26,27,28,29,30,31,32,33,34,35,36,00,00,00,00,00 + + .db 0 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 +; Character: 0 + .db 0b00000000 + .db 0b00111100 + .db 0b01000110 + .db 0b01001010 + .db 0b01010010 + .db 0b01100010 + .db 0b00111100 + .db 0b00000000 +; Character: 1 + .db 0b00000000 + .db 0b00011000 + .db 0b00101000 + .db 0b00001000 + .db 0b00001000 + .db 0b00001000 + .db 0b00111110 + .db 0b00000000 +; Character: 2 + .db 0b00000000 + .db 0b00111100 + .db 0b01000010 + .db 0b00000010 + .db 0b00111100 + .db 0b01000000 + .db 0b01111110 + .db 0b00000000 +; Character: 3 + .db 0b00000000 + .db 0b00111100 + .db 0b01000010 + .db 0b00001100 + .db 0b00000010 + .db 0b01000010 + .db 0b00111100 + .db 0b00000000 +; Character: 4 + .db 0b00000000 + .db 0b00001000 + .db 0b00011000 + .db 0b00101000 + .db 0b01001000 + .db 0b01111110 + .db 0b00001000 + .db 0b00000000 +; Character: 5 + .db 0b00000000 + .db 0b01111110 + .db 0b01000000 + .db 0b01111100 + .db 0b00000010 + .db 0b01000010 + .db 0b00111100 + .db 0b00000000 +; Character: 6 + .db 0b00000000 + .db 0b00111100 + .db 0b01000000 + .db 0b01111100 + .db 0b01000010 + .db 0b01000010 + .db 0b00111100 + .db 0b00000000 +; Character: 7 + .db 0b00000000 + .db 0b01111110 + .db 0b00000010 + .db 0b00000100 + .db 0b00001000 + .db 0b00010000 + .db 0b00010000 + .db 0b00000000 +; Character: 8 + .db 0b00000000 + .db 0b00111100 + .db 0b01000010 + .db 0b00111100 + .db 0b01000010 + .db 0b01000010 + .db 0b00111100 + .db 0b00000000 +; Character: 9 + .db 0b00000000 + .db 0b00111100 + .db 0b01000010 + .db 0b01000010 + .db 0b00111110 + .db 0b00000010 + .db 0b00111100 + .db 0b00000000 +; Character: A + .db 0b00000000 + .db 0b00111100 + .db 0b01000010 + .db 0b01000010 + .db 0b01111110 + .db 0b01000010 + .db 0b01000010 + .db 0b00000000 +; Character: B + .db 0b00000000 + .db 0b01111100 + .db 0b01000010 + .db 0b01111100 + .db 0b01000010 + .db 0b01000010 + .db 0b01111100 + .db 0b00000000 +; Character: C + .db 0b00000000 + .db 0b00111100 + .db 0b01000010 + .db 0b01000000 + .db 0b01000000 + .db 0b01000010 + .db 0b00111100 + .db 0b00000000 +; Character: D + .db 0b00000000 + .db 0b01111000 + .db 0b01000100 + .db 0b01000010 + .db 0b01000010 + .db 0b01000100 + .db 0b01111000 + .db 0b00000000 +; Character: E + .db 0b00000000 + .db 0b01111110 + .db 0b01000000 + .db 0b01111100 + .db 0b01000000 + .db 0b01000000 + .db 0b01111110 + .db 0b00000000 +; Character: F + .db 0b00000000 + .db 0b01111110 + .db 0b01000000 + .db 0b01111100 + .db 0b01000000 + .db 0b01000000 + .db 0b01000000 + .db 0b00000000 +; Character: G + .db 0b00000000 + .db 0b00111100 + .db 0b01000010 + .db 0b01000000 + .db 0b01001110 + .db 0b01000010 + .db 0b00111100 + .db 0b00000000 +; Character: H + .db 0b00000000 + .db 0b01000010 + .db 0b01000010 + .db 0b01111110 + .db 0b01000010 + .db 0b01000010 + .db 0b01000010 + .db 0b00000000 +; Character: I + .db 0b00000000 + .db 0b00111110 + .db 0b00001000 + .db 0b00001000 + .db 0b00001000 + .db 0b00001000 + .db 0b00111110 + .db 0b00000000 +; Character: J + .db 0b00000000 + .db 0b00000010 + .db 0b00000010 + .db 0b00000010 + .db 0b01000010 + .db 0b01000010 + .db 0b00111100 + .db 0b00000000 +; Character: K + .db 0b00000000 + .db 0b01000100 + .db 0b01001000 + .db 0b01110000 + .db 0b01001000 + .db 0b01000100 + .db 0b01000010 + .db 0b00000000 +; Character: L + .db 0b00000000 + .db 0b01000000 + .db 0b01000000 + .db 0b01000000 + .db 0b01000000 + .db 0b01000000 + .db 0b01111110 + .db 0b00000000 +; Character: M + .db 0b00000000 + .db 0b01000010 + .db 0b01100110 + .db 0b01011010 + .db 0b01000010 + .db 0b01000010 + .db 0b01000010 + .db 0b00000000 +; Character: N + .db 0b00000000 + .db 0b01000010 + .db 0b01100010 + .db 0b01010010 + .db 0b01001010 + .db 0b01000110 + .db 0b01000010 + .db 0b00000000 +; Character: O + .db 0b00000000 + .db 0b00111100 + .db 0b01000010 + .db 0b01000010 + .db 0b01000010 + .db 0b01000010 + .db 0b00111100 + .db 0b00000000 +; Character: P + .db 0b00000000 + .db 0b01111100 + .db 0b01000010 + .db 0b01000010 + .db 0b01111100 + .db 0b01000000 + .db 0b01000000 + .db 0b00000000 +; Character: Q + .db 0b00000000 + .db 0b00111100 + .db 0b01000010 + .db 0b01000010 + .db 0b01010010 + .db 0b01001010 + .db 0b00111100 + .db 0b00000000 +; Character: R + .db 0b00000000 + .db 0b01111100 + .db 0b01000010 + .db 0b01000010 + .db 0b01111100 + .db 0b01000100 + .db 0b01000010 + .db 0b00000000 +; Character: S + .db 0b00000000 + .db 0b00111100 + .db 0b01000000 + .db 0b00111100 + .db 0b00000010 + .db 0b01000010 + .db 0b00111100 + .db 0b00000000 +; Character: T + .db 0b00000000 + .db 0b11111110 + .db 0b00010000 + .db 0b00010000 + .db 0b00010000 + .db 0b00010000 + .db 0b00010000 + .db 0b00000000 +; Character: U + .db 0b00000000 + .db 0b01000010 + .db 0b01000010 + .db 0b01000010 + .db 0b01000010 + .db 0b01000010 + .db 0b00111100 + .db 0b00000000 +; Character: V + .db 0b00000000 + .db 0b01000010 + .db 0b01000010 + .db 0b01000010 + .db 0b01000010 + .db 0b00100100 + .db 0b00011000 + .db 0b00000000 +; Character: W + .db 0b00000000 + .db 0b01000010 + .db 0b01000010 + .db 0b01000010 + .db 0b01000010 + .db 0b01011010 + .db 0b00100100 + .db 0b00000000 +; Character: X + .db 0b00000000 + .db 0b01000010 + .db 0b00100100 + .db 0b00011000 + .db 0b00011000 + .db 0b00100100 + .db 0b01000010 + .db 0b00000000 +; Character: Y + .db 0b00000000 + .db 0b10000010 + .db 0b01000100 + .db 0b00101000 + .db 0b00010000 + .db 0b00010000 + .db 0b00010000 + .db 0b00000000 +; Character: Z + .db 0b00000000 + .db 0b01111110 + .db 0b00000100 + .db 0b00001000 + .db 0b00010000 + .db 0b00100000 + .db 0b01111110 + .db 0b00000000 diff --git a/gbdk/gbdk-lib/libc/targets/sm83/f_spect.s b/gbdk/gbdk-lib/libc/targets/sm83/f_spect.s new file mode 100644 index 00000000..0da22f4d --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/f_spect.s @@ -0,0 +1,886 @@ +; font_spect.ms +; Text font +; Michael Hope, 1998 +; michaelh@earthling.net +; Distrubuted under the Artistic License - see www.opensource.org +; + + .module font_spect + .area _HOME + +_font_spect:: + .byte 1+4 ; 128 character encoding + .byte 128-32 ; Tiles required + + .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; All map to space + .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + .byte 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 ; 0x20 + .byte 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 + .byte 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47 ; 0x40 + .byte 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63 + .byte 64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79 ; 0x60 + .byte 80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95 + + .db 0 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 +; Character: ! + .db 0b00000000 + .db 0b00010000 + .db 0b00010000 + .db 0b00010000 + .db 0b00010000 + .db 0b00000000 + .db 0b00010000 + .db 0b00000000 +; Character: " + .db 0b00000000 + .db 0b00100100 + .db 0b00100100 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 +; Character: # + .db 0b00000000 + .db 0b00100100 + .db 0b01111110 + .db 0b00100100 + .db 0b00100100 + .db 0b01111110 + .db 0b00100100 + .db 0b00000000 +; Character: $ + .db 0b00000000 + .db 0b00001000 + .db 0b00111110 + .db 0b00101000 + .db 0b00111110 + .db 0b00001010 + .db 0b00111110 + .db 0b00001000 +; Character: % + .db 0b00000000 + .db 0b01100010 + .db 0b01100100 + .db 0b00001000 + .db 0b00010000 + .db 0b00100110 + .db 0b01000110 + .db 0b00000000 +; Character: & + .db 0b00000000 + .db 0b00010000 + .db 0b00101000 + .db 0b00010000 + .db 0b00101010 + .db 0b01000100 + .db 0b00111010 + .db 0b00000000 +; Character: ' + .db 0b00000000 + .db 0b00001000 + .db 0b00010000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 +; Character: ( + .db 0b00000000 + .db 0b00000100 + .db 0b00001000 + .db 0b00001000 + .db 0b00001000 + .db 0b00001000 + .db 0b00000100 + .db 0b00000000 +; Character: ) + .db 0b00000000 + .db 0b00100000 + .db 0b00010000 + .db 0b00010000 + .db 0b00010000 + .db 0b00010000 + .db 0b00100000 + .db 0b00000000 +; Character: * + .db 0b00000000 + .db 0b00000000 + .db 0b00010100 + .db 0b00001000 + .db 0b00111110 + .db 0b00001000 + .db 0b00010100 + .db 0b00000000 +; Character: + + .db 0b00000000 + .db 0b00000000 + .db 0b00001000 + .db 0b00001000 + .db 0b00111110 + .db 0b00001000 + .db 0b00001000 + .db 0b00000000 +; Character: , + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00001000 + .db 0b00001000 + .db 0b00010000 +; Character: - + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00111110 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 +; Character: . + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00011000 + .db 0b00011000 + .db 0b00000000 +; Character: / + .db 0b00000000 + .db 0b00000000 + .db 0b00000010 + .db 0b00000100 + .db 0b00001000 + .db 0b00010000 + .db 0b00100000 + .db 0b00000000 +; Character: 0 + .db 0b00000000 + .db 0b00111100 + .db 0b01000110 + .db 0b01001010 + .db 0b01010010 + .db 0b01100010 + .db 0b00111100 + .db 0b00000000 +; Character: 1 + .db 0b00000000 + .db 0b00011000 + .db 0b00101000 + .db 0b00001000 + .db 0b00001000 + .db 0b00001000 + .db 0b00111110 + .db 0b00000000 +; Character: 2 + .db 0b00000000 + .db 0b00111100 + .db 0b01000010 + .db 0b00000010 + .db 0b00111100 + .db 0b01000000 + .db 0b01111110 + .db 0b00000000 +; Character: 3 + .db 0b00000000 + .db 0b00111100 + .db 0b01000010 + .db 0b00001100 + .db 0b00000010 + .db 0b01000010 + .db 0b00111100 + .db 0b00000000 +; Character: 4 + .db 0b00000000 + .db 0b00001000 + .db 0b00011000 + .db 0b00101000 + .db 0b01001000 + .db 0b01111110 + .db 0b00001000 + .db 0b00000000 +; Character: 5 + .db 0b00000000 + .db 0b01111110 + .db 0b01000000 + .db 0b01111100 + .db 0b00000010 + .db 0b01000010 + .db 0b00111100 + .db 0b00000000 +; Character: 6 + .db 0b00000000 + .db 0b00111100 + .db 0b01000000 + .db 0b01111100 + .db 0b01000010 + .db 0b01000010 + .db 0b00111100 + .db 0b00000000 +; Character: 7 + .db 0b00000000 + .db 0b01111110 + .db 0b00000010 + .db 0b00000100 + .db 0b00001000 + .db 0b00010000 + .db 0b00010000 + .db 0b00000000 +; Character: 8 + .db 0b00000000 + .db 0b00111100 + .db 0b01000010 + .db 0b00111100 + .db 0b01000010 + .db 0b01000010 + .db 0b00111100 + .db 0b00000000 +; Character: 9 + .db 0b00000000 + .db 0b00111100 + .db 0b01000010 + .db 0b01000010 + .db 0b00111110 + .db 0b00000010 + .db 0b00111100 + .db 0b00000000 +; Character: : + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00010000 + .db 0b00000000 + .db 0b00000000 + .db 0b00010000 + .db 0b00000000 +; Character: ; + .db 0b00000000 + .db 0b00000000 + .db 0b00010000 + .db 0b00000000 + .db 0b00000000 + .db 0b00010000 + .db 0b00010000 + .db 0b00100000 +; Character: < + .db 0b00000000 + .db 0b00000000 + .db 0b00000100 + .db 0b00001000 + .db 0b00010000 + .db 0b00001000 + .db 0b00000100 + .db 0b00000000 +; Character: = + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00111110 + .db 0b00000000 + .db 0b00111110 + .db 0b00000000 + .db 0b00000000 +; Character: > + .db 0b00000000 + .db 0b00000000 + .db 0b00010000 + .db 0b00001000 + .db 0b00000100 + .db 0b00001000 + .db 0b00010000 + .db 0b00000000 +; Character: ? + .db 0b00000000 + .db 0b00111100 + .db 0b01000010 + .db 0b00000100 + .db 0b00001000 + .db 0b00000000 + .db 0b00001000 + .db 0b00000000 +; Character: @ + .db 0b00000000 + .db 0b00111100 + .db 0b01001010 + .db 0b01010110 + .db 0b01011110 + .db 0b01000000 + .db 0b00111100 + .db 0b00000000 +; Character: A + .db 0b00000000 + .db 0b00111100 + .db 0b01000010 + .db 0b01000010 + .db 0b01111110 + .db 0b01000010 + .db 0b01000010 + .db 0b00000000 +; Character: B + .db 0b00000000 + .db 0b01111100 + .db 0b01000010 + .db 0b01111100 + .db 0b01000010 + .db 0b01000010 + .db 0b01111100 + .db 0b00000000 +; Character: C + .db 0b00000000 + .db 0b00111100 + .db 0b01000010 + .db 0b01000000 + .db 0b01000000 + .db 0b01000010 + .db 0b00111100 + .db 0b00000000 +; Character: D + .db 0b00000000 + .db 0b01111000 + .db 0b01000100 + .db 0b01000010 + .db 0b01000010 + .db 0b01000100 + .db 0b01111000 + .db 0b00000000 +; Character: E + .db 0b00000000 + .db 0b01111110 + .db 0b01000000 + .db 0b01111100 + .db 0b01000000 + .db 0b01000000 + .db 0b01111110 + .db 0b00000000 +; Character: F + .db 0b00000000 + .db 0b01111110 + .db 0b01000000 + .db 0b01111100 + .db 0b01000000 + .db 0b01000000 + .db 0b01000000 + .db 0b00000000 +; Character: G + .db 0b00000000 + .db 0b00111100 + .db 0b01000010 + .db 0b01000000 + .db 0b01001110 + .db 0b01000010 + .db 0b00111100 + .db 0b00000000 +; Character: H + .db 0b00000000 + .db 0b01000010 + .db 0b01000010 + .db 0b01111110 + .db 0b01000010 + .db 0b01000010 + .db 0b01000010 + .db 0b00000000 +; Character: I + .db 0b00000000 + .db 0b00111110 + .db 0b00001000 + .db 0b00001000 + .db 0b00001000 + .db 0b00001000 + .db 0b00111110 + .db 0b00000000 +; Character: J + .db 0b00000000 + .db 0b00000010 + .db 0b00000010 + .db 0b00000010 + .db 0b01000010 + .db 0b01000010 + .db 0b00111100 + .db 0b00000000 +; Character: K + .db 0b00000000 + .db 0b01000100 + .db 0b01001000 + .db 0b01110000 + .db 0b01001000 + .db 0b01000100 + .db 0b01000010 + .db 0b00000000 +; Character: L + .db 0b00000000 + .db 0b01000000 + .db 0b01000000 + .db 0b01000000 + .db 0b01000000 + .db 0b01000000 + .db 0b01111110 + .db 0b00000000 +; Character: M + .db 0b00000000 + .db 0b01000010 + .db 0b01100110 + .db 0b01011010 + .db 0b01000010 + .db 0b01000010 + .db 0b01000010 + .db 0b00000000 +; Character: N + .db 0b00000000 + .db 0b01000010 + .db 0b01100010 + .db 0b01010010 + .db 0b01001010 + .db 0b01000110 + .db 0b01000010 + .db 0b00000000 +; Character: O + .db 0b00000000 + .db 0b00111100 + .db 0b01000010 + .db 0b01000010 + .db 0b01000010 + .db 0b01000010 + .db 0b00111100 + .db 0b00000000 +; Character: P + .db 0b00000000 + .db 0b01111100 + .db 0b01000010 + .db 0b01000010 + .db 0b01111100 + .db 0b01000000 + .db 0b01000000 + .db 0b00000000 +; Character: Q + .db 0b00000000 + .db 0b00111100 + .db 0b01000010 + .db 0b01000010 + .db 0b01010010 + .db 0b01001010 + .db 0b00111100 + .db 0b00000000 +; Character: R + .db 0b00000000 + .db 0b01111100 + .db 0b01000010 + .db 0b01000010 + .db 0b01111100 + .db 0b01000100 + .db 0b01000010 + .db 0b00000000 +; Character: S + .db 0b00000000 + .db 0b00111100 + .db 0b01000000 + .db 0b00111100 + .db 0b00000010 + .db 0b01000010 + .db 0b00111100 + .db 0b00000000 +; Character: T + .db 0b00000000 + .db 0b11111110 + .db 0b00010000 + .db 0b00010000 + .db 0b00010000 + .db 0b00010000 + .db 0b00010000 + .db 0b00000000 +; Character: U + .db 0b00000000 + .db 0b01000010 + .db 0b01000010 + .db 0b01000010 + .db 0b01000010 + .db 0b01000010 + .db 0b00111100 + .db 0b00000000 +; Character: V + .db 0b00000000 + .db 0b01000010 + .db 0b01000010 + .db 0b01000010 + .db 0b01000010 + .db 0b00100100 + .db 0b00011000 + .db 0b00000000 +; Character: W + .db 0b00000000 + .db 0b01000010 + .db 0b01000010 + .db 0b01000010 + .db 0b01000010 + .db 0b01011010 + .db 0b00100100 + .db 0b00000000 +; Character: X + .db 0b00000000 + .db 0b01000010 + .db 0b00100100 + .db 0b00011000 + .db 0b00011000 + .db 0b00100100 + .db 0b01000010 + .db 0b00000000 +; Character: Y + .db 0b00000000 + .db 0b10000010 + .db 0b01000100 + .db 0b00101000 + .db 0b00010000 + .db 0b00010000 + .db 0b00010000 + .db 0b00000000 +; Character: Z + .db 0b00000000 + .db 0b01111110 + .db 0b00000100 + .db 0b00001000 + .db 0b00010000 + .db 0b00100000 + .db 0b01111110 + .db 0b00000000 +; Character: [ + .db 0b00000000 + .db 0b00001110 + .db 0b00001000 + .db 0b00001000 + .db 0b00001000 + .db 0b00001000 + .db 0b00001110 + .db 0b00000000 +; Character: \ + .db 0b00000000 + .db 0b00000000 + .db 0b01000000 + .db 0b00100000 + .db 0b00010000 + .db 0b00001000 + .db 0b00000100 + .db 0b00000000 +; Character: ] + .db 0b00000000 + .db 0b01110000 + .db 0b00010000 + .db 0b00010000 + .db 0b00010000 + .db 0b00010000 + .db 0b01110000 + .db 0b00000000 +; Character: ^ + .db 0b00000000 + .db 0b00010000 + .db 0b00111000 + .db 0b01010100 + .db 0b00010000 + .db 0b00010000 + .db 0b00010000 + .db 0b00000000 +; Character: _ + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b11111111 +; Character: Pound + .db 0b00000000 + .db 0b00011100 + .db 0b00100010 + .db 0b01111000 + .db 0b00100000 + .db 0b00100000 + .db 0b01111110 + .db 0b00000000 +; Character: a + .db 0b00000000 + .db 0b00000000 + .db 0b00111000 + .db 0b00000100 + .db 0b00111100 + .db 0b01000100 + .db 0b00111100 + .db 0b00000000 +; Character: b + .db 0b00000000 + .db 0b00100000 + .db 0b00100000 + .db 0b00111100 + .db 0b00100010 + .db 0b00100010 + .db 0b00111100 + .db 0b00000000 +; Character: c + .db 0b00000000 + .db 0b00000000 + .db 0b00011100 + .db 0b00100000 + .db 0b00100000 + .db 0b00100000 + .db 0b00011100 + .db 0b00000000 +; Character: d + .db 0b00000000 + .db 0b00000100 + .db 0b00000100 + .db 0b00111100 + .db 0b01000100 + .db 0b01000100 + .db 0b00111100 + .db 0b00000000 +; Character: e + .db 0b00000000 + .db 0b00000000 + .db 0b00111000 + .db 0b01000100 + .db 0b01111000 + .db 0b01000000 + .db 0b00111100 + .db 0b00000000 +; Character: f + .db 0b00000000 + .db 0b00001100 + .db 0b00010000 + .db 0b00011000 + .db 0b00010000 + .db 0b00010000 + .db 0b00010000 + .db 0b00000000 +; Character: g + .db 0b00000000 + .db 0b00000000 + .db 0b00111100 + .db 0b01000100 + .db 0b01000100 + .db 0b00111100 + .db 0b00000100 + .db 0b00111000 +; Character: h + .db 0b00000000 + .db 0b01000000 + .db 0b01000000 + .db 0b01111000 + .db 0b01000100 + .db 0b01000100 + .db 0b01000100 + .db 0b00000000 +; Character: i + .db 0b00000000 + .db 0b00010000 + .db 0b00000000 + .db 0b00110000 + .db 0b00010000 + .db 0b00010000 + .db 0b00111000 + .db 0b00000000 +; Character: j + .db 0b00000000 + .db 0b00000100 + .db 0b00000000 + .db 0b00000100 + .db 0b00000100 + .db 0b00000100 + .db 0b00100100 + .db 0b00011000 +; Character: k + .db 0b00000000 + .db 0b00100000 + .db 0b00101000 + .db 0b00110000 + .db 0b00110000 + .db 0b00101000 + .db 0b00100100 + .db 0b00000000 +; Character: l + .db 0b00000000 + .db 0b00010000 + .db 0b00010000 + .db 0b00010000 + .db 0b00010000 + .db 0b00010000 + .db 0b00001100 + .db 0b00000000 +; Character: m + .db 0b00000000 + .db 0b00000000 + .db 0b01101000 + .db 0b01010100 + .db 0b01010100 + .db 0b01010100 + .db 0b01010100 + .db 0b00000000 +; Character: n + .db 0b00000000 + .db 0b00000000 + .db 0b01111000 + .db 0b01000100 + .db 0b01000100 + .db 0b01000100 + .db 0b01000100 + .db 0b00000000 +; Character: o + .db 0b00000000 + .db 0b00000000 + .db 0b00111000 + .db 0b01000100 + .db 0b01000100 + .db 0b01000100 + .db 0b00111000 + .db 0b00000000 +; Character: p + .db 0b00000000 + .db 0b00000000 + .db 0b01111000 + .db 0b01000100 + .db 0b01000100 + .db 0b01111000 + .db 0b01000000 + .db 0b01000000 +; Character: q + .db 0b00000000 + .db 0b00000000 + .db 0b00111100 + .db 0b01000100 + .db 0b01000100 + .db 0b00111100 + .db 0b00000100 + .db 0b00000110 +; Character: r + .db 0b00000000 + .db 0b00000000 + .db 0b00011100 + .db 0b00100000 + .db 0b00100000 + .db 0b00100000 + .db 0b00100000 + .db 0b00000000 +; Character: s + .db 0b00000000 + .db 0b00000000 + .db 0b00111000 + .db 0b01000000 + .db 0b00111000 + .db 0b00000100 + .db 0b01111000 + .db 0b00000000 +; Character: t + .db 0b00000000 + .db 0b00010000 + .db 0b00111000 + .db 0b00010000 + .db 0b00010000 + .db 0b00010000 + .db 0b00001100 + .db 0b00000000 +; Character: u + .db 0b00000000 + .db 0b00000000 + .db 0b01000100 + .db 0b01000100 + .db 0b01000100 + .db 0b01000100 + .db 0b00111000 + .db 0b00000000 +; Character: v + .db 0b00000000 + .db 0b00000000 + .db 0b01000100 + .db 0b01000100 + .db 0b00101000 + .db 0b00101000 + .db 0b00010000 + .db 0b00000000 +; Character: w + .db 0b00000000 + .db 0b00000000 + .db 0b01000100 + .db 0b01010100 + .db 0b01010100 + .db 0b01010100 + .db 0b00101000 + .db 0b00000000 +; Character: x + .db 0b00000000 + .db 0b00000000 + .db 0b01000100 + .db 0b00101000 + .db 0b00010000 + .db 0b00101000 + .db 0b01000100 + .db 0b00000000 +; Character: y + .db 0b00000000 + .db 0b00000000 + .db 0b01000100 + .db 0b01000100 + .db 0b01000100 + .db 0b00111100 + .db 0b00000100 + .db 0b00111000 +; Character: z + .db 0b00000000 + .db 0b00000000 + .db 0b01111100 + .db 0b00001000 + .db 0b00010000 + .db 0b00100000 + .db 0b01111100 + .db 0b00000000 +; Character: { + .db 0b00000000 + .db 0b00001110 + .db 0b00001000 + .db 0b00110000 + .db 0b00001000 + .db 0b00001000 + .db 0b00001110 + .db 0b00000000 +; Character: | + .db 0b00000000 + .db 0b00001000 + .db 0b00001000 + .db 0b00001000 + .db 0b00001000 + .db 0b00001000 + .db 0b00001000 + .db 0b00000000 +; Character: } + .db 0b00000000 + .db 0b01110000 + .db 0b00010000 + .db 0b00001100 + .db 0b00010000 + .db 0b00010000 + .db 0b01110000 + .db 0b00000000 +; Character: ~ + .db 0b00000000 + .db 0b00010100 + .db 0b00101000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 +; Character: Copyright + .db 0b00111100 + .db 0b01000010 + .db 0b10011001 + .db 0b10100001 + .db 0b10100001 + .db 0b10011001 + .db 0b01000010 + .db 0b00111100 diff --git a/gbdk/gbdk-lib/libc/targets/sm83/far_ptr.s b/gbdk/gbdk-lib/libc/targets/sm83/far_ptr.s new file mode 100644 index 00000000..1c3a1e57 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/far_ptr.s @@ -0,0 +1,71 @@ +;-------------------------------------------------------------------------- +; far_ptr.s +; +; Copyright (C) 2020, Tony Pavlov +; +; This library is free software; you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by the +; Free Software Foundation; either version 2, or (at your option) any +; later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this library; see the file COPYING. If not, write to the +; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, +; MA 02110-1301, USA. +; +; As a special exception, if you link this library with other files, +; some of which are compiled with SDCC, to produce an executable, +; this library does not by itself cause the resulting executable to +; be covered by the GNU General Public License. This exception does +; not however invalidate any other reasons why the executable file +; might be covered by the GNU General Public License. +;-------------------------------------------------------------------------- + + .module far_ptr + + .include "global.s" + + .area _HOME + +___call__banked:: + ldh A, (#__current_bank) + push AF + ld HL, #1$ + push HL + ld HL, #___call_banked_addr + ld A, (HL+) + ld H, (HL) + ld L, A + ld A, (#___call_banked_bank) + ldh (#__current_bank), A + ld (.MBC_ROM_PAGE),A + jp (HL) +1$: + pop AF + ldh (#__current_bank), A + ld (.MBC1_ROM_PAGE), A + ret + +_to_far_ptr:: + lda HL, 2(SP) + ld A, (HL+) + ld E, A + ld A, (HL+) + ld D, A + ld A, (HL+) + ld H, (HL) + ld L, A + ret + + .area _DATA + +___call_banked_ptr:: +___call_banked_addr:: + .ds 0x02 ; far pointer offset +___call_banked_bank:: + .ds 0x02 ; far pointer segment diff --git a/gbdk/gbdk-lib/libc/targets/sm83/fill_rect.s b/gbdk/gbdk-lib/libc/targets/sm83/fill_rect.s new file mode 100644 index 00000000..ce1740f9 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/fill_rect.s @@ -0,0 +1,85 @@ + .include "global.s" + + .area _HOME + +.fill_rect_wtt:: + PUSH HL + LDH A,(.LCDC) + AND #LCDCF_WIN9C00 + JR Z,.is98 + JR .is9c + ;; Initialize background tile table with B +.fill_rect_btt:: + PUSH HL + LDH A,(.LCDC) + AND #LCDCF_BG9C00 + JR NZ,.is9c +.is98: + LD HL,#0x9800 ; HL = origin + JR .fill_rect +.is9c: + LD HL,#0x9C00 ; HL = origin + + ;; fills rectangle area with tile B at XY = DE, size WH on stack, to vram from address (HL) +.fill_rect: + PUSH BC ; Store source + + SWAP E + RLC E + LD A,E + AND #0x03 + ADD H + LD B,A + LD A,#0xE0 + AND E + ADD D + LD C,A ; dest BC = HL + 0x20 * Y + X + + POP HL ; H = Tile + POP DE ; DE = WH + PUSH DE ; store WH + PUSH BC ; store dest + +3$: ; Copy W tiles + + WAIT_STAT + LD A, H + LD (BC), A + + LD A, C ; inc dest and wrap around + AND #0xE0 + LD E, A + LD A, C + INC A + AND #0x1F + OR E + LD C, A + + DEC D + JR NZ, 3$ + + POP BC + POP DE + + DEC E + RET Z + + PUSH DE + + LD A, B ; next row and wrap around + AND #0xFC + LD E, A ; save high bits + + LD A,#0x20 + + ADD C + LD C, A + ADC B + SUB C + AND #0x03 + OR E ; restore high bits + LD B, A + + PUSH BC + + JR 3$ diff --git a/gbdk/gbdk-lib/libc/targets/sm83/fill_rect_bk.s b/gbdk/gbdk-lib/libc/targets/sm83/fill_rect_bk.s new file mode 100644 index 00000000..2d4a051e --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/fill_rect_bk.s @@ -0,0 +1,22 @@ + .include "global.s" + + .area _HOME + +_fill_bkg_rect:: + PUSH BC + + LDA HL,4(SP) ; Skip return address and registers + LD A,(HL+) ; D = x + LD D, A + LD E,(HL) ; E = y + LDA HL,8(SP) + LD A,(HL-) ; B = tile + LD B, A + LD A,(HL-) ; A = h + LD H,(HL) ; H = w + LD L,A ; L = h + + CALL .fill_rect_btt + + POP BC + RET diff --git a/gbdk/gbdk-lib/libc/targets/sm83/fill_rect_wi.s b/gbdk/gbdk-lib/libc/targets/sm83/fill_rect_wi.s new file mode 100644 index 00000000..b0bd8312 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/fill_rect_wi.s @@ -0,0 +1,22 @@ + .include "global.s" + + .area _HOME + +_fill_win_rect:: + PUSH BC + + LDA HL,4(SP) ; Skip return address and registers + LD A,(HL+) ; D = x + LD D, A + LD E,(HL) ; E = y + LDA HL,8(SP) + LD A,(HL-) ; B = tile + LD B, A + LD A,(HL-) ; A = h + LD H,(HL) ; H = w + LD L,A ; L = h + + CALL .fill_rect_wtt + + POP BC + RET diff --git a/gbdk/gbdk-lib/libc/targets/sm83/font.s b/gbdk/gbdk-lib/libc/targets/sm83/font.s new file mode 100644 index 00000000..e973a24a --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/font.s @@ -0,0 +1,558 @@ +; font.ms +; +; Michael Hope, 1999 +; michaelh@earthling.net +; Distrubuted under the Artistic License - see www.opensource.org +; + .include "global.s" + + .globl .cr_curs + .globl .adv_curs + .globl .cury, .curx + .globl .display_off + + ; Structure offsets + sfont_handle_sizeof = 3 + sfont_handle_font = 1 + sfont_handle_first_tile = 0 + + ; Encoding types - lower 2 bits of font + FONT_256ENCODING = 0 + FONT_128ENCODING = 1 + FONT_NOENCODING = 2 + + ; Other bits + FONT_BCOMPRESSED = 2 + + .CR = 0x0A ; Unix + .SPACE = 0x00 + + ; Maximum number of fonts + .MAX_FONTS = 6 + + .area _FONT_HEADER (ABS) + + .org .MODE_TABLE+4*.T_MODE + JP .tmode + + .module font.ms + + .globl .fg_colour, .bg_colour + + .globl .drawing_vbl, .drawing_lcd + .globl .int_0x40, .int_0x48 + .globl .remove_int + .globl _set_bkg_1bpp_data, _set_bkg_data + + .area _INITIALIZED +.curx:: ; Cursor position + .ds 0x01 +.cury:: + .ds 0x01 + + .area _INITIALIZER + .db 0x00 ; .curx + .db 0x00 ; .cury + + .area _DATA + ; The current font + +font_current:: + .ds sfont_handle_sizeof + ; Cached copy of the first free tile +font_first_free_tile:: + .ds 1 + ; Table containing descriptors for all of the fonts +font_table:: + .ds sfont_handle_sizeof*.MAX_FONTS + + .area _HOME + +_font_load_ibm:: + ld hl,#_font_ibm + call font_load + ret + +; Load the font HL +font_load:: + call .display_off + push hl + + ; Find the first free font entry + ld hl,#font_table+sfont_handle_font + ld b,#.MAX_FONTS +font_load_find_slot: + ld a,(hl) ; Check to see if this entry is free + inc hl ; Free is 0000 for the font pointer + or (hl) + cp #0 + jr z,font_load_found + + inc hl + inc hl + dec b + jr nz,font_load_find_slot + pop hl + ld hl,#0 + jr font_load_exit ; Couldn't find a free space +font_load_found: + ; HL points to the end of the free font table entry + pop de + ld (hl),d ; Copy across the font struct pointer + dec hl + ld (hl),e + + ld a,(font_first_free_tile) + dec hl + ld (hl),a + + push hl + call font_set ; Set this new font to be the default + + ; Only copy the tiles in if were in text mode + ld a,(.mode) + and #.T_MODE + + call nz,font_copy_current + + ; Increase the 'first free tile' counter + ld hl,#font_current+sfont_handle_font + ld a,(hl+) + ld h,(hl) + ld l,a + + inc hl ; Number of tiles used + ld a,(font_first_free_tile) + add a,(hl) + ld (font_first_free_tile),a + + pop hl ; Return font setup in HL +font_load_exit: + ;; Turn the screen on + LDH A,(.LCDC) + OR #(LCDCF_ON | LCDCF_BGON) + AND #~(LCDCF_BG9C00 | LCDCF_BG8000) + LDH (.LCDC),A + + RET + + ; Copy the tiles from the current font into VRAM +font_copy_current:: + ; Find the current font data + ld hl,#font_current+sfont_handle_font + ld a,(hl+) + ld h,(hl) + ld l,a + + ld a, (hl+) + ld e, a + ld a, (hl+) + ld d, a + + ld a, e + ld c, #128 + and #3 + cp #FONT_128ENCODING + jr z, 1$ + cp #FONT_NOENCODING + jr z, 2$ + inc h + jr 2$ +1$: + ld a, c + add l + ld l, a + adc h + sub l + ld h, a +2$: + push hl + ld c, e + ld a, (font_current+sfont_handle_first_tile) + ld e, a + push de + bit FONT_BCOMPRESSED, c + jr nz, 3$ + call _set_bkg_data + jr 4$ +3$: + call _set_bkg_1bpp_data +4$: + add sp, #4 + ret + + ; Set the current font to HL +font_set:: + ld a,(hl+) + ld (font_current),a + ld a,(hl+) + ld (font_current+1),a + ld a,(hl+) + ld (font_current+2),a + ret + + ;; Print a character with interpretation +.put_char:: + ; See if it's a special char + cp #.CR + jr nz,1$ + + ; Now see if were checking special chars + push af + ld a,(.mode) + and #.M_NO_INTERP + jr nz,2$ + call .cr_curs + pop af + ret +2$: + pop af +1$: + call .set_char + jp .adv_curs + + ;; Print a character without interpretation +.out_char:: + call .set_char + jp .adv_curs + + ;; Delete a character +.del_char:: + call .rew_curs + ld a,#.SPACE + jp .set_char + + ;; Print the character in A +.set_char: + push af + ld a,(font_current+2) + ; Must be non-zero if the font system is setup (cant have a font in page zero) + or a + jr nz,3$ + + ; Font system is not yet setup - init it and copy in the ibm font + ; Kind of a compatibility mode + call _font_init + + ; Need all of the tiles + xor a + ld (font_first_free_tile),a + + call _font_load_ibm +3$: + pop af + push bc + push de + push hl + ; Compute which tile maps to this character + ld e,a + ld hl,#font_current+sfont_handle_font + ld a,(hl+) + ld h,(hl) + ld l,a + ld a,(hl+) + and #3 + cp #FONT_NOENCODING + jr z,set_char_no_encoding + inc hl + ; Now at the base of the encoding table + ; E is set above + ld d,#0 + add hl,de + ld e,(hl) ; That's the tile! +set_char_no_encoding: + ld a,(font_current+0) + add a,e + ld e,a + + LD A,(.cury) ; Y coordinate + LD L,A + LD H,#0x00 + ADD HL,HL + ADD HL,HL + ADD HL,HL + ADD HL,HL + ADD HL,HL + LD A,(.curx) ; X coordinate + LD C,A + LD B,#0x00 + ADD HL,BC + LD BC,#0x9800 + ADD HL,BC + + WAIT_STAT + + LD (HL),E + POP HL + POP DE + POP BC + RET + +_putchar:: + PUSH BC + LDA HL,4(SP) ; Skip return address + LD A,(HL) ; A = c + CALL .put_char + POP BC + RET + +_setchar:: + PUSH BC + LDA HL,4(SP) ; Skip return address + LD A,(HL) ; A = c + CALL .set_char + POP BC + RET + +_font_load:: + push bc + LDA HL,4(SP) ; Skip return address and bc + LD A,(HL) ; A = c + inc hl + ld h,(hl) + ld l,a + call font_load + push hl + pop de ; Return in DE + pop bc + ret + +_font_set:: + push bc + LDA HL,4(SP) ; Skip return address + LD A,(HL) ; A = c + inc hl + ld h,(hl) + ld l,a + call font_set + pop bc + ld de,#0 ; Always good... + ret + +_font_init:: + push bc + .globl .tmode + + call .tmode + + xor a + ld (font_first_free_tile),a + + ; Clear the font table + ld hl,#font_table + ld b,#sfont_handle_sizeof*.MAX_FONTS +1$: + ld (hl+),a + dec b + jr nz,1$ + ld a,#3 + ld (.fg_colour),a + xor a + ld (.bg_colour),a + + call .cls_no_reset_pos + pop bc + ret + +_cls:: +.cls:: + XOR A + LD (.curx), A + LD (.cury), A +.cls_no_reset_pos: + PUSH DE + PUSH HL + LD HL,#0x9800 + LD E,#0x20 ; E = height +1$: + LD D,#0x20 ; D = width +2$: + WAIT_STAT + + LD (HL),#.SPACE ; Always clear + INC HL + DEC D + JR NZ,2$ + DEC E + JR NZ,1$ + POP HL + POP DE + RET + + ; Support routines +_gotoxy:: + lda hl,2(sp) + ld a,(hl+) + ld (.curx),a + ld a,(hl) + ld (.cury),a + ret + +_posx:: + LD A,(.mode) + AND #.T_MODE + JR NZ,1$ + PUSH BC + CALL .tmode + POP BC +1$: + LD A,(.curx) + LD E,A + RET + +_posy:: + LD A,(.mode) + AND #.T_MODE + JR NZ,1$ + PUSH BC + CALL .tmode + POP BC +1$: + LD A,(.cury) + LD E,A + RET + + ;; Rewind the cursor +.rew_curs: + PUSH HL + LD HL,#.curx ; X coordinate + XOR A + CP (HL) + JR Z,1$ + DEC (HL) + JR 99$ +1$: + LD (HL),#.MAXCURSPOSX + LD HL,#.cury ; Y coordinate + XOR A + CP (HL) + JR Z,99$ + DEC (HL) +99$: + POP HL + RET + +.cr_curs:: + PUSH HL + XOR A + LD (.curx),A + LD HL,#.cury ; Y coordinate + LD A,#.MAXCURSPOSY + CP (HL) + JR Z,2$ + INC (HL) + JR 99$ +2$: + CALL .scroll +99$: + POP HL + RET + +.adv_curs:: + PUSH HL + LD HL,#.curx ; X coordinate + LD A,#.MAXCURSPOSX + CP (HL) + JR Z,1$ + INC (HL) + JR 99$ +1$: + LD (HL),#0x00 + LD HL,#.cury ; Y coordinate + LD A,#.MAXCURSPOSY + CP (HL) + JR Z,2$ + INC (HL) + JR 99$ +2$: + ;; See if scrolling is disabled + LD A,(.mode) + AND #.M_NO_SCROLL + JR Z,3$ + ;; Nope - reset the cursor to (0,0) + XOR A + LD (.cury),A + LD (.curx),A + JR 99$ +3$: + CALL .scroll +99$: + POP HL + RET + + ;; Scroll the whole screen +.scroll: + PUSH BC + PUSH DE + PUSH HL + LD HL,#0x9800 + LD BC,#0x9800+0x20 ; BC = next line + LD E,#0x20-0x01 ; E = height - 1 +1$: + LD D,#0x20 ; D = width +2$: + WAIT_STAT + LD A,(BC) + LD (HL+),A + INC BC + + DEC D + JR NZ,2$ + DEC E + JR NZ,1$ + + LD D,#0x20 +3$: + WAIT_STAT + LD A,#.SPACE + LD (HL+),A + DEC D + JR NZ,3$ + + POP HL + POP DE + POP BC + RET + + ;; Enter text mode +.tmode:: + DI ; Disable interrupts + + ;; Turn the screen off + LDH A,(.LCDC) + AND #LCDCF_ON + JR Z,1$ + + ;; Turn the screen off + CALL .display_off + + ;; Remove any interrupts setup by the drawing routine + LD BC,#.drawing_vbl + LD HL,#.int_0x40 + CALL .remove_int + LD BC,#.drawing_lcd + LD HL,#.int_0x48 + CALL .remove_int +1$: + + CALL .tmode_out + + ;; Turn the screen on + LDH A,(.LCDC) + OR #(LCDCF_ON | LCDCF_BGON) + AND #~(LCDCF_BG9C00 | LCDCF_BG8000) + LDH (.LCDC),A + + EI ; Enable interrupts + + RET + + ;; Text mode (out only) +.tmode_out:: + ;; Clear screen + CALL .cls_no_reset_pos + + LD A,#.T_MODE + LD (.mode),A + + RET diff --git a/gbdk/gbdk-lib/libc/targets/sm83/font_color.s b/gbdk/gbdk-lib/libc/targets/sm83/font_color.s new file mode 100644 index 00000000..df14149e --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/font_color.s @@ -0,0 +1,12 @@ + .include "global.s" + + .globl .fg_colour, .bg_colour + + .area _HOME +_font_color:: + LDA HL,2(SP) ; Skip return address and registers + LD A,(HL+) ; A = Foreground + LD (.fg_colour),a + LD A,(HL) + LD (.bg_colour),a + RET diff --git a/gbdk/gbdk-lib/libc/targets/sm83/gb/Makefile b/gbdk/gbdk-lib/libc/targets/sm83/gb/Makefile new file mode 100644 index 00000000..393ff679 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/gb/Makefile @@ -0,0 +1,47 @@ +# GB specific Makefile + +TOPDIR = ../../../.. + +THIS = gb +PORT = sm83 + +CSRC = crlf.c digits.c gprint.c gprintf.c gprintln.c gprintn.c + +ASSRC = cgb.s cgb_palettes.s cgb_compat.s \ + cpy_data.s \ + drawing.s drawing_isr.s color.s \ + f_ibm_full.s f_ibm_sh.s f_italic.s f_min.s f_spect.s \ + get_bk_t.s get_data.s get_tile.s \ + get_wi_t.s get_xy_t.s \ + get_addr.s \ + hiramcpy.s init_tt.s input.s \ + pad.s \ + serial.s set_bk_t.s set_tile.s \ + set_data.s set_prop.s set_spr.s set_wi_t.s set_xy_t.s \ + set_1bit_data.s \ + sgb.s font.s font_color.s delay.s \ + emu_debug.s emu_debug_printf.s \ + nowait.s far_ptr.s \ + lcd.s joy.s tim.s tim.s tim_nested.s tim_common.s \ + crash_handler.s \ + ___sdcc_bcall_ehl.s ___sdcc_bcall.s \ + mv_spr.s \ + pad_ex.s \ + mode.s clock.s \ + get_t.s set_t.s init_vram.s \ + fill_rect.s fill_rect_bk.s fill_rect_wi.s \ + metasprites.s metasprites_flip.s metasprites_hide.s metasprites_hide_spr.s \ + set_tile_submap.s set_win_tile_submap.s \ + gb_decompress.s gb_decompress_tiles.s \ + rle_decompress.s \ + heap.s \ + sfr.s \ + crt0.s + +CRT0 = crt0.s + +include $(TOPDIR)/Makefile.common + +AS = $(AS_SM83) + +include ../../../Makefile.platform diff --git a/gbdk/gbdk-lib/libc/targets/sm83/gb/crash_handler.s b/gbdk/gbdk-lib/libc/targets/sm83/gb/crash_handler.s new file mode 100644 index 00000000..ec08a7f8 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/gb/crash_handler.s @@ -0,0 +1,481 @@ +; Crash handler support +; Original code by ISSOtm +; Adapted by Toxa from gb-starter-kit: https://github.com/ISSOtm/gb-starter-kit + + .include "global.s" + + .globl _font_ibm + + SCRN_X = 160 ; Width of screen in pixels + SCRN_Y = 144 ; Height of screen in pixels + SCRN_X_B = 20 ; Width of screen in bytes + SCRN_Y_B = 18 ; Height of screen in bytes + + SCRN_VX = 256 ; Virtual width of screen in pixels + SCRN_VY = 256 ; Virtual height of screen in pixels + SCRN_VX_B = 32 ; Virtual width of screen in bytes + SCRN_VY_B = 32 ; Virtual height of screen in bytes + + + .area _CRASH_HEADER(ABS) + + .org 0x00 + nop + nop + rst 0x38 + + .org 0x38 + di + jp ___HandleCrash + + + .area _HOME + +___HandleCrash:: + + ; We will use VRAM as scratch, since we are going to overwrite it for + ; screen output anyways. The thing is, we need to turn the LCD off + ; *without* affecting flags... fun task, eh? + + ; Note: it's assumed that this was jumped to with IME off. + ; Don't call this directly, use `rst Crash`. + + ld (wCrashA), a ; We need to have at least one working register, so... + ldh a, (.IE) ; We're also going to overwrite this + ld (wCrashIE), a + ldh a, (.LCDC) + ld (wCrashLCDC), a + ld a, #LCDCF_ON ; LCDCF_ON Make sure the LCD is turned on to avoid waiting infinitely + ldh (.LCDC), a + ld a, #IEF_VBLANK ; IEF_VBLANK + ld (.IE), a + ld a, #0 ; `xor a` would overwrite flags + ld (.IF), a ; No point in backing up that register, it's always changing + halt ; With interrupts disabled, this will exit when `IE & IF != 0` + nop ; Handle hardware bug if it becomes true *before* starting to execute the instruction (1-cycle window) + + ; We're now in VBlank! So we can now use VRAM as scratch for some cycles + ld a, #0 + ldh (.LCDC), a ; Turn off LCD so VRAM can always be safely accessed + ; Save regs + ld (vCrashSP), sp + ld sp, #vCrashSP + push hl + push de + push bc + ld a, (wCrashA) + push af + + ; We need to have all the data in bank 0, but we can't guarantee we were there + ldh a, (.VBK) + ld e, a + bit #0, a + jr z, .bank0 + ; Oh noes. We need to copy the data across banks! + ld hl, #vCrashAF + ld c, #(5 * 2) +.copyAcross: + ld b, (hl) + xor a + ldh (.VBK), a + ld (hl), b + inc l ; inc hl + inc a ; ld a, 1 + ldh (.VBK), a + dec c + jr nz, .copyAcross +.bank0: + xor a + ldh (.NR52), a ; Kill sound for this screen + + ldh (.VBK), a + ld a, e + ld (vCrashVBK), a ; copy vCrashVBK across banks + + ld a, #1 + ldh (.VBK), a + ld hl, #vCrashDumpScreen + ld b, #SCRN_Y_B +.writeAttrRow: + xor a + ld c, #(SCRN_X_B + 1) + rst #0x28 ; .MemsetSmall + ld a, l + add a, #(SCRN_VX_B - SCRN_X_B - 1) + ld l, a + dec b + jr nz, .writeAttrRow + xor a + ldh (.VBK), a + + ; Load palettes + ld a, #0x03 + ldh (.BGP), a + ld a, #0x80 + ldh (.BCPS), a + xor a + ld c, #.BCPD + ldh (c), a + ldh (c), a + dec a ; ld a, $FF + ldh (c), a + ldh (c), a + ldh (c), a + ldh (c), a + ldh (c), a + ldh (c), a + + ld a, #(SCRN_VY - SCRN_Y) + ldh (.SCY), a + ld a, #(SCRN_VX - SCRN_X - 4) + ldh (.SCX), a + + call loadfont + + ; Copy the registers to the dump viewers + ld hl, #vDumpHL + ld de, #vCrashHL + ld c, #4 + rst #0x30 ; .MemcpySmall + + ; We're now going to draw the screen, top to bottom + ld hl, #vCrashDumpScreen + + ; First 3 lines of text + ld de, #.header + ld b, #3 +.writeHeaderLine: + ld a, #0x20 ; " " + ld (hl+), a + ld c, #19 + rst #0x30 ; .MemcpySmall + ld a, #0x20 ; " " + ld (hl+), a + ld a, l + add a, #(SCRN_VX_B - SCRN_X_B - 1) + ld l, a + dec b + jr nz, .writeHeaderLine + + ; Blank line + ld a, #0x20 ; " " + ld c, #(SCRN_X_B + 1) + rst #0x28 ; .MemsetSmall + + ; AF and console model + ld l, #<vCrashDumpScreenRow4 + ld c, #4 + rst #0x30 ; .MemcpySmall + pop bc + call .printHexBC + ld c, #8 + rst #0x30 ; .MemcpySmall + ld a, (__cpu) + call .printHexA + ld a, #0x20 ; " " + ld (hl+), a + ld (hl+), a + ld (hl+), a + + ; BC and DE + ld l, #<vCrashDumpScreenRow5 + ld c, #4 + rst #0x30 ; .MemcpySmall + pop bc + call .printHexBC + ld c, #6 + rst #0x30 ; .MemcpySmall + pop bc + call .printHexBC + ld a, #0x20 + ld (hl+), a + ld (hl+), a + ld (hl+), a + + ; Now, the two memory dumps +.writeDump: + ld a, l + add a, #(SCRN_VX_B - SCRN_X_B - 1) + ld l, a + ld c, #4 + rst #0x30 ; .MemcpySmall + pop bc + push bc + call .printHexBC + ld de, #.viewStr + ld c, #7 + rst #0x30 ; .MemcpySmall + pop de + call .printDump + ld de, #.spStr + bit #7, l + jr z, .writeDump + + ld de, #.hwRegsStrs + ld l, #<vCrashDumpScreenRow14 + ld c, #6 + rst #0x30 ; .MemcpySmall + ld a, (wCrashLCDC) + call .printHexA + ld c, #4 + rst #0x30 ; .MemcpySmall + ldh a, (.KEY1) + call .printHexA + ld c, #4 + rst #0x30 ; .MemcpySmall + ld a, (wCrashIE) + call .printHexA + ld (hl), #0x20 ; " " + + ld l, #<vCrashDumpScreenRow15 + ld c, #7 + rst #0x30 ; .MemcpySmall +.writeBank: + ld a, #0x20 ; " " + ld (hl+), a + ld a, (de) + inc de + ld (hl+), a + cp #0x20 ; " " + jr z, .banksDone + ld a, (de) + inc de + ld c, a + ld a, (de) + inc de + ld b, a + ld a, (bc) + call .printHexA + jr .writeBank +.banksDone: + + ; Start displaying + ld a, #(LCDCF_ON | LCDCF_BG9C00 | LCDCF_BGON) + ldh (.LCDC), a + +.loop: + ; The code never lags, and IE is equal to IEF_VBLANK + xor a + ldh (.IF), a + halt + + jr .loop + +.printHexBC: + call .printHexB + ld a, c +.printHexA: + ld b, a +.printHexB: + ld a, b + and #0xF0 + swap a + add a, #0x30 + cp #0x3a + jr c, 1$ + add a, #(0x41 - 0x3a) +1$: ld (hl+), a + ld a, b + and #0x0F + add a, #0x30 + cp #0x3a + jr c, 2$ + add a, #(0x41 - 0x3a) +2$: ld (hl+), a + ret + +.printDump: + ld b, d + ld c, e + call .printHexBC + ld a, #0x20 ; " " + ld (hl+), a + ld (hl+), a + ld a, e + sub #8 + ld e, a + ld a, d + sbc #0 + ld d, a +.writeDumpLine: + ld a, l + add a, #(SCRN_VX_B - SCRN_X_B - 1) + ld l, a + ld a, #0x20 ; " " + ld (hl+), a +.writeDumpWord: + ld a, (de) + inc de + call .printHexA + ld a, (de) + inc de + call .printHexA + ld a, #0x20 ; " " + ld (hl+), a + bit 4, l + jr nz, .writeDumpWord + ld a, l + and #0x7F + jr nz, .writeDumpLine + ret + +loadfont: + xor a + cpl + ld hl, #0x9000 + ld c, #16 + rst #0x28 ; .MemsetSmall + ld hl, #(0x9000 + ' ' * 16) + ld c, #16 + rst #0x28 ; .MemsetSmall + + ld de, #(_font_ibm + 2 + '0') ; recode table + ld hl, #(0x9000 + '0' * 16) ; destination + push hl + ld c, #(16 * 3) +1$: + ld a, (de) + inc de + push de + + swap a + ld l, a + and #0x0f + ld h, a + ld a, l + and #0xf0 + srl h + rra + ld l, a + ld de, #(_font_ibm + 2 + 128) + add hl, de + + ld d, h + ld e, l + + ldhl sp, #2 + ld a, (hl+) + ld h, (hl) + ld l, a + + ld b, #8 +2$: + ld a, (de) + cpl + inc de + ld (hl+), a + ld (hl+), a + + dec b + jr nz, 2$ + + ld d, h + ld a, l + ldhl sp, #2 + ld (hl+), a + ld (hl), d + + pop de + + dec c + jr nz, 1$ + + add sp, #2 + ret + +.header: + ; 0123456789ABCDEFGHI 19 chars + .ascii "KERNEL PANIC PLEASE" + .ascii "SEND A CLEAR PIC OF" + .ascii "THIS SCREEN TO DEVS" + .ascii " AF:" + .ascii " MODEL:" + .ascii " BC:" + .ascii " DE:" + .ascii " HL:" +.viewStr: + .ascii " VIEW:" +.spStr: + .ascii " SP:" +.hwRegsStrs: + .ascii " LCDC:" + .ascii " K1:" + .ascii " IE:" + .ascii " BANK:" + .ascii "R" + .dw __current_bank + .ascii "V" + .dw vCrashVBK + .ascii "W" + .db .SVBK, 0xff + .ascii " " + + + .area _DATA + +wCrashA: + .ds 1 ; We need at least one working register, and A allows accessing memory +wCrashIE: + .ds 1 +wCrashLCDC: + .ds 1 + + + .area _CRASH_SCRATCH(ABS) + + .org 0x9C00 + + ; Put the crash dump screen at the bottom-right of the 9C00 tilemap, since that tends to be unused space + .ds SCRN_VX_B * (SCRN_VY_B - SCRN_Y_B - 2) ; 2 rows reserved as scratch space + + .ds SCRN_X_B ; Try not to overwrite the window area + .ds 2 * 1 ; Free stack entries (we spill into the above by 1 entry, though :/) + ; These are the initial values of the registers + ; They are popped off the stack when printed, freeing up stack space + +vCrashAF: + .ds 2 +vCrashBC: + .ds 2 +vCrashDE: + .ds 2 +vCrashHL: + .ds 2 +vCrashSP: + .ds 2 + + .ds SCRN_X_B +vHeldKeys: + .ds 1 ; Keys held on previous frame +vUnlockCounter: + .ds 1 ; How many frames until dumps are "unlocked" +vWhichDump: + .ds 1 +vDumpHL: + .ds 2 +vDumpSP: + .ds 2 +vCrashVBK: + .ds 1 + .ds 4 ; Unused + + .ds SCRN_VX_B - SCRN_X_B - 1 +vCrashDumpScreen: +vCrashDumpScreenRow0 = vCrashDumpScreen + 1 * SCRN_VX_B +vCrashDumpScreenRow1 = vCrashDumpScreen + 2 * SCRN_VX_B +vCrashDumpScreenRow2 = vCrashDumpScreen + 3 * SCRN_VX_B +vCrashDumpScreenRow3 = vCrashDumpScreen + 4 * SCRN_VX_B +vCrashDumpScreenRow4 = vCrashDumpScreen + 5 * SCRN_VX_B +vCrashDumpScreenRow5 = vCrashDumpScreen + 6 * SCRN_VX_B +vCrashDumpScreenRow6 = vCrashDumpScreen + 7 * SCRN_VX_B +vCrashDumpScreenRow7 = vCrashDumpScreen + 8 * SCRN_VX_B +vCrashDumpScreenRow8 = vCrashDumpScreen + 9 * SCRN_VX_B +vCrashDumpScreenRow9 = vCrashDumpScreen + 10 * SCRN_VX_B +vCrashDumpScreenRow10 = vCrashDumpScreen + 11 * SCRN_VX_B +vCrashDumpScreenRow11 = vCrashDumpScreen + 12 * SCRN_VX_B +vCrashDumpScreenRow12 = vCrashDumpScreen + 13 * SCRN_VX_B +vCrashDumpScreenRow13 = vCrashDumpScreen + 14 * SCRN_VX_B +vCrashDumpScreenRow14 = vCrashDumpScreen + 15 * SCRN_VX_B +vCrashDumpScreenRow15 = vCrashDumpScreen + 16 * SCRN_VX_B +vCrashDumpScreenRow16 = vCrashDumpScreen + 17 * SCRN_VX_B +vCrashDumpScreenRow17 = vCrashDumpScreen + 18 * SCRN_VX_B diff --git a/gbdk/gbdk-lib/libc/targets/sm83/gb/crt0.s b/gbdk/gbdk-lib/libc/targets/sm83/gb/crt0.s new file mode 100644 index 00000000..31dff00b --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/gb/crt0.s @@ -0,0 +1,538 @@ + .include "global.s" + + ;; **************************************** + ;; Beginning of module + ;; BANKED: checked + .title "Runtime" + .module Runtime + .area _HEADER (ABS) + + ;; RST vectors +; .org 0x00 ; Trap, utilized by crash_handler.h + +; .org 0x08 ; --profile handler utilized by emu_debug.h + +; .org 0x10 ; empty + +; .org 0x18 ; empty + + .org 0x20 ; RST 0x20 == call HL +.call_hl:: + JP (HL) + + .org 0x28 ; zero up to 256 bytes in C pointed by HL +.MemsetSmall:: + LD (HL+),A + DEC C + JR NZ,.MemsetSmall + ret + + .org 0x30 ; copy up to 256 bytes in C from DE to HL +.MemcpySmall:: + LD A, (DE) + LD (HL+), A + INC DE + DEC C + JR NZ,.MemcpySmall + RET + +; .org 0x38 ; crash handler utilized by crash_handler.h + + ;; Hardware interrupt vectors + .org 0x40 ; VBL +.int_VBL: + PUSH AF + PUSH HL + LD HL,#.int_0x40 + JP .int + +; .org 0x48 ; LCD + +; .org 0x50 ; TIM + +; .org 0x58 ; SIO + +; .org 0x60 ; JOY + +; .org 0x70 + ;; space for drawing.s bit table + + .org 0x80 +.int:: + PUSH BC + PUSH DE +1$: + LD A,(HL+) + OR (HL) + JR Z,.int_tail + PUSH HL + LD A,(HL-) + LD L,(HL) + LD H,A + RST 0x20 ; .call_hl + POP HL + INC HL + JR 1$ +_wait_int_handler:: + ADD SP,#4 +.int_tail: + POP DE + POP BC + POP HL + + ;; we return at least at the beginning of mode 2 + WAIT_STAT + + POP AF + RETI + + ;; VBlank default interrupt routine +__standard_VBL_handler:: +.std_vbl: + LD HL,#.sys_time + INC (HL) + JR NZ,2$ + INC HL + INC (HL) +2$: + CALL .refresh_OAM + + LD A, #1 + LDH (.vbl_done),A + RET + +_refresh_OAM:: + WAIT_STAT + LD A, #>_shadow_OAM + JP .refresh_OAM + (.refresh_OAM_DMA - .start_refresh_OAM) + +.clear_WRAM: + PUSH DE + XOR A + LD BC, #l__DATA + LD HL, #s__DATA + CALL .memset_simple + + LD A, #>_shadow_OAM + LDH (__shadow_OAM_base), A + LD H, A + XOR A + LD L, A + LD C, #(40 << 2) ; 40 entries 4 bytes each + RST 0x28 + POP DE + RET + + ;; GameBoy Header + + ;; DO NOT CHANGE... + .org 0x100 +.header: + JR .code_start + + ;; Nintendo logo + .org 0x104 + .byte 0xCE,0xED,0x66,0x66 + .byte 0xCC,0x0D,0x00,0x0B + .byte 0x03,0x73,0x00,0x83 + .byte 0x00,0x0C,0x00,0x0D + .byte 0x00,0x08,0x11,0x1F + .byte 0x88,0x89,0x00,0x0E + .byte 0xDC,0xCC,0x6E,0xE6 + .byte 0xDD,0xDD,0xD9,0x99 + .byte 0xBB,0xBB,0x67,0x63 + .byte 0x6E,0x0E,0xEC,0xCC + .byte 0xDD,0xDC,0x99,0x9F + .byte 0xBB,0xB9,0x33,0x3E + + ;; Title of the game + .org 0x134 + .asciz "Title" + + .org 0x144 + .byte 0,0,0 + + ;; Cartridge type is ROM only + .org 0x147 + .byte 0 + + ;; ROM size is 32kB + .org 0x148 + .byte 0 + + ;; RAM size is 0kB + .org 0x149 + .byte 0 + + ;; Maker ID + .org 0x14A + .byte 0x00,0x00 + + ;; Version number + .org 0x14C + .byte 0x01 + + ;; Complement check + .org 0x14D + .byte 0x00 + + ;; Checksum + .org 0x14E + .byte 0x00,0x00 + + ;; **************************************** + .org 0x150 + + ;; soft reset: falldown to .code_start +.reset:: +_reset:: + LD A, (__is_GBA) + LD B, A + LD A, (__cpu) + + ;; Initialization code +.code_start:: + DI ; Disable interrupts + LD D, A ; Store CPU type in D + LD E, B ; Store GBA flag in E + ;; Initialize the stack + LD SP, #.STACK + + CALL .clear_WRAM + +; LD (.mode),A ; Clearing (.mode) is performed when clearing RAM + + ;; Store CPU type + LD A, D + LD (__cpu), A + CP #.CGB_TYPE + JR NZ, 1$ + XOR A + SRL E + RLA + LD (__is_GBA), A +1$: + ;; Turn the screen off + CALL .display_off + + XOR A + ;; Initialize the display + LDH (.SCY),A + LDH (.SCX),A + LDH (.STAT),A + LDH (.WY),A + LD A,#0x07 + LDH (.WX),A + + ;; Copy refresh_OAM routine to HRAM + LD DE,#.start_refresh_OAM ; source + LD HL,#.refresh_OAM ; dest + LD C,#(.end_refresh_OAM - .start_refresh_OAM) ; size + RST 0x30 ; call .MemcpySmall + + ;; Clear the OAM by calling refresh_OAM + CALL .refresh_OAM + + ;; Install interrupt routines + LD BC,#.std_vbl + CALL .add_VBL + + ;; Standard color palettes + LD A,#0b11100100 ; Grey 3 = 11 (Black) + ; Grey 2 = 10 (Dark grey) + ; Grey 1 = 01 (Light grey) + ; Grey 0 = 00 (Transparent) + LDH (.BGP),A + LDH (.OBP0),A + LD A,#0b00011011 + LDH (.OBP1),A + + ;; Turn the screen on + LD A,#(LCDCF_ON | LCDCF_WIN9C00 | LCDCF_WINOFF | LCDCF_BG8800 | LCDCF_BG9800 | LCDCF_OBJ8 | LCDCF_OBJOFF | LCDCF_BGOFF) + LDH (.LCDC),A + XOR A + LDH (.IF),A + LD A,#.VBL_IFLAG ; switch on VBlank interrupt only + LDH (.IE),A + + LDH (__current_bank),A ; current bank is 1 at startup + + XOR A + + LD HL,#.sys_time + LD (HL+),A + LD (HL),A + + LDH (.NR52),A ; Turn sound off + + CALL gsinit + + EI ; Enable interrupts + + ;; Call the main function + CALL _main +_exit:: +99$: + HALT + NOP + JR 99$ ; Wait forever + +_set_interrupts:: + DI + LDA HL,2(SP) ; Skip return address + XOR A + LDH (.IF),A ; Clear pending interrupts + LD A,(HL) + EI ; Enable interrupts + LDH (.IE),A ; interrupts are still disabled here + RET + + ;; Copy OAM data to OAM RAM +.start_refresh_OAM: + LDH A,(__shadow_OAM_base) + OR A + RET Z +.refresh_OAM_DMA: + LDH (.DMA),A ; Put A into DMA registers + LD A,#0x28 ; We need to wait 160 ns +1$: + DEC A + JR NZ,1$ + RET +.end_refresh_OAM: + + .org .MODE_TABLE + ;; Jump table for modes + RET + + ;; **************************************** + + ;; Ordering of segments for the linker + ;; Code that really needs to be in bank 0 + .area _HOME + ;; Similar to _HOME + .area _BASE + ;; Code + .area _CODE + ;; #pragma bank 0 workaround + .area _CODE_0 + ;; Constant data + .area _LIT +; ;; since _CODE_1 area base address is pre-defined in the linker from 0x4000, +; ;; that moves initializer code and tables out of bank 0 +; .area _CODE_1 + ;; Constant data, used to init _DATA + .area _INITIALIZER + ;; Code, used to init _DATA + .area _GSINIT + .area _GSFINAL + ;; Uninitialised ram data + .area _DATA + .area _BSS + ;; Initialised in ram data + .area _INITIALIZED + ;; For malloc + .area _HEAP + .area _HEAP_END + + .area _DATA +.start_crt_globals: + +__cpu:: + .ds 0x01 ; GB type (GB, PGB, CGB) +__is_GBA:: + .ds 0x01 ; detect GBA +.mode:: + .ds 0x01 ; Current mode +.sys_time:: +_sys_time:: + .ds 0x02 ; System time in VBL units +.int_0x40:: + .blkw 0x0A ; 4 interrupt handlers (built-in + user-defined) + +.end_crt_globals: + + .area _HRAM (ABS) + + .org 0xFF90 +__current_bank:: ; Current bank + .ds 0x01 +.vbl_done: + .ds 0x01 ; Is VBL interrupt finished? +__shadow_OAM_base:: + .ds 0x01 + + ;; Runtime library + .area _GSINIT +gsinit:: + ;; initialize static storage variables + LD BC, #l__INITIALIZER + LD HL, #s__INITIALIZER + LD DE, #s__INITIALIZED + call .memcpy_simple + + .area _GSFINAL + ret + + .area _HOME + + ;; fills memory at HL of length BC with A, clobbers DE +.memset_simple:: + LD E, A + LD A, B + OR C + RET Z + LD (HL), E + DEC BC + LD D, H + LD E, L + INC DE + + ;; copies BC bytes from HL into DE +.memcpy_simple:: + LD A, B + OR C + RET Z + + SRL B + RR C + JR NC,3$ + LD A, (HL+) + LD (DE), A + INC DE +3$: + INC B + INC C + JR 2$ +1$: + LD A, (HL+) + LD (DE), A + INC DE + LD A, (HL+) + LD (DE), A + INC DE +2$: + DEC C + JR NZ,1$ + DEC B + JR NZ,1$ +4$: + RET + + ;; Remove interrupt routine in BC from the VBL interrupt list + ;; falldown to .remove_int +.remove_VBL:: + LD HL,#.int_0x40 + + ;; Remove interrupt BC from interrupt list HL if it exists + ;; Abort if a 0000 is found (end of list) +.remove_int:: +1$: + LD A,(HL+) + LD E,A + LD D,(HL) + INC HL + OR D + RET Z ; No interrupt found + + LD A,E + CP C + JR NZ,1$ + LD A,D + CP B + JR NZ,1$ + + LD D,H + LD E,L + DEC DE + DEC DE + + ;; Now do a memcpy from here until the end of the list +2$: + LD A,(HL+) + LD (DE),A + LD B,A + INC DE + LD A,(HL+) + LD (DE),A + INC DE + OR B + RET Z + JR 2$ + + ;; Add interrupt routine in BC to the VBL interrupt list + ;; falldown to .add_int +.add_VBL:: + LD HL,#.int_0x40 + + ;; Add interrupt routine in BC to the interrupt list in HL +.add_int:: +1$: + LD A,(HL+) + OR (HL) + JR Z,2$ + INC HL + JR 1$ +2$: + LD A,B + LD (HL-),A + LD (HL),C + RET + + ;; Wait for VBL interrupt to be finished +.wait_vbl_done:: +_wait_vbl_done:: + ;; Check if the screen is on + LDH A,(.LCDC) + AND #LCDCF_ON + RET Z ; Return if screen is off + XOR A + LDH (.vbl_done),A ; Clear any previous sets of vbl_done +1$: + HALT ; Wait for any interrupt + NOP ; HALT sometimes skips the next instruction + LDH A,(.vbl_done) ; Was it a VBlank interrupt? + ;; Warning: we may lose a VBlank interrupt, if it occurs now + OR A + JR Z,1$ ; No: back to sleep! + RET + +.display_off:: +_display_off:: + ;; Check if the screen is on + LDH A,(.LCDC) + AND #LCDCF_ON + RET Z ; Return if screen is off +1$: ; We wait for the *NEXT* VBL + LDH A,(.LY) + CP #0x92 ; Smaller than or equal to 0x91? + JR NC,1$ ; Loop until smaller than or equal to 0x91 +2$: + LDH A,(.LY) + CP #0x91 ; Bigger than 0x90? + JR C,2$ ; Loop until bigger than 0x90 + + LDH A,(.LCDC) + AND #~LCDCF_ON + LDH (.LCDC),A ; Turn off screen + RET + +_remove_VBL:: + PUSH BC + LDA HL,4(SP) ; Skip return address and registers + LD A,(HL+) + LD C,A + LD B,(HL) + CALL .remove_VBL + POP BC + RET + +_add_VBL:: + PUSH BC + LDA HL, 4(SP) ; Skip return address and registers + LD A,(HL+) + LD C,A + LD B,(HL) + CALL .add_VBL + POP BC + RET diff --git a/gbdk/gbdk-lib/libc/targets/sm83/gb/global.s b/gbdk/gbdk-lib/libc/targets/sm83/gb/global.s new file mode 100644 index 00000000..c9f30ecd --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/gb/global.s @@ -0,0 +1,532 @@ + .NEAR_CALLS = 1 ; <near_calls> - tag so that sed can change this + + _VRAM = 0x8000 ; $8000->$9FFF + _VRAM8000 = 0x8000 + _VRAM8800 = 0x8800 + _VRAM9000 = 0x9000 + _SCRN0 = 0x9800 ; $9800->$9BFF + _SCRN1 = 0x9C00 ; $9C00->$9FFF + _SRAM = 0xA000 ; $A000->$BFFF + _RAM = 0xC000 ; $C000->$CFFF / $C000->$DFFF + _RAMBANK = 0xD000 ; $D000->$DFFF + _OAMRAM = 0xFE00 ; $FE00->$FE9F + _IO = 0xFF00 ; $FF00->$FF7F,$FFFF + _AUD3WAVERAM = 0xFF30 ; $FF30->$FF3F + _HRAM = 0xFF80 ; $FF80->$FFFE + + ;; MBC Equates + + .MBC1_ROM_PAGE = 0x2000 ; Address to write to for MBC1 switching + .MBC_ROM_PAGE = 0x2000 ; Default platform MBC rom switching address + + rRAMG = 0x0000 ; $0000->$1fff + rROMB0 = 0x2000 ; $2000->$2fff + rROMB1 = 0x3000 ; $3000->$3fff - If more than 256 ROM banks are present. + rRAMB = 0x4000 ; $4000->$5fff - Bit 3 enables rumble (if present) + + ;; Keypad + .UP = 0x04 + .DOWN = 0x08 + .LEFT = 0x02 + .RIGHT = 0x01 + .A = 0x10 + .B = 0x20 + .SELECT = 0x40 + .START = 0x80 + + .P14 = 0x10 + .P15 = 0x20 + + ;; Screen dimensions + .MAXCURSPOSX = 0x13 ; In tiles + .MAXCURSPOSY = 0x11 + + .SCREENWIDTH = 0xA0 + .SCREENHEIGHT = 0x90 + .MINWNDPOSX = 0x07 + .MINWNDPOSY = 0x00 + .MAXWNDPOSX = 0xA6 + .MAXWNDPOSY = 0x8F + + ;; Hardware registers + + .P1 = 0x00 ; Joystick: 1.1.P15.P14.P13.P12.P11.P10 + rP1 = 0xFF00 + + P1F_5 = 0b00100000 ; P15 out port, set to 0 to get buttons + P1F_4 = 0b00010000 ; P14 out port, set to 0 to get dpad + P1F_3 = 0b00001000 ; P13 in port + P1F_2 = 0b00000100 ; P12 in port + P1F_1 = 0b00000010 ; P11 in port + P1F_0 = 0b00000001 ; P10 in port + + P1F_GET_DPAD = 0b00100000 + P1F_GET_BTN = 0b00010000 + P1F_GET_NONE = 0b00110000 + + .SB = 0x01 ; Serial IO data buffer + rSB = 0xFF01 + + .SC = 0x02 ; Serial IO control register + rSC = 0xFF02 + + .DIV = 0x04 ; Divider register + rDIV = 0xFF04 + + .TIMA = 0x05 ; Timer counter + rTIMA = 0xFF05 + + .TMA = 0x06 ; Timer modulo + rTMA = 0xFF06 + + .TAC = 0x07 ; Timer control + rTAC = 0xFF07 + + TACF_START = 0b00000100 + TACF_STOP = 0b00000000 + TACF_4KHZ = 0b00000000 + TACF_16KHZ = 0b00000011 + TACF_65KHZ = 0b00000010 + TACF_262KHZ = 0b00000001 + + .IF = 0x0F ; Interrupt flags: 0.0.0.JST.SIO.TIM.LCD.VBL + rIF = 0xFF0F + + .NR10 = 0x10 ; Sound register + rNR10 = 0xFF10 + rAUD1SWEEP = 0xFF10 + + AUD1SWEEP_UP = 0b00000000 + AUD1SWEEP_DOWN = 0b00001000 + + .NR11 = 0x11 ; Sound register + rNR11 = 0xFF11 + rAUD1LEN = 0xFF11 + + .NR12 = 0x12 ; Sound register + rNR12 = 0xFF12 + rAUD1ENV = 0xFF12 + + .NR13 = 0x13 ; Sound register + rNR13 = 0xFF13 + rAUD1LOW = 0xFF13 + + .NR14 = 0x14 ; Sound register + rNR14 = 0xFF14 + rAUD1HIGH = 0xFF14 + + .NR21 = 0x16 ; Sound register + rNR21 = 0xFF16 + rAUD2LEN = 0xFF16 + + .NR22 = 0x17 ; Sound register + rNR22 = 0xFF17 + rAUD2ENV = 0xFF17 + + .NR23 = 0x18 ; Sound register + rNR23 = 0xFF18 + rAUD2LOW = 0xFF18 + + .NR24 = 0x19 ; Sound register + rNR24 = 0xFF19 + rAUD2HIGH = 0xFF19 + + .NR30 = 0x1A ; Sound register + rNR30 = 0xFF1A + rAUD3ENA = 0xFF1A + + .NR31 = 0x1B ; Sound register + rNR31 = 0xFF1B + rAUD3LEN = 0xFF1B + + .NR32 = 0x1C ; Sound register + rNR32 = 0xFF1C + rAUD3LEVEL = 0xFF1C + + .NR33 = 0x1D ; Sound register + rNR33 = 0xFF1D + rAUD3LOW = 0xFF1D + + .NR34 = 0x1E ; Sound register + rNR34 = 0xFF1E + rAUD3HIGH = 0xFF1E + + .NR41 = 0x20 ; Sound register + rNR41 = 0xFF20 + rAUD4LEN = 0xFF20 + + .NR42 = 0x21 ; Sound register + rNR42 = 0xFF21 + rAUD4ENV = 0xFF21 + + .NR43 = 0x22 ; Sound register + rNR43 = 0xFF22 + rAUD4POLY = 0xFF22 + + .NR44 = 0x23 ; Sound register + rNR44 = 0xFF23 + rAUD4GO = 0xFF23 + + .NR50 = 0x24 ; Sound register + rNR50 = 0xFF24 + rAUDVOL = 0xFF24 + + AUDVOL_VIN_LEFT = 0b10000000 ; SO2 + AUDVOL_VIN_RIGHT = 0b00001000 ; SO1 + + .NR51 = 0x25 ; Sound register + rNR51 = 0xFF25 + rAUDTERM = 0xFF25 + + AUDTERM_4_LEFT = 0b10000000 + AUDTERM_3_LEFT = 0b01000000 + AUDTERM_2_LEFT = 0b00100000 + AUDTERM_1_LEFT = 0b00010000 + AUDTERM_4_RIGHT = 0b00001000 + AUDTERM_3_RIGHT = 0b00000100 + AUDTERM_2_RIGHT = 0b00000010 + AUDTERM_1_RIGHT = 0b00000001 + + .NR52 = 0x26 ; Sound register + rNR52 = 0xFF26 + rAUDENA = 0xFF26 + + AUDENA_ON = 0b10000000 + AUDENA_OFF = 0b00000000 ; sets all audio regs to 0! + + .LCDC = 0x40 ; LCD control + rLCDC = 0xFF40 + + LCDCF_OFF = 0b00000000 ; LCD Control Operation + LCDCF_ON = 0b10000000 ; LCD Control Operation + LCDCF_WIN9800 = 0b00000000 ; Window Tile Map Display Select + LCDCF_WIN9C00 = 0b01000000 ; Window Tile Map Display Select + LCDCF_WINOFF = 0b00000000 ; Window Display + LCDCF_WINON = 0b00100000 ; Window Display + LCDCF_BG8800 = 0b00000000 ; BG & Window Tile Data Select + LCDCF_BG8000 = 0b00010000 ; BG & Window Tile Data Select + LCDCF_BG9800 = 0b00000000 ; BG Tile Map Display Select + LCDCF_BG9C00 = 0b00001000 ; BG Tile Map Display Select + LCDCF_OBJ8 = 0b00000000 ; OBJ Construction + LCDCF_OBJ16 = 0b00000100 ; OBJ Construction + LCDCF_OBJOFF = 0b00000000 ; OBJ Display + LCDCF_OBJON = 0b00000010 ; OBJ Display + LCDCF_BGOFF = 0b00000000 ; BG Display + LCDCF_BGON = 0b00000001 ; BG Display + LCDCF_B_ON = 7 + LCDCF_B_WIN9C00 = 6 + LCDCF_B_WINON = 5 + LCDCF_B_BG8000 = 4 + LCDCF_B_BG9C00 = 3 + LCDCF_B_OBJ16 = 2 + LCDCF_B_OBJON = 1 + LCDCF_B_BGON = 0 + + .STAT = 0x41 ; LCD status + rSTAT = 0xFF41 + + STATF_LYC = 0b01000000 ; LYC=LY Coincidence (Selectable) + STATF_MODE10 = 0b00100000 ; Mode 10 + STATF_MODE01 = 0b00010000 ; Mode 01 (V-Blank) + STATF_MODE00 = 0b00001000 ; Mode 00 (H-Blank) + STATF_LYCF = 0b00000100 ; Coincidence Flag + STATF_HBL = 0b00000000 ; H-Blank + STATF_VBL = 0b00000001 ; V-Blank + STATF_OAM = 0b00000010 ; OAM-RAM is used by system + STATF_LCD = 0b00000011 ; Both OAM and VRAM used by system + STATF_BUSY = 0b00000010 ; When set, VRAM access is unsafe + STATF_B_LYC = 6 + STATF_B_MODE10 = 5 + STATF_B_MODE01 = 4 + STATF_B_MODE00 = 3 + STATF_B_LYCF = 2 + STATF_B_VBL = 0 + STATF_B_OAM = 1 + STATF_B_BUSY = 1 + + .SCY = 0x42 ; Scroll Y + rSCY = 0xFF42 + + .SCX = 0x43 ; Scroll X + rSCX = 0xFF43 + + .LY = 0x44 ; LCDC Y-coordinate + rLY = 0xFF44 + + .LYC = 0x45 ; LY compare + rLYC = 0xFF45 + + .DMA = 0x46 ; DMA transfer + rDMA = 0xFF46 + + .BGP = 0x47 ; BG palette data + rBGP = 0xFF47 + + .OBP0 = 0x48 ; OBJ palette 0 data + rOBP0 = 0xFF48 + + .OBP1 = 0x49 ; OBJ palette 1 data + rOBP1 = 0xFF49 + + .WY = 0x4A ; Window Y coordinate + rWY = 0xFF4A + + .WX = 0x4B ; Window X coordinate + rWX = 0xFF4B + + .KEY1 = 0x4D ; CPU speed + rKEY1 = 0xFF4D + rSPD = 0xFF4D + + KEY1F_DBLSPEED = 0b10000000 ; 0=Normal Speed, 1=Double Speed (R) + KEY1F_PREPARE = 0b00000001 ; 0=No, 1=Prepare (R/W) + + .VBK = 0x4F ; VRAM bank + rVBK = 0xFF4F + + .HDMA1 = 0x51 ; DMA control 1 + rHDMA1 = 0xFF51 + + .HDMA2 = 0x52 ; DMA control 2 + rHDMA2 = 0xFF52 + + .HDMA3 = 0x53 ; DMA control 3 + rHDMA3 = 0xFF53 + + .HDMA4 = 0x54 ; DMA control 4 + rHDMA4 = 0xFF54 + + .HDMA5 = 0x55 ; DMA control 5 + rHDMA5 = 0xFF55 + + HDMA5F_MODE_GP = 0b00000000 ; General Purpose DMA (W) + HDMA5F_MODE_HBL = 0b10000000 ; HBlank DMA (W) + + HDMA5F_BUSY = 0b10000000 ; 0=Busy (DMA still in progress), 1=Transfer complete (R) + + .RP = 0x56 ; IR port + rRP = 0xFF56 + + RPF_ENREAD = 0b11000000 + RPF_DATAIN = 0b00000010 ; 0=Receiving IR Signal, 1=Normal + RPF_WRITE_HI = 0b00000001 + RPF_WRITE_LO = 0b00000000 + + .BCPS = 0x68 ; BG color palette specification + rBCPS = 0xFF68 + + BCPSF_AUTOINC = 0b10000000 ; Auto Increment (0=Disabled, 1=Increment after Writing) + + .BCPD = 0x69 ; BG color palette data + rBCPD = 0xFF69 + + .OCPS = 0x6A ; OBJ color palette specification + rOCPS = 0xFF6A + + OCPSF_AUTOINC = 0b10000000 ; Auto Increment (0=Disabled, 1=Increment after Writing) + + .OCPD = 0x6B ; OBJ color palette data + rOCPD = 0xFF6B + + .SVBK = 0x70 ; WRAM bank + rSVBK = 0xFF70 + rSMBK = 0xFF70 + + rPCM12 = 0xFF76 + + rPCM34 = 0xFF77 + + .IE = 0xFF ; Interrupt enable + rIE = 0xFFFF + + .VBL_IFLAG = 0x01 + .LCD_IFLAG = 0x02 + .TIM_IFLAG = 0x04 + .SIO_IFLAG = 0x08 + .JOY_IFLAG = 0x10 + + IEF_HILO = 0b00010000 ; Transition from High to Low of Pin number P10-P13 + IEF_SERIAL = 0b00001000 ; Serial I/O transfer end + IEF_TIMER = 0b00000100 ; Timer Overflow + IEF_STAT = 0b00000010 ; STAT + IEF_VBLANK = 0b00000001 ; V-Blank + + ;; Flags common to multiple sound channels + + AUDLEN_DUTY_12_5 = 0b00000000 ; 12.5% + AUDLEN_DUTY_25 = 0b01000000 ; 25% + AUDLEN_DUTY_50 = 0b10000000 ; 50% + AUDLEN_DUTY_75 = 0b11000000 ; 75% + + AUDENV_UP = 0b00001000 + AUDENV_DOWN = 0b00000000 + + AUDHIGH_RESTART = 0b10000000 + AUDHIGH_LENGTH_ON = 0b01000000 + AUDHIGH_LENGTH_OFF = 0b00000000 + + ;; OAM related constants + + OAM_COUNT = 40 ; number of OAM entries in OAM RAM + + OAMF_PRI = 0b10000000 ; Priority + OAMF_YFLIP = 0b01000000 ; Y flip + OAMF_XFLIP = 0b00100000 ; X flip + OAMF_PAL0 = 0b00000000 ; Palette number; 0,1 (DMG) + OAMF_PAL1 = 0b00010000 ; Palette number; 0,1 (DMG) + OAMF_BANK0 = 0b00000000 ; Bank number; 0,1 (GBC) + OAMF_BANK1 = 0b00001000 ; Bank number; 0,1 (GBC) + + OAMF_PALMASK = 0b00000111 ; Palette (GBC) + + OAMB_PRI = 7 ; Priority + OAMB_YFLIP = 6 ; Y flip + OAMB_XFLIP = 5 ; X flip + OAMB_PAL1 = 4 ; Palette number; 0,1 (DMG) + OAMB_BANK1 = 3 ; Bank number; 0,1 (GBC) + + ;; SGB packets + .PAL_01 = 0x00 + .PAL_23 = 0x01 + .PAL_03 = 0x02 + .PAL_12 = 0x03 + .ATTR_BLK = 0x04 + .ATTR_LIN = 0x05 + .ATTR_DIV = 0x06 + .ATTR_CHR = 0x07 + .SOUND = 0x08 + .SOU_TRN = 0x09 + .PAL_SET = 0x0A + .PAL_TRN = 0x0B + .ATRC_EN = 0x0C + .TEST_EN = 0x0D + .ICON_EN = 0x0E + .DATA_SND = 0x0F + .DATA_TRN = 0x10 + .MLT_REQ = 0x11 + .JUMP = 0x12 + .CHR_TRN = 0x13 + .PCT_TRN = 0x14 + .ATTR_TRN = 0x15 + .ATTR_SET = 0x16 + .MASK_EN = 0x17 + .OBJ_TRN = 0x18 + + ;; CPU detection + .DMG_TYPE = 0x01 ; Original GB or Super GB + .MGB_TYPE = 0xFF ; Pocket GB or Super GB 2 + .CGB_TYPE = 0x11 ; Color GB + + ;; GBDK library screen modes + + .G_MODE = 0x01 ; Graphic mode + .T_MODE = 0x02 ; Text mode (bit 2) + .T_MODE_OUT = 0x02 ; Text mode output only + .T_MODE_INOUT = 0x03 ; Text mode with input + .M_NO_SCROLL = 0x04 ; Disables scrolling of the screen in text mode + .M_NO_INTERP = 0x08 ; Disables special character interpretation + + ;; Status codes for IO + .IO_IDLE = 0x00 + .IO_SENDING = 0x01 + .IO_RECEIVING = 0x02 + .IO_ERROR = 0x04 + + ;; Type of IO data + .DT_IDLE = 0x66 + .DT_RECEIVING = 0x55 + + ;; Table of routines for modes + .MODE_TABLE = 0x01E0 + + ;; C related + ;; Overheap of a banked call. Used for parameters + ;; = ret + real ret + bank + + .if .NEAR_CALLS + .BANKOV = 2 + + .else + .BANKOV = 6 + + .endif + + .globl __current_bank + .globl __shadow_OAM_base + + ;; Global variables + .globl .mode + + .globl __cpu + .globl __is_GBA + + ;; Global routines +; .globl .set_mode ;; don't link mode.o by default + + .globl .reset + + .globl .display_off + + .globl .wait_vbl_done + + ;; Interrupt routines + .globl .add_VBL +; .globl .add_LCD ;; don't link LCD.o by default +; .globl .add_TIM ;; don't link TIM.o by default +; .globl .add_SIO ;; don't link serial.o by default +; .globl .add_JOY ;; don't link JOY.o by default + + ;; Symbols defined at link time + .globl .STACK + .globl _shadow_OAM + .globl .refresh_OAM + + ;; Main user routine + .globl _main + + ;; Macro definitions + +.macro WAIT_STAT ?lbl +lbl: LDH A, (.STAT) + AND #STATF_BUSY ; Check if in LCD modes 0 or 1 + JR NZ, lbl +.endm + +.macro ADD_A_REG16 regH regL + ADD regL + LD regL, A + ADC regH + SUB regL + LD regH, A +.endm + +.macro SIGNED_ADD_A_REG16 regH regL ?lbl + ; If A is negative, we need to subtract 1 from upper byte of 16-bit value + BIT 7, A ; set z if a signed bit is 0 + JR Z, lbl ; if z is set jump to positive + dec regH ; if negative decrement upper byte +lbl: + ADD_A_REG16 regH, regL +.endm + +.macro SIGNED_SUB_A_REG16 regH regL ?lbl + ; negate A then add to 16-bit value + CPL + INC A + SIGNED_ADD_A_REG16 regH, regL +.endm + +.macro MUL_DE_BY_A_RET_HL ?lbl1 ?lbl2 + ; Multiply DE by A, return result in HL; preserves: BC + LD HL, #0 +lbl1: + SRL A + JR NC, lbl2 + ADD HL, DE +lbl2: + SLA E + RL D + OR A + JR NZ, lbl1 +.endm + diff --git a/gbdk/gbdk-lib/libc/targets/sm83/gb/sfr.s b/gbdk/gbdk-lib/libc/targets/sm83/gb/sfr.s new file mode 100644 index 00000000..64febc7a --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/gb/sfr.s @@ -0,0 +1,111 @@ +__VRAM = 0x8000 +__VRAM8000 = 0x8000 +__VRAM8800 = 0x8800 +__VRAM9000 = 0x9000 +__SCRN0 = 0x9800 +__SCRN1 = 0x9C00 +__SRAM = 0xA000 +__RAM = 0xC000 +__RAMBANK = 0xD000 +__OAMRAM = 0xFE00 +__IO = 0xFF00 +__AUD3WAVERAM = 0xFF30 +__HRAM = 0xFF80 + +.globl __VRAM, __VRAM8000, __VRAM8800, __VRAM9000, __SCRN0, __SCRN1, __SRAM, __RAM, __RAMBANK, __OAMRAM, __IO, __AUD3WAVERAM, __HRAM + +_rRAMG = 0x0000 +_rROMB0 = 0x2000 +_rROMB1 = 0x3000 +_rRAMB = 0x4000 + +.globl _rRAMG, _rROMB0, _rROMB1, _rRAMB + +_P1_REG = 0xFF00 ; Joystick: 1.1.P15.P14.P13.P12.P11.P10 +_SB_REG = 0xFF01 ; Serial IO data buffer +_SC_REG = 0xFF02 ; Serial IO control register +_DIV_REG = 0xFF04 ; Divider register +_TIMA_REG = 0xFF05 ; Timer counter +_TMA_REG = 0xFF06 ; Timer modulo +_TAC_REG = 0xFF07 ; Timer control +_IF_REG = 0xFF0F ; Interrupt flags: 0.0.0.JOY.SIO.TIM.LCD.VBL +_NR10_REG = 0xFF10 ; Sound register +_NR11_REG = 0xFF11 ; Sound register +_NR12_REG = 0xFF12 ; Sound register +_NR13_REG = 0xFF13 ; Sound register +_NR14_REG = 0xFF14 ; Sound register +_NR21_REG = 0xFF16 ; Sound register +_NR22_REG = 0xFF17 ; Sound register +_NR23_REG = 0xFF18 ; Sound register +_NR24_REG = 0xFF19 ; Sound register +_NR30_REG = 0xFF1A ; Sound register +_NR31_REG = 0xFF1B ; Sound register +_NR32_REG = 0xFF1C ; Sound register +_NR33_REG = 0xFF1D ; Sound register +_NR34_REG = 0xFF1E ; Sound register +_NR41_REG = 0xFF20 ; Sound register +_NR42_REG = 0xFF21 ; Sound register +_NR43_REG = 0xFF22 ; Sound register +_NR44_REG = 0xFF23 ; Sound register +_NR50_REG = 0xFF24 ; Sound register +_NR51_REG = 0xFF25 ; Sound register +_NR52_REG = 0xFF26 ; Sound register +_PCM_SAMPLE = 0xFF30 ; PCM wave pattern +_AUD3WAVE = 0xFF30 ; PCM wave pattern +_LCDC_REG = 0xFF40 ; LCD control +_STAT_REG = 0xFF41 ; LCD status +_SCY_REG = 0xFF42 ; Scroll Y +_SCX_REG = 0xFF43 ; Scroll X +_LY_REG = 0xFF44 ; LCDC Y-coordinate +_LYC_REG = 0xFF45 ; LY compare +_DMA_REG = 0xFF46 ; DMA transfer +_BGP_REG = 0xFF47 ; BG palette data +_OBP0_REG = 0xFF48 ; OBJ palette 0 data +_OBP1_REG = 0xFF49 ; OBJ palette 1 data +_WY_REG = 0xFF4A ; Window Y coordinate +_WX_REG = 0xFF4B ; Window X coordinate +_KEY1_REG = 0xFF4D ; CPU speed +_VBK_REG = 0xFF4F ; VRAM bank +_HDMA1_REG = 0xFF51 ; DMA control 1 +_HDMA2_REG = 0xFF52 ; DMA control 2 +_HDMA3_REG = 0xFF53 ; DMA control 3 +_HDMA4_REG = 0xFF54 ; DMA control 4 +_HDMA5_REG = 0xFF55 ; DMA control 5 +_RP_REG = 0xFF56 ; IR port +_BCPS_REG = 0xFF68 ; BG color palette specification +_BCPD_REG = 0xFF69 ; BG color palette data +_OCPS_REG = 0xFF6A ; OBJ color palette specification +_OCPD_REG = 0xFF6B ; OBJ color palette data +_SVBK_REG = 0xFF70 ; WRAM bank +_PCM12_REG = 0xFF76 ; Sound channel 1&2 PCM amplitude (R) +_PCM34_REG = 0xFF77 ; Sound channel 3&4 PCM amplitude (R) +_IE_REG = 0xFFFF ; Interrupt enable + +.globl _P1_REG +.globl _SB_REG, _SC_REG +.globl _DIV_REG +.globl _TIMA_REG, _TMA_REG, _TAC_REG +.globl _IF_REG +.globl _NR10_REG, _NR11_REG, _NR12_REG, _NR13_REG, _NR14_REG +.globl _NR21_REG, _NR22_REG, _NR23_REG, _NR24_REG +.globl _NR30_REG, _NR31_REG, _NR32_REG, _NR33_REG, _NR34_REG +.globl _NR41_REG, _NR42_REG, _NR43_REG, _NR44_REG +.globl _NR50_REG, _NR51_REG, _NR52_REG +.globl _PCM_SAMPLE, _AUD3WAVE +.globl _LCDC_REG +.globl _STAT_REG +.globl _SCY_REG, _SCX_REG +.globl _LY_REG, _LYC_REG +.globl _DMA_REG +.globl _BGP_REG +.globl _OBP0_REG, _OBP1_REG +.globl _WY_REG, _WX_REG +.globl _KEY1_REG +.globl _VBK_REG +.globl _HDMA1_REG, _HDMA2_REG, _HDMA3_REG, _HDMA4_REG, _HDMA5_REG +.globl _RP_REG +.globl _BCPS_REG, _BCPD_REG +.globl _OCPS_REG, _OCPD_REG +.globl _SVBK_REG +.globl _PCM12_REG, _PCM34_REG +.globl _IE_REG
\ No newline at end of file diff --git a/gbdk/gbdk-lib/libc/targets/sm83/gb_decompress.s b/gbdk/gbdk-lib/libc/targets/sm83/gb_decompress.s new file mode 100644 index 00000000..72fd7aef --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/gb_decompress.s @@ -0,0 +1,108 @@ +; GB-Deompress routine +; Compatible with GBTD + + .include "global.s" + + .title "GB Decompress" + .module GBDecompress + + .area _CODE + +_gb_decompress:: + lda hl,5(SP) + ld a,(hl-) + ld d,a + ld a,(hl-) + ld e,a + ld a,(hl-) + ld l,(hl) + ld h,a + +; hl = source; de = dest +gb_decompress:: + push bc + push de +1$: + ld a,(hl+) ; load command + or a + jr z,9$ ; exit, if last byte + bit 7,a + jr nz,5$ ; string functions + bit 6,a + jr nz,3$ + ; RLE byte + and #63 ; calc counter + inc a + ld b,a + ld a,(hl+) +2$: + ld (de),a + inc de + dec b + jr nz,2$ + jr 1$ ; next command +3$: ; RLE word + and #63 + inc a + ld b,(hl) ; load word into bc + inc hl + ld c,(hl) + inc hl +4$: + push af + ld a,b ; store word + ld (de),a + inc de + ld a,c + ld (de),a + inc de + pop af + dec a + jr nz,4$ + jr 1$ ; next command +5$: + bit 6,a + jr nz,7$ + ; string repeat + and a,#63 + inc a + push hl + ld c,(hl) + inc hl + ld b,(hl) + ld h,d + ld l,e + add hl,bc + ld b,a +6$: + ld a,(hl+) + ld (de),a + inc de + dec b + jr nz,6$ + pop hl + inc hl + inc hl + jr 1$ ; next command +7$: ; string copy + and #63 + inc a + ld b,a +8$: + ld a,(hl+) + ld (de),a + inc de + dec b + jr nz,8$ + jr 1$ ; next command +9$: + pop hl + ld a, e + sub l + ld e, a + ld a, d + sbc h + ld d, a + pop bc + + ret diff --git a/gbdk/gbdk-lib/libc/targets/sm83/gb_decompress_tiles.s b/gbdk/gbdk-lib/libc/targets/sm83/gb_decompress_tiles.s new file mode 100644 index 00000000..63bb79a5 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/gb_decompress_tiles.s @@ -0,0 +1,165 @@ +; GB-Decompress tiledata directly to VRAM +; Compatible with GBTD + + .include "global.s" + + .title "GB Decompress" + .module GBDecompress + +.macro WRAP_VRAM regH, ?loc + bit 3, regH + jr z, loc + res 4, regH +loc: +.endm + +.macro UNWRAP_VRAM regH, ?loc + bit 3, regH + jr nz, loc + set 4, regH +loc: +.endm + + + .area _CODE + +_gb_decompress_bkg_data:: +_gb_decompress_win_data:: + ld d, #0x90 + ldh a, (.LCDC) + and #LCDCF_BG8000 + jr z, .load_params +_gb_decompress_sprite_data:: + ld d, #0x80 + +.load_params: + ldhl sp, #2 + ld a, (hl+) + + ; Compute dest ptr + swap a ; *16 (size of a tile) + ld e, a + and #0x0F ; Get high bits + add d ; Add base offset of target tile "block" + ld d, a + ld a, e + and #0xF0 ; Get low bits only + ld e, a + WRAP_VRAM d + + ld a, (hl+) + ld h, (hl) + ld l, a + +; hl = source; de = dest +gb_decompress_vram:: + push bc + push de +1$: + ld a,(hl+) ; load command + or a + jp z,9$ ; exit, if last byte + bit 7,a + jr nz,5$ ; string functions + bit 6,a + jr nz,3$ + ; RLE byte + and #63 ; calc counter + inc a + ld c,a + ld a,(hl+) + ld b,a +2$: + WAIT_STAT + ld a,b + ld (de),a + inc de + WRAP_VRAM d + dec c + jr nz,2$ + jr 1$ ; next command + +3$: ; RLE word + and #63 + inc a + ld c, a + ld a,(hl+) + ld b, a +4$: + WAIT_STAT + ld a,b ; store word + ld (de),a + inc de + WRAP_VRAM d + WAIT_STAT + ld a,(hl) + ld (de),a + inc de + WRAP_VRAM d + dec c + jr nz,4$ + inc hl + jr 1$ ; next command + +5$: + bit 6,a + jr nz,7$ + +6$: ; string repeat + and a,#63 + inc a + push hl + + ld c,(hl) + inc hl + ld b,(hl) + + ldhl sp,#3 + bit 4,(hl) ; check start address was above 0x9000 + jr z, 11$ + + ld h,d + ld l,e + add hl,bc + UNWRAP_VRAM h + jr 12$ +11$: + ld h,d + ld l,e + add hl,bc +12$: + ld c,a + +14$: + WAIT_STAT + ld a,(hl+) + ld (de),a + WRAP_VRAM h + inc de + WRAP_VRAM d + dec c + jr nz, 14$ + + pop hl + inc hl + inc hl + jp 1$ ; next command + +7$: ; string copy + and #63 + inc a + ld c,a +15$: + WAIT_STAT + ld a,(hl+) + ld (de),a + inc de + WRAP_VRAM d + dec c + jr nz, 15$ + + jp 1$ ; next command +9$: + pop de + pop bc + ret diff --git a/gbdk/gbdk-lib/libc/targets/sm83/get_addr.s b/gbdk/gbdk-lib/libc/targets/sm83/get_addr.s new file mode 100644 index 00000000..c234ee4a --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/get_addr.s @@ -0,0 +1,39 @@ +.include "global.s" + +.area _CODE + +_get_win_xy_addr:: + ldh a, (.LCDC) + and #LCDCF_WIN9C00 + jr z, .is98 + jr .is9c + +_get_bkg_xy_addr:: + ldh a, (.LCDC) + and #LCDCF_BG9C00 + jr nz, .is9c +.is98: + ld d, #0x98 ; DE = origin + jr .calculate_ofs +.is9c: + ld d, #0x9C ; DE = origin + +.calculate_ofs: + ldhl sp, #3 + + ld a, (hl-) + ld l, (hl) + + ld e, d + swap a + rlca + ld h, a + and #0x03 + add e + ld d, a + ld a, #0xE0 + and h + add l + ld e, a ; dest DE = BASE + 0x20 * Y + X + + ret diff --git a/gbdk/gbdk-lib/libc/targets/sm83/get_bk_t.s b/gbdk/gbdk-lib/libc/targets/sm83/get_bk_t.s new file mode 100644 index 00000000..2e80eb21 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/get_bk_t.s @@ -0,0 +1,24 @@ + .include "global.s" + + .area _HOME + +_get_bkg_tiles:: + PUSH BC + + LDA HL,4(SP) ; Skip return address and registers + LD A,(HL+) ; D = x + LD D, A + LD E,(HL) ; E = y + LDA HL,9(SP) + LD A,(HL-) ; BC = tiles + LD B, A + LD A,(HL-) + LD C, A + LD A,(HL-) ; A = h + LD H,(HL) ; H = w + LD L,A ; L = h + + CALL .get_xy_btt + + POP BC + RET diff --git a/gbdk/gbdk-lib/libc/targets/sm83/get_data.s b/gbdk/gbdk-lib/libc/targets/sm83/get_data.s new file mode 100644 index 00000000..6a62c606 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/get_data.s @@ -0,0 +1,120 @@ + .include "global.s" + + .globl .copy_vram + + .area _HOME + +_get_bkg_data:: +_get_win_data:: + LDH A,(.LCDC) + AND #LCDCF_BG8000 + JP NZ,_get_sprite_data + + PUSH BC + + LDA HL,7(SP) ; Skip return address and registers + LD A,(HL-) ; BC = data + LD B, A + LD A,(HL-) + LD C, A + LD A,(HL-) ; E = nb_tiles + LD E, A + LD L,(HL) ; L = first_tile + PUSH HL + + XOR A + OR E ; Is nb_tiles == 0? + JR NZ,1$ + LD DE,#0x1000 ; DE = nb_tiles = 256 + JR 2$ +1$: + LD H,#0x00 ; HL = nb_tiles + LD L,E + ADD HL,HL ; HL *= 16 + ADD HL,HL + ADD HL,HL + ADD HL,HL + LD D,H ; DE = nb_tiles + LD E,L +2$: + POP HL ; HL = first_tile + LD A,L + RLCA ; Sign extend (patterns have signed numbers) + SBC A + LD H,A + ADD HL,HL ; HL *= 16 + ADD HL,HL + ADD HL,HL + ADD HL,HL + + PUSH BC + LD BC,#0x9000 + ADD HL,BC + POP BC + +3$: ; Special version of '.copy_vram' + BIT 3,H ; Bigger than 0x9800 + JR Z,4$ + BIT 4,H + JR Z,4$ + RES 4,H ; Switch to 0x8800 +4$: + WAIT_STAT + + LD A,(HL+) + LD (BC),A + INC BC + DEC DE + LD A,D + OR E + JR NZ,3$ + + POP BC + RET + +_get_sprite_data:: + PUSH BC + + LDA HL,7(SP) ; Skip return address and registers + LD A,(HL-) ; BC = data + LD B, A + LD A,(HL-) + LD C, A + LD A,(HL-) ; E = nb_tiles + LD E, A + LD L,(HL) ; L = first_tile + PUSH HL + + XOR A + OR E ; Is nb_tiles == 0? + JR NZ,1$ + LD DE,#0x1000 ; DE = nb_tiles = 256 + JR 2$ +1$: + LD H,#0x00 ; HL = nb_tiles + LD L,E + ADD HL,HL ; HL *= 16 + ADD HL,HL + ADD HL,HL + ADD HL,HL + LD D,H ; DE = nb_tiles + LD E,L +2$: + POP HL ; HL = first_tile + LD L,A + ADD HL,HL ; HL *= 16 + ADD HL,HL + ADD HL,HL + ADD HL,HL + + PUSH BC + LD BC,#0x8000 + ADD HL,BC + LD B,H + LD C,L + POP HL + + CALL .copy_vram + + POP BC + RET diff --git a/gbdk/gbdk-lib/libc/targets/sm83/get_t.s b/gbdk/gbdk-lib/libc/targets/sm83/get_t.s new file mode 100644 index 00000000..455f07be --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/get_t.s @@ -0,0 +1,26 @@ + .include "global.s" + + .area _HOME + +; void get_tiles(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t *vram_addr, uint8_t *tiles); + +_get_tiles:: + LDHL SP, #5 + LD A, (HL-) + LD E, A + LD A, (HL-) + LD D, A + PUSH DE + LD A, (HL-) + LD E, A + LD D, (HL) + LDHL SP, #11 + LD A, (HL-) + LD B, A + LD A, (HL-) + LD C, A + LD A, (HL-) + LD L, (HL) + LD H, A + + JP .get_xy_tt ;; Store background tile table into (BC) at XY = DE, size WH on stack, from vram from address (HL) diff --git a/gbdk/gbdk-lib/libc/targets/sm83/get_tile.s b/gbdk/gbdk-lib/libc/targets/sm83/get_tile.s new file mode 100644 index 00000000..1f0b5ce8 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/get_tile.s @@ -0,0 +1,51 @@ +.include "global.s" + +.area _CODE + +_get_vram_byte:: + ldhl sp,#2 + ld a,(hl+) + ld h,(hl) + ld l,a + WAIT_STAT + ld e,(hl) + ret + +_get_win_tile_xy:: + ldh a,(.LCDC) + and #LCDCF_WIN9C00 + jr z,.is98 + jr .is9c +_get_bkg_tile_xy:: + ldh a,(.LCDC) + and #LCDCF_BG9C00 + jr nz,.is9c +.is98: + ld d,#0x98 ; DE = origin + jr .get_tile_xy +.is9c: + ld d,#0x9C ; DE = origin + +.get_tile_xy: + ldhl sp,#3 + + ld a, (hl-) + ld l, (hl) + + ld e, d + swap a + rlca + ld h, a + and #0x03 + add e + ld d, a + ld a, #0xE0 + and h + add l + ld l, a + ld h, d ; dest DE = BASE + 0x20 * Y + X + + WAIT_STAT + ld e, (hl) + + ret diff --git a/gbdk/gbdk-lib/libc/targets/sm83/get_wi_t.s b/gbdk/gbdk-lib/libc/targets/sm83/get_wi_t.s new file mode 100644 index 00000000..a17fd459 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/get_wi_t.s @@ -0,0 +1,26 @@ + .include "global.s" + + .globl .get_xy_wtt + + .area _HOME + +_get_win_tiles:: + PUSH BC + + LDA HL,4(SP) ; Skip return address and registers + LD A,(HL+) ; D = x + LD D, A + LD E,(HL) ; E = y + LDA HL,9(SP) + LD A,(HL-) ; BC = tiles + LD B, A + LD A,(HL-) + LD C, A + LD A,(HL-) ; A = h + LD H,(HL) ; H = w + LD L,A ; L = h + + CALL .get_xy_wtt + + POP BC + RET diff --git a/gbdk/gbdk-lib/libc/targets/sm83/get_xy_t.s b/gbdk/gbdk-lib/libc/targets/sm83/get_xy_t.s new file mode 100644 index 00000000..29739a19 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/get_xy_t.s @@ -0,0 +1,86 @@ + .include "global.s" + + .area _HOME + + ;; Store window tile table into (BC) at xy = DE of size WH = HL +.get_xy_wtt:: + PUSH HL ; Store WH + LDH A,(.LCDC) + AND #LCDCF_WIN9C00 + JR Z,.is98 + JR .is9c + ;; Store background tile table into (BC) at XY = DE of size WH = HL +.get_xy_btt:: + PUSH HL ; Store WH + LDH A,(.LCDC) + AND #LCDCF_BG9C00 + JR NZ,.is9c +.is98: + LD HL,#0x9800 + JR .get_xy_tt +.is9c: + LD HL,#0x9C00 + + ;; Store background tile table into (BC) at XY = DE, size WH on stack, from vram from address (HL) +.get_xy_tt:: + PUSH BC ; Store source + + SWAP E + RLC E + LD A,E + AND #0x03 + ADD H + LD B,A + LD A,#0xE0 + AND E + ADD D + LD C,A ; dest BC = HL + 0x20 * Y + X + + POP HL ; HL = source + POP DE ; DE = WH + PUSH DE ; store WH + PUSH BC ; store dest + +3$: ; Copy W tiles + + WAIT_STAT + LD A, (BC) + LD (HL+), A + + LD A, C ; inc dest and wrap around + AND #0xE0 + LD E, A + LD A, C + INC A + AND #0x1F + OR E + LD C, A + + DEC D + JR NZ, 3$ + + POP BC + POP DE + + DEC E + RET Z + + PUSH DE + + LD A, B ; next row and wrap around + AND #0xFC + LD E, A ; save high bits + + LD A,#0x20 + + ADD C + LD C, A + ADC B + SUB C + AND #0x03 + OR E ; restore high bits + LD B, A + + PUSH BC + + JR 3$ diff --git a/gbdk/gbdk-lib/libc/targets/sm83/gprint.c b/gbdk/gbdk-lib/libc/targets/sm83/gprint.c new file mode 100644 index 00000000..556dbd24 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/gprint.c @@ -0,0 +1,7 @@ +#include <gb/drawing.h> + +void gprint(char *str) NONBANKED +{ + while(*str) + wrtchr(*str++); +} diff --git a/gbdk/gbdk-lib/libc/targets/sm83/gprintf.c b/gbdk/gbdk-lib/libc/targets/sm83/gprintf.c new file mode 100644 index 00000000..560ad396 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/gprintf.c @@ -0,0 +1,86 @@ +#include <stdint.h> +#include <stdarg.h> +#include <gb/drawing.h> + +int8_t gprintf(char *fmt, ...) NONBANKED +{ + va_list ap; + int8_t nb = 0; + + va_start(ap, fmt); + for(; *fmt; fmt++) + if(*fmt == '%') { + switch(*++fmt) { + case 'c': { + /* char */ + char c = va_arg(ap, char); + wrtchr(c); + break; + } + case 'd': { + /* decimal int */ + int8_t b = va_arg(ap, int8_t); + gprintn(b, 10, SIGNED); + break; + } + case 'u': { + /* unsigned int */ + int8_t b = (int8_t)va_arg(ap, int); + gprintn(b, 10, UNSIGNED); + break; + } + case 'o': { + /* octal int */ + int8_t b = va_arg(ap, int8_t); + gprintn(b, 8, UNSIGNED); + break; + } + case 'x': { + /* hexadecimal int */ + int8_t b = va_arg(ap, int8_t); + gprintn(b, 16, UNSIGNED); + break; + } + case 's': { + /* string */ + char *s = va_arg(ap, char *); + gprint(s); + break; + } +#if 0 + case 'l': + /* long */ + switch(*++fmt) { + case 'd': + /* decimal long */ + gprintln(va_arg(ap, int16_t), 10, SIGNED); + break; + case 'u': + /* unsigned long */ + gprintln(va_arg(ap, int16_t), 10, UNSIGNED); + break; + case 'o': + /* octal long */ + gprintln(va_arg(ap, int16_t), 8, UNSIGNED); + break; + case 'x': + /* hexadecimal long */ + gprintln(va_arg(ap, int16_t), 16, UNSIGNED); + break; + } + break; +#endif + case '%': + /* % */ + wrtchr(*fmt); + break; + default: + return -1; + } + nb++; + } else + wrtchr(*fmt); + va_end(ap); + + return nb; +} diff --git a/gbdk/gbdk-lib/libc/targets/sm83/gprintln.c b/gbdk/gbdk-lib/libc/targets/sm83/gprintln.c new file mode 100644 index 00000000..a6ed1459 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/gprintln.c @@ -0,0 +1,19 @@ +#include <stdint.h> +#include <gb/drawing.h> + +/* Print a long number in any radix */ + +extern char *digits; + +void gprintln(int16_t number, int8_t radix, int8_t signed_value) NONBANKED +{ + uint16_t l; + + if(number < 0 && signed_value) { + wrtchr('-'); + number = -number; + } + if((l = (uint16_t)number / (uint16_t)radix) != 0) + gprintln(l, radix, UNSIGNED); + wrtchr(digits[(uint16_t)number % (uint16_t)radix]); +} diff --git a/gbdk/gbdk-lib/libc/targets/sm83/gprintn.c b/gbdk/gbdk-lib/libc/targets/sm83/gprintn.c new file mode 100644 index 00000000..cee919b5 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/gprintn.c @@ -0,0 +1,19 @@ +#include <stdint.h> +#include <gb/drawing.h> + +/* Print a number in any radix */ + +extern char *digits; + +void gprintn(int8_t number, int8_t radix, int8_t signed_value) NONBANKED +{ + uint8_t i; + + if(number < 0 && signed_value) { + wrtchr('-'); + number = -number; + } + if((i = (uint8_t)number / (uint8_t)radix) != 0) + gprintn(i, radix, UNSIGNED); + wrtchr(digits[(uint8_t)number % (uint8_t)radix]); +} diff --git a/gbdk/gbdk-lib/libc/targets/sm83/heap.s b/gbdk/gbdk-lib/libc/targets/sm83/heap.s new file mode 100644 index 00000000..991df234 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/heap.s @@ -0,0 +1,44 @@ +;-------------------------------------------------------------------------- +; heap.s +; +; Copyright (C) 2001, Michael Hope +; +; This library is free software; you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by the +; Free Software Foundation; either version 2, or (at your option) any +; later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this library; see the file COPYING. If not, write to the +; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, +; MA 02110-1301, USA. +; +; As a special exception, if you link this library with other files, +; some of which are compiled with SDCC, to produce an executable, +; this library does not by itself cause the resulting executable to +; be covered by the GNU General Public License. This exception does +; not however invalidate any other reasons why the executable file +; might be covered by the GNU General Public License. +;-------------------------------------------------------------------------- + +; Just stubs - not copyrightable + + ;; Stubs that hook the heap in + .globl ___sdcc_heap_init + + .area _GSINIT + call ___sdcc_heap_init + + .area _HEAP +___sdcc_heap:: + ;; For now just allocate 2k of heap. + .ds 2047 + + .area _HEAP_END +___sdcc_heap_end:: + .ds 1 diff --git a/gbdk/gbdk-lib/libc/targets/sm83/hiramcpy.s b/gbdk/gbdk-lib/libc/targets/sm83/hiramcpy.s new file mode 100644 index 00000000..c43b1b07 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/hiramcpy.s @@ -0,0 +1,34 @@ + .include "global.s" + + .area _HOME + +_hiramcpy:: + LDA HL,2(SP) ; Skip return address and registers + LD E,(HL) ; E = dst + LDA HL,5(SP) + LD A,(HL-) + LD D, A ; D = n + LD A,(HL-) ; HL = src + LD L,(HL) + LD H,A + + ;; Copy memory zone to HIRAM + ;; + ;; Entry conditions + ;; E = destination + ;; D = length + ;; HL = source + ;; + ;; Preserves: BC +.hiramcpy:: + LD A,E + LD E,C + LD C,A +1$: + LD A,(HL+) + LDH (C),A + INC C + DEC D + JR NZ,1$ + LD C,E + RET diff --git a/gbdk/gbdk-lib/libc/targets/sm83/init_tt.s b/gbdk/gbdk-lib/libc/targets/sm83/init_tt.s new file mode 100644 index 00000000..ccc5a395 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/init_tt.s @@ -0,0 +1,52 @@ + .include "global.s" + + .area _HOME + + ;; Initialize window tile table with B +.init_wtt:: + LDH A,(.LCDC) + AND #LCDCF_WIN9C00 + JR Z,.is98 + JR .is9c + ;; Initialize background tile table with B +.init_btt:: + LDH A,(.LCDC) + AND #LCDCF_BG9C00 + JR NZ,.is9c +.is98: + LD HL,#0x9800 ; HL = origin + JR .init_tt +.is9c: + LD HL,#0x9C00 ; HL = origin + +.init_tt:: + LD DE,#0x0400 ; One whole GB Screen + +.init_vram:: + SRL D + RR E + JR NC, 1$ + + WAIT_STAT + LD A, B + LD (HL+),A +1$: + LD A, D + OR E + RET Z + + INC D + INC E + JR 2$ +3$: + WAIT_STAT + LD A, B + LD (HL+),A + LD (HL+),A +2$: + DEC E + JR NZ, 3$ + DEC D + JR NZ, 3$ + + RET diff --git a/gbdk/gbdk-lib/libc/targets/sm83/init_vram.s b/gbdk/gbdk-lib/libc/targets/sm83/init_vram.s new file mode 100644 index 00000000..bfe49ade --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/init_vram.s @@ -0,0 +1,44 @@ + .include "global.s" + + .area _HOME + + .globl .init_wtt, .init_btt, .init_vram + + + ;; Initialize window tile table + ;; void init_win(char c); +_init_win:: + PUSH BC + LDA HL, 4(SP) + LD B, (HL) + CALL .init_wtt + POP BC + RET + + ;; Initialize background tile table + ;; void init_bkg(char c); +_init_bkg:: + PUSH BC + LDA HL, 4(SP) + LD B, (HL) + CALL .init_btt + POP BC + RET + + ;; Fills the VRAM memory region s of size n with c + ;; void _vmemset (void *s, char c, size_t n); +_vmemset:: + PUSH BC + LDA HL, 8(SP) + LD A, (HL-) + LD D, A + LD A, (HL-) + LD E, A + LD A, (HL-) + LD B, A + LD A, (HL-) + LD L, (HL) + LD H, A + CALL .init_vram + POP BC + RET
\ No newline at end of file diff --git a/gbdk/gbdk-lib/libc/targets/sm83/input.s b/gbdk/gbdk-lib/libc/targets/sm83/input.s new file mode 100644 index 00000000..b282b908 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/input.s @@ -0,0 +1,639 @@ + .include "global.s" + + ;; Note that while gets uses a pointer, the pointer had better + ;; be in non-banked RAM else bad things will happen. + + .globl .copy_vram + .globl .set_xy_wtt + .globl .mv_sprite + .globl .set_sprite_prop + .globl .set_sprite_tile + .globl .jpad + .globl .padup + + .MINMSPOSX = 0x02 ; In tiles + .MINMSPOSY = 0x0A + .MAXMSPOSX = 0x11 + .MAXMSPOSY = 0x0F + .INIMSPOSX = .MINMSPOSX + .INIMSPOSY = .MINMSPOSY + + .KBDWINPOSY = 0x08 ; In tiles + .KBDSIZE = 0x1006 + + .MSOFFSETX = 0x0C ; In pixels + .MSOFFSETY = 0x14 + + .MINACCEL = 0x0800 + .MAXACCEL = 0x0100 + + .CR = 0x0A ; Unix +; .CR = 0x0D ; Dos + + .globl .tmode_out ; From 'output.s' + .globl .put_char + .globl .del_char + .globl .cury + + .area _INPUT_HEADER (ABS) + + .org .MODE_TABLE+4*.T_MODE_INOUT + JP .tmode_inout + + .module Terminal + + .area _DATA + +.msx: ; Mouse position + .ds 0x01 +.msy: + .ds 0x01 +.msacc: ; Mouse acceleration + .ds 0x02 +.msstate: ; Mouse state + .ds 0x01 +.mschanged: ; Did the mouse move? + .ds 0x01 +.string_len: ; Used length of input buffer + .ds 0x01 + + .area _HOME + + ;; Enter text mode with input +.tmode_inout:: + DI ; Disable interrupts + + ;; Turn the screen off + LDH A,(.LCDC) + AND #LCDCF_ON + JR Z,1$ + + ;; Turn the screen off + CALL .display_off +1$: + + LD A,(.mode) + AND #.T_MODE + CALL Z,.tmode_out + + LD BC,#.tp1 ; Move pointer + LD HL,#0x8000 + LD DE,#.endtp1-.tp1 + CALL .copy_vram + + LD A,#<.MINACCEL ; Acceleration + LD (.msacc),A + LD A,#>.MINACCEL + LD (.msacc+1),A + + ;; Initialize window + LD BC,#.frame_tiles + LD DE,#0x140A ; 0x140A + LD HL,#0 + CALL set_recoded_win_tiles + + LD BC,#.kbdtable + LD DE,#.KBDSIZE + LD HL,#(0x20 * 2 + 2) ; X=2, Y=2 + CALL set_recoded_win_tiles + + LD A,#.MINWNDPOSX + LDH (.WX),A + LD A,#.MAXWNDPOSY ; Hide window + LDH (.WY),A + + XOR A + ;; Initialize sprite + LD C,A ; Sprite 0x00 + LD D,A ; Default sprite properties + CALL .set_sprite_prop + XOR A + LD C,A ; Sprite 0x00 + LD D,A ; Tile 0x00 + CALL .set_sprite_tile + LD A,#0b00101100 + LDH (.OBP0),A + + ;; Turn the screen on + LD A,#(LCDCF_ON | LCDCF_WIN9C00 | LCDCF_WINOFF | LCDCF_BG8800 | LCDCF_BG9800 | LCDCF_OBJ8 | LCDCF_OBJOFF | LCDCF_BGON) + LDH (.LCDC),A + + LD A,#.T_MODE_INOUT + LD (.mode),A + + EI ; Enable interrupts + + RET + +set_recoded_win_tiles:: + LDH A,(.LCDC) + AND #LCDCF_WIN9C00 + JR Z,2$ + LD A,#0x9C + JR 3$ +2$: + LD A,#0x98 +3$: + ADD H + LD H,A + PUSH DE + PUSH HL +4$: + LD A,(BC) + INC BC + PUSH BC + PUSH HL + + LD C,A + LD HL,#(font_current+1) ; font_current+sfont_handle_font + LD A,(HL+) + LD H,(HL) + LD L,A + LD A,(HL+) + AND #3 + CP #2 ; FONT_NOENCODING + JR Z,5$ + INC HL + LD B,#0 + ADD HL,BC + LD C,(HL) +5$: + POP HL + + WAIT_STAT + LD A,C + LD (HL+),A + + POP BC + + DEC D + JR NZ,4$ + + POP HL + POP DE + + LD A,L + ADD #0x20 + LD L,A + ADC H + SUB L + LD H,A + DEC E + + PUSH DE + PUSH HL + JR NZ,4$ + + ADD SP,#4 + RET + + ;; Prompt the user for a char and return it in A +.get_char: + PUSH BC + PUSH DE + PUSH HL + CALL .show_kbd + CALL .show_mouse +1$: + CALL .track_mouse + CALL .update_mouse + CALL .jpad + LD D,A + AND #.A ; Is A pressed ? + JP Z,1$ + + LD A,(.msy) ; Look for char under the mouse + SUB #.MINMSPOSY + JR Z,12$ + LD E,A + XOR A +11$: + ADD #.MAXMSPOSX-.MINMSPOSX+1 + DEC E + JR NZ,11$ +12$: + LD E,A + LD A,(.msx) + SUB #.MINMSPOSX + ADD E + LD HL,#.kbdtable + LD B,#0x00 + LD C,A + ADD HL,BC + LD B,(HL) + + CALL .hide_mouse + CALL .hide_kbd + LD A,B + + POP HL + POP DE + POP BC + RET + + ;; Prompt the user for a string and store it in (HL) +.get_string: + PUSH BC + PUSH DE + PUSH HL + CALL .show_kbd + CALL .show_bkg + CALL .show_mouse + XOR A + LD (.string_len),A +1$: + CALL .track_mouse + CALL .update_mouse + CALL .jpad + LD D,A + AND #.A ; Is A pressed ? + JP NZ,10$ + LD A,D + AND #.B ; Is B pressed ? + JP NZ,20$ + LD A,D + AND #.SELECT ; Is SELECT pressed ? + JP NZ,30$ + LD A,D + AND #.START ; Is START pressed ? + JR Z,1$ + CALL .padup ; Wait for button to be depressed + + LD A,#.CR + CALL .put_char + LD (HL),#0x00 + CALL .hide_mouse + CALL .hide_bkg + CALL .hide_kbd + POP HL + POP DE + POP BC + RET + +10$: + ;; Insert a character at cursor position + LD A,(.string_len) ; Check buffer length +; CP #.BUFLEN-1 ; Keep 1 char for EOS +; JR Z,13$ + INC A + LD (.string_len),A ; Update it + LD A,(.msy) ; Look for char under the mouse + SUB #.MINMSPOSY + JR Z,12$ + LD E,A + XOR A +11$: + ADD #.MAXMSPOSX-.MINMSPOSX+1 + DEC E + JR NZ,11$ +12$: + LD E,A + LD A,(.msx) + SUB #.MINMSPOSX + ADD E + PUSH HL + LD HL,#.kbdtable + LD B,#0x00 + LD C,A + ADD HL,BC + LD A,(HL) + POP HL + LD (HL+),A ; Add it into input buffer + CALL .put_char ; Print it + CALL .show_bkg ; Ensure the text is not hidden +13$: + CALL .padup ; Wait for button to be depressed + JP 1$ + +20$: + ;; Delete a character at cursor position + LD A,(.string_len) ; Is there any char in the buffer ? + OR A + JR Z,21$ + DEC A ; Yes + LD (.string_len),A ; Update buffer length + DEC HL + CALL .del_char +21$: + CALL .padup ; Wait for button to be depressed + JP 1$ + +30$: + CALL .hide_mouse + CALL .hide_bkg + CALL .hide_kbd + CALL .padup ; Wait for button to be depressed + CALL .show_kbd + CALL .show_bkg + CALL .show_mouse + JP 1$ + +.show_kbd: + PUSH BC + PUSH DE + LDH A,(.LCDC) + OR #LCDCF_WINON ; Window = On + LDH (.LCDC),A + LD A,#.MAXWNDPOSY ; Show window +1$: + BIT 0,A ; Wait for VBL every 2 pixels (slow down) + JR NZ,2$ + LD B,A + CALL .wait_vbl_done + LD A,B +2$: + LDH (.WY),A + CP #.KBDWINPOSY*0x08 + JR Z,99$ + DEC A + JR 1$ +99$: + POP DE + POP BC + RET + +.hide_kbd: + PUSH BC + PUSH DE + LD A,#.KBDWINPOSY*0x08+1 +1$: ; Hide window + BIT 0,A ; Wait for VBL every 2 pixels (slow down) + JR Z,2$ + LD B,A + CALL .wait_vbl_done + LD A,B +2$: + LDH (.WY),A + CP #.MAXWNDPOSY + JR Z,3$ + INC A + JR 1$ +3$: + LDH A,(.LCDC) + AND #~LCDCF_WINON ; Window = Off + LDH (.LCDC),A + POP DE + POP BC + RET + +.show_bkg: + PUSH BC + PUSH DE + LDH A,(.SCY) + LD D,A + LD A,(.cury) + SUB #.KBDWINPOSY-1 + JR C,99$ + JR Z,99$ + SLA A ; A = A * 8 + SLA A + SLA A + SUB D + JR C,99$ + JR Z,99$ + LD C,A + LDH A,(.SCY) +1$: + BIT 0,A ; Wait for VBL every 2 pixels (slow down) + JR Z,2$ + LD B,A + CALL .wait_vbl_done + LD A,B +2$: + INC A + LDH (.SCY),A + DEC C + JR Z,99$ + JR 1$ +99$: + POP DE + POP BC + RET + +.hide_bkg: + LDH A,(.SCY) + OR A + RET Z + PUSH BC + PUSH DE +1$: + BIT 0,A ; Wait for VBL every 2 pixels (slow down) + JR Z,2$ + LD B,A + CALL .wait_vbl_done + LD A,B +2$: + DEC A + LDH (.SCY),A + JR Z,99$ + JR 1$ +99$: + POP DE + POP BC + RET + +.show_mouse: + LD A,#.INIMSPOSX + LD (.msx),A + LD A,#.INIMSPOSY + LD (.msy),A + CALL .set_mouse + LDH A,(.LCDC) + OR #LCDCF_OBJON ; OBJ = On + LDH (.LCDC),A + RET + +.hide_mouse: + LDH A,(.LCDC) + AND #~LCDCF_OBJON ; OBJ = Off + LDH (.LCDC),A + RET + +.track_mouse: + PUSH BC + PUSH DE + PUSH HL + XOR A + LD (.mschanged),A ; Default to no change + CALL .jpad + LD D,A + + LD HL,#.msstate + AND #.UP+.DOWN+.LEFT+.RIGHT + JR NZ,1$ + LD (HL),#0x00 ; Reset state + JP 99$ +1$: + LD A,(HL) + LD (HL),#0x01 ; Set state + OR A ; Was it 0 ? + LD HL,#.msacc ; Acceleration + JR NZ,2$ + ; Yes + LD (HL),#<.MINACCEL + INC HL + LD (HL),#>.MINACCEL + JR 4$ ; Update position +2$: + LD A,(HL+) + LD C, A + LD B,(HL) + DEC BC + LD A,B + OR C + JR Z,3$ + LD (HL),B + DEC HL + LD (HL),C + JP 99$ +3$: ; Set new acceleration to maximum + LD (HL),#>.MAXACCEL + DEC HL + LD (HL),#<.MAXACCEL +4$: ; Update position + LD A,#0x01 + LD (.mschanged),A + LD A,D + AND #.UP ; Is UP pressed ? + JR Z,6$ + LD A,(.msy) + CP #.MINMSPOSY + JR Z,5$ + DEC A + LD (.msy),A + JR 6$ +5$: + LD A,#.MAXMSPOSY + LD (.msy),A +6$: + LD A,D + AND #.DOWN ; Is DOWN pressed ? + JR Z,8$ + LD A,(.msy) + CP #.MAXMSPOSY + JR Z,7$ + INC A + LD (.msy),A + JR 8$ +7$: + LD A,#.MINMSPOSY + LD (.msy),A +8$: + LD A,D + AND #.LEFT ; Is LEFT pressed ? + JR Z,10$ + LD A,(.msx) + CP #.MINMSPOSX + JR Z,9$ + DEC A + LD (.msx),A + JR 10$ +9$: + LD A,#.MAXMSPOSX + LD (.msx),A +10$: + LD A,D + AND #.RIGHT ; Is RIGHT pressed ? + JR Z,99$ + LD A,(.msx) + CP #.MAXMSPOSX + JR Z,11$ + INC A + LD (.msx),A + JR 99$ +11$: + LD A,#.MINMSPOSX + LD (.msx),A +99$: + POP HL + POP DE + POP BC + RET + +.update_mouse: + LD A,(.mschanged) ; Did it change ? + OR A + RET Z ; No +.set_mouse: + PUSH BC + PUSH DE + PUSH HL + LD C,#0x00 ; Sprite 0x00 + LD A,(.msx) + SLA A ; A = A * 8 + SLA A + SLA A + ADD #.MSOFFSETX + LD D,A + LD A,(.msy) + SLA A ; A = A * 8 + SLA A + SLA A + ADD #.MSOFFSETY + LD E,A + CALL .mv_sprite + POP HL + POP DE + POP BC + RET + +_getchar:: + LD A,(.mode) + CP #.T_MODE_INOUT + JR Z,1$ + PUSH BC + CALL .tmode_inout + POP BC +1$: + CALL .get_char + LD E,A + RET + +_gets:: + LD A,(.mode) + CP #.T_MODE_INOUT + JR Z,1$ + PUSH BC + CALL .tmode_inout + POP BC +1$: + LDA HL,2(SP) ; Skip return address + LD A,(HL+) + LD H,(HL) ; HL = s + LD L,A + PUSH HL + CALL .get_string + POP DE + RET + +.tp1: + +.pointers: + + ; Tile 0x00 + .byte 0xFF,0xFF,0xFE,0x82,0xFC,0x84,0xFC,0x84,0xFE,0x82,0xFF,0xB1,0xCF,0xC9,0x87,0x87 + +.endtp1: + +.frame_tiles: + .byte 0x1C,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x1D + .byte 0x0F,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x0F + .byte 0x0F,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x0F + .byte 0x0F,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x0F + .byte 0x0F,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x0F + .byte 0x0F,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x0F + .byte 0x0F,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x0F + .byte 0x0F,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x0F + .byte 0x0F,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x0F + .byte 0x1E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x1F + +.kbdtable: + .db 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27 + .db 0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F + .ascii "0123456789:" + .db 0x3B + .ascii "<=>?" + .ascii "@ABCDEFGHIJKLMNO" + .ascii "PQRSTUVWXYZ[\]^_" + .ascii "`abcdefghijklmno" + .ascii "pqrstuvwxyz{|}~ " diff --git a/gbdk/gbdk-lib/libc/targets/sm83/joy.s b/gbdk/gbdk-lib/libc/targets/sm83/joy.s new file mode 100644 index 00000000..7dbbfbae --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/joy.s @@ -0,0 +1,47 @@ + .include "global.s" + + .globl .int + + .area _HEADER_JOY (ABS) + + .org 0x60 ; JOY +.int_JOY: + PUSH AF + PUSH HL + LD HL,#.int_0x60 + JP .int + + .area _HOME + +_add_JOY:: + PUSH BC + LDA HL,4(SP) ; Skip return address and registers + LD C,(HL) + INC HL + LD B,(HL) + CALL .add_JOY + POP BC + RET + +.add_JOY:: + LD HL,#.int_0x60 + JP .add_int + +_remove_JOY:: + PUSH BC + LDA HL,4(SP) ; Skip return address and registers + LD C,(HL) + INC HL + LD B,(HL) + CALL .remove_JOY + POP BC + RET + +.remove_JOY:: + LD HL,#.int_0x60 + JP .remove_int + + .area _DATA + +.int_0x60:: + .blkw 0x08 diff --git a/gbdk/gbdk-lib/libc/targets/sm83/lcd.s b/gbdk/gbdk-lib/libc/targets/sm83/lcd.s new file mode 100644 index 00000000..5270e2c3 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/lcd.s @@ -0,0 +1,81 @@ + .include "global.s" + + + .area _HEADER_LCD (ABS) + + .org 0x48 ; LCD +.int_LCD: + JP .int_lcd_handler + + .area _HOME + +.int_lcd_handler: + PUSH AF + PUSH HL + PUSH BC + PUSH DE + LD HL, #.int_0x48 + 0 + PUSH HL ; for stack compatibility with std handler only! + LD A,(HL+) + LD H,(HL) + LD L,A + OR H + JR Z, 1$ + RST 0x20 ; .call_hl + LD HL, #.int_0x48 + 2 + LD A,(HL+) + LD H,(HL) + LD L,A + OR H + JR Z, 1$ + RST 0x20 ; .call_hl + LD HL, #.int_0x48 + 4 + LD A,(HL+) + LD H,(HL) + LD L,A + OR H + CALL NZ, .call_hl +1$: + POP HL + POP DE + POP BC + POP HL + + ;; we return at least at the beginning of mode 2 + WAIT_STAT + + POP AF + RETI + +_add_LCD:: + PUSH BC + LDA HL,4(SP) ; Skip return address and registers + LD C,(HL) + INC HL + LD B,(HL) + CALL .add_LCD + POP BC + RET + +.add_LCD:: + LD HL,#.int_0x48 + JP .add_int + +_remove_LCD:: + PUSH BC + LDA HL,4(SP) ; Skip return address and registers + LD C,(HL) + INC HL + LD B,(HL) + CALL .remove_LCD + POP BC + RET + +.remove_LCD:: + LD HL,#.int_0x48 + JP .remove_int + + .area _DATA + +.int_0x48:: + .blkw 0x08 diff --git a/gbdk/gbdk-lib/libc/targets/sm83/metasprites.s b/gbdk/gbdk-lib/libc/targets/sm83/metasprites.s new file mode 100644 index 00000000..6bc50b1c --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/metasprites.s @@ -0,0 +1,82 @@ + .include "global.s" + + .title "Metasprites" + .module Metasprites + + .area _DATA + +___current_metasprite:: + .ds 0x02 +___current_base_tile:: + .ds 0x01 + + .area _INITIALIZED +___render_shadow_OAM:: + .ds 0x01 + + .area _INITIALIZER + .db #>_shadow_OAM + + .area _CODE + +; uint8_t __move_metasprite(uint8_t id, uint8_t x, uint8_t y) + +___move_metasprite:: + ldhl sp, #4 + ld a, (hl-) + ld b, a + ld a, (hl-) + ld c, a + ld a, (hl) + cp #40 + jr nc, 3$ + + add a + add a + ld e, a + + ld hl, #___current_metasprite + ld a, (hl+) + ld h, (hl) + ld l, a + + ld a, (___render_shadow_OAM) + ld d, a +1$: + ld a, (hl+) ; dy + cp #0x80 + jr z, 2$ + add b + ld b, a + ld (de), a + inc e + + ld a, (hl+) ; dx + add c + ld c, a + ld (de), a + inc e + + ld a, (___current_base_tile) + add (hl) ; tile + inc hl + ld (de), a + inc e + + ld a, (hl+) ; props + ld (de), a + inc e + + ld a, e + cp #160 + jr c, 1$ +2$: + ld a, e + srl a + srl a + ldhl sp, #2 +3$: + sub (hl) + ld e, a + + ret diff --git a/gbdk/gbdk-lib/libc/targets/sm83/metasprites_flip.s b/gbdk/gbdk-lib/libc/targets/sm83/metasprites_flip.s new file mode 100644 index 00000000..9a86edea --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/metasprites_flip.s @@ -0,0 +1,203 @@ + .include "global.s" + + .title "Metasprites" + .module Metasprites + + .area _DATA + + .globl ___current_metasprite, ___current_base_tile, ___render_shadow_OAM + + .area _CODE + +; uint8_t __move_metasprite(uint8_t id, uint8_t x, uint8_t y) + +___move_metasprite_hflip:: + ldhl sp, #4 + ld a, (hl-) + ld b, a + ld a, (hl-) + ld c, a + ld a, (hl) + cp #40 + jr nc, 3$ + + add a + add a + ld e, a + + ld hl, #___current_metasprite + ld a, (hl+) + ld h, (hl) + ld l, a + + ld a, (___render_shadow_OAM) + ld d, a +1$: + ld a, (hl+) + cp #0x80 + jr z, 2$ + cpl + inc a + add b + ld b, a + ld (de), a + inc e + + ld a, (hl+) ; dx + add c + ld c, a + ld (de), a + inc e + + ld a, (___current_base_tile) + add (hl) ; tile + inc hl + ld (de), a + inc e + + ld a, (hl+) ; props + xor #0x40 + ld (de), a + inc e + + ld a, e + cp #160 + jr c, 1$ +2$: + ld a, e + srl a + srl a + ldhl sp, #2 +3$: + sub (hl) + ld e, a + + ret + +___move_metasprite_vflip:: + ldhl sp, #4 + ld a, (hl-) + ld b, a + ld a, (hl-) + ld c, a + ld a, (hl) + cp #40 + jr nc, 3$ + + add a + add a + ld e, a + + ld hl, #___current_metasprite + ld a, (hl+) + ld h, (hl) + ld l, a + + ld a, (___render_shadow_OAM) + ld d, a +1$: + ld a, (hl+) ; dy + cp #0x80 + jr z, 2$ + add b + ld b, a + ld (de), a + inc e + + ld a, (hl+) ; dx + cpl + inc a + add c + ld c, a + ld (de), a + inc e + + ld a, (___current_base_tile) + add (hl) ; tile + inc hl + ld (de), a + inc e + + ld a, (hl+) ; props + xor #0x20 + ld (de), a + inc e + + ld a, e + cp #160 + jr c, 1$ +2$: + ld a, e + srl a + srl a + ldhl sp, #2 +3$: + sub (hl) + ld e, a + + ret + +___move_metasprite_hvflip:: + ldhl sp, #4 + ld a, (hl-) + ld b, a + ld a, (hl-) + ld c, a + ld a, (hl) + cp #40 + jr nc, 3$ + + add a + add a + ld e, a + + ld hl, #___current_metasprite + ld a, (hl+) + ld h, (hl) + ld l, a + + ld a, (___render_shadow_OAM) + ld d, a +1$: + ld a, (hl+) + cp #0x80 + jr z, 2$ + cpl + inc a + add b + ld b, a + ld (de), a + inc e + + ld a, (hl+) ; dx + cpl + inc a + add c + ld c, a + ld (de), a + inc e + + ld a, (___current_base_tile) + add (hl) ; tile + inc hl + ld (de), a + inc e + + ld a, (hl+) ; props + xor #0x60 + ld (de), a + inc e + + ld a, e + cp #160 + jr c, 1$ +2$: + ld a, e + srl a + srl a + ldhl sp, #2 +3$: + sub (hl) + ld e, a + + ret diff --git a/gbdk/gbdk-lib/libc/targets/sm83/metasprites_hide.s b/gbdk/gbdk-lib/libc/targets/sm83/metasprites_hide.s new file mode 100644 index 00000000..0762e9e1 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/metasprites_hide.s @@ -0,0 +1,52 @@ + .include "global.s" + + .title "Metasprites" + .module Metasprites + + .globl ___current_metasprite, ___render_shadow_OAM + + .area _CODE + + +; void __hide_metasprite(uint8_t id) + +___hide_metasprite:: + ldhl sp, #2 + ld a, (hl) + cp #40 + ret nc + + add a + add a + ld e, a + + ld hl, #___current_metasprite + ld a, (hl+) + ld h, (hl) + ld l, a + + ld bc, #3 + + ld a, (___render_shadow_OAM) + ld d, a +1$: + ld a, (hl+) + cp #0x80 + ret z + + add hl, bc + + xor a + ld (de), a + + inc e + inc e + inc e + inc e + + ld a, e + cp #160 + + jr c, 1$ + + ret
\ No newline at end of file diff --git a/gbdk/gbdk-lib/libc/targets/sm83/metasprites_hide_spr.s b/gbdk/gbdk-lib/libc/targets/sm83/metasprites_hide_spr.s new file mode 100644 index 00000000..54a3d57f --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/metasprites_hide_spr.s @@ -0,0 +1,71 @@ + .include "global.s" + + .title "Metasprites" + .module Metasprites + + .globl ___render_shadow_OAM + + .area _CODE + +; void hide_sprites_range(UINT8 from, UINT8 to) + +_hide_sprites_range:: + ldhl sp, #2 + ld a, (hl+) + + cp #40 + ret nc + + add a + add a + ld e, a + + ld a, (hl-) + sub (hl) + + ret c + ret z + + ld hl, #___render_shadow_OAM + ld h, (hl) + ld l, e + + ld de, #4 + + rra ; carry is never set here, because of ret c above + jr nc, 0$ + + ld (hl), d + add hl, de ; carry is reset here because hl can't overflow + + ret z ; z is not affected by 16-bit add + +0$: + srl a + jr nc, 1$ + + ld (hl), d + add hl, de + + ld (hl), d + add hl, de + + ret z ; z is not affected by 16-bit add + +1$: + ld (hl), d + add hl, de + + ld (hl), d + add hl, de + + ld (hl), d + add hl, de + + ld (hl), d + add hl, de + + dec a + jr nz, 1$ + + ret diff --git a/gbdk/gbdk-lib/libc/targets/sm83/mode.s b/gbdk/gbdk-lib/libc/targets/sm83/mode.s new file mode 100644 index 00000000..2634bd88 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/mode.s @@ -0,0 +1,30 @@ + .include "global.s" + + .title "screen modes" + .module Modes + + ;; BANKED: checked + .area _HOME + +_mode:: + LDA HL,2(SP) ; Skip return address + LD L,(HL) + LD H,#0x00 + +.set_mode:: + LD A,L + LD (.mode),A + + ;; AND to get rid of the extra flags + AND #0x03 + LD L,A + LD BC,#.MODE_TABLE + SLA L ; Multiply mode by 4 + SLA L + ADD HL,BC + JP (HL) ; Jump to initialization routine + +_get_mode:: + LD HL,#.mode + LD E,(HL) + RET diff --git a/gbdk/gbdk-lib/libc/targets/sm83/mv_spr.s b/gbdk/gbdk-lib/libc/targets/sm83/mv_spr.s new file mode 100644 index 00000000..f4fb9259 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/mv_spr.s @@ -0,0 +1,18 @@ + .include "global.s" + + .area _HOME + + ;; Move sprite number C at XY = DE +.mv_sprite:: + LD HL,#_shadow_OAM ; Calculate origin of sprite info + SLA C ; Multiply C by 4 + SLA C + LD B,#0x00 + ADD HL,BC + + LD A,E ; Set Y + LD (HL+),A + + LD A,D ; Set X + LD (HL+),A + RET diff --git a/gbdk/gbdk-lib/libc/targets/sm83/nowait.s b/gbdk/gbdk-lib/libc/targets/sm83/nowait.s new file mode 100644 index 00000000..7b19152b --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/nowait.s @@ -0,0 +1,10 @@ + ;; interrupt handler that does not wait for .STAT + ;; must be the last one in chain +_nowait_int_handler:: + ADD SP,#4 + + POP DE + POP BC + POP HL + POP AF + RETI diff --git a/gbdk/gbdk-lib/libc/targets/sm83/pad.s b/gbdk/gbdk-lib/libc/targets/sm83/pad.s new file mode 100644 index 00000000..917cc46c --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/pad.s @@ -0,0 +1,68 @@ + .include "global.s" + + .area _HOME + + ;; Wait until all buttons have been released +.padup:: +_waitpadup:: + PUSH AF ; Save modified registers + PUSH DE +1$: + LD D,#0x7F ; wait for .jpad return zero 127 times in a row +2$: + CALL .jpad + OR A ; Have all buttons been released? + JR NZ,1$ ; Not yet + + DEC D + JR NZ,2$ + + POP DE + POP AF + RET + + ;; Get Keypad Button Status + ;; The following bits are set if pressed: + ;; 0x80 - Start 0x08 - Down + ;; 0x40 - Select 0x04 - Up + ;; 0x20 - B 0x02 - Left + ;; 0x10 - A 0x01 - Right +_joypad:: +.jpad:: + LD A,#.P15 + LDH (.P1),A ; Turn on P15 + + LDH A,(.P1) ; Delay + LDH A,(.P1) + AND #0x0F + LD E,A + LD A,#.P14 + LDH (.P1),A ; Turn on P14 + LDH A,(.P1) ; Delay + LDH A,(.P1) + LDH A,(.P1) + LDH A,(.P1) + LDH A,(.P1) + LDH A,(.P1) + AND #0x0F + SWAP A + OR E + CPL + LD E,A + LD A,#(.P14 | .P15) + LDH (.P1),A ; Turn off P14 and P15 (reset joypad) + LD A,E + RET + + ;; Wait for the key to be pressed +_waitpad:: + LDA HL,2(SP) ; Skip return address + LD D,(HL) + ;; Wait for the key in D to be pressed +.wait_pad:: +1$: + CALL .jpad ; Read pad + AND D ; Compare with mask? + JR Z,1$ ; Loop if no intersection + RET + diff --git a/gbdk/gbdk-lib/libc/targets/sm83/pad_ex.s b/gbdk/gbdk-lib/libc/targets/sm83/pad_ex.s new file mode 100644 index 00000000..95684b2e --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/pad_ex.s @@ -0,0 +1,132 @@ + .include "global.s" + + .MLT_REQ = 0x11 + + .area _HOME + +_joypad_init:: + call .sgb_check + ld a, e + inc e + or a + + jr Z, 1$ + + ldhl sp, #0x02 + ld e, (hl) + + add sp, #-0x10 + ldhl sp, #0 + ld c, #0x10 + xor a + rst 0x28 + + ldhl sp, #0 + ld a, #((.MLT_REQ << 3) | 1) + ld (hl+), a + + ld a, e + + cp a, #0x02 + jr Z, 3$ + cp a, #0x04 + jr Z, 4$ + jr 5$ + +3$: + ld a, #0x01 + ld (hl-), a + call .sgb_transfer + ld e, #0x02 + jr 2$ + +4$: + ld a, #0x03 + ld (hl-), a + call .sgb_transfer + ld e, #0x04 + jr 2$ +5$: + ld a, #0x00 + ld (hl-), a + call .sgb_transfer + ld e, #0x01 +2$: + add sp, #0x10 +1$: + ldhl sp, #3 + ld a, (hl+) + ld h, (hl) + ld l, a + ld a, e + ld (hl+), a + xor a + ld (hl+), a + ld (hl+), a + ld (hl+), a + ld (hl), a + ret + +_joypad_ex:: + lda hl, 2(sp) + ld a, (hl+) + ld e, a + ld d, (hl) + +.joypad_ex:: + ld a, (de) + inc de + or a + jr z, 2$ + + dec a + and #3 + inc a +2$: + push bc + ld b, a +1$: + ld a, #(.P14 | .P15) + ldh (#.P1), a + ldh a, (#.P1) + ldh a, (#.P1) + ldh a, (#.P1) + ldh a, (#.P1) + and #0x0f + sub #0x0f + cpl + inc a ; A contains joypad number + + and #0x03 ; buffer overrun protection + + add e ; HL = DE + A + ld l, a + adc d + sub l + ld h, a + + ld a, #.P15 + ldh (#.P1), a + ldh a, (#.P1) + ldh a, (#.P1) + and #0x0f + ld c, a + ld a, #.P14 + ldh (#.P1), a + ldh a, (#.P1) + ldh a, (#.P1) + ldh a, (#.P1) + ldh a, (#.P1) + ldh a, (#.P1) + ldh a, (#.P1) + and #0x0f + swap a + or c + cpl + ld (hl), a + + dec b + jr nz, 1$ + pop bc + + ret diff --git a/gbdk/gbdk-lib/libc/targets/sm83/rle_decompress.s b/gbdk/gbdk-lib/libc/targets/sm83/rle_decompress.s new file mode 100644 index 00000000..4c72e357 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/rle_decompress.s @@ -0,0 +1,116 @@ + .include "global.s" + + .module RLE_DECOMPRESS + + .area _DATA + +rle_cursor: + .ds 0x02 +rle_counter: + .ds 0x01 +rle_current: + .ds 0x01 + + .area _CODE + +_rle_init:: + ldhl sp, #2 + ld a, (hl+) + ld e, (hl) + ld hl, #rle_cursor + ld (hl+), a + ld a, e + ld (hl+), a + xor a + ld (hl+), a + ld (hl), a + ld e, #1 + ret + +_rle_decompress:: + ;; Pop the return address + ldhl sp, #2 + ld a, (hl+) + ld c, a + ld a, (hl+) + ld d, a ; de == dest + ld b, (hl) ; b == count + + ld hl, #rle_cursor + ld a, (hl+) + ld h, (hl) + ld l, a ; hl == cursor + + or h + ld e, a + ret z + + ld e, c + + ld a, (rle_counter) + or a + ld c, a + jr z, 1$ + + ld a, (rle_current) + bit 7, c + jr nz, 10$ + jr 11$ +1$: + ;; Fetch the run + ld c, (hl) + inc hl + ;; Negative means a run +8$: + bit 7, c + jr z, 2$ + ;; Expanding a run + ld a, (hl+) +3$: + ld (de), a + inc de + + dec b + jr z, 6$ +10$: + inc c + jr NZ, 3$ + jr 1$ +2$: + ;; Zero means end of a block + inc c + dec c + jr z, 4$ + ;; Expanding a block +5$: + ld a, (hl+) + ld (de), a + inc de + + dec b + jr z, 6$ +11$: + dec c + jr NZ, 5$ + jr 1$ +4$: + ;; save state and exit + ld hl, #rle_cursor + xor a + ld (hl+), a + ld (hl), a + ld e, a + ret +6$: + ;; save state and exit + ld d, h + ld e, l + ld hl, #rle_current + ld (hl-), a + ld a, c + ld (hl-), a + ld a, d + ld (hl-), a + ld (hl), e + ld e, #1 + ret
\ No newline at end of file diff --git a/gbdk/gbdk-lib/libc/targets/sm83/serial.s b/gbdk/gbdk-lib/libc/targets/sm83/serial.s new file mode 100644 index 00000000..b948ca1d --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/serial.s @@ -0,0 +1,140 @@ + .include "global.s" + + .globl .int + + .globl __io_out + .globl __io_in + .globl __io_status + + .area _HEADER_SIO (ABS) + + .org 0x58 ; SIO +.int_SIO: + PUSH AF + PUSH HL + LD HL,#.int_0x58 + JP .int + + .area _GSINIT + + ;; initialize SIO + LD BC,#.serial_IO + CALL .add_SIO + + XOR A + LDH (.IF),A + + LDH A,(.IE) + OR A,#0b00001000 ; Serial I/O = On + LDH (.IE),A + + LDH (.SC),A ; Use external clock + LD A,#.DT_IDLE + LDH (.SB),A ; Send IDLE byte + LD A,#0x80 + LDH (.SC),A ; Use external clock + + .area _HOME + +_add_SIO:: + PUSH BC + LDA HL,4(SP) ; Skip return address and registers + LD C,(HL) + INC HL + LD B,(HL) + CALL .add_SIO + POP BC + RET + +.add_SIO:: + LD HL,#.int_0x58 + JP .add_int + +_remove_SIO:: + PUSH BC + LDA HL,4(SP) ; Skip return address and registers + LD C,(HL) + INC HL + LD B,(HL) + CALL .remove_SIO + POP BC + RET + +.remove_SIO:: + LD HL,#.int_0x58 + JP .remove_int + + ;; Serial interrupt +.serial_IO:: + LD A,(__io_status) ; Get status + + CP #.IO_RECEIVING + JR NZ, 1$ + + ;; Receiving data + LDH A,(.SB) ; Get data byte + LD (__io_in),A ; Store it + +2$: + LD A,#.IO_IDLE +3$: + LD (__io_status),A ; Store status + + XOR A + LDH (.SC),A ; Use external clock + LD A,#.DT_IDLE + LDH (.SB),A ; Reply with IDLE byte +4$: + LD A,#0x80 + LDH (.SC),A ; Enable transfer with external clock + RET + +1$: + CP #.IO_SENDING + JR NZ, 4$ + + ;; Sending data + LDH A,(.SB) ; Get data byte + CP #.DT_RECEIVING + JR Z, 2$ + LD A,#.IO_ERROR + JR 3$ + + .area _DATA + +__io_out:: + .ds 0x01 ; Byte to send +__io_in:: + .ds 0x01 ; Received byte +__io_status:: + .ds 0x01 ; Status of serial IO +.int_0x58:: + .blkw 0x08 + + .area _CODE + + ;; Send byte in __io_out to the serial port +.send_byte: +_send_byte:: ; Banked + LD A,#.IO_SENDING + LD (__io_status),A ; Store status + LD A,#0x01 + LDH (.SC),A ; Use internal clock + LD A,(__io_out) + LDH (.SB),A ; Send data byte + LD A,#0x81 + LDH (.SC),A ; Use internal clock + RET + + ;; Receive byte from the serial port in __io_in +.receive_byte: +_receive_byte:: ; Banked + LD A,#.IO_RECEIVING + LD (__io_status),A ; Store status + XOR A + LDH (.SC),A ; Use external clock + LD A,#.DT_RECEIVING + LDH (.SB),A ; Send RECEIVING byte + LD A,#0x80 + LDH (.SC),A ; Use external clock + RET diff --git a/gbdk/gbdk-lib/libc/targets/sm83/set_1bit_data.s b/gbdk/gbdk-lib/libc/targets/sm83/set_1bit_data.s new file mode 100644 index 00000000..a16d57b7 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/set_1bit_data.s @@ -0,0 +1,98 @@ + .include "global.s" + + .globl __current_1bpp_colors + + .area _HOME + +_set_bkg_1bpp_data:: +_set_win_1bpp_data:: + ld d, #0x90 + ldh a, (.LCDC) + and #LCDCF_BG8000 + jr z, .copy_1bpp_tiles +_set_sprite_1bpp_data:: + ld d, #0x80 +.copy_1bpp_tiles: + push bc + + lda hl, 4(sp) + ld a, (hl+) ; ID of 1st tile + ld e, a + ld a, (hl+) ; Nb of tiles + ld c, a + ld a, (hl+) ; Src ptr + ld h, (hl) + ld l, a + + ; Compute dest ptr + swap e ; *16 (size of a tile) + ld a, e + and #0x0F ; Get high bits + add d ; Add base offset of target tile "block" + ld d, a + ld a, e + and #0xF0 ; Get low bits only + ld e, a + + push de + ld d, h + ld e, l + pop hl + +1$: + ; Wrap from past $97FF to $8800 onwards + ; This can be reduced to "bit 4 must be clear if bit 3 is set" + bit 3, h + jr z, 2$ + res 4, h +2$: + ld b, #8 +3$: + push bc + ld a, (de) ; a == bits + inc de + push de + push hl + + ld hl, #__current_1bpp_colors + ld c, (hl) + inc hl + ld h, (hl) + ld l, c ; L ==.fg_colour, H == .bg_colour + + ld e, #8 +8$: + rra + jr c, 7$ + ld d, h + jr 9$ +7$: + ld d, l +9$: + srl d + rr c + srl d + rr b + + dec e + jr nz, 8$ + + pop hl + + WAIT_STAT + ld (hl), c + inc l + ld (hl), b + inc hl + + pop de + pop bc + + dec b + jr nz, 3$ + + dec c + jr nz, 1$ + + pop bc + ret
\ No newline at end of file diff --git a/gbdk/gbdk-lib/libc/targets/sm83/set_bk_t.s b/gbdk/gbdk-lib/libc/targets/sm83/set_bk_t.s new file mode 100644 index 00000000..36992eec --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/set_bk_t.s @@ -0,0 +1,26 @@ + .include "global.s" + + .globl .set_xy_btt + + .area _HOME + +_set_bkg_tiles:: + PUSH BC + + LDA HL,4(SP) ; Skip return address and registers + LD A,(HL+) ; D = x + LD D, A + LD E,(HL) ; E = y + LDA HL,9(SP) + LD A,(HL-) ; BC = tiles + LD B, A + LD A,(HL-) + LD C, A + LD A,(HL-) ; A = h + LD H,(HL) ; H = w + LD L,A ; L = h + + CALL .set_xy_btt + + POP BC + RET diff --git a/gbdk/gbdk-lib/libc/targets/sm83/set_data.s b/gbdk/gbdk-lib/libc/targets/sm83/set_data.s new file mode 100644 index 00000000..33208ef7 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/set_data.s @@ -0,0 +1,58 @@ + .include "global.s" + + .area _HOME + +_set_tile_data:: + ldhl sp, #6 + ld d,(hl) + jr .copy_tiles +_set_bkg_data:: +_set_win_data:: + ld d, #0x90 + ldh a, (.LCDC) + and #LCDCF_BG8000 + jr z, .copy_tiles +_set_sprite_data:: + ld d, #0x80 +.copy_tiles: + push bc + ldhl sp, #4 + ld a, (hl+) ; ID of 1st tile + ld e, a + ld a, (hl+) ; Nb of tiles + ld c, a + ld a, (hl+) ; Src ptr + ld h, (hl) + ld l, a + + ; Compute dest ptr + swap e ; *16 (size of a tile) + ld a, e + and #0x0F ; Get high bits + add d ; Add base offset of target tile "block" + ld d, a + ld a, e + and #0xF0 ; Get low bits only + ld e, a +2$: + ; Wrap from past $97FF to $8800 onwards + ; This can be reduced to "bit 4 must be clear if bit 3 is set" + bit 3, d + jr z, 1$ + res 4, d +1$: + ld b, #16 +3$: + WAIT_STAT + ld a, (hl+) + ld (de), a + inc de + + dec b + jr nz, 3$ + + dec c + jr nz, 2$ + + pop bc + ret
\ No newline at end of file diff --git a/gbdk/gbdk-lib/libc/targets/sm83/set_prop.s b/gbdk/gbdk-lib/libc/targets/sm83/set_prop.s new file mode 100644 index 00000000..0cd46be8 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/set_prop.s @@ -0,0 +1,16 @@ + .include "global.s" + + .area _HOME + + ;; Set properties of sprite number C to D +.set_sprite_prop:: + LD HL,#_shadow_OAM+3 ; Calculate origin of sprite info + + SLA C ; Multiply C by 4 + SLA C + LD B,#0x00 + ADD HL,BC + + LD A,D ; Set sprite properties + LD (HL),A + RET diff --git a/gbdk/gbdk-lib/libc/targets/sm83/set_spr.s b/gbdk/gbdk-lib/libc/targets/sm83/set_spr.s new file mode 100644 index 00000000..8b428fe9 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/set_spr.s @@ -0,0 +1,16 @@ + .include "global.s" + + .area _HOME + + ;; Set sprite number C to tile D +.set_sprite_tile:: + LD HL,#_shadow_OAM+2 ; Calculate origin of sprite info + + SLA C ; Multiply C by 4 + SLA C + LD B,#0x00 + ADD HL,BC + + LD A,D ; Set sprite number + LD (HL),A + RET diff --git a/gbdk/gbdk-lib/libc/targets/sm83/set_t.s b/gbdk/gbdk-lib/libc/targets/sm83/set_t.s new file mode 100644 index 00000000..98d7288c --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/set_t.s @@ -0,0 +1,28 @@ + .include "global.s" + + .globl .set_xy_tt + + .area _HOME + +; void set_tiles(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t *vram_addr, const uint8_t *tiles); + +_set_tiles:: + LDHL SP, #5 + LD A, (HL-) + LD E, A + LD A, (HL-) + LD D, A + PUSH DE + LD A, (HL-) + LD E, A + LD D, (HL) + LDHL SP, #11 + LD A, (HL-) + LD B, A + LD A, (HL-) + LD C, A + LD A, (HL-) + LD L, (HL) + LD H, A + + JP .set_xy_tt ;; Set background tile from (BC) at XY = DE, size WH on stack, to vram from address (HL) diff --git a/gbdk/gbdk-lib/libc/targets/sm83/set_tile.s b/gbdk/gbdk-lib/libc/targets/sm83/set_tile.s new file mode 100644 index 00000000..bbb472eb --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/set_tile.s @@ -0,0 +1,60 @@ +.include "global.s" + +.area _CODE + +_set_vram_byte:: + ; de = addr, hl = &t + ldhl sp,#2 + ld a,(hl+) + ld e, a + ld a,(hl+) + ld d, a + + WAIT_STAT + + ; Write tile + ld a,(hl) + ld (de),a + ret + +_set_win_tile_xy:: + ldh a,(.LCDC) + and #LCDCF_WIN9C00 + jr z,.is98 + jr .is9c +_set_bkg_tile_xy:: + ldh a,(.LCDC) + and #LCDCF_BG9C00 + jr nz,.is9c +.is98: + ld d,#0x98 ; DE = origin + jr .set_tile_xy +.is9c: + ld d,#0x9C ; DE = origin + +.set_tile_xy: + push bc + ldhl sp,#4 + + ld a, (hl+) + ld b, a + ld a, (hl+) + + ld e, d + swap a + rlca + ld c, a + and #0x03 + add e + ld d, a + ld a, #0xE0 + and c + add b + ld e, a ; dest DE = BASE + 0x20 * Y + X + + WAIT_STAT + ld a, (hl) + ld (de), a + + pop bc + ret diff --git a/gbdk/gbdk-lib/libc/targets/sm83/set_tile_submap.s b/gbdk/gbdk-lib/libc/targets/sm83/set_tile_submap.s new file mode 100644 index 00000000..266b96da --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/set_tile_submap.s @@ -0,0 +1,150 @@ + .include "global.s" + + .title "Set tile submap" + .module SetTileSubmap + + .area _DATA + +.image_tile_width:: + .ds 0x01 + + .area _INITIALIZED + +__submap_tile_offset:: + .ds 0x01 + + .area _INITIALIZER + + .db 0x00 + + .area _HOME + +_set_bkg_submap:: + ldhl sp, #2 + ld a, (hl+) ; b = x + ld b, a + ld c, (hl) ; c = y + + ldhl sp, #8 + ld a, (hl) + ldhl sp, #4 + sub (hl) + ld (.image_tile_width), a ; .image_tile_width contains corrected width map width + add (hl) + + ld d, #0 + ld e, a + ld a, c + MUL_DE_BY_A_RET_HL + ld a, b + ADD_A_REG16 h, l + ld d, h + ld e, l + + ldhl sp, #6 + ld a,(hl+) + ld h,(hl) + ld l,a + add hl, de + ld b, h + ld c, l + + ldhl sp, #2 + ld a, (hl+) ; d = x + and #0x1f + ld d, a + ld a, (hl) ; e = y + and #0x1f + ld e, a + + ldhl sp, #5 + ld a,(hl-) ; a = h + ld h,(hl) ; h = w + ld l,a ; l = h + + jr .set_xy_bkg_submap + + ;; set window tile table from bc at xy = de of size wh = hl +.set_xy_win_submap:: + push hl ; store wh + ldh a,(.LCDC) + and #LCDCF_WIN9C00 + jr z,.is98 + jr .is9c + ;; set background tile table from (bc) at xy = de of size wh = hl +.set_xy_bkg_submap:: + push hl ; store wh + ldh a,(.LCDC) + and #LCDCF_BG9C00 + jr nz,.is9c +.is98: + ld hl,#0x9800 + jr .set_xy_submap +.is9c: + ld hl,#0x9c00 + ;; set background tile from (bc) at xy = de, size wh on stack, to vram from address (hl) +.set_xy_submap:: + push bc ; store source + + swap e + rlc e + ld a,e + and #0x03 + add h + ld b,a + ld a,#0xe0 + and e + add d + ld c,a ; dest bc = hl + 0x20 * y + x + + pop hl ; hl = source + pop de ; de = wh + push de ; store wh + push bc ; store dest +3$: ; copy w tiles + WAIT_STAT + ld a, (__submap_tile_offset) + add (hl) + ld (bc), a + inc hl + + ld a, c ; inc dest and wrap around + and #0xe0 + ld e, a + ld a, c + inc a + and #0x1f + or e + ld c, a + + dec d + jr nz, 3$ + + ld a, (.image_tile_width) + ADD_A_REG16 h, l + + pop bc + pop de + + dec e + ret z + + push de + + ld a, b ; next row and wrap around + and #0xfc + ld e, a ; save high bits + + ld a,#0x20 + + add c + ld c, a + adc b + sub c + and #0x03 + or e ; restore high bits + ld b, a + + push bc + + jr 3$ diff --git a/gbdk/gbdk-lib/libc/targets/sm83/set_wi_t.s b/gbdk/gbdk-lib/libc/targets/sm83/set_wi_t.s new file mode 100644 index 00000000..0642668e --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/set_wi_t.s @@ -0,0 +1,27 @@ + .include "global.s" + + .globl .set_xy_wtt + + ;; BANKED: checked, imperfect + .area _HOME + +_set_win_tiles:: + PUSH BC + + LDA HL,4(SP) ; Skip return address and registers + LD A,(HL+) ; D = x + LD D, A + LD E,(HL) ; E = y + LDA HL,9(SP) + LD A,(HL-) ; BC = tiles + LD B, A + LD A,(HL-) + LD C, A + LD A,(HL-) ; A = h + LD H,(HL) ; H = w + LD L,A ; L = h + + CALL .set_xy_wtt + + POP BC + RET diff --git a/gbdk/gbdk-lib/libc/targets/sm83/set_win_tile_submap.s b/gbdk/gbdk-lib/libc/targets/sm83/set_win_tile_submap.s new file mode 100644 index 00000000..04c5276b --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/set_win_tile_submap.s @@ -0,0 +1,50 @@ + .include "global.s" + + .globl .image_tile_width, .set_xy_win_submap + + .area _HOME + +_set_win_submap:: + ldhl sp, #2 + ld a, (hl+) ; b = x + ld b, a + ld c, (hl) ; c = y + + ldhl sp, #8 + ld a, (hl) + ldhl sp, #4 + sub (hl) + ld (.image_tile_width), a ; .image_tile_width contains corrected width map width + add (hl) + + ld d, #0 + ld e, a + ld a, c + MUL_DE_BY_A_RET_HL + ld a, b + ADD_A_REG16 h, l + ld d, h + ld e, l + + ldhl sp, #6 + ld a,(hl+) + ld h,(hl) + ld l,a + add hl, de + ld b, h + ld c, l + + ldhl sp, #2 + ld a, (hl+) ; d = x + and #0x1f + ld d, a + ld a, (hl) ; e = y + and #0x1f + ld e, a + + ldhl sp, #5 + ld a,(hl-) ; a = h + ld h,(hl) ; h = w + ld l,a ; l = h + + jp .set_xy_win_submap diff --git a/gbdk/gbdk-lib/libc/targets/sm83/set_xy_t.s b/gbdk/gbdk-lib/libc/targets/sm83/set_xy_t.s new file mode 100644 index 00000000..fe164c47 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/set_xy_t.s @@ -0,0 +1,99 @@ + .include "global.s" + + .title "Set tile map" + .module SetTileMap + + .area _INITIALIZED + +__map_tile_offset:: + .ds 0x01 + + .area _INITIALIZER + + .db 0x00 + + .area _HOME + + ;; Set window tile table from BC at XY = DE of size WH = HL +.set_xy_wtt:: + PUSH HL ; Store WH + LDH A,(.LCDC) + AND #LCDCF_WIN9C00 + JR Z,.is98 + JR .is9c + ;; Set background tile table from (BC) at XY = DE of size WH = HL +.set_xy_btt:: + PUSH HL ; Store WH + LDH A,(.LCDC) + AND #LCDCF_BG9C00 + JR NZ,.is9c +.is98: + LD HL,#0x9800 + JR .set_xy_tt +.is9c: + LD HL,#0x9C00 + ;; Set background tile from (BC) at XY = DE, size WH on stack, to vram from address (HL) +.set_xy_tt:: + PUSH BC ; Store source + + SWAP E + RLC E + LD A,E + AND #0x03 + ADD H + LD B,A + LD A,#0xE0 + AND E + ADD D + LD C,A ; dest BC = HL + 0x20 * Y + X + + POP HL ; HL = source + POP DE ; DE = WH + PUSH DE ; store WH + PUSH BC ; store dest + +3$: ; Copy W tiles + + WAIT_STAT + LD A, (__map_tile_offset) + ADD (HL) + LD (BC), A + INC HL + + LD A, C ; inc dest and wrap around + AND #0xE0 + LD E, A + LD A, C + INC A + AND #0x1F + OR E + LD C, A + + DEC D + JR NZ, 3$ + + POP BC + POP DE + + DEC E + RET Z + + PUSH DE + + LD A, B ; next row and wrap around + AND #0xFC + LD E, A ; save high bits + + LD A,#0x20 + + ADD C + LD C, A + ADC B + SUB C + AND #0x03 + OR E ; restore high bits + LD B, A + + PUSH BC + + JR 3$ diff --git a/gbdk/gbdk-lib/libc/targets/sm83/sgb.s b/gbdk/gbdk-lib/libc/targets/sm83/sgb.s new file mode 100644 index 00000000..aadc6d57 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/sgb.s @@ -0,0 +1,128 @@ + .include "global.s" + + .area _CODE + + ;; Check if running on SGB + ;; Set A to 0xFF when running on SGB + ;; Clear A when running on DMG +.sgb_check:: +_sgb_check:: + PUSH BC + ADD SP, #-0x10 + LDHL SP, #0 + LD C, #0x10 + XOR A + RST 0x28 + LDHL SP,#0 + LD A,#((.MLT_REQ << 3) | 1) + LD (HL+),A + LD A,#0x03 + LD (HL-),A + CALL .sgb_transfer + LD C,#.P1 + LD A,#(.P14 | .P15) + LDH (C),A + LDH A,(C) + LDH A,(C) + LD E, #4 + LDH A,(C) ; read delayed +3$: + LD B, A + + LD A,#.P15 + LDH (C),A + LDH A,(C) + LDH A,(C) + + LD A,#.P14 + LDH (C),A + LDH A,(C) + LDH A,(C) + + LD A,#(.P14 | .P15) + LDH (C),A + LDH A,(C) + LDH A,(C) + LDH A,(C) + LDH A,(C) ; read delayed + CP B + JR NZ,1$ + + DEC E + JR NZ,3$ +2$: + LD E,#0 + JR 4$ +1$: + LDHL SP,#1 + LD A,#0x00 + LD (HL-),A + CALL .sgb_transfer + LD E,#1 +4$: + ADD SP,#0x10 + POP BC + RET + +_sgb_transfer:: + LDHL SP,#2 + LD A,(HL+) + LD H,(HL) + LD L,A + +.sgb_transfer:: + PUSH BC + LD A,(HL) ; Top of command data + AND #0x03 + JR Z,6$ +1$: + PUSH AF + LD C,#.P1 + LDH (C),A ; Send reset + LD A,#(.P14 | .P15) + LDH (C),A + LD B,#0x10 ; Set counter to transfer 16 byte +2$: LD E,#0x08 ; Set counter to transfer 8 bit + LD A,(HL+) + LD D,A + +3$: + SRL D + LD A,#.P14 ; P14 = high, P15 = low (output "1") + JR C,4$ + LD A,#.P15 ; P14 = low, P15 = high (output "0") +4$: + LDH (C),A + LDH A,(C) ; delay + LDH A,(C) + LD A,#(.P14 | .P15); P14 = high, P15 = high + LDH (C),A + LDH A,(C) ; delay + LDH A,(C) + DEC E + JR NZ,3$ + + DEC B + JR NZ,2$ + + LD A,#.P15 ; 129th bit "0" output + LDH (C),A + LDH A,(C) ; delay + LDH A,(C) + LD A,#(.P14 | .P15) + LDH (C),A + + LD DE,#8400 ; was: 7000 +5$: + LDH A,(.P1) ; 3 + + DEC DE ; 2 + + LD A,D ; 1 + + OR E ; 1 + + JR NZ,5$ ; 3 = 10 cycles + + POP AF + DEC A + JR NZ, 1$ +6$: + POP BC + RET diff --git a/gbdk/gbdk-lib/libc/targets/sm83/tim.s b/gbdk/gbdk-lib/libc/targets/sm83/tim.s new file mode 100644 index 00000000..af5563d8 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/tim.s @@ -0,0 +1,25 @@ + .include "global.s" + + .globl .int, .int_0x50 + .globl .add_TIM + + .area _HEADER_TIM (ABS) + + .org 0x50 ; TIM +.int_TIM: + PUSH AF + PUSH HL + LD HL,#.int_0x50 + JP .int + + .area _HOME + +_add_TIM:: + PUSH BC + LDA HL,4(SP) ; Skip return address and registers + LD C,(HL) + INC HL + LD B,(HL) + CALL .add_TIM + POP BC + RET diff --git a/gbdk/gbdk-lib/libc/targets/sm83/tim_common.s b/gbdk/gbdk-lib/libc/targets/sm83/tim_common.s new file mode 100644 index 00000000..1893554e --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/tim_common.s @@ -0,0 +1,28 @@ + .include "global.s" + + .globl .int, .add_int, .remove_int + + .area _HOME + +.add_TIM:: + LD HL,#.int_0x50 + JP .add_int + +_remove_TIM:: + PUSH BC + LDA HL,4(SP) ; Skip return address and registers + LD C,(HL) + INC HL + LD B,(HL) + CALL .remove_TIM + POP BC + RET + +.remove_TIM:: + LD HL,#.int_0x50 + JP .remove_int + + .area _DATA + +.int_0x50:: + .blkw 0x08 diff --git a/gbdk/gbdk-lib/libc/targets/sm83/tim_nested.s b/gbdk/gbdk-lib/libc/targets/sm83/tim_nested.s new file mode 100644 index 00000000..a6ddbcca --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/sm83/tim_nested.s @@ -0,0 +1,29 @@ + .include "global.s" + + .globl .int, .int_0x50 + .globl .add_TIM + + .area _HEADER_NESTED_TIM (ABS) + + .org 0x50 ; TIM +.int_TIM_nested: + EI + PUSH AF + PUSH HL + JP .tim_isr_jump + + .area _HOME + +.tim_isr_jump: + LD HL, #.int_0x50 + JP .int + +_add_low_priority_TIM:: + PUSH BC + LDA HL, 4(SP) ; Skip return address and registers + LD C, (HL) + INC HL + LD B,(HL) + CALL .add_TIM + POP BC + RET diff --git a/gbdk/gbdk-lib/libc/targets/z80/clock.s b/gbdk/gbdk-lib/libc/targets/z80/clock.s new file mode 100644 index 00000000..c1b16d8a --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/clock.s @@ -0,0 +1,12 @@ + .include "global.s" + + .title "System clock" + .module Clock + + .globl .sys_time + + .area _HOME + +_clock:: + LD HL,(.sys_time) + RET diff --git a/gbdk/gbdk-lib/libc/targets/z80/cls.s b/gbdk/gbdk-lib/libc/targets/z80/cls.s new file mode 100644 index 00000000..9ae8e7fa --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/cls.s @@ -0,0 +1,34 @@ + .include "global.s" + + .title "console utilities" + .module ConsoleUtils + + .globl .curx, .cury + + .area _HOME + +_cls:: + ld a, #.SCREEN_X_OFS + ld (.curx), a + ld a, #.SCREEN_Y_OFS + ld (.cury), a + + DISABLE_VBLANK_COPY ; switch OFF copy shadow SAT + + ld hl, #(.VDP_TILEMAP + ((.SCREEN_Y_OFS * .VDP_MAP_WIDTH) * 2)) + WRITE_VDP_CMD_HL + + ld hl, #.SPACE + ld bc, #(.SCREEN_HEIGHT * .VDP_MAP_WIDTH) + inc b + inc c + jr 1$ +2$: + WRITE_VDP_DATA_HL +1$: + dec c + jr nz, 2$ + djnz 2$ + + ENABLE_VBLANK_COPY ; switch ON copy shadow SAT + ret
\ No newline at end of file diff --git a/gbdk/gbdk-lib/libc/targets/z80/color.s b/gbdk/gbdk-lib/libc/targets/z80/color.s new file mode 100644 index 00000000..d65ed1ed --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/color.s @@ -0,0 +1,17 @@ + .include "global.s" + + .title "Colors" + .module colors + + .area _INITIALIZED + +__current_1bpp_colors:: +.fg_colour:: + .ds 1 +.bg_colour:: + .ds 1 + + .area _INITIALIZER + + .db 0x03 ; .fg_colour + .db 0x00 ; .bg_color diff --git a/gbdk/gbdk-lib/libc/targets/z80/coords_to_address.s b/gbdk/gbdk-lib/libc/targets/z80/coords_to_address.s new file mode 100644 index 00000000..7c30c835 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/coords_to_address.s @@ -0,0 +1,47 @@ + .include "global.s" + + .title "VRAM utilities" + .module VRAMUtils + + .area _HOME + +; translate coords in DE and given base in BC into address in DE +.coords_to_address:: + ld a, d + add #.SCREEN_Y_OFS + ld d, a + xor a + FAST_MOD8 d #28 + ld d, a + + ld a, e + add #.SCREEN_X_OFS + and #0x1f + ld e, a + + ld a, d + rrca ; rrca(2) == rlca(6) + rrca + ld d, a + and #0x07 + add b + ld b, a + ld a, #0xC0 + and d + sla e + add e + ld e, a + ld d, b ; dest DE = BC + ((0x20 * Y) * 2) + (X * 2) + + ret + +; uint8_t * get_bkg_xy_addr(uint8_t x, uint8_t y) __z88dk_callee __preserves_regs(iyh, iyl); + +_get_bkg_xy_addr:: + pop hl + ex (sp), hl + ex de, hl + ld bc, #.VDP_TILEMAP + call .coords_to_address + ex de, hl + ret
\ No newline at end of file diff --git a/gbdk/gbdk-lib/libc/targets/z80/delay.s b/gbdk/gbdk-lib/libc/targets/z80/delay.s new file mode 100644 index 00000000..ccb36518 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/delay.s @@ -0,0 +1,53 @@ + .include "global.s" + + .title "Delay" + .module delay + + .area _CODE + +;; hl must contain amount of tstates, which must be >= 141 +wait_hl_tstates:: + ld bc, #-141 + add hl, bc + ld bc, #-23 +1$: + add hl,bc + jr c, 1$ + ld a, l + add a, #15 + jr nc, 2$ + cp #8 + jr c, 3$ + or #0 +2$: + inc hl +3$: + rra + jr c, 4$ + nop +4$: + rra + jr nc, 5$ + or #0 +5$: + rra + ret nc + ret + +;; hl = milliseconds (0 = 65536) +_delay:: + ld e, l + ld d, h +1$: + dec de + ld a,d + or e + jr z, 2$ + + ld hl,#((.CPU_CLOCK / 1000) - 43) + call wait_hl_tstates + jr 1$ +2$: + ld hl,#((.CPU_CLOCK / 1000) - 54) + jp wait_hl_tstates + ret
\ No newline at end of file diff --git a/gbdk/gbdk-lib/libc/targets/z80/emu_debug_printf.s b/gbdk/gbdk-lib/libc/targets/z80/emu_debug_printf.s new file mode 100644 index 00000000..66e73be0 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/emu_debug_printf.s @@ -0,0 +1,44 @@ + .include "global.s" + + .title "EMU_debug" + .module EMU_debug + + .globl _sprintf + + .area _DATA + +ret_save: + .ds 0x02 +printf_buffer: + .ds 0x80 + + .area _HOME + + ;; EMU_printf(fmt, ...) +_EMU_printf:: + di + pop de + ld hl, #ret_save + ld (hl), e + inc hl + ld (hl), d + + ld de, #printf_buffer + push de + call _sprintf + pop hl + + ld d,d + jr 1$ + .dw 0x6464 + .dw 0x0001 + .dw #printf_buffer + .dw 0 +1$: + ld hl, #ret_save + ld a, (hl) + inc hl + ld h, (hl) + ld l, a + ei + jp (hl) diff --git a/gbdk/gbdk-lib/libc/targets/z80/f_ibm_full.s b/gbdk/gbdk-lib/libc/targets/z80/f_ibm_full.s new file mode 100644 index 00000000..d7f09b18 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/f_ibm_full.s @@ -0,0 +1,2616 @@ +; font: font + + .area _HOME + + .globl font_load + ;; Perform tricks with banking to shift this font out of + ;; bank 0. Doesnt currently work as the encoding table + ;; must always be visible. +_font_load_ibm_fixed:: ; Banked + ld hl,#_font_ibm_fixed + call font_load + ret + +_font_ibm_fixed:: + .db 0+4 ; 256 char encoding, compressed + .db 255 ; Number of tiles + +; Encoding table + + ; Hack + .db 0x00 + .db 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08 + .db 0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10 + .db 0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18 + .db 0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20 + .db 0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28 + .db 0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,0x30 + .db 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38 + .db 0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,0x40 + .db 0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48 + .db 0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,0x50 + .db 0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58 + .db 0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F,0x60 + .db 0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68 + .db 0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,0x70 + .db 0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78 + .db 0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F,0x80 + .db 0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88 + .db 0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90 + .db 0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98 + .db 0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,0xA0 + .db 0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8 + .db 0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0 + .db 0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8 + .db 0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF,0xC0 + .db 0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8 + .db 0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0 + .db 0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8 + .db 0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,0xE0 + .db 0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8 + .db 0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0 + .db 0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8 + .db 0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF + ; Tile data + ;; Hook for the graphics routines +_font_ibm_fixed_tiles:: +; Default character (space) + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + +; Character: ? (01) + .db 0b00011000 ; oo + .db 0b00100100 ; o o + .db 0b01000010 ; o o + .db 0b10000001 ; o o + .db 0b11100111 ; ooo ooo + .db 0b00100100 ; o o + .db 0b00100100 ; o o + .db 0b00111100 ; oooo + +; Character: ? (02) + .db 0b00111100 ; oooo + .db 0b00100100 ; o o + .db 0b00100100 ; o o + .db 0b11100111 ; ooo ooo + .db 0b10000001 ; o o + .db 0b01000010 ; o o + .db 0b00100100 ; o o + .db 0b00011000 ; oo + +; Character: ? (03) + .db 0b00011000 ; oo + .db 0b00010100 ; o o + .db 0b11110010 ; oooo o + .db 0b10000001 ; o o + .db 0b10000001 ; o o + .db 0b11110010 ; oooo o + .db 0b00010100 ; o o + .db 0b00011000 ; oo + +; Character: ? (04) + .db 0b00011000 ; oo + .db 0b00101000 ; o o + .db 0b01001111 ; o oooo + .db 0b10000001 ; o o + .db 0b10000001 ; o o + .db 0b01001111 ; o oooo + .db 0b00101000 ; o o + .db 0b00011000 ; oo + +; Character: ? (05) + .db 0b11111111 ; oooooooo + .db 0b10000001 ; o o + .db 0b10000001 ; o o + .db 0b10000001 ; o o + .db 0b10000001 ; o o + .db 0b10000001 ; o o + .db 0b10000001 ; o o + .db 0b11111111 ; oooooooo + +; Character: ? (06) + .db 0b11111000 ; ooooo + .db 0b10001000 ; o o + .db 0b10001111 ; o oooo + .db 0b10001001 ; o o o + .db 0b11111001 ; ooooo o + .db 0b01000001 ; o o + .db 0b01000001 ; o o + .db 0b01111111 ; ooooooo + +; Character: ? (07) + .db 0b11111111 ; oooooooo + .db 0b10001001 ; o o o + .db 0b10001001 ; o o o + .db 0b10001001 ; o o o + .db 0b11111001 ; ooooo o + .db 0b10000001 ; o o + .db 0b10000001 ; o o + .db 0b11111111 ; oooooooo + +; Character: ? (08) + .db 0b00000001 ; o + .db 0b00000011 ; oo + .db 0b00000110 ; oo + .db 0b10001100 ; o oo + .db 0b11011000 ; oo oo + .db 0b01110000 ; ooo + .db 0b00100000 ; o + .db 0b00000000 ; + +; Character: ? (09) + .db 0b01111110 ; oooooo + .db 0b11000011 ; oo oo + .db 0b11010011 ; oo o oo + .db 0b11010011 ; oo o oo + .db 0b11011011 ; oo oo oo + .db 0b11000011 ; oo oo + .db 0b11000011 ; oo oo + .db 0b01111110 ; oooooo + +; Character: ? (0A) + .db 0b00011000 ; oo + .db 0b00111100 ; oooo + .db 0b00101100 ; o oo + .db 0b00101100 ; o oo + .db 0b01111110 ; oooooo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + +; Character: ? (0B) + .db 0b00010000 ; o + .db 0b00011100 ; ooo + .db 0b00010010 ; o o + .db 0b00010000 ; o + .db 0b00010000 ; o + .db 0b01110000 ; ooo + .db 0b11110000 ; oooo + .db 0b01100000 ; oo + +; Character: ? (0C) + .db 0b11110000 ; oooo + .db 0b11000000 ; oo + .db 0b11111110 ; ooooooo + .db 0b11011000 ; oo oo + .db 0b11011110 ; oo oooo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + +; Character: ? (0D) + .db 0b01110000 ; ooo + .db 0b11001000 ; oo o + .db 0b11011110 ; oo oooo + .db 0b11011011 ; oo oo oo + .db 0b11011011 ; oo oo oo + .db 0b01111110 ; oooooo + .db 0b00011011 ; oo oo + .db 0b00011011 ; oo oo + +; Character: ? (0E) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b11111111 ; oooooooo + .db 0b11111111 ; oooooooo + .db 0b11111111 ; oooooooo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (0F) + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + +; Character: ? (10) + .db 0b01111100 ; ooooo + .db 0b11000110 ; oo oo + .db 0b11000110 ; oo oo + .db 0b00000000 ; + .db 0b11000110 ; oo oo + .db 0b11000110 ; oo oo + .db 0b01111100 ; ooooo + .db 0b00000000 ; + +; Character: ? (11) + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00000000 ; + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00000000 ; + +; Character: ? (12) + .db 0b01111100 ; ooooo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b01111100 ; ooooo + .db 0b11000000 ; oo + .db 0b11000000 ; oo + .db 0b01111100 ; ooooo + .db 0b00000000 ; + +; Character: ? (13) + .db 0b01111100 ; ooooo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b01111100 ; ooooo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b01111100 ; ooooo + .db 0b00000000 ; + +; Character: ? (14) + .db 0b11000110 ; oo oo + .db 0b11000110 ; oo oo + .db 0b11000110 ; oo oo + .db 0b01111100 ; ooooo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00000000 ; + +; Character: ? (15) + .db 0b01111100 ; ooooo + .db 0b11000000 ; oo + .db 0b11000000 ; oo + .db 0b01111100 ; ooooo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b01111100 ; ooooo + .db 0b00000000 ; + +; Character: ? (16) + .db 0b01111100 ; ooooo + .db 0b11000000 ; oo + .db 0b11000000 ; oo + .db 0b01111100 ; ooooo + .db 0b11000110 ; oo oo + .db 0b11000110 ; oo oo + .db 0b01111100 ; ooooo + .db 0b00000000 ; + +; Character: ? (17) + .db 0b01111100 ; ooooo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00000000 ; + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00000000 ; + +; Character: ? (18) + .db 0b01111100 ; ooooo + .db 0b11000110 ; oo oo + .db 0b11000110 ; oo oo + .db 0b01111100 ; ooooo + .db 0b11000110 ; oo oo + .db 0b11000110 ; oo oo + .db 0b01111100 ; ooooo + .db 0b00000000 ; + +; Character: ? (19) + .db 0b01111100 ; ooooo + .db 0b11000110 ; oo oo + .db 0b11000110 ; oo oo + .db 0b01111100 ; ooooo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b01111100 ; ooooo + .db 0b00000000 ; + +; Character: ? (1A) + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01000110 ; o oo + .db 0b00000110 ; oo + .db 0b01111110 ; oooooo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: ? (1B) + .db 0b01111000 ; oooo + .db 0b01100110 ; oo oo + .db 0b01111101 ; ooooo o + .db 0b01100100 ; oo o + .db 0b01111110 ; oooooo + .db 0b00000011 ; oo + .db 0b00001011 ; o oo + .db 0b00000110 ; oo + +; Character: ? (1C) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00011111 ; ooooo + .db 0b00011111 ; ooooo + .db 0b00011111 ; ooooo + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + +; Character: ? (1D) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b11111100 ; oooooo + .db 0b11111100 ; oooooo + .db 0b11111100 ; oooooo + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + +; Character: ? (1E) + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + .db 0b00011111 ; ooooo + .db 0b00011111 ; ooooo + .db 0b00011111 ; ooooo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (1F) + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + .db 0b11111100 ; oooooo + .db 0b11111100 ; oooooo + .db 0b11111100 ; oooooo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: (20) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ! (21) + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + .db 0b00011000 ; oo + .db 0b00000000 ; + +; Character: " (22) + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01000100 ; o o + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: # (23) + .db 0b00000000 ; + .db 0b00100100 ; o o + .db 0b01111110 ; oooooo + .db 0b00100100 ; o o + .db 0b00100100 ; o o + .db 0b01111110 ; oooooo + .db 0b00100100 ; o o + .db 0b00000000 ; + +; Character: $ (24) + .db 0b00010100 ; o o + .db 0b00111110 ; ooooo + .db 0b01010101 ; o o o o + .db 0b00111100 ; oooo + .db 0b00011110 ; oooo + .db 0b01010101 ; o o o o + .db 0b00111110 ; ooooo + .db 0b00010100 ; o o + +; Character: % (25) + .db 0b01100010 ; oo o + .db 0b01100110 ; oo oo + .db 0b00001100 ; oo + .db 0b00011000 ; oo + .db 0b00110000 ; oo + .db 0b01100110 ; oo oo + .db 0b01000110 ; o oo + .db 0b00000000 ; + +; Character: & (26) + .db 0b01111000 ; oooo + .db 0b11001100 ; oo oo + .db 0b01100001 ; oo o + .db 0b11001110 ; oo ooo + .db 0b11001100 ; oo oo + .db 0b11001100 ; oo oo + .db 0b01111000 ; oooo + .db 0b00000000 ; + +; Character: ' (27) + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00010000 ; o + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ( (28) + .db 0b00000100 ; o + .db 0b00001000 ; o + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00001000 ; o + .db 0b00000100 ; o + +; Character: ) (29) + .db 0b00100000 ; o + .db 0b00010000 ; o + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00010000 ; o + .db 0b00100000 ; o + +; Character: * (2A) + .db 0b00000000 ; + .db 0b01010100 ; o o o + .db 0b00111000 ; ooo + .db 0b11111110 ; ooooooo + .db 0b00111000 ; ooo + .db 0b01010100 ; o o o + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: + (2B) + .db 0b00000000 ; + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b01111110 ; oooooo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: , (2C) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00110000 ; oo + .db 0b00110000 ; oo + .db 0b00100000 ; o + +; Character: - (2D) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: . (2E) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + +; Character: / (2F) + .db 0b00000011 ; oo + .db 0b00000110 ; oo + .db 0b00001100 ; oo + .db 0b00011000 ; oo + .db 0b00110000 ; oo + .db 0b01100000 ; oo + .db 0b11000000 ; oo + .db 0b00000000 ; + +; Character: 0 (30) + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01101110 ; oo ooo + .db 0b01110110 ; ooo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: 1 (31) + .db 0b00011000 ; oo + .db 0b00111000 ; ooo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + +; Character: 2 (32) + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b00001110 ; ooo + .db 0b00011100 ; ooo + .db 0b00111000 ; ooo + .db 0b01110000 ; ooo + .db 0b01111110 ; oooooo + .db 0b00000000 ; + +; Character: 3 (33) + .db 0b01111110 ; oooooo + .db 0b00001100 ; oo + .db 0b00011000 ; oo + .db 0b00111100 ; oooo + .db 0b00000110 ; oo + .db 0b01000110 ; o oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: 4 (34) + .db 0b00001100 ; oo + .db 0b00011100 ; ooo + .db 0b00101100 ; o oo + .db 0b01001100 ; o oo + .db 0b01111110 ; oooooo + .db 0b00001100 ; oo + .db 0b00001100 ; oo + .db 0b00000000 ; + +; Character: 5 (35) + .db 0b01111110 ; oooooo + .db 0b01100000 ; oo + .db 0b01111100 ; ooooo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b01000110 ; o oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: 6 (36) + .db 0b00011100 ; ooo + .db 0b00100000 ; o + .db 0b01100000 ; oo + .db 0b01111100 ; ooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: 7 (37) + .db 0b01111110 ; oooooo + .db 0b00000110 ; oo + .db 0b00001110 ; ooo + .db 0b00011100 ; ooo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + +; Character: 8 (38) + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: 9 (39) + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111110 ; ooooo + .db 0b00000110 ; oo + .db 0b00001100 ; oo + .db 0b00111000 ; ooo + .db 0b00000000 ; + +; Character: : (3A) + .db 0b00000000 ; + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + +; Character: ; (3B) + .db 0b00000000 ; + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00010000 ; o + .db 0b00000000 ; + +; Character: < (3C) + .db 0b00000110 ; oo + .db 0b00001100 ; oo + .db 0b00011000 ; oo + .db 0b00110000 ; oo + .db 0b00011000 ; oo + .db 0b00001100 ; oo + .db 0b00000110 ; oo + .db 0b00000000 ; + +; Character: = (3D) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: > (3E) + .db 0b01100000 ; oo + .db 0b00110000 ; oo + .db 0b00011000 ; oo + .db 0b00001100 ; oo + .db 0b00011000 ; oo + .db 0b00110000 ; oo + .db 0b01100000 ; oo + .db 0b00000000 ; + +; Character: ? (3F) + .db 0b00111100 ; oooo + .db 0b01000110 ; o oo + .db 0b00000110 ; oo + .db 0b00001100 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + .db 0b00011000 ; oo + +; Character: @ (40) + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01101110 ; oo ooo + .db 0b01101010 ; oo o o + .db 0b01101110 ; oo ooo + .db 0b01100000 ; oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: A (41) + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01111110 ; oooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00000000 ; + +; Character: B (42) + .db 0b01111100 ; ooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01111100 ; ooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01111100 ; ooooo + .db 0b00000000 ; + +; Character: C (43) + .db 0b00111100 ; oooo + .db 0b01100010 ; oo o + .db 0b01100000 ; oo + .db 0b01100000 ; oo + .db 0b01100000 ; oo + .db 0b01100010 ; oo o + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: D (44) + .db 0b01111100 ; ooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01111100 ; ooooo + .db 0b00000000 ; + +; Character: E (45) + .db 0b01111110 ; oooooo + .db 0b01100000 ; oo + .db 0b01100000 ; oo + .db 0b01111100 ; ooooo + .db 0b01100000 ; oo + .db 0b01100000 ; oo + .db 0b01111110 ; oooooo + .db 0b00000000 ; + +; Character: F (46) + .db 0b01111110 ; oooooo + .db 0b01100000 ; oo + .db 0b01100000 ; oo + .db 0b01111100 ; ooooo + .db 0b01100000 ; oo + .db 0b01100000 ; oo + .db 0b01100000 ; oo + .db 0b00000000 ; + +; Character: G (47) + .db 0b00111100 ; oooo + .db 0b01100010 ; oo o + .db 0b01100000 ; oo + .db 0b01101110 ; oo ooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111110 ; ooooo + .db 0b00000000 ; + +; Character: H (48) + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01111110 ; oooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00000000 ; + +; Character: I (49) + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + +; Character: J (4A) + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b01000110 ; o oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: K (4B) + .db 0b01100110 ; oo oo + .db 0b01101100 ; oo oo + .db 0b01111000 ; oooo + .db 0b01110000 ; ooo + .db 0b01111000 ; oooo + .db 0b01101100 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00000000 ; + +; Character: L (4C) + .db 0b01100000 ; oo + .db 0b01100000 ; oo + .db 0b01100000 ; oo + .db 0b01100000 ; oo + .db 0b01100000 ; oo + .db 0b01100000 ; oo + .db 0b01111100 ; ooooo + .db 0b00000000 ; + +; Character: M (4D) + .db 0b11111100 ; oooooo + .db 0b11010110 ; oo o oo + .db 0b11010110 ; oo o oo + .db 0b11010110 ; oo o oo + .db 0b11010110 ; oo o oo + .db 0b11000110 ; oo oo + .db 0b11000110 ; oo oo + .db 0b00000000 ; + +; Character: N (4E) + .db 0b01100010 ; oo o + .db 0b01110010 ; ooo o + .db 0b01111010 ; oooo o + .db 0b01011110 ; o oooo + .db 0b01001110 ; o ooo + .db 0b01000110 ; o oo + .db 0b01000010 ; o o + .db 0b00000000 ; + +; Character: O (4F) + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: P (50) + .db 0b01111100 ; ooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01111100 ; ooooo + .db 0b01100000 ; oo + .db 0b01100000 ; oo + .db 0b01100000 ; oo + .db 0b00000000 ; + +; Character: Q (51) + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b00000110 ; oo + +; Character: R (52) + .db 0b01111100 ; ooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01111100 ; ooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00000000 ; + +; Character: S (53) + .db 0b00111100 ; oooo + .db 0b01100010 ; oo o + .db 0b01110000 ; ooo + .db 0b00111100 ; oooo + .db 0b00001110 ; ooo + .db 0b01000110 ; o oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: T (54) + .db 0b01111110 ; oooooo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + +; Character: U (55) + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: V (56) + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100100 ; oo o + .db 0b01111000 ; oooo + .db 0b00000000 ; + +; Character: W (57) + .db 0b11000110 ; oo oo + .db 0b11000110 ; oo oo + .db 0b11000110 ; oo oo + .db 0b11010110 ; oo o oo + .db 0b11010110 ; oo o oo + .db 0b11010110 ; oo o oo + .db 0b11111100 ; oooooo + .db 0b00000000 ; + +; Character: X (58) + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00000000 ; + +; Character: Y (59) + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + +; Character: Z (5A) + .db 0b01111110 ; oooooo + .db 0b00001110 ; ooo + .db 0b00011100 ; ooo + .db 0b00111000 ; ooo + .db 0b01110000 ; ooo + .db 0b01100000 ; oo + .db 0b01111110 ; oooooo + .db 0b00000000 ; + +; Character: [ (5B) + .db 0b00011110 ; oooo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011110 ; oooo + .db 0b00000000 ; + +; Character: \ (5C) + .db 0b01000000 ; o + .db 0b01100000 ; oo + .db 0b00110000 ; oo + .db 0b00011000 ; oo + .db 0b00001100 ; oo + .db 0b00000110 ; oo + .db 0b00000010 ; o + .db 0b00000000 ; + +; Character: ] (5D) + .db 0b01111000 ; oooo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b01111000 ; oooo + .db 0b00000000 ; + +; Character: ^ (5E) + .db 0b00010000 ; o + .db 0b00111000 ; ooo + .db 0b01101100 ; oo oo + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: _ (5F) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b01111110 ; oooooo + .db 0b00000000 ; + +; Character: ` (60) + .db 0b00000000 ; + .db 0b11000000 ; oo + .db 0b11000000 ; oo + .db 0b01100000 ; oo + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: a (61) + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01000110 ; o oo + .db 0b00111110 ; ooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111110 ; ooooo + .db 0b00000000 ; + +; Character: b (62) + .db 0b01100000 ; oo + .db 0b01111100 ; ooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01111100 ; ooooo + .db 0b00000000 ; + +; Character: c (63) + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01100010 ; oo o + .db 0b01100000 ; oo + .db 0b01100000 ; oo + .db 0b01100010 ; oo o + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: d (64) + .db 0b00000110 ; oo + .db 0b00111110 ; ooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111110 ; ooooo + .db 0b00000000 ; + +; Character: e (65) + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01111110 ; oooooo + .db 0b01100000 ; oo + .db 0b01100010 ; oo o + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: f (66) + .db 0b00011110 ; oooo + .db 0b00110000 ; oo + .db 0b01111100 ; ooooo + .db 0b00110000 ; oo + .db 0b00110000 ; oo + .db 0b00110000 ; oo + .db 0b00110000 ; oo + .db 0b00000000 ; + +; Character: g (67) + .db 0b00000000 ; + .db 0b00111110 ; ooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111110 ; ooooo + .db 0b01000110 ; o oo + .db 0b00111100 ; oooo + +; Character: h (68) + .db 0b01100000 ; oo + .db 0b01111100 ; ooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00000000 ; + +; Character: i (69) + .db 0b00011000 ; oo + .db 0b00000000 ; + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + +; Character: j (6A) + .db 0b00000000 ; + .db 0b00001000 ; o + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b01011000 ; o oo + .db 0b00110000 ; oo + +; Character: k (6B) + .db 0b01100000 ; oo + .db 0b01100100 ; oo o + .db 0b01101000 ; oo o + .db 0b01110000 ; ooo + .db 0b01111000 ; oooo + .db 0b01101100 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00000000 ; + +; Character: l (6C) + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00001100 ; oo + .db 0b00000000 ; + +; Character: m (6D) + .db 0b00000000 ; + .db 0b11111100 ; oooooo + .db 0b11010110 ; oo o oo + .db 0b11010110 ; oo o oo + .db 0b11010110 ; oo o oo + .db 0b11010110 ; oo o oo + .db 0b11000110 ; oo oo + .db 0b00000000 ; + +; Character: n (6E) + .db 0b00000000 ; + .db 0b01111100 ; ooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00000000 ; + +; Character: o (6F) + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: p (70) + .db 0b00000000 ; + .db 0b01111100 ; ooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01111100 ; ooooo + .db 0b01100000 ; oo + .db 0b01100000 ; oo + +; Character: q (71) + .db 0b00000000 ; + .db 0b00111110 ; ooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111110 ; ooooo + .db 0b00000110 ; oo + +; Character: r (72) + .db 0b00000000 ; + .db 0b01101100 ; oo oo + .db 0b01110000 ; ooo + .db 0b01100000 ; oo + .db 0b01100000 ; oo + .db 0b01100000 ; oo + .db 0b01100000 ; oo + .db 0b00000000 ; + +; Character: s (73) + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01110010 ; ooo o + .db 0b00111000 ; ooo + .db 0b00011100 ; ooo + .db 0b01001110 ; o ooo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: t (74) + .db 0b00011000 ; oo + .db 0b00111100 ; oooo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00001100 ; oo + .db 0b00000000 ; + +; Character: u (75) + .db 0b00000000 ; + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111110 ; ooooo + .db 0b00000000 ; + +; Character: v (76) + .db 0b00000000 ; + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100100 ; oo o + .db 0b01111000 ; oooo + .db 0b00000000 ; + +; Character: w (77) + .db 0b00000000 ; + .db 0b11000110 ; oo oo + .db 0b11000110 ; oo oo + .db 0b11010110 ; oo o oo + .db 0b11010110 ; oo o oo + .db 0b11010110 ; oo o oo + .db 0b11111100 ; oooooo + .db 0b00000000 ; + +; Character: x (78) + .db 0b00000000 ; + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00000000 ; + +; Character: y (79) + .db 0b00000000 ; + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00100110 ; o oo + .db 0b00011110 ; oooo + .db 0b01000110 ; o oo + .db 0b00111100 ; oooo + +; Character: z (7A) + .db 0b00000000 ; + .db 0b01111110 ; oooooo + .db 0b00001110 ; ooo + .db 0b00011100 ; ooo + .db 0b00111000 ; ooo + .db 0b01110000 ; ooo + .db 0b01111110 ; oooooo + .db 0b00000000 ; + +; Character: { (7B) + .db 0b00001110 ; ooo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00110000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00001110 ; ooo + .db 0b00000000 ; + +; Character: | (7C) + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + +; Character: } (7D) + .db 0b01110000 ; ooo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00001100 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b01110000 ; ooo + .db 0b00000000 ; + +; Character: ~ (7E) + .db 0b00000000 ; + .db 0b01100000 ; oo + .db 0b11110010 ; oooo o + .db 0b10011110 ; o oooo + .db 0b00001100 ; oo + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (7F) + .db 0b00010000 ; o + .db 0b00010000 ; o + .db 0b00101000 ; o o + .db 0b00101000 ; o o + .db 0b01000100 ; o o + .db 0b01000100 ; o o + .db 0b10000010 ; o o + .db 0b11111110 ; ooooooo + +; Character: ? (80) + .db 0b00111100 ; oooo + .db 0b01100010 ; oo o + .db 0b01100000 ; oo + .db 0b01100000 ; oo + .db 0b01100000 ; oo + .db 0b01100010 ; oo o + .db 0b00011100 ; ooo + .db 0b00110000 ; oo + +; Character: ? (81) + .db 0b00100100 ; o o + .db 0b00000000 ; + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111110 ; ooooo + .db 0b00000000 ; + +; Character: ? (82) + .db 0b00001100 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01111110 ; oooooo + .db 0b01100000 ; oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: ? (83) + .db 0b00011000 ; oo + .db 0b01100110 ; oo oo + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b00000110 ; oo + .db 0b01111110 ; oooooo + .db 0b00111110 ; ooooo + .db 0b00000000 ; + +; Character: ? (84) + .db 0b00100100 ; o o + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01000110 ; o oo + .db 0b00111110 ; ooooo + .db 0b01000110 ; o oo + .db 0b00111110 ; ooooo + .db 0b00000000 ; + +; Character: ? (85) + .db 0b00110000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b00000110 ; oo + .db 0b01111110 ; oooooo + .db 0b00111110 ; ooooo + .db 0b00000000 ; + +; Character: ? (86) + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b00000110 ; oo + .db 0b01111110 ; oooooo + .db 0b00111110 ; ooooo + .db 0b00000000 ; + +; Character: ? (87) + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01100010 ; oo o + .db 0b01100000 ; oo + .db 0b01100010 ; oo o + .db 0b00111100 ; oooo + .db 0b00001000 ; o + .db 0b00011000 ; oo + +; Character: ? (88) + .db 0b00011000 ; oo + .db 0b00110100 ; oo o + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01111110 ; oooooo + .db 0b01100000 ; oo + .db 0b00111110 ; ooooo + .db 0b00000000 ; + +; Character: ? (89) + .db 0b00100100 ; o o + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01111110 ; oooooo + .db 0b01100000 ; oo + .db 0b00111110 ; ooooo + .db 0b00000000 ; + +; Character: ? (8A) + .db 0b00110000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01111110 ; oooooo + .db 0b01100000 ; oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: ? (8B) + .db 0b00100100 ; o o + .db 0b00000000 ; + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + +; Character: ? (8C) + .db 0b00011000 ; oo + .db 0b00100100 ; o o + .db 0b00000000 ; + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + +; Character: ? (8D) + .db 0b00010000 ; o + .db 0b00001000 ; o + .db 0b00000000 ; + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + +; Character: ? (8E) + .db 0b00100100 ; o o + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01111110 ; oooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00000000 ; + +; Character: ? (8F) + .db 0b00011000 ; oo + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01111110 ; oooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00000000 ; + +; Character: ? (90) + .db 0b00001100 ; oo + .db 0b00011000 ; oo + .db 0b01111110 ; oooooo + .db 0b01100000 ; oo + .db 0b01111100 ; ooooo + .db 0b01100000 ; oo + .db 0b01111110 ; oooooo + .db 0b00000000 ; + +; Character: ? (91) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b01111110 ; oooooo + .db 0b00011011 ; oo oo + .db 0b01111111 ; ooooooo + .db 0b11011000 ; oo oo + .db 0b01111110 ; oooooo + .db 0b00000000 ; + +; Character: ? (92) + .db 0b00111111 ; oooooo + .db 0b01111000 ; oooo + .db 0b11011000 ; oo oo + .db 0b11011110 ; oo oooo + .db 0b11111000 ; ooooo + .db 0b11011000 ; oo oo + .db 0b11011111 ; oo ooooo + .db 0b00000000 ; + +; Character: ? (93) + .db 0b00011000 ; oo + .db 0b00110100 ; oo o + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: ? (94) + .db 0b00100100 ; o o + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: ? (95) + .db 0b00110000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: ? (96) + .db 0b00011000 ; oo + .db 0b00100100 ; o o + .db 0b00000000 ; + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: ? (97) + .db 0b00110000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: ? (98) + .db 0b01100110 ; oo oo + .db 0b00000000 ; + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111110 ; ooooo + .db 0b01000110 ; o oo + .db 0b00111100 ; oooo + +; Character: ? (99) + .db 0b01100110 ; oo oo + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: ? (9A) + .db 0b01100110 ; oo oo + .db 0b00000000 ; + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: ? (9B) + .db 0b00011000 ; oo + .db 0b00111100 ; oooo + .db 0b01100010 ; oo o + .db 0b01100000 ; oo + .db 0b01100000 ; oo + .db 0b01100010 ; oo o + .db 0b00111100 ; oooo + .db 0b00011000 ; oo + +; Character: ? (9C) + .db 0b00011100 ; ooo + .db 0b00111010 ; ooo o + .db 0b00110000 ; oo + .db 0b01111100 ; ooooo + .db 0b00110000 ; oo + .db 0b00110000 ; oo + .db 0b01111110 ; oooooo + .db 0b00000000 ; + +; Character: ? (9D) + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b00011000 ; oo + .db 0b00111100 ; oooo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + +; Character: ? (9E) + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01101100 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b11101100 ; ooo oo + .db 0b00000000 ; + +; Character: ? (9F) + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + +; Character: ? (A0) + .db 0b00001100 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b00000110 ; oo + .db 0b01111110 ; oooooo + .db 0b00111110 ; ooooo + .db 0b00000000 ; + +; Character: ? (A1) + .db 0b00001100 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + +; Character: ? (A2) + .db 0b00001100 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: ? (A3) + .db 0b00001100 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111110 ; ooooo + .db 0b00000000 ; + +; Character: ? (A4) + .db 0b00110100 ; oo o + .db 0b01011000 ; o oo + .db 0b00000000 ; + .db 0b01111100 ; ooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00000000 ; + +; Character: ? (A5) + .db 0b00011010 ; oo o + .db 0b00101100 ; o oo + .db 0b01100010 ; oo o + .db 0b01110010 ; ooo o + .db 0b01011010 ; o oo o + .db 0b01001110 ; o ooo + .db 0b01000110 ; o oo + .db 0b00000000 ; + +; Character: ? (A6) + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01000110 ; o oo + .db 0b00111110 ; ooooo + .db 0b01100110 ; oo oo + .db 0b00111110 ; ooooo + .db 0b00000000 ; + .db 0b01111110 ; oooooo + +; Character: ? (A7) + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + .db 0b01111110 ; oooooo + +; Character: ? (A8) + .db 0b00000000 ; + .db 0b00011000 ; oo + .db 0b00000000 ; + .db 0b00011000 ; oo + .db 0b00110000 ; oo + .db 0b01100000 ; oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + +; Character: ? (A9) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00111110 ; ooooo + .db 0b00110000 ; oo + .db 0b00110000 ; oo + .db 0b00110000 ; oo + .db 0b00000000 ; + +; Character: ? (AA) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b01111100 ; ooooo + .db 0b00001100 ; oo + .db 0b00001100 ; oo + .db 0b00001100 ; oo + .db 0b00000000 ; + +; Character: ? (AB) + .db 0b01100010 ; oo o + .db 0b11100100 ; ooo o + .db 0b01101000 ; oo o + .db 0b01110110 ; ooo oo + .db 0b00101011 ; o o oo + .db 0b01000011 ; o oo + .db 0b10000110 ; o oo + .db 0b00001111 ; oooo + +; Character: ? (AC) + .db 0b01100010 ; oo o + .db 0b11100100 ; ooo o + .db 0b01101000 ; oo o + .db 0b01110110 ; ooo oo + .db 0b00101110 ; o ooo + .db 0b01010110 ; o o oo + .db 0b10011111 ; o ooooo + .db 0b00000110 ; oo + +; Character: ? (AD) + .db 0b00000000 ; + .db 0b00011000 ; oo + .db 0b00000000 ; + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + +; Character: ? (AE) + .db 0b00011011 ; oo oo + .db 0b00110110 ; oo oo + .db 0b01101100 ; oo oo + .db 0b11011000 ; oo oo + .db 0b01101100 ; oo oo + .db 0b00110110 ; oo oo + .db 0b00011011 ; oo oo + .db 0b00000000 ; + +; Character: ? (AF) + .db 0b11011000 ; oo oo + .db 0b01101100 ; oo oo + .db 0b00110110 ; oo oo + .db 0b00011011 ; oo oo + .db 0b00110110 ; oo oo + .db 0b01101100 ; oo oo + .db 0b11011000 ; oo oo + .db 0b00000000 ; + +; Character: ? (B0) + .db 0b00110100 ; oo o + .db 0b01011000 ; o oo + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b00000110 ; oo + .db 0b01111110 ; oooooo + .db 0b00111110 ; ooooo + .db 0b00000000 ; + +; Character: ? (B1) + .db 0b00110100 ; oo o + .db 0b01011000 ; o oo + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: ? (B2) + .db 0b00000010 ; o + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01101110 ; oo ooo + .db 0b01110110 ; ooo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b01000000 ; o + +; Character: ? (B3) + .db 0b00000000 ; + .db 0b00000010 ; o + .db 0b00111100 ; oooo + .db 0b01101110 ; oo ooo + .db 0b01110110 ; ooo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b01000000 ; o + +; Character: ? (B4) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b01111110 ; oooooo + .db 0b11011011 ; oo oo oo + .db 0b11011110 ; oo oooo + .db 0b11011000 ; oo oo + .db 0b01111111 ; ooooooo + .db 0b00000000 ; + +; Character: ? (B5) + .db 0b00000000 ; + .db 0b01111110 ; oooooo + .db 0b11011000 ; oo oo + .db 0b11011000 ; oo oo + .db 0b11111100 ; oooooo + .db 0b11011000 ; oo oo + .db 0b11011000 ; oo oo + .db 0b11011110 ; oo oooo + +; Character: ? (B6) + .db 0b00100000 ; o + .db 0b00010000 ; o + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01111110 ; oooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + +; Character: ? (B7) + .db 0b00110100 ; oo o + .db 0b01011000 ; o oo + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01111110 ; oooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + +; Character: ? (B8) + .db 0b00110100 ; oo o + .db 0b01011000 ; o oo + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + +; Character: ? (B9) + .db 0b01100110 ; oo oo + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (BA) + .db 0b00001100 ; oo + .db 0b00011000 ; oo + .db 0b00110000 ; oo + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (BB) + .db 0b00000000 ; + .db 0b00010000 ; o + .db 0b00111000 ; ooo + .db 0b00010000 ; o + .db 0b00010000 ; o + .db 0b00010000 ; o + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (BC) + .db 0b01111010 ; oooo o + .db 0b11001010 ; oo o o + .db 0b11001010 ; oo o o + .db 0b11001010 ; oo o o + .db 0b01111010 ; oooo o + .db 0b00001010 ; o o + .db 0b00001010 ; o o + .db 0b00001010 ; o o + +; Character: ? (BD) + .db 0b00111100 ; oooo + .db 0b01000010 ; o o + .db 0b10011001 ; o oo o + .db 0b10110101 ; o oo o o + .db 0b10110001 ; o oo o + .db 0b10011101 ; o ooo o + .db 0b01000010 ; o o + .db 0b00111100 ; oooo + +; Character: ? (BE) + .db 0b00111100 ; oooo + .db 0b01000010 ; o o + .db 0b10111001 ; o ooo o + .db 0b10110101 ; o oo o o + .db 0b10111001 ; o ooo o + .db 0b10110101 ; o oo o o + .db 0b01000010 ; o o + .db 0b00111100 ; oooo + +; Character: ? (BF) + .db 0b11110001 ; oooo o + .db 0b01011011 ; o oo oo + .db 0b01010101 ; o o o o + .db 0b01010001 ; o o o + .db 0b01010001 ; o o o + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (C0) + .db 0b01100110 ; oo oo + .db 0b00000000 ; + .db 0b11100110 ; ooo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b11110110 ; oooo oo + .db 0b00000110 ; oo + .db 0b00011100 ; ooo + +; Character: ? (C1) + .db 0b11110110 ; oooo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b11110110 ; oooo oo + .db 0b00000110 ; oo + .db 0b00011100 ; ooo + +; Character: ? (C2) + .db 0b00000000 ; + .db 0b01100110 ; oo oo + .db 0b01110110 ; ooo oo + .db 0b00111100 ; oooo + .db 0b01101110 ; oo ooo + .db 0b01100110 ; oo oo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (C3) + .db 0b00000000 ; + .db 0b01111100 ; ooooo + .db 0b00001100 ; oo + .db 0b00001100 ; oo + .db 0b00001100 ; oo + .db 0b01111110 ; oooooo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (C4) + .db 0b00000000 ; + .db 0b00011110 ; oooo + .db 0b00000110 ; oo + .db 0b00001110 ; ooo + .db 0b00011110 ; oooo + .db 0b00110110 ; oo oo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (C5) + .db 0b00000000 ; + .db 0b01111110 ; oooooo + .db 0b00001100 ; oo + .db 0b00001100 ; oo + .db 0b00001100 ; oo + .db 0b00001100 ; oo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (C6) + .db 0b00000000 ; + .db 0b01111100 ; ooooo + .db 0b00000110 ; oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (C7) + .db 0b00000000 ; + .db 0b00011100 ; ooo + .db 0b00001100 ; oo + .db 0b00001100 ; oo + .db 0b00001100 ; oo + .db 0b00001100 ; oo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (C8) + .db 0b00000000 ; + .db 0b00011110 ; oooo + .db 0b00001100 ; oo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (C9) + .db 0b00000000 ; + .db 0b01111110 ; oooooo + .db 0b00110110 ; oo oo + .db 0b00110110 ; oo oo + .db 0b00110110 ; oo oo + .db 0b00110110 ; oo oo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (CA) + .db 0b01100000 ; oo + .db 0b01101110 ; oo ooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01111110 ; oooooo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (CB) + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b00001100 ; oo + .db 0b00001100 ; oo + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (CC) + .db 0b00000000 ; + .db 0b00111110 ; ooooo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00111110 ; ooooo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (CD) + .db 0b01100000 ; oo + .db 0b01111110 ; oooooo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00001110 ; ooo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (CE) + .db 0b00000000 ; + .db 0b01101100 ; oo oo + .db 0b00111110 ; ooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01101110 ; oo ooo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (CF) + .db 0b00000000 ; + .db 0b00011100 ; ooo + .db 0b00001100 ; oo + .db 0b00001100 ; oo + .db 0b00001100 ; oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (D0) + .db 0b00000000 ; + .db 0b00111110 ; ooooo + .db 0b00110110 ; oo oo + .db 0b00110110 ; oo oo + .db 0b00110110 ; oo oo + .db 0b00011100 ; ooo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (D1) + .db 0b00000000 ; + .db 0b00110110 ; oo oo + .db 0b00110110 ; oo oo + .db 0b00110110 ; oo oo + .db 0b00110110 ; oo oo + .db 0b01111110 ; oooooo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (D2) + .db 0b00000000 ; + .db 0b01111110 ; oooooo + .db 0b01100110 ; oo oo + .db 0b01110110 ; ooo oo + .db 0b00000110 ; oo + .db 0b01111110 ; oooooo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (D3) + .db 0b00000000 ; + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b00001110 ; ooo + .db 0b01111110 ; oooooo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (D4) + .db 0b00000000 ; + .db 0b00111110 ; ooooo + .db 0b00000110 ; oo + .db 0b00110110 ; oo oo + .db 0b00110110 ; oo oo + .db 0b00110100 ; oo o + .db 0b00110000 ; oo + .db 0b00000000 ; + +; Character: ? (D5) + .db 0b00000000 ; + .db 0b01111000 ; oooo + .db 0b00001100 ; oo + .db 0b00001100 ; oo + .db 0b00001100 ; oo + .db 0b00001100 ; oo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (D6) + .db 0b00000000 ; + .db 0b11010110 ; oo o oo + .db 0b11010110 ; oo o oo + .db 0b11010110 ; oo o oo + .db 0b11010110 ; oo o oo + .db 0b11111110 ; ooooooo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (D7) + .db 0b00000000 ; + .db 0b01111100 ; ooooo + .db 0b01101100 ; oo oo + .db 0b01101100 ; oo oo + .db 0b01101100 ; oo oo + .db 0b11101100 ; ooo oo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (D8) + .db 0b00000000 ; + .db 0b00011100 ; ooo + .db 0b00001100 ; oo + .db 0b00001100 ; oo + .db 0b00001100 ; oo + .db 0b00001100 ; oo + .db 0b00001100 ; oo + .db 0b00000000 ; + +; Character: ? (D9) + .db 0b00000000 ; + .db 0b00111110 ; ooooo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00000000 ; + +; Character: ? (DA) + .db 0b00000000 ; + .db 0b11111110 ; ooooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01111110 ; oooooo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (DB) + .db 0b00000000 ; + .db 0b01111110 ; oooooo + .db 0b01100110 ; oo oo + .db 0b01110110 ; ooo oo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00000110 ; oo + .db 0b00000000 ; + +; Character: ? (DC) + .db 0b00000000 ; + .db 0b00110110 ; oo oo + .db 0b00110110 ; oo oo + .db 0b00011100 ; ooo + .db 0b00001100 ; oo + .db 0b00001100 ; oo + .db 0b00001100 ; oo + .db 0b00000000 ; + +; Character: ? (DD) + .db 0b00011100 ; ooo + .db 0b00110010 ; oo o + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b01001100 ; o oo + .db 0b00111000 ; ooo + +; Character: ? (DE) + .db 0b00000000 ; + .db 0b00010000 ; o + .db 0b00111000 ; ooo + .db 0b01101100 ; oo oo + .db 0b11000110 ; oo oo + .db 0b10000010 ; o o + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (DF) + .db 0b01100110 ; oo oo + .db 0b11110111 ; oooo ooo + .db 0b10011001 ; o oo o + .db 0b10011001 ; o oo o + .db 0b11101111 ; ooo oooo + .db 0b01100110 ; oo oo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (E0) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b01110110 ; ooo oo + .db 0b11011100 ; oo ooo + .db 0b11001000 ; oo o + .db 0b11011100 ; oo ooo + .db 0b01110110 ; ooo oo + .db 0b00000000 ; + +; Character: ? (E1) + .db 0b00011100 ; ooo + .db 0b00110110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01111100 ; ooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01111100 ; ooooo + .db 0b01100000 ; oo + +; Character: ? (E2) + .db 0b00000000 ; + .db 0b11111110 ; ooooooo + .db 0b01100110 ; oo oo + .db 0b01100010 ; oo o + .db 0b01100000 ; oo + .db 0b01100000 ; oo + .db 0b01100000 ; oo + .db 0b11111000 ; ooooo + +; Character: ? (E3) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b11111110 ; ooooooo + .db 0b01101100 ; oo oo + .db 0b01101100 ; oo oo + .db 0b01101100 ; oo oo + .db 0b01101100 ; oo oo + .db 0b01001000 ; o o + +; Character: ? (E4) + .db 0b11111110 ; ooooooo + .db 0b01100110 ; oo oo + .db 0b00110000 ; oo + .db 0b00011000 ; oo + .db 0b00110000 ; oo + .db 0b01100110 ; oo oo + .db 0b11111110 ; ooooooo + .db 0b00000000 ; + +; Character: ? (E5) + .db 0b00000000 ; + .db 0b00011110 ; oooo + .db 0b00111000 ; ooo + .db 0b01101100 ; oo oo + .db 0b01101100 ; oo oo + .db 0b01101100 ; oo oo + .db 0b00111000 ; ooo + .db 0b00000000 ; + +; Character: ? (E6) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b01101100 ; oo oo + .db 0b01101100 ; oo oo + .db 0b01101100 ; oo oo + .db 0b01101100 ; oo oo + .db 0b01111111 ; ooooooo + .db 0b11000000 ; oo + +; Character: ? (E7) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b01111110 ; oooooo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00010000 ; o + +; Character: ? (E8) + .db 0b00111100 ; oooo + .db 0b00011000 ; oo + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b00011000 ; oo + .db 0b00111100 ; oooo + +; Character: ? (E9) + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01111110 ; oooooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: ? (EA) + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00100100 ; o o + .db 0b01100110 ; oo oo + .db 0b00000000 ; + +; Character: ? (EB) + .db 0b00011100 ; ooo + .db 0b00110110 ; oo oo + .db 0b01111000 ; oooo + .db 0b11011100 ; oo ooo + .db 0b11001100 ; oo oo + .db 0b11101100 ; ooo oo + .db 0b01111000 ; oooo + .db 0b00000000 ; + +; Character: ? (EC) + .db 0b00001100 ; oo + .db 0b00011000 ; oo + .db 0b00111000 ; ooo + .db 0b01010100 ; o o o + .db 0b01010100 ; o o o + .db 0b00111000 ; ooo + .db 0b00110000 ; oo + .db 0b01100000 ; oo + +; Character: ? (ED) + .db 0b00000000 ; + .db 0b00010000 ; o + .db 0b01111100 ; ooooo + .db 0b11010110 ; oo o oo + .db 0b11010110 ; oo o oo + .db 0b11010110 ; oo o oo + .db 0b01111100 ; ooooo + .db 0b00010000 ; o + +; Character: ? (EE) + .db 0b00111110 ; ooooo + .db 0b01110000 ; ooo + .db 0b01100000 ; oo + .db 0b01111110 ; oooooo + .db 0b01100000 ; oo + .db 0b01110000 ; ooo + .db 0b00111110 ; ooooo + .db 0b00000000 ; + +; Character: ? (EF) + .db 0b00111100 ; oooo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b01100110 ; oo oo + .db 0b00000000 ; + +; Character: ? (F0) + .db 0b00000000 ; + .db 0b01111110 ; oooooo + .db 0b00000000 ; + .db 0b01111110 ; oooooo + .db 0b00000000 ; + .db 0b01111110 ; oooooo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (F1) + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b01111110 ; oooooo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + .db 0b01111110 ; oooooo + .db 0b00000000 ; + +; Character: ? (F2) + .db 0b00110000 ; oo + .db 0b00011000 ; oo + .db 0b00001100 ; oo + .db 0b00011000 ; oo + .db 0b00110000 ; oo + .db 0b00000000 ; + .db 0b01111110 ; oooooo + .db 0b00000000 ; + +; Character: ? (F3) + .db 0b00001100 ; oo + .db 0b00011000 ; oo + .db 0b00110000 ; oo + .db 0b00011000 ; oo + .db 0b00001100 ; oo + .db 0b00000000 ; + .db 0b01111110 ; oooooo + .db 0b00000000 ; + +; Character: ? (F4) + .db 0b00000000 ; + .db 0b00001110 ; ooo + .db 0b00011011 ; oo oo + .db 0b00011011 ; oo oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + +; Character: ? (F5) + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b11011000 ; oo oo + .db 0b11011000 ; oo oo + .db 0b01110000 ; ooo + .db 0b00000000 ; + +; Character: ? (F6) + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + .db 0b01111110 ; oooooo + .db 0b00000000 ; + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + +; Character: ? (F7) + .db 0b00000000 ; + .db 0b00110010 ; oo o + .db 0b01001100 ; o oo + .db 0b00000000 ; + .db 0b00110010 ; oo o + .db 0b01001100 ; o oo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (F8) + .db 0b00111000 ; ooo + .db 0b01101100 ; oo oo + .db 0b00111000 ; ooo + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (F9) + .db 0b00111000 ; ooo + .db 0b01111100 ; ooooo + .db 0b00111000 ; ooo + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (FA) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (FB) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00001111 ; oooo + .db 0b00011000 ; oo + .db 0b11011000 ; oo oo + .db 0b01110000 ; ooo + .db 0b00110000 ; oo + .db 0b00000000 ; + +; Character: ? (FC) + .db 0b00111000 ; ooo + .db 0b01101100 ; oo oo + .db 0b01101100 ; oo oo + .db 0b01101100 ; oo oo + .db 0b01101100 ; oo oo + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (FD) + .db 0b00111000 ; ooo + .db 0b01101100 ; oo oo + .db 0b00011000 ; oo + .db 0b00110000 ; oo + .db 0b01111100 ; ooooo + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (FE) + .db 0b01111000 ; oooo + .db 0b00001100 ; oo + .db 0b00111000 ; ooo + .db 0b00001100 ; oo + .db 0b01111000 ; oooo + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (FF) + .db 0b00000000 ; + .db 0b11111110 ; ooooooo + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + diff --git a/gbdk/gbdk-lib/libc/targets/z80/f_ibm_sh.s b/gbdk/gbdk-lib/libc/targets/z80/f_ibm_sh.s new file mode 100644 index 00000000..83e66d6b --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/f_ibm_sh.s @@ -0,0 +1,174 @@ +; ibm_fixed.ms - fixed width IBM font + + .area _HOME + + ; 898 bytes giving ' '-'0'-'@'-'A'-'Z'-'???'-'a'-'z'-127 +_font_ibm:: + .byte 1+4 ; 128 character encoding + .byte 128-32+6 ; Tiles required + + .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,96,97 ; All map to space + .byte 0,0,0,0,0,0,0,0,0,0,0,0,98,99,100,101 + .byte 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 ; 0x20 + .byte 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 + .byte 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47 ; 0x40 + .byte 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63 + .byte 64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79 ; 0x60 + .byte 80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95 + + .byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + .byte 0x18,0x18,0x18,0x18,0x18,0x00,0x18,0x00 + .byte 0x66,0x66,0x44,0x00,0x00,0x00,0x00,0x00 + .byte 0x00,0x24,0x7E,0x24,0x24,0x7E,0x24,0x00 + .byte 0x14,0x3E,0x55,0x3C,0x1E,0x55,0x3E,0x14 + .byte 0x62,0x66,0x0C,0x18,0x30,0x66,0x46,0x00 + .byte 0x78,0xCC,0x61,0xCE,0xCC,0xCC,0x78,0x00 + .byte 0x18,0x18,0x10,0x00,0x00,0x00,0x00,0x00 + .byte 0x04,0x08,0x18,0x18,0x18,0x18,0x08,0x04 + .byte 0x20,0x10,0x18,0x18,0x18,0x18,0x10,0x20 + .byte 0x00,0x54,0x38,0xFE,0x38,0x54,0x00,0x00 + .byte 0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00 + .byte 0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x20 + .byte 0x00,0x00,0x00,0x3C,0x00,0x00,0x00,0x00 + .byte 0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00 + .byte 0x03,0x06,0x0C,0x18,0x30,0x60,0xC0,0x00 + .byte 0x3C,0x66,0x6E,0x76,0x66,0x66,0x3C,0x00 + .byte 0x18,0x38,0x18,0x18,0x18,0x18,0x18,0x00 + .byte 0x3C,0x66,0x0E,0x1C,0x38,0x70,0x7E,0x00 + .byte 0x7E,0x0C,0x18,0x3C,0x06,0x46,0x3C,0x00 + .byte 0x0C,0x1C,0x2C,0x4C,0x7E,0x0C,0x0C,0x00 + .byte 0x7E,0x60,0x7C,0x06,0x06,0x46,0x3C,0x00 + .byte 0x1C,0x20,0x60,0x7C,0x66,0x66,0x3C,0x00 + .byte 0x7E,0x06,0x0E,0x1C,0x18,0x18,0x18,0x00 + .byte 0x3C,0x66,0x66,0x3C,0x66,0x66,0x3C,0x00 + .byte 0x3C,0x66,0x66,0x3E,0x06,0x0C,0x38,0x00 + .byte 0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x00 + .byte 0x00,0x18,0x18,0x00,0x18,0x18,0x10,0x00 + .byte 0x06,0x0C,0x18,0x30,0x18,0x0C,0x06,0x00 + .byte 0x00,0x00,0x3C,0x00,0x00,0x3C,0x00,0x00 + .byte 0x60,0x30,0x18,0x0C,0x18,0x30,0x60,0x00 + .byte 0x3C,0x46,0x06,0x0C,0x18,0x18,0x00,0x18 + .byte 0x3C,0x66,0x6E,0x6A,0x6E,0x60,0x3C,0x00 + .byte 0x3C,0x66,0x66,0x7E,0x66,0x66,0x66,0x00 + .byte 0x7C,0x66,0x66,0x7C,0x66,0x66,0x7C,0x00 + .byte 0x3C,0x62,0x60,0x60,0x60,0x62,0x3C,0x00 + .byte 0x7C,0x66,0x66,0x66,0x66,0x66,0x7C,0x00 + .byte 0x7E,0x60,0x60,0x7C,0x60,0x60,0x7E,0x00 + .byte 0x7E,0x60,0x60,0x7C,0x60,0x60,0x60,0x00 + .byte 0x3C,0x62,0x60,0x6E,0x66,0x66,0x3E,0x00 + .byte 0x66,0x66,0x66,0x7E,0x66,0x66,0x66,0x00 + .byte 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00 + .byte 0x06,0x06,0x06,0x06,0x06,0x46,0x3C,0x00 + .byte 0x66,0x6C,0x78,0x70,0x78,0x6C,0x66,0x00 + .byte 0x60,0x60,0x60,0x60,0x60,0x60,0x7C,0x00 + .byte 0xFC,0xD6,0xD6,0xD6,0xD6,0xC6,0xC6,0x00 + .byte 0x62,0x72,0x7A,0x5E,0x4E,0x46,0x42,0x00 + .byte 0x3C,0x66,0x66,0x66,0x66,0x66,0x3C,0x00 + .byte 0x7C,0x66,0x66,0x7C,0x60,0x60,0x60,0x00 + .byte 0x3C,0x66,0x66,0x66,0x66,0x66,0x3C,0x06 + .byte 0x7C,0x66,0x66,0x7C,0x66,0x66,0x66,0x00 + .byte 0x3C,0x62,0x70,0x3C,0x0E,0x46,0x3C,0x00 + .byte 0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x00 + .byte 0x66,0x66,0x66,0x66,0x66,0x66,0x3C,0x00 + .byte 0x66,0x66,0x66,0x66,0x66,0x64,0x78,0x00 + .byte 0xC6,0xC6,0xC6,0xD6,0xD6,0xD6,0xFC,0x00 + .byte 0x66,0x66,0x66,0x3C,0x66,0x66,0x66,0x00 + .byte 0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x00 + .byte 0x7E,0x0E,0x1C,0x38,0x70,0x60,0x7E,0x00 + .byte 0x1E,0x18,0x18,0x18,0x18,0x18,0x1E,0x00 + .byte 0x40,0x60,0x30,0x18,0x0C,0x06,0x02,0x00 + .byte 0x78,0x18,0x18,0x18,0x18,0x18,0x78,0x00 + .byte 0x10,0x38,0x6C,0x00,0x00,0x00,0x00,0x00 + .byte 0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00 + .byte 0x00,0xC0,0xC0,0x60,0x00,0x00,0x00,0x00 + .byte 0x00,0x3C,0x46,0x3E,0x66,0x66,0x3E,0x00 + .byte 0x60,0x7C,0x66,0x66,0x66,0x66,0x7C,0x00 + .byte 0x00,0x3C,0x62,0x60,0x60,0x62,0x3C,0x00 + .byte 0x06,0x3E,0x66,0x66,0x66,0x66,0x3E,0x00 + .byte 0x00,0x3C,0x66,0x7E,0x60,0x62,0x3C,0x00 + .byte 0x1E,0x30,0x7C,0x30,0x30,0x30,0x30,0x00 + .byte 0x00,0x3E,0x66,0x66,0x66,0x3E,0x46,0x3C + .byte 0x60,0x7C,0x66,0x66,0x66,0x66,0x66,0x00 + .byte 0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00 + .byte 0x00,0x08,0x18,0x18,0x18,0x18,0x58,0x30 + .byte 0x60,0x64,0x68,0x70,0x78,0x6C,0x66,0x00 + .byte 0x18,0x18,0x18,0x18,0x18,0x18,0x0C,0x00 + .byte 0x00,0xFC,0xD6,0xD6,0xD6,0xD6,0xC6,0x00 + .byte 0x00,0x7C,0x66,0x66,0x66,0x66,0x66,0x00 + .byte 0x00,0x3C,0x66,0x66,0x66,0x66,0x3C,0x00 + .byte 0x00,0x7C,0x66,0x66,0x66,0x7C,0x60,0x60 + .byte 0x00,0x3E,0x66,0x66,0x66,0x66,0x3E,0x06 + .byte 0x00,0x6C,0x70,0x60,0x60,0x60,0x60,0x00 + .byte 0x00,0x3C,0x72,0x38,0x1C,0x4E,0x3C,0x00 + .byte 0x18,0x3C,0x18,0x18,0x18,0x18,0x0C,0x00 + .byte 0x00,0x66,0x66,0x66,0x66,0x66,0x3E,0x00 + .byte 0x00,0x66,0x66,0x66,0x66,0x64,0x78,0x00 + .byte 0x00,0xC6,0xC6,0xD6,0xD6,0xD6,0xFC,0x00 + .byte 0x00,0x66,0x66,0x3C,0x66,0x66,0x66,0x00 + .byte 0x00,0x66,0x66,0x66,0x26,0x1E,0x46,0x3C + .byte 0x00,0x7E,0x0E,0x1C,0x38,0x70,0x7E,0x00 + .byte 0x0E,0x18,0x18,0x30,0x18,0x18,0x0E,0x00 + .byte 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18 + .byte 0x70,0x18,0x18,0x0C,0x18,0x18,0x70,0x00 + .byte 0x00,0x60,0xF2,0x9E,0x0C,0x00,0x00,0x00 + .byte 0x10,0x10,0x28,0x28,0x44,0x44,0x82,0xFE + +; Character: ? (0E) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b11111111 ; oooooooo + .db 0b11111111 ; oooooooo + .db 0b11111111 ; oooooooo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (0F) + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + +; Character: ? (1C) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00011111 ; ooooo + .db 0b00011111 ; ooooo + .db 0b00011111 ; ooooo + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + +; Character: ? (1D) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b11111100 ; oooooo + .db 0b11111100 ; oooooo + .db 0b11111100 ; oooooo + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + +; Character: ? (1E) + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + .db 0b00011111 ; ooooo + .db 0b00011111 ; ooooo + .db 0b00011111 ; ooooo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ? (1F) + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + .db 0b00011100 ; ooo + .db 0b11111100 ; oooooo + .db 0b11111100 ; oooooo + .db 0b11111100 ; oooooo + .db 0b00000000 ; + .db 0b00000000 ; diff --git a/gbdk/gbdk-lib/libc/targets/z80/f_italic.s b/gbdk/gbdk-lib/libc/targets/z80/f_italic.s new file mode 100644 index 00000000..cca67aa6 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/f_italic.s @@ -0,0 +1,957 @@ +; font: italic + + .area _HOME + +_font_italic:: + .db 1+4 ; 128 char encoding, compressed + .db 93 ; Number of tiles + +; Encoding table + + .db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + .db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + .db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + .db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + .db 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 + .db 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F + .db 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17 + .db 0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F + .db 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27 + .db 0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F + .db 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37 + .db 0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x00 + .db 0x00,0x3F,0x40,0x41,0x42,0x43,0x44,0x45 + .db 0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D + .db 0x4E,0x4F,0x50,0x51,0x52,0x53,0x54,0x55 + .db 0x56,0x57,0x58,0x59,0x5A,0x5B,0x5C,0x00 +; Tile data +; Default character (space) + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + +; Character: ! (21) + .db 0b00000000 ; + .db 0b00001000 ; o + .db 0b00001000 ; o + .db 0b00001000 ; o + .db 0b00010000 ; o + .db 0b00010000 ; o + .db 0b00000000 ; + .db 0b00100000 ; o + +; Character: " (22) + .db 0b00000000 ; + .db 0b00100100 ; o o + .db 0b00100100 ; o o + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: # (23) + .db 0b00000000 ; + .db 0b00100100 ; o o + .db 0b01111110 ; oooooo + .db 0b00100100 ; o o + .db 0b00100100 ; o o + .db 0b01111110 ; oooooo + .db 0b00100100 ; o o + .db 0b00000000 ; + +; Character: $ (24) + .db 0b00000000 ; + .db 0b00001000 ; o + .db 0b00111110 ; ooooo + .db 0b00101000 ; o o + .db 0b00111110 ; ooooo + .db 0b00001010 ; o o + .db 0b00111110 ; ooooo + .db 0b00001000 ; o + +; Character: % (25) + .db 0b00000000 ; + .db 0b01100010 ; oo o + .db 0b01100100 ; oo o + .db 0b00001000 ; o + .db 0b00010000 ; o + .db 0b00100110 ; o oo + .db 0b01000110 ; o oo + .db 0b00000000 ; + +; Character: & (26) + .db 0b00000000 ; + .db 0b00010000 ; o + .db 0b00101000 ; o o + .db 0b00010000 ; o + .db 0b00101010 ; o o o + .db 0b01000100 ; o o + .db 0b00111010 ; ooo o + .db 0b00000000 ; + +; Character: ' (27) + .db 0b00000000 ; + .db 0b00001000 ; o + .db 0b00010000 ; o + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: ( (28) + .db 0b00000000 ; + .db 0b00000100 ; o + .db 0b00001000 ; o + .db 0b00001000 ; o + .db 0b00001000 ; o + .db 0b00001000 ; o + .db 0b00000100 ; o + .db 0b00000000 ; + +; Character: ) (29) + .db 0b00000000 ; + .db 0b00100000 ; o + .db 0b00010000 ; o + .db 0b00010000 ; o + .db 0b00010000 ; o + .db 0b00010000 ; o + .db 0b00100000 ; o + .db 0b00000000 ; + +; Character: * (2A) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00100100 ; o o + .db 0b00011000 ; oo + .db 0b01111110 ; oooooo + .db 0b00011000 ; oo + .db 0b00100100 ; o o + .db 0b00000000 ; + +; Character: + (2B) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00001000 ; o + .db 0b00001000 ; o + .db 0b00111110 ; ooooo + .db 0b00001000 ; o + .db 0b00001000 ; o + .db 0b00000000 ; + +; Character: , (2C) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00001000 ; o + .db 0b00001000 ; o + .db 0b00010000 ; o + +; Character: - (2D) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00111110 ; ooooo + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: . (2E) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00011000 ; oo + .db 0b00011000 ; oo + .db 0b00000000 ; + +; Character: / (2F) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000010 ; o + .db 0b00000100 ; o + .db 0b00001000 ; o + .db 0b00010000 ; o + .db 0b00100000 ; o + .db 0b00000000 ; + +; Character: 0 (30) + .db 0b00000000 ; + .db 0b00011100 ; ooo + .db 0b00100110 ; o oo + .db 0b01001010 ; o o o + .db 0b01010100 ; o o o + .db 0b10100100 ; o o o + .db 0b11001000 ; oo o + .db 0b01110000 ; ooo + +; Character: 1 (31) + .db 0b00000000 ; + .db 0b00011000 ; oo + .db 0b00101000 ; o o + .db 0b00001000 ; o + .db 0b00010000 ; o + .db 0b00100000 ; o + .db 0b00100000 ; o + .db 0b11111000 ; ooooo + +; Character: 2 (32) + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01000010 ; o o + .db 0b00000100 ; o + .db 0b00011000 ; oo + .db 0b01100000 ; oo + .db 0b10000000 ; o + .db 0b11111100 ; oooooo + +; Character: 3 (33) + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01000010 ; o o + .db 0b00000010 ; o + .db 0b00001100 ; oo + .db 0b00000010 ; o + .db 0b10000100 ; o o + .db 0b01111000 ; oooo + +; Character: 4 (34) + .db 0b00000000 ; + .db 0b00001100 ; oo + .db 0b00110100 ; oo o + .db 0b01000100 ; o o + .db 0b10001000 ; o o + .db 0b11111110 ; ooooooo + .db 0b00010000 ; o + .db 0b00010000 ; o + +; Character: 5 (35) + .db 0b00000000 ; + .db 0b00111110 ; ooooo + .db 0b00100000 ; o + .db 0b01000000 ; o + .db 0b01111000 ; oooo + .db 0b00000100 ; o + .db 0b10000100 ; o o + .db 0b01111000 ; oooo + +; Character: 6 (36) + .db 0b00000000 ; + .db 0b00011100 ; ooo + .db 0b00100010 ; o o + .db 0b01000000 ; o + .db 0b01111000 ; oooo + .db 0b10000100 ; o o + .db 0b10000100 ; o o + .db 0b01111000 ; oooo + +; Character: 7 (37) + .db 0b00000000 ; + .db 0b00111110 ; ooooo + .db 0b00000010 ; o + .db 0b00000100 ; o + .db 0b00001000 ; o + .db 0b00010000 ; o + .db 0b00100000 ; o + .db 0b00100000 ; o + +; Character: 8 (38) + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01000010 ; o o + .db 0b00111100 ; oooo + .db 0b01000010 ; o o + .db 0b10000100 ; o o + .db 0b10000100 ; o o + .db 0b01111000 ; oooo + +; Character: 9 (39) + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01000010 ; o o + .db 0b01000010 ; o o + .db 0b00111100 ; oooo + .db 0b00000100 ; o + .db 0b00001000 ; o + .db 0b11110000 ; oooo + +; Character: : (3A) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00001000 ; o + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00010000 ; o + .db 0b00000000 ; + +; Character: ; (3B) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00010000 ; o + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00010000 ; o + .db 0b00010000 ; o + .db 0b00100000 ; o + +; Character: < (3C) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000100 ; o + .db 0b00001000 ; o + .db 0b00010000 ; o + .db 0b00001000 ; o + .db 0b00000100 ; o + .db 0b00000000 ; + +; Character: = (3D) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00111110 ; ooooo + .db 0b00000000 ; + .db 0b01111100 ; ooooo + .db 0b00000000 ; + .db 0b00000000 ; + +; Character: > (3E) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00010000 ; o + .db 0b00001000 ; o + .db 0b00000100 ; o + .db 0b00001000 ; o + .db 0b00010000 ; o + .db 0b00000000 ; + +; Character: ? (3F) + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01000010 ; o o + .db 0b00000010 ; o + .db 0b00001100 ; oo + .db 0b00010000 ; o + .db 0b00000000 ; + .db 0b00110000 ; oo + +; Character: @ (40) + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b01001010 ; o o o + .db 0b01010110 ; o o oo + .db 0b01011110 ; o oooo + .db 0b01000000 ; o + .db 0b00111100 ; oooo + .db 0b00000000 ; + +; Character: A (41) + .db 0b00000000 ; + .db 0b00011100 ; ooo + .db 0b00100010 ; o o + .db 0b00100010 ; o o + .db 0b01111100 ; ooooo + .db 0b01000100 ; o o + .db 0b10001000 ; o o + .db 0b10001000 ; o o + +; Character: B (42) + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b00100010 ; o o + .db 0b00111100 ; oooo + .db 0b01000010 ; o o + .db 0b01000010 ; o o + .db 0b10000100 ; o o + .db 0b11111000 ; ooooo + +; Character: C (43) + .db 0b00000000 ; + .db 0b00011100 ; ooo + .db 0b00100010 ; o o + .db 0b01000000 ; o + .db 0b01000000 ; o + .db 0b10000000 ; o + .db 0b10000100 ; o o + .db 0b01111000 ; oooo + +; Character: D (44) + .db 0b00000000 ; + .db 0b00111000 ; ooo + .db 0b00100100 ; o o + .db 0b00100010 ; o o + .db 0b01000010 ; o o + .db 0b01000100 ; o o + .db 0b10001000 ; o o + .db 0b11110000 ; oooo + +; Character: E (45) + .db 0b00000000 ; + .db 0b00111110 ; ooooo + .db 0b00100000 ; o + .db 0b01000000 ; o + .db 0b01111000 ; oooo + .db 0b01000000 ; o + .db 0b10000000 ; o + .db 0b11111000 ; ooooo + +; Character: F (46) + .db 0b00000000 ; + .db 0b00111110 ; ooooo + .db 0b00100000 ; o + .db 0b01000000 ; o + .db 0b01111000 ; oooo + .db 0b01000000 ; o + .db 0b10000000 ; o + .db 0b10000000 ; o + +; Character: G (47) + .db 0b00000000 ; + .db 0b00011100 ; ooo + .db 0b00100010 ; o o + .db 0b01000000 ; o + .db 0b01000000 ; o + .db 0b10001110 ; o ooo + .db 0b10000100 ; o o + .db 0b01111000 ; oooo + +; Character: H (48) + .db 0b00000000 ; + .db 0b00100010 ; o o + .db 0b00100010 ; o o + .db 0b01000100 ; o o + .db 0b01111100 ; ooooo + .db 0b01000100 ; o o + .db 0b10001000 ; o o + .db 0b10001000 ; o o + +; Character: I (49) + .db 0b00000000 ; + .db 0b00111110 ; ooooo + .db 0b00001000 ; o + .db 0b00001000 ; o + .db 0b00010000 ; o + .db 0b00100000 ; o + .db 0b00100000 ; o + .db 0b11111000 ; ooooo + +; Character: J (4A) + .db 0b00000000 ; + .db 0b00000010 ; o + .db 0b00000010 ; o + .db 0b00000100 ; o + .db 0b00000100 ; o + .db 0b10001000 ; o o + .db 0b10001000 ; o o + .db 0b01110000 ; ooo + +; Character: K (4B) + .db 0b00000000 ; + .db 0b00100010 ; o o + .db 0b00100100 ; o o + .db 0b01001000 ; o o + .db 0b01110000 ; ooo + .db 0b01001000 ; o o + .db 0b10001000 ; o o + .db 0b10000100 ; o o + +; Character: L (4C) + .db 0b00000000 ; + .db 0b00100000 ; o + .db 0b00100000 ; o + .db 0b01000000 ; o + .db 0b01000000 ; o + .db 0b01000000 ; o + .db 0b10000000 ; o + .db 0b11111100 ; oooooo + +; Character: M (4D) + .db 0b00000000 ; + .db 0b00110110 ; oo oo + .db 0b00101010 ; o o o + .db 0b01010100 ; o o o + .db 0b01010100 ; o o o + .db 0b01000100 ; o o + .db 0b10001000 ; o o + .db 0b10001000 ; o o + +; Character: N (4E) + .db 0b00000000 ; + .db 0b00100010 ; o o + .db 0b00110010 ; oo o + .db 0b01010100 ; o o o + .db 0b01010100 ; o o o + .db 0b01010100 ; o o o + .db 0b10011000 ; o oo + .db 0b10001000 ; o o + +; Character: O (4F) + .db 0b00000000 ; + .db 0b00011100 ; ooo + .db 0b00100010 ; o o + .db 0b01000010 ; o o + .db 0b01000100 ; o o + .db 0b10000100 ; o o + .db 0b10001000 ; o o + .db 0b01110000 ; ooo + +; Character: P (50) + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b00100010 ; o o + .db 0b01000010 ; o o + .db 0b01111100 ; ooooo + .db 0b01000000 ; o + .db 0b10000000 ; o + .db 0b10000000 ; o + +; Character: Q (51) + .db 0b00000000 ; + .db 0b00011100 ; ooo + .db 0b00100010 ; o o + .db 0b01000010 ; o o + .db 0b01000100 ; o o + .db 0b10010100 ; o o o + .db 0b10001000 ; o o + .db 0b01110100 ; ooo o + +; Character: R (52) + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b00100010 ; o o + .db 0b01000010 ; o o + .db 0b01111100 ; ooooo + .db 0b01001000 ; o o + .db 0b10000100 ; o o + .db 0b10000100 ; o o + +; Character: S (53) + .db 0b00000000 ; + .db 0b00011110 ; oooo + .db 0b00100000 ; o + .db 0b00100000 ; o + .db 0b00011000 ; oo + .db 0b00000100 ; o + .db 0b10000100 ; o o + .db 0b01111000 ; oooo + +; Character: T (54) + .db 0b00000000 ; + .db 0b11111110 ; ooooooo + .db 0b00010000 ; o + .db 0b00100000 ; o + .db 0b00100000 ; o + .db 0b00100000 ; o + .db 0b01000000 ; o + .db 0b01000000 ; o + +; Character: U (55) + .db 0b00000000 ; + .db 0b00100010 ; o o + .db 0b00100010 ; o o + .db 0b01000100 ; o o + .db 0b01000100 ; o o + .db 0b10001000 ; o o + .db 0b10001000 ; o o + .db 0b01110000 ; ooo + +; Character: V (56) + .db 0b00000000 ; + .db 0b01000010 ; o o + .db 0b01000010 ; o o + .db 0b01000100 ; o o + .db 0b01000100 ; o o + .db 0b10001000 ; o o + .db 0b10010000 ; o o + .db 0b11100000 ; ooo + +; Character: W (57) + .db 0b00000000 ; + .db 0b00100010 ; o o + .db 0b00100010 ; o o + .db 0b01000100 ; o o + .db 0b01010100 ; o o o + .db 0b10101000 ; o o o + .db 0b10101000 ; o o o + .db 0b01010000 ; o o + +; Character: X (58) + .db 0b00000000 ; + .db 0b01000010 ; o o + .db 0b00100100 ; o o + .db 0b00101000 ; o o + .db 0b00010000 ; o + .db 0b00101000 ; o o + .db 0b01001000 ; o o + .db 0b10000100 ; o o + +; Character: Y (59) + .db 0b00000000 ; + .db 0b01000010 ; o o + .db 0b00100100 ; o o + .db 0b00101000 ; o o + .db 0b00010000 ; o + .db 0b00010000 ; o + .db 0b00100000 ; o + .db 0b00100000 ; o + +; Character: Z (5A) + .db 0b00000000 ; + .db 0b01111110 ; oooooo + .db 0b00000100 ; o + .db 0b00001000 ; o + .db 0b00010000 ; o + .db 0b00100000 ; o + .db 0b01000000 ; o + .db 0b11111100 ; oooooo + +; Character: [ (5B) + .db 0b00000000 ; + .db 0b00001110 ; ooo + .db 0b00001000 ; o + .db 0b00001000 ; o + .db 0b00001000 ; o + .db 0b00001000 ; o + .db 0b00001110 ; ooo + .db 0b00000000 ; + +; Character: \ (5C) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b01000000 ; o + .db 0b00100000 ; o + .db 0b00010000 ; o + .db 0b00001000 ; o + .db 0b00000100 ; o + .db 0b00000000 ; + +; Character: ] (5D) + .db 0b00000000 ; + .db 0b01110000 ; ooo + .db 0b00010000 ; o + .db 0b00010000 ; o + .db 0b00010000 ; o + .db 0b00010000 ; o + .db 0b01110000 ; ooo + .db 0b00000000 ; + +; Character: ^ (5E) + .db 0b00000000 ; + .db 0b00010000 ; o + .db 0b00111000 ; ooo + .db 0b01010100 ; o o o + .db 0b00010000 ; o + .db 0b00010000 ; o + .db 0b00010000 ; o + .db 0b00000000 ; + +; Character: a (61) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00011100 ; ooo + .db 0b00000010 ; o + .db 0b00111110 ; ooooo + .db 0b01000100 ; o o + .db 0b00111100 ; oooo + +; Character: b (62) + .db 0b00000000 ; + .db 0b00010000 ; o + .db 0b00010000 ; o + .db 0b00100000 ; o + .db 0b00111100 ; oooo + .db 0b00100010 ; o o + .db 0b01000100 ; o o + .db 0b01111000 ; oooo + +; Character: c (63) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00011110 ; oooo + .db 0b00100000 ; o + .db 0b01000000 ; o + .db 0b01000000 ; o + .db 0b00111100 ; oooo + +; Character: d (64) + .db 0b00000000 ; + .db 0b00000010 ; o + .db 0b00000010 ; o + .db 0b00000100 ; o + .db 0b00111100 ; oooo + .db 0b01000100 ; o o + .db 0b01001000 ; o o + .db 0b00111000 ; ooo + +; Character: e (65) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00011100 ; ooo + .db 0b00100010 ; o o + .db 0b01111100 ; ooooo + .db 0b01000000 ; o + .db 0b00111000 ; ooo + +; Character: f (66) + .db 0b00000000 ; + .db 0b00001110 ; ooo + .db 0b00010000 ; o + .db 0b00010000 ; o + .db 0b00111000 ; ooo + .db 0b00100000 ; o + .db 0b01000000 ; o + .db 0b01000000 ; o + +; Character: g (67) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00011110 ; oooo + .db 0b00100010 ; o o + .db 0b01000100 ; o o + .db 0b00111100 ; oooo + .db 0b00000100 ; o + .db 0b01111000 ; oooo + +; Character: h (68) + .db 0b00000000 ; + .db 0b00010000 ; o + .db 0b00010000 ; o + .db 0b00100000 ; o + .db 0b00111100 ; oooo + .db 0b00100010 ; o o + .db 0b01000100 ; o o + .db 0b01000100 ; o o + +; Character: i (69) + .db 0b00000000 ; + .db 0b00001000 ; o + .db 0b00000000 ; + .db 0b00011000 ; oo + .db 0b00001000 ; o + .db 0b00010000 ; o + .db 0b00100000 ; o + .db 0b01110000 ; ooo + +; Character: j (6A) + .db 0b00000000 ; + .db 0b00000100 ; o + .db 0b00000000 ; + .db 0b00000100 ; o + .db 0b00000100 ; o + .db 0b01001000 ; o o + .db 0b01001000 ; o o + .db 0b00110000 ; oo + +; Character: k (6B) + .db 0b00000000 ; + .db 0b00010000 ; o + .db 0b00010000 ; o + .db 0b00100000 ; o + .db 0b00100100 ; o o + .db 0b00111000 ; ooo + .db 0b01000100 ; o o + .db 0b01000100 ; o o + +; Character: l (6C) + .db 0b00000000 ; + .db 0b00001000 ; o + .db 0b00001000 ; o + .db 0b00010000 ; o + .db 0b00010000 ; o + .db 0b00100000 ; o + .db 0b00100000 ; o + .db 0b00011000 ; oo + +; Character: m (6D) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00110100 ; oo o + .db 0b00101010 ; o o o + .db 0b00101010 ; o o o + .db 0b01010100 ; o o o + .db 0b01010100 ; o o o + +; Character: n (6E) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00111100 ; oooo + .db 0b00100010 ; o o + .db 0b00100010 ; o o + .db 0b01000100 ; o o + .db 0b01000100 ; o o + +; Character: o (6F) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00011100 ; ooo + .db 0b00100010 ; o o + .db 0b00100010 ; o o + .db 0b01000100 ; o o + .db 0b01000100 ; o o + .db 0b00111000 ; ooo + +; Character: p (70) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00011100 ; ooo + .db 0b00010010 ; o o + .db 0b00100010 ; o o + .db 0b00111100 ; oooo + .db 0b01000000 ; o + .db 0b01000000 ; o + +; Character: q (71) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00011110 ; oooo + .db 0b00100010 ; o o + .db 0b00100100 ; o o + .db 0b00011100 ; ooo + .db 0b00001000 ; o + .db 0b00001100 ; oo + +; Character: r (72) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00001110 ; ooo + .db 0b00010000 ; o + .db 0b00010000 ; o + .db 0b00100000 ; o + .db 0b00100000 ; o + +; Character: s (73) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00011110 ; oooo + .db 0b00100000 ; o + .db 0b00011000 ; oo + .db 0b00000100 ; o + .db 0b01111000 ; oooo + +; Character: t (74) + .db 0b00000000 ; + .db 0b00001000 ; o + .db 0b00001000 ; o + .db 0b00011100 ; ooo + .db 0b00001000 ; o + .db 0b00010000 ; o + .db 0b00010000 ; o + .db 0b00100000 ; o + +; Character: u (75) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00100010 ; o o + .db 0b00100010 ; o o + .db 0b01000100 ; o o + .db 0b01000100 ; o o + .db 0b00111000 ; ooo + +; Character: v (76) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00100010 ; o o + .db 0b00100010 ; o o + .db 0b01000100 ; o o + .db 0b01001000 ; o o + .db 0b00110000 ; oo + +; Character: w (77) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00100010 ; o o + .db 0b00101010 ; o o o + .db 0b01010100 ; o o o + .db 0b01010100 ; o o o + .db 0b00101000 ; o o + +; Character: x (78) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00100100 ; o o + .db 0b00101000 ; o o + .db 0b00011000 ; oo + .db 0b00100100 ; o o + .db 0b01000100 ; o o + +; Character: y (79) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00100010 ; o o + .db 0b00100010 ; o o + .db 0b00011100 ; ooo + .db 0b00000100 ; o + .db 0b01111000 ; oooo + +; Character: z (7A) + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00111110 ; ooooo + .db 0b00000100 ; o + .db 0b00011000 ; oo + .db 0b00100000 ; o + .db 0b01111100 ; ooooo + +; Character: { (7B) + .db 0b00000000 ; + .db 0b00001110 ; ooo + .db 0b00001000 ; o + .db 0b00110000 ; oo + .db 0b00001000 ; o + .db 0b00001000 ; o + .db 0b00001110 ; ooo + .db 0b00000000 ; + +; Character: | (7C) + .db 0b00000000 ; + .db 0b00001000 ; o + .db 0b00001000 ; o + .db 0b00001000 ; o + .db 0b00001000 ; o + .db 0b00001000 ; o + .db 0b00001000 ; o + .db 0b00000000 ; + +; Character: } (7D) + .db 0b00000000 ; + .db 0b01110000 ; ooo + .db 0b00010000 ; o + .db 0b00001100 ; oo + .db 0b00010000 ; o + .db 0b00010000 ; o + .db 0b01110000 ; ooo + .db 0b00000000 ; + +; Character: ~ (7E) + .db 0b00000000 ; + .db 0b00010100 ; o o + .db 0b00101000 ; o o + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + .db 0b00000000 ; + diff --git a/gbdk/gbdk-lib/libc/targets/z80/f_min.s b/gbdk/gbdk-lib/libc/targets/z80/f_min.s new file mode 100644 index 00000000..1fbb5de9 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/f_min.s @@ -0,0 +1,355 @@ +; font_min.s + +; Text font +; Michael Hope, 1998 +; michaelh@earthling.net +; Distrubuted under the Artistic License - see www.opensource.org +; + .module font_min + .area _HOME + +_font_min:: + .byte 1+4 ; 128 character encoding + .byte 37 ; Tiles required + + .byte 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 ; All map to space + .byte 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 ; All map to space + .byte 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 ; All map to space + .byte 01,02,03,04,05,06,07,08,09,10,00,00,00,00,00,00 + .byte 00,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25 + .byte 26,27,28,29,30,21,32,33,34,35,36,00,00,00,00,00 + .byte 00,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25 + .byte 26,27,28,29,30,31,32,33,34,35,36,00,00,00,00,00 + + .db 0 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 +; Character: 0 + .db 0b00000000 + .db 0b00111100 + .db 0b01000110 + .db 0b01001010 + .db 0b01010010 + .db 0b01100010 + .db 0b00111100 + .db 0b00000000 +; Character: 1 + .db 0b00000000 + .db 0b00011000 + .db 0b00101000 + .db 0b00001000 + .db 0b00001000 + .db 0b00001000 + .db 0b00111110 + .db 0b00000000 +; Character: 2 + .db 0b00000000 + .db 0b00111100 + .db 0b01000010 + .db 0b00000010 + .db 0b00111100 + .db 0b01000000 + .db 0b01111110 + .db 0b00000000 +; Character: 3 + .db 0b00000000 + .db 0b00111100 + .db 0b01000010 + .db 0b00001100 + .db 0b00000010 + .db 0b01000010 + .db 0b00111100 + .db 0b00000000 +; Character: 4 + .db 0b00000000 + .db 0b00001000 + .db 0b00011000 + .db 0b00101000 + .db 0b01001000 + .db 0b01111110 + .db 0b00001000 + .db 0b00000000 +; Character: 5 + .db 0b00000000 + .db 0b01111110 + .db 0b01000000 + .db 0b01111100 + .db 0b00000010 + .db 0b01000010 + .db 0b00111100 + .db 0b00000000 +; Character: 6 + .db 0b00000000 + .db 0b00111100 + .db 0b01000000 + .db 0b01111100 + .db 0b01000010 + .db 0b01000010 + .db 0b00111100 + .db 0b00000000 +; Character: 7 + .db 0b00000000 + .db 0b01111110 + .db 0b00000010 + .db 0b00000100 + .db 0b00001000 + .db 0b00010000 + .db 0b00010000 + .db 0b00000000 +; Character: 8 + .db 0b00000000 + .db 0b00111100 + .db 0b01000010 + .db 0b00111100 + .db 0b01000010 + .db 0b01000010 + .db 0b00111100 + .db 0b00000000 +; Character: 9 + .db 0b00000000 + .db 0b00111100 + .db 0b01000010 + .db 0b01000010 + .db 0b00111110 + .db 0b00000010 + .db 0b00111100 + .db 0b00000000 +; Character: A + .db 0b00000000 + .db 0b00111100 + .db 0b01000010 + .db 0b01000010 + .db 0b01111110 + .db 0b01000010 + .db 0b01000010 + .db 0b00000000 +; Character: B + .db 0b00000000 + .db 0b01111100 + .db 0b01000010 + .db 0b01111100 + .db 0b01000010 + .db 0b01000010 + .db 0b01111100 + .db 0b00000000 +; Character: C + .db 0b00000000 + .db 0b00111100 + .db 0b01000010 + .db 0b01000000 + .db 0b01000000 + .db 0b01000010 + .db 0b00111100 + .db 0b00000000 +; Character: D + .db 0b00000000 + .db 0b01111000 + .db 0b01000100 + .db 0b01000010 + .db 0b01000010 + .db 0b01000100 + .db 0b01111000 + .db 0b00000000 +; Character: E + .db 0b00000000 + .db 0b01111110 + .db 0b01000000 + .db 0b01111100 + .db 0b01000000 + .db 0b01000000 + .db 0b01111110 + .db 0b00000000 +; Character: F + .db 0b00000000 + .db 0b01111110 + .db 0b01000000 + .db 0b01111100 + .db 0b01000000 + .db 0b01000000 + .db 0b01000000 + .db 0b00000000 +; Character: G + .db 0b00000000 + .db 0b00111100 + .db 0b01000010 + .db 0b01000000 + .db 0b01001110 + .db 0b01000010 + .db 0b00111100 + .db 0b00000000 +; Character: H + .db 0b00000000 + .db 0b01000010 + .db 0b01000010 + .db 0b01111110 + .db 0b01000010 + .db 0b01000010 + .db 0b01000010 + .db 0b00000000 +; Character: I + .db 0b00000000 + .db 0b00111110 + .db 0b00001000 + .db 0b00001000 + .db 0b00001000 + .db 0b00001000 + .db 0b00111110 + .db 0b00000000 +; Character: J + .db 0b00000000 + .db 0b00000010 + .db 0b00000010 + .db 0b00000010 + .db 0b01000010 + .db 0b01000010 + .db 0b00111100 + .db 0b00000000 +; Character: K + .db 0b00000000 + .db 0b01000100 + .db 0b01001000 + .db 0b01110000 + .db 0b01001000 + .db 0b01000100 + .db 0b01000010 + .db 0b00000000 +; Character: L + .db 0b00000000 + .db 0b01000000 + .db 0b01000000 + .db 0b01000000 + .db 0b01000000 + .db 0b01000000 + .db 0b01111110 + .db 0b00000000 +; Character: M + .db 0b00000000 + .db 0b01000010 + .db 0b01100110 + .db 0b01011010 + .db 0b01000010 + .db 0b01000010 + .db 0b01000010 + .db 0b00000000 +; Character: N + .db 0b00000000 + .db 0b01000010 + .db 0b01100010 + .db 0b01010010 + .db 0b01001010 + .db 0b01000110 + .db 0b01000010 + .db 0b00000000 +; Character: O + .db 0b00000000 + .db 0b00111100 + .db 0b01000010 + .db 0b01000010 + .db 0b01000010 + .db 0b01000010 + .db 0b00111100 + .db 0b00000000 +; Character: P + .db 0b00000000 + .db 0b01111100 + .db 0b01000010 + .db 0b01000010 + .db 0b01111100 + .db 0b01000000 + .db 0b01000000 + .db 0b00000000 +; Character: Q + .db 0b00000000 + .db 0b00111100 + .db 0b01000010 + .db 0b01000010 + .db 0b01010010 + .db 0b01001010 + .db 0b00111100 + .db 0b00000000 +; Character: R + .db 0b00000000 + .db 0b01111100 + .db 0b01000010 + .db 0b01000010 + .db 0b01111100 + .db 0b01000100 + .db 0b01000010 + .db 0b00000000 +; Character: S + .db 0b00000000 + .db 0b00111100 + .db 0b01000000 + .db 0b00111100 + .db 0b00000010 + .db 0b01000010 + .db 0b00111100 + .db 0b00000000 +; Character: T + .db 0b00000000 + .db 0b11111110 + .db 0b00010000 + .db 0b00010000 + .db 0b00010000 + .db 0b00010000 + .db 0b00010000 + .db 0b00000000 +; Character: U + .db 0b00000000 + .db 0b01000010 + .db 0b01000010 + .db 0b01000010 + .db 0b01000010 + .db 0b01000010 + .db 0b00111100 + .db 0b00000000 +; Character: V + .db 0b00000000 + .db 0b01000010 + .db 0b01000010 + .db 0b01000010 + .db 0b01000010 + .db 0b00100100 + .db 0b00011000 + .db 0b00000000 +; Character: W + .db 0b00000000 + .db 0b01000010 + .db 0b01000010 + .db 0b01000010 + .db 0b01000010 + .db 0b01011010 + .db 0b00100100 + .db 0b00000000 +; Character: X + .db 0b00000000 + .db 0b01000010 + .db 0b00100100 + .db 0b00011000 + .db 0b00011000 + .db 0b00100100 + .db 0b01000010 + .db 0b00000000 +; Character: Y + .db 0b00000000 + .db 0b10000010 + .db 0b01000100 + .db 0b00101000 + .db 0b00010000 + .db 0b00010000 + .db 0b00010000 + .db 0b00000000 +; Character: Z + .db 0b00000000 + .db 0b01111110 + .db 0b00000100 + .db 0b00001000 + .db 0b00010000 + .db 0b00100000 + .db 0b01111110 + .db 0b00000000 diff --git a/gbdk/gbdk-lib/libc/targets/z80/f_spect.s b/gbdk/gbdk-lib/libc/targets/z80/f_spect.s new file mode 100644 index 00000000..0da22f4d --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/f_spect.s @@ -0,0 +1,886 @@ +; font_spect.ms +; Text font +; Michael Hope, 1998 +; michaelh@earthling.net +; Distrubuted under the Artistic License - see www.opensource.org +; + + .module font_spect + .area _HOME + +_font_spect:: + .byte 1+4 ; 128 character encoding + .byte 128-32 ; Tiles required + + .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; All map to space + .byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + .byte 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 ; 0x20 + .byte 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 + .byte 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47 ; 0x40 + .byte 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63 + .byte 64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79 ; 0x60 + .byte 80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95 + + .db 0 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 +; Character: ! + .db 0b00000000 + .db 0b00010000 + .db 0b00010000 + .db 0b00010000 + .db 0b00010000 + .db 0b00000000 + .db 0b00010000 + .db 0b00000000 +; Character: " + .db 0b00000000 + .db 0b00100100 + .db 0b00100100 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 +; Character: # + .db 0b00000000 + .db 0b00100100 + .db 0b01111110 + .db 0b00100100 + .db 0b00100100 + .db 0b01111110 + .db 0b00100100 + .db 0b00000000 +; Character: $ + .db 0b00000000 + .db 0b00001000 + .db 0b00111110 + .db 0b00101000 + .db 0b00111110 + .db 0b00001010 + .db 0b00111110 + .db 0b00001000 +; Character: % + .db 0b00000000 + .db 0b01100010 + .db 0b01100100 + .db 0b00001000 + .db 0b00010000 + .db 0b00100110 + .db 0b01000110 + .db 0b00000000 +; Character: & + .db 0b00000000 + .db 0b00010000 + .db 0b00101000 + .db 0b00010000 + .db 0b00101010 + .db 0b01000100 + .db 0b00111010 + .db 0b00000000 +; Character: ' + .db 0b00000000 + .db 0b00001000 + .db 0b00010000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 +; Character: ( + .db 0b00000000 + .db 0b00000100 + .db 0b00001000 + .db 0b00001000 + .db 0b00001000 + .db 0b00001000 + .db 0b00000100 + .db 0b00000000 +; Character: ) + .db 0b00000000 + .db 0b00100000 + .db 0b00010000 + .db 0b00010000 + .db 0b00010000 + .db 0b00010000 + .db 0b00100000 + .db 0b00000000 +; Character: * + .db 0b00000000 + .db 0b00000000 + .db 0b00010100 + .db 0b00001000 + .db 0b00111110 + .db 0b00001000 + .db 0b00010100 + .db 0b00000000 +; Character: + + .db 0b00000000 + .db 0b00000000 + .db 0b00001000 + .db 0b00001000 + .db 0b00111110 + .db 0b00001000 + .db 0b00001000 + .db 0b00000000 +; Character: , + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00001000 + .db 0b00001000 + .db 0b00010000 +; Character: - + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00111110 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 +; Character: . + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00011000 + .db 0b00011000 + .db 0b00000000 +; Character: / + .db 0b00000000 + .db 0b00000000 + .db 0b00000010 + .db 0b00000100 + .db 0b00001000 + .db 0b00010000 + .db 0b00100000 + .db 0b00000000 +; Character: 0 + .db 0b00000000 + .db 0b00111100 + .db 0b01000110 + .db 0b01001010 + .db 0b01010010 + .db 0b01100010 + .db 0b00111100 + .db 0b00000000 +; Character: 1 + .db 0b00000000 + .db 0b00011000 + .db 0b00101000 + .db 0b00001000 + .db 0b00001000 + .db 0b00001000 + .db 0b00111110 + .db 0b00000000 +; Character: 2 + .db 0b00000000 + .db 0b00111100 + .db 0b01000010 + .db 0b00000010 + .db 0b00111100 + .db 0b01000000 + .db 0b01111110 + .db 0b00000000 +; Character: 3 + .db 0b00000000 + .db 0b00111100 + .db 0b01000010 + .db 0b00001100 + .db 0b00000010 + .db 0b01000010 + .db 0b00111100 + .db 0b00000000 +; Character: 4 + .db 0b00000000 + .db 0b00001000 + .db 0b00011000 + .db 0b00101000 + .db 0b01001000 + .db 0b01111110 + .db 0b00001000 + .db 0b00000000 +; Character: 5 + .db 0b00000000 + .db 0b01111110 + .db 0b01000000 + .db 0b01111100 + .db 0b00000010 + .db 0b01000010 + .db 0b00111100 + .db 0b00000000 +; Character: 6 + .db 0b00000000 + .db 0b00111100 + .db 0b01000000 + .db 0b01111100 + .db 0b01000010 + .db 0b01000010 + .db 0b00111100 + .db 0b00000000 +; Character: 7 + .db 0b00000000 + .db 0b01111110 + .db 0b00000010 + .db 0b00000100 + .db 0b00001000 + .db 0b00010000 + .db 0b00010000 + .db 0b00000000 +; Character: 8 + .db 0b00000000 + .db 0b00111100 + .db 0b01000010 + .db 0b00111100 + .db 0b01000010 + .db 0b01000010 + .db 0b00111100 + .db 0b00000000 +; Character: 9 + .db 0b00000000 + .db 0b00111100 + .db 0b01000010 + .db 0b01000010 + .db 0b00111110 + .db 0b00000010 + .db 0b00111100 + .db 0b00000000 +; Character: : + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00010000 + .db 0b00000000 + .db 0b00000000 + .db 0b00010000 + .db 0b00000000 +; Character: ; + .db 0b00000000 + .db 0b00000000 + .db 0b00010000 + .db 0b00000000 + .db 0b00000000 + .db 0b00010000 + .db 0b00010000 + .db 0b00100000 +; Character: < + .db 0b00000000 + .db 0b00000000 + .db 0b00000100 + .db 0b00001000 + .db 0b00010000 + .db 0b00001000 + .db 0b00000100 + .db 0b00000000 +; Character: = + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00111110 + .db 0b00000000 + .db 0b00111110 + .db 0b00000000 + .db 0b00000000 +; Character: > + .db 0b00000000 + .db 0b00000000 + .db 0b00010000 + .db 0b00001000 + .db 0b00000100 + .db 0b00001000 + .db 0b00010000 + .db 0b00000000 +; Character: ? + .db 0b00000000 + .db 0b00111100 + .db 0b01000010 + .db 0b00000100 + .db 0b00001000 + .db 0b00000000 + .db 0b00001000 + .db 0b00000000 +; Character: @ + .db 0b00000000 + .db 0b00111100 + .db 0b01001010 + .db 0b01010110 + .db 0b01011110 + .db 0b01000000 + .db 0b00111100 + .db 0b00000000 +; Character: A + .db 0b00000000 + .db 0b00111100 + .db 0b01000010 + .db 0b01000010 + .db 0b01111110 + .db 0b01000010 + .db 0b01000010 + .db 0b00000000 +; Character: B + .db 0b00000000 + .db 0b01111100 + .db 0b01000010 + .db 0b01111100 + .db 0b01000010 + .db 0b01000010 + .db 0b01111100 + .db 0b00000000 +; Character: C + .db 0b00000000 + .db 0b00111100 + .db 0b01000010 + .db 0b01000000 + .db 0b01000000 + .db 0b01000010 + .db 0b00111100 + .db 0b00000000 +; Character: D + .db 0b00000000 + .db 0b01111000 + .db 0b01000100 + .db 0b01000010 + .db 0b01000010 + .db 0b01000100 + .db 0b01111000 + .db 0b00000000 +; Character: E + .db 0b00000000 + .db 0b01111110 + .db 0b01000000 + .db 0b01111100 + .db 0b01000000 + .db 0b01000000 + .db 0b01111110 + .db 0b00000000 +; Character: F + .db 0b00000000 + .db 0b01111110 + .db 0b01000000 + .db 0b01111100 + .db 0b01000000 + .db 0b01000000 + .db 0b01000000 + .db 0b00000000 +; Character: G + .db 0b00000000 + .db 0b00111100 + .db 0b01000010 + .db 0b01000000 + .db 0b01001110 + .db 0b01000010 + .db 0b00111100 + .db 0b00000000 +; Character: H + .db 0b00000000 + .db 0b01000010 + .db 0b01000010 + .db 0b01111110 + .db 0b01000010 + .db 0b01000010 + .db 0b01000010 + .db 0b00000000 +; Character: I + .db 0b00000000 + .db 0b00111110 + .db 0b00001000 + .db 0b00001000 + .db 0b00001000 + .db 0b00001000 + .db 0b00111110 + .db 0b00000000 +; Character: J + .db 0b00000000 + .db 0b00000010 + .db 0b00000010 + .db 0b00000010 + .db 0b01000010 + .db 0b01000010 + .db 0b00111100 + .db 0b00000000 +; Character: K + .db 0b00000000 + .db 0b01000100 + .db 0b01001000 + .db 0b01110000 + .db 0b01001000 + .db 0b01000100 + .db 0b01000010 + .db 0b00000000 +; Character: L + .db 0b00000000 + .db 0b01000000 + .db 0b01000000 + .db 0b01000000 + .db 0b01000000 + .db 0b01000000 + .db 0b01111110 + .db 0b00000000 +; Character: M + .db 0b00000000 + .db 0b01000010 + .db 0b01100110 + .db 0b01011010 + .db 0b01000010 + .db 0b01000010 + .db 0b01000010 + .db 0b00000000 +; Character: N + .db 0b00000000 + .db 0b01000010 + .db 0b01100010 + .db 0b01010010 + .db 0b01001010 + .db 0b01000110 + .db 0b01000010 + .db 0b00000000 +; Character: O + .db 0b00000000 + .db 0b00111100 + .db 0b01000010 + .db 0b01000010 + .db 0b01000010 + .db 0b01000010 + .db 0b00111100 + .db 0b00000000 +; Character: P + .db 0b00000000 + .db 0b01111100 + .db 0b01000010 + .db 0b01000010 + .db 0b01111100 + .db 0b01000000 + .db 0b01000000 + .db 0b00000000 +; Character: Q + .db 0b00000000 + .db 0b00111100 + .db 0b01000010 + .db 0b01000010 + .db 0b01010010 + .db 0b01001010 + .db 0b00111100 + .db 0b00000000 +; Character: R + .db 0b00000000 + .db 0b01111100 + .db 0b01000010 + .db 0b01000010 + .db 0b01111100 + .db 0b01000100 + .db 0b01000010 + .db 0b00000000 +; Character: S + .db 0b00000000 + .db 0b00111100 + .db 0b01000000 + .db 0b00111100 + .db 0b00000010 + .db 0b01000010 + .db 0b00111100 + .db 0b00000000 +; Character: T + .db 0b00000000 + .db 0b11111110 + .db 0b00010000 + .db 0b00010000 + .db 0b00010000 + .db 0b00010000 + .db 0b00010000 + .db 0b00000000 +; Character: U + .db 0b00000000 + .db 0b01000010 + .db 0b01000010 + .db 0b01000010 + .db 0b01000010 + .db 0b01000010 + .db 0b00111100 + .db 0b00000000 +; Character: V + .db 0b00000000 + .db 0b01000010 + .db 0b01000010 + .db 0b01000010 + .db 0b01000010 + .db 0b00100100 + .db 0b00011000 + .db 0b00000000 +; Character: W + .db 0b00000000 + .db 0b01000010 + .db 0b01000010 + .db 0b01000010 + .db 0b01000010 + .db 0b01011010 + .db 0b00100100 + .db 0b00000000 +; Character: X + .db 0b00000000 + .db 0b01000010 + .db 0b00100100 + .db 0b00011000 + .db 0b00011000 + .db 0b00100100 + .db 0b01000010 + .db 0b00000000 +; Character: Y + .db 0b00000000 + .db 0b10000010 + .db 0b01000100 + .db 0b00101000 + .db 0b00010000 + .db 0b00010000 + .db 0b00010000 + .db 0b00000000 +; Character: Z + .db 0b00000000 + .db 0b01111110 + .db 0b00000100 + .db 0b00001000 + .db 0b00010000 + .db 0b00100000 + .db 0b01111110 + .db 0b00000000 +; Character: [ + .db 0b00000000 + .db 0b00001110 + .db 0b00001000 + .db 0b00001000 + .db 0b00001000 + .db 0b00001000 + .db 0b00001110 + .db 0b00000000 +; Character: \ + .db 0b00000000 + .db 0b00000000 + .db 0b01000000 + .db 0b00100000 + .db 0b00010000 + .db 0b00001000 + .db 0b00000100 + .db 0b00000000 +; Character: ] + .db 0b00000000 + .db 0b01110000 + .db 0b00010000 + .db 0b00010000 + .db 0b00010000 + .db 0b00010000 + .db 0b01110000 + .db 0b00000000 +; Character: ^ + .db 0b00000000 + .db 0b00010000 + .db 0b00111000 + .db 0b01010100 + .db 0b00010000 + .db 0b00010000 + .db 0b00010000 + .db 0b00000000 +; Character: _ + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b11111111 +; Character: Pound + .db 0b00000000 + .db 0b00011100 + .db 0b00100010 + .db 0b01111000 + .db 0b00100000 + .db 0b00100000 + .db 0b01111110 + .db 0b00000000 +; Character: a + .db 0b00000000 + .db 0b00000000 + .db 0b00111000 + .db 0b00000100 + .db 0b00111100 + .db 0b01000100 + .db 0b00111100 + .db 0b00000000 +; Character: b + .db 0b00000000 + .db 0b00100000 + .db 0b00100000 + .db 0b00111100 + .db 0b00100010 + .db 0b00100010 + .db 0b00111100 + .db 0b00000000 +; Character: c + .db 0b00000000 + .db 0b00000000 + .db 0b00011100 + .db 0b00100000 + .db 0b00100000 + .db 0b00100000 + .db 0b00011100 + .db 0b00000000 +; Character: d + .db 0b00000000 + .db 0b00000100 + .db 0b00000100 + .db 0b00111100 + .db 0b01000100 + .db 0b01000100 + .db 0b00111100 + .db 0b00000000 +; Character: e + .db 0b00000000 + .db 0b00000000 + .db 0b00111000 + .db 0b01000100 + .db 0b01111000 + .db 0b01000000 + .db 0b00111100 + .db 0b00000000 +; Character: f + .db 0b00000000 + .db 0b00001100 + .db 0b00010000 + .db 0b00011000 + .db 0b00010000 + .db 0b00010000 + .db 0b00010000 + .db 0b00000000 +; Character: g + .db 0b00000000 + .db 0b00000000 + .db 0b00111100 + .db 0b01000100 + .db 0b01000100 + .db 0b00111100 + .db 0b00000100 + .db 0b00111000 +; Character: h + .db 0b00000000 + .db 0b01000000 + .db 0b01000000 + .db 0b01111000 + .db 0b01000100 + .db 0b01000100 + .db 0b01000100 + .db 0b00000000 +; Character: i + .db 0b00000000 + .db 0b00010000 + .db 0b00000000 + .db 0b00110000 + .db 0b00010000 + .db 0b00010000 + .db 0b00111000 + .db 0b00000000 +; Character: j + .db 0b00000000 + .db 0b00000100 + .db 0b00000000 + .db 0b00000100 + .db 0b00000100 + .db 0b00000100 + .db 0b00100100 + .db 0b00011000 +; Character: k + .db 0b00000000 + .db 0b00100000 + .db 0b00101000 + .db 0b00110000 + .db 0b00110000 + .db 0b00101000 + .db 0b00100100 + .db 0b00000000 +; Character: l + .db 0b00000000 + .db 0b00010000 + .db 0b00010000 + .db 0b00010000 + .db 0b00010000 + .db 0b00010000 + .db 0b00001100 + .db 0b00000000 +; Character: m + .db 0b00000000 + .db 0b00000000 + .db 0b01101000 + .db 0b01010100 + .db 0b01010100 + .db 0b01010100 + .db 0b01010100 + .db 0b00000000 +; Character: n + .db 0b00000000 + .db 0b00000000 + .db 0b01111000 + .db 0b01000100 + .db 0b01000100 + .db 0b01000100 + .db 0b01000100 + .db 0b00000000 +; Character: o + .db 0b00000000 + .db 0b00000000 + .db 0b00111000 + .db 0b01000100 + .db 0b01000100 + .db 0b01000100 + .db 0b00111000 + .db 0b00000000 +; Character: p + .db 0b00000000 + .db 0b00000000 + .db 0b01111000 + .db 0b01000100 + .db 0b01000100 + .db 0b01111000 + .db 0b01000000 + .db 0b01000000 +; Character: q + .db 0b00000000 + .db 0b00000000 + .db 0b00111100 + .db 0b01000100 + .db 0b01000100 + .db 0b00111100 + .db 0b00000100 + .db 0b00000110 +; Character: r + .db 0b00000000 + .db 0b00000000 + .db 0b00011100 + .db 0b00100000 + .db 0b00100000 + .db 0b00100000 + .db 0b00100000 + .db 0b00000000 +; Character: s + .db 0b00000000 + .db 0b00000000 + .db 0b00111000 + .db 0b01000000 + .db 0b00111000 + .db 0b00000100 + .db 0b01111000 + .db 0b00000000 +; Character: t + .db 0b00000000 + .db 0b00010000 + .db 0b00111000 + .db 0b00010000 + .db 0b00010000 + .db 0b00010000 + .db 0b00001100 + .db 0b00000000 +; Character: u + .db 0b00000000 + .db 0b00000000 + .db 0b01000100 + .db 0b01000100 + .db 0b01000100 + .db 0b01000100 + .db 0b00111000 + .db 0b00000000 +; Character: v + .db 0b00000000 + .db 0b00000000 + .db 0b01000100 + .db 0b01000100 + .db 0b00101000 + .db 0b00101000 + .db 0b00010000 + .db 0b00000000 +; Character: w + .db 0b00000000 + .db 0b00000000 + .db 0b01000100 + .db 0b01010100 + .db 0b01010100 + .db 0b01010100 + .db 0b00101000 + .db 0b00000000 +; Character: x + .db 0b00000000 + .db 0b00000000 + .db 0b01000100 + .db 0b00101000 + .db 0b00010000 + .db 0b00101000 + .db 0b01000100 + .db 0b00000000 +; Character: y + .db 0b00000000 + .db 0b00000000 + .db 0b01000100 + .db 0b01000100 + .db 0b01000100 + .db 0b00111100 + .db 0b00000100 + .db 0b00111000 +; Character: z + .db 0b00000000 + .db 0b00000000 + .db 0b01111100 + .db 0b00001000 + .db 0b00010000 + .db 0b00100000 + .db 0b01111100 + .db 0b00000000 +; Character: { + .db 0b00000000 + .db 0b00001110 + .db 0b00001000 + .db 0b00110000 + .db 0b00001000 + .db 0b00001000 + .db 0b00001110 + .db 0b00000000 +; Character: | + .db 0b00000000 + .db 0b00001000 + .db 0b00001000 + .db 0b00001000 + .db 0b00001000 + .db 0b00001000 + .db 0b00001000 + .db 0b00000000 +; Character: } + .db 0b00000000 + .db 0b01110000 + .db 0b00010000 + .db 0b00001100 + .db 0b00010000 + .db 0b00010000 + .db 0b01110000 + .db 0b00000000 +; Character: ~ + .db 0b00000000 + .db 0b00010100 + .db 0b00101000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 + .db 0b00000000 +; Character: Copyright + .db 0b00111100 + .db 0b01000010 + .db 0b10011001 + .db 0b10100001 + .db 0b10100001 + .db 0b10011001 + .db 0b01000010 + .db 0b00111100 diff --git a/gbdk/gbdk-lib/libc/targets/z80/far_ptr.s b/gbdk/gbdk-lib/libc/targets/z80/far_ptr.s new file mode 100644 index 00000000..de908303 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/far_ptr.s @@ -0,0 +1,64 @@ +;-------------------------------------------------------------------------- +; far_ptr.s +; +; Copyright (C) 2020, Tony Pavlov +; +; This library is free software; you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by the +; Free Software Foundation; either version 2, or (at your option) any +; later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this library; see the file COPYING. If not, write to the +; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, +; MA 02110-1301, USA. +; +; As a special exception, if you link this library with other files, +; some of which are compiled with SDCC, to produce an executable, +; this library does not by itself cause the resulting executable to +; be covered by the GNU General Public License. This exception does +; not however invalidate any other reasons why the executable file +; might be covered by the GNU General Public License. +;-------------------------------------------------------------------------- + + .module far_ptr + + .include "global.s" + + .area _HOME + +___call__banked:: + + ld a, (#.MAP_FRAME1) + push af + inc sp + ld a, (___call_banked_bank) + ld (#.MAP_FRAME1), a + ld hl, (___call_banked_addr) + CALL_HL + dec sp + pop af + ld (#.MAP_FRAME1), a + ret + +_to_far_ptr:: + pop bc + pop hl + pop de + push de + push hl + push bc + ret + + .area _DATA + +___call_banked_ptr:: +___call_banked_addr:: + .ds 0x02 ; far pointer offset +___call_banked_bank:: + .ds 0x02 ; far pointer segment diff --git a/gbdk/gbdk-lib/libc/targets/z80/font.s b/gbdk/gbdk-lib/libc/targets/z80/font.s new file mode 100644 index 00000000..76169b97 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/font.s @@ -0,0 +1,170 @@ + .include "global.s" + + .title "Font utilities" + .module FontUtils + + .globl .memset_small + .globl _font_ibm + .globl __current_1bpp_colors, .fg_colour, .bg_colour + .globl _set_native_tile_data, _set_tile_1bpp_data + + ; Structure offsets + sfont_handle_sizeof = 3 + sfont_handle_font = 1 + sfont_handle_first_tile = 0 + + ; Encoding types - lower 2 bits of font + FONT_256ENCODING = 0 + FONT_128ENCODING = 1 + FONT_NOENCODING = 2 + + ; Other bits + FONT_BCOMPRESSED = 2 + + ; Maximum number of fonts + .MAX_FONTS = 6 + + .area _DATA + ; The current font +font_current:: + .ds sfont_handle_sizeof + ; Cached copy of the first free tile +font_first_free_tile: + .ds 1 + ; Table containing descriptors for all of the fonts +font_table: + .ds (sfont_handle_sizeof*.MAX_FONTS) + + .area _HOME + +; void vmemcpy (unsigned int dst, const void *src, unsigned int size) __z88dk_callee __preserves_regs(iyh,iyl); +_font_init:: + xor a + ld (font_first_free_tile), a + + ld hl, #font_table + ld c, #(sfont_handle_sizeof*.MAX_FONTS) + call .memset_small + + ret + +_font_set:: + pop de + pop hl + push hl + push de + +font_set:: + ld de, #font_current + ld bc, #sfont_handle_sizeof + ldir + ret + +_font_color:: + pop de + ex (sp), hl + push de + ld (__current_1bpp_colors), hl + ret + +font_load_ibm:: + ld hl, #_font_ibm + jp font_load + +_font_load:: + pop de + pop hl + push hl + push de + + ;; load font in HL to free slor +font_load:: + push hl + ; find free slot + ld b, #.MAX_FONTS + ld hl, #(font_table+sfont_handle_font) +1$: + ld a, (hl) + inc hl + or (hl) + jr z, 2$ ; found + inc hl + inc hl + dec b + jr nz, 1$ + + ld hl, #0 ; no free slot + ret +2$: + ; fill free slot with passed pointer + pop de + ld (hl), d + dec hl + ld (hl), e + ld a, (font_first_free_tile) + dec hl + ld (hl),a + + push hl + call font_set + + call load_font_tiles + + ld hl, (font_current+sfont_handle_font) + + inc hl ; Number of tiles used + ld a, (font_first_free_tile) + add (hl) + ld (font_first_free_tile), a + + pop hl ; return handle in hl + ret + +load_font_tiles: + ld hl, (font_current+sfont_handle_font) + + inc hl + ld e, (hl) + ld d, #0 + + dec hl + ld a, (hl) ; a = flags + push af + and #3 + + ld bc, #128 + cp #FONT_128ENCODING ; 0 for 256 char encoding table, 1 for 128 char + jr z, 1$ + + ld bc, #0 + cp #FONT_NOENCODING + jr z, 1$ + + ld bc, #256 ; Must be 256 element encoding +1$: + inc hl + inc hl ; Points to the start of the encoding table + add hl, bc + + ld a,(font_current+sfont_handle_first_tile) + ld c, a + ld b, #0 + + pop af ; Recover flags + bit FONT_BCOMPRESSED, a ; Is this font compressed? + jp z, 2$ + + push hl + ld hl, (__current_1bpp_colors) + ex (sp), hl + push hl + push de + push bc + call _set_tile_1bpp_data + ret +2$: + push hl + push de + push bc + call _set_native_tile_data + ret diff --git a/gbdk/gbdk-lib/libc/targets/z80/gb_decompress.s b/gbdk/gbdk-lib/libc/targets/z80/gb_decompress.s new file mode 100644 index 00000000..00c9c947 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/gb_decompress.s @@ -0,0 +1,90 @@ +; GB-Deompress routine +; Compatible with GBTD + + .include "global.s" + + .title "GB Decompress" + .module GBDecompress + + .area _CODE + +; hl = source; de = dest +_gb_decompress:: + pop hl + pop de + ex (sp), hl + ex de, hl + push bc + push de +1$: + ld a, (hl) ; load command + inc hl + or a + jr z, 9$ ; exit, if last byte + bit 7, a + jr nz, 5$ ; string functions + bit 6, a + jr nz, 3$ + ; RLE byte + and #63 ; calc counter + inc a + ld b, a + ld a, (hl) + inc hl +2$: + ld (de), a + inc de + dec b + jr nz, 2$ + jr 1$ ; next command +3$: ; RLE word + and #63 + inc a + ld c, (hl) ; load word into bc + inc hl + ld b, (hl) + inc hl + ex de, hl +4$: + ld (hl), c + inc hl + ld (hl), b + inc hl + dec a + jr nz, 4$ + ex de, hl + jr 1$ ; next command +5$: + bit 6, a + jr nz, 7$ + ; string repeat + and #63 + inc a + push hl + ld c, (hl) + inc hl + ld b, (hl) + ld h, d + ld l, e + add hl, bc + ld c, a + ld b, #0 + ldir + pop hl + inc hl + inc hl + jr 1$ ; next command +7$: ; string copy + and #63 + inc a + ld c, a + ld b, #0 + ldir + jr 1$ ; next command +9$: + pop hl + ex de, hl + or a ; clear carry flag + sbc hl, de + pop bc + ret diff --git a/gbdk/gbdk-lib/libc/targets/z80/gg/Makefile b/gbdk/gbdk-lib/libc/targets/z80/gg/Makefile new file mode 100644 index 00000000..63ec01d7 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/gg/Makefile @@ -0,0 +1,44 @@ +# GB specific Makefile + +TOPDIR = ../../../.. + +THIS = gg +PORT = z80 + +CSRC = crlf.c + +ASSRC = set_interrupts.s \ + outi.s vmemcpy.s \ + sms_refresh_oam.s \ + sms_set_native_data.s sms_set_1bpp_data.s sms_set_2bpp_data.s \ + set_tile_map.s set_tile_map_xy.s set_tile_map_compat.s set_tile_map_xy_compat.s \ + set_tile_submap.s set_tile_submap_compat.s \ + coords_to_address.s \ + set_tile.s \ + sms_fill_rect.s sms_fill_rect_xy.s sms_fill_rect_compat.s sms_fill_rect_xy_compat.s \ + sms_metasprites.s sms_metasprites_hide.s sms_metasprites_hide_spr.s \ + f_ibm_full.s f_ibm_sh.s f_italic.s f_min.s f_spect.s \ + font.s color.s \ + putchar.s \ + scroll.s cls.s gotoxy.s \ + palette.s set_palette.s \ + pad.s pad_ex.s \ + sms_int.s nmi.s \ + mode.s clock.s \ + delay.s \ + emu_debug_printf.s \ + memset_small.s \ + far_ptr.s \ + gb_decompress.s \ + rle_decompress.s \ + heap.s \ + __sdcc_bcall.s \ + crt0.s + +CRT0 = crt0.s + +include $(TOPDIR)/Makefile.common + +AS = $(AS_Z80) + +include ../../../Makefile.platform diff --git a/gbdk/gbdk-lib/libc/targets/z80/gg/__sdcc_bcall.s b/gbdk/gbdk-lib/libc/targets/z80/gg/__sdcc_bcall.s new file mode 100644 index 00000000..60ebd504 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/gg/__sdcc_bcall.s @@ -0,0 +1,68 @@ + .include "global.s" + + .area _CODE + + .globl ___sdcc_bcall + .globl ___sdcc_bcall_abc + .globl ___sdcc_bcall_ehl +; +; trampoline to call banked functions +; used when legacy banking is enabled only +; Usage: +; call ___sdcc_bcall +; .dw <function> +; .dw <function_bank> +; +___sdcc_bcall:: + ex (sp), hl + ld c, (hl) + inc hl + ld b, (hl) + inc hl + ld a, (hl) + inc hl + inc hl + ex (sp), hl +; +; trampoline to call banked functions with __z88dk_fastcall calling convention +; Usage: +; ld a, #<function_bank> +; ld bc, #<function> +; call ___sdcc_bcall_abc +; +___sdcc_bcall_abc:: + push hl + ld l, a + ld a, (#.MAP_FRAME1) + ld h, a + ld a, l + ld (#.MAP_FRAME1), a + ex (sp), hl + inc sp + call ___sdcc_bjump_abc + dec sp + pop af + ld (#.MAP_FRAME1), a + ret +; +___sdcc_bjump_abc: + push bc + ret +; +; default trampoline to call banked functions +; Usage: +; ld e, #<function_bank> +; ld hl, #<function> +; call ___sdcc_bcall_ehl +; +___sdcc_bcall_ehl:: + ld a, (#.MAP_FRAME1) + push af + inc sp + ld a, e + ld (#.MAP_FRAME1), a + CALL_HL + dec sp + pop af + ld (#.MAP_FRAME1), a + ret diff --git a/gbdk/gbdk-lib/libc/targets/z80/gg/crlf.c b/gbdk/gbdk-lib/libc/targets/z80/gg/crlf.c new file mode 100644 index 00000000..aca6ec82 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/gg/crlf.c @@ -0,0 +1 @@ +const char * const __crlf = "\n";
\ No newline at end of file diff --git a/gbdk/gbdk-lib/libc/targets/z80/gg/crt0.s b/gbdk/gbdk-lib/libc/targets/z80/gg/crt0.s new file mode 100644 index 00000000..656cbe7e --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/gg/crt0.s @@ -0,0 +1,268 @@ + .include "global.s" + + .title "Runtime" + .module Runtime + .area _HEADER (ABS) + + .globl _set_default_palette + + .org 0x00 ; Reset 00h + di ; disable interrupt + im 1 ; interrupt mode 1 (this won't change) + jp .init + +; .org 0x08 ; --profile handler + + .org 0x10 ; RST 0x10: VDP_WRITE_CMD + +_WRITE_VDP_CMD:: + VDP_WRITE_CMD h, l + ret + +; .org 0x18 ; unusable + + .org 0x20 ; RST 0x20: VDP_WRITE_DATA + +_WRITE_VDP_DATA:: + VDP_WRITE_DATA h, l + ret + +; .org 0x28 ; unusable + + .org 0x30 ; RST 0x30: call HL +.call_hl:: + jp (HL) + + .org 0x38 ; handle IRQ + jp _INT_ISR + + .org 0x66 ; handle NMI + jp _NMI_ISR + + .org 0x80 + +.init:: + ld sp, #.STACK ; set stack pointer at end of RAM + + ld a, (#.BIOS) + push af + + xor a + ld bc, #l__DATA + ld hl, #s__DATA + call .memset_simple ; initialize veriables in RAM with zero + + pop af + ld (#__BIOS), a ; save BIOS value + + ld hl, #_shadow_OAM + ld de, #(_shadow_OAM + 1) + ld bc, #64 + ld (hl), #0xc0 + ldir + ld (hl), #0 + ld bc, #(128 - 1) + ldir + + ld hl,#0x0000 ; initialize mappers + ld (#.RAM_CONTROL),hl ; [.RAM_CONTROL]=$00, [.MAP_FRAME0]=$00 + ld hl,#0x0201 + ld (#.MAP_FRAME1),hl ; [.MAP_FRAME1]=$01, [.MAP_FRAME2]=$02 + + ;; Initialise global variables + call .gsinit + + ;; Initialize VDP + ld c, #.VDP_CMD + ld b, #(.shadow_VDP_end - .shadow_VDP) + ld hl,#(.shadow_VDP_end - 1) +1$: + outd + + ld a, b + or #.VDP_REG_MASK + out (c), a + + ld a, b + or a + jr nz, 1$ + + ;; detect PAL/NTSC + in a, (.GG_STATE) + and #.GGSTATE_NNTS + jr nz, 2$ + ld a, #.SYSTEM_NTSC + jr 3$ +2$: + ld a, #.SYSTEM_PAL +3$: + ld (#__SYSTEM), a + + call .clear_VRAM + + call _set_default_palette + + VDP_CANCEL_INT + + ei ; re-enable interrupts before going to main() + call _main +10$: + halt + jr 10$ + + ;; Ordering of segments for the linker. + .area _HOME + .area _BASE + .area _CODE + .area _CODE_0 + .area _LIT + .area _INITIALIZER + .area _GSINIT + .area _GSFINAL + + .area _DATA + .area _INITIALIZED + .area _BSEG + .area _BSS + .area _HEAP + .area _HEAP_END + + .area _CODE + .area _GSINIT +.gsinit:: + ;; initialize static storage variables + ld bc, #l__INITIALIZER + ld hl, #s__INITIALIZER + ld de, #s__INITIALIZED + call .memcpy_simple + + .area _GSFINAL + ret + + .area _HOME + +.clear_VRAM: + ld a, #<.VDP_VRAM + out (#.VDP_CMD), a + ld a, #>.VDP_VRAM + out (#.VDP_CMD), a + xor a + ld bc, #0x4101 + jr 6$ +5$: + out (.VDP_DATA), a +6$: + dec c + jr nz, 5$ + dec b + jr nz, 5$ + ret + + ;; fills memory at HL of length BC with A, clobbers DE +.memset_simple:: + ld e, a + ld a, c + or b + ret z + ld (hl), e + dec bc + ld d, h + ld e, l + inc de + + ;; copies BC bytes from HL into DE +.memcpy_simple:: + ld a, c + or b + ret z + ldir + ret + + ;; Wait for VBL interrupt to be finished +.wait_vbl_done:: +_wait_vbl_done:: + ld a, (_shadow_VDP_R1) + and #.R1_DISP_ON + ret z + + xor a + ld (.vbl_done), a +1$: + halt + ld a, (.vbl_done) + or a + jr z, 1$ + ret + + .area _DATA + +.start_crt_globals: +__BIOS:: + .ds 0x01 ; GB type (GB, PGB, CGB) +__SYSTEM:: + .ds 0x01 ; PAL/NTSC +.end_crt_globals: + + .area _INITIALIZED +.shadow_VDP: +_shadow_VDP_R0:: + .ds 0x01 +_shadow_VDP_R1:: + .ds 0x01 +_shadow_VDP_R2:: + .ds 0x01 +_shadow_VDP_R3:: + .ds 0x01 +_shadow_VDP_R4:: + .ds 0x01 +_shadow_VDP_R5:: + .ds 0x01 +_shadow_VDP_R6:: + .ds 0x01 +_shadow_VDP_R7:: +_shadow_VDP_RBORDER:: + .ds 0x01 +_shadow_VDP_R8:: +_shadow_VDP_RSCX:: + .ds 0x01 +_shadow_VDP_R9:: +_shadow_VDP_RSCY:: + .ds 0x01 +_shadow_VDP_R10:: + .ds 0x01 +.shadow_VDP_end:: + +.sys_time:: +_sys_time:: + .ds 0x02 +.vbl_done:: + .ds 0x01 +_VDP_ATTR_SHIFT:: +.vdp_shift:: + .ds 0x01 +__shadow_OAM_base:: + .ds 0x01 +__shadow_OAM_OFF:: + .ds 0x01 +.mode:: + .ds 0x01 ; Current mode + + .area _INITIALIZER + + .db .R0_DEFAULT + .db #(.R1_DEFAULT | .R1_DISP_ON | .R1_IE) ; VBLANK + .db .R2_MAP_0x3800 + .db 0xFF + .db 0xFF + .db .R5_SAT_0x3F00 + .db .R6_DATA_0x2000 + .db #(0 | .R7_COLOR_MASK) + .db 0 ; SCX + .db 0 ; SCY + .db .R10_INT_OFF + .dw 0x0000 ; .sys_time + .db 0 ; .vbl_done + .db 0 ; _VDP_ATTR_SHIFT + .db #>_shadow_OAM ; __shadow_OAM_base + .db 0 ; __shadow_OAM_OFF + .db .T_MODE_INOUT ; .mode
\ No newline at end of file diff --git a/gbdk/gbdk-lib/libc/targets/z80/gg/global.s b/gbdk/gbdk-lib/libc/targets/z80/gg/global.s new file mode 100644 index 00000000..3d618b47 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/gg/global.s @@ -0,0 +1,345 @@ + .GG_STATE = 0x00 + + .GGSTATE_STT = 0b10000000 + .GGSTATE_NJAP = 0b01000000 + .GGSTATE_NNTS = 0b00100000 + + .GG_EXT_7BIT = 0x01 + + .GG_EXT_CTL = 0x02 + + .GGEXT_NINIT = 0b10000000 + + .GG_SIO_SEND = 0x03 + .GG_SIO_RECV = 0x04 + .GG_SIO_CTL = 0x05 + + .SIOCTL_TXFL = 0b00000001 + .SIOCTL_RXRD = 0b00000010 + .SIOCTL_FRER = 0b00000100 + .SIOCTL_INT = 0b00001000 + .SIOCTL_TON = 0b00010000 + .SIOCTL_RON = 0b00100000 + .SIOCTL_BS0 = 0b01000000 + .SIOCTL_BS1 = 0b10000000 + + .GG_SOUND_PAN = 0x06 + + .SOUNDPAN_TN1R = 0b00000001 + .SOUNDPAN_TN2R = 0b00000010 + .SOUNDPAN_TN3R = 0b00000100 + .SOUNDPAN_NOSR = 0b00001000 + .SOUNDPAN_TN1L = 0b00010000 + .SOUNDPAN_TN2L = 0b00100000 + .SOUNDPAN_TN3L = 0b01000000 + .SOUNDPAN_NOSL = 0b10000000 + + .MEMORY_CTL = 0x3E + + .MEMCTL_JOYON = 0b00000000 + .MEMCTL_JOYOFF = 0b00000100 + .MEMCTL_BASEON = 0b00000000 + .MEMCTL_BASEOFF = 0b00001000 + .MEMCTL_RAMON = 0b00000000 + .MEMCTL_RAMOFF = 0b00010000 + .MEMCTL_CROMON = 0b00000000 + .MEMCTL_CROMOFF = 0b00100000 + .MEMCTL_ROMON = 0b00000000 + .MEMCTL_ROMOFF = 0b01000000 + .MEMCTL_EXTON = 0b00000000 + .MEMCTL_EXTOFF = 0b10000000 + + .JOY_CTL = 0x3F + + .JOY_P1_LATCH = 0b00000010 + .JOY_P2_LATCH = 0b00001000 + + .VDP_VRAM = 0x4000 + .VDP_TILEMAP = 0x7800 + .VDP_CRAM = 0xC000 + .VDP_SAT = 0x7F00 + + .VDP_SAT_TERM = 0xD0 + + .VDP_VCOUNTER = 0x7E + .VDP_PSG = 0x7F + .VDP_HCOUNTER = 0x7F + + .VDP_DATA = 0xBE + .VDP_CMD = 0xBF + .VDP_STAT = 0xBF + + .STATF_INT_VBL = 0b10000000 + .STATF_9_SPR = 0b01000000 + .STATF_SPR_COLL = 0b00100000 + + .VDP_REG_MASK = 0b10000000 + .VDP_R0 = 0b10000000 + + .R0_VSCRL = 0b00000000 + .R0_VSCRL_INH = 0b10000000 + .R0_HSCRL = 0b00000000 + .R0_HSCRL_INH = 0b01000000 + .R0_NO_LCB = 0b00000000 + .R0_LCB = 0b00100000 + .R0_IE1_OFF = 0b00000000 + .R0_IE1 = 0b00010000 + .R0_SS_OFF = 0b00000000 + .R0_SS = 0b00001000 + .R0_DEFAULT = 0b00000110 + .R0_ES_OFF = 0b00000000 + .R0_ES = 0b00000001 + + .VDP_R1 = 0b10000001 + + .R1_DEFAULT = 0b10000000 + .R1_DISP_OFF = 0b00000000 + .R1_DISP_ON = 0b01000000 + .R1_IE_OFF = 0b00000000 + .R1_IE = 0b00100000 + .R1_SPR_8X8 = 0b00000000 + .R1_SPR_8X16 = 0b00000010 + + .VDP_R2 = 0b10000010 + + .R2_MAP_0x3800 = 0xFF + .R2_MAP_0x3000 = 0xFD + .R2_MAP_0x2800 = 0xFB + .R2_MAP_0x2000 = 0xF9 + .R2_MAP_0x1800 = 0xF7 + .R2_MAP_0x1000 = 0xF5 + .R2_MAP_0x0800 = 0xF3 + .R2_MAP_0x0000 = 0xF1 + + .VDP_R3 = 0b10000011 + .VDP_R4 = 0b10000100 + .VDP_R5 = 0b10000101 + + .R5_SAT_0x3F00 = 0xFF + .R5_SAT_MASK = 0b10000001 + + .VDP_R6 = 0b10000110 + + .R6_BANK0 = 0xFB + .R6_DATA_0x0000 = 0xFB + .R6_BANK1 = 0xFF + .R6_DATA_0x2000 = 0xFF + + .VDP_R7 = 0b10000111 + .VDP_RBORDER = 0b10000111 + + .R7_COLOR_MASK = 0b11110000 + + .VDP_R8 = 0b10001000 + .VDP_RSCX = 0b10001000 + + .VDP_R9 = 0b10001001 + .VDP_RSCY = 0b10001001 + + .VDP_R10 = 0b10001010 + + .R10_INT_OFF = 0xFF + .R10_INT_EVERY = 0x00 + + .JOYPAD_COUNT = 1 + + .UP = 0b00000001 + .DOWN = 0b00000010 + .LEFT = 0b00000100 + .RIGHT = 0b00001000 + .A = 0b00010000 + .B = 0b00100000 + .SELECT = 0b00100000 ; map to B + .START = 0b10000000 ; Game Gear Start button + + .JOY_PORT1 = 0xDC + + .JOY_P1_UP = 0b00000001 + .JOY_P1_DOWN = 0b00000010 + .JOY_P1_LEFT = 0b00000100 + .JOY_P1_RIGHT = 0b00001000 + .JOY_P1_SW1 = 0b00010000 + .JOY_P1_TRIGGER = 0b00010000 + .JOY_P1_SW2 = 0b00100000 + .JOY_P2_UP = 0b01000000 + .JOY_P2_DOWN = 0b10000000 + + .JOY_PORT2 = 0xDD + + .JOY_P2_LEFT = 0b00000001 + .JOY_P2_RIGHT = 0b00000010 + .JOY_P2_SW1 = 0b00000100 + .JOY_P2_TRIGGER = 0b00000100 + .JOY_P2_SW2 = 0b00001000 + .JOY_RESET = 0b00010000 + .JOY_P1_LIGHT = 0b01000000 + .JOY_P2_LIGHT = 0b10000000 + + .FMADDRESS = 0xF0 + .FMDATA = 0xF1 + .AUDIOCTRL = 0xF2 + + .RAM_CONTROL = 0xfffc + + .RAMCTL_BANK = 0b00000100 + .RAMCTL_ROM = 0b00000000 + .RAMCTL_RAM = 0b00001000 + .RAMCTL_RO = 0b00010000 + .RAMCTL_PROT = 0b10000000 + + .GLASSES_3D = 0xfff8 + + .MAP_FRAME0 = 0xfffd + .MAP_FRAME1 = 0xfffe + .MAP_FRAME2 = 0xffff + + .BIOS = 0xC000 + + .SYSTEM_PAL = 0x00 + .SYSTEM_NTSC = 0x01 + + .CPU_CLOCK = 3579545 + + ;; GBDK library screen modes + + .T_MODE = 0x02 ; Text mode (bit 2) + .T_MODE_OUT = 0x02 ; Text mode output only + .T_MODE_INOUT = 0x03 ; Text mode with input + .M_NO_SCROLL = 0x04 ; Disables scrolling of the screen in text mode + .M_NO_INTERP = 0x08 ; Disables special character interpretation + + ;; Screen dimentions in tiles + + .SCREEN_X_OFS = 6 + .SCREEN_Y_OFS = 3 + .SCREEN_WIDTH = 20 + .SCREEN_HEIGHT = 18 + .VDP_MAP_HEIGHT = 28 + .VDP_MAP_WIDTH = 32 + + ;; Interrupt flags + + .VBL_IFLAG = 0x01 + .LCD_IFLAG = 0x02 + + ; characters + .CR = 0x0A + .SPACE = 0x00 + + ;; Global variables + .globl .mode + + ;; Interrupt routines + .globl _INT_ISR + .globl _NMI_ISR + + ;; Symbols defined at link time + .globl .STACK + .globl _shadow_OAM + .globl __shadow_OAM_OFF + + ;; Main user routine + .globl _main + + ;; Macro definitions + +.macro VDP_WRITE_DATA regH regL ?lbl + ld a, i + ld a, regL + di + out (#.VDP_DATA), a ; 11 + ld a, regH ; 4 + jp po, lbl ; 7/12 + ei ; 4 (total: 26/27) +lbl: + out (#.VDP_DATA), a +.endm + +.macro VDP_WRITE_CMD regH regL ?lbl + ld a, i + ld a, regL + di + out (#.VDP_CMD), a + ld a, regH + jp po, lbl + ei +lbl: + out (#.VDP_CMD), a +.endm + +.macro VDP_DELAY ?lbl + nop + jr lbl +lbl: +.endm + +.macro VDP_CANCEL_INT + in a, (.VDP_STAT) ; cancel pending VDP interrupts +.endm + +.macro WRITE_VDP_CMD_HL + rst 0x10 +.endm + +.macro WRITE_VDP_DATA_HL + rst 0x20 +.endm + +.macro CALL_HL + rst 0x30 +.endm + +.macro DISABLE_VBLANK_COPY + ld a, #1 + ld (__shadow_OAM_OFF), a +.endm + +.macro ENABLE_VBLANK_COPY + xor a + ld (__shadow_OAM_OFF), a +.endm + +.macro ADD_A_REG16 regH regL + add regL + ld regL, a + adc regH + sub regL + ld regH, a +.endm + +.macro MUL_DE_BY_A_RET_HL ?lbl1 ?lbl2 + ; Multiply DE by A, return result in HL; preserves: BC + ld hl, #0 +lbl1: + srl a + jp nc, lbl2 + add hl, de +lbl2: + sla e + rl d + or a + jp nz, lbl1 +.endm + +.macro DIV_PART divident divisor ?lbl + rl divident + rla + sub divisor + jr nc, lbl + add divisor +lbl: +.endm +.macro FAST_DIV8 divident divisor + ; returns modulus in A + .rept 8 + DIV_PART divident divisor + .endm + ld a, divident + cpl +.endm +.macro FAST_MOD8 divident divisor + ; returns modulus in A + .rept 8 + DIV_PART divident divisor + .endm +.endm diff --git a/gbdk/gbdk-lib/libc/targets/z80/gg/nmi.s b/gbdk/gbdk-lib/libc/targets/z80/gg/nmi.s new file mode 100644 index 00000000..d61b5ded --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/gg/nmi.s @@ -0,0 +1,8 @@ + .include "global.s" + + .title "NMI Handler" + .module NMIHandler + .area _HOME + +_NMI_ISR:: + retn
\ No newline at end of file diff --git a/gbdk/gbdk-lib/libc/targets/z80/gg/pad.s b/gbdk/gbdk-lib/libc/targets/z80/gg/pad.s new file mode 100644 index 00000000..cb95ad47 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/gg/pad.s @@ -0,0 +1,43 @@ + .include "global.s" + + .title "JOYPad utilities" + .module JOYPad + .area _HOME + + ;; Get Keypad Button Status +_joypad:: +.jpad:: + in a, (.JOY_PORT1) + cpl + and #0b00111111 + ld l, a + in a, (.GG_STATE) + cpl + and #.GGSTATE_STT + or l + ld l, a + ret + + ;; Wait until all buttons have been released +.padup:: +_waitpadup:: +1$: + ld h,#0x7f ; wait for .jpad return zero 127 times in a row +2$: + call .jpad + or a ; have all buttons been released? + jr nz,1$ ; not yet + + dec h + jr nz,2$ + + ret + + ;; Wait for the key to be pressed +_waitpad:: +.wait_pad:: +1$: + call .jpad ; read pad + and l ; compare with mask? + jr z,1$ ; loop if no intersection + ret diff --git a/gbdk/gbdk-lib/libc/targets/z80/gg/pad_ex.s b/gbdk/gbdk-lib/libc/targets/z80/gg/pad_ex.s new file mode 100644 index 00000000..87004dfb --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/gg/pad_ex.s @@ -0,0 +1,76 @@ + .include "global.s" + + .title "JOYPad utilities" + .module JOYPad + .area _HOME + +; uint8_t joypad_init(uint8_t npads, joypads_t * joypads) __z88dk_callee; +_joypad_init:: + ld hl, #2 + add hl, sp + ld a, (hl) + or a + jr nz, 1$ + ld a, #1 + jr 2$ +1$: + cp #(.JOYPAD_COUNT + 1) + jr c, 2$ + ld a, #.JOYPAD_COUNT +2$: + inc hl + ld e, (hl) + inc hl + ld d, (hl) + + inc hl + pop bc ; pop return address + ld sp, hl ; dispose params + push bc ; push return address back + + ld (de), a ; number of joypads + ld l, a ; return number of joypads in l + xor a + inc de + ld (de), a + inc de + ld (de), a + inc de + ld (de), a + inc de + ld (de), a + + ret + +;void joypad_ex(joypads_t * joypads) __z88dk_fastcall; + +_joypad_ex:: + in a, (.GG_STATE) + cpl + and #.GGSTATE_STT + ld b, a + ld c, #.JOY_PORT1 + in e, (c) + inc c + in d, (c) + ld a, e + rla + rl d + rla + rl d + ld a, e + cpl + and #0b00111111 + or b + ld e, a + ld a, d + cpl + and #0b00111111 + ld d, a + + inc hl + ld (hl), e + inc hl + ld (hl), d + + ret
\ No newline at end of file diff --git a/gbdk/gbdk-lib/libc/targets/z80/gg/palette.s b/gbdk/gbdk-lib/libc/targets/z80/gg/palette.s new file mode 100644 index 00000000..5e35d425 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/gg/palette.s @@ -0,0 +1,107 @@ + ;; SMS palette routines + + .include "global.s" + + .title "CRAM SMS Palettes" + .module CRAMUtils + .area _HOME + +; void set_palette_entry(uint8_t palette, uint8_t entry, uint16_t rgb_data) __z88dk_callee; +_set_palette_entry:: + pop de + pop bc + ld hl, #.VDP_CRAM + bit 0, c + jr z, 1$ + set 4, b +1$: + sla b + ld c, b + ld b, #0 + add hl, bc + pop bc + + ld a, i + di + ld a, l + out (#.VDP_CMD), a + ld a, h + out (#.VDP_CMD), a + ld a, c + out (#.VDP_DATA), a + jr 3$ +3$: + ld a, b + out (#.VDP_DATA), a + jp po, 2$ + ei +2$: + ld h, d + ld l, e + jp (hl) + +; void set_palette(uint8_t first_palette, uint8_t nb_palettes, uint16_t *rgb_data) __z88dk_callee; +_set_palette:: + pop de + pop bc + ld hl, #.VDP_CRAM + bit 0, c + ld a, b + ld bc, #0 + jr z, 1$ + ld c, #0x20 +1$: + add hl, bc + + ld c, a + + DISABLE_VBLANK_COPY ; switch OFF copy shadow SAT + + ld a, i + di + ld a, l + out (#.VDP_CMD), a + ld a, h + out (#.VDP_CMD), a + jp po, 2$ + ei +2$: + ld a, c + or a + jr z, 3$ + + pop hl + ld c, #.VDP_DATA +5$: + ld b, #0x20 +4$: + outi + jr nz, 4$ + + dec a + jr nz, 5$ +3$: + ENABLE_VBLANK_COPY ; switch ON copy shadow SAT + + ld h, d + ld l, e + jp (hl) + +.CRT_DEFAULT_PALETTE:: + .dw 0b0000111111111111 + .dw 0b0000100010001000 + .dw 0b0000010001000100 + .dw 0b0000000000000000 + .dw 0b0000000000001000 + .dw 0b0000000010000000 + .dw 0b0000100000000000 + .dw 0b0000000010001000 + .dw 0b0000100010000000 + .dw 0b0000100000001000 + .dw 0b0000000000001111 + .dw 0b0000000011110000 + .dw 0b0000111100000000 + .dw 0b0000000011111111 + .dw 0b0000111111110000 + .dw 0b0000111100001111 + diff --git a/gbdk/gbdk-lib/libc/targets/z80/gotoxy.s b/gbdk/gbdk-lib/libc/targets/z80/gotoxy.s new file mode 100644 index 00000000..a2394ad4 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/gotoxy.s @@ -0,0 +1,34 @@ + .include "global.s" + + .title "console utilities" + .module ConsoleUtils + + .globl .curx, .cury + + .area _HOME + +_gotoxy:: + pop hl + pop de + push de + push hl + + ld a, #.SCREEN_X_OFS + add e + ld (.curx), a + ld a, #.SCREEN_Y_OFS + add d + ld (.cury), a + ret + +_posx:: + ld a, (.curx) + sub #.SCREEN_X_OFS + ld l, a + ret + +_posy:: + ld a, (.cury) + sub #.SCREEN_Y_OFS + ld l, a + ret
\ No newline at end of file diff --git a/gbdk/gbdk-lib/libc/targets/z80/heap.s b/gbdk/gbdk-lib/libc/targets/z80/heap.s new file mode 100644 index 00000000..991df234 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/heap.s @@ -0,0 +1,44 @@ +;-------------------------------------------------------------------------- +; heap.s +; +; Copyright (C) 2001, Michael Hope +; +; This library is free software; you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published by the +; Free Software Foundation; either version 2, or (at your option) any +; later version. +; +; This library is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this library; see the file COPYING. If not, write to the +; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, +; MA 02110-1301, USA. +; +; As a special exception, if you link this library with other files, +; some of which are compiled with SDCC, to produce an executable, +; this library does not by itself cause the resulting executable to +; be covered by the GNU General Public License. This exception does +; not however invalidate any other reasons why the executable file +; might be covered by the GNU General Public License. +;-------------------------------------------------------------------------- + +; Just stubs - not copyrightable + + ;; Stubs that hook the heap in + .globl ___sdcc_heap_init + + .area _GSINIT + call ___sdcc_heap_init + + .area _HEAP +___sdcc_heap:: + ;; For now just allocate 2k of heap. + .ds 2047 + + .area _HEAP_END +___sdcc_heap_end:: + .ds 1 diff --git a/gbdk/gbdk-lib/libc/targets/z80/memset_small.s b/gbdk/gbdk-lib/libc/targets/z80/memset_small.s new file mode 100644 index 00000000..a2fa3e13 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/memset_small.s @@ -0,0 +1,14 @@ + .include "global.s" + + .title "memset small" + .module MemSetSmall + + .area _HOME + +.memset_small:: +1$: + ld (hl), a + inc hl + dec c + jp nz, 1$ + ret diff --git a/gbdk/gbdk-lib/libc/targets/z80/mode.s b/gbdk/gbdk-lib/libc/targets/z80/mode.s new file mode 100644 index 00000000..17e3b2e1 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/mode.s @@ -0,0 +1,22 @@ + .include "global.s" + + .title "screen modes" + .module Modes + + .area _HOME + +_mode:: + pop de + pop hl + push hl + push de + +.set_mode:: + ld a, l + ld (.mode), a + ret + +_get_mode:: + ld hl, #.mode + ld l, (hl) + ret
\ No newline at end of file diff --git a/gbdk/gbdk-lib/libc/targets/z80/msxdos/Makefile b/gbdk/gbdk-lib/libc/targets/z80/msxdos/Makefile new file mode 100644 index 00000000..77c4a0dd --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/msxdos/Makefile @@ -0,0 +1,36 @@ +# GB specific Makefile + +TOPDIR = ../../../.. + +THIS = msxdos +PORT = z80 + +CSRC = crlf.c + +ASSRC = set_interrupts.s \ + outi.s \ + bdos_putchar.s bdos_getchar.s bdos_gets.s \ + msx_refresh_oam.s \ + msx_write_vdp.s \ + msx_set_native_data.s msx_set_1bpp_data.s msx_set_1bpp_sprite_data.s \ + msx_set_tile_map.s msx_set_tile_map_xy.s \ + msx_fill_rect.s msx_fill_rect_xy.s \ + msx_metasprites.s msx_metasprites_hide.s msx_metasprites_hide_spr.s \ + pad.s \ + msx_int.s \ + mode.s clock.s \ + delay.s \ + memset_small.s \ + far_ptr.s \ + color.s \ + heap.s \ + __sdcc_bcall.s __sdcc_bcall_abc.s \ + crt0.s + +CRT0 = crt0.s + +include $(TOPDIR)/Makefile.common + +AS = $(AS_Z80) + +include ../../../Makefile.platform diff --git a/gbdk/gbdk-lib/libc/targets/z80/msxdos/__sdcc_bcall.s b/gbdk/gbdk-lib/libc/targets/z80/msxdos/__sdcc_bcall.s new file mode 100644 index 00000000..0d39036b --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/msxdos/__sdcc_bcall.s @@ -0,0 +1,41 @@ + .include "global.s" + + .area _CODE + + .globl ___sdcc_bcall_ehl +; +; default trampoline to call banked functions +; Usage: +; ld e, #<function_bank> +; ld hl, #<function> +; call ___sdcc_bcall_ehl +; +___sdcc_bcall_ehl:: + push hl + ld h, #>__banks_remap_table + ld l, e ; e == new bank + + ld a, (__current_bank) + ld l, (hl) ; l == segment + ld h, a ; h == old bank + + ld a, e + ld (__current_bank), a ; new bank to __current_bank + + ld a, l ; set segment + call .mapper_page_set + ex (sp), hl ; old bank is left on stack + inc sp + + CALL_HL + dec sp + + ex (sp), hl + ld a, h + ld (__current_bank), a + ld h, #>__banks_remap_table + ld l, a + ld a, (hl) + call .mapper_page_set + pop hl + ret diff --git a/gbdk/gbdk-lib/libc/targets/z80/msxdos/__sdcc_bcall_abc.s b/gbdk/gbdk-lib/libc/targets/z80/msxdos/__sdcc_bcall_abc.s new file mode 100644 index 00000000..217fac7f --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/msxdos/__sdcc_bcall_abc.s @@ -0,0 +1,59 @@ + .include "global.s" + + .area _CODE + + .globl ___sdcc_bcall + .globl ___sdcc_bcall_abc + +; +; trampoline to call banked functions +; used when legacy banking is enabled only +; Usage: +; call ___sdcc_bcall +; .dw <function> +; .dw <function_bank> +; +___sdcc_bcall:: + ex (sp), hl + ld c, (hl) + inc hl + ld b, (hl) + inc hl + ld a, (hl) + inc hl + inc hl + ex (sp), hl +; +; trampoline to call banked functions with __z88dk_fastcall calling convention +; Usage: +; ld a, #<function_bank> +; ld bc, #<function> +; call ___sdcc_bcall_abc +; +___sdcc_bcall_abc:: + push hl + ld l, a + ld a, (__current_bank) + ld h, #>__banks_remap_table + ld l, (hl) + ld h, a + call .mapper_page_set + ex (sp), hl + + inc sp + call ___sdcc_bjump_abc + dec sp + + ex (sp), hl + ld a, h + ld (__current_bank), a + ld h, #>__banks_remap_table + ld l, a + ld a, (hl) + call .mapper_page_set + pop hl + ret +; +___sdcc_bjump_abc: + push bc + ret diff --git a/gbdk/gbdk-lib/libc/targets/z80/msxdos/bdos_getchar.s b/gbdk/gbdk-lib/libc/targets/z80/msxdos/bdos_getchar.s new file mode 100644 index 00000000..d99cf4ba --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/msxdos/bdos_getchar.s @@ -0,0 +1,10 @@ + .include "global.s" + + .title "getchar" + .module getchar + + .area _CODE + +_getchar:: + JP_BDOS #_INNOE +
\ No newline at end of file diff --git a/gbdk/gbdk-lib/libc/targets/z80/msxdos/bdos_gets.s b/gbdk/gbdk-lib/libc/targets/z80/msxdos/bdos_gets.s new file mode 100644 index 00000000..acc3801a --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/msxdos/bdos_gets.s @@ -0,0 +1,34 @@ + .include "global.s" + + .title "gets" + .module gets + + .area _CODE + +_gets:: + pop hl + pop de + push de + push hl + push de + ld c, #63 ; limit input to 64 bytes including trailing zero + ; that match with internal buffer in scanf() +1$: + push bc + push de + CALL_BDOS #_CONIN + pop de + pop bc + cp #0x0d ; CR + jp z, 2$ + cp #0x05 ; EOF + jp z, 2$ + ld (de), a + inc de + dec c + jp nz, 1$ +2$: + xor a + ld (de), a + pop hl + ret
\ No newline at end of file diff --git a/gbdk/gbdk-lib/libc/targets/z80/msxdos/bdos_putchar.s b/gbdk/gbdk-lib/libc/targets/z80/msxdos/bdos_putchar.s new file mode 100644 index 00000000..79dfa70a --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/msxdos/bdos_putchar.s @@ -0,0 +1,15 @@ + .include "global.s" + + .title "putchar" + .module putchar + + .area _CODE + +_setchar:: +_putchar:: + pop hl + pop de + push de ; char in E + push hl + JP_BDOS #_CONOUT +
\ No newline at end of file diff --git a/gbdk/gbdk-lib/libc/targets/z80/msxdos/crlf.c b/gbdk/gbdk-lib/libc/targets/z80/msxdos/crlf.c new file mode 100644 index 00000000..c10d2cb4 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/msxdos/crlf.c @@ -0,0 +1 @@ +const char * const __crlf = "\r\n";
\ No newline at end of file diff --git a/gbdk/gbdk-lib/libc/targets/z80/msxdos/crt0.s b/gbdk/gbdk-lib/libc/targets/z80/msxdos/crt0.s new file mode 100644 index 00000000..0b1a2e4d --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/msxdos/crt0.s @@ -0,0 +1,522 @@ + .include "global.s" + + .title "Runtime" + .module Runtime + + .ez80 + + ;; Ordering of segments for the linker. + .area _CODE + .area _CODE_0 + .area _HOME + .area _BASE + .area _LIT + .area _GSINIT + .area _GSFINAL + .area _INITIALIZER + + .area _DATA + .area _INITIALIZED + .area _BSEG + .area _BSS + .area _HEAP + .area _HEAP_END + + ; program startup code + .area _CODE +.start:: + ei + call .save_int_vector + call .gsinit + + ld a, (___overlay_count) + and a + call nz, .load_overlays + jp c, .exit_error + + call .setup_video_mode + + ld hl, #.LS_FILE_BUFFER + xor a + ld b, a + ld c, (hl) + or c + jr z, 1$ + + add hl, bc + inc hl + xor a + ld (hl), a + ld c, a ; param counter + + ld hl, #(.LS_FILE_BUFFER + 1) +3$: + ld a, (hl) + or a + jr z, 6$ + cp #0x20 + jr nz, 6$ + inc hl + jr 3$ +6$: + jr z, 2$ + + inc c + push hl +4$: + inc hl + ld a, (hl) + or a + jr z, 2$ + cp #0x20 + jr nz, 4$ +5$: + ld (hl), #0 + inc hl + jr 3$ +2$: + ld hl, #0 + add hl, sp + push hl ; push pointer to argv array on stack +1$: + ld b, #0 + push bc ; push argc + ; reverse argv order + ld e, c + srl e + jr z, 7$ ; only 1 parameter + + dec c + ld ixh, b + ld ixl, c + add ix, ix + ld b, h + ld c, l + add ix, bc +8$: + ld d, (hl) + ld a, 0 (ix) + ld 0 (ix), d + ld (hl), a + inc hl + ld d, (hl) + ld a, 1 (ix) + ld 1 (ix), d + ld (hl), a + inc hl + dec ix + dec ix + dec e + jr nz, 8$ +7$: + call _main +.exit: + push hl + ld l, #0 + call _SWITCH_ROM + call .restore_int_vector + pop hl + ld b, l + CALL_BDOS #_TERM ; try terminate usind MSX DOS 2 function + JP_BDOS #_TERM0 +_exit:: + pop hl + pop hl + jr .exit + +.exit_error: + ld hl, #1$ + push hl + call _puts + JP_BDOS #_TERM0 +1$: + .asciz "LOAD ERROR!\r\n" + + ;; fills memory at HL of length BC with A, clobbers DE +.memset_simple:: + ld e, a + ld a, c + or b + ret z + ld (hl), e + dec bc + ld d, h + ld e, l + inc de + + ;; copies BC bytes from HL into DE +.memcpy_simple:: + ld a, c + or b + ret z + ldir + ret + + ;; put some internal data here, to save bytes wasted for the alignment of __banks_remap_table + +___overlay_count:: + .db 0 +.overlay_fcb: + .db 0 ; drive +___overlay_name:: + .ascii "OVERLAYS" ; filename +.overlay_fcb_ext:: + .ascii "000" ; extension +.overlay_fcb_extent: + .db 0 ; extent + .db 0 ; attributes +.overlay_fcb_record_size: + .db 0 ; extent ; msx-dos1: record size low byte +.overlay_fbc_record_cont: + .db 0 ; record count ; msx-dos1: record size high byte +.overlay_fcb_file_size: + .db 0, 0, 0, 0 ; file size + .db 0, 0, 0, 0 ; volume id + .ds 8 ; internal +.overlay_fcb_position: + .db 0 ; current record within extent +.overlay_fcb_random_pos: + .db 0, 0, 0, 0 ; Random record number +.overlay_fcb_end: + +__memman_present:: + .db 0 +__rammapper_table:: + .dw 0 + +.rammapper_hiwater: + .db 4 ; 7 segments for 128K config +.rammapper_alloc_hiwater: + .db 1 ; allocation starts from bank 1 + +.mapper_page_alloc:: + ld hl, #.rammapper_hiwater + ld a, (hl) + inc (hl) + or a ; never fail + ret + +_SWITCH_ROM:: ; Z88DK_FASTCALL : uint8_t parameter in l + ld a, l + ld (__current_bank), a + ld h, #>__banks_remap_table + ld l, a + ld a, (hl) +.mapper_page_set:: + out (.MAP_FRAME1), a + ret + +.mapper_page_get:: + in a, (.MAP_FRAME1) +__mapper_page_mask = .+1 +.globl __mapper_page_mask + and #0x00 ; zero ram size, will be patched + ret + +__current_bank:: + .db 0 + +; --- 256 byte boundary --------------------------------------- + + .bndry 0x100 +__banks_remap_table:: + .ds 100 +l__banks_remap_table = .-__banks_remap_table + +__mapper_bank_alloc:: + ld hl, #.rammapper_alloc_hiwater + ld a, (hl) + inc (hl) + ld h, #>__banks_remap_table + ld l, a + ld a, #0xff + cp (hl) + jr nz, 1$ + + xor a + ld b, a + push hl + call .mapper_page_alloc + pop hl + ret c ; return if no memory + ld (hl), a ; set segment number for the bank number +1$: + or a + ret ; allocated bank returns in l + +.macro TRANSFER_POINTER ofs dest + ld hl, #dest + ld (hl), #0xc3 + inc hl + ld a, ofs (ix) + ld (hl), a + inc hl + ld a, ofs+1 (ix) + ld (hl), a +.endm + +.initialize_ram_mapper:: + ; detect mapper capacity + in a, (.MAP_FRAME1) + ld e, a + xor a + out (.MAP_FRAME1), a + in a, (.MAP_FRAME1) + cpl + ld (__mapper_page_mask), a + and e + ld hl, #__banks_remap_table + ld (hl), a + inc hl + ld (hl), a ; bank 0 == bank 1 + + xor a + ld de,#0401 ; get routines info table + call .EXTBIO + ld (__rammapper_table), hl + + xor a + ld de, #0x0402 ; populate ram mapper routines table + call .EXTBIO + or a + jr nz, 1$ + scf + ret +1$: + push hl + pop ix + + TRANSFER_POINTER 0x01, .mapper_page_alloc + TRANSFER_POINTER 0x1f, .mapper_page_set + TRANSFER_POINTER 0x22, .mapper_page_get + + ld a, #1 + ld (__memman_present), a + + or a ; return ok + ret + + ;; Wait for VBL interrupt to be finished +.wait_vbl_done:: +_wait_vbl_done:: + ld a, (_shadow_VDP_R1) + and #.R1_DISP_ON + ret z + + xor a + ld (.vbl_done), a +1$: + halt + ld a, (.vbl_done) + or a + jr z, 1$ + ret + +; --- 256 byte boundary --------------------------------------- + + .bndry 256 +_shadow_OAM:: + .ds 0x80 + + ;; load overlays, count in A +.load_overlays: + ld b, a + ld a, (__memman_present) + or a + jr nz, 3$ + ld a, (__mapper_page_mask) + sub #3 ; ram segments used for DOS + inc a + cp b + ret c ; not sufficient ram to load overlays +3$: + ld c, #1 +1$: + push bc + call .load_overlay + pop bc + ret c ; error loading overlay + + ld a, c + cp b + jr z, 2$ ; all loaded - return + + inc c ; next overlay + ld a, #(l__banks_remap_table - 1) + cp c + ret c ; more than 99 overlays are not allowed + + jr 1$ +2$: + xor a + call _SWITCH_ROM + ret + +.load_overlay: + push bc + call __mapper_bank_alloc + pop bc + ret c ; no free segments + + call _SWITCH_ROM ; switch bank to l + + ld b, #8 + xor a +1$: + rlc c + adc a + daa + djnz 1$ + ; result in a, max 99 overlays + ld c, a + ld b, #0x0f + ld e, #'0' + ld hl, #(.overlay_fcb_ext + 1) + rra + rra + rra + rra + and b + add e + ld (hl), a + inc hl + ld a, c + and b + add e + ld (hl), a + + xor a + ld bc, #(.overlay_fcb_end - .overlay_fcb_extent) + ld hl, #.overlay_fcb_extent + call .memset_simple ; initialize fcb + + ld de, #.overlay_fcb + CALL_BDOS #_FOPEN + rrca + ret c ; file not found + + ld de, #0x4000 +3$: + CALL_BDOS #_SETDTA + + push de + ld de, #.overlay_fcb + CALL_BDOS #_RDSEQ + pop de + + rrca + jr c, 2$ ; EOF reached + + ld a, #128 + ADD_A_REG16 d, e + + ld a, #0xc0 + cp d + jr z, 2$ ; end of page1 reached + + jr 3$ +2$: + ld de, #.overlay_fcb + CALL_BDOS #_FCLOSE + + or a ; return ok + ret + +.restore_int_vector: + ld hl, #__old_int_vector + ld de, #.LS_INT_VECTOR + jr .restore_ldir +.save_int_vector: + ld hl, #.LS_INT_VECTOR + ld de, #__old_int_vector +.restore_ldir: + ld bc, #0x0005 + ld a, i + push af + di + ldir + pop af + jp po, 1$ + ei +1$: + ret + +.setup_video_mode: + ld a, i + push af + di + ;; Initialize VDP + ld c, #.VDP_CMD + ld b, #(.shadow_VDP_end - .shadow_VDP) + ld hl,#(.shadow_VDP_end - 1) +1$: + outd + jr 3$ ; delay +3$: + ld a, b + or #.VDP_REG_MASK + out (c), a + + ld a, b + or a + jr nz, 1$ + + pop af + jp po, 2$ + ei +2$: + ret + +.shadow_VDP: +_shadow_VDP_R0:: + .db #(.R0_DEFAULT | .R0_SCR_MODE2) +_shadow_VDP_R1:: + .db #(.R1_DEFAULT | .R1_DISP_ON | .R1_IE | .R1_SCR_MODE2 | .R1_SPR_8X8) +_shadow_VDP_R2:: + .db .R2_MAP_0x1C00 +_shadow_VDP_R3:: + .db 0xFF ; tiledata attr from 0x2000 +_shadow_VDP_R4:: + .db 0x03 ; tiledata from 0x0000 +_shadow_VDP_R5:: + .db .R5_SAT_0x1B00 +_shadow_VDP_R6:: + .db 0x07 +_shadow_VDP_R7:: +_shadow_VDP_RBORDER:: + .db 0x01 +.shadow_VDP_end:: + +.sys_time:: +_sys_time:: + .dw 0x0000 +.vbl_done:: + .db 0 +__shadow_OAM_base:: + .db #>_shadow_OAM +__shadow_OAM_OFF:: + .db 0 +.mode:: + .ds .T_MODE_INOUT ; Current mode +__old_int_vector:: + .ds 5 + + .area _GSINIT +.gsinit:: + ;; initialize static storage + xor a + ld bc, #l__DATA + ld hl, #s__DATA + call .memset_simple ; initialize variables in RAM with zero + + ;; initialize static storage variables + ld bc, #l__INITIALIZER + ld hl, #s__INITIALIZER + ld de, #s__INITIALIZED + call .memcpy_simple + + ;; initialize ram mapper + call .initialize_ram_mapper + + .area _GSFINAL + ret diff --git a/gbdk/gbdk-lib/libc/targets/z80/msxdos/global.s b/gbdk/gbdk-lib/libc/targets/z80/msxdos/global.s new file mode 100644 index 00000000..e20449aa --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/msxdos/global.s @@ -0,0 +1,483 @@ + .OS_RESET = 0x0000 + .LS_IO = 0x0003 + .LS_DSK = 0x0004 + .LS_INT_VECTOR = 0x0038 + .LS_FCB0 = 0x005C + .LS_FCB1 = 0x006C + .LS_FILE_BUFFER = 0x0080 + .BDOS = 0x0005 + + .EXTBIO = 0xFFCA + + ; MSX-DOS 1 + _TERM0 = 0x00 ; Program terminate + _CONIN = 0x01 ; Console input + _CONOUT = 0x02 ; Console output + _AUXIN = 0x03 ; Auxiliary input + _AUXOUT = 0x04 ; Auxiliary output + _LSTOUT = 0x05 ; Printer output + _DIRIO = 0x06 ; Direct console I/O + _DIRIN = 0x07 ; Direct console input + _INNOE = 0x08 ; Console input without echo + _STROUT = 0x09 ; String output + _BUFIN = 0x0A ; Buffered line input + _CONST = 0x0B ; Console status + _CPMVER = 0x0C ; Return version number + _DSKRST = 0x0D ; Disk reset + _SELDSK = 0x0E ; Select disk + _FOPEN = 0x0F ; Open file (FCB) + _FCLOSE = 0x10 ; Close file (FCB) + _SFIRST = 0x11 ; Search for first entry (FCB) + _SNEXT = 0x12 ; Search for next entry (FCB) + _FDEL = 0x13 ; Delete file (FCB) + _RDSEQ = 0x14 ; Sequential read (FCB) + _WRSEQ = 0x15 ; Sequential write (FCB) + _FMAKE = 0x16 ; Create file (FCB) + _FREN = 0x17 ; Rename file (FCB) + _LOGIN = 0x18 ; Get login vector + _CURDRV = 0x19 ; Get current drive + _SETDTA = 0x1A ; Set disk transfer address + _ALLOC = 0x1B ; Get allocation information + _RDRND = 0x21 ; Random read (FCB) + _WRRND = 0x22 ; Random write (FCB) + _FSIZE = 0x23 ; Get file size (FCB) + _SETRND = 0x24 ; Set random record (FCB) + _WRBLK = 0x26 ; Random block write (FCB) + _RDBLK = 0x27 ; Random block read (FCB) + _WRZER = 0x28 ; Random write with zero fill (FCB) + _GDATE = 0x2A ; Get date + _SDATE = 0x2B ; Set date + _GTIME = 0x2C ; Get time + _STIME = 0x2D ; Set time + _VERIFY = 0x2E ; Set/reset verify flag + _RDABS = 0x2F ; Absolute sector read + _WRABS = 0x30 ; Absolute sector write + + ; MSX-DOS2 + _DPARM = 0x31 ; Get disk parameters + _FFIRST = 0x40 ; Find first entry + _FNEXT = 0x41 ; Find next entry + _FNEW = 0x42 ; Find new entry + _OPEN = 0x43 ; Open file handle + _CREATE = 0x44 ; Create file handle + _CLOSE = 0x45 ; Close file handle + _ENSURE = 0x46 ; Ensure file handle + _DUP = 0x47 ; Duplicate file handle + _READ = 0x48 ; Read from file handle + _WRITE = 0x49 ; Write to file handle + _SEEK = 0x4A ; Move file handle pointer + _IOCTL = 0x4B ; I/O control for devices + _HTEST = 0x4C ; Test file handle + _DELETE = 0x4D ; Delete file or subdirectory + _RENAME = 0x4E ; Rename file or subdirectory + _MOVE = 0x4F ; Move file or subdirectory + _ATTR = 0x50 ; Get/set file attributes + _FTIME = 0x51 ; Get/set file date and time + _HDELETE = 0x52 ; Delete file handle + _HRENAME = 0x53 ; Rename file handle + _HMOVE = 0x54 ; Move file handle + _HATTR = 0x55 ; Get/set file handle attributes + _HFTIME = 0x56 ; Get/set file handle date and time + _GETDTA = 0x57 ; Get disk transfer address + _GETVFY = 0x58 ; Get verify flag setting + _GETCD = 0x59 ; Get current directory + _CHDIR = 0x5A ; Change current directory + _PARSE = 0x5B ; Parse pathname + _PFILE = 0x5C ; Parse filename + _CHKCHR = 0x5D ; Check character + _WPATH = 0x5E ; Get whole path string + _FLUSH = 0x5F ; Flush disk buffers + _FORK = 0x60 ; Fork a child process + _JOIN = 0x61 ; Rejoin parent process + _TERM = 0x62 ; Terminate with error code + _DEFAB = 0x63 ; Define abort exit routine + _DEFER = 0x64 ; Define disk error handler routine + _ERROR = 0x65 ; Get previous error code + _EXPLAIN = 0x66 ; Explain error code + _FORMAT = 0x67 ; Format a disk + _RAMD = 0x68 ; Create or destroy RAM disk + _BUFFER = 0x69 ; Allocate sector buffers + _ASSIGN = 0x6A ; Logical drive assignment + _GENV = 0x6B ; Get environment item + _SENV = 0x6C ; Set environment item + _FENV = 0x6D ; Find environment item + _DSKCHK = 0x6E ; Get/set disk check status + _DOSVER = 0x6F ; Get MSX-DOS version number + _REDIR = 0x70 ; Get/set redirection status + + ; MSX_DOS ERROR CODES + .NCOMP = 0xFF ; Incompatible disk + .WRERR = 0xFE ; Write error + .DISK = 0xFD ; Disk error + .NRDY = 0xFC ; Not ready + .VERFY = 0xFB ; Verify error + .DATA = 0xFA ; Data error + .RNF = 0xF9 ; Sector not found + .WPROT = 0xF8 ; Write protected disk + .UFORM = 0xF7 ; Unformatted disk + .NDOS = 0xF6 ; Not a DOS disk + .WDISK = 0xF5 ; Wrong disk + .WFILE = 0xF4 ; Wrong disk for file + .SEEK = 0xF3 ; Seek error + .IFAT = 0xF2 ; Bad file allocation table + .NOUPB = 0xF1 ; -- + .IFORM = 0xF0 ; Cannot format this drive + .INTER = 0xDF ; Internal error + .NORAM = 0xDE ; Not enough memory + .IBDOS = 0xDC ; Invalid MSX-DOS call + .IDRV = 0xDB ; Invalid drive + .IFNM = 0xDA ; Invalid filename + .IPATH = 0xD9 ; Invalid pathname + .PLONG = 0xD8 ; Pathname too long + .NOFIL = 0xD7 ; File not found + .NODIR = 0xD6 ; Directory not found + .DRFUL = 0xD5 ; Root directory full + .DKFUL = 0xD4 ; Disk full + .DUPF = 0xD3 ; Duplicate filename + .DIRE = 0xD2 ; Invalid directory move + .FILRO = 0xD1 ; Read only file + .DIRNE = 0xD0 ; Directory not empty + .IATTR = 0xCF ; Invalid attributes + .DOT = 0xCE ; Invalid . or .. operation + .SYSX = 0xCD ; System file exists + .DIRX = 0xCC ; Directory exists + .FILEX = 0xCB ; File exists + .FOPEN = 0xCA ; File already in use + .OV64K = 0xC9 ; Cannot transfer above 64K + .FILE = 0xC8 ; File allocation error + .EOF = 0xC7 ; End of file + .ACCV = 0xC6 ; File access violation + .IPROC = 0xC5 ; Invalid process id + .NHAND = 0xC4 ; No spare file handles + .IHAND = 0xC3 ; Invalid file handle + .NOPEN = 0xC2 ; File handle not open + .IDEV = 0xC1 ; Invalid device operation + .IENV = 0xC0 ; Invalid environment string + .ELONG = 0xBF ; Environment string too long + .IDATE = 0xBE ; Invalid date + .ITIME = 0xBD ; Invalid time + .RAMDX = 0xBC ; RAM disk (drive H ) already exists + .NRAMD = 0xBB ; RAM disk does not exist + .HDEAD = 0xBA ; File handle has been deleted + .EOL = 0xB9 ; Internal error. Should never occur + .ISBFN = 0xB8 ; Invalid sub-function number + .STOP = 0x9F ; Ctrl-STOP pressed + .CTRLC = 0x9E ; Ctrl-C pressed + .ABORT = 0x9D ; Disk operation aborted + .OUTERR = 0x9C ; Error on standard output + .INERR = 0x9B ; Error on standard input + .BADCOM = 0x8F ; Wrong version of COMMAND + .BADCM = 0x8E ; Unrecognized command + .BUFUL = 0x8D ; Command too long + .OKCMD = 0x8C ; -- + .IPARM = 0x8B ; Invalid parameter + .INP = 0x8A ; Too many parameters + .NOPAR = 0x89 ; Missing parameter + .IOPT = 0x88 ; Invalid option + .BADNO = 0x87 ; Invalid number + .NOHELP = 0x86 ; File for HELP not found + .BADVER = 0x85 ; Wrong version of MSX-DOS + .NOCAT = 0x84 ; Cannot concatenate destination file + .BADEST = 0x83 ; Cannot create destination file + .COPY = 0x82 ; File cannot be copied onto itself + .OVDEST = 0x81 ; Cannot overwrite previous destination file + + .MEMORY_CTL = 0x3E + + .MEMCTL_JOYON = 0b00000000 + .MEMCTL_JOYOFF = 0b00000100 + .MEMCTL_BASEON = 0b00000000 + .MEMCTL_BASEOFF = 0b00001000 + .MEMCTL_RAMON = 0b00000000 + .MEMCTL_RAMOFF = 0b00010000 + .MEMCTL_CROMON = 0b00000000 + .MEMCTL_CROMOFF = 0b00100000 + .MEMCTL_ROMON = 0b00000000 + .MEMCTL_ROMOFF = 0b01000000 + .MEMCTL_EXTON = 0b00000000 + .MEMCTL_EXTOFF = 0b10000000 + + .JOY_CTL = 0x3F + + .JOY_P1_LATCH = 0b00000010 + .JOY_P2_LATCH = 0b00001000 + + .VDP_VRAM = 0x4000 + .VDP_TILEDATA0 = 0x4000 + .VDP_TILEDATA1 = 0x4800 + .VDP_TILEDATA2 = 0x5000 + .VDP_COLORDATA0 = 0x6000 + .VDP_COLORDATA1 = 0x6800 + .VDP_COLORDATA1 = 0x7000 + + .VDP_SPRDATA0 = 0x7800 + + .VDP_TILEMAP = 0x5C00 + .VDP_CRAM = 0xC000 + .VDP_SAT = 0x5B00 + + .VDP_SAT_TERM = 0xD0 + + .VDP_VCOUNTER = 0x7E + .VDP_PSG = 0x7F + .VDP_HCOUNTER = 0x7F + + .VDP_DATA = 0x98 + .VDP_CMD = 0x99 + .VDP_STAT = 0x99 + + .STATF_INT_VBL = 0b10000000 + .STATF_9_SPR = 0b01000000 + .STATF_SPR_COLL = 0b00100000 + + .VDP_REG_MASK = 0b10000000 + .VDP_R0 = 0b10000000 + + .R0_DEFAULT = 0b00000000 + .R0_CB_OUTPUT = 0b00000000 + .R0_CB_INPUT = 0b01000000 + .R0_IE2_OFF = 0b00000000 + .R0_IE2 = 0b00100000 + .R0_IE1_OFF = 0b00000000 + .R0_IE1 = 0b00010000 + .R0_SCR_MODE1 = 0b00000000 + .R0_SCR_MODE2 = 0b00000010 + .R0_ES_OFF = 0b00000000 + .R0_ES = 0b00000001 + + .VDP_R1 = 0b10000001 + + .R1_DEFAULT = 0b10000000 + .R1_DISP_OFF = 0b00000000 + .R1_DISP_ON = 0b01000000 + .R1_IE_OFF = 0b00000000 + .R1_IE = 0b00100000 + .R1_SCR_MODE1 = 0b00010000 + .R1_SCR_MODE2 = 0b00000000 + .R1_SCR_MODE3 = 0b00000000 + .R1_SPR_8X8 = 0b00000000 + .R1_SPR_16X16 = 0b00000010 + .R1_SPR_MAG = 0b00000001 + .R1_SPR_MAG_OFF = 0b00000000 + + .VDP_R2 = 0b10000010 + + .R2_MAP_0x1C00 = 0x07 + + .VDP_R3 = 0b10000011 + .VDP_R4 = 0b10000100 + .VDP_R5 = 0b10000101 + + .R5_SAT_0x1B00 = 0x36 + .R5_SAT_MASK = 0b10000001 + + .VDP_R6 = 0b10000110 + + .VDP_R7 = 0b10000111 + .VDP_RBORDER = 0b10000111 + + .R7_COLOR_MASK = 0b11110000 + + .VDP_R8 = 0b10001000 + + .VDP_R9 = 0b10001001 + + .VDP_R10 = 0b10001010 + + .JOYPAD_COUNT = 1 + + .UP = 0b00100000 + .DOWN = 0b01000000 + .LEFT = 0b00010000 + .RIGHT = 0b10000000 + .A = 0b00000001 + .B = 0b00000100 + .SELECT = 0b00001000 + .START = 0b00000010 + + .KBD_SELECT_ROW = 0xAA + .KBD_INPUT = 0xA9 + + .JOY_PORT1 = 0xDC + + .JOY_P1_UP = 0b00000001 + .JOY_P1_DOWN = 0b00000010 + .JOY_P1_LEFT = 0b00000100 + .JOY_P1_RIGHT = 0b00001000 + .JOY_P1_SW1 = 0b00010000 + .JOY_P1_TRIGGER = 0b00010000 + .JOY_P1_SW2 = 0b00100000 + .JOY_P2_UP = 0b01000000 + .JOY_P2_DOWN = 0b10000000 + + .JOY_PORT2 = 0xDD + + .JOY_P2_LEFT = 0b00000001 + .JOY_P2_RIGHT = 0b00000010 + .JOY_P2_SW1 = 0b00000100 + .JOY_P2_TRIGGER = 0b00000100 + .JOY_P2_SW2 = 0b00001000 + .JOY_RESET = 0b00010000 + .JOY_P1_LIGHT = 0b01000000 + .JOY_P2_LIGHT = 0b10000000 + + .FMADDRESS = 0xF0 + .FMDATA = 0xF1 + .AUDIOCTRL = 0xF2 + + .MAP_FRAME0 = 0xfffc + .MAP_FRAME1 = 0xfffd + .MAP_FRAME2 = 0xfffe + .MAP_FRAME3 = 0xffff + + .BIOS = 0xC000 + + .SYSTEM_PAL = 0x00 + .SYSTEM_NTSC = 0x01 + + .CPU_CLOCK = 3579545 + + ;; GBDK library screen modes + + .T_MODE = 0x02 ; Text mode (bit 2) + .T_MODE_OUT = 0x02 ; Text mode output only + .T_MODE_INOUT = 0x03 ; Text mode with input + .M_NO_SCROLL = 0x04 ; Disables scrolling of the screen in text mode + .M_NO_INTERP = 0x08 ; Disables special character interpretation + + ;; Screen dimentions in tiles + + .SCREEN_X_OFS = 0 + .SCREEN_Y_OFS = 0 + .SCREEN_WIDTH = 32 + .SCREEN_HEIGHT = 24 + .VDP_MAP_HEIGHT = 24 + .VDP_MAP_WIDTH = 32 + + ;; Interrupt flags + + .VBL_IFLAG = 0x01 + .LCD_IFLAG = 0x02 + + ; characters + .CR = 0x0A + .SPACE = 0x00 + + ;; Main user routine + .globl _main + + ;; interrupt handler + .globl _INT_ISR + + ;; Macro definitions + +.macro CALL_BDOS fn + ld c, fn + call .BDOS +.endm + +.macro JP_BDOS fn + ld c, fn + jp .BDOS +.endm + +.macro VDP_WRITE_DATA regH regL ?lbl + ld a, i + ld a, regL + di + out (#.VDP_DATA), a ; 11 + ld a, regH ; 4 + jp po, lbl ; 7/12 + ei ; 4 (total: 26/27) +lbl: + out (#.VDP_DATA), a +.endm + +.macro VDP_WRITE_CMD regH regL ?lbl + ld a, i + ld a, regL + di + out (#.VDP_CMD), a + ld a, regH + jp po, lbl + ei +lbl: + out (#.VDP_CMD), a +.endm + +.macro VDP_DELAY ?lbl + nop + jr lbl +lbl: +.endm + +.macro VDP_CANCEL_INT + in a, (.VDP_STAT) ; cancel pending VDP interrupts +.endm + +.macro WRITE_VDP_CMD_HL + MSX_WRITE_VDP_CMD h, l +.endm + +.macro WRITE_VDP_DATA_HL + MSX_WRITE_VDP_DATA h, l +.endm + +.macro CALL_HL + call ___sdcc_call_hl +.endm + +.macro DISABLE_VBLANK_COPY + ld a, #1 + ld (__shadow_OAM_OFF), a +.endm + +.macro ENABLE_VBLANK_COPY + xor a + ld (__shadow_OAM_OFF), a +.endm + +.macro ADD_A_REG16 regH regL + add regL + ld regL, a + adc regH + sub regL + ld regH, a +.endm + +.macro MUL_DE_BY_A_RET_HL ?lbl1 ?lbl2 + ; Multiply DE by A, return result in HL; preserves: BC + ld hl, #0 +lbl1: + srl a + jp nc, lbl2 + add hl, de +lbl2: + sla e + rl d + or a + jp nz, lbl1 +.endm + +.macro DIV_PART divident divisor ?lbl + rl divident + rla + sub divisor + jr nc, lbl + add divisor +lbl: +.endm +.macro FAST_DIV8 divident divisor + ; returns modulus in A + .rept 8 + DIV_PART divident divisor + .endm + ld a, divident + cpl +.endm +.macro FAST_MOD8 divident divisor + ; returns modulus in A + .rept 8 + DIV_PART divident divisor + .endm +.endm diff --git a/gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_fill_rect.s b/gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_fill_rect.s new file mode 100644 index 00000000..665498fd --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_fill_rect.s @@ -0,0 +1,25 @@ + .include "global.s" + + .globl .fill_rect_xy + + .area _HOME + +; void fill_rect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint16_t tile) __z88dk_callee __preserves_regs(iyh, iyl); +_fill_rect:: + pop hl ; HL = ret + pop bc ; BC = YX + pop de ; DE = WH + ex (sp), hl ; HL = data + ex de, hl ; HL = WH, DE = data + + xor a + FAST_MOD8 b #.VDP_MAP_HEIGHT + + ld b, d + ld d, a + + ld a, c + ld c, e + ld e, a ; BC = data, DE = YX + + jp .fill_rect_xy diff --git a/gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_fill_rect_xy.s b/gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_fill_rect_xy.s new file mode 100644 index 00000000..3dd0d1f1 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_fill_rect_xy.s @@ -0,0 +1,93 @@ + .include "global.s" + + .title "VRAM utilities" + .module VRAMUtils + + .ez80 + + .area _HOME + + ;; Set background tile table from (BC) at XY = DE of size WH = HL +.fill_rect_xy:: + push hl + ld hl, #.VDP_TILEMAP + + ;; Set background tile from (BC) at YX = DE, size WH on stack, to VRAM from address (HL) +.fill_rect_xy_tt:: + push bc ; Store source + + ld a, d + rrca ; rrca(3) == rlca(5) + rrca + rrca + ld d, a + and #0x07 + add h + ld b, a + ld a, #0xE0 + and d + add e + ld c, a ; dest BC = HL + ((0x20 * Y) + X + + ld a, b + cp #>(.VDP_TILEMAP+0x0300) + jr c, 5$ + ld b, #>.VDP_TILEMAP +5$: + pop hl ; HL = source + pop de ; DE = HW + push ix ; save IX + push de ; store HW + ld ixh, b + ld ixl, c + push ix ; store dest + + DISABLE_VBLANK_COPY ; switch OFF copy shadow SAT + +1$: ; copy H rows + VDP_WRITE_CMD ixh, ixl + ld c, #.VDP_DATA +2$: ; copy W tiles + out (c), l + + ld a, ixl + and #0x1F + inc a + bit 5, a + jp z, 3$ + and #0x1F + ld b, a + ld a, ixl + and #0xE0 + or b + ld ixl, a + VDP_WRITE_CMD ixh, ixl + dec e + jp nz, 2$ + jp 7$ +3$: + inc ixl + dec e + jp nz, 2$ +7$: + pop ix + pop de + + dec d + jr z, 6$ + + push de + + ld bc, #0x20 + add ix, bc + ld a, ixh + cp #>(.VDP_TILEMAP+0x0300) + jp c, 4$ + ld ixh, #>.VDP_TILEMAP +4$: + push ix + jp 1$ +6$: + ENABLE_VBLANK_COPY ; switch ON copy shadow SAT + pop ix ; restore IX + ret
\ No newline at end of file diff --git a/gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_int.s b/gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_int.s new file mode 100644 index 00000000..195867c5 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_int.s @@ -0,0 +1,185 @@ + .include "global.s" + + .title "INT Handler" + .module INTHandler + + .globl .sys_time, .vbl_done + .globl .OUTI128, __shadow_OAM_base + + .area _GSINIT + + ld a, i + ld a, #0xc3 + di + ld (.LS_INT_VECTOR), a + ld hl, #_INT_ISR + jp po, 1$ + ei +1$: + ld (.LS_INT_VECTOR + 1), hl + + .area _HOME + +_INT_ISR:: + push af + push bc + push de + push hl + push iy + push ix + + in a, (.VDP_STAT) + and #.STATF_INT_VBL + jp z, 2$ + ;; handle VBlank + + ld hl, (.sys_time) + inc hl + ld (.sys_time), hl + + ld a, #1 + ld (.vbl_done), a + + ;; transfer shadow OAM + ld a, (__shadow_OAM_OFF) ; check transfer is OFF + or a + jp nz, 1$ + ld hl, #__shadow_OAM_base + ld h, (hl) + ld l, a ; a == 0 here + or h + jp z, 1$ + + ld c, #.VDP_CMD + ld a, #<.VDP_SAT + out (c), a + ld a, #>.VDP_SAT + out (c), a + dec c ; c == .VDP_DATA + call .OUTI128 +1$: + + ;; call user-defined VBlank handlers + ld hl, (.VBLANK_HANDLER0) + ld a, h + or l + jp z, 2$ + CALL_HL + + ld hl, (.VBLANK_HANDLER1) + ld a, h + or l + jp z, 2$ + CALL_HL + + ld hl, (.VBLANK_HANDLER2) + ld a, h + or l + jp z, 2$ + CALL_HL + +2$: + pop ix + pop iy + pop hl + pop de + pop bc + pop af + ei + reti + +; void add_VBL(int_handler h) __z88dk_fastcall __preserves_regs(d, e, iyh, iyl); +_add_VBL:: + ld b, h + ld c, l + +.add_VBL:: + ld hl, #.VBLANK_HANDLER0 + + ;; Add interrupt routine in BC to the interrupt list in HL +.add_int:: +1$: + ld a, (hl) + inc hl + or (hl) + jr z, 2$ + inc hl + jr 1$ +2$: + ld (hl), b + dec hl + ld (hl), c + ret + +; void remove_VBL(int_handler h) __z88dk_fastcall __preserves_regs(iyh, iyl); +_remove_VBL:: + ld b, h + ld c, l + + ;; Remove interrupt routine in BC from the VBL interrupt list + ;; falldown to .remove_int +.remove_VBL:: + ld hl, #.VBLANK_HANDLER0 + + ;; Remove interrupt BC from interrupt list HL if it exists + ;; Abort if a 0000 is found (end of list) +.remove_int:: +1$: + ld e, (hl) + inc hl + ld d, (hl) + inc hl + ld a, e + or d + ret z ; No interrupt found + + ld a, e + cp c + jr nz, 1$ + + ld a, d + cp b + jr nz, 1$ + + ld d, h + ld e, l + dec de + dec de + + ;; Now do a memcpy from here until the end of the list +2$: + ld a, (hl) + ldi + or (hl) + ldi + jr nz, 2$ + +_remove_LCD:: +.remove_LCD:: +_add_LCD:: +.add_LCD:: +_remove_TIM:: +_remove_SIO:: +_remove_JOY:: +_add_TIM:: +_add_SIO:: +_add_JOY:: +.empty_function: + ret + + .area _INITIALIZED + +.VBLANK_HANDLER0: + .ds 0x02 +.VBLANK_HANDLER1: + .ds 0x02 +.VBLANK_HANDLER2: + .ds 0x02 + .ds 0x02 + + .area _INITIALIZER + + .dw 0x0000 + .dw 0x0000 + .dw 0x0000 + .dw 0x0000 diff --git a/gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_metasprites.s b/gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_metasprites.s new file mode 100644 index 00000000..57b5bbcd --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_metasprites.s @@ -0,0 +1,77 @@ + .include "global.s" + + .title "Metasprites" + .module Metasprites + + .area _DATA + +___current_metasprite:: + .ds 0x02 +___current_base_tile:: + .ds 0x01 + + .area _CODE + +; uint8_t __move_metasprite(uint8_t id, uint8_t x, uint8_t y) __z88dk_callee __preserves_regs(iyh,iyl); + +___move_metasprite:: + ld hl, #4 + add hl, sp + + ld b, (hl) + dec hl + ld c, (hl) + dec hl + ld e, (hl) + + ld hl, (___current_metasprite) + + ld a, (___render_shadow_OAM) + ld d, a +1$: + ld a, (hl) ; dy + inc hl + cp #0x80 + jp z, 2$ + add b + ld b, a + cp #0xD0 + jp nz, 3$ + ld a, #0xC0 +3$: + ld (de), a + inc e + + ld a, (hl) ; dx + inc hl + add c + ld c, a + ld (de), a + inc e + + ld a, (___current_base_tile) + add (hl) ; tile + inc hl + ld (de), a + inc e + + ld a, (hl) + inc hl + ld (de), a + inc e + + jp 1$ +2$: + pop hl + pop bc + inc sp + push hl + ld a, e + srl a + srl a + sub c + ld l, a + ret + +___render_shadow_OAM:: + .db #>_shadow_OAM diff --git a/gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_metasprites_hide.s b/gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_metasprites_hide.s new file mode 100644 index 00000000..93ca1021 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_metasprites_hide.s @@ -0,0 +1,37 @@ + .include "global.s" + + .title "Metasprites" + .module Metasprites + + .globl ___current_metasprite, ___render_shadow_OAM + + .area _CODE + + +; void __hide_metasprite(uint8_t id) __z88dk_fastcall __preserves_regs(iyh,iyl); + +___hide_metasprite:: + ld e, l + + ld hl, (___current_metasprite) + + ld bc, #4 + + ld a, (___render_shadow_OAM) + ld d, a +1$: + ld a, (hl) + cp #0x80 + ret z + + ld a, #0x1F + cp e + ret c + + add hl, bc + + ld a, #0xC0 + ld (de), a + + inc e + jp 1$ diff --git a/gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_metasprites_hide_spr.s b/gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_metasprites_hide_spr.s new file mode 100644 index 00000000..32551556 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_metasprites_hide_spr.s @@ -0,0 +1,39 @@ + .include "global.s" + + .title "Metasprites" + .module Metasprites + + .globl ___render_shadow_OAM + + .area _CODE + +; void hide_sprites_range(UINT8 from, UINT8 to) __z88dk_callee __preserves_regs(iyh,iyl); + +_hide_sprites_range:: + pop hl + pop de + push hl + + ld a, d + cp #(32+1) + ret nc + + sub e + ret c + ret z + ld b, a + + ld a, e + add a + add a + ld l, a + + ld a, (___render_shadow_OAM) + ld h, a + ld de, #4 +1$: + ld (hl), #0xC0 + add hl, de + djnz 1$ + + ret diff --git a/gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_refresh_oam.s b/gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_refresh_oam.s new file mode 100644 index 00000000..9e175730 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_refresh_oam.s @@ -0,0 +1,27 @@ + .include "global.s" + + .title "VRAM utilities" + .module VRAMUtils + + .globl __shadow_OAM_base + + .ez80 + + .area _HOME + +; void refresh_OAM(); +_refresh_OAM:: + DISABLE_VBLANK_COPY ; switch OFF copy shadow SAT + ld de, #.VDP_SAT + VDP_WRITE_CMD d, e + + ld h, #>_shadow_OAM + ld l, #0 + ld c, #.VDP_DATA + ld b, #128 +1$: + outi + jp nz, 1$ + + ENABLE_VBLANK_COPY ; switch OFF copy shadow SAT + ret
\ No newline at end of file diff --git a/gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_set_1bpp_data.s b/gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_set_1bpp_data.s new file mode 100644 index 00000000..c88669a5 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_set_1bpp_data.s @@ -0,0 +1,77 @@ + .include "global.s" + + .title "VRAM utilities" + .module VRAMUtils + + .ez80 + + .area _HOME + +; void set_tile_1bpp_data(uint16_t start, uint16_t ntiles, const void *src, uint16_t colors) __z88dk_callee; +_set_tile_1bpp_data:: + pop af + pop hl + pop iy + pop de + pop bc + push af + + push ix + ld ixl, c + + add hl, hl + add hl, hl + add hl, hl + + push hl + + ld bc, #.VDP_COLORDATA0 + add hl, bc + ex (sp), hl + + ld bc, #.VDP_TILEDATA0 + add hl, bc + + DISABLE_VBLANK_COPY ; switch OFF copy shadow SAT + + ld c, #.VDP_DATA + inc iyh + inc iyl + jr 2$ + +1$: + VDP_WRITE_CMD h, l + ex de, hl + ld b, #8 +3$: + outi + jr nz, 3$ + ex de, hl + + ld a, #8 + ADD_A_REG16 h, l + ex (sp), hl + + VDP_WRITE_CMD h, l + ld b, #8 + ld a, ixl +4$: + out (c), a + inc hl + dec b + jr nz, 4$ + + ex (sp), hl +2$: + dec iyl + jr nz, 1$ + + dec iyh + jr nz, 1$ + + ENABLE_VBLANK_COPY ; switch ON copy shadow SAT + + pop hl + pop ix + + ret diff --git a/gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_set_1bpp_sprite_data.s b/gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_set_1bpp_sprite_data.s new file mode 100644 index 00000000..8ddf727d --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_set_1bpp_sprite_data.s @@ -0,0 +1,52 @@ + .include "global.s" + + .title "VRAM utilities" + .module VRAMUtils + + .ez80 + + .area _HOME + +; void set_sprite_1bpp_data(uint16_t start, uint16_t ntiles, const void *src) __z88dk_callee; +_set_sprite_1bpp_data:: + pop af + pop hl + pop iy + pop de + push af + + add hl, hl + add hl, hl + add hl, hl + + ld bc, #.VDP_SPRDATA0 + add hl, bc + + DISABLE_VBLANK_COPY ; switch OFF copy shadow SAT + + VDP_WRITE_CMD h, l + + ex de, hl + + ld d, iyh + ld e, iyl + + ld c, #.VDP_DATA + inc d + inc e + jr 2$ +1$: + ld b, #8 +3$: + outi + jr nz, 3$ +2$: + dec e + jr nz, 1$ + + dec d + jr nz, 1$ + + ENABLE_VBLANK_COPY ; switch ON copy shadow SAT + + ret diff --git a/gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_set_native_data.s b/gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_set_native_data.s new file mode 100644 index 00000000..5c758ecf --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_set_native_data.s @@ -0,0 +1,73 @@ + .include "global.s" + + .title "VRAM utilities" + .module VRAMUtils + .ez80 + + .area _HOME + +; void set_native_tile_data(uint16_t start, uint16_t ntiles, const void *src) __z88dk_callee +_set_native_tile_data:: + pop bc + pop hl + pop iy + pop de + push bc + + add hl, hl + add hl, hl + add hl, hl + + push hl + + ld bc, #.VDP_COLORDATA0 + add hl, bc + ex (sp), hl + + ld bc, #.VDP_TILEDATA0 + add hl, bc + + DISABLE_VBLANK_COPY ; switch OFF copy shadow SAT + + ld c, #.VDP_DATA + inc iyh + inc iyl + jr 2$ + +1$: + VDP_WRITE_CMD h, l + ex de, hl + ld b, #8 +3$: + outi + jr nz, 3$ + ex de, hl + + ld a, #8 + ADD_A_REG16 h, l + ex (sp), hl + + VDP_WRITE_CMD h, l + ex de, hl + ld b, #8 +4$: + outi + jr nz, 4$ + ex de, hl + + ld a, #8 + ADD_A_REG16 h, l + ex (sp), hl + +2$: + dec iyl + jr nz, 1$ + + dec iyh + jr nz, 1$ + + pop hl + + ENABLE_VBLANK_COPY ; switch ON copy shadow SAT + + ret diff --git a/gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_set_tile_map.s b/gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_set_tile_map.s new file mode 100644 index 00000000..119bd742 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_set_tile_map.s @@ -0,0 +1,29 @@ + .include "global.s" + + .title "VRAM utilities" + .module VRAMUtils + + .globl .set_tile_map_xy + + .area _HOME + +; void set_tile_map(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t *tiles) __z88dk_callee __preserves_regs(iyh, iyl); +_set_tile_map:: + pop hl ; HL = ret + pop bc ; BC = YX + pop de ; DE = WH + ex (sp), hl ; HL = data + ex de, hl ; HL = WH, DE = data + + xor a + FAST_MOD8 b #.VDP_MAP_HEIGHT + + ld b, d + ld d, a + + ld a, c + ld c, e + ld e, a ; BC = data, DE = YX + + jp .set_tile_map_xy + diff --git a/gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_set_tile_map_xy.s b/gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_set_tile_map_xy.s new file mode 100644 index 00000000..f1419a69 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_set_tile_map_xy.s @@ -0,0 +1,100 @@ + .include "global.s" + + .title "VRAM utilities" + .module VRAMUtils + + .ez80 + + .area _HOME + + ;; Set background tile table from (BC) at XY = DE of size WH = HL +.set_tile_map_xy:: + push hl + ld hl, #.VDP_TILEMAP + + ;; Set background tile from (BC) at YX = DE, size WH on stack, to VRAM from address (HL) +.set_tile_map_xy_tt:: + push bc ; Store source + + ld a, d + rrca ; rrca(3) == rlca(5) + rrca + rrca + ld d, a + and #0x07 + add h + ld b, a + ld a, #0xE0 + and d + add e + ld c, a ; dest BC = HL + ((0x20 * Y) + X + + ld a, b + cp #>(.VDP_TILEMAP+0x0300) + jr c, 5$ + ld b, #>.VDP_TILEMAP +5$: + pop hl ; HL = source + pop de ; DE = HW + push ix ; save IX + push de ; store HW + ld ixh, b + ld ixl, c + push ix ; store dest + + DISABLE_VBLANK_COPY ; switch OFF copy shadow SAT + +1$: ; copy H rows + VDP_WRITE_CMD ixh, ixl + ld c, #.VDP_DATA +2$: ; copy W tiles + ld a, (__map_tile_offset) + add (hl) + out (c), a + inc hl + dec b + + ld a, ixl + and #0x1F + inc a + bit 5, a + jp z, 3$ + and #0x1F + ld b, a + ld a, ixl + and #0xE0 + or b + ld ixl, a + VDP_WRITE_CMD ixh, ixl + dec e + jp nz, 2$ + jp 7$ +3$: + inc ixl + dec e + jp nz, 2$ +7$: + pop ix + pop de + + dec d + jr z, 6$ + + push de + + ld bc, #0x20 + add ix, bc + ld a, ixh + cp #>(.VDP_TILEMAP+0x0300) + jp c, 4$ + ld ixh, #>.VDP_TILEMAP +4$: + push ix + jp 1$ +6$: + ENABLE_VBLANK_COPY ; switch ON copy shadow SAT + pop ix ; restore IX + ret + +__map_tile_offset:: + .db 0x00 diff --git a/gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_write_vdp.s b/gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_write_vdp.s new file mode 100644 index 00000000..53f7c9b4 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_write_vdp.s @@ -0,0 +1,14 @@ + .include "global.s" + + .title "write vdp" + .module write_vdp + + .area _CODE + +_WRITE_VDP_CMD:: + VDP_WRITE_CMD h, l + ret +_WRITE_VDP_DATA:: + VDP_WRITE_DATA h, l + ret +
\ No newline at end of file diff --git a/gbdk/gbdk-lib/libc/targets/z80/msxdos/pad.s b/gbdk/gbdk-lib/libc/targets/z80/msxdos/pad.s new file mode 100644 index 00000000..ce73c347 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/msxdos/pad.s @@ -0,0 +1,66 @@ + .include "global.s" + + .title "JOYPad utilities" + .module JOYPad + .area _HOME + + ;; Get Keypad Button Status +_joypad:: +.jpad:: + ld a, #0x06 ; ... <code> <caps> <graph> <ctrl> <shift> + out (.KBD_SELECT_ROW), a + in a, (.KBD_INPUT) + cpl + + rrca + rl l + rrca + rrca + rl l ; shift graph + + ld a, #0x07 ; <ret>, ... + out (.KBD_SELECT_ROW), a + in a, (.KBD_INPUT) + cpl + + rlca + rl l + rl l + ld a, #0b00001110 + and l + ld l, a + + ld a, #0x08 ; <r><d><u><l><del><ins><home><space> + out (.KBD_SELECT_ROW), a + in a, (.KBD_INPUT) + cpl + and #0b11110001 + + or l + ld l, a ; <r><d><u><l><shift><graph><enter><space> + + ret + + ;; Wait until all buttons have been released +.padup:: +_waitpadup:: +1$: + ld h,#0x7f ; wait for .jpad return zero 127 times in a row +2$: + call .jpad + or a ; have all buttons been released? + jr nz,1$ ; not yet + + dec h + jr nz,2$ + + ret + + ;; Wait for the key to be pressed +_waitpad:: +.wait_pad:: +1$: + call .jpad ; read pad + and l ; compare with mask? + jr z,1$ ; loop if no intersection + ret diff --git a/gbdk/gbdk-lib/libc/targets/z80/outi.s b/gbdk/gbdk-lib/libc/targets/z80/outi.s new file mode 100644 index 00000000..6a61c17a --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/outi.s @@ -0,0 +1,20 @@ + .include "global.s" + + .title "VRAM utilities" + .module VRAMUtils + .area _HOME + +.OUTI128:: ; _OUTI128 label points to a block of 128 OUTI and a RET + .rept 64 + outi + .endm +.OUTI64:: ; _OUTI64 label points to a block of 64 OUTI and a RET + .rept 32 + outi + .endm +.OUTI32:: ; _OUTI32 label points to a block of 32 OUTI and a RET + .rept 32 + outi + .endm +.OUTI_END:: ; _outi_block label points to END of OUTI block + ret diff --git a/gbdk/gbdk-lib/libc/targets/z80/putchar.s b/gbdk/gbdk-lib/libc/targets/z80/putchar.s new file mode 100644 index 00000000..22c5ce98 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/putchar.s @@ -0,0 +1,126 @@ + .include "global.s" + + .title "putchar" + .module putchar + + .globl font_current, font_set, font_load_ibm + .globl .scroll_viewport + + ; Structure offsets + sfont_handle_sizeof = 3 + sfont_handle_font = 1 + sfont_handle_first_tile = 0 + + ; Encoding types - lower 2 bits of font + FONT_256ENCODING = 0 + FONT_128ENCODING = 1 + FONT_NOENCODING = 2 + + .area _INITIALIZED + ; The current font +.curx:: + .ds 1 +.cury:: + .ds 1 + + .area _INITIALIZER + .db #.SCREEN_X_OFS ; .curx + .db #.SCREEN_Y_OFS ; .cury + + .area _HOME + +_setchar:: +_putchar:: + pop hl + pop de + push de + push hl + + ld a, e + cp #.CR + jr nz, 0$ + + ld a, #.SCREEN_X_OFS + ld (.curx), a + jp 2$ +0$: + ld hl, (font_current+sfont_handle_font) + ld a, h + or l + jr nz, 6$ + + push de + call font_load_ibm + ld a, h + or l + ret z + call font_set + pop de + ld hl, (font_current+sfont_handle_font) +6$: + ld a, (hl) + and #3 + cp #FONT_NOENCODING + jr z, 4$ + inc hl + inc hl + ld d, #0 + add hl, de + ld e, (hl) +4$: + ld a, (font_current) + add a, e + ld e, a + + ld a, (.cury) + ld l, a + ld h, #0 + add hl, hl + add hl, hl + add hl, hl + add hl, hl + add hl, hl + add hl, hl + ld a, (.curx) + add a + add l + ld l, a + adc h + sub l + ld h, a + + ld bc, #.VDP_TILEMAP + add hl, bc + + DISABLE_VBLANK_COPY ; switch OFF copy shadow SAT + WRITE_VDP_CMD_HL + + ld a, e + out (.VDP_DATA), a + VDP_DELAY + xor a + out (.VDP_DATA), a + + ENABLE_VBLANK_COPY ; switch ON copy shadow SAT + + ld a, (.curx) + inc a + cp #(.SCREEN_X_OFS + .SCREEN_WIDTH) + jr c, 5$ + ld a, #.SCREEN_X_OFS +5$: + ld (.curx), a + ret nz +2$: + ld a, (.cury) + inc a + cp #(.SCREEN_Y_OFS + .SCREEN_HEIGHT) + jr c, 3$ + ld a, #(.SCREEN_Y_OFS + .SCREEN_HEIGHT - 1) + ld (.cury), a + + call .scroll_viewport + ret +3$: + ld (.cury), a + ret diff --git a/gbdk/gbdk-lib/libc/targets/z80/rle_decompress.s b/gbdk/gbdk-lib/libc/targets/z80/rle_decompress.s new file mode 100644 index 00000000..d34d0bf3 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/rle_decompress.s @@ -0,0 +1,100 @@ + .include "global.s" + + .module RLE_DECOMPRESS + + .area _DATA + +rle_cursor: + .ds 0x02 +rle_counter: + .ds 0x01 +rle_current: + .ds 0x01 + + .area _CODE + +_rle_init:: + ld (rle_cursor), hl + xor a + ld hl, #rle_counter + ld (hl), a + inc hl + ld (hl), a + ld l, #1 + ret + +_rle_decompress:: + ;; Pop the return address + pop hl + pop de + dec sp + ex (sp), hl + ld b, h + + ld hl, (rle_cursor) + + ld a, l + or h + ret z + + ld a, (rle_counter) + or a + ld c, a + jr z, 1$ + + ld a, (rle_current) + bit 7, c + jr nz, 10$ + jr 11$ +1$: + ;; Fetch the run + ld c, (hl) + inc hl + ;; Negative means a run +8$: + bit 7, c + jr z, 2$ + ;; Expanding a run + ld a, (hl) + inc hl +3$: + ld (de), a + inc de + + dec b + jr z, 6$ +10$: + inc c + jr NZ, 3$ + jr 1$ +2$: + ;; Zero means end of a block + inc c + dec c + jr z, 4$ + ;; Expanding a block +5$: + ldi + inc bc + + dec b + jr z, 6$ +11$: + dec c + jr NZ, 5$ + jr 1$ +4$: + ;; save state and exit + ld hl, #0 + ld (rle_cursor), hl + ld (rle_counter), hl + ret +6$: + ;; save state and exit + ld (rle_cursor), hl + ld hl, #rle_counter + ld (hl), c + inc hl + ld (hl), a + ld l, #1 + ret
\ No newline at end of file diff --git a/gbdk/gbdk-lib/libc/targets/z80/scroll.s b/gbdk/gbdk-lib/libc/targets/z80/scroll.s new file mode 100644 index 00000000..47306d6b --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/scroll.s @@ -0,0 +1,61 @@ + .include "global.s" + + .title "console utilities" + .module ConsoleUtils + + .globl .curx, .cury + + .area _HOME + +.scroll_viewport:: + DISABLE_VBLANK_COPY ; switch OFF copy shadow SAT + ld hl, #(.VDP_TILEMAP + ((.SCREEN_Y_OFS + 1) * .VDP_MAP_WIDTH * 2)) + + ld bc, #((.SCREEN_HEIGHT - 1) * .VDP_MAP_WIDTH * 2) + inc b + inc c + jr 1$ +2$: + res 6, h + WRITE_VDP_CMD_HL + nop + nop + in a, (.VDP_DATA) + ld e, a + + ld a, l + sub #(.VDP_MAP_WIDTH * 2) + ld l, a + ld a, h + sbc #0 + ld h, a + + set 6, h + WRITE_VDP_CMD_HL + nop + ld a, e + out (.VDP_DATA), a + + ld a, #((.VDP_MAP_WIDTH * 2) + 1) + add l + ld l, a + adc h + sub l + ld h, a + +1$: + dec c + jr nz, 2$ + djnz 2$ + + ld hl, #(.VDP_TILEMAP + ((.SCREEN_Y_OFS + .SCREEN_HEIGHT - 1) * .VDP_MAP_WIDTH * 2)) + WRITE_VDP_CMD_HL + + ld hl, #.SPACE + ld b, #.VDP_MAP_WIDTH +3$: + WRITE_VDP_DATA_HL + djnz 3$ + + ENABLE_VBLANK_COPY ; switch ON copy shadow SAT + ret
\ No newline at end of file diff --git a/gbdk/gbdk-lib/libc/targets/z80/set_interrupts.s b/gbdk/gbdk-lib/libc/targets/z80/set_interrupts.s new file mode 100644 index 00000000..1135e529 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/set_interrupts.s @@ -0,0 +1,46 @@ + .include "global.s" + + .title "Set interrupts" + .module SetInterrupts + + .globl _shadow_VDP_R0 + .globl _shadow_VDP_R1 + + .area _HOME + +_set_interrupts:: + ld a, i + di + push af + + ld a, (_shadow_VDP_R1) + bit 0, l + jr z, 1$ + or #.R1_IE + jr 2$ +1$: + and #~.R1_IE +2$: + ld (_shadow_VDP_R1), a + out (.VDP_CMD), a + ld a, #.VDP_R1 + out (.VDP_CMD), a + + ld a, (_shadow_VDP_R0) + bit 1, l + jr z, 3$ + or #.R0_IE1 + jr 4$ +3$: + and #~.R0_IE1 +4$: + ld (_shadow_VDP_R0), a + out (.VDP_CMD), a + ld a, #.VDP_R0 + out (.VDP_CMD), a + + pop af + jp po, 5$ + ei +5$: + ret diff --git a/gbdk/gbdk-lib/libc/targets/z80/set_palette.s b/gbdk/gbdk-lib/libc/targets/z80/set_palette.s new file mode 100644 index 00000000..07579211 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/set_palette.s @@ -0,0 +1,23 @@ + ;; SMS palette routines + + .include "global.s" + + .title "CRAM SMS Palettes" + .module CRAMUtils + + .globl .CRT_DEFAULT_PALETTE, _set_palette + + .area _HOME + +_set_default_palette:: + ld hl, #.CRT_DEFAULT_PALETTE + push hl + ld hl, #0x0100 + push hl + call _set_palette + ld hl, #.CRT_DEFAULT_PALETTE + push hl + ld hl, #0x0101 + push hl + call _set_palette + ret diff --git a/gbdk/gbdk-lib/libc/targets/z80/set_tile.s b/gbdk/gbdk-lib/libc/targets/z80/set_tile.s new file mode 100644 index 00000000..9f2b410d --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/set_tile.s @@ -0,0 +1,70 @@ + .include "global.s" + + .title "VRAM utilities" + .module VRAMUtils + + .globl .coords_to_address + + .area _HOME + +; void set_vram_byte(uint8_t * addr, uint8_t v) __z88dk_callee __preserves_regs(iyh, iyl); +_set_vram_byte:: + pop de + pop hl + DISABLE_VBLANK_COPY + WRITE_VDP_CMD_HL + ex de, hl + dec sp + ex (sp), hl + ld a, h + out (.VDP_DATA), a + ENABLE_VBLANK_COPY + ret + +; uint8_t * set_attributed_tile_xy(uint8_t x, uint8_t y, uint16_t t) __z88dk_callee __preserves_regs(iyh, iyl); +_set_attributed_tile_xy:: + pop hl ; HL = ret + pop de ; DE = YX + ex (sp), hl ; HL = data + + ld a, d + + ld bc, #.VDP_TILEMAP + call .coords_to_address + ex de, hl + + DISABLE_VBLANK_COPY + WRITE_VDP_CMD_HL + + ld c, #.VDP_DATA + out (c), e + VDP_DELAY + out (c), d + + ENABLE_VBLANK_COPY + ret + +; uint8_t * set_tile_xy(uint8_t x, uint8_t y, uint8_t t) __z88dk_callee __preserves_regs(iyh, iyl); +_set_tile_xy:: + pop hl ; HL = ret + pop de ; DE = YX + dec sp + ex (sp), hl ; HL = data + + ld a, d + + ld bc, #.VDP_TILEMAP + call .coords_to_address + ex de, hl + + ld a, (.vdp_shift) + ADD_A_REG16 h, l + + DISABLE_VBLANK_COPY + WRITE_VDP_CMD_HL + + ld a, d + out (.VDP_DATA), a + + ENABLE_VBLANK_COPY + ret diff --git a/gbdk/gbdk-lib/libc/targets/z80/set_tile_map.s b/gbdk/gbdk-lib/libc/targets/z80/set_tile_map.s new file mode 100644 index 00000000..514106b9 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/set_tile_map.s @@ -0,0 +1,33 @@ + .include "global.s" + + .title "VRAM utilities" + .module VRAMUtils + + .globl .set_tile_map_xy + + .area _HOME + +; void set_tile_map(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t *tiles) __z88dk_callee __preserves_regs(iyh, iyl); +_set_tile_map:: + pop hl ; HL = ret + pop bc ; BC = YX + pop de ; DE = WH + ex (sp), hl ; HL = data + ex de, hl ; HL = WH, DE = data + + ld a, b + ld b, d + + add #.SCREEN_Y_OFS + ld d, a + xor a + FAST_MOD8 d #28 + ld d, a + + ld a, c + add #.SCREEN_X_OFS + and #0x1f + ld c, e + ld e, a ; BC = data, DE = YX + + jp .set_tile_map_xy diff --git a/gbdk/gbdk-lib/libc/targets/z80/set_tile_map_compat.s b/gbdk/gbdk-lib/libc/targets/z80/set_tile_map_compat.s new file mode 100644 index 00000000..5160ccd8 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/set_tile_map_compat.s @@ -0,0 +1,33 @@ + .include "global.s" + + .title "VRAM utilities" + .module VRAMUtils + + .globl .set_tile_map_xy + + .area _HOME + +; void set_tile_map(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t *tiles) __z88dk_callee __preserves_regs(iyh, iyl); +_set_tile_map_compat:: + pop hl ; HL = ret + pop bc ; BC = YX + pop de ; DE = WH + ex (sp), hl ; HL = data + ex de, hl ; HL = WH, DE = data + + ld a, b + ld b, d + + add #.SCREEN_Y_OFS + ld d, a + xor a + FAST_MOD8 d #28 + ld d, a + + ld a, c + add #.SCREEN_X_OFS + and #0x1f + ld c, e + ld e, a ; BC = data, DE = YX + + jp .set_tile_map_xy_compat diff --git a/gbdk/gbdk-lib/libc/targets/z80/set_tile_map_xy.s b/gbdk/gbdk-lib/libc/targets/z80/set_tile_map_xy.s new file mode 100644 index 00000000..7e028e2c --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/set_tile_map_xy.s @@ -0,0 +1,98 @@ + .include "global.s" + + .title "VRAM utilities" + .module VRAMUtils + + .ez80 + + .area _HOME + + ;; Set background tile table from (BC) at XY = DE of size WH = HL +.set_tile_map_xy:: + push hl + ld hl, #.VDP_TILEMAP + + ;; Set background tile from (BC) at YX = DE, size WH on stack, to VRAM from address (HL) +.set_tile_map_xy_tt:: + push bc ; Store source + + ld a, d + rrca ; rrca(2) == rlca(6) + rrca + ld d, a + and #0x07 + add h + ld b, a + ld a, #0xC0 + and d + sla e + add e + ld c, a ; dest BC = HL + ((0x20 * Y) * 2) + (X * 2) + + ld a, b + cp #>(.VDP_TILEMAP+0x0700) + jr c, 5$ + ld b, #>.VDP_TILEMAP +5$: + pop hl ; HL = source + pop de ; DE = HW + push ix ; save IX + push de ; store HW + + ld ixh, b + ld ixl, c + push ix ; store dest + + DISABLE_VBLANK_COPY ; switch OFF copy shadow SAT + +1$: ; copy H rows + VDP_WRITE_CMD ixh, ixl + ld c, #.VDP_DATA +2$: ; copy W tiles + outi + VDP_DELAY + outi + + ld a, ixl + and #0x3F + inc a + inc a + bit 6, a + jp z, 3$ + and #0x3F + ld b, a + ld a, ixl + and #0xC0 + or b + ld ixl, a + VDP_WRITE_CMD ixh, ixl + dec e + jp nz, 2$ + jp 7$ +3$: + inc ixl + inc ixl + dec e + jp nz, 2$ +7$: + pop ix + pop de + + dec d + jr z, 6$ + + push de + + ld bc, #0x40 + add ix, bc + ld a, ixh + cp #>(.VDP_TILEMAP+0x0700) + jp c, 4$ + ld ixh, #>.VDP_TILEMAP +4$: + push ix + jp 1$ +6$: + ENABLE_VBLANK_COPY ; switch ON copy shadow SAT + pop ix ; restore IX + ret
\ No newline at end of file diff --git a/gbdk/gbdk-lib/libc/targets/z80/set_tile_map_xy_compat.s b/gbdk/gbdk-lib/libc/targets/z80/set_tile_map_xy_compat.s new file mode 100644 index 00000000..eb630dc2 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/set_tile_map_xy_compat.s @@ -0,0 +1,115 @@ + .include "global.s" + + .globl .vdp_shift + + .title "VRAM utilities" + .module VRAMUtils + + .ez80 + + .area _INITIALIZED + +__map_tile_offset:: + .ds 0x01 + + .area _INITIALIZER + + .db 0x00 + + .area _HOME + + ;; Set background tile table from (BC) at XY = DE of size WH = HL +.set_tile_map_xy_compat:: + push hl + ld hl, #.VDP_TILEMAP + + ;; Set background tile from (BC) at YX = DE, size WH on stack, to VRAM from address (HL) +.set_tile_map_xy_tt_compat:: + push bc ; Store source + + ld a, d + rrca ; rrca(2) == rlca(6) + rrca + ld d, a + and #0x07 + add h + ld b, a + ld a, #0xC0 + and d + sla e + add e + ld hl, #.vdp_shift + add (hl) + ld c, a ; dest BC = HL + ((0x20 * Y) * 2) + (X * 2) + + ld a, b + cp #>(.VDP_TILEMAP+0x0700) + jr c, 5$ + ld b, #>.VDP_TILEMAP +5$: + pop hl ; HL = source + pop de ; DE = HW + push ix ; save IX + push de ; store HW + ld ixh, b + ld ixl, c + push ix ; store dest + + DISABLE_VBLANK_COPY ; switch OFF copy shadow SAT + +1$: ; copy H rows + VDP_WRITE_CMD ixh, ixl + ld c, #.VDP_DATA +2$: ; copy W tiles + ld a, (__map_tile_offset) + add (hl) + out (c), a + inc hl + dec b + jr 8$ ; delay +8$: + in a, (c) ; skip next byte + + ld a, ixl + and #0x3F + inc a + inc a + bit 6, a + jp z, 3$ + and #0x3F + ld b, a + ld a, ixl + and #0xC0 + or b + ld ixl, a + VDP_WRITE_CMD ixh, ixl + dec e + jp nz, 2$ + jp 7$ +3$: + inc ixl + inc ixl + dec e + jp nz, 2$ +7$: + pop ix + pop de + + dec d + jr z, 6$ + + push de + + ld bc, #0x40 + add ix, bc + ld a, ixh + cp #>(.VDP_TILEMAP+0x0700) + jp c, 4$ + ld ixh, #>.VDP_TILEMAP +4$: + push ix + jp 1$ +6$: + ENABLE_VBLANK_COPY ; switch ON copy shadow SAT + pop ix ; restore IX + ret
\ No newline at end of file diff --git a/gbdk/gbdk-lib/libc/targets/z80/set_tile_submap.s b/gbdk/gbdk-lib/libc/targets/z80/set_tile_submap.s new file mode 100644 index 00000000..198bf0d0 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/set_tile_submap.s @@ -0,0 +1,156 @@ + .include "global.s" + + .title "VRAM utilities" + .module VRAMUtils + + .ez80 + + .area _DATA + +.image_tile_width:: + .ds 0x01 + + .area _HOME + +; void set_tile_submap(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t map_w, const uint8_t *map) __z88dk_callee __preserves_regs(iyh, iyl); +_set_tile_submap:: + pop hl ; HL = ret + pop bc ; BC = YX + pop de ; DE = WH + + dec sp + pop af + sub e + ld (.image_tile_width), a ; .image_tile_width contains corrected width + + ex (sp), hl ; HL = data + ex de, hl ; HL = WH, DE = data + + push hl + push de + + add l + ld e, a + ld d, #0 + ld a, b + MUL_DE_BY_A_RET_HL + ld a, c + ADD_A_REG16 h, l + add hl, hl + + pop de + add hl, de + ex de, hl + + pop hl + + ld a, b + ld b, d + + add #.SCREEN_Y_OFS + ld d, a + xor a + FAST_MOD8 d #28 + ld d, a + + ld a, c + add #.SCREEN_X_OFS + and #0x1f + ld c, e + ld e, a ; BC = data, DE = YX + + ;; Set background tile table from (BC) at XY = DE of size WH = HL +.set_tile_submap_xy:: + push hl + ld hl, #.VDP_TILEMAP + + ;; Set background tile from (BC) at YX = DE, size WH on stack, to VRAM from address (HL) +.set_tile_submap_xy_tt:: + push bc ; Store source + + ld a, d + rrca ; rrca(2) == rlca(6) + rrca + ld d, a + and #0x07 + add h + ld b, a + ld a, #0xC0 + and d + sla e + add e + ld c, a ; dest BC = HL + ((0x20 * Y) * 2) + (X * 2) + + ld a, b + cp #>(.VDP_TILEMAP+0x0700) + jr c, 5$ + ld b, #>.VDP_TILEMAP +5$: + pop hl ; HL = source + pop de ; DE = HW + push ix ; save IX + push de ; store HW + + ld ixh, b + ld ixl, c + push ix ; store dest + + DISABLE_VBLANK_COPY ; switch OFF copy shadow SAT + +1$: ; copy H rows + VDP_WRITE_CMD ixh, ixl + ld c, #.VDP_DATA +2$: ; copy W tiles + outi + VDP_DELAY + outi + + ld a, ixl + and #0x3F + inc a + inc a + bit 6, a + jp z, 3$ + and #0x3F + ld b, a + ld a, ixl + and #0xC0 + or b + ld ixl, a + VDP_WRITE_CMD ixh, ixl + dec e + jp nz, 2$ + jp 7$ +3$: + inc ixl + inc ixl + dec e + jp nz, 2$ +7$: + pop ix + pop de + + dec d + jr z, 6$ + + push de + + ld b, #0 + ld a, (.image_tile_width) + ld c, a + add hl, bc + add hl, bc + + ld bc, #0x40 + add ix, bc + ld a, ixh + cp #>(.VDP_TILEMAP+0x0700) + jp c, 4$ + ld ixh, #>.VDP_TILEMAP +4$: + push ix + jp 1$ +6$: + ENABLE_VBLANK_COPY ; switch ON copy shadow SAT + pop ix ; restore IX + ret diff --git a/gbdk/gbdk-lib/libc/targets/z80/set_tile_submap_compat.s b/gbdk/gbdk-lib/libc/targets/z80/set_tile_submap_compat.s new file mode 100644 index 00000000..477dde97 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/set_tile_submap_compat.s @@ -0,0 +1,168 @@ + .include "global.s" + + .title "VRAM utilities" + .module VRAMUtils + + .ez80 + + .area _DATA + +.image_tile_width_compat:: + .ds 0x01 + + .area _INITIALIZED + +__submap_tile_offset:: + .ds 0x01 + + .area _INITIALIZER + + .db 0x00 + + .area _HOME + +; void set_tile_submap_compat(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t map_w, const uint8_t *map) __z88dk_callee __preserves_regs(iyh, iyl); +_set_tile_submap_compat:: + pop hl ; HL = ret + pop bc ; BC = YX + pop de ; DE = WH + + dec sp + pop af + sub e + ld (.image_tile_width_compat), a ; .image_tile_width_compat contains corrected width + + ex (sp), hl ; HL = data + ex de, hl ; HL = WH, DE = data + + push hl + push de + + add l + ld e, a + ld d, #0 + ld a, b + MUL_DE_BY_A_RET_HL + ld a, c + ADD_A_REG16 h, l + + pop de + add hl, de + ex de, hl + + pop hl + + ld a, b + ld b, d + + add #.SCREEN_Y_OFS + ld d, a + xor a + FAST_MOD8 d #28 + ld d, a + + ld a, c + add #.SCREEN_X_OFS + and #0x1f + ld c, e + ld e, a ; BC = data, DE = YX + + ;; Set background tile table from (BC) at XY = DE of size WH = HL +.set_tile_submap_xy_compat:: + push hl + ld hl, #.VDP_TILEMAP + + ;; Set background tile from (BC) at YX = DE, size WH on stack, to VRAM from address (HL) +.set_tile_submap_xy_tt_compat:: + push bc ; Store source + + ld a, d + rrca ; rrca(2) == rlca(6) + rrca + ld d, a + and #0x07 + add h + ld b, a + ld a, #0xC0 + and d + sla e + add e + ld hl, #.vdp_shift + add (hl) + ld c, a ; dest BC = HL + ((0x20 * Y) * 2) + (X * 2) + + ld a, b + cp #>(.VDP_TILEMAP+0x0700) + jr c, 5$ + ld b, #>.VDP_TILEMAP +5$: + pop hl ; HL = source + pop de ; DE = HW + push ix ; save IX + push de ; store HW + + ld ixh, b + ld ixl, c + push ix ; store dest + + DISABLE_VBLANK_COPY ; switch OFF copy shadow SAT + +1$: ; copy H rows + VDP_WRITE_CMD ixh, ixl + ld c, #.VDP_DATA +2$: ; copy W tiles + ld a, (__map_tile_offset) + add (hl) + out (c), a + inc hl + dec b + jr 8$ ; delay +8$: + in a, (c) ; skip next byte + + ld a, ixl + and #0x3F + inc a + inc a + bit 6, a + jp z, 3$ + and #0x3F + ld b, a + ld a, ixl + and #0xC0 + or b + ld ixl, a + VDP_WRITE_CMD ixh, ixl + dec e + jp nz, 2$ + jp 7$ +3$: + inc ixl + inc ixl + dec e + jp nz, 2$ +7$: + pop ix + pop de + + dec d + jr z, 6$ + + push de + + ld a, (.image_tile_width_compat) + ADD_A_REG16 h, l + + ld bc, #0x40 + add ix, bc + ld a, ixh + cp #>(.VDP_TILEMAP+0x0700) + jp c, 4$ + ld ixh, #>.VDP_TILEMAP +4$: + push ix + jp 1$ +6$: + ENABLE_VBLANK_COPY ; switch ON copy shadow SAT + pop ix ; restore IX + ret diff --git a/gbdk/gbdk-lib/libc/targets/z80/sms/Makefile b/gbdk/gbdk-lib/libc/targets/z80/sms/Makefile new file mode 100644 index 00000000..34074067 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/sms/Makefile @@ -0,0 +1,44 @@ +# GB specific Makefile + +TOPDIR = ../../../.. + +THIS = sms +PORT = z80 + +CSRC = crlf.c + +ASSRC = set_interrupts.s \ + outi.s vmemcpy.s \ + sms_refresh_oam.s \ + sms_set_native_data.s sms_set_1bpp_data.s sms_set_2bpp_data.s \ + set_tile_map.s set_tile_map_xy.s set_tile_map_compat.s set_tile_map_xy_compat.s \ + set_tile_submap.s set_tile_submap_compat.s \ + coords_to_address.s \ + set_tile.s \ + sms_fill_rect.s sms_fill_rect_xy.s sms_fill_rect_compat.s sms_fill_rect_xy_compat.s \ + sms_metasprites.s sms_metasprites_hide.s sms_metasprites_hide_spr.s \ + f_ibm_full.s f_ibm_sh.s f_italic.s f_min.s f_spect.s \ + font.s color.s \ + putchar.s \ + scroll.s cls.s gotoxy.s \ + palette.s set_palette.s \ + pad.s pad_ex.s \ + sms_int.s nmi.s \ + mode.s clock.s \ + delay.s \ + emu_debug_printf.s \ + memset_small.s \ + far_ptr.s \ + gb_decompress.s \ + rle_decompress.s \ + heap.s \ + __sdcc_bcall.s \ + crt0.s + +CRT0 = crt0.s + +include $(TOPDIR)/Makefile.common + +AS = $(AS_Z80) + +include ../../../Makefile.platform diff --git a/gbdk/gbdk-lib/libc/targets/z80/sms/__sdcc_bcall.s b/gbdk/gbdk-lib/libc/targets/z80/sms/__sdcc_bcall.s new file mode 100644 index 00000000..60ebd504 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/sms/__sdcc_bcall.s @@ -0,0 +1,68 @@ + .include "global.s" + + .area _CODE + + .globl ___sdcc_bcall + .globl ___sdcc_bcall_abc + .globl ___sdcc_bcall_ehl +; +; trampoline to call banked functions +; used when legacy banking is enabled only +; Usage: +; call ___sdcc_bcall +; .dw <function> +; .dw <function_bank> +; +___sdcc_bcall:: + ex (sp), hl + ld c, (hl) + inc hl + ld b, (hl) + inc hl + ld a, (hl) + inc hl + inc hl + ex (sp), hl +; +; trampoline to call banked functions with __z88dk_fastcall calling convention +; Usage: +; ld a, #<function_bank> +; ld bc, #<function> +; call ___sdcc_bcall_abc +; +___sdcc_bcall_abc:: + push hl + ld l, a + ld a, (#.MAP_FRAME1) + ld h, a + ld a, l + ld (#.MAP_FRAME1), a + ex (sp), hl + inc sp + call ___sdcc_bjump_abc + dec sp + pop af + ld (#.MAP_FRAME1), a + ret +; +___sdcc_bjump_abc: + push bc + ret +; +; default trampoline to call banked functions +; Usage: +; ld e, #<function_bank> +; ld hl, #<function> +; call ___sdcc_bcall_ehl +; +___sdcc_bcall_ehl:: + ld a, (#.MAP_FRAME1) + push af + inc sp + ld a, e + ld (#.MAP_FRAME1), a + CALL_HL + dec sp + pop af + ld (#.MAP_FRAME1), a + ret diff --git a/gbdk/gbdk-lib/libc/targets/z80/sms/crlf.c b/gbdk/gbdk-lib/libc/targets/z80/sms/crlf.c new file mode 100644 index 00000000..aca6ec82 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/sms/crlf.c @@ -0,0 +1 @@ +const char * const __crlf = "\n";
\ No newline at end of file diff --git a/gbdk/gbdk-lib/libc/targets/z80/sms/crt0.s b/gbdk/gbdk-lib/libc/targets/z80/sms/crt0.s new file mode 100644 index 00000000..55823330 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/sms/crt0.s @@ -0,0 +1,275 @@ + .include "global.s" + + .title "Runtime" + .module Runtime + .area _HEADER (ABS) + + .globl _set_default_palette + + .org 0x00 ; Reset 00h + di ; disable interrupt + im 1 ; interrupt mode 1 (this won't change) + jp .init + +; .org 0x08 ; --profile handler + + .org 0x10 ; RST 0x10: VDP_WRITE_CMD + +_WRITE_VDP_CMD:: + VDP_WRITE_CMD h, l + ret + +; .org 0x18 ; unusable + + .org 0x20 ; RST 0x20: VDP_WRITE_DATA + +_WRITE_VDP_DATA:: + VDP_WRITE_DATA h, l + ret + +; .org 0x28 ; unusable + + .org 0x30 ; RST 0x30: call HL +.call_hl:: + jp (HL) + + .org 0x38 ; handle IRQ + jp _INT_ISR + + .org 0x66 ; handle NMI + jp _NMI_ISR + + .org 0x80 + +.init:: + ld sp, #.STACK ; set stack pointer at end of RAM + + ld a, (#.BIOS) + push af + + xor a + ld bc, #l__DATA + ld hl, #s__DATA + call .memset_simple ; initialize veriables in RAM with zero + + pop af + ld (#__BIOS), a ; save BIOS value + + ld hl, #_shadow_OAM + ld de, #(_shadow_OAM + 1) + ld bc, #64 + ld (hl), #0xc0 + ldir + ld (hl), #0 + ld bc, #(128 - 1) + ldir + + ld hl,#0x0000 ; initialize mappers + ld (#.RAM_CONTROL),hl ; [.RAM_CONTROL]=$00, [.MAP_FRAME0]=$00 + ld hl,#0x0201 + ld (#.MAP_FRAME1),hl ; [.MAP_FRAME1]=$01, [.MAP_FRAME2]=$02 + + ;; Initialise global variables + call .gsinit + + ;; Initialize VDP + ld c, #.VDP_CMD + ld b, #(.shadow_VDP_end - .shadow_VDP) + ld hl,#(.shadow_VDP_end - 1) +1$: + outd + + ld a, b + or #.VDP_REG_MASK + out (c), a + + ld a, b + or a + jr nz, 1$ + + ;; detect PAL/NTSC + ld c, #.VDP_VCOUNTER +2$: in a, (c) + cp #0x80 + jr nz, 2$ +3$: ld b, a + in a, (c) + cp b + jr nc, 3$ + + ld a, b + cp #0xE8 + ld a, #.SYSTEM_NTSC + jr c, 4$ + ld a, #.SYSTEM_PAL +4$: + ld (#__SYSTEM), a + + call .clear_VRAM + + call _set_default_palette + + VDP_CANCEL_INT + + ei ; re-enable interrupts before going to main() + call _main +10$: + halt + jr 10$ + + ;; Ordering of segments for the linker. + .area _HOME + .area _BASE + .area _CODE + .area _CODE_0 + .area _LIT + .area _INITIALIZER + .area _GSINIT + .area _GSFINAL + + .area _DATA + .area _INITIALIZED + .area _BSEG + .area _BSS + .area _HEAP + .area _HEAP_END + + .area _CODE + .area _GSINIT +.gsinit:: + ;; initialize static storage variables + ld bc, #l__INITIALIZER + ld hl, #s__INITIALIZER + ld de, #s__INITIALIZED + call .memcpy_simple + + .area _GSFINAL + ret + + .area _HOME + +.clear_VRAM: + ld a, #<.VDP_VRAM + out (#.VDP_CMD), a + ld a, #>.VDP_VRAM + out (#.VDP_CMD), a + xor a + ld bc, #0x4101 + jr 6$ +5$: + out (.VDP_DATA), a +6$: + dec c + jr nz, 5$ + dec b + jr nz, 5$ + ret + + ;; fills memory at HL of length BC with A, clobbers DE +.memset_simple:: + ld e, a + ld a, c + or b + ret z + ld (hl), e + dec bc + ld d, h + ld e, l + inc de + + ;; copies BC bytes from HL into DE +.memcpy_simple:: + ld a, c + or b + ret z + ldir + ret + + ;; Wait for VBL interrupt to be finished +.wait_vbl_done:: +_wait_vbl_done:: + ld a, (_shadow_VDP_R1) + and #.R1_DISP_ON + ret z + + xor a + ld (.vbl_done), a +1$: + halt + ld a, (.vbl_done) + or a + jr z, 1$ + ret + + .area _DATA + +.start_crt_globals: +__BIOS:: + .ds 0x01 ; GB type (GB, PGB, CGB) +__SYSTEM:: + .ds 0x01 ; PAL/NTSC +.end_crt_globals: + + .area _INITIALIZED +.shadow_VDP: +_shadow_VDP_R0:: + .ds 0x01 +_shadow_VDP_R1:: + .ds 0x01 +_shadow_VDP_R2:: + .ds 0x01 +_shadow_VDP_R3:: + .ds 0x01 +_shadow_VDP_R4:: + .ds 0x01 +_shadow_VDP_R5:: + .ds 0x01 +_shadow_VDP_R6:: + .ds 0x01 +_shadow_VDP_R7:: +_shadow_VDP_RBORDER:: + .ds 0x01 +_shadow_VDP_R8:: +_shadow_VDP_RSCX:: + .ds 0x01 +_shadow_VDP_R9:: +_shadow_VDP_RSCY:: + .ds 0x01 +_shadow_VDP_R10:: + .ds 0x01 +.shadow_VDP_end:: + +.sys_time:: +_sys_time:: + .ds 0x02 +.vbl_done:: + .ds 0x01 +_VDP_ATTR_SHIFT:: +.vdp_shift:: + .ds 0x01 +__shadow_OAM_base:: + .ds 0x01 +__shadow_OAM_OFF:: + .ds 0x01 +.mode:: + .ds 0x01 ; Current mode + + .area _INITIALIZER + + .db .R0_DEFAULT + .db #(.R1_DEFAULT | .R1_DISP_ON | .R1_IE) ; VBLANK + .db .R2_MAP_0x3800 + .db 0xFF + .db 0xFF + .db .R5_SAT_0x3F00 + .db .R6_DATA_0x2000 + .db #(0 | .R7_COLOR_MASK) + .db 0 ; SCX + .db 0 ; SCY + .db .R10_INT_OFF + .dw 0x0000 ; .sys_time + .db 0 ; .vbl_done + .db 0 ; _VDP_ATTR_SHIFT + .db #>_shadow_OAM ; __shadow_OAM_base + .db 0 ; __shadow_OAM_OFF + .db .T_MODE_INOUT ; .mode
\ No newline at end of file diff --git a/gbdk/gbdk-lib/libc/targets/z80/sms/global.s b/gbdk/gbdk-lib/libc/targets/z80/sms/global.s new file mode 100644 index 00000000..e4b09bcc --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/sms/global.s @@ -0,0 +1,310 @@ + .MEMORY_CTL = 0x3E + + .MEMCTL_JOYON = 0b00000000 + .MEMCTL_JOYOFF = 0b00000100 + .MEMCTL_BASEON = 0b00000000 + .MEMCTL_BASEOFF = 0b00001000 + .MEMCTL_RAMON = 0b00000000 + .MEMCTL_RAMOFF = 0b00010000 + .MEMCTL_CROMON = 0b00000000 + .MEMCTL_CROMOFF = 0b00100000 + .MEMCTL_ROMON = 0b00000000 + .MEMCTL_ROMOFF = 0b01000000 + .MEMCTL_EXTON = 0b00000000 + .MEMCTL_EXTOFF = 0b10000000 + + .JOY_CTL = 0x3F + + .JOY_P1_LATCH = 0b00000010 + .JOY_P2_LATCH = 0b00001000 + + .VDP_VRAM = 0x4000 + .VDP_TILEMAP = 0x7800 + .VDP_CRAM = 0xC000 + .VDP_SAT = 0x7F00 + + .VDP_SAT_TERM = 0xD0 + + .VDP_VCOUNTER = 0x7E + .VDP_PSG = 0x7F + .VDP_HCOUNTER = 0x7F + + .VDP_DATA = 0xBE + .VDP_CMD = 0xBF + .VDP_STAT = 0xBF + + .STATF_INT_VBL = 0b10000000 + .STATF_9_SPR = 0b01000000 + .STATF_SPR_COLL = 0b00100000 + + .VDP_REG_MASK = 0b10000000 + .VDP_R0 = 0b10000000 + + .R0_VSCRL = 0b00000000 + .R0_VSCRL_INH = 0b10000000 + .R0_HSCRL = 0b00000000 + .R0_HSCRL_INH = 0b01000000 + .R0_NO_LCB = 0b00000000 + .R0_LCB = 0b00100000 + .R0_IE1_OFF = 0b00000000 + .R0_IE1 = 0b00010000 + .R0_SS_OFF = 0b00000000 + .R0_SS = 0b00001000 + .R0_DEFAULT = 0b00000110 + .R0_ES_OFF = 0b00000000 + .R0_ES = 0b00000001 + + .VDP_R1 = 0b10000001 + + .R1_DEFAULT = 0b10000000 + .R1_DISP_OFF = 0b00000000 + .R1_DISP_ON = 0b01000000 + .R1_IE_OFF = 0b00000000 + .R1_IE = 0b00100000 + .R1_SPR_8X8 = 0b00000000 + .R1_SPR_8X16 = 0b00000010 + + .VDP_R2 = 0b10000010 + + .R2_MAP_0x3800 = 0xFF + .R2_MAP_0x3000 = 0xFD + .R2_MAP_0x2800 = 0xFB + .R2_MAP_0x2000 = 0xF9 + .R2_MAP_0x1800 = 0xF7 + .R2_MAP_0x1000 = 0xF5 + .R2_MAP_0x0800 = 0xF3 + .R2_MAP_0x0000 = 0xF1 + + .VDP_R3 = 0b10000011 + .VDP_R4 = 0b10000100 + .VDP_R5 = 0b10000101 + + .R5_SAT_0x3F00 = 0xFF + .R5_SAT_MASK = 0b10000001 + + .VDP_R6 = 0b10000110 + + .R6_BANK0 = 0xFB + .R6_DATA_0x0000 = 0xFB + .R6_BANK1 = 0xFF + .R6_DATA_0x2000 = 0xFF + + .VDP_R7 = 0b10000111 + .VDP_RBORDER = 0b10000111 + + .R7_COLOR_MASK = 0b11110000 + + .VDP_R8 = 0b10001000 + .VDP_RSCX = 0b10001000 + + .VDP_R9 = 0b10001001 + .VDP_RSCY = 0b10001001 + + .VDP_R10 = 0b10001010 + + .R10_INT_OFF = 0xFF + .R10_INT_EVERY = 0x00 + + .UP = 0b00000001 + .DOWN = 0b00000010 + .LEFT = 0b00000100 + .RIGHT = 0b00001000 + .A = 0b00010000 + .B = 0b00100000 + .SELECT = 0b00100000 ; map to B + .START = 0b00010000 ; map to A + + .JOYPAD_COUNT = 2 + + .JOY_PORT1 = 0xDC + + .JOY_P1_UP = 0b00000001 + .JOY_P1_DOWN = 0b00000010 + .JOY_P1_LEFT = 0b00000100 + .JOY_P1_RIGHT = 0b00001000 + .JOY_P1_SW1 = 0b00010000 + .JOY_P1_TRIGGER = 0b00010000 + .JOY_P1_SW2 = 0b00100000 + .JOY_P2_UP = 0b01000000 + .JOY_P2_DOWN = 0b10000000 + + .JOY_PORT2 = 0xDD + + .JOY_P2_LEFT = 0b00000001 + .JOY_P2_RIGHT = 0b00000010 + .JOY_P2_SW1 = 0b00000100 + .JOY_P2_TRIGGER = 0b00000100 + .JOY_P2_SW2 = 0b00001000 + .JOY_RESET = 0b00010000 + .JOY_P1_LIGHT = 0b01000000 + .JOY_P2_LIGHT = 0b10000000 + + .FMADDRESS = 0xF0 + .FMDATA = 0xF1 + .AUDIOCTRL = 0xF2 + + .RAM_CONTROL = 0xfffc + + .RAMCTL_BANK = 0b00000100 + .RAMCTL_ROM = 0b00000000 + .RAMCTL_RAM = 0b00001000 + .RAMCTL_RO = 0b00010000 + .RAMCTL_PROT = 0b10000000 + + .GLASSES_3D = 0xfff8 + + .MAP_FRAME0 = 0xfffd + .MAP_FRAME1 = 0xfffe + .MAP_FRAME2 = 0xffff + + .BIOS = 0xC000 + + .SYSTEM_PAL = 0x00 + .SYSTEM_NTSC = 0x01 + + .CPU_CLOCK = 3579545 + + ;; GBDK library screen modes + + .T_MODE = 0x02 ; Text mode (bit 2) + .T_MODE_OUT = 0x02 ; Text mode output only + .T_MODE_INOUT = 0x03 ; Text mode with input + .M_NO_SCROLL = 0x04 ; Disables scrolling of the screen in text mode + .M_NO_INTERP = 0x08 ; Disables special character interpretation + + ;; Screen dimentions in tiles + + .SCREEN_X_OFS = 0 + .SCREEN_Y_OFS = 0 + .SCREEN_WIDTH = 32 + .SCREEN_HEIGHT = 24 + .VDP_MAP_HEIGHT = 28 + .VDP_MAP_WIDTH = 32 + + ;; Interrupt flags + + .VBL_IFLAG = 0x01 + .LCD_IFLAG = 0x02 + + ; characters + .CR = 0x0A + .SPACE = 0x00 + + ;; Global variables + .globl .mode + + ;; Interrupt routines + .globl _INT_ISR + .globl _NMI_ISR + + ;; Symbols defined at link time + .globl .STACK + .globl _shadow_OAM + .globl __shadow_OAM_OFF + + ;; Main user routine + .globl _main + + ;; Macro definitions + +.macro VDP_WRITE_DATA regH regL ?lbl + ld a, i + ld a, regL + di + out (#.VDP_DATA), a ; 11 + ld a, regH ; 4 + jp po, lbl ; 7/12 + ei ; 4 (total: 26/27) +lbl: + out (#.VDP_DATA), a +.endm + +.macro VDP_WRITE_CMD regH regL ?lbl + ld a, i + ld a, regL + di + out (#.VDP_CMD), a + ld a, regH + jp po, lbl + ei +lbl: + out (#.VDP_CMD), a +.endm + +.macro VDP_DELAY ?lbl + nop + jr lbl +lbl: +.endm + +.macro VDP_CANCEL_INT + in a, (.VDP_STAT) ; cancel pending VDP interrupts +.endm + +.macro WRITE_VDP_CMD_HL + rst 0x10 +.endm + +.macro WRITE_VDP_DATA_HL + rst 0x20 +.endm + +.macro CALL_HL + rst 0x30 +.endm + +.macro DISABLE_VBLANK_COPY + ld a, #1 + ld (__shadow_OAM_OFF), a +.endm + +.macro ENABLE_VBLANK_COPY + xor a + ld (__shadow_OAM_OFF), a +.endm + +.macro ADD_A_REG16 regH regL + add regL + ld regL, a + adc regH + sub regL + ld regH, a +.endm + +.macro MUL_DE_BY_A_RET_HL ?lbl1 ?lbl2 + ; Multiply DE by A, return result in HL; preserves: BC + ld hl, #0 +lbl1: + srl a + jp nc, lbl2 + add hl, de +lbl2: + sla e + rl d + or a + jp nz, lbl1 +.endm + +.macro DIV_PART divident divisor ?lbl + rl divident + rla + sub divisor + jr nc, lbl + add divisor +lbl: +.endm +.macro FAST_DIV8 divident divisor + ; returns modulus in A + .rept 8 + DIV_PART divident divisor + .endm + ld a, divident + cpl +.endm +.macro FAST_MOD8 divident divisor + ; returns modulus in A + .rept 8 + DIV_PART divident divisor + .endm +.endm + diff --git a/gbdk/gbdk-lib/libc/targets/z80/sms/nmi.s b/gbdk/gbdk-lib/libc/targets/z80/sms/nmi.s new file mode 100644 index 00000000..d61b5ded --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/sms/nmi.s @@ -0,0 +1,8 @@ + .include "global.s" + + .title "NMI Handler" + .module NMIHandler + .area _HOME + +_NMI_ISR:: + retn
\ No newline at end of file diff --git a/gbdk/gbdk-lib/libc/targets/z80/sms/pad.s b/gbdk/gbdk-lib/libc/targets/z80/sms/pad.s new file mode 100644 index 00000000..579bae79 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/sms/pad.s @@ -0,0 +1,38 @@ + .include "global.s" + + .title "JOYPad utilities" + .module JOYPad + .area _HOME + + ;; Get Keypad Button Status +_joypad:: +.jpad:: + in a, (.JOY_PORT1) + cpl + and #0b00111111 + ld l, a + ret + + ;; Wait until all buttons have been released +.padup:: +_waitpadup:: +1$: + ld h,#0x7f ; wait for .jpad return zero 127 times in a row +2$: + call .jpad + or a ; have all buttons been released? + jr nz,1$ ; not yet + + dec h + jr nz,2$ + + ret + + ;; Wait for the key to be pressed +_waitpad:: +.wait_pad:: +1$: + call .jpad ; read pad + and l ; compare with mask? + jr z,1$ ; loop if no intersection + ret diff --git a/gbdk/gbdk-lib/libc/targets/z80/sms/pad_ex.s b/gbdk/gbdk-lib/libc/targets/z80/sms/pad_ex.s new file mode 100644 index 00000000..0d864360 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/sms/pad_ex.s @@ -0,0 +1,71 @@ + .include "global.s" + + .title "JOYPad utilities" + .module JOYPad + .area _HOME + +; uint8_t joypad_init(uint8_t npads, joypads_t * joypads) __z88dk_callee; +_joypad_init:: + ld hl, #2 + add hl, sp + ld a, (hl) + or a + jr nz, 1$ + ld a, #1 + jr 2$ +1$: + cp #(.JOYPAD_COUNT + 1) + jr c, 2$ + ld a, #.JOYPAD_COUNT +2$: + inc hl + ld e, (hl) + inc hl + ld d, (hl) + + inc hl + pop bc ; pop return address + ld sp, hl ; dispose params + push bc ; push return address back + + ld (de), a ; number of joypads + ld l, a ; return number of joypads in l + xor a + inc de + ld (de), a + inc de + ld (de), a + inc de + ld (de), a + inc de + ld (de), a + + ret + +;void joypad_ex(joypads_t * joypads) __z88dk_fastcall; + +_joypad_ex:: + ld c, #.JOY_PORT1 + in e, (c) + inc c + in d, (c) + ld a, e + rla + rl d + rla + rl d + ld a, e + cpl + and #0b00111111 + ld e, a + ld a, d + cpl + and #0b01111111 + ld d, a + + inc hl + ld (hl), e + inc hl + ld (hl), d + + ret
\ No newline at end of file diff --git a/gbdk/gbdk-lib/libc/targets/z80/sms/palette.s b/gbdk/gbdk-lib/libc/targets/z80/sms/palette.s new file mode 100644 index 00000000..1e0a791d --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/sms/palette.s @@ -0,0 +1,103 @@ + ;; SMS palette routines + + .include "global.s" + + .title "CRAM SMS Palettes" + .module CRAMUtils + .area _HOME + +; void set_palette_entry(uint8_t palette, uint8_t entry, uint16_t rgb_data) __z88dk_callee; +_set_palette_entry:: + pop de + pop bc + ld hl, #.VDP_CRAM + bit 0, c + jr z, 1$ + set 4, b +1$: + ld c, b + ld b, #0 + add hl, bc + pop bc + + ld a, i + di + ld a, l + out (#.VDP_CMD), a + ld a, h + out (#.VDP_CMD), a + ld a, c + jp po, 2$ + ei +2$: + out (#.VDP_DATA), a + + ld h, d + ld l, e + jp (hl) + +; void set_palette(uint8_t first_palette, uint8_t nb_palettes, uint16_t *rgb_data) __z88dk_callee; +_set_palette:: + pop de + pop bc + ld hl, #.VDP_CRAM + bit 0, c + ld a, b + ld bc, #0 + jr z, 1$ + ld c, #0x10 +1$: + add hl, bc + + ld c, a + + DISABLE_VBLANK_COPY ; switch OFF copy shadow SAT + + ld a, i + di + ld a, l + out (#.VDP_CMD), a + ld a, h + out (#.VDP_CMD), a + jp po, 2$ + ei +2$: + ld a, c + or a + jr z, 3$ + + pop hl + ld c, #.VDP_DATA +5$: + ld b, #0x10 +4$: + outi + jr nz, 4$ + + dec a + jr nz, 5$ +3$: + ENABLE_VBLANK_COPY ; switch ON copy shadow SAT + + ld h, d + ld l, e + jp (hl) + +.CRT_DEFAULT_PALETTE:: + .db 0b00111111 + .db 0b00101010 + .db 0b00010101 + .db 0b00000000 + .db 0b00000010 + .db 0b00001000 + .db 0b00100000 + .db 0b00001010 + .db 0b00101000 + .db 0b00100010 + .db 0b00000011 + .db 0b00001100 + .db 0b00110000 + .db 0b00001111 + .db 0b00111100 + .db 0b00110011 + diff --git a/gbdk/gbdk-lib/libc/targets/z80/sms_fill_rect.s b/gbdk/gbdk-lib/libc/targets/z80/sms_fill_rect.s new file mode 100644 index 00000000..3eeb48ca --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/sms_fill_rect.s @@ -0,0 +1,30 @@ + .include "global.s" + + .globl .fill_rect_xy + + .area _HOME + +; void fill_rect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint16_t tile) __z88dk_callee __preserves_regs(iyh, iyl); +_fill_rect:: + pop hl ; HL = ret + pop bc ; BC = YX + pop de ; DE = WH + ex (sp), hl ; HL = data + ex de, hl ; HL = WH, DE = data + + ld a, b + ld b, d + + add #.SCREEN_Y_OFS + ld d, a + xor a + FAST_MOD8 d #28 + ld d, a + + ld a, c + add #.SCREEN_X_OFS + and #0x1f + ld c, e + ld e, a ; BC = data, DE = YX + + jp .fill_rect_xy diff --git a/gbdk/gbdk-lib/libc/targets/z80/sms_fill_rect_compat.s b/gbdk/gbdk-lib/libc/targets/z80/sms_fill_rect_compat.s new file mode 100644 index 00000000..e6e8dba4 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/sms_fill_rect_compat.s @@ -0,0 +1,30 @@ + .include "global.s" + + .globl .set_tile_map_xy + + .area _HOME + +; void fill_rect_compat(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint16_t tile) __z88dk_callee __preserves_regs(iyh, iyl); +_fill_rect_compat:: + pop hl ; HL = ret + pop bc ; BC = YX + pop de ; DE = WH + ex (sp), hl ; HL = data + ex de, hl ; HL = WH, DE = data + + ld a, b + ld b, d + + add #.SCREEN_Y_OFS + ld d, a + xor a + FAST_MOD8 d #28 + ld d, a + + ld a, c + add #.SCREEN_X_OFS + and #0x1f + ld c, e + ld e, a ; BC = data, DE = YX + + jp .fill_rect_xy_compat diff --git a/gbdk/gbdk-lib/libc/targets/z80/sms_fill_rect_xy.s b/gbdk/gbdk-lib/libc/targets/z80/sms_fill_rect_xy.s new file mode 100644 index 00000000..02325cbe --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/sms_fill_rect_xy.s @@ -0,0 +1,98 @@ + .include "global.s" + + .title "VRAM utilities" + .module VRAMUtils + + .ez80 + + .area _HOME + + ;; Set background tile table from (BC) at XY = DE of size WH = HL +.fill_rect_xy:: + push hl + ld hl, #.VDP_TILEMAP + + ;; Set background tile from (BC) at YX = DE, size WH on stack, to VRAM from address (HL) +.fill_rect_xy_tt:: + push bc ; Store source + + ld a, d + rrca ; rrca(2) == rlca(6) + rrca + ld d, a + and #0x07 + add h + ld b, a + ld a, #0xC0 + and d + sla e + add e + ld c, a ; dest BC = HL + ((0x20 * Y) * 2) + (X * 2) + + ld a, b + cp #>(.VDP_TILEMAP+0x0700) + jr c, 5$ + ld b, #>.VDP_TILEMAP +5$: + pop hl ; HL = source + pop de ; DE = HW + push ix ; save IX + push de ; store HW + + ld ixh, b + ld ixl, c + push ix ; store dest + + DISABLE_VBLANK_COPY ; switch OFF copy shadow SAT + +1$: ; copy H rows + VDP_WRITE_CMD ixh, ixl + ld c, #.VDP_DATA +2$: ; copy W tiles + out (c), l + VDP_DELAY + out (c), h + + ld a, ixl + and #0x3F + inc a + inc a + bit 6, a + jp z, 3$ + and #0x3F + ld b, a + ld a, ixl + and #0xC0 + or b + ld ixl, a + VDP_WRITE_CMD ixh, ixl + dec e + jp nz, 2$ + jp 7$ +3$: + inc ixl + inc ixl + dec e + jp nz, 2$ +7$: + pop ix + pop de + + dec d + jr z, 6$ + + push de + + ld bc, #0x40 + add ix, bc + ld a, ixh + cp #>(.VDP_TILEMAP+0x0700) + jp c, 4$ + ld ixh, #>.VDP_TILEMAP +4$: + push ix + jp 1$ +6$: + ENABLE_VBLANK_COPY ; switch ON copy shadow SAT + pop ix ; restore IX + ret
\ No newline at end of file diff --git a/gbdk/gbdk-lib/libc/targets/z80/sms_fill_rect_xy_compat.s b/gbdk/gbdk-lib/libc/targets/z80/sms_fill_rect_xy_compat.s new file mode 100644 index 00000000..7183ff9d --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/sms_fill_rect_xy_compat.s @@ -0,0 +1,101 @@ + .include "global.s" + + .globl .vdp_shift + + .title "VRAM utilities" + .module VRAMUtils + + .ez80 + + .area _HOME + + ;; Set background tile table from (BC) at XY = DE of size WH = HL +.fill_rect_xy_compat:: + push hl + ld hl, #.VDP_TILEMAP + + ;; Set background tile from (BC) at YX = DE, size WH on stack, to VRAM from address (HL) +.fill_rect_xy_tt_compat:: + push bc ; Store source + + ld a, d + rrca ; rrca(2) == rlca(6) + rrca + ld d, a + and #0x07 + add h + ld b, a + ld a, #0xC0 + and d + sla e + add e + ld hl, #.vdp_shift + add (hl) + ld c, a ; dest BC = HL + ((0x20 * Y) * 2) + (X * 2) + + ld a, b + cp #>(.VDP_TILEMAP+0x0700) + jr c, 5$ + ld b, #>.VDP_TILEMAP +5$: + pop hl ; HL = source + pop de ; DE = HW + push ix ; save IX + push de ; store HW + ld ixh, b + ld ixl, c + push ix ; store dest + + DISABLE_VBLANK_COPY ; switch OFF copy shadow SAT + +1$: ; copy H rows + VDP_WRITE_CMD ixh, ixl + ld c, #.VDP_DATA +2$: ; copy W tiles + out (c), l + VDP_DELAY + in a, (c) ; skip next byte + + ld a, ixl + and #0x3F + inc a + inc a + bit 6, a + jp z, 3$ + and #0x3F + ld b, a + ld a, ixl + and #0xC0 + or b + ld ixl, a + VDP_WRITE_CMD ixh, ixl + dec e + jp nz, 2$ + jp 7$ +3$: + inc ixl + inc ixl + dec e + jp nz, 2$ +7$: + pop ix + pop de + + dec d + jr z, 6$ + + push de + + ld bc, #0x40 + add ix, bc + ld a, ixh + cp #>(.VDP_TILEMAP+0x0700) + jp c, 4$ + ld ixh, #>.VDP_TILEMAP +4$: + push ix + jp 1$ +6$: + ENABLE_VBLANK_COPY ; switch ON copy shadow SAT + pop ix ; restore IX + ret
\ No newline at end of file diff --git a/gbdk/gbdk-lib/libc/targets/z80/sms_int.s b/gbdk/gbdk-lib/libc/targets/z80/sms_int.s new file mode 100644 index 00000000..3de09db0 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/sms_int.s @@ -0,0 +1,197 @@ + .include "global.s" + + .title "INT Handler" + .module INTHandler + + .globl .sys_time, .vbl_done + .globl .OUTI128, .OUTI64, __shadow_OAM_base + + .area _HOME + +_INT_ISR:: + push af + push bc + push de + push hl + push iy + push ix + + in a, (.VDP_STAT) + and #.STATF_INT_VBL + jp z, 2$ + ;; handle VBlank + + ld hl, (.sys_time) + inc hl + ld (.sys_time), hl + + ld a, #1 + ld (.vbl_done), a + + ;; transfer shadow OAM + ld a, (__shadow_OAM_OFF) ; check transfer is OFF + or a + jp nz, 1$ + ld hl, #__shadow_OAM_base + ld h, (hl) + ld l, a ; a == 0 here + or h + jp z, 1$ + + ld c, #.VDP_CMD + ld a, #<.VDP_SAT + out (c), a + ld a, #>.VDP_SAT + out (c), a + dec c ; c == .VDP_DATA + call .OUTI64 + inc c ; c == .VDP_CMD + ld a, #<(.VDP_SAT + 0x80) + out (c), a + ld a, #>(.VDP_SAT + 0x80) + out (c), a + dec c ; c == .VDP_DATA + call .OUTI128 +1$: + + ;; call user-defined VBlank handlers + ld hl, (.VBLANK_HANDLER0) + ld a, h + or l + jp z, 3$ + CALL_HL + + ld hl, (.VBLANK_HANDLER1) + ld a, h + or l + jp z, 3$ + CALL_HL + + ld hl, (.VBLANK_HANDLER2) + ld a, h + or l + jp z, 3$ + CALL_HL + jp 3$ + + ;; handle HBlank +2$: + ld hl, (.HBLANK_HANDLER0) + CALL_HL + +3$: + pop ix + pop iy + pop hl + pop de + pop bc + pop af + ei + reti + +; void remove_LCD (int_handler h) __z88dk_fastcall __preserves_regs(b, c, iyh, iyl); +_remove_LCD:: +.remove_LCD:: + ld hl, #.empty_function + +; void add_LCD (int_handler h) __z88dk_fastcall __preserves_regs(b, c, iyh, iyl); +_add_LCD:: +.add_LCD:: + ld (.HBLANK_HANDLER0), hl + ret + +; void add_VBL(int_handler h) __z88dk_fastcall __preserves_regs(d, e, iyh, iyl); +_add_VBL:: + ld b, h + ld c, l + +.add_VBL:: + ld hl, #.VBLANK_HANDLER0 + + ;; Add interrupt routine in BC to the interrupt list in HL +.add_int:: +1$: + ld a, (hl) + inc hl + or (hl) + jr z, 2$ + inc hl + jr 1$ +2$: + ld (hl), b + dec hl + ld (hl), c + ret + +; void remove_VBL(int_handler h) __z88dk_fastcall __preserves_regs(iyh, iyl); +_remove_VBL:: + ld b, h + ld c, l + + ;; Remove interrupt routine in BC from the VBL interrupt list + ;; falldown to .remove_int +.remove_VBL:: + ld hl, #.VBLANK_HANDLER0 + + ;; Remove interrupt BC from interrupt list HL if it exists + ;; Abort if a 0000 is found (end of list) +.remove_int:: +1$: + ld e, (hl) + inc hl + ld d, (hl) + inc hl + ld a, e + or d + ret z ; No interrupt found + + ld a, e + cp c + jr nz, 1$ + + ld a, d + cp b + jr nz, 1$ + + ld d, h + ld e, l + dec de + dec de + + ;; Now do a memcpy from here until the end of the list +2$: + ld a, (hl) + ldi + or (hl) + ldi + jr nz, 2$ + ret + +_remove_TIM:: +_remove_SIO:: +_remove_JOY:: +_add_TIM:: +_add_SIO:: +_add_JOY:: +.empty_function: + ret + + .area _INITIALIZED + +.HBLANK_HANDLER0: + .ds 0x02 +.VBLANK_HANDLER0: + .ds 0x02 +.VBLANK_HANDLER1: + .ds 0x02 +.VBLANK_HANDLER2: + .ds 0x02 + .ds 0x02 + + .area _INITIALIZER + + .dw .empty_function + .dw 0x0000 + .dw 0x0000 + .dw 0x0000 + .dw 0x0000
\ No newline at end of file diff --git a/gbdk/gbdk-lib/libc/targets/z80/sms_metasprites.s b/gbdk/gbdk-lib/libc/targets/z80/sms_metasprites.s new file mode 100644 index 00000000..92b313a1 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/sms_metasprites.s @@ -0,0 +1,82 @@ + .include "global.s" + + .title "Metasprites" + .module Metasprites + + .area _DATA + +___current_metasprite:: + .ds 0x02 +___current_base_tile:: + .ds 0x01 + + .area _INITIALIZED +___render_shadow_OAM:: + .ds 0x01 + + .area _INITIALIZER + .db #>_shadow_OAM + + .area _CODE + +; uint8_t __move_metasprite(uint8_t id, uint8_t x, uint8_t y) __z88dk_callee __preserves_regs(iyh,iyl); + +___move_metasprite:: + ld hl, #4 + add hl, sp + + ld b, (hl) + dec hl + ld c, (hl) + dec hl + ld e, (hl) + + ld hl, (___current_metasprite) + + ld a, (___render_shadow_OAM) + ld d, a +1$: + ld a, (hl) ; dy + inc hl + cp #0x80 + jp z, 2$ + add b + ld b, a + cp #0xD0 + jp nz, 3$ + ld a, #0xC0 +3$: + ld (de), a + + push de + + ld a, e + add a + add #0x40 + ld e, a + + ld a, (hl) ; dx + inc hl + add c + ld c, a + ld (de), a + inc e + + ld a, (___current_base_tile) + add (hl) ; tile + inc hl + ld (de), a + + pop de + inc e + + jp 1$ +2$: + pop hl + pop bc + inc sp + push hl + ld a, e + sub c + ld l, a + ret diff --git a/gbdk/gbdk-lib/libc/targets/z80/sms_metasprites_hide.s b/gbdk/gbdk-lib/libc/targets/z80/sms_metasprites_hide.s new file mode 100644 index 00000000..21eacfe9 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/sms_metasprites_hide.s @@ -0,0 +1,37 @@ + .include "global.s" + + .title "Metasprites" + .module Metasprites + + .globl ___current_metasprite, ___render_shadow_OAM + + .area _CODE + + +; void __hide_metasprite(uint8_t id) __z88dk_fastcall __preserves_regs(iyh,iyl); + +___hide_metasprite:: + ld e, l + + ld hl, (___current_metasprite) + + ld bc, #3 + + ld a, (___render_shadow_OAM) + ld d, a +1$: + ld a, (hl) + cp #0x80 + ret z + + ld a, #0x3F + cp e + ret c + + add hl, bc + + ld a, #0xC0 + ld (de), a + + inc e + jp 1$ diff --git a/gbdk/gbdk-lib/libc/targets/z80/sms_metasprites_hide_spr.s b/gbdk/gbdk-lib/libc/targets/z80/sms_metasprites_hide_spr.s new file mode 100644 index 00000000..789a190b --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/sms_metasprites_hide_spr.s @@ -0,0 +1,41 @@ + .include "global.s" + + .title "Metasprites" + .module Metasprites + + .globl ___render_shadow_OAM + + .area _CODE + +; void hide_sprites_range(UINT8 from, UINT8 to) __z88dk_callee __preserves_regs(iyh,iyl); + +_hide_sprites_range:: + pop hl + pop de + push hl + + ld a, d + cp #(64+1) + ret nc + + sub e + ret c + ret z + + ld c, a + xor a + ld b, a + + ld hl, #___render_shadow_OAM + ld h, (hl) + ld l, e + + ld d, h + inc e + ld (hl), #0xC0 + + dec c + ret z + + ldir + ret diff --git a/gbdk/gbdk-lib/libc/targets/z80/sms_refresh_oam.s b/gbdk/gbdk-lib/libc/targets/z80/sms_refresh_oam.s new file mode 100644 index 00000000..e107563b --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/sms_refresh_oam.s @@ -0,0 +1,34 @@ + .include "global.s" + + .title "VRAM utilities" + .module VRAMUtils + + .globl __shadow_OAM_base + + .ez80 + + .area _HOME + +; void refresh_OAM(); +_refresh_OAM:: + DISABLE_VBLANK_COPY ; switch OFF copy shadow SAT + ld de, #.VDP_SAT + VDP_WRITE_CMD d, e + + ld h, #>_shadow_OAM + ld l, #0 + ld c, #.VDP_DATA + ld b, #64 +1$: + outi + jp nz, 1$ + + ld de, #(.VDP_SAT + 0x80) + VDP_WRITE_CMD d, e + ld b, #128 +2$: + outi + jp nz, 2$ + + ENABLE_VBLANK_COPY ; switch OFF copy shadow SAT + ret
\ No newline at end of file diff --git a/gbdk/gbdk-lib/libc/targets/z80/sms_set_1bpp_data.s b/gbdk/gbdk-lib/libc/targets/z80/sms_set_1bpp_data.s new file mode 100644 index 00000000..52662d96 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/sms_set_1bpp_data.s @@ -0,0 +1,108 @@ + .include "global.s" + + .title "VRAM utilities" + .module VRAMUtils + + .ez80 + + .area _HOME + +; void set_tile_1bpp_data(uint16_t start, uint16_t ntiles, const void *src, uint16_t colors) __z88dk_callee __preserves_regs(iyh,iyl); +_set_tile_1bpp_data:: + pop de ; pop ret address + pop hl + + add hl, hl + add hl, hl + add hl, hl + add hl, hl + add hl, hl + + ld bc, #.VDP_VRAM + add hl, bc + + DISABLE_VBLANK_COPY ; switch OFF copy shadow SAT + + VDP_WRITE_CMD h, l + + ex de, hl ; hl = ret + + pop bc ; bc = ntiles + pop de ; de = src + ex (sp), hl ; hl = palette + + ex de, hl + + inc b + inc c + push ix + + ld ixh, d + ld ixl, e ; ix == palette + + push iy + ld iy, #-4 + add iy, sp + ld sp, iy + push bc + jr 2$ + +1$: + ex (sp), hl + + ld d, #8 +6$: + ld c, (hl) + inc hl + + ld e, #8 +5$: + srl c + + jr c, 10$ + ld a, ixh + jr 11$ +10$: + ld a, ixl +11$: + rra + rr 0 (iy) + rra + rr 1 (iy) + rra + rr 2 (iy) + rra + rr 3 (iy) + + dec e + jr nz, 5$ + + ld a, 0 (iy) + out (.VDP_DATA), a + ld a, 1 (iy) + out (.VDP_DATA), a + ld a, 2 (iy) + out (.VDP_DATA), a + ld a, 3 (iy) + out (.VDP_DATA), a + + dec d + jr nz, 6$ +2$: + ex (sp), hl + + dec l + jr nz, 1$ + + dec h + jr nz, 1$ + + ld iy, #6 + add iy, sp + ld sp, iy + pop iy + pop ix + + ENABLE_VBLANK_COPY ; switch ON copy shadow SAT + + ret diff --git a/gbdk/gbdk-lib/libc/targets/z80/sms_set_2bpp_data.s b/gbdk/gbdk-lib/libc/targets/z80/sms_set_2bpp_data.s new file mode 100644 index 00000000..a77e08fe --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/sms_set_2bpp_data.s @@ -0,0 +1,144 @@ + .include "global.s" + + .title "VRAM utilities" + .module VRAMUtils + + .ez80 + + .area _INITIALIZED +__current_2bpp_palette:: + .ds 0x02 + + .area _INITIALIZER + .dw 0b0011001000010000 + + .area _HOME + +; void set_tile_2bpp_data(uint16_t start, uint16_t ntiles, const void *src, uint16_t palette) __z88dk_callee __preserves_regs(iyh,iyl); +_set_tile_2bpp_data:: + pop de ; pop ret address + pop hl + + add hl, hl + add hl, hl + add hl, hl + add hl, hl + add hl, hl + + ld bc, #.VDP_VRAM + add hl, bc + + DISABLE_VBLANK_COPY ; switch OFF copy shadow SAT + + VDP_WRITE_CMD h, l + + ex de, hl ; hl = ret + + pop bc ; bc = ntiles + pop de ; de = src + ex (sp), hl ; hl = palette + + ex de, hl + + inc b + inc c + push ix + push iy + ld iy, #-4 + add iy, sp + ld sp, iy + push bc + jr 2$ + +1$: + ex (sp), hl + + ld ixh, #8 +6$: + ld c, (hl) + inc hl + ld b, (hl) + inc hl + + ld ixl, #8 +5$: + xor a + srl b + rla + srl c + rla + + push de ; save palette + + inc a + dec a + jr nz, 10$ + ; zero + ld a, e + jr 13$ +10$: + dec a + jr nz, 11$ + ; one + ld a, e + jr 14$ +11$: + dec a + jr nz, 12$ + ; two + ld a, d + jr 13$ +12$: + ;three + ld a, d +14$: + rra + rra + rra + rra +13$: + and #0x0F + + rra + rr 0 (iy) + rra + rr 1 (iy) + rra + rr 2 (iy) + rra + rr 3 (iy) + + pop de ; restore palette + + dec ixl + jr nz, 5$ + + ld a, 0 (iy) + out (.VDP_DATA), a + ld a, 1 (iy) + out (.VDP_DATA), a + ld a, 2 (iy) + out (.VDP_DATA), a + ld a, 3 (iy) + out (.VDP_DATA), a + + dec ixh + jr nz, 6$ +2$: + ex (sp), hl + + dec l + jr nz, 1$ + + dec h + jr nz, 1$ + + ld iy, #6 + add iy, sp + ld sp, iy + pop iy + pop ix + + ENABLE_VBLANK_COPY ; switch ON copy shadow SAT + + ret diff --git a/gbdk/gbdk-lib/libc/targets/z80/sms_set_native_data.s b/gbdk/gbdk-lib/libc/targets/z80/sms_set_native_data.s new file mode 100644 index 00000000..bcd418f1 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/sms_set_native_data.s @@ -0,0 +1,51 @@ + .include "global.s" + + .title "VRAM utilities" + .module VRAMUtils + .area _HOME + +; void set_native_tile_data(uint16_t start, uint16_t ntiles, const void *src) __z88dk_callee __preserves_regs(iyh,iyl); +_set_native_tile_data:: + pop de ; pop ret address + pop hl + + add hl, hl + add hl, hl + add hl, hl + add hl, hl + add hl, hl + + ld bc, #.VDP_VRAM + add hl, bc + + DISABLE_VBLANK_COPY ; switch OFF copy shadow SAT + + VDP_WRITE_CMD h, l + + pop bc + pop hl + push de + + ld e, c + ld d, b + + ld c, #.VDP_DATA + inc d + inc e + jr 2$ + +1$: + ld b, #32 +3$: + outi + jr nz, 3$ +2$: + dec e + jr nz, 1$ + + dec d + jr nz, 1$ + + ENABLE_VBLANK_COPY ; switch ON copy shadow SAT + + ret diff --git a/gbdk/gbdk-lib/libc/targets/z80/vmemcpy.s b/gbdk/gbdk-lib/libc/targets/z80/vmemcpy.s new file mode 100644 index 00000000..8c420059 --- /dev/null +++ b/gbdk/gbdk-lib/libc/targets/z80/vmemcpy.s @@ -0,0 +1,45 @@ + .include "global.s" + + .title "VRAM utilities" + .module VRAMUtils + .area _HOME + +; void vmemcpy (unsigned int dst, const void *src, unsigned int size) __z88dk_callee __preserves_regs(iyh,iyl); +_set_data:: +_vmemcpy:: + pop de ; pop ret address + pop hl ; dst + + DISABLE_VBLANK_COPY + + VDP_WRITE_CMD h, l + + pop hl ; src + pop bc ; size + + ld a, b ; HI(size) + ld b, c ; LO(size) + + ld c, #.VDP_DATA + + rlc b + rrc b ; check b is zero + jr z, 2$ +1$: + outi + jp nz, 1$ ; 10 = 26 (VRAM safe) +2$: + inc a + jp 4$ +3$: + outi + jp nz, 3$ ; 10 = 26 (VRAM safe) +4$: + dec a + jp nz, 3$ + + ENABLE_VBLANK_COPY + + ld h, d + ld l, e + jp (hl) diff --git a/gbdk/gbdk-lib/libc/time.c b/gbdk/gbdk-lib/libc/time.c new file mode 100644 index 00000000..b6801760 --- /dev/null +++ b/gbdk/gbdk-lib/libc/time.c @@ -0,0 +1,17 @@ +/* + time.c + Simple, not completely conformant implementation of time routines +*/ + +#include <stdint.h> + +/* clock() is in clock.s */ +#include <time.h> + +time_t time(time_t *t) { + uint16_t ret; + /* Should be relative to 0:00 1970 GMT but hey */ + ret = clock() / CLOCKS_PER_SEC; + if (t) *t = ret; + return ret; +} diff --git a/gbdk/gbdk-lib/libc/tolower.c b/gbdk/gbdk-lib/libc/tolower.c new file mode 100644 index 00000000..9a730d50 --- /dev/null +++ b/gbdk/gbdk-lib/libc/tolower.c @@ -0,0 +1,5 @@ +#include <stdint.h> + +char tolower (char c) { + return ((uint8_t)((uint8_t)c - 'A') < ('Z' - 'A' + 1)) ? c + 32u : c; +} diff --git a/gbdk/gbdk-lib/libc/toupper.c b/gbdk/gbdk-lib/libc/toupper.c new file mode 100644 index 00000000..661eb0ca --- /dev/null +++ b/gbdk/gbdk-lib/libc/toupper.c @@ -0,0 +1,5 @@ +#include <stdint.h> + +char toupper(char c) { + return ((uint8_t)((uint8_t)c - 'a') < ('z' - 'a' + 1)) ? c - 32u : c; +} |
