|
| 1 | +#ifndef _FCEU_APU_H |
| 2 | +#define _FCEU_APU_H |
| 3 | + |
| 4 | +enum FrameSeqMode { |
| 5 | + FrameFourStepMode = 0, |
| 6 | + FrameFiveStepMode = 1 |
| 7 | +}; |
| 8 | + |
| 9 | +enum FrameType { |
| 10 | + FrameNone = 0, |
| 11 | + FrameHalf = 1, |
| 12 | + FrameQuarter = 2 |
| 13 | +}; |
| 14 | + |
| 15 | +enum WavePositionShift { |
| 16 | + SQ_SHIFT = 24, |
| 17 | + TRINPCM_SHIFT = 16 |
| 18 | +}; |
| 19 | + |
| 20 | +typedef struct Timer { |
| 21 | + uint16 period; /* Frequency period for square wave (controls pitch) */ |
| 22 | + |
| 23 | + /* Internal */ |
| 24 | + int32 counter; /* Counter tracking the square wave period (timing of cycles) */ |
| 25 | + int32 count2; /* Shifted period timer for low-quality mode */ |
| 26 | +} Timer; |
| 27 | + |
| 28 | +typedef struct LengthCount { |
| 29 | + /* Registers */ |
| 30 | + uint8 enabled; /* set by channel enable flag in 4015 write */ |
| 31 | + uint8 halt; /* Halt flag: if set, disables further counting */ |
| 32 | + |
| 33 | + uint8 counter; /* Current count value for length counter (counts down) */ |
| 34 | + |
| 35 | + uint8 delayHalt; |
| 36 | + uint8 delayCounter; |
| 37 | + uint8 nextHalt; |
| 38 | + uint8 nextCounter; |
| 39 | +} LengthCount; |
| 40 | + |
| 41 | +typedef struct Envelope { |
| 42 | + /* Register */ |
| 43 | + uint8 loop; /* Loop mode flag: if set, envelope restarts after reaching a certain state */ |
| 44 | + uint8 constant; /* Constant mode flag: if set, volume remains constant */ |
| 45 | + uint8 speed; /* Speed of volume decay, affecting the rate of decrease */ |
| 46 | + |
| 47 | + /* internal */ |
| 48 | + uint8 decay_volume; /* Current volume level during the decay phase */ |
| 49 | + uint8 counter; /* Counter tracking the current state of decay process */ |
| 50 | + uint8 reload; /* Flag to reload decay counter (restarts volume decrease) */ |
| 51 | +} Envelope; |
| 52 | + |
| 53 | +typedef struct Sweep { |
| 54 | + /* Register */ |
| 55 | + uint8 enabled; /* Enable flag for sweep operation (if set, sweep occurs) */ |
| 56 | + uint8 period; /* Sweep period: determines the rate at which frequency is adjusted */ |
| 57 | + uint8 negate; /* Negate flag: if set, subtracts from the frequency during sweep */ |
| 58 | + uint8 shift; /* Number of bits to shift for frequency adjustment in the sweep */ |
| 59 | + |
| 60 | + uint16 pulsePeriod; /* Period of the pulse being swept (frequency of waveform) */ |
| 61 | + |
| 62 | + /* Internal */ |
| 63 | + uint8 id; |
| 64 | + uint8 counter; /* Counter for sweep timing (decrements until reload) */ |
| 65 | + uint8 reload; /* Reload flag: when set, resets sweep counter to initial value */ |
| 66 | +} Sweep; |
| 67 | + |
| 68 | +typedef struct SquareUnit { |
| 69 | + /* Registers*/ |
| 70 | + uint8 duty; /* Duty cycle defines the waveform's high-to-low ratio */ |
| 71 | + |
| 72 | + /* Internal */ |
| 73 | + uint8 step; /* Counter for tracking the current phase of the duty cycle */ |
| 74 | + |
| 75 | + LengthCount length; /* Length counter to manage note duration for square wave */ |
| 76 | + Envelope envelope; /* Envelope to control volume for square wave */ |
| 77 | + Sweep sweep; /* Sweep to modify frequency of square wave */ |
| 78 | + Timer timer; /* Cycle counter and period to reload */ |
| 79 | +} SquareUnit; |
| 80 | + |
| 81 | +typedef struct TriangleUnit { |
| 82 | + uint8 linearPeriod; /* Linear length control value for the triangle wave */ |
| 83 | + |
| 84 | + /* Internal */ |
| 85 | + uint8 linearCounter; /* Counter to track linear length during envelope decay */ |
| 86 | + uint8 linearReload; /* Flag to reload the linear length counter */ |
| 87 | + uint8 stepCounter; /* Counter for tracking the steps in the triangle wave's length */ |
| 88 | + |
| 89 | + LengthCount length; /* Length counter for triangle wave channel (note duration) */ |
| 90 | + Timer timer; /* Cycle counter and period to reload */ |
| 91 | +} TriangleUnit; |
| 92 | + |
| 93 | +typedef struct NoiseUnit { |
| 94 | + /* Register */ |
| 95 | + uint8 shortMode; /* Short mode flag for noise wave: alters frequency generation behavior */ |
| 96 | + uint8 periodIndex; /* The period determines how many CPU cycles happen between shift register clocks. */ |
| 97 | + |
| 98 | + /* Internal */ |
| 99 | + uint16 shiftRegister; /* Shift register used to generate noise waveform */ |
| 100 | + |
| 101 | + LengthCount length; /* Length counter for noise wave channel (note duration) */ |
| 102 | + Envelope envelope; /* Envelope to control volume for noise wave */ |
| 103 | + Timer timer; /* Cycle counter and period to reload */ |
| 104 | +} NoiseUnit; |
| 105 | + |
| 106 | +typedef struct DMCUnit { |
| 107 | + uint8 bitCounter; /* Bit counter for reading sample data bits (tracks position in current sample) */ |
| 108 | + |
| 109 | + uint8 addressLatch; /* Address latch for DMC sample address (mapped to $4012) */ |
| 110 | + uint8 lengthLatch; /* Length latch for DMC sample length (mapped to $4013) */ |
| 111 | + uint8 periodIndex; /* The rate determines for how many CPU cycles happen between changes in the output level during automatic delta-encoded sample playback */ |
| 112 | + uint8 loop; /* Loop flag for DMC sample (1 = loop, 0 = no loop) */ |
| 113 | + uint8 irqEnabled; /* IRQ enabled flag: if set, triggers IRQ when sample finishes loading */ |
| 114 | + uint8 irqPending; /* Flag indicating if an IRQ is pending */ |
| 115 | + |
| 116 | + uint16 readAddress; /* Address to read data from in memory for DMC sample */ |
| 117 | + uint16 lengthCounter; /* Counter for the length of the sample data to play */ |
| 118 | + uint8 sampleShiftReg; /* Holds the current sample data during DMA shift processing */ |
| 119 | + |
| 120 | + uint8 dmaBufferValid; /* Flag indicating whether the DMA buffer contains valid data */ |
| 121 | + uint8 dmaBuffer; /* DMA buffer for transferring sample data to audio output */ |
| 122 | + uint8 sampleValid; /* Sample validity flag: indicates if sample data is properly loaded */ |
| 123 | + uint8 rawDataLatch; /* Raw data latch for DMC control (mapped to $4011 0xxxxxxx) */ |
| 124 | + |
| 125 | + Timer timer; |
| 126 | +} DMCUnit; |
| 127 | + |
| 128 | +typedef struct FrameCounter { |
| 129 | + uint8 mode; /* Mode of the frame counter operation, 1=5-step, 0=4-step */ |
| 130 | + uint8 irqInhibit; /* Flag to inhibit IRQ generation */ |
| 131 | + uint8 irqPending; /* Flag indicating if an IRQ is pending */ |
| 132 | + uint8 step; /* Current step in frame counter operation */ |
| 133 | + |
| 134 | + /* Timers */ |
| 135 | + int32 counter; /* frame cycle counter */ |
| 136 | + |
| 137 | + uint8 delay; /* Delay after 4017 write */ |
| 138 | + uint8 newMode; |
| 139 | +} FrameCounter; |
| 140 | + |
| 141 | +#endif /* _FCEU_APU_H */ |
0 commit comments