From 8c4a9be8d3a1472c7ebe4c6bcf11e89bbf4e7eaf Mon Sep 17 00:00:00 2001 From: Ignacio Sanchez Gines <863613+drhelius@users.noreply.github.com> Date: Wed, 7 Aug 2024 21:05:02 +0200 Subject: [PATCH] Improve vce and vdc --- platforms/shared/desktop/emu.cpp | 3 + platforms/shared/desktop/gui.cpp | 47 +-- .../shared/desktop/gui_debug_huc6260.cpp | 20 +- .../shared/desktop/gui_debug_huc6270.cpp | 39 +- platforms/shared/desktop/renderer.cpp | 4 +- src/geargrafx_core.cpp | 39 +- src/huc6260.cpp | 129 ++++++- src/huc6260.h | 33 +- src/huc6260_inline.h | 39 +- src/huc6270.cpp | 339 +++++++++--------- src/huc6270.h | 72 ++-- src/huc6270_defines.h | 2 +- src/huc6270_inline.h | 12 +- 13 files changed, 449 insertions(+), 329 deletions(-) diff --git a/platforms/shared/desktop/emu.cpp b/platforms/shared/desktop/emu.cpp index 1855b12..30b228b 100644 --- a/platforms/shared/desktop/emu.cpp +++ b/platforms/shared/desktop/emu.cpp @@ -445,6 +445,9 @@ static void update_debug_background_buffer(void) int color = ((byte1 >> (7 - tile_x)) & 0x01) | (((byte2 >> (7 - tile_x)) & 0x01) << 1) | (((byte3 >> (7 - tile_x)) & 0x01) << 2) | (((byte4 >> (7 - tile_x)) & 0x01) << 3); + if (color == 0) + color_table = 0; + u16 color_value = huc6260->GetColorTable()[(color_table * 16) + color]; // convert to 8 bit color diff --git a/platforms/shared/desktop/gui.cpp b/platforms/shared/desktop/gui.cpp index 6a58608..30c2bb3 100644 --- a/platforms/shared/desktop/gui.cpp +++ b/platforms/shared/desktop/gui.cpp @@ -43,7 +43,6 @@ static u32 status_message_start_time = 0; static u32 status_message_duration = 0; static void main_window(void); static void push_recent_rom(std::string path); -//static Cartridge::CartridgeRegions get_region(int index); static void show_status_message(void); void gui_init(void) @@ -229,12 +228,19 @@ void gui_load_rom(const char* path) if (config_emulator.start_paused) { emu_pause(); - + for (int i=0; i < (GG_MAX_RESOLUTION_WIDTH * GG_MAX_RESOLUTION_HEIGHT); i++) { emu_frame_buffer[i] = 0; } } + + if (!emu_is_empty()) + { + char title[256]; + sprintf(title, "%s %s - %s", GEARGRAFX_TITLE, GEARGRAFX_VERSION, emu_get_core()->GetCartridge()->GetFileName()); + application_update_title(title); + } } void gui_set_status_message(const char* message, u32 milliseconds) @@ -364,28 +370,6 @@ static void main_window(void) } } - - - -// static GC_Color color_float_to_int(ImVec4 color) -// { -// GC_Color ret; -// ret.red = (u8)floor(color.x >= 1.0 ? 255.0 : color.x * 256.0); -// ret.green = (u8)floor(color.y >= 1.0 ? 255.0 : color.y * 256.0); -// ret.blue = (u8)floor(color.z >= 1.0 ? 255.0 : color.z * 256.0); -// return ret; -// } - -// static ImVec4 color_int_to_float(GC_Color color) -// { -// ImVec4 ret; -// ret.w = 0; -// ret.x = (1.0f / 255.0f) * color.red; -// ret.y = (1.0f / 255.0f) * color.green; -// ret.z = (1.0f / 255.0f) * color.blue; -// return ret; -// } - static void push_recent_rom(std::string path) { int slot = 0; @@ -407,21 +391,6 @@ static void push_recent_rom(std::string path) config_emulator.recent_roms[0] = path; } -// static Cartridge::CartridgeRegions get_region(int index) -// { -// switch (index) -// { -// case 0: -// return Cartridge::CartridgeUnknownRegion; -// case 1: -// return Cartridge::CartridgeNTSC; -// case 2: -// return Cartridge::CartridgePAL; -// default: -// return Cartridge::CartridgeUnknownRegion; -// } -// } - static void show_status_message(void) { if (status_message_active) diff --git a/platforms/shared/desktop/gui_debug_huc6260.cpp b/platforms/shared/desktop/gui_debug_huc6260.cpp index 18e5a3b..66afba8 100644 --- a/platforms/shared/desktop/gui_debug_huc6260.cpp +++ b/platforms/shared/desktop/gui_debug_huc6260.cpp @@ -42,20 +42,30 @@ void gui_debug_window_huc6260_info(void) HuC6260* huc6260 = core->GetHuC6260(); HuC6260::HuC6260_State* huc6260_state = huc6260->GetState(); - ImGui::TextColored(magenta, "SPEED"); ImGui::SameLine(); + ImGui::TextColored(magenta, "SPEED "); ImGui::SameLine(); const char* speed[] = { "10.8 MHz", "7.16 MHz", "5.36 MHz" }; ImGui::TextColored(green, "%s", speed[huc6260->GetSpeed()]); - ImGui::TextColored(magenta, "CR "); ImGui::SameLine(); + ImGui::TextColored(magenta, "SIGNALS "); ImGui::SameLine(); + ImGui::TextColored(*huc6260_state->HSYNC ? gray : orange, "HSYNC"); ImGui::SameLine(); + ImGui::TextColored(*huc6260_state->VSYNC ? gray : orange, "VSYNC"); + + ImGui::TextColored(magenta, "HPOS,VPOS"); ImGui::SameLine(); + ImGui::TextColored(white, "%03X,%03X (%03d,%03d)", *huc6260_state->HPOS, *huc6260_state->VPOS, *huc6260_state->HPOS, *huc6260_state->VPOS); + + ImGui::TextColored(magenta, "PIXEL "); ImGui::SameLine(); + ImGui::TextColored(white, "%0X", *huc6260_state->PIXEL_INDEX); + + ImGui::TextColored(magenta, "CTRL REG "); ImGui::SameLine(); ImGui::Text("$%02X (" BYTE_TO_BINARY_PATTERN_SPACED ")", *huc6260_state->CR, BYTE_TO_BINARY(*huc6260_state->CR)); - ImGui::TextColored(magenta, "CTA "); ImGui::SameLine(); + ImGui::TextColored(magenta, "CTA "); ImGui::SameLine(); ImGui::Text("$%04X (" BYTE_TO_BINARY_PATTERN_SPACED " " BYTE_TO_BINARY_PATTERN_SPACED ")", *huc6260_state->CTA, BYTE_TO_BINARY(*huc6260_state->CTA >> 8), BYTE_TO_BINARY(*huc6260_state->CTA & 0xFF)); - ImGui::TextColored(magenta, "BLUR "); ImGui::SameLine(); + ImGui::TextColored(magenta, "BLUR "); ImGui::SameLine(); ImGui::TextColored(IsSetBit(*huc6260_state->CR, 2) ? green : gray, "%s", IsSetBit(*huc6260_state->CR, 2) ? "ON" : "OFF"); - ImGui::TextColored(magenta, "B&W "); ImGui::SameLine(); + ImGui::TextColored(magenta, "B&W "); ImGui::SameLine(); ImGui::TextColored(IsSetBit(*huc6260_state->CR, 7) ? green : gray, "%s", IsSetBit(*huc6260_state->CR, 7) ? "ON" : "OFF"); ImGui::PopFont(); diff --git a/platforms/shared/desktop/gui_debug_huc6270.cpp b/platforms/shared/desktop/gui_debug_huc6270.cpp index d6d75e9..341a2dc 100644 --- a/platforms/shared/desktop/gui_debug_huc6270.cpp +++ b/platforms/shared/desktop/gui_debug_huc6270.cpp @@ -46,12 +46,19 @@ void gui_debug_window_huc6270_info(void) const char* speed[] = { "10.8 MHz", "7.16 MHz", "5.36 MHz" }; ImGui::TextColored(green, "%s", speed[huc6260->GetSpeed()]); - ImGui::TextColored(magenta, "SCANLINE"); ImGui::SameLine(); - ImGui::TextColored(orange, "%s", k_scanline_sections[*huc6270_state->SCANLINE_SECTION]); - ImGui::TextColored(magenta, "X,Y "); ImGui::SameLine(); ImGui::TextColored(white, "%03X,%03X (%03d,%03d)", *huc6270_state->HPOS, *huc6270_state->VPOS, *huc6270_state->HPOS, *huc6270_state->VPOS); + const char* h_states[] = { "HDS", "HDW", "HDE", "HSW" }; + HuC6270::HuC6270_Horizontal_State* h_state = huc6270_state->H_STATE; + ImGui::TextColored(magenta, "H STATE "); ImGui::SameLine(); + ImGui::TextColored(orange, "%s", h_states[*h_state]); + + const char* v_states[] = { "VSW", "VDS", "VDW", "VCR" }; + HuC6270::HuC6270_Vertical_State* v_state = huc6270_state->V_STATE; + ImGui::TextColored(magenta, "V STATE "); ImGui::SameLine(); + ImGui::TextColored(orange, "%s", v_states[*v_state]); + ImGui::NewLine(); ImGui::TextColored(cyan, "CONTROL REGISTRY"); ImGui::Separator(); ImGui::TextColored(magenta, "BACKGRND"); ImGui::SameLine(); @@ -102,6 +109,18 @@ void gui_debug_window_huc6270_info(void) ImGui::TextColored(magenta, "CG MODE "); ImGui::SameLine(); ImGui::TextColored(white, "%d", (huc6270_state->R[HUC6270_REG_MWR] >> 7) & 0x01); + ImGui::TextColored(magenta, "HDS"); ImGui::SameLine(); + ImGui::TextColored(white, "%02X", (huc6270_state->R[HUC6270_REG_HSR] >> 8) & 0x7F); ImGui::SameLine(); + + ImGui::TextColored(magenta, "HDW"); ImGui::SameLine(); + ImGui::TextColored(white, "%02X", huc6270_state->R[HUC6270_REG_HDR] & 0x7F); ImGui::SameLine(); + + ImGui::TextColored(magenta, "HDE"); ImGui::SameLine(); + ImGui::TextColored(white, "%02X", (huc6270_state->R[HUC6270_REG_HDR] >> 8) & 0x7F); ImGui::SameLine(); + + ImGui::TextColored(magenta, "HSW"); ImGui::SameLine(); + ImGui::TextColored(white, "%02X", huc6270_state->R[HUC6270_REG_HSR] & 0x1F); + ImGui::TextColored(magenta, "VSW"); ImGui::SameLine(); ImGui::TextColored(white, "%02X", huc6270_state->R[HUC6270_REG_VPR] & 0x1F); ImGui::SameLine(); @@ -109,23 +128,11 @@ void gui_debug_window_huc6270_info(void) ImGui::TextColored(white, "%02X", (huc6270_state->R[HUC6270_REG_VPR] >> 8) & 0xFF); ImGui::SameLine(); ImGui::TextColored(magenta, "VDW"); ImGui::SameLine(); - ImGui::TextColored(white, "%02X", huc6270_state->R[HUC6270_REG_VDR] & 0x1FF); ImGui::SameLine(); + ImGui::TextColored(white, "%02X", huc6270_state->R[HUC6270_REG_VDW] & 0x1FF); ImGui::SameLine(); ImGui::TextColored(magenta, "VCR"); ImGui::SameLine(); ImGui::TextColored(white, "%02X", huc6270_state->R[HUC6270_REG_VCR] & 0xFF); - ImGui::TextColored(magenta, "HSW"); ImGui::SameLine(); - ImGui::TextColored(white, "%02X", huc6270_state->R[HUC6270_REG_HSR] & 0x1F); ImGui::SameLine(); - - ImGui::TextColored(magenta, "HDS"); ImGui::SameLine(); - ImGui::TextColored(white, "%02X", (huc6270_state->R[HUC6270_REG_HSR] >> 8) & 0x7F); ImGui::SameLine(); - - ImGui::TextColored(magenta, "HDW"); ImGui::SameLine(); - ImGui::TextColored(white, "%02X", huc6270_state->R[HUC6270_REG_HDR] & 0x7F); ImGui::SameLine(); - - ImGui::TextColored(magenta, "HDE"); ImGui::SameLine(); - ImGui::TextColored(white, "%02X", (huc6270_state->R[HUC6270_REG_HDR] >> 8) & 0x7F); - ImGui::NewLine(); ImGui::TextColored(cyan, "SCROLLING"); ImGui::Separator(); ImGui::TextColored(magenta, "X,Y "); ImGui::SameLine(); diff --git a/platforms/shared/desktop/renderer.cpp b/platforms/shared/desktop/renderer.cpp index cbb15bd..93b4505 100644 --- a/platforms/shared/desktop/renderer.cpp +++ b/platforms/shared/desktop/renderer.cpp @@ -71,11 +71,11 @@ void renderer_init(void) } renderer_glew_version = (const char*)glewGetString(GLEW_VERSION); - Debug("Using GLEW %s", renderer_glew_version); + Log("Using GLEW %s", renderer_glew_version); #endif renderer_opengl_version = (const char*)glGetString(GL_VERSION); - Debug("Using OpenGL %s", renderer_opengl_version); + Log("Using OpenGL %s", renderer_opengl_version); init_ogl_gui(); init_ogl_emu(); diff --git a/src/geargrafx_core.cpp b/src/geargrafx_core.cpp index 4bd0f63..4028b2f 100644 --- a/src/geargrafx_core.cpp +++ b/src/geargrafx_core.cpp @@ -55,7 +55,8 @@ GeargrafxCore::~GeargrafxCore() void GeargrafxCore::Init(GG_Pixel_Format pixel_format) { - Debug("--== %s %s by Ignacio Sanchez ==--", GEARGRAFX_TITLE, GEARGRAFX_VERSION); + Log("Loading %s core %s ...", GEARGRAFX_TITLE, GEARGRAFX_VERSION); + Log("by Ignacio Sanchez"); srand((unsigned int)time(NULL)); @@ -69,8 +70,8 @@ void GeargrafxCore::Init(GG_Pixel_Format pixel_format) m_cartridge->Init(); m_memory->Init(); - m_huc6260->Init(); - m_huc6270->Init(m_huc6260, pixel_format); + m_huc6260->Init(pixel_format); + m_huc6270->Init(); m_huc6280->Init(m_memory, m_huc6270); m_audio->Init(); m_input->Init(); @@ -90,28 +91,25 @@ bool GeargrafxCore::RunToVBlank(u8* frame_buffer, s16* sample_buffer, int* sampl } #endif + m_huc6260->SetBuffer(frame_buffer); bool instruction_completed = false; bool stop = false; - const int timer_divider = 3; - const int audio_divider = 6; + int failsafe_clocks = 0; int huc6280_divider = m_huc6280->IsHighSpeed() ? 3 : 12; - int huc6260_divider = m_huc6260->GetClockDivider(); do { - m_clock++; instruction_completed = false; + if (m_clock % 3 == 0) + m_huc6280->ClockTimer(); + if (m_clock % huc6280_divider == 0) instruction_completed = m_huc6280->Clock(); - if (m_clock % timer_divider == 0) - m_huc6280->ClockTimer(); - - if (m_clock % huc6260_divider == 0) - stop = m_huc6270->Clock(frame_buffer); + stop = m_huc6260->Clock(); - if (m_clock % audio_divider == 0) + if (m_clock % 6 == 0) m_audio->Clock(); #ifndef GG_DISABLE_DISASSEMBLER @@ -125,11 +123,14 @@ bool GeargrafxCore::RunToVBlank(u8* frame_buffer, s16* sample_buffer, int* sampl stop = true; #endif // Failsafe: if the emulator is running too long, stop it - // if (m_clock >= 89683) - // { - // m_clock -= 89683; + // if (failsafe_clocks >= 150000) // stop = true; - // } + + m_clock++; + failsafe_clocks++; + + if ( m_clock == 12) + m_clock = 0; } while (!stop); @@ -234,9 +235,9 @@ void GeargrafxCore::KeyReleased(GG_Controllers controller, GG_Keys key) void GeargrafxCore::Pause(bool paused) { if (!m_paused && paused) - Log("Geargrafx PAUSED"); + Debug("Core paused"); else if (m_paused && !paused) - Log("Geargrafx RESUMED"); + Debug("Core resumed"); m_paused = paused; } diff --git a/src/huc6260.cpp b/src/huc6260.cpp index d70cfc2..c00c0bd 100644 --- a/src/huc6260.cpp +++ b/src/huc6260.cpp @@ -22,13 +22,16 @@ HuC6260::HuC6260(HuC6270* huc6270) { m_huc6270 = huc6270; - m_control_register = 0; - m_color_table_address = 0; - m_speed = HuC6260_SPEED_5_36_MHZ; - m_clock_divider = 4; - InitPointer(m_color_table); + m_pixel_format = GG_PIXEL_RGB888; m_state.CR = &m_control_register; m_state.CTA = &m_color_table_address; + m_state.HPOS = &m_hpos; + m_state.VPOS = &m_vpos; + m_state.PIXEL_INDEX = &m_pixel_index; + m_state.HSYNC = &m_hsync; + m_state.VSYNC = &m_vsync; + InitPointer(m_color_table); + InitPointer(m_frame_buffer); } HuC6260::~HuC6260() @@ -36,24 +39,133 @@ HuC6260::~HuC6260() SafeDeleteArray(m_color_table); } -void HuC6260::Init() +void HuC6260::Init(GG_Pixel_Format pixel_format) { + m_pixel_format = pixel_format; m_color_table = new u16[512]; + + InitPalettes(); Reset(); } +void HuC6260::InitPalettes() +{ + for (int i = 0; i < 512; i++) + { + u8 green = ((i >> 6) & 0x07) * 255 / 7; + u8 red = ((i >> 3) & 0x07) * 255 / 7; + u8 blue = (i & 0x07) * 255 / 7; + m_rgb888_palette[i][0] = red; + m_rgb888_palette[i][1] = green; + m_rgb888_palette[i][2] = blue; + m_bgr888_palette[i][0] = blue; + m_bgr888_palette[i][1] = green; + m_bgr888_palette[i][2] = red; + + green = ((i >> 6) & 0x07) * 31 / 7; + red = ((i >> 3) & 0x07) * 63 / 7; + blue = (i & 0x07) * 31 / 7; + m_rgb565_palette[i] = (red << 11) | (green << 5) | blue; + m_bgr565_palette[i] = (blue << 11) | (green << 5) | red; + + green = ((i >> 6) & 0x07) * 31 / 7; + red = ((i >> 3) & 0x07) * 31 / 7; + blue = (i & 0x07) * 31 / 7; + m_rgb555_palette[i] = (red << 10) | (green << 5) | blue; + m_bgr555_palette[i] = (blue << 10) | (green << 5) | red; + } +} + void HuC6260::Reset() { m_control_register = 0; m_color_table_address = 0; m_speed = HuC6260_SPEED_5_36_MHZ; m_clock_divider = 4; + m_hpos = 0; + m_vpos = 0; + m_pixel_index = 0; + m_pixel_clock = 0; + m_hsync = true; + m_vsync = true; + for (int i = 0; i < 512; i++) { m_color_table[i] = ((i ^ (i >> 3)) & 1) ? 0x000 : 0x1FF; } } +bool HuC6260::Clock() +{ + bool frame_ready = false; + + if (m_pixel_clock == 0) + { + bool active = false; + u16 pixel = m_huc6270->Clock(&active); + + if (active) + { + if ((pixel & 0x10F) == 0) + pixel = 0; + + u16 color = m_color_table[pixel]; + + u8 red = m_rgb888_palette[color][0]; + u8 green = m_rgb888_palette[color][1]; + u8 blue = m_rgb888_palette[color][2]; + + if (m_pixel_index >= (256 * 240)) + Debug("Pixel Index: %d\n", m_pixel_index); + else + { + m_frame_buffer[((m_pixel_index) * 3) + 0] = red; + m_frame_buffer[((m_pixel_index) * 3) + 1] = green; + m_frame_buffer[((m_pixel_index) * 3) + 2] = blue; + } + + m_pixel_index++; + } + } + + m_pixel_clock = (m_pixel_clock + 1) % m_clock_divider; + m_hpos = (m_hpos + 1) % HUC6260_LINE_LENGTH; + + switch (m_hpos) + { + case HUC6260_HSYNC_START_HPOS: + // Start of horizontal sync + m_hsync = false; + m_huc6270->SetHSync(false); + break; + case HUC6260_HSYNC_END_HPOS: + // End of horizontal sync + m_hsync = true; + m_huc6270->SetHSync(true); + m_vpos = (m_vpos + 1) % HUC6260_LINES; + m_pixel_clock = 0; + break; + case HUC6260_VSYNC_HPOS: + // Start of vertical sync + if (m_vpos == HUC6260_VSYNC_START_VPOS) + { + m_vsync = false; + m_huc6270->SetVSync(false); + } + // End of vertical sync + else if (m_vpos == HUC6260_VSYNC_END_VPOS) + { + m_pixel_index = 0; + frame_ready = true; + m_vsync = true; + m_huc6270->SetVSync(true); + } + break; + } + + return frame_ready; +} + HuC6260::HuC6260_State* HuC6260::GetState() { return &m_state; @@ -72,4 +184,9 @@ int HuC6260::GetClockDivider() u16* HuC6260::GetColorTable() { return m_color_table; +} + +void HuC6260::SetBuffer(u8* frame_buffer) +{ + m_frame_buffer = frame_buffer; } \ No newline at end of file diff --git a/src/huc6260.h b/src/huc6260.h index 464b95d..e93e613 100644 --- a/src/huc6260.h +++ b/src/huc6260.h @@ -22,6 +22,15 @@ #include "common.h" +#define HUC6260_LINE_LENGTH 1365 +#define HUC6260_LINES 263 +#define HUC6260_HSYNC_LENGTH 237 +#define HUC6260_HSYNC_START_HPOS (HUC6260_LINE_LENGTH - HUC6260_HSYNC_LENGTH) +#define HUC6260_HSYNC_END_HPOS 0 +#define HUC6260_VSYNC_HPOS (HUC6260_HSYNC_START_HPOS + 30) +#define HUC6260_VSYNC_START_VPOS (HUC6260_LINES - 4) +#define HUC6260_VSYNC_END_VPOS (HUC6260_LINES - 1) + class HuC6270; class HuC6260 @@ -31,6 +40,11 @@ class HuC6260 { u8* CR; u16* CTA; + int* HPOS; + int* VPOS; + int* PIXEL_INDEX; + bool* HSYNC; + bool* VSYNC; }; enum HuC6260_Speed @@ -43,14 +57,17 @@ class HuC6260 public: HuC6260(HuC6270* huc6270); ~HuC6260(); - void Init(); + void Init(GG_Pixel_Format pixel_format = GG_PIXEL_RGB888); + void InitPalettes(); void Reset(); + bool Clock(); u8 ReadRegister(u32 address); void WriteRegister(u32 address, u8 value); HuC6260_State* GetState(); HuC6260_Speed GetSpeed(); int GetClockDivider(); u16* GetColorTable(); + void SetBuffer(u8* frame_buffer); private: HuC6270* m_huc6270; @@ -60,6 +77,20 @@ class HuC6260 HuC6260_Speed m_speed; int m_clock_divider; u16* m_color_table; + u8* m_frame_buffer; + int m_hpos; + int m_vpos; + int m_pixel_index; + int m_pixel_clock; + bool m_hsync; + bool m_vsync; + GG_Pixel_Format m_pixel_format; + u8 m_rgb888_palette[512][3]; + u8 m_bgr888_palette[512][3]; + u16 m_rgb565_palette[512]; + u16 m_bgr565_palette[512]; + u16 m_rgb555_palette[512]; + u16 m_bgr555_palette[512]; }; #include "huc6260_inline.h" diff --git a/src/huc6260_inline.h b/src/huc6260_inline.h index 335c16a..b54c00c 100644 --- a/src/huc6260_inline.h +++ b/src/huc6260_inline.h @@ -25,51 +25,32 @@ inline u8 HuC6260::ReadRegister(u32 address) { - // Debug("HuC6260 register read at %06X", address); + u8 ret = 0xFF; switch (address & 0x07) { - case 0: - // Control register - // Debug("HuC6260 Read control register"); - return 0xFF; - case 2: - // Color table address LSB - // Debug("HuC6260 Read color table address LSB"); - return 0xFF; - case 3: - // Color table address MSB - // Debug("HuC6260 Read color table address MSB"); - return 0xFF; case 4: // Color table data LSB - // Debug("HuC6260 Read color table data LSB"); - return m_color_table[m_color_table_address] & 0xFF; + ret = m_color_table[m_color_table_address] & 0xFF; + break; case 5: - { // Color table data MSB - // Debug("HuC6260 Read color table data MSB"); - u8 ret = 0xFE | ((m_color_table[m_color_table_address] >> 8) & 0x01); + ret = 0xFE | ((m_color_table[m_color_table_address] >> 8) & 0x01); m_color_table_address = (m_color_table_address + 1) & 0x01FF; - return ret; - } - default: - // Not used - Debug("HuC6260 Read unused register"); - return 0xFF; + break; } + + return ret; } inline void HuC6260::WriteRegister(u32 address, u8 value) { - // Debug("HuC6260 register write at %06X, value=%02X", address, value); - switch (address & 0x07) { case 0: // Control register m_control_register = value; - // Debug("HuC6260 Write control register: %02X", m_control_register); + switch (m_control_register & 0x03) { case 0: @@ -92,21 +73,17 @@ inline void HuC6260::WriteRegister(u32 address, u8 value) case 2: // Color table address LSB m_color_table_address = (m_color_table_address & 0x0100) | value; - // Debug("HuC6260 Write color table address LSB: %04X", m_color_table_address); break; case 3: // Color table address MSB m_color_table_address = (m_color_table_address & 0x00FF) | ((value & 0x01) << 8); - // Debug("HuC6260 Write color table address MSB: %04X", m_color_table_address); break; case 4: // Color table data LSB - // Debug("HuC6260 Write color table data LSB: %02X", value); m_color_table[m_color_table_address] = (m_color_table[m_color_table_address] & 0x0100) | value; break; case 5: // Color table data MSB - // Debug("HuC6260 Write color table data MSB: %02X", value); m_color_table[m_color_table_address] = (m_color_table[m_color_table_address] & 0x00FF) | ((value & 0x01) << 8); m_color_table_address = (m_color_table_address + 1) & 0x01FF; break; diff --git a/src/huc6270.cpp b/src/huc6270.cpp index 457651c..6aec37b 100644 --- a/src/huc6270.cpp +++ b/src/huc6270.cpp @@ -24,33 +24,18 @@ HuC6270::HuC6270(HuC6280* huC6280) { m_huc6280 = huC6280; - InitPointer(m_huc6260); InitPointer(m_vram); InitPointer(m_sat); - m_address_register = 0; - m_status_register = 0; - m_read_buffer = 0; - m_hpos = 0; - m_vpos = 0; - m_raster_line = 0; - m_scanline_section = 0; - m_trigger_sat_transfer = false; - m_auto_sat_transfer = false; - m_pixel_format = GG_PIXEL_RGB888; - InitPointer(m_frame_buffer); - - for (int i = 0; i < 20; i++) - { - m_register[i] = 0; - } - m_state.AR = &m_address_register; m_state.SR = &m_status_register; m_state.R = m_register; m_state.READ_BUFFER = &m_read_buffer; m_state.HPOS = &m_hpos; m_state.VPOS = &m_vpos; - m_state.SCANLINE_SECTION = &m_scanline_section; + m_state.HSYNC = &m_hsync; + m_state.VSYNC = &m_vsync; + m_state.V_STATE = &m_v_state; + m_state.H_STATE = &m_h_state; } HuC6270::~HuC6270() @@ -59,10 +44,8 @@ HuC6270::~HuC6270() SafeDeleteArray(m_sat); } -void HuC6270::Init(HuC6260* huc6260, GG_Pixel_Format pixel_format) +void HuC6270::Init() { - m_huc6260 = huc6260; - m_pixel_format = pixel_format; m_vram = new u16[HUC6270_VRAM_SIZE]; m_sat = new u16[HUC6270_SAT_SIZE]; Reset(); @@ -70,28 +53,33 @@ void HuC6270::Init(HuC6260* huc6260, GG_Pixel_Format pixel_format) void HuC6270::Reset() { + for (int i = 0; i < 20; i++) + { + m_register[i] = 0; + } + + m_register[HUC6270_REG_HSR] = 0x0202; + m_register[HUC6270_REG_HDR] = 0x041f; + m_register[HUC6270_REG_VPR] = 0x0f02; + m_register[HUC6270_REG_VDW] = 0x00ef; + m_register[HUC6270_REG_VCR] = 0x0004; + m_address_register = 0; m_status_register = 0; m_read_buffer = 0xFFFF; m_hpos = 0; m_vpos = 0; m_raster_line = 0; - m_scanline_section = 0; m_trigger_sat_transfer = false; m_auto_sat_transfer = false; - - m_line_events.vint = false; - m_line_events.hint = false; - m_line_events.render = false; - - m_timing[TIMING_VINT] = 256; - m_timing[TIMING_HINT] = 256; - m_timing[TIMING_RENDER] = 256; - - for (int i = 0; i < 20; i++) - { - m_register[i] = 0; - } + m_latched_byr = 0; + m_hsync = true; + m_vsync = true; + m_v_state = HuC6270_VERTICAL_STATE_VSW; + m_h_state = HuC6270_HORIZONTAL_STATE_HDS; + m_clocks_to_next_v_state = 0;//3; + m_clocks_to_next_h_state = 0;//24; + m_hds_clocks = (std::max(((m_register[HUC6270_REG_HSR] >> 8) & 0x7F), 2) + 1) << 3; for (int i = 0; i < HUC6270_VRAM_SIZE; i++) { @@ -104,41 +92,111 @@ void HuC6270::Reset() } } -bool HuC6270::Clock(u8* frame_buffer) +u16 HuC6270::Clock(bool* active) { - m_frame_buffer = frame_buffer; - bool frame_ready = false; - int vsw = m_register[HUC6270_REG_VPR] & 0x1F; - int vds = m_register[HUC6270_REG_VPR] >> 8; - int vdw = m_register[HUC6270_REG_VDR] & 0x1FF; - int vcr = m_register[HUC6270_REG_VCR] & 0xFF; - - if (m_vpos < HUC6270_ACTIVE_DISPLAY_START) - { - //Debug("HuC6270 during top blanking"); - m_scanline_section = SCANLINE_BOTTOM_BLANKING; - } - else if (m_vpos < HUC6270_BOTTOM_BLANKING_START) - { - //Debug("HuC6270 during active display"); - m_scanline_section = SCANLINE_ACTIVE; - } - else if (m_vpos < HUC6270_SYNC_START) + *active = false; + u16 pixel = 0; + + if (m_v_state == HuC6270_VERTICAL_STATE_VDW && m_h_state == HuC6270_HORIZONTAL_STATE_HDW) { - //Debug("HuC6270 during bottom blanking"); - m_scanline_section = SCANLINE_BOTTOM_BLANKING; + *active = true; + + int screen_reg = (m_register[HUC6270_REG_MWR] >> 4) & 0x07; + int screen_size_x = k_scren_size_x[screen_reg]; + int screen_size_x_pixels = screen_size_x * 8; + int screen_size_y = k_scren_size_y[screen_reg]; + int screen_size_y_pixels = screen_size_y * 8; + + int scroll_x = m_register[HUC6270_REG_BXR]; + + int bg_y = m_latched_byr; + bg_y %= screen_size_y_pixels; + int bat_offset = (bg_y / 8) * screen_size_x; + + int bg_x = (m_hpos - m_hds_clocks) + scroll_x; + + bg_x %= screen_size_x_pixels; + + u16 bat_entry = m_vram[bat_offset + (bg_x / 8)]; + int tile_index = bat_entry & 0x07FF; + int color_table = (bat_entry >> 12) & 0x0F; + int tile_data = tile_index * 16; + int tile_x = (bg_x % 8); + int tile_y = (bg_y % 8); + int line_start_a = (tile_data + tile_y); + int line_start_b = (tile_data + tile_y + 8); + u8 byte1 = m_vram[line_start_a] & 0xFF; + u8 byte2 = m_vram[line_start_a] >> 8; + u8 byte3 = m_vram[line_start_b] & 0xFF; + u8 byte4 = m_vram[line_start_b] >> 8; + + pixel = color_table << 4; + + pixel |= ((byte1 >> (7 - tile_x)) & 0x01) | (((byte2 >> (7 - tile_x)) & 0x01) << 1) | (((byte3 >> (7 - tile_x)) & 0x01) << 2) | (((byte4 >> (7 - tile_x)) & 0x01) << 3); } - else + + m_hpos++; + + m_clocks_to_next_h_state--; + while (m_clocks_to_next_h_state == 0) + NextHorizontalState(); + + return pixel; +} + +void HuC6270::SetHSync(bool active) +{ + if (m_hsync != active) { - //Debug("HuC6270 during sync"); - m_scanline_section = SCANLINE_SYNC; + // High to low + if (!active) + { + if (m_register[HUC6270_REG_CR] & HUC6270_CONTROL_SCANLINE) + { + if (m_register[HUC6270_REG_RCR] == m_raster_line) + { + m_status_register |= HUC6270_STATUS_SCANLINE; + m_huc6280->AssertIRQ1(true); + } + } + } + // Low to high + else + { + m_h_state = HuC6270_HORIZONTAL_STATE_HSW; + m_clocks_to_next_h_state = 0; + m_clocks_to_next_v_state--; + m_latched_byr++; + m_raster_line++; + + if ((m_clocks_to_next_v_state == 2) && (m_v_state == HuC6270_VERTICAL_STATE_VDS)) + { + m_raster_line = 64; + } + + while (m_clocks_to_next_h_state == 0) + NextHorizontalState(); + } } - ///// VINT ///// - if (!m_line_events.vint && (m_hpos >= m_timing[TIMING_VINT])) + m_hsync = active; +} + +void HuC6270::SetVSync(bool active) +{ + if (m_vsync != active) { - m_line_events.vint = true; - if (m_vpos == HUC6270_BOTTOM_BLANKING_START) + // High to low + if (!active) + { + m_v_state = HuC6270_VERTICAL_STATE_VCR; + m_clocks_to_next_v_state = 0; + + while ( m_clocks_to_next_v_state == 0 ) + NextVerticalState(); + } + // Low to high + else { if (m_register[HUC6270_REG_CR] & HUC6270_CONTROL_VBLANK) { @@ -167,63 +225,7 @@ bool HuC6270::Clock(u8* frame_buffer) } } - ///// HINT ///// - if (!m_line_events.hint && (m_hpos >= m_timing[TIMING_HINT])) - { - m_line_events.hint = true; - //if (m_scanline_section == SCANLINE_ACTIVE) - { - if (m_register[HUC6270_REG_CR] & HUC6270_CONTROL_SCANLINE) - { - if (m_register[HUC6270_REG_RCR] == m_raster_line) - { - m_status_register |= HUC6270_STATUS_SCANLINE; - m_huc6280->AssertIRQ1(true); - } - } - } - } - - ///// RENDER ///// - if (!m_line_events.render && (m_hpos >= m_timing[TIMING_RENDER])) - { - m_line_events.render = true; - int raster_start = vsw + vds; - int raster_end = raster_start + vdw + 1; - if ((m_vpos >= raster_start) && (m_vpos < raster_end)) - { - RenderLine(m_vpos - raster_start); - } - } - - m_hpos++; - - ///// END OF LINE ///// - if (m_hpos > 341) - { - m_hpos = 0; - m_vpos++; - m_raster_line++; - - int raster_reset = vsw + vds; - - if (m_vpos == raster_reset) - { - m_raster_line = 64; - } - - if (m_vpos > HUC6270_LINES) - { - m_vpos = 0; - frame_ready = true; - } - - m_line_events.vint = false; - m_line_events.hint = false; - m_line_events.render = false; - } - - return frame_ready; + m_vsync = active; } HuC6270::HuC6270_State* HuC6270::GetState() @@ -241,55 +243,58 @@ u16* HuC6270::GetSAT() return m_sat; } -void HuC6270::RenderLine(int y) +void HuC6270::NextVerticalState() { - if (y >= GG_MAX_RESOLUTION_HEIGHT) + switch (m_v_state) { - return; + case HuC6270_VERTICAL_STATE_VSW: + m_v_state = HuC6270_VERTICAL_STATE_VDS; + m_clocks_to_next_v_state = ((m_register[HUC6270_REG_VPR] >> 8) & 0xFF) + 2; + break; + case HuC6270_VERTICAL_STATE_VDS: + m_v_state = HuC6270_VERTICAL_STATE_VDW; + m_clocks_to_next_v_state = (m_register[HUC6270_REG_VDW] & 0x1FF) + 1; + m_latched_byr = m_register[HUC6270_REG_BYR]; + break; + case HuC6270_VERTICAL_STATE_VDW: + m_v_state = HuC6270_VERTICAL_STATE_VCR; + m_clocks_to_next_v_state = m_register[HUC6270_REG_VCR] & 0xFF; + break; + case HuC6270_VERTICAL_STATE_VCR: + m_v_state = HuC6270_VERTICAL_STATE_VSW; + m_clocks_to_next_v_state = (m_register[HUC6270_REG_VPR] & 0x1F) + 1; + m_vpos = 0; + break; } +} - int screen_reg = (m_register[HUC6270_REG_MWR] >> 4) & 0x07; - int screen_size_x = k_scren_size_x[screen_reg]; - int screen_size_x_pixels = screen_size_x * 8; - int screen_size_y = k_scren_size_y[screen_reg]; - int screen_size_y_pixels = screen_size_y * 8; - int buffer_line_offset = y * GG_MAX_RESOLUTION_WIDTH; - - int scroll_x = m_register[HUC6270_REG_BXR]; - int scroll_y = m_register[HUC6270_REG_BYR]; - - int bg_y = y + scroll_y; - bg_y %= screen_size_y_pixels; - int bat_offset = (bg_y / 8) * screen_size_x; - - for (int line_x = 0; line_x < GG_MAX_RESOLUTION_WIDTH; line_x++) +void HuC6270::NextHorizontalState() +{ + switch (m_h_state) { - int bg_x = line_x + scroll_x; - bg_x %= screen_size_x_pixels; - - u16 bat_entry = m_vram[bat_offset + (bg_x / 8)]; - int tile_index = bat_entry & 0x07FF; - int color_table = (bat_entry >> 12) & 0x0F; - int tile_data = tile_index * 16; - int tile_x = (bg_x % 8); - int tile_y = (bg_y % 8); - int line_start_a = (tile_data + tile_y); - int line_start_b = (tile_data + tile_y + 8); - u8 byte1 = m_vram[line_start_a] & 0xFF; - u8 byte2 = m_vram[line_start_a] >> 8; - u8 byte3 = m_vram[line_start_b] & 0xFF; - u8 byte4 = m_vram[line_start_b] >> 8; - - int color = ((byte1 >> (7 - tile_x)) & 0x01) | (((byte2 >> (7 - tile_x)) & 0x01) << 1) | (((byte3 >> (7 - tile_x)) & 0x01) << 2) | (((byte4 >> (7 - tile_x)) & 0x01) << 3); - - u16 color_value = m_huc6260->GetColorTable()[(color_table * 16) + color]; - int blue = (color_value & 0x07) * 255 / 7; - int red = ((color_value >> 3) & 0x07) * 255 / 7; - int green = ((color_value >> 6) & 0x07) * 255 / 7; - - int index = (buffer_line_offset + line_x) * 3; - m_frame_buffer[index] = red; - m_frame_buffer[index + 1] = green; - m_frame_buffer[index + 2] = blue; + case HuC6270_HORIZONTAL_STATE_HDS: + m_h_state = HuC6270_HORIZONTAL_STATE_HDW; + m_clocks_to_next_h_state = ((m_register[HUC6270_REG_HDR] & 0x7F) + 1) << 3; + break; + case HuC6270_HORIZONTAL_STATE_HDW: + m_h_state = HuC6270_HORIZONTAL_STATE_HDE; + m_clocks_to_next_h_state = (((m_register[HUC6270_REG_HDR] >> 8) & 0x7F) + 1) << 3; + break; + case HuC6270_HORIZONTAL_STATE_HDE: + m_h_state = HuC6270_HORIZONTAL_STATE_HSW; + m_clocks_to_next_h_state = ((m_register[HUC6270_REG_HSR] & 0x1F) + 1) << 3; + break; + case HuC6270_HORIZONTAL_STATE_HSW: + m_h_state = HuC6270_HORIZONTAL_STATE_HDS; + m_clocks_to_next_h_state = (std::max(((m_register[HUC6270_REG_HSR] >> 8) & 0x7F), 2) + 1) << 3; + m_hds_clocks = m_clocks_to_next_h_state; + + m_hpos = 0; + m_vpos++; + + while (m_clocks_to_next_v_state == 0) + NextVerticalState(); + + break; } -} \ No newline at end of file +} diff --git a/src/huc6270.h b/src/huc6270.h index 021b28b..c1a0d2e 100644 --- a/src/huc6270.h +++ b/src/huc6270.h @@ -24,11 +24,26 @@ #include "common.h" class HuC6280; -class HuC6260; class HuC6270 { public: + enum HuC6270_Vertical_State + { + HuC6270_VERTICAL_STATE_VSW, + HuC6270_VERTICAL_STATE_VDS, + HuC6270_VERTICAL_STATE_VDW, + HuC6270_VERTICAL_STATE_VCR + }; + + enum HuC6270_Horizontal_State + { + HuC6270_HORIZONTAL_STATE_HDS, + HuC6270_HORIZONTAL_STATE_HDW, + HuC6270_HORIZONTAL_STATE_HDE, + HuC6270_HORIZONTAL_STATE_HSW + }; + struct HuC6270_State { u8* AR; @@ -37,15 +52,20 @@ class HuC6270 u16* READ_BUFFER; int* HPOS; int* VPOS; - int* SCANLINE_SECTION; + bool* HSYNC; + bool* VSYNC; + HuC6270_Vertical_State* V_STATE; + HuC6270_Horizontal_State* H_STATE; }; public: HuC6270(HuC6280* huC6280); ~HuC6270(); - void Init(HuC6260* huc6260, GG_Pixel_Format pixel_format = GG_PIXEL_RGB888); + void Init(); void Reset(); - bool Clock(u8* frame_buffer); + u16 Clock(bool* active); + void SetHSync(bool active); + void SetVSync(bool active); u8 ReadRegister(u32 address); void WriteRegister(u32 address, u8 value); HuC6270_State* GetState(); @@ -53,32 +73,7 @@ class HuC6270 u16* GetSAT(); private: - - enum Timing - { - TIMING_VINT, - TIMING_HINT, - TIMING_RENDER, - TIMING_COUNT - }; - - enum Scanline_Section - { - SCANLINE_TOP_BLANKING, - SCANLINE_ACTIVE, - SCANLINE_BOTTOM_BLANKING, - SCANLINE_SYNC - }; - - struct Line_Events - { - bool vint; - bool hint; - bool render; - }; - HuC6280* m_huc6280; - HuC6260* m_huc6260; HuC6270_State m_state; u16* m_vram; u8 m_address_register; @@ -89,16 +84,20 @@ class HuC6270 int m_hpos; int m_vpos; int m_raster_line; - int m_scanline_section; bool m_trigger_sat_transfer; bool m_auto_sat_transfer; - GG_Pixel_Format m_pixel_format; - u8* m_frame_buffer; - Line_Events m_line_events; - int m_timing[TIMING_COUNT]; + u8 m_latched_byr; + bool m_hsync; + bool m_vsync; + HuC6270_Vertical_State m_v_state; + HuC6270_Horizontal_State m_h_state; + int m_clocks_to_next_v_state; + int m_clocks_to_next_h_state; + int m_hds_clocks; private: - void RenderLine(int y); + void NextVerticalState(); + void NextHorizontalState(); }; static const u16 k_register_mask[20] = { @@ -123,9 +122,6 @@ static const char* const k_register_names[20] = { "HSR", "HDR", "VPR", "VDR", "VCR", "DCR", "SOUR", "DESR", "LENR", "DVSSR" }; -static const char* const k_scanline_sections[] = { - "TOP BLANKING", "ACTIVE", "BOTTOM BLANKING", "SYNC" }; - #include "huc6270_inline.h" #endif /* HUC6270_H */ \ No newline at end of file diff --git a/src/huc6270_defines.h b/src/huc6270_defines.h index a38b643..3c62558 100644 --- a/src/huc6270_defines.h +++ b/src/huc6270_defines.h @@ -67,7 +67,7 @@ #define HUC6270_REG_HSR 0x0A #define HUC6270_REG_HDR 0x0B #define HUC6270_REG_VPR 0x0C -#define HUC6270_REG_VDR 0x0D +#define HUC6270_REG_VDW 0x0D #define HUC6270_REG_VCR 0x0E #define HUC6270_REG_DCR 0x0F #define HUC6270_REG_SOUR 0x10 diff --git a/src/huc6270_inline.h b/src/huc6270_inline.h index 50da88b..64efc76 100644 --- a/src/huc6270_inline.h +++ b/src/huc6270_inline.h @@ -47,7 +47,7 @@ inline u8 HuC6270::ReadRegister(u32 address) } else { - Debug("HuC6270 invalid read data register: %02X", m_address_register); + //Debug("HuC6270 invalid read data register: %02X", m_address_register); return m_register[HUC6270_REG_VWR] & 0xFF; } break; @@ -65,12 +65,12 @@ inline u8 HuC6270::ReadRegister(u32 address) } else { - Debug("HuC6270 invalid read data register: %02X", m_address_register); + //Debug("HuC6270 invalid read data register: %02X", m_address_register); return m_register[HUC6270_REG_VWR] & 0xFF; } break; default: - Debug("HuC6270 invalid read at %06X", address); + //Debug("HuC6270 invalid read at %06X", address); return 0x00; } } @@ -124,6 +124,10 @@ inline void HuC6270::WriteRegister(u32 address, u8 value) m_register[HUC6270_REG_MAWR] = m_register[HUC6270_REG_MAWR] + increment; } break; + // 0x08 + case HUC6270_REG_BYR: + m_latched_byr = m_register[HUC6270_REG_BYR]; + break; // 0x12 case HUC6270_REG_LENR: // Debug("HuC6270 write LENR (%s) %02X: %04X", msb ? "MSB" : "LSB", value, m_register[m_address_register]); @@ -165,7 +169,7 @@ inline void HuC6270::WriteRegister(u32 address, u8 value) break; } default: - Debug("HuC6270 invalid write at %06X, value=%02X", address, value); + //Debug("HuC6270 invalid write at %06X, value=%02X", address, value); break; } }