Skip to content

Commit

Permalink
Merge pull request #13 from Kagamiin/misc/test-bits-timers-portread
Browse files Browse the repository at this point in the history
Improved test bit accuracy; fixed port read function; implemented timers
  • Loading branch information
Kagamiin authored Feb 29, 2024
2 parents db720e2 + adf0d59 commit 26cc9bb
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 45 deletions.
26 changes: 25 additions & 1 deletion esfm.c
Original file line number Diff line number Diff line change
Expand Up @@ -2054,10 +2054,13 @@ ESFM_clip_sample(int32 sample)
return (int16_t)sample;
}

#define TIMER1_CONST (0.2517482517482517)
#define TIMER2_CONST (0.06293706293706293)
/* ------------------------------------------------------------------------- */
static void
ESFM_update_timers(esfm_chip *chip)
{
{
int i;
// Tremolo
if ((chip->global_timer & 0x3f) == 0x3f)
{
Expand Down Expand Up @@ -2110,6 +2113,27 @@ ESFM_update_timers(esfm_chip *chip)
}
}

for (i = 0; i < 2; i++)
{
if (chip->timer_enable[i])
{
chip->timer_accumulator[i] += i == 0 ? TIMER1_CONST : TIMER2_CONST;
if (chip->timer_accumulator[i] > 1.0)
{
chip->timer_accumulator[i] -= 1.0;
chip->timer_counter[i]++;
if (chip->timer_counter[i] == 0)
{
if (chip->timer_mask[i] == 0)
{
chip->timer_overflow[i] = true;
}
chip->timer_counter[i] = chip->timer_reload[i];
}
}
}
}

chip->eg_tick ^= 1;
}

Expand Down
22 changes: 16 additions & 6 deletions esfm.h
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ struct _esfm_chip
{
esfm_channel channels[18];
int32 output_accm[2];
uint_fast16_t addr_latch;
uint16 addr_latch;

flag emu_wavesel_enable;
flag emu_newmode;
Expand Down Expand Up @@ -248,25 +248,35 @@ struct _esfm_chip
flag emu_vibrato_deep;
flag emu_tremolo_deep;

double timer_accumulator[2];
uint8 timer_reload[2];
uint8 timer_counter[2];
flag timer_enable[2];
flag timer_mask[2];
flag timer_overflow[2];
flag irq_bit;

// Halts the envelope generators from advancing.
flag test_bit_eg_halt;
// -- Test bits (NOT IMPLEMENTED) --
// Halts the envelope generators from advancing. Written on bit 0, read back from bit 5.
flag test_bit_w0_r5_eg_halt;
/*
* Activates some sort of waveform test mode that amplifies the output volume greatly
* and continuously shifts the waveform table downwards, possibly also outputting the
* waveform's derivative? (it's so weird!)
*/
flag test_bit_distort;
flag test_bit_1_distort;
// Seems to do nothing.
flag test_bit_2;
// Seems to do nothing.
flag test_bit_3;
// Appears to attenuate the output by about 3 dB.
flag test_bit_attenuate;
flag test_bit_4_attenuate;
// Written on bit 5, read back from bit 0. Seems to do nothing.
flag test_bit_w5_r0;
// Resets all phase generators and holds them in the reset state while this bit is set.
flag test_bit_phase_stop_reset;
flag test_bit_6_phase_stop_reset;
// Seems to do nothing.
flag test_bit_7;

esfm_write_buf write_buf[ESFM_WRITEBUF_SIZE];
size_t write_buf_start;
Expand Down
72 changes: 34 additions & 38 deletions esfm_registers.c
Original file line number Diff line number Diff line change
Expand Up @@ -485,10 +485,14 @@ ESFM_write_reg_native (esfm_chip *chip, uint16_t address, uint8_t data)
}
break;
case TEST_REG:
chip->test_bit_eg_halt = (data & 0x01) | ((data & 0x20) != 0);
chip->test_bit_distort = (data & 0x02) != 0;
chip->test_bit_attenuate = (data & 0x10) != 0;
chip->test_bit_phase_stop_reset = (data & 0x40) != 0;
chip->test_bit_w0_r5_eg_halt = (data & 0x01) | ((data & 0x20) != 0);
chip->test_bit_1_distort = (data & 0x02) != 0;
chip->test_bit_2 = (data & 0x04) != 0;
chip->test_bit_3 = (data & 0x08) != 0;
chip->test_bit_4_attenuate = (data & 0x10) != 0;
chip->test_bit_w5_r0 = (data & 0x20) != 0;
chip->test_bit_6_phase_stop_reset = (data & 0x40) != 0;
chip->test_bit_7 = (data & 0x80) != 0;
break;
}
}
Expand Down Expand Up @@ -563,11 +567,14 @@ ESFM_readback_reg_native (esfm_chip *chip, uint16_t address)
data |= chip->emu_tremolo_deep << 7;
break;
case TEST_REG:
data |= chip->test_bit_eg_halt != 0;
data |= (chip->test_bit_distort != 0) << 1;
data |= (chip->test_bit_attenuate != 0) << 4;
data |= (chip->test_bit_eg_halt != 0) << 5;
data |= (chip->test_bit_phase_stop_reset != 0) << 6;
data |= chip->test_bit_w5_r0 != 0;
data |= (chip->test_bit_1_distort != 0) << 1;
data |= (chip->test_bit_2 != 0) << 2;
data |= (chip->test_bit_3 != 0) << 3;
data |= (chip->test_bit_4_attenuate != 0) << 4;
data |= (chip->test_bit_w0_r5_eg_halt != 0) << 5;
data |= (chip->test_bit_6_phase_stop_reset != 0) << 6;
data |= (chip->test_bit_7 != 0) << 7;
break;
case FOUROP_CONN_REG:
for (i = 0; i < 3; i++)
Expand All @@ -577,6 +584,7 @@ ESFM_readback_reg_native (esfm_chip *chip, uint16_t address)
}
break;
case NATIVE_MODE_REG:
data |= (chip->emu_newmode != 0);
data |= (chip->native_mode != 0) << 7;
break;
}
Expand Down Expand Up @@ -850,6 +858,7 @@ ESFM_write_port (esfm_chip *chip, uint8_t offset, uint8_t data)
case 0:
chip->native_mode = 0;
ESFM_native_to_emu_switch(chip);
// TODO: verify if the address write goes through
chip->addr_latch = data;
break;
case 1:
Expand Down Expand Up @@ -886,43 +895,30 @@ uint8_t
ESFM_read_port (esfm_chip *chip, uint8_t offset)
{
uint8_t data = 0;
if (chip->native_mode)

switch(offset)
{
switch(offset)
case 0:
data |= (chip->irq_bit != 0) << 7;
data |= (chip->timer_overflow[0] != 0) << 6;
data |= (chip->timer_overflow[1] != 0) << 5;
break;
case 1:
if (chip->native_mode)
{
case 0:
// TODO: actually implement timer count, trigger and reset
data |= (chip->irq_bit != 0) << 7;
data |= (chip->timer_overflow[0] != 0) << 6;
data |= (chip->timer_overflow[1] != 0) << 5;
break;
case 1:
data = ESFM_readback_reg_native(chip, chip->addr_latch);
break;
// TODO: verify what the ESFM chip actually returns when reading
// from the other address ports
}
}
else
{
switch(offset)
else
{
case 0:
data |= (chip->irq_bit != 0) << 7;
data |= (chip->timer_overflow[0] != 0) << 6;
data |= (chip->timer_overflow[1] != 0) << 5;
break;
case 1:
data = 0;
break;
case 2: case 3:
// This matches OPL3 behavior.
// TODO: verify what the ESFM chip actually returns when reading
// from address ports in emulation mode
data = 0xff;
break;
}
break;
case 2: case 3:
// This matches OPL3 behavior.
data = 0xff;
break;
}

return data;
}

Expand Down

0 comments on commit 26cc9bb

Please sign in to comment.