├── .editorconfig ├── .github └── workflows │ └── create-release.yml ├── .gitignore ├── LICENSE ├── Makefile ├── Makefile.targets ├── README.md ├── assets ├── 2bitpxlr.png └── pxlr.sav ├── include ├── analysis.h ├── bankedData.h ├── bleep.h ├── branch.h ├── camera.h ├── debug.h ├── defines.h ├── dialog.h ├── expose.h ├── flasher.h ├── gallery.h ├── gbcamera.h ├── globals.h ├── imageIndexing.h ├── imageInfo.h ├── images.h ├── joypad.h ├── mainLoop.h ├── mainMenu.h ├── menus │ ├── imageMenuItems.h │ ├── mainMenuItems.h │ ├── shootingAssistedMenuItems.h │ └── shootingManualMenuItems.h ├── modeShootingAssisted.h ├── modeShootingBurst.h ├── modeShootingManual.h ├── overlays │ ├── overlayDefs.h │ └── overlays.h ├── printCmd.h ├── remote.h ├── saveImage.h ├── splash.h ├── systemdetect.h ├── typedefs │ ├── AssistedOption.h │ ├── Histogram.h │ ├── Image.h │ ├── MenuItem.h │ ├── MenuOption.h │ └── Overlay.h ├── utils.h ├── values.h ├── valuesAssisted.h └── valuesDefs.h ├── res ├── font.c ├── font.h ├── gfx │ ├── gb │ │ └── backgrounds │ │ │ ├── frame_pxlr.png │ │ │ ├── frame_pxlr.png.meta │ │ │ ├── logo.png │ │ │ ├── logo.png.meta │ │ │ ├── wild_bottom.png │ │ │ ├── wild_bottom.png.meta │ │ │ ├── wild_center.png │ │ │ ├── wild_center.png.meta │ │ │ ├── wild_top.png │ │ │ └── wild_top.png.meta │ └── gbc │ │ └── backgrounds │ │ ├── frame_pxlr.png │ │ ├── frame_pxlr.png.meta │ │ ├── logo.png │ │ ├── logo.png.meta │ │ ├── wild_bottom.png │ │ ├── wild_bottom.png.meta │ │ ├── wild_center.png │ │ ├── wild_center.png.meta │ │ ├── wild_top.png │ │ └── wild_top.png.meta ├── maps.c ├── maps.h ├── nope.c ├── nope.h ├── tiles.c └── tiles.h ├── src ├── analysis.c ├── bankedData.c ├── bleep.c ├── camera.c ├── debug.c ├── dialog.c ├── expose.c ├── flasher.c ├── gallery.c ├── globals.c ├── imageIndexing.c ├── imageInfo.c ├── images.c ├── joypad.c ├── main.c ├── mainLoop.c ├── mainMenu.c ├── menus │ ├── imageMenuItems.c │ ├── mainMenuItems.c │ ├── shootingAssistedMenuItems.c │ └── shootingManualMenuItems.c ├── modeShootingAssisted.c ├── modeShootingBurst.c ├── modeShootingManual.c ├── overlays │ ├── overlayDefs.c │ └── overlays.c ├── printCmd.c ├── remote.c ├── saveImage.c ├── sm83 │ └── flasher_s.s ├── splash.c ├── systemdetect.c ├── utils.c ├── values.c └── valuesAssisted.c ├── temp └── gbdk-2020-Linux-x64.tar.gz ├── utils ├── dump2vgm.py ├── fxhammer2data.py ├── romusage.py ├── vgm2data.py └── wav2data.py └── version /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = crlf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.github/workflows/create-release.yml: -------------------------------------------------------------------------------- 1 | name: Create Release 🛳 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | 7 | jobs: 8 | build-and-deploy: 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | - name: Checkout 💳 13 | uses: actions/checkout@v2.3.1 14 | 15 | - name: Add release version to environment variables 🌍 16 | run: echo RELEASE_VERSION=$(> $GITHUB_ENV 17 | 18 | - name: Check if tag already exists 🏷 19 | id: checkTag 20 | uses: mukunku/tag-exists-action@v1.0.0 21 | with: 22 | tag: ${{ env.RELEASE_VERSION }} 23 | env: 24 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 25 | 26 | - name: Download and install GBDK 🛠 27 | if: steps.checkTag.outputs.exists == 'false' 28 | run: | 29 | tar -xf temp/gbdk-2020-Linux-x64.tar.gz gbdk/bin gbdk/include gbdk/lib 30 | echo GBDK_FOLDER=gbdk >> $GITHUB_ENV 31 | 32 | - name: Make 🧱 33 | if: steps.checkTag.outputs.exists == 'false' 34 | run: make 35 | 36 | - name: Create archive for release 🗄 37 | if: steps.checkTag.outputs.exists == 'false' 38 | run: | 39 | mkdir release 40 | cp build/gb/pxlr.gb release/pxlr.gb 41 | cp build/gbc/pxlr.gbc release/pxlr.gbc 42 | cp build/gb/pxlr.sav release/pxlr.sav 43 | 44 | - name: Create GitHub Release 🥳 45 | uses: softprops/action-gh-release@v1 46 | if: steps.checkTag.outputs.exists == 'false' 47 | with: 48 | tag_name: ${{ env.RELEASE_VERSION }} 49 | name: Version ${{ env.RELEASE_VERSION }} 50 | files: | 51 | release/pxlr.gb 52 | release/pxlr.gbc 53 | release/pxlr.sav 54 | 55 | - name: Create itch.io release 🎉 56 | if: steps.checkTag.outputs.exists == 'false' 57 | uses: manleydev/butler-publish-itchio-action@master 58 | env: 59 | BUTLER_CREDENTIALS: ${{ secrets.BUTLER_CREDENTIALS }} 60 | CHANNEL: gameboy 61 | ITCH_GAME: 2bit-pxlr-studio 62 | ITCH_USER: ${{ secrets.ITCHIO_USER }} 63 | PACKAGE: release 64 | VERSION_FILE: version 65 | 66 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /obj 2 | .idea 3 | /include/generated 4 | /pxlr.zip 5 | /release 6 | /build 7 | /cmake-build-debug/ 8 | /CMakeLists.txt 9 | unused 10 | .vscode 11 | /*.bat 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Andreas Hahn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SHELL := /bin/bash 2 | 3 | # If you move this project you can change the directory 4 | # to match your GBDK root directory (ex: GBDK_HOME = "C:/GBDK/" 5 | 6 | GBDK_HOME = $(GBDK_FOLDER)/ 7 | #GBCPU = gbz80 8 | 9 | #GBDK_HOME = ../../../gbdk-2020/build/gbdk/ 10 | GBCPU = sm83 11 | 12 | LCC = $(GBDK_HOME)bin/lcc 13 | PNG2ASSET = $(GBDK_HOME)bin/png2asset 14 | 15 | START_SAVE = 12 16 | 17 | # Set platforms to build here, spaced separated. (These are in the separate Makefile.targets) 18 | # They can also be built/cleaned individually: "make gg" and "make gg-clean" 19 | # Possible are: gb gbc pocket sms gg 20 | #TARGETS = gb gbc pocket sms gg 21 | TARGETS = gb gbc 22 | 23 | #LIBRARIES = -Wl-llib/$(PORT)/hUGEDriver.lib 24 | LIBRARIES = 25 | 26 | # Configure platform specific LCC flags here: 27 | LCCFLAGS_gb = $(LIBRARIES) -Wl-yt0xFC -Wm-yn"$(PROJECTNAME)" 28 | LCCFLAGS_pocket = $(LIBRARIES) -Wl-yt0xFC -Wm-yn"$(PROJECTNAME)" 29 | LCCFLAGS_gbc = $(LIBRARIES) -Wl-yt0xFC -Wm-yc -Wm-yn"$(PROJECTNAME)" 30 | LCCFLAGS_sms = 31 | LCCFLAGS_gg = 32 | 33 | LCCFLAGS += -Wl-g.start_save=$(START_SAVE) $(LCCFLAGS_$(EXT)) -Wm-yS # This adds the current platform specific LCC Flags 34 | 35 | LCCFLAGS += -Wl-j -Wm-yoA -Wm-ya16 -autobank -Wb-ext=.rel 36 | # LCCFLAGS += -debug # Uncomment to enable debug output 37 | # LCCFLAGS += -v # Uncomment for lcc verbose output 38 | 39 | CFLAGS += -Iinclude -Iinclude/$(PORT) -Iinclude/$(PLAT) -I$(RESDIR) -Iobj/$(EXT) 40 | 41 | BRANCH = $(shell git rev-parse --abbrev-ref HEAD) 42 | VERSION = $(shell cat version) 43 | CFLAGS += -DBRANCH=$(BRANCH) -DVERSION=$(VERSION) 44 | 45 | # You can set the name of the ROM file here 46 | PROJECTNAME = pxlr 47 | 48 | # EXT?=gb # Only sets extension to default (game boy .gb) if not populated 49 | SRCDIR = src 50 | SRCPORT = src/$(PORT) 51 | SRCPLAT = src/$(PLAT) 52 | OBJDIR = obj/$(EXT) 53 | RESDIR = res 54 | BINDIR = build/$(EXT) 55 | MKDIRS = $(OBJDIR) $(BINDIR) # See bottom of Makefile for directory auto-creation 56 | 57 | BINS = $(OBJDIR)/$(PROJECTNAME).$(EXT) 58 | 59 | VGM_RES = $(foreach dir,$(RESDIR),$(notdir $(wildcard $(dir)/audio/$(PLAT)/sounds/*.vgm))) 60 | FX_RES = $(foreach dir,$(RESDIR),$(notdir $(wildcard $(dir)/audio/$(PLAT)/sounds/*.sav))) 61 | UGE_RES = $(foreach dir,$(RESDIR),$(notdir $(wildcard $(dir)/audio/$(PLAT)/music/*.uge))) 62 | WAV_RES = $(foreach dir,$(RESDIR),$(notdir $(wildcard $(dir)/audio/$(PLAT)/waveforms/*.wav))) 63 | 64 | SPR_RES = $(foreach dir,$(RESDIR),$(notdir $(wildcard $(dir)/gfx/$(EXT)/sprites/*.png))) 65 | BKG_RES = $(foreach dir,$(RESDIR),$(notdir $(wildcard $(dir)/gfx/$(EXT)/backgrounds/*.png))) 66 | 67 | CSOURCES = $(foreach dir,$(SRCDIR),$(notdir $(wildcard $(dir)/*.c))) $(foreach dir,$(SRCPLAT),$(notdir $(wildcard $(dir)/*.c))) $(foreach dir,$(SRCPORT),$(notdir $(wildcard $(dir)/*.c))) $(foreach dir,$(RESDIR),$(notdir $(wildcard $(dir)/*.c))) $(foreach dir,$(RESDIR),$(notdir $(wildcard $(dir)/audio/$(PLAT)/*.c))) $(foreach dir,$(SRCDIR),$(notdir $(wildcard $(dir)/menus/*.c))) $(foreach dir,$(SRCDIR),$(notdir $(wildcard $(dir)/overlays/*.c))) 68 | ASMSOURCES = $(foreach dir,$(SRCDIR),$(notdir $(wildcard $(dir)/*.s))) $(foreach dir,$(SRCPLAT),$(notdir $(wildcard $(dir)/*.s))) $(foreach dir,$(SRCPORT),$(notdir $(wildcard $(dir)/*.s))) 69 | 70 | OBJS = $(CSOURCES:%.c=$(OBJDIR)/%.o) $(ASMSOURCES:%.s=$(OBJDIR)/%.o) 71 | RESOBJ = $(VGM_RES:%.vgm=$(OBJDIR)/%.o) $(WAV_RES:%.wav=$(OBJDIR)/%.o) $(FX_RES:%.sav=$(OBJDIR)/%.o) $(UGE_RES:%.uge=$(OBJDIR)/%.o) $(SPR_RES:%.png=$(OBJDIR)/%.o) $(BKG_RES:%.png=$(OBJDIR)/%.o) 72 | 73 | DEPENDANT = $(CSOURCES:%.c=$(OBJDIR)/%.o) 74 | 75 | # Builds all targets sequentially 76 | all: $(TARGETS) 77 | 78 | # Dependencies 79 | DEPS = $(DEPENDANT:%.o=%.d) 80 | 81 | -include $(DEPS) 82 | 83 | .SECONDEXPANSION: 84 | $(OBJDIR)/%.c: $(RESDIR)/audio/$(PLAT)/sounds/%.vgm $$(wildcard $(RESDIR)/audio/$(PLAT)/sounds/%.vgm.meta) 85 | python utils/vgm2data.py -5 -w -3 -d 4 -b 255 `cat <$<.meta 2>/dev/null` -o $@ $< 86 | 87 | .SECONDEXPANSION: 88 | $(OBJDIR)/%.c: $(RESDIR)/audio/$(PLAT)/sounds/%.sav $$(wildcard $(RESDIR)/audio/$(PLAT)/sounds/%.sav.meta) 89 | python utils/fxhammer2data.py -d 4 -c -b 255 `cat <$<.meta 2>/dev/null` -o $@ $< 90 | 91 | $(OBJDIR)/%.c: $(RESDIR)/audio/$(PLAT)/music/%.uge 92 | utils/uge2source $< -b 255 $(basename $(notdir $<)) $@ 93 | 94 | $(OBJDIR)/%.c: $(RESDIR)/audio/$(PLAT)/waveforms/%.wav 95 | python utils/wav2data.py -b 255 -o $@ $< 96 | 97 | $(OBJDIR)/%.o: $(RESDIR)/audio/$(PLAT)/%.c 98 | $(LCC) $(CFLAGS) -c -o $@ $< 99 | 100 | 101 | .SECONDEXPANSION: 102 | $(OBJDIR)/%.c: $(RESDIR)/gfx/$(EXT)/sprites/%.png $$(wildcard $(RESDIR)/gfx/$(EXT)/sprites/%.png.meta) 103 | $(PNG2ASSET) $< -c $@ `cat <$<.meta 2>/dev/null` -spr8x16 -b 255 104 | 105 | .SECONDEXPANSION: 106 | $(OBJDIR)/%.c: $(RESDIR)/gfx/$(EXT)/backgrounds/%.png $$(wildcard $(RESDIR)/gfx/$(EXT)/backgrounds/%.png.meta) 107 | $(PNG2ASSET) $< -c $@ -map `cat <$<.meta 2>/dev/null` -b 255 108 | 109 | 110 | $(OBJDIR)/%.o: $(OBJDIR)/%.c 111 | $(LCC) $(CFLAGS) -c -o $@ $< 112 | 113 | # Compile .c files in "res/" to .o object files 114 | $(OBJDIR)/%.o: $(RESDIR)/%.c 115 | $(LCC) -Wf-MMD $(CFLAGS) -c -o $@ $< 116 | 117 | 118 | # Compile .c files in "src/" to .o object files 119 | $(OBJDIR)/%.o: $(SRCDIR)/%.c 120 | $(LCC) -Wf-MMD $(CFLAGS) $(filter -Wf-ba%, $(subst .d,-Wf-ba,$(suffix $(<:%.c=%)))) -c -o $@ $< 121 | 122 | # Compile .c files in "src/menus/" to .o object files 123 | $(OBJDIR)/%.o: $(SRCDIR)/menus/%.c 124 | $(LCC) -Wf-MMD $(CFLAGS) $(filter -Wf-ba%, $(subst .d,-Wf-ba,$(suffix $(<:%.c=%)))) -c -o $@ $< 125 | 126 | # Compile .c files in "src/overlays/" to .o object files 127 | $(OBJDIR)/%.o: $(SRCDIR)/overlays/%.c 128 | $(LCC) -Wf-MMD $(CFLAGS) $(filter -Wf-ba%, $(subst .d,-Wf-ba,$(suffix $(<:%.c=%)))) -c -o $@ $< 129 | 130 | # Compile .s assembly files in "src/" to .o object files 131 | $(OBJDIR)/%.o: $(SRCDIR)/%.s 132 | $(LCC) $(CFLAGS) -c -o $@ $< 133 | 134 | # Compile .c files in "src//" to .o object files 135 | $(OBJDIR)/%.o: $(SRCPLAT)/%.c 136 | $(LCC) -Wf-MMD $(CFLAGS) -c -o $@ $< 137 | 138 | # Compile .s assembly files in "src//" to .o object files 139 | $(OBJDIR)/%.o: $(SRCPLAT)/%.s 140 | $(LCC) $(CFLAGS) -c -o $@ $< 141 | 142 | 143 | # Compile .c files in "src//" to .o object files 144 | $(OBJDIR)/%.o: $(SRCPORT)/%.c 145 | $(LCC) -Wf-MMD $(CFLAGS) -c -o $@ $< 146 | 147 | # Compile .s assembly files in "src//" to .o object files 148 | $(OBJDIR)/%.o: $(SRCPORT)/%.s 149 | $(LCC) $(CFLAGS) -c -o $@ $< 150 | 151 | 152 | # Link the compiled object files into a .gb ROM file 153 | $(BINS): $(RESOBJ) $(OBJS) 154 | $(LCC) $(LCCFLAGS) $(CFLAGS) -o $(BINDIR)/$(PROJECTNAME).$(EXT) $^ 155 | @cp assets/pxlr.sav $(BINDIR)/pxlr.sav 156 | 157 | clean: 158 | @echo Cleaning 159 | @for target in $(TARGETS); do \ 160 | $(MAKE) $$target-clean; \ 161 | done 162 | 163 | # Include available build targets 164 | include Makefile.targets 165 | 166 | 167 | # create necessary directories after Makefile is parsed but before build 168 | # info prevents the command from being pasted into the makefile 169 | ifneq ($(strip $(EXT)),) # Only make the directories if EXT has been set by a target 170 | $(info $(shell mkdir -p $(MKDIRS))) 171 | endif 172 | -------------------------------------------------------------------------------- /Makefile.targets: -------------------------------------------------------------------------------- 1 | 2 | # Platform specific flags for compiling (only populate if they're both present) 3 | ifneq ($(strip $(PORT)),) 4 | ifneq ($(strip $(PLAT)),) 5 | CFLAGS += -m$(PORT):$(PLAT) 6 | endif 7 | endif 8 | 9 | # Called by the individual targets below to build a ROM 10 | build-target: $(BINS) 11 | 12 | clean-target: 13 | rm -rf $(OBJDIR) 14 | rm -rf $(BINDIR) 15 | 16 | gb-clean: 17 | ${MAKE} clean-target EXT=gb 18 | gb: 19 | ${MAKE} build-target PORT=$(GBCPU) PLAT=gb EXT=gb 20 | 21 | gbc-clean: 22 | ${MAKE} clean-target EXT=gbc 23 | gbc: 24 | ${MAKE} build-target PORT=$(GBCPU) PLAT=gb EXT=gbc 25 | 26 | pocket-clean: 27 | ${MAKE} clean-target EXT=pocket 28 | pocket: 29 | ${MAKE} build-target PORT=$(GBCPU) PLAT=ap EXT=pocket 30 | 31 | 32 | sms-clean: 33 | ${MAKE} clean-target EXT=sms 34 | sms: 35 | ${MAKE} build-target PORT=z80 PLAT=sms EXT=sms 36 | 37 | 38 | gg-clean: 39 | ${MAKE} clean-target EXT=gg 40 | gg: 41 | ${MAKE} build-target PORT=z80 PLAT=gg EXT=gg 42 | 43 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 2bit PXLR Studio 2 | ![2bit PXLR Studio Logo](assets/2bitpxlr.png "2bit PXLR Studio") 3 | 4 | **2bit PXLR Studio** is a custom ROM ("firmware") for the Game Boy Camera targeted on accessing the full potential of the original Game Boy Camera's sensor, as well as giving photographers more control. 5 | It is meant to be used with [HDR's flashable Game Boy Camera PCB](https://github.com/HDR/Gameboy-Camera-Flashcart). 6 | For convenience there's also a [itch.io page](https://herrzatacke.itch.io/2bit-pxlr-studio). 7 | You can also tag your images with [#2bitpxlr](https://www.instagram.com/explore/tags/2bitpxlr/) or use the hashtag [#2bitpxlr](https://twitter.com/search?q=2bitpxlr) on Twitter. 8 | 9 | ## Current features: 10 | + Most settings of the camera's sensor are already configurable 11 | + Images can be saved, deleted and printed 12 | + Sensor settings are being saved across restarts. To reset hold `start`+`select` on boot 13 | 14 | # Feedback 15 | **Remember: I can only improve things I know about!!** 16 | If you have actually used this ROM any type of feedback is very much appreciated. Please provide any feedback [via the issues](https://github.com/HerrZatacke/custom-camera-rom/issues). 17 | Feedback includes but is not restricted to things like: 18 | + "I'd like to have feature XX" 19 | + "I've used the following combination of parameters which work really well/bad" 20 | + "When I set param XX, I'd also like param YY to change" 21 | 22 | # Building / Setup 23 | This project has been created with [GBDK 2020](https://github.com/gbdk-2020/gbdk-2020). 24 | This project requires an environment variable `GBDK_FOLDER="..."` pointing to the folder of GBDK 25 | E.g. on wsl for windows add `export GBDK_FOLDER="/mnt/c/path_to_gbdk"` to your `.bashrc` 26 | 27 | # Credits 28 | Thanks to the following people for direct and indirect help with this project: 29 | * [Toxa](https://github.com/untoxa) for a lot of help while refactoring, and for the GBDK in general. 30 | * [@rembrandx](https://www.instagram.com/rembrandx/) for the Logo/Splashcreen 31 | * [Raphaël Boichot](https://github.com/Raphael-Boichot/) for the in-depth analysis of the [Game Boy Camera's RAM structure](https://funtography.online/wiki/Cartridge_RAM) 32 | * [AntonioND](https://github.com/AntonioND) for the outstanding [Documentation regarding the camera's sensor](https://github.com/AntonioND/gbcam-rev-engineer) / [PDF](https://github.com/AntonioND/gbcam-rev-engineer/blob/master/doc/gb_camera_doc_v1_1_1.pdf) 33 | * [reini1305](https://github.com/reini1305) for the [print function](https://github.com/HerrZatacke/custom-camera-rom/commit/5976b47e6b6d577c954e2b678affa9925824f5b5) and general help with some C concepts 34 | * [Alex (insidegadgets)](https://github.com/insidegadgets) for figuring out the flickering issue and more 35 | * [All the folks from Game Boy Gamera Club Discord](https://discord.gg/C7WFJHG) for their support and ideas 36 | 37 | # Other resources 38 | - Mitsubishi [Sensor Datasheet](https://pdf1.alldatasheet.com/datasheet-pdf/view/146598/MITSUBISHI/M64282FP.html) 39 | 40 | # Contributing 41 | _This project is very much a work in progress._ 42 | Join the [Game Boy Gamera Club Discord](https://discord.gg/C7WFJHG) for discussions in detail. And feel free to check and add to [this project's issues](https://github.com/HerrZatacke/custom-camera-rom/issues) 43 | 44 | # License 45 | This project is released under the [MIT License](LICENSE) 46 | -------------------------------------------------------------------------------- /assets/2bitpxlr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HerrZatacke/2bit-pxlr-studio/77f579f5583927c10b787994f7ca01e389dd1660/assets/2bitpxlr.png -------------------------------------------------------------------------------- /assets/pxlr.sav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HerrZatacke/2bit-pxlr-studio/77f579f5583927c10b787994f7ca01e389dd1660/assets/pxlr.sav -------------------------------------------------------------------------------- /include/analysis.h: -------------------------------------------------------------------------------- 1 | #ifndef ANALYSIS_H 2 | #define ANALYSIS_H 3 | 4 | extern void createHistogram(uint8_t *data) BANKED; 5 | extern void getHistogram(uint8_t imageIndex, uint8_t *tileMap) BANKED; 6 | extern void displayHistogram(uint8_t imageIndex) BANKED; 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /include/bankedData.h: -------------------------------------------------------------------------------- 1 | #ifndef BANKEDDATA_H 2 | #define BANKEDDATA_H 3 | 4 | #include 5 | 6 | extern void set_bkg_tiles_banked(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t *map, uint8_t bank); 7 | extern void set_bkg_data_banked(uint8_t offset, uint8_t length, uint8_t *data, uint8_t bank); 8 | extern void set_data_banked(uint16_t *address, uint8_t *data, uint16_t length, uint8_t bank); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /include/bleep.h: -------------------------------------------------------------------------------- 1 | #ifndef BLEEP_H 2 | #define BLEEP_H 3 | 4 | #include 5 | 6 | extern void bleep() BANKED; 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /include/branch.h: -------------------------------------------------------------------------------- 1 | const uint8_t branch[] = { 2 | 0x66, 3 | 0x65, 4 | 0x61, 5 | 0x74, 6 | 0x75, 7 | 0x72, 8 | 0x65, 9 | 0x2F, 10 | 0x73, 11 | 0x74, 12 | 0x72, 13 | 0x75, 14 | 0x63, 15 | 0x74, 16 | 0x75, 17 | 0x72, 18 | 0x65, 19 | }; 20 | -------------------------------------------------------------------------------- /include/camera.h: -------------------------------------------------------------------------------- 1 | #ifndef CAMERA_H 2 | #define CAMERA_H 3 | 4 | extern void setDitherMatrix(uint8_t ditherSet, uint8_t contrast) BANKED; 5 | extern void initCam() BANKED; 6 | extern void capture(uint8_t capt, uint8_t edExOpGain, uint16_t expTime, uint8_t edRInvVref, uint8_t zeroVout) BANKED; 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /include/debug.h: -------------------------------------------------------------------------------- 1 | #ifndef DEBUG_H 2 | #define DEBUG_H 3 | 4 | #include 5 | 6 | extern void debugMenu() BANKED; 7 | extern void initDebug() BANKED; 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /include/defines.h: -------------------------------------------------------------------------------- 1 | #ifndef DEFINES_H 2 | #define DEFINES_H 3 | 4 | #define OFFSET_FONT 128u 5 | #define OFFSET_BLANK 128u 6 | #define OFFSET_TILES 219u 7 | #define OFFSET_FILL 219u 8 | #define OFFSET_MENU_ARROW 220u 9 | #define OFFSET_BORDER_H 221u 10 | #define OFFSET_BORDER_V 222u 11 | #define MENU_BORDER_LEFT 223u 12 | #define MENU_BORDER_TOP 224u 13 | #define OFFSET_BLEEP_CURSOR 225u 14 | 15 | #define SPRITE_MENU_INDICATOR 0 16 | #define SPRITE_BORDER_H_1 1 17 | #define SPRITE_BORDER_H_2 2 18 | #define SPRITE_BORDER_H_3 3 19 | #define SPRITE_BORDER_H_4 4 20 | #define SPRITE_BORDER_H_5 5 21 | #define SPRITE_BORDER_H_6 6 22 | #define SPRITE_BORDER_H_7 7 23 | #define SPRITE_BORDER_H_8 8 24 | #define SPRITE_BORDER_V_1 9 25 | #define SPRITE_BORDER_V_2 10 26 | #define SPRITE_BORDER_V_3 11 27 | #define SPRITE_BORDER_V_4 12 28 | #define SPRITE_BORDER_V_5 13 29 | #define SPRITE_BORDER_V_6 14 30 | #define SPRITE_BORDER_V_7 15 31 | #define SPRITE_BORDER_V_8 16 32 | #define SPRITE_BLEEP_CURSOR 17 33 | 34 | #define PALETTE_SPRITES 0b11100100u 35 | #define PALETTE_SPRITES_OVERLAYS 0b11100000u 36 | #define PALETTE_NORMAL 0b11100100u 37 | #define PALETTE_FADE_1 0b11111001u 38 | #define PALETTE_FADE_2 0b11111110u 39 | #define PALETTE_BLANK 0b11111111u 40 | #define PALETTE_INVERTED 0b00011011u 41 | 42 | #define MENU_TEXT_LENGTH 6 43 | 44 | #define MAIN_LOOP_MENU 0 45 | #define MAIN_LOOP_SHOOT_MANUAL 1 46 | #define MAIN_LOOP_SHOOT_BURST 2 47 | #define MAIN_LOOP_SHOOT_ASSISTED 3 48 | #define MAIN_LOOP_IMAGE_GALLERY 4 49 | #define MAIN_LOOP_IMAGE 5 50 | #define MAIN_LOOP_DELETE_ALL 6 51 | #define MAIN_LOOP_DEBUG 254 52 | #define MAIN_LOOP_NOT_IMPLEMENTED 255 53 | 54 | #define IMAGE_MENU_INFO 0 55 | #define IMAGE_MENU_HISTOGRAM 1 56 | #define IMAGE_MENU_DELETE 2 57 | #define IMAGE_MENU_PRINT 3 58 | #define IMAGE_MENU_BLEEP 4 59 | #define IMAGE_MENU_EXPOSE 5 60 | 61 | #define HALF_IMAGE_SIZE 1792 62 | #define VRAM_9000 (uint16_t *)0x9000 63 | #define VRAM_8000 (uint16_t *)0x8000 64 | 65 | #define THUMBNAIL_BYTE_CAPTURE 0x00 66 | #define THUMBNAIL_BYTE_EDGEGAINS 0x10 67 | #define THUMBNAIL_BYTE_EXPOSURE_HIGH 0x20 68 | #define THUMBNAIL_BYTE_EXPOSURE_LOW 0x30 69 | #define THUMBNAIL_BYTE_EDMOVOLT 0xC6 70 | #define THUMBNAIL_BYTE_VOUTZERO 0xD6 71 | #define THUMBNAIL_BYTE_DITHERSET 0xE6 72 | #define THUMBNAIL_BYTE_CONTRAST 0xF6 73 | 74 | #define yMenu(index) (index * 2) + 2 75 | #define yMenuSprite(index) (index * 16) + 31 76 | 77 | #endif 78 | -------------------------------------------------------------------------------- /include/dialog.h: -------------------------------------------------------------------------------- 1 | #ifndef DIALOG_H 2 | #define DIALOG_H 3 | 4 | #include 5 | 6 | void appearDialog() BANKED; 7 | void disappearDialog() BANKED; 8 | uint8_t dialog(uint8_t *message, uint8_t handleOverlays) NONBANKED; 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /include/expose.h: -------------------------------------------------------------------------------- 1 | #ifndef EXPOSE_H 2 | #define EXPOSE_H 3 | 4 | extern void expose() BANKED; 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /include/flasher.h: -------------------------------------------------------------------------------- 1 | #ifndef __FLASHER_H_INCLUDE 2 | #define __FLASHER_H_INCLUDE 3 | 4 | #include 5 | 6 | uint8_t flash_check_gallery_exist(uint8_t slot) NONBANKED; 7 | uint8_t flash_load_gallery_from_slot(uint8_t slot) BANKED; 8 | uint8_t flash_save_gallery_to_slot(uint8_t slot) BANKED; 9 | uint8_t flash_erase_slot(uint8_t slot) BANKED; 10 | 11 | #endif -------------------------------------------------------------------------------- /include/gallery.h: -------------------------------------------------------------------------------- 1 | #ifndef GALLERY_H 2 | #define GALLERY_H 3 | 4 | extern void appearImageMenu() BANKED; 5 | extern void loadAndShowGalleryImage() BANKED; 6 | extern void initGallery() BANKED; 7 | extern void initImageMenu() BANKED; 8 | extern void galleryMenu() BANKED; 9 | extern void imageMenu() BANKED; 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /include/gbcamera.h: -------------------------------------------------------------------------------- 1 | #ifndef __GBCAMERA_H_INCLUDE__ 2 | #define __GBCAMERA_H_INCLUDE__ 3 | 4 | #include 5 | #include 6 | 7 | #define CAMERA_MAX_IMAGE_SLOTS 30 8 | 9 | #define CAMERA_IMAGE_TILE_WIDTH 16 10 | #define CAMERA_IMAGE_TILE_HEIGHT 14 11 | 12 | #define CAMERA_THUMB_TILE_WIDTH 4 13 | #define CAMERA_THUMB_TILE_HEIGHT 4 14 | 15 | #define CAMERA_IMAGE_SIZE (CAMERA_IMAGE_TILE_WIDTH * CAMERA_IMAGE_TILE_HEIGHT * 16) 16 | #define CAMERA_THUMB_SIZE (CAMERA_THUMB_TILE_WIDTH * CAMERA_THUMB_TILE_HEIGHT * 16) 17 | 18 | #define CAMERA_MAGIC "Magic" 19 | 20 | typedef struct cam_game_data_t { 21 | uint8_t imageslots[CAMERA_MAX_IMAGE_SLOTS]; 22 | uint8_t magic[5]; 23 | uint8_t CRC_add; 24 | uint8_t CRC_xor; 25 | } cam_game_data_t; 26 | 27 | /* 28 | * Area 0x0000 to 0x1FFF in RAM 29 | * Using RAM Bank 0 30 | * Containing Last seen image, gameface data etc. 31 | */ 32 | 33 | //static uint8_t AT(0xA000) last_seen_upper_unused[256]; 34 | static uint8_t AT(0xA100) last_seen[CAMERA_IMAGE_SIZE]; 35 | static uint8_t AT(0xA100) last_seen_upper[CAMERA_IMAGE_SIZE >> 1]; 36 | static uint8_t AT(0xA800) last_seen_lower[CAMERA_IMAGE_SIZE >> 1]; 37 | //static uint8_t AT(0xAF00) last_seen_padding[256]; 38 | //static uint8_t AT(0xB000) game_data_meta_pad_0[434]; 39 | 40 | static cam_game_data_t AT(0xB1B2) cam_game_data; 41 | static cam_game_data_t AT(0xB1D7) cam_game_data_echo; 42 | 43 | //static uint8_t AT(0xB1FC) game_data_meta[3588]; 44 | 45 | /* 46 | * The 30 actual images in the camera's RAM 47 | * Area from 0x2000 to end in RAM 48 | * In steps of 0x2000 bytes using Banks 1 to 15 49 | * Each area containing two images (first/secons) including metadata, thumbnail etc 50 | * https://funtography.online/wiki/Cartridge_RAM 51 | */ 52 | static uint8_t AT(0xA000) image_first[CAMERA_IMAGE_SIZE]; 53 | static uint8_t AT(0xA000) image_first_upper[CAMERA_IMAGE_SIZE >> 1]; 54 | static uint8_t AT(0xA700) image_first_lower[CAMERA_IMAGE_SIZE >> 1]; 55 | static uint8_t AT(0xAE00) image_first_thumbnail[CAMERA_THUMB_SIZE]; 56 | static uint8_t AT(0xAF00) image_first_meta[92]; 57 | static uint8_t AT(0xAF5C) image_first_meta_echo[92]; 58 | // static uint8_t AT(0xAFB8) image_first_padding[51]; 59 | static uint8_t AT(0xAFEB) image_first_unused[21]; // THIS AREA IS UNUSED BY THE ORIGINAL ROM - PXLR Stores data here in RAM bank 1! 60 | 61 | static uint8_t AT(0xB000) image_second[CAMERA_IMAGE_SIZE]; 62 | static uint8_t AT(0xB000) image_second_upper[CAMERA_IMAGE_SIZE >> 1]; 63 | static uint8_t AT(0xB700) image_second_lower[CAMERA_IMAGE_SIZE >> 1]; 64 | static uint8_t AT(0xBE00) image_second_thumbnail[CAMERA_THUMB_SIZE]; 65 | static uint8_t AT(0xBF00) image_second_meta[92]; 66 | static uint8_t AT(0xBF5C) image_second_meta_echo[92]; 67 | // static uint8_t AT(0xBFB8) image_second_padding[51]; 68 | // static uint8_t AT(0xBFEB) image_second_unused[21]; // THIS AREA IS UNUSED BY THE ORIGINAL ROM - PXLR may store data here in the future 69 | 70 | /* 71 | * 0x0000 to 0x0035 72 | * Must be written to RAM bank 16 to control the camera's sensor 73 | */ 74 | 75 | // Camera hardware register: Capture 76 | static volatile uint8_t AT(0xA000) CAM_REG_CAPTURE; 77 | // Camera hardware register: EdgeExclusive, EdgeOperation, Gain 78 | static uint8_t AT(0xA001) CAM_REG_EDEXOPGAIN; 79 | // Camera hardware register: Exposure Time 80 | static uint16_t AT(0xA002) CAM_REG_EXPTIME; 81 | // Camera hardware register: Edge Ratio, Invert Output, Voltage Ref 82 | static uint8_t AT(0xA004) CAM_REG_EDRAINVVREF; 83 | // Camera hardware register: Zero Points, Voltage Out 84 | static uint8_t AT(0xA005) CAM_REG_ZEROVOUT; 85 | // Camera hardware register: Dither Pattern (48 bytes) 86 | static uint8_t AT(0xA006) CAM_REG_DITHERPATTERN[48]; 87 | 88 | #endif 89 | -------------------------------------------------------------------------------- /include/globals.h: -------------------------------------------------------------------------------- 1 | #ifndef GLOBALS_H 2 | #define GLOBALS_H 3 | 4 | #include 5 | #include "imageIndexing.h" 6 | 7 | extern uint8_t mainLoopState; 8 | extern uint8_t isCapturing; 9 | extern uint8_t imageMenuIndex; 10 | extern uint8_t imageInfo[360]; 11 | extern uint8_t imageIndex; 12 | extern uint8_t numVisibleImages; 13 | extern uint8_t sortedIndices[NUM_IMAGES]; 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /include/imageIndexing.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGEINDEXING_H 2 | #define IMAGEINDEXING_H 3 | 4 | #include 5 | #include 6 | 7 | #define NUM_IMAGES 30 8 | #define IMAGE_DELETED 0xFF 9 | #define IMAGE_UNDEFINED 0xFE 10 | 11 | extern void setImageSlot(uint8_t address, uint8_t newValue) BANKED; 12 | extern uint8_t getImageSlot(uint8_t index) BANKED; 13 | extern uint8_t getAddressForIndex(uint8_t index) BANKED; 14 | extern uint8_t getNextHighestAddress(uint8_t searchIndex) BANKED; 15 | extern void reduceIndexAfterDelete(uint8_t deletedIndex) BANKED; 16 | extern void cleanupIndexGaps() BANKED; 17 | extern void sortImages() BANKED; 18 | extern uint8_t findFirstFreeSlot() BANKED; 19 | extern void deleteAllImages() BANKED; 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /include/imageInfo.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGEINFO_H 2 | #define IMAGEINFO_H 3 | 4 | #include 5 | 6 | void getImageInfo(uint8_t imageIndex, uint8_t *tileMap) BANKED; 7 | void displayImageInfo(uint8_t imageIndex) BANKED; 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /include/images.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGES_H 2 | #define IMAGES_H 3 | 4 | #include 5 | #include "typedefs/Image.h" 6 | 7 | extern const Image * const images[30]; 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /include/joypad.h: -------------------------------------------------------------------------------- 1 | #ifndef JOYPAD_H 2 | #define JOYPAD_H 3 | 4 | #include 5 | 6 | // global joypad store variable 7 | extern volatile uint8_t jp; 8 | //extern uint8_t jpCooldown; 9 | 10 | extern void joypadConsumed() BANKED; 11 | extern void waitRelease() BANKED; 12 | extern void captureJoypadISR() BANKED; 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /include/mainLoop.h: -------------------------------------------------------------------------------- 1 | #ifndef MAINLOOP_H 2 | #define MAINLOOP_H 3 | 4 | extern void fastLoadImageTiles() BANKED; 5 | extern void mainLoop() BANKED; 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /include/mainMenu.h: -------------------------------------------------------------------------------- 1 | #ifndef MAINMENU_H 2 | #define MAINMENU_H 3 | 4 | #include 5 | 6 | extern void menuSelectMode(uint8_t loopState) BANKED; 7 | extern void initMainMenu() BANKED; 8 | extern void mainMenu() BANKED; 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /include/menus/imageMenuItems.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_MENUITEMS_H 2 | #define IMAGE_MENUITEMS_H 3 | 4 | #define NUM_IMAGE_MENU_OPTIONS 6 5 | 6 | #include "typedefs/MenuOption.h" 7 | 8 | extern const MenuOption imageMenuItems[NUM_IMAGE_MENU_OPTIONS]; 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /include/menus/mainMenuItems.h: -------------------------------------------------------------------------------- 1 | #ifndef MAIN_MENUITEMS_H 2 | #define MAIN_MENUITEMS_H 3 | 4 | #define NUM_MAIN_MENU_OPTIONS 5 5 | 6 | #include "typedefs/MenuOption.h" 7 | 8 | extern const MenuOption mainMenuItems[NUM_MAIN_MENU_OPTIONS]; 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /include/menus/shootingAssistedMenuItems.h: -------------------------------------------------------------------------------- 1 | #ifndef SHOOTINGASSISTED_MENUITEMS_H 2 | #define SHOOTINGASSISTED_MENUITEMS_H 3 | 4 | #define NUM_MENU_ELEMENTS_ASSISTED 3 5 | 6 | #include "typedefs/MenuItem.h" 7 | 8 | extern MenuItem assistedOptionsMenu; 9 | extern MenuItem contrastsMenuAssisted; 10 | extern MenuItem ditherToggleMenu; 11 | 12 | extern MenuItem *menuItemsAssisted[NUM_MENU_ELEMENTS_ASSISTED]; 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /include/menus/shootingManualMenuItems.h: -------------------------------------------------------------------------------- 1 | #ifndef SHOOTINGMANUAL_MENUITEMS_H 2 | #define SHOOTINGMANUAL_MENUITEMS_H 3 | 4 | #define NUM_MENU_ELEMENTS 11 5 | #define MENU_ACTION_NONE 0 6 | #define MENU_ACTION_DITHER 1 7 | 8 | #include "typedefs/MenuItem.h" 9 | 10 | extern MenuItem exposureTimesMenu; 11 | extern MenuItem gainsMenu; 12 | extern MenuItem voltageOutsMenu; 13 | extern MenuItem contrastsMenu; 14 | extern MenuItem ditherSetsMenu; 15 | extern MenuItem voltageRefsMenu; 16 | extern MenuItem invertOutputsMenu; 17 | extern MenuItem zeroPointsMenu; 18 | extern MenuItem edgeOpModesMenu; 19 | extern MenuItem edgeModesMenu; 20 | extern MenuItem edgeExclusivesMenu; 21 | extern MenuItem captureModesMenu; 22 | 23 | extern MenuItem *menuItems[NUM_MENU_ELEMENTS]; 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /include/modeShootingAssisted.h: -------------------------------------------------------------------------------- 1 | #ifndef MODE_SHOOTING_ASSISTED 2 | #define MODE_SHOOTING_ASSISTED 3 | 4 | extern void initAssistedMode() BANKED; 5 | extern void assistedShootLoop() BANKED; 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /include/modeShootingBurst.h: -------------------------------------------------------------------------------- 1 | #ifndef MODE_SHOOTING_BURST 2 | #define MODE_SHOOTING_BURST 3 | 4 | extern void initBurstMode() BANKED; 5 | extern void burstShootLoop() BANKED; 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /include/modeShootingManual.h: -------------------------------------------------------------------------------- 1 | #ifndef MODE_SHHOOTING_MANUAL_H 2 | #define MODE_SHHOOTING_MANUAL_H 3 | 4 | #include 5 | 6 | #define SETTINGS_REQUIRE_RESET TRUE 7 | #define SETTINGS_REQUIRE_NO_RESET FALSE 8 | 9 | extern void renderManualMenu() BANKED; 10 | extern void initManualMode() BANKED; 11 | extern void storeSettings() BANKED; 12 | extern void restoreDefaults() BANKED; 13 | extern uint8_t loadSettingsFromRAM() BANKED; 14 | extern void renderManualMenu() BANKED; 15 | extern void menuAction() BANKED; 16 | extern void manualShootLoop() BANKED; 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /include/overlays/overlayDefs.h: -------------------------------------------------------------------------------- 1 | #ifndef OVERLAYDEFS_H 2 | #define OVERLAYDEFS_H 3 | 4 | #include "typedefs/Overlay.h" 5 | 6 | #define NUM_OVERLAY_SPRITES 16 7 | #define NUM_OVERLAYS 3 8 | 9 | extern const Overlay *noOverlay[NUM_OVERLAY_SPRITES]; 10 | extern const Overlay *outerBorder[NUM_OVERLAY_SPRITES]; 11 | extern const Overlay *ruleOfThirds[NUM_OVERLAY_SPRITES]; 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /include/overlays/overlays.h: -------------------------------------------------------------------------------- 1 | #ifndef OVERLAYS_H 2 | #define OVERLAYS_H 3 | 4 | #include 5 | 6 | extern void initOverlays() BANKED; 7 | extern void showOverlay() BANKED; 8 | extern void hideLowerOverlay() BANKED; 9 | extern void hideOverlay() BANKED; 10 | extern void nextOverlay() BANKED; 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /include/printCmd.h: -------------------------------------------------------------------------------- 1 | // Original library by DragonEagles from http://shen.mansell.tripod.com/games/gameboy/gameboy.html 2 | // Ported to GBDK 2020 by T0biasCZe 3 | // Print Screen function added by Christianr 4 | // Print Screen (360 tile mode) added by T0biasCZe 5 | 6 | #ifndef PRINTCMD_H 7 | #define PRINTCMD_H 8 | 9 | #include 10 | 11 | extern void printerInit(void) BANKED; 12 | extern uint8_t getPrinterStatus() BANKED; 13 | extern void printImageWild(uint8_t *lower, uint8_t *upper, uint8_t bank) NONBANKED; 14 | extern void printImage(uint8_t *lower, uint8_t *upper, uint8_t bank) NONBANKED; 15 | extern void printImageInfo(uint8_t *imageInfo) NONBANKED; 16 | extern void waitPrinterReady() BANKED; 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /include/remote.h: -------------------------------------------------------------------------------- 1 | #ifndef __REMOTE_H_INCLUDE__ 2 | #define __REMOTE_H_INCLUDE__ 3 | 4 | #include 5 | #include 6 | 7 | #define REMOTE_ENABLED TRUE 8 | #define REMOTE_DISABLED FALSE 9 | 10 | extern volatile uint8_t remote_keys; 11 | 12 | inline uint8_t remote_joypad() { 13 | return remote_keys; 14 | } 15 | 16 | void remote_init() BANKED; 17 | uint8_t remote_activate(uint8_t value) BANKED; 18 | 19 | #endif -------------------------------------------------------------------------------- /include/saveImage.h: -------------------------------------------------------------------------------- 1 | #ifndef SAVEIMAGE_H 2 | #define SAVEIMAGE_H 3 | 4 | #include 5 | 6 | extern void saveImage(uint8_t capt, uint8_t edExOpGain, uint16_t expTime, uint8_t edRInvVref, uint8_t zeroVout, uint8_t ditherSet, uint8_t contrast) BANKED; 7 | extern void saveImageDialog(uint8_t capt, uint8_t edExOpGain, uint16_t expTime, uint8_t edRInvVref, uint8_t zeroVout, uint8_t ditherSet, uint8_t contrast) BANKED; 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /include/splash.h: -------------------------------------------------------------------------------- 1 | #ifndef SPLASH_H 2 | #define SPLASH_H 3 | 4 | #include 5 | 6 | extern uint8_t splash() BANKED; 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /include/systemdetect.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYSTEMDETECT_H_INCLUDE__ 2 | #define __SYSTEMDETECT_H_INCLUDE__ 3 | 4 | #include 5 | #include 6 | 7 | extern uint8_t _is_SUPER, _is_COLOR, _is_ADVANCE; 8 | 9 | void detect_system(); 10 | 11 | #endif -------------------------------------------------------------------------------- /include/typedefs/AssistedOption.h: -------------------------------------------------------------------------------- 1 | #ifndef TYPEDEF_ASSISTED_OPTION_H 2 | #define TYPEDEF_ASSISTED_OPTION_H 3 | 4 | #include 5 | #include "typedefs/MenuOption.h" 6 | 7 | typedef struct AssistedOption { 8 | uint8_t gain; 9 | uint8_t vOut; 10 | uint8_t edgeExclusive; 11 | uint8_t edgeOperation; 12 | uint16_t expTime; 13 | uint8_t ditherSet; 14 | } AssistedOption; 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /include/typedefs/Histogram.h: -------------------------------------------------------------------------------- 1 | #ifndef TYPEDEF_HISTOGRAM_H 2 | #define TYPEDEF_HISTOGRAM_H 3 | 4 | #include 5 | 6 | typedef struct { 7 | uint16_t white; 8 | uint16_t lgrey; 9 | uint16_t dgrey; 10 | uint16_t black; 11 | uint16_t time; 12 | } Histogram; 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /include/typedefs/Image.h: -------------------------------------------------------------------------------- 1 | #ifndef TYPEDEF_IMAGE_H 2 | #define TYPEDEF_IMAGE_H 3 | 4 | #include 5 | 6 | typedef struct { 7 | const uint8_t bank; 8 | uint8_t* const tilesUpper; 9 | uint8_t* const tilesLower; 10 | uint8_t* const thumbnail; 11 | uint8_t* const meta; 12 | uint8_t* const metaEcho; 13 | } Image; 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /include/typedefs/MenuItem.h: -------------------------------------------------------------------------------- 1 | #ifndef TYPEDEF_MENUITEM_H 2 | #define TYPEDEF_MENUITEM_H 3 | 4 | #include 5 | #include "typedefs/MenuOption.h" 6 | 7 | typedef struct MenuItem { 8 | const uint8_t x; 9 | const uint8_t page; 10 | uint8_t value; 11 | const uint8_t storeOffset; 12 | const uint8_t numOptions; 13 | const uint8_t defaultValue; 14 | const int8_t* title; 15 | const int8_t* description; 16 | const MenuOption* options; 17 | const uint8_t action; 18 | } MenuItem; 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /include/typedefs/MenuOption.h: -------------------------------------------------------------------------------- 1 | #ifndef TYPEDEF_MENUOPTION_H 2 | #define TYPEDEF_MENUOPTION_H 3 | 4 | #include 5 | 6 | typedef struct { 7 | const uint8_t value; 8 | const int8_t* title; 9 | } MenuOption; 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /include/typedefs/Overlay.h: -------------------------------------------------------------------------------- 1 | #ifndef TYPEDEF_OVERLAY_H 2 | #define TYPEDEF_OVERLAY_H 3 | 4 | #include 5 | 6 | typedef struct { 7 | const uint8_t sprite; 8 | const uint8_t x; 9 | const uint8_t y; 10 | } Overlay; 11 | 12 | #endif 13 | 14 | -------------------------------------------------------------------------------- /include/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef UTILS_H 2 | #define UTILS_H 3 | 4 | #include 5 | #include "typedefs/MenuItem.h" 6 | 7 | extern void initGfx() BANKED; 8 | extern void initSound() BANKED; 9 | extern void beep() BANKED; 10 | extern void boop() BANKED; 11 | extern void clonk() BANKED; 12 | extern void clearBkg() BANKED; 13 | extern void pause(uint8_t frames) BANKED; 14 | extern void writeNumber(uint8_t x, uint8_t y, uint8_t length, uint8_t number) BANKED; 15 | extern void dead() BANKED; 16 | extern void hexChar(uint8_t *target, uint8_t value) BANKED; 17 | extern void fadeIn() BANKED; 18 | extern void fadeOut() BANKED; 19 | extern void describeExposureTime(uint16_t exposureTime, uint8_t *target) BANKED; 20 | 21 | inline uint8_t getMenuValue(MenuItem * menuItem) { 22 | return menuItem->options[menuItem->value].value; 23 | } 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /include/values.h: -------------------------------------------------------------------------------- 1 | #ifndef VALUES_H 2 | #define VALUES_H 3 | 4 | #include 5 | #include "valuesDefs.h" 6 | #include "typedefs/MenuOption.h" 7 | 8 | extern const uint16_t exposureTimesValues[NUM_EXPOSURE_TIMES]; 9 | extern const MenuOption exposureTimes[NUM_EXPOSURE_TIMES]; 10 | 11 | extern const uint8_t ditherHighLightValues[NUM_CONTRASTS][NUM_CONTRAST_SIZE]; 12 | extern const uint8_t ditherLowLightValues[NUM_CONTRASTS][NUM_CONTRAST_SIZE]; 13 | extern const uint8_t ditherNoHighLightValues[NUM_CONTRASTS][NUM_CONTRAST_SIZE]; 14 | extern const uint8_t ditherNoLowLightValues[NUM_CONTRASTS][NUM_CONTRAST_SIZE]; 15 | extern const MenuOption contrasts[NUM_CONTRASTS]; 16 | 17 | extern const MenuOption gains[NUM_GAIN_LEVELS]; 18 | extern const MenuOption edgeOpModes[NUM_EDGE_OP_MODES]; 19 | extern const MenuOption edgeExclusives[NUM_EDGE_EXCLUSIVE]; 20 | extern const MenuOption edgeModes[NUM_EDGE_MODES]; 21 | extern const MenuOption ditherSets[NUM_DITHERSETS]; 22 | extern const MenuOption invertOutputs[NUM_INVERT_OUTPUTS]; 23 | extern const MenuOption zeroPoints[NUM_ZERO_POINTS]; 24 | extern const MenuOption captureModes[NUM_CAPTURE_MODES]; 25 | extern const MenuOption voltageRefs[NUM_VOLTAGE_REFS]; 26 | extern const MenuOption voltageOuts[NUM_VOLTAGE_OUTS]; 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /include/valuesAssisted.h: -------------------------------------------------------------------------------- 1 | #ifndef VALUES_ASSISTED_H 2 | #define VALUES_ASSISTED_H 3 | 4 | #include "valuesDefs.h" 5 | #include "typedefs/AssistedOption.h" 6 | 7 | #define NUM_ASSISTED_OPTIONS 127 8 | 9 | extern const AssistedOption assistedOptionsValues[NUM_ASSISTED_OPTIONS]; 10 | extern const MenuOption assistedOptions[NUM_ASSISTED_OPTIONS]; 11 | extern const MenuOption ditherToggle[NUM_DITHERSETS]; 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /include/valuesDefs.h: -------------------------------------------------------------------------------- 1 | #ifndef VALUES_DEFS_H 2 | #define VALUES_DEFS_H 3 | 4 | #define NUM_GAIN_LEVELS 21 5 | #define NUM_EXPOSURE_TIMES 39 6 | #define NUM_CONTRASTS 16 7 | #define NUM_CONTRAST_SIZE 48 8 | #define NUM_DITHERSETS 4 9 | #define NUM_DITHER_TOGGLE 2 10 | #define NUM_EDGE_MODES 8 11 | #define NUM_VOLTAGE_REFS 8 12 | #define NUM_ZERO_POINTS 3 13 | #define NUM_CAPTURE_MODES 2 14 | #define NUM_VOLTAGE_OUTS 64 15 | #define NUM_EDGE_OP_MODES 4 16 | #define NUM_EDGE_EXCLUSIVE 2 17 | #define NUM_INVERT_OUTPUTS 2 18 | 19 | #define DITHERSET_HIGH 0b00000000 20 | #define DITHERSET_LOW 0b00000001 21 | #define DITHER_ON 0x00000000 22 | #define DITHER_OFF 0x00000010 23 | 24 | #define A000_MASK_CAPTURE 0b00000011 25 | 26 | #define A001_MASK_EDGE_EXCLUSIVE 0b10000000 27 | #define A001_MASK_EDGE_OP_MODE 0b01100000 28 | #define A001_MASK_GAIN 0b00011111 29 | 30 | #define A002_EXPOSURE_TIME_1050_00 0xFFFF // 1050ms 31 | #define A002_EXPOSURE_TIME_1000_00 0x24F4 // 1000ms 32 | #define A002_EXPOSURE_TIME_0866_00 0x6DD3 // 866ms 33 | #define A002_EXPOSURE_TIME_0833_00 0x5ECB // 833ms 34 | #define A002_EXPOSURE_TIME_0800_00 0x50C3 // 800ms 35 | #define A002_EXPOSURE_TIME_0666_00 0x98A2 // 666ms 36 | #define A002_EXPOSURE_TIME_0633_00 0x8A9A // 633ms 37 | #define A002_EXPOSURE_TIME_0600_00 0x7C92 // 600ms 38 | #define A002_EXPOSURE_TIME_0566_00 0x2E8A // 566ms 39 | #define A002_EXPOSURE_TIME_0533_00 0x2082 // 533ms 40 | #define A002_EXPOSURE_TIME_0500_00 0x127A // 500ms 41 | #define A002_EXPOSURE_TIME_0466_00 0xC471 // 466ms 42 | #define A002_EXPOSURE_TIME_0433_00 0xB669 // 433ms 43 | #define A002_EXPOSURE_TIME_0400_00 0xA861 // 400ms 44 | #define A002_EXPOSURE_TIME_0366_00 0x5B59 // 366ms 45 | #define A002_EXPOSURE_TIME_0333_00 0x4C51 // 333ms 46 | #define A002_EXPOSURE_TIME_0300_00 0x3E49 // 300ms 47 | #define A002_EXPOSURE_TIME_0283_00 0x1745 // 283ms 48 | #define A002_EXPOSURE_TIME_0266_00 0xF140 // 266ms 49 | #define A002_EXPOSURE_TIME_0250_00 0x093D // 250ms 50 | #define A002_EXPOSURE_TIME_0233_00 0xE238 // 233ms 51 | #define A002_EXPOSURE_TIME_0216_00 0xBB34 // 216ms 52 | #define A002_EXPOSURE_TIME_0200_00 0xD430 // 200ms 53 | #define A002_EXPOSURE_TIME_0187_00 0xA72D // 187ms 54 | #define A002_EXPOSURE_TIME_0173_00 0x3C2A // 173ms 55 | #define A002_EXPOSURE_TIME_0160_00 0x1027 // 160ms 56 | #define A002_EXPOSURE_TIME_0148_00 0x2124 // 148ms 57 | #define A002_EXPOSURE_TIME_0137_00 0x7221 // 137ms 58 | #define A002_EXPOSURE_TIME_0125_00 0x851E // 125ms 59 | #define A002_EXPOSURE_TIME_0117_00 0x901C // 117ms 60 | #define A002_EXPOSURE_TIME_0108_00 0x5D1A // 108ms 61 | #define A002_EXPOSURE_TIME_0100_00 0x6A18 // 100ms 62 | #define A002_EXPOSURE_TIME_0094_00 0xF316 // 94ms 63 | #define A002_EXPOSURE_TIME_0087_00 0x3D15 // 87ms 64 | #define A002_EXPOSURE_TIME_0080_00 0x8813 // 80ms 65 | #define A002_EXPOSURE_TIME_0077_00 0xCC12 // 77ms 66 | #define A002_EXPOSURE_TIME_0073_00 0xD211 // 73ms 67 | #define A002_EXPOSURE_TIME_0070_00 0x1711 // 70ms 68 | #define A002_EXPOSURE_TIME_0067_00 0x5B10 // 67ms 69 | #define A002_EXPOSURE_TIME_0063_00 0x610F // 63ms 70 | #define A002_EXPOSURE_TIME_0060_00 0xA60E // 60ms 71 | #define A002_EXPOSURE_TIME_0057_00 0xEA0D // 57ms 72 | #define A002_EXPOSURE_TIME_0053_00 0xF00C // 53ms 73 | #define A002_EXPOSURE_TIME_0050_00 0x350C // 50ms 74 | #define A002_EXPOSURE_TIME_0047_00 0x790B // 47ms 75 | #define A002_EXPOSURE_TIME_0043_00 0x7F0A // 43ms 76 | #define A002_EXPOSURE_TIME_0040_00 0xC409 // 40ms 77 | #define A002_EXPOSURE_TIME_0037_00 0x0809 // 37ms 78 | #define A002_EXPOSURE_TIME_0033_00 0x0E08 // 33ms 79 | #define A002_EXPOSURE_TIME_0030_00 0x5307 // 30ms 80 | #define A002_EXPOSURE_TIME_0028_00 0xD606 // 28ms 81 | #define A002_EXPOSURE_TIME_0027_00 0x9706 // 27ms 82 | #define A002_EXPOSURE_TIME_0025_00 0x1B06 // 25ms 83 | #define A002_EXPOSURE_TIME_0023_00 0x9D05 // 23ms 84 | #define A002_EXPOSURE_TIME_0022_00 0x5F05 // 22ms 85 | #define A002_EXPOSURE_TIME_0020_00 0xE204 // 20ms 86 | #define A002_EXPOSURE_TIME_0017_00 0x2604 // 17ms 87 | #define A002_EXPOSURE_TIME_0016_00 0xE803 // 16ms 88 | #define A002_EXPOSURE_TIME_0015_00 0xAA03 // 15ms 89 | #define A002_EXPOSURE_TIME_0014_00 0x6B03 // 14ms 90 | #define A002_EXPOSURE_TIME_0013_00 0x2C03 // 13ms 91 | #define A002_EXPOSURE_TIME_0012_50 0x0E03 // 12.5ms 92 | #define A002_EXPOSURE_TIME_0012_00 0xEE02 // 12ms 93 | #define A002_EXPOSURE_TIME_0011_00 0xAF02 // 11ms 94 | #define A002_EXPOSURE_TIME_0010_00 0x7102 // 10ms 95 | #define A002_EXPOSURE_TIME_0009_30 0x4502 // 9.3ms 96 | #define A002_EXPOSURE_TIME_0008_60 0x1902 // 8.6ms 97 | #define A002_EXPOSURE_TIME_0008_00 0xF401 // 8ms 98 | #define A002_EXPOSURE_TIME_0007_30 0xC801 // 7.3ms 99 | #define A002_EXPOSURE_TIME_0006_60 0x9C01 // 6.6ms 100 | #define A002_EXPOSURE_TIME_0006_00 0x7701 // 6ms 101 | #define A002_EXPOSURE_TIME_0005_60 0x5E01 // 5.6ms 102 | #define A002_EXPOSURE_TIME_0005_30 0x4B01 // 5.3ms 103 | #define A002_EXPOSURE_TIME_0005_00 0x3901 // 5ms 104 | #define A002_EXPOSURE_TIME_0004_60 0x1F01 // 4.6ms 105 | #define A002_EXPOSURE_TIME_0004_30 0x0C01 // 4.3ms 106 | #define A002_EXPOSURE_TIME_0004_00 0xFA00 // 4ms 107 | #define A002_EXPOSURE_TIME_0003_60 0xE100 // 3.6ms 108 | #define A002_EXPOSURE_TIME_0003_30 0xCE00 // 3.3ms 109 | #define A002_EXPOSURE_TIME_0003_00 0xBC00 // 3ms 110 | #define A002_EXPOSURE_TIME_0002_80 0xAF00 // 2.8ms 111 | #define A002_EXPOSURE_TIME_0002_70 0xA800 // 2.7ms 112 | #define A002_EXPOSURE_TIME_0002_50 0x9D00 // 2.5ms 113 | #define A002_EXPOSURE_TIME_0002_30 0x8F00 // 2.3ms 114 | #define A002_EXPOSURE_TIME_0002_20 0x8900 // 2.2ms 115 | #define A002_EXPOSURE_TIME_0002_00 0x7D00 // 2ms 116 | #define A002_EXPOSURE_TIME_0001_80 0x7000 // 1.8ms 117 | #define A002_EXPOSURE_TIME_0001_70 0x6A00 // 1.7ms 118 | #define A002_EXPOSURE_TIME_0001_50 0x5E00 // 1.5ms 119 | #define A002_EXPOSURE_TIME_0001_40 0x5700 // 1.4ms 120 | #define A002_EXPOSURE_TIME_0001_35 0x5400 // 1.35ms 121 | #define A002_EXPOSURE_TIME_0001_25 0x4E00 // 1.25ms 122 | #define A002_EXPOSURE_TIME_0001_15 0x4700 // 1.15ms 123 | #define A002_EXPOSURE_TIME_0001_10 0x4400 // 1.1ms 124 | #define A002_EXPOSURE_TIME_0001_00 0x3F00 // 1ms 125 | #define A002_EXPOSURE_TIME_0000_93 0x3A00 // 0.93ms 126 | #define A002_EXPOSURE_TIME_0000_86 0x3500 // 0.86ms 127 | #define A002_EXPOSURE_TIME_0000_80 0x3200 // 0.8ms 128 | #define A002_EXPOSURE_TIME_0000_73 0x2D00 // 0.73ms 129 | #define A002_EXPOSURE_TIME_0000_66 0x2900 // 0.66ms 130 | #define A002_EXPOSURE_TIME_0000_60 0x2600 // 0.6ms 131 | #define A002_EXPOSURE_TIME_0000_56 0x2300 // 0.56ms 132 | #define A002_EXPOSURE_TIME_0000_53 0x2100 // 0.53ms 133 | #define A002_EXPOSURE_TIME_0000_50 0x2000 // 0.5ms 134 | #define A002_EXPOSURE_TIME_0000_46 0x1C00 // 0.46ms 135 | #define A002_EXPOSURE_TIME_0000_43 0x1A00 // 0.43ms 136 | #define A002_EXPOSURE_TIME_0000_40 0x1900 // 0.4ms 137 | #define A002_EXPOSURE_TIME_0000_36 0x1600 // 0.36ms 138 | #define A002_EXPOSURE_TIME_0000_33 0x1400 // 0.33ms 139 | #define A002_EXPOSURE_TIME_0000_30 0x1300 // 0.3ms 140 | #define A002_EXPOSURE_TIME_0000_26 0x1000 // 0.26ms 141 | #define A002_EXPOSURE_TIME_0000_23 0x0E00 // 0.23ms 142 | #define A002_EXPOSURE_TIME_0000_20 0x0D00 // 0.2ms 143 | 144 | 145 | #define A004_MASK_EDGE_RATIO 0b01110000 146 | #define A004_MASK_INVERT_OUTPUT 0b00001000 147 | #define A004_MASK_VOLTAGE_REF 0b00000111 148 | 149 | #define A005_MASK_ZERO 0b11000000 150 | #define A005_MASK_VOLTAGE_OUT 0b00111111 151 | 152 | #define A000_START_CAPTURE_POSITIVE 0b00000011 153 | #define A000_START_CAPTURE_NEGATIVE 0b00000001 154 | 155 | // The Game Boy Camera uses 0x00, 0x04, 0x08 and 0x0C 156 | // They are 14.0dB, 20.0dB, 26.0dB and 32dB, which translate to a gain of 5.01, 10.00, 19.95 and 39.81. 157 | #define A001_GAIN_140 0b00000000 // 14.0 (gbcam gain: 5.01) 158 | #define A001_GAIN_155 0b00000001 // 15.5 159 | #define A001_GAIN_170 0b00000010 // 17.0 160 | #define A001_GAIN_185 0b00000010 // 18.5 161 | #define A001_GAIN_200 0b00000100 // 20.0 (gbcam gain: 10.00) 162 | #define A001_GAIN_200_D 0b00010000 // 20.0 (d) 163 | #define A001_GAIN_215 0b00000101 // 21.5 164 | #define A001_GAIN_215_D 0b00010001 // 21.5 (d) 165 | #define A001_GAIN_230 0b00000110 // 23.0 166 | #define A001_GAIN_230_D 0b00010010 // 23.0 (d) 167 | #define A001_GAIN_245 0b00000111 // 24.5 168 | #define A001_GAIN_245_D 0b00010010 // 24.5 (d) 169 | #define A001_GAIN_260 0b00001000 // 26.0 (gbcam gain: 19.95) 170 | #define A001_GAIN_260_D 0b00010100 // 26.0 (d) 171 | #define A001_GAIN_275 0b00010101 // 27.5 172 | #define A001_GAIN_290 0b00001001 // 29.0 173 | #define A001_GAIN_290_D 0b00010110 // 29.0 (d) 174 | #define A001_GAIN_305 0b00010111 // 30.5 175 | #define A001_GAIN_320 0b00001010 // 32.0 (gbcam gain: 39.81) 176 | #define A001_GAIN_320_D 0b00011000 // 32.0 (d) 177 | #define A001_GAIN_350 0b00001011 // 35.0 178 | #define A001_GAIN_350_D 0b00011001 // 35.0 (d) 179 | #define A001_GAIN_380 0b00001100 // 38.0 180 | #define A001_GAIN_380_D 0b00011010 // 38.0 (d) 181 | #define A001_GAIN_410 0b00001101 // 41.0 182 | #define A001_GAIN_410_D 0b00011011 // 41.0 (d) 183 | #define A001_GAIN_440 0b00011100 // 44.0 184 | #define A001_GAIN_455 0b00001110 // 45.5 185 | #define A001_GAIN_470 0b00011101 // 47.0 186 | #define A001_GAIN_515 0b00001111 // 51.5 187 | #define A001_GAIN_515_D 0b00011110 // 51.5 (d) 188 | #define A001_GAIN_575 0b00011111 // 57.5 189 | 190 | #define A001_EDGE_OP_MODE_NONE 0b00000000 191 | #define A001_EDGE_OP_MODE_HORIZONTAL 0b00100000 192 | #define A001_EDGE_OP_MODE_VERTICAL 0b01000000 193 | #define A001_EDGE_OP_MODE_2D 0b01100000 194 | 195 | #define A001_EDGE_EXCLUSIVE_VERT_ON 0b10000000 196 | #define A001_EDGE_EXCLUSIVE_VERT_OFF 0b00000000 197 | 198 | #define A004_EDGE_RATIO_050 0b00000000 199 | #define A004_EDGE_RATIO_075 0b00010000 200 | #define A004_EDGE_RATIO_100 0b00100000 201 | #define A004_EDGE_RATIO_125 0b00110000 202 | #define A004_EDGE_RATIO_200 0b01000000 203 | #define A004_EDGE_RATIO_300 0b01010000 204 | #define A004_EDGE_RATIO_400 0b01100000 205 | #define A004_EDGE_RATIO_500 0b01110000 206 | 207 | #define A004_INVERT_OUTPUT_ON 0b00001000 208 | #define A004_INVERT_OUTPUT_OFF 0b00000000 209 | 210 | #define A004_VOLTAGE_REF_00 0b00000000 211 | #define A004_VOLTAGE_REF_05 0b00000001 212 | #define A004_VOLTAGE_REF_10 0b00000010 213 | #define A004_VOLTAGE_REF_15 0b00000011 214 | #define A004_VOLTAGE_REF_20 0b00000100 215 | #define A004_VOLTAGE_REF_25 0b00000101 216 | #define A004_VOLTAGE_REF_30 0b00000110 217 | #define A004_VOLTAGE_REF_35 0b00000111 218 | 219 | #define A005_ZERO_DISABLED 0b00000000 220 | #define A005_ZERO_POSITIVE 0b10000000 221 | #define A005_ZERO_NEGATIVE 0b01000000 222 | 223 | #define A005_VOLTAGE_OUT_NEG_992 0b00011111 // -0.992mV 224 | #define A005_VOLTAGE_OUT_NEG_960 0b00011110 // -0.960mV 225 | #define A005_VOLTAGE_OUT_NEG_928 0b00011101 // -0.928mV 226 | #define A005_VOLTAGE_OUT_NEG_896 0b00011100 // -0.896mV 227 | #define A005_VOLTAGE_OUT_NEG_864 0b00011011 // -0.864mV 228 | #define A005_VOLTAGE_OUT_NEG_832 0b00011010 // -0.832mV 229 | #define A005_VOLTAGE_OUT_NEG_800 0b00011001 // -0.800mV 230 | #define A005_VOLTAGE_OUT_NEG_768 0b00011000 // -0.768mV 231 | #define A005_VOLTAGE_OUT_NEG_736 0b00010111 // -0.736mV 232 | #define A005_VOLTAGE_OUT_NEG_704 0b00010110 // -0.704mV 233 | #define A005_VOLTAGE_OUT_NEG_672 0b00010101 // -0.672mV 234 | #define A005_VOLTAGE_OUT_NEG_640 0b00010100 // -0.640mV 235 | #define A005_VOLTAGE_OUT_NEG_608 0b00010011 // -0.608mV 236 | #define A005_VOLTAGE_OUT_NEG_576 0b00010010 // -0.576mV 237 | #define A005_VOLTAGE_OUT_NEG_544 0b00010001 // -0.544mV 238 | #define A005_VOLTAGE_OUT_NEG_512 0b00010000 // -0.512mV 239 | #define A005_VOLTAGE_OUT_NEG_480 0b00001111 // -0.480mV 240 | #define A005_VOLTAGE_OUT_NEG_448 0b00001110 // -0.448mV 241 | #define A005_VOLTAGE_OUT_NEG_416 0b00001101 // -0.416mV 242 | #define A005_VOLTAGE_OUT_NEG_384 0b00001100 // -0.384mV 243 | #define A005_VOLTAGE_OUT_NEG_352 0b00001011 // -0.352mV 244 | #define A005_VOLTAGE_OUT_NEG_320 0b00001010 // -0.320mV 245 | #define A005_VOLTAGE_OUT_NEG_288 0b00001001 // -0.288mV 246 | #define A005_VOLTAGE_OUT_NEG_256 0b00001000 // -0.256mV 247 | #define A005_VOLTAGE_OUT_NEG_224 0b00000111 // -0.224mV 248 | #define A005_VOLTAGE_OUT_NEG_192 0b00000110 // -0.192mV 249 | #define A005_VOLTAGE_OUT_NEG_160 0b00000101 // -0.160mV 250 | #define A005_VOLTAGE_OUT_NEG_128 0b00000100 // -0.128mV 251 | #define A005_VOLTAGE_OUT_NEG_096 0b00000011 // -0.096mV 252 | #define A005_VOLTAGE_OUT_NEG_064 0b00000010 // -0.064mV 253 | #define A005_VOLTAGE_OUT_NEG_032 0b00000001 // -0.032mV 254 | #define A005_VOLTAGE_OUT_NEG_000 0b00000000 // -0.000mV 255 | #define A005_VOLTAGE_OUT_POS_000 0b00100000 // 0.000mV 256 | #define A005_VOLTAGE_OUT_POS_032 0b00100001 // 0.032mV 257 | #define A005_VOLTAGE_OUT_POS_064 0b00100010 // 0.064mV 258 | #define A005_VOLTAGE_OUT_POS_096 0b00100011 // 0.096mV 259 | #define A005_VOLTAGE_OUT_POS_128 0b00100100 // 0.128mV 260 | #define A005_VOLTAGE_OUT_POS_160 0b00100101 // 0.160mV 261 | #define A005_VOLTAGE_OUT_POS_192 0b00100110 // 0.192mV 262 | #define A005_VOLTAGE_OUT_POS_224 0b00100111 // 0.224mV 263 | #define A005_VOLTAGE_OUT_POS_256 0b00101000 // 0.256mV 264 | #define A005_VOLTAGE_OUT_POS_288 0b00101001 // 0.288mV 265 | #define A005_VOLTAGE_OUT_POS_320 0b00101010 // 0.320mV 266 | #define A005_VOLTAGE_OUT_POS_352 0b00101011 // 0.352mV 267 | #define A005_VOLTAGE_OUT_POS_384 0b00101100 // 0.384mV 268 | #define A005_VOLTAGE_OUT_POS_416 0b00101101 // 0.416mV 269 | #define A005_VOLTAGE_OUT_POS_448 0b00101110 // 0.448mV 270 | #define A005_VOLTAGE_OUT_POS_480 0b00101111 // 0.480mV 271 | #define A005_VOLTAGE_OUT_POS_512 0b00110000 // 0.512mV 272 | #define A005_VOLTAGE_OUT_POS_544 0b00110001 // 0.544mV 273 | #define A005_VOLTAGE_OUT_POS_576 0b00110010 // 0.576mV 274 | #define A005_VOLTAGE_OUT_POS_608 0b00110011 // 0.608mV 275 | #define A005_VOLTAGE_OUT_POS_640 0b00110100 // 0.640mV 276 | #define A005_VOLTAGE_OUT_POS_672 0b00110101 // 0.672mV 277 | #define A005_VOLTAGE_OUT_POS_704 0b00110110 // 0.704mV 278 | #define A005_VOLTAGE_OUT_POS_736 0b00110111 // 0.736mV 279 | #define A005_VOLTAGE_OUT_POS_768 0b00111000 // 0.768mV 280 | #define A005_VOLTAGE_OUT_POS_800 0b00111001 // 0.800mV 281 | #define A005_VOLTAGE_OUT_POS_832 0b00111010 // 0.832mV 282 | #define A005_VOLTAGE_OUT_POS_864 0b00111011 // 0.864mV 283 | #define A005_VOLTAGE_OUT_POS_896 0b00111100 // 0.896mV 284 | #define A005_VOLTAGE_OUT_POS_928 0b00111101 // 0.928mV 285 | #define A005_VOLTAGE_OUT_POS_960 0b00111110 // 0.960mV 286 | #define A005_VOLTAGE_OUT_POS_992 0b00111111 // 0.992mV 287 | 288 | #endif 289 | -------------------------------------------------------------------------------- /res/font.h: -------------------------------------------------------------------------------- 1 | #ifndef FONT_H 2 | #define FONT_H 3 | 4 | #include 5 | 6 | BANKREF_EXTERN(font) 7 | 8 | #define NUM_FONT_CHARS 91 9 | extern const uint8_t font[1456]; 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /res/gfx/gb/backgrounds/frame_pxlr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HerrZatacke/2bit-pxlr-studio/77f579f5583927c10b787994f7ca01e389dd1660/res/gfx/gb/backgrounds/frame_pxlr.png -------------------------------------------------------------------------------- /res/gfx/gb/backgrounds/frame_pxlr.png.meta: -------------------------------------------------------------------------------- 1 | -noflip -------------------------------------------------------------------------------- /res/gfx/gb/backgrounds/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HerrZatacke/2bit-pxlr-studio/77f579f5583927c10b787994f7ca01e389dd1660/res/gfx/gb/backgrounds/logo.png -------------------------------------------------------------------------------- /res/gfx/gb/backgrounds/logo.png.meta: -------------------------------------------------------------------------------- 1 | -noflip -------------------------------------------------------------------------------- /res/gfx/gb/backgrounds/wild_bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HerrZatacke/2bit-pxlr-studio/77f579f5583927c10b787994f7ca01e389dd1660/res/gfx/gb/backgrounds/wild_bottom.png -------------------------------------------------------------------------------- /res/gfx/gb/backgrounds/wild_bottom.png.meta: -------------------------------------------------------------------------------- 1 | -noflip -------------------------------------------------------------------------------- /res/gfx/gb/backgrounds/wild_center.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HerrZatacke/2bit-pxlr-studio/77f579f5583927c10b787994f7ca01e389dd1660/res/gfx/gb/backgrounds/wild_center.png -------------------------------------------------------------------------------- /res/gfx/gb/backgrounds/wild_center.png.meta: -------------------------------------------------------------------------------- 1 | -noflip -------------------------------------------------------------------------------- /res/gfx/gb/backgrounds/wild_top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HerrZatacke/2bit-pxlr-studio/77f579f5583927c10b787994f7ca01e389dd1660/res/gfx/gb/backgrounds/wild_top.png -------------------------------------------------------------------------------- /res/gfx/gb/backgrounds/wild_top.png.meta: -------------------------------------------------------------------------------- 1 | -noflip -------------------------------------------------------------------------------- /res/gfx/gbc/backgrounds/frame_pxlr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HerrZatacke/2bit-pxlr-studio/77f579f5583927c10b787994f7ca01e389dd1660/res/gfx/gbc/backgrounds/frame_pxlr.png -------------------------------------------------------------------------------- /res/gfx/gbc/backgrounds/frame_pxlr.png.meta: -------------------------------------------------------------------------------- 1 | -noflip -------------------------------------------------------------------------------- /res/gfx/gbc/backgrounds/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HerrZatacke/2bit-pxlr-studio/77f579f5583927c10b787994f7ca01e389dd1660/res/gfx/gbc/backgrounds/logo.png -------------------------------------------------------------------------------- /res/gfx/gbc/backgrounds/logo.png.meta: -------------------------------------------------------------------------------- 1 | -noflip -------------------------------------------------------------------------------- /res/gfx/gbc/backgrounds/wild_bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HerrZatacke/2bit-pxlr-studio/77f579f5583927c10b787994f7ca01e389dd1660/res/gfx/gbc/backgrounds/wild_bottom.png -------------------------------------------------------------------------------- /res/gfx/gbc/backgrounds/wild_bottom.png.meta: -------------------------------------------------------------------------------- 1 | -noflip -------------------------------------------------------------------------------- /res/gfx/gbc/backgrounds/wild_center.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HerrZatacke/2bit-pxlr-studio/77f579f5583927c10b787994f7ca01e389dd1660/res/gfx/gbc/backgrounds/wild_center.png -------------------------------------------------------------------------------- /res/gfx/gbc/backgrounds/wild_center.png.meta: -------------------------------------------------------------------------------- 1 | -noflip -------------------------------------------------------------------------------- /res/gfx/gbc/backgrounds/wild_top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HerrZatacke/2bit-pxlr-studio/77f579f5583927c10b787994f7ca01e389dd1660/res/gfx/gbc/backgrounds/wild_top.png -------------------------------------------------------------------------------- /res/gfx/gbc/backgrounds/wild_top.png.meta: -------------------------------------------------------------------------------- 1 | -noflip -------------------------------------------------------------------------------- /res/maps.c: -------------------------------------------------------------------------------- 1 | #pragma bank 1 2 | 3 | #include 4 | 5 | const uint8_t map_normal[] = { 6 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 7 | 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 8 | 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 9 | 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 10 | 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 11 | 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 12 | 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 13 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 14 | 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 15 | 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 16 | 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 17 | 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 18 | 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 19 | 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 20 | }; 21 | 22 | const uint8_t map_flipped[] = { 23 | 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 24 | 0x1F, 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 25 | 0x2F, 0x2E, 0x2D, 0x2C, 0x2B, 0x2A, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 26 | 0x3F, 0x3E, 0x3D, 0x3C, 0x3B, 0x3A, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 27 | 0x4F, 0x4E, 0x4D, 0x4C, 0x4B, 0x4A, 0x49, 0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40, 28 | 0x5F, 0x5E, 0x5D, 0x5C, 0x5B, 0x5A, 0x59, 0x58, 0x57, 0x56, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50, 29 | 0x6F, 0x6E, 0x6D, 0x6C, 0x6B, 0x6A, 0x69, 0x68, 0x67, 0x66, 0x65, 0x64, 0x63, 0x62, 0x61, 0x60, 30 | 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 31 | 0x1F, 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 32 | 0x2F, 0x2E, 0x2D, 0x2C, 0x2B, 0x2A, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 33 | 0x3F, 0x3E, 0x3D, 0x3C, 0x3B, 0x3A, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 34 | 0x4F, 0x4E, 0x4D, 0x4C, 0x4B, 0x4A, 0x49, 0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40, 35 | 0x5F, 0x5E, 0x5D, 0x5C, 0x5B, 0x5A, 0x59, 0x58, 0x57, 0x56, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50, 36 | 0x6F, 0x6E, 0x6D, 0x6C, 0x6B, 0x6A, 0x69, 0x68, 0x67, 0x66, 0x65, 0x64, 0x63, 0x62, 0x61, 0x60, 37 | }; 38 | -------------------------------------------------------------------------------- /res/maps.h: -------------------------------------------------------------------------------- 1 | #ifndef MAPS_H 2 | #define MAPS_H 3 | 4 | #include 5 | 6 | extern const uint8_t map_normal[]; 7 | extern const uint8_t map_flipped[]; 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /res/nope.c: -------------------------------------------------------------------------------- 1 | #pragma bank 1 2 | 3 | #include 4 | 5 | const uint8_t nope_tiles[1792] = { 6 | 0x36, 0x23, 0x6F, 0x61, 0x6A, 0x5A, 0xCF, 0x79, 0xDB, 0xE3, 0x4F, 0x7F, 0x4F, 0x66, 0xCB, 0x94, 7 | 0x0C, 0x8C, 0xE6, 0x5B, 0x8B, 0x67, 0x94, 0x8E, 0x47, 0x8C, 0x65, 0x2D, 0x12, 0x96, 0x55, 0x18, 8 | 0x19, 0xD2, 0x71, 0xEA, 0xFA, 0x16, 0x41, 0x6C, 0xCB, 0x85, 0x5D, 0x22, 0x3E, 0x17, 0x8E, 0x19, 9 | 0x3A, 0x8D, 0x3A, 0xA8, 0x83, 0x76, 0xAD, 0xB3, 0xE8, 0x74, 0x8F, 0x6B, 0x05, 0xEE, 0x5B, 0x7F, 10 | 0x51, 0x90, 0xA1, 0x9C, 0xC9, 0x26, 0x8D, 0x3A, 0x76, 0x60, 0xA9, 0x1F, 0xB9, 0x0C, 0x48, 0x06, 11 | 0xFF, 0xD6, 0x60, 0x58, 0x36, 0xCA, 0x86, 0x62, 0x81, 0x30, 0xE3, 0xDF, 0x89, 0x00, 0x78, 0xAE, 12 | 0xDC, 0xF9, 0x38, 0x2F, 0xBC, 0x9B, 0x03, 0x33, 0x8F, 0xEE, 0xF8, 0x1C, 0xE0, 0x51, 0x24, 0x4A, 13 | 0xBF, 0x82, 0xD2, 0x4F, 0x1C, 0x56, 0x4A, 0xFB, 0x25, 0xD6, 0xEA, 0x1C, 0xD6, 0x19, 0xDC, 0x80, 14 | 0x96, 0x2F, 0x86, 0xBF, 0xED, 0x24, 0x91, 0x38, 0xE4, 0x8E, 0x1C, 0x36, 0xBD, 0x86, 0x11, 0xF2, 15 | 0xB5, 0x91, 0x23, 0xF9, 0xA5, 0xAE, 0xA8, 0x5F, 0xDF, 0x52, 0x92, 0x3F, 0x58, 0x0F, 0xBF, 0x45, 16 | 0x51, 0xB9, 0xB0, 0x61, 0xDF, 0x8F, 0x32, 0x80, 0x0F, 0xF8, 0xC6, 0x30, 0x2B, 0x6E, 0x2F, 0xFB, 17 | 0x9F, 0x51, 0xD0, 0xEC, 0x63, 0xDA, 0x9C, 0xAF, 0xF1, 0xB5, 0x35, 0xE9, 0x10, 0xCF, 0x33, 0xAD, 18 | 0xDA, 0x95, 0x31, 0xEA, 0xB0, 0x30, 0xD9, 0x2B, 0x71, 0x77, 0x41, 0x9D, 0x09, 0xD6, 0xA2, 0xE0, 19 | 0x10, 0xB7, 0x2A, 0xE7, 0x0C, 0x19, 0x96, 0xD9, 0xD1, 0x68, 0xD7, 0x33, 0x42, 0xC5, 0xB1, 0x97, 20 | 0x67, 0xE0, 0x32, 0x43, 0x30, 0xCC, 0xD0, 0x04, 0x59, 0x40, 0x20, 0x7A, 0xE1, 0xF7, 0x76, 0x64, 21 | 0x5F, 0xBB, 0x26, 0xF4, 0x3B, 0x6D, 0xE1, 0x7F, 0x21, 0x57, 0x8D, 0x74, 0x41, 0x14, 0x30, 0xD2, 22 | 0xAF, 0x5F, 0x8E, 0x8A, 0xD2, 0x80, 0x9E, 0xB7, 0x25, 0xC2, 0xED, 0xCA, 0xCA, 0xB3, 0xF4, 0x98, 23 | 0xDD, 0x4B, 0xC9, 0x06, 0x9A, 0x06, 0xAC, 0x35, 0xAD, 0xDA, 0xA4, 0xD5, 0xA2, 0xB0, 0x2A, 0x5D, 24 | 0x65, 0x8F, 0x87, 0x14, 0xFA, 0x1C, 0xEF, 0xFA, 0xBF, 0x42, 0x0D, 0x5C, 0x92, 0x06, 0x3B, 0xB2, 25 | 0x8D, 0x4C, 0x47, 0x4D, 0x64, 0xD5, 0x6A, 0xC7, 0x5D, 0x80, 0xC2, 0x48, 0xB5, 0xE1, 0x65, 0xBE, 26 | 0x1F, 0x6D, 0xF5, 0x20, 0xAC, 0x72, 0x37, 0xAC, 0x8B, 0x03, 0xFD, 0x17, 0xE2, 0x99, 0x4B, 0x0B, 27 | 0xDB, 0x0A, 0x67, 0xC1, 0x11, 0x8A, 0x92, 0xB8, 0xBD, 0xC8, 0xEC, 0x7A, 0xC0, 0xCA, 0xA9, 0x21, 28 | 0xC9, 0x69, 0xFC, 0xCE, 0x6C, 0xF6, 0x58, 0xDB, 0x6D, 0x05, 0xE2, 0xA7, 0x73, 0xAF, 0x2D, 0x8D, 29 | 0x7C, 0x56, 0x21, 0x18, 0x02, 0x16, 0xCA, 0xCA, 0x5E, 0x7E, 0x04, 0x9B, 0xAE, 0x76, 0x3A, 0x48, 30 | 0x13, 0x7A, 0x15, 0x86, 0x49, 0x1E, 0xD3, 0xAB, 0x00, 0xA5, 0xF0, 0x89, 0x86, 0x10, 0x31, 0x63, 31 | 0xAD, 0x80, 0xF2, 0x07, 0xB3, 0x5B, 0xAA, 0x0B, 0xC6, 0x7D, 0xF9, 0xCA, 0xB9, 0x5A, 0xF8, 0x8E, 32 | 0x55, 0xC2, 0xA1, 0xBE, 0x35, 0x8D, 0xAD, 0x6A, 0xE9, 0x30, 0x5E, 0xCC, 0x43, 0x0D, 0x1F, 0x02, 33 | 0x8E, 0x87, 0x7A, 0xFA, 0x92, 0x10, 0x26, 0x41, 0xDE, 0xCF, 0x45, 0x7F, 0x1E, 0x14, 0x97, 0x16, 34 | 0x07, 0x61, 0xEB, 0x7E, 0xC9, 0x80, 0x95, 0x25, 0x5A, 0x50, 0x1B, 0x29, 0xEF, 0xE5, 0x36, 0x1E, 35 | 0x2E, 0x46, 0xC6, 0x2F, 0x0A, 0x82, 0xE2, 0x07, 0x56, 0xCE, 0x90, 0xB6, 0xA5, 0xE8, 0x61, 0x87, 36 | 0x2F, 0xBB, 0x22, 0xDA, 0x5C, 0xAB, 0x53, 0xB7, 0xD6, 0x43, 0x30, 0x9C, 0xE1, 0xD7, 0x0B, 0x64, 37 | 0x61, 0xF6, 0xD7, 0x14, 0x62, 0x93, 0xC8, 0xBC, 0x3F, 0xED, 0xDF, 0x66, 0xE3, 0x66, 0x38, 0x17, 38 | 0xA1, 0x7F, 0xFB, 0xE0, 0x5D, 0xE4, 0xE9, 0xE3, 0x38, 0x7D, 0x94, 0x5E, 0xDD, 0x32, 0xF3, 0x2E, 39 | 0xDB, 0x14, 0x85, 0xD9, 0x32, 0xDA, 0xA7, 0x0A, 0x34, 0x69, 0xF1, 0x38, 0x3D, 0x07, 0xF9, 0xD9, 40 | 0xD6, 0x50, 0xCA, 0x5C, 0xE6, 0xF4, 0xFA, 0xFB, 0x1D, 0x2A, 0x48, 0x26, 0x80, 0xF7, 0x00, 0x96, 41 | 0xA6, 0xAF, 0x18, 0x84, 0xD3, 0xC3, 0xA5, 0x27, 0x12, 0x6E, 0x4D, 0x22, 0x38, 0x42, 0x4A, 0xE7, 42 | 0x8D, 0x60, 0x44, 0x74, 0xC0, 0x87, 0x54, 0x5E, 0xA5, 0x12, 0xD6, 0x4B, 0xBC, 0x04, 0xF4, 0x8A, 43 | 0xD9, 0x5E, 0x57, 0x08, 0xFB, 0xD8, 0x2E, 0x6E, 0xAC, 0x13, 0x55, 0x4E, 0xBB, 0xAE, 0xE7, 0x04, 44 | 0x91, 0xFE, 0xAB, 0x0F, 0xA3, 0xF5, 0xB9, 0xD2, 0xFF, 0xBB, 0x52, 0x78, 0x19, 0x41, 0xCA, 0xCA, 45 | 0x12, 0x8F, 0x3E, 0xBE, 0x70, 0x55, 0x9B, 0x37, 0x90, 0xC3, 0xB9, 0xFF, 0x61, 0x6F, 0xA1, 0xD5, 46 | 0x39, 0x07, 0xB7, 0x9F, 0xA7, 0x3B, 0xF1, 0xB7, 0x2F, 0xF0, 0xCD, 0x5F, 0x58, 0x56, 0x61, 0x12, 47 | 0x2C, 0xF2, 0xE2, 0xB7, 0x74, 0x7D, 0x60, 0x8C, 0x87, 0xCD, 0xBB, 0xD8, 0x02, 0xCF, 0xE6, 0xFF, 48 | 0xF0, 0x51, 0x2D, 0x8A, 0x5D, 0x7A, 0x02, 0x92, 0x6F, 0x1C, 0x77, 0xD4, 0x82, 0x75, 0x4D, 0xB7, 49 | 0x54, 0x0E, 0xF5, 0xAA, 0x4A, 0x83, 0x46, 0xA8, 0x82, 0x6C, 0x25, 0xA7, 0x46, 0x32, 0x88, 0x78, 50 | 0xAD, 0x56, 0xE0, 0x9E, 0x32, 0xFD, 0x7F, 0xF5, 0xCC, 0x36, 0xCB, 0x8A, 0xB0, 0x18, 0x2F, 0x1A, 51 | 0x06, 0x52, 0xD1, 0xB1, 0x93, 0xB6, 0xFC, 0x98, 0x60, 0xDC, 0x40, 0xD9, 0xC2, 0xB9, 0x13, 0x84, 52 | 0x44, 0x3B, 0x80, 0xA3, 0xA5, 0x4A, 0x46, 0x98, 0xD6, 0x4E, 0x09, 0x5F, 0xB6, 0x5E, 0xCA, 0x79, 53 | 0xBC, 0xEA, 0x20, 0x79, 0x44, 0x88, 0x01, 0x92, 0xAD, 0x54, 0x56, 0x9B, 0x26, 0x9B, 0xB2, 0x92, 54 | 0xE3, 0x9F, 0xFC, 0x79, 0x32, 0x40, 0x89, 0x24, 0xF2, 0xC7, 0x31, 0x54, 0xED, 0x35, 0x0C, 0x9A, 55 | 0x2D, 0xFB, 0xA7, 0xA9, 0x21, 0xCD, 0x80, 0x86, 0xCE, 0x66, 0xAA, 0x3A, 0x7B, 0x53, 0x90, 0x05, 56 | 0x63, 0xDB, 0x06, 0xBB, 0xF7, 0xF7, 0xD6, 0xAC, 0x0B, 0x2C, 0xFB, 0xB2, 0xF6, 0x7C, 0x57, 0x20, 57 | 0x0E, 0x23, 0xDE, 0x2D, 0x74, 0x6C, 0x97, 0xB0, 0xA2, 0x2C, 0x14, 0x5F, 0xCF, 0x50, 0xE6, 0xB5, 58 | 0x23, 0x42, 0x65, 0x2C, 0xE3, 0xBF, 0xEC, 0x5A, 0x2A, 0xD3, 0xED, 0x06, 0xCB, 0xE8, 0x8A, 0x64, 59 | 0x20, 0x0E, 0xEF, 0x74, 0x72, 0xEF, 0xA3, 0x9D, 0x77, 0xF1, 0x6E, 0x63, 0x73, 0x62, 0xE0, 0x9A, 60 | 0x55, 0x19, 0x1E, 0x06, 0x73, 0x69, 0x73, 0xE6, 0x19, 0x6A, 0x01, 0x4F, 0x90, 0x9E, 0xF3, 0xB5, 61 | 0xE4, 0x45, 0x11, 0x39, 0x6D, 0x5A, 0x72, 0x39, 0xA5, 0x45, 0xA1, 0x4C, 0x31, 0x6B, 0x12, 0xE6, 62 | 0x7C, 0x66, 0x36, 0xFB, 0x69, 0x61, 0x3F, 0x20, 0xB2, 0xA5, 0x15, 0x76, 0xB6, 0x70, 0xA9, 0x93, 63 | 0x45, 0x85, 0xC0, 0x00, 0x57, 0xC8, 0x21, 0xF9, 0x01, 0xFB, 0xC0, 0x64, 0x52, 0xC8, 0x6F, 0x47, 64 | 0x49, 0x29, 0xE7, 0x15, 0xEA, 0x15, 0x1A, 0xE5, 0xF7, 0x02, 0xA4, 0x58, 0xC2, 0xCB, 0x31, 0x25, 65 | 0x3E, 0x88, 0xEC, 0xAA, 0xA8, 0xD8, 0x20, 0x2F, 0x7F, 0x66, 0x20, 0xB1, 0x7C, 0xB3, 0x2F, 0xFB, 66 | 0x44, 0x6A, 0xBD, 0xA0, 0x3E, 0x7E, 0x10, 0x36, 0x2C, 0x44, 0xE4, 0x20, 0xF1, 0x8B, 0x96, 0x6F, 67 | 0x42, 0xA2, 0x02, 0xFC, 0x70, 0xC3, 0xD8, 0x7A, 0xDC, 0xDE, 0xCC, 0xC9, 0x01, 0x5C, 0x17, 0x03, 68 | 0x39, 0x93, 0x07, 0x05, 0x34, 0xF0, 0xAA, 0xBE, 0x31, 0xF7, 0x0C, 0x39, 0x39, 0x5C, 0xDA, 0xF8, 69 | 0x83, 0x80, 0x48, 0x14, 0xC8, 0x6C, 0x3B, 0xF3, 0x09, 0xD4, 0x74, 0xAF, 0xC3, 0x60, 0xC2, 0xD4, 70 | 0x26, 0xB8, 0x9F, 0xEB, 0x38, 0xE4, 0x6E, 0x4B, 0xBD, 0x9A, 0x4B, 0x67, 0x60, 0x70, 0xD8, 0x02, 71 | 0x65, 0xAE, 0xE7, 0x26, 0x15, 0xBC, 0xF4, 0xE4, 0xE0, 0x62, 0xA4, 0xB4, 0x24, 0x6C, 0xD4, 0xC1, 72 | 0x5D, 0x59, 0xA3, 0x6B, 0x81, 0xBF, 0xD6, 0x58, 0x77, 0xE9, 0x4E, 0x55, 0xD0, 0xF5, 0x49, 0x42, 73 | 0xA1, 0xB7, 0x6F, 0xEC, 0xC0, 0x6F, 0x97, 0x17, 0xB7, 0x7E, 0xC2, 0xF5, 0xE3, 0x40, 0x5C, 0xC6, 74 | 0xA5, 0xF2, 0xFA, 0xB2, 0x4D, 0x70, 0x14, 0x2D, 0xCC, 0xCF, 0xAE, 0xBE, 0xB8, 0xDF, 0xEE, 0x55, 75 | 0x5D, 0x99, 0x2F, 0x67, 0x6F, 0xBC, 0x01, 0x3B, 0x53, 0x1B, 0x0E, 0xAA, 0x9F, 0x25, 0xCC, 0x0A, 76 | 0x95, 0xE3, 0x3B, 0xD3, 0x2F, 0xA0, 0xF4, 0xA5, 0x73, 0x66, 0xDC, 0x5E, 0x32, 0x20, 0xF2, 0xB8, 77 | 0xCC, 0x93, 0xE8, 0x64, 0xED, 0x99, 0x44, 0xEE, 0x63, 0x47, 0xB2, 0xC0, 0x79, 0x43, 0xD4, 0x21, 78 | 0xE8, 0xD1, 0x3E, 0xCB, 0xDA, 0x39, 0xCC, 0x65, 0xB6, 0x8B, 0xB4, 0x1A, 0xB0, 0xBF, 0xEF, 0xE4, 79 | 0x02, 0xB7, 0x79, 0xCA, 0xE3, 0x43, 0x1F, 0x77, 0xF8, 0x5F, 0x2B, 0x20, 0xF1, 0x33, 0xF5, 0xE8, 80 | 0x98, 0xCE, 0xA3, 0x7C, 0x8D, 0x5D, 0x67, 0xD1, 0xB9, 0xB3, 0x6B, 0x1A, 0x7A, 0xFC, 0xCC, 0x71, 81 | 0x78, 0x34, 0x3F, 0x0A, 0x68, 0xEA, 0xDE, 0x0D, 0xE4, 0x1E, 0x8B, 0xFF, 0xF5, 0x05, 0x74, 0xC6, 82 | 0x57, 0xEF, 0x20, 0x76, 0x3C, 0xA8, 0xE6, 0xAD, 0x13, 0x01, 0xD6, 0xB9, 0xF4, 0xF7, 0xB2, 0x36, 83 | 0xF0, 0xE1, 0xF4, 0xD1, 0xC4, 0xB9, 0xC5, 0x5B, 0xA1, 0xEE, 0xEB, 0xEF, 0xAC, 0x60, 0x1E, 0xCB, 84 | 0x4B, 0x7B, 0x5E, 0x7D, 0x58, 0x3A, 0x0A, 0x06, 0xFB, 0x27, 0x18, 0x37, 0x11, 0x9D, 0x3B, 0xDF, 85 | 0x7F, 0xDC, 0xEA, 0x29, 0x40, 0xC1, 0xF7, 0x63, 0xB7, 0xD4, 0x8C, 0xCC, 0x88, 0xCC, 0x0E, 0x25, 86 | 0x1B, 0x72, 0x07, 0xD4, 0x5A, 0xB8, 0x9F, 0xE2, 0x1F, 0x7B, 0x82, 0x55, 0xD2, 0x9F, 0xC8, 0xC9, 87 | 0x7E, 0x78, 0x7D, 0xDE, 0xD1, 0x0D, 0x8F, 0x0F, 0x44, 0x1A, 0x87, 0x3E, 0x48, 0x4C, 0xE6, 0xDA, 88 | 0x90, 0x6F, 0xA8, 0x42, 0x27, 0xC7, 0x00, 0x44, 0xBE, 0x6B, 0x6D, 0xCA, 0x4F, 0x91, 0x69, 0x6D, 89 | 0x77, 0xD3, 0x7B, 0x5B, 0x46, 0xEF, 0x6C, 0xC1, 0xC1, 0xE4, 0xF5, 0x62, 0x5B, 0x23, 0xEB, 0x33, 90 | 0xC0, 0x40, 0x71, 0x83, 0x9A, 0xE0, 0x96, 0x54, 0x06, 0x53, 0x9A, 0xE4, 0xEE, 0x31, 0xED, 0xE7, 91 | 0x1A, 0x90, 0x3A, 0x35, 0xB6, 0x0C, 0x25, 0x08, 0x6A, 0x6C, 0x30, 0x6E, 0x18, 0xE1, 0xCC, 0x83, 92 | 0xA8, 0x1A, 0xB8, 0xFE, 0xE5, 0x8A, 0xC7, 0x51, 0x6D, 0x12, 0x20, 0xE6, 0xD4, 0x9E, 0x4B, 0x1B, 93 | 0xB1, 0x9D, 0x67, 0xF5, 0xDF, 0xD8, 0x02, 0x7B, 0x05, 0x31, 0x2C, 0x00, 0x11, 0x0D, 0x23, 0x07, 94 | 0x76, 0xDF, 0xB3, 0xC7, 0x36, 0x94, 0x24, 0x89, 0x06, 0x5A, 0x76, 0xBF, 0x4F, 0x38, 0x0E, 0x7F, 95 | 0x1D, 0xBE, 0xEE, 0xAC, 0x1C, 0x09, 0x96, 0xCD, 0x76, 0xF8, 0x22, 0xEF, 0xE1, 0xB1, 0xD8, 0x50, 96 | 0xDE, 0x4C, 0x70, 0x8D, 0x01, 0x7B, 0x81, 0x93, 0xC1, 0x73, 0xCC, 0xA2, 0x1A, 0xB6, 0x1F, 0x67, 97 | 0x73, 0x1D, 0x78, 0x3D, 0x36, 0x36, 0x28, 0x12, 0x3F, 0x8A, 0x7F, 0xAD, 0xF9, 0x2C, 0xCB, 0x02, 98 | 0x30, 0xC3, 0x95, 0x89, 0xD1, 0x12, 0x3E, 0x06, 0xB5, 0x04, 0x87, 0x8C, 0x8C, 0x54, 0x4B, 0x49, 99 | 0xCF, 0x0B, 0xD2, 0x5E, 0xBE, 0xB5, 0xAF, 0x2D, 0xBD, 0x5D, 0x60, 0xCA, 0xEA, 0x22, 0x14, 0xC5, 100 | 0x26, 0x12, 0x68, 0x37, 0x91, 0x0C, 0x0D, 0x69, 0xF0, 0x8F, 0x44, 0xF5, 0x45, 0x16, 0x8D, 0x87, 101 | 0xE4, 0x07, 0x2D, 0x0A, 0xD3, 0xC6, 0x08, 0x3C, 0xE0, 0xF8, 0x7F, 0xCC, 0x25, 0x26, 0xDA, 0x7A, 102 | 0xA5, 0xC6, 0x3F, 0x13, 0x6B, 0x85, 0x3E, 0xA9, 0xFA, 0x8E, 0xEC, 0x13, 0x69, 0x0A, 0x62, 0x3B, 103 | 0xB1, 0x6A, 0xE8, 0x4A, 0x02, 0xC5, 0x0E, 0x39, 0x36, 0xFF, 0x4D, 0x99, 0xAA, 0x11, 0xFC, 0x1F, 104 | 0x83, 0x8F, 0x46, 0x2E, 0xC5, 0x94, 0x41, 0xC0, 0x63, 0x9A, 0x99, 0x86, 0x97, 0x59, 0x74, 0xE6, 105 | 0x68, 0xDD, 0xAA, 0x4C, 0x53, 0x07, 0xCA, 0x0B, 0xEC, 0xFE, 0xE5, 0xF6, 0xF1, 0x3B, 0x4E, 0x84, 106 | 0x3B, 0x40, 0x81, 0x17, 0x3F, 0x69, 0x99, 0xB3, 0x65, 0x86, 0x3C, 0x7E, 0x77, 0xDF, 0x16, 0x48, 107 | 0x5D, 0x93, 0x4E, 0x35, 0x70, 0xA0, 0xDB, 0x29, 0x98, 0xF6, 0x10, 0x0B, 0xA0, 0xA3, 0x88, 0x90, 108 | 0x28, 0xAB, 0x0C, 0xC5, 0x37, 0x17, 0x7A, 0xC4, 0x6B, 0x50, 0x9A, 0x1E, 0x43, 0xAC, 0xCA, 0x7A, 109 | 0x22, 0x9B, 0xF1, 0x77, 0xC7, 0xD3, 0xF6, 0x3C, 0x6F, 0x4A, 0xA7, 0x75, 0x34, 0x8B, 0x5E, 0xC2, 110 | 0xD6, 0xC9, 0x6E, 0x5D, 0xBC, 0xF2, 0x98, 0x81, 0x3D, 0x97, 0xDE, 0xCA, 0x13, 0x44, 0xB2, 0x6C, 111 | 0x7B, 0x0F, 0xE4, 0xF5, 0xE8, 0x75, 0xD2, 0x20, 0x9F, 0x09, 0xE0, 0xA0, 0x33, 0xB4, 0xDC, 0xEF, 112 | 0xA0, 0x12, 0x94, 0xF3, 0x49, 0xB4, 0xF7, 0x77, 0x25, 0xB9, 0xD5, 0xF6, 0xA4, 0x28, 0x54, 0x56, 113 | 0x7D, 0x82, 0x6E, 0xC9, 0xED, 0x7E, 0xC7, 0x55, 0x00, 0x1F, 0x5F, 0x6D, 0xD6, 0xF4, 0x6E, 0xE0, 114 | 0x74, 0x1E, 0x0F, 0xD5, 0x26, 0xFC, 0x2C, 0x9E, 0x4E, 0xE8, 0x0C, 0x95, 0x15, 0x03, 0x0B, 0xAE, 115 | 0x90, 0xE7, 0x68, 0xD6, 0xD2, 0x22, 0xBC, 0x2D, 0x86, 0x08, 0xDB, 0x1D, 0x5C, 0xAC, 0x57, 0xB1, 116 | 0xD9, 0x9C, 0x33, 0x0C, 0x9F, 0xF2, 0xFA, 0xAD, 0xA9, 0x25, 0x80, 0x0A, 0xBB, 0x7D, 0xE1, 0xE9, 117 | 0xC5, 0xE3, 0xC7, 0x4A, 0x4B, 0xCD, 0xD9, 0x17, 0xBD, 0x68, 0x19, 0x47, 0xE0, 0x07, 0xCA, 0xE1, 118 | }; 119 | -------------------------------------------------------------------------------- /res/nope.h: -------------------------------------------------------------------------------- 1 | #ifndef NOPE_H 2 | #define NOPE_H 3 | 4 | #include 5 | 6 | extern const uint8_t nope_tiles[1792]; 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /res/tiles.c: -------------------------------------------------------------------------------- 1 | #pragma bank 1 2 | 3 | #include 4 | 5 | const uint8_t constantTiles[] = { 6 | // Filled 7 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 8 | // Arrow 9 | // 0x00, 0x00, 0x00, 0x20, 0x00, 0x30, 0x00, 0x38, 0x04, 0x38, 0x08, 0x30, 0x10, 0x20, 0x20, 0x00, 10 | 0x00, 0x00, 0x20, 0x00, 0x30, 0x00, 0x38, 0x00, 0x38, 0x04, 0x30, 0x08, 0x20, 0x10, 0x00, 0x20, 11 | // Border Horizontal 12 | 0xff, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 13 | // Border Vertical 14 | 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 15 | // Menu Border Left 16 | 0x83, 0x9f, 0xa7, 0x9f, 0xb3, 0x8f, 0xa6, 0x9f, 0x83, 0x9f, 0xa7, 0x9f, 0xb3, 0x8f, 0xa6, 0x9f, 17 | // Menu Border Top 18 | 0xff, 0xff, 0x00, 0x00, 0xee, 0x00, 0x44, 0xbb, 0x00, 0xff, 0xaa, 0xff, 0xff, 0xff, 0x77, 0xff, 19 | 20 | // Beep Cursor 21 | 0xfe, 0x00, 0xff, 0x7d, 0xc3, 0x41, 0xc3, 0x41, 0xc3, 0x41, 0xc3, 0x41, 0xff, 0x01, 0x7f, 0x7f, 22 | 23 | // Free space 31 more 24 | 0x00, 0x00, 0x7e, 0x00, 0x42, 0x3c, 0x5a, 0x3c, 0xa5, 0xc3, 0xbd, 0xc3, 0x81, 0xff, 0xff, 0xff, 25 | 0x00, 0x00, 0x7e, 0x00, 0x42, 0x3c, 0x5a, 0x3c, 0xa5, 0xc3, 0xbd, 0xc3, 0x81, 0xff, 0xff, 0xff, 26 | 0x00, 0x00, 0x7e, 0x00, 0x42, 0x3c, 0x5a, 0x3c, 0xa5, 0xc3, 0xbd, 0xc3, 0x81, 0xff, 0xff, 0xff, 27 | 0x00, 0x00, 0x7e, 0x00, 0x42, 0x3c, 0x5a, 0x3c, 0xa5, 0xc3, 0xbd, 0xc3, 0x81, 0xff, 0xff, 0xff, 28 | 0x00, 0x00, 0x7e, 0x00, 0x42, 0x3c, 0x5a, 0x3c, 0xa5, 0xc3, 0xbd, 0xc3, 0x81, 0xff, 0xff, 0xff, 29 | 0x00, 0x00, 0x7e, 0x00, 0x42, 0x3c, 0x5a, 0x3c, 0xa5, 0xc3, 0xbd, 0xc3, 0x81, 0xff, 0xff, 0xff, 30 | 0x00, 0x00, 0x7e, 0x00, 0x42, 0x3c, 0x5a, 0x3c, 0xa5, 0xc3, 0xbd, 0xc3, 0x81, 0xff, 0xff, 0xff, 31 | 0x00, 0x00, 0x7e, 0x00, 0x42, 0x3c, 0x5a, 0x3c, 0xa5, 0xc3, 0xbd, 0xc3, 0x81, 0xff, 0xff, 0xff, 32 | 0x00, 0x00, 0x7e, 0x00, 0x42, 0x3c, 0x5a, 0x3c, 0xa5, 0xc3, 0xbd, 0xc3, 0x81, 0xff, 0xff, 0xff, 33 | 0x00, 0x00, 0x7e, 0x00, 0x42, 0x3c, 0x5a, 0x3c, 0xa5, 0xc3, 0xbd, 0xc3, 0x81, 0xff, 0xff, 0xff, 34 | 0x00, 0x00, 0x7e, 0x00, 0x42, 0x3c, 0x5a, 0x3c, 0xa5, 0xc3, 0xbd, 0xc3, 0x81, 0xff, 0xff, 0xff, 35 | 0x00, 0x00, 0x7e, 0x00, 0x42, 0x3c, 0x5a, 0x3c, 0xa5, 0xc3, 0xbd, 0xc3, 0x81, 0xff, 0xff, 0xff, 36 | 0x00, 0x00, 0x7e, 0x00, 0x42, 0x3c, 0x5a, 0x3c, 0xa5, 0xc3, 0xbd, 0xc3, 0x81, 0xff, 0xff, 0xff, 37 | 0x00, 0x00, 0x7e, 0x00, 0x42, 0x3c, 0x5a, 0x3c, 0xa5, 0xc3, 0xbd, 0xc3, 0x81, 0xff, 0xff, 0xff, 38 | 0x00, 0x00, 0x7e, 0x00, 0x42, 0x3c, 0x5a, 0x3c, 0xa5, 0xc3, 0xbd, 0xc3, 0x81, 0xff, 0xff, 0xff, 39 | 0x00, 0x00, 0x7e, 0x00, 0x42, 0x3c, 0x5a, 0x3c, 0xa5, 0xc3, 0xbd, 0xc3, 0x81, 0xff, 0xff, 0xff, 40 | 0x00, 0x00, 0x7e, 0x00, 0x42, 0x3c, 0x5a, 0x3c, 0xa5, 0xc3, 0xbd, 0xc3, 0x81, 0xff, 0xff, 0xff, 41 | 0x00, 0x00, 0x7e, 0x00, 0x42, 0x3c, 0x5a, 0x3c, 0xa5, 0xc3, 0xbd, 0xc3, 0x81, 0xff, 0xff, 0xff, 42 | 0x00, 0x00, 0x7e, 0x00, 0x42, 0x3c, 0x5a, 0x3c, 0xa5, 0xc3, 0xbd, 0xc3, 0x81, 0xff, 0xff, 0xff, 43 | 0x00, 0x00, 0x7e, 0x00, 0x42, 0x3c, 0x5a, 0x3c, 0xa5, 0xc3, 0xbd, 0xc3, 0x81, 0xff, 0xff, 0xff, 44 | 0x00, 0x00, 0x7e, 0x00, 0x42, 0x3c, 0x5a, 0x3c, 0xa5, 0xc3, 0xbd, 0xc3, 0x81, 0xff, 0xff, 0xff, 45 | 0x00, 0x00, 0x7e, 0x00, 0x42, 0x3c, 0x5a, 0x3c, 0xa5, 0xc3, 0xbd, 0xc3, 0x81, 0xff, 0xff, 0xff, 46 | 0x00, 0x00, 0x7e, 0x00, 0x42, 0x3c, 0x5a, 0x3c, 0xa5, 0xc3, 0xbd, 0xc3, 0x81, 0xff, 0xff, 0xff, 47 | 0x00, 0x00, 0x7e, 0x00, 0x42, 0x3c, 0x5a, 0x3c, 0xa5, 0xc3, 0xbd, 0xc3, 0x81, 0xff, 0xff, 0xff, 48 | 0x00, 0x00, 0x7e, 0x00, 0x42, 0x3c, 0x5a, 0x3c, 0xa5, 0xc3, 0xbd, 0xc3, 0x81, 0xff, 0xff, 0xff, 49 | 0x00, 0x00, 0x7e, 0x00, 0x42, 0x3c, 0x5a, 0x3c, 0xa5, 0xc3, 0xbd, 0xc3, 0x81, 0xff, 0xff, 0xff, 50 | 0x00, 0x00, 0x7e, 0x00, 0x42, 0x3c, 0x5a, 0x3c, 0xa5, 0xc3, 0xbd, 0xc3, 0x81, 0xff, 0xff, 0xff, 51 | 0x00, 0x00, 0x7e, 0x00, 0x42, 0x3c, 0x5a, 0x3c, 0xa5, 0xc3, 0xbd, 0xc3, 0x81, 0xff, 0xff, 0xff, 52 | 0x00, 0x00, 0x7e, 0x00, 0x42, 0x3c, 0x5a, 0x3c, 0xa5, 0xc3, 0xbd, 0xc3, 0x81, 0xff, 0xff, 0xff, 53 | 0x00, 0x00, 0x7e, 0x00, 0x42, 0x3c, 0x5a, 0x3c, 0xa5, 0xc3, 0xbd, 0xc3, 0x81, 0xff, 0xff, 0xff, 54 | 0x00, 0x00, 0x7e, 0x00, 0x42, 0x3c, 0x5a, 0x3c, 0xa5, 0xc3, 0xbd, 0xc3, 0x81, 0xff, 0xff, 0xff, 55 | }; 56 | 57 | const uint8_t upperLowerDoubleTiles[] = { 58 | 0x00, 0x00, 0x7e, 0x00, 0x42, 0x3c, 0x5a, 0x3c, 0xa5, 0xc3, 0xbd, 0xc3, 0x81, 0xff, 0xff, 0xff, 59 | 0x00, 0x00, 0x7e, 0x00, 0x42, 0x3c, 0x5a, 0x3c, 0xa5, 0xc3, 0xbd, 0xc3, 0x81, 0xff, 0xff, 0xff, 60 | 0x00, 0x00, 0x7e, 0x00, 0x42, 0x3c, 0x5a, 0x3c, 0xa5, 0xc3, 0xbd, 0xc3, 0x81, 0xff, 0xff, 0xff, 61 | 0x00, 0x00, 0x7e, 0x00, 0x42, 0x3c, 0x5a, 0x3c, 0xa5, 0xc3, 0xbd, 0xc3, 0x81, 0xff, 0xff, 0xff, 62 | 0x00, 0x00, 0x7e, 0x00, 0x42, 0x3c, 0x5a, 0x3c, 0xa5, 0xc3, 0xbd, 0xc3, 0x81, 0xff, 0xff, 0xff, 63 | 0x00, 0x00, 0x7e, 0x00, 0x42, 0x3c, 0x5a, 0x3c, 0xa5, 0xc3, 0xbd, 0xc3, 0x81, 0xff, 0xff, 0xff, 64 | 0x00, 0x00, 0x7e, 0x00, 0x42, 0x3c, 0x5a, 0x3c, 0xa5, 0xc3, 0xbd, 0xc3, 0x81, 0xff, 0xff, 0xff, 65 | 0x00, 0x00, 0x7e, 0x00, 0x42, 0x3c, 0x5a, 0x3c, 0xa5, 0xc3, 0xbd, 0xc3, 0x81, 0xff, 0xff, 0xff, 66 | 0x00, 0x00, 0x7e, 0x00, 0x42, 0x3c, 0x5a, 0x3c, 0xa5, 0xc3, 0xbd, 0xc3, 0x81, 0xff, 0xff, 0xff, 67 | 0x00, 0x00, 0x7e, 0x00, 0x42, 0x3c, 0x5a, 0x3c, 0xa5, 0xc3, 0xbd, 0xc3, 0x81, 0xff, 0xff, 0xff, 68 | 0x00, 0x00, 0x7e, 0x00, 0x42, 0x3c, 0x5a, 0x3c, 0xa5, 0xc3, 0xbd, 0xc3, 0x81, 0xff, 0xff, 0xff, 69 | 0x00, 0x00, 0x7e, 0x00, 0x42, 0x3c, 0x5a, 0x3c, 0xa5, 0xc3, 0xbd, 0xc3, 0x81, 0xff, 0xff, 0xff, 70 | 0x00, 0x00, 0x7e, 0x00, 0x42, 0x3c, 0x5a, 0x3c, 0xa5, 0xc3, 0xbd, 0xc3, 0x81, 0xff, 0xff, 0xff, 71 | 0x00, 0x00, 0x7e, 0x00, 0x42, 0x3c, 0x5a, 0x3c, 0xa5, 0xc3, 0xbd, 0xc3, 0x81, 0xff, 0xff, 0xff, 72 | 0x00, 0x00, 0x7e, 0x00, 0x42, 0x3c, 0x5a, 0x3c, 0xa5, 0xc3, 0xbd, 0xc3, 0x81, 0xff, 0xff, 0xff, 73 | 0x00, 0x00, 0x7e, 0x00, 0x42, 0x3c, 0x5a, 0x3c, 0xa5, 0xc3, 0xbd, 0xc3, 0x81, 0xff, 0xff, 0xff, 74 | }; 75 | 76 | #define HBOR 0xFF 77 | // bytes marked HBOR (horizontal border) are used for hidden data 78 | 79 | const uint8_t tiles_thumbnail[] = { 80 | HBOR, 0xFF, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 81 | HBOR, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 82 | HBOR, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 83 | HBOR, 0xFF, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 84 | 0x80, 0x80, 0x87, 0x80, 0x8F, 0x80, 0x8C, 0x83, 0x81, 0x8C, 0x83, 0x80, 0x87, 0x80, 0x8E, 0x81, 85 | 0x00, 0x00, 0x9C, 0x00, 0xDC, 0x00, 0xCC, 0x10, 0xCF, 0x00, 0x8F, 0x40, 0x0C, 0x83, 0x0C, 0x00, 86 | 0x00, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x00, 0x0C, 0x9D, 0x00, 0xDD, 0x00, 0xCC, 0x11, 0xCC, 0x00, 87 | 0x01, 0x01, 0x01, 0x01, 0xC1, 0x01, 0xC1, 0x01, 0xF1, 0x01, 0xF1, 0x01, 0xC1, 0x31, 0xC1, 0x01, 88 | 0x8F, 0x80, 0x8F, 0x80, 0x80, 0x8F, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 89 | 0xCF, 0x00, 0xCF, 0x00, 0x00, 0xCF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 90 | 0xDE, 0x00, 0x9E, 0x40, 0x00, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 91 | 0xF1, 0x01, 0x71, 0x81, 0x01, 0x71, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 92 | 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, HBOR, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 93 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, HBOR, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 94 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, HBOR, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 95 | 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, HBOR, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 96 | }; 97 | -------------------------------------------------------------------------------- /res/tiles.h: -------------------------------------------------------------------------------- 1 | #ifndef TILES_H 2 | #define TILES_H 3 | 4 | #include 5 | 6 | #define NUM_CONSTANT_TILES 37 7 | #define BLNK OFFSET_BLANK 8 | 9 | extern const uint8_t constantTiles[]; 10 | extern const uint8_t upperLowerDoubleTiles[]; 11 | extern const uint8_t tiles_thumbnail[]; 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /src/analysis.c: -------------------------------------------------------------------------------- 1 | #pragma bank 255 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "typedefs/Histogram.h" 8 | #include "gbcamera.h" 9 | #include "globals.h" 10 | #include "defines.h" 11 | #include "joypad.h" 12 | #include "images.h" 13 | 14 | 15 | const uint8_t bitsSetLUT[256] = { 16 | 0u, 1u, 1u, 2u, 1u, 2u, 2u, 3u, 1u, 2u, 2u, 3u, 2u, 3u, 3u, 4u, 17 | 1u, 2u, 2u, 3u, 2u, 3u, 3u, 4u, 2u, 3u, 3u, 4u, 3u, 4u, 4u, 5u, 18 | 1u, 2u, 2u, 3u, 2u, 3u, 3u, 4u, 2u, 3u, 3u, 4u, 3u, 4u, 4u, 5u, 19 | 2u, 3u, 3u, 4u, 3u, 4u, 4u, 5u, 3u, 4u, 4u, 5u, 4u, 5u, 5u, 6u, 20 | 1u, 2u, 2u, 3u, 2u, 3u, 3u, 4u, 2u, 3u, 3u, 4u, 3u, 4u, 4u, 5u, 21 | 2u, 3u, 3u, 4u, 3u, 4u, 4u, 5u, 3u, 4u, 4u, 5u, 4u, 5u, 5u, 6u, 22 | 2u, 3u, 3u, 4u, 3u, 4u, 4u, 5u, 3u, 4u, 4u, 5u, 4u, 5u, 5u, 6u, 23 | 3u, 4u, 4u, 5u, 4u, 5u, 5u, 6u, 4u, 5u, 5u, 6u, 5u, 6u, 6u, 7u, 24 | 1u, 2u, 2u, 3u, 2u, 3u, 3u, 4u, 2u, 3u, 3u, 4u, 3u, 4u, 4u, 5u, 25 | 2u, 3u, 3u, 4u, 3u, 4u, 4u, 5u, 3u, 4u, 4u, 5u, 4u, 5u, 5u, 6u, 26 | 2u, 3u, 3u, 4u, 3u, 4u, 4u, 5u, 3u, 4u, 4u, 5u, 4u, 5u, 5u, 6u, 27 | 3u, 4u, 4u, 5u, 4u, 5u, 5u, 6u, 4u, 5u, 5u, 6u, 5u, 6u, 6u, 7u, 28 | 2u, 3u, 3u, 4u, 3u, 4u, 4u, 5u, 3u, 4u, 4u, 5u, 4u, 5u, 5u, 6u, 29 | 3u, 4u, 4u, 5u, 4u, 5u, 5u, 6u, 4u, 5u, 5u, 6u, 5u, 6u, 6u, 7u, 30 | 3u, 4u, 4u, 5u, 4u, 5u, 5u, 6u, 4u, 5u, 5u, 6u, 5u, 6u, 6u, 7u, 31 | 4u, 5u, 5u, 6u, 5u, 6u, 6u, 7u, 5u, 6u, 6u, 7u, 6u, 7u, 7u, 8u, 32 | }; 33 | 34 | 35 | void createHistogram(uint8_t *data, Histogram *histogram) BANKED { 36 | static Histogram hist; 37 | 38 | hist.white = hist.lgrey = hist.dgrey = hist.black = 0; 39 | hist.time = sys_time; 40 | 41 | static uint8_t lower, upper; 42 | for (uint8_t * ptr = data; ptr < data + CAMERA_IMAGE_SIZE; ) { 43 | lower = *ptr++; 44 | upper = *ptr++; 45 | hist.white += bitsSetLUT[~lower & ~upper]; 46 | hist.lgrey += bitsSetLUT[lower & ~upper]; 47 | hist.dgrey += bitsSetLUT[~lower & upper]; 48 | hist.black += bitsSetLUT[lower & upper]; 49 | } 50 | 51 | hist.time = sys_time - hist.time; 52 | 53 | *histogram = hist; 54 | } 55 | 56 | void getHistogram(uint8_t imageIndex, uint8_t *tileMap) BANKED { 57 | Histogram histogram; 58 | uint8_t imageSlot = getImageSlot(imageIndex); 59 | uint8_t digits[10]; 60 | BCD bcd = MAKE_BCD(0); 61 | 62 | SWITCH_RAM(images[imageSlot]->bank); 63 | createHistogram(images[imageSlot]->tilesUpper, &histogram); 64 | memcpy(&tileMap[0], 65 | " " 66 | " Histogram " 67 | " " 68 | " White " 69 | " ????? " 70 | " " 71 | " Light grey " 72 | " ????? " 73 | " " 74 | " Dark grey " 75 | " ????? " 76 | " " 77 | " Black " 78 | " ????? " 79 | " " 80 | " Time " 81 | " ????? " 82 | " ", 83 | 360); 84 | 85 | uint2bcd(histogram.white, &bcd); 86 | bcd2text(&bcd, 48u, digits); 87 | memcpy(&tileMap[84], &digits[3], 5); 88 | 89 | uint2bcd(histogram.lgrey, &bcd); 90 | bcd2text(&bcd, 48u, digits); 91 | memcpy(&tileMap[144], &digits[3], 5); 92 | 93 | uint2bcd(histogram.dgrey, &bcd); 94 | bcd2text(&bcd, 48u, digits); 95 | memcpy(&tileMap[204], &digits[3], 5); 96 | 97 | uint2bcd(histogram.black, &bcd); 98 | bcd2text(&bcd, 48u, digits); 99 | memcpy(&tileMap[264], &digits[3], 5); 100 | 101 | uint2bcd(histogram.time, &bcd); 102 | bcd2text(&bcd, 48u, digits); 103 | memcpy(&tileMap[324], &digits[3], 5); 104 | } 105 | 106 | void displayHistogram(uint8_t imageIndex) BANKED { 107 | move_sprite(SPRITE_MENU_INDICATOR, 0, 0); 108 | 109 | getHistogram(imageIndex, imageInfo); 110 | 111 | waitRelease(); 112 | 113 | fill_win_rect(0, 0, 20, 18, OFFSET_BLANK); 114 | move_win(6, 0); 115 | set_win_based_tiles(0, 0, 20, 18, imageInfo, OFFSET_FONT - 32); 116 | 117 | while (jp != J_B && jp != J_A) { 118 | wait_vbl_done(); 119 | } 120 | 121 | fill_win_rect(0, 0, 20, 18, OFFSET_BLANK); 122 | move_win(78, 0); 123 | } 124 | -------------------------------------------------------------------------------- /src/bankedData.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "globals.h" 4 | 5 | static uint8_t savedBank; 6 | 7 | void set_bkg_tiles_banked(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t *map, uint8_t bank) { 8 | savedBank = _current_bank; 9 | SWITCH_ROM(bank); 10 | set_bkg_tiles(x, y, w, h, map); 11 | SWITCH_ROM(savedBank); 12 | } 13 | 14 | void set_bkg_data_banked(uint8_t offset, uint8_t length, uint8_t *data, uint8_t bank) { 15 | savedBank = _current_bank; 16 | SWITCH_ROM(bank); 17 | set_bkg_data(offset, length, data); 18 | SWITCH_ROM(savedBank); 19 | } 20 | 21 | void set_data_banked(uint16_t *address, uint8_t *data, uint16_t length, uint8_t bank) { 22 | savedBank = _current_bank; 23 | SWITCH_ROM(bank); 24 | set_data(address, data, length); 25 | SWITCH_ROM(savedBank); 26 | } 27 | -------------------------------------------------------------------------------- /src/bleep.c: -------------------------------------------------------------------------------- 1 | #pragma bank 255 2 | 3 | #include 4 | #include 5 | #include 6 | #include "globals.h" 7 | #include "images.h" 8 | #include "defines.h" 9 | #include "joypad.h" 10 | #include "imageIndexing.h" 11 | #include "images.h" 12 | 13 | // Manual selection of tones 14 | //const uint8_t freqLookupN33[] = { 0x00, 0x44, 0x70, 0x90, 0xa4, 0xb4, 0xc2, 0xcd, 0xd7, 0xde, 0xe4, 0xe8, 0xed, 0xf0, 0xf2, 0xf4, }; 15 | //const uint8_t freqLookupN34[] = { 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, }; 16 | 17 | 18 | // Manual selection of tones ~ 100Hz steps 19 | // 809, 910, 1024, 1130, 1214, 1338, 1425, 1489, 1560, 1638, 1771, 1928, 2114, 2260, 2427, 2521 | 2979, 3449 20 | const uint8_t freqLookupN33[] = { 0xaf, 0xb8, 0xc0, 0xc6, 0xca, 0xcf, 0xd2, 0xd4, 0xd6, 0xd8, 0xdb, 0xde, 0xe1, 0xe3, 0xe5, 0xe6, 0xea, 0xed, }; 21 | const uint8_t freqLookupN34[] = { 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, }; 22 | 23 | inline void silence() { 24 | NR30_REG=0x00; 25 | } 26 | 27 | uint8_t breakBleep = 0; 28 | 29 | inline void loadWaveform() { 30 | const uint8_t sinewave[16] = { 0x89, 0xbc, 0xde, 0xff, 0xff, 0xfe, 0xdb, 0xa8, 0x75, 0x42, 0x10, 0x00, 0x00, 0x12, 0x34, 0x67 }; 31 | // const uint8_t sinewavex2[16] = { 0x8b, 0xdf, 0xfe, 0xc9, 0x63, 0x10, 0x02, 0x47, 0xbd, 0xff, 0xec, 0x96, 0x31, 0x00, 0x24, 0x7b }; 32 | // const uint8_t randwave[16] = { 0x13, 0x08, 0xd2, 0x53, 0xa1, 0xa0, 0x4f, 0x4c, 0x99, 0xbc, 0xe8, 0x7f, 0x62, 0xe7, 0x5b, 0xd6 }; 33 | // const uint8_t sawtoothwave[16] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }; 34 | // const uint8_t sawtoothwave2[16] = { 0x02, 0x46, 0x8a, 0xce, 0x02, 0x46, 0x8a, 0xce, 0x02, 0x46, 0x8a, 0xce, 0x02, 0x46, 0x8a, 0xce, }; 35 | // const uint8_t single[16] = { 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 36 | 37 | memcpy(_AUD3WAVERAM, sinewave, 16); 38 | } 39 | 40 | void breakSound(uint8_t times) BANKED { 41 | for(uint8_t i = 0; i < times; i++) { 42 | wait_vbl_done(); 43 | if (jp == J_B) { 44 | breakBleep = 1; 45 | move_sprite(SPRITE_BLEEP_CURSOR, 0, 0); 46 | silence(); 47 | return; 48 | } 49 | } 50 | } 51 | 52 | void playBeep(uint8_t r1, uint8_t r2) BANKED { 53 | NR30_REG=0x80; 54 | NR31_REG=0x00; 55 | NR32_REG=0x20; 56 | NR33_REG=r1; 57 | NR34_REG=r2; 58 | 59 | breakSound(1); 60 | silence(); 61 | breakSound(1); 62 | } 63 | 64 | void bleep() BANKED { 65 | breakBleep = 0; 66 | loadWaveform(); 67 | uint8_t imageAddress = getAddressForIndex(imageIndex); 68 | SWITCH_RAM(images[imageAddress]->bank); 69 | uint8_t i = 0; 70 | 71 | playBeep(freqLookupN33[17], freqLookupN34[17]); 72 | 73 | for (i = 0; i < 32; i += 1) { 74 | playBeep(freqLookupN33[i % 16], freqLookupN34[i % 16]); 75 | 76 | if (breakBleep == 1) { 77 | move_sprite(SPRITE_BLEEP_CURSOR, 0, 0); 78 | joypadConsumed(); 79 | return; 80 | } 81 | } 82 | 83 | // Loop upper part 84 | for (uint16_t i = 0; i < HALF_IMAGE_SIZE; i++) { 85 | uint8_t tileByte = images[imageAddress]->tilesUpper[i]; 86 | 87 | if (i % 16 == 0) { 88 | uint8_t tileIndex = i >> 4; 89 | uint8_t cursorX = tileIndex % 16; 90 | uint8_t cursorY = tileIndex >> 4; 91 | move_sprite(SPRITE_BLEEP_CURSOR, (cursorX << 3) + 24, (cursorY << 3) + 32); 92 | playBeep(freqLookupN33[17], freqLookupN34[17]); 93 | } 94 | 95 | playBeep(freqLookupN33[tileByte >> 4], freqLookupN34[tileByte >> 4]); 96 | playBeep(freqLookupN33[tileByte % 16], freqLookupN34[tileByte % 16]); 97 | 98 | if (breakBleep == 1) { 99 | move_sprite(SPRITE_BLEEP_CURSOR, 0, 0); 100 | joypadConsumed(); 101 | return; 102 | } 103 | } 104 | 105 | // Loop lower part 106 | for (uint16_t i = 0; i < HALF_IMAGE_SIZE; i++) { 107 | uint8_t tileByte = images[imageAddress]->tilesLower[i]; 108 | 109 | if (i % 16 == 0) { 110 | uint8_t tileIndex = i >> 4; 111 | uint8_t cursorX = tileIndex % 16; 112 | uint8_t cursorY = tileIndex >> 4; 113 | move_sprite(SPRITE_BLEEP_CURSOR, (cursorX << 3) + 24, (cursorY << 3) + 32 + 56); 114 | playBeep(freqLookupN33[17], freqLookupN34[17]); 115 | } 116 | 117 | playBeep(freqLookupN33[tileByte >> 4], freqLookupN34[tileByte >> 4]); 118 | playBeep(freqLookupN33[tileByte % 16], freqLookupN34[tileByte % 16]); 119 | 120 | if (breakBleep == 1) { 121 | move_sprite(SPRITE_BLEEP_CURSOR, 0, 0); 122 | joypadConsumed(); 123 | return; 124 | } 125 | } 126 | 127 | playBeep(freqLookupN33[17], freqLookupN34[17]); 128 | 129 | move_sprite(SPRITE_BLEEP_CURSOR, 0, 0); 130 | joypadConsumed(); 131 | } 132 | -------------------------------------------------------------------------------- /src/camera.c: -------------------------------------------------------------------------------- 1 | #pragma bank 255 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "gbcamera.h" 8 | #include "globals.h" 9 | #include "defines.h" 10 | #include "menus/shootingManualMenuItems.h" 11 | #include "modeShootingManual.h" 12 | #include "utils.h" 13 | #include "joypad.h" 14 | #include "values.h" 15 | 16 | void setDitherMatrix(uint8_t ditherSet, uint8_t contrast) BANKED { 17 | SWITCH_RAM(16); 18 | 19 | for (uint16_t i = 0; i < 48; i += 1) { 20 | if (ditherSet == DITHERSET_HIGH | DITHER_ON) { 21 | memcpy(CAM_REG_DITHERPATTERN, ditherHighLightValues[contrast], 48); 22 | } else if (ditherSet == DITHERSET_LOW | DITHER_ON) { 23 | memcpy(CAM_REG_DITHERPATTERN, ditherLowLightValues[contrast], 48); 24 | } else if (ditherSet == DITHERSET_HIGH | DITHER_OFF) { 25 | memcpy(CAM_REG_DITHERPATTERN, ditherNoHighLightValues[contrast], 48); 26 | } else if (ditherSet == DITHERSET_LOW | DITHER_OFF) { 27 | memcpy(CAM_REG_DITHERPATTERN, ditherNoLowLightValues[contrast], 48); 28 | } 29 | } 30 | } 31 | 32 | void initCam() BANKED { 33 | if ( 34 | loadSettingsFromRAM() == SETTINGS_REQUIRE_RESET || 35 | (joypad() == (J_START | J_SELECT)) // "factory" reset 36 | ) { 37 | restoreDefaults(); // reset all sensor params to default 38 | boop(); 39 | pause(20); 40 | beep(); 41 | } 42 | 43 | setDitherMatrix(getMenuValue(&ditherSetsMenu), getMenuValue(&contrastsMenu)); 44 | } 45 | 46 | void capture(uint8_t capt, uint8_t edExOpGain, uint16_t expTime, uint8_t edRInvVref, uint8_t zeroVout) BANKED { 47 | SWITCH_RAM(16); 48 | 49 | CAM_REG_EDEXOPGAIN = edExOpGain; 50 | CAM_REG_EXPTIME = expTime; 51 | CAM_REG_EDRAINVVREF = edRInvVref; 52 | CAM_REG_ZEROVOUT = zeroVout; 53 | 54 | isCapturing = 1; 55 | 56 | CAM_REG_CAPTURE = capt; 57 | 58 | captureJoypadISR(); 59 | 60 | while (CAM_REG_CAPTURE % 2) { 61 | if (!jp) { 62 | captureJoypadISR(); 63 | } 64 | } 65 | 66 | isCapturing = 0; 67 | } 68 | -------------------------------------------------------------------------------- /src/debug.c: -------------------------------------------------------------------------------- 1 | #pragma bank 255 2 | 3 | #include 4 | #include 5 | #include "defines.h" 6 | #include "joypad.h" 7 | #include "utils.h" 8 | #include "gbcamera.h" 9 | #include "mainMenu.h" 10 | #include "overlays/overlays.h" 11 | 12 | void debugMenu() BANKED { 13 | if (jp == J_B) { 14 | menuSelectMode(MAIN_LOOP_MENU); 15 | joypadConsumed(); 16 | } 17 | } 18 | 19 | void initDebug() BANKED { 20 | clearBkg(); 21 | hideOverlay(); 22 | move_sprite(SPRITE_MENU_INDICATOR, 0, 0); 23 | 24 | SWITCH_RAM(0); 25 | writeNumber(0, 0, 3, cam_game_data.imageslots[0]); 26 | writeNumber(4, 0, 3, cam_game_data.imageslots[1]); 27 | writeNumber(8, 0, 3, cam_game_data.imageslots[2]); 28 | writeNumber(12, 0, 3, cam_game_data.imageslots[3]); 29 | writeNumber(16, 0, 3, cam_game_data.imageslots[4]); 30 | writeNumber(0, 1, 3, cam_game_data.imageslots[5]); 31 | writeNumber(4, 1, 3, cam_game_data.imageslots[6]); 32 | writeNumber(8, 1, 3, cam_game_data.imageslots[7]); 33 | writeNumber(12, 1, 3, cam_game_data.imageslots[8]); 34 | writeNumber(16, 1, 3, cam_game_data.imageslots[9]); 35 | 36 | writeNumber(0, 2, 3, cam_game_data.imageslots[10]); 37 | writeNumber(4, 2, 3, cam_game_data.imageslots[11]); 38 | writeNumber(8, 2, 3, cam_game_data.imageslots[12]); 39 | writeNumber(12, 2, 3, cam_game_data.imageslots[13]); 40 | writeNumber(16, 2, 3, cam_game_data.imageslots[14]); 41 | writeNumber(0, 3, 3, cam_game_data.imageslots[15]); 42 | writeNumber(4, 3, 3, cam_game_data.imageslots[16]); 43 | writeNumber(8, 3, 3, cam_game_data.imageslots[17]); 44 | writeNumber(12, 3, 3, cam_game_data.imageslots[18]); 45 | writeNumber(16, 3, 3, cam_game_data.imageslots[19]); 46 | 47 | writeNumber(0, 4, 3, cam_game_data.imageslots[20]); 48 | writeNumber(4, 4, 3, cam_game_data.imageslots[21]); 49 | writeNumber(8, 4, 3, cam_game_data.imageslots[22]); 50 | writeNumber(12, 4, 3, cam_game_data.imageslots[23]); 51 | writeNumber(16, 4, 3, cam_game_data.imageslots[24]); 52 | writeNumber(0, 5, 3, cam_game_data.imageslots[25]); 53 | writeNumber(4, 5, 3, cam_game_data.imageslots[26]); 54 | writeNumber(8, 5, 3, cam_game_data.imageslots[27]); 55 | writeNumber(12, 5, 3, cam_game_data.imageslots[28]); 56 | writeNumber(16, 5, 3, cam_game_data.imageslots[29]); 57 | 58 | set_bkg_based_tiles(1, 7, sizeof(cam_game_data.magic), 1, cam_game_data.magic, OFFSET_FONT - 32); 59 | writeNumber(7, 7, 3, cam_game_data.CRC_add); 60 | writeNumber(11, 7, 3, cam_game_data.CRC_xor); 61 | 62 | 63 | writeNumber(0, 9, 3, cam_game_data_echo.imageslots[0]); 64 | writeNumber(4, 9, 3, cam_game_data_echo.imageslots[1]); 65 | writeNumber(8, 9, 3, cam_game_data_echo.imageslots[2]); 66 | writeNumber(12, 9, 3, cam_game_data_echo.imageslots[3]); 67 | writeNumber(16, 9, 3, cam_game_data_echo.imageslots[4]); 68 | writeNumber(0, 10, 3, cam_game_data_echo.imageslots[5]); 69 | writeNumber(4, 10, 3, cam_game_data_echo.imageslots[6]); 70 | writeNumber(8, 10, 3, cam_game_data_echo.imageslots[7]); 71 | writeNumber(12, 10, 3, cam_game_data_echo.imageslots[8]); 72 | writeNumber(16, 10, 3, cam_game_data_echo.imageslots[9]); 73 | 74 | writeNumber(0, 11, 3, cam_game_data_echo.imageslots[10]); 75 | writeNumber(4, 11, 3, cam_game_data_echo.imageslots[11]); 76 | writeNumber(8, 11, 3, cam_game_data_echo.imageslots[12]); 77 | writeNumber(12, 11, 3, cam_game_data_echo.imageslots[13]); 78 | writeNumber(16, 11, 3, cam_game_data_echo.imageslots[14]); 79 | writeNumber(0, 12, 3, cam_game_data_echo.imageslots[15]); 80 | writeNumber(4, 12, 3, cam_game_data_echo.imageslots[16]); 81 | writeNumber(8, 12, 3, cam_game_data_echo.imageslots[17]); 82 | writeNumber(12, 12, 3, cam_game_data_echo.imageslots[18]); 83 | writeNumber(16, 12, 3, cam_game_data_echo.imageslots[19]); 84 | 85 | writeNumber(0, 13, 3, cam_game_data_echo.imageslots[20]); 86 | writeNumber(4, 13, 3, cam_game_data_echo.imageslots[21]); 87 | writeNumber(8, 13, 3, cam_game_data_echo.imageslots[22]); 88 | writeNumber(12, 13, 3, cam_game_data_echo.imageslots[23]); 89 | writeNumber(16, 13, 3, cam_game_data_echo.imageslots[24]); 90 | writeNumber(0, 14, 3, cam_game_data_echo.imageslots[25]); 91 | writeNumber(4, 14, 3, cam_game_data_echo.imageslots[26]); 92 | writeNumber(8, 14, 3, cam_game_data_echo.imageslots[27]); 93 | writeNumber(12, 14, 3, cam_game_data_echo.imageslots[28]); 94 | writeNumber(16, 14, 3, cam_game_data_echo.imageslots[29]); 95 | 96 | set_bkg_based_tiles(1, 16, sizeof(cam_game_data_echo.magic), 1, cam_game_data_echo.magic, OFFSET_FONT - 32); 97 | writeNumber(7, 16, 3, cam_game_data_echo.CRC_add); 98 | writeNumber(11, 16, 3, cam_game_data_echo.CRC_xor); 99 | } 100 | -------------------------------------------------------------------------------- /src/dialog.c: -------------------------------------------------------------------------------- 1 | #pragma bank 255 2 | 3 | #include 4 | #include 5 | #include "defines.h" 6 | #include "joypad.h" 7 | #include "utils.h" 8 | #include "overlays/overlays.h" 9 | 10 | #define ANSWER_YES 0x01 11 | #define ANSWER_NO 0x00 12 | #define ANSWER_PENDING 0xFF 13 | 14 | void appearDialog() BANKED { 15 | move_win(7, 146); 16 | 17 | for (uint8_t i = 0; i < 8; i += 1) { 18 | 19 | if (i == 4) { 20 | beep(); 21 | } 22 | 23 | scroll_win(0, -7); 24 | wait_vbl_done(); 25 | } 26 | 27 | waitRelease(); 28 | } 29 | 30 | void disappearDialog() BANKED { 31 | waitRelease(); 32 | 33 | for (uint8_t i = 0; i < 8; i += 1) { 34 | scroll_win(0, 7); 35 | wait_vbl_done(); 36 | } 37 | 38 | move_win(7, 146); 39 | } 40 | 41 | uint8_t dialog(const uint8_t *message, uint8_t handleOverlays) NONBANKED { 42 | if (handleOverlays) { 43 | hideLowerOverlay(); 44 | } 45 | 46 | fill_win_rect(0, 0, 20, 1, MENU_BORDER_TOP); 47 | fill_win_rect(0, 1, 20, 10, OFFSET_BLANK); 48 | set_win_based_tiles(1, 2, 16, 1, message, OFFSET_FONT - 32); 49 | set_win_based_tiles(14, 4, 5, 2, "Yes A No B", OFFSET_FONT - 32); 50 | 51 | appearDialog(); 52 | 53 | uint8_t answer = ANSWER_PENDING; 54 | 55 | while (answer == ANSWER_PENDING) { 56 | wait_vbl_done(); 57 | 58 | if (jp == J_B) { 59 | boop(); 60 | disappearDialog(); 61 | answer = ANSWER_NO; 62 | } else if (jp == J_A) { 63 | beep(); 64 | disappearDialog(); 65 | answer = ANSWER_YES; 66 | } 67 | } 68 | 69 | if (handleOverlays) { 70 | showOverlay(); 71 | } 72 | 73 | return answer; 74 | } 75 | -------------------------------------------------------------------------------- /src/expose.c: -------------------------------------------------------------------------------- 1 | #pragma bank 255 2 | 3 | #include 4 | #include 5 | #include 6 | #include "maps.h" 7 | #include "frame_pxlr.h" 8 | #include "font.h" 9 | #include "tiles.h" 10 | #include "images.h" 11 | #include "bankedData.h" 12 | #include "joypad.h" 13 | #include "defines.h" 14 | #include "globals.h" 15 | #include "utils.h" 16 | #include "imageIndexing.h" 17 | #include "images.h" 18 | 19 | #define PALETTE_EXPOSE_0 0b00000011u 20 | #define PALETTE_EXPOSE_1 0b00001111u 21 | #define PALETTE_EXPOSE_2 0b00111111u 22 | 23 | #define MSB2LSB(b) (((b)&1?128:0)|((b)&2?64:0)|((b)&4?32:0)|((b)&8?16:0)|((b)&16?8:0)|((b)&32?4:0)|((b)&64?2:0)|((b)&128?1:0)) 24 | 25 | const uint8_t exposePalettes[3] = { 26 | PALETTE_EXPOSE_0, 27 | PALETTE_EXPOSE_1, 28 | PALETTE_EXPOSE_2, 29 | }; 30 | 31 | uint8_t exposeIndex = 0; 32 | 33 | // ToDo: convert this to a "flipTiles" function and then use set_data() to write to vram 34 | void set_bkg_data_flipped(uint8_t from, uint8_t length, const uint8_t tiles[], const uint8_t vramHighLow) NONBANKED { 35 | 36 | uint8_t flippedTiles[HALF_IMAGE_SIZE]; 37 | memcpy(flippedTiles, tiles, HALF_IMAGE_SIZE); 38 | 39 | for (uint16_t i = 0; i < 1792; i += 1) { 40 | flippedTiles[i] = MSB2LSB(flippedTiles[i]); 41 | } 42 | 43 | if (vramHighLow) { 44 | LCDC_REG &= ~LCDCF_BG8000; 45 | } else { 46 | LCDC_REG |= LCDCF_BG8000; 47 | } 48 | 49 | set_bkg_data(from, length, flippedTiles); 50 | } 51 | 52 | void set_flipped_map(const uint8_t map[], uint8_t offset) BANKED { 53 | uint8_t flippedMap[360]; 54 | for (uint16_t yc = 0; yc < 360; yc += 20) { 55 | for (uint8_t xc = 0; xc < 20; xc += 1) { 56 | flippedMap[xc + yc] = map[yc + 19 - xc]; 57 | } 58 | } 59 | set_bkg_based_tiles(0, 0, 20, 18, flippedMap, offset); 60 | } 61 | 62 | void loadImageTilesFlipped() BANKED { 63 | uint8_t imageSlot = getImageSlot(imageIndex); 64 | SWITCH_RAM(images[imageSlot]->bank); 65 | 66 | set_bkg_data_flipped(0, 112, images[imageSlot]->tilesUpper, 1); 67 | set_bkg_data_flipped(0, 112, images[imageSlot]->tilesLower, 0); 68 | set_bkg_tiles_banked(2, 2, 16, 14, map_flipped, 1); 69 | } 70 | 71 | 72 | void expose() BANKED { 73 | BGP_REG = PALETTE_BLANK; 74 | 75 | // ToDo - Use functions in banked.h 76 | set_bkg_data_flipped(OFFSET_FONT, frame_pxlr_TILE_COUNT, frame_pxlr_tiles, BANK(frame_pxlr)); 77 | set_flipped_map(frame_pxlr_map, OFFSET_FONT); 78 | 79 | loadImageTilesFlipped(); 80 | waitRelease(); 81 | 82 | while (jp != J_B) { 83 | 84 | BGP_REG = exposePalettes[exposeIndex]; 85 | exposeIndex = (exposeIndex + 1) % 3; 86 | 87 | // BGP_REG = PALETTE_INVERTED; 88 | // BGP_REG = PALETTE_NORMAL; 89 | 90 | wait_vbl_done(); 91 | wait_vbl_done(); 92 | wait_vbl_done(); 93 | } 94 | 95 | joypadConsumed(); 96 | waitRelease(); 97 | 98 | 99 | // Back to normal 100 | BGP_REG = PALETTE_BLANK; 101 | clearBkg(); 102 | set_bkg_data_banked(OFFSET_FONT, NUM_FONT_CHARS, font, 1); 103 | set_bkg_data_banked(OFFSET_TILES, NUM_CONSTANT_TILES, constantTiles, 1); 104 | set_bkg_tiles_banked(2, 2, 16, 14, map_normal, 1); 105 | 106 | BGP_REG = PALETTE_NORMAL; 107 | } 108 | -------------------------------------------------------------------------------- /src/flasher.c: -------------------------------------------------------------------------------- 1 | #pragma bank 255 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #include "flasher.h" 9 | #include "gbcamera.h" 10 | 11 | #define FIRST_HALF_OFS 0 12 | #define FIRST_HALF_LEN 8 13 | #define SECOND_HALF_OFS 8 14 | #define SECOND_HALF_LEN 8 15 | 16 | extern uint8_t save_rom_bank; 17 | extern uint8_t save_sram_bank_offset; 18 | 19 | static cam_game_data_t AT(0x51B2) saved_game_data; 20 | 21 | inline uint8_t slot_to_bank(uint8_t slot, uint8_t ofs) { 22 | return (((slot + 2) << 1) + ofs) << 2; 23 | } 24 | 25 | uint8_t flash_check_gallery_exist(uint8_t slot) NONBANKED { 26 | uint8_t _save = _current_bank, result; 27 | SWITCH_ROM(slot_to_bank(slot, 0)); 28 | result = ((saved_game_data.magic[0] == 'M') && 29 | (saved_game_data.magic[1] == 'a') && 30 | (saved_game_data.magic[2] == 'g') && 31 | (saved_game_data.magic[3] == 'i') && 32 | (saved_game_data.magic[4] == 'c')); 33 | SWITCH_ROM(_save); 34 | return result; 35 | } 36 | 37 | void restore_sram_bank(uint8_t bank) NONBANKED { 38 | uint8_t _save = _current_bank; 39 | SWITCH_ROM(save_rom_bank + (bank >> 1)); 40 | memcpy((uint8_t *)0xA000, (uint8_t *)(0x4000 + ((bank & 1) << 13)), 0x2000); 41 | SWITCH_ROM(_save); 42 | } 43 | 44 | uint8_t flash_load_gallery_from_slot(uint8_t slot) BANKED { 45 | // check saved gallery exist 46 | if (!flash_check_gallery_exist(slot)) return FALSE; 47 | // read 8 SRAM banks from the flash sector 48 | save_rom_bank = slot_to_bank(slot, 0); 49 | save_sram_bank_offset = FIRST_HALF_OFS; 50 | for (uint8_t i = 0; i < FIRST_HALF_LEN; i++) { 51 | SWITCH_RAM(i + FIRST_HALF_OFS); 52 | restore_sram_bank(i); 53 | } 54 | // read the next 8 SRAM banks from the next flash sector 55 | save_rom_bank = slot_to_bank(slot, 1); 56 | save_sram_bank_offset = SECOND_HALF_OFS; 57 | for (uint8_t i = 0; i < SECOND_HALF_LEN; i++) { 58 | SWITCH_RAM(i + SECOND_HALF_OFS); 59 | restore_sram_bank(i); 60 | } 61 | return TRUE; 62 | } 63 | 64 | extern uint8_t erase_flash() OLDCALL; // erases FLASH sector: 64K or 4 banks 65 | extern uint8_t save_sram_banks(uint8_t count) OLDCALL; // copies up to count SRAM banks to FLASH 66 | 67 | uint8_t flash_save_gallery_to_slot(uint8_t slot) BANKED { 68 | // erase the sector and save first 8 SRAM banks 69 | save_sram_bank_offset = FIRST_HALF_OFS; 70 | save_rom_bank = slot_to_bank(slot, 0); 71 | if (!erase_flash()) return FALSE; 72 | if (!save_sram_banks(FIRST_HALF_LEN)) return FALSE; 73 | // erase the next sector and save the next 8 sram banks 74 | save_sram_bank_offset = SECOND_HALF_OFS; 75 | save_rom_bank = slot_to_bank(slot, 1); 76 | if (!erase_flash()) return FALSE; 77 | return save_sram_banks(SECOND_HALF_LEN); // update offset 78 | } 79 | 80 | uint8_t flash_erase_slot(uint8_t slot) BANKED { 81 | save_rom_bank = slot_to_bank(slot, 0); 82 | if (!erase_flash()) return FALSE; 83 | save_rom_bank = slot_to_bank(slot, 1); 84 | return erase_flash(); 85 | } 86 | -------------------------------------------------------------------------------- /src/gallery.c: -------------------------------------------------------------------------------- 1 | #pragma bank 255 2 | 3 | #include 4 | #include 5 | 6 | #include "menus/imageMenuItems.h" 7 | #include "mainMenu.h" 8 | #include "joypad.h" 9 | #include "utils.h" 10 | #include "defines.h" 11 | #include "globals.h" 12 | #include "images.h" 13 | #include "bankedData.h" 14 | #include "printCmd.h" 15 | #include "expose.h" 16 | #include "bleep.h" 17 | #include "imageInfo.h" 18 | #include "analysis.h" 19 | #include "font.h" 20 | #include "nope.h" 21 | #include "maps.h" 22 | #include "images.h" 23 | #include "remote.h" 24 | 25 | uint8_t specialAction; 26 | 27 | inline void renderImageMenu() { 28 | move_sprite(SPRITE_MENU_INDICATOR, 88, yMenuSprite(imageMenuIndex)); 29 | } 30 | 31 | void appearImageMenu() BANKED { 32 | move_win(168, 0); 33 | 34 | for (uint8_t i = 0; i < 10; i += 1) { 35 | scroll_win(-9, 0); 36 | wait_vbl_done(); 37 | } 38 | 39 | renderImageMenu(); 40 | } 41 | 42 | 43 | static void disappearImageMenu() { 44 | move_sprite(SPRITE_MENU_INDICATOR, 0, 0); 45 | 46 | waitRelease(); 47 | 48 | for (uint8_t i = 0; i < 10; i += 1) { 49 | scroll_win(9, 0); 50 | wait_vbl_done(); 51 | } 52 | 53 | move_win(168, 0); 54 | } 55 | 56 | void loadAndShowGalleryImage() BANKED { 57 | if (numVisibleImages > 0) { 58 | uint8_t imageSlot = getImageSlot(imageIndex); 59 | SWITCH_RAM(images[imageSlot]->bank); 60 | 61 | set_data(VRAM_9000, images[imageSlot]->tilesUpper, HALF_IMAGE_SIZE); 62 | set_data(VRAM_8000, images[imageSlot]->tilesLower, HALF_IMAGE_SIZE); 63 | 64 | set_bkg_based_tiles(2, 16, 5, 2, "Image / ", OFFSET_FONT - 32); 65 | writeNumber(1, 17, 2, imageIndex + 1); 66 | writeNumber(4, 17, 2, numVisibleImages); 67 | // writeNumber(2, 16, 3, findFirstFreeSlot()); 68 | } else { 69 | set_data_banked(VRAM_9000, nope_tiles, HALF_IMAGE_SIZE, 1); 70 | set_data_banked(VRAM_8000, nope_tiles, HALF_IMAGE_SIZE, 1); 71 | 72 | set_bkg_based_tiles(2, 16, 5, 2, "No Image", OFFSET_FONT - 32); 73 | } 74 | } 75 | 76 | void initGallery() BANKED { 77 | clearBkg(); 78 | set_bkg_tiles_banked(2, 2, 16, 14, map_normal, 1); 79 | 80 | disappearImageMenu(); 81 | sortImages(); 82 | move_sprite(SPRITE_MENU_INDICATOR, 0, 0); 83 | loadAndShowGalleryImage(); 84 | } 85 | 86 | void initImageMenu() BANKED { 87 | fill_win_rect(0, 0, 1, 32, MENU_BORDER_LEFT); 88 | fill_win_rect(1, 0, 31, 32, OFFSET_BLANK); 89 | 90 | for (uint8_t index = 0; index < NUM_IMAGE_MENU_OPTIONS; index += 1) { 91 | set_win_based_tiles(2, yMenu(index), 8, 1, imageMenuItems[index].title, OFFSET_FONT - 32); 92 | } 93 | } 94 | 95 | void galleryMenu() BANKED { 96 | 97 | if (jp == J_RIGHT) { 98 | imageIndex = (imageIndex + 1) % numVisibleImages; 99 | loadAndShowGalleryImage(); 100 | joypadConsumed(); 101 | } else if (jp == J_LEFT) { 102 | imageIndex = (imageIndex + numVisibleImages - 1) % numVisibleImages; 103 | loadAndShowGalleryImage(); 104 | joypadConsumed(); 105 | } else if (jp == J_B) { 106 | menuSelectMode(MAIN_LOOP_MENU); 107 | joypadConsumed(); 108 | } else if (jp == J_A) { 109 | menuSelectMode(MAIN_LOOP_IMAGE); 110 | joypadConsumed(); 111 | } 112 | } 113 | 114 | 115 | static void imageMenuAction(uint8_t value) { 116 | uint8_t address = getImageSlot(imageIndex); 117 | 118 | if (address >= NUM_IMAGES) { 119 | boop(); 120 | return; 121 | } 122 | 123 | if (value == IMAGE_MENU_INFO) { 124 | remote_activate(REMOTE_DISABLED); 125 | if (getPrinterStatus()) { 126 | displayImageInfo(imageIndex); 127 | initImageMenu(); 128 | renderImageMenu(); 129 | } else { 130 | 131 | getImageInfo(imageIndex, imageInfo); 132 | printImageInfo(imageInfo); 133 | 134 | waitPrinterReady(); 135 | 136 | beep(); 137 | } 138 | remote_activate(REMOTE_ENABLED); 139 | } else if (value == IMAGE_MENU_HISTOGRAM) { 140 | displayHistogram(imageIndex); 141 | initImageMenu(); 142 | renderImageMenu(); 143 | } else if (value == IMAGE_MENU_DELETE) { 144 | setImageSlot(address, 0xff); 145 | reduceIndexAfterDelete(imageIndex); 146 | sortImages(); 147 | if (imageIndex > 0) { 148 | imageIndex = (imageIndex + numVisibleImages - 1) % numVisibleImages; 149 | } 150 | loadAndShowGalleryImage(); 151 | clonk(); 152 | } else if (value == IMAGE_MENU_PRINT) { 153 | remote_activate(REMOTE_DISABLED); 154 | printerInit(); 155 | if (getPrinterStatus()) { 156 | boop(); 157 | } else { 158 | if (specialAction == TRUE) { 159 | printImageWild(images[address]->tilesLower, images[address]->tilesUpper, images[address]->bank); 160 | } else { 161 | printImage(images[address]->tilesLower, images[address]->tilesUpper, images[address]->bank); 162 | } 163 | 164 | waitPrinterReady(); 165 | 166 | beep(); 167 | } 168 | remote_activate(REMOTE_ENABLED); 169 | } else if (value == IMAGE_MENU_BLEEP) { 170 | disappearImageMenu(); 171 | bleep(); 172 | appearImageMenu(); 173 | } else if (value == IMAGE_MENU_EXPOSE) { 174 | disappearImageMenu(); 175 | expose(); 176 | loadAndShowGalleryImage(); 177 | appearImageMenu(); 178 | } 179 | } 180 | 181 | void imageMenu() BANKED { 182 | specialAction = FALSE; 183 | 184 | if (jp == J_UP) { 185 | imageMenuIndex = (imageMenuIndex + NUM_IMAGE_MENU_OPTIONS - 1) % NUM_IMAGE_MENU_OPTIONS; 186 | clonk(); 187 | renderImageMenu(); 188 | joypadConsumed(); 189 | } else if (jp == J_DOWN) { 190 | imageMenuIndex = (imageMenuIndex + 1) % NUM_IMAGE_MENU_OPTIONS; 191 | clonk(); 192 | renderImageMenu(); 193 | joypadConsumed(); 194 | } else if (jp == J_RIGHT) { 195 | imageIndex = (imageIndex + 1) % numVisibleImages; 196 | loadAndShowGalleryImage(); 197 | joypadConsumed(); 198 | } else if (jp == J_LEFT) { 199 | imageIndex = (imageIndex + numVisibleImages - 1) % numVisibleImages; 200 | loadAndShowGalleryImage(); 201 | joypadConsumed(); 202 | } else if (jp == J_A) { 203 | if (numVisibleImages > 0) { 204 | imageMenuAction(imageMenuItems[imageMenuIndex].value); 205 | } else { 206 | boop(); 207 | } 208 | joypadConsumed(); 209 | } else if (jp == J_START) { 210 | specialAction = TRUE; 211 | if (numVisibleImages > 0) { 212 | imageMenuAction(imageMenuItems[imageMenuIndex].value); 213 | } else { 214 | boop(); 215 | } 216 | joypadConsumed(); 217 | } else if (jp == J_B) { 218 | menuSelectMode(MAIN_LOOP_IMAGE_GALLERY); 219 | joypadConsumed(); 220 | } 221 | 222 | } 223 | -------------------------------------------------------------------------------- /src/globals.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "imageIndexing.h" 3 | 4 | uint8_t mainLoopState = 0; 5 | uint8_t isCapturing = 0; 6 | uint8_t imageMenuIndex = 0; 7 | uint8_t imageInfo[360]; 8 | uint8_t imageIndex = 0; 9 | uint8_t numVisibleImages = 0; 10 | uint8_t sortedIndices[NUM_IMAGES] = { 11 | IMAGE_UNDEFINED, IMAGE_UNDEFINED, IMAGE_UNDEFINED, IMAGE_UNDEFINED, IMAGE_UNDEFINED, IMAGE_UNDEFINED, IMAGE_UNDEFINED, IMAGE_UNDEFINED, IMAGE_UNDEFINED, IMAGE_UNDEFINED, 12 | IMAGE_UNDEFINED, IMAGE_UNDEFINED, IMAGE_UNDEFINED, IMAGE_UNDEFINED, IMAGE_UNDEFINED, IMAGE_UNDEFINED, IMAGE_UNDEFINED, IMAGE_UNDEFINED, IMAGE_UNDEFINED, IMAGE_UNDEFINED, 13 | IMAGE_UNDEFINED, IMAGE_UNDEFINED, IMAGE_UNDEFINED, IMAGE_UNDEFINED, IMAGE_UNDEFINED, IMAGE_UNDEFINED, IMAGE_UNDEFINED, IMAGE_UNDEFINED, IMAGE_UNDEFINED, IMAGE_UNDEFINED, 14 | }; 15 | 16 | -------------------------------------------------------------------------------- /src/imageIndexing.c: -------------------------------------------------------------------------------- 1 | #pragma bank 255 2 | 3 | #include 4 | #include 5 | #include "gbcamera.h" 6 | #include "utils.h" 7 | #include "globals.h" 8 | 9 | #define NUM_IMAGES 30 10 | #define IMAGE_DELETED 0xFF 11 | #define IMAGE_UNDEFINED 0xFE 12 | 13 | void setImageSlot(uint8_t address, uint8_t newValue) BANKED { 14 | SWITCH_RAM(0); 15 | 16 | if (address >= NUM_IMAGES) { 17 | dead(); 18 | } 19 | 20 | uint8_t oldValue = cam_game_data_echo.imageslots[address]; 21 | 22 | if (newValue == oldValue) { 23 | return; 24 | } 25 | 26 | // Update value for imageslot 27 | cam_game_data_echo.imageslots[address] = cam_game_data.imageslots[address] = newValue; 28 | 29 | // Update checksum SUM 30 | cam_game_data_echo.CRC_add = cam_game_data.CRC_add = cam_game_data.CRC_add + newValue - oldValue; 31 | 32 | // Update checksum XOR 33 | cam_game_data_echo.CRC_xor = cam_game_data.CRC_xor = cam_game_data.CRC_xor ^ newValue ^ oldValue; 34 | } 35 | 36 | uint8_t getImageSlot(uint8_t index) BANKED { 37 | if (index >= NUM_IMAGES) { 38 | return NUM_IMAGES; 39 | } 40 | 41 | return sortedIndices[index]; 42 | } 43 | 44 | 45 | 46 | uint8_t getAddressForIndex(uint8_t index) BANKED { 47 | SWITCH_RAM(0); 48 | for (uint8_t address = 0; address < NUM_IMAGES; address++) { 49 | if (cam_game_data_echo.imageslots[address] == index) { 50 | return address; 51 | } 52 | } 53 | 54 | return NUM_IMAGES; 55 | } 56 | 57 | 58 | uint8_t getNextHighestAddress(uint8_t searchIndex) BANKED { 59 | SWITCH_RAM(0); 60 | 61 | while (searchIndex < NUM_IMAGES) { 62 | for (uint8_t address = 0; address < NUM_IMAGES; address++) { 63 | if (cam_game_data_echo.imageslots[address] == searchIndex) { 64 | return address; 65 | } 66 | } 67 | 68 | searchIndex += 1; 69 | } 70 | 71 | return NUM_IMAGES; 72 | } 73 | 74 | void reduceIndexAfterDelete(uint8_t deletedIndex) BANKED { 75 | SWITCH_RAM(0); 76 | for (uint8_t address = 0; address < NUM_IMAGES; address++) { 77 | uint8_t index = cam_game_data_echo.imageslots[address]; 78 | if (index > deletedIndex && index < NUM_IMAGES) { 79 | setImageSlot(address, index - 1); 80 | } 81 | } 82 | } 83 | 84 | void cleanupIndexGaps() BANKED { 85 | SWITCH_RAM(0); 86 | for (uint8_t index = 0; index < NUM_IMAGES; index++) { 87 | // image number does not exist in list 88 | if (getAddressForIndex(index) >= NUM_IMAGES) { 89 | uint8_t address = getNextHighestAddress(index); 90 | if (address < NUM_IMAGES) { 91 | setImageSlot(address, index); 92 | } 93 | } 94 | } 95 | } 96 | 97 | void sortImages() BANKED { 98 | SWITCH_RAM(0); 99 | 100 | uint8_t deletedIndex = 0; 101 | numVisibleImages = 0; 102 | uint8_t sortedDeletedIndices[NUM_IMAGES]; 103 | uint8_t i = 0; 104 | 105 | for (i = 0; i < NUM_IMAGES; i++) { 106 | uint8_t current = cam_game_data_echo.imageslots[i]; 107 | 108 | if (current == IMAGE_DELETED) { 109 | sortedDeletedIndices[deletedIndex] = i; 110 | deletedIndex += 1; 111 | } else { 112 | sortedIndices[current] = i; 113 | numVisibleImages += 1; 114 | } 115 | } 116 | 117 | deletedIndex = 0; 118 | for (i = 0; i < NUM_IMAGES; i++) { 119 | if (sortedIndices[i] == IMAGE_UNDEFINED) { 120 | sortedIndices[i] = sortedDeletedIndices[deletedIndex]; 121 | deletedIndex += 1; 122 | } 123 | } 124 | } 125 | 126 | uint8_t findFirstFreeSlot() BANKED { 127 | SWITCH_RAM(0); 128 | 129 | for (uint8_t i = 0; i < NUM_IMAGES; i++) { 130 | if (cam_game_data_echo.imageslots[i] == IMAGE_DELETED) { 131 | return i; 132 | } 133 | } 134 | 135 | return NUM_IMAGES; 136 | } 137 | 138 | void deleteAllImages() BANKED { 139 | for (uint8_t address = 0; address < 30; address += 1) { 140 | setImageSlot(address, 0xff); 141 | } 142 | sortImages(); 143 | imageIndex = 0; 144 | } 145 | -------------------------------------------------------------------------------- /src/imageInfo.c: -------------------------------------------------------------------------------- 1 | #pragma bank 255 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "defines.h" 8 | #include "values.h" 9 | #include "globals.h" 10 | #include "utils.h" 11 | #include "joypad.h" 12 | #include "images.h" 13 | #include "menus/shootingManualMenuItems.h" 14 | #include "images.h" 15 | 16 | void getImageInfo(uint8_t imageIndex, uint8_t *tileMap) BANKED { 17 | uint8_t imageSlot = getImageSlot(imageIndex); 18 | uint8_t i; 19 | 20 | SWITCH_RAM(images[imageSlot]->bank); 21 | 22 | uint8_t capture = images[imageSlot]->thumbnail[THUMBNAIL_BYTE_CAPTURE]; 23 | uint8_t edgeGains = images[imageSlot]->thumbnail[THUMBNAIL_BYTE_EDGEGAINS]; 24 | uint8_t exposureHigh = images[imageSlot]->thumbnail[THUMBNAIL_BYTE_EXPOSURE_HIGH]; 25 | uint8_t exposureLow = images[imageSlot]->thumbnail[THUMBNAIL_BYTE_EXPOSURE_LOW]; 26 | uint8_t edgeModeVolt = images[imageSlot]->thumbnail[THUMBNAIL_BYTE_EDMOVOLT]; 27 | uint8_t voltageZeroPoint = images[imageSlot]->thumbnail[THUMBNAIL_BYTE_VOUTZERO]; 28 | uint8_t ditherSet = images[imageSlot]->thumbnail[THUMBNAIL_BYTE_DITHERSET]; 29 | uint8_t contrast = images[imageSlot]->thumbnail[THUMBNAIL_BYTE_CONTRAST]; 30 | 31 | uint8_t captureMode = capture & A000_MASK_CAPTURE; 32 | uint8_t edgeExclusive = edgeGains & A001_MASK_EDGE_EXCLUSIVE; 33 | uint8_t edgeOperation = edgeGains & A001_MASK_EDGE_OP_MODE; 34 | uint8_t gain = edgeGains & A001_MASK_GAIN; 35 | uint8_t edgeMode = edgeModeVolt & A004_MASK_EDGE_RATIO; 36 | uint8_t invertOut = edgeModeVolt & A004_MASK_INVERT_OUTPUT; 37 | uint8_t vRef = edgeModeVolt & A004_MASK_VOLTAGE_REF; 38 | uint8_t zeroPoint = voltageZeroPoint & A005_MASK_ZERO; 39 | uint8_t vOut = voltageZeroPoint & A005_MASK_VOLTAGE_OUT; 40 | 41 | if ( 42 | capture == 0xFF && 43 | edgeGains == 0xFF && 44 | exposureHigh == 0xFF && 45 | exposureLow == 0xFF && 46 | edgeModeVolt == 0xFF && 47 | voltageZeroPoint == 0xFF && 48 | ditherSet == 0xFF && 49 | contrast == 0xFF 50 | ) { 51 | memcpy(&tileMap[0], 52 | " " 53 | " " 54 | " " 55 | " " 56 | " " 57 | " " 58 | " Image was not " 59 | " " 60 | " taken with " 61 | " " 62 | " 2bit PXLR Studio " 63 | " " 64 | " " 65 | " " 66 | " " 67 | " " 68 | " " 69 | " ", 70 | 360); 71 | return; 72 | } 73 | 74 | 75 | memcpy(&tileMap[0], 76 | "Image #??? Slot #???" 77 | " " 78 | "Exposure Time ????ms" 79 | "Sensor Gain ??????" 80 | "Voltage Output??????" 81 | "Dith. Contrast??????" 82 | "Dither Set ??????" 83 | "Voltage Ref ??????" 84 | "Invert Output ??????" 85 | "Zero Point ??????" 86 | "Capture Mode ??????" 87 | "Edge Operation??????" 88 | "Edge Mode ??????" 89 | "Edge Exclusive??????" 90 | " " 91 | "Registers " 92 | " 0x?? 0x?? 0x?? 0x??" 93 | " 0x?? 0x?? 0x?? 0x??", 94 | 360); 95 | 96 | #define POS_IMG 7 97 | #define POS_SLOT 17 98 | #define POS_01 54 99 | #define POS_02 74 100 | #define POS_03 94 101 | #define POS_04 114 102 | #define POS_05 134 103 | #define POS_06 154 104 | #define POS_07 174 105 | #define POS_08 194 106 | #define POS_09 214 107 | #define POS_10 234 108 | #define POS_11 254 109 | #define POS_12 274 110 | 111 | uint16_t exposureTimeInt = (exposureHigh << 8) + exposureLow; 112 | describeExposureTime(exposureTimeInt, &tileMap[POS_01]); 113 | 114 | for (i = 0; i < NUM_GAIN_LEVELS; i += 1) { 115 | if (gains[i].value == gain) { 116 | memcpy(&tileMap[POS_02], gains[i].title, MENU_TEXT_LENGTH); 117 | } 118 | } 119 | 120 | for (i = 0; i < NUM_VOLTAGE_OUTS; i += 1) { 121 | if (voltageOuts[i].value == vOut) { 122 | memcpy(&tileMap[POS_03], voltageOuts[i].title, MENU_TEXT_LENGTH); 123 | } 124 | } 125 | 126 | for (i = 0; i < NUM_CONTRASTS; i += 1) { 127 | if (contrasts[i].value == contrast) { 128 | memcpy(&tileMap[POS_04], contrasts[i].title, MENU_TEXT_LENGTH); 129 | } 130 | } 131 | 132 | for (i = 0; i < NUM_DITHERSETS; i += 1) { 133 | if (ditherSets[i].value == ditherSet) { 134 | memcpy(&tileMap[POS_05], ditherSets[i].title, MENU_TEXT_LENGTH); 135 | } 136 | } 137 | 138 | 139 | for (i = 0; i < NUM_VOLTAGE_REFS; i += 1) { 140 | if (voltageRefs[i].value == vRef) { 141 | memcpy(&tileMap[POS_06], voltageRefs[i].title, MENU_TEXT_LENGTH); 142 | } 143 | } 144 | 145 | for (i = 0; i < NUM_INVERT_OUTPUTS; i += 1) { 146 | if (invertOutputs[i].value == invertOut) { 147 | memcpy(&tileMap[POS_07], invertOutputs[i].title, MENU_TEXT_LENGTH); 148 | } 149 | } 150 | 151 | for (i = 0; i < NUM_ZERO_POINTS; i += 1) { 152 | if (zeroPoints[i].value == zeroPoint) { 153 | memcpy(&tileMap[POS_08], zeroPoints[i].title, MENU_TEXT_LENGTH); 154 | } 155 | } 156 | 157 | for (i = 0; i < NUM_CAPTURE_MODES; i += 1) { 158 | if (captureModes[i].value == captureMode) { 159 | memcpy(&tileMap[POS_09], captureModes[i].title, MENU_TEXT_LENGTH); 160 | } 161 | } 162 | 163 | for (i = 0; i < NUM_EDGE_OP_MODES; i += 1) { 164 | if (edgeOpModes[i].value == edgeOperation) { 165 | memcpy(&tileMap[POS_10], edgeOpModes[i].title, MENU_TEXT_LENGTH); 166 | } 167 | } 168 | 169 | for (i = 0; i < NUM_EDGE_MODES; i += 1) { 170 | if (edgeModes[i].value == edgeMode) { 171 | memcpy(&tileMap[POS_11], edgeModes[i].title, MENU_TEXT_LENGTH); 172 | } 173 | } 174 | 175 | for (i = 0; i < NUM_EDGE_EXCLUSIVE; i += 1) { 176 | if (edgeExclusives[i].value == edgeExclusive) { 177 | memcpy(&tileMap[POS_12], edgeExclusives[i].title, MENU_TEXT_LENGTH); 178 | } 179 | } 180 | 181 | uint8_t digits[10]; 182 | BCD bcd = MAKE_BCD(0); 183 | 184 | uint2bcd(imageIndex, &bcd); 185 | bcd2text(&bcd, 48u, digits); 186 | memcpy(&tileMap[POS_IMG], &digits[5], 3); 187 | 188 | uint2bcd(imageSlot, &bcd); 189 | bcd2text(&bcd, 48u, digits); 190 | memcpy(&tileMap[POS_SLOT], &digits[5], 3); 191 | 192 | hexChar(&tileMap[323], capture); 193 | hexChar(&tileMap[328], edgeGains); 194 | hexChar(&tileMap[333], exposureHigh); 195 | hexChar(&tileMap[338], exposureLow); 196 | hexChar(&tileMap[343], edgeModeVolt); 197 | hexChar(&tileMap[348], voltageZeroPoint); 198 | hexChar(&tileMap[353], ditherSet); 199 | hexChar(&tileMap[358], contrast); 200 | } 201 | 202 | void displayImageInfo(uint8_t imageIndex) BANKED { 203 | move_sprite(SPRITE_MENU_INDICATOR, 0, 0); 204 | 205 | getImageInfo(imageIndex, imageInfo); 206 | 207 | waitRelease(); 208 | 209 | fill_win_rect(0, 0, 20, 18, OFFSET_BLANK); 210 | move_win(6, 0); 211 | set_win_based_tiles(0, 0, 20, 18, imageInfo, OFFSET_FONT - 32); 212 | 213 | while (jp != J_B && jp != J_A) { 214 | wait_vbl_done(); 215 | } 216 | 217 | fill_win_rect(0, 0, 20, 18, OFFSET_BLANK); 218 | move_win(78, 0); 219 | } 220 | -------------------------------------------------------------------------------- /src/images.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "typedefs/Image.h" 3 | #include "gbcamera.h" 4 | 5 | static const Image image01 = { 1, image_first_upper, image_first_lower, image_first_thumbnail, image_first_meta, image_first_meta_echo }; 6 | static const Image image02 = { 1, image_second_upper, image_second_lower, image_second_thumbnail, image_second_meta, image_second_meta_echo }; 7 | static const Image image03 = { 2, image_first_upper, image_first_lower, image_first_thumbnail, image_first_meta, image_first_meta_echo }; 8 | static const Image image04 = { 2, image_second_upper, image_second_lower, image_second_thumbnail, image_second_meta, image_second_meta_echo }; 9 | static const Image image05 = { 3, image_first_upper, image_first_lower, image_first_thumbnail, image_first_meta, image_first_meta_echo }; 10 | static const Image image06 = { 3, image_second_upper, image_second_lower, image_second_thumbnail, image_second_meta, image_second_meta_echo }; 11 | static const Image image07 = { 4, image_first_upper, image_first_lower, image_first_thumbnail, image_first_meta, image_first_meta_echo }; 12 | static const Image image08 = { 4, image_second_upper, image_second_lower, image_second_thumbnail, image_second_meta, image_second_meta_echo }; 13 | static const Image image09 = { 5, image_first_upper, image_first_lower, image_first_thumbnail, image_first_meta, image_first_meta_echo }; 14 | static const Image image10 = { 5, image_second_upper, image_second_lower, image_second_thumbnail, image_second_meta, image_second_meta_echo }; 15 | static const Image image11 = { 6, image_first_upper, image_first_lower, image_first_thumbnail, image_first_meta, image_first_meta_echo }; 16 | static const Image image12 = { 6, image_second_upper, image_second_lower, image_second_thumbnail, image_second_meta, image_second_meta_echo }; 17 | static const Image image13 = { 7, image_first_upper, image_first_lower, image_first_thumbnail, image_first_meta, image_first_meta_echo }; 18 | static const Image image14 = { 7, image_second_upper, image_second_lower, image_second_thumbnail, image_second_meta, image_second_meta_echo }; 19 | static const Image image15 = { 8, image_first_upper, image_first_lower, image_first_thumbnail, image_first_meta, image_first_meta_echo }; 20 | static const Image image16 = { 8, image_second_upper, image_second_lower, image_second_thumbnail, image_second_meta, image_second_meta_echo }; 21 | static const Image image17 = { 9, image_first_upper, image_first_lower, image_first_thumbnail, image_first_meta, image_first_meta_echo }; 22 | static const Image image18 = { 9, image_second_upper, image_second_lower, image_second_thumbnail, image_second_meta, image_second_meta_echo }; 23 | static const Image image19 = {10, image_first_upper, image_first_lower, image_first_thumbnail, image_first_meta, image_first_meta_echo }; 24 | static const Image image20 = {10, image_second_upper, image_second_lower, image_second_thumbnail, image_second_meta, image_second_meta_echo }; 25 | static const Image image21 = {11, image_first_upper, image_first_lower, image_first_thumbnail, image_first_meta, image_first_meta_echo }; 26 | static const Image image22 = {11, image_second_upper, image_second_lower, image_second_thumbnail, image_second_meta, image_second_meta_echo }; 27 | static const Image image23 = {12, image_first_upper, image_first_lower, image_first_thumbnail, image_first_meta, image_first_meta_echo }; 28 | static const Image image24 = {12, image_second_upper, image_second_lower, image_second_thumbnail, image_second_meta, image_second_meta_echo }; 29 | static const Image image25 = {13, image_first_upper, image_first_lower, image_first_thumbnail, image_first_meta, image_first_meta_echo }; 30 | static const Image image26 = {13, image_second_upper, image_second_lower, image_second_thumbnail, image_second_meta, image_second_meta_echo }; 31 | static const Image image27 = {14, image_first_upper, image_first_lower, image_first_thumbnail, image_first_meta, image_first_meta_echo }; 32 | static const Image image28 = {14, image_second_upper, image_second_lower, image_second_thumbnail, image_second_meta, image_second_meta_echo }; 33 | static const Image image29 = {15, image_first_upper, image_first_lower, image_first_thumbnail, image_first_meta, image_first_meta_echo }; 34 | static const Image image30 = {15, image_second_upper, image_second_lower, image_second_thumbnail, image_second_meta, image_second_meta_echo }; 35 | 36 | const Image * const images[30] = { 37 | &image01, &image02, &image03, &image04, &image05, 38 | &image06, &image07, &image08, &image09, &image10, 39 | &image11, &image12, &image13, &image14, &image15, 40 | &image16, &image17, &image18, &image19, &image20, 41 | &image21, &image22, &image23, &image24, &image25, 42 | &image26, &image27, &image28, &image29, &image30, 43 | }; 44 | -------------------------------------------------------------------------------- /src/joypad.c: -------------------------------------------------------------------------------- 1 | #pragma bank 255 2 | 3 | #include 4 | #include 5 | 6 | #include "remote.h" 7 | 8 | // global joypad store variable 9 | volatile uint8_t jp = 0; 10 | static uint8_t jpCooldown = 0; 11 | 12 | void joypadConsumed() BANKED { 13 | jp = 0; 14 | jpCooldown = 15; 15 | } 16 | 17 | void waitRelease() BANKED { 18 | // Wait until all inputs have been released 19 | while (jp != 0) { 20 | wait_vbl_done(); 21 | } 22 | 23 | joypadConsumed(); 24 | } 25 | 26 | void captureJoypadISR() BANKED { 27 | uint8_t value = (joypad() | remote_joypad()); 28 | if (jpCooldown && (value)) { 29 | jpCooldown--; 30 | } else { 31 | jp = value; 32 | jpCooldown = 0; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "camera.h" 5 | #include "defines.h" 6 | #include "globals.h" 7 | #include "imageIndexing.h" 8 | #include "joypad.h" 9 | #include "mainLoop.h" 10 | #include "mainMenu.h" 11 | #include "overlays/overlays.h" 12 | #include "splash.h" 13 | #include "utils.h" 14 | #include "systemdetect.h" 15 | #include "flasher.h" 16 | #include "remote.h" 17 | 18 | void scanlineIsr() { 19 | if (LYC_REG == 71) { 20 | while (STAT_REG & STATF_LCD != 0); 21 | LCDC_REG |= LCDCF_BG8000; 22 | LYC_REG = 144; 23 | } else if (LYC_REG == 144) { 24 | LCDC_REG &= ~ LCDCF_BG8000; 25 | LYC_REG = 71; 26 | 27 | if (!isCapturing) { 28 | captureJoypadISR(); 29 | } 30 | } 31 | } 32 | 33 | void main() { 34 | detect_system(); 35 | if (_is_COLOR) { 36 | // cpu_fast(); // cant use cpu_fast() with gbcamera 37 | cgb_compatibility(); 38 | } 39 | 40 | ENABLE_RAM; 41 | 42 | CRITICAL { 43 | STAT_REG |= STATF_LYC; 44 | LYC_REG = 144; 45 | add_LCD(scanlineIsr); 46 | } 47 | set_interrupts(VBL_IFLAG | LCD_IFLAG); 48 | 49 | remote_init(); 50 | remote_activate(REMOTE_ENABLED); 51 | 52 | initGfx(); 53 | initSound(); 54 | initCam(); 55 | initOverlays(); 56 | cleanupIndexGaps(); 57 | sortImages(); 58 | 59 | uint8_t splashPressed = splash(); 60 | clearBkg(); 61 | BGP_REG = PALETTE_NORMAL; 62 | 63 | if (splashPressed == J_A) { 64 | menuSelectMode(MAIN_LOOP_SHOOT_ASSISTED); 65 | } else { 66 | menuSelectMode(MAIN_LOOP_MENU); 67 | } 68 | 69 | mainLoop(); 70 | } 71 | -------------------------------------------------------------------------------- /src/mainLoop.c: -------------------------------------------------------------------------------- 1 | #pragma bank 255 2 | 3 | #include 4 | #include 5 | 6 | #include "defines.h" 7 | #include "globals.h" 8 | #include "gbcamera.h" 9 | #include "camera.h" 10 | #include "modeShootingManual.h" 11 | #include "modeShootingBurst.h" 12 | #include "modeShootingAssisted.h" 13 | #include "mainMenu.h" 14 | #include "debug.h" 15 | #include "gallery.h" 16 | #include "images.h" 17 | 18 | void fastLoadImageTiles() BANKED { 19 | SWITCH_RAM(0); 20 | set_data(VRAM_9000, last_seen_upper, HALF_IMAGE_SIZE); 21 | set_data(VRAM_8000, last_seen_lower, HALF_IMAGE_SIZE); 22 | } 23 | 24 | void mainLoop() BANKED { 25 | // Loop forever 26 | while (TRUE) { 27 | switch (mainLoopState) { 28 | case MAIN_LOOP_SHOOT_MANUAL: 29 | fastLoadImageTiles(); 30 | manualShootLoop(); 31 | break; 32 | case MAIN_LOOP_SHOOT_BURST: 33 | fastLoadImageTiles(); 34 | burstShootLoop(); 35 | break; 36 | case MAIN_LOOP_SHOOT_ASSISTED: 37 | fastLoadImageTiles(); 38 | assistedShootLoop(); 39 | break; 40 | case MAIN_LOOP_MENU: 41 | mainMenu(); 42 | break; 43 | case MAIN_LOOP_DEBUG: 44 | debugMenu(); 45 | break; 46 | case MAIN_LOOP_IMAGE_GALLERY: 47 | galleryMenu(); 48 | break; 49 | case MAIN_LOOP_IMAGE: 50 | imageMenu(); 51 | break; 52 | } 53 | 54 | wait_vbl_done(); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/mainMenu.c: -------------------------------------------------------------------------------- 1 | #pragma bank 255 2 | 3 | #include 4 | #include 5 | 6 | #include "menus/mainMenuItems.h" 7 | #include "globals.h" 8 | #include "joypad.h" 9 | #include "utils.h" 10 | #include "defines.h" 11 | #include "overlays/overlays.h" 12 | #include "debug.h" 13 | #include "gallery.h" 14 | #include "modeShootingBurst.h" 15 | #include "modeShootingManual.h" 16 | #include "modeShootingAssisted.h" 17 | #include "imageIndexing.h" 18 | #include "dialog.h" 19 | 20 | uint8_t mainMenuPos = 0; 21 | 22 | inline void mainMenuSprite() { 23 | move_sprite(SPRITE_MENU_INDICATOR, 16, yMenuSprite(mainMenuPos)); 24 | } 25 | 26 | void initMainMenu() BANKED { 27 | clearBkg(); 28 | hideOverlay(); 29 | 30 | for (uint8_t index = 0; index < NUM_MAIN_MENU_OPTIONS; index += 1) { 31 | set_bkg_based_tiles(2, yMenu(index), 16, 1, mainMenuItems[index].title, OFFSET_FONT - 32); 32 | } 33 | 34 | mainMenuSprite(); 35 | } 36 | 37 | void menuSelectMode(uint8_t loopState) BANKED { 38 | mainLoopState = loopState; 39 | if (loopState == MAIN_LOOP_SHOOT_MANUAL) { 40 | initManualMode(); 41 | } else if (loopState == MAIN_LOOP_SHOOT_BURST) { 42 | initBurstMode(); 43 | } else if (loopState == MAIN_LOOP_SHOOT_ASSISTED) { 44 | initAssistedMode(); 45 | } else if (loopState == MAIN_LOOP_MENU) { 46 | initMainMenu(); 47 | } else if (loopState == MAIN_LOOP_IMAGE_GALLERY) { 48 | initGallery(); 49 | } else if (loopState == MAIN_LOOP_IMAGE) { 50 | initImageMenu(); 51 | appearImageMenu(); 52 | loadAndShowGalleryImage(); 53 | } else if (loopState == MAIN_LOOP_DELETE_ALL) { 54 | if (dialog("Delete all? ", 0)) { 55 | deleteAllImages(); 56 | } 57 | mainLoopState = MAIN_LOOP_MENU; 58 | } else if (loopState == MAIN_LOOP_DEBUG) { 59 | initDebug(); 60 | } else { // fallback to main menu 61 | clearBkg(); 62 | boop(); 63 | mainLoopState = MAIN_LOOP_MENU; 64 | hideOverlay(); 65 | initMainMenu(); 66 | } 67 | } 68 | 69 | void mainMenu() BANKED { 70 | if (jp == J_DOWN) { 71 | clonk(); 72 | mainMenuPos = (mainMenuPos + 1) % NUM_MAIN_MENU_OPTIONS; 73 | mainMenuSprite(); 74 | joypadConsumed(); 75 | } else if (jp == J_UP) { 76 | clonk(); 77 | mainMenuPos = (mainMenuPos + NUM_MAIN_MENU_OPTIONS - 1) % NUM_MAIN_MENU_OPTIONS; 78 | mainMenuSprite(); 79 | joypadConsumed(); 80 | } else if (jp == J_A) { 81 | menuSelectMode(mainMenuItems[mainMenuPos].value); 82 | joypadConsumed(); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/menus/imageMenuItems.c: -------------------------------------------------------------------------------- 1 | #define NUM_IMAGE_MENU_OPTIONS 6 2 | 3 | #include "typedefs/MenuOption.h" 4 | #include "defines.h" 5 | 6 | const MenuOption imageMenuItems[NUM_IMAGE_MENU_OPTIONS] = { 7 | { IMAGE_MENU_INFO, "Info ", }, 8 | { IMAGE_MENU_HISTOGRAM, "Histogrm", }, 9 | { IMAGE_MENU_DELETE, "Delete ", }, 10 | { IMAGE_MENU_PRINT, "Print ", }, 11 | { IMAGE_MENU_BLEEP, "Beep Out", }, 12 | { IMAGE_MENU_EXPOSE, "Expose ", }, 13 | }; 14 | -------------------------------------------------------------------------------- /src/menus/mainMenuItems.c: -------------------------------------------------------------------------------- 1 | #define NUM_MAIN_MENU_OPTIONS 5 2 | 3 | #include "typedefs/MenuOption.h" 4 | #include "defines.h" 5 | 6 | const MenuOption mainMenuItems[NUM_MAIN_MENU_OPTIONS] = { 7 | // { MAIN_LOOP_NOT_IMPLEMENTED, "Automatic mode ", }, 8 | { MAIN_LOOP_SHOOT_MANUAL, "Manual mode ", }, 9 | { MAIN_LOOP_SHOOT_BURST, "Burst mode ", }, 10 | { MAIN_LOOP_SHOOT_ASSISTED, "Assisted mode ", }, 11 | // { MAIN_LOOP_NOT_IMPLEMENTED, "Settings mode ", }, 12 | // { MAIN_LOOP_NOT_IMPLEMENTED, "Continuous mode ", }, 13 | // { MAIN_LOOP_NOT_IMPLEMENTED, "Panorama mode ", }, 14 | { MAIN_LOOP_IMAGE_GALLERY, "Image Gallery ", }, 15 | // { MAIN_LOOP_NOT_IMPLEMENTED, "Settings ", }, 16 | { MAIN_LOOP_DELETE_ALL, "Clear all images", }, 17 | { MAIN_LOOP_DEBUG, "Debug ", }, 18 | }; 19 | -------------------------------------------------------------------------------- /src/menus/shootingAssistedMenuItems.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "typedefs/MenuItem.h" 3 | #include "values.h" 4 | #include "valuesAssisted.h" 5 | 6 | #define NUM_MENU_ELEMENTS_ASSISTED 3 7 | 8 | MenuItem assistedOptionsMenu = { 0, 0, 0, 2, NUM_ASSISTED_OPTIONS, 63, " Set", " Exposure Setting", &assistedOptions[0], 0, }; 9 | MenuItem contrastsMenuAssisted = { 7, 1, 0, 3, NUM_CONTRASTS, 8, "Cntrst", " Dither Contrast", &contrasts[0], 0, }; 10 | MenuItem ditherToggleMenu = { 14, 1, 0, 4, NUM_DITHER_TOGGLE, 0, "Dither", " Dither Toggle", &ditherToggle[0], 0, }; 11 | 12 | MenuItem *menuItemsAssisted[NUM_MENU_ELEMENTS_ASSISTED] = { 13 | &assistedOptionsMenu, 14 | &contrastsMenuAssisted, 15 | &ditherToggleMenu, 16 | }; 17 | -------------------------------------------------------------------------------- /src/menus/shootingManualMenuItems.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "typedefs/MenuItem.h" 3 | #include "values.h" 4 | 5 | #define NUM_MENU_ELEMENTS 11 6 | #define MENU_ACTION_NONE 0 7 | #define MENU_ACTION_DITHER 1 8 | 9 | MenuItem exposureTimesMenu = { 0, 0, 0, 2, NUM_EXPOSURE_TIMES, 24, "ExTime", " ExposureTime (ms)", &exposureTimes[0], MENU_ACTION_NONE, }; 10 | MenuItem gainsMenu = { 7, 0, 0, 1, NUM_GAIN_LEVELS, 4, " Gain", " Sensor Gain", &gains[0], MENU_ACTION_NONE, }; 11 | MenuItem voltageOutsMenu = { 14, 0, 0, 8, NUM_VOLTAGE_OUTS, 40, " V-Out", " Voltage Output", &voltageOuts[0], MENU_ACTION_NONE, }; 12 | 13 | MenuItem contrastsMenu = { 0, 1, 0, 3, NUM_CONTRASTS, 7, "Cntrst", " Dither Contrast", &contrasts[0], MENU_ACTION_DITHER, }; 14 | MenuItem ditherSetsMenu = { 7, 1, 0, 4, NUM_DITHERSETS, 1, "Dither", " Dither Set", &ditherSets[0], MENU_ACTION_DITHER, }; 15 | MenuItem voltageRefsMenu = { 14, 1, 0, 6, NUM_VOLTAGE_REFS, 3, " V-Ref", " VoltageReference", &voltageRefs[0], MENU_ACTION_NONE, }; 16 | 17 | MenuItem invertOutputsMenu = { 4, 2, 0, 11, NUM_INVERT_OUTPUTS, 0, "InvOut", " Invert Output", &invertOutputs[0], MENU_ACTION_NONE, }; 18 | MenuItem zeroPointsMenu = { 11, 2, 0, 7, NUM_ZERO_POINTS, 1, "0Point", " Zero Points", &zeroPoints[0], MENU_ACTION_NONE, }; 19 | 20 | MenuItem edgeOpModesMenu = { 0, 3, 0, 9, NUM_EDGE_OP_MODES, 3, "EdOper", " EdgeOperation", &edgeOpModes[0], MENU_ACTION_NONE, }; 21 | MenuItem edgeModesMenu = { 7, 3, 0, 5, NUM_EDGE_MODES, 0, "EdMode", " Edge Mode", &edgeModes[0], MENU_ACTION_NONE, }; 22 | MenuItem edgeExclusivesMenu = { 14, 3, 0, 10, NUM_EDGE_EXCLUSIVE, 1, "EdExcl", " EdgeExclusive", &edgeExclusives[0], MENU_ACTION_NONE, }; 23 | 24 | MenuItem captureModesMenu = { 0, 0, 0, 12, NUM_CAPTURE_MODES, 0, "Captur", " Capture Mode", &captureModes[0], MENU_ACTION_NONE, }; 25 | 26 | MenuItem *menuItems[NUM_MENU_ELEMENTS] = { 27 | &exposureTimesMenu, 28 | &gainsMenu, 29 | &voltageOutsMenu, 30 | 31 | &contrastsMenu, 32 | &ditherSetsMenu, 33 | &voltageRefsMenu, 34 | 35 | &invertOutputsMenu, 36 | &zeroPointsMenu, 37 | // &captureModesMenu, 38 | 39 | &edgeOpModesMenu, 40 | &edgeModesMenu, 41 | &edgeExclusivesMenu, 42 | }; 43 | -------------------------------------------------------------------------------- /src/modeShootingAssisted.c: -------------------------------------------------------------------------------- 1 | #pragma bank 255 2 | 3 | #include 4 | #include 5 | 6 | #include "globals.h" 7 | #include "defines.h" 8 | #include "utils.h" 9 | #include "joypad.h" 10 | #include "saveImage.h" 11 | #include "maps.h" 12 | #include "overlays/overlays.h" 13 | #include "imageIndexing.h" 14 | #include "bankedData.h" 15 | #include "mainMenu.h" 16 | #include "camera.h" 17 | #include "tiles.h" 18 | #include "dialog.h" 19 | #include "menus/shootingAssistedMenuItems.h" 20 | #include "valuesAssisted.h" 21 | #include "valuesDefs.h" 22 | 23 | uint8_t assistedMenuPos = 0; 24 | 25 | void renderAssistedMenu() BANKED { 26 | clonk(); 27 | fill_bkg_rect(0, 0, 20, 2, BLNK); 28 | fill_bkg_rect(0, 16, 20, 2, BLNK); 29 | 30 | uint8_t spriteX = (menuItemsAssisted[assistedMenuPos]->x * 8) + 8; 31 | move_sprite(SPRITE_MENU_INDICATOR, spriteX, 23); 32 | 33 | for (uint8_t i = 0; i < NUM_MENU_ELEMENTS_ASSISTED; i += 1) { 34 | uint8_t value = menuItemsAssisted[i]->value; 35 | set_bkg_based_tiles(menuItemsAssisted[i]->x, 0, MENU_TEXT_LENGTH, 1, menuItemsAssisted[i]->title, OFFSET_FONT - 32); 36 | set_bkg_based_tiles(menuItemsAssisted[i]->x, 1, MENU_TEXT_LENGTH, 1, menuItemsAssisted[i]->options[value].title, OFFSET_FONT - 32); 37 | } 38 | 39 | set_bkg_based_tiles(0, 16, 9, 2, menuItemsAssisted[assistedMenuPos]->description, OFFSET_FONT - 32); 40 | 41 | set_bkg_based_tiles(12, 16, 6, 2, " /30Images", OFFSET_FONT - 32); 42 | writeNumber(12, 16, 2, numVisibleImages); 43 | } 44 | 45 | void restoreAssistedDefaults() BANKED { 46 | for (uint8_t i = 0; i < NUM_MENU_ELEMENTS_ASSISTED; i += 1) { 47 | menuItemsAssisted[i]->value = menuItemsAssisted[i]->defaultValue; 48 | } 49 | } 50 | 51 | void updateDithering() BANKED { 52 | uint8_t assistedOptionIndex = getMenuValue(&assistedOptionsMenu); 53 | uint8_t ditherOnOff = getMenuValue(&ditherToggleMenu); 54 | uint8_t contrast = getMenuValue(&contrastsMenuAssisted); 55 | uint8_t ditherSet = assistedOptionsValues[assistedOptionIndex].ditherSet | getMenuValue(&ditherToggleMenu); 56 | 57 | setDitherMatrix(ditherSet, contrast); 58 | } 59 | 60 | void initAssistedMode() BANKED { 61 | clearBkg(); 62 | set_bkg_tiles_banked(2, 2, 16, 14, map_normal, 1); 63 | sortImages(); 64 | showOverlay(); 65 | restoreAssistedDefaults(); 66 | updateDithering(); 67 | renderAssistedMenu(); 68 | } 69 | 70 | void assistedShootLoop() BANKED { 71 | uint8_t assistedOptionIndex = getMenuValue(&assistedOptionsMenu); 72 | 73 | uint8_t capt = A000_START_CAPTURE_POSITIVE; 74 | uint8_t edExOpGain = assistedOptionsValues[assistedOptionIndex].edgeOperation | assistedOptionsValues[assistedOptionIndex].gain | assistedOptionsValues[assistedOptionIndex].edgeExclusive; 75 | uint16_t expTime = assistedOptionsValues[assistedOptionIndex].expTime; 76 | uint8_t edRInvVref = A004_EDGE_RATIO_050 | A004_VOLTAGE_REF_15 | A004_INVERT_OUTPUT_OFF; 77 | uint8_t zeroVout = assistedOptionsValues[assistedOptionIndex].vOut | A005_ZERO_POSITIVE; 78 | 79 | capture(capt, edExOpGain, expTime, edRInvVref, zeroVout); 80 | 81 | if (jp == J_RIGHT) { 82 | assistedMenuPos = (assistedMenuPos + 1) % NUM_MENU_ELEMENTS_ASSISTED; 83 | renderAssistedMenu(); 84 | joypadConsumed(); 85 | } else if (jp == J_LEFT) { 86 | assistedMenuPos = (assistedMenuPos + NUM_MENU_ELEMENTS_ASSISTED - 1) % NUM_MENU_ELEMENTS_ASSISTED; 87 | renderAssistedMenu(); 88 | joypadConsumed(); 89 | } else if (jp == J_UP) { 90 | menuItemsAssisted[assistedMenuPos]->value = (menuItemsAssisted[assistedMenuPos]->value + 1) % menuItemsAssisted[assistedMenuPos]->numOptions; 91 | updateDithering(); 92 | renderAssistedMenu(); 93 | joypadConsumed(); 94 | } else if (jp == J_DOWN) { 95 | menuItemsAssisted[assistedMenuPos]->value = (menuItemsAssisted[assistedMenuPos]->value + menuItemsAssisted[assistedMenuPos]->numOptions - 1) % menuItemsAssisted[assistedMenuPos]->numOptions; 96 | updateDithering(); 97 | renderAssistedMenu(); 98 | joypadConsumed(); 99 | } else if (jp == J_B) { 100 | menuSelectMode(MAIN_LOOP_MENU); 101 | joypadConsumed(); 102 | } else if (jp == J_SELECT) { 103 | if (dialog("Reset settings? ", 1)) { 104 | restoreAssistedDefaults(); 105 | updateDithering(); 106 | renderAssistedMenu(); 107 | } 108 | joypadConsumed(); 109 | } else if (jp == J_A) { 110 | uint8_t ditherSet = assistedOptionsValues[assistedOptionIndex].ditherSet | getMenuValue(&ditherToggleMenu); 111 | uint8_t contrast = getMenuValue(&contrastsMenuAssisted); 112 | 113 | saveImageDialog(capt, edExOpGain, expTime, edRInvVref, zeroVout, ditherSet, contrast); 114 | renderAssistedMenu(); 115 | joypadConsumed(); 116 | } else if (jp == J_START) { 117 | nextOverlay(); 118 | clonk(); 119 | showOverlay(); 120 | joypadConsumed(); 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/modeShootingBurst.c: -------------------------------------------------------------------------------- 1 | #pragma bank 255 2 | 3 | #include 4 | #include 5 | 6 | #include "globals.h" 7 | #include "defines.h" 8 | #include "utils.h" 9 | #include "joypad.h" 10 | #include "saveImage.h" 11 | #include "maps.h" 12 | #include "menus/shootingManualMenuItems.h" 13 | #include "overlays/overlays.h" 14 | #include "imageIndexing.h" 15 | #include "bankedData.h" 16 | #include "mainMenu.h" 17 | #include "camera.h" 18 | #include "values.h" 19 | 20 | uint8_t burstActive = 0; 21 | 22 | static void renderBurstMenu() { 23 | set_bkg_based_tiles(12, 16, 6, 2, " /30Images", OFFSET_FONT - 32); 24 | writeNumber(12, 16, 2, numVisibleImages); 25 | } 26 | 27 | void initBurstMode() BANKED { 28 | clearBkg(); 29 | set_bkg_tiles_banked(2, 2, 16, 14, map_normal, 1); 30 | sortImages(); 31 | showOverlay(); 32 | renderBurstMenu(); 33 | move_sprite(SPRITE_MENU_INDICATOR, 0, 0); 34 | burstActive = 0; 35 | } 36 | 37 | void burstShootLoop() BANKED { 38 | uint8_t capt = getMenuValue(&captureModesMenu); 39 | uint8_t edExOpGain = getMenuValue(&edgeOpModesMenu) | getMenuValue(&gainsMenu) | getMenuValue(&edgeExclusivesMenu); 40 | uint16_t expTime = exposureTimesValues[getMenuValue(&exposureTimesMenu)]; 41 | uint8_t edRInvVref = getMenuValue(&edgeModesMenu) | getMenuValue(&voltageRefsMenu) | getMenuValue(&invertOutputsMenu); 42 | uint8_t zeroVout = getMenuValue(&voltageOutsMenu) | getMenuValue(&zeroPointsMenu); 43 | 44 | uint8_t ditherSet = getMenuValue(&ditherSetsMenu); 45 | uint8_t contrast = getMenuValue(&contrastsMenu); 46 | 47 | capture(capt, edExOpGain, expTime, edRInvVref, zeroVout); 48 | 49 | if (jp == J_B) { 50 | burstActive = 0; 51 | menuSelectMode(MAIN_LOOP_MENU); 52 | joypadConsumed(); 53 | } else if (jp == J_A) { 54 | burstActive = 1; 55 | beep(); 56 | joypadConsumed(); 57 | } 58 | 59 | if (burstActive == 1) { 60 | if (findFirstFreeSlot() != NUM_IMAGES) { 61 | saveImage(capt, edExOpGain, expTime, edRInvVref, zeroVout, ditherSet, contrast); 62 | renderBurstMenu(); 63 | } else { 64 | boop(); 65 | burstActive = 0; 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/modeShootingManual.c: -------------------------------------------------------------------------------- 1 | #pragma bank 255 2 | 3 | #include 4 | #include 5 | 6 | #include "globals.h" 7 | #include "defines.h" 8 | #include "utils.h" 9 | #include "joypad.h" 10 | #include "saveImage.h" 11 | #include "tiles.h" 12 | #include "maps.h" 13 | #include "menus/shootingManualMenuItems.h" 14 | #include "overlays/overlays.h" 15 | #include "gbcamera.h" 16 | #include "bankedData.h" 17 | #include "mainMenu.h" 18 | #include "camera.h" 19 | #include "dialog.h" 20 | #include "values.h" 21 | 22 | #define SETTINGS_REQUIRE_RESET TRUE 23 | #define SETTINGS_REQUIRE_NO_RESET FALSE 24 | 25 | uint8_t manualMenuPos = 0; 26 | 27 | void renderManualMenu() BANKED { 28 | clonk(); 29 | fill_bkg_rect(0, 0, 20, 2, BLNK); 30 | fill_bkg_rect(0, 16, 20, 2, BLNK); 31 | 32 | uint8_t currentPage = menuItems[manualMenuPos]->page; 33 | uint8_t spriteX = (menuItems[manualMenuPos]->x * 8) + 8; 34 | move_sprite(SPRITE_MENU_INDICATOR, spriteX, 23); 35 | 36 | for (uint8_t i = 0; i < NUM_MENU_ELEMENTS; i += 1) { 37 | 38 | if (menuItems[i]->page == currentPage) { 39 | 40 | uint8_t value = menuItems[i]->value; 41 | set_bkg_based_tiles(menuItems[i]->x, 0, MENU_TEXT_LENGTH, 1, menuItems[i]->title, OFFSET_FONT - 32); 42 | set_bkg_based_tiles(menuItems[i]->x, 1, MENU_TEXT_LENGTH, 1, menuItems[i]->options[value].title, OFFSET_FONT - 32); 43 | 44 | } 45 | } 46 | 47 | set_bkg_based_tiles(0, 16, 9, 2, menuItems[manualMenuPos]->description, OFFSET_FONT - 32); 48 | 49 | set_bkg_based_tiles(12, 16, 6, 2, " /30Images", OFFSET_FONT - 32); 50 | writeNumber(12, 16, 2, numVisibleImages); 51 | } 52 | 53 | void initManualMode() BANKED { 54 | clearBkg(); 55 | set_bkg_tiles_banked(2, 2, 16, 14, map_normal, 1); 56 | sortImages(); 57 | showOverlay(); 58 | renderManualMenu(); 59 | } 60 | 61 | void storeSettings() BANKED { 62 | SWITCH_RAM(1); 63 | for (uint8_t i = 0; i < NUM_MENU_ELEMENTS; i += 1) { 64 | image_first_unused[menuItems[i]->storeOffset] = menuItems[i]->value; 65 | } 66 | } 67 | 68 | void restoreDefaults() BANKED { 69 | for (uint8_t i = 0; i < NUM_MENU_ELEMENTS; i += 1) { 70 | menuItems[i]->value = menuItems[i]->defaultValue; 71 | } 72 | 73 | storeSettings(); 74 | } 75 | 76 | uint8_t loadSettingsFromRAM() BANKED { 77 | SWITCH_RAM(1); 78 | 79 | uint8_t i = 0; 80 | uint8_t noAA = 0; 81 | 82 | // check if any of the storage cells already has a valid value 83 | // the initial value which is never changes on an original cart is 0xAA 84 | for (i = 0; i < NUM_MENU_ELEMENTS; i += 1) { 85 | if (image_first_unused[menuItems[i]->storeOffset] != 0xAA) { 86 | noAA = 1; 87 | } 88 | } 89 | 90 | // load initial values from storage cells 91 | if (noAA) { 92 | 93 | for (i = 0; i < NUM_MENU_ELEMENTS; i += 1) { 94 | menuItems[i]->value = image_first_unused[menuItems[i]->storeOffset]; 95 | } 96 | 97 | return SETTINGS_REQUIRE_NO_RESET; 98 | } 99 | 100 | return SETTINGS_REQUIRE_RESET; 101 | } 102 | 103 | void menuAction() BANKED { 104 | if (menuItems[manualMenuPos]->action == MENU_ACTION_DITHER) { 105 | setDitherMatrix(getMenuValue(&ditherSetsMenu), getMenuValue(&contrastsMenu)); 106 | } 107 | } 108 | 109 | void manualShootLoop() BANKED { 110 | uint8_t capt = getMenuValue(&captureModesMenu); 111 | uint8_t edExOpGain = getMenuValue(&edgeOpModesMenu) | getMenuValue(&gainsMenu) | getMenuValue(&edgeExclusivesMenu); 112 | uint16_t expTime = exposureTimesValues[getMenuValue(&exposureTimesMenu)]; 113 | uint8_t edRInvVref = getMenuValue(&edgeModesMenu) | getMenuValue(&voltageRefsMenu) | getMenuValue(&invertOutputsMenu); 114 | uint8_t zeroVout = getMenuValue(&voltageOutsMenu) | getMenuValue(&zeroPointsMenu); 115 | 116 | uint8_t ditherSet = getMenuValue(&ditherSetsMenu); 117 | uint8_t contrast = getMenuValue(&contrastsMenu); 118 | 119 | capture(capt, edExOpGain, expTime, edRInvVref, zeroVout); 120 | 121 | if (jp == J_RIGHT) { 122 | manualMenuPos = (manualMenuPos + 1) % NUM_MENU_ELEMENTS; 123 | renderManualMenu(); 124 | joypadConsumed(); 125 | } else if (jp == J_LEFT) { 126 | manualMenuPos = (manualMenuPos + NUM_MENU_ELEMENTS - 1) % NUM_MENU_ELEMENTS; 127 | renderManualMenu(); 128 | joypadConsumed(); 129 | } else if (jp == J_UP) { 130 | 131 | menuItems[manualMenuPos]->value = (menuItems[manualMenuPos]->value + 1) % menuItems[manualMenuPos]->numOptions; 132 | 133 | menuAction(); 134 | storeSettings(); 135 | renderManualMenu(); 136 | joypadConsumed(); 137 | } else if (jp == J_DOWN) { 138 | 139 | menuItems[manualMenuPos]->value = (menuItems[manualMenuPos]->value + menuItems[manualMenuPos]->numOptions - 1) % menuItems[manualMenuPos]->numOptions; 140 | 141 | menuAction(); 142 | storeSettings(); 143 | renderManualMenu(); 144 | joypadConsumed(); 145 | } else if (jp == J_B) { 146 | menuSelectMode(MAIN_LOOP_MENU); 147 | joypadConsumed(); 148 | } else if (jp == J_SELECT) { 149 | if (dialog("Reset settings? ", 1)) { 150 | restoreDefaults(); 151 | setDitherMatrix(getMenuValue(&ditherSetsMenu), getMenuValue(&contrastsMenu)); 152 | renderManualMenu(); 153 | } 154 | 155 | joypadConsumed(); 156 | } else if (jp == J_A) { 157 | saveImageDialog(capt, edExOpGain, expTime, edRInvVref, zeroVout, ditherSet, contrast); 158 | joypadConsumed(); 159 | } else if (jp == J_START) { 160 | nextOverlay(); 161 | clonk(); 162 | showOverlay(); 163 | joypadConsumed(); 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /src/overlays/overlayDefs.c: -------------------------------------------------------------------------------- 1 | #include "typedefs/Overlay.h" 2 | #include "defines.h" 3 | 4 | #define NUM_OVERLAY_SPRITES 16 5 | 6 | const Overlay noOverlayH1 = { SPRITE_BORDER_H_1, 0, 0, }; 7 | const Overlay noOverlayH2 = { SPRITE_BORDER_H_2, 0, 0, }; 8 | const Overlay noOverlayH3 = { SPRITE_BORDER_H_3, 0, 0, }; 9 | const Overlay noOverlayH4 = { SPRITE_BORDER_H_4, 0, 0, }; 10 | const Overlay noOverlayH5 = { SPRITE_BORDER_H_5, 0, 0, }; 11 | const Overlay noOverlayH6 = { SPRITE_BORDER_H_6, 0, 0, }; 12 | const Overlay noOverlayH7 = { SPRITE_BORDER_H_7, 0, 0, }; 13 | const Overlay noOverlayH8 = { SPRITE_BORDER_H_8, 0, 0, }; 14 | const Overlay noOverlayV1 = { SPRITE_BORDER_V_1, 0, 0, }; 15 | const Overlay noOverlayV2 = { SPRITE_BORDER_V_2, 0, 0, }; 16 | const Overlay noOverlayV3 = { SPRITE_BORDER_V_3, 0, 0, }; 17 | const Overlay noOverlayV4 = { SPRITE_BORDER_V_4, 0, 0, }; 18 | const Overlay noOverlayV5 = { SPRITE_BORDER_V_5, 0, 0, }; 19 | const Overlay noOverlayV6 = { SPRITE_BORDER_V_6, 0, 0, }; 20 | const Overlay noOverlayV7 = { SPRITE_BORDER_V_7, 0, 0, }; 21 | const Overlay noOverlayV8 = { SPRITE_BORDER_V_8, 0, 0, }; 22 | 23 | const Overlay *noOverlay[NUM_OVERLAY_SPRITES] = { 24 | &noOverlayH1, &noOverlayH2, &noOverlayH3, &noOverlayH4, 25 | &noOverlayH5, &noOverlayH6, &noOverlayH7, &noOverlayH8, 26 | &noOverlayV1, &noOverlayV2, &noOverlayV3, &noOverlayV4, 27 | &noOverlayV5, &noOverlayV6, &noOverlayV7, &noOverlayV8, 28 | }; 29 | 30 | const Overlay outerBorderH1 = { SPRITE_BORDER_H_1, 24, 32, }; 31 | const Overlay outerBorderH2 = { SPRITE_BORDER_H_2, 32, 32, }; 32 | const Overlay outerBorderH3 = { SPRITE_BORDER_H_3, 136, 32, }; 33 | const Overlay outerBorderH4 = { SPRITE_BORDER_H_4, 144, 32, }; 34 | const Overlay outerBorderH5 = { SPRITE_BORDER_H_5, 24, 143, }; 35 | const Overlay outerBorderH6 = { SPRITE_BORDER_H_6, 32, 143, }; 36 | const Overlay outerBorderH7 = { SPRITE_BORDER_H_7, 136, 143, }; 37 | const Overlay outerBorderH8 = { SPRITE_BORDER_H_8, 144, 143, }; 38 | const Overlay outerBorderV1 = { SPRITE_BORDER_V_1, 17, 31, }; 39 | const Overlay outerBorderV2 = { SPRITE_BORDER_V_2, 17, 39, }; 40 | const Overlay outerBorderV3 = { SPRITE_BORDER_V_3, 144, 31, }; 41 | const Overlay outerBorderV4 = { SPRITE_BORDER_V_4, 144, 39, }; 42 | const Overlay outerBorderV5 = { SPRITE_BORDER_V_5, 17, 127, }; 43 | const Overlay outerBorderV6 = { SPRITE_BORDER_V_6, 17, 135, }; 44 | const Overlay outerBorderV7 = { SPRITE_BORDER_V_7, 144, 127, }; 45 | const Overlay outerBorderV8 = { SPRITE_BORDER_V_8, 144, 135, }; 46 | 47 | const Overlay *outerBorder[NUM_OVERLAY_SPRITES] = { 48 | &outerBorderH1, &outerBorderH2, &outerBorderH3, &outerBorderH4, 49 | &outerBorderH5, &outerBorderH6, &outerBorderH7, &outerBorderH8, 50 | &outerBorderV1, &outerBorderV2, &outerBorderV3, &outerBorderV4, 51 | &outerBorderV5, &outerBorderV6, &outerBorderV7, &outerBorderV8, 52 | }; 53 | 54 | const Overlay ruleOfThirdsH1 = { SPRITE_BORDER_H_1, 59, 69, }; 55 | const Overlay ruleOfThirdsH2 = { SPRITE_BORDER_H_2, 66, 69, }; 56 | const Overlay ruleOfThirdsH3 = { SPRITE_BORDER_H_3, 102, 69, }; 57 | const Overlay ruleOfThirdsH4 = { SPRITE_BORDER_H_4, 109, 69, }; 58 | const Overlay ruleOfThirdsH5 = { SPRITE_BORDER_H_5, 59, 106, }; 59 | const Overlay ruleOfThirdsH6 = { SPRITE_BORDER_H_6, 66, 106, }; 60 | const Overlay ruleOfThirdsH7 = { SPRITE_BORDER_H_7, 102, 106, }; 61 | const Overlay ruleOfThirdsH8 = { SPRITE_BORDER_H_8, 109, 106, }; 62 | const Overlay ruleOfThirdsV1 = { SPRITE_BORDER_V_1, 59, 62, }; 63 | const Overlay ruleOfThirdsV2 = { SPRITE_BORDER_V_2, 59, 69, }; 64 | const Overlay ruleOfThirdsV3 = { SPRITE_BORDER_V_3, 102, 62, }; 65 | const Overlay ruleOfThirdsV4 = { SPRITE_BORDER_V_4, 102, 69, }; 66 | const Overlay ruleOfThirdsV5 = { SPRITE_BORDER_V_5, 59, 99, }; 67 | const Overlay ruleOfThirdsV6 = { SPRITE_BORDER_V_6, 59, 106, }; 68 | const Overlay ruleOfThirdsV7 = { SPRITE_BORDER_V_7, 102, 99, }; 69 | const Overlay ruleOfThirdsV8 = { SPRITE_BORDER_V_8, 102, 106, }; 70 | 71 | const Overlay *ruleOfThirds[NUM_OVERLAY_SPRITES] = { 72 | &ruleOfThirdsH1, &ruleOfThirdsH2, &ruleOfThirdsH3, &ruleOfThirdsH4, 73 | &ruleOfThirdsH5, &ruleOfThirdsH6, &ruleOfThirdsH7, &ruleOfThirdsH8, 74 | &ruleOfThirdsV1, &ruleOfThirdsV2, &ruleOfThirdsV3, &ruleOfThirdsV4, 75 | &ruleOfThirdsV5, &ruleOfThirdsV6, &ruleOfThirdsV7, &ruleOfThirdsV8, 76 | }; 77 | -------------------------------------------------------------------------------- /src/overlays/overlays.c: -------------------------------------------------------------------------------- 1 | #pragma bank 255 2 | 3 | #include 4 | #include 5 | #include "defines.h" 6 | #include "globals.h" 7 | #include "overlays/overlayDefs.h" 8 | 9 | void initOverlays() BANKED { 10 | set_sprite_tile(SPRITE_BORDER_H_1, OFFSET_BORDER_H); 11 | set_sprite_tile(SPRITE_BORDER_H_2, OFFSET_BORDER_H); 12 | set_sprite_tile(SPRITE_BORDER_H_3, OFFSET_BORDER_H); 13 | set_sprite_tile(SPRITE_BORDER_H_4, OFFSET_BORDER_H); 14 | set_sprite_tile(SPRITE_BORDER_H_5, OFFSET_BORDER_H); 15 | set_sprite_tile(SPRITE_BORDER_H_6, OFFSET_BORDER_H); 16 | set_sprite_tile(SPRITE_BORDER_H_7, OFFSET_BORDER_H); 17 | set_sprite_tile(SPRITE_BORDER_H_8, OFFSET_BORDER_H); 18 | 19 | set_sprite_tile(SPRITE_BORDER_V_1, OFFSET_BORDER_V); 20 | set_sprite_tile(SPRITE_BORDER_V_2, OFFSET_BORDER_V); 21 | set_sprite_tile(SPRITE_BORDER_V_3, OFFSET_BORDER_V); 22 | set_sprite_tile(SPRITE_BORDER_V_4, OFFSET_BORDER_V); 23 | set_sprite_tile(SPRITE_BORDER_V_5, OFFSET_BORDER_V); 24 | set_sprite_tile(SPRITE_BORDER_V_6, OFFSET_BORDER_V); 25 | set_sprite_tile(SPRITE_BORDER_V_7, OFFSET_BORDER_V); 26 | set_sprite_tile(SPRITE_BORDER_V_8, OFFSET_BORDER_V); 27 | 28 | set_sprite_prop(SPRITE_BORDER_H_1, S_PALETTE); 29 | set_sprite_prop(SPRITE_BORDER_H_2, S_PALETTE); 30 | set_sprite_prop(SPRITE_BORDER_H_3, S_PALETTE); 31 | set_sprite_prop(SPRITE_BORDER_H_4, S_PALETTE); 32 | set_sprite_prop(SPRITE_BORDER_H_5, S_PALETTE); 33 | set_sprite_prop(SPRITE_BORDER_H_6, S_PALETTE); 34 | set_sprite_prop(SPRITE_BORDER_H_7, S_PALETTE); 35 | set_sprite_prop(SPRITE_BORDER_H_8, S_PALETTE); 36 | 37 | set_sprite_prop(SPRITE_BORDER_V_1, S_PALETTE); 38 | set_sprite_prop(SPRITE_BORDER_V_2, S_PALETTE); 39 | set_sprite_prop(SPRITE_BORDER_V_3, S_PALETTE); 40 | set_sprite_prop(SPRITE_BORDER_V_4, S_PALETTE); 41 | set_sprite_prop(SPRITE_BORDER_V_5, S_PALETTE); 42 | set_sprite_prop(SPRITE_BORDER_V_6, S_PALETTE); 43 | set_sprite_prop(SPRITE_BORDER_V_7, S_PALETTE); 44 | set_sprite_prop(SPRITE_BORDER_V_8, S_PALETTE); 45 | } 46 | 47 | uint8_t currentOverlay = 1; 48 | 49 | void showOverlay() BANKED { 50 | for (uint8_t ov = 0; ov < NUM_OVERLAY_SPRITES; ov++) { 51 | if (currentOverlay == 0) { 52 | move_sprite(noOverlay[ov]->sprite, noOverlay[ov]->x, noOverlay[ov]->y); 53 | } else if (currentOverlay == 1) { 54 | move_sprite(outerBorder[ov]->sprite, outerBorder[ov]->x, outerBorder[ov]->y); 55 | } else if (currentOverlay == 2) { 56 | move_sprite(ruleOfThirds[ov]->sprite, ruleOfThirds[ov]->x, ruleOfThirds[ov]->y); 57 | } 58 | } 59 | } 60 | 61 | void hideLowerOverlay() BANKED { 62 | for (uint8_t ov = 0; ov < NUM_OVERLAY_SPRITES; ov++) { 63 | if (currentOverlay == 0) { 64 | if (noOverlay[ov]->y > 99) { 65 | move_sprite(noOverlay[ov]->sprite, 0, 0); 66 | } 67 | } else if (currentOverlay == 1) { 68 | if (outerBorder[ov]->y > 99) { 69 | move_sprite(outerBorder[ov]->sprite, 0, 0); 70 | } 71 | } else if (currentOverlay == 2) { 72 | if (ruleOfThirds[ov]->y > 99) { 73 | move_sprite(ruleOfThirds[ov]->sprite, 0, 0); 74 | } 75 | } 76 | } 77 | } 78 | 79 | void hideOverlay() BANKED { 80 | for (uint8_t ov = 0; ov < NUM_OVERLAY_SPRITES; ov++) { 81 | move_sprite(noOverlay[ov]->sprite, 0, 0); 82 | } 83 | } 84 | 85 | void nextOverlay() BANKED { 86 | currentOverlay = (currentOverlay + 1) % NUM_OVERLAYS; 87 | } 88 | -------------------------------------------------------------------------------- /src/printCmd.c: -------------------------------------------------------------------------------- 1 | // Original library by DragonEagles from http://shen.mansell.tripod.com/games/gameboy/gameboy.html 2 | // Ported to GBDK 2020 by T0biasCZe 3 | // Print Screen function added by Christianr 4 | // Print Screen (360 tile mode) added by T0biasCZe 5 | 6 | #pragma bank 255 7 | 8 | #include 9 | #include 10 | #include 11 | #include "frame_pxlr.h" 12 | #include "wild_top.h" 13 | #include "wild_center.h" 14 | #include "wild_bottom.h" 15 | #include "font.h" 16 | 17 | uint8_t printerStatus[3]; 18 | 19 | #define PALETTE_NORMAL 0b11100100u 20 | #define PALETTE_INVERTED 0b00011011u 21 | 22 | #define MAGIC_1 0x88 23 | #define MAGIC_2 0x33 24 | 25 | #define COMMAND_INIT 0x01 26 | #define COMMAND_PRINT 0x02 27 | #define COMMAND_DATA 0x04 28 | #define COMMAND_STATUS 0x0F 29 | 30 | #define EXPOSURE_LIGHT 0x00 31 | #define EXPOSURE_DEFAULT 0x40 32 | #define EXPOSURE_DARK 0x7F 33 | 34 | #define STATUS_LOWBAT 0x80 35 | #define STATUS_ER2 0x40 36 | #define STATUS_ER1 0x20 37 | #define STATUS_ER0 0x10 38 | #define STATUS_UNTRAN 0x08 39 | #define STATUS_FULL 0x04 40 | #define STATUS_BUSY 0x02 41 | #define STATUS_SUM 0x01 42 | 43 | const uint8_t PRINTER_INIT[] = { 6, MAGIC_1, MAGIC_2, COMMAND_INIT, 0x00, 0x00, 0x00, }; 44 | const uint8_t PRINTER_STATUS[] = { 6, MAGIC_1, MAGIC_2, COMMAND_STATUS, 0x00, 0x00, 0x00, }; 45 | const uint8_t PRINTER_START[] = { 6, MAGIC_1, MAGIC_2, COMMAND_PRINT, 0x00, 0x04, 0x00, }; // 0x04, 0x00 = length 4 Bytes 46 | const uint8_t PRINTER_EOF[] = { 6, MAGIC_1, MAGIC_2, COMMAND_DATA, 0x00, 0x00, 0x00, }; 47 | const uint8_t PRINT_TILE[] = { 6, MAGIC_1, MAGIC_2, COMMAND_DATA, 0x00, 0x80, 0x02, }; // 0x80, 0x02 = length 640 Bytes 48 | 49 | uint8_t tile_num, packet_num; 50 | 51 | uint16_t CRC; 52 | 53 | uint8_t sendPrinterByte(uint8_t byte) BANKED { 54 | uint8_t result; 55 | SB_REG = byte; // data to send 56 | SC_REG = 0x81; // 1000 0001 - start, internal clock 57 | while (SC_REG & 0x80); // wait until b1 reset 58 | result = SB_REG; // return response stored in SB_REG 59 | return result; 60 | } 61 | 62 | void sendByte(uint8_t dataByte, uint8_t addToChecksum) BANKED { 63 | if (addToChecksum) { 64 | CRC += dataByte; 65 | } 66 | 67 | uint8_t result; 68 | result = sendPrinterByte(dataByte); 69 | printerStatus[0] = printerStatus[1]; 70 | printerStatus[1] = printerStatus[2]; 71 | printerStatus[2] = result; 72 | } 73 | 74 | void sendPrinterCommand(const uint8_t *command) BANKED { 75 | uint8_t length, index; 76 | index = 0; 77 | length = *command; 78 | CRC = 0; 79 | 80 | while (index < length) { 81 | index++; 82 | sendByte(*(command + index), index > 2); 83 | } 84 | } 85 | 86 | 87 | inline uint8_t getHigh(uint16_t w) { 88 | return (w & 0xFF00u) >> 8; 89 | } 90 | 91 | inline uint8_t getLow(uint16_t w) { 92 | return (w & 0xFFu); 93 | } 94 | 95 | 96 | void sendChecksum() BANKED { 97 | sendByte(getLow(CRC), FALSE); 98 | sendByte(getHigh(CRC), FALSE); 99 | sendByte(0x00, FALSE); 100 | sendByte(0x00, FALSE); 101 | } 102 | 103 | void printerInit() BANKED { 104 | tile_num = 0; 105 | packet_num = 0; 106 | sendPrinterCommand(PRINTER_INIT); 107 | sendChecksum(); 108 | } 109 | 110 | uint8_t checkLinkCable() BANKED { 111 | if (printerStatus[0] != 0) { 112 | return 2; 113 | } 114 | if ((printerStatus[1] & 0xF0) != 0x80) { 115 | return 2; 116 | } 117 | return 0; 118 | } 119 | 120 | uint8_t getPrinterStatus() BANKED { 121 | sendPrinterCommand(PRINTER_STATUS); 122 | sendChecksum(); 123 | return checkLinkCable(); 124 | } 125 | 126 | uint8_t checkForErrors() BANKED { 127 | if (printerStatus[2] & STATUS_LOWBAT) { 128 | return 1; 129 | } 130 | if (printerStatus[2] & STATUS_ER2) { 131 | return 2; 132 | } 133 | if (printerStatus[2] & STATUS_ER1) { 134 | return 3; 135 | } 136 | if (printerStatus[2] & STATUS_ER0) { 137 | return 4; 138 | } 139 | if (printerStatus[2] & STATUS_SUM) { 140 | return 5; 141 | } 142 | return 0; 143 | } 144 | 145 | uint8_t printerBusy() BANKED { 146 | sendPrinterCommand(PRINTER_STATUS); 147 | sendChecksum(); 148 | return (printerStatus[2] & STATUS_BUSY); 149 | } 150 | 151 | 152 | void waitPrinterReady() BANKED { 153 | // Wait for max 30s to give the printer time to become ready. 154 | // If not ready after 30s, return anyway to not hang the program 155 | for (uint16_t wait = 0; wait < 1800; wait++) { 156 | wait_vbl_done(); 157 | if (!printerBusy()) { 158 | return; 159 | } 160 | } 161 | } 162 | 163 | 164 | void printTileData(const uint8_t *tileData, uint8_t num_packets, uint8_t margins, uint8_t palette, uint8_t exposure) NONBANKED { 165 | uint8_t tileIndex; 166 | 167 | if (tile_num == 0) { 168 | sendPrinterCommand(PRINT_TILE); 169 | } 170 | 171 | tile_num++; 172 | 173 | for (tileIndex = 0; tileIndex < 16; tileIndex++) { 174 | sendByte(tileData[tileIndex], TRUE); 175 | } 176 | 177 | // two lines of 20 tiles each 178 | if (tile_num == 40) { 179 | sendChecksum(); 180 | 181 | tile_num = 0; 182 | packet_num++; 183 | 184 | if (packet_num == num_packets) { // all done the page 185 | packet_num = 0; 186 | sendPrinterCommand(PRINTER_EOF); // data end packet 187 | sendChecksum(); 188 | 189 | sendPrinterCommand(PRINTER_START); 190 | sendByte(0x01, TRUE); // Sheets 191 | sendByte(margins, TRUE); // Margin 192 | sendByte(palette, TRUE); // Palette (normal=0xE4, inverted=0x1B) 193 | sendByte(exposure, TRUE); // Exposure/Intensity (min=0x00, default=0x40, max=0x7F) 194 | sendChecksum(); 195 | 196 | // Wait for max 2s to give the printer time to become "busy". 197 | // If not busy after 2s, return anyway to not hang the program 198 | for (uint8_t wait = 0; wait < 120; wait++) { 199 | wait_vbl_done(); 200 | if (printerBusy()) { 201 | return; 202 | } 203 | } 204 | 205 | } 206 | } 207 | } 208 | 209 | 210 | 211 | void printImageWild(uint8_t *lower, uint8_t *upper, uint8_t bank) NONBANKED { 212 | uint8_t save = _current_bank; 213 | uint16_t index; 214 | uint8_t x; 215 | uint8_t y; 216 | 217 | printerInit(); 218 | 219 | SWITCH_ROM(BANK(wild_top)); 220 | for (index = 0; index < 280; index++) { 221 | printTileData(&wild_top_tiles[wild_top_map[index] * 16], 7, 0x00, PALETTE_NORMAL, EXPOSURE_DEFAULT); 222 | } 223 | 224 | waitPrinterReady(); 225 | printerInit(); 226 | 227 | SWITCH_RAM(bank); 228 | SWITCH_ROM(BANK(wild_center)); 229 | uint8_t *image = upper; 230 | for (y = 0; y < 14; y++) { 231 | if (y == 7) { 232 | image = lower; 233 | } 234 | 235 | for (x = 0; x < 20; x++) { 236 | if (x < 2 || x >= 18) { 237 | printTileData(&wild_center_tiles[wild_center_map[x] * 16], 7, 0x00, PALETTE_NORMAL, EXPOSURE_DEFAULT); 238 | } else { 239 | printTileData(image, 7, 0x00, PALETTE_NORMAL, EXPOSURE_DEFAULT); 240 | image += 16; 241 | } 242 | } 243 | } 244 | 245 | waitPrinterReady(); 246 | printerInit(); 247 | 248 | SWITCH_ROM(BANK(wild_bottom)); 249 | for (index = 0; index < 320; index++) { 250 | printTileData(&wild_bottom_tiles[wild_bottom_map[index] * 16], 8, 0x02, PALETTE_NORMAL, EXPOSURE_DEFAULT); 251 | } 252 | 253 | SWITCH_ROM(save); 254 | } 255 | 256 | 257 | void printImage(uint8_t *lower, uint8_t *upper, uint8_t bank) NONBANKED { 258 | uint8_t save = _current_bank; 259 | SWITCH_ROM(BANK(frame_pxlr)); 260 | 261 | printerInit(); 262 | SWITCH_RAM(bank); 263 | uint8_t x, y; 264 | uint16_t frameTileIndex = 0; 265 | 266 | uint8_t *image = upper; 267 | for (y = 0; y < 18; y++) { 268 | for (x = 0; x < 20; x++) { 269 | if (x == 0 && y == 9) { 270 | image = lower; 271 | } 272 | 273 | if (x < 2 || y < 2 || x >= 18 || y >= 16) { 274 | printTileData(&frame_pxlr_tiles[frame_pxlr_map[frameTileIndex] * 16], 9, 0x02, PALETTE_NORMAL, EXPOSURE_DEFAULT); 275 | } else { 276 | printTileData(image, 9, 0x03, PALETTE_NORMAL, EXPOSURE_DEFAULT); 277 | image += 16; 278 | } 279 | 280 | frameTileIndex++; 281 | } 282 | } 283 | 284 | SWITCH_ROM(save); 285 | } 286 | 287 | void printImageInfo(uint8_t *imageInfo) NONBANKED { 288 | uint8_t save = _current_bank; 289 | SWITCH_ROM(BANK(frame_pxlr)); 290 | 291 | uint16_t index; 292 | printerInit(); 293 | 294 | for (index = 0; index < 40; index++) { 295 | printTileData(&frame_pxlr_tiles[frame_pxlr_map[index] * 16], 1, 0x00, PALETTE_INVERTED, EXPOSURE_DEFAULT); 296 | } 297 | 298 | waitPrinterReady(); 299 | printerInit(); 300 | 301 | SWITCH_ROM(BANK(font)); 302 | 303 | for (index = 0; index < 360; index++) { 304 | printTileData(&font[(imageInfo[index] - 32) * 16], 9, 0x00, PALETTE_INVERTED, EXPOSURE_DARK); 305 | } 306 | 307 | 308 | waitPrinterReady(); 309 | printerInit(); 310 | 311 | SWITCH_ROM(BANK(frame_pxlr)); 312 | 313 | for (index = 320; index < 360; index++) { 314 | printTileData(&frame_pxlr_tiles[frame_pxlr_map[index] * 16], 1, 0x03, PALETTE_INVERTED, EXPOSURE_DEFAULT); 315 | } 316 | 317 | SWITCH_ROM(save); 318 | } 319 | -------------------------------------------------------------------------------- /src/remote.c: -------------------------------------------------------------------------------- 1 | #pragma bank 255 2 | 3 | #include "remote.h" 4 | 5 | #define WATCHDOG_DELAY 2 6 | 7 | volatile uint8_t remote_keys; 8 | volatile uint8_t remote_watchdog; 9 | 10 | inline void SIO_request_transfer() { 11 | SC_REG = 0x80; // start transfer with external clock 12 | } 13 | inline void SIO_cancel_transfer() { 14 | SC_REG = 0x00; // reset transfer request 15 | } 16 | 17 | void isr_remote_SIO() NONBANKED NAKED { 18 | __asm 19 | ld hl, #_remote_keys 20 | ldh a, (_SB_REG) ; 0bS0IPXXXX S-stop, I-identifier, P-parity, XXXX - 4 button bits 21 | ld e, a 22 | 23 | and #0xC0 24 | cp #0x80 25 | jr nz, 1$ ; check bit 7 is 1 and bit 6 is 0 26 | 27 | ld a, e 28 | ld d, #0 29 | xor a 30 | .rept 4 31 | rrc e 32 | adc d 33 | .endm 34 | xor e 35 | and #1 36 | jr nz, 1$ ; check parity bit (result must be 0 when parity matches) 37 | 38 | bit 1, e 39 | jr nz, 2$ 40 | 41 | ld a, #0xf0 42 | and e 43 | swap a 44 | ld e, a 45 | ld a, #0xf0 46 | jr 3$ 47 | 2$: 48 | ld a, #0xf0 49 | and e 50 | ld e, a 51 | ld a, #0x0f 52 | 3$: 53 | and (hl) 54 | or e 55 | ld (hl), a 56 | 57 | ld a, #0x80 58 | ldh (_SC_REG), a ; initialize next transfer 59 | ret 60 | 1$: 61 | xor a 62 | ld (hl), a 63 | ld (_remote_watchdog), a 64 | 65 | ret 66 | __endasm; 67 | } 68 | 69 | void isr_remote_VBL() NONBANKED { 70 | if (remote_watchdog < WATCHDOG_DELAY) { 71 | if ((++remote_watchdog) == WATCHDOG_DELAY) { 72 | SIO_cancel_transfer(); 73 | SIO_request_transfer(); 74 | } 75 | } 76 | } 77 | 78 | void remote_init() BANKED { 79 | CRITICAL { 80 | // reinstall SIO handler (receive data) 81 | remove_SIO(isr_remote_SIO); 82 | add_SIO(isr_remote_SIO); 83 | 84 | // reinstall VBL handler (watchdog) 85 | remove_VBL(isr_remote_VBL); 86 | add_VBL(isr_remote_VBL); 87 | 88 | remote_watchdog = 0; 89 | remote_keys = 0; 90 | } 91 | } 92 | 93 | uint8_t remote_activate(uint8_t value) BANKED { 94 | if (value) { 95 | set_interrupts(IE_REG | SIO_IFLAG); 96 | SIO_cancel_transfer(); 97 | SIO_request_transfer(); 98 | } else { 99 | set_interrupts(IE_REG & ~SIO_IFLAG); 100 | SIO_cancel_transfer(); 101 | } 102 | remote_keys = 0; 103 | return value; 104 | } 105 | -------------------------------------------------------------------------------- /src/saveImage.c: -------------------------------------------------------------------------------- 1 | #pragma bank 255 2 | 3 | #include 4 | #include 5 | #include 6 | #include "tiles.h" 7 | #include "imageIndexing.h" 8 | #include "defines.h" 9 | #include "globals.h" 10 | #include "utils.h" 11 | #include "joypad.h" 12 | #include "dialog.h" 13 | #include "images.h" 14 | #include "values.h" 15 | #include "modeShootingManual.h" 16 | #include "images.h" 17 | 18 | void saveImage(uint8_t capt, uint8_t edExOpGain, uint16_t expTime, uint8_t edRInvVref, uint8_t zeroVout, uint8_t ditherSet, uint8_t contrast) BANKED { 19 | uint8_t firstFreeSlot = findFirstFreeSlot(); 20 | 21 | if (firstFreeSlot >= NUM_IMAGES) { 22 | return; 23 | } 24 | 25 | sortImages(); 26 | 27 | SWITCH_RAM(images[firstFreeSlot]->bank); 28 | get_data(images[firstFreeSlot]->tilesUpper, VRAM_9000, HALF_IMAGE_SIZE); 29 | get_data(images[firstFreeSlot]->tilesLower, VRAM_8000, HALF_IMAGE_SIZE); 30 | 31 | // ToDo: 32 | // This crashes if this .c file is in a #pragma bank 2 33 | memcpy(images[firstFreeSlot]->thumbnail, tiles_thumbnail, 256); 34 | 35 | images[firstFreeSlot]->thumbnail[THUMBNAIL_BYTE_CAPTURE] = capt; 36 | images[firstFreeSlot]->thumbnail[THUMBNAIL_BYTE_EDGEGAINS] = edExOpGain; 37 | images[firstFreeSlot]->thumbnail[THUMBNAIL_BYTE_EXPOSURE_HIGH] = (uint8_t)(expTime >> 8); 38 | images[firstFreeSlot]->thumbnail[THUMBNAIL_BYTE_EXPOSURE_LOW] = (uint8_t)expTime; 39 | images[firstFreeSlot]->thumbnail[THUMBNAIL_BYTE_EDMOVOLT] = edRInvVref; 40 | images[firstFreeSlot]->thumbnail[THUMBNAIL_BYTE_VOUTZERO] = zeroVout; 41 | // ToDo: Add dither and contrasts to save options 42 | images[firstFreeSlot]->thumbnail[THUMBNAIL_BYTE_DITHERSET] = ditherSet; 43 | images[firstFreeSlot]->thumbnail[THUMBNAIL_BYTE_CONTRAST] = contrast; 44 | 45 | setImageSlot(firstFreeSlot, numVisibleImages); 46 | 47 | sortImages(); 48 | if (mainLoopState == MAIN_LOOP_SHOOT_MANUAL) { 49 | renderManualMenu(); 50 | } else { 51 | clonk(); 52 | } 53 | } 54 | 55 | void saveImageDialog(uint8_t capt, uint8_t edExOpGain, uint16_t expTime, uint8_t edRInvVref, uint8_t zeroVout, uint8_t ditherSet, uint8_t contrast) BANKED { 56 | if (findFirstFreeSlot() >= NUM_IMAGES) { 57 | boop(); 58 | waitRelease(); 59 | return; 60 | } 61 | 62 | if (dialog("Save Image? ", 1)) { 63 | saveImage(capt, edExOpGain, expTime, edRInvVref, zeroVout, ditherSet, contrast); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/sm83/flasher_s.s: -------------------------------------------------------------------------------- 1 | .include "global.s" 2 | 3 | .globl .start_save 4 | .globl __current_bank 5 | 6 | .area _INITIALIZED 7 | _save_rom_bank:: 8 | .ds 1 9 | _save_sram_bank_offset:: 10 | .ds 1 11 | 12 | .area _INITIALIZER 13 | .db .start_save 14 | .db 0 15 | 16 | .area _CODE 17 | 18 | .macro .wb addr, val 19 | ld a, val 20 | ld (addr), a 21 | .endm 22 | 23 | _flash_data_routine: 24 | push bc 25 | 26 | di 27 | 28 | ldh a, (#__current_bank) 29 | push af ; save current bank 30 | 31 | lda hl, 6(sp) 32 | ld a, (hl) 33 | 34 | ld c, a ; c == SRAM bank 35 | 36 | ld hl, #_save_rom_bank 37 | srl a 38 | add (hl) 39 | ld (#rROMB0), a ; switch ROM bank 40 | 41 | ld h, #0x40 ; two SRAM banks are saved into one ROM bank. 42 | bit 0, c 43 | jr z,0$ 44 | set 5, h 45 | 0$: 46 | xor a 47 | ld l, a ; destination HL == 0x4000 or HL == 0x6000 48 | 49 | ld d, #0xA0 ; source DE == 0xA000 50 | ld e, a 51 | 52 | 1$: 53 | .wb #rRAMG, #0x0A ; enable SRAM 54 | 55 | ld a, (_save_sram_bank_offset) 56 | add c 57 | ldh (#rRAMB), a ; switch SRAM 58 | 59 | ld a, (de) ; read byte 60 | ld b, a 61 | 62 | .wb #rRAMG, #0x00 ; disable SRAM 63 | 64 | .wb #0x0555, #0xAA 65 | .wb #0x02AA, #0x55 66 | .wb #0x0555, #0xA0 ; perform magic 67 | 68 | ld a, b 69 | ld (hl), a ; write byte 70 | 71 | ld b, #0 ; wait counter 72 | 2$: 73 | cp (hl) 74 | jr z, 3$ ; check byte 75 | 76 | push hl 77 | pop hl 78 | push hl 79 | pop hl ; delay 4+3+4+3=14 80 | 81 | dec b 82 | jr nz, 2$ 83 | 84 | ld e, #0 ; fail 85 | jr 5$ 86 | 3$: 87 | inc de ; next source 88 | inc hl ; next destination 89 | 90 | ld a, #0xc0 ; until de == 0xc000 91 | cp d 92 | jr nz, 1$ 93 | 94 | ld e, #1 ; success 95 | 5$: 96 | .wb #0x4000, #0xF0 ; reset? 97 | 98 | .wb #rRAMG, #0x0A ; enable SRAM back 99 | 100 | pop af 101 | ld (#rROMB0), a ; restore bank 102 | 103 | ei 104 | 105 | pop bc 106 | ret 107 | 108 | _end_flash_data_routine: 109 | 110 | _save_sram_banks:: 111 | lda hl, 2(sp) 112 | ld b, (hl) 113 | 114 | lda hl, 0(sp) 115 | ld d, h 116 | ld e, l ; de = sp 117 | 118 | ld hl, #(_flash_data_routine - _end_flash_data_routine) 119 | add hl, sp 120 | ld sp, hl ; allocate ram on stack for the routine 121 | push de 122 | 123 | push hl ; save routine address 124 | 125 | ld c, #(_end_flash_data_routine - _flash_data_routine) 126 | ld de, #_flash_data_routine 127 | rst 0x30 ; copy up to 256 bytes in C from DE to HL 128 | 129 | ld a, b 130 | pop bc ; restore routine address into bc 131 | 132 | ld e, #0 ; result 133 | sub #1 134 | jr c, 3$ ; copy zero banks? 135 | and #7 ; max 8 banks 136 | 1$: 137 | push af 138 | 139 | ld h, b 140 | ld l, c 141 | inc sp 142 | rst 0x20 ; call routine, bc is preserved 143 | dec sp 144 | 145 | ld a, e 146 | or a 147 | jr z, 2$ 148 | 149 | pop af 150 | sub #1 151 | jr nc, 1$ 152 | 153 | push af 154 | 2$: 155 | pop af 156 | 3$: 157 | 158 | pop hl 159 | ld sp, hl 160 | 161 | ret 162 | 163 | _erase_flash_sector_routine: 164 | di 165 | 166 | ldh a, (#__current_bank) 167 | push af ; save current bank 168 | 169 | .wb #rRAMG, #0x00 ; disable SRAM 170 | 171 | .wb #rROMB0, (#_save_rom_bank) 172 | 173 | .wb #0x4000, #0xF0 ; reset 174 | 175 | .wb #0x0555, #0xAA 176 | .wb #0x02AA, #0x55 177 | .wb #0x0555, #0x80 178 | .wb #0x0555, #0xAA 179 | .wb #0x02AA, #0x55 180 | .wb #0x4000, #0x30 ; perform magic 181 | 182 | ld de, #0 ; wait counter 183 | 1$: 184 | ld a, (#0x4000) 185 | cp #0xFF 186 | jr z, 2$ ; check byte 187 | 188 | push hl 189 | pop hl 190 | push hl 191 | pop hl ; delay 4+3+4+3=14 192 | 193 | dec e 194 | jr nz, 1$ 195 | dec d 196 | jr nz, 1$ 197 | 198 | ld e, #0 ; fail 199 | jr 3$ 200 | 2$: 201 | ld e, #1 ; success 202 | 3$: 203 | .wb #rRAMG, #0x0A ; enable SRAM back 204 | 205 | pop af 206 | ld (#rROMB0), a ; restore bank 207 | 208 | ei 209 | 210 | ret 211 | _end_erase_flash_sector_routine: 212 | 213 | _erase_flash:: 214 | lda hl, 0(sp) 215 | ld d, h 216 | ld e, l ; de = sp 217 | 218 | ld hl, #(_erase_flash_sector_routine - _end_erase_flash_sector_routine) 219 | add hl, sp 220 | ld sp, hl ; allocate ram on stack for the routine 221 | 222 | push de 223 | push hl 224 | 225 | ld c, #(_end_erase_flash_sector_routine - _erase_flash_sector_routine) 226 | ld de, #_erase_flash_sector_routine 227 | rst 0x30 ; copy up to 256 bytes in C from DE to HL 228 | 229 | pop hl 230 | rst 0x20 ; call routine on stack using call hl 231 | 232 | pop hl 233 | ld sp, hl 234 | 235 | ret 236 | -------------------------------------------------------------------------------- /src/splash.c: -------------------------------------------------------------------------------- 1 | #pragma bank 255 2 | 3 | #include 4 | #include 5 | 6 | #include "joypad.h" 7 | #include "bankedData.h" 8 | #include "defines.h" 9 | #include "utils.h" 10 | #include "logo.h" 11 | 12 | #define Q(x) #x 13 | #define QUOTE(x) Q(x) 14 | 15 | static const uint8_t branch[] = QUOTE(BRANCH); 16 | static const uint8_t version[] = QUOTE(VERSION); 17 | 18 | 19 | uint8_t splash() BANKED { 20 | HIDE_SPRITES; 21 | BGP_REG = PALETTE_BLANK; 22 | 23 | set_data_banked(VRAM_9000, logo_tiles, logo_TILE_COUNT * 16, BANK(logo)); 24 | set_data_banked(VRAM_8000, logo_tiles, logo_TILE_COUNT * 16, BANK(logo)); 25 | 26 | set_bkg_tiles_banked(0, 0, 20, 18, logo_map, 1); 27 | 28 | set_bkg_based_tiles(0, 16, sizeof(branch) - 1, 1, branch, OFFSET_FONT - 32); 29 | set_bkg_based_tiles(0, 17, sizeof(version) - 1, 1, version, OFFSET_FONT - 32); 30 | set_bkg_based_tiles(13, 16, 7, 2, "Shoot A Menu B", OFFSET_FONT - 32); 31 | 32 | fadeIn(); 33 | 34 | while (jp != J_A && jp != J_B) { 35 | wait_vbl_done(); 36 | } 37 | 38 | uint8_t result = jp; 39 | 40 | waitRelease(); // waitRelease() resets `jp` 41 | 42 | fadeOut(); 43 | pause(15); 44 | SHOW_SPRITES; 45 | 46 | return result; 47 | } 48 | -------------------------------------------------------------------------------- /src/systemdetect.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "systemdetect.h" 5 | 6 | uint8_t _is_SUPER, _is_COLOR, _is_ADVANCE; 7 | 8 | void detect_system() { 9 | #if defined(NINTENDO) 10 | _is_SUPER = sgb_check(); 11 | _is_COLOR = ((!_is_SUPER) && (_cpu == CGB_TYPE) && (*(uint8_t *)0x0143 & 0x80)); 12 | _is_ADVANCE = (_is_GBA && _is_COLOR); 13 | #elif defined(SEGA) 14 | _is_SUPER = FALSE; 15 | _is_COLOR = TRUE; 16 | _is_ADVANCE = FALSE; 17 | #endif 18 | } -------------------------------------------------------------------------------- /src/utils.c: -------------------------------------------------------------------------------- 1 | #pragma bank 255 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "defines.h" 8 | #include "font.h" 9 | #include "tiles.h" 10 | #include "bankedData.h" 11 | 12 | #define EXPOSURE_MICROS_STEP 4096 13 | #define EXPOSURE_NANOS_STEP 16 14 | 15 | void clearBkg() BANKED { 16 | fill_bkg_rect(0, 0, 20, 18, OFFSET_BLANK); 17 | } 18 | 19 | void initGfx() BANKED { 20 | SHOW_BKG; 21 | BGP_REG = PALETTE_NORMAL; 22 | 23 | OBP0_REG = PALETTE_SPRITES; 24 | OBP1_REG = PALETTE_SPRITES_OVERLAYS; 25 | SHOW_SPRITES; 26 | SPRITES_8x8; 27 | 28 | SHOW_WIN; 29 | move_win(7, 146); 30 | 31 | set_sprite_tile(SPRITE_MENU_INDICATOR, OFFSET_MENU_ARROW); 32 | set_sprite_tile(SPRITE_BLEEP_CURSOR, OFFSET_BLEEP_CURSOR); 33 | 34 | clearBkg(); 35 | set_bkg_data_banked(OFFSET_FONT, NUM_FONT_CHARS, font, 1); 36 | set_bkg_data_banked(OFFSET_TILES, NUM_CONSTANT_TILES, constantTiles, 1); 37 | set_data((uint8_t *)0x9700, upperLowerDoubleTiles, 256); 38 | set_data((uint8_t *)0x8700, upperLowerDoubleTiles, 256); 39 | } 40 | 41 | void initSound() BANKED { 42 | // This enables sound, registers must be in this specific order! 43 | NR52_REG = 0x80; 44 | NR50_REG = 0x77; 45 | NR51_REG = 0xFF; 46 | } 47 | 48 | void beep() BANKED { 49 | NR21_REG=0x80; 50 | NR22_REG=0xA2; 51 | NR23_REG=0x60; 52 | NR24_REG=0x87; 53 | } 54 | 55 | void boop() BANKED { 56 | NR21_REG=0x80; 57 | NR22_REG=0xA2; 58 | NR23_REG=0xD7; 59 | NR24_REG=0x86; 60 | } 61 | 62 | void clonk() BANKED { 63 | NR41_REG=0x01; 64 | NR42_REG=0xC1; 65 | NR43_REG=0x70; 66 | NR44_REG=0xC0; 67 | } 68 | 69 | void pause(uint8_t frames) BANKED { 70 | for (uint8_t i = 0; i < frames; i++) { 71 | wait_vbl_done(); 72 | } 73 | } 74 | 75 | uint8_t digits_map[10]; 76 | void writeNumber(uint8_t x, uint8_t y, uint8_t length, uint8_t number) BANKED { 77 | BCD bcd = MAKE_BCD(0); 78 | uint2bcd(number, &bcd); 79 | bcd2text(&bcd, OFFSET_FONT + 16u, digits_map); 80 | 81 | uint8_t digits[3] = { 0x80, 0x80 , 0x80, }; 82 | 83 | if (length == 1) { 84 | digits[0] = digits_map[7]; 85 | set_bkg_tiles(x + 2, y, 1, 1, digits); 86 | return; 87 | } 88 | 89 | if (length == 2) { 90 | digits[1] = digits_map[7]; 91 | 92 | if (number > 9) { 93 | digits[0] = digits_map[6]; 94 | } 95 | 96 | set_bkg_tiles(x + 1, y, 2, 1, digits); 97 | return; 98 | } 99 | 100 | if (length == 3) { 101 | digits[2] = digits_map[7]; 102 | 103 | if (number > 9) { 104 | digits[1] = digits_map[6]; 105 | } 106 | 107 | if (number > 99) { 108 | digits[0] = digits_map[5]; 109 | } 110 | 111 | set_bkg_tiles(x, y, 3, 1, digits); 112 | return; 113 | } 114 | } 115 | 116 | // ToDo: add a "reason" for calling "dead" 117 | void dead(/*uint8_t reason*/) BANKED { 118 | while (1) { 119 | boop(); 120 | for(uint8_t i = 0; i < 120; i++) { 121 | wait_vbl_done(); 122 | } 123 | } 124 | } 125 | 126 | const uint8_t hexCharLUT[] = "0123456789ABCDEF"; 127 | 128 | void hexChar(uint8_t *target, uint8_t value) BANKED { 129 | target[0] = hexCharLUT[(value >> 4) & 0b00001111]; 130 | target[1] = hexCharLUT[value & 0b00001111]; 131 | } 132 | 133 | void fadeIn() BANKED { 134 | pause(8); 135 | BGP_REG = PALETTE_FADE_2; 136 | pause(8); 137 | BGP_REG = PALETTE_FADE_1; 138 | pause(8); 139 | BGP_REG = PALETTE_NORMAL; 140 | } 141 | 142 | void fadeOut() BANKED { 143 | pause(8); 144 | BGP_REG = PALETTE_FADE_1; 145 | pause(8); 146 | BGP_REG = PALETTE_FADE_2; 147 | pause(8); 148 | BGP_REG = PALETTE_BLANK; 149 | } 150 | 151 | void describeExposureTime(uint16_t exposureTime, uint8_t *target) BANKED { 152 | BCD bcd = MAKE_BCD(0); 153 | uint8_t str[10]; 154 | 155 | uint32_t lower = (exposureTime >> 8) & 0xff; 156 | uint32_t upper = exposureTime & 0xff; 157 | 158 | uint32_t micros = upper * EXPOSURE_MICROS_STEP + lower * EXPOSURE_NANOS_STEP; 159 | 160 | uint16_t numericValue = micros / 1000; 161 | 162 | uint8_t decimals = 0; 163 | 164 | if (numericValue < 10) { 165 | numericValue = micros / 10; 166 | decimals = 2; 167 | } else if (numericValue < 100) { 168 | numericValue = micros / 100; 169 | decimals = 1; 170 | } 171 | 172 | uint2bcd(numericValue, &bcd); 173 | bcd2text(&bcd, 48u, str); 174 | memcpy(target, &str[4], 4); 175 | 176 | if (decimals == 1) { 177 | target[0] = str[5]; 178 | target[1] = str[6]; 179 | target[2] = '.'; 180 | target[3] = str[7]; 181 | } else if (decimals == 2) { 182 | target[0] = str[5]; 183 | target[1] = '.'; 184 | target[2] = str[6]; 185 | target[3] = str[7]; 186 | } else { 187 | for (uint8_t i = 0; i < 3; i++) { 188 | if (target[i] != '0') { 189 | return; 190 | } 191 | target[i] = ' '; 192 | } 193 | } 194 | 195 | } 196 | -------------------------------------------------------------------------------- /temp/gbdk-2020-Linux-x64.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HerrZatacke/2bit-pxlr-studio/77f579f5583927c10b787994f7ca01e389dd1660/temp/gbdk-2020-Linux-x64.tar.gz -------------------------------------------------------------------------------- /utils/dump2vgm.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import sys 3 | from struct import pack 4 | 5 | from pathlib import Path 6 | from optparse import OptionParser 7 | 8 | def create_vgm(filename): 9 | outfile = open(filename, "wb") 10 | outfile.write(pack('IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 0x206D6756, 0, 0x161, 0,0,0,0,0,0,0,0,0,0,0xc0-0x34,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x400000,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)) 11 | return outfile 12 | 13 | def finalize_vgm(outfile, cut): 14 | if (cut): 15 | outfile.write(b'\x62') 16 | outfile.write(pack('BBBBBBBBBBBB', 0xb3, 0xff12 - 0xff10, 0x00, 0xb3, 0xff17 - 0xff10, 0x00, 0xb3, 0xff1c - 0xff10, 0x00, 0xb3, 0xff21 - 0xff10, 0x00)) 17 | outfile.write(pack('BBBBBBBBB', 0xb3, 0xff14 - 0xff10, 0xc0, 0xb3, 0xff19 - 0xff10, 0xc0, 0xb3, 0xff23 - 0xff10, 0xc0)) 18 | outfile.write(b'\x66') 19 | 20 | def main(argv=None): 21 | parser = OptionParser("Usage: dump2vgm.py [options] INPUT_FILE_NAME.TXT") 22 | 23 | parser.add_option("-c", "--cut", dest="cut_sound", action="store_true", default=False, help='cut all sound channels') 24 | 25 | (options, args) = parser.parse_args() 26 | 27 | if (len(args) == 0): 28 | parser.print_help() 29 | parser.error("Input file name required\n") 30 | 31 | infilename = Path(args[0]) 32 | 33 | outfilename = infilename.with_suffix('.c') 34 | 35 | line = "" 36 | song_no = 0; 37 | outfile = None 38 | reset = True 39 | 40 | with open(str(infilename), 'r') as f: 41 | line = f.readline() 42 | while (line): 43 | decoded_line = [x.strip() for x in line.split()] 44 | if len(decoded_line) == 0: 45 | if (outfile): 46 | finalize_vgm(outfile, options.cut_sound) 47 | outfile = None 48 | song_no += 1 49 | print(song_no) 50 | elif len(decoded_line) == 2: 51 | if (decoded_line[0] == "subsong"): 52 | pass; 53 | else: 54 | if (not outfile): 55 | outfile = create_vgm(str(infilename.with_suffix('')) + ".{}.vgm".format(song_no)) 56 | reset = True 57 | reg, value = [int(x.strip(), base = 16) for x in decoded_line[1].split(sep = '=')] 58 | 59 | if (reg in range(0xFF10, 0xFF16) or reg in range(0xFF16, 0xFF20) or 60 | reg in range(0xFF1A, 0xFF1F) or reg in range(0xFF20, 0xFF24) or 61 | reg in range(0xFF24, 0xFF27) or reg in range(0xFF30, 0xFF40)): 62 | delay = round(int(decoded_line[0], base=16) / 70224) 63 | if (not reset) and (delay > 0): 64 | for i in range(0, delay): 65 | outfile.write(b'\x62') 66 | outfile.write(pack('BBB', 0xb3, reg - 0xFF10, value)) 67 | else: 68 | print("Skipped: 0x{:04x}".format(reg)) 69 | 70 | reset = False 71 | 72 | line = f.readline() 73 | 74 | if (outfile): 75 | finalize_vgm(outfile, options.cut_sound) 76 | outfile = None 77 | 78 | return 79 | 80 | if __name__=='__main__': 81 | main() -------------------------------------------------------------------------------- /utils/fxhammer2data.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import sys 3 | from pathlib import Path 4 | from optparse import OptionParser 5 | 6 | note_freqs = [ 7 | 44 ,156 ,262 ,363 ,457 ,547 ,631 ,710 ,786 ,854 ,923 ,986 , 8 | 1046,1102,1155,1205,1253,1297,1339,1379,1417,1452,1486,1517, 9 | 1546,1575,1602,1627,1650,1673,1694,1714,1732,1750,1767,1783, 10 | 1798,1812,1825,1837,1849,1860,1871,1881,1890,1899,1907,1915, 11 | 1923,1930,1936,1943,1949,1954,1959,1964,1969,1974,1978,1982, 12 | 1985,1988,1992,1995,1998,2001,2004,2006,2009,2011,2013,2015 13 | ] 14 | 15 | def make_frame(ch, a, b, c, d, cache): 16 | mask = 0b01001000 | ch 17 | result = ",0x{:02x}".format(a) 18 | if b != cache[0]: 19 | mask |= 0b00100000 20 | result = "{:s},0x{:02x}".format(result, b) 21 | cache[0] = b 22 | if c != cache[1]: 23 | mask |= 0b00010000 24 | result = "{:s},0x{:02x}".format(result, c) 25 | cache[1] = c 26 | return "0b{:08b}{:s},0x{:02x}".format(mask, result, d) 27 | 28 | def write_effect_data(cfile, hfile, identifier, ch, data, options): 29 | global note_freqs 30 | 31 | if len(data) != 256: 32 | print("ERROR: Unexpected end of file") 33 | sys.exit(1) 34 | 35 | ch_mask = (0x02 if (ch & 0xf0) else 0) | (0x08 if (ch & 0x0f) else 0) 36 | 37 | cfile.write(bytes(("BANKREF({0:s})\n" 38 | "const uint8_t {0:s}[] = {{\n").format(identifier), "ascii")) 39 | 40 | ch2_cache = [-1,-1] 41 | ch4_cache = [-1,-1] 42 | old_pan = 0xff 43 | 44 | for i in range(0, 32): 45 | duration, ch2pan, ch2vol, ch2duty, ch2note, ch4pan, ch4vol, ch4freq = data[i * 8:(i + 1) * 8] 46 | 47 | if duration == 0: 48 | break; 49 | 50 | result = "" 51 | count = 0 52 | 53 | if options.use_pan: 54 | current_pan = 0b01010101 | ch2pan | ch4pan 55 | if (old_pan != current_pan): 56 | count += 1 57 | result = "{:s},0b{:08b},0x{:02x}".format(result, 0b01000100, current_pan) 58 | old_pan = current_pan 59 | 60 | if (ch2pan != 0): 61 | count += 1 62 | freq = note_freqs[(ch2note - 0x40) >> 1] 63 | if options.optimize: 64 | result = "{:s},{:s}".format(result, make_frame(1, ch2duty, ch2vol, freq & 0xff, ((freq >> 8) | 0x80) & 0xff, ch2_cache)) 65 | else: 66 | result = "{:s},0b{:08b},0x{:02x},0x{:02x},0x{:02x},0x{:02x}".format( 67 | result, 0b01111001, ch2duty, ch2vol, freq & 0xff, ((freq >> 8) | 0x80) & 0xff 68 | ) 69 | 70 | if (ch4pan != 0): 71 | count += 1 72 | if options.optimize: 73 | result = "{:s},{:s}".format(result, make_frame(3, 0x2a, ch4vol, ch4freq, 0x80, ch4_cache)) 74 | else: 75 | result = "{:s},0b{:08b},0x{:02x},0x{:02x},0x{:02x},0x{:02x}".format( 76 | result, 0b01111011, 0x2a, ch4vol, ch4freq, 0x80 77 | ) 78 | 79 | delay = max(0, (int(options.delay) * duration) - 1) 80 | delta = min(15, delay) 81 | 82 | cfile.write(bytes("0x{:02x}{:s},\n".format(((delta & 0x0f) << 4) | count, result), "ascii")) 83 | 84 | delay -= delta 85 | while (delay > 0): 86 | delta = min(15, delay) 87 | cfile.write(bytes("0x{:02x},\n".format((delta & 0x0f) << 4), "ascii")) 88 | delay -= delta; 89 | 90 | count = 1 91 | result = "" 92 | if options.cut_sound: 93 | if (ch_mask & 2): 94 | count += 1 95 | result = "{:s}0b{:08b},0x{:02x},0x{:02x},".format(result, 0b00101001, 0, 0xc0) 96 | 97 | if (ch_mask & 8): 98 | count += 1 99 | result = "{:s}0b{:08b},0x{:02x},0x{:02x},".format(result, 0b00101011, 0, 0xc0) 100 | 101 | if options.use_pan: 102 | count += 1 103 | result = "{:s}0b{:08b},0x{:02x},".format(result, 0b01000100, 0xff) 104 | 105 | cfile.write(bytes("0x{:02x},{:s}0b{:08b}\n}};\n".format(count, result, 7), "ascii")) 106 | cfile.write(bytes("void AT(0b{1:08b}) __mute_mask_{0:s};\n\n".format(identifier, ch_mask), "ascii")) 107 | 108 | hfile.write(bytes(("#define MUTE_MASK_{0:s} 0b{1:08b}\n" 109 | "BANKREF_EXTERN({0:s})\n" 110 | "extern const uint8_t {0:s}[];\n" 111 | "extern void __mute_mask_{0:s};\n\n").format(identifier, ch_mask), "ascii")) 112 | 113 | def main(argv=None): 114 | parser = OptionParser("Usage: fxhammer2data.py [options] INPUT_FILE_NAME.SAV") 115 | parser.add_option("-o", '--out', dest='outfilename', help='output file name') 116 | parser.add_option("-i", '--identifier', dest='identifier', help='source identifier') 117 | parser.add_option("-n", '--number', dest='effectnum', default="all", help='effect number or "all"') 118 | 119 | parser.add_option("-d", "--delay", dest='delay', default=1, help='delay size') 120 | parser.add_option("-b", '--bank', dest='bank', default="255", help='BANK number (default AUTO=255)') 121 | parser.add_option("-c", "--cut", dest="cut_sound", action="store_true", default=False, help='cut all used sound channels at the end') 122 | parser.add_option("-p", "--no-pan", dest="use_pan", action="store_false", default=True, help='disable channel panning') 123 | parser.add_option("-s", "--no-opt", dest="optimize", action="store_false", default=True, help='disable optimization') 124 | 125 | (options, args) = parser.parse_args() 126 | 127 | if (len(args) == 0): 128 | parser.print_help() 129 | parser.error("Input file name required\n") 130 | 131 | infilename = Path(args[0]) 132 | 133 | if options.outfilename == None: 134 | outfilename = infilename.with_suffix('.c') 135 | else: 136 | outfilename = Path(options.outfilename) 137 | 138 | if options.identifier == None: 139 | identifier = str(Path(infilename.name).with_suffix('')) 140 | else: 141 | identifier = options.identifier 142 | 143 | with open(str(infilename), mode="rb") as f: 144 | data = f.read() 145 | 146 | if data[0x09:0x12] != b"FX HAMMER": 147 | print("ERROR: Invalid FX HAMMER file format") 148 | sys.exit(1) 149 | 150 | cfile = open(str(outfilename), "wb") 151 | cfile.write(bytes(("#pragma bank {0:s}\n\n" 152 | "#include \n" 153 | "#include \n\n").format(options.bank), "ascii")) 154 | 155 | hfile = open(str(outfilename.with_suffix('.h')), "wb") 156 | hfile.write(bytes(("#ifndef __{0:s}_INCLUDE__\n" 157 | "#define __{0:s}_INCLUDE__\n\n" 158 | "#include \n" 159 | "#include \n\n").format(identifier), "ascii")) 160 | 161 | if str(options.effectnum).lower() == 'all': 162 | for effectnum in range(0, 0x3C): 163 | channels = data[0x300 + effectnum] 164 | if channels != 0: 165 | write_effect_data(cfile, hfile, 166 | "{:s}_{:02x}".format(identifier, effectnum), 167 | channels, 168 | data[0x400 + effectnum * 256:0x400 + (effectnum + 1) * 256], 169 | options) 170 | else: 171 | effectnum = max(0, int(options.effectnum, 10)) 172 | write_effect_data(cfile, hfile, 173 | identifier, 174 | data[0x300 + effectnum], 175 | data[0x400 + effectnum * 256:0x400 + (effectnum + 1) * 256], 176 | options) 177 | 178 | hfile.write(b"#endif\n") 179 | 180 | cfile.close() 181 | hfile.close() 182 | 183 | if __name__=='__main__': 184 | main() -------------------------------------------------------------------------------- /utils/romusage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import sys 3 | from PIL import Image 4 | 5 | def hexdump(b, w=32): 6 | print("\n".join(b[i:i + w].hex() for i in range(0, len(b), w))) 7 | 8 | def render_to_texels(data, twidth=16): 9 | rowbytes = 16 * twidth 10 | numrows = -(-len(data) // rowbytes) 11 | texels = bytearray() 12 | for i in range(numrows): 13 | rowdata = data[i * rowbytes:i * rowbytes + rowbytes] 14 | if len(rowdata) < rowbytes: 15 | rowdata = rowdata + bytes(rowbytes - len(rowdata)) 16 | plane0 = b''.join(rowdata[i::16] for i in range(0, 16, 2)) 17 | plane1 = b''.join(rowdata[i::16] for i in range(1, 17, 2)) 18 | for p0, p1 in zip(plane0, plane1): 19 | texels.extend( 20 | ((p0 >> x) & 1) | (((p1 >> x) & 1) << 1) 21 | for x in range(7, -1, -1) 22 | ) 23 | im = Image.new('P', (8 * twidth, 8 * numrows)) 24 | im.putdata(texels) 25 | im.putpalette(b'\xC0\xFF\x5F\x80\xBF\x5F\x40\x7F\x5F\x00\x3F\x5F') 26 | return im 27 | 28 | def main(argv=None): 29 | argv = argv or sys.argv 30 | if len(argv) < 2: 31 | print("romusage.py: no filename; try romusage.py --help") 32 | sys.exit(1) 33 | infilename = argv[1] 34 | outfilename = argv[2] if len(argv) > 2 else None 35 | if infilename in ('--help', '-h'): 36 | print("usage: romusage.py ROMNAME [PNGNAME]") 37 | return 38 | with open(infilename, "rb") as infp: 39 | romdata = infp.read() 40 | twidth = 32 41 | tiles = render_to_texels(romdata, twidth) 42 | if outfilename: 43 | tiles.save(outfilename) 44 | else: 45 | tiles.show() 46 | 47 | if __name__=='__main__': 48 | if 'idlelib' in sys.modules: 49 | main(['./romusage.py', '../gb240p.gb']) 50 | else: 51 | main() 52 | -------------------------------------------------------------------------------- /utils/vgm2data.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import sys 3 | from struct import unpack 4 | from pathlib import Path 5 | from optparse import OptionParser 6 | 7 | def main(argv=None): 8 | parser = OptionParser("Usage: vgm2data.py [options] INPUT_FILE_NAME.VGM") 9 | parser.add_option("-o", '--out', dest='outfilename', help='output file name') 10 | parser.add_option("-i", '--identifier', dest='identifier', help='C source identifier') 11 | 12 | parser.add_option("-1", "--no-nr1x", dest="no_nr1x", action="store_true", default=False, help='disable channel 0') 13 | parser.add_option("-2", "--no-nr2x", dest="no_nr2x", action="store_true", default=False, help='disable channel 1') 14 | parser.add_option("-3", "--no-nr3x", dest="no_nr3x", action="store_true", default=False, help='disable channel 2') 15 | parser.add_option("-4", "--no-nr4x", dest="no_nr4x", action="store_true", default=False, help='disable channel 3') 16 | parser.add_option("-5", "--no-nr5x", dest="no_nr5x", action="store_true", default=False, help='disable NR5X manipulation') 17 | parser.add_option("-s", "--no-init", dest="no_init", action="store_true", default=False, help='disable sound init') 18 | parser.add_option("-w", "--no-wave", dest="no_wave", action="store_true", default=False, help='disable waveform loading') 19 | 20 | parser.add_option("-d", "--delay", dest='delay', default=1, help='delay size') 21 | parser.add_option("-b", '--bank', dest='bank', default="255", help='BANK number (default AUTO=255)') 22 | 23 | (options, args) = parser.parse_args() 24 | 25 | if (len(args) == 0): 26 | parser.print_help() 27 | parser.error("Input file name required\n") 28 | 29 | infilename = Path(args[0]) 30 | 31 | if options.outfilename == None: 32 | outfilename = infilename.with_suffix('.c') 33 | else: 34 | outfilename = Path(options.outfilename) 35 | 36 | if options.identifier == None: 37 | identifier = str(Path(infilename.name).with_suffix('')) 38 | else: 39 | identifier = options.identifier 40 | 41 | disabled_channels = set() 42 | if (options.no_nr1x): 43 | disabled_channels.add(0) 44 | print("Channel 1 disabled") 45 | if (options.no_nr2x): 46 | disabled_channels.add(1) 47 | print("Channel 2 disabled") 48 | if (options.no_nr3x): 49 | disabled_channels.add(2) 50 | print("Channel 3 disabled") 51 | if (options.no_nr4x): 52 | disabled_channels.add(3) 53 | print("Channel 4 disabled") 54 | if (options.no_nr5x): 55 | print("NR5x registers disabled") 56 | if (options.no_wave): 57 | print("waveform data update disabled") 58 | 59 | with open(str(infilename), "rb") as inf: 60 | channel_mute_mask = 0 61 | 62 | # check VGM format 63 | if inf.read(4) != b'Vgm ': 64 | print("invalid file format") 65 | sys.exit(1) 66 | inf.seek(0x08) 67 | if (unpack('\n" 83 | "#include \n\n" 84 | "BANKREF({0:s})\n" 85 | "const uint8_t {0:s}[] = {{\n").format(identifier, options.bank), "ascii")) 86 | 87 | row = {} 88 | data = inf.read(1) 89 | while (data): 90 | if data == b'\x66': 91 | outf.write(bytes("1,0b{:08b}\n}};\n".format(7), "ascii")) 92 | break; 93 | elif data == b'\xb3': 94 | addr, data = unpack('BB', inf.read(2)) 95 | addr += 0x10 96 | if addr in range(0x10, 0x16): 97 | row.setdefault(0, {})[addr-0x10]=data 98 | elif addr in range(0x16, 0x20): 99 | row.setdefault(1, {})[addr-0x15]=data 100 | elif addr in range(0x1A, 0x1F): 101 | row.setdefault(2, {})[addr-0x1A]=data 102 | elif addr in range(0x20, 0x24): 103 | row.setdefault(3, {})[addr-0x1F]=data 104 | elif addr in range(0x24, 0x27): 105 | row.setdefault(4, {})[addr-0x24]=data 106 | elif addr in range(0x30, 0x40): 107 | row.setdefault(5, {})[addr-0x30]=data 108 | else: 109 | print("ERROR: Invalid register address: 0x{:02x}".format(addr)) 110 | sys.exit(1) 111 | value = data 112 | elif data == b'\x62': 113 | # if (not row.setdefault(0, {}).setdefault(4, None)): 114 | # row.pop(0, None) 115 | # if (not row.setdefault(1, {}).setdefault(4, None)): 116 | # row.pop(1, None) 117 | 118 | result = "" 119 | count = 0 120 | # NR5x regs: 121 | ch = row.pop(4, None) 122 | if (ch) and (not options.no_nr5x): 123 | val = ch.pop(3, -1) 124 | if (val != -1) and (not options.no_init): 125 | count += 1 126 | result = "{}0b{:08b},0x{:02x},".format(result, 0b00100100, val) 127 | mask = 4 128 | tmp = "" 129 | for i in range(0, 2): 130 | val = ch.pop(i, -1) 131 | if (val != -1): 132 | mask |= 1 << (7 - i) 133 | tmp = "{}0x{:02x},".format(tmp, val) 134 | if (mask != 4): 135 | count += 1 136 | result = "{}0b{:08b},{}".format(result, mask, tmp) 137 | 138 | # AUD3WAVE[] 139 | ch = row.pop(5, None) 140 | if (ch) and (not options.no_wave): 141 | mask = 5 142 | tmp = "" 143 | for i in range(0, 16): 144 | val = ch.pop(i, 0) 145 | tmp = "{}0x{:02x},".format(tmp, val) 146 | count += 1 147 | result = "{}0b{:08b},{}".format(result, mask, tmp) 148 | 149 | # NR1x, NR2x, NR3x, NR4x regs: 150 | for j in range(0, 4): 151 | ch = row.pop(j, None) 152 | if (ch) and (not j in disabled_channels): 153 | mask = j 154 | tmp = "" 155 | for i in range(0, 5): 156 | val = ch.pop(i, -1) 157 | if (val != -1): 158 | mask |= 1 << (7 - i) 159 | tmp = "{}0x{:02x},".format(tmp, val) 160 | if (mask != j) and ((mask & 0b00001000) != 0): 161 | count += 1 162 | result = "{}0b{:08b},{}".format(result, mask, tmp) 163 | channel_mute_mask |= (1 << j) 164 | 165 | # optional delay 166 | count |= max(0, int(options.delay) - 1) << 4 167 | 168 | # output result 169 | result = "0x{:02x},{}\n".format(count, result) 170 | outf.write(bytes(result, "ascii")) 171 | 172 | # reset row 173 | row = {} 174 | pass 175 | else: 176 | print("ERROR: unsupported command 0x{:02x}".format(unpack('B', data)[0])) 177 | sys.exit(1) 178 | data = inf.read(1) 179 | 180 | outf.write(bytes("void AT(0b{1:08b}) __mute_mask_{0:s};".format(identifier, channel_mute_mask), "ascii")) 181 | 182 | # output C header file 183 | if outfilename.suffix == ".c": 184 | with open(str(outfilename.with_suffix('.h')), "wb") as hdrf: 185 | hdrf.write(bytes(("#ifndef __{0:s}_INCLUDE__\n" 186 | "#define __{0:s}_INCLUDE__\n\n" 187 | "#include \n" 188 | "#include \n\n" 189 | "#define MUTE_MASK_{0:s} 0b{1:08b}\n\n" 190 | "BANKREF_EXTERN({0:s})\n" 191 | "extern const uint8_t {0:s}[];\n" 192 | "extern void __mute_mask_{0:s};\n\n" 193 | "#endif\n").format(identifier, channel_mute_mask), "ascii")) 194 | 195 | if __name__=='__main__': 196 | main() 197 | -------------------------------------------------------------------------------- /utils/wav2data.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import sys 3 | import wave 4 | from pathlib import Path 5 | from optparse import OptionParser 6 | 7 | def main(argv=None): 8 | parser = OptionParser("Usage: wav2data.py [options] INPUT_FILE_NAME.WAV") 9 | parser.add_option("-o", '--out', dest='outfilename', help='output file name') 10 | parser.add_option("-i", '--identifier', dest='identifier', help='source identifier') 11 | 12 | parser.add_option("-b", '--bank', dest='bank', default="255", help='BANK number (default AUTO=255)') 13 | 14 | (options, args) = parser.parse_args() 15 | 16 | if (len(args) == 0): 17 | parser.print_help() 18 | parser.error("Input file name required\n") 19 | 20 | infilename = Path(args[0]) 21 | 22 | if options.outfilename == None: 23 | outfilename = infilename.with_suffix('.c') 24 | else: 25 | outfilename = Path(options.outfilename) 26 | 27 | if options.identifier == None: 28 | identifier = str(Path(infilename.name).with_suffix('')) 29 | else: 30 | identifier = options.identifier 31 | 32 | sHDR = ("#pragma bank {1:s}\n\n" 33 | "#include \n" 34 | "#include \n\n" 35 | "BANKREF({0:s})\n" 36 | "const uint8_t {0:s}[] = {{\n") 37 | sFOOT = "1,0b{:08b}\n}};\n" 38 | sEMIT = "0x{:x}" 39 | sNEW = ",\n" 40 | sNONEW = "," 41 | 42 | with wave.open(str(infilename), mode="rb") as f: 43 | p = f.getparams() 44 | if (p.nchannels == 1) and (p.sampwidth == 1) and (p.framerate >= 8000) and (p.framerate <= 8192) and (p.comptype == 'NONE'): 45 | data = f.readframes(p.nframes) 46 | c = 0 47 | cnt = 0; 48 | flag = False 49 | 50 | # output C source file 51 | with open(str(outfilename), "wb") as outf: 52 | outf.write(bytes(sHDR.format(identifier, options.bank), "ascii")) 53 | result = "" 54 | for i in range(len(data) - len(data) % 32): 55 | c = ((c << 4) | (data[i] >> 4)) & 0xFF 56 | if flag: 57 | result += sEMIT.format(c) 58 | cnt += 1 59 | if (cnt % 16 == 0): 60 | result = "1,0b00000110,{}{}".format(result, sNEW) 61 | outf.write(bytes(result, "ascii")) 62 | result = "" 63 | else: 64 | result += sNONEW 65 | flag = not flag 66 | outf.write(bytes(sFOOT.format(7), "ascii")) 67 | outf.write(bytes("void AT(0b{1:08b}) __mute_mask_{0:s};".format(identifier, 4),"ascii")) 68 | else: 69 | print("ERROR: Invalid WAV file format") 70 | sys.exit(1) 71 | 72 | # output C header file 73 | if outfilename.suffix == ".c": 74 | with open(str(outfilename.with_suffix('.h')), "wb") as hdrf: 75 | hdrf.write(bytes(("#ifndef __{0:s}_INCLUDE__\n" 76 | "#define __{0:s}_INCLUDE__\n\n" 77 | "#include \n" 78 | "#include \n\n" 79 | "#define MUTE_MASK_{0:s} 0b{1:08b}\n\n" 80 | "BANKREF_EXTERN({0:s})\n" 81 | "extern const uint8_t {0:s}[];\n" 82 | "extern void __mute_mask_{0:s};\n\n" 83 | "#endif\n").format(identifier, 4), "ascii")) 84 | 85 | if __name__=='__main__': 86 | main() -------------------------------------------------------------------------------- /version: -------------------------------------------------------------------------------- 1 | 0.12.1 2 | --------------------------------------------------------------------------------