From 4539c12f8e97ededaa540acff1d63d753deff804 Mon Sep 17 00:00:00 2001 From: Ignacio Sanchez Gines <863613+drhelius@users.noreply.github.com> Date: Tue, 25 Jun 2024 21:17:33 +0200 Subject: [PATCH] Basic structure --- platforms/shared/desktop/Makefile.sources | 12 +- platforms/shared/desktop/config.cpp | 2 - platforms/shared/desktop/config.h | 1 - platforms/shared/desktop/emu.cpp | 21 + platforms/shared/desktop/emu.h | 77 + platforms/shared/desktop/gui_menus.cpp | 17 - src/audio.cpp | 64 + src/audio.h | 44 + src/cartridge.cpp | 18 + src/cartridge.h | 48 + src/geargrafx.h | 8 + src/geargrafx_core.cpp | 508 ++++++- src/geargrafx_core.h | 56 + src/huc6270.cpp | 18 + src/huc6270.h | 26 + src/huc6280.cpp | 135 ++ src/huc6280.h | 192 +++ src/huc6280_functors.cpp | 295 ++++ src/huc6280_inline.h | 196 +++ src/huc6280_names.h | 296 ++++ src/huc6280_opcodes.cpp | 1667 +++++++++++++++++++++ src/huc6280_opcodes_inline.h | 304 ++++ src/huc6280_psg.cpp | 18 + src/huc6280_psg.h | 23 + src/huc6280_registers.h | 117 ++ src/huc6280_timer.cpp | 18 + src/huc6280_timer.h | 23 + src/huc6280_timing.h | 89 ++ src/input.cpp | 50 + src/input.h | 40 + src/memory.cpp | 18 + src/memory.h | 23 + src/types.h | 41 + 33 files changed, 4442 insertions(+), 23 deletions(-) create mode 100644 platforms/shared/desktop/emu.cpp create mode 100644 platforms/shared/desktop/emu.h create mode 100644 src/audio.cpp create mode 100644 src/audio.h create mode 100644 src/cartridge.cpp create mode 100644 src/cartridge.h create mode 100644 src/huc6270.cpp create mode 100644 src/huc6270.h create mode 100644 src/huc6280.cpp create mode 100644 src/huc6280.h create mode 100644 src/huc6280_functors.cpp create mode 100644 src/huc6280_inline.h create mode 100644 src/huc6280_names.h create mode 100644 src/huc6280_opcodes.cpp create mode 100644 src/huc6280_opcodes_inline.h create mode 100644 src/huc6280_psg.cpp create mode 100644 src/huc6280_psg.h create mode 100644 src/huc6280_registers.h create mode 100644 src/huc6280_timer.cpp create mode 100644 src/huc6280_timer.h create mode 100644 src/huc6280_timing.h create mode 100644 src/input.cpp create mode 100644 src/input.h create mode 100644 src/memory.cpp create mode 100644 src/memory.h diff --git a/platforms/shared/desktop/Makefile.sources b/platforms/shared/desktop/Makefile.sources index ce797be..ffd59d9 100644 --- a/platforms/shared/desktop/Makefile.sources +++ b/platforms/shared/desktop/Makefile.sources @@ -23,5 +23,13 @@ SOURCES_CXX := \ $(DESKTOP_SRC_DIR)/imgui/imgui_demo.cpp \ $(DESKTOP_SRC_DIR)/imgui/memory_editor.cpp \ $(SRC_DIR)/geargrafx_core.cpp \ - - + $(SRC_DIR)/audio.cpp \ + $(SRC_DIR)/cartridge.cpp \ + $(SRC_DIR)/huc6270.cpp \ + $(SRC_DIR)/huc6280.cpp \ + $(SRC_DIR)/huc6280_functors.cpp \ + $(SRC_DIR)/huc6280_opcodes.cpp \ + $(SRC_DIR)/huc6280_psg.cpp \ + $(SRC_DIR)/huc6280_timer.cpp \ + $(SRC_DIR)/input.cpp \ + $(SRC_DIR)/memory.cpp \ diff --git a/platforms/shared/desktop/config.cpp b/platforms/shared/desktop/config.cpp index 596af40..89c4810 100644 --- a/platforms/shared/desktop/config.cpp +++ b/platforms/shared/desktop/config.cpp @@ -117,7 +117,6 @@ void config_read(void) config_emulator.ffwd_speed = read_int("Emulator", "FFWD", 1); config_emulator.save_slot = read_int("Emulator", "SaveSlot", 0); config_emulator.start_paused = read_bool("Emulator", "StartPaused", false); - config_emulator.region = read_int("Emulator", "Region", 0); config_emulator.savefiles_dir_option = read_int("Emulator", "SaveFilesDirOption", 0); config_emulator.savefiles_path = read_string("Emulator", "SaveFilesPath"); config_emulator.savestates_dir_option = read_int("Emulator", "SaveStatesDirOption", 0); @@ -219,7 +218,6 @@ void config_write(void) write_int("Emulator", "FFWD", config_emulator.ffwd_speed); write_int("Emulator", "SaveSlot", config_emulator.save_slot); write_bool("Emulator", "StartPaused", config_emulator.start_paused); - write_int("Emulator", "Region", config_emulator.region); write_int("Emulator", "SaveFilesDirOption", config_emulator.savefiles_dir_option); write_string("Emulator", "SaveFilesPath", config_emulator.savefiles_path); write_int("Emulator", "SaveStatesDirOption", config_emulator.savestates_dir_option); diff --git a/platforms/shared/desktop/config.h b/platforms/shared/desktop/config.h index 1152823..90eb1bd 100644 --- a/platforms/shared/desktop/config.h +++ b/platforms/shared/desktop/config.h @@ -43,7 +43,6 @@ struct config_Emulator bool start_paused = false; bool ffwd = false; int ffwd_speed = 1; - int region = 0; bool show_info = false; std::string recent_roms[config_max_recent_roms]; int savefiles_dir_option = 0; diff --git a/platforms/shared/desktop/emu.cpp b/platforms/shared/desktop/emu.cpp new file mode 100644 index 0000000..c9eb6a6 --- /dev/null +++ b/platforms/shared/desktop/emu.cpp @@ -0,0 +1,21 @@ +/* + * Geargrafx - PC Engine / TurboGrafx Emulator + * Copyright (C) 2024 Ignacio Sanchez + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/ + * + */ + +#define GUI_EMU_IMPORT +#include "emu.h" \ No newline at end of file diff --git a/platforms/shared/desktop/emu.h b/platforms/shared/desktop/emu.h new file mode 100644 index 0000000..cfddc81 --- /dev/null +++ b/platforms/shared/desktop/emu.h @@ -0,0 +1,77 @@ +/* + * Geargrafx - PC Engine / TurboGrafx Emulator + * Copyright (C) 2024 Ignacio Sanchez + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/ + * + */ + +#ifndef EMU_H +#define EMU_H + +#include "../../../src/geargrafx.h" + +#ifdef EMU_IMPORT + #define EXTERN +#else + #define EXTERN extern +#endif + +EXTERN u8* emu_frame_buffer; +// EXTERN u8* emu_debug_background_buffer; +// EXTERN u8* emu_debug_tile_buffer; +// EXTERN u8* emu_debug_sprite_buffers[64]; + +EXTERN bool emu_audio_sync; +// EXTERN bool emu_debug_disable_breakpoints_cpu; +// EXTERN bool emu_debug_disable_breakpoints_mem; +// EXTERN int emu_debug_tile_palette; +EXTERN bool emu_savefiles_dir_option; +EXTERN bool emu_savestates_dir_option; +EXTERN char emu_savefiles_path[4096]; +EXTERN char emu_savestates_path[4096]; + +EXTERN void emu_init(void); +EXTERN void emu_destroy(void); +EXTERN void emu_update(void); +EXTERN void emu_load_rom(const char* file_path, Cartridge::ForceConfiguration config); +EXTERN void emu_key_pressed(GC_Controllers controller, GC_Keys key); +EXTERN void emu_key_released(GC_Controllers controller, GC_Keys key); +EXTERN void emu_pause(void); +EXTERN void emu_resume(void); +EXTERN bool emu_is_paused(void); +EXTERN bool emu_is_empty(void); +EXTERN void emu_reset(Cartridge::ForceConfiguration config); +EXTERN void emu_audio_mute(bool mute); +EXTERN void emu_audio_reset(void); +EXTERN bool emu_is_audio_enabled(void); +EXTERN void emu_save_ram(const char* file_path); +EXTERN void emu_load_ram(const char* file_path, Cartridge::ForceConfiguration config); +EXTERN void emu_save_state_slot(int index); +EXTERN void emu_load_state_slot(int index); +EXTERN void emu_save_state_file(const char* file_path); +EXTERN void emu_load_state_file(const char* file_path); +EXTERN void emu_get_runtime(GC_RuntimeInfo& runtime); +EXTERN void emu_get_info(char* info); +EXTERN GearcolecoCore* emu_get_core(void); +// EXTERN void emu_debug_step(void); +// EXTERN void emu_debug_continue(void); +// EXTERN void emu_debug_next_frame(void); +EXTERN void emu_video_no_sprite_limit(bool enabled); +EXTERN void emu_set_overscan(int overscan); +EXTERN void emu_save_screenshot(const char* file_path); + +#undef EMU_IMPORT +#undef EXTERN +#endif /* EMU_H */ \ No newline at end of file diff --git a/platforms/shared/desktop/gui_menus.cpp b/platforms/shared/desktop/gui_menus.cpp index d6bcaf1..91e6378 100644 --- a/platforms/shared/desktop/gui_menus.cpp +++ b/platforms/shared/desktop/gui_menus.cpp @@ -213,23 +213,6 @@ static void menu_emulator(void) { gui_in_use = true; - if (ImGui::BeginMenu("Refresh Rate")) - { - ImGui::PushItemWidth(130.0f); - if (ImGui::Combo("##emu_rate", &config_emulator.region, "Auto\0NTSC (60 Hz)\0PAL (50 Hz)\0\0")) - { - if (config_emulator.region > 0) - { - config_emulator.ffwd = false; - config_audio.sync = true; - } - } - ImGui::PopItemWidth(); - ImGui::EndMenu(); - } - - ImGui::Separator(); - ImGui::MenuItem("Start Paused", "", &config_emulator.start_paused); ImGui::Separator(); diff --git a/src/audio.cpp b/src/audio.cpp new file mode 100644 index 0000000..65a716b --- /dev/null +++ b/src/audio.cpp @@ -0,0 +1,64 @@ +/* + * Geargrafx - PC Engine / TurboGrafx Emulator + * Copyright (C) 2024 Ignacio Sanchez + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/ + * + */ + +#include +#include +#include "audio.h" + +Audio::Audio() +{ + m_elapsed_cycles = 0; + m_sample_rate = 44100; + m_mute = false; +} + +Audio::~Audio() +{ +} + +void Audio::Init() +{ + +} + +void Audio::Reset() +{ + m_elapsed_cycles = 0; +} + +void Audio::Mute(bool mute) +{ + m_mute = mute; +} + +void Audio::EndFrame(s16* sample_buffer, int* sample_count) +{ + *sample_count = 0; + m_elapsed_cycles = 0; +} + +// void Audio::SaveState(std::ostream& stream) +// { +// stream.write(reinterpret_cast (&m_elapsed_cycles), sizeof(m_ElapsedCycles)); +// } + +// void Audio::LoadState(std::istream& stream) +// { +// stream.read(reinterpret_cast (&m_elapsed_cycles), sizeof(m_ElapsedCycles)); +// } \ No newline at end of file diff --git a/src/audio.h b/src/audio.h new file mode 100644 index 0000000..1971922 --- /dev/null +++ b/src/audio.h @@ -0,0 +1,44 @@ +/* + * Geargrafx - PC Engine / TurboGrafx Emulator + * Copyright (C) 2024 Ignacio Sanchez + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/ + * + */ + +#include "types.h" + +class Audio +{ +public: + Audio(); + ~Audio(); + void Init(); + void Reset(); + void Mute(bool mute); + void Tick(unsigned int clock_cycles); + void EndFrame(s16* sample_buffer, int* sample_count); + // void SaveState(std::ostream& stream); + // void LoadState(std::istream& stream); + +private: + u64 m_elapsed_cycles; + int m_sample_rate; + bool m_mute; +}; + +inline void Audio::Tick(unsigned int clock_cycles) +{ + m_elapsed_cycles += clock_cycles; +} diff --git a/src/cartridge.cpp b/src/cartridge.cpp new file mode 100644 index 0000000..11b4d5b --- /dev/null +++ b/src/cartridge.cpp @@ -0,0 +1,18 @@ +/* + * Geargrafx - PC Engine / TurboGrafx Emulator + * Copyright (C) 2024 Ignacio Sanchez + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/ + * + */ diff --git a/src/cartridge.h b/src/cartridge.h new file mode 100644 index 0000000..26814c0 --- /dev/null +++ b/src/cartridge.h @@ -0,0 +1,48 @@ +/* + * Geargrafx - PC Engine / TurboGrafx Emulator + * Copyright (C) 2024 Ignacio Sanchez + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/ + * + */ + +class Cartridge +{ +public: + Cartridge(); + ~Cartridge(); + void Init(); + void Reset(); + u32 GetCRC(); + bool IsReady(); + int GetROMSize(); + int GetROMBankCount(); + const char* GetFilePath(); + const char* GetFileName(); + u8* GetROM(); + bool LoadFromFile(const char* path); + bool LoadFromBuffer(const u8* buffer, int size); + +private: + bool LoadFromZipFile(const u8* buffer, int size); + +private: + u8* m_pROM; + int m_iROMSize; + bool m_bReady; + char m_szFilePath[512]; + char m_szFileName[512]; + int m_iROMBankCount; + u32 m_iCRC; +}; \ No newline at end of file diff --git a/src/geargrafx.h b/src/geargrafx.h index 523ae73..3587458 100644 --- a/src/geargrafx.h +++ b/src/geargrafx.h @@ -22,5 +22,13 @@ #include "common.h" #include "geargrafx_core.h" +#include "input.h" +#include "audio.h" +#include "cartridge.h" +#include "memory.h" +#include "huc6270.h" +#include "huc6280.h" +#include "huc6280_psg.h" +#include "huc6280_timer.h" #endif /* GEARGRAFX_H */ \ No newline at end of file diff --git a/src/geargrafx_core.cpp b/src/geargrafx_core.cpp index 4a0b2f7..95dd22d 100644 --- a/src/geargrafx_core.cpp +++ b/src/geargrafx_core.cpp @@ -17,4 +17,510 @@ * */ -#include "geargrafx_core.h" \ No newline at end of file +#include "geargrafx_core.h" +#include "common.h" +#include "cartridge.h" +#include "memory.h" +#include "huc6280.h" +#include "huc6270.h" +#include "audio.h" +#include "input.h" + +GeargrafxCore::GeargrafxCore() +{ + // InitPointer(m_memory); + InitPointer(m_processor); + InitPointer(m_audio); + // InitPointer(m_video); + InitPointer(m_input); + // InitPointer(m_cartridge); + m_paused = true; + m_pixel_format = GG_PIXEL_RGB888; +} + +GeargrafxCore::~GeargrafxCore() +{ + // SafeDelete(m_cartridge); + SafeDelete(m_input); + // SafeDelete(m_video); + SafeDelete(m_audio); + SafeDelete(m_processor); + // SafeDelete(m_memory); +} + +void GeargrafxCore::Init(GG_Pixel_Format pixel_format) +{ + Debug("--== %s %s by Ignacio Sanchez ==--", GEARGRAFX_TITLE, GEARGRAFX_VERSION); + + m_pixel_format = pixel_format; + + // m_cartridge = new Cartridge(); + // m_memory = new Memory(m_cartridge); + m_processor = new HuC6280(); + m_audio = new Audio(); + // m_video = new Video(m_memory, m_processor); + m_input = new Input(); + + // m_memory->Init(); + m_processor->Init(); + m_audio->Init(); + // m_video->Init(); + m_input->Init(); + // m_cartridge->Init(); +} + +bool GeargrafxCore::RunToVBlank(u8* frame_buffer, s16* sample_buffer, int* sample_count, bool step, bool stopOnBreakpoints) +{ + bool breakpoint = false; + + // if (!m_paused && m_cartridge->IsReady()) + // { + // bool vblank = false; + // int totalClocks = 0; + // while (!vblank) + // { + // unsigned int clockCycles = m_processor->RunFor(1); + // // vblank = m_video->Tick(clockCycles); + // m_audio->Tick(clockCycles); + + // totalClocks += clockCycles; + + // // if ((step || (stopOnBreakpoints && m_processor->BreakpointHit())) && !m_processor->DuringInputOpcode()) + // // { + // // vblank = true; + // // if (m_processor->BreakpointHit()) + // // breakpoint = true; + // // } + + // if (totalClocks > 702240) + // vblank = true; + // } + + // m_audio->EndFrame(sample_buffer, sample_count); + // RenderFrameBuffer(frame_buffer); + // } + + return breakpoint; +} + +bool GeargrafxCore::LoadROM(const char* szFilePath) +{ + // if (m_cartridge->LoadFromFile(szFilePath)) + // { + // Reset(); + + // // m_memory->ResetRomDisassembledMemory(); + // // m_processor->DisassembleNextOpcode(); + + // return true; + // } + // else + // return false; +} + +bool GeargrafxCore::LoadROMFromBuffer(const u8* buffer, int size) +{ + // if (m_cartridge->LoadFromBuffer(buffer, size)) + // { + // Reset(); + + // // m_memory->ResetRomDisassembledMemory(); + // // m_processor->DisassembleNextOpcode(); + + // return true; + // } + // else + // return false; +} + +bool GeargrafxCore::GetRuntimeInfo(GG_Runtime_Info& runtime_info) +{ + runtime_info.screen_width = GG_RESOLUTION_WIDTH; + runtime_info.screen_height = GG_RESOLUTION_HEIGHT; + + // if (m_cartridge->IsReady()) + // { + // // if (m_video->GetOverscan() == Video::OverscanFull284) + // // runtime_info.screen_width = GC_RESOLUTION_WIDTH + GC_RESOLUTION_SMS_OVERSCAN_H_284_L + GC_RESOLUTION_SMS_OVERSCAN_H_284_R; + // // if (m_video->GetOverscan() == Video::OverscanFull320) + // // runtime_info.screen_width = GC_RESOLUTION_WIDTH + GC_RESOLUTION_SMS_OVERSCAN_H_320_L + GC_RESOLUTION_SMS_OVERSCAN_H_320_R; + // // if (m_video->GetOverscan() != Video::OverscanDisabled) + // // runtime_info.screen_height = GC_RESOLUTION_HEIGHT + (2 * (m_cartridge->IsPAL() ? GC_RESOLUTION_OVERSCAN_V_PAL : GC_RESOLUTION_OVERSCAN_V)); + // return true; + // } + + // return false; +} + +// Memory* GeargrafxCore::GetMemory() +// { +// return m_memory; +// } + +// Cartridge* GeargrafxCore::GetCartridge() +// { +// return m_cartridge; +// } + +HuC6280* GeargrafxCore::GetProcessor() +{ + return m_processor; +} + +// Audio* GeargrafxCore::GetAudio() +// { +// return m_audio; +// } + +// Video* GeargrafxCore::GetVideo() +// { +// return m_video; +// } + +void GeargrafxCore::KeyPressed(GG_Controllers controller, GG_Keys key) +{ + m_input->KeyPressed(controller, key); +} + +void GeargrafxCore::KeyReleased(GG_Controllers controller, GG_Keys key) +{ + m_input->KeyReleased(controller, key); +} + +void GeargrafxCore::Pause(bool paused) +{ + if (paused) + { + Log("Geargrafx PAUSED"); + } + else + { + Log("Geargrafx RESUMED"); + } + m_paused = paused; +} + +bool GeargrafxCore::IsPaused() +{ + return m_paused; +} + +void GeargrafxCore::ResetROM(bool preserve_ram) +{ + // if (m_cartridge->IsReady()) + // { + // Log("Geargrafx RESET"); + + // Reset(); + + // m_processor->DisassembleNextOpcode(); + // } +} + +void GeargrafxCore::ResetSound() +{ + // m_audio->Reset(m_cartridge->IsPAL()); +} + +// void GeargrafxCore::SaveRam() +// { +// SaveRam(NULL); +// } + +// void GeargrafxCore::SaveRam(const char*, bool) +// { +// // TODO +// } + +// void GeargrafxCore::LoadRam() +// { +// LoadRam(NULL); +// } + +// void GeargrafxCore::LoadRam(const char*, bool) +// { +// // TODO +// } + +// void GeargrafxCore::SaveState(int index) +// { +// Log("Creating save state %d...", index); + +// SaveState(NULL, index); + +// Log("Save state %d created", index); +// } + +// void GeargrafxCore::SaveState(const char* szPath, int index) +// { +// Log("Creating save state..."); + +// using namespace std; + +// size_t size; +// SaveState(NULL, size); + +// u8* buffer = new u8[size]; +// string path = ""; + +// if (IsValidPointer(szPath)) +// { +// path += szPath; +// path += "/"; +// path += m_cartridge->GetFileName(); +// } +// else +// { +// path = m_cartridge->GetFilePath(); +// } + +// string::size_type i = path.rfind('.', path.length()); + +// if (i != string::npos) { +// path.replace(i + 1, 3, "state"); +// } + +// stringstream sstm; + +// if (index < 0) +// sstm << szPath; +// else +// sstm << path << index; + +// Log("Save state file: %s", sstm.str().c_str()); + +// ofstream file(sstm.str().c_str(), ios::out | ios::binary); + +// SaveState(file, size); + +// SafeDeleteArray(buffer); + +// file.close(); + +// Log("Save state created"); +// } + +// bool GeargrafxCore::SaveState(u8* buffer, size_t& size) +// { +// bool ret = false; + +// if (m_cartridge->IsReady()) +// { +// using namespace std; + +// stringstream stream; + +// if (SaveState(stream, size)) +// ret = true; + +// if (IsValidPointer(buffer)) +// { +// Log("Saving state to buffer [%d bytes]...", size); +// memcpy(buffer, stream.str().c_str(), size); +// ret = true; +// } +// } +// else +// { +// Log("Invalid rom."); +// } + +// return ret; +// } + +// bool GeargrafxCore::SaveState(std::ostream& stream, size_t& size) +// { +// if (m_cartridge->IsReady()) +// { +// Log("Gathering save state data..."); + +// m_memory->SaveState(stream); +// m_processor->SaveState(stream); +// m_audio->SaveState(stream); +// m_video->SaveState(stream); +// m_input->SaveState(stream); + +// size = static_cast(stream.tellp()); +// size += (sizeof(u32) * 2); + +// u32 header_magic = GC_SAVESTATE_MAGIC; +// u32 header_size = static_cast(size); + +// stream.write(reinterpret_cast (&header_magic), sizeof(header_magic)); +// stream.write(reinterpret_cast (&header_size), sizeof(header_size)); + +// Log("Save state size: %d", static_cast(stream.tellp())); + +// return true; +// } + +// Log("Invalid rom."); + +// return false; +// } + +// void GeargrafxCore::LoadState(int index) +// { +// Log("Loading save state %d...", index); + +// LoadState(NULL, index); + +// Log("State %d file loaded", index); +// } + +// void GeargrafxCore::LoadState(const char* szPath, int index) +// { +// Log("Loading save state..."); + +// using namespace std; + +// string sav_path = ""; + +// if (IsValidPointer(szPath)) +// { +// sav_path += szPath; +// sav_path += "/"; +// sav_path += m_cartridge->GetFileName(); +// } +// else +// { +// sav_path = m_cartridge->GetFilePath(); +// } + +// string rom_path = sav_path; + +// string::size_type i = sav_path.rfind('.', sav_path.length()); + +// if (i != string::npos) { +// sav_path.replace(i + 1, 3, "state"); +// } + +// std::stringstream sstm; + +// if (index < 0) +// sstm << szPath; +// else +// sstm << sav_path << index; + +// Log("Opening save file: %s", sstm.str().c_str()); + +// ifstream file; + +// file.open(sstm.str().c_str(), ios::in | ios::binary); + +// if (!file.fail()) +// { +// if (LoadState(file)) +// { +// Log("Save state loaded"); +// } +// } +// else +// { +// Log("Save state file doesn't exist"); +// } + +// file.close(); +// } + +// bool GeargrafxCore::LoadState(const u8* buffer, size_t size) +// { +// if (m_cartridge->IsReady() && (size > 0) && IsValidPointer(buffer)) +// { +// Log("Gathering load state data [%d bytes]...", size); + +// using namespace std; + +// stringstream stream; + +// stream.write(reinterpret_cast (buffer), size); + +// return LoadState(stream); +// } + +// Log("Invalid rom or memory."); + +// return false; +// } + +// bool GeargrafxCore::LoadState(std::istream& stream) +// { +// if (m_cartridge->IsReady()) +// { +// using namespace std; + +// u32 header_magic = 0; +// u32 header_size = 0; + +// stream.seekg(0, ios::end); +// size_t size = static_cast(stream.tellg()); +// stream.seekg(0, ios::beg); + +// Log("Load state stream size: %d", size); + +// stream.seekg(size - (2 * sizeof(u32)), ios::beg); +// stream.read(reinterpret_cast (&header_magic), sizeof(header_magic)); +// stream.read(reinterpret_cast (&header_size), sizeof(header_size)); +// stream.seekg(0, ios::beg); + +// Log("Load state magic: 0x%08x", header_magic); +// Log("Load state size: %d", header_size); + +// if ((header_size == size) && (header_magic == GC_SAVESTATE_MAGIC)) +// { +// Log("Loading state..."); + +// m_memory->LoadState(stream); +// m_processor->LoadState(stream); +// m_audio->LoadState(stream); +// m_video->LoadState(stream); +// m_input->LoadState(stream); + +// return true; +// } +// else +// { +// Log("Invalid save state size or header"); +// } +// } +// else +// { +// Log("Invalid rom"); +// } + +// return false; +// } + +void GeargrafxCore::Reset() +{ + // m_memory->Reset(); + m_processor->Reset(); + // m_audio->Reset(m_cartridge->IsPAL()); + // m_video->Reset(m_cartridge->IsPAL()); + m_input->Reset(); + m_paused = false; +} + +void GeargrafxCore::RenderFrameBuffer(u8* finalFrameBuffer) +{ + // int size = GC_RESOLUTION_WIDTH_WITH_OVERSCAN * GC_RESOLUTION_HEIGHT_WITH_OVERSCAN; + // u16* srcBuffer = (m_memory->IsBiosLoaded() ? m_video->GetFrameBuffer() : kNoBiosImage); + + // switch (m_pixelFormat) + // { + // case GG_PIXEL_RGB555: + // case GG_PIXEL_BGR555: + // case GG_PIXEL_RGB565: + // case GG_PIXEL_BGR565: + // { + // m_video->Render16bit(srcBuffer, finalFrameBuffer, m_pixelFormat, size, true); + // break; + // } + // case GG_PIXEL_RGB888: + // case GG_PIXEL_BGR888: + // { + // m_video->Render24bit(srcBuffer, finalFrameBuffer, m_pixelFormat, size, true); + // break; + // } + // } +} \ No newline at end of file diff --git a/src/geargrafx_core.h b/src/geargrafx_core.h index 2b38e46..be440b9 100644 --- a/src/geargrafx_core.h +++ b/src/geargrafx_core.h @@ -20,4 +20,60 @@ #ifndef GEARGRAFX_CORE_H #define GEARGRAFX_CORE_H +#include "types.h" + +class Audio; +class Input; +class HuC6280; + +class GeargrafxCore +{ + +public: + GeargrafxCore(); + ~GeargrafxCore(); + void Init(GG_Pixel_Format pixel_format = GG_PIXEL_RGB888); + bool RunToVBlank(u8* frame_buffer, s16* sample_buffer, int* sample_count, bool step = false, bool stopOnBreakpoints = false); + bool LoadROM(const char* szFilePath); + bool LoadROMFromBuffer(const u8* buffer, int size); + void ResetROM(bool preserve_ram); + void KeyPressed(GG_Controllers controller, GG_Keys key); + void KeyReleased(GG_Controllers controller, GG_Keys key); + void Pause(bool paused); + bool IsPaused(); + // void SaveRam(); + // void SaveRam(const char* path, bool full_path = false); + // void LoadRam(); + // void LoadRam(const char* path, bool full_path = false); + // void SaveState(int index); + // void SaveState(const char* path, int index); + // bool SaveState(u8* buffer, size_t& size); + // bool SaveState(std::ostream& stream, size_t& size); + // void LoadState(int index); + // void LoadState(const char* path, int index); + // bool LoadState(const u8* buffer, size_t size); + // bool LoadState(std::istream& stream); + void ResetSound(); + bool GetRuntimeInfo(GG_Runtime_Info& runtime_info); + // Memory* GetMemory(); + // Cartridge* GetCartridge(); + HuC6280* GetProcessor(); + Audio* GetAudio(); + // HuC6270* GetVideo(); + +private: + void Reset(); + void RenderFrameBuffer(u8* finalFrameBuffer); + +private: + // Memory* m_memory; + HuC6280* m_processor; + Audio* m_audio; + // Video* m_video; + Input* m_input; + // Cartridge* m_cartridge; + bool m_paused; + GG_Pixel_Format m_pixel_format; +}; + #endif /* GEARGRAFX_CORE_H */ \ No newline at end of file diff --git a/src/huc6270.cpp b/src/huc6270.cpp new file mode 100644 index 0000000..11b4d5b --- /dev/null +++ b/src/huc6270.cpp @@ -0,0 +1,18 @@ +/* + * Geargrafx - PC Engine / TurboGrafx Emulator + * Copyright (C) 2024 Ignacio Sanchez + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/ + * + */ diff --git a/src/huc6270.h b/src/huc6270.h new file mode 100644 index 0000000..d9fd7ae --- /dev/null +++ b/src/huc6270.h @@ -0,0 +1,26 @@ +/* + * Geargrafx - PC Engine / TurboGrafx Emulator + * Copyright (C) 2024 Ignacio Sanchez + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/ + * + */ + +#ifndef HUC6270_H +#define HUC6270_H + +#define GG_RESOLUTION_WIDTH 256 +#define GG_RESOLUTION_HEIGHT 192 + +#endif /* HUC6270_H */ \ No newline at end of file diff --git a/src/huc6280.cpp b/src/huc6280.cpp new file mode 100644 index 0000000..cbc9716 --- /dev/null +++ b/src/huc6280.cpp @@ -0,0 +1,135 @@ +/* + * Geargrafx - PC Engine / TurboGrafx Emulator + * Copyright (C) 2024 Ignacio Sanchez + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/ + * + */ + +#include "huc6280.h" +#include "huc6280_timing.h" + +HuC6280::HuC6280() +{ + InitOPCodeFunctors(); + m_t_states = 0; + m_interrupt_asserted = false; + m_nmi_interrupt_requested = false; + m_page_crossed = false; + m_branch_taken = false; +} + +HuC6280::~HuC6280() +{ +} + +void HuC6280::Init() +{ +} + +void HuC6280::Reset() +{ + // m_PC.SetLow(memory_impl_->Read(0xFFFC)); + // m_PC.SetHigh(memory_impl_->Read(0xFFFD)); + m_A.SetValue(0x00); + m_X.SetValue(0x00); + m_Y.SetValue(0x00); + m_S.SetValue(0xFD); + m_P.SetValue(0x34); + m_t_states = 0; + m_interrupt_asserted = false; + m_nmi_interrupt_requested = false; + m_page_crossed = false; + m_branch_taken = false; +} + +unsigned int HuC6280::RunFor(unsigned int t_states) +{ + unsigned int count = 0; + + while (count < t_states) + { + count += Tick(); + } + + return count; +} + +unsigned int HuC6280::Tick() +{ + m_t_states = 0; + m_page_crossed = false; + m_branch_taken = false; + + if (m_nmi_interrupt_requested) + { + m_nmi_interrupt_requested = false; + StackPush16(m_PC.GetValue()); + ClearFlag(FLAG_BRK); + StackPush8(m_P.GetValue()); + SetFlag(FLAG_IRQ); + // m_PC.SetLow(memory_impl_->Read(0xFFFA)); + // m_PC.SetHigh(memory_impl_->Read(0xFFFB)); + m_t_states += 7; + return m_t_states; + } + else if (!IsSetFlag(FLAG_IRQ) && m_interrupt_asserted) + { + StackPush16(m_PC.GetValue()); + ClearFlag(FLAG_BRK); + StackPush8(m_P.GetValue()); + SetFlag(FLAG_IRQ); + // m_PC.SetLow(memory_impl_->Read(0xFFFE)); + // m_PC.SetHigh(memory_impl_->Read(0xFFFF)); + m_t_states += 7; + return m_t_states; + } + + u8 opcode = Fetch8(); + +#ifdef HuC6280_DISASM + { + u16 opcode_address = m_PC.GetValue() - 1; + + if (!memory_impl_->IsDisassembled(opcode_address)) + { + memory_impl_->Disassemble(opcode_address, kOPCodeNames[opcode]); + } + } +#endif + +#ifdef HuC6280_DEBUG + { + u16 opcode_address = m_PC.GetValue() - 1; + printf("HuC6280 --> $%.4X %s\n", opcode_address, kOPCodeNames[opcode]); + } +#endif + + (this->*m_opcodes[opcode])(); + + m_t_states += k_opcode_tstates[opcode]; + m_t_states += m_page_crossed ? k_opcode_tstates_cross_paged[opcode] : 0; + m_t_states += m_branch_taken ? 1 : 0; + + return m_t_states; +} + +void HuC6280::UnofficialOPCode() +{ +#ifdef HuC6280_DEBUG + u16 opcode_address = m_PC.GetValue() - 1; + u8 opcode = memory_impl_->Read(opcode_address); + printf("HuC6280 --> ** UNOFFICIAL OP Code (%X) at $%.4X -- %s\n", opcode, opcode_address, kOPCodeNames[opcode]); +#endif +} diff --git a/src/huc6280.h b/src/huc6280.h new file mode 100644 index 0000000..d592e55 --- /dev/null +++ b/src/huc6280.h @@ -0,0 +1,192 @@ +/* + * Geargrafx - PC Engine / TurboGrafx Emulator + * Copyright (C) 2024 Ignacio Sanchez + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/ + * + */ + +#ifndef HUC6280_H +#define HUC6280_H + +#include "common.h" +#include "huc6280_registers.h" + +#define FLAG_CARRY 0x01 +#define FLAG_ZERO 0x02 +#define FLAG_IRQ 0x04 +#define FLAG_DECIMAL 0x08 +#define FLAG_BRK 0x10 +#define FLAG_UNUSED 0x20 +#define FLAG_OVERFLOW 0x40 +#define FLAG_NEGATIVE 0x80 + +class HuC6280 +{ +public: + HuC6280(); + ~HuC6280(); + void Init(); + void Reset(); + unsigned int RunFor(unsigned int t_states); + unsigned int Tick(); + void AssertIRQ(bool asserted); + void RequestNMI(); + +private: + typedef void (HuC6280::*opcodeptr) (void); + opcodeptr m_opcodes[256]; + SixteenBitRegister m_PC; + EightBitRegister m_A; + EightBitRegister m_X; + EightBitRegister m_Y; + EightBitRegister m_S; + EightBitRegister m_P; + unsigned int m_t_states; + bool m_interrupt_asserted; + bool m_nmi_interrupt_requested; + bool m_page_crossed; + bool m_branch_taken; + +private: + u8 Fetch8(); + u16 Fetch16(); + u16 Address16(u8 high, u8 low); + bool PageCrossed(u16 old_address, u16 new_address); + + void SetZeroFlagFromResult(u8 result); + void SetOverflowFlagFromResult(u8 result); + void SetNegativeFlagFromResult(u8 result); + void SetFlag(u8 flag); + void ClearFlag(u8 flag); + bool IsSetFlag(u8 flag); + + void StackPush16(u16 value); + void StackPush8(u8 value); + u16 StackPop16(); + u8 StackPop8(); + + u8 Read(u16 address); + void Write(u16 address, u8 value); + + u8 ImmediateAddressing(); + u16 ZeroPageAddressing(); + u16 ZeroPageAddressing(EightBitRegister* reg); + s8 RelativeAddressing(); + u16 AbsoluteAddressing(); + u16 AbsoluteAddressing(EightBitRegister* reg); + u16 IndirectAddressing(); + u16 IndexedIndirectAddressing(); + u16 IndirectIndexedAddressing(); + + void UnofficialOPCode(); + void OPCodes_ADC(u8 value); + void OPCodes_AND(u8 value); + void OPCodes_ASL_Accumulator(); + void OPCodes_ASL_Memory(u16 address); + void OPcodes_Branch(bool condition); + void OPCodes_BIT(u16 address); + void OPCodes_BRK(); + void OPCodes_ClearFlag(u8 flag); + void OPCodes_SetFlag(u8 flag); + void OPCodes_CMP(EightBitRegister* reg, u8 value); + void OPCodes_DEC_Mem(u16 address); + void OPCodes_DEC_Reg(EightBitRegister* reg); + void OPCodes_EOR(u8 value); + void OPCodes_INC_Mem(u16 address); + void OPCodes_INC_Reg(EightBitRegister* reg); + void OPCodes_LD(EightBitRegister* reg, u8 value); + void OPCodes_LSR_Accumulator(); + void OPCodes_LSR_Memory(u16 address); + void OPCodes_ORA(u8 value); + void OPCodes_ROL_Accumulator(); + void OPCodes_ROL_Memory(u16 address); + void OPCodes_ROR_Accumulator(); + void OPCodes_ROR_Memory(u16 address); + void OPCodes_SBC(u8 value); + void OPCodes_Store(EightBitRegister* reg, u16 address); + void OPCodes_Transfer(EightBitRegister* reg, EightBitRegister* target); + + void InitOPCodeFunctors(); + + void OPCode0x00(); void OPCode0x01(); void OPCode0x02(); void OPCode0x03(); + void OPCode0x04(); void OPCode0x05(); void OPCode0x06(); void OPCode0x07(); + void OPCode0x08(); void OPCode0x09(); void OPCode0x0A(); void OPCode0x0B(); + void OPCode0x0C(); void OPCode0x0D(); void OPCode0x0E(); void OPCode0x0F(); + void OPCode0x10(); void OPCode0x11(); void OPCode0x12(); void OPCode0x13(); + void OPCode0x14(); void OPCode0x15(); void OPCode0x16(); void OPCode0x17(); + void OPCode0x18(); void OPCode0x19(); void OPCode0x1A(); void OPCode0x1B(); + void OPCode0x1C(); void OPCode0x1D(); void OPCode0x1E(); void OPCode0x1F(); + void OPCode0x20(); void OPCode0x21(); void OPCode0x22(); void OPCode0x23(); + void OPCode0x24(); void OPCode0x25(); void OPCode0x26(); void OPCode0x27(); + void OPCode0x28(); void OPCode0x29(); void OPCode0x2A(); void OPCode0x2B(); + void OPCode0x2C(); void OPCode0x2D(); void OPCode0x2E(); void OPCode0x2F(); + void OPCode0x30(); void OPCode0x31(); void OPCode0x32(); void OPCode0x33(); + void OPCode0x34(); void OPCode0x35(); void OPCode0x36(); void OPCode0x37(); + void OPCode0x38(); void OPCode0x39(); void OPCode0x3A(); void OPCode0x3B(); + void OPCode0x3C(); void OPCode0x3D(); void OPCode0x3E(); void OPCode0x3F(); + void OPCode0x40(); void OPCode0x41(); void OPCode0x42(); void OPCode0x43(); + void OPCode0x44(); void OPCode0x45(); void OPCode0x46(); void OPCode0x47(); + void OPCode0x48(); void OPCode0x49(); void OPCode0x4A(); void OPCode0x4B(); + void OPCode0x4C(); void OPCode0x4D(); void OPCode0x4E(); void OPCode0x4F(); + void OPCode0x50(); void OPCode0x51(); void OPCode0x52(); void OPCode0x53(); + void OPCode0x54(); void OPCode0x55(); void OPCode0x56(); void OPCode0x57(); + void OPCode0x58(); void OPCode0x59(); void OPCode0x5A(); void OPCode0x5B(); + void OPCode0x5C(); void OPCode0x5D(); void OPCode0x5E(); void OPCode0x5F(); + void OPCode0x60(); void OPCode0x61(); void OPCode0x62(); void OPCode0x63(); + void OPCode0x64(); void OPCode0x65(); void OPCode0x66(); void OPCode0x67(); + void OPCode0x68(); void OPCode0x69(); void OPCode0x6A(); void OPCode0x6B(); + void OPCode0x6C(); void OPCode0x6D(); void OPCode0x6E(); void OPCode0x6F(); + void OPCode0x70(); void OPCode0x71(); void OPCode0x72(); void OPCode0x73(); + void OPCode0x74(); void OPCode0x75(); void OPCode0x76(); void OPCode0x77(); + void OPCode0x78(); void OPCode0x79(); void OPCode0x7A(); void OPCode0x7B(); + void OPCode0x7C(); void OPCode0x7D(); void OPCode0x7E(); void OPCode0x7F(); + void OPCode0x80(); void OPCode0x81(); void OPCode0x82(); void OPCode0x83(); + void OPCode0x84(); void OPCode0x85(); void OPCode0x86(); void OPCode0x87(); + void OPCode0x88(); void OPCode0x89(); void OPCode0x8A(); void OPCode0x8B(); + void OPCode0x8C(); void OPCode0x8D(); void OPCode0x8E(); void OPCode0x8F(); + void OPCode0x90(); void OPCode0x91(); void OPCode0x92(); void OPCode0x93(); + void OPCode0x94(); void OPCode0x95(); void OPCode0x96(); void OPCode0x97(); + void OPCode0x98(); void OPCode0x99(); void OPCode0x9A(); void OPCode0x9B(); + void OPCode0x9C(); void OPCode0x9D(); void OPCode0x9E(); void OPCode0x9F(); + void OPCode0xA0(); void OPCode0xA1(); void OPCode0xA2(); void OPCode0xA3(); + void OPCode0xA4(); void OPCode0xA5(); void OPCode0xA6(); void OPCode0xA7(); + void OPCode0xA8(); void OPCode0xA9(); void OPCode0xAA(); void OPCode0xAB(); + void OPCode0xAC(); void OPCode0xAD(); void OPCode0xAE(); void OPCode0xAF(); + void OPCode0xB0(); void OPCode0xB1(); void OPCode0xB2(); void OPCode0xB3(); + void OPCode0xB4(); void OPCode0xB5(); void OPCode0xB6(); void OPCode0xB7(); + void OPCode0xB8(); void OPCode0xB9(); void OPCode0xBA(); void OPCode0xBB(); + void OPCode0xBC(); void OPCode0xBD(); void OPCode0xBE(); void OPCode0xBF(); + void OPCode0xC0(); void OPCode0xC1(); void OPCode0xC2(); void OPCode0xC3(); + void OPCode0xC4(); void OPCode0xC5(); void OPCode0xC6(); void OPCode0xC7(); + void OPCode0xC8(); void OPCode0xC9(); void OPCode0xCA(); void OPCode0xCB(); + void OPCode0xCC(); void OPCode0xCD(); void OPCode0xCE(); void OPCode0xCF(); + void OPCode0xD0(); void OPCode0xD1(); void OPCode0xD2(); void OPCode0xD3(); + void OPCode0xD4(); void OPCode0xD5(); void OPCode0xD6(); void OPCode0xD7(); + void OPCode0xD8(); void OPCode0xD9(); void OPCode0xDA(); void OPCode0xDB(); + void OPCode0xDC(); void OPCode0xDD(); void OPCode0xDE(); void OPCode0xDF(); + void OPCode0xE0(); void OPCode0xE1(); void OPCode0xE2(); void OPCode0xE3(); + void OPCode0xE4(); void OPCode0xE5(); void OPCode0xE6(); void OPCode0xE7(); + void OPCode0xE8(); void OPCode0xE9(); void OPCode0xEA(); void OPCode0xEB(); + void OPCode0xEC(); void OPCode0xED(); void OPCode0xEE(); void OPCode0xEF(); + void OPCode0xF0(); void OPCode0xF1(); void OPCode0xF2(); void OPCode0xF3(); + void OPCode0xF4(); void OPCode0xF5(); void OPCode0xF6(); void OPCode0xF7(); + void OPCode0xF8(); void OPCode0xF9(); void OPCode0xFA(); void OPCode0xFB(); + void OPCode0xFC(); void OPCode0xFD(); void OPCode0xFE(); void OPCode0xFF(); +}; + +#include "huc6280_inline.h" +#include "huc6280_opcodes_inline.h" + +#endif /* HUC6280_H */ \ No newline at end of file diff --git a/src/huc6280_functors.cpp b/src/huc6280_functors.cpp new file mode 100644 index 0000000..929d137 --- /dev/null +++ b/src/huc6280_functors.cpp @@ -0,0 +1,295 @@ +/* + * Geargrafx - PC Engine / TurboGrafx Emulator + * Copyright (C) 2024 Ignacio Sanchez + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/ + * + */ + +#include "huc6280.h" + +void HuC6280::InitOPCodeFunctors() +{ + m_opcodes[0x00] = &HuC6280::OPCode0x00; + m_opcodes[0x01] = &HuC6280::OPCode0x01; + m_opcodes[0x02] = &HuC6280::OPCode0x02; + m_opcodes[0x03] = &HuC6280::OPCode0x03; + m_opcodes[0x04] = &HuC6280::OPCode0x04; + m_opcodes[0x05] = &HuC6280::OPCode0x05; + m_opcodes[0x06] = &HuC6280::OPCode0x06; + m_opcodes[0x07] = &HuC6280::OPCode0x07; + m_opcodes[0x08] = &HuC6280::OPCode0x08; + m_opcodes[0x09] = &HuC6280::OPCode0x09; + m_opcodes[0x0A] = &HuC6280::OPCode0x0A; + m_opcodes[0x0B] = &HuC6280::OPCode0x0B; + m_opcodes[0x0C] = &HuC6280::OPCode0x0C; + m_opcodes[0x0D] = &HuC6280::OPCode0x0D; + m_opcodes[0x0E] = &HuC6280::OPCode0x0E; + m_opcodes[0x0F] = &HuC6280::OPCode0x0F; + + m_opcodes[0x10] = &HuC6280::OPCode0x10; + m_opcodes[0x11] = &HuC6280::OPCode0x11; + m_opcodes[0x12] = &HuC6280::OPCode0x12; + m_opcodes[0x13] = &HuC6280::OPCode0x13; + m_opcodes[0x14] = &HuC6280::OPCode0x14; + m_opcodes[0x15] = &HuC6280::OPCode0x15; + m_opcodes[0x16] = &HuC6280::OPCode0x16; + m_opcodes[0x17] = &HuC6280::OPCode0x17; + m_opcodes[0x18] = &HuC6280::OPCode0x18; + m_opcodes[0x19] = &HuC6280::OPCode0x19; + m_opcodes[0x1A] = &HuC6280::OPCode0x1A; + m_opcodes[0x1B] = &HuC6280::OPCode0x1B; + m_opcodes[0x1C] = &HuC6280::OPCode0x1C; + m_opcodes[0x1D] = &HuC6280::OPCode0x1D; + m_opcodes[0x1E] = &HuC6280::OPCode0x1E; + m_opcodes[0x1F] = &HuC6280::OPCode0x1F; + + m_opcodes[0x20] = &HuC6280::OPCode0x20; + m_opcodes[0x21] = &HuC6280::OPCode0x21; + m_opcodes[0x22] = &HuC6280::OPCode0x22; + m_opcodes[0x23] = &HuC6280::OPCode0x23; + m_opcodes[0x24] = &HuC6280::OPCode0x24; + m_opcodes[0x25] = &HuC6280::OPCode0x25; + m_opcodes[0x26] = &HuC6280::OPCode0x26; + m_opcodes[0x27] = &HuC6280::OPCode0x27; + m_opcodes[0x28] = &HuC6280::OPCode0x28; + m_opcodes[0x29] = &HuC6280::OPCode0x29; + m_opcodes[0x2A] = &HuC6280::OPCode0x2A; + m_opcodes[0x2B] = &HuC6280::OPCode0x2B; + m_opcodes[0x2C] = &HuC6280::OPCode0x2C; + m_opcodes[0x2D] = &HuC6280::OPCode0x2D; + m_opcodes[0x2E] = &HuC6280::OPCode0x2E; + m_opcodes[0x2F] = &HuC6280::OPCode0x2F; + + m_opcodes[0x30] = &HuC6280::OPCode0x30; + m_opcodes[0x31] = &HuC6280::OPCode0x31; + m_opcodes[0x32] = &HuC6280::OPCode0x32; + m_opcodes[0x33] = &HuC6280::OPCode0x33; + m_opcodes[0x34] = &HuC6280::OPCode0x34; + m_opcodes[0x35] = &HuC6280::OPCode0x35; + m_opcodes[0x36] = &HuC6280::OPCode0x36; + m_opcodes[0x37] = &HuC6280::OPCode0x37; + m_opcodes[0x38] = &HuC6280::OPCode0x38; + m_opcodes[0x39] = &HuC6280::OPCode0x39; + m_opcodes[0x3A] = &HuC6280::OPCode0x3A; + m_opcodes[0x3B] = &HuC6280::OPCode0x3B; + m_opcodes[0x3C] = &HuC6280::OPCode0x3C; + m_opcodes[0x3D] = &HuC6280::OPCode0x3D; + m_opcodes[0x3E] = &HuC6280::OPCode0x3E; + m_opcodes[0x3F] = &HuC6280::OPCode0x3F; + + m_opcodes[0x40] = &HuC6280::OPCode0x40; + m_opcodes[0x41] = &HuC6280::OPCode0x41; + m_opcodes[0x42] = &HuC6280::OPCode0x42; + m_opcodes[0x43] = &HuC6280::OPCode0x43; + m_opcodes[0x44] = &HuC6280::OPCode0x44; + m_opcodes[0x45] = &HuC6280::OPCode0x45; + m_opcodes[0x46] = &HuC6280::OPCode0x46; + m_opcodes[0x47] = &HuC6280::OPCode0x47; + m_opcodes[0x48] = &HuC6280::OPCode0x48; + m_opcodes[0x49] = &HuC6280::OPCode0x49; + m_opcodes[0x4A] = &HuC6280::OPCode0x4A; + m_opcodes[0x4B] = &HuC6280::OPCode0x4B; + m_opcodes[0x4C] = &HuC6280::OPCode0x4C; + m_opcodes[0x4D] = &HuC6280::OPCode0x4D; + m_opcodes[0x4E] = &HuC6280::OPCode0x4E; + m_opcodes[0x4F] = &HuC6280::OPCode0x4F; + + m_opcodes[0x50] = &HuC6280::OPCode0x50; + m_opcodes[0x51] = &HuC6280::OPCode0x51; + m_opcodes[0x52] = &HuC6280::OPCode0x52; + m_opcodes[0x53] = &HuC6280::OPCode0x53; + m_opcodes[0x54] = &HuC6280::OPCode0x54; + m_opcodes[0x55] = &HuC6280::OPCode0x55; + m_opcodes[0x56] = &HuC6280::OPCode0x56; + m_opcodes[0x57] = &HuC6280::OPCode0x57; + m_opcodes[0x58] = &HuC6280::OPCode0x58; + m_opcodes[0x59] = &HuC6280::OPCode0x59; + m_opcodes[0x5A] = &HuC6280::OPCode0x5A; + m_opcodes[0x5B] = &HuC6280::OPCode0x5B; + m_opcodes[0x5C] = &HuC6280::OPCode0x5C; + m_opcodes[0x5D] = &HuC6280::OPCode0x5D; + m_opcodes[0x5E] = &HuC6280::OPCode0x5E; + m_opcodes[0x5F] = &HuC6280::OPCode0x5F; + + m_opcodes[0x60] = &HuC6280::OPCode0x60; + m_opcodes[0x61] = &HuC6280::OPCode0x61; + m_opcodes[0x62] = &HuC6280::OPCode0x62; + m_opcodes[0x63] = &HuC6280::OPCode0x63; + m_opcodes[0x64] = &HuC6280::OPCode0x64; + m_opcodes[0x65] = &HuC6280::OPCode0x65; + m_opcodes[0x66] = &HuC6280::OPCode0x66; + m_opcodes[0x67] = &HuC6280::OPCode0x67; + m_opcodes[0x68] = &HuC6280::OPCode0x68; + m_opcodes[0x69] = &HuC6280::OPCode0x69; + m_opcodes[0x6A] = &HuC6280::OPCode0x6A; + m_opcodes[0x6B] = &HuC6280::OPCode0x6B; + m_opcodes[0x6C] = &HuC6280::OPCode0x6C; + m_opcodes[0x6D] = &HuC6280::OPCode0x6D; + m_opcodes[0x6E] = &HuC6280::OPCode0x6E; + m_opcodes[0x6F] = &HuC6280::OPCode0x6F; + + m_opcodes[0x70] = &HuC6280::OPCode0x70; + m_opcodes[0x71] = &HuC6280::OPCode0x71; + m_opcodes[0x72] = &HuC6280::OPCode0x72; + m_opcodes[0x73] = &HuC6280::OPCode0x73; + m_opcodes[0x74] = &HuC6280::OPCode0x74; + m_opcodes[0x75] = &HuC6280::OPCode0x75; + m_opcodes[0x76] = &HuC6280::OPCode0x76; + m_opcodes[0x77] = &HuC6280::OPCode0x77; + m_opcodes[0x78] = &HuC6280::OPCode0x78; + m_opcodes[0x79] = &HuC6280::OPCode0x79; + m_opcodes[0x7A] = &HuC6280::OPCode0x7A; + m_opcodes[0x7B] = &HuC6280::OPCode0x7B; + m_opcodes[0x7C] = &HuC6280::OPCode0x7C; + m_opcodes[0x7D] = &HuC6280::OPCode0x7D; + m_opcodes[0x7E] = &HuC6280::OPCode0x7E; + m_opcodes[0x7F] = &HuC6280::OPCode0x7F; + + m_opcodes[0x80] = &HuC6280::OPCode0x80; + m_opcodes[0x81] = &HuC6280::OPCode0x81; + m_opcodes[0x82] = &HuC6280::OPCode0x82; + m_opcodes[0x83] = &HuC6280::OPCode0x83; + m_opcodes[0x84] = &HuC6280::OPCode0x84; + m_opcodes[0x85] = &HuC6280::OPCode0x85; + m_opcodes[0x86] = &HuC6280::OPCode0x86; + m_opcodes[0x87] = &HuC6280::OPCode0x87; + m_opcodes[0x88] = &HuC6280::OPCode0x88; + m_opcodes[0x89] = &HuC6280::OPCode0x89; + m_opcodes[0x8A] = &HuC6280::OPCode0x8A; + m_opcodes[0x8B] = &HuC6280::OPCode0x8B; + m_opcodes[0x8C] = &HuC6280::OPCode0x8C; + m_opcodes[0x8D] = &HuC6280::OPCode0x8D; + m_opcodes[0x8E] = &HuC6280::OPCode0x8E; + m_opcodes[0x8F] = &HuC6280::OPCode0x8F; + + m_opcodes[0x90] = &HuC6280::OPCode0x90; + m_opcodes[0x91] = &HuC6280::OPCode0x91; + m_opcodes[0x92] = &HuC6280::OPCode0x92; + m_opcodes[0x93] = &HuC6280::OPCode0x93; + m_opcodes[0x94] = &HuC6280::OPCode0x94; + m_opcodes[0x95] = &HuC6280::OPCode0x95; + m_opcodes[0x96] = &HuC6280::OPCode0x96; + m_opcodes[0x97] = &HuC6280::OPCode0x97; + m_opcodes[0x98] = &HuC6280::OPCode0x98; + m_opcodes[0x99] = &HuC6280::OPCode0x99; + m_opcodes[0x9A] = &HuC6280::OPCode0x9A; + m_opcodes[0x9B] = &HuC6280::OPCode0x9B; + m_opcodes[0x9C] = &HuC6280::OPCode0x9C; + m_opcodes[0x9D] = &HuC6280::OPCode0x9D; + m_opcodes[0x9E] = &HuC6280::OPCode0x9E; + m_opcodes[0x9F] = &HuC6280::OPCode0x9F; + + m_opcodes[0xA0] = &HuC6280::OPCode0xA0; + m_opcodes[0xA1] = &HuC6280::OPCode0xA1; + m_opcodes[0xA2] = &HuC6280::OPCode0xA2; + m_opcodes[0xA3] = &HuC6280::OPCode0xA3; + m_opcodes[0xA4] = &HuC6280::OPCode0xA4; + m_opcodes[0xA5] = &HuC6280::OPCode0xA5; + m_opcodes[0xA6] = &HuC6280::OPCode0xA6; + m_opcodes[0xA7] = &HuC6280::OPCode0xA7; + m_opcodes[0xA8] = &HuC6280::OPCode0xA8; + m_opcodes[0xA9] = &HuC6280::OPCode0xA9; + m_opcodes[0xAA] = &HuC6280::OPCode0xAA; + m_opcodes[0xAB] = &HuC6280::OPCode0xAB; + m_opcodes[0xAC] = &HuC6280::OPCode0xAC; + m_opcodes[0xAD] = &HuC6280::OPCode0xAD; + m_opcodes[0xAE] = &HuC6280::OPCode0xAE; + m_opcodes[0xAF] = &HuC6280::OPCode0xAF; + + m_opcodes[0xB0] = &HuC6280::OPCode0xB0; + m_opcodes[0xB1] = &HuC6280::OPCode0xB1; + m_opcodes[0xB2] = &HuC6280::OPCode0xB2; + m_opcodes[0xB3] = &HuC6280::OPCode0xB3; + m_opcodes[0xB4] = &HuC6280::OPCode0xB4; + m_opcodes[0xB5] = &HuC6280::OPCode0xB5; + m_opcodes[0xB6] = &HuC6280::OPCode0xB6; + m_opcodes[0xB7] = &HuC6280::OPCode0xB7; + m_opcodes[0xB8] = &HuC6280::OPCode0xB8; + m_opcodes[0xB9] = &HuC6280::OPCode0xB9; + m_opcodes[0xBA] = &HuC6280::OPCode0xBA; + m_opcodes[0xBB] = &HuC6280::OPCode0xBB; + m_opcodes[0xBC] = &HuC6280::OPCode0xBC; + m_opcodes[0xBD] = &HuC6280::OPCode0xBD; + m_opcodes[0xBE] = &HuC6280::OPCode0xBE; + m_opcodes[0xBF] = &HuC6280::OPCode0xBF; + + m_opcodes[0xC0] = &HuC6280::OPCode0xC0; + m_opcodes[0xC1] = &HuC6280::OPCode0xC1; + m_opcodes[0xC2] = &HuC6280::OPCode0xC2; + m_opcodes[0xC3] = &HuC6280::OPCode0xC3; + m_opcodes[0xC4] = &HuC6280::OPCode0xC4; + m_opcodes[0xC5] = &HuC6280::OPCode0xC5; + m_opcodes[0xC6] = &HuC6280::OPCode0xC6; + m_opcodes[0xC7] = &HuC6280::OPCode0xC7; + m_opcodes[0xC8] = &HuC6280::OPCode0xC8; + m_opcodes[0xC9] = &HuC6280::OPCode0xC9; + m_opcodes[0xCA] = &HuC6280::OPCode0xCA; + m_opcodes[0xCB] = &HuC6280::OPCode0xCB; + m_opcodes[0xCC] = &HuC6280::OPCode0xCC; + m_opcodes[0xCD] = &HuC6280::OPCode0xCD; + m_opcodes[0xCE] = &HuC6280::OPCode0xCE; + m_opcodes[0xCF] = &HuC6280::OPCode0xCF; + + m_opcodes[0xD0] = &HuC6280::OPCode0xD0; + m_opcodes[0xD1] = &HuC6280::OPCode0xD1; + m_opcodes[0xD2] = &HuC6280::OPCode0xD2; + m_opcodes[0xD3] = &HuC6280::OPCode0xD3; + m_opcodes[0xD4] = &HuC6280::OPCode0xD4; + m_opcodes[0xD5] = &HuC6280::OPCode0xD5; + m_opcodes[0xD6] = &HuC6280::OPCode0xD6; + m_opcodes[0xD7] = &HuC6280::OPCode0xD7; + m_opcodes[0xD8] = &HuC6280::OPCode0xD8; + m_opcodes[0xD9] = &HuC6280::OPCode0xD9; + m_opcodes[0xDA] = &HuC6280::OPCode0xDA; + m_opcodes[0xDB] = &HuC6280::OPCode0xDB; + m_opcodes[0xDC] = &HuC6280::OPCode0xDC; + m_opcodes[0xDD] = &HuC6280::OPCode0xDD; + m_opcodes[0xDE] = &HuC6280::OPCode0xDE; + m_opcodes[0xDF] = &HuC6280::OPCode0xDF; + + m_opcodes[0xE0] = &HuC6280::OPCode0xE0; + m_opcodes[0xE1] = &HuC6280::OPCode0xE1; + m_opcodes[0xE2] = &HuC6280::OPCode0xE2; + m_opcodes[0xE3] = &HuC6280::OPCode0xE3; + m_opcodes[0xE4] = &HuC6280::OPCode0xE4; + m_opcodes[0xE5] = &HuC6280::OPCode0xE5; + m_opcodes[0xE6] = &HuC6280::OPCode0xE6; + m_opcodes[0xE7] = &HuC6280::OPCode0xE7; + m_opcodes[0xE8] = &HuC6280::OPCode0xE8; + m_opcodes[0xE9] = &HuC6280::OPCode0xE9; + m_opcodes[0xEA] = &HuC6280::OPCode0xEA; + m_opcodes[0xEB] = &HuC6280::OPCode0xEB; + m_opcodes[0xEC] = &HuC6280::OPCode0xEC; + m_opcodes[0xED] = &HuC6280::OPCode0xED; + m_opcodes[0xEE] = &HuC6280::OPCode0xEE; + m_opcodes[0xEF] = &HuC6280::OPCode0xEF; + + m_opcodes[0xF0] = &HuC6280::OPCode0xF0; + m_opcodes[0xF1] = &HuC6280::OPCode0xF1; + m_opcodes[0xF2] = &HuC6280::OPCode0xF2; + m_opcodes[0xF3] = &HuC6280::OPCode0xF3; + m_opcodes[0xF4] = &HuC6280::OPCode0xF4; + m_opcodes[0xF5] = &HuC6280::OPCode0xF5; + m_opcodes[0xF6] = &HuC6280::OPCode0xF6; + m_opcodes[0xF7] = &HuC6280::OPCode0xF7; + m_opcodes[0xF8] = &HuC6280::OPCode0xF8; + m_opcodes[0xF9] = &HuC6280::OPCode0xF9; + m_opcodes[0xFA] = &HuC6280::OPCode0xFA; + m_opcodes[0xFB] = &HuC6280::OPCode0xFB; + m_opcodes[0xFC] = &HuC6280::OPCode0xFC; + m_opcodes[0xFD] = &HuC6280::OPCode0xFD; + m_opcodes[0xFE] = &HuC6280::OPCode0xFE; + m_opcodes[0xFF] = &HuC6280::OPCode0xFF; +} \ No newline at end of file diff --git a/src/huc6280_inline.h b/src/huc6280_inline.h new file mode 100644 index 0000000..f2b7122 --- /dev/null +++ b/src/huc6280_inline.h @@ -0,0 +1,196 @@ +/* + * Geargrafx - PC Engine / TurboGrafx Emulator + * Copyright (C) 2024 Ignacio Sanchez + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/ + * + */ + +#ifndef HUC6280_INLINE_H +#define HUC6280_INLINE_H + +#include "huc6280.h" + +inline void HuC6280::AssertIRQ(bool asserted) +{ + m_interrupt_asserted = asserted; +} + +inline void HuC6280::RequestNMI() +{ + m_nmi_interrupt_requested = true; +} + +inline u8 HuC6280::Fetch8() +{ + u8 value = Read(m_PC.GetValue()); + m_PC.Increment(); + return value; +} + +inline u16 HuC6280::Fetch16() +{ + u16 pc = m_PC.GetValue(); + u8 l = Read(pc); + u8 h = Read(pc + 1); + m_PC.SetValue(pc + 2); + return Address16(h , l); +} + +inline u16 HuC6280::Address16(u8 high, u8 low) +{ + return static_cast(high << 8 ) | low; +} + +inline bool HuC6280::PageCrossed(u16 old_address, u16 new_address) +{ + return (old_address ^ new_address) > 0x00FF; +} + +inline void HuC6280::SetZeroFlagFromResult(u8 result) +{ + if (result == 0) + SetFlag(FLAG_ZERO); + else + ClearFlag(FLAG_ZERO); +} + +inline void HuC6280::SetOverflowFlagFromResult(u8 result) +{ + m_P.SetValue((m_P.GetValue() & 0xBF) | (result & 0x40)); +} + +inline void HuC6280::SetNegativeFlagFromResult(u8 result) +{ + m_P.SetValue((m_P.GetValue() & 0x7F) | (result & 0x80)); +} + +inline void HuC6280::SetFlag(u8 flag) +{ + m_P.SetValue(m_P.GetValue() | flag); +} + +inline void HuC6280::ClearFlag(u8 flag) +{ + m_P.SetValue(m_P.GetValue() & (~flag)); +} + +inline bool HuC6280::IsSetFlag(u8 flag) +{ + return (m_P.GetValue() & flag) != 0; +} + +inline void HuC6280::StackPush16(u16 value) +{ + Write(0x0100 | m_S.GetValue(), static_cast((value >> 8) & 0x00FF)); + m_S.Decrement(); + Write(0x0100 | m_S.GetValue(), static_cast(value & 0x00FF)); + m_S.Decrement(); +} + +inline void HuC6280::StackPush8(u8 value) +{ + Write(0x0100 | m_S.GetValue(), value); + m_S.Decrement(); +} + +inline u16 HuC6280::StackPop16() +{ + m_S.Increment(); + u8 l = Read(0x0100 | m_S.GetValue()); + m_S.Increment(); + u8 h = Read(0x0100 | m_S.GetValue()); + return Address16(h , l); +} + +inline u8 HuC6280::StackPop8() +{ + m_S.Increment(); + u8 result = Read(0x0100 | m_S.GetValue()); + return result; +} + +inline u8 HuC6280::Read(u16 address) +{ + // TODO + return 0; +} + +inline void HuC6280::Write(u16 address, u8 value) +{ + // TODO + // memory_impl_->Write(address, value); +} + +inline u8 HuC6280::ImmediateAddressing() +{ + return Fetch8(); +} + +inline u16 HuC6280::ZeroPageAddressing() +{ + return 0x00FF & Fetch8(); +} + +inline u16 HuC6280::ZeroPageAddressing(EightBitRegister* reg) +{ + return 0x00FF & (Fetch8() + reg->GetValue()); +} + +inline s8 HuC6280::RelativeAddressing() +{ + return static_cast(Fetch8()); +} + +inline u16 HuC6280::AbsoluteAddressing() +{ + return Fetch16(); +} + +inline u16 HuC6280::AbsoluteAddressing(EightBitRegister* reg) +{ + u16 address = Fetch16(); + u16 result = address + reg->GetValue(); + m_page_crossed = PageCrossed(address, result); + return result; +} + +inline u16 HuC6280::IndirectAddressing() +{ + u16 address = Fetch16(); + u8 l = Read(address); + u8 h = Read((address & 0xFF00) | ((address + 1) & 0x00FF)); + return Address16(h, l); +} + +inline u16 HuC6280::IndexedIndirectAddressing() +{ + u16 address = Fetch8() + m_X.GetValue(); + u8 l = Read(address & 0x00FF); + u8 h = Read((address + 1) & 0x00FF); + return Address16(h, l); +} + +inline u16 HuC6280::IndirectIndexedAddressing() +{ + u16 address = Fetch8(); + u8 l = Read(address); + u8 h = Read(address+1); + address = Address16(h, l); + u16 result = address + m_Y.GetValue(); + m_page_crossed = PageCrossed(address, result); + return result; +} + +#endif /* HUC6280_INLINE_H */ \ No newline at end of file diff --git a/src/huc6280_names.h b/src/huc6280_names.h new file mode 100644 index 0000000..a7ca507 --- /dev/null +++ b/src/huc6280_names.h @@ -0,0 +1,296 @@ +/* + * Geargrafx - PC Engine / TurboGrafx Emulator + * Copyright (C) 2024 Ignacio Sanchez + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/ + * + */ +#ifndef HUC6280_NAME_H +#define HUC6280_NAME_H + +static const char* kOPCodeNames[256] = { + "BRK", + "ORA $(%2%1,X)", + "KIL", + "SLO $(%2%1,X)", + "NOP $%1", + "ORA $%1", + "ASL $%1", + "SLO $%1", + "PHP", + "ORA #$%1", + "ASL A", + "ANC #$%1", + "NOP $%2%1", + "ORA $%2%1", + "ASL $%2%1", + "SLO $%2%1", + + "BPL $%3", + "ORA ($%1),Y", + "KIL", + "SLO ($%1),Y", + "NOP $%1,X", + "ORA $%1,X", + "ASL $%1,X", + "SLO $%1,X", + "CLC", + "ORA $%2%1,Y", + "NOP", + "SLO $%2%1,Y", + "NOP $%2%1,X", + "ORA $%2%1,X", + "ASL $%2%1,X", + "SLO $%2%1,X", + + "JSR $%2%1", + "AND $(%2%1,X)", + "KIL", + "RLA $(%2%1,X)", + "BIT $%1", + "AND $%1", + "ROL $%1", + "RLA $%1", + "PLP", + "AND #$%1", + "ROL", + "ANC #$%1", + "BIT $%2%1", + "AND $%2%1", + "ROL $%2%1", + "RLA $%2%1", + + "BMI $%3", + "AND ($%1),Y", + "KIL", + "RLA ($%1),Y", + "NOP $%1,X", + "AND $%1,X", + "ROL $%1,X", + "RLA $%1,X", + "SEC", + "AND $%2%1,Y", + "NOP", + "RLA $%2%1,Y", + "NOP $%2%1,X", + "AND $%2%1,X", + "ROL $%2%1,X", + "RLA $%2%1,X", + + "RTI", + "EOR $(%2%1,X)", + "KIL", + "SRE $(%2%1,X)", + "NOP $%1", + "EOR $%1", + "LSR $%1", + "SRE $%1", + "PHA", + "EOR #$%1", + "LSR", + "ALR #$%1", + "JMP $%2%1", + "EOR $%2%1", + "LSR $%2%1", + "SRE $%2%1", + + "BVC $%3", + "EOR ($%1),Y", + "KIL", + "SRE ($%1),Y", + "NOP $%1,X", + "EOR $%1,X", + "LSR $%1,X", + "SRE $%1,X", + "CLI", + "EOR $%2%1,Y", + "NOP", + "SRE $%2%1,Y", + "NOP $%2%1,X", + "EOR $%2%1,X", + "LSR $%2%1,X", + "SRE $%2%1,X", + + "RTS", + "ADC $(%2%1,X)", + "KIL", + "RRA $(%2%1,X)", + "NOP $%1", + "ADC $%1", + "ROR $%1", + "RRA $%1", + "PLA", + "ADC #$%1", + "ROR", + "ARR #$%1", + "JMP ($%2%1)", + "ADC $%2%1", + "ROR $%2%1", + "RRA $%2%1", + + "BVS $%3", + "ADC ($%1),Y", + "KIL", + "RRA ($%1),Y", + "NOP $%1,X", + "ADC $%1,X", + "ROR $%1,X", + "RRA $%1,X", + "SEI", + "ADC $%2%1,Y", + "NOP", + "RRA $%2%1,Y", + "NOP $%2%1,X", + "ADC $%2%1,X", + "ROR $%2%1,X", + "RRA $%2%1,X", + + "NOP #$%1", + "STA $(%2%1,X)", + "NOP #$%1", + "SAX $(%2%1,X)", + "STY $%1", + "STA $%1", + "STX $%1", + "SAX $%1", + "DEY", + "NOP #$%1", + "TXA", + "XAA #$%1", + "STY $%2%1", + "STA $%2%1", + "STX $%2%1", + "SAX $%2%1", + + "BCC $%3", + "STA ($%1),Y", + "KIL", + "AHX ($%1),Y", + "STY $%1,X", + "STA $%1,X", + "STX $%1,Y", + "SAX $%1,Y", + "TYA", + "STA $%2%1,Y", + "TXS", + "TAS $%2%1,Y", + "SHY $%2%1,X", + "STA $%2%1,X", + "SHX $%2%1,Y", + "AHX $%2%1,Y", + + "LDY #$%1", + "LDA $(%2%1,X)", + "LDX #$%1", + "LAX $(%2%1,X)", + "LDY $%1", + "LDA $%1", + "LDX $%1", + "LAX $%1", + "TAY", + "LDA #$%1", + "TAX", + "LAX #$%1", + "LDY $%2%1", + "LDA $%2%1", + "LDX $%2%1", + "LAX $%2%1", + + "BCS $%3", + "LDA ($%1),Y", + "KIL", + "LAX ($%1),Y", + "LDY $%1,X", + "LDA $%1,X", + "LDX $%1,Y", + "LAX $%1,Y", + "CLV", + "LDA $%2%1,Y", + "TSX", + "LAS $%2%1,Y", + "LDY $%2%1,X", + "LDA $%2%1,X", + "LDX $%2%1,Y", + "LAX $%2%1,Y", + + "CPY #$%1", + "CMP $(%2%1,X)", + "NOP #$%1", + "DCP $(%2%1,X)", + "CPY $%1", + "CMP $%1", + "DEC $%1", + "DCP $%1", + "INY", + "CMP #$%1", + "DEX", + "CMP #$%1", + "CPY $%2%1", + "CMP $%2%1", + "DEC $%2%1", + "DCP $%2%1", + + "BNE $%3", + "CMP ($%1),Y", + "KIL", + "DCP ($%1),Y", + "NOP $%1,X", + "CMP $%1,X", + "DEC $%1,X", + "DCP $%1,X", + "CLD", + "CMP $%2%1,Y", + "NOP", + "NOP $%2%1,X", + "DCP $%2%1,Y", + "CMP $%2%1,X", + "DEC $%2%1,X", + "DCP $%2%1,X", + + "CPX #$%1", + "SBC $(%2%1,X)", + "NOP #$%1", + "ISC $(%2%1,X)", + "CPX $%1", + "SBC $%1", + "INC $%1", + "ISC $%1", + "INX", + "SBC #$%1", + "NOP", + "SBC #$%1", + "CPX $%2%1", + "SBC $%2%1", + "INC $%2%1", + "ISC $%2%1", + + "BEQ $%3", + "SBC ($%1),Y", + "KIL", + "ISC ($%1),Y", + "NOP $%1,X", + "SBC $%1,X", + "INC $%1,X", + "ISC $%1,X", + "SED", + "SBC $%2%1,Y", + "NOP", + "ISC $%2%1,Y", + "NOP $%2%1,X", + "SBC $%2%1,X", + "INC $%2%1,X", + "ISC $%2%1,X" +}; + +#endif /* HUC6280_NAME_H */ \ No newline at end of file diff --git a/src/huc6280_opcodes.cpp b/src/huc6280_opcodes.cpp new file mode 100644 index 0000000..0959288 --- /dev/null +++ b/src/huc6280_opcodes.cpp @@ -0,0 +1,1667 @@ +/* + * Geargrafx - PC Engine / TurboGrafx Emulator + * Copyright (C) 2024 Ignacio Sanchez + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/ + * + */ + +#include "huc6280.h" + +void HuC6280::OPCode0x00() +{ + // BRK + OPCodes_BRK(); +} + +void HuC6280::OPCode0x01() +{ + // ORA $(nn,X) + OPCodes_ORA(Read(IndexedIndirectAddressing())); +} + +void HuC6280::OPCode0x02() +{ + // UNOFFICIAL + // KILL + UnofficialOPCode(); +} + +void HuC6280::OPCode0x03() +{ + // UNOFFICIAL + // SLO $(nn,X) + UnofficialOPCode(); +} + +void HuC6280::OPCode0x04() +{ + // UNOFFICIAL + // NOP $n + UnofficialOPCode(); +} + +void HuC6280::OPCode0x05() +{ + // ORA $n + OPCodes_ORA(Read(ZeroPageAddressing())); +} + +void HuC6280::OPCode0x06() +{ + // ASL $n + OPCodes_ASL_Memory(ZeroPageAddressing()); +} + +void HuC6280::OPCode0x07() +{ + // UNOFFICIAL + // SLO $n + UnofficialOPCode(); +} + +void HuC6280::OPCode0x08() +{ + // PHP + SetFlag(FLAG_BRK); + StackPush8(m_P.GetValue()); +} + +void HuC6280::OPCode0x09() +{ + // ORA #$n + OPCodes_ORA(ImmediateAddressing()); +} + +void HuC6280::OPCode0x0A() +{ + // ASL A + OPCodes_ASL_Accumulator(); +} + +void HuC6280::OPCode0x0B() +{ + // UNOFFICIAL + // ANC #$n + UnofficialOPCode(); +} + +void HuC6280::OPCode0x0C() +{ + // UNOFFICIAL + // NOP $nn + UnofficialOPCode(); +} + +void HuC6280::OPCode0x0D() +{ + // ORA $nn + OPCodes_ORA(Read(AbsoluteAddressing())); +} + +void HuC6280::OPCode0x0E() +{ + // ASL $nn + OPCodes_ASL_Memory(AbsoluteAddressing()); +} + +void HuC6280::OPCode0x0F() +{ + // UNOFFICIAL + // SLO $nn + UnofficialOPCode(); +} + +void HuC6280::OPCode0x10() +{ + // BPL $s + OPcodes_Branch(!IsSetFlag(FLAG_NEGATIVE)); +} + +void HuC6280::OPCode0x11() +{ + // ORA ($n),Y + OPCodes_ORA(Read(IndirectIndexedAddressing())); +} + +void HuC6280::OPCode0x12() +{ + // UNOFFICIAL + // KILL + UnofficialOPCode(); +} + +void HuC6280::OPCode0x13() +{ + // UNOFFICIAL + // SLO ($n),Y + UnofficialOPCode(); +} + +void HuC6280::OPCode0x14() +{ + // UNOFFICIAL + // NOP $n,X + UnofficialOPCode(); +} + +void HuC6280::OPCode0x15() +{ + // ORA $n,X + OPCodes_ORA(Read(ZeroPageAddressing(&m_X))); +} + +void HuC6280::OPCode0x16() +{ + // ASL $n,X + OPCodes_ASL_Memory(ZeroPageAddressing(&m_X)); +} + +void HuC6280::OPCode0x17() +{ + // UNOFFICIAL + // SLO $n,X + UnofficialOPCode(); +} + +void HuC6280::OPCode0x18() +{ + // CLC + OPCodes_ClearFlag(FLAG_CARRY); +} + +void HuC6280::OPCode0x19() +{ + // ORA $nn,Y + OPCodes_ORA(Read(AbsoluteAddressing(&m_Y))); +} + +void HuC6280::OPCode0x1A() +{ + // UNOFFICIAL + // NOP + UnofficialOPCode(); +} + +void HuC6280::OPCode0x1B() +{ + // UNOFFICIAL + // SLO $nn,Y + UnofficialOPCode(); +} + +void HuC6280::OPCode0x1C() +{ + // UNOFFICIAL + // NOP $nn,X + UnofficialOPCode(); +} + +void HuC6280::OPCode0x1D() +{ + // ORA $nn,X + OPCodes_ORA(Read(AbsoluteAddressing(&m_X))); +} + +void HuC6280::OPCode0x1E() +{ + // ASL $nn,X + OPCodes_ASL_Memory(AbsoluteAddressing(&m_X)); +} + +void HuC6280::OPCode0x1F() +{ + // UNOFFICIAL + // SLO $nn,X + UnofficialOPCode(); +} + +void HuC6280::OPCode0x20() +{ + // JSR $nn + u16 target = AbsoluteAddressing(); + StackPush16(m_PC.GetValue() - 1); + m_PC.SetValue(target); +} + +void HuC6280::OPCode0x21() +{ + // AND $(nn,X) + OPCodes_AND(Read(IndexedIndirectAddressing())); +} + +void HuC6280::OPCode0x22() +{ + // UNOFFICIAL + // KILL + UnofficialOPCode(); +} + +void HuC6280::OPCode0x23() +{ + // UNOFFICIAL + // RLA $(nn,X) + UnofficialOPCode(); +} + +void HuC6280::OPCode0x24() +{ + // BIT $n + OPCodes_BIT(ZeroPageAddressing()); +} + +void HuC6280::OPCode0x25() +{ + // AND $n + OPCodes_AND(Read(ZeroPageAddressing())); +} + +void HuC6280::OPCode0x26() +{ + // ROL $n + OPCodes_ROL_Memory(ZeroPageAddressing()); +} + +void HuC6280::OPCode0x27() +{ + // UNOFFICIAL + // RLA $n + UnofficialOPCode(); +} + +void HuC6280::OPCode0x28() +{ + // PLP + m_P.SetValue((StackPop8() & 0xCF) | (m_P.GetValue() & 0x30)); +} + +void HuC6280::OPCode0x29() +{ + // AND #$n + OPCodes_AND(ImmediateAddressing()); +} + +void HuC6280::OPCode0x2A() +{ + // ROL + OPCodes_ROL_Accumulator(); +} + +void HuC6280::OPCode0x2B() +{ + // UNOFFICIAL + // ANC #$n + UnofficialOPCode(); +} + +void HuC6280::OPCode0x2C() +{ + // BIT $nn + OPCodes_BIT(AbsoluteAddressing()); +} + +void HuC6280::OPCode0x2D() +{ + // AND $nn + OPCodes_AND(Read(AbsoluteAddressing())); +} + +void HuC6280::OPCode0x2E() +{ + // ROL $nn + OPCodes_ROL_Memory(AbsoluteAddressing()); +} + +void HuC6280::OPCode0x2F() +{ + // UNOFFICIAL + // RLA $nn + UnofficialOPCode(); +} + +void HuC6280::OPCode0x30() +{ + // BMI $s + OPcodes_Branch(IsSetFlag(FLAG_NEGATIVE)); +} + +void HuC6280::OPCode0x31() +{ + // AND ($n),Y + OPCodes_AND(Read(IndirectIndexedAddressing())); +} + +void HuC6280::OPCode0x32() +{ + // UNOFFICIAL + // KILL + UnofficialOPCode(); +} + +void HuC6280::OPCode0x33() +{ + // UNOFFICIAL + // RLA ($n),Y + UnofficialOPCode(); +} + +void HuC6280::OPCode0x34() +{ + // UNOFFICIAL + // NOP $n,X + UnofficialOPCode(); +} + +void HuC6280::OPCode0x35() +{ + // AND $n,X + OPCodes_AND(Read(ZeroPageAddressing(&m_X))); +} + +void HuC6280::OPCode0x36() +{ + // ROL $n,X + OPCodes_ROL_Memory(ZeroPageAddressing(&m_X)); +} + +void HuC6280::OPCode0x37() +{ + // UNOFFICIAL + // RLA $n,X + UnofficialOPCode(); +} + +void HuC6280::OPCode0x38() +{ + // SEC + OPCodes_SetFlag(FLAG_CARRY); +} + +void HuC6280::OPCode0x39() +{ + // AND $nn,Y + OPCodes_AND(Read(AbsoluteAddressing(&m_Y))); +} + +void HuC6280::OPCode0x3A() +{ + // UNOFFICIAL + // NOP + UnofficialOPCode(); +} + +void HuC6280::OPCode0x3B() +{ + // UNOFFICIAL + // RLA $nn,Y + UnofficialOPCode(); +} + +void HuC6280::OPCode0x3C() +{ + // UNOFFICIAL + // NOP $nn,X + UnofficialOPCode(); +} + +void HuC6280::OPCode0x3D() +{ + // AND $nn,X + OPCodes_AND(Read(AbsoluteAddressing(&m_X))); +} + +void HuC6280::OPCode0x3E() +{ + // ROL $nn,X + OPCodes_ROL_Memory(AbsoluteAddressing(&m_X)); +} + +void HuC6280::OPCode0x3F() +{ + // UNOFFICIAL + // RLA $nn,X + UnofficialOPCode(); +} + +void HuC6280::OPCode0x40() +{ + // RTI + m_P.SetValue((StackPop8() & 0xCF) | (m_P.GetValue() & 0x30)); + m_PC.SetValue(StackPop16()); +} + +void HuC6280::OPCode0x41() +{ + // EOR $(nn,X) + OPCodes_EOR(Read(IndexedIndirectAddressing())); +} + +void HuC6280::OPCode0x42() +{ + // UNOFFICIAL + // KILL + UnofficialOPCode(); +} + +void HuC6280::OPCode0x43() +{ + // UNOFFICIAL + // SRE $(nn,X); + UnofficialOPCode(); +} + +void HuC6280::OPCode0x44() +{ + // UNOFFICIAL + // NOP $n + UnofficialOPCode(); +} + +void HuC6280::OPCode0x45() +{ + // EOR $n + OPCodes_EOR(Read(ZeroPageAddressing())); +} + +void HuC6280::OPCode0x46() +{ + // LSR $n + OPCodes_LSR_Memory(ZeroPageAddressing()); +} + +void HuC6280::OPCode0x47() +{ + // UNOFFICIAL + // SRE $n + UnofficialOPCode(); +} + +void HuC6280::OPCode0x48() +{ + // PHA + StackPush8(m_A.GetValue()); +} + +void HuC6280::OPCode0x49() +{ + // EOR #$n + OPCodes_EOR(ImmediateAddressing()); +} + +void HuC6280::OPCode0x4A() +{ + // LSR + OPCodes_LSR_Accumulator(); +} + +void HuC6280::OPCode0x4B() +{ + // UNOFFICIAL + // ALR #$n + UnofficialOPCode(); +} + +void HuC6280::OPCode0x4C() +{ + // JMP $nn + m_PC.SetValue(AbsoluteAddressing()); +} + +void HuC6280::OPCode0x4D() +{ + // EOR $nn + OPCodes_EOR(Read(AbsoluteAddressing())); +} + +void HuC6280::OPCode0x4E() +{ + // LSR $nn + OPCodes_LSR_Memory(AbsoluteAddressing()); +} + +void HuC6280::OPCode0x4F() +{ + // UNOFFICIAL + // SRE $nn + UnofficialOPCode(); +} + +void HuC6280::OPCode0x50() +{ + // BVC $s + OPcodes_Branch(!IsSetFlag(FLAG_OVERFLOW)); +} + +void HuC6280::OPCode0x51() +{ + // EOR ($n),Y + OPCodes_EOR(Read(IndirectIndexedAddressing())); +} + +void HuC6280::OPCode0x52() +{ + // UNOFFICIAL + // KILL + UnofficialOPCode(); +} + +void HuC6280::OPCode0x53() +{ + // UNOFFICIAL + // SRE ($n),Y + UnofficialOPCode(); +} + +void HuC6280::OPCode0x54() +{ + // UNOFFICIAL + // NOP $n,X + UnofficialOPCode(); +} + +void HuC6280::OPCode0x55() +{ + // EOR $n,X + OPCodes_EOR(Read(ZeroPageAddressing(&m_X))); +} + +void HuC6280::OPCode0x56() +{ + // LSR $n,X + OPCodes_LSR_Memory(ZeroPageAddressing(&m_X)); +} + +void HuC6280::OPCode0x57() +{ + // UNOFFICIAL + // SRE $n,X + UnofficialOPCode(); +} + +void HuC6280::OPCode0x58() +{ + // CLI + OPCodes_ClearFlag(FLAG_IRQ); +} + +void HuC6280::OPCode0x59() +{ + // EOR $nn,Y + OPCodes_EOR(Read(AbsoluteAddressing(&m_Y))); +} + +void HuC6280::OPCode0x5A() +{ + // UNOFFICIAL + // NOP + UnofficialOPCode(); +} + +void HuC6280::OPCode0x5B() +{ + // UNOFFICIAL + // SRE $nn,Y + UnofficialOPCode(); +} + +void HuC6280::OPCode0x5C() +{ + // UNOFFICIAL + // NOP $nn,X + UnofficialOPCode(); +} + +void HuC6280::OPCode0x5D() +{ + // EOR $nn,X + OPCodes_EOR(Read(AbsoluteAddressing(&m_X))); +} + +void HuC6280::OPCode0x5E() +{ + // LSR $nn,X + OPCodes_LSR_Memory(AbsoluteAddressing(&m_X)); +} + +void HuC6280::OPCode0x5F() +{ + // UNOFFICIAL + // SRE $nn,X + UnofficialOPCode(); +} + +void HuC6280::OPCode0x60() +{ + // RTS + m_PC.SetValue(StackPop16() + 1); +} + +void HuC6280::OPCode0x61() +{ + // ADC $(nn,X) + OPCodes_ADC(Read(IndexedIndirectAddressing())); +} + +void HuC6280::OPCode0x62() +{ + // UNOFFICIAL + // KILL + UnofficialOPCode(); +} + +void HuC6280::OPCode0x63() +{ + // UNOFFICIAL + // RRA $(nn,X) + UnofficialOPCode(); +} + +void HuC6280::OPCode0x64() +{ + // UNOFFICIAL + // NOP $n + UnofficialOPCode(); +} + +void HuC6280::OPCode0x65() +{ + // ADC $n + OPCodes_ADC(Read(ZeroPageAddressing())); +} + +void HuC6280::OPCode0x66() +{ + // ROR $n + OPCodes_ROR_Memory(ZeroPageAddressing()); +} + +void HuC6280::OPCode0x67() +{ + // UNOFFICIAL + // RRA $n + UnofficialOPCode(); +} + +void HuC6280::OPCode0x68() +{ + // PLA + u8 result = StackPop8(); + m_A.SetValue(result); + SetZeroFlagFromResult(result); + SetNegativeFlagFromResult(result); +} + +void HuC6280::OPCode0x69() +{ + // ADC #$n + OPCodes_ADC(ImmediateAddressing()); +} + +void HuC6280::OPCode0x6A() +{ + // ROR + OPCodes_ROR_Accumulator(); +} + +void HuC6280::OPCode0x6B() +{ + // UNOFFICIAL + // ARR #$n + UnofficialOPCode(); +} + +void HuC6280::OPCode0x6C() +{ + // JMP ($nn) + m_PC.SetValue(IndirectAddressing()); +} + +void HuC6280::OPCode0x6D() +{ + // ADC $nn + OPCodes_ADC(Read(AbsoluteAddressing())); +} + +void HuC6280::OPCode0x6E() +{ + // ROR $nn + OPCodes_ROR_Memory(AbsoluteAddressing()); +} + +void HuC6280::OPCode0x6F() +{ + // UNOFFICIAL + // RRA $nn + UnofficialOPCode(); +} + +void HuC6280::OPCode0x70() +{ + // BVS $s + OPcodes_Branch(IsSetFlag(FLAG_OVERFLOW)); +} + +void HuC6280::OPCode0x71() +{ + // ADC ($n),Y + OPCodes_ADC(Read(IndirectIndexedAddressing())); +} + +void HuC6280::OPCode0x72() +{ + // UNOFFICIAL + // KILL + UnofficialOPCode(); +} + +void HuC6280::OPCode0x73() +{ + // UNOFFICIAL + // RRA ($n),Y + UnofficialOPCode(); +} + +void HuC6280::OPCode0x74() +{ + // UNOFFICIAL + // NOP $n,X + UnofficialOPCode(); +} + +void HuC6280::OPCode0x75() +{ + // ADC $n,X + OPCodes_ADC(Read(ZeroPageAddressing(&m_X))); +} + +void HuC6280::OPCode0x76() +{ + // ROR $n,X + OPCodes_ROR_Memory(ZeroPageAddressing(&m_X)); +} + +void HuC6280::OPCode0x77() +{ + // UNOFFICIAL + // RRA $n,X + UnofficialOPCode(); +} + +void HuC6280::OPCode0x78() +{ + // SEI + OPCodes_SetFlag(FLAG_IRQ); +} + +void HuC6280::OPCode0x79() +{ + // ADC $nn,Y + OPCodes_ADC(Read(AbsoluteAddressing(&m_Y))); +} + +void HuC6280::OPCode0x7A() +{ + // UNOFFICIAL + // NOP + UnofficialOPCode(); +} + +void HuC6280::OPCode0x7B() +{ + // UNOFFICIAL + // RRA $nn,Y + UnofficialOPCode(); +} + +void HuC6280::OPCode0x7C() +{ + // UNOFFICIAL + // NOP $nn,X + UnofficialOPCode(); +} + +void HuC6280::OPCode0x7D() +{ + // ADC $nn,X + OPCodes_ADC(Read(AbsoluteAddressing(&m_X))); +} + +void HuC6280::OPCode0x7E() +{ + // ROR $nn,X + OPCodes_ROR_Memory(AbsoluteAddressing(&m_X)); +} + +void HuC6280::OPCode0x7F() +{ + // UNOFFICIAL + // RRA $nn,X + UnofficialOPCode(); +} + +void HuC6280::OPCode0x80() +{ + // UNOFFICIAL + // NOP #$n + UnofficialOPCode(); +} + +void HuC6280::OPCode0x81() +{ + // STA $(nn,X) + OPCodes_Store(&m_A, IndexedIndirectAddressing()); +} + +void HuC6280::OPCode0x82() +{ + // UNOFFICIAL + // NOP #$n + UnofficialOPCode(); +} + +void HuC6280::OPCode0x83() +{ + // UNOFFICIAL + // SAX $(nn,X) + UnofficialOPCode(); +} + +void HuC6280::OPCode0x84() +{ + // STY $n + OPCodes_Store(&m_Y, ZeroPageAddressing()); +} + +void HuC6280::OPCode0x85() +{ + // STA $n + OPCodes_Store(&m_A, ZeroPageAddressing()); +} + +void HuC6280::OPCode0x86() +{ + // STX $n + OPCodes_Store(&m_X, ZeroPageAddressing()); +} + +void HuC6280::OPCode0x87() +{ + // UNOFFICIAL + // SAX $n + UnofficialOPCode(); +} + +void HuC6280::OPCode0x88() +{ + // DEY + OPCodes_DEC_Reg(&m_Y); +} + +void HuC6280::OPCode0x89() +{ + // UNOFFICIAL + // NOP #$n + UnofficialOPCode(); +} + +void HuC6280::OPCode0x8A() +{ + // TXA + OPCodes_Transfer(&m_X, &m_A); +} + +void HuC6280::OPCode0x8B() +{ + // UNOFFICIAL + // XAA #$n + UnofficialOPCode(); +} + +void HuC6280::OPCode0x8C() +{ + // STY $nn + OPCodes_Store(&m_Y, AbsoluteAddressing()); +} + +void HuC6280::OPCode0x8D() +{ + // STA $nn + OPCodes_Store(&m_A, AbsoluteAddressing()); +} + +void HuC6280::OPCode0x8E() +{ + // STX $nn + OPCodes_Store(&m_X, AbsoluteAddressing()); +} + +void HuC6280::OPCode0x8F() +{ + // UNOFFICIAL + // SAX $nn + UnofficialOPCode(); +} + +void HuC6280::OPCode0x90() +{ + // BCC $s + OPcodes_Branch(!IsSetFlag(FLAG_CARRY)); +} + +void HuC6280::OPCode0x91() +{ + // STA ($n),Y + OPCodes_Store(&m_A, IndirectIndexedAddressing()); +} + +void HuC6280::OPCode0x92() +{ + // UNOFFICIAL + // KILL + UnofficialOPCode(); +} + +void HuC6280::OPCode0x93() +{ + // UNOFFICIAL + // AHX ($n),Y + UnofficialOPCode(); +} + +void HuC6280::OPCode0x94() +{ + // STY $n,X + OPCodes_Store(&m_Y, ZeroPageAddressing(&m_X)); +} + +void HuC6280::OPCode0x95() +{ + // STA $n,X + OPCodes_Store(&m_A, ZeroPageAddressing(&m_X)); +} + +void HuC6280::OPCode0x96() +{ + // STX $n,Y + OPCodes_Store(&m_X, ZeroPageAddressing(&m_Y)); +} + +void HuC6280::OPCode0x97() +{ + // UNOFFICIAL + // SAX $n,Y + UnofficialOPCode(); +} + +void HuC6280::OPCode0x98() +{ + // TYA + OPCodes_Transfer(&m_Y, &m_A); +} + +void HuC6280::OPCode0x99() +{ + // STA $nn,Y + OPCodes_Store(&m_A, AbsoluteAddressing(&m_Y)); +} + +void HuC6280::OPCode0x9A() +{ + // TXS + OPCodes_Transfer(&m_X, &m_S); +} + +void HuC6280::OPCode0x9B() +{ + // UNOFFICIAL + // TAS $nn,Y + UnofficialOPCode(); +} + +void HuC6280::OPCode0x9C() +{ + // UNOFFICIAL + // SHY $nn,X + UnofficialOPCode(); +} + +void HuC6280::OPCode0x9D() +{ + // STA $nn,X + OPCodes_Store(&m_A, AbsoluteAddressing(&m_X)); +} + +void HuC6280::OPCode0x9E() +{ + // UNOFFICIAL + // SHX $nn,Y + UnofficialOPCode(); +} + +void HuC6280::OPCode0x9F() +{ + // UNOFFICIAL + // AHX $nn,Y + UnofficialOPCode(); +} + +void HuC6280::OPCode0xA0() +{ + // LDY #$n + OPCodes_LD(&m_Y, ImmediateAddressing()); +} + +void HuC6280::OPCode0xA1() +{ + // LDA $(nn,X) + OPCodes_LD(&m_A, Read(IndexedIndirectAddressing())); +} + +void HuC6280::OPCode0xA2() +{ + // LDX #$n + OPCodes_LD(&m_X, ImmediateAddressing()); +} + +void HuC6280::OPCode0xA3() +{ + // UNOFFICIAL + // LAX $(nn,X) + UnofficialOPCode(); +} + +void HuC6280::OPCode0xA4() +{ + // LDY $n + OPCodes_LD(&m_Y, Read(ZeroPageAddressing())); +} + +void HuC6280::OPCode0xA5() +{ + // LDA $n + OPCodes_LD(&m_A, Read(ZeroPageAddressing())); +} + +void HuC6280::OPCode0xA6() +{ + // LDX $n + OPCodes_LD(&m_X, Read(ZeroPageAddressing())); +} + +void HuC6280::OPCode0xA7() +{ + // UNOFFICIAL + // LAX $n + UnofficialOPCode(); +} + +void HuC6280::OPCode0xA8() +{ + // TAY + OPCodes_Transfer(&m_A, &m_Y); +} + +void HuC6280::OPCode0xA9() +{ + // LDA #$n + OPCodes_LD(&m_A, ImmediateAddressing()); +} + +void HuC6280::OPCode0xAA() +{ + // TAX + OPCodes_Transfer(&m_A, &m_X); +} + +void HuC6280::OPCode0xAB() +{ + // UNOFFICIAL + // LAX #$n + UnofficialOPCode(); +} + +void HuC6280::OPCode0xAC() +{ + // LDY $nn + OPCodes_LD(&m_Y, Read(AbsoluteAddressing())); +} + +void HuC6280::OPCode0xAD() +{ + // LDA $nn + OPCodes_LD(&m_A, Read(AbsoluteAddressing())); +} + +void HuC6280::OPCode0xAE() +{ + // LDX $nn + OPCodes_LD(&m_X, Read(AbsoluteAddressing())); +} + +void HuC6280::OPCode0xAF() +{ + // UNOFFICIAL + // LAX $nn + UnofficialOPCode(); +} + +void HuC6280::OPCode0xB0() +{ + // BCS $s + OPcodes_Branch(IsSetFlag(FLAG_CARRY)); +} + +void HuC6280::OPCode0xB1() +{ + // LDA ($n),Y + OPCodes_LD(&m_A, Read(IndirectIndexedAddressing())); +} + +void HuC6280::OPCode0xB2() +{ + // UNOFFICIAL + // KILL + UnofficialOPCode(); +} + +void HuC6280::OPCode0xB3() +{ + // UNOFFICIAL + // LAX ($n),Y + UnofficialOPCode(); +} + +void HuC6280::OPCode0xB4() +{ + // LDY $n,X + OPCodes_LD(&m_Y, Read(ZeroPageAddressing(&m_X))); +} + +void HuC6280::OPCode0xB5() +{ + // LDA $n,X + OPCodes_LD(&m_A, Read(ZeroPageAddressing(&m_X))); +} + +void HuC6280::OPCode0xB6() +{ + // LDX $n,Y + OPCodes_LD(&m_X, Read(ZeroPageAddressing(&m_Y))); +} + +void HuC6280::OPCode0xB7() +{ + // UNOFFICIAL + // LAX $n,Y + UnofficialOPCode(); +} + +void HuC6280::OPCode0xB8() +{ + // CLV + OPCodes_ClearFlag(FLAG_OVERFLOW); +} + +void HuC6280::OPCode0xB9() +{ + // LDA $nn,Y + OPCodes_LD(&m_A, Read(AbsoluteAddressing(&m_Y))); +} + +void HuC6280::OPCode0xBA() +{ + // TSX + OPCodes_Transfer(&m_S, &m_X); +} + +void HuC6280::OPCode0xBB() +{ + // UNOFFICIAL + // LAS $nn,Y + UnofficialOPCode(); +} + +void HuC6280::OPCode0xBC() +{ + // LDY $nn,X + OPCodes_LD(&m_Y, Read(AbsoluteAddressing(&m_X))); +} + +void HuC6280::OPCode0xBD() +{ + // LDA $nn,X + OPCodes_LD(&m_A, Read(AbsoluteAddressing(&m_X))); +} + +void HuC6280::OPCode0xBE() +{ + // LDX $nn,Y + OPCodes_LD(&m_X, Read(AbsoluteAddressing(&m_Y))); +} + +void HuC6280::OPCode0xBF() +{ + // UNOFFICIAL + // LAX $nn,Y + UnofficialOPCode(); +} + +void HuC6280::OPCode0xC0() +{ + // CPY #$n + OPCodes_CMP(&m_Y, ImmediateAddressing()); +} + +void HuC6280::OPCode0xC1() +{ + // CMP $(nn,X) + OPCodes_CMP(&m_A, Read(IndexedIndirectAddressing())); +} + +void HuC6280::OPCode0xC2() +{ + // UNOFFICIAL + // NOP #$n + UnofficialOPCode(); +} + +void HuC6280::OPCode0xC3() +{ + // UNOFFICIAL + // DCP $(nn,X) + UnofficialOPCode(); +} + +void HuC6280::OPCode0xC4() +{ + // CPY $n + OPCodes_CMP(&m_Y, Read(ZeroPageAddressing())); +} + +void HuC6280::OPCode0xC5() +{ + // CMP $n + OPCodes_CMP(&m_A, Read(ZeroPageAddressing())); +} + +void HuC6280::OPCode0xC6() +{ + // DEC $n + OPCodes_DEC_Mem(ZeroPageAddressing()); +} + +void HuC6280::OPCode0xC7() +{ + // UNOFFICIAL + // DCP $n + UnofficialOPCode(); +} + +void HuC6280::OPCode0xC8() +{ + // INY + OPCodes_INC_Reg(&m_Y); +} + +void HuC6280::OPCode0xC9() +{ + // CMP #$n + OPCodes_CMP(&m_A, ImmediateAddressing()); +} + +void HuC6280::OPCode0xCA() +{ + // DEX + OPCodes_DEC_Reg(&m_X); +} + +void HuC6280::OPCode0xCB() +{ + // UNOFFICIAL + // CMP #$n + UnofficialOPCode(); +} + +void HuC6280::OPCode0xCC() +{ + // CPY $nn + OPCodes_CMP(&m_Y, Read(AbsoluteAddressing())); +} + +void HuC6280::OPCode0xCD() +{ + // CMP $nn + OPCodes_CMP(&m_A, Read(AbsoluteAddressing())); +} + +void HuC6280::OPCode0xCE() +{ + // DEC $nn + OPCodes_DEC_Mem(AbsoluteAddressing()); +} + +void HuC6280::OPCode0xCF() +{ + // UNOFFICIAL + // DCP $nn + UnofficialOPCode(); +} + +void HuC6280::OPCode0xD0() +{ + // BNE $s + OPcodes_Branch(!IsSetFlag(FLAG_ZERO)); +} + +void HuC6280::OPCode0xD1() +{ + // CMP ($n),Y + OPCodes_CMP(&m_A, Read(IndirectIndexedAddressing())); +} + +void HuC6280::OPCode0xD2() +{ + // UNOFFICIAL + // KILL + UnofficialOPCode(); +} + +void HuC6280::OPCode0xD3() +{ + // UNOFFICIAL + // DCP ($n),Y + UnofficialOPCode(); +} + +void HuC6280::OPCode0xD4() +{ + // UNOFFICIAL + // NOP $n,X + UnofficialOPCode(); +} + +void HuC6280::OPCode0xD5() +{ + // CMP $n,X + OPCodes_CMP(&m_A, Read(ZeroPageAddressing(&m_X))); +} + +void HuC6280::OPCode0xD6() +{ + // DEC $n,X + OPCodes_DEC_Mem(ZeroPageAddressing(&m_X)); +} + +void HuC6280::OPCode0xD7() +{ + // UNOFFICIAL + // DCP $n,X + UnofficialOPCode(); +} + +void HuC6280::OPCode0xD8() +{ + // CLD + OPCodes_ClearFlag(FLAG_DECIMAL); +} + +void HuC6280::OPCode0xD9() +{ + // CMP $nn,Y + OPCodes_CMP(&m_A, Read(AbsoluteAddressing(&m_Y))); +} + +void HuC6280::OPCode0xDA() +{ + // UNOFFICIAL + // NOP + UnofficialOPCode(); +} + +void HuC6280::OPCode0xDB() +{ + // UNOFFICIAL + // DCP $nn,Y + UnofficialOPCode(); +} + +void HuC6280::OPCode0xDC() +{ + // UNOFFICIAL + // NOP $nn,X + UnofficialOPCode(); +} + +void HuC6280::OPCode0xDD() +{ + // CMP $nn,X + OPCodes_CMP(&m_A, Read(AbsoluteAddressing(&m_X))); +} + +void HuC6280::OPCode0xDE() +{ + // DEC $nn,X + OPCodes_DEC_Mem(AbsoluteAddressing(&m_X)); +} + +void HuC6280::OPCode0xDF() +{ + // UNOFFICIAL + // DCP $nn,X + UnofficialOPCode(); +} + +void HuC6280::OPCode0xE0() +{ + // CPX #$n + OPCodes_CMP(&m_X, ImmediateAddressing()); +} + +void HuC6280::OPCode0xE1() +{ + // SBC $(nn,X) + OPCodes_SBC(Read(IndexedIndirectAddressing())); +} + +void HuC6280::OPCode0xE2() +{ + // UNOFFICIAL + // NOP #$n + UnofficialOPCode(); +} + +void HuC6280::OPCode0xE3() +{ + // UNOFFICIAL + // ISC $(nn,X) + UnofficialOPCode(); +} + +void HuC6280::OPCode0xE4() +{ + // CPX $n + OPCodes_CMP(&m_X, Read(ZeroPageAddressing())); +} + +void HuC6280::OPCode0xE5() +{ + // SBC $n + OPCodes_SBC(Read(ZeroPageAddressing())); +} + +void HuC6280::OPCode0xE6() +{ + // INC $n + OPCodes_INC_Mem(ZeroPageAddressing()); +} + +void HuC6280::OPCode0xE7() +{ + // UNOFFICIAL + // ISC $n + UnofficialOPCode(); +} + +void HuC6280::OPCode0xE8() +{ + // INX + OPCodes_INC_Reg(&m_X); +} + +void HuC6280::OPCode0xE9() +{ + // SBC #$n + OPCodes_SBC(ImmediateAddressing()); +} + +void HuC6280::OPCode0xEA() +{ + // NOP +} + +void HuC6280::OPCode0xEB() +{ + // UNOFFICIAL + // SBC #$n + UnofficialOPCode(); +} + +void HuC6280::OPCode0xEC() +{ + // CPX $nn + OPCodes_CMP(&m_X, Read(AbsoluteAddressing())); +} + +void HuC6280::OPCode0xED() +{ + // SBC $nn + OPCodes_SBC(Read(AbsoluteAddressing())); +} + +void HuC6280::OPCode0xEE() +{ + // INC $nn + OPCodes_INC_Mem(AbsoluteAddressing()); +} + +void HuC6280::OPCode0xEF() +{ + // UNOFFICIAL + // ISC $nn + UnofficialOPCode(); +} + +void HuC6280::OPCode0xF0() +{ + // BEQ $s + OPcodes_Branch(IsSetFlag(FLAG_ZERO)); +} + +void HuC6280::OPCode0xF1() +{ + // SBC ($n),Y + OPCodes_SBC(Read(IndirectIndexedAddressing())); +} + +void HuC6280::OPCode0xF2() +{ + // UNOFFICIAL + // KILL + UnofficialOPCode(); +} + +void HuC6280::OPCode0xF3() +{ + // UNOFFICIAL + // ISC ($n),Y + UnofficialOPCode(); +} + +void HuC6280::OPCode0xF4() +{ + // UNOFFICIAL + // NOP $n,X + UnofficialOPCode(); +} + +void HuC6280::OPCode0xF5() +{ + // SBC $n,X + OPCodes_SBC(Read(ZeroPageAddressing(&m_X))); +} + +void HuC6280::OPCode0xF6() +{ + // INC $n,X + OPCodes_INC_Mem(ZeroPageAddressing(&m_X)); +} + +void HuC6280::OPCode0xF7() +{ + // UNOFFICIAL + // ISC $n,X + UnofficialOPCode(); +} + +void HuC6280::OPCode0xF8() +{ + // SED + OPCodes_SetFlag(FLAG_DECIMAL); +} + +void HuC6280::OPCode0xF9() +{ + // SBC $nn,Y + OPCodes_SBC(Read(AbsoluteAddressing(&m_Y))); +} + +void HuC6280::OPCode0xFA() +{ + // UNOFFICIAL + // NOP + UnofficialOPCode(); +} + +void HuC6280::OPCode0xFB() +{ + // UNOFFICIAL + // ISC $nn,Y + UnofficialOPCode(); +} + +void HuC6280::OPCode0xFC() +{ + // UNOFFICIAL + // NOP $nn,X + UnofficialOPCode(); +} + +void HuC6280::OPCode0xFD() +{ + // SBC $nn,X + OPCodes_SBC(Read(AbsoluteAddressing(&m_X))); +} + +void HuC6280::OPCode0xFE() +{ + // INC $nn,X + OPCodes_INC_Mem(AbsoluteAddressing(&m_X)); +} + +void HuC6280::OPCode0xFF() +{ + // UNOFFICIAL + // ISC $nn,X + UnofficialOPCode(); +} \ No newline at end of file diff --git a/src/huc6280_opcodes_inline.h b/src/huc6280_opcodes_inline.h new file mode 100644 index 0000000..1373eee --- /dev/null +++ b/src/huc6280_opcodes_inline.h @@ -0,0 +1,304 @@ +/* + * Geargrafx - PC Engine / TurboGrafx Emulator + * Copyright (C) 2024 Ignacio Sanchez + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/ + * + */ + +#ifndef HUC6280_OPCODES_INLINE_H +#define HUC6280_OPCODES_INLINE_H + +#include "huc6280.h" + +inline void HuC6280::OPCodes_ADC(u8 value) +{ + int result = m_A.GetValue() + value + (IsSetFlag(FLAG_CARRY) ? 1 : 0); + u8 final_result = static_cast (result & 0xFF); + SetZeroFlagFromResult(final_result); + SetNegativeFlagFromResult(final_result); + if ((result & 0x100) != 0) + SetFlag(FLAG_CARRY); + else + ClearFlag(FLAG_CARRY); + if ((((m_A.GetValue() ^ value) & 0x80) == 0) && (((m_A.GetValue() ^ result) & 0x80) != 0)) + SetFlag(FLAG_OVERFLOW); + else + ClearFlag(FLAG_OVERFLOW); + m_A.SetValue(final_result); +} + +inline void HuC6280::OPCodes_AND(u8 value) +{ + u8 result = m_A.GetValue() & value; + m_A.SetValue(result); + SetZeroFlagFromResult(result); + SetNegativeFlagFromResult(result); +} + +inline void HuC6280::OPCodes_ASL_Accumulator() +{ + u8 value = m_A.GetValue(); + u8 result = static_cast(value << 1); + m_A.SetValue(result); + SetZeroFlagFromResult(result); + SetNegativeFlagFromResult(result); + if ((value & 0x80) != 0) + SetFlag(FLAG_CARRY); + else + ClearFlag(FLAG_CARRY); +} + +inline void HuC6280::OPCodes_ASL_Memory(u16 address) +{ + u8 value = Read(address); + u8 result = static_cast(value << 1); + Write(address, result); + SetZeroFlagFromResult(result); + SetNegativeFlagFromResult(result); + if ((value & 0x80) != 0) + SetFlag(FLAG_CARRY); + else + ClearFlag(FLAG_CARRY); +} + +inline void HuC6280::OPcodes_Branch(bool condition) +{ + if (condition) + { + s8 displacement = RelativeAddressing(); + u16 address = m_PC.GetValue(); + u16 result = static_cast(address + displacement); + m_PC.SetValue(result); + m_branch_taken = true; + m_page_crossed = PageCrossed(address, result); + } + else + m_PC.Increment(); +} + +inline void HuC6280::OPCodes_BIT(u16 address) +{ + u8 value = Read(address); + u8 result = m_A.GetValue() & value; + SetZeroFlagFromResult(result); + SetOverflowFlagFromResult(value); + SetNegativeFlagFromResult(value); +} + +inline void HuC6280::OPCodes_BRK() +{ + StackPush16(m_PC.GetValue()); + SetFlag(FLAG_BRK); + StackPush8(m_P.GetValue()); + SetFlag(FLAG_IRQ); + m_PC.SetLow(Read(0xFFFE)); + m_PC.SetHigh(Read(0xFFFF)); +} + +inline void HuC6280::OPCodes_ClearFlag(u8 flag) +{ + ClearFlag(flag); +} + +inline void HuC6280::OPCodes_SetFlag(u8 flag) +{ + SetFlag(flag); +} + +inline void HuC6280::OPCodes_CMP(EightBitRegister* reg, u8 value) +{ + u8 reg_value = reg->GetValue(); + u8 result = reg_value - value; + SetZeroFlagFromResult(result); + SetNegativeFlagFromResult(result); + if (reg_value >= value) + SetFlag(FLAG_CARRY); + else + ClearFlag(FLAG_CARRY); +} + +inline void HuC6280::OPCodes_DEC_Mem(u16 address) +{ + u8 value = Read(address); + u8 result = value - 1; + Write(address, result); + SetZeroFlagFromResult(result); + SetNegativeFlagFromResult(result); +} + +inline void HuC6280::OPCodes_DEC_Reg(EightBitRegister* reg) +{ + u8 value = reg->GetValue(); + u8 result = value - 1; + reg->SetValue(result); + SetZeroFlagFromResult(result); + SetNegativeFlagFromResult(result); +} + +inline void HuC6280::OPCodes_EOR(u8 value) +{ + u8 result = m_A.GetValue() ^ value; + m_A.SetValue(result); + SetZeroFlagFromResult(result); + SetNegativeFlagFromResult(result); +} + +inline void HuC6280::OPCodes_INC_Mem(u16 address) +{ + u8 value = Read(address); + u8 result = value + 1; + Write(address, result); + SetZeroFlagFromResult(result); + SetNegativeFlagFromResult(result); +} + +inline void HuC6280::OPCodes_INC_Reg(EightBitRegister* reg) +{ + u8 value = reg->GetValue(); + u8 result = value + 1; + reg->SetValue(result); + SetZeroFlagFromResult(result); + SetNegativeFlagFromResult(result); +} + +inline void HuC6280::OPCodes_LD(EightBitRegister* reg, u8 value) +{ + reg->SetValue(value); + SetZeroFlagFromResult(value); + SetNegativeFlagFromResult(value); +} + +inline void HuC6280::OPCodes_LSR_Accumulator() +{ + u8 value = m_A.GetValue(); + u8 result = value >> 1; + m_A.SetValue(result); + SetZeroFlagFromResult(result); + SetNegativeFlagFromResult(result); + if ((value & 0x01) != 0) + SetFlag(FLAG_CARRY); + else + ClearFlag(FLAG_CARRY); +} + +inline void HuC6280::OPCodes_LSR_Memory(u16 address) +{ + u8 value = Read(address); + u8 result = value >> 1; + Write(address, result); + SetZeroFlagFromResult(result); + SetNegativeFlagFromResult(result); + if ((value & 0x01) != 0) + SetFlag(FLAG_CARRY); + else + ClearFlag(FLAG_CARRY); +} + +inline void HuC6280::OPCodes_ORA(u8 value) +{ + u8 result = m_A.GetValue() | value; + m_A.SetValue(result); + SetZeroFlagFromResult(result); + SetNegativeFlagFromResult(result); +} + +inline void HuC6280::OPCodes_ROL_Accumulator() +{ + u8 value = m_A.GetValue(); + u8 result = static_cast(value << 1); + result |= IsSetFlag(FLAG_CARRY) ? 0x01 : 0x00; + m_A.SetValue(result); + SetZeroFlagFromResult(result); + SetNegativeFlagFromResult(result); + if ((value & 0x80) != 0) + SetFlag(FLAG_CARRY); + else + ClearFlag(FLAG_CARRY); +} + +inline void HuC6280::OPCodes_ROL_Memory(u16 address) +{ + u8 value = Read(address); + u8 result = static_cast(value << 1); + result |= IsSetFlag(FLAG_CARRY) ? 0x01 : 0x00; + Write(address, result); + SetZeroFlagFromResult(result); + SetNegativeFlagFromResult(result); + if ((value & 0x80) != 0) + SetFlag(FLAG_CARRY); + else + ClearFlag(FLAG_CARRY); +} + +inline void HuC6280::OPCodes_ROR_Accumulator() +{ + u8 value = m_A.GetValue(); + u8 result = value >> 1; + result |= IsSetFlag(FLAG_CARRY) ? 0x80 : 0x00; + m_A.SetValue(result); + SetZeroFlagFromResult(result); + SetNegativeFlagFromResult(result); + if ((value & 0x01) != 0) + SetFlag(FLAG_CARRY); + else + ClearFlag(FLAG_CARRY); +} + +inline void HuC6280::OPCodes_ROR_Memory(u16 address) +{ + u8 value = Read(address); + u8 result = value >> 1; + result |= IsSetFlag(FLAG_CARRY) ? 0x80 : 0x00; + Write(address, result); + SetZeroFlagFromResult(result); + SetNegativeFlagFromResult(result); + if ((value & 0x01) != 0) + SetFlag(FLAG_CARRY); + else + ClearFlag(FLAG_CARRY); +} + +inline void HuC6280::OPCodes_SBC(u8 value) +{ + int result = m_A.GetValue() - value - (IsSetFlag(FLAG_CARRY) ? 0x00 : 0x01); + u8 final_result = static_cast (result & 0xFF); + SetZeroFlagFromResult(final_result); + SetNegativeFlagFromResult(final_result); + if ((result & 0x100) == 0) + SetFlag(FLAG_CARRY); + else + ClearFlag(FLAG_CARRY); + if ((((m_A.GetValue() ^ value) & 0x80) != 0) && (((m_A.GetValue() ^ result) & 0x80) != 0)) + SetFlag(FLAG_OVERFLOW); + else + ClearFlag(FLAG_OVERFLOW); + m_A.SetValue(final_result); +} + +inline void HuC6280::OPCodes_Store(EightBitRegister* reg, u16 address) +{ + u8 value = reg->GetValue(); + Write(address, value); +} + +inline void HuC6280::OPCodes_Transfer(EightBitRegister* reg, EightBitRegister* target) +{ + u8 value = reg->GetValue(); + target->SetValue(value); + SetZeroFlagFromResult(value); + SetNegativeFlagFromResult(value); +} + +#endif /* HUC6280_OPCODES_INLINE_H */ \ No newline at end of file diff --git a/src/huc6280_psg.cpp b/src/huc6280_psg.cpp new file mode 100644 index 0000000..11b4d5b --- /dev/null +++ b/src/huc6280_psg.cpp @@ -0,0 +1,18 @@ +/* + * Geargrafx - PC Engine / TurboGrafx Emulator + * Copyright (C) 2024 Ignacio Sanchez + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/ + * + */ diff --git a/src/huc6280_psg.h b/src/huc6280_psg.h new file mode 100644 index 0000000..e380e43 --- /dev/null +++ b/src/huc6280_psg.h @@ -0,0 +1,23 @@ +/* + * Geargrafx - PC Engine / TurboGrafx Emulator + * Copyright (C) 2024 Ignacio Sanchez + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/ + * + */ + +#ifndef HUC6280_PSG_H +#define HUC6280_PSG_H + +#endif /* HUC6280_PSG_H */ \ No newline at end of file diff --git a/src/huc6280_registers.h b/src/huc6280_registers.h new file mode 100644 index 0000000..0224262 --- /dev/null +++ b/src/huc6280_registers.h @@ -0,0 +1,117 @@ +/* + * Geargrafx - PC Engine / TurboGrafx Emulator + * Copyright (C) 2024 Ignacio Sanchez + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/ + * + */ + +#ifndef HUC6280_REGISTERS_H +#define HUC6280_REGISTERS_H + +#include "common.h" + +class EightBitRegister +{ +public: + EightBitRegister() : m_value(0) { } + u8 GetValue() const; + void SetValue(u8 value); + void Increment(); + void Decrement(); + +private: + u8 m_value; +}; + +inline u8 EightBitRegister::GetValue() const +{ + return m_value; +} + +inline void EightBitRegister::SetValue(u8 value) +{ + m_value = value; +} + +inline void EightBitRegister::Increment() +{ + m_value++; +} + +inline void EightBitRegister::Decrement() +{ + m_value--; +} + +////////////////////////////////////////////////////////////////////////// + +class SixteenBitRegister +{ +public: + SixteenBitRegister() : m_value(0) { } + u8 GetLow() const; + u8 GetHigh() const; + u16 GetValue() const; + void SetLow(u8 low); + void SetHigh(u8 high); + void SetValue(u16 value); + void Increment(); + void Decrement(); + +private: + u16 m_value; +}; + +inline u8 SixteenBitRegister::GetLow() const +{ + return static_cast(m_value & 0x00FF); +} + +inline u8 SixteenBitRegister::GetHigh() const +{ + return static_cast((m_value >> 8) & 0x00FF); +} + +inline u16 SixteenBitRegister::GetValue() const +{ + return m_value; +} + +inline void SixteenBitRegister::SetLow(u8 low) +{ + m_value = (m_value & 0xFF00) | low; +} + +inline void SixteenBitRegister::SetHigh(u8 high) +{ + m_value = static_cast(high << 8) | (m_value & 0x00FF); +} + +inline void SixteenBitRegister::SetValue(u16 value) +{ + m_value = value; +} + +inline void SixteenBitRegister::Increment() +{ + m_value++; +} + +inline void SixteenBitRegister::Decrement() +{ + m_value--; +} + +#endif /* HUC6280_REGISTERS_H */ \ No newline at end of file diff --git a/src/huc6280_timer.cpp b/src/huc6280_timer.cpp new file mode 100644 index 0000000..8b69510 --- /dev/null +++ b/src/huc6280_timer.cpp @@ -0,0 +1,18 @@ +/* + * Geargrafx - PC Engine / TurboGrafx Emulator + * Copyright (C) 2024 Ignacio Sanchez + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/ + * + */ \ No newline at end of file diff --git a/src/huc6280_timer.h b/src/huc6280_timer.h new file mode 100644 index 0000000..6f3b11b --- /dev/null +++ b/src/huc6280_timer.h @@ -0,0 +1,23 @@ +/* + * Geargrafx - PC Engine / TurboGrafx Emulator + * Copyright (C) 2024 Ignacio Sanchez + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/ + * + */ + +#ifndef HUC6280_TIMER_H +#define HUC6280_TIMER_H + +#endif /* HUC6280_TIMER_H */ \ No newline at end of file diff --git a/src/huc6280_timing.h b/src/huc6280_timing.h new file mode 100644 index 0000000..47553e0 --- /dev/null +++ b/src/huc6280_timing.h @@ -0,0 +1,89 @@ +/* + * Geargrafx - PC Engine / TurboGrafx Emulator + * Copyright (C) 2024 Ignacio Sanchez + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/ + * + */ + +#ifndef HUC6280_TIMING_H +#define HUC6280_TIMING_H + +#include "common.h" + +const u8 k_opcode_tstates[256] = +{ +/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ +/* 0x00 */ 7, 6, 2, 8, 3, 3, 5, 5, 3, 2, 2, 2, 4, 4, 6, 6, +/* 0x10 */ 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 7, 7, +/* 0x20 */ 6, 6, 2, 8, 3, 3, 5, 5, 4, 2, 2, 2, 4, 4, 6, 6, +/* 0x30 */ 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 7, 7, +/* 0x40 */ 6, 6, 2, 8, 3, 3, 5, 5, 3, 2, 2, 2, 3, 4, 6, 6, +/* 0x50 */ 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 7, 7, +/* 0x60 */ 6, 6, 2, 8, 3, 3, 5, 5, 4, 2, 2, 2, 5, 4, 6, 6, +/* 0x70 */ 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 7, 7, +/* 0x80 */ 2, 6, 2, 6, 3, 3, 3, 3, 2, 2, 2, 2, 4, 4, 4, 4, +/* 0x90 */ 2, 6, 2, 6, 4, 4, 4, 4, 2, 5, 2, 5, 5, 5, 5, 5, +/* 0xA0 */ 2, 6, 2, 6, 3, 3, 3, 3, 2, 2, 2, 2, 4, 4, 4, 4, +/* 0xB0 */ 2, 5, 2, 5, 4, 4, 4, 4, 2, 4, 2, 4, 4, 4, 4, 4, +/* 0xC0 */ 2, 6, 2, 8, 3, 3, 5, 5, 2, 2, 2, 2, 4, 4, 6, 6, +/* 0xD0 */ 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 7, 7, +/* 0xE0 */ 2, 6, 2, 8, 3, 3, 5, 5, 2, 2, 2, 2, 4, 4, 6, 6, +/* 0xF0 */ 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 7, 7 +}; + +const u8 k_opcode_tstates_cross_paged[256] = +{ +/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ +/* 0x00 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/* 0x10 */ 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, +/* 0x20 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/* 0x30 */ 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, +/* 0x40 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/* 0x50 */ 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, +/* 0x60 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/* 0x70 */ 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, +/* 0x80 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/* 0x90 */ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/* 0xA0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/* 0xB0 */ 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, +/* 0xC0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/* 0xD0 */ 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, +/* 0xE0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/* 0xF0 */ 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0 +}; + +const u8 k_opcode_sizes[256] = +{ +/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ +/* 0x00 */ 1, 2, 0, 0, 2, 2, 2, 0, 1, 2, 1, 0, 3, 3, 3, 0, +/* 0x10 */ 2, 2, 0, 0, 2, 2, 2, 0, 1, 3, 1, 0, 3, 3, 3, 0, +/* 0x20 */ 3, 2, 0, 0, 2, 2, 2, 0, 1, 2, 1, 0, 3, 3, 3, 0, +/* 0x30 */ 2, 2, 0, 0, 2, 2, 2, 0, 1, 3, 1, 0, 3, 3, 3, 0, +/* 0x40 */ 1, 2, 0, 0, 2, 2, 2, 0, 1, 2, 1, 0, 3, 3, 3, 0, +/* 0x50 */ 2, 2, 0, 0, 2, 2, 2, 0, 1, 3, 1, 0, 3, 3, 3, 0, +/* 0x60 */ 1, 2, 0, 0, 2, 2, 2, 0, 1, 2, 1, 0, 3, 3, 3, 0, +/* 0x70 */ 2, 2, 0, 0, 2, 2, 2, 0, 1, 3, 1, 0, 3, 3, 3, 0, +/* 0x80 */ 2, 2, 0, 0, 2, 2, 2, 0, 1, 0, 1, 0, 3, 3, 3, 0, +/* 0x90 */ 2, 2, 0, 0, 2, 2, 2, 0, 1, 3, 1, 0, 0, 3, 0, 0, +/* 0xA0 */ 2, 2, 2, 0, 2, 2, 2, 0, 1, 2, 1, 0, 3, 3, 3, 0, +/* 0xB0 */ 2, 2, 0, 0, 2, 2, 2, 0, 1, 3, 1, 0, 3, 3, 3, 0, +/* 0xC0 */ 2, 2, 0, 0, 2, 2, 2, 0, 1, 2, 1, 0, 3, 3, 3, 0, +/* 0xD0 */ 2, 2, 0, 0, 2, 2, 2, 0, 1, 3, 1, 0, 3, 3, 3, 0, +/* 0xE0 */ 2, 2, 0, 0, 2, 2, 2, 0, 1, 2, 1, 0, 3, 3, 3, 0, +/* 0xF0 */ 2, 2, 0, 0, 2, 2, 2, 0, 1, 3, 1, 0, 3, 3, 3, 0 +}; + + +#endif /* HUC6280_TIMING_H */ \ No newline at end of file diff --git a/src/input.cpp b/src/input.cpp new file mode 100644 index 0000000..d246ed6 --- /dev/null +++ b/src/input.cpp @@ -0,0 +1,50 @@ +/* + * Geargrafx - PC Engine / TurboGrafx Emulator + * Copyright (C) 2024 Ignacio Sanchez + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/ + * + */ + +#include "input.h" +#include "common.h" + +Input::Input() +{ +} + +void Input::Init() +{ + Reset(); +} + +void Input::Reset() +{ +} + +void Input::KeyPressed(GG_Controllers controller, GG_Keys key) +{ +} + +void Input::KeyReleased(GG_Controllers controller, GG_Keys key) +{ +} + +// void Input::SaveState(std::ostream& stream) +// { +// } + +// void Input::LoadState(std::istream& stream) +// { +// } \ No newline at end of file diff --git a/src/input.h b/src/input.h new file mode 100644 index 0000000..cb9a34f --- /dev/null +++ b/src/input.h @@ -0,0 +1,40 @@ +/* + * Geargrafx - PC Engine / TurboGrafx Emulator + * Copyright (C) 2024 Ignacio Sanchez + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/ + * + */ + +#ifndef INPUT_H +#define INPUT_H + +#include "common.h" + +class Input +{ +public: + Input(); + void Init(); + void Reset(); + void KeyPressed(GG_Controllers controller, GG_Keys key); + void KeyReleased(GG_Controllers controller, GG_Keys key); + // void SaveState(std::ostream& stream); + // void LoadState(std::istream& stream); + +private: + +}; + +#endif /* INPUT_H */ \ No newline at end of file diff --git a/src/memory.cpp b/src/memory.cpp new file mode 100644 index 0000000..11b4d5b --- /dev/null +++ b/src/memory.cpp @@ -0,0 +1,18 @@ +/* + * Geargrafx - PC Engine / TurboGrafx Emulator + * Copyright (C) 2024 Ignacio Sanchez + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/ + * + */ diff --git a/src/memory.h b/src/memory.h new file mode 100644 index 0000000..89ccae5 --- /dev/null +++ b/src/memory.h @@ -0,0 +1,23 @@ +/* + * Geargrafx - PC Engine / TurboGrafx Emulator + * Copyright (C) 2024 Ignacio Sanchez + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/ + * + */ + +#ifndef MEMORY_H +#define MEMORY_H + +#endif /* MEMORY_H */ \ No newline at end of file diff --git a/src/types.h b/src/types.h index 4fa07de..1001ba2 100644 --- a/src/types.h +++ b/src/types.h @@ -31,4 +31,45 @@ typedef int32_t s32; typedef uint64_t u64; typedef int64_t s64; +struct GG_Runtime_Info +{ + int screen_width; + int screen_height; +}; + +struct GG_Color +{ + u8 red; + u8 green; + u8 blue; +}; + +enum GG_Pixel_Format +{ + GG_PIXEL_RGB565, + GG_PIXEL_RGB555, + GG_PIXEL_RGB888, + GG_PIXEL_BGR565, + GG_PIXEL_BGR555, + GG_PIXEL_BGR888 +}; + +enum GG_Keys +{ + GG_KEY_UP, + GG_KEY_DOWN, + GG_KEY_LEFT, + GG_KEY_RIGHT, + GG_KEY_1, + GG_KEY_2, + GG_KEY_RUN, + GG_KEY_SELECT +}; + +enum GG_Controllers +{ + GG_CONTROLLER_1, + GG_CONTROLLER_2 +}; + #endif /* TYPES_H */ \ No newline at end of file