Switch graphic & key management to OpenGL/GLFW3, correct sprite behaviour, still not perfect, but way better (no more issue with overlapping and overflow is correctly handled now)

->PPU still need a complete rewrite.
 Bump version to 0.7!
This commit is contained in:
Godzil 2016-12-29 18:21:39 +01:00
parent 866dcfa969
commit cc9fe51828
49 changed files with 1171 additions and 946 deletions

View File

@ -9,8 +9,16 @@
# $HeadURL$
# $Revision$
cmake_minimum_required (VERSION 3.6)
set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
add_subdirectory("external/glfw")
find_package(OpenGL REQUIRED)
include_directories(${OPENGL_INCLUDE_DIR})
cmake_minimum_required (VERSION 2.6)
project (TINES)
add_subdirectory (src)

View File

@ -2,15 +2,13 @@
# TI-NES CMake
#
# Created by Manoel TRAPIER.
# Copyright (c) 2003-2008 986Corp. All rights reserved.
# Copyright (c) 2003-2016 986-Studio. All rights reserved.
#
# $LastChangedDate$
# $Author$
# $HeadURL$
# $Revision$
include_directories($(TINES_SOURCE_DIR)/include)
##########################
# Configurations variables
##########################
@ -22,17 +20,7 @@ set(DETECT_BUS_CONFLICT OFF CACHE BOOL "Activate the bus conflit detector? (Coul
set(USE_EFENCE OFF CACHE BOOL "Use electricfence memory debugger?")
set(USE_PROFILING OFF CACHE BOOL "Use profiling tools? (Will slow down a lot.)")
set(USE_ALLEGRO ON CACHE BOOL "Use Allegro backend" FORCE)
IF(NOT CMAKE_BUILD_TYPE)
SET(CMAKE_BUILD_TYPE Debug CACHE STRING
"Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel."
FORCE)
ENDIF(NOT CMAKE_BUILD_TYPE)
if (APPLE)
SET (CMAKE_FIND_FRAMEWORK LAST)
endif (APPLE)
set(USE_ALLEGRO ON CACHE BOOL "Use Allegro backend")
##########################
# Link & Compile flags
@ -41,9 +29,7 @@ endif (APPLE)
set (CMAKE_C_FLAGS "-Wall -Wextra -Wno-unused-parameter -Werror ${PLATFORM_FLAGS}")
set (CMAKE_CXX_FLAGS "-Wall -Wextra -Wno-unused-parameter -Werror ${PLATFORM_FLAGS}")
add_definitions (-DNO_DECIMAL -DFAST_RDOP)
SET ( CMAKE_EXE_LINKER_FLAGS "-mmacosx-version-min=10.4")
add_definitions (-DNO_DECIMAL)
if (PPU_ISPAL)
add_definitions (-DISPAL)
@ -63,15 +49,6 @@ if (DETECT_BUS_CONFLICT)
add_definitions (-DDETECT_BUS_CONFLICT)
endif (DETECT_BUS_CONFLICT)
if (USE_EFENCE)
if (CMAKE_BUILD_TYPE MATCHES Release)
SET(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Debug info is forced" FORCE)
else(CMAKE_BUILD_TYPE)
SET(CMAKE_BUILD_TYPE Debug CACHE STRING "Debug info is forced" FORCE)
endif(CMAKE_BUILD_TYPE)
endif (USE_EFENCE)
if (USE_PROFILING)
if (CMAKE_BUILD_TYPE MATCHES Rel)
SET(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Debug info is forced" FORCE)
@ -82,18 +59,7 @@ if (USE_PROFILING)
set(CMAKE_C_FLAGS -pg)
endif (USE_PROFILING)
if (APPLE)
include_directories(BEFORE /usr/include)
endif (APPLE)
#if the CPU is LSB set the define
if (CMAKE_SYSTEM_PROCESSOR MATCHES i386 OR CMAKE_SYSTEM_PROCESSOR MATCHES [aA][rR][mM])
add_definitions (-DLSB_FIRST)
endif (CMAKE_SYSTEM_PROCESSOR MATCHES i386 OR CMAKE_SYSTEM_PROCESSOR MATCHES [aA][rR][mM])
#Add release mode extra C Flags
set (CMAKE_C_FLAGS_RELEASE "-fomit-frame-pointer -funroll-loops -Wall ${CMAKE_C_FLAGS_RELEASE}")
set (CMAKE_C_FLAGS_RELWITHDEBINFO "-fomit-frame-pointer -funroll-loops -Wall ${CMAKE_C_FLAGS_RELWITHDEBINFO}")
include_directories(include)
add_subdirectory(apu)
add_subdirectory(corecpu)
@ -105,36 +71,13 @@ add_subdirectory(ppu)
if (TARGET_TI68k)
add_subdirectory(os/ti68k)
elseif (APPLE AND ${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
add_subdirectory(os/macos)
elseif (UNIX)
add_subdirectory(os/unix)
else (TARGET_TI68k)
#So we target UNIX like OS
elseif (WIN32)
add_subdirectory(os/win32)
else (TARGET_TI68k)
add_subdirectory(os/unix)
endif (TARGET_TI68k)
add_library (main main.c paddle.c NESCarts.c)
add_executable(tines main.c)
set(CMAKE_FIND_FRAMEWORK LAST)
find_library(ALLEGROLIB allegro)
find_library(PTHREADLIB pthread)
if (USE_EFENCE)
find_library(EFENCELIB efence)
target_link_libraries(tines ${EFENCELIB})
endif (USE_EFENCE)
if (USE_ALLEGRO)
target_link_libraries(tines debug alld-main)
# target_link_libraries(tines)
if (APPLE)
find_library(COCOALIB Cocoa)
target_link_libraries(tines ${COCOALIB})
endif (APPLE)
endif (USE_ALLEGRO)
target_link_libraries(tines main apu corecpu mappermanager memorymanager pluginsmanager ppu oslib ${ALLEGROLIB} ${PTHREADLIB})
add_executable(tines main.c paddle.c NESCarts.c)
target_link_libraries(tines apu corecpu mappermanager memorymanager pluginsmanager ppu oslib ${PTHREADLIB})

View File

@ -3,7 +3,7 @@
* NESCart.c
*
* Created by Manoel TRAPIER.
* Copyright (c) 2003-2008 986Corp. All rights reserved.
* Copyright (c) 2003-2016 986-Studio. All rights reserved.
*
* $LastChangedDate$
* $Author$

View File

@ -2,7 +2,7 @@
# TI-NES CMake
#
# Created by Manoel TRAPIER.
# Copyright (c) 2003-2008 986Corp. All rights reserved.
# Copyright (c) 2003-2016 986-Studio. All rights reserved.
#
# $LastChangedDate$
# $Author$

View File

@ -10,7 +10,7 @@
/** commercially. Please, notify me, if you make any **/
/** changes to this file. **/
/*************************************************************/
#include "Sound.h"
//#include "Sound.h"
#include <stdlib.h>
#include <stdio.h>
@ -20,7 +20,7 @@
#include <sys/ioctl.h>
#include <os_dependent.h>
#if 0
#ifdef SUN_AUDIO
#include <sys/audioio.h>
@ -553,3 +553,4 @@ void UnixDrum(int Type,int Force)
{
/* This function is currently empty */
}
#endif

View File

@ -3,7 +3,7 @@
* NESCart.h
*
* Created by Manoel TRAPIER.
* Copyright (c) 2003-2008 986Corp. All rights reserved.
* Copyright (c) 2003-2016 986-Studio. All rights reserved.
*
* $LastChangedDate$
* $Author$

View File

@ -1,9 +1,9 @@
/**
* ANSI Color definitiont - The Quick6502 Project
* ANSI Color definition - The Quick6502 Project
* include/color.h
*
* Created by Manoel Trapier on 25/06/10
* Copyright 2010 986 Corp. All rights reserved.
* Copyright (c) 2003-2016 986-Studio. All rights reserved.
*
* $LastChangedDate:$
* $Author:$

View File

@ -3,7 +3,7 @@
* corecpu.h
*
* Created by Manoel Trapier on 24/02/08
* Copyright 2008 986 Corp. All rights reserved.
* Copyright (c) 2003-2016 986-Studio. All rights reserved.
*
* $LastChangedDate$
* $Author$

View File

@ -3,7 +3,7 @@
* include/log.h
*
* Created by Manoel Trapier on 19/05/10
* Copyright 2010 986 Corp. All rights reserved.
* Copyright (c) 2003-2016 986-Studio. All rights reserved.
*
* $LastChangedDate:$
* $Author:$

View File

@ -3,7 +3,7 @@
* os_dependent.h
*
* Created by Manoel TRAPIER on 08/05/08.
* Copyright (c) 2003-2008 986Corp. All rights reserved.
* Copyright (c) 2003-2016 986-Studio. All rights reserved.
*
* $LastChangedDate$
* $Author$
@ -15,11 +15,21 @@
#ifndef OS_DEPENDENT_H
#define OS_DEPENDENT_H
#include <stdint.h>
/* File related functions */
/* Graphics related functions */
int graphics_init();
int graphics_drawpixel(long x, long y, long color);
int graphics_blit(long x, long y, long w, long h);
int graphics_drawline(long x, long y, long x1, long y1, long color);
typedef struct Palette_t
{
uint8_t r,g,b,a;
} Palette;
int getKeyStatus(int key);
/* Sound related functions */
@ -37,7 +47,6 @@ typedef enum ConsoleLevel_t
Console_Debug,
} ConsoleLevel;
int console_init(ConsoleLevel DefaultLevel);
int console_printf(const ConsoleLevel level, const char *format, ...);
int console_printf_d(const char *format, ...);

View File

@ -3,7 +3,7 @@
* paddle.h
*
* Created by Manoel TRAPIER.
* Copyright (c) 2003-2008 986Corp. All rights reserved.
* Copyright (c) 2003-2016 986-Studio. All rights reserved.
*
* $LastChangedDate$
* $Author$

View File

@ -6,7 +6,7 @@
* $Revision$
*/
PALETTE basicPalette = {
Palette basicPalette[] = {
{ 0x1E, 0x1E, 0x1E, 0x07 },
{ 0x03, 0x09, 0x28, 0xB7 },
{ 0x0A, 0x04, 0x2B, 0x0D },

View File

@ -5,7 +5,7 @@
* Define and emulate the PPU (Picture Processing Unit) of the real NES
*
* Created by Manoel TRAPIER.
* Copyright (c) 2003-2008 986Corp. All rights reserved.
* Copyright (c) 2003-2016 986-Studio. All rights reserved.
*
* $LastChangedDate$
* $Author$
@ -21,10 +21,10 @@
typedef struct PPU_Sprite_
{
byte y;
byte tileid;
byte flags;
byte x;
uint8_t y;
uint8_t tileid;
uint8_t flags;
uint8_t x;
} PPU_Sprite;
/*
@ -32,13 +32,13 @@ PPU must be initialized after memory initialisation..
*/
int ppu_init();
int ppu_hblank(int scanline);
int ppu_hblank(uint16_t scanline);
byte ppu_readReg(byte id);
uint8_t ppu_readReg(uint8_t id);
void ppu_writeReg(byte id, byte val);
void ppu_writeReg(uint8_t id, uint8_t val);
void ppu_fillSprRamDMA(byte value);
void ppu_fillSprRamDMA(uint8_t value);
#define PPU_MIRROR_HORIZTAL 0
#define PPU_MIRROR_VERTICAL 1
@ -52,15 +52,15 @@ void ppu_fillSprRamDMA(byte value);
#define PPU_SCMODE_NORMAL 1
#define PPU_SCMODE_FOURSC 2
void ppu_setMirroring(byte direction);
void ppu_setSingleScreen(byte screen);
void ppu_setScreenMode(byte mode);
void ppu_setMirroring(uint8_t direction);
void ppu_setSingleScreen(uint8_t screen);
void ppu_setScreenMode(uint8_t mode);
PPU_Sprite ppu_getSprite(unsigned short i);
PPU_Sprite ppu_getSprite(uint16_t i);
unsigned char ppu_memoryRead(byte page, byte addr);
void ppu_memoryWrite(byte page, byte addr, byte value);
unsigned char ppu_memoryRead(uint8_t page, uint8_t addr);
void ppu_memoryWrite(uint8_t page, uint8_t addr, uint8_t value);
void ppu_debugSprites();
void ppu_debugColor();

View File

@ -3,7 +3,7 @@
* types.h - Taken from the Quick6502 project
*
* Created by Manoel Trapier on 18/09/06.
* Copyright 2003-2008 986 Corp. All rights reserved.
* Copyright (c) 2003-2016 986-Studio. All rights reserved.
*
* $LastChangedDate$
* $Author$
@ -15,12 +15,14 @@
#ifndef TYPES_H
#define TYPES_H
#include <stdint.h>
#ifndef BYTE_TYPE_DEFINED
#define BYTE_TYPE_DEFINED
typedef unsigned char byte;
typedef uint8_t byte;
#endif
typedef unsigned char bool;
typedef uint8_t bool;
#define true (0)
#define false (!true)

View File

@ -3,7 +3,7 @@
* main.c
*
* Created by Manoel TRAPIER.
* Copyright (c) 2003-2012 986Corp. All rights reserved.
* Copyright (c) 2003-2016 986-Studio. All rights reserved.
*
* $LastChangedDate$
* $Author$
@ -20,21 +20,15 @@
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <time.h>
#include <ctype.h>
/* Allegro includes */
#ifdef __APPLE__
#define USE_CONSOLE
#include <Allegro/allegro.h>
#else
#define USE_CONSOLE
#include <allegro.h>
#endif
#include <GLFW/glfw3.h>
#else
@ -61,23 +55,11 @@
#include <Sound.h>
#endif
#include <palette.h>
/* PAL support is broken, so force NTSC mode */
#if ISPAL || ISNTSC
#undef ISPAL
#undef ISNTSC
#endif
#define ISNTSC 1
#if ISPAL && !ISNTSC
int VBLANK_TIME = 70;
int HBLANK_TIME = 140;
int HBLANK_TIME = 103;
double APU_BASEFREQ = 1.7734474;
#elif !ISPAL && ISNTSC
int VBLANK_TIME = 20;
int HBLANK_TIME = 113;
double APU_BASEFREQ = 1.7897725;
@ -91,13 +73,16 @@ double APU_BASEFREQ = 1.7897725;
/* TI-NESulator Version */
#define V_MAJOR 0
#define V_MINOR 40
#define V_MINOR 70
#ifdef USE_SOUND
#undef USE_SOUND
#endif
/* SVN specific values */
#define VS_ID "$Id$"
#define VS_REVISION "$Revision$"
#define VS_LASTCHANGEDDATE "$LastChangedDate$"
#define VS_HEADURL "$HeadURL$"
#define VS_AUTHOR "$Author$"
/*
@ -113,10 +98,6 @@ NesCart *Cart;
byte *FDSRom;
byte *FDSRam;
/* Allegro main screen */
BITMAP *Buffer;
/* Command line options */
byte START_DEBUG = 0;
byte START_WITH_FDS = 0;
@ -139,8 +120,6 @@ struct timeval timeEnd;
volatile unsigned long FPS, IPS;
PALETTE pal;
short IRQScanHit = -1;
short SZHit = -1;
@ -166,15 +145,6 @@ void CloseHook(void)
WantClosing = 1;
}
void ips_fps_counter(void)
{
FPS = frame;
IPS = ccount;
frame = 0;
ccount = 0;
}
END_OF_FUNCTION(ips_fps_counter);
void SaveSaveRam(char *name)
{
FILE *fp;
@ -216,7 +186,7 @@ void LoadSaveRam(char *name)
}
void LoadPalette(char *filename, PALETTE pal)
void LoadPalette(char *filename, Palette *pal)
{
FILE *fp;
int ret;
@ -380,6 +350,7 @@ byte Page40[256];
void WrHook4000Multiplexer(byte addr, byte value)
{
#ifdef USE_SOUND
static byte SQ1V = 0;
static byte SQ2V = 0;
static byte NOIV = 0;
@ -400,6 +371,8 @@ void WrHook4000Multiplexer(byte addr, byte value)
static byte Sq2_reg3 = 0;
double SQ = 0.0;
#endif
switch(addr)
{
#ifdef USE_SOUND
@ -655,14 +628,9 @@ int main(int argc, char *argv[])
/* Print the banner */
console_printf(Console_Default, "--------------------------------------------------------------------------------\n"
"Welcome to TI-NESulator v%d.%d - by Godzil\n"
"Copyright 2003-2012 TRAPIER Manoel (godzil@godzil.net)\n"
"%s\n%s\n%s\n"
"Copyright 2003-2016 TRAPIER Manoel (godzil@godzil.net)\n"
"--------------------------------------------------------------------------------\n\n",
V_MAJOR,
V_MINOR,
VS_REVISION,
VS_LASTCHANGEDDATE,
VS_AUTHOR);
V_MAJOR, V_MINOR);
console_printf(Console_Default, "Install signal handlers...\t[");
signal(SIGABRT, signalhandler);
@ -929,22 +897,6 @@ int main(int argc, char *argv[])
InitPaddle(&P1);
console_printf(Console_Default, "Initializing Allegro...\t\t");
allegro_init();
install_timer();
install_keyboard();
console_printf(Console_Default, "[ OK ]\n");
console_printf(Console_Default, "Set graphic mode...\t\t");
set_color_depth(8);
set_gfx_mode(GFX_AUTODETECT_WINDOWED, 512 + 256, 480, 512 + 256, 480);
Buffer = create_bitmap(512 + 256, 480);
clear_to_color(Buffer, 0x0D);
//set_close_button_callback(CloseHook);
//set_window_title("TI-NESulator");
console_printf(Console_Default, "[ OK ]\n");
console_printf(Console_Default, "Init PPU...\n");
if (ppu_init() != 0)
@ -970,15 +922,7 @@ int main(int argc, char *argv[])
return -1;
console_printf(Console_Default, "[ OK ]\n");
if (PALETTE_FILENAME == NULL)
{
set_palette(basicPalette);
}
else
{
LoadPalette(PALETTE_FILENAME, pal);
set_palette(pal);
}
// set_palette(basicPalette);
#ifdef USE_SOUND
InitSound(44400,!0);
@ -990,7 +934,7 @@ int main(int argc, char *argv[])
#endif
// Actually no real debugguer...
//console_printf(Console_Default, "Press ESC to pause emulation and jump to debugguer\n");
install_int(ips_fps_counter, 1000);
ScanLine = 0;
/* Initialize the CPU */
@ -1027,7 +971,6 @@ int main(int argc, char *argv[])
}
return 0;
}
END_OF_MAIN()
/* Access directly to Memory pages *HACKISH* */
extern byte *memory_pages[0xFF];
@ -1079,7 +1022,7 @@ void MemoryPageZeroWrite (unsigned short Addr, byte Value)
void Loop6502(quick6502_cpu *R)
{
byte ret;
short skey;
// short skey;
long WaitTime;
static long delta=0;
@ -1122,7 +1065,7 @@ void Loop6502(quick6502_cpu *R)
#endif
/* If we press Page Up, we want to accelerate "time" */
if ((!key[KEY_PGUP]) && (!key[KEY_Y]))
if (!getKeyStatus('Y'))
if ((WaitTime >= 0) && (WaitTime < 100000))
usleep(WaitTime);
@ -1148,13 +1091,12 @@ void Loop6502(quick6502_cpu *R)
ScanLine++;
//console_printf(Console_Default, "SL:%d HBT:%d VbT:%d\n", ScanLine, HBLANK_TIME, VBLANK_TIME);
if (keypressed())
{
skey = (readkey() & 0xFF);
// TODO: NO DEBUGER
/* if (skey == 27)
R->Trace = 1;*/
// TODO: NO DEBUGER
if (getKeyStatus(GLFW_KEY_ESCAPE))
exit(0);
#if 0
if (skey == '9')
{
VBLANK_TIME += 2;
@ -1178,17 +1120,16 @@ void Loop6502(quick6502_cpu *R)
HBLANK_TIME -= 1;
console_printf(Console_Default, "HBLT: %d\n", HBLANK_TIME);
}
#endif
if ((skey == 'r') || (skey == 'R'))
if (getKeyStatus('r') || getKeyStatus('R'))
{
/* Force the PPU to stop NMIs */
MemoryWrite(0x2000, 0x00);
quick6502_reset(R);
}
plugin_keypress(skey);
}
// plugin_keypress(skey);
if (ret != 0)
quick6502_int(R, ret);

View File

@ -2,7 +2,7 @@
# TI-NES CMake
#
# Created by Manoel TRAPIER.
# Copyright (c) 2003-2008 986Corp. All rights reserved.
# Copyright (c) 2003-2016 986-Studio. All rights reserved.
#
# $LastChangedDate$
# $Author$

View File

@ -3,7 +3,7 @@
* manager.c
*
* Created by Manoel TRAPIER.
* Copyright (c) 2003-2008 986Corp. All rights reserved.
* Copyright (c) 2003-2016 986-Studio. All rights reserved.
*
* $LastChangedDate$
* $Author$

View File

@ -3,7 +3,7 @@
* aorom.c
*
* Created by Manoel TRAPIER.
* Copyright (c) 2003-2008 986Corp. All rights reserved.
* Copyright (c) 2003-2016 986-Studio. All rights reserved.
*
* $LastChangedDate$
* $Author$
@ -55,7 +55,7 @@ void aorom_MapperWriteHook(register byte Addr, register byte Value)
aorom_load_bank = BankNb;
console_printf(Console_Default, "aorom: Asking bank %d - NT is 0x%04X\n",BankNb,(Value&0x10)?0x2400:0x2000);
//console_printf(Console_Default, "aorom: Asking bank %d - NT is 0x%04X\n",BankNb,(Value&0x10)?0x2400:0x2000);
set_prom_bank_32k(0x8000,BankNb);
}

View File

@ -3,7 +3,7 @@
* aorom.h
*
* Created by Manoel TRAPIER.
* Copyright (c) 2003-2008 986Corp. All rights reserved.
* Copyright (c) 2003-2016 986-Studio. All rights reserved.
*
* $LastChangedDate$
* $Author$

View File

@ -3,7 +3,7 @@
* cnrom.c
*
* Created by Manoel TRAPIER.
* Copyright (c) 2003-2008 986Corp. All rights reserved.
* Copyright (c) 2003-2016 986-Studio. All rights reserved.
*
* $LastChangedDate$
* $Author$

View File

@ -3,7 +3,7 @@
* cnrom.h
*
* Created by Manoel TRAPIER.
* Copyright (c) 2003-2008 986Corp. All rights reserved.
* Copyright (c) 2003-2016 986-Studio. All rights reserved.
*
* $LastChangedDate$
* $Author$

View File

@ -3,7 +3,7 @@
* iremh3001.c
*
* Created by Manoel TRAPIER.
* Copyright (c) 2003-2008 986Corp. All rights reserved.
* Copyright (c) 2003-2016 986-Studio. All rights reserved.
*
* $LastChangedDate$
* $Author$

View File

@ -3,7 +3,7 @@
* iremh3001.h
*
* Created by Manoel TRAPIER.
* Copyright (c) 2003-2008 986Corp. All rights reserved.
* Copyright (c) 2003-2016 986-Studio. All rights reserved.
*
* $LastChangedDate$
* $Author$

View File

@ -3,7 +3,7 @@
* mmc1.h
*
* Created by Manoel TRAPIER.
* Copyright (c) 2003-2008 986Corp. All rights reserved.
* Copyright (c) 2003-2016 986-Studio. All rights reserved.
*
* $LastChangedDate$
* $Author$

View File

@ -3,7 +3,7 @@
* mmc1.h
*
* Created by Manoel TRAPIER.
* Copyright (c) 2003-2008 986Corp. All rights reserved.
* Copyright (c) 2003-2016 986-Studio. All rights reserved.
*
* $LastChangedDate$
* $Author$

View File

@ -3,7 +3,7 @@
* mmc3.h
*
* Created by Manoel TRAPIER.
* Copyright (c) 2003-2008 986Corp. All rights reserved.
* Copyright (c) 2003-2016 986-Studio. All rights reserved.
*
* $LastChangedDate$
* $Author$

View File

@ -3,7 +3,7 @@
* mmc3.h
*
* Created by Manoel TRAPIER.
* Copyright (c) 2003-2008 986Corp. All rights reserved.
* Copyright (c) 2003-2016 986-Studio. All rights reserved.
*
* $LastChangedDate$
* $Author$

View File

@ -3,7 +3,7 @@
* mmc4.h
*
* Created by Manoel TRAPIER.
* Copyright (c) 2007-2008 986Corp. All rights reserved.
* Copyright (c) 2003-2016 986-Studio. All rights reserved.
*
* $LastChangedDate$
* $Author$

View File

@ -3,7 +3,7 @@
* mmc4.h
*
* Created by Manoel TRAPIER.
* Copyright (c) 2007-2008 986Corp. All rights reserved.
* Copyright (c) 2003-2016 986-Studio. All rights reserved.
*
* $LastChangedDate$
* $Author$

View File

@ -3,7 +3,7 @@
* norom.c
*
* Created by Manoel TRAPIER.
* Copyright (c) 2003-2008 986Corp. All rights reserved.
* Copyright (c) 2003-2016 986-Studio. All rights reserved.
*
* $LastChangedDate$
* $Author$

View File

@ -3,7 +3,7 @@
* norom.c
*
* Created by Manoel TRAPIER.
* Copyright (c) 2003-2008 986Corp. All rights reserved.
* Copyright (c) 2003-2016 986-Studio. All rights reserved.
*
* $LastChangedDate$
* $Author$

View File

@ -3,7 +3,7 @@
* unrom.h
*
* Created by Manoel TRAPIER.
* Copyright (c) 2003-2008 986Corp. All rights reserved.
* Copyright (c) 2003-2016 986-Studio. All rights reserved.
*
* $LastChangedDate$
* $Author$

View File

@ -3,7 +3,7 @@
* unrom.h
*
* Created by Manoel TRAPIER.
* Copyright (c) 2003-2008 986Corp. All rights reserved.
* Copyright (c) 2003-2016 986-Studio. All rights reserved.
*
* $LastChangedDate$
* $Author$

View File

@ -3,7 +3,7 @@
* mappers_list.h
*
* Created by Manoel TRAPIER on 25/10/07.
* Copyright (c) 2003-2008 986Corp. All rights reserved.
* Copyright (c) 2003-2016 986-Studio. All rights reserved.
*
* $LastChangedDate$
* $Author$

View File

@ -3,7 +3,7 @@
* mappers.c
*
* Created by Manoel TRAPIER.
* Copyright (c) 2003-2008 986Corp. All rights reserved.
* Copyright (c) 2003-2016 986-Studio. All rights reserved.
*
* $LastChangedDate$
* $Author$

View File

@ -2,7 +2,7 @@
# TI-NES CMake
#
# Created by Manoel TRAPIER.
# Copyright (c) 2003-2008 986Corp. All rights reserved.
# Copyright (c) 2003-2016 986-Studio. All rights reserved.
#
# $LastChangedDate$
# $Author$

View File

@ -3,7 +3,7 @@
* memory.c - Taken from the Quick6502 project
*
* Created by Manoel Trapier on 18/09/06.
* Copyright 2003-2008 986 Corp. All rights reserved.
* Copyright (c) 2003-2016 986-Studio. All rights reserved.
*
* $LastChangedDate$
* $Author$

View File

@ -2,7 +2,7 @@
# TI-NES CMake
#
# Created by Manoel TRAPIER.
# Copyright (c) 2003-2008 986Corp. All rights reserved.
# Copyright (c) 2003-2016 986-Studio. All rights reserved.
#
# $LastChangedDate$
# $Author$
@ -10,3 +10,5 @@
# $Revision$
add_library(oslib loadfile.c graphics.c sound.c io.c)
target_link_libraries(oslib glfw ${OPENGL_glu_LIBRARY})

View File

@ -3,7 +3,7 @@
* os/macos/graphics.c
*
* Created by Manoel TRAPIER on 08/05/08.
* Copyright (c) 2003-2008 986Corp. All rights reserved.
* Copyright (c) 2003-2016 986-Studio. All rights reserved.
*
* $LastChangedDate$
* $Author$
@ -11,19 +11,426 @@
* $Revision$
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <os_dependent.h>
#include <GLFW/glfw3.h>
#include <OpenGL/glext.h>
#include <palette.h>
typedef struct GLWindow_t GLWindow;
struct KeyArray
{
unsigned char lastState;
unsigned char curState;
unsigned char debounced;
GLFWwindow* window;
};
struct GLWindow_t
{
struct KeyArray keyArray[512];
GLFWwindow* windows;
unsigned char *videoMemory;
GLint videoTexture;
int WIDTH;
int HEIGHT;
};
#ifndef GL_TEXTURE_RECTANGLE_EXT
#define GL_TEXTURE_RECTANGLE_EXT GL_TEXTURE_RECTANGLE_NV
#endif
static int window_num = 0;
void GLWindowInitEx(GLWindow *g, int w, int h)
{
g->WIDTH = w;
g->HEIGHT = h;
g->videoTexture = window_num++;
}
void GLWindowInit(GLWindow *g)
{
GLWindowInitEx(g, 100, 100);
}
void ShowScreen(GLWindow *g, int w, int h)
{
glBindTexture(GL_TEXTURE_RECTANGLE_EXT, g->videoTexture);
// glTexSubImage2D is faster when not using a texture range
glTexSubImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, 0, 0, w, h, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, g->videoMemory);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f);
glVertex2f(-1.0f,1.0f);
glTexCoord2f(0.0f, h);
glVertex2f(-1.0f, -1.0f);
glTexCoord2f(w, h);
glVertex2f(1.0f, -1.0f);
glTexCoord2f(w, 0.0f);
glVertex2f(1.0f, 1.0f);
glEnd();
glFlush();
}
void setupGL(GLWindow *g, int w, int h)
{
g->videoMemory = (unsigned char*)malloc(w*h*sizeof(unsigned int));
memset(g->videoMemory, 0,w*h*sizeof(unsigned int));
//Tell OpenGL how to convert from coordinates to pixel values
glViewport(0, 0, w, h);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glClearColor(1.0f, 0.f, 1.0f, 1.0f);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glDisable(GL_TEXTURE_2D);
glEnable(GL_TEXTURE_RECTANGLE_EXT);
glBindTexture(GL_TEXTURE_RECTANGLE_EXT, g->videoTexture);
// glTextureRangeAPPLE(GL_TEXTURE_RECTANGLE_NV_EXT, 0, NULL);
// glTexParameteri(GL_TEXTURE_RECTANGLE_NV_EXT, GL_TEXTURE_STORAGE_HINT_APPLE , GL_STORAGE_CACHED_APPLE);
// glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, GL_RGBA, w,
h, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, g->videoMemory);
glDisable(GL_DEPTH_TEST);
}
void restoreGL(GLWindow *g, int w, int h)
{
//Tell OpenGL how to convert from coordinates to pixel values
glViewport(0, 0, w, h);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glClearColor(1.0f, 0.f, 1.0f, 1.0f);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glDisable(GL_TEXTURE_2D);
glEnable(GL_TEXTURE_RECTANGLE_EXT);
glDisable(GL_DEPTH_TEST);
}
void kbHandler(GLFWwindow* window, int key, int scan, int action, int mod )
{
struct KeyArray *keyArray;
keyArray = (struct KeyArray*) glfwGetWindowUserPointer(window);
keyArray[key].lastState=keyArray[key].curState;
if (action==GLFW_RELEASE)
{
keyArray[key].curState=GLFW_RELEASE;
}
else
{
keyArray[key].curState=GLFW_PRESS;
}
keyArray[key].debounced |= (keyArray[key].lastState==GLFW_RELEASE)&&(keyArray[key].curState==GLFW_PRESS);
keyArray[key].window = window;
}
void sizeHandler(GLFWwindow* window,int xs,int ys)
{
glfwMakeContextCurrent(window);
glViewport(0, 0, xs, ys);
}
void initDisplay(GLWindow *g)
{
int h = g->HEIGHT;
int w = g->WIDTH;
/// Initialize GLFW
glfwInit();
// Open screen OpenGL window
if( !(g->windows=glfwCreateWindow( g->WIDTH, g->HEIGHT, "Main", NULL, NULL)) )
{
glfwTerminate();
fprintf(stderr, "Window creation error...\n");
return;
}
glfwMakeContextCurrent(g->windows);
setupGL(g, g->WIDTH, g->HEIGHT);
glfwSwapInterval(0); // Disable VSYNC
glfwGetWindowSize(g->windows, &w, &h);
glfwSetWindowUserPointer(g->windows, g->keyArray);
glfwSetKeyCallback(g->windows, kbHandler);
glfwSetWindowSizeCallback(g->windows, sizeHandler);
}
void drawPixel(GLWindow *gw, int x, int y, uint32_t colour)
{
uint8_t r,g,b,a;
uint32_t offset = (y*gw->WIDTH*4)+4*x;
if ((x < 0) || (x > gw->WIDTH) || (y < 0) || (y > gw->HEIGHT))
return;
b = colour & 0xFF;
g = (colour >> 8) & 0xFF;
r = (colour >> 16) & 0xFF;
a = (colour >> 24) & 0xFF;
gw->videoMemory[offset + 0] = a;
gw->videoMemory[offset + 1] = r;
gw->videoMemory[offset + 2] = g;
gw->videoMemory[offset + 3] = b;
}
void drawLine(GLWindow *g, int x0, int y0, int x1, int y1, uint32_t colour)
{
int d, dx, dy, aincr, bincr, xincr, yincr, x, y;
if (abs(x1 - x0) < abs(y1 - y0))
{
/* parcours par l'axe vertical */
if (y0 > y1)
{
drawLine(g, x1, y1, x0, y0, colour);
goto exit;
}
xincr = x1 > x0 ? 1 : -1;
dy = y1 - y0;
dx = abs(x1 - x0);
d = 2 * dx - dy;
aincr = 2 * (dx - dy);
bincr = 2 * dx;
x = x0;
y = y0;
drawPixel(g, x, y, colour);
for (y = y0+1; y <= y1; y++)
{
if (d >= 0)
{
x += xincr;
d += aincr;
}
else
{
d += bincr;
}
drawPixel(g, x, y, colour);
}
}
else
{
/* parcours par l'axe horizontal */
if (x0 > x1)
{
drawLine(g, x1, y1, x0, y0, colour);
goto exit;
}
yincr = y1 > y0 ? 1 : -1;
dx = x1 - x0;
dy = abs(y1 - y0);
d = 2 * dy - dx;
aincr = 2 * (dy - dx);
bincr = 2 * dy;
x = x0;
y = y0;
drawPixel(g, x, y, colour);
for (x = x0+1; x <= x1; ++x)
{
if (d >= 0)
{
y += yincr;
d += aincr;
}
else
{
d += bincr;
}
drawPixel(g, x, y, colour);
}
}
exit:
return;
}
void drawCircle(GLWindow *g, int xc, int yc, int radius, uint32_t colour)
{
int f = 1 - radius;
int ddF_x = 0;
int ddF_y = -2 * radius;
int x = 0;
int y = radius;
int pX, pY;
pX = xc; pY = yc + radius;
drawPixel(g, pX, pY, colour);
pY -= (2*radius);
drawPixel(g, pX, pY, colour);
pY += radius; pX += radius;
drawPixel(g, pX, pY, colour);
pX -= (2*radius);
drawPixel(g, pX, pY, colour);
while(x < y)
{
if(f >= 0)
{
y--;
ddF_y += 2;
f += ddF_y;
}
x++;
ddF_x += 2;
f += ddF_x + 1;
pX = xc+x ; pY = yc+y;
drawPixel(g, pX, pY, colour);
pX = xc-x ; pY = yc+y;
drawPixel(g, pX, pY, colour);
pX = xc+x ; pY = yc-y;
drawPixel(g, pX, pY, colour);
pX = xc-x ; pY = yc-y;
drawPixel(g, pX, pY, colour);
pX = xc+y ; pY = yc+x;
drawPixel(g, pX, pY, colour);
pX = xc-y ; pY = yc+x;
drawPixel(g, pX, pY, colour);
pX = xc+y ; pY = yc-x;
drawPixel(g, pX, pY, colour);
pX = xc-y ; pY = yc-x;
drawPixel(g, pX, pY, colour);
}
return;
}
void drawRect(GLWindow *g, int x0, int y0, int w, int h, uint32_t colour)
{
drawLine(g, x0 , y0 , x0 + w, y0 , colour);
drawLine(g, x0 + w, y0 , x0 + w, y0 + h, colour);
drawLine(g, x0 + w, y0 + h, x0 , y0 + h, colour);
drawLine(g, x0 , y0 + h, x0 , y0 , colour);
}
void drawFillrect(GLWindow *g, int x0, int y0, int w, int h, uint32_t colour)
{
int i;
for(i = 0; i < h; i++)
drawLine(g, x0, y0+i, x0+w, y0+i, colour);
}
void clearScreen(GLWindow *g)
{
memset(g->videoMemory, 0, sizeof(uint8_t) * g->WIDTH * g->HEIGHT * 4);
}
void updateScreen(GLWindow *g)
{
/*Update windows code */
glfwMakeContextCurrent(g->windows);
ShowScreen(g, g->WIDTH, g->HEIGHT);
glfwSwapBuffers(g->windows);
glfwPollEvents();
}
void updateScreenAndWait(GLWindow *g)
{
while (glfwGetKey(g->windows,GLFW_KEY_ESCAPE) != GLFW_PRESS)
{
updateScreen(g);
glfwPollEvents();
}
while(glfwGetKey(g->windows,GLFW_KEY_ESCAPE) != GLFW_RELEASE)
{
glfwPollEvents();
}
}
GLWindow mainWindow;
int graphics_init()
{
GLWindowInitEx(&mainWindow, 256, 240);
initDisplay(&mainWindow);
clearScreen(&mainWindow);
updateScreen(&mainWindow);
return 0;
}
static unsigned long getColour(long color)
{
Palette *pal = &basicPalette[color];
uint8_t r, g, b, a;
r = pal->r;
b = pal->b;
g = pal->g;
a = 255;//pal->a;
return (b << 24) | (g << 16) | (r << 8) | a;
}
int graphics_drawpixel(long x, long y, long color)
{
drawPixel(&mainWindow, x, y, getColour(color));
return 0;
}
int graphics_drawline(long x, long y, long x1, long y1, long color)
{
drawLine(&mainWindow, x, y, x1, y1, getColour(color));
return 0;
}
int graphics_blit(long x, long y, long w, long h)
{
updateScreen(&mainWindow);
return 0;
}
int getKeyStatus(int key)
{
return mainWindow.keyArray[key].curState;
}

View File

@ -3,7 +3,7 @@
* os/macos/graphics.c
*
* Created by Manoël Trapier on 04/01/09.
* Copyright (c) 2003-2009 986 Corp. All rights reserved.
* Copyright (c) 2003-2016 986-Studio. All rights reserved.
*
* $LastChangedDate$
* $Author$

View File

@ -1,3 +1,6 @@
/*
* Copyright (c) 2003-2016 986-Studio. All rights reserved.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

View File

@ -3,7 +3,7 @@
* paddle.c
*
* Created by Manoel TRAPIER.
* Copyright (c) 2003-2008 986Corp. All rights reserved.
* Copyright (c) 2003-2016 986-Studio. All rights reserved.
*
* $LastChangedDate$
* $Author$
@ -12,14 +12,8 @@
*
*/
/* Allegro includes */
#ifdef __APPLE__
#define USE_CONSOLE
#include <Allegro/allegro.h>
#else
#define USE_CONSOLE
#include <allegro.h>
#endif
#include <os_dependent.h>
#include "paddle.h"
void InitPaddle(Paddle *pdl)
@ -36,93 +30,65 @@ void WritePaddle(Paddle *pdl, unsigned char val)
pdl->LastWrite = val;
}
unsigned char ReadPaddle(Paddle *pdl)
{
switch(pdl->Bit++)
{
case 1:
if (key[KEY_Z])
if ( getKeyStatus('O') )
return 0x41;
break;
case 2:
if (key[KEY_X])
if ( getKeyStatus('P') )
return 0x41;
break;
case 3:
if (key[KEY_P])
if ( getKeyStatus('I') )
return 0x41;
break;
case 4:
if (key[KEY_ENTER])
if ( getKeyStatus('U') )
return 0x41;
break;
case 5:
if (key[KEY_UP])
if ( getKeyStatus('W') )
return 0x41;
break;
case 6:
if (key[KEY_DOWN])
if ( getKeyStatus('S') )
return 0x41;
break;
case 7:
if (key[KEY_LEFT])
if ( getKeyStatus('A') )
return 0x41;
break;
case 8:
if (key[KEY_RIGHT])
if ( getKeyStatus('D') )
return 0x41;
break;
case 20:
return 0x40;
break;
case 24:
pdl->Bit = 1;
return 0x40;
default:
return 0x40;
break;
}
return 0x40;
return 0x40;
}

View File

@ -2,7 +2,7 @@
# TI-NES CMake
#
# Created by Manoel TRAPIER.
# Copyright (c) 2003-2008 986Corp. All rights reserved.
# Copyright (c) 2003-2016 986-Studio. All rights reserved.
#
# $LastChangedDate$
# $Author$

View File

@ -3,7 +3,7 @@
* plugins.c
*
* Created by Manoel TRAPIER on 02/04/07.
* Copyright (c) 2003-2008 986Corp. All rights reserved.
* Copyright (c) 2003-2016 986-Studio. All rights reserved.
*
* $LastChangedDate$
* $Author$

View File

@ -3,7 +3,7 @@
* gamegenie.c: Hack your games with unlimited lives of add new powers!
*
* Created by Manoel Trapier.
* Copyright 2003-2008 986 Corp. All rights reserved.
* Copyright (c) 2003-2016 986-Studio. All rights reserved.
*
* $LastChangedDate$
* $Author$
@ -24,6 +24,7 @@
#include <memory/manager.h>
#include <types.h>
#if 0
/* Allegro includes */
#ifdef __APPLE__
#define USE_CONSOLE
@ -824,3 +825,4 @@ int gg_Deinit()
{
return 0;
}
#endif

View File

@ -3,7 +3,7 @@
* gamegenie.h
*
* Created by Manoel Trapier.
* Copyright 2003-2008 986 Corp. All rights reserved.
* Copyright (c) 2003-2016 986-Studio. All rights reserved.
*
* $LastChangedDate$
* $Author$

View File

@ -3,7 +3,7 @@
* plugins_list.h
*
* Created by Manoel Trapier.
* Copyright 2003-2008 986 Corp. All rights reserved.
* Copyright (c) 2003-2016 986-Studio. All rights reserved.
*
* $LastChangedDate$
* $Author$
@ -17,7 +17,7 @@
#include "plugins/gamegenie.h"
Plugin Plugins[] = {
{ "Game Genie", gg_Init, gg_Deinit },
// { "Game Genie", gg_Init, gg_Deinit },
/* EOL tag */
{ NULL, NULL, NULL }

View File

@ -5,7 +5,7 @@
* Define and emulate the PPU (Picture Processing Unit) of the real NES
*
* Created by Manoel TRAPIER.
* Copyright (c) 2003-2008 986Corp. All rights reserved.
* Copyright (c) 2003-2016 986-Studio. All rights reserved.
*
* $LastChangedDate$
* $Author$
@ -14,20 +14,14 @@
*
*/
/* Allegro includes */
#ifdef __APPLE__
#define USE_CONSOLE
#include <Allegro/allegro.h>
#else
#define USE_CONSOLE
#include <allegro.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <os_dependent.h>
#define __TINES_PPU_INTERNAL__
#include <ppu/ppu.h>
#include <ppu/ppu.memory.h>
#include <ppu/ppu.debug.h>
@ -37,12 +31,11 @@
#include <os_dependent.h>
#define __TINES_PLUGINS__
#include <plugins/manager.h>
extern int VBLANK_TIME;
extern BITMAP *Buffer;
volatile extern int frame;
volatile extern unsigned long IPS, FPS;
@ -50,115 +43,93 @@ extern unsigned long ColorPalette[ 9 * 63 ];
extern short IRQScanHit;
extern short SZHit;
BITMAP *VideoBuffer; /* The ppu will only write pixel to this, and then bliting
this on the screen "surface" */
typedef struct spriteData
{
uint8_t palette;
uint8_t flip_h;
uint8_t flip_v;
uint8_t priority;
uint8_t tile;
uint8_t bank;
uint8_t y;
uint8_t x;
uint8_t rel_y;
uint8_t inUse;
} spriteData;
/* PPU sprite sorted by scanline */
/* Work as follow:
3322 2222 2222 1111 1111 1100 0000 0000
1098 7654 3210 9876 5432 1098 7654 3210
---------------------------------------
AAAA AAAA TTTT TTTT xxxx XXXX YYYY YYYY
---------------------------------------
8421 8421 8421 8421 8421 8421 8421 8421
A = Sprite Attributes
x = reserved
T = Tile ID
X = X relative position
Y = Y absolute position
x = for future use
*/
unsigned long PPU_SpriteByScanLine[241][9]; /* There is 240 scanline and 8 sprite per scanline */
unsigned long PPU_NbSpriteByScanLine[241]; /* There is 240 scanline and 8 sprite per scanline */
unsigned long PPU_NbSpriteByScanLineOverFlow[241]; /* There is 240 scanline and 8 sprite per scanline */
#define PPU_SCANLINESPRITE_GET_ATTRS(sprt) (((sprt)&0xFF000000) >> 24)
#define PPU_SCANLINESPRITE_GET_TILIDX(sprt) (((sprt)&0x00FF0000) >> 16)
#define PPU_SCANLINESPRITE_GET_RELY(sprt) (((sprt)&0x00000F00) >> 8)
#define PPU_SCANLINESPRITE_GET_X(sprt) ((sprt)&0x000000FF)
#define PPU_SCANLINESPRITE_SET_ATTRS(sprt, v) sprt = (((sprt)&0x00FFFFFF) | (( (v) & 0xFF) << 24))
#define PPU_SCANLINESPRITE_SET_TILIDX(sprt, v) sprt = (((sprt)&0xFF00FFFF) | (( (v) & 0xFF) << 16))
#define PPU_SCANLINESPRITE_SET_RELY(sprt, v) sprt = (((sprt)&0xFFFFF0FF) | (( (v) & 0x0F) << 8))
#define PPU_SCANLINESPRITE_SET_X(sprt, v) sprt = (((sprt)&0xFFFFFF00) | ( (v) & 0xFF ))
/* PPU registers */
/* NT: Name Table */
byte PPU_Reg_NT;
uint8_t PPU_Reg_NT;
/* AT: Attribute/Color Table */
byte PPU_Reg_AT;
uint8_t PPU_Reg_AT;
/* FV: Fine Vertical Scroll latch/counter */
byte PPU_Reg_FV;
uint8_t PPU_Reg_FV;
/* HV: Fine Horizontal Scroll latch/counter */
byte PPU_Reg_FH;
uint8_t PPU_Reg_FH;
/* VT: Vertical Tile indev latch/counter */
byte PPU_Reg_VT;
uint8_t PPU_Reg_VT;
/* HT: Horizontal Tile indev latch/counter */
byte PPU_Reg_HT;
uint8_t PPU_Reg_HT;
/* V: Vertical Name Table Selection latch/counter */
byte PPU_Reg_V;
uint8_t PPU_Reg_V;
/* H: Horizontal Name Table Selection latch/counter */
byte PPU_Reg_H;
uint8_t PPU_Reg_H;
/* S: Playfield pattern table selection latch */
unsigned short PPU_Reg_S;
/* PAR: Picture Address Register */
byte PPU_Reg_PAR;
uint8_t PPU_Reg_PAR;
/* AR: Tile Attribute (palette select) value latch */
byte PPU_Reg_AR;
uint8_t PPU_Reg_AR;
unsigned short PPU_Reg_Counter;
/* PPU Memory Areas */
byte *ppu_mem_nameTables;
byte *ppu_mem_patternTables;
byte *ppu_mem_paletteValues;
uint8_t *ppu_mem_nameTables;
uint8_t *ppu_mem_patternTables;
uint8_t *ppu_mem_paletteValues;
byte ppu_mem_spritesTable[0x100];
byte ppu_mem_sptrTablePtr;
uint8_t ppu_mem_spritesTable[0x100];
uint8_t ppu_mem_sptrTablePtr;
/* Some other PPU "registers" */
byte ppu_VramAccessFlipFlop;
uint8_t ppu_VramAccessFlipFlop;
byte ppu_inVBlankTime;
byte ppu_spriteZeroHit;
byte ppu_scanlineSpriteOverflow;
uint8_t ppu_inVBlankTime;
uint8_t ppu_spriteZeroHit;
uint8_t ppu_scanlineSpriteOverflow;
byte ppu_bgColor;
uint8_t ppu_bgColor;
/* CR #1 variables */
unsigned short ppu_spritePatternTable;
byte ppu_spriteSize;
byte ppu_addrIncrement;
byte ppu_execNMIonVBlank;
uint16_t ppu_spritePatternTable;
uint8_t ppu_spriteSize;
uint8_t ppu_addrIncrement;
uint8_t ppu_execNMIonVBlank;
/* CR #2 variables */
byte ppu_spriteVisibility;
byte ppu_backgroundVisibility;
byte ppu_spriteClipping;
byte ppu_backgroundClipping;
byte ppu_displayType;
uint8_t ppu_spriteVisibility;
uint8_t ppu_backgroundVisibility;
uint8_t ppu_spriteClipping;
uint8_t ppu_backgroundClipping;
uint8_t ppu_displayType;
byte ppu_mirrorMode;
byte ppu_singleScreenMode;
byte ppu_screenMode;
uint8_t ppu_mirrorMode;
uint8_t ppu_singleScreenMode;
uint8_t ppu_screenMode;
#define PPU_MEM_PATTERNTABLES_SIZE 0x2000
#define PPU_MEM_NAMETABLE_SIZE 0x1000
@ -184,7 +155,7 @@ int ppu_init()
{
int i;
/*byte defaultColors[] = { 0x09,0x01,0x00,0x01,0x00,0x02,0x02,0x0D,0x08,0x10,0x08,0x24,0x00,0x00,0x04,0x2C,
/*uint8_t defaultColors[] = { 0x09,0x01,0x00,0x01,0x00,0x02,0x02,0x0D,0x08,0x10,0x08,0x24,0x00,0x00,0x04,0x2C,
0x09,0x01,0x34,0x03,0x00,0x04,0x00,0x14,0x08,0x3A,0x00,0x02,0x00,0x20,0x2C,0x08 };*/
if ( ppu_initMemory() )
@ -193,15 +164,15 @@ int ppu_init()
/* Set ppu memory parameters */
/* First: Allocate each memory zone */
ppu_mem_patternTables = (byte*) malloc(PPU_MEM_PATTERNTABLES_SIZE);
ppu_mem_patternTables = (uint8_t *) malloc(PPU_MEM_PATTERNTABLES_SIZE);
if ( !ppu_mem_patternTables )
return -1;
ppu_mem_nameTables = (byte*) malloc(PPU_MEM_NAMETABLE_SIZE);
ppu_mem_nameTables = (uint8_t *) malloc(PPU_MEM_NAMETABLE_SIZE);
if ( !ppu_mem_nameTables )
return -1;
ppu_mem_paletteValues = (byte*) malloc(PPU_MEM_PALETTEVALUES_SIZE);
ppu_mem_paletteValues = (uint8_t *) malloc(PPU_MEM_PALETTEVALUES_SIZE);
if ( !ppu_mem_paletteValues )
return -1;
@ -264,86 +235,12 @@ int ppu_init()
set_page_ghost(i, true, 0x20);
/* allocate the PPU Video memory */
VideoBuffer = create_bitmap(256, 240);
if (VideoBuffer == NULL)
return -1;
graphics_init();
return 0;
}
void ppu_updateSpriteScanlineTable()
{
int32_t i,j,k;
int line;
volatile int32_t sprite_x, sprite_y, sprite_idx, sprite_attr;
int curline;
for (line = 0; line < 241; line ++)
{
PPU_NbSpriteByScanLine[line] = 0;
PPU_NbSpriteByScanLineOverFlow[line] = 0;
for (i = 0; i < 9; i++)
PPU_SpriteByScanLine[line][i] = 0xFFFFFFFF;
}
for ( i = 0; i < 64; i ++)
{
/* Fill sprite_zzz variables */
sprite_y = ppu_mem_spritesTable[(i*4) + 0] + 1;
sprite_idx = ppu_mem_spritesTable[(i*4) + 1];
sprite_attr = ppu_mem_spritesTable[(i*4) + 2] | ((i==0)?0x04:0); /* Add a flag for the sprite #0 */
sprite_x = ppu_mem_spritesTable[(i*4) + 3];
/* For each line covered by the sprite */
for (line = 0; line < ppu_spriteSize; line ++)
{
curline = line + sprite_y;
if ((curline < 0) || (curline > 240))
continue; /* Don't go beyond, this sprite go beyond the borders */
if (PPU_NbSpriteByScanLine[curline] < 8)
PPU_NbSpriteByScanLine[curline] ++;
else
{
PPU_NbSpriteByScanLineOverFlow[curline] = 1;
continue; /* We have 8 sprite in this line, don't continue */
}
if (((sprite_x+8) < 0) && ((sprite_x-8) > 256))
continue; /* this sprite isn't either displayable */
/* Now test if this sprite can be put in the sprite list */
for (j = 0; j <= (int32_t)PPU_NbSpriteByScanLine[curline]; j++)
{
/* sprite are ordered by their y value, so, the first time that
we have lower y value is where we need to put the sprite */
if (sprite_x < (int32_t)PPU_SCANLINESPRITE_GET_X(PPU_SpriteByScanLine[curline][j]))
{
/* move the j eme item and next to the right in the list, trashing
if needed the rightest item. */
for (k = 7; k >= j; k--)
PPU_SpriteByScanLine[curline][k] = PPU_SpriteByScanLine[curline][k-1];
PPU_SpriteByScanLine[curline][j] = 0;
PPU_SCANLINESPRITE_SET_ATTRS (PPU_SpriteByScanLine[curline][j], sprite_attr);
PPU_SCANLINESPRITE_SET_TILIDX(PPU_SpriteByScanLine[curline][j], sprite_idx);
PPU_SCANLINESPRITE_SET_RELY (PPU_SpriteByScanLine[curline][j], curline - sprite_y);
PPU_SCANLINESPRITE_SET_X (PPU_SpriteByScanLine[curline][j], sprite_x);
break; /* Stop the for, we don't need to go further in the line list */
}
}
}
}
}
void ppu_setMirroring(byte direction)
void ppu_setMirroring(uint8_t direction)
{
if ( ppu_screenMode != PPU_SCMODE_NORMAL )
return;
@ -373,7 +270,7 @@ void ppu_setMirroring(byte direction)
ppu_mirrorMode = direction;
}
void ppu_setSingleScreen(byte screen)
void ppu_setSingleScreen(uint8_t screen)
{
if ( ppu_screenMode != PPU_SCMODE_SINGLE )
return;
@ -421,7 +318,7 @@ void ppu_setSingleScreen(byte screen)
Single screen (1 NT with mirroring)
Normal screen (2 NT with mirroring)
Four screen (4 NT without mirroring) */
void ppu_setScreenMode(byte mode)
void ppu_setScreenMode(uint8_t mode)
{
if ( ppu_screenMode == mode )
return; /* Same value, no need to change! */
@ -478,40 +375,73 @@ _AAA BCDD DDDE EEEE
PPU_Reg_Counter |= PPU_Reg_HT;
}
int ppu_hblank(int scanline)
int ppu_hblank(uint16_t scanline)
{
uint32_t i, j;
byte pixelColor = 0x42;
byte BgColor = 0x42;
byte SpriteColor = 0x42;
uint8_t pixelColor = 0;
uint8_t BgColor = 0;
uint8_t SpriteColor = 0;
/* Sprite to display on current scanline */
spriteData scanSprites[8];
uint16_t addr;
byte value;
uint8_t value;
uint16_t tmp_HHT = 0;
uint16_t tmp_VVTFV = 0;
uint32_t CurrentSprite;
byte SpriteVFlip;
uint8_t spriteCount = 0;
ppu_scanlineSpriteOverflow = 0;
if ( scanline == 0 )
{
ppu_bgColor = ppu_readMemory(0x3F,00);
rectfill(Buffer, 256, 0, 277, 260, ppu_bgColor);
if ( ( ppu_spriteVisibility != 0 ) || ( ppu_backgroundVisibility != 0 ) )
ppu_updateCounters();
}
if ( scanline < 240 )
{
/* Search for sprites on current scanline */
for (i = 0 ; i < 8 ; i++)
{
scanSprites[i].inUse = 0;
}
for (i = 0 ; i < 64 && spriteCount < 8; i++)
{
uint8_t spriteY = ppu_mem_spritesTable[i*4] + 1;
if ((scanline >= spriteY) && (scanline < (spriteY + ppu_spriteSize)))
{
/* This sprite is on the scanline */
scanSprites[spriteCount].inUse = 1;
scanSprites[spriteCount].x = ppu_mem_spritesTable[i*4 + 3];
scanSprites[spriteCount].y = spriteY;
scanSprites[spriteCount].rel_y = scanline - scanSprites[spriteCount].y;
scanSprites[spriteCount].tile = ppu_mem_spritesTable[i * 4 + 1];
scanSprites[spriteCount].bank = ppu_mem_spritesTable[i * 4 + 1] & 0x01;
scanSprites[spriteCount].flip_h = ( ppu_mem_spritesTable[i * 4 + 2] & PPU_SPRITE_FLAGS_HFLIP )?1:0;
scanSprites[spriteCount].flip_v = ( ppu_mem_spritesTable[i * 4 + 2] & PPU_SPRITE_FLAGS_VFLIP )?1:0;
scanSprites[spriteCount].palette = ( ppu_mem_spritesTable[i * 4 + 2] & PPU_SPRITE_FLAGS_UPPERCOLOR ) & 0x0F;
scanSprites[spriteCount].priority = ( ppu_mem_spritesTable[i * 4 + 2] & PPU_SPRITE_FLAGS_BGPRIO )?1:0;
spriteCount++;
}
}
ppu_bgColor = ppu_readMemory(0x3F, 00);
/* For each PPU pixel of this scanline */
for ( i = 0 ; i < 256 ; i++ )
{
/* Set the current pixel color to the bg color */
pixelColor = ppu_readMemory(0x3F,00);
pixelColor = ppu_bgColor;
BgColor = 0;
/* Compute current pixel bg color if bg is visible */
if (ppu_backgroundVisibility == 1)
if (( ppu_backgroundVisibility == 1 ) && (!getKeyStatus('B')))
{
if ( ((i < 8) && (!ppu_backgroundClipping)) || (i >= 8))
{
addr = ( PPU_Reg_Counter & 0x0C00 );
addr = addr | 0x03C0;
@ -555,89 +485,118 @@ int ppu_hblank(int scanline)
( tmp_HHT & 0x001F );
}
}
#if 0
// ISPAL
else
{
pixelColor = 0x1D;
}
#endif
}
/* Now calculate if there is a sprite here and sprite visibility is on */
if ((ppu_spriteVisibility == 1) &&
(PPU_NbSpriteByScanLine[scanline] != 0))
if ( ppu_spriteVisibility == 1 )
{
/* scan each sprite on this line to find the one (or more) that is on this pixel */
for (j = 0; j < PPU_NbSpriteByScanLine[scanline]; j++)
if (((!ppu_spriteClipping) && (i < 8)) || (i >= 8))
{
/* they are orderer by X, so if this one is too far on the right
it's not need to go further */
CurrentSprite = PPU_SpriteByScanLine[scanline][j];
for( j = 0 ; j < 8 ; j++)
{
spriteData *sprite = &scanSprites[j];
int8_t spriteRelX;
if (PPU_SCANLINESPRITE_GET_X(CurrentSprite) > i)
break; /* break the current for */
if ( sprite->inUse == 0 )
break;
if ((PPU_SCANLINESPRITE_GET_X(CurrentSprite) + 8) < i)
continue; /* Not this one too (too far on the left) try next one*/
/* Ok if we arrive here, the current sprite is on the good position */
/* Does the sprite is a BG or FG sprite ? */
/* Ok we could now get the sprite current pixel color */
/* Read sprite scanline pattern */
SpriteVFlip = PPU_SCANLINESPRITE_GET_ATTRS(CurrentSprite) & PPU_SPRITE_FLAGS_VFLIP;
spriteRelX = i - sprite->x;
if ( ( spriteRelX >= 0 ) && ( spriteRelX < 8 ) )
{
/* Get sprite tile address */
if ( ppu_spriteSize == 8 )
{
addr = (PPU_SCANLINESPRITE_GET_TILIDX(CurrentSprite) << 4) + ppu_spritePatternTable;
addr = ( sprite->tile << 4 ) + ppu_spritePatternTable;
}
else
{
if (PPU_SCANLINESPRITE_GET_RELY(CurrentSprite) < 8)
addr = (((PPU_SCANLINESPRITE_GET_TILIDX(CurrentSprite)&0xFE) + (SpriteVFlip?1:0)) << 4) + ((PPU_SCANLINESPRITE_GET_TILIDX(CurrentSprite)&0x01)?0x1000:0x0000);
else
addr = (((PPU_SCANLINESPRITE_GET_TILIDX(CurrentSprite)&0xFE) + (SpriteVFlip?0:1)) << 4) + ((PPU_SCANLINESPRITE_GET_TILIDX(CurrentSprite)&0x01)?0x1000:0x0000);
if ( sprite->rel_y < 8 )
{
addr = ( ( ( sprite->tile & 0xFE ) + ( sprite->flip_v?1:0 ) ) << 4 ) +
( ( sprite->bank )?0x1000:0x0000 );
}
if (SpriteVFlip)
else
{
addr = ( ( ( sprite->tile & 0xFE ) + ( sprite->flip_v?0:1 ) ) << 4 ) +
( ( sprite->bank )?0x1000:0x0000 );
}
}
if ( sprite->flip_v )
{
addr += 7;
addr -= (PPU_SCANLINESPRITE_GET_RELY(CurrentSprite) % 8);
addr -= sprite->rel_y % 8;
}
else
addr += (PPU_SCANLINESPRITE_GET_RELY(CurrentSprite) % 8);
{
addr += sprite->rel_y % 8;
}
if (PPU_SCANLINESPRITE_GET_ATTRS(CurrentSprite) & PPU_SPRITE_FLAGS_HFLIP)
if ( sprite->flip_h )
{
value = ppu_readMemory(( addr >> 8 ), addr);
SpriteColor = (value & (1 << (i-PPU_SCANLINESPRITE_GET_X(CurrentSprite))))?0x01:0;
SpriteColor = ( value & ( 1 << ( spriteRelX ) ) )?0x01:0;
value = ppu_readMemory(( addr >> 8 ), addr | 0x08);
SpriteColor |= (value & (1 << (i-PPU_SCANLINESPRITE_GET_X(CurrentSprite))))?0x02:0;
SpriteColor |= ( value & ( 1 << ( spriteRelX ) ) )?0x02:0;
}
else
{
value = ppu_readMemory(( addr >> 8 ), addr);
SpriteColor = (value & (1 << (7-(i-PPU_SCANLINESPRITE_GET_X(CurrentSprite)))))?0x01:0;
SpriteColor = ( value & ( 1 << ( 7 - ( spriteRelX ) ) ) )?0x01:0;
value = ppu_readMemory(( addr >> 8 ), addr | 0x08);
SpriteColor |= (value & (1 << (7-(i-PPU_SCANLINESPRITE_GET_X(CurrentSprite)))))?0x02:0;
SpriteColor |= ( value & ( 1 << ( 7 - ( spriteRelX ) ) ) )?0x02:0;
}
if (SpriteColor > 0x00)
/* If we get a color different from 0, the pixel is not transparent */
if ( SpriteColor > 0 )
{
SpriteColor |= ((PPU_SCANLINESPRITE_GET_ATTRS(CurrentSprite) & PPU_SPRITE_FLAGS_UPPERCOLOR) << 2);
/* Add second part of the colour */
SpriteColor |= ( ( sprite->palette ) << 2 );
SpriteColor &= 0x0F;
}
if ((PPU_SCANLINESPRITE_GET_ATTRS(CurrentSprite) & 0x04) &&
(SpriteColor != 0x00) && (BgColor != 0x00))
if ( j == 0 )
{
if (!ppu_spriteZeroHit)
/* Sprite 0 */
if ( ( BgColor != 0 ) && ( !ppu_spriteZeroHit ) )
{
ppu_spriteZeroHit = ( ppu_backgroundVisibility )?1:0;
if ( ppu_spriteZeroHit )
SZHit = scanline;
}
}
if ( ( (PPU_SCANLINESPRITE_GET_ATTRS(CurrentSprite) & PPU_SPRITE_FLAGS_BGPRIO) && (BgColor == 0x0000)) ||
(!(PPU_SCANLINESPRITE_GET_ATTRS(CurrentSprite) & PPU_SPRITE_FLAGS_BGPRIO)) )
if ( sprite->priority )
{
if (SpriteColor != 0x00) pixelColor = ppu_readMemory(0x3F, (0x10 + SpriteColor));
if ( SpriteColor > 0x00 )
{
if ( BgColor == 0 )
{
pixelColor = ppu_readMemory(0x3F, ( 0x10 + SpriteColor ));
}
break;
}
}
else
{
if ( SpriteColor != 0x00 )
{
pixelColor = ppu_readMemory(0x3F, ( 0x10 + SpriteColor ));
break;
}
}
}
}
}
}
}
@ -646,14 +605,13 @@ int ppu_hblank(int scanline)
pixelColor &= 0x30;
/* draw the pixel */
_putpixel(VideoBuffer, i, scanline, pixelColor);
graphics_drawpixel(i, scanline, pixelColor);
}
if (ppu_backgroundVisibility || ppu_spriteVisibility)
if (PPU_NbSpriteByScanLineOverFlow[scanline] == 1)
if (spriteCount > 8)
{
ppu_scanlineSpriteOverflow = 1;
//blit(VideoBuffer, screen, 0, scanline, 0, scanline, 256, 1);
}
if ( ppu_backgroundVisibility == 1 )
{
@ -680,7 +638,7 @@ int ppu_hblank(int scanline)
PPU_Reg_HT;
}
}
/* Increment only V & VT & FV*/
/* Increment only V, VT & FV*/
/*
8421 8421 8421 8421
@ -706,33 +664,22 @@ E = HT
if ( scanline == 239 )
{
ppu_inVBlankTime = 1;
textprintf_ex(Buffer, font, 260, 3, 4, 0, "FPS : %ld (CPU@~%2.2fMhz : %d%%)", FPS, (float) (((float) IPS) / 1000000.0), (int) ((((float) IPS) / 1770000.0) * 100.0));
blit(VideoBuffer, Buffer, 0, 0, 0, 0, 256, 240);
blit(Buffer, screen, 0, 0, 0, 0, 512+256, 512);
// textprintf_ex(Buffer, font, 260, 3, 4, 0, "FPS : %ld (CPU@~%2.2fMhz : %d%%)", FPS, (float) (((float) IPS) / 1000000.0), (int) ((((float) IPS) / 1770000.0) * 100.0));
graphics_blit(0, 0, 256, 240);
return ppu_execNMIonVBlank;
}
if (scanline == SZHit)
/* Debug tools */
/*if ( scanline == SZHit )
{
line(Buffer, 257, scanline, 267, scanline, 0x12);
line(Buffer, 257, scanline, 260, scanline-2, 0x12);
line(Buffer, 257, scanline, 260, scanline+2, 0x12);
graphics_drawline(0, scanline, 256, scanline, 0x12);
}
if ( scanline == IRQScanHit )
{
line(Buffer, 267, scanline, 277, scanline, 0x13);
line(Buffer, 267, scanline, 270, scanline-2, 0x13);
line(Buffer, 267, scanline, 270, scanline+2, 0x13);
}
if (key[KEY_B])
{
blit(VideoBuffer, Buffer, 0, 0, 0, 0, 256, 240);
blit(Buffer, screen, 0, 0, 0, 0, 512 + 256, 480);
}
graphics_drawline(0, scanline, 256, scanline, 0x13);
}*/
/* */
if ( scanline == ( 239 + VBLANK_TIME ) + 0 )
{
@ -743,13 +690,13 @@ E = HT
return 0;
}
byte PPU_RegValues[8];
uint8_t PPU_RegValues[8];
byte ppu_readReg(byte id)
uint8_t ppu_readReg(uint8_t id)
{
id &= 0x07;
static byte garbage;
static byte lastValue;
static uint8_t garbage;
static uint8_t lastValue;
switch(id)
{
default:
@ -795,7 +742,7 @@ byte ppu_readReg(byte id)
}
void ppu_writeReg(byte id, byte val)
void ppu_writeReg(uint8_t id, uint8_t val)
{
id &= 0x07;
PPU_RegValues[id] = val;
@ -805,7 +752,6 @@ void ppu_writeReg(byte id, byte val)
break;
case 0x00: /* PPU Control Register #1 */
/*
+===============+===============================================+
|2000 | 1 0 4 |
@ -829,14 +775,11 @@ void ppu_writeReg(byte id, byte val)
break;
case 0x01: /* PPU Control Register #2 */
ppu_spriteVisibility = ( val & 0x10 )?1:0;
ppu_backgroundVisibility = ( val & 0x08 )?1:0;
ppu_spriteClipping = (val & 0x04)?1:0;
ppu_backgroundClipping = (val & 0x02)?1:0;
ppu_spriteClipping = ( val & 0x04 )?0:1;
ppu_backgroundClipping = ( val & 0x02 )?0:1;
ppu_displayType = ( val & 0x01 )?1:0;
ppu_updateSpriteScanlineTable();
break;
case 0x03: /* SPR-RAM Address Register */
@ -845,7 +788,6 @@ void ppu_writeReg(byte id, byte val)
case 0x04: /* SPR-RAM I/O */
ppu_mem_spritesTable[ppu_mem_sptrTablePtr++] = val;
ppu_updateSpriteScanlineTable();
break;
case 0x05: /* 2005 VRAM Register */
@ -928,13 +870,12 @@ void ppu_writeReg(byte id, byte val)
}
}
void ppu_fillSprRamDMA(byte value)
void ppu_fillSprRamDMA(uint8_t value)
{
short i;
byte *ptr = get_page_ptr(value);
uint8_t *ptr = get_page_ptr(value);
for ( i = 0 ; i < 0x100 ; i++ )
{
ppu_mem_spritesTable[( ppu_mem_sptrTablePtr + i ) & 0xFF] = *( ptr + i );
}
ppu_updateSpriteScanlineTable();
}

View File

@ -3,7 +3,7 @@
* ppu.memory.c - Inspired from the memory manager of the Quick6502 Project.
*
* Created by Manoel Trapier on 12/04/07.
* Copyright 2003-2008 986 Corp. All rights reserved.
* Copyright (c) 2003-2016 986-Studio. All rights reserved.
*
* $LastChangedDate$
* $Author$