libsidplayfp 1.0.3
|
00001 /* 00002 * This file is part of libsidplayfp, a SID player engine. 00003 * 00004 * Copyright 2012-2013 Leandro Nini <drfiemost@users.sourceforge.net> 00005 * Copyright 2010 Antti Lankila 00006 * 00007 * This program is free software; you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation; either version 2 of the License, or 00010 * (at your option) any later version. 00011 * 00012 * This program is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with this program; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00020 */ 00021 00022 #ifndef SYSTEMROMBANKS_H 00023 #define SYSTEMROMBANKS_H 00024 00025 #include <string.h> 00026 #include <stdint.h> 00027 00028 #include "Bank.h" 00029 #include "sidplayfp/c64/CPU/opcodes.h" 00030 00035 template <int N> 00036 class romBank : public Bank 00037 { 00038 protected: 00040 uint8_t rom[N]; 00041 00042 protected: 00044 void setVal(uint_least16_t address, uint8_t val) { rom[address & (N-1)]=val; } 00045 00047 uint8_t getVal(uint_least16_t address) const { return rom[address & (N-1)]; } 00048 00050 void* getPtr(uint_least16_t address) const { return (void*)&rom[address & (N-1)]; } 00051 00052 public: 00054 void set(const uint8_t* source) { if (source) memcpy(rom, source, N); } 00055 00057 void poke(uint_least16_t address SID_UNUSED, uint8_t value SID_UNUSED) {} 00058 00059 uint8_t peek(uint_least16_t address) { return rom[address & (N-1)]; } 00060 }; 00061 00065 class KernalRomBank : public romBank<0x2000> 00066 { 00067 private: 00068 uint8_t resetVectorLo; // 0xfffc 00069 uint8_t resetVectorHi; // 0xfffd 00070 00071 public: 00072 void set(const uint8_t* kernal) 00073 { 00074 romBank<0x2000>::set(kernal); 00075 00076 if (kernal) 00077 { 00078 // Apply Kernal hacks 00079 setVal(0xfd69, 0x9f); // Bypass memory check 00080 setVal(0xe55f, 0x00); // Bypass screen clear 00081 setVal(0xfdc4, 0xea); // Ignore sid volume reset to avoid DC 00082 setVal(0xfdc5, 0xea); // click (potentially incompatibility)!! 00083 setVal(0xfdc6, 0xea); 00084 } 00085 else 00086 { 00087 // Normal IRQ interrupt 00088 setVal(0xea31, LDAa); // Ack IRQs 00089 setVal(0xea32, 0x0D); 00090 setVal(0xea33, 0xDC); 00091 setVal(0xea34, PLAn); // Restore regs 00092 setVal(0xea35, TAYn); 00093 setVal(0xea36, PLAn); 00094 setVal(0xea37, TAXn); 00095 setVal(0xea38, PLAn); 00096 setVal(0xea39, RTIn); // Return 00097 00098 // Hardware setup routine 00099 setVal(0xff84, LDAa); // Set CIA 1 Timer A 00100 setVal(0xff85, 0xa6); 00101 setVal(0xff86, 0x02); 00102 setVal(0xff87, BEQr); 00103 setVal(0xff88, 0x06); 00104 setVal(0xff89, LDAb); // PAL 00105 setVal(0xff8a, 0x25); 00106 setVal(0xff8b, LDXb); 00107 setVal(0xff8c, 0x40); 00108 setVal(0xff8d, BNEr); 00109 setVal(0xff8e, 0x04); 00110 setVal(0xff8f, LDAb); // NTSC 00111 setVal(0xff90, 0x95); 00112 setVal(0xff91, LDXb); 00113 setVal(0xff92, 0x42); 00114 setVal(0xff93, STAa); 00115 setVal(0xff94, 0x04); 00116 setVal(0xff95, 0xdc); 00117 setVal(0xff96, STXa); 00118 setVal(0xff97, 0x05); 00119 setVal(0xff98, 0xdc); 00120 setVal(0xff99, LDAb); // Set SID to maximum volume 00121 setVal(0xff9a, 0x0f); 00122 setVal(0xff9b, STAa); 00123 setVal(0xff9c, 0x18); 00124 setVal(0xff9d, 0xd4); 00125 setVal(0xff9e, RTSn); 00126 00127 // IRQ entry point 00128 setVal(0xffa0, PHAn); // Save regs 00129 setVal(0xffa1, TXAn); 00130 setVal(0xffa2, PHAn); 00131 setVal(0xffa3, TYAn); 00132 setVal(0xffa4, PHAn); 00133 setVal(0xffa5, JMPi); // Jump to IRQ routine 00134 setVal(0xffa6, 0x14); 00135 setVal(0xffa7, 0x03); 00136 00137 // Hardware vectors 00138 setVal(0xfffa, 0x39); // NMI vector 00139 setVal(0xfffb, 0xea); 00140 setVal(0xfffc, 0x39); // RESET vector 00141 setVal(0xfffd, 0xea); 00142 setVal(0xfffe, 0xa0); // IRQ/BRK vector 00143 setVal(0xffff, 0xff); 00144 } 00145 00146 // Backup Reset Vector 00147 resetVectorLo = getVal(0xfffc); 00148 resetVectorHi = getVal(0xfffd); 00149 } 00150 00151 void reset() 00152 { 00153 // Restore original Reset Vector 00154 setVal(0xfffc, resetVectorLo); 00155 setVal(0xfffd, resetVectorHi); 00156 } 00157 00163 void installResetHook(uint_least16_t addr) 00164 { 00165 setVal(0xfffc, endian_16lo8(addr)); 00166 setVal(0xfffd, endian_16hi8(addr)); 00167 } 00168 }; 00169 00173 class BasicRomBank : public romBank<0x2000> 00174 { 00175 private: 00176 uint8_t trap[3]; 00177 uint8_t subTune[11]; 00178 00179 public: 00180 void set(const uint8_t* basic) 00181 { 00182 romBank<0x2000>::set(basic); 00183 00184 // Backup BASIC Warm Start 00185 memcpy(trap, getPtr(0xa7ae), 3); 00186 00187 memcpy(subTune, getPtr(0xbf53), 11); 00188 } 00189 00190 void reset() 00191 { 00192 // Restore original BASIC Warm Start 00193 memcpy(getPtr(0xa7ae), trap, 3); 00194 00195 memcpy(getPtr(0xbf53), subTune, 11); 00196 } 00197 00203 void installTrap(uint_least16_t addr) 00204 { 00205 setVal(0xa7ae, JMPw); 00206 setVal(0xa7af, endian_16lo8(addr)); 00207 setVal(0xa7b0, endian_16hi8(addr)); 00208 } 00209 00210 void setSubtune(uint8_t tune) 00211 { 00212 setVal(0xbf53, LDAb); 00213 setVal(0xbf54, tune); 00214 setVal(0xbf55, STAa); 00215 setVal(0xbf56, 0x0c); 00216 setVal(0xbf57, 0x03); 00217 setVal(0xbf58, JSRw); 00218 setVal(0xbf59, 0x2c); 00219 setVal(0xbf5a, 0xa8); 00220 setVal(0xbf5b, JMPw); 00221 setVal(0xbf5c, 0xb1); 00222 setVal(0xbf5d, 0xa7); 00223 } 00224 }; 00225 00229 class CharacterRomBank : public romBank<0x1000> {}; 00230 00231 #endif