From dfaace8956f9f260a72f36e992e03a682a14ae24 Mon Sep 17 00:00:00 2001
From: FIX94 <fix94.1@gmail.com>
Date: Sun, 4 Jun 2017 00:21:50 +0200
Subject: [PATCH] now supporting color palette changes through register $2001
 used by several games

---
 apu.c                       |   5 +-
 audio.c                     |   1 +
 audio_fds.c                 |   1 +
 audio_mmc5.c                |   1 +
 audio_vrc6.c                |   2 +-
 audio_vrc7.c                |   3 +-
 build_linux.sh              |   2 +-
 build_msys32.sh             |   2 +
 build_windows_console.bat   |   2 +-
 build_windows_noconsole.bat |   2 +-
 cpu.c                       | 141 ++++++++++++++++++------------------
 fm2play.c                   |   1 +
 input.c                     |   1 +
 main.c                      |  16 +---
 mapper/fds.c                |   1 +
 mapper/m1.c                 |   1 +
 mapper/m13.c                |   1 +
 mapper/m15.c                |   1 +
 mapper/m4.c                 |   1 +
 mapper/m48.c                |   1 +
 mapper/m7.c                 |   1 +
 mapper/nsf.c                |   1 +
 mapper/p16c4.c              |   1 +
 mapper/p16c8.c              |   1 +
 mapper/p32c4.c              |   1 +
 mapper/p32c8.c              |   1 +
 mapper/vrc2_4.c             |   1 +
 mapper/vrc6.c               |   1 +
 mapper/vrc7.c               |   1 +
 mem.c                       |   1 +
 ppu.c                       |  54 +++++++++++---
 31 files changed, 150 insertions(+), 100 deletions(-)
 create mode 100644 build_msys32.sh

diff --git a/apu.c b/apu.c
index 09f46af..692a8fb 100644
--- a/apu.c
+++ b/apu.c
@@ -8,6 +8,7 @@
 #include <stdio.h>
 #include <stdbool.h>
 #include <inttypes.h>
+#include <string.h>
 #include <malloc.h>
 #include "apu.h"
 #include "audio_fds.h"
@@ -152,7 +153,9 @@ void apuInitBufs()
 	mode4Ctr = nesPAL ? mode4CtrPal : mode4CtrNtsc;
 	mode5Ctr = nesPAL ? mode5CtrPal : mode5CtrNtsc;
 	//effective frequencies for 50.000Hz and 60.000Hz Video out
-	apuFrequency = nesPAL ? 831187 : 893415;
+	//apuFrequency = nesPAL ? 831187 : 893415;
+	//effective frequencies for Original PPU Video out
+	apuFrequency = nesPAL ? 831303 : 894886;
 	double dt = 1.0/((double)apuFrequency);
 	//LP at 22kHz
 	double rc = 1.0/(M_2_PI * 22000.0);
diff --git a/audio.c b/audio.c
index 652e3b8..0f66e79 100644
--- a/audio.c
+++ b/audio.c
@@ -1,6 +1,7 @@
 #include <string.h>
 #include <stdio.h>
 #include <stdbool.h>
+#include <string.h>
 #include <malloc.h>
 #include <math.h>
 #include "AL/al.h"
diff --git a/audio_fds.c b/audio_fds.c
index feb4f43..9e2455f 100644
--- a/audio_fds.c
+++ b/audio_fds.c
@@ -8,6 +8,7 @@
 #include <stdio.h>
 #include <stdbool.h>
 #include <inttypes.h>
+#include <string.h>
 #include <malloc.h>
 #include "apu.h"
 #include "audio_fds.h"
diff --git a/audio_mmc5.c b/audio_mmc5.c
index b1ed8c6..fd22f4b 100644
--- a/audio_mmc5.c
+++ b/audio_mmc5.c
@@ -8,6 +8,7 @@
 #include <stdio.h>
 #include <stdbool.h>
 #include <inttypes.h>
+#include <string.h>
 #include <malloc.h>
 #include "apu.h"
 #include "audio_mmc5.h"
diff --git a/audio_vrc6.c b/audio_vrc6.c
index 9a4b4d9..fbc4394 100644
--- a/audio_vrc6.c
+++ b/audio_vrc6.c
@@ -38,7 +38,7 @@ void vrc6AudioInit()
 	vrc6_p1Duty = 0, vrc6_p2Duty = 0, vrc6_sawAdd = 0;
 	vrc6_speed = 0;
 	vrc6_p1const = false, vrc6_p2const = false;
-	vrc6_p1enable = false, vrc6_p2enable = false, vrc6_sawenable;
+	vrc6_p1enable = false, vrc6_p2enable = false, vrc6_sawenable = false;
 	vrc6_halt = false;
 	//printf("VRC6 Audio Inited!\n");
 }
diff --git a/audio_vrc7.c b/audio_vrc7.c
index 1822fe9..83caef4 100644
--- a/audio_vrc7.c
+++ b/audio_vrc7.c
@@ -8,6 +8,7 @@
 #include <stdio.h>
 #include <stdbool.h>
 #include <inttypes.h>
+#include <string.h>
 #include <malloc.h>
 #include <math.h>
 #include "audio_vrc7.h"
@@ -85,7 +86,7 @@ enum
 static const uint32_t vrc7MaxAtten = (1<<23);
 static const double attenDb = (1<<23) / 48.0;
 
-inline int32_t vrc7FromDb(double in)
+static inline int32_t vrc7FromDb(double in)
 {
 	return (int32_t)(in * attenDb);
 }
diff --git a/build_linux.sh b/build_linux.sh
index 2060387..e321d6a 100755
--- a/build_linux.sh
+++ b/build_linux.sh
@@ -2,6 +2,6 @@
 
 #Need to replace this with a makefile
 
-gcc main.c apu.c audio.c audio_fds.c audio_mmc5.c audio_vrc6.c audio_vrc7.c alhelpers.c cpu.c ppu.c mem.c input.c mapper.c mapperList.c fm2play.c vrc_irq.c mapper/*.c -DFREEGLUT_STATIC -lglut -lopenal -lGL -lGLU -lm -Wall -Wextra -O3 -msse -mfpmath=sse -ffast-math -s -o fixNES
+gcc main.c apu.c audio.c audio_fds.c audio_mmc5.c audio_vrc6.c audio_vrc7.c alhelpers.c cpu.c ppu.c mem.c input.c mapper.c mapperList.c fm2play.c vrc_irq.c mapper/*.c -DFREEGLUT_STATIC -lglut -lopenal -lGL -lGLU -lm -Wall -Wextra -O3 -flto -msse -mfpmath=sse -ffast-math -s -o fixNES
 echo "Succesfully built fixNES"
 
diff --git a/build_msys32.sh b/build_msys32.sh
new file mode 100644
index 0000000..85312f4
--- /dev/null
+++ b/build_msys32.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+gcc -DWINDOWS_BUILD main.c apu.c audio.c audio_fds.c audio_mmc5.c audio_vrc6.c audio_vrc7.c alhelpers.c cpu.c ppu.c mem.c input.c mapper.c mapperList.c fm2play.c vrc_irq.c mapper/*.c -DFREEGLUT_STATIC -lfreeglut_static -lopenal32 -lopengl32 -lglu32 -lgdi32 -lwinmm -Wall -Wextra -O3 -flto -msse -mfpmath=sse -ffast-math -s -o fixNES
\ No newline at end of file
diff --git a/build_windows_console.bat b/build_windows_console.bat
index a1a5c1f..cea8b45 100644
--- a/build_windows_console.bat
+++ b/build_windows_console.bat
@@ -1,2 +1,2 @@
-gcc -DWINDOWS_BUILD main.c apu.c audio.c audio_fds.c audio_mmc5.c audio_vrc6.c audio_vrc7.c alhelpers.c cpu.c ppu.c mem.c input.c mapper.c mapperList.c fm2play.c vrc_irq.c mapper/*.c -DFREEGLUT_STATIC -lfreeglut_static -lopenal32 -lopengl32 -lglu32 -lgdi32 -lwinmm -Wall -Wextra -O3 -msse -mfpmath=sse -ffast-math -s -o fixNES
+gcc -DWINDOWS_BUILD main.c apu.c audio.c audio_fds.c audio_mmc5.c audio_vrc6.c audio_vrc7.c alhelpers.c cpu.c ppu.c mem.c input.c mapper.c mapperList.c fm2play.c vrc_irq.c mapper/*.c -DFREEGLUT_STATIC -lfreeglut_static -lopenal32 -lopengl32 -lglu32 -lgdi32 -lwinmm -Wall -Wextra -O3 -flto -msse -mfpmath=sse -ffast-math -s -o fixNES
 pause
\ No newline at end of file
diff --git a/build_windows_noconsole.bat b/build_windows_noconsole.bat
index 6db2a7d..41a62e6 100644
--- a/build_windows_noconsole.bat
+++ b/build_windows_noconsole.bat
@@ -1,2 +1,2 @@
-gcc -DWINDOWS_BUILD main.c apu.c audio.c audio_fds.c audio_mmc5.c audio_vrc6.c audio_vrc7.c alhelpers.c cpu.c ppu.c mem.c input.c mapper.c mapperList.c fm2play.c vrc_irq.c mapper/*.c -DFREEGLUT_STATIC -lfreeglut_static -lopenal32 -lopengl32 -lglu32 -lgdi32 -lwinmm -Wall -Wextra -O3 -msse -mfpmath=sse -ffast-math -s -o fixNES -Wl,--subsystem,windows
+gcc -DWINDOWS_BUILD main.c apu.c audio.c audio_fds.c audio_mmc5.c audio_vrc6.c audio_vrc7.c alhelpers.c cpu.c ppu.c mem.c input.c mapper.c mapperList.c fm2play.c vrc_irq.c mapper/*.c -DFREEGLUT_STATIC -lfreeglut_static -lopenal32 -lopengl32 -lglu32 -lgdi32 -lwinmm -Wall -Wextra -O3 -flto -msse -mfpmath=sse -ffast-math -s -o fixNES -Wl,--subsystem,windows
 pause 
diff --git a/cpu.c b/cpu.c
index 2366301..a494d57 100644
--- a/cpu.c
+++ b/cpu.c
@@ -8,6 +8,7 @@
 #include <stdio.h>
 #include <stdbool.h>
 #include <inttypes.h>
+#include <string.h>
 #include "mem.h"
 #include "ppu.h"
 #include "apu.h"
@@ -270,6 +271,8 @@ static uint8_t cpuCMP(uint8_t reg)
 	return cmpVal;
 }
 
+static void cpuNoAction() { ; };
+
 static void cpuCMPa() { cpuCMP(a); }
 static void cpuCMPx() { cpuCMP(x); }
 static void cpuCMPy() { cpuCMP(y); }
@@ -630,85 +633,87 @@ static uint8_t *cpu_instr_arr[256] = {
 static cpu_action_t cpu_actions_arr[256];
 void cpuSetupActionArr()
 {
-	cpu_actions_arr[0x00] = NULL; cpu_actions_arr[0x01] = cpuORA; cpu_actions_arr[0x02] = cpuKIL; cpu_actions_arr[0x03] = cpuSLO;
-	cpu_actions_arr[0x04] = NULL; cpu_actions_arr[0x05] = cpuORA; cpu_actions_arr[0x06] = cpuASLt; cpu_actions_arr[0x07] = cpuSLO;
-	cpu_actions_arr[0x08] = NULL; cpu_actions_arr[0x09] = cpuORA; cpu_actions_arr[0x0A] = cpuASLa; cpu_actions_arr[0x0B] = cpuAAC; 
-	cpu_actions_arr[0x0C] = NULL; cpu_actions_arr[0x0D] = cpuORA; cpu_actions_arr[0x0E] = cpuASLt; cpu_actions_arr[0x0F] = cpuSLO;
+	cpu_actions_arr[0x00] = cpuNoAction; cpu_actions_arr[0x01] = cpuORA; cpu_actions_arr[0x02] = cpuKIL; cpu_actions_arr[0x03] = cpuSLO;
+	cpu_actions_arr[0x04] = cpuNoAction; cpu_actions_arr[0x05] = cpuORA; cpu_actions_arr[0x06] = cpuASLt; cpu_actions_arr[0x07] = cpuSLO;
+	cpu_actions_arr[0x08] = cpuNoAction; cpu_actions_arr[0x09] = cpuORA; cpu_actions_arr[0x0A] = cpuASLa; cpu_actions_arr[0x0B] = cpuAAC; 
+	cpu_actions_arr[0x0C] = cpuNoAction; cpu_actions_arr[0x0D] = cpuORA; cpu_actions_arr[0x0E] = cpuASLt; cpu_actions_arr[0x0F] = cpuSLO;
 
-	cpu_actions_arr[0x10] = NULL; cpu_actions_arr[0x11] = cpuORA; cpu_actions_arr[0x12] = cpuKIL; cpu_actions_arr[0x13] = cpuSLO;
-	cpu_actions_arr[0x14] = NULL; cpu_actions_arr[0x15] = cpuORA; cpu_actions_arr[0x16] = cpuASLt; cpu_actions_arr[0x17] = cpuSLO;
-	cpu_actions_arr[0x18] = cpuCLC; cpu_actions_arr[0x19] = cpuORA; cpu_actions_arr[0x1A] = NULL; cpu_actions_arr[0x1B] = cpuSLO; 
-	cpu_actions_arr[0x1C] = NULL; cpu_actions_arr[0x1D] = cpuORA; cpu_actions_arr[0x1E] = cpuASLt; cpu_actions_arr[0x1F] = cpuSLO;
+	cpu_actions_arr[0x10] = cpuNoAction; cpu_actions_arr[0x11] = cpuORA; cpu_actions_arr[0x12] = cpuKIL; cpu_actions_arr[0x13] = cpuSLO;
+	cpu_actions_arr[0x14] = cpuNoAction; cpu_actions_arr[0x15] = cpuORA; cpu_actions_arr[0x16] = cpuASLt; cpu_actions_arr[0x17] = cpuSLO;
+	cpu_actions_arr[0x18] = cpuCLC; cpu_actions_arr[0x19] = cpuORA; cpu_actions_arr[0x1A] = cpuNoAction; cpu_actions_arr[0x1B] = cpuSLO; 
+	cpu_actions_arr[0x1C] = cpuNoAction; cpu_actions_arr[0x1D] = cpuORA; cpu_actions_arr[0x1E] = cpuASLt; cpu_actions_arr[0x1F] = cpuSLO;
 
-	cpu_actions_arr[0x20] = NULL; cpu_actions_arr[0x21] = cpuAND; cpu_actions_arr[0x22] = cpuKIL; cpu_actions_arr[0x23] = cpuRLA;
+	cpu_actions_arr[0x20] = cpuNoAction; cpu_actions_arr[0x21] = cpuAND; cpu_actions_arr[0x22] = cpuKIL; cpu_actions_arr[0x23] = cpuRLA;
 	cpu_actions_arr[0x24] = cpuBIT; cpu_actions_arr[0x25] = cpuAND; cpu_actions_arr[0x26] = cpuROLt; cpu_actions_arr[0x27] = cpuRLA;
-	cpu_actions_arr[0x28] = NULL; cpu_actions_arr[0x29] = cpuAND; cpu_actions_arr[0x2A] = cpuROLa; cpu_actions_arr[0x2B] = cpuAAC; 
+	cpu_actions_arr[0x28] = cpuNoAction; cpu_actions_arr[0x29] = cpuAND; cpu_actions_arr[0x2A] = cpuROLa; cpu_actions_arr[0x2B] = cpuAAC; 
 	cpu_actions_arr[0x2C] = cpuBIT; cpu_actions_arr[0x2D] = cpuAND; cpu_actions_arr[0x2E] = cpuROLt; cpu_actions_arr[0x2F] = cpuRLA;
 
-	cpu_actions_arr[0x30] = NULL; cpu_actions_arr[0x31] = cpuAND; cpu_actions_arr[0x32] = cpuKIL; cpu_actions_arr[0x33] = cpuRLA;
-	cpu_actions_arr[0x34] = NULL; cpu_actions_arr[0x35] = cpuAND; cpu_actions_arr[0x36] = cpuROLt; cpu_actions_arr[0x37] = cpuRLA;
-	cpu_actions_arr[0x38] = cpuSEC; cpu_actions_arr[0x39] = cpuAND; cpu_actions_arr[0x3A] = NULL; cpu_actions_arr[0x3B] = cpuRLA; 
-	cpu_actions_arr[0x3C] = NULL; cpu_actions_arr[0x3D] = cpuAND; cpu_actions_arr[0x3E] = cpuROLt; cpu_actions_arr[0x3F] = cpuRLA;
-
-	cpu_actions_arr[0x40] = NULL; cpu_actions_arr[0x41] = cpuEOR; cpu_actions_arr[0x42] = cpuKIL; cpu_actions_arr[0x43] = cpuSRE;
-	cpu_actions_arr[0x44] = NULL; cpu_actions_arr[0x45] = cpuEOR; cpu_actions_arr[0x46] = cpuLSRt; cpu_actions_arr[0x47] = cpuSRE;
-	cpu_actions_arr[0x48] = NULL; cpu_actions_arr[0x49] = cpuEOR; cpu_actions_arr[0x4A] = cpuLSRa; cpu_actions_arr[0x4B] = cpuASR; 
-	cpu_actions_arr[0x4C] = NULL; cpu_actions_arr[0x4D] = cpuEOR; cpu_actions_arr[0x4E] = cpuLSRt; cpu_actions_arr[0x4F] = cpuSRE;
-
-	cpu_actions_arr[0x50] = NULL; cpu_actions_arr[0x51] = cpuEOR; cpu_actions_arr[0x52] = cpuKIL; cpu_actions_arr[0x53] = cpuSRE;
-	cpu_actions_arr[0x54] = NULL; cpu_actions_arr[0x55] = cpuEOR; cpu_actions_arr[0x56] = cpuLSRt; cpu_actions_arr[0x57] = cpuSRE;
-	cpu_actions_arr[0x58] = cpuCLI; cpu_actions_arr[0x59] = cpuEOR; cpu_actions_arr[0x5A] = NULL; cpu_actions_arr[0x5B] = cpuSRE; 
-	cpu_actions_arr[0x5C] = NULL; cpu_actions_arr[0x5D] = cpuEOR; cpu_actions_arr[0x5E] = cpuLSRt; cpu_actions_arr[0x5F] = cpuSRE;
-
-	cpu_actions_arr[0x60] = NULL; cpu_actions_arr[0x61] = cpuADC; cpu_actions_arr[0x62] = cpuKIL; cpu_actions_arr[0x63] = cpuRRA;
-	cpu_actions_arr[0x64] = NULL; cpu_actions_arr[0x65] = cpuADC; cpu_actions_arr[0x66] = cpuRORt; cpu_actions_arr[0x67] = cpuRRA;
-	cpu_actions_arr[0x68] = NULL; cpu_actions_arr[0x69] = cpuADC; cpu_actions_arr[0x6A] = cpuRORa; cpu_actions_arr[0x6B] = cpuARR; 
-	cpu_actions_arr[0x6C] = NULL; cpu_actions_arr[0x6D] = cpuADC; cpu_actions_arr[0x6E] = cpuRORt; cpu_actions_arr[0x6F] = cpuRRA;
-
-	cpu_actions_arr[0x70] = NULL; cpu_actions_arr[0x71] = cpuADC; cpu_actions_arr[0x72] = cpuKIL; cpu_actions_arr[0x73] = cpuRRA;
-	cpu_actions_arr[0x74] = NULL; cpu_actions_arr[0x75] = cpuADC; cpu_actions_arr[0x76] = cpuRORt; cpu_actions_arr[0x77] = cpuRRA;
-	cpu_actions_arr[0x78] = cpuSEI; cpu_actions_arr[0x79] = cpuADC; cpu_actions_arr[0x7A] = NULL; cpu_actions_arr[0x7B] = cpuRRA; 
-	cpu_actions_arr[0x7C] = NULL; cpu_actions_arr[0x7D] = cpuADC; cpu_actions_arr[0x7E] = cpuRORt; cpu_actions_arr[0x7F] = cpuRRA;
-
-	cpu_actions_arr[0x80] = NULL; cpu_actions_arr[0x81] = NULL; cpu_actions_arr[0x82] = NULL; cpu_actions_arr[0x83] = NULL;
-	cpu_actions_arr[0x84] = NULL; cpu_actions_arr[0x85] = NULL; cpu_actions_arr[0x86] = NULL; cpu_actions_arr[0x87] = NULL;
-	cpu_actions_arr[0x88] = cpuDEY; cpu_actions_arr[0x89] = NULL; cpu_actions_arr[0x8A] = cpuTXA; cpu_actions_arr[0x8B] = cpuXAA; 
-	cpu_actions_arr[0x8C] = NULL; cpu_actions_arr[0x8D] = NULL; cpu_actions_arr[0x8E] = NULL; cpu_actions_arr[0x8F] = NULL;
-
-	cpu_actions_arr[0x90] = NULL; cpu_actions_arr[0x91] = NULL; cpu_actions_arr[0x92] = cpuKIL; cpu_actions_arr[0x93] = NULL;
-	cpu_actions_arr[0x94] = NULL; cpu_actions_arr[0x95] = NULL; cpu_actions_arr[0x96] = NULL; cpu_actions_arr[0x97] = NULL;
-	cpu_actions_arr[0x98] = cpuTYA; cpu_actions_arr[0x99] = NULL; cpu_actions_arr[0x9A] = cpuTXS; cpu_actions_arr[0x9B] = NULL; 
-	cpu_actions_arr[0x9C] = NULL; cpu_actions_arr[0x9D] = NULL; cpu_actions_arr[0x9E] = NULL; cpu_actions_arr[0x9F] = NULL;
+	cpu_actions_arr[0x30] = cpuNoAction; cpu_actions_arr[0x31] = cpuAND; cpu_actions_arr[0x32] = cpuKIL; cpu_actions_arr[0x33] = cpuRLA;
+	cpu_actions_arr[0x34] = cpuNoAction; cpu_actions_arr[0x35] = cpuAND; cpu_actions_arr[0x36] = cpuROLt; cpu_actions_arr[0x37] = cpuRLA;
+	cpu_actions_arr[0x38] = cpuSEC; cpu_actions_arr[0x39] = cpuAND; cpu_actions_arr[0x3A] = cpuNoAction; cpu_actions_arr[0x3B] = cpuRLA; 
+	cpu_actions_arr[0x3C] = cpuNoAction; cpu_actions_arr[0x3D] = cpuAND; cpu_actions_arr[0x3E] = cpuROLt; cpu_actions_arr[0x3F] = cpuRLA;
+
+	cpu_actions_arr[0x40] = cpuNoAction; cpu_actions_arr[0x41] = cpuEOR; cpu_actions_arr[0x42] = cpuKIL; cpu_actions_arr[0x43] = cpuSRE;
+	cpu_actions_arr[0x44] = cpuNoAction; cpu_actions_arr[0x45] = cpuEOR; cpu_actions_arr[0x46] = cpuLSRt; cpu_actions_arr[0x47] = cpuSRE;
+	cpu_actions_arr[0x48] = cpuNoAction; cpu_actions_arr[0x49] = cpuEOR; cpu_actions_arr[0x4A] = cpuLSRa; cpu_actions_arr[0x4B] = cpuASR; 
+	cpu_actions_arr[0x4C] = cpuNoAction; cpu_actions_arr[0x4D] = cpuEOR; cpu_actions_arr[0x4E] = cpuLSRt; cpu_actions_arr[0x4F] = cpuSRE;
+
+	cpu_actions_arr[0x50] = cpuNoAction; cpu_actions_arr[0x51] = cpuEOR; cpu_actions_arr[0x52] = cpuKIL; cpu_actions_arr[0x53] = cpuSRE;
+	cpu_actions_arr[0x54] = cpuNoAction; cpu_actions_arr[0x55] = cpuEOR; cpu_actions_arr[0x56] = cpuLSRt; cpu_actions_arr[0x57] = cpuSRE;
+	cpu_actions_arr[0x58] = cpuCLI; cpu_actions_arr[0x59] = cpuEOR; cpu_actions_arr[0x5A] = cpuNoAction; cpu_actions_arr[0x5B] = cpuSRE; 
+	cpu_actions_arr[0x5C] = cpuNoAction; cpu_actions_arr[0x5D] = cpuEOR; cpu_actions_arr[0x5E] = cpuLSRt; cpu_actions_arr[0x5F] = cpuSRE;
+
+	cpu_actions_arr[0x60] = cpuNoAction; cpu_actions_arr[0x61] = cpuADC; cpu_actions_arr[0x62] = cpuKIL; cpu_actions_arr[0x63] = cpuRRA;
+	cpu_actions_arr[0x64] = cpuNoAction; cpu_actions_arr[0x65] = cpuADC; cpu_actions_arr[0x66] = cpuRORt; cpu_actions_arr[0x67] = cpuRRA;
+	cpu_actions_arr[0x68] = cpuNoAction; cpu_actions_arr[0x69] = cpuADC; cpu_actions_arr[0x6A] = cpuRORa; cpu_actions_arr[0x6B] = cpuARR; 
+	cpu_actions_arr[0x6C] = cpuNoAction; cpu_actions_arr[0x6D] = cpuADC; cpu_actions_arr[0x6E] = cpuRORt; cpu_actions_arr[0x6F] = cpuRRA;
+
+	cpu_actions_arr[0x70] = cpuNoAction; cpu_actions_arr[0x71] = cpuADC; cpu_actions_arr[0x72] = cpuKIL; cpu_actions_arr[0x73] = cpuRRA;
+	cpu_actions_arr[0x74] = cpuNoAction; cpu_actions_arr[0x75] = cpuADC; cpu_actions_arr[0x76] = cpuRORt; cpu_actions_arr[0x77] = cpuRRA;
+	cpu_actions_arr[0x78] = cpuSEI; cpu_actions_arr[0x79] = cpuADC; cpu_actions_arr[0x7A] = cpuNoAction; cpu_actions_arr[0x7B] = cpuRRA; 
+	cpu_actions_arr[0x7C] = cpuNoAction; cpu_actions_arr[0x7D] = cpuADC; cpu_actions_arr[0x7E] = cpuRORt; cpu_actions_arr[0x7F] = cpuRRA;
+
+	cpu_actions_arr[0x80] = cpuNoAction; cpu_actions_arr[0x81] = cpuNoAction; cpu_actions_arr[0x82] = cpuNoAction; cpu_actions_arr[0x83] = cpuNoAction;
+	cpu_actions_arr[0x84] = cpuNoAction; cpu_actions_arr[0x85] = cpuNoAction; cpu_actions_arr[0x86] = cpuNoAction; cpu_actions_arr[0x87] = cpuNoAction;
+	cpu_actions_arr[0x88] = cpuDEY; cpu_actions_arr[0x89] = cpuNoAction; cpu_actions_arr[0x8A] = cpuTXA; cpu_actions_arr[0x8B] = cpuXAA; 
+	cpu_actions_arr[0x8C] = cpuNoAction; cpu_actions_arr[0x8D] = cpuNoAction; cpu_actions_arr[0x8E] = cpuNoAction; cpu_actions_arr[0x8F] = cpuNoAction;
+
+	cpu_actions_arr[0x90] = cpuNoAction; cpu_actions_arr[0x91] = cpuNoAction; cpu_actions_arr[0x92] = cpuKIL; cpu_actions_arr[0x93] = cpuNoAction;
+	cpu_actions_arr[0x94] = cpuNoAction; cpu_actions_arr[0x95] = cpuNoAction; cpu_actions_arr[0x96] = cpuNoAction; cpu_actions_arr[0x97] = cpuNoAction;
+	cpu_actions_arr[0x98] = cpuTYA; cpu_actions_arr[0x99] = cpuNoAction; cpu_actions_arr[0x9A] = cpuTXS; cpu_actions_arr[0x9B] = cpuNoAction; 
+	cpu_actions_arr[0x9C] = cpuNoAction; cpu_actions_arr[0x9D] = cpuNoAction; cpu_actions_arr[0x9E] = cpuNoAction; cpu_actions_arr[0x9F] = cpuNoAction;
 
 	cpu_actions_arr[0xA0] = cpuLDY; cpu_actions_arr[0xA1] = cpuLDA; cpu_actions_arr[0xA2] = cpuLDX; cpu_actions_arr[0xA3] = cpuLAX;
 	cpu_actions_arr[0xA4] = cpuLDY; cpu_actions_arr[0xA5] = cpuLDA; cpu_actions_arr[0xA6] = cpuLDX; cpu_actions_arr[0xA7] = cpuLAX;
 	cpu_actions_arr[0xA8] = cpuTAY; cpu_actions_arr[0xA9] = cpuLDA; cpu_actions_arr[0xAA] = cpuTAX; cpu_actions_arr[0xAB] = cpuAXT; 
 	cpu_actions_arr[0xAC] = cpuLDY; cpu_actions_arr[0xAD] = cpuLDA; cpu_actions_arr[0xAE] = cpuLDX; cpu_actions_arr[0xAF] = cpuLAX;
 
-	cpu_actions_arr[0xB0] = NULL; cpu_actions_arr[0xB1] = cpuLDA; cpu_actions_arr[0xB2] = cpuKIL; cpu_actions_arr[0xB3] = cpuLAX;
+	cpu_actions_arr[0xB0] = cpuNoAction; cpu_actions_arr[0xB1] = cpuLDA; cpu_actions_arr[0xB2] = cpuKIL; cpu_actions_arr[0xB3] = cpuLAX;
 	cpu_actions_arr[0xB4] = cpuLDY; cpu_actions_arr[0xB5] = cpuLDA; cpu_actions_arr[0xB6] = cpuLDX; cpu_actions_arr[0xB7] = cpuLAX;
 	cpu_actions_arr[0xB8] = cpuCLV; cpu_actions_arr[0xB9] = cpuLDA; cpu_actions_arr[0xBA] = cpuTSX; cpu_actions_arr[0xBB] = cpuLAR; 
 	cpu_actions_arr[0xBC] = cpuLDY; cpu_actions_arr[0xBD] = cpuLDA; cpu_actions_arr[0xBE] = cpuLDX; cpu_actions_arr[0xBF] = cpuLAX;
 
-	cpu_actions_arr[0xC0] = cpuCMPy; cpu_actions_arr[0xC1] = cpuCMPa; cpu_actions_arr[0xC2] = NULL; cpu_actions_arr[0xC3] = cpuDCP;
+	cpu_actions_arr[0xC0] = cpuCMPy; cpu_actions_arr[0xC1] = cpuCMPa; cpu_actions_arr[0xC2] = cpuNoAction; cpu_actions_arr[0xC3] = cpuDCP;
 	cpu_actions_arr[0xC4] = cpuCMPy; cpu_actions_arr[0xC5] = cpuCMPa; cpu_actions_arr[0xC6] = cpuDECt; cpu_actions_arr[0xC7] = cpuDCP;
 	cpu_actions_arr[0xC8] = cpuINY; cpu_actions_arr[0xC9] = cpuCMPa; cpu_actions_arr[0xCA] = cpuDEX; cpu_actions_arr[0xCB] = cpuCMPax; 
 	cpu_actions_arr[0xCC] = cpuCMPy; cpu_actions_arr[0xCD] = cpuCMPa; cpu_actions_arr[0xCE] = cpuDECt; cpu_actions_arr[0xCF] = cpuDCP;
 
-	cpu_actions_arr[0xD0] = NULL; cpu_actions_arr[0xD1] = cpuCMPa; cpu_actions_arr[0xD2] = cpuKIL; cpu_actions_arr[0xD3] = cpuDCP;
-	cpu_actions_arr[0xD4] = NULL; cpu_actions_arr[0xD5] = cpuCMPa; cpu_actions_arr[0xD6] = cpuDECt; cpu_actions_arr[0xD7] = cpuDCP;
-	cpu_actions_arr[0xD8] = cpuCLD; cpu_actions_arr[0xD9] = cpuCMPa; cpu_actions_arr[0xDA] = NULL; cpu_actions_arr[0xDB] = cpuDCP; 
-	cpu_actions_arr[0xDC] = NULL; cpu_actions_arr[0xDD] = cpuCMPa; cpu_actions_arr[0xDE] = cpuDECt; cpu_actions_arr[0xDF] = cpuDCP;
+	cpu_actions_arr[0xD0] = cpuNoAction; cpu_actions_arr[0xD1] = cpuCMPa; cpu_actions_arr[0xD2] = cpuKIL; cpu_actions_arr[0xD3] = cpuDCP;
+	cpu_actions_arr[0xD4] = cpuNoAction; cpu_actions_arr[0xD5] = cpuCMPa; cpu_actions_arr[0xD6] = cpuDECt; cpu_actions_arr[0xD7] = cpuDCP;
+	cpu_actions_arr[0xD8] = cpuCLD; cpu_actions_arr[0xD9] = cpuCMPa; cpu_actions_arr[0xDA] = cpuNoAction; cpu_actions_arr[0xDB] = cpuDCP; 
+	cpu_actions_arr[0xDC] = cpuNoAction; cpu_actions_arr[0xDD] = cpuCMPa; cpu_actions_arr[0xDE] = cpuDECt; cpu_actions_arr[0xDF] = cpuDCP;
 
-	cpu_actions_arr[0xE0] = cpuCMPx; cpu_actions_arr[0xE1] = cpuSBC; cpu_actions_arr[0xE2] = NULL; cpu_actions_arr[0xE3] = cpuISC;
+	cpu_actions_arr[0xE0] = cpuCMPx; cpu_actions_arr[0xE1] = cpuSBC; cpu_actions_arr[0xE2] = cpuNoAction; cpu_actions_arr[0xE3] = cpuISC;
 	cpu_actions_arr[0xE4] = cpuCMPx; cpu_actions_arr[0xE5] = cpuSBC; cpu_actions_arr[0xE6] = cpuINCt; cpu_actions_arr[0xE7] = cpuISC;
-	cpu_actions_arr[0xE8] = cpuINX; cpu_actions_arr[0xE9] = cpuSBC; cpu_actions_arr[0xEA] = NULL; cpu_actions_arr[0xEB] = cpuSBC; 
+	cpu_actions_arr[0xE8] = cpuINX; cpu_actions_arr[0xE9] = cpuSBC; cpu_actions_arr[0xEA] = cpuNoAction; cpu_actions_arr[0xEB] = cpuSBC; 
 	cpu_actions_arr[0xEC] = cpuCMPx; cpu_actions_arr[0xED] = cpuSBC; cpu_actions_arr[0xEE] = cpuINCt; cpu_actions_arr[0xEF] = cpuISC;
 
-	cpu_actions_arr[0xF0] = NULL; cpu_actions_arr[0xF1] = cpuSBC; cpu_actions_arr[0xF2] = cpuKIL; cpu_actions_arr[0xF3] = cpuISC;
-	cpu_actions_arr[0xF4] = NULL; cpu_actions_arr[0xF5] = cpuSBC; cpu_actions_arr[0xF6] = cpuINCt; cpu_actions_arr[0xF7] = cpuISC;
-	cpu_actions_arr[0xF8] = cpuSED; cpu_actions_arr[0xF9] = cpuSBC; cpu_actions_arr[0xFA] = NULL; cpu_actions_arr[0xFB] = cpuISC; 
-	cpu_actions_arr[0xFC] = NULL; cpu_actions_arr[0xFD] = cpuSBC; cpu_actions_arr[0xFE] = cpuINCt; cpu_actions_arr[0xFF] = cpuISC;
+	cpu_actions_arr[0xF0] = cpuNoAction; cpu_actions_arr[0xF1] = cpuSBC; cpu_actions_arr[0xF2] = cpuKIL; cpu_actions_arr[0xF3] = cpuISC;
+	cpu_actions_arr[0xF4] = cpuNoAction; cpu_actions_arr[0xF5] = cpuSBC; cpu_actions_arr[0xF6] = cpuINCt; cpu_actions_arr[0xF7] = cpuISC;
+	cpu_actions_arr[0xF8] = cpuSED; cpu_actions_arr[0xF9] = cpuSBC; cpu_actions_arr[0xFA] = cpuNoAction; cpu_actions_arr[0xFB] = cpuISC; 
+	cpu_actions_arr[0xFC] = cpuNoAction; cpu_actions_arr[0xFD] = cpuSBC; cpu_actions_arr[0xFE] = cpuINCt; cpu_actions_arr[0xFF] = cpuISC;
+
+	cpu_action_func = cpuNoAction;
 }
 
 /* Do all IRQ related updates */
@@ -724,7 +729,7 @@ static bool cpuHandleIrqUpdates()
 	{
 		cpu_action_arr = cpu_reset_arr;
 		cpu_arr_pos = 0;
-		cpu_action_func = NULL;
+		cpu_action_func = cpuNoAction;
 		reset = false;
 		return true;
 	}
@@ -732,7 +737,7 @@ static bool cpuHandleIrqUpdates()
 	{
 		cpu_action_arr = cpu_nmi_arr;
 		cpu_arr_pos = 0;
-		cpu_action_func = NULL;
+		cpu_action_func = cpuNoAction;
 		#if DEBUG_INTR
 		printf("NMI from p %02x pc %04x\n",p,pc);
 		#endif
@@ -743,7 +748,7 @@ static bool cpuHandleIrqUpdates()
 	{
 		cpu_action_arr = cpu_irq_arr;
 		cpu_arr_pos = 0;
-		cpu_action_func = NULL;
+		cpu_action_func = cpuNoAction;
 		#if DEBUG_INTR
 		printf("INTR %d %d %d from p %02x pc %04x\n",interrupt,dmc_interrupt,apu_interrupt,p,pc);
 		#endif
@@ -851,8 +856,7 @@ bool cpuCycle()
 			pc++;
 			break;
 		case CPU_ACTION:
-			if(cpu_action_func)
-				cpu_action_func();
+			cpu_action_func();
 			break;
 		case CPU_NULL_READ8_PC:
 			memGet8(pc);
@@ -870,16 +874,14 @@ bool cpuCycle()
 			break;
 		case CPU_NULL_READ8_PC_ACTION:
 			memGet8(pc);
-			if(cpu_action_func)
-				cpu_action_func();
+			cpu_action_func();
 			break;
 		case CPU_TMP_READ8_PC_INC:
 			cpuTmp = memGet8(pc++);
 			break;
 		case CPU_TMP_READ8_PC_INC_ACTION:
 			cpuTmp = memGet8(pc++);
-			if(cpu_action_func)
-				cpu_action_func();
+			cpu_action_func();
 			break;
 		case CPU_ADDR_READ8_PC_INC:
 			absAddr = memGet8(pc++);
@@ -940,15 +942,13 @@ bool cpuCycle()
 			break;
 		case CPU_ADDR_READ8_ACTION:
 			cpuTmp = memGet8(absAddr);
-			if(cpu_action_func)
-				cpu_action_func();
+			cpu_action_func();
 			break;
 		case CPU_ADDR_READ8_ACTION_CHK:
 			cpuTmp = memGet8(absAddr);
 			if(!cpuDoAddrIndFix())
 			{
-				if(cpu_action_func)
-					cpu_action_func();
+				cpu_action_func();
 				//only execute extra cycle
 				//if fixup is needed
 				cpu_arr_pos++;
@@ -1017,8 +1017,7 @@ bool cpuCycle()
 		case CPU_ADDR_WRITE8_ACTION:
 			memSet8(absAddr, cpuTmp);
 			cpuWriteTMP = true;
-			if(cpu_action_func)
-				cpu_action_func();
+			cpu_action_func();
 			break;
 		case CPU_CHECK_BCC:
 			takeBranch = !(p & P_FLAG_CARRY);
diff --git a/fm2play.c b/fm2play.c
index bbdd130..67a15f7 100644
--- a/fm2play.c
+++ b/fm2play.c
@@ -7,6 +7,7 @@
 
 #include <stdint.h>
 #include <stdbool.h>
+#include <string.h>
 #include <stdio.h>
 #include <malloc.h>
 #include "fm2play.h"
diff --git a/input.c b/input.c
index c38a978..8691b12 100644
--- a/input.c
+++ b/input.c
@@ -8,6 +8,7 @@
 #include <stdio.h>
 #include <stdbool.h>
 #include <inttypes.h>
+#include <string.h>
 #include "input.h"
 
 //used externally by main.c
diff --git a/main.c b/main.c
index 94ea6f4..31d89ba 100644
--- a/main.c
+++ b/main.c
@@ -8,6 +8,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdbool.h>
+#include <string.h>
 #include <malloc.h>
 #include <inttypes.h>
 #include <GL/glut.h>
@@ -30,7 +31,7 @@
 #define DEBUG_KEY 0
 #define DEBUG_LOAD_INFO 1
 
-static const char *VERSION_STRING = "fixNES Alpha v0.8.2";
+static const char *VERSION_STRING = "fixNES Alpha v0.8.3";
 
 static void nesEmuDisplayFrame(void);
 static void nesEmuMainLoop(void);
@@ -47,7 +48,7 @@ static char *emuSaveName = NULL;
 static uint8_t *emuPrgRAM = NULL;
 static uint32_t emuPrgRAMsize = 0;
 //used externally
-uint8_t *textureImage = NULL;
+uint32_t textureImage[0xF000];
 bool nesPause = false;
 bool ppuDebugPauseFrame = false;
 bool doOverscan = true;
@@ -295,12 +296,7 @@ int main(int argc, char** argv)
 	emuMainFrameStart = GetTickCount();
 	#endif
 	#endif
-	textureImage = malloc(visibleImg);
 	memset(textureImage,0,visibleImg);
-	//make sure image is visible
-	uint32_t i;
-	for(i = 0; i < visibleImg; i+=4)
-		textureImage[i+3] = 0xFF;
 	cpuCycleTimer = nesPAL ? 16 : 12;
 	//do one scanline per idle loop
 	ppuCycleTimer = nesPAL ? 5 : 4;
@@ -376,9 +372,6 @@ static void nesEmuDeinit(void)
 		free(emuPrgRAM);
 	}
 	emuPrgRAM = NULL;
-	if(textureImage != NULL)
-		free(textureImage);
-	textureImage = NULL;
 	//printf("Bye!\n");
 }
 
@@ -809,8 +802,7 @@ static void nesEmuDisplayFrame()
 			emuRenderFrame = false;
 			return;
 		}
-		if(textureImage != NULL)
-			glTexImage2D(GL_TEXTURE_2D, 0, 4, VISIBLE_DOTS, VISIBLE_LINES, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, textureImage);
+		glTexImage2D(GL_TEXTURE_2D, 0, 4, VISIBLE_DOTS, VISIBLE_LINES, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, textureImage);
 		emuRenderFrame = false;
 	}
 
diff --git a/mapper/fds.c b/mapper/fds.c
index a320242..df59930 100644
--- a/mapper/fds.c
+++ b/mapper/fds.c
@@ -8,6 +8,7 @@
 #include <stdio.h>
 #include <stdbool.h>
 #include <inttypes.h>
+#include <string.h>
 #include "../ppu.h"
 #include "../cpu.h"
 #include "../input.h"
diff --git a/mapper/m1.c b/mapper/m1.c
index 0173f9d..96fba42 100644
--- a/mapper/m1.c
+++ b/mapper/m1.c
@@ -7,6 +7,7 @@
 
 #include <stdio.h>
 #include <inttypes.h>
+#include <string.h>
 #include <stdbool.h>
 #include "../ppu.h"
 
diff --git a/mapper/m13.c b/mapper/m13.c
index 5a00b21..16c5b76 100644
--- a/mapper/m13.c
+++ b/mapper/m13.c
@@ -7,6 +7,7 @@
 
 #include <stdio.h>
 #include <inttypes.h>
+#include <string.h>
 
 static uint8_t *m13_prgROM;
 static uint32_t m13_prgROMsize;
diff --git a/mapper/m15.c b/mapper/m15.c
index 12be4e2..92c5928 100644
--- a/mapper/m15.c
+++ b/mapper/m15.c
@@ -8,6 +8,7 @@
 #include <stdio.h>
 #include <stdbool.h>
 #include <inttypes.h>
+#include <string.h>
 #include "../ppu.h"
 
 static uint8_t *m15_prgROM;
diff --git a/mapper/m4.c b/mapper/m4.c
index 4e660fe..fea0cfb 100644
--- a/mapper/m4.c
+++ b/mapper/m4.c
@@ -8,6 +8,7 @@
 #include <stdio.h>
 #include <inttypes.h>
 #include <stdbool.h>
+#include <string.h>
 #include "../ppu.h"
 
 static uint8_t *m4_prgROM;
diff --git a/mapper/m48.c b/mapper/m48.c
index 5801700..1dee3ca 100644
--- a/mapper/m48.c
+++ b/mapper/m48.c
@@ -8,6 +8,7 @@
 #include <stdio.h>
 #include <inttypes.h>
 #include <stdbool.h>
+#include <string.h>
 #include "../ppu.h"
 
 static uint8_t *m48_prgROM;
diff --git a/mapper/m7.c b/mapper/m7.c
index b25c112..b02cc2b 100644
--- a/mapper/m7.c
+++ b/mapper/m7.c
@@ -8,6 +8,7 @@
 #include <stdio.h>
 #include <stdbool.h>
 #include <inttypes.h>
+#include <string.h>
 #include "../ppu.h"
 
 static uint8_t *m7_prgROM;
diff --git a/mapper/nsf.c b/mapper/nsf.c
index 9b4687f..a52edb4 100644
--- a/mapper/nsf.c
+++ b/mapper/nsf.c
@@ -8,6 +8,7 @@
 #include <stdio.h>
 #include <stdbool.h>
 #include <inttypes.h>
+#include <string.h>
 #include "../ppu.h"
 #include "../cpu.h"
 #include "../input.h"
diff --git a/mapper/p16c4.c b/mapper/p16c4.c
index 72fa719..cfd2424 100644
--- a/mapper/p16c4.c
+++ b/mapper/p16c4.c
@@ -8,6 +8,7 @@
 #include <stdio.h>
 #include <stdbool.h>
 #include <inttypes.h>
+#include <string.h>
 #include "../ppu.h"
 
 static uint8_t *p16c4_prgROM;
diff --git a/mapper/p16c8.c b/mapper/p16c8.c
index 6c33378..1a98a52 100644
--- a/mapper/p16c8.c
+++ b/mapper/p16c8.c
@@ -8,6 +8,7 @@
 #include <stdio.h>
 #include <stdbool.h>
 #include <inttypes.h>
+#include <string.h>
 #include "../ppu.h"
 
 static uint8_t *p16c8_prgROM;
diff --git a/mapper/p32c4.c b/mapper/p32c4.c
index ddfadc1..4d34a6c 100644
--- a/mapper/p32c4.c
+++ b/mapper/p32c4.c
@@ -8,6 +8,7 @@
 #include <stdio.h>
 #include <stdbool.h>
 #include <inttypes.h>
+#include <string.h>
 #include "../ppu.h"
 
 static uint8_t *p32c4_prgROM;
diff --git a/mapper/p32c8.c b/mapper/p32c8.c
index 334f818..076380c 100644
--- a/mapper/p32c8.c
+++ b/mapper/p32c8.c
@@ -8,6 +8,7 @@
 #include <stdio.h>
 #include <stdbool.h>
 #include <inttypes.h>
+#include <string.h>
 #include "../ppu.h"
 
 static uint8_t *p32c8_prgROM;
diff --git a/mapper/vrc2_4.c b/mapper/vrc2_4.c
index 1687dd4..d2c407f 100644
--- a/mapper/vrc2_4.c
+++ b/mapper/vrc2_4.c
@@ -8,6 +8,7 @@
 #include <stdio.h>
 #include <stdbool.h>
 #include <inttypes.h>
+#include <string.h>
 #include "../ppu.h"
 #include "../vrc_irq.h"
 
diff --git a/mapper/vrc6.c b/mapper/vrc6.c
index 5cec98d..95891ed 100644
--- a/mapper/vrc6.c
+++ b/mapper/vrc6.c
@@ -8,6 +8,7 @@
 #include <stdio.h>
 #include <stdbool.h>
 #include <inttypes.h>
+#include <string.h>
 #include "../ppu.h"
 #include "../audio_vrc6.h"
 #include "../vrc_irq.h"
diff --git a/mapper/vrc7.c b/mapper/vrc7.c
index 74e4de0..c390d69 100644
--- a/mapper/vrc7.c
+++ b/mapper/vrc7.c
@@ -8,6 +8,7 @@
 #include <stdio.h>
 #include <stdbool.h>
 #include <inttypes.h>
+#include <string.h>
 #include "../ppu.h"
 #include "../audio_vrc7.h"
 #include "../vrc_irq.h"
diff --git a/mem.c b/mem.c
index c1d6ad0..af6fa63 100644
--- a/mem.c
+++ b/mem.c
@@ -8,6 +8,7 @@
 #include <stdio.h>
 #include <stdbool.h>
 #include <inttypes.h>
+#include <string.h>
 #include "mapper.h"
 #include "ppu.h"
 #include "cpu.h"
diff --git a/ppu.c b/ppu.c
index 945da71..a26d87a 100644
--- a/ppu.c
+++ b/ppu.c
@@ -8,6 +8,7 @@
 #include <stdio.h>
 #include <stdbool.h>
 #include <inttypes.h>
+#include <string.h>
 #include "mapper.h"
 #include "ppu.h"
 
@@ -51,7 +52,7 @@
 bool ppu4Screen = false;
 
 //from main.c
-extern uint8_t *textureImage;
+extern uint32_t textureImage[0xF000];
 extern bool nesPause;
 extern bool ppuDebugPauseFrame;
 extern bool doOverscan;
@@ -79,6 +80,7 @@ static uint8_t PPU_OAM[0x100];
 static uint8_t PPU_OAM2[0x20];
 
 static uint8_t PPU_PALRAM[0x20];
+static uint32_t PPU_BGRLUT[0x200];
 //internally processed, ready to draw
 static uint8_t PPU_Sprites[0x20];
 
@@ -158,6 +160,36 @@ void ppuInit()
 	ppuCurNMIStat = false;
 	ppuOddFrame = false;
 	ppuReadReg2 = false;
+	//generate full BGR LUT
+	uint8_t rtint = nesPAL ? (1<<6) : (1<<5);
+	uint8_t gtint = nesPAL ? (1<<5) : (1<<6);
+	uint8_t btint = (1<<7);
+	int32_t i;
+	for(i = 0; i < 0x200; i++)
+	{
+		uint8_t palpos = (i&0x3F)*3;
+		uint8_t r = PPU_Pal[palpos];
+		uint8_t g = PPU_Pal[palpos+1];
+		uint8_t b = PPU_Pal[palpos+2];
+		if((i & 0xF) <= 0xD)
+		{
+			//reduce red
+			if((i>>1) & btint) r = (uint8_t)(((float)r)*0.75f);
+			if((i>>1) & gtint) r = (uint8_t)(((float)r)*0.75f);
+			//reduce green
+			if((i>>1) & rtint) g = (uint8_t)(((float)g)*0.75f);
+			if((i>>1) & btint) g = (uint8_t)(((float)g)*0.75f);
+			//reduce blue
+			if((i>>1) & rtint) b = (uint8_t)(((float)b)*0.75f);
+			if((i>>1) & gtint) b = (uint8_t)(((float)b)*0.75f);
+		}
+		//save new color into LUT
+		PPU_BGRLUT[i] = 
+			(b) //Blue
+			| (g<<8) //Green
+			| (r<<16) //Red
+			| (0xFF<<24); //Alpha
+	}
 }
 
 static inline uint16_t ppuGetVramTbl(uint16_t tblStart)
@@ -318,20 +350,20 @@ bool ppuCycle()
 		if((!(PPU_Reg[1] & PPU_BG_8PX) || !(PPU_Reg[1] & PPU_SPRITE_8PX)) && (curDot < 8 || curDot > 248))
 			curCol = 0xFF;
 		/* Draw current dot on screen */
-		size_t drawPos = (curDot<<2)+(curLine<<10);
+		size_t drawPos = (curDot)+(curLine<<8);
 		if(curCol != 0xFF)
 		{
-			uint8_t cPalIdx = (PPU_PALRAM[curCol]&((PPU_Reg[1]&PPU_GRAY)?0x30:0x3F))*3;
-			textureImage[drawPos] = PPU_Pal[cPalIdx+2];
-			textureImage[drawPos+1] = PPU_Pal[cPalIdx+1];
-			textureImage[drawPos+2] = PPU_Pal[cPalIdx];
+			uint16_t cPalIdx;
+			if(pictureOutput) //use color from bg or sprite input
+				cPalIdx = (PPU_PALRAM[curCol&0x1F]&((PPU_Reg[1]&PPU_GRAY)?0x30:0x3F))|((PPU_Reg[1]&0xE0)<<1);
+			else if(ppuVramAddr >= 0x3F00 && ppuVramAddr < 0x4000) //bg and sprite disabled but address within PALRAM
+				cPalIdx = (PPU_PALRAM[ppuVramAddr&0x1F]&((PPU_Reg[1]&PPU_GRAY)?0x30:0x3F))|((PPU_Reg[1]&0xE0)<<1);
+			else //bg and sprite disabled and address not within PALRAM
+				cPalIdx = PPU_PALRAM[0];
+			textureImage[drawPos] = PPU_BGRLUT[cPalIdx];
 		}
 		else /* Draw clipped area as black */
-		{
-			textureImage[drawPos] = 0;
-			textureImage[drawPos+1] = 0;
-			textureImage[drawPos+2] = 0;
-		}
+			textureImage[drawPos] = 0xFF000000;
 	}
 
 	/* set to 0 during not visible dots up to post-render line */