From 3aacf3d2cedfdeca49ceb57533389870bfc688a9 Mon Sep 17 00:00:00 2001 From: sik Date: Sun, 23 Jul 2017 03:20:35 -0300 Subject: Now with pausing and other niceties --- README | 16 +- built/old-builds/prog-z80-1.4.bin | Bin 0 -> 5120 bytes built/prog-z80.bin | Bin 5120 -> 4864 bytes c/echo.c | 117 ++++++-- c/echo.h | 27 +- c/echoblob.h | 548 ++++++++++++++++++-------------------- doc/api-asm.68k | 30 ++- doc/api-c.txt | 18 +- doc/esf.txt | 21 +- src-68k/echo.68k | 165 ++++++++++-- src-z80/build.z80 | 8 +- src-z80/core/bgm.z80 | 185 ++++++++----- src-z80/core/macro.z80 | 41 +++ src-z80/core/main.z80 | 113 ++++---- src-z80/core/sfx.z80 | 48 +++- src-z80/core/vars.z80 | 18 +- src-z80/player/fm.z80 | 30 ++- src-z80/player/misc.z80 | 55 ++++ src-z80/player/pcm (copia).z80 | 236 ++++++++++++++++ src-z80/player/pcm.z80 | 197 +++++++------- src-z80/player/psg.z80 | 6 +- 21 files changed, 1264 insertions(+), 615 deletions(-) create mode 100644 built/old-builds/prog-z80-1.4.bin create mode 100644 src-z80/core/macro.z80 create mode 100644 src-z80/player/pcm (copia).z80 diff --git a/README b/README index e1b42b4..6f036e2 100644 --- a/README +++ b/README @@ -7,12 +7,18 @@ | | |_ |_ ___ | | | | | | | | | |_______ |_ |___| _| | | | | |_ |_____| _| |___________| |________| |___| |___| |_________| - ___ ___ _ _ ___ __ ___ ___ ___ _ ___ ___ _ _ _ - | _| | | | | \ | _| | _| | | _| | | | | | - | |_| | | | | | | | | | |_| | | |_| | | | |_ _ _ ___ ___ | | | | | + ___ ___ _ _ ___ __ ___ ___ ___ _ ___ ___ _ ___ + | _| | | | | \ | _| | _| | | _| | | | _| + | |_| | | | | | | | | | |_| | | |_| | | | |_ _ _ ___ ___ | | | |_ |_ | | | | | | | | | | _| | | | | | | | _| | | | __| _ \ | | |_ | - _| | | | | | | | | | | |_| | | | | | | | |_ | | | __| /_ | |_ | | - |___|___|___|_|_|__/ |___|_|_|___|_|_|_|___| \_/|___|_|_\_| |_|_| |_| + _| | | | | | | | | | | |_| | | | | | | | |_ | | | __| /_ | |_ _| | + |___|___|___|_|_|__/ |___|_|_|___|_|_|_|___| \_/|___|_|_\_| |_|_|___| + +============================================================================= + +WARNING: if you used Echo_SetVolumeEx in Echo 1.4, beware that the ABI +changed to require 16 bytes instead of 13. Currently the extra bytes are +ignored, but consider adapting your code (just set them to zeroes). ============================================================================= diff --git a/built/old-builds/prog-z80-1.4.bin b/built/old-builds/prog-z80-1.4.bin new file mode 100644 index 0000000..bbb92e2 Binary files /dev/null and b/built/old-builds/prog-z80-1.4.bin differ diff --git a/built/prog-z80.bin b/built/prog-z80.bin index bbb92e2..1658d7f 100644 Binary files a/built/prog-z80.bin and b/built/prog-z80.bin differ diff --git a/c/echo.c b/c/echo.c index e488e33..23bd409 100644 --- a/c/echo.c +++ b/c/echo.c @@ -98,7 +98,7 @@ void echo_init(const void **list) { // Set up global volume int i; - for (i = 0; i < 12; i++) + for (i = 0; i < 16; i++) z80_ram[0x1FE0+i] = 0; z80_ram[0x1FEC] = 1; z80_ram[0x1FF1] = 1; @@ -120,15 +120,19 @@ void echo_send_command(uint8_t cmd) { Z80_REQUEST(); // Is Echo busy yet? - while (z80_ram[0x1FFF] != 0x00) { - Z80_RELEASE(); - DELAY(); - Z80_REQUEST(); + volatile uint8_t *ptr = &z80_ram[0x1FFC] + if (ptr[3] != 0x00) { + ptr -= 4; + while (ptr[3] != 0x00) { + Z80_RELEASE(); + DELAY(); + Z80_REQUEST(); + } } // Write the command - z80_ram[0x1FFF] = cmd; - + ptr[3] = cmd; + // Done with the Z80 Z80_RELEASE(); } @@ -151,21 +155,25 @@ void echo_send_command_addr(uint8_t cmd, const void *addr) { Z80_REQUEST(); // Is Echo busy yet? - while (z80_ram[0x1FFF] != 0x00) { - Z80_RELEASE(); - DELAY(); - Z80_REQUEST(); + volatile uint8_t *ptr = &z80_ram[0x1FFC] + if (ptr[3] != 0x00) { + ptr -= 4; + while (ptr[3] != 0x00) { + Z80_RELEASE(); + DELAY(); + Z80_REQUEST(); + } } // Write the command - z80_ram[0x1FFF] = cmd; - z80_ram[0x1FFD] = param; + ptr[3] = cmd; + ptr[1] = param; param >>= 8; - z80_ram[0x1FFE] = param | 0x80; + ptr[2] = param | 0x80; param >>= 7; param = (param & 0x7F) | (param >> 1 & 0x80); - z80_ram[0x1FFC] = param; - + ptr[0] = param; + // Done with the Z80 Z80_RELEASE(); } @@ -183,17 +191,20 @@ void echo_send_command_byte(uint8_t cmd, uint8_t byte) { Z80_REQUEST(); // Is Echo busy yet? - while (z80_ram[0x1FFF] != 0x00) { - Z80_RELEASE(); - int16_t i; - for (i = 0x3FF; i >= 0; i--); - Z80_REQUEST(); + volatile uint8_t *ptr = &z80_ram[0x1FFC] + if (ptr[3] != 0x00) { + ptr -= 4; + while (ptr[3] != 0x00) { + Z80_RELEASE(); + DELAY(); + Z80_REQUEST(); + } } // Write the command - z80_ram[0x1FFF] = cmd; - z80_ram[0x1FFC] = byte; - + ptr[3] = cmd; + ptr[0] = byte; + // Done with the Z80 Z80_RELEASE(); } @@ -218,16 +229,23 @@ void echo_stop_bgm(void) { echo_send_command(ECHO_CMD_STOPBGM); } +//*************************************************************************** +// echo_pause_bgm +// Pauses background music playback. +//*************************************************************************** + +void echo_pause_bgm(void) { + echo_send_command(ECHO_CMD_PAUSEBGM); +} + //*************************************************************************** // echo_resume_bgm // Resumes background music playback. //*************************************************************************** -/* void echo_resume_bgm(void) { echo_send_command(ECHO_CMD_RESUMEBGM); } -*/ //*************************************************************************** // echo_play_sfx @@ -328,7 +346,7 @@ void echo_set_volume_ex(const uint8_t *ptr) { // Store the new volume values int i; - for (i = 0; i < 13; i++) + for (i = 0; i < 16; i++) z80_ram[0x1FE0+i] = ptr[i]; // Tell Echo to update all the volumes @@ -363,7 +381,7 @@ uint16_t echo_get_status(void) { // Retrieve status from Z80 RAM uint16_t status = 0; status = z80_ram[0x1FF0]; - if (z80_ram[0x1FFF] != 0) + if (z80_ram[0x1FFB] != 0) status |= ECHO_STAT_BUSY; if (z80_ram[0x1F00] != 0xFF) status |= ECHO_STAT_DIRBUSY; @@ -374,3 +392,46 @@ uint16_t echo_get_status(void) { // Return status return status; } + +//*************************************************************************** +// echo_get_flags +// Gets the current values of the flags. +//--------------------------------------------------------------------------- +// return: bitmask with flags +//*************************************************************************** + +uint8_t echo_get_flags(void) +{ + Z80_REQUEST(); + uint8_t flags = z80_ram[0x1FF2]; + Z88_RELEASE(); + return flags; +} + +//*************************************************************************** +// echo_set_flags +// Sets flags from the 68000. +//--------------------------------------------------------------------------- +// param flags: bitmask of flags to be set (1 = set, 0 = intact) +//*************************************************************************** + +void echo_set_flags(uint8_t flags) +{ + Z80_REQUEST(); + z80_ram[0x1FF2] |= flags; + Z80_RELEASE(); +} + +//*************************************************************************** +// echo_clear_flags +// Clears flags from the 68000. +//--------------------------------------------------------------------------- +// param flags: bitmask of flags to be cleared (1 = clear, 0 = intact) +//*************************************************************************** + +void echo_clear_flags(uint8_t flags) +{ + Z80_REQUEST(); + z80_ram[0x1FF2] &= ~flags; + Z80_RELEASE(); +} diff --git a/c/echo.h b/c/echo.h index 56088b6..c1d6062 100644 --- a/c/echo.h +++ b/c/echo.h @@ -14,6 +14,7 @@ enum { ECHO_CMD_STOPBGM, /* 0x05 - Stop BGM playback */ ECHO_CMD_RESUMEBGM, /* 0x06 - Resume BGM playback */ ECHO_CMD_SETPCMRATE, /* 0x07 - Set PCM rate */ + ECHO_CMD_PAUSEBGM, /* 0x08 - Pause BGM playback */ }; /* Echo status flags */ @@ -23,20 +24,24 @@ enum { #define ECHO_STAT_BUSY 0x8000 /* Echo still didn't parse command */ /* Function prototypes */ -void echo_init(const void **); -void echo_play_bgm(const void *); +void echo_init(const void **list); +void echo_play_bgm(const void *esf); void echo_stop_bgm(void); -/*void echo_resume_bgm(void);*/ -void echo_play_sfx(const void *); +void echo_pause_bgm(void); +void echo_resume_bgm(void); +void echo_play_sfx(const void *esf); void echo_stop_sfx(void); -void echo_play_direct(const void *); -void echo_set_volume(uint8_t); -void echo_set_volume_ex(const uint8_t *); -void echo_set_pcm_rate(uint8_t); +void echo_play_direct(const void *esf); +void echo_set_volume(uint8_t vol); +void echo_set_volume_ex(const uint8_t *vol_list); +void echo_set_pcm_rate(uint8_t rate); uint16_t echo_get_status(void); -void echo_send_command(uint8_t); -void echo_send_command_addr(uint8_t, const void *); -void echo_send_command_byte(uint8_t, uint8_t); +uint8_t echo_get_flags(void); +void echo_set_flags(uint8_t flags); +void echo_clear_flags(uint8_t flags); +void echo_send_command(uint8_t cmd); +void echo_send_command_addr(uint8_t cmd, const void *addr); +void echo_send_command_byte(uint8_t cmd, uint8_t byte); /* Deprecated functions */ static void (* const echo_send_command_ex)(uint8_t, const void *) = diff --git a/c/echoblob.h b/c/echoblob.h index 827cc5b..e4c8d4d 100644 --- a/c/echoblob.h +++ b/c/echoblob.h @@ -1,285 +1,269 @@ static uint8_t echo_blob[] = { - 49,224, 31,175, 50,240, 31, 33, 17,127, 54,159, 54,191, 54,223, - 54,255,175, 50, 0, 19, 50, 16, 19, 50, 32, 19, 50, 48, 19, 33, - 0, 96,117,117,117,117,117,117,117,117,117,221, 33, 0, 64,253, - 38, 64,217, 6, 0,217,221, 54, 0, 43,221, 54, 1, 0, 30,127, - 62, 64, 6, 4,221,119, 0,221,115, 1,221,119, 2,221,115, 3, - 60,221,119, 0,221,115, 1,221,119, 2,221,115, 3, 60,221,119, - 0,221,115, 1,221,119, 2,221,115, 3, 60, 60, 16,214,221, 54, - 0,180,221, 54, 1,192,221, 54, 0,181,221, 54, 1,192,221, 54, - 0,182,221, 54, 1,192,221, 54, 2,180,221, 54, 3,192,221, 54, - 2,181,221, 54, 3,192,221, 54, 2,182,221, 54, 3,192,221, 54, - 0, 36,221, 54, 1,254,221, 54, 0, 37,221, 54, 1, 3,221, 54, - 0, 38,221, 54, 1,201,221, 54, 0, 39,221, 54, 1, 63,195,239, - 0, 61,202, 83, 1, 61,202,109, 5, 61,202,156, 6, 61,202, 21, - 3, 61,202,159, 4, 61,202,102, 3, 61,202,243, 2, 58, 0, 64, - 15,220, 34, 2,175, 50,255, 31, 58, 0, 64, 15,220, 34, 2, 58, - 255, 31,183, 32,204, 58, 0, 64, 15,220, 34, 2, 58, 0, 64,203, - 79, 32, 8,203, 71,196, 34, 2,195,239, 0, 58, 0, 64, 15,220, - 34, 2,221, 54, 0, 39,221, 54, 1, 47, 58, 0, 64, 15,220, 34, - 2, 58,241, 31,183,196,227, 16,195, 43, 1, 58, 0, 64, 15,220, - 34, 2,205, 84, 7, 58, 0, 64, 15,220, 34, 2,195, 63, 1, 58, - 0, 64, 15,220, 34, 2,195, 4, 13, 58, 0, 64, 15,220, 34, 2, - 195,239, 0, 33,252, 31, 78, 44, 94, 44, 86,235,175, 50,255, 31, - 17, 0, 28,205,129, 1,120,183,202,126, 1, 18, 20,205,129, 1, - 120, 18, 20,205,129, 1,120, 18, 21, 21, 28,195, 99, 1,195,239, - 0, 58,152, 19,185,202,161, 1,121, 50,152, 19,229, 33, 0, 96, - 119, 15,119, 15,119, 15,119, 15,119, 15,119, 15,119,116, 15,119, - 225, 70, 44,194,173, 1, 36,194,173, 1, 38,128, 12,201,205,200, - 1,195,230, 5, 58, 0, 64, 15,220, 34, 2, 58,142, 19,183,194, - 132, 4,205,200, 1,195,195, 3, 58,236, 31,183,200,205,129, 1, - 120,217, 38, 28,111, 86, 36, 94, 36, 78, 33, 0, 96,121, 50,152, - 19,119, 15,119, 15,119, 15,119, 15,119, 15,119, 15,119,116, 15, - 119, 38, 19,123,246,240,111, 69, 26,119, 28, 44,194,248, 1,104, - 123,183,194, 12, 2, 20,194, 12, 2, 22,128, 12,217,175, 50, 34, - 2,221, 54, 0, 43,221, 54, 1,128,221, 54, 0, 42,221, 54, 1, - 128,201,201,217,221, 54, 0, 39,221, 54, 1, 31,126, 60, 40, 12, - 221, 54, 0, 42,221,119, 1, 44, 40, 22,217,201, 6, 0,221, 54, - 0, 42,221, 54, 1,128,221, 54, 0, 43,221, 54, 1, 0,217,201, - 58,152, 19,185,202,110, 2,121, 50,152, 19, 33, 0, 96,119, 15, - 119, 15,119, 15,119, 15,119, 15,119, 15,119,116, 15,119, 33,240, - 19, 26,119, 44, 28, 26,119, 44, 28, 26,119, 44, 28, 26,119, 44, - 28, 26,119, 44, 28, 26,119, 44, 28, 26,119, 44, 28, 26,119, 44, - 28, 26,119, 44, 28, 26,119, 44, 28, 26,119, 44, 28, 26,119, 44, - 28, 26,119, 44, 28, 26,119, 44, 28, 26,119, 44, 28, 26,119, 44, - 28,194,187, 2, 20,194,187, 2, 22,128, 12, 46,240,195, 36, 2, - 205,218, 2,195,230, 5, 58, 0, 64, 15,220, 34, 2, 58,142, 19, - 183,194,195, 3,205,218, 2,195,195, 3, 62,201, 50, 34, 2,221, - 54, 0, 43,221, 54, 1, 0,201, 62, 1, 50,142, 19,205,218, 2, - 195,230, 5, 58,252, 31, 47, 71,175, 50,255, 31,120,221, 54, 0, - 36, 15, 15,246,192,221,119, 1,120,221, 54, 0, 37,230, 3,221, - 119, 1,195,239, 0, 58, 0, 64, 15,220, 34, 2,205,205, 4, 58, - 0, 64, 15,220, 34, 2, 58,240, 31,246, 2, 50,240, 31, 58, 0, - 64, 15,220, 34, 2, 33,252, 31, 78, 44, 94, 44, 86, 58, 0, 64, - 15,220, 34, 2,175, 50,255, 31, 33,153, 19, 54, 1, 44, 54, 1, - 44,113, 44,115, 44,114, 58, 0, 64, 15,220, 34, 2, 33,162, 3, - 34, 61, 1,195,239, 0,175, 50,255, 31, 6, 8, 17,143, 19, 58, - 0, 64, 15,220, 34, 2, 26,183,194,135, 3, 58, 0, 64, 15,220, - 34, 2, 5,205,205, 12, 4, 29, 5,194,111, 3, 58,240, 31,246, - 2, 50,240, 31, 33,153, 19, 54, 1, 33,162, 3, 34, 61, 1,195, - 239, 0, 58, 0, 64, 15,220, 34, 2, 33,154, 19,126, 61,202,181, - 3,119,195, 63, 1, 58, 0, 64, 15,220, 34, 2, 44, 78, 44, 94, - 44, 86,235, 58, 0, 64, 15,220, 34, 2,205,129, 1, 58, 0, 64, - 15,220, 34, 2,120,254, 8,218,130, 7,254, 11,218,194, 13,202, - 70, 14,254, 12,202,180, 1, 58, 0, 64, 15,220, 34, 2,120,254, - 24,218, 35, 8,254, 28,218,162, 14,202,198, 2, 58, 0, 64, 15, - 220, 34, 2,120,254,254,202,168, 16,254,255,202,153, 4,254,252, - 202, 67, 5,254,253,202, 88, 5, 58, 0, 64, 15,220, 34, 2,120, - 254, 40,218, 14, 10,254, 44,218,255, 14, 58, 0, 64, 15,220, 34, - 2,120,254, 56,218, 81, 8,254, 59,218, 19, 16,202,109, 16, 58, - 0, 64, 15,220, 34, 2,120,254, 72,218,208, 8,254, 76,218,150, - 15, 58, 0, 64, 15,220, 34, 2,120,254,224,218,184, 16,254,248, - 218,135, 11,254,250,218,226, 11, 58, 0, 64, 15,220, 34, 2,195, - 153, 4, 58, 0, 64, 15,220, 34, 2, 44,194,132, 4, 36,194,132, - 4, 38,128, 12, 58, 0, 64, 15,220, 34, 2, 44,194,150, 4, 36, - 194,150, 4, 38,128, 12,195,195, 3,205,169, 4,195, 63, 1,175, - 50,255, 31,205,169, 4,195,239, 0, 58,240, 31,230,253, 50,240, - 31, 58, 0, 64, 15,220, 34, 2,205,205, 4, 58, 0, 64, 15,220, - 34, 2,175, 50,153, 19, 33, 63, 1, 34, 61, 1,201, 58,142, 19, - 183,204,218, 2, 6, 4, 17, 63, 19, 33,147, 19, 58, 0, 64, 15, - 220, 34, 2, 54, 0,123,214, 15, 95,126,183, 32, 2,175, 18, 58, - 0, 64, 15,220, 34, 2, 29, 45, 16,226, 6, 8, 17, 79, 19, 58, - 0, 64, 15,220, 34, 2, 62,127, 18, 29, 58, 0, 64, 15,220, 34, - 2,126,183,194, 52, 5, 5,120,205, 68, 12, 58, 0, 64, 15,220, - 34, 2,120,230, 4,253,111,120,230, 3,198,180,253,119, 0,253, - 54, 1,192, 4, 45, 16,200, 33, 80, 19, 62,192, 6, 8,119, 44, - 16,252,201, 58, 0, 64, 15,220, 34, 2,235, 44, 78, 44, 94, 44, - 86, 45, 45, 45,235,195,195, 3, 58, 0, 64, 15,220, 34, 2,235, - 44,113, 44,115, 44,114, 45, 45, 45,235,195,195, 3, 58, 0, 64, - 15,220, 34, 2,205,216, 6, 58, 0, 64, 15,220, 34, 2, 58,240, - 31,246, 1, 50,240, 31, 58, 0, 64, 15,220, 34, 2, 33,252, 31, - 78, 44, 94, 44, 86, 58, 0, 64, 15,220, 34, 2,175, 50,255, 31, - 33,161, 19, 54, 1, 44, 54, 1, 44,113, 44,115, 44,114, 58, 0, - 64, 15,220, 34, 2, 33,197, 5, 34, 41, 1, 58, 0, 64, 15,220, - 34, 2,195,239, 0, 58, 0, 64, 15,220, 34, 2, 33,162, 19,126, - 61,202,216, 5,119,195, 43, 1, 58, 0, 64, 15,220, 34, 2, 44, - 78, 44, 94, 44, 86,235, 58, 0, 64, 15,220, 34, 2,205,129, 1, - 58, 0, 64, 15,220, 34, 2,120,254, 8,218,124, 7,254, 11,218, - 188, 13,202, 64, 14,254, 12,202,174, 1, 58, 0, 64, 15,220, 34, - 2,120,254, 24,218, 29, 8,254, 28,218,156, 14,202,192, 2, 58, - 0, 64, 15,220, 34, 2,120,254,254,202,162, 16,254,255,202,150, - 6, 58, 0, 64, 15,220, 34, 2,120,254, 40,218, 8, 10,254, 44, - 218,217, 14, 58, 0, 64, 15,220, 34, 2,120,254, 56,218, 75, 8, - 254, 59,218, 13, 16,202,103, 16, 58, 0, 64, 15,220, 34, 2,120, - 254, 72,218,202, 8,254, 76,218, 80, 15, 58, 0, 64, 15,220, 34, - 2,120,254,224,218,174, 16,254,232,218, 18, 12,254,236,218,122, - 16,202,232, 2, 58, 0, 64, 15,220, 34, 2,120,254,248,218, 88, - 11,254,250,218,220, 11,205,166, 6,195, 43, 1,175, 50,255, 31, - 205,166, 6,195,239, 0, 58, 0, 64, 15,220, 34, 2, 58,240, 31, - 230,254, 50,240, 31, 58, 0, 64, 15,220, 34, 2,175, 50,161, 19, - 33, 43, 1, 34, 41, 1, 58, 0, 64, 15,220, 34, 2,205,216, 6, - 58, 0, 64, 15,220, 34, 2,201, 58,142, 19,183,196,218, 2, 6, - 4, 17,147, 19, 58, 0, 64, 15,220, 34, 2, 26,183, 40, 64,175, - 18, 58, 0, 64, 15,220, 34, 2,120, 15, 15, 15, 15, 61, 38, 19, - 111, 78,214, 15,111,113, 58, 0, 64, 15,220, 34, 2,213,125,198, - 8,111,198, 4, 95, 84, 58, 0, 64, 15,220, 34, 2, 26,119, 44, - 28, 26,119, 44, 28, 26,119,209, 58, 0, 64, 15,220, 34, 2, 29, - 16,178, 6, 8, 58, 0, 64, 15,220, 34, 2, 26,183,202, 78, 7, - 175, 18, 58, 0, 64, 15,220, 34, 2, 5,205,205, 12, 4, 29, 5, - 194, 52, 7,201, 58, 0, 31, 60,200, 58, 0, 64, 15,220, 34, 2, - 33,112, 7, 34, 12, 4, 33, 0, 31, 58,152, 19, 79,195,195, 3, - 33,153, 4, 34, 12, 4, 62,255, 50, 0, 31,201,205,160, 7,195, - 230, 5, 71, 58, 0, 64, 15,220, 34, 2,229,120,230, 7, 33,136, - 19,133,111,126,225,183,194,132, 4,120,205,160, 7,195,195, 3, - 230, 7,221, 54, 0, 40,221,119, 1, 71, 8, 58, 0, 64, 15,220, - 34, 2,120,230, 4, 15,253,111, 58, 0, 64, 15,220, 34, 2,205, - 129, 1, 58, 0, 64, 15,220, 34, 2, 8,213,229, 87,230, 3,198, - 164, 95, 58, 0, 64, 15,220, 34, 2, 38, 18,120,230, 31,198,144, - 111, 58, 0, 64, 15,220, 34, 2,120,230,224, 15, 15, 71,126,176, - 253,115, 0,253,119, 1, 58, 0, 64, 15,220, 34, 2,123,214, 4, - 95, 45,126,253,115, 0,253,119, 1, 58, 0, 64, 15,220, 34, 2, - 122,246,240,221, 54, 0, 40,221,119, 1,225,209,201,205, 65, 8, - 195,230, 5, 71, 58, 0, 64, 15,220, 34, 2,120,229,230, 7, 33, - 136, 19,133,111,126,225,183,194,195, 3,120,205, 65, 8,195,195, - 3,230, 7,221, 54, 0, 40,221,119, 1,201,205,111, 8,195,230, - 5, 71, 58, 0, 64, 15,220, 34, 2,120,229,230, 7, 33,136, 19, - 133,111,126,225,183,194,114, 4,120,205,111, 8,195,195, 3,245, - 71, 58, 0, 64, 15,220, 34, 2,120,230, 4, 15,253,111, 58, 0, - 64, 15,220, 34, 2,205,129, 1, 58, 0, 64, 15,220, 34, 2,241, - 213,230, 7, 87,230, 3,198,164, 95, 58, 0, 64, 15,220, 34, 2, - 253,115, 0,253,112, 1, 58, 0, 64, 15,220, 34, 2,205,129, 1, - 58, 0, 64, 15,220, 34, 2,123,214, 4, 95,253,115, 0,253,112, - 1, 58, 0, 64, 15,220, 34, 2,209,201,205, 50, 9,195,230, 5, - 230, 7, 71, 58, 0, 64, 15,220, 34, 2,213,197,120, 17, 64, 19, - 131, 95, 58, 0, 64, 15,220, 34, 2,205,129, 1, 58, 0, 64, 15, - 220, 34, 2,120, 18,123,198, 8, 95,175, 18, 89,193, 75,209, 58, - 0, 64, 15,220, 34, 2,229,120, 38, 19,198,136,111,126,225,183, - 194,195, 3, 58, 0, 64, 15,220, 34, 2,120,229, 33, 64, 19,133, - 111, 70,225, 8, 58, 0, 64, 15,220, 34, 2, 8,205, 71, 9,195, - 195, 3,230, 7, 8, 58, 0, 64, 15,220, 34, 2,205,129, 1, 58, - 0, 64, 15,220, 34, 2, 8,245,230, 4, 15,253,111, 58, 0, 64, - 15,220, 34, 2,241,197,213,229, 38, 28,104, 86, 36, 94, 36, 78, - 235,245, 58, 0, 64, 15,220, 34, 2, 6, 7, 17,166, 19,120, 8, - 205,129, 1,235,112,235, 28,205,129, 1,235,112,235, 28,205,129, - 1,235,112,235, 28,205,129, 1,235,112,235, 28, 8, 71, 16,222, - 205,129, 1,235,112,235, 58, 0, 64, 15,220, 34, 2,241, 71,205, - 68, 12,120, 17, 96, 19,230, 7,131, 95,245,230, 3,198,176, 33, - 166, 19, 8, 58, 0, 64, 15,220, 34, 2, 8,253,119, 0, 70, 44, - 253,112, 1, 8,120, 18,123,198, 8, 95, 58, 0, 64, 15,220, 34, - 2, 8,214,128, 6, 28,253,119, 0, 78,253,113, 1,198, 4, 44, - 16,244, 58, 0, 64, 15,220, 34, 2,125,214, 24,111, 6, 4,126, - 18,123,198, 8, 95, 44, 16,247, 58, 0, 64, 15,220, 34, 2,241, - 225,209,193, 6, 0,195,126, 10,205,107, 10,195,230, 5,230, 7, - 71, 58, 0, 64, 15,220, 34, 2,213,197,120, 22, 19,198, 72, 95, - 58, 0, 64, 15,220, 34, 2,205,129, 1, 58, 0, 64, 15,220, 34, - 2,235,112,235, 89,193, 75,209, 58, 0, 64, 15,220, 34, 2,229, - 120, 33,136, 19,133,111,126,225,183,194,195, 3, 58, 0, 64, 15, - 220, 34, 2,120,229, 33, 72, 19,133,111, 70,225,245, 58, 0, 64, - 15,220, 34, 2,241,205,126, 10,195,195, 3,245, 58, 0, 64, 15, - 220, 34, 2,205,129, 1, 58, 0, 64, 15,220, 34, 2,241,197,213, - 229,230, 7,245, 38, 19,198, 88,111,112,241,245, 38, 19,198, 96, - 111, 8, 58, 0, 64, 15,220, 34, 2, 8,230, 7,246,224, 22, 31, - 95, 8, 26, 87, 58, 0, 64, 15,220, 34, 2, 8,230, 4, 15,253, - 111, 58, 0, 64, 15,220, 34, 2,241,230, 3,198, 64, 79,126,230, - 7, 95, 58, 0, 64, 15,220, 34, 2,125,198, 8,111,123,254, 7, - 56, 17,253,113, 0,126,130,250,222, 10,128,242,224, 10, 62,127, - 253,119, 1,121,198, 4, 79, 58, 0, 64, 15,220, 34, 2,125,198, - 8,111,123,254, 5, 56, 17,253,113, 0,126,130,250, 3, 11,128, - 242, 5, 11, 62,127,253,119, 1,121,198, 4, 79, 58, 0, 64, 15, - 220, 34, 2,125,198, 8,111,123,254, 4, 56, 17,253,113, 0,126, - 130,250, 40, 11,128,242, 42, 11, 62,127,253,119, 1,121,198, 4, - 79, 58, 0, 64, 15,220, 34, 2,125,198, 8,111,253,113, 0,126, - 130,250, 72, 11,128,242, 74, 11, 62,127,253,119, 1, 58, 0, 64, - 15,220, 34, 2,225,209,193,201, 71, 58, 0, 64, 15,220, 34, 2, - 120,230, 4, 15,253,111,120, 8, 58, 0, 64, 15,220, 34, 2,205, - 129, 1, 58, 0, 64, 15,220, 34, 2, 8,230, 3,198,180,253,119, - 0,253,112, 1,195,230, 5, 71, 58, 0, 64, 15,220, 34, 2,120, - 230, 4, 15,253,111,120, 8, 58, 0, 64, 15,220, 34, 2,205,129, - 1, 58, 0, 64, 15,220, 34, 2, 8,229,230, 7, 38, 19,198, 80, - 111,112, 8, 58, 0, 64, 15,220, 34, 2, 8,230, 7,198,136,111, - 8,126,183,225,194,195, 3, 58, 0, 64, 15,220, 34, 2, 8,230, - 3,198,180,253,119, 0,253,112, 1,195,195, 3,205,232, 11,195, - 230, 5,205,232, 11,195,195, 3,230, 1,135,253,111, 58, 0, 64, - 15,220, 34, 2,205,129, 1,197, 58, 0, 64, 15,220, 34, 2,205, - 129, 1, 58, 0, 64, 15,220, 34, 2,120,193,253,112, 0,253,119, - 1,201,230, 7, 71, 58, 0, 64, 15,220, 34, 2,229, 38, 19,120, - 198,136,111, 54, 1,225, 58, 0, 64, 15,220, 34, 2,120,230, 4, - 15,253,111,120,230, 3,135,135,198,180,253,119, 0,253, 54, 1, - 192,195,230, 5,230, 7,245,213,229, 79,230, 4, 15,253,111,121, - 230, 3,198, 64, 14, 6, 33,181, 18, 8, 58, 0, 64, 15,220, 34, - 2, 8, 94,253,119, 0,253,115, 1,198, 4, 8, 58, 0, 64, 15, - 220, 34, 2, 8,253,119, 0,253,115, 1,198, 4, 8, 58, 0, 64, - 15,220, 34, 2, 8,253,119, 0,253,115, 1,198, 4, 8, 58, 0, - 64, 15,220, 34, 2, 8,253,119, 0,253,115, 1,198, 4, 44, 13, - 194, 89, 12,225,209, 58, 0, 64, 15,220, 34, 2,241, 79,246,240, - 221, 54, 0, 40,221,113, 1,221, 54, 0, 40,221,119, 1,221, 54, - 0, 40,221,113, 1, 58, 0, 64, 15,220, 34, 2,201,120, 38, 19, - 198, 64,111,197,120, 70,205, 71, 9,193, 58, 0, 64, 15,220, 34, - 2,197,125,198, 8,111,120, 70,205,126, 10,193,125,198, 8,111, - 120,230, 3,198,180,253,119, 0,126,253,119, 1, 58, 0, 64, 15, - 220, 34, 2,201, 33, 48, 19, 6, 3,197,126,203,127, 32, 6, 6, - 15, 44,195,107, 13,230,127, 71, 44,126,128, 71, 58, 0, 64, 15, - 220, 34, 2,197, 44, 78, 44, 94, 44, 86,235, 58, 0, 64, 15,220, - 34, 2,205,129, 1, 58, 0, 64, 15,220, 34, 2,120,254,254,202, - 146, 13,254,255,202,167, 13,253,104, 58, 0, 64, 15,220, 34, 2, - 235,114, 45,115, 45,113, 45,193, 58, 0, 64, 15,220, 34, 2,253, - 125,230, 15,128, 71,254, 16, 56, 2, 6, 15, 58, 0, 64, 15,220, - 34, 2,120, 7, 7, 7,193,176, 15, 15, 15,246,144, 50, 17,127, - 125,214, 17,111, 58, 0, 64, 15,220, 34, 2, 5,242, 9, 13,195, - 73, 1, 58, 0, 64, 15,220, 34, 2, 28,235,113, 44,115, 44,114, - 235, 29, 29, 29,195, 43, 13, 58, 0, 64, 15,220, 34, 2, 28,235, - 78, 44, 94, 44, 86,235, 29, 29, 29,195, 43, 13,205,224, 13,195, - 230, 5, 71, 58, 0, 64, 15,220, 34, 2,120,229,230, 3, 33,144, - 19,133,111,126,225,183,194,132, 4,120,205,224, 13,195,195, 3, - 230, 3, 71, 8, 58, 0, 64, 15,220, 34, 2,229, 38, 19,120, 15, - 15, 15, 15,111,126,246,128,119, 58, 0, 64, 15,220, 34, 2,213, - 44, 44, 84,125,198, 6, 95, 58, 0, 64, 15,220, 34, 2, 26,119, - 44, 28, 26,119, 44, 28, 26,119,209,225, 58, 0, 64, 15,220, 34, - 2,205,129, 1, 58, 0, 64, 15,220, 34, 2, 8,229,213, 38, 18, - 104, 17, 17,127, 15, 15, 15, 70,176, 18, 44,126, 18,209,225,201, - 205, 83, 14,195,230, 5, 58,147, 19,183,194,132, 4,205, 83, 14, - 195,195, 3, 58, 0, 64, 15,220, 34, 2,229, 33, 48, 19,126,246, - 128,119, 58, 0, 64, 15,220, 34, 2,213, 44, 44, 84,125,198, 6, - 95, 58, 0, 64, 15,220, 34, 2, 26,119, 44, 28, 26,119, 44, 28, - 26,119,209,225, 58, 0, 64, 15,220, 34, 2,205,129, 1, 58, 0, - 64, 15,220, 34, 2, 62,224,176, 50, 17,127,201,205,192, 14,195, - 230, 5, 71, 58, 0, 64, 15,220, 34, 2,120,229,230, 3, 33,144, - 19,133,111,126,225,183,194,195, 3,120,205,192, 14,195,195, 3, - 230, 3, 71, 58, 0, 64, 15,220, 34, 2,229, 38, 19,120, 15, 15, - 15, 15,111,126,230,127,119,225,201,230, 3, 8, 58, 0, 64, 15, - 220, 34, 2,205,129, 1, 58, 0, 64, 15,220, 34, 2, 8,229, 38, - 19, 15, 15, 15, 15,111,126,230,128,176,119,225,195,230, 5,230, - 3, 8, 58, 0, 64, 15,220, 34, 2,205,129, 1, 58, 0, 64, 15, - 220, 34, 2, 8,213,229,245, 17,144, 19,131, 95, 26, 95, 58, 0, - 64, 15,220, 34, 2,241, 38, 19, 15, 15, 15, 15,198, 15,111,112, - 58, 0, 64, 15,220, 34, 2,123,183, 32, 16,125,214, 15,111,126, - 230,128,176,119, 58, 0, 64, 15,220, 34, 2,225,209,195,195, 3, - 230, 3, 8, 58, 0, 64, 15,220, 34, 2,205,129, 1, 58, 0, 64, - 15,220, 34, 2, 8,213,229, 22, 28, 88, 38, 19, 15, 15, 15, 15, - 198, 10,111, 58, 0, 64, 15,220, 34, 2, 26,119, 20, 45, 26,119, - 20, 45, 26,119, 58, 0, 64, 15,220, 34, 2,125,214, 8,111, 54, - 0,225,209,195,230, 5,230, 3, 8, 58, 0, 64, 15,220, 34, 2, - 205,129, 1, 58, 0, 64, 15,220, 34, 2, 8,213,229, 22, 28, 88, - 33,144, 19,245,133,111,241, 70, 38, 19, 15, 15, 15, 15,198, 15, - 111, 58, 0, 64, 15,220, 34, 2,119, 45, 26,119, 20, 45, 26,119, - 20, 45, 26,119, 58, 0, 64, 15,220, 34, 2,120,183,202,229, 15, - 225,209,195,195, 3, 58, 0, 64, 15,220, 34, 2, 84,125,214, 4, - 95,126, 18, 44, 28,126, 18, 44, 28,126, 18, 58, 0, 64, 15,220, - 34, 2,125,214, 8,111, 54, 0,225,209,195,195, 3,205, 49, 16, - 195,230, 5, 71, 58, 0, 64, 15,220, 34, 2,120,229,230, 15, 38, - 19,198,136,111,126,225,183,194,114, 4,120,205, 49, 16,195,195, - 3,230, 3, 8, 58, 0, 64, 15,220, 34, 2,205,129, 1, 58, 0, - 64, 15,220, 34, 2, 8,213, 17, 17,127, 15, 15, 15,176,246,128, - 18, 58, 0, 64, 15,220, 34, 2,205,129, 1, 58, 0, 64, 15,220, - 34, 2,235,112,235,209,201,205,132, 14,195,230, 5, 58,147, 19, - 183,194,132, 4,205,132, 14,195,195, 3,230, 3, 71, 58, 0, 64, - 15,220, 34, 2,229, 38, 19,120,198,144,111, 54, 1, 58, 0, 64, - 15,220, 34, 2,120, 15, 15, 15, 15,111, 38, 19, 54, 0,225,195, - 230, 5,205,194, 16,195, 43, 1,205,194, 16,195, 63, 1,230, 15, - 60, 71,205,211, 16,195, 43, 1,230, 15, 60, 71,205,211, 16,195, - 63, 1, 58, 0, 64, 15,220, 34, 2,205,129, 1, 58, 0, 64, 15, - 220, 34, 2,235,114, 45,115, 45,113, 58, 0, 64, 15,220, 34, 2, - 45,112,201, 33,240, 31, 17, 88, 19, 14, 8, 26, 70,128,242,243, - 16, 62,127, 71,125,205,126, 10, 44, 28, 13, 32,238, 33,232, 31, - 17, 1, 19, 1, 16, 4,126, 18, 44,123,129, 95, 58, 0, 64, 15, - 220, 34, 2, 16,241,175, 50,241, 31,201,255,255,255,255,255,255, - 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, - 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, - 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, - 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, - 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, - 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, - 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 195,104, 1, 0, 0, 0, 0, 0,201,217,221, 54, 0, 39,221, 54, + 1, 31,126, 60, 40, 12,221, 54, 0, 42,221,119, 1, 44, 40, 25, + 217,201, 62,201, 50, 8, 0,221, 54, 0, 42,221, 54, 1,128,221, + 54, 0, 43,221, 54, 1, 0,217,201, 58,152, 18,185,202, 87, 0, + 121, 50,152, 18, 33, 0, 96,119, 15,119, 15,119, 15,119, 15,119, + 15,119, 15,119,116, 15,119, 33,240, 18, 26,119, 44, 28, 26,119, + 44, 28, 26,119, 44, 28, 26,119, 44, 28, 26,119, 44, 28, 26,119, + 44, 28, 26,119, 44, 28, 26,119, 44, 28, 26,119, 44, 28, 26,119, + 44, 28, 26,119, 44, 28, 26,119, 44, 28, 26,119, 44, 28, 26,119, + 44, 28, 26,119, 44, 28, 26,119, 44, 28,194,164, 0, 20,194,164, + 0, 22,128, 12, 46,240,195, 10, 0,205,193, 0,195,238, 5, 58, + 0, 64, 15,207, 58,142, 18,183,194,188, 4,205,193, 0,195, 7, + 4, 58,236, 31,183,200,205,234, 2,120,217, 38, 28,111, 86, 36, + 94, 36, 78, 33, 0, 96,121, 50,152, 18,119, 15,119, 15,119, 15, + 119, 15,119, 15,119, 15,119,116, 15,119, 38, 18,123,246,240,111, + 69, 26,119, 28, 44,194,241, 0,104,123,183,194, 5, 1, 20,194, + 5, 1, 22,128, 12,217, 62,208, 50, 8, 0,221, 54, 0, 43,221, + 54, 1,128,221, 54, 0, 42,221, 54, 1,128,201,205, 52, 1,195, + 238, 5, 58, 0, 64, 15,207, 58,142, 18,183,194, 7, 4,205, 52, + 1,195, 7, 4, 62,201, 50, 8, 0,221, 54, 0, 43,221, 54, 1, + 0,201, 62, 1, 50,142, 18,205, 52, 1,195,238, 5, 58,252, 31, + 47, 71, 33, 0, 64, 54, 36, 15, 15,246,192, 44,119,120, 45, 54, + 37,230, 3, 44,119,195, 81, 2,175, 50,240, 31, 50,251, 31, 49, + 224, 31, 33, 17,127, 54,159, 54,191, 54,223, 54,255,175, 50, 0, + 18, 50, 16, 18, 50, 32, 18, 50, 48, 18, 33, 0, 96,117,117,117, + 117,117,117,117,117,117,221, 33, 0, 64,253, 38, 64,217, 6, 0, + 217,221, 54, 0, 43,221, 54, 1, 0, 30,127, 62, 64, 6, 4,221, + 119, 0,221,115, 1,221,119, 2,221,115, 3, 60,221,119, 0,221, + 115, 1,221,119, 2,221,115, 3, 60,221,119, 0,221,115, 1,221, + 119, 2,221,115, 3, 60, 60, 16,214,221, 54, 0,180,221, 54, 1, + 192,221, 54, 0,181,221, 54, 1,192,221, 54, 0,182,221, 54, 1, + 192,221, 54, 2,180,221, 54, 3,192,221, 54, 2,181,221, 54, 3, + 192,221, 54, 2,182,221, 54, 3,192,221, 54, 0, 36,221, 54, 1, + 254,221, 54, 0, 37,221, 54, 1, 3,221, 54, 0, 38,221, 54, 1, + 201,221, 54, 0, 39,221, 54, 1, 63,195,102, 2, 61,202,194, 2, + 61,202,137, 5, 61,202,164, 6, 61,202, 23, 3, 61,202,213, 4, + 61,202,181, 3, 61,202, 77, 1, 61,202, 93, 3, 58, 0, 64, 15, + 207, 42,248, 31, 34,252, 31, 42,250, 31, 34,254, 31,175, 50,251, + 31, 58, 0, 64, 15,207, 58,255, 31,183, 32,192, 58, 0, 64, 15, + 207, 58, 0, 64,203, 79, 32, 8,203, 71,196, 8, 0,195,102, 2, + 58, 0, 64, 15,207,221, 54, 0, 39,221, 54, 1, 47, 58, 0, 64, + 15,207, 58,241, 31,183,196, 71, 16,195,156, 2, 58, 0, 64, 15, + 207,205, 94, 7, 58, 0, 64, 15,207, 58,169, 18,183, 32, 3,195, + 178, 2, 58, 0, 64, 15,207,195,136, 12, 58, 0, 64, 15,207,195, + 102, 2, 42,253, 31, 58,252, 31, 79, 17, 0, 28,205,234, 2,120, + 183,202,231, 2, 18, 20,205,234, 2,120, 18, 20,205,234, 2,120, + 18, 21, 21, 28,195,204, 2,195, 81, 2, 58,152, 18,185,202, 10, + 3,121, 50,152, 18,229, 33, 0, 96,119, 15,119, 15,119, 15,119, + 15,119, 15,119, 15,119,116, 15,119,225, 70, 44,194, 22, 3, 36, + 194, 22, 3, 38,128, 12,201, 58, 0, 64, 15,207,205,251, 4, 58, + 0, 64, 15,207, 58,240, 31,246, 2, 50,240, 31, 58, 0, 64, 15, + 207, 33,252, 31, 78, 44, 94, 44, 86, 58, 0, 64, 15,207,175, 50, + 169, 18, 60, 33,153, 18,119, 44,119, 44,113, 44,115, 44,114, 58, + 0, 64, 15,207, 33,234, 3, 34,176, 2,195, 81, 2, 58,153, 18, + 183,202, 81, 2, 62, 1, 50,169, 18, 6,127, 14, 7, 33,143, 18, + 58, 0, 64, 15,207,126,183, 32, 4,121,205, 54, 10, 58, 0, 64, + 15,207, 45, 13,242,112, 3, 6, 4, 14, 15, 17,144, 18, 33, 0, + 18, 58, 0, 64, 15,207, 26,183, 32, 5,126,230,128,177,119, 58, + 0, 64, 15,207,125,198, 16,111, 28, 16,230, 58,142, 18,183,204, + 52, 1,195, 81, 2, 58,153, 18,183,202, 81, 2,175, 50,169, 18, + 6, 4, 17,147, 18, 33, 63, 18, 58, 0, 64, 15,207, 78,125,214, + 15,111, 26,183, 32, 5,126,230,128,177,119, 58, 0, 64, 15,207, + 45, 29, 16,228,205, 71, 16,195, 81, 2, 58, 0, 64, 15,207, 33, + 154, 18,126, 61,202,251, 3,119,195,178, 2, 58, 0, 64, 15,207, + 44, 78, 44, 94, 44, 86,235, 58, 0, 64, 15,207,205,234, 2, 58, + 0, 64, 15,207,120,254, 8,218,138, 7,254, 11,218, 52, 13,202, + 172, 13,254, 12,202,175, 0, 58, 0, 64, 15,207,120,254, 24,218, + 27, 8,254, 28,218,254, 13,202, 34, 1, 58, 0, 64, 15,207,120, + 254,254,202,208, 15,254,255,202,207, 4,254,252,202,107, 5,254, + 253,202,122, 5, 58, 0, 64, 15,207,120,254, 40,218,229, 9,254, + 44,218, 83, 14, 58, 0, 64, 15,207,120,254, 56,218, 71, 8,254, + 59,218, 73, 15,202,153, 15, 58, 0, 64, 15,207,120,254, 72,218, + 182, 8,254, 76,218,216, 14, 58, 0, 64, 15,207,120,254,224,218, + 224, 15,254,248,218, 47, 11,254,250,218,128, 11,202, 11, 16,254, + 251,202, 44, 16, 58, 0, 64, 15,207,195,207, 4, 58, 0, 64, 15, + 207, 44,194,188, 4, 36,194,188, 4, 38,128, 12, 58, 0, 64, 15, + 207, 44,194,204, 4, 36,194,204, 4, 38,128, 12,195, 7, 4,205, + 219, 4,195,178, 2,205,219, 4,195, 81, 2, 58,240, 31,230,253, + 50,240, 31, 58, 0, 64, 15,207,205,251, 4, 58, 0, 64, 15,207, + 175, 50,153, 18, 33,178, 2, 34,176, 2,201, 58,142, 18,183,204, + 52, 1, 6, 4, 17, 63, 18, 33,147, 18, 58, 0, 64, 15,207, 54, + 0,123,214, 15, 95,126,183, 32, 2,175, 18, 58, 0, 64, 15,207, + 29, 45, 16,230, 6, 8, 17, 79, 18, 58, 0, 64, 15,207, 62,127, + 18, 29, 58, 0, 64, 15,207,126,183,194, 88, 5, 5,120,205,216, + 11, 58, 0, 64, 15,207,120,230, 4,253,111,120,230, 3,198,180, + 253,119, 0,253, 54, 1,192, 4, 45, 16,206, 33, 80, 18, 62,192, + 6, 8,119, 44, 16,252,175, 50,242, 31,201, 58, 0, 64, 15,207, + 42,159, 18, 58,158, 18, 79,195, 7, 4, 58, 0, 64, 15,207,121, + 50,158, 18, 34,159, 18,195, 7, 4, 58, 0, 64, 15,207,205,212, + 6, 58, 0, 64, 15,207, 58,240, 31,246, 1, 50,240, 31, 58, 0, + 64, 15,207, 33,252, 31, 78, 44, 94, 44, 86, 58, 0, 64, 15,207, + 33,161, 18, 54, 1, 44, 54, 1, 44,113, 44,115, 44,114, 58, 0, + 64, 15,207, 33,209, 5, 34,154, 2, 58, 0, 64, 15,207,195, 81, + 2, 58, 0, 64, 15,207, 33,162, 18,126, 61,202,226, 5,119,195, + 156, 2, 58, 0, 64, 15,207, 44, 78, 44, 94, 44, 86,235, 58, 0, + 64, 15,207,205,234, 2, 58, 0, 64, 15,207,120,254, 8,218,132, + 7,254, 11,218, 46, 13,202,166, 13,254, 12,202,169, 0, 58, 0, + 64, 15,207,120,254, 24,218, 21, 8,254, 28,218,248, 13,202, 28, + 1, 58, 0, 64, 15,207,120,254,254,202,202, 15,254,255,202,158, + 6, 58, 0, 64, 15,207,120,254, 40,218,208, 9,254, 44,218, 49, + 14, 58, 0, 64, 15,207,120,254, 56,218, 65, 8,254, 59,218, 67, + 15,202,147, 15, 58, 0, 64, 15,207,120,254, 72,218,176, 8,254, + 76,218,154, 14, 58, 0, 64, 15,207,120,254,224,218,214, 15,254, + 232,218,170, 11,254,236,218,166, 15,202, 66, 1, 58, 0, 64, 15, + 207,120,254,248,218, 6, 11,254,250,218,122, 11,202, 5, 16,254, + 251,202, 38, 16,254,252,202, 64, 7,254,253,202, 79, 7,205,170, + 6,195,156, 2,205,170, 6,195, 81, 2, 58, 0, 64, 15,207, 58, + 240, 31,230,254, 50,240, 31, 58, 0, 64, 15,207,175, 50,161, 18, + 33,156, 2, 34,154, 2, 58, 0, 64, 15,207,205,212, 6, 58, 0, + 64, 15,207,201, 58,142, 18,183,196, 52, 1, 6, 4, 17,147, 18, + 58, 0, 64, 15,207, 26,183, 40, 56,175, 18, 58, 0, 64, 15,207, + 120, 15, 15, 15, 15, 61, 38, 18,111, 78,214, 15,111,113, 58, 0, + 64, 15,207,213,125,198, 8,111,198, 4, 95, 84, 58, 0, 64, 15, + 207, 26,119, 44, 28, 26,119, 44, 28, 26,119,209, 58, 0, 64, 15, + 207, 29, 16,188, 6, 8, 58, 0, 64, 15,207, 26,183,202, 60, 7, + 175, 18, 58, 0, 64, 15,207, 5,205, 85, 12, 4, 29, 16,231,201, + 58, 0, 64, 15,207, 42,167, 18, 58,166, 18, 79,195,238, 5, 58, + 0, 64, 15,207,121, 50,166, 18, 34,167, 18,195,238, 5, 58, 0, + 31, 60,200, 58, 0, 64, 15,207, 33,120, 7, 34, 72, 4, 33, 0, + 31, 58,152, 18, 79,195, 7, 4, 33,207, 4, 34, 72, 4, 62,255, + 50, 0, 31,201,205,166, 7,195,238, 5, 71, 58, 0, 64, 15,207, + 229,120,230, 7, 33,136, 18,133,111,126,225,183,194,188, 4,120, + 205,166, 7,195, 7, 4,230, 7,221, 54, 0, 40,221,119, 1, 71, + 8, 58, 0, 64, 15,207,120,230, 4, 15,253,111, 58, 0, 64, 15, + 207,205,234, 2, 58, 0, 64, 15,207, 8,213,229, 87,230, 3,198, + 164, 95, 58, 0, 64, 15,207, 38, 17,120,230, 31,198,144,111, 58, + 0, 64, 15,207,120,230,224, 15, 15, 71,126,176,253,115, 0,253, + 119, 1, 58, 0, 64, 15,207,123,214, 4, 95, 45,126,253,115, 0, + 253,119, 1, 58, 0, 64, 15,207,122,246,240,221, 54, 0, 40,221, + 119, 1,225,209,201,205, 55, 8,195,238, 5, 71, 58, 0, 64, 15, + 207,120,229,230, 7, 33,136, 18,133,111,126,225,183,194, 7, 4, + 120,205, 55, 8,195, 7, 4,230, 7,221, 54, 0, 40,221,119, 1, + 201,205, 99, 8,195,238, 5, 71, 58, 0, 64, 15,207,120,229,230, + 7, 33,136, 18,133,111,126,225,183,194,172, 4,120,205, 99, 8, + 195, 7, 4,245, 71, 58, 0, 64, 15,207,120,230, 4, 15,253,111, + 58, 0, 64, 15,207,205,234, 2, 58, 0, 64, 15,207,241,213,230, + 7, 87,230, 3,198,164, 95, 58, 0, 64, 15,207,253,115, 0,253, + 112, 1, 58, 0, 64, 15,207,205,234, 2, 58, 0, 64, 15,207,123, + 214, 4, 95,253,115, 0,253,112, 1, 58, 0, 64, 15,207,209,201, + 205, 12, 9,195,238, 5,230, 7, 71, 58, 0, 64, 15,207,213,197, + 120, 17, 64, 18,131, 95, 58, 0, 64, 15,207,205,234, 2, 58, 0, + 64, 15,207,120, 18,123,198, 8, 95,175, 18, 89,193, 75,209, 58, + 0, 64, 15,207,229,120, 38, 18,198,136,111,126,225,183,194, 7, + 4, 58, 0, 64, 15,207,120,229, 33, 64, 18,133,111, 70,225, 8, + 58, 0, 64, 15,207, 8,205, 29, 9,195, 7, 4,230, 7, 8, 58, + 0, 64, 15,207,205,234, 2, 58, 0, 64, 15,207, 8,245,230, 4, + 15,253,111, 58, 0, 64, 15,207,241,197,213,229, 38, 28,104, 86, + 36, 94, 36, 78,235,245, 58, 0, 64, 15,207, 6, 7, 17,176, 18, + 120, 8,205,234, 2,235,112,235, 28,205,234, 2,235,112,235, 28, + 205,234, 2,235,112,235, 28,205,234, 2,235,112,235, 28, 8, 71, + 16,222,205,234, 2,235,112,235, 58, 0, 64, 15,207,241, 71,205, + 216, 11,120, 17, 96, 18,230, 7,131, 95,245,230, 3,198,176, 33, + 176, 18, 8, 58, 0, 64, 15,207, 8,253,119, 0, 70, 44,253,112, + 1, 8,120, 18,123,198, 8, 95, 58, 0, 64, 15,207, 8,214,128, + 6, 28,253,119, 0, 78,253,113, 1,198, 4, 44, 16,244, 58, 0, + 64, 15,207,125,214, 24,111, 6, 4,126, 18,123,198, 8, 95, 44, + 16,247, 58, 0, 64, 15,207,241,225,209,193, 6, 0,195, 60, 10, + 245, 58, 0, 64, 15,207,205,234, 2, 58, 0, 64, 15,207,241,205, + 60, 10,195,238, 5,230, 7, 71, 58, 0, 64, 15,207,213,197,120, + 22, 18,198, 72, 95, 58, 0, 64, 15,207,205,234, 2, 58, 0, 64, + 15,207,235,112,235, 89,193, 75,209, 58, 0, 64, 15,207,229,120, + 33,136, 18,133,111,126,225,183,194, 7, 4, 58, 0, 64, 15,207, + 120,229, 33, 72, 18,133,111, 70,225,245, 58, 0, 64, 15,207,241, + 205, 60, 10,195, 7, 4,197,213,229,195, 73, 10,197,213,229,230, + 7,245, 38, 18,198, 88,111,112,241,245, 38, 18,198, 96,111, 8, + 58, 0, 64, 15,207, 8,230, 7,246,224, 22, 31, 95, 8, 26, 87, + 58, 0, 64, 15,207, 8,230, 4, 15,253,111, 58, 0, 64, 15,207, + 241,230, 3,198, 64, 79,126,230, 7, 95, 58, 0, 64, 15,207,125, + 198, 8,111,123,254, 7, 56, 17,253,113, 0,126,130,250,148, 10, + 128,242,150, 10, 62,127,253,119, 1,121,198, 4, 79, 58, 0, 64, + 15,207,125,198, 8,111,123,254, 5, 56, 17,253,113, 0,126,130, + 250,183, 10,128,242,185, 10, 62,127,253,119, 1,121,198, 4, 79, + 58, 0, 64, 15,207,125,198, 8,111,123,254, 4, 56, 17,253,113, + 0,126,130,250,218, 10,128,242,220, 10, 62,127,253,119, 1,121, + 198, 4, 79, 58, 0, 64, 15,207,125,198, 8,111,253,113, 0,126, + 130,250,248, 10,128,242,250, 10, 62,127,253,119, 1, 58, 0, 64, + 15,207,225,209,193,201, 71, 58, 0, 64, 15,207,120,230, 4, 15, + 253,111,120, 8, 58, 0, 64, 15,207,205,234, 2, 58, 0, 64, 15, + 207, 8,230, 3,198,180,253,119, 0,253,112, 1,195,238, 5, 71, + 58, 0, 64, 15,207,120,230, 4, 15,253,111,120, 8, 58, 0, 64, + 15,207,205,234, 2, 58, 0, 64, 15,207, 8,229,230, 7, 38, 18, + 198, 80,111,112, 8, 58, 0, 64, 15,207, 8,230, 7,198,136,111, + 8,126,183,225,194, 7, 4, 58, 0, 64, 15,207, 8,230, 3,198, + 180,253,119, 0,253,112, 1,195, 7, 4,205,134, 11,195,238, 5, + 205,134, 11,195, 7, 4,230, 1,135,253,111, 58, 0, 64, 15,207, + 205,234, 2,197, 58, 0, 64, 15,207,205,234, 2, 58, 0, 64, 15, + 207,120,193,253,112, 0,253,119, 1,201,230, 7, 71, 58, 0, 64, + 15,207,229, 38, 18,120,198,136,111, 54, 1,225, 58, 0, 64, 15, + 207,120,230, 4, 15,253,111,120,230, 3,135,135,198,180,253,119, + 0,253, 54, 1,192,195,238, 5,230, 7,245,213,229, 79,230, 4, + 15,253,111,121,230, 3,198, 64, 14, 6, 33,181, 17, 8, 58, 0, + 64, 15,207, 8, 94,253,119, 0,253,115, 1,198, 4, 8, 58, 0, + 64, 15,207, 8,253,119, 0,253,115, 1,198, 4, 8, 58, 0, 64, + 15,207, 8,253,119, 0,253,115, 1,198, 4, 8, 58, 0, 64, 15, + 207, 8,253,119, 0,253,115, 1,198, 4, 44, 13,194,237, 11,225, + 209, 58, 0, 64, 15,207,241, 79,246,240,221, 54, 0, 40,221,113, + 1,221, 54, 0, 40,221,119, 1,221, 54, 0, 40,221,113, 1, 58, + 0, 64, 15,207,201,120, 38, 18,198, 64,111,197,120, 70,205, 29, + 9,193, 58, 0, 64, 15,207,197,125,198, 8,111,120, 70,205, 60, + 10,193,125,198, 8,111,120,230, 3,198,180,253,119, 0,126,253, + 119, 1, 58, 0, 64, 15,207,201, 33, 48, 18, 6, 3,197,126,183, + 250,153, 12, 6, 15, 44,195,229, 12,230,127, 71, 44,126,128, 71, + 58, 0, 64, 15,207,197, 44, 78, 44, 94, 44, 86,235, 58, 0, 64, + 15,207,205,234, 2, 58, 0, 64, 15,207,120,254,254,202, 8, 13, + 254,255,202, 27, 13,253,104, 58, 0, 64, 15,207,235,114, 45,115, + 45,113, 45,193, 58, 0, 64, 15,207,253,125,230, 15,128, 71,254, + 16, 56, 2, 6, 15, 58, 0, 64, 15,207,120, 7, 7, 7,193,176, + 15, 15, 15,246,144, 50, 17,127,125,214, 17,111, 58, 0, 64, 15, + 207, 5,242,141, 12,195,186, 2, 58, 0, 64, 15,207, 28,235,113, + 44,115, 44,114,235, 29, 29, 29,195,173, 12, 58, 0, 64, 15,207, + 28,235, 78, 44, 94, 44, 86,235, 29, 29, 29,195,173, 12,205, 80, + 13,195,238, 5, 71, 58, 0, 64, 15,207,120,229,230, 3, 33,144, + 18,133,111,126,225,183,194,188, 4,120,205, 80, 13,195, 7, 4, + 230, 3, 71, 8, 58, 0, 64, 15,207,229, 38, 18,120, 15, 15, 15, + 15,111,126,246,128,119, 58, 0, 64, 15,207,213, 44, 44, 84,125, + 198, 6, 95, 58, 0, 64, 15,207, 26,119, 44, 28, 26,119, 44, 28, + 26,119,209,225, 58, 0, 64, 15,207,205,234, 2, 58, 0, 64, 15, + 207, 8,229,213, 38, 17,104, 17, 17,127, 15, 15, 15, 70,176, 18, + 44,126, 18,209,225,201,205,185, 13,195,238, 5, 58,147, 18,183, + 194,188, 4,205,185, 13,195, 7, 4, 58, 0, 64, 15,207,229, 33, + 48, 18,126,246,128,119, 58, 0, 64, 15,207,213, 44, 44, 84,125, + 198, 6, 95, 58, 0, 64, 15,207, 26,119, 44, 28, 26,119, 44, 28, + 26,119,209,225, 58, 0, 64, 15,207,205,234, 2, 58, 0, 64, 15, + 207, 62,224,176, 50, 17,127,201,205, 26, 14,195,238, 5, 71, 58, + 0, 64, 15,207,120,229,230, 3, 33,144, 18,133,111,126,225,183, + 194, 7, 4,120,205, 26, 14,195, 7, 4,230, 3, 71, 58, 0, 64, + 15,207,229, 38, 18,120, 15, 15, 15, 15,111,126,230,127,119,225, + 201,230, 3, 8, 58, 0, 64, 15,207,205,234, 2, 58, 0, 64, 15, + 207, 8,229, 38, 18, 15, 15, 15, 15,111,126,230,128,176,119,225, + 195,238, 5,230, 3, 8, 58, 0, 64, 15,207,205,234, 2, 58, 0, + 64, 15,207, 8,213,229,245, 17,144, 18,131, 95, 26, 95, 58, 0, + 64, 15,207,241, 38, 18, 15, 15, 15, 15,198, 15,111,112, 58, 0, + 64, 15,207,123,183, 32, 14,125,214, 15,111,126,230,128,176,119, + 58, 0, 64, 15,207,225,209,195, 7, 4,230, 3, 8, 58, 0, 64, + 15,207,205,234, 2, 58, 0, 64, 15,207, 8,213,229, 22, 28, 88, + 38, 18, 15, 15, 15, 15,198, 10,111, 58, 0, 64, 15,207, 26,119, + 20, 45, 26,119, 20, 45, 26,119, 58, 0, 64, 15,207,125,214, 8, + 111, 54, 0,225,209,195,238, 5,230, 3, 8, 58, 0, 64, 15,207, + 205,234, 2, 58, 0, 64, 15,207, 8,213,229, 22, 28, 88, 33,144, + 18,245,133,111,241, 70, 38, 18, 15, 15, 15, 15,198, 15,111, 58, + 0, 64, 15,207,119, 45, 26,119, 20, 45, 26,119, 20, 45, 26,119, + 58, 0, 64, 15,207,120,183,202, 31, 15,225,209,195, 7, 4, 58, + 0, 64, 15,207, 84,125,214, 4, 95,126, 18, 44, 28,126, 18, 44, + 28,126, 18, 58, 0, 64, 15,207,125,214, 8,111, 54, 0,225,209, + 195, 7, 4,205,101, 15,195,238, 5, 71, 58, 0, 64, 15,207,120, + 229,230, 15, 38, 18,198,136,111,126,225,183,194,172, 4,120,205, + 101, 15,195, 7, 4,230, 3, 8, 58, 0, 64, 15,207,205,234, 2, + 58, 0, 64, 15,207, 8,213, 17, 17,127, 15, 15, 15,176,246,128, + 18, 58, 0, 64, 15,207,205,234, 2, 58, 0, 64, 15,207,235,112, + 235,209,201,205,228, 13,195,238, 5, 58,147, 18,183,194,188, 4, + 205,228, 13,195, 7, 4,230, 3, 71, 58, 0, 64, 15,207,229, 38, + 18,120,198,144,111, 54, 1, 58, 0, 64, 15,207,120, 15, 15, 15, + 15,111, 38, 18, 54, 0,225,195,238, 5,205,234, 15,195,156, 2, + 205,234, 15,195,178, 2,230, 15, 60, 71,205,247, 15,195,156, 2, + 230, 15, 60, 71,205,247, 15,195,178, 2, 58, 0, 64, 15,207,205, + 234, 2, 58, 0, 64, 15,207,235,114, 45,115, 45,113, 58, 0, 64, + 15,207, 45,112,201,205, 17, 16,195,238, 5,205, 17, 16,195, 7, + 4, 58, 0, 64, 15,207,205,234, 2, 58, 0, 64, 15,207, 58,242, + 31,176, 50,242, 31,201,205, 50, 16,195,238, 5,205, 50, 16,195, + 7, 4, 58, 0, 64, 15,207,205,234, 2, 58, 0, 64, 15,207, 58, + 242, 31,160, 50,242, 31,201, 33,240, 31, 17, 88, 18, 14, 8, 26, + 70,128,242, 87, 16, 62,127, 71,125,205, 60, 10, 44, 28, 13, 58, + 0, 64, 15,207, 32,233, 33,232, 31, 17, 1, 18, 1, 16, 4,126, + 18, 44,123,129, 95, 58, 0, 64, 15,207, 16,243,175, 50,241, 31, + 201,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, @@ -313,9 +297,9 @@ static uint8_t echo_blob[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 diff --git a/doc/api-asm.68k b/doc/api-asm.68k index 8c0995c..3293b9e 100644 --- a/doc/api-asm.68k +++ b/doc/api-asm.68k @@ -20,6 +20,7 @@ Unless stated otherwise, calling the API subroutines will *not* modify the *** Initialization *** Echo_Init + in a0 = pointer to instrument list Initializes Echo. Loads the instrument list, loads the Z80 engine and gets it running. You need to call this before you can use Echo (usually when @@ -42,20 +43,29 @@ Echo_Init *** Background music *** Echo_PlayBGM + in a0 = pointer to ESF data to play Starts playback of the specified background music. The register a0 points to the ESF data for the background music. Echo_StopBGM - Stops playback of background music. Used both to stop and to pause music - (the latter can be undone with Echo_ResumeBGM, see below). + Stops playback of background music. Used both to stop and to pause music. + +Echo_PauseBGM + + Pauses BGM playback (SFXs should be unaffected). + +Echo_ResumeBGM + + Resumes BGM playback after it has been paused with Echo_PauseBGM. ============================================================================= *** Sound effects *** Echo_PlaySFX + in a0 = pointer to ESF data to play Starts playback of the specified sound effect. The register a0 points to the ESF data for the sound effect. @@ -69,6 +79,7 @@ Echo_StopSFX *** Direct events *** Echo_PlayDirect + in a0 = pointer to ESF data to inject Injects events to be played as part of the BGM the next tick. The register a0 points to the ESF data to be injected. @@ -91,6 +102,7 @@ Echo_PlayDirect *** Control *** Echo_GetStatus + out d0 = status (see below) Gets the current status of Echo. The status is returned as a word in d0, with the following bits set as relevant: @@ -105,6 +117,7 @@ Echo_GetStatus the 68000 until Echo is ready to take more commands. Echo_SetVolume + in d0 = new volume ($00 = quietest, $FF = loudest) Sets the global volume. Register d0 is a byte value ranging from 0 (quietest) to 255 (loudest), and every channel is affected immediately. @@ -114,20 +127,26 @@ Echo_SetVolume on the volume value (the cut off point is at 25%). Echo_SetVolumeEx + in a0 = pointer to volume data (see below) Sets the global volume for each channel separately. Register a0 points to - a list of 13 bytes (one for each Echo channel). Values for FM and PSG + a list of 16 bytes (one for each Echo channel). Values for FM and PSG channels are given in the same way as in events, that is: logarithmic scale, 0..127 for FM, 0..15 for PSG, lower = louder. The last byte (the one belonging to the PCM channel) is used to toggle whether PCM plays, either 0 (disabled) or 1 (enabled). + + NOTE: the Echo 1.4 docs requested for 13 bytes instead of 16. This has + been changed for the sake of expansion. Currently the extra bytes are + ignored, but consider adapting your code (just set them to zero). ============================================================================= *** Settings *** Echo_SetPCMRate + in d0 = new PCM rate (see below) Changes the sample rate of PCM. Note this is a global parameter as it affects both BGM and SFX. The value is what one would write in timer A of @@ -153,17 +172,22 @@ Echo_SetPCMRate *** Raw access *** Echo_SendCommand + in d0 = command Sends an argument-less command to Echo. The command ID is given as a byte in register d0. Echo_SendCommandAddr + in d0 = command + in a0 = address Sends a command to Echo that takes an address as its argument. The command ID is given as a byte in register d0, while the address argument is given in register a0. Echo_SendCommandByte + in d0 = command + in d1 = argument Sends a command to Echo that takes a byte as its argument. The command ID is given as a byte in register d0, while the byte argument is given in diff --git a/doc/api-c.txt b/doc/api-c.txt index 24c6312..541a895 100644 --- a/doc/api-c.txt +++ b/doc/api-c.txt @@ -52,8 +52,15 @@ void echo_play_bgm(const void *esf) void echo_stop_bgm() - Stops playback of background music. Used both to stop and to pause music - (the latter can be undone with echo_resume_bgm, see below). + Stops playback of background music. Used both to stop and to pause music. + +void echo_pause_bgm() + + Pauses BGM playback (SFXs should be unaffected). + +void echo_resume_bgm() + + Resumes BGM playback after it has been paused with echo_pause_bgm. ============================================================================= @@ -120,12 +127,16 @@ void echo_set_volume(uint8_t vol) void echo_set_volume_ex(const uint8_t *ptr) Sets the global volume for each channel separately. The parameter 'ptr' - points to a list of 13 bytes (one for each Echo channel). Values for FM + points to a list of 16 bytes (one for each Echo channel). Values for FM and PSG channels are given in the same way as in events, that is: logarithmic scale, 0..127 for FM, 0..15 for PSG, lower = louder. The last byte (the one belonging to the PCM channel) is used to toggle whether PCM plays, either 0 (disabled) or 1 (enabled). + + NOTE: the Echo 1.4 docs requested for 13 bytes instead of 16. This has + been changed for the sake of expansion. Currently the extra bytes are + ignored, but consider adapting your code (just set them to zero). ============================================================================= @@ -162,6 +173,7 @@ void echo_send_command(uint8_t command) command to send, and may be one of the following: ECHO_CMD_STOPBGM ..... Stop background music playback + ECHO_CMD_PAUSEBGM .... Pause background music playback ECHO_CMD_RESUMEBGM ... Resume background music playback ECHO_CMD_STOPSFX ..... Stop sound effect playback diff --git a/doc/esf.txt b/doc/esf.txt index a96e35d..eb04474 100644 --- a/doc/esf.txt +++ b/doc/esf.txt @@ -367,12 +367,27 @@ $F9rrnn: Set FM register in bank 1 ============================================================================= -$FC: Go to loop [BGM ONLY] -$FD: Set loop point [BGM ONLY] +$FAnn: Set flags - This event are used in BGM streams to loop music. Put event $FD where the + This event will set some of the flags. The value nn is a bitmask that is + OR'd with the current flags. + +$FBnn: Clear flags + + This event will clear some of the flags. The value nn is a bitmask that + is AND'd with the current flags. + +============================================================================= + +$FC: Go to loop +$FD: Set loop point + + This event are used in streams to loop music. Put event $FD where the loop starts, and then end the stream using event $FC (don't use event $FF). This will tell Echo to loop the song instead of stopping playback. + + SFX support for this event was added in 1.5, if you loop a sound effect + you'll have to either stop it manually or play another SFX. $FEnn: Delay ticks diff --git a/src-68k/echo.68k b/src-68k/echo.68k index f10695a..e6682bd 100644 --- a/src-68k/echo.68k +++ b/src-68k/echo.68k @@ -40,12 +40,16 @@ Echo_Z80Reset macro ;**************************************************************************** Echo_SendCommand: - move.w d1, -(sp) ; Save register - + movem.l d1/a1, -(sp) ; Save registers Echo_Z80Request ; We need the Z80 bus + lea ($A01FFF), a1 ; First try the 1st slot + tst.b (a1) ; Is 1st slot available? + beq.s @Ready ; If so, move on + subq.l #4, a1 ; Try 2nd slot otherwise + @Try: - tst.b ($A01FFF) ; Check if Echo is ready + tst.b (a1) ; Check if 2nd slot is ready beq.s @Ready ; Too busy? Echo_Z80Release ; Let Echo continue move.w #$FF, d1 ; Give it some time @@ -54,10 +58,10 @@ Echo_SendCommand: bra.s @Try ; Try again @Ready: - move.b d0, ($A01FFF) ; Write command ID + move.b d0, (a1) ; Write command ID Echo_Z80Release ; We're done with the Z80 bus - move.w (sp)+, d1 ; Restore register + movem.l (sp)+, d1/a1 ; Restore registers rts ; End of subroutine ;**************************************************************************** @@ -70,12 +74,16 @@ Echo_SendCommand: Echo_SendCommandAddr: Echo_SendCommandEx: - movem.l d0-d1, -(sp) ; Save register - + movem.l d0-d1/a1, -(sp) ; Save registers Echo_Z80Request ; We need the Z80 bus + lea ($A01FFF), a1 ; First try the 1st slot + tst.b (a1) ; Is 1st slot available? + beq.s @Ready ; If so, move on + subq.l #4, a1 ; Try 2nd slot otherwise + @Try: - tst.b ($A01FFF) ; Check if Echo is ready + tst.b (a1) ; Check if 2nd slot is ready beq.s @Ready ; Too busy? Echo_Z80Release ; Let Echo continue move.w #$FF, d1 ; Give it some time @@ -84,14 +92,14 @@ Echo_SendCommandEx: bra.s @Try ; Try again @Ready: - move.b d0, ($A01FFF) ; Write command ID + move.b d0, (a1) ; Write command ID move.l a0, d0 ; Easier to manipulate here - move.b d0, ($A01FFD) ; Store low address byte + move.b d0, -2(a1) ; Store low address byte lsr.l #7, d0 ; Get high address byte lsr.b #1, d0 ; We skip one bit bset.l #7, d0 ; Point into bank window - move.b d0, ($A01FFE) ; Store high address byte + move.b d0, -1(a1) ; Store high address byte lsr.w #8, d0 ; Get bank byte move.w d0, d1 ; Parse 32X bit separately @@ -99,11 +107,11 @@ Echo_SendCommandEx: and.b #$7F, d0 ; Filter out unused bit from addresses and.b #$80, d1 ; Filter out all but 32X bit or.b d1, d0 ; Put everything together - move.b d0, ($A01FFC) ; Store bank byte + move.b d0, -3(a1) ; Store bank byte Echo_Z80Release ; We're done with the Z80 bus - movem.l (sp)+, d0-d1 ; Restore register + movem.l (sp)+, d0-d1/a1 ; Restore registers rts ; End of subroutine ;**************************************************************************** @@ -115,11 +123,16 @@ Echo_SendCommandEx: ;**************************************************************************** Echo_SendCommandByte: + movem.l d1/a1, -(sp) ; Save registers Echo_Z80Request ; We need the Z80 bus - move.w d1, -(sp) ; Save register + lea ($A01FFF), a1 ; First try the 1st slot + tst.b (a1) ; Is 1st slot available? + beq.s @Ready ; If so, move on + subq.l #4, a1 ; Try 2nd slot otherwise + @Try: - tst.b ($A01FFF) ; Check if Echo is ready + tst.b (a1) ; Check if 2nd slot is ready beq.s @Ready ; Too busy? Echo_Z80Release ; Let Echo continue move.w #$FF, d1 ; Give it some time @@ -128,11 +141,11 @@ Echo_SendCommandByte: bra.s @Try ; Try again @Ready: - move.w (sp)+, d1 ; Restore register - move.b d0, ($A01FFF) ; Write command ID - move.b d1, ($A01FFC) ; Write parameter + move.b d0, (a1) ; Write command ID + move.b d1, -3(a1) ; Write parameter Echo_Z80Release ; We're done with the Z80 bus + movem.l (sp)+, d1/a1 ; Restore registers rts ; End of subroutine ;**************************************************************************** @@ -147,6 +160,11 @@ Echo_PlaySFX: move.b #$02, d0 ; Command $02 = play SFX bsr Echo_SendCommandAddr ; Send command to Echo move.w (sp)+, d0 ; Restore register + + Echo_Z80Request ; We need Z80 RAM access... + ori.b #$01, ($A01FF0) ; Force SFX flag to be on + Echo_Z80Release ; OK done with it for real + rts ; End of subroutine ;**************************************************************************** @@ -159,6 +177,11 @@ Echo_StopSFX: move.b #$03, d0 ; Command $03 = stop SFX bsr Echo_SendCommand ; Send command to Echo move.w (sp)+, d0 ; Restore register + + Echo_Z80Request ; We need Z80 RAM access... + andi.b #$FE, ($A01FF0) ; Force SFX flag to be off + Echo_Z80Release ; OK done with it for real + rts ; End of subroutine ;**************************************************************************** @@ -173,6 +196,11 @@ Echo_PlayBGM: move.b #$04, d0 ; Command $04 = play BGM bsr Echo_SendCommandAddr ; Send command to Echo move.w (sp)+, d0 ; Restore register + + Echo_Z80Request ; We need Z80 RAM access... + ori.b #$02, ($A01FF0) ; Force BGM flag to be on + Echo_Z80Release ; OK done with it for real + rts ; End of subroutine ;**************************************************************************** @@ -185,6 +213,23 @@ Echo_StopBGM: move.b #$05, d0 ; Command $05 = stop BGM bsr Echo_SendCommand ; Send command to Echo move.w (sp)+, d0 ; Restore register + + Echo_Z80Request ; We need Z80 RAM access... + andi.b #$FD, ($A01FF0) ; Force BGM flag to be off + Echo_Z80Release ; OK done with it for real + + rts ; End of subroutine + +;**************************************************************************** +; Echo_PauseBGM +; Pauses BGM playback +;**************************************************************************** + +Echo_PauseBGM: + move.w d0, -(sp) ; Save register + move.b #$08, d0 ; Command $08 = pause BGM + bsr Echo_SendCommand ; Send command to Echo + move.w (sp)+, d0 ; Restore register rts ; End of subroutine ;**************************************************************************** @@ -192,12 +237,12 @@ Echo_StopBGM: ; Resumes BGM playback ;**************************************************************************** -;Echo_ResumeBGM: -; move.w d0, -(sp) ; Save register -; move.b #$06, d0 ; Command $06 = resume BGM -; bsr Echo_SendCommand ; Send command to Echo -; move.w (sp)+, d0 ; Restore register -; rts ; End of subroutine +Echo_ResumeBGM: + move.w d0, -(sp) ; Save register + move.b #$06, d0 ; Command $06 = resume BGM + bsr Echo_SendCommand ; Send command to Echo + move.w (sp)+, d0 ; Restore register + rts ; End of subroutine ;**************************************************************************** ; Echo_PlayDirect @@ -311,10 +356,11 @@ Echo_SetVolume: ; Echo_SetVolumeEx ; Changes the global volume for each individual channel. ; -; input a0.l ... Pointer to 13 bytes +; input a0.l ... Pointer to 16 bytes ; 8 bytes with FM volumes (0..127) ; 4 bytes with PSG volumes (0..15) ; 1 byte with PCM toggle (0/1) +; 3 reserved (unused for now) ;**************************************************************************** Echo_SetVolumeEx: @@ -335,6 +381,9 @@ Echo_SetVolumeEx: move.b (a0)+, (a1)+ ; PSG channel 2 move.b (a0)+, (a1)+ ; PSG channel 3 move.b (a0)+, (a1)+ ; PCM channel toggle + move.b (a0)+, (a1)+ ; (reserved) + move.b (a0)+, (a1)+ ; (reserved) + move.b (a0)+, (a1)+ ; (reserved) move.b #1, ($A01FF1) ; Tell Echo to update the volume levels @@ -358,9 +407,9 @@ Echo_GetStatus: Echo_Z80Request ; We need the Z80 bus move.b ($A01FF0), d0 ; Get the status flags - tst.b ($A01FFF) ; Check if command still has to be parsed - beq.s @NotBusy ; Any commands left to be parsed? - bset.l #15, d0 ; If so, set the relevant flag + tst.b ($A01FFB) ; Check if any commands can be sent + beq.s @NotBusy ; Any room left for new commands? + bset.l #15, d0 ; If not, set the relevant flag @NotBusy: cmpi.b #$FF, ($A01F00) ; Check if the direct buffer is empty @@ -371,6 +420,63 @@ Echo_GetStatus: Echo_Z80Release ; Let the Z80 go! rts ; End of subroutine +;**************************************************************************** +; Echo_GetFlags +; Gets the current values of the flags. +; +; output d0.b ... Bitmask with flags +;**************************************************************************** + +Echo_GetFlags: + Echo_Z80Request ; Request Z80 bus + move.b ($A01FF2), d0 ; Get the flags + Echo_Z80Release ; Done with Z80 RAM + rts ; End of subroutine + +;**************************************************************************** +; Echo_SetFlags +; Sets flags from the 68000. +; +; input d0.b ... Bitmask of flags to be set (1 = set, 0 = intact) +;**************************************************************************** + +Echo_SetFlags: + subq.w #4, sp ; Buffer for the events + move.b #$FA, (sp) ; Set flags + move.b d0, 1(sp) ; + move.b #$FF, 2(sp) ; End of stream + + move.l a0, -(sp) ; Issue the events + lea 4(sp), a0 + bsr Echo_PlayDirect + move.l (sp)+, a0 + + addq.w #4, sp ; Done with the buffer + rts ; End of subroutine + +;**************************************************************************** +; Echo_ClearFlags +; Clear flags from the 68000. +; +; input d0.b ... Bitmask of flags to be cleared (1 = clear, 0 = intact) +;**************************************************************************** + +Echo_ClearFlags: + not.b d0 ; Bitmask is inverted + subq.w #4, sp ; Buffer for the events + move.b #$FB, (sp) ; Set flags + move.b d0, 1(sp) ; + move.b #$FF, 2(sp) ; End of stream + not.b d0 ; Restore register + + move.l a0, -(sp) ; Issue the events + lea 4(sp), a0 + bsr Echo_PlayDirect + move.l (sp)+, a0 + + addq.w #4, sp ; Done with the buffer + rts ; End of subroutine + ;**************************************************************************** ; Echo_ListEntry ; Defines an entry in a pointer list @@ -443,6 +549,9 @@ Echo_Init: move.b d0, (a0)+ move.b d0, (a0)+ move.b #1, (a0)+ + move.b d0, (a0)+ + move.b d0, (a0)+ + move.b d0, (a0)+ move.b d0, ($A01FF1) move.b #$FF, ($A01F00) ; No direct events to execute diff --git a/src-z80/build.z80 b/src-z80/build.z80 index 1aaa709..2f7fd5f 100644 --- a/src-z80/build.z80 +++ b/src-z80/build.z80 @@ -1,11 +1,15 @@ - include "src-z80/core/main.z80" + jp EntryPoint ; Jump to the entry point + db 0,0,0,0,0 ; Padding to 0008h + + include "src-z80/core/macro.z80" include "src-z80/player/pcm.z80" + include "src-z80/core/main.z80" include "src-z80/core/bgm.z80" include "src-z80/core/sfx.z80" include "src-z80/core/direct.z80" include "src-z80/player/fm.z80" include "src-z80/player/psg.z80" include "src-z80/player/misc.z80" - + include "src-z80/player/freq.z80" include "src-z80/core/vars.z80" diff --git a/src-z80/core/bgm.z80 b/src-z80/core/bgm.z80 index 338a7a6..b48d87a 100644 --- a/src-z80/core/bgm.z80 +++ b/src-z80/core/bgm.z80 @@ -25,13 +25,14 @@ PlayBGM: PollPCM - xor a ; Command parsed - ld (RAM_Command), a + xor a ; Playing a BGM immediately unpauses playback + ld (RAM_Paused), a + inc a ld hl, RAM_BGMData ; Set BGM as playing - ld (hl), $01 + ld (hl), a inc l ; No delays! - ld (hl), $01 + ld (hl), a inc l ; Store BGM start bank ld (hl), c inc l ; Store BGM start address (low) @@ -44,55 +45,111 @@ PlayBGM: ld hl, ProcessBGM ; Tell Echo to process BGM ld (DoTick_BGM+1), hl - jp IdleLoop ; End of subroutine + jp EndOfCommand ; End of subroutine ;**************************************************************************** -; ResumeBGM [command $06] -; Resumes a stopped BGM +; PauseBGM [command $08] +; Pauses a playing BGM ;---------------------------------------------------------------------------- ; breaks: all ;**************************************************************************** -ResumeBGM: - xor a ; Command parsed - ld (RAM_Command), a +PauseBGM: + ld a, (RAM_BGMPlaying) ; Is BGM even playing? + or a + jp z, EndOfCommand + + ld a, 1 ; Halt BGM playback + ld (RAM_Paused), a ;---------------------------------------------------------------------------- - - ld b, 8 ; Restore all FM channels - ld de, RAM_Locked+7 -.restorefm: + ld b, $7F ; Mute all FM channels + ld c, 7 + ld hl, RAM_Locked+7 +.mutefm: PollPCM - - ld a, (de) ; Check if this channel is locked + ld a, (hl) or a - jp nz, .fmlocked - + jr nz, .nofmmute + ld a, c + call SetFMVolTempLoad +.nofmmute: PollPCM + dec l + dec c + jp p, .mutefm - dec b ; Restore FM channel - call RestoreFM - inc b - -.fmlocked: - dec e ; Go for next channel to restore - dec b - jp nz, .restorefm + ld b, 4 ; Mute all PSG channels + ld c, $0F + ld de, RAM_Locked+8 + ld hl, RAM_PSGData +.mutepsg: + PollPCM + ld a, (de) + or a + jr nz, .nopsgmute + ld a, (hl) + and $80 + or c, + ld (hl), a +.nopsgmute: + PollPCM + ld a, l + add 16 + ld l, a + inc e + djnz .mutepsg ;---------------------------------------------------------------------------- - ld a, (RAM_Status) ; Show BGM playback in Echo's status - or $02 - ld (RAM_Status), a + ld a, (RAM_Locked+6) ; Mute PCM channel + or a + call z, StopPCM - ld hl, RAM_BGMData ; Set BGM as playing - ld (hl), $01 +;---------------------------------------------------------------------------- + + jp EndOfCommand ; End of subroutine + +;**************************************************************************** +; ResumeBGM [command $06] +; Resumes a stopped BGM +;---------------------------------------------------------------------------- +; breaks: all +;**************************************************************************** + +ResumeBGM: + ld a, (RAM_BGMPlaying) ; Was BGM even playing? + or a + jp z, EndOfCommand - ld hl, ProcessBGM ; Tell Echo to process BGM - ld (DoTick_BGM+1), hl + xor a + ld (RAM_Paused), a ; Resume BGM playback - jp IdleLoop ; End of subroutine + ld b, 4 ; Restore PSG channels + ld de, RAM_Locked+11 + ld hl, RAM_PSGData+63 +.resumepsg: + PollPCM + ld c, (hl) + ld a, l + sub 15 + ld l, a + ld a, (de) + or a + jr nz, .nopsgresume + ld a, (hl) + and $80 + or c + ld (hl), a +.nopsgresume: + PollPCM + dec l + dec e + djnz .resumepsg + + call RefreshVolume ; Restore remaining channels + jp EndOfCommand ; End of subroutine ;**************************************************************************** ; ProcessBGM @@ -197,6 +254,9 @@ ProcessBGMEventFF: jp c, SetFMParamBGM cp $FA ; Events $F8-$F9: set FM register jp c, SetFMRegBGM + jp z, SetFlagsBGM ; Events $FA-$FB: set/clear flags + cp $FB + jp z, ClearFlagsBGM PollPCM ; FFFFFFFFF bad event >:( ProcessBGMEnd: @@ -234,10 +294,8 @@ StopBGMEvent: jp DoTick_BGMSkip ; End of subroutine StopBGMCmd: - xor a ; Command parsed - ld (RAM_Command), a call StopBGM ; We're just a wrapper - jp IdleLoop ; End of subroutine + jp EndOfCommand ; End of subroutine StopBGM: ld a, (RAM_Status) ; Hide BGM playback in Echo's status @@ -271,7 +329,7 @@ ClearBGM: ld b, 4 ; Reset all PSG channels ld de, RAM_PSGData+48+15 ld hl, RAM_Locked+11 -.mutepsg: +.killpsg: PollPCM ld (hl), $00 ; Reset BGM volume @@ -282,22 +340,22 @@ ClearBGM: ld a, (hl) ; Mute PSG channel if it isn't locked or a - jr nz, .nopsgmute + jr nz, .nopsgkill xor a ld (de), a -.nopsgmute: +.nopsgkill: PollPCM dec e dec l - djnz .mutepsg + djnz .killpsg ;---------------------------------------------------------------------------- ld b, 8 ; Reset all FM channels ld de, RAM_BGMFMVol+7 -.resetfm: +.killfm: PollPCM ld a, $7F ; Reset BGM volume @@ -328,10 +386,10 @@ ClearBGM: inc b .nofmkill: dec l - djnz .resetfm + djnz .killfm ;---------------------------------------------------------------------------- - + ld hl, RAM_BGMFMPan ; Reset panning status (for restoring) ld a, $C0 ld b, 8 @@ -339,6 +397,9 @@ ClearBGM: ld (hl), a inc l djnz .initpanstat + + xor a ; Reset flags + ld (RAM_Flags), a ret ; End of subroutine @@ -349,19 +410,11 @@ ClearBGM: LoopBGM: PollPCM - - ex de, hl ; Get looping address - inc l - ld c, (hl) - inc l - ld e, (hl) - inc l - ld d, (hl) - dec l - dec l - dec l - ex de, hl - + + ld hl, (RAM_BGMLoopPoint+1) ; Get looping address + ld a, (RAM_BGMLoopPoint) + ld c, a + jp ProcessBGMRun ; End of subroutine ;**************************************************************************** @@ -371,17 +424,9 @@ LoopBGM: SetLoopBGM: PollPCM - - ex de, hl - inc l ; Store loop point address - ld (hl), c - inc l - ld (hl), e - inc l - ld (hl), d - dec l - dec l - dec l - ex de, hl - + + ld a, c ; Store loop point address + ld (RAM_BGMLoopPoint), a + ld (RAM_BGMLoopPoint+1), hl + jp ProcessBGMRun ; End of subroutine diff --git a/src-z80/core/macro.z80 b/src-z80/core/macro.z80 new file mode 100644 index 0000000..eedd527 --- /dev/null +++ b/src-z80/core/macro.z80 @@ -0,0 +1,41 @@ +;**************************************************************************** +; PollPCM +; Used to update PCM while not idle +;---------------------------------------------------------------------------- +; breaks: af +;**************************************************************************** + +PollPCM: macro + ld a, ($4000) + rrca + rst $08 + endm + +;**************************************************************************** +; BankSwitch +; Switches into a new bank (won't update player status!) +;---------------------------------------------------------------------------- +; input A .... New bank to switch into +; input HL ... Must be $60xx +;---------------------------------------------------------------------------- +; breaks ..... AF +;**************************************************************************** + +BankSwitch: macro + ld (hl), a + rrca + ld (hl), a + rrca + ld (hl), a + rrca + ld (hl), a + rrca + ld (hl), a + rrca + ld (hl), a + rrca + ld (hl), a + ld (hl), h + rrca + ld (hl), a + endm diff --git a/src-z80/core/main.z80 b/src-z80/core/main.z80 index 4eb6e5a..387b879 100644 --- a/src-z80/core/main.z80 +++ b/src-z80/core/main.z80 @@ -4,10 +4,11 @@ ;**************************************************************************** EntryPoint: - ld sp, RAM_Stack ; Init stack + xor a ; Reset Echo status (we don't clear + ld (RAM_Status), a ; RAM_Command since Echo_Init fills in values + ld (RAM_Command2), a ; before Echo gets to run!) - xor a ; Reset Echo status - ld (RAM_Status), a + ld sp, RAM_Stack ; Init stack ld hl, $7F11 ; Mute PSG ld (hl), $9F @@ -87,23 +88,12 @@ EntryPoint: jp IdleLoop ; Go into idle loop -;**************************************************************************** -; PollPCM -; Used to update PCM while not idle -;---------------------------------------------------------------------------- -; breaks: af -;**************************************************************************** - -PollPCM: macro - ld a, ($4000) - rrca - call c, UpdatePCM - endm - ;**************************************************************************** ; RunCommand ; Checks which command to run ;---------------------------------------------------------------------------- +; notes: doesn't return +;---------------------------------------------------------------------------- ; To-do: replace with pointer list? ;**************************************************************************** @@ -122,17 +112,36 @@ RunCommand: jp z, ResumeBGM dec a ; Command $07: set PCM rate jp z, SetPCMRate + dec a ; Command $08: pause BGM + jp z, PauseBGM PollPCM - xor a ; Bad command, ignore >:( - ld (RAM_Command), a + ; Bad command, ignore >:( + +;**************************************************************************** +; EndOfCommand +; Cleans up when a command finishes +;---------------------------------------------------------------------------- +; notes: doesn't return +;**************************************************************************** +EndOfCommand: + ld hl, ($1FF8) ; Copy second slot into first + ld ($1FFC), hl + ld hl, ($1FFA) + ld ($1FFE), hl + + xor a ; Free up second slot + ld (RAM_Command2), a + PollPCM ;**************************************************************************** ; IdleLoop ; Loop that runs when not processing SFX or BGM +;---------------------------------------------------------------------------- +; notes: doesn't return (d'oh) ;**************************************************************************** IdleLoop: @@ -153,13 +162,11 @@ IdleLoop: ;**************************************************************************** ; DoTick ; Called whenever a new tick triggers +;---------------------------------------------------------------------------- +; notes: doesn't return ;**************************************************************************** DoTick: -; ld a, (ix+0) -; bit 0, a -; call nz, UpdatePCM - PollPCM ld (ix+0), $27 ; Retrigger the timer @@ -181,6 +188,9 @@ DoTick_SFXSkip: PollPCM + ld a, (RAM_Paused) ; BGMs are paused? + or a + jr nz, DoTick_BGMSkip DoTick_BGM: ; Process BGMs jp DoTick_BGMSkip DoTick_BGMSkip: @@ -194,58 +204,31 @@ DoTick_PSGSkip: jp IdleLoop ; End of subroutine -;**************************************************************************** -; BankSwitch -; Switches into a new bank (won't update player status!) -; -; input A .... New bank to switch into -; input HL ... Must be $6000 -; breaks ..... AF -;**************************************************************************** - -BankSwitch: macro - ld (hl), a - rrca - ld (hl), a - rrca - ld (hl), a - rrca - ld (hl), a - rrca - ld (hl), a - rrca - ld (hl), a - rrca - ld (hl), a - ld (hl), h - rrca - ld (hl), a - endm - ;**************************************************************************** ; LoadList [command $01] ; Loads the pointer list ;**************************************************************************** LoadList: - ld hl, RAM_ComBank ; Get command parameters - ld c, (hl) - inc l - ld e, (hl) - inc l - ld d, (hl) - ex de, hl - - xor a ; Command parsed - ld (RAM_Command), a +; ld hl, RAM_ComBank ; Get command parameters +; ld c, (hl) +; inc l +; ld e, (hl) +; inc l +; ld d, (hl) +; ex de, hl + + ld hl, (RAM_ComAddr) ; Get command parameters + ld a, (RAM_ComBank) + ld c, a ld de, RAM_PointerList ; Where the pointer list starts -.loop: +.loadloop: call GetParam ; Get high byte address ld a, b ; Is it the end of the list? or a - jp z, .end + jp z, .loadend ld (de), a ; Store high byte address inc d @@ -261,10 +244,10 @@ LoadList: dec d ; Go for next byte dec d inc e - jp .loop + jp .loadloop -.end: - jp IdleLoop ; End of subroutine +.loadend: + jp EndOfCommand ; End of subroutine ;**************************************************************************** ; GetParam diff --git a/src-z80/core/sfx.z80 b/src-z80/core/sfx.z80 index 4bca4c7..8c5e7dd 100644 --- a/src-z80/core/sfx.z80 +++ b/src-z80/core/sfx.z80 @@ -25,9 +25,6 @@ PlaySFX: PollPCM - xor a ; Command parsed - ld (RAM_Command), a - ld hl, RAM_SFXData ; Set SFX as playing ld (hl), $01 inc l ; No delays! @@ -45,7 +42,7 @@ PlaySFX: ld (DoTick_SFX+1), hl PollPCM - jp IdleLoop ; End of subroutine + jp EndOfCommand ; End of subroutine ;**************************************************************************** ; ProcessSFX @@ -153,6 +150,14 @@ ProcessSFXRun: jp c, SetFMParamSFX cp $FA ; Events $F8-$F9: set FM register jp c, SetFMRegSFX + jp z, SetFlagsSFX ; Events $FA-$FB: set/clear flags + cp $FB + jp z, ClearFlagsSFX + + cp $FC + jp z, LoopSFX ; Event $FC: loop SFX + cp $FD + jp z, SetLoopSFX ; Event $FD: set loop point ;**************************************************************************** ; StopSFX* [command $03, event $FF] @@ -166,10 +171,8 @@ StopSFXEvent: jp DoTick_SFXSkip ; End of subroutine StopSFXCmd: - xor a ; Command parsed - ld (RAM_Command), a call StopSFX ; We're just a wrapper - jp IdleLoop ; End of subroutine + jp EndOfCommand ; End of subroutine StopSFX: PollPCM @@ -283,9 +286,36 @@ ClearSFX: .fmfree: dec e ; Go for next FM channel to unlock - dec b - jp nz, .unlockfm + djnz .unlockfm ;---------------------------------------------------------------------------- ret ; End of subroutine + +;**************************************************************************** +; LoopSFX [event $FC] +; Makes a SFX loop +;**************************************************************************** + +LoopSFX: + PollPCM + + ld hl, (RAM_SFXLoopPoint+1) ; Get looping address + ld a, (RAM_SFXLoopPoint) + ld c, a + + jp ProcessSFXRun ; End of subroutine + +;**************************************************************************** +; SetLoopSFX [event $FD] +; Sets the SFX loop point +;**************************************************************************** + +SetLoopSFX: + PollPCM + + ld a, c ; Store loop point address + ld (RAM_SFXLoopPoint), a + ld (RAM_SFXLoopPoint+1), hl + + jp ProcessSFXRun ; End of subroutine diff --git a/src-z80/core/vars.z80 b/src-z80/core/vars.z80 index cd7162d..79e4a1d 100644 --- a/src-z80/core/vars.z80 +++ b/src-z80/core/vars.z80 @@ -42,13 +42,23 @@ RAM_SFXPlaying: ds 1 ; Set if a SFX is playing RAM_SFXDelay: ds 1 ; How many ticks to wait RAM_SFXBank: ds 1 ; Current SFX bank RAM_SFXAddress: ds 2 ; Current SFX address +RAM_SFXLoopPoint: ds 3 ; SFX loop point + +RAM_Paused: ds 1 ; Set if BGM stream is paused + +RAM_PCMBank1: db 1 ; (not implemented yet) +RAM_PCMAddr1: dw 1 ; (not implemented yet) +RAM_PCMBank2: db 1 ; (not implemented yet) +RAM_PCMAddr2: dw 1 ; (not implemented yet) RAM_Scratch: ds 32 ; Scratch bytes, may be useful when ; buffering to speed up to avoid bank ; switching conflicts ds $F0-($&$FF), $FF -RAM_PCMBuffer: ds 16 ; PCM buffer +RAM_PCMBuffer: ds 0 ; PCM buffer +RAM_PCMBuffer1: ds 8 ; (not implemented yet) +RAM_PCMBuffer2: ds 8 ; (not implemented yet) ;**************************************************************************** ; Pointer list starts being stored from here @@ -71,6 +81,12 @@ RAM_Stack: equ $1FE0 ; Where stack starts RAM_GlobalVol: equ $1FE0 ; Global volume for all channels RAM_Status: equ $1FF0 ; Current playback status RAM_RefreshVol: equ $1FF1 ; Set to refresh all volumes +RAM_Flags: equ $1FF2 ; Track flags + RAM_Command: equ $1FFF ; Command type RAM_ComAddr: equ $1FFD ; Command address parameter RAM_ComBank: equ $1FFC ; Command bank parameter + +RAM_Command2: equ $1FFB ; (second slot for all the above) +RAM_ComAddr2: equ $1FF9 +RAM_ComBank2: equ $1FF8 diff --git a/src-z80/player/fm.z80 b/src-z80/player/fm.z80 index 505e849..d5d49ba 100644 --- a/src-z80/player/fm.z80 +++ b/src-z80/player/fm.z80 @@ -432,7 +432,13 @@ LoadFMDirect: ;**************************************************************************** SetFMVolSFX: - call SetFMVolSFXEvent ; We're just a wrapper + push af + PollPCM + call GetParam ; Get new volume + PollPCM + pop af + + call SetFMVolLoad ; We're just a wrapper jp ProcessSFXRun ; End of subroutine SetFMVolBGM: @@ -487,12 +493,21 @@ SetFMVolBGM: call SetFMVolLoad ; We're just a wrapper jp ProcessBGMRun ; End of subroutine -SetFMVolSFXEvent: - push af - PollPCM - call GetParam ; Get new volume - PollPCM - pop af +;---------------------------------------------------------------------------- +; input a = channel ID +; input b = new volume level +;---------------------------------------------------------------------------- + +SetFMVolTempLoad: + push bc + push de + push hl + jp SetFMVolDoIt + +;---------------------------------------------------------------------------- +; input a = channel ID (bottom 3 bits) +; input b = new volume level +;---------------------------------------------------------------------------- SetFMVolLoad: push bc @@ -508,6 +523,7 @@ SetFMVolLoad: ld (hl), b pop af +SetFMVolDoIt: push af ld h, RAM_FMData>>8 ; Get address of FM data add RAM_FMData&$FF diff --git a/src-z80/player/misc.z80 b/src-z80/player/misc.z80 index dee980e..56e11b4 100644 --- a/src-z80/player/misc.z80 +++ b/src-z80/player/misc.z80 @@ -1,6 +1,8 @@ ;**************************************************************************** ; SetDelay* [event $FE, events $D0-$DF] ; Adds a delay in playback +;---------------------------------------------------------------------------- +; breaks: c, de, hl ;**************************************************************************** SetDelaySFX: @@ -45,6 +47,58 @@ SetDelayShort: ret ; End of subroutine +;**************************************************************************** +; SetFlags [event $FA] +; Sets some of the flags. +;---------------------------------------------------------------------------- +; breaks: c, de, hl +;**************************************************************************** + +SetFlagsSFX: + call SetFlags + jp ProcessSFXRun + +SetFlagsBGM: + call SetFlags + jp ProcessBGMRun + +SetFlags: + PollPCM ; Get which flags to set + call GetParam + PollPCM + + ld a, (RAM_Flags) ; Set the flags + or b + ld (RAM_Flags), a + + ret ; End of subroutine + +;**************************************************************************** +; ClearFlags [event $FB] +; Clears some of the flags. +;---------------------------------------------------------------------------- +; breaks: c, de, hl +;**************************************************************************** + +ClearFlagsSFX: + call ClearFlags + jp ProcessSFXRun + +ClearFlagsBGM: + call ClearFlags + jp ProcessBGMRun + +ClearFlags: + PollPCM ; Get which flags to clear + call GetParam + PollPCM + + ld a, (RAM_Flags) ; Clear the flags + and b + ld (RAM_Flags), a + + ret ; End of subroutine + ;**************************************************************************** ; RefreshVolume ; Reloads the volume for all channels. @@ -69,6 +123,7 @@ RefreshVolume: inc l inc e dec c + PollPCM jr nz, .fixfmvol ld hl, $1FE8 ; Update PSG volume diff --git a/src-z80/player/pcm (copia).z80 b/src-z80/player/pcm (copia).z80 new file mode 100644 index 0000000..ae7b34a --- /dev/null +++ b/src-z80/player/pcm (copia).z80 @@ -0,0 +1,236 @@ +;**************************************************************************** +; UpdatePCM +; Updates PCM output upon a timer event +;**************************************************************************** + +UpdatePCM: + ret ; $C9 = RET = no PCM playback + ; $D0 = RET NC = PCM playback + + exx ; Switch to PCM registers + +.doagain: + ld (ix+0), $27 ; Acknowledge timer + ld (ix+1), $1F + + ld a, (hl) ; Fetch next sample + inc a ; Check if it's the end of the waveform + jr z, .stop + ld (ix+0), $2A ; Nope, send sample to YM2612 + ld (ix+1), a + + inc l ; Update buffer position + jr z, .reload ; Need to buffer more? + +.nopcm: + exx ; Switch to normal registers + ret ; End of subroutine + +.stop: + ld a, $C9 ; Stop playback + ld (UpdatePCM), a + ld (ix+0), $2A ; Turn off DAC + ld (ix+1), $80 + ld (ix+0), $2B + ld (ix+1), $00 + exx ; Switch to normal registers + ret ; End of subroutine + +.reload: + ld a, (RAM_LastBank) ; Bank switch if needed + cp c + jp z, .noswitchu + ld a, c + ld (RAM_LastBank), a + ld hl, $6000 + BankSwitch +.noswitchu: + + ld hl, RAM_PCMBuffer ; Load samples into the buffer + ld a, c + ex de, hl + + ldi + ldi + ldi + ldi + + ldi + ldi + ldi + ldi + + ldi + ldi + ldi + ldi + + ldi + ldi + ldi + ldi + + ex de, hl + ld c, a + + ld a, e + or a + jp nz, .nobankchg ; Update high bytes of address if needed + inc d + jp nz, .nobankchg + ld d, $80 + inc c +.nobankchg: + + ld l, RAM_PCMBuffer&$FF ; Go back to the beginning of the buffer + jp .doagain ; We took so long we should play the next + ; sample already ._.' + +;**************************************************************************** +; PlayPCM* [event $0C] +; Plays a PCM sample +;---------------------------------------------------------------------------- +; input c .... current bank +; input hl ... current address +;---------------------------------------------------------------------------- +; breaks: af, b +;**************************************************************************** + +PlayPCMSFX: + call PlayPCM ; We're just a wrapper + jp ProcessSFXRun ; End of subroutine + +PlayPCMBGM: + PollPCM + + ld a, (RAM_Locked+6) ; Check if channel is free + or a + jp nz, ProcessBGMSkip1 ; Don't play sample if locked + + call PlayPCM ; We're just a wrapper + jp ProcessBGMRun ; End of subroutine + +PlayPCM: + ld a, (RAM_GlobalVol+$0C) ; Are we allowed to play PCM? + or a + ret z + + call GetParam ; Get sample ID + + ld a, b + exx ; We'll modify PCM data now + + ld h, RAM_PointerList>>8 ; Get offset in pointer list + ld l, a + + ld d, (hl) ; Get PCM address + inc h + ld e, (hl) + inc h + ld c, (hl) + + ld hl, $6000 ; Initial bank switch + ld a, c + ld (RAM_LastBank), a + BankSwitch + + ld h, RAM_PCMBuffer>>8 ; Set buffer where the sample starts + ld a, e + or $F0 + ld l, a + + ld b, l +.load1st: ; Copy initial samples into the buffer + ld a, (de) + ld (hl), a + inc e + inc l + jp nz, .load1st + ld l, b + + ld a, e ; Check if the sample should skip ahead + or a ; already + jp nz, .noskip1st + inc d + jp nz, .noskip1st + ld d, $80 + inc c +.noskip1st: + + exx ; Back to standard registers + ld a, $D0 ; Enable PCM playback + ld (UpdatePCM), a + + ld (ix+0), $2B ; Turn on DAC + ld (ix+1), $80 + ld (ix+0), $2A + ld (ix+1), $80 + + ret ; End of subroutine + +;**************************************************************************** +; StopPCM* +; Stops a PCM sample +;**************************************************************************** + +StopPCMSFX: + call StopPCM ; We're just a wrapper + jp ProcessSFXRun ; End of subroutine + +StopPCMBGM: + PollPCM + + ld a, (RAM_Locked+6) ; Check if channel is free + or a + jp nz, ProcessBGMRun ; Don't stop sample if locked + + call StopPCM ; We're just a wrapper + jp ProcessBGMRun ; End of subroutine + +StopPCM: + ld a, $C9 ; Stop PCM playback + ld (UpdatePCM), a + + ld (ix+0), $2B ; Disable DAC + ld (ix+1), $00 + + ret ; End of subroutine + +;**************************************************************************** +; LockChannelPCM [event $EC] +; Locks the PCM channel +;**************************************************************************** + +LockChannelPCM: + ld a, $01 ; Lock PCM channel + ld (RAM_Locked+6), a + + call StopPCM ; Stop PCM playback + jp ProcessSFXRun ; End of subroutine + +;**************************************************************************** +; SetPCMRate [command $07] +; Changes the sample rate of PCM +;**************************************************************************** + +SetPCMRate: + ld a, (RAM_ComBank) ; Get new rate + cpl + ld b, a + + xor a ; Parsed command already + ld (RAM_Command), a + + ld a, b ; Set high bits of timer + ld (ix+0), $24 + rrca + rrca + or $C0 + ld (ix+1), a + + ld a, b ; Set low bits of timer + ld (ix+0), $25 + and $03 + ld (ix+1), a + + jp IdleLoop ; End of subroutine diff --git a/src-z80/player/pcm.z80 b/src-z80/player/pcm.z80 index 99feb6d..2b7bcc4 100644 --- a/src-z80/player/pcm.z80 +++ b/src-z80/player/pcm.z80 @@ -1,100 +1,21 @@ -;**************************************************************************** -; PlayPCM* [event $0C] -; Plays a PCM sample -;---------------------------------------------------------------------------- -; input c .... current bank -; input hl ... current address -;---------------------------------------------------------------------------- -; breaks: af, b -;**************************************************************************** - -PlayPCMSFX: - call PlayPCM ; We're just a wrapper - jp ProcessSFXRun ; End of subroutine - -PlayPCMBGM: - PollPCM - - ld a, (RAM_Locked+6) ; Check if channel is free - or a - jp nz, ProcessBGMSkip1 ; Don't play sample if locked - - call PlayPCM ; We're just a wrapper - jp ProcessBGMRun ; End of subroutine - -PlayPCM: - ld a, (RAM_GlobalVol+$0C) ; Are we allowed to play PCM? - or a - ret z - - call GetParam ; Get sample ID - - ld a, b - exx ; We'll modify PCM data now - - ld h, RAM_PointerList>>8 ; Get offset in pointer list - ld l, a - - ld d, (hl) ; Get PCM address - inc h - ld e, (hl) - inc h - ld c, (hl) - - ld hl, $6000 ; Initial bank switch - ld a, c - ld (RAM_LastBank), a - BankSwitch - - ld h, RAM_PCMBuffer>>8 ; Set buffer where the sample starts - ld a, e - or $F0 - ld l, a - - ld b, l -.load1st: ; Copy initial samples into the buffer - ld a, (de) - ld (hl), a - inc e - inc l - jp nz, .load1st - ld l, b - - ld a, e ; Check if the sample should skip ahead - or a ; already - jp nz, .noskip1st - inc d - jp nz, .noskip1st - ld d, $80 - inc c -.noskip1st: - - ;ld b, $01 ; Play PCM! - exx ; Back to standard registers - xor a ; Enable PCM playback - ld (UpdatePCM), a - - ld (ix+0), $2B ; Turn on DAC - ld (ix+1), $80 - ld (ix+0), $2A - ld (ix+1), $80 - - ret ; End of subroutine - ;**************************************************************************** ; UpdatePCM ; Updates PCM output upon a timer event ;**************************************************************************** UpdatePCM: - ret ; RET = no PCM playback - ; NOP = PCM playback + ret ; $C9 = RET = no PCM playback + ; $D0 = RET NC = PCM playback exx ; Switch to PCM registers .doagain: ld (ix+0), $27 ; Acknowledge timer ld (ix+1), $1F + ;push hl + ;ld hl, $1F27 + ;ld ($4000), hl + ;pop hl ld a, (hl) ; Fetch next sample inc a ; Check if it's the end of the waveform @@ -110,7 +31,9 @@ UpdatePCM: ret ; End of subroutine .stop: - ld b, $00 ; Stop playback +; ld b, $00 ; Stop playback + ld a, $C9 ; Stop playback + ld (UpdatePCM), a ld (ix+0), $2A ; Turn off DAC ld (ix+1), $80 ld (ix+0), $2B @@ -209,6 +132,88 @@ UpdatePCM: jp .doagain ; We took so long we should play the next ; sample already ._.' +;**************************************************************************** +; PlayPCM* [event $0C] +; Plays a PCM sample +;---------------------------------------------------------------------------- +; input c .... current bank +; input hl ... current address +;---------------------------------------------------------------------------- +; breaks: af, b +;**************************************************************************** + +PlayPCMSFX: + call PlayPCM ; We're just a wrapper + jp ProcessSFXRun ; End of subroutine + +PlayPCMBGM: + PollPCM + + ld a, (RAM_Locked+6) ; Check if channel is free + or a + jp nz, ProcessBGMSkip1 ; Don't play sample if locked + + call PlayPCM ; We're just a wrapper + jp ProcessBGMRun ; End of subroutine + +PlayPCM: + ld a, (RAM_GlobalVol+$0C) ; Are we allowed to play PCM? + or a + ret z + + call GetParam ; Get sample ID + + ld a, b + exx ; We'll modify PCM data now + + ld h, RAM_PointerList>>8 ; Get offset in pointer list + ld l, a + + ld d, (hl) ; Get PCM address + inc h + ld e, (hl) + inc h + ld c, (hl) + + ld hl, $6000 ; Initial bank switch + ld a, c + ld (RAM_LastBank), a + BankSwitch + + ld h, RAM_PCMBuffer>>8 ; Set buffer where the sample starts + ld a, e + or $F0 + ld l, a + + ld b, l +.load1st: ; Copy initial samples into the buffer + ld a, (de) + ld (hl), a + inc e + inc l + jp nz, .load1st + ld l, b + + ld a, e ; Check if the sample should skip ahead + or a ; already + jp nz, .noskip1st + inc d + jp nz, .noskip1st + ld d, $80 + inc c +.noskip1st: + + exx ; Back to standard registers + ld a, $D0 ; Enable PCM playback + ld (UpdatePCM), a + + ld (ix+0), $2B ; Turn on DAC + ld (ix+1), $80 + ld (ix+0), $2A + ld (ix+1), $80 + + ret ; End of subroutine + ;**************************************************************************** ; StopPCM* ; Stops a PCM sample @@ -257,21 +262,21 @@ LockChannelPCM: SetPCMRate: ld a, (RAM_ComBank) ; Get new rate cpl - ld b, a - xor a ; Parsed command already - ld (RAM_Command), a - - ld a, b ; Set high bits of timer - ld (ix+0), $24 + ld b, a ; Set high bits of timer + ld hl, $4000 + ld (hl), $24 rrca rrca or $C0 - ld (ix+1), a + inc l + ld (hl), a ld a, b ; Set low bits of timer - ld (ix+0), $25 + dec l + ld (hl), $25 and $03 - ld (ix+1), a + inc l + ld (hl), a - jp IdleLoop ; End of subroutine + jp EndOfCommand ; End of subroutine diff --git a/src-z80/player/psg.z80 b/src-z80/player/psg.z80 index b88978c..6ddaae7 100644 --- a/src-z80/player/psg.z80 +++ b/src-z80/player/psg.z80 @@ -10,8 +10,10 @@ UpdatePSG: push bc ld a, (hl) ; Get channel volume - bit 7, a - jr nz, .noskip +; bit 7, a +; jr nz, .noskip + or a + jp m, .noskip ld b, $0F inc l jp .skip -- cgit v1.2.3