diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..be743c1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.o +*.pch +.vscode* +vgcore.* \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..7c95a47 --- /dev/null +++ b/Makefile @@ -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 + diff --git a/src/bitmap.c b/src/bitmap.c index 85ca5d7..ab48e33 100644 --- a/src/bitmap.c +++ b/src/bitmap.c @@ -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 { diff --git a/src/cpu/nes6502.c b/src/cpu/nes6502.c index 24bead4..767f3cb 100644 --- a/src/cpu/nes6502.c +++ b/src/cpu/nes6502.c @@ -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) @@ -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 */ diff --git a/src/gui.c b/src/gui.c index 126c14b..61befd6 100644 --- a/src/gui.c +++ b/src/gui.c @@ -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; diff --git a/src/memguard.c b/src/memguard.c index e484188..1466494 100644 --- a/src/memguard.c +++ b/src/memguard.c @@ -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 @@ -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); } @@ -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 */ @@ -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, @@ -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); diff --git a/src/nes/nes.c b/src/nes/nes.c index b5efc83..bd13f2c 100644 --- a/src/nes/nes.c +++ b/src/nes/nes.c @@ -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(); } @@ -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) { @@ -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); @@ -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]) @@ -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 */ diff --git a/src/nes/nes.h b/src/nes/nes.h index b36d902..be12efb 100644 --- a/src/nes/nes.h +++ b/src/nes/nes.h @@ -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; diff --git a/src/nes/nes_ppu.c b/src/nes/nes_ppu.c index 93b9a48..8aad653 100644 --- a/src/nes/nes_ppu.c +++ b/src/nes/nes_ppu.c @@ -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)) @@ -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; @@ -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]; @@ -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; @@ -719,8 +717,11 @@ 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)); @@ -728,7 +729,7 @@ static void ppu_renderbg(uint8 *vidbuf) /* 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; @@ -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; @@ -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) @@ -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); diff --git a/src/nes/nes_ppu.h b/src/nes/nes_ppu.h index ecaf48b..4c96a12 100644 --- a/src/nes/nes_ppu.h +++ b/src/nes/nes_ppu.h @@ -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; diff --git a/src/nes/nes_rom.c b/src/nes/nes_rom.c index b2fbc4f..ca0cee1 100644 --- a/src/nes/nes_rom.c +++ b/src/nes/nes_rom.c @@ -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); + } } } } diff --git a/src/nofrendo.c b/src/nofrendo.c index 4026ab4..1e476dd 100644 --- a/src/nofrendo.c +++ b/src/nofrendo.c @@ -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)); } diff --git a/src/noftypes.h b/src/noftypes.h index c72ffa0..3a2dc03 100644 --- a/src/noftypes.h +++ b/src/noftypes.h @@ -28,14 +28,14 @@ #include -#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 @@ -60,13 +60,13 @@ typedef signed int int32; typedef unsigned char uint8; typedef unsigned short uint16; typedef unsigned int uint32; - +#include #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 */ diff --git a/src/pcx.h b/src/pcx.h index c36d4b6..cff8850 100644 --- a/src/pcx.h +++ b/src/pcx.h @@ -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); diff --git a/src/sdl/sdl.c b/src/sdl/sdl.c new file mode 100644 index 0000000..713566b --- /dev/null +++ b/src/sdl/sdl.c @@ -0,0 +1,790 @@ +/* vim: set tabstop=3 expandtab: +** +** Nofrendo (c) 1998-2000 Matthew Conte (matt@conte.com) +** +** +** This program is free software; you can redistribute it and/or +** modify it under the terms of version 2 of the GNU Library General +** Public License as published by the Free Software Foundation. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** Library General Public License for more details. To obtain a +** copy of the GNU Library General Public License, write to the Free +** Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +** +** Any permitted reproduction of these routines, in whole or in part, +** must bear this legend. +** +** +** sdl.c +** +** $Id: sdl.c,v 1.2 2001/04/27 14:37:11 neil Exp $ +** +*/ +#ifdef NES_SDL +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define DEFAULT_SAMPLERATE 22050 +#define DEFAULT_BPS 8 +#define DEFAULT_FRAGSIZE 1024 + +#define DEFAULT_WIDTH 256 +#define NES_VISIBLE_HEIGHT NES_SCREEN_HEIGHT +#define DEFAULT_HEIGHT NES_VISIBLE_HEIGHT + +/* +** Timer +*/ + +static void (*timer_callback)(void) = NULL; +static int tick_ideal = 0; +static int tick_interval = 0; + +Uint32 mySDLTimer(Uint32 i) +{ + static int tickDiff = 0; + Uint32 tickLast; + + tickLast = SDL_GetTicks(); + + if (timer_callback) + timer_callback(); + + tickDiff += tick_interval - tick_ideal + tickLast - SDL_GetTicks(); + + if (tickDiff >= 10) + { + tickDiff -= 10; + return tick_interval - 10; + } + else + { + return tick_interval; + } +} +/* +static int round(double value) +{ + int upper, lower; + upper = (int) ceil(value); + lower = (int) floor(value); + + if (upper - value > value - lower) + return lower; + else + return upper; +} +*/ +int osd_installtimer(int frequency, void *func, int funcsize, void *counter, int countersize) +{ + double ideal = 1000 / frequency; + + /* these arguments are used only for djgpp, which needs to lock code/data */ + UNUSED(counter); + UNUSED(countersize); + UNUSED(funcsize); + + tick_ideal = round(ideal); + tick_interval = round(ideal / 10) * 10; + + SDL_SetTimer(tick_interval, mySDLTimer); + + timer_callback = func; + + return 0; +} +void *mem_alloc( int size, bool prefer_fast_memory){ + return malloc(size); +} +int main(int argc, char **argv){ + return nofrendo_main(argc, argv); +} + +/* +** Audio +*/ +static int sound_bps = DEFAULT_BPS; +static int sound_samplerate = DEFAULT_SAMPLERATE; +static int sound_fragsize = DEFAULT_FRAGSIZE; +static unsigned char *audioBuffer = NULL; +static void (*audio_callback)(void *buffer, int length) = NULL; + +/* this is the callback that SDL calls to obtain more audio data */ +static void sdl_audio_player(void *udata, unsigned char *stream, int len) +{ + /* SDL requests buffer fills in terms of bytes, not samples */ + if (16 == sound_bps) + len /= 2; + + if (audio_callback) + audio_callback(stream, len); +} + +void osd_setsound(void (*playfunc)(void *buffer, int length)) +{ + audio_callback = playfunc; +} + +static void osd_stopsound(void) +{ + audio_callback = NULL; + + SDL_CloseAudio(); + if (NULL != audioBuffer) + free(audioBuffer); +} + +static int osd_init_sound(void) +{ + SDL_AudioSpec wanted, obtained; + unsigned int bufferSize; + + sound_bps = config.read_int("sdlaudio", "sound_bps", DEFAULT_BPS); + sound_samplerate = config.read_int("sdlaudio", "sound_samplerate", DEFAULT_SAMPLERATE); + sound_fragsize = config.read_int("sdlaudio", "sound_fragsize", DEFAULT_FRAGSIZE); + + if (sound_bps != 8 && sound_bps != 16) + sound_bps = 8; + + if (sound_samplerate < 5000) + sound_samplerate = 5000; + else if (sound_samplerate > 48000) + sound_samplerate = 48000; + + if (sound_fragsize < 128) + sound_fragsize = 128; + else if (sound_fragsize > 32768) + sound_fragsize = 32768; + + audio_callback = NULL; + + /* set the audio format */ + wanted.freq = sound_samplerate; + wanted.format = (sound_bps == 8) ? AUDIO_U8 : AUDIO_S16; + wanted.channels = 1; /* 1 = mono, 2 = stereo */ + wanted.samples = sound_fragsize; + wanted.callback = sdl_audio_player; + wanted.userdata = NULL; + + if (SDL_OpenAudio (&wanted, &obtained) < 0) + { + nofrendo_log_printf("Couldn't open audio: %s\n", SDL_GetError()); + return -1; + } + + /* ensure we get U8 or S16 */ + if (AUDIO_U8 != obtained.format && AUDIO_S16 != obtained.format) + { + nofrendo_log_printf("Could not get correct audio output format\n"); + return -1; + } + + sound_bps = (obtained.format == AUDIO_U8) ? 8 : 16; + sound_samplerate = obtained.freq; + /* twice as big, to be on the safe side */ + bufferSize = (sound_bps / 8) * obtained.samples * 2; + + audioBuffer = malloc(bufferSize); + if (NULL == audioBuffer) + { + nofrendo_log_printf("error allocating audio buffer\n"); + return -1; + } + + SDL_PauseAudio(0); + return 0; +} + +void osd_getsoundinfo(sndinfo_t *info) +{ + info->sample_rate = sound_samplerate; + info->bps = sound_bps; +} + +/* +** Video +*/ + +static int init(int width, int height); +static void shutdown(void); +static int set_mode(int width, int height); +static void set_palette(rgb_t *pal); +static void clear(uint8 color); +static bitmap_t *lock_write(void); +static void free_write(int num_dirties, rect_t *dirty_rects); + +viddriver_t sdlDriver = +{ + "Simple DirectMedia Layer", /* name */ + init, /* init */ + shutdown, /* shutdown */ + set_mode, /* set_mode */ + set_palette, /* set_palette */ + clear, /* clear */ + lock_write, /* lock_write */ + free_write, /* free_write */ + NULL, /* custom_blit */ + false /* invalidate flag */ +}; + +void osd_getvideoinfo(vidinfo_t *info) +{ + info->default_width = DEFAULT_WIDTH; + info->default_height = DEFAULT_HEIGHT; + info->driver = &sdlDriver; +} + +/* Now that the driver declaration is out of the way, on to the SDL stuff */ +static SDL_Surface *mySurface = NULL; +static SDL_Color myPalette[256]; +static bitmap_t *myBitmap = NULL; +static bool fullscreen = false; + +/* flip between full screen and windowed */ +void osd_togglefullscreen(int code) +{ + bool pause; + nes_t *nes = nes_getcontextptr(); + + if (INP_STATE_MAKE != code) + return; + + ASSERT(nes); + + pause = nes->pause; + nes->pause = true; + + fullscreen ^= true; + + if (set_mode(mySurface->w, mySurface->h)) + ASSERT(0); + + sdlDriver.invalidate = true; + + nes->pause = pause; +} + +/* initialise SDL video */ +static int init(int width, int height) +{ + return set_mode(width, height); +} + +/* squash memory leaks */ +static void shutdown(void) +{ + if (NULL != mySurface) + { + SDL_FreeSurface(mySurface); + mySurface = NULL; + } + + if (NULL != myBitmap) + bmp_destroy(&myBitmap); +} + +/* set a video mode */ +static int set_mode(int width, int height) +{ + int flags; + bool restorePalette; + + if (NULL != mySurface) + { + SDL_FreeSurface(mySurface); + mySurface = NULL; + restorePalette = true; + } + + if (fullscreen) + { + flags = SDL_HWSURFACE | SDL_HWPALETTE | SDL_FULLSCREEN; + mySurface = SDL_SetVideoMode(width, height, 8, flags); + if (NULL == mySurface) + nofrendo_log_printf("Fullscreeen failed: %s\n", SDL_GetError()); + } + + if (NULL == mySurface) + { + fullscreen = false; + flags = SDL_HWSURFACE | SDL_HWPALETTE; + mySurface = SDL_SetVideoMode(width, height, 8, flags); + } + + if (NULL == mySurface) + { + nofrendo_log_printf("SDL Video failed: %s\n", SDL_GetError()); + return -1; + } + + if (restorePalette) + { + SDL_SetColors(mySurface, myPalette, 0, 256); + } + + SDL_ShowCursor(0); + return 0; +} + +/* copy nes palette over to hardware */ +static void set_palette(rgb_t *pal) +{ + int i; + + for (i = 0; i < 256; i++) + { + myPalette[i].r = pal[i].r; + myPalette[i].g = pal[i].g; + myPalette[i].b = pal[i].b; + } + + SDL_SetColors(mySurface, myPalette, 0, 256); +} + +/* clear all frames to a particular color */ +static void clear(uint8 color) +{ + SDL_FillRect(mySurface, 0, color); +} + +/* acquire the directbuffer for writing */ +static bitmap_t *lock_write(void) +{ + SDL_LockSurface(mySurface); + myBitmap = bmp_createhw(mySurface->pixels, mySurface->w, + mySurface->h, mySurface->pitch); + return myBitmap; +} + +/* release the resource */ +static void free_write(int num_dirties, rect_t *dirty_rects) +{ + bmp_destroy(&myBitmap); + SDL_UnlockSurface(mySurface); + + if (-1 == num_dirties) + { + SDL_UpdateRect(mySurface, 0, 0, 0, 0); + } + else if (num_dirties > 0) + { + /* loop through and modify the rects to be in terms of the screen */ + if (NES_SCREEN_WIDTH < mySurface->w || NES_VISIBLE_HEIGHT < mySurface->h) + { + int i, x_offset, y_offset; + + x_offset = (mySurface->w - NES_SCREEN_WIDTH) >> 1; + y_offset = (mySurface->h - NES_VISIBLE_HEIGHT) >> 1; + + for (i = 0; i < num_dirties; i++) + { + dirty_rects[i].x += x_offset; + dirty_rects[i].y += y_offset; + } + } + + SDL_UpdateRects(mySurface, num_dirties, (SDL_Rect *) dirty_rects); + } +} + +/* +** Input +*/ + +typedef struct joystick_s +{ + SDL_Joystick *js; + int *button_array; + int *axis_array; +} joystick_t; + +static joystick_t **joystick_array = 0; +static int joystick_count = 0; + +static int key_array[SDLK_LAST]; +#define LOAD_KEY(key, def_key) \ +key_array[key] = config.read_int("sdlkeys", #key, def_key) + +static void osd_initinput() +{ + int i, j; + SDL_Joystick *js; + char group[255]; + char key[255]; + + /* joystick */ + + joystick_count = SDL_NumJoysticks(); + joystick_array = malloc(joystick_count * sizeof(joystick_t *)); + + if (NULL == joystick_array) + { + nofrendo_log_printf("error allocating space for joystick array\n"); + joystick_count = 0; + } + + nofrendo_log_printf("joystick_count == %i\n", joystick_count); + + for (i = 0; i < joystick_count; i++) + { + sprintf(group, "sdljoystick%i", i); + js = SDL_JoystickOpen(i); + + if (js) + { + joystick_array[i] = malloc(sizeof(joystick_t)); + joystick_array[i]->js = js; + + nofrendo_log_printf("joystick %i is a %s\n", i, SDL_JoystickName(i)); + + /* load buttons */ + j = SDL_JoystickNumButtons(joystick_array[i]->js); + joystick_array[i]->button_array = malloc(j * sizeof(int)); + for (j--; j >= 0; j--) + { + sprintf(key, "button%i", j); + joystick_array[i]->button_array[j] = config.read_int(group, key, event_none); + } + + /* load axes */ + j = SDL_JoystickNumAxes(joystick_array[i]->js); + joystick_array[i]->axis_array = malloc(j * sizeof(int) * 2); + for (j--; j >= 0; j--) + { + sprintf(key, "positiveaxis%i", j); + joystick_array[i]->axis_array[(j << 1) + 1] = config.read_int(group, key, event_none); + + sprintf(key, "negativeaxis%i", j); + joystick_array[i]->axis_array[j << 1] = config.read_int(group, key, event_none); + } + } + else + { + joystick_array[i] = 0; + } + } + + SDL_JoystickEventState(SDL_ENABLE); + + /* keyboard */ + + LOAD_KEY(SDLK_ESCAPE, event_quit); + + LOAD_KEY(SDLK_F1, event_soft_reset); + LOAD_KEY(SDLK_F2, event_hard_reset); + LOAD_KEY(SDLK_F3, event_gui_toggle_fps); + LOAD_KEY(SDLK_F4, event_snapshot); + LOAD_KEY(SDLK_F5, event_state_save); + LOAD_KEY(SDLK_F6, event_toggle_sprites); + LOAD_KEY(SDLK_F7, event_state_load); + LOAD_KEY(SDLK_F8, event_none); + LOAD_KEY(SDLK_F9, event_none); + LOAD_KEY(SDLK_F10, event_osd_1); + LOAD_KEY(SDLK_F11, event_none); + LOAD_KEY(SDLK_F12, event_none); + + LOAD_KEY(SDLK_BACKQUOTE, event_none); + + LOAD_KEY(SDLK_1, event_state_slot_1); + LOAD_KEY(SDLK_EXCLAIM, event_state_slot_1); + LOAD_KEY(SDLK_2, event_state_slot_2); + LOAD_KEY(SDLK_AT, event_state_slot_2); + LOAD_KEY(SDLK_3, event_state_slot_3); + LOAD_KEY(SDLK_HASH, event_state_slot_3); + LOAD_KEY(SDLK_4, event_state_slot_4); + LOAD_KEY(SDLK_DOLLAR, event_state_slot_4); + LOAD_KEY(SDLK_5, event_state_slot_5); +/* LOAD_KEY(SDLK_PERCENT, event_state_slot_5);*/ + LOAD_KEY(SDLK_6, event_state_slot_6); + LOAD_KEY(SDLK_CARET, event_state_slot_6); + LOAD_KEY(SDLK_7, event_state_slot_7); + LOAD_KEY(SDLK_AMPERSAND, event_state_slot_7); + LOAD_KEY(SDLK_8, event_state_slot_8); + LOAD_KEY(SDLK_ASTERISK, event_state_slot_8); + LOAD_KEY(SDLK_9, event_state_slot_9); + LOAD_KEY(SDLK_LEFTPAREN, event_state_slot_9); + LOAD_KEY(SDLK_0, event_state_slot_0); + LOAD_KEY(SDLK_RIGHTPAREN, event_state_slot_0); + + LOAD_KEY(SDLK_MINUS, event_gui_pattern_color_down); + LOAD_KEY(SDLK_UNDERSCORE, event_gui_pattern_color_down); + LOAD_KEY(SDLK_EQUALS, event_gui_pattern_color_up); + LOAD_KEY(SDLK_PLUS, event_gui_pattern_color_up); + + LOAD_KEY(SDLK_BACKSPACE, event_gui_display_info); + + LOAD_KEY(SDLK_TAB, event_joypad1_select); + + LOAD_KEY(SDLK_q, event_toggle_channel_0); + LOAD_KEY(SDLK_w, event_toggle_channel_1); + LOAD_KEY(SDLK_e, event_toggle_channel_2); + LOAD_KEY(SDLK_r, event_toggle_channel_3); + LOAD_KEY(SDLK_t, event_toggle_channel_4); + LOAD_KEY(SDLK_y, event_toggle_channel_5); + LOAD_KEY(SDLK_u, event_palette_hue_down); + LOAD_KEY(SDLK_i, event_palette_hue_up); + LOAD_KEY(SDLK_o, event_gui_toggle_oam); + LOAD_KEY(SDLK_p, event_gui_toggle_pattern); + +/* LOAD_KEY(SDLK_LEFTBRACE, event_none); + LOAD_KEY(SDLK_RIGHTBRACE, event_none);*/ + LOAD_KEY(SDLK_LEFTBRACKET, event_none); + LOAD_KEY(SDLK_RIGHTBRACKET, event_none); + LOAD_KEY(SDLK_BACKSLASH, event_toggle_frameskip); +/* LOAD_KEY(SDLK_Bar, event_toggle_frameskip);*/ + + LOAD_KEY(SDLK_a, event_gui_toggle_wave); + LOAD_KEY(SDLK_s, event_set_filter_0); + LOAD_KEY(SDLK_d, event_set_filter_1); + LOAD_KEY(SDLK_f, event_set_filter_2); + LOAD_KEY(SDLK_g, event_none); + LOAD_KEY(SDLK_h, event_none); + LOAD_KEY(SDLK_j, event_palette_tint_down); + LOAD_KEY(SDLK_k, event_palette_tint_up); + LOAD_KEY(SDLK_l, event_palette_set_shady); + LOAD_KEY(SDLK_COLON, event_palette_set_default); + LOAD_KEY(SDLK_SEMICOLON, event_palette_set_default); + LOAD_KEY(SDLK_QUOTEDBL, event_none); + LOAD_KEY(SDLK_RETURN, event_joypad1_start); + LOAD_KEY(SDLK_PAUSE, event_togglepause); + + LOAD_KEY(SDLK_z, event_joypad1_b); + LOAD_KEY(SDLK_x, event_joypad1_a); + LOAD_KEY(SDLK_c, event_joypad1_select); + LOAD_KEY(SDLK_v, event_joypad1_start); + LOAD_KEY(SDLK_b, event_joypad2_b); + LOAD_KEY(SDLK_n, event_joypad2_a); + LOAD_KEY(SDLK_m, event_joypad2_select); + LOAD_KEY(SDLK_COMMA, event_joypad2_start); + LOAD_KEY(SDLK_LESS, event_none); + LOAD_KEY(SDLK_PERIOD, event_none); + LOAD_KEY(SDLK_GREATER, event_none); + LOAD_KEY(SDLK_QUESTION, event_none); + LOAD_KEY(SDLK_SLASH, event_none); + + LOAD_KEY(SDLK_SPACE, event_gui_toggle); + + LOAD_KEY(SDLK_LCTRL, event_joypad1_b); + LOAD_KEY(SDLK_RCTRL, event_joypad1_b); + LOAD_KEY(SDLK_LALT, event_joypad1_a); + LOAD_KEY(SDLK_RALT, event_joypad1_a); + LOAD_KEY(SDLK_LSHIFT, event_joypad1_a); + LOAD_KEY(SDLK_RSHIFT, event_joypad1_a); + + LOAD_KEY(SDLK_KP1, event_none); + LOAD_KEY(SDLK_KP2, event_joypad1_down); + LOAD_KEY(SDLK_KP3, event_none); + LOAD_KEY(SDLK_KP4, event_joypad1_left); + LOAD_KEY(SDLK_KP5, event_startsong); + LOAD_KEY(SDLK_KP6, event_joypad1_right); + LOAD_KEY(SDLK_KP7, event_songdown); + LOAD_KEY(SDLK_KP8, event_joypad1_up); + LOAD_KEY(SDLK_KP9, event_songup); + LOAD_KEY(SDLK_UP, event_joypad1_up); + LOAD_KEY(SDLK_DOWN, event_joypad1_down); + LOAD_KEY(SDLK_LEFT, event_joypad1_left); + LOAD_KEY(SDLK_RIGHT, event_joypad1_right); + LOAD_KEY(SDLK_HOME, event_none); + LOAD_KEY(SDLK_END, event_none); + LOAD_KEY(SDLK_PAGEUP, event_none); + LOAD_KEY(SDLK_PAGEDOWN, event_none); + LOAD_KEY(SDLK_KP_PLUS, event_toggle_frameskip); + + /* events */ + + event_set(event_osd_1, osd_togglefullscreen); +} + +void osd_getinput(void) +{ + int code, highval, lowval; + SDL_Event myEvent; + event_t func_event; + + while (SDL_PollEvent(&myEvent)) + { + switch(myEvent.type) + { + case SDL_KEYDOWN: + case SDL_KEYUP: + code = (myEvent.key.state == SDL_PRESSED) ? INP_STATE_MAKE : INP_STATE_BREAK; + + func_event = event_get(key_array[myEvent.key.keysym.sym]); + if (func_event) + func_event(code); + break; + + case SDL_QUIT: + event_get(event_quit)(INP_STATE_MAKE); + break; + + case SDL_JOYAXISMOTION: + highval = (myEvent.jaxis.value > 0) ? INP_STATE_MAKE : INP_STATE_BREAK; + lowval = (myEvent.jaxis.value < 0) ? INP_STATE_MAKE : INP_STATE_BREAK; + + func_event = event_get(joystick_array[myEvent.jaxis.which]->axis_array[myEvent.jaxis.axis << 1]); + if (func_event) + func_event(lowval); + + func_event = event_get(joystick_array[myEvent.jaxis.which]->axis_array[(myEvent.jaxis.axis << 1) + 1]); + if (func_event) + func_event(highval); + break; + + case SDL_JOYBUTTONDOWN: + case SDL_JOYBUTTONUP: + code = (myEvent.jbutton.state == SDL_PRESSED) ? INP_STATE_MAKE : INP_STATE_BREAK; + + func_event = event_get( joystick_array[myEvent.jbutton.which]->button_array[myEvent.jbutton.button] ); + if (func_event) + func_event(code); + break; + + default: + break; + } + } +} + +static void osd_freeinput(void) +{ + int i; + + for (i = 0; i < joystick_count; i++) + { + if (joystick_array[i]) + { + SDL_JoystickClose(joystick_array[i]->js); + free(joystick_array[i]->button_array); + free(joystick_array[i]->axis_array); + free(joystick_array[i]); + } + } + + free(joystick_array); +} + +void osd_getmouse(int *x, int *y, int *button) +{ + *button = SDL_GetMouseState(x, y); +} + +/* +** Shutdown +*/ + +/* this is at the bottom, to eliminate warnings */ +void osd_shutdown() +{ + osd_stopsound(); + osd_freeinput(); + SDL_Quit(); +} + +static int logprint(const char *string) +{ + return fprintf(stderr, "%s", string); +} + +/* +** Startup +*/ + +int osd_init() +{ + nofrendo_log_chain_logfunc(logprint); + + /* Initialize the SDL library */ + if (SDL_Init (SDL_INIT_AUDIO | SDL_INIT_TIMER | SDL_INIT_VIDEO + | SDL_INIT_JOYSTICK) < 0) + { + printf("Couldn't initialize SDL: %s\n", SDL_GetError()); + return -1; + } + + SDL_WM_SetCaption("Nofrendo", 0); + + if (osd_init_sound()) + return -1; + + osd_initinput(); + + return 0; +} + +/* +** $Log: sdl.c,v $ +** Revision 1.2 2001/04/27 14:37:11 neil +** wheeee +** +** Revision 1.1.1.1 2001/04/27 07:03:54 neil +** initial +** +** Revision 1.16 2000/12/11 13:31:41 neil +** caption +** +** Revision 1.15 2000/11/25 20:29:42 matt +** tiny mod +** +** Revision 1.14 2000/11/09 14:06:31 matt +** state load fixed, state save mostly fixed +** +** Revision 1.13 2000/11/06 02:20:00 matt +** vid_drv / log api changes +** +** Revision 1.12 2000/11/05 16:36:06 matt +** thinlib round 2 +** +** Revision 1.11 2000/11/05 06:26:41 matt +** thinlib spawns changes +** +** Revision 1.10 2000/11/01 17:31:54 neil +** fixed some conflicting key assignments +** +** Revision 1.9 2000/11/01 14:17:16 matt +** multi-system event system, or whatever +** +** Revision 1.8 2000/10/23 15:54:15 matt +** suppressed warnings +** +** Revision 1.7 2000/10/22 20:37:33 neil +** restored proper timer correction, and added support for variable frequencies +** +** Revision 1.6 2000/10/22 19:17:06 matt +** more sane timer ISR / autoframeskip +** +** Revision 1.5 2000/10/21 19:34:03 matt +** many more cleanups +** +** Revision 1.4 2000/10/17 11:59:29 matt +** let me see why i can't go window->full->window +** +** Revision 1.3 2000/10/13 14:09:57 matt +** sound is configurable from config file +** +** Revision 1.2 2000/10/13 13:19:15 matt +** fixed a few minor bugs and 16-bit sound +** +** Revision 1.1 2000/10/10 14:24:25 matt +** initial revision +** +*/ +#endif \ No newline at end of file diff --git a/src/sndhrdw/nes_apu.c b/src/sndhrdw/nes_apu.c index 9c53f5c..bc0001b 100644 --- a/src/sndhrdw/nes_apu.c +++ b/src/sndhrdw/nes_apu.c @@ -730,13 +730,11 @@ void apu_write(uint32 address, uint8 value) break; case APU_WRE1: /* 7-bit DAC */ - /* add the _delta_ between written value and - ** current output level of the volume reg - */ + // $4011 is a direct write + // https://www.nesdev.org/wiki/APU_DMC value &= 0x7F; /* bit 7 ignored */ - apu.dmc.output_vol += ((value - apu.dmc.regs[1]) << 8); + apu.dmc.output_vol = ((value) << 8); apu.dmc.regs[1] = value; - break; case APU_WRE2: apu.dmc.regs[2] = value; diff --git a/src/unix/osd.c b/src/unix/osd.c new file mode 100644 index 0000000..38bf119 --- /dev/null +++ b/src/unix/osd.c @@ -0,0 +1,311 @@ +/* vim: set tabstop=3 expandtab: +** +** This file is in the public domain. +** +** osd.c +** +** $Id: osd.c,v 1.2 2001/04/27 14:37:11 neil Exp $ +** +*/ +#ifdef NES_UNIX +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +/* path must be a valid path, and therefore no longer than PATH_MAX */ +static void addSlash(char *path) +{ + int len = strlen(path); + if(path[len - 1] != '/' && len + 1 <= PATH_MAX) + { + path[len] = '/'; + path[++len] = 0; + } +} + +/* filename must be a valid filename, and therefore no longer than PATH_MAX */ +static void removePath(char *filename) +{ + char temp[PATH_MAX + 1]; + int i; + + i = strlen(filename); + while(filename[--i] != '/' && i > 0); + + if(filename[i] == '/') + { + strncpy(temp, (filename + i + 1), PATH_MAX); + strncpy(filename, temp, PATH_MAX); + } +} + +/* if filename ends in extension, cut it off of filename */ +static void removeExtension(char *filename, const char *extension) +{ + int i = strlen(filename); + int j = strlen(extension); + + if(i <= j) return; + + while(i && j) + { + i--; + j--; + if(filename[i] != extension[j]) return; + } + filename[i] = 0; +} + +/* this determines where to store our data files */ +static const char *dataDirectory(void) +{ + static char dataPath[PATH_MAX + 1]; + static bool checked = false; + char cwd[PATH_MAX + 1]; + + if(!checked) + { + checked = true; + + /* fall back to using cwd */ + getcwd(cwd, PATH_MAX); + strncpy(dataPath, cwd, PATH_MAX); + + /* but default to using ~/.nofrendo/ if possible */ + if(getenv("HOME")) + { + char temp[PATH_MAX + 1]; + strncpy(temp, getenv("HOME"), PATH_MAX); + addSlash(temp); + strncat(temp, ".nofrendo", PATH_MAX - strlen(temp)); + + if(!mkdir(temp, 0755) || errno == EEXIST) + { + nofrendo_log_printf("Succeeded in choosing HOME-based homeDirectory.\n"); + strncpy(dataPath, temp, PATH_MAX); + } + } + + /* make sure either path ends in a slash */ + addSlash(dataPath); + nofrendo_log_printf("Storing data in %s\n", dataPath); + } + + return dataPath; +} + +/* This is os-specific part of main() */ +int osd_main(int argc, char *argv[]) +{ + static char configfilename[PATH_MAX + 1]; + + /* command-line parameters */ + if(argc < 2) + { + printf("usage: %s IMAGE\n\n", argv[0]); + printf("WHAP!\n"); + printf("WHAP!\n"); + printf("WHAP!\n"); + printf("Bad user!\n"); + printf("Run me correctly or you'll get more of the same!\n"); + return -1; + } + + /* config file */ + strncpy(configfilename, dataDirectory(), PATH_MAX); + strncat(configfilename, "config", PATH_MAX - strlen(configfilename)); + config.filename = configfilename; + + /* all done */ + return main_loop(argv[1], system_autodetect); +} + +/* File system interface */ +void osd_fullname(char *fullname, const char *shortname) +{ + strncpy(fullname, shortname, PATH_MAX); +} + +/* This gives filenames for storage of saves */ +char *osd_newextension(char *string, char *ext) +{ + char name[PATH_MAX + 1]; + + removePath(string); + removeExtension(string, ".gz"); + removeExtension(string, ".bz2"); + + strncpy(name, dataDirectory(), PATH_MAX); + strncat(name, string, PATH_MAX - strlen(name)); + strncat(name, ext, PATH_MAX - strlen(name)); + + strcpy(string, name); + + nofrendo_log_printf("osd_newextension: %s\n", string); + return string; +} + +/* This gives filenames for storage of PCX snapshots */ +int osd_makesnapname(char *filename, int len) +{ + char fullpath[PATH_MAX + 1]; + struct stat stat_data; + int pcx_num = -1; + + /* TODO: check if fullpath has %, \, or anything else special in it */ + strncpy(fullpath, dataDirectory(), PATH_MAX); + strncat(fullpath, "snap%04d.pcx", PATH_MAX - strlen(fullpath)); + + while (++pcx_num < 10000) + { + snprintf(filename, len, fullpath, pcx_num); + + if(stat(filename, &stat_data)) + return pcx_num; + } + + return -1; +} + +/* +** $Log: osd.c,v $ +** Revision 1.2 2001/04/27 14:37:11 neil +** wheeee +** +** Revision 1.1 2001/04/27 12:54:40 neil +** blah +** +** Revision 1.1.1.1 2001/04/27 07:03:54 neil +** initial +** +** Revision 1.38 2000/10/10 14:04:27 neil +** what's TRUE is not true +** +** Revision 1.37 2000/10/10 13:58:14 matt +** stroustrup squeezing his way in the door +** +** Revision 1.36 2000/10/10 13:05:20 matt +** Mr. Clean makes a guest appearance +** +** Revision 1.35 2000/07/31 04:29:04 matt +** one million cleanups +** +** Revision 1.34 2000/07/27 01:37:30 neil +** change of case in system enum +** +** Revision 1.33 2000/07/26 21:36:14 neil +** Big honkin' change -- see the mailing list +** +** Revision 1.32 2000/07/23 16:47:15 neil +** no more static charp[ in osd_newextension +** +** Revision 1.31 2000/07/21 18:08:43 neil +** Now we store our data files in ~/.nofrendo +** +** Revision 1.30 2000/07/21 14:35:58 neil +** Off by one on extension stripping +** +** Revision 1.29 2000/07/21 14:06:16 neil +** little convenience fixes +** +** Revision 1.28 2000/07/21 13:54:42 neil +** Fixed snapshot file generation +** +** Revision 1.27 2000/07/21 13:39:17 neil +** New main structure and new event structure +** +** Revision 1.26 2000/07/20 15:09:26 neil +** moving to SDL +** +** Revision 1.25 2000/07/19 15:59:40 neil +** PATH_MAX, strncpy, snprintf, and strncat are our friends +** +** Revision 1.24 2000/07/19 12:32:37 neil +** warning-free days are here again with PATH_MAX +** +** Revision 1.23 2000/07/18 09:24:07 neil +** Sound update... SDL works reasonably, but latent. OSS direct buffer access split out from OSS write() access. +** +** Revision 1.22 2000/07/16 06:47:23 neil +** Madly hacking at the sound, Desprately grabbing at whatever might work +** +** Revision 1.21 2000/07/14 05:40:31 neil +** Exploring options for making sound work +** +** Revision 1.20 2000/07/11 08:04:59 neil +** Moved the rom info display to osd.c from input.c +** +** Revision 1.19 2000/07/11 07:48:49 neil +** Replaced config.h with version.h, thanks to the config.h API +** +** Revision 1.18 2000/07/11 07:39:25 neil +** split input into input.c and ggiinput.c; swallowed bogoggi.h into linux.h +** +** Revision 1.17 2000/07/11 07:14:45 neil +** Headers merged +** +** Revision 1.16 2000/07/11 06:34:40 neil +** moved some files from input.c to (better?) places in osd.c and sound.c +** +** Revision 1.15 2000/07/09 19:39:13 bsittler +** Fixed timer interval (it was 17 us, not 17 ms) and added page-flipping. +** +** Revision 1.14 2000/07/09 18:36:38 neil +** bogoggi eliminates the uintx already defined warnings +** +** Revision 1.13 2000/07/09 06:42:06 neil +** Non-working attempt at GGI keyboard input +** +** Revision 1.12 2000/07/07 03:23:24 neil +** You can't see anything, but input and sound work impeccably +** +** Revision 1.11 2000/07/06 18:55:35 neil +** Pub-lic Do-main here I come... I don't need no GPL +** +** Revision 1.10 2000/07/06 16:41:42 matt +** removed dpp flag +** +** Revision 1.9 2000/07/06 16:40:14 neil +** copyright and/or log added +** +** Revision 1.8 2000/07/06 16:31:50 neil +** Now works, albeit lacking speed and input, on my desktop +** +** Revision 1.7 2000/07/06 05:38:38 neil +** read it and weep (I'm not sure if it's tears of joy +** +** Revision 1.6 2000/07/06 04:27:14 neil +** It's close enough to working that I can taste it +** +** Revision 1.5 2000/07/05 23:37:46 neil +** Muahahaha +** +** Revision 1.3 2000/07/05 19:57:36 neil +** __GNUC -> __DJGPP in nes.c +** +** Revision 1.2 2000/07/05 17:26:16 neil +** Moved the externs in nofrendo.c to osd.h +** +** Revision 1.1 2000/07/05 17:14:34 neil +** Linux: Act Two, Scene One +** +** +*/ +#endif \ No newline at end of file diff --git a/src/vid_drv.c b/src/vid_drv.c index 08e3e98..1b10f6d 100644 --- a/src/vid_drv.c +++ b/src/vid_drv.c @@ -35,12 +35,10 @@ /* hardware surface */ static bitmap_t *screen = NULL; -/* primary / backbuffer surfaces */ -#ifdef NOFRENDO_DOUBLE_FRAMEBUFFER -static bitmap_t *primary_buffer = NULL, *back_buffer = NULL; -#else /* !NOFRENDO_DOUBLE_FRAMEBUFFER */ +/* primary surface */ +// backbuffer_stuff should be done outside + static bitmap_t *primary_buffer = NULL; -#endif /* !NOFRENDO_DOUBLE_FRAMEBUFFER */ static viddriver_t *driver = NULL; @@ -92,7 +90,7 @@ static viddriver_t *driver = NULL; INLINE int vid_memcmp(const void *p1, const void *p2, int len) { /* check for 32-bit aligned data */ - if (0 == (((uint32)p1 & 3) | ((uint32)p2 & 3))) + if (0 == (((uintptr_t)p1 & 3) | ((uintptr_t)p2 & 3))) { uint32 *dw1 = (uint32 *)p1; uint32 *dw2 = (uint32 *)p2; @@ -140,7 +138,7 @@ INLINE void vid_memcpy(void *dest, const void *src, int len) uint32 *s = (uint32 *)src; uint32 *d = (uint32 *)dest; - ASSERT(0 == ((len & 3) | ((uint32)src & 3) | ((uint32)dest & 3))); + ASSERT(0 == ((len & 3) | ((uintptr_t)src & 3) | ((uintptr_t)dest & 3))); len >>= 2; DUFFS_DEVICE(*d++ = *s++, len); @@ -386,13 +384,6 @@ void vid_flush(void) driver->custom_blit(primary_buffer, num_dirties, dirty_rects); else vid_blitscreen(num_dirties, dirty_rects); - -#ifdef NOFRENDO_DOUBLE_FRAMEBUFFER - /* Swap pointers to the main/back buffers */ - temp = back_buffer; - back_buffer = primary_buffer; - primary_buffer = temp; -#endif /* NOFRENDO_DOUBLE_FRAMEBUFFER */ } /* emulated machine tells us which resolution it wants */ @@ -400,31 +391,14 @@ int vid_setmode(int width, int height) { if (NULL != primary_buffer) bmp_destroy(&primary_buffer); -#ifdef NOFRENDO_DOUBLE_FRAMEBUFFER - if (NULL != back_buffer) - bmp_destroy(&back_buffer); -#endif /* NOFRENDO_DOUBLE_FRAMEBUFFER */ - primary_buffer = bmp_create(width, height, 0); /* no overdraw */ + primary_buffer = bmp_create(width, height, 8); /* overdraw 8 */ if (NULL == primary_buffer) return -1; -#ifdef NOFRENDO_DOUBLE_FRAMEBUFFER - /* Create our backbuffer */ - back_buffer = bmp_create(width, height, 0); /* no overdraw */ - if (NULL == back_buffer) - { - bmp_destroy(&primary_buffer); - return -1; - } -#endif /* NOFRENDO_DOUBLE_FRAMEBUFFER */ bmp_clear(primary_buffer, GUI_BLACK); -#ifdef NOFRENDO_DOUBLE_FRAMEBUFFER - bmp_clear(back_buffer, GUI_BLACK); -#endif /* NOFRENDO_DOUBLE_FRAMEBUFFER */ - return 0; } @@ -440,7 +414,8 @@ static int vid_findmode(int width, int height, viddriver_t *osd_driver) driver = osd_driver; /* re-assert dimensions, clear the surface */ - screen = driver->lock_write(); + if (driver->lock_write) + screen = driver->lock_write(); /* use custom pageclear, if necessary */ if (driver->clear) @@ -448,12 +423,14 @@ static int vid_findmode(int width, int height, viddriver_t *osd_driver) else bmp_clear(screen, GUI_BLACK); + if (screen) + nofrendo_log_printf("video driver: %s at %dx%d\n", driver->name, + screen->width, screen->height); + /* release surface */ if (driver->free_write) driver->free_write(-1, NULL); - nofrendo_log_printf("video driver: %s at %dx%d\n", driver->name, - screen->width, screen->height); return 0; } @@ -479,11 +456,6 @@ void vid_shutdown(void) if (NULL != primary_buffer) bmp_destroy(&primary_buffer); -#ifdef NOFRENDO_DOUBLE_FRAMEBUFFER - if (NULL != back_buffer) - bmp_destroy(&back_buffer); -#endif /* NOFRENDO_DOUBLE_FRAMEBUFFER */ - if (driver && driver->shutdown) driver->shutdown(); }