From 13b65e4e50fffd7c1870cd9d3c967e280645a1da Mon Sep 17 00:00:00 2001 From: ferris Date: Sat, 18 May 2013 16:15:29 +0200 Subject: [PATCH] Major top-level cleanup and updated GLVideoDriver --- GLVideoDriver.cpp | 100 ++++++++++------ GLVideoDriver.h | 10 +- Main.cpp | 297 +++++++++++++++++++++++++--------------------- 3 files changed, 231 insertions(+), 176 deletions(-) diff --git a/GLVideoDriver.cpp b/GLVideoDriver.cpp index fef8093..d761474 100644 --- a/GLVideoDriver.cpp +++ b/GLVideoDriver.cpp @@ -2,61 +2,70 @@ GLVideoDriver::GLVideoDriver(Viewport *viewport) { - this->viewport = (Win32Viewport *)viewport; - outputHandle = this->viewport->GetHandle(); - SetupDC(); - rc = wglCreateContext(dc); - wglMakeCurrent(dc, rc); + this->viewport = nullptr; + outputHandle = NULL; + dc = NULL; + rc = NULL; - glGenTextures(1, &textureHandle); - glBindTexture(GL_TEXTURE_2D, textureHandle); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glBindTexture(GL_TEXTURE_2D, 0); + SetViewport(viewport); } GLVideoDriver::~GLVideoDriver() { wglMakeCurrent(NULL, NULL); wglDeleteContext(rc); - ReleaseDC(outputHandle, dc); + destroyDC(); } -void GLVideoDriver::SetOutput(int width, int height, const unsigned int *data) +void GLVideoDriver::SetViewport(Viewport *viewport) { - auto newOutputHandle = viewport->GetHandle(); - if (newOutputHandle != outputHandle) + wglMakeCurrent(NULL, NULL); + if (this->viewport) destroyDC(); + this->viewport = (Win32Viewport *)viewport; + if (viewport) { - wglMakeCurrent(NULL, NULL); - ReleaseDC(outputHandle, dc); - outputHandle = newOutputHandle; - SetupDC(); + createDC(); + if (rc == NULL) createRC(); } - wglMakeCurrent(dc, rc); +} - glViewport(0, 0, viewport->GetWidth(), viewport->GetHeight()); +void GLVideoDriver::SetOutput(int width, int height, const unsigned int *data) +{ + if (viewport) + { + auto newOutputHandle = viewport->GetHandle(); + if (newOutputHandle != outputHandle) + { + destroyDC(); + createDC(); + } + wglMakeCurrent(dc, rc); - glBindTexture(GL_TEXTURE_2D, textureHandle); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, data); - glEnable(GL_TEXTURE_2D); - glBegin(GL_QUADS); - glTexCoord2i(0, 1); - glVertex2i(-1, -1); - glTexCoord2i(1, 1); - glVertex2i( 1, -1); - glTexCoord2i(1, 0); - glVertex2i( 1, 1); - glTexCoord2i(0, 0); - glVertex2i(-1, 1); - glEnd(); - glDisable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, 0); + glViewport(0, 0, viewport->GetWidth(), viewport->GetHeight()); + + glBindTexture(GL_TEXTURE_2D, textureHandle); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, data); + glEnable(GL_TEXTURE_2D); + glBegin(GL_QUADS); + glTexCoord2i(0, 1); + glVertex2i(-1, -1); + glTexCoord2i(1, 1); + glVertex2i( 1, -1); + glTexCoord2i(1, 0); + glVertex2i( 1, 1); + glTexCoord2i(0, 0); + glVertex2i(-1, 1); + glEnd(); + glDisable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, 0); - SwapBuffers(dc); + SwapBuffers(dc); + } } -void GLVideoDriver::SetupDC() +void GLVideoDriver::createDC() { + outputHandle = viewport->GetHandle(); dc = GetDC(outputHandle); PIXELFORMATDESCRIPTOR pfd = { @@ -78,3 +87,20 @@ void GLVideoDriver::SetupDC() }; SetPixelFormat(dc, ChoosePixelFormat(dc, &pfd), &pfd); } + +void GLVideoDriver::destroyDC() +{ + ReleaseDC(outputHandle, dc); +} + +void GLVideoDriver::createRC() +{ + rc = wglCreateContext(dc); + wglMakeCurrent(dc, rc); + + glGenTextures(1, &textureHandle); + glBindTexture(GL_TEXTURE_2D, textureHandle); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glBindTexture(GL_TEXTURE_2D, 0); +} diff --git a/GLVideoDriver.h b/GLVideoDriver.h index 584de49..424c762 100644 --- a/GLVideoDriver.h +++ b/GLVideoDriver.h @@ -7,17 +7,21 @@ #include #include -// TODO: This should be separated. class GLVideoDriver : public IVideoDriver { public: - GLVideoDriver(Viewport *viewport); + GLVideoDriver(Viewport *viewport = nullptr); virtual ~GLVideoDriver(); + virtual void SetViewport(Viewport *viewport); + virtual void SetOutput(int width, int height, const unsigned int *data); private: - void SetupDC(); + void createDC(); + void destroyDC(); + + void createRC(); Win32Viewport *viewport; HWND outputHandle; diff --git a/Main.cpp b/Main.cpp index 81172e1..2127169 100644 --- a/Main.cpp +++ b/Main.cpp @@ -10,12 +10,126 @@ int Main(const List& arguments) { Chip8 chip8; - auto running = true; + auto videoDriver = new GLVideoDriver(); + chip8.SetVideoDriver(videoDriver); + + auto audioDriver = new DirectSoundAudioDriver(); + chip8.SetAudioDriver(audioDriver); + + const int numLatencies = 8; + const int latencies[] = { 20, 40, 60, 80, 100, 200, 500, 1000 }; + + const int numZooms = 4; + const int zooms[] = { 4, 8, 16, 32 }; + + const int numSpeeds = 10; + const int speeds[] = { 1, 2, 5, 10, 20, 50, 100, 200, 500, 1000 }; Config config(Directory::GetApplicationDirectory() + "\\config.cfg"); + auto running = true; + auto window = Window::Create("Vip8"); - Key keys[] = { Key::X, Key::Number1, Key::Number2, Key::Number3, Key::Q, Key::W, Key::E, Key::A, Key::S, Key::D, Key::Z, Key::C, Key::Number4, Key::R, Key::F, Key::V }; + auto menu = Menu::Create(); + auto fileMenu = Menu::Create("File"); + auto fileLoadRomImage = MenuItem::Create("Load ROM Image..."); + fileMenu->AddChild(fileLoadRomImage); + fileMenu->AddSeparator(); + auto fileExit = MenuItem::Create("Exit"); + fileMenu->AddChild(fileExit); + menu->AddChild(fileMenu); + auto systemMenu = Menu::Create("System"); + auto systemReset = MenuItem::Create("Reset"); + systemMenu->AddChild(systemReset); + systemMenu->AddSeparator(); + auto systemAudioMenu = Menu::Create("Audio"); + auto systemAudioEnabled = MenuItem::Create("Enabled"); + systemAudioEnabled->SetToggleEnabled(true); + systemAudioMenu->AddChild(systemAudioEnabled); + auto systemAudioLatencyMenu = Menu::Create("Latency"); + List systemAudioLatencyItems; + for (int i = 0; i < numLatencies; i++) + { + auto latency = latencies[i]; + auto item = MenuItem::Create(String(latency) + " ms"); + systemAudioLatencyMenu->AddChild(item); + systemAudioLatencyItems.Add(item); + } + systemAudioMenu->AddChild(systemAudioLatencyMenu); + systemMenu->AddChild(systemAudioMenu); + auto systemVideoMenu = Menu::Create("Video"); + auto systemVideoZoomMenu = Menu::Create("Zoom"); + List systemVideoZoomItems; + for (int i = 0; i < numZooms; i++) + { + auto zoom = zooms[i]; + auto item = MenuItem::Create(String(zoom) + "x" + zoom); + systemVideoZoomMenu->AddChild(item); + systemVideoZoomItems.Add(item); + } + systemVideoMenu->AddChild(systemVideoZoomMenu); + systemMenu->AddChild(systemVideoMenu); + auto systemSpeedMenu = Menu::Create("Speed"); + List systemSpeedItems; + for (int i = 0; i < numSpeeds; i++) + { + auto speed = speeds[i]; + auto item = MenuItem::Create(String(speed) + " instruction" + (speed > 1 ? "s" : "") + "/frame"); + systemSpeedMenu->AddChild(item); + systemSpeedItems.Add(item); + } + systemMenu->AddChild(systemSpeedMenu); + menu->AddChild(systemMenu); + auto helpMenu = Menu::Create("Help"); + auto helpAbout = MenuItem::Create("About..."); + helpAbout->Click += [&] { MessageWindow::Info(window, "Vip8 - A Chip-8 emulator"); }; + helpMenu->AddChild(helpAbout); + menu->AddChild(helpMenu); + window->SetMenu(menu); + auto viewport = Viewport::Create(); + window->SetContent(viewport); + + auto loadAndStartRomImage = [&] (const String& fileName) + { + try + { + chip8.LoadRom(File::ReadAllBytes(fileName)); + chip8.Start(); + } + catch (const Exception& e) + { + MessageWindow::Error(e.GetMsg()); + } + }; + + auto reflectAudioEnabled = [&] + { + config.AudioEnabled = systemAudioEnabled->GetChecked(); + audioDriver->SetEnabled(config.AudioEnabled); + }; + + auto reflectLatencyIndex = [&] + { + auto latency = latencies[config.AudioLatencyIndex]; + audioDriver->SetLatencyMs(latency); + for (int i = 0; i < systemAudioLatencyItems.Count(); i++) systemAudioLatencyItems[i]->SetChecked(i == config.AudioLatencyIndex); + }; + + auto reflectZoomIndex = [&] + { + auto zoom = zooms[config.VideoZoomIndex]; + window->SetDesiredSize(chip8.GetOutputWidth() * zoom, chip8.GetOutputHeight() * zoom); + for (int i = 0; i < systemVideoZoomItems.Count(); i++) systemVideoZoomItems[i]->SetChecked(i == config.VideoZoomIndex); + }; + + auto reflectSpeedIndex = [&] + { + auto speed = speeds[config.SystemSpeedIndex]; + chip8.SetSpeed(speed); + for (int i = 0; i < systemSpeedItems.Count(); i++) systemSpeedItems[i]->SetChecked(i == config.SystemSpeedIndex); + }; + + const Key keys[] = { Key::X, Key::Number1, Key::Number2, Key::Number3, Key::Q, Key::W, Key::E, Key::A, Key::S, Key::D, Key::Z, Key::C, Key::Number4, Key::R, Key::F, Key::V }; window->KeyDown += [&] (Key key) { if (key == Key::Escape) @@ -26,7 +140,11 @@ int Main(const List& arguments) { for (int i = 0; i < 16; i++) { - if (key == keys[i]) chip8.SetInput(i, true); + if (key == keys[i]) + { + chip8.SetInput(i, true); + break; + } } } }; @@ -34,27 +152,16 @@ int Main(const List& arguments) { for (int i = 0; i < 16; i++) { - if (key == keys[i]) chip8.SetInput(i, false); + if (key == keys[i]) + { + chip8.SetInput(i, false); + break; + } } }; - window->Closing += [&] { running = false; }; - auto loadAndStartRomImage = [&] (const String& fileName) - { - try - { - chip8.LoadRom(File::ReadAllBytes(fileName)); - chip8.Start(); - } - catch (const Exception& e) - { - MessageWindow::Error(e.GetMsg()); - } - }; + window->Closing += [&] { running = false; }; - auto menu = Menu::Create(); - auto fileMenu = Menu::Create("File"); - auto fileLoadRomImage = MenuItem::Create("Load ROM Image..."); fileLoadRomImage->Click += [&] { auto fileName = DialogWindow::OpenFile(window, "Load ROM Image"); @@ -64,132 +171,55 @@ int Main(const List& arguments) loadAndStartRomImage(fileName); } }; - fileMenu->AddChild(fileLoadRomImage); - fileMenu->AddSeparator(); - auto fileExit = MenuItem::Create("Exit"); + fileExit->Click += [&] { running = false; }; - fileMenu->AddChild(fileExit); - menu->AddChild(fileMenu); - auto systemMenu = Menu::Create("System"); - auto systemReset = MenuItem::Create("Reset"); systemReset->Click += [&] { chip8.Reset(); if (chip8.HasRom()) chip8.Start(); }; - systemMenu->AddChild(systemReset); - systemMenu->AddSeparator(); - - auto audioDriver = new DirectSoundAudioDriver(); - chip8.SetAudioDriver(audioDriver); - auto systemAudioMenu = Menu::Create("Audio"); - auto systemAudioEnabled = MenuItem::Create("Enabled"); - systemAudioEnabled->SetChecked(config.AudioEnabled); - systemAudioEnabled->SetToggleEnabled(true); - auto reflectAudioEnabled = [&] - { - config.AudioEnabled = systemAudioEnabled->GetChecked(); - audioDriver->SetEnabled(config.AudioEnabled); - }; systemAudioEnabled->CheckedChanged += reflectAudioEnabled; - reflectAudioEnabled(); - systemAudioMenu->AddChild(systemAudioEnabled); - auto systemAudioLatencyMenu = Menu::Create("Latency"); - const int numLatencies = 8; - const int latencies[] = { 20, 40, 60, 80, 100, 200, 500, 1000 }; - List systemAudioLatencyItems; - auto reflectLatencyIndex = [&] - { - auto latency = latencies[config.AudioLatencyIndex]; - audioDriver->SetLatencyMs(latency); - for (int i = 0; i < systemAudioLatencyItems.Count(); i++) systemAudioLatencyItems[i]->SetChecked(i == config.AudioLatencyIndex); - }; - for (int i = 0; i < numLatencies; i++) + + for (int i = 0; i < systemAudioLatencyItems.Count(); i++) { - auto latency = latencies[i]; - auto item = MenuItem::Create(String(latency) + " ms"); + auto item = systemAudioLatencyItems[i]; item->Click += [&, i] { config.AudioLatencyIndex = i; reflectLatencyIndex(); }; - systemAudioLatencyMenu->AddChild(item); - systemAudioLatencyItems.Add(item); } - reflectLatencyIndex(); - systemAudioMenu->AddChild(systemAudioLatencyMenu); - systemMenu->AddChild(systemAudioMenu); - - auto systemVideoMenu = Menu::Create("Video"); - auto systemVideoZoomMenu = Menu::Create("Zoom"); - const int numZooms = 4; - const int zooms[] = { 4, 8, 16, 32 }; - List systemVideoZoomItems; - auto reflectZoomIndex = [&] - { - auto zoom = zooms[config.VideoZoomIndex]; - window->SetDesiredSize(chip8.GetOutputWidth() * zoom, chip8.GetOutputHeight() * zoom); - for (int i = 0; i < systemVideoZoomItems.Count(); i++) systemVideoZoomItems[i]->SetChecked(i == config.VideoZoomIndex); - }; - for (int i = 0; i < numZooms; i++) + + for (int i = 0; i < systemVideoZoomItems.Count(); i++) { - auto zoom = zooms[i]; - auto item = MenuItem::Create(String(zoom) + "x" + zoom); + auto item = systemVideoZoomItems[i]; item->Click += [&, i] { config.VideoZoomIndex = i; reflectZoomIndex(); }; - systemVideoZoomMenu->AddChild(item); - systemVideoZoomItems.Add(item); } - reflectZoomIndex(); - systemVideoMenu->AddChild(systemVideoZoomMenu); - systemMenu->AddChild(systemVideoMenu); - auto systemSpeedMenu = Menu::Create("Speed"); - const int numSpeeds = 10; - const int speeds[] = { 1, 2, 5, 10, 20, 50, 100, 200, 500, 1000 }; - List systemSpeedItems; - auto reflectSpeedIndex = [&] - { - auto speed = speeds[config.SystemSpeedIndex]; - chip8.SetSpeed(speed); - for (int i = 0; i < systemSpeedItems.Count(); i++) systemSpeedItems[i]->SetChecked(i == config.SystemSpeedIndex); - }; - for (int i = 0; i < numSpeeds; i++) + for (int i = 0; i < systemSpeedItems.Count(); i++) { - auto speed = speeds[i]; - auto item = MenuItem::Create(String(speed) + " instruction" + (speed > 1 ? "s" : "") + "/frame"); + auto item = systemSpeedItems[i]; item->Click += [&, i] { config.SystemSpeedIndex = i; reflectSpeedIndex(); }; - systemSpeedMenu->AddChild(item); - systemSpeedItems.Add(item); } - reflectSpeedIndex(); - systemMenu->AddChild(systemSpeedMenu); - - menu->AddChild(systemMenu); - - auto helpMenu = Menu::Create("Help"); - auto helpAbout = MenuItem::Create("About..."); - helpAbout->Click += [&] { MessageWindow::Info(window, "Vip8 - A Chip-8 emulator"); }; - helpMenu->AddChild(helpAbout); - menu->AddChild(helpMenu); - window->SetMenu(menu); - - auto viewport = Viewport::Create(); - window->SetContent(viewport); - auto videoDriver = new GLVideoDriver(viewport); - chip8.SetVideoDriver(videoDriver); + videoDriver->SetViewport(viewport); - if (arguments.Count()) loadAndStartRomImage(arguments[0]); + systemAudioEnabled->SetChecked(config.AudioEnabled); + reflectAudioEnabled(); + reflectLatencyIndex(); + reflectZoomIndex(); + reflectSpeedIndex(); + if (arguments.Count() == 1) loadAndStartRomImage(arguments[0]); while (running) { @@ -207,30 +237,25 @@ int Main(const List& arguments) config.Save(); delete window; - delete menu; - delete fileMenu; - delete fileLoadRomImage; - delete fileExit; - - delete systemMenu; - delete systemReset; - - delete systemAudioMenu; - delete systemAudioEnabled; - delete systemAudioLatencyMenu; - for (int i = 0; i < systemAudioLatencyItems.Count(); i++) delete systemAudioLatencyItems[i]; - - delete systemVideoMenu; - delete systemVideoZoomMenu; - for (int i = 0; i < systemVideoZoomItems.Count(); i++) delete systemVideoZoomItems[i]; - - delete systemSpeedMenu; - for (int i = 0; i < systemSpeedItems.Count(); i++) delete systemSpeedItems[i]; - - delete helpMenu; - delete helpAbout; + delete menu; + delete fileMenu; + delete fileLoadRomImage; + delete fileExit; + delete systemMenu; + delete systemReset; + delete systemAudioMenu; + delete systemAudioEnabled; + delete systemAudioLatencyMenu; + for (int i = 0; i < systemAudioLatencyItems.Count(); i++) delete systemAudioLatencyItems[i]; + delete systemVideoMenu; + delete systemVideoZoomMenu; + for (int i = 0; i < systemVideoZoomItems.Count(); i++) delete systemVideoZoomItems[i]; + delete systemSpeedMenu; + for (int i = 0; i < systemSpeedItems.Count(); i++) delete systemSpeedItems[i]; + delete helpMenu; + delete helpAbout; + delete viewport; - delete viewport; delete videoDriver; delete audioDriver; }