From 36acf905738ae4bd6b216681e46b60d0d4a03486 Mon Sep 17 00:00:00 2001 From: William Emfinger Date: Sun, 6 Apr 2025 16:29:30 -0500 Subject: [PATCH] feat: Update nes/gbc/sms/genesis emulators to use shared memory * Add `shared_memory` component for sharing memory between the emulators more easily * Refactored all emulators to use new shared memory for majority of state and data. This means each emulator component now has less than 5k of D/IRAM in use that is not from shared memory. * Update to have better clear screen function that wont have any race conditions and wont destroy buffers. Update video task to have simple clear screen function if passed nullptr. * Update cmake lists to use newer version of cmake * Update to hid roms from rom list if their emulator is not enabled for easier / faster iteration and testing when adding / modifying emulators * Update espp to latest Shared memory means that it is not easier to add more emulators (such as msx and doom) since the emulators no longer fill up the internal ram. This does require in some cases modifying the emulators to leverage the shared memory, but this is a one-time operation and actually helps ensure the emulator maintains high performance by keeping its state within internal memory as much as possible, instead of in offboard PSRAM. Build and run `main` on box-3 and ensure all emulators work for multiple sessions of different roms in sequence. Also ensure that saving state and loading state works for each emulator. --- CMakeLists.txt | 2 +- components/box-emu/include/box-emu.hpp | 1 + components/box-emu/src/box-emu.cpp | 27 +- components/espp | 2 +- components/gbc/CMakeLists.txt | 2 +- components/gbc/gnuboy/include/gnuboy/cpu.h | 2 +- .../gbc/gnuboy/include/gnuboy/cpuregs.h | 54 +- components/gbc/gnuboy/include/gnuboy/lcd.h | 4 +- components/gbc/gnuboy/include/gnuboy/loader.h | 2 +- components/gbc/gnuboy/src/cpu.c | 62 +- components/gbc/gnuboy/src/emu.c | 2 +- components/gbc/gnuboy/src/hw.c | 6 +- components/gbc/gnuboy/src/lcd.c | 48 +- components/gbc/gnuboy/src/lcdc.c | 6 +- components/gbc/gnuboy/src/save.c | 291 +++++++--- components/gbc/gnuboy/src/sound.c | 4 +- components/gbc/include/gbc_shared_memory.hpp | 21 + components/gbc/src/gameboy.cpp | 44 +- components/gbc/src/gbc_shared_memory.cpp | 107 ++++ components/genesis/CMakeLists.txt | 29 +- .../genesis/gwenesis/src/cpus/M68K/m68k.h | 2 +- .../genesis/gwenesis/src/cpus/M68K/m68kcpu.c | 106 ++-- .../genesis/gwenesis/src/cpus/M68K/m68kcpu.h | 112 ++-- .../genesis/gwenesis/src/cpus/M68K/m68kops.h | 32 +- .../genesis/gwenesis/src/sound/ym2612.c | 493 ++++++---------- .../genesis/gwenesis/src/sound/ym2612.h | 143 +++++ .../genesis/gwenesis/src/vdp/gwenesis_vdp.h | 5 + .../gwenesis/src/vdp/gwenesis_vdp_gfx.c | 23 +- .../gwenesis/src/vdp/gwenesis_vdp_mem.c | 53 +- components/genesis/include/genesis.hpp | 28 +- .../genesis/include/genesis_shared_memory.hpp | 26 + .../genesis/include/z80_shared_memory.hpp | 18 + components/genesis/src/genesis.cpp | 28 +- .../genesis/src/genesis_shared_memory.cpp | 49 ++ components/genesis/src/z80_shared_memory.cpp | 137 +++++ components/nes/CMakeLists.txt | 4 +- components/nes/include/nes_external.h | 17 + components/nes/include/nes_shared_memory.h | 28 + components/nes/nofrendo/bitmap.c | 4 +- components/nes/nofrendo/cpu/nes6502.c | 114 ++-- components/nes/nofrendo/cpu/nes6502.h | 2 + components/nes/nofrendo/event.c | 18 +- components/nes/nofrendo/intro.c | 6 +- components/nes/nofrendo/memguard.c | 361 ------------ components/nes/nofrendo/nes/nes.c | 115 ++-- components/nes/nofrendo/nes/nes.h | 1 + components/nes/nofrendo/nes/nes_mmc.c | 58 +- components/nes/nofrendo/nes/nes_pal.c | 2 +- components/nes/nofrendo/nes/nes_pal.h | 2 +- components/nes/nofrendo/nes/nes_ppu.c | 368 ++++++------ components/nes/nofrendo/sndhrdw/nes_apu.c | 528 +++++++++--------- components/nes/src/nes.cpp | 28 +- components/nes/src/nes_shared_memory.c | 45 ++ components/nes/src/video_audio.cpp | 4 +- components/rom_info/src/rom_info.cpp | 20 + components/shared_memory/CMakeLists.txt | 5 + .../shared_memory/include/shared_memory.h | 47 ++ components/shared_memory/src/shared_memory.c | 77 +++ components/sms/CMakeLists.txt | 2 +- components/sms/include/sms.hpp | 2 + components/sms/smsplus/cpu/z80.c | 222 ++++---- components/sms/smsplus/cpu/z80.h | 2 +- components/sms/smsplus/hvc.c | 14 +- components/sms/smsplus/hvc.h | 14 +- components/sms/smsplus/loadrom.c | 80 +-- components/sms/smsplus/memz80.c | 60 +- components/sms/smsplus/pio.c | 79 ++- components/sms/smsplus/render.c | 133 ++--- components/sms/smsplus/render.h | 12 +- components/sms/smsplus/shared.h | 9 + components/sms/smsplus/sms.c | 158 +++--- components/sms/smsplus/sms.h | 20 +- components/sms/smsplus/sound/sn76489.c | 2 +- components/sms/smsplus/sound/sn76489.h | 1 + components/sms/smsplus/sound/sound.c | 120 ++-- components/sms/smsplus/sound/sound.h | 2 +- components/sms/smsplus/state.c | 95 ++-- components/sms/smsplus/system.c | 44 +- components/sms/smsplus/tms.c | 84 +-- components/sms/smsplus/vdp.c | 348 ++++++------ components/sms/smsplus/vdp.h | 4 +- components/sms/src/sms.cpp | 63 ++- main/cart.hpp | 10 +- main/main.cpp | 3 - 84 files changed, 2945 insertions(+), 2463 deletions(-) create mode 100644 components/gbc/include/gbc_shared_memory.hpp create mode 100644 components/gbc/src/gbc_shared_memory.cpp create mode 100644 components/genesis/include/genesis_shared_memory.hpp create mode 100644 components/genesis/include/z80_shared_memory.hpp create mode 100644 components/genesis/src/genesis_shared_memory.cpp create mode 100644 components/genesis/src/z80_shared_memory.cpp create mode 100644 components/nes/include/nes_external.h create mode 100644 components/nes/include/nes_shared_memory.h create mode 100644 components/nes/src/nes_shared_memory.c create mode 100644 components/shared_memory/CMakeLists.txt create mode 100644 components/shared_memory/include/shared_memory.h create mode 100644 components/shared_memory/src/shared_memory.c 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(); }