Renamed PPU to Screen

This commit is contained in:
neauoire 2021-12-28 13:37:26 -08:00
parent 2a9fc00441
commit 7b33cf3d95
6 changed files with 167 additions and 162 deletions

View File

@ -14,8 +14,8 @@ then
echo "Formatting.."
clang-format -i src/uxn.h
clang-format -i src/uxn.c
clang-format -i src/devices/ppu.h
clang-format -i src/devices/ppu.c
clang-format -i src/devices/screen.h
clang-format -i src/devices/screen.c
clang-format -i src/devices/apu.h
clang-format -i src/devices/apu.c
clang-format -i src/devices/file.h
@ -62,7 +62,7 @@ fi
echo "Building.."
${CC} ${CFLAGS} src/uxnasm.c -o bin/uxnasm
${CC} ${CFLAGS} ${CORE} src/devices/file.c src/devices/mouse.c src/devices/controller.c src/devices/ppu.c src/devices/apu.c src/uxnemu.c ${UXNEMU_LDFLAGS} -o bin/uxnemu
${CC} ${CFLAGS} ${CORE} src/devices/file.c src/devices/mouse.c src/devices/controller.c src/devices/screen.c src/devices/apu.c src/uxnemu.c ${UXNEMU_LDFLAGS} -o bin/uxnemu
${CC} ${CFLAGS} ${CORE} src/devices/file.c src/uxncli.c -o bin/uxncli
if [ -d "$HOME/bin" ]

6
mkfile
View File

@ -8,7 +8,7 @@ HFILES=\
/sys/include/npe/stdio.h\
src/devices/apu.h\
src/devices/file.h\
src/devices/ppu.h\
src/devices/screen.h\
src/uxn.h\
CLEANFILES=$TARG $ROM
@ -35,13 +35,13 @@ bin/uxncli: file.$O uxncli.$O uxn.$O
bin/uxnasm: uxnasm.$O
$LD $LDFLAGS -o $target $prereq
bin/uxnemu: uxnemu.$O apu.$O file.$O ppu.$O uxn.$O
bin/uxnemu: uxnemu.$O apu.$O file.$O screen.$O uxn.$O
$LD $LDFLAGS -o $target $prereq
(uxnasm|uxncli|uxnemu|uxn)\.$O:R: src/\1.c
$CC $CFLAGS -Isrc -o $target src/$stem1.c
(apu|file|ppu)\.$O:R: src/devices/\1.c
(apu|file|screen)\.$O:R: src/devices/\1.c
$CC $CFLAGS -Isrc -o $target src/devices/$stem1.c
nuke:V: clean

View File

@ -1,37 +0,0 @@
#include <stdlib.h>
/*
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;
typedef struct Layer {
Uint8 *pixels;
Uint8 changed;
} Layer;
typedef struct Ppu {
Uint32 palette[4], *screen;
Uint16 width, height;
Layer fg, bg;
} Ppu;
void ppu_palette(Ppu *p, Uint8 *addr);
void ppu_resize(Ppu *p, Uint16 width, Uint16 height);
void ppu_clear(Ppu *p, Layer *layer);
void ppu_redraw(Ppu *p, Uint32 *screen);
void ppu_write(Ppu *p, Layer *layer, Uint16 x, Uint16 y, Uint8 color);
void ppu_blit(Ppu *p, Layer *layer, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 color, Uint8 flipx, Uint8 flipy, Uint8 twobpp);
void ppu_debug(Ppu *p, Uint8 *stack, Uint8 wptr, Uint8 rptr, Uint8 *memory);

View File

@ -1,4 +1,5 @@
#include "ppu.h"
#include "../uxn.h"
#include "screen.h"
/*
Copyright (c) 2021 Devine Lu Linvega
@ -12,6 +13,8 @@ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE.
*/
Screen screen;
static Uint8 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},
@ -37,8 +40,39 @@ static Uint8 font[][8] = {
{0x00, 0x7c, 0x82, 0x80, 0xf0, 0x80, 0x82, 0x7c},
{0x00, 0x7c, 0x82, 0x80, 0xf0, 0x80, 0x80, 0x80}};
static void
screen_write(Screen *p, Layer *layer, Uint16 x, Uint16 y, Uint8 color)
{
if(x < p->width && y < p->height) {
Uint32 i = x + y * p->width;
Uint8 prev = layer->pixels[i];
if(color != prev) {
layer->pixels[i] = color;
layer->changed = 1;
}
}
}
static void
screen_blit(Screen *p, Layer *layer, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 color, Uint8 flipx, Uint8 flipy, Uint8 twobpp)
{
int v, h, opaque = blending[4][color];
for(v = 0; v < 8; ++v) {
Uint16 c = sprite[v] | (twobpp ? sprite[v + 8] : 0) << 8;
for(h = 7; h >= 0; --h, c >>= 1) {
Uint8 ch = (c & 1) | ((c >> 7) & 2);
if(opaque || ch)
screen_write(p,
layer,
x + (flipx ? 7 - h : h),
y + (flipy ? 7 - v : v),
blending[ch][color]);
}
}
}
void
ppu_palette(Ppu *p, Uint8 *addr)
screen_palette(Screen *p, Uint8 *addr)
{
int i, shift;
for(i = 0, shift = 4; i < 4; ++i, shift ^= 4) {
@ -53,27 +87,27 @@ ppu_palette(Ppu *p, Uint8 *addr)
}
void
ppu_resize(Ppu *p, Uint16 width, Uint16 height)
screen_resize(Screen *p, Uint16 width, Uint16 height)
{
Uint8
*bg = realloc(p->bg.pixels, width * height),
*fg = realloc(p->fg.pixels, width * height);
Uint32
*screen = realloc(p->screen, width * height * sizeof(Uint32));
*pixels = realloc(p->pixels, width * height * sizeof(Uint32));
if(bg) p->bg.pixels = bg;
if(fg) p->fg.pixels = fg;
if(screen) p->screen = screen;
if(bg && fg && screen) {
if(pixels) p->pixels = pixels;
if(bg && fg && pixels) {
p->width = width;
p->height = height;
p->screen = screen;
ppu_clear(p, &p->bg);
ppu_clear(p, &p->fg);
p->pixels = pixels;
screen_clear(p, &p->bg);
screen_clear(p, &p->fg);
}
}
void
ppu_clear(Ppu *p, Layer *layer)
screen_clear(Screen *p, Layer *layer)
{
Uint32 i, size = p->width * p->height;
for(i = 0; i < size; ++i)
@ -82,72 +116,87 @@ ppu_clear(Ppu *p, Layer *layer)
}
void
ppu_redraw(Ppu *p, Uint32 *screen)
screen_redraw(Screen *p, Uint32 *pixels)
{
Uint32 i, size = p->width * p->height, palette[16];
for(i = 0; i < 16; ++i)
palette[i] = p->palette[(i >> 2) ? (i >> 2) : (i & 3)];
for(i = 0; i < size; ++i)
screen[i] = palette[p->fg.pixels[i] << 2 | p->bg.pixels[i]];
pixels[i] = palette[p->fg.pixels[i] << 2 | p->bg.pixels[i]];
p->fg.changed = p->bg.changed = 0;
}
void
ppu_write(Ppu *p, Layer *layer, Uint16 x, Uint16 y, Uint8 color)
{
if(x < p->width && y < p->height) {
Uint32 i = x + y * p->width;
Uint8 prev = layer->pixels[i];
if(color != prev) {
layer->pixels[i] = color;
layer->changed = 1;
}
}
}
void
ppu_blit(Ppu *p, Layer *layer, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 color, Uint8 flipx, Uint8 flipy, Uint8 twobpp)
{
int v, h, opaque = blending[4][color];
for(v = 0; v < 8; ++v) {
Uint16 c = sprite[v] | (twobpp ? sprite[v + 8] : 0) << 8;
for(h = 7; h >= 0; --h, c >>= 1) {
Uint8 ch = (c & 1) | ((c >> 7) & 2);
if(opaque || ch)
ppu_write(p,
layer,
x + (flipx ? 7 - h : h),
y + (flipy ? 7 - v : v),
blending[ch][color]);
}
}
}
void
ppu_debug(Ppu *p, Uint8 *stack, Uint8 wptr, Uint8 rptr, Uint8 *memory)
screen_debug(Screen *p, Uint8 *stack, Uint8 wptr, Uint8 rptr, Uint8 *memory)
{
Uint8 i, x, y, b;
for(i = 0; i < 0x20; ++i) {
x = ((i % 8) * 3 + 1) * 8, y = (i / 8 + 1) * 8, b = stack[i];
/* working stack */
ppu_blit(p, &p->fg, x, y, font[(b >> 4) & 0xf], 1 + (wptr == i) * 0x7, 0, 0, 0);
ppu_blit(p, &p->fg, x + 8, y, font[b & 0xf], 1 + (wptr == i) * 0x7, 0, 0, 0);
screen_blit(p, &p->fg, x, y, font[(b >> 4) & 0xf], 1 + (wptr == i) * 0x7, 0, 0, 0);
screen_blit(p, &p->fg, x + 8, y, font[b & 0xf], 1 + (wptr == i) * 0x7, 0, 0, 0);
y = 0x28 + (i / 8 + 1) * 8;
b = memory[i];
/* return stack */
ppu_blit(p, &p->fg, x, y, font[(b >> 4) & 0xf], 3, 0, 0, 0);
ppu_blit(p, &p->fg, x + 8, y, font[b & 0xf], 3, 0, 0, 0);
screen_blit(p, &p->fg, x, y, font[(b >> 4) & 0xf], 3, 0, 0, 0);
screen_blit(p, &p->fg, x + 8, y, font[b & 0xf], 3, 0, 0, 0);
}
/* return pointer */
ppu_blit(p, &p->fg, 0x8, y + 0x10, font[(rptr >> 4) & 0xf], 0x2, 0, 0, 0);
ppu_blit(p, &p->fg, 0x10, y + 0x10, font[rptr & 0xf], 0x2, 0, 0, 0);
screen_blit(p, &p->fg, 0x8, y + 0x10, font[(rptr >> 4) & 0xf], 0x2, 0, 0, 0);
screen_blit(p, &p->fg, 0x10, y + 0x10, font[rptr & 0xf], 0x2, 0, 0, 0);
/* guides */
for(x = 0; x < 0x10; ++x) {
ppu_write(p, &p->fg, x, p->height / 2, 2);
ppu_write(p, &p->fg, p->width - x, p->height / 2, 2);
ppu_write(p, &p->fg, p->width / 2, p->height - x, 2);
ppu_write(p, &p->fg, p->width / 2, x, 2);
ppu_write(p, &p->fg, p->width / 2 - 0x10 / 2 + x, p->height / 2, 2);
ppu_write(p, &p->fg, p->width / 2, p->height / 2 - 0x10 / 2 + x, 2);
screen_write(p, &p->fg, x, p->height / 2, 2);
screen_write(p, &p->fg, p->width - x, p->height / 2, 2);
screen_write(p, &p->fg, p->width / 2, p->height - x, 2);
screen_write(p, &p->fg, p->width / 2, x, 2);
screen_write(p, &p->fg, p->width / 2 - 0x10 / 2 + x, p->height / 2, 2);
screen_write(p, &p->fg, p->width / 2, p->height / 2 - 0x10 / 2 + x, 2);
}
}
/* APIs */
Uint8
screen_dei(Device *d, Uint8 port)
{
switch(port) {
case 0x2: return screen.width >> 8;
case 0x3: return screen.width;
case 0x4: return screen.height >> 8;
case 0x5: return screen.height;
default: return d->dat[port];
}
}
void
screen_deo(Device *d, Uint8 port)
{
switch(port) {
case 0x1: d->vector = peek16(d->dat, 0x0); break;
case 0x5:
/* TODO: if(!FIXED_SIZE) set_size(peek16(d->dat, 0x2), peek16(d->dat, 0x4), 1); */
break;
case 0xe: {
Uint16 x = peek16(d->dat, 0x8);
Uint16 y = peek16(d->dat, 0xa);
Uint8 layer = d->dat[0xe] & 0x40;
screen_write(&screen, layer ? &screen.fg : &screen.bg, x, y, d->dat[0xe] & 0x3);
if(d->dat[0x6] & 0x01) poke16(d->dat, 0x8, x + 1); /* auto x+1 */
if(d->dat[0x6] & 0x02) poke16(d->dat, 0xa, y + 1); /* auto y+1 */
break;
}
case 0xf: {
Uint16 x = peek16(d->dat, 0x8);
Uint16 y = peek16(d->dat, 0xa);
Layer *layer = (d->dat[0xf] & 0x40) ? &screen.fg : &screen.bg;
Uint8 *addr = &d->mem[peek16(d->dat, 0xc)];
Uint8 twobpp = !!(d->dat[0xf] & 0x80);
screen_blit(&screen, layer, x, y, addr, d->dat[0xf] & 0xf, d->dat[0xf] & 0x10, d->dat[0xf] & 0x20, twobpp);
if(d->dat[0x6] & 0x04) poke16(d->dat, 0xc, peek16(d->dat, 0xc) + 8 + twobpp * 8); /* auto addr+8 / auto addr+16 */
if(d->dat[0x6] & 0x01) poke16(d->dat, 0x8, x + 8); /* auto x+8 */
if(d->dat[0x6] & 0x02) poke16(d->dat, 0xa, y + 8); /* auto y+8 */
break;
}
}
}

37
src/devices/screen.h Normal file
View File

@ -0,0 +1,37 @@
#include <stdlib.h>
/*
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.
*/
#define FIXED_SIZE 0
typedef struct Layer {
Uint8 *pixels;
Uint8 changed;
} Layer;
typedef struct Screen {
Uint32 palette[4], *pixels;
Uint16 width, height;
Layer fg, bg;
} Screen;
extern Screen screen;
void screen_palette(Screen *p, Uint8 *addr);
void screen_resize(Screen *p, Uint16 width, Uint16 height);
void screen_clear(Screen *p, Layer *layer);
void screen_redraw(Screen *p, Uint32 *pixels);
void screen_debug(Screen *p, Uint8 *stack, Uint8 wptr, Uint8 rptr, Uint8 *memory);
Uint8 screen_dei(Device *d, Uint8 port);
void screen_deo(Device *d, Uint8 port);

View File

@ -8,7 +8,7 @@
#pragma GCC diagnostic ignored "-Wpedantic"
#pragma clang diagnostic ignored "-Wtypedef-redefinition"
#include <SDL.h>
#include "devices/ppu.h"
#include "devices/screen.h"
#include "devices/apu.h"
#include "devices/file.h"
#include "devices/controller.h"
@ -30,7 +30,6 @@ WITH REGARD TO THIS SOFTWARE.
#define WIDTH 64 * 8
#define HEIGHT 40 * 8
#define PAD 4
#define FIXED_SIZE 0
#define POLYPHONY 4
#define BENCH 0
@ -39,8 +38,9 @@ static SDL_Texture *gTexture;
static SDL_Renderer *gRenderer;
static SDL_AudioDeviceID audio_id;
static SDL_Rect gRect;
/* devices */
static Ppu ppu;
static Apu apu[POLYPHONY];
static Device *devsystem, *devscreen, *devmouse, *devctrl, *devaudio0, *devconsole;
static Uint8 zoom = 1;
@ -106,20 +106,20 @@ set_window_size(SDL_Window *window, int w, int h)
static int
set_size(Uint16 width, Uint16 height, int is_resize)
{
ppu_resize(&ppu, width, height);
screen_resize(&screen, width, height);
gRect.x = PAD;
gRect.y = PAD;
gRect.w = ppu.width;
gRect.h = ppu.height;
gRect.w = screen.width;
gRect.h = screen.height;
if(gTexture != NULL) SDL_DestroyTexture(gTexture);
SDL_RenderSetLogicalSize(gRenderer, ppu.width + PAD * 2, ppu.height + PAD * 2);
gTexture = SDL_CreateTexture(gRenderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, ppu.width + PAD * 2, ppu.height + PAD * 2);
SDL_RenderSetLogicalSize(gRenderer, screen.width + PAD * 2, screen.height + PAD * 2);
gTexture = SDL_CreateTexture(gRenderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, screen.width + PAD * 2, screen.height + PAD * 2);
if(gTexture == NULL || SDL_SetTextureBlendMode(gTexture, SDL_BLENDMODE_NONE))
return error("gTexture", SDL_GetError());
if(SDL_UpdateTexture(gTexture, NULL, ppu.screen, sizeof(Uint32)) != 0)
if(SDL_UpdateTexture(gTexture, NULL, screen.pixels, sizeof(Uint32)) != 0)
return error("SDL_UpdateTexture", SDL_GetError());
if(is_resize)
set_window_size(gWindow, (ppu.width + PAD * 2) * zoom, (ppu.height + PAD * 2) * zoom);
set_window_size(gWindow, (screen.width + PAD * 2) * zoom, (screen.height + PAD * 2) * zoom);
return 1;
}
@ -127,9 +127,9 @@ static void
redraw(Uxn *u)
{
if(devsystem->dat[0xe])
ppu_debug(&ppu, u->wst.dat, u->wst.ptr, u->rst.ptr, u->ram.dat);
ppu_redraw(&ppu, ppu.screen);
if(SDL_UpdateTexture(gTexture, &gRect, ppu.screen, ppu.width * sizeof(Uint32)) != 0)
screen_debug(&screen, u->wst.dat, u->wst.ptr, u->rst.ptr, u->ram.dat);
screen_redraw(&screen, screen.pixels);
if(SDL_UpdateTexture(gTexture, &gRect, screen.pixels, screen.width * sizeof(Uint32)) != 0)
error("SDL_UpdateTexture", SDL_GetError());
SDL_RenderClear(gRenderer);
SDL_RenderCopy(gRenderer, gTexture, NULL, NULL);
@ -197,7 +197,7 @@ system_deo(Device *d, Uint8 port)
case 0x3: d->u->rst.ptr = d->dat[port]; break;
}
if(port > 0x7 && port < 0xe)
ppu_palette(&ppu, &d->dat[0x8]);
screen_palette(&screen, &d->dat[0x8]);
}
static void
@ -209,50 +209,6 @@ console_deo(Device *d, Uint8 port)
write(port - 0x7, (char *)&d->dat[port], 1);
}
static Uint8
screen_dei(Device *d, Uint8 port)
{
switch(port) {
case 0x2: return ppu.width >> 8;
case 0x3: return ppu.width;
case 0x4: return ppu.height >> 8;
case 0x5: return ppu.height;
default: return d->dat[port];
}
}
static void
screen_deo(Device *d, Uint8 port)
{
switch(port) {
case 0x1: d->vector = peek16(d->dat, 0x0); break;
case 0x5:
if(!FIXED_SIZE) set_size(peek16(d->dat, 0x2), peek16(d->dat, 0x4), 1);
break;
case 0xe: {
Uint16 x = peek16(d->dat, 0x8);
Uint16 y = peek16(d->dat, 0xa);
Uint8 layer = d->dat[0xe] & 0x40;
ppu_write(&ppu, layer ? &ppu.fg : &ppu.bg, x, y, d->dat[0xe] & 0x3);
if(d->dat[0x6] & 0x01) poke16(d->dat, 0x8, x + 1); /* auto x+1 */
if(d->dat[0x6] & 0x02) poke16(d->dat, 0xa, y + 1); /* auto y+1 */
break;
}
case 0xf: {
Uint16 x = peek16(d->dat, 0x8);
Uint16 y = peek16(d->dat, 0xa);
Layer *layer = (d->dat[0xf] & 0x40) ? &ppu.fg : &ppu.bg;
Uint8 *addr = &d->mem[peek16(d->dat, 0xc)];
Uint8 twobpp = !!(d->dat[0xf] & 0x80);
ppu_blit(&ppu, layer, x, y, addr, d->dat[0xf] & 0xf, d->dat[0xf] & 0x10, d->dat[0xf] & 0x20, twobpp);
if(d->dat[0x6] & 0x04) poke16(d->dat, 0xc, peek16(d->dat, 0xc) + 8 + twobpp * 8); /* auto addr+8 / auto addr+16 */
if(d->dat[0x6] & 0x01) poke16(d->dat, 0x8, x + 8); /* auto x+8 */
if(d->dat[0x6] & 0x02) poke16(d->dat, 0xa, y + 8); /* auto y+8 */
break;
}
}
}
static Uint8
audio_dei(Device *d, Uint8 port)
{
@ -370,14 +326,14 @@ static void
set_zoom(Uint8 scale)
{
zoom = clamp(scale, 1, 3);
set_window_size(gWindow, (ppu.width + PAD * 2) * zoom, (ppu.height + PAD * 2) * zoom);
set_window_size(gWindow, (screen.width + PAD * 2) * zoom, (screen.height + PAD * 2) * zoom);
}
static void
toggle_debugger(void)
{
devsystem->dat[0xe] = !devsystem->dat[0xe];
ppu_clear(&ppu, &ppu.fg);
screen_clear(&screen, &screen.fg);
}
static void
@ -502,8 +458,8 @@ run(Uxn *u)
/* Mouse */
else if(event.type == SDL_MOUSEMOTION)
mouse_pos(devmouse,
clamp(event.motion.x - PAD, 0, ppu.width - 1),
clamp(event.motion.y - PAD, 0, ppu.height - 1));
clamp(event.motion.x - PAD, 0, screen.width - 1),
clamp(event.motion.y - PAD, 0, screen.height - 1));
else if(event.type == SDL_MOUSEBUTTONUP)
mouse_up(devmouse, 0x1 << (event.button.button - 1));
else if(event.type == SDL_MOUSEBUTTONDOWN)
@ -537,7 +493,7 @@ run(Uxn *u)
console_input(u, event.cbutton.button);
}
uxn_eval(u, devscreen->vector);
if(ppu.fg.changed || ppu.bg.changed || devsystem->dat[0xe])
if(screen.fg.changed || screen.bg.changed || devsystem->dat[0xe])
redraw(u);
if(!BENCH) {
elapsed = (SDL_GetPerformanceCounter() - begin) / (double)SDL_GetPerformanceFrequency() * 1000.0f;