From 9d707f612a2eabdab2572360cc8d5070ad998d4c Mon Sep 17 00:00:00 2001 From: David Voswinkel Date: Sun, 5 Jul 2009 10:44:00 +0200 Subject: [PATCH] add regdump --- snes/regdump/Makefile | 71 +++++++ snes/regdump/PPU.c | 80 ++++++++ snes/regdump/PPU.h | 11 + snes/regdump/StartupSnes.asm | 240 ++++++++++++++++++++++ snes/regdump/data.h | 8 + snes/regdump/debug.c | 227 +++++++++++++++++++++ snes/regdump/debug.h | 8 + snes/regdump/event.asm | 294 +++++++++++++++++++++++++++ snes/regdump/event.c | 101 +++++++++ snes/regdump/event.h | 16 ++ snes/regdump/inject.py | 22 ++ snes/regdump/main.c | 68 +++++++ snes/regdump/myEvents.c | 97 +++++++++ snes/regdump/myEvents.h | 6 + snes/regdump/pad.c | 17 ++ snes/regdump/pad.h | 19 ++ snes/regdump/ressource.asm | 23 +++ snes/regdump/ressource.h | 3 + snes/regdump/ressource/debugFont.clr | Bin 0 -> 2 bytes snes/regdump/ressource/debugFont.pcx | Bin 0 -> 3154 bytes snes/regdump/ressource/debugFont.pic | Bin 0 -> 2048 bytes snes/regdump/ressource/debugFont.xcf | Bin 0 -> 6237 bytes snes/regdump/ressource/kungfu.clr | Bin 0 -> 512 bytes snes/regdump/ressource/kungfu.pcx | Bin 0 -> 7706 bytes snes/regdump/ressource/kungfu.pic | Bin 0 -> 7136 bytes snes/regdump/tools/padbin.exe | Bin 0 -> 16095 bytes 26 files changed, 1311 insertions(+) create mode 100644 snes/regdump/Makefile create mode 100644 snes/regdump/PPU.c create mode 100644 snes/regdump/PPU.h create mode 100644 snes/regdump/StartupSnes.asm create mode 100644 snes/regdump/data.h create mode 100644 snes/regdump/debug.c create mode 100644 snes/regdump/debug.h create mode 100644 snes/regdump/event.asm create mode 100644 snes/regdump/event.c create mode 100644 snes/regdump/event.h create mode 100644 snes/regdump/inject.py create mode 100644 snes/regdump/main.c create mode 100644 snes/regdump/myEvents.c create mode 100644 snes/regdump/myEvents.h create mode 100644 snes/regdump/pad.c create mode 100644 snes/regdump/pad.h create mode 100644 snes/regdump/ressource.asm create mode 100644 snes/regdump/ressource.h create mode 100644 snes/regdump/ressource/debugFont.clr create mode 100644 snes/regdump/ressource/debugFont.pcx create mode 100644 snes/regdump/ressource/debugFont.pic create mode 100644 snes/regdump/ressource/debugFont.xcf create mode 100644 snes/regdump/ressource/kungfu.clr create mode 100644 snes/regdump/ressource/kungfu.pcx create mode 100644 snes/regdump/ressource/kungfu.pic create mode 100644 snes/regdump/tools/padbin.exe diff --git a/snes/regdump/Makefile b/snes/regdump/Makefile new file mode 100644 index 0000000..3c4ff67 --- /dev/null +++ b/snes/regdump/Makefile @@ -0,0 +1,71 @@ +# SDK Config + + +PLATFORM=mac + +ifeq ($(PLATFORM),linux) + + # Linux Wine + SDK=/home/david/.wine/drive_c/65xx_FreeSDK + WINE=wine + EMU=zsnes + EMU_DEBUG=/home/david/Devel/arch/snes/tools/zsnes_linux_debug151/src/zsnesd -d +else + # Mac Wine + SDK=/Users/david/.wine/drive_c/65xx_FreeSDK + WINE=wine + EMU=zsnes +endif + +CC=$(WINE) $(SDK)/bin/WDC816CC.exe +AS=$(WINE) $(SDK)/bin/WDC816AS.exe +LD=$(WINE) $(SDK)/bin/WDCLN.exe +PADBIN=$(WINE) tools/padbin.exe +PCX2SNES=$(WINE) tools/Pcx2Snes.exe + + + +# Project + +INC=$(SDK)/include +LIBS=$(SDK)/lib/cc +#OBJS=StartupSnes.obj main.obj pad.obj event.obj myEvents.obj PPU.obj debug.obj ressource.obj +OBJS=StartupSnes.obj main.obj pad.obj PPU.obj debug.obj ressource.obj +APP=regdump.smc +GFX=kungfu debugfont + +all: $(APP) check + +run: + $(EMU) $(APP) + +debugger: + $(EMU_DEBUG) $(APP) + +check: + ucon64 -chk $(APP) + + +debugfont: + $(PCX2SNES) ressource/debugFont -n -c16 -s8 -o1 + +StartupSnes.obj: StartupSnes.asm + $(AS) -V $? + +ressource.obj: ressource.asm + $(AS) -V $? + +%.obj: %.c + $(CC) -wl -wp -sop -MC -I $(INC) $? + +$(APP): $(OBJS) + $(LD) -HB -M21 -V -T -Pff \ + -C008000,0000 -U0000,0000 \ + -Avectors=FFE4,7FE4 \ + -Aregistration_data=FFB0,7FB0 \ + -Aressource=38000,8000 \ + -N $(OBJS) -L$(LIBS) -O $@ + $(PADBIN) 0x20000 $(APP) + +clean: + rm -vf $(APP) *.obj diff --git a/snes/regdump/PPU.c b/snes/regdump/PPU.c new file mode 100644 index 0000000..e61b481 --- /dev/null +++ b/snes/regdump/PPU.c @@ -0,0 +1,80 @@ +#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; +} \ No newline at end of file diff --git a/snes/regdump/PPU.h b/snes/regdump/PPU.h new file mode 100644 index 0000000..36ecef9 --- /dev/null +++ b/snes/regdump/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); \ No newline at end of file diff --git a/snes/regdump/StartupSnes.asm b/snes/regdump/StartupSnes.asm new file mode 100644 index 0000000..a310e64 --- /dev/null +++ b/snes/regdump/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 $0B +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 + diff --git a/snes/regdump/data.h b/snes/regdump/data.h new file mode 100644 index 0000000..673102c --- /dev/null +++ b/snes/regdump/data.h @@ -0,0 +1,8 @@ + +#ifndef _DATA + +typedef unsigned char byte; +typedef unsigned short word; + +#define _DATA +#endif diff --git a/snes/regdump/debug.c b/snes/regdump/debug.c new file mode 100644 index 0000000..5674a6b --- /dev/null +++ b/snes/regdump/debug.c @@ -0,0 +1,227 @@ +#include +#include +#include +#include + +#include "debug.h" +#include "data.h" +#include "pad.h" +#include "PPU.h" +#include "ressource.h" + + + + +#define DEBUG_BUFFER_SIZE 256 + +word debug_map[0x400]; +char debug_buffer[DEBUG_BUFFER_SIZE]; +//char screen_buffer[DEBUG_BUFFER_SIZE]; + + + +void debug_init(void) +{ + + memset(debug_map, 0, 0x800); + memset(debug_buffer, 0,DEBUG_BUFFER_SIZE); + +#if 0 + memset(screen_buffer, 0, DEBUG_BUFFER_SIZE); + printfc("screen_buffer=%p\n",screen_buffer); + printfc("debug_buffer=%p\n",debug_buffer); + printfc("debug_map=%p\n",debug_map); +#endif + +} + + +void debug_enable(void) +{ + VRAMLoad((word) debugFont_pic, 0x5000, 2048); + VRAMLoad((word) debug_map, 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; + } + y ++; + x = y * 0x20; + buffer++; + waitForVBlank(); + continue; + } + *(byte *) 0x2115 = 0x80; + *(word *) 0x2116 = 0x4000 + x; + *(byte *) 0x2118 = *buffer - 32; + x++; + buffer++; +#if 0 + 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(debug_buffer, fmt, ap); + va_end(ap); + _print_screen(y, debug_buffer); + //memset(debug_buffer, 0, DEBUG_BUFFER_SIZE); + //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 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 (clear) { + printfc("*\n"); + clear = 0; + } + printfc("%06lX:", addr + i); + for (j = 0; j < 16; j++) { + printfc(" %x", 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"); + } +} + +/* + * 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; +} diff --git a/snes/regdump/debug.h b/snes/regdump/debug.h new file mode 100644 index 0000000..6f82af9 --- /dev/null +++ b/snes/regdump/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); diff --git a/snes/regdump/event.asm b/snes/regdump/event.asm new file mode 100644 index 0000000..f659a35 --- /dev/null +++ b/snes/regdump/event.asm @@ -0,0 +1,294 @@ +;:ts=8 +R0 equ 1 +R1 equ 5 +R2 equ 9 +R3 equ 13 + code + xdef __initEvents + func +__initEvents: + longa on + longi on + stz |__events + rts +L2 equ 0 +L3 equ 1 + ends + efunc + code + xdef __createEvent + func +__createEvent: + longa on + longi on + tsc + sec + sbc #L5 + tcs + phd + tcd +callback_0 set 3 +myEvent_1 set 0 + pea #<$8 + jsr __malloc + sta + +#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; + } + +} diff --git a/snes/regdump/event.h b/snes/regdump/event.h new file mode 100644 index 0000000..76b07dc --- /dev/null +++ b/snes/regdump/event.h @@ -0,0 +1,16 @@ +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); diff --git a/snes/regdump/inject.py b/snes/regdump/inject.py new file mode 100644 index 0000000..921e04a --- /dev/null +++ b/snes/regdump/inject.py @@ -0,0 +1,22 @@ +import os +import sys + +def main(): + + bank_size = 2 ** 15 + + rom = open(sys.argv[1],"r").read() + + out = open(sys.argv[1].replace(".smc",".inject"),"r+") + + out.write(rom) + + out.seek(0x2140) + for i in range(0,128): + out.write(chr(i)) + out.close() + + +if __name__ == '__main__': + main() + diff --git a/snes/regdump/main.c b/snes/regdump/main.c new file mode 100644 index 0000000..5521ec9 --- /dev/null +++ b/snes/regdump/main.c @@ -0,0 +1,68 @@ +#include "data.h"; +#include "pad.h"; +#include "event.h"; +#include "myEvents.h"; +#include "ressource.h"; +#include "PPU.h" +#include "debug.h" + + +#include + +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 main(void) { + word x,y; + padStatus pad1; + 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(); + + + addr = 0x21400; + x = 0; + y = 0; + for (addr = 0x2100 ; addr < 0x21C0; addr+=8){ + waitForVBlank(); + printfs(y,"%lX: %02X %02X %02X %02X %02X %02X %02X %02X",addr, + *(byte *) addr,*(byte *) (addr +1),*(byte *) (addr+2),*(byte *) (addr+3), + *(byte *) (addr+4),*(byte *) (addr +5),*(byte *) (addr+6),*(byte *) (addr+7)); + y++; + } + + + + while(1){ + while(!pad1.start) { + waitForVBlank(); + pad1 = readPad((byte) 0); + } + } + while(1); +} + +void IRQHandler(void) { +} + +void NMIHandler(void) { + //processEvents(); +} diff --git a/snes/regdump/myEvents.c b/snes/regdump/myEvents.c new file mode 100644 index 0000000..92c78ac --- /dev/null +++ b/snes/regdump/myEvents.c @@ -0,0 +1,97 @@ +#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; +} \ No newline at end of file diff --git a/snes/regdump/myEvents.h b/snes/regdump/myEvents.h new file mode 100644 index 0000000..719abe7 --- /dev/null +++ b/snes/regdump/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); \ No newline at end of file diff --git a/snes/regdump/pad.c b/snes/regdump/pad.c new file mode 100644 index 0000000..2b86eac --- /dev/null +++ b/snes/regdump/pad.c @@ -0,0 +1,17 @@ +#include "data.h"; +#include "pad.h"; + +void enablePad(void) { + // Enable pad reading and NMI + *(byte*)0x4200 = 0x81; +} + +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; +} diff --git a/snes/regdump/pad.h b/snes/regdump/pad.h new file mode 100644 index 0000000..e5a907f --- /dev/null +++ b/snes/regdump/pad.h @@ -0,0 +1,19 @@ +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 padStatus readPad(byte padNumber); diff --git a/snes/regdump/ressource.asm b/snes/regdump/ressource.asm new file mode 100644 index 0000000..6802a07 --- /dev/null +++ b/snes/regdump/ressource.asm @@ -0,0 +1,23 @@ +ressource .section + +; XDEF __title_map +;__title_map: +; INSERT ressource/kungfu.map +; +; XDEF __title_pic +;__title_pic: +; INSERT ressource/kungfu.pic +; +; XDEF __title_pal +;__title_pal: +;make INSERT ressource/kungfu.clr + + XDEF _~debugFont_pic +_~debugFont_pic + INSERT ressource/debugFont.pic + + XDEF _~debugFont_pal +_~debugFont_pal + INSERT ressource/debugFont.clr + +.ends diff --git a/snes/regdump/ressource.h b/snes/regdump/ressource.h new file mode 100644 index 0000000..8298c7e --- /dev/null +++ b/snes/regdump/ressource.h @@ -0,0 +1,3 @@ + +extern word debugFont_pic[]; +extern word debugFont_pal[]; diff --git a/snes/regdump/ressource/debugFont.clr b/snes/regdump/ressource/debugFont.clr new file mode 100644 index 0000000000000000000000000000000000000000..09f370e38f498a462e1ca0faa724559b6630c04f GIT binary patch literal 2 JcmZQz0000200961 literal 0 HcmV?d00001 diff --git a/snes/regdump/ressource/debugFont.pcx b/snes/regdump/ressource/debugFont.pcx new file mode 100644 index 0000000000000000000000000000000000000000..9a481e084bc507111f54174d01131fa9268d0117 GIT binary patch literal 3154 zcmeH}Yi`^y41{F^MT??G$^8!?KawWfGqg9^&Nn1wyImB>?`C%`$$Sil6m9L-Pt%vC z&wcvbo~EaX^}9Y(o8RwrM7U4a@5}TyEp45)w)ooH^xU-CB;9p&U7JLU=3i4s%W}a= zzs0{;*NDE{U$x#7yyLJ7@tDHJAXijEKK@0-5%+rA6{?FRA))Z9?AomKG|bj$RuXNS zHFPbR7tJ==Syo_0KkTcH<(ic#V@j)6hK4LrX9ph3p*hIri!X4Sq&~JMN)37t`Lc@fl1J z^$RWTJ*uie(W&fS_lCs1z~x`OYNNBXf8SbRYc{Kk8>G8vMKCu9U0rWMSt-E+;`t$A z-+Kphh1rD!Uc(diAvhk7lXs>rs51l{j##lT#Y1F;WU^kVq^knZ$2YySA|D^DH;K+i zJ4Zb-a@=+Bo=#&LERNz_MaR*TOMBME8PCk02r&7@>79o?do6)A1Ndwg)@kOOVOFXE e$`Su8mYUo)-}K++-tPJwe{w!n9~Jm-D)1XJOx*kc literal 0 HcmV?d00001 diff --git a/snes/regdump/ressource/debugFont.pic b/snes/regdump/ressource/debugFont.pic new file mode 100644 index 0000000000000000000000000000000000000000..ea179dc0fc59ef93fe15239af9bb545c4bab84b1 GIT binary patch literal 2048 zcmai#ziPuU5XKLaL3HvEN(T=ngitbMD4~>6{A?#Y#G4->uTqgA^f7{8AlW<=-0vjE zrQ+oJFdlxs)BX7*4K(~Qik^Ww>Wnw}MwH;|$Sq-Gl=uhXyyPmpF2?ZsB+zHP4_sM= zGw}=W+3+K8Sm8CkGGJKdi4H4)8lYUuTTr^NrZIMQ6@=TOJjT{3~>J zi!N8J@M->u{Jnn$-%|IVxcsBUZ>U-E3M}ihUg6$fVki73E-_O65_>Mb_|EwYOZbPr zkNZSfKk&|+%qc%BT=eI_Tta{M=?4YG0R|F%*7?cQ34J=U1@;HDr|S>%a7XR^*{Y9+cKpOOZ)&F3ip9$#fAIH_?h;(;7gOt><~!fNEzXE} z|FwQTPxDLk-}7+8sOO{1M=X_p;Gj$BSntohdusj-d0zv6Ro|07=JFSo&?oN4!r}gK tIlfAMN6i16cjmU}vu}mhRKL~ePi^p3ct_5-}I3TzIH;#OgEbmo+rgwJpAw*$TRa0GERo&C|x_Wk& z>#OV0=3*^6GdH(SDHVcL%?JVRTR=HbPxWv?*bWNVGYR?%as;1Xnrs`{D4E3h1Csik z>{qg%$!6&pkv-1lvt-|qeM9yI*{5WmkbOw@KH1x3=gD3pJ4d!jwobM}_8eF+OX(EZ z_hj>AN66;Lq&K28O}33}lT0~! zK^qT@^*G*&tDSf$dZFG~i5`36+VWzv(QHMta;vnK7pl?R-Z{C32>VReZn!QCakc%?5;|U|Sv*3($?v z?c0Cg;Gx6!A9;Wl%o?vEh?ycXM~%#6j2Rg>Rr2IG7CDF$w7g5Ila;D)N9?S5!X5l+1#wGHkaaPsk>HPtuGptV8qUnD`Bqu zi&~H*nqrfG56OQRbOQ8De}DcLB)Wm5e2irNq}0UcNYcG1ML%Mz&SCK{!3PUQlvUni`baMKJb{MK44A_N|6&5LM@eH+v@d?6<@D0`9m^MRM z+le%qD02u&%Nc|>1Bw&I;%HNJ^n60~7XxwzL3n{eG9q!>DiX=iziCx=Y!>h2A6rUq(HSNd}mtn@&<5MG{`&!-Ql7 zJ~e+iwsw#)16()J$O;soDX>e{tZ(I|KQ9T)>%0Y6E-}vah3*eD!f2Cz3Wv-_U?6@5 zC^92KNmBfp5yYaTr4UKhBxYNw&0#KPh8it0ibOEu*&t$7rjMEXMJ!4XN+=mc)TYk_ zop4i-#}QkRWJV&{DM=$K&a30d6&4s+DFQuV?@krqo`Wt2fN0$==zX0ajNpQhHwYsJ zNd{%EcO2Th7f*b#4BA)wguQ}i!CA0f!kzL6$e$sS-(yq&qnDHmK+j8(ZnGP?bx8(B zfq{Zkaw7$LXUZbT5}KWk)fP!~V_eN3jWaZ$9Ze&YJJp18)(9ez(tKqGGtHrMwqfls zCTddr5|1G;IK)|+YI2bBLu3yM@^XL+N=5Osnm3sQLR}RIC<#kzhLO1J*J(NsOA?+9 z=vx`66eQXHs8=^~t}=*g^^NAV&L+WWU_sNj>IOl2XO@_Gf(1Xl?S|(Kt1TS@rXl;= zrp_D57OZi5>L5m1N-}`-ON|#EE(L+Mg@}QMjUAX;<{rZ#IVsNz9$aF$Lflkia%X)u zAmKW)Q}16EZPo;@cv}M=Kf0>xBgjSI9_D7}xx@;>yX&MkJAH2sM-1q@?)Qi1Jp22@ zUJ*LZo%f`SLs7jfDdUQB3;1`N4VyJTr(Q+QSC;G3PTPHXNNNVnULwgnGR`6 z#mEBB2DH!QN=!aXCho8(<=H5e;U3OPqDj-#h`Xsx50E`(W` z0`r6hRuGlJM~dC51`#O)L^3$&L!pc51SHA$nPGquon?K}+3}o%6H?DqG8HdX^hxer z%+(Hm$}X@I`k%|2pT7*r$eUOhDR(y*s)e^u*G!ICTl}+R2z<=>cMX<nQL7@*AJ`8M!Iscre)qB|KLxdgMIXGd6CsYDPy{GgR zks{_rw{D^R+vNhVzK{AuUo2VQWN%?4cIu5RPnut`&WFyl|?NTXYl4+)PsgyA> zO^w|vm$g3AOa;xtIJ+0b_v%I#QZ@r#Qu0_-F04&~E`hT9-CtenCI!&^4bmxg|Hq|H z$=@4&oHML8@y0Uwp49m_@IY{L{Aqi03~u+1Y>h-cPg|n(eT*ky`B++3GjiQ&lCJ5l^30{zEh07Ty(wyk+Qw|#f&dQ_;}E}fKRRX0Oco<0ocuZ z$$z;L=u*o!CN%heiW43H3vG%B?rf5Bppvn3|B2+=mQn}w=Nfem_nk(b$DJS8aN&&9 z-<0_sZ|jrIjWcm|BU-FBp5KVs#cyf+zIL;};qkM!xpwgTA1*gl2s2e!47KNLENRbpCB`=u=nHQMyEBFt3BWZe(oJgMha3+6J+3eV|Md{ulp`E;V^-}P@&OnyITm|++EzbfB% z;m`5(ER?a~;;-~uZIA1?3Y)HX7ygNCnHE*3V!=JBVQoIJY(ue8he!tVgk2TW0pLMz zp8|spxG+;bO1e@po&b(e7tB${6;}{r2P$Jlt1L8+V;J>^RneGf##CUw!jTI`HHUDz zfZm4C&;UqSjR5k@BG4jBax}+20zjQRi@J~4$L!nKU@SLA#wE|>qgdmc$E6e0#MaCe zsm473ToWh7VQv1&N4Gx@t4xpPR(Xv!B7^-vJ~?Vbf*PlLY0cj%)5izB+p)D|rf)H!kk?A&@ZA|aGuw_j>#QR4U=epR&skmQ|o+t5rco*VkN}fYp({G8K zHaP`#ET^P#3V&=E-7s=CB~S4Yt#=t)QhrG!s{#&YPw|xD^J)Bi%0%(WG{v98&u&u{ zAwHNgPjcJ%l+kmpr)GP~(_3t1Qx|RtbuxfVFQ$el(2?S`EHzp|r+dTQ*y9&dnIfPN z^L2RZ)AyWPX&6~0BfP>+1mbfZw`-?uY^Q62u;F?vuNq>}PUBU$hS?wyTM2MTgPfXH zV-xX7bohK?pW>$>aI8UT#{AHj0X@jO@o5YxKDGgI*Ua%|;2;s1Bu@-pf(~e`%V~VN zH{l8|DoN%lrNtkKmmG0t?A8{mENyK%IvSf=JQ)j1rjQ7rEGWwa0@1Q1Nwbb|G?|Pu;r%2@@yGDP;0&ie8)MeO`mxTOi zKD%OHiYa~v*ldBVursuR_0Ymo+79G9IN5V7Art$z4%Kdjy;Xu99(nbZ_6p^V5z>ST zxdyS}Is>3L;wNNrMV`OrTEqRH{|;A%w0xv*JfY^*u;HRyxt`L$&Fz)med*Jf+cdmo zmZ;$y$ns$x;U*(p6#yBZF}%%v-1wTp7pF|)cfK7NLR6yEq?ADJbuM17J3VeZvf$BG z4WPTI+U(Z>kG`}h1e#G_tL`GfiE1xCO=z>*Qc(leH)}a_YixW553tML_t*POgkl^T zVseiS?=t#a7+V@@z|+Q*cK5%Okj z$yCbdUp^SwdHR4>HtEKOeMR1^uobX>DSRc1_mc!9^kBeDa_~`pk&Zq@iB33KR*5RaFl*c>1WT-36 z7HP)5dP0i&&T7_%`eYs}dM<62a@K@Jc~Z_<3%T=GVJoIPsp%E?HKzZjH!bK*vue&x zp1VIVH$KhMoI1*VyRe$g+fg$#vjrPiKTOrns=b~vGz)$m=q*^inv0(#j?=^iXwRbu zwXvj2@^^ttpnedQv=&$NKF~ol2FKslu!kG3t`*bS1j3vQ-_AwUX%Z za$@&8W=S25j95az_~@CG7Ok0s4w<-24ka@gday^M(+sZYchP~E)jZd)sz>wA5AUJg zMm^=68l>$kWhmxJKPK`y1W~_w&da`oUqM-ReN(MEw?5dITF$5F{W*SPmXiMsEi5g) z0xfF}P(72we30rS@Y6s$_5Kz;ypJubfPKl$&r7?}(or)Z`4g}u58Ubr^}*jn2VnBP zJT$ubn^0J?D{$%T8@NmLpk~P*qT@u$COS1?o761oiB2lGgZTTA&cg1TV*D+GE0^aD zw3YE=Lk|`k%e|F)QxJ3)vr(+6US;}`L4)2hjPw26v~mEwyu=70yJsyi(iA> z^d>aX>y#?yO=vvc?6;vM-f-)Y4Q+;AH}`=3-KtfW!chFy}n3d zuE8hBp_0?nK#8AAs06cS$uf9Uh~tz!Fm}y%lHlIw&zF{#moXo6-FzcbOH1wc8cDl7 z%Xc9@_~4JZoRgSw<{Q_70PZ$OJkMM=-=BZJw$|xvYI*RWTAj}Y_gs*)T6lV=15eF3 z^F5g$It78ub@L6Xag6xWTsPl;$OSGucwhnxZy_eGCZmSm$Qzh!?10B$vXnvuN~M4b zK_fz?>c5npH*pUuv4}-PDg+T`QEM|^kur)7qJFp=`obqWLXbx*!Fq5vxGN(WCJBuY zsnUdgc^CDXU4iUVbmrWuJMYyzg>SMa>T`FO{M%t)*dGGHW~{N=SYM_JjPN6k$ksSjJ;Kn zSvVBXQ;NS3XJ=UxyQGIVphq{4emnZ*=$+9! z0gb;TJtI9A6QN=^FXv^AbV1g^DJb{}O&7G*nWMxg;gKT$U;un-EF%BR0Qhr2+7~;d z9{nR-Azhc72fse}5}abyo)V{^m^~Dnf_|hGyjRTMmP$hqz!Dh@2F1#z{-Vd3TPX58 z5~+NNNXaV~pMb$j)-7d8I@38;*@dN96K1@*&SQ=D9|?>n?y(Oq9dAay{QKgf?4L*R z$I8YEhsvZ;_iFCETXp8Zl@srT>dQIlnR7{stfh72Fsq?PoWx_QFI-`E!#l#x9mRRD zLz(OA>>|T*lQOq1i3VpUUf^!20HQS$Eh}MUxU_!)kx|Y?ZRh8#T zk$L`AWS)P$Jj>>47-AIr$De8x`=?d{?kxL5<;1!IoMXTdfPaXAi2&@I2;d3IzKH-m z0X@UE=hb9t{|Bee9Pn%6j=g@v^c`YYJ!!`4QmV#Co$-qFg8DV{7d;64#PfNLa1T?@ z=QUP^t!1$+?r3d`w(xHR?+0&beLHyDSJ;-=A}g>!{1}jSr+=bVN*1^-ac#o@bqk;beeenzoAY^D8*uHan7bHn-v_A9oO?R&HKo9G%n)wu?W$Et3;H-2~WyUEXw zZXVu1&zz{*c2UVF3Sf3xM{S!{QD=+Jc@m@66`hl61of#@b+@9w5$9;vq}WT9GFg06 zyh*GWJ%Y1MvJ{{=Bb)qbomXYQQ(I{N#ixFDtVu|Rzt{e50mNnQ4z zu50DaAYJpHb47hcD^@STWJG+9T*fq!N1xL|)?Nb7^u6*M)*KW#sE>u%j;<&&A z;+Bmo)>wNR#MZ_S-ygg+7!>1?JsVfqv&JKCB^;5qaJH1YCyTvT@eF&s|!ys_>uIG)1s@KHi$_@l^BZOsc?n{W5%<2bJCJ!Y@Xhgl$f`0lX>>7@NYDF{1_HYWY*U1--iWrK6Oh;uQwj^^Is_G zbeekpj)Nz-uCbqGu$`u6WjYS5udbTz%>M1~r|FmiZVSaUKLfzCo;=yxv+<3McAI_R z&sM8^hBq9R&-lh;^~RfOUGG0Ezj3WE|NeIl_ z9*?Nn1VeXa~ifgpp>oDHy-MZ!b-R{K& zkL`3`yojQ$t!lLax?4g;+NvJK%E)L_mXO-d#&0v!r$Y&k^oMXM4@l`?B$pMjLW}6X zS6B3QewC8>R1#ao+}tbk&fF_h7Vu&wVAGR3K|eU~gT6GC0c9l$*G2MI`S_$KM{;s` zmchV>;{IYstcm)3&4B^-Z+e{mGyWuM6Sr`XgI6uT{`>acl_MK{5`C&eo9d-_E4~xo zN&Pg)$XqsaK+6Xz`5c6pPutNnlz*n;pybls^DBXPNIX`;r-fc^r$W1GI(Jp`OtWM& zsn7%iogWiLyYdLt*QLy|B#C461?>HCn(BFt297Oh)Ra$qabXk(odx_(Xb%+2 zkj_nJ1c8GZDd6(?8^34ZS#P|tynO9imE_tr&yz{|<<;TU>D2}4X_jnnGfz#j6+|sPP!>p(Csis94num zCdo8~W=ZG6^(|s}4ev)dqc!s|^D^J?jLy^iAHs3G9LIw}j?cVN@bx|U54j0MSW%aRG%w;gX%M_D8{LbS@pTqy1t0r z?=Kh@!{PBU`0&+NJf8a7wqNrbeuHm#Nq?i~LmB^me}jLmx_-R&Z#c}d4T`K?;3=y2 zXzsb3QPgY^HHw-g59k=l7V#H)m9^wdp4qUZ@ihw;;}P|T?c$c%{&3S-y)Hi~@Y(w7 zH>m!H1^&JIzu2nFzZLjw{ipsG$-@HwUVp21L#iCP%=S0rRrYh3PP@zfiP{Sl#{!@2 GFaHBIqLwfK literal 0 HcmV?d00001 diff --git a/snes/regdump/tools/padbin.exe b/snes/regdump/tools/padbin.exe new file mode 100644 index 0000000000000000000000000000000000000000..dcd84809309d153d1ce260cda1d5b79fcf7bf676 GIT binary patch literal 16095 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 literal 0 HcmV?d00001