diff --git a/html/src/main/java/emu/joric/gwt/GwtAYPSG.java b/html/src/main/java/emu/joric/gwt/GwtAYPSG.java index a7c98b5..16f92bc 100644 --- a/html/src/main/java/emu/joric/gwt/GwtAYPSG.java +++ b/html/src/main/java/emu/joric/gwt/GwtAYPSG.java @@ -151,12 +151,18 @@ public void init(Via via, Keyboard keyboard, Snapshot snapshot) { updateStep = (int) (((long) step * 8L * (long) SAMPLE_RATE) / (long) CLOCK_1MHZ); output = new int[] { 0, 0, 0, 0xFF }; count = new int[] { updateStep, updateStep, updateStep, 0x7fff, updateStep }; - period = new int[] { updateStep, updateStep, updateStep, updateStep, 0 }; + // Every period must be non-zero: writeSample's counter catch-up loops + // never terminate on a zero period. + period = new int[] { updateStep, updateStep, updateStep, updateStep, updateStep }; registers = new int[16]; volumeA = volumeB = volumeC = volumeEnvelope = 0; disableToneA = disableToneB = disableToneC = disableAllNoise = false; - countEnv = hold = alternate = attack = holding = 0; + countEnv = hold = alternate = attack = 0; + // The envelope starts out holding, as if the reset-default shape 0 + // (decay then hold) had already completed its decay to 0. It starts + // moving when a program first writes the envelope shape register. + holding = 1; enable = 0; outNoise = 0; random = 1; @@ -384,6 +390,12 @@ public void writeRegister(int address, int value) { case 0x0B: case 0x0C: { int val = (((registers[0x0C] << 8) | registers[0x0B]) * updateStep) << 1; + // On the real chip an envelope period register value of 0 runs at + // twice the speed of period 1, i.e. a full 16-step envelope cycle + // in 128us at 1 MHz. (This is unlike the tone and noise periods, + // where 0 behaves the same as 1.) Period 1 is (updateStep << 1) + // here, so period 0 maps to half of that, which is updateStep. + val = (val == 0 ? updateStep : val); int last = period[ENVELOPE]; period[ENVELOPE] = val; int newCount = count[ENVELOPE] - (val - last); @@ -514,7 +526,7 @@ public void writeSample() { left -= add; } while (left > 0); - if (holding == 0 && period[ENVELOPE] != 0) { + if (holding == 0) { if ((count[ENVELOPE] -= step) <= 0) { int ce = countEnv; int envelopePeriod = period[ENVELOPE];