diff --git a/LICENSE b/LICENSE index 798102d..0ae3745 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -© 2010-2013 Javier Degirolmo +© 2010-2017 Javier Degirolmo This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/README b/README index 0916d2b..e1b42b4 100644 --- a/README +++ b/README @@ -7,12 +7,12 @@ | | |_ |_ ___ | | | | | | | | | |_______ |_ |___| _| | | | | |_ |_____| _| |___________| |________| |___| |___| |_________| - ___ ___ _ _ ___ __ ___ ___ ___ _ ___ ___ _ ___ - | _| | | | | \ | _| | _| | | _| | | |_ | - | |_| | | | | | | | | | |_| | | |_| | | | |_ _ _ ___ ___ | | _| | + ___ ___ _ _ ___ __ ___ ___ ___ _ ___ ___ _ _ _ + | _| | | | | \ | _| | _| | | _| | | | | | + | |_| | | | | | | | | | |_| | | |_| | | | |_ _ _ ___ ___ | | | | | |_ | | | | | | | | | | _| | | | | | | | _| | | | __| _ \ | | |_ | - _| | | | | | | | | | | |_| | | | | | | | |_ | | | __| /_ | |_ _| | - |___|___|___|_|_|__/ |___|_|_|___|_|_|_|___| \_/|___|_|_\_| |_|_|___| + _| | | | | | | | | | | |_| | | | | | | | |_ | | | __| /_ | |_ | | + |___|___|___|_|_|__/ |___|_|_|___|_|_|_|___| \_/|___|_|_\_| |_|_| |_| ============================================================================= @@ -93,6 +93,7 @@ THANKS FOR TESTING: * John Springer (you heart his pizza) * Flygon (sorry for your headphones :P) * djcouchycouch (for using an API I didn't even check if it worked) + * BigEvilCorporation (helped with testing Echo 1.4) OTHER THANKS: diff --git a/built/old-builds/prog-z80-1.3.bin b/built/old-builds/prog-z80-1.3.bin new file mode 100644 index 0000000..307ea44 Binary files /dev/null and b/built/old-builds/prog-z80-1.3.bin differ diff --git a/built/prog-z80.bin b/built/prog-z80.bin index 307ea44..bbb92e2 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 b4368da..e488e33 100644 --- a/c/echo.c +++ b/c/echo.c @@ -15,9 +15,37 @@ static volatile uint16_t* const z80_reset = (uint16_t *) 0xA11200; { *z80_busreq = 0; } #define Z80_RESET() \ { *z80_reset = 0; \ - int16_t i; for (i = 8; i >= 0; i--); \ + volatile int16_t i; for (i = 4; i >= 0; i--); \ *z80_reset = 0x100; } +// Macro to add delays +// Using volatile is needlessly ugly but at least portable +// GCC is already awful at optimizing, so this isn't that bad... +#define DELAY() \ + { volatile int16_t i; for (i = 0xFF; i >= 0; i--); } + +// Look-up tables for echo_set_volume +static const uint8_t fm_volumes[] = { + 0x7F,0x7B,0x77,0x73,0x70,0x6C,0x68,0x65, + 0x61,0x5E,0x5A,0x57,0x54,0x50,0x4D,0x4A, + 0x47,0x44,0x41,0x3F,0x3C,0x39,0x36,0x34, + 0x31,0x2F,0x2D,0x2A,0x28,0x26,0x24,0x22, + 0x20,0x1E,0x1C,0x1A,0x18,0x16,0x15,0x13, + 0x12,0x10,0x0F,0x0D,0x0C,0x0B,0x0A,0x09, + 0x08,0x07,0x06,0x05,0x04,0x04,0x03,0x02, + 0x02,0x01,0x01,0x01,0x00,0x00,0x00,0x00 +}; +static const uint8_t psg_volumes[] = { + 0x0F,0x0F,0x0E,0x0E,0x0D,0x0D,0x0C,0x0C, + 0x0B,0x0B,0x0B,0x0A,0x0A,0x0A,0x09,0x09, + 0x08,0x08,0x08,0x07,0x07,0x07,0x06,0x06, + 0x06,0x06,0x05,0x05,0x05,0x04,0x04,0x04, + 0x04,0x03,0x03,0x03,0x03,0x03,0x02,0x02, + 0x02,0x02,0x02,0x02,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +}; + //*************************************************************************** // echo_init // Initializes Echo and gets it running. @@ -35,6 +63,9 @@ void echo_init(const void **list) { // due to linker shenanigans) z80_ram[0x1FFF] = 0x00; + // Direct stream is empty yet + z80_ram[0x1F00] = 0xFF; + // Load the instrument list manually, since thanks to linker shenanigans // we can't implement the list properly in ROM :/ volatile uint8_t *dest = &z80_ram[0x1C00]; @@ -65,6 +96,13 @@ void echo_init(const void **list) { while (count-- >= 0) *dest++ = *src++; + // Set up global volume + int i; + for (i = 0; i < 12; i++) + z80_ram[0x1FE0+i] = 0; + z80_ram[0x1FEC] = 1; + z80_ram[0x1FF1] = 1; + // Let Echo start running! Z80_RESET(); Z80_RELEASE(); @@ -84,8 +122,7 @@ void echo_send_command(uint8_t cmd) { // Is Echo busy yet? while (z80_ram[0x1FFF] != 0x00) { Z80_RELEASE(); - int16_t i; - for (i = 0x3FF; i >= 0; i--); + DELAY(); Z80_REQUEST(); } @@ -116,8 +153,7 @@ void echo_send_command_addr(uint8_t cmd, const void *addr) { // Is Echo busy yet? while (z80_ram[0x1FFF] != 0x00) { Z80_RELEASE(); - int16_t i; - for (i = 0x3FF; i >= 0; i--); + DELAY(); Z80_REQUEST(); } @@ -187,9 +223,11 @@ void echo_stop_bgm(void) { // Resumes background music playback. //*************************************************************************** +/* void echo_resume_bgm(void) { echo_send_command(ECHO_CMD_RESUMEBGM); } +*/ //*************************************************************************** // echo_play_sfx @@ -211,6 +249,95 @@ void echo_stop_sfx(void) { echo_send_command(ECHO_CMD_STOPSFX); } +//*************************************************************************** +// echo_play_direct +// Injects events into the BGM stream for the next tick. +//--------------------------------------------------------------------------- +// param ptr: pointer to BGM stream +//*************************************************************************** + +void echo_play_direct(const void *ptr) { + // We need access to Z80 bus + Z80_REQUEST(); + + // Check where we can start writing events + volatile uint8_t *dest = &z80_ram[0x1F00]; + while (*dest != 0xFF) dest++; + + // Write the events + const uint8_t *src = (uint8_t*)(ptr); + for (;;) { + uint8_t byte = *src++; + *dest++ = byte; + if (byte == 0xFF) break; + } + + // Done with the Z80 + Z80_RELEASE(); +} + +//*************************************************************************** +// echo_set_volume +// Changes the global volume for every channel. +//--------------------------------------------------------------------------- +// param vol: new volume (0 = quietest, 255 = loudest) +//*************************************************************************** + +void echo_set_volume(uint8_t vol) { + // We need access to Z80 bus + Z80_REQUEST(); + + // Set FM volume values + uint8_t fm_vol = fm_volumes[vol >> 2]; + z80_ram[0x1FE0] = fm_vol; + z80_ram[0x1FE1] = fm_vol; + z80_ram[0x1FE2] = fm_vol; + z80_ram[0x1FE3] = fm_vol; + z80_ram[0x1FE4] = fm_vol; + z80_ram[0x1FE5] = fm_vol; + z80_ram[0x1FE6] = fm_vol; + z80_ram[0x1FE7] = fm_vol; + + // Set PSG volume values + uint8_t psg_vol = psg_volumes[vol >> 2]; + z80_ram[0x1FE8] = psg_vol; + z80_ram[0x1FE9] = psg_vol; + z80_ram[0x1FEA] = psg_vol; + z80_ram[0x1FEB] = psg_vol; + + // Determine whether to enable PCM + z80_ram[0x1FEC] = (vol >= 0x40) ? 1 : 0; + + // Tell Echo to update all the volumes + z80_ram[0x1FF1] = 1; + + // Done with the Z80 + Z80_RELEASE(); +} + +//*************************************************************************** +// echo_set_volume_ex +// Changes the global volume for each individual channel. +//--------------------------------------------------------------------------- +// param ptr: pointer to array with volume values +//*************************************************************************** + +void echo_set_volume_ex(const uint8_t *ptr) { + // We need access to Z80 bus + Z80_REQUEST(); + + // Store the new volume values + int i; + for (i = 0; i < 13; i++) + z80_ram[0x1FE0+i] = ptr[i]; + + // Tell Echo to update all the volumes + z80_ram[0x1FF1] = 1; + + // Done with the Z80 + Z80_RELEASE(); +} + //*************************************************************************** // echo_set_pcm_rate // Changes the playback rate of PCM. @@ -238,6 +365,8 @@ uint16_t echo_get_status(void) { status = z80_ram[0x1FF0]; if (z80_ram[0x1FFF] != 0) status |= ECHO_STAT_BUSY; + if (z80_ram[0x1F00] != 0xFF) + status |= ECHO_STAT_DIRBUSY; // Done with the Z80 Z80_RELEASE(); diff --git a/c/echo.h b/c/echo.h index 086535e..56088b6 100644 --- a/c/echo.h +++ b/c/echo.h @@ -19,15 +19,19 @@ enum { /* Echo status flags */ #define ECHO_STAT_BGM 0x0002 /* Background music is playing */ #define ECHO_STAT_SFX 0x0001 /* Sound effect is playing */ +#define ECHO_STAT_DIRBUSY 0x4000 /* Echo isn't done with direct events */ #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_stop_bgm(void); -void echo_resume_bgm(void); +/*void echo_resume_bgm(void);*/ void echo_play_sfx(const void *); 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); uint16_t echo_get_status(void); void echo_send_command(uint8_t); diff --git a/c/echoblob.h b/c/echoblob.h index 1782524..827cc5b 100644 --- a/c/echoblob.h +++ b/c/echoblob.h @@ -1,6 +1,6 @@ static uint8_t echo_blob[] = { - 49,240, 31,175, 50,240, 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, + 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, @@ -11,253 +11,269 @@ static uint8_t echo_blob[] = { 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, 67, 1, 61,202, 83, 5, 61,202,125, 6, 61,202, 0, - 3, 61,202,133, 4, 61,202, 81, 3, 61,202,222, 2, 58, 0, 64, - 15,220, 13, 2,175, 50,255, 31, 58, 0, 64, 15,220, 13, 2, 58, - 255, 31,183, 32,204, 58, 0, 64, 15,220, 13, 2, 58, 0, 64,203, - 79, 32, 8,203, 71,196, 13, 2,195,239, 0,221,126, 0,203, 71, - 196, 13, 2,221, 54, 0, 39,221, 54, 1, 47, 58, 0, 64, 15,220, - 13, 2,195, 37, 1, 58, 0, 64, 15,220, 13, 2,195, 47, 1, 58, - 0, 64, 15,220, 13, 2,195, 69, 12, 58, 0, 64, 15,220, 13, 2, + 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,113, 1,120,183,202,110, 1, 18, 20,205,113, 1, - 120, 18, 20,205,113, 1,120, 18, 21, 21, 28,195, 83, 1,195,239, - 0, 58,140, 18,185,202,145, 1,121, 50,140, 18,229, 33, 0, 96, + 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,157, 1, 36,194,157, 1, 38,128, 12,201,205,184, - 1,195,204, 5, 58, 0, 64, 15,220, 13, 2, 58,134, 18,183,194, - 106, 4,205,184, 1,195,174, 3,205,113, 1,120,217, 38, 28,111, - 86, 36, 94, 36, 78, 33, 0, 96,121, 50,140, 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,227, 1,104,123,183,194,247, 1, - 20,194,247, 1, 22,128, 12,217,175, 50, 13, 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,140, 18,185,202, - 89, 2,121, 50,140, 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,166, 2, 20, - 194,166, 2, 22,128, 12, 46,240,195, 15, 2,205,197, 2,195,204, - 5, 58, 0, 64, 15,220, 13, 2, 58,134, 18,183,194,174, 3,205, - 197, 2,195,174, 3, 62,201, 50, 13, 2,221, 54, 0, 43,221, 54, - 1, 0,201, 62, 1, 50,134, 18,205,197, 2,195,204, 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, 13, 2,205,179, 4, 58, 0, 64, 15,220, 13, - 2, 58,240, 31,246, 2, 50,240, 31, 58, 0, 64, 15,220, 13, 2, - 33,252, 31, 78, 44, 94, 44, 86, 58, 0, 64, 15,220, 13, 2,175, - 50,255, 31, 33,141, 18, 54, 1, 44, 54, 1, 44,113, 44,115, 44, - 114, 58, 0, 64, 15,220, 13, 2, 33,141, 3, 34, 45, 1,195,239, - 0,175, 50,255, 31, 6, 8, 17,135, 18, 58, 0, 64, 15,220, 13, - 2, 26,183,194,114, 3, 58, 0, 64, 15,220, 13, 2, 5,205, 14, - 12, 4, 29, 5,194, 90, 3, 58,240, 31,246, 2, 50,240, 31, 33, - 141, 18, 54, 1, 33,141, 3, 34, 45, 1,195,239, 0, 58, 0, 64, - 15,220, 13, 2, 33,142, 18,126, 61,202,160, 3,119,195, 47, 1, - 58, 0, 64, 15,220, 13, 2, 44, 78, 44, 94, 44, 86,235, 58, 0, - 64, 15,220, 13, 2,205,113, 1, 58, 0, 64, 15,220, 13, 2,120, - 254, 8,218, 59, 7,254, 11,218, 1, 13,202,133, 13,254, 12,202, - 164, 1, 58, 0, 64, 15,220, 13, 2,120,254, 24,218,220, 7,254, - 28,218,225, 13,202,177, 2, 58, 0, 64, 15,220, 13, 2,120,254, - 254,202,231, 15,254,255,202,127, 4,254,252,202, 41, 5,254,253, - 202, 62, 5, 58, 0, 64, 15,220, 13, 2,120,254, 40,218,195, 9, - 254, 44,218, 62, 14, 58, 0, 64, 15,220, 13, 2,120,254, 56,218, - 10, 8,254, 59,218, 82, 15,202,172, 15, 58, 0, 64, 15,220, 13, - 2,120,254, 72,218,137, 8,254, 76,218,213, 14, 58, 0, 64, 15, - 220, 13, 2,120,254,224,218,247, 15,254,248,218, 22, 11, 58, 0, - 64, 15,220, 13, 2,195,127, 4, 58, 0, 64, 15,220, 13, 2, 44, - 194,106, 4, 36,194,106, 4, 38,128, 12, 58, 0, 64, 15,220, 13, - 2, 44,194,124, 4, 36,194,124, 4, 38,128, 12,195,174, 3,205, - 143, 4,195, 47, 1,175, 50,255, 31,205,143, 4,195,239, 0, 58, - 240, 31,230,253, 50,240, 31, 58, 0, 64, 15,220, 13, 2,205,179, - 4, 58, 0, 64, 15,220, 13, 2,175, 50,141, 18, 33, 47, 1, 34, - 45, 1,201, 58,134, 18,183,204,197, 2, 6, 4, 17, 63, 18, 33, - 139, 18, 58, 0, 64, 15,220, 13, 2, 54, 0,123,214, 15, 95,126, - 183, 32, 2,175, 18, 58, 0, 64, 15,220, 13, 2, 29, 45, 16,226, - 6, 8, 17, 79, 18, 58, 0, 64, 15,220, 13, 2, 62,127, 18, 29, - 58, 0, 64, 15,220, 13, 2,126,183,194, 26, 5, 5,120,205,157, - 11, 58, 0, 64, 15,220, 13, 2,120,230, 4,253,111,120,230, 3, - 198,180,253,119, 0,253, 54, 1,192, 4, 45, 16,200, 33, 80, 18, - 62,192, 6, 8,119, 44, 16,252,201, 58, 0, 64, 15,220, 13, 2, - 235, 44, 78, 44, 94, 44, 86, 45, 45, 45,235,195,174, 3, 58, 0, - 64, 15,220, 13, 2,235, 44,113, 44,115, 44,114, 45, 45, 45,235, - 195,174, 3, 58, 0, 64, 15,220, 13, 2,205,185, 6, 58, 0, 64, - 15,220, 13, 2, 58,240, 31,246, 1, 50,240, 31, 58, 0, 64, 15, - 220, 13, 2, 33,252, 31, 78, 44, 94, 44, 86, 58, 0, 64, 15,220, - 13, 2,175, 50,255, 31, 33,149, 18, 54, 1, 44, 54, 1, 44,113, - 44,115, 44,114, 58, 0, 64, 15,220, 13, 2, 33,171, 5, 34, 35, - 1, 58, 0, 64, 15,220, 13, 2,195,239, 0, 58, 0, 64, 15,220, - 13, 2, 33,150, 18,126, 61,202,190, 5,119,195, 37, 1, 58, 0, - 64, 15,220, 13, 2, 44, 78, 44, 94, 44, 86,235, 58, 0, 64, 15, - 220, 13, 2,205,113, 1, 58, 0, 64, 15,220, 13, 2,120,254, 8, - 218, 53, 7,254, 11,218,251, 12,202,127, 13,254, 12,202,158, 1, - 58, 0, 64, 15,220, 13, 2,120,254, 24,218,214, 7,254, 28,218, - 219, 13,202,171, 2, 58, 0, 64, 15,220, 13, 2,120,254,254,202, - 225, 15,254,255,202,119, 6, 58, 0, 64, 15,220, 13, 2,120,254, - 40,218,189, 9,254, 44,218, 24, 14, 58, 0, 64, 15,220, 13, 2, - 120,254, 56,218, 4, 8,254, 59,218, 76, 15,202,166, 15, 58, 0, - 64, 15,220, 13, 2,120,254, 72,218,131, 8,254, 76,218,143, 14, - 58, 0, 64, 15,220, 13, 2,120,254,224,218,237, 15,254,232,218, - 107, 11,254,236,218,185, 15,202,211, 2, 58, 0, 64, 15,220, 13, - 2,120,254,248,218,231, 10,205,135, 6,195, 37, 1,175, 50,255, - 31,205,135, 6,195,239, 0, 58, 0, 64, 15,220, 13, 2, 58,240, - 31,230,254, 50,240, 31, 58, 0, 64, 15,220, 13, 2,175, 50,149, - 18, 33, 37, 1, 34, 35, 1, 58, 0, 64, 15,220, 13, 2,205,185, - 6, 58, 0, 64, 15,220, 13, 2,201, 58,134, 18,183,196,197, 2, - 6, 4, 17,139, 18, 58, 0, 64, 15,220, 13, 2, 26,183, 40, 64, - 175, 18, 58, 0, 64, 15,220, 13, 2,120, 15, 15, 15, 15, 61, 38, - 18,111, 78,214, 15,111,113, 58, 0, 64, 15,220, 13, 2,213,125, - 198, 8,111,198, 4, 95, 84, 58, 0, 64, 15,220, 13, 2, 26,119, - 44, 28, 26,119, 44, 28, 26,119,209, 58, 0, 64, 15,220, 13, 2, - 29, 16,178, 6, 8, 58, 0, 64, 15,220, 13, 2, 26,183,202, 47, - 7,175, 18, 58, 0, 64, 15,220, 13, 2, 5,205, 14, 12, 4, 29, - 5,194, 21, 7,201,205, 89, 7,195,204, 5, 71, 58, 0, 64, 15, - 220, 13, 2,229,120,230, 7, 33,128, 18,133,111,126,225,183,194, - 106, 4,120,205, 89, 7,195,174, 3,230, 7,221, 54, 0, 40,221, - 119, 1, 71, 8, 58, 0, 64, 15,220, 13, 2,120,230, 4, 15,253, - 111, 58, 0, 64, 15,220, 13, 2,205,113, 1, 58, 0, 64, 15,220, - 13, 2, 8,213,229, 87,230, 3,198,164, 95, 58, 0, 64, 15,220, - 13, 2, 38, 17,120,230, 31,198,144,111, 58, 0, 64, 15,220, 13, - 2,120,230,224, 15, 15, 71,126,176,253,115, 0,253,119, 1, 58, - 0, 64, 15,220, 13, 2,123,214, 4, 95, 45,126,253,115, 0,253, - 119, 1, 58, 0, 64, 15,220, 13, 2,122,246,240,221, 54, 0, 40, - 221,119, 1,225,209,201,205,250, 7,195,204, 5, 71, 58, 0, 64, - 15,220, 13, 2,120,229,230, 7, 33,128, 18,133,111,126,225,183, - 194,174, 3,120,205,250, 7,195,174, 3,230, 7,221, 54, 0, 40, - 221,119, 1,201,205, 40, 8,195,204, 5, 71, 58, 0, 64, 15,220, - 13, 2,120,229,230, 7, 33,128, 18,133,111,126,225,183,194, 88, - 4,120,205, 40, 8,195,174, 3,245, 71, 58, 0, 64, 15,220, 13, - 2,120,230, 4, 15,253,111, 58, 0, 64, 15,220, 13, 2,205,113, - 1, 58, 0, 64, 15,220, 13, 2,241,213,230, 7, 87,230, 3,198, - 164, 95, 58, 0, 64, 15,220, 13, 2,253,115, 0,253,112, 1, 58, - 0, 64, 15,220, 13, 2,205,113, 1, 58, 0, 64, 15,220, 13, 2, - 123,214, 4, 95,253,115, 0,253,112, 1, 58, 0, 64, 15,220, 13, - 2,209,201,205,235, 8,195,204, 5,230, 7, 71, 58, 0, 64, 15, - 220, 13, 2,213,197,120, 17, 64, 18,131, 95, 58, 0, 64, 15,220, - 13, 2,205,113, 1, 58, 0, 64, 15,220, 13, 2,120, 18,123,198, - 8, 95,175, 18, 89,193, 75,209, 58, 0, 64, 15,220, 13, 2,229, - 120, 38, 18,198,128,111,126,225,183,194,174, 3, 58, 0, 64, 15, - 220, 13, 2,120,229, 33, 64, 18,133,111, 70,225, 8, 58, 0, 64, - 15,220, 13, 2, 8,205, 0, 9,195,174, 3,230, 7, 8, 58, 0, - 64, 15,220, 13, 2,205,113, 1, 58, 0, 64, 15,220, 13, 2, 8, - 245,230, 4, 15,253,111, 58, 0, 64, 15,220, 13, 2,241,197,213, - 229, 38, 28,104, 86, 36, 94, 36, 78,235,245, 58, 0, 64, 15,220, - 13, 2, 6, 7, 17,154, 18,120, 8,205,113, 1,235,112,235, 28, - 205,113, 1,235,112,235, 28,205,113, 1,235,112,235, 28,205,113, - 1,235,112,235, 28, 8, 71, 16,222,205,113, 1,235,112,235, 58, - 0, 64, 15,220, 13, 2,241, 71,205,157, 11,120, 17, 88, 18,230, - 7,131, 95,245,230, 3,198,176, 33,154, 18, 8, 58, 0, 64, 15, - 220, 13, 2, 8,253,119, 0, 70, 44,253,112, 1, 8,120, 18,123, - 198, 8, 95, 58, 0, 64, 15,220, 13, 2, 8,214,128, 6, 28,253, - 119, 0, 78,253,113, 1,198, 4, 44, 16,244, 58, 0, 64, 15,220, - 13, 2,125,214, 24,111, 6, 4,126, 18,123,198, 8, 95, 44, 16, - 247, 58, 0, 64, 15,220, 13, 2,241,225,209,193,201,205, 32, 10, - 195,204, 5,230, 7, 71, 58, 0, 64, 15,220, 13, 2,213,197,120, - 22, 18,198, 72, 95, 58, 0, 64, 15,220, 13, 2,205,113, 1, 58, - 0, 64, 15,220, 13, 2,235,112,235, 89,193, 75,209, 58, 0, 64, - 15,220, 13, 2,229,120, 33,128, 18,133,111,126,225,183,194,174, - 3, 58, 0, 64, 15,220, 13, 2,120,229, 33, 72, 18,133,111, 70, - 225,245, 58, 0, 64, 15,220, 13, 2,241,205, 51, 10,195,174, 3, - 245, 58, 0, 64, 15,220, 13, 2,205,113, 1, 58, 0, 64, 15,220, - 13, 2,241,197,213,229,230, 7,245, 38, 18,198, 88,111, 8, 58, - 0, 64, 15,220, 13, 2, 8,230, 4, 15,253,111, 58, 0, 64, 15, - 220, 13, 2,241,230, 3,198, 64, 79,126,230, 7, 95, 58, 0, 64, - 15,220, 13, 2,125,198, 8,111,123,254, 7, 56, 14,253,113, 0, - 126,128,254,127, 56, 2, 62,127,253,119, 1,121,198, 4, 79, 58, - 0, 64, 15,220, 13, 2,125,198, 8,111,123,254, 5, 56, 14,253, - 113, 0,126,128,254,127, 56, 2, 62,127,253,119, 1,121,198, 4, - 79, 58, 0, 64, 15,220, 13, 2,125,198, 8,111,123,254, 4, 56, - 14,253,113, 0,126,128,254,127, 56, 2, 62,127,253,119, 1,121, - 198, 4, 79, 58, 0, 64, 15,220, 13, 2,125,198, 8,111,253,113, - 0,126,128,254,127, 56, 2, 62,127,253,119, 1, 58, 0, 64, 15, - 220, 13, 2,225,209,193,201, 71, 58, 0, 64, 15,220, 13, 2,120, - 230, 4, 15,253,111,120, 8, 58, 0, 64, 15,220, 13, 2,205,113, - 1, 58, 0, 64, 15,220, 13, 2, 8,230, 3,198,180,253,119, 0, - 253,112, 1,195,204, 5, 71, 58, 0, 64, 15,220, 13, 2,120,230, - 4, 15,253,111,120, 8, 58, 0, 64, 15,220, 13, 2,205,113, 1, - 58, 0, 64, 15,220, 13, 2, 8,229,230, 7, 38, 18,198, 80,111, - 112, 8, 58, 0, 64, 15,220, 13, 2, 8,230, 7,198,128,111, 8, - 126,183,225,194,174, 3, 58, 0, 64, 15,220, 13, 2, 8,230, 3, - 198,180,253,119, 0,253,112, 1,195,174, 3,230, 7, 71, 58, 0, - 64, 15,220, 13, 2,229, 38, 18,120,198,128,111, 54, 1,225, 58, - 0, 64, 15,220, 13, 2,120,230, 4, 15,253,111,120,230, 3,135, - 135,198,180,253,119, 0,253, 54, 1,192,195,204, 5,230, 7,245, - 213,229, 79,230, 4, 15,253,111,121,230, 3,198, 64, 14, 6, 33, - 168, 17, 8, 58, 0, 64, 15,220, 13, 2, 8, 94,253,119, 0,198, - 4,253,115, 1, 0,253,119, 0,198, 4,253,115, 1, 0,253,119, - 0,198, 4,253,115, 1, 0,253,119, 0,198, 4,253,115, 1, 44, - 13,194,178, 11,225,209, 58, 0, 64, 15,220, 13, 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, 13, 2,201,120, 38, - 18,198, 64,111,197,120, 70,205, 0, 9,193, 58, 0, 64, 15,220, - 13, 2,197,125,198, 8,111,120, 70,205, 51, 10,193,125,198, 8, - 111,120,230, 3,198,180,253,119, 0,126,253,119, 1, 58, 0, 64, - 15,220, 13, 2,201, 33, 48, 18, 6, 3,197,126,203,127, 32, 6, - 6, 15, 44,195,170, 12,230,127, 71, 44,126,128, 71, 58, 0, 64, - 15,220, 13, 2,197, 44, 78, 44, 94, 44, 86,235, 58, 0, 64, 15, - 220, 13, 2,205,113, 1, 58, 0, 64, 15,220, 13, 2,120,254,254, - 202,209, 12,254,255,202,230, 12,253,104, 58, 0, 64, 15,220, 13, - 2,235,114, 45,115, 45,113, 45,193, 58, 0, 64, 15,220, 13, 2, - 253,125,128, 71,254, 16, 56, 2, 6, 15, 58, 0, 64, 15,220, 13, - 2,120, 7, 7, 7,193,176, 15, 15, 15,246,144, 50, 17,127,125, - 214, 17,111, 58, 0, 64, 15,220, 13, 2, 5,242, 74, 12,195, 57, - 1, 58, 0, 64, 15,220, 13, 2, 28,235,113, 44,115, 44,114,235, - 29, 29, 29,195,108, 12, 58, 0, 64, 15,220, 13, 2, 28,235, 78, - 44, 94, 44, 86,235, 29, 29, 29,195,108, 12,205, 31, 13,195,204, - 5, 71, 58, 0, 64, 15,220, 13, 2,120,229,230, 3, 33,136, 18, - 133,111,126,225,183,194,106, 4,120,205, 31, 13,195,174, 3,230, - 3, 71, 8, 58, 0, 64, 15,220, 13, 2,229, 38, 18,120, 15, 15, - 15, 15,111,126,246,128,119, 58, 0, 64, 15,220, 13, 2,213, 44, - 44, 84,125,198, 6, 95, 58, 0, 64, 15,220, 13, 2, 26,119, 44, - 28, 26,119, 44, 28, 26,119,209,225, 58, 0, 64, 15,220, 13, 2, - 205,113, 1, 58, 0, 64, 15,220, 13, 2, 8,229,213, 38, 17,104, - 17, 17,127, 15, 15, 15, 70,176, 18, 44,126, 18,209,225,201,205, - 146, 13,195,204, 5, 58,139, 18,183,194,106, 4,205,146, 13,195, - 174, 3, 58, 0, 64, 15,220, 13, 2,229, 33, 48, 18,126,246,128, - 119, 58, 0, 64, 15,220, 13, 2,213, 44, 44, 84,125,198, 6, 95, - 58, 0, 64, 15,220, 13, 2, 26,119, 44, 28, 26,119, 44, 28, 26, - 119,209,225, 58, 0, 64, 15,220, 13, 2,205,113, 1, 58, 0, 64, - 15,220, 13, 2, 62,224,176, 50, 17,127,201,205,255, 13,195,204, - 5, 71, 58, 0, 64, 15,220, 13, 2,120,229,230, 3, 33,136, 18, - 133,111,126,225,183,194,174, 3,120,205,255, 13,195,174, 3,230, - 3, 71, 58, 0, 64, 15,220, 13, 2,229, 38, 18,120, 15, 15, 15, - 15,111,126,230,127,119,225,201,230, 3, 8, 58, 0, 64, 15,220, - 13, 2,205,113, 1, 58, 0, 64, 15,220, 13, 2, 8,229, 38, 18, - 15, 15, 15, 15,111,126,230,128,176,119,225,195,204, 5,230, 3, - 8, 58, 0, 64, 15,220, 13, 2,205,113, 1, 58, 0, 64, 15,220, - 13, 2, 8,213,229,245, 17,136, 18,131, 95, 26, 95, 58, 0, 64, - 15,220, 13, 2,241, 38, 18, 15, 15, 15, 15,198, 15,111,112, 58, - 0, 64, 15,220, 13, 2,123,183, 32, 16,125,214, 15,111,126,230, - 128,176,119, 58, 0, 64, 15,220, 13, 2,225,209,195,174, 3,230, - 3, 8, 58, 0, 64, 15,220, 13, 2,205,113, 1, 58, 0, 64, 15, - 220, 13, 2, 8,213,229, 22, 28, 88, 38, 18, 15, 15, 15, 15,198, - 10,111, 58, 0, 64, 15,220, 13, 2, 26,119, 20, 45, 26,119, 20, - 45, 26,119, 58, 0, 64, 15,220, 13, 2,125,214, 8,111, 54, 0, - 225,209,195,204, 5,230, 3, 8, 58, 0, 64, 15,220, 13, 2,205, - 113, 1, 58, 0, 64, 15,220, 13, 2, 8,213,229, 22, 28, 88, 33, - 136, 18,245,133,111,241, 70, 38, 18, 15, 15, 15, 15,198, 15,111, - 58, 0, 64, 15,220, 13, 2,119, 45, 26,119, 20, 45, 26,119, 20, - 45, 26,119, 58, 0, 64, 15,220, 13, 2,120,183,202, 36, 15,225, - 209,195,174, 3, 58, 0, 64, 15,220, 13, 2, 84,125,214, 4, 95, - 126, 18, 44, 28,126, 18, 44, 28,126, 18, 58, 0, 64, 15,220, 13, - 2,125,214, 8,111, 54, 0,225,209,195,174, 3,205,112, 15,195, - 204, 5, 71, 58, 0, 64, 15,220, 13, 2,120,229,230, 15, 38, 18, - 198,128,111,126,225,183,194, 88, 4,120,205,112, 15,195,174, 3, - 230, 3, 8, 58, 0, 64, 15,220, 13, 2,205,113, 1, 58, 0, 64, - 15,220, 13, 2, 8,213, 17, 17,127, 15, 15, 15,176,246,128, 18, - 58, 0, 64, 15,220, 13, 2,205,113, 1, 58, 0, 64, 15,220, 13, - 2,235,112,235,209,201,205,195, 13,195,204, 5, 58,139, 18,183, - 194,106, 4,205,195, 13,195,174, 3,230, 3, 71, 58, 0, 64, 15, - 220, 13, 2,229, 38, 18,120,198,136,111, 54, 1, 58, 0, 64, 15, - 220, 13, 2,120, 15, 15, 15, 15,111, 38, 18, 54, 0,225,195,204, - 5,205, 1, 16,195, 37, 1,205, 1, 16,195, 47, 1,230, 15, 60, - 71,205, 18, 16,195, 37, 1,230, 15, 60, 71,205, 18, 16,195, 47, - 1, 58, 0, 64, 15,220, 13, 2,205,113, 1, 58, 0, 64, 15,220, - 13, 2,235,114, 45,115, 45,113, 58, 0, 64, 15,220, 13, 2, 45, - 112,201,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 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, @@ -281,8 +297,8 @@ static uint8_t echo_blob[] = { 129, 2,143, 1,141, 1,140, 1,138, 1,137, 1,135, 1,134, 1, 133, 1,131, 1,130, 1,129, 1,128, 1,143, 0,142, 0,142, 0, 132, 2,169, 2,210, 2,253, 2, 42, 3, 90, 3,142, 3,196, 3, - 253, 3, 57, 4,122, 4,190, 4,127, 0, 31, 31,255, 0,255,255, - 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 253, 3, 57, 4,122, 4,190, 4, 0, 2, 4, 6, 8, 10, 12,254, + 252,250,248,246,244,127, 0, 31, 31,255, 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,255,255,255,255,255,255,255,255,255,255,255, @@ -298,8 +314,8 @@ 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,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, + 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 b6fa48b..8c0995c 100644 --- a/doc/api-asm.68k +++ b/doc/api-asm.68k @@ -51,11 +51,6 @@ 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). -Echo_ResumeBGM - - Resumes playback of whatever background music was playing last time before - Echo_StopBGM was called. Used when you want to unpause music. - ============================================================================= *** Sound effects *** @@ -71,6 +66,28 @@ Echo_StopSFX ============================================================================= +*** Direct events *** + +Echo_PlayDirect + + Injects events to be played as part of the BGM the next tick. The register + a0 points to the ESF data to be injected. + + The injected events are a small stream on their own. The last event must + be $FF (this will return back to the BGM). Do *not* issue $FC, $FD or $FE + events, as you'll just break everything instead. + + The buffer is small, so don't go overboard. There's room for up to 128 + bytes (though again, each event is just 2-3 bytes). If there were direct + events pending to play, the new events will be appended at the end, so + take this into account when it comes to the buffer usage. You can check + if there are pending events with Echo_GetStatus (see bit 14) if you're + worried about running out of space. + + The buffer is only checked every tick. + +============================================================================= + *** Control *** Echo_GetStatus @@ -80,12 +97,32 @@ Echo_GetStatus Bit 0 .... Sound effect is playing Bit 1 .... Background music is playing + Bit 14 ... Echo isn't done parsing direct events Bit 15 ... Echo is busy (can't take commands) The API will automatically wait if you try to send a command while Echo is busy, so the only reason to check for that is if you don't want to halt the 68000 until Echo is ready to take more commands. +Echo_SetVolume + + Sets the global volume. Register d0 is a byte value ranging from 0 + (quietest) to 255 (loudest), and every channel is affected immediately. + The scale of the volume in this case is *linear*. + + Note that since PCM doesn't have volume, it gets toggled on/off depending + on the volume value (the cut off point is at 25%). + +Echo_SetVolumeEx + + 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 + 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). + ============================================================================= *** Settings *** diff --git a/doc/api-c.txt b/doc/api-c.txt index f0dd326..24c6312 100644 --- a/doc/api-c.txt +++ b/doc/api-c.txt @@ -55,11 +55,6 @@ 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). -void echo_resume_bgm() - - Resumes playback of whatever background music was playing last time before - echo_stop_bgm was called. Used when you want to unpause music. - ============================================================================= *** Sound effects *** @@ -75,6 +70,28 @@ void echo_stop_sfx() ============================================================================= +*** Direct events *** + +void echo_play_direct(const void *esf) + + Injects events to be played as part of the BGM the next tick. The + parameter 'esf' points to the ESF data to be injected. + + The injected events are a small stream on their own. The last event must + be $FF (this will return back to the BGM). Do *not* issue $FC, $FD or $FE + events, as you'll just break everything instead. + + The buffer is small, so don't go overboard. There's room for up to 128 + bytes (though again, each event is just 2-3 bytes). If there were direct + events pending to play, the new events will be appended at the end, so + take this into account when it comes to the buffer usage. You can check + if there are pending events with Echo_GetStatus (see ECHO_STAT_DIRBUSY) + if you're worried about running out of space. + + The buffer is only checked every tick. + +============================================================================= + *** Control *** uint16_t echo_get_status() @@ -82,14 +99,34 @@ uint16_t echo_get_status() Gets the current status of Echo. Returns an OR of the following flags, as relevant: - ECHO_STAT_BGM .... Background music is playing - ECHO_STAT_SFX .... Sound effect is playing - ECHO_STAT_BUSY ... Echo is busy (can't take commands) + ECHO_STAT_BGM ....... Background music is playing + ECHO_STAT_SFX ....... Sound effect is playing + ECHO_STAT_DIRBUSY ... Echo isn't done parsing direct events + ECHO_STAT_BUSY ...... Echo is busy (can't take commands) The API will automatically wait if you try to send a command while Echo is busy, so the only reason to check for that is if you don't want to halt the 68000 until Echo is ready to take more commands. +void echo_set_volume(uint8_t vol) + + Sets the global volume. The value 'vol' ranges from 0 (quietest) to 255 + (loudest), and every channel is affected immediately. The scale of the + volume in this case is *linear*. + + Note that since PCM doesn't have volume, it gets toggled on/off depending + on the volume value (the cut off point is at 25%). + +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 + 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). + ============================================================================= *** Settings *** diff --git a/doc/esf.txt b/doc/esf.txt index a7b833e..a96e35d 100644 --- a/doc/esf.txt +++ b/doc/esf.txt @@ -85,6 +85,8 @@ EVENT LIST $4Ann ..... Set instrument PSG channel #3 $4Bnn ..... Set instrument PSG channel #4 + $Dn ....... Delay ticks (short) + $E0 ....... [SFX] Lock FM channel #1 $E1 ....... [SFX] Lock FM channel #2 $E2 ....... [SFX] Lock FM channel #3 @@ -103,9 +105,12 @@ EVENT LIST $F5nn ..... Set parameters FM channel #5 $F6nn ..... Set parameters FM channel #6 + $F8rrnn ... Set FM register in bank 0 + $F9rrnn ... Set FM register in bank 1 + $FC ....... [BGM] Go to loop $FD ....... [BGM] Set loop point - $FEnn ..... Delay ticks + $FEnn ..... Delay ticks (long) $FF ....... Stop playback ============================================================================= @@ -288,6 +293,14 @@ $4Bnn: Set instrument PSG channel #4 ============================================================================= +$D0~$DF: Delay ticks (short) + + Same as $FE01 to $FE10 ($D0 = $FE01, $D1 = $FE02, etc.). Just a shorter + variant of the event to reduce space usage for shorter delays (which are + the most common). + +============================================================================= + $E0: Lock FM channel #1 [SFX ONLY] $E1: Lock FM channel #2 [SFX ONLY] $E2: Lock FM channel #3 [SFX ONLY] @@ -326,6 +339,34 @@ $F6: Set parameters FM channel #6 ============================================================================= +$F8rrnn: Set FM register in bank 0 +$F9rrnn: Set FM register in bank 1 + + These events are used to change the value of a YM2612 register directly. + The rr byte indicates the register, the nn byte is the value to be + written into it ($F8 writes to $4000/1, $F9 writes to $4002/3). + + HERE BE DRAGONS, USE AT YOUR OWN RISK. The channel locking mechanism will + *not* take care of this event, and if a SFX locks the channel then the + register will *not* be restored properly once the SFX is over. + + More specifically: + + * If you use it on a BGM, don't let it touch any channels that may + get locked by SFXs. + + * If you use it on a SFX for an effect on the SFX itself, use it only + for channels locked by that SFX. + + * If you use it on a SFX to affect the music, use it only on channels + that are *not* locked by any SFX (same as first rule, actually). + + * It's possible to touch the global registers ($22~$2B in bank 0). + Do it at your own risk. You may mess up with Echo's functionality, + so be careful about it and make sure you know what you're doing. + +============================================================================= + $FC: Go to loop [BGM ONLY] $FD: Set loop point [BGM ONLY] diff --git a/src-68k/echo.68k b/src-68k/echo.68k index 9304247..f10695a 100644 --- a/src-68k/echo.68k +++ b/src-68k/echo.68k @@ -192,11 +192,40 @@ 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 +;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 +; Injects events into the BGM stream for the next tick. +; +; input a0.l ... Pointer to stream data +;**************************************************************************** + +Echo_PlayDirect: + Echo_Z80Request ; We need the Z80 bus + movem.l d0-d1/a0-a1, -(sp) ; Save registers + + lea ($A01F00), a1 ; Skip any pending events + moveq #-1, d1 +@Skip: + cmp.b (a1), d1 + beq.s @Load + addq.w #1, a1 + bra.s @Skip + +@Load: ; Copy stream into the direct buffer + move.b (a0)+, d0 + move.b d0, (a1)+ + cmp.b d1, d0 + bne.s @Load + + movem.l (sp)+, d0-d1/a0-a1 ; Restore registers + Echo_Z80Release ; We're done with the Z80 bus rts ; End of subroutine ;**************************************************************************** @@ -214,6 +243,105 @@ Echo_SetPCMRate: movem.l (sp)+, d0-d1 ; Restore registers rts ; End of subroutine +;**************************************************************************** +; Echo_SetVolume +; Changes the global volume for every channel. +; +; input d0.b ... New volume (0 = quietest, 255 = loudest) +;**************************************************************************** + +Echo_SetVolume: + Echo_Z80Request ; We need the Z80 bus + movem.l d0-d1/a0-a1, -(sp) ; Save registers + + lea @FMTable(pc), a0 ; Determine FM volume + moveq #0, d1 + move.b d0, d1 + lsr.b #2, d1 + move.b (a0,d1.w), d1 + + lea ($A01FE0), a1 ; Copy new FM volume values + move.b d1, (a1)+ ; FM channel 0 + move.b d1, (a1)+ ; FM channel 1 + move.b d1, (a1)+ ; FM channel 2 + move.b d1, (a1)+ ; FM channel 3 + move.b d1, (a1)+ ; FM channel 4 + move.b d1, (a1)+ ; FM channel 5 + move.b d1, (a1)+ ; FM channel 6 + move.b d1, (a1)+ ; FM channel 7 + + lea @PSGTable(pc), a0 ; Determine PSG volume + moveq #0, d1 + move.b d0, d1 + lsr.b #2, d1 + move.b (a0,d1.w), d1 + + ; Copy new PSG values + move.b d1, (a1)+ ; PSG channel 0 + move.b d1, (a1)+ ; PSG channel 1 + move.b d1, (a1)+ ; PSG channel 2 + move.b d1, (a1)+ ; PSG channel 3 + + cmp.b #$40, d0 ; Determine whether PCM should be enabled + shs d1 ; (we do an heuristic for enabling PCM + and.b #1, d1 ; based on the volume value) + move.b d1, (a1)+ + + move.b #1, ($A01FF1) ; Tell Echo to update the volume levels + + movem.l (sp)+, d0-d1/a0-a1 ; Restore registers + Echo_Z80Release ; We're done with the Z80 bus + rts ; End of subroutine + +;---------------------------------------------------------------------------- + +@FMTable: + dc.b $7F,$7B,$77,$73,$70,$6C,$68,$65,$61,$5E,$5A,$57,$54,$50,$4D,$4A + dc.b $47,$44,$41,$3F,$3C,$39,$36,$34,$31,$2F,$2D,$2A,$28,$26,$24,$22 + dc.b $20,$1E,$1C,$1A,$18,$16,$15,$13,$12,$10,$0F,$0D,$0C,$0B,$0A,$09 + dc.b $08,$07,$06,$05,$04,$04,$03,$02,$02,$01,$01,$01,$00,$00,$00,$00 + +@PSGTable: + dc.b $0F,$0F,$0E,$0E,$0D,$0D,$0C,$0C,$0B,$0B,$0B,$0A,$0A,$0A,$09,$09 + dc.b $08,$08,$08,$07,$07,$07,$06,$06,$06,$06,$05,$05,$05,$04,$04,$04 + dc.b $04,$03,$03,$03,$03,$03,$02,$02,$02,$02,$02,$02,$01,$01,$01,$01 + dc.b $01,$01,$01,$01,$01,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 + +;**************************************************************************** +; Echo_SetVolumeEx +; Changes the global volume for each individual channel. +; +; input a0.l ... Pointer to 13 bytes +; 8 bytes with FM volumes (0..127) +; 4 bytes with PSG volumes (0..15) +; 1 byte with PCM toggle (0/1) +;**************************************************************************** + +Echo_SetVolumeEx: + Echo_Z80Request ; We need the Z80 bus + movem.l a0-a1, -(sp) ; Save registers + + lea ($A01FE0), a1 ; Copy new volume values + move.b (a0)+, (a1)+ ; FM channel 0 + move.b (a0)+, (a1)+ ; FM channel 1 + move.b (a0)+, (a1)+ ; FM channel 2 + move.b (a0)+, (a1)+ ; FM channel 3 + move.b (a0)+, (a1)+ ; FM channel 4 + move.b (a0)+, (a1)+ ; FM channel 5 + move.b (a0)+, (a1)+ ; FM channel 6 + move.b (a0)+, (a1)+ ; FM channel 7 + move.b (a0)+, (a1)+ ; PSG channel 0 + move.b (a0)+, (a1)+ ; PSG channel 1 + move.b (a0)+, (a1)+ ; PSG channel 2 + move.b (a0)+, (a1)+ ; PSG channel 3 + move.b (a0)+, (a1)+ ; PCM channel toggle + + move.b #1, ($A01FF1) ; Tell Echo to update the volume levels + + movem.l (sp)+, a0-a1 ; Restore registers + Echo_Z80Release ; We're done with the Z80 bus + rts ; End of subroutine + ;**************************************************************************** ; Echo_GetStatus ; Gets the current status of Echo @@ -221,6 +349,7 @@ Echo_SetPCMRate: ; output d0.w ... Echo status ; Bit #0: SFX is playing ; Bit #1: BGM is playing +; Bit #14: direct events not played ; Bit #15: command still not parsed ;**************************************************************************** @@ -228,10 +357,17 @@ Echo_GetStatus: moveq #0, d0 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 @NotBusy: + + cmpi.b #$FF, ($A01F00) ; Check if the direct buffer is empty + beq.s @DirectEmpty ; Any direct events still to be played? + bset.l #14, d0 ; If so, set the relevant flag +@DirectEmpty: + Echo_Z80Release ; Let the Z80 go! rts ; End of subroutine @@ -292,6 +428,25 @@ Echo_Init: move.b (a0)+, (a1)+ ; Copy byte into Z80 RAM dbf d0, @LoadLoop ; Go for next byte + moveq #0, d0 ; Set default global volumes + lea ($A01FE0), a0 + move.b d0, (a0)+ + move.b d0, (a0)+ + move.b d0, (a0)+ + move.b d0, (a0)+ + move.b d0, (a0)+ + move.b d0, (a0)+ + move.b d0, (a0)+ + move.b d0, (a0)+ + move.b d0, (a0)+ + move.b d0, (a0)+ + move.b d0, (a0)+ + move.b d0, (a0)+ + move.b #1, (a0)+ + move.b d0, ($A01FF1) + + move.b #$FF, ($A01F00) ; No direct events to execute + Echo_Z80Reset ; Now reset for real Echo_Z80Release ; Let the Z80 go! diff --git a/src-68k/esf.68k b/src-68k/esf.68k index fdaa55e..fc8dacc 100644 --- a/src-68k/esf.68k +++ b/src-68k/esf.68k @@ -44,6 +44,15 @@ ESF_FMFREQ_9 equ ESF_FMFREQ_A ESF_FMFREQ_10 equ ESF_FMFREQ_AS ESF_FMFREQ_11 equ ESF_FMFREQ_B +;**************************************************************************** +; Panning values +;**************************************************************************** + +ESF_PAN_OFF: equ $00 ; Mute +ESF_PAN_L: equ $80 ; Left speaker only +ESF_PAN_R: equ $40 ; Right speaker only +ESF_PAN_LR: equ $C0 ; Both speakers + ;**************************************************************************** ; ESF_NoteOn ; Start playing a note. @@ -165,6 +174,40 @@ ESF_Lock macro dc.b $E0+(\1) endm +;**************************************************************************** +; ESF_SetPan +; Set the panning of a FM channel. +;---------------------------------------------------------------------------- +; Format: +; ESF_SetPan channel, panning +;---------------------------------------------------------------------------- +; param channel ... channel to modify +; param panning ... panning (see ESF_PAN_*) +;**************************************************************************** + +ESF_SetPan macro + dc.b $F0+(\1) + dc.b (\2) + endm + +;**************************************************************************** +; ESF_SetFMReg +; Set a FM register directly. +;---------------------------------------------------------------------------- +; Format: +; ESF_SetFMReg bank, register, value +;---------------------------------------------------------------------------- +; param bank ....... YM2612 bank (0 or 1) +; param register ... register to modify +; param value ...... value to write +;**************************************************************************** + +ESF_SetFMReg macro + dc.b $F8+(\1) + dc.b (\2) + dc.b (\3) + endm + ;**************************************************************************** ; ESF_Delay ; Stop event. diff --git a/src-z80/build.z80 b/src-z80/build.z80 index 88932ac..1aaa709 100644 --- a/src-z80/build.z80 +++ b/src-z80/build.z80 @@ -2,6 +2,7 @@ include "src-z80/player/pcm.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" diff --git a/src-z80/core/bgm.z80 b/src-z80/core/bgm.z80 index 2f57a73..338a7a6 100644 --- a/src-z80/core/bgm.z80 +++ b/src-z80/core/bgm.z80 @@ -97,6 +97,8 @@ ResumeBGM: ;**************************************************************************** ; ProcessBGM ; Processes a tick for a BGM +;---------------------------------------------------------------------------- +; breaks: all ;**************************************************************************** ProcessBGM: @@ -153,6 +155,7 @@ ProcessBGMSkip: cp $FE jp z, SetDelayBGM ; Event $FE: set delay cp $FF +ProcessBGMEventFF: jp z, StopBGMEvent ; Event $FF: stop BGM cp $FC jp z, LoopBGM ; Event $FC: loop BGM @@ -192,8 +195,11 @@ ProcessBGMSkip: cp $F8 ; Events $F0-$F7: set FM parameters jp c, SetFMParamBGM + cp $FA ; Events $F8-$F9: set FM register + jp c, SetFMRegBGM PollPCM ; FFFFFFFFF bad event >:( +ProcessBGMEnd: jp StopBGMEvent ; End of subroutine ProcessBGMSkip2: ; This is where we land after a locked event diff --git a/src-z80/core/direct.z80 b/src-z80/core/direct.z80 new file mode 100644 index 0000000..d796ddf --- /dev/null +++ b/src-z80/core/direct.z80 @@ -0,0 +1,30 @@ +;**************************************************************************** +; ProcessDirect +; Processes the direct event stream. +;---------------------------------------------------------------------------- +; breaks: all +;**************************************************************************** + +ProcessDirect: + ld a, ($1F00) ; Are there even events to process? + inc a + ret z + + PollPCM + + ld hl, ProcessDirectEnd ; Override $FF event + ld (ProcessBGMEventFF+1), hl + + ld hl, $1F00 ; Where event data is stored + ld a, (RAM_LastBank) ; To avoid wasting time with bank + ld c, a ; switching + + jp ProcessBGMRun ; Start processing the event + +ProcessDirectEnd: + ld hl, StopBGMEvent ; Restore $FF event + ld (ProcessBGMEventFF+1), hl + ld a, $FF ; Reset the stream + ld ($1F00), a + + ret ; Return to the main loop diff --git a/src-z80/core/main.z80 b/src-z80/core/main.z80 index da323f4..4eb6e5a 100644 --- a/src-z80/core/main.z80 +++ b/src-z80/core/main.z80 @@ -90,6 +90,8 @@ EntryPoint: ;**************************************************************************** ; PollPCM ; Used to update PCM while not idle +;---------------------------------------------------------------------------- +; breaks: af ;**************************************************************************** PollPCM: macro @@ -154,21 +156,31 @@ IdleLoop: ;**************************************************************************** DoTick: - ld a, (ix+0) - bit 0, a - call nz, UpdatePCM +; ld a, (ix+0) +; bit 0, a +; call nz, UpdatePCM - ld (ix+0), $27 + PollPCM + + ld (ix+0), $27 ; Retrigger the timer ld (ix+1), $2F PollPCM + + ld a, ($1FF1) ; Refresh volume if needed + or a + call nz, RefreshVolume DoTick_SFX: ; Process SFXs jp DoTick_SFXSkip DoTick_SFXSkip: PollPCM + + call ProcessDirect ; Process direct events + PollPCM + DoTick_BGM: ; Process BGMs jp DoTick_BGMSkip DoTick_BGMSkip: @@ -257,6 +269,19 @@ LoadList: ;**************************************************************************** ; GetParam ; Subroutine for getting the parameter byte +;---------------------------------------------------------------------------- +; input c .... current bank +; input hl ... current address +;---------------------------------------------------------------------------- +; output b .... value +; output c .... new bank +; output hl ... new address +;---------------------------------------------------------------------------- +; breaks: af +;---------------------------------------------------------------------------- +; note: the C value gets incremented *only* when HL hits $0000 (this is +; relevant if you consider using it to fetch from Z80 RAM, which should +; never result in HL becoming $0000). ;**************************************************************************** GetParam: @@ -270,7 +295,7 @@ GetParam: BankSwitch pop hl .noswitchp: - ld b, (hl) ; Get volume + ld b, (hl) ; Get value inc l ; Get next address jp nz, .nonewbankp diff --git a/src-z80/core/sfx.z80 b/src-z80/core/sfx.z80 index 1c62873..4bca4c7 100644 --- a/src-z80/core/sfx.z80 +++ b/src-z80/core/sfx.z80 @@ -1,6 +1,8 @@ ;**************************************************************************** ; PlaySFX [command $02] ; Plays a SFX +;---------------------------------------------------------------------------- +; breaks: all ;**************************************************************************** PlaySFX: @@ -48,6 +50,8 @@ PlaySFX: ;**************************************************************************** ; ProcessSFX ; Processes a tick for a SFX +;---------------------------------------------------------------------------- +; breaks: all ;**************************************************************************** ProcessSFX: @@ -147,10 +151,14 @@ ProcessSFXRun: cp $F8 ; Events $F0-$F7: set FM parameters jp c, SetFMParamSFX + cp $FA ; Events $F8-$F9: set FM register + jp c, SetFMRegSFX ;**************************************************************************** ; StopSFX* [command $03, event $FF] ; Stops SFX playback +;---------------------------------------------------------------------------- +; breaks: all ;**************************************************************************** StopSFXEvent: @@ -186,6 +194,8 @@ StopSFX: ;**************************************************************************** ; ClearSFX ; Clears SFX resources +;---------------------------------------------------------------------------- +; breaks: all ;**************************************************************************** ClearSFX: diff --git a/src-z80/core/vars.z80 b/src-z80/core/vars.z80 index 959711b..cd7162d 100644 --- a/src-z80/core/vars.z80 +++ b/src-z80/core/vars.z80 @@ -17,6 +17,7 @@ RAM_BGMFMInstr: ds 8 ; FM instruments used by BGM RAM_BGMFMVol: ds 8 ; FM volumes used by BGM RAM_BGMFMPan: ds 8, $C0 ; FM panning used by BGM +RAM_FMVol: ds 8 ; FM volume of each channel RAM_FMData: ds 8*5 ; FM info (for volume handling) ; ds 8*1 ... Register $B0 ; ds 8*1 ... Register $40 @@ -25,6 +26,7 @@ RAM_FMData: ds 8*5 ; FM info (for volume handling) ; ds 8*1 ... Register $4C RAM_Locked: ds 12 ; Locked channels +RAM_PSGNote: ds 4 ; Current PSG notes RAM_LastBank: ds 1 ; Last accessed bank @@ -64,9 +66,11 @@ RAM_PointerList: equ $1C00 ; 68000 communication variables ;**************************************************************************** -RAM_Stack: equ $1FF0 ; Where stack starts +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_Command: equ $1FFF ; Command type RAM_ComAddr: equ $1FFD ; Command address parameter RAM_ComBank: equ $1FFC ; Command bank parameter diff --git a/src-z80/player/fm.z80 b/src-z80/player/fm.z80 index 558a01d..505e849 100644 --- a/src-z80/player/fm.z80 +++ b/src-z80/player/fm.z80 @@ -1,6 +1,12 @@ ;**************************************************************************** -; NoteOnFM +; NoteOnFM* [events $00~$07] ; Does a "note on" for a FM channel +;---------------------------------------------------------------------------- +; input a .... FM channel (bottom 3 bits) +; input c .... current bank +; input hl ... current address +;---------------------------------------------------------------------------- +; breaks: af, b ;**************************************************************************** NoteOnFMSFX: @@ -95,8 +101,14 @@ NoteOnFM: ret ; End of subroutine ;**************************************************************************** -; NoteOffFM +; NoteOffFM [events $10~$17] ; Does a "note off" for a FM channel +;---------------------------------------------------------------------------- +; input a .... FM channel (bottom 3 bits) +; input c .... current bank +; input hl ... current address +;---------------------------------------------------------------------------- +; breaks: af, b ;**************************************************************************** NoteOffFMSFX: @@ -129,8 +141,14 @@ NoteOffFM: ret ; End of subroutine ;**************************************************************************** -; SetFMNote* +; SetFMNote* [events $30~$37] ; Sets the note of a FM channel without "note on" +;---------------------------------------------------------------------------- +; input a .... FM channel (bottom 3 bits) +; input c .... current bank +; input hl ... current address +;---------------------------------------------------------------------------- +; breaks: af, b ;**************************************************************************** SetNoteFMSFX: @@ -200,8 +218,14 @@ SetNoteFM: ret ; End of subroutine ;**************************************************************************** -; LoadFM* +; LoadFM* [events $40~$47] ; Loads a FM instrument +;---------------------------------------------------------------------------- +; input a .... FM channel (bottom 3 bits) +; input c .... current bank +; input hl ... current address +;---------------------------------------------------------------------------- +; breaks: af, b ;**************************************************************************** LoadFMSFX: @@ -398,7 +422,9 @@ LoadFMDirect: pop hl pop de pop bc - ret + + ld b, 0 + jp SetFMVolLoad ;**************************************************************************** ; SetFMVol* @@ -475,6 +501,13 @@ SetFMVolLoad: and $07 ; Get channel ID + push af ; Store new FM volume + ld h, RAM_FMVol>>8 + add RAM_FMVol&$FF + ld l, a + ld (hl), b + pop af + push af ld h, RAM_FMData>>8 ; Get address of FM data add RAM_FMData&$FF @@ -483,6 +516,17 @@ SetFMVolLoad: ex af, af' PollPCM ex af, af' + + and $07 ; Get global volume + or $E0 + ld d, $1F + ld e, a + ex af, af' + ld a, (de) + ld d, a + + PollPCM + ex af, af' and $04 ; Determine which port to write rrca @@ -508,11 +552,13 @@ SetFMVolLoad: jr c, .noop1 ld (iy+0), c ld a, (hl) + add d + jp m, .tooquiet1 add b - cp $7F - jr c, .notooloud1 + jp p, .notooquiet1 +.tooquiet1: ld a, $7F -.notooloud1: +.notooquiet1: ld (iy+1), a .noop1: ld a, c @@ -529,11 +575,13 @@ SetFMVolLoad: jr c, .noop2 ld (iy+0), c ld a, (hl) + add d + jp m, .tooquiet2 add b - cp $7F - jr c, .notooloud2 + jp p, .notooquiet2 +.tooquiet2: ld a, $7F -.notooloud2: +.notooquiet2: ld (iy+1), a .noop2: ld a, c @@ -550,11 +598,13 @@ SetFMVolLoad: jr c, .noop3 ld (iy+0), c ld a, (hl) + add d + jp m, .tooquiet3 add b - cp $7F - jr c, .notooloud3 + jp p, .notooquiet3 +.tooquiet3: ld a, $7F -.notooloud3: +.notooquiet3: ld (iy+1), a .noop3: ld a, c @@ -568,11 +618,13 @@ SetFMVolLoad: ld l, a ld (iy+0), c ld a, (hl) ; Process operator #4 + add d + jp m, .tooquiet4 add b - cp $7F - jr c, .notooloud4 + jp p, .notooquiet4 +.tooquiet4: ld a, $7F -.notooloud4: +.notooquiet4: ld (iy+1), a PollPCM @@ -583,8 +635,17 @@ SetFMVolLoad: ret ; End of subroutine ;**************************************************************************** -; SetFMParam* +; SetFMParam* [events $F0-$F7] ; Sets the different parameters of a FM channel +;---------------------------------------------------------------------------- +; input c .... current bank +; input hl ... current address +;---------------------------------------------------------------------------- +; output b .... value +; output c .... new bank +; output hl ... new address +;---------------------------------------------------------------------------- +; breaks: af, b ;**************************************************************************** SetFMParamSFX: @@ -656,9 +717,63 @@ SetFMParamBGM: jp ProcessBGMRun ; End of subroutine +;**************************************************************************** +; SetFMReg* [events $F8-$F9] +; Changes a FM register +;---------------------------------------------------------------------------- +; input a .... YM2612 register bank (0 or 1, in bit 0) +; input c .... current bank +; input hl ... current address +;---------------------------------------------------------------------------- +; output b .... value +; output c .... new bank +; output hl ... new address +;---------------------------------------------------------------------------- +; breaks: af, b +;**************************************************************************** + +SetFMRegSFX: + call SetFMReg ; We're just a wrapper + jp ProcessSFXRun + +SetFMRegBGM: + call SetFMReg ; We're just a wrapper + jp ProcessBGMRun + +;---------------------------------------------------------------------------- + +SetFMReg: + and $01 ; Get port address + add a + ld iyl, a + + PollPCM ; Get parameters + call GetParam + push bc + PollPCM + call GetParam + PollPCM + ld a, b + pop bc + + ld (iy+0), b ; Write register + ld (iy+1), a + + ret ; End of subroutine + ;**************************************************************************** ; LockChannelFM [events $E0-$E7] ; Locks a FM channel +;---------------------------------------------------------------------------- +; input a ... FM channel (0..7, in bottom 3 bits) +; input c .... current bank +; input hl ... current address +;---------------------------------------------------------------------------- +; output b .... value +; output c .... new bank +; output hl ... new address +;---------------------------------------------------------------------------- +; breaks: af, iy ;**************************************************************************** LockChannelFM: @@ -694,6 +809,10 @@ LockChannelFM: ;**************************************************************************** ; KillFM ; Kills a FM channel +;---------------------------------------------------------------------------- +; input a ... FM channel (0..7, in bottom 3 bits) +;---------------------------------------------------------------------------- +; breaks: af, c, iy ;**************************************************************************** KillFM: @@ -720,20 +839,26 @@ KillFM: ld e, (hl) ld (iy+0), a - add 4 ld (iy+1), e - nop - ld (iy+0), a add 4 - ld (iy+1), e - nop + ex af, af' + PollPCM + ex af, af' ld (iy+0), a - add 4 ld (iy+1), e - nop + add 4 + ex af, af' + PollPCM + ex af, af' ld (iy+0), a + ld (iy+1), e add 4 + ex af, af' + PollPCM + ex af, af' + ld (iy+0), a ld (iy+1), e + add 4 inc l dec c @@ -743,7 +868,7 @@ KillFM: pop de PollPCM pop af - + ld c, a ; Cause the ADSR to reset or $F0 ld (ix+0), $28 @@ -752,7 +877,7 @@ KillFM: ld (ix+1), a ld (ix+0), $28 ld (ix+1), c - + PollPCM ret ; End of subroutine diff --git a/src-z80/player/freq.z80 b/src-z80/player/freq.z80 index beb8702..7f963e5 100644 --- a/src-z80/player/freq.z80 +++ b/src-z80/player/freq.z80 @@ -88,6 +88,16 @@ FMFreqTable: dw 810, 858, 910, 964 dw 1021, 1081, 1146, 1214 +;**************************************************************************** +; PSGShiftTable +; Semitone shifting table for PSG instruments +;**************************************************************************** + +PSGShiftTable: + db 0 + db 2, 4, 6, 8, 10, 12 + db -2, -4, -6, -8, -10, -12 + ;**************************************************************************** ; DummyFMInstr ; Dummy FM instrument to mute FM channels... diff --git a/src-z80/player/misc.z80 b/src-z80/player/misc.z80 index 36be250..dee980e 100644 --- a/src-z80/player/misc.z80 +++ b/src-z80/player/misc.z80 @@ -44,3 +44,47 @@ SetDelayShort: ld (hl), b ret ; End of subroutine + +;**************************************************************************** +; RefreshVolume +; Reloads the volume for all channels. +;---------------------------------------------------------------------------- +; breaks: all +;**************************************************************************** + +RefreshVolume: + ld hl, $1FF0 ; Update FM volume + ld de, RAM_FMVol + ld c, 8 +.fixfmvol: + ld a, (de) + ld b, (hl) + add b + jp p, .fixfmvolok + ld a, $7F +.fixfmvolok: + ld b, a + ld a, l + call SetFMVolLoad + inc l + inc e + dec c + jr nz, .fixfmvol + + ld hl, $1FE8 ; Update PSG volume + ld de, RAM_PSGData+1 + ld bc, $0410 +.fixpsgvol: + ld a, (hl) + ld (de), a + inc l + ld a, e + add a, c + ld e, a + PollPCM + djnz .fixpsgvol + + xor a ; Mark that volume was refreshed + ld ($1FF1), a + + ret ; End of subroutine diff --git a/src-z80/player/pcm.z80 b/src-z80/player/pcm.z80 index 2a484d4..99feb6d 100644 --- a/src-z80/player/pcm.z80 +++ b/src-z80/player/pcm.z80 @@ -1,6 +1,11 @@ ;**************************************************************************** -; PlayPCM* +; PlayPCM* [event $0C] ; Plays a PCM sample +;---------------------------------------------------------------------------- +; input c .... current bank +; input hl ... current address +;---------------------------------------------------------------------------- +; breaks: af, b ;**************************************************************************** PlayPCMSFX: @@ -18,6 +23,10 @@ PlayPCMBGM: 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 diff --git a/src-z80/player/psg.z80 b/src-z80/player/psg.z80 index f0c5a76..b88978c 100644 --- a/src-z80/player/psg.z80 +++ b/src-z80/player/psg.z80 @@ -46,7 +46,7 @@ UpdatePSG: cp $FF ; Loop envelope? jp z, .envloop - ld iyl, b ; Keep byte safe somewhere... + ld iyl, b ; Keep byte safe somewhere... PollPCM ex de, hl ; Store new address @@ -61,6 +61,7 @@ UpdatePSG: PollPCM db $FD,$7D ; ld a, iyl ; Mix envelope with volume + and $0F add b ld b, a