diff --git a/CMakeLists.txt b/CMakeLists.txt index debba749..c1108b1a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ # The following lines of boilerplate have to be in your project's CMakeLists # in this exact order for cmake to work correctly -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.15) include($ENV{IDF_PATH}/tools/cmake/project.cmake) diff --git a/components/box-emu/include/box-emu.hpp b/components/box-emu/include/box-emu.hpp index c9217876..d0ccc66a 100644 --- a/components/box-emu/include/box-emu.hpp +++ b/components/box-emu/include/box-emu.hpp @@ -151,6 +151,7 @@ class BoxEmu : public espp::BaseComponent { ///////////////////////////////////////////////////////////////////////////// bool initialize_video(); + void clear_screen(); void display_size(size_t width, size_t height); void native_size(size_t width, size_t height, int pitch = -1); void palette(const uint16_t *palette, size_t size = 256); diff --git a/components/box-emu/src/box-emu.cpp b/components/box-emu/src/box-emu.cpp index e81473ec..b91e4879 100644 --- a/components/box-emu/src/box-emu.cpp +++ b/components/box-emu/src/box-emu.cpp @@ -467,6 +467,11 @@ bool BoxEmu::initialize_video() { return true; } +void BoxEmu::clear_screen() { + static int buffer = 0; + xQueueSend(video_queue_, &buffer, 10); +} + void BoxEmu::display_size(size_t width, size_t height) { display_width_ = width; display_height_ = height; @@ -717,13 +722,29 @@ bool BoxEmu::video_task_callback(std::mutex &m, std::condition_variable& cv, boo return false; } static constexpr int num_lines_to_write = num_rows_in_framebuffer; - auto &box = Bsp::get(); + static auto &box = Bsp::get(); + static const uint16_t *vram0 = (uint16_t*)box.vram0(); + static const uint16_t *vram1 = (uint16_t*)box.vram1(); static uint16_t vram_index = 0; // has to be static so that it persists between calls const int _x_offset = x_offset(); const int _y_offset = y_offset(); const uint16_t* _palette = palette(); - uint16_t *vram0 = (uint16_t*)box.vram0(); - uint16_t *vram1 = (uint16_t*)box.vram1(); + // special case: if _frame_ptr is null, then we ignore all palette, scaling, + // etc. and simply fill the screen with 0 + if (_frame_ptr == nullptr) { + for (int y=0; y(num_lines_to_write, lcd_height()-y); + // memset the buffer to 0 + memset(_buf, 0, lcd_width() * num_lines * sizeof(Pixel)); + box.write_lcd_frame(0, y + _y_offset, lcd_width(), num_lines, (uint8_t*)&_buf[0]); + } + + // now return + return false; + } + if (is_native()) { if (has_palette()) { for (int y=0; yaf) +#define F LB(cpu->af) +#define B HB(cpu->bc) +#define C LB(cpu->bc) +#define D HB(cpu->de) +#define E LB(cpu->de) +#define H HB(cpu->hl) +#define L LB(cpu->hl) + +#define AF W(cpu->af) +#define BC W(cpu->bc) +#define DE W(cpu->de) +#define HL W(cpu->hl) + +#define PC W(cpu->pc) +#define SP W(cpu->sp) + +#define xAF DW(cpu->af) +#define xBC DW(cpu->bc) +#define xDE DW(cpu->de) +#define xHL DW(cpu->hl) + +#define xPC DW(cpu->pc) +#define xSP DW(cpu->sp) + +#define IMA cpu->ima +#define IME cpu->ime #define IF R_IF #define IE R_IE diff --git a/components/gbc/gnuboy/include/gnuboy/lcd.h b/components/gbc/gnuboy/include/gnuboy/lcd.h index 9dfe3aae..a885c97d 100644 --- a/components/gbc/gnuboy/include/gnuboy/lcd.h +++ b/components/gbc/gnuboy/include/gnuboy/lcd.h @@ -13,7 +13,7 @@ struct vissprite //byte pad[2]; //6 }; -struct scan +struct gbc_scan { int bg[64]; int wnd[64]; @@ -45,7 +45,7 @@ struct lcd }; extern struct lcd lcd; -extern struct scan scan; +extern struct gbc_scan *scan; void lcd_begin(); diff --git a/components/gbc/gnuboy/include/gnuboy/loader.h b/components/gbc/gnuboy/include/gnuboy/loader.h index 74a50631..5ec9c0b5 100644 --- a/components/gbc/gnuboy/include/gnuboy/loader.h +++ b/components/gbc/gnuboy/include/gnuboy/loader.h @@ -22,6 +22,6 @@ int sram_save(); void state_load(int n); void state_save(int n); - +extern unsigned char *gbc_filebuf; #endif diff --git a/components/gbc/gnuboy/src/cpu.c b/components/gbc/gnuboy/src/cpu.c index 8c3ea7b7..cfd598be 100644 --- a/components/gbc/gnuboy/src/cpu.c +++ b/components/gbc/gnuboy/src/cpu.c @@ -15,12 +15,6 @@ #include "gnuboy/asm.h" #endif - -struct cpu cpu; - - - - #define ZFLAG(n) ( (n) ? 0 : FZ ) #define HFLAG(n) ( (n) ? 0 : FH ) #define CFLAG(n) ( (n) ? 0 : FC ) @@ -231,7 +225,7 @@ label: op(b); break; #define RET ( POP(PC) ) #define EI ( IMA = 1 ) -#define DI ( cpu.halt = IMA = IME = 0 ) +#define DI ( cpu->halt = IMA = IME = 0 ) @@ -251,13 +245,13 @@ label: op(b); break; void cpu_reset() { - cpu.speed = 0; - cpu.halt = 0; - cpu.div = 0; - cpu.tim = 0; + cpu->speed = 0; + cpu->halt = 0; + cpu->div = 0; + cpu->tim = 0; /* set lcdc ahead of cpu by 19us; see A */ /* FIXME: leave value at 0, use lcdc_trans() to actually send lcdc ahead */ - cpu.lcdc = 40; + cpu->lcdc = 40; IME = 0; IMA = 0; @@ -281,11 +275,11 @@ void cpu_reset() handle differences in place */ void div_advance(int cnt) { - cpu.div += (cnt<<1); - if (cpu.div >= 256) + cpu->div += (cnt<<1); + if (cpu->div >= 256) { - R_DIV += (cpu.div >> 8); - cpu.div &= 0xff; + R_DIV += (cpu->div >> 8); + cpu->div &= 0xff; } } @@ -302,12 +296,12 @@ void timer_advance(int cnt) if (!(R_TAC & 0x04)) return; unit = ((-R_TAC) & 3) << 1; - cpu.tim += (cnt<tim += (cnt<= 512) + if (cpu->tim >= 512) { - tima = R_TIMA + (cpu.tim >> 9); - cpu.tim &= 0x1ff; + tima = R_TIMA + (cpu->tim >> 9); + cpu->tim &= 0x1ff; if (tima >= 256) { hw_interrupt(IF_TIMER, IF_TIMER); @@ -325,21 +319,21 @@ void timer_advance(int cnt) */ inline void lcdc_advance(int cnt) { - cpu.lcdc -= cnt; - if (cpu.lcdc <= 0) lcdc_trans(); + cpu->lcdc -= cnt; + if (cpu->lcdc <= 0) lcdc_trans(); } /* cnt - time to emulate, expressed in 2MHz units */ inline void sound_advance(int cnt) { - cpu.snd += cnt; + cpu->snd += cnt; } /* cnt - time to emulate, expressed in 2MHz units */ void cpu_timers(int cnt) { - div_advance(cnt << cpu.speed); - timer_advance(cnt << cpu.speed); + div_advance(cnt << cpu->speed); + timer_advance(cnt << cpu->speed); lcdc_advance(cnt); sound_advance(cnt); } @@ -356,16 +350,16 @@ int cpu_idle(int max) int cnt, unit; - if (!(cpu.halt && IME)) return 0; + if (!(cpu->halt && IME)) return 0; if (R_IF & R_IE) { - cpu.halt = 0; + cpu->halt = 0; return 0; } /* Make sure we don't miss lcdc status events! */ - if ((R_IE & (IF_VBLANK | IF_STAT)) && (max > cpu.lcdc)) - max = cpu.lcdc; + if ((R_IE & (IF_VBLANK | IF_STAT)) && (max > cpu->lcdc)) + max = cpu->lcdc; /* If timer interrupt cannot happen, this is very simple! */ if (!((R_IE & IF_TIMER) && (R_TAC & 0x04))) @@ -376,7 +370,7 @@ int cpu_idle(int max) /* Figure out when the next timer interrupt will happen */ unit = ((-R_TAC) & 3) << 1; - cnt = (511 - cpu.tim + (1<> unit; + cnt = (511 - cpu->tim + (1<> unit; cnt += (255 - R_TIMA) << (9 - unit); if (max < cnt) @@ -909,15 +903,15 @@ int cpu_emulate(int cycles) PC++; if (R_KEY1 & 1) { - cpu.speed = cpu.speed ^ 1; - R_KEY1 = (R_KEY1 & 0x7E) | (cpu.speed << 7); + cpu->speed = cpu->speed ^ 1; + R_KEY1 = (R_KEY1 & 0x7E) | (cpu->speed << 7); break; } /* NOTE - we do not implement dmg STOP whatsoever */ break; case 0x76: /* HALT */ - cpu.halt = 1; + cpu->halt = 1; break; case 0xCB: /* CB prefix */ @@ -956,7 +950,7 @@ int cpu_emulate(int cycles) clen <<= 1; div_advance(clen); timer_advance(clen); - clen >>= cpu.speed; + clen >>= cpu->speed; lcdc_advance(clen); sound_advance(clen); diff --git a/components/gbc/gnuboy/src/emu.c b/components/gbc/gnuboy/src/emu.c index 2f501d17..37e8821f 100644 --- a/components/gbc/gnuboy/src/emu.c +++ b/components/gbc/gnuboy/src/emu.c @@ -41,7 +41,7 @@ void emu_reset() */ void emu_step() { - cpu_emulate(cpu.lcdc); + cpu_emulate(cpu->lcdc); } diff --git a/components/gbc/gnuboy/src/hw.c b/components/gbc/gnuboy/src/hw.c index cef4f76c..fffd959e 100644 --- a/components/gbc/gnuboy/src/hw.c +++ b/components/gbc/gnuboy/src/hw.c @@ -31,9 +31,9 @@ void hw_interrupt(byte i, byte mask) R_IF |= i & (hw.ilines ^ i); /* FIXME - is this correct? not sure the docs understand... */ - if ((R_IF & (R_IF ^ oldif) & R_IE) && cpu.ime) cpu.halt = 0; - /* if ((i & (hw.ilines ^ i) & R_IE) && cpu.ime) cpu.halt = 0; */ - /* if ((i & R_IE) && cpu.ime) cpu.halt = 0; */ + if ((R_IF & (R_IF ^ oldif) & R_IE) && cpu->ime) cpu->halt = 0; + /* if ((i & (hw.ilines ^ i) & R_IE) && cpu->ime) cpu->halt = 0; */ + /* if ((i & R_IE) && cpu->ime) cpu->halt = 0; */ hw.ilines &= ~mask; hw.ilines |= i; diff --git a/components/gbc/gnuboy/src/lcd.c b/components/gbc/gnuboy/src/lcd.c index 81984d42..8f77c9d8 100755 --- a/components/gbc/gnuboy/src/lcd.c +++ b/components/gbc/gnuboy/src/lcd.c @@ -21,30 +21,30 @@ struct lcd lcd; -struct scan scan; - -#define BG (scan.bg) -#define WND (scan.wnd) -#define BUF (scan.buf) -#define PRI (scan.pri) - - -#define PAL2 (scan.pal2) - -#define VS (scan.vs) /* vissprites */ -#define NS (scan.ns) - -#define L (scan.l) /* line */ -#define X (scan.x) /* screen position */ -#define Y (scan.y) -#define S (scan.s) /* tilemap position */ -#define T (scan.t) -#define U (scan.u) /* position within tile */ -#define V (scan.v) -#define WX (scan.wx) -#define WY (scan.wy) -#define WT (scan.wt) -#define WV (scan.wv) +struct gbc_scan *scan = NULL; + +#define BG (scan->bg) +#define WND (scan->wnd) +#define BUF (scan->buf) +#define PRI (scan->pri) + + +#define PAL2 (scan->pal2) + +#define VS (scan->vs) /* vissprites */ +#define NS (scan->ns) + +#define L (scan->l) /* line */ +#define X (scan->x) /* screen position */ +#define Y (scan->y) +#define S (scan->s) /* tilemap position */ +#define T (scan->t) +#define U (scan->u) /* position within tile */ +#define V (scan->v) +#define WX (scan->wx) +#define WY (scan->wy) +#define WT (scan->wt) +#define WV (scan->wv) static int sprsort = 1; diff --git a/components/gbc/gnuboy/src/lcdc.c b/components/gbc/gnuboy/src/lcdc.c index cfca1553..6eb7c12c 100644 --- a/components/gbc/gnuboy/src/lcdc.c +++ b/components/gbc/gnuboy/src/lcdc.c @@ -12,7 +12,7 @@ #include -#define C (cpu.lcdc) +#define C (cpu->lcdc) /* @@ -109,7 +109,7 @@ void lcdc_change(byte b) adds up to exactly 228 double-speed cycles (109us). LCDC emulation begins with R_LCDC set to "operation enabled", R_LY - set to line #0 and R_STAT set to state-hblank. cpu.lcdc is also + set to line #0 and R_STAT set to state-hblank. cpu->lcdc is also set to zero, to begin emulation we call lcdc_trans() once to force-advance LCD through the first iteration. @@ -234,7 +234,7 @@ void lcdc_trans() this better be done here or within stat_change(), otherwise CPU will have a chance to run for some time before interrupt is triggered */ - if (cpu.halt) + if (cpu->halt) { hw_interrupt(IF_VBLANK, IF_VBLANK); C += 228; diff --git a/components/gbc/gnuboy/src/save.c b/components/gbc/gnuboy/src/save.c index 5f9b6f65..10836af7 100644 --- a/components/gbc/gnuboy/src/save.c +++ b/components/gbc/gnuboy/src/save.c @@ -40,6 +40,192 @@ static int ver; static int sramblock, iramblock, vramblock; static int hramofs, hiofs, palofs, oamofs, wavofs; +// byte buf[4096]; +byte *gbc_filebuf = NULL; + +void loadstate(FILE *f) +{ + struct svar svars[] = + { + I4("GbSs", &ver), + + I2("PC ", &PC), + I2("SP ", &SP), + I2("BC ", &BC), + I2("DE ", &DE), + I2("HL ", &HL), + I2("AF ", &AF), + + I4("IME ", &cpu->ime), + I4("ima ", &cpu->ima), + I4("spd ", &cpu->speed), + I4("halt", &cpu->halt), + I4("div ", &cpu->div), + I4("tim ", &cpu->tim), + I4("lcdc", &cpu->lcdc), + I4("snd ", &cpu->snd), + + I1("ints", &hw.ilines), + I1("pad ", &hw.pad), + I4("cgb ", &hw.cgb), + I4("gba ", &hw.gba), + + I4("mbcm", &mbc.model), + I4("romb", &mbc.rombank), + I4("ramb", &mbc.rambank), + I4("enab", &mbc.enableram), + I4("batt", &mbc.batt), + + I4("rtcR", &rtc.sel), + I4("rtcL", &rtc.latch), + I4("rtcC", &rtc.carry), + I4("rtcS", &rtc.stop), + I4("rtcd", &rtc.d), + I4("rtch", &rtc.h), + I4("rtcm", &rtc.m), + I4("rtcs", &rtc.s), + I4("rtct", &rtc.t), + I1("rtR8", &rtc.regs[0]), + I1("rtR9", &rtc.regs[1]), + I1("rtRA", &rtc.regs[2]), + I1("rtRB", &rtc.regs[3]), + I1("rtRC", &rtc.regs[4]), + + I4("S1on", &snd.ch[0].on), + I4("S1p ", &snd.ch[0].pos), + I4("S1c ", &snd.ch[0].cnt), + I4("S1ec", &snd.ch[0].encnt), + I4("S1sc", &snd.ch[0].swcnt), + I4("S1sf", &snd.ch[0].swfreq), + + I4("S2on", &snd.ch[1].on), + I4("S2p ", &snd.ch[1].pos), + I4("S2c ", &snd.ch[1].cnt), + I4("S2ec", &snd.ch[1].encnt), + + I4("S3on", &snd.ch[2].on), + I4("S3p ", &snd.ch[2].pos), + I4("S3c ", &snd.ch[2].cnt), + + I4("S4on", &snd.ch[3].on), + I4("S4p ", &snd.ch[3].pos), + I4("S4c ", &snd.ch[3].cnt), + I4("S4ec", &snd.ch[3].encnt), + + I4("hdma", &hw.hdma), + + I4("sram", &sramblock), + I4("iram", &iramblock), + I4("vram", &vramblock), + I4("hi ", &hiofs), + I4("pal ", &palofs), + I4("oam ", &oamofs), + I4("wav ", &wavofs), + + /* NOSAVE is a special code to prevent the rest of the table + * from being saved, used to support old stuff for backwards + * compatibility... */ + NOSAVE, + + /* the following are obsolete as of 0x104 */ + + I4("hram", &hramofs), + + R(P1), R(SB), R(SC), + R(DIV), R(TIMA), R(TMA), R(TAC), + R(IE), R(IF), + R(LCDC), R(STAT), R(LY), R(LYC), + R(SCX), R(SCY), R(WX), R(WY), + R(BGP), R(OBP0), R(OBP1), + R(DMA), + + R(VBK), R(SVBK), R(KEY1), + R(BCPS), R(BCPD), R(OCPS), R(OCPD), + + R(NR10), R(NR11), R(NR12), R(NR13), R(NR14), + R(NR21), R(NR22), R(NR23), R(NR24), + R(NR30), R(NR31), R(NR32), R(NR33), R(NR34), + R(NR41), R(NR42), R(NR43), R(NR44), + R(NR50), R(NR51), R(NR52), + + I1("DMA1", &R_HDMA1), + I1("DMA2", &R_HDMA2), + I1("DMA3", &R_HDMA3), + I1("DMA4", &R_HDMA4), + I1("DMA5", &R_HDMA5), + + END + }; + + + int i, j; + + un32 (*header)[2] = (un32 (*)[2])gbc_filebuf; + un32 d; + int irl = hw.cgb ? 8 : 2; + int vrl = hw.cgb ? 4 : 2; + int srl = mbc.ramsize << 1; + + ver = hramofs = hiofs = palofs = oamofs = wavofs = 0; + + fseek(f, 0, SEEK_SET); + fread(gbc_filebuf, 4096, 1, f); + + for (j = 0; header[j][0]; j++) + { + for (i = 0; svars[i].ptr; i++) + { + if (header[j][0] != *(un32 *)svars[i].key) + continue; + d = LIL(header[j][1]); + switch (svars[i].len) + { + case 1: + *(byte *)svars[i].ptr = d; + break; + case 2: + *(un16 *)svars[i].ptr = d; + break; + case 4: + *(un32 *)svars[i].ptr = d; + break; + } + break; + } + } + + /* obsolete as of version 0x104 */ + if (hramofs) memcpy(ram.hi+128, gbc_filebuf+hramofs, 127); + + if (hiofs) memcpy(ram.hi, gbc_filebuf+hiofs, sizeof ram.hi); + if (palofs) memcpy(lcd.pal, gbc_filebuf+palofs, sizeof lcd.pal); + if (oamofs) memcpy(lcd.oam.mem, gbc_filebuf+oamofs, sizeof lcd.oam); + + if (wavofs) memcpy(snd.wave, gbc_filebuf+wavofs, sizeof snd.wave); + else memcpy(snd.wave, ram.hi+0x30, 16); /* patch data from older files */ + + iramblock = 1; + vramblock = 1+irl; + sramblock = 1+irl+vrl; + + fseek(f, iramblock<<12, SEEK_SET); + fread(ram.ibank, 4096, irl, f); + + fseek(f, vramblock<<12, SEEK_SET); + fread(lcd.vbank, 4096, vrl, f); + + fseek(f, sramblock<<12, SEEK_SET); + + size_t count = fread(ram.sbank, 4096, srl, f); + printf("loadstate: read sram addr=%p, size=0x%x, count=%d\n", (void*)ram.sbank, 4096 * srl, count); + + //byte* ptr = (byte*)(0x3f800000 + 0x300000 + (0xbe7a & 0x1fff)); + //printf("loadstate: watch = 0x%x, 0x%x, 0x%x, 0x%x\n", *ptr, *(ptr+1), *(ptr+2), *(ptr+3)); +} + + +void savestate(FILE *f) +{ struct svar svars[] = { I4("GbSs", &ver), @@ -51,14 +237,14 @@ struct svar svars[] = I2("HL ", &HL), I2("AF ", &AF), - I4("IME ", &cpu.ime), - I4("ima ", &cpu.ima), - I4("spd ", &cpu.speed), - I4("halt", &cpu.halt), - I4("div ", &cpu.div), - I4("tim ", &cpu.tim), - I4("lcdc", &cpu.lcdc), - I4("snd ", &cpu.snd), + I4("IME ", &cpu->ime), + I4("ima ", &cpu->ima), + I4("spd ", &cpu->speed), + I4("halt", &cpu->halt), + I4("div ", &cpu->div), + I4("tim ", &cpu->tim), + I4("lcdc", &cpu->lcdc), + I4("snd ", &cpu->snd), I1("ints", &hw.ilines), I1("pad ", &hw.pad), @@ -152,81 +338,10 @@ struct svar svars[] = END }; -byte buf[4096]; -void loadstate(FILE *f) -{ - int i, j; - - un32 (*header)[2] = (un32 (*)[2])buf; - un32 d; - int irl = hw.cgb ? 8 : 2; - int vrl = hw.cgb ? 4 : 2; - int srl = mbc.ramsize << 1; - - ver = hramofs = hiofs = palofs = oamofs = wavofs = 0; - - fseek(f, 0, SEEK_SET); - fread(buf, 4096, 1, f); - - for (j = 0; header[j][0]; j++) - { - for (i = 0; svars[i].ptr; i++) - { - if (header[j][0] != *(un32 *)svars[i].key) - continue; - d = LIL(header[j][1]); - switch (svars[i].len) - { - case 1: - *(byte *)svars[i].ptr = d; - break; - case 2: - *(un16 *)svars[i].ptr = d; - break; - case 4: - *(un32 *)svars[i].ptr = d; - break; - } - break; - } - } - - /* obsolete as of version 0x104 */ - if (hramofs) memcpy(ram.hi+128, buf+hramofs, 127); - - if (hiofs) memcpy(ram.hi, buf+hiofs, sizeof ram.hi); - if (palofs) memcpy(lcd.pal, buf+palofs, sizeof lcd.pal); - if (oamofs) memcpy(lcd.oam.mem, buf+oamofs, sizeof lcd.oam); - - if (wavofs) memcpy(snd.wave, buf+wavofs, sizeof snd.wave); - else memcpy(snd.wave, ram.hi+0x30, 16); /* patch data from older files */ - - iramblock = 1; - vramblock = 1+irl; - sramblock = 1+irl+vrl; - - fseek(f, iramblock<<12, SEEK_SET); - fread(ram.ibank, 4096, irl, f); - - fseek(f, vramblock<<12, SEEK_SET); - fread(lcd.vbank, 4096, vrl, f); - - fseek(f, sramblock<<12, SEEK_SET); - - size_t count = fread(ram.sbank, 4096, srl, f); - printf("loadstate: read sram addr=%p, size=0x%x, count=%d\n", (void*)ram.sbank, 4096 * srl, count); - - //byte* ptr = (byte*)(0x3f800000 + 0x300000 + (0xbe7a & 0x1fff)); - //printf("loadstate: watch = 0x%x, 0x%x, 0x%x, 0x%x\n", *ptr, *(ptr+1), *(ptr+2), *(ptr+3)); -} - - -void savestate(FILE *f) -{ int i; - un32 (*header)[2] = (un32 (*)[2])buf; + un32 (*header)[2] = (un32 (*)[2])gbc_filebuf; un32 d = 0; int irl = hw.cgb ? 8 : 2; int vrl = hw.cgb ? 4 : 2; @@ -240,7 +355,7 @@ void savestate(FILE *f) hiofs = 4096 - 768; palofs = 4096 - 512; oamofs = 4096 - 256; - memset(buf, 0, /*sizeof buf*/4096); + memset(gbc_filebuf, 0, /*sizeof gbc_filebuf*/4096); for (i = 0; svars[i].len > 0; i++) { @@ -261,13 +376,13 @@ void savestate(FILE *f) } header[i][0] = header[i][1] = 0; - memcpy(buf+hiofs, ram.hi, sizeof ram.hi); - memcpy(buf+palofs, lcd.pal, sizeof lcd.pal); - memcpy(buf+oamofs, lcd.oam.mem, sizeof lcd.oam); - memcpy(buf+wavofs, snd.wave, sizeof snd.wave); + memcpy(gbc_filebuf+hiofs, ram.hi, sizeof ram.hi); + memcpy(gbc_filebuf+palofs, lcd.pal, sizeof lcd.pal); + memcpy(gbc_filebuf+oamofs, lcd.oam.mem, sizeof lcd.oam); + memcpy(gbc_filebuf+wavofs, snd.wave, sizeof snd.wave); fseek(f, 0, SEEK_SET); - fwrite(buf, 4096, 1, f); + fwrite(gbc_filebuf, 4096, 1, f); fseek(f, iramblock<<12, SEEK_SET); fwrite(ram.ibank, 4096, irl, f); @@ -282,8 +397,8 @@ void savestate(FILE *f) byte* tmp = (byte *)ram.sbank; for (int j = 0; j < srl; ++j) { - memcpy(buf, (void*)tmp, 4096); - size_t count = fwrite(buf, 4096, 1, f); + memcpy(gbc_filebuf, (void*)tmp, 4096); + size_t count = fwrite(gbc_filebuf, 4096, 1, f); printf("savesate: wrote sram addr=%p, size=0x%x, count=%d\n", (void*)tmp, 4096, count); tmp += 4096; } diff --git a/components/gbc/gnuboy/src/sound.c b/components/gbc/gnuboy/src/sound.c index 5d462f51..4399bbac 100644 --- a/components/gbc/gnuboy/src/sound.c +++ b/components/gbc/gnuboy/src/sound.c @@ -158,9 +158,9 @@ void sound_mix() { int s, l, r, f, n; - if (!RATE || cpu.snd < RATE) return; + if (!RATE || cpu->snd < RATE) return; - for (; cpu.snd >= RATE; cpu.snd -= RATE) + for (; cpu->snd >= RATE; cpu->snd -= RATE) { l = r = 0; diff --git a/components/gbc/include/gbc_shared_memory.hpp b/components/gbc/include/gbc_shared_memory.hpp new file mode 100644 index 00000000..41028dc2 --- /dev/null +++ b/components/gbc/include/gbc_shared_memory.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// Initialize GBC shared memory and hardware components +void gbc_init_shared_memory(void); + +// Free GBC shared memory +void gbc_free_shared_memory(void); + +// Get pointers to shared memory regions +void gbc_get_memory_regions(uint8_t** vram, uint8_t** wram, uint8_t** audio); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/components/gbc/src/gameboy.cpp b/components/gbc/src/gameboy.cpp index 37e3f23c..f8c7fc04 100644 --- a/components/gbc/src/gameboy.cpp +++ b/components/gbc/src/gameboy.cpp @@ -1,6 +1,8 @@ // #pragma GCC optimize ("Ofast") #include "gameboy.hpp" +#include "gbc_shared_memory.hpp" +#include "shared_memory.h" #include @@ -27,7 +29,7 @@ extern "C" { using namespace std::chrono_literals; -// need to have these haere for gnuboy to work +// need to have these here for gnuboy to work uint32_t frame = 0; uint16_t* displayBuffer[2]; @@ -101,20 +103,21 @@ void reset_gameboy() { static bool unlock = false; void init_gameboy(const std::string& rom_filename, uint8_t *romdata, size_t rom_data_size) { - // if lcd.vbank is null, then we need to allocate memory for it - if (!lcd.vbank) { - lcd.vbank = (uint8_t*)heap_caps_malloc(2 * 8192, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); - } - - if (!ram.ibank) { - ram.ibank = (uint8_t*)heap_caps_malloc(8 * 4096, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); - } - - if (!pcm.buf) { - int buf_size = GAMEBOY_AUDIO_SAMPLE_RATE * 2 * 2 / 5; // TODO: ths / 5 is a hack to make it work since somtimes the gbc emulator writes a lot of sound bytes - pcm.buf = (int16_t*)heap_caps_malloc(buf_size, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); - pcm.len = buf_size; - } + // Initialize shared memory + gbc_init_shared_memory(); + + // Get shared memory regions + uint8_t* vram = nullptr; + uint8_t* wram = nullptr; + uint8_t* audio = nullptr; + gbc_get_memory_regions(&vram, &wram, &audio); + + // Use shared memory regions + lcd.vbank = vram; + ram.ibank = wram; + pcm.buf = (int16_t*)audio; + static constexpr int GBC_AUDIO_BUFFER_SIZE = GAMEBOY_AUDIO_SAMPLE_RATE * 2 * 2 / 5; // TODO: 5 is a hack to make it work + pcm.len = GBC_AUDIO_BUFFER_SIZE / sizeof(int16_t); // set native size BoxEmu::get().native_size(GAMEBOY_SCREEN_WIDTH, GAMEBOY_SCREEN_HEIGHT); @@ -192,10 +195,10 @@ void load_gameboy(std::string_view save_path) { auto f = fopen(save_path.data(), "rb"); loadstate(f); fclose(f); - vram_dirty(); - pal_dirty(); - sound_dirty(); - mem_updatemap(); + vram_dirty(); + pal_dirty(); + sound_dirty(); + mem_updatemap(); } } @@ -219,6 +222,9 @@ std::vector get_gameboy_video_buffer() { } void deinit_gameboy() { + // Free shared memory + gbc_free_shared_memory(); + // now unload everything loader_unload(); BoxEmu::get().audio_sample_rate(48000); diff --git a/components/gbc/src/gbc_shared_memory.cpp b/components/gbc/src/gbc_shared_memory.cpp new file mode 100644 index 00000000..31d3bcf2 --- /dev/null +++ b/components/gbc/src/gbc_shared_memory.cpp @@ -0,0 +1,107 @@ +#include "gbc_shared_memory.hpp" +#include "shared_memory.h" +#include "esp_log.h" + +#include + +extern "C" { +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +} + +static const char *TAG = "gbc_shared_memory"; + +// GBC memory sizes +#define GBC_VRAM_SIZE (16 * 1024) // 16KB VRAM +#define GBC_WRAM_SIZE (32 * 1024) // 32KB WRAM +#define GBC_AUDIO_BUFFER_SIZE (2048 * sizeof(int16_t)) // 2048 samples at 16-bit per sample + +// Static pointers to shared memory regions +static uint8_t* vram_ptr = nullptr; +static uint8_t* wram_ptr = nullptr; +static uint8_t* audio_ptr = nullptr; +struct cpu *cpu = nullptr; + +void gbc_init_shared_memory(void) { + // Allocate VRAM in shared memory + shared_mem_request_t vram_request = { + .size = GBC_VRAM_SIZE, + .region = SHARED_MEM_DEFAULT + }; + vram_ptr = (uint8_t*)shared_mem_allocate(&vram_request); + if (!vram_ptr) { + ESP_LOGE(TAG, "Failed to allocate VRAM"); + return; + } + memset(vram_ptr, 0, GBC_VRAM_SIZE); + + // Allocate WRAM in shared memory + shared_mem_request_t wram_request = { + .size = GBC_WRAM_SIZE, + .region = SHARED_MEM_DEFAULT + }; + wram_ptr = (uint8_t*)shared_mem_allocate(&wram_request); + if (!wram_ptr) { + ESP_LOGE(TAG, "Failed to allocate WRAM"); + return; + } + memset(wram_ptr, 0, GBC_WRAM_SIZE); + + // allocate gbc scan object in shared memory + shared_mem_request_t gbc_scan_request = { + .size = sizeof(struct gbc_scan), + .region = SHARED_MEM_DEFAULT + }; + scan = (struct gbc_scan*)shared_mem_allocate(&gbc_scan_request); + + // allocate gbc file buf in shared memory + shared_mem_request_t gbc_file_request = { + .size = 4096, + .region = SHARED_MEM_DEFAULT + }; + gbc_filebuf = (uint8_t*)shared_mem_allocate(&gbc_file_request); + + // allocate CPU structure in shared memory + shared_mem_request_t cpu_request = { + .size = sizeof(struct cpu), + .region = SHARED_MEM_DEFAULT + }; + cpu = (struct cpu*)shared_mem_allocate(&cpu_request); + + // Allocate audio buffer in shared memory + shared_mem_request_t audio_request = { + .size = GBC_AUDIO_BUFFER_SIZE, + .region = SHARED_MEM_DEFAULT + }; + audio_ptr = (uint8_t*)shared_mem_allocate(&audio_request); + if (!audio_ptr) { + ESP_LOGE(TAG, "Failed to allocate audio buffer"); + return; + } + memset(audio_ptr, 0, GBC_AUDIO_BUFFER_SIZE); +} + +void gbc_free_shared_memory(void) { + // Clear all shared memory + shared_mem_clear(); + + // Reset pointers + vram_ptr = nullptr; + wram_ptr = nullptr; + audio_ptr = nullptr; +} + +void gbc_get_memory_regions(uint8_t** vram, uint8_t** wram, uint8_t** audio) { + if (vram) *vram = vram_ptr; + if (wram) *wram = wram_ptr; + if (audio) *audio = audio_ptr; +} diff --git a/components/genesis/CMakeLists.txt b/components/genesis/CMakeLists.txt index e5931a3c..5c82a1f8 100644 --- a/components/genesis/CMakeLists.txt +++ b/components/genesis/CMakeLists.txt @@ -1,10 +1,27 @@ idf_component_register( - INCLUDE_DIRS "include" - SRC_DIRS "src" "gwenesis/src/bus" "gwenesis/src/cpus/M68K" "gwenesis/src/cpus/Z80" "gwenesis/src/io" "gwenesis/src/savestate" "gwenesis/src/sound" "gwenesis/src/vdp" - PRIV_INCLUDE_DIRS "." "gwenesis/src/bus" "gwenesis/src/cpus/M68K" "gwenesis/src/cpus/Z80" "gwenesis/src/io" "gwenesis/src/savestate" "gwenesis/src/sound" "gwenesis/src/vdp" - LDFRAGMENTS "linker.lf" - REQUIRES box-emu statistics - ) + SRC_DIRS + "src" + "gwenesis/src/bus" + "gwenesis/src/cpus/M68K" + "gwenesis/src/cpus/Z80" + "gwenesis/src/sound" + "gwenesis/src/vdp" + "gwenesis/src/io" + "gwenesis/src/savestate" + INCLUDE_DIRS + "include" + "gwenesis/src" + "gwenesis/src/bus" + "gwenesis/src/cpus/M68K" + "gwenesis/src/cpus/Z80" + "gwenesis/src/sound" + "gwenesis/src/vdp" + "gwenesis/src/io" + "gwenesis/src/savestate" + REQUIRES + shared_memory + box-emu +) # target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-char-subscripts -Wno-attributes -Wno-implicit-fallthrough -Wno-unused-function -Wno-unused-variable -Wno-discarded-qualifiers) target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-unused-const-variable -Wno-unused-value -Ofast) # target_compile_definitions(${COMPONENT_LIB} PRIVATE GWENESIS_AUDIO_ACCURATE=0 BUILD_TABLES=0 TABLES_FULL=0) diff --git a/components/genesis/gwenesis/src/cpus/M68K/m68k.h b/components/genesis/gwenesis/src/cpus/M68K/m68k.h index cd1b76a5..56bd071e 100644 --- a/components/genesis/gwenesis/src/cpus/M68K/m68k.h +++ b/components/genesis/gwenesis/src/cpus/M68K/m68k.h @@ -341,7 +341,7 @@ typedef struct } m68ki_cpu_core; /* CPU cores */ -extern m68ki_cpu_core m68k; +extern m68ki_cpu_core *m68k; /* ======================================================================== */ /* ============================== CALLBACKS =============================== */ diff --git a/components/genesis/gwenesis/src/cpus/M68K/m68kcpu.c b/components/genesis/gwenesis/src/cpus/M68K/m68kcpu.c index fda0384a..fa701d39 100644 --- a/components/genesis/gwenesis/src/cpus/M68K/m68kcpu.c +++ b/components/genesis/gwenesis/src/cpus/M68K/m68kcpu.c @@ -36,7 +36,7 @@ static unsigned char m68ki_cycles[0x10000]; static int irq_latency; -m68ki_cpu_core m68k; +m68ki_cpu_core *m68k = NULL; /* ======================================================================== */ @@ -88,39 +88,39 @@ unsigned int m68k_get_reg(m68k_register_t regnum) { switch(regnum) { - case M68K_REG_D0: return m68ki_cpu.dar[0]; - case M68K_REG_D1: return m68ki_cpu.dar[1]; - case M68K_REG_D2: return m68ki_cpu.dar[2]; - case M68K_REG_D3: return m68ki_cpu.dar[3]; - case M68K_REG_D4: return m68ki_cpu.dar[4]; - case M68K_REG_D5: return m68ki_cpu.dar[5]; - case M68K_REG_D6: return m68ki_cpu.dar[6]; - case M68K_REG_D7: return m68ki_cpu.dar[7]; - case M68K_REG_A0: return m68ki_cpu.dar[8]; - case M68K_REG_A1: return m68ki_cpu.dar[9]; - case M68K_REG_A2: return m68ki_cpu.dar[10]; - case M68K_REG_A3: return m68ki_cpu.dar[11]; - case M68K_REG_A4: return m68ki_cpu.dar[12]; - case M68K_REG_A5: return m68ki_cpu.dar[13]; - case M68K_REG_A6: return m68ki_cpu.dar[14]; - case M68K_REG_A7: return m68ki_cpu.dar[15]; - case M68K_REG_PC: return MASK_OUT_ABOVE_32(m68ki_cpu.pc); - case M68K_REG_SR: return m68ki_cpu.t1_flag | - (m68ki_cpu.s_flag << 11) | - m68ki_cpu.int_mask | - ((m68ki_cpu.x_flag & XFLAG_SET) >> 4) | - ((m68ki_cpu.n_flag & NFLAG_SET) >> 4) | - ((!m68ki_cpu.not_z_flag) << 2) | - ((m68ki_cpu.v_flag & VFLAG_SET) >> 6) | - ((m68ki_cpu.c_flag & CFLAG_SET) >> 8); - case M68K_REG_SP: return m68ki_cpu.dar[15]; - case M68K_REG_USP: return m68ki_cpu.s_flag ? m68ki_cpu.sp[0] : m68ki_cpu.dar[15]; - case M68K_REG_ISP: return m68ki_cpu.s_flag ? m68ki_cpu.dar[15] : m68ki_cpu.sp[4]; + case M68K_REG_D0: return m68ki_cpu->dar[0]; + case M68K_REG_D1: return m68ki_cpu->dar[1]; + case M68K_REG_D2: return m68ki_cpu->dar[2]; + case M68K_REG_D3: return m68ki_cpu->dar[3]; + case M68K_REG_D4: return m68ki_cpu->dar[4]; + case M68K_REG_D5: return m68ki_cpu->dar[5]; + case M68K_REG_D6: return m68ki_cpu->dar[6]; + case M68K_REG_D7: return m68ki_cpu->dar[7]; + case M68K_REG_A0: return m68ki_cpu->dar[8]; + case M68K_REG_A1: return m68ki_cpu->dar[9]; + case M68K_REG_A2: return m68ki_cpu->dar[10]; + case M68K_REG_A3: return m68ki_cpu->dar[11]; + case M68K_REG_A4: return m68ki_cpu->dar[12]; + case M68K_REG_A5: return m68ki_cpu->dar[13]; + case M68K_REG_A6: return m68ki_cpu->dar[14]; + case M68K_REG_A7: return m68ki_cpu->dar[15]; + case M68K_REG_PC: return MASK_OUT_ABOVE_32(m68ki_cpu->pc); + case M68K_REG_SR: return m68ki_cpu->t1_flag | + (m68ki_cpu->s_flag << 11) | + m68ki_cpu->int_mask | + ((m68ki_cpu->x_flag & XFLAG_SET) >> 4) | + ((m68ki_cpu->n_flag & NFLAG_SET) >> 4) | + ((!m68ki_cpu->not_z_flag) << 2) | + ((m68ki_cpu->v_flag & VFLAG_SET) >> 6) | + ((m68ki_cpu->c_flag & CFLAG_SET) >> 8); + case M68K_REG_SP: return m68ki_cpu->dar[15]; + case M68K_REG_USP: return m68ki_cpu->s_flag ? m68ki_cpu->sp[0] : m68ki_cpu->dar[15]; + case M68K_REG_ISP: return m68ki_cpu->s_flag ? m68ki_cpu->dar[15] : m68ki_cpu->sp[4]; #if M68K_EMULATE_PREFETCH - case M68K_REG_PREF_ADDR: return m68ki_cpu.pref_addr; - case M68K_REG_PREF_DATA: return m68ki_cpu.pref_data; + case M68K_REG_PREF_ADDR: return m68ki_cpu->pref_addr; + case M68K_REG_PREF_DATA: return m68ki_cpu->pref_data; #endif - case M68K_REG_IR: return m68ki_cpu.ir; + case M68K_REG_IR: return m68ki_cpu->ir; default: return 0; } } @@ -211,7 +211,7 @@ void m68k_update_irq(unsigned int mask) CPU_INT_LEVEL |= (mask << 8); #ifdef LOGERROR - error("[%d(%d)][%d(%d)] m68k IRQ Level = %d(0x%02x) (%x)\n", v_counter, m68k.cycles/3420, m68k.cycles, m68k.cycles%3420,CPU_INT_LEVEL>>8,FLAG_INT_MASK,m68k_get_reg(M68K_REG_PC)); + error("[%d(%d)][%d(%d)] m68k IRQ Level = %d(0x%02x) (%x)\n", v_counter, m68k->cycles/3420, m68k->cycles, m68k->cycles%3420,CPU_INT_LEVEL>>8,FLAG_INT_MASK,m68k_get_reg(M68K_REG_PC)); #endif } @@ -221,7 +221,7 @@ void m68k_set_irq(unsigned int int_level) CPU_INT_LEVEL = int_level << 8; #ifdef LOGERROR - error("[%d(%d)][%d(%d)] m68k IRQ Level = %d(0x%02x) (%x)\n", v_counter, m68k.cycles/3420, m68k.cycles, m68k.cycles%3420,CPU_INT_LEVEL>>8,FLAG_INT_MASK,m68k_get_reg(M68K_REG_PC)); + error("[%d(%d)][%d(%d)] m68k IRQ Level = %d(0x%02x) (%x)\n", v_counter, m68k->cycles/3420, m68k->cycles, m68k->cycles%3420,CPU_INT_LEVEL>>8,FLAG_INT_MASK,m68k_get_reg(M68K_REG_PC)); #endif } @@ -254,7 +254,7 @@ void m68k_set_irq_delay(unsigned int int_level) } #ifdef LOGERROR - error("[%d(%d)][%d(%d)] m68k IRQ Level = %d(0x%02x) (%x)\n", v_counter, m68k.cycles/3420, m68k.cycles, m68k.cycles%3420,CPU_INT_LEVEL>>8,FLAG_INT_MASK,m68k_get_reg(M68K_REG_PC)); + error("[%d(%d)][%d(%d)] m68k IRQ Level = %d(0x%02x) (%x)\n", v_counter, m68k->cycles/3420, m68k->cycles, m68k->cycles%3420,CPU_INT_LEVEL>>8,FLAG_INT_MASK,m68k_get_reg(M68K_REG_PC)); #endif /* Check interrupt mask to process IRQ */ @@ -263,10 +263,10 @@ void m68k_set_irq_delay(unsigned int int_level) void m68k_run(unsigned int cycles) { - // printf("m68K_run current_cycles=%d add=%d STOP=%x\n",m68k.cycles,cycles,CPU_STOPPED); + // printf("m68K_run current_cycles=%d add=%d STOP=%x\n",m68k->cycles,cycles,CPU_STOPPED); /* Make sure CPU is not already ahead */ - if (m68k.cycles >= cycles) + if (m68k->cycles >= cycles) { return; } @@ -277,21 +277,21 @@ void m68k_run(unsigned int cycles) /* Make sure we're not stopped */ if (CPU_STOPPED) { - m68k.cycles = cycles; + m68k->cycles = cycles; return; } /* Save end cycles count for when CPU is stopped */ - m68k.cycle_end = cycles; + m68k->cycle_end = cycles; /* Return point for when we have an address error (TODO: use goto) */ m68ki_set_address_error_trap() /* auto-disable (see m68kcpu.h) */ #ifdef LOGERROR - error("[%d][%d] m68k run to %d cycles (%x), irq mask = %x (%x)\n", v_counter, m68k.cycles, cycles, m68k.pc,FLAG_INT_MASK, CPU_INT_LEVEL); + error("[%d][%d] m68k run to %d cycles (%x), irq mask = %x (%x)\n", v_counter, m68k->cycles, cycles, m68k->pc,FLAG_INT_MASK, CPU_INT_LEVEL); #endif - while (m68k.cycles < cycles) + while (m68k->cycles < cycles) { /* Set tracing accodring to T1. */ m68ki_trace_t1() /* auto-disable (see m68kcpu.h) */ @@ -308,7 +308,7 @@ void m68k_run(unsigned int cycles) /* Decode next instruction */ REG_IR = m68ki_read_imm_16(); -// printf("PC=%x IR=%x CYCLES=%d \n",m68k.pc,REG_IR,CYC_INSTRUCTION[REG_IR]); +// printf("PC=%x IR=%x CYCLES=%d \n",m68k->pc,REG_IR,CYC_INSTRUCTION[REG_IR]); /* Execute instruction */ m68ki_instruction_jump_table[REG_IR](); @@ -326,12 +326,12 @@ int m68k_cycles(void) int m68k_cycles_run(void) { - return m68k.cycle_end - m68k.cycles; + return m68k->cycle_end - m68k->cycles; } int m68k_cycles_master(void) { - return m68k.cycles; + return m68k->cycles; } void m68k_init(void) @@ -348,7 +348,7 @@ void m68k_init(void) #endif #ifdef M68K_OVERCLOCK_SHIFT - m68k.cycle_ratio = 1 << M68K_OVERCLOCK_SHIFT; + m68k->cycle_ratio = 1 << M68K_OVERCLOCK_SHIFT; #endif #if M68K_EMULATE_INT_ACK == OPT_ON @@ -429,10 +429,10 @@ void gwenesis_m68k_save_state() { saveGwenesisStateSet(state, "REG_ISP", REG_ISP); saveGwenesisStateSet(state, "REG_IR", REG_IR); - saveGwenesisStateSet(state, "m68k_cycle_end", m68k.cycle_end); - saveGwenesisStateSet(state, "m68k_cycles", m68k.cycles); - saveGwenesisStateSet(state, "m68k_int_level", m68k.int_level); - saveGwenesisStateSet(state, "m68k_stopped", m68k.stopped); + saveGwenesisStateSet(state, "m68k_cycle_end", m68k->cycle_end); + saveGwenesisStateSet(state, "m68k_cycles", m68k->cycles); + saveGwenesisStateSet(state, "m68k_int_level", m68k->int_level); + saveGwenesisStateSet(state, "m68k_stopped", m68k->stopped); } void gwenesis_m68k_load_state() { @@ -446,10 +446,10 @@ void gwenesis_m68k_load_state() { REG_ISP = saveGwenesisStateGet(state, "REG_ISP"); REG_IR = saveGwenesisStateGet(state, "REG_IR"); - m68k.cycle_end = saveGwenesisStateGet(state, "m68k_cycle_end"); - m68k.cycles = saveGwenesisStateGet(state, "m68k_cycles"); - m68k.int_level = saveGwenesisStateGet(state, "m68k_int_level"); - m68k.stopped = saveGwenesisStateGet(state, "m68k_stopped"); + m68k->cycle_end = saveGwenesisStateGet(state, "m68k_cycle_end"); + m68k->cycles = saveGwenesisStateGet(state, "m68k_cycles"); + m68k->int_level = saveGwenesisStateGet(state, "m68k_int_level"); + m68k->stopped = saveGwenesisStateGet(state, "m68k_stopped"); } diff --git a/components/genesis/gwenesis/src/cpus/M68K/m68kcpu.h b/components/genesis/gwenesis/src/cpus/M68K/m68kcpu.h index 956dd36a..9af5df70 100644 --- a/components/genesis/gwenesis/src/cpus/M68K/m68kcpu.h +++ b/components/genesis/gwenesis/src/cpus/M68K/m68kcpu.h @@ -182,35 +182,35 @@ /* ------------------------------ CPU Access ------------------------------ */ /* Access the CPU registers */ -#define REG_DA m68ki_cpu.dar /* easy access to data and address regs */ -#define REG_D m68ki_cpu.dar -#define REG_A (m68ki_cpu.dar+8) -#define REG_PC m68ki_cpu.pc -#define REG_SP_BASE m68ki_cpu.sp -#define REG_USP m68ki_cpu.sp[0] -#define REG_ISP m68ki_cpu.sp[4] -#define REG_SP m68ki_cpu.dar[15] -#define REG_IR m68ki_cpu.ir - -#define FLAG_T1 m68ki_cpu.t1_flag -#define FLAG_S m68ki_cpu.s_flag -#define FLAG_X m68ki_cpu.x_flag -#define FLAG_N m68ki_cpu.n_flag -#define FLAG_Z m68ki_cpu.not_z_flag -#define FLAG_V m68ki_cpu.v_flag -#define FLAG_C m68ki_cpu.c_flag -#define FLAG_INT_MASK m68ki_cpu.int_mask - -#define CPU_INT_LEVEL m68ki_cpu.int_level /* ASG: changed from CPU_INTS_PENDING */ -#define CPU_STOPPED m68ki_cpu.stopped +#define REG_DA m68ki_cpu->dar /* easy access to data and address regs */ +#define REG_D m68ki_cpu->dar +#define REG_A (m68ki_cpu->dar+8) +#define REG_PC m68ki_cpu->pc +#define REG_SP_BASE m68ki_cpu->sp +#define REG_USP m68ki_cpu->sp[0] +#define REG_ISP m68ki_cpu->sp[4] +#define REG_SP m68ki_cpu->dar[15] +#define REG_IR m68ki_cpu->ir + +#define FLAG_T1 m68ki_cpu->t1_flag +#define FLAG_S m68ki_cpu->s_flag +#define FLAG_X m68ki_cpu->x_flag +#define FLAG_N m68ki_cpu->n_flag +#define FLAG_Z m68ki_cpu->not_z_flag +#define FLAG_V m68ki_cpu->v_flag +#define FLAG_C m68ki_cpu->c_flag +#define FLAG_INT_MASK m68ki_cpu->int_mask + +#define CPU_INT_LEVEL m68ki_cpu->int_level /* ASG: changed from CPU_INTS_PENDING */ +#define CPU_STOPPED m68ki_cpu->stopped #if M68K_EMULATE_PREFETCH -#define CPU_PREF_ADDR m68ki_cpu.pref_addr -#define CPU_PREF_DATA m68ki_cpu.pref_data +#define CPU_PREF_ADDR m68ki_cpu->pref_addr +#define CPU_PREF_DATA m68ki_cpu->pref_data #endif #define CPU_ADDRESS_MASK 0x00ffffff #if M68K_EMULATE_ADDRESS_ERROR -#define CPU_INSTR_MODE m68ki_cpu.instr_mode -#define CPU_RUN_MODE m68ki_cpu.run_mode +#define CPU_INSTR_MODE m68ki_cpu->instr_mode +#define CPU_RUN_MODE m68ki_cpu->run_mode #endif #define CYC_INSTRUCTION m68ki_cycles @@ -226,16 +226,16 @@ #define CYC_RESET (132 * MUL) #if M68K_EMULATE_INT_ACK == OPT_ON -#define CALLBACK_INT_ACK m68ki_cpu.int_ack_callback +#define CALLBACK_INT_ACK m68ki_cpu->int_ack_callback #endif #if M68K_EMULATE_RESET == OPT_ON -#define CALLBACK_RESET_INSTR m68ki_cpu.reset_instr_callback +#define CALLBACK_RESET_INSTR m68ki_cpu->reset_instr_callback #endif #if M68K_TAS_HAS_CALLBACK == OPT_ON -#define CALLBACK_TAS_INSTR m68ki_cpu.tas_instr_callback +#define CALLBACK_TAS_INSTR m68ki_cpu->tas_instr_callback #endif #if M68K_EMULATE_FC == OPT_ON -#define CALLBACK_SET_FC m68ki_cpu.set_fc_callback +#define CALLBACK_SET_FC m68ki_cpu->set_fc_callback #endif @@ -283,9 +283,9 @@ #else #define m68ki_set_fc(A) CALLBACK_SET_FC(A); #endif - #define m68ki_use_data_space() m68ki_cpu.address_space = FUNCTION_CODE_USER_DATA; - #define m68ki_use_program_space() m68ki_cpu.address_space = FUNCTION_CODE_USER_PROGRAM; - #define m68ki_get_address_space() m68ki_cpu.address_space + #define m68ki_use_data_space() m68ki_cpu->address_space = FUNCTION_CODE_USER_DATA; + #define m68ki_use_program_space() m68ki_cpu->address_space = FUNCTION_CODE_USER_PROGRAM; + #define m68ki_get_address_space() m68ki_cpu->address_space #else #define m68ki_set_fc(A) #define m68ki_use_data_space() @@ -297,11 +297,11 @@ /* Enable or disable trace emulation */ #if M68K_EMULATE_TRACE /* Initiates trace checking before each instruction (t1) */ - #define m68ki_trace_t1() m68ki_cpu.tracing = FLAG_T1; + #define m68ki_trace_t1() m68ki_cpu->tracing = FLAG_T1; /* Clear all tracing */ - #define m68ki_clear_trace() m68ki_cpu.tracing = 0; + #define m68ki_clear_trace() m68ki_cpu->tracing = 0; /* Cause a trace exception if we are tracing */ - #define m68ki_exception_if_trace() if(m68ki_cpu.tracing) m68ki_exception_trace(); + #define m68ki_exception_if_trace() if(m68ki_cpu->tracing) m68ki_exception_trace(); #else #define m68ki_trace_t1() #define m68ki_clear_trace() @@ -312,7 +312,7 @@ /* Enable or disable Address error emulation */ #if M68K_EMULATE_ADDRESS_ERROR #define m68ki_set_address_error_trap() \ - if(setjmp(m68ki_cpu.aerr_trap) != 0) \ + if(setjmp(m68ki_cpu->aerr_trap) != 0) \ { \ m68ki_exception_address_error(); \ } @@ -320,12 +320,12 @@ #define m68ki_check_address_error(ADDR, WRITE_MODE, FC) \ if((ADDR)&1) \ { \ - if (m68ki_cpu.aerr_enabled) \ + if (m68ki_cpu->aerr_enabled) \ { \ - m68ki_cpu.aerr_address = ADDR; \ - m68ki_cpu.aerr_write_mode = WRITE_MODE; \ - m68ki_cpu.aerr_fc = FC; \ - longjmp(m68ki_cpu.aerr_trap, 1); \ + m68ki_cpu->aerr_address = ADDR; \ + m68ki_cpu->aerr_write_mode = WRITE_MODE; \ + m68ki_cpu->aerr_fc = FC; \ + longjmp(m68ki_cpu->aerr_trap, 1); \ } \ } #else @@ -514,11 +514,11 @@ /* ---------------------------- Cycle Counting ---------------------------- */ #ifdef M68K_OVERCLOCK_SHIFT -#define USE_CYCLES(A) m68ki_cpu.cycles += ((A) * m68ki_cpu.cycle_ratio) >> M68K_OVERCLOCK_SHIFT +#define USE_CYCLES(A) m68ki_cpu->cycles += ((A) * m68ki_cpu->cycle_ratio) >> M68K_OVERCLOCK_SHIFT #else -#define USE_CYCLES(A) m68ki_cpu.cycles += (A) +#define USE_CYCLES(A) m68ki_cpu->cycles += (A) #endif -#define SET_CYCLES(A) m68ki_cpu.cycles = (A) +#define SET_CYCLES(A) m68ki_cpu->cycles = (A) /* ======================================================================== */ @@ -532,11 +532,11 @@ void gwenesis_m68k_load_state(); /*** BZHXX ***/ /* Read data immediately following the PC */ -//#define m68k_read_immediate_16(address) *(uint16 *)(m68ki_cpu.memory_map[((address)>>16)&0xff].base + ((address) & 0xffff)) +//#define m68k_read_immediate_16(address) *(uint16 *)(m68ki_cpu->memory_map[((address)>>16)&0xff].base + ((address) & 0xffff)) //#define m68k_read_immediate_32(address) (m68k_read_immediate_16(address) << 16) | (m68k_read_immediate_16(address+2)) /* Read data relative to the PC */ -//#define m68k_read_pcrelative_8(address) READ_BYTE(m68ki_cpu.memory_map[((address)>>16)&0xff].base, (address) & 0xffff) +//#define m68k_read_pcrelative_8(address) READ_BYTE(m68ki_cpu->memory_map[((address)>>16)&0xff].base, (address) & 0xffff) //#define m68k_read_pcrelative_16(address) m68k_read_immediate_16(address) //#define m68k_read_pcrelative_32(address) m68k_read_immediate_32(address) @@ -921,7 +921,7 @@ INLINE void m68ki_write_32(uint32 address, uint32 value) #if 0 INLINE uint32 m68ki_read_8(uint32 address) { - cpu_memory_map *temp = &m68ki_cpu.memory_map[((address)>>16)&0xff]; + cpu_memory_map *temp = &m68ki_cpu->memory_map[((address)>>16)&0xff]; uint32 val; m68ki_set_fc(FLAG_S | m68ki_get_address_space()) /* auto-disable (see m68kcpu.h) */ @@ -945,7 +945,7 @@ INLINE uint32 m68ki_read_16(uint32 address) m68ki_set_fc(FLAG_S | m68ki_get_address_space()) /* auto-disable (see m68kcpu.h) */ m68ki_check_address_error(address, MODE_READ, FLAG_S | m68ki_get_address_space()) /* auto-disable (see m68kcpu.h) */ - temp = &m68ki_cpu.memory_map[((address)>>16)&0xff]; + temp = &m68ki_cpu->memory_map[((address)>>16)&0xff]; if (temp->read16) val = (*temp->read16)(ADDRESS_68K(address)); else val = *(uint16 *)(temp->base + ((address) & 0xffff)); @@ -965,7 +965,7 @@ INLINE uint32 m68ki_read_32(uint32 address) m68ki_set_fc(FLAG_S | m68ki_get_address_space()) /* auto-disable (see m68kcpu.h) */ m68ki_check_address_error(address, MODE_READ, FLAG_S | m68ki_get_address_space()) /* auto-disable (see m68kcpu.h) */ - temp = &m68ki_cpu.memory_map[((address)>>16)&0xff]; + temp = &m68ki_cpu->memory_map[((address)>>16)&0xff]; if (temp->read16) val = ((*temp->read16)(ADDRESS_68K(address)) << 16) | ((*temp->read16)(ADDRESS_68K(address + 2))); else val = m68k_read_immediate_32(address); @@ -988,7 +988,7 @@ INLINE void m68ki_write_8(uint32 address, uint32 value) cpu_hook(HOOK_M68K_W, 1, address, value); #endif - temp = &m68ki_cpu.memory_map[((address)>>16)&0xff]; + temp = &m68ki_cpu->memory_map[((address)>>16)&0xff]; if (temp->write8) (*temp->write8)(ADDRESS_68K(address),value); else WRITE_BYTE(temp->base, (address) & 0xffff, value); } @@ -1005,7 +1005,7 @@ INLINE void m68ki_write_16(uint32 address, uint32 value) cpu_hook(HOOK_M68K_W, 2, address, value); #endif - temp = &m68ki_cpu.memory_map[((address)>>16)&0xff]; + temp = &m68ki_cpu->memory_map[((address)>>16)&0xff]; if (temp->write16) (*temp->write16)(ADDRESS_68K(address),value); else *(uint16 *)(temp->base + ((address) & 0xffff)) = value; } @@ -1022,11 +1022,11 @@ INLINE void m68ki_write_32(uint32 address, uint32 value) cpu_hook(HOOK_M68K_W, 4, address, value); #endif - temp = &m68ki_cpu.memory_map[((address)>>16)&0xff]; + temp = &m68ki_cpu->memory_map[((address)>>16)&0xff]; if (temp->write16) (*temp->write16)(ADDRESS_68K(address),value>>16); else *(uint16 *)(temp->base + ((address) & 0xffff)) = value >> 16; - temp = &m68ki_cpu.memory_map[((address + 2)>>16)&0xff]; + temp = &m68ki_cpu->memory_map[((address + 2)>>16)&0xff]; if (temp->write16) (*temp->write16)(ADDRESS_68K(address+2),value&0xffff); else *(uint16 *)(temp->base + ((address + 2) & 0xffff)) = value; } @@ -1306,13 +1306,13 @@ INLINE void m68ki_stack_frame_buserr(uint32 sr) m68ki_push_32(REG_PC); m68ki_push_16(sr); m68ki_push_16(REG_IR); - m68ki_push_32(m68ki_cpu.aerr_address); /* access address */ + m68ki_push_32(m68ki_cpu->aerr_address); /* access address */ /* 0 0 0 0 0 0 0 0 0 0 0 R/W I/N FC * R/W 0 = write, 1 = read * I/N 0 = instruction, 1 = not * FC 3-bit function code */ - m68ki_push_16(m68ki_cpu.aerr_write_mode | CPU_INSTR_MODE | m68ki_cpu.aerr_fc); + m68ki_push_16(m68ki_cpu->aerr_write_mode | CPU_INSTR_MODE | m68ki_cpu->aerr_fc); } #endif @@ -1430,7 +1430,7 @@ INLINE void m68ki_exception_address_error(void) if(CPU_RUN_MODE == RUN_MODE_BERR_AERR_RESET) { CPU_STOPPED = STOP_LEVEL_HALT; - SET_CYCLES(m68ki_cpu.cycle_end - CYC_INSTRUCTION[REG_IR]); + SET_CYCLES(m68ki_cpu->cycle_end - CYC_INSTRUCTION[REG_IR]); return; } CPU_RUN_MODE = RUN_MODE_BERR_AERR_RESET; diff --git a/components/genesis/gwenesis/src/cpus/M68K/m68kops.h b/components/genesis/gwenesis/src/cpus/M68K/m68kops.h index 339d867e..b1a5adbb 100644 --- a/components/genesis/gwenesis/src/cpus/M68K/m68kops.h +++ b/components/genesis/gwenesis/src/cpus/M68K/m68kops.h @@ -7239,7 +7239,7 @@ static void m68k_op_dbf_16(void) USE_CYCLES(CYC_DBCC_F_NOEXP); /* reset idle loop detection */ - m68ki_cpu.poll.detected = 0; + m68ki_cpu->poll.detected = 0; return; } REG_PC += 2; @@ -7263,7 +7263,7 @@ static void m68k_op_dbhi_16(void) USE_CYCLES(CYC_DBCC_F_NOEXP); /* reset idle loop detection */ - m68ki_cpu.poll.detected = 0; + m68ki_cpu->poll.detected = 0; return; } REG_PC += 2; @@ -7290,7 +7290,7 @@ static void m68k_op_dbls_16(void) USE_CYCLES(CYC_DBCC_F_NOEXP); /* reset idle loop detection */ - m68ki_cpu.poll.detected = 0; + m68ki_cpu->poll.detected = 0; return; } REG_PC += 2; @@ -7317,7 +7317,7 @@ static void m68k_op_dbcc_16(void) USE_CYCLES(CYC_DBCC_F_NOEXP); /* reset idle loop detection */ - m68ki_cpu.poll.detected = 0; + m68ki_cpu->poll.detected = 0; return; } REG_PC += 2; @@ -7344,7 +7344,7 @@ static void m68k_op_dbcs_16(void) USE_CYCLES(CYC_DBCC_F_NOEXP); /* reset idle loop detection */ - m68ki_cpu.poll.detected = 0; + m68ki_cpu->poll.detected = 0; return; } REG_PC += 2; @@ -7371,7 +7371,7 @@ static void m68k_op_dbne_16(void) USE_CYCLES(CYC_DBCC_F_NOEXP); /* reset idle loop detection */ - m68ki_cpu.poll.detected = 0; + m68ki_cpu->poll.detected = 0; return; } REG_PC += 2; @@ -7398,7 +7398,7 @@ static void m68k_op_dbeq_16(void) USE_CYCLES(CYC_DBCC_F_NOEXP); /* reset idle loop detection */ - m68ki_cpu.poll.detected = 0; + m68ki_cpu->poll.detected = 0; return; } REG_PC += 2; @@ -7425,7 +7425,7 @@ static void m68k_op_dbvc_16(void) USE_CYCLES(CYC_DBCC_F_NOEXP); /* reset idle loop detection */ - m68ki_cpu.poll.detected = 0; + m68ki_cpu->poll.detected = 0; return; } REG_PC += 2; @@ -7452,7 +7452,7 @@ static void m68k_op_dbvs_16(void) USE_CYCLES(CYC_DBCC_F_NOEXP); /* reset idle loop detection */ - m68ki_cpu.poll.detected = 0; + m68ki_cpu->poll.detected = 0; return; } REG_PC += 2; @@ -7479,7 +7479,7 @@ static void m68k_op_dbpl_16(void) USE_CYCLES(CYC_DBCC_F_NOEXP); /* reset idle loop detection */ - m68ki_cpu.poll.detected = 0; + m68ki_cpu->poll.detected = 0; return; } REG_PC += 2; @@ -7506,7 +7506,7 @@ static void m68k_op_dbmi_16(void) USE_CYCLES(CYC_DBCC_F_NOEXP); /* reset idle loop detection */ - m68ki_cpu.poll.detected = 0; + m68ki_cpu->poll.detected = 0; return; } REG_PC += 2; @@ -7533,7 +7533,7 @@ static void m68k_op_dbge_16(void) USE_CYCLES(CYC_DBCC_F_NOEXP); /* reset idle loop detection */ - m68ki_cpu.poll.detected = 0; + m68ki_cpu->poll.detected = 0; return; } REG_PC += 2; @@ -7560,7 +7560,7 @@ static void m68k_op_dblt_16(void) USE_CYCLES(CYC_DBCC_F_NOEXP); /* reset idle loop detection */ - m68ki_cpu.poll.detected = 0; + m68ki_cpu->poll.detected = 0; return; } REG_PC += 2; @@ -7587,7 +7587,7 @@ static void m68k_op_dbgt_16(void) USE_CYCLES(CYC_DBCC_F_NOEXP); /* reset idle loop detection */ - m68ki_cpu.poll.detected = 0; + m68ki_cpu->poll.detected = 0; return; } REG_PC += 2; @@ -7614,7 +7614,7 @@ static void m68k_op_dble_16(void) USE_CYCLES(CYC_DBCC_F_NOEXP); /* reset idle loop detection */ - m68ki_cpu.poll.detected = 0; + m68ki_cpu->poll.detected = 0; return; } REG_PC += 2; @@ -20970,7 +20970,7 @@ static void m68k_op_stop(void) m68ki_set_sr(new_sr); if (CPU_STOPPED) { - SET_CYCLES(m68ki_cpu.cycle_end - 4*MUL); + SET_CYCLES(m68ki_cpu->cycle_end - 4*MUL); } return; } diff --git a/components/genesis/gwenesis/src/sound/ym2612.c b/components/genesis/gwenesis/src/sound/ym2612.c index fb7f1716..a7e9f636 100644 --- a/components/genesis/gwenesis/src/sound/ym2612.c +++ b/components/genesis/gwenesis/src/sound/ym2612.c @@ -192,11 +192,6 @@ void ym_log(const char *subs, const char *fmt, ...) { #define DT_LEN (1 << DT_BITS) #define DT_MASK (DT_LEN - 1) -/* operator unit */ -#define SIN_BITS 10 -#define SIN_LEN (1<>3) /* sin waveform table in 'decibel' scale */ -static unsigned int sin_tab[SIN_LEN]; +unsigned int *sin_tab; // [SIN_LEN]; /* sustain level table (3dB per step) */ /* bit0, bit1, bit2, bit3, bit4, bit5, bit6 */ @@ -522,140 +517,8 @@ static const UINT8 lfo_pm_output[7*8][8]={ #define SLOT3 1 #define SLOT4 3 -/* struct describing a single operator (SLOT) */ -typedef struct -{ - INT32 *DT; /* detune :dt_tab[DT] */ - UINT8 KSR; /* key scale rate :3-KSR */ - UINT32 ar; /* attack rate */ - UINT32 d1r; /* decay rate */ - UINT32 d2r; /* sustain rate */ - UINT32 rr; /* release rate */ - UINT8 ksr; /* key scale rate :kcode>>(3-KSR) */ - UINT32 mul; /* multiple :ML_TABLE[ML] */ - - /* Phase Generator */ - UINT32 phase; /* phase counter */ - INT32 Incr; /* phase step */ - - /* Envelope Generator */ - UINT8 state; /* phase type */ - UINT32 tl; /* total level: TL << 3 */ - INT32 volume; /* envelope counter */ - UINT32 sl; /* sustain level:sl_table[SL] */ - UINT32 vol_out; /* current output from EG circuit (without AM from LFO) */ - - UINT8 eg_sh_ar; /* (attack state) */ - UINT8 eg_sel_ar; /* (attack state) */ - UINT8 eg_sh_d1r; /* (decay state) */ - UINT8 eg_sel_d1r; /* (decay state) */ - UINT8 eg_sh_d2r; /* (sustain state) */ - UINT8 eg_sel_d2r; /* (sustain state) */ - UINT8 eg_sh_rr; /* (release state) */ - UINT8 eg_sel_rr; /* (release state) */ - - UINT8 ssg; /* SSG-EG waveform */ - UINT8 ssgn; /* SSG-EG negated output */ - - UINT8 key; /* 0=last key was KEY OFF, 1=KEY ON */ - - /* LFO */ - UINT32 AMmask; /* AM enable flag */ - -} FM_SLOT; - -typedef struct -{ - FM_SLOT SLOT[4]; /* four SLOTs (operators) */ - - UINT8 ALGO; /* algorithm */ - UINT8 FB; /* feedback shift */ - INT32 op1_out[2]; /* op1 output for feedback */ - - INT32 *connect1; /* SLOT1 output pointer */ - INT32 *connect3; /* SLOT3 output pointer */ - INT32 *connect2; /* SLOT2 output pointer */ - INT32 *connect4; /* SLOT4 output pointer */ - - INT32 *mem_connect; /* where to put the delayed sample (MEM) */ - INT32 mem_value; /* delayed sample (MEM) value */ - - INT32 pms; /* channel PMS */ - UINT8 ams; /* channel AMS */ - - UINT32 fc; /* fnum,blk */ - UINT8 kcode; /* key code */ - UINT32 block_fnum; /* blk/fnum value (for LFO PM calculations) */ -} FM_CH; - - -typedef struct -{ - UINT16 address; /* address register */ - UINT8 status; /* status flag */ - UINT32 mode; /* mode CSM / 3SLOT */ - UINT8 fn_h; /* freq latch */ - INT32 TA; /* timer a value */ - INT32 TAL; /* timer a base */ - INT32 TAC; /* timer a counter */ - INT32 TB; /* timer b value */ - INT32 TBL; /* timer b base */ - INT32 TBC; /* timer b counter */ - INT32 dt_tab[8][32]; /* DeTune table */ - -} FM_ST; - - -/***********************************************************/ -/* OPN unit */ -/***********************************************************/ - -/* OPN 3slot struct */ -typedef struct -{ - UINT32 fc[3]; /* fnum3,blk3: calculated */ - UINT8 fn_h; /* freq3 latch */ - UINT8 kcode[3]; /* key code */ - UINT32 block_fnum[3]; /* current fnum value for this slot (can be different betweeen slots of one channel in 3slot mode) */ - UINT8 key_csm; /* CSM mode Key-ON flag */ - -} FM_3SLOT; - -/* OPN/A/B common state */ -typedef struct -{ - FM_ST ST; /* general state */ - FM_3SLOT SL3; /* 3 slot mode state */ - unsigned int pan[6*2]; /* fm channels output masks (0xffffffff = enable) */ - - /* EG */ - UINT32 eg_cnt; /* global envelope generator counter */ - UINT32 eg_timer; /* global envelope generator counter works at frequency = chipclock/144/3 */ - - /* LFO */ - UINT8 lfo_cnt; /* current LFO phase (out of 128) */ - UINT32 lfo_timer; /* current LFO phase runs at LFO frequency */ - UINT32 lfo_timer_overflow; /* LFO timer overflows every N samples (depends on LFO frequency) */ - UINT32 LFO_AM; /* current LFO AM step */ - UINT32 LFO_PM; /* current LFO PM step */ - -} FM_OPN; - -/***********************************************************/ -/* YM2612 chip */ -/***********************************************************/ -typedef struct -{ - FM_CH CH[6]; /* channel state */ - UINT8 dacen; /* DAC mode */ - INT32 dacout; /* DAC output */ - FM_OPN OPN; /* OPN state */ - UINT32 divisor; /* sample rate divsor in system clock */ - -} YM2612; - /* emulated chip */ -static YM2612 ym2612; +YM2612 *ym2612 = NULL; /* current chip state */ static INT32 m2,c1,c2; /* Phase Modulation input for operators 2,3,4 */ @@ -664,13 +527,13 @@ static INT32 out_fm[8]; /* outputs of working channels */ static UINT32 bitmask; /* working channels output bitmasking (DAC quantization) */ /* mirror of all OPN registers */ -static uint8_t OPNREGS[512]; +uint8_t *OPNREGS = NULL; // [512]; INLINE void FM_KEYON(FM_CH *CH , int s ) { FM_SLOT *SLOT = &CH->SLOT[s]; - if (!SLOT->key && !ym2612.OPN.SL3.key_csm) + if (!SLOT->key && !ym2612->OPN.SL3.key_csm) { /* restart Phase Generator */ SLOT->phase = 0; @@ -705,7 +568,7 @@ INLINE void FM_KEYOFF(FM_CH *CH , int s ) { FM_SLOT *SLOT = &CH->SLOT[s]; - if (SLOT->key && !ym2612.OPN.SL3.key_csm) + if (SLOT->key && !ym2612->OPN.SL3.key_csm) { if (SLOT->state>EG_REL) { @@ -738,7 +601,7 @@ INLINE void FM_KEYON_CSM(FM_CH *CH , int s ) { FM_SLOT *SLOT = &CH->SLOT[s]; - if (!SLOT->key && !ym2612.OPN.SL3.key_csm) + if (!SLOT->key && !ym2612->OPN.SL3.key_csm) { /* restart Phase Generator */ SLOT->phase = 0; @@ -805,46 +668,46 @@ INLINE void CSMKeyControll(FM_CH *CH) FM_KEYON_CSM(CH,SLOT2); FM_KEYON_CSM(CH,SLOT3); FM_KEYON_CSM(CH,SLOT4); - ym2612.OPN.SL3.key_csm = 1; + ym2612->OPN.SL3.key_csm = 1; } INLINE void INTERNAL_TIMER_A() { - if (ym2612.OPN.ST.mode & 0x01) + if (ym2612->OPN.ST.mode & 0x01) { - ym2612.OPN.ST.TAC--; - if (ym2612.OPN.ST.TAC <= 0) + ym2612->OPN.ST.TAC--; + if (ym2612->OPN.ST.TAC <= 0) { /* set status (if enabled) */ - if (ym2612.OPN.ST.mode & 0x04) - ym2612.OPN.ST.status |= 0x01; + if (ym2612->OPN.ST.mode & 0x04) + ym2612->OPN.ST.status |= 0x01; /* reload the counter */ - ym2612.OPN.ST.TAC = ym2612.OPN.ST.TAL; + ym2612->OPN.ST.TAC = ym2612->OPN.ST.TAL; /* CSM mode auto key on */ - if ((ym2612.OPN.ST.mode & 0xC0) == 0x80) - CSMKeyControll(&ym2612.CH[2]); + if ((ym2612->OPN.ST.mode & 0xC0) == 0x80) + CSMKeyControll(&ym2612->CH[2]); } } } INLINE void INTERNAL_TIMER_B(int step) { - if (ym2612.OPN.ST.mode & 0x02) + if (ym2612->OPN.ST.mode & 0x02) { - ym2612.OPN.ST.TBC-=step; - if (ym2612.OPN.ST.TBC <= 0) + ym2612->OPN.ST.TBC-=step; + if (ym2612->OPN.ST.TBC <= 0) { /* set status (if enabled) */ - if (ym2612.OPN.ST.mode & 0x08) - ym2612.OPN.ST.status |= 0x02; + if (ym2612->OPN.ST.mode & 0x08) + ym2612->OPN.ST.status |= 0x02; /* reload the counter */ - if (ym2612.OPN.ST.TBL) - ym2612.OPN.ST.TBC += ym2612.OPN.ST.TBL; + if (ym2612->OPN.ST.TBL) + ym2612->OPN.ST.TBC += ym2612->OPN.ST.TBL; else - ym2612.OPN.ST.TBC = ym2612.OPN.ST.TBL; + ym2612->OPN.ST.TBC = ym2612->OPN.ST.TBL; } } } @@ -861,33 +724,33 @@ INLINE void set_timers(int v ) /* b1 = load b */ /* b0 = load a */ - if ((ym2612.OPN.ST.mode ^ v) & 0xC0) + if ((ym2612->OPN.ST.mode ^ v) & 0xC0) { /* phase increment need to be recalculated */ - ym2612.CH[2].SLOT[SLOT1].Incr=-1; + ym2612->CH[2].SLOT[SLOT1].Incr=-1; /* CSM mode disabled and CSM key ON active*/ - if (((v & 0xC0) != 0x80) && ym2612.OPN.SL3.key_csm) + if (((v & 0xC0) != 0x80) && ym2612->OPN.SL3.key_csm) { /* CSM Mode Key OFF (verified by Nemesis on real hardware) */ - FM_KEYOFF_CSM(&ym2612.CH[2],SLOT1); - FM_KEYOFF_CSM(&ym2612.CH[2],SLOT2); - FM_KEYOFF_CSM(&ym2612.CH[2],SLOT3); - FM_KEYOFF_CSM(&ym2612.CH[2],SLOT4); - ym2612.OPN.SL3.key_csm = 0; + FM_KEYOFF_CSM(&ym2612->CH[2],SLOT1); + FM_KEYOFF_CSM(&ym2612->CH[2],SLOT2); + FM_KEYOFF_CSM(&ym2612->CH[2],SLOT3); + FM_KEYOFF_CSM(&ym2612->CH[2],SLOT4); + ym2612->OPN.SL3.key_csm = 0; } } /* reload Timers */ - if ((v&1) && !(ym2612.OPN.ST.mode&1)) - ym2612.OPN.ST.TAC = ym2612.OPN.ST.TAL; - if ((v&2) && !(ym2612.OPN.ST.mode&2)) - ym2612.OPN.ST.TBC = ym2612.OPN.ST.TBL; + if ((v&1) && !(ym2612->OPN.ST.mode&1)) + ym2612->OPN.ST.TAC = ym2612->OPN.ST.TAL; + if ((v&2) && !(ym2612->OPN.ST.mode&2)) + ym2612->OPN.ST.TBC = ym2612->OPN.ST.TBL; /* reset Timers flags */ - ym2612.OPN.ST.status &= (~((unsigned int)(v)) >> 4); + ym2612->OPN.ST.status &= (~((unsigned int)(v)) >> 4); - ym2612.OPN.ST.mode = v; + ym2612->OPN.ST.mode = v; } /* set algorithm connection */ @@ -981,7 +844,7 @@ INLINE void setup_connection( FM_CH *CH, int ch ) INLINE void set_det_mul(FM_CH *CH,FM_SLOT *SLOT,int v) { SLOT->mul = (v&0x0f)? (v&0x0f)*2 : 1; - SLOT->DT = ym2612.OPN.ST.dt_tab[(v>>4)&7]; + SLOT->DT = ym2612->OPN.ST.dt_tab[(v>>4)&7]; CH->SLOT[SLOT1].Incr=-1; } @@ -1063,28 +926,28 @@ INLINE void set_sl_rr(FM_SLOT *SLOT,int v) INLINE void advance_lfo() { - if (ym2612.OPN.lfo_timer_overflow) /* LFO enabled ? */ + if (ym2612->OPN.lfo_timer_overflow) /* LFO enabled ? */ { /* increment LFO timer (every samples) */ - ym2612.OPN.lfo_timer ++; + ym2612->OPN.lfo_timer ++; /* when LFO is enabled, one level will last for 108, 77, 71, 67, 62, 44, 8 or 5 samples */ - if (ym2612.OPN.lfo_timer >= ym2612.OPN.lfo_timer_overflow) + if (ym2612->OPN.lfo_timer >= ym2612->OPN.lfo_timer_overflow) { - ym2612.OPN.lfo_timer = 0; + ym2612->OPN.lfo_timer = 0; /* There are 128 LFO steps */ - ym2612.OPN.lfo_cnt = ( ym2612.OPN.lfo_cnt + 1 ) & 127; + ym2612->OPN.lfo_cnt = ( ym2612->OPN.lfo_cnt + 1 ) & 127; /* triangle (inverted) */ /* AM: from 126 to 0 step -2, 0 to 126 step +2 */ - if (ym2612.OPN.lfo_cnt<64) - ym2612.OPN.LFO_AM = (ym2612.OPN.lfo_cnt ^ 63) << 1; + if (ym2612->OPN.lfo_cnt<64) + ym2612->OPN.LFO_AM = (ym2612->OPN.lfo_cnt ^ 63) << 1; else - ym2612.OPN.LFO_AM = (ym2612.OPN.lfo_cnt & 63) << 1; + ym2612->OPN.LFO_AM = (ym2612->OPN.lfo_cnt & 63) << 1; /* PM works with 4 times slower clock */ - ym2612.OPN.LFO_PM = ym2612.OPN.lfo_cnt >> 2; + ym2612->OPN.LFO_PM = ym2612->OPN.lfo_cnt >> 2; } } } @@ -1322,10 +1185,10 @@ INLINE void update_phase_lfo_slot(FM_SLOT *SLOT, INT32 pms, UINT32 block_fnum) { #if GW_TARGET - INT32 lfo_fn_table_index_offset = lfo_pm_table[(((block_fnum & 0x7f0) >> 4) << 7) + pms + (ym2612.OPN.LFO_PM & 0xF)]; - if ( ym2612.OPN.LFO_PM & 0x10) lfo_fn_table_index_offset = - lfo_fn_table_index_offset; + INT32 lfo_fn_table_index_offset = lfo_pm_table[(((block_fnum & 0x7f0) >> 4) << 7) + pms + (ym2612->OPN.LFO_PM & 0xF)]; + if ( ym2612->OPN.LFO_PM & 0x10) lfo_fn_table_index_offset = - lfo_fn_table_index_offset; #else - INT32 lfo_fn_table_index_offset = lfo_pm_table[(((block_fnum & 0x7f0) >> 4) << 8) + pms + ym2612.OPN.LFO_PM]; + INT32 lfo_fn_table_index_offset = lfo_pm_table[(((block_fnum & 0x7f0) >> 4) << 8) + pms + ym2612->OPN.LFO_PM]; #endif if (lfo_fn_table_index_offset) /* LFO phase modulation active */ @@ -1359,10 +1222,10 @@ INLINE void update_phase_lfo_channel(FM_CH *CH) UINT32 block_fnum = CH->block_fnum; #if GW_TARGET - INT32 lfo_fn_table_index_offset = lfo_pm_table[(((block_fnum & 0x7f0) >> 4) << 7) + CH->pms + (ym2612.OPN.LFO_PM & 0xF)]; - if ( ym2612.OPN.LFO_PM & 0x10) lfo_fn_table_index_offset = - lfo_fn_table_index_offset; + INT32 lfo_fn_table_index_offset = lfo_pm_table[(((block_fnum & 0x7f0) >> 4) << 7) + CH->pms + (ym2612->OPN.LFO_PM & 0xF)]; + if ( ym2612->OPN.LFO_PM & 0x10) lfo_fn_table_index_offset = - lfo_fn_table_index_offset; #else - INT32 lfo_fn_table_index_offset = lfo_pm_table[(((block_fnum & 0x7f0) >> 4) << 8) + CH->pms + ym2612.OPN.LFO_PM]; + INT32 lfo_fn_table_index_offset = lfo_pm_table[(((block_fnum & 0x7f0) >> 4) << 8) + CH->pms + ym2612->OPN.LFO_PM]; #endif if (lfo_fn_table_index_offset) /* LFO phase modulation active */ @@ -1486,7 +1349,7 @@ INLINE void chan_calc(FM_CH *CH, int num) { do { - UINT32 AM = ym2612.OPN.LFO_AM >> CH->ams; + UINT32 AM = ym2612->OPN.LFO_AM >> CH->ams; unsigned int eg_out = volume_calc(&CH->SLOT[SLOT1]); m2 = c1 = c2 = mem = 0; @@ -1534,11 +1397,11 @@ INLINE void chan_calc(FM_CH *CH, int num) if(CH->pms) { /* add support for 3 slot mode */ - if ((ym2612.OPN.ST.mode & 0xC0) && (CH == &ym2612.CH[2])) + if ((ym2612->OPN.ST.mode & 0xC0) && (CH == &ym2612->CH[2])) { - update_phase_lfo_slot(&CH->SLOT[SLOT1], CH->pms, ym2612.OPN.SL3.block_fnum[1]); - update_phase_lfo_slot(&CH->SLOT[SLOT2], CH->pms, ym2612.OPN.SL3.block_fnum[2]); - update_phase_lfo_slot(&CH->SLOT[SLOT3], CH->pms, ym2612.OPN.SL3.block_fnum[0]); + update_phase_lfo_slot(&CH->SLOT[SLOT1], CH->pms, ym2612->OPN.SL3.block_fnum[1]); + update_phase_lfo_slot(&CH->SLOT[SLOT2], CH->pms, ym2612->OPN.SL3.block_fnum[2]); + update_phase_lfo_slot(&CH->SLOT[SLOT3], CH->pms, ym2612->OPN.SL3.block_fnum[0]); update_phase_lfo_slot(&CH->SLOT[SLOT4], CH->pms, CH->block_fnum); } else @@ -1574,29 +1437,29 @@ INLINE void OPNWriteMode(int r, int v) case 0x22: /* LFO FREQ (YM2608/YM2610/YM2610B/ym2612) */ if (v&8) /* LFO enabled ? */ { - ym2612.OPN.lfo_timer_overflow = lfo_samples_per_step[v&7]; + ym2612->OPN.lfo_timer_overflow = lfo_samples_per_step[v&7]; } else { /* hold LFO waveform in reset state */ - ym2612.OPN.lfo_timer_overflow = 0; - ym2612.OPN.lfo_timer = 0; - ym2612.OPN.lfo_cnt = 0; - ym2612.OPN.LFO_PM = 0; - ym2612.OPN.LFO_AM = 126; + ym2612->OPN.lfo_timer_overflow = 0; + ym2612->OPN.lfo_timer = 0; + ym2612->OPN.lfo_cnt = 0; + ym2612->OPN.LFO_PM = 0; + ym2612->OPN.LFO_AM = 126; } break; case 0x24: /* timer A High 8*/ - ym2612.OPN.ST.TA = (ym2612.OPN.ST.TA & 0x03)|(((int)v)<<2); - ym2612.OPN.ST.TAL = 1024 - ym2612.OPN.ST.TA; + ym2612->OPN.ST.TA = (ym2612->OPN.ST.TA & 0x03)|(((int)v)<<2); + ym2612->OPN.ST.TAL = 1024 - ym2612->OPN.ST.TA; break; case 0x25: /* timer A Low 2*/ - ym2612.OPN.ST.TA = (ym2612.OPN.ST.TA & 0x3fc)|(v&3); - ym2612.OPN.ST.TAL = 1024 - ym2612.OPN.ST.TA; + ym2612->OPN.ST.TA = (ym2612->OPN.ST.TA & 0x3fc)|(v&3); + ym2612->OPN.ST.TAL = 1024 - ym2612->OPN.ST.TA; break; case 0x26: /* timer B */ - ym2612.OPN.ST.TB = v; - ym2612.OPN.ST.TBL = (256 - v) << 4; + ym2612->OPN.ST.TB = v; + ym2612->OPN.ST.TBL = (256 - v) << 4; break; case 0x27: /* mode, timer control */ set_timers(v); @@ -1605,7 +1468,7 @@ INLINE void OPNWriteMode(int r, int v) c = v & 0x03; if( c == 3 ) break; if (v&0x04) c+=3; /* CH 4-6 */ - CH = &ym2612.CH[c]; + CH = &ym2612->CH[c]; if (v&0x10) FM_KEYON(CH,SLOT1); else FM_KEYOFF(CH,SLOT1); if (v&0x20) FM_KEYON(CH,SLOT2); else FM_KEYOFF(CH,SLOT2); @@ -1630,7 +1493,7 @@ INLINE void OPNWriteReg(int r, int v) if (r >= 0x100) c+=3; - CH = &ym2612.CH[c]; + CH = &ym2612->CH[c]; SLOT = &(CH->SLOT[OPN_SLOT(r)]); @@ -1753,8 +1616,8 @@ INLINE void OPNWriteReg(int r, int v) switch( OPN_SLOT(r) ){ case 0: /* 0xa0-0xa2 : FNUM1 */ { - UINT32 fn = (((UINT32)((ym2612.OPN.ST.fn_h)&7))<<8) + v; - UINT8 blk = ym2612.OPN.ST.fn_h>>3; + UINT32 fn = (((UINT32)((ym2612->OPN.ST.fn_h)&7))<<8) + v; + UINT8 blk = ym2612->OPN.ST.fn_h>>3; /* keyscale code */ CH->kcode = (blk<<2) | opn_fktable[fn >> 7]; /* phase increment counter */ @@ -1767,24 +1630,24 @@ INLINE void OPNWriteReg(int r, int v) break; } case 1: /* 0xa4-0xa6 : FNUM2,BLK */ - ym2612.OPN.ST.fn_h = v&0x3f; + ym2612->OPN.ST.fn_h = v&0x3f; break; case 2: /* 0xa8-0xaa : 3CH FNUM1 */ if(r < 0x100) { - UINT32 fn = (((UINT32)(ym2612.OPN.SL3.fn_h&7))<<8) + v; - UINT8 blk = ym2612.OPN.SL3.fn_h>>3; + UINT32 fn = (((UINT32)(ym2612->OPN.SL3.fn_h&7))<<8) + v; + UINT8 blk = ym2612->OPN.SL3.fn_h>>3; /* keyscale code */ - ym2612.OPN.SL3.kcode[c]= (blk<<2) | opn_fktable[fn >> 7]; + ym2612->OPN.SL3.kcode[c]= (blk<<2) | opn_fktable[fn >> 7]; /* phase increment counter */ - ym2612.OPN.SL3.fc[c] = (fn << 6) >> (7 - blk); - ym2612.OPN.SL3.block_fnum[c] = (blk<<11) | fn; - ym2612.CH[2].SLOT[SLOT1].Incr=-1; + ym2612->OPN.SL3.fc[c] = (fn << 6) >> (7 - blk); + ym2612->OPN.SL3.block_fnum[c] = (blk<<11) | fn; + ym2612->CH[2].SLOT[SLOT1].Incr=-1; } break; case 3: /* 0xac-0xae : 3CH FNUM2,BLK */ if(r < 0x100) - ym2612.OPN.SL3.fn_h = v&0x3f; + ym2612->OPN.SL3.fn_h = v&0x3f; break; } break; @@ -1806,8 +1669,8 @@ INLINE void OPNWriteReg(int r, int v) CH->ams = lfo_ams_depth_shift[(v>>4) & 0x03]; /* PAN : b7 = L, b6 = R */ - // ym2612.OPN.pan[ c*2 ] = (v & 0x80) ? bitmask : 0; - // ym2612.OPN.pan[ c*2+1 ] = (v & 0x40) ? bitmask : 0; + // ym2612->OPN.pan[ c*2 ] = (v & 0x80) ? bitmask : 0; + // ym2612->OPN.pan[ c*2+1 ] = (v & 0x40) ? bitmask : 0; break; } break; @@ -1949,8 +1812,8 @@ static void init_tables(void) { for (i = 0;i <= 31;i++) { - ym2612.OPN.ST.dt_tab[d][i] = (INT32) dt_tab[d*32 + i]; - ym2612.OPN.ST.dt_tab[d+4][i] = -ym2612.OPN.ST.dt_tab[d][i]; + ym2612->OPN.ST.dt_tab[d][i] = (INT32) dt_tab[d*32 + i]; + ym2612->OPN.ST.dt_tab[d+4][i] = -ym2612->OPN.ST.dt_tab[d][i]; } } @@ -1960,7 +1823,7 @@ static void init_tables(void) void YM2612Init(void) { static unsigned init_table_done = 0; - memset(&ym2612, 0, sizeof(YM2612)); + memset(ym2612, 0, sizeof(YM2612)); if (init_table_done == 0) { init_tables(); init_table_done = 1; @@ -1974,30 +1837,30 @@ void YM2612ResetChip(void) int i; - ym2612.OPN.eg_timer = 0; - ym2612.OPN.eg_cnt = 0; + ym2612->OPN.eg_timer = 0; + ym2612->OPN.eg_cnt = 0; - ym2612.OPN.lfo_timer_overflow = 0; - ym2612.OPN.lfo_timer = 0; - ym2612.OPN.lfo_cnt = 0; - ym2612.OPN.LFO_AM = 126; - ym2612.OPN.LFO_PM = 0; + ym2612->OPN.lfo_timer_overflow = 0; + ym2612->OPN.lfo_timer = 0; + ym2612->OPN.lfo_cnt = 0; + ym2612->OPN.LFO_AM = 126; + ym2612->OPN.LFO_PM = 0; - ym2612.OPN.ST.TAC = 0; - ym2612.OPN.ST.TBC = 0; + ym2612->OPN.ST.TAC = 0; + ym2612->OPN.ST.TBC = 0; - ym2612.OPN.SL3.key_csm = 0; + ym2612->OPN.SL3.key_csm = 0; - ym2612.dacen = 0; - ym2612.dacout = 0; + ym2612->dacen = 0; + ym2612->dacout = 0; set_timers(0x30); - ym2612.OPN.ST.TB = 0; - ym2612.OPN.ST.TBL = 256 << 4; - ym2612.OPN.ST.TA = 0; - ym2612.OPN.ST.TAL = 1024; + ym2612->OPN.ST.TB = 0; + ym2612->OPN.ST.TBL = 256 << 4; + ym2612->OPN.ST.TA = 0; + ym2612->OPN.ST.TAL = 1024; - reset_channels(&ym2612.CH[0] , 6 ); + reset_channels(&ym2612->CH[0] , 6 ); for(i = 0xb6 ; i >= 0xb4 ; i-- ) { @@ -2019,28 +1882,28 @@ static inline void YM2612Update(int16_t *buffer, int length) int lt; /* refresh PG increments and EG rates if required */ - refresh_fc_eg_chan(&ym2612.CH[0]); - refresh_fc_eg_chan(&ym2612.CH[1]); + refresh_fc_eg_chan(&ym2612->CH[0]); + refresh_fc_eg_chan(&ym2612->CH[1]); - if (!(ym2612.OPN.ST.mode & 0xC0)) + if (!(ym2612->OPN.ST.mode & 0xC0)) { - refresh_fc_eg_chan(&ym2612.CH[2]); + refresh_fc_eg_chan(&ym2612->CH[2]); } else { /* 3SLOT MODE (operator order is 0,1,3,2) */ - if(ym2612.CH[2].SLOT[SLOT1].Incr==-1) + if(ym2612->CH[2].SLOT[SLOT1].Incr==-1) { - refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT1] , ym2612.OPN.SL3.fc[1] , ym2612.OPN.SL3.kcode[1] ); - refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT2] , ym2612.OPN.SL3.fc[2] , ym2612.OPN.SL3.kcode[2] ); - refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT3] , ym2612.OPN.SL3.fc[0] , ym2612.OPN.SL3.kcode[0] ); - refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT4] , ym2612.CH[2].fc , ym2612.CH[2].kcode ); + refresh_fc_eg_slot(&ym2612->CH[2].SLOT[SLOT1] , ym2612->OPN.SL3.fc[1] , ym2612->OPN.SL3.kcode[1] ); + refresh_fc_eg_slot(&ym2612->CH[2].SLOT[SLOT2] , ym2612->OPN.SL3.fc[2] , ym2612->OPN.SL3.kcode[2] ); + refresh_fc_eg_slot(&ym2612->CH[2].SLOT[SLOT3] , ym2612->OPN.SL3.fc[0] , ym2612->OPN.SL3.kcode[0] ); + refresh_fc_eg_slot(&ym2612->CH[2].SLOT[SLOT4] , ym2612->CH[2].fc , ym2612->CH[2].kcode ); } } - refresh_fc_eg_chan(&ym2612.CH[3]); - refresh_fc_eg_chan(&ym2612.CH[4]); - refresh_fc_eg_chan(&ym2612.CH[5]); + refresh_fc_eg_chan(&ym2612->CH[3]); + refresh_fc_eg_chan(&ym2612->CH[4]); + refresh_fc_eg_chan(&ym2612->CH[5]); /* buffering */ for(i=0; i < length ; i++) @@ -2054,32 +1917,32 @@ static inline void YM2612Update(int16_t *buffer, int length) out_fm[5] = 0; /* update SSG-EG output */ - update_ssg_eg_channels(&ym2612.CH[0]); + update_ssg_eg_channels(&ym2612->CH[0]); /* calculate FM */ - if (!ym2612.dacen) + if (!ym2612->dacen) { - chan_calc(&ym2612.CH[0],6); + chan_calc(&ym2612->CH[0],6); } else { /* DAC Mode */ - out_fm[5] = ym2612.dacout; - chan_calc(&ym2612.CH[0],5); + out_fm[5] = ym2612->dacout; + chan_calc(&ym2612->CH[0],5); } /* advance LFO */ advance_lfo(); /* advance envelope generator */ - ym2612.OPN.eg_timer ++; + ym2612->OPN.eg_timer ++; /* EG is updated every 3 samples */ - if (ym2612.OPN.eg_timer >= 3) + if (ym2612->OPN.eg_timer >= 3) { - ym2612.OPN.eg_timer = 0; - ym2612.OPN.eg_cnt++; - advance_eg_channels(&ym2612.CH[0], ym2612.OPN.eg_cnt); + ym2612->OPN.eg_timer = 0; + ym2612->OPN.eg_cnt++; + advance_eg_channels(&ym2612->CH[0], ym2612->OPN.eg_cnt); } /* 14-bit accumulator channels outputs (range is -8192;+8191) */ if (out_fm[0] > 8191) out_fm[0] = 8191; @@ -2097,18 +1960,18 @@ static inline void YM2612Update(int16_t *buffer, int length) /* stereo DAC channels outputs mixing */ #if 0 - lt = ((out_fm[0]) & ym2612.OPN.pan[0]); - rt = ((out_fm[0]) & ym2612.OPN.pan[1]); - lt += ((out_fm[1]) & ym2612.OPN.pan[2]); - rt += ((out_fm[1]) & ym2612.OPN.pan[3]); - lt += ((out_fm[2]) & ym2612.OPN.pan[4]); - rt += ((out_fm[2]) & ym2612.OPN.pan[5]); - lt += ((out_fm[3]) & ym2612.OPN.pan[6]); - rt += ((out_fm[3]) & ym2612.OPN.pan[7]); - lt += ((out_fm[4]) & ym2612.OPN.pan[8]); - rt += ((out_fm[4]) & ym2612.OPN.pan[9]); - lt += ((out_fm[5]) & ym2612.OPN.pan[10]); - rt += ((out_fm[5]) & ym2612.OPN.pan[11]); + lt = ((out_fm[0]) & ym2612->OPN.pan[0]); + rt = ((out_fm[0]) & ym2612->OPN.pan[1]); + lt += ((out_fm[1]) & ym2612->OPN.pan[2]); + rt += ((out_fm[1]) & ym2612->OPN.pan[3]); + lt += ((out_fm[2]) & ym2612->OPN.pan[4]); + rt += ((out_fm[2]) & ym2612->OPN.pan[5]); + lt += ((out_fm[3]) & ym2612->OPN.pan[6]); + rt += ((out_fm[3]) & ym2612->OPN.pan[7]); + lt += ((out_fm[4]) & ym2612->OPN.pan[8]); + rt += ((out_fm[4]) & ym2612->OPN.pan[9]); + lt += ((out_fm[5]) & ym2612->OPN.pan[10]); + rt += ((out_fm[5]) & ym2612->OPN.pan[11]); #endif lt = out_fm[0]; // rt = out_fm[0]; @@ -2127,20 +1990,20 @@ static inline void YM2612Update(int16_t *buffer, int length) /* CSM mode: if CSM Key ON has occured, CSM Key OFF need to be sent */ /* only if Timer A does not overflow again (i.e CSM Key ON not set again) */ - ym2612.OPN.SL3.key_csm <<= 1; + ym2612->OPN.SL3.key_csm <<= 1; /* timer A control */ INTERNAL_TIMER_A(); /* CSM Mode Key ON still disabled */ - if (ym2612.OPN.SL3.key_csm & 2) + if (ym2612->OPN.SL3.key_csm & 2) { /* CSM Mode Key OFF (verified by Nemesis on real hardware) */ - FM_KEYOFF_CSM(&ym2612.CH[2],SLOT1); - FM_KEYOFF_CSM(&ym2612.CH[2],SLOT2); - FM_KEYOFF_CSM(&ym2612.CH[2],SLOT3); - FM_KEYOFF_CSM(&ym2612.CH[2],SLOT4); - ym2612.OPN.SL3.key_csm = 0; + FM_KEYOFF_CSM(&ym2612->CH[2],SLOT1); + FM_KEYOFF_CSM(&ym2612->CH[2],SLOT2); + FM_KEYOFF_CSM(&ym2612->CH[2],SLOT3); + FM_KEYOFF_CSM(&ym2612->CH[2],SLOT4); + ym2612->OPN.SL3.key_csm = 0; } } @@ -2154,10 +2017,10 @@ void ym2612_run( int target) { return; } int ym2612_prev_index = ym2612_index; - ym2612_index += (target-ym2612_clock) / ym2612.divisor; + ym2612_index += (target-ym2612_clock) / ym2612->divisor; if (ym2612_index > ym2612_prev_index) { YM2612Update(gwenesis_ym2612_buffer + ym2612_prev_index, ym2612_index-ym2612_prev_index); - ym2612_clock = ym2612_index*ym2612.divisor; + ym2612_clock = ym2612_index*ym2612->divisor; } else { ym2612_index = ym2612_prev_index; @@ -2181,30 +2044,30 @@ void YM2612Write(unsigned int a, unsigned int v, int target) switch( a ) { case 0: /* address port 0 */ - ym2612.OPN.ST.address = v; + ym2612->OPN.ST.address = v; break; case 2: /* address port 1 */ - ym2612.OPN.ST.address = v | 0x100; + ym2612->OPN.ST.address = v | 0x100; break; default: /* data port */ { - int addr = ym2612.OPN.ST.address; /* verified by Nemesis on real YM2612 */ + int addr = ym2612->OPN.ST.address; /* verified by Nemesis on real YM2612 */ switch( addr & 0x1f0 ) { case 0x20: /* 0x20-0x2f Mode */ switch( addr ) { case 0x2a: /* DAC data (ym2612) */ - ym2612.dacout =((int)v - 0x80) << 6; /* convert to 14-bit signed output */ - //ym2612.dacout = ((int)v - 0x80) * 64; /* convert to signed output */ - //printf("WriteDAC : %x:%x\n",v,ym2612.dacout); + ym2612->dacout =((int)v - 0x80) << 6; /* convert to 14-bit signed output */ + //ym2612->dacout = ((int)v - 0x80) * 64; /* convert to signed output */ + //printf("WriteDAC : %x:%x\n",v,ym2612->dacout); break; case 0x2b: /* DAC Sel (ym2612) */ /* b7 = dac enable */ - //printf("WriteDAC : %x:%x\n",v,ym2612.dacout); - ym2612.dacen = v & 0x80; + //printf("WriteDAC : %x:%x\n",v,ym2612->dacout); + ym2612->dacen = v & 0x80; break; default: /* OPN section */ /* write register */ @@ -2225,8 +2088,8 @@ unsigned int YM2612Read(int target) // //Sync if (GWENESIS_AUDIO_ACCURATE == 1) ym2612_run(target); - ym_log(__FUNCTION__, "%02x",ym2612.OPN.ST.status & 0xff); - return ym2612.OPN.ST.status & 0xff; + ym_log(__FUNCTION__, "%02x",ym2612->OPN.ST.status & 0xff); + return ym2612->OPN.ST.status & 0xff; } @@ -2240,12 +2103,12 @@ void YM2612Config(unsigned char dac_bits) //,unsigned int AUDIO_FREQ_DIVISOR) /* update L/R panning bitmasks */ for (i=0; i<2*6; i++) { - if (ym2612.OPN.pan[i]) + if (ym2612->OPN.pan[i]) { - ym2612.OPN.pan[i] = bitmask; + ym2612->OPN.pan[i] = bitmask; } } - ym2612.divisor = AUDIO_FREQ_DIVISOR; + ym2612->divisor = AUDIO_FREQ_DIVISOR; } void YM2612SaveRegs(uint8_t *regs) @@ -2265,12 +2128,12 @@ void YM2612LoadRegs(uint8_t *regs) } /* restore outputs connections */ - setup_connection(&ym2612.CH[0],0); - setup_connection(&ym2612.CH[1],1); - setup_connection(&ym2612.CH[2],2); - setup_connection(&ym2612.CH[3],3); - setup_connection(&ym2612.CH[4],4); - setup_connection(&ym2612.CH[5],5); + setup_connection(&ym2612->CH[0],0); + setup_connection(&ym2612->CH[1],1); + setup_connection(&ym2612->CH[2],2); + setup_connection(&ym2612->CH[3],3); + setup_connection(&ym2612->CH[4],4); + setup_connection(&ym2612->CH[5],5); } @@ -2282,7 +2145,7 @@ int YM2612LoadContext(unsigned char *state) int bufferptr = 0; /* restore YM2612 context */ - load_param(&ym2612, sizeof(ym2612)); + load_param(ym2612, sizeof(YM2612)); /* restore DT table address pointer for each channel slots */ for (c=0; c<6; c++) @@ -2291,17 +2154,17 @@ int YM2612LoadContext(unsigned char *state) { load_param(&index,sizeof(index)); bufferptr += sizeof(index); - ym2612.CH[c].SLOT[s].DT = ym2612.OPN.ST.dt_tab[index&7]; + ym2612->CH[c].SLOT[s].DT = ym2612->OPN.ST.dt_tab[index&7]; } } /* restore outputs connections */ - setup_connection(&ym2612.CH[0],0); - setup_connection(&ym2612.CH[1],1); - setup_connection(&ym2612.CH[2],2); - setup_connection(&ym2612.CH[3],3); - setup_connection(&ym2612.CH[4],4); - setup_connection(&ym2612.CH[5],5); + setup_connection(&ym2612->CH[0],0); + setup_connection(&ym2612->CH[1],1); + setup_connection(&ym2612->CH[2],2); + setup_connection(&ym2612->CH[3],3); + setup_connection(&ym2612->CH[4],4); + setup_connection(&ym2612->CH[5],5); return bufferptr; } @@ -2314,14 +2177,14 @@ int YM2612SaveContext(unsigned char *state) int bufferptr = 0; /* save YM2612 context */ - save_param(&ym2612, sizeof(ym2612)); + save_param(ym2612, sizeof(YM2612)); /* save DT table index for each channel slots */ for (c=0; c<6; c++) { for (s=0; s<4; s++) { - index = (ym2612.CH[c].SLOT[s].DT - ym2612.OPN.ST.dt_tab[0]) >> 5; + index = (ym2612->CH[c].SLOT[s].DT - ym2612->OPN.ST.dt_tab[0]) >> 5; save_param(&index,sizeof(index)); bufferptr += sizeof(index); } @@ -2334,7 +2197,7 @@ int YM2612SaveContext(unsigned char *state) void gwenesis_ym2612_save_state() { SaveState* state; state = saveGwenesisStateOpenForWrite("ym2612"); - saveGwenesisStateSetBuffer(state, "ym2612", &ym2612, sizeof(ym2612)); + saveGwenesisStateSetBuffer(state, "ym2612", ym2612, sizeof(YM2612)); saveGwenesisStateSet(state, "m2", m2); saveGwenesisStateSet(state, "c1", c1); saveGwenesisStateSet(state, "c2", c2); @@ -2346,7 +2209,7 @@ void gwenesis_ym2612_save_state() { void gwenesis_ym2612_load_state() { SaveState* state = saveGwenesisStateOpenForRead("ym2612"); - saveGwenesisStateGetBuffer(state, "ym2612", &ym2612, sizeof(ym2612)); + saveGwenesisStateGetBuffer(state, "ym2612", ym2612, sizeof(YM2612)); m2 = saveGwenesisStateGet(state, "m2"); c1 = saveGwenesisStateGet(state, "c1"); c2 = saveGwenesisStateGet(state, "c2"); diff --git a/components/genesis/gwenesis/src/sound/ym2612.h b/components/genesis/gwenesis/src/sound/ym2612.h index bd0d3631..305feb02 100644 --- a/components/genesis/gwenesis/src/sound/ym2612.h +++ b/components/genesis/gwenesis/src/sound/ym2612.h @@ -39,7 +39,150 @@ extern uint8_t *lfo_pm_table; extern int32_t *lfo_pm_table; #endif +/* operator unit */ +#define SIN_BITS 10 +#define SIN_LEN (1< + +/* struct describing a single operator (SLOT) */ +typedef struct +{ + int32_t *DT; /* detune :dt_tab[DT] */ + uint8_t KSR; /* key scale rate :3-KSR */ + uint32_t ar; /* attack rate */ + uint32_t d1r; /* decay rate */ + uint32_t d2r; /* sustain rate */ + uint32_t rr; /* release rate */ + uint8_t ksr; /* key scale rate :kcode>>(3-KSR) */ + uint32_t mul; /* multiple :ML_TABLE[ML] */ + + /* Phase Generator */ + uint32_t phase; /* phase counter */ + int32_t Incr; /* phase step */ + + /* Envelope Generator */ + uint8_t state; /* phase type */ + uint32_t tl; /* total level: TL << 3 */ + int32_t volume; /* envelope counter */ + uint32_t sl; /* sustain level:sl_table[SL] */ + uint32_t vol_out; /* current output from EG circuit (without AM from LFO) */ + + uint8_t eg_sh_ar; /* (attack state) */ + uint8_t eg_sel_ar; /* (attack state) */ + uint8_t eg_sh_d1r; /* (decay state) */ + uint8_t eg_sel_d1r; /* (decay state) */ + uint8_t eg_sh_d2r; /* (sustain state) */ + uint8_t eg_sel_d2r; /* (sustain state) */ + uint8_t eg_sh_rr; /* (release state) */ + uint8_t eg_sel_rr; /* (release state) */ + + uint8_t ssg; /* SSG-EG waveform */ + uint8_t ssgn; /* SSG-EG negated output */ + + uint8_t key; /* 0=last key was KEY OFF, 1=KEY ON */ + + /* LFO */ + uint32_t AMmask; /* AM enable flag */ + +} FM_SLOT; + +typedef struct +{ + FM_SLOT SLOT[4]; /* four SLOTs (operators) */ + + uint8_t ALGO; /* algorithm */ + uint8_t FB; /* feedback shift */ + int32_t op1_out[2]; /* op1 output for feedback */ + + int32_t *connect1; /* SLOT1 output pointer */ + int32_t *connect3; /* SLOT3 output pointer */ + int32_t *connect2; /* SLOT2 output pointer */ + int32_t *connect4; /* SLOT4 output pointer */ + + int32_t *mem_connect; /* where to put the delayed sample (MEM) */ + int32_t mem_value; /* delayed sample (MEM) value */ + + int32_t pms; /* channel PMS */ + uint8_t ams; /* channel AMS */ + + uint32_t fc; /* fnum,blk */ + uint8_t kcode; /* key code */ + uint32_t block_fnum; /* blk/fnum value (for LFO PM calculations) */ +} FM_CH; + + +typedef struct +{ + uint16_t address; /* address register */ + uint8_t status; /* status flag */ + uint32_t mode; /* mode CSM / 3SLOT */ + uint8_t fn_h; /* freq latch */ + int32_t TA; /* timer a value */ + int32_t TAL; /* timer a base */ + int32_t TAC; /* timer a counter */ + int32_t TB; /* timer b value */ + int32_t TBL; /* timer b base */ + int32_t TBC; /* timer b counter */ + int32_t dt_tab[8][32]; /* DeTune table */ + +} FM_ST; + + +/***********************************************************/ +/* OPN unit */ +/***********************************************************/ + +/* OPN 3slot struct */ +typedef struct +{ + uint32_t fc[3]; /* fnum3,blk3: calculated */ + uint8_t fn_h; /* freq3 latch */ + uint8_t kcode[3]; /* key code */ + uint32_t block_fnum[3]; /* current fnum value for this slot (can be different betweeen slots of one channel in 3slot mode) */ + uint8_t key_csm; /* CSM mode Key-ON flag */ + +} FM_3SLOT; + +/* OPN/A/B common state */ +typedef struct +{ + FM_ST ST; /* general state */ + FM_3SLOT SL3; /* 3 slot mode state */ + unsigned int pan[6*2]; /* fm channels output masks (0xffffffff = enable) */ + + /* EG */ + uint32_t eg_cnt; /* global envelope generator counter */ + uint32_t eg_timer; /* global envelope generator counter works at frequency = chipclock/144/3 */ + + /* LFO */ + uint8_t lfo_cnt; /* current LFO phase (out of 128) */ + uint32_t lfo_timer; /* current LFO phase runs at LFO frequency */ + uint32_t lfo_timer_overflow; /* LFO timer overflows every N samples (depends on LFO frequency) */ + uint32_t LFO_AM; /* current LFO AM step */ + uint32_t LFO_PM; /* current LFO PM step */ + +} FM_OPN; + +/***********************************************************/ +/* YM2612 chip */ +/***********************************************************/ +typedef struct +{ + FM_CH CH[6]; /* channel state */ + uint8_t dacen; /* DAC mode */ + int32_t dacout; /* DAC output */ + FM_OPN OPN; /* OPN state */ + uint32_t divisor; /* sample rate divsor in system clock */ + +} YM2612; + +extern YM2612 *ym2612; /* pointer to the YM2612 state */ //extern void YM2612LoadRegs(uint8_t *regs); //extern void YM2612SaveRegs(uint8_t *regs); diff --git a/components/genesis/gwenesis/src/vdp/gwenesis_vdp.h b/components/genesis/gwenesis/src/vdp/gwenesis_vdp.h index 1a938897..d659db3d 100644 --- a/components/genesis/gwenesis/src/vdp/gwenesis_vdp.h +++ b/components/genesis/gwenesis/src/vdp/gwenesis_vdp.h @@ -113,6 +113,11 @@ __license__ = "GPLv3" #define SHI_IS_SHADOW(x) (!((x) & 0x80)) #define SHI_IS_HIGHLIGHT(x) ((x) & 0x40) +enum { PIX_OVERFLOW = 32 }; + +extern uint8_t *render_buffer; // [SCREEN_WIDTH + PIX_OVERFLOW*2]; +extern uint8_t *sprite_buffer; // [SCREEN_WIDTH + PIX_OVERFLOW*2]; + void gwenesis_vdp_reset(); void gwenesis_vdp_set_hblank(); void gwenesis_vdp_clear_hblank(); diff --git a/components/genesis/gwenesis/src/vdp/gwenesis_vdp_gfx.c b/components/genesis/gwenesis/src/vdp/gwenesis_vdp_gfx.c index 8ca4d506..a9e295d4 100644 --- a/components/genesis/gwenesis/src/vdp/gwenesis_vdp_gfx.c +++ b/components/genesis/gwenesis/src/vdp/gwenesis_vdp_gfx.c @@ -31,18 +31,25 @@ __license__ = "GPLv3" #pragma GCC optimize("Ofast") +extern unsigned short *CRAM; // [CRAM_MAX_SIZE]; // CRAM - Palettes +extern unsigned char *SAT_CACHE; // [SAT_CACHE_MAX_SIZE]; // Sprite cache +extern unsigned char *gwenesis_vdp_regs; // [REG_SIZE]; // Registers +extern unsigned short *fifo; // [FIFO_SIZE]; // Fifo +extern unsigned short *CRAM565; // [CRAM_MAX_SIZE * 4]; // CRAM - Palettes +extern unsigned short *VSRAM; // [VSRAM_MAX_SIZE]; // VSRAM - Scrolling + // typedef unsigned char uint8_t; // typedef unsigned short uint16_t; // typedef unsigned int uint32_t; extern unsigned char *VRAM; -extern unsigned short CRAM[]; // CRAM - Palettes -extern unsigned char SAT_CACHE[]__attribute__((aligned(4))); // Sprite cache -extern unsigned char gwenesis_vdp_regs[]; // Registers +// extern unsigned short CRAM[]; // CRAM - Palettes +// extern unsigned char SAT_CACHE[]__attribute__((aligned(4))); // Sprite cache +// extern unsigned char gwenesis_vdp_regs[]; // Registers -extern unsigned short CRAM565[]; // CRAM - Palettes +// extern unsigned short CRAM565[]; // CRAM - Palettes -extern unsigned short VSRAM[]; // VSRAM - Scrolling +// extern unsigned short VSRAM[]; // VSRAM - Scrolling // Define screen buffers for embedded 565 format static uint8_t *screen_buffer_line=0; @@ -52,10 +59,8 @@ static uint8_t *screen_buffer=0; // wasting time and code in clipping. The maximum object is a 4x4 sprite, // so 32 pixels (on both side) is enough. -enum { PIX_OVERFLOW = 32 }; - -static uint8_t render_buffer[SCREEN_WIDTH + PIX_OVERFLOW*2]; -static uint8_t sprite_buffer[SCREEN_WIDTH + PIX_OVERFLOW*2]; +uint8_t *render_buffer=NULL; // [SCREEN_WIDTH + PIX_OVERFLOW*2]; +uint8_t *sprite_buffer=NULL; // [SCREEN_WIDTH + PIX_OVERFLOW*2]; // Define VIDEO MODE static int mode_h40; diff --git a/components/genesis/gwenesis/src/vdp/gwenesis_vdp_mem.c b/components/genesis/gwenesis/src/vdp/gwenesis_vdp_mem.c index 857b2730..e3d11cc2 100644 --- a/components/genesis/gwenesis/src/vdp/gwenesis_vdp_mem.c +++ b/components/genesis/gwenesis/src/vdp/gwenesis_vdp_mem.c @@ -74,12 +74,19 @@ void vdpm_log(const char *subs, const char *fmt, ...) { unsigned char *VRAM; -unsigned short CRAM[CRAM_MAX_SIZE]; // CRAM - Palettes -unsigned char SAT_CACHE[SAT_CACHE_MAX_SIZE]; // Sprite cache -unsigned char gwenesis_vdp_regs[REG_SIZE]; // Registers -unsigned short fifo[FIFO_SIZE]; // Fifo -unsigned short CRAM565[CRAM_MAX_SIZE * 4]; // CRAM - Palettes -unsigned short VSRAM[VSRAM_MAX_SIZE]; // VSRAM - Scrolling +/* unsigned short CRAM[CRAM_MAX_SIZE]; // CRAM - Palettes */ +/* unsigned char SAT_CACHE[SAT_CACHE_MAX_SIZE]; // Sprite cache */ +/* unsigned char gwenesis_vdp_regs[REG_SIZE]; // Registers */ +/* unsigned short fifo[FIFO_SIZE]; // Fifo */ +/* unsigned short CRAM565[CRAM_MAX_SIZE * 4]; // CRAM - Palettes */ +/* unsigned short VSRAM[VSRAM_MAX_SIZE]; // VSRAM - Scrolling */ + +unsigned short *CRAM = NULL; // [CRAM_MAX_SIZE]; // CRAM - Palettes +unsigned char *SAT_CACHE = NULL; // [SAT_CACHE_MAX_SIZE]; // Sprite cache +unsigned char *gwenesis_vdp_regs = NULL; // [REG_SIZE]; // Registers +unsigned short *fifo = NULL; // [FIFO_SIZE]; // Fifo +unsigned short *CRAM565 = NULL; // [CRAM_MAX_SIZE * 4]; // CRAM - Palettes +unsigned short *VSRAM = NULL; // [VSRAM_MAX_SIZE]; // VSRAM - Scrolling // Define VDP control code and set initial code static unsigned char code_reg = 0; @@ -157,11 +164,11 @@ int m68k_irq_acked(int irq) { void gwenesis_vdp_reset() { memset(VRAM, 0, VRAM_MAX_SIZE); - memset(SAT_CACHE, 0, sizeof(SAT_CACHE)); - memset(CRAM, 0, sizeof(CRAM)); - memset(CRAM565, 0, sizeof(CRAM565)); - memset(VSRAM, 0, sizeof(VSRAM)); - memset(gwenesis_vdp_regs, 0, sizeof(gwenesis_vdp_regs)); + memset(SAT_CACHE, 0, SAT_CACHE_MAX_SIZE); + memset(CRAM, 0, CRAM_MAX_SIZE * sizeof(unsigned short)); + memset(CRAM565, 0, CRAM_MAX_SIZE * 4 * sizeof(unsigned short)); + memset(VSRAM, 0, VSRAM_MAX_SIZE * sizeof(unsigned short)); + memset(gwenesis_vdp_regs, 0, REG_SIZE); command_word_pending = 0; address_reg = 0; code_reg = 0; @@ -975,12 +982,12 @@ void gwenesis_vdp_mem_save_state() { state = saveGwenesisStateOpenForWrite("vdp_mem"); saveGwenesisStateSetBuffer(state, "VRAM", VRAM, VRAM_MAX_SIZE); - saveGwenesisStateSetBuffer(state, "CRAM", CRAM, sizeof(CRAM)); - saveGwenesisStateSetBuffer(state, "SAT_CACHE", SAT_CACHE, sizeof(SAT_CACHE)); - saveGwenesisStateSetBuffer(state, "gwenesis_vdp_regs", gwenesis_vdp_regs, sizeof(gwenesis_vdp_regs)); - saveGwenesisStateSetBuffer(state, "fifo", fifo, sizeof(fifo)); - saveGwenesisStateSetBuffer(state, "CRAM565", CRAM565, sizeof(CRAM565)); - saveGwenesisStateSetBuffer(state, "VSRAM", VSRAM, sizeof(VSRAM)); + saveGwenesisStateSetBuffer(state, "CRAM", CRAM, CRAM_MAX_SIZE*sizeof(uint16_t)); + saveGwenesisStateSetBuffer(state, "SAT_CACHE", SAT_CACHE, SAT_CACHE_MAX_SIZE); + saveGwenesisStateSetBuffer(state, "gwenesis_vdp_regs", gwenesis_vdp_regs, REG_SIZE); + saveGwenesisStateSetBuffer(state, "fifo", fifo, FIFO_SIZE*sizeof(uint16_t)); + saveGwenesisStateSetBuffer(state, "CRAM565", CRAM565, CRAM_MAX_SIZE * 4 * sizeof(uint16_t) ); + saveGwenesisStateSetBuffer(state, "VSRAM", VSRAM, VSRAM_MAX_SIZE*sizeof(uint16_t)); saveGwenesisStateSet(state, "code_reg", code_reg); saveGwenesisStateSet(state, "address_reg", address_reg); saveGwenesisStateSet(state, "command_word_pending", command_word_pending); @@ -995,12 +1002,12 @@ void gwenesis_vdp_mem_load_state() { SaveState* state = saveGwenesisStateOpenForRead("vdp_mem"); saveGwenesisStateGetBuffer(state, "VRAM", VRAM, VRAM_MAX_SIZE); - saveGwenesisStateGetBuffer(state, "CRAM", CRAM, sizeof(CRAM)); - saveGwenesisStateGetBuffer(state, "SAT_CACHE", SAT_CACHE, sizeof(SAT_CACHE)); - saveGwenesisStateGetBuffer(state, "gwenesis_vdp_regs", gwenesis_vdp_regs, sizeof(gwenesis_vdp_regs)); - saveGwenesisStateGetBuffer(state, "fifo", fifo, sizeof(fifo)); - saveGwenesisStateGetBuffer(state, "CRAM565", CRAM565, sizeof(CRAM565)); - saveGwenesisStateGetBuffer(state, "VSRAM", VSRAM, sizeof(VSRAM)); + saveGwenesisStateGetBuffer(state, "CRAM", CRAM, CRAM_MAX_SIZE*sizeof(uint16_t)); + saveGwenesisStateGetBuffer(state, "SAT_CACHE", SAT_CACHE, SAT_CACHE_MAX_SIZE); + saveGwenesisStateGetBuffer(state, "gwenesis_vdp_regs", gwenesis_vdp_regs, REG_SIZE); + saveGwenesisStateGetBuffer(state, "fifo", fifo, FIFO_SIZE*sizeof(uint16_t)); + saveGwenesisStateGetBuffer(state, "CRAM565", CRAM565, CRAM_MAX_SIZE * 4 * sizeof(uint16_t) ); + saveGwenesisStateGetBuffer(state, "VSRAM", VSRAM, VSRAM_MAX_SIZE*sizeof(uint16_t)); code_reg = saveGwenesisStateGet(state, "code_reg"); address_reg = saveGwenesisStateGet(state, "address_reg"); command_word_pending = saveGwenesisStateGet(state, "command_word_pending"); diff --git a/components/genesis/include/genesis.hpp b/components/genesis/include/genesis.hpp index 54491fc2..7f4cfb52 100644 --- a/components/genesis/include/genesis.hpp +++ b/components/genesis/include/genesis.hpp @@ -3,11 +3,37 @@ #include #include #include +#include +#include +#include "genesis_shared_memory.hpp" +#include "z80_shared_memory.hpp" +#include "box-emu.hpp" -void reset_genesis(); +#ifdef __cplusplus +extern "C" { +#endif + +// Initialize the Genesis emulator void init_genesis(uint8_t *romdata, size_t rom_data_size); + +// Reset the Genesis emulator +void reset_genesis(); + +// Load a Genesis save state void load_genesis(std::string_view save_path); + +// Save a Genesis save state void save_genesis(std::string_view save_path); + +// Run the Genesis emulator void run_genesis_rom(); + +// Deinitialize the Genesis emulator void deinit_genesis(); + +// Get the Genesis video buffer std::vector get_genesis_video_buffer(); + +#ifdef __cplusplus +} +#endif diff --git a/components/genesis/include/genesis_shared_memory.hpp b/components/genesis/include/genesis_shared_memory.hpp new file mode 100644 index 00000000..6add4254 --- /dev/null +++ b/components/genesis/include/genesis_shared_memory.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include +#include + +#include "shared_memory.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Initialize Genesis shared memory and hardware components +void genesis_init_shared_memory(void); + +// Free Genesis shared memory +void genesis_free_shared_memory(void); + +// Get pointers to shared memory regions +void genesis_get_memory_regions(uint8_t** vram, uint8_t** m68k_ram, uint8_t** z80_ram, + int32_t** lfo_pm_table, int** tl_tab, int16_t** audio_buffer, + uint16_t** cram, uint16_t** vsram, uint8_t** sat_cache, + uint8_t** fifo, uint8_t** vdp_regs); + +#ifdef __cplusplus +} +#endif diff --git a/components/genesis/include/z80_shared_memory.hpp b/components/genesis/include/z80_shared_memory.hpp new file mode 100644 index 00000000..4a9d765d --- /dev/null +++ b/components/genesis/include/z80_shared_memory.hpp @@ -0,0 +1,18 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +void z80_init_shared_memory(void); +void z80_free_shared_memory(void); +void z80_get_memory_regions(uint8_t** cycles_table, uint8_t** cycles_cb_table, uint8_t** cycles_ed_table, + uint8_t** cycles_xx_table, uint8_t** cycles_xxcb_table, uint8_t** zs_table, + uint8_t** pzs_table, uint16_t** daa_table); + +#ifdef __cplusplus +} +#endif diff --git a/components/genesis/src/genesis.cpp b/components/genesis/src/genesis.cpp index c97a6e5d..3af48536 100644 --- a/components/genesis/src/genesis.cpp +++ b/components/genesis/src/genesis.cpp @@ -2,6 +2,8 @@ #pragma GCC optimize("Ofast") +#include "genesis_shared_memory.hpp" + extern "C" { /* Gwenesis Emulator */ #include "m68k.h" @@ -25,7 +27,7 @@ static constexpr size_t GENESIS_SCREEN_WIDTH = 320; static constexpr size_t GENESIS_VISIBLE_HEIGHT = 224; static constexpr size_t PALETTE_SIZE = 256; -static uint16_t palette[PALETTE_SIZE]; +static uint16_t *palette = nullptr; static int frame_counter = 0; static uint16_t muteFrameCount = 0; @@ -60,9 +62,9 @@ int32_t *lfo_pm_table = nullptr; // 128*8*32 signed int *tl_tab = nullptr; // 13*2*TL_RES_LEN (13*2*256) -extern unsigned char gwenesis_vdp_regs[0x20]; +extern unsigned char *gwenesis_vdp_regs; // [0x20]; extern unsigned int gwenesis_vdp_status; -extern unsigned short CRAM565[256]; +extern unsigned short *CRAM565; // [256]; extern unsigned int screen_width, screen_height; extern int hint_pending; @@ -146,12 +148,23 @@ void reset_genesis() { static void init(uint8_t *romdata, size_t rom_data_size) { static bool initialized = false; + + VRAM = (uint8_t*)shared_malloc(VRAM_MAX_SIZE); // 0x10000 (64kB) for VRAM + M68K_RAM = (uint8_t*)shared_malloc(MAX_RAM_SIZE); // 0x10000 (64kB) for M68K RAM + // ZRAM = (uint8_t*)shared_malloc(MAX_Z80_RAM_SIZE); // 0x2000 (8kB) for Z80 RAM + + palette = (uint16_t*)shared_malloc(sizeof(uint16_t) * PALETTE_SIZE); + // gwenesis_sn76489_buffer = (int16_t*)shared_malloc(AUDIO_BUFFER_LENGTH * sizeof(int16_t)); + // gwenesis_ym2612_buffer = (int16_t*)shared_malloc(AUDIO_BUFFER_LENGTH * sizeof(int16_t)); + + genesis_init_shared_memory(); + if (!initialized) { - VRAM = (uint8_t*)heap_caps_malloc(VRAM_MAX_SIZE, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); gwenesis_sn76489_buffer = (int16_t*)heap_caps_malloc(AUDIO_BUFFER_LENGTH * sizeof(int16_t), MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); gwenesis_ym2612_buffer = (int16_t*)heap_caps_malloc(AUDIO_BUFFER_LENGTH * sizeof(int16_t), MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); - M68K_RAM = (uint8_t*)heap_caps_malloc(MAX_RAM_SIZE, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); - ZRAM = (uint8_t*)heap_caps_malloc(MAX_Z80_RAM_SIZE, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); + // VRAM = (uint8_t*)heap_caps_malloc(VRAM_MAX_SIZE, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); // 0x10000 (64kB) for VRAM + // M68K_RAM = (uint8_t*)heap_caps_malloc(MAX_RAM_SIZE, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); // 0x10000 (64kB) for M68K RAM + ZRAM = (uint8_t*)heap_caps_malloc(MAX_Z80_RAM_SIZE, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); // 0x2000 (8kB) for Z80 RAM lfo_pm_table = (int32_t*)heap_caps_malloc(128*8*32 * sizeof(int32_t), MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); tl_tab = (signed int*)heap_caps_malloc(13*2*256 * sizeof(signed int), MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); } @@ -305,7 +318,7 @@ void IRAM_ATTR run_genesis_rom() { } // reset m68k cycles to the begin of next frame cycle - m68k.cycles -= system_clock; + m68k->cycles -= system_clock; if (drawFrame) { // copy the palette @@ -386,4 +399,5 @@ std::vector get_genesis_video_buffer() { void deinit_genesis() { BoxEmu::get().audio_sample_rate(48000); + shared_mem_clear(); } diff --git a/components/genesis/src/genesis_shared_memory.cpp b/components/genesis/src/genesis_shared_memory.cpp new file mode 100644 index 00000000..c21095aa --- /dev/null +++ b/components/genesis/src/genesis_shared_memory.cpp @@ -0,0 +1,49 @@ +#include "genesis_shared_memory.hpp" +#include "shared_memory.h" +#include "esp_log.h" + +#include + +extern "C" { +#include "m68k.h" +#include "ym2612.h" +#include "gwenesis_bus.h" +#include "gwenesis_vdp.h" +} + +static const char *TAG = "genesis_shared_memory"; + +extern unsigned short *CRAM; // [CRAM_MAX_SIZE]; // CRAM - Palettes +extern unsigned char *SAT_CACHE; // [SAT_CACHE_MAX_SIZE]; // Sprite cache +extern unsigned char *gwenesis_vdp_regs; // [REG_SIZE]; // Registers +extern unsigned short *fifo; // [FIFO_SIZE]; // Fifo +extern unsigned short *CRAM565; // [CRAM_MAX_SIZE * 4]; // CRAM - Palettes +extern unsigned short *VSRAM; // [VSRAM_MAX_SIZE]; // VSRAM - Scrolling + +void genesis_init_shared_memory(void) { + // allocate m68k cpu state in shared memory + m68k = (m68ki_cpu_core*)shared_malloc(sizeof(m68ki_cpu_core)); + if (!m68k) { + ESP_LOGE(TAG, "Failed to allocate M68K CPU state"); + return; + } + + ym2612 = (YM2612*)shared_malloc(sizeof(YM2612)); + OPNREGS = (uint8_t*)shared_malloc(512); + sin_tab = (unsigned int*)shared_malloc(SIN_LEN * sizeof(unsigned int)); + + render_buffer = (uint8_t*)shared_malloc(SCREEN_WIDTH + PIX_OVERFLOW*2); + sprite_buffer = (uint8_t*)shared_malloc(SCREEN_WIDTH + PIX_OVERFLOW*2); + + CRAM = (uint16_t*)shared_malloc(CRAM_MAX_SIZE * sizeof(uint16_t)); + SAT_CACHE = (uint8_t*)shared_malloc(SAT_CACHE_MAX_SIZE); + gwenesis_vdp_regs = (uint8_t*)shared_malloc(REG_SIZE); + fifo = (uint16_t*)shared_malloc(FIFO_SIZE * sizeof(uint16_t)); + CRAM565 = (uint16_t*)shared_malloc(CRAM_MAX_SIZE * 4 * sizeof(uint16_t)); + VSRAM = (uint16_t*)shared_malloc(VSRAM_MAX_SIZE * sizeof(uint16_t)); +} + +void genesis_free_shared_memory(void) { + // Clear all shared memory + shared_mem_clear(); +} diff --git a/components/genesis/src/z80_shared_memory.cpp b/components/genesis/src/z80_shared_memory.cpp new file mode 100644 index 00000000..e3550cad --- /dev/null +++ b/components/genesis/src/z80_shared_memory.cpp @@ -0,0 +1,137 @@ +#include "z80_shared_memory.hpp" +#include "shared_memory.h" +#include "esp_log.h" + +static const char* TAG = "z80_shared_memory"; + +// Memory sizes +static constexpr size_t Z80_CYCLES_SIZE = 256; +static constexpr size_t Z80_CYCLES_CB_SIZE = 256; +static constexpr size_t Z80_CYCLES_ED_SIZE = 256; +static constexpr size_t Z80_CYCLES_XX_SIZE = 256; +static constexpr size_t Z80_CYCLES_XXCB_SIZE = 256; +static constexpr size_t Z80_ZS_TABLE_SIZE = 256; +static constexpr size_t Z80_PZS_TABLE_SIZE = 256; +static constexpr size_t Z80_DAA_TABLE_SIZE = 2048; + +// Static pointers to shared memory regions +static uint8_t* cycles = nullptr; +static uint8_t* cycles_cb = nullptr; +static uint8_t* cycles_ed = nullptr; +static uint8_t* cycles_xx = nullptr; +static uint8_t* cycles_xxcb = nullptr; +static uint8_t* zs_table = nullptr; +static uint8_t* pzs_table = nullptr; +static uint16_t* daa_table = nullptr; + +void z80_init_shared_memory() { + // Allocate memory for each table + shared_mem_request_t cycles_request = { + .size = Z80_CYCLES_SIZE, + .region = SHARED_MEM_DEFAULT + }; + cycles = static_cast(shared_mem_allocate(&cycles_request)); + if (!cycles) { + ESP_LOGE(TAG, "Failed to allocate memory for Z80 cycles table"); + return; + } + + shared_mem_request_t cycles_cb_request = { + .size = Z80_CYCLES_CB_SIZE, + .region = SHARED_MEM_DEFAULT + }; + cycles_cb = static_cast(shared_mem_allocate(&cycles_cb_request)); + if (!cycles_cb) { + ESP_LOGE(TAG, "Failed to allocate memory for Z80 cycles CB table"); + return; + } + + shared_mem_request_t cycles_ed_request = { + .size = Z80_CYCLES_ED_SIZE, + .region = SHARED_MEM_DEFAULT + }; + cycles_ed = static_cast(shared_mem_allocate(&cycles_ed_request)); + if (!cycles_ed) { + ESP_LOGE(TAG, "Failed to allocate memory for Z80 cycles ED table"); + return; + } + + shared_mem_request_t cycles_xx_request = { + .size = Z80_CYCLES_XX_SIZE, + .region = SHARED_MEM_DEFAULT + }; + cycles_xx = static_cast(shared_mem_allocate(&cycles_xx_request)); + if (!cycles_xx) { + ESP_LOGE(TAG, "Failed to allocate memory for Z80 cycles XX table"); + return; + } + + shared_mem_request_t cycles_xxcb_request = { + .size = Z80_CYCLES_XXCB_SIZE, + .region = SHARED_MEM_DEFAULT + }; + cycles_xxcb = static_cast(shared_mem_allocate(&cycles_xxcb_request)); + if (!cycles_xxcb) { + ESP_LOGE(TAG, "Failed to allocate memory for Z80 cycles XXCB table"); + return; + } + + shared_mem_request_t zs_table_request = { + .size = Z80_ZS_TABLE_SIZE, + .region = SHARED_MEM_DEFAULT + }; + zs_table = static_cast(shared_mem_allocate(&zs_table_request)); + if (!zs_table) { + ESP_LOGE(TAG, "Failed to allocate memory for Z80 ZS table"); + return; + } + + shared_mem_request_t pzs_table_request = { + .size = Z80_PZS_TABLE_SIZE, + .region = SHARED_MEM_DEFAULT + }; + pzs_table = static_cast(shared_mem_allocate(&pzs_table_request)); + if (!pzs_table) { + ESP_LOGE(TAG, "Failed to allocate memory for Z80 PZS table"); + return; + } + + shared_mem_request_t daa_table_request = { + .size = Z80_DAA_TABLE_SIZE * sizeof(uint16_t), + .region = SHARED_MEM_DEFAULT + }; + daa_table = static_cast(shared_mem_allocate(&daa_table_request)); + if (!daa_table) { + ESP_LOGE(TAG, "Failed to allocate memory for Z80 DAA table"); + return; + } +} + +void z80_free_shared_memory() { + // Clear all shared memory + shared_mem_clear(); + + // Reset pointers + cycles = nullptr; + cycles_cb = nullptr; + cycles_ed = nullptr; + cycles_xx = nullptr; + cycles_xxcb = nullptr; + zs_table = nullptr; + pzs_table = nullptr; + daa_table = nullptr; +} + +void z80_get_memory_regions(uint8_t** cycles_out, uint8_t** cycles_cb_out, uint8_t** cycles_ed_out, + uint8_t** cycles_xx_out, uint8_t** cycles_xxcb_out, uint8_t** zs_table_out, + uint8_t** pzs_table_out, uint16_t** daa_table_out) { + // Output pointers to memory regions + *cycles_out = cycles; + *cycles_cb_out = cycles_cb; + *cycles_ed_out = cycles_ed; + *cycles_xx_out = cycles_xx; + *cycles_xxcb_out = cycles_xxcb; + *zs_table_out = zs_table; + *pzs_table_out = pzs_table; + *daa_table_out = daa_table; +} \ No newline at end of file diff --git a/components/nes/CMakeLists.txt b/components/nes/CMakeLists.txt index aebdd686..839a7e21 100644 --- a/components/nes/CMakeLists.txt +++ b/components/nes/CMakeLists.txt @@ -2,6 +2,6 @@ idf_component_register( INCLUDE_DIRS "include" SRC_DIRS "src" "nofrendo/cpu" "nofrendo/libsnss" "nofrendo/nes" "nofrendo/sndhrdw" "nofrendo/mappers" "nofrendo" PRIV_INCLUDE_DIRS "nofrendo/cpu" "nofrendo/libsnss" "nofrendo/nes" "nofrendo/sndhrdw" "nofrendo" - REQUIRES "box-emu" "statistics" - ) + REQUIRES "box-emu" "statistics" "shared_memory" +) target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-char-subscripts -Wno-attributes -Wno-implicit-fallthrough -Wno-unused-function -Wno-unused-variable -Wno-discarded-qualifiers) diff --git a/components/nes/include/nes_external.h b/components/nes/include/nes_external.h new file mode 100644 index 00000000..b77675a1 --- /dev/null +++ b/components/nes/include/nes_external.h @@ -0,0 +1,17 @@ +#ifndef _NES_EXTERNAL_H_ +#define _NES_EXTERNAL_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +// External declaration of the NES context that will be defined in shared memory +extern nes_t nes; + +#ifdef __cplusplus +} +#endif + +#endif /* _NES_EXTERNAL_H_ */ \ No newline at end of file diff --git a/components/nes/include/nes_shared_memory.h b/components/nes/include/nes_shared_memory.h new file mode 100644 index 00000000..0f07c349 --- /dev/null +++ b/components/nes/include/nes_shared_memory.h @@ -0,0 +1,28 @@ +#ifndef _NES_SHARED_MEMORY_H_ +#define _NES_SHARED_MEMORY_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include + +// Initialize NES shared memory and hardware components +nes_t* nes_init_shared_memory(void); + +// Free NES shared memory +void nes_free_shared_memory(void); + +// NES hardware initialization functions +int nes6502_init(void); +int nes_ppu_init(void); +int nes_apu_init(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _NES_SHARED_MEMORY_H_ */ diff --git a/components/nes/nofrendo/bitmap.c b/components/nes/nofrendo/bitmap.c index 42c68323..c6748706 100644 --- a/components/nes/nofrendo/bitmap.c +++ b/components/nes/nofrendo/bitmap.c @@ -109,8 +109,8 @@ void bmp_destroy(bitmap_t **bitmap) { // if ((*bitmap)->data && false == (*bitmap)->hardware) // free((*bitmap)->data); - free(*bitmap); - *bitmap = NULL; + /* free(*bitmap); */ + /* *bitmap = NULL; */ } } diff --git a/components/nes/nofrendo/cpu/nes6502.c b/components/nes/nofrendo/cpu/nes6502.c index 5a7db41d..3426013e 100644 --- a/components/nes/nofrendo/cpu/nes6502.c +++ b/components/nes/nofrendo/cpu/nes6502.c @@ -40,7 +40,7 @@ #define ADD_CYCLES(x) \ { \ remaining_cycles -= (x); \ - nes_cpu.total_cycles += (x); \ + nes_cpu->total_cycles += (x); \ } /* @@ -554,9 +554,9 @@ { \ i_flag = 0; \ ADD_CYCLES(2); \ - if (nes_cpu.int_pending && remaining_cycles > 0) \ + if (nes_cpu->int_pending && remaining_cycles > 0) \ { \ - nes_cpu.int_pending = 0; \ + nes_cpu->int_pending = 0; \ IRQ_PROC(); \ ADD_CYCLES(INT_CYCLES); \ } \ @@ -686,8 +686,8 @@ #define JAM() \ { \ PC--; \ - nes_cpu.jammed = true; \ - nes_cpu.int_pending = 0; \ + nes_cpu->jammed = true; \ + nes_cpu->int_pending = 0; \ ADD_CYCLES(2); \ } #endif /* !NES6502_TESTOPS */ @@ -896,9 +896,9 @@ PC = PULL(); \ PC |= PULL() << 8; \ ADD_CYCLES(6); \ - if (0 == i_flag && nes_cpu.int_pending && remaining_cycles > 0) \ + if (0 == i_flag && nes_cpu->int_pending && remaining_cycles > 0) \ { \ - nes_cpu.int_pending = 0; \ + nes_cpu->int_pending = 0; \ IRQ_PROC(); \ ADD_CYCLES(INT_CYCLES); \ } \ @@ -1133,12 +1133,12 @@ /* internal CPU context */ -nes6502_context nes_cpu; +nes6502_context *nes_cpu = NULL; static int remaining_cycles = 0; /* so we can release timeslice */ /* memory region pointers */ static uint8 *ram = NULL, *stack = NULL; -static uint8 null_page[NES6502_BANKSIZE]; - +// static uint8 null_page[NES6502_BANKSIZE]; +static uint8 *null_page = NULL; /* ** Zero-page helper macros @@ -1164,7 +1164,7 @@ INLINE uint32 bank_readword(register uint32 address) ** be fetching a word across page boundaries, which only would ** make sense if the banks were physically consecutive. */ - return (uint32) (*(uint16 *)(nes_cpu.mem_page[address >> NES6502_BANKSHIFT] + (address & NES6502_BANKMASK))); + return (uint32) (*(uint16 *)(nes_cpu->mem_page[address >> NES6502_BANKSHIFT] + (address & NES6502_BANKMASK))); } #else /* !HOST_LITTLE_ENDIAN */ @@ -1182,9 +1182,9 @@ INLINE uint32 zp_readword(register uint8 address) INLINE uint32 bank_readword(register uint32 address) { #ifdef TARGET_CPU_PPC - return __lhbrx(nes_cpu.mem_page[address >> NES6502_BANKSHIFT], address & NES6502_BANKMASK); + return __lhbrx(nes_cpu->mem_page[address >> NES6502_BANKSHIFT], address & NES6502_BANKMASK); #else /* !TARGET_CPU_PPC */ - uint32 x = (uint32) *(uint16 *)(nes_cpu.mem_page[address >> NES6502_BANKSHIFT] + (address & NES6502_BANKMASK)); + uint32 x = (uint32) *(uint16 *)(nes_cpu->mem_page[address >> NES6502_BANKSHIFT] + (address & NES6502_BANKMASK)); return (x << 8) | (x >> 8); #endif /* !TARGET_CPU_PPC */ } @@ -1193,12 +1193,12 @@ INLINE uint32 bank_readword(register uint32 address) INLINE uint8 bank_readbyte(register uint32 address) { - return nes_cpu.mem_page[address >> NES6502_BANKSHIFT][address & NES6502_BANKMASK]; + return nes_cpu->mem_page[address >> NES6502_BANKSHIFT][address & NES6502_BANKMASK]; } INLINE void bank_writebyte(register uint32 address, register uint8 value) { - nes_cpu.mem_page[address >> NES6502_BANKSHIFT][address & NES6502_BANKMASK] = value; + nes_cpu->mem_page[address >> NES6502_BANKSHIFT][address & NES6502_BANKMASK] = value; } /* read a byte of 6502 memory */ @@ -1220,7 +1220,7 @@ static uint8 mem_readbyte(uint32 address) /* check memory range handlers */ else { - for (mr = nes_cpu.read_handler; mr->min_range != 0xFFFFFFFF; mr++) + for (mr = nes_cpu->read_handler; mr->min_range != 0xFFFFFFFF; mr++) { if (address >= mr->min_range && address <= mr->max_range) return mr->read_func(address); @@ -1245,7 +1245,7 @@ static void mem_writebyte(uint32 address, uint8 value) /* check memory range handlers */ else { - for (mw = nes_cpu.write_handler; mw->min_range != 0xFFFFFFFF; mw++) + for (mw = nes_cpu->write_handler; mw->min_range != 0xFFFFFFFF; mw++) { if (address >= mw->min_range && address <= mw->max_range) { @@ -1266,16 +1266,20 @@ void nes6502_setcontext(nes6502_context *context) ASSERT(context); - nes_cpu = *context; + *nes_cpu = *context; + + if (null_page == NULL) { + null_page = (uint8 *) _my_malloc(NES6502_BANKSIZE); + } /* set dead page for all pages not pointed at anything */ for (loop = 0; loop < NES6502_NUMBANKS; loop++) { - if (NULL == nes_cpu.mem_page[loop]) - nes_cpu.mem_page[loop] = null_page; + if (NULL == nes_cpu->mem_page[loop]) + nes_cpu->mem_page[loop] = null_page; } - ram = nes_cpu.mem_page[0]; /* quick zero-page/RAM references */ + ram = nes_cpu->mem_page[0]; /* quick zero-page/RAM references */ stack = ram + STACK_OFFSET; } @@ -1286,7 +1290,7 @@ void nes6502_getcontext(nes6502_context *context) ASSERT(context); - *context = nes_cpu; + *context = *nes_cpu; /* reset dead pages to null */ for (loop = 0; loop < NES6502_NUMBANKS; loop++) @@ -1305,32 +1309,32 @@ uint8 nes6502_getbyte(uint32 address) /* get number of elapsed cycles */ uint32 nes6502_getcycles(bool reset_flag) { - uint32 cycles = nes_cpu.total_cycles; + uint32 cycles = nes_cpu->total_cycles; if (reset_flag) - nes_cpu.total_cycles = 0; + nes_cpu->total_cycles = 0; return cycles; } #define GET_GLOBAL_REGS() \ { \ - PC = nes_cpu.pc_reg; \ - A = nes_cpu.a_reg; \ - X = nes_cpu.x_reg; \ - Y = nes_cpu.y_reg; \ - SCATTER_FLAGS(nes_cpu.p_reg); \ - S = nes_cpu.s_reg; \ + PC = nes_cpu->pc_reg; \ + A = nes_cpu->a_reg; \ + X = nes_cpu->x_reg; \ + Y = nes_cpu->y_reg; \ + SCATTER_FLAGS(nes_cpu->p_reg); \ + S = nes_cpu->s_reg; \ } #define STORE_LOCAL_REGS() \ { \ - nes_cpu.pc_reg = PC; \ - nes_cpu.a_reg = A; \ - nes_cpu.x_reg = X; \ - nes_cpu.y_reg = Y; \ - nes_cpu.p_reg = COMBINE_FLAGS(); \ - nes_cpu.s_reg = S; \ + nes_cpu->pc_reg = PC; \ + nes_cpu->a_reg = A; \ + nes_cpu->x_reg = X; \ + nes_cpu->y_reg = Y; \ + nes_cpu->p_reg = COMBINE_FLAGS(); \ + nes_cpu->s_reg = S; \ } #define MIN(a,b) (((a) < (b)) ? (a) : (b)) @@ -1368,7 +1372,7 @@ uint32 nes6502_getcycles(bool reset_flag) */ int nes6502_execute(int timeslice_cycles) { - int old_cycles = nes_cpu.total_cycles; + int old_cycles = nes_cpu->total_cycles; uint32 temp, addr; /* for macros */ uint8 btemp, baddr; /* for macros */ @@ -1427,18 +1431,18 @@ int nes6502_execute(int timeslice_cycles) GET_GLOBAL_REGS(); /* check for DMA cycle burning */ - if (nes_cpu.burn_cycles && remaining_cycles > 0) + if (nes_cpu->burn_cycles && remaining_cycles > 0) { int burn_for; - burn_for = MIN(remaining_cycles, nes_cpu.burn_cycles); + burn_for = MIN(remaining_cycles, nes_cpu->burn_cycles); ADD_CYCLES(burn_for); - nes_cpu.burn_cycles -= burn_for; + nes_cpu->burn_cycles -= burn_for; } - if (0 == i_flag && nes_cpu.int_pending && remaining_cycles > 0) + if (0 == i_flag && nes_cpu->int_pending && remaining_cycles > 0) { - nes_cpu.int_pending = 0; + nes_cpu->int_pending = 0; IRQ_PROC(); ADD_CYCLES(INT_CYCLES); } @@ -2400,18 +2404,18 @@ int nes6502_execute(int timeslice_cycles) STORE_LOCAL_REGS(); /* Return our actual amount of executed cycles */ - return (nes_cpu.total_cycles - old_cycles); + return (nes_cpu->total_cycles - old_cycles); } /* Issue a CPU Reset */ void nes6502_reset(void) { - nes_cpu.p_reg = Z_FLAG | R_FLAG | I_FLAG; /* Reserved bit always 1 */ - nes_cpu.int_pending = 0; /* No pending interrupts */ - nes_cpu.int_latency = 0; /* No latent interrupts */ - nes_cpu.pc_reg = bank_readword(RESET_VECTOR); /* Fetch reset vector */ - nes_cpu.burn_cycles = RESET_CYCLES; - nes_cpu.jammed = false; + nes_cpu->p_reg = Z_FLAG | R_FLAG | I_FLAG; /* Reserved bit always 1 */ + nes_cpu->int_pending = 0; /* No pending interrupts */ + nes_cpu->int_latency = 0; /* No latent interrupts */ + nes_cpu->pc_reg = bank_readword(RESET_VECTOR); /* Fetch reset vector */ + nes_cpu->burn_cycles = RESET_CYCLES; + nes_cpu->jammed = false; } /* following macro is used for below 2 functions */ @@ -2426,11 +2430,11 @@ void nes6502_nmi(void) { DECLARE_LOCAL_REGS - if (false == nes_cpu.jammed) + if (false == nes_cpu->jammed) { GET_GLOBAL_REGS(); NMI_PROC(); - nes_cpu.burn_cycles += INT_CYCLES; + nes_cpu->burn_cycles += INT_CYCLES; STORE_LOCAL_REGS(); } } @@ -2440,17 +2444,17 @@ void nes6502_irq(void) { DECLARE_LOCAL_REGS - if (false == nes_cpu.jammed) + if (false == nes_cpu->jammed) { GET_GLOBAL_REGS(); if (0 == i_flag) { IRQ_PROC(); - nes_cpu.burn_cycles += INT_CYCLES; + nes_cpu->burn_cycles += INT_CYCLES; } else { - nes_cpu.int_pending = 1; + nes_cpu->int_pending = 1; } STORE_LOCAL_REGS(); } @@ -2459,7 +2463,7 @@ void nes6502_irq(void) /* Set dead cycle period */ void nes6502_burn(int cycles) { - nes_cpu.burn_cycles += cycles; + nes_cpu->burn_cycles += cycles; } /* Release our timeslice */ diff --git a/components/nes/nofrendo/cpu/nes6502.h b/components/nes/nofrendo/cpu/nes6502.h index c2245a14..59884697 100644 --- a/components/nes/nofrendo/cpu/nes6502.h +++ b/components/nes/nofrendo/cpu/nes6502.h @@ -95,6 +95,8 @@ typedef struct int32 total_cycles, burn_cycles; } nes6502_context; +extern nes6502_context *nes_cpu; + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ diff --git a/components/nes/nofrendo/event.c b/components/nes/nofrendo/event.c index 74c7326e..1ba0a5b4 100644 --- a/components/nes/nofrendo/event.c +++ b/components/nes/nofrendo/event.c @@ -395,7 +395,7 @@ static void func_event_startsong(int code) } /* NES events */ -static event_t nes_events[] = +static const event_t nes_events[] = { NULL, /* 0 */ func_event_quit, @@ -483,7 +483,7 @@ static event_t nes_events[] = }; -static event_t *event_system_table[NUM_SUPPORTED_SYSTEMS] = +static const event_t *event_system_table[NUM_SUPPORTED_SYSTEMS] = { NULL, /* unknown */ NULL, /* autodetect */ @@ -513,13 +513,13 @@ void event_set(int index, event_t handler) */ int i; - for (i = 0; i < NUM_SUPPORTED_SYSTEMS; i++) - { - if(event_system_table[i]) - { - event_system_table[i][index] = handler; - } - } + /* for (i = 0; i < NUM_SUPPORTED_SYSTEMS; i++) */ + /* { */ + /* if(event_system_table[i]) */ + /* { */ + /* event_system_table[i][index] = handler; */ + /* } */ + /* } */ } event_t event_get(int index) diff --git a/components/nes/nofrendo/intro.c b/components/nes/nofrendo/intro.c index 84a22b89..029c8edb 100644 --- a/components/nes/nofrendo/intro.c +++ b/components/nes/nofrendo/intro.c @@ -32,7 +32,7 @@ #define VROM_SIZE 0x2000 /* 6502 code for the intro */ -static uint8 intro_code[301] = +static const uint8 intro_code[301] = { 0x78, 0xD8, 0xA2, 0x00, 0x8E, 0x00, 0x20, 0x8E, 0x01, 0x20, 0xAD, 0x02, 0x20, 0xAD, 0x02, 0x20, 0x10, 0xFB, 0xAD, 0x02, 0x20, 0x10, 0xFB, 0x8E, 0x03, 0x20, 0xCA, 0x9A, 0xA9, 0x3F, 0x8D, 0x06, @@ -56,13 +56,13 @@ static uint8 intro_code[301] = } ; /* interrupt vectors (FFFAh - FFFFh) */ -static uint8 intro_vec[6] = +static const uint8 intro_vec[6] = { 0x27, 0x81, 0x00, 0x80, 0x27, 0x81 }; /* graphics */ -static uint8 intro_vrom[4096] = +static const uint8 intro_vrom[4096] = { 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, diff --git a/components/nes/nofrendo/memguard.c b/components/nes/nofrendo/memguard.c index df302117..a75c6131 100644 --- a/components/nes/nofrendo/memguard.c +++ b/components/nes/nofrendo/memguard.c @@ -50,316 +50,6 @@ typedef struct memblock_s int line_num; } memblock_t; -/* debugging flag */ -bool mem_debug = true; - - -#ifdef NOFRENDO_DEBUG - -static int mem_blockcount = 0; /* allocated block count */ -static memblock_t *mem_record = NULL; - -#define GUARD_STRING "GgUuAaRrDdSsTtRrIiNnGgBbLlOoCcKk" -#define GUARD_LENGTH 256 /* before and after allocated block */ - - -/* -** Check the memory guard to make sure out of bounds writes have not -** occurred. -*/ -static int mem_checkguardblock(void *data, int guard_size) -{ - char *check, *block; - int i, alloc_size; - - /* get the original pointer */ - block = ((char *) data) - guard_size; - - /* get the size */ - alloc_size = *((uint32 *) block); - block+=4; - - /* check leading guard string */ - check = GUARD_STRING; - for (i = sizeof(uint32); i < guard_size; i++) - { - /* wrap */ - if ('\0' == *check) - check = GUARD_STRING; - - if (*block++ != *check++) - return -1; - } - - /* check end of block */ - check = GUARD_STRING; - block = ((char *) data) + alloc_size; - for (i = 0; i < guard_size; i++) - { - /* wrap */ - if ('\0' == *check) - check = GUARD_STRING; - if (*block++ != *check++) - return -1; - } - - /* we're okay! */ - return 0; -} - -/* free a guard block */ -static void mem_freeguardblock(void *data, int guard_size) -{ - char *orig = ((char *) data) - guard_size; - - free(orig); -} - -/* allocate memory, guarding with a guard block in front and behind */ -static void *mem_guardalloc(int alloc_size, int guard_size) -{ - void *orig; - char *block, *check; - uint32 *ptr; - int i; - - /* pad it up to a 32-bit multiple */ - alloc_size = (alloc_size + 3) & ~3; - - /* allocate memory */ - orig = malloc(alloc_size + (guard_size * 2)); - if (NULL == orig) - return NULL; - - block = (char *) orig; - - /* get it to the pointer we will actually return */ - orig = (void *) ((char *) orig + guard_size); - - /* trash it all */ - ptr = (uint32 *) orig; - for (i = alloc_size / 4; i; i--) - *ptr++ = 0xDEADBEEF; - - /* store the size of the newly allocated block*/ - *((uint32 *) block) = alloc_size; - block+=4; - - /* put guard string at beginning of block */ - check = GUARD_STRING; - for (i = sizeof(uint32); i < guard_size; i++) - { - /* wrap */ - if ('\0' == *check) - check = GUARD_STRING; - - *block++ = *check++; - } - - /* put at end of block */ - check = GUARD_STRING; - block = (char *) orig + alloc_size; - for (i = 0; i < guard_size; i++) - { - /* wrap */ - if ('\0' == *check) - check = GUARD_STRING; - - *block++ = *check++; - } - - return orig; -} - - -/* Free up the space used by the memory block manager */ -void mem_cleanup(void) -{ - if (mem_record) - { - free(mem_record); - mem_record = NULL; - } -} - - -/* Allocate a bunch of memory to keep track of all memory blocks */ -static void mem_init(void) -{ - mem_cleanup(); - - mem_blockcount = 0; - - mem_record = malloc(MAX_BLOCKS * sizeof(memblock_t)); - ASSERT(mem_record); - memset(mem_record, 0, MAX_BLOCKS * sizeof(memblock_t)); -} - - -/* add a block of memory to the master record */ -static void mem_addblock(void *data, int block_size, char *file, int line) -{ - int i; - - for (i = 0; i < MAX_BLOCKS; i++) - { - if (NULL == mem_record[i].block_addr) - { - mem_record[i].block_addr = data; - mem_record[i].block_size = block_size; - mem_record[i].file_name = file; - mem_record[i].line_num = line; - return; - } - } - - ASSERT_MSG("out of memory blocks."); -} - -/* find an entry in the block record and delete it */ -static void mem_deleteblock(void *data, char *file, int line) -{ - int i; - char fail[256]; - - for (i = 0; i < MAX_BLOCKS; i++) - { - if (data == mem_record[i].block_addr) - { - if (mem_checkguardblock(mem_record[i].block_addr, GUARD_LENGTH)) - { - sprintf(fail, "mem_deleteblock 0x%08X at line %d of %s -- block corrupt", - (uint32) data, line, file); - ASSERT_MSG(fail); - } - - memset(&mem_record[i], 0, sizeof(memblock_t)); - return; - } - } - - sprintf(fail, "mem_deleteblock 0x%08X at line %d of %s -- block not found", - (uint32) data, line, file); - ASSERT_MSG(fail); -} -#endif /* NOFRENDO_DEBUG */ - -/* debugger-friendly versions of calls */ -#ifdef NOFRENDO_DEBUG - -/* allocates memory and clears it */ -void *_my_malloc(int size, char *file, int line) -{ - void *temp; - char fail[256]; - - if (NULL == mem_record && false != mem_debug) - mem_init(); - - if (false != mem_debug) - temp = mem_guardalloc(size, GUARD_LENGTH); - else - temp = malloc(size); - - printf("Malloc: %d at %s:%d\n", size, file, line); - if (NULL == temp) - { - sprintf(fail, "malloc: out of memory at line %d of %s. block size: %d\n", - line, file, size); - ASSERT_MSG(fail); - } - - if (false != mem_debug) - mem_addblock(temp, size, file, line); - - mem_blockcount++; - - return temp; -} - -/* free a pointer allocated with my_malloc */ -void _my_free(void **data, char *file, int line) -{ - char fail[256]; - - if (NULL == data || NULL == *data) - { - sprintf(fail, "free: attempted to free NULL pointer at line %d of %s\n", - line, file); - ASSERT_MSG(fail); - } - - /* if this is true, we are in REAL trouble */ - if (0 == mem_blockcount) - { - ASSERT_MSG("free: attempted to free memory when no blocks available"); - } - - mem_blockcount--; /* dec our block count */ - - if (false != mem_debug) - { - mem_deleteblock(*data, file, line); - mem_freeguardblock(*data, GUARD_LENGTH); - } - else - { - free(*data); - } - - *data = NULL; /* NULL our source */ -} - -char *_my_strdup(const char *string, char *file, int line) -{ - char *temp; - - if (NULL == string) - return NULL; - - temp = (char *) _my_malloc(strlen(string) + 1, file, line); - if (NULL == temp) - return NULL; - - strcpy(temp, string); - - return temp; -} - -#else /* !NOFRENDO_DEBUG */ - -/* allocates memory and clears it */ -void *_my_malloc(int size) -{ - void *temp; - char fail[256]; - - temp = malloc(size); - - if (NULL == temp) - { - sprintf(fail, "malloc: out of memory. block size: %d\n", size); - ASSERT_MSG(fail); - } - - return temp; -} - -/* free a pointer allocated with my_malloc */ -void _my_free(void **data) -{ - char fail[256]; - - if (NULL == data || NULL == *data) - { - sprintf(fail, "free: attempted to free NULL pointer.\n"); - ASSERT_MSG(fail); - } - - free(*data); - *data = NULL; /* NULL our source */ -} - char *_my_strdup(const char *string) { char *temp; @@ -377,64 +67,13 @@ char *_my_strdup(const char *string) return temp; } -#endif /* !NOFRENDO_DEBUG */ - /* check for orphaned memory handles */ void mem_checkleaks(void) { -#ifdef NOFRENDO_DEBUG - int i; - - if (false == mem_debug || NULL == mem_record) - return; - - if (mem_blockcount) - { - log_printf("memory leak - %d unfreed block%s\n\n", mem_blockcount, - mem_blockcount == 1 ? "" : "s"); - - for (i = 0; i < MAX_BLOCKS; i++) - { - if (mem_record[i].block_addr) - { - log_printf("addr: 0x%08X, size: %d, line %d of %s%s\n", - (uint32) mem_record[i].block_addr, - mem_record[i].block_size, - mem_record[i].line_num, - mem_record[i].file_name, - (mem_checkguardblock(mem_record[i].block_addr, GUARD_LENGTH)) - ? " -- block corrupt" : ""); - } - } - } - else - log_printf("no memory leaks\n"); -#endif /* NOFRENDO_DEBUG */ } void mem_checkblocks(void) { -#ifdef NOFRENDO_DEBUG - int i; - - if (false == mem_debug || NULL == mem_record) - return; - - for (i = 0; i < MAX_BLOCKS; i++) - { - if (mem_record[i].block_addr) - { - if (mem_checkguardblock(mem_record[i].block_addr, GUARD_LENGTH)) - { - log_printf("addr: 0x%08X, size: %d, line %d of %s -- block corrupt\n", - (uint32) mem_record[i].block_addr, - mem_record[i].block_size, - mem_record[i].line_num, - mem_record[i].file_name); - } - } - } -#endif /* NOFRENDO_DEBUG */ } /* diff --git a/components/nes/nofrendo/nes/nes.c b/components/nes/nofrendo/nes/nes.c index e1a2852c..9eec5142 100644 --- a/components/nes/nofrendo/nes/nes.c +++ b/components/nes/nofrendo/nes/nes.c @@ -52,8 +52,6 @@ #define NES_SKIP_LIMIT (NES_REFRESH_RATE / 5) /* 12 or 10, depending on PAL/NTSC */ -static nes_t nes; - /* find out if a file is ours */ int nes_isourfile(const char *filename) { @@ -63,17 +61,17 @@ int nes_isourfile(const char *filename) /* TODO: just asking for problems -- please remove */ nes_t *nes_getcontextptr(void) { - return &nes; + return nes_context; } void nes_getcontext(nes_t *machine) { - apu_getcontext(nes.apu); - ppu_getcontext(nes.ppu); - nes6502_getcontext(nes.cpu); - mmc_getcontext(nes.mmc); + apu_getcontext(nes_context->apu); + ppu_getcontext(nes_context->ppu); + nes6502_getcontext(nes_context->cpu); + mmc_getcontext(nes_context->mmc); - *machine = nes; + *machine = *nes_context; } void nes_setcontext(nes_t *machine) @@ -85,17 +83,17 @@ void nes_setcontext(nes_t *machine) nes6502_setcontext(machine->cpu); mmc_setcontext(machine->mmc); - nes = *machine; + *nes_context = *machine; } static uint8 ram_read(uint32 address) { - return nes.cpu->mem_page[0][address & (NES_RAMSIZE - 1)]; + return nes_context->cpu->mem_page[0][address & (NES_RAMSIZE - 1)]; } static void ram_write(uint32 address, uint8 value) { - nes.cpu->mem_page[0][address & (NES_RAMSIZE - 1)] = value; + nes_context->cpu->mem_page[0][address & (NES_RAMSIZE - 1)] = value; } static void write_protect(uint32 address, uint8 value) @@ -252,8 +250,8 @@ static void build_address_handlers(nes_t *machine) void nes_irq(void) { #ifdef NOFRENDO_DEBUG - if (nes.scanline <= NES_SCREEN_HEIGHT) - memset(nes.vidbuf->line[nes.scanline - 1], GUI_RED, NES_SCREEN_WIDTH); + if (nes_context->scanline <= NES_SCREEN_HEIGHT) + memset(nes_context->vidbuf->line[nes_context->scanline - 1], GUI_RED, NES_SCREEN_WIDTH); #endif /* NOFRENDO_DEBUG */ nes6502_irq(); @@ -261,9 +259,9 @@ void nes_irq(void) static uint8 nes_clearfiq(void) { - if (nes.fiq_occurred) + if (nes_context->fiq_occurred) { - nes.fiq_occurred = false; + nes_context->fiq_occurred = false; return 0x40; } @@ -272,19 +270,19 @@ static uint8 nes_clearfiq(void) void nes_setfiq(uint8 value) { - nes.fiq_state = value; - nes.fiq_cycles = (int) NES_FIQ_PERIOD; + nes_context->fiq_state = value; + nes_context->fiq_cycles = (int) NES_FIQ_PERIOD; } static void nes_checkfiq(int cycles) { - nes.fiq_cycles -= cycles; - if (nes.fiq_cycles <= 0) + nes_context->fiq_cycles -= cycles; + if (nes_context->fiq_cycles <= 0) { - nes.fiq_cycles += (int) NES_FIQ_PERIOD; - if (0 == (nes.fiq_state & 0xC0)) + nes_context->fiq_cycles += (int) NES_FIQ_PERIOD; + if (0 == (nes_context->fiq_state & 0xC0)) { - nes.fiq_occurred = true; + nes_context->fiq_occurred = true; nes6502_irq(); } } @@ -298,18 +296,18 @@ void nes_nmi(void) static void nes_renderframe(bool draw_flag) { int elapsed_cycles; - mapintf_t *mapintf = nes.mmc->intf; + mapintf_t *mapintf = nes_context->mmc->intf; int in_vblank = 0; - while (262 != nes.scanline) + while (262 != nes_context->scanline) { - ppu_scanline(nes.vidbuf, nes.scanline, draw_flag); + ppu_scanline(nes_context->vidbuf, nes_context->scanline, draw_flag); - if (241 == nes.scanline) + if (241 == nes_context->scanline) { /* 7-9 cycle delay between when VINT flag goes up and NMI is taken */ elapsed_cycles = nes6502_execute(7); - nes.scanline_cycles -= elapsed_cycles; + nes_context->scanline_cycles -= elapsed_cycles; nes_checkfiq(elapsed_cycles); ppu_checknmi(); @@ -322,16 +320,16 @@ static void nes_renderframe(bool draw_flag) if (mapintf->hblank) mapintf->hblank(in_vblank); - nes.scanline_cycles += (float) NES_SCANLINE_CYCLES; - elapsed_cycles = nes6502_execute((int) nes.scanline_cycles); - nes.scanline_cycles -= (float) elapsed_cycles; + nes_context->scanline_cycles += (float) NES_SCANLINE_CYCLES; + elapsed_cycles = nes6502_execute((int) nes_context->scanline_cycles); + nes_context->scanline_cycles -= (float) elapsed_cycles; nes_checkfiq(elapsed_cycles); - ppu_endscanline(nes.scanline); - nes.scanline++; + ppu_endscanline(nes_context->scanline); + nes_context->scanline++; } - nes.scanline = 0; + nes_context->scanline = 0; } static void system_video(bool draw) @@ -344,7 +342,7 @@ static void system_video(bool draw) } /* blit the NES screen to our video surface */ - vid_blit(nes.vidbuf, 0, (NES_SCREEN_HEIGHT - NES_VISIBLE_HEIGHT) / 2, + vid_blit(nes_context->vidbuf, 0, (NES_SCREEN_HEIGHT - NES_VISIBLE_HEIGHT) / 2, 0, 0, NES_SCREEN_WIDTH, NES_VISIBLE_HEIGHT); /* overlay our GUI on top of it */ @@ -364,17 +362,17 @@ extern bool forceConsoleReset; void nes_emulate(void) { nes_prep_emulation(NULL, NULL); - while (false == nes.poweroff) + while (false == nes_context->poweroff) { nes_emulateframe(0); } } void nes_prep_emulation(char* filename, nes_t *machine) { - osd_setsound(nes.apu->process); + osd_setsound(nes_context->apu->process); - nes.scanline_cycles = 0; - nes.fiq_cycles = (int) NES_FIQ_PERIOD; + nes_context->scanline_cycles = 0; + nes_context->fiq_cycles = (int) NES_FIQ_PERIOD; for (int i = 0; i < 4; ++i) { @@ -423,9 +421,9 @@ void nes_reset(int reset_type) { if (HARD_RESET == reset_type) { - memset(nes.cpu->mem_page[0], 0, NES_RAMSIZE); - if (nes.rominfo->vram) - mem_trash(nes.rominfo->vram, 0x2000 * nes.rominfo->vram_banks); + memset(nes_context->cpu->mem_page[0], 0, NES_RAMSIZE); + if (nes_context->rominfo->vram) + mem_trash(nes_context->rominfo->vram, 0x2000 * nes_context->rominfo->vram_banks); } apu_reset(); @@ -433,7 +431,7 @@ void nes_reset(int reset_type) mmc_reset(); nes6502_reset(); - nes.scanline = 241; + nes_context->scanline = 241; /* gui_sendmsg(GUI_GREEN, "NES %s", */ /* (HARD_RESET == reset_type) ? "powered on" : "reset"); */ @@ -443,31 +441,30 @@ void nes_destroy(nes_t **machine) { if (*machine) { - rom_free(&(*machine)->rominfo); - mmc_destroy(&(*machine)->mmc); - ppu_destroy(&(*machine)->ppu); - apu_destroy(&(*machine)->apu); - bmp_destroy(&(*machine)->vidbuf); - if ((*machine)->cpu) - { - if ((*machine)->cpu->mem_page[0]) - free((*machine)->cpu->mem_page[0]); - free((*machine)->cpu); - } - - free(*machine); - *machine = NULL; + /* rom_free(&(*machine)->rominfo); */ + /* mmc_destroy(&(*machine)->mmc); */ + /* ppu_destroy(&(*machine)->ppu); */ + /* apu_destroy(&(*machine)->apu); */ + /* bmp_destroy(&(*machine)->vidbuf); */ + /* if ((*machine)->cpu) */ + /* { */ + /* // No need to free mem_page[0] as it points to shared memory */ + /* free((*machine)->cpu); */ + /* } */ + + /* free(*machine); */ + /* *machine = NULL; */ } } void nes_poweroff(void) { - nes.poweroff = true; + nes_context->poweroff = true; } void nes_togglepause(void) { - nes.pause ^= true; + nes_context->pause ^= true; } /* insert a cart into the NES */ @@ -578,7 +575,7 @@ nes_t *nes_create(void) _fail: nes_destroy(&machine); return NULL; -} + } /* ** $Log: nes.c,v $ diff --git a/components/nes/nofrendo/nes/nes.h b/components/nes/nofrendo/nes/nes.h index d47190c5..f0aa0718 100644 --- a/components/nes/nofrendo/nes/nes.h +++ b/components/nes/nofrendo/nes/nes.h @@ -88,6 +88,7 @@ typedef struct nes_s } nes_t; +extern nes_t *nes_context; extern int nes_isourfile(const char *filename); diff --git a/components/nes/nofrendo/nes/nes_mmc.c b/components/nes/nofrendo/nes/nes_mmc.c index 8a41cde5..448e1ad3 100644 --- a/components/nes/nofrendo/nes/nes_mmc.c +++ b/components/nes/nofrendo/nes/nes_mmc.c @@ -34,13 +34,13 @@ #include //#include -#define MMC_8KROM (mmc.cart->rom_banks * 2) -#define MMC_16KROM (mmc.cart->rom_banks) -#define MMC_32KROM (mmc.cart->rom_banks / 2) -#define MMC_8KVROM (mmc.cart->vrom_banks) -#define MMC_4KVROM (mmc.cart->vrom_banks * 2) -#define MMC_2KVROM (mmc.cart->vrom_banks * 4) -#define MMC_1KVROM (mmc.cart->vrom_banks * 8) +#define MMC_8KROM (mmc->cart->rom_banks * 2) +#define MMC_16KROM (mmc->cart->rom_banks) +#define MMC_32KROM (mmc->cart->rom_banks / 2) +#define MMC_8KVROM (mmc->cart->vrom_banks) +#define MMC_4KVROM (mmc->cart->vrom_banks * 2) +#define MMC_2KVROM (mmc->cart->vrom_banks * 4) +#define MMC_1KVROM (mmc->cart->vrom_banks * 8) #define MMC_LAST8KROM (MMC_8KROM - 1) #define MMC_LAST16KROM (MMC_16KROM - 1) @@ -50,29 +50,29 @@ #define MMC_LAST2KVROM (MMC_2KVROM - 1) #define MMC_LAST1KVROM (MMC_1KVROM - 1) -static mmc_t mmc; +static mmc_t *mmc = NULL; rominfo_t *mmc_getinfo(void) { - return mmc.cart; + return mmc->cart; } void mmc_setcontext(mmc_t *src_mmc) { ASSERT(src_mmc); - mmc = *src_mmc; + mmc = src_mmc; } void mmc_getcontext(mmc_t *dest_mmc) { - *dest_mmc = mmc; + *dest_mmc = *mmc; } /* VROM bankswitching */ void mmc_bankvrom(int size, uint32 address, int bank) { - if (0 == mmc.cart->vrom_banks) + if (0 == mmc->cart->vrom_banks) return; switch (size) @@ -80,25 +80,25 @@ void mmc_bankvrom(int size, uint32 address, int bank) case 1: if (bank == MMC_LASTBANK) bank = MMC_LAST1KVROM; - ppu_setpage(1, address >> 10, &mmc.cart->vrom[(bank % MMC_1KVROM) << 10] - address); + ppu_setpage(1, address >> 10, &mmc->cart->vrom[(bank % MMC_1KVROM) << 10] - address); break; case 2: if (bank == MMC_LASTBANK) bank = MMC_LAST2KVROM; - ppu_setpage(2, address >> 10, &mmc.cart->vrom[(bank % MMC_2KVROM) << 11] - address); + ppu_setpage(2, address >> 10, &mmc->cart->vrom[(bank % MMC_2KVROM) << 11] - address); break; case 4: if (bank == MMC_LASTBANK) bank = MMC_LAST4KVROM; - ppu_setpage(4, address >> 10, &mmc.cart->vrom[(bank % MMC_4KVROM) << 12] - address); + ppu_setpage(4, address >> 10, &mmc->cart->vrom[(bank % MMC_4KVROM) << 12] - address); break; case 8: if (bank == MMC_LASTBANK) bank = MMC_LAST8KVROM; - ppu_setpage(8, 0, &mmc.cart->vrom[(bank % MMC_8KVROM) << 13]); + ppu_setpage(8, 0, &mmc->cart->vrom[(bank % MMC_8KVROM) << 13]); break; default: @@ -122,7 +122,7 @@ void mmc_bankrom(int size, uint32 address, int bank) bank = MMC_LAST8KROM; { int page = address >> NES6502_BANKSHIFT; - mmc_cpu.mem_page[page] = &mmc.cart->rom[(bank % MMC_8KROM) << 13]; + mmc_cpu.mem_page[page] = &mmc->cart->rom[(bank % MMC_8KROM) << 13]; mmc_cpu.mem_page[page + 1] = mmc_cpu.mem_page[page] + 0x1000; } @@ -133,7 +133,7 @@ void mmc_bankrom(int size, uint32 address, int bank) bank = MMC_LAST16KROM; { int page = address >> NES6502_BANKSHIFT; - mmc_cpu.mem_page[page] = &mmc.cart->rom[(bank % MMC_16KROM) << 14]; + mmc_cpu.mem_page[page] = &mmc->cart->rom[(bank % MMC_16KROM) << 14]; mmc_cpu.mem_page[page + 1] = mmc_cpu.mem_page[page] + 0x1000; mmc_cpu.mem_page[page + 2] = mmc_cpu.mem_page[page] + 0x2000; mmc_cpu.mem_page[page + 3] = mmc_cpu.mem_page[page] + 0x3000; @@ -144,7 +144,7 @@ void mmc_bankrom(int size, uint32 address, int bank) if (bank == MMC_LASTBANK) bank = MMC_LAST32KROM; - mmc_cpu.mem_page[8] = &mmc.cart->rom[(bank % MMC_32KROM) << 15]; + mmc_cpu.mem_page[8] = &mmc->cart->rom[(bank % MMC_32KROM) << 15]; mmc_cpu.mem_page[9] = mmc_cpu.mem_page[8] + 0x1000; mmc_cpu.mem_page[10] = mmc_cpu.mem_page[8] + 0x2000; mmc_cpu.mem_page[11] = mmc_cpu.mem_page[8] + 0x3000; @@ -180,20 +180,20 @@ bool mmc_peek(int map_num) static void mmc_setpages(void) { - printf("setting up mapper %d\n", mmc.intf->number); + printf("setting up mapper %d\n", mmc->intf->number); /* Switch ROM into CPU space, set VROM/VRAM (done for ALL ROMs) */ mmc_bankrom(16, 0x8000, 0); mmc_bankrom(16, 0xC000, MMC_LASTBANK); mmc_bankvrom(8, 0x0000, 0); - if (mmc.cart->flags & ROM_FLAG_FOURSCREEN) + if (mmc->cart->flags & ROM_FLAG_FOURSCREEN) { ppu_mirror(0, 1, 2, 3); } else { - if (MIRROR_VERT == mmc.cart->mirror) + if (MIRROR_VERT == mmc->cart->mirror) ppu_mirror(0, 1, 0, 1); else ppu_mirror(0, 0, 1, 1); @@ -201,11 +201,11 @@ static void mmc_setpages(void) /* if we have no VROM, switch in VRAM */ /* TODO: fix this hack implementation */ - if (0 == mmc.cart->vrom_banks) + if (0 == mmc->cart->vrom_banks) { - ASSERT(mmc.cart->vram); + ASSERT(mmc->cart->vram); - ppu_setpage(8, 0, mmc.cart->vram); + ppu_setpage(8, 0, mmc->cart->vram); ppu_mirrorhipages(); } } @@ -218,8 +218,8 @@ void mmc_reset(void) ppu_setlatchfunc(NULL); ppu_setvromswitch(NULL); - if (mmc.intf->init) - mmc.intf->init(); + if (mmc->intf->init) + mmc->intf->init(); log_printf("reset memory mapper\n"); } @@ -227,8 +227,8 @@ void mmc_reset(void) void mmc_destroy(mmc_t **nes_mmc) { - if (*nes_mmc) - free(*nes_mmc); + /* if (*nes_mmc) */ + /* free(*nes_mmc); */ } mmc_t *mmc_create(rominfo_t *rominfo) diff --git a/components/nes/nofrendo/nes/nes_pal.c b/components/nes/nofrendo/nes/nes_pal.c index 0c9d917a..eb087cf6 100644 --- a/components/nes/nofrendo/nes/nes_pal.c +++ b/components/nes/nofrendo/nes/nes_pal.c @@ -33,7 +33,7 @@ #endif /* my NES palette, converted to RGB */ -rgb_t shady_palette[] = +const rgb_t shady_palette[] = { {0x80,0x80,0x80}, {0x00,0x00,0xBB}, {0x37,0x00,0xBF}, {0x84,0x00,0xA6}, {0xBB,0x00,0x6A}, {0xB7,0x00,0x1E}, {0xB3,0x00,0x00}, {0x91,0x26,0x00}, diff --git a/components/nes/nofrendo/nes/nes_pal.h b/components/nes/nofrendo/nes/nes_pal.h index 5066e930..eb4828ed 100644 --- a/components/nes/nofrendo/nes/nes_pal.h +++ b/components/nes/nofrendo/nes/nes_pal.h @@ -27,7 +27,7 @@ #define _NESPAL_H_ extern rgb_t nes_palette[]; -extern rgb_t shady_palette[]; +extern const rgb_t shady_palette[]; extern void pal_generate(void); diff --git a/components/nes/nofrendo/nes/nes_ppu.c b/components/nes/nofrendo/nes/nes_ppu.c index dcef6527..853ec3f5 100644 --- a/components/nes/nofrendo/nes/nes_ppu.c +++ b/components/nes/nofrendo/nes/nes_ppu.c @@ -39,7 +39,7 @@ /* PPU access */ -#define PPU_MEM(x) ppu.page[(x) >> 10][(x)] +#define PPU_MEM(x) ppu->page[(x) >> 10][(x)] /* Background (color 0) and solid sprite pixel flags */ #define BG_TRANS 0x80 @@ -49,22 +49,24 @@ #define SP_CLEAR(V) (0 == ((V) & SP_PIXEL)) /* Full BG color */ -#define FULLBG (ppu.palette[0] | BG_TRANS) +#define FULLBG (ppu->palette[0] | BG_TRANS) /* the NES PPU */ -static ppu_t ppu; +ppu_t *ppu = NULL; void ppu_displaysprites(bool display) { - ppu.drawsprites = display; + ppu->drawsprites = display; } void ppu_setcontext(ppu_t *src_ppu) { int nametab[4]; ASSERT(src_ppu); - ppu = *src_ppu; + if (NULL == ppu) + ppu = _my_malloc(sizeof(ppu_t)); + *ppu = *src_ppu; /* we can't just copy contexts here, because more than likely, ** the top 8 pages of the ppu are pointing to internal PPU memory, @@ -79,14 +81,14 @@ void ppu_setcontext(ppu_t *src_ppu) nametab[2] = (src_ppu->page[10] - src_ppu->nametab + 0x2800) >> 10; nametab[3] = (src_ppu->page[11] - src_ppu->nametab + 0x2C00) >> 10; - ppu.page[8] = ppu.nametab + (nametab[0] << 10) - 0x2000; - ppu.page[9] = ppu.nametab + (nametab[1] << 10) - 0x2400; - ppu.page[10] = ppu.nametab + (nametab[2] << 10) - 0x2800; - ppu.page[11] = ppu.nametab + (nametab[3] << 10) - 0x2C00; - ppu.page[12] = ppu.page[8] - 0x1000; - ppu.page[13] = ppu.page[9] - 0x1000; - ppu.page[14] = ppu.page[10] - 0x1000; - ppu.page[15] = ppu.page[11] - 0x1000; + ppu->page[8] = ppu->nametab + (nametab[0] << 10) - 0x2000; + ppu->page[9] = ppu->nametab + (nametab[1] << 10) - 0x2400; + ppu->page[10] = ppu->nametab + (nametab[2] << 10) - 0x2800; + ppu->page[11] = ppu->nametab + (nametab[3] << 10) - 0x2C00; + ppu->page[12] = ppu->page[8] - 0x1000; + ppu->page[13] = ppu->page[9] - 0x1000; + ppu->page[14] = ppu->page[10] - 0x1000; + ppu->page[15] = ppu->page[11] - 0x1000; } void ppu_getcontext(ppu_t *dest_ppu) @@ -94,7 +96,7 @@ void ppu_getcontext(ppu_t *dest_ppu) int nametab[4]; ASSERT(dest_ppu); - *dest_ppu = ppu; + *dest_ppu = *ppu; /* we can't just copy contexts here, because more than likely, ** the top 8 pages of the ppu are pointing to internal PPU memory, @@ -104,10 +106,10 @@ void ppu_getcontext(ppu_t *dest_ppu) ** definitely pointing to internal PPU RAM, not just something ** that some crazy mapper paged in. */ - nametab[0] = (ppu.page[8] - ppu.nametab + 0x2000) >> 10; - nametab[1] = (ppu.page[9] - ppu.nametab + 0x2400) >> 10; - nametab[2] = (ppu.page[10] - ppu.nametab + 0x2800) >> 10; - nametab[3] = (ppu.page[11] - ppu.nametab + 0x2C00) >> 10; + nametab[0] = (ppu->page[8] - ppu->nametab + 0x2000) >> 10; + nametab[1] = (ppu->page[9] - ppu->nametab + 0x2400) >> 10; + nametab[2] = (ppu->page[10] - ppu->nametab + 0x2800) >> 10; + nametab[3] = (ppu->page[11] - ppu->nametab + 0x2C00) >> 10; dest_ppu->page[8] = dest_ppu->nametab + (nametab[0] << 10) - 0x2000; dest_ppu->page[9] = dest_ppu->nametab + (nametab[1] << 10) - 0x2400; @@ -151,8 +153,8 @@ void ppu_destroy(ppu_t **src_ppu) { if (*src_ppu) { - free(*src_ppu); - *src_ppu = NULL; + // free(*src_ppu); + // *src_ppu = NULL; } } @@ -162,17 +164,17 @@ void ppu_setpage(int size, int page_num, uint8 *location) switch (size) { case 8: - ppu.page[page_num++] = location; - ppu.page[page_num++] = location; - ppu.page[page_num++] = location; - ppu.page[page_num++] = location; + ppu->page[page_num++] = location; + ppu->page[page_num++] = location; + ppu->page[page_num++] = location; + ppu->page[page_num++] = location; case 4: - ppu.page[page_num++] = location; - ppu.page[page_num++] = location; + ppu->page[page_num++] = location; + ppu->page[page_num++] = location; case 2: - ppu.page[page_num++] = location; + ppu->page[page_num++] = location; case 1: - ppu.page[page_num++] = location; + ppu->page[page_num++] = location; break; } } @@ -180,28 +182,28 @@ void ppu_setpage(int size, int page_num, uint8 *location) /* make sure $3000-$3F00 mirrors $2000-$2F00 */ void ppu_mirrorhipages(void) { - ppu.page[12] = ppu.page[8] - 0x1000; - ppu.page[13] = ppu.page[9] - 0x1000; - ppu.page[14] = ppu.page[10] - 0x1000; - ppu.page[15] = ppu.page[11] - 0x1000; + ppu->page[12] = ppu->page[8] - 0x1000; + ppu->page[13] = ppu->page[9] - 0x1000; + ppu->page[14] = ppu->page[10] - 0x1000; + ppu->page[15] = ppu->page[11] - 0x1000; } void ppu_mirror(int nt1, int nt2, int nt3, int nt4) { - ppu.page[8] = ppu.nametab + (nt1 << 10) - 0x2000; - ppu.page[9] = ppu.nametab + (nt2 << 10) - 0x2400; - ppu.page[10] = ppu.nametab + (nt3 << 10) - 0x2800; - ppu.page[11] = ppu.nametab + (nt4 << 10) - 0x2C00; - ppu.page[12] = ppu.page[8] - 0x1000; - ppu.page[13] = ppu.page[9] - 0x1000; - ppu.page[14] = ppu.page[10] - 0x1000; - ppu.page[15] = ppu.page[11] - 0x1000; + ppu->page[8] = ppu->nametab + (nt1 << 10) - 0x2000; + ppu->page[9] = ppu->nametab + (nt2 << 10) - 0x2400; + ppu->page[10] = ppu->nametab + (nt3 << 10) - 0x2800; + ppu->page[11] = ppu->nametab + (nt4 << 10) - 0x2C00; + ppu->page[12] = ppu->page[8] - 0x1000; + ppu->page[13] = ppu->page[9] - 0x1000; + ppu->page[14] = ppu->page[10] - 0x1000; + ppu->page[15] = ppu->page[11] - 0x1000; } /* bleh, for snss */ uint8 *ppu_getpage(int page) { - return ppu.page[page]; + return ppu->page[page]; } static void mem_trash(uint8 *buffer, int length) @@ -216,18 +218,18 @@ static void mem_trash(uint8 *buffer, int length) void ppu_reset(int reset_type) { if (HARD_RESET == reset_type) - mem_trash(ppu.oam, 256); - - ppu.ctrl0 = 0; - ppu.ctrl1 = PPU_CTRL1F_OBJON | PPU_CTRL1F_BGON; - ppu.stat = 0; - ppu.flipflop = 0; - ppu.vaddr = ppu.vaddr_latch = 0x2000; - ppu.oam_addr = 0; - ppu.tile_xofs = 0; - - ppu.latch = 0; - ppu.vram_accessible = true; + mem_trash(ppu->oam, 256); + + ppu->ctrl0 = 0; + ppu->ctrl1 = PPU_CTRL1F_OBJON | PPU_CTRL1F_BGON; + ppu->stat = 0; + ppu->flipflop = 0; + ppu->vaddr = ppu->vaddr_latch = 0x2000; + ppu->oam_addr = 0; + ppu->tile_xofs = 0; + + ppu->latch = 0; + ppu->vram_accessible = true; } /* we render a scanline of graphics first so we know exactly @@ -236,12 +238,12 @@ void ppu_reset(int reset_type) */ static void ppu_setstrike(int x_loc) { - if (false == ppu.strikeflag) + if (false == ppu->strikeflag) { - ppu.strikeflag = true; + ppu->strikeflag = true; /* 3 pixels per cpu cycle */ - ppu.strike_cycle = nes6502_getcycles(false) + (x_loc / 3); + ppu->strike_cycle = nes6502_getcycles(false) + (x_loc / 3); } } @@ -253,29 +255,29 @@ static void ppu_oamdma(uint8 value) cpu_address = (uint32) (value << 8); /* Sprite DMA starts at the current SPRRAM address */ - oam_loc = ppu.oam_addr; + oam_loc = ppu->oam_addr; do { - ppu.oam[oam_loc++] = nes6502_getbyte(cpu_address++); + ppu->oam[oam_loc++] = nes6502_getbyte(cpu_address++); } - while (oam_loc != ppu.oam_addr); + while (oam_loc != ppu->oam_addr); /* TODO: enough with houdini */ cpu_address -= 256; /* Odd address in $2003 */ - if ((ppu.oam_addr >> 2) & 1) + if ((ppu->oam_addr >> 2) & 1) { for (oam_loc = 4; oam_loc < 8; oam_loc++) - ppu.oam[oam_loc] = nes6502_getbyte(cpu_address++); + ppu->oam[oam_loc] = nes6502_getbyte(cpu_address++); cpu_address += 248; for (oam_loc = 0; oam_loc < 4; oam_loc++) - ppu.oam[oam_loc] = nes6502_getbyte(cpu_address++); + ppu->oam[oam_loc] = nes6502_getbyte(cpu_address++); } /* Even address in $2003 */ else { for (oam_loc = 0; oam_loc < 8; oam_loc++) - ppu.oam[oam_loc] = nes6502_getbyte(cpu_address++); + ppu->oam[oam_loc] = nes6502_getbyte(cpu_address++); } /* make the CPU spin for DMA cycles */ @@ -294,16 +296,16 @@ void ppu_writehigh(uint32 address, uint8 value) case PPU_JOY0: /* VS system VROM switching - bleh!*/ - if (ppu.vromswitch) - ppu.vromswitch(value); + if (ppu->vromswitch) + ppu->vromswitch(value); /* see if we need to strobe them joypads */ value &= 1; - if (0 == value && ppu.strobe) + if (0 == value && ppu->strobe) input_strobe(); - ppu.strobe = value; + ppu->strobe = value; break; case PPU_JOY1: /* frame IRQ control */ @@ -350,40 +352,40 @@ uint8 ppu_read(uint32 address) switch (address & 0x2007) { case PPU_STAT: - value = (ppu.stat & 0xE0) | (ppu.latch & 0x1F); + value = (ppu->stat & 0xE0) | (ppu->latch & 0x1F); - if (ppu.strikeflag) + if (ppu->strikeflag) { - if (nes6502_getcycles(false) >= ppu.strike_cycle) + if (nes6502_getcycles(false) >= ppu->strike_cycle) value |= PPU_STATF_STRIKE; } /* clear both vblank flag and vram address flipflop */ - ppu.stat &= ~PPU_STATF_VBLANK; - ppu.flipflop = 0; + ppu->stat &= ~PPU_STATF_VBLANK; + ppu->flipflop = 0; break; case PPU_VDATA: /* buffered VRAM reads */ - value = ppu.latch = ppu.vdata_latch; + value = ppu->latch = ppu->vdata_latch; /* VRAM only accessible during VBL */ - if ((ppu.bg_on || ppu.obj_on) && !ppu.vram_accessible) + if ((ppu->bg_on || ppu->obj_on) && !ppu->vram_accessible) { - ppu.vdata_latch = 0xFF; + ppu->vdata_latch = 0xFF; //log_printf("VRAM read at $%04X, scanline %d\n", - // ppu.vaddr, nes_getcontextptr()->scanline); + // ppu->vaddr, nes_getcontextptr()->scanline); } else { - uint32 addr = ppu.vaddr; + uint32 addr = ppu->vaddr; if (addr >= 0x3000) addr -= 0x1000; - ppu.vdata_latch = PPU_MEM(addr); + ppu->vdata_latch = PPU_MEM(addr); } - ppu.vaddr += ppu.vaddr_inc; - ppu.vaddr &= 0x3FFF; + ppu->vaddr += ppu->vaddr_inc; + ppu->vaddr &= 0x3FFF; break; case PPU_OAMDATA: @@ -393,7 +395,7 @@ uint8 ppu_read(uint32 address) case PPU_SCROLL: case PPU_VADDR: default: - value = ppu.latch; + value = ppu->latch; break; } @@ -404,117 +406,117 @@ uint8 ppu_read(uint32 address) void ppu_write(uint32 address, uint8 value) { /* write goes into ppu latch... */ - ppu.latch = value; + ppu->latch = value; switch (address & 0x2007) { case PPU_CTRL0: - ppu.ctrl0 = value; + ppu->ctrl0 = value; - ppu.obj_height = (value & PPU_CTRL0F_OBJ16) ? 16 : 8; - ppu.bg_base = (value & PPU_CTRL0F_BGADDR) ? 0x1000 : 0; - ppu.obj_base = (value & PPU_CTRL0F_OBJADDR) ? 0x1000 : 0; - ppu.vaddr_inc = (value & PPU_CTRL0F_ADDRINC) ? 32 : 1; - ppu.tile_nametab = value & PPU_CTRL0F_NAMETAB; + ppu->obj_height = (value & PPU_CTRL0F_OBJ16) ? 16 : 8; + ppu->bg_base = (value & PPU_CTRL0F_BGADDR) ? 0x1000 : 0; + ppu->obj_base = (value & PPU_CTRL0F_OBJADDR) ? 0x1000 : 0; + ppu->vaddr_inc = (value & PPU_CTRL0F_ADDRINC) ? 32 : 1; + ppu->tile_nametab = value & PPU_CTRL0F_NAMETAB; /* Mask out bits 10 & 11 in the ppu latch */ - ppu.vaddr_latch &= ~0x0C00; - ppu.vaddr_latch |= ((value & 3) << 10); + ppu->vaddr_latch &= ~0x0C00; + ppu->vaddr_latch |= ((value & 3) << 10); break; case PPU_CTRL1: - ppu.ctrl1 = value; + ppu->ctrl1 = value; - ppu.obj_on = (value & PPU_CTRL1F_OBJON) ? true : false; - ppu.bg_on = (value & PPU_CTRL1F_BGON) ? true : false; - ppu.obj_mask = (value & PPU_CTRL1F_OBJMASK) ? false : true; - ppu.bg_mask = (value & PPU_CTRL1F_BGMASK) ? false : true; + ppu->obj_on = (value & PPU_CTRL1F_OBJON) ? true : false; + ppu->bg_on = (value & PPU_CTRL1F_BGON) ? true : false; + ppu->obj_mask = (value & PPU_CTRL1F_OBJMASK) ? false : true; + ppu->bg_mask = (value & PPU_CTRL1F_BGMASK) ? false : true; break; case PPU_OAMADDR: - ppu.oam_addr = value; + ppu->oam_addr = value; break; case PPU_OAMDATA: - ppu.oam[ppu.oam_addr++] = value; + ppu->oam[ppu->oam_addr++] = value; break; case PPU_SCROLL: - if (0 == ppu.flipflop) + if (0 == ppu->flipflop) { /* Mask out bits 4 - 0 in the ppu latch */ - ppu.vaddr_latch &= ~0x001F; - ppu.vaddr_latch |= (value >> 3); /* Tile number */ - ppu.tile_xofs = (value & 7); /* Tile offset (0-7 pix) */ + ppu->vaddr_latch &= ~0x001F; + ppu->vaddr_latch |= (value >> 3); /* Tile number */ + ppu->tile_xofs = (value & 7); /* Tile offset (0-7 pix) */ } else { /* Mask out bits 14-12 and 9-5 in the ppu latch */ - ppu.vaddr_latch &= ~0x73E0; - ppu.vaddr_latch |= ((value & 0xF8) << 2); /* Tile number */ - ppu.vaddr_latch |= ((value & 7) << 12); /* Tile offset (0-7 pix) */ + ppu->vaddr_latch &= ~0x73E0; + ppu->vaddr_latch |= ((value & 0xF8) << 2); /* Tile number */ + ppu->vaddr_latch |= ((value & 7) << 12); /* Tile offset (0-7 pix) */ } - ppu.flipflop ^= 1; + ppu->flipflop ^= 1; break; case PPU_VADDR: - if (0 == ppu.flipflop) + if (0 == ppu->flipflop) { /* Mask out bits 15-8 in ppu latch */ - ppu.vaddr_latch &= ~0xFF00; - ppu.vaddr_latch |= ((value & 0x3F) << 8); + ppu->vaddr_latch &= ~0xFF00; + ppu->vaddr_latch |= ((value & 0x3F) << 8); } else { /* Mask out bits 7-0 in ppu latch */ - ppu.vaddr_latch &= ~0x00FF; - ppu.vaddr_latch |= value; - ppu.vaddr = ppu.vaddr_latch; + ppu->vaddr_latch &= ~0x00FF; + ppu->vaddr_latch |= value; + ppu->vaddr = ppu->vaddr_latch; } - ppu.flipflop ^= 1; + ppu->flipflop ^= 1; break; case PPU_VDATA: - if (ppu.vaddr < 0x3F00) + if (ppu->vaddr < 0x3F00) { /* VRAM only accessible during scanlines 241-260 */ - if ((ppu.bg_on || ppu.obj_on) && !ppu.vram_accessible) + if ((ppu->bg_on || ppu->obj_on) && !ppu->vram_accessible) { log_printf("VRAM write to $%04X, scanline %d\n", - ppu.vaddr, nes_getcontextptr()->scanline); - PPU_MEM(ppu.vaddr) = 0xFF; /* corrupt */ + ppu->vaddr, nes_getcontextptr()->scanline); + PPU_MEM(ppu->vaddr) = 0xFF; /* corrupt */ } else { - uint32 addr = ppu.vaddr; + uint32 addr = ppu->vaddr; - if (false == ppu.vram_present && addr >= 0x3000) - ppu.vaddr -= 0x1000; + if (false == ppu->vram_present && addr >= 0x3000) + ppu->vaddr -= 0x1000; PPU_MEM(addr) = value; } } else { - if (0 == (ppu.vaddr & 0x0F)) + if (0 == (ppu->vaddr & 0x0F)) { int i; for (i = 0; i < 8; i ++) - ppu.palette[i << 2] = (value & 0x3F) | BG_TRANS; + ppu->palette[i << 2] = (value & 0x3F) | BG_TRANS; } - else if (ppu.vaddr & 3) + else if (ppu->vaddr & 3) { - ppu.palette[ppu.vaddr & 0x1F] = value & 0x3F; + ppu->palette[ppu->vaddr & 0x1F] = value & 0x3F; } } - ppu.vaddr += ppu.vaddr_inc; - ppu.vaddr &= 0x3FFF; + ppu->vaddr += ppu->vaddr_inc; + ppu->vaddr &= 0x3FFF; break; default: @@ -559,12 +561,12 @@ void ppu_setdefaultpal(ppu_t *src_ppu) void ppu_setlatchfunc(ppulatchfunc_t func) { - ppu.latchfunc = func; + ppu->latchfunc = func; } void ppu_setvromswitch(ppuvromswitch_t func) { - ppu.vromswitch = func; + ppu->vromswitch = func; } /* rendering routines */ @@ -694,17 +696,17 @@ static void ppu_renderbg(uint8 *vidbuf) uint8 col_high, attrib, attrib_shift; /* draw a line of transparent background color if bg is disabled */ - if (false == ppu.bg_on) + if (false == ppu->bg_on) { memset(vidbuf, FULLBG, NES_SCREEN_WIDTH); return; } - bmp_ptr = vidbuf - ppu.tile_xofs; /* scroll x */ - refresh_vaddr = 0x2000 + (ppu.vaddr & 0x0FE0); /* mask out x tile */ - x_tile = ppu.vaddr & 0x1F; - y_tile = (ppu.vaddr >> 5) & 0x1F; /* to simplify calculations */ - bg_offset = ((ppu.vaddr >> 12) & 7) + ppu.bg_base; /* offset in y tile */ + bmp_ptr = vidbuf - ppu->tile_xofs; /* scroll x */ + refresh_vaddr = 0x2000 + (ppu->vaddr & 0x0FE0); /* mask out x tile */ + x_tile = ppu->vaddr & 0x1F; + y_tile = (ppu->vaddr >> 5) & 0x1F; /* to simplify calculations */ + bg_offset = ((ppu->vaddr >> 12) & 7) + ppu->bg_base; /* offset in y tile */ /* calculate initial values */ tile_ptr = &PPU_MEM(refresh_vaddr + x_tile); /* pointer to tile index */ @@ -723,10 +725,10 @@ static void ppu_renderbg(uint8 *vidbuf) data_ptr = &PPU_MEM(bg_offset + (tile_index << 4)); /* Handle $FD/$FE tile VROM switching (PunchOut) */ - if (ppu.latchfunc) - ppu.latchfunc(ppu.bg_base, tile_index); + if (ppu->latchfunc) + ppu->latchfunc(ppu->bg_base, tile_index); - draw_bgtile(bmp_ptr, data_ptr[0], data_ptr[8], ppu.palette + col_high); + draw_bgtile(bmp_ptr, data_ptr[0], data_ptr[8], ppu->palette + col_high); bmp_ptr += 8; x_tile++; @@ -756,7 +758,7 @@ static void ppu_renderbg(uint8 *vidbuf) } /* Blank left hand column if need be */ - if (ppu.bg_mask) + if (ppu->bg_mask) { uint32 *buf_ptr = (uint32 *) vidbuf; uint32 bg_clear = FULLBG | FULLBG << 8 | FULLBG << 16 | FULLBG << 24; @@ -785,24 +787,24 @@ static void ppu_renderoam(uint8 *vidbuf, int scanline) obj_t *sprite_ptr; uint8 sprite_height; - if (false == ppu.obj_on) + if (false == ppu->obj_on) return; /* Get our buffer pointer */ buf_ptr = vidbuf; /* Save left hand column? */ - if (ppu.obj_mask) + if (ppu->obj_mask) { savecol[0] = ((uint32 *) buf_ptr)[0]; savecol[1] = ((uint32 *) buf_ptr)[1]; } - sprite_height = ppu.obj_height; - vram_offset = ppu.obj_base; + sprite_height = ppu->obj_height; + vram_offset = ppu->obj_base; spritecount = 0; - sprite_ptr = (obj_t *) ppu.oam; + sprite_ptr = (obj_t *) ppu->oam; for (sprite_num = 0; sprite_num < 64; sprite_num++, sprite_ptr++) { @@ -828,14 +830,14 @@ static void ppu_renderoam(uint8 *vidbuf, int scanline) bmp_ptr = buf_ptr + sprite_x; /* Handle $FD/$FE tile VROM switching (PunchOut) */ - if (ppu.latchfunc) - ppu.latchfunc(vram_offset, tile_index); + if (ppu->latchfunc) + ppu->latchfunc(vram_offset, tile_index); /* Get upper two bits of color */ col_high = ((attrib & 3) << 2); /* 8x16 even sprites use $0000, odd use $1000 */ - if (16 == ppu.obj_height) + if (16 == ppu->obj_height) vram_adr = ((tile_index & 1) << 12) | ((tile_index & 0xFE) << 4); else vram_adr = vram_offset + (tile_index << 4); @@ -851,7 +853,7 @@ static void ppu_renderoam(uint8 *vidbuf, int scanline) /* Account for vertical flippage */ if (attrib & OAMF_VFLIP) { - if (16 == ppu.obj_height) + if (16 == ppu->obj_height) y_offset -= 23; else y_offset -= 7; @@ -866,21 +868,21 @@ static void ppu_renderoam(uint8 *vidbuf, int scanline) /* if we're on sprite 0 and sprite 0 strike flag isn't set, ** check for a strike */ - check_strike = (0 == sprite_num) && (false == ppu.strikeflag); - strike_pixel = draw_oamtile(bmp_ptr, attrib, data_ptr[0], data_ptr[8], ppu.palette + 16 + col_high, check_strike); + check_strike = (0 == sprite_num) && (false == ppu->strikeflag); + strike_pixel = draw_oamtile(bmp_ptr, attrib, data_ptr[0], data_ptr[8], ppu->palette + 16 + col_high, check_strike); if (strike_pixel >= 0) ppu_setstrike(strike_pixel); /* maximum of 8 sprites per scanline */ if (++spritecount == PPU_MAXSPRITE) { - ppu.stat |= PPU_STATF_MAXSPRITE; + ppu->stat |= PPU_STATF_MAXSPRITE; break; } } /* Restore lefthand column */ - if (ppu.obj_mask) + if (ppu->obj_mask) { ((uint32 *) buf_ptr)[0] = savecol[0]; ((uint32 *) buf_ptr)[1] = savecol[1]; @@ -901,11 +903,11 @@ static void ppu_fakeoam(int scanline) /* we don't need to be here if strike flag is set */ - if (false == ppu.obj_on || ppu.strikeflag) + if (false == ppu->obj_on || ppu->strikeflag) return; - sprite_height = ppu.obj_height; - sprite_ptr = (obj_t *) ppu.oam; + sprite_height = ppu->obj_height; + sprite_ptr = (obj_t *) ppu->oam; sprite_y = sprite_ptr->y_loc + 1; /* Check to see if sprite is out of range */ @@ -918,10 +920,10 @@ static void ppu_fakeoam(int scanline) attrib = sprite_ptr->atr; /* 8x16 even sprites use $0000, odd use $1000 */ - if (16 == ppu.obj_height) + if (16 == ppu->obj_height) vram_adr = ((tile_index & 1) << 12) | ((tile_index & 0xFE) << 4); else - vram_adr = ppu.obj_base + (tile_index << 4); + vram_adr = ppu->obj_base + (tile_index << 4); data_ptr = &PPU_MEM(vram_adr); @@ -933,7 +935,7 @@ static void ppu_fakeoam(int scanline) /* Account for vertical flippage */ if (attrib & OAMF_VFLIP) { - if (16 == ppu.obj_height) + if (16 == ppu->obj_height) y_offset -= 23; else y_offset -= 7; @@ -999,7 +1001,7 @@ static void ppu_fakeoam(int scanline) bool ppu_enabled(void) { - return (ppu.bg_on || ppu.obj_on); + return (ppu->bg_on || ppu->obj_on); } static void ppu_renderscanline(bitmap_t *bmp, int scanline, bool draw_flag) @@ -1007,16 +1009,16 @@ static void ppu_renderscanline(bitmap_t *bmp, int scanline, bool draw_flag) uint8 *buf = bmp->line[scanline]; /* start scanline - transfer ppu latch into vaddr */ - if (ppu.bg_on || ppu.obj_on) + if (ppu->bg_on || ppu->obj_on) { if (0 == scanline) { - ppu.vaddr = ppu.vaddr_latch; + ppu->vaddr = ppu->vaddr_latch; } else { - ppu.vaddr &= ~0x041F; - ppu.vaddr |= (ppu.vaddr_latch & 0x041F); + ppu->vaddr &= ~0x041F; + ppu->vaddr |= (ppu->vaddr_latch & 0x041F); } } @@ -1024,7 +1026,7 @@ static void ppu_renderscanline(bitmap_t *bmp, int scanline, bool draw_flag) ppu_renderbg(buf); /* TODO: fetch obj data 1 scanline before */ - if (true == ppu.drawsprites && true == draw_flag) + if (true == ppu->drawsprites && true == draw_flag) ppu_renderoam(buf, scanline); else ppu_fakeoam(scanline); @@ -1034,40 +1036,40 @@ static void ppu_renderscanline(bitmap_t *bmp, int scanline, bool draw_flag) void ppu_endscanline(int scanline) { /* modify vram address at end of scanline */ - if (scanline < 240 && (ppu.bg_on || ppu.obj_on)) + if (scanline < 240 && (ppu->bg_on || ppu->obj_on)) { int ytile; /* check for max 3 bit y tile offset */ - if (7 == (ppu.vaddr >> 12)) + if (7 == (ppu->vaddr >> 12)) { - ppu.vaddr &= ~0x7000; /* clear y tile offset */ - ytile = (ppu.vaddr >> 5) & 0x1F; + ppu->vaddr &= ~0x7000; /* clear y tile offset */ + ytile = (ppu->vaddr >> 5) & 0x1F; if (29 == ytile) { - ppu.vaddr &= ~0x03E0; /* clear y tile */ - ppu.vaddr ^= 0x0800; /* toggle nametable */ + ppu->vaddr &= ~0x03E0; /* clear y tile */ + ppu->vaddr ^= 0x0800; /* toggle nametable */ } else if (31 == ytile) { - ppu.vaddr &= ~0x03E0; /* clear y tile */ + ppu->vaddr &= ~0x03E0; /* clear y tile */ } else { - ppu.vaddr += 0x20; /* increment y tile */ + ppu->vaddr += 0x20; /* increment y tile */ } } else { - ppu.vaddr += 0x1000; /* increment tile y offset */ + ppu->vaddr += 0x1000; /* increment tile y offset */ } } } void ppu_checknmi(void) { - if (ppu.ctrl0 & PPU_CTRL0F_NMI) + if (ppu->ctrl0 & PPU_CTRL0F_NMI) nes_nmi(); } @@ -1076,21 +1078,21 @@ void ppu_scanline(bitmap_t *bmp, int scanline, bool draw_flag) if (scanline < 240) { /* Lower the Max Sprite per scanline flag */ - ppu.stat &= ~PPU_STATF_MAXSPRITE; + ppu->stat &= ~PPU_STATF_MAXSPRITE; ppu_renderscanline(bmp, scanline, draw_flag); } else if (241 == scanline) { - ppu.stat |= PPU_STATF_VBLANK; - ppu.vram_accessible = true; + ppu->stat |= PPU_STATF_VBLANK; + ppu->vram_accessible = true; } else if (261 == scanline) { - ppu.stat &= ~PPU_STATF_VBLANK; - ppu.strikeflag = false; - ppu.strike_cycle = (uint32) -1; + ppu->stat &= ~PPU_STATF_VBLANK; + ppu->strikeflag = false; + ppu->strike_cycle = (uint32) -1; - ppu.vram_accessible = false; + ppu->vram_accessible = false; } } @@ -1123,12 +1125,12 @@ static void draw_sprite(bitmap_t *bmp, int x, int y, uint8 tile_num, uint8 attri col_high = ((attrib & 3) << 2); /* 8x16 even sprites use $0000, odd use $1000 */ - height = ppu.obj_height; + height = ppu->obj_height; if (16 == height) vram_adr = ((tile_num & 1) << 12) | ((tile_num & 0xFE) << 4); /* else just use the offset from $2000 */ else - vram_adr = ppu.obj_base + (tile_num << 4); + vram_adr = ppu->obj_base + (tile_num << 4); data_ptr = &PPU_MEM(vram_adr); @@ -1137,8 +1139,8 @@ static void draw_sprite(bitmap_t *bmp, int x, int y, uint8 tile_num, uint8 attri if (line == 8) data_ptr += 8; - draw_bgtile(vid, data_ptr[0], data_ptr[8], ppu.palette + 16 + col_high); - //draw_oamtile(vid, attrib, data_ptr[0], data_ptr[8], ppu.palette + 16 + col_high); + draw_bgtile(vid, data_ptr[0], data_ptr[8], ppu->palette + 16 + col_high); + //draw_oamtile(vid, attrib, data_ptr[0], data_ptr[8], ppu->palette + 16 + col_high); data_ptr++; vid += bmp->pitch; diff --git a/components/nes/nofrendo/sndhrdw/nes_apu.c b/components/nes/nofrendo/sndhrdw/nes_apu.c index c09dee05..0e137c4f 100644 --- a/components/nes/nofrendo/sndhrdw/nes_apu.c +++ b/components/nes/nofrendo/sndhrdw/nes_apu.c @@ -36,13 +36,13 @@ /* the following seem to be the correct (empirically determined) ** relative volumes between the sound channels */ -#define APU_RECTANGLE_OUTPUT(channel) (apu.rectangle[channel].output_vol) -#define APU_TRIANGLE_OUTPUT (apu.triangle.output_vol + (apu.triangle.output_vol >> 2)) -#define APU_NOISE_OUTPUT ((apu.noise.output_vol + apu.noise.output_vol + apu.noise.output_vol) >> 2) -#define APU_DMC_OUTPUT ((apu.dmc.output_vol + apu.dmc.output_vol + apu.dmc.output_vol) >> 2) +#define APU_RECTANGLE_OUTPUT(channel) (apu->rectangle[channel].output_vol) +#define APU_TRIANGLE_OUTPUT (apu->triangle.output_vol + (apu->triangle.output_vol >> 2)) +#define APU_NOISE_OUTPUT ((apu->noise.output_vol + apu->noise.output_vol + apu->noise.output_vol) >> 2) +#define APU_DMC_OUTPUT ((apu->dmc.output_vol + apu->dmc.output_vol + apu->dmc.output_vol) >> 2) /* active APU */ -static apu_t apu; +static apu_t *apu = NULL; /* look up table madness */ static int32 decay_lut[16]; @@ -103,20 +103,20 @@ static const int duty_flip[4] = { 2, 4, 8, 12 }; void apu_setcontext(apu_t *src_apu) { - apu = *src_apu; + apu = src_apu; } void apu_getcontext(apu_t *dest_apu) { - *dest_apu = apu; + *dest_apu = *apu; } void apu_setchan(int chan, bool enabled) { if (enabled) - apu.mix_enable |= (1 << chan); + apu->mix_enable |= (1 << chan); else - apu.mix_enable &= ~(1 << chan); + apu->mix_enable &= ~(1 << chan); } /* emulation of the 15-bit shift register the @@ -184,72 +184,72 @@ static int32 apu_rectangle_##ch(void) \ int32 output, total; \ int num_times; \ \ - APU_VOLUME_DECAY(apu.rectangle[ch].output_vol); \ + APU_VOLUME_DECAY(apu->rectangle[ch].output_vol); \ \ - if (false == apu.rectangle[ch].enabled || 0 == apu.rectangle[ch].vbl_length) \ + if (false == apu->rectangle[ch].enabled || 0 == apu->rectangle[ch].vbl_length) \ return APU_RECTANGLE_OUTPUT(ch); \ \ /* vbl length counter */ \ - if (false == apu.rectangle[ch].holdnote) \ - apu.rectangle[ch].vbl_length--; \ + if (false == apu->rectangle[ch].holdnote) \ + apu->rectangle[ch].vbl_length--; \ \ /* envelope decay at a rate of (env_delay + 1) / 240 secs */ \ - apu.rectangle[ch].env_phase -= 4; /* 240/60 */ \ - while (apu.rectangle[ch].env_phase < 0) \ + apu->rectangle[ch].env_phase -= 4; /* 240/60 */ \ + while (apu->rectangle[ch].env_phase < 0) \ { \ - apu.rectangle[ch].env_phase += apu.rectangle[ch].env_delay; \ + apu->rectangle[ch].env_phase += apu->rectangle[ch].env_delay; \ \ - if (apu.rectangle[ch].holdnote) \ - apu.rectangle[ch].env_vol = (apu.rectangle[ch].env_vol + 1) & 0x0F; \ - else if (apu.rectangle[ch].env_vol < 0x0F) \ - apu.rectangle[ch].env_vol++; \ + if (apu->rectangle[ch].holdnote) \ + apu->rectangle[ch].env_vol = (apu->rectangle[ch].env_vol + 1) & 0x0F; \ + else if (apu->rectangle[ch].env_vol < 0x0F) \ + apu->rectangle[ch].env_vol++; \ } \ \ /* TODO: find true relation of freq_limit to register values */ \ - if (apu.rectangle[ch].freq < 8 \ - || (false == apu.rectangle[ch].sweep_inc \ - && apu.rectangle[ch].freq > apu.rectangle[ch].freq_limit)) \ + if (apu->rectangle[ch].freq < 8 \ + || (false == apu->rectangle[ch].sweep_inc \ + && apu->rectangle[ch].freq > apu->rectangle[ch].freq_limit)) \ return APU_RECTANGLE_OUTPUT(ch); \ \ /* frequency sweeping at a rate of (sweep_delay + 1) / 120 secs */ \ - if (apu.rectangle[ch].sweep_on && apu.rectangle[ch].sweep_shifts) \ + if (apu->rectangle[ch].sweep_on && apu->rectangle[ch].sweep_shifts) \ { \ - apu.rectangle[ch].sweep_phase -= 2; /* 120/60 */ \ - while (apu.rectangle[ch].sweep_phase < 0) \ + apu->rectangle[ch].sweep_phase -= 2; /* 120/60 */ \ + while (apu->rectangle[ch].sweep_phase < 0) \ { \ - apu.rectangle[ch].sweep_phase += apu.rectangle[ch].sweep_delay; \ + apu->rectangle[ch].sweep_phase += apu->rectangle[ch].sweep_delay; \ \ - if (apu.rectangle[ch].sweep_inc) /* ramp up */ \ + if (apu->rectangle[ch].sweep_inc) /* ramp up */ \ { \ if (0 == ch) \ - apu.rectangle[ch].freq += ~(apu.rectangle[ch].freq >> apu.rectangle[ch].sweep_shifts); \ + apu->rectangle[ch].freq += ~(apu->rectangle[ch].freq >> apu->rectangle[ch].sweep_shifts); \ else \ - apu.rectangle[ch].freq -= (apu.rectangle[ch].freq >> apu.rectangle[ch].sweep_shifts); \ + apu->rectangle[ch].freq -= (apu->rectangle[ch].freq >> apu->rectangle[ch].sweep_shifts); \ } \ else /* ramp down */ \ { \ - apu.rectangle[ch].freq += (apu.rectangle[ch].freq >> apu.rectangle[ch].sweep_shifts); \ + apu->rectangle[ch].freq += (apu->rectangle[ch].freq >> apu->rectangle[ch].sweep_shifts); \ } \ } \ } \ \ - apu.rectangle[ch].accum -= apu.cycle_rate; \ - if (apu.rectangle[ch].accum >= 0) \ + apu->rectangle[ch].accum -= apu->cycle_rate; \ + if (apu->rectangle[ch].accum >= 0) \ return APU_RECTANGLE_OUTPUT(ch); \ \ - if (apu.rectangle[ch].fixed_envelope) \ - output = apu.rectangle[ch].volume << 8; /* fixed volume */ \ + if (apu->rectangle[ch].fixed_envelope) \ + output = apu->rectangle[ch].volume << 8; /* fixed volume */ \ else \ - output = (apu.rectangle[ch].env_vol ^ 0x0F) << 8; \ + output = (apu->rectangle[ch].env_vol ^ 0x0F) << 8; \ \ num_times = total = 0; \ \ - while (apu.rectangle[ch].accum < 0) \ + while (apu->rectangle[ch].accum < 0) \ { \ - apu.rectangle[ch].accum += apu.rectangle[ch].freq + 1; \ - apu.rectangle[ch].adder = (apu.rectangle[ch].adder + 1) & 0x0F; \ + apu->rectangle[ch].accum += apu->rectangle[ch].freq + 1; \ + apu->rectangle[ch].adder = (apu->rectangle[ch].adder + 1) & 0x0F; \ \ - if (apu.rectangle[ch].adder < apu.rectangle[ch].duty_flip) \ + if (apu->rectangle[ch].adder < apu->rectangle[ch].duty_flip) \ total += output; \ else \ total -= output; \ @@ -257,7 +257,7 @@ static int32 apu_rectangle_##ch(void) \ num_times++; \ } \ \ - apu.rectangle[ch].output_vol = total / num_times; \ + apu->rectangle[ch].output_vol = total / num_times; \ return APU_RECTANGLE_OUTPUT(ch); \ } @@ -267,72 +267,72 @@ static int32 apu_rectangle_##ch(void) \ { \ int32 output; \ \ - APU_VOLUME_DECAY(apu.rectangle[ch].output_vol); \ + APU_VOLUME_DECAY(apu->rectangle[ch].output_vol); \ \ - if (false == apu.rectangle[ch].enabled || 0 == apu.rectangle[ch].vbl_length) \ + if (false == apu->rectangle[ch].enabled || 0 == apu->rectangle[ch].vbl_length) \ return APU_RECTANGLE_OUTPUT(ch); \ \ /* vbl length counter */ \ - if (false == apu.rectangle[ch].holdnote) \ - apu.rectangle[ch].vbl_length--; \ + if (false == apu->rectangle[ch].holdnote) \ + apu->rectangle[ch].vbl_length--; \ \ /* envelope decay at a rate of (env_delay + 1) / 240 secs */ \ - apu.rectangle[ch].env_phase -= 4; /* 240/60 */ \ - while (apu.rectangle[ch].env_phase < 0) \ + apu->rectangle[ch].env_phase -= 4; /* 240/60 */ \ + while (apu->rectangle[ch].env_phase < 0) \ { \ - apu.rectangle[ch].env_phase += apu.rectangle[ch].env_delay; \ + apu->rectangle[ch].env_phase += apu->rectangle[ch].env_delay; \ \ - if (apu.rectangle[ch].holdnote) \ - apu.rectangle[ch].env_vol = (apu.rectangle[ch].env_vol + 1) & 0x0F; \ - else if (apu.rectangle[ch].env_vol < 0x0F) \ - apu.rectangle[ch].env_vol++; \ + if (apu->rectangle[ch].holdnote) \ + apu->rectangle[ch].env_vol = (apu->rectangle[ch].env_vol + 1) & 0x0F; \ + else if (apu->rectangle[ch].env_vol < 0x0F) \ + apu->rectangle[ch].env_vol++; \ } \ \ /* TODO: find true relation of freq_limit to register values */ \ - if (apu.rectangle[ch].freq < 8 || (false == apu.rectangle[ch].sweep_inc && apu.rectangle[ch].freq > apu.rectangle[ch].freq_limit)) \ + if (apu->rectangle[ch].freq < 8 || (false == apu->rectangle[ch].sweep_inc && apu->rectangle[ch].freq > apu->rectangle[ch].freq_limit)) \ return APU_RECTANGLE_OUTPUT(ch); \ \ /* frequency sweeping at a rate of (sweep_delay + 1) / 120 secs */ \ - if (apu.rectangle[ch].sweep_on && apu.rectangle[ch].sweep_shifts) \ + if (apu->rectangle[ch].sweep_on && apu->rectangle[ch].sweep_shifts) \ { \ - apu.rectangle[ch].sweep_phase -= 2; /* 120/60 */ \ - while (apu.rectangle[ch].sweep_phase < 0) \ + apu->rectangle[ch].sweep_phase -= 2; /* 120/60 */ \ + while (apu->rectangle[ch].sweep_phase < 0) \ { \ - apu.rectangle[ch].sweep_phase += apu.rectangle[ch].sweep_delay; \ + apu->rectangle[ch].sweep_phase += apu->rectangle[ch].sweep_delay; \ \ - if (apu.rectangle[ch].sweep_inc) /* ramp up */ \ + if (apu->rectangle[ch].sweep_inc) /* ramp up */ \ { \ if (0 == ch) \ - apu.rectangle[ch].freq += ~(apu.rectangle[ch].freq >> apu.rectangle[ch].sweep_shifts); \ + apu->rectangle[ch].freq += ~(apu->rectangle[ch].freq >> apu->rectangle[ch].sweep_shifts); \ else \ - apu.rectangle[ch].freq -= (apu.rectangle[ch].freq >> apu.rectangle[ch].sweep_shifts); \ + apu->rectangle[ch].freq -= (apu->rectangle[ch].freq >> apu->rectangle[ch].sweep_shifts); \ } \ else /* ramp down */ \ { \ - apu.rectangle[ch].freq += (apu.rectangle[ch].freq >> apu.rectangle[ch].sweep_shifts); \ + apu->rectangle[ch].freq += (apu->rectangle[ch].freq >> apu->rectangle[ch].sweep_shifts); \ } \ } \ } \ \ - apu.rectangle[ch].accum -= apu.cycle_rate; \ - if (apu.rectangle[ch].accum >= 0) \ + apu->rectangle[ch].accum -= apu->cycle_rate; \ + if (apu->rectangle[ch].accum >= 0) \ return APU_RECTANGLE_OUTPUT(ch); \ \ - while (apu.rectangle[ch].accum < 0) \ + while (apu->rectangle[ch].accum < 0) \ { \ - apu.rectangle[ch].accum += (apu.rectangle[ch].freq + 1); \ - apu.rectangle[ch].adder = (apu.rectangle[ch].adder + 1) & 0x0F; \ + apu->rectangle[ch].accum += (apu->rectangle[ch].freq + 1); \ + apu->rectangle[ch].adder = (apu->rectangle[ch].adder + 1) & 0x0F; \ } \ \ - if (apu.rectangle[ch].fixed_envelope) \ - output = apu.rectangle[ch].volume << 8; /* fixed volume */ \ + if (apu->rectangle[ch].fixed_envelope) \ + output = apu->rectangle[ch].volume << 8; /* fixed volume */ \ else \ - output = (apu.rectangle[ch].env_vol ^ 0x0F) << 8; \ + output = (apu->rectangle[ch].env_vol ^ 0x0F) << 8; \ \ - if (0 == apu.rectangle[ch].adder) \ - apu.rectangle[ch].output_vol = output; \ - else if (apu.rectangle[ch].adder == apu.rectangle[ch].duty_flip) \ - apu.rectangle[ch].output_vol = -output; \ + if (0 == apu->rectangle[ch].adder) \ + apu->rectangle[ch].output_vol = output; \ + else if (apu->rectangle[ch].adder == apu->rectangle[ch].duty_flip) \ + apu->rectangle[ch].output_vol = -output; \ \ return APU_RECTANGLE_OUTPUT(ch); \ } @@ -352,37 +352,37 @@ APU_MAKE_RECTANGLE(1) */ static int32 apu_triangle(void) { - APU_VOLUME_DECAY(apu.triangle.output_vol); + APU_VOLUME_DECAY(apu->triangle.output_vol); - if (false == apu.triangle.enabled || 0 == apu.triangle.vbl_length) + if (false == apu->triangle.enabled || 0 == apu->triangle.vbl_length) return APU_TRIANGLE_OUTPUT; - if (apu.triangle.counter_started) + if (apu->triangle.counter_started) { - if (apu.triangle.linear_length > 0) - apu.triangle.linear_length--; - if (apu.triangle.vbl_length && false == apu.triangle.holdnote) - apu.triangle.vbl_length--; + if (apu->triangle.linear_length > 0) + apu->triangle.linear_length--; + if (apu->triangle.vbl_length && false == apu->triangle.holdnote) + apu->triangle.vbl_length--; } - else if (false == apu.triangle.holdnote && apu.triangle.write_latency) + else if (false == apu->triangle.holdnote && apu->triangle.write_latency) { - if (--apu.triangle.write_latency == 0) - apu.triangle.counter_started = true; + if (--apu->triangle.write_latency == 0) + apu->triangle.counter_started = true; } - if (0 == apu.triangle.linear_length || apu.triangle.freq < 4) /* inaudible */ + if (0 == apu->triangle.linear_length || apu->triangle.freq < 4) /* inaudible */ return APU_TRIANGLE_OUTPUT; - apu.triangle.accum -= apu.cycle_rate; \ - while (apu.triangle.accum < 0) + apu->triangle.accum -= apu->cycle_rate; \ + while (apu->triangle.accum < 0) { - apu.triangle.accum += apu.triangle.freq; - apu.triangle.adder = (apu.triangle.adder + 1) & 0x1F; + apu->triangle.accum += apu->triangle.freq; + apu->triangle.adder = (apu->triangle.adder + 1) & 0x1F; - if (apu.triangle.adder & 0x10) - apu.triangle.output_vol -= (2 << 8); + if (apu->triangle.adder & 0x10) + apu->triangle.output_vol -= (2 << 8); else - apu.triangle.output_vol += (2 << 8); + apu->triangle.output_vol += (2 << 8); } return APU_TRIANGLE_OUTPUT; @@ -409,76 +409,76 @@ static int32 apu_noise(void) int32 total; #endif /* APU_OVERSAMPLE */ - APU_VOLUME_DECAY(apu.noise.output_vol); + APU_VOLUME_DECAY(apu->noise.output_vol); - if (false == apu.noise.enabled || 0 == apu.noise.vbl_length) + if (false == apu->noise.enabled || 0 == apu->noise.vbl_length) return APU_NOISE_OUTPUT; /* vbl length counter */ - if (false == apu.noise.holdnote) - apu.noise.vbl_length--; + if (false == apu->noise.holdnote) + apu->noise.vbl_length--; /* envelope decay at a rate of (env_delay + 1) / 240 secs */ - apu.noise.env_phase -= 4; /* 240/60 */ - while (apu.noise.env_phase < 0) + apu->noise.env_phase -= 4; /* 240/60 */ + while (apu->noise.env_phase < 0) { - apu.noise.env_phase += apu.noise.env_delay; + apu->noise.env_phase += apu->noise.env_delay; - if (apu.noise.holdnote) - apu.noise.env_vol = (apu.noise.env_vol + 1) & 0x0F; - else if (apu.noise.env_vol < 0x0F) - apu.noise.env_vol++; + if (apu->noise.holdnote) + apu->noise.env_vol = (apu->noise.env_vol + 1) & 0x0F; + else if (apu->noise.env_vol < 0x0F) + apu->noise.env_vol++; } - apu.noise.accum -= apu.cycle_rate; - if (apu.noise.accum >= 0) + apu->noise.accum -= apu->cycle_rate; + if (apu->noise.accum >= 0) return APU_NOISE_OUTPUT; #ifdef APU_OVERSAMPLE - if (apu.noise.fixed_envelope) - outvol = apu.noise.volume << 8; /* fixed volume */ + if (apu->noise.fixed_envelope) + outvol = apu->noise.volume << 8; /* fixed volume */ else - outvol = (apu.noise.env_vol ^ 0x0F) << 8; + outvol = (apu->noise.env_vol ^ 0x0F) << 8; num_times = total = 0; #endif /* APU_OVERSAMPLE */ - while (apu.noise.accum < 0) + while (apu->noise.accum < 0) { - apu.noise.accum += apu.noise.freq; + apu->noise.accum += apu->noise.freq; #ifdef REALTIME_NOISE #ifdef APU_OVERSAMPLE - if (shift_register15(apu.noise.xor_tap)) + if (shift_register15(apu->noise.xor_tap)) total += outvol; else total -= outvol; num_times++; #else /* !APU_OVERSAMPLE */ - noise_bit = shift_register15(apu.noise.xor_tap); + noise_bit = shift_register15(apu->noise.xor_tap); #endif /* !APU_OVERSAMPLE */ #else /* !REALTIME_NOISE */ - apu.noise.cur_pos++; + apu->noise.cur_pos++; - if (apu.noise.short_sample) + if (apu->noise.short_sample) { - if (APU_NOISE_93 == apu.noise.cur_pos) - apu.noise.cur_pos = 0; + if (APU_NOISE_93 == apu->noise.cur_pos) + apu->noise.cur_pos = 0; } else { - if (APU_NOISE_32K == apu.noise.cur_pos) - apu.noise.cur_pos = 0; + if (APU_NOISE_32K == apu->noise.cur_pos) + apu->noise.cur_pos = 0; } #ifdef APU_OVERSAMPLE - if (apu.noise.short_sample) - noise_bit = noise_short_lut[apu.noise.cur_pos]; + if (apu->noise.short_sample) + noise_bit = noise_short_lut[apu->noise.cur_pos]; else - noise_bit = noise_long_lut[apu.noise.cur_pos]; + noise_bit = noise_long_lut[apu->noise.cur_pos]; if (noise_bit) total += outvol; @@ -491,24 +491,24 @@ static int32 apu_noise(void) } #ifdef APU_OVERSAMPLE - apu.noise.output_vol = total / num_times; + apu->noise.output_vol = total / num_times; #else /* !APU_OVERSAMPLE */ - if (apu.noise.fixed_envelope) - outvol = apu.noise.volume << 8; /* fixed volume */ + if (apu->noise.fixed_envelope) + outvol = apu->noise.volume << 8; /* fixed volume */ else - outvol = (apu.noise.env_vol ^ 0x0F) << 8; + outvol = (apu->noise.env_vol ^ 0x0F) << 8; #ifndef REALTIME_NOISE - if (apu.noise.short_sample) - noise_bit = noise_short_lut[apu.noise.cur_pos]; + if (apu->noise.short_sample) + noise_bit = noise_short_lut[apu->noise.cur_pos]; else - noise_bit = noise_long_lut[apu.noise.cur_pos]; + noise_bit = noise_long_lut[apu->noise.cur_pos]; #endif /* !REALTIME_NOISE */ if (noise_bit) - apu.noise.output_vol = outvol; + apu->noise.output_vol = outvol; else - apu.noise.output_vol = -outvol; + apu->noise.output_vol = -outvol; #endif /* !APU_OVERSAMPLE */ return APU_NOISE_OUTPUT; @@ -517,9 +517,9 @@ static int32 apu_noise(void) INLINE void apu_dmcreload(void) { - apu.dmc.address = apu.dmc.cached_addr; - apu.dmc.dma_length = apu.dmc.cached_dmalength; - apu.dmc.irq_occurred = false; + apu->dmc.address = apu->dmc.cached_addr; + apu->dmc.dma_length = apu->dmc.cached_dmalength; + apu->dmc.irq_occurred = false; } /* DELTA MODULATION CHANNEL @@ -533,72 +533,72 @@ static int32 apu_dmc(void) { int delta_bit; - APU_VOLUME_DECAY(apu.dmc.output_vol); + APU_VOLUME_DECAY(apu->dmc.output_vol); /* only process when channel is alive */ - if (apu.dmc.dma_length) + if (apu->dmc.dma_length) { - apu.dmc.accum -= apu.cycle_rate; + apu->dmc.accum -= apu->cycle_rate; - while (apu.dmc.accum < 0) + while (apu->dmc.accum < 0) { - apu.dmc.accum += apu.dmc.freq; + apu->dmc.accum += apu->dmc.freq; - delta_bit = (apu.dmc.dma_length & 7) ^ 7; + delta_bit = (apu->dmc.dma_length & 7) ^ 7; if (7 == delta_bit) { - apu.dmc.cur_byte = nes6502_getbyte(apu.dmc.address); + apu->dmc.cur_byte = nes6502_getbyte(apu->dmc.address); /* steal a cycle from CPU*/ nes6502_burn(1); /* prevent wraparound */ - if (0xFFFF == apu.dmc.address) - apu.dmc.address = 0x8000; + if (0xFFFF == apu->dmc.address) + apu->dmc.address = 0x8000; else - apu.dmc.address++; + apu->dmc.address++; } - if (--apu.dmc.dma_length == 0) + if (--apu->dmc.dma_length == 0) { /* if loop bit set, we're cool to retrigger sample */ - if (apu.dmc.looping) + if (apu->dmc.looping) { apu_dmcreload(); } else { /* check to see if we should generate an irq */ - if (apu.dmc.irq_gen) + if (apu->dmc.irq_gen) { - apu.dmc.irq_occurred = true; - if (apu.irq_callback) - apu.irq_callback(); + apu->dmc.irq_occurred = true; + if (apu->irq_callback) + apu->irq_callback(); } /* bodge for timestamp queue */ - apu.dmc.enabled = false; + apu->dmc.enabled = false; break; } } /* positive delta */ - if (apu.dmc.cur_byte & (1 << delta_bit)) + if (apu->dmc.cur_byte & (1 << delta_bit)) { - if (apu.dmc.regs[1] < 0x7D) + if (apu->dmc.regs[1] < 0x7D) { - apu.dmc.regs[1] += 2; - apu.dmc.output_vol += (2 << 8); + apu->dmc.regs[1] += 2; + apu->dmc.output_vol += (2 << 8); } } /* negative delta */ else { - if (apu.dmc.regs[1] > 1) + if (apu->dmc.regs[1] > 1) { - apu.dmc.regs[1] -= 2; - apu.dmc.output_vol -= (2 << 8); + apu->dmc.regs[1] -= 2; + apu->dmc.output_vol -= (2 << 8); } } } @@ -618,60 +618,60 @@ void apu_write(uint32 address, uint8 value) case APU_WRA0: case APU_WRB0: chan = (address & 4) >> 2; - apu.rectangle[chan].regs[0] = value; - apu.rectangle[chan].volume = value & 0x0F; - apu.rectangle[chan].env_delay = decay_lut[value & 0x0F]; - apu.rectangle[chan].holdnote = (value & 0x20) ? true : false; - apu.rectangle[chan].fixed_envelope = (value & 0x10) ? true : false; - apu.rectangle[chan].duty_flip = duty_flip[value >> 6]; + apu->rectangle[chan].regs[0] = value; + apu->rectangle[chan].volume = value & 0x0F; + apu->rectangle[chan].env_delay = decay_lut[value & 0x0F]; + apu->rectangle[chan].holdnote = (value & 0x20) ? true : false; + apu->rectangle[chan].fixed_envelope = (value & 0x10) ? true : false; + apu->rectangle[chan].duty_flip = duty_flip[value >> 6]; break; case APU_WRA1: case APU_WRB1: chan = (address & 4) >> 2; - apu.rectangle[chan].regs[1] = value; - apu.rectangle[chan].sweep_on = (value & 0x80) ? true : false; - apu.rectangle[chan].sweep_shifts = value & 7; - apu.rectangle[chan].sweep_delay = decay_lut[(value >> 4) & 7]; - apu.rectangle[chan].sweep_inc = (value & 0x08) ? true : false; - apu.rectangle[chan].freq_limit = freq_limit[value & 7]; + apu->rectangle[chan].regs[1] = value; + apu->rectangle[chan].sweep_on = (value & 0x80) ? true : false; + apu->rectangle[chan].sweep_shifts = value & 7; + apu->rectangle[chan].sweep_delay = decay_lut[(value >> 4) & 7]; + apu->rectangle[chan].sweep_inc = (value & 0x08) ? true : false; + apu->rectangle[chan].freq_limit = freq_limit[value & 7]; break; case APU_WRA2: case APU_WRB2: chan = (address & 4) >> 2; - apu.rectangle[chan].regs[2] = value; - apu.rectangle[chan].freq = (apu.rectangle[chan].freq & ~0xFF) | value; + apu->rectangle[chan].regs[2] = value; + apu->rectangle[chan].freq = (apu->rectangle[chan].freq & ~0xFF) | value; break; case APU_WRA3: case APU_WRB3: chan = (address & 4) >> 2; - apu.rectangle[chan].regs[3] = value; - apu.rectangle[chan].vbl_length = vbl_lut[value >> 3]; - apu.rectangle[chan].env_vol = 0; - apu.rectangle[chan].freq = ((value & 7) << 8) | (apu.rectangle[chan].freq & 0xFF); - apu.rectangle[chan].adder = 0; + apu->rectangle[chan].regs[3] = value; + apu->rectangle[chan].vbl_length = vbl_lut[value >> 3]; + apu->rectangle[chan].env_vol = 0; + apu->rectangle[chan].freq = ((value & 7) << 8) | (apu->rectangle[chan].freq & 0xFF); + apu->rectangle[chan].adder = 0; break; /* triangle */ case APU_WRC0: - apu.triangle.regs[0] = value; - apu.triangle.holdnote = (value & 0x80) ? true : false; + apu->triangle.regs[0] = value; + apu->triangle.holdnote = (value & 0x80) ? true : false; - if (false == apu.triangle.counter_started && apu.triangle.vbl_length) - apu.triangle.linear_length = trilength_lut[value & 0x7F]; + if (false == apu->triangle.counter_started && apu->triangle.vbl_length) + apu->triangle.linear_length = trilength_lut[value & 0x7F]; break; case APU_WRC2: - apu.triangle.regs[1] = value; - apu.triangle.freq = (((apu.triangle.regs[2] & 7) << 8) + value) + 1; + apu->triangle.regs[1] = value; + apu->triangle.freq = (((apu->triangle.regs[2] & 7) << 8) + value) + 1; break; case APU_WRC3: - apu.triangle.regs[2] = value; + apu->triangle.regs[2] = value; /* this is somewhat of a hack. there appears to be some latency on ** the Real Thing between when trireg0 is written to and when the @@ -684,60 +684,60 @@ void apu_write(uint32 address, uint8 value) ** for the 6502 code to do a couple of table dereferences and load up ** the other triregs */ - apu.triangle.write_latency = (int) (228 / apu.cycle_rate); - apu.triangle.freq = (((value & 7) << 8) + apu.triangle.regs[1]) + 1; - apu.triangle.vbl_length = vbl_lut[value >> 3]; - apu.triangle.counter_started = false; - apu.triangle.linear_length = trilength_lut[apu.triangle.regs[0] & 0x7F]; + apu->triangle.write_latency = (int) (228 / apu->cycle_rate); + apu->triangle.freq = (((value & 7) << 8) + apu->triangle.regs[1]) + 1; + apu->triangle.vbl_length = vbl_lut[value >> 3]; + apu->triangle.counter_started = false; + apu->triangle.linear_length = trilength_lut[apu->triangle.regs[0] & 0x7F]; break; /* noise */ case APU_WRD0: - apu.noise.regs[0] = value; - apu.noise.env_delay = decay_lut[value & 0x0F]; - apu.noise.holdnote = (value & 0x20) ? true : false; - apu.noise.fixed_envelope = (value & 0x10) ? true : false; - apu.noise.volume = value & 0x0F; + apu->noise.regs[0] = value; + apu->noise.env_delay = decay_lut[value & 0x0F]; + apu->noise.holdnote = (value & 0x20) ? true : false; + apu->noise.fixed_envelope = (value & 0x10) ? true : false; + apu->noise.volume = value & 0x0F; break; case APU_WRD2: - apu.noise.regs[1] = value; - apu.noise.freq = noise_freq[value & 0x0F]; + apu->noise.regs[1] = value; + apu->noise.freq = noise_freq[value & 0x0F]; #ifdef REALTIME_NOISE - apu.noise.xor_tap = (value & 0x80) ? 0x40: 0x02; + apu->noise.xor_tap = (value & 0x80) ? 0x40: 0x02; #else /* !REALTIME_NOISE */ /* detect transition from long->short sample */ - if ((value & 0x80) && false == apu.noise.short_sample) + if ((value & 0x80) && false == apu->noise.short_sample) { /* recalculate short noise buffer */ shift_register15(noise_short_lut, APU_NOISE_93); - apu.noise.cur_pos = 0; + apu->noise.cur_pos = 0; } - apu.noise.short_sample = (value & 0x80) ? true : false; + apu->noise.short_sample = (value & 0x80) ? true : false; #endif /* !REALTIME_NOISE */ break; case APU_WRD3: - apu.noise.regs[2] = value; - apu.noise.vbl_length = vbl_lut[value >> 3]; - apu.noise.env_vol = 0; /* reset envelope */ + apu->noise.regs[2] = value; + apu->noise.vbl_length = vbl_lut[value >> 3]; + apu->noise.env_vol = 0; /* reset envelope */ break; /* DMC */ case APU_WRE0: - apu.dmc.regs[0] = value; - apu.dmc.freq = dmc_clocks[value & 0x0F]; - apu.dmc.looping = (value & 0x40) ? true : false; + apu->dmc.regs[0] = value; + apu->dmc.freq = dmc_clocks[value & 0x0F]; + apu->dmc.looping = (value & 0x40) ? true : false; if (value & 0x80) { - apu.dmc.irq_gen = true; + apu->dmc.irq_gen = true; } else { - apu.dmc.irq_gen = false; - apu.dmc.irq_occurred = false; + apu->dmc.irq_gen = false; + apu->dmc.irq_occurred = false; } break; @@ -746,72 +746,72 @@ void apu_write(uint32 address, uint8 value) ** current output level of the volume reg */ value &= 0x7F; /* bit 7 ignored */ - apu.dmc.output_vol += ((value - apu.dmc.regs[1]) << 8); - apu.dmc.regs[1] = value; + apu->dmc.output_vol += ((value - apu->dmc.regs[1]) << 8); + apu->dmc.regs[1] = value; break; case APU_WRE2: - apu.dmc.regs[2] = value; - apu.dmc.cached_addr = 0xC000 + (uint16) (value << 6); + apu->dmc.regs[2] = value; + apu->dmc.cached_addr = 0xC000 + (uint16) (value << 6); break; case APU_WRE3: - apu.dmc.regs[3] = value; - apu.dmc.cached_dmalength = ((value << 4) + 1) << 3; + apu->dmc.regs[3] = value; + apu->dmc.cached_dmalength = ((value << 4) + 1) << 3; break; case APU_SMASK: /* bodge for timestamp queue */ - apu.dmc.enabled = (value & 0x10) ? true : false; - apu.enable_reg = value; + apu->dmc.enabled = (value & 0x10) ? true : false; + apu->enable_reg = value; for (chan = 0; chan < 2; chan++) { if (value & (1 << chan)) { - apu.rectangle[chan].enabled = true; + apu->rectangle[chan].enabled = true; } else { - apu.rectangle[chan].enabled = false; - apu.rectangle[chan].vbl_length = 0; + apu->rectangle[chan].enabled = false; + apu->rectangle[chan].vbl_length = 0; } } if (value & 0x04) { - apu.triangle.enabled = true; + apu->triangle.enabled = true; } else { - apu.triangle.enabled = false; - apu.triangle.vbl_length = 0; - apu.triangle.linear_length = 0; - apu.triangle.counter_started = false; - apu.triangle.write_latency = 0; + apu->triangle.enabled = false; + apu->triangle.vbl_length = 0; + apu->triangle.linear_length = 0; + apu->triangle.counter_started = false; + apu->triangle.write_latency = 0; } if (value & 0x08) { - apu.noise.enabled = true; + apu->noise.enabled = true; } else { - apu.noise.enabled = false; - apu.noise.vbl_length = 0; + apu->noise.enabled = false; + apu->noise.vbl_length = 0; } if (value & 0x10) { - if (0 == apu.dmc.dma_length) + if (0 == apu->dmc.dma_length) apu_dmcreload(); } else { - apu.dmc.dma_length = 0; + apu->dmc.dma_length = 0; } - apu.dmc.irq_occurred = false; + apu->dmc.irq_occurred = false; break; /* unused, but they get hit in some mem-clear loops */ @@ -834,24 +834,24 @@ uint8 apu_read(uint32 address) case APU_SMASK: value = 0; /* Return 1 in 0-5 bit pos if a channel is playing */ - if (apu.rectangle[0].enabled && apu.rectangle[0].vbl_length) + if (apu->rectangle[0].enabled && apu->rectangle[0].vbl_length) value |= 0x01; - if (apu.rectangle[1].enabled && apu.rectangle[1].vbl_length) + if (apu->rectangle[1].enabled && apu->rectangle[1].vbl_length) value |= 0x02; - if (apu.triangle.enabled && apu.triangle.vbl_length) + if (apu->triangle.enabled && apu->triangle.vbl_length) value |= 0x04; - if (apu.noise.enabled && apu.noise.vbl_length) + if (apu->noise.enabled && apu->noise.vbl_length) value |= 0x08; /* bodge for timestamp queue */ - if (apu.dmc.enabled) + if (apu->dmc.enabled) value |= 0x10; - if (apu.dmc.irq_occurred) + if (apu->dmc.irq_occurred) value |= 0x80; - if (apu.irqclear_callback) - value |= apu.irqclear_callback(); + if (apu->irqclear_callback) + value |= apu->irqclear_callback(); break; @@ -882,7 +882,7 @@ void apu_process(void *buffer, int num_samples) if (NULL != buffer) { /* bleh */ - apu.buffer = buffer; + apu->buffer = buffer; buf16 = (int16 *) buffer; buf8 = (uint8 *) buffer; @@ -891,25 +891,25 @@ void apu_process(void *buffer, int num_samples) { int32 next_sample, accum = 0; - if (apu.mix_enable & 0x01) + if (apu->mix_enable & 0x01) accum += apu_rectangle_0(); - if (apu.mix_enable & 0x02) + if (apu->mix_enable & 0x02) accum += apu_rectangle_1(); - if (apu.mix_enable & 0x04) + if (apu->mix_enable & 0x04) accum += apu_triangle(); - if (apu.mix_enable & 0x08) + if (apu->mix_enable & 0x08) accum += apu_noise(); - if (apu.mix_enable & 0x10) + if (apu->mix_enable & 0x10) accum += apu_dmc(); - if (apu.ext && (apu.mix_enable & 0x20)) - accum += apu.ext->process(); + if (apu->ext && (apu->mix_enable & 0x20)) + accum += apu->ext->process(); /* do any filtering */ - if (APU_FILTER_NONE != apu.filter_type) + if (APU_FILTER_NONE != apu->filter_type) { next_sample = accum; - if (APU_FILTER_LOWPASS == apu.filter_type) + if (APU_FILTER_LOWPASS == apu->filter_type) { accum += prev_sample; accum >>= 1; @@ -924,7 +924,7 @@ void apu_process(void *buffer, int num_samples) CLIP_OUTPUT16(accum); /* signed 16-bit output, unsigned 8-bit */ - if (16 == apu.sample_bits) + if (16 == apu->sample_bits) *buf16++ = (int16) accum; else *buf8++ = (accum >> 8) ^ 0x80; @@ -935,7 +935,7 @@ void apu_process(void *buffer, int num_samples) /* set the filter type */ void apu_setfilter(int filter_type) { - apu.filter_type = filter_type; + apu->filter_type = filter_type; } void apu_reset(void) @@ -948,8 +948,8 @@ void apu_reset(void) apu_write(0x4015, 0); - if (apu.ext && NULL != apu.ext->reset) - apu.ext->reset(); + if (apu->ext && NULL != apu->ext->reset) + apu->ext->reset(); } void apu_build_luts(int num_samples) @@ -977,18 +977,18 @@ void apu_build_luts(int num_samples) void apu_setparams(double base_freq, int sample_rate, int refresh_rate, int sample_bits) { - apu.sample_rate = sample_rate; - apu.refresh_rate = refresh_rate; - apu.sample_bits = sample_bits; - apu.num_samples = sample_rate / refresh_rate; + apu->sample_rate = sample_rate; + apu->refresh_rate = refresh_rate; + apu->sample_bits = sample_bits; + apu->num_samples = sample_rate / refresh_rate; if (0 == base_freq) - apu.base_freq = APU_BASEFREQ; + apu->base_freq = APU_BASEFREQ; else - apu.base_freq = base_freq; - apu.cycle_rate = (float) (apu.base_freq / sample_rate); + apu->base_freq = base_freq; + apu->cycle_rate = (float) (apu->base_freq / sample_rate); /* build various lookup tables for apu */ - apu_build_luts(apu.num_samples); + apu_build_luts(apu->num_samples); apu_reset(); } @@ -1031,10 +1031,10 @@ void apu_destroy(apu_t **src_apu) { if (*src_apu) { - if ((*src_apu)->ext && NULL != (*src_apu)->ext->shutdown) - (*src_apu)->ext->shutdown(); - free(*src_apu); - *src_apu = NULL; + /* if ((*src_apu)->ext && NULL != (*src_apu)->ext->shutdown) */ + /* (*src_apu)->ext->shutdown(); */ + /* free(*src_apu); */ + /* *src_apu = NULL; */ } } diff --git a/components/nes/src/nes.cpp b/components/nes/src/nes.cpp index eda64cb9..f52ad86d 100644 --- a/components/nes/src/nes.cpp +++ b/components/nes/src/nes.cpp @@ -1,10 +1,5 @@ #include "nes.hpp" - -extern "C" { -#include "event.h" -#include -#include -} +#include "nes_shared_memory.h" static nes_t* console_nes; @@ -21,19 +16,13 @@ static bool unlock = false; static uint8_t first_frame = 0; void init_nes(const std::string& rom_filename, uint8_t *romdata, size_t rom_data_size) { - static bool initialized = false; - if (!initialized) { - event_init(); - osd_init(); - vidinfo_t video; - osd_getvideoinfo(&video); - vid_init(video.default_width, video.default_height, video.driver); - console_nes = nes_create(); - event_set_system(system_nes); - } else { - nes_reset(HARD_RESET); - } - initialized = true; + event_init(); + osd_init(); + vidinfo_t video; + osd_getvideoinfo(&video); + vid_init(video.default_width, video.default_height, video.driver); + console_nes = nes_init_shared_memory(); + event_set_system(system_nes); // reset unlock unlock = false; @@ -108,4 +97,5 @@ std::vector get_nes_video_buffer() { void deinit_nes() { nes_poweroff(); BoxEmu::get().audio_sample_rate(48000); + nes_free_shared_memory(); } diff --git a/components/nes/src/nes_shared_memory.c b/components/nes/src/nes_shared_memory.c new file mode 100644 index 00000000..61c2ad02 --- /dev/null +++ b/components/nes/src/nes_shared_memory.c @@ -0,0 +1,45 @@ +#include "nes_shared_memory.h" +#include "nes_external.h" +#include "shared_memory.h" +#include "esp_log.h" + +#include + +static const char *TAG = "nes_shared_memory"; + +// Define the external nes variable in shared memory +nes_t *nes_context; + +/* allocates memory and clears it */ +void *_my_malloc(int size) +{ + // get a pointer to the memory pool + shared_mem_request_t request = { + .size = size, + .region = SHARED_MEM_DEFAULT + }; + uint8_t *ptr = shared_mem_allocate(&request); + return ptr; +} + +/* free a pointer allocated with my_malloc */ +void _my_free(void **data) +{ +} + +nes_t* nes_init_shared_memory(void) { + nes_cpu = (nes6502_context *)_my_malloc(sizeof(nes6502_context)); + + nes_context = nes_create(); + + if (!nes_context) { + ESP_LOGE("nes_init_shared_memory", "Failed to allocate NES state"); + return NULL; + } + + return nes_context; +} + +void nes_free_shared_memory(void) { + shared_mem_clear(); +} diff --git a/components/nes/src/video_audio.cpp b/components/nes/src/video_audio.cpp index c2c221b2..eec714aa 100644 --- a/components/nes/src/video_audio.cpp +++ b/components/nes/src/video_audio.cpp @@ -128,7 +128,7 @@ static int set_mode(int width, int height) return 0; } -uint16 myPalette[256]; +uint16 *myPalette = nullptr; /* copy nes palette over to hardware */ static void set_palette(rgb_t *pal) @@ -137,6 +137,8 @@ static void set_palette(rgb_t *pal) int i; + myPalette = (uint16_t*)_my_malloc(256 * sizeof(uint16)); + printf("set palette!\n"); for (i = 0; i < 256; i++) { diff --git a/components/rom_info/src/rom_info.cpp b/components/rom_info/src/rom_info.cpp index 975b2f3f..11ca57e1 100644 --- a/components/rom_info/src/rom_info.cpp +++ b/components/rom_info/src/rom_info.cpp @@ -44,25 +44,45 @@ std::vector parse_metadata(const std::string& metadata_path) { } Emulator platform = Emulator::UNKNOWN; if (endsWith(rom_path, ".nes")) { // nes +#ifdef ENABLE_NES platform = Emulator::NES; +#endif } else if (endsWith(rom_path, ".gb")) { // gameboy +#ifdef ENABLE_GBC platform = Emulator::GAMEBOY; +#endif } else if (endsWith(rom_path, ".gbc")) { // gameboy color +#ifdef ENABLE_GBC platform = Emulator::GAMEBOY_COLOR; +#endif } else if (endsWith(rom_path, ".sms")) { // sega master system +#ifdef ENABLE_SMS platform = Emulator::SEGA_MASTER_SYSTEM; +#endif } else if (endsWith(rom_path, ".gg")) { // sega game gear +#ifdef ENABLE_SMS platform = Emulator::SEGA_GAME_GEAR; +#endif } else if (endsWith(rom_path, ".gen")) { // sega genesis +#ifdef ENABLE_GENESIS platform = Emulator::SEGA_GENESIS; +#endif } else if (endsWith(rom_path, ".md")) { // sega mega drive +#ifdef ENABLE_GENESIS platform = Emulator::SEGA_MEGA_DRIVE; +#endif } else if (endsWith(rom_path, ".sfc")) { // snes +#ifdef ENABLE_SNES platform = Emulator::SNES; +#endif } else if (endsWith(rom_path, ".rom")) { // msx +#ifdef ENABLE_MSX platform = Emulator::MSX; +#endif } else if (endsWith(rom_path, ".wad")) { // doom +#ifdef ENABLE_DOOM platform = Emulator::DOOM; +#endif } if (platform != Emulator::UNKNOWN) { // for each row, create rom entry diff --git a/components/shared_memory/CMakeLists.txt b/components/shared_memory/CMakeLists.txt new file mode 100644 index 00000000..247af0b7 --- /dev/null +++ b/components/shared_memory/CMakeLists.txt @@ -0,0 +1,5 @@ +idf_component_register( + INCLUDE_DIRS "include" + SRC_DIRS "src" + REQUIRES "" +) diff --git a/components/shared_memory/include/shared_memory.h b/components/shared_memory/include/shared_memory.h new file mode 100644 index 00000000..45d02bc7 --- /dev/null +++ b/components/shared_memory/include/shared_memory.h @@ -0,0 +1,47 @@ +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// Memory regions for different alignment requirements +typedef enum { + SHARED_MEM_DEFAULT, // 4-byte aligned + SHARED_MEM_VECTOR, // 16-byte aligned for SIMD operations + SHARED_MEM_CACHE_LINE // 32-byte aligned for cache line optimization +} shared_mem_region_t; + +// Memory allocation request +typedef struct { + size_t size; + shared_mem_region_t region; +} shared_mem_request_t; + +// Memory usage statistics +typedef struct { + size_t total_allocated; + size_t total_free; +} shared_mem_stats_t; + +// Get singleton instance +void* shared_mem_get_instance(void); + +// Allocate memory with specific alignment requirements +void* shared_mem_allocate(const shared_mem_request_t* request); + +void* shared_malloc(size_t size); + +size_t shared_num_bytes_allocated(void); + +// Clear all memory (using SIMD-accelerated memset) +void shared_mem_clear(void); + +// Get current memory usage statistics +shared_mem_stats_t shared_mem_get_stats(void); + +#ifdef __cplusplus +} +#endif diff --git a/components/shared_memory/src/shared_memory.c b/components/shared_memory/src/shared_memory.c new file mode 100644 index 00000000..c8790263 --- /dev/null +++ b/components/shared_memory/src/shared_memory.c @@ -0,0 +1,77 @@ +#include "shared_memory.h" +#include +#include + +// Total shared memory size - can be tuned based on needs +#define TOTAL_MEMORY_SIZE (150 * 1024) // 256KB total shared memory + +// Aligned memory pool +static uint8_t memory_pool_[TOTAL_MEMORY_SIZE] __attribute__((aligned(32))); +static size_t current_offset_ = 0; + +// Calculate alignment offset for a region +static size_t get_alignment_offset(shared_mem_region_t region) { + switch (region) { + case SHARED_MEM_VECTOR: + return 16; + case SHARED_MEM_CACHE_LINE: + return 32; + default: + return 4; + } +} + +void* shared_mem_get_instance(void) { + return memory_pool_; // Return base address of memory pool +} + +void* shared_malloc(size_t size) { + shared_mem_request_t request = { + .size = size, + .region = SHARED_MEM_DEFAULT + }; + return shared_mem_allocate(&request); +} + +size_t shared_num_bytes_allocated(void) { + return current_offset_; +} + +void* shared_mem_allocate(const shared_mem_request_t* request) { + if (!request) { + return NULL; + } + + // Calculate alignment offset + size_t alignment = get_alignment_offset(request->region); + size_t offset = (alignment - (current_offset_ % alignment)) % alignment; + + // Check if we have enough space + if (current_offset_ + offset + request->size > TOTAL_MEMORY_SIZE) { + return NULL; + } + + // Calculate aligned address + void* ptr = memory_pool_ + current_offset_ + offset; + + // Update current offset + current_offset_ += offset + request->size; + + return ptr; +} + +void shared_mem_clear(void) { + printf("Num bytes allocated: %d\n", current_offset_); + // Use SIMD-accelerated memset from ESP32 + // heap_caps_memset(memory_pool_, 0, TOTAL_MEMORY_SIZE); + memset(memory_pool_, 0, TOTAL_MEMORY_SIZE); + current_offset_ = 0; +} + +shared_mem_stats_t shared_mem_get_stats(void) { + shared_mem_stats_t stats = { + .total_allocated = current_offset_, + .total_free = TOTAL_MEMORY_SIZE - current_offset_ + }; + return stats; +} diff --git a/components/sms/CMakeLists.txt b/components/sms/CMakeLists.txt index 996c745d..28dbe6c4 100644 --- a/components/sms/CMakeLists.txt +++ b/components/sms/CMakeLists.txt @@ -2,7 +2,7 @@ idf_component_register( INCLUDE_DIRS "include" SRC_DIRS "src" "smsplus" "smsplus/cpu" "smsplus/sound" PRIV_INCLUDE_DIRS "." "smsplus" "smsplus/cpu" "smsplus/sound" - REQUIRES box-emu statistics + REQUIRES box-emu statistics shared_memory ) # target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-char-subscripts -Wno-attributes -Wno-implicit-fallthrough -Wno-unused-function -Wno-unused-variable -Wno-discarded-qualifiers) target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-unused-const-variable) diff --git a/components/sms/include/sms.hpp b/components/sms/include/sms.hpp index 954c5dd7..6897b8a6 100644 --- a/components/sms/include/sms.hpp +++ b/components/sms/include/sms.hpp @@ -4,6 +4,8 @@ #include #include +#include "shared_memory.h" + void reset_sms(); void init_sms(uint8_t *romdata, size_t rom_data_size); void init_gg(uint8_t *romdata, size_t rom_data_size); diff --git a/components/sms/smsplus/cpu/z80.c b/components/sms/smsplus/cpu/z80.c index a3eef05b..81cb856d 100644 --- a/components/sms/smsplus/cpu/z80.c +++ b/components/sms/smsplus/cpu/z80.c @@ -169,56 +169,56 @@ int z80_cycle_count = 0; /* running total of cycles executed */ #define INT_IRQ 0x01 #define NMI_IRQ 0x02 -#define PCD Z80.pc.d -#define PC Z80.pc.w.l - -#define SPD Z80.sp.d -#define SP Z80.sp.w.l - -#define AFD Z80.af.d -#define AF Z80.af.w.l -#define A Z80.af.b.h -#define F Z80.af.b.l - -#define BCD Z80.bc.d -#define BC Z80.bc.w.l -#define B Z80.bc.b.h -#define C Z80.bc.b.l - -#define DED Z80.de.d -#define DE Z80.de.w.l -#define D Z80.de.b.h -#define E Z80.de.b.l - -#define HLD Z80.hl.d -#define HL Z80.hl.w.l -#define H Z80.hl.b.h -#define L Z80.hl.b.l - -#define IXD Z80.ix.d -#define IX Z80.ix.w.l -#define HX Z80.ix.b.h -#define LX Z80.ix.b.l - -#define IYD Z80.iy.d -#define IY Z80.iy.w.l -#define HY Z80.iy.b.h -#define LY Z80.iy.b.l - -#define WZ Z80.wz.w.l -#define WZ_H Z80.wz.b.h -#define WZ_L Z80.wz.b.l - -#define I Z80.i -#define R Z80.r -#define R2 Z80.r2 -#define IM Z80.im -#define IFF1 Z80.iff1 -#define IFF2 Z80.iff2 -#define HALT Z80.halt +#define PCD Z80->pc.d +#define PC Z80->pc.w.l + +#define SPD Z80->sp.d +#define SP Z80->sp.w.l + +#define AFD Z80->af.d +#define AF Z80->af.w.l +#define A Z80->af.b.h +#define F Z80->af.b.l + +#define BCD Z80->bc.d +#define BC Z80->bc.w.l +#define B Z80->bc.b.h +#define C Z80->bc.b.l + +#define DED Z80->de.d +#define DE Z80->de.w.l +#define D Z80->de.b.h +#define E Z80->de.b.l + +#define HLD Z80->hl.d +#define HL Z80->hl.w.l +#define H Z80->hl.b.h +#define L Z80->hl.b.l + +#define IXD Z80->ix.d +#define IX Z80->ix.w.l +#define HX Z80->ix.b.h +#define LX Z80->ix.b.l + +#define IYD Z80->iy.d +#define IY Z80->iy.w.l +#define HY Z80->iy.b.h +#define LY Z80->iy.b.l + +#define WZ Z80->wz.w.l +#define WZ_H Z80->wz.b.h +#define WZ_L Z80->wz.b.l + +#define I Z80->i +#define R Z80->r +#define R2 Z80->r2 +#define IM Z80->im +#define IFF1 Z80->iff1 +#define IFF2 Z80->iff2 +#define HALT Z80->halt int z80_ICount; -Z80_Regs Z80; +Z80_Regs *Z80 = NULL; static int z80_exec = 0; /* 1= in exec loop, 0= out of */ static int z80_requested_cycles = 0; /* requested cycles to execute this timeslice */ @@ -235,7 +235,7 @@ static UINT8 SZHV_dec[256]; /* zero, sign, half carry and overflow flags DEC r8 static UINT8 *SZHVC_add = 0; static UINT8 *SZHVC_sub = 0; #else -static DRAM_ATTR const UINT8 SZ[256] = { /* zero and sign flags */ +static const UINT8 SZ[256] = { /* zero and sign flags */ 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, @@ -253,7 +253,7 @@ static DRAM_ATTR const UINT8 SZ[256] = { /* zero and sign flags */ 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8 }; -static DRAM_ATTR const UINT8 SZ_BIT[256] = { +static const UINT8 SZ_BIT[256] = { 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, @@ -271,7 +271,7 @@ static DRAM_ATTR const UINT8 SZ_BIT[256] = { 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8 }; -static DRAM_ATTR const UINT8 SZP[256] = { +static const UINT8 SZP[256] = { 0x44, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x00, 0x08, 0x0c, 0x0c, 0x08, 0x0c, 0x08, 0x08, 0x0c, 0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x04, 0x0c, 0x08, 0x08, 0x0c, 0x08, 0x0c, 0x0c, 0x08, 0x20, 0x24, 0x24, 0x20, 0x24, 0x20, 0x20, 0x24, 0x2c, 0x28, 0x28, 0x2c, 0x28, 0x2c, 0x2c, 0x28, @@ -289,7 +289,7 @@ static DRAM_ATTR const UINT8 SZP[256] = { 0xa0, 0xa4, 0xa4, 0xa0, 0xa4, 0xa0, 0xa0, 0xa4, 0xac, 0xa8, 0xa8, 0xac, 0xa8, 0xac, 0xac, 0xa8, 0xa4, 0xa0, 0xa0, 0xa4, 0xa0, 0xa4, 0xa4, 0xa0, 0xa8, 0xac, 0xac, 0xa8, 0xac, 0xa8, 0xa8, 0xac }; -static DRAM_ATTR const UINT8 SZHV_inc[256] = { +static const UINT8 SZHV_inc[256] = { 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, @@ -307,7 +307,7 @@ static DRAM_ATTR const UINT8 SZHV_inc[256] = { 0xb0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xb0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8 }; -static DRAM_ATTR const UINT8 SZHV_dec[256] = { +static const UINT8 SZHV_dec[256] = { 0x42, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x1a, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x1a, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x3a, @@ -330,7 +330,7 @@ extern const UINT8 SZHVC_add[2 * 256 * 256]; extern const UINT8 SZHVC_sub[2*256*256]; #endif -static DRAM_ATTR const UINT8 cc_op[0x100] = { +static const UINT8 cc_op[0x100] = { 4,10, 7, 6, 4, 4, 7, 4, 4,11, 7, 6, 4, 4, 7, 4, 8,10, 7, 6, 4, 4, 7, 4,12,11, 7, 6, 4, 4, 7, 4, 7,10,16, 6, 4, 4, 7, 4, 7,11,16, 6, 4, 4, 7, 4, @@ -348,7 +348,7 @@ static DRAM_ATTR const UINT8 cc_op[0x100] = { 5,10,10,19,10,11, 7,11, 5, 4,10, 4,10, 0, 7,11, 5,10,10, 4,10,11, 7,11, 5, 6,10, 4,10, 0, 7,11}; -static DRAM_ATTR const UINT8 cc_cb[0x100] = { +static const UINT8 cc_cb[0x100] = { 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, @@ -366,7 +366,7 @@ static DRAM_ATTR const UINT8 cc_cb[0x100] = { 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8, 8, 8, 8, 8, 8, 8,15, 8}; -static DRAM_ATTR const UINT8 cc_ed[0x100] = { +static const UINT8 cc_ed[0x100] = { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, @@ -404,7 +404,7 @@ static DRAM_ATTR const UINT8 cc_ed[0x100] = { */ /* illegal combo should return 4 + cc_op[i] */ -static DRAM_ATTR const UINT8 cc_xy[0x100] ={ +static const UINT8 cc_xy[0x100] ={ 8,14,11,10, 8, 8,11, 8, 8,15,11,10, 8, 8,11, 8, 12,14,11,10, 8, 8,11, 8,16,15,11,10, 8, 8,11, 8, 11,14,20,10, 9, 9,12, 8,11,15,20,10, 9, 9,12, 8, @@ -422,7 +422,7 @@ static DRAM_ATTR const UINT8 cc_xy[0x100] ={ 9,14,14,23,14,15,11,15, 9, 8,14, 8,14, 4,11,15, 9,14,14, 8,14,15,11,15, 9,10,14, 8,14, 4,11,15}; -static DRAM_ATTR const UINT8 cc_xycb[0x100] = { +static const UINT8 cc_xycb[0x100] = { 23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, 23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, 23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23, @@ -441,7 +441,7 @@ static DRAM_ATTR const UINT8 cc_xycb[0x100] = { 23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23}; /* extra cycles if jr/jp/call taken and 'interrupt latency' on rst 0-7 */ -static DRAM_ATTR const UINT8 cc_ex[0x100] = { +static const UINT8 cc_ex[0x100] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* DJNZ */ 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, /* JR NZ/JR Z */ @@ -782,12 +782,12 @@ INLINE UINT32 ARG16(void) /*************************************************************** * POP ***************************************************************/ -#define POP(DR) do { RM16( SPD, &Z80.DR ); SP += 2; } while (0) +#define POP(DR) do { RM16( SPD, &Z80->DR ); SP += 2; } while (0) /*************************************************************** * PUSH ***************************************************************/ -#define PUSH(SR) do { SP -= 2; WM16( SPD, &Z80.SR ); } while (0) +#define PUSH(SR) do { SP -= 2; WM16( SPD, &Z80->SR ); } while (0) /*************************************************************** * JP @@ -1117,7 +1117,7 @@ INLINE UINT8 DEC(UINT8 value) ***************************************************************/ #define EX_AF { \ PAIR tmp; \ - tmp = Z80.af; Z80.af = Z80.af2; Z80.af2 = tmp; \ + tmp = Z80->af; Z80->af = Z80->af2; Z80->af2 = tmp; \ } /*************************************************************** @@ -1125,7 +1125,7 @@ INLINE UINT8 DEC(UINT8 value) ***************************************************************/ #define EX_DE_HL { \ PAIR tmp; \ - tmp = Z80.de; Z80.de = Z80.hl; Z80.hl = tmp; \ + tmp = Z80->de; Z80->de = Z80->hl; Z80->hl = tmp; \ } /*************************************************************** @@ -1133,9 +1133,9 @@ INLINE UINT8 DEC(UINT8 value) ***************************************************************/ #define EXX { \ PAIR tmp; \ - tmp = Z80.bc; Z80.bc = Z80.bc2; Z80.bc2 = tmp; \ - tmp = Z80.de; Z80.de = Z80.de2; Z80.de2 = tmp; \ - tmp = Z80.hl; Z80.hl = Z80.hl2; Z80.hl2 = tmp; \ + tmp = Z80->bc; Z80->bc = Z80->bc2; Z80->bc2 = tmp; \ + tmp = Z80->de; Z80->de = Z80->de2; Z80->de2 = tmp; \ + tmp = Z80->hl; Z80->hl = Z80->hl2; Z80->hl2 = tmp; \ } /*************************************************************** @@ -1145,9 +1145,9 @@ INLINE UINT8 DEC(UINT8 value) { \ PAIR tmp = { { 0, 0, 0, 0 } }; \ RM16( SPD, &tmp ); \ - WM16( SPD, &Z80.DR ); \ - Z80.DR = tmp; \ - WZ = Z80.DR.d; \ + WM16( SPD, &Z80->DR ); \ + Z80->DR = tmp; \ + WZ = Z80->DR.d; \ } @@ -1156,12 +1156,12 @@ INLINE UINT8 DEC(UINT8 value) ***************************************************************/ #define ADD16(DR,SR) \ { \ - UINT32 res = Z80.DR.d + Z80.SR.d; \ - WZ = Z80.DR.d + 1; \ + UINT32 res = Z80->DR.d + Z80->SR.d; \ + WZ = Z80->DR.d + 1; \ F = (F & (SF | ZF | VF)) | \ - (((Z80.DR.d ^ res ^ Z80.SR.d) >> 8) & HF) | \ + (((Z80->DR.d ^ res ^ Z80->SR.d) >> 8) & HF) | \ ((res >> 16) & CF) | ((res >> 8) & (YF | XF)); \ - Z80.DR.w.l = (UINT16)res; \ + Z80->DR.w.l = (UINT16)res; \ } /*************************************************************** @@ -1169,13 +1169,13 @@ INLINE UINT8 DEC(UINT8 value) ***************************************************************/ #define ADC16(Reg) \ { \ - UINT32 res = HLD + Z80.Reg.d + (F & CF); \ + UINT32 res = HLD + Z80->Reg.d + (F & CF); \ WZ = HL + 1; \ - F = (((HLD ^ res ^ Z80.Reg.d) >> 8) & HF) | \ + F = (((HLD ^ res ^ Z80->Reg.d) >> 8) & HF) | \ ((res >> 16) & CF) | \ ((res >> 8) & (SF | YF | XF)) | \ ((res & 0xffff) ? 0 : ZF) | \ - (((Z80.Reg.d ^ HLD ^ 0x8000) & (Z80.Reg.d ^ res) & 0x8000) >> 13); \ + (((Z80->Reg.d ^ HLD ^ 0x8000) & (Z80->Reg.d ^ res) & 0x8000) >> 13); \ HL = (UINT16)res; \ } @@ -1184,13 +1184,13 @@ INLINE UINT8 DEC(UINT8 value) ***************************************************************/ #define SBC16(Reg) \ { \ - UINT32 res = HLD - Z80.Reg.d - (F & CF); \ + UINT32 res = HLD - Z80->Reg.d - (F & CF); \ WZ = HL + 1; \ - F = (((HLD ^ res ^ Z80.Reg.d) >> 8) & HF) | NF | \ + F = (((HLD ^ res ^ Z80->Reg.d) >> 8) & HF) | NF | \ ((res >> 16) & CF) | \ ((res >> 8) & (SF | YF | XF)) | \ ((res & 0xffff) ? 0 : ZF) | \ - (((Z80.Reg.d ^ HLD) & (HLD ^ res) &0x8000) >> 13); \ + (((Z80->Reg.d ^ HLD) & (HLD ^ res) &0x8000) >> 13); \ HL = (UINT16)res; \ } @@ -1548,7 +1548,7 @@ INLINE UINT8 SET(UINT8 bit, UINT8 value) ***************************************************************/ #define EI { \ IFF1 = IFF2 = 1; \ - Z80.after_ei = TRUE; \ + Z80->after_ei = TRUE; \ } /********************************************************** @@ -2232,7 +2232,7 @@ OP(ed,3f) { illegal_2(); } /* DB ED OP(ed,40) { B = IN(BC); F = (F & CF) | SZP[B]; } /* IN B,(C) */ OP(ed,41) { OUT(BC, B); } /* OUT (C),B */ OP(ed,42) { SBC16( bc ); } /* SBC HL,BC */ -OP(ed,43) { EA = ARG16(); WM16( EA, &Z80.bc ); WZ = EA+1; } /* LD (w),BC */ +OP(ed,43) { EA = ARG16(); WM16( EA, &Z80->bc ); WZ = EA+1; } /* LD (w),BC */ OP(ed,44) { NEG; } /* NEG */ OP(ed,45) { RETN; } /* RETN; */ OP(ed,46) { IM = 0; } /* IM 0 */ @@ -2241,7 +2241,7 @@ OP(ed,47) { LD_I_A; } /* LD I,A OP(ed,48) { C = IN(BC); F = (F & CF) | SZP[C]; } /* IN C,(C) */ OP(ed,49) { OUT(BC, C); } /* OUT (C),C */ OP(ed,4a) { ADC16( bc ); } /* ADC HL,BC */ -OP(ed,4b) { EA = ARG16(); RM16( EA, &Z80.bc ); WZ = EA+1; } /* LD BC,(w) */ +OP(ed,4b) { EA = ARG16(); RM16( EA, &Z80->bc ); WZ = EA+1; } /* LD BC,(w) */ OP(ed,4c) { NEG; } /* NEG */ OP(ed,4d) { RETI; } /* RETI */ OP(ed,4e) { IM = 0; } /* IM 0 */ @@ -2250,7 +2250,7 @@ OP(ed,4f) { LD_R_A; } /* LD R,A OP(ed,50) { D = IN(BC); F = (F & CF) | SZP[D]; } /* IN D,(C) */ OP(ed,51) { OUT(BC, D); } /* OUT (C),D */ OP(ed,52) { SBC16( de ); } /* SBC HL,DE */ -OP(ed,53) { EA = ARG16(); WM16( EA, &Z80.de ); WZ = EA+1; } /* LD (w),DE */ +OP(ed,53) { EA = ARG16(); WM16( EA, &Z80->de ); WZ = EA+1; } /* LD (w),DE */ OP(ed,54) { NEG; } /* NEG */ OP(ed,55) { RETN; } /* RETN; */ OP(ed,56) { IM = 1; } /* IM 1 */ @@ -2259,7 +2259,7 @@ OP(ed,57) { LD_A_I; } /* LD A,I OP(ed,58) { E = IN(BC); F = (F & CF) | SZP[E]; } /* IN E,(C) */ OP(ed,59) { OUT(BC, E); } /* OUT (C),E */ OP(ed,5a) { ADC16( de ); } /* ADC HL,DE */ -OP(ed,5b) { EA = ARG16(); RM16( EA, &Z80.de ); WZ = EA+1; } /* LD DE,(w) */ +OP(ed,5b) { EA = ARG16(); RM16( EA, &Z80->de ); WZ = EA+1; } /* LD DE,(w) */ OP(ed,5c) { NEG; } /* NEG */ OP(ed,5d) { RETI; } /* RETI */ OP(ed,5e) { IM = 2; } /* IM 2 */ @@ -2268,7 +2268,7 @@ OP(ed,5f) { LD_A_R; } /* LD A,R OP(ed,60) { H = IN(BC); F = (F & CF) | SZP[H]; } /* IN H,(C) */ OP(ed,61) { OUT(BC, H); } /* OUT (C),H */ OP(ed,62) { SBC16( hl ); } /* SBC HL,HL */ -OP(ed,63) { EA = ARG16(); WM16( EA, &Z80.hl ); WZ = EA+1; } /* LD (w),HL */ +OP(ed,63) { EA = ARG16(); WM16( EA, &Z80->hl ); WZ = EA+1; } /* LD (w),HL */ OP(ed,64) { NEG; } /* NEG */ OP(ed,65) { RETN; } /* RETN; */ OP(ed,66) { IM = 0; } /* IM 0 */ @@ -2277,7 +2277,7 @@ OP(ed,67) { RRD; } /* RRD (HL) OP(ed,68) { L = IN(BC); F = (F & CF) | SZP[L]; } /* IN L,(C) */ OP(ed,69) { OUT(BC, L); } /* OUT (C),L */ OP(ed,6a) { ADC16( hl ); } /* ADC HL,HL */ -OP(ed,6b) { EA = ARG16(); RM16( EA, &Z80.hl ); WZ = EA+1; } /* LD HL,(w) */ +OP(ed,6b) { EA = ARG16(); RM16( EA, &Z80->hl ); WZ = EA+1; } /* LD HL,(w) */ OP(ed,6c) { NEG; } /* NEG */ OP(ed,6d) { RETI; } /* RETI */ OP(ed,6e) { IM = 0; } /* IM 0 */ @@ -2286,7 +2286,7 @@ OP(ed,6f) { RLD; } /* RLD (HL) OP(ed,70) { UINT8 res = IN(BC); F = (F & CF) | SZP[res]; } /* IN 0,(C) */ OP(ed,71) { OUT(BC, 0); } /* OUT (C),0 */ OP(ed,72) { SBC16( sp ); } /* SBC HL,SP */ -OP(ed,73) { EA = ARG16(); WM16( EA, &Z80.sp ); WZ = EA+1; } /* LD (w),SP */ +OP(ed,73) { EA = ARG16(); WM16( EA, &Z80->sp ); WZ = EA+1; } /* LD (w),SP */ OP(ed,74) { NEG; } /* NEG */ OP(ed,75) { RETN; } /* RETN; */ OP(ed,76) { IM = 1; } /* IM 1 */ @@ -2295,7 +2295,7 @@ OP(ed,77) { illegal_2(); } /* DB ED,77 OP(ed,78) { A = IN(BC); F = (F & CF) | SZP[A]; WZ = BC+1; } /* IN E,(C) */ OP(ed,79) { OUT(BC, A); WZ = BC + 1; } /* OUT (C),A */ OP(ed,7a) { ADC16( sp ); } /* ADC HL,SP */ -OP(ed,7b) { EA = ARG16(); RM16( EA, &Z80.sp ); WZ = EA+1; } /* LD SP,(w) */ +OP(ed,7b) { EA = ARG16(); RM16( EA, &Z80->sp ); WZ = EA+1; } /* LD SP,(w) */ OP(ed,7c) { NEG; } /* NEG */ OP(ed,7d) { RETI; } /* RETI */ OP(ed,7e) { IM = 2; } /* IM 2 */ @@ -2487,7 +2487,7 @@ OP(op,1f) { RRA; OP(op,20) { JR_COND( !(F & ZF), 0x20 ); } /* JR NZ,o */ OP(op,21) { HL = ARG16(); } /* LD HL,w */ -OP(op,22) { EA = ARG16(); WM16( EA, &Z80.hl ); WZ = EA+1; } /* LD (w),HL */ +OP(op,22) { EA = ARG16(); WM16( EA, &Z80->hl ); WZ = EA+1; } /* LD (w),HL */ OP(op,23) { HL++; } /* INC HL */ OP(op,24) { H = INC(H); } /* INC H */ OP(op,25) { H = DEC(H); } /* DEC H */ @@ -2496,7 +2496,7 @@ OP(op,27) { DAA; OP(op,28) { JR_COND( F & ZF, 0x28 ); } /* JR Z,o */ OP(op,29) { ADD16(hl, hl); } /* ADD HL,HL */ -OP(op,2a) { EA = ARG16(); RM16( EA, &Z80.hl ); WZ = EA+1; } /* LD HL,(w) */ +OP(op,2a) { EA = ARG16(); RM16( EA, &Z80->hl ); WZ = EA+1; } /* LD HL,(w) */ OP(op,2b) { HL--; } /* DEC HL */ OP(op,2c) { L = INC(L); } /* INC L */ OP(op,2d) { L = DEC(L); } /* DEC L */ @@ -2776,7 +2776,7 @@ OP(dd,1f) { illegal_1(); op_1f(); } /* DB DD OP(dd,20) { illegal_1(); op_20(); } /* DB DD */ OP(dd,21) { IX = ARG16(); } /* LD IX,w */ -OP(dd,22) { EA = ARG16(); WM16( EA, &Z80.ix ); WZ = EA+1; } /* LD (w),IX */ +OP(dd,22) { EA = ARG16(); WM16( EA, &Z80->ix ); WZ = EA+1; } /* LD (w),IX */ OP(dd,23) { IX++; } /* INC IX */ OP(dd,24) { HX = INC(HX); } /* INC HX */ OP(dd,25) { HX = DEC(HX); } /* DEC HX */ @@ -2785,7 +2785,7 @@ OP(dd,27) { illegal_1(); op_27(); } /* DB DD OP(dd,28) { illegal_1(); op_28(); } /* DB DD */ OP(dd,29) { ADD16(ix,ix); } /* ADD IX,IX */ -OP(dd,2a) { EA = ARG16(); RM16( EA, &Z80.ix ); WZ = EA+1; } /* LD IX,(w) */ +OP(dd,2a) { EA = ARG16(); RM16( EA, &Z80->ix ); WZ = EA+1; } /* LD IX,(w) */ OP(dd,2b) { IX--; } /* DEC IX */ OP(dd,2c) { LX = INC(LX); } /* INC LX */ OP(dd,2d) { LX = DEC(LX); } /* DEC LX */ @@ -3067,7 +3067,7 @@ OP(fd,1f) { illegal_1(); op_1f(); } /* DB FD OP(fd,20) { illegal_1(); op_20(); } /* DB FD */ OP(fd,21) { IY = ARG16(); } /* LD IY,w */ -OP(fd,22) { EA = ARG16(); WM16( EA, &Z80.iy ); WZ = EA+1; } /* LD (w),IY */ +OP(fd,22) { EA = ARG16(); WM16( EA, &Z80->iy ); WZ = EA+1; } /* LD (w),IY */ OP(fd,23) { IY++; } /* INC IY */ OP(fd,24) { HY = INC(HY); } /* INC HY */ OP(fd,25) { HY = DEC(HY); } /* DEC HY */ @@ -3076,7 +3076,7 @@ OP(fd,27) { illegal_1(); op_27(); } /* DB FD OP(fd,28) { illegal_1(); op_28(); } /* DB FD */ OP(fd,29) { ADD16(iy,iy); } /* ADD IY,IY */ -OP(fd,2a) { EA = ARG16(); RM16( EA, &Z80.iy ); WZ = EA+1; } /* LD IY,(w) */ +OP(fd,2a) { EA = ARG16(); RM16( EA, &Z80->iy ); WZ = EA+1; } /* LD IY,(w) */ OP(fd,2b) { IY--; } /* DEC IY */ OP(fd,2c) { LY = INC(LY); } /* INC LY */ OP(fd,2d) { LY = DEC(LY); } /* DEC LY */ @@ -3329,16 +3329,16 @@ static void take_interrupt(void) IFF1 = IFF2 = 0; /* call back the cpu interface to retrieve the vector */ - irq_vector = (*Z80.irq_callback)(0); + irq_vector = (*Z80->irq_callback)(0); LOG(("Z80 #%d single int. irq_vector $%02x\n", cpu_getactivecpu(), irq_vector)); - /* Interrupt mode 2. Call [Z80.i:databyte] */ + /* Interrupt mode 2. Call [Z80->i:databyte] */ if( IM == 2 ) { irq_vector = (irq_vector & 0xff) | (I << 8); PUSH( pc ); - RM16( irq_vector, &Z80.pc ); + RM16( irq_vector, &Z80->pc ); LOG(("Z80 #%d IM2 [$%04x] = $%04x\n",cpu_getactivecpu() , irq_vector, PCD)); /* CALL $xxxx + 'interrupt latency' cycles */ z80_ICount -= cc[Z80_TABLE_op][0xcd] + cc[Z80_TABLE_ex][0xff]; @@ -3475,12 +3475,12 @@ void z80_init(int index, int clock, const void *config, int (*irqcallback)(int)) #endif /* Reset registers to their initial values */ - memset(&Z80, 0, sizeof(Z80)); + memset(Z80, 0, sizeof(Z80)); IX = IY = 0xffff; /* IX and IY are FFFF after a reset! */ F = ZF; /* Zero flag is set */ SP = 0xdff0; /* fix Shadow Dancer & Ace of Aces (normally set by BIOS) */ - Z80.daisy = config; - Z80.irq_callback = irqcallback; + Z80->daisy = config; + Z80->irq_callback = irqcallback; /* setup cycle tables */ cc[Z80_TABLE_op] = cc_op; @@ -3504,7 +3504,7 @@ void z80_reset(void) IFF1 = IFF2 = 0; HALT = 0; - Z80.after_ei = FALSE; + Z80->after_ei = FALSE; WZ=PCD; } @@ -3531,7 +3531,7 @@ int z80_execute(int cycles) /* check for NMIs on the way in; they can only be set externally */ /* via timers, and can't be dynamically enabled, so it is safe */ /* to just check here */ - if (Z80.nmi_pending) + if (Z80->nmi_pending) { LOG(("Z80 #%d take NMI\n", cpu_getactivecpu())); LEAVE_HALT; /* Check if processor was halted */ @@ -3541,15 +3541,15 @@ int z80_execute(int cycles) PCD = 0x0066; WZ=PCD; z80_ICount -= 11; - Z80.nmi_pending = FALSE; + Z80->nmi_pending = FALSE; } while( z80_ICount > 0 ) { /* check for IRQs before each instruction */ - if (Z80.irq_state != CLEAR_LINE && IFF1 && !Z80.after_ei) + if (Z80->irq_state != CLEAR_LINE && IFF1 && !Z80->after_ei) take_interrupt(); - Z80.after_ei = FALSE; + Z80->after_ei = FALSE; if (z80_ICount > 0) { @@ -3584,7 +3584,7 @@ void z80_burn(int cycles) void z80_get_context (void *dst) { if( dst ) - *(Z80_Regs*)dst = Z80; + *(Z80_Regs*)dst = *Z80; } /**************************************************************************** @@ -3593,7 +3593,7 @@ void z80_get_context (void *dst) void z80_set_context (void *src) { if( src ) - Z80 = *(Z80_Regs*)src; + *Z80 = *(Z80_Regs*)src; } /**************************************************************************** @@ -3604,14 +3604,14 @@ void z80_set_irq_line(int irqline, int state) if (irqline == INPUT_LINE_NMI) { /* mark an NMI pending on the rising edge */ - if (Z80.nmi_state == CLEAR_LINE && state != CLEAR_LINE) - Z80.nmi_pending = TRUE; - Z80.nmi_state = state; + if (Z80->nmi_state == CLEAR_LINE && state != CLEAR_LINE) + Z80->nmi_pending = TRUE; + Z80->nmi_state = state; } else { /* update the IRQ state via the daisy chain */ - Z80.irq_state = state; + Z80->irq_state = state; /* the main execute loop will take the interrupt */ } diff --git a/components/sms/smsplus/cpu/z80.h b/components/sms/smsplus/cpu/z80.h index 1aea267e..365aa4a6 100644 --- a/components/sms/smsplus/cpu/z80.h +++ b/components/sms/smsplus/cpu/z80.h @@ -51,7 +51,7 @@ typedef struct extern int z80_cycle_count; -extern Z80_Regs Z80; +extern Z80_Regs *Z80; void z80_init(int index, int clock, const void *config, int (*irqcallback)(int)); void z80_reset (void); diff --git a/components/sms/smsplus/hvc.c b/components/sms/smsplus/hvc.c index bd914444..712bc080 100644 --- a/components/sms/smsplus/hvc.c +++ b/components/sms/smsplus/hvc.c @@ -24,7 +24,7 @@ #include "shared.h" /* fixed hc table (thanks to FluBBa) */ -uint8 hc_256[228] = +const uint8 hc_256[228] = { 0xF4,0xF5,0xF6,0xF6,0xF7,0xF8,0xF9,0xF9,0xFA,0xFB,0xFC,0xFC,0xFD,0xFE,0xFF,0xFF, 0x00,0x01,0x02,0x02,0x03,0x04,0x05,0x05,0x06,0x07,0x08,0x08,0x09,0x0A,0x0B,0x0B, @@ -44,7 +44,7 @@ uint8 hc_256[228] = 0xF1,0xF2,0xF3,0xF3 }; -uint8 vc_ntsc_192[] = +const uint8 vc_ntsc_192[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, @@ -65,7 +65,7 @@ uint8 vc_ntsc_192[] = 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, }; -uint8 vc_ntsc_224[] = +const uint8 vc_ntsc_224[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, @@ -86,7 +86,7 @@ uint8 vc_ntsc_224[] = 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, }; -uint8 vc_ntsc_240[] = +const uint8 vc_ntsc_240[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, @@ -107,7 +107,7 @@ uint8 vc_ntsc_240[] = 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 }; -uint8 vc_pal_192[] = +const uint8 vc_pal_192[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, @@ -132,7 +132,7 @@ uint8 vc_pal_192[] = 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, }; -uint8 vc_pal_224[] = +const uint8 vc_pal_224[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, @@ -157,7 +157,7 @@ uint8 vc_pal_224[] = 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, }; -uint8 vc_pal_240[] = +const uint8 vc_pal_240[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, diff --git a/components/sms/smsplus/hvc.h b/components/sms/smsplus/hvc.h index 8ae9fe1c..3c643e63 100644 --- a/components/sms/smsplus/hvc.h +++ b/components/sms/smsplus/hvc.h @@ -26,19 +26,19 @@ #define _HVC_H_ /* fixed hc table (thanks to FluBBa) */ -extern uint8 hc_256[228]; +extern const uint8 hc_256[228]; -extern uint8 vc_ntsc_192[]; +extern const uint8 vc_ntsc_192[]; -extern uint8 vc_ntsc_224[]; +extern const uint8 vc_ntsc_224[]; -extern uint8 vc_ntsc_240[]; +extern const uint8 vc_ntsc_240[]; -extern uint8 vc_pal_192[]; +extern const uint8 vc_pal_192[]; -extern uint8 vc_pal_224[] ; +extern const uint8 vc_pal_224[] ; -extern uint8 vc_pal_240[]; +extern const uint8 vc_pal_240[]; extern const uint8 * vc_table[2][3]; diff --git a/components/sms/smsplus/loadrom.c b/components/sms/smsplus/loadrom.c index ffdba0f7..d812727e 100644 --- a/components/sms/smsplus/loadrom.c +++ b/components/sms/smsplus/loadrom.c @@ -254,13 +254,13 @@ void set_config() /* default sms settings */ cart.mapper = MAPPER_SEGA; - sms.console = CONSOLE_SMS2; - sms.territory = TERRITORY_EXPORT; - sms.display = DISPLAY_NTSC; - sms.glasses_3d = 0; - sms.device[0] = DEVICE_PAD2B; - sms.device[1] = DEVICE_PAD2B; - sms.use_fm = option.fm; + sms->console = CONSOLE_SMS2; + sms->territory = TERRITORY_EXPORT; + sms->display = DISPLAY_NTSC; + sms->glasses_3d = 0; + sms->device[0] = DEVICE_PAD2B; + sms->device[1] = DEVICE_PAD2B; + sms->use_fm = option.fm; /* console type detection */ /* SMS Header is located at 0x7ff0 */ @@ -272,32 +272,32 @@ void set_config() { case 5: printf("GG domestic detected.\n"); - sms.console = CONSOLE_GG; - sms.territory = TERRITORY_DOMESTIC; + sms->console = CONSOLE_GG; + sms->territory = TERRITORY_DOMESTIC; break; case 6: case 7: printf("GG Export detected.\n"); - sms.console = CONSOLE_GG; - sms.territory = TERRITORY_EXPORT; + sms->console = CONSOLE_GG; + sms->territory = TERRITORY_EXPORT; break; case 3: printf("SMS domestic detected.\n"); - sms.console = CONSOLE_SMS; - sms.territory = TERRITORY_DOMESTIC; + sms->console = CONSOLE_SMS; + sms->territory = TERRITORY_DOMESTIC; break; default: printf("SMS2 export detected.\n"); - sms.console = CONSOLE_SMS2; - sms.territory = TERRITORY_EXPORT; + sms->console = CONSOLE_SMS2; + sms->territory = TERRITORY_EXPORT; break; } } - sms.gun_offset = 20; /* default offset */ + sms->gun_offset = 20; /* default offset */ /* retrieve game settings from database */ for (i = 0; i < GAME_DATABASE_CNT; i++) @@ -305,62 +305,62 @@ void set_config() if (cart.crc == game_list[i].crc) { cart.mapper = game_list[i].mapper; - sms.display = game_list[i].display; - sms.territory = game_list[i].territory; - sms.glasses_3d = game_list[i].glasses_3d; - sms.console = game_list[i].console; - sms.device[0] = game_list[i].device; - if (game_list[i].device != DEVICE_LIGHTGUN) sms.device[1] = game_list[i].device; + sms->display = game_list[i].display; + sms->territory = game_list[i].territory; + sms->glasses_3d = game_list[i].glasses_3d; + sms->console = game_list[i].console; + sms->device[0] = game_list[i].device; + if (game_list[i].device != DEVICE_LIGHTGUN) sms->device[1] = game_list[i].device; if ((strcmp(game_list[i].name, "Spacegun") == 0) || (strcmp(game_list[i].name, "Gangster Town") == 0)) { /* these games seem to use different gun position calculation method */ - sms.gun_offset = 16; + sms->gun_offset = 16; } i = GAME_DATABASE_CNT; } } /* enable BIOS on SMS only */ - bios.enabled &= 2; - if (IS_SMS) bios.enabled |= option.use_bios; + bios->enabled &= 2; + if (IS_SMS) bios->enabled |= option.use_bios; #if 1 /* force settings if AUTO is not set*/ if (option.console == 1) - sms.console = CONSOLE_SMS; + sms->console = CONSOLE_SMS; else if (option.console == 2) - sms.console = CONSOLE_SMS2; + sms->console = CONSOLE_SMS2; else if (option.console == 3) - sms.console = CONSOLE_GG; + sms->console = CONSOLE_GG; else if (option.console == 4) - sms.console = CONSOLE_GGMS; + sms->console = CONSOLE_GGMS; else if (option.console == 5) { - sms.console = CONSOLE_SG1000; + sms->console = CONSOLE_SG1000; cart.mapper = MAPPER_NONE; } else if (option.console == 6) { - sms.console = CONSOLE_COLECO; + sms->console = CONSOLE_COLECO; cart.mapper = MAPPER_NONE; } if (option.country == 1) /* USA */ { - sms.display = DISPLAY_NTSC; - sms.territory = TERRITORY_EXPORT; + sms->display = DISPLAY_NTSC; + sms->territory = TERRITORY_EXPORT; } else if (option.country == 2) /* EUROPE */ { - sms.display = DISPLAY_PAL; - sms.territory = TERRITORY_EXPORT; + sms->display = DISPLAY_PAL; + sms->territory = TERRITORY_EXPORT; } else if (option.country == 3) /* JAPAN */ { - sms.display = DISPLAY_NTSC; - sms.territory = TERRITORY_DOMESTIC; + sms->display = DISPLAY_NTSC; + sms->territory = TERRITORY_DOMESTIC; } #endif } @@ -381,12 +381,12 @@ int load_rom (char *filename) if (strcmp(filename + (nameLength - 4), ".col") == 0) { - fd = fopen("/sd/roms/col/BIOS.col", "rb"); + fd = fopen("/sd/roms/col/BIOS->col", "rb"); if(!fd) abort(); - coleco.rom = ESP32_PSRAM + 0x100000; + coleco->rom = ESP32_PSRAM + 0x100000; - fread(coleco.rom, 0x2000, 1, fd); + fread(coleco->rom, 0x2000, 1, fd); __asm__("nop"); __asm__("nop"); diff --git a/components/sms/smsplus/memz80.c b/components/sms/smsplus/memz80.c index 1eaaea56..ca2a06ea 100644 --- a/components/sms/smsplus/memz80.c +++ b/components/sms/smsplus/memz80.c @@ -32,7 +32,7 @@ uint8 data_bus_pulldown = 0x00; /* Read unmapped memory */ uint8 z80_read_unmapped(void) { - int pc = Z80.pc.w.l; + int pc = Z80->pc.w.l; uint8 data; pc = (pc - 1) & 0xFFFF; data = cpu_readmap[pc >> 13][pc & 0x03FF]; @@ -46,18 +46,18 @@ void memctrl_w(uint8 data) if (IS_SMS) { /* autodetect loaded BIOS ROM */ - if (!(bios.enabled & 2) && ((data & 0xE8) == 0xE8)) + if (!(bios->enabled & 2) && ((data & 0xE8) == 0xE8)) { - bios.enabled = 0; //option.use_bios | 2; - memcpy(bios.rom, cart.rom, cart.size); - memcpy(bios.fcr, cart.fcr, 4); - bios.pages = cart.pages; + bios->enabled = 0; //option.use_bios | 2; + memcpy(bios->rom, cart.rom, cart.size); + memcpy(bios->fcr, cart.fcr, 4); + bios->pages = cart.pages; cart.loaded = 0; } /* disables CART & BIOS by default */ - slot.rom = NULL; - slot.mapper = MAPPER_NONE; + slot->rom = NULL; + slot->mapper = MAPPER_NONE; switch (data & 0x48) { @@ -65,18 +65,18 @@ void memctrl_w(uint8 data) case 0x08: /* BIOS disabled, CART enabled */ if (cart.loaded) { - slot.rom = cart.rom; - slot.pages = cart.pages; - slot.mapper = cart.mapper; - slot.fcr = &cart.fcr[0]; + slot->rom = cart.rom; + slot->pages = cart.pages; + slot->mapper = cart.mapper; + slot->fcr = &cart.fcr[0]; } break; case 0x40: /* BIOS enabled, CART disabled */ - slot.rom = bios.rom; - slot.pages = bios.pages; - slot.mapper = MAPPER_SEGA; - slot.fcr = &bios.fcr[0]; + slot->rom = bios->rom; + slot->pages = bios->pages; + slot->mapper = MAPPER_SEGA; + slot->fcr = &bios->fcr[0]; break; default: @@ -86,22 +86,22 @@ void memctrl_w(uint8 data) mapper_reset(); /* reset SLOT mapping */ - if (slot.rom) + if (slot->rom) { - cpu_readmap[0] = &slot.rom[0]; - if (slot.mapper != MAPPER_KOREA_MSX) + cpu_readmap[0] = &slot->rom[0]; + if (slot->mapper != MAPPER_KOREA_MSX) { - mapper_16k_w(0,slot.fcr[0]); - mapper_16k_w(1,slot.fcr[1]); - mapper_16k_w(2,slot.fcr[2]); - mapper_16k_w(3,slot.fcr[3]); + mapper_16k_w(0,slot->fcr[0]); + mapper_16k_w(1,slot->fcr[1]); + mapper_16k_w(2,slot->fcr[2]); + mapper_16k_w(3,slot->fcr[3]); } else { - mapper_8k_w(0,slot.fcr[0]); - mapper_8k_w(1,slot.fcr[1]); - mapper_8k_w(2,slot.fcr[2]); - mapper_8k_w(3,slot.fcr[3]); + mapper_8k_w(0,slot->fcr[0]); + mapper_8k_w(1,slot->fcr[1]); + mapper_8k_w(2,slot->fcr[2]); + mapper_8k_w(3,slot->fcr[3]); } } else @@ -116,7 +116,7 @@ void memctrl_w(uint8 data) } /* update register value */ - sms.memctrl = data; + sms->memctrl = data; } /*--------------------------------------------------------------------------*/ @@ -441,7 +441,7 @@ void coleco_port_w(uint16 port, uint8 data) switch(port & 0xE0) { case 0x80: - coleco.pio_mode = 0; + coleco->pio_mode = 0; return; case 0xa0: @@ -449,7 +449,7 @@ void coleco_port_w(uint16 port, uint8 data) return; case 0xc0: - coleco.pio_mode = 1; + coleco->pio_mode = 1; return; case 0xe0: diff --git a/components/sms/smsplus/pio.c b/components/sms/smsplus/pio.c index 2c80d09b..b0453479 100644 --- a/components/sms/smsplus/pio.c +++ b/components/sms/smsplus/pio.c @@ -26,14 +26,7 @@ #include "shared.h" #include -typedef struct { - uint8 tr_level[2]; /* TR pin output level */ - uint8 th_level[2]; /* TH pin output level */ - uint8 tr_dir[2]; /* TR pin direction */ - uint8 th_dir[2]; /* TH pin direction */ -} io_state; - -static io_state io_lut[2][256]; +io_state (*io_lut)[256]; // [2][256]; static io_state *io_current; @@ -100,16 +93,16 @@ void pio_init(void) void pio_reset(void) { /* GG SIO power-on defaults */ - sms.sio.pdr = 0x7F; - sms.sio.ddr = 0xFF; - sms.sio.txdata = 0x00; - sms.sio.rxdata = 0xFF; - sms.sio.sctrl = 0x00; + sms->sio.pdr = 0x7F; + sms->sio.ddr = 0xFF; + sms->sio.txdata = 0x00; + sms->sio.rxdata = 0xFF; + sms->sio.sctrl = 0x00; input.analog[0][0] = 128; input.analog[0][1] = 96; /* SMS I/O power-on defaults */ - io_current = &io_lut[sms.territory][0xFF]; + io_current = &io_lut[sms->territory][0xFF]; pio_ctrl_w(0xFF); } @@ -129,17 +122,17 @@ void pio_ctrl_w(uint8 data) th_level[1] = io_current->th_level[1]; /* HCounter is latched on TH Low->High transition */ - io_current = &io_lut[sms.territory][data]; + io_current = &io_lut[sms->territory][data]; if ((io_current->th_dir[0] == PIN_DIR_IN) && (io_current->th_level[0] == PIN_LVL_HI) && (th_level[0] == PIN_LVL_LO) ) { - sms.hlatch = hc_256[z80_get_elapsed_cycles() % CYCLES_PER_LINE]; + sms->hlatch = hc_256[z80_get_elapsed_cycles() % CYCLES_PER_LINE]; } /* update port value */ - sms.ioctrl = data; + sms->ioctrl = data; } /* @@ -164,7 +157,7 @@ static uint8 device_r(int port) { uint8 temp = 0x7F; - switch(sms.device[port]) + switch(sms->device[port]) { case DEVICE_NONE: break; @@ -184,7 +177,7 @@ static uint8 device_r(int port) http://www.smspower.org/forums/viewtopic.php?t=6783 */ case DEVICE_PADDLE: - if (sms.territory == TERRITORY_EXPORT) + if (sms->territory == TERRITORY_EXPORT) { /* non-japanese mode: TH output control */ paddle_toggle[port] = (io_current->th_level[0] == PIN_LVL_LO); @@ -232,7 +225,7 @@ static uint8 device_r(int port) { int hc = hc_256[z80_get_elapsed_cycles() % CYCLES_PER_LINE]; int dx = input.analog[port][0] - (hc*2); - int dy = input.analog[port][1] - vdp.line; + int dy = input.analog[port][1] - vdp->line; /* is current pixel is within lightgun spot ? */ if ((abs(dy) <= 5) && (abs(dx) <= 60)) @@ -244,7 +237,7 @@ static uint8 device_r(int port) if (!lightgun_latch) { /* latch estimated HC value */ - sms.hlatch = sms.gun_offset + (input.analog[port][0])/2; + sms->hlatch = sms->gun_offset + (input.analog[port][0])/2; lightgun_latch = 1; } } @@ -272,7 +265,7 @@ uint8 pio_port_r(int offset) If I/O chip is disabled, reads return last byte of instruction that read the I/O port. */ - if(sms.memctrl & 0x04) return z80_read_unmapped(); + if(sms->memctrl & 0x04) return z80_read_unmapped(); switch (offset & 1) { @@ -386,33 +379,33 @@ uint8 sio_r(int offset) case 0: /* Input port #2 */ temp = 0xE0; if(input.system & INPUT_START) temp &= ~0x80; - if(sms.territory == TERRITORY_DOMESTIC) temp &= ~0x40; - if(sms.display == DISPLAY_NTSC) temp &= ~0x20; + if(sms->territory == TERRITORY_DOMESTIC) temp &= ~0x40; + if(sms->display == DISPLAY_NTSC) temp &= ~0x20; return temp; case 1: /* Parallel data register */ temp = 0x00; - temp |= (sms.sio.ddr & 0x01) ? 0x01 : (sms.sio.pdr & 0x01); - temp |= (sms.sio.ddr & 0x02) ? 0x02 : (sms.sio.pdr & 0x02); - temp |= (sms.sio.ddr & 0x04) ? 0x04 : (sms.sio.pdr & 0x04); - temp |= (sms.sio.ddr & 0x08) ? 0x08 : (sms.sio.pdr & 0x08); - temp |= (sms.sio.ddr & 0x10) ? 0x10 : (sms.sio.pdr & 0x10); - temp |= (sms.sio.ddr & 0x20) ? 0x20 : (sms.sio.pdr & 0x20); - temp |= (sms.sio.ddr & 0x40) ? 0x40 : (sms.sio.pdr & 0x40); - temp |= (sms.sio.pdr & 0x80); + temp |= (sms->sio.ddr & 0x01) ? 0x01 : (sms->sio.pdr & 0x01); + temp |= (sms->sio.ddr & 0x02) ? 0x02 : (sms->sio.pdr & 0x02); + temp |= (sms->sio.ddr & 0x04) ? 0x04 : (sms->sio.pdr & 0x04); + temp |= (sms->sio.ddr & 0x08) ? 0x08 : (sms->sio.pdr & 0x08); + temp |= (sms->sio.ddr & 0x10) ? 0x10 : (sms->sio.pdr & 0x10); + temp |= (sms->sio.ddr & 0x20) ? 0x20 : (sms->sio.pdr & 0x20); + temp |= (sms->sio.ddr & 0x40) ? 0x40 : (sms->sio.pdr & 0x40); + temp |= (sms->sio.pdr & 0x80); return temp; case 2: /* Data direction register and NMI enable */ - return sms.sio.ddr; + return sms->sio.ddr; case 3: /* Transmit data buffer */ - return sms.sio.txdata; + return sms->sio.txdata; case 4: /* Receive data buffer */ - return sms.sio.rxdata; + return sms->sio.rxdata; case 5: /* Serial control */ - return sms.sio.sctrl; + return sms->sio.sctrl; case 6: /* Stereo sound control */ return 0xFF; @@ -430,22 +423,22 @@ void sio_w(int offset, int data) return; case 1: /* Parallel data register */ - sms.sio.pdr = data; + sms->sio.pdr = data; return; case 2: /* Data direction register and NMI enable */ - sms.sio.ddr = data; + sms->sio.ddr = data; return; case 3: /* Transmit data buffer */ - sms.sio.txdata = data; + sms->sio.txdata = data; return; case 4: /* Receive data buffer */ return; case 5: /* Serial control */ - sms.sio.sctrl = data & 0xF8; + sms->sio.sctrl = data & 0xF8; return; case 6: /* Stereo output control */ @@ -475,7 +468,7 @@ uint8 coleco_pio_r(int port) { uint8 temp = 0x7f; - if (coleco.pio_mode) + if (coleco->pio_mode) { /* Joystick */ if(input.pad[port] & INPUT_UP) temp &= ~1; @@ -489,8 +482,8 @@ uint8 coleco_pio_r(int port) else { /* KeyPad (0-9,*,#) */ - if (coleco.keypad[port] < 12) - temp = keymask[coleco.keypad[port]]; + if (coleco->keypad[port] < 12) + temp = keymask[coleco->keypad[port]]; /* Right Button */ if(input.pad[port] & INPUT_BUTTON2) temp &= ~0x40; diff --git a/components/sms/smsplus/render.c b/components/sms/smsplus/render.c index 1472e44f..27a5e8f4 100644 --- a/components/sms/smsplus/render.c +++ b/components/sms/smsplus/render.c @@ -35,13 +35,14 @@ /*** Vertical Counter Tables ***/ extern const uint8 * vc_table[2][3]; -struct -{ - uint16 yrange; - uint16 xpos; - uint16 attr; - uint16 _pad0; -} object_info[64]; +/* struct */ +/* { */ +/* uint16 yrange; */ +/* uint16 xpos; */ +/* uint16 attr; */ +/* uint16 _pad0; */ +/* } object_info[64]; */ +struct obj_info_t *object_info = NULL; /* Background drawing function */ void (*render_bg)(int line) = NULL; @@ -60,7 +61,7 @@ uint8 gg_cram_expand_table[16]; //uint16 bg_list_index; /* # of modified patterns in list */ /* Internal buffer for drawing non 8-bit displays */ -static uint8 internal_buffer[0x200]; +uint8 *internal_buffer = NULL; // [0x200]; /* Precalculated pixel table */ static uint16 pixel[PALETTE_SIZE]; @@ -74,21 +75,21 @@ extern const uint8 lut[0x10000]; static uint8 object_index_count; /* Top Border area height */ -static DRAM_ATTR const uint8 active_border[2][3] = +static const uint8 active_border[2][3] = { {24, 8, 0}, /* NTSC VDP */ {48, 32, 24} /* PAL VDP */ }; /* Active Scan Area height */ -static DRAM_ATTR const uint16 active_range[2] = +static const uint16 active_range[2] = { 243, /* NTSC VDP */ 294 /* PAL VDP */ }; /* CRAM palette in TMS compatibility mode */ -static DRAM_ATTR const uint8 tms_crom[] = +static const uint8 tms_crom[] = { 0x00, 0x00, 0x08, 0x0C, 0x10, 0x30, 0x01, 0x3C, @@ -97,7 +98,7 @@ static DRAM_ATTR const uint8 tms_crom[] = }; /* original TMS palette for SG-1000 & Colecovision */ -static DRAM_ATTR const uint8 tms_palette[16*3][3] = +static const uint8 tms_palette[16*3][3] = { /* from Sean Young (http://www.smspower.org/dev/docs/tms9918a.txt) */ { 0, 0, 0}, @@ -155,7 +156,7 @@ static DRAM_ATTR const uint8 tms_palette[16*3][3] = }; /* Attribute expansion table */ -static DRAM_ATTR const uint32 atex[4] = +static const uint32 atex[4] = { 0x00000000, 0x10101010, @@ -362,7 +363,7 @@ void render_reset(void) //memset(bg_pattern_cache, 0, 0x20000 /*sizeof(bg_pattern_cache)*/); /* Pick default render routine */ - if (vdp.reg[0] & 4) + if (vdp->reg[0] & 4) { render_bg = render_bg_sms; render_obj = render_obj_sms; @@ -389,28 +390,28 @@ void render_line(int line) prev_line = line; /* Ensure we're within the VDP active area (incl. overscan) */ - int top_border = active_border[sms.display][vdp.extended]; - int vline = (line + top_border) % vdp.lpf; - if (vline >= active_range[sms.display]) return; + int top_border = active_border[sms->display][vdp->extended]; + int vline = (line + top_border) % vdp->lpf; + if (vline >= active_range[sms->display]) return; /* adjust for Game Gear screen */ - top_border = top_border + (vdp.height - bitmap.viewport.h) / 2; + top_border = top_border + (vdp->height - bitmap.viewport.h) / 2; /* Point to current line in output buffer */ linebuf = &internal_buffer[0]; /* Sprite limit flag is set at the beginning of the line */ - if (vdp.spr_ovr) + if (vdp->spr_ovr) { - vdp.spr_ovr = 0; - vdp.status |= 0x40; + vdp->spr_ovr = 0; + vdp->status |= 0x40; } /* Vertical borders */ if ((vline < top_border) || (vline >= (bitmap.viewport.h + top_border))) { /* Sprites are still processed offscreen */ - if ((vdp.mode > 7) && (vdp.reg[1] & 0x40)) + if ((vdp->mode > 7) && (vdp->reg[1] & 0x40)) render_obj(line); /* Line is only displayed where overscan is emulated */ @@ -426,7 +427,7 @@ void render_line(int line) else { /* Display enabled ? */ - if (vdp.reg[1] & 0x40) + if (vdp->reg[1] & 0x40) { /* adjust line horizontal offset */ if (overscan) @@ -442,7 +443,7 @@ void render_line(int line) render_obj(line); /* Blank leftmost column of display */ - if((vdp.reg[0] & 0x20) && (IS_SMS || IS_MD)) + if((vdp->reg[0] & 0x20) && (IS_SMS || IS_MD)) memset(linebuf, BACKDROP_COLOR, 8); /* Horizontal borders */ @@ -461,15 +462,15 @@ void render_line(int line) } /* Parse Sprites for next line */ - if (vdp.mode > 7) + if (vdp->mode > 7) parse_satb(line); else parse_line(line); /* LightGun mark */ - if (sms.device[0] == DEVICE_LIGHTGUN) + if (sms->device[0] == DEVICE_LIGHTGUN) { - int dy = vdp.line - input.analog[0][1]; + int dy = vdp->line - input.analog[0][1]; if (abs(dy) < 6) { @@ -513,7 +514,7 @@ static void* tile_get(short attr, short line) const uint16 y = (attr & 0x400) ? (line ^ 7) : line; - const uint16* ptr = (uint16_t*)&vdp.vram[(name << 5) | (y << 2) | (0)]; + const uint16* ptr = (uint16_t*)&vdp->vram[(name << 5) | (y << 2) | (0)]; const uint16 bp01 = *ptr++; const uint16 bp23 = *ptr; const uint32 temp = (bp_lut[bp01] >> 2) | (bp_lut[bp23]); @@ -532,14 +533,14 @@ static void* tile_get(short attr, short line) void render_bg_sms(int line) { int locked = 0; - int yscroll_mask = (vdp.extended) ? 256 : 224; - int v_line = (line + vdp.vscroll) % yscroll_mask; + int yscroll_mask = (vdp->extended) ? 256 : 224; + int v_line = (line + vdp->vscroll) % yscroll_mask; int v_row = (v_line & 7) << 3; - int hscroll = ((vdp.reg[0] & 0x40) && (line < 0x10) && (sms.console != CONSOLE_GG)) ? 0 : (0x100 - vdp.reg[8]); + int hscroll = ((vdp->reg[0] & 0x40) && (line < 0x10) && (sms->console != CONSOLE_GG)) ? 0 : (0x100 - vdp->reg[8]); int column = 0; uint16 attr; - uint16 nt_addr = (vdp.ntab + ((v_line >> 3) << 6)) & (((sms.console == CONSOLE_SMS) && !(vdp.reg[2] & 1)) ? ~0x400 :0xFFFF); - uint16 *nt = (uint16 *)&vdp.vram[nt_addr]; + uint16 nt_addr = (vdp->ntab + ((v_line >> 3) << 6)) & (((sms->console == CONSOLE_SMS) && !(vdp->reg[2] & 1)) ? ~0x400 :0xFFFF); + uint16 *nt = (uint16 *)&vdp->vram[nt_addr]; int nt_scroll = (hscroll >> 3); int shift = (hscroll & 7); uint32 atex_mask; @@ -562,11 +563,11 @@ void render_bg_sms(int line) for(; column < 32; column++) { /* Stop vertical scrolling for leftmost eight columns */ - if((vdp.reg[0] & 0x80) && (!locked) && (column >= 24)) + if((vdp->reg[0] & 0x80) && (!locked) && (column >= 24)) { locked = 1; v_row = (line & 7) << 3; - nt = (uint16 *)&vdp.vram[nt_addr]; + nt = (uint16 *)&vdp->vram[nt_addr]; } /* Get name table attribute word */ @@ -593,8 +594,8 @@ void render_bg_sms(int line) // y = (y ^ 7); // } // - // uint16 bp01 = *(uint16 *)&vdp.vram[(name << 5) | (y << 2) | (0)]; - // uint16 bp23 = *(uint16 *)&vdp.vram[(name << 5) | (y << 2) | (2)]; + // uint16 bp01 = *(uint16 *)&vdp->vram[(name << 5) | (y << 2) | (0)]; + // uint16 bp23 = *(uint16 *)&vdp->vram[(name << 5) | (y << 2) | (2)]; // uint32 temp = (bp_lut[bp01] >> 2) | (bp_lut[bp23]); // // uint8 rot = (attr >> (1 + 8)) & 0x03; @@ -662,7 +663,7 @@ void render_obj_sms(int line) int width = 8; /* Adjust dimensions for double size sprites */ - if(vdp.reg[1] & 0x01) + if(vdp->reg[1] & 0x01) width *= 2; /* Draw sprites in front-to-back order */ @@ -682,13 +683,13 @@ void render_obj_sms(int line) n = object_info[i].attr; /* X position shift */ - if(vdp.reg[0] & 0x08) xp -= 8; + if(vdp->reg[0] & 0x08) xp -= 8; /* Add MSB of pattern name */ - if(vdp.reg[6] & 0x04) n |= 0x0100; + if(vdp->reg[6] & 0x04) n |= 0x0100; /* Mask LSB for 8x16 sprites */ - if(vdp.reg[1] & 0x02) n &= 0x01FE; + if(vdp->reg[1] & 0x02) n &= 0x01FE; /* Point to offset in line buffer */ linebuf_ptr = (uint8 *)&linebuf[xp]; @@ -702,7 +703,7 @@ void render_obj_sms(int line) end = (256 - xp); /* Draw double size sprite */ - if(vdp.reg[1] & 0x01) + if(vdp->reg[1] & 0x01) { #if 0 /* Retrieve tile data from cached nametable */ @@ -727,11 +728,11 @@ void render_obj_sms(int line) linebuf_ptr[x] = linebuf_ptr[x+1] = lut[(bg << 8) | (sp)]; /* Check sprite collision */ - if ((bg & 0x40) && !(vdp.status & 0x20)) + if ((bg & 0x40) && !(vdp->status & 0x20)) { /* pixel-accurate SPR_COL flag */ - vdp.status |= 0x20; - vdp.spr_col = (line << 8) | ((xp + x + 13) >> 1); + vdp->status |= 0x20; + vdp->spr_col = (line << 8) | ((xp + x + 13) >> 1); } } } @@ -761,11 +762,11 @@ void render_obj_sms(int line) linebuf_ptr[x] = lut[(bg << 8) | (sp)]; /* Check sprite collision */ - if ((bg & 0x40) && !(vdp.status & 0x20)) + if ((bg & 0x40) && !(vdp->status & 0x20)) { /* pixel-accurate SPR_COL flag */ - vdp.status |= 0x20; - vdp.spr_col = (line << 8) | ((xp + x + 13) >> 1); + vdp->status |= 0x20; + vdp->spr_col = (line << 8) | ((xp + x + 13) >> 1); } } } @@ -779,16 +780,16 @@ void palette_sync(int index) int r, g, b; /* VDP Mode */ - if ((vdp.reg[0] & 4) || IS_GG) + if ((vdp->reg[0] & 4) || IS_GG) { /* Mode 4 or Game Gear TMS mode*/ - if(sms.console == CONSOLE_GG) + if(sms->console == CONSOLE_GG) { /* GG palette */ /* ----BBBBGGGGRRRR */ - r = (vdp.cram[(index << 1) | (0)] >> 0) & 0x0F; - g = (vdp.cram[(index << 1) | (0)] >> 4) & 0x0F; - b = (vdp.cram[(index << 1) | (1)] >> 0) & 0x0F; + r = (vdp->cram[(index << 1) | (0)] >> 0) & 0x0F; + g = (vdp->cram[(index << 1) | (0)] >> 4) & 0x0F; + b = (vdp->cram[(index << 1) | (1)] >> 0) & 0x0F; r = gg_cram_expand_table[r]; g = gg_cram_expand_table[g]; @@ -798,9 +799,9 @@ void palette_sync(int index) { /* SMS palette */ /* --BBGGRR */ - r = (vdp.cram[index] >> 0) & 3; - g = (vdp.cram[index] >> 2) & 3; - b = (vdp.cram[index] >> 4) & 3; + r = (vdp->cram[index] >> 0) & 3; + g = (vdp->cram[index] >> 2) & 3; + b = (vdp->cram[index] >> 4) & 3; r = sms_cram_expand_table[r]; g = sms_cram_expand_table[g]; @@ -812,7 +813,7 @@ void palette_sync(int index) /* TMS Mode (16 colors only) */ int color = index & 0x0F; - if (sms.console < CONSOLE_SMS) + if (sms->console < CONSOLE_SMS) { /* pick one of the original TMS9918 palettes */ color += option.tms_pal * 16; @@ -842,24 +843,24 @@ void palette_sync(int index) static void parse_satb(int line) { /* Pointer to sprite attribute table */ - uint8 *st = (uint8 *)&vdp.vram[vdp.satb]; + uint8 *st = (uint8 *)&vdp->vram[vdp->satb]; /* Sprite counter (64 max.) */ int i = 0; /* Line counter value */ - int vc = vc_table[sms.display][vdp.extended][line]; + int vc = vc_table[sms->display][vdp->extended][line]; /* Sprite height (8x8 by default) */ int yp; int height = 8; /* Adjust height for 8x16 sprites */ - if(vdp.reg[1] & 0x02) + if(vdp->reg[1] & 0x02) height <<= 1; /* Adjust height for zoomed sprites */ - if(vdp.reg[1] & 0x01) + if(vdp->reg[1] & 0x01) height <<= 1; /* Sprite count for current line (8 max.) */ @@ -871,7 +872,7 @@ static void parse_satb(int line) yp = st[i]; /* Found end of sprite list marker for non-extended modes? */ - if(vdp.extended == 0 && yp == 208) + if(vdp->extended == 0 && yp == 208) return; /* Wrap Y coordinate for sprites > 240 */ @@ -887,8 +888,8 @@ static void parse_satb(int line) if (object_index_count == 8) { /* Flag is set only during active area */ - if (line < vdp.height) - vdp.spr_ovr = 1; + if (line < vdp->height) + vdp->spr_ovr = 1; /* End of sprite parsing */ if (option.spritelimit) @@ -928,8 +929,8 @@ static void update_bg_pattern_cache(void) { uint8 *dst = &bg_pattern_cache[name << 6]; - uint16 bp01 = *(uint16 *)&vdp.vram[(name << 5) | (y << 2) | (0)]; - uint16 bp23 = *(uint16 *)&vdp.vram[(name << 5) | (y << 2) | (2)]; + uint16 bp01 = *(uint16 *)&vdp->vram[(name << 5) | (y << 2) | (0)]; + uint16 bp23 = *(uint16 *)&vdp->vram[(name << 5) | (y << 2) | (2)]; uint32 temp = (bp_lut[bp01] >> 2) | (bp_lut[bp23]); for(x = 0; x < 8; x++) diff --git a/components/sms/smsplus/render.h b/components/sms/smsplus/render.h index c9eba4d7..d9c2618c 100644 --- a/components/sms/smsplus/render.h +++ b/components/sms/smsplus/render.h @@ -29,7 +29,7 @@ #define MAKE_PIXEL(r,g,b) (((r << 8) & 0xF800) | ((g << 3) & 0x07E0) | ((b >> 3) & 0x001F)) /* Used for blanking a line in whole or in part */ -#define BACKDROP_COLOR (0x10 | (vdp.reg[7] & 0x0F)) +#define BACKDROP_COLOR (0x10 | (vdp->reg[7] & 0x0F)) extern void (*render_bg)(int line); extern void (*render_obj)(int line); @@ -40,6 +40,16 @@ extern uint8 gg_cram_expand_table[16]; //extern uint16 bg_name_list[0x200]; //extern uint16 bg_list_index; +extern struct obj_info_t +{ + uint16 yrange; + uint16 xpos; + uint16 attr; + uint16 _pad0; +} *object_info; + +extern uint8 *internal_buffer; + extern void render_shutdown(void); extern void render_init(void); extern void render_reset(void); diff --git a/components/sms/smsplus/shared.h b/components/sms/smsplus/shared.h index 54a70c52..4b634162 100644 --- a/components/sms/smsplus/shared.h +++ b/components/sms/smsplus/shared.h @@ -22,6 +22,15 @@ typedef signed long int int32; #define PATH_MAX 1024 +typedef struct { + uint8 tr_level[2]; /* TR pin output level */ + uint8 th_level[2]; /* TH pin output level */ + uint8 tr_dir[2]; /* TR pin direction */ + uint8 th_dir[2]; /* TH pin direction */ +} io_state; + +extern io_state (*io_lut)[256]; + #include "z80.h" #include "sms.h" #include "pio.h" diff --git a/components/sms/smsplus/sms.c b/components/sms/smsplus/sms.c index 750407fc..2f7a5333 100644 --- a/components/sms/smsplus/sms.c +++ b/components/sms/smsplus/sms.c @@ -26,17 +26,17 @@ #include "shared.h" /* SMS context */ -sms_t sms; +sms_t *sms; /* BIOS/CART ROM */ -bios_t bios; -slot_t slot; +bios_t *bios; +slot_t *slot; /* Colecovision support */ -t_coleco coleco; +t_coleco *coleco; -uint8 dummy_write[0x400]; -uint8 dummy_read[0x400]; +uint8 *dummy_write; // [0x400]; +uint8 *dummy_read; //[0x400]; static void writemem_mapper_none(int offset, int data) { @@ -95,7 +95,7 @@ static void writemem_mapper_korea(int offset, int data) void mapper_reset(void) { - switch(slot.mapper) + switch(slot->mapper) { case MAPPER_NONE: cpu_writemem16 = writemem_mapper_none; @@ -128,9 +128,9 @@ void sms_init(void) data_bus_pulldown = 0x00; /* Initialize port handlers */ - printf("%s: sms.console= %#04x\n", __func__, sms.console); + printf("%s: sms->console= %#04x\n", __func__, sms->console); - switch(sms.console) + switch(sms->console) { case CONSOLE_COLECO: cpu_writeport16 = coleco_port_w; @@ -201,30 +201,30 @@ void sms_reset(void) /* clear SMS context */ memset(dummy_write,data_bus_pullup, sizeof(dummy_write)); memset(dummy_read,data_bus_pullup, sizeof(dummy_read)); - // memset(sms.wram,0, sizeof(sms.wram)); - memset(sms.wram,0, 0x2000); - sms.paused = 0x00; - sms.save = 0x00; - sms.fm_detect = 0x00; - sms.ioctrl = 0xFF; - sms.hlatch = 0x00; - sms.memctrl = 0xAB; + // memset(sms->wram,0, sizeof(sms->wram)); + memset(sms->wram,0, 0x2000); + sms->paused = 0x00; + sms->save = 0x00; + sms->fm_detect = 0x00; + sms->ioctrl = 0xFF; + sms->hlatch = 0x00; + sms->memctrl = 0xAB; /* enable Cartridge ROM by default*/ - slot.rom = cart.rom; - slot.pages = cart.pages; - slot.mapper = cart.mapper; - slot.fcr = &cart.fcr[0]; + slot->rom = cart.rom; + slot->pages = cart.pages; + slot->mapper = cart.mapper; + slot->fcr = &cart.fcr[0]; /* reset Memory Mapping */ - switch(sms.console) + switch(sms->console) { case CONSOLE_COLECO: { /* $0000-$1FFF mapped to internal ROM (8K) */ for(i = 0x00; i < 0x08; i++) { - cpu_readmap[i] = &coleco.rom[i << 10]; + cpu_readmap[i] = &coleco->rom[i << 10]; cpu_writemap[i] = dummy_write; } @@ -238,8 +238,8 @@ void sms_reset(void) /* $6000-$7FFF mapped to RAM (1K mirrored) */ for(i = 0x18; i < 0x20; i++) { - cpu_readmap[i] = &sms.wram[0]; - cpu_writemap[i] = &sms.wram[0]; + cpu_readmap[i] = &sms->wram[0]; + cpu_writemap[i] = &sms->wram[0]; } /* $8000-$FFFF mapped to Cartridge ROM (max. 32K) */ @@ -250,9 +250,9 @@ void sms_reset(void) } /* reset I/O */ - coleco.keypad[0] = 0xf0; - coleco.keypad[1] = 0xf0; - coleco.pio_mode = 0x00; + coleco->keypad[0] = 0xf0; + coleco->keypad[1] = 0xf0; + coleco->pio_mode = 0x00; break; } @@ -290,40 +290,40 @@ void sms_reset(void) /* SMS BIOS support */ if (IS_SMS) { - if (bios.enabled == 3) + if (bios->enabled == 3) { /* reset BIOS paging */ - bios.fcr[0] = 0; - bios.fcr[1] = 0; - bios.fcr[2] = 1; - bios.fcr[3] = 2; + bios->fcr[0] = 0; + bios->fcr[1] = 0; + bios->fcr[2] = 1; + bios->fcr[3] = 2; /* enable BIOS ROM */ - slot.rom = bios.rom; - slot.pages = bios.pages; - slot.mapper = MAPPER_SEGA; - slot.fcr = &bios.fcr[0]; - sms.memctrl = 0xE0; + slot->rom = bios->rom; + slot->pages = bios->pages; + slot->mapper = MAPPER_SEGA; + slot->fcr = &bios->fcr[0]; + sms->memctrl = 0xE0; } else { /* save Memory Control register value in RAM */ - sms.wram[0] = sms.memctrl; + sms->wram[0] = sms->memctrl; } } /* default cartridge ROM mapping at $0000-$BFFF (first 32k mirrored) */ for(i = 0x00; i <= 0x2F; i++) { - cpu_readmap[i] = &slot.rom[(i & 0x1F) << 10]; + cpu_readmap[i] = &slot->rom[(i & 0x1F) << 10]; cpu_writemap[i] = dummy_write; } /* enable internal RAM at $C000-$FFFF (8k mirrored) */ for(i = 0x30; i <= 0x3F; i++) { - cpu_readmap[i] = &sms.wram[(i & 0x07) << 10]; - cpu_writemap[i] = &sms.wram[(i & 0x07) << 10]; + cpu_readmap[i] = &sms->wram[(i & 0x07) << 10]; + cpu_writemap[i] = &sms->wram[(i & 0x07) << 10]; } /* reset cartridge paging registers */ @@ -346,19 +346,19 @@ void sms_reset(void) } /* reset memory map */ - if (slot.mapper != MAPPER_KOREA_MSX) + if (slot->mapper != MAPPER_KOREA_MSX) { - mapper_16k_w(0,slot.fcr[0]); - mapper_16k_w(1,slot.fcr[1]); - mapper_16k_w(2,slot.fcr[2]); - mapper_16k_w(3,slot.fcr[3]); + mapper_16k_w(0,slot->fcr[0]); + mapper_16k_w(1,slot->fcr[1]); + mapper_16k_w(2,slot->fcr[2]); + mapper_16k_w(3,slot->fcr[3]); } else { - mapper_8k_w(0,slot.fcr[0]); - mapper_8k_w(1,slot.fcr[1]); - mapper_8k_w(2,slot.fcr[2]); - mapper_8k_w(3,slot.fcr[3]); + mapper_8k_w(0,slot->fcr[0]); + mapper_8k_w(1,slot->fcr[1]); + mapper_8k_w(2,slot->fcr[2]); + mapper_8k_w(3,slot->fcr[3]); } break; } @@ -373,10 +373,10 @@ void mapper_8k_w(int address, int data) int i; /* cartridge ROM page (8k) index */ - uint8 page = data % (slot.pages << 1); + uint8 page = data % (slot->pages << 1); /* Save frame control register data */ - slot.fcr[address] = data; + slot->fcr[address] = data; switch (address & 3) { @@ -384,7 +384,7 @@ void mapper_8k_w(int address, int data) { for(i = 0x20; i <= 0x27; i++) { - cpu_readmap[i] = &slot.rom[(page << 13) | ((i & 0x07) << 10)]; + cpu_readmap[i] = &slot->rom[(page << 13) | ((i & 0x07) << 10)]; } break; } @@ -393,7 +393,7 @@ void mapper_8k_w(int address, int data) { for(i = 0x28; i <= 0x2F; i++) { - cpu_readmap[i] = &slot.rom[(page << 13) | ((i & 0x07) << 10)]; + cpu_readmap[i] = &slot->rom[(page << 13) | ((i & 0x07) << 10)]; } break; } @@ -402,7 +402,7 @@ void mapper_8k_w(int address, int data) { for(i = 0x10; i <= 0x17; i++) { - cpu_readmap[i] = &slot.rom[(page << 13) | ((i & 0x07) << 10)]; + cpu_readmap[i] = &slot->rom[(page << 13) | ((i & 0x07) << 10)]; } break; } @@ -411,7 +411,7 @@ void mapper_8k_w(int address, int data) { for(i = 0x18; i <= 0x1F; i++) { - cpu_readmap[i] = &slot.rom[(page << 13) | ((i & 0x07) << 10)]; + cpu_readmap[i] = &slot->rom[(page << 13) | ((i & 0x07) << 10)]; } break; } @@ -423,16 +423,16 @@ void mapper_16k_w(int address, int data) int i; /* cartridge ROM page (16k) index */ - uint8 page = data % slot.pages; + uint8 page = data % slot->pages; /* page index increment (SEGA mapper) */ - if (slot.fcr[0] & 0x03) + if (slot->fcr[0] & 0x03) { - page = (page + ((4 - (slot.fcr[0] & 0x03)) << 3)) % slot.pages; + page = (page + ((4 - (slot->fcr[0] & 0x03)) << 3)) % slot->pages; } /* save frame control register data */ - slot.fcr[address] = data; + slot->fcr[address] = data; switch (address) { @@ -446,22 +446,22 @@ void mapper_16k_w(int address, int data) { cpu_readmap[i] = cpu_writemap[i] = &cart.sram[offset + ((i & 0x0F) << 10)]; } - sms.save = 1; + sms->save = 1; } else { - page = slot.fcr[3] % slot.pages; + page = slot->fcr[3] % slot->pages; /* page index increment (SEGA mapper) */ - if (slot.fcr[0] & 0x03) + if (slot->fcr[0] & 0x03) { - page = (page + ((4 - (slot.fcr[0] & 0x03)) << 3)) % slot.pages; + page = (page + ((4 - (slot->fcr[0] & 0x03)) << 3)) % slot->pages; } /* cartridge ROM mapped at $8000-$BFFF */ for(i = 0x20; i <= 0x2F; i++) { - cpu_readmap[i] = &slot.rom[(page << 14) | ((i & 0x0F) << 10)]; + cpu_readmap[i] = &slot->rom[(page << 14) | ((i & 0x0F) << 10)]; cpu_writemap[i] = dummy_write; } } @@ -473,14 +473,14 @@ void mapper_16k_w(int address, int data) { cpu_writemap[i] = cpu_readmap[i] = &cart.sram[(i & 0x0F) << 10]; } - sms.save = 1; + sms->save = 1; } else { /* internal RAM (8K mirrorred) mapped at $C000-$FFFF */ for(i = 0x30; i <= 0x3F; i++) { - cpu_writemap[i] = cpu_readmap[i] = &sms.wram[(i & 0x07) << 10]; + cpu_writemap[i] = cpu_readmap[i] = &sms->wram[(i & 0x07) << 10]; } } break; @@ -489,14 +489,14 @@ void mapper_16k_w(int address, int data) case 1: /* cartridge ROM bank (16k) at $0000-$3FFF */ { /* first 1k is not fixed (CODEMASTER mapper) */ - if (slot.mapper == MAPPER_CODIES) + if (slot->mapper == MAPPER_CODIES) { - cpu_readmap[0] = &slot.rom[(page << 14)]; + cpu_readmap[0] = &slot->rom[(page << 14)]; } for(i = 0x01; i <= 0x0F; i++) { - cpu_readmap[i] = &slot.rom[(page << 14) | ((i & 0x0F) << 10)]; + cpu_readmap[i] = &slot->rom[(page << 14) | ((i & 0x0F) << 10)]; } break; } @@ -505,11 +505,11 @@ void mapper_16k_w(int address, int data) { for(i = 0x10; i <= 0x1F; i++) { - cpu_readmap[i] = &slot.rom[(page << 14) | ((i & 0x0F) << 10)]; + cpu_readmap[i] = &slot->rom[(page << 14) | ((i & 0x0F) << 10)]; } /* Ernie Elf's Golf external RAM switch */ - if (slot.mapper == MAPPER_CODIES) + if (slot->mapper == MAPPER_CODIES) { if (data & 0x80) { @@ -518,14 +518,14 @@ void mapper_16k_w(int address, int data) { cpu_writemap[i] = cpu_readmap[i] = &cart.sram[(i & 0x0F) << 10]; } - sms.save = 1; + sms->save = 1; } else { /* cartridge ROM mapped at $A000-$BFFF */ for(i = 0x28; i <= 0x2F; i++) { - cpu_readmap[i] = &slot.rom[((slot.fcr[3] % slot.pages) << 14) | ((i & 0x0F) << 10)]; + cpu_readmap[i] = &slot->rom[((slot->fcr[3] % slot->pages) << 14) | ((i & 0x0F) << 10)]; cpu_writemap[i] = dummy_write; } } @@ -536,21 +536,21 @@ void mapper_16k_w(int address, int data) case 3: /* cartridge ROM bank (16k) at $8000-$BFFF */ { /* check that external RAM (16k) is not mapped at $8000-$BFFF (SEGA mapper) */ - if ((slot.fcr[0] & 0x08)) break; + if ((slot->fcr[0] & 0x08)) break; /* first 8k */ for(i = 0x20; i <= 0x27; i++) { - cpu_readmap[i] = &slot.rom[(page << 14) | ((i & 0x0F) << 10)]; + cpu_readmap[i] = &slot->rom[(page << 14) | ((i & 0x0F) << 10)]; } /* check that external RAM (8k) is not mapped at $A000-$BFFF (CODEMASTER mapper) */ - if ((slot.mapper == MAPPER_CODIES) && (slot.fcr[2] & 0x80)) break; + if ((slot->mapper == MAPPER_CODIES) && (slot->fcr[2] & 0x80)) break; /* last 8k */ for(i = 0x28; i <= 0x2F; i++) { - cpu_readmap[i] = &slot.rom[(page << 14) | ((i & 0x0F) << 10)]; + cpu_readmap[i] = &slot->rom[(page << 14) | ((i & 0x0F) << 10)]; } break; } diff --git a/components/sms/smsplus/sms.h b/components/sms/smsplus/sms.h index f534e44a..95aa1543 100644 --- a/components/sms/smsplus/sms.h +++ b/components/sms/smsplus/sms.h @@ -81,10 +81,10 @@ enum { #define HWTYPE_GG CONSOLE_GG #define HWTYPE_MD CONSOLE_MD -#define IS_TMS (sms.console & HWTYPE_TMS) -#define IS_SMS (sms.console & HWTYPE_SMS) -#define IS_GG (sms.console & HWTYPE_GG) -#define IS_MD (sms.console & HWTYPE_MD) +#define IS_TMS (sms->console & HWTYPE_TMS) +#define IS_SMS (sms->console & HWTYPE_SMS) +#define IS_GG (sms->console & HWTYPE_GG) +#define IS_MD (sms->console & HWTYPE_MD) enum { TERRITORY_DOMESTIC = 0, @@ -155,12 +155,12 @@ typedef struct { } __attribute__((packed, aligned(1))) t_coleco; /* Global data */ -extern sms_t sms; -extern bios_t bios; -extern slot_t slot; -extern t_coleco coleco; -extern uint8 dummy_write[0x400]; -extern uint8 dummy_read[0x400]; +extern sms_t *sms; +extern bios_t *bios; +extern slot_t *slot; +extern t_coleco *coleco; +extern uint8 *dummy_write;//[0x400]; +extern uint8 *dummy_read;//[0x400]; /* Function prototypes */ extern void sms_init(void); diff --git a/components/sms/smsplus/sound/sn76489.c b/components/sms/smsplus/sound/sn76489.c index a6bbbffe..70f90b4e 100644 --- a/components/sms/smsplus/sound/sn76489.c +++ b/components/sms/smsplus/sound/sn76489.c @@ -31,7 +31,7 @@ static const int PSGVolumeValues[2][16] = { {892,774,669,575,492,417,351,292,239,192,150,113,80,50,24,0} }; -static SN76489_Context SN76489[MAX_SN76489]; +SN76489_Context *SN76489 = NULL; // [MAX_SN76489]; void SN76489_Init(int which, int PSGClockValue, int SamplingRate) { diff --git a/components/sms/smsplus/sound/sn76489.h b/components/sms/smsplus/sound/sn76489.h index 8293da82..a08981f5 100644 --- a/components/sms/smsplus/sound/sn76489.h +++ b/components/sms/smsplus/sound/sn76489.h @@ -60,6 +60,7 @@ typedef struct INT32 IntermediatePos[4]; /* intermediate values used at boundaries between + and - */ } SN76489_Context; +extern SN76489_Context *SN76489; // [MAX_SN76489]; /* Function prototypes */ void SN76489_Init(int which, int PSGClockValue, int SamplingRate); diff --git a/components/sms/smsplus/sound/sound.c b/components/sms/smsplus/sound/sound.c index d672d62e..eaa415d0 100644 --- a/components/sms/smsplus/sound/sound.c +++ b/components/sms/smsplus/sound/sound.c @@ -26,7 +26,7 @@ #include "shared.h" #include "config.h" -sms_snd_t sms_snd; +sms_snd_t *sms_snd = NULL; static int16 **fm_buffer; static int16 **psg_buffer; int *smptab; @@ -40,15 +40,15 @@ int sound_init(void) int restore_sound = 0; int i; - sms_snd.fm_which = option.fm; - sms_snd.fps = (sms.display == DISPLAY_NTSC) ? FPS_NTSC : FPS_PAL; - sms_snd.fm_clock = (sms.display == DISPLAY_NTSC) ? CLOCK_NTSC : CLOCK_PAL; - sms_snd.psg_clock = (sms.display == DISPLAY_NTSC) ? CLOCK_NTSC : CLOCK_PAL; - sms_snd.sample_rate = option.sndrate; - sms_snd.mixer_callback = NULL; + sms_snd->fm_which = option.fm; + sms_snd->fps = (sms->display == DISPLAY_NTSC) ? FPS_NTSC : FPS_PAL; + sms_snd->fm_clock = (sms->display == DISPLAY_NTSC) ? CLOCK_NTSC : CLOCK_PAL; + sms_snd->psg_clock = (sms->display == DISPLAY_NTSC) ? CLOCK_NTSC : CLOCK_PAL; + sms_snd->sample_rate = option.sndrate; + sms_snd->mixer_callback = NULL; /* Save register settings */ - if(sms_snd.enabled) + if(sms_snd->enabled) { restore_sound = 1; @@ -63,31 +63,31 @@ int sound_init(void) } /* If we are reinitializing, shut down sound emulation */ - if(sms_snd.enabled) + if(sms_snd->enabled) { sound_shutdown(); } /* Disable sound until initialization is complete */ - sms_snd.enabled = 0; + sms_snd->enabled = 0; /* Check if sample rate is invalid */ - if(sms_snd.sample_rate < 8000 || sms_snd.sample_rate > 48000) + if(sms_snd->sample_rate < 8000 || sms_snd->sample_rate > 48000) { abort(); } /* Assign stream mixing callback if none provided */ - if(!sms_snd.mixer_callback) - sms_snd.mixer_callback = sound_mixer_callback; + if(!sms_snd->mixer_callback) + sms_snd->mixer_callback = sound_mixer_callback; /* Calculate number of samples generated per frame */ - sms_snd.sample_count = (sms_snd.sample_rate / sms_snd.fps) + 1; - printf("%s: sample_count=%d fps=%d (actual=%f)\n", __func__, sms_snd.sample_count, sms_snd.fps, (float)sms_snd.sample_rate / (float)sms_snd.fps); + sms_snd->sample_count = (sms_snd->sample_rate / sms_snd->fps) + 1; + printf("%s: sample_count=%d fps=%d (actual=%f)\n", __func__, sms_snd->sample_count, sms_snd->fps, (float)sms_snd->sample_rate / (float)sms_snd->fps); /* Calculate size of sample buffer */ - sms_snd.buffer_size = sms_snd.sample_count * 2; - printf("%s: sms_snd.buffer_size=%d\n", __func__, sms_snd.buffer_size); + sms_snd->buffer_size = sms_snd->sample_count * 2; + printf("%s: sms_snd->buffer_size=%d\n", __func__, sms_snd->buffer_size); /* Free sample buffer position table if previously allocated */ if(smptab) @@ -97,14 +97,14 @@ int sound_init(void) } /* Prepare incremental info */ - sms_snd.done_so_far = 0; - smptab_len = (sms.display == DISPLAY_NTSC) ? 262 : 313; + sms_snd->done_so_far = 0; + smptab_len = (sms->display == DISPLAY_NTSC) ? 262 : 313; smptab = malloc(smptab_len * sizeof(int)); if (!smptab) abort(); for (i = 0; i < smptab_len; i++) { - double calc = (sms_snd.sample_count * i); + double calc = (sms_snd->sample_count * i); calc = calc / (double)smptab_len; smptab[i] = (int)calc; } @@ -112,25 +112,25 @@ int sound_init(void) /* Allocate emulated sound streams */ for(i = 0; i < STREAM_MAX; i++) { - sms_snd.stream[i] = malloc(sms_snd.buffer_size); - if(!sms_snd.stream[i]) abort(); - memset(sms_snd.stream[i], 0, sms_snd.buffer_size); + sms_snd->stream[i] = malloc(sms_snd->buffer_size); + if(!sms_snd->stream[i]) abort(); + memset(sms_snd->stream[i], 0, sms_snd->buffer_size); } #ifndef NGC /* Allocate sound output streams */ - sms_snd.output[0] = malloc(sms_snd.buffer_size); - sms_snd.output[1] = malloc(sms_snd.buffer_size); - if(!sms_snd.output[0] || !sms_snd.output[1]) abort(); + sms_snd->output[0] = malloc(sms_snd->buffer_size); + sms_snd->output[1] = malloc(sms_snd->buffer_size); + if(!sms_snd->output[0] || !sms_snd->output[1]) abort(); #endif /* Set up buffer pointers */ - fm_buffer = (int16 **)&sms_snd.stream[STREAM_FM_MO]; - psg_buffer = (int16 **)&sms_snd.stream[STREAM_PSG_L]; + fm_buffer = (int16 **)&sms_snd->stream[STREAM_FM_MO]; + psg_buffer = (int16 **)&sms_snd->stream[STREAM_PSG_L]; /* Set up SN76489 emulation */ - SN76489_Init(0, sms_snd.psg_clock, sms_snd.sample_rate); - SN76489_Config(0, MUTE_ALLON, BOOST_OFF /*BOOST_ON*/, VOL_FULL, (sms.console < CONSOLE_SMS) ? FB_SC3000 : FB_SEGAVDP); + SN76489_Init(0, sms_snd->psg_clock, sms_snd->sample_rate); + SN76489_Config(0, MUTE_ALLON, BOOST_OFF /*BOOST_ON*/, VOL_FULL, (sms->console < CONSOLE_SMS) ? FB_SC3000 : FB_SEGAVDP); #if 0 /* Set up YM2413 emulation */ @@ -147,7 +147,7 @@ int sound_init(void) } /* Inform other functions that we can use sound */ - sms_snd.enabled = 1; + sms_snd->enabled = 1; return 1; } @@ -157,16 +157,16 @@ void sound_shutdown(void) { int i; - if(!sms_snd.enabled) + if(!sms_snd->enabled) return; /* Free emulated sound streams */ for(i = 0; i < STREAM_MAX; i++) { - if(sms_snd.stream[i]) + if(sms_snd->stream[i]) { - free(sms_snd.stream[i]); - sms_snd.stream[i] = NULL; + free(sms_snd->stream[i]); + sms_snd->stream[i] = NULL; } } @@ -174,10 +174,10 @@ void sound_shutdown(void) /* Free sound output buffers */ for(i = 0; i < 2; i++) { - if(sms_snd.output[i]) + if(sms_snd->output[i]) { - free(sms_snd.output[i]); - sms_snd.output[i] = NULL; + free(sms_snd->output[i]); + sms_snd->output[i] = NULL; } } #endif @@ -194,7 +194,7 @@ void sound_shutdown(void) void sms_sound_reset(void) { - if(!sms_snd.enabled) + if(!sms_snd->enabled) return; /* Reset SN76489 emulator */ @@ -211,42 +211,42 @@ void sound_update(int line) { int16 *fm[2], *psg[2]; - if(!sms_snd.enabled) + if(!sms_snd->enabled) return; /* Finish buffers at end of frame */ if(line == smptab_len - 1) { - psg[0] = psg_buffer[0] + sms_snd.done_so_far; - psg[1] = psg_buffer[1] + sms_snd.done_so_far; - fm[0] = fm_buffer[0] + sms_snd.done_so_far; - fm[1] = fm_buffer[1] + sms_snd.done_so_far; + psg[0] = psg_buffer[0] + sms_snd->done_so_far; + psg[1] = psg_buffer[1] + sms_snd->done_so_far; + fm[0] = fm_buffer[0] + sms_snd->done_so_far; + fm[1] = fm_buffer[1] + sms_snd->done_so_far; /* Generate SN76489 sample data */ - SN76489_Update(0, psg, sms_snd.sample_count - sms_snd.done_so_far); + SN76489_Update(0, psg, sms_snd->sample_count - sms_snd->done_so_far); #if 0 /* Generate YM2413 sample data */ - FM_Update(fm, sms_snd.sample_count - sms_snd.done_so_far); + FM_Update(fm, sms_snd->sample_count - sms_snd->done_so_far); #endif /* Mix streams into output buffer */ - sms_snd.mixer_callback(sms_snd.stream, sms_snd.output, sms_snd.sample_count); + sms_snd->mixer_callback(sms_snd->stream, sms_snd->output, sms_snd->sample_count); /* Reset */ - sms_snd.done_so_far = 0; + sms_snd->done_so_far = 0; } else { int tinybit; - tinybit = smptab[line] - sms_snd.done_so_far; + tinybit = smptab[line] - sms_snd->done_so_far; /* Do a tiny bit */ - psg[0] = psg_buffer[0] + sms_snd.done_so_far; - psg[1] = psg_buffer[1] + sms_snd.done_so_far; - fm[0] = fm_buffer[0] + sms_snd.done_so_far; - fm[1] = fm_buffer[1] + sms_snd.done_so_far; + psg[0] = psg_buffer[0] + sms_snd->done_so_far; + psg[1] = psg_buffer[1] + sms_snd->done_so_far; + fm[0] = fm_buffer[0] + sms_snd->done_so_far; + fm[1] = fm_buffer[1] + sms_snd->done_so_far; /* Generate SN76489 sample data */ SN76489_Update(0, psg, tinybit); @@ -257,7 +257,7 @@ void sound_update(int line) #endif /* Sum total */ - sms_snd.done_so_far += tinybit; + sms_snd->done_so_far += tinybit; } } @@ -281,7 +281,7 @@ void sound_mixer_callback(int16 **stream, int16 **output, int length) void psg_stereo_w(int data) { - if(!sms_snd.enabled) return; + if(!sms_snd->enabled) return; SN76489_GGStereoWrite(0, data); } @@ -292,7 +292,7 @@ void stream_update(int which, int position) void psg_write(int data) { - if(!sms_snd.enabled) return; + if(!sms_snd->enabled) return; SN76489_Write(0, data); } @@ -302,17 +302,17 @@ void psg_write(int data) int fmunit_detect_r(void) { - return sms.fm_detect; + return sms->fm_detect; } void fmunit_detect_w(int data) { - if(!sms_snd.enabled || !sms.use_fm) return; - sms.fm_detect = data; + if(!sms_snd->enabled || !sms->use_fm) return; + sms->fm_detect = data; } void fmunit_write(int offset, int data) { - if(!sms_snd.enabled || !sms.use_fm) return; + if(!sms_snd->enabled || !sms->use_fm) return; abort(); //FM_Write(offset, data); } diff --git a/components/sms/smsplus/sound/sound.h b/components/sms/smsplus/sound/sound.h index 6086d647..e20dec25 100644 --- a/components/sms/smsplus/sound/sound.h +++ b/components/sms/smsplus/sound/sound.h @@ -52,7 +52,7 @@ typedef struct /* Global data */ -extern sms_snd_t sms_snd; +extern sms_snd_t *sms_snd; /* Function prototypes */ void psg_write(int data); diff --git a/components/sms/smsplus/state.c b/components/sms/smsplus/state.c index df639cd8..fb4397ce 100644 --- a/components/sms/smsplus/state.c +++ b/components/sms/smsplus/state.c @@ -40,42 +40,42 @@ system_save_state: sizeof SN76489_Context=92 */ // The three malloc-ed data structures are: -// sms.wram -// vdp.vram +// sms->wram +// vdp->vram // cart.sram int system_save_state(void *mem) { int i; - printf("%s: sizeof sms=%d\n", __func__, sizeof(sms)); - printf("%s: sizeof vdp=%d\n", __func__, sizeof(vdp)); - printf("%s: sizeof Z80=%d\n", __func__, sizeof(Z80)); + printf("%s: sizeof sms=%d\n", __func__, sizeof(sms_t)); + printf("%s: sizeof vdp=%d\n", __func__, sizeof(vdp_t)); + printf("%s: sizeof Z80=%d\n", __func__, sizeof(Z80_Regs)); printf("%s: sizeof SN76489_Context=%d\n", __func__, sizeof(SN76489_Context)); /*** Save SMS Context ***/ // fwrite(&sms, sizeof(sms), 1, mem); - uint8 *wram = sms.wram; + uint8 *wram = sms->wram; // cannot directly write sms since it contains a pointer to malloc-ed memory, // so we must save the malloced data and then separately save the non-malloced // data fwrite(wram, 0x2000, 1, mem); // now save the rest of the sms_t struct - sms.wram = NULL; - fwrite(&sms, sizeof(sms), 1, mem); + sms->wram = NULL; + fwrite(sms, sizeof(sms_t), 1, mem); // now restore the sms_t struct - sms.wram = wram; + sms->wram = wram; /*** Save VDP state ***/ // Same for vdp, we must save the malloced data and then separately save the // non-malloced data - // fwrite(&vdp, sizeof(vdp), 1, mem); - uint8 *vram = vdp.vram; + // fwrite(&vdp, sizeof(vdp_t), 1, mem); + uint8 *vram = vdp->vram; fwrite(vram, 0x4000, 1, mem); - vdp.vram = NULL; - fwrite(&vdp, sizeof(vdp), 1, mem); - vdp.vram = vram; + vdp->vram = NULL; + fwrite(vdp, sizeof(vdp_t), 1, mem); + vdp->vram = vram; /*** Save cart info ***/ for (i = 0; i < 4; i++) @@ -87,7 +87,7 @@ int system_save_state(void *mem) fwrite(cart.sram, 0x8000, 1, mem); /*** Save Z80 Context ***/ - fwrite(&Z80, sizeof(Z80), 1, mem); + fwrite(Z80, sizeof(Z80_Regs), 1, mem); #if 0 /*** Save YM2413 ***/ @@ -105,43 +105,42 @@ int system_save_state(void *mem) void system_load_state(void *mem) { int i; - uint8 *buf; - printf("%s: sizeof sms=%d\n", __func__, sizeof(sms)); - printf("%s: sizeof vdp=%d\n", __func__, sizeof(vdp)); - printf("%s: sizeof Z80=%d\n", __func__, sizeof(Z80)); + printf("%s: sizeof sms=%d\n", __func__, sizeof(sms_t)); + printf("%s: sizeof vdp=%d\n", __func__, sizeof(vdp_t)); + printf("%s: sizeof Z80=%d\n", __func__, sizeof(Z80_Regs)); printf("%s: sizeof SN76489_Context=%d\n", __func__, sizeof(SN76489_Context)); /* Initialize everything */ system_reset(); - // first read the malloc-ed data from sms.wram - fread(sms.wram, 0x2000, 1, mem); + // first read the malloc-ed data from sms->wram + fread(sms->wram, 0x2000, 1, mem); // save the pointer to the malloc-ed data - uint8 *wram = sms.wram; + uint8 *wram = sms->wram; // Then read the rest of the sms_t struct /*** Set SMS Context ***/ sms_t sms_tmp; fread(&sms_tmp, sizeof(sms_tmp), 1, mem); - if(sms.console != sms_tmp.console) + if(sms->console != sms_tmp.console) { system_reset(); printf("%s: Bad save data\n", __func__); return; } - sms = sms_tmp; + *sms = sms_tmp; // restore the pointer to the malloc-ed data - sms.wram = wram; + sms->wram = wram; - // first read the malloc-ed data from vdp.vram - fread(vdp.vram, 0x4000, 1, mem); + // first read the malloc-ed data from vdp->vram + fread(vdp->vram, 0x4000, 1, mem); // save the pointer to the malloc-ed data - uint8 *vram = vdp.vram; + uint8 *vram = vdp->vram; /*** Set vdp state ***/ - fread(&vdp, sizeof(vdp), 1, mem); + fread(vdp, sizeof(vdp_t), 1, mem); // restore the pointer to the malloc-ed data - vdp.vram = vram; + vdp->vram = vram; /** restore video & audio settings (needed if timing changed) ***/ vdp_init(); @@ -157,9 +156,9 @@ void system_load_state(void *mem) fread(cart.sram, 0x8000, 1, mem); /*** Set Z80 Context ***/ - int (*irq_cb)(int) = Z80.irq_callback; - fread(&Z80, sizeof(Z80), 1, mem); - Z80.irq_callback = irq_cb; + int (*irq_cb)(int) = Z80->irq_callback; + fread(Z80, sizeof(Z80_Regs), 1, mem); + Z80->irq_callback = irq_cb; #if 0 /*** Set YM2413 ***/ @@ -183,30 +182,30 @@ void system_load_state(void *mem) psg->dClock = psg_dClock; - if ((sms.console != CONSOLE_COLECO) && (sms.console != CONSOLE_SG1000)) + if ((sms->console != CONSOLE_COLECO) && (sms->console != CONSOLE_SG1000)) { /* Cartridge by default */ - slot.rom = cart.rom; - slot.pages = cart.pages; - slot.mapper = cart.mapper; - slot.fcr = &cart.fcr[0]; + slot->rom = cart.rom; + slot->pages = cart.pages; + slot->mapper = cart.mapper; + slot->fcr = &cart.fcr[0]; /* Restore mapping */ mapper_reset(); - cpu_readmap[0] = &slot.rom[0]; - if (slot.mapper != MAPPER_KOREA_MSX) + cpu_readmap[0] = &slot->rom[0]; + if (slot->mapper != MAPPER_KOREA_MSX) { - mapper_16k_w(0,slot.fcr[0]); - mapper_16k_w(1,slot.fcr[1]); - mapper_16k_w(2,slot.fcr[2]); - mapper_16k_w(3,slot.fcr[3]); + mapper_16k_w(0,slot->fcr[0]); + mapper_16k_w(1,slot->fcr[1]); + mapper_16k_w(2,slot->fcr[2]); + mapper_16k_w(3,slot->fcr[3]); } else { - mapper_8k_w(0,slot.fcr[0]); - mapper_8k_w(1,slot.fcr[1]); - mapper_8k_w(2,slot.fcr[2]); - mapper_8k_w(3,slot.fcr[3]); + mapper_8k_w(0,slot->fcr[0]); + mapper_8k_w(1,slot->fcr[1]); + mapper_8k_w(2,slot->fcr[2]); + mapper_8k_w(3,slot->fcr[3]); } } diff --git a/components/sms/smsplus/system.c b/components/sms/smsplus/system.c index ce0e3bde..fc4e7215 100644 --- a/components/sms/smsplus/system.c +++ b/components/sms/smsplus/system.c @@ -36,54 +36,54 @@ void system_frame(int skip_render) /* Debounce pause key */ if(input.system & INPUT_PAUSE) { - if(!sms.paused) + if(!sms->paused) { - sms.paused = 1; + sms->paused = 1; z80_set_irq_line(INPUT_LINE_NMI, ASSERT_LINE); z80_set_irq_line(INPUT_LINE_NMI, CLEAR_LINE); } } else { - sms.paused = 0; + sms->paused = 0; } /* Reset TMS Text offset counter */ text_counter = 0; /* 3D glasses faking */ - if (sms.glasses_3d) skip_render = sms.wram[0x1ffb]; + if (sms->glasses_3d) skip_render = sms->wram[0x1ffb]; /* VDP register 9 is latched during VBLANK */ - vdp.vscroll = vdp.reg[9]; + vdp->vscroll = vdp->reg[9]; /* Reload Horizontal Interrupt counter */ - vdp.left = vdp.reg[0x0A]; + vdp->left = vdp->reg[0x0A]; /* Reset collision flag infos */ - vdp.spr_col = 0xff00; + vdp->spr_col = 0xff00; /* Line processing */ - for(vdp.line = 0; vdp.line < vdp.lpf; vdp.line++) + for(vdp->line = 0; vdp->line < vdp->lpf; vdp->line++) { - iline = vdp.height; + iline = vdp->height; /* VDP line rendering */ if(!skip_render) { - render_line(vdp.line); + render_line(vdp->line); } /* Horizontal Interrupt */ - if (sms.console >= CONSOLE_SMS) + if (sms->console >= CONSOLE_SMS) { - if(vdp.line <= iline) + if(vdp->line <= iline) { - if(--vdp.left < 0) + if(--vdp->left < 0) { - vdp.left = vdp.reg[0x0A]; - vdp.hint_pending = 1; - if(vdp.reg[0x00] & 0x10) + vdp->left = vdp->reg[0x0A]; + vdp->hint_pending = 1; + if(vdp->reg[0x00] & 0x10) { /* IRQ line is latched between instructions, on instruction last cycle */ /* This means that if Z80 cycle count is exactly a multiple of CYCLES_PER_LINE, */ @@ -102,18 +102,18 @@ void system_frame(int skip_render) z80_execute(line_z80 - z80_cycle_count); /* Vertical Interrupt */ - if(vdp.line == iline) + if(vdp->line == iline) { - vdp.status |= 0x80; - vdp.vint_pending = 1; - if(vdp.reg[0x01] & 0x20) + vdp->status |= 0x80; + vdp->vint_pending = 1; + if(vdp->reg[0x01] & 0x20) { - z80_set_irq_line(vdp.irq, ASSERT_LINE); + z80_set_irq_line(vdp->irq, ASSERT_LINE); } } /* Run sound chips */ - sound_update(vdp.line); + sound_update(vdp->line); } /* Adjust Z80 cycle count for next frame */ diff --git a/components/sms/smsplus/tms.c b/components/sms/smsplus/tms.c index 04f409e1..33957ccc 100644 --- a/components/sms/smsplus/tms.c +++ b/components/sms/smsplus/tms.c @@ -58,7 +58,7 @@ static void render_bg_m2(int line); void parse_line(int line) { int yp, i; - int mode = vdp.reg[1] & 3; + int mode = vdp->reg[1] & 3; int size = size_tab[mode]; int diff, name; uint8 *sa, *sg; @@ -72,7 +72,7 @@ void parse_line(int line) { /* Point to current sprite in SA and our current sprite record */ p = &sprites[sprites_found]; - sa = &vdp.vram[vdp.sa + (i << 2)]; + sa = &vdp->vram[vdp->sa + (i << 2)]; /* Fetch Y coordinate */ yp = sa[0]; @@ -92,7 +92,7 @@ void parse_line(int line) if(sprites_found == 4) { /* Set 5S and abort parsing */ - vdp.status |= 0x40; + vdp->status |= 0x40; goto parse_end; } @@ -117,7 +117,7 @@ void parse_line(int line) name |= 1; /* Fetch SG data */ - sg = &vdp.vram[vdp.sg | (name << 3) | (diff & 7)]; + sg = &vdp->vram[vdp->sg | (name << 3) | (diff & 7)]; p->sg[0] = sg[0x00]; p->sg[1] = sg[0x10]; @@ -128,7 +128,7 @@ void parse_line(int line) parse_end: /* Insert number of last sprite entry processed */ - vdp.status = (vdp.status & 0xE0) | (i & 0x1F); + vdp->status = (vdp->status & 0xE0) | (i & 0x1F); } void render_obj_tms(int line) @@ -140,7 +140,7 @@ void render_obj_tms(int line) uint8 *lb, *lut, *ex[2]; tms_sprite *p; - mode = vdp.reg[1] & 3; + mode = vdp->reg[1] & 3; size = size_tab[mode]; /* Render sprites */ @@ -174,11 +174,11 @@ void render_obj_tms(int line) if(ex[0][x]) { /* Check sprite collision */ - if ((lb[x] & 0x40) && !(vdp.status & 0x20)) + if ((lb[x] & 0x40) && !(vdp->status & 0x20)) { /* pixel-accurate SPR_COL flag */ - vdp.status |= 0x20; - vdp.spr_col = (line << 8) | ((p->xpos + x + 13) >> 1); + vdp->status |= 0x20; + vdp->spr_col = (line << 8) | ((p->xpos + x + 13) >> 1); } lb[x] = lut[lb[x]]; } @@ -190,11 +190,11 @@ void render_obj_tms(int line) if(ex[0][x >> 1]) { /* Check sprite collision */ - if ((lb[x] & 0x40) && !(vdp.status & 0x20)) + if ((lb[x] & 0x40) && !(vdp->status & 0x20)) { /* pixel-accurate SPR_COL flag */ - vdp.status |= 0x20; - vdp.spr_col = (line << 8) | ((p->xpos + x + 13) >> 1); + vdp->status |= 0x20; + vdp->spr_col = (line << 8) | ((p->xpos + x + 13) >> 1); } lb[x] = lut[lb[x]]; } @@ -206,11 +206,11 @@ void render_obj_tms(int line) if(ex[(x >> 3) & 1][x & 7]) { /* Check sprite collision */ - if ((lb[x] & 0x40) && !(vdp.status & 0x20)) + if ((lb[x] & 0x40) && !(vdp->status & 0x20)) { /* pixel-accurate SPR_COL flag */ - vdp.status |= 0x20; - vdp.spr_col = (line << 8) | ((p->xpos + x + 13) >> 1); + vdp->status |= 0x20; + vdp->spr_col = (line << 8) | ((p->xpos + x + 13) >> 1); } lb[x] = lut[lb[x]]; } @@ -222,11 +222,11 @@ void render_obj_tms(int line) if(ex[(x >> 4) & 1][(x >> 1) & 7]) { /* Check sprite collision */ - if ((lb[x] & 0x40) && !(vdp.status & 0x20)) + if ((lb[x] & 0x40) && !(vdp->status & 0x20)) { /* pixel-accurate SPR_COL flag */ - vdp.status |= 0x20; - vdp.spr_col = (line << 8) | ((p->xpos + x + 13) >> 1); + vdp->status |= 0x20; + vdp->spr_col = (line << 8) | ((p->xpos + x + 13) >> 1); } lb[x] = lut[lb[x]]; } @@ -405,7 +405,7 @@ void make_tms_tables(void) void render_bg_tms(int line) { - switch(vdp.mode & 7) + switch(vdp->mode & 7) { case 0: /* Graphics I */ render_bg_m0(line); @@ -451,14 +451,14 @@ static void render_bg_m0(int line) uint8 *clut; uint8 *bpex; uint8 *lb = &linebuf[0]; - uint8 *pn = &vdp.vram[vdp.pn + ((line >> 3) << 5)]; - uint8 *ct = &vdp.vram[vdp.ct]; - uint8 *pg = &vdp.vram[vdp.pg | (v_row)]; + uint8 *pn = &vdp->vram[vdp->pn + ((line >> 3) << 5)]; + uint8 *ct = &vdp->vram[vdp->ct]; + uint8 *pg = &vdp->vram[vdp->pg | (v_row)]; for(column = 0; column < 32; column++) { name = pn[column]; - clut = &tms_lookup[vdp.bd][ct[name >> 3]][0]; + clut = &tms_lookup[vdp->bd][ct[name >> 3]][0]; bpex = &bp_expand[pg[name << 3]][0]; RENDER_GR_LINE } @@ -473,12 +473,12 @@ static void render_bg_m1(int line) uint8 *clut; uint8 *bpex; uint8 *lb = &linebuf[0]; -// uint8 *pn = &vdp.vram[vdp.pn + ((line >> 3) * 40)]; +// uint8 *pn = &vdp->vram[vdp->pn + ((line >> 3) * 40)]; - uint8 *pn = &vdp.vram[vdp.pn + text_counter]; + uint8 *pn = &vdp->vram[vdp->pn + text_counter]; - uint8 *pg = &vdp.vram[vdp.pg | (v_row)]; - uint8 bk = vdp.reg[7]; + uint8 *pg = &vdp->vram[vdp->pg | (v_row)]; + uint8 bk = vdp->reg[7]; clut = &txt_lookup[bk][0]; @@ -489,7 +489,7 @@ static void render_bg_m1(int line) } /* V3 */ - if((vdp.line & 7) == 7) + if((vdp->line & 7) == 7) text_counter += 40; RENDER_TX_BORDER @@ -504,9 +504,9 @@ static void render_bg_m1x(int line) uint8 *clut; uint8 *bpex; uint8 *lb = &linebuf[0]; - uint8 *pn = &vdp.vram[vdp.pn + ((line >> 3) * 40)]; - uint8 *pg = &vdp.vram[vdp.pg + (v_row) + ((line & 0xC0) << 5)]; - uint8 bk = vdp.reg[7]; + uint8 *pn = &vdp->vram[vdp->pn + ((line >> 3) * 40)]; + uint8 *pg = &vdp->vram[vdp->pg + (v_row) + ((line & 0xC0) << 5)]; + uint8 bk = vdp->reg[7]; clut = &tms_lookup[0][bk][0]; @@ -525,7 +525,7 @@ static void render_bg_inv(int line) uint8 *clut; uint8 *bpex; uint8 *lb = &linebuf[0]; - uint8 bk = vdp.reg[7]; + uint8 bk = vdp->reg[7]; clut = &txt_lookup[bk][0]; @@ -543,12 +543,12 @@ static void render_bg_m3(int line) uint8 *mcex; uint8 *lb = &linebuf[0]; - uint8 *pn = &vdp.vram[vdp.pn + ((line >> 3) << 5)]; - uint8 *pg = &vdp.vram[vdp.pg + ((line >> 2) & 7)]; + uint8 *pn = &vdp->vram[vdp->pn + ((line >> 3) << 5)]; + uint8 *pg = &vdp->vram[vdp->pg + ((line >> 2) & 7)]; for(column = 0; column < 32; column++) { - mcex = &mc_lookup[vdp.bd][pg[pn[column]<<3]][0]; + mcex = &mc_lookup[vdp->bd][pg[pn[column]<<3]][0]; RENDER_MC_LINE } } @@ -559,12 +559,12 @@ static void render_bg_m3x(int line) int column; uint8 *mcex; uint8 *lb = &linebuf[0]; - uint8 *pn = &vdp.vram[vdp.pn + ((line >> 3) << 5)]; - uint8 *pg = &vdp.vram[vdp.pg + ((line >> 2) & 7) + ((line & 0xC0) << 5)]; + uint8 *pn = &vdp->vram[vdp->pn + ((line >> 3) << 5)]; + uint8 *pg = &vdp->vram[vdp->pg + ((line >> 2) & 7) + ((line & 0xC0) << 5)]; for(column = 0; column < 32; column++) { - mcex = &mc_lookup[vdp.bd][pg[pn[column]<<3]][0]; + mcex = &mc_lookup[vdp->bd][pg[pn[column]<<3]][0]; RENDER_MC_LINE } } @@ -579,14 +579,14 @@ static void render_bg_m2(int line) uint8 *clut; uint8 *bpex; uint8 *lb = &linebuf[0]; - uint8 *pn = &vdp.vram[vdp.pn | ((line & 0xF8) << 2)]; - uint8 *ct = &vdp.vram[(vdp.ct & 0x2000) | (v_row) | ((line & 0xC0) << 5)]; - uint8 *pg = &vdp.vram[(vdp.pg & 0x2000) | (v_row) | ((line & 0xC0) << 5)]; + uint8 *pn = &vdp->vram[vdp->pn | ((line & 0xF8) << 2)]; + uint8 *ct = &vdp->vram[(vdp->ct & 0x2000) | (v_row) | ((line & 0xC0) << 5)]; + uint8 *pg = &vdp->vram[(vdp->pg & 0x2000) | (v_row) | ((line & 0xC0) << 5)]; for(column = 0; column < 32; column++) { name = pn[column] << 3; - clut = &tms_lookup[vdp.bd][ct[name]][0]; + clut = &tms_lookup[vdp->bd][ct[name]][0]; bpex = &bp_expand[pg[name]][0]; RENDER_GR_LINE } diff --git a/components/sms/smsplus/vdp.c b/components/sms/smsplus/vdp.c index d56edfbe..3ebc64e2 100644 --- a/components/sms/smsplus/vdp.c +++ b/components/sms/smsplus/vdp.c @@ -43,13 +43,13 @@ #endif /* VDP context */ -vdp_t vdp; +vdp_t *vdp; /* Initialize VDP emulation */ void vdp_init(void) { /* display area */ - if ((sms.console == CONSOLE_GG) && (!option.extra_gg)) + if ((sms->console == CONSOLE_GG) && (!option.extra_gg)) { bitmap.viewport.w = 160; bitmap.viewport.x = 48; @@ -67,7 +67,7 @@ void vdp_init(void) } /* number of scanlines */ - vdp.lpf = sms.display ? 313 : 262; + vdp->lpf = sms->display ? 313 : 262; /* reset viewport */ viewport_check(); @@ -83,46 +83,46 @@ void vdp_shutdown(void) void vdp_reset(void) { // save the vram pointer - uint8 *vram = vdp.vram; + uint8 *vram = vdp->vram; /* reset VDP structure */ - memset(&vdp, 0, sizeof(vdp_t)); + memset(vdp, 0, sizeof(vdp_t)); // reset the vram pointer - vdp.vram = vram; + vdp->vram = vram; /* number of scanlines */ - vdp.lpf = sms.display ? 313 : 262; + vdp->lpf = sms->display ? 313 : 262; /* VDP registers default values (usually set by BIOS) */ - if (IS_SMS && (bios.enabled != 3)) + if (IS_SMS && (bios->enabled != 3)) { - vdp.reg[0] = 0x36; - vdp.reg[1] = 0x80; - vdp.reg[2] = 0xFF; - vdp.reg[3] = 0xFF; - vdp.reg[4] = 0xFF; - vdp.reg[5] = 0xFF; - vdp.reg[6] = 0xFB; - vdp.reg[10] = 0xFF; + vdp->reg[0] = 0x36; + vdp->reg[1] = 0x80; + vdp->reg[2] = 0xFF; + vdp->reg[3] = 0xFF; + vdp->reg[4] = 0xFF; + vdp->reg[5] = 0xFF; + vdp->reg[6] = 0xFB; + vdp->reg[10] = 0xFF; } /* VDP interrupt */ - if (sms.console == CONSOLE_COLECO) - vdp.irq = INPUT_LINE_NMI; + if (sms->console == CONSOLE_COLECO) + vdp->irq = INPUT_LINE_NMI; else - vdp.irq = INPUT_LINE_IRQ0; + vdp->irq = INPUT_LINE_IRQ0; /* reset VDP viewport */ viewport_check(); /* reset VDP internals */ - vdp.ct = (vdp.reg[3] << 6) & 0x3FC0; - vdp.pg = (vdp.reg[4] << 11) & 0x3800; - vdp.satb = (vdp.reg[5] << 7) & 0x3F00; - vdp.sa = (vdp.reg[5] << 7) & 0x3F80; - vdp.sg = (vdp.reg[6] << 11) & 0x3800; - vdp.bd = (vdp.reg[7] & 0x0F); + vdp->ct = (vdp->reg[3] << 6) & 0x3FC0; + vdp->pg = (vdp->reg[4] << 11) & 0x3800; + vdp->satb = (vdp->reg[5] << 7) & 0x3F00; + vdp->sa = (vdp->reg[5] << 7) & 0x3F80; + vdp->sg = (vdp->reg[6] << 11) & 0x3800; + vdp->bd = (vdp->reg[7] & 0x0F); bitmap.viewport.changed = 1; } @@ -131,58 +131,58 @@ void vdp_reset(void) void viewport_check(void) { int i; - int m1 = (vdp.reg[1] >> 4) & 1; - int m3 = (vdp.reg[1] >> 3) & 1; - int m2 = (vdp.reg[0] >> 1) & 1; - int m4 = (vdp.reg[0] >> 2) & 1; + int m1 = (vdp->reg[1] >> 4) & 1; + int m3 = (vdp->reg[1] >> 3) & 1; + int m2 = (vdp->reg[0] >> 1) & 1; + int m4 = (vdp->reg[0] >> 2) & 1; - vdp.mode = (m4 << 3 | m3 << 2 | m2 << 1 | m1 << 0); + vdp->mode = (m4 << 3 | m3 << 2 | m2 << 1 | m1 << 0); /* Check for extended modes */ - if (sms.console >= CONSOLE_SMS2) + if (sms->console >= CONSOLE_SMS2) { - switch (vdp.mode) + switch (vdp->mode) { case 0x0B: /* Mode 4 extended (224 lines) */ - vdp.height = 224; - vdp.extended = 1; - vdp.ntab = ((vdp.reg[2] << 10) & 0x3000) | 0x0700; + vdp->height = 224; + vdp->extended = 1; + vdp->ntab = ((vdp->reg[2] << 10) & 0x3000) | 0x0700; break; case 0x0E: /* Mode 4 extended (240 lines) */ - vdp.height = 240; - vdp.extended = 2; - vdp.ntab = ((vdp.reg[2] << 10) & 0x3000) | 0x0700; + vdp->height = 240; + vdp->extended = 2; + vdp->ntab = ((vdp->reg[2] << 10) & 0x3000) | 0x0700; break; default: /* Mode 4 (192 lines) */ - vdp.height = 192; - vdp.extended = 0; - vdp.ntab = (vdp.reg[2] << 10) & 0x3800; + vdp->height = 192; + vdp->extended = 0; + vdp->ntab = (vdp->reg[2] << 10) & 0x3800; /* invalid text mode (Mode 4) */ - if ((vdp.mode & 0x0B) == 0x09) vdp.mode = 1; + if ((vdp->mode & 0x0B) == 0x09) vdp->mode = 1; break; } } else { /* always use Mode 4 (192 lines) */ - vdp.height = 192; - vdp.extended = 0; - vdp.ntab = (vdp.reg[2] << 10) & 0x3800; + vdp->height = 192; + vdp->extended = 0; + vdp->ntab = (vdp->reg[2] << 10) & 0x3800; /* invalid text mode (Mode 4) */ - if ((vdp.mode & 0x09) == 0x09) vdp.mode = 1; + if ((vdp->mode & 0x09) == 0x09) vdp->mode = 1; } /* update display area */ - if ((sms.console != CONSOLE_GG) || option.extra_gg) + if ((sms->console != CONSOLE_GG) || option.extra_gg) { - if(bitmap.viewport.h != vdp.height) + if(bitmap.viewport.h != vdp->height) { bitmap.viewport.oh = bitmap.viewport.h; - bitmap.viewport.h = vdp.height; + bitmap.viewport.h = vdp->height; bitmap.viewport.changed = 1; } } @@ -196,7 +196,7 @@ void viewport_check(void) bitmap.viewport.y = 0; if (option.overscan) { - int max = sms.display ? 288 : 240; + int max = sms->display ? 288 : 240; bitmap.viewport.y = (max - bitmap.viewport.h) / 2; } @@ -210,9 +210,9 @@ void viewport_check(void) } } - vdp.pn = (vdp.reg[2] << 10) & 0x3C00; + vdp->pn = (vdp->reg[2] << 10) & 0x3C00; - if (vdp.mode & 8) + if (vdp->mode & 8) { render_bg = render_bg_sms; render_obj = render_obj_sms; @@ -230,13 +230,13 @@ void viewport_check(void) void vdp_reg_w(uint8 r, uint8 d) { /* Store register data */ - vdp.reg[r] = d; + vdp->reg[r] = d; switch(r) { case 0x00: /* Mode Control No. 1 */ - if(vdp.hint_pending) + if(vdp->hint_pending) { if(d & 0x10) z80_set_irq_line(0, ASSERT_LINE); else z80_set_irq_line(0, CLEAR_LINE); @@ -245,10 +245,10 @@ void vdp_reg_w(uint8 r, uint8 d) break; case 0x01: /* Mode Control No. 2 */ - if(vdp.vint_pending) + if(vdp->vint_pending) { - if(d & 0x20) z80_set_irq_line(vdp.irq, ASSERT_LINE); - else z80_set_irq_line(vdp.irq, CLEAR_LINE); + if(d & 0x20) z80_set_irq_line(vdp->irq, ASSERT_LINE); + else z80_set_irq_line(vdp->irq, CLEAR_LINE); } viewport_check(); break; @@ -258,24 +258,24 @@ void vdp_reg_w(uint8 r, uint8 d) break; case 0x03: - vdp.ct = (d << 6) & 0x3FC0; + vdp->ct = (d << 6) & 0x3FC0; break; case 0x04: - vdp.pg = (d << 11) & 0x3800; + vdp->pg = (d << 11) & 0x3800; break; case 0x05: /* Sprite Attribute Table Base Address */ - vdp.satb = (d << 7) & 0x3F00; - vdp.sa = (d << 7) & 0x3F80; + vdp->satb = (d << 7) & 0x3F00; + vdp->sa = (d << 7) & 0x3F80; break; case 0x06: - vdp.sg = (d << 11) & 0x3800; + vdp->sg = (d << 11) & 0x3800; break; case 0x07: - vdp.bd = (d & 0x0F); + vdp->bd = (d & 0x0F); break; } } @@ -284,68 +284,68 @@ void vdp_write(int offset, uint8 data) { int index; - if (((z80_get_elapsed_cycles() + 1) / CYCLES_PER_LINE) > vdp.line) + if (((z80_get_elapsed_cycles() + 1) / CYCLES_PER_LINE) > vdp->line) { /* render next line now BEFORE updating register */ - render_line((vdp.line+1)%vdp.lpf); + render_line((vdp->line+1)%vdp->lpf); } switch(offset & 1) { case 0: /* Data port */ - vdp.pending = 0; + vdp->pending = 0; - switch(vdp.code) + switch(vdp->code) { case 0: /* VRAM write */ case 1: /* VRAM write */ case 2: /* VRAM write */ - index = (vdp.addr & 0x3FFF); - if(data != vdp.vram[index]) + index = (vdp->addr & 0x3FFF); + if(data != vdp->vram[index]) { - vdp.vram[index] = data; - MARK_BG_DIRTY(vdp.addr); + vdp->vram[index] = data; + MARK_BG_DIRTY(vdp->addr); } - vdp.buffer = data; + vdp->buffer = data; break; case 3: /* CRAM write */ - index = (vdp.addr & 0x1F); - if(data != vdp.cram[index]) + index = (vdp->addr & 0x1F); + if(data != vdp->cram[index]) { - vdp.cram[index] = data; + vdp->cram[index] = data; palette_sync(index); } - vdp.buffer = data; + vdp->buffer = data; break; } - vdp.addr = (vdp.addr + 1) & 0x3FFF; + vdp->addr = (vdp->addr + 1) & 0x3FFF; return; case 1: /* Control port */ - if(vdp.pending == 0) + if(vdp->pending == 0) { - vdp.addr = (vdp.addr & 0x3F00) | (data & 0xFF); - vdp.latch = data; - vdp.pending = 1; + vdp->addr = (vdp->addr & 0x3F00) | (data & 0xFF); + vdp->latch = data; + vdp->pending = 1; } else { - vdp.pending = 0; - vdp.code = (data >> 6) & 3; - vdp.addr = (data << 8 | vdp.latch) & 0x3FFF; + vdp->pending = 0; + vdp->code = (data >> 6) & 3; + vdp->addr = (data << 8 | vdp->latch) & 0x3FFF; - if(vdp.code == 0) + if(vdp->code == 0) { - vdp.buffer = vdp.vram[vdp.addr & 0x3FFF]; - vdp.addr = (vdp.addr + 1) & 0x3FFF; + vdp->buffer = vdp->vram[vdp->addr & 0x3FFF]; + vdp->addr = (vdp->addr + 1) & 0x3FFF; } - if(vdp.code == 2) + if(vdp->code == 2) { int r = (data & 0x0F); - int d = vdp.latch; + int d = vdp->latch; vdp_reg_w(r, d); } } @@ -360,41 +360,41 @@ uint8 vdp_read(int offset) switch(offset & 1) { case 0: /* CPU <-> VDP data buffer */ - vdp.pending = 0; - temp = vdp.buffer; - vdp.buffer = vdp.vram[vdp.addr & 0x3FFF]; - vdp.addr = (vdp.addr + 1) & 0x3FFF; + vdp->pending = 0; + temp = vdp->buffer; + vdp->buffer = vdp->vram[vdp->addr & 0x3FFF]; + vdp->addr = (vdp->addr + 1) & 0x3FFF; return temp; case 1: /* Status flags */ { /* cycle-accurate SPR_OVR and INT flags */ int cyc = z80_get_elapsed_cycles(); - int line = vdp.line; + int line = vdp->line; if ((cyc / CYCLES_PER_LINE) > line) { - if (line == vdp.height) vdp.status |= 0x80; - line = (line + 1)%vdp.lpf; + if (line == vdp->height) vdp->status |= 0x80; + line = (line + 1)%vdp->lpf; render_line(line); } /* low 5 bits return non-zero data (fixes PGA Tour Golf course map introduction) */ - temp = vdp.status | 0x1f; + temp = vdp->status | 0x1f; /* clear flags */ - vdp.status = 0; - vdp.pending = 0; - vdp.vint_pending = 0; - vdp.hint_pending = 0; - z80_set_irq_line(vdp.irq, CLEAR_LINE); + vdp->status = 0; + vdp->pending = 0; + vdp->vint_pending = 0; + vdp->hint_pending = 0; + z80_set_irq_line(vdp->irq, CLEAR_LINE); /* cycle-accurate SPR_COL flag */ if (temp & 0x20) { uint8 hc = hc_256[(cyc + 1) % CYCLES_PER_LINE]; - if ((line == (vdp.spr_col >> 8)) && ((hc < (vdp.spr_col & 0xff)) || (hc > 0xf3))) + if ((line == (vdp->spr_col >> 8)) && ((hc < (vdp->spr_col & 0xff)) || (hc > 0xf3))) { - vdp.status |= 0x20; + vdp->status |= 0x20; temp &= ~0x20; } } @@ -412,10 +412,10 @@ uint8 vdp_counter_r(int offset) switch(offset & 1) { case 0: /* V Counter */ - return vc_table[sms.display][vdp.extended][z80_get_elapsed_cycles() / CYCLES_PER_LINE]; + return vc_table[sms->display][vdp->extended][z80_get_elapsed_cycles() / CYCLES_PER_LINE]; case 1: /* H Counter -- return previously latched values or ZERO */ - return sms.hlatch; + return sms->hlatch; } /* Just to please the compiler */ @@ -431,71 +431,71 @@ void gg_vdp_write(int offset, uint8 data) { int index; - if (((z80_get_elapsed_cycles() + 1) / CYCLES_PER_LINE) > vdp.line) + if (((z80_get_elapsed_cycles() + 1) / CYCLES_PER_LINE) > vdp->line) { /* render next line now BEFORE updating register */ - render_line((vdp.line+1)%vdp.lpf); + render_line((vdp->line+1)%vdp->lpf); } switch(offset & 1) { case 0: /* Data port */ - vdp.pending = 0; - switch(vdp.code) + vdp->pending = 0; + switch(vdp->code) { case 0: /* VRAM write */ case 1: /* VRAM write */ case 2: /* VRAM write */ - index = (vdp.addr & 0x3FFF); - if(data != vdp.vram[index]) + index = (vdp->addr & 0x3FFF); + if(data != vdp->vram[index]) { - vdp.vram[index] = data; - MARK_BG_DIRTY(vdp.addr); + vdp->vram[index] = data; + MARK_BG_DIRTY(vdp->addr); } - vdp.buffer = data; + vdp->buffer = data; break; case 3: /* CRAM write */ - if(vdp.addr & 1) + if(vdp->addr & 1) { - vdp.cram_latch = (vdp.cram_latch & 0x00FF) | ((data & 0xFF) << 8); - vdp.cram[(vdp.addr & 0x3E) | (0)] = (vdp.cram_latch >> 0) & 0xFF; - vdp.cram[(vdp.addr & 0x3E) | (1)] = (vdp.cram_latch >> 8) & 0xFF; - palette_sync((vdp.addr >> 1) & 0x1F); + vdp->cram_latch = (vdp->cram_latch & 0x00FF) | ((data & 0xFF) << 8); + vdp->cram[(vdp->addr & 0x3E) | (0)] = (vdp->cram_latch >> 0) & 0xFF; + vdp->cram[(vdp->addr & 0x3E) | (1)] = (vdp->cram_latch >> 8) & 0xFF; + palette_sync((vdp->addr >> 1) & 0x1F); } else { - vdp.cram_latch = (vdp.cram_latch & 0xFF00) | ((data & 0xFF) << 0); + vdp->cram_latch = (vdp->cram_latch & 0xFF00) | ((data & 0xFF) << 0); } - vdp.buffer = data; + vdp->buffer = data; break; } - vdp.addr = (vdp.addr + 1) & 0x3FFF; + vdp->addr = (vdp->addr + 1) & 0x3FFF; return; case 1: /* Control port */ - if(vdp.pending == 0) + if(vdp->pending == 0) { - vdp.addr = (vdp.addr & 0x3F00) | (data & 0xFF); - vdp.latch = data; - vdp.pending = 1; + vdp->addr = (vdp->addr & 0x3F00) | (data & 0xFF); + vdp->latch = data; + vdp->pending = 1; } else { - vdp.pending = 0; - vdp.code = (data >> 6) & 3; - vdp.addr = (data << 8 | vdp.latch) & 0x3FFF; + vdp->pending = 0; + vdp->code = (data >> 6) & 3; + vdp->addr = (data << 8 | vdp->latch) & 0x3FFF; - if(vdp.code == 0) + if(vdp->code == 0) { - vdp.buffer = vdp.vram[vdp.addr & 0x3FFF]; - vdp.addr = (vdp.addr + 1) & 0x3FFF; + vdp->buffer = vdp->vram[vdp->addr & 0x3FFF]; + vdp->addr = (vdp->addr + 1) & 0x3FFF; } - if(vdp.code == 2) + if(vdp->code == 2) { int r = (data & 0x0F); - int d = vdp.latch; + int d = vdp->latch; vdp_reg_w(r, d); } } @@ -515,55 +515,55 @@ void md_vdp_write(int offset, uint8 data) { case 0: /* Data port */ - vdp.pending = 0; + vdp->pending = 0; - switch(vdp.code) + switch(vdp->code) { case 0: /* VRAM write */ case 1: /* VRAM write */ - index = (vdp.addr & 0x3FFF); - if(data != vdp.vram[index]) + index = (vdp->addr & 0x3FFF); + if(data != vdp->vram[index]) { - vdp.vram[index] = data; - MARK_BG_DIRTY(vdp.addr); + vdp->vram[index] = data; + MARK_BG_DIRTY(vdp->addr); } break; case 2: /* CRAM write */ case 3: /* CRAM write */ - index = (vdp.addr & 0x1F); - if(data != vdp.cram[index]) + index = (vdp->addr & 0x1F); + if(data != vdp->cram[index]) { - vdp.cram[index] = data; + vdp->cram[index] = data; palette_sync(index); } break; } - vdp.addr = (vdp.addr + 1) & 0x3FFF; + vdp->addr = (vdp->addr + 1) & 0x3FFF; return; case 1: /* Control port */ - if(vdp.pending == 0) + if(vdp->pending == 0) { - vdp.latch = data; - vdp.pending = 1; + vdp->latch = data; + vdp->pending = 1; } else { - vdp.pending = 0; - vdp.code = (data >> 6) & 3; - vdp.addr = (data << 8 | vdp.latch) & 0x3FFF; + vdp->pending = 0; + vdp->code = (data >> 6) & 3; + vdp->addr = (data << 8 | vdp->latch) & 0x3FFF; - if(vdp.code == 0) + if(vdp->code == 0) { - vdp.buffer = vdp.vram[vdp.addr & 0x3FFF]; - vdp.addr = (vdp.addr + 1) & 0x3FFF; + vdp->buffer = vdp->vram[vdp->addr & 0x3FFF]; + vdp->addr = (vdp->addr + 1) & 0x3FFF; } - if(vdp.code == 2) + if(vdp->code == 2) { int r = (data & 0x0F); - int d = vdp.latch; + int d = vdp->latch; vdp_reg_w(r, d); } } @@ -583,47 +583,47 @@ void tms_write(int offset, int data) { case 0: /* Data port */ - vdp.pending = 0; + vdp->pending = 0; - switch(vdp.code) + switch(vdp->code) { case 0: /* VRAM write */ case 1: /* VRAM write */ case 2: /* VRAM write */ case 3: /* VRAM write */ - index = (vdp.addr & 0x3FFF); - if(data != vdp.vram[index]) + index = (vdp->addr & 0x3FFF); + if(data != vdp->vram[index]) { - vdp.vram[index] = data; - MARK_BG_DIRTY(vdp.addr); + vdp->vram[index] = data; + MARK_BG_DIRTY(vdp->addr); } break; } - vdp.addr = (vdp.addr + 1) & 0x3FFF; + vdp->addr = (vdp->addr + 1) & 0x3FFF; return; case 1: /* Control port */ - if(vdp.pending == 0) + if(vdp->pending == 0) { - vdp.latch = data; - vdp.pending = 1; + vdp->latch = data; + vdp->pending = 1; } else { - vdp.pending = 0; - vdp.code = (data >> 6) & 3; - vdp.addr = (data << 8 | vdp.latch) & 0x3FFF; + vdp->pending = 0; + vdp->code = (data >> 6) & 3; + vdp->addr = (data << 8 | vdp->latch) & 0x3FFF; - if(vdp.code == 0) + if(vdp->code == 0) { - vdp.buffer = vdp.vram[vdp.addr & 0x3FFF]; - vdp.addr = (vdp.addr + 1) & 0x3FFF; + vdp->buffer = vdp->vram[vdp->addr & 0x3FFF]; + vdp->addr = (vdp->addr + 1) & 0x3FFF; } - if(vdp.code == 2) + if(vdp->code == 2) { int r = (data & 0x07); - int d = vdp.latch; + int d = vdp->latch; vdp_reg_w(r, d); } } diff --git a/components/sms/smsplus/vdp.h b/components/sms/smsplus/vdp.h index cb6689ef..e551db32 100644 --- a/components/sms/smsplus/vdp.h +++ b/components/sms/smsplus/vdp.h @@ -83,8 +83,8 @@ typedef struct } __attribute__((packed, aligned(1))) vdp_t; /* Global data */ -extern vdp_t vdp; -extern uint8 hc_256[228]; +extern vdp_t *vdp; +extern const uint8 hc_256[228]; /* Function prototypes */ extern void vdp_init(void); diff --git a/components/sms/src/sms.cpp b/components/sms/src/sms.cpp index a6de8894..320d110f 100644 --- a/components/sms/src/sms.cpp +++ b/components/sms/src/sms.cpp @@ -17,6 +17,11 @@ static constexpr size_t GG_VISIBLE_HEIGHT = 144; static uint16_t palette[PALETTE_SIZE]; +static constexpr size_t SRAM_SIZE = 0x8000; +static constexpr size_t RAM_SIZE = 0x2000; +static constexpr size_t VRAM_SIZE = 0x4000; +static constexpr size_t AUDIO_SIZE = 0x10000; + static uint8_t *sms_sram = nullptr; static uint8_t *sms_ram = nullptr; static uint8_t *sms_vdp_vram = nullptr; @@ -47,24 +52,37 @@ void reset_sms() { muteFrameCount = 0; } -static void init(uint8_t *romdata, size_t rom_data_size) { - static bool initialized = false; - if (!initialized) { - sms_sram = (uint8_t*)heap_caps_malloc(0x8000, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); - sms_ram = (uint8_t*)heap_caps_malloc(0x2000, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); - sms_vdp_vram = (uint8_t*)heap_caps_malloc(0x4000, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); - sms_audio_buffer = (uint32_t*)heap_caps_malloc(0x10000, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); - } +static void init_memory() { + // Use shared memory regions instead of dynamic allocation + sms_sram = (uint8_t*)shared_malloc(SRAM_SIZE); + sms_ram = (uint8_t*)shared_malloc(RAM_SIZE); + sms_vdp_vram = (uint8_t*)shared_malloc(VRAM_SIZE); + sms_audio_buffer = (uint32_t*)shared_malloc(AUDIO_SIZE); + Z80 = (Z80_Regs*)shared_malloc(sizeof(Z80_Regs)); + io_lut = (io_state (*)[256])shared_malloc(sizeof(io_state[2][256])); + sms = (sms_t*)shared_malloc(sizeof(sms_t)); + bios = (bios_t*)shared_malloc(sizeof(bios_t)); + slot = (slot_t*)shared_malloc(sizeof(slot_t)); + coleco = (t_coleco*)shared_malloc(sizeof(t_coleco)); + dummy_write = (uint8_t*)shared_malloc(0x400); + dummy_read = (uint8_t*)shared_malloc(0x400); + vdp = (vdp_t*)shared_malloc(sizeof(vdp_t)); + internal_buffer = (uint8_t*)shared_malloc(0x200); + object_info = (struct obj_info_t*)shared_malloc(sizeof(struct obj_info_t) * 64); + sms_snd = (sms_snd_t*)shared_malloc(sizeof(sms_snd_t)); + SN76489 = (SN76489_Context*)shared_malloc(sizeof(SN76489_Context) * MAX_SN76489); +} +static void init(uint8_t *romdata, size_t rom_data_size) { bitmap.width = SMS_SCREEN_WIDTH; bitmap.height = SMS_VISIBLE_HEIGHT; bitmap.pitch = bitmap.width; bitmap.data = BoxEmu::get().frame_buffer0(); cart.sram = sms_sram; - sms.wram = sms_ram; - sms.use_fm = 0; - vdp.vram = sms_vdp_vram; + sms->wram = sms_ram; + sms->use_fm = 0; + vdp->vram = sms_vdp_vram; set_option_defaults(); @@ -81,17 +99,17 @@ static void init(uint8_t *romdata, size_t rom_data_size) { // reset unlock unlock = false; - initialized = true; reset_frame_time(); } void init_sms(uint8_t *romdata, size_t rom_data_size) { is_gg = false; BoxEmu::get().native_size(SMS_SCREEN_WIDTH, SMS_VISIBLE_HEIGHT, SMS_SCREEN_WIDTH); + init_memory(); load_rom_data(romdata, rom_data_size); - sms.console = CONSOLE_SMS; - sms.display = DISPLAY_NTSC; - sms.territory = TERRITORY_DOMESTIC; + sms->console = CONSOLE_SMS; + sms->display = DISPLAY_NTSC; + sms->territory = TERRITORY_DOMESTIC; frame_buffer_offset = 0; frame_buffer_size = SMS_SCREEN_WIDTH * SMS_VISIBLE_HEIGHT; init(romdata, rom_data_size); @@ -101,10 +119,11 @@ void init_sms(uint8_t *romdata, size_t rom_data_size) { void init_gg(uint8_t *romdata, size_t rom_data_size) { is_gg = true; BoxEmu::get().native_size(GG_SCREEN_WIDTH, GG_VISIBLE_HEIGHT, SMS_SCREEN_WIDTH); + init_memory(); load_rom_data(romdata, rom_data_size); - sms.console = CONSOLE_GG; - sms.display = DISPLAY_NTSC; - sms.territory = TERRITORY_DOMESTIC; + sms->console = CONSOLE_GG; + sms->display = DISPLAY_NTSC; + sms->territory = TERRITORY_DOMESTIC; frame_buffer_offset = 48; // from odroid_display.cpp lines 1055 frame_buffer_size = GG_SCREEN_WIDTH * GG_VISIBLE_HEIGHT; init(romdata, rom_data_size); @@ -162,7 +181,7 @@ void run_sms_rom() { ++frame_counter; // Process audio - for (int x = 0; x < sms_snd.sample_count; x++) { + for (int x = 0; x < sms_snd->sample_count; x++) { uint32_t sample; if (muteFrameCount < 60 * 2) { @@ -171,12 +190,12 @@ void run_sms_rom() { sample = 0; ++muteFrameCount; } else { - sample = (sms_snd.output[0][x] << 16) + sms_snd.output[1][x]; + sample = (sms_snd->output[0][x] << 16) + sms_snd->output[1][x]; } sms_audio_buffer[x] = sample; } - auto sms_audio_buffer_len = sms_snd.sample_count - 1; + auto sms_audio_buffer_len = sms_snd->sample_count - 1; // push the audio buffer to the audio task BoxEmu::get().play_audio((uint8_t*)sms_audio_buffer, sms_audio_buffer_len * 2 * 2); // 2 channels, 2 bytes per sample @@ -234,5 +253,5 @@ std::vector get_sms_video_buffer() { } void deinit_sms() { - // TODO: + shared_mem_clear(); } diff --git a/main/cart.hpp b/main/cart.hpp index 28a6a7fd..135c08b3 100644 --- a/main/cart.hpp +++ b/main/cart.hpp @@ -20,7 +20,7 @@ /// - romdata class Cart { public: - using Pixel = lv_color16_t; + using Pixel = BoxEmu::Pixel; /// Configuration for the Cart class struct Config { RomInfo info; ///< rom info @@ -37,7 +37,7 @@ class Cart { logger_({.tag = "Cart", .level = config.verbosity}) { logger_.info("ctor"); // clear the screen - espp::St7789::clear(0,0,320,240); + BoxEmu::get().clear_screen(); // copy the romdata rom_size_bytes_ = BoxEmu::get().copy_file_to_romdata(get_rom_filename()); romdata_ = BoxEmu::get().romdata(); @@ -177,7 +177,7 @@ class Cart { std::this_thread::sleep_for(100ms); } // make sure to clear the screen before we resume the game - espp::St7789::clear(0,0,320,240); + BoxEmu::get().clear_screen(); // only run the post_menu if we are still running if (running_) post_menu(); @@ -186,8 +186,8 @@ class Cart { } protected: - static constexpr size_t SCREEN_WIDTH = 320; - static constexpr size_t SCREEN_HEIGHT = 240; + static constexpr size_t SCREEN_WIDTH = BoxEmu::lcd_width(); + static constexpr size_t SCREEN_HEIGHT = BoxEmu::lcd_height(); static constexpr std::string FS_PREFIX = BoxEmu::mount_point; static constexpr std::string SAVE_DIR = "/saves/"; diff --git a/main/main.cpp b/main/main.cpp index e60b660e..963d3c9e 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -119,9 +119,6 @@ extern "C" void app_main(void) { logger.debug("Task table:\n{}", espp::TaskMonitor::get_latest_info_table()); - // need to reset to control the whole screen - espp::St7789::clear(0,0,320,240); - gui.resume(); display->force_refresh(); }