Browse Source

wram analysis

David Voswinkel 15 years ago
parent
commit
396729e2e2

+ 70 - 0
snes/wram/Makefile

@@ -0,0 +1,70 @@
+# SDK Config
+
+
+PLATFORM=$(shell uname)
+
+ifeq ($(PLATFORM),Linux)
+    # Linux Wine 
+    SDK=/home/david/.wine/drive_c/65xx_FreeSDK
+    WINE=wine
+    EMU=../../tools/bsnes/bsnes
+    DISASM=/home/david/Devel/arch/snes/devkit/bin/disasm
+    UCON=ucon64
+else
+    # Mac Wine 
+    SDK=/Users/david/.wine/drive_c/65xx_FreeSDK
+    WINE=wine
+    EMU=zsnes
+    DISASM=/Users/david/Devel/arch/snes/devkit/bin/disasm
+    UCON=ucon64
+endif
+
+CC=$(WINE) $(SDK)/bin/WDC816CC.exe
+AS=$(WINE) $(SDK)/bin/WDC816AS.exe
+LD=$(WINE) $(SDK)/bin/WDCLN.exe
+
+
+# Project
+
+INC=$(SDK)/include
+LIBS=-L$(SDK)/lib/cl 
+#-L$(SDK)/lib/c134
+
+
+OBJS=StartupSnes.obj main.obj pad.obj PPU.obj debug.obj ressource.obj
+APP=wram.smc
+GFX=debugfont
+
+all:  $(APP) repair
+
+run:
+	$(EMU) $(APP)
+
+
+disasm: $(APP)
+	rm -rf  $(APP)
+	$(DISASM) $(APP) >  $(APP).asm
+
+repair: $(APP)
+	$(UCON) -snes -chk $(APP) 2>&1 >/dev/null
+	rm -rf *.bak
+
+StartupSnes.obj: StartupSnes.asm
+	$(AS) -V $?
+
+ressource.obj: ressource.asm
+	$(AS) -V $?
+
+%.obj: %.c
+	$(CC)  -wl -wp -sop -ML -I $(INC) $?
+
+$(APP): $(OBJS) 
+	$(LD) -B -HB -M21 -V -T -Pff \
+        -C008000,0000 -U0000,0000 \
+        -Avectors=FFE4,7FE4 \
+        -Aregistration_data=FFB0,7FB0 \
+        -Aressource=18000,8000 \
+        -N $(OBJS) $(LIBS) -O $@
+
+clean:
+	rm -vf $(APP) *.obj *.TMP

+ 90 - 0
snes/wram/PPU.c

@@ -0,0 +1,90 @@
+#include "data.h"
+
+byte tileMapLocation[4];
+word characterLocation[4];
+
+void waitForVBlank(void)
+{
+    byte Status;
+    do {
+        Status = *(byte *) 0x4210;
+    } while (!(Status & 0x80));
+}
+
+void setTileMapLocation(word vramDst, byte screenProp, byte bgNumber)
+{
+    tileMapLocation[bgNumber] = ((vramDst >> 8) & 0xfc) | (screenProp & 0x03);
+    *(byte *) (0x2107 + bgNumber) = tileMapLocation[bgNumber];
+}
+
+void restoreTileMapLocation(byte bgNumber)
+{
+    *(byte *) (0x2107 + bgNumber) = tileMapLocation[bgNumber];
+}
+
+void setCharacterLocation(word vramDst, byte bgNumber)
+{
+    characterLocation[bgNumber] = vramDst;
+    if (bgNumber < 2) {
+        *(byte *) 0x210b =
+            (characterLocation[1] >> 8 & 0xf0) + (characterLocation[0] >> 12);
+    } else {
+        *(byte *) 0x210c =
+            (characterLocation[3] >> 8 & 0xf0) + (characterLocation[2] >> 12);
+    }
+}
+
+void restoreCharacterLocation(byte bgNumber)
+{
+    setCharacterLocation(characterLocation[bgNumber], bgNumber);
+}
+
+void VRAMByteWrite(byte value, word vramDst)
+{
+    *(byte *) 0x2115 = 0x80;
+    *(word *) 0x2116 = vramDst;
+
+    *(byte *) 0x2118 = value;
+}
+
+void VRAMLoad(word src, word vramDst, word size)
+{
+    // set address in VRam for read or write ($2116) + block size transfer ($2115)
+    *(byte *) 0x2115 = 0x80;
+    *(word *) 0x2116 = vramDst;
+
+    *(word *) 0x4300 = 0x1801;  // set DMA control register (1 word inc) 
+    // and destination ($21xx xx -> 0x18)
+    *(word *) 0x4302 = src;     // DMA channel x source address offset 
+    // (low $4302 and high $4303 optimisation)
+    *(byte *) 0x4304 = 0x01;    // DMA channel x source address bank
+    *(word *) 0x4305 = size;    // DMA channel x transfer size 
+    // (low $4305 and high $4306 optimisation)
+
+    // Turn on DMA transfer for this channel
+    waitForVBlank();
+    *(byte *) 0x2100 = 0x80;
+    *(byte *) 0x420b = 0x01;
+    *(byte *) 0x2100 = 0x00;
+}
+
+void CGRAMLoad(word src, byte cgramDst, word size)
+{
+
+    // set address in VRam for read or write + block size
+    *(byte *) 0x2121 = cgramDst;
+
+    *(word *) 0x4300 = 0x2200;  // set DMA control register (1 byte inc) 
+    // and destination ($21xx xx -> 022)
+    *(word *) 0x4302 = src;     // DMA channel x source address offset
+    // (low $4302 and high $4303 optimisation)
+    *(byte *) 0x4304 = 0x01;    // DMA channel x source address bank
+    *(word *) 0x4305 = size;    // DMA channel x transfer size
+    // (low $4305 and high $4306 optimisation)
+
+    // Turn on DMA transfer for this channel
+    waitForVBlank();
+    *(byte *) 0x2100 = 0x80;
+    *(byte *) 0x420b = 0x01;
+    *(byte *) 0x2100 = 0x00;
+}

+ 11 - 0
snes/wram/PPU.h

@@ -0,0 +1,11 @@
+extern byte tileMapLocation[4];
+extern word characterLocation[4];
+
+void waitForVBlank(void);
+void setTileMapLocation(word vramDst, byte screenProp, byte bgNumber);
+void restoreTileMapLocation(byte bgNumber);
+void setCharacterLocation(word vramDst, byte bgNumber);
+void restoreCharacterLocation(byte bgNumber);
+void VRAMByteWrite(byte value, word vramDst);
+void VRAMLoad(word src, word vramDst, word size);
+void CGRAMLoad(word src, byte cgramDst, word size);

+ 240 - 0
snes/wram/StartupSnes.asm

@@ -0,0 +1,240 @@
+; SNES ROM startup code 
+
+;******************************************************************************
+;*** Define a special section in case most of the code is not in bank 0.    ***
+;******************************************************************************
+
+;STACK   EQU   $01ff     ;CHANGE THIS FOR YOUR SYSTEM
+
+;STARTUP SECTION OFFSET $008000
+
+CODE
+
+	XDEF  	START
+START:
+        XREF  	~~main
+  	
+	sei             ; Disabled interrupts
+        clc             ; clear carry to switch to native mode
+        xce             ; Xchange carry & emulation bit. native mode
+        rep     #$18    ; Binary mode (decimal mode off), X/Y 16 bit
+	LONGI	ON
+        ldx     #$1FFF  ; set stack to $1FFF
+        txs
+
+	rep 	#$30
+	longa	on
+	longi	on
+
+	; Init data used for heap 
+	; see heap definition below
+	XREF ~~_heap_top
+	XREF ~~_mem_start
+	stz	~~_heap_top
+	stz	~~_mem_start
+	
+	XREF	~~preInit
+        jsr   	>~~preInit
+
+        sep     #$30    ; X,Y,A are 8 bit numbers
+	LONGA	OFF
+	LONGI	OFF	
+        lda     #$8F    ; screen off, full brightness
+        sta     $2100   ; brightness + screen enable register 
+        stz     $2101   ; Sprite register (size + address in VRAM) 
+        stz     $2102   ; Sprite registers (address of sprite memory [OAM])
+        stz     $2103   ;    ""                       ""
+        stz     $2105   ; Mode 0, = Graphic mode register
+        stz     $2106   ; noplanes, no mosaic, = Mosaic register
+        stz     $2107   ; Plane 0 map VRAM location
+        stz     $2108   ; Plane 1 map VRAM location
+        stz     $2109   ; Plane 2 map VRAM location
+        stz     $210A   ; Plane 3 map VRAM location
+        stz     $210B   ; Plane 0+1 Tile data location
+        stz     $210C   ; Plane 2+3 Tile data location
+        stz     $210D   ; Plane 0 scroll x (first 8 bits)
+        stz     $210D   ; Plane 0 scroll x (last 3 bits) #$0 - #$07ff
+        stz     $210E   ; Plane 0 scroll y (first 8 bits)
+        stz     $210E   ; Plane 0 scroll y (last 3 bits) #$0 - #$07ff
+        stz     $210F   ; Plane 1 scroll x (first 8 bits)
+        stz     $210F   ; Plane 1 scroll x (last 3 bits) #$0 - #$07ff
+        stz     $2110   ; Plane 1 scroll y (first 8 bits)
+        stz     $2110   ; Plane 1 scroll y (last 3 bits) #$0 - #$07ff
+        stz     $2111   ; Plane 2 scroll x (first 8 bits)
+        stz     $2111   ; Plane 2 scroll x (last 3 bits) #$0 - #$07ff
+        stz     $2112   ; Plane 2 scroll y (first 8 bits)
+        stz     $2112   ; Plane 2 scroll y (last 3 bits) #$0 - #$07ff
+        stz     $2113   ; Plane 3 scroll x (first 8 bits)
+        stz     $2113   ; Plane 3 scroll x (last 3 bits) #$0 - #$07ff
+        stz     $2114   ; Plane 3 scroll y (first 8 bits)
+        stz     $2114   ; Plane 3 scroll y (last 3 bits) #$0 - #$07ff
+        lda     #$80    ; increase VRAM address after writing to $2119
+        sta     $2115   ; VRAM address increment register
+        stz     $2116   ; VRAM address low
+        stz     $2117   ; VRAM address high
+        stz     $211A   ; Initial Mode 7 setting register
+        stz     $211B   ; Mode 7 matrix parameter A register (low)
+        lda     #$01
+        sta     $211B   ; Mode 7 matrix parameter A register (high)
+        stz     $211C   ; Mode 7 matrix parameter B register (low)
+        stz     $211C   ; Mode 7 matrix parameter B register (high)
+        stz     $211D   ; Mode 7 matrix parameter C register (low)
+        stz     $211D   ; Mode 7 matrix parameter C register (high)
+        stz     $211E   ; Mode 7 matrix parameter D register (low)
+        sta     $211E   ; Mode 7 matrix parameter D register (high)
+        stz     $211F   ; Mode 7 center position X register (low)
+        stz     $211F   ; Mode 7 center position X register (high)
+        stz     $2120   ; Mode 7 center position Y register (low)
+        stz     $2120   ; Mode 7 center position Y register (high)
+        stz     $2121   ; Color number register ($0-ff)
+        stz     $2123   ; BG1 & BG2 Window mask setting register
+        stz     $2124   ; BG3 & BG4 Window mask setting register
+        stz     $2125   ; OBJ & Color Window mask setting register
+        stz     $2126   ; Window 1 left position register
+        stz     $2127   ; Window 2 left position register
+        stz     $2128   ; Window 3 left position register
+        stz     $2129   ; Window 4 left position register
+        stz     $212A   ; BG1, BG2, BG3, BG4 Window Logic register
+        stz     $212B   ; OBJ, Color Window Logic Register (or,and,xor,xnor)
+        sta     $212C   ; Main Screen designation (planes, sprites enable)
+        stz     $212D   ; Sub Screen designation
+        stz     $212E   ; Window mask for Main Screen
+        stz     $212F   ; Window mask for Sub Screen
+        lda     #$30
+        sta     $2130   ; Color addition & screen addition init setting
+        stz     $2131   ; Add/Sub sub designation for screen, sprite, color
+        lda     #$E0
+        sta     $2132   ; color data for addition/subtraction
+        stz     $2133   ; Screen setting (interlace x,y/enable SFX data)
+        stz     $4200   ; Enable V-blank, interrupt, Joypad register
+        lda     #$FF
+        sta     $4201   ; Programmable I/O port
+        stz     $4202   ; Multiplicand A
+        stz     $4203   ; Multiplier B
+        stz     $4204   ; Multiplier C
+        stz     $4205   ; Multiplicand C
+        stz     $4206   ; Divisor B
+        stz     $4207   ; Horizontal Count Timer
+        stz     $4208   ; Horizontal Count Timer MSB (most significant bit)
+    stz     $4209   ; Vertical Count Timer
+    stz     $420A   ; Vertical Count Timer MSB
+    stz     $420B   ; General DMA enable (bits 0-7)
+    stz     $420C   ; Horizontal DMA (HDMA) enable (bits 0-7)
+    stz     $420D   ; Access cycle designation (slow/fast rom)
+    cli             ; Enable interrupts
+
+	rep     #$30
+	longa	on
+	longi	on
+
+    jsr   	>~~main
+    brk
+
+	XDEF IRQ
+IRQ:	
+	XREF ~~IRQHandler
+	LONGA	ON
+	LONGI	ON
+	rep	#$30
+	pha
+	phx
+	phy
+	jsr	~~IRQHandler
+	ply
+	plx
+	pla
+	rti
+	
+	XDEF	NMI
+NMI:
+	XREF	~~NMIHandler
+	LONGA	ON
+	LONGI	ON
+	rep	#$30
+	pha
+	phx
+	phy
+	phd
+	phb
+	lda	#$0000
+	sep     #$30    ; X,Y,A are 8 bit numbers
+	LONGA	OFF
+	LONGI	OFF
+	lda     $4210		; Read NMI 
+	LONGA	ON
+	LONGI	ON
+	rep	#$30
+	jsr	~~NMIHandler
+	plb
+	pld
+	ply
+	plx
+	pla
+	rti
+  
+DIRQ:
+	rti
+
+ENDS
+
+;******************************************************************************
+;*** Heap definition                                                        ***
+;******************************************************************************
+
+DATA
+
+	XDEF	~~heap_start
+	XDEF	~~heap_end
+
+~~heap_start:
+	WORD	$1000
+~~heap_end:
+	WORD	$1200
+
+;******************************************************************************
+;*** SNES ROM Registartion Data                                             ***
+;******************************************************************************
+
+REGISTRATION_DATA SECTION
+
+MAKER_CODE          FCC	/FF/
+GAME_CODE		    FCC	/SMWJ/
+FIXED_VALUE0		BYTE	$00, $00, $00, $00, $00, $00, $00
+EXPANSION_RAM_SIZE	BYTE	$00
+SPECIAL_VERSION		BYTE	$00
+CARTRIDGE_TYPE_SUB	BYTE	$00
+GAME_TITLE		    FCC	/GAME TITLE          !/
+				        ;012345678901234567890;
+MAP_MODE            BYTE	$20
+CARTRIDGE_SIZE		BYTE	$00
+ROM_SIZE            BYTE	$09
+RAM_SIZE            BYTE	$00
+DESTINATION_CODE	BYTE	$00
+FIXED_VALUE1		BYTE	$33
+MASK_ROM_VERSION	BYTE	$00
+COMPLEMENT_CHECK	BYTE	$00, $00
+CHEKSUM             BYTE	$00, $00 
+
+;******************************************************************************
+;*** SNES Interrupts and Reset vector                                       ***
+;******************************************************************************
+
+VECTORS	SECTION
+; Native vector
+N_COP   DW   DIRQ
+N_BRK   DW   DIRQ
+N_ABORT DW   DIRQ        
+N_NMI   DW   NMI
+N_RSRVD DW   DIRQ
+N_IRQ   DW   IRQ
+        DS   4
+; Emulation vector
+E_COP   DW   DIRQ
+E_RSRVD DW   DIRQ
+E_ABORT DW   DIRQ
+E_NMI   DW   DIRQ
+E_RESET DW   START
+E_IRQ   DW   DIRQ
+
+END
+

+ 37 - 0
snes/wram/crc.c

@@ -0,0 +1,37 @@
+#include "data.h"
+
+
+word crc_update(char far * data, word size)
+{
+    word i;
+    word j;
+    word crc = 0;
+    for (j = 0; j < size; j++) {
+        crc = crc ^ ((word) data[j] << 8);
+        for (i = 0; i < 8; i++) {
+            if (crc & 0x8000)
+                crc = (crc << 1) ^ 0x1021;
+            else
+                crc <<= 1;
+        }
+    }
+    return crc;
+}
+
+
+word crc_update_mem(unsigned long addr, word size)
+{
+    word i;
+    word j;
+    word crc = 0;
+    for (j = 0; j < size; j++) {
+        crc = crc ^ ((word) * (byte *) (addr + j) << 8);
+        for (i = 0; i < 8; i++) {
+            if (crc & 0x8000)
+                crc = (crc << 1) ^ 0x1021;
+            else
+                crc <<= 1;
+        }
+    }
+    return crc;
+}

+ 3 - 0
snes/wram/crc.h

@@ -0,0 +1,3 @@
+
+word crc_update(byte * data, word size);
+word crc_update_mem(unsigned long, word size);

+ 8 - 0
snes/wram/data.h

@@ -0,0 +1,8 @@
+
+#ifndef _DATA
+
+typedef unsigned char byte;
+typedef unsigned short word;
+
+#define _DATA
+#endif

+ 224 - 0
snes/wram/debug.c

@@ -0,0 +1,224 @@
+#include <string.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <fcntl.h>
+
+#include "debug.h"
+#include "data.h"
+#include "pad.h"
+#include "PPU.h"
+#include "ressource.h"
+
+
+
+#define DEBUG_BUFFER_SIZE 128
+
+word debugMap[0x400];
+char debug_buffer[DEBUG_BUFFER_SIZE];
+char screen_buffer[DEBUG_BUFFER_SIZE];
+
+
+void debug_init(void)
+{
+    word i;
+    for (i = 0; i < 0x400; i++) {
+        debugMap[i] = 0x00;
+    }
+    memset(debug_buffer, 0, DEBUG_BUFFER_SIZE);
+    memset(screen_buffer, 0,DEBUG_BUFFER_SIZE);
+}
+
+
+void debug_enable(void)
+{
+    VRAMLoad((word) debugFont_pic, 0x5000, 2048);
+    VRAMLoad((word) debugMap, 0x4000, 0x0800);
+    setTileMapLocation(0x4000, (byte) 0x00, (byte) 0);
+    setCharacterLocation(0x5000, (byte) 0);
+    *(byte *) 0x2100 = 0x0f;    // enable background
+
+    // Font Color
+    // hex(24 << 10 | 24 << 5 | 24 ) = '0x6318'
+    *(byte *) 0x2121 = 0x02;
+    *(byte *) 0x2122 = 0xff;
+    *(byte *) 0x2122 = 0x7f;
+
+    // Font Border Color
+    *(byte *) 0x2121 = 0x00;
+    *(byte *) 0x2122 = 0x00;
+    *(byte *) 0x2122 = 0x00;
+
+    // Background Color
+    *(byte *) 0x2121 = 0x01;
+    *(byte *) 0x2122 = 0x05;
+    *(byte *) 0x2122 = 0x29;
+
+
+}
+
+void clears(void)
+{
+    word i, y;
+    for (y = 0; y < 20; y++) {
+        waitForVBlank();
+        for (i = 0; i < 32; i++) {
+            *(byte *) 0x2115 = 0x80;
+            *(word *) 0x2116 = 0x4000 + i + (y * 0x20);
+            *(byte *) 0x2118 = 0;
+        }
+    }
+}
+
+void _print_char(word y, word x, char c)
+{
+    waitForVBlank();
+    VRAMByteWrite((byte) (c - 32), (word) (0x4000 + x + (y * 0x20)));
+}
+
+void _print_screen(word y, char *buffer)
+{
+    char l;
+    unsigned int x; 
+    x = y * 0x20;
+    l = strlen(buffer);
+    waitForVBlank();
+    while (*buffer) {
+        if (*buffer == '\n') {
+            while (x++ < 32) {
+                *(byte *) 0x2115 = 0x80;
+                *(word *) 0x2116 = 0x4000 + x + (y * 0x20);
+                *(byte *) 0x2118 = 0;
+            }
+            x = 0;
+            y += 0x20;
+            buffer++;
+            waitForVBlank();
+            continue;
+        }
+        *(byte *) 0x2115 = 0x80;
+        *(word *) 0x2116 = 0x4000 + x;
+        *(byte *) 0x2118 = *buffer - 32;
+        x++;
+        buffer++;
+#if 1
+        waitForVBlank();
+#endif
+    }
+}
+void _print_console(const char *buffer)
+{
+    while (*buffer)
+        *(byte *) 0x3000 = *buffer++;
+}
+
+
+
+
+void printfc(const char *fmt, ...)
+{
+    va_list ap;
+    va_start(ap, fmt);
+    vsprintf(debug_buffer, fmt, ap);
+    va_end(ap);
+    _print_console(debug_buffer);
+    //memset(debug_buffer,0,DEBUG_BUFFER_SIZE);
+
+}
+
+void printfs(word y, const char *fmt, ...)
+{
+    va_list ap;
+    va_start(ap, fmt);
+    vsprintf(screen_buffer, fmt, ap);
+    va_end(ap);
+    _print_screen(y, screen_buffer);
+    //memset(screen_buffer, 0, DEBUG_BUFFER_SIZE);
+}
+
+void printc_packet(unsigned long addr, unsigned int len, byte * packet)
+{
+    unsigned int i, j;
+    unsigned int sum = 0;
+    unsigned int last_sum = 0;
+    unsigned int clear = 0;
+    
+    for (i = 0; i < len; i += 16) {
+
+        sum = 0;
+        for (j = 0; j < 16; j++) {
+            sum += packet[i + j];
+        }
+        if (!sum) {
+            clear = 1;
+            continue;
+        }
+        
+        if (last_sum == sum) {
+            clear = 1;
+            continue;
+        }
+        
+        if (clear) {
+            printfc("*\n");
+            clear = 0;
+        }
+        printfc("%06lX:", addr + i);
+        for (j = 0; j < 16; j++) {
+            printfc(" %02x", packet[i + j]);
+        }
+        printfc(" |");
+        for (j = 0; j < 16; j++) {
+            if (packet[i + j] >= 33 && packet[i + j] <= 126)
+                printfc("%c", packet[i + j]);
+            else
+                printfc(".");
+        }
+        printfc("|\n");
+        last_sum = sum;
+    }
+}
+/*
+ * keep the linker happy 
+ */
+int open(const char *_name, int _mode)
+{
+    _print_console("open called\n");
+    return -1;
+}
+
+int close(int fd)
+{
+    _print_console("close called\n");
+    return -1;
+
+}
+
+size_t read(int fd, void *buff, size_t len)
+{
+    _print_console("read called\n");
+    return 0;
+}
+
+size_t write(int fd, void *buffer, size_t len)
+{
+    _print_console("write called\n");
+    return 0;
+}
+
+long lseek(int fd, long off, int count)
+{
+    _print_console("lseek called\n");
+    return 0;
+}
+
+int unlink(const char *name)
+{
+    _print_console("unlink called\n");
+    return -1;
+}
+
+int isatty()
+{
+    _print_console("isatty called\n");
+    return 1;
+}

+ 8 - 0
snes/wram/debug.h

@@ -0,0 +1,8 @@
+#include "data.h"
+
+void debug_init(void);
+void debug_enable(void);
+void printfs(word y, const char *fmt, ...);
+void printfc(const char *fmt, ...);
+void clears(void);
+void printc_packet(unsigned long addr, unsigned int len, byte * packet);

+ 106 - 0
snes/wram/event.c

@@ -0,0 +1,106 @@
+#include <stdlib.h>
+
+#include "data.h";
+#include "event.h";
+
+event *events;
+
+void initEvents(void)
+{
+    events = NULL;
+}
+
+event *createEvent(char (*callback) (word counter))
+{
+    event *myEvent;
+
+    myEvent = (event *) malloc(sizeof(event));
+
+    myEvent->VBlankCount = 0;
+    myEvent->callback = callback;
+    myEvent->nextEvent = NULL;
+    myEvent->previousEvent = NULL;
+
+
+    return myEvent;
+}
+
+event *addEvent(char (*callback) (word counter), int noDuplicateCallback)
+{
+
+    event *lastEvent;
+    event *myEvent;
+
+    if (events == NULL) {
+        events = createEvent(callback);
+        return events;
+    } else {
+        lastEvent = events;
+        // TODO optimise this with noduplicate
+        while (lastEvent->nextEvent != NULL) {
+            if (noDuplicateCallback == 1 && lastEvent->callback == *callback) {
+                return NULL;
+            }
+            lastEvent = lastEvent->nextEvent;
+        }
+        if (noDuplicateCallback == 1 && lastEvent->callback == *callback) {
+            return NULL;
+        }
+        myEvent = createEvent(callback);
+        myEvent->previousEvent = lastEvent;
+        lastEvent->nextEvent = myEvent;
+        return myEvent;
+    }
+
+
+}
+
+void removeEvent(event * eventElement)
+{
+
+    byte alone = 0;
+    event *next, *previous;
+
+    next = eventElement->nextEvent;
+    previous = eventElement->previousEvent;
+
+    if (eventElement->nextEvent != NULL && eventElement->previousEvent != NULL) {
+        alone++;
+        next->previousEvent = previous;
+        previous->nextEvent = next;
+
+    } else if (eventElement->nextEvent != NULL) {
+        alone++;
+        next->previousEvent = NULL;
+        events = next;
+
+    } else if (eventElement->previousEvent != NULL) {
+        alone++;
+        previous->nextEvent = NULL;
+    }
+
+    free(eventElement);
+
+    if (alone == 0) {
+        events = NULL;
+    }
+}
+
+void processEvents(void)
+{
+
+    event *currentEvent;
+    char returnValue;
+
+    currentEvent = events;
+    while (currentEvent != NULL) {
+        returnValue = currentEvent->callback(currentEvent->VBlankCount);
+        if (returnValue == EVENT_CONTINUE) {
+            currentEvent->VBlankCount++;
+        } else {
+            removeEvent(currentEvent);
+        }
+        currentEvent = currentEvent->nextEvent;
+    }
+
+}

+ 17 - 0
snes/wram/event.h

@@ -0,0 +1,17 @@
+typedef struct event {
+    word VBlankCount;
+    char (*callback) (word counter);
+    struct event *previousEvent;
+    struct event *nextEvent;
+} event;
+
+#define EVENT_STOP 0
+#define EVENT_CONTINUE 1
+
+extern event *events;
+
+void initEvents(void);
+extern event *addEvent(char (*callback) (word counter),
+                       int noDuplicateCallback);
+extern void removeEvent(event * eventElement);
+extern void processEvents(void);

+ 48 - 0
snes/wram/integer.h

@@ -0,0 +1,48 @@
+/*-------------------------------------------*/
+/*
+ * Integer type definitions for FatFs module 
+ */
+/*-------------------------------------------*/
+
+#ifndef _INTEGER
+
+
+/*
+ * These types must be 16-bit, 32-bit or larger integer 
+ */
+typedef int INT;
+typedef unsigned int UINT;
+
+/*
+ * These types must be 8-bit integer 
+ */
+typedef signed char CHAR;
+typedef unsigned char UCHAR;
+typedef unsigned char BYTE;
+
+/*
+ * These types must be 16-bit integer 
+ */
+typedef short SHORT;
+typedef unsigned short USHORT;
+typedef unsigned short WORD;
+typedef unsigned short WCHAR;
+
+/*
+ * These types must be 32-bit integer 
+ */
+typedef long LONG;
+typedef unsigned long ULONG;
+typedef unsigned long DWORD;
+
+/*
+ * Boolean type 
+ */
+// enum { false = 0 , true } bool;
+
+//typedef int BOOL;
+#define FALSE 0
+#define TRUE  1
+
+#define _INTEGER
+#endif

+ 128 - 0
snes/wram/main.c

@@ -0,0 +1,128 @@
+
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "data.h";
+#include "pad.h";
+#include "event.h";
+#include "myEvents.h";
+#include "ressource.h";
+#include "PPU.h"
+#include "debug.h"
+#include "integer.h"
+
+
+
+typedef void (*FUNC) (void);
+
+padStatus pad1;
+
+void initInternalRegisters(void)
+{
+    characterLocation[0] = 0x0000;
+    characterLocation[1] = 0x0000;
+    characterLocation[2] = 0x0000;
+    characterLocation[3] = 0x0000;
+    debug_init();
+}
+
+void preInit(void)
+{
+
+    // For testing purpose ... 
+    // Insert code here to be executed before register init
+} 
+
+void halt(void)
+{
+    while (1);
+}
+
+void wait(void)
+{
+    printfc("SNES::wait: press A to continue\n");
+    enablePad();
+    pad1 = readPad((byte) 0);
+    while (!pad1.A) {
+        waitForVBlank();
+        pad1 = readPad((byte) 0);
+    }
+    printfc("SNES::wait: done\n");
+}
+
+void boot(DWORD addr)
+{
+    FUNC fn;
+    //printfc("SNES::boot addr=%lx\n", addr);
+    fn = (FUNC) addr;
+    fn();
+
+} 
+void main(void)
+{
+    unsigned char i,j;
+    unsigned long addr;
+    initInternalRegisters();
+    *(byte *) 0x2105 = 0x01;    // MODE 1 value
+    *(byte *) 0x212c = 0x01;    // Plane 0 (bit one) enable register
+    *(byte *) 0x212d = 0x00;    // All subPlane disable
+    *(byte *) 0x2100 = 0x0f;    // enable background
+
+    debug_enable();
+#if 0    
+    addr = 0x008000;
+    for (i=0;i<28;i++){
+        printfs(i,"ROW %02i %02X %08li %06lX",i,i,addr,addr);
+        printfc("ROW %02i %02X %08li %06lX\n",i,i,addr,addr);
+        addr += 0x10000;
+    }
+#endif
+
+#define START_ADDR 0x020000
+#define END_ADDR   0x7f2000
+    addr = 0x000000;
+    i=0;
+    j=0;
+    for (addr=START_ADDR; addr < END_ADDR; addr+=0x1000){
+        if (addr > START_ADDR && addr%0x2000==0){
+            //printfc("hit %06lx\n",addr);
+            addr += 0x10000 - 0x2000;
+            j++;
+            if (j>26)
+                j=0;
+        }
+        i++;
+        printfc("fill mem=%06lx tag=%02x tag=%i \n", addr, i, i);
+        *(byte *) (addr) = i;
+    }
+    i=0;
+    j=0;
+    for (addr=START_ADDR; addr < END_ADDR; addr+=0x1000){
+        if (addr > START_ADDR && addr%0x2000==0){
+            addr += 0x10000 - 0x2000;
+            i++;
+            j++;
+            if (j>26)
+                j=0;
+        }
+        printfs(j,"DUMP %06lX ",addr);
+        printc_packet(addr,16,(byte *) (addr));
+    }
+    
+    
+    while (1) {
+        wait();
+    }
+}
+
+void IRQHandler(void)
+{
+
+}
+
+void NMIHandler(void)
+{
+
+    // processEvents();
+}

+ 103 - 0
snes/wram/myEvents.c

@@ -0,0 +1,103 @@
+#include "data.h";
+#include "pad.h";
+#include "event.h";
+
+extern padStatus pad1;
+extern word scrollValue;
+
+char fadeOut(word counter)
+{
+    static byte fadeOutValue;
+
+    if (counter == 0) {
+        // init fade value
+        fadeOutValue = 0x0f;
+    } else {
+        fadeOutValue--;
+    }
+
+    *(byte *) 0x2100 = fadeOutValue;
+
+    if (fadeOutValue == 0x00) {
+        return EVENT_STOP;
+    } else {
+        return EVENT_CONTINUE;
+    }
+}
+
+char fadeIn(word counter)
+{
+    static byte fadeInValue;
+
+    if (counter == 0) {
+        // init fade value
+        fadeInValue = 0x00;
+    } else {
+        fadeInValue++;
+    }
+
+    *(byte *) 0x2100 = fadeInValue;
+
+    if (fadeInValue >= 0x0f) {
+        return EVENT_STOP;
+    } else {
+        return EVENT_CONTINUE;
+    }
+}
+
+char mosaicOut(word counter)
+{
+    static byte mosaicOutValue;
+
+    if (counter == 0) {
+        // init fade value
+        mosaicOutValue = 0xff;
+    } else {
+        mosaicOutValue -= 0x10;
+    }
+
+    *(byte *) 0x2106 = mosaicOutValue;
+
+    if (mosaicOutValue == 0x0f) {
+        return EVENT_STOP;
+    } else {
+        return EVENT_CONTINUE;
+    }
+}
+
+char mosaicIn(word counter)
+{
+    static byte mosaicInValue;
+
+    if (counter == 0) {
+        // init fade value
+        mosaicInValue = 0x0f;
+    } else {
+        mosaicInValue += 0x10;
+    }
+
+    *(byte *) 0x2106 = mosaicInValue;
+
+    if (mosaicInValue == 0xff) {
+        return EVENT_STOP;
+    } else {
+        return EVENT_CONTINUE;
+    }
+}
+
+char NMIReadPad(word counter)
+{
+    pad1 = readPad((byte) 0);
+
+    return EVENT_CONTINUE;
+}
+
+char scrollLeft(word counter)
+{
+    scrollValue++;
+
+    *(byte *) 0x210d = (byte) scrollValue;
+    *(byte *) 0x210d = (byte) (scrollValue >> 8);
+
+    return EVENT_CONTINUE;
+}

+ 6 - 0
snes/wram/myEvents.h

@@ -0,0 +1,6 @@
+char fadeOut(word counter);
+char fadeIn(word counter);
+char mosaicOut(word counter);
+char mosaicIn(word counter);
+char NMIReadPad(word counter);
+char scrollLeft(word counter);

+ 26 - 0
snes/wram/pad.c

@@ -0,0 +1,26 @@
+#include "data.h";
+#include "pad.h";
+#include "debug.h";
+
+void enablePad(void)
+{
+    // Enable pad reading and NMI
+    *(byte *) 0x4200 = 0x01;
+}
+
+void disablePad(void)
+{
+    // Enable pad reading and NMI
+    *(byte *) 0x4200 = 0x00;
+}
+
+padStatus readPad(byte padNumber)
+{
+    word test;
+    padStatus *status;
+    padNumber = padNumber << 1;
+    test = (word) * (byte *) 0x4218 + padNumber << 8;
+    test |= (word) * (byte *) 0x4219 + padNumber;
+    status = (padStatus *) & test;
+    return *status;
+}

+ 20 - 0
snes/wram/pad.h

@@ -0,0 +1,20 @@
+typedef struct padStatus {
+    byte right:1;
+    byte left:1;
+    byte down:1;
+    byte up:1;
+    byte start:1;               // Enter
+    byte select:1;              // Space
+    byte Y:1;                   // X
+    byte B:1;                   // C
+    // --------------------------------
+    byte Dummy:4;
+    byte R:1;                   // Z
+    byte L:1;                   // A
+    byte X:1;                   // S
+    byte A:1;                   // D
+} padStatus;
+
+extern void enablePad(void);
+extern void disablePad(void);
+extern padStatus readPad(byte padNumber);

+ 9 - 0
snes/wram/ressource.asm

@@ -0,0 +1,9 @@
+ressource .section
+
+
+	XDEF ~~debugFont_pic
+~~debugFont_pic
+	INSERT ressource/debugFont.pic
+
+
+.ends

+ 2 - 0
snes/wram/ressource.h

@@ -0,0 +1,2 @@
+
+extern word debugFont_pic[];

BIN
snes/wram/ressource/debugFont.clr


BIN
snes/wram/ressource/debugFont.pcx


BIN
snes/wram/ressource/debugFont.pic


BIN
snes/wram/ressource/debugFont.xcf


+ 91 - 0
snes/wram/wram.bnk

@@ -0,0 +1,91 @@
+
+Sections:
+org=00000000 siz=00001BAF end=00001BAF 'CODE'
+org=00001BAF siz=00000394 end=00001F43 'DATA'
+org=00000000 siz=00000B1C end=00000B1C 'UDATA'
+org=00007FE4 siz=0000001C end=00008000 'vectors'
+org=00007FB0 siz=00000030 end=00007FE0 'registration_data'
+org=00008000 siz=00000800 end=00008800 'ressource'
+
+Module map:
+ROM:00000000 0000013B  REL:00008000 0000813B S=CODE       M=StartupSnes.obj F=StartupSnes.obj
+ROM:00000000 00000002  REL:00000000 00000002 S=UDATA      M=main.obj F=main.obj
+ROM:00000002 00000004  REL:00000002 00000004 S=UDATA      M=pad.obj F=pad.obj
+ROM:00000004 00000010  REL:00000004 00000010 S=UDATA      M=PPU.obj F=PPU.obj
+ROM:00000010 00000910  REL:00000010 00000910 S=UDATA      M=debug.obj F=debug.obj
+ROM:0000013B 0000030E  REL:0000813B 0000830E S=CODE       M=main.obj F=main.obj
+ROM:0000030E 00000390  REL:0000830E 00008390 S=CODE       M=pad.obj F=pad.obj
+ROM:00000390 000005CC  REL:00008390 000085CC S=CODE       M=PPU.obj F=PPU.obj
+ROM:000005CC 00000AB8  REL:000085CC 00008AB8 S=CODE       M=debug.obj F=debug.obj
+ROM:00000910 00000914  REL:00000910 00000914 S=UDATA      M=sbrk F=/home/david/.wine/drive_c/65xx_FreeSDK/lib/cl.lib
+ROM:00000914 00000918  REL:00000914 00000918 S=UDATA      M=_mem_start F=/home/david/.wine/drive_c/65xx_FreeSDK/lib/cl.lib
+ROM:00000918 00000B18  REL:00000918 00000B18 S=UDATA      M=_format F=/home/david/.wine/drive_c/65xx_FreeSDK/lib/cl.lib
+ROM:00000AB8 00000B06  REL:00008AB8 00008B06 S=CODE       M=sbrk F=/home/david/.wine/drive_c/65xx_FreeSDK/lib/cl.lib
+ROM:00000B06 00000B32  REL:00008B06 00008B32 S=CODE       M=memset F=/home/david/.wine/drive_c/65xx_FreeSDK/lib/cl.lib
+ROM:00000B18 00000B1C  REL:00000B18 00000B1C S=UDATA      M=_close_stdio F=/home/david/.wine/drive_c/65xx_FreeSDK/lib/cl.lib
+ROM:00000B32 00000B50  REL:00008B32 00008B50 S=CODE       M=strlen F=/home/david/.wine/drive_c/65xx_FreeSDK/lib/cl.lib
+ROM:00000B50 00000BAD  REL:00008B50 00008BAD S=CODE       M=vsprintf F=/home/david/.wine/drive_c/65xx_FreeSDK/lib/cl.lib
+ROM:00000BAD 00000BCE  REL:00008BAD 00008BCE S=CODE       M=~fmov F=/home/david/.wine/drive_c/65xx_FreeSDK/lib/cl.lib
+ROM:00000BCE 00000BEE  REL:00008BCE 00008BEE S=CODE       M=~fnmov F=/home/david/.wine/drive_c/65xx_FreeSDK/lib/cl.lib
+ROM:00000BEE 00000BF6  REL:00008BEE 00008BF6 S=CODE       M=~lcal F=/home/david/.wine/drive_c/65xx_FreeSDK/lib/cl.lib
+ROM:00000BF6 00000BFE  REL:00008BF6 00008BFE S=CODE       M=~lsr F=/home/david/.wine/drive_c/65xx_FreeSDK/lib/cl.lib
+ROM:00000BFE 000013E6  REL:00008BFE 000093E6 S=CODE       M=_format F=/home/david/.wine/drive_c/65xx_FreeSDK/lib/cl.lib
+ROM:000013E6 00001400  REL:000093E6 00009400 S=CODE       M=~ludv F=/home/david/.wine/drive_c/65xx_FreeSDK/lib/cl.lib
+ROM:00001400 00001415  REL:00009400 00009415 S=CODE       M=~lumd F=/home/david/.wine/drive_c/65xx_FreeSDK/lib/cl.lib
+ROM:00001415 00001436  REL:00009415 00009436 S=CODE       M=~swt F=/home/david/.wine/drive_c/65xx_FreeSDK/lib/cl.lib
+ROM:00001436 000016E0  REL:00009436 000096E0 S=CODE       M=_flsbuf F=/home/david/.wine/drive_c/65xx_FreeSDK/lib/cl.lib
+ROM:000016E0 000017A9  REL:000096E0 000097A9 S=CODE       M=_getbuf F=/home/david/.wine/drive_c/65xx_FreeSDK/lib/cl.lib
+ROM:000017A9 00001886  REL:000097A9 00009886 S=CODE       M=malloc F=/home/david/.wine/drive_c/65xx_FreeSDK/lib/cl.lib
+ROM:00001886 000018C7  REL:00009886 000098C7 S=CODE       M=~comdiv F=/home/david/.wine/drive_c/65xx_FreeSDK/lib/cl.lib
+ROM:000018C7 000018FB  REL:000098C7 000098FB S=CODE       M=~udv F=/home/david/.wine/drive_c/65xx_FreeSDK/lib/cl.lib
+ROM:000018FB 0000193B  REL:000098FB 0000993B S=CODE       M=_closeall F=/home/david/.wine/drive_c/65xx_FreeSDK/lib/cl.lib
+ROM:0000193B 00001A3E  REL:0000993B 00009A3E S=CODE       M=fclose F=/home/david/.wine/drive_c/65xx_FreeSDK/lib/cl.lib
+ROM:00001A3E 00001ABB  REL:00009A3E 00009ABB S=CODE       M=fflush F=/home/david/.wine/drive_c/65xx_FreeSDK/lib/cl.lib
+ROM:00001ABB 00001B84  REL:00009ABB 00009B84 S=CODE       M=free F=/home/david/.wine/drive_c/65xx_FreeSDK/lib/cl.lib
+ROM:00001B84 00001BA9  REL:00009B84 00009BA9 S=CODE       M=strcpy F=/home/david/.wine/drive_c/65xx_FreeSDK/lib/cl.lib
+ROM:00001BA9 00001BAF  REL:00009BA9 00009BAF S=CODE       M=~umd F=/home/david/.wine/drive_c/65xx_FreeSDK/lib/cl.lib
+ROM:00001BAF 00001C0F  REL:00009BAF 00009C0F S=DATA       M=main.obj F=main.obj
+ROM:00001C0F 00001C8C  REL:00009C0F 00009C8C S=DATA       M=debug.obj F=debug.obj
+ROM:00001C8C 00001CAE  REL:00009C8C 00009CAE S=DATA       M=_format F=/home/david/.wine/drive_c/65xx_FreeSDK/lib/cl.lib
+ROM:00001CAE 00001DAF  REL:00009CAE 00009DAF S=DATA       M=_ctype F=/home/david/.wine/drive_c/65xx_FreeSDK/lib/cl.lib
+ROM:00001DAF 00001F3F  REL:00009DAF 00009F3F S=DATA       M=_iob F=/home/david/.wine/drive_c/65xx_FreeSDK/lib/cl.lib
+ROM:00001F3F 00001F43  REL:00009F3F 00009F43 S=DATA       M=fclose F=/home/david/.wine/drive_c/65xx_FreeSDK/lib/cl.lib
+ROM:00007FB0 00007FE0  REL:0000FFB0 0000FFE0 S=registrati M=StartupSnes.obj F=StartupSnes.obj
+ROM:00007FE4 00008000  REL:0000FFE4 00010000 S=vectors    M=StartupSnes.obj F=StartupSnes.obj
+ROM:00008000 00008800  REL:00018000 00018800 S=ressource  M=ressource.obj F=ressource.obj
+
+TOTSTRINGS=1191
+  CACHE: 0
+ OBJMOD: 1914
+ SECMAP: 200
+SECINFO: 6720
+ SYMTAB: 576
+ OUTPUT: 0
+ STRING: 2836
+ SYMBOL: 1782
+SECTION: 528
+   FILE: 112
+TOTMEM: 14668
+
+Section: ORG:    ROM ORG:  SIZE:
+CODE     008000  000000     1BAFH (  7087)
+DATA     009BAF  001BAF      394H (   916)
+UDATA    000000  ------      B1CH (  2844)
+vectors  00FFE4  007FE4       1CH (    28)
+registra 00FFB0  007FB0       30H (    48)
+ressourc 018000  008000      800H (  2048)
+Total                       32ABH ( 12971)
+
+
+TOTSTRINGS=1191
+  CACHE: 17580
+ OBJMOD: 1914
+ SECMAP: 200
+SECINFO: 6720
+ SYMTAB: 576
+ OUTPUT: 0
+ STRING: 2836
+ SYMBOL: 1782
+SECTION: 528
+   FILE: 112
+TOTMEM: 32248