Skip to content

Commit

Permalink
Autosave/load state, Zoom window, Proper fullscreen aspect ratio, Sav…
Browse files Browse the repository at this point in the history
…e settings to file

Merges PR snesrev#7 and some of PR snesrev#21 (without the move from C/C++ to C99):
* Get SDL from Nuget
* Makefile
* Add F11 as Fullscreen toggle
* Handle gamepad and keyconf.yaml mapping
* Convert *.py to unix (LF, shebang, +x)

Additionally:
* Optional autosave on quit, autoload on start
* Autozoom to best size for screen, or change zoom manually
* Keep proper ratio in fullscreen
* Save settings to config.yaml
* In addition to key changes from PR snesrev#21 , also:
  Esc to quit
  Ctrl+P or Pause/Break to pause
  +/- to change zoom
  F11 or Alt+Enter to toggle fullscreen
  PgUp/PgDn/Home to navigate stages in saves/ref/
  • Loading branch information
Nutzzz committed Aug 31, 2022
1 parent 11219f9 commit 7240ef9
Show file tree
Hide file tree
Showing 16 changed files with 584 additions and 92 deletions.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
/.vs/
/.vscode/
/packages/
.DS_Store
*.dSYM
*.sfc
*.user
/Debug
/Release
/x64
Expand All @@ -11,3 +14,6 @@
/tables/old/
/saves/*.sav
__pycache__
*.o
*.exe
*.out
21 changes: 21 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
TARGET_EXEC:=zelda3
ROM:=tables/zelda3.sfc
SRCS:=$(wildcard *.c snes/*.c)
OBJS:=$(SRCS:%.c=%.o)
GEN:=$(shell grep -hor tables/generated.*.h --include \*.c)
CFLAGS:=${CFLAGS} $(shell sdl2-config --cflags)
LDFLAGS:=${LDFLAGS} $(shell sdl2-config --libs)

# first target is the default one
$(TARGET_EXEC): tables/generated_dialogue.h $(OBJS)
$(CC) $(OBJS) -o $@ $(LDFLAGS)
$(GEN): tables/dialogue.txt
cd tables; ./compile_resources.py ../$(ROM)
tables/dialogue.txt:
cd tables; ./extract_resources.py ../$(ROM)

clean: clean_obj clean_gen
clean_obj:
$(RM) $(OBJS) $(TARGET_EXEC)
clean_gen:
$(RM) $(GEN)
63 changes: 48 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,23 @@ It's around 70-80kLOC of C/C++ code, and reimplements all parts of the original

You need a copy of the ROM to extract game resources (levels, images). Then once that's done, the ROM is no longer needed.

It uses the PPU and DSP implementation from LakeSnes. Additionally, it can be configured to also run the original machine code side by side. Then the RAM state is compared after each frame, to verify that the C++ implementation is correct.
It uses the PPU and DSP implementation from [LakeSnes](https://github.com/elzo-d/LakeSnes). Additionally, it can be configured to also run the original machine code side by side. Then the RAM state is compared after each frame, to verify that the C++ implementation is correct.

I got much assistance from spannierism's Zelda 3 JP disassembly and the other ones that documented loads of function names and variables.

## Dependencies

- the `libsdl2-dev` library (ubuntu: `apt install libsdl2-dev`, macOS: `brew install sdl2`)
- a `tables/zelda3.sfc` USA ROM file (for asset extraction step only)
- The `pillow` and `pyyaml` python dependencies used by assets extractor

## Compiling

Put the ROM in tables/zelda3.sfc

`cd tables`
```
cd tables; pip install pillow pyyaml
```

Install python dependencies: `pip install pillow` and `pip install pyyaml`

Expand All @@ -34,6 +42,21 @@ Build the .sln file with Visual Studio
Make sure you are in the root directory.

`clang++ -I/usr/include/SDL2 -lSDL2 -O2 -ozelda3 *.cpp snes/*.cpp`
```sh
make
```

You can set `make` variables to use custom compilation flags or custom compiler:

```sh
make # will use default compiler
CC=gcc make
CC=clang make
CFLAGS=-O2 make
CFLAGS=-DSDL_DISABLE_IMMINTRIN_H CC=tcc make
CFLAGS=-DSDL_DISABLE_IMMINTRIN_H CC=chibicc make # also need SDL.h tweaking
CFLAGS=-m32 LDFLAGS=-m32 make # compile and link as x86 executable
```


## Usage and controls
Expand All @@ -57,23 +80,33 @@ The game is run with `./zelda3` and takes an optional path to the ROM-file, whic
| L | D |
| R | C |

This mapping can be configured using the [keyconf.yaml](keyconf.yaml) file. Some settings can be configured using the [config.yaml](config.yaml) file.

Additionally, the following commands are available:

| Key | Action |
| --- | --------------------- |
| W | Fill health/magic |
| E | Hard reset |
| P | Pause |
| T | Toggle replay turbo |
| K | Clear all input history from current snapshot |
| F1-F10 | Load snapshot |
| Shift+F1-F10 | Save snapshot |
| Ctrl+F1-F10 | Replay the snapshot |

Additionally, there are a bunch of included playthrough snapshots that play all dungeons of the game. You access them with the digit keys. If you want to replay the stage in turbo mode, press Ctrl+Digit (eg Ctrl-5).
| Key | Action |
| ---------------- | ---------------------- |
| Esc | Quit |
| Ctrl+R | Hard reset |
| Ctrl+P or Pause | Pause |
| +/- | Zoom in/out window |
| F11 or Alt+Enter | Toggle fullscreen |
| Ctrl+T | Toggle replay turbo |
| Ctrl+W | Fill health/magic |
| Ctrl+O | Set dungeon keys to 1 |
| Ctrl+K | Clear all input history from current snapshot |
| F1-F10 | Load user snapshot |
| Shift+F1-F10 | Save user snapshot |
| Ctrl+F1-F10 | Replay user snapshot |
| PgUp/PgDn | Load prev/next stage (1-13) |
| Home | Restart stage |
| Ctrl+Home | Replay stage |

Note the smallest window zoom is an autozoom to the largest integer scale for the screen.

The included playthrough snapshots of all stages of the game in [./saves/ref/](saves/ref/) can be loaded with the square bracket keys ( \[/\] ). If you want to replay the stage in turbo mode, press Ctrl + \\.


## License

This project is licensed under the MIT license. See 'LICENSE.txt' for details.
This project is licensed under the MIT license. See [LICENSE.txt](LICENSE.txt) for details.
15 changes: 15 additions & 0 deletions config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Zelda3 user configuration file

# default (same as removing this file)
#dungeon: 1 # dungeon in "saves/ref/" to load/replay; 1 to 13
#zoom: -1 # zoom 512x480 window; -1 to 20, where -1=autosize, 0=50%, 1=100%, 2=200%, 3=300%, etc.
#fullscreen: 0 # launch in fullscreen; 0=false, 1=true
#autosave: 1 # automatically save state on quit, and load on start; 0=false, 1=true
#hide_wincmd: 1 # hide debug window (Windows only); 0=false, 1=true


dungeon: 1
zoom: -1
fullscreen: 0
autosave: 1
hide_wincmd: 1
32 changes: 32 additions & 0 deletions keyconf.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# SNES to Key config file
# SDL list at https://github.com/libsdl-org/SDL/blob/main/include/SDL_keycode.h
# Symbols need a 0x40000000 mask over their value

# AZERTY example
#A: 120 # 'x'
#B: 119 # 'w'
#X: 115 # 's'
#Y: 113 # 'q'
#Up: 0x40000052
#Down: 0x40000051
#Left: 0x40000050
#Right: 0x4000004F
#Select: 0x400000e5
#Start: 13 # ENTER
#L: 100 # 'd'
#R: 99 # 'c'


# default (same as removing this file)
A: 120 # 'x'
B: 122 # 'z'
X: 115 # 's'
Y: 97 # 'a'
Up: 0x40000052 # UP
Down: 0x40000051 # DOWN
Left: 0x40000050 # LEFT
Right: 0x4000004F # RIGHT
Select: 0x400000e5 # RSHIFT
Start: 13 # ENTER
L: 100 # 'd'
R: 99 # 'c'
Loading

0 comments on commit 7240ef9

Please sign in to comment.