Permalink
Browse files

Echo 1.6 release... kind of a mess, will clean up in further commits …

…I guess
  • Loading branch information...
sik
sik committed Jan 22, 2018
1 parent a2f67fb commit 8fdf49b8e53fd3063ccc2eb51c49c3b6e4d073bb
@@ -1,4 +1,4 @@
© 2010-2017 Javier Degirolmo
© 2010-2018 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
12 README
@@ -7,12 +7,12 @@
| | |_ |_ ___ | | | | | | | |
| |_______ |_ |___| _| | | | | |_ |_____| _|
|___________| |________| |___| |___| |_________|
___ ___ _ _ ___ __ ___ ___ ___ _ ___ ___ _ ___ ___
| _| | | | | \ | _| | _| | | _| | | | _|_ |
| |_| | | | | | | | | | |_| | | |_| | | | |_ _ _ ___ ___ | | | |_ _| |
|_ | | | | | | | | | | _| | | | | | | | _| | | | __| _ \ | | |_ | _|
_| | | | | | | | | | | |_| | | | | | | | |_ | | | __| /_ | |_ _| | |_
|___|___|___|_|_|__/ |___|_|_|___|_|_|_|___| \_/|___|_|_\_| |_|_|___|___|
___ ___ _ _ ___ __ ___ ___ ___ _ ___ ___ _ ___
| _| | | | | \ | _| | _| | | _| | | | _|
| |_| | | | | | | | | | |_| | | |_| | | | |_ _ _ ___ ___ | | | |_
|_ | | | | | | | | | | _| | | | | | | | _| | | | __| _ \ | | | |
_| | | | | | | | | | | |_| | | | | | | | |_ | | | __| /_ | |_| | |
|___|___|___|_|_|__/ |___|_|_|___|_|_|_|___| \_/|___|_|_\_| |_|_|___|
=============================================================================
Binary file not shown.
BIN +256 Bytes (110%) built/prog-z80.bin
Binary file not shown.
@@ -25,7 +25,7 @@ static volatile uint16_t* const z80_reset = (uint16_t *) 0xA11200;
{ volatile int16_t i; for (i = 0xFF; i >= 0; i--); }
// Look-up tables for echo_set_volume
static const uint8_t fm_volumes[] = {
const uint8_t echo_fm_vol_table[0x40] = {
0x7F,0x7B,0x77,0x73,0x70,0x6C,0x68,0x65,
0x61,0x5E,0x5A,0x57,0x54,0x50,0x4D,0x4A,
0x47,0x44,0x41,0x3F,0x3C,0x39,0x36,0x34,
@@ -35,7 +35,7 @@ static const uint8_t fm_volumes[] = {
0x08,0x07,0x06,0x05,0x04,0x04,0x03,0x02,
0x02,0x01,0x01,0x01,0x00,0x00,0x00,0x00
};
static const uint8_t psg_volumes[] = {
const uint8_t echo_psg_vol_table[0x40] = {
0x0F,0x0F,0x0E,0x0E,0x0D,0x0D,0x0C,0x0C,
0x0B,0x0B,0x0B,0x0A,0x0A,0x0A,0x09,0x09,
0x08,0x08,0x08,0x07,0x07,0x07,0x06,0x06,
@@ -306,7 +306,7 @@ void echo_set_volume(uint8_t vol) {
Z80_REQUEST();
// Set FM volume values
uint8_t fm_vol = fm_volumes[vol >> 2];
uint8_t fm_vol = echo_fm_vol_table[vol >> 2];
z80_ram[0x1FE0] = fm_vol;
z80_ram[0x1FE1] = fm_vol;
z80_ram[0x1FE2] = fm_vol;
@@ -317,7 +317,7 @@ void echo_set_volume(uint8_t vol) {
z80_ram[0x1FE7] = fm_vol;
// Set PSG volume values
uint8_t psg_vol = psg_volumes[vol >> 2];
uint8_t psg_vol = echo_psg_vol_table[vol >> 2];
z80_ram[0x1FE8] = psg_vol;
z80_ram[0x1FE9] = psg_vol;
z80_ram[0x1FEA] = psg_vol;
@@ -367,6 +367,17 @@ void echo_set_pcm_rate(uint8_t rate) {
echo_send_command_byte(ECHO_CMD_SETPCMRATE, rate);
}
//***************************************************************************
// echo_set_stereo
// Toggles stereo or mono.
//---------------------------------------------------------------------------
// param enable: non-zero for stereo, zero for mono
//***************************************************************************
void echo_set_stereo(int enable) {
echo_send_command_byte(ECHO_CMD_SETSTEREO, !!enable);
}
//***************************************************************************
// echo_get_status
// Retrieves Echo's current status.
@@ -15,6 +15,7 @@ enum {
ECHO_CMD_RESUMEBGM, /* 0x06 - Resume BGM playback */
ECHO_CMD_SETPCMRATE, /* 0x07 - Set PCM rate */
ECHO_CMD_PAUSEBGM, /* 0x08 - Pause BGM playback */
ECHO_CMD_SETSTEREO, /* 0x09 - Toggle stereo */
};
/* Echo status flags */
@@ -47,4 +48,8 @@ void echo_send_command_byte(uint8_t cmd, uint8_t byte);
static void (* const echo_send_command_ex)(uint8_t, const void *) =
echo_send_command_addr;
/* Look-up tables */
extern const uint8_t echo_fm_vol_table[0x40];
extern const uint8_t echo_psg_vol_table[0x40];
#endif

Large diffs are not rendered by default.

Oops, something went wrong.
@@ -132,7 +132,9 @@ Echo_SetVolumeEx
Sets the global volume for each channel separately. Register a0 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.
scale, 0..127 for FM, 0..15 for PSG, lower = louder. You can use the
look-up tables described below (Echo_FMVolTable and Echo_PSGVolTable) to
convert from linear to .
The last byte (the one belonging to the PCM channel) is used to toggle
whether PCM plays, either 0 (disabled) or 1 (enabled).
@@ -141,6 +143,17 @@ Echo_SetVolumeEx
been changed for the sake of expansion. Currently the extra bytes are
ignored, but consider adapting your code (just set them to zero).
Echo_FMVolTable
Echo_PSGVolTable
These two are not subroutines but rather look-up tables. They have 64
byte-sized entries and they're used to convert a linear volume value into
a hardware volume value (e.g. for Echo_SetVolumeEx).
To give an idea of how to use these: take what you'd pass in d0 to
Echo_SetVolume divided by 4 (shift right by 2), then use it as an offset
to these tables. The byte will be the volume as the hardware (or
Echo_SetVolumeEx) wants it.
=============================================================================
*** Settings ***
@@ -167,6 +180,15 @@ Echo_SetPCMRate
(which can hamper Echo's ability to process complex streams). Be careful
if you increase the sample rate.
Echo_SetStereo
in d0 = $00 to use mono, otherwise to use stereo
Toggles whether sound is forced to mono (d0 == $00) or if stereo panning
works (d0 != $00). Will take effect for all following panning events. Can
be used to implement a mono/stereo toggle in games.
By default Echo is in stereo mode.
=============================================================================
*** Raw access ***
@@ -138,6 +138,17 @@ void echo_set_volume_ex(const uint8_t *ptr)
been changed for the sake of expansion. Currently the extra bytes are
ignored, but consider adapting your code (just set them to zero).
const uint8_t echo_fm_vol_table[]
const uint8_t echo_psg_vol_table[]
These two are not subroutines but rather look-up tables. They have 64
byte-sized entries and they're used to convert a linear volume value into
a hardware volume value (e.g. for echo_set_volume_ex).
To give an idea of how to use these: take what you'd pass as argument to
echo_set_volume divided by 4 (shift right by 2), then use it as an index
to these arrays. The byte will be the volume as the hardware (or
echo_set_volume_ex) wants it.
=============================================================================
*** Settings ***
@@ -163,6 +174,14 @@ void echo_set_pcm_rate(uint8_t rate)
(which can hamper Echo's ability to process complex streams). Be careful
if you increase the sample rate.
void echo_set_stereo(int enable)
Toggles whether sound is forced to mono (enable == 0) or if stereo panning
works (enable != 0). Will take effect for all following panning events.
Can be used to implement a mono/stereo toggle in games.
By default Echo is in stereo mode.
=============================================================================
*** Raw access ***
@@ -7,13 +7,25 @@ OVERVIEW
FORMAT
EEF instruments consist of a list of volume levels. Each byte represents
a different volume level, and the value ranges from $00 (loudest) to $0F
(quietest). Each byte represents one tick (i.e. 1/60th of a second).
EEF instruments consist of a byte per tick (1/60th of a second). The
bottom nibble is the volume level (relative to the note's volume),
ranging from $x0 (loudest) to $xF (quietest).
The upper nibble is a "semitone shift", which is added to the current
note's semitone. These can be useful for things like vibrato (e.g. for
whistles) and such. The amount the semitone is shifted is as follows:
$0x ... 0 | $1x ... +1 | $8x ... -1
| $2x ... +2 | $9x ... -2
| $3x ... +3 | $Ax ... -3
| $4x ... +4 | $Bx ... -4
| $5x ... +6 | $Cx ... -6
| $6x ... +8 | $Dx ... -8
| $7x ... +12 | $Ex ... -12
Looping is possible. The start of the loop is marked by a byte with value
$FE, while the end of the loop is marked by a byte with value $FF. There
must be at least one volume byte between them or Echo will hang.
must be at least one tick byte between them or Echo will hang.
To make a non-looping PSG instrument, just put the last volume value
inside the loop.
@@ -22,14 +34,14 @@ FORMAT
NOTES
Yes, this format was kind of an afterthought. Later I may improve it to
provide at least some kind of RLE-like compression, but for now you'll
have to stick with this :P
Also, since PSG instruments are required to use PSG channels and I know
many of you don't want to mess with them at all, here's a flat PSG
instrument (i.e. no envelope):
Since PSG instruments are required to use PSG channels and I know many of
you don't want to mess with them at all, here's a flat PSG instrument
(i.e. no envelope):
$FE,$00,$FF
There's a flavor of the Set Frequency event that doesn't play nice with
semitone shifting (in which case it'll just act as if it was always $0x).
It will work again once a new note starts or the other flavor is used.
=============================================================================
@@ -217,34 +217,56 @@ $2Bnn: Set volume PSG channel #4
=============================================================================
$30nnnn: Set frequency FM channel #1
$31nnnn: Set frequency FM channel #2
$32nnnn: Set frequency FM channel #3
$34nnnn: Set frequency FM channel #4
$35nnnn: Set frequency FM channel #5
$36nnnn: Set frequency FM channel #6
$30nn/$30nnnn: Set frequency FM channel #1
$31nn/$31nnnn: Set frequency FM channel #2
$32nn/$32nnnn: Set frequency FM channel #3
$34nn/$34nnnn: Set frequency FM channel #4
$35nn/$35nnnn: Set frequency FM channel #5
$36nn/$36nnnn: Set frequency FM channel #6
These events set the raw frequency of a specific FM channel, without
triggering a new note. Meant for note slides. The following two bytes
specify the new frequency in the same format as the YM2612 expects. The
first byte is register +$A4, the second byte is register +$A0.
triggering a new note. Meant for note slides. The format of this event
depends on whether the second byte has its MSB set or not.
If the 2nd byte's MSB is set, the event is two bytes long. The 2nd byte
is the semitone in this format (where "octave" is from 0 to 7 and
"semitone" is from 0 to 11):
octave * 16 + semitone + 128
If the 2nd byte's MSB is clear, the event is three bytes long. The 2nd
and 3rd bytes specify the new frequency in the same format as the YM2612
expects. The 2nd byte is register $A4+, the 3rd byte is register $A0+.
Echo uses the following frequency values for each semitone:
C - 644 | E - 810 | G# - 1021
C# - 681 | F - 858 | A - 1081
D - 722 | F# - 910 | A# - 1146
D# - 765 | G - 964 | B - 1214
$38nnnn: Set frequency PSG channel #1
$39nnnn: Set frequency PSG channel #2
$3Annnn: Set frequency PSG channel #3
$38nn/$38nnnn: Set frequency PSG channel #1
$39nn/$39nnnn: Set frequency PSG channel #2
$3Ann/$3Annnn: Set frequency PSG channel #3
These events set the raw frequency of a specific square wave PSG channel,
without triggering a new note. Meant for note slides. The following two
bytes specify the new frequency, the first byte containing the four least
significant bits (LSB aligned), and the next byte containing the six most
significant bits (LSB aligned too).
without triggering a new note. Meant for note slides. The format of this
event depends on whether the second byte has its MSB set or not.
If the 2nd byte's MSB is set, the event is two bytes long. The 2nd byte
is the semitone in this format (where "octave" is from 0 to 5 and
"semitone" is from 0 to 11):
octave * 12 + semitone + 128
If the 2nd byte's MSB is clear, the event is three bytes long. The 2nd
and 3rd bytes specify the new frequency, the 2nd byte containing the
four least significant bits (LSB aligned), and the 3rd byte containing
the six most significant bits (LSB aligned too).
IMPORTANT: using the 3-byte event prevents semitone shifting in PSG
instruments from working. It will start working again whenever a new note
or the 2-byte version of this event is used.
Echo uses the following frequency values for each semitone:
@@ -272,6 +272,22 @@ Echo_SetPCMRate:
movem.l (sp)+, d0-d1 ; Restore registers
rts ; End of subroutine
;****************************************************************************
; Echo_SetStereo
; Sets whether stereo is enabled or not
;
; input d0.b ... 0 to disable, otherwise to enable
;****************************************************************************
Echo_SetStereo:
movem.l d0-d1, -(sp) ; Save registers
tst.b d0 ; Check what we want to do
seq.b d1 ; Put parameter in place
move.b #$09, d0 ; Command $09 = set stereo
bsr Echo_SendCommandByte ; Send command to Echo
movem.l (sp)+, d0-d1 ; Restore registers
rts ; End of subroutine
;****************************************************************************
; Echo_SetVolume
; Changes the global volume for every channel.
@@ -283,7 +299,7 @@ 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
lea Echo_FMVolTable(pc), a0 ; Determine FM volume
moveq #0, d1
move.b d0, d1
lsr.b #2, d1
@@ -299,7 +315,7 @@ Echo_SetVolume:
move.b d1, (a1)+ ; FM channel 6
move.b d1, (a1)+ ; FM channel 7
lea @PSGTable(pc), a0 ; Determine PSG volume
lea Echo_PSGVolTable(pc),a0 ; Determine PSG volume
moveq #0, d1
move.b d0, d1
lsr.b #2, d1
@@ -324,13 +340,13 @@ Echo_SetVolume:
;----------------------------------------------------------------------------
@FMTable:
Echo_FMVolTable:
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:
Echo_PSGVolTable:
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
@@ -220,12 +220,19 @@ ESF_SetFMReg macro
ESF_Delay macro
if (\1)>0
if (\1)<=$10
dc.b $D0-1+(\1)
else
dc.b $FE
dc.b (\1)&$FF
endc
if (\1)>=$100
rept (\1)/$100
dc.b $FE, $00
endr
endc
if (\1)%$100
if ((\1)%$100)<=$10
dc.b $D0-1+((\1)%$100)
else
dc.b $FE
dc.b (\1)%$100
endc
endc
endc
endm
@@ -376,10 +376,11 @@ ClearBGM:
ld a, b ; Reset panning
and $04
rrca
ld iyl, a
ld a, b
and $03
add $B4
add a, $B4
ld (iy+0), a
ld (iy+1), $C0
Oops, something went wrong.

0 comments on commit 8fdf49b

Please sign in to comment.