Prepare uxn ppu initialization

This commit is contained in:
Bad Diode 2022-03-04 15:09:58 +01:00
parent 9f81a64787
commit bfd3c8ece9
8 changed files with 4625 additions and 39 deletions

View File

@ -1,9 +1,10 @@
BASE_UXN := src/uxn/src
SRC_DIR ?= src SRC_DIR ?= src
BUILD_DIR ?= build BUILD_DIR ?= build
SRC_MAIN ?= $(SRC_DIR)/main.c SRC_MAIN ?= $(SRC_DIR)/main.c
EXE_NAME ?= fbtest EXE_NAME ?= fbtest
BIN := $(BUILD_DIR)/$(EXE_NAME) BIN := $(BUILD_DIR)/$(EXE_NAME)
BASE_UXN := src/uxn/src/uxn.h UXN_HEAD := $(BASE_UXN)/uxn.h
CC ?= cc CC ?= cc
CFLAGS := -Wall -Wextra -pedantic CFLAGS := -Wall -Wextra -pedantic
@ -24,13 +25,13 @@ endif
main: $(BIN) main: $(BIN)
$(BIN): $(SRC_MAIN) $(BUILD_DIR) $(BASE_UXN) $(BIN): $(SRC_MAIN) $(BUILD_DIR) $(UXN_HEAD)
$(CC) $(CFLAGS) -o $(BIN) $(SRC_MAIN) $(CC) $(CFLAGS) -o $(BIN) $(SRC_MAIN)
$(BUILD_DIR): $(BUILD_DIR):
mkdir -p $(BUILD_DIR) mkdir -p $(BUILD_DIR)
$(BASE_UXN): $(UXN_HEAD):
git submodule init git submodule init
git submodule update git submodule update

View File

@ -8,38 +8,29 @@
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/mman.h> #include <sys/mman.h>
#include "shorthand.h"
#include "ppu.c"
#include "uxn-fast.c"
#include "rom.c"
// static Uxn u;
// static Device *devscreen;
// static Device *devctrl;
// static Device *devmouse;
// static Device *devaudio;
int int
main(void) { main(void) {
// Open frambuffer and get the size. ppu_init();
int fb = open("/dev/fb0", O_RDWR);
if (fb <= 0) {
fprintf(stderr, "couldn't open the framebuffer\n");
exit(EXIT_FAILURE);
}
struct fb_var_screeninfo info;
if (ioctl(fb, FBIOGET_VSCREENINFO, &info) != 0) {
fprintf(stderr, "couldn't get the framebuffer size\n");
exit(EXIT_FAILURE);
}
// Mmap the framebuffer to a buffer object.
size_t width = info.xres;
size_t height = info.yres;
size_t len = 4 * width * height;
uint32_t *buf = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fb, 0);
if (buf == MAP_FAILED) {
fprintf(stderr, "couldn't mmap the framebuffer\n");
exit(EXIT_FAILURE);
}
// Main loop. // Main loop.
uint8_t shade = 0; uint8_t shade = 0;
size_t counter = 0; size_t counter = 0;
size_t direction = 1; size_t direction = 1;
while (true) { while (true) {
for (size_t j = 0; j < height; j++) { for (size_t j = 0; j < screen_height; j++) {
for (size_t i = 0; i < width; i++) { for (size_t i = 0; i < screen_width; i++) {
buf[j * width + i] = shade; framebuffer[j * screen_width + i] = shade;
} }
} }
counter++; counter++;
@ -54,8 +45,5 @@ main(void) {
} }
} }
// Cleanup.
munmap(buf, len);
close(fb);
return 0; return 0;
} }

144
src/ppu.c Normal file
View File

@ -0,0 +1,144 @@
#include <string.h>
#include "ppu.h"
/*
Copyright (c) 2021 Devine Lu Linvega
Copyright (c) 2021 Andrew Alderwick
Copyright (c) 2021 Bad Diode
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE.
*/
static size_t screen_width = 0;
static size_t screen_height = 0;
static u32 *framebuffer = 0;
static u32 palette[16];
static u8 *pixels_buf;
static u8 *dirty_lines;
static u8 reqdraw = 0;
// TODO: Probably should consider this
// static u32 rgb_order;
static u8 blending[5][16] = {
{0, 0, 0, 0, 1, 0, 1, 1, 2, 2, 0, 2, 3, 3, 3, 0},
{0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3},
{1, 2, 3, 1, 1, 2, 3, 1, 1, 2, 3, 1, 1, 2, 3, 1},
{2, 3, 1, 2, 2, 3, 1, 2, 2, 3, 1, 2, 2, 3, 1, 2},
{1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0}};
void
ppu_pixel(u8 layer, u16 x, u16 y, u8 color) {
size_t idx = y * screen_width + x;
u8 *pixel = &pixels_buf[idx], shift = layer * 2;
if(x < screen_width && y < screen_height) {
*pixel = (*pixel & ~(0x3 << shift)) | (color << shift);
}
dirty_lines[y] |= 1;
}
void
ppu_1bpp(u8 layer, u16 x, u16 y, u8 *sprite, u8 color, u8 flipx, u8 flipy) {
u16 v, h;
for(v = 0; v < 8; v++)
for(h = 0; h < 8; h++) {
u8 ch1 = (sprite[v] >> (7 - h)) & 0x1;
if(ch1 || blending[4][color])
ppu_pixel(layer,
x + (flipx ? 7 - h : h),
y + (flipy ? 7 - v : v),
blending[ch1][color]);
}
}
void
ppu_2bpp(u8 layer, u16 x, u16 y, u8 *sprite, u8 color, u8 flipx, u8 flipy) {
u16 v, h;
for(v = 0; v < 8; v++)
for(h = 0; h < 8; h++) {
u8 ch1 = ((sprite[v] >> (7 - h)) & 0x1);
u8 ch2 = ((sprite[v + 8] >> (7 - h)) & 0x1);
u8 ch = ch1 + ch2 * 2;
if(ch || blending[4][color])
ppu_pixel(layer,
x + (flipx ? 7 - h : h),
y + (flipy ? 7 - v : v),
blending[ch][color]);
}
}
void
redraw_screen(void) {
for (size_t j = 0; j < screen_height; j++) {
dirty_lines[j] = 1;
}
}
int
ppu_init(void) {
// Open frambuffer and get the size.
int fb = open("/dev/fb0", O_RDWR);
if (fb <= 0) {
fprintf(stderr, "couldn't open the framebuffer\n");
exit(EXIT_FAILURE);
}
struct fb_var_screeninfo info;
if (ioctl(fb, FBIOGET_VSCREENINFO, &info) != 0) {
fprintf(stderr, "couldn't get the framebuffer size\n");
exit(EXIT_FAILURE);
}
// Mmap the framebuffer to a buffer object.
screen_width = info.xres;
screen_height = info.yres;
size_t len = 4 * screen_width * screen_height;
framebuffer = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fb, 0);
if (framebuffer == MAP_FAILED) {
fprintf(stderr, "couldn't mmap the framebuffer\n");
exit(EXIT_FAILURE);
}
// Allocate intermediate buffers.
pixels_buf = malloc(screen_width * screen_height);
dirty_lines = malloc(screen_height);
// Initialize default palette.
palette[0] = 0x444444;
palette[1] = 0xffffff;
palette[2] = 0x7777ff;
palette[3] = 0xff7777;
// Clear pixel buffer memory.
memset(pixels_buf, 0, screen_width * screen_height);
memset(dirty_lines, 1, screen_height);
// Make sure we perform an initial screen drawing.
reqdraw = 1;
redraw_screen();
return 1;
}
void
blit_framebuffer(void) {
if (reqdraw == 0) {
return;
}
for (size_t j = 0; j < screen_height; j++) {
if (dirty_lines[j] != 0) {
for (size_t i = 0; i < screen_width; i++) {
size_t idx = i + j * screen_width;
framebuffer[idx] = palette[pixels_buf[idx] % 16];
}
}
dirty_lines[j] = 0;
}
reqdraw = 0;
}

20
src/ppu.h Normal file
View File

@ -0,0 +1,20 @@
/*
Copyright (c) 2021 Devine Lu Linvega
Copyright (c) 2021 Andrew Alderwick
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE.
*/
typedef unsigned char Uint8;
typedef unsigned short Uint16;
typedef unsigned int Uint32;
int ppu_init(void);
void ppu_pixel(Uint8 layer, Uint16 x, Uint16 y, Uint8 color);
void ppu_1bpp(Uint8 layer, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 color, Uint8 flipx, Uint8 flipy);
void ppu_2bpp(Uint8 layer, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 color, Uint8 flipx, Uint8 flipy);

52
src/rom.c Normal file
View File

@ -0,0 +1,52 @@
const u16 uxn_rom[] = {
0x0120, 0x8043, 0x3720, 0xf020, 0x807f, 0x3708, 0xf020, 0x80e0,
0x370a, 0xf020, 0x80c0, 0x370c, 0x2280, 0x8036, 0x3f01, 0x0020,
0x3920, 0x0280, 0x8031, 0x3624, 0x0180, 0x803f, 0x3104, 0x0120,
0x2ed4, 0x0220, 0x2e2f, 0x0220, 0x2e71, 0x0220, 0x2eae, 0x0320,
0x2e3a, 0x8000, 0x3000, 0x2321, 0x0080, 0x8031, 0x3002, 0x0020,
0x3848, 0x2880, 0x8037, 0x3004, 0x0020, 0x3950, 0x2a80, 0x8037,
0x0f01, 0x0305, 0x0480, 0x801f, 0x0500, 0x3080, 0x203f, 0x9103,
0x8038, 0x372c, 0x80cf, 0x172f, 0x0f80, 0x801c, 0x0500, 0x3080,
0x203f, 0x9103, 0x8038, 0x372c, 0x2880, 0x2036, 0x0800, 0x8038,
0x3728, 0x80cf, 0x172f, 0x8003, 0x1f04, 0x0080, 0x8005, 0x3f30,
0x0320, 0x3891, 0x2c80, 0x8037, 0x3628, 0x0020, 0x3808, 0x2880,
0xcf37, 0x2f80, 0x8017, 0x1c0f, 0x0080, 0x8005, 0x3f30, 0x0320,
0x3891, 0x2c80, 0x8037, 0x3628, 0x0020, 0x3808, 0x2880, 0x4f37,
0x2f80, 0x0017, 0x1080, 0x0080, 0x8003, 0x1f30, 0x0080, 0x2005,
0x9103, 0x8038, 0x372c, 0x8003, 0x1f30, 0x0080, 0x8005, 0x3002,
0x0020, 0x3940, 0x8038, 0x3728, 0x0480, 0x2030, 0x5000, 0x8039,
0x372a, 0x0180, 0x2f80, 0x0317, 0x3080, 0x801f, 0x0500, 0x0480,
0x2030, 0x4000, 0x3839, 0x2a80, 0x8037, 0x3002, 0x0020, 0x3950,
0x2880, 0x8037, 0x8001, 0x172f, 0x8a01, 0xab80, 0x220d, 0x206c,
0x8103, 0x2c80, 0x8037, 0x8000, 0x0300, 0x0f80, 0x801c, 0x1f40,
0x0180, 0x801f, 0x0500, 0x0280, 0x2030, 0x4000, 0x3839, 0x2880,
0x0337, 0xf080, 0x801c, 0x1f01, 0x0080, 0x8005, 0x3004, 0x0020,
0x3940, 0x8038, 0x372a, 0x8003, 0x172f, 0x8901, 0xca80, 0x220d,
0x806c, 0x8010, 0x8f00, 0x8003, 0x1f02, 0x0080, 0x8005, 0x3f40,
0x0480, 0x2030, 0x4000, 0x3839, 0x032f, 0x0380, 0x801c, 0x0500,
0x4080, 0x203f, 0x4000, 0x8038, 0x3002, 0x0020, 0x3808, 0x6f38,
0x804f, 0x2000, 0xe702, 0x012e, 0x808a, 0x0dc9, 0x6c22, 0x1080,
0x0080, 0x038f, 0x0280, 0x801f, 0x0500, 0x4080, 0x803f, 0x3004,
0x2f38, 0x8003, 0x1c03, 0x0080, 0x8005, 0x3f40, 0x0020, 0x3840,
0x0280, 0x2030, 0x0800, 0x3838, 0x4f6f, 0x8080, 0x0220, 0x2ee7,
0x8a01, 0xcd80, 0x220d, 0x186c, 0x200f, 0x8103, 0x2c80, 0x8037,
0x372a, 0x2880, 0x8037, 0xcf00, 0x8018, 0x172f, 0x2880, 0x2036,
0x0800, 0x8038, 0x3728, 0x1080, 0x18cf, 0x2f80, 0x8017, 0x3628,
0x0020, 0x3908, 0x2880, 0x8037, 0x362a, 0x0020, 0x3808, 0x2a80,
0x8037, 0xcf20, 0x8018, 0x172f, 0x2880, 0x2036, 0x0800, 0x8038,
0x3728, 0x3080, 0x184f, 0x2f80, 0x6c17, 0x0480, 0x2030, 0x4000,
0x8039, 0x372a, 0x0280, 0x2030, 0x4800, 0x8038, 0x3728, 0x0080,
0x2e80, 0x8017, 0x3002, 0x0020, 0x3849, 0x2880, 0x8037, 0x8001,
0x172e, 0x0280, 0x2030, 0x4a00, 0x8038, 0x3728, 0x0280, 0x2e80,
0x8017, 0x3002, 0x0020, 0x384b, 0x2880, 0x8037, 0x8003, 0x172e,
0x0f6c, 0x6738, 0xdf5f, 0xbfbf, 0x00bf, 0x1807, 0x2320, 0x4844,
0x0048, 0x827c, 0x8282, 0x8282, 0x007c, 0x1030, 0x1010, 0x1010,
0x0010, 0x827c, 0x7c02, 0x8080, 0x00fe, 0x827c, 0x1c02, 0x8202,
0x007c, 0x140c, 0x4424, 0xfe84, 0x0004, 0x80fe, 0x7c80, 0x8202,
0x007c, 0x827c, 0xfc80, 0x8282, 0x007c, 0x827c, 0x1e02, 0x0202,
0x0002, 0x827c, 0x7c82, 0x8282, 0x007c, 0x827c, 0x7e82, 0x8202,
0x007c, 0x827c, 0x7e02, 0x8282, 0x007e, 0x82fc, 0xfc82, 0x8282,
0x00fc, 0x827c, 0x8080, 0x8280, 0x007c, 0x82fc, 0x8282, 0x8282,
0x00fc, 0x827c, 0xf080, 0x8280, 0x007c, 0x827c, 0xf080, 0x8080,
0x8080,
};

46
src/shorthand.h Normal file
View File

@ -0,0 +1,46 @@
/*
Copyright (c) 2021 Bad Diode
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE.
*/
#ifndef UTILS_SHORTHAND_H
#define UTILS_SHORTHAND_H
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
//
// This simple header just typedefs the basic C define types to a shorter name,
// loads the quality of life bool macro for _Bool and defines shorthand macros
// for byte sizes.
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
typedef int8_t s8;
typedef int16_t s16;
typedef int32_t s32;
typedef int64_t s64;
typedef volatile u8 vu8;
typedef volatile u16 vu16;
typedef volatile u32 vu32;
typedef volatile u64 vu64;
typedef volatile s8 vs8;
typedef volatile s16 vs16;
typedef volatile s32 vs32;
typedef volatile s64 vs64;
#define KB(N) ((u64)(N) * 1024)
#define MB(N) ((u64)KB(N) * 1024)
#define GB(N) ((u64)MB(N) * 1024)
#define TB(N) ((u64)GB(N) * 1024)
#endif // UTILS_SHORTHAND_H

4286
src/uxn-fast.c Normal file

File diff suppressed because it is too large Load Diff

49
src/uxn.h Normal file
View File

@ -0,0 +1,49 @@
/*
Copyright (c) 2021 Devine Lu Linvega
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE.
*/
typedef unsigned char Uint8;
typedef signed char Sint8;
typedef unsigned short Uint16;
typedef signed short Sint16;
#define PAGE_PROGRAM 0x0100
typedef struct {
Uint8 ptr, kptr, error;
Uint8 dat[256];
} Stack;
typedef struct {
Uint16 ptr;
Uint8 dat[65536];
} Memory;
typedef struct Device {
struct Uxn *u;
Uint8 addr, dat[16], *mem;
void (*talk)(struct Device *d, Uint8, Uint8);
} Device;
typedef struct Uxn {
Stack wst, rst, *src, *dst;
Memory ram;
Device dev[16];
} Uxn;
struct Uxn;
void mempoke16(Uint8 *m, Uint16 a, Uint16 b);
Uint16 mempeek16(Uint8 *m, Uint16 a);
int uxn_boot(Uxn *c);
int uxn_eval(Uxn *u, Uint16 vec);
int uxn_halt(Uxn *u, Uint8 error, char *name, int id);
Device *uxn_port(Uxn *u, Uint8 id, char *name, void (*talkfn)(Device *, Uint8, Uint8));