A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 281 lines 6.6 kB view raw
1#include "rockmacros.h" 2 3#include "defs.h" 4#include "cpu-gb.h" 5#include "cpuregs.h" 6#include "hw.h" 7#include "regs.h" 8#include "lcd-gb.h" 9#include "rtc-gb.h" 10#include "mem.h" 11#include "sound.h" 12#include "save.h" 13 14#ifdef ROCKBOX_LITTLE_ENDIAN 15#define LIL(x) (x) 16#else 17#define LIL(x) ((x<<24)|((x&0xff00)<<8)|((x>>8)&0xff00)|(x>>24)) 18#endif 19 20#define I1(s, p) { 1, { s }, p } 21#define I2(s, p) { 2, { s }, p } 22#define I4(s, p) { 4, { s }, p } 23#define R(r) I1(#r, &R_##r) 24#define NOSAVE { -1, { "\0\0\0\0" }, 0 } 25#define END { 0, { "\0\0\0\0" }, 0 } 26 27struct svar 28{ 29 int len; 30 union 31 { 32 char _key[4] __NONSTRING; 33 un32 key; 34 } k; 35 void *ptr; 36}; 37 38static int ver; 39static int sramblock, iramblock, vramblock; 40static int hramofs, hiofs, palofs, oamofs, wavofs; 41 42struct svar svars[] = 43{ 44 I4("GbSs", &ver), 45 46 I2("PC ", &PC), 47 I2("SP ", &SP), 48 I2("HL ", &HL), 49#ifdef DYNAREC 50 I1("A ", &A), 51 I1("B ", &A), 52 I1("C ", &A), 53 I1("D ", &A), 54 I1("E ", &A), 55 I1("F ", &A), 56#else 57 I2("BC ", &BC), 58 I2("DE ", &DE), 59 I2("AF ", &AF), 60#endif 61 I4("IME ", &cpu.ime), 62 I4("ima ", &cpu.ima), 63 I4("spd ", &cpu.speed), 64 I4("halt", &cpu.halt), 65 I4("div ", &cpu.div), 66 I4("tim ", &cpu.tim), 67 I4("lcdc", &cpu.lcdc), 68 I4("snd ", &cpu.snd), 69 70 I1("ints", &hw.ilines), 71 I1("pad ", &hw.pad), 72 I4("cgb ", &hw.cgb), 73 74 I4("mbcm", &mbc.model), 75 I4("romb", &mbc.rombank), 76 I4("ramb", &mbc.rambank), 77 I4("enab", &mbc.enableram), 78 I4("batt", &mbc.batt), 79 80 I4("rtcR", &rtc.sel), 81 I4("rtcL", &rtc.latch), 82 I4("rtcC", &rtc.carry), 83 I4("rtcS", &rtc.stop), 84 I4("rtcd", &rtc.d), 85 I4("rtch", &rtc.h), 86 I4("rtcm", &rtc.m), 87 I4("rtcs", &rtc.s), 88 I4("rtct", &rtc.t), 89 I1("rtR8", &rtc.regs[0]), 90 I1("rtR9", &rtc.regs[1]), 91 I1("rtRA", &rtc.regs[2]), 92 I1("rtRB", &rtc.regs[3]), 93 I1("rtRC", &rtc.regs[4]), 94 95 I4("S1on", &snd.ch[0].on), 96 I4("S1p ", &snd.ch[0].pos), 97 I4("S1c ", &snd.ch[0].len), 98 I4("S1ec", &snd.ch[0].enlen), 99 I4("S1sc", &snd.ch[0].swlen), 100 101 I4("S2on", &snd.ch[1].on), 102 I4("S2p ", &snd.ch[1].pos), 103 I4("S2c ", &snd.ch[1].len), 104 I4("S2ec", &snd.ch[1].enlen), 105 106 I4("S3on", &snd.ch[2].on), 107 I4("S3p ", &snd.ch[2].pos), 108 I4("S3c ", &snd.ch[2].len), 109 110 I4("S4on", &snd.ch[3].on), 111 I4("S4p ", &snd.ch[3].pos), 112 I4("S4c ", &snd.ch[3].len), 113 I4("S4ec", &snd.ch[3].enlen), 114 115 I4("hdma", &hw.hdma), 116 117 I4("sram", &sramblock), 118 I4("iram", &iramblock), 119 I4("vram", &vramblock), 120 I4("hi ", &hiofs), 121 I4("pal ", &palofs), 122 I4("oam ", &oamofs), 123 124 /* NOSAVE is a special code to prevent the rest of the table 125 * from being saved, used to support old stuff for backwards 126 * compatibility... */ 127 NOSAVE, 128 129 /* the following are obsolete as of 0x104 */ 130 131 I4("hram", &hramofs), 132 /* I4("gba ", &hw.gba), */ 133 /* I4("S1sf", &snd.ch[0].swfreq), */ 134 I4("wav ", &wavofs), 135 136 R(P1), R(SB), R(SC), 137 R(DIV), R(TIMA), R(TMA), R(TAC), 138 R(IE), R(IF), 139 R(LCDC), R(STAT), R(LY), R(LYC), 140 R(SCX), R(SCY), R(WX), R(WY), 141 R(BGP), R(OBP0), R(OBP1), 142 R(DMA), 143 144 R(VBK), R(SVBK), R(KEY1), 145 R(BCPS), R(BCPD), R(OCPS), R(OCPD), 146 147 R(NR10), R(NR11), R(NR12), R(NR13), R(NR14), 148 R(NR21), R(NR22), R(NR23), R(NR24), 149 R(NR30), R(NR31), R(NR32), R(NR33), R(NR34), 150 R(NR41), R(NR42), R(NR43), R(NR44), 151 R(NR50), R(NR51), R(NR52), 152 153 I1("DMA1", &R_HDMA1), 154 I1("DMA2", &R_HDMA2), 155 I1("DMA3", &R_HDMA3), 156 I1("DMA4", &R_HDMA4), 157 I1("DMA5", &R_HDMA5), 158 159 END 160}; 161 162 163void loadstate(int fd) 164{ 165 int i, j; 166 byte buf[4096]; 167 un32 (*header)[2] = (un32 (*)[2])buf; 168 un32 d; 169 int irl = hw.cgb ? 8 : 2; 170 int vrl = hw.cgb ? 4 : 2; 171 int srl = mbc.ramsize << 1; 172 size_t base_offset; 173 174 ver = hramofs = hiofs = palofs = oamofs = wavofs = 0; 175 176 base_offset = lseek(fd, 0, SEEK_CUR); 177 178 read(fd,buf, 4096); 179 180 for (j = 0; header[j][0]; j++) 181 { 182 for (i = 0; svars[i].ptr; i++) 183 { 184 if (header[j][0] != svars[i].k.key) 185 continue; 186 d = LIL(header[j][1]); 187 switch (svars[i].len) 188 { 189 case 1: 190 *(byte *)svars[i].ptr = d; 191 break; 192 case 2: 193 *(un16 *)svars[i].ptr = d; 194 break; 195 case 4: 196 *(un32 *)svars[i].ptr = d; 197 break; 198 } 199 break; 200 } 201 } 202 203 /* obsolete as of version 0x104 */ 204 if (hramofs) memcpy(ram.hi+128, buf+hramofs, 127); 205 if (wavofs) memcpy(ram.hi+48, buf+wavofs, 16); 206 207 if (hiofs) memcpy(ram.hi, buf+hiofs, sizeof ram.hi); 208 if (palofs) memcpy(lcd.pal, buf+palofs, sizeof lcd.pal); 209 if (oamofs) memcpy(lcd.oam.mem, buf+oamofs, sizeof lcd.oam); 210 211 lseek(fd, base_offset + (iramblock << 12), SEEK_SET); 212 read(fd,ram.ibank, 4096*irl); 213 214 lseek(fd, base_offset + (vramblock << 12), SEEK_SET); 215 read(fd,lcd.vbank, 4096*vrl); 216 217 lseek(fd, base_offset + (sramblock << 12), SEEK_SET); 218 read(fd,ram.sbank, 4096*srl); 219 vram_dirty(); 220 pal_dirty(); 221 sound_dirty(); 222 mem_updatemap(); 223} 224 225void savestate(int fd) 226{ 227 int i; 228 byte buf[4096]; 229 un32 (*header)[2] = (un32 (*)[2])buf; 230 un32 d = 0; 231 int irl = hw.cgb ? 8 : 2; 232 int vrl = hw.cgb ? 4 : 2; 233 int srl = mbc.ramsize << 1; 234 size_t base_offset; 235 236 ver = 0x104; 237 iramblock = 1; 238 vramblock = 1+irl; 239 sramblock = 1+irl+vrl; 240 hiofs = 4096 - 768; 241 palofs = 4096 - 512; 242 oamofs = 4096 - 256; 243 memset(buf, 0, sizeof buf); 244 245 for (i = 0; svars[i].len > 0; i++) 246 { 247 header[i][0] = svars[i].k.key; 248 switch (svars[i].len) 249 { 250 case 1: 251 d = *(byte *)svars[i].ptr; 252 break; 253 case 2: 254 d = *(un16 *)svars[i].ptr; 255 break; 256 case 4: 257 d = *(un32 *)svars[i].ptr; 258 break; 259 } 260 header[i][1] = LIL(d); 261 } 262 header[i][0] = header[i][1] = 0; 263 264 memcpy(buf+hiofs, ram.hi, sizeof ram.hi); 265 memcpy(buf+palofs, lcd.pal, sizeof lcd.pal); 266 memcpy(buf+oamofs, lcd.oam.mem, sizeof lcd.oam); 267 268 /* calculate base offset for output file */ 269 /* (we'll seek relative to that from now on) */ 270 base_offset = lseek(fd, 0, SEEK_CUR); 271 write(fd,buf, 4096); 272 273 lseek(fd, base_offset + (iramblock << 12), SEEK_SET); 274 write(fd,ram.ibank, 4096*irl); 275 276 lseek(fd, base_offset + (vramblock << 12), SEEK_SET); 277 write(fd,lcd.vbank, 4096*vrl); 278 279 lseek(fd, base_offset + (sramblock << 12), SEEK_SET); 280 write(fd,ram.sbank, 4096*srl); 281}