diff --git a/software/interprocess/interprocess.h b/software/interprocess/interprocess.h
index c3b055bed8dc001cca63857e04e62f1adbc7c193..ec26723afaba11ef1018f0f4b4fb137ac9778f06 100644
--- a/software/interprocess/interprocess.h
+++ b/software/interprocess/interprocess.h
@@ -9,7 +9,6 @@
 
 #define ISD_BASE INTERPROC_SHARED_DATA_BASE
 
-
 // Mouse: R
 #define MOUSE_XY	0		// - 3
 #define MOUSE_W		4		// - 5
@@ -21,9 +20,9 @@
 #define mouse_btn IORD_8DIRECT(ISD_BASE, MOUSE_BTN)
 
 // For usb
-#define set_mouse_xy(val) IORD_32DIRECT(ISD_BASE, MOUSE_XY, val)
-#define set_mouse_wheel(val) IORD_16DIRECT(ISD_BASE, MOUSE_W, val)
-#define set_mouse_btn(val) IORD_8DIRECT(ISD_BASE, MOUSE_BTN, btn)
+#define set_mouse_xy(val) IOWR_32DIRECT(ISD_BASE, MOUSE_XY, val)
+#define set_mouse_wheel(val) IOWR_16DIRECT(ISD_BASE, MOUSE_W, val)
+#define set_mouse_btn(val) IOWR_8DIRECT(ISD_BASE, MOUSE_BTN, btn)
 
 // Background: W
 // Trig: ADDR
@@ -63,6 +62,7 @@ inline void mpeg_cancel_audio() {
 #define mpeg_audio_len IORD_32DIRECT(ISD_BASE, MPEG_AUDIO_LEN)
 #define mpeg_audio_start IORD_32DIRECT(ISD_BASE, MPEG_AUDIO_START)
 #define mpeg_audio_reset(val) IOWR_32DIRECT(ISD_BASE, MPEG_AUDIO_ADDR, val)
+#define mpeg_audio_len_change(val) IOWR_32DIRECT(ISD_BASE, MPEG_AUDIO_LEN, val)
 
 // Audio Mixdown: W
 // Trig: ADDR
@@ -87,23 +87,21 @@ inline void mpeg_play_fx(uint32_t addr, uint32_t len) {
 // Ready: ADDR
 #define MPEG_READ_ADDR		36	// - 39
 #define MPEG_READ_LEN		40	// - 43
-#define MPEG_READ_PTR1		44	// - 47
-#define MPEG_READ_PTR2		48	// - 51
+#define MPEG_READ_PTR		44	// - 47
 
 // For main
 inline void mpeg_read(uint32_t addr, uint32_t len, void *buf) {
-	uint64_t ptr = (uint64_t) buf;
+	uint32_t ptr = (uint32_t) buf;
 	while(IORD_32DIRECT(ISD_BASE, MPEG_READ_ADDR));
 	IOWR_32DIRECT(ISD_BASE, MPEG_READ_LEN, len);
-	IOWR_32DIRECT(ISD_BASE, MPEG_READ_PTR1, ptr&0xffff);
-	IOWR_32DIRECT(ISD_BASE, MPEG_READ_PTR2, (ptr&0xffff0000)>>32);
+	IOWR_32DIRECT(ISD_BASE, MPEG_READ_PTR, ptr);
 	IOWR_32DIRECT(ISD_BASE, MPEG_READ_ADDR, addr);
 }
 
 // For mpeg
 #define mpeg_read_addr IORD_32DIRECT(ISD_BASE, MPEG_READ_ADDR)
 #define mpeg_read_len IORD_32DIRECT(ISD_BASE, MPEG_READ_LEN)
-#define mpeg_read_ptr (void *)((IORD_32DIRECT(ISD_BASE, MPEG_READ_PTR2)<<32)|IORD_32DIRECT(ISD_BASE, MPEG_READ_PTR1))
+#define mpeg_read_ptr (void *)(IORD_32DIRECT(ISD_BASE, MPEG_READ_PTR))
 #define mpeg_read_reset(val) IOWR_32DIRECT(ISD_BASE, MPEG_READ_ADDR, val)
 
 // Sprite: W
@@ -124,11 +122,24 @@ inline void mpeg_read(uint32_t addr, uint16_t w, uint16_t h, uint32_t dest) {
 }
 
 // For mpeg
-#define mpeg_read_addr IORD_32DIRECT(ISD_BASE, MPEG_IMG_ADDR)
-#define mpeg_read_width IORD_32DIRECT(ISD_BASE, MPEG_IMG_WIDTH)
-#define mpeg_read_height IORD_32DIRECT(ISD_BASE, MPEG_IMG_HEIGHT)
-#define mpeg_read_dest ((IORD_32DIRECT(ISD_BASE, MPEG_IMG_DEST2)<<32)|IORD_32DIRECT(ISD_BASE, MPEG_IMG_DEST1))
-#define mpeg_read_reset(val) IOWR_32DIRECT(ISD_BASE, MPEG_IMG_ADDR, val)
+#define mpeg_img_addr IORD_32DIRECT(ISD_BASE, MPEG_IMG_ADDR)
+#define mpeg_img_width IORD_16DIRECT(ISD_BASE, MPEG_IMG_WIDTH)
+#define mpeg_img_height IORD_16DIRECT(ISD_BASE, MPEG_IMG_HEIGHT)
+#define mpeg_img_dest IORD_32DIRECT(ISD_BASE, MPEG_IMG_DEST)
+#define mpeg_img_reset(val) IOWR_32DIRECT(ISD_BASE, MPEG_IMG_ADDR, val)
+
+
+#define AUDIO_BUFFER1	3072		// - 3
+#define AUDIO_BUFFER2	3584	// - 5
+
+// For read audio buffer
+#define rd_audio_buffer1(val1) IORD_32DIRECT(ISD_BASE, AUDIO_BUFFER1+(val1<<2))
+#define rd_audio_buffer2(val1) IORD_32DIRECT(ISD_BASE, AUDIO_BUFFER2+(val1<<2))
+// For write audio buffer
+#define wr_audio_buffer1(val1,val2) IOWR_32DIRECT(ISD_BASE, AUDIO_BUFFER1+(val1<<2),val2)
+#define wr_audio_buffer2(val1,val2) IOWR_32DIRECT(ISD_BASE, AUDIO_BUFFER2+(val1<<2),val2)
 
+#define rd_audio_buffer1_8(val1) IORD_8DIRECT(ISD_BASE, AUDIO_BUFFER1+val1)
+#define rd_audio_buffer1_16(val1) IORD_8DIRECT(ISD_BASE, AUDIO_BUFFER1+val1<<1)
 
 #endif
diff --git a/software/osu_sd_core/main.c b/software/osu_sd_core/main.c
index ef1335e0ac842938e9fcc0db93444b19492f1947..8d7c1e0e2ebf1f0b38c85e8530223fa71d1ce8a6 100644
--- a/software/osu_sd_core/main.c
+++ b/software/osu_sd_core/main.c
@@ -7,6 +7,7 @@
 #include "terasic_sdcard/sd_lib.h"
 #include "../interprocess/interprocess.h"
 #include "system.h"
+#include "../osu_main/src/gl/gl.h"
 
 #define audioData ((uint32_t*)AUDIO_0_BASE)
 #define audioReady ((uint32_t*)(AUDIO_0_BASE+0x100))
@@ -19,63 +20,135 @@ int main() {
 	*audioVol = 0x77;
 	*VolReset = 1;
 	uint32_t i;
-	uint8_t j;
-	uint32_t temp_start,temp_len;
+	uint8_t j,c1,c2;
+	uint16_t img_buf;
+	uint16_t* temp_dest;
     SDLIB_Init();
     char bg_buf[516];
     uint32_t *buf = ALIGN_32(&bg_buf);
+    /*
     char o_meta_buf[516];
 	uint32_t *audio_buf1 = ALIGN_32(&o_meta_buf);
 	char o_song_buf[516];
-	uint32_t *audio_buf2 = ALIGN_32(&o_song_buf);
+	uint32_t *audio_buf2 = ALIGN_32(&o_song_buf);*/
+	int bptr = 512;
+	uint32_t bg_ptr; 
 
 	//giant probe sequence
 	SDLIB_ReadBlock512(o_song->cover_begin,buf);
 	PROBE:
 	while (1){
     	if (mpeg_bg){
-    		SDLIB_ReadBlock512(mpeg_bg,buf);
+    		bg_ptr = mpeg_bg;
+    		SDLIB_ReadBlock512(bg_ptr,buf);
     		if (strncasecmp(buf, "PLT", 3)!=0) {
 				printf("Invalid palette magic: %c%c%c\n", buf[0], buf[1], buf[2]);
 			}
-			for (int i=0; i<128; i++) {
-				uint32_t c = (buf[i*3+3]<<16) | (buf[i*3+4]<<8) | buf[i*3+5];
-				GL_PLWR(i+128, c);
-				GL_PLWR(i, 0);
-			}            
+			for (int x=0; x<128; x++) {
+				uint32_t c = (buf[x*3+3]<<16) | (buf[x*3+4]<<8) | buf[x*3+5];
+				GL_PLWR(x+128, c);
+				GL_PLWR(x, 0);
+			}
+			bptr = 512;
+			for (int y=0; y<480; y++) {
+				for (int x=0; x<640; x+=2) {
+					if (bptr >= 512) {
+						// Fetch next
+						//osu_read_song(++sdptr, buf);
+						SDLIB_ReadBlock512(++bg_ptr,(char*)AUDIO_BUFFER1);
+						bptr = 0;
+					}
+					// c1 = buf[bptr++];
+					// c2 = buf[bptr++];
+					c1 = rd_audio_buffer1_8(bptr++);
+					c2 = rd_audio_buffer1_8(bptr++);
+					GL_SRAMWR(GL_SRAM_BGBASE+gl_make_point_8bit(x,y), (c2<<8)|c1);
+				}
+			}
+			mpeg_bg_reset(0);
   			continue;
   		}
-  		if (){}
+  		if (mpeg_img_addr){
+  			goto IMG;
+  		}
+  		if (mpeg_read_addr){
+  			goto READ;
+  		}
 		if (mpeg_audio_addr){
 			goto AUDIO;
 		}	
-
+		if (mpeg_fx_addr){
+			goto FX_AUDIO;
+		}
 	}
 	AUDIO:
 	//SDLIB_ReadBlock512(temp_start,audioData);
 	usleep(mpeg_audio_start);
-	for (i=0;i<mpeg_audio_len;++i){
-		while (!(*audioReady));
-		if (mpeg_fx_addr){
-			if (mpeg_fx_len){
-				SDLIB_ReadBlock512(mpeg_audio_addr+i,audio_buf1);
-				SDLIB_ReadBlock512(mpeg_fx_addr,audio_buf2);
-				for (j=0;j<128;++j){
-					IOWR_32DIRECT(audioData+j,0,audio_buf1[j]+audio_buf2[j]);
-				}
-				mpeg_fx_reset(mpeg_fx_addr+1);
-				mpeg_fx_len_change(mpeg_fx_len-1);
-			}else{
-				SDLIB_ReadBlock512(mpeg_audio_addr+i,audioData);
-				mpeg_fx_reset(0);
-			}
-			
+	while(mpeg_audio_len>0){
+		SDLIB_ReadBlock512(mpeg_audio_addr,(char*)AUDIO_BUFFER1);
+		//wr_audio_buffer1(val1,val2)
+		if (mpeg_fx_addr && mpeg_fx_len){
+			SDLIB_ReadBlock512(mpeg_fx_addr,(char*)AUDIO_BUFFER2);
+			mpeg_fx_reset(mpeg_fx_addr+1);
+			mpeg_fx_len_change(mpeg_fx_len-1);
 		}else{
-			SDLIB_ReadBlock512(mpeg_audio_addr+i,audioData);
+			for (j=0;j<128;++j){
+				wr_audio_buffer2(j,0);
+			}
+			mpeg_fx_reset(0);
 		}
+
+		while (!(*audioReady));
+		for (j=0;j<128;++j){
+			IOWR_32DIRECT(audioData+j,0,rd_audio_buffer1(j)+rd_audio_buffer2(j));
+		}
+		mpeg_audio_reset(mpeg_audio_addr+1);
+		mpeg_audio_len_change(mpeg_audio_len-1);
 	}
 	mpeg_audio_reset(0);
 	goto PROBE;
+
+	READ:
+	for (i=0;i<mpeg_read_len;++i){
+		SDLIB_ReadBlock512(mpeg_read_addr,mpeg_read_ptr+i<<9);
+		mpeg_read_reset(mpeg_read_addr+1);
+	}
+	mpeg_read_reset(0);
+	goto PROBE;
+
+	FX_AUDIO:
+	while (mpeg_fx_len>0){
+		SDLIB_ReadBlock512(mpeg_fx_addr,(char*)AUDIO_BUFFER2);
+		while (!(*audioReady));
+		for (j=0;j<128;++j){
+			IOWR_32DIRECT(audioData+j,0,rd_audio_buffer2(j));
+		}
+		mpeg_fx_reset(mpeg_fx_addr+1);
+		mpeg_fx_len_change(mpeg_fx_len-1);
+	}
+	mpeg_fx_reset(0);
+	goto PROBE;
+
+	IMG:
+	temp_dest = mpeg_img_dest;
+	bg_ptr = mpeg_img_addr;
+	bptr = 256;
+	for (int y=0; y<mpeg_img_height; y++) {
+		for (int x=0; x<mpeg_img_width; x++) {
+			if (bptr >= 256) {
+				// Fetch next
+				//osu_read_song(++sdptr, buf);
+				SDLIB_ReadBlock512(bg_ptr++,(char*)AUDIO_BUFFER1);
+				bptr = 0;
+			}
+			// c1 = buf[bptr++];
+			// c2 = buf[bptr++];
+			img_buf = rd_audio_buffer1_16(bptr++);
+			GL_SRAMWR(temp_dest++,img_buf);
+		}
+	}
+	mpeg_img_reset(0);
+	goto PROBE;
 }
 
 
diff --git a/software/osu_sd_core/terasic_sdcard/sd_hal.c b/software/osu_sd_core/terasic_sdcard/sd_hal.c
index 87d94a9288b618024d6f71bffad7d03a0b5b14fc..a8e5d959e1d11c33d4ffc06ec52d74bfe97b37bb 100644
--- a/software/osu_sd_core/terasic_sdcard/sd_hal.c
+++ b/software/osu_sd_core/terasic_sdcard/sd_hal.c
@@ -119,11 +119,19 @@ bool SDHAL_ReadData(alt_u8 szBuf[], int nBufLen){
 
     //while (!(*InterfaceStatus));
     while (!(IORD_32DIRECT(InterfaceStatus,0)));
-    for (i=0;i<128;++i){
-
-        ((uint32_t*)szBuf)[i] = IORD_32DIRECT(SDData+i,0);
+    if (szBuf == AUDIO_BUFFER1){
+        for (i=0;i<128;++i){
+            wr_audio_buffer1(i,IORD_32DIRECT(SDData+i,0));
+        }
+    }else if (szBuf == AUDIO_BUFFER2){
+        for (i=0;i<128;++i){
+            wr_audio_buffer2(i,IORD_32DIRECT(SDData+i,0));
+        }
+    }else{
+        for (i=0;i<128;++i){
+            ((uint32_t*)szBuf)[i] = IORD_32DIRECT(SDData+i,0);
+        }
     }
-
     //*InterfaceCmd = 5;
     IOWR_32DIRECT(InterfaceCmd,0,5);
     //*InterfaceCmd = 4;