Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
6d171f5
restore linux sdl1 for debuging purposes
frostmorn Oct 11, 2025
8342008
init gitignore
frostmorn Oct 11, 2025
9dc5297
use after free in vid_findmode. trying to log dimensions of destroyed…
frostmorn Oct 11, 2025
797f9bf
missing include "osd.h" in memguard.c, implicit declaration(could bec…
frostmorn Oct 11, 2025
a0487a2
few more uint32 pointer casts to uintptr_t
frostmorn Oct 11, 2025
118caff
make a whole struct aligned by 2, and packed(pcxheader_s)
frostmorn Oct 11, 2025
26eea98
use uint32 for nametab to avoid casting to int, same for color calcul…
frostmorn Oct 11, 2025
f704115
well it doesn't break something, but sanitizer more happy
frostmorn Oct 11, 2025
61e9941
write past allocated mem block while trying to render 33rd tile
frostmorn Oct 11, 2025
ed4e3da
make this stuff signed to be sure no int conversions on pointers woul…
frostmorn Oct 11, 2025
62eeeca
finally we could remove that excessive loggage
frostmorn Oct 11, 2025
77d6838
use NES_UNIX and NES_OSD defines to avoid buildage for linux sdl1 in …
frostmorn Oct 11, 2025
46ffe35
ignore xofs
frostmorn Oct 11, 2025
f814f84
add check on sprite_x sprite_y in ppu_renderoam. some of those want t…
frostmorn Oct 11, 2025
98aea96
todo update
frostmorn Oct 11, 2025
dfe6037
APU DMC Register treated wrong way
frostmorn Oct 11, 2025
5f89c88
ensure valid ptr before fwrite
frostmorn Oct 12, 2025
7bec671
fix overdraw issue. When we've only one framebuffer, we still need ov…
frostmorn Oct 13, 2025
5ba6da5
elliminate NES_DOUBLE_FRAMEBUFFER completely
frostmorn Oct 13, 2025
c90e524
Restore xoffs as well as 33 ppu tiles cause origin of mem problem was…
frostmorn Oct 13, 2025
5c2163a
allow driver not provide lock_write. this effectively removes 134 KB …
frostmorn Oct 15, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
*.o
*.pch
.vscode*
vgcore.*
16 changes: 16 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
CC = gcc
CFLAGS = -m64 -Wno-unused-variable -Wno-unused-but-set-variable -Wno-unused-function -Werror=implicit-function-declaration -Werror=format -Werror=pointer-to-int-cast -fsanitize=address,undefined -fstack-protector-all -fstack-protector-strong -fstack-check -Wall -lm -lSDL -O0 -g3 -DNES_UNIX -DNES_SDL -I $(shell realpath src)
SRC = $(shell find src -name "*.c" )
OBJ = $(SRC:.c=.o)

all: linux_nofrendo

linux_nofrendo: $(OBJ)
$(CC) $(CFLAGS) -o $@ $(OBJ)

%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@

clean:
rm -f $(OBJ) linux_nofrendo

2 changes: 1 addition & 1 deletion src/bitmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ static bitmap_t *_make_bitmap(uint8 *data_addr, bool hw, int width,
if (false == bitmap->hardware)
{
bitmap->pitch = (bitmap->pitch + 3) & ~3;
bitmap->line[0] = (uint8 *)(((uint32)bitmap->data + overdraw + 3) & ~3);
bitmap->line[0] = (uint8 *)(((uintptr_t)bitmap->data + overdraw + 3) & ~3);
}
else
{
Expand Down
8 changes: 6 additions & 2 deletions src/cpu/nes6502.c
Original file line number Diff line number Diff line change
Expand Up @@ -1137,7 +1137,8 @@ static uint8 null_page[NES6502_BANKSIZE];
*/
INLINE uint32 zp_readword(register uint8 address)
{
return (uint32)(*(uint16 *)(ram + address));
// return (uint32)(*(uint16 *)(ram + address));
return ram[address] | (ram[address + 1] << 8);
}

INLINE uint32 bank_readword(register uint32 address)
Expand All @@ -1147,7 +1148,10 @@ INLINE uint32 bank_readword(register uint32 address)
** be fetching a word across page boundaries, which only would
** make sense if the banks were physically consecutive.
*/
return (uint32)(*(uint16 *)(cpu.mem_page[address >> NES6502_BANKSHIFT] + (address & NES6502_BANKMASK)));
// return (uint32)(*(uint16 *)(cpu.mem_page[address >> NES6502_BANKSHIFT] + (address & NES6502_BANKMASK)));

uint8 *ptr = cpu.mem_page[address >> NES6502_BANKSHIFT] + (address & NES6502_BANKMASK);
return (uint32)ptr[0] | ((uint32)ptr[1] << 8);
}

#else /* !HOST_LITTLE_ENDIAN */
Expand Down
6 changes: 2 additions & 4 deletions src/gui.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,9 @@ void gui_savesnap(void)
if (osd_makesnapname(filename, PATH_MAX) < 0)
return;

#ifdef NOFRENDO_DOUBLE_FRAMEBUFFER
if (pcx_write(filename, nes->vidbuf, nes->ppu->curpal))
#else /* !NOFRENDO_DOUBLE_FRAMEBUFFER */

if (pcx_write(filename, vid_getbuffer(), nes->ppu->curpal))
#endif /* !NOFRENDO_DOUBLE_FRAMEBUFFER */


return;

Expand Down
13 changes: 7 additions & 6 deletions src/memguard.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "noftypes.h"
#include "memguard.h"
#include "log.h"
#include "osd.h"

/* Maximum number of allocated blocks at any one time */
#define MAX_BLOCKS 4096
Expand Down Expand Up @@ -224,8 +225,8 @@ static void mem_deleteblock(void *data, char *file, int line)
{
if (mem_checkguardblock(mem_record[i].block_addr, GUARD_LENGTH))
{
sprintf(fail, "mem_deleteblock 0x%08X at line %d of %s -- block corrupt",
(uint32)data, line, file);
sprintf(fail, "mem_deleteblock 0x%08lX at line %d of %s -- block corrupt",
(uintptr_t)data, line, file);
ASSERT_MSG(fail);
}

Expand All @@ -234,8 +235,8 @@ static void mem_deleteblock(void *data, char *file, int line)
}
}

sprintf(fail, "mem_deleteblock 0x%08X at line %d of %s -- block not found",
(uint32)data, line, file);
sprintf(fail, "mem_deleteblock 0x%08lX at line %d of %s -- block not found",
(uintptr_t)data, line, file);
ASSERT_MSG(fail);
}
#endif /* NOFRENDO_DEBUG */
Expand Down Expand Up @@ -396,7 +397,7 @@ void mem_checkleaks(void)
if (mem_record[i].block_addr)
{
nofrendo_log_printf("addr: 0x%08X, size: %d, line %d of %s%s\n",
(uint32)mem_record[i].block_addr,
(uintptr_t)mem_record[i].block_addr,
mem_record[i].block_size,
mem_record[i].line_num,
mem_record[i].file_name,
Expand Down Expand Up @@ -426,7 +427,7 @@ void mem_checkblocks(void)
if (mem_checkguardblock(mem_record[i].block_addr, GUARD_LENGTH))
{
nofrendo_log_printf("addr: 0x%08X, size: %d, line %d of %s -- block corrupt\n",
(uint32)mem_record[i].block_addr,
(uintptr_t)mem_record[i].block_addr,
mem_record[i].block_size,
mem_record[i].line_num,
mem_record[i].file_name);
Expand Down
30 changes: 1 addition & 29 deletions src/nes/nes.c
Original file line number Diff line number Diff line change
Expand Up @@ -250,13 +250,6 @@ static void build_address_handlers(nes_t *machine)
/* raise an IRQ */
void nes_irq(void)
{
#ifdef NOFRENDO_DEBUG
#ifdef NOFRENDO_DOUBLE_FRAMEBUFFER
if (nes.scanline <= NES_SCREEN_HEIGHT)
memset(nes.vidbuf->line[nes.scanline - 1], GUI_RED, NES_SCREEN_WIDTH);
#endif /* NOFRENDO_DOUBLE_FRAMEBUFFER */
#endif /* NOFRENDO_DEBUG */

nes6502_irq();
}

Expand Down Expand Up @@ -304,11 +297,8 @@ static void nes_renderframe(bool draw_flag)

while (262 != nes.scanline)
{
#ifdef NOFRENDO_DOUBLE_FRAMEBUFFER
ppu_scanline(nes.vidbuf, nes.scanline, draw_flag);
#else /* !NOFRENDO_DOUBLE_FRAMEBUFFER */

ppu_scanline(vid_getbuffer(), nes.scanline, draw_flag);
#endif /* !NOFRENDO_DOUBLE_FRAMEBUFFER */

if (241 == nes.scanline)
{
Expand Down Expand Up @@ -348,12 +338,6 @@ static void system_video(bool draw)
return;
}

#ifdef NOFRENDO_DOUBLE_FRAMEBUFFER
/* blit the NES screen to our video surface */
vid_blit(nes.vidbuf, 0, (NES_SCREEN_HEIGHT - NES_VISIBLE_HEIGHT) / 2,
0, 0, NES_SCREEN_WIDTH, NES_VISIBLE_HEIGHT);
#endif /* NOFRENDO_DOUBLE_FRAMEBUFFER */

/* overlay our GUI on top of it */
gui_frame(true);

Expand Down Expand Up @@ -446,10 +430,6 @@ void nes_destroy(nes_t **machine)
ppu_destroy(&(*machine)->ppu);
apu_destroy(&(*machine)->apu);

#ifdef NOFRENDO_DOUBLE_FRAMEBUFFER
bmp_destroy(&(*machine)->vidbuf);
#endif /* NOFRENDO_DOUBLE_FRAMEBUFFER */

if ((*machine)->cpu)
{
if ((*machine)->cpu->mem_page[0])
Expand Down Expand Up @@ -525,14 +505,6 @@ nes_t *nes_create(void)

memset(machine, 0, sizeof(nes_t));

/* bitmap */
/* 8 pixel overdraw */
#ifdef NOFRENDO_DOUBLE_FRAMEBUFFER
machine->vidbuf = bmp_create(NES_SCREEN_WIDTH, NES_SCREEN_HEIGHT, 8);
if (NULL == machine->vidbuf)
goto _fail;
#endif /* NOFRENDO_DOUBLE_FRAMEBUFFER */

machine->autoframeskip = true;

/* cpu */
Expand Down
5 changes: 0 additions & 5 deletions src/nes/nes.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,6 @@ typedef struct nes_s
mmc_t *mmc;
rominfo_t *rominfo;

/* video buffer */
#ifdef NOFRENDO_DOUBLE_FRAMEBUFFER
bitmap_t *vidbuf;
#endif /* NOFRENDO_DOUBLE_FRAMEBUFFER */

bool fiq_occurred;
uint8 fiq_state;
int fiq_cycles;
Expand Down
18 changes: 10 additions & 8 deletions src/nes/nes_ppu.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@
#define PPU_MEM(x) ppu.page[(x) >> 10][(x)]

/* Background (color 0) and solid sprite pixel flags */
#define BG_TRANS 0x80
#define SP_PIXEL 0x40
#define BG_TRANS 0x80U
#define SP_PIXEL 0x40U
#define BG_CLEAR(V) ((V)&BG_TRANS)
#define BG_SOLID(V) (0 == BG_CLEAR(V))
#define SP_CLEAR(V) (0 == ((V)&SP_PIXEL))
Expand All @@ -62,7 +62,7 @@ void ppu_displaysprites(bool display)

void ppu_setcontext(ppu_t *src_ppu)
{
int nametab[4];
uint32 nametab[4];
ASSERT(src_ppu);
ppu = *src_ppu;

Expand Down Expand Up @@ -577,7 +577,6 @@ INLINE void draw_bgtile(uint8 *surface, uint8 pat1, uint8 pat2,
const uint8 *colors)
{
uint32 pattern = ((pat2 & 0xAA) << 8) | ((pat2 & 0x55) << 1) | ((pat1 & 0xAA) << 7) | (pat1 & 0x55);

*surface++ = colors[(pattern >> 14) & 3];
*surface++ = colors[(pattern >> 6) & 3];
*surface++ = colors[(pattern >> 12) & 3];
Expand Down Expand Up @@ -702,7 +701,6 @@ static void ppu_renderbg(uint8 *vidbuf)
memset(vidbuf, FULLBG, NES_SCREEN_WIDTH);
return;
}

bmp_ptr = vidbuf - ppu.tile_xofs; /* scroll x */
refresh_vaddr = 0x2000 + (ppu.vaddr & 0x0FE0); /* mask out x tile */
x_tile = ppu.vaddr & 0x1F;
Expand All @@ -719,16 +717,19 @@ static void ppu_renderbg(uint8 *vidbuf)

/* ppu fetches 33 tiles */
tile_count = 33;

while (tile_count--)
{
// printf("bmp_ptr = %p, vidbuf = %p, offset = %ld\n",
// (void*)bmp_ptr, (void*)vidbuf, bmp_ptr - vidbuf);
/* Tile number from nametable */
tile_index = *tile_ptr++;
data_ptr = &PPU_MEM(bg_offset + (tile_index << 4));

/* Handle $FD/$FE tile VROM switching (PunchOut) */
if (ppu.latchfunc)
ppu.latchfunc(ppu.bg_base, tile_index);

// Shit is happening here
draw_bgtile(bmp_ptr, data_ptr[0], data_ptr[8], ppu.palette + col_high);
bmp_ptr += 8;

Expand Down Expand Up @@ -825,6 +826,9 @@ static void ppu_renderoam(uint8 *vidbuf, int scanline)
sprite_x = sprite_ptr->x_loc;
tile_index = sprite_ptr->tile;
attrib = sprite_ptr->atr;
if (sprite_x > NES_SCREEN_WIDTH)
continue;


bmp_ptr = buf_ptr + sprite_x;

Expand Down Expand Up @@ -1173,7 +1177,6 @@ static void draw_sprite(bitmap_t *bmp, int x, int y, uint8 tile_num, uint8 attri
vram_adr = ppu.obj_base + (tile_num << 4);

data_ptr = &PPU_MEM(vram_adr);

for (line = 0; line < height; line++)
{
if (line == 8)
Expand Down Expand Up @@ -1234,7 +1237,6 @@ void ppu_dumppattern(bitmap_t *bmp, int table_num, int x_loc, int y_loc, int col
{
data_ptr = &PPU_MEM((table_num << 12) + (tile_num << 4));
ptr = bmp_ptr;

for (line = 0; line < 8; line++)
{
draw_bgtile(ptr, data_ptr[0], data_ptr[8], ppu.palette + col_high);
Expand Down
4 changes: 2 additions & 2 deletions src/nes/nes_ppu.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ typedef struct ppu_s
/* hardware registers */
uint8 ctrl0, ctrl1, stat, oam_addr;
uint32 vaddr, vaddr_latch;
int tile_xofs, flipflop;
int vaddr_inc;
uint8 tile_xofs, flipflop;
uint32 vaddr_inc;
uint32 tile_nametab;

uint8 obj_height;
Expand Down
13 changes: 10 additions & 3 deletions src/nes/nes_rom.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,16 @@ static void rom_savesram(rominfo_t *rominfo)
fp = fopen(fn, "wb");
if (NULL != fp)
{
fwrite(rominfo->sram, SRAM_BANK_LENGTH, rominfo->sram_banks, fp);
fclose(fp);
nofrendo_log_printf("Wrote battery RAM to %s.\n", fn);
if (rominfo->sram){
fwrite(rominfo->sram, SRAM_BANK_LENGTH, rominfo->sram_banks, fp);
fclose(fp);
nofrendo_log_printf("Wrote battery RAM to %s.\n", fn);
}
else
{
fclose(fp);
nofrendo_log_printf("Wrote battery RAM to %s failed.\n", fn);
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/nofrendo.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ static system_t detect_systemtype(const char *filename)
static int install_timer(int hertz)
{
return osd_installtimer(hertz, (void *)timer_isr,
(int)timer_isr_end - (int)timer_isr,
(uintptr_t)timer_isr_end - (uintptr_t)timer_isr,
(void *)&nofrendo_ticks,
sizeof(nofrendo_ticks));
}
Expand Down
10 changes: 5 additions & 5 deletions src/noftypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,14 @@

#include <stdbool.h>

#define NOFRENDO_DEBUG
#define NOFRENDO_MEM_DEBUG
// #define NOFRENDO_DEBUG
// #define NOFRENDO_MEM_DEBUG
// #define NOFRENDO_VRAM_DEBUG
// #define NOFRENDO_LOG_TO_FILE
/* For the ESP32, it costs too much memory to render to a separate buffer and blit that to the main buffer.
Instead, the code has been modified to directly grab the primary buffer from the video subsystem and render
there, saving us about 64K of memory. */
// #define NOFRENDO_DOUBLE_FRAMEBUFFER


/* Define this if running on little-endian (x86) systems */
#define HOST_LITTLE_ENDIAN
Expand All @@ -60,13 +60,13 @@ typedef signed int int32;
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned int uint32;

#include <stdint.h>
#include "memguard.h"
#include "log.h"

#ifdef NOFRENDO_DEBUG

#define ASSERT(expr) nofrendo_log_assert((int)(expr), __LINE__, __FILE__, NULL)
#define ASSERT(expr) nofrendo_log_assert((uintptr_t)(expr), __LINE__, __FILE__, NULL)
#define ASSERT_MSG(msg) nofrendo_log_assert(false, __LINE__, __FILE__, (msg))

#else /* !NOFRENDO_DEBUG */
Expand Down
38 changes: 19 additions & 19 deletions src/pcx.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,25 +32,25 @@
/* Got these out of ZSoft's document */
typedef struct pcxheader_s
{
uint8 Manufacturer __PACKED__;
uint8 Version __PACKED__;
uint8 Encoding __PACKED__;
uint8 BitsPerPixel __PACKED__;
uint16 Xmin __PACKED__;
uint16 Ymin __PACKED__;
uint16 Xmax __PACKED__;
uint16 Ymax __PACKED__;
uint16 HDpi __PACKED__;
uint16 VDpi __PACKED__;
uint8 Colormap[48] __PACKED__;
uint8 Reserved __PACKED__;
uint8 NPlanes __PACKED__;
uint16 BytesPerLine __PACKED__;
uint16 PaletteInfo __PACKED__;
uint16 HscreenSize __PACKED__;
uint16 VscreenSize __PACKED__;
uint8 Filler[54] __PACKED__;
} pcxheader_t;
uint8 Manufacturer;
uint8 Version;
uint8 Encoding;
uint8 BitsPerPixel;
uint16 Xmin;
uint16 Ymin;
uint16 Xmax;
uint16 Ymax;
uint16 HDpi;
uint16 VDpi;
uint8 Colormap[48];
uint8 Reserved;
uint8 NPlanes;
uint16 BytesPerLine;
uint16 PaletteInfo;
uint16 HscreenSize;
uint16 VscreenSize;
uint8 Filler[54] ;
} __PACKED__ __attribute__((aligned(2))) pcxheader_t;

extern int pcx_write(char *filename, bitmap_t *bmp, rgb_t *pal);

Expand Down
Loading