// license:GPL-2.0+ // copyright-holders:Matthew Conte /***************************************************************************** MAME/MESS NES APU CORE Based on the Nofrendo/Nosefart NES RP2A03 sound emulation core written by Matthew Conte (matt@conte.com) and redesigned for use in MAME/MESS by Who Wants to Know? (wwtk@mail.com) This core is written with the advise and consent of Matthew Conte and is released under the GNU Public License. ***************************************************************************** NES_DEFS.H NES APU internal type definitions and constants. *****************************************************************************/ #ifndef MAME_SOUND_NES_DEFS_H #define MAME_SOUND_NES_DEFS_H #pragma once /* APU type */ struct apu_t { /* CHANNEL TYPE DEFINITIONS */ /* Square Wave */ struct square_t { square_t() { for (auto & elem : regs) elem = 0; } u8 regs[4]; s32 vbl_length = 0; s32 freq = 0; float phaseacc = 0.0; float env_phase = 0.0; float sweep_phase = 0.0; u8 adder = 0; u8 env_vol = 0; bool enabled = false; u8 output = 0; }; /* Triangle Wave */ struct triangle_t { triangle_t() { for (auto & elem : regs) elem = 0; } u8 regs[4]; /* regs[1] unused */ s32 linear_length = 0; bool linear_reload = false; s32 vbl_length = 0; s32 write_latency = 0; float phaseacc = 0.0; u8 adder = 0; bool counter_started = false; bool enabled = false; u8 output = 0; }; /* Noise Wave */ struct noise_t { noise_t() { for (auto & elem : regs) elem = 0; } u8 regs[4]; /* regs[1] unused */ u16 lfsr = 1; s32 vbl_length = 0; float phaseacc = 0.0; float env_phase = 0.0; u8 env_vol = 0; bool enabled = false; u8 output = 0; }; /* DPCM Wave */ struct dpcm_t { dpcm_t() { for (auto & elem : regs) elem = 0; } u8 regs[4]; u32 address = 0; u32 length = 0; s32 bits_left = 0; float phaseacc = 0.0; u8 cur_byte = 0; bool enabled = false; bool irq_occurred = false; s16 vol = 0; u8 output = 0; }; /* REGISTER DEFINITIONS */ static constexpr unsigned WRA0 = 0x00; static constexpr unsigned WRA1 = 0x01; static constexpr unsigned WRA2 = 0x02; static constexpr unsigned WRA3 = 0x03; static constexpr unsigned WRB0 = 0x04; static constexpr unsigned WRB1 = 0x05; static constexpr unsigned WRB2 = 0x06; static constexpr unsigned WRB3 = 0x07; static constexpr unsigned WRC0 = 0x08; static constexpr unsigned WRC2 = 0x0A; static constexpr unsigned WRC3 = 0x0B; static constexpr unsigned WRD0 = 0x0C; static constexpr unsigned WRD2 = 0x0E; static constexpr unsigned WRD3 = 0x0F; static constexpr unsigned WRE0 = 0x10; static constexpr unsigned WRE1 = 0x11; static constexpr unsigned WRE2 = 0x12; static constexpr unsigned WRE3 = 0x13; static constexpr unsigned SMASK = 0x15; static constexpr unsigned IRQCTRL = 0x17; /* Sound channels */ square_t squ[2]; triangle_t tri; noise_t noi; dpcm_t dpcm; u8 step_mode = 0; bool frame_irq_enabled = false; bool frame_irq_occurred = false; }; struct mmc5_sound_t { /* CHANNEL TYPE DEFINITIONS */ /* Square Wave */ struct square_t { square_t() { for (auto & elem : regs) elem = 0; } u8 regs[4]; s32 vbl_length = 0; s32 freq = 0; float phaseacc = 0.0; float env_phase = 0.0; u8 adder = 0; u8 env_vol = 0; bool enabled = false; u8 output = 0; }; /* DPCM Wave */ struct pcm_t { pcm_t() { for (auto & elem : regs) elem = 0; } u8 regs[2]; bool irq_enabled = false; bool irq_line = false; u8 output = 0; }; /* REGISTER DEFINITIONS */ static constexpr unsigned WRA0 = 0x00; static constexpr unsigned WRA1 = 0x01; static constexpr unsigned WRA2 = 0x02; static constexpr unsigned WRA3 = 0x03; static constexpr unsigned WRB0 = 0x04; static constexpr unsigned WRB1 = 0x05; static constexpr unsigned WRB2 = 0x06; static constexpr unsigned WRB3 = 0x07; static constexpr unsigned WRE0 = 0x10; static constexpr unsigned WRE1 = 0x11; static constexpr unsigned SMASK = 0x15; /* Sound channels */ square_t squ[2]; pcm_t pcm; }; /* CONSTANTS */ /* vblank length table used for squares, triangle, noise */ static const u8 vbl_length[32] = { 10, 254, 20, 2, 40, 4, 80, 6, 160, 8, 60, 10, 14, 12, 26, 14, 12, 16, 24, 18, 48, 20, 96, 22, 192, 24, 72, 26, 16, 28, 32, 30 }; /* frequency limit of square channels */ static const int freq_limit[8] = { 0x3FF, 0x555, 0x666, 0x71C, 0x787, 0x7C1, 0x7E0, 0x7F0, }; // table of noise period // each fundamental is determined as: freq = master / period / 93 static const int noise_freq[2][16] = { { 4, 8, 16, 32, 64, 96, 128, 160, 202, 254, 380, 508, 762, 1016, 2034, 4068 }, // NTSC { 4, 8, 14, 30, 60, 88, 118, 148, 188, 236, 354, 472, 708, 944, 1890, 3778 } // PAL }; // dpcm (cpu) cycle period // each frequency is determined as: freq = master / period static const int dpcm_clocks[2][16] = { { 428, 380, 340, 320, 286, 254, 226, 214, 190, 160, 142, 128, 106, 84, 72, 54 }, // NTSC { 398, 354, 316, 298, 276, 236, 210, 198, 176, 148, 132, 118, 98, 78, 66, 50 } // PAL }; /* ratios of pos/neg pulse for square waves */ /* 2/16 = 12.5%, 4/16 = 25%, 8/16 = 50%, 12/16 = 75% */ static const int duty_lut[4] = { 0b01000000, // 01000000 (12.5%) 0b01100000, // 01100000 (25%) 0b01111000, // 01111000 (50%) 0b10011111, // 10011111 (25% negated) }; #endif // MAME_SOUND_NES_DEFS_H