////////////////////////////////////////////////////////////////////////// // MapperNSF NSF:NES Sound Format // ////////////////////////////////////////////////////////////////////////// #include "math.h" #define NSF_PROFILE 0 #if NSF_PROFILE static DWORD avecount = 0; static float tave = 0.0f; static float pave = 0.0f; static float ptave = 0.0f; static DWORD maxtotalclk = 0; static DWORD maxprofclk = 0; static DWORD maxproftotalclk = 0; static DWORD maxproftotalcnt = 0; #endif BYTE MapperNSF::Font6x8[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00, 0x50,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x50,0xF8,0x50,0xF8,0x50,0x50,0x00, 0x20,0x78,0xA0,0x70,0x28,0xF0,0x20,0x00,0x48,0xB0,0x50,0x20,0x50,0x68,0x90,0x00, 0x40,0xA0,0xA8,0x68,0x90,0x90,0x68,0x00,0x30,0x20,0x00,0x00,0x00,0x00,0x00,0x00, 0x10,0x20,0x40,0x40,0x40,0x20,0x10,0x00,0x40,0x20,0x10,0x10,0x10,0x20,0x40,0x00, 0x00,0x88,0x50,0x20,0x50,0x88,0x00,0x00,0x00,0x20,0x20,0xF8,0x20,0x20,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x20,0x40,0x00,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x08,0x10,0x10,0x20,0x40,0x40,0x80,0x00, 0x70,0x88,0x98,0xA8,0xC8,0x88,0x70,0x00,0x20,0x60,0x20,0x20,0x20,0x20,0xF8,0x00, 0x70,0x88,0x08,0x30,0x40,0x80,0xF8,0x00,0x70,0x88,0x08,0x30,0x08,0x88,0x70,0x00, 0x30,0x50,0x90,0x90,0xF8,0x10,0x10,0x00,0xF8,0x80,0x80,0xF0,0x08,0x08,0xF0,0x00, 0x70,0x88,0x80,0xF0,0x88,0x88,0x70,0x00,0xF8,0x08,0x10,0x10,0x20,0x20,0x20,0x00, 0x70,0x88,0x88,0x70,0x88,0x88,0x70,0x00,0x70,0x88,0x88,0x78,0x08,0x88,0x70,0x00, 0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x40,0x00, 0x10,0x20,0x40,0x80,0x40,0x20,0x10,0x00,0x00,0x00,0xF8,0x00,0xF8,0x00,0x00,0x00, 0x40,0x20,0x10,0x08,0x10,0x20,0x40,0x00,0x70,0x88,0x08,0x10,0x20,0x00,0x20,0x00, 0x30,0x48,0x88,0x98,0xA8,0xA8,0x78,0x00,0x20,0x50,0x50,0x88,0xF8,0x88,0x88,0x00, 0xF0,0x88,0x88,0xF0,0x88,0x88,0xF0,0x00,0x70,0x88,0x80,0x80,0x80,0x88,0x70,0x00, 0xF0,0x88,0x88,0x88,0x88,0x88,0xF0,0x00,0xF8,0x80,0x80,0xF0,0x80,0x80,0xF8,0x00, 0xF8,0x80,0x80,0xF0,0x80,0x80,0x80,0x00,0x70,0x88,0x80,0xB8,0x88,0x88,0x70,0x00, 0x88,0x88,0x88,0xF8,0x88,0x88,0x88,0x00,0xF8,0x20,0x20,0x20,0x20,0x20,0xF8,0x00, 0x38,0x08,0x08,0x08,0x08,0x88,0x70,0x00,0x88,0x88,0x90,0xE0,0x90,0x88,0x88,0x00, 0x80,0x80,0x80,0x80,0x80,0x80,0xF8,0x00,0x88,0xD8,0xA8,0xA8,0xA8,0xA8,0xA8,0x00, 0x88,0xC8,0xA8,0xA8,0xA8,0x98,0x88,0x00,0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x00, 0xF0,0x88,0x88,0xF0,0x80,0x80,0x80,0x00,0x70,0x88,0x88,0x88,0xA8,0x90,0x68,0x00, 0xF0,0x88,0x88,0xF0,0x88,0x88,0x88,0x00,0x70,0x88,0x80,0x70,0x08,0x88,0x70,0x00, 0xF8,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x88,0x88,0x88,0x88,0x88,0x88,0x70,0x00, 0x88,0x88,0x88,0x50,0x50,0x50,0x20,0x00,0x88,0xA8,0xA8,0xA8,0xA8,0xD8,0x88,0x00, 0x88,0x88,0x50,0x20,0x50,0x88,0x88,0x00,0x88,0x88,0x88,0x70,0x20,0x20,0x20,0x00, 0xF8,0x08,0x10,0x20,0x40,0x80,0xF8,0x00,0x70,0x40,0x40,0x40,0x40,0x40,0x70,0x00, 0x88,0x50,0xF8,0x20,0xF8,0x20,0x20,0x00,0x70,0x10,0x10,0x10,0x10,0x10,0x70,0x00, 0x20,0x50,0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x00, 0x80,0xC0,0xE0,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x70,0x08,0x78,0x88,0xF8,0x00, 0x80,0x80,0x80,0xF0,0x88,0x88,0xF0,0x00,0x00,0x00,0x78,0x80,0x80,0x80,0x78,0x00, 0x08,0x08,0x08,0x78,0x88,0x88,0x78,0x00,0x00,0x00,0x70,0x88,0xF8,0x80,0x78,0x00, 0x18,0x20,0xF8,0x20,0x20,0x20,0x20,0x00,0x00,0x00,0x78,0x88,0x78,0x08,0xF0,0x00, 0x80,0x80,0x80,0xF0,0x88,0x88,0x88,0x00,0x20,0x00,0x20,0x20,0x20,0x20,0x20,0x00, 0x20,0x00,0x20,0x20,0x20,0x20,0xC0,0x00,0x80,0x80,0x88,0x90,0xE0,0x90,0x88,0x00, 0x20,0x20,0x20,0x20,0x20,0x20,0x30,0x00,0x00,0x00,0xF0,0xA8,0xA8,0xA8,0xA8,0x00, 0x00,0x00,0xF0,0x88,0x88,0x88,0x88,0x00,0x00,0x00,0x70,0x88,0x88,0x88,0x70,0x00, 0x00,0x00,0xF0,0x88,0xF0,0x80,0x80,0x00,0x00,0x00,0x78,0x88,0x78,0x08,0x08,0x00, 0x00,0x00,0xB8,0xC0,0x80,0x80,0x80,0x00,0x00,0x00,0x78,0x80,0x70,0x08,0xF0,0x00, 0x20,0x20,0xF8,0x20,0x20,0x20,0x20,0x00,0x00,0x00,0x88,0x88,0x88,0x88,0x70,0x00, 0x00,0x00,0x88,0x88,0x50,0x50,0x20,0x00,0x00,0x00,0x88,0xA8,0xA8,0xD8,0x88,0x00, 0x00,0x00,0x88,0x50,0x20,0x50,0x88,0x00,0x00,0x00,0x88,0x88,0x78,0x08,0xF0,0x00, 0x00,0x00,0xF8,0x08,0x70,0x80,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, }; BYTE MapperNSF::KeyBoardBitmap[] = { 48, 26, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x10, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x0F, 0x10, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x10, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x0F, 0x10, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x0F, 0x10, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x10, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x0F, 0x10, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x10, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x0F, 0x10, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x0F, 0x10, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x10, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x0F, 0x10, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x10, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x0F, 0x10, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x0F, 0x10, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x0F, 0x10, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x0F, 0x10, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x0F, 0x10, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10, 0x0F, 0x10, 0x10, 0x10, 0x20, 0x20, 0x10, 0x0F, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10, 0x0F, 0x10, 0x10, 0x10, 0x20, 0x20, 0x10, 0x0F, 0x10, 0x10, 0x10, 0x20, 0x20, 0x10, 0x0F, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0F, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10, 0x20, 0x20, 0x20, 0x20, 0x10, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x20, 0x10, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x20, 0x10, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x20, 0x10, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x20, 0x10, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x20, 0x10, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0F, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0F, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0F, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0F, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0F, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0F, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0F, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0F, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0F, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0F, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0F, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0F, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0F, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0F, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0F, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0F, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0F, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0F, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, }; // KeyA(6x26) BYTE MapperNSF::KeyBitmapA[] = { 6, 26, 0x2A, 0x2A, 0x2A, 0x2A, 0xFF, 0xFF, 0x2A, 0x2A, 0x2A, 0x2A, 0xFF, 0xFF, 0x2A, 0x2A, 0x2A, 0x2A, 0xFF, 0xFF, 0x2A, 0x2A, 0x2A, 0x2A, 0xFF, 0xFF, 0x2A, 0x2A, 0x2A, 0x2A, 0xFF, 0xFF, 0x2A, 0x2A, 0x2A, 0x2A, 0xFF, 0xFF, 0x2A, 0x2A, 0x2A, 0x2A, 0xFF, 0xFF, 0x2A, 0x2A, 0x2A, 0x2A, 0xFF, 0xFF, 0x2A, 0x2A, 0x2A, 0x2A, 0xFF, 0xFF, 0x2A, 0x2A, 0x2A, 0x2A, 0xFF, 0xFF, 0x2A, 0x2A, 0x2A, 0x2A, 0xFF, 0xFF, 0x2A, 0x2A, 0x2A, 0x2A, 0xFF, 0xFF, 0x2A, 0x2A, 0x2A, 0x2A, 0xFF, 0xFF, 0x2A, 0x2A, 0x2A, 0x2A, 0xFF, 0xFF, 0x2A, 0x2A, 0x2A, 0x2A, 0xFF, 0xFF, 0x2A, 0x2A, 0x2A, 0x2A, 0xFF, 0xFF, 0x2A, 0x2A, 0x2A, 0x2A, 0x0F, 0x0F, 0x2A, 0x2A, 0x2A, 0x2A, 0x0F, 0x0F, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x1A, 0x2A, 0x2A, 0x2A, 0x2A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, }; // KeyB(6x26) BYTE MapperNSF::KeyBitmapB[] = { 6, 26, 0xFF, 0xFF, 0x1A, 0x2A, 0xFF, 0xFF, 0xFF, 0xFF, 0x1A, 0x2A, 0xFF, 0xFF, 0xFF, 0xFF, 0x1A, 0x2A, 0xFF, 0xFF, 0xFF, 0xFF, 0x1A, 0x2A, 0xFF, 0xFF, 0xFF, 0xFF, 0x1A, 0x2A, 0xFF, 0xFF, 0xFF, 0xFF, 0x1A, 0x2A, 0xFF, 0xFF, 0xFF, 0xFF, 0x1A, 0x2A, 0xFF, 0xFF, 0xFF, 0xFF, 0x1A, 0x2A, 0xFF, 0xFF, 0xFF, 0xFF, 0x1A, 0x2A, 0xFF, 0xFF, 0xFF, 0xFF, 0x1A, 0x2A, 0xFF, 0xFF, 0xFF, 0xFF, 0x1A, 0x2A, 0xFF, 0xFF, 0xFF, 0xFF, 0x1A, 0x2A, 0xFF, 0xFF, 0xFF, 0xFF, 0x1A, 0x2A, 0xFF, 0xFF, 0xFF, 0xFF, 0x1A, 0x2A, 0xFF, 0xFF, 0xFF, 0xFF, 0x1A, 0x2A, 0xFF, 0xFF, 0xFF, 0xFF, 0x1A, 0x2A, 0xFF, 0xFF, 0x0F, 0x0F, 0x1A, 0x2A, 0x0F, 0x0F, 0x0F, 0x0F, 0x2A, 0x2A, 0x0F, 0x0F, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x1A, 0x2A, 0x2A, 0x2A, 0x2A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, }; // KeyC(6x26) BYTE MapperNSF::KeyBitmapC[] = { 6, 26, 0xFF, 0xFF, 0x1A, 0x2A, 0x2A, 0x2A, 0xFF, 0xFF, 0x1A, 0x2A, 0x2A, 0x2A, 0xFF, 0xFF, 0x1A, 0x2A, 0x2A, 0x2A, 0xFF, 0xFF, 0x1A, 0x2A, 0x2A, 0x2A, 0xFF, 0xFF, 0x1A, 0x2A, 0x2A, 0x2A, 0xFF, 0xFF, 0x1A, 0x2A, 0x2A, 0x2A, 0xFF, 0xFF, 0x1A, 0x2A, 0x2A, 0x2A, 0xFF, 0xFF, 0x1A, 0x2A, 0x2A, 0x2A, 0xFF, 0xFF, 0x1A, 0x2A, 0x2A, 0x2A, 0xFF, 0xFF, 0x1A, 0x2A, 0x2A, 0x2A, 0xFF, 0xFF, 0x1A, 0x2A, 0x2A, 0x2A, 0xFF, 0xFF, 0x1A, 0x2A, 0x2A, 0x2A, 0xFF, 0xFF, 0x1A, 0x2A, 0x2A, 0x2A, 0xFF, 0xFF, 0x1A, 0x2A, 0x2A, 0x2A, 0xFF, 0xFF, 0x1A, 0x2A, 0x2A, 0x2A, 0xFF, 0xFF, 0x1A, 0x2A, 0x2A, 0x2A, 0x0F, 0x0F, 0x1A, 0x2A, 0x2A, 0x2A, 0x0F, 0x0F, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x1A, 0x2A, 0x2A, 0x2A, 0x2A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, }; // KeyD(5x16) BYTE MapperNSF::KeyBitmapD[] = { 5, 16, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x2A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x2A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x2A, 0x1A, 0x1A, 0x1A, 0x1A, 0x2A, 0x2A, 0x2A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, }; // ネオン管(のつもり) BYTE MapperNSF::NeonBitmapA[] = { 6, 26, 0xFF, 0x02, 0x12, 0x12, 0x02, 0xFF, 0x02, 0x12, 0x21, 0x21, 0x12, 0x02, 0x12, 0x21, 0x31, 0x31, 0x21, 0x12, 0x12, 0x21, 0x31, 0x31, 0x21, 0x12, 0x12, 0x21, 0x31, 0x31, 0x21, 0x12, 0x12, 0x21, 0x31, 0x31, 0x21, 0x12, 0x12, 0x21, 0x31, 0x31, 0x21, 0x12, 0x12, 0x21, 0x31, 0x31, 0x21, 0x12, 0x12, 0x21, 0x31, 0x31, 0x21, 0x12, 0x12, 0x21, 0x31, 0x31, 0x21, 0x12, 0x12, 0x21, 0x31, 0x31, 0x21, 0x12, 0x12, 0x21, 0x31, 0x31, 0x21, 0x12, 0x12, 0x21, 0x31, 0x31, 0x21, 0x12, 0x12, 0x21, 0x31, 0x31, 0x21, 0x12, 0x12, 0x21, 0x31, 0x31, 0x21, 0x12, 0x12, 0x21, 0x31, 0x31, 0x21, 0x12, 0x12, 0x21, 0x31, 0x31, 0x21, 0x12, 0x12, 0x21, 0x31, 0x31, 0x21, 0x12, 0x12, 0x21, 0x31, 0x31, 0x21, 0x12, 0x12, 0x21, 0x31, 0x31, 0x21, 0x12, 0x12, 0x21, 0x31, 0x31, 0x21, 0x12, 0x12, 0x21, 0x31, 0x31, 0x21, 0x12, 0x12, 0x21, 0x31, 0x31, 0x21, 0x12, 0x12, 0x21, 0x31, 0x31, 0x21, 0x12, 0x02, 0x12, 0x21, 0x21, 0x12, 0x02, 0xFF, 0x02, 0x12, 0x12, 0x02, 0xFF, }; BYTE MapperNSF::NeonBitmapB[] = { 6, 26, 0xFF, 0x09, 0x1A, 0x1A, 0x09, 0xFF, 0x09, 0x1A, 0x2A, 0x2A, 0x1A, 0x09, 0x1A, 0x2A, 0x3B, 0x3B, 0x2A, 0x1A, 0x1A, 0x2A, 0x3B, 0x3B, 0x2A, 0x1A, 0x1A, 0x2A, 0x3B, 0x3B, 0x2A, 0x1A, 0x1A, 0x2A, 0x3B, 0x3B, 0x2A, 0x1A, 0x1A, 0x2A, 0x3B, 0x3B, 0x2A, 0x1A, 0x1A, 0x2A, 0x3B, 0x3B, 0x2A, 0x1A, 0x1A, 0x2A, 0x3B, 0x3B, 0x2A, 0x1A, 0x1A, 0x2A, 0x3B, 0x3B, 0x2A, 0x1A, 0x1A, 0x2A, 0x3B, 0x3B, 0x2A, 0x1A, 0x1A, 0x2A, 0x3B, 0x3B, 0x2A, 0x1A, 0x1A, 0x2A, 0x3B, 0x3B, 0x2A, 0x1A, 0x1A, 0x2A, 0x3B, 0x3B, 0x2A, 0x1A, 0x1A, 0x2A, 0x3B, 0x3B, 0x2A, 0x1A, 0x1A, 0x2A, 0x3B, 0x3B, 0x2A, 0x1A, 0x1A, 0x2A, 0x3B, 0x3B, 0x2A, 0x1A, 0x1A, 0x2A, 0x3B, 0x3B, 0x2A, 0x1A, 0x1A, 0x2A, 0x3B, 0x3B, 0x2A, 0x1A, 0x1A, 0x2A, 0x3B, 0x3B, 0x2A, 0x1A, 0x1A, 0x2A, 0x3B, 0x3B, 0x2A, 0x1A, 0x1A, 0x2A, 0x3B, 0x3B, 0x2A, 0x1A, 0x1A, 0x2A, 0x3B, 0x3B, 0x2A, 0x1A, 0x1A, 0x2A, 0x3B, 0x3B, 0x2A, 0x1A, 0x09, 0x1A, 0x2A, 0x2A, 0x1A, 0x09, 0xFF, 0x09, 0x1A, 0x1A, 0x09, 0xFF, }; BYTE MapperNSF::NeonBitmapC[] = { 6, 26, 0xFF, 0x1E, 0x1D, 0x1D, 0x1E, 0xFF, 0x1E, 0x1D, 0x2D, 0x2D, 0x1D, 0x1E, 0x1D, 0x2D, 0x00, 0x00, 0x2D, 0x1D, 0x1D, 0x2D, 0x00, 0x00, 0x2D, 0x1D, 0x1D, 0x2D, 0x00, 0x00, 0x2D, 0x1D, 0x1D, 0x2D, 0x00, 0x00, 0x2D, 0x1D, 0x1D, 0x2D, 0x00, 0x00, 0x2D, 0x1D, 0x1D, 0x2D, 0x00, 0x00, 0x2D, 0x1D, 0x1D, 0x2D, 0x00, 0x00, 0x2D, 0x1D, 0x1D, 0x2D, 0x00, 0x00, 0x2D, 0x1D, 0x1D, 0x2D, 0x00, 0x00, 0x2D, 0x1D, 0x1D, 0x2D, 0x00, 0x00, 0x2D, 0x1D, 0x1D, 0x2D, 0x00, 0x00, 0x2D, 0x1D, 0x1D, 0x2D, 0x00, 0x00, 0x2D, 0x1D, 0x1D, 0x2D, 0x00, 0x00, 0x2D, 0x1D, 0x1D, 0x2D, 0x00, 0x00, 0x2D, 0x1D, 0x1D, 0x2D, 0x00, 0x00, 0x2D, 0x1D, 0x1D, 0x2D, 0x00, 0x00, 0x2D, 0x1D, 0x1D, 0x2D, 0x00, 0x00, 0x2D, 0x1D, 0x1D, 0x2D, 0x00, 0x00, 0x2D, 0x1D, 0x1D, 0x2D, 0x00, 0x00, 0x2D, 0x1D, 0x1D, 0x2D, 0x00, 0x00, 0x2D, 0x1D, 0x1D, 0x2D, 0x00, 0x00, 0x2D, 0x1D, 0x1D, 0x2D, 0x00, 0x00, 0x2D, 0x1D, 0x1E, 0x1D, 0x2D, 0x2D, 0x1D, 0x1E, 0xFF, 0x1E, 0x1D, 0x1D, 0x1E, 0xFF, }; INT MapperNSF::KeyBitmapOfs[] = { 0, 4, 7, 11, 14, 21, 25, 28, 32, 35, 39, 42, }; LPBYTE MapperNSF::KeyBitmapTbl[] = { MapperNSF::KeyBitmapA, MapperNSF::KeyBitmapD, MapperNSF::KeyBitmapB, MapperNSF::KeyBitmapD, MapperNSF::KeyBitmapC, MapperNSF::KeyBitmapA, MapperNSF::KeyBitmapD, MapperNSF::KeyBitmapB, MapperNSF::KeyBitmapD, MapperNSF::KeyBitmapB, MapperNSF::KeyBitmapD, MapperNSF::KeyBitmapC, }; BYTE MapperNSF::StarBitmapA[] = { 5, 5, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x2D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }; BYTE MapperNSF::StarBitmapB[] = { 5, 5, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1D, 0xFF, 0xFF, 0xFF, 0x1D, 0x2D, 0x1D, 0xFF, 0xFF, 0xFF, 0x1D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }; BYTE MapperNSF::StarBitmapC[] = { 5, 5, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x2D, 0xFF, 0xFF, 0xFF, 0x2D, 0x10, 0x2D, 0xFF, 0xFF, 0xFF, 0x2D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }; BYTE MapperNSF::StarBitmapD[] = { 5, 5, 0xFF, 0xFF, 0x2D, 0xFF, 0xFF, 0xFF, 0x2D, 0x10, 0x2D, 0xFF, 0x2D, 0x10, 0x20, 0x10, 0x2D, 0xFF, 0x2D, 0x10, 0x2D, 0xFF, 0xFF, 0xFF, 0x2D, 0xFF, 0xFF, }; LPBYTE MapperNSF::StarBitmapTbl[] = { MapperNSF::StarBitmapA, MapperNSF::StarBitmapB, MapperNSF::StarBitmapC, MapperNSF::StarBitmapD, }; void MapperNSF::Reset() { INT i; songno = 0; pad = padold = 0; repcnt = 0; BGPAL[0] = BGPAL[1] = BGPAL[2] = BGPAL[3] = SPPAL[0] = SPPAL[1] = SPPAL[2] = SPPAL[3] = 0x0F; exaddr = 0; ZEROMEMORY( exram, sizeof(exram) ); SetPROM_Bank( 2, WRAM+0xA000, BANKTYPE_RAM ); // 4000-5FFF SetPROM_Bank( 3, WRAM+0x0000, BANKTYPE_RAM ); // 6000-7FFF SetPROM_Bank( 4, WRAM+0x2000, BANKTYPE_RAM ); // 8000-9FFF SetPROM_Bank( 5, WRAM+0x4000, BANKTYPE_RAM ); // A000-BFFF SetPROM_Bank( 6, WRAM+0x6000, BANKTYPE_RAM ); // C000-DFFF SetPROM_Bank( 7, WRAM+0x8000, BANKTYPE_RAM ); // E000-FFFF nsfheader = *(nes->rom->GetNsfHeader()); exchip = nsfheader.ExtraChipSelect; banksize = nes->rom->GetNSF_SIZE(); if( (songno = nsfheader.StartSong-1) >= nsfheader.TotalSong ) { songno = 0; } bankswitch = 0; for( i = 0; i < 8; i++ ) { bankswitch |= nsfheader.BankSwitch[i]; } if( bankswitch ) { // Bankswitch on BYTE start_bank = nsfheader.LoadAddress>>12; for( i = 0; (start_bank+i) < 8; i++ ) { BankSwitch( start_bank+i, i ); } for( i = 0; i < 8; i++ ) { BankSwitch( i+8, nsfheader.BankSwitch[i] ); } if( exchip&0x04 ) { //FDS BankSwitch( 6, nsfheader.BankSwitch[6] ); BankSwitch( 7, nsfheader.BankSwitch[7] ); } } else { // Bankswitch off LPBYTE pPtr = nes->rom->GetPROM(); if( banksize < 8 ) { for( i = 0; i < 0x1000*banksize; i++ ) { if( nsfheader.LoadAddress-0x8000+i < 0x8000 ) { WRAM[0x2000+nsfheader.LoadAddress-0x8000+i] = pPtr[i]; } } } else { for( i = 0; i < 0x8000; i++ ) { if( nsfheader.LoadAddress-0x8000+i < 0x8000 ) { WRAM[0x2000+nsfheader.LoadAddress-0x8000+i] = pPtr[i]; } } } } // $4700は待機無限ループ WRAM[0xA700] = 0x4c; //jmp WRAM[0xA701] = 0x00; WRAM[0xA702] = 0x47; // $4710はInitルーチンを呼んだ後無限ループへ WRAM[0xA710] = 0x20; // jsr WRAM[0xA711] = (BYTE) nsfheader.InitAddress & 0xFF; WRAM[0xA712] = (BYTE)(nsfheader.InitAddress>>8); WRAM[0xA713] = 0x4c; // jmp WRAM[0xA714] = 0x00; WRAM[0xA715] = 0x47; // $4720はPlayルーチンを呼んだ後無限ループへ #if NSF_PROFILE WRAM[0xA720] = 0x8D; // sta WRAM[0xA721] = 0x1E; // $401E WRAM[0xA722] = 0x40; // $401E WRAM[0xA723] = 0x20; // jsr WRAM[0xA724] = (BYTE) nsfheader.PlayAddress; WRAM[0xA725] = (BYTE)(nsfheader.PlayAddress>>8); WRAM[0xA726] = 0x8D; // sta WRAM[0xA727] = 0x1F; // $401F WRAM[0xA728] = 0x40; // $401F WRAM[0xA729] = 0x4c; //jmp WRAM[0xA72A] = 0x00; WRAM[0xA72B] = 0x47; #else WRAM[0xA720] = 0x20; // jsr WRAM[0xA721] = (BYTE) nsfheader.PlayAddress; WRAM[0xA722] = (BYTE)(nsfheader.PlayAddress>>8); WRAM[0xA723] = 0x4c; //jmp WRAM[0xA724] = 0x00; WRAM[0xA725] = 0x47; #endif nes->apu->SelectExSound( exchip ); nes->apu->Write( 0x4015, 0x1F ); nes->apu->ExWrite( 0x4080, 0x80 ); // FDS Volume 0 nes->apu->ExWrite( 0x408A, 0xE8 ); // FDS Envelope ON // For DQ1/2?? nes->SetFrameIRQmode( FALSE ); // NTSC/PAL tune nes->SetVideoMode( (nsfheader.NTSC_PALbits&0x01) ); // 周波数->Keyテーブルの作成 for( i = 0; i < 12*8+1; i++ ) { Freq2KeyTbl[i] = (INT)(440.0*256.0*pow(2.0,((double)(i-45)-0.5)/12.0)); } // おまけ StarInitial(); // #if NSF_PROFILE avecount = 0; tave = 0.0f; pave = 0.0f; ptave = 0.0f; maxtotalclk = 0; maxprofclk = 0; maxproftotalclk = 0; maxproftotalcnt = 0; #endif } BYTE MapperNSF::ExRead( WORD addr ) { BYTE data = 0; if( addr >= 0x4040 && addr < 0x4100 ) { data = nes->apu->ExRead( addr ); } return data; } void MapperNSF::ExWrite( WORD addr, BYTE data ) { if( addr >= 0x4040 && addr < 0x4100 ) { nes->apu->ExWrite( addr, data ); } } BYTE MapperNSF::ReadLow( WORD addr ) { if( addr == 0x4800 ) { BYTE data = exram[exaddr&0x7F]; if( exaddr&0x80 ) exaddr = (exaddr+1)|0x80; nes->apu->ExRead( addr ); return data; } else if( addr == 0x5205 ) { // MMC5 return (BYTE)multipul[0]*multipul[1]; } else if( addr == 0x5206 ) { // MMC5 return (BYTE)(((WORD)multipul[0]*(WORD)multipul[1])>>8); } if (addr >= 0x4700 && addr < 0x4730) { //NSF player opcode メカキ return CPU_MEM_BANK[addr >> 13][addr & 0x1FFF]; } // if( addr >= 0x47A0 && addr < 0x4800 ) { // return WRAM[addr+0x6000]; // } if( addr >= 0x5C00 && addr < 0x5FFF ) { // MMC5 return DRAM[addr-0x5C00]; } if( addr >= 0x6000 ) { return WRAM[addr-0x6000]; } return (BYTE)(addr>>8); } void MapperNSF::WriteLow( WORD addr, BYTE data ) { if( addr == 0x4800 || (addr >= 0x5000 && addr <= 0x5015) ) { //DEBUGOUT( "$4800 WR=%02X\n", data ); exram[exaddr&0x7F] = data; if( exaddr&0x80 ) exaddr = (exaddr+1)|0x80; nes->apu->ExWrite( addr, data ); } else if( addr == 0x5205 ) { // MMC5 multipul[0] = data; } else if( addr == 0x5206 ) { // MMC5 multipul[1] = data; } else if( addr >= 0x5C00 && addr < 0x5FF6 ) { // MMC5 DRAM[addr-0x5C00] = data; } // if( addr >= 0x47A0 && addr < 0x4800 ) { // WRAM[addr+0x6000] = data; // } if( addr >= 0x5FF6 && addr <= 0x5FFF ) { // Bank switch BankSwitch( addr&0x0F, data ); } if( addr >= 0x6000 ) { WRAM[addr-0x6000] = data; nes->apu->ExWrite( addr, data ); } } void MapperNSF::Write( WORD addr, BYTE data ) { if( (exchip&0x04) ) { //FDS WRAM[addr-0x6000] = data; } nes->apu->ExWrite( addr, data ); if( addr == 0xF800 ) { exaddr = data; } } void MapperNSF::BankSwitch( INT no, BYTE bank ) { INT i; INT addr, offs; LPBYTE pPtr; offs = 0x1000*(INT)bank-(INT)(nsfheader.LoadAddress&0x0FFF); pPtr = nes->rom->GetPROM(); if( no == 6 || no == 7 ) { for( i = 0; i < 0x1000; i++ ) { //4K size addr = offs+i; if( addr < 0 || addr > (4096*banksize)-1 ) { WRAM[0x1000*(no&1)+i] = 0; } else { WRAM[0x1000*(no&1)+i] = pPtr[addr]; } } } else if( no >= 8 && no <= 15 ) { for( i = 0; i < 0x1000; i++ ) { //4K size addr = offs+i; if( addr < 0 || addr > (4096*banksize)-1 ) { WRAM[0x2000+0x1000*(no&7)+i] = 0; } else { WRAM[0x2000+0x1000*(no&7)+i] = pPtr[addr]; } } } } void MapperNSF::VSync() { // データ設定 padold = pad; pad = nes->pad->GetNsfController(); BYTE padpush = ~padold & pad; if( padpush ) { repcnt = 20; } else if( pad ) { if( --repcnt == 0 ) { repcnt = 8; padpush |= pad & 0xFC; } } // -1 if( padpush & (1<<2) ) { if( --songno < 0 ) { songno = nsfheader.TotalSong-1; } } // +1 if( padpush & (1<<3) ) { if( ++songno >= nsfheader.TotalSong ) { songno = 0; } } // -16 if( padpush & (1<<4) ) { if( (songno-=16) < 0 ) { while( songno < 0 ) { songno += nsfheader.TotalSong; } songno %= nsfheader.TotalSong; } } // +16 if( padpush & (1<<5) ) { if( (songno+=16) >= nsfheader.TotalSong ) { songno -= nsfheader.TotalSong; songno %= nsfheader.TotalSong; } } // Play if( padpush & (1<<0) ) { nes->SetNsfPlay( songno, 0 ); } // Stop if( padpush & (1<<1) ) { nes->SetNsfStop(); } // おまけ Star(); // Drawing screen // DrawString( 10, 16, "TITLE :", 0x30 ); // DrawString( 10, 31, "ARTIST:", 0x30 ); // DrawString( 10, 46, "(C) :", 0x30 ); // DrawString( 10, 61, "NO :", 0x30 ); DrawString( 10, 16, "Title :", 0x30 ); DrawString( 10, 31, "Artist:", 0x30 ); DrawString( 10, 46, "(C) :", 0x30 ); DrawString( 10, 61, "No :", 0x30 ); DrawString( 28, 76, "Keyboard", 0x30 ); DrawString( 32, 152, "Wave View", 0x30 ); // タイトルなど CHAR str[64]; memcpy( str, nsfheader.SongName, 32 ); str[32] = 0; DrawString( 53, 16, str, 0x30 ); memcpy( str, nsfheader.ArtistName, 32 ); str[32] = 0; DrawString( 53, 31, str, 0x30 ); memcpy( str, nsfheader.CopyrightName, 32 ); str[32] = 0; DrawString( 53, 46, str, 0x30 ); // Song no sprintf( str, "%02X", songno ); DrawString( 53, 61, str, 0x30 ); // Extra sound DrawString( 76+6* 0, 61, "VRC6", (exchip&0x01)?0x2B:0x2D ); DrawString( 76+6* 5, 61, "VRC7", (exchip&0x02)?0x2B:0x2D ); DrawString( 76+6*10, 61, "FDS", (exchip&0x04)?0x2B:0x2D ); DrawString( 76+6*14, 61, "MMC5", (exchip&0x08)?0x2B:0x2D ); DrawString( 76+6*19, 61, "N106", (exchip&0x10)?0x2B:0x2D ); DrawString( 76+6*24, 61, "FME7", (exchip&0x20)?0x2B:0x2D ); // タイトルなどのライン DrawRect( 52, 24, 243-52, 0, 0x30 ); DrawRect( 52, 39, 243-52, 0, 0x30 ); DrawRect( 52, 54, 243-52, 0, 0x30 ); DrawRect( 52, 69, 12, 0, 0x30 ); DrawRect( 75, 69, 243-75, 0, 0x30 ); // キーボード枠 DrawRect( 27, 84, 229-27, 148- 84, 0x30 ); // WAVEVIEW枠 #if !NSF_PROFILE DrawRect( 31, 160, 224-31, 224-160, 0x30 ); DrawRect( 32, 192, 223-32, 0, 0x27 ); // Wave DrawWave( 28+4, 192, 0x2A ); #endif // キーボード上段(O5-O8) DrawBitmap( 31+49*0, 88, KeyBoardBitmap ); DrawBitmap( 31+49*1, 88, KeyBoardBitmap ); DrawBitmap( 31+49*2, 88, KeyBoardBitmap ); DrawBitmap( 31+49*3, 88, KeyBoardBitmap ); // キーボード下段(O1-O4) DrawBitmap( 31+49*0, 119, KeyBoardBitmap ); DrawBitmap( 31+49*1, 119, KeyBoardBitmap ); DrawBitmap( 31+49*2, 119, KeyBoardBitmap ); DrawBitmap( 31+49*3, 119, KeyBoardBitmap ); // キーボードが押されているのを描画 // Internal APU DrawKey( GetKeyTable(nes->apu->GetChannelFrequency(0x0000)) ); DrawKey( GetKeyTable(nes->apu->GetChannelFrequency(0x0001)) ); DrawKey( GetKeyTable(nes->apu->GetChannelFrequency(0x0002)) ); // Internal Noise if( nes->apu->GetChannelFrequency(0x0003) ) { DrawBitmap( 10, 88, NeonBitmapA ); DrawBitmap( 241, 88, NeonBitmapA ); DrawBitmap( 10, 119, NeonBitmapA ); DrawBitmap( 241, 119, NeonBitmapA ); } else { DrawBitmap( 10, 88, NeonBitmapC ); DrawBitmap( 241, 88, NeonBitmapC ); DrawBitmap( 10, 119, NeonBitmapC ); DrawBitmap( 241, 119, NeonBitmapC ); } // Internal DPCM if( nes->apu->GetChannelFrequency(0x0004) ) { DrawBitmap( 18, 88, NeonBitmapB ); DrawBitmap( 233, 88, NeonBitmapB ); DrawBitmap( 18, 119, NeonBitmapB ); DrawBitmap( 233, 119, NeonBitmapB ); } else { DrawBitmap( 18, 88, NeonBitmapC ); DrawBitmap( 233, 88, NeonBitmapC ); DrawBitmap( 18, 119, NeonBitmapC ); DrawBitmap( 233, 119, NeonBitmapC ); } // VRC6 DrawKey( GetKeyTable(nes->apu->GetChannelFrequency(0x0100)) ); DrawKey( GetKeyTable(nes->apu->GetChannelFrequency(0x0101)) ); DrawKey( GetKeyTable(nes->apu->GetChannelFrequency(0x0102)) ); // VRC7 // Nothing... // FDS DrawKey( GetKeyTable(nes->apu->GetChannelFrequency(0x0300)) ); // MMC5 DrawKey( GetKeyTable(nes->apu->GetChannelFrequency(0x0400)) ); DrawKey( GetKeyTable(nes->apu->GetChannelFrequency(0x0401)) ); // N106 DrawKey( GetKeyTable(nes->apu->GetChannelFrequency(0x0500)) ); DrawKey( GetKeyTable(nes->apu->GetChannelFrequency(0x0501)) ); DrawKey( GetKeyTable(nes->apu->GetChannelFrequency(0x0502)) ); DrawKey( GetKeyTable(nes->apu->GetChannelFrequency(0x0503)) ); DrawKey( GetKeyTable(nes->apu->GetChannelFrequency(0x0504)) ); DrawKey( GetKeyTable(nes->apu->GetChannelFrequency(0x0505)) ); DrawKey( GetKeyTable(nes->apu->GetChannelFrequency(0x0506)) ); DrawKey( GetKeyTable(nes->apu->GetChannelFrequency(0x0507)) ); // FME7 DrawKey( GetKeyTable(nes->apu->GetChannelFrequency(0x0600)) ); DrawKey( GetKeyTable(nes->apu->GetChannelFrequency(0x0601)) ); DrawKey( GetKeyTable(nes->apu->GetChannelFrequency(0x0602)) ); DrawKey( GetKeyTable(nes->apu->GetChannelFrequency(0x0610)) ); // Noise DrawKey( GetKeyTable(nes->apu->GetChannelFrequency(0x0611)) ); // Noise DrawKey( GetKeyTable(nes->apu->GetChannelFrequency(0x0612)) ); // Noise // VRC7 DrawKey( GetKeyTable(nes->apu->GetChannelFrequency(0x0700)) ); DrawKey( GetKeyTable(nes->apu->GetChannelFrequency(0x0701)) ); DrawKey( GetKeyTable(nes->apu->GetChannelFrequency(0x0702)) ); DrawKey( GetKeyTable(nes->apu->GetChannelFrequency(0x0703)) ); DrawKey( GetKeyTable(nes->apu->GetChannelFrequency(0x0704)) ); DrawKey( GetKeyTable(nes->apu->GetChannelFrequency(0x0705)) ); DrawKey( GetKeyTable(nes->apu->GetChannelFrequency(0x0706)) ); DrawKey( GetKeyTable(nes->apu->GetChannelFrequency(0x0707)) ); DrawKey( GetKeyTable(nes->apu->GetChannelFrequency(0x0708)) ); // TEST #if NSF_PROFILE if( nes->IsNsfPlaying() ) { DWORD total, profile; total = nes->GetFrameTotalCycles(); profile = nes->GetProfileCycles(); if( maxtotalclk < total ) { maxtotalclk = total; } if( maxprofclk < profile ) { maxprofclk = profile; } if( maxproftotalclk < nes->GetProfileTotalCycles() ) { maxproftotalclk = nes->GetProfileTotalCycles(); } if( maxproftotalcnt < nes->GetProfileTotalCount() ) { maxproftotalcnt = nes->GetProfileTotalCount(); } tave += total; pave += profile; ptave += nes->GetProfileTotalCycles(); avecount++; sprintf( str, "TOTAL CLK :%8d", total ); DrawString( 16, 160, str, 0x30 ); sprintf( str, "TOTAL MAX :%8d", maxtotalclk ); DrawString( 134, 160, str, 0x30 ); sprintf( str, "TOTAL AVE :%8.2f", tave / (float)avecount ); DrawString( 16, 168, str, 0x30 ); sprintf( str, "PROFILE :%8d", profile ); DrawString( 16, 176, str, 0x30 ); sprintf( str, "PROFILEMAX:%8d", maxprofclk ); DrawString( 134, 176, str, 0x30 ); sprintf( str, "POFILE AVE:%8.2f", pave / (float)avecount ); DrawString( 16, 184, str, 0x30 ); sprintf( str, "PRF/TTL %%:%8.2f", 100.0f * (float)profile / (float)total ); DrawString( 16, 192, str, 0x30 ); sprintf( str, "FRM-P TTL :%8d", nes->GetProfileTotalCycles() ); DrawString( 16, 200, str, 0x30 ); sprintf( str, "F-P TTLMAX:%8d", maxproftotalclk ); DrawString( 134, 200, str, 0x30 ); sprintf( str, "FRM-P CNT :%8d", nes->GetProfileTotalCount() ); DrawString( 16, 208, str, 0x30 ); sprintf( str, "F-P CNTMAX:%8d", maxproftotalcnt ); DrawString( 134, 208, str, 0x30 ); sprintf( str, "F P/T AVE :%8.2f", ptave / (float)avecount ); DrawString( 16, 216, str, 0x30 ); sprintf( str, "F PRF/TTL%%:%8.2f", 100.0f * (float)nes->GetProfileTotalCycles() / (float)total ); DrawString( 16, 224, str, 0x30 ); if( avecount >= 60 ) { avecount = 0; tave = 0.0f; pave = 0.0f; ptave = 0.0f; maxtotalclk = 0; maxprofclk = 0; maxproftotalclk = 0; maxproftotalcnt = 0; } } #endif } INT MapperNSF::GetKeyTable( INT freq ) { INT ret = -1; if( freq < Freq2KeyTbl[0] ) return -1; for( INT i = 0; i < 12*8+1; i++ ) { if( freq < Freq2KeyTbl[i] ) return ret; ret = i; } return -1; } void MapperNSF::DrawKey( INT key ) { if( key < 0 || key > 12*8-1 ) return; if( key < 12*4 ) { DrawBitmap( 31+(key/12)*49+KeyBitmapOfs[key%12], 119, KeyBitmapTbl[key%12] ); } else { DrawBitmap( 31+((key-12*4)/12)*49+KeyBitmapOfs[key%12], 88, KeyBitmapTbl[key%12] ); } } void MapperNSF::DrawRect( INT x, INT y, INT w, INT h, BYTE col ) { INT i; LPBYTE pScn = nes->ppu->GetScreenPtr()+8; LPBYTE p0, p1; p0 = pScn+(256+16)*y+x; p1 = p0+(256+16)*h; for( i = 0; i < w+1; i++ ) { *p0++ = col; *p1++ = col; } p0 = pScn+(256+16)*y+x; p1 = p0+w; for( i = 0; i < h+1; i++ ) { *p0 = col; *p1 = col; p0 += (256+16); p1 += (256+16); } } void MapperNSF::DrawFont( INT x, INT y, BYTE chr, BYTE col ) { INT i; LPBYTE pFnt; LPBYTE pPtr; LPBYTE pScn = nes->ppu->GetScreenPtr()+8; if( chr < 0x20 || chr > 0x7F ) return; chr -= 0x20; pFnt = &Font6x8[chr*8]; pPtr = pScn+(256+16)*y+x; for( i = 0; i < 8; i++ ) { if( pFnt[i] & 0x80 ) pPtr[0] = col; if( pFnt[i] & 0x40 ) pPtr[1] = col; if( pFnt[i] & 0x20 ) pPtr[2] = col; if( pFnt[i] & 0x10 ) pPtr[3] = col; if( pFnt[i] & 0x08 ) pPtr[4] = col; if( pFnt[i] & 0x04 ) pPtr[5] = col; pPtr += (256+16); } } void MapperNSF::DrawString( INT x, INT y, LPSTR str, BYTE col ) { while( *str ) { DrawFont( x, y, *str, col ); str++; x += 6; } } void MapperNSF::DrawWave( INT x, INT y, INT col ) { INT i, j; INT yp, ypold; LPBYTE pScn = nes->ppu->GetScreenPtr()+8+(256+16)*y+x; LPBYTE pPtr; ypold = 0; LPSWORD pBuffer = (LPSWORD)nes->apu->GetSoundBuffer(); for( i = 0; i < 192; i++ ) { yp = -((INT)*pBuffer)/1024; if( yp < -31 ) yp = -31; if( yp > 31 ) yp = 31; if( abs( yp-ypold ) <= 1 || i == 0 ) { pPtr = pScn+yp*(256+16)+i; *pPtr = col; } else { // Line DDA INT xpos, ypos; INT sx, sy; xpos = 65536*(i-1)+32768; ypos = ypold; sy = yp-ypold; sx = 65536/abs(sy); for( j = 0; j <= abs(sy); j++ ) { pPtr = pScn+ypos*(256+16)+(xpos/65536); *pPtr = col; ypos += (sy>0)?1:-1; xpos += sx; } } ypold = yp; pBuffer++; } } void MapperNSF::DrawBitmap( INT x, INT y, LPBYTE lpBitmap ) { INT i, j; INT h, v; LPBYTE pScn = nes->ppu->GetScreenPtr()+8+(256+16)*y+x; LPBYTE pPtr; h = (INT)*lpBitmap++; v = (INT)*lpBitmap++; for( j = 0; j < v; j++ ) { pPtr = pScn; for( i = 0; i < h; i++ ) { if( *lpBitmap != 0xFF ) { *pPtr = *lpBitmap; } lpBitmap++; pPtr++; } pScn += 256+16; } } void MapperNSF::StarInitial() { for( INT i = 0; i < STAR_MAX; i++ ) { StarBuf[i].x = ((rand()%(256-10))-(256-10)/2)*256; StarBuf[i].y = ((rand()%(240-10))-(240-10)/2)*256; StarBuf[i].z = (rand()%250)+5; } } void MapperNSF::Star() { INT x, y, z; for( INT i = 0; i < STAR_MAX; i++ ) { if( --StarBuf[i].z < 5 ) { StarBuf[i].x = ((rand()%(256-10))-(256-10)/2)*256; StarBuf[i].y = ((rand()%(240-10))-(240-10)/2)*256; StarBuf[i].z = 255; } x = 256/2+(StarBuf[i].x-5/128)/StarBuf[i].z; y = 240/2+(StarBuf[i].y-5/128)/StarBuf[i].z; if( x < 3 || x >= 256-8 || y < 3 || y >= 240-8 ) { StarBuf[i].x = ((rand()%(256-10))-(256-10)/2)*256; StarBuf[i].y = ((rand()%(240-10))-(240-10)/2)*256; StarBuf[i].z = 255; continue; } if( StarBuf[i].z > 200 ) z = 0; else if( StarBuf[i].z > 100 ) z = 1; else if( StarBuf[i].z > 50 ) z = 2; else z = 3; DrawBitmap( x, y, StarBitmapTbl[z] ); } }