Have a basic status output for the VM.

master
Zed A. Shaw 2 months ago
parent 5efa8be1c4
commit fc8729930a
  1. 12
      assets/config.json
  2. 10
      assets/shaders.json
  3. 18
      assets/shaders/ui_error.frag
  4. 29
      assets/shaders/ui_shader.frag
  5. 12
      assets/shaders/ui_shape_shader.frag
  6. BIN
      assets/sounds/blank.ogg
  7. BIN
      assets/sounds/clicker_bark.ogg
  8. BIN
      assets/sounds/ui_click.ogg
  9. BIN
      assets/sounds/ui_hover.ogg
  10. BIN
      assets/text.otf
  11. 8
      meson.build
  12. 1
      src/code_panel.cpp
  13. 1
      src/code_panel.hpp
  14. 38
      src/display.cpp
  15. 10
      src/display.hpp
  16. 4
      src/main.cpp
  17. 2
      src/meson.build
  18. 52
      src/status_panel.cpp
  19. 15
      src/status_panel.hpp

@ -0,0 +1,12 @@
{
"sounds": {
"ui_click": "assets/sounds/ui_click.ogg",
"ui_hover": "assets/sounds/ui_hover.ogg",
"blank": "assets/sounds/blank.ogg"
},
"sprites": {
},
"graphics": {
"smooth_textures": false
}
}

@ -0,0 +1,10 @@
{
"ui_shader": {
"file_name": "assets/shaders/ui_shader.frag",
"type": "fragment"
},
"ERROR": {
"file_name": "assets/shaders/ui_error.frag",
"type": "fragment"
}
}

@ -0,0 +1,18 @@
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_duration;
uniform float u_time;
uniform float u_time_end;
uniform sampler2D texture;
uniform bool is_shape;
void main() {
if(is_shape) {
vec4 color = vec4(1.0, 0.0, 0.0, 1.0);
gl_FragColor = gl_Color * color;
} else {
vec4 pixel = texture2D(texture, gl_TexCoord[0].xy);
vec4 color = vec4(1.0, 0.0, 0.0, 1.0);
gl_FragColor = gl_Color * color * pixel;
}
}

@ -0,0 +1,29 @@
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_duration;
uniform float u_time;
uniform float u_time_end;
uniform sampler2D texture;
uniform bool is_shape;
uniform bool hover;
vec4 blink() {
if(hover) {
return vec4(0.95, 0.95, 1.0, 1.0);
} else {
float tick = (u_time_end - u_time) / u_duration;
float blink = mix(0.5, 1.0, tick);
return vec4(blink, blink, blink, 1.0);
}
}
void main() {
vec4 color = blink();
if(!is_shape) {
vec4 pixel = texture2D(texture, gl_TexCoord[0].xy);
color *= pixel;
}
gl_FragColor = gl_Color * color;
}

@ -0,0 +1,12 @@
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_duration;
uniform float u_time;
uniform float u_time_end;
void main() {
float tick = (u_time_end - u_time) / u_duration;
float blink = smoothstep(1.0, 0.5, tick);
vec4 color = vec4(blink, blink, blink, 1.0);
gl_FragColor = gl_Color * color;
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

@ -72,13 +72,14 @@ sfml_network = subproject('sfml').get_variable('sfml_network_dep')
sfml_system = subproject('sfml').get_variable('sfml_system_dep') sfml_system = subproject('sfml').get_variable('sfml_system_dep')
sfml_window = subproject('sfml').get_variable('sfml_window_dep') sfml_window = subproject('sfml').get_variable('sfml_window_dep')
lel_guecs = subproject('lel-guecs').get_variable('lel_guecs_dep') lel_guecs = subproject('lel-guecs').get_variable('lel_guecs_dep')
lel_guecs_sfml = subproject('lel-guecs').get_variable('lel_guecs_sfml_dep')
dependencies += [ dependencies += [
fmt, freetype2, fmt, freetype2,
flac, ogg, vorbis, vorbisfile, vorbisenc, flac, ogg, vorbis, vorbisfile, vorbisenc,
sfml_audio, sfml_graphics, sfml_audio, sfml_graphics,
sfml_network, sfml_system, sfml_network, sfml_system,
sfml_window, lel_guecs sfml_window, lel_guecs, lel_guecs_sfml
] ]
inc_dirs = include_directories('src') inc_dirs = include_directories('src')
@ -95,11 +96,10 @@ b8rk_dep = declare_dependency(
link_with: b8rk_lib, link_with: b8rk_lib,
include_directories: inc_dirs) include_directories: inc_dirs)
dependencies += [b8rk_dep]
executable('b8rk', executable('b8rk',
[ 'src/main.cpp' ], [ 'src/main.cpp' ],
cpp_args: cpp_args, cpp_args: cpp_args,
link_args: link_args, link_args: link_args,
include_directories: inc_dirs,
override_options: exe_defaults, override_options: exe_defaults,
dependencies: dependencies) dependencies: dependencies + [b8rk_dep])

@ -0,0 +1 @@
#include "code_panel.hpp"

@ -0,0 +1 @@
#pragma once

@ -4,10 +4,10 @@
#include <SFML/Audio.hpp> #include <SFML/Audio.hpp>
Display::Display(sf::RenderWindow& window, sf::Vector2f pos, sf::Vector2f size) : Display::Display(sf::RenderWindow& window, sf::Vector2f pos, sf::Vector2f size) :
window(window) $window(window)
{ {
float border_width = 2.0f; float border_width = 2.0f;
texture.setSmooth(false); $texture.setSmooth(false);
float ratio = (size.x - border_width * 2) / 64.0f; float ratio = (size.x - border_width * 2) / 64.0f;
// rectangle position doesn't include the border because everyone hates humans // rectangle position doesn't include the border because everyone hates humans
@ -15,20 +15,22 @@ Display::Display(sf::RenderWindow& window, sf::Vector2f pos, sf::Vector2f size)
sf::Vector2f scale{ratio, ratio}; sf::Vector2f scale{ratio, ratio};
// have to move in one more time for the border we just moved in for the border // have to move in one more time for the border we just moved in for the border
texture_sprite.setPosition({border_pos.x + border_width, border_pos.y + border_width}); $texture_sprite.setPosition({border_pos.x + border_width, border_pos.y + border_width});
texture_sprite.setScale(scale); $texture_sprite.setScale(scale);
border.setPosition(border_pos); $border.setPosition(border_pos);
border.setSize({64 * ratio, 32 * ratio}); $border.setSize({64 * ratio, 32 * ratio});
border.setOutlineColor({30,20,50,255}); $border.setOutlineColor({30,20,50,255});
border.setOutlineThickness(border_width); $border.setOutlineThickness(border_width);
border.setFillColor({0,0,0,255}); $border.setFillColor({0,0,0,255});
$status.init();
} }
void Display::handle_inputs(Chip8& vm) { void Display::handle_inputs(Chip8& vm) {
while (const auto event = window.pollEvent()) { while (const auto event = $window.pollEvent()) {
if(event->is<sf::Event::Closed>()) { if(event->is<sf::Event::Closed>()) {
window.close(); $window.close();
} }
if(const auto* key = event->getIf<sf::Event::KeyPressed>()) { if(const auto* key = event->getIf<sf::Event::KeyPressed>()) {
@ -41,15 +43,17 @@ void Display::handle_inputs(Chip8& vm) {
void Display::update(Chip8& vm) { void Display::update(Chip8& vm) {
handle_inputs(vm); handle_inputs(vm);
texture.update((uint8_t *)(vm.video), {64, 32}, {0,0}); $texture.update((uint8_t *)(vm.video), {64, 32}, {0,0});
$status.update(vm);
} }
void Display::render() { void Display::render() {
window.draw(border); $window.draw($border);
window.draw(texture_sprite); $window.draw($texture_sprite);
window.display(); $status.render($window);
$window.display();
} }
bool Display::active() { bool Display::active() {
return window.isOpen(); return $window.isOpen();
} }

@ -4,12 +4,14 @@
#include <SFML/Graphics/RenderWindow.hpp> #include <SFML/Graphics/RenderWindow.hpp>
#include <SFML/Graphics/RectangleShape.hpp> #include <SFML/Graphics/RectangleShape.hpp>
#include "chip8.hpp" #include "chip8.hpp"
#include "status_panel.hpp"
struct Display { struct Display {
sf::RenderWindow& window; sf::RenderWindow& $window;
sf::Texture texture{sf::Vector2u{64,32}}; sf::Texture $texture{sf::Vector2u{VIDEO_WIDTH, VIDEO_HEIGHT}};
sf::Sprite texture_sprite{texture}; sf::Sprite $texture_sprite{$texture};
sf::RectangleShape border; sf::RectangleShape $border;
StatusPanel $status;
Display(sf::RenderWindow& window, sf::Vector2f pos, sf::Vector2f size); Display(sf::RenderWindow& window, sf::Vector2f pos, sf::Vector2f size);

@ -6,6 +6,7 @@
#include "chip8.hpp" #include "chip8.hpp"
#include "stats.hpp" #include "stats.hpp"
#include "display.hpp" #include "display.hpp"
#include <guecs/sfml/backend.hpp>
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
if(argc != 4) { if(argc != 4) {
@ -22,6 +23,9 @@ int main(int argc, char* argv[]) {
int videoPitch = sizeof(chip8.video[0]) * VIDEO_WIDTH; int videoPitch = sizeof(chip8.video[0]) * VIDEO_WIDTH;
sfml::Backend backend;
guecs::init(&backend);
sf::RenderWindow window{sf::VideoMode({1280, 720}), "Chip8 Emulator"}; sf::RenderWindow window{sf::VideoMode({1280, 720}), "Chip8 Emulator"};
window.setFramerateLimit(framerate); window.setFramerateLimit(framerate);
window.setVerticalSyncEnabled(false); window.setVerticalSyncEnabled(false);

@ -4,4 +4,6 @@ sources = files(
'chip8.cpp', 'chip8.cpp',
'stats.cpp', 'stats.cpp',
'display.cpp', 'display.cpp',
'status_panel.cpp',
'code_panel.cpp',
) )

@ -0,0 +1,52 @@
#include "status_panel.hpp"
#include <fmt/xchar.h>
StatusPanel::StatusPanel() {
$gui.position(1000, 0, 1280 - 1000, 720);
$gui.layout(
"[N|Reg|Stk|Key]"
"[x0|r0|s0|k0]"
"[x1|r1|s1|k1]"
"[x2|r2|s2|k2]"
"[x3|r3|s3|k3]"
"[x4|r4|s4|k4]"
"[x5|r5|s5|k5]"
"[x6|r6|s6|k6]"
"[x7|r7|s7|k7]"
"[x8|r8|s8|k8]"
"[x9|r9|s9|k9]"
"[xA|r10|s10|k10]"
"[xB|r11|s11|k11]"
"[xC|r12|s12|k12]"
"[xD|r13|s13|k13]"
"[xE|r14|s14|k14]"
"[xF|r15|s15|k15]");
}
void StatusPanel::init() {
for(auto& [name, cell] : $gui.cells()) {
auto id = $gui.entity(name);
$gui.set<guecs::Rectangle>(id, {});
$gui.set<guecs::Text>(id, {guecs::to_wstring(name)});
}
$gui.init();
}
void StatusPanel::render(sf::RenderTarget& window) {
$gui.render(window);
}
void StatusPanel::update(Chip8& vm) {
for(size_t i = 0; i < 16; i++) {
$gui.show_text(fmt::format("r{}", i), fmt::format(L"{}", vm.registers[i]));
}
for(size_t i = 0; i < 16; i++) {
$gui.show_text(fmt::format("s{}", i), fmt::format(L"{}", vm.stack[i]));
}
for(size_t i = 0; i < 16; i++) {
$gui.show_text(fmt::format("k{}", i), fmt::format(L"{}", vm.keypad[i]));
}
}

@ -0,0 +1,15 @@
#pragma once
#include <guecs/sfml/components.hpp>
#include <guecs/ui.hpp>
#include "chip8.hpp"
struct StatusPanel {
guecs::UI $gui;
StatusPanel();
void init();
void render(sf::RenderTarget& window);
void update(Chip8& vm);
};
Loading…
Cancel
Save