Implement Pixelbuffer display using SDL2

This commit is contained in:
Rekai Nyangadzayi Musuka 2021-06-17 02:36:06 -05:00
parent 4ef56bbcaf
commit 2885adabcd
3 changed files with 51 additions and 26 deletions

2
.gitignore vendored
View File

@ -6,3 +6,5 @@
# ROM directory # ROM directory
/bin /bin
# VSCode Directories
/.vscode

View File

@ -34,7 +34,6 @@ pub fn decode(cpu: *Cpu, word: u16) ?Instruction {
const nib3: u4 = @intCast(u4, (word & 0x00F0) >> 4); const nib3: u4 = @intCast(u4, (word & 0x00F0) >> 4);
const nib4: u4 = @intCast(u4, (word & 0x000F) >> 0); const nib4: u4 = @intCast(u4, (word & 0x000F) >> 0);
if (nib1 == 0x0) { if (nib1 == 0x0) {
// nib2 is 0x0, nib3 is 0xE // nib2 is 0x0, nib3 is 0xE
@ -84,20 +83,20 @@ pub fn decode(cpu: *Cpu, word: u16) ?Instruction {
pub fn execute(cpu: *Cpu, instr: Instruction) void { pub fn execute(cpu: *Cpu, instr: Instruction) void {
switch (instr) { switch (instr) {
.CLS => std.debug.print("CLS\n", .{}), .CLS => std.log.debug("CLS", .{}),
.RET => { .RET => {
std.debug.print("RET\n", .{}); std.log.debug("RET", .{});
cpu.pc = cpu.stack[cpu.sp]; cpu.pc = cpu.stack[cpu.sp];
cpu.sp -= 1; cpu.sp -= 1;
}, },
.JP => |addr| { .JP => |addr| {
std.debug.print("JP 0x{X:}\n", .{ addr }); std.log.debug("JP 0x{X:}", .{ addr });
cpu.pc = addr; cpu.pc = addr;
}, },
.CALL => |addr| { .CALL => |addr| {
std.debug.print("CALL 0x{X:}\n", .{ addr }); std.log.debug("CALL 0x{X:}", .{ addr });
cpu.sp += 1; cpu.sp += 1;
cpu.stack[cpu.sp] = cpu.pc; cpu.stack[cpu.sp] = cpu.pc;
@ -106,7 +105,7 @@ pub fn execute(cpu: *Cpu, instr: Instruction) void {
.SE_3 => |args| { .SE_3 => |args| {
const x = args.x; const x = args.x;
const kk = args.kk; const kk = args.kk;
std.debug.print("SE V{}, 0x{X:}\n", .{ x, kk }); std.log.debug("SE V{}, 0x{X:}", .{ x, kk });
if (cpu.v[x] != kk) { if (cpu.v[x] != kk) {
cpu.pc += 2; cpu.pc += 2;
@ -115,19 +114,19 @@ pub fn execute(cpu: *Cpu, instr: Instruction) void {
.LD_6 => |args| { .LD_6 => |args| {
const x = args.x; const x = args.x;
const kk = args.kk; const kk = args.kk;
std.debug.print("LD V{} 0x{X:}\n", .{ x, kk }); std.log.debug("LD V{} 0x{X:}", .{ x, kk });
cpu.v[x] = kk; cpu.v[x] = kk;
}, },
.LD_I => |addr| { .LD_I => |addr| {
std.debug.print("LD I, 0x{X:}\n", .{ addr }); std.log.debug("LD I, 0x{X:}", .{ addr });
cpu.i = addr; cpu.i = addr;
}, },
.DRW => |args| { .DRW => |args| {
const x = args.x; const x = args.x;
const y = args.y; const y = args.y;
const n = args.n; const n = args.n;
std.debug.print("DRW V{}, V{}, 0x{X:}\n", .{ x, y, n }); std.log.debug("DRW V{}, V{}, 0x{X:}", .{ x, y, n });
const draw_pos: Point = .{ .x = cpu.v[x], .y = cpu.v[y] }; const draw_pos: Point = .{ .x = cpu.v[x], .y = cpu.v[y] };
const sprite_data = cpu.memory[cpu.i..(cpu.i + n)]; const sprite_data = cpu.memory[cpu.i..(cpu.i + n)];
@ -141,7 +140,7 @@ pub fn execute(cpu: *Cpu, instr: Instruction) void {
.ADD_7 => |args| { .ADD_7 => |args| {
const x = args.x; const x = args.x;
const kk = args.kk; const kk = args.kk;
std.debug.print("ADD V{}, 0x{X:}\n", .{ x, kk }); std.log.debug("ADD V{}, 0x{X:}", .{ x, kk });
cpu.v[x] = cpu.v[x] + kk; cpu.v[x] = cpu.v[x] + kk;
} }
@ -158,18 +157,19 @@ fn load_rom(cpu: *Cpu, buf: []u8) void {
} }
pub fn load_rom_path(cpu: *Cpu, path: []const u8) !void { pub fn load_rom_path(cpu: *Cpu, path: []const u8) !void {
var alloc = std.heap.page_allocator; var heap = std.heap.page_allocator;
const file = try std.fs.cwd().openFile(path, .{ .read = true }); const file = try std.fs.cwd().openFile(path, .{ .read = true });
defer file.close(); defer file.close();
const file_size = try file.getEndPos(); const file_size = try file.getEndPos();
const rom_buf = try file.readToEndAlloc(alloc, file_size); const rom_buf = try file.readToEndAlloc(heap, file_size);
defer heap.free(rom_buf);
load_rom(cpu, rom_buf); load_rom(cpu, rom_buf);
} }
pub fn cycle(cpu: *Cpu) void { pub fn step(cpu: *Cpu) void {
const opcode = fetch(cpu); const opcode = fetch(cpu);
const maybe_instr = decode(cpu, opcode); const maybe_instr = decode(cpu, opcode);

View File

@ -1,17 +1,22 @@
const std = @import("std"); const std = @import("std");
const cpu = @import("cpu.zig"); const emu = @import("emu.zig");
const Display = @import("display.zig").Display; const Display = @import("display.zig").Display;
const c = @cImport(@cInclude("SDL.h")); const c = @cImport(@cInclude("SDL.h"));
const Cpu = emu.Cpu;
const WIDTH = 64; const WIDTH = 64;
const HEIGHT = 32; const HEIGHT = 32;
const WINDOW_WIDTH = WIDTH * 10;
const WINDOW_HEIGHT = HEIGHT * 10;
const PIXELBUF_LEN = WIDTH * HEIGHT * @sizeOf(u32);
pub fn main() anyerror!void { pub fn main() !void {
_ = c.SDL_Init(c.SDL_INIT_VIDEO); _ = c.SDL_Init(c.SDL_INIT_VIDEO);
defer c.SDL_Quit(); defer c.SDL_Quit();
const window = c.SDL_CreateWindow("CHIP-8", c.SDL_WINDOWPOS_CENTERED, c.SDL_WINDOWPOS_CENTERED, WIDTH, HEIGHT, c.SDL_WINDOW_OPENGL); const window = c.SDL_CreateWindow("CHIP-8", c.SDL_WINDOWPOS_CENTERED, c.SDL_WINDOWPOS_CENTERED, WINDOW_WIDTH, WINDOW_HEIGHT, c.SDL_WINDOW_OPENGL);
defer c.SDL_DestroyWindow(window); defer c.SDL_DestroyWindow(window);
const renderer = c.SDL_CreateRenderer(window, -1, c.SDL_RENDERER_ACCELERATED); const renderer = c.SDL_CreateRenderer(window, -1, c.SDL_RENDERER_ACCELERATED);
@ -20,8 +25,7 @@ pub fn main() anyerror!void {
const texture = c.SDL_CreateTexture(renderer, c.SDL_PIXELFORMAT_RGBA8888, c.SDL_TEXTUREACCESS_STATIC, WIDTH, HEIGHT); const texture = c.SDL_CreateTexture(renderer, c.SDL_PIXELFORMAT_RGBA8888, c.SDL_TEXTUREACCESS_STATIC, WIDTH, HEIGHT);
defer c.SDL_DestroyTexture(texture); defer c.SDL_DestroyTexture(texture);
var zig8 = emu.Cpu {
var zig8 = cpu.Cpu {
.i = 0x00, .i = 0x00,
.pc = 0x200, .pc = 0x200,
.sp = 0x00, .sp = 0x00,
@ -31,15 +35,15 @@ pub fn main() anyerror!void {
.disp = Display.new(), .disp = Display.new(),
}; };
try cpu.load_rom_path(&zig8, "./bin/IBM Logo.ch8"); try emu.load_rom_path(&zig8, "./bin/IBM Logo.ch8");
var pixel_buf: [PIXELBUF_LEN]u8 = [_]u8 {0x00} ** PIXELBUF_LEN;
const size = WIDTH * HEIGHT * @sizeOf(u32);
var pixels: [size]u8 = [_]u8 {0xFF} ** size;
emuloop: while(true) { emuloop: while(true) {
var event: c.SDL_Event = undefined; _ = c.SDL_UpdateTexture(texture, null, @ptrCast(*const c_void, &pixel_buf), WIDTH * @sizeOf(u32));
_ = c.SDL_RenderCopy(renderer, texture, null, null);
_ = c.SDL_RenderPresent(renderer);
var event: c.SDL_Event = undefined;
while(c.SDL_PollEvent(&event) != 0) { while(c.SDL_PollEvent(&event) != 0) {
switch(event.type) { switch(event.type) {
c.SDL_QUIT => break :emuloop, c.SDL_QUIT => break :emuloop,
@ -47,8 +51,27 @@ pub fn main() anyerror!void {
} }
} }
var c_ptr = @ptrCast(*const c_void, &pixels); emu.step(&zig8);
draw(&zig8.disp, &pixel_buf);
}
}
_ = c.SDL_UpdateTexture(texture, null, c_ptr, WIDTH * @sizeOf(u32)); fn draw(display: *const Display, pixel_buf: *[8192]u8) void {
var emu_i: usize = 0;
while (emu_i < display.buf.len) : (emu_i += 1) {
var pixel_i = emu_i * 4;
if (display.buf[emu_i] == 0x01) {
pixel_buf[pixel_i] = 0xFF;
pixel_buf[pixel_i + 1] = 0xFF;
pixel_buf[pixel_i + 2] = 0xFF;
pixel_buf[pixel_i + 3] = 0xFF;
} else {
pixel_buf[pixel_i] = 0xFF;
pixel_buf[pixel_i + 1] = 0x00;
pixel_buf[pixel_i + 2] = 0x00;
pixel_buf[pixel_i + 3] = 0x00;
}
} }
} }