summaryrefslogtreecommitdiffstats
path: root/gbdk/gbdk-lib/libc
diff options
context:
space:
mode:
authorLouis Burda <quent.burda@gmail.com>2022-06-02 15:28:40 +0200
committerLouis Burda <quent.burda@gmail.com>2022-06-02 15:28:40 +0200
commit5bc16063c29aa4d3d287ebd163ccdbcbf54c4f9f (patch)
treec131f947a37b3af2d14d41e9eda098bdec2d061c /gbdk/gbdk-lib/libc
parent78a5f810b22f0d8cafa05f638b0cb2e889824859 (diff)
downloadcscg2022-gearboy-master.tar.gz
cscg2022-gearboy-master.zip
Added submodule filesHEADmaster
Diffstat (limited to 'gbdk/gbdk-lib/libc')
-rw-r--r--gbdk/gbdk-lib/libc/Makefile53
-rw-r--r--gbdk/gbdk-lib/libc/Makefile.platform8
-rw-r--r--gbdk/gbdk-lib/libc/Makefile.rules19
-rw-r--r--gbdk/gbdk-lib/libc/__assert.c38
-rw-r--r--gbdk/gbdk-lib/libc/_divslong.c35
-rw-r--r--gbdk/gbdk-lib/libc/_divulong.c351
-rw-r--r--gbdk/gbdk-lib/libc/_modslong.c35
-rw-r--r--gbdk/gbdk-lib/libc/_modulong.c55
-rw-r--r--gbdk/gbdk-lib/libc/_mullong.c91
-rw-r--r--gbdk/gbdk-lib/libc/asm/Makefile.port11
-rw-r--r--gbdk/gbdk-lib/libc/asm/sm83/Makefile22
-rw-r--r--gbdk/gbdk-lib/libc/asm/sm83/__sdcc_call_hl.s38
-rw-r--r--gbdk/gbdk-lib/libc/asm/sm83/_memcmp.s45
-rw-r--r--gbdk/gbdk-lib/libc/asm/sm83/_memmove.c54
-rw-r--r--gbdk/gbdk-lib/libc/asm/sm83/_memset.s52
-rw-r--r--gbdk/gbdk-lib/libc/asm/sm83/_strcmp.s35
-rw-r--r--gbdk/gbdk-lib/libc/asm/sm83/_strcpy.s26
-rw-r--r--gbdk/gbdk-lib/libc/asm/sm83/abs.s19
-rw-r--r--gbdk/gbdk-lib/libc/asm/sm83/arand.s116
-rw-r--r--gbdk/gbdk-lib/libc/asm/sm83/atomic_flag_test_and_set.s46
-rw-r--r--gbdk/gbdk-lib/libc/asm/sm83/bcd.s233
-rw-r--r--gbdk/gbdk-lib/libc/asm/sm83/crt0_rle.s69
-rw-r--r--gbdk/gbdk-lib/libc/asm/sm83/div.s339
-rw-r--r--gbdk/gbdk-lib/libc/asm/sm83/itoa.s190
-rw-r--r--gbdk/gbdk-lib/libc/asm/sm83/labs.s70
-rw-r--r--gbdk/gbdk-lib/libc/asm/sm83/ltoa.s222
-rw-r--r--gbdk/gbdk-lib/libc/asm/sm83/memcpy.s94
-rw-r--r--gbdk/gbdk-lib/libc/asm/sm83/mul.s158
-rw-r--r--gbdk/gbdk-lib/libc/asm/sm83/rand.s117
-rw-r--r--gbdk/gbdk-lib/libc/asm/sm83/reverse.s84
-rw-r--r--gbdk/gbdk-lib/libc/asm/sm83/setjmp.s105
-rw-r--r--gbdk/gbdk-lib/libc/asm/sm83/shift.s89
-rw-r--r--gbdk/gbdk-lib/libc/asm/sm83/strlen.s44
-rw-r--r--gbdk/gbdk-lib/libc/asm/z80/Makefile27
-rw-r--r--gbdk/gbdk-lib/libc/asm/z80/__itoa.s231
-rw-r--r--gbdk/gbdk-lib/libc/asm/z80/__ltoa.s254
-rw-r--r--gbdk/gbdk-lib/libc/asm/z80/__sdcc_call_hl.s37
-rw-r--r--gbdk/gbdk-lib/libc/asm/z80/__sdcc_call_iy.s37
-rw-r--r--gbdk/gbdk-lib/libc/asm/z80/__sdcc_critical.s54
-rw-r--r--gbdk/gbdk-lib/libc/asm/z80/__strreverse.s63
-rw-r--r--gbdk/gbdk-lib/libc/asm/z80/__uitobcd.s87
-rw-r--r--gbdk/gbdk-lib/libc/asm/z80/__ultobcd.s122
-rw-r--r--gbdk/gbdk-lib/libc/asm/z80/abs.s61
-rw-r--r--gbdk/gbdk-lib/libc/asm/z80/arand.s78
-rw-r--r--gbdk/gbdk-lib/libc/asm/z80/atomic_flag_test_and_set.s44
-rw-r--r--gbdk/gbdk-lib/libc/asm/z80/crtenter.s41
-rw-r--r--gbdk/gbdk-lib/libc/asm/z80/divmixed.s49
-rw-r--r--gbdk/gbdk-lib/libc/asm/z80/divsigned.s124
-rw-r--r--gbdk/gbdk-lib/libc/asm/z80/divunsigned.s131
-rw-r--r--gbdk/gbdk-lib/libc/asm/z80/memcmp.s38
-rw-r--r--gbdk/gbdk-lib/libc/asm/z80/memcpy.s49
-rw-r--r--gbdk/gbdk-lib/libc/asm/z80/memmove.s65
-rw-r--r--gbdk/gbdk-lib/libc/asm/z80/memset.s30
-rw-r--r--gbdk/gbdk-lib/libc/asm/z80/modmixed.s53
-rw-r--r--gbdk/gbdk-lib/libc/asm/z80/modsigned.s46
-rw-r--r--gbdk/gbdk-lib/libc/asm/z80/modunsigned.s46
-rw-r--r--gbdk/gbdk-lib/libc/asm/z80/mul.s72
-rw-r--r--gbdk/gbdk-lib/libc/asm/z80/mulchar.s68
-rw-r--r--gbdk/gbdk-lib/libc/asm/z80/rand.s52
-rw-r--r--gbdk/gbdk-lib/libc/asm/z80/setjmp.s95
-rw-r--r--gbdk/gbdk-lib/libc/asm/z80/strcpy.s48
-rw-r--r--gbdk/gbdk-lib/libc/asm/z80/strlen.s47
-rw-r--r--gbdk/gbdk-lib/libc/atoi.c31
-rw-r--r--gbdk/gbdk-lib/libc/atol.c28
-rw-r--r--gbdk/gbdk-lib/libc/atomic_flag_clear.c41
-rw-r--r--gbdk/gbdk-lib/libc/bsearch.c51
-rw-r--r--gbdk/gbdk-lib/libc/calloc.c62
-rw-r--r--gbdk/gbdk-lib/libc/free.c80
-rw-r--r--gbdk/gbdk-lib/libc/isalpha.c7
-rw-r--r--gbdk/gbdk-lib/libc/isdigit.c7
-rw-r--r--gbdk/gbdk-lib/libc/islower.c7
-rw-r--r--gbdk/gbdk-lib/libc/isspace.c7
-rw-r--r--gbdk/gbdk-lib/libc/isupper.c7
-rw-r--r--gbdk/gbdk-lib/libc/malloc.c114
-rw-r--r--gbdk/gbdk-lib/libc/printf.c11
-rw-r--r--gbdk/gbdk-lib/libc/puts.c12
-rw-r--r--gbdk/gbdk-lib/libc/qsort.c61
-rw-r--r--gbdk/gbdk-lib/libc/realloc.c139
-rw-r--r--gbdk/gbdk-lib/libc/rules-asxxxx.mk18
-rw-r--r--gbdk/gbdk-lib/libc/scanf.c153
-rw-r--r--gbdk/gbdk-lib/libc/sprintf.c112
-rw-r--r--gbdk/gbdk-lib/libc/strcat.c14
-rw-r--r--gbdk/gbdk-lib/libc/string.c36
-rw-r--r--gbdk/gbdk-lib/libc/strncat.c21
-rw-r--r--gbdk/gbdk-lib/libc/strncmp.c16
-rw-r--r--gbdk/gbdk-lib/libc/strncpy.c18
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/___sdcc_bcall.s27
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/___sdcc_bcall_ehl.s15
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/ap/Makefile47
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/ap/crash_handler.s481
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/ap/crt0.s529
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/ap/global.s533
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/ap/sfr.s111
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/cgb.s37
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/cgb_compat.s21
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/cgb_palettes.s78
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/clock.s16
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/color.s32
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/cpy_data.s44
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/crlf.c1
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/delay.s73
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/digits.c1
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/drawing.s1767
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/drawing_isr.s23
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/duck/Makefile47
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/duck/crash_handler.s476
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/duck/crt0.s468
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/duck/global.s533
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/duck/sfr.s111
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/emu_debug.s20
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/emu_debug_printf.s43
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/f_ibm_full.s2616
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/f_ibm_sh.s174
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/f_italic.s956
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/f_min.s356
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/f_spect.s886
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/far_ptr.s71
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/fill_rect.s85
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/fill_rect_bk.s22
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/fill_rect_wi.s22
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/font.s558
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/font_color.s12
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/gb/Makefile47
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/gb/crash_handler.s481
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/gb/crt0.s538
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/gb/global.s532
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/gb/sfr.s111
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/gb_decompress.s108
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/gb_decompress_tiles.s165
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/get_addr.s39
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/get_bk_t.s24
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/get_data.s120
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/get_t.s26
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/get_tile.s51
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/get_wi_t.s26
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/get_xy_t.s86
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/gprint.c7
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/gprintf.c86
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/gprintln.c19
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/gprintn.c19
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/heap.s44
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/hiramcpy.s34
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/init_tt.s52
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/init_vram.s44
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/input.s639
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/joy.s47
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/lcd.s81
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/metasprites.s82
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/metasprites_flip.s203
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/metasprites_hide.s52
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/metasprites_hide_spr.s71
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/mode.s30
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/mv_spr.s18
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/nowait.s10
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/pad.s68
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/pad_ex.s132
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/rle_decompress.s116
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/serial.s140
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/set_1bit_data.s98
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/set_bk_t.s26
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/set_data.s58
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/set_prop.s16
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/set_spr.s16
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/set_t.s28
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/set_tile.s60
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/set_tile_submap.s150
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/set_wi_t.s27
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/set_win_tile_submap.s50
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/set_xy_t.s99
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/sgb.s128
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/tim.s25
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/tim_common.s28
-rw-r--r--gbdk/gbdk-lib/libc/targets/sm83/tim_nested.s29
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/clock.s12
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/cls.s34
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/color.s17
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/coords_to_address.s47
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/delay.s53
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/emu_debug_printf.s44
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/f_ibm_full.s2616
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/f_ibm_sh.s174
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/f_italic.s957
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/f_min.s355
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/f_spect.s886
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/far_ptr.s64
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/font.s170
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/gb_decompress.s90
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/gg/Makefile44
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/gg/__sdcc_bcall.s68
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/gg/crlf.c1
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/gg/crt0.s268
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/gg/global.s345
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/gg/nmi.s8
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/gg/pad.s43
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/gg/pad_ex.s76
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/gg/palette.s107
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/gotoxy.s34
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/heap.s44
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/memset_small.s14
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/mode.s22
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/msxdos/Makefile36
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/msxdos/__sdcc_bcall.s41
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/msxdos/__sdcc_bcall_abc.s59
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/msxdos/bdos_getchar.s10
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/msxdos/bdos_gets.s34
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/msxdos/bdos_putchar.s15
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/msxdos/crlf.c1
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/msxdos/crt0.s522
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/msxdos/global.s483
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_fill_rect.s25
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_fill_rect_xy.s93
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_int.s185
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_metasprites.s77
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_metasprites_hide.s37
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_metasprites_hide_spr.s39
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_refresh_oam.s27
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_set_1bpp_data.s77
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_set_1bpp_sprite_data.s52
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_set_native_data.s73
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_set_tile_map.s29
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_set_tile_map_xy.s100
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/msxdos/msx_write_vdp.s14
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/msxdos/pad.s66
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/outi.s20
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/putchar.s126
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/rle_decompress.s100
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/scroll.s61
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/set_interrupts.s46
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/set_palette.s23
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/set_tile.s70
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/set_tile_map.s33
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/set_tile_map_compat.s33
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/set_tile_map_xy.s98
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/set_tile_map_xy_compat.s115
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/set_tile_submap.s156
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/set_tile_submap_compat.s168
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/sms/Makefile44
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/sms/__sdcc_bcall.s68
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/sms/crlf.c1
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/sms/crt0.s275
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/sms/global.s310
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/sms/nmi.s8
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/sms/pad.s38
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/sms/pad_ex.s71
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/sms/palette.s103
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/sms_fill_rect.s30
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/sms_fill_rect_compat.s30
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/sms_fill_rect_xy.s98
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/sms_fill_rect_xy_compat.s101
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/sms_int.s197
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/sms_metasprites.s82
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/sms_metasprites_hide.s37
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/sms_metasprites_hide_spr.s41
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/sms_refresh_oam.s34
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/sms_set_1bpp_data.s108
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/sms_set_2bpp_data.s144
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/sms_set_native_data.s51
-rw-r--r--gbdk/gbdk-lib/libc/targets/z80/vmemcpy.s45
-rw-r--r--gbdk/gbdk-lib/libc/time.c17
-rw-r--r--gbdk/gbdk-lib/libc/tolower.c5
-rw-r--r--gbdk/gbdk-lib/libc/toupper.c5
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;
+}