From 47dffcae855f3c2e0005c60ae3cae990a3504bd1 Mon Sep 17 00:00:00 2001
From: Tim Allen
Date: Wed, 8 Aug 2012 00:08:37 +1000
Subject: [PATCH] Update to v090 release.
byuu says:
Most notably, this release adds Nintendo DS emulation. The Nintendo DS
module was written entirely by Cydrak, so please give him all of the
credit for it. I for one am extremely grateful to be allowed to use his
module in bsnes.
The Nintendo DS emulator's standalone name is dasShiny. You will need
the Nintendo DS firmware, which I cannot provide, in order to use it. It
also cannot (currently?) detect the save type used by NDS games. As
such, manifest.xml files must be created manually for this purpose. The
long-term plan is to create a database of save types for each game.
Also, you will need an analog input device for the touch screen for now
(joypad axes work well.)
There have also been a lot of changes from my end: a unified
manifest.xml format across all systems, major improvements to SPC7110
emulation, enhancements to RTC emulation, MSU1 enhancements, icons in
the file browser list, improvements to SNES coprocessor memory mapping,
cleanups and improvements in the libraries used to build bsnes, etc.
I've also included kaijuu (which allows launching game folders directly
with bsnes) and purify (which allows opening images that are compressed,
have copier headers, and have wrong extensions); both of which are fully
GUI-based.
This release only loads game folders, not files. Use purify to load ROM
files in bsnes.
Note that this will likely be the last release for a long time, and that
I will probably rename the emulator for the next release, due to how
many additional systems it now supports.
---
bsnes/Makefile | 19 +-
bsnes/data/bsnes.Manifest | 0
bsnes/data/bsnes.desktop | 0
bsnes/data/bsnes.ico | Bin
bsnes/data/bsnes.png | Bin
bsnes/data/cheats.xml | 748 +++++++++-
bsnes/data/laevateinn.hpp | 0
bsnes/emulator/emulator.hpp | 2 +-
bsnes/emulator/interface.hpp | 0
bsnes/fc/Makefile | 0
bsnes/fc/apu/apu.cpp | 0
bsnes/fc/apu/apu.hpp | 0
bsnes/fc/apu/dmc.cpp | 0
bsnes/fc/apu/dmc.hpp | 0
bsnes/fc/apu/envelope.cpp | 0
bsnes/fc/apu/envelope.hpp | 0
bsnes/fc/apu/noise.cpp | 0
bsnes/fc/apu/noise.hpp | 0
bsnes/fc/apu/pulse.cpp | 0
bsnes/fc/apu/pulse.hpp | 0
bsnes/fc/apu/serialization.cpp | 0
bsnes/fc/apu/sweep.cpp | 0
bsnes/fc/apu/sweep.hpp | 0
bsnes/fc/apu/triangle.cpp | 0
bsnes/fc/apu/triangle.hpp | 0
bsnes/fc/cartridge/board/bandai-fcg.cpp | 0
bsnes/fc/cartridge/board/board.cpp | 0
bsnes/fc/cartridge/board/board.hpp | 0
bsnes/fc/cartridge/board/konami-vrc1.cpp | 0
bsnes/fc/cartridge/board/konami-vrc2.cpp | 0
bsnes/fc/cartridge/board/konami-vrc3.cpp | 0
bsnes/fc/cartridge/board/konami-vrc4.cpp | 0
bsnes/fc/cartridge/board/konami-vrc6.cpp | 0
bsnes/fc/cartridge/board/konami-vrc7.cpp | 0
bsnes/fc/cartridge/board/nes-axrom.cpp | 0
bsnes/fc/cartridge/board/nes-bnrom.cpp | 0
bsnes/fc/cartridge/board/nes-cnrom.cpp | 0
bsnes/fc/cartridge/board/nes-exrom.cpp | 0
bsnes/fc/cartridge/board/nes-fxrom.cpp | 0
bsnes/fc/cartridge/board/nes-gxrom.cpp | 0
bsnes/fc/cartridge/board/nes-hkrom.cpp | 0
bsnes/fc/cartridge/board/nes-nrom.cpp | 0
bsnes/fc/cartridge/board/nes-pxrom.cpp | 0
bsnes/fc/cartridge/board/nes-sxrom.cpp | 0
bsnes/fc/cartridge/board/nes-txrom.cpp | 0
bsnes/fc/cartridge/board/nes-uxrom.cpp | 0
bsnes/fc/cartridge/board/sunsoft-5b.cpp | 0
bsnes/fc/cartridge/cartridge.cpp | 0
bsnes/fc/cartridge/cartridge.hpp | 0
bsnes/fc/cartridge/chip/chip.cpp | 0
bsnes/fc/cartridge/chip/chip.hpp | 0
bsnes/fc/cartridge/chip/mmc1.cpp | 0
bsnes/fc/cartridge/chip/mmc3.cpp | 0
bsnes/fc/cartridge/chip/mmc5.cpp | 0
bsnes/fc/cartridge/chip/mmc6.cpp | 0
bsnes/fc/cartridge/chip/vrc1.cpp | 0
bsnes/fc/cartridge/chip/vrc2.cpp | 0
bsnes/fc/cartridge/chip/vrc3.cpp | 0
bsnes/fc/cartridge/chip/vrc4.cpp | 0
bsnes/fc/cartridge/chip/vrc6.cpp | 0
bsnes/fc/cartridge/chip/vrc7.cpp | 0
bsnes/fc/cheat/cheat.cpp | 0
bsnes/fc/cheat/cheat.hpp | 0
bsnes/fc/cpu/cpu.cpp | 0
bsnes/fc/cpu/cpu.hpp | 0
bsnes/fc/cpu/serialization.cpp | 0
bsnes/fc/cpu/timing.cpp | 0
bsnes/fc/fc.hpp | 0
bsnes/fc/input/input.cpp | 0
bsnes/fc/input/input.hpp | 0
bsnes/fc/input/serialization.cpp | 0
bsnes/fc/interface/interface.cpp | 0
bsnes/fc/interface/interface.hpp | 0
bsnes/fc/memory/memory.cpp | 0
bsnes/fc/memory/memory.hpp | 0
bsnes/fc/ppu/ppu.cpp | 0
bsnes/fc/ppu/ppu.hpp | 0
bsnes/fc/ppu/serialization.cpp | 0
bsnes/fc/scheduler/scheduler.cpp | 0
bsnes/fc/scheduler/scheduler.hpp | 0
bsnes/fc/system/serialization.cpp | 0
bsnes/fc/system/system.cpp | 0
bsnes/fc/system/system.hpp | 0
bsnes/fc/video/video.cpp | 0
bsnes/fc/video/video.hpp | 0
bsnes/gb/Makefile | 0
bsnes/gb/apu/apu.cpp | 0
bsnes/gb/apu/apu.hpp | 0
bsnes/gb/apu/master/master.cpp | 0
bsnes/gb/apu/master/master.hpp | 0
bsnes/gb/apu/noise/noise.cpp | 0
bsnes/gb/apu/noise/noise.hpp | 0
bsnes/gb/apu/serialization.cpp | 0
bsnes/gb/apu/square1/square1.cpp | 0
bsnes/gb/apu/square1/square1.hpp | 0
bsnes/gb/apu/square2/square2.cpp | 0
bsnes/gb/apu/square2/square2.hpp | 0
bsnes/gb/apu/wave/wave.cpp | 0
bsnes/gb/apu/wave/wave.hpp | 0
bsnes/gb/cartridge/cartridge.cpp | 0
bsnes/gb/cartridge/cartridge.hpp | 0
bsnes/gb/cartridge/huc1/huc1.cpp | 0
bsnes/gb/cartridge/huc1/huc1.hpp | 0
bsnes/gb/cartridge/huc3/huc3.cpp | 0
bsnes/gb/cartridge/huc3/huc3.hpp | 0
bsnes/gb/cartridge/mbc0/mbc0.cpp | 0
bsnes/gb/cartridge/mbc0/mbc0.hpp | 0
bsnes/gb/cartridge/mbc1/mbc1.cpp | 0
bsnes/gb/cartridge/mbc1/mbc1.hpp | 0
bsnes/gb/cartridge/mbc2/mbc2.cpp | 0
bsnes/gb/cartridge/mbc2/mbc2.hpp | 0
bsnes/gb/cartridge/mbc3/mbc3.cpp | 0
bsnes/gb/cartridge/mbc3/mbc3.hpp | 0
bsnes/gb/cartridge/mbc5/mbc5.cpp | 0
bsnes/gb/cartridge/mbc5/mbc5.hpp | 0
bsnes/gb/cartridge/mmm01/mmm01.cpp | 0
bsnes/gb/cartridge/mmm01/mmm01.hpp | 0
bsnes/gb/cartridge/serialization.cpp | 0
bsnes/gb/cheat/cheat.cpp | 0
bsnes/gb/cheat/cheat.hpp | 0
bsnes/gb/cpu/cpu.cpp | 0
bsnes/gb/cpu/cpu.hpp | 0
bsnes/gb/cpu/memory.cpp | 0
bsnes/gb/cpu/mmio.cpp | 0
bsnes/gb/cpu/serialization.cpp | 0
bsnes/gb/cpu/timing.cpp | 0
bsnes/gb/gb.hpp | 0
bsnes/gb/interface/interface.cpp | 0
bsnes/gb/interface/interface.hpp | 0
bsnes/gb/memory/memory.cpp | 0
bsnes/gb/memory/memory.hpp | 0
bsnes/gb/ppu/cgb.cpp | 0
bsnes/gb/ppu/dmg.cpp | 0
bsnes/gb/ppu/mmio.cpp | 0
bsnes/gb/ppu/ppu.cpp | 0
bsnes/gb/ppu/ppu.hpp | 0
bsnes/gb/ppu/serialization.cpp | 0
bsnes/gb/scheduler/scheduler.cpp | 0
bsnes/gb/scheduler/scheduler.hpp | 0
bsnes/gb/system/serialization.cpp | 0
bsnes/gb/system/system.cpp | 0
bsnes/gb/system/system.hpp | 0
bsnes/gb/video/video.cpp | 0
bsnes/gb/video/video.hpp | 0
bsnes/gba/Makefile | 0
bsnes/gba/apu/apu.cpp | 0
bsnes/gba/apu/apu.hpp | 0
bsnes/gba/apu/fifo.cpp | 0
bsnes/gba/apu/mmio.cpp | 0
bsnes/gba/apu/noise.cpp | 0
bsnes/gba/apu/registers.cpp | 0
bsnes/gba/apu/registers.hpp | 0
bsnes/gba/apu/sequencer.cpp | 0
bsnes/gba/apu/serialization.cpp | 0
bsnes/gba/apu/square.cpp | 0
bsnes/gba/apu/square1.cpp | 0
bsnes/gba/apu/square2.cpp | 0
bsnes/gba/apu/wave.cpp | 0
bsnes/gba/cartridge/cartridge.cpp | 0
bsnes/gba/cartridge/cartridge.hpp | 0
bsnes/gba/cartridge/eeprom.cpp | 0
bsnes/gba/cartridge/flashrom.cpp | 0
bsnes/gba/cartridge/memory.hpp | 0
bsnes/gba/cartridge/serialization.cpp | 0
bsnes/gba/cpu/cpu.cpp | 0
bsnes/gba/cpu/cpu.hpp | 0
bsnes/gba/cpu/dma.cpp | 0
bsnes/gba/cpu/memory.cpp | 0
bsnes/gba/cpu/mmio.cpp | 0
bsnes/gba/cpu/registers.cpp | 0
bsnes/gba/cpu/registers.hpp | 0
bsnes/gba/cpu/serialization.cpp | 0
bsnes/gba/cpu/state.hpp | 0
bsnes/gba/cpu/timer.cpp | 0
bsnes/gba/gba.hpp | 0
bsnes/gba/interface/interface.cpp | 0
bsnes/gba/interface/interface.hpp | 0
bsnes/gba/memory/memory.cpp | 0
bsnes/gba/memory/memory.hpp | 0
bsnes/gba/memory/mmio.cpp | 0
bsnes/gba/memory/serialization.cpp | 0
bsnes/gba/ppu/background.cpp | 0
bsnes/gba/ppu/memory.cpp | 0
bsnes/gba/ppu/mmio.cpp | 0
bsnes/gba/ppu/mosaic.cpp | 0
bsnes/gba/ppu/object.cpp | 0
bsnes/gba/ppu/ppu.cpp | 0
bsnes/gba/ppu/ppu.hpp | 0
bsnes/gba/ppu/registers.cpp | 0
bsnes/gba/ppu/registers.hpp | 0
bsnes/gba/ppu/screen.cpp | 0
bsnes/gba/ppu/serialization.cpp | 0
bsnes/gba/ppu/state.hpp | 0
bsnes/gba/scheduler/scheduler.cpp | 0
bsnes/gba/scheduler/scheduler.hpp | 0
bsnes/gba/system/bios.cpp | 0
bsnes/gba/system/serialization.cpp | 0
bsnes/gba/system/system.cpp | 0
bsnes/gba/system/system.hpp | 0
bsnes/gba/video/video.cpp | 0
bsnes/gba/video/video.hpp | 0
bsnes/libco/amd64.c | 0
bsnes/libco/fiber.c | 0
bsnes/libco/libco.c | 0
bsnes/libco/libco.h | 0
bsnes/libco/ppc.c | 0
bsnes/libco/sjlj.c | 0
bsnes/libco/ucontext.c | 0
bsnes/libco/x86.c | 0
bsnes/nall/Makefile | 0
bsnes/nall/algorithm.hpp | 0
bsnes/nall/any.hpp | 0
bsnes/nall/atoi.hpp | 0
bsnes/nall/base64.hpp | 0
bsnes/nall/bit.hpp | 0
bsnes/nall/bmp.hpp | 0
bsnes/nall/bps/delta.hpp | 0
bsnes/nall/bps/linear.hpp | 0
bsnes/nall/bps/metadata.hpp | 0
bsnes/nall/bps/patch.hpp | 0
bsnes/nall/compositor.hpp | 0
bsnes/nall/config.hpp | 0
bsnes/nall/crc32.hpp | 0
bsnes/nall/directory.hpp | 0
bsnes/nall/dl.hpp | 0
bsnes/nall/dsp.hpp | 0
bsnes/nall/dsp/buffer.hpp | 0
bsnes/nall/dsp/core.hpp | 0
bsnes/nall/dsp/resample/average.hpp | 0
bsnes/nall/dsp/resample/cosine.hpp | 0
bsnes/nall/dsp/resample/cubic.hpp | 0
bsnes/nall/dsp/resample/hermite.hpp | 0
bsnes/nall/dsp/resample/lib/sinc.hpp | 0
bsnes/nall/dsp/resample/linear.hpp | 0
bsnes/nall/dsp/resample/nearest.hpp | 0
bsnes/nall/dsp/resample/sinc.hpp | 0
bsnes/nall/dsp/settings.hpp | 0
bsnes/nall/emulation/famicom.hpp | 0
bsnes/nall/emulation/game-boy-advance.hpp | 0
bsnes/nall/emulation/game-boy.hpp | 0
bsnes/nall/emulation/satellaview.hpp | 0
bsnes/nall/emulation/sufami-turbo.hpp | 0
bsnes/nall/emulation/super-famicom-usart.hpp | 0
bsnes/nall/emulation/super-famicom.hpp | 3 +
bsnes/nall/endian.hpp | 0
bsnes/nall/file.hpp | 0
bsnes/nall/filemap.hpp | 0
bsnes/nall/function.hpp | 0
bsnes/nall/gzip.hpp | 0
bsnes/nall/http.hpp | 0
bsnes/nall/image.hpp | 0
bsnes/nall/inflate.hpp | 0
bsnes/nall/input.hpp | 0
bsnes/nall/interpolation.hpp | 0
bsnes/nall/intrinsics.hpp | 0
bsnes/nall/invoke.hpp | 0
bsnes/nall/ips.hpp | 0
bsnes/nall/lzss.hpp | 0
bsnes/nall/map.hpp | 0
bsnes/nall/mosaic.hpp | 0
bsnes/nall/mosaic/bitstream.hpp | 0
bsnes/nall/mosaic/context.hpp | 0
bsnes/nall/mosaic/parser.hpp | 0
bsnes/nall/nall.hpp | 0
bsnes/nall/platform.hpp | 0
bsnes/nall/png.hpp | 0
bsnes/nall/priority-queue.hpp | 0
bsnes/nall/property.hpp | 0
bsnes/nall/public-cast.hpp | 0
bsnes/nall/random.hpp | 0
bsnes/nall/serial.hpp | 0
bsnes/nall/serializer.hpp | 0
bsnes/nall/set.hpp | 0
bsnes/nall/sha256.hpp | 0
bsnes/nall/sort.hpp | 0
bsnes/nall/stdint.hpp | 0
bsnes/nall/stream.hpp | 0
bsnes/nall/stream/auto.hpp | 0
bsnes/nall/stream/file.hpp | 0
bsnes/nall/stream/gzip.hpp | 0
bsnes/nall/stream/http.hpp | 0
bsnes/nall/stream/memory.hpp | 0
bsnes/nall/stream/mmap.hpp | 0
bsnes/nall/stream/stream.hpp | 0
bsnes/nall/stream/vector.hpp | 0
bsnes/nall/stream/zip.hpp | 0
bsnes/nall/string.hpp | 0
bsnes/nall/string/base.hpp | 0
bsnes/nall/string/bml.hpp | 0
bsnes/nall/string/bsv.hpp | 0
bsnes/nall/string/cast.hpp | 0
bsnes/nall/string/compare.hpp | 0
bsnes/nall/string/convert.hpp | 0
bsnes/nall/string/core.hpp | 0
bsnes/nall/string/cstring.hpp | 0
bsnes/nall/string/filename.hpp | 0
bsnes/nall/string/math-fixed-point.hpp | 0
bsnes/nall/string/math-floating-point.hpp | 0
bsnes/nall/string/platform.hpp | 0
bsnes/nall/string/replace.hpp | 0
bsnes/nall/string/split.hpp | 0
bsnes/nall/string/static.hpp | 0
bsnes/nall/string/strm.hpp | 0
bsnes/nall/string/strpos.hpp | 0
bsnes/nall/string/trim.hpp | 0
bsnes/nall/string/utf8.hpp | 0
bsnes/nall/string/utility.hpp | 0
bsnes/nall/string/variadic.hpp | 0
bsnes/nall/string/wildcard.hpp | 0
bsnes/nall/string/wrapper.hpp | 0
bsnes/nall/string/xml-legacy.hpp | 0
bsnes/nall/string/xml.hpp | 0
bsnes/nall/traits.hpp | 0
bsnes/nall/udl.hpp | 0
bsnes/nall/ups.hpp | 0
bsnes/nall/utility.hpp | 0
bsnes/nall/varint.hpp | 0
bsnes/nall/vector.hpp | 0
bsnes/nall/windows/detour.hpp | 0
bsnes/nall/windows/guid.hpp | 0
bsnes/nall/windows/launcher.hpp | 0
bsnes/nall/windows/registry.hpp | 0
bsnes/nall/windows/utf8.hpp | 0
bsnes/nall/xorg/guard.hpp | 0
bsnes/nall/xorg/xorg.hpp | 0
bsnes/nall/zip.hpp | 0
bsnes/nds/Makefile | 16 +
bsnes/nds/apu/apu.cpp | 403 +++++
bsnes/nds/apu/apu.hpp | 100 ++
bsnes/nds/cpu/arm.cpp | 230 +++
bsnes/nds/cpu/arm7tdmi.cpp | 565 +++++++
bsnes/nds/cpu/arm946es.cpp | 697 +++++++++
bsnes/nds/cpu/bit.hpp | 66 +
bsnes/nds/cpu/core.cpp | 214 +++
bsnes/nds/cpu/core.hpp | 135 ++
bsnes/nds/cpu/cpu.cpp | 337 +++++
bsnes/nds/cpu/cpu.hpp | 288 ++++
bsnes/nds/cpu/disasm.cpp | 411 +++++
bsnes/nds/cpu/dma.cpp | 131 ++
bsnes/nds/cpu/math.cpp | 115 ++
bsnes/nds/cpu/message.cpp | 98 ++
bsnes/nds/cpu/slot.cpp | 131 ++
bsnes/nds/cpu/thumb.cpp | 150 ++
bsnes/nds/cpu/timer.cpp | 78 +
bsnes/nds/gpu/commands.cpp | 527 +++++++
bsnes/nds/gpu/commands.hpp | 41 +
bsnes/nds/gpu/geometry.cpp | 316 ++++
bsnes/nds/gpu/geometry.hpp | 83 ++
bsnes/nds/gpu/gpu.cpp | 497 ++++++
bsnes/nds/gpu/gpu.hpp | 77 +
bsnes/nds/gpu/math.cpp | 143 ++
bsnes/nds/gpu/math.hpp | 53 +
bsnes/nds/gpu/render.cpp | 578 +++++++
bsnes/nds/gpu/render.hpp | 163 ++
bsnes/nds/gpu/textures.cpp | 304 ++++
bsnes/nds/interface/interface.cpp | 410 +++++
bsnes/nds/interface/interface.hpp | 91 ++
bsnes/nds/memory/eeprom.cpp | 96 ++
bsnes/nds/memory/eeprom.hpp | 17 +
bsnes/nds/memory/flash.cpp | 137 ++
bsnes/nds/memory/flash.hpp | 20 +
bsnes/nds/memory/fram.cpp | 64 +
bsnes/nds/memory/fram.hpp | 16 +
bsnes/nds/memory/memory.cpp | 127 ++
bsnes/nds/memory/memory.hpp | 76 +
bsnes/nds/nds.hpp | 29 +
bsnes/nds/ppu/bg.cpp | 251 ++++
bsnes/nds/ppu/obj.cpp | 159 ++
bsnes/nds/ppu/ppu.cpp | 414 +++++
bsnes/nds/ppu/ppu.hpp | 148 ++
bsnes/nds/slot1/slot1.cpp | 244 +++
bsnes/nds/slot1/slot1.hpp | 113 ++
bsnes/nds/slot2/slot2.cpp | 0
bsnes/nds/slot2/slot2.hpp | 0
bsnes/nds/system/clock.cpp | 239 +++
bsnes/nds/system/eventqueue.hpp | 120 ++
bsnes/nds/system/powermgr.cpp | 14 +
bsnes/nds/system/system.cpp | 537 +++++++
bsnes/nds/system/system.hpp | 231 +++
bsnes/nds/system/touchscreen.cpp | 112 ++
bsnes/nds/video/video.cpp | 180 +++
bsnes/nds/video/video.hpp | 44 +
bsnes/nds/wifi/wifi.cpp | 488 ++++++
bsnes/nds/wifi/wifi.hpp | 153 ++
bsnes/phoenix/Makefile | 0
bsnes/phoenix/core/core.cpp | 0
bsnes/phoenix/core/core.hpp | 0
bsnes/phoenix/core/keyboard.hpp | 0
bsnes/phoenix/core/layout/fixed-layout.cpp | 0
bsnes/phoenix/core/layout/fixed-layout.hpp | 0
.../phoenix/core/layout/horizontal-layout.cpp | 0
.../phoenix/core/layout/horizontal-layout.hpp | 0
bsnes/phoenix/core/layout/vertical-layout.cpp | 0
bsnes/phoenix/core/layout/vertical-layout.hpp | 0
bsnes/phoenix/core/state.hpp | 0
bsnes/phoenix/gtk/action/action.cpp | 0
bsnes/phoenix/gtk/action/check-item.cpp | 0
bsnes/phoenix/gtk/action/item.cpp | 0
bsnes/phoenix/gtk/action/menu.cpp | 0
bsnes/phoenix/gtk/action/radio-item.cpp | 0
bsnes/phoenix/gtk/action/separator.cpp | 0
bsnes/phoenix/gtk/desktop.cpp | 0
bsnes/phoenix/gtk/dialog-window.cpp | 0
bsnes/phoenix/gtk/font.cpp | 0
bsnes/phoenix/gtk/keyboard.cpp | 0
bsnes/phoenix/gtk/message-window.cpp | 0
bsnes/phoenix/gtk/mouse.cpp | 0
bsnes/phoenix/gtk/platform.cpp | 0
bsnes/phoenix/gtk/platform.hpp | 0
bsnes/phoenix/gtk/settings.cpp | 0
bsnes/phoenix/gtk/timer.cpp | 0
bsnes/phoenix/gtk/utility.cpp | 0
bsnes/phoenix/gtk/widget/button.cpp | 0
bsnes/phoenix/gtk/widget/canvas.cpp | 0
bsnes/phoenix/gtk/widget/check-box.cpp | 0
bsnes/phoenix/gtk/widget/combo-box.cpp | 0
bsnes/phoenix/gtk/widget/hex-edit.cpp | 0
.../gtk/widget/horizontal-scroll-bar.cpp | 0
.../phoenix/gtk/widget/horizontal-slider.cpp | 0
bsnes/phoenix/gtk/widget/label.cpp | 0
bsnes/phoenix/gtk/widget/line-edit.cpp | 0
bsnes/phoenix/gtk/widget/list-view.cpp | 0
bsnes/phoenix/gtk/widget/progress-bar.cpp | 0
bsnes/phoenix/gtk/widget/radio-box.cpp | 0
bsnes/phoenix/gtk/widget/text-edit.cpp | 0
.../gtk/widget/vertical-scroll-bar.cpp | 0
bsnes/phoenix/gtk/widget/vertical-slider.cpp | 0
bsnes/phoenix/gtk/widget/viewport.cpp | 0
bsnes/phoenix/gtk/widget/widget.cpp | 0
bsnes/phoenix/gtk/window.cpp | 0
bsnes/phoenix/phoenix.cpp | 0
bsnes/phoenix/phoenix.hpp | 0
bsnes/phoenix/qt/action/action.cpp | 0
bsnes/phoenix/qt/action/check-item.cpp | 0
bsnes/phoenix/qt/action/item.cpp | 0
bsnes/phoenix/qt/action/menu.cpp | 0
bsnes/phoenix/qt/action/radio-item.cpp | 0
bsnes/phoenix/qt/action/separator.cpp | 0
bsnes/phoenix/qt/desktop.cpp | 0
bsnes/phoenix/qt/dialog-window.cpp | 0
bsnes/phoenix/qt/font.cpp | 0
bsnes/phoenix/qt/keyboard.cpp | 0
bsnes/phoenix/qt/message-window.cpp | 0
bsnes/phoenix/qt/mouse.cpp | 0
bsnes/phoenix/qt/platform.cpp | 0
bsnes/phoenix/qt/platform.moc | 0
bsnes/phoenix/qt/platform.moc.hpp | 0
bsnes/phoenix/qt/settings.cpp | 0
bsnes/phoenix/qt/timer.cpp | 0
bsnes/phoenix/qt/utility.cpp | 0
bsnes/phoenix/qt/widget/button.cpp | 0
bsnes/phoenix/qt/widget/canvas.cpp | 0
bsnes/phoenix/qt/widget/check-box.cpp | 0
bsnes/phoenix/qt/widget/combo-box.cpp | 0
bsnes/phoenix/qt/widget/hex-edit.cpp | 0
.../qt/widget/horizontal-scroll-bar.cpp | 0
bsnes/phoenix/qt/widget/horizontal-slider.cpp | 0
bsnes/phoenix/qt/widget/label.cpp | 0
bsnes/phoenix/qt/widget/line-edit.cpp | 0
bsnes/phoenix/qt/widget/list-view.cpp | 0
bsnes/phoenix/qt/widget/progress-bar.cpp | 0
bsnes/phoenix/qt/widget/radio-box.cpp | 0
bsnes/phoenix/qt/widget/text-edit.cpp | 0
.../phoenix/qt/widget/vertical-scroll-bar.cpp | 0
bsnes/phoenix/qt/widget/vertical-slider.cpp | 0
bsnes/phoenix/qt/widget/viewport.cpp | 0
bsnes/phoenix/qt/widget/widget.cpp | 0
bsnes/phoenix/qt/window.cpp | 0
bsnes/phoenix/reference/action/action.cpp | 0
bsnes/phoenix/reference/action/check-item.cpp | 0
bsnes/phoenix/reference/action/item.cpp | 0
bsnes/phoenix/reference/action/menu.cpp | 0
bsnes/phoenix/reference/action/radio-item.cpp | 0
bsnes/phoenix/reference/action/separator.cpp | 0
bsnes/phoenix/reference/desktop.cpp | 0
bsnes/phoenix/reference/dialog-window.cpp | 0
bsnes/phoenix/reference/font.cpp | 0
bsnes/phoenix/reference/keyboard.cpp | 0
bsnes/phoenix/reference/message-window.cpp | 0
bsnes/phoenix/reference/mouse.cpp | 0
bsnes/phoenix/reference/platform.cpp | 0
bsnes/phoenix/reference/platform.hpp | 0
bsnes/phoenix/reference/timer.cpp | 0
bsnes/phoenix/reference/widget/button.cpp | 0
bsnes/phoenix/reference/widget/canvas.cpp | 0
bsnes/phoenix/reference/widget/check-box.cpp | 0
bsnes/phoenix/reference/widget/combo-box.cpp | 0
bsnes/phoenix/reference/widget/hex-edit.cpp | 0
.../widget/horizontal-scroll-bar.cpp | 0
.../reference/widget/horizontal-slider.cpp | 0
bsnes/phoenix/reference/widget/label.cpp | 0
bsnes/phoenix/reference/widget/line-edit.cpp | 0
bsnes/phoenix/reference/widget/list-view.cpp | 0
.../phoenix/reference/widget/progress-bar.cpp | 0
bsnes/phoenix/reference/widget/radio-box.cpp | 0
bsnes/phoenix/reference/widget/text-edit.cpp | 0
.../reference/widget/vertical-scroll-bar.cpp | 0
.../reference/widget/vertical-slider.cpp | 0
bsnes/phoenix/reference/widget/viewport.cpp | 0
bsnes/phoenix/reference/widget/widget.cpp | 0
bsnes/phoenix/reference/window.cpp | 0
bsnes/phoenix/sync.sh | 0
bsnes/phoenix/windows/action/action.cpp | 0
bsnes/phoenix/windows/action/check-item.cpp | 0
bsnes/phoenix/windows/action/item.cpp | 0
bsnes/phoenix/windows/action/menu.cpp | 0
bsnes/phoenix/windows/action/radio-item.cpp | 0
bsnes/phoenix/windows/action/separator.cpp | 0
bsnes/phoenix/windows/desktop.cpp | 0
bsnes/phoenix/windows/dialog-window.cpp | 0
bsnes/phoenix/windows/font.cpp | 0
bsnes/phoenix/windows/keyboard.cpp | 0
bsnes/phoenix/windows/message-window.cpp | 0
bsnes/phoenix/windows/mouse.cpp | 0
bsnes/phoenix/windows/object.cpp | 0
bsnes/phoenix/windows/phoenix.Manifest | 0
bsnes/phoenix/windows/phoenix.rc | 0
bsnes/phoenix/windows/platform.cpp | 0
bsnes/phoenix/windows/platform.hpp | 0
bsnes/phoenix/windows/settings.cpp | 0
bsnes/phoenix/windows/timer.cpp | 0
bsnes/phoenix/windows/utility.cpp | 0
bsnes/phoenix/windows/widget/button.cpp | 0
bsnes/phoenix/windows/widget/canvas.cpp | 0
bsnes/phoenix/windows/widget/check-box.cpp | 0
bsnes/phoenix/windows/widget/combo-box.cpp | 0
bsnes/phoenix/windows/widget/hex-edit.cpp | 0
.../windows/widget/horizontal-scroll-bar.cpp | 0
.../windows/widget/horizontal-slider.cpp | 0
bsnes/phoenix/windows/widget/label.cpp | 0
bsnes/phoenix/windows/widget/line-edit.cpp | 0
bsnes/phoenix/windows/widget/list-view.cpp | 0
bsnes/phoenix/windows/widget/progress-bar.cpp | 0
bsnes/phoenix/windows/widget/radio-box.cpp | 0
bsnes/phoenix/windows/widget/text-edit.cpp | 0
.../windows/widget/vertical-scroll-bar.cpp | 0
.../windows/widget/vertical-slider.cpp | 0
bsnes/phoenix/windows/widget/viewport.cpp | 0
bsnes/phoenix/windows/widget/widget.cpp | 0
bsnes/phoenix/windows/window.cpp | 0
bsnes/processor/Makefile | 0
bsnes/processor/arm/algorithms.cpp | 0
bsnes/processor/arm/arm.cpp | 0
bsnes/processor/arm/arm.hpp | 0
bsnes/processor/arm/disassembler.cpp | 0
bsnes/processor/arm/disassembler.hpp | 0
bsnes/processor/arm/instructions-arm.cpp | 0
bsnes/processor/arm/instructions-arm.hpp | 0
bsnes/processor/arm/instructions-thumb.cpp | 0
bsnes/processor/arm/instructions-thumb.hpp | 0
bsnes/processor/arm/registers.cpp | 0
bsnes/processor/arm/registers.hpp | 0
bsnes/processor/arm/serialization.cpp | 0
bsnes/processor/gsu/gsu.cpp | 0
bsnes/processor/gsu/gsu.hpp | 0
bsnes/processor/gsu/instructions.cpp | 0
bsnes/processor/gsu/registers.hpp | 0
bsnes/processor/gsu/serialization.cpp | 0
bsnes/processor/gsu/table.cpp | 0
bsnes/processor/hg51b/hg51b.cpp | 0
bsnes/processor/hg51b/hg51b.hpp | 0
bsnes/processor/hg51b/instructions.cpp | 0
bsnes/processor/hg51b/registers.cpp | 0
bsnes/processor/hg51b/registers.hpp | 0
bsnes/processor/hg51b/serialization.cpp | 0
bsnes/processor/lr35902/disassembler.cpp | 0
bsnes/processor/lr35902/instructions.cpp | 0
bsnes/processor/lr35902/lr35902.cpp | 0
bsnes/processor/lr35902/lr35902.hpp | 0
bsnes/processor/lr35902/registers.hpp | 0
bsnes/processor/lr35902/serialization.cpp | 0
bsnes/processor/processor.hpp | 0
bsnes/processor/r6502/disassembler.cpp | 0
bsnes/processor/r6502/instructions.cpp | 0
bsnes/processor/r6502/memory.cpp | 0
bsnes/processor/r6502/r6502.cpp | 0
bsnes/processor/r6502/r6502.hpp | 0
bsnes/processor/r6502/registers.hpp | 0
bsnes/processor/r6502/serialization.cpp | 0
bsnes/processor/r65816/algorithms.cpp | 0
bsnes/processor/r65816/disassembler.cpp | 0
bsnes/processor/r65816/disassembler.hpp | 0
bsnes/processor/r65816/memory.hpp | 0
bsnes/processor/r65816/opcode_misc.cpp | 0
bsnes/processor/r65816/opcode_pc.cpp | 0
bsnes/processor/r65816/opcode_read.cpp | 0
bsnes/processor/r65816/opcode_rmw.cpp | 0
bsnes/processor/r65816/opcode_write.cpp | 0
bsnes/processor/r65816/r65816.cpp | 0
bsnes/processor/r65816/r65816.hpp | 0
bsnes/processor/r65816/registers.hpp | 0
bsnes/processor/r65816/serialization.cpp | 0
bsnes/processor/r65816/table.cpp | 0
bsnes/processor/spc700/algorithms.cpp | 0
bsnes/processor/spc700/disassembler.cpp | 0
bsnes/processor/spc700/instructions.cpp | 0
bsnes/processor/spc700/memory.hpp | 0
bsnes/processor/spc700/registers.hpp | 0
bsnes/processor/spc700/serialization.cpp | 0
bsnes/processor/spc700/spc700.cpp | 0
bsnes/processor/spc700/spc700.hpp | 0
bsnes/processor/upd96050/disassembler.cpp | 0
bsnes/processor/upd96050/instructions.cpp | 0
bsnes/processor/upd96050/memory.cpp | 0
bsnes/processor/upd96050/registers.hpp | 0
bsnes/processor/upd96050/serialization.cpp | 0
bsnes/processor/upd96050/upd96050.cpp | 0
bsnes/processor/upd96050/upd96050.hpp | 0
.../profile/BS-X Satellaview.sfc/manifest.xml | 0
bsnes/profile/Famicom.sys/manifest.xml | 0
.../profile/Game Boy Advance.sys/manifest.xml | 0
bsnes/profile/Game Boy Color.sys/boot.rom | Bin
bsnes/profile/Game Boy Color.sys/manifest.xml | 0
bsnes/profile/Game Boy.sys/boot.rom | Bin
bsnes/profile/Game Boy.sys/manifest.xml | 0
bsnes/profile/Nintendo DS.sys/manifest.xml | 31 +
bsnes/profile/Sufami Turbo.sfc/manifest.xml | 0
bsnes/profile/Super Famicom.sys/manifest.xml | 0
bsnes/profile/Super Famicom.sys/spc700.rom | Bin
bsnes/profile/Super Game Boy.sfc/boot.rom | Bin
bsnes/profile/Super Game Boy.sfc/manifest.xml | 0
bsnes/ruby/Makefile | 0
bsnes/ruby/audio.hpp | 0
bsnes/ruby/audio/alsa.cpp | 0
bsnes/ruby/audio/ao.cpp | 0
bsnes/ruby/audio/directsound.cpp | 0
bsnes/ruby/audio/openal.cpp | 0
bsnes/ruby/audio/oss.cpp | 0
bsnes/ruby/audio/pulseaudio.cpp | 0
bsnes/ruby/audio/pulseaudiosimple.cpp | 0
bsnes/ruby/audio/xaudio2.cpp | 0
bsnes/ruby/audio/xaudio2.hpp | 0
bsnes/ruby/input.hpp | 0
bsnes/ruby/input/carbon.cpp | 0
bsnes/ruby/input/directinput.cpp | 0
bsnes/ruby/input/rawinput.cpp | 0
bsnes/ruby/input/sdl.cpp | 0
bsnes/ruby/input/x.cpp | 0
bsnes/ruby/input/xlibkeys.hpp | 0
bsnes/ruby/ruby.cpp | 0
bsnes/ruby/ruby.hpp | 0
bsnes/ruby/ruby_impl.cpp | 0
bsnes/ruby/video.hpp | 0
bsnes/ruby/video/direct3d.cpp | 0
bsnes/ruby/video/directdraw.cpp | 0
bsnes/ruby/video/gdi.cpp | 0
bsnes/ruby/video/glx.cpp | 0
bsnes/ruby/video/opengl.hpp | 0
bsnes/ruby/video/qtopengl.cpp | 0
bsnes/ruby/video/qtraster.cpp | 0
bsnes/ruby/video/sdl.cpp | 0
bsnes/ruby/video/wgl.cpp | 0
bsnes/ruby/video/xshm.cpp | 0
bsnes/ruby/video/xv.cpp | 0
bsnes/sfc/Makefile | 0
bsnes/sfc/alt/cpu/cpu.cpp | 0
bsnes/sfc/alt/cpu/cpu.hpp | 0
bsnes/sfc/alt/cpu/dma.cpp | 0
bsnes/sfc/alt/cpu/memory.cpp | 0
bsnes/sfc/alt/cpu/mmio.cpp | 0
bsnes/sfc/alt/cpu/serialization.cpp | 0
bsnes/sfc/alt/cpu/timing.cpp | 0
bsnes/sfc/alt/dsp/SPC_DSP.cpp | 0
bsnes/sfc/alt/dsp/SPC_DSP.h | 0
bsnes/sfc/alt/dsp/blargg_common.h | 0
bsnes/sfc/alt/dsp/blargg_config.h | 0
bsnes/sfc/alt/dsp/blargg_endian.h | 0
bsnes/sfc/alt/dsp/blargg_source.h | 0
bsnes/sfc/alt/dsp/dsp.cpp | 0
bsnes/sfc/alt/dsp/dsp.hpp | 0
bsnes/sfc/alt/dsp/serialization.cpp | 0
.../alt/ppu-compatibility/memory/memory.cpp | 0
.../alt/ppu-compatibility/memory/memory.hpp | 0
bsnes/sfc/alt/ppu-compatibility/mmio/mmio.cpp | 0
bsnes/sfc/alt/ppu-compatibility/mmio/mmio.hpp | 0
bsnes/sfc/alt/ppu-compatibility/ppu.cpp | 0
bsnes/sfc/alt/ppu-compatibility/ppu.hpp | 0
.../alt/ppu-compatibility/render/addsub.cpp | 0
bsnes/sfc/alt/ppu-compatibility/render/bg.cpp | 0
.../alt/ppu-compatibility/render/cache.cpp | 0
.../sfc/alt/ppu-compatibility/render/line.cpp | 0
.../alt/ppu-compatibility/render/mode7.cpp | 0
.../sfc/alt/ppu-compatibility/render/oam.cpp | 0
.../alt/ppu-compatibility/render/render.cpp | 0
.../alt/ppu-compatibility/render/render.hpp | 0
.../alt/ppu-compatibility/render/windows.cpp | 0
.../alt/ppu-compatibility/serialization.cpp | 0
.../ppu-performance/background/background.cpp | 0
.../ppu-performance/background/background.hpp | 0
.../alt/ppu-performance/background/mode7.cpp | 0
bsnes/sfc/alt/ppu-performance/cache/cache.cpp | 0
bsnes/sfc/alt/ppu-performance/cache/cache.hpp | 0
bsnes/sfc/alt/ppu-performance/mmio/mmio.cpp | 0
bsnes/sfc/alt/ppu-performance/mmio/mmio.hpp | 0
bsnes/sfc/alt/ppu-performance/ppu.cpp | 0
bsnes/sfc/alt/ppu-performance/ppu.hpp | 0
.../sfc/alt/ppu-performance/screen/screen.cpp | 0
.../sfc/alt/ppu-performance/screen/screen.hpp | 0
.../sfc/alt/ppu-performance/serialization.cpp | 0
.../sfc/alt/ppu-performance/sprite/sprite.cpp | 0
.../sfc/alt/ppu-performance/sprite/sprite.hpp | 0
.../sfc/alt/ppu-performance/window/window.cpp | 0
.../sfc/alt/ppu-performance/window/window.hpp | 0
bsnes/sfc/alt/smp/algorithms.cpp | 0
bsnes/sfc/alt/smp/core.cpp | 0
bsnes/sfc/alt/smp/core/cc.sh | 0
bsnes/sfc/alt/smp/core/generate.cpp | 0
bsnes/sfc/alt/smp/core/op_misc.b | 0
bsnes/sfc/alt/smp/core/op_misc.cpp | 0
bsnes/sfc/alt/smp/core/op_mov.b | 0
bsnes/sfc/alt/smp/core/op_mov.cpp | 0
bsnes/sfc/alt/smp/core/op_pc.b | 0
bsnes/sfc/alt/smp/core/op_pc.cpp | 0
bsnes/sfc/alt/smp/core/op_read.b | 0
bsnes/sfc/alt/smp/core/op_read.cpp | 0
bsnes/sfc/alt/smp/core/op_rmw.b | 0
bsnes/sfc/alt/smp/core/op_rmw.cpp | 0
bsnes/sfc/alt/smp/core/opcycle_misc.cpp | 0
bsnes/sfc/alt/smp/core/opcycle_mov.cpp | 0
bsnes/sfc/alt/smp/core/opcycle_pc.cpp | 0
bsnes/sfc/alt/smp/core/opcycle_read.cpp | 0
bsnes/sfc/alt/smp/core/opcycle_rmw.cpp | 0
bsnes/sfc/alt/smp/disassembler.cpp | 0
bsnes/sfc/alt/smp/memory.cpp | 0
bsnes/sfc/alt/smp/smp.cpp | 0
bsnes/sfc/alt/smp/smp.hpp | 0
bsnes/sfc/alt/smp/timing.cpp | 0
bsnes/sfc/cartridge/cartridge.cpp | 0
bsnes/sfc/cartridge/cartridge.hpp | 0
bsnes/sfc/cartridge/markup.cpp | 0
bsnes/sfc/cartridge/serialization.cpp | 0
bsnes/sfc/cheat/cheat.cpp | 0
bsnes/sfc/cheat/cheat.hpp | 0
bsnes/sfc/chip/armdsp/armdsp.cpp | 0
bsnes/sfc/chip/armdsp/armdsp.hpp | 0
bsnes/sfc/chip/armdsp/memory.cpp | 0
bsnes/sfc/chip/armdsp/registers.hpp | 0
bsnes/sfc/chip/armdsp/serialization.cpp | 0
bsnes/sfc/chip/bsx/bsx.cpp | 0
bsnes/sfc/chip/bsx/bsx.hpp | 0
bsnes/sfc/chip/bsx/cartridge/cartridge.cpp | 0
bsnes/sfc/chip/bsx/cartridge/cartridge.hpp | 0
.../sfc/chip/bsx/cartridge/serialization.cpp | 0
bsnes/sfc/chip/bsx/flash/flash.cpp | 0
bsnes/sfc/chip/bsx/flash/flash.hpp | 0
.../sfc/chip/bsx/satellaview/satellaview.cpp | 0
.../sfc/chip/bsx/satellaview/satellaview.hpp | 0
bsnes/sfc/chip/chip.hpp | 0
bsnes/sfc/chip/epsonrtc/epsonrtc.cpp | 0
bsnes/sfc/chip/epsonrtc/epsonrtc.hpp | 0
bsnes/sfc/chip/epsonrtc/memory.cpp | 0
bsnes/sfc/chip/epsonrtc/serialization.cpp | 0
bsnes/sfc/chip/epsonrtc/time.cpp | 0
bsnes/sfc/chip/hitachidsp/hitachidsp.cpp | 0
bsnes/sfc/chip/hitachidsp/hitachidsp.hpp | 0
bsnes/sfc/chip/hitachidsp/memory.cpp | 0
bsnes/sfc/chip/hitachidsp/mmio.hpp | 0
bsnes/sfc/chip/hitachidsp/serialization.cpp | 0
bsnes/sfc/chip/icd2/icd2.cpp | 0
bsnes/sfc/chip/icd2/icd2.hpp | 0
bsnes/sfc/chip/icd2/interface/interface.cpp | 0
bsnes/sfc/chip/icd2/interface/interface.hpp | 0
bsnes/sfc/chip/icd2/mmio/mmio.cpp | 0
bsnes/sfc/chip/icd2/mmio/mmio.hpp | 0
bsnes/sfc/chip/icd2/serialization.cpp | 0
bsnes/sfc/chip/msu1/msu1.cpp | 0
bsnes/sfc/chip/msu1/msu1.hpp | 0
bsnes/sfc/chip/msu1/serialization.cpp | 0
bsnes/sfc/chip/necdsp/necdsp.cpp | 0
bsnes/sfc/chip/necdsp/necdsp.hpp | 0
bsnes/sfc/chip/necdsp/serialization.cpp | 0
bsnes/sfc/chip/nss/nss.cpp | 0
bsnes/sfc/chip/nss/nss.hpp | 0
bsnes/sfc/chip/obc1/obc1.cpp | 0
bsnes/sfc/chip/obc1/obc1.hpp | 0
bsnes/sfc/chip/obc1/serialization.cpp | 0
bsnes/sfc/chip/sa1/bus/bus.cpp | 0
bsnes/sfc/chip/sa1/bus/bus.hpp | 0
bsnes/sfc/chip/sa1/dma/dma.cpp | 0
bsnes/sfc/chip/sa1/dma/dma.hpp | 0
bsnes/sfc/chip/sa1/memory/memory.cpp | 0
bsnes/sfc/chip/sa1/memory/memory.hpp | 0
bsnes/sfc/chip/sa1/mmio/mmio.cpp | 0
bsnes/sfc/chip/sa1/mmio/mmio.hpp | 0
bsnes/sfc/chip/sa1/sa1.cpp | 0
bsnes/sfc/chip/sa1/sa1.hpp | 0
bsnes/sfc/chip/sa1/serialization.cpp | 0
bsnes/sfc/chip/sdd1/decomp.cpp | 0
bsnes/sfc/chip/sdd1/decomp.hpp | 0
bsnes/sfc/chip/sdd1/sdd1.cpp | 0
bsnes/sfc/chip/sdd1/sdd1.hpp | 0
bsnes/sfc/chip/sdd1/serialization.cpp | 0
bsnes/sfc/chip/sharprtc/memory.cpp | 0
bsnes/sfc/chip/sharprtc/serialization.cpp | 0
bsnes/sfc/chip/sharprtc/sharprtc.cpp | 0
bsnes/sfc/chip/sharprtc/sharprtc.hpp | 0
bsnes/sfc/chip/sharprtc/time.cpp | 0
bsnes/sfc/chip/spc7110/alu.cpp | 0
bsnes/sfc/chip/spc7110/data.cpp | 0
bsnes/sfc/chip/spc7110/dcu.cpp | 0
bsnes/sfc/chip/spc7110/decompressor.cpp | 0
bsnes/sfc/chip/spc7110/serialization.cpp | 0
bsnes/sfc/chip/spc7110/spc7110.cpp | 0
bsnes/sfc/chip/spc7110/spc7110.hpp | 0
bsnes/sfc/chip/sufamiturbo/serialization.cpp | 0
bsnes/sfc/chip/sufamiturbo/sufamiturbo.cpp | 0
bsnes/sfc/chip/sufamiturbo/sufamiturbo.hpp | 0
bsnes/sfc/chip/superfx/bus/bus.cpp | 0
bsnes/sfc/chip/superfx/bus/bus.hpp | 0
bsnes/sfc/chip/superfx/core/core.cpp | 0
bsnes/sfc/chip/superfx/core/core.hpp | 0
bsnes/sfc/chip/superfx/disasm/disasm.cpp | 0
bsnes/sfc/chip/superfx/disasm/disasm.hpp | 0
bsnes/sfc/chip/superfx/memory/memory.cpp | 0
bsnes/sfc/chip/superfx/memory/memory.hpp | 0
bsnes/sfc/chip/superfx/mmio/mmio.cpp | 0
bsnes/sfc/chip/superfx/mmio/mmio.hpp | 0
bsnes/sfc/chip/superfx/serialization.cpp | 0
bsnes/sfc/chip/superfx/superfx.cpp | 0
bsnes/sfc/chip/superfx/superfx.hpp | 0
bsnes/sfc/chip/superfx/timing/timing.cpp | 0
bsnes/sfc/chip/superfx/timing/timing.hpp | 0
bsnes/sfc/config/config.cpp | 0
bsnes/sfc/config/config.hpp | 0
bsnes/sfc/controller/controller.cpp | 0
bsnes/sfc/controller/controller.hpp | 0
bsnes/sfc/controller/gamepad/gamepad.cpp | 43 +-
bsnes/sfc/controller/gamepad/gamepad.hpp | 4 +
bsnes/sfc/controller/justifier/justifier.cpp | 0
bsnes/sfc/controller/justifier/justifier.hpp | 0
bsnes/sfc/controller/mouse/mouse.cpp | 84 +-
bsnes/sfc/controller/mouse/mouse.hpp | 15 +-
bsnes/sfc/controller/multitap/multitap.cpp | 0
bsnes/sfc/controller/multitap/multitap.hpp | 0
.../sfc/controller/superscope/superscope.cpp | 0
.../sfc/controller/superscope/superscope.hpp | 0
bsnes/sfc/controller/usart/usart.cpp | 0
bsnes/sfc/controller/usart/usart.hpp | 0
bsnes/sfc/cpu/cpu.cpp | 0
bsnes/sfc/cpu/cpu.hpp | 0
bsnes/sfc/cpu/dma/dma.cpp | 0
bsnes/sfc/cpu/dma/dma.hpp | 0
bsnes/sfc/cpu/memory/memory.cpp | 0
bsnes/sfc/cpu/memory/memory.hpp | 0
bsnes/sfc/cpu/mmio/mmio.cpp | 0
bsnes/sfc/cpu/mmio/mmio.hpp | 0
bsnes/sfc/cpu/serialization.cpp | 0
bsnes/sfc/cpu/timing/irq.cpp | 0
bsnes/sfc/cpu/timing/joypad.cpp | 0
bsnes/sfc/cpu/timing/timing.cpp | 0
bsnes/sfc/cpu/timing/timing.hpp | 0
bsnes/sfc/dsp/brr.cpp | 0
bsnes/sfc/dsp/counter.cpp | 0
bsnes/sfc/dsp/dsp.cpp | 0
bsnes/sfc/dsp/dsp.hpp | 0
bsnes/sfc/dsp/echo.cpp | 0
bsnes/sfc/dsp/envelope.cpp | 0
bsnes/sfc/dsp/gaussian.cpp | 0
bsnes/sfc/dsp/misc.cpp | 0
bsnes/sfc/dsp/moduloarray.hpp | 0
bsnes/sfc/dsp/serialization.cpp | 0
bsnes/sfc/dsp/voice.cpp | 0
bsnes/sfc/interface/interface.cpp | 2 +-
bsnes/sfc/interface/interface.hpp | 0
bsnes/sfc/memory/memory-inline.hpp | 0
bsnes/sfc/memory/memory.cpp | 0
bsnes/sfc/memory/memory.hpp | 0
bsnes/sfc/ppu/background/background.cpp | 0
bsnes/sfc/ppu/background/background.hpp | 0
bsnes/sfc/ppu/background/mode7.cpp | 0
bsnes/sfc/ppu/counter/counter-inline.hpp | 0
bsnes/sfc/ppu/counter/counter.hpp | 0
bsnes/sfc/ppu/mmio/mmio.cpp | 0
bsnes/sfc/ppu/mmio/mmio.hpp | 0
bsnes/sfc/ppu/ppu.cpp | 0
bsnes/sfc/ppu/ppu.hpp | 0
bsnes/sfc/ppu/screen/screen.cpp | 0
bsnes/sfc/ppu/screen/screen.hpp | 0
bsnes/sfc/ppu/serialization.cpp | 0
bsnes/sfc/ppu/sprite/list.cpp | 0
bsnes/sfc/ppu/sprite/sprite.cpp | 0
bsnes/sfc/ppu/sprite/sprite.hpp | 0
bsnes/sfc/ppu/window/window.cpp | 0
bsnes/sfc/ppu/window/window.hpp | 0
bsnes/sfc/profile-accuracy.hpp | 0
bsnes/sfc/profile-compatibility.hpp | 0
bsnes/sfc/profile-performance.hpp | 0
bsnes/sfc/random/random.cpp | 0
bsnes/sfc/random/random.hpp | 0
bsnes/sfc/scheduler/scheduler.cpp | 0
bsnes/sfc/scheduler/scheduler.hpp | 0
bsnes/sfc/sfc.hpp | 0
bsnes/sfc/smp/memory.cpp | 0
bsnes/sfc/smp/serialization.cpp | 0
bsnes/sfc/smp/smp.cpp | 0
bsnes/sfc/smp/smp.hpp | 0
bsnes/sfc/smp/timing.cpp | 0
bsnes/sfc/system/audio.cpp | 0
bsnes/sfc/system/audio.hpp | 0
bsnes/sfc/system/input.cpp | 0
bsnes/sfc/system/input.hpp | 0
bsnes/sfc/system/serialization.cpp | 0
bsnes/sfc/system/system.cpp | 0
bsnes/sfc/system/system.hpp | 0
bsnes/sfc/system/video.cpp | 0
bsnes/sfc/system/video.hpp | 0
bsnes/target-ethos/Makefile | 6 +-
bsnes/target-ethos/bootstrap.cpp | 2 +
.../configuration/configuration.cpp | 0
.../configuration/configuration.hpp | 0
bsnes/target-ethos/ethos.cpp | 0
bsnes/target-ethos/ethos.hpp | 0
bsnes/target-ethos/general/browser.cpp | 0
bsnes/target-ethos/general/browser.hpp | 0
bsnes/target-ethos/general/dip-switches.cpp | 0
bsnes/target-ethos/general/dip-switches.hpp | 0
bsnes/target-ethos/general/general.cpp | 0
bsnes/target-ethos/general/general.hpp | 0
bsnes/target-ethos/general/presentation.cpp | 0
bsnes/target-ethos/general/presentation.hpp | 0
bsnes/target-ethos/input/hotkeys.cpp | 0
bsnes/target-ethos/input/input.cpp | 0
bsnes/target-ethos/input/input.hpp | 0
bsnes/target-ethos/interface/interface.cpp | 0
bsnes/target-ethos/interface/interface.hpp | 0
bsnes/target-ethos/resource.rc | 0
bsnes/target-ethos/resource/folder.png | Bin
bsnes/target-ethos/resource/game.png | Bin
bsnes/target-ethos/resource/home.png | Bin
bsnes/target-ethos/resource/resource.cpp | 0
bsnes/target-ethos/resource/resource.hpp | 0
bsnes/target-ethos/resource/resource.xml | 0
bsnes/target-ethos/resource/up.png | Bin
bsnes/target-ethos/settings/audio.cpp | 0
bsnes/target-ethos/settings/audio.hpp | 0
bsnes/target-ethos/settings/driver.cpp | 0
bsnes/target-ethos/settings/driver.hpp | 0
bsnes/target-ethos/settings/hotkey.cpp | 0
bsnes/target-ethos/settings/hotkey.hpp | 0
bsnes/target-ethos/settings/input.cpp | 0
bsnes/target-ethos/settings/input.hpp | 0
bsnes/target-ethos/settings/settings.cpp | 0
bsnes/target-ethos/settings/settings.hpp | 0
bsnes/target-ethos/settings/timing.cpp | 0
bsnes/target-ethos/settings/timing.hpp | 0
bsnes/target-ethos/settings/video.cpp | 0
bsnes/target-ethos/settings/video.hpp | 0
bsnes/target-ethos/tools/cheat-database.cpp | 0
bsnes/target-ethos/tools/cheat-database.hpp | 0
bsnes/target-ethos/tools/cheat-editor.cpp | 0
bsnes/target-ethos/tools/cheat-editor.hpp | 0
bsnes/target-ethos/tools/state-manager.cpp | 0
bsnes/target-ethos/tools/state-manager.hpp | 0
bsnes/target-ethos/tools/tools.cpp | 0
bsnes/target-ethos/tools/tools.hpp | 0
bsnes/target-ethos/utility/utility.cpp | 0
bsnes/target-ethos/utility/utility.hpp | 0
bsnes/target-ethos/window/window.cpp | 0
bsnes/target-ethos/window/window.hpp | 0
bsnes/target-laevateinn/Makefile | 0
bsnes/target-laevateinn/base.hpp | 0
.../breakpoint/breakpoint.cpp | 0
.../breakpoint/breakpoint.hpp | 0
bsnes/target-laevateinn/console/about.cpp | 0
bsnes/target-laevateinn/console/console.cpp | 0
bsnes/target-laevateinn/console/console.hpp | 0
bsnes/target-laevateinn/cpu/cpu.cpp | 0
bsnes/target-laevateinn/cpu/cpu.hpp | 0
bsnes/target-laevateinn/cpu/registers.cpp | 0
bsnes/target-laevateinn/debugger/debugger.cpp | 0
bsnes/target-laevateinn/debugger/debugger.hpp | 0
bsnes/target-laevateinn/debugger/hook.cpp | 0
bsnes/target-laevateinn/debugger/usage.cpp | 0
.../target-laevateinn/interface/interface.cpp | 0
.../target-laevateinn/interface/interface.hpp | 0
bsnes/target-laevateinn/main.cpp | 0
bsnes/target-laevateinn/memory/memory.cpp | 0
bsnes/target-laevateinn/memory/memory.hpp | 0
.../properties/properties.cpp | 0
.../properties/properties.hpp | 0
bsnes/target-laevateinn/resource.rc | 0
bsnes/target-laevateinn/settings/settings.cpp | 0
bsnes/target-laevateinn/settings/settings.hpp | 0
bsnes/target-laevateinn/smp/registers.cpp | 0
bsnes/target-laevateinn/smp/smp.cpp | 0
bsnes/target-laevateinn/smp/smp.hpp | 0
bsnes/target-laevateinn/tracer/tracer.cpp | 0
bsnes/target-laevateinn/tracer/tracer.hpp | 0
bsnes/target-laevateinn/video/video.cpp | 0
bsnes/target-laevateinn/video/video.hpp | 0
bsnes/target-laevateinn/vram/vram.cpp | 0
bsnes/target-laevateinn/vram/vram.hpp | 0
bsnes/target-laevateinn/window/window.cpp | 0
bsnes/target-laevateinn/window/window.hpp | 0
kaijuu/Makefile | 18 +
kaijuu/cc32.bat | 8 +
kaijuu/cc64.bat | 8 +
kaijuu/extension.cpp | 175 +++
kaijuu/extension.hpp | 23 +
kaijuu/factory.cpp | 40 +
kaijuu/factory.hpp | 17 +
kaijuu/guid.hpp | 11 +
kaijuu/interface.cpp | 307 ++++
kaijuu/interface.hpp | 72 +
kaijuu/kaijuu.Manifest | 21 +
kaijuu/kaijuu.cpp | 50 +
kaijuu/kaijuu.def | 5 +
kaijuu/kaijuu.hpp | 25 +
kaijuu/kaijuu.html | 200 +++
kaijuu/kaijuu.rc | 1 +
{snesfilter => kaijuu}/nall/Makefile | 10 +-
{snesfilter => kaijuu}/nall/algorithm.hpp | 0
{snesfilter => kaijuu}/nall/any.hpp | 17 +-
{snesfilter => kaijuu}/nall/atoi.hpp | 15 +
{snesfilter => kaijuu}/nall/base64.hpp | 0
kaijuu/nall/bit.hpp | 82 +
{snesfilter => kaijuu}/nall/bmp.hpp | 0
{snesfilter => kaijuu}/nall/bps/delta.hpp | 0
{snesfilter => kaijuu}/nall/bps/linear.hpp | 0
{snesfilter => kaijuu}/nall/bps/metadata.hpp | 0
{snesfilter => kaijuu}/nall/bps/patch.hpp | 0
{snesfilter => kaijuu}/nall/compositor.hpp | 0
{snesfilter => kaijuu}/nall/config.hpp | 37 +-
{snesfilter => kaijuu}/nall/crc32.hpp | 0
{snesfilter => kaijuu}/nall/directory.hpp | 46 +-
{snesfilter => kaijuu}/nall/dl.hpp | 0
{snesfilter => kaijuu}/nall/dsp.hpp | 0
{snesfilter => kaijuu}/nall/dsp/buffer.hpp | 0
{snesfilter => kaijuu}/nall/dsp/core.hpp | 0
.../nall/dsp/resample/average.hpp | 0
.../nall/dsp/resample/cosine.hpp | 0
.../nall/dsp/resample/cubic.hpp | 0
.../nall/dsp/resample/hermite.hpp | 0
.../nall/dsp/resample/lib/sinc.hpp | 0
.../nall/dsp/resample/linear.hpp | 0
.../nall/dsp/resample/nearest.hpp | 0
.../nall/dsp/resample/sinc.hpp | 0
{snesfilter => kaijuu}/nall/dsp/settings.hpp | 0
kaijuu/nall/emulation/famicom.hpp | 182 +++
kaijuu/nall/emulation/game-boy-advance.hpp | 68 +
.../nall/emulation/game-boy.hpp | 32 +-
kaijuu/nall/emulation/satellaview.hpp | 26 +
kaijuu/nall/emulation/sufami-turbo.hpp | 33 +
kaijuu/nall/emulation/super-famicom-usart.hpp | 103 ++
kaijuu/nall/emulation/super-famicom.hpp | 800 ++++++++++
{snesfilter => kaijuu}/nall/endian.hpp | 0
{snesfilter => kaijuu}/nall/file.hpp | 75 +-
{snesfilter => kaijuu}/nall/filemap.hpp | 1 +
{snesfilter => kaijuu}/nall/function.hpp | 0
{snesfilter => kaijuu}/nall/gzip.hpp | 18 +-
{snesfilter => kaijuu}/nall/http.hpp | 4 +-
{snesfilter => kaijuu}/nall/image.hpp | 123 +-
{snesfilter => kaijuu}/nall/inflate.hpp | 0
{snesfilter => kaijuu}/nall/input.hpp | 0
{snesfilter => kaijuu}/nall/interpolation.hpp | 8 +-
{snesfilter => kaijuu}/nall/intrinsics.hpp | 0
kaijuu/nall/invoke.hpp | 52 +
{snesfilter => kaijuu}/nall/ips.hpp | 10 -
{snesfilter => kaijuu}/nall/lzss.hpp | 0
kaijuu/nall/map.hpp | 117 ++
kaijuu/nall/mosaic.hpp | 10 +
kaijuu/nall/mosaic/bitstream.hpp | 55 +
kaijuu/nall/mosaic/context.hpp | 224 +++
kaijuu/nall/mosaic/parser.hpp | 126 ++
kaijuu/nall/nall.hpp | 56 +
kaijuu/nall/platform.hpp | 86 ++
{snesfilter => kaijuu}/nall/png.hpp | 10 +-
.../nall/priority-queue.hpp | 4 +-
{snesfilter => kaijuu}/nall/property.hpp | 0
.../nall/public-cast.hpp | 0
{snesfilter => kaijuu}/nall/random.hpp | 0
{snesfilter => kaijuu}/nall/serial.hpp | 29 +-
{snesfilter => kaijuu}/nall/serializer.hpp | 4 +-
kaijuu/nall/set.hpp | 158 ++
{snesfilter => kaijuu}/nall/sha256.hpp | 0
kaijuu/nall/sort.hpp | 77 +
{snesfilter => kaijuu}/nall/stdint.hpp | 2 -
kaijuu/nall/stream.hpp | 26 +
kaijuu/nall/stream/auto.hpp | 25 +
kaijuu/nall/stream/file.hpp | 42 +
kaijuu/nall/stream/gzip.hpp | 34 +
kaijuu/nall/stream/http.hpp | 49 +
kaijuu/nall/stream/memory.hpp | 47 +
kaijuu/nall/stream/mmap.hpp | 42 +
kaijuu/nall/stream/stream.hpp | 92 ++
kaijuu/nall/stream/vector.hpp | 39 +
kaijuu/nall/stream/zip.hpp | 38 +
{snesfilter => kaijuu}/nall/string.hpp | 8 +-
{snesfilter => kaijuu}/nall/string/base.hpp | 34 +-
{snesfilter => kaijuu}/nall/string/bml.hpp | 6 +-
{snesfilter => kaijuu}/nall/string/bsv.hpp | 0
{snesfilter => kaijuu}/nall/string/cast.hpp | 0
.../nall/string/compare.hpp | 0
.../nall/string/convert.hpp | 0
{snesfilter => kaijuu}/nall/string/core.hpp | 47 +-
.../nall/string/cstring.hpp | 0
kaijuu/nall/string/filename.hpp | 74 +
.../nall/string/math-fixed-point.hpp | 9 +
.../nall/string/math-floating-point.hpp | 10 +-
kaijuu/nall/string/platform.hpp | 63 +
.../nall/string/replace.hpp | 0
{snesfilter => kaijuu}/nall/string/split.hpp | 0
kaijuu/nall/string/static.hpp | 13 +
kaijuu/nall/string/strm.hpp | 45 +
{snesfilter => kaijuu}/nall/string/strpos.hpp | 0
{snesfilter => kaijuu}/nall/string/trim.hpp | 0
kaijuu/nall/string/utf8.hpp | 43 +
.../nall/string/utility.hpp | 16 +-
.../nall/string/variadic.hpp | 0
.../nall/string/wildcard.hpp | 0
.../nall/string/wrapper.hpp | 1 +
.../nall/string/xml-legacy.hpp | 0
kaijuu/nall/string/xml.hpp | 250 ++++
kaijuu/nall/traits.hpp | 33 +
kaijuu/nall/udl.hpp | 28 +
{snesfilter => kaijuu}/nall/ups.hpp | 0
{snesfilter => kaijuu}/nall/utility.hpp | 10 -
kaijuu/nall/varint.hpp | 168 +++
kaijuu/nall/vector.hpp | 204 +++
.../nall/windows/detour.hpp | 0
kaijuu/nall/windows/guid.hpp | 30 +
.../nall/windows/launcher.hpp | 0
kaijuu/nall/windows/registry.hpp | 120 ++
{snesfilter => kaijuu}/nall/windows/utf8.hpp | 1 +
kaijuu/nall/xorg/guard.hpp | 29 +
kaijuu/nall/xorg/xorg.hpp | 12 +
{snesfilter => kaijuu}/nall/zip.hpp | 32 +-
kaijuu/phoenix/Makefile | 21 +
kaijuu/phoenix/core/core.cpp | 1326 +++++++++++++++++
kaijuu/phoenix/core/core.hpp | 612 ++++++++
kaijuu/phoenix/core/keyboard.hpp | 45 +
kaijuu/phoenix/core/layout/fixed-layout.cpp | 80 +
kaijuu/phoenix/core/layout/fixed-layout.hpp | 27 +
.../phoenix/core/layout/horizontal-layout.cpp | 142 ++
.../phoenix/core/layout/horizontal-layout.hpp | 31 +
.../phoenix/core/layout/vertical-layout.cpp | 142 ++
.../phoenix/core/layout/vertical-layout.hpp | 31 +
kaijuu/phoenix/core/state.hpp | 278 ++++
kaijuu/phoenix/gtk/action/action.cpp | 27 +
kaijuu/phoenix/gtk/action/check-item.cpp | 33 +
kaijuu/phoenix/gtk/action/item.cpp | 31 +
kaijuu/phoenix/gtk/action/menu.cpp | 51 +
kaijuu/phoenix/gtk/action/radio-item.cpp | 48 +
kaijuu/phoenix/gtk/action/separator.cpp | 12 +
kaijuu/phoenix/gtk/desktop.cpp | 36 +
kaijuu/phoenix/gtk/dialog-window.cpp | 69 +
kaijuu/phoenix/gtk/font.cpp | 58 +
kaijuu/phoenix/gtk/keyboard.cpp | 142 ++
kaijuu/phoenix/gtk/message-window.cpp | 61 +
kaijuu/phoenix/gtk/mouse.cpp | 20 +
kaijuu/phoenix/gtk/platform.cpp | 87 ++
kaijuu/phoenix/gtk/platform.hpp | 501 +++++++
kaijuu/phoenix/gtk/settings.cpp | 25 +
kaijuu/phoenix/gtk/timer.cpp | 24 +
kaijuu/phoenix/gtk/utility.cpp | 200 +++
kaijuu/phoenix/gtk/widget/button.cpp | 53 +
kaijuu/phoenix/gtk/widget/canvas.cpp | 70 +
kaijuu/phoenix/gtk/widget/check-box.cpp | 40 +
kaijuu/phoenix/gtk/widget/combo-box.cpp | 73 +
kaijuu/phoenix/gtk/widget/hex-edit.cpp | 264 ++++
.../gtk/widget/horizontal-scroll-bar.cpp | 42 +
.../phoenix/gtk/widget/horizontal-slider.cpp | 41 +
kaijuu/phoenix/gtk/widget/label.cpp | 24 +
kaijuu/phoenix/gtk/widget/line-edit.cpp | 45 +
kaijuu/phoenix/gtk/widget/list-view.cpp | 217 +++
kaijuu/phoenix/gtk/widget/progress-bar.cpp | 23 +
kaijuu/phoenix/gtk/widget/radio-box.cpp | 50 +
kaijuu/phoenix/gtk/widget/text-edit.cpp | 66 +
.../gtk/widget/vertical-scroll-bar.cpp | 42 +
kaijuu/phoenix/gtk/widget/vertical-slider.cpp | 41 +
kaijuu/phoenix/gtk/widget/viewport.cpp | 58 +
kaijuu/phoenix/gtk/widget/widget.cpp | 47 +
kaijuu/phoenix/gtk/window.cpp | 352 +++++
kaijuu/phoenix/phoenix.cpp | 52 +
kaijuu/phoenix/phoenix.hpp | 19 +
kaijuu/phoenix/qt/action/action.cpp | 49 +
kaijuu/phoenix/qt/action/check-item.cpp | 27 +
kaijuu/phoenix/qt/action/item.cpp | 21 +
kaijuu/phoenix/qt/action/menu.cpp | 51 +
kaijuu/phoenix/qt/action/radio-item.cpp | 41 +
kaijuu/phoenix/qt/action/separator.cpp | 9 +
kaijuu/phoenix/qt/desktop.cpp | 9 +
kaijuu/phoenix/qt/dialog-window.cpp | 57 +
kaijuu/phoenix/qt/font.cpp | 40 +
kaijuu/phoenix/qt/keyboard.cpp | 142 ++
kaijuu/phoenix/qt/message-window.cpp | 47 +
kaijuu/phoenix/qt/mouse.cpp | 14 +
kaijuu/phoenix/qt/platform.cpp | 91 ++
kaijuu/phoenix/qt/platform.moc | 1105 ++++++++++++++
kaijuu/phoenix/qt/platform.moc.hpp | 633 ++++++++
kaijuu/phoenix/qt/settings.cpp | 24 +
kaijuu/phoenix/qt/timer.cpp | 25 +
kaijuu/phoenix/qt/utility.cpp | 190 +++
kaijuu/phoenix/qt/widget/button.cpp | 52 +
kaijuu/phoenix/qt/widget/canvas.cpp | 73 +
kaijuu/phoenix/qt/widget/check-box.cpp | 42 +
kaijuu/phoenix/qt/widget/combo-box.cpp | 68 +
kaijuu/phoenix/qt/widget/hex-edit.cpp | 191 +++
.../qt/widget/horizontal-scroll-bar.cpp | 43 +
.../phoenix/qt/widget/horizontal-slider.cpp | 43 +
kaijuu/phoenix/qt/widget/label.cpp | 25 +
kaijuu/phoenix/qt/widget/line-edit.cpp | 45 +
kaijuu/phoenix/qt/widget/list-view.cpp | 164 ++
kaijuu/phoenix/qt/widget/progress-bar.cpp | 26 +
kaijuu/phoenix/qt/widget/radio-box.cpp | 64 +
kaijuu/phoenix/qt/widget/text-edit.cpp | 50 +
.../phoenix/qt/widget/vertical-scroll-bar.cpp | 43 +
kaijuu/phoenix/qt/widget/vertical-slider.cpp | 43 +
kaijuu/phoenix/qt/widget/viewport.cpp | 51 +
kaijuu/phoenix/qt/widget/widget.cpp | 52 +
kaijuu/phoenix/qt/window.cpp | 288 ++++
kaijuu/phoenix/reference/action/action.cpp | 8 +
.../phoenix/reference/action/check-item.cpp | 15 +
kaijuu/phoenix/reference/action/item.cpp | 11 +
kaijuu/phoenix/reference/action/menu.cpp | 17 +
.../phoenix/reference/action/radio-item.cpp | 18 +
kaijuu/phoenix/reference/action/separator.cpp | 5 +
kaijuu/phoenix/reference/desktop.cpp | 8 +
kaijuu/phoenix/reference/dialog-window.cpp | 11 +
kaijuu/phoenix/reference/font.cpp | 3 +
kaijuu/phoenix/reference/keyboard.cpp | 10 +
kaijuu/phoenix/reference/message-window.cpp | 15 +
kaijuu/phoenix/reference/mouse.cpp | 7 +
kaijuu/phoenix/reference/platform.cpp | 52 +
kaijuu/phoenix/reference/platform.hpp | 381 +++++
kaijuu/phoenix/reference/timer.cpp | 8 +
kaijuu/phoenix/reference/widget/button.cpp | 8 +
kaijuu/phoenix/reference/widget/canvas.cpp | 8 +
kaijuu/phoenix/reference/widget/check-box.cpp | 12 +
kaijuu/phoenix/reference/widget/combo-box.cpp | 21 +
kaijuu/phoenix/reference/widget/hex-edit.cpp | 17 +
.../widget/horizontal-scroll-bar.cpp | 12 +
.../reference/widget/horizontal-slider.cpp | 12 +
kaijuu/phoenix/reference/widget/label.cpp | 5 +
kaijuu/phoenix/reference/widget/line-edit.cpp | 11 +
kaijuu/phoenix/reference/widget/list-view.cpp | 49 +
.../phoenix/reference/widget/progress-bar.cpp | 5 +
kaijuu/phoenix/reference/widget/radio-box.cpp | 15 +
kaijuu/phoenix/reference/widget/text-edit.cpp | 17 +
.../reference/widget/vertical-scroll-bar.cpp | 12 +
.../reference/widget/vertical-slider.cpp | 12 +
kaijuu/phoenix/reference/widget/viewport.cpp | 6 +
kaijuu/phoenix/reference/widget/widget.cpp | 25 +
kaijuu/phoenix/reference/window.cpp | 78 +
{snesfilter => kaijuu/phoenix}/sync.sh | 1 +
kaijuu/phoenix/windows/action/action.cpp | 12 +
kaijuu/phoenix/windows/action/check-item.cpp | 18 +
kaijuu/phoenix/windows/action/item.cpp | 29 +
kaijuu/phoenix/windows/action/menu.cpp | 109 ++
kaijuu/phoenix/windows/action/radio-item.cpp | 26 +
kaijuu/phoenix/windows/action/separator.cpp | 6 +
kaijuu/phoenix/windows/desktop.cpp | 9 +
kaijuu/phoenix/windows/dialog-window.cpp | 88 ++
kaijuu/phoenix/windows/font.cpp | 44 +
kaijuu/phoenix/windows/keyboard.cpp | 137 ++
kaijuu/phoenix/windows/message-window.cpp | 41 +
kaijuu/phoenix/windows/mouse.cpp | 14 +
kaijuu/phoenix/windows/object.cpp | 13 +
kaijuu/phoenix/windows/phoenix.Manifest | 14 +
kaijuu/phoenix/windows/phoenix.rc | 1 +
kaijuu/phoenix/windows/platform.cpp | 479 ++++++
kaijuu/phoenix/windows/platform.hpp | 481 ++++++
kaijuu/phoenix/windows/settings.cpp | 1 +
kaijuu/phoenix/windows/timer.cpp | 31 +
kaijuu/phoenix/windows/utility.cpp | 150 ++
kaijuu/phoenix/windows/widget/button.cpp | 90 ++
kaijuu/phoenix/windows/widget/canvas.cpp | 92 ++
kaijuu/phoenix/windows/widget/check-box.cpp | 39 +
kaijuu/phoenix/windows/widget/combo-box.cpp | 70 +
kaijuu/phoenix/windows/widget/hex-edit.cpp | 136 ++
.../windows/widget/horizontal-scroll-bar.cpp | 38 +
.../windows/widget/horizontal-slider.cpp | 39 +
kaijuu/phoenix/windows/widget/label.cpp | 64 +
kaijuu/phoenix/windows/widget/line-edit.cpp | 45 +
kaijuu/phoenix/windows/widget/list-view.cpp | 210 +++
.../phoenix/windows/widget/progress-bar.cpp | 25 +
kaijuu/phoenix/windows/widget/radio-box.cpp | 43 +
kaijuu/phoenix/windows/widget/text-edit.cpp | 58 +
.../windows/widget/vertical-scroll-bar.cpp | 38 +
.../windows/widget/vertical-slider.cpp | 39 +
kaijuu/phoenix/windows/widget/viewport.cpp | 57 +
kaijuu/phoenix/windows/widget/widget.cpp | 66 +
kaijuu/phoenix/windows/window.cpp | 229 +++
kaijuu/resource/kaijuu.png | Bin 0 -> 13013 bytes
kaijuu/resource/resource.cpp | 413 +++++
kaijuu/resource/resource.hpp | 3 +
kaijuu/resource/resource.xml | 4 +
kaijuu/settings.hpp | 45 +
kaijuu/sync.sh | 7 +
purify/Makefile | 6 +-
purify/nall/Makefile | 3 +
purify/nall/algorithm.hpp | 0
purify/nall/any.hpp | 0
purify/nall/atoi.hpp | 0
purify/nall/base64.hpp | 0
purify/nall/bit.hpp | 0
purify/nall/bmp.hpp | 0
purify/nall/bps/delta.hpp | 0
purify/nall/bps/linear.hpp | 0
purify/nall/bps/metadata.hpp | 0
purify/nall/bps/patch.hpp | 0
purify/nall/compositor.hpp | 0
purify/nall/config.hpp | 0
purify/nall/crc32.hpp | 0
purify/nall/directory.hpp | 0
purify/nall/dl.hpp | 0
purify/nall/dsp.hpp | 0
purify/nall/dsp/buffer.hpp | 0
purify/nall/dsp/core.hpp | 0
purify/nall/dsp/resample/average.hpp | 0
purify/nall/dsp/resample/cosine.hpp | 0
purify/nall/dsp/resample/cubic.hpp | 0
purify/nall/dsp/resample/hermite.hpp | 0
purify/nall/dsp/resample/lib/sinc.hpp | 0
purify/nall/dsp/resample/linear.hpp | 0
purify/nall/dsp/resample/nearest.hpp | 0
purify/nall/dsp/resample/sinc.hpp | 0
purify/nall/dsp/settings.hpp | 0
purify/nall/emulation/famicom.hpp | 0
purify/nall/emulation/game-boy-advance.hpp | 0
purify/nall/emulation/game-boy.hpp | 0
purify/nall/emulation/satellaview.hpp | 0
purify/nall/emulation/sufami-turbo.hpp | 0
purify/nall/emulation/super-famicom-usart.hpp | 0
purify/nall/emulation/super-famicom.hpp | 3 +
purify/nall/endian.hpp | 0
purify/nall/file.hpp | 0
purify/nall/filemap.hpp | 0
purify/nall/function.hpp | 0
purify/nall/gzip.hpp | 0
purify/nall/http.hpp | 0
purify/nall/image.hpp | 0
purify/nall/inflate.hpp | 0
purify/nall/input.hpp | 0
purify/nall/interpolation.hpp | 0
purify/nall/intrinsics.hpp | 0
purify/nall/invoke.hpp | 0
purify/nall/ips.hpp | 0
purify/nall/lzss.hpp | 0
purify/nall/map.hpp | 0
purify/nall/mosaic.hpp | 0
purify/nall/mosaic/bitstream.hpp | 0
purify/nall/mosaic/context.hpp | 0
purify/nall/mosaic/parser.hpp | 0
purify/nall/nall.hpp | 0
purify/nall/platform.hpp | 0
purify/nall/png.hpp | 0
purify/nall/priority-queue.hpp | 0
purify/nall/property.hpp | 0
purify/nall/public-cast.hpp | 0
purify/nall/random.hpp | 0
purify/nall/serial.hpp | 0
purify/nall/serializer.hpp | 0
purify/nall/set.hpp | 0
purify/nall/sha256.hpp | 0
purify/nall/sort.hpp | 0
purify/nall/stdint.hpp | 0
purify/nall/stream.hpp | 0
purify/nall/stream/auto.hpp | 0
purify/nall/stream/file.hpp | 0
purify/nall/stream/gzip.hpp | 0
purify/nall/stream/http.hpp | 0
purify/nall/stream/memory.hpp | 0
purify/nall/stream/mmap.hpp | 0
purify/nall/stream/stream.hpp | 0
purify/nall/stream/vector.hpp | 0
purify/nall/stream/zip.hpp | 0
purify/nall/string.hpp | 0
purify/nall/string/base.hpp | 0
purify/nall/string/bml.hpp | 0
purify/nall/string/bsv.hpp | 0
purify/nall/string/cast.hpp | 0
purify/nall/string/compare.hpp | 0
purify/nall/string/convert.hpp | 0
purify/nall/string/core.hpp | 0
purify/nall/string/cstring.hpp | 0
purify/nall/string/filename.hpp | 0
purify/nall/string/math-fixed-point.hpp | 0
purify/nall/string/math-floating-point.hpp | 0
purify/nall/string/platform.hpp | 0
purify/nall/string/replace.hpp | 0
purify/nall/string/split.hpp | 0
purify/nall/string/static.hpp | 0
purify/nall/string/strm.hpp | 0
purify/nall/string/strpos.hpp | 0
purify/nall/string/trim.hpp | 0
purify/nall/string/utf8.hpp | 0
purify/nall/string/utility.hpp | 0
purify/nall/string/variadic.hpp | 0
purify/nall/string/wildcard.hpp | 0
purify/nall/string/wrapper.hpp | 0
purify/nall/string/xml-legacy.hpp | 0
purify/nall/string/xml.hpp | 0
purify/nall/traits.hpp | 0
purify/nall/udl.hpp | 0
purify/nall/ups.hpp | 0
purify/nall/utility.hpp | 0
purify/nall/varint.hpp | 0
purify/nall/vector.hpp | 0
purify/nall/windows/detour.hpp | 0
purify/nall/windows/guid.hpp | 0
purify/nall/windows/launcher.hpp | 0
purify/nall/windows/registry.hpp | 0
purify/nall/windows/utf8.hpp | 0
purify/nall/xorg/guard.hpp | 0
purify/nall/xorg/xorg.hpp | 0
purify/nall/zip.hpp | 0
purify/phoenix/Makefile | 0
purify/phoenix/core/core.cpp | 0
purify/phoenix/core/core.hpp | 0
purify/phoenix/core/keyboard.hpp | 0
purify/phoenix/core/layout/fixed-layout.cpp | 0
purify/phoenix/core/layout/fixed-layout.hpp | 0
.../phoenix/core/layout/horizontal-layout.cpp | 0
.../phoenix/core/layout/horizontal-layout.hpp | 0
.../phoenix/core/layout/vertical-layout.cpp | 0
.../phoenix/core/layout/vertical-layout.hpp | 0
purify/phoenix/core/state.hpp | 0
purify/phoenix/gtk/action/action.cpp | 0
purify/phoenix/gtk/action/check-item.cpp | 0
purify/phoenix/gtk/action/item.cpp | 0
purify/phoenix/gtk/action/menu.cpp | 0
purify/phoenix/gtk/action/radio-item.cpp | 0
purify/phoenix/gtk/action/separator.cpp | 0
purify/phoenix/gtk/desktop.cpp | 0
purify/phoenix/gtk/dialog-window.cpp | 0
purify/phoenix/gtk/font.cpp | 0
purify/phoenix/gtk/keyboard.cpp | 0
purify/phoenix/gtk/message-window.cpp | 0
purify/phoenix/gtk/mouse.cpp | 0
purify/phoenix/gtk/platform.cpp | 0
purify/phoenix/gtk/platform.hpp | 0
purify/phoenix/gtk/settings.cpp | 0
purify/phoenix/gtk/timer.cpp | 0
purify/phoenix/gtk/utility.cpp | 0
purify/phoenix/gtk/widget/button.cpp | 0
purify/phoenix/gtk/widget/canvas.cpp | 0
purify/phoenix/gtk/widget/check-box.cpp | 0
purify/phoenix/gtk/widget/combo-box.cpp | 0
purify/phoenix/gtk/widget/hex-edit.cpp | 0
.../gtk/widget/horizontal-scroll-bar.cpp | 0
.../phoenix/gtk/widget/horizontal-slider.cpp | 0
purify/phoenix/gtk/widget/label.cpp | 0
purify/phoenix/gtk/widget/line-edit.cpp | 0
purify/phoenix/gtk/widget/list-view.cpp | 0
purify/phoenix/gtk/widget/progress-bar.cpp | 0
purify/phoenix/gtk/widget/radio-box.cpp | 0
purify/phoenix/gtk/widget/text-edit.cpp | 0
.../gtk/widget/vertical-scroll-bar.cpp | 0
purify/phoenix/gtk/widget/vertical-slider.cpp | 0
purify/phoenix/gtk/widget/viewport.cpp | 0
purify/phoenix/gtk/widget/widget.cpp | 0
purify/phoenix/gtk/window.cpp | 0
purify/phoenix/phoenix.cpp | 0
purify/phoenix/phoenix.hpp | 0
purify/phoenix/qt/action/action.cpp | 0
purify/phoenix/qt/action/check-item.cpp | 0
purify/phoenix/qt/action/item.cpp | 0
purify/phoenix/qt/action/menu.cpp | 0
purify/phoenix/qt/action/radio-item.cpp | 0
purify/phoenix/qt/action/separator.cpp | 0
purify/phoenix/qt/desktop.cpp | 0
purify/phoenix/qt/dialog-window.cpp | 0
purify/phoenix/qt/font.cpp | 0
purify/phoenix/qt/keyboard.cpp | 0
purify/phoenix/qt/message-window.cpp | 0
purify/phoenix/qt/mouse.cpp | 0
purify/phoenix/qt/platform.cpp | 0
purify/phoenix/qt/platform.moc | 0
purify/phoenix/qt/platform.moc.hpp | 0
purify/phoenix/qt/settings.cpp | 0
purify/phoenix/qt/timer.cpp | 0
purify/phoenix/qt/utility.cpp | 0
purify/phoenix/qt/widget/button.cpp | 0
purify/phoenix/qt/widget/canvas.cpp | 0
purify/phoenix/qt/widget/check-box.cpp | 0
purify/phoenix/qt/widget/combo-box.cpp | 0
purify/phoenix/qt/widget/hex-edit.cpp | 0
.../qt/widget/horizontal-scroll-bar.cpp | 0
.../phoenix/qt/widget/horizontal-slider.cpp | 0
purify/phoenix/qt/widget/label.cpp | 0
purify/phoenix/qt/widget/line-edit.cpp | 0
purify/phoenix/qt/widget/list-view.cpp | 0
purify/phoenix/qt/widget/progress-bar.cpp | 0
purify/phoenix/qt/widget/radio-box.cpp | 0
purify/phoenix/qt/widget/text-edit.cpp | 0
.../phoenix/qt/widget/vertical-scroll-bar.cpp | 0
purify/phoenix/qt/widget/vertical-slider.cpp | 0
purify/phoenix/qt/widget/viewport.cpp | 0
purify/phoenix/qt/widget/widget.cpp | 0
purify/phoenix/qt/window.cpp | 0
purify/phoenix/reference/action/action.cpp | 0
.../phoenix/reference/action/check-item.cpp | 0
purify/phoenix/reference/action/item.cpp | 0
purify/phoenix/reference/action/menu.cpp | 0
.../phoenix/reference/action/radio-item.cpp | 0
purify/phoenix/reference/action/separator.cpp | 0
purify/phoenix/reference/desktop.cpp | 0
purify/phoenix/reference/dialog-window.cpp | 0
purify/phoenix/reference/font.cpp | 0
purify/phoenix/reference/keyboard.cpp | 0
purify/phoenix/reference/message-window.cpp | 0
purify/phoenix/reference/mouse.cpp | 0
purify/phoenix/reference/platform.cpp | 0
purify/phoenix/reference/platform.hpp | 0
purify/phoenix/reference/timer.cpp | 0
purify/phoenix/reference/widget/button.cpp | 0
purify/phoenix/reference/widget/canvas.cpp | 0
purify/phoenix/reference/widget/check-box.cpp | 0
purify/phoenix/reference/widget/combo-box.cpp | 0
purify/phoenix/reference/widget/hex-edit.cpp | 0
.../widget/horizontal-scroll-bar.cpp | 0
.../reference/widget/horizontal-slider.cpp | 0
purify/phoenix/reference/widget/label.cpp | 0
purify/phoenix/reference/widget/line-edit.cpp | 0
purify/phoenix/reference/widget/list-view.cpp | 0
.../phoenix/reference/widget/progress-bar.cpp | 0
purify/phoenix/reference/widget/radio-box.cpp | 0
purify/phoenix/reference/widget/text-edit.cpp | 0
.../reference/widget/vertical-scroll-bar.cpp | 0
.../reference/widget/vertical-slider.cpp | 0
purify/phoenix/reference/widget/viewport.cpp | 0
purify/phoenix/reference/widget/widget.cpp | 0
purify/phoenix/reference/window.cpp | 0
purify/phoenix/sync.sh | 0
purify/phoenix/windows/action/action.cpp | 0
purify/phoenix/windows/action/check-item.cpp | 0
purify/phoenix/windows/action/item.cpp | 0
purify/phoenix/windows/action/menu.cpp | 0
purify/phoenix/windows/action/radio-item.cpp | 0
purify/phoenix/windows/action/separator.cpp | 0
purify/phoenix/windows/desktop.cpp | 0
purify/phoenix/windows/dialog-window.cpp | 0
purify/phoenix/windows/font.cpp | 0
purify/phoenix/windows/keyboard.cpp | 0
purify/phoenix/windows/message-window.cpp | 0
purify/phoenix/windows/mouse.cpp | 0
purify/phoenix/windows/object.cpp | 0
purify/phoenix/windows/phoenix.Manifest | 0
purify/phoenix/windows/phoenix.rc | 0
purify/phoenix/windows/platform.cpp | 0
purify/phoenix/windows/platform.hpp | 0
purify/phoenix/windows/settings.cpp | 0
purify/phoenix/windows/timer.cpp | 0
purify/phoenix/windows/utility.cpp | 0
purify/phoenix/windows/widget/button.cpp | 0
purify/phoenix/windows/widget/canvas.cpp | 0
purify/phoenix/windows/widget/check-box.cpp | 0
purify/phoenix/windows/widget/combo-box.cpp | 0
purify/phoenix/windows/widget/hex-edit.cpp | 0
.../windows/widget/horizontal-scroll-bar.cpp | 0
.../windows/widget/horizontal-slider.cpp | 0
purify/phoenix/windows/widget/label.cpp | 0
purify/phoenix/windows/widget/line-edit.cpp | 0
purify/phoenix/windows/widget/list-view.cpp | 0
.../phoenix/windows/widget/progress-bar.cpp | 0
purify/phoenix/windows/widget/radio-box.cpp | 0
purify/phoenix/windows/widget/text-edit.cpp | 0
.../windows/widget/vertical-scroll-bar.cpp | 0
.../windows/widget/vertical-slider.cpp | 0
purify/phoenix/windows/widget/viewport.cpp | 0
purify/phoenix/windows/widget/widget.cpp | 0
purify/phoenix/windows/window.cpp | 0
purify/purify.cpp | 2 +-
purify/resource/applications-system.png | Bin
purify/resource/drive-harddisk.png | Bin
purify/resource/folder.png | Bin
purify/resource/input-gaming.png | Bin
purify/resource/resource.cpp | 0
purify/resource/resource.hpp | 0
purify/resource/resource.xml | 0
purify/resource/view-refresh.png | Bin
snesfilter/HQ2x/HQ2x-RGB555.cpp | 206 ---
snesfilter/HQ2x/HQ2x.cpp | 214 ---
snesfilter/LQ2x/LQ2x.cpp | 52 -
snesfilter/Makefile | 43 -
snesfilter/Phosphor3x/Phosphor3x.cpp | 58 -
snesfilter/Pixellate2x/Pixellate2x.cpp | 36 -
snesfilter/Scale2x/Scale2x.cpp | 51 -
snesfilter/Scanline/Scanline-Dark.cpp | 32 -
snesfilter/Scanline/Scanline-Light.cpp | 33 -
snesfilter/nall/array.hpp | 141 --
snesfilter/nall/bit.hpp | 51 -
snesfilter/nall/moduloarray.hpp | 40 -
snesfilter/nall/platform.hpp | 142 --
snesfilter/nall/reference_array.hpp | 142 --
snesfilter/nall/resource.hpp | 61 -
snesfilter/nall/snes/cartridge.hpp | 792 ----------
snesfilter/nall/snes/cpu.hpp | 458 ------
snesfilter/nall/snes/smp.hpp | 639 --------
snesfilter/nall/sort.hpp | 62 -
snesfilter/nall/stack.hpp | 26 -
snesfilter/nall/static.hpp | 20 -
snesfilter/nall/string/filename.hpp | 62 -
snesfilter/nall/string/math.hpp | 167 ---
snesfilter/nall/string/platform.hpp | 39 -
snesfilter/nall/string/strl.hpp | 51 -
snesfilter/nall/test/cc.bat | 2 -
snesfilter/nall/test/cc.sh | 2 -
snesfilter/nall/test/document.bml | 14 -
snesfilter/nall/test/test | Bin 250304 -> 0 bytes
snesfilter/nall/test/test.cpp | 90 --
snesfilter/nall/varint.hpp | 121 --
snesfilter/nall/vector.hpp | 414 -----
snesfilter/out/.gitignore | 1 -
snesshader/Archive/HDR-TV.OpenGL.shader | 17 -
snesshader/Archive/Watercolor.OpenGL.shader | 61 -
snesshader/Curvature.OpenGL.shader | 22 -
snesshader/HQ2x.OpenGL.shader | 73 -
snesshader/Makefile | 4 -
snesshader/Pixellate.OpenGL.shader | 44 -
snesshader/Scale2x.OpenGL.shader | 55 -
snesshader/Sepia.Direct3D.shader | 30 -
1613 files changed, 31738 insertions(+), 4846 deletions(-)
mode change 100755 => 100644 bsnes/Makefile
mode change 100755 => 100644 bsnes/data/bsnes.Manifest
mode change 100755 => 100644 bsnes/data/bsnes.desktop
mode change 100755 => 100644 bsnes/data/bsnes.ico
mode change 100755 => 100644 bsnes/data/bsnes.png
mode change 100755 => 100644 bsnes/data/cheats.xml
mode change 100755 => 100644 bsnes/data/laevateinn.hpp
mode change 100755 => 100644 bsnes/emulator/emulator.hpp
mode change 100755 => 100644 bsnes/emulator/interface.hpp
mode change 100755 => 100644 bsnes/fc/Makefile
mode change 100755 => 100644 bsnes/fc/apu/apu.cpp
mode change 100755 => 100644 bsnes/fc/apu/apu.hpp
mode change 100755 => 100644 bsnes/fc/apu/dmc.cpp
mode change 100755 => 100644 bsnes/fc/apu/dmc.hpp
mode change 100755 => 100644 bsnes/fc/apu/envelope.cpp
mode change 100755 => 100644 bsnes/fc/apu/envelope.hpp
mode change 100755 => 100644 bsnes/fc/apu/noise.cpp
mode change 100755 => 100644 bsnes/fc/apu/noise.hpp
mode change 100755 => 100644 bsnes/fc/apu/pulse.cpp
mode change 100755 => 100644 bsnes/fc/apu/pulse.hpp
mode change 100755 => 100644 bsnes/fc/apu/serialization.cpp
mode change 100755 => 100644 bsnes/fc/apu/sweep.cpp
mode change 100755 => 100644 bsnes/fc/apu/sweep.hpp
mode change 100755 => 100644 bsnes/fc/apu/triangle.cpp
mode change 100755 => 100644 bsnes/fc/apu/triangle.hpp
mode change 100755 => 100644 bsnes/fc/cartridge/board/bandai-fcg.cpp
mode change 100755 => 100644 bsnes/fc/cartridge/board/board.cpp
mode change 100755 => 100644 bsnes/fc/cartridge/board/board.hpp
mode change 100755 => 100644 bsnes/fc/cartridge/board/konami-vrc1.cpp
mode change 100755 => 100644 bsnes/fc/cartridge/board/konami-vrc2.cpp
mode change 100755 => 100644 bsnes/fc/cartridge/board/konami-vrc3.cpp
mode change 100755 => 100644 bsnes/fc/cartridge/board/konami-vrc4.cpp
mode change 100755 => 100644 bsnes/fc/cartridge/board/konami-vrc6.cpp
mode change 100755 => 100644 bsnes/fc/cartridge/board/konami-vrc7.cpp
mode change 100755 => 100644 bsnes/fc/cartridge/board/nes-axrom.cpp
mode change 100755 => 100644 bsnes/fc/cartridge/board/nes-bnrom.cpp
mode change 100755 => 100644 bsnes/fc/cartridge/board/nes-cnrom.cpp
mode change 100755 => 100644 bsnes/fc/cartridge/board/nes-exrom.cpp
mode change 100755 => 100644 bsnes/fc/cartridge/board/nes-fxrom.cpp
mode change 100755 => 100644 bsnes/fc/cartridge/board/nes-gxrom.cpp
mode change 100755 => 100644 bsnes/fc/cartridge/board/nes-hkrom.cpp
mode change 100755 => 100644 bsnes/fc/cartridge/board/nes-nrom.cpp
mode change 100755 => 100644 bsnes/fc/cartridge/board/nes-pxrom.cpp
mode change 100755 => 100644 bsnes/fc/cartridge/board/nes-sxrom.cpp
mode change 100755 => 100644 bsnes/fc/cartridge/board/nes-txrom.cpp
mode change 100755 => 100644 bsnes/fc/cartridge/board/nes-uxrom.cpp
mode change 100755 => 100644 bsnes/fc/cartridge/board/sunsoft-5b.cpp
mode change 100755 => 100644 bsnes/fc/cartridge/cartridge.cpp
mode change 100755 => 100644 bsnes/fc/cartridge/cartridge.hpp
mode change 100755 => 100644 bsnes/fc/cartridge/chip/chip.cpp
mode change 100755 => 100644 bsnes/fc/cartridge/chip/chip.hpp
mode change 100755 => 100644 bsnes/fc/cartridge/chip/mmc1.cpp
mode change 100755 => 100644 bsnes/fc/cartridge/chip/mmc3.cpp
mode change 100755 => 100644 bsnes/fc/cartridge/chip/mmc5.cpp
mode change 100755 => 100644 bsnes/fc/cartridge/chip/mmc6.cpp
mode change 100755 => 100644 bsnes/fc/cartridge/chip/vrc1.cpp
mode change 100755 => 100644 bsnes/fc/cartridge/chip/vrc2.cpp
mode change 100755 => 100644 bsnes/fc/cartridge/chip/vrc3.cpp
mode change 100755 => 100644 bsnes/fc/cartridge/chip/vrc4.cpp
mode change 100755 => 100644 bsnes/fc/cartridge/chip/vrc6.cpp
mode change 100755 => 100644 bsnes/fc/cartridge/chip/vrc7.cpp
mode change 100755 => 100644 bsnes/fc/cheat/cheat.cpp
mode change 100755 => 100644 bsnes/fc/cheat/cheat.hpp
mode change 100755 => 100644 bsnes/fc/cpu/cpu.cpp
mode change 100755 => 100644 bsnes/fc/cpu/cpu.hpp
mode change 100755 => 100644 bsnes/fc/cpu/serialization.cpp
mode change 100755 => 100644 bsnes/fc/cpu/timing.cpp
mode change 100755 => 100644 bsnes/fc/fc.hpp
mode change 100755 => 100644 bsnes/fc/input/input.cpp
mode change 100755 => 100644 bsnes/fc/input/input.hpp
mode change 100755 => 100644 bsnes/fc/input/serialization.cpp
mode change 100755 => 100644 bsnes/fc/interface/interface.cpp
mode change 100755 => 100644 bsnes/fc/interface/interface.hpp
mode change 100755 => 100644 bsnes/fc/memory/memory.cpp
mode change 100755 => 100644 bsnes/fc/memory/memory.hpp
mode change 100755 => 100644 bsnes/fc/ppu/ppu.cpp
mode change 100755 => 100644 bsnes/fc/ppu/ppu.hpp
mode change 100755 => 100644 bsnes/fc/ppu/serialization.cpp
mode change 100755 => 100644 bsnes/fc/scheduler/scheduler.cpp
mode change 100755 => 100644 bsnes/fc/scheduler/scheduler.hpp
mode change 100755 => 100644 bsnes/fc/system/serialization.cpp
mode change 100755 => 100644 bsnes/fc/system/system.cpp
mode change 100755 => 100644 bsnes/fc/system/system.hpp
mode change 100755 => 100644 bsnes/fc/video/video.cpp
mode change 100755 => 100644 bsnes/fc/video/video.hpp
mode change 100755 => 100644 bsnes/gb/Makefile
mode change 100755 => 100644 bsnes/gb/apu/apu.cpp
mode change 100755 => 100644 bsnes/gb/apu/apu.hpp
mode change 100755 => 100644 bsnes/gb/apu/master/master.cpp
mode change 100755 => 100644 bsnes/gb/apu/master/master.hpp
mode change 100755 => 100644 bsnes/gb/apu/noise/noise.cpp
mode change 100755 => 100644 bsnes/gb/apu/noise/noise.hpp
mode change 100755 => 100644 bsnes/gb/apu/serialization.cpp
mode change 100755 => 100644 bsnes/gb/apu/square1/square1.cpp
mode change 100755 => 100644 bsnes/gb/apu/square1/square1.hpp
mode change 100755 => 100644 bsnes/gb/apu/square2/square2.cpp
mode change 100755 => 100644 bsnes/gb/apu/square2/square2.hpp
mode change 100755 => 100644 bsnes/gb/apu/wave/wave.cpp
mode change 100755 => 100644 bsnes/gb/apu/wave/wave.hpp
mode change 100755 => 100644 bsnes/gb/cartridge/cartridge.cpp
mode change 100755 => 100644 bsnes/gb/cartridge/cartridge.hpp
mode change 100755 => 100644 bsnes/gb/cartridge/huc1/huc1.cpp
mode change 100755 => 100644 bsnes/gb/cartridge/huc1/huc1.hpp
mode change 100755 => 100644 bsnes/gb/cartridge/huc3/huc3.cpp
mode change 100755 => 100644 bsnes/gb/cartridge/huc3/huc3.hpp
mode change 100755 => 100644 bsnes/gb/cartridge/mbc0/mbc0.cpp
mode change 100755 => 100644 bsnes/gb/cartridge/mbc0/mbc0.hpp
mode change 100755 => 100644 bsnes/gb/cartridge/mbc1/mbc1.cpp
mode change 100755 => 100644 bsnes/gb/cartridge/mbc1/mbc1.hpp
mode change 100755 => 100644 bsnes/gb/cartridge/mbc2/mbc2.cpp
mode change 100755 => 100644 bsnes/gb/cartridge/mbc2/mbc2.hpp
mode change 100755 => 100644 bsnes/gb/cartridge/mbc3/mbc3.cpp
mode change 100755 => 100644 bsnes/gb/cartridge/mbc3/mbc3.hpp
mode change 100755 => 100644 bsnes/gb/cartridge/mbc5/mbc5.cpp
mode change 100755 => 100644 bsnes/gb/cartridge/mbc5/mbc5.hpp
mode change 100755 => 100644 bsnes/gb/cartridge/mmm01/mmm01.cpp
mode change 100755 => 100644 bsnes/gb/cartridge/mmm01/mmm01.hpp
mode change 100755 => 100644 bsnes/gb/cartridge/serialization.cpp
mode change 100755 => 100644 bsnes/gb/cheat/cheat.cpp
mode change 100755 => 100644 bsnes/gb/cheat/cheat.hpp
mode change 100755 => 100644 bsnes/gb/cpu/cpu.cpp
mode change 100755 => 100644 bsnes/gb/cpu/cpu.hpp
mode change 100755 => 100644 bsnes/gb/cpu/memory.cpp
mode change 100755 => 100644 bsnes/gb/cpu/mmio.cpp
mode change 100755 => 100644 bsnes/gb/cpu/serialization.cpp
mode change 100755 => 100644 bsnes/gb/cpu/timing.cpp
mode change 100755 => 100644 bsnes/gb/gb.hpp
mode change 100755 => 100644 bsnes/gb/interface/interface.cpp
mode change 100755 => 100644 bsnes/gb/interface/interface.hpp
mode change 100755 => 100644 bsnes/gb/memory/memory.cpp
mode change 100755 => 100644 bsnes/gb/memory/memory.hpp
mode change 100755 => 100644 bsnes/gb/ppu/cgb.cpp
mode change 100755 => 100644 bsnes/gb/ppu/dmg.cpp
mode change 100755 => 100644 bsnes/gb/ppu/mmio.cpp
mode change 100755 => 100644 bsnes/gb/ppu/ppu.cpp
mode change 100755 => 100644 bsnes/gb/ppu/ppu.hpp
mode change 100755 => 100644 bsnes/gb/ppu/serialization.cpp
mode change 100755 => 100644 bsnes/gb/scheduler/scheduler.cpp
mode change 100755 => 100644 bsnes/gb/scheduler/scheduler.hpp
mode change 100755 => 100644 bsnes/gb/system/serialization.cpp
mode change 100755 => 100644 bsnes/gb/system/system.cpp
mode change 100755 => 100644 bsnes/gb/system/system.hpp
mode change 100755 => 100644 bsnes/gb/video/video.cpp
mode change 100755 => 100644 bsnes/gb/video/video.hpp
mode change 100755 => 100644 bsnes/gba/Makefile
mode change 100755 => 100644 bsnes/gba/apu/apu.cpp
mode change 100755 => 100644 bsnes/gba/apu/apu.hpp
mode change 100755 => 100644 bsnes/gba/apu/fifo.cpp
mode change 100755 => 100644 bsnes/gba/apu/mmio.cpp
mode change 100755 => 100644 bsnes/gba/apu/noise.cpp
mode change 100755 => 100644 bsnes/gba/apu/registers.cpp
mode change 100755 => 100644 bsnes/gba/apu/registers.hpp
mode change 100755 => 100644 bsnes/gba/apu/sequencer.cpp
mode change 100755 => 100644 bsnes/gba/apu/serialization.cpp
mode change 100755 => 100644 bsnes/gba/apu/square.cpp
mode change 100755 => 100644 bsnes/gba/apu/square1.cpp
mode change 100755 => 100644 bsnes/gba/apu/square2.cpp
mode change 100755 => 100644 bsnes/gba/apu/wave.cpp
mode change 100755 => 100644 bsnes/gba/cartridge/cartridge.cpp
mode change 100755 => 100644 bsnes/gba/cartridge/cartridge.hpp
mode change 100755 => 100644 bsnes/gba/cartridge/eeprom.cpp
mode change 100755 => 100644 bsnes/gba/cartridge/flashrom.cpp
mode change 100755 => 100644 bsnes/gba/cartridge/memory.hpp
mode change 100755 => 100644 bsnes/gba/cartridge/serialization.cpp
mode change 100755 => 100644 bsnes/gba/cpu/cpu.cpp
mode change 100755 => 100644 bsnes/gba/cpu/cpu.hpp
mode change 100755 => 100644 bsnes/gba/cpu/dma.cpp
mode change 100755 => 100644 bsnes/gba/cpu/memory.cpp
mode change 100755 => 100644 bsnes/gba/cpu/mmio.cpp
mode change 100755 => 100644 bsnes/gba/cpu/registers.cpp
mode change 100755 => 100644 bsnes/gba/cpu/registers.hpp
mode change 100755 => 100644 bsnes/gba/cpu/serialization.cpp
mode change 100755 => 100644 bsnes/gba/cpu/state.hpp
mode change 100755 => 100644 bsnes/gba/cpu/timer.cpp
mode change 100755 => 100644 bsnes/gba/gba.hpp
mode change 100755 => 100644 bsnes/gba/interface/interface.cpp
mode change 100755 => 100644 bsnes/gba/interface/interface.hpp
mode change 100755 => 100644 bsnes/gba/memory/memory.cpp
mode change 100755 => 100644 bsnes/gba/memory/memory.hpp
mode change 100755 => 100644 bsnes/gba/memory/mmio.cpp
mode change 100755 => 100644 bsnes/gba/memory/serialization.cpp
mode change 100755 => 100644 bsnes/gba/ppu/background.cpp
mode change 100755 => 100644 bsnes/gba/ppu/memory.cpp
mode change 100755 => 100644 bsnes/gba/ppu/mmio.cpp
mode change 100755 => 100644 bsnes/gba/ppu/mosaic.cpp
mode change 100755 => 100644 bsnes/gba/ppu/object.cpp
mode change 100755 => 100644 bsnes/gba/ppu/ppu.cpp
mode change 100755 => 100644 bsnes/gba/ppu/ppu.hpp
mode change 100755 => 100644 bsnes/gba/ppu/registers.cpp
mode change 100755 => 100644 bsnes/gba/ppu/registers.hpp
mode change 100755 => 100644 bsnes/gba/ppu/screen.cpp
mode change 100755 => 100644 bsnes/gba/ppu/serialization.cpp
mode change 100755 => 100644 bsnes/gba/ppu/state.hpp
mode change 100755 => 100644 bsnes/gba/scheduler/scheduler.cpp
mode change 100755 => 100644 bsnes/gba/scheduler/scheduler.hpp
mode change 100755 => 100644 bsnes/gba/system/bios.cpp
mode change 100755 => 100644 bsnes/gba/system/serialization.cpp
mode change 100755 => 100644 bsnes/gba/system/system.cpp
mode change 100755 => 100644 bsnes/gba/system/system.hpp
mode change 100755 => 100644 bsnes/gba/video/video.cpp
mode change 100755 => 100644 bsnes/gba/video/video.hpp
mode change 100755 => 100644 bsnes/libco/amd64.c
mode change 100755 => 100644 bsnes/libco/fiber.c
mode change 100755 => 100644 bsnes/libco/libco.c
mode change 100755 => 100644 bsnes/libco/libco.h
mode change 100755 => 100644 bsnes/libco/ppc.c
mode change 100755 => 100644 bsnes/libco/sjlj.c
mode change 100755 => 100644 bsnes/libco/ucontext.c
mode change 100755 => 100644 bsnes/libco/x86.c
mode change 100755 => 100644 bsnes/nall/Makefile
mode change 100755 => 100644 bsnes/nall/algorithm.hpp
mode change 100755 => 100644 bsnes/nall/any.hpp
mode change 100755 => 100644 bsnes/nall/atoi.hpp
mode change 100755 => 100644 bsnes/nall/base64.hpp
mode change 100755 => 100644 bsnes/nall/bit.hpp
mode change 100755 => 100644 bsnes/nall/bmp.hpp
mode change 100755 => 100644 bsnes/nall/bps/delta.hpp
mode change 100755 => 100644 bsnes/nall/bps/linear.hpp
mode change 100755 => 100644 bsnes/nall/bps/metadata.hpp
mode change 100755 => 100644 bsnes/nall/bps/patch.hpp
mode change 100755 => 100644 bsnes/nall/compositor.hpp
mode change 100755 => 100644 bsnes/nall/config.hpp
mode change 100755 => 100644 bsnes/nall/crc32.hpp
mode change 100755 => 100644 bsnes/nall/directory.hpp
mode change 100755 => 100644 bsnes/nall/dl.hpp
mode change 100755 => 100644 bsnes/nall/dsp.hpp
mode change 100755 => 100644 bsnes/nall/dsp/buffer.hpp
mode change 100755 => 100644 bsnes/nall/dsp/core.hpp
mode change 100755 => 100644 bsnes/nall/dsp/resample/average.hpp
mode change 100755 => 100644 bsnes/nall/dsp/resample/cosine.hpp
mode change 100755 => 100644 bsnes/nall/dsp/resample/cubic.hpp
mode change 100755 => 100644 bsnes/nall/dsp/resample/hermite.hpp
mode change 100755 => 100644 bsnes/nall/dsp/resample/lib/sinc.hpp
mode change 100755 => 100644 bsnes/nall/dsp/resample/linear.hpp
mode change 100755 => 100644 bsnes/nall/dsp/resample/nearest.hpp
mode change 100755 => 100644 bsnes/nall/dsp/resample/sinc.hpp
mode change 100755 => 100644 bsnes/nall/dsp/settings.hpp
mode change 100755 => 100644 bsnes/nall/emulation/famicom.hpp
mode change 100755 => 100644 bsnes/nall/emulation/game-boy-advance.hpp
mode change 100755 => 100644 bsnes/nall/emulation/game-boy.hpp
mode change 100755 => 100644 bsnes/nall/emulation/satellaview.hpp
mode change 100755 => 100644 bsnes/nall/emulation/sufami-turbo.hpp
mode change 100755 => 100644 bsnes/nall/emulation/super-famicom-usart.hpp
mode change 100755 => 100644 bsnes/nall/emulation/super-famicom.hpp
mode change 100755 => 100644 bsnes/nall/endian.hpp
mode change 100755 => 100644 bsnes/nall/file.hpp
mode change 100755 => 100644 bsnes/nall/filemap.hpp
mode change 100755 => 100644 bsnes/nall/function.hpp
mode change 100755 => 100644 bsnes/nall/gzip.hpp
mode change 100755 => 100644 bsnes/nall/http.hpp
mode change 100755 => 100644 bsnes/nall/image.hpp
mode change 100755 => 100644 bsnes/nall/inflate.hpp
mode change 100755 => 100644 bsnes/nall/input.hpp
mode change 100755 => 100644 bsnes/nall/interpolation.hpp
mode change 100755 => 100644 bsnes/nall/intrinsics.hpp
mode change 100755 => 100644 bsnes/nall/invoke.hpp
mode change 100755 => 100644 bsnes/nall/ips.hpp
mode change 100755 => 100644 bsnes/nall/lzss.hpp
mode change 100755 => 100644 bsnes/nall/map.hpp
mode change 100755 => 100644 bsnes/nall/mosaic.hpp
mode change 100755 => 100644 bsnes/nall/mosaic/bitstream.hpp
mode change 100755 => 100644 bsnes/nall/mosaic/context.hpp
mode change 100755 => 100644 bsnes/nall/mosaic/parser.hpp
mode change 100755 => 100644 bsnes/nall/nall.hpp
mode change 100755 => 100644 bsnes/nall/platform.hpp
mode change 100755 => 100644 bsnes/nall/png.hpp
mode change 100755 => 100644 bsnes/nall/priority-queue.hpp
mode change 100755 => 100644 bsnes/nall/property.hpp
mode change 100755 => 100644 bsnes/nall/public-cast.hpp
mode change 100755 => 100644 bsnes/nall/random.hpp
mode change 100755 => 100644 bsnes/nall/serial.hpp
mode change 100755 => 100644 bsnes/nall/serializer.hpp
mode change 100755 => 100644 bsnes/nall/set.hpp
mode change 100755 => 100644 bsnes/nall/sha256.hpp
mode change 100755 => 100644 bsnes/nall/sort.hpp
mode change 100755 => 100644 bsnes/nall/stdint.hpp
mode change 100755 => 100644 bsnes/nall/stream.hpp
mode change 100755 => 100644 bsnes/nall/stream/auto.hpp
mode change 100755 => 100644 bsnes/nall/stream/file.hpp
mode change 100755 => 100644 bsnes/nall/stream/gzip.hpp
mode change 100755 => 100644 bsnes/nall/stream/http.hpp
mode change 100755 => 100644 bsnes/nall/stream/memory.hpp
mode change 100755 => 100644 bsnes/nall/stream/mmap.hpp
mode change 100755 => 100644 bsnes/nall/stream/stream.hpp
mode change 100755 => 100644 bsnes/nall/stream/vector.hpp
mode change 100755 => 100644 bsnes/nall/stream/zip.hpp
mode change 100755 => 100644 bsnes/nall/string.hpp
mode change 100755 => 100644 bsnes/nall/string/base.hpp
mode change 100755 => 100644 bsnes/nall/string/bml.hpp
mode change 100755 => 100644 bsnes/nall/string/bsv.hpp
mode change 100755 => 100644 bsnes/nall/string/cast.hpp
mode change 100755 => 100644 bsnes/nall/string/compare.hpp
mode change 100755 => 100644 bsnes/nall/string/convert.hpp
mode change 100755 => 100644 bsnes/nall/string/core.hpp
mode change 100755 => 100644 bsnes/nall/string/cstring.hpp
mode change 100755 => 100644 bsnes/nall/string/filename.hpp
mode change 100755 => 100644 bsnes/nall/string/math-fixed-point.hpp
mode change 100755 => 100644 bsnes/nall/string/math-floating-point.hpp
mode change 100755 => 100644 bsnes/nall/string/platform.hpp
mode change 100755 => 100644 bsnes/nall/string/replace.hpp
mode change 100755 => 100644 bsnes/nall/string/split.hpp
mode change 100755 => 100644 bsnes/nall/string/static.hpp
mode change 100755 => 100644 bsnes/nall/string/strm.hpp
mode change 100755 => 100644 bsnes/nall/string/strpos.hpp
mode change 100755 => 100644 bsnes/nall/string/trim.hpp
mode change 100755 => 100644 bsnes/nall/string/utf8.hpp
mode change 100755 => 100644 bsnes/nall/string/utility.hpp
mode change 100755 => 100644 bsnes/nall/string/variadic.hpp
mode change 100755 => 100644 bsnes/nall/string/wildcard.hpp
mode change 100755 => 100644 bsnes/nall/string/wrapper.hpp
mode change 100755 => 100644 bsnes/nall/string/xml-legacy.hpp
mode change 100755 => 100644 bsnes/nall/string/xml.hpp
mode change 100755 => 100644 bsnes/nall/traits.hpp
mode change 100755 => 100644 bsnes/nall/udl.hpp
mode change 100755 => 100644 bsnes/nall/ups.hpp
mode change 100755 => 100644 bsnes/nall/utility.hpp
mode change 100755 => 100644 bsnes/nall/varint.hpp
mode change 100755 => 100644 bsnes/nall/vector.hpp
mode change 100755 => 100644 bsnes/nall/windows/detour.hpp
mode change 100755 => 100644 bsnes/nall/windows/guid.hpp
mode change 100755 => 100644 bsnes/nall/windows/launcher.hpp
mode change 100755 => 100644 bsnes/nall/windows/registry.hpp
mode change 100755 => 100644 bsnes/nall/windows/utf8.hpp
mode change 100755 => 100644 bsnes/nall/xorg/guard.hpp
mode change 100755 => 100644 bsnes/nall/xorg/xorg.hpp
mode change 100755 => 100644 bsnes/nall/zip.hpp
create mode 100644 bsnes/nds/Makefile
create mode 100644 bsnes/nds/apu/apu.cpp
create mode 100644 bsnes/nds/apu/apu.hpp
create mode 100644 bsnes/nds/cpu/arm.cpp
create mode 100644 bsnes/nds/cpu/arm7tdmi.cpp
create mode 100644 bsnes/nds/cpu/arm946es.cpp
create mode 100644 bsnes/nds/cpu/bit.hpp
create mode 100644 bsnes/nds/cpu/core.cpp
create mode 100644 bsnes/nds/cpu/core.hpp
create mode 100644 bsnes/nds/cpu/cpu.cpp
create mode 100644 bsnes/nds/cpu/cpu.hpp
create mode 100644 bsnes/nds/cpu/disasm.cpp
create mode 100644 bsnes/nds/cpu/dma.cpp
create mode 100644 bsnes/nds/cpu/math.cpp
create mode 100644 bsnes/nds/cpu/message.cpp
create mode 100644 bsnes/nds/cpu/slot.cpp
create mode 100644 bsnes/nds/cpu/thumb.cpp
create mode 100644 bsnes/nds/cpu/timer.cpp
create mode 100644 bsnes/nds/gpu/commands.cpp
create mode 100644 bsnes/nds/gpu/commands.hpp
create mode 100644 bsnes/nds/gpu/geometry.cpp
create mode 100644 bsnes/nds/gpu/geometry.hpp
create mode 100644 bsnes/nds/gpu/gpu.cpp
create mode 100644 bsnes/nds/gpu/gpu.hpp
create mode 100644 bsnes/nds/gpu/math.cpp
create mode 100644 bsnes/nds/gpu/math.hpp
create mode 100644 bsnes/nds/gpu/render.cpp
create mode 100644 bsnes/nds/gpu/render.hpp
create mode 100644 bsnes/nds/gpu/textures.cpp
create mode 100644 bsnes/nds/interface/interface.cpp
create mode 100644 bsnes/nds/interface/interface.hpp
create mode 100644 bsnes/nds/memory/eeprom.cpp
create mode 100644 bsnes/nds/memory/eeprom.hpp
create mode 100644 bsnes/nds/memory/flash.cpp
create mode 100644 bsnes/nds/memory/flash.hpp
create mode 100644 bsnes/nds/memory/fram.cpp
create mode 100644 bsnes/nds/memory/fram.hpp
create mode 100644 bsnes/nds/memory/memory.cpp
create mode 100644 bsnes/nds/memory/memory.hpp
create mode 100644 bsnes/nds/nds.hpp
create mode 100644 bsnes/nds/ppu/bg.cpp
create mode 100644 bsnes/nds/ppu/obj.cpp
create mode 100644 bsnes/nds/ppu/ppu.cpp
create mode 100644 bsnes/nds/ppu/ppu.hpp
create mode 100644 bsnes/nds/slot1/slot1.cpp
create mode 100644 bsnes/nds/slot1/slot1.hpp
create mode 100644 bsnes/nds/slot2/slot2.cpp
create mode 100644 bsnes/nds/slot2/slot2.hpp
create mode 100644 bsnes/nds/system/clock.cpp
create mode 100644 bsnes/nds/system/eventqueue.hpp
create mode 100644 bsnes/nds/system/powermgr.cpp
create mode 100644 bsnes/nds/system/system.cpp
create mode 100644 bsnes/nds/system/system.hpp
create mode 100644 bsnes/nds/system/touchscreen.cpp
create mode 100644 bsnes/nds/video/video.cpp
create mode 100644 bsnes/nds/video/video.hpp
create mode 100644 bsnes/nds/wifi/wifi.cpp
create mode 100644 bsnes/nds/wifi/wifi.hpp
mode change 100755 => 100644 bsnes/phoenix/Makefile
mode change 100755 => 100644 bsnes/phoenix/core/core.cpp
mode change 100755 => 100644 bsnes/phoenix/core/core.hpp
mode change 100755 => 100644 bsnes/phoenix/core/keyboard.hpp
mode change 100755 => 100644 bsnes/phoenix/core/layout/fixed-layout.cpp
mode change 100755 => 100644 bsnes/phoenix/core/layout/fixed-layout.hpp
mode change 100755 => 100644 bsnes/phoenix/core/layout/horizontal-layout.cpp
mode change 100755 => 100644 bsnes/phoenix/core/layout/horizontal-layout.hpp
mode change 100755 => 100644 bsnes/phoenix/core/layout/vertical-layout.cpp
mode change 100755 => 100644 bsnes/phoenix/core/layout/vertical-layout.hpp
mode change 100755 => 100644 bsnes/phoenix/core/state.hpp
mode change 100755 => 100644 bsnes/phoenix/gtk/action/action.cpp
mode change 100755 => 100644 bsnes/phoenix/gtk/action/check-item.cpp
mode change 100755 => 100644 bsnes/phoenix/gtk/action/item.cpp
mode change 100755 => 100644 bsnes/phoenix/gtk/action/menu.cpp
mode change 100755 => 100644 bsnes/phoenix/gtk/action/radio-item.cpp
mode change 100755 => 100644 bsnes/phoenix/gtk/action/separator.cpp
mode change 100755 => 100644 bsnes/phoenix/gtk/desktop.cpp
mode change 100755 => 100644 bsnes/phoenix/gtk/dialog-window.cpp
mode change 100755 => 100644 bsnes/phoenix/gtk/font.cpp
mode change 100755 => 100644 bsnes/phoenix/gtk/keyboard.cpp
mode change 100755 => 100644 bsnes/phoenix/gtk/message-window.cpp
mode change 100755 => 100644 bsnes/phoenix/gtk/mouse.cpp
mode change 100755 => 100644 bsnes/phoenix/gtk/platform.cpp
mode change 100755 => 100644 bsnes/phoenix/gtk/platform.hpp
mode change 100755 => 100644 bsnes/phoenix/gtk/settings.cpp
mode change 100755 => 100644 bsnes/phoenix/gtk/timer.cpp
mode change 100755 => 100644 bsnes/phoenix/gtk/utility.cpp
mode change 100755 => 100644 bsnes/phoenix/gtk/widget/button.cpp
mode change 100755 => 100644 bsnes/phoenix/gtk/widget/canvas.cpp
mode change 100755 => 100644 bsnes/phoenix/gtk/widget/check-box.cpp
mode change 100755 => 100644 bsnes/phoenix/gtk/widget/combo-box.cpp
mode change 100755 => 100644 bsnes/phoenix/gtk/widget/hex-edit.cpp
mode change 100755 => 100644 bsnes/phoenix/gtk/widget/horizontal-scroll-bar.cpp
mode change 100755 => 100644 bsnes/phoenix/gtk/widget/horizontal-slider.cpp
mode change 100755 => 100644 bsnes/phoenix/gtk/widget/label.cpp
mode change 100755 => 100644 bsnes/phoenix/gtk/widget/line-edit.cpp
mode change 100755 => 100644 bsnes/phoenix/gtk/widget/list-view.cpp
mode change 100755 => 100644 bsnes/phoenix/gtk/widget/progress-bar.cpp
mode change 100755 => 100644 bsnes/phoenix/gtk/widget/radio-box.cpp
mode change 100755 => 100644 bsnes/phoenix/gtk/widget/text-edit.cpp
mode change 100755 => 100644 bsnes/phoenix/gtk/widget/vertical-scroll-bar.cpp
mode change 100755 => 100644 bsnes/phoenix/gtk/widget/vertical-slider.cpp
mode change 100755 => 100644 bsnes/phoenix/gtk/widget/viewport.cpp
mode change 100755 => 100644 bsnes/phoenix/gtk/widget/widget.cpp
mode change 100755 => 100644 bsnes/phoenix/gtk/window.cpp
mode change 100755 => 100644 bsnes/phoenix/phoenix.cpp
mode change 100755 => 100644 bsnes/phoenix/phoenix.hpp
mode change 100755 => 100644 bsnes/phoenix/qt/action/action.cpp
mode change 100755 => 100644 bsnes/phoenix/qt/action/check-item.cpp
mode change 100755 => 100644 bsnes/phoenix/qt/action/item.cpp
mode change 100755 => 100644 bsnes/phoenix/qt/action/menu.cpp
mode change 100755 => 100644 bsnes/phoenix/qt/action/radio-item.cpp
mode change 100755 => 100644 bsnes/phoenix/qt/action/separator.cpp
mode change 100755 => 100644 bsnes/phoenix/qt/desktop.cpp
mode change 100755 => 100644 bsnes/phoenix/qt/dialog-window.cpp
mode change 100755 => 100644 bsnes/phoenix/qt/font.cpp
mode change 100755 => 100644 bsnes/phoenix/qt/keyboard.cpp
mode change 100755 => 100644 bsnes/phoenix/qt/message-window.cpp
mode change 100755 => 100644 bsnes/phoenix/qt/mouse.cpp
mode change 100755 => 100644 bsnes/phoenix/qt/platform.cpp
mode change 100755 => 100644 bsnes/phoenix/qt/platform.moc
mode change 100755 => 100644 bsnes/phoenix/qt/platform.moc.hpp
mode change 100755 => 100644 bsnes/phoenix/qt/settings.cpp
mode change 100755 => 100644 bsnes/phoenix/qt/timer.cpp
mode change 100755 => 100644 bsnes/phoenix/qt/utility.cpp
mode change 100755 => 100644 bsnes/phoenix/qt/widget/button.cpp
mode change 100755 => 100644 bsnes/phoenix/qt/widget/canvas.cpp
mode change 100755 => 100644 bsnes/phoenix/qt/widget/check-box.cpp
mode change 100755 => 100644 bsnes/phoenix/qt/widget/combo-box.cpp
mode change 100755 => 100644 bsnes/phoenix/qt/widget/hex-edit.cpp
mode change 100755 => 100644 bsnes/phoenix/qt/widget/horizontal-scroll-bar.cpp
mode change 100755 => 100644 bsnes/phoenix/qt/widget/horizontal-slider.cpp
mode change 100755 => 100644 bsnes/phoenix/qt/widget/label.cpp
mode change 100755 => 100644 bsnes/phoenix/qt/widget/line-edit.cpp
mode change 100755 => 100644 bsnes/phoenix/qt/widget/list-view.cpp
mode change 100755 => 100644 bsnes/phoenix/qt/widget/progress-bar.cpp
mode change 100755 => 100644 bsnes/phoenix/qt/widget/radio-box.cpp
mode change 100755 => 100644 bsnes/phoenix/qt/widget/text-edit.cpp
mode change 100755 => 100644 bsnes/phoenix/qt/widget/vertical-scroll-bar.cpp
mode change 100755 => 100644 bsnes/phoenix/qt/widget/vertical-slider.cpp
mode change 100755 => 100644 bsnes/phoenix/qt/widget/viewport.cpp
mode change 100755 => 100644 bsnes/phoenix/qt/widget/widget.cpp
mode change 100755 => 100644 bsnes/phoenix/qt/window.cpp
mode change 100755 => 100644 bsnes/phoenix/reference/action/action.cpp
mode change 100755 => 100644 bsnes/phoenix/reference/action/check-item.cpp
mode change 100755 => 100644 bsnes/phoenix/reference/action/item.cpp
mode change 100755 => 100644 bsnes/phoenix/reference/action/menu.cpp
mode change 100755 => 100644 bsnes/phoenix/reference/action/radio-item.cpp
mode change 100755 => 100644 bsnes/phoenix/reference/action/separator.cpp
mode change 100755 => 100644 bsnes/phoenix/reference/desktop.cpp
mode change 100755 => 100644 bsnes/phoenix/reference/dialog-window.cpp
mode change 100755 => 100644 bsnes/phoenix/reference/font.cpp
mode change 100755 => 100644 bsnes/phoenix/reference/keyboard.cpp
mode change 100755 => 100644 bsnes/phoenix/reference/message-window.cpp
mode change 100755 => 100644 bsnes/phoenix/reference/mouse.cpp
mode change 100755 => 100644 bsnes/phoenix/reference/platform.cpp
mode change 100755 => 100644 bsnes/phoenix/reference/platform.hpp
mode change 100755 => 100644 bsnes/phoenix/reference/timer.cpp
mode change 100755 => 100644 bsnes/phoenix/reference/widget/button.cpp
mode change 100755 => 100644 bsnes/phoenix/reference/widget/canvas.cpp
mode change 100755 => 100644 bsnes/phoenix/reference/widget/check-box.cpp
mode change 100755 => 100644 bsnes/phoenix/reference/widget/combo-box.cpp
mode change 100755 => 100644 bsnes/phoenix/reference/widget/hex-edit.cpp
mode change 100755 => 100644 bsnes/phoenix/reference/widget/horizontal-scroll-bar.cpp
mode change 100755 => 100644 bsnes/phoenix/reference/widget/horizontal-slider.cpp
mode change 100755 => 100644 bsnes/phoenix/reference/widget/label.cpp
mode change 100755 => 100644 bsnes/phoenix/reference/widget/line-edit.cpp
mode change 100755 => 100644 bsnes/phoenix/reference/widget/list-view.cpp
mode change 100755 => 100644 bsnes/phoenix/reference/widget/progress-bar.cpp
mode change 100755 => 100644 bsnes/phoenix/reference/widget/radio-box.cpp
mode change 100755 => 100644 bsnes/phoenix/reference/widget/text-edit.cpp
mode change 100755 => 100644 bsnes/phoenix/reference/widget/vertical-scroll-bar.cpp
mode change 100755 => 100644 bsnes/phoenix/reference/widget/vertical-slider.cpp
mode change 100755 => 100644 bsnes/phoenix/reference/widget/viewport.cpp
mode change 100755 => 100644 bsnes/phoenix/reference/widget/widget.cpp
mode change 100755 => 100644 bsnes/phoenix/reference/window.cpp
mode change 100755 => 100644 bsnes/phoenix/sync.sh
mode change 100755 => 100644 bsnes/phoenix/windows/action/action.cpp
mode change 100755 => 100644 bsnes/phoenix/windows/action/check-item.cpp
mode change 100755 => 100644 bsnes/phoenix/windows/action/item.cpp
mode change 100755 => 100644 bsnes/phoenix/windows/action/menu.cpp
mode change 100755 => 100644 bsnes/phoenix/windows/action/radio-item.cpp
mode change 100755 => 100644 bsnes/phoenix/windows/action/separator.cpp
mode change 100755 => 100644 bsnes/phoenix/windows/desktop.cpp
mode change 100755 => 100644 bsnes/phoenix/windows/dialog-window.cpp
mode change 100755 => 100644 bsnes/phoenix/windows/font.cpp
mode change 100755 => 100644 bsnes/phoenix/windows/keyboard.cpp
mode change 100755 => 100644 bsnes/phoenix/windows/message-window.cpp
mode change 100755 => 100644 bsnes/phoenix/windows/mouse.cpp
mode change 100755 => 100644 bsnes/phoenix/windows/object.cpp
mode change 100755 => 100644 bsnes/phoenix/windows/phoenix.Manifest
mode change 100755 => 100644 bsnes/phoenix/windows/phoenix.rc
mode change 100755 => 100644 bsnes/phoenix/windows/platform.cpp
mode change 100755 => 100644 bsnes/phoenix/windows/platform.hpp
mode change 100755 => 100644 bsnes/phoenix/windows/settings.cpp
mode change 100755 => 100644 bsnes/phoenix/windows/timer.cpp
mode change 100755 => 100644 bsnes/phoenix/windows/utility.cpp
mode change 100755 => 100644 bsnes/phoenix/windows/widget/button.cpp
mode change 100755 => 100644 bsnes/phoenix/windows/widget/canvas.cpp
mode change 100755 => 100644 bsnes/phoenix/windows/widget/check-box.cpp
mode change 100755 => 100644 bsnes/phoenix/windows/widget/combo-box.cpp
mode change 100755 => 100644 bsnes/phoenix/windows/widget/hex-edit.cpp
mode change 100755 => 100644 bsnes/phoenix/windows/widget/horizontal-scroll-bar.cpp
mode change 100755 => 100644 bsnes/phoenix/windows/widget/horizontal-slider.cpp
mode change 100755 => 100644 bsnes/phoenix/windows/widget/label.cpp
mode change 100755 => 100644 bsnes/phoenix/windows/widget/line-edit.cpp
mode change 100755 => 100644 bsnes/phoenix/windows/widget/list-view.cpp
mode change 100755 => 100644 bsnes/phoenix/windows/widget/progress-bar.cpp
mode change 100755 => 100644 bsnes/phoenix/windows/widget/radio-box.cpp
mode change 100755 => 100644 bsnes/phoenix/windows/widget/text-edit.cpp
mode change 100755 => 100644 bsnes/phoenix/windows/widget/vertical-scroll-bar.cpp
mode change 100755 => 100644 bsnes/phoenix/windows/widget/vertical-slider.cpp
mode change 100755 => 100644 bsnes/phoenix/windows/widget/viewport.cpp
mode change 100755 => 100644 bsnes/phoenix/windows/widget/widget.cpp
mode change 100755 => 100644 bsnes/phoenix/windows/window.cpp
mode change 100755 => 100644 bsnes/processor/Makefile
mode change 100755 => 100644 bsnes/processor/arm/algorithms.cpp
mode change 100755 => 100644 bsnes/processor/arm/arm.cpp
mode change 100755 => 100644 bsnes/processor/arm/arm.hpp
mode change 100755 => 100644 bsnes/processor/arm/disassembler.cpp
mode change 100755 => 100644 bsnes/processor/arm/disassembler.hpp
mode change 100755 => 100644 bsnes/processor/arm/instructions-arm.cpp
mode change 100755 => 100644 bsnes/processor/arm/instructions-arm.hpp
mode change 100755 => 100644 bsnes/processor/arm/instructions-thumb.cpp
mode change 100755 => 100644 bsnes/processor/arm/instructions-thumb.hpp
mode change 100755 => 100644 bsnes/processor/arm/registers.cpp
mode change 100755 => 100644 bsnes/processor/arm/registers.hpp
mode change 100755 => 100644 bsnes/processor/arm/serialization.cpp
mode change 100755 => 100644 bsnes/processor/gsu/gsu.cpp
mode change 100755 => 100644 bsnes/processor/gsu/gsu.hpp
mode change 100755 => 100644 bsnes/processor/gsu/instructions.cpp
mode change 100755 => 100644 bsnes/processor/gsu/registers.hpp
mode change 100755 => 100644 bsnes/processor/gsu/serialization.cpp
mode change 100755 => 100644 bsnes/processor/gsu/table.cpp
mode change 100755 => 100644 bsnes/processor/hg51b/hg51b.cpp
mode change 100755 => 100644 bsnes/processor/hg51b/hg51b.hpp
mode change 100755 => 100644 bsnes/processor/hg51b/instructions.cpp
mode change 100755 => 100644 bsnes/processor/hg51b/registers.cpp
mode change 100755 => 100644 bsnes/processor/hg51b/registers.hpp
mode change 100755 => 100644 bsnes/processor/hg51b/serialization.cpp
mode change 100755 => 100644 bsnes/processor/lr35902/disassembler.cpp
mode change 100755 => 100644 bsnes/processor/lr35902/instructions.cpp
mode change 100755 => 100644 bsnes/processor/lr35902/lr35902.cpp
mode change 100755 => 100644 bsnes/processor/lr35902/lr35902.hpp
mode change 100755 => 100644 bsnes/processor/lr35902/registers.hpp
mode change 100755 => 100644 bsnes/processor/lr35902/serialization.cpp
mode change 100755 => 100644 bsnes/processor/processor.hpp
mode change 100755 => 100644 bsnes/processor/r6502/disassembler.cpp
mode change 100755 => 100644 bsnes/processor/r6502/instructions.cpp
mode change 100755 => 100644 bsnes/processor/r6502/memory.cpp
mode change 100755 => 100644 bsnes/processor/r6502/r6502.cpp
mode change 100755 => 100644 bsnes/processor/r6502/r6502.hpp
mode change 100755 => 100644 bsnes/processor/r6502/registers.hpp
mode change 100755 => 100644 bsnes/processor/r6502/serialization.cpp
mode change 100755 => 100644 bsnes/processor/r65816/algorithms.cpp
mode change 100755 => 100644 bsnes/processor/r65816/disassembler.cpp
mode change 100755 => 100644 bsnes/processor/r65816/disassembler.hpp
mode change 100755 => 100644 bsnes/processor/r65816/memory.hpp
mode change 100755 => 100644 bsnes/processor/r65816/opcode_misc.cpp
mode change 100755 => 100644 bsnes/processor/r65816/opcode_pc.cpp
mode change 100755 => 100644 bsnes/processor/r65816/opcode_read.cpp
mode change 100755 => 100644 bsnes/processor/r65816/opcode_rmw.cpp
mode change 100755 => 100644 bsnes/processor/r65816/opcode_write.cpp
mode change 100755 => 100644 bsnes/processor/r65816/r65816.cpp
mode change 100755 => 100644 bsnes/processor/r65816/r65816.hpp
mode change 100755 => 100644 bsnes/processor/r65816/registers.hpp
mode change 100755 => 100644 bsnes/processor/r65816/serialization.cpp
mode change 100755 => 100644 bsnes/processor/r65816/table.cpp
mode change 100755 => 100644 bsnes/processor/spc700/algorithms.cpp
mode change 100755 => 100644 bsnes/processor/spc700/disassembler.cpp
mode change 100755 => 100644 bsnes/processor/spc700/instructions.cpp
mode change 100755 => 100644 bsnes/processor/spc700/memory.hpp
mode change 100755 => 100644 bsnes/processor/spc700/registers.hpp
mode change 100755 => 100644 bsnes/processor/spc700/serialization.cpp
mode change 100755 => 100644 bsnes/processor/spc700/spc700.cpp
mode change 100755 => 100644 bsnes/processor/spc700/spc700.hpp
mode change 100755 => 100644 bsnes/processor/upd96050/disassembler.cpp
mode change 100755 => 100644 bsnes/processor/upd96050/instructions.cpp
mode change 100755 => 100644 bsnes/processor/upd96050/memory.cpp
mode change 100755 => 100644 bsnes/processor/upd96050/registers.hpp
mode change 100755 => 100644 bsnes/processor/upd96050/serialization.cpp
mode change 100755 => 100644 bsnes/processor/upd96050/upd96050.cpp
mode change 100755 => 100644 bsnes/processor/upd96050/upd96050.hpp
mode change 100755 => 100644 bsnes/profile/BS-X Satellaview.sfc/manifest.xml
mode change 100755 => 100644 bsnes/profile/Famicom.sys/manifest.xml
mode change 100755 => 100644 bsnes/profile/Game Boy Advance.sys/manifest.xml
mode change 100755 => 100644 bsnes/profile/Game Boy Color.sys/boot.rom
mode change 100755 => 100644 bsnes/profile/Game Boy Color.sys/manifest.xml
mode change 100755 => 100644 bsnes/profile/Game Boy.sys/boot.rom
mode change 100755 => 100644 bsnes/profile/Game Boy.sys/manifest.xml
create mode 100644 bsnes/profile/Nintendo DS.sys/manifest.xml
mode change 100755 => 100644 bsnes/profile/Sufami Turbo.sfc/manifest.xml
mode change 100755 => 100644 bsnes/profile/Super Famicom.sys/manifest.xml
mode change 100755 => 100644 bsnes/profile/Super Famicom.sys/spc700.rom
mode change 100755 => 100644 bsnes/profile/Super Game Boy.sfc/boot.rom
mode change 100755 => 100644 bsnes/profile/Super Game Boy.sfc/manifest.xml
mode change 100755 => 100644 bsnes/ruby/Makefile
mode change 100755 => 100644 bsnes/ruby/audio.hpp
mode change 100755 => 100644 bsnes/ruby/audio/alsa.cpp
mode change 100755 => 100644 bsnes/ruby/audio/ao.cpp
mode change 100755 => 100644 bsnes/ruby/audio/directsound.cpp
mode change 100755 => 100644 bsnes/ruby/audio/openal.cpp
mode change 100755 => 100644 bsnes/ruby/audio/oss.cpp
mode change 100755 => 100644 bsnes/ruby/audio/pulseaudio.cpp
mode change 100755 => 100644 bsnes/ruby/audio/pulseaudiosimple.cpp
mode change 100755 => 100644 bsnes/ruby/audio/xaudio2.cpp
mode change 100755 => 100644 bsnes/ruby/audio/xaudio2.hpp
mode change 100755 => 100644 bsnes/ruby/input.hpp
mode change 100755 => 100644 bsnes/ruby/input/carbon.cpp
mode change 100755 => 100644 bsnes/ruby/input/directinput.cpp
mode change 100755 => 100644 bsnes/ruby/input/rawinput.cpp
mode change 100755 => 100644 bsnes/ruby/input/sdl.cpp
mode change 100755 => 100644 bsnes/ruby/input/x.cpp
mode change 100755 => 100644 bsnes/ruby/input/xlibkeys.hpp
mode change 100755 => 100644 bsnes/ruby/ruby.cpp
mode change 100755 => 100644 bsnes/ruby/ruby.hpp
mode change 100755 => 100644 bsnes/ruby/ruby_impl.cpp
mode change 100755 => 100644 bsnes/ruby/video.hpp
mode change 100755 => 100644 bsnes/ruby/video/direct3d.cpp
mode change 100755 => 100644 bsnes/ruby/video/directdraw.cpp
mode change 100755 => 100644 bsnes/ruby/video/gdi.cpp
mode change 100755 => 100644 bsnes/ruby/video/glx.cpp
mode change 100755 => 100644 bsnes/ruby/video/opengl.hpp
mode change 100755 => 100644 bsnes/ruby/video/qtopengl.cpp
mode change 100755 => 100644 bsnes/ruby/video/qtraster.cpp
mode change 100755 => 100644 bsnes/ruby/video/sdl.cpp
mode change 100755 => 100644 bsnes/ruby/video/wgl.cpp
mode change 100755 => 100644 bsnes/ruby/video/xshm.cpp
mode change 100755 => 100644 bsnes/ruby/video/xv.cpp
mode change 100755 => 100644 bsnes/sfc/Makefile
mode change 100755 => 100644 bsnes/sfc/alt/cpu/cpu.cpp
mode change 100755 => 100644 bsnes/sfc/alt/cpu/cpu.hpp
mode change 100755 => 100644 bsnes/sfc/alt/cpu/dma.cpp
mode change 100755 => 100644 bsnes/sfc/alt/cpu/memory.cpp
mode change 100755 => 100644 bsnes/sfc/alt/cpu/mmio.cpp
mode change 100755 => 100644 bsnes/sfc/alt/cpu/serialization.cpp
mode change 100755 => 100644 bsnes/sfc/alt/cpu/timing.cpp
mode change 100755 => 100644 bsnes/sfc/alt/dsp/SPC_DSP.cpp
mode change 100755 => 100644 bsnes/sfc/alt/dsp/SPC_DSP.h
mode change 100755 => 100644 bsnes/sfc/alt/dsp/blargg_common.h
mode change 100755 => 100644 bsnes/sfc/alt/dsp/blargg_config.h
mode change 100755 => 100644 bsnes/sfc/alt/dsp/blargg_endian.h
mode change 100755 => 100644 bsnes/sfc/alt/dsp/blargg_source.h
mode change 100755 => 100644 bsnes/sfc/alt/dsp/dsp.cpp
mode change 100755 => 100644 bsnes/sfc/alt/dsp/dsp.hpp
mode change 100755 => 100644 bsnes/sfc/alt/dsp/serialization.cpp
mode change 100755 => 100644 bsnes/sfc/alt/ppu-compatibility/memory/memory.cpp
mode change 100755 => 100644 bsnes/sfc/alt/ppu-compatibility/memory/memory.hpp
mode change 100755 => 100644 bsnes/sfc/alt/ppu-compatibility/mmio/mmio.cpp
mode change 100755 => 100644 bsnes/sfc/alt/ppu-compatibility/mmio/mmio.hpp
mode change 100755 => 100644 bsnes/sfc/alt/ppu-compatibility/ppu.cpp
mode change 100755 => 100644 bsnes/sfc/alt/ppu-compatibility/ppu.hpp
mode change 100755 => 100644 bsnes/sfc/alt/ppu-compatibility/render/addsub.cpp
mode change 100755 => 100644 bsnes/sfc/alt/ppu-compatibility/render/bg.cpp
mode change 100755 => 100644 bsnes/sfc/alt/ppu-compatibility/render/cache.cpp
mode change 100755 => 100644 bsnes/sfc/alt/ppu-compatibility/render/line.cpp
mode change 100755 => 100644 bsnes/sfc/alt/ppu-compatibility/render/mode7.cpp
mode change 100755 => 100644 bsnes/sfc/alt/ppu-compatibility/render/oam.cpp
mode change 100755 => 100644 bsnes/sfc/alt/ppu-compatibility/render/render.cpp
mode change 100755 => 100644 bsnes/sfc/alt/ppu-compatibility/render/render.hpp
mode change 100755 => 100644 bsnes/sfc/alt/ppu-compatibility/render/windows.cpp
mode change 100755 => 100644 bsnes/sfc/alt/ppu-compatibility/serialization.cpp
mode change 100755 => 100644 bsnes/sfc/alt/ppu-performance/background/background.cpp
mode change 100755 => 100644 bsnes/sfc/alt/ppu-performance/background/background.hpp
mode change 100755 => 100644 bsnes/sfc/alt/ppu-performance/background/mode7.cpp
mode change 100755 => 100644 bsnes/sfc/alt/ppu-performance/cache/cache.cpp
mode change 100755 => 100644 bsnes/sfc/alt/ppu-performance/cache/cache.hpp
mode change 100755 => 100644 bsnes/sfc/alt/ppu-performance/mmio/mmio.cpp
mode change 100755 => 100644 bsnes/sfc/alt/ppu-performance/mmio/mmio.hpp
mode change 100755 => 100644 bsnes/sfc/alt/ppu-performance/ppu.cpp
mode change 100755 => 100644 bsnes/sfc/alt/ppu-performance/ppu.hpp
mode change 100755 => 100644 bsnes/sfc/alt/ppu-performance/screen/screen.cpp
mode change 100755 => 100644 bsnes/sfc/alt/ppu-performance/screen/screen.hpp
mode change 100755 => 100644 bsnes/sfc/alt/ppu-performance/serialization.cpp
mode change 100755 => 100644 bsnes/sfc/alt/ppu-performance/sprite/sprite.cpp
mode change 100755 => 100644 bsnes/sfc/alt/ppu-performance/sprite/sprite.hpp
mode change 100755 => 100644 bsnes/sfc/alt/ppu-performance/window/window.cpp
mode change 100755 => 100644 bsnes/sfc/alt/ppu-performance/window/window.hpp
mode change 100755 => 100644 bsnes/sfc/alt/smp/algorithms.cpp
mode change 100755 => 100644 bsnes/sfc/alt/smp/core.cpp
mode change 100755 => 100644 bsnes/sfc/alt/smp/core/cc.sh
mode change 100755 => 100644 bsnes/sfc/alt/smp/core/generate.cpp
mode change 100755 => 100644 bsnes/sfc/alt/smp/core/op_misc.b
mode change 100755 => 100644 bsnes/sfc/alt/smp/core/op_misc.cpp
mode change 100755 => 100644 bsnes/sfc/alt/smp/core/op_mov.b
mode change 100755 => 100644 bsnes/sfc/alt/smp/core/op_mov.cpp
mode change 100755 => 100644 bsnes/sfc/alt/smp/core/op_pc.b
mode change 100755 => 100644 bsnes/sfc/alt/smp/core/op_pc.cpp
mode change 100755 => 100644 bsnes/sfc/alt/smp/core/op_read.b
mode change 100755 => 100644 bsnes/sfc/alt/smp/core/op_read.cpp
mode change 100755 => 100644 bsnes/sfc/alt/smp/core/op_rmw.b
mode change 100755 => 100644 bsnes/sfc/alt/smp/core/op_rmw.cpp
mode change 100755 => 100644 bsnes/sfc/alt/smp/core/opcycle_misc.cpp
mode change 100755 => 100644 bsnes/sfc/alt/smp/core/opcycle_mov.cpp
mode change 100755 => 100644 bsnes/sfc/alt/smp/core/opcycle_pc.cpp
mode change 100755 => 100644 bsnes/sfc/alt/smp/core/opcycle_read.cpp
mode change 100755 => 100644 bsnes/sfc/alt/smp/core/opcycle_rmw.cpp
mode change 100755 => 100644 bsnes/sfc/alt/smp/disassembler.cpp
mode change 100755 => 100644 bsnes/sfc/alt/smp/memory.cpp
mode change 100755 => 100644 bsnes/sfc/alt/smp/smp.cpp
mode change 100755 => 100644 bsnes/sfc/alt/smp/smp.hpp
mode change 100755 => 100644 bsnes/sfc/alt/smp/timing.cpp
mode change 100755 => 100644 bsnes/sfc/cartridge/cartridge.cpp
mode change 100755 => 100644 bsnes/sfc/cartridge/cartridge.hpp
mode change 100755 => 100644 bsnes/sfc/cartridge/markup.cpp
mode change 100755 => 100644 bsnes/sfc/cartridge/serialization.cpp
mode change 100755 => 100644 bsnes/sfc/cheat/cheat.cpp
mode change 100755 => 100644 bsnes/sfc/cheat/cheat.hpp
mode change 100755 => 100644 bsnes/sfc/chip/armdsp/armdsp.cpp
mode change 100755 => 100644 bsnes/sfc/chip/armdsp/armdsp.hpp
mode change 100755 => 100644 bsnes/sfc/chip/armdsp/memory.cpp
mode change 100755 => 100644 bsnes/sfc/chip/armdsp/registers.hpp
mode change 100755 => 100644 bsnes/sfc/chip/armdsp/serialization.cpp
mode change 100755 => 100644 bsnes/sfc/chip/bsx/bsx.cpp
mode change 100755 => 100644 bsnes/sfc/chip/bsx/bsx.hpp
mode change 100755 => 100644 bsnes/sfc/chip/bsx/cartridge/cartridge.cpp
mode change 100755 => 100644 bsnes/sfc/chip/bsx/cartridge/cartridge.hpp
mode change 100755 => 100644 bsnes/sfc/chip/bsx/cartridge/serialization.cpp
mode change 100755 => 100644 bsnes/sfc/chip/bsx/flash/flash.cpp
mode change 100755 => 100644 bsnes/sfc/chip/bsx/flash/flash.hpp
mode change 100755 => 100644 bsnes/sfc/chip/bsx/satellaview/satellaview.cpp
mode change 100755 => 100644 bsnes/sfc/chip/bsx/satellaview/satellaview.hpp
mode change 100755 => 100644 bsnes/sfc/chip/chip.hpp
mode change 100755 => 100644 bsnes/sfc/chip/epsonrtc/epsonrtc.cpp
mode change 100755 => 100644 bsnes/sfc/chip/epsonrtc/epsonrtc.hpp
mode change 100755 => 100644 bsnes/sfc/chip/epsonrtc/memory.cpp
mode change 100755 => 100644 bsnes/sfc/chip/epsonrtc/serialization.cpp
mode change 100755 => 100644 bsnes/sfc/chip/epsonrtc/time.cpp
mode change 100755 => 100644 bsnes/sfc/chip/hitachidsp/hitachidsp.cpp
mode change 100755 => 100644 bsnes/sfc/chip/hitachidsp/hitachidsp.hpp
mode change 100755 => 100644 bsnes/sfc/chip/hitachidsp/memory.cpp
mode change 100755 => 100644 bsnes/sfc/chip/hitachidsp/mmio.hpp
mode change 100755 => 100644 bsnes/sfc/chip/hitachidsp/serialization.cpp
mode change 100755 => 100644 bsnes/sfc/chip/icd2/icd2.cpp
mode change 100755 => 100644 bsnes/sfc/chip/icd2/icd2.hpp
mode change 100755 => 100644 bsnes/sfc/chip/icd2/interface/interface.cpp
mode change 100755 => 100644 bsnes/sfc/chip/icd2/interface/interface.hpp
mode change 100755 => 100644 bsnes/sfc/chip/icd2/mmio/mmio.cpp
mode change 100755 => 100644 bsnes/sfc/chip/icd2/mmio/mmio.hpp
mode change 100755 => 100644 bsnes/sfc/chip/icd2/serialization.cpp
mode change 100755 => 100644 bsnes/sfc/chip/msu1/msu1.cpp
mode change 100755 => 100644 bsnes/sfc/chip/msu1/msu1.hpp
mode change 100755 => 100644 bsnes/sfc/chip/msu1/serialization.cpp
mode change 100755 => 100644 bsnes/sfc/chip/necdsp/necdsp.cpp
mode change 100755 => 100644 bsnes/sfc/chip/necdsp/necdsp.hpp
mode change 100755 => 100644 bsnes/sfc/chip/necdsp/serialization.cpp
mode change 100755 => 100644 bsnes/sfc/chip/nss/nss.cpp
mode change 100755 => 100644 bsnes/sfc/chip/nss/nss.hpp
mode change 100755 => 100644 bsnes/sfc/chip/obc1/obc1.cpp
mode change 100755 => 100644 bsnes/sfc/chip/obc1/obc1.hpp
mode change 100755 => 100644 bsnes/sfc/chip/obc1/serialization.cpp
mode change 100755 => 100644 bsnes/sfc/chip/sa1/bus/bus.cpp
mode change 100755 => 100644 bsnes/sfc/chip/sa1/bus/bus.hpp
mode change 100755 => 100644 bsnes/sfc/chip/sa1/dma/dma.cpp
mode change 100755 => 100644 bsnes/sfc/chip/sa1/dma/dma.hpp
mode change 100755 => 100644 bsnes/sfc/chip/sa1/memory/memory.cpp
mode change 100755 => 100644 bsnes/sfc/chip/sa1/memory/memory.hpp
mode change 100755 => 100644 bsnes/sfc/chip/sa1/mmio/mmio.cpp
mode change 100755 => 100644 bsnes/sfc/chip/sa1/mmio/mmio.hpp
mode change 100755 => 100644 bsnes/sfc/chip/sa1/sa1.cpp
mode change 100755 => 100644 bsnes/sfc/chip/sa1/sa1.hpp
mode change 100755 => 100644 bsnes/sfc/chip/sa1/serialization.cpp
mode change 100755 => 100644 bsnes/sfc/chip/sdd1/decomp.cpp
mode change 100755 => 100644 bsnes/sfc/chip/sdd1/decomp.hpp
mode change 100755 => 100644 bsnes/sfc/chip/sdd1/sdd1.cpp
mode change 100755 => 100644 bsnes/sfc/chip/sdd1/sdd1.hpp
mode change 100755 => 100644 bsnes/sfc/chip/sdd1/serialization.cpp
mode change 100755 => 100644 bsnes/sfc/chip/sharprtc/memory.cpp
mode change 100755 => 100644 bsnes/sfc/chip/sharprtc/serialization.cpp
mode change 100755 => 100644 bsnes/sfc/chip/sharprtc/sharprtc.cpp
mode change 100755 => 100644 bsnes/sfc/chip/sharprtc/sharprtc.hpp
mode change 100755 => 100644 bsnes/sfc/chip/sharprtc/time.cpp
mode change 100755 => 100644 bsnes/sfc/chip/spc7110/alu.cpp
mode change 100755 => 100644 bsnes/sfc/chip/spc7110/data.cpp
mode change 100755 => 100644 bsnes/sfc/chip/spc7110/dcu.cpp
mode change 100755 => 100644 bsnes/sfc/chip/spc7110/decompressor.cpp
mode change 100755 => 100644 bsnes/sfc/chip/spc7110/serialization.cpp
mode change 100755 => 100644 bsnes/sfc/chip/spc7110/spc7110.cpp
mode change 100755 => 100644 bsnes/sfc/chip/spc7110/spc7110.hpp
mode change 100755 => 100644 bsnes/sfc/chip/sufamiturbo/serialization.cpp
mode change 100755 => 100644 bsnes/sfc/chip/sufamiturbo/sufamiturbo.cpp
mode change 100755 => 100644 bsnes/sfc/chip/sufamiturbo/sufamiturbo.hpp
mode change 100755 => 100644 bsnes/sfc/chip/superfx/bus/bus.cpp
mode change 100755 => 100644 bsnes/sfc/chip/superfx/bus/bus.hpp
mode change 100755 => 100644 bsnes/sfc/chip/superfx/core/core.cpp
mode change 100755 => 100644 bsnes/sfc/chip/superfx/core/core.hpp
mode change 100755 => 100644 bsnes/sfc/chip/superfx/disasm/disasm.cpp
mode change 100755 => 100644 bsnes/sfc/chip/superfx/disasm/disasm.hpp
mode change 100755 => 100644 bsnes/sfc/chip/superfx/memory/memory.cpp
mode change 100755 => 100644 bsnes/sfc/chip/superfx/memory/memory.hpp
mode change 100755 => 100644 bsnes/sfc/chip/superfx/mmio/mmio.cpp
mode change 100755 => 100644 bsnes/sfc/chip/superfx/mmio/mmio.hpp
mode change 100755 => 100644 bsnes/sfc/chip/superfx/serialization.cpp
mode change 100755 => 100644 bsnes/sfc/chip/superfx/superfx.cpp
mode change 100755 => 100644 bsnes/sfc/chip/superfx/superfx.hpp
mode change 100755 => 100644 bsnes/sfc/chip/superfx/timing/timing.cpp
mode change 100755 => 100644 bsnes/sfc/chip/superfx/timing/timing.hpp
mode change 100755 => 100644 bsnes/sfc/config/config.cpp
mode change 100755 => 100644 bsnes/sfc/config/config.hpp
mode change 100755 => 100644 bsnes/sfc/controller/controller.cpp
mode change 100755 => 100644 bsnes/sfc/controller/controller.hpp
mode change 100755 => 100644 bsnes/sfc/controller/gamepad/gamepad.cpp
mode change 100755 => 100644 bsnes/sfc/controller/gamepad/gamepad.hpp
mode change 100755 => 100644 bsnes/sfc/controller/justifier/justifier.cpp
mode change 100755 => 100644 bsnes/sfc/controller/justifier/justifier.hpp
mode change 100755 => 100644 bsnes/sfc/controller/mouse/mouse.cpp
mode change 100755 => 100644 bsnes/sfc/controller/mouse/mouse.hpp
mode change 100755 => 100644 bsnes/sfc/controller/multitap/multitap.cpp
mode change 100755 => 100644 bsnes/sfc/controller/multitap/multitap.hpp
mode change 100755 => 100644 bsnes/sfc/controller/superscope/superscope.cpp
mode change 100755 => 100644 bsnes/sfc/controller/superscope/superscope.hpp
mode change 100755 => 100644 bsnes/sfc/controller/usart/usart.cpp
mode change 100755 => 100644 bsnes/sfc/controller/usart/usart.hpp
mode change 100755 => 100644 bsnes/sfc/cpu/cpu.cpp
mode change 100755 => 100644 bsnes/sfc/cpu/cpu.hpp
mode change 100755 => 100644 bsnes/sfc/cpu/dma/dma.cpp
mode change 100755 => 100644 bsnes/sfc/cpu/dma/dma.hpp
mode change 100755 => 100644 bsnes/sfc/cpu/memory/memory.cpp
mode change 100755 => 100644 bsnes/sfc/cpu/memory/memory.hpp
mode change 100755 => 100644 bsnes/sfc/cpu/mmio/mmio.cpp
mode change 100755 => 100644 bsnes/sfc/cpu/mmio/mmio.hpp
mode change 100755 => 100644 bsnes/sfc/cpu/serialization.cpp
mode change 100755 => 100644 bsnes/sfc/cpu/timing/irq.cpp
mode change 100755 => 100644 bsnes/sfc/cpu/timing/joypad.cpp
mode change 100755 => 100644 bsnes/sfc/cpu/timing/timing.cpp
mode change 100755 => 100644 bsnes/sfc/cpu/timing/timing.hpp
mode change 100755 => 100644 bsnes/sfc/dsp/brr.cpp
mode change 100755 => 100644 bsnes/sfc/dsp/counter.cpp
mode change 100755 => 100644 bsnes/sfc/dsp/dsp.cpp
mode change 100755 => 100644 bsnes/sfc/dsp/dsp.hpp
mode change 100755 => 100644 bsnes/sfc/dsp/echo.cpp
mode change 100755 => 100644 bsnes/sfc/dsp/envelope.cpp
mode change 100755 => 100644 bsnes/sfc/dsp/gaussian.cpp
mode change 100755 => 100644 bsnes/sfc/dsp/misc.cpp
mode change 100755 => 100644 bsnes/sfc/dsp/moduloarray.hpp
mode change 100755 => 100644 bsnes/sfc/dsp/serialization.cpp
mode change 100755 => 100644 bsnes/sfc/dsp/voice.cpp
mode change 100755 => 100644 bsnes/sfc/interface/interface.cpp
mode change 100755 => 100644 bsnes/sfc/interface/interface.hpp
mode change 100755 => 100644 bsnes/sfc/memory/memory-inline.hpp
mode change 100755 => 100644 bsnes/sfc/memory/memory.cpp
mode change 100755 => 100644 bsnes/sfc/memory/memory.hpp
mode change 100755 => 100644 bsnes/sfc/ppu/background/background.cpp
mode change 100755 => 100644 bsnes/sfc/ppu/background/background.hpp
mode change 100755 => 100644 bsnes/sfc/ppu/background/mode7.cpp
mode change 100755 => 100644 bsnes/sfc/ppu/counter/counter-inline.hpp
mode change 100755 => 100644 bsnes/sfc/ppu/counter/counter.hpp
mode change 100755 => 100644 bsnes/sfc/ppu/mmio/mmio.cpp
mode change 100755 => 100644 bsnes/sfc/ppu/mmio/mmio.hpp
mode change 100755 => 100644 bsnes/sfc/ppu/ppu.cpp
mode change 100755 => 100644 bsnes/sfc/ppu/ppu.hpp
mode change 100755 => 100644 bsnes/sfc/ppu/screen/screen.cpp
mode change 100755 => 100644 bsnes/sfc/ppu/screen/screen.hpp
mode change 100755 => 100644 bsnes/sfc/ppu/serialization.cpp
mode change 100755 => 100644 bsnes/sfc/ppu/sprite/list.cpp
mode change 100755 => 100644 bsnes/sfc/ppu/sprite/sprite.cpp
mode change 100755 => 100644 bsnes/sfc/ppu/sprite/sprite.hpp
mode change 100755 => 100644 bsnes/sfc/ppu/window/window.cpp
mode change 100755 => 100644 bsnes/sfc/ppu/window/window.hpp
mode change 100755 => 100644 bsnes/sfc/profile-accuracy.hpp
mode change 100755 => 100644 bsnes/sfc/profile-compatibility.hpp
mode change 100755 => 100644 bsnes/sfc/profile-performance.hpp
mode change 100755 => 100644 bsnes/sfc/random/random.cpp
mode change 100755 => 100644 bsnes/sfc/random/random.hpp
mode change 100755 => 100644 bsnes/sfc/scheduler/scheduler.cpp
mode change 100755 => 100644 bsnes/sfc/scheduler/scheduler.hpp
mode change 100755 => 100644 bsnes/sfc/sfc.hpp
mode change 100755 => 100644 bsnes/sfc/smp/memory.cpp
mode change 100755 => 100644 bsnes/sfc/smp/serialization.cpp
mode change 100755 => 100644 bsnes/sfc/smp/smp.cpp
mode change 100755 => 100644 bsnes/sfc/smp/smp.hpp
mode change 100755 => 100644 bsnes/sfc/smp/timing.cpp
mode change 100755 => 100644 bsnes/sfc/system/audio.cpp
mode change 100755 => 100644 bsnes/sfc/system/audio.hpp
mode change 100755 => 100644 bsnes/sfc/system/input.cpp
mode change 100755 => 100644 bsnes/sfc/system/input.hpp
mode change 100755 => 100644 bsnes/sfc/system/serialization.cpp
mode change 100755 => 100644 bsnes/sfc/system/system.cpp
mode change 100755 => 100644 bsnes/sfc/system/system.hpp
mode change 100755 => 100644 bsnes/sfc/system/video.cpp
mode change 100755 => 100644 bsnes/sfc/system/video.hpp
mode change 100755 => 100644 bsnes/target-ethos/Makefile
mode change 100755 => 100644 bsnes/target-ethos/bootstrap.cpp
mode change 100755 => 100644 bsnes/target-ethos/configuration/configuration.cpp
mode change 100755 => 100644 bsnes/target-ethos/configuration/configuration.hpp
mode change 100755 => 100644 bsnes/target-ethos/ethos.cpp
mode change 100755 => 100644 bsnes/target-ethos/ethos.hpp
mode change 100755 => 100644 bsnes/target-ethos/general/browser.cpp
mode change 100755 => 100644 bsnes/target-ethos/general/browser.hpp
mode change 100755 => 100644 bsnes/target-ethos/general/dip-switches.cpp
mode change 100755 => 100644 bsnes/target-ethos/general/dip-switches.hpp
mode change 100755 => 100644 bsnes/target-ethos/general/general.cpp
mode change 100755 => 100644 bsnes/target-ethos/general/general.hpp
mode change 100755 => 100644 bsnes/target-ethos/general/presentation.cpp
mode change 100755 => 100644 bsnes/target-ethos/general/presentation.hpp
mode change 100755 => 100644 bsnes/target-ethos/input/hotkeys.cpp
mode change 100755 => 100644 bsnes/target-ethos/input/input.cpp
mode change 100755 => 100644 bsnes/target-ethos/input/input.hpp
mode change 100755 => 100644 bsnes/target-ethos/interface/interface.cpp
mode change 100755 => 100644 bsnes/target-ethos/interface/interface.hpp
mode change 100755 => 100644 bsnes/target-ethos/resource.rc
mode change 100755 => 100644 bsnes/target-ethos/resource/folder.png
mode change 100755 => 100644 bsnes/target-ethos/resource/game.png
mode change 100755 => 100644 bsnes/target-ethos/resource/home.png
mode change 100755 => 100644 bsnes/target-ethos/resource/resource.cpp
mode change 100755 => 100644 bsnes/target-ethos/resource/resource.hpp
mode change 100755 => 100644 bsnes/target-ethos/resource/resource.xml
mode change 100755 => 100644 bsnes/target-ethos/resource/up.png
mode change 100755 => 100644 bsnes/target-ethos/settings/audio.cpp
mode change 100755 => 100644 bsnes/target-ethos/settings/audio.hpp
mode change 100755 => 100644 bsnes/target-ethos/settings/driver.cpp
mode change 100755 => 100644 bsnes/target-ethos/settings/driver.hpp
mode change 100755 => 100644 bsnes/target-ethos/settings/hotkey.cpp
mode change 100755 => 100644 bsnes/target-ethos/settings/hotkey.hpp
mode change 100755 => 100644 bsnes/target-ethos/settings/input.cpp
mode change 100755 => 100644 bsnes/target-ethos/settings/input.hpp
mode change 100755 => 100644 bsnes/target-ethos/settings/settings.cpp
mode change 100755 => 100644 bsnes/target-ethos/settings/settings.hpp
mode change 100755 => 100644 bsnes/target-ethos/settings/timing.cpp
mode change 100755 => 100644 bsnes/target-ethos/settings/timing.hpp
mode change 100755 => 100644 bsnes/target-ethos/settings/video.cpp
mode change 100755 => 100644 bsnes/target-ethos/settings/video.hpp
mode change 100755 => 100644 bsnes/target-ethos/tools/cheat-database.cpp
mode change 100755 => 100644 bsnes/target-ethos/tools/cheat-database.hpp
mode change 100755 => 100644 bsnes/target-ethos/tools/cheat-editor.cpp
mode change 100755 => 100644 bsnes/target-ethos/tools/cheat-editor.hpp
mode change 100755 => 100644 bsnes/target-ethos/tools/state-manager.cpp
mode change 100755 => 100644 bsnes/target-ethos/tools/state-manager.hpp
mode change 100755 => 100644 bsnes/target-ethos/tools/tools.cpp
mode change 100755 => 100644 bsnes/target-ethos/tools/tools.hpp
mode change 100755 => 100644 bsnes/target-ethos/utility/utility.cpp
mode change 100755 => 100644 bsnes/target-ethos/utility/utility.hpp
mode change 100755 => 100644 bsnes/target-ethos/window/window.cpp
mode change 100755 => 100644 bsnes/target-ethos/window/window.hpp
mode change 100755 => 100644 bsnes/target-laevateinn/Makefile
mode change 100755 => 100644 bsnes/target-laevateinn/base.hpp
mode change 100755 => 100644 bsnes/target-laevateinn/breakpoint/breakpoint.cpp
mode change 100755 => 100644 bsnes/target-laevateinn/breakpoint/breakpoint.hpp
mode change 100755 => 100644 bsnes/target-laevateinn/console/about.cpp
mode change 100755 => 100644 bsnes/target-laevateinn/console/console.cpp
mode change 100755 => 100644 bsnes/target-laevateinn/console/console.hpp
mode change 100755 => 100644 bsnes/target-laevateinn/cpu/cpu.cpp
mode change 100755 => 100644 bsnes/target-laevateinn/cpu/cpu.hpp
mode change 100755 => 100644 bsnes/target-laevateinn/cpu/registers.cpp
mode change 100755 => 100644 bsnes/target-laevateinn/debugger/debugger.cpp
mode change 100755 => 100644 bsnes/target-laevateinn/debugger/debugger.hpp
mode change 100755 => 100644 bsnes/target-laevateinn/debugger/hook.cpp
mode change 100755 => 100644 bsnes/target-laevateinn/debugger/usage.cpp
mode change 100755 => 100644 bsnes/target-laevateinn/interface/interface.cpp
mode change 100755 => 100644 bsnes/target-laevateinn/interface/interface.hpp
mode change 100755 => 100644 bsnes/target-laevateinn/main.cpp
mode change 100755 => 100644 bsnes/target-laevateinn/memory/memory.cpp
mode change 100755 => 100644 bsnes/target-laevateinn/memory/memory.hpp
mode change 100755 => 100644 bsnes/target-laevateinn/properties/properties.cpp
mode change 100755 => 100644 bsnes/target-laevateinn/properties/properties.hpp
mode change 100755 => 100644 bsnes/target-laevateinn/resource.rc
mode change 100755 => 100644 bsnes/target-laevateinn/settings/settings.cpp
mode change 100755 => 100644 bsnes/target-laevateinn/settings/settings.hpp
mode change 100755 => 100644 bsnes/target-laevateinn/smp/registers.cpp
mode change 100755 => 100644 bsnes/target-laevateinn/smp/smp.cpp
mode change 100755 => 100644 bsnes/target-laevateinn/smp/smp.hpp
mode change 100755 => 100644 bsnes/target-laevateinn/tracer/tracer.cpp
mode change 100755 => 100644 bsnes/target-laevateinn/tracer/tracer.hpp
mode change 100755 => 100644 bsnes/target-laevateinn/video/video.cpp
mode change 100755 => 100644 bsnes/target-laevateinn/video/video.hpp
mode change 100755 => 100644 bsnes/target-laevateinn/vram/vram.cpp
mode change 100755 => 100644 bsnes/target-laevateinn/vram/vram.hpp
mode change 100755 => 100644 bsnes/target-laevateinn/window/window.cpp
mode change 100755 => 100644 bsnes/target-laevateinn/window/window.hpp
create mode 100644 kaijuu/Makefile
create mode 100755 kaijuu/cc32.bat
create mode 100755 kaijuu/cc64.bat
create mode 100644 kaijuu/extension.cpp
create mode 100644 kaijuu/extension.hpp
create mode 100644 kaijuu/factory.cpp
create mode 100644 kaijuu/factory.hpp
create mode 100644 kaijuu/guid.hpp
create mode 100644 kaijuu/interface.cpp
create mode 100644 kaijuu/interface.hpp
create mode 100644 kaijuu/kaijuu.Manifest
create mode 100644 kaijuu/kaijuu.cpp
create mode 100644 kaijuu/kaijuu.def
create mode 100644 kaijuu/kaijuu.hpp
create mode 100644 kaijuu/kaijuu.html
create mode 100644 kaijuu/kaijuu.rc
rename {snesfilter => kaijuu}/nall/Makefile (90%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/algorithm.hpp (100%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/any.hpp (84%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/atoi.hpp (82%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/base64.hpp (100%)
mode change 100755 => 100644
create mode 100644 kaijuu/nall/bit.hpp
rename {snesfilter => kaijuu}/nall/bmp.hpp (100%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/bps/delta.hpp (100%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/bps/linear.hpp (100%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/bps/metadata.hpp (100%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/bps/patch.hpp (100%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/compositor.hpp (100%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/config.hpp (76%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/crc32.hpp (100%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/directory.hpp (77%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/dl.hpp (100%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/dsp.hpp (100%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/dsp/buffer.hpp (100%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/dsp/core.hpp (100%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/dsp/resample/average.hpp (100%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/dsp/resample/cosine.hpp (100%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/dsp/resample/cubic.hpp (100%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/dsp/resample/hermite.hpp (100%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/dsp/resample/lib/sinc.hpp (100%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/dsp/resample/linear.hpp (100%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/dsp/resample/nearest.hpp (100%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/dsp/resample/sinc.hpp (100%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/dsp/settings.hpp (100%)
mode change 100755 => 100644
create mode 100644 kaijuu/nall/emulation/famicom.hpp
create mode 100644 kaijuu/nall/emulation/game-boy-advance.hpp
rename snesfilter/nall/gameboy/cartridge.hpp => kaijuu/nall/emulation/game-boy.hpp (85%)
mode change 100755 => 100644
create mode 100644 kaijuu/nall/emulation/satellaview.hpp
create mode 100644 kaijuu/nall/emulation/sufami-turbo.hpp
create mode 100644 kaijuu/nall/emulation/super-famicom-usart.hpp
create mode 100644 kaijuu/nall/emulation/super-famicom.hpp
rename {snesfilter => kaijuu}/nall/endian.hpp (100%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/file.hpp (81%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/filemap.hpp (99%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/function.hpp (100%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/gzip.hpp (83%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/http.hpp (99%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/image.hpp (75%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/inflate.hpp (100%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/input.hpp (100%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/interpolation.hpp (91%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/intrinsics.hpp (100%)
mode change 100755 => 100644
create mode 100644 kaijuu/nall/invoke.hpp
rename {snesfilter => kaijuu}/nall/ips.hpp (89%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/lzss.hpp (100%)
mode change 100755 => 100644
create mode 100644 kaijuu/nall/map.hpp
create mode 100644 kaijuu/nall/mosaic.hpp
create mode 100644 kaijuu/nall/mosaic/bitstream.hpp
create mode 100644 kaijuu/nall/mosaic/context.hpp
create mode 100644 kaijuu/nall/mosaic/parser.hpp
create mode 100644 kaijuu/nall/nall.hpp
create mode 100644 kaijuu/nall/platform.hpp
rename {snesfilter => kaijuu}/nall/png.hpp (98%)
mode change 100755 => 100644
rename snesfilter/nall/priorityqueue.hpp => kaijuu/nall/priority-queue.hpp (97%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/property.hpp (100%)
mode change 100755 => 100644
rename snesfilter/nall/public_cast.hpp => kaijuu/nall/public-cast.hpp (100%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/random.hpp (100%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/serial.hpp (73%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/serializer.hpp (94%)
mode change 100755 => 100644
create mode 100644 kaijuu/nall/set.hpp
rename {snesfilter => kaijuu}/nall/sha256.hpp (100%)
mode change 100755 => 100644
create mode 100644 kaijuu/nall/sort.hpp
rename {snesfilter => kaijuu}/nall/stdint.hpp (97%)
mode change 100755 => 100644
create mode 100644 kaijuu/nall/stream.hpp
create mode 100644 kaijuu/nall/stream/auto.hpp
create mode 100644 kaijuu/nall/stream/file.hpp
create mode 100644 kaijuu/nall/stream/gzip.hpp
create mode 100644 kaijuu/nall/stream/http.hpp
create mode 100644 kaijuu/nall/stream/memory.hpp
create mode 100644 kaijuu/nall/stream/mmap.hpp
create mode 100644 kaijuu/nall/stream/stream.hpp
create mode 100644 kaijuu/nall/stream/vector.hpp
create mode 100644 kaijuu/nall/stream/zip.hpp
rename {snesfilter => kaijuu}/nall/string.hpp (92%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/string/base.hpp (87%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/string/bml.hpp (97%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/string/bsv.hpp (100%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/string/cast.hpp (100%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/string/compare.hpp (100%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/string/convert.hpp (100%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/string/core.hpp (76%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/string/cstring.hpp (100%)
mode change 100755 => 100644
create mode 100644 kaijuu/nall/string/filename.hpp
rename {snesfilter => kaijuu}/nall/string/math-fixed-point.hpp (96%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/string/math-floating-point.hpp (96%)
mode change 100755 => 100644
create mode 100644 kaijuu/nall/string/platform.hpp
rename {snesfilter => kaijuu}/nall/string/replace.hpp (100%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/string/split.hpp (100%)
mode change 100755 => 100644
create mode 100644 kaijuu/nall/string/static.hpp
create mode 100644 kaijuu/nall/string/strm.hpp
rename {snesfilter => kaijuu}/nall/string/strpos.hpp (100%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/string/trim.hpp (100%)
mode change 100755 => 100644
create mode 100644 kaijuu/nall/string/utf8.hpp
rename {snesfilter => kaijuu}/nall/string/utility.hpp (94%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/string/variadic.hpp (100%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/string/wildcard.hpp (100%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/string/wrapper.hpp (97%)
mode change 100755 => 100644
rename snesfilter/nall/string/xml.hpp => kaijuu/nall/string/xml-legacy.hpp (100%)
mode change 100755 => 100644
create mode 100644 kaijuu/nall/string/xml.hpp
create mode 100644 kaijuu/nall/traits.hpp
create mode 100644 kaijuu/nall/udl.hpp
rename {snesfilter => kaijuu}/nall/ups.hpp (100%)
mode change 100755 => 100644
rename {snesfilter => kaijuu}/nall/utility.hpp (71%)
mode change 100755 => 100644
create mode 100644 kaijuu/nall/varint.hpp
create mode 100644 kaijuu/nall/vector.hpp
rename {snesfilter => kaijuu}/nall/windows/detour.hpp (100%)
mode change 100755 => 100644
create mode 100644 kaijuu/nall/windows/guid.hpp
rename {snesfilter => kaijuu}/nall/windows/launcher.hpp (100%)
mode change 100755 => 100644
create mode 100644 kaijuu/nall/windows/registry.hpp
rename {snesfilter => kaijuu}/nall/windows/utf8.hpp (98%)
mode change 100755 => 100644
create mode 100644 kaijuu/nall/xorg/guard.hpp
create mode 100644 kaijuu/nall/xorg/xorg.hpp
rename {snesfilter => kaijuu}/nall/zip.hpp (79%)
mode change 100755 => 100644
create mode 100644 kaijuu/phoenix/Makefile
create mode 100644 kaijuu/phoenix/core/core.cpp
create mode 100644 kaijuu/phoenix/core/core.hpp
create mode 100644 kaijuu/phoenix/core/keyboard.hpp
create mode 100644 kaijuu/phoenix/core/layout/fixed-layout.cpp
create mode 100644 kaijuu/phoenix/core/layout/fixed-layout.hpp
create mode 100644 kaijuu/phoenix/core/layout/horizontal-layout.cpp
create mode 100644 kaijuu/phoenix/core/layout/horizontal-layout.hpp
create mode 100644 kaijuu/phoenix/core/layout/vertical-layout.cpp
create mode 100644 kaijuu/phoenix/core/layout/vertical-layout.hpp
create mode 100644 kaijuu/phoenix/core/state.hpp
create mode 100644 kaijuu/phoenix/gtk/action/action.cpp
create mode 100644 kaijuu/phoenix/gtk/action/check-item.cpp
create mode 100644 kaijuu/phoenix/gtk/action/item.cpp
create mode 100644 kaijuu/phoenix/gtk/action/menu.cpp
create mode 100644 kaijuu/phoenix/gtk/action/radio-item.cpp
create mode 100644 kaijuu/phoenix/gtk/action/separator.cpp
create mode 100644 kaijuu/phoenix/gtk/desktop.cpp
create mode 100644 kaijuu/phoenix/gtk/dialog-window.cpp
create mode 100644 kaijuu/phoenix/gtk/font.cpp
create mode 100644 kaijuu/phoenix/gtk/keyboard.cpp
create mode 100644 kaijuu/phoenix/gtk/message-window.cpp
create mode 100644 kaijuu/phoenix/gtk/mouse.cpp
create mode 100644 kaijuu/phoenix/gtk/platform.cpp
create mode 100644 kaijuu/phoenix/gtk/platform.hpp
create mode 100644 kaijuu/phoenix/gtk/settings.cpp
create mode 100644 kaijuu/phoenix/gtk/timer.cpp
create mode 100644 kaijuu/phoenix/gtk/utility.cpp
create mode 100644 kaijuu/phoenix/gtk/widget/button.cpp
create mode 100644 kaijuu/phoenix/gtk/widget/canvas.cpp
create mode 100644 kaijuu/phoenix/gtk/widget/check-box.cpp
create mode 100644 kaijuu/phoenix/gtk/widget/combo-box.cpp
create mode 100644 kaijuu/phoenix/gtk/widget/hex-edit.cpp
create mode 100644 kaijuu/phoenix/gtk/widget/horizontal-scroll-bar.cpp
create mode 100644 kaijuu/phoenix/gtk/widget/horizontal-slider.cpp
create mode 100644 kaijuu/phoenix/gtk/widget/label.cpp
create mode 100644 kaijuu/phoenix/gtk/widget/line-edit.cpp
create mode 100644 kaijuu/phoenix/gtk/widget/list-view.cpp
create mode 100644 kaijuu/phoenix/gtk/widget/progress-bar.cpp
create mode 100644 kaijuu/phoenix/gtk/widget/radio-box.cpp
create mode 100644 kaijuu/phoenix/gtk/widget/text-edit.cpp
create mode 100644 kaijuu/phoenix/gtk/widget/vertical-scroll-bar.cpp
create mode 100644 kaijuu/phoenix/gtk/widget/vertical-slider.cpp
create mode 100644 kaijuu/phoenix/gtk/widget/viewport.cpp
create mode 100644 kaijuu/phoenix/gtk/widget/widget.cpp
create mode 100644 kaijuu/phoenix/gtk/window.cpp
create mode 100644 kaijuu/phoenix/phoenix.cpp
create mode 100644 kaijuu/phoenix/phoenix.hpp
create mode 100644 kaijuu/phoenix/qt/action/action.cpp
create mode 100644 kaijuu/phoenix/qt/action/check-item.cpp
create mode 100644 kaijuu/phoenix/qt/action/item.cpp
create mode 100644 kaijuu/phoenix/qt/action/menu.cpp
create mode 100644 kaijuu/phoenix/qt/action/radio-item.cpp
create mode 100644 kaijuu/phoenix/qt/action/separator.cpp
create mode 100644 kaijuu/phoenix/qt/desktop.cpp
create mode 100644 kaijuu/phoenix/qt/dialog-window.cpp
create mode 100644 kaijuu/phoenix/qt/font.cpp
create mode 100644 kaijuu/phoenix/qt/keyboard.cpp
create mode 100644 kaijuu/phoenix/qt/message-window.cpp
create mode 100644 kaijuu/phoenix/qt/mouse.cpp
create mode 100644 kaijuu/phoenix/qt/platform.cpp
create mode 100644 kaijuu/phoenix/qt/platform.moc
create mode 100644 kaijuu/phoenix/qt/platform.moc.hpp
create mode 100644 kaijuu/phoenix/qt/settings.cpp
create mode 100644 kaijuu/phoenix/qt/timer.cpp
create mode 100644 kaijuu/phoenix/qt/utility.cpp
create mode 100644 kaijuu/phoenix/qt/widget/button.cpp
create mode 100644 kaijuu/phoenix/qt/widget/canvas.cpp
create mode 100644 kaijuu/phoenix/qt/widget/check-box.cpp
create mode 100644 kaijuu/phoenix/qt/widget/combo-box.cpp
create mode 100644 kaijuu/phoenix/qt/widget/hex-edit.cpp
create mode 100644 kaijuu/phoenix/qt/widget/horizontal-scroll-bar.cpp
create mode 100644 kaijuu/phoenix/qt/widget/horizontal-slider.cpp
create mode 100644 kaijuu/phoenix/qt/widget/label.cpp
create mode 100644 kaijuu/phoenix/qt/widget/line-edit.cpp
create mode 100644 kaijuu/phoenix/qt/widget/list-view.cpp
create mode 100644 kaijuu/phoenix/qt/widget/progress-bar.cpp
create mode 100644 kaijuu/phoenix/qt/widget/radio-box.cpp
create mode 100644 kaijuu/phoenix/qt/widget/text-edit.cpp
create mode 100644 kaijuu/phoenix/qt/widget/vertical-scroll-bar.cpp
create mode 100644 kaijuu/phoenix/qt/widget/vertical-slider.cpp
create mode 100644 kaijuu/phoenix/qt/widget/viewport.cpp
create mode 100644 kaijuu/phoenix/qt/widget/widget.cpp
create mode 100644 kaijuu/phoenix/qt/window.cpp
create mode 100644 kaijuu/phoenix/reference/action/action.cpp
create mode 100644 kaijuu/phoenix/reference/action/check-item.cpp
create mode 100644 kaijuu/phoenix/reference/action/item.cpp
create mode 100644 kaijuu/phoenix/reference/action/menu.cpp
create mode 100644 kaijuu/phoenix/reference/action/radio-item.cpp
create mode 100644 kaijuu/phoenix/reference/action/separator.cpp
create mode 100644 kaijuu/phoenix/reference/desktop.cpp
create mode 100644 kaijuu/phoenix/reference/dialog-window.cpp
create mode 100644 kaijuu/phoenix/reference/font.cpp
create mode 100644 kaijuu/phoenix/reference/keyboard.cpp
create mode 100644 kaijuu/phoenix/reference/message-window.cpp
create mode 100644 kaijuu/phoenix/reference/mouse.cpp
create mode 100644 kaijuu/phoenix/reference/platform.cpp
create mode 100644 kaijuu/phoenix/reference/platform.hpp
create mode 100644 kaijuu/phoenix/reference/timer.cpp
create mode 100644 kaijuu/phoenix/reference/widget/button.cpp
create mode 100644 kaijuu/phoenix/reference/widget/canvas.cpp
create mode 100644 kaijuu/phoenix/reference/widget/check-box.cpp
create mode 100644 kaijuu/phoenix/reference/widget/combo-box.cpp
create mode 100644 kaijuu/phoenix/reference/widget/hex-edit.cpp
create mode 100644 kaijuu/phoenix/reference/widget/horizontal-scroll-bar.cpp
create mode 100644 kaijuu/phoenix/reference/widget/horizontal-slider.cpp
create mode 100644 kaijuu/phoenix/reference/widget/label.cpp
create mode 100644 kaijuu/phoenix/reference/widget/line-edit.cpp
create mode 100644 kaijuu/phoenix/reference/widget/list-view.cpp
create mode 100644 kaijuu/phoenix/reference/widget/progress-bar.cpp
create mode 100644 kaijuu/phoenix/reference/widget/radio-box.cpp
create mode 100644 kaijuu/phoenix/reference/widget/text-edit.cpp
create mode 100644 kaijuu/phoenix/reference/widget/vertical-scroll-bar.cpp
create mode 100644 kaijuu/phoenix/reference/widget/vertical-slider.cpp
create mode 100644 kaijuu/phoenix/reference/widget/viewport.cpp
create mode 100644 kaijuu/phoenix/reference/widget/widget.cpp
create mode 100644 kaijuu/phoenix/reference/window.cpp
rename {snesfilter => kaijuu/phoenix}/sync.sh (88%)
mode change 100755 => 100644
create mode 100644 kaijuu/phoenix/windows/action/action.cpp
create mode 100644 kaijuu/phoenix/windows/action/check-item.cpp
create mode 100644 kaijuu/phoenix/windows/action/item.cpp
create mode 100644 kaijuu/phoenix/windows/action/menu.cpp
create mode 100644 kaijuu/phoenix/windows/action/radio-item.cpp
create mode 100644 kaijuu/phoenix/windows/action/separator.cpp
create mode 100644 kaijuu/phoenix/windows/desktop.cpp
create mode 100644 kaijuu/phoenix/windows/dialog-window.cpp
create mode 100644 kaijuu/phoenix/windows/font.cpp
create mode 100644 kaijuu/phoenix/windows/keyboard.cpp
create mode 100644 kaijuu/phoenix/windows/message-window.cpp
create mode 100644 kaijuu/phoenix/windows/mouse.cpp
create mode 100644 kaijuu/phoenix/windows/object.cpp
create mode 100644 kaijuu/phoenix/windows/phoenix.Manifest
create mode 100644 kaijuu/phoenix/windows/phoenix.rc
create mode 100644 kaijuu/phoenix/windows/platform.cpp
create mode 100644 kaijuu/phoenix/windows/platform.hpp
create mode 100644 kaijuu/phoenix/windows/settings.cpp
create mode 100644 kaijuu/phoenix/windows/timer.cpp
create mode 100644 kaijuu/phoenix/windows/utility.cpp
create mode 100644 kaijuu/phoenix/windows/widget/button.cpp
create mode 100644 kaijuu/phoenix/windows/widget/canvas.cpp
create mode 100644 kaijuu/phoenix/windows/widget/check-box.cpp
create mode 100644 kaijuu/phoenix/windows/widget/combo-box.cpp
create mode 100644 kaijuu/phoenix/windows/widget/hex-edit.cpp
create mode 100644 kaijuu/phoenix/windows/widget/horizontal-scroll-bar.cpp
create mode 100644 kaijuu/phoenix/windows/widget/horizontal-slider.cpp
create mode 100644 kaijuu/phoenix/windows/widget/label.cpp
create mode 100644 kaijuu/phoenix/windows/widget/line-edit.cpp
create mode 100644 kaijuu/phoenix/windows/widget/list-view.cpp
create mode 100644 kaijuu/phoenix/windows/widget/progress-bar.cpp
create mode 100644 kaijuu/phoenix/windows/widget/radio-box.cpp
create mode 100644 kaijuu/phoenix/windows/widget/text-edit.cpp
create mode 100644 kaijuu/phoenix/windows/widget/vertical-scroll-bar.cpp
create mode 100644 kaijuu/phoenix/windows/widget/vertical-slider.cpp
create mode 100644 kaijuu/phoenix/windows/widget/viewport.cpp
create mode 100644 kaijuu/phoenix/windows/widget/widget.cpp
create mode 100644 kaijuu/phoenix/windows/window.cpp
create mode 100644 kaijuu/resource/kaijuu.png
create mode 100644 kaijuu/resource/resource.cpp
create mode 100644 kaijuu/resource/resource.hpp
create mode 100644 kaijuu/resource/resource.xml
create mode 100644 kaijuu/settings.hpp
create mode 100644 kaijuu/sync.sh
mode change 100755 => 100644 purify/Makefile
mode change 100755 => 100644 purify/nall/Makefile
mode change 100755 => 100644 purify/nall/algorithm.hpp
mode change 100755 => 100644 purify/nall/any.hpp
mode change 100755 => 100644 purify/nall/atoi.hpp
mode change 100755 => 100644 purify/nall/base64.hpp
mode change 100755 => 100644 purify/nall/bit.hpp
mode change 100755 => 100644 purify/nall/bmp.hpp
mode change 100755 => 100644 purify/nall/bps/delta.hpp
mode change 100755 => 100644 purify/nall/bps/linear.hpp
mode change 100755 => 100644 purify/nall/bps/metadata.hpp
mode change 100755 => 100644 purify/nall/bps/patch.hpp
mode change 100755 => 100644 purify/nall/compositor.hpp
mode change 100755 => 100644 purify/nall/config.hpp
mode change 100755 => 100644 purify/nall/crc32.hpp
mode change 100755 => 100644 purify/nall/directory.hpp
mode change 100755 => 100644 purify/nall/dl.hpp
mode change 100755 => 100644 purify/nall/dsp.hpp
mode change 100755 => 100644 purify/nall/dsp/buffer.hpp
mode change 100755 => 100644 purify/nall/dsp/core.hpp
mode change 100755 => 100644 purify/nall/dsp/resample/average.hpp
mode change 100755 => 100644 purify/nall/dsp/resample/cosine.hpp
mode change 100755 => 100644 purify/nall/dsp/resample/cubic.hpp
mode change 100755 => 100644 purify/nall/dsp/resample/hermite.hpp
mode change 100755 => 100644 purify/nall/dsp/resample/lib/sinc.hpp
mode change 100755 => 100644 purify/nall/dsp/resample/linear.hpp
mode change 100755 => 100644 purify/nall/dsp/resample/nearest.hpp
mode change 100755 => 100644 purify/nall/dsp/resample/sinc.hpp
mode change 100755 => 100644 purify/nall/dsp/settings.hpp
mode change 100755 => 100644 purify/nall/emulation/famicom.hpp
mode change 100755 => 100644 purify/nall/emulation/game-boy-advance.hpp
mode change 100755 => 100644 purify/nall/emulation/game-boy.hpp
mode change 100755 => 100644 purify/nall/emulation/satellaview.hpp
mode change 100755 => 100644 purify/nall/emulation/sufami-turbo.hpp
mode change 100755 => 100644 purify/nall/emulation/super-famicom-usart.hpp
mode change 100755 => 100644 purify/nall/emulation/super-famicom.hpp
mode change 100755 => 100644 purify/nall/endian.hpp
mode change 100755 => 100644 purify/nall/file.hpp
mode change 100755 => 100644 purify/nall/filemap.hpp
mode change 100755 => 100644 purify/nall/function.hpp
mode change 100755 => 100644 purify/nall/gzip.hpp
mode change 100755 => 100644 purify/nall/http.hpp
mode change 100755 => 100644 purify/nall/image.hpp
mode change 100755 => 100644 purify/nall/inflate.hpp
mode change 100755 => 100644 purify/nall/input.hpp
mode change 100755 => 100644 purify/nall/interpolation.hpp
mode change 100755 => 100644 purify/nall/intrinsics.hpp
mode change 100755 => 100644 purify/nall/invoke.hpp
mode change 100755 => 100644 purify/nall/ips.hpp
mode change 100755 => 100644 purify/nall/lzss.hpp
mode change 100755 => 100644 purify/nall/map.hpp
mode change 100755 => 100644 purify/nall/mosaic.hpp
mode change 100755 => 100644 purify/nall/mosaic/bitstream.hpp
mode change 100755 => 100644 purify/nall/mosaic/context.hpp
mode change 100755 => 100644 purify/nall/mosaic/parser.hpp
mode change 100755 => 100644 purify/nall/nall.hpp
mode change 100755 => 100644 purify/nall/platform.hpp
mode change 100755 => 100644 purify/nall/png.hpp
mode change 100755 => 100644 purify/nall/priority-queue.hpp
mode change 100755 => 100644 purify/nall/property.hpp
mode change 100755 => 100644 purify/nall/public-cast.hpp
mode change 100755 => 100644 purify/nall/random.hpp
mode change 100755 => 100644 purify/nall/serial.hpp
mode change 100755 => 100644 purify/nall/serializer.hpp
mode change 100755 => 100644 purify/nall/set.hpp
mode change 100755 => 100644 purify/nall/sha256.hpp
mode change 100755 => 100644 purify/nall/sort.hpp
mode change 100755 => 100644 purify/nall/stdint.hpp
mode change 100755 => 100644 purify/nall/stream.hpp
mode change 100755 => 100644 purify/nall/stream/auto.hpp
mode change 100755 => 100644 purify/nall/stream/file.hpp
mode change 100755 => 100644 purify/nall/stream/gzip.hpp
mode change 100755 => 100644 purify/nall/stream/http.hpp
mode change 100755 => 100644 purify/nall/stream/memory.hpp
mode change 100755 => 100644 purify/nall/stream/mmap.hpp
mode change 100755 => 100644 purify/nall/stream/stream.hpp
mode change 100755 => 100644 purify/nall/stream/vector.hpp
mode change 100755 => 100644 purify/nall/stream/zip.hpp
mode change 100755 => 100644 purify/nall/string.hpp
mode change 100755 => 100644 purify/nall/string/base.hpp
mode change 100755 => 100644 purify/nall/string/bml.hpp
mode change 100755 => 100644 purify/nall/string/bsv.hpp
mode change 100755 => 100644 purify/nall/string/cast.hpp
mode change 100755 => 100644 purify/nall/string/compare.hpp
mode change 100755 => 100644 purify/nall/string/convert.hpp
mode change 100755 => 100644 purify/nall/string/core.hpp
mode change 100755 => 100644 purify/nall/string/cstring.hpp
mode change 100755 => 100644 purify/nall/string/filename.hpp
mode change 100755 => 100644 purify/nall/string/math-fixed-point.hpp
mode change 100755 => 100644 purify/nall/string/math-floating-point.hpp
mode change 100755 => 100644 purify/nall/string/platform.hpp
mode change 100755 => 100644 purify/nall/string/replace.hpp
mode change 100755 => 100644 purify/nall/string/split.hpp
mode change 100755 => 100644 purify/nall/string/static.hpp
mode change 100755 => 100644 purify/nall/string/strm.hpp
mode change 100755 => 100644 purify/nall/string/strpos.hpp
mode change 100755 => 100644 purify/nall/string/trim.hpp
mode change 100755 => 100644 purify/nall/string/utf8.hpp
mode change 100755 => 100644 purify/nall/string/utility.hpp
mode change 100755 => 100644 purify/nall/string/variadic.hpp
mode change 100755 => 100644 purify/nall/string/wildcard.hpp
mode change 100755 => 100644 purify/nall/string/wrapper.hpp
mode change 100755 => 100644 purify/nall/string/xml-legacy.hpp
mode change 100755 => 100644 purify/nall/string/xml.hpp
mode change 100755 => 100644 purify/nall/traits.hpp
mode change 100755 => 100644 purify/nall/udl.hpp
mode change 100755 => 100644 purify/nall/ups.hpp
mode change 100755 => 100644 purify/nall/utility.hpp
mode change 100755 => 100644 purify/nall/varint.hpp
mode change 100755 => 100644 purify/nall/vector.hpp
mode change 100755 => 100644 purify/nall/windows/detour.hpp
mode change 100755 => 100644 purify/nall/windows/guid.hpp
mode change 100755 => 100644 purify/nall/windows/launcher.hpp
mode change 100755 => 100644 purify/nall/windows/registry.hpp
mode change 100755 => 100644 purify/nall/windows/utf8.hpp
mode change 100755 => 100644 purify/nall/xorg/guard.hpp
mode change 100755 => 100644 purify/nall/xorg/xorg.hpp
mode change 100755 => 100644 purify/nall/zip.hpp
mode change 100755 => 100644 purify/phoenix/Makefile
mode change 100755 => 100644 purify/phoenix/core/core.cpp
mode change 100755 => 100644 purify/phoenix/core/core.hpp
mode change 100755 => 100644 purify/phoenix/core/keyboard.hpp
mode change 100755 => 100644 purify/phoenix/core/layout/fixed-layout.cpp
mode change 100755 => 100644 purify/phoenix/core/layout/fixed-layout.hpp
mode change 100755 => 100644 purify/phoenix/core/layout/horizontal-layout.cpp
mode change 100755 => 100644 purify/phoenix/core/layout/horizontal-layout.hpp
mode change 100755 => 100644 purify/phoenix/core/layout/vertical-layout.cpp
mode change 100755 => 100644 purify/phoenix/core/layout/vertical-layout.hpp
mode change 100755 => 100644 purify/phoenix/core/state.hpp
mode change 100755 => 100644 purify/phoenix/gtk/action/action.cpp
mode change 100755 => 100644 purify/phoenix/gtk/action/check-item.cpp
mode change 100755 => 100644 purify/phoenix/gtk/action/item.cpp
mode change 100755 => 100644 purify/phoenix/gtk/action/menu.cpp
mode change 100755 => 100644 purify/phoenix/gtk/action/radio-item.cpp
mode change 100755 => 100644 purify/phoenix/gtk/action/separator.cpp
mode change 100755 => 100644 purify/phoenix/gtk/desktop.cpp
mode change 100755 => 100644 purify/phoenix/gtk/dialog-window.cpp
mode change 100755 => 100644 purify/phoenix/gtk/font.cpp
mode change 100755 => 100644 purify/phoenix/gtk/keyboard.cpp
mode change 100755 => 100644 purify/phoenix/gtk/message-window.cpp
mode change 100755 => 100644 purify/phoenix/gtk/mouse.cpp
mode change 100755 => 100644 purify/phoenix/gtk/platform.cpp
mode change 100755 => 100644 purify/phoenix/gtk/platform.hpp
mode change 100755 => 100644 purify/phoenix/gtk/settings.cpp
mode change 100755 => 100644 purify/phoenix/gtk/timer.cpp
mode change 100755 => 100644 purify/phoenix/gtk/utility.cpp
mode change 100755 => 100644 purify/phoenix/gtk/widget/button.cpp
mode change 100755 => 100644 purify/phoenix/gtk/widget/canvas.cpp
mode change 100755 => 100644 purify/phoenix/gtk/widget/check-box.cpp
mode change 100755 => 100644 purify/phoenix/gtk/widget/combo-box.cpp
mode change 100755 => 100644 purify/phoenix/gtk/widget/hex-edit.cpp
mode change 100755 => 100644 purify/phoenix/gtk/widget/horizontal-scroll-bar.cpp
mode change 100755 => 100644 purify/phoenix/gtk/widget/horizontal-slider.cpp
mode change 100755 => 100644 purify/phoenix/gtk/widget/label.cpp
mode change 100755 => 100644 purify/phoenix/gtk/widget/line-edit.cpp
mode change 100755 => 100644 purify/phoenix/gtk/widget/list-view.cpp
mode change 100755 => 100644 purify/phoenix/gtk/widget/progress-bar.cpp
mode change 100755 => 100644 purify/phoenix/gtk/widget/radio-box.cpp
mode change 100755 => 100644 purify/phoenix/gtk/widget/text-edit.cpp
mode change 100755 => 100644 purify/phoenix/gtk/widget/vertical-scroll-bar.cpp
mode change 100755 => 100644 purify/phoenix/gtk/widget/vertical-slider.cpp
mode change 100755 => 100644 purify/phoenix/gtk/widget/viewport.cpp
mode change 100755 => 100644 purify/phoenix/gtk/widget/widget.cpp
mode change 100755 => 100644 purify/phoenix/gtk/window.cpp
mode change 100755 => 100644 purify/phoenix/phoenix.cpp
mode change 100755 => 100644 purify/phoenix/phoenix.hpp
mode change 100755 => 100644 purify/phoenix/qt/action/action.cpp
mode change 100755 => 100644 purify/phoenix/qt/action/check-item.cpp
mode change 100755 => 100644 purify/phoenix/qt/action/item.cpp
mode change 100755 => 100644 purify/phoenix/qt/action/menu.cpp
mode change 100755 => 100644 purify/phoenix/qt/action/radio-item.cpp
mode change 100755 => 100644 purify/phoenix/qt/action/separator.cpp
mode change 100755 => 100644 purify/phoenix/qt/desktop.cpp
mode change 100755 => 100644 purify/phoenix/qt/dialog-window.cpp
mode change 100755 => 100644 purify/phoenix/qt/font.cpp
mode change 100755 => 100644 purify/phoenix/qt/keyboard.cpp
mode change 100755 => 100644 purify/phoenix/qt/message-window.cpp
mode change 100755 => 100644 purify/phoenix/qt/mouse.cpp
mode change 100755 => 100644 purify/phoenix/qt/platform.cpp
mode change 100755 => 100644 purify/phoenix/qt/platform.moc
mode change 100755 => 100644 purify/phoenix/qt/platform.moc.hpp
mode change 100755 => 100644 purify/phoenix/qt/settings.cpp
mode change 100755 => 100644 purify/phoenix/qt/timer.cpp
mode change 100755 => 100644 purify/phoenix/qt/utility.cpp
mode change 100755 => 100644 purify/phoenix/qt/widget/button.cpp
mode change 100755 => 100644 purify/phoenix/qt/widget/canvas.cpp
mode change 100755 => 100644 purify/phoenix/qt/widget/check-box.cpp
mode change 100755 => 100644 purify/phoenix/qt/widget/combo-box.cpp
mode change 100755 => 100644 purify/phoenix/qt/widget/hex-edit.cpp
mode change 100755 => 100644 purify/phoenix/qt/widget/horizontal-scroll-bar.cpp
mode change 100755 => 100644 purify/phoenix/qt/widget/horizontal-slider.cpp
mode change 100755 => 100644 purify/phoenix/qt/widget/label.cpp
mode change 100755 => 100644 purify/phoenix/qt/widget/line-edit.cpp
mode change 100755 => 100644 purify/phoenix/qt/widget/list-view.cpp
mode change 100755 => 100644 purify/phoenix/qt/widget/progress-bar.cpp
mode change 100755 => 100644 purify/phoenix/qt/widget/radio-box.cpp
mode change 100755 => 100644 purify/phoenix/qt/widget/text-edit.cpp
mode change 100755 => 100644 purify/phoenix/qt/widget/vertical-scroll-bar.cpp
mode change 100755 => 100644 purify/phoenix/qt/widget/vertical-slider.cpp
mode change 100755 => 100644 purify/phoenix/qt/widget/viewport.cpp
mode change 100755 => 100644 purify/phoenix/qt/widget/widget.cpp
mode change 100755 => 100644 purify/phoenix/qt/window.cpp
mode change 100755 => 100644 purify/phoenix/reference/action/action.cpp
mode change 100755 => 100644 purify/phoenix/reference/action/check-item.cpp
mode change 100755 => 100644 purify/phoenix/reference/action/item.cpp
mode change 100755 => 100644 purify/phoenix/reference/action/menu.cpp
mode change 100755 => 100644 purify/phoenix/reference/action/radio-item.cpp
mode change 100755 => 100644 purify/phoenix/reference/action/separator.cpp
mode change 100755 => 100644 purify/phoenix/reference/desktop.cpp
mode change 100755 => 100644 purify/phoenix/reference/dialog-window.cpp
mode change 100755 => 100644 purify/phoenix/reference/font.cpp
mode change 100755 => 100644 purify/phoenix/reference/keyboard.cpp
mode change 100755 => 100644 purify/phoenix/reference/message-window.cpp
mode change 100755 => 100644 purify/phoenix/reference/mouse.cpp
mode change 100755 => 100644 purify/phoenix/reference/platform.cpp
mode change 100755 => 100644 purify/phoenix/reference/platform.hpp
mode change 100755 => 100644 purify/phoenix/reference/timer.cpp
mode change 100755 => 100644 purify/phoenix/reference/widget/button.cpp
mode change 100755 => 100644 purify/phoenix/reference/widget/canvas.cpp
mode change 100755 => 100644 purify/phoenix/reference/widget/check-box.cpp
mode change 100755 => 100644 purify/phoenix/reference/widget/combo-box.cpp
mode change 100755 => 100644 purify/phoenix/reference/widget/hex-edit.cpp
mode change 100755 => 100644 purify/phoenix/reference/widget/horizontal-scroll-bar.cpp
mode change 100755 => 100644 purify/phoenix/reference/widget/horizontal-slider.cpp
mode change 100755 => 100644 purify/phoenix/reference/widget/label.cpp
mode change 100755 => 100644 purify/phoenix/reference/widget/line-edit.cpp
mode change 100755 => 100644 purify/phoenix/reference/widget/list-view.cpp
mode change 100755 => 100644 purify/phoenix/reference/widget/progress-bar.cpp
mode change 100755 => 100644 purify/phoenix/reference/widget/radio-box.cpp
mode change 100755 => 100644 purify/phoenix/reference/widget/text-edit.cpp
mode change 100755 => 100644 purify/phoenix/reference/widget/vertical-scroll-bar.cpp
mode change 100755 => 100644 purify/phoenix/reference/widget/vertical-slider.cpp
mode change 100755 => 100644 purify/phoenix/reference/widget/viewport.cpp
mode change 100755 => 100644 purify/phoenix/reference/widget/widget.cpp
mode change 100755 => 100644 purify/phoenix/reference/window.cpp
mode change 100755 => 100644 purify/phoenix/sync.sh
mode change 100755 => 100644 purify/phoenix/windows/action/action.cpp
mode change 100755 => 100644 purify/phoenix/windows/action/check-item.cpp
mode change 100755 => 100644 purify/phoenix/windows/action/item.cpp
mode change 100755 => 100644 purify/phoenix/windows/action/menu.cpp
mode change 100755 => 100644 purify/phoenix/windows/action/radio-item.cpp
mode change 100755 => 100644 purify/phoenix/windows/action/separator.cpp
mode change 100755 => 100644 purify/phoenix/windows/desktop.cpp
mode change 100755 => 100644 purify/phoenix/windows/dialog-window.cpp
mode change 100755 => 100644 purify/phoenix/windows/font.cpp
mode change 100755 => 100644 purify/phoenix/windows/keyboard.cpp
mode change 100755 => 100644 purify/phoenix/windows/message-window.cpp
mode change 100755 => 100644 purify/phoenix/windows/mouse.cpp
mode change 100755 => 100644 purify/phoenix/windows/object.cpp
mode change 100755 => 100644 purify/phoenix/windows/phoenix.Manifest
mode change 100755 => 100644 purify/phoenix/windows/phoenix.rc
mode change 100755 => 100644 purify/phoenix/windows/platform.cpp
mode change 100755 => 100644 purify/phoenix/windows/platform.hpp
mode change 100755 => 100644 purify/phoenix/windows/settings.cpp
mode change 100755 => 100644 purify/phoenix/windows/timer.cpp
mode change 100755 => 100644 purify/phoenix/windows/utility.cpp
mode change 100755 => 100644 purify/phoenix/windows/widget/button.cpp
mode change 100755 => 100644 purify/phoenix/windows/widget/canvas.cpp
mode change 100755 => 100644 purify/phoenix/windows/widget/check-box.cpp
mode change 100755 => 100644 purify/phoenix/windows/widget/combo-box.cpp
mode change 100755 => 100644 purify/phoenix/windows/widget/hex-edit.cpp
mode change 100755 => 100644 purify/phoenix/windows/widget/horizontal-scroll-bar.cpp
mode change 100755 => 100644 purify/phoenix/windows/widget/horizontal-slider.cpp
mode change 100755 => 100644 purify/phoenix/windows/widget/label.cpp
mode change 100755 => 100644 purify/phoenix/windows/widget/line-edit.cpp
mode change 100755 => 100644 purify/phoenix/windows/widget/list-view.cpp
mode change 100755 => 100644 purify/phoenix/windows/widget/progress-bar.cpp
mode change 100755 => 100644 purify/phoenix/windows/widget/radio-box.cpp
mode change 100755 => 100644 purify/phoenix/windows/widget/text-edit.cpp
mode change 100755 => 100644 purify/phoenix/windows/widget/vertical-scroll-bar.cpp
mode change 100755 => 100644 purify/phoenix/windows/widget/vertical-slider.cpp
mode change 100755 => 100644 purify/phoenix/windows/widget/viewport.cpp
mode change 100755 => 100644 purify/phoenix/windows/widget/widget.cpp
mode change 100755 => 100644 purify/phoenix/windows/window.cpp
mode change 100755 => 100644 purify/purify.cpp
mode change 100755 => 100644 purify/resource/applications-system.png
mode change 100755 => 100644 purify/resource/drive-harddisk.png
mode change 100755 => 100644 purify/resource/folder.png
mode change 100755 => 100644 purify/resource/input-gaming.png
mode change 100755 => 100644 purify/resource/resource.cpp
mode change 100755 => 100644 purify/resource/resource.hpp
mode change 100755 => 100644 purify/resource/resource.xml
mode change 100755 => 100644 purify/resource/view-refresh.png
delete mode 100755 snesfilter/HQ2x/HQ2x-RGB555.cpp
delete mode 100755 snesfilter/HQ2x/HQ2x.cpp
delete mode 100755 snesfilter/LQ2x/LQ2x.cpp
delete mode 100755 snesfilter/Makefile
delete mode 100755 snesfilter/Phosphor3x/Phosphor3x.cpp
delete mode 100755 snesfilter/Pixellate2x/Pixellate2x.cpp
delete mode 100755 snesfilter/Scale2x/Scale2x.cpp
delete mode 100755 snesfilter/Scanline/Scanline-Dark.cpp
delete mode 100755 snesfilter/Scanline/Scanline-Light.cpp
delete mode 100755 snesfilter/nall/array.hpp
delete mode 100755 snesfilter/nall/bit.hpp
delete mode 100755 snesfilter/nall/moduloarray.hpp
delete mode 100755 snesfilter/nall/platform.hpp
delete mode 100755 snesfilter/nall/reference_array.hpp
delete mode 100755 snesfilter/nall/resource.hpp
delete mode 100755 snesfilter/nall/snes/cartridge.hpp
delete mode 100755 snesfilter/nall/snes/cpu.hpp
delete mode 100755 snesfilter/nall/snes/smp.hpp
delete mode 100755 snesfilter/nall/sort.hpp
delete mode 100755 snesfilter/nall/stack.hpp
delete mode 100755 snesfilter/nall/static.hpp
delete mode 100755 snesfilter/nall/string/filename.hpp
delete mode 100755 snesfilter/nall/string/math.hpp
delete mode 100755 snesfilter/nall/string/platform.hpp
delete mode 100755 snesfilter/nall/string/strl.hpp
delete mode 100755 snesfilter/nall/test/cc.bat
delete mode 100755 snesfilter/nall/test/cc.sh
delete mode 100755 snesfilter/nall/test/document.bml
delete mode 100755 snesfilter/nall/test/test
delete mode 100755 snesfilter/nall/test/test.cpp
delete mode 100755 snesfilter/nall/varint.hpp
delete mode 100755 snesfilter/nall/vector.hpp
delete mode 100644 snesfilter/out/.gitignore
delete mode 100755 snesshader/Archive/HDR-TV.OpenGL.shader
delete mode 100755 snesshader/Archive/Watercolor.OpenGL.shader
delete mode 100755 snesshader/Curvature.OpenGL.shader
delete mode 100755 snesshader/HQ2x.OpenGL.shader
delete mode 100755 snesshader/Makefile
delete mode 100755 snesshader/Pixellate.OpenGL.shader
delete mode 100755 snesshader/Scale2x.OpenGL.shader
delete mode 100755 snesshader/Sepia.Direct3D.shader
diff --git a/bsnes/Makefile b/bsnes/Makefile
old mode 100755
new mode 100644
index f1b70c6c..65ad25d5
--- a/bsnes/Makefile
+++ b/bsnes/Makefile
@@ -4,11 +4,14 @@ fc := fc
sfc := sfc
gb := gb
gba := gba
+nds := nds
profile := accuracy
target := ethos
-# options += console
+# options += debugger
+# arch := win32
+# console := true
# compiler
c := $(compiler) -std=gnu99
@@ -34,7 +37,15 @@ ifeq ($(platform),x)
link += -ldl -lX11 -lXext
else ifeq ($(platform),osx)
else ifeq ($(platform),win)
- link += $(if $(findstring console,$(options)),-mconsole,-mwindows)
+ ifeq ($(arch),win32)
+ flags += -m32
+ link += -m32
+ endif
+ ifeq ($(console),true)
+ link += -mconsole
+ else
+ link += -mwindows
+ endif
link += -mthreads -luuid -lkernel32 -luser32 -lgdi32 -lcomctl32 -lcomdlg32 -lshell32 -lole32
link += -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc
else
@@ -94,7 +105,7 @@ sync:
rm -r phoenix/test
archive:
- if [ -f bsnes.tar.bz2 ]; then rm bsnes.tar.bz2; fi
- tar -cjf bsnes.tar.bz2 `ls`
+ if [ -f bsnes.tar.xz ]; then rm bsnes.tar.xz; fi
+ tar -cJf bsnes.tar.xz `ls`
help:;
diff --git a/bsnes/data/bsnes.Manifest b/bsnes/data/bsnes.Manifest
old mode 100755
new mode 100644
diff --git a/bsnes/data/bsnes.desktop b/bsnes/data/bsnes.desktop
old mode 100755
new mode 100644
diff --git a/bsnes/data/bsnes.ico b/bsnes/data/bsnes.ico
old mode 100755
new mode 100644
diff --git a/bsnes/data/bsnes.png b/bsnes/data/bsnes.png
old mode 100755
new mode 100644
diff --git a/bsnes/data/cheats.xml b/bsnes/data/cheats.xml
old mode 100755
new mode 100644
index 0619442d..1f94df58
--- a/bsnes/data/cheats.xml
+++ b/bsnes/data/cheats.xml
@@ -1,5 +1,5 @@
-
+
1942 (Japan, USA)
@@ -423,6 +423,14 @@
Invincibility
AVISVG
+
+ One hit kills
+ EIKVVIEY
+
+
+ No enemies
+ GXUIZIAI
+
Addams Family, The (USA)
@@ -3845,6 +3853,10 @@
Super fast punching
AEUZITPA
+
+ Force 2-player mode
+ AENTAIPL
+
Start with 1 life
PENVZILA
@@ -4383,6 +4395,13 @@
ZAXAYGAA
+
+ Bio Miracle Bokutte Upa (Japan).nes
+
+ Hit anywhere - normal enemies
+ AAKTZTIG+AEOLVGTZ
+
+
Bionic Commando (USA)
@@ -4417,10 +4436,30 @@
Autofire - main game
XYXUUOEN
+
+ Longer grapple line - sidescrolling levels
+ AINPTZAL+TSEOGZAG+YIVPAXZU
+
+
+ Longest grapple line - sidescrolling levels
+ EINPYZEP+EIVPPZEP+ESEOIZEP
+
+
+ Longer range for normal 3-way gun - sidescrolling levels
+ YOVUESPA
+
+
+ Longer range for fireball 3-way gun - sidescrolling levels
+ IPKLKVGA
+
Use with BIO Code 11 for improved autofire with normal gun
AAKUOOZA
+
+ Have all items (using the hidden gun will crash the game)
+ ELKLZAEY+EIXLTPEY
+
Start with 3 life energy capsules
LAUKOZAA+XTUKUXVU
@@ -9647,6 +9686,13 @@
PAUIEZIA
+
+ Donkey Kong Jr. Math (USA, Europe).nes
+
+ Always get the correct answer
+ AAKILSZA+AAUILSZP
+
+
Donkey Kong Classics (USA, Europe)
@@ -11273,6 +11319,10 @@
Infinite lives (alt)
SGXGZGVG
+
+ Multi-jump
+ ENVVIPNP+PXVVPOVP+XOVVTPXT+ZKVVGOGK
+
Take more damage
APONPXAA
@@ -13634,6 +13684,14 @@
Infinite credits
SXXGSVVK
+
+ Hit anywhere
+ AIUPKZEL+APUPSZGX+ASEOEPEL+EUEZTGGN+GKEZIKOS+KXEZYGIA+ZUEOOOAI
+
+
+ Get items from anywhere
+ AINPXZEL+YPNPUXPX
+
Galactic Crusader (USA) (Unl)
@@ -15140,6 +15198,18 @@
Infinite special weapons
SXVZTXSE
+
+ One hit kills
+ EIEIYYEP
+
+
+ Enemies die automatically
+ AAUZLOAP+AUSSANAO+SAUZTOVK
+
+
+ Get items from anywhere
+ AUVSINKU+AVVSTNAP
+
Invincibility (alt)
0400:02
@@ -15546,6 +15616,13 @@
SLONNKSO
+
+ Heracles no Eikou - Toujin Makyou Den (Japan)
+
+ No random battles
+ AVSVTZAZ
+
+
Hogan's Alley (World)
@@ -17257,6 +17334,14 @@
Take less damage
PTYSEK
+
+ Hit anywhere
+ GKKEAZSK+OVKEPXPA+XEKEZZEP
+
+
+ Multi-jump
+ AEOTTIGA
+
9 Tornado Attacks on pick-up
PESIKYYE
@@ -18643,6 +18728,14 @@
Press Start to complete the level
GEXGUALU+LEXGSALU+OXXGXAIK
+
+ Hit anywhere - throwing
+ ELXKKESZ+TIXKSAYA
+
+
+ Multi-jump when falling
+ ESXPZZEY+KOXPLZKS+OKOOYZOX+PEXPPXSG+PXXPAZES
+
One life after continue
PASKOILA
@@ -18889,6 +18982,14 @@
Infinite lives
SXKTPKVG
+
+ Hit anywhere (spitting)
+ AOOEIOOV+AOOETPYE+EANEZAAT+GGNEAESN+GXKEIPEL+VGNEPAGY
+
+
+ Inhale from anywhere
+ AASELZZG+AINEYZEP+SZNEGXSV
+
Less health from 'pep drinks'
ZAKLLXAA
@@ -18948,6 +19049,14 @@
Infinite lives
SXKTPKVG
+
+ Hit anywhere (spitting)
+ AEKAIEIA+AEXAIPTL+AOOAGEOV+AOOAIAYE+GXKEIPEL
+
+
+ Inhale from anywhere
+ AASELZZG+GXEAGZEL
+
Less health from 'pep drinks'
ZAKLLXAA
@@ -21342,6 +21451,10 @@
Magic of Scheherazade, The (USA)
+
+ Invincibility
+ OXUYZKPX
+
Infinite HP
OTSXLGSV
@@ -21350,6 +21463,18 @@
Infinite lives
SXEVPLVG
+
+ Hit anywhere
+ AEEYYGLA+ALNNIGEP+SZNNLGSG+TZNNTKPA+UGNNGKPE
+
+
+ Never lose Mashroobs
+ SZEAEKVK
+
+
+ Get coins from anywhere
+ TEXAXLLA
+
Less energy gained from Bread
POKAOZZU
@@ -21358,10 +21483,6 @@
Less magic gained from Mashroobs
ZAEEXGIA
-
- Never lose Mashroobs
- SZEAEKVK
-
Start with only 20 Gold Coins
ZAUTAZIA
@@ -25957,6 +26078,13 @@
03E2:1D
+
+ Otaku no Seiza - An Adventure in the Otaku Galaxy (Japan)
+
+ No random battles
+ AVEIXKOZ
+
+
Over Horizon (Europe)
@@ -27001,7 +27129,7 @@
- Princess Tomato in Salad Kingdom (USA)
+ Princess Tomato in the Salad Kingdom (USA)
Infinite gold coins
03CB:09
@@ -29841,6 +29969,10 @@
Infinite time
SZEVYZVG
+
+ Hit anywhere
+ AKSZANEL+ATUILYEI+OXSZPNEX
+
200 Machine Gun bullets on pick-up
EKSTEAGV
@@ -30578,6 +30710,13 @@
AANOLAZE
+
+ Shinsenden (Japan)
+
+ No random battles
+ ATXUPAAL
+
+
Shooting Range (USA)
@@ -33991,6 +34130,10 @@
Quick pick-up
SXUASXOU
+
+ Twice as much time in sub-space
+ NNXPZIAV
+
Infinite magic carpet time
SLNZZLVI
@@ -34194,6 +34337,10 @@
Quick pick-up
SXUASXOU
+
+ Twice as much time in sub-space
+ NNXPZIAV
+
Jump as high as a squat jump
AEUEKKGL
@@ -38384,6 +38531,10 @@
Vice - Project Doom (USA)
+
+ Invincibility
+ AANSEIYP
+
Infinite lives
SZSKIOVK
@@ -38404,6 +38555,14 @@
Infinite power
SXVYVKSE
+
+ Hit anywhere
+ AEEYXEET
+
+
+ Multi-jump
+ XVVKISZK
+
10 coins for an extra life
ZEOYNGGV
@@ -39101,10 +39260,22 @@
Wing of Madoola, The (Japan) (Sample)
+
+ Invincibility
+ SXKGXTSA
+
Infinite hits and magic
SLUUVYSP
+
+ Hit anywhere
+ AAOGEVPA+AAOGSVZI+PZOGKTSN
+
+
+ One hit kills
+ APXKETSV+APXKOVEE
+
Start with 9999 hits
OOKZKPAE+OOKXEPAO
@@ -40490,6 +40661,17 @@
YYKSKIPE
+
+ Ys III - Wanderers from Ys (Japan).nes
+
+ Hit anywhere
+ XTKXSAAV+XTNXUAAV+XTVZKAAV+XVOZXAAV
+
+
+ One hit kills
+ AAEZYYGA
+
+
Yume Koujou Doki Doki Panic (Japan) [b] (FDS)
@@ -40567,6 +40749,10 @@
Zanac (USA)
+
+ Invincibility + Hit anywhere
+ ALSEGZEU+ATSEIZPL+SZOELXOO
+
Infinite lives
OXEENYVK
@@ -42123,9 +42309,14 @@
Infinite lives
DD67-4468
-
-
- DDB3-C764
+
+ Hit anywhere
+ 40B5-17A4+40B6-14A4+40BB-17D4+40BC-1DA4
+
+
+ One hit kills
+ DDB3-C764
+
Small magic power-up adds 3 instead of 1
D7C0-37A7
@@ -42923,6 +43114,14 @@
Infinite lives
C282-34A1
+
+ Hit anywhere
+ DDA0-476A+DDA9-4F6A
+
+
+ Moon jump
+ 5C88-1D09+7D88-1DA9+DD83-17A9
+
Adventures of Rocky and Bullwinkle and Friends, The (USA)
@@ -44468,6 +44667,25 @@
6D14-7DD4
+
+ Ashita no Joe (Japan)
+
+ Hit anywhere - P1
+ DD81-64AF
+
+
+ Hit anywhere - P2
+ DD8A-A46D
+
+
+ Invincibility - P1
+ 6D8A-6DDD
+
+
+ Invincibility - P2
+ 6D81-0FDF
+
+
Asterix (Europe) (En,Fr,De,Es)
@@ -44775,6 +44993,10 @@
Infinite weapons (except for Flame)
3C37-A7D4
+
+ Hit anywhere
+ DDE2-6D04+DDEF-AD04
+
Max weapons on pick-up
DDC0-C770
@@ -46107,6 +46329,10 @@
Infinite Hyper Bombs - Neptune
C2C3-DF67
+
+ Hit anywhere
+ 1D85-AD0F+1D8B-ADAF+C28A-D7A4+7685-ADDF+768B-AD6F
+
Start with 1 ship
DD6E-6707
@@ -46178,6 +46404,10 @@
Infinite Discs
8289-CFDF
+
+ Multi-jump
+ 6D21-CFAF+6D29-CD6F
+
Bobby's World (USA) (Proto)
@@ -46186,13 +46416,25 @@
2DB7-1DD8
- Infinite energy
+ Infinite health
82BC-1468
+
+ Infinite health (alt)
+ 7E139B03
+
Infinite lives
822D-17AF
+
+ Infinite lives (alt)
+ 7E139509
+
+
+ Multi-jump
+ DDB3-17AC
+
Bonkers (USA)
@@ -46216,6 +46458,10 @@
Infinite dash
C98C-CD0F
+
+ Hit anywhere
+ 6DE1-1F04+9DE1-1F64
+
Boogerman - A Pick and Flick Adventure (USA)
@@ -46286,6 +46532,14 @@
Boxing Legends of the Ring (USA)
+
+ Invincibility - P1
+ 6D6A-C4A9
+
+
+ Invincibility - P2
+ 6D66-3D05
+
Infinite super punches - P1
C26D-3F05
@@ -46302,6 +46556,22 @@
Infinite time per round
C2BA-A7A7
+
+ Hit anywhere - P1
+ 1DBD-4460+F6BD-4400
+
+
+ Hit anywhere - P2
+ 1D69-3FD9+F669-3DA9
+
+
+ Blocking disabled - P1
+ DD62-CD09
+
+
+ Blocking disabled - P2
+ DD66-3FA5
+
Each round is 1 minute
DF8D-CDA7
@@ -48406,6 +48676,13 @@
D460-CD0D
+
+ Bulls vs Blazers and the NBA Playoffs (USA)
+
+ Never miss a shot
+ DD66-C4BD
+
+
Bust-A-Move (USA)
@@ -49569,6 +49846,14 @@
Infinite lives
DDEC-CF6D
+
+ Hit anywhere
+ DD6B-ADA4
+
+
+ Multi-jump
+ DDA2-DDDF
+
Stay as Super Congo (you may change if you walk on spikes)
CB69-34D7
@@ -50107,6 +50392,22 @@
Infinite Nutty attacks
C287-34AD
+
+ Hit anywhere
+ DD33-1DDF
+
+
+ Get items from anywhere
+ DD20-C7A4+DD26-1FD4+DD27-CFA7+DD3C-1D6D
+
+
+ One hit kills
+ 6D86-17DF
+
+
+ Disable recoil
+ DD89-CFAD
+
Juice cans set health to 1/2
D121-CD64
@@ -50774,6 +51075,14 @@
Invincibility after one hit
C92A-44A7
+
+ Hit anywhere
+ DD66-47DC+DD6C-4D6C+6D6D-3DDC+6D64-3DAC
+
+
+ Get GP from anywhere
+ DDA5-176C
+
Large health refills full health
C9AC-176C
@@ -51490,6 +51799,10 @@
Infinite credits - both players
C260-67F7
+
+ Hit and stomp anywhere
+ 6DAE-6469+F9AE-64A9
+
Clock runs faster
7A64-D420
@@ -53648,9 +53961,17 @@
EE2E-54A1
- Fast money (buy a bread w/the code off, turn code on and sell it for $32,646)
+ Fast money (buy a bread with the code disabled, enable and sell it for $32,646)
EE9A-E5F5
+
+ Dad never calls
+ E395-87DD
+
+
+ Massive numbers of enemies (piracy check)
+ 6D4F-7704
+
Start with a level 9 character
DB23-77D1
@@ -53683,10 +54004,6 @@
Start with a lot of PSI
BB2F-54A1
-
- Dad never calls
- E395-87DD
-
Infinite health
7E9A13:E7+7E9A14:03
@@ -60503,8 +60820,16 @@
Imperium (USA)
- Invincibility against lesser robots, weapons and lasers
- 1D34-D4A1+1DC3-DDF7
+ Invincibility
+ 6DCC-DD27+DD38-AFA9
+
+
+ Hit anywhere
+ 6D31-DDA1+C236-DD01
+
+
+ Infinite bombs
+ C2A9-D46F
Start with 1 life point
@@ -60683,6 +61008,18 @@
Health doesn't decrease when Hulked-out
C260-4746
+
+ Hit anywhere
+ 0AB3-4D00+2DB3-4DD0+3DB2-4700+DDB2-4760+DDB2-47A0
+
+
+ One hit kills
+ DDBF-47D0
+
+
+ Get items from anywhere
+ 6DBF-17CB
+
Get 4 shots from gun
D0BC-173B
@@ -61373,6 +61710,13 @@
7E0269:03
+
+ Jeopardy! (USA)
+
+ Always get the correct answer
+ 6DC8-6D67+6DCE-64A7
+
+
Jetsons, The - Invasion of the Planet Pirates (USA)
@@ -61499,6 +61843,10 @@
Hit anywhere
6DC3-0DAD+C9E5-DDDD+DDC4-076D
+
+ One hit kills
+ 40CC-07DD
+
Start with 2 lives
CBC8-6404+DFC8-6464
@@ -64516,10 +64864,9 @@
Pit death disabled
1DA9-04D1
-
- Get 1 gold for each creature killed
- 1BB5-D769+DFB5-D7A9+3CB6-DDD9
-
+
+
+ 1BB5-D769+DFB5-D7A9+3CB6-DDD9
Get 100 gold for each creature killed
1BB5-D769+10B5-D7A9+3CB6-DDD9
@@ -65106,6 +65453,10 @@
Dash without having the Pegasus Boots
EEE5-2356
+
+ Dash without charge up
+ 45B8-D49A
+
Use the Magic Mirror to warp between the Light and Dark Worlds freely
6DC9-0D23
@@ -70208,6 +70559,10 @@
Infinite timeouts - both players (slightly glitchy)
8250-5700
+
+ Cannot be tackled (hold X)
+ 6D59-7FD7+7D59-7F67+C959-7DA7+DC59-7F07+E959-7FA7
+
Field goals worth 0 points
DD6F-8404
@@ -70283,6 +70638,10 @@
Infinite timeouts
8297-7F09
+
+ Cannot be tackled (hold X)
+ 6D6C-EFDF+7D6C-EF6F+C96C-EDAF+DC6C-EF0F+E96C-EFAF
+
Safeties are worth 0 points
DD62-EFA7
@@ -70348,6 +70707,20 @@
DF65-E7A7
+
+ Madden NFL 97 (USA)
+
+ Cannot be tackled (hold X)
+ 6D66-7767+7D6B-7DD7+C966-7707+DC66-77A7+E96B-7D07
+
+
+
+ Madden NFL 98 (USA)
+
+ Cannot be tackled (hold X)
+ 6D6F-5407+7D6F-54A7+C96F-54D7+DC6F-5467+E96F-57D7
+
+
Magic Boy (USA)
@@ -71254,7 +71627,7 @@
Infinite weapon energy
- FEC2-E405
+ FE42-E405
One hit kills
@@ -71268,6 +71641,50 @@
Multi-jump
DC51-ED65+BD51-EDA5+D751-EFD5+4D51-EF05+8551-EF65+7451-EFA5+4D51-E4D5+BC51-E405+FF51-E465+1D51-E4A5+1DFC-E400+5EFC-E460+C951-EDD5+0951-ED05
+
+ Always Shoot Shots
+ FF40-E405
+
+
+ Always shoot Freeze Cracker
+ 4040-E405
+
+
+ Always shoot Scorch Wheel
+ 4140-E405
+
+
+ Always shoot Danger Wrap Bombs
+ 4340-E405
+
+
+ Always shoot Noise Crush
+ 1140-E405
+
+
+ Always shoot Fully Charged Mega Buster Blasts
+ 5240-E405
+
+
+ Always shoot Slash Claw
+ BA40-E405
+
+
+ Always shoot Thunder Bolt
+ 8940-E405
+
+
+ Always shoot Wild Coil
+ E740-E405
+
+
+ Always shoot Charged Wild Coils
+ EE40-E405
+
+
+ White Shots/Special Weapons
+ EE02-E465
+
Infinite E-Tanks (alt)
7E0BA0:FF
@@ -71379,6 +71796,14 @@
Multi-jump
4065-17A9+EA66-1409+B966-1469
+
+ Enemies always drop large energy
+ C4CB-3DBD+D4CB-3D2D
+
+
+ Enemies always drop large weapon energy
+ C4CB-3DBD+D0CB-3D2D
+
Bogus jump (may go back to normal jumps)
D08A-1FBC
@@ -71482,6 +71907,14 @@
Multi-jump
4065-1F09+E465-17A9+B966-1DD9
+
+ Enemies always drop large energy
+ C4C6-379D+D4C6-37BD
+
+
+ Enemies always drop large weapon energy
+ C4C6-379D+D0C6-37BD
+
Bogus jump (may go back to normal jumps)
D08A-1FBC
@@ -71553,6 +71986,10 @@
Mega Man X2 (USA)
+
+ Invincibility
+ D6B0-DD4F
+
Infinite health
C223-0414
@@ -71573,10 +72010,6 @@
Multi-jump
40BE-DD44+26BE-D4C4+8BBE-D434
-
- Invincibility
- 8944008
-
Infinite health (alt 2)
7E09FF:20
@@ -71680,6 +72113,14 @@
Multi-jump
4064-042F+D367-0F9F+C567-0FBF
+
+ Enemies always drop large energy
+ C42E-0D2F+D42E-0FFF
+
+
+ Enemies always drop large weapon energy
+ C42E-0D2F+D02E-0FFF
+
Super-jump
D586-6F26
@@ -71751,6 +72192,14 @@
View ending (select Capcom Championship)
81829B:EE+81829C:E0
+
+ Unlock Capcom Championship mode ending
+ 82D1F0:EA+82D1F1:EA+82D1F2:EA+82D1F3:EA
+
+
+ Unlock Tournament mode ending
+ 82D29C:EA+82D29D:EA+82D29E:EA+82D29F:EA
+
Metal Combat - Falcon's Revenge (USA)
@@ -72097,6 +72546,10 @@
Infinite bombs on pick-up
C2B7-0FF7
+
+ Collect items from anywhere
+ 4084-D794+6D8A-0724+F282-0DF4
+
Mega-jump
EC6A-ADF7
@@ -76654,6 +77107,10 @@
PGA Tour Golf (USA)
+
+ Ball goes in from anywhere
+ 6D85-67AD+6DCC-ADD7
+
Allow 14 clubs for full set instead of 13
D235-6D07+D22A-D40F
@@ -78807,6 +79264,10 @@
Infinite lives - P2
3CB5-0467
+
+ Hit anywhere
+ 44E8-6446+6DE8-6F36+C9E3-6446
+
Replacement planes carry 0 bombs - P1
CEB7-DFD7+62B7-DF07
@@ -79431,9 +79892,14 @@
No score lost when special attack is used
DD62-A7A6
-
-
- EEC4-OD6F+EE64-646C+EE63-04A7+EE68-A7A1
+
+ Hit anywhere (might make some enemies invisible)
+ 6DB6-69EA+F9B6-617A
+
+
+ Start with more health
+ EEC4-OD6F+EE64-646C+EE63-04A7+EE68-A7A1
+
Start with less health
FEC4-0D6F+FE64-646C+FE63-04A7+FE68-A7A1
@@ -83080,9 +83546,14 @@
Infinite health
C208-87D1
-
-
- FDDB-5FB9
+
+ Hit anywhere
+ 40F8-84B0
+
+
+ Don't blink after getting hit
+ FDDB-5FB9
+
Falling doesn't use life points
C2F4-7FD1
@@ -87983,6 +88454,10 @@
Spin jump in mid air (hold for float down)
F53F-6767+DD3F-67A7
+
+ Press R to scroll through items in the items box
+ D2AF-6407+D2AF-6DD7+DFAF-6F67+17AF-6FD7+1DAF-6467+62AF-6FA7+A4AD-67A7+A4AD-67D7+A4AF-64D7+CBAF-6F07+D1AF-6D67+D2AD-6707
+
Low jump
D02C-AF6F
@@ -88500,6 +88975,10 @@
Infinite Power Bombs (alt)
17DA-9E8C
+
+ Hit anywhere
+ 40C8-18DD+6DB1-3C6F+6DC2-1BDD
+
Super-jumps don't drain energy
C22A-456D
@@ -89717,6 +90196,28 @@
D4E9-6DEF
+
+ Super Solitaire (USA) (En,Fr,De,Es,It)
+
+ Move cards to any pile - Klondike
+ 6D8C-476F+DD8A-34AD+DD88-3D0D
+
+
+ Move cards to any pile - Free Cell
+ 6D8F-44A4
+
+
+
+ Super Soukoban (Japan)
+
+ Infinite steps
+ C2CC-64AB
+
+
+ Walk through walls
+ DD88-D4A6+DD88-D706
+
+
Super Star Wars (USA) (Rev 1)
@@ -91357,6 +91858,14 @@
Infinite hits on armor
C2AA-0FAF
+
+ Hit anywhere
+ DD8D-DD0D+DDAB-D4DF
+
+
+ Get items from anywhere
+ 6D8A-AF67
+
Heart worth more
F684-0F0D
@@ -92158,6 +92667,13 @@
3C38-C25D
+
+ Tecmo Super NBA Basketball (USA)
+
+ Never miss a shot (hold Y and press the shot button)
+ 7D69-CDE7+C269-CD77+D869-CD57+DC69-CD87+FF69-CF77
+
+
Teenage Mutant Ninja Turtles IV - Turtles in Time (USA)
@@ -92371,6 +92887,26 @@
Start with 7 continues
D6B1-CF60
+
+ Infinite health
+ 7E0EE460
+
+
+ Full power bar
+ 7E1AC060
+
+
+ Empty power bar - opponent
+ 7E1B1000
+
+
+ Opponent dizzy after every knockdown
+ 7E0FC210
+
+
+ Win one round to win match
+ 7E195002
+
Tengai Makyou Zero (Japan)
@@ -93198,6 +93734,18 @@
Race in any country
6DB7-AFEA
+
+ Don't slow down offroad
+ C229-D4F1
+
+
+ Don't slow down against obstacles
+ DD23-6499
+
+
+ Don't slow down against cars
+ DD38-D7F9+DD38-DF29
+
Start with 1/2 fuel
972B-0F64
@@ -97118,6 +97666,10 @@
Zero the Kamikaze Squirrel (USA)
+
+ Jump higher
+ E060-1D62+E060-CF03
+
Invincibility
7E0E2C:02
@@ -98947,6 +99499,25 @@
FA1-21E-4C1
+
+ Bubble Bobble (USA, Europe)
+
+ Hit anywhere
+ 00D-22E-C4A+18D-29E-08A
+
+
+ Hit anywhere - Bosses (except final boss)
+ 00C-05B-A29+00B-FCB-A29
+
+
+ Get items from anywhere
+ 00C-02D-A29+00C-0BD-A29+00D-56D-A29+375-8FB-6EE+37D-5FD-A29+C95-90B-91E
+
+
+ One hit kill - final boss
+ AF8-B7B-19E
+
+
Bubble Bobble Part 2 (USA, Europe)
@@ -99001,6 +99572,17 @@
BE6-00E-19E
+
+ Bug's Life, A (USA) (SGB Enhanced)
+
+ Infinite lives
+ 006-2FD-3BE
+
+
+ Invincibility (can still drown)
+ 000-EEE-081
+
+
BurgerTime Deluxe (World)
@@ -99702,6 +100284,13 @@
0AB-0C8-E6E
+
+ Deer Hunter (USA)
+
+ Infinite time
+ 004-1FF-19A
+
+
Dig Dug (USA)
@@ -100961,6 +101550,14 @@
Kid Icarus - Of Myths and Monsters (USA, Europe)
+
+ Hit anywhere
+ 008-B8B-5D4
+
+
+ Run into enemies to get Hearts
+ 185-67B-4CA
+
Collected hammers seem to count towards your enemy kill number
C9A-D18-08F+7AA-B48-E69
@@ -101067,6 +101664,14 @@
Infinite vitality bars except against end of stage boss
FA4-63B-4C1
+
+ Hit anywhere
+ 003-E1B-F7E
+
+
+ Inhale from anywhere
+ 008-53B-08E+008-67B-7FE
+
Start with 2 lives
021-BBF-F7E
@@ -101114,6 +101719,18 @@
Infinite lives
FA1-C4B-4C1
+
+ Hit anywhere
+ 006-E5D-6EA+187-04D-2AA
+
+
+ Inhale from anywhere
+ 005-BED-19E+005-DFD-91A
+
+
+ Get items from anywhere
+ 18B-898-08A
+
One hit and you die
AFA-9EC-A28
@@ -102119,6 +102736,17 @@
095-B2E-E66
+
+ Ms. Pac-Man (USA)
+
+ Invincibility
+ 009-06E-E62
+
+
+ Get fruit from anywhere
+ 00B-21E-D56
+
+
Mysterium (USA)
@@ -102161,6 +102789,44 @@
084-B5F-F7A
+
+ Nemesis (Europe)
+
+ Hit anywhere - Default weapon
+ 008-A7D-A29+008-B8D-A29
+
+
+ Hit anywhere - Laser
+ 009-5FD-A29+009-70D-A29
+
+
+ Hit anywhere - Missiles
+ 009-CBD-A29+009-DCD-A29
+
+
+ Get items from anywhere
+ 007-68D-A29
+
+
+
+ Nemesis (USA)
+
+ Hit anywhere - normal weapon
+ 008-A5D-A29+008-94D-A29
+
+
+ Hit anywhere - Laser
+ 009-5DD-A29+009-4CD-A29
+
+
+ Hit anywhere - Missiles
+ 009-C9D-A29+009-B8D-A29
+
+
+ Get items from anywhere
+ 007-55D-A29
+
+
NFL Football (USA)
@@ -102184,6 +102850,13 @@
08F-59F-F72
+
+ Ninja Boy (USA, Europe)
+
+ Hit anywhere (can get items from anywhere by punching)
+ 00E-279-C43
+
+
Nintendo World Cup (USA, Europe)
@@ -102316,6 +102989,17 @@
081-ACF-E66
+
+ Pac-Man (USA)
+
+ Invincibility
+ C97-7DE-A29
+
+
+ Get fruit from anywhere
+ 009-22E-E69+009-28E-E69
+
+
Pagemaster, The (USA) (SGB Enhanced)
diff --git a/bsnes/data/laevateinn.hpp b/bsnes/data/laevateinn.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/emulator/emulator.hpp b/bsnes/emulator/emulator.hpp
old mode 100755
new mode 100644
index 0e83b052..b5e856aa
--- a/bsnes/emulator/emulator.hpp
+++ b/bsnes/emulator/emulator.hpp
@@ -3,7 +3,7 @@
namespace Emulator {
static const char Name[] = "bsnes";
- static const char Version[] = "089.18";
+ static const char Version[] = "090";
static const char Author[] = "byuu";
static const char License[] = "GPLv3";
}
diff --git a/bsnes/emulator/interface.hpp b/bsnes/emulator/interface.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/Makefile b/bsnes/fc/Makefile
old mode 100755
new mode 100644
diff --git a/bsnes/fc/apu/apu.cpp b/bsnes/fc/apu/apu.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/apu/apu.hpp b/bsnes/fc/apu/apu.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/apu/dmc.cpp b/bsnes/fc/apu/dmc.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/apu/dmc.hpp b/bsnes/fc/apu/dmc.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/apu/envelope.cpp b/bsnes/fc/apu/envelope.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/apu/envelope.hpp b/bsnes/fc/apu/envelope.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/apu/noise.cpp b/bsnes/fc/apu/noise.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/apu/noise.hpp b/bsnes/fc/apu/noise.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/apu/pulse.cpp b/bsnes/fc/apu/pulse.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/apu/pulse.hpp b/bsnes/fc/apu/pulse.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/apu/serialization.cpp b/bsnes/fc/apu/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/apu/sweep.cpp b/bsnes/fc/apu/sweep.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/apu/sweep.hpp b/bsnes/fc/apu/sweep.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/apu/triangle.cpp b/bsnes/fc/apu/triangle.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/apu/triangle.hpp b/bsnes/fc/apu/triangle.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/cartridge/board/bandai-fcg.cpp b/bsnes/fc/cartridge/board/bandai-fcg.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/cartridge/board/board.cpp b/bsnes/fc/cartridge/board/board.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/cartridge/board/board.hpp b/bsnes/fc/cartridge/board/board.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/cartridge/board/konami-vrc1.cpp b/bsnes/fc/cartridge/board/konami-vrc1.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/cartridge/board/konami-vrc2.cpp b/bsnes/fc/cartridge/board/konami-vrc2.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/cartridge/board/konami-vrc3.cpp b/bsnes/fc/cartridge/board/konami-vrc3.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/cartridge/board/konami-vrc4.cpp b/bsnes/fc/cartridge/board/konami-vrc4.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/cartridge/board/konami-vrc6.cpp b/bsnes/fc/cartridge/board/konami-vrc6.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/cartridge/board/konami-vrc7.cpp b/bsnes/fc/cartridge/board/konami-vrc7.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/cartridge/board/nes-axrom.cpp b/bsnes/fc/cartridge/board/nes-axrom.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/cartridge/board/nes-bnrom.cpp b/bsnes/fc/cartridge/board/nes-bnrom.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/cartridge/board/nes-cnrom.cpp b/bsnes/fc/cartridge/board/nes-cnrom.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/cartridge/board/nes-exrom.cpp b/bsnes/fc/cartridge/board/nes-exrom.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/cartridge/board/nes-fxrom.cpp b/bsnes/fc/cartridge/board/nes-fxrom.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/cartridge/board/nes-gxrom.cpp b/bsnes/fc/cartridge/board/nes-gxrom.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/cartridge/board/nes-hkrom.cpp b/bsnes/fc/cartridge/board/nes-hkrom.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/cartridge/board/nes-nrom.cpp b/bsnes/fc/cartridge/board/nes-nrom.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/cartridge/board/nes-pxrom.cpp b/bsnes/fc/cartridge/board/nes-pxrom.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/cartridge/board/nes-sxrom.cpp b/bsnes/fc/cartridge/board/nes-sxrom.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/cartridge/board/nes-txrom.cpp b/bsnes/fc/cartridge/board/nes-txrom.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/cartridge/board/nes-uxrom.cpp b/bsnes/fc/cartridge/board/nes-uxrom.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/cartridge/board/sunsoft-5b.cpp b/bsnes/fc/cartridge/board/sunsoft-5b.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/cartridge/cartridge.cpp b/bsnes/fc/cartridge/cartridge.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/cartridge/cartridge.hpp b/bsnes/fc/cartridge/cartridge.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/cartridge/chip/chip.cpp b/bsnes/fc/cartridge/chip/chip.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/cartridge/chip/chip.hpp b/bsnes/fc/cartridge/chip/chip.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/cartridge/chip/mmc1.cpp b/bsnes/fc/cartridge/chip/mmc1.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/cartridge/chip/mmc3.cpp b/bsnes/fc/cartridge/chip/mmc3.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/cartridge/chip/mmc5.cpp b/bsnes/fc/cartridge/chip/mmc5.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/cartridge/chip/mmc6.cpp b/bsnes/fc/cartridge/chip/mmc6.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/cartridge/chip/vrc1.cpp b/bsnes/fc/cartridge/chip/vrc1.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/cartridge/chip/vrc2.cpp b/bsnes/fc/cartridge/chip/vrc2.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/cartridge/chip/vrc3.cpp b/bsnes/fc/cartridge/chip/vrc3.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/cartridge/chip/vrc4.cpp b/bsnes/fc/cartridge/chip/vrc4.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/cartridge/chip/vrc6.cpp b/bsnes/fc/cartridge/chip/vrc6.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/cartridge/chip/vrc7.cpp b/bsnes/fc/cartridge/chip/vrc7.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/cheat/cheat.cpp b/bsnes/fc/cheat/cheat.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/cheat/cheat.hpp b/bsnes/fc/cheat/cheat.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/cpu/cpu.cpp b/bsnes/fc/cpu/cpu.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/cpu/cpu.hpp b/bsnes/fc/cpu/cpu.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/cpu/serialization.cpp b/bsnes/fc/cpu/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/cpu/timing.cpp b/bsnes/fc/cpu/timing.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/fc.hpp b/bsnes/fc/fc.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/input/input.cpp b/bsnes/fc/input/input.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/input/input.hpp b/bsnes/fc/input/input.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/input/serialization.cpp b/bsnes/fc/input/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/interface/interface.cpp b/bsnes/fc/interface/interface.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/interface/interface.hpp b/bsnes/fc/interface/interface.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/memory/memory.cpp b/bsnes/fc/memory/memory.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/memory/memory.hpp b/bsnes/fc/memory/memory.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/ppu/ppu.cpp b/bsnes/fc/ppu/ppu.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/ppu/ppu.hpp b/bsnes/fc/ppu/ppu.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/ppu/serialization.cpp b/bsnes/fc/ppu/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/scheduler/scheduler.cpp b/bsnes/fc/scheduler/scheduler.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/scheduler/scheduler.hpp b/bsnes/fc/scheduler/scheduler.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/system/serialization.cpp b/bsnes/fc/system/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/system/system.cpp b/bsnes/fc/system/system.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/system/system.hpp b/bsnes/fc/system/system.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/video/video.cpp b/bsnes/fc/video/video.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/fc/video/video.hpp b/bsnes/fc/video/video.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/Makefile b/bsnes/gb/Makefile
old mode 100755
new mode 100644
diff --git a/bsnes/gb/apu/apu.cpp b/bsnes/gb/apu/apu.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/apu/apu.hpp b/bsnes/gb/apu/apu.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/apu/master/master.cpp b/bsnes/gb/apu/master/master.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/apu/master/master.hpp b/bsnes/gb/apu/master/master.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/apu/noise/noise.cpp b/bsnes/gb/apu/noise/noise.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/apu/noise/noise.hpp b/bsnes/gb/apu/noise/noise.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/apu/serialization.cpp b/bsnes/gb/apu/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/apu/square1/square1.cpp b/bsnes/gb/apu/square1/square1.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/apu/square1/square1.hpp b/bsnes/gb/apu/square1/square1.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/apu/square2/square2.cpp b/bsnes/gb/apu/square2/square2.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/apu/square2/square2.hpp b/bsnes/gb/apu/square2/square2.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/apu/wave/wave.cpp b/bsnes/gb/apu/wave/wave.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/apu/wave/wave.hpp b/bsnes/gb/apu/wave/wave.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/cartridge/cartridge.cpp b/bsnes/gb/cartridge/cartridge.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/cartridge/cartridge.hpp b/bsnes/gb/cartridge/cartridge.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/cartridge/huc1/huc1.cpp b/bsnes/gb/cartridge/huc1/huc1.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/cartridge/huc1/huc1.hpp b/bsnes/gb/cartridge/huc1/huc1.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/cartridge/huc3/huc3.cpp b/bsnes/gb/cartridge/huc3/huc3.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/cartridge/huc3/huc3.hpp b/bsnes/gb/cartridge/huc3/huc3.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/cartridge/mbc0/mbc0.cpp b/bsnes/gb/cartridge/mbc0/mbc0.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/cartridge/mbc0/mbc0.hpp b/bsnes/gb/cartridge/mbc0/mbc0.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/cartridge/mbc1/mbc1.cpp b/bsnes/gb/cartridge/mbc1/mbc1.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/cartridge/mbc1/mbc1.hpp b/bsnes/gb/cartridge/mbc1/mbc1.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/cartridge/mbc2/mbc2.cpp b/bsnes/gb/cartridge/mbc2/mbc2.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/cartridge/mbc2/mbc2.hpp b/bsnes/gb/cartridge/mbc2/mbc2.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/cartridge/mbc3/mbc3.cpp b/bsnes/gb/cartridge/mbc3/mbc3.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/cartridge/mbc3/mbc3.hpp b/bsnes/gb/cartridge/mbc3/mbc3.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/cartridge/mbc5/mbc5.cpp b/bsnes/gb/cartridge/mbc5/mbc5.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/cartridge/mbc5/mbc5.hpp b/bsnes/gb/cartridge/mbc5/mbc5.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/cartridge/mmm01/mmm01.cpp b/bsnes/gb/cartridge/mmm01/mmm01.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/cartridge/mmm01/mmm01.hpp b/bsnes/gb/cartridge/mmm01/mmm01.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/cartridge/serialization.cpp b/bsnes/gb/cartridge/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/cheat/cheat.cpp b/bsnes/gb/cheat/cheat.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/cheat/cheat.hpp b/bsnes/gb/cheat/cheat.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/cpu/cpu.cpp b/bsnes/gb/cpu/cpu.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/cpu/cpu.hpp b/bsnes/gb/cpu/cpu.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/cpu/memory.cpp b/bsnes/gb/cpu/memory.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/cpu/mmio.cpp b/bsnes/gb/cpu/mmio.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/cpu/serialization.cpp b/bsnes/gb/cpu/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/cpu/timing.cpp b/bsnes/gb/cpu/timing.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/gb.hpp b/bsnes/gb/gb.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/interface/interface.cpp b/bsnes/gb/interface/interface.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/interface/interface.hpp b/bsnes/gb/interface/interface.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/memory/memory.cpp b/bsnes/gb/memory/memory.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/memory/memory.hpp b/bsnes/gb/memory/memory.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/ppu/cgb.cpp b/bsnes/gb/ppu/cgb.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/ppu/dmg.cpp b/bsnes/gb/ppu/dmg.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/ppu/mmio.cpp b/bsnes/gb/ppu/mmio.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/ppu/ppu.cpp b/bsnes/gb/ppu/ppu.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/ppu/ppu.hpp b/bsnes/gb/ppu/ppu.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/ppu/serialization.cpp b/bsnes/gb/ppu/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/scheduler/scheduler.cpp b/bsnes/gb/scheduler/scheduler.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/scheduler/scheduler.hpp b/bsnes/gb/scheduler/scheduler.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/system/serialization.cpp b/bsnes/gb/system/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/system/system.cpp b/bsnes/gb/system/system.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/system/system.hpp b/bsnes/gb/system/system.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/video/video.cpp b/bsnes/gb/video/video.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gb/video/video.hpp b/bsnes/gb/video/video.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/Makefile b/bsnes/gba/Makefile
old mode 100755
new mode 100644
diff --git a/bsnes/gba/apu/apu.cpp b/bsnes/gba/apu/apu.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/apu/apu.hpp b/bsnes/gba/apu/apu.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/apu/fifo.cpp b/bsnes/gba/apu/fifo.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/apu/mmio.cpp b/bsnes/gba/apu/mmio.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/apu/noise.cpp b/bsnes/gba/apu/noise.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/apu/registers.cpp b/bsnes/gba/apu/registers.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/apu/registers.hpp b/bsnes/gba/apu/registers.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/apu/sequencer.cpp b/bsnes/gba/apu/sequencer.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/apu/serialization.cpp b/bsnes/gba/apu/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/apu/square.cpp b/bsnes/gba/apu/square.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/apu/square1.cpp b/bsnes/gba/apu/square1.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/apu/square2.cpp b/bsnes/gba/apu/square2.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/apu/wave.cpp b/bsnes/gba/apu/wave.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/cartridge/cartridge.cpp b/bsnes/gba/cartridge/cartridge.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/cartridge/cartridge.hpp b/bsnes/gba/cartridge/cartridge.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/cartridge/eeprom.cpp b/bsnes/gba/cartridge/eeprom.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/cartridge/flashrom.cpp b/bsnes/gba/cartridge/flashrom.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/cartridge/memory.hpp b/bsnes/gba/cartridge/memory.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/cartridge/serialization.cpp b/bsnes/gba/cartridge/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/cpu/cpu.cpp b/bsnes/gba/cpu/cpu.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/cpu/cpu.hpp b/bsnes/gba/cpu/cpu.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/cpu/dma.cpp b/bsnes/gba/cpu/dma.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/cpu/memory.cpp b/bsnes/gba/cpu/memory.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/cpu/mmio.cpp b/bsnes/gba/cpu/mmio.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/cpu/registers.cpp b/bsnes/gba/cpu/registers.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/cpu/registers.hpp b/bsnes/gba/cpu/registers.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/cpu/serialization.cpp b/bsnes/gba/cpu/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/cpu/state.hpp b/bsnes/gba/cpu/state.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/cpu/timer.cpp b/bsnes/gba/cpu/timer.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/gba.hpp b/bsnes/gba/gba.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/interface/interface.cpp b/bsnes/gba/interface/interface.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/interface/interface.hpp b/bsnes/gba/interface/interface.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/memory/memory.cpp b/bsnes/gba/memory/memory.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/memory/memory.hpp b/bsnes/gba/memory/memory.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/memory/mmio.cpp b/bsnes/gba/memory/mmio.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/memory/serialization.cpp b/bsnes/gba/memory/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/ppu/background.cpp b/bsnes/gba/ppu/background.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/ppu/memory.cpp b/bsnes/gba/ppu/memory.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/ppu/mmio.cpp b/bsnes/gba/ppu/mmio.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/ppu/mosaic.cpp b/bsnes/gba/ppu/mosaic.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/ppu/object.cpp b/bsnes/gba/ppu/object.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/ppu/ppu.cpp b/bsnes/gba/ppu/ppu.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/ppu/ppu.hpp b/bsnes/gba/ppu/ppu.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/ppu/registers.cpp b/bsnes/gba/ppu/registers.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/ppu/registers.hpp b/bsnes/gba/ppu/registers.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/ppu/screen.cpp b/bsnes/gba/ppu/screen.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/ppu/serialization.cpp b/bsnes/gba/ppu/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/ppu/state.hpp b/bsnes/gba/ppu/state.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/scheduler/scheduler.cpp b/bsnes/gba/scheduler/scheduler.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/scheduler/scheduler.hpp b/bsnes/gba/scheduler/scheduler.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/system/bios.cpp b/bsnes/gba/system/bios.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/system/serialization.cpp b/bsnes/gba/system/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/system/system.cpp b/bsnes/gba/system/system.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/system/system.hpp b/bsnes/gba/system/system.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/video/video.cpp b/bsnes/gba/video/video.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/gba/video/video.hpp b/bsnes/gba/video/video.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/libco/amd64.c b/bsnes/libco/amd64.c
old mode 100755
new mode 100644
diff --git a/bsnes/libco/fiber.c b/bsnes/libco/fiber.c
old mode 100755
new mode 100644
diff --git a/bsnes/libco/libco.c b/bsnes/libco/libco.c
old mode 100755
new mode 100644
diff --git a/bsnes/libco/libco.h b/bsnes/libco/libco.h
old mode 100755
new mode 100644
diff --git a/bsnes/libco/ppc.c b/bsnes/libco/ppc.c
old mode 100755
new mode 100644
diff --git a/bsnes/libco/sjlj.c b/bsnes/libco/sjlj.c
old mode 100755
new mode 100644
diff --git a/bsnes/libco/ucontext.c b/bsnes/libco/ucontext.c
old mode 100755
new mode 100644
diff --git a/bsnes/libco/x86.c b/bsnes/libco/x86.c
old mode 100755
new mode 100644
diff --git a/bsnes/nall/Makefile b/bsnes/nall/Makefile
old mode 100755
new mode 100644
diff --git a/bsnes/nall/algorithm.hpp b/bsnes/nall/algorithm.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/any.hpp b/bsnes/nall/any.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/atoi.hpp b/bsnes/nall/atoi.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/base64.hpp b/bsnes/nall/base64.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/bit.hpp b/bsnes/nall/bit.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/bmp.hpp b/bsnes/nall/bmp.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/bps/delta.hpp b/bsnes/nall/bps/delta.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/bps/linear.hpp b/bsnes/nall/bps/linear.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/bps/metadata.hpp b/bsnes/nall/bps/metadata.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/bps/patch.hpp b/bsnes/nall/bps/patch.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/compositor.hpp b/bsnes/nall/compositor.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/config.hpp b/bsnes/nall/config.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/crc32.hpp b/bsnes/nall/crc32.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/directory.hpp b/bsnes/nall/directory.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/dl.hpp b/bsnes/nall/dl.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/dsp.hpp b/bsnes/nall/dsp.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/dsp/buffer.hpp b/bsnes/nall/dsp/buffer.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/dsp/core.hpp b/bsnes/nall/dsp/core.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/dsp/resample/average.hpp b/bsnes/nall/dsp/resample/average.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/dsp/resample/cosine.hpp b/bsnes/nall/dsp/resample/cosine.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/dsp/resample/cubic.hpp b/bsnes/nall/dsp/resample/cubic.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/dsp/resample/hermite.hpp b/bsnes/nall/dsp/resample/hermite.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/dsp/resample/lib/sinc.hpp b/bsnes/nall/dsp/resample/lib/sinc.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/dsp/resample/linear.hpp b/bsnes/nall/dsp/resample/linear.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/dsp/resample/nearest.hpp b/bsnes/nall/dsp/resample/nearest.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/dsp/resample/sinc.hpp b/bsnes/nall/dsp/resample/sinc.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/dsp/settings.hpp b/bsnes/nall/dsp/settings.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/emulation/famicom.hpp b/bsnes/nall/emulation/famicom.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/emulation/game-boy-advance.hpp b/bsnes/nall/emulation/game-boy-advance.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/emulation/game-boy.hpp b/bsnes/nall/emulation/game-boy.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/emulation/satellaview.hpp b/bsnes/nall/emulation/satellaview.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/emulation/sufami-turbo.hpp b/bsnes/nall/emulation/sufami-turbo.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/emulation/super-famicom-usart.hpp b/bsnes/nall/emulation/super-famicom-usart.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/emulation/super-famicom.hpp b/bsnes/nall/emulation/super-famicom.hpp
old mode 100755
new mode 100644
index 597f9893..3115d7ea
--- a/bsnes/nall/emulation/super-famicom.hpp
+++ b/bsnes/nall/emulation/super-famicom.hpp
@@ -106,6 +106,9 @@ struct SuperFamicomCartridge {
};
SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size) {
+ //skip copier header
+ if((size & 0x7fff) == 512) data += 512, size -= 512;
+
markup = "";
if(size < 0x8000) return;
diff --git a/bsnes/nall/endian.hpp b/bsnes/nall/endian.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/file.hpp b/bsnes/nall/file.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/filemap.hpp b/bsnes/nall/filemap.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/function.hpp b/bsnes/nall/function.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/gzip.hpp b/bsnes/nall/gzip.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/http.hpp b/bsnes/nall/http.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/image.hpp b/bsnes/nall/image.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/inflate.hpp b/bsnes/nall/inflate.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/input.hpp b/bsnes/nall/input.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/interpolation.hpp b/bsnes/nall/interpolation.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/intrinsics.hpp b/bsnes/nall/intrinsics.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/invoke.hpp b/bsnes/nall/invoke.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/ips.hpp b/bsnes/nall/ips.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/lzss.hpp b/bsnes/nall/lzss.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/map.hpp b/bsnes/nall/map.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/mosaic.hpp b/bsnes/nall/mosaic.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/mosaic/bitstream.hpp b/bsnes/nall/mosaic/bitstream.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/mosaic/context.hpp b/bsnes/nall/mosaic/context.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/mosaic/parser.hpp b/bsnes/nall/mosaic/parser.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/nall.hpp b/bsnes/nall/nall.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/platform.hpp b/bsnes/nall/platform.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/png.hpp b/bsnes/nall/png.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/priority-queue.hpp b/bsnes/nall/priority-queue.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/property.hpp b/bsnes/nall/property.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/public-cast.hpp b/bsnes/nall/public-cast.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/random.hpp b/bsnes/nall/random.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/serial.hpp b/bsnes/nall/serial.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/serializer.hpp b/bsnes/nall/serializer.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/set.hpp b/bsnes/nall/set.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/sha256.hpp b/bsnes/nall/sha256.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/sort.hpp b/bsnes/nall/sort.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/stdint.hpp b/bsnes/nall/stdint.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/stream.hpp b/bsnes/nall/stream.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/stream/auto.hpp b/bsnes/nall/stream/auto.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/stream/file.hpp b/bsnes/nall/stream/file.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/stream/gzip.hpp b/bsnes/nall/stream/gzip.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/stream/http.hpp b/bsnes/nall/stream/http.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/stream/memory.hpp b/bsnes/nall/stream/memory.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/stream/mmap.hpp b/bsnes/nall/stream/mmap.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/stream/stream.hpp b/bsnes/nall/stream/stream.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/stream/vector.hpp b/bsnes/nall/stream/vector.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/stream/zip.hpp b/bsnes/nall/stream/zip.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/string.hpp b/bsnes/nall/string.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/string/base.hpp b/bsnes/nall/string/base.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/string/bml.hpp b/bsnes/nall/string/bml.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/string/bsv.hpp b/bsnes/nall/string/bsv.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/string/cast.hpp b/bsnes/nall/string/cast.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/string/compare.hpp b/bsnes/nall/string/compare.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/string/convert.hpp b/bsnes/nall/string/convert.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/string/core.hpp b/bsnes/nall/string/core.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/string/cstring.hpp b/bsnes/nall/string/cstring.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/string/filename.hpp b/bsnes/nall/string/filename.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/string/math-fixed-point.hpp b/bsnes/nall/string/math-fixed-point.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/string/math-floating-point.hpp b/bsnes/nall/string/math-floating-point.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/string/platform.hpp b/bsnes/nall/string/platform.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/string/replace.hpp b/bsnes/nall/string/replace.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/string/split.hpp b/bsnes/nall/string/split.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/string/static.hpp b/bsnes/nall/string/static.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/string/strm.hpp b/bsnes/nall/string/strm.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/string/strpos.hpp b/bsnes/nall/string/strpos.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/string/trim.hpp b/bsnes/nall/string/trim.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/string/utf8.hpp b/bsnes/nall/string/utf8.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/string/utility.hpp b/bsnes/nall/string/utility.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/string/variadic.hpp b/bsnes/nall/string/variadic.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/string/wildcard.hpp b/bsnes/nall/string/wildcard.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/string/wrapper.hpp b/bsnes/nall/string/wrapper.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/string/xml-legacy.hpp b/bsnes/nall/string/xml-legacy.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/string/xml.hpp b/bsnes/nall/string/xml.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/traits.hpp b/bsnes/nall/traits.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/udl.hpp b/bsnes/nall/udl.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/ups.hpp b/bsnes/nall/ups.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/utility.hpp b/bsnes/nall/utility.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/varint.hpp b/bsnes/nall/varint.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/vector.hpp b/bsnes/nall/vector.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/windows/detour.hpp b/bsnes/nall/windows/detour.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/windows/guid.hpp b/bsnes/nall/windows/guid.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/windows/launcher.hpp b/bsnes/nall/windows/launcher.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/windows/registry.hpp b/bsnes/nall/windows/registry.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/windows/utf8.hpp b/bsnes/nall/windows/utf8.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/xorg/guard.hpp b/bsnes/nall/xorg/guard.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/xorg/xorg.hpp b/bsnes/nall/xorg/xorg.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nall/zip.hpp b/bsnes/nall/zip.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/nds/Makefile b/bsnes/nds/Makefile
new file mode 100644
index 00000000..43007231
--- /dev/null
+++ b/bsnes/nds/Makefile
@@ -0,0 +1,16 @@
+nds_objects := nds-interface
+nds_objects += nds-cpu nds-apu nds-ppu nds-gpu nds-video
+nds_objects += nds-memory nds-system nds-slot1 nds-slot2 nds-wifi
+objects += $(nds_objects)
+
+obj/nds-interface.o: $(nds)/interface/interface.cpp $(call rwildcard,$(nds)/interface)
+obj/nds-cpu.o: $(nds)/cpu/cpu.cpp $(call rwildcard,$(nds)/cpu)
+obj/nds-apu.o: $(nds)/apu/apu.cpp $(call rwildcard,$(nds)/apu)
+obj/nds-ppu.o: $(nds)/ppu/ppu.cpp $(call rwildcard,$(nds)/ppu)
+obj/nds-gpu.o: $(nds)/gpu/gpu.cpp $(call rwildcard,$(nds)/gpu)
+obj/nds-video.o: $(nds)/video/video.cpp $(call rwildcard,$(nds)/video)
+obj/nds-memory.o: $(nds)/memory/memory.cpp $(call rwildcard,$(nds)/memory)
+obj/nds-system.o: $(nds)/system/system.cpp $(call rwildcard,$(nds)/system)
+obj/nds-slot1.o: $(nds)/slot1/slot1.cpp $(call rwildcard,$(nds)/slot1)
+obj/nds-slot2.o: $(nds)/slot2/slot2.cpp $(call rwildcard,$(nds)/slot2)
+obj/nds-wifi.o: $(nds)/wifi/wifi.cpp $(call rwildcard,$(nds)/wifi)
\ No newline at end of file
diff --git a/bsnes/nds/apu/apu.cpp b/bsnes/nds/apu/apu.cpp
new file mode 100644
index 00000000..3e80d320
--- /dev/null
+++ b/bsnes/nds/apu/apu.cpp
@@ -0,0 +1,403 @@
+#include
+
+namespace NintendoDS {
+
+APU apu;
+
+
+void APU::power() {
+ for(unsigned n = 0; n < 16; n++) {
+ auto &v = voices[n];
+
+ v.enable = false;
+ v.hold = false;
+ v.running = false;
+ v.format = Voice::PCM8;
+ v.duty = 0;
+ v.limit = 0;
+ v.panning = 0x40;
+ v.volumeBase = 0x7f;
+ v.volumeExp = 0;
+ v.amplitude = 0x7f0;
+
+ v.source = 0;
+ v.length = 0;
+ v.counter = 0;
+ v.sample = 0;
+
+ v.init.source = 0;
+ v.init.counter = 0;
+ v.init.length1 = 0;
+ v.init.length2 = 0;
+
+ v.event.action = [&, n]() { stepVoice(n); };
+ }
+ // Audio runs at 16.8MHz. I've somewhat arbitrarily set
+ // it up so that things run in the following order:
+ // - channel read + update (+0)
+ // - mixer (+1)
+ // - eventually, capture (+2)
+ //
+ // Mixer runs at 33Khz = 66 MHz / 2048
+ mixEvent.action = [&]() { stepMixer(); };
+ arm7.event.queue.add(2048+1, mixEvent);
+
+ powered = true;
+}
+
+void APU::stepMixer() {
+ arm7.event.queue.add(2048, mixEvent);
+
+ int64 l = 0, r = 0;
+
+ for(unsigned n = 0; n < 16; n++) {
+ auto &v = voices[n];
+ int64 s = v.sample * v.amplitude;
+
+ l += s * (128 - v.panning);
+ r += s * (0 + v.panning);
+ }
+ l = sclamp<16>(l / 0x80000);
+ r = sclamp<16>(r / 0x80000);
+
+ interface->audioSample(l, r);
+}
+
+void APU::stepVoice(unsigned no) {
+ auto &v = voices[no];
+
+ uint32 t = arm7.event.queue.time;
+
+ if(v.format == Voice::PCM8) stepPCM8(no);
+ else if(v.format == Voice::PCM16) stepPCM16(no);
+ else if(v.format == Voice::ADPCM4) stepADPCM4(no);
+ else if(v.format == Voice::PSG && no >= 14) stepNoise(no);
+ else if(v.format == Voice::PSG && no >= 8) stepPulse(no);
+
+ v.counter = v.init.counter;
+
+ uint32 fetchTime = arm7.event.queue.time - t;
+ uint32 nextSample = 4*(0x10000 - v.counter);
+
+ nextSample -= fetchTime;
+ if(unsigned k = t & 3)
+ nextSample += 4 - k;
+
+ // When this happens, the buffering can't keep up. It isn't clear
+ // what the real system will do, but it can't be anything good...
+ if(nextSample >= 0x80000000)
+ nextSample = 0;
+
+ // This requires further thought and investigation.
+ // Do buffering issues delay the playback timer? (hopefully not)
+ // Do audio DMAs interleave in any way? (doubtful; it'd be 10x slower)
+ if(v.running)
+ arm7.event.queue.add(nextSample, v.event);
+}
+
+void APU::stepPulse(unsigned no) {
+ auto &v = voices[no];
+ uint3 step = v.state--;
+
+ v.sample = step > v.duty? -0x7fff : +0x7fff;
+}
+
+void APU::stepNoise(unsigned no) {
+ auto &v = voices[no];
+ bool out = v.state & 1;
+
+ v.state >>= 1;
+ v.state ^= 0x6000*out;
+ v.sample = out? -0x7fff : +0x7fff;
+}
+
+void APU::stepPCM8(unsigned no) {
+ auto &v = voices[no];
+
+ checkLength(no);
+ fillBuffer(no);
+ v.sample = 0x100*int8(v.buffer[v.index/8] >> 4*(v.index & 6));
+ v.index += 2;
+ v.length -= 1;
+}
+
+void APU::stepPCM16(unsigned no) {
+ auto &v = voices[no];
+
+ checkLength(no);
+ fillBuffer(no);
+ v.sample = int16(v.buffer[v.index/8] >> 4*(v.index & 4));
+ v.index += 4;
+ v.length -= 2;
+}
+
+void APU::stepADPCM4(unsigned no) {
+ auto &v = voices[no];
+
+ static const int16 table[] = {
+ 0x0007,0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,
+ 0x0010,0x0011,0x0013,0x0015,0x0017,0x0019,0x001c,0x001f,
+ 0x0022,0x0025,0x0029,0x002d,0x0032,0x0037,0x003c,0x0042,
+ 0x0049,0x0050,0x0058,0x0061,0x006b,0x0076,0x0082,0x008f,
+ 0x009d,0x00ad,0x00be,0x00d1,0x00e6,0x00fd,0x0117,0x0133,
+ 0x0151,0x0173,0x0198,0x01c1,0x01ee,0x0220,0x0256,0x0292,
+ 0x02d4,0x031c,0x036c,0x03c3,0x0424,0x048e,0x0502,0x0583,
+ 0x0610,0x06ab,0x0756,0x0812,0x08e0,0x09c3,0x0abd,0x0bd0,
+ 0x0cff,0x0e4c,0x0fba,0x114c,0x1307,0x14ee,0x1706,0x1954,
+ 0x1bdc,0x1ea5,0x21b6,0x2515,0x28ca,0x2cdf,0x315b,0x364b,
+ 0x3bb9,0x41b2,0x4844,0x4f7e,0x5771,0x602f,0x69ce,0x7462,
+ 0x7fff
+ };
+
+ checkLength(no);
+ fillBuffer(no);
+
+ if(v.state == 0x7fff) {
+ uint32 header = v.buffer[0];
+
+ // Minimum length is 4 words anyway, but check this later..
+ v.sample = header>>0;
+ v.state = min(88, header>>16 & 0x7f);
+ v.index += 8;
+ v.length -= 4;
+ }
+
+ int4 s = v.buffer[v.index/8] >> 4*(v.index & 7);
+ int16 x = table[v.state--];
+
+ int16 delta = x/8;
+ if(s & 1) delta += x/4;
+ if(s & 2) delta += x/2;
+ if(s & 4) delta += x/1, v.state += 2*(s & 3) + 3;
+
+ if(s < 0) v.sample = max(-0x7fff, v.sample - delta);
+ else v.sample = min(+0x7fff, v.sample + delta);
+
+ v.state = max(0, min(88, v.state));
+
+ if(++v.index & 1) return;
+ v.length -= 1;
+}
+
+
+
+void APU::stopVoice(unsigned no) {
+ auto &v = voices[no];
+
+ arm7.event.queue.remove(v.event);
+ v.running = false;
+ if(v.hold == false)
+ v.sample = 0;
+}
+
+void APU::fillBuffer(unsigned no) {
+ auto &v = voices[no];
+ if(v.index) return;
+
+ for(unsigned i = 0; i < 4; i++, v.source += 4)
+ v.buffer[i] = arm7.read(v.source, Word, true);
+}
+
+void APU::checkLength(unsigned no) {
+ auto &v = voices[no];
+ if(v.length) return;
+
+ if(v.loop.source == 0xffffffff) {
+ // We're passing the loop point for the first time. In particular
+ // the hardware will store the ADPCM state. For this reason it's not
+ // possible to stream ADPCM audio without software assist. :(
+ v.length = v.loop.length;
+ v.loop.sample = v.sample;
+ v.loop.state = v.state;
+ v.loop.source = v.source;
+ if(v.index) // Account for buffer
+ v.loop.source += 4*(v.index/8 - 4);
+
+ if(v.limit && v.length < 4)
+ return stopVoice(no);
+ }
+ else {
+ if(v.limit & Voice::once)
+ return stopVoice(no);
+
+ // There are still issues with loops here.. or possibly
+ // readback of the voice status.
+ if(v.limit & Voice::looped) {
+ v.source = v.loop.source;
+ v.length = v.loop.length;
+ v.sample = v.loop.sample;
+ v.state = v.loop.state;
+ v.index = 0;
+ }
+ }
+}
+
+void APU::checkEnable(unsigned no) {
+ auto &v = voices[no];
+
+ // maxmod's interpolated mode expects this undocumented behavior. Instead
+ // of software mixing, it resamples each voice's audio into a small buffer.
+ // Master enable is used to trigger every voice at the same time.
+ if(v.running == (enable && v.enable)) return;
+
+ stopVoice(no);
+ v.running = enable && v.enable;
+ if(!v.running) return;
+
+ uint32 next = 4*(0x10000 - v.init.counter);
+
+ if(unsigned k = arm7.event.queue.time & 3)
+ next += 4 - k; // Align to 16MHz audio clock
+
+ arm7.event.queue.add(next, v.event);
+
+ // After 1 sample..
+ v.length = 1;
+ v.event.action = [&, no]() {
+ uint32 period = 4*(0x10000 - v.init.counter);
+
+ // Start the channel. From testing, it seems impossible to adjust
+ // length1/2 afterwards, so the settings must be latched somewhere.
+ // The loop flags can be changed though.
+ v.source = v.init.source;
+ v.counter = v.init.counter;
+ v.length = 4*v.init.length1;
+ v.loop.length = 4*v.init.length2;
+ v.loop.source = 0xffffffff;
+ v.sample = 0;
+ v.index = 0;
+ v.state = 0x7fff;
+
+ // PCM has a couple more samples of startup latency.
+ // ADPCM takes a further 8 samples to process the header..
+ switch(v.format) {
+ case Voice::PCM8: // add further startup latency
+ case Voice::PCM16: period = 3*period; break;
+ case Voice::ADPCM4: period = 11*period; break;
+ case Voice::PSG: period = 1*period; break;
+ }
+
+ unsigned k = arm7.event.queue.time & 3;
+ if(k) period += 4 - k;
+
+ arm7.event.queue.add(period, v.event);
+ v.event.action = [&, no]() { stepVoice(no); };
+ };
+}
+
+
+uint32 APU::regControl() {
+ return volume<<0 | output[0]<<8 | output[1]<<10 | muteDsp[0]<<12 | muteDsp[1]<<13 | enable<<15;
+}
+
+uint32 APU::regBias() {
+ return bias;
+}
+
+uint32 APU::regCaptureControl() {
+ return capture[0]<<7 | capture[1]<<15;
+}
+
+uint32 APU::regCaptureDest(unsigned no) {
+ return captureDest[no];
+}
+
+
+
+void APU::regControl(uint32 data, uint32 mask) {
+ if(mask & 0x00ff) {
+ volume = data >> 0;
+ }
+ if(mask & 0xff00) {
+ output[0] = data >> 8;
+ output[1] = data >> 10;
+ muteDsp[0] = data >> 12;
+ muteDsp[1] = data >> 13;
+ enable = data >> 15;
+
+ if(enable) {
+ // Start any pending voices - maxmod uses this for interpolated mode.
+ // What it does is:
+ // - clear the master enable
+ // - enable all 16 channels (won't do anything yet)
+ // - set the master enable (this will trigger all 16 at once)
+ // - wait ~16K clocks @ 33Mhz (16 samples), then set the mixing timer.
+ for(unsigned no = 0; no < 16; no++)
+ checkEnable(no);
+ }
+ }
+}
+
+void APU::regBias(uint32 data, uint32 mask) {
+ bias = data;
+}
+
+void APU::regCaptureControl(uint32 data, uint32 mask) {
+ capture[0] = data>>7;
+ capture[1] = data>>15;
+}
+
+void APU::regCaptureDest(unsigned no, uint32 data, uint32 mask) {
+ captureDest[no] = data;
+}
+
+void APU::regCaptureLength(unsigned no, uint32 data, uint32 mask) {
+ captureLength[no] = data;
+}
+
+
+
+uint32 APU::regVoiceControl(unsigned no) {
+ auto &v = voices[no];
+
+ return v.volumeBase<<0 | v.volumeExp<<8 | v.hold<<15 | v.panning<<16
+ | v.duty<<24 | v.limit<<27 | v.format<<29 | (v.running)<<31;
+}
+
+void APU::regVoiceControl(unsigned no, uint32 data, uint32 mask) {
+ auto &v = voices[no];
+
+ int exponent[] = { 4, 3, 2, 0 };
+
+ if(mask & 0x0000007f) {
+ v.volumeBase = data >> 0;
+ v.amplitude = v.volumeBase << exponent[v.volumeExp];
+ }
+ if(mask & 0x00008300) {
+ v.volumeExp = data >> 8;
+ v.hold = data >> 15;
+ v.amplitude = v.volumeBase << exponent[v.volumeExp];
+ }
+ if(mask & 0x007f0000) {
+ v.panning = data >> 16;
+ }
+ if(mask & 0xff000000) {
+ v.duty = data >> 24;
+ v.limit = data >> 27;
+ v.format = data >> 29;
+ v.enable = data >> 31;
+
+ checkEnable(no);
+ }
+}
+
+void APU::regVoiceSource(unsigned no, uint32 data, uint32 mask) {
+ auto &v = voices[no];
+
+ v.init.source = data & 0x07fffffc;
+}
+
+void APU::regVoicePeriod(unsigned no, uint32 data, uint32 mask) {
+ auto &v = voices[no];
+
+ if(mask & 0x0000ffff) v.init.counter ^= (v.init.counter ^ data>>0) & mask>>0;
+ if(mask & 0xffff0000) v.init.length1 ^= (v.init.length1 ^ data>>16) & mask>>16;
+}
+
+void APU::regVoiceLength(unsigned no, uint32 data, uint32 mask) {
+ auto &v = voices[no];
+
+ v.init.length2 ^= (v.init.length2 ^ data) & mask & 0x3fffff;
+}
+
+}
diff --git a/bsnes/nds/apu/apu.hpp b/bsnes/nds/apu/apu.hpp
new file mode 100644
index 00000000..7673fad7
--- /dev/null
+++ b/bsnes/nds/apu/apu.hpp
@@ -0,0 +1,100 @@
+
+struct APU {
+ void power();
+
+ void stepMixer();
+
+ void stepVoice(unsigned no);
+ void stepPCM8(unsigned no);
+ void stepPCM16(unsigned no);
+ void stepADPCM4(unsigned no);
+ void stepPulse(unsigned no);
+ void stepNoise(unsigned no);
+
+ void stopVoice(unsigned no);
+ void fillBuffer(unsigned no);
+ void checkLength(unsigned no);
+ void checkEnable(unsigned no);
+
+
+ uint32 regControl();
+ uint32 regBias();
+ uint32 regCaptureControl();
+ uint32 regCaptureDest(unsigned no);
+ uint32 regVoiceControl(unsigned no);
+
+ void regControl(uint32 data, uint32 mask);
+ void regBias(uint32 data, uint32 mask);
+ void regCaptureControl(uint32 data, uint32 mask);
+ void regCaptureDest(unsigned no, uint32 data, uint32 mask);
+ void regCaptureLength(unsigned no, uint32 data, uint32 mask);
+
+ void regVoiceControl(unsigned no, uint32 data, uint32 mask);
+ void regVoiceSource(unsigned no, uint32 data, uint32 mask);
+ void regVoicePeriod(unsigned no, uint32 data, uint32 mask);
+ void regVoiceLength(unsigned no, uint32 data, uint32 mask);
+
+
+
+ struct Voice {
+ uint1 enable, hold, running;
+ uint2 format; enum { PCM8, PCM16, ADPCM4, PSG };
+ uint3 duty;
+ uint2 limit; enum { looped=1, once=2 };
+ uint7 panning;
+
+ // Volume is essentially some kind of float format.
+ // The effective value is base * 2^-(4 >> (3-exponent)).
+ uint7 volumeBase;
+ uint2 volumeExp;
+
+ struct {
+ uint32 source;
+ uint16 counter;
+ uint16 length1;
+ uint32 length2;
+ } init;
+
+ struct {
+ uint32 source;
+ uint32 length;
+ int16 sample;
+ int16 state;
+ } loop;
+
+ uint32 source;
+ uint32 length;
+ uint16 counter;
+
+ Event event;
+
+ uint5 index; // nibble index into 16-byte buffer
+ uint32 buffer[4]; // holds 8, 16, or 32 buffered samples
+ int16 state; // used for pulse, noise, and ADPCM
+
+ int32 amplitude;
+ int16 sample;
+ } voices[16];
+
+ Event mixEvent;
+
+ // Voices 0 + 2 (L,R) are designated here as streaming audio.
+ // Voices 1 + 3 (L,R) are meant for DSP effects. Both are optional though.
+ uint1 powered;
+ uint1 enable;
+ uint10 bias;
+ uint7 volume;
+ uint2 output[2]; enum { srcMixer, srcDspL, srcDspR, srcDspMono };
+ uint1 muteDsp[2]; // Don't send 1+3 to the mixer - avoids feedback.
+ uint1 dspToStream[3]; // Mix 1+3 back into 0+2.
+
+ // Capture enables writing mixed audio to RAM - and in conjunction with
+ // voices 1 + 3, allows software DSP such as filtering or echo effects.
+ uint1 capture[2]; // Enable capturing
+ uint1 captureStream[2]; // ..otherwise mixer outputs
+ uint32 captureDest[2];
+ uint32 captureLength[2];
+ uint32 captureCount[2];
+};
+
+extern APU apu;
\ No newline at end of file
diff --git a/bsnes/nds/cpu/arm.cpp b/bsnes/nds/cpu/arm.cpp
new file mode 100644
index 00000000..d47eb0b3
--- /dev/null
+++ b/bsnes/nds/cpu/arm.cpp
@@ -0,0 +1,230 @@
+
+void ARMCore::armWritePsr(uint1 opcode, uint4 mask, uint32 rm) {
+ r[15] += 4;
+
+ if(opcode == 0) return writeCpsr(rm, mask);
+ if(opcode == 1) {
+ if(mode == USR || mode == SYS) return;
+
+ uint32 update = 0xff000000*(mask>>3) | 0xff*(mask&1);
+ spsr() ^= (spsr() ^ rm) & update;
+ }
+}
+
+void ARMCore::armReadPsr(uint1 opcode, uint4 ird) {
+ r[15] += 4;
+
+ if(opcode == 0) r[ird] = readCpsr();
+ if(opcode == 1) {
+ if(mode == USR || mode == SYS) return;
+ r[ird] = spsr();
+ }
+ if(ird == 15) branch(0, r[15]);
+}
+
+void ARMCore::armBranch(uint1 link, uint1 exch, int26 offset) {
+ if(link) r[14] = r[15] - 4;
+ branch(exch, r[15] + offset);
+}
+
+void ARMCore::armBranchEx(uint1 link, uint4 irm) {
+ if(link) r[14] = r[15] - 4;
+ branch(r[irm] & 1, r[irm]);
+}
+
+void ARMCore::armClz(uint4 ird, uint4 irm) {
+ auto &rd = r[ird], rm = r[irm];
+ r[15] += 4;
+
+ if(rm == 0) { rd = 32; return; }
+
+ rd = 0;
+ while(~rm & 1<<31)
+ rm <<= 1, rd++;
+}
+
+void ARMCore::armDspAdd(uint2 opcode, uint4 ird, uint4 irn, uint4 irm) {
+ auto &rd = r[ird], rn = r[irn], rm = r[irm];
+ r[15] += 4;
+
+ if(opcode & 2) { // qdadd/qdsub
+ rd = rm, rm += rm;
+ if(oflow(rm,rd,rd) & 1<<31)
+ Qf = -1, rm = 0x80000000 - (rm>>31);
+ }
+ if(opcode & 1) rd = rn - rm, (rm = ~rm); // qsub
+ else rd = rn + rm; // qadd
+
+ if(oflow(rd,rn,rm) & 1<<31)
+ Qf = -1, rd = 0x80000000 - (rd>>31);
+
+ if(ird == 15) branch(0, r[15]);
+}
+
+void ARMCore::armDspMul(uint2 opcode, uint2 xy, uint4 ird, uint4 irn, uint4 irm, uint4 irs) {
+ auto rn = r[irn];
+ r[15] += 4;
+
+ if(opcode == 1) { // smulwy, smlawy
+ int32 rm = r[irm];
+ int16 rs = r[irs] >> 16*(xy>>1);
+ uint32 rd = (int64) rm * rs >> 16;
+
+ if(xy & 1) {
+ uint32 ra = rd + rn;
+ Qf |= oflow(ra,rd,rn);
+ rd = ra;
+ }
+ r[ird] = rd;
+ }
+ else { // smulxy(3), smlaxy(0), smlalxy(2)
+ int16 rm = r[irm] >> 16*(xy & 1);
+ int16 rs = r[irs] >> 16*(xy>>1);
+ int64 rd = (int64) rm * rs;
+
+ if(opcode == 0) Qf |= oflow(rd+rn, rd, rn); // smlaxy
+ if(opcode != 3 /*accumulate*/) rd += rn; // smlaxy, smlalxy
+ if(opcode == 2 /*long*/) {
+ r[irn] = rd; rd >>= 32;
+ rd += r[ird];
+ if(irn == 15) branch(0, r[15]);
+ }
+ r[ird] = rd;
+ }
+ if(ird == 15) branch(0, r[15]);
+}
+
+void ARMCore::armMultiply(uint4 opcode, uint4 ird, uint4 irn, uint4 irm, uint4 irs) {
+ bool long_mul = opcode & 8, accumulate = opcode & 2;
+ bool signed_mul = opcode & 4, setf = opcode & 1;
+
+ auto rm = r[irm], rs = r[irs], rn = r[irn];
+ int64 rd = (uint64) rm * rs;
+ r[15] += 4;
+
+ if(setf) Zf = 0;
+ if(accumulate) rd += rn;
+ if(long_mul) {
+ r[irn] = rd; rd >>= 32;
+
+ if(setf) Zf |= r[irn];
+ if(accumulate) rd += r[ird];
+ if(signed_mul) {
+ if(rm & 1<<31) rd -= rs;
+ if(rs & 1<<31) rd -= rm;
+ }
+ }
+ r[ird] = rd;
+ if(setf) Nf = r[ird], Zf |= r[ird];
+ if(ird == 15) branch(0, r[15]);
+}
+
+void ARMCore::armData(uint5 opcode, uint4 ird, uint4 irn, SOut rm) {
+ auto rn = r[irn];
+ r[15] += 4;
+
+ alu(opcode, r[ird], rn, rm);
+
+ if(ird == 15 && (opcode & 1)) writeCpsr(spsr(), 0xf);
+ if(ird == 15) branch(Tf, r[15]); // use Tf here because MOVS/SUBS changes it
+}
+
+void ARMCore::armDataRs(uint5 opcode, uint4 ird, uint4 irn, uint4 irm, uint2 sh, uint4 irs) {
+ auto rs = r[irs];
+ r[15] += 4;
+
+ if(sh == 0) alu(opcode, r[ird], r[irn], lsl(r[irm], rs));
+ if(sh == 1) alu(opcode, r[ird], r[irn], lsr(r[irm], rs));
+ if(sh == 2) alu(opcode, r[ird], r[irn], asr(r[irm], rs));
+ if(sh == 3) alu(opcode, r[ird], r[irn], ror(r[irm], rs));
+
+ if(ird == 15 && (opcode & 1)) writeCpsr(spsr(), 0xf);
+ if(ird == 15) branch(Tf, r[15]);
+}
+
+void ARMCore::armMemSwap(uint1 opcode, uint4 ird, uint4 irn, uint4 irm) {
+ auto rn = r[irn];
+ r[15] += 4;
+
+ uint32 rd = load(rn, opcode? Byte : Word);
+ store(rn, opcode? Byte : Word, r[irm]);
+ r[ird] = rd;
+ if(ird == 15) branch(r[15] & 1, r[15]);
+}
+
+void ARMCore::armMem(uint5 opcode, uint4 ird, uint4 irn, uint32 rm) {
+ auto &rd = r[ird], &rn = r[irn];
+ uint32 update = opcode & 0x08? rn+rm : rn-rm;
+ uint32 addr = opcode & 0x10? update : rn;
+ r[15] += 4;
+
+ if((opcode & 2) || !(opcode & 0x10)) rn = update;
+
+ if(opcode & 1) rd = load(addr, opcode & 4? Byte : Word); // ldr, ldrb
+ else store(addr, opcode & 4? Byte : Word, rd); // str, strb
+
+ if(ird == 15) branch(r[15] & 1, r[15]);
+}
+
+void ARMCore::armMem_v4(uint5 opcode, uint2 sh, uint4 ird, uint4 irn, uint32 rm) {
+ auto &rd = r[ird], &rn = r[irn];
+ uint32 update = opcode & 0x08? rn+rm : rn-rm;
+ uint32 addr = opcode & 0x10? update : rn;
+ r[15] += 4;
+
+ if((opcode & 2) || !(opcode & 0x10)) rn = update;
+
+ if(opcode & 1) {
+ if(sh == 1) rd = load(addr, Half); // ldrh
+ if(sh == 3) rd = (int16) load(addr, Half); // ldrsh
+ if(sh == 2) rd = (int8) load(addr, Byte); // ldrsb
+ if(ird == 15) branch(r[15] & 1, r[15]);
+ } else {
+ if(sh == 1) store(addr, Half, rd); // strh
+ }
+}
+
+void ARMCore::armMem_v5(uint5 opcode, uint2 sh, uint4 ird, uint4 irn, uint32 rm) {
+ auto &rd = r[ird], &rn = r[irn];
+ uint32 update = opcode & 0x08? rn+rm : rn-rm;
+ uint32 addr = opcode & 0x10? update : rn;
+ r[15] += 4;
+
+ if((opcode & 2) || !(opcode & 0x10)) rn = update;
+
+ if(~opcode & 1) {
+ if(sh == 3) { store(addr, Word, r[ird&~1]); store(addr+4, Word, r[ird|1]); } // strd
+ if(sh == 2) { r[ird&~1] = load(addr, Word); r[ird|1] = load(addr+4, Word); // ldrd
+ if(ird >= 14) branch(r[15] & 1, r[15]); }
+ }
+}
+
+void ARMCore::armBlock(uint5 opcode, uint4 irn, uint16 rlist) {
+ unsigned index = opcode & 0x18, up = opcode & 0x08;
+ bool writeback = opcode & 0x02, ld = opcode & 0x01;
+ bool user = (opcode & 4) && !(ld && (rlist & 1<<15));
+ auto &rn = r[irn];
+ uint32 addr = rn, base = rn, size = 4*bit::count(rlist);
+ r[15] += 4;
+
+ if(index == 0x00) addr += 4 - size; // da
+ if(index == 0x10) addr += 0 - size; // db
+ if(index == 0x18) addr += 4; // ib
+
+ if(user) swapBank(mode);
+
+ for(unsigned b = 0, s = 0; b < 16; b++) {
+ if(~rlist & 1<= 0; j--)
+ crc = crc>>1 ^ (crc&1) * (table[j] << j);
+ }
+ return crc;
+}
+
+void ARM7TDMI::main() {
+ if(auto card = slot1.card) {
+ // ARM7 BIOS and firmware should be doing this, but it requires
+ // clock, card emulation and fancy things like that.
+ uint32 arm9src = card->rom.read(0x20, Word), arm7src = card->rom.read(0x30, Word);
+ uint32 arm9entry = card->rom.read(0x24, Word), arm7entry = card->rom.read(0x34, Word);
+ uint32 arm9dest = card->rom.read(0x28, Word), arm7dest = card->rom.read(0x38, Word);
+ uint32 arm9size = card->rom.read(0x2c, Word), arm7size = card->rom.read(0x3c, Word);
+
+ // Copy user settings to RAM
+ // - Homebrew and games (?) both require this. libnds actually attempts
+ // to read the settings from flash, but the struct contains a bitfield
+ // that GCC expands by 2 bytes, throwing the size and checksum off.
+ for(unsigned n = 0; n < 0x70; n += 1) {
+ store(0x02fffc80+n, Byte, system.firmware.read(0x3fe00+n, Byte));
+ }
+
+ // Check CRCs on firmware data and warn if incorrect
+ uint8 *wifiData = &system.firmware.data[0x0002a];
+
+ uint8 *wfcData[3] = {
+ &system.firmware.data[0x3fa00],
+ &system.firmware.data[0x3fb00],
+ &system.firmware.data[0x3fc00],
+ };
+ uint8 *userData[2] = {
+ &system.firmware.data[0x3fe00],
+ &system.firmware.data[0x3ff00],
+ };
+
+ // MAC address + Wifi chipset programming data
+ uint32 wifiDataLen = wifiData[2] | wifiData[3]<<8;
+ uint32 wifiDataExpected = wifiData[0] | wifiData[1]<<8;
+ uint32 wifiDataActual = crc16(wifiData+2, wifiDataLen, 0);
+
+ if(wifiDataExpected != wifiDataActual)
+ print("Warning: Wifi chipset data: crc is ",
+ hex<4>(wifiDataActual),"; expected ",hex<4>(wifiDataExpected),"\n");
+
+ // Nintendo Wifi Connection - access point IDs + WEP passwords
+ for(unsigned i = 0; i < 3; i++) {
+ uint32 expected = wfcData[i][0xfe] | wfcData[i][0xff]<<8;
+ uint32 actual = crc16(wfcData[i], 0xfe, 0);
+
+ if(expected != actual)
+ print("Warning: WFC access point #",i,": crc is ",
+ hex<4>(actual),"; expected ",hex<4>(expected),"\n");
+ }
+
+ // User settings area - nickname, birthday, favorite color etc.
+ for(unsigned i = 0; i < 2; i++) {
+ uint32 expected = userData[i][0x72] | userData[i][0x73]<<8;
+ uint32 actual = crc16(userData[i], 0x70, 0xffff);
+
+ if(expected != actual)
+ print("Warning: User settings #",i,": crc is ",
+ hex<4>(actual),"; expected ",hex<4>(expected),"\n");
+ }
+
+ // Copy header into RAM
+ for(unsigned n = 0; n < 0x200; n += 4) {
+ write(0x02fffe00+n, Word, 0, card->rom.read(n, Word));
+ }
+
+ // Copy executables
+ if(0x200 <= arm9src && arm9src + arm9size <= card->rom.size) {
+ if(0x02000000 <= arm9dest && arm9dest + arm9size <= 0x023bfe00) {
+ for(unsigned n = 0; n < arm9size; n += 4)
+ write(arm9dest + n, Word, 0, card->rom.read(arm9src + n, Word));
+ }
+ }
+ if(0x200 <= arm7src && arm7src + arm7size <= card->rom.size) {
+ if(0x02000000 <= arm7dest && arm7dest + arm7size <= 0x023bfe00
+ || 0x037f8000 <= arm7dest && arm7dest + arm7size <= 0x03807e00) {
+ for(unsigned n = 0; n < arm7size; n += 4)
+ write(arm7dest + n, Word, 0, card->rom.read(arm7src + n, Word));
+ }
+ }
+ // Should write the card's ROM ID to RAM too... where is it again?
+ arm7.booted = 0;
+ arm9.booted = 0;
+
+ arm7.writeCpsr(0xdf, 0xf);
+ arm7.branch(arm7entry & 1, arm7entry);
+ arm7.r[15] = arm7entry; // pc
+ arm7.r[14] = arm7entry; // lr
+ arm7.r[13] = 0x03007f00; // sp
+ arm7.r_irq[0] = 0x03007fa0; // sp_irq
+ arm7.r_svc[0] = 0x03007fe0; // sp_svc
+
+ arm9.writeCpsr(0xdf, 0xf);
+ arm9.branch(arm9entry & 1, arm9entry);
+ arm9.r[15] = arm9entry; // pc
+ arm9.r[14] = arm9entry; // lr
+ arm9.r[13] = 0x00803ec0; // sp
+ arm9.r_irq[0] = 0x00803fa0; // sp_irq
+ arm9.r_svc[0] = 0x00803fc0; // sp_svc
+ }
+
+ arm7.event.queue.time -= arm7.clock;
+ for(unsigned n=1; n <= arm7.event.queue.size; n++)
+ arm7.event.queue.items[n]->time -= arm7.clock;
+
+ arm7.clock = 0;
+
+ for(;;) {
+ if(arm7.clock >= 256)
+ co_switch(arm9.thread);
+
+ event.irq = interrupt.gate && (interrupt.enable & interrupt.flags);
+ //if(event.irq && !If) {
+ // print("arm7: irq (if=",hex<8>(interrupt.flags),")\n");
+ //}
+
+ if(Tf) execTHUMB();
+ else execARM();
+ }
+}
+
+void ARM7TDMI::istep(unsigned clocks) {
+ arm7.clock += 2*clocks;
+ event.queue.step(2*clocks);
+}
+
+void ARM7TDMI::step(unsigned clocks) {
+ return istep(clocks);
+}
+
+
+
+void ARM7TDMI::execARM() {
+ if(branched) {
+ //if(r[15] == 0) print(hex<8>(r[14]), ": jump to nullptr!\n");
+ branched = false; r[15] &= ~3;
+ iexecute = fetch(r[15], Word, 0); r[15] += 4;
+ idecode = fetch(r[15], Word, 1); r[15] += 4;
+ } else {
+ iexecute = idecode, idecode = ifetch;
+ }
+ ifetch = fetch(r[15], Word, 1);
+ uint32 i = iexecute;
+
+ if(event.irq && !If) return irq();
+ //if(trace && r[15] >= 0x2000000) traceInsn();
+
+ if(!evalCond(i>>28)) { r[15] += 4; return; }
+
+ // opcode, sh, Rd, Rn, Rm, Rs
+ if(imatch("00x10xx0/////")) {
+ if(imatch("00110r10/// ..../")) return armWritePsr(i>>22, i>>16, armImmed(i, i>>8));
+ if(imatch("00010r10/// 0000/")) return armWritePsr(i>>22, i>>16, armRm(i));
+ if(imatch("00010r00/// 0000/")) return armReadPsr (i>>22, i>>12);
+ if(imatch("00010010/// 00l1/")) return armBranchEx( i>>5, i);
+ if(imatch("00010b00/// 1001/")) return armMemSwap (i>>22, i>>12, i>>16, i);
+ }
+ if(imatch("000...../// 1..1/")) {
+ if(imatch("0000luas/// 1001/")) return armMultiply(i>>20, i>>16, i>>12, i, i>>8);
+ if(imatch("000pu0wl/// 1sh1/")) return armMem_v4 (i>>20, i>>5, i>>12, i>>16, armRm(i));
+ if(imatch("000pu1wl/// 1sh1/")) return armMem_v4 (i>>20, i>>5, i>>12, i>>16, armOffset8(i, i>>8));
+ }
+ if(imatch("001aaaas/// ..../")) return armData (i>>20, i>>12, i>>16, armImmed(i, i>>8));
+ if(imatch("000aaaas/// .sh0/")) return armData (i>>20, i>>12, i>>16, shiftImm(i, i>>5, i>>7));
+ if(imatch("010pubwl/// ..../")) return armMem (i>>20, i>>12, i>>16, armOffset12(i));
+ if(imatch("011pubwl/// ...0/")) return armMem (i>>20, i>>12, i>>16, shiftImm(i, i>>5, i>>7));
+ if(imatch("100puswl/// ..../")) return armBlock (i>>20, i>>16, i);
+ if(imatch("101l..../// ..../")) return armBranch (i>>24, 0, i<<2);
+ if(imatch("000aaaas/// 0sh1/")) return armDataRs (i>>20, i>>12, i>>16, i, i>>5, i>>8);
+
+ if(imatch("1111..../// ..../")) return swi ();
+ return undefined();
+}
+
+void ARM7TDMI::execTHUMB() {
+ if(branched) {
+ //if(r[15] == 0) print(hex<8>(r[14]), ": jump to nullptr!\n");
+ branched = false; r[15] &= ~1;
+ iexecute = fetch(r[15], Half, 0) >> 8*(r[15] & 2) & 0xffff; r[15] += 2;
+ idecode = fetch(r[15], Half, 1) >> 8*(r[15] & 2) & 0xffff; r[15] += 2;
+ } else {
+ iexecute = idecode, idecode = ifetch;
+ }
+ ifetch = fetch(r[15], Half, 1) >> 8*(r[15] & 2) & 0xffff;
+ uint16 i = iexecute;
+
+ if(event.irq && !If) return irq();
+ //if(trace && r[15] >= 0x2000000) traceInsn();
+
+ if(imatch("00011ismmmnnnddd")) return thumbAddSub (i>>9, i, i>>3, i>>6);
+ if(imatch("000ssiiiiimmmddd")) return thumbShiftImm(i>>11, i, i>>3, i>>6);
+ if(imatch("001oodddiiiiiiii")) return thumbDataImm (i>>11, i>>8, i);
+ if(imatch("010000oooommmddd")) return thumbDataLo (i>>6, i, i>>3);
+ if(imatch("010001oodmmmmddd")) return thumbDataHi (i>>8, (i&7)+(i>>4&8), i>>3);
+
+ if(imatch("0101ooommmnnnddd")) return thumbMemReg (i>>9, i, i>>3, i>>6);
+ if(imatch("011bliiiiinnnddd")) return thumbMemImm (i>>11, i, i>>3, i>>6);
+ if(imatch("1000liiiiinnnddd")) return thumbMemImm (i>>11, i, i>>3, i>>6);
+
+ if(imatch("10110000siiiiiii")) return thumbAddSP ( i>>7, i);
+ if(imatch("01001dddrrrrrrrr")) return thumbRelative(i>>11, i>>8, i);
+ if(imatch("1001odddrrrrrrrr")) return thumbRelative(i>>11, i>>8, i);
+ if(imatch("1010odddrrrrrrrr")) return thumbRelative(i>>11, i>>8, i);
+
+ if(imatch("1101ccccrrrrrrrr")) return thumbCond ( i>>8, i);
+ if(imatch("11100rrrrrrrrrrr")) return thumbBranch (i);
+ if(imatch("11110rrrrrrrrrrr")) return thumbBh (i);
+ if(imatch("11111rrrrrrrrrrr")) return thumbBlx (1, i);
+
+ if(imatch("1o..lnnnrrrrrrrr")) return thumbBlock (i>>11, i>>8, i);
+
+ return undefined();
+}
+
+
+
+uint32 ARM7TDMI::fetch(uint32 addr, uint32 size, bool s) {
+ return read(addr, size, s);
+}
+
+uint32 ARM7TDMI::read(uint32 addr, uint32 size, bool s) {
+ const int h = size==Word? 2 : 1; // 16-bit bus timing
+ const int e = 8*!s + h; // EWRAM timing
+
+ //if((addr & 0xf3ff000) == 0x23ff000) {
+ // istep(e);
+ // uint32 data = system.ewram.read(addr % 0x400000, size);
+ // print(hex<8>(arm7.event.queue.time), " ",hex<8>(r[15])," arm7: r ",hex<8>(addr),":",size," = ",hex<8>(data),"\n");
+ // return data;
+ //}
+
+ switch(addr >> 23) {
+ case 0x00>>3:
+ case 0x08>>3: istep(1); addr &= bios.size-1; return bios.read(addr, size);
+ case 0x20>>3:
+ case 0x28>>3: istep(e); addr %= 0x400000; return system.ewram.read(addr, size);
+ case 0x30>>3: istep(1); addr %= 0x008000; return system.swram[addr>>14].read(addr % 0x4000, size);
+ case 0x38>>3: istep(1); addr %= 0x010000; return system.iwram.read(addr, size);
+ case 0x40>>3: istep(1); { // return readReg(addr, size);
+ uint32 data = readReg(addr, size);
+ //print(hex<8>(arm7.event.queue.time), " ", hex<8>(r[15])," arm7: r ",hex<8>(addr),":",size," = ",hex<8>(data),"\n");
+ return data;
+ }
+ case 0x48>>3: istep(1); return wifi.read(addr, size);
+ case 0x60>>3:
+ case 0x68>>3: istep(h); addr %= 0x040000; return system.vmap.arm7[addr>>14].read(addr, size);
+ }
+ istep(1);
+ return 0;
+}
+
+void ARM7TDMI::write(uint32 addr, uint32 size, bool s, uint32 data) {
+ const int h = size==Word? 2 : 1; // 16-bit bus timing
+ const int e = 8*!s + h; // EWRAM timing
+
+ //if((addr & 0xf3ff000) == 0x23ff000)
+ // print(hex<8>(arm7.event.queue.time), " ",hex<8>(r[15]), " arm7: w ",hex<8>(addr),":",size," = ",hex<8>(data),"\n");
+
+ switch(addr >> 23) {
+ case 0x20>>3:
+ case 0x28>>3: istep(e); addr %= 0x400000; return system.ewram.write(addr, size, data);
+ case 0x30>>3: istep(1); addr %= 0x008000; return system.swram[addr>>14].write(addr % 0x4000, size, data);
+ case 0x38>>3: istep(1); addr %= 0x010000; return system.iwram.write(addr, size, data);
+ case 0x40>>3: istep(1); { // return writeReg(addr, size, data);
+ //if(addr != 0x4000301)
+ // print(hex<8>(arm7.event.queue.time), " ", hex<8>(r[15])," arm7: w ",hex<8>(addr),":",size," = ",hex<8>(data),"\n");
+ writeReg(addr, size, data);
+ return;
+ }
+ case 0x48>>3: istep(1); return wifi.write(addr, size, data);
+ case 0x60>>3:
+ case 0x68>>3: istep(h); addr %= 0x040000; if(size > Byte) return system.vmap.arm7[addr>>14].write(addr, size, data);
+ // STRB - special case, only works on ARM7
+ auto &page = system.vmap.arm7[addr>>14];
+ page[addr] &= addr & 1? 0x00ff : 0xff00;
+ page[addr] |= addr & 1? data & 0xff00 : data & 0x00ff;
+ return;
+ }
+ istep(1);
+}
+
+void ARM7TDMI::dataCop(uint4 cpno, uint4 op1, uint4 ird, uint4 irn, uint4 irm, uint4 op2) {
+ return undefined();
+}
+
+
+
+uint32 ARM7TDMI::readReg(uint32 addr, uint32 size) {
+ switch(addr-0x4000000 & ~3) {
+
+ case 0x134: {
+ // Aux GPIO
+ // - missing link port (SI pin = clock /IRQ)
+ // - misc inputs
+ uint8 keys = 0;
+ for(unsigned n = 10; n < 16; n++) {
+ if(interface->inputPoll(ID::Port::Buttons, 0, n))
+ keys += 1 << n-10;
+ }
+ if(system.touchscreen.penDown()) keys += 1<<6;
+ if(interface->inputPoll(ID::Port::Sensors, 0, ID::Sensors::Lid)==0) keys += 1<<7;
+ return (keys ^ 0xff)<<16 | regSio()<<0;
+ }
+
+ case 0x138: return regRtc(); // GPIO - system clock
+ case 0x1c0: return regSpi(); // SPI - power, touch, firmware flash
+
+ // Memory status, slot 2
+ case 0x204: return arm9.ramPriority<<15 | arm9.slot1access<<11
+ | arm9.slot2access<< 7 | regSlot2Control();
+ // Wifi waitstates
+ case 0x206: break;
+
+ case 0x240: break; // VRAM status
+ case 0x241: break; // SWRAM status
+
+ case 0x300: return flag300<<1 | booted<<0;
+ case 0x304: return apu.powered<<0 | wifi.powered<<1;
+
+ case 0x400: case 0x410: case 0x420: case 0x430:
+ case 0x440: case 0x450: case 0x460: case 0x470:
+ case 0x480: case 0x490: case 0x4a0: case 0x4b0:
+ case 0x4c0: case 0x4d0: case 0x4e0: case 0x4f0:
+ return apu.regVoiceControl(addr>>4 & 15);
+
+ case 0x500: return apu.regControl();
+ case 0x504: return apu.regBias();
+ case 0x508: return apu.regCaptureControl();
+ case 0x510: return apu.regCaptureDest(0);
+ case 0x518: return apu.regCaptureDest(1);
+
+ }
+ return CPUCore::readReg(addr, size);
+}
+
+void ARM7TDMI::writeReg(uint32 addr, uint32 size, uint32 data) {
+ uint32 mask = 0xffffffff;
+ if(size == Half) mask = 0xffff << 8*(addr & 2);
+ if(size == Byte) mask = 0xff << 8*(addr & 3);
+
+ data &= mask;
+
+ switch(addr-0x4000000 & ~3) {
+
+ case 0x134: return regSio(data, mask); // GPIO - missing link port
+ case 0x138: return regRtc(data, mask); // GPIO - system clock
+ case 0x1c0: return regSpi(data, mask); // SPI - power, touch, firmware flash
+
+ case 0x204: return regSlot2Control(data, mask);
+ case 0x206: break; // Wifi waitstates
+
+ case 0x300: // System mode
+ booted |= data & 1; // not possible to clear it
+ if(mask & 0xff)
+ flag300 = data >> 1;
+
+ // 0x4000: halt arm9 and enter GBA mode
+ // 0x8000: halt arm7 and wait for IRQ
+ // 0xc000: halt system and wait for IRQ (low-power sleep mode)
+ //
+ // Nearly everything is frozen in sleep mode, including timers. Only
+ // a few things can generate interrupts to bring it back out:
+ // - lid sensor, buttons
+ // - alarm from real-time clock
+ // - wireless chipset (?)
+ // - cart in slot 1 or 2 (?)
+ if(data & 0xc000) {
+ //print("arm7: wait (ime=",interrupt.gate,", ie=",hex<8>(interrupt.enable),")\n");
+ powerState = waiting;
+ for(;;) {
+ if((interrupt.enable & interrupt.flags)) {
+ powerState = running;
+ break;
+ }
+ istep(256);
+ if(arm7.clock >= 256)
+ co_switch(arm9.thread);
+ }
+ }
+ return;
+
+ case 0x304: // Power
+ if(mask & 0xff) {
+ apu.powered = data>>0;
+ wifi.powered = data>>1;
+ }
+ return;
+
+ case 0x308: break; // BIOS protection
+
+ case 0x400: case 0x410: case 0x420: case 0x430:
+ case 0x440: case 0x450: case 0x460: case 0x470:
+ case 0x480: case 0x490: case 0x4a0: case 0x4b0:
+ case 0x4c0: case 0x4d0: case 0x4e0: case 0x4f0:
+ return apu.regVoiceControl(addr>>4 & 15, data, mask);
+
+ case 0x404: case 0x414: case 0x424: case 0x434:
+ case 0x444: case 0x454: case 0x464: case 0x474:
+ case 0x484: case 0x494: case 0x4a4: case 0x4b4:
+ case 0x4c4: case 0x4d4: case 0x4e4: case 0x4f4:
+ return apu.regVoiceSource(addr>>4 & 15, data, mask);
+
+ case 0x408: case 0x418: case 0x428: case 0x438:
+ case 0x448: case 0x458: case 0x468: case 0x478:
+ case 0x488: case 0x498: case 0x4a8: case 0x4b8:
+ case 0x4c8: case 0x4d8: case 0x4e8: case 0x4f8:
+ return apu.regVoicePeriod(addr>>4 & 15, data, mask);
+
+ case 0x40c: case 0x41c: case 0x42c: case 0x43c:
+ case 0x44c: case 0x45c: case 0x46c: case 0x47c:
+ case 0x48c: case 0x49c: case 0x4ac: case 0x4bc:
+ case 0x4cc: case 0x4dc: case 0x4ec: case 0x4fc:
+ return apu.regVoiceLength(addr>>4 & 15, data, mask);
+
+ case 0x500: return apu.regControl(data, mask);
+ case 0x504: return apu.regBias(data, mask);
+ case 0x508: return apu.regCaptureControl(data, mask);
+ case 0x510: return apu.regCaptureDest(0, data, mask);
+ case 0x514: return apu.regCaptureLength(0, data, mask);
+ case 0x518: return apu.regCaptureDest(1, data, mask);
+ case 0x51c: return apu.regCaptureLength(1, data, mask);
+
+ }
+ return CPUCore::writeReg(addr, size, data);
+}
+
+
+uint32 ARM7TDMI::regSpi() {
+ return spi.divider<<0 | spi.device<<8 | spi.size<<10
+ | spi.hold<<11 | spi.irq<<14 | spi.enable<<15
+ | spi.data<<16;
+}
+
+void ARM7TDMI::regSpi(uint32 data, uint32 mask) {
+ if(mask & 0x000000ff) {
+ spi.divider = data>>0;
+ }
+ if(mask & 0x0000ff00) {
+ spi.device = data>>8;
+ spi.size = data>>10;
+ spi.hold = data>>11;
+ spi.irq = data>>14;
+ spi.enable = data>>15;
+
+ if(spi.enable == false) {
+ // Hrm, must be implicit as libnds does not release the hold
+ // before last transfer - or is spi.hold not delayed after all?
+ system.firmware.select(false);
+ system.powerMgr.select(false);
+ system.touchscreen.select(false);
+ }
+ }
+ if(mask & 0xffff0000) {
+ if(!spi.enable) return;
+
+ SPIDevice* device = nullptr;
+ if(spi.device == SPI::flash) device = &system.firmware;
+ if(spi.device == SPI::power) device = &system.powerMgr;
+ if(spi.device == SPI::touch) device = &system.touchscreen;
+
+ if(device) {
+ // SPI transfers are bidirectional so there's always a read+write.
+ device->select(true);
+ spi.data = device->transfer(data>>16);
+ device->select(spi.hold);
+ }
+ }
+}
+
+
+
+uint32 ARM7TDMI::regRtc() {
+ // I've blithely assumed: pin = (out | ~dir) & in
+ //
+ // Something like that is necessary because Nintendo read-modify-writes
+ // the output pins.
+ return uint4( (rtc.out[0] | ~rtc.dir[0]) & rtc.in[0] )<<0 | rtc.dir[0]<<4
+ | uint4( (rtc.out[1] | ~rtc.dir[1]) & rtc.in[1] )<<8 | rtc.dir[1]<<12;
+}
+
+void ARM7TDMI::regRtc(uint32 data, uint32 mask) {
+ // It would've been nice if the clock was on the SPI bus, like the touchpad,
+ // firmware and power chips.. it seems that wasn't possible because of the
+ // bi-directional data pin. Software has to bit-bang the GPIO pins instead.
+
+ if(mask & 0x00ff) {
+ rtc.out[0] = data>>0; // if dir==1, use output from the DS side.
+ rtc.dir[0] = data>>4; // if dir==0, use as input with pullup (?)
+ }
+ if(mask & 0xff00) {
+ rtc.out[1] = data>>0; // these may exist, but don't appear to be used.
+ rtc.dir[1] = data>>4;
+ }
+ // All pins can be either inputs or outputs.
+ // "in" is the value being driven externally (or 1, if not).
+ uint4 pins = (rtc.out[0] | ~rtc.dir[0]) & rtc.in[0];
+ rtc.in[0] = system.clock.io(pins);
+}
+
+
+
+uint32 ARM7TDMI::regSio() {
+ return sio.in<<0 | sio.dir<<4 | sio.irq<<8 | sio.mode<<14;
+}
+
+void ARM7TDMI::regSio(uint32 data, uint32 mask) {
+ sio.out = data>>0;
+ sio.dir = data>>4;
+ sio.irq = data>>8;
+ sio.mode = data>>14;
+}
+
diff --git a/bsnes/nds/cpu/arm946es.cpp b/bsnes/nds/cpu/arm946es.cpp
new file mode 100644
index 00000000..e3b24577
--- /dev/null
+++ b/bsnes/nds/cpu/arm946es.cpp
@@ -0,0 +1,697 @@
+
+ARM946ES::ARM946ES() {
+ itcm.data = new uint32_t[(itcm.size = 0x8000)/4];
+ dtcm.data = new uint32_t[(dtcm.size = 0x4000)/4];
+ bios.data = new uint32[(bios.size = 0x001000)/4]();
+ memset(bios.data, 0, bios.size);
+}
+
+void ARM946ES::Thread() { arm9.main(); }
+
+void ARM946ES::power() {
+ // 2 * 33513982 MHz
+ if(thread) co_delete(thread);
+ thread = co_create(262144 * sizeof(void*), ARM946ES::Thread);
+
+ vectorBase = 0xffff0000;
+ bxWithLoadedPC = true;
+ insnLatch = 0;
+
+ memset(itcm.data, 0, itcm.size);
+ memset(dtcm.data, 0, dtcm.size);
+
+ divMode = 0; rootMode = 0;
+ divByZero = 0; rootBusy = 0;
+ divBusy = 0; square = 0;
+ numerator = 0; squareRoot = 0;
+ denominator = 0;
+ quotient = 0;
+ remainder = 0;
+
+ booted = 0;
+ flag300 = 0;
+
+ slot1access = 1;
+ slot2access = 1;
+ ramPriority = 1;
+
+ CPUCore::power();
+ trace = false;
+
+ control.mmu = false;
+ control.dcache = false;
+ control.icache = false;
+
+ control.dtcm = false;
+ control.itcm = false;
+ control.dtcmLoad = false;
+ control.itcmLoad = false;
+
+ control.endian = CR::little;
+ control.cachePolicy = CR::random;
+}
+
+void ARM946ES::istep(unsigned clocks) {
+ arm7.clock -= clocks;
+ event.queue.step(clocks);
+}
+
+void ARM946ES::step(unsigned clocks) {
+ return istep(clocks);
+}
+
+
+
+void ARM946ES::main() {
+ itcmRegion = 0x00000000 | 14<<1; control.itcm = true;
+ dtcmRegion = 0x00800000 | 14<<1; control.dtcm = true;
+ updateTcm();
+
+ for(;;) {
+ if(arm7.clock < -256)
+ co_switch(arm7.thread);
+
+ event.irq = interrupt.gate && (interrupt.enable & interrupt.flags);
+ //if(event.irq && !If) {
+ // print("arm9: irq (if=",hex<8>(interrupt.flags),")\n");
+ //}
+
+ if(Tf) execTHUMB();
+ else execARM();
+ }
+}
+
+
+
+void ARM946ES::execARM() {
+ if(branched) {
+ //if(r[15] == 0) print(hex<8>(r[14]), ": jump to nullptr!\n");
+ branched = false; r[15] &= ~3;
+ iexecute = fetch(r[15], Word, 0); r[15] += 4;
+ idecode = fetch(r[15], Word, 0); r[15] += 4;
+ } else {
+ iexecute = idecode, idecode = ifetch;
+ }
+ ifetch = fetch(r[15], Word, 1);
+ uint32 i = iexecute;
+ if(event.irq && !If) return irq();
+ //if(trace) traceInsn();
+
+ if(i < 0xe0000000 && !evalCond(i>>28)) { r[15] += 4; return; }
+
+ // opcode, sh, Rd, Rn, Rm, Rs
+ if(imatch("1111......../////")) {
+ if(imatch("111101x1u101/////")) { r[15] += 4; return; } // pld - reportedly NOP on DS?
+ if(imatch("1111101l..../////")) return armBranch (1, 1, i<<2 | (i>>23 & 2));
+ return undefined();
+ }
+ if(imatch("00x10xx0/////")) {
+ if(imatch("00110r10/// ..../")) return armWritePsr(i>>22, i>>16, armImmed(i, i>>8));
+ if(imatch("00010r10/// 0000/")) return armWritePsr(i>>22, i>>16, armRm(i));
+ if(imatch("00010r00/// 0000/")) return armReadPsr (i>>22, i>>12);
+ if(imatch("00010010/// 00l1/")) return armBranchEx( i>>5, i);
+ if(imatch("00010010/// 0111/")) return pfabort (); // bkpt
+ if(imatch("00010110/// 0001/")) return armClz ( i>>12, i);
+ if(imatch("00010ds0/// 0101/")) return armDspAdd (i>>21, i>>12, i>>16, i);
+ if(imatch("00010oo0/// 1yx0/")) return armDspMul (i>>21, i>>5, i>>16, i>>12, i, i>>8);
+ if(imatch("00010b00/// 1001/")) return armMemSwap (i>>22, i>>12, i>>16, i);
+ }
+ if(imatch("000...../// 1..1/")) {
+ if(imatch("0000luas/// 1001/")) return armMultiply(i>>20, i>>16, i>>12, i, i>>8);
+ if(imatch("000pu0w0/// 11s1/")) return armMem_v5 (i>>20, i>>5, i>>12, i>>16, armRm(i));
+ if(imatch("000pu0wl/// 1sh1/")) return armMem_v4 (i>>20, i>>5, i>>12, i>>16, armRm(i));
+ if(imatch("000pu1w0/// 11s1/")) return armMem_v5 (i>>20, i>>5, i>>12, i>>16, armOffset8(i, i>>8));
+ if(imatch("000pu1wl/// 1sh1/")) return armMem_v4 (i>>20, i>>5, i>>12, i>>16, armOffset8(i, i>>8));
+ }
+ if(imatch("001aaaas/// ..../")) return armData (i>>20, i>>12, i>>16, armImmed(i, i>>8));
+ if(imatch("000aaaas/// .sh0/")) return armData (i>>20, i>>12, i>>16, shiftImm(i, i>>5, i>>7));
+ if(imatch("010pubwl/// ..../")) return armMem (i>>20, i>>12, i>>16, armOffset12(i));
+ if(imatch("011pubwl/// ...0/")) return armMem (i>>20, i>>12, i>>16, shiftImm(i, i>>5, i>>7));
+ if(imatch("100puswl/// ..../")) return armBlock (i>>20, i>>16, i);
+ if(imatch("101l..../// ..../")) return armBranch (i>>24, 0, i<<2);
+ if(imatch("000aaaas/// 0sh1/")) return armDataRs (i>>20, i>>12, i>>16, i, i>>5, i>>8);
+
+ if(imatch("1110..../// ..../")) return dataCop (i>>8, i>>20, i>>12, i>>16, i, i>>4);
+ if(imatch("1111..../// ..../")) return swi();
+ return undefined();
+}
+
+void ARM946ES::execTHUMB() {
+ if(branched) {
+ //if(r[15] == 0) print(hex<8>(r[14]), ": jump to nullptr!\n");
+ branched = false; r[15] &= ~1;
+ iexecute = fetch(r[15], Half, 0) >> 8*(r[15] & 2) & 0xffff; r[15] += 2;
+ idecode = fetch(r[15], Half, 1) >> 8*(r[15] & 2) & 0xffff; r[15] += 2;
+ } else {
+ iexecute = idecode, idecode = ifetch;
+ }
+ ifetch = fetch(r[15], Half, 1) >> 8*(r[15] & 2) & 0xffff;
+ uint16 i = iexecute;
+
+ if(event.irq && !If) return irq();
+ //if(trace) traceInsn();
+
+ if(imatch("00011ismmmnnnddd")) return thumbAddSub (i>>9, i, i>>3, i>>6);
+ if(imatch("000ssiiiiimmmddd")) return thumbShiftImm(i>>11, i, i>>3, i>>6);
+ if(imatch("001oodddiiiiiiii")) return thumbDataImm (i>>11, i>>8, i);
+ if(imatch("010000oooommmddd")) return thumbDataLo (i>>6, i, i>>3);
+ if(imatch("010001oodmmmmddd")) return thumbDataHi (i>>8, (i&7)+(i>>4&8), i>>3);
+
+ if(imatch("0101ooommmnnnddd")) return thumbMemReg (i>>9, i, i>>3, i>>6);
+ if(imatch("011bliiiiinnnddd")) return thumbMemImm (i>>11, i, i>>3, i>>6);
+ if(imatch("1000liiiiinnnddd")) return thumbMemImm (i>>11, i, i>>3, i>>6);
+
+ if(imatch("10111110........")) return pfabort(); // bkpt
+ if(imatch("10110000siiiiiii")) return thumbAddSP ( i>>7, i);
+ if(imatch("01001dddrrrrrrrr")) return thumbRelative(i>>11, i>>8, i);
+ if(imatch("1001odddrrrrrrrr")) return thumbRelative(i>>11, i>>8, i);
+ if(imatch("1010odddrrrrrrrr")) return thumbRelative(i>>11, i>>8, i);
+
+ if(imatch("1101ccccrrrrrrrr")) return thumbCond ( i>>8, i);
+ if(imatch("11100rrrrrrrrrrr")) return thumbBranch (i);
+ if(imatch("11110rrrrrrrrrrr")) return thumbBh (i);
+ if(imatch("111t1rrrrrrrrrrr")) return thumbBlx (i>>12, i);
+
+ if(imatch("1o..lnnnrrrrrrrr")) return thumbBlock (i>>11, i>>8, i);
+
+ return undefined();
+}
+
+
+
+uint32 ARM946ES::fetch(uint32 addr, uint32 size, bool s) {
+ istep(1); // Assume cached for now
+
+ if(itcmRCompare == (itcmRMask & addr)) { return itcm.read(addr % 0x8000, size); }
+ /* DTCM is not executable */
+
+ switch(addr >> 24) {
+ case 0x2: return system.ewram.read(addr % 0x400000, size);
+ case 0x3: return system.swram[addr>>14 & 1].read(addr % 0x4000, size);
+ case 0x6: return system.vmap.arm9[addr>>21 & 7][addr>>14 & 63].read(addr, size);
+ }
+ if(addr >= 0xffff0000) return bios.read(addr & bios.size-1, size);
+ return 0;
+}
+
+uint32 ARM946ES::read(uint32 addr, uint32 size, bool s) {
+ if(itcmRCompare == (itcmRMask & addr)) { istep(1); return itcm.read(addr % 0x8000, size); }
+ if(dtcmRCompare == (dtcmRMask & addr)) { return dtcm.read(addr % 0x4000, size); }
+
+ const int w = 6*!s + 2; // 32-bit bus timing
+ const int h = 6*!s + (size==Word? 4 : 2); // 16-bit bus timing
+ //const int e = 2*!s + h; // EWRAM timing
+
+ //if((addr & 0xf3ff000) == 0x23ff000) {
+ // istep(e);
+ // uint32 data = system.ewram.read(addr % 0x400000, size);
+ // print(hex<8>(arm9.event.queue.time), " ",hex<8>(r[15])," arm9: r ",hex<8>(addr),":",size," = ",hex<8>(data),"\n");
+ // return data;
+ //}
+
+ switch(addr >> 24) {
+ case 0x2: istep(3); return system.ewram.read(addr % 0x400000, size);
+ case 0x3: istep(w); return system.swram[addr>>14 & 1].read(addr % 0x4000, size);
+ case 0x4: istep(w); { //return readReg(addr, size); {
+ uint32 data = readReg(addr, size);
+ //if(addr != 0x40001a0 && addr != 0x40001a4 && addr != 0x4100010)
+ // print(hex<8>(arm9.event.queue.time), " ",hex<8>(r[15])," arm9: r ",hex<8>(addr),":",size," = ",hex<8>(data),"\n");
+ return data;
+ }
+ case 0x5: istep(h); return ppu[addr>>10 & 1].readPalette(addr % 0x400);
+ case 0x6: istep(h); return system.vmap.arm9[addr>>21 & 7][addr>>14 & 63].read(addr, size);
+ case 0x7: istep(w); return ppu[addr>>10 & 1].readOam(addr % 0x400);
+ }
+ istep(w); if(addr >= 0xffff0000) return bios.read(addr & bios.size-1, size);
+ return 0;
+}
+
+void ARM946ES::write(uint32 addr, uint32 size, bool s, uint32 data) {
+ if(itcmWCompare == (itcmWMask & addr)) { istep(1); return itcm.write(addr % 0x8000, size, data); }
+ if(dtcmWCompare == (dtcmWMask & addr)) { return dtcm.write(addr % 0x4000, size, data); }
+
+ //if((addr & 0xf3ff000) == 0x23ff000)
+ // print(hex<8>(arm9.event.queue.time), " ",hex<8>(r[15]), " arm9: w ",hex<8>(addr),":",size," = ",hex<8>(data),"\n");
+
+ const int w = 6*!s + 2; // 32-bit bus timing
+ const int h = 6*!s + (size==Word? 4 : 2); // 16-bit bus timing
+ //const int e = 2*!s + h; // EWRAM timing
+
+ switch(addr >> 24) {
+ case 0x2: istep(3); return system.ewram.write(addr % 0x400000, size, data);
+ case 0x3: istep(w); return system.swram[addr>>16 & 1].write(addr % 0x4000, size, data);
+ case 0x4: istep(w); { //return writeReg(addr, size, data);
+ //if(addr != 0x04000400)
+ // print(hex<8>(arm9.event.queue.time), " ", hex<8>(r[15])," arm9: w ",hex<8>(addr),":",size," = ",hex<8>(data),"\n");
+ writeReg(addr, size, data);
+ return;
+ }
+ case 0x5: istep(h); return ppu[addr>>10 & 1].writePalette(addr % 0x400, size, data);
+ case 0x6: istep(h); return system.vmap.arm9[addr>>21 & 7][addr>>14 & 63].write(addr, size, data);
+ case 0x7: istep(w); return ppu[addr>>10 & 1].writeOam(addr % 0x400, size, data);
+ }
+ istep(w);
+}
+
+void ARM946ES::dataCop(uint4 cpno, uint4 op1, uint4 ird, uint4 irn, uint4 irm, uint4 op2) {
+ if(cpno == 15) {
+ auto &rd = r[ird];
+ uint32 rm = r[irm];
+ r[15] += 4;
+
+ if(op2 & 1) { // MRC, MCR
+ switch(op1<<12 | irn<<8 | irm<<4 | op2>>1) {
+
+ case 0x1000: // c0,c0,0 Processor ID
+ rd = 'A'<<24; // Implementor ARM
+ rd |= 0<<20; // Variant 0
+ rd |= 5<<16; // Architecture v5
+ rd |= 0x946<< 4; // Model 946
+ rd |= 1<< 0; // Revision 1
+ return;
+
+ case 0x1001: // c0,c0,1 Cache information
+ rd = 0x0f<<24; // type B Harvard
+ rd |= 0x0d2<<12; // 4K data, 4-way, 32-byte lines
+ rd |= 0x112<< 0; // 8K insn, 4-way, 32-byte lines
+ return;
+
+ case 0x1002: // c0,c0,2 TCM information
+ rd = 5<<18; // 16K dtcm
+ rd |= 6<< 6; // 32K itcm
+ return;
+
+ case 0x1100: // c1,c0,0 Control register
+ rd = control.mmu<<0 | control.dcache<<2 | 1<<3 /*write buffer*/
+ | 1<<4 | 1<<5 | 1<<6 /*32 bit only, late abort model*/
+ | control.endian<<7 | control.icache<<12 | !!vectorBase<<13
+ | control.cachePolicy<<14 | !bxWithLoadedPC<<15
+ | control.dtcm<<16 | control.dtcmLoad<<17
+ | control.itcm<<18 | control.itcmLoad<<19;
+ return;
+
+ case 0x0100:
+ control.mmu = rd >> 0;
+ control.dcache = rd >> 1;
+ control.endian = rd >> 7;
+ control.icache = rd >> 12;
+ vectorBase = rd & 1<<13? 0xffff0000 : 0;
+ control.cachePolicy = rd >> 14;
+ bxWithLoadedPC = rd & 1<<15? false : true;
+ control.dtcm = rd >> 16;
+ control.dtcmLoad = rd >> 17;
+ control.itcm = rd >> 18;
+ control.itcmLoad = rd >> 19;
+
+ updateTcm();
+ return;
+
+ case 0x0900: case 0x1900: // c9,c0,0 Lock dcache
+ case 0x0901: case 0x1901: // c9,c0,1 Lock icache
+ return;
+
+ case 0x0910: // c9,c1,0 DTCM mapping
+ dtcmRegion = rd;
+ updateTcm();
+ return;
+ case 0x1910:
+ rd = dtcmRegion;
+ return;
+
+ case 0x0911: // c9,c1,1 ITCM mapping
+ itcmRegion = rd;
+ updateTcm();
+ return;
+ case 0x1911:
+ rd = itcmRegion;
+ return;
+
+ case 0x0200: case 0x1200: // c2,c0,0 Region data cache bits
+ case 0x0201: case 0x1201: // c2,c0,1 Region insn cache bits
+ case 0x0300: case 0x1300: // c3,c0,0 Region data buffer bits
+ case 0x0500: case 0x1500: // c5,c0,0 Region data permissions
+ case 0x0501: case 0x1501: // c5,c0,1 Region insn permissions
+ case 0x0502: case 0x1502: // c5,c0,2 Region data permissions - extended
+ case 0x0503: case 0x1503: // c5,c0,3 Region insn permissions - extended
+ return;
+
+ case 0x0600: case 0x1600: case 0x0601: case 0x1601: // c6,cN,0 Region mappings
+ case 0x0610: case 0x1610: case 0x0611: case 0x1611:
+ case 0x0620: case 0x1620: case 0x0621: case 0x1621:
+ case 0x0630: case 0x1630: case 0x0631: case 0x1631:
+ case 0x0640: case 0x1640: case 0x0641: case 0x1641:
+ case 0x0650: case 0x1650: case 0x0651: case 0x1651:
+ case 0x0660: case 0x1660: case 0x0661: case 0x1661:
+ case 0x0670: case 0x1670: case 0x0671: case 0x1671:
+ return;
+
+ case 0x0704: // c7,c0,4 Wait for Interrupt
+ case 0x0782: // c7,c8,2 (alternate version)
+ //print("arm9: wait (ime=",interrupt.gate,", ie=",hex<8>(interrupt.enable),")\n");
+ powerState = waiting;
+ for(;;) {
+ // Because this one is integrated with the ARM9,
+ // it's "behind" the IRQ line and knows nothing about IME/IE/IF.
+ if(interrupt.gate && (interrupt.enable & interrupt.flags)) {
+ powerState = running;
+ break;
+ }
+ istep(256);
+ if(arm7.clock < -256)
+ co_switch(arm7.thread);
+ }
+ return;
+
+ case 0x0750: // c7, c5,0 Invalidate icache entirely
+ case 0x0751: // c7, c5,1 Invalidate icache by address
+ case 0x0752: // c7, c5,2 Invalidate icache by line (?)
+ case 0x07d1: // c7,c13,1 Preload icache by address
+ return;
+
+ case 0x0760: // c7, c6,0 Invalidate dcache entirely
+ case 0x0761: // c7, c6,1 Invalidate dcache by address
+ case 0x0762: // c7, c6,2 Invalidate dcache by line (? zelda gallery uses this)
+
+ //case 0x07a0://c7,c10,0 Clean dcache entirely (?)
+ case 0x07a1: // c7,c10,1 Clean dcache by address
+ case 0x07a2: // c7,c10,2 Clean dcache by line
+ case 0x07a4: // c7,c10,4 Drain write buffer
+
+ //case 0x07e0://c7,c14,0 Flush dcache entirely (?)
+ case 0x07e1: // c7,c14,1 Flush dcache by address
+ case 0x07e2: // c7,c14,2 Flush dcache by line
+ return;
+
+ case 0x0f00: case 0x1f00: // 0,c15,c0,0 Cache control
+ case 0x6f00: case 0x7f00: // 3,c15,c0,0 Cache tag/data index
+ case 0x6f01: case 0x7f01: // 3,c15,c0,1 R/W icache tag
+ case 0x6f02: case 0x7f02: // 3,c15,c0,2 R/W dcache tag
+ case 0x6f03: case 0x7f03: // 3,c15,c0,3 R/W icache data
+ case 0x6f04: case 0x7f04: // 3,c15,c0,4 R/W dcache data
+ return;
+
+ }
+ }
+ }
+ bool iscdp = op2&1, isld = op1&1;
+ print("arm9: ",hex<8>(r[15])," undefined ", iscdp? "cdp" : isld? "mrc" : "mcr", " p",cpno,", ",
+ iscdp? (unsigned)op1 : op1>>1, ", ", iscdp? "cr":"r", ird, ", cr", irn, ", cr", irm, ", ", op2>>1, "\n");
+ return undefined();
+}
+
+
+
+uint32 ARM946ES::readReg(uint32 addr, uint32 size) {
+ switch(addr-0x4000000 & ~3) {
+
+ // These registers shouldn't be here - but they contain bits from logically
+ // separate hardware units, so it's not clear where else to put them.
+
+ case 0x0000: // Display 0 / PPU0 BG, OBJ control
+ return (video.frameBuffer<<18 & 0xc0000)
+ | video.source[0]<<16 | ppu[0].regControl();
+
+ case 0x1000: // Display 1 / PPU1 BG, OBJ control
+ return video.source[1]<<16 | ppu[1].regControl();
+
+ case 0x0008: case 0x1008: // BG0,BG1
+ case 0x000c: case 0x100c: // BG2,BG3
+ return ppu[addr>>12 & 1].regBg((addr>>1 & 2) + 0)<<0
+ | ppu[addr>>12 & 1].regBg((addr>>1 & 2) + 1)<<16;
+
+ case 0x0010: case 0x1010: // BG0H,V
+ case 0x0014: case 0x1014: // BG1H,V
+ case 0x0018: case 0x1018: // BG2H,V
+ case 0x001c: case 0x101c: // BG3H,V
+ return ppu[addr>>12 & 1].regBgOffs(addr>>2 & 3);
+
+ case 0x0048: case 0x1048: // Window area 0,1,out,obj
+ return ppu[addr>>12 & 1].regWinArea();
+
+ case 0x0050: case 0x1050: // Blend control
+ return ppu[addr>>12 & 1].regBlend();
+
+ // Miscellaneous graphics registers
+ case 0x0060: return gpu.regRenderOptions();
+ case 0x0064: return video.regCapture();
+ case 0x006c: return video.regBrightness(0);
+
+ case 0x1060: return 0;
+ case 0x1064: return 0;
+ case 0x1068: return 0;
+ case 0x106c: return video.regBrightness(1);
+
+ // Memory control
+ case 0x0204: return ramPriority<<15 | slot1access<<11
+ | slot2access<<7 | regSlot2Control();
+
+ case 0x0240: return system.regVmap(0);
+ case 0x0244: return system.regVmap(1);
+ case 0x0248: return system.regVmap(2);
+
+ // Math
+ case 0x0280: return regDivideControl();
+ case 0x0290: return regNumerator(0);
+ case 0x0294: return regNumerator(1);
+ case 0x0298: return regDenominator(0);
+ case 0x029c: return regDenominator(1);
+ case 0x02a0: return regQuotient(0);
+ case 0x02a4: return regQuotient(1);
+ case 0x02a8: return regRemainder(0);
+ case 0x02ac: return regRemainder(1);
+
+ case 0x02b0: return regSquareRootControl();
+ case 0x02b4: return regSquareRoot();
+ case 0x02b8: return regSquare(0);
+ case 0x02bc: return regSquare(1);
+
+ case 0x0300: return booted<<0 | flag300<<1;
+
+ // Power
+ case 0x0304:
+ return video.screensPowered<< 0 | ppu[0].powered<<1
+ | video.ppu0Screen <<15 | ppu[1].powered<<9;
+
+ // Render status
+ case 0x0320: return gpu.regRenderLoad();
+
+ // This shouldn't exist, but various games read it nonetheless..
+ case 0x04a4: return 0;
+
+ // Geometry status
+ case 0x0600: return gpu.regGeomStatus();
+ case 0x0604: return gpu.regGeomLoad();
+
+ case 0x0620: case 0x0624: case 0x0628: case 0x062c:
+ return gpu.regGeomPosition((addr - 0x4000620)/4);
+
+ case 0x0630: case 0x0634:
+ return gpu.regGeomNormal((addr - 0x4000630)/4);
+
+ case 0x0640: case 0x0644: case 0x0648: case 0x064c:
+ case 0x0650: case 0x0654: case 0x0658: case 0x065c:
+ case 0x0660: case 0x0664: case 0x0668: case 0x066c:
+ case 0x0670: case 0x0674: case 0x0678: case 0x067c:
+ return gpu.regClipMatrix((addr - 0x4000640)/4);
+
+ case 0x0680: case 0x0684: case 0x0688:
+ case 0x068c: case 0x0690: case 0x0694:
+ case 0x0698: case 0x069c: case 0x06a0:
+ return gpu.regLightMatrix((addr - 0x4000680)/4);
+
+ }
+ return CPUCore::readReg(addr, size);
+}
+
+void ARM946ES::writeReg(uint32 addr, uint32 size, uint32 data) {
+ uint32 mask = 0xffffffff;
+ if(size == Half) mask = 0xffff << 8*(addr & 2);
+ if(size == Byte) mask = 0xff << 8*(addr & 3);
+
+ data &= mask;
+
+ switch(addr-0x4000000 & ~3) {
+
+ case 0x0000: // Display 0 / PPU0 control
+ if(mask & 0x000f0000) {
+ // These bits go to the display controller - not PPU0.
+ video.frameBuffer &= ~0xc;
+ video.frameBuffer |= 0xc & data>>16;
+ video.source[0] = 0x3 & data>>16;
+ }
+ ppu[0].regControl(data, mask);
+ return;
+
+ case 0x1000: // Display 1 / PPU1 control
+ if(mask & 0x000f0000) {
+ // Framebuffer/FIFO sources aren't supported here.
+ video.source[1] = 0x1 & data>>16;
+ }
+ ppu[1].regControl(data, mask);
+ return;
+
+ case 0x0008: case 0x1008: // BGn control
+ case 0x000c: case 0x100c: //
+ if(mask & 0x0000ffff) ppu[addr>>12 & 1].regBg((addr>>1 & 2) + 0, data>>0, mask>>0);
+ if(mask & 0xffff0000) ppu[addr>>12 & 1].regBg((addr>>1 & 2) + 1, data>>16, mask>>16);
+ return;
+
+ case 0x0010: case 0x1010: // BGn H,V scroll
+ case 0x0014: case 0x1014: //
+ case 0x0018: case 0x1018: //
+ case 0x001c: case 0x101c: return ppu[addr>>12 & 1].regBgOffs(addr>>2 & 3, data, mask);
+
+ case 0x0020: case 0x1020: // BG2 affine A, B, C, D
+ case 0x0024: case 0x1024: //
+ case 0x0028: case 0x1028: // BG2 origin X, Y
+ case 0x002c: case 0x102c: return ppu[addr>>12 & 1].regBgAffine(2, addr>>2 & 3, data, mask);
+
+ case 0x0030: case 0x1030: // BG3 affine A, B, C, D
+ case 0x0034: case 0x1034: //
+ case 0x0038: case 0x1038: // BG3 origin X, Y
+ case 0x003c: case 0x103c: return ppu[addr>>12 & 1].regBgAffine(3, addr>>2 & 3, data, mask);
+
+ case 0x0040: case 0x1040: return ppu[addr>>12 & 1].regWinDims(0, data, mask); // Window 0,1 X range
+ case 0x0044: case 0x1044: return ppu[addr>>12 & 1].regWinDims(1, data, mask); // 0,1 Y range
+ case 0x0048: case 0x1048: return ppu[addr>>12 & 1].regWinArea(data, mask); // area 0,1,out,obj
+ case 0x004c: case 0x104c: return; // Mosaic BG,OBJ X,Y
+
+ case 0x0050: case 0x1050: // Blend control
+ case 0x0054: case 0x1054: return ppu[addr>>12 & 1].regBlend(addr>>2 & 1, data, mask);
+
+ case 0x0058: case 0x1058: return; // not present, but frequently zeroed anyway
+ case 0x005c: case 0x105c: return; //
+
+ // Some miscellaneous registers, none of which belong here... hunh.
+ case 0x0060: return gpu.regRenderOptions(data, mask);
+ case 0x0064: return video.regCapture(data, mask);
+ case 0x0068: return video.regFifo(data);
+ case 0x006c: return video.regBrightness(0, data, mask);
+
+ case 0x1060: return;
+ case 0x1064: return;
+ case 0x1068: return;
+ case 0x106c: return video.regBrightness(1, data, mask);
+
+ // Memory control
+ case 0x0204:
+ if(mask & 0x00ff) {
+ slot2access = !(data & 1<<7);
+ }
+ if(mask & 0xff00) {
+ slot1access = !(data & 1<<11);
+ ramPriority = !(data & 1<<15);
+ }
+ return regSlot2Control(data, mask);
+
+ case 0x0240: return system.regVmap(0, data, mask);
+ case 0x0244: return system.regVmap(1, data, mask);
+ case 0x0248: return system.regVmap(2, data, mask);
+
+ // Math
+ case 0x0280: return regDivideControl(data, mask);
+ case 0x0290: return regNumerator(0, data, mask);
+ case 0x0294: return regNumerator(1, data, mask);
+ case 0x0298: return regDenominator(0, data, mask);
+ case 0x029c: return regDenominator(1, data, mask);
+
+ case 0x02b0: return regSquareRootControl(data, mask);
+ case 0x02b8: return regSquare(0, data, mask);
+ case 0x02bc: return regSquare(1, data, mask);
+
+ case 0x0300:
+ if(mask & 0xff) {
+ booted |= data>>0;
+ flag300 = data>>1;
+ }
+ return;
+
+ case 0x0304: // Power control
+ if(mask & 0x00ff) {
+ video.screensPowered = data>>0;
+ ppu[0].powered = data>>1;
+ //gpu.renderPowered = data>>2;
+ //gpu.geomPowered = data>>3;
+ }
+ if(mask & 0xff00) {
+ ppu[1].powered = data>>9;
+ video.ppu0Screen = data>>15;
+ }
+ return;
+
+ // Toon edge table
+ case 0x0330: case 0x0334: case 0x0338: case 0x033c:
+ return gpu.regRenderEdgeTable((addr - 0x4000330)/4, data, mask);
+
+ // Misc
+ case 0x0340: return gpu.regRenderMinAlpha(data, mask);
+ case 0x0350: return gpu.regRenderClearColor(data, mask);
+ case 0x0354: return gpu.regRenderClearCoord(data, mask);
+ case 0x0358: return gpu.regRenderFogColor(data, mask);
+ case 0x035c: return gpu.regRenderFogCoord(data, mask);
+
+ // Fog table
+ case 0x0360: case 0x0364: case 0x0368: case 0x036c:
+ case 0x0370: case 0x0374: case 0x0378: case 0x037c:
+ return gpu.regRenderFogTable((addr - 0x4000360)/4, data, mask);
+
+ // Toon shade table
+ case 0x0380: case 0x0384: case 0x0388: case 0x038c:
+ case 0x0390: case 0x0394: case 0x0398: case 0x039c:
+ case 0x03a0: case 0x03a4: case 0x03a8: case 0x03ac:
+ case 0x03b0: case 0x03b4: case 0x03b8: case 0x03bc:
+ return gpu.regRenderToonTable((addr - 0x4000380)/4, data, mask);
+
+ // GPU command pipe - buffered - mirrored to support STM
+ case 0x0400: case 0x0404: case 0x0408: case 0x040c: case 0x0410: case 0x0414: case 0x0418: case 0x041c:
+ case 0x0420: case 0x0424: case 0x0428: case 0x042c: case 0x0430: case 0x0434: case 0x0438: case 0x043c:
+ return gpu.sendGeomBuffered(data);
+
+ // GPU command pipe - immediate - the address itself is used as command number.
+ case 0x0440: case 0x0444: case 0x0448: case 0x044c: case 0x0450: case 0x0454: case 0x0458: case 0x045c:
+ case 0x0460: case 0x0464: case 0x0468: case 0x046c: case 0x0470: case 0x0474: case 0x0478: case 0x047c:
+ case 0x0480: case 0x0484: case 0x0488: case 0x048c: case 0x0490: case 0x0494: case 0x0498: case 0x049c:
+ case 0x04a0: case 0x04a4: case 0x04a8: case 0x04ac: case 0x04b0: case 0x04b4: case 0x04b8: case 0x04bc:
+ case 0x04c0: case 0x04c4: case 0x04c8: case 0x04cc: case 0x04d0: case 0x04d4: case 0x04d8: case 0x04dc:
+ case 0x04e0: case 0x04e4: case 0x04e8: case 0x04ec: case 0x04f0: case 0x04f4: case 0x04f8: case 0x04fc:
+ case 0x0500: case 0x0504: case 0x0508: case 0x050c: case 0x0510: case 0x0514: case 0x0518: case 0x051c:
+ case 0x0520: case 0x0524: case 0x0528: case 0x052c: case 0x0530: case 0x0534: case 0x0538: case 0x053c:
+ case 0x0540: case 0x0544: case 0x0548: case 0x054c: case 0x0550: case 0x0554: case 0x0558: case 0x055c:
+ case 0x0560: case 0x0564: case 0x0568: case 0x056c: case 0x0570: case 0x0574: case 0x0578: case 0x057c:
+ case 0x0580: case 0x0584: case 0x0588: case 0x058c: case 0x0590: case 0x0594: case 0x0598: case 0x059c:
+ case 0x05a0: case 0x05a4: case 0x05a8: case 0x05ac: case 0x05b0: case 0x05b4: case 0x05b8: case 0x05bc:
+ case 0x05c0: case 0x05c4: case 0x05c8: case 0x05cc: case 0x05d0: case 0x05d4: case 0x05d8: case 0x05dc:
+ case 0x05e0: case 0x05e4: case 0x05e8: case 0x05ec: case 0x05f0: case 0x05f4: case 0x05f8: case 0x05fc:
+ return gpu.sendGeomImmediate(addr>>2 & 0x7f, data);
+
+ // Geometry engine
+ case 0x0600: return gpu.regGeomStatus(data, mask);
+ case 0x0610: return gpu.regGeomMaxPointDepth(data, mask);
+
+ // zelda gallery writes 0x2468ace0 here - ???
+ case 0x0640: break;
+ }
+ return CPUCore::writeReg(addr, size, data);
+}
+
+
+void ARM946ES::updateTcm() {
+ uint32 itcmAddr = 0, itcmSize = itcmRegion>>1 & 0x1f;
+ uint32 dtcmAddr = dtcmRegion & ~0xfff, dtcmSize = dtcmRegion>>1 & 0x1f;
+
+ // Disable by default
+ itcmRCompare = itcmWCompare = ~0;
+ dtcmRCompare = dtcmWCompare = ~0;
+ itcmRMask = itcmWMask = 0;
+ dtcmRMask = dtcmWMask = 0;
+
+ // Enable bit enables access; load bit disables reading
+ if(control.itcm) itcmWCompare = itcmAddr, itcmWMask = -1 << 9+itcmSize;
+ if(control.dtcm) dtcmWCompare = dtcmAddr, dtcmWMask = -1 << 9+dtcmSize;
+ if(control.itcm && !control.itcmLoad) itcmRCompare = itcmAddr, itcmRMask = -1 << 9+itcmSize;
+ if(control.dtcm && !control.dtcmLoad) dtcmRCompare = dtcmAddr, dtcmRMask = -1 << 9+dtcmSize;
+}
+
+
+
+#include "math.cpp"
diff --git a/bsnes/nds/cpu/bit.hpp b/bsnes/nds/cpu/bit.hpp
new file mode 100644
index 00000000..e03e03c4
--- /dev/null
+++ b/bsnes/nds/cpu/bit.hpp
@@ -0,0 +1,66 @@
+
+namespace Bit {
+
+ template
+ constexpr int count(T n) {
+ return n == 0 || w == 0? n
+ : count(n>>w & (1<(n & (1< constexpr long lowest_bit_no(long x) {
+ return !x? -1 : !s? 0 :
+ x & (1<(x)
+ : s + lowest_bit_no(x >> s);
+}
+
+constexpr long binary(const char *s) {
+ return !*s? 0 : (*s=='1') << bitpos(s) | binary(s+1);
+}
+constexpr long mask(const char *s) {
+ return !*s? 0 : (*s=='0'||*s=='1') << bitpos(s) | mask(s+1);
+}
+constexpr long field(const char *s) {
+ return !*s? 0 : (*s!=' '&& isfield(*s)) << bitpos(s) | field(s+1);
+}
+constexpr bool match(long data, const char *s) {
+ return (data & mask(s)) == binary(s);
+}
+
+// Masks all 'bits' from the input and shifts them down into one contiguous
+// value. This inlines to a sequence of &, >> and + instructions.
+// Example:
+// collect(i)
+// joins i's 1st, 3rd, and 5th nibbles (0x12345 => 0x135).
+template constexpr long collect(long data);
+template constexpr long collect_field(long data) {
+ return (data & (1<> nmask)>(data >> nmask) << nmask*(bits&1));
+}
+
+template constexpr long collect(long data) {
+ return collect_field(data);
+}
+template<> constexpr long collect<0>(long data) {
+ return 0;
+}
+
+};
diff --git a/bsnes/nds/cpu/core.cpp b/bsnes/nds/cpu/core.cpp
new file mode 100644
index 00000000..1bfcf4f3
--- /dev/null
+++ b/bsnes/nds/cpu/core.cpp
@@ -0,0 +1,214 @@
+
+void ARMCore::power() {
+ for(int n = 0; n < 16; n++) r[n] = 0;
+ for(int n = 0; n < 7; n++) r_fiq[n] = 0;
+ for(int n = 0; n < 2; n++) r_irq[n] = r_svc[n] = r_abt[n] = r_und[n] = 0;
+
+ spsr_none = spsr_fiq = spsr_irq = spsr_svc = spsr_abt = spsr_und = 0;
+ carryout = 0;
+ Nf = Cf = Vf = Qf = 0;
+ Zf = -1;
+
+ reset();
+}
+
+
+
+uint32& ARMCore::spsr() {
+ return mode == FIQ? spsr_fiq : mode == IRQ? spsr_irq
+ : mode == SVC? spsr_svc : mode == UND? spsr_und
+ : mode == ABT? spsr_abt : spsr_none;
+}
+
+uint32 ARMCore::readCpsr() {
+ uint32 n = Nf & 1<<31, c = Cf & 1<<31;
+ uint32 v = Vf & 1<<31, q = Qf & 1<<31;
+ uint32 z = !Zf <<31;
+
+ return n>>0 | z>>1 | c>>2 | v>>3 | q>>4 | If<<7 | Ff<<6 | Tf<<5 | mode<<0;
+}
+
+void ARMCore::writeCpsr(uint32 value, unsigned mask) {
+ if(mask & 8) {
+ Nf = value<<0 & 1<<31; Zf = !(value<<1 & 1<<31);
+ Cf = value<<2 & 1<<31; Vf = value<<3 & 1<<31;
+ Qf = value<<4 & 1<<31;
+ }
+ if(mode == USR)
+ return; // cpsr_c is privileged
+
+ if(mask & 1) {
+ swapBank(mode);
+ If = value>>7 & 1; Ff = value>>6 & 1;
+ Tf = value>>5 & 1; mode = value & 0x1f;
+
+ mode |= 0x10; // enforce 32-bit addressing
+ if(mode & 0x0c)
+ mode |= 0x03; // enforce valid mode bits
+ swapBank(mode);
+ }
+}
+
+void ARMCore::vector(uint32 offset, unsigned tomode) {
+ uint32 psr = readCpsr();
+
+ swapBank(mode);
+ swapBank(mode = tomode);
+
+ // vector() is called between the instruction fetch and PC increment..
+ // therefore in ARM mode, r15 == PC+8. THUMB requires an adjustment
+ // (done in the caller).
+ r[14] = r[15] - 4;
+ r[15] = vectorBase + offset;
+ If = 1;
+ Tf = 0;
+ spsr() = psr;
+ branched = true;
+}
+
+void ARMCore::swapBank(unsigned mode) {
+ uint32 *bank = nullptr, *user = &r[15];
+ unsigned count = 0;
+
+ if(mode == FIQ) bank = &r_fiq[count = 7];
+ if(mode == IRQ) bank = &r_irq[count = 2];
+ if(mode == SVC) bank = &r_svc[count = 2];
+ if(mode == ABT) bank = &r_abt[count = 2];
+ if(mode == UND) bank = &r_und[count = 2];
+
+ while(count--) std::swap(*--bank, *--user);
+}
+
+
+
+bool ARMCore::evalCond(unsigned cond) {
+ if(cond == 14) return true;
+ if(cond == 0) return (Zf == 0); // eq
+ if(cond == 1) return !(Zf == 0); // ne
+ if(cond == 2) return (Cf < 0); // hs / cs
+ if(cond == 3) return !(Cf < 0); // lo / cc
+ if(cond == 8) return (Cf < 0 && Zf); // hi
+ if(cond == 9) return !(Cf < 0 && Zf); // ls
+ if(cond == 10) return ((Nf^Vf) >= 0); // ge
+ if(cond == 11) return !((Nf^Vf) >= 0); // lt
+ if(cond == 12) return ((Nf^Vf) >= 0 && Zf); // gt
+ if(cond == 13) return !((Nf^Vf) >= 0 && Zf); // le
+ if(cond == 4) return (Nf < 0); // mi
+ if(cond == 5) return !(Nf < 0); // pl
+ if(cond == 6) return (Vf < 0); // vs
+ if(cond == 7) return !(Vf < 0); // vc
+ return false;
+}
+
+void ARMCore::branch(bool tf, uint32 target) {
+ r[15] = target;
+ Tf = tf;
+ branched = true;
+}
+
+
+
+uint32 ARMCore::load(uint32 addr, uint32 size) {
+ uint32 data = read(addr, size, false);
+ data = ror(data, 8*(addr & 3));
+ step(1);
+
+ if(size == Half) data &= 0xffff;
+ if(size == Byte) data &= 0xff;
+ return data;
+}
+
+void ARMCore::store(uint32 addr, uint32 size, uint32 data) {
+ if(size == Half) data &= 0xffff, data *= 0x00010001;
+ if(size == Byte) data &= 0xff, data *= 0x01010101;
+
+ write(addr, size, false, data);
+}
+
+
+
+ARMCore::SOut ARMCore::lsl(uint32 rm, uint8 rs) {
+ if(rs == 0) return {rm, Cf};
+ else return {rs>31? 0 : rm << rs,
+ rs>32? 0 : rm << rs-1};
+}
+ARMCore::SOut ARMCore::lsr(uint32 rm, uint8 rs) {
+ if(rs == 0) return {rm, Cf};
+ else return {rs>31? 0 : rm >> rs,
+ rs>32? 0 : rm << 32-rs};
+}
+ARMCore::SOut ARMCore::asr(uint32 rm, uint8 rs) {
+ if(rs == 0) return {rm, Cf};
+ else return {rs>31? (int32)rm>>31 : (int32)rm >> rs,
+ rs>32? rm : rm << 32-rs};
+}
+ARMCore::SOut ARMCore::ror(uint32 rm, uint8 rs) {
+ if(rs == 0) return {rm, Cf};
+ if(!(rs &= 31)) return {rm, rm}; // rs == multiple of 32
+ else return {rm << 32-rs | rm >> rs, rm << 32-rs};
+}
+ARMCore::SOut ARMCore::rrx(uint32 rm) {
+ return {(Cf & 1<<31) | rm >> 1, rm << 31};
+}
+
+ARMCore::SOut ARMCore::shiftImm(uint4 irm, uint2 opcode, uint5 rs) {
+ if(opcode == 0) return lsl(r[irm], rs);
+ if(opcode == 1) return lsr(r[irm], rs? (uint8)rs : 32);
+ if(opcode == 2) return asr(r[irm], rs? (uint8)rs : 32);
+ if(rs != 0) return ror(r[irm], rs);
+ if(rs == 0) return rrx(r[irm]);
+}
+
+void ARMCore::alu(unsigned opcode, uint32& rd, uint32 rn, SOut rm) {
+ if(opcode == 13*2+0) return bitf(0, rd = rm, rm); // mov
+ if(opcode == 2*2+0) return sumf(0, rd = rn - rm, rn,~rm); // sub
+ if(opcode == 4*2+0) return sumf(0, rd = rn + rm, rn, rm); // add
+ if(opcode == 0*2+0) return bitf(0, rd = rn & rm, rm); // and
+ if(opcode == 12*2+0) return bitf(0, rd = rn | rm, rm); // orr
+ if(opcode == 14*2+0) return bitf(0, rd = rn &~rm, rm); // bic
+ if(opcode == 1*2+0) return bitf(0, rd = rn ^ rm, rm); // eor
+
+ if(opcode == 13*2+1) return bitf(1, rd = rm, rm); // movs
+ if(opcode == 10*2+1) return sumf(1, rn - rm, rn,~rm); // cmps
+ if(opcode == 11*2+1) return sumf(1, rn + rm, rn, rm); // adds
+
+ if(opcode == 2*2+1) return sumf(1, rd = rn - rm, rn,~rm); // subs
+ if(opcode == 4*2+1) return sumf(1, rd = rn + rm, rn, rm); // adds
+ if(opcode == 0*2+1) return bitf(1, rd = rn & rm, rm); // ands
+ if(opcode == 12*2+1) return bitf(1, rd = rn | rm, rm); // orrs
+ if(opcode == 14*2+1) return bitf(1, rd = rn &~rm, rm); // bics
+ if(opcode == 1*2+1) return bitf(1, rd = rn ^ rm, rm); // eors
+ if(opcode == 8*2+1) return bitf(1, rn & rm, rm); // tsts
+ if(opcode == 9*2+1) return bitf(1, rn ^ rm, rm); // teqs
+
+ if(opcode == 3*2+0) return sumf(0, rd = rm - rn, ~rn, rm); // rsb
+ if(opcode == 5*2+0) return sumf(0, rd = rn + rm +!!(Cf>>31), rn, rm); // adc
+ if(opcode == 6*2+0) return sumf(0, rd = rn - rm - !(Cf>>31), rn,~rm); // sbc
+ if(opcode == 7*2+0) return sumf(0, rd = rm - rn - !(Cf>>31),~rn, rm); // rsc
+ if(opcode == 15*2+0) return bitf(0, rd = ~rm, rm); // mvn
+
+ if(opcode == 3*2+1) return sumf(1, rd = rm - rn, ~rn, rm); // rsbs
+ if(opcode == 5*2+1) return sumf(1, rd = rn + rm +!!(Cf>>31), rn, rm); // adcs
+ if(opcode == 6*2+1) return sumf(1, rd = rn - rm - !(Cf>>31), rn,~rm); // sbcs
+ if(opcode == 7*2+1) return sumf(1, rd = rm - rn - !(Cf>>31),~rn, rm); // rscs
+ if(opcode == 15*2+1) return bitf(1, rd = ~rm, rm); // mvns
+}
+
+
+
+uint32 ARMCore::oflow(uint32 rd, uint32 rn, uint32 rm) {
+ return ~(rn^rm) & (rn^rd);
+}
+
+void ARMCore::bitf(bool s, uint32 rd, SOut rm) {
+ if(s) Cf = rm.carry, Nf = Zf = rd;
+}
+
+void ARMCore::sumf(bool s, uint32 rd, uint32 rn, uint32 rm) {
+ if(s) Vf = oflow(rd,rn,rm), Cf = Vf ^ rd^rn^rm, Nf = Zf = rd;
+}
+
+
+
+#include "arm.cpp"
+#include "thumb.cpp"
diff --git a/bsnes/nds/cpu/core.hpp b/bsnes/nds/cpu/core.hpp
new file mode 100644
index 00000000..3838067d
--- /dev/null
+++ b/bsnes/nds/cpu/core.hpp
@@ -0,0 +1,135 @@
+
+struct ARMCore {
+ // Model specific implementation
+ virtual void power();
+ virtual void step(unsigned n) = 0;
+
+ // Instruction and data access
+ virtual uint32 fetch(uint32 addr, uint32 size, bool s) = 0;
+ virtual uint32 read(uint32 addr, uint32 size, bool s) = 0;
+ virtual void write(uint32 addr, uint32 size, bool s, uint32 data) = 0;
+
+ // CDP, MCR, MRC
+ virtual void dataCop(uint4 cpno, uint4 op1, uint4 ird, uint4 irn, uint4 irm, uint4 op2) = 0;
+
+ // Vectors
+ void reset() { vector(0x000, SVC); Ff = 1; } // THUMB:
+ void fiq() { vector(0x01c, FIQ); Ff = 1; if(spsr() & 1<<5) r[14] += 4; } // LR = insn+4
+ void irq() { vector(0x018, IRQ); if(spsr() & 1<<5) r[14] += 4; }
+ void swi() { vector(0x008, SVC); if(spsr() & 1<<5) r[14] += 2; } // LR = insn+2
+ void undefined() { vector(0x004, UND); if(spsr() & 1<<5) r[14] += 2; }
+ void pfabort() { vector(0x00c, ABT); if(spsr() & 1<<5) r[14] += 2; }
+ void abort() { vector(0x010, ABT); if(spsr() & 1<<5) r[14] += 8; } // LR = insn+8
+
+ // PSRs and mode switching
+ uint32& spsr();
+ uint32 readCpsr();
+ void writeCpsr(uint32 value, uint32 mask);
+ void vector(uint32 offset, unsigned tomode);
+ void swapBank(unsigned mode);
+
+ alwaysinline bool evalCond(unsigned cond);
+
+ void branch(bool tf, uint32 target);
+
+ // LDR rotation, STR mirroring
+ uint32 load(uint32 addr, uint32 size);
+ void store(uint32 addr, uint32 size, uint32 data);
+
+ // Shifts, arithmetic
+ struct SOut {
+ // Shifter output
+ uint32 rm;
+ int32 carry;
+
+ SOut(uint32 rm) : rm(rm) {}
+ SOut(uint32 rm, int32 carry) : rm(rm), carry(carry) {}
+ operator uint32() { return rm; }
+ };
+ alwaysinline SOut lsl(uint32 rm, uint8 rs);
+ alwaysinline SOut lsr(uint32 rm, uint8 rs);
+ alwaysinline SOut asr(uint32 rm, uint8 rs);
+ alwaysinline SOut ror(uint32 rm, uint8 rs);
+ alwaysinline SOut rrx(uint32 rm);
+
+ alwaysinline SOut shiftImm(uint4 irm, uint2 opcode, uint5 rs);
+ alwaysinline void alu(unsigned opcode, uint32& rd, uint32 rn, SOut rm);
+
+ // Flags
+ alwaysinline uint32 oflow(uint32 rd, uint32 rn, uint32 rm);
+ alwaysinline void bitf(bool s, uint32 rd, SOut rm);
+ alwaysinline void sumf(bool s, uint32 rd, uint32 rn, uint32 rm);
+
+ // ARM argument Rm
+ alwaysinline uint32 armRm(uint4 irm) { return r[irm]; }
+ alwaysinline SOut armImmed(uint8 value, uint4 rs) { return ror(value, 2*rs); }
+ alwaysinline uint32 armOffset8(uint4 lo, uint4 hi) { return lo | hi<<4; }
+ alwaysinline uint32 armOffset12(uint12 value) { return value; }
+
+ // ARM handlers
+ void armWritePsr(uint1 opcode, uint4 mask, uint32 rm);
+ void armReadPsr(uint1 opcode, uint4 ird);
+ void armBranch(uint1 link, uint1 exch, int26 offset);
+ void armBranchEx(uint1 link, uint4 irm);
+ void armClz(uint4 ird, uint4 irm);
+ void armDspAdd(uint2 opcode, uint4 ird, uint4 irn, uint4 irm);
+ void armDspMul(uint2 opcode, uint2 xy, uint4 ird, uint4 irn, uint4 irm, uint4 irs);
+ void armMultiply(uint4 opcode, uint4 ird, uint4 irn, uint4 irm, uint4 irs);
+ void armDataRs(uint5 opcode, uint4 ird, uint4 irn, uint4 irm, uint2 sh, uint4 irs);
+ void armData(uint5 opcode, uint4 ird, uint4 irn, SOut rm);
+ void armMemSwap(uint1 opcode, uint4 ird, uint4 irn, uint4 irm);
+ void armMem(uint5 opcode, uint4 ird, uint4 irn, uint32 rm);
+ void armMem_v4(uint5 opcode, uint2 sh, uint4 ird, uint4 irn, uint32 rm);
+ void armMem_v5(uint5 opcode, uint2 sh, uint4 ird, uint4 irn, uint32 rm);
+ void armBlock(uint5 opcode, uint4 irn, uint16 rlist);
+
+ // THUMB handlers
+ void thumbDataLo(uint4 opcode, uint3 ird, uint3 irm);
+ void thumbDataHi(uint2 opcode, uint4 ird, uint4 irm);
+ void thumbDataImm(uint2 opcode, uint3 ird, uint8 rm);
+ void thumbShiftImm(uint2 opcode, uint3 ird, uint3 irm, uint5 rs);
+ void thumbAddSub(uint2 opcode, uint3 ird, uint3 irn, uint3 irm);
+ void thumbMemImm(uint5 opcode, uint3 ird, uint3 irn, uint5 rm);
+ void thumbMemReg(uint3 opcode, uint3 ird, uint3 irn, uint3 irm);
+ void thumbRelative(uint5 opcode, uint3 ird, uint8 rm);
+ void thumbAddSP(uint1 opcode, uint7 rm);
+ void thumbBlock(uint4 opcode, uint3 irn, uint8 rlist);
+ void thumbCond(uint4 opcode, int8 offset);
+ void thumbBranch(int11 offset);
+ void thumbBh(int11 offset);
+ void thumbBlx(uint1 link, uint11 offset);
+
+ // CPSR
+ // NZCVQ are stored in a lazy format:
+ // - Z is only true when 0.
+ // - NCVQ are true when < 0 (bit 31 set).
+ int32 Nf, Zf, Cf, Vf, Qf;
+ uint8 If, Ff, Tf, mode;
+
+ // Output from shifter
+ int32 carryout; // same format as Cf
+
+ // Pipeline data
+ bool branched;
+ uint32 ifetch, idecode, iexecute;
+
+ // Configuration
+ uint32 vectorBase; // Address of vector table
+ bool bxWithLoadedPC; // Does LDR/LDM PC behave as MOV or BX Rm?
+
+ // Register banks
+ // - r_fiq[n] etc. hold registers in other banks.
+ // - r[n] holds registers for the active mode
+ // - This means that in FIQ mode, r_fiq[n] holds shadowed _user_ registers.
+ // - SPSR is not swapped, use spsr() to access it.
+ uint32 r[16], spsr_none, r_abt[2], spsr_abt;
+ uint32 r_fiq[7], spsr_fiq, r_irq[2], spsr_irq;
+ uint32 r_svc[2], spsr_svc, r_und[2], spsr_und;
+
+ // Exception modes
+ enum {
+ USR = 0x10,
+ FIQ = 0x11, IRQ = 0x12, SVC = 0x13,
+ UND = 0x1b, ABT = 0x17, SYS = 0x1f,
+ };
+};
diff --git a/bsnes/nds/cpu/cpu.cpp b/bsnes/nds/cpu/cpu.cpp
new file mode 100644
index 00000000..1b9dd4d1
--- /dev/null
+++ b/bsnes/nds/cpu/cpu.cpp
@@ -0,0 +1,337 @@
+#include
+#include "bit.hpp"
+#define imatch(bits) ((i & force< Bit::mask(bits) >()) \
+ == force< Bit::binary(bits) >())
+
+template static constexpr uint32 force() { return arg; }
+
+namespace NintendoDS {
+
+#include "core.cpp"
+#include "disasm.cpp"
+
+ARM7TDMI arm7;
+ARM946ES arm9;
+
+
+CPUCore::CPUCore() {
+ thread = nullptr;
+}
+
+CPUCore::~CPUCore() {
+ if(thread) co_delete(thread);
+}
+
+void CPUCore::power() {
+ ARMCore::power();
+
+ clock = 0;
+ trace = false;
+
+ powerState = running;
+
+ config.xorSeeds[0] = 0;
+ config.xorSeeds[1] = 0;
+ config.slot2ramTiming = 0;
+ config.slot2romTiming0 = 0;
+ config.slot2romTiming1 = 0;
+ config.slot2phi = 0;
+
+ interrupt.gate = false;
+ interrupt.enable = false;
+ interrupt.flags = 0;
+
+ status.inVBlank = false;
+ status.inHBlank = false;
+ status.inVMatch = false;
+ status.irqOnVBlank = false;
+ status.irqOnHBlank = false;
+ status.irqOnVMatch = false;
+ status.vcompare = 0;
+
+ msg.enable = false;
+ msg.irqOnRecv = false;
+ msg.irqOnSent = false;
+ msg.error = 0;
+ msg.empty = 1;
+ msg.full = 0;
+ msg.writeOffset = 0;
+ msg.readOffset = 0;
+ for(auto &e : msg.buffer)
+ e = 0;
+
+ sync.enable = false;
+ sync.output = 0;
+
+ event.irq = false;
+ event.anydma = false;
+ event.queue.reset();
+
+ for(unsigned n = 0; n < 4; n++) {
+ dma[n].enable = false;
+ dma[n].irq = false;
+ dma[n].size = 0;
+ dma[n].repeat = false;
+ dma[n].trigger = 0;
+ dma[n].srcStep = 0;
+ dma[n].destStep = 0;
+ dma[n].source = 0;
+ dma[n].dest = 0;
+ dma[n].count = 0;
+ dma[n].fill = 0;
+ dma[n].init.source = 0;
+ dma[n].init.dest = 0;
+ dma[n].init.count = 0;
+
+ timer[n].enable = false;
+ timer[n].irq = false;
+ timer[n].cascade = false;
+ timer[n].divider = 0;
+ timer[n].reload = 0;
+ timer[n].count = 0;
+ timer[n].lastUpdate = 0;
+ timer[n].event.action = [&, n]() { updateTimer(n); };
+ }
+}
+
+void CPUCore::hdraw() {
+ status.inHBlank = false;
+ status.inVMatch = false;
+
+ if(192 == video.line) {
+ status.inVBlank = true;
+ if(status.irqOnVBlank)
+ interrupt.flags |= irqVBlank;
+
+ // Trigger vblank DMAs
+ dmaTrigger(0xf, 1);
+ }
+ if(262 == video.line) {
+ status.inVBlank = false;
+ }
+
+ // Trigger peripheral-to-framebuffer DMA
+ if(config.arm9 && 2 <= video.line && video.line < 192+2)
+ dmaTrigger(0xf, 3);
+
+ if(status.vcompare == video.line) {
+ status.inVMatch = true;
+ if(status.irqOnVMatch) {
+ interrupt.flags |= irqVMatch;
+ }
+ }
+}
+
+void CPUCore::hblank() {
+ status.inHBlank = true;
+ if(status.irqOnHBlank)
+ interrupt.flags |= irqHBlank;
+
+ // Trigger HDMAs
+ if(config.arm9 && video.line < 192)
+ dmaTrigger(0xf, 2);
+}
+
+
+
+string CPUCore::tracePsr(uint32 value) {
+ return { value & 1<<31? "N":" ",
+ value & 1<<30? "Z":" ",
+ value & 1<<29? "C":" ",
+ value & 1<<28? "V":" ",
+ value & 1<<27? "Q":" ",
+ value & 1<< 7? "I":" ",
+ value & 1<< 6? "F":" ",
+ value & 1<< 5? "T":" ",
+ "/", hex<2>(value & 0x1f) };
+}
+
+void CPUCore::traceInsn() {
+ for(unsigned n = 0; n < 8; n++) print(hex<1>(n),":",hex<8>(r[n])," ");
+
+ print(tracePsr(readCpsr()), "\n");
+
+ for(unsigned n = 8; n < 16; n++) print(hex<1>(n),":",hex<8>(r[n])," ");
+
+ if(mode != SYS && mode != USR) print(tracePsr(spsr()), "\n");
+ else print("--------:--", "\n");
+
+ if(Tf) print(hex<8>(r[15] - 4), ": ", hex<4>(iexecute), " ", disasm::thumb(this, iexecute), "\n");
+ else print(hex<8>(r[15] - 8), ": ", hex<8>(iexecute), " ", disasm::arm(this, iexecute), "\n");
+
+ fflush(stdout);
+}
+
+
+
+uint32 CPUCore::readReg(uint32 addr, uint32 size) {
+ addr &= ~3;
+
+ //static bool vbl = 0;
+ switch(addr-0x04000000) {
+ case 0x0004: // Display status
+ return video.line << 16 | status.irqOnVMatch<< 5 | status.inVMatch<< 2
+ | (status.vcompare & 0x0ff)<< 8 | status.irqOnHBlank<< 4 | status.inHBlank<< 1
+ | (status.vcompare & 0x100)>> 1 | status.irqOnVBlank<< 3 | status.inVBlank<< 0;
+
+ case 0x1004:
+ return 0;
+
+ case 0x00b0: // DMA0 source
+ case 0x00bc: // DMA1 source
+ case 0x00c8: // DMA2 source
+ case 0x00d4: // DMA3 source
+ return regDmaSource((addr-0x40000b0)/12);
+
+ case 0x00b4: // DMA0 dest
+ case 0x00c0: // DMA1 dest
+ case 0x00cc: // DMA2 dest
+ case 0x00d8: // DMA3 dest
+ return regDmaDest((addr-0x40000b0)/12);
+
+ case 0x00b8: // DMA0 control
+ case 0x00c4: // DMA1 control
+ case 0x00d0: // DMA2 control
+ case 0x00dc: // DMA3 control
+ return regDmaControl((addr-0x40000b0)/12);
+
+ case 0x00e0: // DMA0 fill
+ case 0x00e4: // DMA1 fill
+ case 0x00e8: // DMA2 fill
+ case 0x00ec: // DMA3 fill
+ return regDmaFill(addr>>2 & 3);
+
+ case 0x0100: // Timer 0
+ case 0x0104: // Timer 1
+ case 0x0108: // Timer 2
+ case 0x010c: // Timer 3
+ return regTimer(addr>>2 & 3);
+
+ case 0x130: { // Keypad input
+ unsigned keys = 0;
+ for(unsigned n = 0; n < 10; n++) {
+ if(interface->inputPoll(ID::Port::Buttons, 0, n))
+ keys += 1<(addr),":",size,": unimplemented\n");
+ return 0;
+}
+
+
+
+void CPUCore::writeReg(uint32 addr, uint32 size, uint32 data) {
+ uint32 mask = 0xffffffff;
+ if(size == Half) mask = 0xffff << 8*(addr & 2);
+ if(size == Byte) mask = 0xff << 8*(addr & 3);
+
+ addr &= ~3, data &= mask;
+
+ switch(addr-0x04000000) {
+ case 0x0004: // Display status
+ // It might seem odd to have this here, but each CPU has one.
+ if(mask & 0xff00) status.vcompare = (status.vcompare & 0x100) | (data>>8 & 0x0ff);
+ if(mask & 0x0080) status.vcompare = (status.vcompare & 0x0ff) | (data<<1 & 0x100);
+ if(mask & 0x003f) {
+ status.irqOnVMatch = data >> 5;
+ status.irqOnHBlank = data >> 4;
+ status.irqOnVBlank = data >> 3;
+ }
+ return;
+
+ case 0x1004:
+ return;
+
+ case 0x00b0: // DMA0 source
+ case 0x00bc: // DMA1 source
+ case 0x00c8: // DMA2 source
+ case 0x00d4: // DMA3 source
+ return regDmaSource((addr-0x40000b0)/12, data, mask);
+
+ case 0x00b4: // DMA0 dest
+ case 0x00c0: // DMA1 dest
+ case 0x00cc: // DMA2 dest
+ case 0x00d8: // DMA3 dest
+ return regDmaDest((addr-0x40000b0)/12, data, mask);
+
+ case 0x00b8: // DMA0 control
+ case 0x00c4: // DMA1 control
+ case 0x00d0: // DMA2 control
+ case 0x00dc: // DMA3 control
+ return regDmaControl((addr-0x40000b0)/12, data, mask);
+
+ case 0x00e0: // DMA0 fill
+ case 0x00e4: // DMA1 fill
+ case 0x00e8: // DMA2 fill
+ case 0x00ec: // DMA3 fill
+ return regDmaFill(addr>>2 & 3, data, mask);
+
+ case 0x0100: // Timer 0
+ case 0x0104: // Timer 1
+ case 0x0108: // Timer 2
+ case 0x010c: // Timer 3
+ return regTimer(addr>>2 & 3, data, mask);
+
+ case 0x132: // Keypad interrupt
+ break;
+
+ // SYNC, message control, send port
+ case 0x0180: return regSync(data, mask);
+ case 0x0184: return regMsgControl(data, mask);
+ case 0x0188: return regMsgSend(data);
+
+ // Slot 1
+ case 0x01a0: return regSlot1Control(data, mask);
+ case 0x01a4: return regSlot1RomControl(data, mask);
+ case 0x01a8: return regSlot1RomCommand(0, data, mask);
+ case 0x01ac: return regSlot1RomCommand(1, data, mask);
+ case 0x01b0: return regSlot1RomSeed(0, data, mask);
+ case 0x01b4: return regSlot1RomSeed(1, data, mask);
+ case 0x01b8: return regSlot1RomSeed(2, data, mask);
+
+ // IME, IE, IF
+ case 0x0208: if(mask & 1) interrupt.gate = data & 1; return;
+ case 0x0210: interrupt.enable = interrupt.enable & ~mask | data; return;
+ case 0x0214: interrupt.flags &= ~data; return;
+ case 0x0218: return; // IE: DSi bits
+ case 0x021c: return; // IF: DSi bits
+ }
+ //print("w ",hex<8>(addr),":",size," = ",hex<8>(data),": unimplemented\n");
+}
+
+#include "slot.cpp"
+#include "message.cpp"
+#include "dma.cpp"
+#include "timer.cpp"
+#include "arm7tdmi.cpp"
+#include "arm946es.cpp"
+
+#undef imatch
+
+}
diff --git a/bsnes/nds/cpu/cpu.hpp b/bsnes/nds/cpu/cpu.hpp
new file mode 100644
index 00000000..061e4568
--- /dev/null
+++ b/bsnes/nds/cpu/cpu.hpp
@@ -0,0 +1,288 @@
+#include "core.hpp"
+
+struct CPUCore : ARMCore {
+ CPUCore();
+ ~CPUCore();
+
+ void power();
+ void hdraw();
+ void hblank();
+
+ string tracePsr(uint32 value);
+ void traceInsn();
+
+ uint32 readReg(uint32 addr, uint32 size);
+ void writeReg(uint32 addr, uint32 size, uint32 data);
+
+ void popMsg();
+ void pushMsg(uint32 data);
+ void clearMsg();
+
+ uint32 regMsgControl();
+ uint32 regMsgRecv();
+ uint32 regSync();
+
+ void regMsgControl(uint32 data, uint32 mask);
+ void regMsgSend(uint32 data);
+ void regSync(uint32 data, uint32 mask);
+
+ void dmaTransfer(unsigned no);
+ bool dmaTrigger(unsigned channels, unsigned value);
+
+ uint32 regDmaControl(unsigned no);
+ uint32 regDmaSource(unsigned no);
+ uint32 regDmaDest(unsigned no);
+ uint32 regDmaFill(unsigned no);
+
+ void regDmaControl(unsigned no, uint32 data, uint32 mask);
+ void regDmaSource(unsigned no, uint32 data, uint32 mask);
+ void regDmaDest(unsigned no, uint32 data, uint32 mask);
+ void regDmaFill(unsigned no, uint32 data, uint32 mask);
+
+ void updateTimer(unsigned no);
+ uint32 regTimer(unsigned no);
+ void regTimer(unsigned no, uint32 data, uint32 mask);
+
+ uint32 regSlot1Control();
+ uint32 regSlot1RomControl();
+ uint32 regSlot1RomCommand(unsigned index);
+ uint32 regSlot1RomRecv();
+
+ void regSlot1Control(uint32 data, uint32 mask);
+ void regSlot1RomControl(uint32 data, uint32 mask);
+ void regSlot1RomCommand(unsigned index, uint32 data, uint32 mask);
+ void regSlot1RomSeed(unsigned index, uint32 data, uint32 mask);
+
+ uint32 regSlot2Control();
+ void regSlot2Control(uint32 data, uint32 mask);
+
+ enum {
+ // REG_IE, REG_IF bits
+ irqVBlank = 1<<0, irqHBlank = 1<<1,
+ irqVMatch = 1<<2, irqTimer = 1<<3,
+ irqClock = 1<<7, irqDma = 1<<8,
+ irqKeypad = 1<<12, irqSlot2 = 1<<13,
+
+ irqSync = 1<<16,
+ irqMsgSent = 1<<17, irqMsgRecv = 1<<18,
+ irqCardDone = 1<<19, irqSlot1 = 1<<20,
+ irqGeomBuf = 1<<21, irqLid = 1<<22,
+ irqSpi = 1<<23, irqWifi = 1<<24,
+ };
+
+ struct {
+ bool arm7, arm9;
+
+ uint64 xorSeeds[2];
+
+ uint2 slot2ramTiming;
+ uint2 slot2romTiming0;
+ uint1 slot2romTiming1;
+ uint2 slot2phi;
+ } config;
+
+ struct {
+ bool gate;
+ uint32 enable, flags;
+ } interrupt;
+
+ struct {
+ uint1 enable, irqOnRecv, irqOnSent;
+ uint1 error, empty, full;
+ uint4 writeOffset, readOffset;
+ uint32 buffer[16];
+ } msg;
+
+ struct {
+ uint1 enable;
+ uint4 output;
+ } sync;
+
+ struct {
+ uint1 inVBlank, inHBlank, inVMatch; // vblank, hblank, line?
+ uint1 irqOnVBlank, irqOnHBlank, irqOnVMatch; // virq, hirq, lirq?
+ uint9 vcompare; // lineCompare?
+ } status;
+
+ struct {
+ uint1 enable, irq, size, repeat;
+ uint3 trigger;
+ uint2 srcStep, destStep;
+ uint32 source, dest, count, fill;
+ struct {
+ uint32 source, dest, count;
+ } init;
+ } dma[4];
+
+ struct Timer {
+ uint1 enable, irq, cascade;
+ uint2 divider;
+ uint16 reload, count;
+ uint32 lastUpdate;
+
+ Event event;
+
+ uint32 regRead();
+ void regWrite(uint32 data, uint32 mask);
+ void update();
+ void operator()();
+ } timer[4];
+
+ struct Ev {
+ bool irq;
+ bool anydma;
+
+ EventQueue queue;
+
+ Ev() : queue(60) {}
+ } event;
+
+ bool trace;
+ uint32 insnLatch;
+ unsigned powerState;
+ enum { running, waiting, sleeping };
+
+ WordMemory bios;
+
+ CPUCore* other;
+
+ cothread_t thread;
+ int32 clock;
+};
+
+
+
+struct ARM7TDMI : CPUCore {
+ static void Thread();
+ void main();
+ void power();
+ void step(unsigned clocks);
+
+ alwaysinline void istep(unsigned clocks);
+ alwaysinline void execARM();
+ alwaysinline void execTHUMB();
+
+ uint32 fetch(uint32 addr, uint32 size, bool s);
+ uint32 read(uint32 addr, uint32 size, bool s);
+ void write(uint32 addr, uint32 size, bool s, uint32 data);
+ void dataCop(uint4 cpno, uint4 op1, uint4 ird, uint4 irn, uint4 irm, uint4 op2);
+
+ uint32 readReg(uint32 addr, uint32 size);
+ void writeReg(uint32 addr, uint32 size, uint32 data);
+
+ ARM7TDMI();
+
+ struct SPI {
+ uint1 enable, hold, irq, size;
+ uint2 divider; // 4, 2, 1, 0.5 MHz
+ uint2 device; enum { power, flash, touch, none };
+ uint16 data;
+ } spi;
+
+ struct RTC {
+ uint4 in[2];
+ uint4 out[2];
+ uint4 dir[2];
+ uint8 buffer;
+ uint3 index;
+ } rtc;
+
+ struct SIO {
+ uint4 in, out, dir;
+ uint1 irq;
+ uint2 mode;
+ } sio;
+
+ uint1 booted;
+ uint1 flag300;
+
+ uint32 regSpi();
+ void regSpi(uint32 data, uint32 mask);
+
+ uint32 regRtc();
+ void regRtc(uint32 data, uint32 mask);
+
+ uint32 regSio();
+ void regSio(uint32 data, uint32 mask);
+};
+
+
+
+struct ARM946ES : CPUCore {
+ SRAM itcm;
+ SRAM dtcm;
+ uint32 itcmRegion, itcmRCompare, itcmRMask, itcmWCompare, itcmWMask;
+ uint32 dtcmRegion, dtcmRCompare, dtcmRMask, dtcmWCompare, dtcmWMask;
+
+ struct CR {
+ uint1 mmu;
+ uint1 dcache, icache;
+ uint1 endian; enum { little, big };
+ uint1 cachePolicy; enum { random, roundRobin };
+ uint1 dtcm, dtcmLoad;
+ uint1 itcm, itcmLoad;
+ } control;
+
+ // Math functions
+ uint2 divMode; enum { div32, div64_32, div64 };
+ uint1 divByZero;
+ uint1 divBusy;
+ int64 numerator;
+ int64 denominator;
+ int64 quotient;
+ int64 remainder;
+
+ uint1 rootMode; enum { sqrt32, sqrt64 };
+ uint1 rootBusy;
+ uint64 square;
+ uint32 squareRoot;
+
+ uint1 booted;
+ uint1 flag300;
+ uint1 slot1access;
+ uint1 slot2access;
+ uint1 ramPriority;
+
+ static void Thread();
+ void main();
+ void power();
+ void step(unsigned clocks);
+
+ alwaysinline void istep(unsigned clocks);
+ alwaysinline void execARM();
+ alwaysinline void execTHUMB();
+
+ uint32 fetch(uint32 addr, uint32 size, bool s);
+ uint32 read(uint32 addr, uint32 size, bool s);
+ void write(uint32 addr, uint32 size, bool s, uint32 data);
+ void dataCop(uint4 cpno, uint4 op1, uint4 ird, uint4 irn, uint4 irm, uint4 op2);
+
+ uint32 readReg(uint32 addr, uint32 size);
+ void writeReg(uint32 addr, uint32 size, uint32 data);
+
+ void updateTcm();
+
+ void regDivideControl(uint32 data, uint32 mask);
+ void regNumerator(unsigned index, uint32 data, uint32 mask);
+ void regDenominator(unsigned index, uint32 data, uint32 mask);
+ void regSquareRootControl(uint32 data, uint32 mask);
+ void regSquare(unsigned index, uint32 data, uint32 mask);
+
+ uint32 regDivideControl();
+ uint32 regNumerator(unsigned index);
+ uint32 regDenominator(unsigned index);
+ uint32 regQuotient(unsigned index);
+ uint32 regRemainder(unsigned index);
+ uint32 regSquareRootControl();
+ uint32 regSquare(unsigned index);
+ uint32 regSquareRoot();
+
+ void startDivide();
+ void startSquareRoot();
+
+ ARM946ES();
+};
+
+
+extern ARM7TDMI arm7;
+extern ARM946ES arm9;
diff --git a/bsnes/nds/cpu/disasm.cpp b/bsnes/nds/cpu/disasm.cpp
new file mode 100644
index 00000000..75cd55bf
--- /dev/null
+++ b/bsnes/nds/cpu/disasm.cpp
@@ -0,0 +1,411 @@
+//#include "bit.hpp"
+namespace disasm {
+
+#define collect(i, bits) (Bit::collect< Bit::field(bits) >((long)i))
+#define match(i, bits) ((i & force< Bit::mask(bits) >()) \
+ == force< Bit::binary(bits) >())
+
+template static constexpr uint32 force() { return arg; }
+
+static string conds[] = {
+ "eq","ne","cs","cc","mi","pl","vs","vc","hi","ls","ge","lt","gt","le","",""
+};
+static string regs[] = {
+ "r0","r1","r2","r3","r4","r5","r6","r7","r8","r9","r10","r11","r12","sp","lr","pc"
+};
+static string aluops[] = {
+ "and","eor","sub","rsb","add","adc","sbc","rsc","tst","teq","cmp","cmn","orr","mov","bic","mvn"
+};
+static string shiftops[] = {
+ "lsl","lsr","asr","ror"
+};
+static string blockops[] = {
+ "da","ia","db","ib"
+};
+
+string armAddr(uint2 index, uint4 rn, string u, string rm) {
+ if(index < 2) return {"[", regs[rn], "], ", u, rm};
+ if(index == 2) return {"[", regs[rn], ", ", u, rm, "]"};
+ if(index == 3) return {"[", regs[rn], ", ", u, rm, "]!"};
+}
+
+string armImmed(uint8 imm, uint4 rs) {
+ if(!rs) return {"#0x",hex<8>(imm)};
+ if(imm & 0x03) return {"#0x",hex<8>(imm << 32-2*rs | imm >> 2*rs)};
+ else return {"#0x",hex<2>(imm), ", ", 2*rs};
+}
+
+string armOffset8(uint4 lo, uint4 hi) {
+ return {"#0x",hex<2>(hi<<4 | lo)};
+}
+
+string armOffset12(uint12 offset) {
+ return {"#0x",hex<3>(offset)};
+}
+
+string armRm(uint4 rm) {
+ return regs[rm];
+}
+
+string armShiftImm(uint4 rm, uint2 sh, uint5 imm) {
+ if(sh==0 && imm==0) return regs[rm];
+ if(sh==3 && imm==0) return {regs[rm], ", rrx"};
+ return {regs[rm], ", ", shiftops[sh], " #", imm==0? 32u : (unsigned)imm};
+}
+
+string armShiftReg(uint4 rm, uint2 sh, uint4 rs) {
+ return {regs[rm], ", ", shiftops[sh], " ", regs[rs]};
+}
+
+string armUndefined(uint32 i) {
+ return {" #0x", hex<8>(i)};
+}
+
+string armBkpt(uint4 cc, uint12 hi, uint4 lo) {
+ return {"bkpt", conds[cc], " #0x", hex<4>(hi<<4 | lo)};
+}
+
+string armSwi(uint4 cc, uint24 immed) {
+ return {"swi", conds[cc], " #0x", hex<6>(immed)};
+}
+
+string armWritePsr(uint4 cc, uint1 psr, uint4 mask, string rm) {
+ string f = mask&8? "f":"";
+ string s = mask&4? "s":"";
+ string x = mask&2? "x":"";
+ string c = mask&1? "c":"";
+ return {"msr", conds[cc], " ", psr? "spsr":"cpsr", "_", f,s,x,c, ", ", rm};
+}
+
+string armReadPsr(uint4 cc, uint1 psr, uint4 rd) {
+ return {"mrs", conds[cc], " ", regs[rd], ", ", psr? "spsr":"cpsr"};
+}
+
+string armClz(uint4 cc, uint4 rd, uint4 rm) {
+ return {"clz", conds[cc], " ", regs[rd], ", ", regs[rm]};
+}
+
+string armDspAdd(uint4 cc, uint2 op, uint4 rd, uint4 rn, uint4 rm) {
+ string alu = op&1? "sub":"add";
+ string d = op&2? "d":"";
+ return {"q",d,alu, conds[cc], " ", regs[rd], ", ", regs[rn], ", ", regs[rm]};
+}
+
+string armDspMul(uint4 cc, uint2 op, uint2 xy, uint4 rd, uint4 rn, uint4 rm, uint4 rs) {
+ string x = xy&1? "t":"b";
+ string y = xy&2? "t":"b";
+
+ if(op==3) return {"smul",x,y, conds[cc], " ", regs[rd], ", ", regs[rm], ", ", regs[rs]};
+ if(op==0) return {"smla",x,y, conds[cc], " ", regs[rd], ", ", regs[rm], ", ", regs[rs], ", ", regs[rn]};
+ if(op==2) return {"smlal",x,y,conds[cc], " ", regs[rn], ", ", regs[rd], ", ", regs[rm], ", ", regs[rs]};
+
+ if(op==1 && (xy&1)) return {"smulw",y, conds[cc], " ", regs[rd], ", ", regs[rm], ", ", regs[rs]};
+ if(op==1) return {"smlaw",y, conds[cc], " ", regs[rd], ", ", regs[rm], ", ", regs[rs], ", ", regs[rn]};
+}
+
+string armMultiply(uint4 cc, uint4 op, uint4 rd, uint4 rn, uint4 rm, uint4 rs) {
+ string s = op & 1? "s":"";
+ op &= ~1;
+
+ if(op== 0) return {"mul", conds[cc], s, " ", regs[rd], ", ", regs[rm], ", ", regs[rs]};
+ if(op== 2) return {"mla", conds[cc], s, " ", regs[rd], ", ", regs[rm], ", ", regs[rs], ", ", regs[rn]};
+
+ if(op== 8) return {"umull", conds[cc], s, " ", regs[rn], ", ", regs[rd], ", ", regs[rm], ", ", regs[rs]};
+ if(op==10) return {"umlal", conds[cc], s, " ", regs[rn], ", ", regs[rd], ", ", regs[rm], ", ", regs[rs]};
+ if(op==12) return {"smull", conds[cc], s, " ", regs[rn], ", ", regs[rd], ", ", regs[rm], ", ", regs[rs]};
+ if(op==14) return {"smlal", conds[cc], s, " ", regs[rn], ", ", regs[rd], ", ", regs[rm], ", ", regs[rs]};
+}
+
+string armData(uint4 cc, uint5 op, uint4 rd, uint4 rn, string rm) {
+ string alu = aluops[collect(op, "aaaa.")];
+ string s = collect(op, "....s")? "s" : "";
+
+ if(alu == "cmp" || alu == "cmn" || alu == "tst" || alu == "teq")
+ return {alu, conds[cc], s, " ", regs[rn], ", ", rm};
+
+ if(alu == "mov" || alu == "mvn" || rd == rn)
+ return {alu, conds[cc], s, " ", regs[rd], ", ", rm};
+
+ return {alu, conds[cc], s, " ", regs[rd], ", ", regs[rn], ", ", rm};
+}
+
+string armMem(uint4 cc, uint5 op, uint4 rd, uint4 rn, string rm) {
+ uint2 index = collect(op, "p..w.");
+ string u = collect(op, ".u...")? "" : "-";
+ string b = collect(op, "..b..")? "b" : "";
+ uint1 l = collect(op, "....l");
+
+ return {cc==15? "pld" : l? "ldr":"str", conds[cc], b, index==1?"t":"",
+ " ", regs[rd], ", ", armAddr(index, rn, u, rm)};
+}
+
+string armMem_v4(uint4 cc, uint5 op1, uint2 op2, uint4 rd, uint4 rn, string rm) {
+ uint2 index = collect(op1, "p..w.");
+ string u = collect(op1, ".u...")? "" : "-";
+ uint1 l = collect(op1, "....l");
+ string sh = op2==2?"sb" : op2==3?"sh" : "h";
+
+ return {l?"ldr":"str", conds[cc], sh, " ", regs[rd], ", ", armAddr(index, rn, u, rm)};
+}
+
+string armMem_v5(uint4 cc, uint5 op1, uint2 op2, uint4 rd, uint4 rn, string rm) {
+ uint2 index = collect(op1, "p..w.");
+ string u = collect(op1, ".u...")? "" : "-";
+ uint1 s = op2 & 1;
+
+ return {s?"str":"ldr", conds[cc], "d ", regs[rd], ", ", armAddr(index, rn, u, rm)};
+}
+
+string armMemSwap(uint4 cc, uint1 op, uint4 rd, uint4 rn, uint4 rm) {
+ string b = op? "b":"";
+ return {"swp", conds[cc], b, " ", regs[rm],", ", regs[rd], ", [", regs[rn], "]"};
+}
+
+string armMemCop(uint4 cc, uint4 cpno, uint5 op, uint4 rd, uint4 rn, uint8 offset) {
+ uint2 index = collect(op, "p..w.");
+ string u = collect(op, ".u...")? "" : "-";
+ string n = collect(op, "..n..")? "l" : "";
+ uint1 l = collect(op, "....l");
+
+ return {l? "ldc":"stc", conds[cc], cc==15?"2":"", n, " p",cpno, ", c",regs[rd], ", ",
+ armAddr(index, rn, index?u:"#", {"0x",hex<2>(offset)})};
+}
+
+string armBlock(uint4 cc, uint5 op, uint4 rn, uint16 rlist) {
+ uint2 index = collect(op, "pu...");
+ string s = collect(op, "..s..")? "^" : "";
+ string w = collect(op, "...w.")? "!" : "";
+ uint1 l = collect(op, "....l");
+
+ string regnames = "";
+ for(unsigned b = 0; b < 16; b++) {
+ if(rlist & 1<(target) + 2*link*exch};
+}
+
+string armBranchEx(uint4 cc, uint2 sh, uint4 rm) {
+ return {sh & 1? "blx":"bx", conds[cc], " ", regs[rm]};
+}
+
+string armCop(uint4 cc, uint4 cpno, uint4 op1, uint4 rd, uint4 rn, uint4 rm, uint4 op2) {
+ bool cdp = ~op2 & 1;
+ bool l = op1 & 1;
+ if(!cdp) op1 >>= 1;
+ op2 >>= 1;
+ return {cdp?"cdp" : l? "mrc":"mcr", conds[cc], cc==15?"2":"",
+ " p",cpno, ",", op1>>1, ", ", cdp?"cr":"r",rd, ", ", "cr",rn, ", ", "cr",rm, ", ", op2};
+}
+
+string armCop_v5(uint4 cc, uint4 cpno, uint4 op1, uint4 rd, uint4 rn, uint4 rm, uint4 op2) {
+ bool l = op1 & 1;
+ return {l? "mrrc":"mcrr", conds[cc], cc==15?"2":"",
+ " p",cpno, ",", op2, ", ", regs[rd], ", ", regs[rn], ", ", "cr",rm};
+}
+
+
+
+static string thumbmemregops[] = {
+ "str", "strh", "strb", "ldrsb", "ldr", "ldrh", "ldrb", "ldrsh"
+};
+static string thumbmemimmops[] = {
+ "str", "ldr", "strb", "ldrb", "strh", "ldrh"
+};
+
+string thumbUndefined(uint16 i) {
+ return {" #0x", hex<4>(i)};
+}
+
+string thumbBkpt(uint8 imm) {
+ return {"bkpt #0x", hex<2>(imm)};
+}
+
+string thumbSwi(uint8 imm) {
+ return {"swi #0x", hex<2>(imm)};
+}
+
+string thumbAddSub(uint2 op, uint3 rd, uint3 rn, uint3 rm) {
+ if(op == 2 && rm == 0) return {"mov ", regs[rd], ", ", regs[rn]};
+ if(op & 2) return {op & 1?"sub":"add", " ", regs[rd], ", ", regs[rn], ", #", rm};
+ else return {op & 1?"sub":"add", " ", regs[rd], ", ", regs[rn], ", ", regs[rm]};
+}
+
+string thumbShiftImm(uint2 op, uint3 rd, uint3 rm, uint5 imm) {
+ return {shiftops[op], " ", regs[rd], ", ", regs[rm], ", #", op==0 || imm? (unsigned)imm : 32};
+}
+
+string thumbDataImm(uint2 op, uint3 rd, uint8 imm) {
+ if(op == 0) return {"mov ", regs[rd], ", #0x", hex<2>(imm)};
+ if(op == 1) return {"cmp ", regs[rd], ", #0x", hex<2>(imm)};
+ if(op == 2) return {"add ", regs[rd], ", #0x", hex<2>(imm)};
+ if(op == 3) return {"sub ", regs[rd], ", #0x", hex<2>(imm)};
+}
+
+string thumbDataLo(uint4 op, uint3 rd, uint3 rm) {
+ if(op == 2) return {"lsl ", regs[rd], ", ", regs[rm]};
+ if(op == 3) return {"lsr ", regs[rd], ", ", regs[rm]};
+ if(op == 4) return {"asr ", regs[rd], ", ", regs[rm]};
+ if(op == 7) return {"ror ", regs[rd], ", ", regs[rm]};
+ if(op == 9) return {"neg ", regs[rd], ", ", regs[rm]};
+ if(op ==13) return {"mul ", regs[rd], ", ", regs[rm]};
+
+ return {aluops[op], " ", regs[rd], ", ", regs[rm]};
+}
+
+string thumbDataHi(uint2 op, uint4 rd, uint4 rm) {
+ if(op == 0) return {"add ", regs[rd], ", ", regs[rm]};
+ if(op == 1) return {"cmp ", regs[rd], ", ", regs[rm]};
+ if(op == 2) return {"mov ", regs[rd], ", ", regs[rm]};
+ if(rd & 8) return {"blx ", regs[rm]};
+ else return {"bx ", regs[rm]};
+}
+
+string thumbMemReg(uint3 op, uint3 rd, uint3 rn, uint3 rm) {
+ return {thumbmemregops[op], " ", regs[rd], ", [", regs[rn], ", ", regs[rm], "]"};
+}
+
+string thumbMemImm(uint5 op, uint3 rd, uint3 rn, uint5 offset) {
+ unsigned rm = offset;
+ if(op < 14) rm *= 4;
+ if(op >= 16) rm *= 2;
+
+ return {thumbmemimmops[op-12], " ", regs[rd], ", [", regs[rn], ", #0x", hex<3>(rm), "]"};
+}
+
+string thumbAddSP(uint1 op, uint7 offset) {
+ return {op?"sub":"add", " sp, #0x", hex<3>(4*offset)};
+}
+
+string thumbRelative(uint5 op, uint3 rd, uint8 offset) {
+ if(op == 9) return {"ldr ", regs[rd], ", [pc, #0x", hex<3>(4*offset), "]"};
+ if(op ==18) return {"str ", regs[rd], ", [sp, #0x", hex<3>(4*offset), "]"};
+ if(op ==19) return {"ldr ", regs[rd], ", [sp, #0x", hex<3>(4*offset), "]"};
+ if(op ==20) return {"add ", regs[rd], ", pc, ", "#0x", hex<3>(4*offset)};
+ if(op ==21) return {"add ", regs[rd], ", sp, ", "#0x", hex<3>(4*offset)};
+}
+
+string thumbBlock(uint4 op, uint3 rn, uint8 rlist) {
+ bool l = op & 1;
+ string regnames = "";
+ for(unsigned b = 0; b < 8; b++) {
+ if(rlist & 1<(target)};
+}
+
+string thumbBranch(uint32 target) {
+ return {"b 0x", hex<8>(target)};
+}
+
+string thumbBh(int11 offset_hi) {
+ return {"bh 0x", hex<3>(2*offset_hi)};
+}
+
+string thumbBl(uint1 tbit, uint32 target) {
+ return {tbit? "bl":"blx", " 0x", hex<8>(target)};
+}
+
+string arm(ARMCore* arm, uint32 i) {
+ uint8 op = i>>20;
+ uint4 cc = i>>28;
+ uint4 rd = i>>12, rn = i>>16;
+ uint4 rm = i, rs = i>>8;
+ uint2 sh = i>>5;
+ uint32 pc = arm->r[15] & ~3;
+
+ if(match(i, "1111 0101u101/// ..../")) return armMem(15, op, rd, rn, armOffset12(i));
+ if(match(i, "1111 0111u101/// ...0/")) return armMem(15, op, rd, rn, armShiftImm(rm, sh, i>>7));
+ if(match(i, "1111 101l..../// ..../")) return armBranch(14, 0, 1, pc + 4*int24(i));
+ if(match(i, "1111 1100000l/// ..../")) return armUndefined(i);
+ if(match(i, "1111 1100010l/// ..../")) return armCop_v5(15, i>>8, op, rd, rn, rm, i>>4);
+ if(match(i, "1111 110punwl/// ..../")) return armMemCop(15, i>>8, op, rd, rn, i);
+ if(match(i, "1111 1110..../// ..../")) return armCop(15, i>>8, op, rd, rn, rm, i>>4);
+ if(match(i, "1111 ......../// ..../")) return armUndefined(i);
+
+ if(match(i, ".... 00110r10/// ..../")) return armWritePsr(cc, i>>22, rn, armImmed(i, rs));
+ if(match(i, ".... 00010r10/// 0000/")) return armWritePsr(cc, i>>22, rn, armRm(rm));
+ if(match(i, ".... 00010r00/// 0000/")) return armReadPsr (cc, i>>22, rd);
+ if(match(i, ".... 00010010/// 00l1/")) return armBranchEx(cc, sh, rm);
+ if(match(i, ".... 00010010/// 0111/")) return armBkpt (cc, i>>8, i);
+ if(match(i, ".... 00010110/// 0001/")) return armClz (cc, rd, rm);
+ if(match(i, ".... 00010ds0/// 0101/")) return armDspAdd (cc, i>>21, rd, rn, rm);
+ if(match(i, ".... 00010oo0/// 1yx0/")) return armDspMul (cc, i>>21, sh, rn, rd, rm, rs);
+
+ if(match(i, ".... 0000luas/// 1001/")) return armMultiply(cc, op, rn, rd, rm, rs);
+ if(match(i, ".... 00010b00/// 1001/")) return armMemSwap (cc, i>>22, rd, rn, rm);
+ if(match(i, ".... 0000ui1l/// 1sh1/")) return armUndefined(i);
+ if(match(i, ".... 000pu0w0/// 11s1/")) return armMem_v5 (cc, op, sh, rd, rn, armRm(i));
+ if(match(i, ".... 000pu0wl/// 1sh1/")) return armMem_v4 (cc, op, sh, rd, rn, armRm(i));
+ if(match(i, ".... 000pu1w0/// 11s1/")) return armMem_v5 (cc, op, sh, rd, rn, armOffset8(i, i>>8));
+ if(match(i, ".... 000pu1wl/// 1sh1/")) return armMem_v4 (cc, op, sh, rd, rn, armOffset8(i, i>>8));
+
+ if(match(i, ".... 000aaaas/// 0sh1/")) return armData (cc, op, rd, rn, armShiftReg(rm, sh, rs));
+ if(match(i, ".... 000aaaas/// .sh0/")) return armData (cc, op, rd, rn, armShiftImm(rm, sh, i>>7));
+ if(match(i, ".... 001aaaas/// ..../")) return armData (cc, op, rd, rn, armImmed(i, rs));
+ if(match(i, ".... 010pubwl/// ..../")) return armMem (cc, op, rd, rn, armOffset12(i));
+ if(match(i, ".... 011pubwl/// ...0/")) return armMem (cc, op, rd, rn, armShiftImm(rm, sh, i>>7));
+
+ if(match(i, ".... 100puswl/// ..../")) return armBlock(cc, op, rn, i);
+ if(match(i, ".... 101l..../// ..../")) return armBranch(cc, i>>24, 0, pc + 4*int24(i));
+ if(match(i, ".... 1100000l/// ..../")) return armUndefined(i);
+ if(match(i, ".... 1100010l/// ..../")) return armCop_v5(cc, i>>8, op, rd, rn, rm, i>>4);
+ if(match(i, ".... 110punwl/// ..../")) return armMemCop(cc, i>>8, op, rd, rn, i);
+ if(match(i, ".... 1110..../// ..../")) return armCop(cc, i>>8, op, rd, rn, rm, i>>4);
+ if(match(i, ".... 1111..../// ..../")) return armSwi(cc, i);
+
+ return armUndefined(i);
+}
+
+string thumb(ARMCore* arm, uint16 i) {
+ uint32 pc = arm->r[15] & ~1;
+
+ if(match(i, "00011ismmmnnnddd")) return thumbAddSub (i>>9, i, i>>3, i>>6);
+ if(match(i, "000ssiiiiimmmddd")) return thumbShiftImm(i>>11, i, i>>3, i>>6);
+ if(match(i, "001oodddiiiiiiii")) return thumbDataImm (i>>11, i>>8, i);
+ if(match(i, "010000oooommmddd")) return thumbDataLo (i>>6, i, i>>3);
+ if(match(i, "010001oodmmmmddd")) return thumbDataHi (i>>8, (i&7)+(i>>4&8), i>>3);
+
+ if(match(i, "0101ooommmnnnddd")) return thumbMemReg (i>>9, i, i>>3, i>>6);
+ if(match(i, "011bliiiiinnnddd")) return thumbMemImm (i>>11, i, i>>3, i>>6);
+ if(match(i, "1000liiiiinnnddd")) return thumbMemImm (i>>11, i, i>>3, i>>6);
+
+ if(match(i, "10111110........")) return thumbBkpt(i);
+ if(match(i, "10110000siiiiiii")) return thumbAddSP ( i>>7, i);
+ if(match(i, "01001dddrrrrrrrr")) return thumbRelative(i>>11, i>>8, i);
+ if(match(i, "1001odddrrrrrrrr")) return thumbRelative(i>>11, i>>8, i);
+ if(match(i, "1010odddrrrrrrrr")) return thumbRelative(i>>11, i>>8, i);
+
+ if(match(i, "11011110rrrrrrrr")) return thumbUndefined(i);
+ if(match(i, "11011111rrrrrrrr")) return thumbSwi(i);
+ if(match(i, "1101ccccrrrrrrrr")) return thumbCond ( i>>8, pc + 2*int8(i));
+ if(match(i, "11100rrrrrrrrrrr")) return thumbBranch (pc + 2*int11(i));
+ if(match(i, "11110rrrrrrrrrrr")) return thumbBh (i);
+ if(match(i, "11101rrrrrrrrrr1")) return thumbUndefined(i);
+ if(match(i, "111t1rrrrrrrrrrr")) return thumbBl (i>>12, arm->r[14] + 2*uint11(i));
+ if(match(i, "1o..lnnnrrrrrrrr")) return thumbBlock (i>>11, i>>8, i);
+
+ return thumbUndefined(i);
+}
+
+#undef collect
+#undef match
+}
diff --git a/bsnes/nds/cpu/dma.cpp b/bsnes/nds/cpu/dma.cpp
new file mode 100644
index 00000000..f69363ec
--- /dev/null
+++ b/bsnes/nds/cpu/dma.cpp
@@ -0,0 +1,131 @@
+
+bool CPUCore::dmaTrigger(unsigned channels, unsigned value) {
+ for(unsigned no = 0; no < 4; no++) {
+ if((channels & 1<dma[no];
+
+ uint32 size = dma.size? Word : Half;
+ uint32 srcmask = config.arm7 && no == 0? 0x07fffffe : 0x0ffffffe;
+ uint32 destmask = config.arm7 && no < 3? 0x07fffffe : 0x0ffffffe;
+ uint32 countmask = 0x1fffff;
+
+ if(config.arm7)
+ countmask = no < 3? 0x3fff : 0xffff;
+
+ int srcinc = (dma.srcStep == 1? -2 : dma.srcStep != 2? +2 : 0);
+ int destinc = (dma.destStep == 1? -2 : dma.destStep != 2? +2 : 0);
+
+ if(size == Word)
+ srcinc <<= 1, destinc <<= 1;
+
+ do {
+ uint32 data = read(dma.source, size, true);
+ write(dma.dest, size, true, data);
+
+ dma.source = (dma.source + srcinc) & srcmask;
+ dma.dest = (dma.dest + destinc) & destmask;
+ } while(--dma.count & countmask);
+
+ if(dma.destStep == 3) dma.dest = dma.init.dest;
+ if(dma.repeat == 1) dma.count = dma.init.count;
+ if(dma.repeat == 0) dma.enable = false;
+
+ if(dma.irq) interrupt.flags |= irqDma << no;
+}
+
+
+uint32 CPUCore::regDmaControl(unsigned no) {
+ return dma[no].init.count<<0 | dma[no].destStep<<21 | dma[no].srcStep<<23
+ | dma[no].repeat<<25 | dma[no].size<<26 | dma[no].trigger<<27
+ | dma[no].irq<<30 | dma[no].enable<<31;
+}
+
+uint32 CPUCore::regDmaSource(unsigned no) {
+ return dma[no].init.source;
+}
+
+uint32 CPUCore::regDmaDest(unsigned no) {
+ return dma[no].init.dest;
+}
+
+uint32 CPUCore::regDmaFill(unsigned no) {
+ return dma[no].fill;
+}
+
+void CPUCore::regDmaControl(unsigned no, uint32 data, uint32 mask) {
+ auto &dma = this->dma[no];
+
+ uint32 countmask = 0x1fffff;
+ if(config.arm7) // still limited to 16K / 64K transfers
+ countmask = no < 3? 0x3fff : 0xffff;
+
+ if(mask & countmask) {
+ dma.init.count ^= (dma.init.count ^ data) & countmask;
+ }
+ if(mask & 0xffe00000) { // ??
+ bool previously = dma.enable;
+
+ dma.destStep = data>>21;
+ dma.srcStep = data>>23;
+ dma.repeat = data>>25;
+ dma.size = data>>26;
+ dma.trigger = data>>27;
+ dma.irq = data>>30;
+ dma.enable = data>>31;
+
+ if(config.arm7)
+ dma.trigger >>= 1;
+
+ if(dma.enable) {
+ if(previously == false) {
+ // Latch new settings
+ dma.source = dma.init.source;
+ dma.dest = dma.init.dest;
+ dma.count = dma.init.count;
+ }
+ if(dma.trigger == 0) {
+ dmaTransfer(no);
+ }
+ else if(dma.trigger == 7) {
+ // Geometry fifo - DMA display list
+ // - just do it right here since we lack timing
+ dmaTransfer(no);
+ }
+ //else {
+ // print(config.arm7?"arm7":"arm9",
+ // ": dma trigger ",dma.trigger,": unimplemented\n");
+ //}
+ }
+ }
+}
+
+void CPUCore::regDmaSource(unsigned no, uint32 data, uint32 mask) {
+ mask &= 0x0ffffffe;
+ if(config.arm7 && no == 0)
+ mask &= 0x07fffffe; // DMA0 is internal only
+
+ dma[no].init.source ^= (dma[no].init.source ^ data) & mask;
+}
+
+void CPUCore::regDmaDest(unsigned no, uint32 data, uint32 mask) {
+ mask &= 0x0ffffffe;
+ if(config.arm7 && no != 3)
+ mask &= 0x07fffffe; // only DMA3 can write to slot 2
+
+ dma[no].init.dest ^= (dma[no].init.dest ^ data) & mask;
+}
+
+void CPUCore::regDmaFill(unsigned no, uint32 data, uint32 mask) {
+ if(config.arm7)
+ return; // not present
+
+ dma[no].fill ^= (dma[no].fill ^ data) & mask;
+}
diff --git a/bsnes/nds/cpu/math.cpp b/bsnes/nds/cpu/math.cpp
new file mode 100644
index 00000000..f7ec1bd4
--- /dev/null
+++ b/bsnes/nds/cpu/math.cpp
@@ -0,0 +1,115 @@
+
+void ARM946ES::regDivideControl(uint32 data, uint32 mask) {
+ if(mask & 3) divMode = data;
+ startDivide();
+}
+
+void ARM946ES::regNumerator(unsigned index, uint32 data, uint32 mask) {
+ int64 update = data & mask; update <<= 32*index;
+ int64 umask = mask; umask <<= 32*index;
+
+ numerator ^= (numerator ^ update) & umask;
+ startDivide();
+}
+
+void ARM946ES::regDenominator(unsigned index, uint32 data, uint32 mask) {
+ int64 update = data & mask; update <<= 32*index;
+ int64 umask = mask; umask <<= 32*index;
+
+ denominator ^= (denominator ^ update) & umask;
+ startDivide();
+}
+
+
+
+void ARM946ES::regSquareRootControl(uint32 data, uint32 mask) {
+ if(mask & 1) rootMode = data;
+ startSquareRoot();
+}
+
+void ARM946ES::regSquare(unsigned index, uint32 data, uint32 mask) {
+ int64 update = data & mask; update <<= 32*index;
+ int64 umask = mask; umask <<= 32*index;
+
+ square ^= (square ^ update) & umask;
+ startSquareRoot();
+}
+
+
+
+uint32 ARM946ES::regDivideControl() {
+ return divMode<<0 | divByZero<<13 | divBusy<<15;
+}
+
+uint32 ARM946ES::regNumerator(unsigned index) {
+ return numerator >> 32*index;
+}
+
+uint32 ARM946ES::regDenominator(unsigned index) {
+ return denominator >> 32*index;
+}
+
+uint32 ARM946ES::regQuotient(unsigned index) {
+ return quotient >> 32*index;
+}
+
+uint32 ARM946ES::regRemainder(unsigned index) {
+ return remainder >> 32*index;
+}
+
+
+
+uint32 ARM946ES::regSquareRootControl() {
+ return rootMode<<0 | rootBusy<<15;
+}
+
+uint32 ARM946ES::regSquare(unsigned index) {
+ return square >> 32*index;
+}
+
+uint32 ARM946ES::regSquareRoot() {
+ return squareRoot;
+}
+
+
+
+void ARM946ES::startDivide() {
+ divByZero = false;
+
+ int64 n = numerator, d = denominator;
+
+ if(divMode == div32) { n &= 0xffffffffll; n -= 2*(n & 1ll<<31); }
+ if(divMode != div64) { d &= 0xffffffffll; d -= 2*(d & 1ll<<31); }
+
+ // Ugh, GBATEK does not say at all how remainder works with signed values.
+ // Will have to fix this later..
+ if(d == 0) {
+ divByZero = true;
+ quotient = n >= 0? -1 : +1;
+ remainder = n;
+ }
+ else if(n == (-1ll<<63) && d == -1ll) {
+ quotient = -1ll<<63;
+ }
+ else {
+ quotient = n / d;
+ remainder = n % d;
+ }
+}
+
+
+
+void ARM946ES::startSquareRoot() {
+ uint64 x = square, r = 0;
+ if(rootMode == sqrt32)
+ x = uint32(x);
+
+ for(uint64 bit = 1ull << 62; bit != 0; bit >>= 2) {
+ r >>= 1;
+ if(x >= 2*r + bit) {
+ x -= 2*r + bit;
+ r += bit;
+ }
+ }
+ squareRoot = r;
+}
diff --git a/bsnes/nds/cpu/message.cpp b/bsnes/nds/cpu/message.cpp
new file mode 100644
index 00000000..16f7c554
--- /dev/null
+++ b/bsnes/nds/cpu/message.cpp
@@ -0,0 +1,98 @@
+
+void CPUCore::popMsg() {
+ msg.full = false;
+ if(++msg.readOffset == msg.writeOffset)
+ msg.empty = true;
+}
+
+void CPUCore::pushMsg(uint32 data) {
+ msg.buffer[msg.writeOffset] = data;
+ msg.empty = false;
+ if(++msg.writeOffset == msg.readOffset)
+ msg.full = true;
+}
+
+void CPUCore::clearMsg() {
+ msg.readOffset = 0;
+ msg.writeOffset = 0;
+ msg.empty = true;
+ msg.full = false;
+ for(unsigned n = 0; n < 16; n++)
+ msg.buffer[n] = 0;
+}
+
+uint32 CPUCore::regMsgControl() {
+ return msg.enable<<15 | msg.error<<14
+ | msg.irqOnRecv<<10 | other->msg.full<<9 | other->msg.empty<<8
+ | msg.irqOnSent<<2 | this->msg.full<<1 | this->msg.empty<<0;
+}
+
+void CPUCore::regMsgControl(uint32 data, uint32 mask) {
+ if(mask & 0x00ff) {
+ bool previously = msg.irqOnSent;
+
+ msg.irqOnSent = data>>2;
+ if(data & 1<<3) clearMsg();
+
+ // Edge triggered
+ if(msg.empty && msg.irqOnSent && previously == false) {
+ interrupt.flags |= irqMsgSent;
+ }
+ }
+ if(mask & 0xff00) {
+ bool previously = msg.irqOnRecv;
+
+ msg.irqOnRecv = data>>10;
+ msg.enable = data>>15;
+ if(data & 1<<14) msg.error = false;
+
+ // Edge triggered
+ if(!other->msg.empty && msg.irqOnRecv && previously == false)
+ interrupt.flags |= irqMsgRecv;
+ }
+}
+
+void CPUCore::regMsgSend(uint32 data) {
+ if(msg.enable) {
+ if(msg.full) {
+ msg.error = true;
+ return;
+ }
+ bool wasEmpty = msg.empty;
+ pushMsg(data);
+
+ if(wasEmpty && other->msg.irqOnRecv)
+ other->interrupt.flags |= irqMsgRecv;
+ }
+}
+
+uint32 CPUCore::regMsgRecv() {
+ uint32 data = other->msg.buffer[other->msg.readOffset];
+
+ if(other->msg.enable) {
+ if(other->msg.empty) {
+ msg.error = true;
+ return data;
+ }
+ other->popMsg();
+
+ if(other->msg.empty && other->msg.irqOnSent)
+ other->interrupt.flags |= irqMsgSent;
+ }
+ return data;
+}
+
+uint32 CPUCore::regSync() {
+ return sync.enable<<14 | this->sync.output<<8 | other->sync.output<<0;
+}
+
+void CPUCore::regSync(uint32 data, uint32 mask) {
+ if(mask & 0xff00) {
+ sync.enable = data>>14;
+ sync.output = data>>8;
+ if(data & 1<<13) {
+ if(other->sync.enable)
+ other->interrupt.flags |= irqSync;
+ }
+ }
+}
diff --git a/bsnes/nds/cpu/slot.cpp b/bsnes/nds/cpu/slot.cpp
new file mode 100644
index 00000000..ebd7c600
--- /dev/null
+++ b/bsnes/nds/cpu/slot.cpp
@@ -0,0 +1,131 @@
+
+uint32 CPUCore::regSlot1Control() {
+ return slot1.spi.baud<<0 | slot1.spi.hold<<6
+ | slot1.spi.busy<<7 | slot1.spi.enable<<13
+ | slot1.transferIrq<<14 | slot1.enable<<15
+ | slot1.spi.data<<16;
+}
+
+uint32 CPUCore::regSlot1RomControl() {
+ return slot1.decryptLatency<<0 | slot1.xorData<<13
+ | slot1.responseLatency<<16 | slot1.xorCmds<<22
+ | slot1.dataReady<<23 | slot1.blockSize<<24
+ | slot1.clock<<27 | slot1.secureMode<<28
+ | 1<<29 | slot1.transferPending<<31;
+}
+
+uint32 CPUCore::regSlot1RomCommand(unsigned index) {
+ auto cmd = slot1.command;
+ if(index == 0) cmd >>= 32;
+
+ return (cmd>>24 & 0xff) << 0
+ | (cmd>>16 & 0xff) << 8
+ | (cmd>> 8 & 0xff) << 16
+ | (cmd>> 0 & 0xff) << 24;
+}
+
+uint32 CPUCore::regSlot1RomRecv() {
+ uint32 data = 0;
+ data += slot1.readRom() << 0;
+ data += slot1.readRom() << 8;
+ data += slot1.readRom() << 16;
+ data += slot1.readRom() << 24;
+ return data;
+}
+
+void CPUCore::regSlot1Control(uint32 data, uint32 mask) {
+ if(mask & 0x000000ff) {
+ slot1.spi.baud = data>>0;
+ slot1.spi.hold = data>>6;
+ }
+ if(mask & 0x0000ff00) {
+ slot1.spi.enable = data>>13;
+ slot1.transferIrq = data>>14;
+ slot1.enable = data>>15;
+
+ if(slot1.enable == false || slot1.spi.enable == false) {
+ if(slot1.card && slot1.card->spi) {
+ //print("slot1 spi: deselect\n");
+ slot1.card->spi->select(false);
+ }
+ }
+ }
+ if(mask & 0x00ff0000) {
+ // SPI transfer
+ if(!slot1.spi.enable) return;
+ slot1.spi.data = slot1.spiTransfer(data>>16);
+ //print("slot1 spi: w ",hex<2>(data>>16)," r ",hex<2>(slot1.spi.data),"\n");
+ }
+}
+
+void CPUCore::regSlot1RomControl(uint32 data, uint32 mask) {
+ if(mask & 0x00001fff) {
+ slot1.decryptLatency ^= (slot1.decryptLatency ^ data) & mask;
+ }
+ if(mask & 0x0000e000) {
+ slot1.xorData = data>>13;
+ if(data & 1<<15) {
+ slot1.lfsr[0] = config.xorSeeds[0];
+ slot1.lfsr[1] = config.xorSeeds[1];
+ }
+ }
+ if(mask & 0x00ff0000) {
+ slot1.responseLatency = data>>16;
+ slot1.xorCmds = data>>22;
+ }
+ if(mask & 0xff000000) {
+ slot1.blockSize = data>>24;
+ slot1.clock = data>>27;
+ slot1.secureMode = data>>28;
+ if(data & 1<<31)
+ slot1.startRomTransfer();
+ }
+}
+
+void CPUCore::regSlot1RomCommand(unsigned index, uint32 data, uint32 mask) {
+ auto &cmd = slot1.command;
+ uint64 ldata = data;
+
+ // Big endian commands, argh!
+ if(index == 0) {
+ if(mask & 0x000000ff) cmd ^= (cmd ^ ldata<<56) & 0xff00000000000000;
+ if(mask & 0x0000ff00) cmd ^= (cmd ^ ldata<<40) & 0x00ff000000000000;
+ if(mask & 0x00ff0000) cmd ^= (cmd ^ ldata<<24) & 0x0000ff0000000000;
+ if(mask & 0xff000000) cmd ^= (cmd ^ ldata<< 8) & 0x000000ff00000000;
+ } else {
+ if(mask & 0x000000ff) cmd ^= (cmd ^ ldata<<24) & 0x00000000ff000000;
+ if(mask & 0x0000ff00) cmd ^= (cmd ^ ldata<< 8) & 0x0000000000ff0000;
+ if(mask & 0x00ff0000) cmd ^= (cmd ^ ldata>> 8) & 0x000000000000ff00;
+ if(mask & 0xff000000) cmd ^= (cmd ^ ldata>>24) & 0x00000000000000ff;
+ }
+}
+
+void CPUCore::regSlot1RomSeed(unsigned index, uint32 data, uint32 mask) {
+ if(index == 2) {
+ data &= 0x7f007f & mask;
+ if(mask & 0x00007f) config.xorSeeds[0] = (config.xorSeeds[0] & 0xffffffff) | uint64(data>>0 )<<32;
+ if(mask & 0x7f0000) config.xorSeeds[1] = (config.xorSeeds[1] & 0xffffffff) | uint64(data>>16)<<32;
+ }
+ else {
+ config.xorSeeds[index] ^= (config.xorSeeds[index] ^ data) & mask;
+ }
+}
+
+
+
+uint32 CPUCore::regSlot2Control() {
+ return config.slot2ramTiming<<0 | config.slot2romTiming0<<2
+ | config.slot2romTiming1<<4 | config.slot2phi<<5
+ | !arm9.slot2access<<7 | !arm9.slot1access<<11
+ | 1<<13 | 1<<14 | !arm9.ramPriority<<15;
+}
+
+void CPUCore::regSlot2Control(uint32 data, uint32 mask) {
+ if(mask & 0xff) {
+ config.slot2ramTiming = data>>0;
+ config.slot2romTiming0 = data>>2;
+ config.slot2romTiming1 = data>>4;
+ config.slot2phi = data>>5;
+ }
+}
+
diff --git a/bsnes/nds/cpu/thumb.cpp b/bsnes/nds/cpu/thumb.cpp
new file mode 100644
index 00000000..50ec31ce
--- /dev/null
+++ b/bsnes/nds/cpu/thumb.cpp
@@ -0,0 +1,150 @@
+
+void ARMCore::thumbShiftImm(uint2 opcode, uint3 ird, uint3 irm, uint5 rs) {
+ auto &rd = r[ird];
+ r[15] += 2;
+
+ SOut r = shiftImm(irm, opcode, rs);
+ bitf(true, rd = r, r); // lsl, lsr, asr
+}
+
+void ARMCore::thumbAddSub(uint2 opcode, uint3 ird, uint3 irn, uint3 irm) {
+ auto& rd = r[ird], rn = r[irn], rm = opcode & 2? (uint32)irm : r[irm];
+ r[15] += 2;
+
+ if(opcode & 1) sumf(true, rd = rn-rm, rn, ~rm); // subs
+ else sumf(true, rd = rn+rm, rn, rm); // adds
+}
+
+void ARMCore::thumbDataImm(uint2 opcode, uint3 ird, uint8 rm) {
+ auto &rd = r[ird], rn = rd;
+ r[15] += 2;
+
+ if(opcode == 0) bitf(true, rd = rm, {rm, Cf}); // movs
+ if(opcode == 1) sumf(true, rn-rm, rn, ~rm); // cmps
+ if(opcode == 2) sumf(true, rd = rn+rm, rn, rm); // adds
+ if(opcode == 3) sumf(true, rd = rn-rm, rn, ~rm); // subs
+}
+
+void ARMCore::thumbDataLo(uint4 opcode, uint3 ird, uint3 irm) {
+ auto &rd = r[ird], rm = r[irm];
+ r[15] += 2;
+
+ if(opcode == 2) { SOut r = lsl(rd, rm); bitf(true, rd = r, r); } // lsls
+ else if(opcode == 3) { SOut r = lsr(rd, rm); bitf(true, rd = r, r); } // lsrs
+ else if(opcode == 4) { SOut r = asr(rd, rm); bitf(true, rd = r, r); } // asrs
+ else if(opcode == 7) { SOut r = ror(rd, rm); bitf(true, rd = r, r); } // rors
+ else if(opcode == 9) sumf(true, rd = -rm, 0, ~rm); // negs
+ else if(opcode == 13) bitf(true, rd = rm * rd, {rm*rd, Cf}); // muls
+ else alu(2*opcode+1, rd, rd, {rm,Cf}); // others are same as ARM
+}
+
+void ARMCore::thumbDataHi(uint2 opcode, uint4 ird, uint4 irm) {
+ auto &rd = r[ird], rn = rd, rm = r[irm];
+ r[15] += 2;
+
+ if(opcode == 0) rd = rn + rm; // add
+ if(opcode == 1) sumf(true, rn-rm, rn, ~rm); // cmps
+ if(opcode == 2) rd = rm; // mov
+ if(opcode == 3) { // bx, blx
+ if(ird & 8) r[14] = r[15] - 4 + 1;
+ return branch(rm & 1, rm);
+ }
+ if(ird == 15) branch(1, r[15]);
+}
+
+void ARMCore::thumbMemImm(uint5 opcode, uint3 ird, uint3 irn, uint5 rm) {
+ auto &rd = r[ird], addr = r[irn];
+ r[15] += 2;
+
+ if(opcode == 13) rd = load(addr + 4*rm, Word); // ldr
+ if(opcode == 15) rd = load(addr + 1*rm, Byte); // ldrb
+ if(opcode == 17) rd = load(addr + 2*rm, Half); // ldrh
+ if(opcode == 12) store(addr + 4*rm, Word, rd); // str
+ if(opcode == 14) store(addr + 1*rm, Byte, rd); // strb
+ if(opcode == 16) store(addr + 2*rm, Half, rd); // strh
+}
+
+void ARMCore::thumbMemReg(uint3 opcode, uint3 ird, uint3 irn, uint3 irm) {
+ bool ld = opcode & 1;
+ auto &rd = r[ird], addr = r[irn] + r[irm];
+ r[15] += 2;
+
+ if(opcode == 0) store(addr, Word, rd); // str
+ if(opcode == 1) store(addr, Half, rd); // strh
+ if(opcode == 2) store(addr, Byte, rd); // strb
+ if(opcode == 4) rd = load(addr, Word); // ldr
+ if(opcode == 5) rd = load(addr, Half); // ldrh
+ if(opcode == 6) rd = load(addr, Byte); // ldrb
+ if(opcode == 7) rd = (int16) load(addr, Half); // ldrsh
+ if(opcode == 3) rd = (int8) load(addr, Byte); // ldrsb
+}
+
+void ARMCore::thumbRelative(uint5 opcode, uint3 ird, uint8 rm) {
+ auto &rd = r[ird], pc = r[15] & ~3;
+ r[15] += 2;
+
+ if(opcode == 9) rd = load(pc + 4*rm, Word); // ldr [pc,#n]
+ if(opcode ==18) store(r[13] + 4*rm, Word, rd); // str [sp,#n]
+ if(opcode ==19) rd = load(r[13] + 4*rm, Word); // ldr [sp,#n]
+ if(opcode ==20) rd = pc + 4*rm; // adr rd,pc,..
+ if(opcode ==21) rd = r[13] + 4*rm; // adr rd,sp,..
+}
+
+void ARMCore::thumbAddSP(uint1 opcode, uint7 rm) {
+ r[15] += 2;
+ if(opcode == 0) r[13] += 4*rm; // add sp,#n
+ if(opcode == 1) r[13] -= 4*rm; // sub sp,#n
+}
+
+void ARMCore::thumbBlock(uint4 opcode, uint3 irn, uint8 rlist) {
+ auto &rn = opcode < 8? r[13] : r[irn];
+ bool ld = opcode & 1;
+ bool up = true;
+ bool writeback = true;
+ uint32 regs = rlist;
+
+ if(opcode < 8) {
+ up = ld;
+ if(irn & 1) regs |= (1 << 14+ld);
+ }
+
+ uint32 addr = rn, base = rn, size = 4*bit::count(regs);
+ if(!up) addr -= size;
+ r[15] += 2;
+
+ for(unsigned b = 0, s = 0; b < 16; b++) {
+ if(~regs & 1<timer[no];
+
+ if(timer.cascade == false)
+ updateTimer(no);
+
+ return timer.count<<0 | timer.divider<<16
+ | timer.cascade<<18 | timer.irq<<22 | timer.enable<<23;
+}
+
+void CPUCore::regTimer(unsigned no, uint32 data, uint32 mask) {
+ auto &timer = this->timer[no];
+
+ if(timer.cascade == false)
+ updateTimer(no);
+
+ event.queue.remove(timer.event);
+
+ if(mask & 0x00ffff) {
+ timer.reload ^= (timer.reload ^ data) & mask;
+ }
+ if(mask & 0xff0000) {
+ if(!timer.enable && (data & 1<<23)) {
+ timer.count = timer.reload;
+ }
+ timer.divider = data>>16;
+ timer.cascade = data>>18;
+ timer.irq = data>>22;
+ timer.enable = data>>23;
+ }
+
+ if(timer.cascade == false)
+ updateTimer(no);
+}
+
+void CPUCore::updateTimer(unsigned no) {
+ auto &timer = this->timer[no];
+
+ if(timer.enable) {
+ uint16 old = timer.count;
+ uint32 ticks = 1;
+
+ unsigned dbits[] = { 1, 7, 9, 11 }; // 33MHz, 512KHz, 128KHz, 32KHz
+ unsigned s = dbits[timer.divider];
+ uint32 divider = 1 << s;
+
+ if(timer.cascade) {
+ timer.count++;
+ } else {
+ ticks = (event.queue.time >> s) - (timer.lastUpdate >> s);
+ timer.count += ticks;
+ }
+
+ if(ticks && timer.count <= old) {
+ if(timer.irq) interrupt.flags |= irqTimer << no;
+
+ timer.count = timer.reload;
+
+ if(no < 3 && this->timer[no+1].cascade)
+ updateTimer(no+1);
+ }
+
+ if(timer.cascade == false) {
+ uint32 ticksLeft = 0x10000 - timer.count;
+ uint32 nextTick = divider;// - (event.queue.time & divider-1);
+ uint32 nextOverflow = nextTick + divider * (ticksLeft-1);
+
+ // The above commented part breaks maxmod's interpolated audio
+ // - perhaps the internal counters have expanded?
+ if(event.queue.time & 1)
+ nextTick -= 1; // align to 33MHz clock however
+
+ event.queue.add(nextOverflow, timer.event);
+ }
+ }
+ timer.lastUpdate = event.queue.time;
+}
diff --git a/bsnes/nds/gpu/commands.cpp b/bsnes/nds/gpu/commands.cpp
new file mode 100644
index 00000000..530c47e9
--- /dev/null
+++ b/bsnes/nds/gpu/commands.cpp
@@ -0,0 +1,527 @@
+
+bool GPU::gxMatrixMode() {
+ if(numArgs < 1) return false;
+
+ matrixMode = args[0];
+ return true;
+}
+
+bool GPU::gxMatrixPush() {
+ if(matrixMode == mmTexture) {
+ return true;
+ }
+ if(matrixMode == mmProjection) {
+ projStack[0] = projMatrix;
+ if(projSP++ == 1) { stackOverflow = true; }
+ return true;
+ }
+ // mmModelView or mmLitView
+ lightStack[viewSP % 32] = lightMatrix;
+ viewStack[viewSP % 32] = viewMatrix;
+
+ if(viewSP++ >= 31) { stackOverflow = true; }
+ return true;
+}
+
+bool GPU::gxMatrixPop() {
+ if(numArgs < 1) return false;
+
+ if(matrixMode == mmTexture) {
+ return true;
+ }
+ if(matrixMode == mmProjection) {
+ if(projSP-- == 0) { stackOverflow = true; }
+ projMatrix = projStack[0];
+ return true;
+ }
+ // mmModelView or mmLitView
+ args[0] %= 64;
+ viewSP -= args[0];
+ if(viewSP >= 31) { stackOverflow = true; }
+
+ lightMatrix = lightStack[viewSP % 32];
+ viewMatrix = viewStack[viewSP % 32];
+ return true;
+}
+
+bool GPU::gxMatrixStore() {
+ if(numArgs < 1) return false;
+
+ if(matrixMode == mmTexture) {
+ return true;
+ }
+ if(matrixMode == mmProjection) {
+ projStack[0] = projMatrix;
+ return true;
+ }
+ // mmModelView or mmLitView
+ args[0] %= 32;
+ if(args[0] == 31) { stackOverflow = true; }
+
+ lightStack[args[0]] = lightMatrix;
+ viewStack[args[0]] = viewMatrix;
+ return true;
+}
+
+bool GPU::gxMatrixRestore() {
+ if(numArgs < 1) return false;
+
+ if(matrixMode == mmTexture) {
+ return true;
+ }
+ if(matrixMode == mmProjection) {
+ projMatrix = projStack[0];
+ clipMatrix = projMatrix;
+ transform(clipMatrix, viewMatrix);
+ return true;
+ }
+ // mmModelView or mmLitView
+ args[0] %= 32;
+ if(args[0] == 31) { stackOverflow = true; }
+
+ lightMatrix = lightStack[args[0]];
+ viewMatrix = viewStack[args[0]];
+ clipMatrix = projMatrix;
+ transform(clipMatrix, viewMatrix);
+ return true;
+}
+
+bool GPU::gxMatrixLoadIdentity() {
+ loadMatrix({ 0x1000, 0, 0, 0,
+ 0, 0x1000, 0, 0,
+ 0, 0, 0x1000, 0,
+ 0, 0, 0, 0x1000 });
+ return true;
+}
+
+// Storage is transposed to make each row contiguous, which is opposite
+// of OpenGL. This allows easy multiplication with column vectors.
+
+bool GPU::gxMatrixLoad4x4() {
+ if(numArgs < 16) return false;
+
+ loadMatrix({ args[ 0], args[ 4], args[ 8], args[12],
+ args[ 1], args[ 5], args[ 9], args[13],
+ args[ 2], args[ 6], args[10], args[14],
+ args[ 3], args[ 7], args[11], args[15] });
+ return true;
+}
+
+bool GPU::gxMatrixLoad4x3() {
+ if(numArgs < 12) return false;
+
+ loadMatrix({ args[ 0], args[ 3], args[ 6], args[ 9],
+ args[ 1], args[ 4], args[ 7], args[10],
+ args[ 2], args[ 5], args[ 8], args[11],
+ 0, 0, 0, 0x1000 });
+ return true;
+}
+
+bool GPU::gxMatrixMult4x4() {
+ if(numArgs < 16) return false;
+
+ multMatrix({ args[ 0], args[ 4], args[ 8], args[12],
+ args[ 1], args[ 5], args[ 9], args[13],
+ args[ 2], args[ 6], args[10], args[14],
+ args[ 3], args[ 7], args[11], args[15] });
+ return true;
+}
+
+bool GPU::gxMatrixMult4x3() {
+ if(numArgs < 12) return false;
+
+ multMatrix({ args[ 0], args[ 3], args[ 6], args[ 9],
+ args[ 1], args[ 4], args[ 7], args[10],
+ args[ 2], args[ 5], args[ 8], args[11],
+ 0, 0, 0, 0x1000 });
+ return true;
+}
+
+bool GPU::gxMatrixRotate() {
+ if(numArgs < 9) return false;
+
+ multMatrix({ args[0], args[3], args[6], 0,
+ args[1], args[4], args[7], 0,
+ args[2], args[5], args[8], 0,
+ 0, 0, 0, 0x1000 });
+ return true;
+}
+
+bool GPU::gxMatrixScale() {
+ if(numArgs < 3) return false;
+
+ // Don't scale the lighting matrix
+ unsigned prevMode = matrixMode;
+ if(matrixMode == mmLitView)
+ matrixMode = mmModelView;
+
+ multMatrix({ args[0], 0, 0, 0,
+ 0, args[1], 0, 0,
+ 0, 0, args[2], 0,
+ 0, 0, 0, 0x1000 });
+ matrixMode = prevMode;
+ return true;
+}
+
+bool GPU::gxMatrixTranslate() {
+ if(numArgs < 3) return false;
+
+ multMatrix({ 0x1000, 0, 0, args[0],
+ 0, 0x1000, 0, args[1],
+ 0, 0, 0x1000, args[2],
+ 0, 0, 0, 0x1000 });
+ return true;
+}
+
+
+
+void GPU::unpackColor(int32* color, uint16 rgb) {
+ // Yes, it's really this crazy. PPU and GPU colors do NOT match!
+ // Super annoying when trying to hide things or make them seamless.
+ int r = 2*(rgb>> 0 & 31); r += (r>0);
+ int g = 2*(rgb>> 5 & 31); g += (g>0);
+ int b = 2*(rgb>>10 & 31); b += (b>0);
+
+ color[0] = 0x1000*r;
+ color[1] = 0x1000*g;
+ color[2] = 0x1000*b;
+}
+
+bool GPU::gxColor() {
+ if(numArgs < 1) return false;
+
+ unpackColor(vertex.color, args[0]);
+ return true;
+}
+
+bool GPU::gxNormal() {
+ if(numArgs < 1) return false;
+
+ // Normalize to +/- 1 range
+ normal[0] = int10(args[0]>> 0) << 3;
+ normal[1] = int10(args[0]>>10) << 3;
+ normal[2] = int10(args[0]>>20) << 3;
+ normal[3] = 0;
+
+ if(primitive.texTransform == PS::ttNormal) {
+ // Used for environment mapping.
+ textureMatrix(0,3) = vertex.texCoord[0];
+ textureMatrix(1,3) = vertex.texCoord[1];
+
+ vertex.texCoord[0] = normal[0];
+ vertex.texCoord[1] = normal[1];
+ vertex.texCoord[2] = normal[2];
+ vertex.texCoord[3] = 0x1000;
+
+ transform(textureMatrix, vertex.texCoord);
+ }
+
+ transform(lightMatrix, normal);
+
+ vertex.color = emission;
+
+ for(auto& light : lights) {
+ if(light.enable == false)
+ continue;
+
+ int32 dl = max(0, -dot(light.eyeVector, normal));
+ int32 sl = max(0, -dot(light.halfVector, normal));
+
+ sl = min(0xfff, sl*sl / 0x1000);
+ if(useShineTable)
+ sl = shininess[sl>>5] << 4;
+
+ for(unsigned n = 0; n < 3; n++) {
+ vertex.color[n] += (int64) specular[n] * light.color[n] * sl / 0x8000000;
+ vertex.color[n] += (int64) diffuse[n] * light.color[n] * dl / 0x8000000;
+ vertex.color[n] += (int64) ambient[n] * light.color[n] * 0x200 / 0x8000000; // ??
+ }
+ }
+ return true;
+}
+
+bool GPU::gxTexCoord() {
+ if(numArgs < 1) return false;
+
+ vertex.texCoord[0] = 0x1000 * int16(args[0]>> 0);
+ vertex.texCoord[1] = 0x1000 * int16(args[0]>>16);
+ vertex.texCoord[2] = 0x1000;
+ vertex.texCoord[3] = 0x1000;
+
+ // Affine texture transformations
+ if(primitive.texTransform == PS::ttTexCoord)
+ transform(textureMatrix, vertex.texCoord);
+
+ //if(primitive.texTransform == PS::ttNormal || primitive.texTransform == PS::ttVertex) {
+ // // Plug in U,V for environment/vertex mapping
+ // textureMatrix(0,3) = vertex.texCoord[0];
+ // textureMatrix(1,3) = vertex.texCoord[1];
+ //}
+ return true;
+}
+
+bool GPU::gxVertex3i_16() {
+ if(numArgs < 2) return false;
+
+ // 4.12, +/- 16 range
+ vertex.position[0] = int16(args[0]>> 0);
+ vertex.position[1] = int16(args[0]>>16);
+ vertex.position[2] = int16(args[1]>> 0);
+ submitVertex();
+ return true;
+}
+
+bool GPU::gxVertex3i_10() {
+ if(numArgs < 1) return false;
+
+ // 4.6, +/- 16 range
+ vertex.position[0] = int10(args[0]>> 0) << 6;
+ vertex.position[1] = int10(args[0]>>10) << 6;
+ vertex.position[2] = int10(args[0]>>20) << 6;
+ submitVertex();
+ return true;
+}
+
+bool GPU::gxVertex2i_XY() {
+ if(numArgs < 1) return false;
+
+ // Use same Z as before
+ vertex.position[0] = int16(args[0]>> 0);
+ vertex.position[1] = int16(args[0]>>16);
+ submitVertex();
+ return true;
+}
+
+bool GPU::gxVertex2i_XZ() {
+ if(numArgs < 1) return false;
+
+ // Use same Y as before
+ vertex.position[0] = int16(args[0]>> 0);
+ vertex.position[2] = int16(args[0]>>16);
+ submitVertex();
+ return true;
+}
+
+bool GPU::gxVertex2i_YZ() {
+ if(numArgs < 1) return false;
+
+ // Use same X as before
+ vertex.position[1] = int16(args[0]>> 0);
+ vertex.position[2] = int16(args[0]>>16);
+ submitVertex();
+ return true;
+}
+
+bool GPU::gxVertex3i_Rel() {
+ if(numArgs < 1) return false;
+
+ // 0.10, previous vertex +/- 0.125 relative range
+ vertex.position[0] = int16(vertex.position[0] + int10(args[0]>> 0));
+ vertex.position[1] = int16(vertex.position[1] + int10(args[0]>>10));
+ vertex.position[2] = int16(vertex.position[2] + int10(args[0]>>20));
+ submitVertex();
+ return true;
+}
+
+
+
+bool GPU::gxAttribute() {
+ if(numArgs < 1) return false;
+
+ for(unsigned n = 0; n < 4; n++)
+ lights[n].enable = args[0] >> n;
+
+ attributes = args[0];
+ return true;
+}
+
+bool GPU::gxTexImage() {
+ if(numArgs < 1) return false;
+
+ texImage = args[0] & 0x3fffffff;
+ primitive.texTransform = args[0] >> 30;
+
+ //if(primitive.type == PS::tris || primitive.type == PS::quads)
+ // primitive.texImage = texImage;
+ return true;
+}
+
+bool GPU::gxTexPalette() {
+ if(numArgs < 1) return false;
+
+ texPalette = args[0] & 0x1fff;
+
+ //if(primitive.type == PS::tris || primitive.type == PS::quads)
+ // primitive.texPalette = texPalette;
+ return true;
+}
+
+
+
+bool GPU::gxLightDiffuseAmbient() {
+ if(numArgs < 1) return false;
+
+ unpackColor(diffuse, args[0] >> 0);
+ unpackColor(ambient, args[0] >> 16);
+
+ // This is meant to allow display lists to be ignorant of
+ // the lighting state (namely whether it's in use or not).
+ if(args[0] & 1<<15)
+ unpackColor(vertex.color, args[0]);
+ return true;
+}
+
+bool GPU::gxLightSpecularEmission() {
+ if(numArgs < 1) return false;
+
+ unpackColor(specular, args[0] >> 0);
+ unpackColor(emission, args[0] >> 16);
+
+ useShineTable = args[0] & 1<<15;
+ return true;
+}
+
+bool GPU::gxLightDirection() {
+ if(numArgs < 1) return false;
+
+ unsigned no = args[0] >> 30;
+ auto &light = lights[no];
+
+ light.direction[0] = int10(args[0] >> 0);
+ light.direction[1] = int10(args[0] >>10);
+ light.direction[2] = int10(args[0] >>20);
+ light.direction[3] = 0;
+
+ light.eyeVector = light.direction;
+ transform(lightMatrix, light.eyeVector);
+
+ light.halfVector[0] = (light.eyeVector[0] + 0)/2;
+ light.halfVector[1] = (light.eyeVector[1] + 0)/2;
+ light.halfVector[2] = (light.eyeVector[2] - 0x1000)/2;
+ light.halfVector[3] = 0;
+ return true;
+}
+
+bool GPU::gxLightColor() {
+ if(numArgs < 1) return false;
+
+ unsigned no = args[0] >> 30;
+
+ unpackColor(lights[no].color, args[0]);
+ return true;
+}
+
+bool GPU::gxLightShininess() {
+ if(numArgs < 32) return false;
+
+ for(unsigned n = 0; n < 128; n += 4) {
+ shininess[n+0] = args[n/4] >> 0;
+ shininess[n+1] = args[n/4] >> 8;
+ shininess[n+2] = args[n/4] >> 16;
+ shininess[n+3] = args[n/4] >> 24;
+ }
+ return true;
+}
+
+
+
+bool GPU::gxBeginPrimitive() {
+ if(numArgs < 1) return false;
+
+ if(uploadList->numPrims < 2048
+ && primitive.size >= (primitive.type==PS::quadStrip? 4 : 3))
+ uploadList->numPrims++; // terminate the preceding strip
+
+ primitive.type = args[0];
+ primitive.size = 0;
+ primitive.winding = 0;
+ primitive.attributes = attributes;
+ primitive.texImage = texImage;
+ primitive.texPalette = texPalette;
+ return true;
+}
+
+bool GPU::gxSwapBuffers() {
+ if(numArgs < 1) return false;
+
+ sceneFinished = true;
+ swapArgument = args[0];
+ return true;
+}
+
+bool GPU::gxViewport() {
+ if(numArgs < 1) return false;
+
+ viewport.x = (args[0]>> 0 & 0xff) + 0;
+ viewport.y = (args[0]>> 8 & 0xff) + 0;
+ viewport.w = (args[0]>>16 & 0xff) + 1 - viewport.x;
+ viewport.h = (args[0]>>24 & 0xff) + 1 - viewport.y;
+ return true;
+}
+
+
+
+bool GPU::gxCullTest() {
+ if(numArgs < 3) return false;
+
+ // Box range given as x, y, z, w, h, d
+ int16 a[6] = {
+ int16(args[0]>> 0), int16(args[0]>>16), int16(args[1]>> 0),
+ int16(args[1]>>16), int16(args[2]>> 0), int16(args[2]>>16),
+ };
+ // -> l, b, n, r, t, f
+ a[3] += a[0]; a[4] += a[1]; a[5] += a[2];
+
+ // Generate all 8 corners and outcodes
+ int32 out[8];
+ ClipSpaceVertex vertex[8] = { // X Y Z
+ {{ a[0], a[1], a[2], 0x1000 }}, // l,b,n
+ {{ a[0], a[1], a[5], 0x1000 }}, // l,b,f
+ {{ a[0], a[4], a[2], 0x1000 }}, // l,t,n
+ {{ a[0], a[4], a[5], 0x1000 }}, // l,t,f
+ {{ a[3], a[1], a[2], 0x1000 }}, // r,b,n
+ {{ a[3], a[1], a[5], 0x1000 }}, // r,b,f
+ {{ a[3], a[4], a[2], 0x1000 }}, // r,t,n
+ {{ a[3], a[4], a[5], 0x1000 }}, // r,t,f
+ };
+ for(unsigned n = 0; n < 8; n++) {
+ transform(clipMatrix, vertex[n].position);
+ out[n] = outcode(vertex[n]);
+ }
+
+ // Find out which sides of the box would be drawn
+ bool front = (out[0] & out[2] & out[4] & out[6]) == 0;
+ bool back = (out[1] & out[3] & out[5] & out[7]) == 0;
+ bool bottom = (out[0] & out[1] & out[4] & out[5]) == 0;
+ bool top = (out[2] & out[3] & out[6] & out[7]) == 0;
+ bool left = (out[0] & out[1] & out[2] & out[3]) == 0;
+ bool right = (out[4] & out[5] & out[6] & out[7]) == 0;
+
+ // True if at least one face was accepted
+ boxResult = front || back || bottom || top || left || right;
+ return true;
+}
+
+bool GPU::gxPositionTest() {
+ if(numArgs < 2) return false;
+
+ vertex.position[0] = int16(args[0]>> 0);
+ vertex.position[1] = int16(args[0]>>16);
+ vertex.position[2] = int16(args[1]>> 0);
+
+ vertexResult = vertex.position;
+ transform(clipMatrix, vertexResult);
+ return true;
+}
+
+bool GPU::gxDirectionTest() {
+ if(numArgs < 1) return false;
+
+ normalResult[0] = int10(args[0]>> 0) << 3;
+ normalResult[1] = int10(args[0]>>10) << 3;
+ normalResult[2] = int10(args[0]>>20) << 3;
+ normalResult[3] = 0;
+
+ transform(lightMatrix, normalResult);
+ return true;
+}
diff --git a/bsnes/nds/gpu/commands.hpp b/bsnes/nds/gpu/commands.hpp
new file mode 100644
index 00000000..032f0c12
--- /dev/null
+++ b/bsnes/nds/gpu/commands.hpp
@@ -0,0 +1,41 @@
+
+ bool gxMatrixMode();
+ bool gxMatrixPush();
+ bool gxMatrixPop();
+ bool gxMatrixStore();
+ bool gxMatrixRestore();
+ bool gxMatrixLoadIdentity();
+ bool gxMatrixLoad4x4();
+ bool gxMatrixLoad4x3();
+ bool gxMatrixMult4x4();
+ bool gxMatrixMult4x3();
+ bool gxMatrixRotate();
+ bool gxMatrixScale();
+ bool gxMatrixTranslate();
+
+ bool gxColor();
+ bool gxNormal();
+ bool gxTexCoord();
+ bool gxVertex3i_16();
+ bool gxVertex3i_10();
+ bool gxVertex2i_XY();
+ bool gxVertex2i_XZ();
+ bool gxVertex2i_YZ();
+ bool gxVertex3i_Rel();
+ bool gxAttribute();
+ bool gxTexImage();
+ bool gxTexPalette();
+
+ bool gxLightDiffuseAmbient();
+ bool gxLightSpecularEmission();
+ bool gxLightDirection();
+ bool gxLightColor();
+ bool gxLightShininess();
+
+ bool gxBeginPrimitive();
+ bool gxSwapBuffers();
+ bool gxViewport();
+
+ bool gxCullTest();
+ bool gxPositionTest();
+ bool gxDirectionTest();
diff --git a/bsnes/nds/gpu/geometry.cpp b/bsnes/nds/gpu/geometry.cpp
new file mode 100644
index 00000000..51a52f08
--- /dev/null
+++ b/bsnes/nds/gpu/geometry.cpp
@@ -0,0 +1,316 @@
+
+void GPU::submitVertex() {
+ if(primitive.texTransform == PS::ttVertex) {
+ textureMatrix(0,3) = vertex.texCoord[0];
+ textureMatrix(1,3) = vertex.texCoord[1];
+
+ vertex.texCoord[0] = vertex.position[0];
+ vertex.texCoord[1] = vertex.position[1];
+ vertex.texCoord[2] = vertex.position[2];
+ vertex.texCoord[3] = 0x1000;
+
+ transform(textureMatrix, vertex.texCoord);
+ }
+
+ auto &v = primitive.v;
+ auto input = vertex;
+
+ transform(clipMatrix, input.position);
+
+ switch(primitive.type) {
+ case PS::tris:
+ v[primitive.size] = input;
+
+ if(++primitive.size >= 3)
+ submitTri(v[0], v[1], v[2]);
+ break;
+
+ case PS::triStrip:
+ v[min(2, primitive.size)] = input;
+
+ if(++primitive.size >= 3) {
+ submitTriStrip(v[0], v[1], v[2]);
+ primitive.winding ^= 1;
+ v[0] = v[1];
+ v[1] = v[2];
+ }
+ break;
+
+ case PS::quads:
+ v[primitive.size] = input;
+
+ // Slightly different order than triangles and strips
+ if(++primitive.size >= 4)
+ submitQuad(v[0], v[1], v[2], v[3]);
+ break;
+
+ case PS::quadStrip:
+ if(primitive.size % 2) v[min(3, primitive.size)] = input;
+ else v[min(2, primitive.size)] = input;
+
+ if(++primitive.size >= 4) {
+ if(primitive.size % 2 == 0) {
+ submitQuadStrip(v[0], v[1], v[2], v[3]);
+ v[0] = v[2];
+ v[1] = v[3];
+ }
+ }
+ break;
+ }
+}
+
+
+
+void GPU::submitTri(ClipSpaceVertex& v0, ClipSpaceVertex& v1, ClipSpaceVertex& v2) {
+ int32 out[] = { outcode(v0), outcode(v1), outcode(v2) };
+ int32 face = facing(v0, v1, v2);
+
+ if(primitive.winding == 1)
+ face = -face; // this can happen when clipping triangle strips
+
+ bool front = primitive.attributes & PS::drawFront;
+ bool back = primitive.attributes & PS::drawBack;
+
+ bool culled = face && !(front && face > 0 || back && face < 0);
+ bool clipped = out[0] | out[1] | out[2];
+ bool reject = out[0] & out[1] & out[2] | culled;
+
+ if(!reject) {
+ ClipSpaceVertex *vs[] = { &v0, &v1, &v2 };
+ addPoly(vs, 3, clipped);
+ }
+ primitive.texImage = texImage;
+ primitive.texPalette = texPalette;
+ primitive.size = 0;
+}
+
+void GPU::submitQuad(ClipSpaceVertex& v0, ClipSpaceVertex& v1, ClipSpaceVertex& v2, ClipSpaceVertex& v3) {
+ int32 out[] = { outcode(v0), outcode(v1), outcode(v2), outcode(v3) };
+ int32 face = facing(v0, v1, v2);
+
+ bool front = primitive.attributes & PS::drawFront;
+ bool back = primitive.attributes & PS::drawBack;
+
+ bool culled = face && !(front && face > 0 || back && face < 0);
+ bool clipped = out[0] | out[1] | out[2] | out[3];
+ bool reject = out[0] & out[1] & out[2] & out[3] | culled;
+
+ if(!reject) {
+ ClipSpaceVertex *vs[] = { &v0, &v1, &v2, &v3 };
+ addPoly(vs, 4, clipped);
+ }
+ primitive.texImage = texImage;
+ primitive.texPalette = texPalette;
+ primitive.size = 0;
+}
+
+
+
+void GPU::submitTriStrip(ClipSpaceVertex& v0, ClipSpaceVertex& v1, ClipSpaceVertex& v2) {
+ int32 face = facing(v0, v1, v2);
+
+ if(primitive.winding == 1)
+ face = -face;
+
+ // Clipping is a pain here. The easiest way that comes to mind is to check
+ // whether a vertex was clipped. Then if so, split this polygon off and,
+ // after clipping, restart the primitive with the current winding order.
+ bool front = primitive.attributes & PS::drawFront;
+ bool back = primitive.attributes & PS::drawBack;
+
+ bool culled = face != 0 && !(front && face > 0 || back && face < 0);
+ bool clipped = outcode(v0) | outcode(v1) | outcode(v2);
+
+ if(culled || clipped) {
+ if(uploadList->numPrims < 2048 && primitive.size > 3)
+ uploadList->numPrims++; // Terminate the current strip (if any)
+
+ submitTri(v0, v1, v2); // Submit as separate triangle
+ primitive.size = 2; // Next vertex restarts the strip
+ return;
+ }
+ if(primitive.size == 3) {
+ addPrim(Prim::triStrip);
+ addVertex(v0);
+ addVertex(v1);
+ }
+ addVertex(v2);
+}
+
+void GPU::submitQuadStrip(ClipSpaceVertex& v0, ClipSpaceVertex& v1, ClipSpaceVertex& v2, ClipSpaceVertex& v3) {
+ int32 face = facing(v0, v1, v3);
+ bool front = primitive.attributes & PS::drawFront;
+ bool back = primitive.attributes & PS::drawBack;
+
+ bool culled = face != 0 && !(front && face > 0 || back && face < 0);
+ bool clipped = outcode(v0) | outcode(v1) | outcode(v2) | outcode(v3);
+
+ if(culled || clipped) {
+ if(uploadList->numPrims < 2048 && primitive.size > 4)
+ uploadList->numPrims++; // Terminate the current strip (if any)
+
+ submitQuad(v0, v1, v3, v2); // Submit as separate quad
+ primitive.size = 2; // Next two vertices restart the strip
+ return;
+ }
+ if(primitive.size == 4) {
+ addPrim(Prim::quadStrip);
+ addVertex(v0);
+ addVertex(v1);
+ }
+ addVertex(v2);
+ addVertex(v3);
+}
+
+bool GPU::addPoly(ClipSpaceVertex **v, unsigned numVerts, bool clip) {
+ struct Entry {
+ ClipSpaceVertex v; unsigned out;
+ Entry() {}
+ Entry(const ClipSpaceVertex& s) : v(s), out(outcode(s)) {}
+ operator ClipSpaceVertex() const { return v; }
+ };
+
+ vector list[2], *in = list+0, *out = list+1;
+
+ for(unsigned i = 0; i < numVerts; i++)
+ out->append({ *(v[i]) });
+
+ if(clip) {
+ for(unsigned plane = 0; plane < 6; plane++) {
+ const int axis = plane/2, side = plane%2? +1 : -1;
+
+ std::swap(in, out);
+ out->reset();
+
+ for(unsigned i = 0; i < in->size(); ) {
+ auto &a = (*in)[i++];
+ auto &b = (*in)[i % in->size()];
+
+ if(1<append({ clipEdge(b, a, axis, side) });
+ if(1<append({ clipEdge(a, b, axis, side) });
+ else out->append({ b });
+ }
+ }
+ }
+ if(!out->size())
+ return true;
+
+ if(!addPrim(Prim::poly))
+ return false;
+
+ for(unsigned i = 0; i < out->size(); i++)
+ addVertex((*out)[i]);
+
+ uploadList->numPrims++;
+ return true;
+}
+
+bool GPU::addVertex(const ClipSpaceVertex &v) {
+ if(uploadList->numPrims == 2048 || uploadList->numVerts == 6144)
+ return false;
+
+ // XYZ are all in range +/-w in homogenous coordinates
+ uploadList->prims[uploadList->numPrims].numVerts++;
+ auto &out = uploadList->verts[uploadList->numVerts++];
+
+ // xyzw = 20.12
+ // uv = 20.12 (in texels)
+ // rgb = 20.12 (0 - 63.0)
+ int32 w = v.position[3];
+
+ // Perspective transformation - divide everything by W.
+ // This flattens the perspective and allows linear pixel interpolation.
+ out.w = w? w : 1; // still needed to restore UVZ and RGB.
+ out.x = (int64) v.position[0] * 0x40000000/w; // x/w
+ out.y = (int64) v.position[1] * 0x40000000/w; // y/w
+ out.z = (int64) v.position[2] * 0x40000000/w; // z/w
+ out.u = (int64) v.texCoord[0] * 0x4000/w; // u/w
+ out.v = (int64) v.texCoord[1] * 0x4000/w; // v/w
+ out.r = (int64) v.color[0] * 0x4000/w; // r/w
+ out.g = (int64) v.color[1] * 0x4000/w; // g/w
+ out.b = (int64) v.color[2] * 0x4000/w; // b/w
+
+ // Apply viewport scaling. X and Y get rounded off somehow. Vertices and
+ // interpolants jump around a lot, despite being perspective correct. :(
+ out.x = (out.x + 0x40000000ll) * viewport.w/2 + 0x400000*viewport.x >> 8;
+ out.y = (out.y + 0x40000000ll) * viewport.h/2 + 0x400000*viewport.y >> 8;
+
+ // With perspective projections, W is a linear function of Z. Default then
+ // is to use the nonlinear Z/W, giving more precision close up. This setting
+ // gives linear depth values instead.
+ //
+ // Note: In orthographic/2D views, Z/W is linear anyway because W=1. In that
+ // case this option kills Z buffering (kinda bad, given the auto Y sort).
+ //if(uploadList->depthUseW)
+ // out.z = max(-0x8000, min(0x7fff, w)); // ?
+ return true;
+}
+
+bool GPU::addPrim(unsigned shape) {
+ if(uploadList->numPrims == 2048)
+ return false;
+
+ auto &out = uploadList->prims[uploadList->numPrims];
+
+ //primitive.texImage = texImage;
+ //primitive.texPalette = texPalette;
+
+ out.numVerts = 0;
+ out.firstVert = uploadList->numVerts;
+ out.id = primitive.attributes >> 24 & 63;
+ out.alpha = primitive.attributes >> 16 & 31;
+ out.drawMode = shape;
+ out.drawMode += Prim::fog * uint1(primitive.attributes >> 15);
+ out.drawMode += Prim::zequal * uint1(primitive.attributes >> 14);
+ out.drawMode += Prim::zwrite * uint1(primitive.attributes >> 11);
+ out.drawMode += Prim::shadeMask & uint2(primitive.attributes >> 4);
+ out.drawMode += Prim::colorKey * uint1(primitive.texImage >> 29);
+
+ out.texFormat = primitive.texImage >> 26 & 7;
+ //out.texSize[1] = primitive.texImage >> 23 & 7;
+ //out.texSize[0] = primitive.texImage >> 20 & 7;
+ //out.texBorder[1] = primitive.texImage >> 17 & 5;
+ //out.texBorder[0] = primitive.texImage >> 16 & 5;
+ out.texImage = primitive.texImage;
+ out.texPalette = primitive.texPalette;
+ if(out.texFormat != Prim::I2)
+ out.texPalette *= 2;
+
+ return true;
+}
+
+
+// Matrices, OpenGL style:
+//
+// clip projection view.. model.. vertex
+// |Cx| |0 4 8 c| |0 4 8 c| |0 4 8 c| |Vx|
+// |Cy| = |1 5 9 d| * |1 5 9 d| * |1 5 9 d| * |Vy|
+// |Cz| |2 6 a e| |2 6 a e| |2 6 a e| |Vz|
+// |Cw| |3 7 b f| |3 7 b f| |3 7 b f| |Vw|
+//
+// transform() multiplies new matrix on the LEFT, ie. m = t*m.
+
+void GPU::loadMatrix(const Matrix& m) {
+ if(matrixMode == mmTexture) textureMatrix = m;
+ else {
+ if(matrixMode == mmLitView) lightMatrix = m;
+ if(matrixMode == mmProjection) projMatrix = m;
+ else /*mmModelView,mmLitView*/ viewMatrix = m;
+
+ clipMatrix = projMatrix;
+ transform(clipMatrix, viewMatrix);
+ }
+}
+
+void GPU::multMatrix(const Matrix& m) {
+ if(matrixMode == mmTexture) transform(textureMatrix, m);
+ else {
+ if(matrixMode == mmLitView) transform(lightMatrix, m);
+ if(matrixMode == mmProjection) transform(projMatrix, m);
+ else /*mmModelView,mmLitView*/ transform(viewMatrix, m);
+
+ clipMatrix = projMatrix;
+ transform(clipMatrix, viewMatrix);
+ }
+}
diff --git a/bsnes/nds/gpu/geometry.hpp b/bsnes/nds/gpu/geometry.hpp
new file mode 100644
index 00000000..fb48cc84
--- /dev/null
+++ b/bsnes/nds/gpu/geometry.hpp
@@ -0,0 +1,83 @@
+
+ uint32 regGeomStatus();
+ uint32 regGeomLoad();
+ uint32 regGeomPosition(unsigned index);
+ uint32 regGeomNormal(unsigned index);
+ uint32 regClipMatrix(unsigned index);
+ uint32 regLightMatrix(unsigned index);
+
+ void regGeomMaxPointDepth(uint32 data, uint32 mask);
+ void regGeomStatus(uint32 data, uint32 mask);
+
+
+ void loadMatrix(const Matrix& m);
+ void multMatrix(const Matrix& m);
+
+ void unpackColor(int32* color, uint16 rgb);
+
+ void submitVertex();
+ void submitTriStrip(ClipSpaceVertex& v0, ClipSpaceVertex& v1, ClipSpaceVertex& v2);
+ void submitQuadStrip(ClipSpaceVertex& v0, ClipSpaceVertex& v1, ClipSpaceVertex& v2, ClipSpaceVertex& v3);
+ void submitTri(ClipSpaceVertex& v0, ClipSpaceVertex& v1, ClipSpaceVertex& v2);
+ void submitQuad(ClipSpaceVertex& v0, ClipSpaceVertex& v1, ClipSpaceVertex& v2, ClipSpaceVertex& v3);
+
+ bool addPoly(ClipSpaceVertex **v, unsigned numVerts, bool clip);
+ bool addVertex(const ClipSpaceVertex &v);
+ bool addPrim(unsigned shape);
+
+ struct Light {
+ uint1 enable;
+ Vector color;
+ Vector direction;
+
+ Vector eyeVector;
+ Vector halfVector;
+ };
+
+ // Matrix state
+ uint2 matrixMode; enum { mmProjection, mmModelView, mmLitView, mmTexture };
+ bool stackOverflow;
+ uint1 projSP;
+ uint6 viewSP;
+ Matrix clipMatrix;
+ Matrix textureMatrix;
+ Matrix projMatrix, projStack[1];
+ Matrix viewMatrix, viewStack[32];
+ Matrix lightMatrix, lightStack[32];
+
+ Vector vertexResult;
+ Vector normalResult;
+ bool boxResult;
+
+ // Lighting and material state
+ Light lights[4];
+ Vector normal;
+ Vector diffuse;
+ Vector ambient;
+ Vector specular;
+ Vector emission;
+ uint8 shininess[128];
+ bool useShineTable;
+
+ // Primitive state
+ struct PS {
+ unsigned size;
+ uint1 winding;
+ uint2 type; enum { tris, quads, triStrip, quadStrip };
+ uint32 attributes; enum { drawFront = 0x80, drawBack = 0x40 };
+
+ uint32 texImage;
+ uint16 texPalette;
+ uint2 texTransform; enum { ttNone, ttTexCoord, ttNormal, ttVertex };
+
+ ClipSpaceVertex v[4];
+ } primitive;
+
+ uint32 attributes;
+ uint32 texImage;
+ uint16 texPalette;
+ ClipSpaceVertex vertex;
+
+ struct {
+ unsigned x, y, w, h;
+ } viewport;
diff --git a/bsnes/nds/gpu/gpu.cpp b/bsnes/nds/gpu/gpu.cpp
new file mode 100644
index 00000000..6911f6c2
--- /dev/null
+++ b/bsnes/nds/gpu/gpu.cpp
@@ -0,0 +1,497 @@
+#include
+
+namespace NintendoDS {
+
+GPU gpu;
+
+
+GPU::GPU() { }
+
+void GPU::power() {
+ powered = true;
+ swapArgument = 0;
+ uploadList = &sceneList[0];
+ renderList = &sceneList[1];
+ renderedLines = 0;
+ stencilMode = false;
+ sceneFinished = false;
+ commandBufIrq = false;
+ packedCommands = 0;
+ numArgs = 0;
+
+ for(unsigned n = 0; n < 2; n++) {
+ sceneList[n].numVerts = 0;
+ sceneList[n].numPrims = 0;
+ sceneList[n].firstAlpha = 0;
+ sceneList[n].alphaSort = 1;
+ sceneList[n].depthUseW = 0;
+
+ memset(sceneList[n].verts, 0, sizeof sceneList[n].verts);
+ memset(sceneList[n].prims, 0, sizeof sceneList[n].prims);
+ }
+
+ // Geometry state
+ Matrix identity = {
+ 0x1000, 0,0,0,
+ 0, 0x1000, 0,0,
+ 0,0, 0x1000, 0,
+ 0,0,0, 0x1000,
+ };
+ clipMatrix = identity; projSP = viewSP = stackOverflow = 0;
+ textureMatrix = identity; matrixMode = mmProjection;
+ projMatrix = identity; for(auto &m : projStack) m = identity;
+ viewMatrix = identity; for(auto &m : viewStack) m = identity;
+ lightMatrix = identity; for(auto &m : lightStack) m = identity;
+
+ for(auto &l : lights) {
+ l.enable = false;
+ l.color = Vector{0,0,0,0};
+ l.direction = Vector{0,0,0,0};
+ l.eyeVector = Vector{0,0,0,0};
+ l.halfVector = Vector{0,0,0,0};
+ }
+ diffuse = Vector{0,0,0,0};
+ ambient = Vector{0,0,0,0};
+ specular = Vector{0,0,0,0};
+ emission = Vector{0,0,0,0};
+ useShineTable = false;
+ for(auto &e : shininess) e = 0;
+
+ normal = Vector{0,0,0,0};
+ vertex.position = Vector{0,0,0,0x1000};
+ vertex.texCoord = Vector{0,0,0,0x1000};
+ vertex.color = Vector{0x3f000,0x3f000,0x3f000,0};
+
+ primitive.size = 0;
+ primitive.winding = 0;
+ primitive.type = PS::tris;
+ primitive.attributes = attributes = 0;
+ primitive.texImage = texImage = 0;
+ primitive.texPalette = texPalette = 0;
+ primitive.texTransform = PS::ttNone;
+
+ // Render state
+ renderControl.texturing = false;
+ renderControl.toonShading = RC::darken;
+ renderControl.edgeMode = RC::solid;
+ renderControl.fogMode = 0;
+ renderControl.fogLevel = 0;
+ renderControl.alphaTest = false;
+ renderControl.alphaBlend = false;
+ renderControl.backImage = false;
+
+ backColor[0] = 0; fogColor[0] = 0;
+ backColor[1] = 0; fogColor[1] = 0;
+ backColor[2] = 0; fogColor[2] = 0;
+ backAlpha = 0; fogAlpha = 0;
+ backId = 0; fogZ = 0;
+ backX = 0;
+ backY = 0; minAlpha = 0;
+ backZ = 0x7fff;
+
+ for(auto &e : fogTable) e = 0;
+ for(auto &e : edgeTable) e = Vector{0,0,0,0};
+ for(auto &e : toonTable[0]) e = Vector{0,0,0,0};
+ for(auto &e : toonTable[1]) e = Vector{0,0,0,0};
+
+ for(unsigned n = 0; n < 2; n++) {
+ drawList[n].first = 0;
+ drawList[n].last = 0;
+ drawList[n].nextPrim = 0;
+ drawList[n].lastPrim = 0;
+ }
+}
+
+void GPU::scanline() {
+ uint8 renderTime = (video.line + 50) % 263;
+
+ if(renderTime < 241 && renderedLines < 192+1) {
+ // Rendering starts in advance. Draw time varies; however, up to 48 extra
+ // scanlines can be cached, providing a buffer for complicated scenes.
+ //
+ // That isn't emulated at the moment. Scanline rendering is still needed,
+ // however, to get stencilling and other edge cases right.
+ renderScanline();
+ renderedLines++;
+ }
+
+ if(renderTime == 242) {
+ // Finished rendering - process the new scene list.
+ // Games are free to load textures during this time.
+ swapBuffers();
+ renderedLines = -1;
+
+ drawList[0].nextPrim = 0;
+ drawList[0].lastPrim = renderList->firstAlpha;
+ drawList[0].first = 0;
+ drawList[0].last = 0;
+
+ drawList[1].nextPrim = renderList->firstAlpha;
+ drawList[1].lastPrim = renderList->numPrims;
+ drawList[1].first = 0;
+ drawList[1].last = 0;
+
+ for(auto &line : pixels) for(auto &p : line) {
+ p.a.a = p.b.a = 0;
+ p.a.id = p.b.id = 0xff;
+ p.az = p.bz = 0x7fffffff;
+ }
+ }
+
+ if(commandBufIrq)
+ arm9.interrupt.flags |= CPUCore::irqGeomBuf;
+}
+
+void GPU::swapBuffers() {
+ if(sceneFinished) {
+ std::swap(uploadList, renderList);
+
+ // These settings apply to the NEW list, not the old one.
+ uploadList->alphaSort = !(swapArgument >> 0);
+ uploadList->depthUseW = swapArgument >> 1;
+ uploadList->numVerts = 0;
+ uploadList->numPrims = 0;
+
+ // Release the ARM9 if it was blocking on a command..
+ sceneFinished = false;
+ //texCache.reset();
+
+ // Terminate the current strip, if any.
+ if(renderList->numPrims < 2048 && primitive.type >= 2
+ && primitive.size >= (primitive.type==PS::quadStrip? 4 : 3))
+ renderList->numPrims++;
+
+ while(renderList->numPrims) {
+ auto &p = renderList->prims[renderList->numPrims-1];
+
+ // Ensure the program submitted enough vertices..
+ // Amusingly, this case not only crashes us, but the real GPU as well.
+ // Should issue a diagnostic here.
+ //
+ // This check also catches the case where vertex RAM fills up,
+ // leaving the last primitive unfinished.
+ if(p.numVerts < 3 || p.numVerts < 4 && (p.drawMode & Prim::quadStrip)) {
+ renderList->numPrims--;
+ } else {
+ break;
+ }
+ }
+ primitive.size = 0;
+
+ // Sort the new list
+ auto count = renderList->numPrims;
+ auto &prims = renderList->prims;
+ auto &verts = renderList->verts;
+
+ renderList->firstAlpha = 0;
+
+ for(unsigned n = 0; n < count; n++) {
+ renderList->order[n] = n;
+
+ // Is this per primitive or per polygon?
+ prims[n].minY = 255;
+ prims[n].maxY = 0;
+
+ // Clip range is x/w, y/w := +/- 0x40000000
+ for(unsigned k = 0; k < prims[n].numVerts; k++) {
+ int32 y = 192 - verts[prims[n].firstVert + k].y/0x400000;
+
+ prims[n].minY = min(prims[n].minY, y);
+ prims[n].maxY = max(prims[n].maxY, y);
+ }
+
+ // Special case for wireframe... only edge pixels are drawn.
+ if(prims[n].alpha == 0) {
+ prims[n].alpha = 31;
+ prims[n].wire = 1;
+ }
+ // Alpha is not the only thing that can send a primitive to the
+ // translucent pile. Using textures with the alpha channel does it too.
+ prims[n].blend = prims[n].alpha < 31
+ || prims[n].texFormat == Prim::A3_I5
+ || prims[n].texFormat == Prim::A5_I3;
+
+ if(prims[n].blend == 0)
+ renderList->firstAlpha++;
+ }
+
+ std::sort(renderList->order, renderList->order+count, [&](uint16 i0, uint16 i1) -> bool {
+ auto &p0 = prims[i0], &p1 = prims[i1];
+
+ if(p0.blend != p1.blend) {
+ return p0.blend < p1.blend; // separate solid + blend passes
+ }
+ if(p0.blend == false || renderList->alphaSort) {
+ // Sort polygons towards the top of the screen first. They prolly
+ // do this to save time and avoid searching the entire list.
+ if(p0.minY != p1.minY) return p0.minY < p1.minY;
+ if(p0.maxY != p1.maxY) return p0.maxY < p1.maxY;
+ }
+ return i0 < i1; // retain order in case of blending or ties
+ });
+ }
+}
+
+
+
+uint32 GPU::regRenderOptions() {
+ return renderControl.texturing<<0 | renderControl.toonShading<<1
+ | renderControl.alphaTest<<2 | renderControl.alphaBlend<<3
+ | renderControl.edgeMode<<4 | renderControl.fogMode<<6
+ | renderControl.fogLevel<<8 | renderControl.backImage<<14;
+}
+
+uint32 GPU::regRenderLoad() {
+ return 48-2;
+}
+
+void GPU::regRenderOptions(uint32 data, uint32 mask) {
+ if(mask & 0x00ff) {
+ renderControl.texturing = data >> 0;
+ renderControl.toonShading = data >> 1;
+ renderControl.alphaTest = data >> 2;
+ renderControl.alphaBlend = data >> 3;
+ renderControl.edgeMode = data >> 4;
+ renderControl.fogMode = data >> 6;
+ }
+ if(mask & 0x7f00) {
+ renderControl.fogLevel = data >> 8;
+ renderControl.backImage = data >> 14;
+ }
+}
+
+void GPU::regRenderMinAlpha(uint32 data, uint32 mask) {
+ minAlpha ^= (minAlpha ^ data) & mask;
+}
+
+void GPU::regRenderClearColor(uint32 data, uint32 mask) {
+ if(mask & 0x00007fff) {
+ backColor[0] = data>> 0 & 31;
+ backColor[1] = data>> 5 & 31;
+ backColor[2] = data>>10 & 31;
+ backFog = data>>15 & 1;
+
+ for(unsigned n = 0; n < 3; n++)
+ backColor[n] = 2*backColor[n] + (backColor[n] > 0);
+ }
+ if(mask & 0x001f0000) backAlpha = data>>16 & 31;
+ if(mask & 0x3f000000) backId = data>>24 & 63;
+}
+
+void GPU::regRenderClearCoord(uint32 data, uint32 mask) {
+ if(mask & 0x00007fff) backZ = data>>0;
+ if(mask & 0x00ff0000) backX = data>>16;
+ if(mask & 0xff000000) backY = data>>24;
+}
+
+void GPU::regRenderFogColor(uint32 data, uint32 mask) {
+ if(mask & 0x00007fff) {
+ fogColor[0] = data>> 0 & 31;
+ fogColor[1] = data>> 5 & 31;
+ fogColor[2] = data>>10 & 31;
+ for(unsigned n = 0; n < 3; n++)
+ fogColor[n] = 2*fogColor[n] + (fogColor[n] > 0);
+ }
+ if(mask & 0x001f0000) {
+ fogAlpha = data>>16 & 31;
+ }
+}
+
+void GPU::regRenderFogCoord(uint32 data, uint32 mask) {
+ if(mask & 0x00007fff) fogZ = data;
+}
+
+void GPU::regRenderFogTable(unsigned index, uint32 data, uint32 mask) {
+ if(mask & 0x000000ff) fogTable[4*index+0] = data >> 0 & 0x7f;
+ if(mask & 0x0000ff00) fogTable[4*index+1] = data >> 8 & 0x7f;
+ if(mask & 0x00ff0000) fogTable[4*index+2] = data >> 16 & 0x7f;
+ if(mask & 0xff000000) fogTable[4*index+3] = data >> 24 & 0x7f;
+
+ fogTable[32] = fogTable[31]; // extra element for lerping
+}
+
+void GPU::regRenderEdgeTable(unsigned index, uint32 data, uint32 mask) {
+ //uint6 r0 = 2*uint5(data>> 0), r1 = 2*uint5(data>>16);
+ //uint6 g0 = 2*uint5(data>> 5), g1 = 2*uint5(data>>21);
+ //uint6 b0 = 2*uint5(data>>10), b1 = 2*uint5(data>>26);
+ //
+ //if(r0) r0++; if(r1) r1++;
+ //if(g0) g0++; if(g1) g1++;
+ //if(b0) b0++; if(b1) b1++;
+ //
+ //auto *edge = &edgeTable[2*index];
+ //
+ //if(mask & 0x0000ffff) edge[0] = b0<<12 | g0<<6 | r0<<0;
+ //if(mask & 0xffff0000) edge[1] = b1<<12 | g1<<6 | r1<<0;
+ if(mask & 0x0000ffff) unpackColor(edgeTable[2*index+0], data>>0);
+ if(mask & 0xffff0000) unpackColor(edgeTable[2*index+1], data>>16);
+}
+
+void GPU::regRenderToonTable(unsigned index, uint32 data, uint32 mask) {
+ auto &d0 = toonTable[0][2*index+0];
+ auto &d1 = toonTable[0][2*index+1];
+ auto &l0 = toonTable[1][2*index+0];
+ auto &l1 = toonTable[1][2*index+1];
+
+ if(mask & 0x0000ffff) unpackColor(d0, data>>0);
+ if(mask & 0xffff0000) unpackColor(d1, data>>16);
+
+ // Generate entries for lighten mode
+ l0 = d0; l1 = d1;
+ l0[0] += 0x1000; l1[0] += 0x1000;
+ l0[1] += 0x1000; l1[1] += 0x1000;
+ l0[2] += 0x1000; l1[2] += 0x1000;
+}
+
+
+
+void GPU::regGeomMaxPointDepth(uint32 data, uint32 mask) {
+
+}
+
+void GPU::regGeomStatus(uint32 data, uint32 mask) {
+ data &= mask;
+ if(data & 1<<15) {
+ stackOverflow = false;
+ projSP = 0;
+ viewSP = 0;
+ }
+
+ if(mask & 0xff000000) {
+ commandBufIrq = data>>30;
+ if(commandBufIrq)
+ arm9.interrupt.flags |= CPUCore::irqGeomBuf;
+ }
+}
+
+uint32 GPU::regGeomStatus() {
+ return boxResult<<1 | (viewSP % 32)<<8 | projSP<<13 | stackOverflow<<15
+ | 1<<25 | 1<<26 | commandBufIrq<<30;
+}
+
+uint32 GPU::regGeomLoad() {
+ return uploadList->numPrims<<0 | uploadList->numVerts<<16;
+}
+
+uint32 GPU::regGeomPosition(unsigned index) {
+ return vertexResult[index];
+}
+
+uint32 GPU::regGeomNormal(unsigned index) {
+ return uint16(int12(normalResult[index/2 + 0]))<<0
+ | uint16(int12(normalResult[index/2 + 1]))<<16;
+}
+
+uint32 GPU::regClipMatrix(unsigned index) {
+ uint2 col = index / 4;
+ uint2 row = index % 4;
+
+ return clipMatrix[4*row + col];
+}
+
+uint32 GPU::regLightMatrix(unsigned index) {
+ uint2 col = index / 3;
+ uint2 row = index % 3;
+
+ return lightMatrix[4*row + col];
+}
+
+
+
+void GPU::sendGeomBuffered(uint32 data) {
+ // On real hardware commands are buffered, and filling up this buffer
+ // forces an indefinite waitstate until the buffer drains. A swapBuffers
+ // command sits around 'til vblank, thereby throttling the game at 60fps.
+
+ // Since we don't emulate that yet, this is the closest thing.
+ while(sceneFinished) {
+ arm9.step(16);
+ if(arm7.clock < -255)
+ co_switch(arm7.thread);
+ }
+ // Command bytes are packed 4 to a word..
+ if(packedCommands) args[numArgs++] = data;
+ else packedCommands = data;
+
+ // Take the first one and try to run it.
+ // It succeeds when enough arguments are provided.
+ //
+ // It's important to run ALL possible commands here, since some of them
+ // don't consume any arguments and the next invocation would erroneously
+ // pass data to the wrong command.
+ while(packedCommands && geomCommand(packedCommands)) {
+ numArgs = 0;
+ packedCommands >>= 8;
+ }
+ if(commandBufIrq)
+ arm9.interrupt.flags |= CPUCore::irqGeomBuf;
+}
+
+void GPU::sendGeomImmediate(uint8 command, uint32 data) {
+ while(sceneFinished) {
+ arm9.step(16);
+ if(arm7.clock < -255)
+ co_switch(arm7.thread);
+ }
+ args[numArgs++] = data;
+ if(geomCommand(command)) {
+ numArgs = 0;
+ }
+ if(commandBufIrq)
+ arm9.interrupt.flags |= CPUCore::irqGeomBuf;
+}
+
+bool GPU::geomCommand(uint8 command) {
+ switch(command) {
+ case 0x10: return gxMatrixMode();
+ case 0x11: return gxMatrixPush();
+ case 0x12: return gxMatrixPop();
+ case 0x13: return gxMatrixStore();
+ case 0x14: return gxMatrixRestore();
+ case 0x15: return gxMatrixLoadIdentity();
+ case 0x16: return gxMatrixLoad4x4();
+ case 0x17: return gxMatrixLoad4x3();
+ case 0x18: return gxMatrixMult4x4();
+ case 0x19: return gxMatrixMult4x3();
+ case 0x1a: return gxMatrixRotate();
+ case 0x1b: return gxMatrixScale();
+ case 0x1c: return gxMatrixTranslate();
+
+ case 0x20: return gxColor();
+ case 0x21: return gxNormal();
+ case 0x22: return gxTexCoord();
+ case 0x23: return gxVertex3i_16();
+ case 0x24: return gxVertex3i_10();
+ case 0x25: return gxVertex2i_XY();
+ case 0x26: return gxVertex2i_XZ();
+ case 0x27: return gxVertex2i_YZ();
+ case 0x28: return gxVertex3i_Rel();
+ case 0x29: return gxAttribute();
+ case 0x2a: return gxTexImage();
+ case 0x2b: return gxTexPalette();
+
+ case 0x30: return gxLightDiffuseAmbient();
+ case 0x31: return gxLightSpecularEmission();
+ case 0x32: return gxLightDirection();
+ case 0x33: return gxLightColor();
+ case 0x34: return gxLightShininess();
+
+ case 0x40: return gxBeginPrimitive();
+ case 0x50: return gxSwapBuffers();
+ case 0x60: return gxViewport();
+
+ case 0x70: return gxCullTest();
+ case 0x71: return gxPositionTest();
+ case 0x72: return gxDirectionTest();
+ }
+ return true;
+}
+
+
+#include "math.cpp"
+#include "commands.cpp"
+#include "geometry.cpp"
+#include "render.cpp"
+#include "textures.cpp"
+
+}
diff --git a/bsnes/nds/gpu/gpu.hpp b/bsnes/nds/gpu/gpu.hpp
new file mode 100644
index 00000000..cdaa59f4
--- /dev/null
+++ b/bsnes/nds/gpu/gpu.hpp
@@ -0,0 +1,77 @@
+
+struct GPU {
+ GPU();
+
+ void power();
+ void scanline();
+ void swapBuffers();
+
+ void sendGeomBuffered(uint32 data);
+ void sendGeomImmediate(uint8 command, uint32 data);
+ bool geomCommand(uint8 command);
+
+ // Once the geometry submitted by the program gets through transform,
+ // lighting, culling, and clipping, we've built a SceneList with:
+ struct Vertex {
+ // A single point within a primitive.
+ int64 x, y, z; // normalized device coordinates (xyz/w => -1..+1)
+ int32 u, v; // texture coordinates (u/w, v/w)
+ int32 r, g, b; // color (r/w, g/w, b/w)
+ int32 w; //
+ };
+ struct Prim {
+ // A strip of triangles or quads - or a single, clipped n-gon.
+ // AFAIK, none of these attributes can change between primitives.
+ uint16 firstVert, numVerts;
+ uint8 minY, maxY;
+ uint1 blend, wire;
+ uint8 drawMode; enum { shadeMask=0x03, normal=0, decal=1, toon=2, stencil=3,
+ poly=0, triStrip=0x04, quadStrip=0x08,
+ colorKey=0x10, zequal=0x20, zwrite=0x40, fog=0x80 };
+ uint8 id, alpha;
+ uint8 texFormat; enum { untextured, A3_I5, I2,I4,I8, packed, A5_I3, A1_RGB15 };
+ uint8 texBorder[2]; enum { clamp=0, repeat=1, clamp_=4, mirror=5 };
+ uint8 texSize[2]; // 8 << texSize
+
+ uint16 texPalette;
+ uint32 texImage;
+ };
+
+ struct SceneList {
+ unsigned numVerts;
+ unsigned numPrims;
+ unsigned firstAlpha;
+
+ Vertex verts[6144];
+ Prim prims[2048];
+ uint16 order[2048]; // by solid first, top Y, bottom Y, then index
+
+ uint1 alphaSort; // Sort transparent geometry by Y coordinate?
+ uint1 depthUseW; // Use Z or W for depth buffering?
+ };
+
+ uint1 powered;
+ uint2 swapArgument;
+ SceneList sceneList[2];
+ SceneList *uploadList;
+ SceneList *renderList;
+
+ bool sceneFinished;
+ uint2 commandBufIrq;
+ int32 renderedLines;
+ uint32 packedCommands;
+ uint32 args[32], numArgs;
+
+ uint32 output[256*192]; // ARGB5666
+
+ struct Matrix;
+ struct Vector;
+ struct ClipSpaceVertex;
+
+ #include "math.hpp"
+ #include "commands.hpp"
+ #include "geometry.hpp"
+ #include "render.hpp"
+};
+
+extern GPU gpu;
diff --git a/bsnes/nds/gpu/math.cpp b/bsnes/nds/gpu/math.cpp
new file mode 100644
index 00000000..c44d9629
--- /dev/null
+++ b/bsnes/nds/gpu/math.cpp
@@ -0,0 +1,143 @@
+
+// Flips a 4x4 matrix along the diagonal:
+// |a b c d| |a e i m|
+// |e f g h| -> |b f j n|
+// |i j k l| |c g k o|
+// |m n o p| |d h l p|
+void GPU::Matrix::transpose() {
+ auto &m = *this;
+ std::swap(m(0,1), m(1,0));
+ std::swap(m(0,2), m(2,0));
+ std::swap(m(0,3), m(3,0));
+ std::swap(m(1,2), m(2,1));
+ std::swap(m(1,3), m(3,1));
+ std::swap(m(2,3), m(3,2));
+}
+
+// Product of two matrices: M := M * T.
+void GPU::transform(Matrix& m, Matrix t) {
+ t.transpose();
+ for(unsigned i = 0; i < 4; i++)
+ transform(t, m(i));
+}
+
+// Product of 4x4 matrix and 4D vector: v := T * v.
+void GPU::transform(const Matrix& t, int32* v) {
+ int32 vector[] = { v[0], v[1], v[2], v[3] };
+ for(unsigned i = 0; i < 4; i++)
+ v[i] = dot(t(i), vector);
+}
+
+// Dot product of two 4D vectors: s := a . b.
+int32 GPU::dot(const int32* a, const int32* b) {
+ return ( (int64) a[0] * b[0]
+ + (int64) a[1] * b[1]
+ + (int64) a[2] * b[2]
+ + (int64) a[3] * b[3] )
+ / 0x1000;
+}
+
+// Given a 4D homogenous coordinate, returns a mask telling whether
+// it's out of bounds. One bit per side of the clipping volume.
+unsigned GPU::outcode(const ClipSpaceVertex &v) {
+ const int32 &x = v.position[0], &y = v.position[1];
+ const int32 &z = v.position[2], &w = v.position[3];
+
+ unsigned code = 0;
+ if(x < -w) code += 1; if(x > +w) code += 2; // left, right
+ if(y < -w) code += 4; if(y > +w) code += 8; // bottom, top
+ if(z < -w) code += 16; if(z > +w) code += 32; // near, far
+ return code;
+}
+
+// Looks at three triangle vertices and returns a signed value:
+// negative (back face), zero (edge on), or positive (front face).
+//
+// AKA sign of Z from the cross product (v1-v0) x (v2-v1) in screen coordinates:
+// Z = (v1-v0).x (v2-v1).y - (v1-v0).y (v2-v1).x
+int GPU::facing(const ClipSpaceVertex &v0, const ClipSpaceVertex &v1, const ClipSpaceVertex &v2) {
+ // These are in homogenous space, so.. that's more like:
+ // Z = a + b - c, where
+ // a = (v0.x v1.y - v0.y v1.x) / (v0.w v1.w)
+ // b = (v1.x v2.y - v1.y v2.x) / (v1.w v2.w)
+ // c = (v0.x v2.y - v0.y v2.x) / (v0.w v2.w)
+ //
+ // Since only the sign matters,
+ // S = (a+b-c <=> 0) = (a+b <=> c)
+ //
+ // and knowing w is positive within the clipping volume,
+ // p = v0.w v1.w v2.w
+ // a' = a*p, b' = b*p, c' = c*p
+ //
+ // that makes the divisions disappear.
+ // x y y x w
+ int64 a = ((int64) v0.position[0]*v1.position[1] - (int64) v0.position[1]*v1.position[0]) / 0x1000 * v2.position[3];
+ int64 b = ((int64) v1.position[0]*v2.position[1] - (int64) v1.position[1]*v2.position[0]) / 0x1000 * v0.position[3];
+ int64 c = ((int64) v0.position[0]*v2.position[1] - (int64) v0.position[1]*v2.position[0]) / 0x1000 * v1.position[3];
+
+ int64 r = a + b - c;
+ return r<0? -1 : r>0? +1 : 0;
+}
+
+// a is inside the clipping plane
+// b is outside, and will be clipped to the
+// intersection between AB and the clip plane.
+// axis controls which of X,Y,Z is tested.
+// side affects the sign of the W comparand.
+GPU::ClipSpaceVertex GPU::clipEdge(const ClipSpaceVertex &a, const ClipSpaceVertex &b, unsigned axis, int side) {
+ // Normally, to find the intersection we would attempt to find the fraction
+ // of the edge that remains unclipped:
+ // t = (1 - ax) / (bx - ax)
+ //
+ // The problem is that we haven't divided by W. We end up with this mess:
+ // t = (1 - ax/aw) / (bx/bw - ax/aw)
+ //
+ // Not very helpful. Besides which we still need W for perspective-correct
+ // texturing.
+ //
+ // In homogenous space, the clipping volume is defined by:
+ // -w < {x,y,z} < +w
+ //
+ // So we expect the clipped vertex c to have:
+ // cx = +/-cw ; cx,cy,cz depending on the plane
+ //
+ // And for each {x,y,z,w}:
+ // cx = ax + t*(bx - ax)
+ //
+ // Expanding both sides of the first equation:
+ // ax + t*(bx - ax) = aw + t*(bw - aw)
+ // t*(bx - ax) - t*(bw - aw) = aw - ax
+ // t = (aw - ax) / ((bx - ax) - (bw - aw))
+ //
+ // We end up with these two equations:
+ // t = (+aw - ax) / ((+aw - ax) - (+bw - bx)) ; cx=+cw
+ // t = (-aw - ax) / ((-aw - ax) - (-bw - bx)) ; cx=-cw
+ //
+ // or more simply:
+ // t = (ax - +aw) / ((ax - +aw) - (bx - +bw)) ; cx=+cw
+ // t = (ax - -aw) / ((ax - -aw) - (bx - -bw)) ; cx=-cw
+ //
+ // t = (ax +/- aw) / ((ax +/- aw) - (bx +/- bw))
+ //
+ // So clipping requires one division per edge that crosses a clipping plane.
+ // Quite pleasant, actually.
+ ClipSpaceVertex c;
+ int32 ax_aw = a.position[axis] - side*a.position[3];
+ int32 bx_bw = b.position[axis] - side*b.position[3];
+
+ if(ax_aw - bx_bw) {
+ int64 t = 0x40000000ll * ax_aw / (ax_aw - bx_bw);
+
+ // t should be between 0 and 1. Rather than being a linear function of X/Y/Z
+ // it also includes W. But at this point it's just an interpolation.
+ for(unsigned n = 0; n < 4; n++) {
+ c.position[n] = a.position[n] + int64(b.position[n] - a.position[n]) * t/0x40000000;
+ c.texCoord[n] = a.texCoord[n] + int64(b.texCoord[n] - a.texCoord[n]) * t/0x40000000;
+ c.color[n] = a.color[n] + int64(b.color[n] - a.color[n] ) * t/0x40000000;
+ }
+ // Ensure vertex is exactly on the clipping plane,
+ // so we don't try and clip it again.
+ c.position[axis] = side*c.position[3];
+ }
+ return c;
+}
diff --git a/bsnes/nds/gpu/math.hpp b/bsnes/nds/gpu/math.hpp
new file mode 100644
index 00000000..74298f7e
--- /dev/null
+++ b/bsnes/nds/gpu/math.hpp
@@ -0,0 +1,53 @@
+
+ struct Vector {
+ int32 v[4];
+
+ Vector() { }
+
+ Vector(const std::initializer_list& elems) {
+ unsigned n = 0;
+ for(auto i : elems) {
+ if(n == 4) break;
+ v[n++] = i;
+ }
+ }
+ inline int32& operator[](unsigned i) { return v[i]; }
+ inline const int32& operator[](unsigned i) const { return v[i]; }
+ inline operator int32*() { return v; }
+ };
+
+ struct Matrix {
+ int32 m[4*4];
+
+ Matrix() { }
+
+ Matrix(const std::initializer_list& elems) {
+ unsigned n = 0;
+ for(auto i: elems)
+ if(n < 4*4) m[n++] = i;
+ }
+
+ inline int32& operator[](unsigned i) { return m[i]; }
+ inline int32& operator()(unsigned i, unsigned j) { return m[4*i + j]; }
+ inline int32* operator()(unsigned i) { return &m[4*i]; }
+
+ inline const int32& operator[](unsigned i) const { return m[i]; }
+ inline const int32& operator()(unsigned i, unsigned j) const { return m[4*i + j]; }
+ inline const int32* operator()(unsigned i) const { return &m[4*i]; }
+
+ void transpose();
+ };
+
+ struct ClipSpaceVertex {
+ Vector position;
+ Vector texCoord;
+ Vector color;
+ };
+
+ static void transform(Matrix& m, Matrix t);
+ static void transform(const Matrix& t, int32* v);
+
+ static int32 dot(const int32* a, const int32* b);
+ static int facing(const ClipSpaceVertex &v0, const ClipSpaceVertex &v1, const ClipSpaceVertex &v2);
+ static unsigned outcode(const ClipSpaceVertex &v);
+ static ClipSpaceVertex clipEdge(const ClipSpaceVertex &b, const ClipSpaceVertex &a, unsigned axis, int side);
diff --git a/bsnes/nds/gpu/render.cpp b/bsnes/nds/gpu/render.cpp
new file mode 100644
index 00000000..8439329e
--- /dev/null
+++ b/bsnes/nds/gpu/render.cpp
@@ -0,0 +1,578 @@
+
+void GPU::updateDrawList(int y, DrawList& list, bool sorted) {
+ // Blah, why are polys with numVerts==0 making it in?
+
+ // Remove polygons that have finished rendering
+ while(list.first < list.last && (!list.polys[list.first].numVerts
+ || 192-list.polys[list.first].v[list.polys[list.first].numVerts-1]->y/0x400000 < y))
+ list.first++;
+
+ // Add primitives matching Y as their first line
+ unsigned pi = list.nextPrim;
+ while(pi < list.lastPrim) {
+ auto *prim = &renderList->prims[renderList->order[pi]];
+ if(sorted && y < prim->minY-1)
+ break;
+
+ if(!sorted || y == prim->minY-1) {
+ auto *v = &renderList->verts[prim->firstVert];
+
+ if(prim->drawMode & Prim::triStrip) {
+ for(unsigned n = 2; n < prim->numVerts; n += 1, v += 1)
+ setupPoly(list.polys[list.last++], prim, v, 3);
+ }
+ else if(prim->drawMode & Prim::quadStrip) {
+ for(unsigned n = 2; n < prim->numVerts; n += 2, v += 2)
+ setupPoly(list.polys[list.last++], prim, v, 4);
+ }
+ else {
+ setupPoly(list.polys[list.last++], prim, v, prim->numVerts);
+ }
+
+ if(list.nextPrim == pi)
+ list.nextPrim++;
+ }
+ pi++;
+ }
+}
+
+void GPU::setupPoly(ActivePoly& poly, Prim* prim, Vertex *vs, unsigned numVerts) {
+ for(unsigned n = 0; n < numVerts; n++)
+ poly.v[n] = &vs[n];
+
+ // Sort vertices by Y, then X if on same line
+ std::sort(poly.v, poly.v+numVerts, [](Vertex *a, Vertex *b)
+ { return a->y != b->y? a->y > b->y : a->x < b->x; });
+
+ poly.numVerts = numVerts;
+ if(!numVerts) return;
+
+ poly.p = prim;
+ poly.lv = poly.next_lv = 0; // start at top vertex
+ poly.rv = poly.next_rv = 0;
+ poly.side[0] = 0; // top and bottom are
+ poly.side[numVerts-1] = 0; // considered to be on both sides.
+
+ // Find out which side each vertex is on. This is based on the observation
+ // that with a convex polygon, edges always curve inwards, towards the other
+ // side. So we switch sides every time the curve changes direction.
+ for(int n = 1; n < numVerts-1; n++) {
+ int64 dx0 = poly.v[n]->x - poly.v[n-1]->x;
+ int64 dx1 = poly.v[n+1]->x - poly.v[n]->x;
+ int64 dy0 = -(poly.v[n]->y - poly.v[n-1]->y);
+ int64 dy1 = -(poly.v[n+1]->y - poly.v[n]->y);
+
+ poly.side[n] = poly.side[n-1]; // special case for straight or co-linear edges
+
+ if(!dy0) dy0 = 1;
+ if(!dy1) dy1 = 1;
+
+ // compare dx1/dy1 <=> dx0/dy0
+ // - both sides have been multiplied by dy0*dy1 to avoid division by 0
+ if(dx1*dy0 > dx0*dy1) poly.side[n] = -1; // curves to the right, so must be on the left
+ if(dx1*dy0 < dx0*dy1) poly.side[n] = +1; // curves to the left, so must be on the right
+ }
+ setupNextEdge(poly, poly.lv, poly.next_lv, -1, poly.lnext, poly.dl_dv);
+ setupNextEdge(poly, poly.rv, poly.next_rv, +1, poly.rnext, poly.dr_dv);
+
+ poly.prev_lx = poly.lnext.x;
+ poly.prev_rx = poly.rnext.x;
+}
+
+void GPU::setupNextEdge(ActivePoly& poly, unsigned& vi, unsigned& next,
+ int side, Interpolants& edge, Interpolants& gradient)
+{
+ vi = next++;
+ while(poly.side[next]*side < 0)
+ next++;
+
+ Interpolants endpoint;
+ assignEdge(edge, poly.v[vi]); edge.x &= ~0x3fffff;
+ assignEdge(endpoint, poly.v[next]); endpoint.x &= ~0x3fffff;
+
+ int32 y0 = 192 - poly.v[vi]->y/0x400000;
+ int32 y1 = 192 - poly.v[next]->y/0x400000;
+ int32 numLines = y1 - y0;
+ if(numLines) {
+ for(unsigned j = 0; j < Interpolants::count; j++)
+ gradient[j] = (endpoint[j] - edge[j]) / numLines;
+ }
+}
+
+void GPU::assignEdge(Interpolants& edge, Vertex* v) {
+ edge.r = v->r; edge.u = v->u;
+ edge.g = v->g; edge.v = v->v;
+ edge.b = v->b; edge.z = v->z;
+
+ edge.inv_w = 0x80000000000/max(1,v->w);
+ edge.x = v->x;
+}
+
+
+
+void GPU::renderScanline() {
+ int y = renderedLines;
+ auto *line = 1 + pixels[y-0 & 3];
+ auto *line1 = 1 + pixels[y-1 & 3];
+ auto *line2 = 1 + pixels[y-2 & 3];
+
+ updateDrawList(y, drawList[0], true);
+ updateDrawList(y, drawList[1], renderList->alphaSort);
+
+ unsigned backOffs = 0x40000 + 512*(backY+y & 0xff);
+ uint16 *backImageColor = &system.vmap.tex[backOffs+0x00000 >> 14][backOffs+0x00000];
+ uint16 *backImageDepth = &system.vmap.tex[backOffs+0x20000 >> 14][backOffs+0x20000];
+
+ for(int x = -1; x <= 256; x++) {
+ auto &px = line[x];
+ uint16 color = backImageColor[backX+x & 0xff];
+ uint16 depth = backImageDepth[backX+x & 0xff];
+
+ // Stencil is preserved, even between frames!
+ // Transitioning to stencilMode=1 is what clears it.
+ px.flags &= Pixel::stencil;
+ px.flags &= ~Pixel::blends;
+
+ if(renderControl.backImage) {
+ px.a.r = color<<1 & 62; px.a.r += px.a.r > 0;
+ px.a.g = color>>4 & 62; px.a.g += px.a.g > 0;
+ px.a.b = color>>9 & 62; px.a.b += px.a.b > 0;
+ px.a.a = color>>15? 31 : 0;
+ px.a.id = backId;
+ px.az = depth<<16 & 0x7fff0000;
+
+ if(depth & 1<<15) px.flags |= Pixel::fog;
+ }
+ else {
+ px.a.r = backColor[0];
+ px.a.g = backColor[1];
+ px.a.b = backColor[2];
+ px.a.a = backAlpha;
+ px.a.id = backId;
+ px.az = backZ<<16;
+
+ if(backFog) px.flags |= Pixel::fog;
+ }
+
+ px.b.a = 0;
+ px.b.id = 0xff;
+ px.bz = 0x7fffffff;
+ px.sz = 0x7fffffff;
+ }
+
+ renderDrawList(y, drawList[0], false);
+ renderDrawList(y, drawList[1], true);
+ if(y < 1) return;
+
+ y--; // edge filter requires 1 line latency
+
+ int32 fogZ = this->fogZ << 16;
+ uint32 *__restrict dest = &output[256*y];
+
+ for(int x = 0; x < 256; x++) {
+ // Any remaining fragments are combined here... or maybe this should
+ // be done between solid/alpha passes? I'm not sure if you can get a
+ // transparent pixel between a solid and a smooth edge, and still have
+ // it look right.
+ auto &px = line1[x];
+ auto &above = px.a;
+ auto &below = px.b;
+ uint8 r = above.r;
+ uint8 g = above.g;
+ uint8 b = above.b;
+ uint8 a = above.a;
+ uint8 id = above.id;
+ int64 z = px.az;
+
+ if(px.flags & Pixel::edge) {
+ auto &up = line2[x];
+ auto &left = line1[x-1], &right = line1[x+1];
+ auto &down = line[x];
+
+ // Toon edge filter - need to verify logic here, might be &&, etc.
+ if( z < up.az && id != up.a.id || z < down.az && id != down.a.id
+ || z < left.az && id != left.a.id || z < right.az && id != right.a.id
+ ) {
+ Vector outline = edgeTable[id/8];
+
+ if(renderControl.edgeMode & RC::toon) {
+ // Replace RGB with values from the table.
+ // Is there an option to disable this for some polygons?
+ r = outline[0] / 0x1000;
+ g = outline[1] / 0x1000;
+ b = outline[2] / 0x1000;
+
+ // In this case, alpha is also overwritten. Edges that don't
+ // pass the filter remain antialiased, as in "smooth" mode.
+ if(renderControl.edgeMode == RC::blended)
+ a = 16; // fixed value - or is there a register?
+ }
+ }
+ }
+
+ if(below.a /*not empty*/) {
+ if(below.id == id && a < 31 && (px.flags & Pixel::blends)) {
+ // Don't blend equal object IDs
+ r = below.r;
+ g = below.g;
+ b = below.b;
+ a = below.a;
+ }
+ else if(renderControl.alphaBlend || !(px.flags & Pixel::blends)) {
+ // Z blends, too! You can see this if you set fogAlpha=0
+ // with edge smoothing on.
+ z = px.bz + (z - px.bz) * (a+1) / 32u;
+
+ // They cheaped out here. To get correct Photoshop-style alpha
+ // (non pre-multiplied) requires dividing by A. It's nasty.
+ r = below.r + (r - below.r) * (a+1) / 32u;
+ g = below.g + (g - below.g) * (a+1) / 32u;
+ b = below.b + (b - below.b) * (a+1) / 32u;
+ a = max(a, below.a);
+ }
+ }
+
+ // Polygons can be fogged toward a constant RGBA, or optionally just
+ // their alpha channel. Unlike most systems, this is a per-pixel effect
+ // based on the Z buffer.
+ if(px.flags & Pixel::fog) {
+ // Z := 0..0x7fffffff
+ int32 dist = z-fogZ >> 16-renderControl.fogLevel;
+ dist = max(0, min(0x7fff, dist));
+
+ int32 ifog = fogTable[dist/0x400u];
+ ifog += (fogTable[dist/0x400u + 1] - ifog) * (dist & 0x3ff)/0x400u;
+
+ if(renderControl.fogMode == RC::color) {
+ r += (fogColor[0] - r) * (ifog+1)/0x80u;
+ g += (fogColor[1] - g) * (ifog+1)/0x80u;
+ b += (fogColor[2] - b) * (ifog+1)/0x80u;
+ }
+ a += (fogAlpha - a) * (ifog+1)/0x80u;
+ }
+ *dest++ = a<<18 | b<<12 | g<<6 | r<<0;
+ }
+}
+
+void GPU::renderDrawList(int y, DrawList& list, bool blend) {
+ auto *line = 1 + pixels[y & 3];
+
+ unsigned alphaTest = minAlpha * renderControl.alphaTest;
+
+ for(unsigned n = list.first; n < list.last; n++) {
+ auto &poly = list.polys[n];
+ if(!poly.numVerts) continue;
+
+ int y0 = 192-poly.v[0]->y/0x400000;
+ int y1 = 192-poly.v[poly.numVerts-1]->y/0x400000;
+
+ if(y < y0-1 || y >= y1) continue;
+
+ while(y == 192-poly.v[poly.next_lv]->y/0x400000-1 && poly.next_lv < poly.numVerts-1)
+ setupNextEdge(poly, poly.lv, poly.next_lv, -1, poly.lnext, poly.dl_dv);
+
+ while(y == 192-poly.v[poly.next_rv]->y/0x400000-1 && poly.next_rv < poly.numVerts-1)
+ setupNextEdge(poly, poly.rv, poly.next_rv, +1, poly.rnext, poly.dr_dv);
+
+ // X range for previous, current, and next line
+ // We need this to determine "edge" cases (sorry) ->
+ int px0 = poly.prev_lx / 0x400000; // Top: x in x0..prev_x0
+ int px1 = poly.prev_rx / 0x400000; // or prev_x1..x1
+ int x0 = poly.left.x / 0x400000; // Bottom: x in x0..next_x0
+ int x1 = poly.right.x / 0x400000; // or next_x1..x1
+ int nx0 = poly.lnext.x / 0x400000; // Left: x+0 == x0
+ int nx1 = poly.rnext.x / 0x400000; // Right: x+1 == x1
+
+ // Theory:
+ // A pixel is marked "edge" on one of the above conditions. Translucent
+ // (alpha < 31) polygons do not modify the edge flags. Smooth edges have
+ // their alpha set to the fraction of pixel covered.
+
+ // Test for dropout - DS doesn't have explicit line or point primitives;
+ // to draw them, you simply use geometry thinner than 1px. The rasterizer
+ // ALMOST never leaves holes.. even in extremely narrow triangles. Very
+ // occasionally, degenerate triangles will have gaps.
+ if(x0 > px1) x0 = px1;
+ if(x1 < px0) x1 = px0;
+ if(x1 <= x0) x1 = x0;
+
+ if(y >= y0) {
+ Texture *tex = nullptr;
+ if(renderControl.texturing)
+ tex = getTexture(poly.p->texImage, poly.p->texPalette);
+
+ Interpolants i = poly.left; // RGB, UVZW at current pixel
+ Interpolants delta; // Gradient from left to right edges
+
+ if(x1 > x0)
+ for(unsigned j = 0; j < Interpolants::count; j++)
+ delta[j] = (poly.left[j] - poly.right[j]) / (x0-x1);
+
+ uint8 id = poly.p->id;
+ int drawMode = poly.p->drawMode;
+ int shadeMode = drawMode & Prim::shadeMask;
+
+ if(!renderControl.fogMode)
+ drawMode &= ~Prim::fog;
+
+ if((drawMode & Prim::shadeMask) == Prim::stencil) {
+ if(id) {
+ stencilMode = false; // Draw to screen, using stencil bits as mask.
+ }
+ else if(stencilMode == false) {
+ stencilMode = true; // Draw to stencil buffer.
+
+ // Toggling into stencil mode with ID=0 was observed to clear the
+ // stencil buffer. This IS affected by polygon sorting so it will
+ // not happen on every line, or even every frame, unless so arranged!
+ //
+ // The buffer holds data for only 2 lines, and if not cleared, then
+ // old data is used. So shadow volumes must be closed to work.
+ for(unsigned x = 0; x < 256; x++)
+ line[x].flags &= ~Pixel::stencil;
+ }
+ }
+
+ if(i.inv_w < 0x2000) i.inv_w = 0x2000;
+
+ // Hrm. Too many variables here, this should be split up. Perhaps:
+ // pass 1: calculate edge coverage (a==31 only)
+ // pass 2: if z <= bz, calculate [argbf]z (modulate, decal, toon, stencil)
+ // pass 3: do atest, ztest (less, equal), merge with line buffer (a==31, a<31)?
+
+ for(unsigned x = x0; x <= x1; x++) {
+ int32 w = 0x80000000000ll / max(2ll, i.inv_w);
+ int32 z = i.z + 0x40000000; // z/w
+
+ // Should find some way to justify this - <<7 was Selected for
+ // suitable fog in Mario Kart's Chocolate Mountain course..
+ if(renderList->depthUseW)
+ z = w<<7;
+
+ // Unproject the interpolated values
+ int32 u = ((int64) i.u * w)/0x40000000;
+ int32 v = ((int64) i.v * w)/0x40000000;
+
+ Vector color = {
+ min(63, (int64) i.r * w/0x4000000),
+ min(63, (int64) i.g * w/0x4000000),
+ min(63, (int64) i.b * w/0x4000000),
+ poly.p->alpha
+ };
+
+ i.u += delta.u; i.r += delta.r;
+ i.v += delta.v; i.g += delta.g;
+ i.z += delta.z; i.b += delta.b;
+ i.inv_w += delta.inv_w;
+
+ bool edge = false;
+
+ if(blend == false) {
+ edge = x0 <= x && (x <= px0 || x <= nx0)
+ || (px1 <= x || nx1 <= x) && x <= x1
+ || x == x0 || x == x1;
+
+ if(renderControl.edgeMode & RC::smooth) {
+ if(x == x0) color[3] = 31-(poly.left.x>>17 & 31);
+ if(x == x1) color[3] = (poly.right.x>>17 & 31);
+ }
+ }
+
+ Vector texColor = { 63, 63, 63, 31 };
+ if(tex) {
+ u = max(0, min(tex->width-1, u & tex->umask));
+ v = max(0, min(tex->height-1, v & tex->vmask));
+
+ uint32 abgr = tex->image[tex->width*v + u];
+ texColor[0] = 2*(abgr>> 0 & 31) + 1;
+ texColor[1] = 2*(abgr>> 5 & 31) + 1;
+ texColor[2] = 2*(abgr>>10 & 31) + 1;
+ texColor[3] = (abgr>>15);
+ }
+
+ auto &px = line[x];
+ auto &above = px.a;
+ auto &below = px.b;
+ bool ztest_a = drawMode & Prim::zequal? z == px.az : z < px.az;
+ bool ztest_b = drawMode & Prim::zequal? z == px.bz : z < px.bz;
+
+ if(shadeMode == Prim::stencil) {
+ if(stencilMode) {
+ // Draw to stencil buffer, not the screen
+ // Does texturing work here? Alpha, maybe?
+ if(ztest_a == false) {
+ px.flags |= Pixel::stencil;
+ px.sz = px.az;
+ }
+ continue;
+ }
+ // Mask polygons using the stencil buffer
+ if(px.flags & Pixel::stencil) {
+ // Succeeded - force Z onto the fragment being shadowed
+ z = px.sz;
+ if(id == above.id) {
+ // FF IV surrounds characters in shadow volumes, and uses the ID
+ // to prevent self-shadowing. So technically this fragment is on
+ // top, yet the DS somehow draws it underneath the model. If not
+ // done this way, edge smoothing would clash with the shadow.
+ ztest_a = false;
+ ztest_b = true;
+ z = px.bz;
+ }
+ } else {
+ // Failed stencil test
+ continue;
+ }
+ }
+
+ if(shadeMode == Prim::toon) {
+ // Look up shade based on the red channel
+ int a = color[3];
+ color = toonTable[renderControl.toonShading][color[0]/2 & 31];
+ color[0] /= 0x1000u;
+ color[1] /= 0x1000u;
+ color[2] /= 0x1000u;
+ color[3] = a;
+ }
+
+ if(shadeMode == Prim::decal) {
+ color[0] += (texColor[0] - color[0]) * (texColor[3]+1) / 32u;
+ color[1] += (texColor[1] - color[1]) * (texColor[3]+1) / 32u;
+ color[2] += (texColor[2] - color[2]) * (texColor[3]+1) / 32u;
+ } else {
+ color[0] = color[0] * texColor[0] / 64u;
+ color[1] = color[1] * texColor[1] / 64u;
+ color[2] = color[2] * texColor[2] / 64u;
+ color[3] = (1 + color[3]) * texColor[3] / 32u;
+ }
+
+ if(color[3] <= renderControl.alphaTest)
+ continue;
+
+ if(blend) {
+ if(ztest_a) {
+ if(above.id == id) continue;
+
+ if(!renderControl.alphaBlend) {
+ // Mario Kart uses this on the car selection screen. The alpha
+ // and coverage are still retained and used for PPU blending.
+ above.r = color[0];
+ above.g = color[1];
+ above.b = color[2];
+ above.a = max(color[3], px.a.a);
+ above.id = id;
+
+ if(!(drawMode & Prim::fog)) px.flags &= ~Pixel::fog;
+ if(drawMode & Prim::zwrite) px.az = z;
+ continue;
+ }
+
+ if(below.a /*not empty*/) {
+ if(below.id != above.id || color[3] == 31 || !(px.flags & Pixel::blends)) {
+ // Merge the top pixel down to make room
+ px.bz += int64(px.az - px.bz) * (above.a + 1)/32u;
+
+ below.r += (above.r - below.r) * (above.a + 1)/32u;
+ below.g += (above.g - below.g) * (above.a + 1)/32u;
+ below.b += (above.b - below.b) * (above.a + 1)/32u;
+ below.a = max(above.a, below.a);
+ below.id = above.id;
+ }
+ } else {
+ // Bottom empty or top solid, simply push down
+ below = above;
+ px.bz = px.az;
+ }
+ // Then write the top one
+ above.r = color[0];
+ above.g = color[1];
+ above.b = color[2];
+ above.a = color[3];
+ above.id = id;
+
+ // AND with previous fog bit
+ if(!(drawMode & Prim::fog)) px.flags &= ~Pixel::fog;
+ if(drawMode & Prim::zwrite) px.az = z;
+
+ px.flags |= Pixel::blends;
+ }
+ else if(ztest_b) {
+ if(below.a /*not empty*/) {
+ if(below.id == id && color[3] < 31) continue;
+
+ if(!renderControl.alphaBlend) {
+ if(drawMode & Prim::zwrite)
+ px.bz = z;
+
+ below.r = color[0];
+ below.g = color[1];
+ below.b = color[2];
+ }
+ else {
+ // Blend into bottom pixel
+ if(drawMode & Prim::zwrite)
+ px.bz += int64(z - px.bz) * (color[3] + 1)/32u;
+
+ below.r += (color[0] - below.r) * (color[3] + 1)/32u;
+ below.g += (color[1] - below.g) * (color[3] + 1)/32u;
+ below.b += (color[2] - below.b) * (color[3] + 1)/32u;
+ }
+ below.a = max(color[3], below.a);
+ below.id = id;
+ } else {
+ // Bottom empty, simply replace
+ if(drawMode & Prim::zwrite)
+ px.bz = z;
+
+ below.r = color[0];
+ below.g = color[1];
+ below.b = color[2];
+ below.a = color[3];
+ below.id = id;
+ }
+ }
+ continue;
+ }
+
+ if(ztest_a) {
+ if(drawMode & Prim::fog) px.flags |= Pixel::fog;
+ else px.flags &= ~Pixel::fog;
+
+ // Push the top pixel down. Anything beneath is lost.
+ // Check first to avoid breaking backAlpha == 0.
+ if(above.a /*not empty*/) {
+ px.bz = px.az;
+ below = above;
+ below.a = 31;
+ }
+ above.r = color[0];
+ above.g = color[1];
+ above.b = color[2];
+ above.a = color[3];
+ above.id = id;
+ px.az = z;
+
+ if(edge) px.flags |= Pixel::edge;
+ else px.flags &= ~Pixel::edge;
+ }
+ else if(ztest_b) {
+ below.r = color[0];
+ below.g = color[1];
+ below.b = color[2];
+ below.a = 31;
+ below.id = id;
+ px.bz = z;
+ }
+ }
+ poly.prev_lx = poly.left.x;
+ poly.prev_rx = poly.right.x;
+ }
+ poly.left = poly.lnext;
+ poly.right = poly.rnext;
+
+ for(unsigned j = 0; j < Interpolants::count; j++) {
+ poly.lnext[j] += poly.dl_dv[j];
+ poly.rnext[j] += poly.dr_dv[j];
+ }
+ }
+}
diff --git a/bsnes/nds/gpu/render.hpp b/bsnes/nds/gpu/render.hpp
new file mode 100644
index 00000000..77e56562
--- /dev/null
+++ b/bsnes/nds/gpu/render.hpp
@@ -0,0 +1,163 @@
+
+ struct ActivePoly;
+ union Interpolants;
+ struct DrawList;
+
+ void updateDrawList(int y, DrawList& list, bool sorted);
+ void setupPoly(ActivePoly& poly, Prim* prim, Vertex *vs, unsigned numVerts);
+ void setupNextEdge(ActivePoly& poly, unsigned& vi, unsigned& next, int side, Interpolants& edge, Interpolants& gradient);
+ void assignEdge(Interpolants& edge, Vertex* v);
+
+ void renderScanline();
+ void renderDrawList(int y, DrawList& list, bool blend);
+
+ uint32 regRenderOptions();
+ uint32 regRenderLoad();
+
+ void regRenderOptions(uint32 data, uint32 mask);
+ void regRenderMinAlpha(uint32 data, uint32 mask);
+ void regRenderClearColor(uint32 data, uint32 mask);
+ void regRenderClearCoord(uint32 data, uint32 mask);
+ void regRenderFogColor(uint32 data, uint32 mask);
+ void regRenderFogCoord(uint32 data, uint32 mask);
+ void regRenderFogTable(unsigned index, uint32 data, uint32 mask);
+ void regRenderEdgeTable(unsigned index, uint32 data, uint32 mask);
+ void regRenderToonTable(unsigned index, uint32 data, uint32 mask);
+
+ struct Texture {
+ // Lookup data - 44 significant bits
+ uint64 key; // paladdr<<32 | format<<16 | texaddr<<0
+ uint32 imageBase, indexBase, colorBase;
+
+ // Mirrored textures: clamp at 2*size, wrap at 2*size, cache all 4 mirrors
+ // Repeating textures: clamp dt 1*size, wrap at 1*size
+ // Clamped textures: clamp at 1*size, wrap at UINT_MAX
+ int32 width, height;
+ int32 umask, vmask;
+ uint32 *image;
+
+ // Address ranges for dirty checks
+ uint32 texelRange[2]; // pixel data
+ uint32 indexRange[2]; // for compressed format
+ uint32 colorRange[2]; // for paletted formats
+
+ ~Texture() { delete[] image; }
+ Texture(uint64 key, int width, int height) : key(key),
+ width(width), height(height), umask(~0), vmask(~0), image(nullptr) {}
+ };
+
+ struct TexCache {
+ void reset();
+ void flushDirty(unsigned bank);
+ bool checkDirty(Texture *texture, uint32 *range, VRAMMapping *map, uint32 mask);
+
+ void add(Texture *t);
+ Texture *get(uint64 key);
+
+ enum { tableSize = 1<<10 };
+ vector table[tableSize];
+ int size;
+ } texCache;
+
+ Texture *getTexture(uint32 texImage, uint16 texPalette);
+ void mirrorTexture(Texture *tex, int width, int height);
+ void convertPacked(Texture *tex, int width, int height);
+ void convertI2(Texture *tex, int width, int height, bool colorKey);
+ void convertI3(Texture *tex, int width, int height);
+ void convertI4(Texture *tex, int width, int height, bool colorKey);
+ void convertI5(Texture *tex, int width, int height);
+ void convertI8(Texture *tex, int width, int height, bool colorKey);
+ void convertARGB(Texture *tex, int width, int height);
+
+
+ union Interpolants {
+ int64& operator[](unsigned i) { return val[i]; }
+
+ int64 val[8]; enum { count=8 };
+ struct {
+ int64 r, g, b, u, v, z, inv_w, x;
+ };
+ };
+
+ struct ActivePoly {
+ Prim *p;
+ uint8 numVerts;
+ int8 side[8]; // is vertex on left or right?
+ Vertex *v[8];
+ Interpolants left, right; // current values at l, r
+ Interpolants lnext, rnext;
+ Interpolants dl_dv, dr_dv; // gradient down each side
+ unsigned lv, rv; // index of current vertex
+ unsigned next_lv, next_rv; // index of next vertex
+ int32 prev_lx, prev_rx; // x span on previous line
+ };
+
+ struct Pixel {
+ // Z for depth sorting. We need two layers (!) to make edge smoothing
+ // independent of draw order. It also saves the trouble of blending every
+ // pixel drawn - the worst case is a single pass at the end.
+ int32 az, bz; // at least 24 bits? 15 bit had too much Z fighting :/
+ int32 sz; // shadow buffer z
+ struct {
+ uint8 r, g, b; // 6 bits
+ uint8 a; // 5 bits
+
+ // Object ID is a kludge Nintendo came up with to deal with edge fill.
+ // They chose to make all polygon edges overlap, so their antialiasing
+ // looks right. However, this means translucent edge pixels would be
+ // drawn twice. The object ID is used to suppress that.
+ uint8 id;
+ } a, b;
+
+ // Some miscellaneous bits, only one layer here.
+ // There have been comments to the effect that multiple stencil bits are
+ // needed, but I don't think that's true - shadow volumes are drawn one
+ // at a time with the stencil cleared in-between, and the object ID
+ // prevents shadows blending more than once per pixel per light.
+ uint8 flags; enum {
+ fog = 1<<7, // apply post pass Z-based fogging
+ edge = 1<<6, // apply post pass toon edge filter
+ stencil = 1<<5, // pixels can be drawn here in stencil mode
+ blends = 1<<4, // if true, treat a as alpha; else as coverage
+ };
+ };
+
+ struct RC {
+ uint1 texturing;
+ uint1 toonShading; enum { darken, lighten };
+ uint2 edgeMode; enum { solid, smooth, toon, blended };
+ uint2 fogMode; enum { color=2, alpha=3 };
+ uint4 fogLevel;
+ uint1 alphaTest;
+ uint1 alphaBlend;
+ uint1 backImage;
+ } renderControl;
+
+ struct DrawList {
+ unsigned first, last;
+ unsigned nextPrim, lastPrim;
+ ActivePoly polys[6144];
+ } drawList[2]; // 2 passes - solid and translucent
+
+ uint5 minAlpha;
+
+ uint6 backColor[3];
+ uint5 backAlpha;
+ uint6 backId;
+ uint8 backX, backY;
+ uint15 backZ;
+ uint1 backFog;
+
+ int8 fogTable[32+1];
+ uint6 fogColor[3];
+ uint5 fogAlpha;
+ int16 fogZ;
+
+ bool stencilMode;
+
+ Vector toonTable[2][32];
+ Vector edgeTable[8];
+
+ // Need two buffers here for edge transparency
+ // Need three for toon edges, argh. Will redo later.
+ Pixel pixels[4][256+2];
diff --git a/bsnes/nds/gpu/textures.cpp b/bsnes/nds/gpu/textures.cpp
new file mode 100644
index 00000000..c3bbbfea
--- /dev/null
+++ b/bsnes/nds/gpu/textures.cpp
@@ -0,0 +1,304 @@
+
+void GPU::TexCache::reset() {
+ for(auto &bucket : table) {
+ for(auto &texture : bucket)
+ delete texture;
+
+ bucket.reset();
+ }
+ size = 0;
+}
+
+bool GPU::TexCache::checkDirty(Texture *texture, uint32 *range, VRAMMapping* map, uint32 mask) {
+ uint32 addr = range[0] & ~255 & mask;
+ uint32 end = range[1] + 255 & ~255 & mask;
+
+ for(; addr != end; addr = addr+256 & mask)
+ if(map[addr>>14].dirty(addr)) return true;
+
+ return false;
+}
+
+void GPU::TexCache::flushDirty(unsigned bank) {
+ // Called whenever VRAM is (re-)assigned as texture memory
+ // (ie. the game finished uploading and has locked it).
+ bool palMem = bank >= 4;
+
+ for(auto &bucket : table) {
+ for(auto &texture : bucket) {
+ if(!(!palMem && checkDirty(texture, texture->texelRange, system.vmap.tex, 0x7ffff)
+ || !palMem && checkDirty(texture, texture->indexRange, system.vmap.tex, 0x7ffff)
+ || palMem && checkDirty(texture, texture->colorRange, system.vmap.texpal, 0x1ffff) ))
+ continue;
+
+ delete texture;
+ texture = nullptr;
+ }
+ // Flush all the nullptrs at once to avoid O(n^2) removal.
+ unsigned count = 0;
+ for(unsigned n = 0; n < bucket.size(); n++) {
+ if(bucket[n]) bucket[count++] = bucket[n];
+ }
+ bucket.resize(count);
+ }
+}
+
+
+void GPU::TexCache::add(Texture *t) {
+ uint10 hash = t->key ^ t->key>>10 ^ t->key>>20 ^ t->key>>30;
+ table[hash].append(t);
+ size++;
+}
+
+GPU::Texture* GPU::TexCache::get(uint64 key) {
+ uint10 hash = key ^ key>>10 ^ key>>20 ^ key>>30;
+
+ for(auto texture : table[hash]) {
+ if(texture->key == key)
+ return texture;
+ }
+ return nullptr;
+}
+
+
+
+GPU::Texture *GPU::getTexture(uint32 texImage, uint16 texPalette) {
+ //texCache.reset();
+
+ uint64 key = (uint64) texImage ^ (uint64)texPalette<<30;
+ Texture *tex = texCache.get(key);
+
+ if(!tex) {
+ int format = texImage>>26 & 7;
+ if(!format) return nullptr;
+
+ bool colorKey = texImage & 1<<29;
+ unsigned uaxis = texImage>>16 & 5;
+ unsigned vaxis = texImage>>17 & 5;
+ unsigned imgwidth = 8 << (texImage>>20 & 7);
+ unsigned imgheight = 8 << (texImage>>23 & 7);
+
+ tex = new Texture(key, imgwidth, imgheight);
+
+ tex->colorBase = 8*(texPalette & 0x3fff);
+ tex->imageBase = 8*(texImage & 0xffff);
+ tex->indexBase = 0x20000 + (tex->imageBase/2 & 0xffff);
+ if(tex->imageBase >= 0x40000)
+ tex->indexBase += 0x10000;
+
+ // Mirroring implies repeat as well.
+ if(uaxis == Prim::mirror) tex->width *= 2;
+ if(vaxis == Prim::mirror) tex->height *= 2;
+ if(uaxis & Prim::repeat) tex->umask = tex->width-1;
+ if(vaxis & Prim::repeat) tex->vmask = tex->height-1;
+
+ tex->image = new uint32[tex->width * tex->height];
+ tex->colorRange[0] = tex->colorRange[1] = tex->colorBase;
+ tex->texelRange[0] = tex->texelRange[1] = tex->imageBase;
+ tex->indexRange[0] = tex->indexRange[1] = tex->indexBase;
+
+ switch(format) {
+ case Prim::packed: convertPacked(tex, imgwidth, imgheight); break;
+ case Prim::I2: convertI2(tex, imgwidth, imgheight, colorKey); break;
+ case Prim::A5_I3: convertI3(tex, imgwidth, imgheight); break;
+ case Prim::I4: convertI4(tex, imgwidth, imgheight, colorKey); break;
+ case Prim::A3_I5: convertI5(tex, imgwidth, imgheight); break;
+ case Prim::I8: convertI8(tex, imgwidth, imgheight, colorKey); break;
+ case Prim::A1_RGB15: convertARGB(tex, imgwidth, imgheight); break;
+ }
+ mirrorTexture(tex, imgwidth, imgheight);
+ texCache.add(tex);
+ }
+ return tex;
+}
+
+void GPU::mirrorTexture(Texture *tex, int width, int height) {
+ for(int y = 0; y < height; y++) {
+ uint32 *row = &tex->image[tex->width*y];
+ uint32 *mirror = &tex->image[tex->width*(tex->height-1 - y)];
+
+ if(tex->width > width) {
+ for(int x = 0; x < width; x++)
+ row[tex->width-1 - x] = row[x];
+ }
+ if(tex->height > height) {
+ memcpy(mirror, row, tex->width*sizeof(*row));
+ }
+ }
+}
+
+void GPU::convertPacked(Texture *tex, int width, int height) {
+ uint32 taddr = tex->imageBase;
+ uint32 caddr = tex->indexBase;
+
+ tex->texelRange[1] += (width/4)*(height/4)*4;
+ tex->indexRange[1] += (width/4)*(height/4)*2;
+ tex->colorRange[0] += 0x10000;
+
+ for(unsigned v = 0; v < height; v += 4) {
+ uint32 *dest = &tex->image[tex->width*v];
+
+ for(unsigned u = 0; u < width; u += 4) {
+ // Retrieve 4x4 block = 16 pixels x 2bpp = 32 bits
+ auto &page = system.vmap.tex[taddr>>14 & 31];
+ uint32 block = page[taddr] | page[taddr+2]<<16;
+
+ // Retrieve color selection and mode bits
+ uint16 colorsel = system.vmap.tex[caddr>>14 & 31][caddr];
+ uint32 paddr = tex->colorBase + (4*colorsel & 0xfffc);
+ uint32 fields = 31<<20 | 31<<10 | 31<<0;
+ uint32 gap = 15; // space apart to allow averaging
+
+ // This could potentially span most of the palette space, but that would
+ // complicate the game's texture allocation, so rather unlikely.
+ tex->colorRange[0] = min(tex->colorRange[0], paddr+0);
+ tex->colorRange[1] = max(tex->colorRange[1], paddr+8);
+
+ uint32 alpha[4] = { 31, 31, 31, 31 };
+
+ uint32 colors[4] = {
+ uint15(system.vmap.texpal[paddr+0 >> 14 & 31][paddr+0]) * (1<> 14 & 31][paddr+2]) * (1<> 14 & 31][paddr+4]) * (1<> 14 & 31][paddr+6]) * (1<> 14) {
+ case 3: // 2 colors (4-way mix)
+ colors[2] = (5*colors[0] + 3*colors[1])/8 & fields;
+ colors[3] = (3*colors[0] + 5*colors[1])/8 & fields;
+ case 2: // 4 colors (separate)
+ break;
+
+ case 1: // 2 colors (3-way mix) + transparent
+ colors[2] = (4*colors[0] + 4*colors[1])/8 & fields;
+ case 0: // 3 colors (separate) + transarent
+ alpha[3] = 0;
+ break;
+ }
+
+ for(int i = 0; i < 4; i++) {
+ colors[i] |= colors[i] >> gap;
+ colors[i] = alpha[i]<<15 | colors[i] & 0x7fff;
+ }
+ for(int sv = 0; sv < 4; sv++, dest += tex->width) {
+ for(int su = 0; su < 4; su++, block >>= 2)
+ dest[su] = colors[block & 3];
+ }
+ dest += 4 - 4*tex->width;
+ taddr += 4;
+ caddr += 2;
+ }
+ }
+}
+
+void GPU::convertI2(Texture *tex, int width, int height, bool colorKey) {
+ tex->texelRange[1] += width*height/4;
+ tex->colorRange[1] += 8;
+
+ for(unsigned v = 0; v < height; v++) {
+ uint32 *dest = &tex->image[tex->width*v];
+ uint32 taddr = tex->imageBase + width/4*v;
+
+ for(unsigned u = 0; u < width; u++, taddr += !(u%4)) {
+ uint2 index = system.vmap.tex[taddr>>14 & 31][taddr] >> 2*(u&7);
+ uint32 paddr = tex->colorBase + 2*index;
+ uint16 bgr = system.vmap.texpal[paddr>>14 & 31][paddr];
+ uint5 a = 31*(colorKey == false || index > 0);
+
+ *dest++ = a<<15 | bgr;
+ }
+ }
+}
+
+void GPU::convertI3(Texture *tex, int width, int height) {
+ tex->texelRange[1] += width*height/1;
+ tex->colorRange[1] += 16;
+
+ for(unsigned v = 0; v < height; v++) {
+ uint32 *dest = &tex->image[tex->width*v];
+ uint32 taddr = tex->imageBase + width*v;
+
+ for(unsigned u = 0; u < width; u++, taddr++) {
+ uint8 index = system.vmap.tex[taddr>>14 & 31][taddr] >> 8*(u&1);
+ uint32 paddr = tex->colorBase + 2*(index & 0x07);
+ uint16 bgr = system.vmap.texpal[paddr>>14 & 31][paddr];
+ uint5 a = index>>3;
+
+ *dest++ = a<<15 | bgr;
+ }
+ }
+}
+
+void GPU::convertI4(Texture *tex, int width, int height, bool colorKey) {
+ tex->texelRange[1] += width*height/2;
+ tex->colorRange[1] += 32;
+
+ for(unsigned v = 0; v < height; v++) {
+ uint32 *dest = &tex->image[tex->width*v];
+ uint32 taddr = tex->imageBase + width/2*v;
+
+ for(unsigned u = 0; u < width; u++, taddr += !(u%2)) {
+ uint4 index = system.vmap.tex[taddr>>14 & 31][taddr] >> 4*(u&3);
+ uint32 paddr = tex->colorBase + 2*index;
+ uint16 bgr = system.vmap.texpal[paddr>>14 & 31][paddr];
+ uint5 a = 31*(colorKey == false || index > 0);
+
+ *dest++ = a<<15 | bgr;
+ }
+ }
+}
+
+void GPU::convertI5(Texture *tex, int width, int height) {
+ tex->texelRange[1] += width*height/1;
+ tex->colorRange[1] += 64;
+
+ for(unsigned v = 0; v < height; v++) {
+ uint32 *dest = &tex->image[tex->width*v];
+ uint32 taddr = tex->imageBase + width*v;
+
+ for(unsigned u = 0; u < width; u++, taddr++) {
+ uint8 index = system.vmap.tex[taddr>>14 & 31][taddr] >> 8*(u&1);
+ uint32 paddr = tex->colorBase + 2*(index & 0x1f);
+ uint16 bgr = system.vmap.texpal[paddr>>14 & 31][paddr];
+ uint5 a = (index>>5) * 9/2;
+
+ *dest++ = a<<15 | bgr;
+ }
+ }
+}
+
+void GPU::convertI8(Texture *tex, int width, int height, bool colorKey) {
+ tex->texelRange[1] += width*height/1;
+ tex->colorRange[1] += 512;
+
+ for(unsigned v = 0; v < height; v++) {
+ uint32 *dest = &tex->image[tex->width*v];
+ uint32 taddr = tex->imageBase + width*v;
+
+ for(unsigned u = 0; u < width; u++, taddr++) {
+ uint8 index = system.vmap.tex[taddr>>14 & 31][taddr] >> 8*(u&1);
+ uint32 paddr = tex->colorBase + 2*index;
+ uint16 bgr = system.vmap.texpal[paddr>>14 & 31][paddr];
+ uint5 a = 31*(colorKey == false || index > 0);
+
+ *dest++ = a<<15 | bgr;
+ }
+ }
+}
+
+void GPU::convertARGB(Texture *tex, int width, int height) {
+ tex->texelRange[1] += width*height*2;
+
+ for(unsigned v = 0; v < height; v++) {
+ uint32 *dest = &tex->image[tex->width*v];
+ uint32 taddr = tex->imageBase + 2*width*v;
+
+ for(unsigned u = 0; u < width; u++, taddr += 2) {
+ uint16 abgr = system.vmap.tex[taddr>>14 & 31][taddr];
+ uint5 a = 31*(abgr >> 15);
+
+ *dest++ = a<<15 | abgr;
+ }
+ }
+}
\ No newline at end of file
diff --git a/bsnes/nds/interface/interface.cpp b/bsnes/nds/interface/interface.cpp
new file mode 100644
index 00000000..42cf40ce
--- /dev/null
+++ b/bsnes/nds/interface/interface.cpp
@@ -0,0 +1,410 @@
+#include
+#include
+
+namespace NintendoDS {
+
+Interface *interface = nullptr;
+
+double Interface::videoFrequency() {
+ return 2.*33513982 / (2*6 * 263*355);
+}
+
+double Interface::audioFrequency() {
+ return 2.*33513982 / (2 * 1024);
+}
+
+bool Interface::loaded() {
+ return true;
+}
+
+unsigned Interface::group(unsigned id) {
+ if(id == ARM7BIOS || id == ARM9BIOS) return 0;
+ if(id == Firmware || id == Clock) return 0;
+
+ if(id == Slot1ROM || id == Slot1EEPROM) return 1;
+ if(id == Slot1FRAM || id == Slot1Flash) return 1;
+
+ if(id == Slot2ROM || id == Slot2RAM) return 2;
+ if(id == Slot2SRAM || id == Slot2EEPROM) return 2;
+ if(id == Slot2FRAM || id == Slot2Flash) return 2;
+
+ return 0;
+}
+
+void Interface::load(unsigned id, const string& manifest) {
+ //print(manifest,"\n");
+ string syspath = interface->path(System);
+
+ if(id == NintendoDS) {
+ gameManifest = manifest;
+ systemManifest.readfile({syspath, "manifest.xml"});
+ XML::Document sysdoc(systemManifest);
+
+ if(!sysdoc["system"].exists()) {
+ interface->notify("manifest.xml not found");
+ }
+ else {
+ auto &sys = sysdoc["system"];
+
+ string arm7BiosFile = sys["arm7"]["bios"]["data"].data;
+ string arm9BiosFile = sys["arm9"]["bios"]["data"].data;
+ string firmwareFile = sys["flash"]["data"].data;
+ string clockXmlFile = sys["rtc"]["data"].data;
+
+ if(!file::exists({syspath, arm7BiosFile})) interface->notify("arm7 bios not found");
+ if(!file::exists({syspath, arm9BiosFile})) interface->notify("arm9 bios not found");
+ if(!file::exists({syspath, firmwareFile})) interface->notify("firmware not found");
+
+ interface->loadRequest(ARM7BIOS, arm7BiosFile);
+ interface->loadRequest(ARM9BIOS, arm9BiosFile);
+ interface->loadRequest(Firmware, firmwareFile);
+ interface->loadRequest(Clock, clockXmlFile);
+ }
+
+ if(gameManifest == "") {
+ // Default to 1GB ROM with no save. Since GameCard does bounds-check,
+ // we only allocate enough to hold the stream passed in.
+ gameManifest =
+ ""
+ ""
+ ""
+ ""
+ "";
+ }
+
+ //
+ XML::Document document(gameManifest);
+
+ //if(document.error != "") {
+ // print(document.error,"\n");
+ // return;
+ //}
+
+ auto &eslot1 = document["cartridge"]["slot1"];
+
+ //
+ if(eslot1.exists()) {
+ //
+ if(eslot1["rom"].exists()) {
+ string file = string(eslot1["rom"]["name"].data);
+ uint32 size = numeral(eslot1["rom"]["size"].data);
+ uint32 chipId = numeral(eslot1["rom"]["id"].data);
+
+ print("Loading slot-1 ROM (", file, ").. ");
+ slot1.load(new GameCard(chipId));
+ interface->loadRequest(Slot1ROM, file);
+ print("\n");
+ }
+ //
+ if(eslot1["save"].exists()) {
+ string file = string(eslot1["save"]["name"].data);
+ string type = string(eslot1["save"]["type"].data);
+ uint32 size = numeral(eslot1["save"]["size"].data);
+ uint32 psize = numeral(eslot1["save"]["page"].data); // EEPROM only
+ uint32 chipId = numeral(eslot1["save"]["id"].data); // Flash only
+
+ unsigned id = 0;
+ if(auto card = slot1.card) {
+ if(type == "EEPROM") id = Slot1EEPROM, card->spi = new EEPROM(size, psize);
+ if(type == "Flash") id = Slot1Flash, card->spi = new Flash(size, chipId);
+ if(type == "FRAM") id = Slot1FRAM, card->spi = new FRAM(size);
+ }
+ if(id) {
+ print("Loading slot-1 ",eslot1["save"]["type"].data," (", file, ").. ");
+ interface->loadRequest(id, file);
+ print("\n");
+ }
+ }
+ //
+ if(eslot1["irport"].exists()) {
+ // Required by Pokemon HG/SS and B/W. These cards have an infrared port
+ // built-in. Since there's only one /CS, access to flash memory passes
+ // through the infrared bridge via an override command.
+ slot1.card->spi = new IRPort(slot1.card->spi);
+ }
+ }
+ }
+
+ // Provide blank images if needed (we'd crash otherwise).
+ if(system.firmware.size == 0) {
+ system.firmware.size = 0x40000;
+ system.firmware.data = new uint8[system.firmware.size];
+ memset(system.firmware.data, 0xff, system.firmware.size);
+ }
+ if(arm7.bios.size == 0) {
+ arm7.bios.size = 4;
+ arm7.bios.data = new uint32[arm7.bios.size/4];
+ memset(arm7.bios.data, 0xef, arm7.bios.size);
+ }
+ if(arm9.bios.size == 0) {
+ arm9.bios.size = 4;
+ arm9.bios.data = new uint32[arm9.bios.size/4];
+ memset(arm9.bios.data, 0xef, arm9.bios.size);
+ }
+}
+
+void Interface::load(unsigned id, const stream& memory, const string& markup) {
+ if(id == ARM7BIOS) return system.loadArm7Bios(memory);
+ if(id == ARM9BIOS) return system.loadArm9Bios(memory);
+ if(id == Firmware) return system.loadFirmware(memory);
+ if(id == Clock) return system.loadRTC(memory);
+
+ XML::Document document(gameManifest);
+
+ auto &eslot1 = document["cartridge"]["slot1"];
+
+ if(eslot1.exists()) {
+ if(eslot1["rom"].exists() && id == Slot1ROM) {
+ string hash = string(eslot1["rom"]["sha256"].data);
+ uint32 size = numeral(eslot1["rom"]["size"].data);
+
+ if(auto card = slot1.card) {
+ delete card->rom.data;
+ card->rom.size = min(memory.size(), size);
+ card->rom.data = new uint8[card->rom.size];
+ card->size = bit::round(size);
+
+ memory.read(card->rom.data, card->rom.size);
+
+ if(hash && hash != card->sha256) print("SHA256 mismatch.");
+ else print("OK.");
+ }
+ }
+ if(eslot1["save"].exists() && slot1.card && (id==Slot1EEPROM || id==Slot1Flash || id==Slot1FRAM)) {
+ uint32 size = numeral(eslot1["save"]["size"].data);
+
+ if(auto save = slot1.card->spi) {
+ if(auto irport = dynamic_cast(save))
+ save = irport->slave;
+
+ if(auto media = dynamic_cast(save)) {
+ memory.read(media->data, min(media->size, memory.size()));
+ print("OK.");
+ }
+ }
+ }
+ }
+}
+
+
+
+void Interface::save() {
+ XML::Document sysdoc(systemManifest);
+
+ if(sysdoc["system"].exists()) {
+ auto &sys = sysdoc["system"];
+
+ interface->saveRequest(Firmware, sys["flash"]["data"].data);
+ interface->saveRequest(Clock, sys["rtc"]["data"].data);
+ }
+
+ XML::Document document(gameManifest);
+ auto &eslot1 = document["cartridge"]["slot1"];
+
+ if(eslot1.exists() && eslot1["save"].exists()) {
+ string file = eslot1["save"]["name"].data;
+ string type = eslot1["save"]["type"].data;
+
+ print("Saving slot-1 ",type,".. ");
+
+ if(type == "EEPROM") interface->saveRequest(Slot1EEPROM, file);
+ if(type == "Flash") interface->saveRequest(Slot1Flash, file);
+ if(type == "FRAM") interface->saveRequest(Slot1FRAM, file);
+
+ print("\n");
+ }
+}
+
+void Interface::save(unsigned id, const stream& memory) {
+ if(id == Firmware) return system.saveFirmware(memory);
+ if(id == Clock) return system.saveRTC(memory);
+
+ if(slot1.card && (id == Slot1EEPROM || id == Slot1Flash || id == Slot1FRAM)) {
+ if(auto save = slot1.card->spi) {
+ if(auto irport = dynamic_cast(save))
+ save = irport->slave;
+
+ if(auto media = dynamic_cast(save)) {
+ memory.write(media->data, media->size);
+ print("OK.");
+ }
+ }
+ }
+}
+
+
+
+void Interface::unload() {
+ struct timeval tv;
+ gettimeofday(&tv, nullptr);
+ system.clock.freeze(tv.tv_sec, tv.tv_usec);
+ system.running = false;
+
+ save();
+ delete slot1.unload();
+}
+
+void Interface::power() {
+ system.power();
+}
+
+void Interface::run() {
+ if(!system.running) {
+ struct timeval tv;
+ gettimeofday(&tv, nullptr);
+ system.clock.thaw(tv.tv_sec, tv.tv_usec);
+ system.running = true;
+ }
+ system.run();
+}
+
+serializer Interface::serialize() {
+ return {};
+}
+
+bool Interface::unserialize(serializer &s) {
+ return false;
+}
+
+void Interface::paletteUpdate() {
+ for(unsigned color = 0; color < 01000000; color++) {
+ uint16 r = uint6(color>> 0) * 010101/4;
+ uint16 g = uint6(color>> 6) * 010101/4;
+ uint16 b = uint6(color>>12) * 010101/4;
+
+ palette[color] = interface->videoColor(color, r,g,b);
+ }
+}
+
+void Interface::videoRefresh(const uint32_t *data, unsigned pitch, unsigned width, unsigned height) {
+ static uint32_t pixels[256*384];
+
+ for(unsigned y = 0; y < 384; y++) {
+ const uint32 *src = &data[y*pitch/4];
+ uint32 *dest = &pixels[y*256];
+
+ for(unsigned x = 0; x < 256; x++)
+ dest[x] = palette[src[x] & 0777777];
+ }
+ return bind->videoRefresh(pixels, 256*4, 256, 384);
+}
+
+
+Interface::Interface() {
+ interface = this;
+
+ information.name = "Nintendo DS";
+ information.width = 256;
+ information.height = 384;
+ information.aspectRatio = 1.0;
+ information.overscan = false;
+ information.resettable = false;
+ information.capability.states = false;
+ information.capability.cheats = false;
+
+ media.append({NintendoDS, "Nintendo DS", "nds"});
+ //media.append({NintendoDS, "Nintendo DS", "nds", "Menu"});
+
+ // Input devices and ports
+
+ emptySlot = Device{ID::Device::Empty, 1<port)
+ for(auto &device : this->device)
+ if(device.portmask & 1< device;
+
+ // System inputs
+ Device sensors;
+ Device buttons;
+ Device touchpad;
+
+ Device emptySlot;
+
+ // Slot 1
+ Device gameCard;
+
+ // Slot 2 peripherals
+ Device gamePak; // for linking Pokémon D/P/HG/SS and R/S/E
+ Device expansionPak; // Opera browser, homebrew
+ Device rumblePak; // Metroid Pinball, others
+ Device guitarGrip; // Guitar Hero: On Tour
+ Device piano; // Easy Piano
+ Device paddle; // Arkanoid
+
+ unsigned palette[01000000];
+};
+
+extern Interface *interface;
+
+#ifndef NDS_HPP
+}
+#endif
diff --git a/bsnes/nds/memory/eeprom.cpp b/bsnes/nds/memory/eeprom.cpp
new file mode 100644
index 00000000..cdb873f0
--- /dev/null
+++ b/bsnes/nds/memory/eeprom.cpp
@@ -0,0 +1,96 @@
+
+EEPROM::~EEPROM() { }
+
+EEPROM::EEPROM(uint32 esize, uint32 psize) {
+ data = new uint8[size = esize];
+ pageSize = psize;
+ memset(data, 0xff, size);
+}
+
+EEPROM::EEPROM(const stream& memory, uint32 esize, uint32 psize) {
+ data = new uint8[size = esize];
+ pageSize = psize;
+ memset(data, 0xff, size);
+ memory.read(data, min(memory.size(), size));
+}
+
+void EEPROM::power() {
+ if(!pageSize) {
+ if(size <= 0x200) pageSize = 0x10;
+ else if(size <= 0x2000) pageSize = 0x20;
+ else pageSize = 0x80;
+ }
+ command = 0;
+ writeEnable = false;
+}
+
+void EEPROM::select(bool state) {
+ if(state) return;
+
+ if(command && writeEnable) {
+ // Finish some previously submitted commands
+ if(command == 0x02 || command == 0x0a) {
+ //print("finishing write to ",hex<6>(page),"\n");
+ address = page;
+
+ // Write page
+ for(unsigned n = 0; n < count; n++) {
+ if(!(address & pageSize-1)) address = page;
+ this->data[address++] = buffer[n];
+ }
+ writeEnable = false;
+ }
+ }
+ // Reset and wait for a new command
+ command = 0;
+}
+
+uint8 EEPROM::transfer(uint8 data) {
+ if(command == 0) {
+ command = data;
+ address = count = 0;
+ addrCount = 0;
+
+ //print("eeprom: cmd ",hex<2>(command),"\n");
+ if(command == 0x02 || command == 0x0a) addrCount = 1 + (size > 512);
+ if(command == 0x03 || command == 0x0b) addrCount = 1 + (size > 512);
+
+ if(command == 0x0a && size == 512) address = 1; // read/write 2nd page
+ if(command == 0x0b && size == 512) address = 1; // (512-byte only)
+
+ if(command == 0x04) writeEnable = false;
+ if(command == 0x06) writeEnable = true;
+ return 0xff;
+ }
+
+ if(addrCount) { // Input address
+ addrCount--;
+ address = address<<8 | data;
+ page = address;
+ return 0xff;
+ }
+
+ if(command == 0x01) {
+ return 0xff; // Write status
+ }
+
+ if(command == 0x05) { // Read status
+ return (size > 512? 0x00 : 0xf0) | writeEnable<<1; // | writing<<0;
+ }
+
+ if(command == 0x03 || command == 0x0b) { // Read data
+ //if(address == page) print("eeprom: read ",hex<6>(address),"\n");
+ if(address == size) address = 0;
+ return this->data[address++];
+ }
+
+ if(command == 0x02 || command == 0x0a) { // Write data
+ //if(address == page) print("eeprom: write ",hex<6>(address),"\n");
+ if(count < pageSize) {
+ if(!(address & pageSize-1)) address = page;
+ buffer[count++] = data;
+ return this->data[address++];
+ }
+ }
+ return 0xff;
+}
diff --git a/bsnes/nds/memory/eeprom.hpp b/bsnes/nds/memory/eeprom.hpp
new file mode 100644
index 00000000..248390a1
--- /dev/null
+++ b/bsnes/nds/memory/eeprom.hpp
@@ -0,0 +1,17 @@
+
+struct EEPROM : SPIDevice, StaticMemory {
+ ~EEPROM();
+ EEPROM(uint32 esize, uint32 psize);
+ EEPROM(const stream& memory, uint32 esize, uint32 psize);
+
+ void power();
+ void select(bool state);
+ uint8 transfer(uint8 data);
+
+ uint8 command;
+ uint16 address, page, pageSize;
+ unsigned addrCount;
+ unsigned count;
+ uint8 buffer[256];
+ bool writeEnable;
+};
diff --git a/bsnes/nds/memory/flash.cpp b/bsnes/nds/memory/flash.cpp
new file mode 100644
index 00000000..15bcb572
--- /dev/null
+++ b/bsnes/nds/memory/flash.cpp
@@ -0,0 +1,137 @@
+
+Flash::~Flash() { }
+
+Flash::Flash(uint32 esize, uint32 id) {
+ data = new uint8[size = esize];
+ memset(data, 0xff, size);
+ this->id = id;
+}
+
+Flash::Flash(const stream& memory, uint32 esize, uint32 id) {
+ data = new uint8[size = esize];
+ memset(data, 0xff, size);
+ memory.read(data, min(memory.size(), size));
+ this->id = id;
+}
+
+void Flash::power() {
+ powered = true;
+ command = 0;
+ writeEnable = false;
+}
+
+void Flash::select(bool state) {
+ if(state) return;
+
+ //print("flash: deselect - cmd=",hex<2>(command)," wen=",writeEnable,"\n");
+ if(command && writeEnable) {
+ // Finish some previously submitted commands
+ if(command == 0x0a) {
+ // Read any remaining page into the buffer,
+ // so it's not lost during the erase cycle.
+ while(count < 256) {
+ buffer[count++] = data[address++];
+ if(!(address & 0xff)) address -= 0x100;
+ }
+ }
+
+ if(command == 0x0a || command == 0xdb || command == 0xd8) {
+ // Modify page / erase page / erase 64Kbyte sector
+ unsigned block = command == 0xd8? 0x10000 : 0x100;
+
+ address = page & ~(block-1);
+
+ // Erasing sets data bits to 1.
+ for(unsigned n = 0; n < block; n++)
+ data[address++] = 0xff;
+
+ writeEnable = false;
+ }
+
+ if(command == 0x0a || command == 0x02) {
+ // Modify page / write page
+ address = page;
+ //print("finishing write to ",hex<6>(page),"\n");
+
+ for(unsigned n = 0; n < 256; n++) {
+ // Writing can only clear bits.
+ data[address++] &= buffer[n];
+ if(!(address & 0xff)) address -= 0x100;
+ }
+ writeEnable = false;
+ }
+ }
+ // Reset and wait for a new command
+ command = 0;
+}
+
+uint8 Flash::transfer(uint8 data) {
+ if(command == 0) {
+ command = data;
+ count = 0;
+ address = 0;
+ addrCount = 0;
+
+ //print("flash: cmd ",hex<2>(command),"\n");
+
+ if(command == 0xab) powered = true; // Wake up
+
+ if(powered) {
+ if(command == 0x9f) count = 3; // Read ID
+ if(command == 0xb9) powered = false; // Power down
+ if(command == 0x06) writeEnable = true; // Write enable
+ if(command == 0x04) writeEnable = false; // Write disable
+
+ if(command == 0xdb || command == 0xd8) addrCount = 3; // Erase page / sector
+ if(command == 0x02 || command == 0x0a) addrCount = 3; // Write data
+ if(command == 0x03 || command == 0x0b) addrCount = 3; // Read data
+ }
+ return 0;
+ }
+ if(!powered)
+ return 0;
+
+ if(addrCount) {
+ // Input address
+ addrCount--;
+ address = address<<8 | data;
+ page = address;
+ if(command == 0x0b) count = 1; // Dummy byte between address and data
+ return 0;
+ }
+
+ if(command == 0x9f) {
+ // Read ID
+ //print("flash: read id\n");
+ if(count) count--;
+ return id >> 8*count;
+ }
+
+ if(command == 0x05) {
+ // Read status
+ //print("flash: read status\n");
+ return writeEnable<<1; // | writing<<0;
+ }
+
+ if(command == 0x03 || command == 0x0b) {
+ // Read data
+ //if(address == page) print("flash: read ",hex<6>(address),"\n");
+ if(count) { count--; return 0; }
+ if(address >= size) address = 0;
+ return this->data[address++];
+ }
+
+ if(command == 0x02 || command == 0x0a) {
+ // Write page / modify page
+ //if(address == page) print("flash: write ",hex<6>(address),"\n");
+ if(count < 0x100) {
+ if(address >= size) address = 0;
+ buffer[count++] = data;
+ uint8 r = this->data[address++];
+ if(!(address & 0xff)) address -= 0x100;
+ return r;
+ }
+ return 0;
+ }
+ return 0;
+}
diff --git a/bsnes/nds/memory/flash.hpp b/bsnes/nds/memory/flash.hpp
new file mode 100644
index 00000000..32656344
--- /dev/null
+++ b/bsnes/nds/memory/flash.hpp
@@ -0,0 +1,20 @@
+
+struct Flash : SPIDevice, StaticMemory {
+ ~Flash();
+ Flash() {}
+ Flash(uint32 esize, uint32 id);
+ Flash(const stream& memory, uint32 esize, uint32 id);
+
+ void power();
+ void select(bool state);
+ uint8 transfer(uint8 data);
+
+ uint24 id;
+ uint8 command;
+ uint24 address, page;
+ unsigned addrCount;
+ unsigned count;
+ uint8 buffer[256];
+ bool powered;
+ bool writeEnable;
+};
diff --git a/bsnes/nds/memory/fram.cpp b/bsnes/nds/memory/fram.cpp
new file mode 100644
index 00000000..1e955bd6
--- /dev/null
+++ b/bsnes/nds/memory/fram.cpp
@@ -0,0 +1,64 @@
+
+FRAM::~FRAM() { }
+
+FRAM::FRAM(uint32 esize) {
+ data = new uint8[size = esize];
+ memset(data, 0xff, size);
+}
+
+FRAM::FRAM(const stream& memory, uint32 esize) {
+ data = new uint8[size = esize];
+ memset(data, 0xff, size);
+ memory.read(data, min(memory.size(), size));
+}
+
+void FRAM::power() {
+ command = 0;
+ writeEnable = false;
+}
+
+void FRAM::select(bool state) {
+ if(state) return;
+
+ // Reset and wait for a new command
+ if(command == 0x02) writeEnable = false;
+ command = 0;
+}
+
+uint8 FRAM::transfer(uint8 data) {
+ if(command == 0) {
+ command = data;
+ address = addrCount = 0;
+
+ if(command == 0x02) addrCount = 2;
+ if(command == 0x03) addrCount = 2;
+ if(command == 0x04) writeEnable = false;
+ if(command == 0x06) writeEnable = true;
+ return 0xff;
+ }
+
+ if(addrCount) { // Input address
+ addrCount--;
+ address = address<<8 | data;
+ return 0xff;
+ }
+
+ if(command == 0x01) {
+ return 0xff; // Write status
+ }
+
+ if(command == 0x05) { // Read status
+ return writeEnable<<1; // | writing<<0;
+ }
+
+ if(command == 0x03) { // Read data
+ if(address == size) address = 0;
+ return this->data[address++];
+ }
+
+ if(command == 0x02) { // Write data
+ if(address == size) address = 0;
+ return this->data[address++] = data;
+ }
+ return 0xff;
+}
diff --git a/bsnes/nds/memory/fram.hpp b/bsnes/nds/memory/fram.hpp
new file mode 100644
index 00000000..753f2a29
--- /dev/null
+++ b/bsnes/nds/memory/fram.hpp
@@ -0,0 +1,16 @@
+
+struct FRAM : SPIDevice, StaticMemory {
+ ~FRAM();
+ FRAM(uint32 esize);
+ FRAM(const stream& memory, uint32 esize);
+
+ void power();
+ void select(bool state);
+ uint8 transfer(uint8 data);
+
+ uint8 command;
+ uint16 address, page, pageSize;
+ unsigned addrCount;
+ uint8 buffer[256];
+ bool writeEnable;
+};
diff --git a/bsnes/nds/memory/memory.cpp b/bsnes/nds/memory/memory.cpp
new file mode 100644
index 00000000..e4e10d44
--- /dev/null
+++ b/bsnes/nds/memory/memory.cpp
@@ -0,0 +1,127 @@
+#include
+
+namespace NintendoDS {
+
+Memory::~Memory() {}
+
+struct UnmappedMemory : Memory {
+ uint32 read(uint32 addr, uint32 size) { return 0u; }
+ void write(uint32 addr, uint32 size, uint32 word) {}
+};
+
+static UnmappedMemory unmappedMemory;
+
+
+StaticMemory::StaticMemory() { data = nullptr; size = 0u; }
+StaticMemory::~StaticMemory() { if(data) delete[] data; }
+uint8& StaticMemory::operator[](uint32 addr) { return data[addr]; }
+
+uint32 StaticMemory::read(uint32 addr, uint32 size) {
+ if(size == Byte) return (*this)[addr];
+ if(size == Half) return addr &= ~1, (*this)[addr] | (*this)[addr+1]<<8;
+ if(size == Word) return addr &= ~3, (*this)[addr] | (*this)[addr+1]<<8 | (*this)[addr+2]<<16 | (*this)[addr+3]<<24;
+}
+
+void StaticMemory::write(uint32 addr, uint32 size, uint32 word) {
+ if(size == Half) addr &= ~1;
+ if(size == Word) addr &= ~3;
+
+ (*this)[addr] = word;
+ if(size >= Half) {
+ (*this)[addr+1] = word>>8;
+ }
+ if(size >= Word) {
+ (*this)[addr+2] = word>>16;
+ (*this)[addr+3] = word>>24;
+ }
+}
+
+
+ByteMemory::ByteMemory() { data = nullptr; size = 0u; }
+ByteMemory::~ByteMemory() { if(data) delete[] data; }
+uint8& ByteMemory::operator[](uint32 addr) { return data[addr]; }
+
+uint32 ByteMemory::read(uint32 addr, uint32 size) {
+ return (*this)[addr] * 0x01010101;
+}
+
+void ByteMemory::write(uint32 addr, uint32 size, uint32 word) {
+ (*this)[addr] = word;
+}
+
+
+HalfMemory::HalfMemory() { data = nullptr; size = 0u; }
+HalfMemory::~HalfMemory() { if(data) delete[] data; }
+
+uint16& HalfMemory::operator[](uint32 addr) { return data[addr>>1]; }
+
+uint32 HalfMemory::read(uint32 addr, uint32 size) {
+ if(size == Word) return addr &= ~3, (*this)[addr] + ((*this)[addr+2] << 16);
+ if(size != Word) return (*this)[addr] * 0x00010001;
+}
+
+void HalfMemory::write(uint32 addr, uint32 size, uint32 word) {
+ if(size == Word) addr &= ~3;
+
+ (*this)[addr] = word;
+ if(size == Word)
+ (*this)[addr+2] = word>>16;
+}
+
+
+WordMemory::WordMemory() { data = nullptr; size = 0u; }
+WordMemory::~WordMemory() { if(data) delete[] data; }
+
+uint32& WordMemory::operator[](uint32 addr) { return data[addr>>2]; }
+
+uint32 WordMemory::read(uint32 addr, uint32 size) {
+ return (*this)[addr];
+}
+
+void WordMemory::write(uint32 addr, uint32 size, uint32 word) {
+ if(size == Word) (*this)[addr] = word;
+ if(size != Word) (*this)[addr] ^= ((*this)[addr] ^ word) & 0xffff << 8*(addr & 2);
+}
+
+
+SDRAM::SDRAM() { data = nullptr; size = 0u; }
+SDRAM::~SDRAM() { if(data) delete[] data; }
+
+uint16& SDRAM::operator[](uint32 addr) { return data[addr>>1]; }
+
+uint32 SDRAM::read(uint32 addr, uint32 size) {
+ if(size == Word) return addr &= ~3, (*this)[addr] + ((*this)[addr+2] << 16);
+ if(size != Word) return (*this)[addr] * 0x00010001;
+}
+
+void SDRAM::write(uint32 addr, uint32 size, uint32 word) {
+ if(size == Word) {
+ addr &= ~3;
+ (*this)[addr+0] = word;
+ (*this)[addr+2] = word>>16;
+ }
+ if(size == Half) (*this)[addr] = word;
+ if(size == Byte) (*this)[addr] ^= ((*this)[addr] ^ word) & 0xff << 8*(addr & 1);
+}
+
+
+SRAM::SRAM() { data = nullptr; size = 0u; }
+SRAM::~SRAM() { if(data) delete[] data; }
+
+uint32& SRAM::operator[](uint32 addr) { return data[addr>>2]; }
+
+uint32 SRAM::read(uint32 addr, uint32 size) {
+ return (*this)[addr];
+}
+
+void SRAM::write(uint32 addr, uint32 size, uint32 word) {
+ if(size == Word) (*this)[addr] = word;
+ if(size == Half) (*this)[addr] ^= ((*this)[addr] ^ word) & 0xffff << 8*(addr & 2);
+ if(size == Byte) (*this)[addr] ^= ((*this)[addr] ^ word) & 0xff << 8*(addr & 3);
+}
+
+#include "eeprom.cpp"
+#include "fram.cpp"
+#include "flash.cpp"
+
+}
diff --git a/bsnes/nds/memory/memory.hpp b/bsnes/nds/memory/memory.hpp
new file mode 100644
index 00000000..b1f2ed7f
--- /dev/null
+++ b/bsnes/nds/memory/memory.hpp
@@ -0,0 +1,76 @@
+struct Memory {
+ virtual ~Memory();
+ virtual uint32 read(uint32 addr, uint32 size) = 0;
+ virtual void write(uint32 addr, uint32 size, uint32 word) = 0;
+};
+
+struct StaticMemory : Memory {
+ uint8_t *data;
+ unsigned size;
+
+ uint8& operator[](uint32 addr);
+ uint32 read(uint32 addr, uint32 size);
+ void write(uint32 addr, uint32 size, uint32 word);
+ StaticMemory();
+ ~StaticMemory();
+};
+
+// Slot 2 SRAM - 8-bit; bytes only
+struct ByteMemory : Memory {
+ uint8_t *data;
+ unsigned size;
+
+ uint8& operator[](uint32 addr);
+ uint32 read(uint32 addr, uint32 size);
+ void write(uint32 addr, uint32 size, uint32 word);
+ ByteMemory();
+ ~ByteMemory();
+};
+
+// VRAM, Palettes - 16-bit; halves and words
+struct HalfMemory : Memory {
+ uint16_t *data;
+ unsigned size;
+
+ uint16& operator[](uint32 addr);
+ uint32 read(uint32 addr, uint32 size);
+ void write(uint32 addr, uint32 size, uint32 word);
+ HalfMemory();
+ ~HalfMemory();
+};
+
+// OAM, BIOS - 32-bit; halves and words
+struct WordMemory : Memory {
+ uint32_t *data;
+ unsigned size;
+
+ uint32& operator[](uint32 addr);
+ uint32 read(uint32 addr, uint32 size);
+ void write(uint32 addr, uint32 size, uint32 word);
+ WordMemory();
+ ~WordMemory();
+};
+
+// EWRAM - 16-bit; all sizes
+struct SDRAM : Memory {
+ uint16_t *data;
+ unsigned size;
+
+ uint16& operator[](uint32 addr);
+ uint32 read(uint32 addr, uint32 size);
+ void write(uint32 addr, uint32 size, uint32 word);
+ SDRAM();
+ ~SDRAM();
+};
+
+// TCM, IWRAM - 32-bit; all sizes
+struct SRAM : Memory {
+ uint32_t *data;
+ unsigned size;
+
+ uint32& operator[](uint32 addr);
+ uint32 read(uint32 addr, uint32 size);
+ void write(uint32 addr, uint32 size, uint32 word);
+ SRAM();
+ ~SRAM();
+};
diff --git a/bsnes/nds/nds.hpp b/bsnes/nds/nds.hpp
new file mode 100644
index 00000000..72f7d9ae
--- /dev/null
+++ b/bsnes/nds/nds.hpp
@@ -0,0 +1,29 @@
+#ifndef NDS_HPP
+#define NDS_HPP
+
+// dasShiny - Nintendo DS emulator
+// Copyright (c) 2012 Cydrak
+// License: GPLv3
+
+#include
+#include
+
+namespace NintendoDS {
+ enum : unsigned {
+ Byte = 8, Half = 16, Word = 32
+ };
+
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+}
+
+#endif
diff --git a/bsnes/nds/ppu/bg.cpp b/bsnes/nds/ppu/bg.cpp
new file mode 100644
index 00000000..401d0e35
--- /dev/null
+++ b/bsnes/nds/ppu/bg.cpp
@@ -0,0 +1,251 @@
+
+void PPU::renderBgs(unsigned y) {
+ unsigned bpp[4] = {};
+ unsigned mapw[4], maph[4]; // tiled dimensions
+ unsigned affw[4], affh[4]; // Affine dimensions
+ unsigned bitw[4], bith[4]; // Bitmap dimensions
+
+ for(unsigned n = 0; n < 4; n++) {
+ // Tiled dimensions
+ mapw[n] = bg[n].size & 1? 64 : 32;
+ maph[n] = bg[n].size & 2? 64 : 32;
+
+ // Affine settings
+ affw[n] = 16 << bg[n].size;
+ affh[n] = 16 << bg[n].size;
+ bitw[n] = 128 << (bg[n].size - (bg[n].size >= 3)); // 128,256,512,512
+ bith[n] = 128 << (bg[n].size - (bg[n].size >= 2)); // 128,256,256,512
+ bpp[n] = 8 << (bg[n].tiles & 1);
+ }
+
+ if(video.line == 0) {
+ bg[2].linex = bg[2].originx;
+ bg[2].liney = bg[2].originy;
+ bg[3].linex = bg[3].originx;
+ bg[3].liney = bg[3].originy;
+ }
+
+ if(bgMode == 6) {
+ // Large 512 x 1024 x 8bpp bitmap - uses all 512K BG
+ // Supposedly 3D is still available on BG0, though
+ // you'd have no VRAM leftover for textures...
+ bitw[2] = 512 << (bg[2].size & 1);
+ bith[2] = 1024 >> (bg[2].size & 1);
+
+ renderBitmapBg(2, 8, bitw[2], bith[2], y);
+ }
+ else {
+ // BG0 is either tiled or 3D render output
+ // BG1 is always tiled
+ if(bg0FromGPU == 0) renderTiledBg (0, mapw[0], maph[0], y);
+ renderTiledBg (1, mapw[1], maph[1], y);
+
+ // BG2-3 are a selectable mix of:
+ // - Tiled: 16-bit screen blocks with tile attributes
+ // - GBA: 8-bit affine maps, only tile number
+ // - NDS: 16-bit affine maps with tile attributes;
+ // these also work as 8/16-bpp bitmaps
+ //
+ if(bgMode == 0) { // 2 x tiled
+ renderTiledBg (2, mapw[2], maph[2], y);
+ renderTiledBg (3, mapw[3], maph[3], y);
+ }
+ if(bgMode == 1) { // Tiled + GBA
+ renderTiledBg (2, mapw[2], maph[2], y);
+ renderAffineBg(3, 8, affw[3], affh[3], y);
+ }
+ if(bgMode == 2) { // 2 x GBA
+ renderAffineBg(2, 8, affw[2], affh[2], y);
+ renderAffineBg(3, 8, affw[3], affh[3], y);
+ }
+ if(bgMode == 3) { // Tiled + NDS
+ renderTiledBg (2, mapw[2], maph[2], y);
+ if(bg[3].depth == 0) renderAffineBg(3, 16, affw[3], affh[3], y);
+ if(bg[3].depth == 1) renderBitmapBg(3, bpp[3], bitw[3], bith[3], y);
+ }
+ if(bgMode == 4) { // GBA + NDS
+ renderAffineBg(2, 8, affw[2], affh[2], y);
+ if(bg[3].depth == 0) renderAffineBg(3, 16, affw[3], affh[3], y);
+ if(bg[3].depth == 1) renderBitmapBg(3, bpp[3], bitw[3], bith[3], y);
+ }
+ if(bgMode == 5) { // 2 x NDS
+ if(bg[2].depth == 0) renderAffineBg(2, 16, affw[2], affh[2], y);
+ if(bg[3].depth == 0) renderAffineBg(3, 16, affw[3], affh[3], y);
+ if(bg[2].depth == 1) renderBitmapBg(2, bpp[2], bitw[2], bith[2], y);
+ if(bg[3].depth == 1) renderBitmapBg(3, bpp[3], bitw[3], bith[3], y);
+ }
+ }
+
+ bg[2].linex += bg[2].transform.dx_dv;
+ bg[2].liney += bg[2].transform.dy_dv;
+ bg[3].linex += bg[3].transform.dx_dv;
+ bg[3].liney += bg[3].transform.dy_dv;
+}
+
+void PPU::renderTiledBg(unsigned no, unsigned mapw, unsigned maph, unsigned y) {
+ auto &bg = this->bg[no];
+ if(bg.enable == false)
+ return;
+
+ uint32 flags = pxPriority*bg.priority + pxLayer*(2u+no);
+ unsigned line = bg.voffs + y;
+ unsigned finex = bg.hoffs % 8;
+ auto above = &this->above[8 - finex];
+ auto below = &this->below[8 - finex];
+
+ if(blendAbove & 1< 32 && (mapy & 32)) maddr += 32*mapw;
+ if(mapw > 32 && (mapx & 32)) maddr += 32*32;
+
+ bool ext = bg.depth && bgLargePal;
+ unsigned depth = bg.depth? 0x100 : 0x10;
+ unsigned imask = depth-1;
+
+ unsigned extpalbase = 0x1000*no;
+ if(bg.affineWrap) // special case for BG0/BG1 - this bit
+ extpalbase |= 0x2000; // makes them share BG2/BG3's palettes
+
+ for(unsigned x = 0; x < 256+8; ) {
+ uint16 attr = system.vmap.bg(which, 2*maddr>>14)[2*maddr];
+ int pal = (attr>>12)*depth + extpalbase;
+ uint1 vflip = attr>>11;
+ uint1 hflip = attr>>10;
+ uint10 tile = attr;
+
+ int row = line%8;
+ if(vflip) row ^= 7;
+
+ uint32 taddr = 0x10000*bgTileBase + 0x4000*bg.tiles + ((32*tile + 4*row) << bg.depth);
+ auto tref = &system.vmap.bg(which, taddr>>14)[taddr];
+
+ uint64 slice = 0;
+ for(int n = 3; n >= 0; --n)
+ slice = slice<<16 | tref[n];
+
+ int dir = +1;
+ if(hflip) dir = -1, x += 7;
+
+ for(unsigned n = 0; n < 8; n++, x += dir) {
+ if(window[x + 8 - finex] & 1<> 13][pal+index << 1];
+ bgr = (bgr<<3 & 0760000) | (bgr<<2 & 0007600) | (bgr<<1 & 0000076);
+ }
+ if(flags < above[x]) below[x] = above[x], above[x] = flags + bgr;
+ else if(flags < below[x]) below[x] = flags + bgr;
+ }
+ }
+ slice >>= (4 << bg.depth);
+ }
+
+ if(hflip) x += 9;
+
+ if((++maddr & 31) == 0) {
+ maddr -= 32;
+ if(mapw > 32) // wrap to next screen
+ maddr += mapx & 32? -32*32 : +32*32;
+ }
+ }
+}
+
+void PPU::renderAffineBg(unsigned no, unsigned mapDepth, unsigned mapW, unsigned mapH, unsigned y) {
+ auto &bg = this->bg[no];
+ if(bg.enable == false)
+ return;
+
+ bool ext = mapDepth==16 && bgLargePal;
+ uint32 flags = pxPriority*bg.priority + pxLayer*(2+no);
+ int32 fx = bg.linex;
+ int32 fy = bg.liney;
+
+ if(blendAbove & 1<> 8;
+ unsigned my = fy >> 8;
+
+ if(bg.affineWrap)
+ mx &= 8*mapW-1, my &= 8*mapH-1;
+
+ if(mx < 8*mapW && my < 8*mapH) {
+ uint32 addr = 0x10000*bgMapBase + 2*32*32*bg.map + ((mapW*(my/8) + (mx/8)) << (mapDepth == 16));
+ uint16 attr = system.vmap.bg(which, addr>>14)[addr];
+
+ if(mapDepth == 8) {
+ // no special handling - pal, vflip, hflip will all be 0
+ attr = attr >> 8*(mx/8 & 1) & 0xff;
+ }
+ int pal = (attr>>12)*0x100 + no*0x1000;
+ uint1 vflip = attr>>11;
+ uint1 hflip = attr>>10;
+ uint10 tile = attr;
+
+ int row = my%8 ^ 7*vflip;
+ int col = mx%8 ^ 7*hflip;
+
+ uint32 taddr = 0x10000*bgTileBase + 0x4000*bg.tiles + 64*tile + 8*row + col;
+ uint8 index = system.vmap.bg(which, taddr>>14)[taddr] >> 8*(col & 1);
+
+ if(index) {
+ uint32 bgr = bgPal[pal+index & 0xff];
+ if(ext) {
+ bgr = system.vmap.bgpal[which][pal>>13][pal+index << 1];
+ bgr = (bgr<<3 & 0760000) | (bgr<<2 & 0007600) | (bgr<<1 & 0000076);
+ }
+ if(flags < above[x]) below[x] = above[x], above[x] = flags + bgr;
+ else if(flags < below[x]) below[x] = flags + bgr;
+ }
+ }
+ }
+ fx += bg.transform.dx_dh;
+ fy += bg.transform.dy_dh;
+ }
+}
+
+void PPU::renderBitmapBg(unsigned no, unsigned mapDepth, unsigned mapW, unsigned mapH, unsigned y) {
+ auto &bg = this->bg[no];
+ if(bg.enable == false)
+ return;
+
+ uint32 flags = pxPriority*bg.priority + pxLayer*(2+no);
+ int32 fx = bg.linex;
+ int32 fy = bg.liney;
+
+ if(blendAbove & 1<>8, my = fy>>8;
+
+ if(bg.affineWrap)
+ mx &= mapW-1, my &= mapH-1;
+
+ if(mx < mapW && my < mapH) {
+ uint32 addr = 0x4000*bg.map + ((mapW*my + mx) << (mapDepth == 16));
+ uint16 data = system.vmap.bg(which, addr>>14)[addr] >> 8*(addr & 1);
+ uint32 bgr;
+
+ if(mapDepth== 8) bgr = bgPal[data &= 0xff];
+ if(mapDepth==16) bgr = (data<<3&62<<12)|(data<<2&62<<6)|(data<<1&62), data &= 0x8000;
+
+ if(data) {
+ if(flags < above[x]) below[x] = above[x], above[x] = flags + bgr;
+ else if(flags < below[x]) below[x] = flags + bgr;
+ }
+ }
+ }
+ fx += bg.transform.dx_dh;
+ fy += bg.transform.dy_dh;
+ }
+}
diff --git a/bsnes/nds/ppu/obj.cpp b/bsnes/nds/ppu/obj.cpp
new file mode 100644
index 00000000..f1bce309
--- /dev/null
+++ b/bsnes/nds/ppu/obj.cpp
@@ -0,0 +1,159 @@
+
+void PPU::renderObjs(unsigned y) {
+ if(objEnable == false)
+ return;
+
+ for(unsigned n = 0; n < 128; n++) {
+ objinfo& obj = this->obj[n];
+
+ if(obj.renderMode == objinfo::hidden) continue;
+
+ uint8 width = 1 << obj.size;
+ uint8 height = 1 << obj.size;
+ uint8 row = y - obj.y;
+
+ bool wide = obj.shape == objinfo::wide;
+ bool tall = obj.shape == objinfo::tall;
+ bool affine = obj.renderMode & objinfo::affine;
+ bool size = obj.renderMode == objinfo::affineDouble;
+
+ if(obj.size <= 1) width <<= wide, height <<= tall;
+ if(obj.size >= 1) width >>= tall, height >>= wide;
+ if(wide && tall) width = 1, height = 1;
+
+ if(row >= 8*(height << size)) continue;
+ if(obj.x <= -8*(width << size)) continue;
+
+ if(obj.kind == objinfo::bitmap) renderBitmapObj(obj, width, height, row);
+ else renderTiledObj(obj, width, height, row);
+ }
+}
+
+void PPU::renderTiledObj(objinfo& obj, unsigned objw, unsigned objh, unsigned y) {
+ unsigned step = objTileMode? 0+objTileStep : 0;
+ unsigned srow = objTileMode? objw << obj.depth : 32;
+ unsigned tile = obj.index << step;
+
+ uint32 zmask = pxPriority*3u + pxLayer*7u;
+ uint32 flags = pxPriority*obj.priority + pxLayer*1u;
+ bool affine = obj.renderMode & objinfo::affine;
+ bool size = obj.renderMode == objinfo::affineDouble;
+ bool hflip = obj.transform & 8;
+ bool vflip = obj.transform & 16;
+ bool ext = obj.depth && objLargePal;
+ bool win = obj.kind == objinfo::window;
+ unsigned pal = obj.depth? 256*obj.palette : 16*obj.palette;
+ unsigned mask = obj.depth? 0xff : 0x0f;
+
+ if(blendAbove & 1<<4) flags |= pxBlendAbove;
+ if(blendBelow & 1<<4) flags |= pxBlendBelow;
+
+ if(obj.kind == objinfo::blend) flags |= pxBlendForce;
+
+ affineparam tf = { 0x100, 0, 0, 0x100 };
+
+ int32 cx = 8*objw/2, ox = 0 - (cx << size), dw = 8*objw << size;
+ int32 cy = 8*objh/2, oy = y - (cy << size), dh = 8*objh << size;
+
+ if(affine) {
+ tf = objTransform[obj.transform];
+ } else {
+ if(hflip) ox++, tf.dx_dh *= -1;
+ if(vflip) oy++, tf.dy_dv *= -1;
+ }
+
+ int32 fx = ox*tf.dx_dh + oy*tf.dx_dv;
+ int32 fy = ox*tf.dy_dh + oy*tf.dy_dv;
+
+ int x = obj.x + 8;
+ for(unsigned t = 0; t < dw && x < 256+8; x++, t++) {
+ uint32 mx = (fx >> 8) + cx;
+ uint32 my = (fy >> 8) + cy;
+
+ if(mx < 8*objw && my < 8*objh) {
+ unsigned taddr = tile;
+
+ taddr += (my/8)*srow;
+ taddr += (mx/8) << obj.depth; taddr <<= 3;
+ taddr += (my%8) << obj.depth; taddr <<= 2;
+ taddr += (mx%8) >>!obj.depth;
+
+ uint16 data = system.vmap.obj(which, taddr>>14)[taddr];
+
+ if(obj.depth) data = data >> 8*(mx%2) & mask;
+ else data = data >> 4*(mx%4) & mask;
+
+ if(x >= 0 && data) {
+ if(win) {
+ window[x] = min(window[x], 0x20+winArea[2]);
+ }
+ else {
+ uint32 bgr = objPal[pal+data & 0xff];
+ if(ext) {
+ bgr = system.vmap.objpal[which][pal>>13][pal+data << 1];
+ bgr = (bgr<<3 & 0760000) | (bgr<<2 & 0007600) | (bgr<<1 & 0000076);
+ }
+ if(flags < (objLayer[x] & zmask)) objLayer[x] = flags + bgr;
+ }
+ }
+ }
+ fx += tf.dx_dh;
+ fy += tf.dy_dh;
+ }
+}
+
+void PPU::renderBitmapObj(objinfo& obj, unsigned objw, unsigned objh, unsigned y) {
+ unsigned srow = objBitmapMode>1? 16*objw : 256<1) tile <<= 7+objBitmapStep;
+ else tile = 8*srow*(obj.index>>5 & 31) + 16*(obj.index & 31);
+
+ uint32 zmask = pxPriority*3u + pxLayer*7u;
+ uint32 flags = pxPriority*obj.priority + pxLayer*1u + pxAlpha*2u*(obj.palette+1);
+ bool affine = obj.renderMode & objinfo::affine;
+ bool size = obj.renderMode == objinfo::affineDouble;
+ bool hflip = obj.transform & 8;
+ bool vflip = obj.transform & 16;
+ unsigned alpha = obj.palette;
+
+ if(blendAbove & 1<<4) flags |= pxBlendAbove;
+ if(blendBelow & 1<<4) flags |= pxBlendBelow;
+
+ flags |= pxBlendForce + (2*alpha+1)*pxAlpha;
+
+ affineparam tf = { 0x100, 0, 0, 0x100 };
+
+ int32 cx = 8*objw/2, ox = 0 - (cx << size), dw = 8*objw << size;
+ int32 cy = 8*objh/2, oy = y - (cy << size), dh = 8*objh << size;
+
+ if(affine) {
+ tf = objTransform[obj.transform];
+ } else {
+ if(hflip) ox++, tf.dx_dh *= -1;
+ if(vflip) oy++, tf.dy_dv *= -1;
+ }
+
+ int32 fx = ox*tf.dx_dh + oy*tf.dx_dv;
+ int32 fy = ox*tf.dy_dh + oy*tf.dy_dv;
+
+ int x = obj.x + 8;
+ for(unsigned t = 0; t < dw && x < 256+8; x++, t++) {
+ uint32 mx = (fx >> 8) + cx;
+ uint32 my = (fy >> 8) + cy;
+
+ if(mx < 8*objw && my < 8*objh) {
+ unsigned taddr = tile + srow*my + 2*mx;
+
+ uint16 data = system.vmap.obj(which, taddr>>14)[taddr];
+
+ if(x >= 0 && (data & 0x8000)) {
+ uint5 b = data>>10, g = data>>5, r = data>>0;
+
+ if(flags < (objLayer[x] & zmask)) objLayer[x] = flags | b<<13 | g<<7 | r<<1;
+ }
+ }
+ fx += tf.dx_dh;
+ fy += tf.dy_dh;
+ }
+}
diff --git a/bsnes/nds/ppu/ppu.cpp b/bsnes/nds/ppu/ppu.cpp
new file mode 100644
index 00000000..c5197b5d
--- /dev/null
+++ b/bsnes/nds/ppu/ppu.cpp
@@ -0,0 +1,414 @@
+#include
+
+namespace NintendoDS {
+
+PPU ppu[2];
+
+
+
+PPU::PPU() {
+}
+
+void PPU::power() {
+ forceBlank = false;
+
+ bgLargePal = false;
+ bg0FromGPU = false;
+ bgMode = 0;
+ bgTileBase = 0;
+ bgMapBase = 0;
+
+ for(unsigned n = 0; n < 4; n++) {
+ bg[n].enable = false;
+ bg[n].mosaic = false;
+ bg[n].affineWrap = false;
+ bg[n].depth = 0;
+ bg[n].priority = 0;
+ bg[n].size = 0;
+ bg[n].map = 0;
+ bg[n].tiles = 0;
+ bg[n].palette = 0;
+ bg[n].hoffs = 0;
+ bg[n].voffs = 0;
+ bg[n].originx = 0;
+ bg[n].originy = 0;
+ bg[n].linex = 0;
+ bg[n].liney = 0;
+ bg[n].transform.dx_dh = 0;
+ bg[n].transform.dy_dh = 0;
+ bg[n].transform.dx_dv = 0;
+ bg[n].transform.dy_dv = 0;
+ }
+ objEnable = false;
+ objInHBlank = false;
+ objLargePal = false;
+ objTileMode = 0;
+ objTileStep = 0;
+ objBitmapMode = 0;
+ objBitmapStep = 0;
+
+ for(unsigned n = 0; n < 128; n++) {
+ obj[n].kind = objinfo::none;
+ obj[n].renderMode = objinfo::normal;
+ obj[n].mosaic = false;
+ obj[n].depth = 0;
+ obj[n].size = 0;
+ obj[n].shape = objinfo::square;
+ obj[n].transform = 0;
+ obj[n].x = 0;
+ obj[n].y = 0;
+ obj[n].index = 0;
+ obj[n].priority = 0;
+ obj[n].palette = 0;
+ }
+ for(unsigned n = 0; n < 32; n++) {
+ objTransform[n].dx_dh = 0;
+ objTransform[n].dy_dh = 0;
+ objTransform[n].dx_dv = 0;
+ objTransform[n].dy_dv = 0;
+ }
+
+ blendMode = 0;
+ blendAbove = 0;
+ blendBelow = 0;
+ blendAf = 0;
+ blendBf = 0;
+ blendYf = 0;
+
+ for(unsigned n = 0; n < 2; n++) {
+ winX[n][0] = 0; winX[n][1] = 0xff;
+ winY[n][0] = 0; winY[n][1] = 0xff;
+ }
+ winArea[0] = 0; winEnable[0] = false;
+ winArea[1] = 0; winEnable[1] = false;
+ winArea[2] = 0; winEnable[2] = false;
+ winArea[3] = 0;
+}
+
+
+void PPU::scanline() {
+ if(video.line < 192) {
+ // Set up backdrop
+ for(unsigned x = 0; x < 256+16; x++) {
+ above[x] = pxPriority*3u + pxLayer*6u + bgPal[0];
+ below[x] = pxPriority*3u + pxLayer*7u;
+ objLayer[x] = pxPriority*3u + pxLayer*7u;
+
+ if(blendAbove & 1<<5) above[x] |= pxBlendAbove; // can shade backdrop
+ if(blendBelow & 1<<5) above[x] |= pxBlendBelow; // can blend over backdrop
+ }
+
+ // Set up window buffer
+ bool useWindowing = winEnable[0] || winEnable[1] || winEnable[2];
+
+ if(useWindowing) memset(window, 0xc0+winArea[3], 256+16); // initialize with winout
+ else memset(window, 0x3f, 256+16); // draw everything
+
+ for(int w = 1; w >= 0; w--)
+ if(winEnable[w] && winY[w][0] <= video.line && video.line <= winY[w][1] && winX[w][1] > winX[w][0])
+ memset(&window[winX[w][0] + 8], 0x40+winArea[w], winX[w][1] - winX[w][0]);
+
+ // Draw layers
+ if(objEnable)
+ renderObjs(video.line);
+
+ renderBgs(video.line);
+
+
+ // Feed in 3D layer, if requested
+ if(bg[0].enable && bg0FromGPU && which == 0) {
+ auto *gpuOut = &gpu.output[256*video.line];
+
+ uint32 depth = pxPriority*bg[0].priority + pxLayer*2;
+ uint32 flags = pxBlendForce;
+
+ if(blendAbove & 1<<0) flags |= pxBlendAbove;
+ if(blendBelow & 1<<0) flags |= pxBlendBelow;
+
+ for(unsigned x = 0; x < 256; x++) {
+ if(!(window[x+8] & 1<<0)) continue;
+ if(gpuOut[x] < 1*pxAlpha) continue;
+
+ if(depth < above[8+x]) {
+ below[8+x] = above[8+x];
+ above[8+x] = depth | flags | gpuOut[x];
+ }
+ else if(depth < below[8+x]) {
+ below[8+x] = depth | flags | gpuOut[x];
+ }
+ }
+ }
+
+ // Add OBJs, if enabled
+ if(objEnable) {
+ for(unsigned x = 0; x < 256; x++) {
+ if(!(window[x+8] & 1<<4)) continue;
+
+ auto &objPx = objLayer[x+8];
+ auto &abovePx = above[x+8];
+ auto &belowPx = below[x+8];
+
+ if(objPx < abovePx) belowPx = abovePx, abovePx = objPx;
+ else if(objPx < belowPx) belowPx = objPx;
+ }
+ }
+
+ unsigned yf = min(32, 2*blendYf);
+
+ uint64 round = 02000200020;
+ uint64 shade = round;
+ if(blendMode == lighten)
+ shade += 07700770077ull*yf;
+
+ for(unsigned x = 0; x < 256; x++) {
+ auto &abovePx = above[x+8];
+ auto &belowPx = below[x+8];
+
+ unsigned af = min(32, 2*blendAf);
+ unsigned bf = min(32, 2*blendBf);
+
+ bool canShade = (abovePx & pxBlendAbove);
+ bool canBlend = (abovePx & (pxBlendAbove|pxBlendForce)) && (belowPx & pxBlendBelow);
+ bool forceAlpha = (abovePx & pxBlendForce ) && (belowPx & pxBlendBelow);
+ unsigned mode = forceAlpha? alphaBlend : blendMode;
+
+ if(!(mode && (window[x+8] & 1<<5))) {
+ output[x] = abovePx;
+ continue;
+ }
+
+ uint64 a = (abovePx & 0777777)*01000001ull & 07700770077ull;
+ uint64 b = (belowPx & 0777777)*01000001ull & 07700770077ull;
+
+ if(forceAlpha && (abovePx & 31*pxAlpha))
+ af = (abovePx>>18 & 31) + 1, bf = 32-af;
+
+ if(canBlend && mode == alphaBlend) a = (a*af + b*bf + round)/32;
+ else if(canShade && mode > alphaBlend) a = (a*(32 - yf) + shade)/32;
+
+ if(uint32 oflow = a & 010001000100)
+ a |= oflow - (oflow>>6);
+
+ a &= 07700770077;
+ output[x] = (a | a>>18) & 0777777;
+ }
+ }
+}
+
+
+#include "bg.cpp"
+#include "obj.cpp"
+
+
+uint32 PPU::readPalette(uint32 addr) {
+ addr &= ~3;
+ uint32* p = addr < 0x200? &bgPal[addr>>1 & 0xfe] : &objPal[addr>>1 & 0xfe];
+
+ uint5 b0 = p[0]>>13, g0 = p[0]>>7, r0 = p[0]>>1;
+ uint5 b1 = p[1]>>13, g1 = p[1]>>7, r1 = p[1]>>1;
+
+ return b0<<10 | g0<<5 | r0<<0 | b1<<26 | g1<<21 | r1<<16;
+}
+
+void PPU::writePalette(uint32 addr, uint32 size, uint32 data) {
+ uint32 mask = 0xffffffff;
+
+ if(size == Byte) size = Half;
+ if(size == Half) addr &= ~1, mask = 0xffff << 8*(addr & 3);
+ if(size == Word) addr &= ~3;
+
+ uint32* p = addr < 0x200? &bgPal[addr>>1 & 0xfe] : &objPal[addr>>1 & 0xfe];
+
+ uint5 b0 = data>>10, g0 = data>> 5, r0 = data>> 0;
+ uint5 b1 = data>>26, g1 = data>>21, r1 = data>>16;
+
+ if(mask & 0x0000ffff) p[0] = b0<<13 | g0<<7 | r0<<1;
+ if(mask & 0xffff0000) p[1] = b1<<13 | g1<<7 | r1<<1;
+}
+
+uint32 PPU::readOam(uint32 addr) {
+ addr &= ~3;
+
+ objinfo& obj = this->obj[addr/8];
+ affineparam& tf = this->objTransform[addr/32];
+
+ switch(addr & 4) {
+ case 0:
+ return obj.y<<0 | obj.renderMode<<8 | obj.kind<10
+ | obj.mosaic<<12 | obj.depth<<13 | obj.size<<14
+ | obj.x<<16 | obj.transform<<25 | obj.shape<<30;
+
+ case 4:
+ return obj.index<<0 | obj.priority<<10 | obj.palette<<12
+ | tf.m[addr>>3 & 3];
+ }
+}
+
+void PPU::writeOam(uint32 addr, uint32 size, uint32 data) {
+ if(size == Byte) return;
+
+ if(size == Word) {
+ addr &= ~3;
+ writeOam(addr+0, Half, data>>0);
+ writeOam(addr+2, Half, data>>16);
+ return;
+ }
+
+ objinfo& obj = this->obj[addr/8];
+ affineparam& tf = this->objTransform[addr/32];
+
+ switch(addr & 6) {
+ case 0:
+ obj.y = data>>0;
+ obj.renderMode = data>>8;
+ obj.kind = data>>10;
+ obj.mosaic = data>>12;
+ obj.depth = data>>13;
+ obj.shape = data>>14;
+ return;
+
+ case 2:
+ obj.x = data>>0;
+ obj.transform = data>>9;
+ obj.size = data>>14;
+ return;
+
+ case 4:
+ obj.index = data>>0;
+ obj.priority = data>>10;
+ obj.palette = data>>12;
+ return;
+
+ case 6:
+ tf.m[addr>>3 & 3] = data;
+ return;
+ }
+}
+
+
+
+uint32 PPU::regControl() {
+ return bgMode<<0 | bg0FromGPU<<3 | forceBlank<<7 | objInHBlank<<23
+ | objTileMode<<4 | objBitmapMode<<5 | objTileStep<<20 | objBitmapStep<<22
+ | bg[0].enable<<8 | bg[1].enable<<9 | bg[2].enable<<10 | bg[3].enable<<11
+ | objEnable<<12 | winEnable[0]<<13 | winEnable[1]<<14 | winEnable[2]<<15
+ | bgTileBase<<24 | bgMapBase<<27 | bgLargePal<<30 | objLargePal<<31;
+}
+
+void PPU::regControl(uint32 data, uint32 mask) {
+ if(mask & 0x000000ff) {
+ bgMode = data>>0;
+ bg0FromGPU = data>>3;
+ objTileMode = data>>4;
+ objBitmapMode = data>>5;
+ forceBlank = data>>7;
+ }
+ if(mask & 0x0000ff00) {
+ bg[0].enable = data>>8;
+ bg[1].enable = data>>9;
+ bg[2].enable = data>>10;
+ bg[3].enable = data>>11;
+ objEnable = data>>12;
+ winEnable[0] = data>>13;
+ winEnable[1] = data>>14;
+ winEnable[2] = data>>15;
+ }
+ if(mask & 0x00f00000) {
+ objTileStep = data>>20;
+ objBitmapStep = data>>22;
+ objInHBlank = data>>23;
+ }
+ if(mask & 0xff000000) {
+ bgTileBase = data>>24;
+ bgMapBase = data>>27;
+ bgLargePal = data>>30;
+ objLargePal = data>>31;
+ }
+}
+
+uint32 PPU::regBg(unsigned no) {
+ return bg[no].priority<<0
+ | bg[no].tiles<<2 | bg[no].mosaic<<6 | bg[no].depth<<7
+ | bg[no].map<<8 | bg[no].affineWrap<<13 | bg[no].size<<14;
+}
+
+void PPU::regBg(unsigned no, uint32 data, uint32 mask) {
+ //bg0 = 17 00 map 23, size -, tiles --, pri 0, 3D
+ //bg1 = f8 8b map 24, size 3, tiles 02, pri 3, 256 color
+ //bg2 = b0 01 map 16, size 2, tiles 00, pri 1, 16-bit affine
+ //bg3 = b4 0a map 20, size 2, tiles 02, pri 2, 16-bit affine
+ if(mask & 0x00ff) {
+ bg[no].priority = data>>0;
+ bg[no].tiles = data>>2;
+ bg[no].mosaic = data>>6;
+ bg[no].depth = data>>7;
+ }
+ if(mask & 0xff00) {
+ bg[no].map = data>>8;
+ bg[no].affineWrap = data>>13;
+ bg[no].size = data>>14;
+ }
+}
+
+uint32 PPU::regBgOffs(unsigned no) {
+ return bg[no].hoffs | bg[no].voffs<<16;
+}
+
+void PPU::regBgOffs(unsigned no, uint32 data, uint32 mask) {
+ bg[no].hoffs ^= (bg[no].hoffs ^ data) & mask; data >>= 16; mask >>= 16;
+ bg[no].voffs ^= (bg[no].voffs ^ data) & mask;
+}
+
+void PPU::regBgAffine(unsigned no, unsigned index, uint32 data, uint32 mask) {
+ if(index < 2) {
+ bg[no].transform.m[2*index+0] ^= (bg[no].transform.m[2*index+0] ^ data) & mask; data >>= 16; mask >>= 16;
+ bg[no].transform.m[2*index+1] ^= (bg[no].transform.m[2*index+1] ^ data) & mask;
+ }
+ if(index == 2) {
+ bg[no].originx ^= (bg[no].originx ^ data) & mask;
+ bg[no].linex = bg[no].originx;
+ }
+ if(index == 3) {
+ bg[no].originy ^= (bg[no].originy ^ data) & mask;
+ bg[no].liney = bg[no].originy;
+ }
+}
+
+void PPU::regWinDims(unsigned index, uint32 data, uint32 mask) {
+ auto dims = index == 0? winX : winY;
+
+ if(mask & 0x000000ff) dims[0][1] = data>>0;
+ if(mask & 0x0000ff00) dims[0][0] = data>>8;
+ if(mask & 0x00ff0000) dims[1][1] = data>>16;
+ if(mask & 0xff000000) dims[1][0] = data>>24;
+}
+
+uint32 PPU::regWinArea() {
+ return winArea[0] | winArea[1]<<8 | winArea[3]<<16 | winArea[2]<<24;
+}
+
+void PPU::regWinArea(uint32 data, uint32 mask) {
+ if(mask & 0x0000003f) winArea[0] = data>>0 & 0x3f;
+ if(mask & 0x00003f00) winArea[1] = data>>8 & 0x3f;
+ if(mask & 0x003f0000) winArea[3] = data>>16 & 0x3f;
+ if(mask & 0x3f000000) winArea[2] = data>>24 & 0x3f;
+}
+
+uint32 PPU::regBlend() {
+ return blendAbove<<0 | blendMode<<6 | blendBelow<<8;
+}
+
+void PPU::regBlend(unsigned index, uint32 data, uint32 mask) {
+ uint64 maskl = uint64(mask) << 32*index;
+
+ if(maskl & 0x000000003full) blendAbove = data>>0;
+ if(maskl & 0x00000000c0ull) blendMode = data>>6;
+ if(maskl & 0x0000003f00ull) blendBelow = data>>8;
+ if(maskl & 0x00001f0000ull) blendAf = data>>16;
+ if(maskl & 0x001f000000ull) blendBf = data>>24;
+ if(maskl & 0x1f00000000ull) blendYf = data>>0;
+}
+
+
+
+}
\ No newline at end of file
diff --git a/bsnes/nds/ppu/ppu.hpp b/bsnes/nds/ppu/ppu.hpp
new file mode 100644
index 00000000..22049f2b
--- /dev/null
+++ b/bsnes/nds/ppu/ppu.hpp
@@ -0,0 +1,148 @@
+
+struct PPU {
+ PPU();
+
+ void power();
+ void scanline();
+
+ struct objinfo;
+
+ void renderBgs(unsigned y);
+ void renderTiledBg(unsigned no, unsigned mapW, unsigned mapH, unsigned y);
+ void renderAffineBg(unsigned no, unsigned mapDepth, unsigned mapW, unsigned mapH, unsigned y);
+ void renderBitmapBg(unsigned no, unsigned mapDepth, unsigned mapW, unsigned mapH, unsigned y);
+
+ void renderObjs(unsigned y);
+ void renderTiledObj (objinfo& obj, unsigned objw, unsigned objh, unsigned y);
+ void renderBitmapObj(objinfo& obj, unsigned objw, unsigned objh, unsigned y);
+
+ uint32 readPalette(uint32 addr);
+ void writePalette(uint32 addr, uint32 size, uint32 data);
+
+ uint32 readOam(uint32 addr);
+ void writeOam(uint32 addr, uint32 size, uint32 data);
+
+ uint32 regControl();
+ void regControl(uint32 data, uint32 mask);
+
+ uint32 regBg(unsigned no);
+ void regBg(unsigned no, uint32 data, uint32 mask);
+
+ uint32 regBgOffs(unsigned no);
+ void regBgOffs(unsigned no, uint32 data, uint32 mask);
+
+ void regBgAffine(unsigned no, unsigned index, uint32 data, uint32 mask);
+
+ void regWinDims(unsigned index, uint32 data, uint32 mask);
+
+ uint32 regWinArea();
+ void regWinArea(uint32 data, uint32 mask);
+
+ uint32 regBlend();
+ void regBlend(unsigned index, uint32 data, uint32 mask);
+
+ // PPU #0: PPU #1:
+ // Has access to VRAM banks 0..6 More limited features
+ // BG0 can source 3D GPU output Has access to VRAM banks 2,3,7,8
+ // Can use frame- and render-buffers Max 128K BG, 128K OBJ
+ // Max 512K BG, 256K OBJ
+ int which;
+ uint1 powered;
+
+ // Internal pixel format: pplllMBAF aaaaa bbbbbb gggggg rrrrrr
+ enum {
+ pxPriority = 1<<30, // p - from BG control
+ pxLayer = 1<<27, // l - 1: OBJ, 2..5:BG, 6:backdrop
+ pxMosaic = 1<<26, // M
+ pxBlendBelow = 1<<25, // B
+ pxBlendAbove = 1<<24, // A
+ pxBlendForce = 1<<23, // F - for 3D/OBJ pixel
+ pxAlpha = 1<<18, // a - alpha (0=solid)
+ };
+
+ uint32 output[256];
+
+ uint32 above[256 + 16];
+ uint32 below[256 + 16];
+ uint32 objLayer[256 + 16];
+
+ uint32 bgPal[256];
+ uint32 objPal[256];
+
+ union affineparam {
+ struct {
+ int16 dx_dh, dx_dv; // A, B
+ int16 dy_dh, dy_dv; // C, D
+ };
+ int16 m[4];
+ };
+
+ struct bginfo {
+ uint1 enable;
+ uint1 mosaic, depth;
+ uint1 affineWrap;
+ uint2 priority;
+ uint2 size;
+ uint5 map; // 2K offset for maps / 16K for bitmaps
+ uint4 tiles; // 16K offset for tiles
+ uint2 palette; // 8K offset for large palette mode
+
+ uint9 hoffs, voffs; // Tiled scrolling
+ int32 originx, originy; // Affine settings
+ int32 linex, liney;
+ affineparam transform;
+ };
+
+ struct objinfo {
+ uint2 kind; enum { none=0, blend=1, window=2, bitmap=3 };
+ uint2 renderMode; enum { normal=0, affine=1, hidden=2, affineDouble=3 };
+ uint1 mosaic;
+ uint1 depth;
+ uint2 size;
+ uint2 shape; enum { square=0, wide=1, tall=2 };
+ uint5 transform; enum { hflip=8, vflip=16 };
+ int9 x;
+ uint8 y;
+ uint10 index;
+ uint2 priority;
+ uint4 palette; // subpalette for tiled; alpha for bitmap sprites
+ };
+
+ uint1 forceBlank;
+
+ uint1 bgLargePal; // 256-color BGs use system.vmap.bgpal
+ uint1 bg0FromGPU; // Display 3D rendering on BG0
+ uint3 bgMode; // Determines affine vs. tiled layers
+ uint3 bgTileBase; // 64K starting base for tiles
+ uint3 bgMapBase; // 64K starting base for maps
+ uint4 bgMosaicX;
+ uint4 bgMosaicY;
+ bginfo bg[4];
+
+ uint1 objEnable;
+ uint1 objInHBlank;
+ uint1 objLargePal; // 256-color OBJs use system.vmap.objpal
+ uint1 objTileMode; // 0 = 256x256 px sprite sheet, 1 = linear
+ uint2 objBitmapMode; // 0 = 128x256, 1 = 256x256, 2..3 = linear
+ uint2 objTileStep; // tile index << in linear mode
+ uint1 objBitmapStep; //
+ uint4 objMosaicX;
+ uint4 objMosaicY;
+ objinfo obj[128];
+
+ affineparam objTransform[32];
+
+ uint1 winEnable[3]; // [win0, win1, winobj, winout]
+ uint8 winArea[4]; // BLD, OBJ, BG3..BG0
+ uint8 winX[2][2]; //
+ uint8 winY[2][2]; // not uint9 - Nintendo's oversight
+ uint8 window[256+16]; // window no.<<6 | area
+
+ uint2 blendMode; enum { alphaBlend=1, lighten=2, darken=3 };
+ uint6 blendAbove; // BG0..BG3, OBJ, lignten/darken BD
+ uint6 blendBelow; // BG0..BG3, OBJ, blend over BD
+ uint5 blendAf, blendBf; // alphaBlend coefficients
+ uint5 blendYf; // lighten/darken coefficient
+};
+
+extern PPU ppu[2];
diff --git a/bsnes/nds/slot1/slot1.cpp b/bsnes/nds/slot1/slot1.cpp
new file mode 100644
index 00000000..f30232d9
--- /dev/null
+++ b/bsnes/nds/slot1/slot1.cpp
@@ -0,0 +1,244 @@
+#include
+
+namespace NintendoDS {
+
+Slot1 slot1;
+
+
+Slot1::Slot1() {
+ card = nullptr;
+}
+
+void Slot1::power() {
+ if(card) {
+ card->power();
+ if(card->spi)
+ card->spi->power();
+ }
+ enable = true;
+
+ decryptLatency = 0;
+ responseLatency = 0;
+ xorData = 0;
+ xorCmds = 0;
+ dataReady = 0;
+ blockSize = 0;
+ clock = 0;
+ secureMode = 0;
+ transferPending = 0;
+ transferIrq = 0;
+ transferLength = 0;
+
+ command = 0;
+ lfsr[0] = 0;
+ lfsr[1] = 0;
+
+ spi.data = 0;
+ spi.baud = 0;
+ spi.hold = 0;
+ spi.busy = 0;
+ spi.enable = 0;
+}
+
+void Slot1::load(GameCard* card) {
+ this->card = card;
+ if(card->spi)
+ card->spi->power();
+}
+
+GameCard* Slot1::unload() {
+ //if(card && card->spi)
+ // card->spi->select(false);
+
+ auto r = card;
+ card = nullptr;
+ return r;
+}
+
+
+void Slot1::startRomTransfer() {
+ transferPending = true;
+ transferLength = 0;
+
+ if(blockSize == 7) transferLength = 4;
+ else if(blockSize) transferLength = 512 << (blockSize-1);
+
+ if(transferLength) dataReady = true;
+ else transferPending = false;
+
+ if(card) card->command(command);
+
+ // Hack for now, until we implement timing. Should test whether the ARM9
+ // halts during this entire DMA - one complete word transfers every 40 or
+ // 64 clocks at 66MHz.
+ CPUCore *arm = arm9.slot1access? (CPUCore*)&arm9 : (CPUCore*)&arm7;
+ //while(transferLength > 0 && arm->dmaTrigger(0xf, 5)) /**/;
+ int ch = -1;
+ for(unsigned n = 0; n < 4; n++)
+ if(arm->dma[n].enable && arm->dma[n].trigger == 5)
+ ch = n;
+
+ while(ch >= 0 && transferLength > 0)
+ arm->dmaTransfer(ch);
+}
+
+uint8 Slot1::readRom() {
+ uint8 data = 0xff;
+
+ if(transferLength) {
+ // Empty slot simply returns 0xff
+ if(card) data = card->read();
+
+ if(!--transferLength) {
+ dataReady = false;
+ transferPending = false;
+
+ if(transferIrq) {
+ if(arm9.slot1access == 0) arm7.interrupt.flags |= CPUCore::irqCardDone;
+ if(arm9.slot1access == 1) arm9.interrupt.flags |= CPUCore::irqCardDone;
+ }
+ }
+ }
+ return data;
+}
+
+uint8 Slot1::spiTransfer(uint8 data) {
+ if(!card || !card->spi)
+ return 0xff;
+
+ auto device = card->spi;
+ device->select(true);
+ uint8 r = device->transfer(data);
+ device->select(spi.hold);
+ return r;
+}
+
+
+GameCard::~GameCard() {
+ delete spi;
+}
+
+GameCard::GameCard(uint32 id) {
+ rom.size = 0x10000;
+ rom.data = new uint8[rom.size];
+ memset(rom.data, 0xff, rom.size);
+
+ size = bit::round(rom.size);
+ chipId = id;
+ spi = nullptr;
+}
+
+GameCard::GameCard(const stream& memory, uint32 esize, uint32 id) {
+ rom.size = esize;
+ rom.data = new uint8[rom.size];
+ memset(rom.data, 0xff, rom.size);
+ memory.read(rom.data, min(memory.size(), rom.size));
+
+ size = bit::round(rom.size);
+ sha256 = nall::sha256(rom.data, rom.size);
+ chipId = id;
+ spi = nullptr;
+}
+
+void GameCard::power() {
+ state = idle;
+}
+
+void GameCard::command(uint64 command) {
+ if((command>>56) == 0xb7) {
+ state = readData;
+ offset = command>>24 & 0x00000fff;
+ block = command>>24 & 0xfffff000;
+ block &= size-1;
+
+ // Once initialized, forbid reading the header and startup code.
+ if(block < 0x8000) block += 0x8000;
+ }
+ if((command>>56) == 0xb8) {
+ state = readId;
+ offset = 0;
+ }
+}
+
+uint8 GameCard::read() {
+ uint8 r = 0xff;
+
+ if(state == readData) {
+ // We remain in this state indefinitely, until the next command.
+ // However, reading from most (?) game cards wraps at 4K intervals.
+ uint32 addr = (block + offset++) & size-1;
+ offset &= 0xfff;
+
+ // Cards come in 2^n ROM sizes, however many images have the empty space
+ // trimmed off. Homebrew images aren't even padded out! Rather than waste
+ // memory, just check for this and return $ff.
+ if(addr < rom.size)
+ r = rom.data[addr];
+ }
+
+ if(state == readId) {
+ // Need to ensure the matching ID is in RAM or games won't run
+ // (where does the firmware put it?)
+ r = 0;/**/chipId >> 8*offset++;
+ offset &= 3;
+ }
+ return r;
+}
+
+
+
+void IRPort::power() {
+ bypass = false;
+ command = 0;
+ if(slave)
+ slave->power();
+}
+
+void IRPort::select(bool state) {
+ if(bypass) {
+ slave->select(state);
+ }
+ if(state == false) {
+ bypass = false;
+ command = 0;
+ }
+}
+
+uint8 IRPort::transfer(uint8 data) {
+ if(bypass) {
+ // Pass transfers through to flash memory
+ if(slave) return slave->transfer(data);
+ else return 0xff;
+ }
+
+ if(command == 0x00) {
+ command = data;
+
+ // Engage passthrough mode - allows access to save data.
+ if(command == 0x00) {
+ bypass = true;
+ return 0xff;
+ }
+
+ if(command == 0x01) {
+ // Receive? HG/SS expect an 8-bit packet size,
+ // then 0..185 bytes, all XORed with $aa.
+ return 0x00;
+ }
+
+ if(command == 0x02) {
+ // Write a packet, maybe to transmit buffer
+ return 0xff;
+ }
+
+ if(command == 0x08) {
+ // ID of some kind? Is it even a valid command?
+ // Returns $aa after powerup - haven't tested the Pokewalker with it.
+ // Pokemon HG/SS frequently check this, even when not communicating.
+ return 0xaa;
+ }
+ }
+ return 0xff;
+}
+
+}
diff --git a/bsnes/nds/slot1/slot1.hpp b/bsnes/nds/slot1/slot1.hpp
new file mode 100644
index 00000000..05219ef6
--- /dev/null
+++ b/bsnes/nds/slot1/slot1.hpp
@@ -0,0 +1,113 @@
+
+struct GameCard;
+struct SPIDevice;
+
+// Pins 1-17: GND, Clock, -, /ROM, /RESET, /SPI, /IRQ, VCC, D0-D7, GND
+//
+// This is a hybrid serial-parallel bus, one byte transferred each clock.
+// Both the cards and the slot support XOR obfuscation using a 39-bit LFSR,
+// and some commands are further encrypted via a Blowfish variant.
+//
+// Transfer rates are 33MHz /5 or /8, which is 4-6MB/sec, and there's a
+// 32-bit buffer making it possible to DMA straight to VRAM. For perspective,
+// 6MB/s is enough to stream 256x192x16bpp video + audio at 60fps.
+
+struct Slot1 {
+ Slot1();
+ void power();
+ void load(GameCard* card);
+ GameCard* unload();
+
+ void startRomTransfer();
+ uint8 readRom();
+ uint8 spiTransfer(uint8 data);
+
+ GameCard *card;
+
+ uint1 enable;
+
+ // ROM interface
+ uint1 clock; // 33MHz / {5, 8}
+ uint13 decryptLatency; // clocks to wait for card to decrypt command
+ uint6 responseLatency; // clocks to wait for response (data buffering?)
+ uint2 xorData; // XOR data received (2 bits?)
+ uint1 xorCmds; // XOR commands sent
+ uint1 dataReady; // 32 bits buffered and ready in read port
+ uint3 blockSize; // {0, 512 bytes (usual), 1K-16K, 32 bits}
+ uint1 secureMode; // ?
+ uint1 transferIrq; // generate IRQ at end of block
+ uint1 transferPending; // still more bytes to transfer?
+ uint32 transferLength; // # bytes remaining
+
+ uint64 command; // latch holding 8 command bytes for next transfer
+ uint64 lfsr[2]; // registers used to obfuscate communication
+
+ // Serial interface for EEPROM, flash, and peripheral access.
+ // Each transfer writes and reads 8 bits, one bit per clock.
+ // Pins D6/D7 do double duty as data in/out respectively.
+ struct SPI {
+ uint8 data; // read from last transfer
+ uint2 baud; // 4MHz >> n
+ uint1 enable, busy, hold;
+ } spi;
+};
+
+struct GameCard {
+ virtual ~GameCard();
+ GameCard(uint32 id);
+ GameCard(const stream& memory, uint32 size, uint32 id);
+
+ virtual void power();
+ virtual void command(uint64 command);
+ virtual uint8 read();
+
+ int state; enum { idle, readData, readId };
+ uint32 block; // 4K block for reading
+ uint32 offset; // byte offset
+ uint32 size; // power of 2 rom size
+ uint64 lfsr[2]; // for obfuscation
+ uint32 chipId;
+ string sha256;
+
+ StaticMemory rom;
+ SPIDevice *spi;
+};
+
+struct IRPort : SPIDevice {
+ IRPort() : slave(nullptr) { }
+ IRPort(SPIDevice *slave) : slave(slave) { }
+
+ void power();
+ void select(bool state);
+ uint8 transfer(uint8 data);
+
+ SPIDevice *slave;
+ bool bypass;
+ uint8 command;
+};
+
+struct S1EEPROM : SPIDevice, StaticMemory {
+ void select(bool state);
+ uint8 transfer(uint8 data);
+
+ int state; enum { idle, params, dataIo };
+ uint8 command; enum {
+ cmdWriteDisable, cmdWriteEnable, // 0x04, 0x06
+ cmdWriteStatus, cmdReadStatus, // 0x01, 0x05
+ cmdWrite, cmdRead, // 0x02, 0x03
+ cmdReadID, // 0x9f
+ };
+ uint8 numArgs;
+ uint32 offset;
+
+ // Status register
+ uint1 busy;
+ uint1 writeEnable;
+ uint2 writeProtect;
+ uint1 statusLock;
+
+ uint1 unlockable; // /W pin, presumably enabled on game cards
+};
+
+
+extern Slot1 slot1;
diff --git a/bsnes/nds/slot2/slot2.cpp b/bsnes/nds/slot2/slot2.cpp
new file mode 100644
index 00000000..e69de29b
diff --git a/bsnes/nds/slot2/slot2.hpp b/bsnes/nds/slot2/slot2.hpp
new file mode 100644
index 00000000..e69de29b
diff --git a/bsnes/nds/system/clock.cpp b/bsnes/nds/system/clock.cpp
new file mode 100644
index 00000000..3ddd7376
--- /dev/null
+++ b/bsnes/nds/system/clock.cpp
@@ -0,0 +1,239 @@
+
+Clock::~Clock() { }
+
+Clock::Clock() {
+ stoppedSec = 0;
+ stoppedUSec = 0;
+}
+
+void Clock::reset() {
+ status1 = 0; year = 0; hour = 0;
+ status2 = 0; month = 1; minute = 0;
+ adjust = 0; day = 1; second = 0;
+ userByte = 0; weekday = 0;
+
+ for(int i = 0; i < 2; i++)
+ for(int j = 0; j < 3; j++)
+ alarm[i].setting[j] = 0;
+}
+
+void Clock::power() {
+ secondsTickPending = hold = false;
+ intr[0] = intr[1] = lag = 0;
+ lastClk = lastCs = output = false;
+ command = buffer = nbits = dataOut = 0;
+
+ // The clock is 32768 Hz but we need twice that, because serial
+ // interrupts are edge sensitive.
+ event.action = [&]() {
+ tick();
+ arm7.event.queue.add(2*33513982/(2*32768), event);
+ };
+ arm7.event.queue.add(2*33513982/(2*32768), event);
+}
+
+uint4 Clock::io(uint4 pins) {
+ uint1 dataIn = pins>>0;
+ uint1 clk = pins>>1;
+ uint1 cs = pins>>2;
+
+ if(cs != lastCs && !(lastCs = cs)) {
+ command = nbits = 0;
+ output = false;
+ return 0xf;
+ }
+ // Wait for falling CLK edge with CS high..
+ if(clk != lastClk && !(lastClk = clk)) {
+ // Rotate data through the buffer
+ dataOut = buffer;
+ buffer = dataIn<<7 | buffer>>1;
+
+ if(++nbits == 0) {
+ // Have we got a full byte to act on?
+
+ // Accept a new command. They're MSB first, unlike data:
+ if(!command && (buffer & 0x0f) == 6) { // 0110
+ command = buffer & 0x7f; // ccc
+ output = buffer & 0x80; // D
+ index = 0;
+
+ // Prevent the time changing while read
+ if(command == 0x26 || command == 0x66)
+ hold = true;
+
+ if(output == false) return 0xf;
+ else /*fall through and latch output byte for reading*/;
+ }
+ if(command == 0x06) field(status1, resetBit|hourMode);
+ if(command == 0x46) field(status2, int1Mode|int2Mode|testMode);
+ if(command == 0x26) dateTime();
+ if(command == 0x66) dateTime();
+ if(command == 0x16) alarmTime(0);
+ if(command == 0x56) alarmTime(1);
+ if(command == 0x36) field(adjust, 0xff);
+ if(command == 0x76) field(userByte, 0xff);
+ }
+ }
+ return output? dataOut | 0xe : 0xf;
+}
+
+
+
+void Clock::field(uint8& src, uint8 mask) {
+ if(command == 0x06 && output == 0 && (buffer & resetBit)) {
+ reset(); buffer &= ~resetBit;
+ }
+ if(output) buffer = src;
+ else src ^= (src ^ buffer) & mask;
+}
+
+void Clock::dateTime() {
+ if(index >= 7) return;
+ if(command == 0x66) // start from time field
+ index = max(4, index);
+
+ bool fixHour = !(status1 & hourMode) && index == 4;
+
+ if(output) {
+ buffer = time[index++];
+ if(fixHour && buffer >= 0x12)
+ buffer += 0x40 - 0x12; // Convert back to 12-hour + AM/PM
+ return;
+ }
+ time[index] = buffer; // Should correct these properly..
+ if(fixHour && (buffer & 0x40))
+ time[index] += 0x12 - 0x40; // Convert from 12-hour mode
+ index++;
+}
+
+void Clock::alarmTime(unsigned no) {
+ if(index >= 3) return;
+ if(output) buffer = alarm[no].setting[index++];
+ else alarm[no].setting[index++] = buffer;
+}
+
+
+
+bool Clock::incBCD(uint8& val, uint8 first, uint8 last) {
+ val++;
+ if((val & 0x0f) == 0x0a) val += 0x06;
+ if((val & 0xf0) == 0xa0) val += 0x60;
+ if(val > last) val = first;
+ return val == first; // carry out
+}
+
+void Clock::tick() {
+ bool previously = intr[0] | intr[1];
+
+ if(++counter == 0)
+ secondsTickPending = true;
+
+ // Ticks can be held for up to 500 ms while reading the time.
+ if(secondsTickPending && (hold == false || counter >= 2*16384)) {
+ lag = counter;
+ tickSecond();
+ }
+
+ switch(status2 & int2Mode /*0..1*/) {
+ case 0: intr[1] = 0; break;
+ default: break; // Alarm 2 - checked in tickSecond
+ }
+
+ switch(status2 & int1Mode /*0..15*/) {
+ case 0: intr[0] = 0; break;
+ case 4: break; // Alarm 1 - checked in tickSecond
+
+ case 1: /**/;
+ case 5: // Selectable frequency - often used as seconds interrupt.
+ intr[0] = 0; // /IRQ output is the AND of the selected divisors.
+ for(unsigned divisor = 0; divisor <= 4; divisor++) // 1..16 Hz
+ intr[0] |= (~counter >> 15-divisor) & (alarm[0].minute >> divisor) & 1;
+ break;
+
+ case 2: /**/; // Start-of-minute interrupts
+ case 6: intr[0] |= !second && counter-lag < 2*4u; break; // latched
+ case 3: intr[0] = second < 0x30; break; // 30 sec duty
+ case 7: intr[0] = counter-lag < lag+2*128u; break; // 128 ticks duty
+
+ default: intr[0] = !(counter & 1<<0); break; // 32KHz clock
+ }
+
+ if(intr[0]) status1 |= int1Flag;
+ if(intr[1]) status1 |= int2Flag;
+
+ bool interrupt = intr[0] | intr[1];
+
+ if(arm7.sio.irq && interrupt && previously == false) {
+ //arm7.raiseIrq(CPUCore::irqClock);
+ arm7.interrupt.flags |= CPUCore::irqClock;
+ }
+}
+
+void Clock::tickSecond() {
+ secondsTickPending = false;
+
+ if( incBCD(second, 0, 0x59)
+ && incBCD(minute, 0, 0x59)
+ && incBCD(hour, 0, 0x23))
+ tickDay();
+
+ // Check alarms - not sure how this is supposed to work yet.
+ // The datasheet implies this is checked each minute, something like:
+ // d:hh:mm weekly d:**:mm hourly for one day a week?
+ // *:hh:mm daily d:**:** every minute for one day a week?
+ // *:**:mm hourly? d:hh:** every minute for one hour on one day?
+ // *:**:** every minute? *:hh:** every minute for one hour a day
+ if(second == 0x00) {
+ bool enable[2] = {
+ (status2 & int1Mode) == 4, // Alarm 1
+ (status2 & int2Mode) != 0, // Alarm 2
+ };
+ // Triggered at start of minute; cleared by disabling alarm
+ for(unsigned i = 0; i < 2; i++)
+ if(enable[i]
+ && (weekday == (alarm[i].weekday & 0x07) || alarm[i].weekday < 0x80)
+ && (hour == (alarm[i].hour & 0x1f) || alarm[i].hour < 0x80)
+ && (minute == (alarm[i].minute & 0x3f) || alarm[i].minute < 0x80))
+ intr[i] = 1;
+
+ }
+}
+
+void Clock::tickDay() {
+ if(++weekday == 7) weekday = 0;
+
+ unsigned y = 10*(year>>4) + (year & 15);
+ unsigned daysIn[32] = { 0, // (invalid)
+ 0x31,0x28+!(y % 4), // Jan..Feb
+ 0x31,0x30,0x31,0x30,0x31, // Mar..Jul
+ 0x31,0x30, 0,0,0,0,0,0, // Aug..Sep (+ invalid months)
+ 0x31,0x30,0x31 // Oct..Dec
+ };
+ incBCD(day, 1, daysIn[month & 31])
+ && incBCD(month, 1, 0x12)
+ && incBCD(year, 0, 0x99);
+}
+
+
+void Clock::thaw(int64 curSec, int64 curUSec) {
+ // Calculate time elapsed while the emulation wasn't running..
+ // Then advance RTC to make up for it.
+ int64 secs = curSec - stoppedSec;
+ int64 usecs = curUSec - stoppedUSec;
+ if(usecs < 0) secs -= 1, usecs += 1000000;
+
+ int32 ticks = counter + usecs * 32768/1000000;
+ counter = ticks;
+ if(ticks >= 32768) secs += 1;
+
+ while(secs > 86400) { secs -= 86400; tickDay(); }
+ while(secs > 0) { secs -= 1; tickSecond(); }
+
+ stoppedSec = curSec;
+ stoppedUSec = curUSec;
+}
+
+void Clock::freeze(int64 curSec, int64 curUSec) {
+ stoppedSec = curSec;
+ stoppedUSec = curUSec;
+}
diff --git a/bsnes/nds/system/eventqueue.hpp b/bsnes/nds/system/eventqueue.hpp
new file mode 100644
index 00000000..6ae71226
--- /dev/null
+++ b/bsnes/nds/system/eventqueue.hpp
@@ -0,0 +1,120 @@
+
+template struct Event_of {
+ uint32 time;
+ uint32 node;
+ T action;
+
+ Event_of() : time(0), node(0) {}
+ Event_of(T action) : time(0), node(0), action(action) {}
+ inline bool operator<(const Event_of& rhs) const { return time - rhs.time >= 0x80000000u; }
+ inline bool operator<(uint32 rhs) const { return time - rhs >= 0x80000000u; }
+};
+
+template struct EventQueue_of {
+ typedef Event_of Elem;
+
+ uint32 time;
+
+ EventQueue_of(uint32 capacity) : size(0), time(0) {
+ //items.reserve(capacity+1); // to simplify math, items[0] is unused
+ for(unsigned n = 0; n < capacity+1; n++)
+ items[n] = nullptr;
+ }
+
+ void reset() {
+ clear();
+ time = 0;
+ }
+ void clear() {
+ for(unsigned n = 1; n <= size; n++) {
+ items[n]->node = 0;
+ items[n] = nullptr;
+ }
+ size = 0;
+ }
+ bool valid(uint32 n = 1) {
+ return (2*n+0 > size || *(items[n]) < items[2*n+0]->time+1 && valid(2*n+0))
+ && (2*n+1 > size || *(items[n]) < items[2*n+1]->time+1 && valid(2*n+1));
+ }
+ void add(uint32 dt, Elem& e) {
+ if(e.node) {
+ remove(e);
+ return add(dt, e);
+ }
+ uint32 old = e.time;
+ e.time = time + dt;
+ e.node = ++size;
+ bubble(e);
+ if(valid() == false) asm volatile("\n\t int $3");
+ }
+ void remove(Elem& e) {
+ if(e.node == 0) return;
+
+ items[e.node] = items[size];
+ items[e.node]->node = e.node;
+ items[size--] = nullptr;
+
+ if(size > 1 && e.node <= size) {
+ Elem& m = *(items[e.node]);
+
+ if(m < e) {
+ // This can happen if removing something besides the min element.
+ bubble(m);
+ if(valid() == false) asm volatile("\n\t int $3");
+ }
+ else {
+ while(2*m.node <= size) {
+ uint32 l = 2*m.node;
+ uint32 r = 2*m.node + (l < size);
+ uint32 c = *(items[r]) < *(items[l])? r : l;
+
+ if(!(*(items[c]) < m)) break;
+
+ items[m.node] = items[c];
+ items[m.node]->node = m.node;
+ m.node = c;
+ }
+ items[m.node] = &m;
+ if(valid() == false) asm volatile("\n\t int $3");
+ }
+ }
+ e.node = 0;
+ }
+
+ inline void step(uint32 ticks) {
+ ticks += time; // relative -> absolute time
+ time = ticks; // default case for early out
+
+ // Caution! We're running under the assumption our queue is never empty.
+ // Fortunately, due to audio/video events, that's true in dasShiny.
+ // Gives around 16% speedup in some cases.
+ if(!(*(items[1]) < ticks)) return; // early out, nothing to do
+
+ auto &next = items[1];
+ do {
+ Elem& e = *next;
+ time = e.time; // update the time so add()
+ remove(e); // works during the callback.
+ e.action();
+ } while(/*size && */*next < ticks);
+
+ if(time - ticks >= 0x80000000u)
+ time = ticks;
+ }
+
+//private:
+ //linear_vector items;
+ Elem* items[64];
+ uint32 size;
+
+ void bubble(Elem& e) {
+ while(1 < e.node && e < *(items[e.node/2])) {
+ items[e.node] = items[e.node/2];
+ items[e.node]->node = e.node;
+ e.node /= 2;
+ }
+ items[e.node] = &e;
+ }
+
+ EventQueue_of();
+};
diff --git a/bsnes/nds/system/powermgr.cpp b/bsnes/nds/system/powermgr.cpp
new file mode 100644
index 00000000..cfb56820
--- /dev/null
+++ b/bsnes/nds/system/powermgr.cpp
@@ -0,0 +1,14 @@
+
+PowerMgr::~PowerMgr() { }
+
+void PowerMgr::power() {
+
+}
+
+void PowerMgr::select(bool state) {
+
+}
+
+uint8 PowerMgr::transfer(uint8 data) {
+ return 0;
+}
diff --git a/bsnes/nds/system/system.cpp b/bsnes/nds/system/system.cpp
new file mode 100644
index 00000000..cc2b6c7c
--- /dev/null
+++ b/bsnes/nds/system/system.cpp
@@ -0,0 +1,537 @@
+#if !defined(_WIN32)
+ #include
+ #include
+#else
+ // Suppress mingw's timeval which uses 32-bit longs
+ #define _TIMEVAL_DEFINED
+ #include
+ #include
+ #include
+
+ struct timeval {
+ int64_t tv_sec, tv_usec;
+ };
+ #define timegm(tm) _mkgmtime64(tm)
+ #define gmtime(tv) _gmtime64(tv)
+ #define gettimeofday(tv,tz) gettimeofday64(tv,tz)
+
+ int gettimeofday64(struct timeval *tv, struct timezone *tz) {
+ FILETIME ft;
+ GetSystemTimeAsFileTime(&ft); // UTC in 100ns units
+
+ // UNIX epoch: Jan 1 1970
+ // Windows epoch: Jan 1 1601
+ //
+ // 1970 - 1601 = 369 years = 11636784000 sec
+ // 89 leap years => +89 days = +7689600 sec
+ int64_t diff = 11644473600LL * 10000000LL;
+ int64_t ns = ft.dwLowDateTime + ft.dwHighDateTime * (1LL<<32) - diff;
+
+ tv->tv_sec = ns / 10000000;
+ tv->tv_usec = ns % 10000000 / 10;
+ }
+#endif
+
+
+namespace NintendoDS {
+
+System system;
+
+
+SPIDevice::~SPIDevice() { }
+
+
+VRAMMapping::VRAMMapping() {
+ data = nullptr; size = 0;
+ dirtyBits = nullptr;
+}
+VRAMMapping::VRAMMapping(HalfMemory& target, uint8 *dirtyBits, unsigned pageno)
+ : dirtyBits(dirtyBits + pageno*256/0x4000)
+{
+ data = target.data + 0x4000/2*pageno; size = 0;
+}
+VRAMMapping::~VRAMMapping() {
+ data = nullptr; size = 0;
+ dirtyBits = nullptr;
+}
+
+uint16& VRAMMapping::operator[](uint32 addr) {
+ return data? data[addr>>1 & 0x1fff]
+ : system.unmappedVram[addr>>1 & 0x1fff];
+}
+
+uint32 VRAMMapping::read(uint32 addr, uint32 size) {
+ if(!data) return 0;
+ return HalfMemory::read(addr & 0x3fff, size);
+}
+void VRAMMapping::write(uint32 addr, uint32 size, uint32 word) {
+ if(!data) return; HalfMemory::write(addr & 0x3fff, size, word);
+ if(!dirtyBits) return; dirtyBits[(addr & 0x3fff)/256] = 0xff;
+}
+bool VRAMMapping::dirty(uint32 addr) {
+ return dirtyBits && dirtyBits[(addr & 0x3fff)/256];
+}
+
+
+System::System() {
+ firmware.data = new uint8 [(firmware.size = 0x080000)/1]();
+
+ ewram.data = new uint16[(ewram.size = 0x400000)/2];
+ iwram.data = new uint32[(iwram.size = 0x010000)/4];
+ swram[0].data = new uint32[(swram[0].size = 0x004000)/4];
+ swram[1].data = new uint32[(swram[1].size = 0x004000)/4];
+
+ vram[0].data = new uint16[(vram[0].size = 0x020000)/2];
+ vram[1].data = new uint16[(vram[1].size = 0x020000)/2];
+ vram[2].data = new uint16[(vram[2].size = 0x020000)/2];
+ vram[3].data = new uint16[(vram[3].size = 0x020000)/2];
+ vram[4].data = new uint16[(vram[4].size = 0x010000)/2];
+ vram[5].data = new uint16[(vram[5].size = 0x004000)/2];
+ vram[6].data = new uint16[(vram[6].size = 0x004000)/2];
+ vram[7].data = new uint16[(vram[7].size = 0x008000)/2];
+ vram[8].data = new uint16[(vram[8].size = 0x004000)/2];
+
+ wxram.data = new uint16[(wxram.size = 0x002000)/2];
+
+ memset(firmware.data, 0, firmware.size);
+
+ callerThread = nullptr;
+ activeThread = nullptr;
+ running = false;
+}
+
+void System::mapVram(VRAMMapping* loc, uint8 *dirtyBits, unsigned npages, HalfMemory& bank) {
+ for(unsigned offset = 0; offset < npages; offset++)
+ loc[offset] = VRAMMapping{ bank, dirtyBits, offset % (bank.size/0x4000) };
+}
+
+void System::clearVmap() {
+ for(unsigned n = 0; n < 8; n++) {
+ for(auto &m : vmap.arm9[n]) m = VRAMMapping{};
+ }
+ for(auto &m : vmap.arm7) m = VRAMMapping{};
+ for(auto &m : vmap.tex) m = VRAMMapping{};
+ for(auto &m : vmap.texpal) m = VRAMMapping{};
+ for(auto &m : vmap.bgpal[0]) m = VRAMMapping{};
+ for(auto &m : vmap.objpal[0]) m = VRAMMapping{};
+ for(auto &m : vmap.bgpal[1]) m = VRAMMapping{};
+ for(auto &m : vmap.objpal[1]) m = VRAMMapping{};
+}
+
+void System::updateVmap() {
+ static const uint32 offsets[] = {
+ 0x00000, 0x20000, 0x40000, 0x60000, 0x80000, 0x90000, 0x94000, 0x98000, 0xa0000
+ };
+ static const uint32 altOffsets[] = {
+ 0x00000, 0x04000, 0x10000, 0x14000
+ };
+
+ clearVmap();
+ gpu.texCache.reset();
+
+ auto bank = vmap.regs;
+
+ for(unsigned n = 0; n < 7; n++) {
+ if(!bank[n].enable) continue;
+
+ unsigned offset = offsets[n] >> 14;
+ unsigned npages = vram[n].size >> 14;
+
+ int sel = bank[n].bus;
+
+ // Restrict MST to valid options (some are mirrored)
+ if(n < 2 || n < 4 && sel > 4 || sel > 5) sel &= 3;
+
+ if(sel == VRAMConfig::display)
+ mapVram(&vmap.arm9[4][offset], &vmap.dirty[offsets[n]/256], npages, vram[n]);
+ }
+
+ // Banks 0-3, all are 128K, mapped at increments of the same size.
+ for(unsigned n = 0; n < 4; n++) {
+ if(!bank[n].enable) continue;
+
+ unsigned offset = offsets[bank[n].offset] >> 14;
+ unsigned npages = vram[n].size >> 14;
+
+ uint8* dirty = &vmap.dirty[offsets[n]/256];
+ uint8* dirtyEnd = &vmap.dirty[offsets[n+1]/256];
+
+ VRAMMapping *bus = nullptr;
+ int sel = bank[n].bus;
+ if(n < 2 || sel > 4) sel &= 3;
+
+ if( sel == VRAMConfig::bg0) bus = &vmap.bg(0, offset);
+ if(n < 2 && sel == VRAMConfig::obj0) bus = &vmap.obj(0, offset);
+ if(n >= 2 && sel == VRAMConfig::arm7) bus = &vmap.arm7[offset];
+ if(n == 2 && sel == VRAMConfig::ppu1) bus = &vmap.bg(1, 0);
+ if(n == 3 && sel == VRAMConfig::ppu1) bus = &vmap.obj(1, 0);
+
+ if(sel == VRAMConfig::tex) {
+ bus = &vmap.tex[offset];
+
+ // Discard dirty textures, then mark the locked pages clean. Lines
+ // 191..213 are available for texture updates; games wishing to do so
+ // will perform at least one {unlock, DMA, lock} cycle in that time.
+ gpu.texCache.flushDirty(n);
+ memset(dirty, 0, dirtyEnd-dirty);
+ }
+ if(bus) mapVram(bus, dirty, npages, vram[n]);
+ }
+
+ // Banks 4-6 are 32K + 16K + 16K and carry over from the GBA.
+ // They always map into the first 128K of address space.
+ for(unsigned n = 4; n < 7; n++) {
+ if(!bank[n].enable) continue;
+
+ uint8* dirty = &vmap.dirty[offsets[n]/256];
+ uint8* dirtyEnd = &vmap.dirty[offsets[n+1]/256];
+
+ unsigned offset = n > 4? altOffsets[bank[n].offset] >> 14 : 0;
+ unsigned npages = vram[n].size >> 14;
+
+ VRAMMapping *bus = nullptr;
+ int sel = bank[n].bus;
+ if(sel > 5) sel &= 3;
+
+ if(sel == VRAMConfig::bg0) bus = &vmap.bg(0, offset);
+ if(sel == VRAMConfig::obj0) bus = &vmap.obj(0, offset);
+ if(sel == VRAMConfig::bgpal0) bus = &vmap.bgpal[0][offset];
+ if(sel == VRAMConfig::objpal0) bus = &vmap.objpal[0][offset];
+
+ if(sel == VRAMConfig::texpal) {
+ bus = &vmap.texpal[offset];
+
+ // The current implementation caches textures in ABGR format,
+ // so we need to check for dirty palettes, too.
+ gpu.texCache.flushDirty(n);
+ memset(dirty, 0, dirtyEnd-dirty);
+ }
+
+ if(bus) {
+ // Banks 5 and 6 (x) have offset 0 [x x ..............]
+ // mirroring that allows them to 1 [ x x ..128K banks..]
+ // map adjacent to larger banks. 2 [ x x ..............]
+ // Bank 4 (f) is fixed: 3 [ffff x x..............]
+ mapVram(bus + 0, dirty, npages, vram[n]);
+ if(n > 4) mapVram(bus + 2, dirty, npages, vram[n]);
+ }
+ }
+
+ // These two banks are only used with PPU1.
+ for(unsigned n = 8; n < 10; n++) {
+ if(!bank[n].enable) continue;
+
+ uint8* dirty = &vmap.dirty[offsets[n-1]/256];
+ int sel = bank[n].bus & 3;
+
+ if(sel == VRAMConfig::bg1) {
+ // These map in an odd sequence [hh hh ]
+ // where the Is mirror in pairs: [ ii ii]
+ mapVram(&vmap.bg(1, n==9? 2 : 0), dirty, 2, vram[n-1]);
+ mapVram(&vmap.bg(1, n==9? 6 : 4), dirty, 2, vram[n-1]);
+ }
+ if(n == 9 && sel == VRAMConfig::obj1) mapVram(&vmap.obj(1, 0), dirty, 8, vram[n-1]);
+ if(n == 8 && sel == VRAMConfig::bgpal1) mapVram(&vmap.bgpal[1][0], dirty, 8, vram[n-1]);
+ if(n == 9 && sel == VRAMConfig::objpal1) mapVram(&vmap.objpal[1][0], dirty, 8, vram[n-1]);
+ if(n == 8 && sel == VRAMConfig::display) mapVram(&vmap.arm9[4][38], dirty, 2, vram[n-1]);
+ if(n == 9 && sel == VRAMConfig::display) mapVram(&vmap.arm9[4][40], dirty, 1, vram[n-1]);
+ }
+
+ // Still unimplemented: bank[7] for SWRAM
+ // (currently both ARM7 and ARM9 have access)
+
+ // Apply mirroring to address spaces smaller than 512K
+ // Only needed in cases where it's possible to read out of bounds.
+ for(unsigned n = 0; n < 8; n++) {
+ // OBJ0 - 256K
+ vmap.obj(0, n+16) = vmap.obj(0, n+0);
+ vmap.obj(0, n+24) = vmap.obj(0, n+8);
+ // BG1, OBJ1 - 128K
+ vmap.bg(1, n+ 8) = vmap.bg(1, n);
+ vmap.bg(1, n+16) = vmap.bg(1, n);
+ vmap.bg(1, n+24) = vmap.bg(1, n);
+ vmap.obj(1, n+ 8) = vmap.obj(1, n);
+ vmap.obj(1, n+16) = vmap.obj(1, n);
+ vmap.obj(1, n+24) = vmap.obj(1, n);
+ }
+
+ for(unsigned i = 0; i < 4; i++)
+ for(unsigned n = 0; n < 32; n++)
+ vmap.arm9[i][n+32] = vmap.arm9[i][n+0];
+}
+
+uint32 System::regVmap(unsigned index) {
+ if(index == 0) return vmap.regs[3]<<24 | vmap.regs[2]<<16 | vmap.regs[1]<<8 | vmap.regs[0]<<0;
+ if(index == 1) return vmap.regs[7]<<24 | vmap.regs[6]<<16 | vmap.regs[5]<<8 | vmap.regs[4]<<0;
+ if(index == 2) return vmap.regs[9]<<8 | vmap.regs[8]<<0;
+}
+
+void System::regVmap(unsigned index, uint32 data, uint32 mask) {
+ if(mask & 0x000000ff) vmap.regs[4*index + 0] = data>>0;
+ if(mask & 0x0000ff00) vmap.regs[4*index + 1] = data>>8;
+ if(mask & 0x00ff0000 && index < 2) vmap.regs[4*index + 2] = data>>16;
+ if(mask & 0xff000000 && index < 2) vmap.regs[4*index + 3] = data>>24;
+
+ updateVmap();
+}
+
+
+
+void System::loadArm7Bios(const stream& stream) {
+ delete[] arm7.bios.data;
+
+ arm7.bios.size = stream.size();
+ arm7.bios.data = new uint32[(arm7.bios.size + 3)/4];
+
+ for(unsigned n = 0; n < arm7.bios.size; n += 4)
+ arm7.bios.write(n, Word, stream.readl(4));
+}
+
+
+void System::loadArm9Bios(const stream& stream) {
+ delete[] arm9.bios.data;
+
+ arm9.bios.size = stream.size();
+ arm9.bios.data = new uint32[(arm9.bios.size + 3)/4];
+
+ for(unsigned n = 0; n < arm9.bios.size; n += 4)
+ arm9.bios.write(n, Word, stream.readl(4));
+}
+
+
+void System::loadFirmware(const stream& stream) {
+ delete[] firmware.data;
+
+ firmware.size = stream.size();
+ firmware.data = new uint8[firmware.size];
+ for(unsigned n = 0; n < firmware.size; n++)
+ firmware.write(n, Byte, stream.read());
+}
+
+void System::saveFirmware(const stream& stream) {
+ for(unsigned n = 0; n < firmware.size; n++)
+ stream.write(firmware.read(n, Byte));
+}
+
+
+void System::loadRTC(const stream& stream) {
+ struct timeval cur = {};
+ gettimeofday(&cur, 0);
+
+ clock.reset();
+ clock.stoppedSec = cur.tv_sec;
+ clock.stoppedUSec = cur.tv_usec;
+
+ if(!stream.size()) return;
+
+ uint8* xml = new uint8[stream.size() + 1];
+ stream.read(xml, stream.size());
+ xml[stream.size()] = 0;
+
+ XML::Document document((const char*)xml);
+ delete[] xml;
+
+ if(document["rtc"].exists() == false)
+ return;
+
+ auto &rtc = document["rtc"];
+ //string model = rtc["model"].data;
+
+ if(rtc["settings"].exists()) {
+ clock.status1 = hex(rtc["settings"]["status"].data);
+ clock.status2 = hex(rtc["settings"]["mode"].data);
+ clock.adjust = hex(rtc["settings"]["adjust"].data);
+ clock.userByte = hex(rtc["settings"]["scratch"].data);
+ }
+ if(rtc["clock"].exists()) {
+ lstring date = rtc["clock"]["date"].data.split("/");
+ lstring time = rtc["clock"]["time"].data.split(":");
+ string wday = rtc["clock"]["day"].data;
+
+ if(date.size() >= 3 && time.size() >= 3) {
+ string sec = time[2];
+ string frac = "0";
+
+ if(sec.position(".")) {
+ frac = sec.split(".")[1];
+ sec = sec.split(".")[0];
+ }
+ clock.weekday = hex(wday) & 0x07;
+ clock.year = hex(date[0]) & 0xff;
+ clock.month = hex(date[1]) & 0x1f;
+ clock.day = hex(date[2]) & 0x3f;
+ clock.hour = hex(time[0]) & 0x3f;
+ clock.minute = hex(time[1]) & 0x7f;
+ clock.second = hex(sec) & 0x7f;
+ clock.counter = hex(frac);
+ }
+ }
+
+ for(unsigned i = 0; i < 2; i++) {
+ string alarm = {"alarm", i+1};
+ if(rtc[alarm].exists() == false) continue;
+
+ string wday = rtc[alarm]["day"].data;
+ lstring time = rtc[alarm]["time"].data.split(":");
+ lstring mode = rtc[alarm]["mode"].data.split(",");
+
+ clock.alarm[i].setting[0] = hex(wday) & 0x07;
+
+ if(time.size() >= 2) {
+ clock.alarm[i].setting[1] = hex(time[0]) & 0x7f;
+ clock.alarm[i].setting[2] = hex(time[1]) & 0x7f;
+ }
+ for(auto &select : mode) {
+ if(select.iequals("day")) clock.alarm[i].weekday |= 0x80;
+ if(select.iequals("hour")) clock.alarm[i].hour |= 0x80;
+ if(select.iequals("minute")) clock.alarm[i].minute |= 0x80;
+ }
+ }
+
+ if(rtc["saved"].exists()) {
+ lstring savedOn = rtc["saved"]["on"].data.split("/");
+ lstring savedAt = rtc["saved"]["at"].data.split(":");
+ string savedDst = rtc["saved"]["dst"].data;
+
+ if(savedOn.size() >= 3 && savedAt.size() >= 3) {
+ struct tm last = {};
+ string sec = savedAt[2];
+ string usec = "0";
+
+ if(sec.position(".")) {
+ usec = sec.split(".")[1];
+ sec = sec.split(".")[0];
+ }
+ last.tm_isdst = savedDst != ""? integer(savedDst) : -1;
+ last.tm_yday = -1;
+ last.tm_year = decimal(savedOn[0]) - 1900;
+ last.tm_mon = decimal(savedOn[1]) - 1;
+ last.tm_mday = decimal(savedOn[2]);
+ last.tm_wday = -1;
+ last.tm_hour = decimal(savedAt[0]);
+ last.tm_min = decimal(savedAt[1]);
+ last.tm_sec = decimal(sec);
+
+ struct timeval now = {};
+ gettimeofday(&now, nullptr);
+
+ clock.freeze(timegm(&last), decimal(usec));
+ clock.thaw(now.tv_sec, now.tv_usec);
+ }
+ }
+}
+
+
+void System::saveRTC(const stream& stream) {
+ struct timeval tv = {};
+ gettimeofday(&tv, nullptr);
+ clock.thaw(tv.tv_sec, tv.tv_usec);
+ clock.freeze(tv.tv_sec, tv.tv_usec);
+
+ struct tm now = *gmtime(&tv.tv_sec);
+
+ string saveDate = { decimal(1900 + now.tm_year), "/", decimal<2,'0'>(now.tm_mon+1), "/", decimal<2,'0'>(now.tm_mday) };
+ string saveTime = { decimal<2,'0'>(now.tm_hour), ":", decimal<2,'0'>(now.tm_min), ":", decimal<2,'0'>(now.tm_sec), ".", decimal<6,'0'>(tv.tv_usec) };
+
+ string dateStr = { hex<4>(0x2000 + clock.year), "/", hex<2>(clock.month), "/", hex<2>(clock.day) };
+ string timeStr = { hex<2>(clock.hour), ":", hex<2>(clock.minute), ":", hex<2>(clock.second), ".", hex<4>(clock.counter) };
+
+ string alarmTime[2], alarmDay[2], alarmMode[2];
+
+ for(unsigned i = 0; i < 2; i++) {
+ lstring conditions;
+ if(clock.alarm[i].weekday & 0x80) conditions[i].append("day");
+ if(clock.alarm[i].hour & 0x80) conditions[i].append("hour");
+ if(clock.alarm[i].minute & 0x80) conditions[i].append("minute");
+
+ alarmMode[i] = conditions.concatenate(",");
+ alarmDay[i] = hex<1>(clock.alarm[i].weekday & 7);
+ alarmTime[i] = { hex<2>(clock.alarm[i].hour & 0x3f),
+ ":", hex<2>(clock.alarm[i].minute & 0x7f) };
+ };
+
+ string xml{
+ "\n",
+ ""
+ };
+ stream.write((uint8*)(const char*)xml, xml.length());
+}
+
+
+
+void System::power() {
+ // Clear memory
+ memset(ewram.data, 0, ewram.size);
+ memset(iwram.data, 0, iwram.size);
+ memset(swram[0].data, 0, swram[0].size);
+ memset(swram[1].data, 0, swram[1].size);
+ memset(unmappedVram, 0, sizeof unmappedVram);
+
+ for(unsigned n = 0; n < 9; n++)
+ memset(vram[n].data, 0, vram[n].size);
+
+ // Reset VRAM mappings
+ for(auto &r : vmap.regs) r = 0x00;
+ clearVmap();
+ memset(vmap.dirty, 0xff, sizeof vmap.dirty);
+
+ arm9.config.arm9 = true;
+ arm9.config.arm7 = false;
+ arm7.config.arm9 = false;
+ arm7.config.arm7 = true;
+ arm9.other = &arm7;
+ arm7.other = &arm9;
+
+ ppu[0].which = 0;
+ ppu[1].which = 1;
+
+ arm7.power();
+ arm9.power();
+ clock.power();
+ powerMgr.power();
+ firmware.power();
+ touchscreen.power();
+ slot1.power();
+ video.power();
+ gpu.power();
+ ppu[0].power();
+ ppu[1].power();
+ apu.power();
+ wifi.power();
+
+ callerThread = co_active();
+ activeThread = arm7.thread; // Required since right now ARM7 loads the binaries..
+}
+
+void System::run() {
+ callerThread = co_active();
+ co_switch(activeThread);
+}
+
+void System::frame() {
+ interface->videoRefresh(video.output, 256*4, 256, 384);
+ activeThread = co_active();
+ co_switch(callerThread);
+}
+
+#include "clock.cpp"
+#include "powermgr.cpp"
+#include "touchscreen.cpp"
+
+}
diff --git a/bsnes/nds/system/system.hpp b/bsnes/nds/system/system.hpp
new file mode 100644
index 00000000..e1d8a73c
--- /dev/null
+++ b/bsnes/nds/system/system.hpp
@@ -0,0 +1,231 @@
+#include "eventqueue.hpp"
+
+typedef function Action;
+typedef EventQueue_of EventQueue;
+typedef EventQueue_of::Elem Event;
+
+
+enum class Input : unsigned {
+ // REG_KEYINPUT (10 bits)
+ A, B, Select, Start, Right, Left, Up, Down, R, L,
+
+ // REG_AUXINPUT (8 bits)
+ // - C, Z, W seem present, but unconnected
+ // - D is supposedly on debug units
+ X, Y, C, D, Z, W, Pen, Lid,
+
+ // Touchscreen
+ PenX, PenY, PenZ1, PenZ2,
+};
+
+
+struct SPIDevice {
+ virtual ~SPIDevice();
+ virtual void power() = 0;
+ virtual void select(bool state) = 0;
+ virtual uint8 transfer(uint8 data) = 0;
+};
+
+#include "../memory/eeprom.hpp"
+#include "../memory/fram.hpp"
+#include "../memory/flash.hpp"
+
+struct PowerMgr : SPIDevice {
+ ~PowerMgr();
+ void power();
+ void select(bool state);
+ uint8 transfer(uint8 data);
+};
+
+
+struct Touchscreen : SPIDevice {
+ ~Touchscreen();
+ void power();
+ void select(bool state);
+ uint8 transfer(uint8 data);
+
+ bool penDown();
+
+ uint1 bitDepth; enum { read12, read8 };
+ uint1 refMode; enum { diff, single };
+ uint2 powerMode; enum { powerAuto, powerADC, powerRef, powerFull };
+ uint3 input; enum {
+ temp0 = 0, temp1 = 7,
+ vbatt = 2, aux = 6,
+ ypos = 1, xpos = 5,
+ pressure0 = 3, pressure1 = 4,
+ };
+
+ uint32 adc;
+ uint12 last;
+};
+
+
+struct Clock {
+ Clock();
+ ~Clock();
+ void reset();
+ void power();
+ uint4 io(uint4 pins);
+
+ void dateTime();
+ void alarmTime(unsigned no);
+ void field(uint8& src, uint8 mask);
+
+ void tick();
+ void tickSecond();
+ void tickDay();
+ bool incBCD(uint8& val, uint8 first, uint8 last);
+
+ void freeze(int64 curSec, int64 curUSec);
+ void thaw(int64 curSec, int64 curUSec);
+
+
+ int64 stoppedSec, stoppedUSec;
+
+ uint1 lastCs, lastClk;
+ uint8 buffer, dataOut;
+ uint3 nbits;
+ uint8 command, index;
+ bool output;
+
+ uint8 status1; enum {
+ resetBit = 0x01, hourMode = 0x02,
+ int1Flag = 0x10, int2Flag = 0x20,
+ powerLow = 0x40, powerLost = 0x80
+ };
+ uint8 status2; enum {
+ int1Mode = 0x0f,
+ int2Mode = 0x40, testMode = 0x80
+ };
+ uint8 adjust; // clock rate fine adjustment
+ uint8 userByte;
+
+ Event event;
+ uint16 counter; // 32KHz subsecond counter
+ uint1 intr[2]; // Interrupts (both go to IRQ pin)
+ uint1 hold; // Delays seconds tick while reading the time
+ uint16 lag; // How long the seconds tick was delayed
+ uint1 secondsTickPending;
+
+ union {
+ struct { uint8 year, month, day, weekday, hour, minute, second; };
+ struct { uint8 time[7]; };
+ };
+ union {
+ struct { uint8 weekday, hour, minute; };
+ struct { uint8 setting[3]; };
+ } alarm[2];
+};
+
+
+struct VRAMMapping : HalfMemory {
+ VRAMMapping();
+ VRAMMapping(HalfMemory& target, uint8* dirtyBits, unsigned pageno);
+ ~VRAMMapping();
+
+ uint16& operator[](uint32 addr);
+ uint32 read(uint32 addr, uint32 size);
+ void write(uint32 addr, uint32 size, uint32 word);
+ bool dirty(uint32 addr);
+ void clearDirty(uint32 addr, uint32 size);
+
+ uint8 *dirtyBits;
+};
+
+
+struct System {
+ cothread_t callerThread;
+ cothread_t activeThread;
+ bool running;
+
+ Flash firmware;
+ Touchscreen touchscreen;
+ PowerMgr powerMgr;
+ Clock clock;
+
+ SDRAM ewram; // 4MB shared external WRAM
+ SRAM iwram; // 64KB 32-bit work RAM, private to ARM7
+ SRAM swram[2]; // 16KB x 2 banks switchable 32-bit WRAM
+ HalfMemory vram[9]; // 656KB in 9 banks of 16-bit VRAM
+ HalfMemory wxram; // 8KB wireless packet buffer
+
+ uint16 unmappedVram[0x2000];
+
+ struct VRAMConfig {
+ uint1 enable;
+ uint2 offset;
+ uint3 bus; // aka. MST or "Magic Selector Thing"
+ enum {
+ display=0, // all banks
+ bg0=1, // A,B,C,D,E,F,G
+ obj0=2, // A,B, E,F,G
+ arm7=2, // C,D
+ tex=3, // A,B,C,D
+ texpal=3, // E,F,G
+ bgpal0=4, // E,F,G
+ objpal0=5, // E?,F,G
+ ppu1=4, // C,D
+ bg1=1, // H,I
+ obj1=2, // I
+ bgpal1=2, // H
+ objpal1=3, // I
+ };
+
+ operator uint8() {
+ return enable<<7 | offset<<3 | bus<<0;
+ }
+ VRAMConfig& operator=(uint8 data) {
+ enable = data>>7;
+ offset = data>>3;
+ bus = data>>0;
+ return *this;
+ }
+ };
+
+ struct {
+ // Mappings for each graphics bus that can have VRAM banked onto it.
+ // Each page is 16K, the finest granularity.
+ VRAMMapping arm9[8][64]; // 8x1M arm9 map - 0x060,062,064,066,068,..
+ VRAMMapping arm7[16]; // 256K arm7 map - 0x060..
+
+ // Locked memory can be used by the GPU, but isn't mapped in CPU space.
+ VRAMMapping tex[32]; // 512K locked texture memory
+ VRAMMapping texpal[8]; // 128K locked texture palettes
+ VRAMMapping bgpal[2][8]; // 32K locked BG palettes
+ VRAMMapping objpal[2][8]; // 8K locked OBJ palettes
+
+ VRAMMapping &bg(int w, int i) { return arm9[0+w][i]; }
+ VRAMMapping &obj(int w, int i) { return arm9[2+w][i]; }
+ VRAMMapping &display(int i) { return arm9[4][i&31]; }
+
+ VRAMConfig regs[10]; // A,B,C,D, E,F,G,SWRAM, H,I
+
+ uint8 dirty[(512 + 96 + 48)*1024 / 256];
+ } vmap;
+
+
+ void clearVmap();
+ void updateVmap();
+ void mapVram(VRAMMapping* loc, uint8 *dirtyBits, unsigned npages, HalfMemory& bank);
+
+ uint32 regVmap(unsigned index);
+ void regVmap(unsigned index, uint32 data, uint32 mask);
+
+ void loadArm7Bios(const stream&);
+ void loadArm9Bios(const stream&);
+ void loadFirmware(const stream&);
+ void loadRTC(const stream&);
+
+ void saveFirmware(const stream&);
+ void saveRTC(const stream&);
+
+ void power();
+ void run();
+
+ void frame();
+
+ System();
+};
+
+extern System system;
diff --git a/bsnes/nds/system/touchscreen.cpp b/bsnes/nds/system/touchscreen.cpp
new file mode 100644
index 00000000..0db32907
--- /dev/null
+++ b/bsnes/nds/system/touchscreen.cpp
@@ -0,0 +1,112 @@
+
+Touchscreen::~Touchscreen() { }
+
+void Touchscreen::power() {
+ input = 0;
+ bitDepth = 0;
+ refMode = 0;
+ powerMode = 0;
+ adc = 0;
+ last = 0;
+}
+
+void Touchscreen::select(bool state) {
+ if(state) return;
+
+ adc = 0;
+}
+
+bool Touchscreen::penDown() {
+ if(powerMode == 3) return true; // differs between NDS Lite and original?
+
+ signed x = interface->inputPoll(ID::Port::Touchpad, 0, ID::Touchpad::X);
+ signed y = interface->inputPoll(ID::Port::Touchpad, 0, ID::Touchpad::Y);
+ signed p = interface->inputPoll(ID::Port::Touchpad, 0, ID::Touchpad::Pressure);
+ signed d = 0;//interface->inputPoll(ID::Port::Touchpad, 0, ID::Touchpad::PressureD);
+
+ if(y < 0) y = -0x8000;
+
+ if(x == -0x8000 || y == -0x8000) {
+ return 0; // no touch input
+ }
+ if(p == -0x8000) // no analog pressure
+ p = d? 0 : -0x7fff; // use digital
+
+ return p > -0x7ff0;
+}
+
+uint8 Touchscreen::transfer(uint8 data) {
+ if(data & 0x80) {
+ // Start a new measurement
+ input = data>>4;
+ bitDepth = data>>3;
+ refMode = data>>2;
+ powerMode = data>>0;
+
+ signed NONE = -0x8000;
+ signed x = interface->inputPoll(ID::Port::Touchpad, 0, ID::Touchpad::X);
+ signed y = interface->inputPoll(ID::Port::Touchpad, 0, ID::Touchpad::Y);
+ signed p = interface->inputPoll(ID::Port::Touchpad, 0, ID::Touchpad::Pressure);
+ signed d = 0;//interface->inputPoll(ID::Port::Touchpad, 0, ID::Touchpad::PressureD);
+
+ if(p==NONE) p = !d? -0x7fff : -0x3fff; // no analog? use digital pen
+ if(x==NONE || y==NONE) p = NONE; // check if pen offscreen
+ if(y < 0) p = NONE; // restrict to bottom screen
+
+ x += 0x7fff; y *= 2;
+ p += 0x7fff;
+
+ if(p > 0) {
+ signed z1 = 0x000, z2 = 0xfff, r = 0xffff - p;
+ if(x > 0) { // bleh, div-by-zero, just use medium pressure for now
+ z1 = 0xc00; //0xffffff / (0x1000 + 0x1000/x + 0x1000*(r - y)/x);
+ z2 = 0x400; //z1*(0x1000 + 0x1000*r/x) / 0x1000;
+ }
+ x /= 16;
+ y /= 16;
+
+ // Without any pressure, there's no connection, and the input floats.
+ // The measurements seem to return previous values to some extent.
+ if(input == xpos) last = x; // y+ (along x-/x+ axis)
+ if(input == ypos) last = y; // x+ (along y-/y+ axis)
+ if(input == pressure0) last = z1; // x+ (along x-/y+ diagonal?)
+ if(input == pressure1) last = z2; // y- (along x-/y+ diagonal?)
+ }
+
+ signed vref = 0x34cc; // reference = 3.3V
+ signed room = (273 + 25)*0x1000; // 25*C in kelvin
+ signed k = room;
+ signed t1 = 0x1000*600 - (k-room)*21/10; // t1 = 600mV @ room - 2.1mV/*K + error
+ signed t2 = t1 + k * 0x1000/0x292b; // t2 = t1 + k/2.573
+
+ if(input == temp0) last = t1 * 0xfff/vref; // temperature
+ if(input == temp1) last = t2 * 0xfff/vref; // temp (w/bias)
+ if(input == vbatt) last = 0x000; // grounded
+ if(input == aux) {
+ // This was split into two inputs - reference is always "single" mode
+ if(refMode==single) last = 0x800; // microphone
+ if(refMode==diff) last = 0xfff; // Vcc (NDS Lite)
+ }
+
+ adc |= last;
+
+ // 8-bit isn't any faster since you have to read two bytes over the serial
+ // interface either way. Bumping the clock to 4MHz may not provide enough
+ // time for the ADC to settle, producing less accurate results.
+ if(bitDepth == read8)
+ adc &= ~0xf;
+ }
+ // Response is 1 bit delay + 8 or 12 bits data.
+ // This causes some misalignment:
+ // -------- 0hhhhhhhlllll - after command
+ // 0hhhhhhh lllll000----- - after first read
+ // lllll000 [0hhhhhhhlllll] - after second read [+ command]
+ // [0hhhhhhh lllll000-----] - ...
+ // [lllll000 0hhhhhhhlllll] -
+ // response next data
+ //
+ // It's perfectly legit (and common) to send a new command while reading the
+ // low byte. By doing this, you receive a stream of readings with no gaps or
+ // command overhead in between.
+ return adc <<= 8, adc >> 21;
+}
diff --git a/bsnes/nds/video/video.cpp b/bsnes/nds/video/video.cpp
new file mode 100644
index 00000000..5c535b79
--- /dev/null
+++ b/bsnes/nds/video/video.cpp
@@ -0,0 +1,180 @@
+#include
+
+namespace NintendoDS {
+
+Video video;
+
+void Video::scanline(unsigned y) {
+ gpu.scanline();
+ ppu[0].scanline();
+ ppu[1].scanline();
+
+ if(line < 192) {
+ bool display = source[0] == srcFrameBuffer;
+ bool read = write && sourceB == srcFrameBuffer;
+
+ unsigned srcline = y + 64*(frameBuffer & (display? 0xc : 0xf));
+ unsigned destline = y + 64*targetBuffer;
+
+ uint16 *src = &system.vmap.display(srcline / 32)[512*(srcline % 32)];
+ uint16 *dest = &system.vmap.display(destline / 32)[512*(destline % 32)];
+
+ if(read || display) {
+ for(unsigned x = 0; x < 256; x++) {
+ uint16 c = src[x];
+ uint5 r = c>>0, g = c>>5, b = c>>10;
+
+ frameBufData[x] = b<<13 | g<<7 | r<<1;
+ }
+ }
+ if(write) {
+ uint32 *aData = sourceA == srcGPU? &gpu.output[256*line] : ppu[0].output;
+ uint32 *bData = sourceB == srcFifo? fifoData : frameBufData;
+
+ unsigned af = min((unsigned)blendAf, 16u);
+ unsigned bf = min((unsigned)blendBf, 16u);
+
+ if(targetSource == 0) af = 16, bf = 0;
+ if(targetSource == 1) af = 0, bf = 16;
+
+ // Need to see what happens with alpha bit..
+ for(unsigned x = 0; x < 256; x++) {
+ uint32 a = aData[x], b = bData[x];
+
+ uint6 ar = a>>0, ag = a>>6, ab = a>>12;
+ uint6 br = b>>0, bg = b>>6, bb = b>>12;
+
+ ar = (ar*af + br*bf + 8) / 32u;
+ ag = (ag*af + bg*bf + 8) / 32u;
+ ab = (ab*af + bb*bf + 8) / 32u;
+
+ dest[x] = 0x8000 | ab<<10 | ag<<5 | ar<<0;
+ }
+ }
+
+ uint32* line[2] = { &output[256*(y + 192*(ppu0Screen == 0))],
+ &output[256*(y + 192*(ppu0Screen == 1))] };
+
+ if(source[0] == srcNone) memcpy(line[0], blankData, 256*4);
+ if(source[0] == srcPPU) memcpy(line[0], ppu[0].output, 256*4);
+ if(source[0] == srcFrameBuffer) memcpy(line[0], frameBufData, 256*4);
+ if(source[0] == srcFifo) memcpy(line[0], fifoData, 256*4);
+
+ if(source[1] == srcNone) memcpy(line[1], blankData, 256*4);
+ if(source[1] == srcPPU) memcpy(line[1], ppu[1].output, 256*4);
+ if(source[1] == srcFrameBuffer) memcpy(line[1], blankData, 256*4);
+ if(source[1] == srcFifo) memcpy(line[1], blankData, 256*4);
+
+ for(unsigned s = 0; s < 2; s++) {
+ if(!fade[s] || !blendYf[s]) continue;
+
+ uint64 yf = min(32, 2*blendYf[s]);
+ uint64 y = 02000200020;
+ if(fade[s] == lighten)
+ y += 07700770077*yf;
+
+ for(unsigned x = 0; x < 256; x++) {
+ uint64 bgr = (line[s][x] & 0777777)*01000001ull & 07700770077ull;
+
+ bgr = (bgr*(32-yf) + y)/32;
+
+ if(bgr & 010000000000) bgr |= 007700000000;
+ if(bgr & 000001000000) bgr |= 000000770000;
+ if(bgr & 000000000100) bgr |= 000000000077;
+ bgr &= 007700770077;
+
+ line[s][x] = (bgr | bgr>>18) & 0777777;
+ }
+ }
+ }
+}
+
+uint32 Video::regCapture() {
+ return blendAf<<0 | blendBf<<8
+ | (targetBuffer<<14 & 3<<16)
+ | (targetBuffer<<18 & 3<<18)
+ | (frameBuffer<<26 & 3<<26)
+ | (sourceA == srcGPU? 1<<24 : 0)
+ | (sourceB == srcFifo? 1<<25 : 0)
+ | targetSource<<29 | write<<31;
+}
+
+void Video::regCapture(uint32 data, uint32 mask) {
+ if(mask & 0x000000ff) {
+ blendAf = data>>0;
+ }
+ if(mask & 0x0000ff00) {
+ blendBf = data>>8;
+ }
+ if(mask & 0x00ff0000) {
+ targetBuffer = data>>14 & 0xc;
+ targetBuffer += data>>18 & 0x3;
+ targetSize = data>>20;
+ }
+ if(mask & 0xff000000) {
+ frameBuffer &= ~3;
+ frameBuffer += data>>26 & 0x3;
+ sourceA = data & 1<<24? srcGPU : srcPPU;
+ sourceB = data & 1<<25? srcFifo : srcFrameBuffer;
+ targetSource = data>>29;
+ write = data>>31;
+ }
+}
+
+void Video::regFifo(uint32 data) {
+}
+
+uint32 Video::regBrightness(unsigned index) {
+ return fade[index]<<14 | blendYf[index]<<0;
+}
+
+void Video::regBrightness(unsigned index, uint32 data, uint32 mask) {
+ if(mask & 0x001f) blendYf[index] = data>>0;
+ if(mask & 0xc000) fade[index] = data>>14;
+}
+
+
+void Video::power() {
+ for(unsigned x = 0; x < 256; x++)
+ blankData[x] = 0x3ffff;
+
+ line = 262;
+ ppu0Screen = 0;
+ source[0] = srcNone;
+ source[1] = srcNone;
+ frameBuffer = 0;
+ fade[0] = 0;
+ fade[1] = 0;
+ blendYf[0] = 0;
+ blendYf[1] = 0;
+
+ write = false;
+ sourceA = srcNone;
+ sourceB = srcNone;
+ blendAf = blendBf = 0;
+ targetBuffer = 0;
+
+ hdrawEvent.action = [&]() {
+ if(++line == 263) {
+ line = 0;
+ }
+ if(line == 192) {
+ write = false;
+ system.frame();
+ }
+ scanline(line);
+ arm9.event.queue.add(12*256, hblankEvent);
+ arm7.hdraw();
+ arm9.hdraw();
+ };
+
+ hblankEvent.action = [&]() {
+ arm9.event.queue.add(12*99, hdrawEvent);
+ arm7.hblank();
+ arm9.hblank();
+ };
+
+ arm9.event.queue.add(0, hdrawEvent);
+}
+
+}
diff --git a/bsnes/nds/video/video.hpp b/bsnes/nds/video/video.hpp
new file mode 100644
index 00000000..b3df3fa8
--- /dev/null
+++ b/bsnes/nds/video/video.hpp
@@ -0,0 +1,44 @@
+struct Video {
+ void power();
+ void scanline(unsigned y);
+
+ uint32 regCapture();
+ void regCapture(uint32 data, uint32 mask);
+ void regFifo(uint32 data);
+
+ uint32 regBrightness(unsigned index);
+ void regBrightness(unsigned index, uint32 data, uint32 mask);
+
+ uint32 output[256*384];
+
+ uint32 blankData[256];
+ uint32 frameBufData[256];
+ uint32 fifoData[256];
+
+ uint9 line;
+ Event hdrawEvent;
+ Event hblankEvent;
+
+ // Display and rendering on NDS are more loosely coupled, although
+ // the GPU and PPUs are still all locked to 60fps.
+ enum { srcNone, srcPPU, srcFrameBuffer, srcFifo, srcGPU };
+
+ // For display onscreen
+ uint1 screensPowered;
+ uint1 ppu0Screen; // 0 is bottom, 1 is top
+ int source[2];
+ int fade[2]; enum { lighten=1, darken=2 };
+ uint5 blendYf[2];
+
+ // For rendering to VRAM
+ bool write;
+ int sourceA; // PPU0 or GPU
+ int sourceB; // framebuffer or FIFO
+ uint5 blendAf, blendBf; // for blending A + B
+ uint2 targetSize;
+ uint2 targetSource;
+ uint4 targetBuffer;
+ uint4 frameBuffer;
+};
+
+extern Video video;
diff --git a/bsnes/nds/wifi/wifi.cpp b/bsnes/nds/wifi/wifi.cpp
new file mode 100644
index 00000000..dfebb566
--- /dev/null
+++ b/bsnes/nds/wifi/wifi.cpp
@@ -0,0 +1,488 @@
+#include
+
+namespace NintendoDS {
+
+WIFI wifi;
+
+
+void WIFI::power() {
+ // This isn't really cleared but we have to be deterministic.
+ memset(system.wxram.data, 0, system.wxram.size);
+
+ powered = true;
+
+ reg004 = 0;
+ reg034 = 0;
+ swMode = 0;
+ wepMode = 0;
+ memset(macAddr, 0, sizeof macAddr);
+ memset(bssId, 0, sizeof bssId);
+ assocIdl = 0;
+ assocIdf = 0;
+
+ rxControl = 0;
+ wepControl = 0;
+ reg034 = 0;
+ baseBandPower = 0;
+
+ interrupt.flags = 0;
+ interrupt.enable = 0;
+ interrupt.counterFlags = 0;
+ interrupt.counterEnable = 0;
+ interrupt.oflowFlags = 0;
+ interrupt.oflowEnable = 0;
+
+ pm.txIdle = 0;
+ pm.wakeRequest = 0;
+ pm.wakePending = 0;
+ pm.sleeping = 0;
+
+ bb.event.action = [&]() { bbTransferBit(); };
+ bb.time = 0;
+ bb.busy = 0;
+ bb.read = 0;
+ bb.write = 0;
+ bb.header = 0;
+ bb.powerl = 0;
+ bb.powerh = 0;
+ bb.mode8 = 0;
+ bb.modeE = 0;
+ bb.clock = 0;
+
+ memset(bb.regs, 0, sizeof bb.regs);
+
+ bb.regs[0x00] = 0x6d;
+ bb.regs[0x4d] = 0xff;
+ bb.regs[0x5d] = 0x01;
+ bb.regs[0x64] = 0xff;
+
+ rf.event.action = [&]() { rfTransferBit(); };
+ rf.time = 0;
+ rf.busy = 0;
+ rf.data = 0;
+ rf.length = 24;
+ rf.type = 0;
+ rf.reserved = 0;
+
+ memset(rf.regs, 0, sizeof rf.regs);
+
+ rf.regs[0x00] = 0x00007;
+ rf.regs[0x01] = 0x09003;
+ rf.regs[0x02] = 0x00022;
+ rf.regs[0x03] = 0x1ff78;
+ rf.regs[0x04] = 0x09003;
+ rf.regs[0x05] = 0x01780;
+ rf.regs[0x06] = 0x00000;
+ rf.regs[0x07] = 0x14578;
+ rf.regs[0x08] = 0x1e742;
+ rf.regs[0x09] = 0x00120;
+ rf.regs[0x0a] = 0x00000;
+ rf.regs[0x0b] = 0x00000;
+ rf.regs[0x0c] = 0x00000;
+ rf.regs[0x1b] = 0x0000f;
+ rf.regs[0x0e] = 0x00022;
+ rf.regs[0x1f] = 0x00001;
+
+ txWritePos = 0; rxBufBegin = 0;
+ txWriteCounter = 0; rxBufEnd = 0;
+ txGapBegin = 0; rxWritePos = 0;
+ txGapSize = 0; rxWritePosLatch = 0;
+ txTimOffset = 0; rxReadPos = 0;
+ txBeacon = 0; rxSoftReadPos = 0;
+ txMultiCmd = 0; rxReadCounter = 0;
+ txSlots[0] = 0; rxGapBegin = 0;
+ txSlots[1] = 0; rxGapSize = 0;
+ txSlots[2] = 0; reg00a = 0;
+ txStatControl = 0;
+ txRetryLimit = 0;
+
+ reg1a0l = 0;
+ reg1a0m = 0;
+ reg1a0n = 0;
+ reg1a0h = 0;
+ reg1a2 = 0;
+ reg1a4 = 0;
+
+ listenCount = 0;
+ listenInterval = 0;
+ beaconInterval = 0;
+ preamble = 0;
+ random = 1;
+
+ timer.enable = false;
+ timer.enableIrq = false;
+ timer.enableTxMP = false;
+ timer.count = 0;
+ timer.compare = 0;
+
+ config120l = 0; config140 = 0; config154l = 0;
+ config120h = 0; config142 = 0; config154m = 0;
+ config122 = 0; config144 = 0; config154h = 0;
+ config124 = 0; config146 = 0;
+ config128 = 0; config148 = 0; config0d4 = 0;
+ config130 = 0; config14a = 0; config0d8 = 0;
+ config132l = 0; config14c = 0; config0da = 0;
+ config132h = 0; config150l = 0; config0ecl = 0;
+ configBeaconCount = 0; config150h = 0; config0ech = 0;
+
+ stats.reg1b0 = 0;
+ stats.reg1b2 = 0;
+ stats.reg1b4 = 0;
+ stats.reg1b6 = 0;
+ stats.reg1b8 = 0;
+ stats.reg1ba = 0;
+ stats.reg1bc = 0;
+ stats.reg1be = 0;
+ stats.txErrors = 0;
+ stats.rxPackets = 0;
+ memset(stats.mpErrors, 0, sizeof stats.mpErrors);
+}
+
+void WIFI::bbTransfer() {
+ // Assuming 22MHz (66MHz/3) clock here. Probably wrong.
+ bb.busy = 0;
+ bb.read = 0;
+ bb.time = 16 + 8;
+ arm7.event.queue.add(3, bb.event);
+}
+
+void WIFI::bbTransferBit() {
+ if(--bb.time) {
+ // Small delay before setting busy bit
+ if(bb.time == 20) bb.busy = 1;
+
+ arm7.event.queue.add(3, bb.event);
+ return;
+ }
+ // Finished, commit the read or write.
+ bb.busy = 0;
+
+ uint1 start = bb.header>>14;
+ uint1 rd = bb.header>>13;
+ uint1 wr = bb.header>>12;
+ uint8 addr = bb.header>>0;
+
+ if(start) {
+ if(rd) {
+ bb.read = addr < 0x69? bb.regs[addr] : 0;
+ //print("bb read ",hex<2>(addr)," = ",hex<2>(bb.read),"\n");
+ }
+ if(wr) {
+ if(0x0d <= addr && addr <= 0x12) return;
+ if(0x16 <= addr && addr <= 0x1a) return;
+ if(0x5d <= addr && addr <= 0x61) return;
+ if(0x00 == addr || 0x27 == addr) return;
+ if(0x4d == addr || 0x64 == addr) return;
+ if(0x66 == addr || 0x69 <= addr) return;
+
+ if(addr < 0x69) bb.regs[addr] = bb.write;
+ //print("bb write ",hex<2>(addr)," : ",hex<2>(bb.write),"\n");
+ }
+ }
+}
+
+void WIFI::rfTransfer() {
+ rf.busy = 1;
+ rf.time = 18 + 6;
+ arm7.event.queue.add(3, rf.event);
+}
+
+void WIFI::rfTransferBit() {
+ if(--rf.time) {
+ arm7.event.queue.add(3, rf.event);
+ return;
+ }
+ //Finished, commit the read or write.
+ rf.busy = 0;
+
+ uint1 rd = rf.data>>23;
+ uint5 addr = rf.data>>18;
+ uint18 data = rf.data>>0;
+
+ if(rd) {
+ rf.data = rf.regs[addr];
+ //print("rf read ",hex<2>(addr)," = ",hex<5>(rf.data),"\n");
+ }
+ else {
+ rf.regs[addr] = data;
+ //print("rf write ",hex<2>(addr)," : ",hex<5>(data),"\n");
+ }
+}
+
+uint32 WIFI::read(uint32 addr, uint32 size) {
+ if(addr & 0x4000)
+ return system.wxram.read(addr & 0x1fff, size);
+
+ if(size==Word) { return read(addr&~2, Half)<<0
+ | read(addr| 2, Half)<<16; }
+ //if(addr != 0x480015e && addr != 0x4800180)
+ // print("wifi r ",hex<8>(addr),"\n");
+
+ switch(addr & 0xffe) {
+ case 0x000: return 0xc340; // chip ID
+ case 0x004: return reg004;
+ case 0x006: return swMode<<0 | wifi.wepMode<<3;
+ case 0x008: return txStatControl;
+ case 0x00a: return reg00a;
+ case 0x010: return interrupt.flags;
+ case 0x012: return interrupt.enable;
+
+ case 0x018: return macAddr[0] | macAddr[1]<<8;
+ case 0x01a: return macAddr[2] | macAddr[3]<<8;
+ case 0x01c: return macAddr[4] | macAddr[5]<<8;
+ case 0x020: return bssId[0] | bssId[1]<<8;
+ case 0x022: return bssId[2] | bssId[3]<<8;
+ case 0x024: return bssId[4] | bssId[5]<<8;
+ case 0x028: return assocIdl;
+ case 0x02a: return assocIdf;
+ case 0x02c: return txRetryLimit;
+
+ case 0x030: return rxControl;
+ case 0x032: return wepControl;
+ case 0x034: return reg034;
+ case 0x036: return bb.clock;
+ case 0x038: return pm.txIdle;
+ case 0x03c: return pm.wakeRequest | pm.wakePending<<8 | pm.sleeping<<9;
+ case 0x040: return 0;//wifi.pm.;
+
+ case 0x044: {
+ uint11 data = random;
+ random = random<<1 | random>>10;
+ random ^= data & 1;
+ return data;
+ }
+
+ case 0x050: return rxBufBegin;
+ case 0x052: return rxBufEnd;
+ case 0x054: return rxWritePos;
+ case 0x056: return rxWritePosLatch;
+ case 0x058: return rxReadPos<<1;
+ case 0x05a: return rxSoftReadPos;
+ case 0x05c: return rxReadCounter;
+ case 0x060: break;//return rxBufRead();
+ case 0x062: return rxGapBegin<<1;
+ case 0x064: return rxGapSize;
+
+ case 0x068: return txWritePos<<1;
+ case 0x06c: return txWriteCounter;
+ case 0x074: return txGapBegin<<1;
+ case 0x076: return txGapSize;
+ case 0x080: return txBeacon;
+ case 0x084: return txTimOffset;
+ case 0x088: return listenCount;
+ case 0x08c: return beaconInterval;
+ case 0x08e: return listenInterval;
+
+ case 0x0bc: return preamble;
+
+ case 0x0d4: return config0d4;
+ case 0x0d8: return config0d8;
+ case 0x0da: return config0da;
+ case 0x0e8: return timer.enable;
+ case 0x0ea: return timer.enableIrq;
+ case 0x0ec: return config0ecl | config0ech<<8;
+ case 0x0ee: return timer.enableTxMP;
+
+ case 0x110: return preBeacon;
+
+ case 0x120: return config120l | config120h<<15;
+ case 0x122: return config122;
+ case 0x124: return config124;
+ case 0x128: return config128;
+ case 0x130: return config130;
+ case 0x132: return config132l | config132h<<15;
+ case 0x134: return configBeaconCount;
+ case 0x140: return config140;
+ case 0x142: return config142;
+ case 0x144: return config144;
+ case 0x146: return config146;
+ case 0x148: return config148;
+ case 0x14a: return config14a;
+ case 0x14c: return config14c;
+ case 0x150: return config150l | config150h<<8;
+ case 0x154: return config154l | config154m<<9 | config154h<<11;
+
+ case 0x15c: return bb.read;
+ case 0x15e: return bb.busy;
+ case 0x160: return bb.mode8<<8 | bb.modeE<<14;
+ case 0x168: return bb.powerl<<0 | bb.powerh<<15;
+
+ case 0x17c: return rf.data>>16;
+ case 0x17e: return rf.data>>0;
+ case 0x180: return rf.busy;
+
+ case 0x1a0: return reg1a0l | reg1a0m<<4 | reg1a0n<<8 | reg1a0h<<11;
+ case 0x1a2: return reg1a2;
+ case 0x1a4: return reg1a4;
+
+ case 0x244: return 0x0000;
+ case 0x254: return 0xeeee;
+ case 0x290: return 0xffff;
+ }
+ //print("r ",hex<8>(addr),": unimplemented\n");
+ return 0;
+}
+
+void WIFI::write(uint32 addr, uint32 size, uint32 data) {
+ if(size==Byte) return;
+ if(size==Word) { write(addr&~2, Half, data & 0xffff);
+ write(addr| 2, Half, data >> 16); return; }
+ if(addr & 0x4000)
+ return system.wxram.write(addr & 0x1fff, Half, size);
+
+ //print("wifi w ",hex<8>(addr)," : ",hex<4>(data),"\n");
+
+ switch(addr & 0xffe) {
+ case 0x004:
+ if((reg004 ^ data) & 1<<0) {
+ if(data & 1) {
+ reg034 = 0x2;
+ //rf.pins = 0x46;
+ //rf.status = 9;
+ //reg27c = 5;
+ //reg2a2 = ..;
+ }
+ else {
+ reg034 = 0xa;
+ }
+ }
+ if(data & 1<<13) {
+ rxWritePosLatch = 0;
+ //reg0c0 = 0;
+ //reg0c4 = 0;
+ //reg1a4 = 0;
+ //reg278 = 0xf;
+ }
+ if(data & 1<<14) {
+ swMode = 0;
+ wepMode = 0;
+ //txStatCnt = 0;
+ //reg00a = 0;
+ memset(macAddr, 0, sizeof macAddr);
+ memset(bssId, 0, sizeof bssId);
+ assocIdl = 0;
+ assocIdf = 0;
+ //txRetryLimit = 0;
+ //reg02e = 0;
+ rxBufBegin = 0x4000;
+ rxBufEnd = 0x4800;
+ txTimOffset = 0;
+ //reg0bc = 1;
+ //reg0d0 = 0x401;
+ config0d4 = 1;
+ //reg0e0 = 8;
+ config0ecl = 3;
+ config0ech = 0x3f;
+ //reg194 = 0;
+ //reg198 = 0;
+ //reg1a2 = 1;
+ //reg224 = 3;
+ //reg230 = 0x47;
+ }
+ reg004 = data;
+ return;
+
+ case 0x006: swMode = data>>0; wepMode = data>>3; return;
+ case 0x008: txStatControl = data; return;
+ case 0x00a: reg00a = data; return;
+ case 0x21c: interrupt.flags |= data & ~0x400; return;
+ case 0x010: interrupt.flags &= ~data; return;
+ case 0x012: interrupt.enable = data; return;
+
+ case 0x018: macAddr[0] = data; macAddr[1] = data>>8; return;
+ case 0x01a: macAddr[2] = data; macAddr[3] = data>>8; return;
+ case 0x01c: macAddr[4] = data; macAddr[5] = data>>8; return;
+ case 0x020: bssId[0] = data; bssId[1] = data>>8; return;
+ case 0x022: bssId[2] = data; bssId[3] = data>>8; return;
+ case 0x024: bssId[4] = data; bssId[5] = data>>8; return;
+ case 0x028: assocIdl = data; return;
+ case 0x02a: assocIdf = data; return;
+ case 0x02c: txRetryLimit = data; return;
+
+ case 0x030: rxControl = data; return;
+ case 0x032: wepControl = data & 0x8000; return;
+ case 0x034: reg034 = data; return;
+ case 0x036: bb.clock = data; return;
+ case 0x038: pm.txIdle = data; return;
+ case 0x03c: pm.wakeRequest = data>>1; return;
+ case 0x040: if(data & 1<<15) {
+ reg034 = 2;
+ pm.sleeping = data>>0;
+ }
+ return;
+
+ case 0x050: rxBufBegin = data; return;
+ case 0x052: rxBufEnd = data; return;
+ case 0x056: rxWritePosLatch = data; return;
+ case 0x058: rxReadPos = data>>1; return;
+ case 0x05a: rxSoftReadPos = data; return;
+ case 0x05c: rxReadCounter = data; return;
+ case 0x062: rxGapBegin = data>>1; return;
+ case 0x064: rxGapSize = data; return;
+
+ case 0x068: txWritePos = data>>1; return;
+ case 0x06c: txWriteCounter = data; return;
+ case 0x070: break;//return txBufWrite(data);
+ case 0x074: txGapBegin = data>>1; return;
+ case 0x076: txGapSize = data; return;
+
+ case 0x080: txBeacon = data; return;
+ case 0x084: txTimOffset = data; return;
+ case 0x088: listenCount = data; return;
+ case 0x08c: beaconInterval = data; return;
+ case 0x08e: listenInterval = data; return;
+
+ case 0x0b4: return; //txBufReset
+ case 0x0bc: preamble = data; return;
+
+ case 0x0d4: config0d4 = data; return;
+ case 0x0d8: config0d8 = data; return;
+ case 0x0da: config0da = data; return;
+ case 0x0e8: timer.enable = data; return;
+ case 0x0ec: config0ecl = data; config0ech = data>>8; return;
+ case 0x0ea: timer.enableIrq = data; return;//if bit 1 trigger irq14
+ case 0x0ee: timer.enableTxMP = data; return;
+
+ case 0x110: preBeacon = data; return;
+
+ case 0x120: config120l = data; config120h = data>>15; return;
+ case 0x122: config122 = data; return;
+ case 0x124: config124 = data; return;
+ case 0x128: config128 = data; return;
+ case 0x130: config130 = data; return;
+ case 0x132: config132l = data; config132h = data>>15; return;
+ case 0x134: configBeaconCount = data; return;
+ case 0x140: config140 = data; return;
+ case 0x142: config142 = data; return;
+ case 0x144: config144 = data; return;
+ case 0x146: config146 = data; return;
+ case 0x148: config148 = data; return;
+ case 0x14a: config14a = data; return;
+ case 0x14c: config14c = data; return;
+ case 0x150: config150l = data; config150h = data>>8; return;
+ case 0x154: config154l = data; config154m = data>>9; config154h = data>>11; return;
+
+ case 0x158: bb.header = data; return wifi.bbTransfer();
+ case 0x15a: bb.write = data; return;
+ case 0x160: bb.mode8 = data>>8; bb.modeE = data>>14; return;
+ case 0x168: bb.powerl = data>>0; bb.powerh = data>>15; return;
+
+ case 0x17c: rf.data &= 0xffff; rf.data |= data<<16; return wifi.rfTransfer();
+ case 0x17e: rf.data &= ~0xffff; rf.data |= data<<0; return;
+ case 0x184: rf.length = data>>0;
+ rf.type = data>>8;
+ rf.reserved = data>>14; return;
+
+ case 0x1a0: reg1a0l = data; reg1a0m = data>>4; reg1a0n = data>>8; reg1a0h = data>>11; return;
+ case 0x1a2: reg1a2 = data; return;
+ case 0x1a4: reg1a4 = data; return;
+
+ case 0x244: return;
+ case 0x254: return;
+ case 0x290: return;
+ }
+ //print("w ",hex<8>(addr),": unimplemented\n");
+}
+
+
+}
diff --git a/bsnes/nds/wifi/wifi.hpp b/bsnes/nds/wifi/wifi.hpp
new file mode 100644
index 00000000..548940e6
--- /dev/null
+++ b/bsnes/nds/wifi/wifi.hpp
@@ -0,0 +1,153 @@
+
+struct WIFI {
+ void power();
+
+ void bbTransfer();
+ void bbTransferBit();
+
+ void rfTransfer();
+ void rfTransferBit();
+
+ uint32 read(uint32 addr, uint32 size);
+ void write(uint32 addr, uint32 size, uint32 data);
+
+ uint1 powered;
+
+ uint16 reg004;
+ uint3 swMode, wepMode;
+
+ uint8 macAddr[6];
+ uint8 bssId[6];
+ uint4 assocIdl;
+ uint11 assocIdf;
+
+ uint16 rxControl, wepControl;
+ uint16 reg034, baseBandPower;
+
+ uint16 rxBufBegin, rxBufEnd;
+ uint12 rxWritePos, rxWritePosLatch;
+ uint12 rxReadPos, rxSoftReadPos;
+ uint12 rxGapBegin, rxGapSize;
+ uint12 rxReadCounter;
+ uint16 reg00a;
+
+ uint12 txWritePos;
+ uint12 txGapBegin, txGapSize;
+ uint16 txBeacon;
+ uint16 txMultiCmd;
+ uint16 txSlots[3];
+ uint8 txTimOffset;
+ uint12 txWriteCounter;
+ uint16 txStatControl;
+ uint16 txRetryLimit;
+
+ uint8 listenCount;
+ uint8 listenInterval;
+ uint10 beaconInterval;
+ uint2 preamble;
+ uint16 preBeacon;
+ uint11 random;
+
+ struct {
+ uint1 enable;
+ uint1 enableIrq;
+ uint1 enableTxMP;
+ uint64 count;
+ uint64 compare;
+ } timer;
+
+ uint2 config0d4;
+ uint12 config0d8;
+ uint16 config0da;
+ uint5 config0ecl;
+ uint6 config0ech;
+
+ uint9 config120l;
+ uint1 config120h;
+ uint16 config122;
+ uint16 config124;
+ uint16 config128;
+ uint12 config130;
+ uint12 config132l;
+ uint1 config132h;
+ uint16 configBeaconCount;
+
+ uint16 config140;
+ uint16 config142;
+ uint8 config144;
+ uint8 config146;
+ uint8 config148;
+ uint8 config14a;
+ uint16 config14c;
+
+ uint6 config150l;
+ uint8 config150h;
+ uint7 config154l;
+ uint1 config154m;
+ uint4 config154h;
+
+ uint2 reg1a0l;
+ uint2 reg1a0m;
+ uint1 reg1a0n;
+ uint1 reg1a0h;
+ uint2 reg1a2;
+ uint16 reg1a4;
+
+ struct {
+ uint16 enable, counterEnable, oflowEnable;
+ uint16 flags, counterFlags, oflowFlags;
+ } interrupt;
+
+ struct {
+ uint8 reg1b0;
+ uint16 reg1b2;
+ uint16 reg1b4;
+ uint16 reg1b6;
+ uint8 reg1b8;
+ uint8 reg1ba;
+ uint16 reg1bc;
+ uint16 reg1be;
+ uint16 txErrors;
+ uint16 rxPackets;
+ uint8 mpErrors[16];
+ } stats;
+
+ struct {
+ uint4 txIdle;
+ uint2 wakeRequest;
+ uint1 wakePending;
+ uint1 sleeping;
+ } pm;
+
+ // Baseband serial interface
+ struct {
+ uint16 header; // 01rw0000 aaaaaaaa (r/w, address)
+ uint8 read, write; // data sent and received
+ uint4 powerl;
+ uint1 powerh;
+ uint1 mode8, modeE;
+ uint1 busy;
+ uint1 clock;
+
+ uint8 time;
+ Event event;
+
+ uint8 regs[0x69];
+ } bb;
+
+ // RF serial interface
+ struct {
+ uint32 data; // r aaaaa dd dddddddd dddddddd (r/w, address, data)
+ uint6 length; // should be 24 bits
+ uint1 type; // should be 0
+ uint1 reserved;
+ uint1 busy;
+
+ uint8 time;
+ Event event;
+
+ uint18 regs[0x20];
+ } rf;
+};
+
+extern WIFI wifi;
\ No newline at end of file
diff --git a/bsnes/phoenix/Makefile b/bsnes/phoenix/Makefile
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/core/core.cpp b/bsnes/phoenix/core/core.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/core/core.hpp b/bsnes/phoenix/core/core.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/core/keyboard.hpp b/bsnes/phoenix/core/keyboard.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/core/layout/fixed-layout.cpp b/bsnes/phoenix/core/layout/fixed-layout.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/core/layout/fixed-layout.hpp b/bsnes/phoenix/core/layout/fixed-layout.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/core/layout/horizontal-layout.cpp b/bsnes/phoenix/core/layout/horizontal-layout.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/core/layout/horizontal-layout.hpp b/bsnes/phoenix/core/layout/horizontal-layout.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/core/layout/vertical-layout.cpp b/bsnes/phoenix/core/layout/vertical-layout.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/core/layout/vertical-layout.hpp b/bsnes/phoenix/core/layout/vertical-layout.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/core/state.hpp b/bsnes/phoenix/core/state.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/gtk/action/action.cpp b/bsnes/phoenix/gtk/action/action.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/gtk/action/check-item.cpp b/bsnes/phoenix/gtk/action/check-item.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/gtk/action/item.cpp b/bsnes/phoenix/gtk/action/item.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/gtk/action/menu.cpp b/bsnes/phoenix/gtk/action/menu.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/gtk/action/radio-item.cpp b/bsnes/phoenix/gtk/action/radio-item.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/gtk/action/separator.cpp b/bsnes/phoenix/gtk/action/separator.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/gtk/desktop.cpp b/bsnes/phoenix/gtk/desktop.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/gtk/dialog-window.cpp b/bsnes/phoenix/gtk/dialog-window.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/gtk/font.cpp b/bsnes/phoenix/gtk/font.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/gtk/keyboard.cpp b/bsnes/phoenix/gtk/keyboard.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/gtk/message-window.cpp b/bsnes/phoenix/gtk/message-window.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/gtk/mouse.cpp b/bsnes/phoenix/gtk/mouse.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/gtk/platform.cpp b/bsnes/phoenix/gtk/platform.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/gtk/platform.hpp b/bsnes/phoenix/gtk/platform.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/gtk/settings.cpp b/bsnes/phoenix/gtk/settings.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/gtk/timer.cpp b/bsnes/phoenix/gtk/timer.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/gtk/utility.cpp b/bsnes/phoenix/gtk/utility.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/gtk/widget/button.cpp b/bsnes/phoenix/gtk/widget/button.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/gtk/widget/canvas.cpp b/bsnes/phoenix/gtk/widget/canvas.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/gtk/widget/check-box.cpp b/bsnes/phoenix/gtk/widget/check-box.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/gtk/widget/combo-box.cpp b/bsnes/phoenix/gtk/widget/combo-box.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/gtk/widget/hex-edit.cpp b/bsnes/phoenix/gtk/widget/hex-edit.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/gtk/widget/horizontal-scroll-bar.cpp b/bsnes/phoenix/gtk/widget/horizontal-scroll-bar.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/gtk/widget/horizontal-slider.cpp b/bsnes/phoenix/gtk/widget/horizontal-slider.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/gtk/widget/label.cpp b/bsnes/phoenix/gtk/widget/label.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/gtk/widget/line-edit.cpp b/bsnes/phoenix/gtk/widget/line-edit.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/gtk/widget/list-view.cpp b/bsnes/phoenix/gtk/widget/list-view.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/gtk/widget/progress-bar.cpp b/bsnes/phoenix/gtk/widget/progress-bar.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/gtk/widget/radio-box.cpp b/bsnes/phoenix/gtk/widget/radio-box.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/gtk/widget/text-edit.cpp b/bsnes/phoenix/gtk/widget/text-edit.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/gtk/widget/vertical-scroll-bar.cpp b/bsnes/phoenix/gtk/widget/vertical-scroll-bar.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/gtk/widget/vertical-slider.cpp b/bsnes/phoenix/gtk/widget/vertical-slider.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/gtk/widget/viewport.cpp b/bsnes/phoenix/gtk/widget/viewport.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/gtk/widget/widget.cpp b/bsnes/phoenix/gtk/widget/widget.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/gtk/window.cpp b/bsnes/phoenix/gtk/window.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/phoenix.cpp b/bsnes/phoenix/phoenix.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/phoenix.hpp b/bsnes/phoenix/phoenix.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/qt/action/action.cpp b/bsnes/phoenix/qt/action/action.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/qt/action/check-item.cpp b/bsnes/phoenix/qt/action/check-item.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/qt/action/item.cpp b/bsnes/phoenix/qt/action/item.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/qt/action/menu.cpp b/bsnes/phoenix/qt/action/menu.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/qt/action/radio-item.cpp b/bsnes/phoenix/qt/action/radio-item.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/qt/action/separator.cpp b/bsnes/phoenix/qt/action/separator.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/qt/desktop.cpp b/bsnes/phoenix/qt/desktop.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/qt/dialog-window.cpp b/bsnes/phoenix/qt/dialog-window.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/qt/font.cpp b/bsnes/phoenix/qt/font.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/qt/keyboard.cpp b/bsnes/phoenix/qt/keyboard.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/qt/message-window.cpp b/bsnes/phoenix/qt/message-window.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/qt/mouse.cpp b/bsnes/phoenix/qt/mouse.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/qt/platform.cpp b/bsnes/phoenix/qt/platform.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/qt/platform.moc b/bsnes/phoenix/qt/platform.moc
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/qt/platform.moc.hpp b/bsnes/phoenix/qt/platform.moc.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/qt/settings.cpp b/bsnes/phoenix/qt/settings.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/qt/timer.cpp b/bsnes/phoenix/qt/timer.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/qt/utility.cpp b/bsnes/phoenix/qt/utility.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/qt/widget/button.cpp b/bsnes/phoenix/qt/widget/button.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/qt/widget/canvas.cpp b/bsnes/phoenix/qt/widget/canvas.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/qt/widget/check-box.cpp b/bsnes/phoenix/qt/widget/check-box.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/qt/widget/combo-box.cpp b/bsnes/phoenix/qt/widget/combo-box.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/qt/widget/hex-edit.cpp b/bsnes/phoenix/qt/widget/hex-edit.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/qt/widget/horizontal-scroll-bar.cpp b/bsnes/phoenix/qt/widget/horizontal-scroll-bar.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/qt/widget/horizontal-slider.cpp b/bsnes/phoenix/qt/widget/horizontal-slider.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/qt/widget/label.cpp b/bsnes/phoenix/qt/widget/label.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/qt/widget/line-edit.cpp b/bsnes/phoenix/qt/widget/line-edit.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/qt/widget/list-view.cpp b/bsnes/phoenix/qt/widget/list-view.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/qt/widget/progress-bar.cpp b/bsnes/phoenix/qt/widget/progress-bar.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/qt/widget/radio-box.cpp b/bsnes/phoenix/qt/widget/radio-box.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/qt/widget/text-edit.cpp b/bsnes/phoenix/qt/widget/text-edit.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/qt/widget/vertical-scroll-bar.cpp b/bsnes/phoenix/qt/widget/vertical-scroll-bar.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/qt/widget/vertical-slider.cpp b/bsnes/phoenix/qt/widget/vertical-slider.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/qt/widget/viewport.cpp b/bsnes/phoenix/qt/widget/viewport.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/qt/widget/widget.cpp b/bsnes/phoenix/qt/widget/widget.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/qt/window.cpp b/bsnes/phoenix/qt/window.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/reference/action/action.cpp b/bsnes/phoenix/reference/action/action.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/reference/action/check-item.cpp b/bsnes/phoenix/reference/action/check-item.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/reference/action/item.cpp b/bsnes/phoenix/reference/action/item.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/reference/action/menu.cpp b/bsnes/phoenix/reference/action/menu.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/reference/action/radio-item.cpp b/bsnes/phoenix/reference/action/radio-item.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/reference/action/separator.cpp b/bsnes/phoenix/reference/action/separator.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/reference/desktop.cpp b/bsnes/phoenix/reference/desktop.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/reference/dialog-window.cpp b/bsnes/phoenix/reference/dialog-window.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/reference/font.cpp b/bsnes/phoenix/reference/font.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/reference/keyboard.cpp b/bsnes/phoenix/reference/keyboard.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/reference/message-window.cpp b/bsnes/phoenix/reference/message-window.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/reference/mouse.cpp b/bsnes/phoenix/reference/mouse.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/reference/platform.cpp b/bsnes/phoenix/reference/platform.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/reference/platform.hpp b/bsnes/phoenix/reference/platform.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/reference/timer.cpp b/bsnes/phoenix/reference/timer.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/reference/widget/button.cpp b/bsnes/phoenix/reference/widget/button.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/reference/widget/canvas.cpp b/bsnes/phoenix/reference/widget/canvas.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/reference/widget/check-box.cpp b/bsnes/phoenix/reference/widget/check-box.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/reference/widget/combo-box.cpp b/bsnes/phoenix/reference/widget/combo-box.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/reference/widget/hex-edit.cpp b/bsnes/phoenix/reference/widget/hex-edit.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/reference/widget/horizontal-scroll-bar.cpp b/bsnes/phoenix/reference/widget/horizontal-scroll-bar.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/reference/widget/horizontal-slider.cpp b/bsnes/phoenix/reference/widget/horizontal-slider.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/reference/widget/label.cpp b/bsnes/phoenix/reference/widget/label.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/reference/widget/line-edit.cpp b/bsnes/phoenix/reference/widget/line-edit.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/reference/widget/list-view.cpp b/bsnes/phoenix/reference/widget/list-view.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/reference/widget/progress-bar.cpp b/bsnes/phoenix/reference/widget/progress-bar.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/reference/widget/radio-box.cpp b/bsnes/phoenix/reference/widget/radio-box.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/reference/widget/text-edit.cpp b/bsnes/phoenix/reference/widget/text-edit.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/reference/widget/vertical-scroll-bar.cpp b/bsnes/phoenix/reference/widget/vertical-scroll-bar.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/reference/widget/vertical-slider.cpp b/bsnes/phoenix/reference/widget/vertical-slider.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/reference/widget/viewport.cpp b/bsnes/phoenix/reference/widget/viewport.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/reference/widget/widget.cpp b/bsnes/phoenix/reference/widget/widget.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/reference/window.cpp b/bsnes/phoenix/reference/window.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/sync.sh b/bsnes/phoenix/sync.sh
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/windows/action/action.cpp b/bsnes/phoenix/windows/action/action.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/windows/action/check-item.cpp b/bsnes/phoenix/windows/action/check-item.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/windows/action/item.cpp b/bsnes/phoenix/windows/action/item.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/windows/action/menu.cpp b/bsnes/phoenix/windows/action/menu.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/windows/action/radio-item.cpp b/bsnes/phoenix/windows/action/radio-item.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/windows/action/separator.cpp b/bsnes/phoenix/windows/action/separator.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/windows/desktop.cpp b/bsnes/phoenix/windows/desktop.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/windows/dialog-window.cpp b/bsnes/phoenix/windows/dialog-window.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/windows/font.cpp b/bsnes/phoenix/windows/font.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/windows/keyboard.cpp b/bsnes/phoenix/windows/keyboard.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/windows/message-window.cpp b/bsnes/phoenix/windows/message-window.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/windows/mouse.cpp b/bsnes/phoenix/windows/mouse.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/windows/object.cpp b/bsnes/phoenix/windows/object.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/windows/phoenix.Manifest b/bsnes/phoenix/windows/phoenix.Manifest
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/windows/phoenix.rc b/bsnes/phoenix/windows/phoenix.rc
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/windows/platform.cpp b/bsnes/phoenix/windows/platform.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/windows/platform.hpp b/bsnes/phoenix/windows/platform.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/windows/settings.cpp b/bsnes/phoenix/windows/settings.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/windows/timer.cpp b/bsnes/phoenix/windows/timer.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/windows/utility.cpp b/bsnes/phoenix/windows/utility.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/windows/widget/button.cpp b/bsnes/phoenix/windows/widget/button.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/windows/widget/canvas.cpp b/bsnes/phoenix/windows/widget/canvas.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/windows/widget/check-box.cpp b/bsnes/phoenix/windows/widget/check-box.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/windows/widget/combo-box.cpp b/bsnes/phoenix/windows/widget/combo-box.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/windows/widget/hex-edit.cpp b/bsnes/phoenix/windows/widget/hex-edit.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/windows/widget/horizontal-scroll-bar.cpp b/bsnes/phoenix/windows/widget/horizontal-scroll-bar.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/windows/widget/horizontal-slider.cpp b/bsnes/phoenix/windows/widget/horizontal-slider.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/windows/widget/label.cpp b/bsnes/phoenix/windows/widget/label.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/windows/widget/line-edit.cpp b/bsnes/phoenix/windows/widget/line-edit.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/windows/widget/list-view.cpp b/bsnes/phoenix/windows/widget/list-view.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/windows/widget/progress-bar.cpp b/bsnes/phoenix/windows/widget/progress-bar.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/windows/widget/radio-box.cpp b/bsnes/phoenix/windows/widget/radio-box.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/windows/widget/text-edit.cpp b/bsnes/phoenix/windows/widget/text-edit.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/windows/widget/vertical-scroll-bar.cpp b/bsnes/phoenix/windows/widget/vertical-scroll-bar.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/windows/widget/vertical-slider.cpp b/bsnes/phoenix/windows/widget/vertical-slider.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/windows/widget/viewport.cpp b/bsnes/phoenix/windows/widget/viewport.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/windows/widget/widget.cpp b/bsnes/phoenix/windows/widget/widget.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/phoenix/windows/window.cpp b/bsnes/phoenix/windows/window.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/Makefile b/bsnes/processor/Makefile
old mode 100755
new mode 100644
diff --git a/bsnes/processor/arm/algorithms.cpp b/bsnes/processor/arm/algorithms.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/arm/arm.cpp b/bsnes/processor/arm/arm.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/arm/arm.hpp b/bsnes/processor/arm/arm.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/arm/disassembler.cpp b/bsnes/processor/arm/disassembler.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/arm/disassembler.hpp b/bsnes/processor/arm/disassembler.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/arm/instructions-arm.cpp b/bsnes/processor/arm/instructions-arm.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/arm/instructions-arm.hpp b/bsnes/processor/arm/instructions-arm.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/arm/instructions-thumb.cpp b/bsnes/processor/arm/instructions-thumb.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/arm/instructions-thumb.hpp b/bsnes/processor/arm/instructions-thumb.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/arm/registers.cpp b/bsnes/processor/arm/registers.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/arm/registers.hpp b/bsnes/processor/arm/registers.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/arm/serialization.cpp b/bsnes/processor/arm/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/gsu/gsu.cpp b/bsnes/processor/gsu/gsu.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/gsu/gsu.hpp b/bsnes/processor/gsu/gsu.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/gsu/instructions.cpp b/bsnes/processor/gsu/instructions.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/gsu/registers.hpp b/bsnes/processor/gsu/registers.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/gsu/serialization.cpp b/bsnes/processor/gsu/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/gsu/table.cpp b/bsnes/processor/gsu/table.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/hg51b/hg51b.cpp b/bsnes/processor/hg51b/hg51b.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/hg51b/hg51b.hpp b/bsnes/processor/hg51b/hg51b.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/hg51b/instructions.cpp b/bsnes/processor/hg51b/instructions.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/hg51b/registers.cpp b/bsnes/processor/hg51b/registers.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/hg51b/registers.hpp b/bsnes/processor/hg51b/registers.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/hg51b/serialization.cpp b/bsnes/processor/hg51b/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/lr35902/disassembler.cpp b/bsnes/processor/lr35902/disassembler.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/lr35902/instructions.cpp b/bsnes/processor/lr35902/instructions.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/lr35902/lr35902.cpp b/bsnes/processor/lr35902/lr35902.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/lr35902/lr35902.hpp b/bsnes/processor/lr35902/lr35902.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/lr35902/registers.hpp b/bsnes/processor/lr35902/registers.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/lr35902/serialization.cpp b/bsnes/processor/lr35902/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/processor.hpp b/bsnes/processor/processor.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/r6502/disassembler.cpp b/bsnes/processor/r6502/disassembler.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/r6502/instructions.cpp b/bsnes/processor/r6502/instructions.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/r6502/memory.cpp b/bsnes/processor/r6502/memory.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/r6502/r6502.cpp b/bsnes/processor/r6502/r6502.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/r6502/r6502.hpp b/bsnes/processor/r6502/r6502.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/r6502/registers.hpp b/bsnes/processor/r6502/registers.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/r6502/serialization.cpp b/bsnes/processor/r6502/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/r65816/algorithms.cpp b/bsnes/processor/r65816/algorithms.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/r65816/disassembler.cpp b/bsnes/processor/r65816/disassembler.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/r65816/disassembler.hpp b/bsnes/processor/r65816/disassembler.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/r65816/memory.hpp b/bsnes/processor/r65816/memory.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/r65816/opcode_misc.cpp b/bsnes/processor/r65816/opcode_misc.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/r65816/opcode_pc.cpp b/bsnes/processor/r65816/opcode_pc.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/r65816/opcode_read.cpp b/bsnes/processor/r65816/opcode_read.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/r65816/opcode_rmw.cpp b/bsnes/processor/r65816/opcode_rmw.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/r65816/opcode_write.cpp b/bsnes/processor/r65816/opcode_write.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/r65816/r65816.cpp b/bsnes/processor/r65816/r65816.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/r65816/r65816.hpp b/bsnes/processor/r65816/r65816.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/r65816/registers.hpp b/bsnes/processor/r65816/registers.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/r65816/serialization.cpp b/bsnes/processor/r65816/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/r65816/table.cpp b/bsnes/processor/r65816/table.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/spc700/algorithms.cpp b/bsnes/processor/spc700/algorithms.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/spc700/disassembler.cpp b/bsnes/processor/spc700/disassembler.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/spc700/instructions.cpp b/bsnes/processor/spc700/instructions.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/spc700/memory.hpp b/bsnes/processor/spc700/memory.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/spc700/registers.hpp b/bsnes/processor/spc700/registers.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/spc700/serialization.cpp b/bsnes/processor/spc700/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/spc700/spc700.cpp b/bsnes/processor/spc700/spc700.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/spc700/spc700.hpp b/bsnes/processor/spc700/spc700.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/upd96050/disassembler.cpp b/bsnes/processor/upd96050/disassembler.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/upd96050/instructions.cpp b/bsnes/processor/upd96050/instructions.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/upd96050/memory.cpp b/bsnes/processor/upd96050/memory.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/upd96050/registers.hpp b/bsnes/processor/upd96050/registers.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/upd96050/serialization.cpp b/bsnes/processor/upd96050/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/upd96050/upd96050.cpp b/bsnes/processor/upd96050/upd96050.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/processor/upd96050/upd96050.hpp b/bsnes/processor/upd96050/upd96050.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/profile/BS-X Satellaview.sfc/manifest.xml b/bsnes/profile/BS-X Satellaview.sfc/manifest.xml
old mode 100755
new mode 100644
diff --git a/bsnes/profile/Famicom.sys/manifest.xml b/bsnes/profile/Famicom.sys/manifest.xml
old mode 100755
new mode 100644
diff --git a/bsnes/profile/Game Boy Advance.sys/manifest.xml b/bsnes/profile/Game Boy Advance.sys/manifest.xml
old mode 100755
new mode 100644
diff --git a/bsnes/profile/Game Boy Color.sys/boot.rom b/bsnes/profile/Game Boy Color.sys/boot.rom
old mode 100755
new mode 100644
diff --git a/bsnes/profile/Game Boy Color.sys/manifest.xml b/bsnes/profile/Game Boy Color.sys/manifest.xml
old mode 100755
new mode 100644
diff --git a/bsnes/profile/Game Boy.sys/boot.rom b/bsnes/profile/Game Boy.sys/boot.rom
old mode 100755
new mode 100644
diff --git a/bsnes/profile/Game Boy.sys/manifest.xml b/bsnes/profile/Game Boy.sys/manifest.xml
old mode 100755
new mode 100644
diff --git a/bsnes/profile/Nintendo DS.sys/manifest.xml b/bsnes/profile/Nintendo DS.sys/manifest.xml
new file mode 100644
index 00000000..732887a3
--- /dev/null
+++ b/bsnes/profile/Nintendo DS.sys/manifest.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/bsnes/profile/Sufami Turbo.sfc/manifest.xml b/bsnes/profile/Sufami Turbo.sfc/manifest.xml
old mode 100755
new mode 100644
diff --git a/bsnes/profile/Super Famicom.sys/manifest.xml b/bsnes/profile/Super Famicom.sys/manifest.xml
old mode 100755
new mode 100644
diff --git a/bsnes/profile/Super Famicom.sys/spc700.rom b/bsnes/profile/Super Famicom.sys/spc700.rom
old mode 100755
new mode 100644
diff --git a/bsnes/profile/Super Game Boy.sfc/boot.rom b/bsnes/profile/Super Game Boy.sfc/boot.rom
old mode 100755
new mode 100644
diff --git a/bsnes/profile/Super Game Boy.sfc/manifest.xml b/bsnes/profile/Super Game Boy.sfc/manifest.xml
old mode 100755
new mode 100644
diff --git a/bsnes/ruby/Makefile b/bsnes/ruby/Makefile
old mode 100755
new mode 100644
diff --git a/bsnes/ruby/audio.hpp b/bsnes/ruby/audio.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/ruby/audio/alsa.cpp b/bsnes/ruby/audio/alsa.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/ruby/audio/ao.cpp b/bsnes/ruby/audio/ao.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/ruby/audio/directsound.cpp b/bsnes/ruby/audio/directsound.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/ruby/audio/openal.cpp b/bsnes/ruby/audio/openal.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/ruby/audio/oss.cpp b/bsnes/ruby/audio/oss.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/ruby/audio/pulseaudio.cpp b/bsnes/ruby/audio/pulseaudio.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/ruby/audio/pulseaudiosimple.cpp b/bsnes/ruby/audio/pulseaudiosimple.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/ruby/audio/xaudio2.cpp b/bsnes/ruby/audio/xaudio2.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/ruby/audio/xaudio2.hpp b/bsnes/ruby/audio/xaudio2.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/ruby/input.hpp b/bsnes/ruby/input.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/ruby/input/carbon.cpp b/bsnes/ruby/input/carbon.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/ruby/input/directinput.cpp b/bsnes/ruby/input/directinput.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/ruby/input/rawinput.cpp b/bsnes/ruby/input/rawinput.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/ruby/input/sdl.cpp b/bsnes/ruby/input/sdl.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/ruby/input/x.cpp b/bsnes/ruby/input/x.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/ruby/input/xlibkeys.hpp b/bsnes/ruby/input/xlibkeys.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/ruby/ruby.cpp b/bsnes/ruby/ruby.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/ruby/ruby.hpp b/bsnes/ruby/ruby.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/ruby/ruby_impl.cpp b/bsnes/ruby/ruby_impl.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/ruby/video.hpp b/bsnes/ruby/video.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/ruby/video/direct3d.cpp b/bsnes/ruby/video/direct3d.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/ruby/video/directdraw.cpp b/bsnes/ruby/video/directdraw.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/ruby/video/gdi.cpp b/bsnes/ruby/video/gdi.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/ruby/video/glx.cpp b/bsnes/ruby/video/glx.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/ruby/video/opengl.hpp b/bsnes/ruby/video/opengl.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/ruby/video/qtopengl.cpp b/bsnes/ruby/video/qtopengl.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/ruby/video/qtraster.cpp b/bsnes/ruby/video/qtraster.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/ruby/video/sdl.cpp b/bsnes/ruby/video/sdl.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/ruby/video/wgl.cpp b/bsnes/ruby/video/wgl.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/ruby/video/xshm.cpp b/bsnes/ruby/video/xshm.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/ruby/video/xv.cpp b/bsnes/ruby/video/xv.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/Makefile b/bsnes/sfc/Makefile
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/cpu/cpu.cpp b/bsnes/sfc/alt/cpu/cpu.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/cpu/cpu.hpp b/bsnes/sfc/alt/cpu/cpu.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/cpu/dma.cpp b/bsnes/sfc/alt/cpu/dma.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/cpu/memory.cpp b/bsnes/sfc/alt/cpu/memory.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/cpu/mmio.cpp b/bsnes/sfc/alt/cpu/mmio.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/cpu/serialization.cpp b/bsnes/sfc/alt/cpu/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/cpu/timing.cpp b/bsnes/sfc/alt/cpu/timing.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/dsp/SPC_DSP.cpp b/bsnes/sfc/alt/dsp/SPC_DSP.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/dsp/SPC_DSP.h b/bsnes/sfc/alt/dsp/SPC_DSP.h
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/dsp/blargg_common.h b/bsnes/sfc/alt/dsp/blargg_common.h
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/dsp/blargg_config.h b/bsnes/sfc/alt/dsp/blargg_config.h
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/dsp/blargg_endian.h b/bsnes/sfc/alt/dsp/blargg_endian.h
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/dsp/blargg_source.h b/bsnes/sfc/alt/dsp/blargg_source.h
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/dsp/dsp.cpp b/bsnes/sfc/alt/dsp/dsp.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/dsp/dsp.hpp b/bsnes/sfc/alt/dsp/dsp.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/dsp/serialization.cpp b/bsnes/sfc/alt/dsp/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/ppu-compatibility/memory/memory.cpp b/bsnes/sfc/alt/ppu-compatibility/memory/memory.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/ppu-compatibility/memory/memory.hpp b/bsnes/sfc/alt/ppu-compatibility/memory/memory.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/ppu-compatibility/mmio/mmio.cpp b/bsnes/sfc/alt/ppu-compatibility/mmio/mmio.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/ppu-compatibility/mmio/mmio.hpp b/bsnes/sfc/alt/ppu-compatibility/mmio/mmio.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/ppu-compatibility/ppu.cpp b/bsnes/sfc/alt/ppu-compatibility/ppu.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/ppu-compatibility/ppu.hpp b/bsnes/sfc/alt/ppu-compatibility/ppu.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/ppu-compatibility/render/addsub.cpp b/bsnes/sfc/alt/ppu-compatibility/render/addsub.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/ppu-compatibility/render/bg.cpp b/bsnes/sfc/alt/ppu-compatibility/render/bg.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/ppu-compatibility/render/cache.cpp b/bsnes/sfc/alt/ppu-compatibility/render/cache.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/ppu-compatibility/render/line.cpp b/bsnes/sfc/alt/ppu-compatibility/render/line.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/ppu-compatibility/render/mode7.cpp b/bsnes/sfc/alt/ppu-compatibility/render/mode7.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/ppu-compatibility/render/oam.cpp b/bsnes/sfc/alt/ppu-compatibility/render/oam.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/ppu-compatibility/render/render.cpp b/bsnes/sfc/alt/ppu-compatibility/render/render.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/ppu-compatibility/render/render.hpp b/bsnes/sfc/alt/ppu-compatibility/render/render.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/ppu-compatibility/render/windows.cpp b/bsnes/sfc/alt/ppu-compatibility/render/windows.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/ppu-compatibility/serialization.cpp b/bsnes/sfc/alt/ppu-compatibility/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/ppu-performance/background/background.cpp b/bsnes/sfc/alt/ppu-performance/background/background.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/ppu-performance/background/background.hpp b/bsnes/sfc/alt/ppu-performance/background/background.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/ppu-performance/background/mode7.cpp b/bsnes/sfc/alt/ppu-performance/background/mode7.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/ppu-performance/cache/cache.cpp b/bsnes/sfc/alt/ppu-performance/cache/cache.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/ppu-performance/cache/cache.hpp b/bsnes/sfc/alt/ppu-performance/cache/cache.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/ppu-performance/mmio/mmio.cpp b/bsnes/sfc/alt/ppu-performance/mmio/mmio.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/ppu-performance/mmio/mmio.hpp b/bsnes/sfc/alt/ppu-performance/mmio/mmio.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/ppu-performance/ppu.cpp b/bsnes/sfc/alt/ppu-performance/ppu.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/ppu-performance/ppu.hpp b/bsnes/sfc/alt/ppu-performance/ppu.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/ppu-performance/screen/screen.cpp b/bsnes/sfc/alt/ppu-performance/screen/screen.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/ppu-performance/screen/screen.hpp b/bsnes/sfc/alt/ppu-performance/screen/screen.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/ppu-performance/serialization.cpp b/bsnes/sfc/alt/ppu-performance/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/ppu-performance/sprite/sprite.cpp b/bsnes/sfc/alt/ppu-performance/sprite/sprite.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/ppu-performance/sprite/sprite.hpp b/bsnes/sfc/alt/ppu-performance/sprite/sprite.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/ppu-performance/window/window.cpp b/bsnes/sfc/alt/ppu-performance/window/window.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/ppu-performance/window/window.hpp b/bsnes/sfc/alt/ppu-performance/window/window.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/smp/algorithms.cpp b/bsnes/sfc/alt/smp/algorithms.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/smp/core.cpp b/bsnes/sfc/alt/smp/core.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/smp/core/cc.sh b/bsnes/sfc/alt/smp/core/cc.sh
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/smp/core/generate.cpp b/bsnes/sfc/alt/smp/core/generate.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/smp/core/op_misc.b b/bsnes/sfc/alt/smp/core/op_misc.b
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/smp/core/op_misc.cpp b/bsnes/sfc/alt/smp/core/op_misc.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/smp/core/op_mov.b b/bsnes/sfc/alt/smp/core/op_mov.b
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/smp/core/op_mov.cpp b/bsnes/sfc/alt/smp/core/op_mov.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/smp/core/op_pc.b b/bsnes/sfc/alt/smp/core/op_pc.b
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/smp/core/op_pc.cpp b/bsnes/sfc/alt/smp/core/op_pc.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/smp/core/op_read.b b/bsnes/sfc/alt/smp/core/op_read.b
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/smp/core/op_read.cpp b/bsnes/sfc/alt/smp/core/op_read.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/smp/core/op_rmw.b b/bsnes/sfc/alt/smp/core/op_rmw.b
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/smp/core/op_rmw.cpp b/bsnes/sfc/alt/smp/core/op_rmw.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/smp/core/opcycle_misc.cpp b/bsnes/sfc/alt/smp/core/opcycle_misc.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/smp/core/opcycle_mov.cpp b/bsnes/sfc/alt/smp/core/opcycle_mov.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/smp/core/opcycle_pc.cpp b/bsnes/sfc/alt/smp/core/opcycle_pc.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/smp/core/opcycle_read.cpp b/bsnes/sfc/alt/smp/core/opcycle_read.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/smp/core/opcycle_rmw.cpp b/bsnes/sfc/alt/smp/core/opcycle_rmw.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/smp/disassembler.cpp b/bsnes/sfc/alt/smp/disassembler.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/smp/memory.cpp b/bsnes/sfc/alt/smp/memory.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/smp/smp.cpp b/bsnes/sfc/alt/smp/smp.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/smp/smp.hpp b/bsnes/sfc/alt/smp/smp.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/alt/smp/timing.cpp b/bsnes/sfc/alt/smp/timing.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/cartridge/cartridge.cpp b/bsnes/sfc/cartridge/cartridge.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/cartridge/cartridge.hpp b/bsnes/sfc/cartridge/cartridge.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/cartridge/markup.cpp b/bsnes/sfc/cartridge/markup.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/cartridge/serialization.cpp b/bsnes/sfc/cartridge/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/cheat/cheat.cpp b/bsnes/sfc/cheat/cheat.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/cheat/cheat.hpp b/bsnes/sfc/cheat/cheat.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/armdsp/armdsp.cpp b/bsnes/sfc/chip/armdsp/armdsp.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/armdsp/armdsp.hpp b/bsnes/sfc/chip/armdsp/armdsp.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/armdsp/memory.cpp b/bsnes/sfc/chip/armdsp/memory.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/armdsp/registers.hpp b/bsnes/sfc/chip/armdsp/registers.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/armdsp/serialization.cpp b/bsnes/sfc/chip/armdsp/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/bsx/bsx.cpp b/bsnes/sfc/chip/bsx/bsx.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/bsx/bsx.hpp b/bsnes/sfc/chip/bsx/bsx.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/bsx/cartridge/cartridge.cpp b/bsnes/sfc/chip/bsx/cartridge/cartridge.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/bsx/cartridge/cartridge.hpp b/bsnes/sfc/chip/bsx/cartridge/cartridge.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/bsx/cartridge/serialization.cpp b/bsnes/sfc/chip/bsx/cartridge/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/bsx/flash/flash.cpp b/bsnes/sfc/chip/bsx/flash/flash.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/bsx/flash/flash.hpp b/bsnes/sfc/chip/bsx/flash/flash.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/bsx/satellaview/satellaview.cpp b/bsnes/sfc/chip/bsx/satellaview/satellaview.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/bsx/satellaview/satellaview.hpp b/bsnes/sfc/chip/bsx/satellaview/satellaview.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/chip.hpp b/bsnes/sfc/chip/chip.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/epsonrtc/epsonrtc.cpp b/bsnes/sfc/chip/epsonrtc/epsonrtc.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/epsonrtc/epsonrtc.hpp b/bsnes/sfc/chip/epsonrtc/epsonrtc.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/epsonrtc/memory.cpp b/bsnes/sfc/chip/epsonrtc/memory.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/epsonrtc/serialization.cpp b/bsnes/sfc/chip/epsonrtc/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/epsonrtc/time.cpp b/bsnes/sfc/chip/epsonrtc/time.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/hitachidsp/hitachidsp.cpp b/bsnes/sfc/chip/hitachidsp/hitachidsp.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/hitachidsp/hitachidsp.hpp b/bsnes/sfc/chip/hitachidsp/hitachidsp.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/hitachidsp/memory.cpp b/bsnes/sfc/chip/hitachidsp/memory.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/hitachidsp/mmio.hpp b/bsnes/sfc/chip/hitachidsp/mmio.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/hitachidsp/serialization.cpp b/bsnes/sfc/chip/hitachidsp/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/icd2/icd2.cpp b/bsnes/sfc/chip/icd2/icd2.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/icd2/icd2.hpp b/bsnes/sfc/chip/icd2/icd2.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/icd2/interface/interface.cpp b/bsnes/sfc/chip/icd2/interface/interface.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/icd2/interface/interface.hpp b/bsnes/sfc/chip/icd2/interface/interface.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/icd2/mmio/mmio.cpp b/bsnes/sfc/chip/icd2/mmio/mmio.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/icd2/mmio/mmio.hpp b/bsnes/sfc/chip/icd2/mmio/mmio.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/icd2/serialization.cpp b/bsnes/sfc/chip/icd2/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/msu1/msu1.cpp b/bsnes/sfc/chip/msu1/msu1.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/msu1/msu1.hpp b/bsnes/sfc/chip/msu1/msu1.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/msu1/serialization.cpp b/bsnes/sfc/chip/msu1/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/necdsp/necdsp.cpp b/bsnes/sfc/chip/necdsp/necdsp.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/necdsp/necdsp.hpp b/bsnes/sfc/chip/necdsp/necdsp.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/necdsp/serialization.cpp b/bsnes/sfc/chip/necdsp/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/nss/nss.cpp b/bsnes/sfc/chip/nss/nss.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/nss/nss.hpp b/bsnes/sfc/chip/nss/nss.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/obc1/obc1.cpp b/bsnes/sfc/chip/obc1/obc1.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/obc1/obc1.hpp b/bsnes/sfc/chip/obc1/obc1.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/obc1/serialization.cpp b/bsnes/sfc/chip/obc1/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/sa1/bus/bus.cpp b/bsnes/sfc/chip/sa1/bus/bus.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/sa1/bus/bus.hpp b/bsnes/sfc/chip/sa1/bus/bus.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/sa1/dma/dma.cpp b/bsnes/sfc/chip/sa1/dma/dma.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/sa1/dma/dma.hpp b/bsnes/sfc/chip/sa1/dma/dma.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/sa1/memory/memory.cpp b/bsnes/sfc/chip/sa1/memory/memory.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/sa1/memory/memory.hpp b/bsnes/sfc/chip/sa1/memory/memory.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/sa1/mmio/mmio.cpp b/bsnes/sfc/chip/sa1/mmio/mmio.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/sa1/mmio/mmio.hpp b/bsnes/sfc/chip/sa1/mmio/mmio.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/sa1/sa1.cpp b/bsnes/sfc/chip/sa1/sa1.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/sa1/sa1.hpp b/bsnes/sfc/chip/sa1/sa1.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/sa1/serialization.cpp b/bsnes/sfc/chip/sa1/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/sdd1/decomp.cpp b/bsnes/sfc/chip/sdd1/decomp.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/sdd1/decomp.hpp b/bsnes/sfc/chip/sdd1/decomp.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/sdd1/sdd1.cpp b/bsnes/sfc/chip/sdd1/sdd1.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/sdd1/sdd1.hpp b/bsnes/sfc/chip/sdd1/sdd1.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/sdd1/serialization.cpp b/bsnes/sfc/chip/sdd1/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/sharprtc/memory.cpp b/bsnes/sfc/chip/sharprtc/memory.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/sharprtc/serialization.cpp b/bsnes/sfc/chip/sharprtc/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/sharprtc/sharprtc.cpp b/bsnes/sfc/chip/sharprtc/sharprtc.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/sharprtc/sharprtc.hpp b/bsnes/sfc/chip/sharprtc/sharprtc.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/sharprtc/time.cpp b/bsnes/sfc/chip/sharprtc/time.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/spc7110/alu.cpp b/bsnes/sfc/chip/spc7110/alu.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/spc7110/data.cpp b/bsnes/sfc/chip/spc7110/data.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/spc7110/dcu.cpp b/bsnes/sfc/chip/spc7110/dcu.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/spc7110/decompressor.cpp b/bsnes/sfc/chip/spc7110/decompressor.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/spc7110/serialization.cpp b/bsnes/sfc/chip/spc7110/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/spc7110/spc7110.cpp b/bsnes/sfc/chip/spc7110/spc7110.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/spc7110/spc7110.hpp b/bsnes/sfc/chip/spc7110/spc7110.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/sufamiturbo/serialization.cpp b/bsnes/sfc/chip/sufamiturbo/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/sufamiturbo/sufamiturbo.cpp b/bsnes/sfc/chip/sufamiturbo/sufamiturbo.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/sufamiturbo/sufamiturbo.hpp b/bsnes/sfc/chip/sufamiturbo/sufamiturbo.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/superfx/bus/bus.cpp b/bsnes/sfc/chip/superfx/bus/bus.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/superfx/bus/bus.hpp b/bsnes/sfc/chip/superfx/bus/bus.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/superfx/core/core.cpp b/bsnes/sfc/chip/superfx/core/core.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/superfx/core/core.hpp b/bsnes/sfc/chip/superfx/core/core.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/superfx/disasm/disasm.cpp b/bsnes/sfc/chip/superfx/disasm/disasm.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/superfx/disasm/disasm.hpp b/bsnes/sfc/chip/superfx/disasm/disasm.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/superfx/memory/memory.cpp b/bsnes/sfc/chip/superfx/memory/memory.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/superfx/memory/memory.hpp b/bsnes/sfc/chip/superfx/memory/memory.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/superfx/mmio/mmio.cpp b/bsnes/sfc/chip/superfx/mmio/mmio.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/superfx/mmio/mmio.hpp b/bsnes/sfc/chip/superfx/mmio/mmio.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/superfx/serialization.cpp b/bsnes/sfc/chip/superfx/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/superfx/superfx.cpp b/bsnes/sfc/chip/superfx/superfx.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/superfx/superfx.hpp b/bsnes/sfc/chip/superfx/superfx.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/superfx/timing/timing.cpp b/bsnes/sfc/chip/superfx/timing/timing.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/chip/superfx/timing/timing.hpp b/bsnes/sfc/chip/superfx/timing/timing.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/config/config.cpp b/bsnes/sfc/config/config.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/config/config.hpp b/bsnes/sfc/config/config.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/controller/controller.cpp b/bsnes/sfc/controller/controller.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/controller/controller.hpp b/bsnes/sfc/controller/controller.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/controller/gamepad/gamepad.cpp b/bsnes/sfc/controller/gamepad/gamepad.cpp
old mode 100755
new mode 100644
index 23d838f9..e78f93d3
--- a/bsnes/sfc/controller/gamepad/gamepad.cpp
+++ b/bsnes/sfc/controller/gamepad/gamepad.cpp
@@ -2,21 +2,56 @@
uint2 Gamepad::data() {
if(counter >= 16) return 1;
- uint2 result = 0;
- if(counter < 12) result = interface->inputPoll(port, (unsigned)Input::Device::Joypad, counter);
- if(latched == 0) counter++;
- return result;
+ if(latched == 1) return interface->inputPoll(port, (unsigned)Input::Device::Joypad, (unsigned)Input::JoypadID::B);
+
+ //note: D-pad physically prevents up+down and left+right from being pressed at the same time
+ switch(counter++) {
+ case 0: return b;
+ case 1: return y;
+ case 2: return select;
+ case 3: return start;
+ case 4: return up & !down;
+ case 5: return down & !up;
+ case 6: return left & !right;
+ case 7: return right & !left;
+ case 8: return a;
+ case 9: return x;
+ case 10: return l;
+ case 11: return r;
+ }
+
+ return 0; //12-15: signature
}
void Gamepad::latch(bool data) {
if(latched == data) return;
latched = data;
counter = 0;
+
+ if(latched == 0) {
+ unsigned id = (unsigned)Input::Device::Joypad;
+ b = interface->inputPoll(port, id, 0);
+ y = interface->inputPoll(port, id, 1);
+ select = interface->inputPoll(port, id, 2);
+ start = interface->inputPoll(port, id, 3);
+ up = interface->inputPoll(port, id, 4);
+ down = interface->inputPoll(port, id, 5);
+ left = interface->inputPoll(port, id, 6);
+ right = interface->inputPoll(port, id, 7);
+ a = interface->inputPoll(port, id, 8);
+ x = interface->inputPoll(port, id, 9);
+ l = interface->inputPoll(port, id, 10);
+ r = interface->inputPoll(port, id, 11);
+ }
}
Gamepad::Gamepad(bool port) : Controller(port) {
latched = 0;
counter = 0;
+
+ b = y = select = start = 0;
+ up = down = left = right = 0;
+ a = x = l = r = 0;
}
#endif
diff --git a/bsnes/sfc/controller/gamepad/gamepad.hpp b/bsnes/sfc/controller/gamepad/gamepad.hpp
old mode 100755
new mode 100644
index c5ca69ca..9a12cebf
--- a/bsnes/sfc/controller/gamepad/gamepad.hpp
+++ b/bsnes/sfc/controller/gamepad/gamepad.hpp
@@ -6,4 +6,8 @@ struct Gamepad : Controller {
private:
bool latched;
unsigned counter;
+
+ bool b, y, select, start;
+ bool up, down, left, right;
+ bool a, x, l, r;
};
diff --git a/bsnes/sfc/controller/justifier/justifier.cpp b/bsnes/sfc/controller/justifier/justifier.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/controller/justifier/justifier.hpp b/bsnes/sfc/controller/justifier/justifier.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/controller/mouse/mouse.cpp b/bsnes/sfc/controller/mouse/mouse.cpp
old mode 100755
new mode 100644
index 9bc6f53d..83f647e6
--- a/bsnes/sfc/controller/mouse/mouse.cpp
+++ b/bsnes/sfc/controller/mouse/mouse.cpp
@@ -1,6 +1,11 @@
#ifdef CONTROLLER_CPP
uint2 Mouse::data() {
+ if(latched == 1) {
+ speed = (speed + 1) % 3;
+ return 0;
+ }
+
if(counter >= 32) return 1;
switch(counter++) { default:
@@ -13,33 +18,33 @@ uint2 Mouse::data() {
case 6: return 0;
case 7: return 0;
- case 8: return input.r;
- case 9: return input.l;
- case 10: return 0; //speed (0 = slow, 1 = normal, 2 = fast, 3 = unused)
- case 11: return 0; // ||
+ case 8: return r;
+ case 9: return l;
+ case 10: return (speed >> 1) & 1;
+ case 11: return (speed >> 0) & 1;
case 12: return 0; //signature
case 13: return 0; // ||
case 14: return 0; // ||
case 15: return 1; // ||
- case 16: return input.dy;
- case 17: return (input.y >> 6) & 1;
- case 18: return (input.y >> 5) & 1;
- case 19: return (input.y >> 4) & 1;
- case 20: return (input.y >> 3) & 1;
- case 21: return (input.y >> 2) & 1;
- case 22: return (input.y >> 1) & 1;
- case 23: return (input.y >> 0) & 1;
+ case 16: return dy;
+ case 17: return (y >> 6) & 1;
+ case 18: return (y >> 5) & 1;
+ case 19: return (y >> 4) & 1;
+ case 20: return (y >> 3) & 1;
+ case 21: return (y >> 2) & 1;
+ case 22: return (y >> 1) & 1;
+ case 23: return (y >> 0) & 1;
- case 24: return input.dx;
- case 25: return (input.x >> 6) & 1;
- case 26: return (input.x >> 5) & 1;
- case 27: return (input.x >> 4) & 1;
- case 28: return (input.x >> 3) & 1;
- case 29: return (input.x >> 2) & 1;
- case 30: return (input.x >> 1) & 1;
- case 31: return (input.x >> 0) & 1;
+ case 24: return dx;
+ case 25: return (x >> 6) & 1;
+ case 26: return (x >> 5) & 1;
+ case 27: return (x >> 4) & 1;
+ case 28: return (x >> 3) & 1;
+ case 29: return (x >> 2) & 1;
+ case 30: return (x >> 1) & 1;
+ case 31: return (x >> 0) & 1;
}
}
@@ -48,31 +53,38 @@ void Mouse::latch(bool data) {
latched = data;
counter = 0;
- input.x = interface->inputPoll(port, (unsigned)Input::Device::Mouse, (unsigned)Input::MouseID::X); //-n = left, 0 = center, +n = right
- input.y = interface->inputPoll(port, (unsigned)Input::Device::Mouse, (unsigned)Input::MouseID::Y); //-n = up, 0 = center, +n = down
- input.l = interface->inputPoll(port, (unsigned)Input::Device::Mouse, (unsigned)Input::MouseID::Left );
- input.r = interface->inputPoll(port, (unsigned)Input::Device::Mouse, (unsigned)Input::MouseID::Right);
+ x = interface->inputPoll(port, (unsigned)Input::Device::Mouse, (unsigned)Input::MouseID::X); //-n = left, 0 = center, +n = right
+ y = interface->inputPoll(port, (unsigned)Input::Device::Mouse, (unsigned)Input::MouseID::Y); //-n = up, 0 = center, +n = down
+ l = interface->inputPoll(port, (unsigned)Input::Device::Mouse, (unsigned)Input::MouseID::Left );
+ r = interface->inputPoll(port, (unsigned)Input::Device::Mouse, (unsigned)Input::MouseID::Right);
- input.dx = input.x < 0; //0 = right, 1 = left
- input.dy = input.y < 0; //0 = down, 1 = up
+ dx = x < 0; //0 = right, 1 = left
+ dy = y < 0; //0 = down, 1 = up
- if(input.x < 0) input.x = -input.x; //abs(position_x)
- if(input.y < 0) input.y = -input.y; //abs(position_y)
+ if(x < 0) x = -x; //abs(position_x)
+ if(y < 0) y = -y; //abs(position_y)
- input.x = min(127, input.x);
- input.y = min(127, input.y);
+ double multiplier = 1.0;
+ if(speed == 1) multiplier = 1.5;
+ if(speed == 2) multiplier = 2.0;
+ x = (double)x * multiplier;
+ y = (double)y * multiplier;
+
+ x = min(127, x);
+ y = min(127, y);
}
Mouse::Mouse(bool port) : Controller(port) {
latched = 0;
counter = 0;
- input.x = 0;
- input.y = 0;
- input.dx = 0;
- input.dy = 0;
- input.l = 0;
- input.r = 0;
+ speed = 0;
+ x = 0;
+ y = 0;
+ dx = 0;
+ dy = 0;
+ l = 0;
+ r = 0;
}
#endif
diff --git a/bsnes/sfc/controller/mouse/mouse.hpp b/bsnes/sfc/controller/mouse/mouse.hpp
old mode 100755
new mode 100644
index cc5871b0..2ecd9c3f
--- a/bsnes/sfc/controller/mouse/mouse.hpp
+++ b/bsnes/sfc/controller/mouse/mouse.hpp
@@ -7,12 +7,11 @@ private:
bool latched;
unsigned counter;
- struct MouseInput {
- signed x; //x-coordinate
- signed y; //y-coordinate
- bool dx; //x-direction
- bool dy; //y-direction
- bool l; //left button
- bool r; //right button
- } input;
+ unsigned speed; //0 = slow, 1 = normal, 2 = fast
+ signed x; //x-coordinate
+ signed y; //y-coordinate
+ bool dx; //x-direction
+ bool dy; //y-direction
+ bool l; //left button
+ bool r; //right button
};
diff --git a/bsnes/sfc/controller/multitap/multitap.cpp b/bsnes/sfc/controller/multitap/multitap.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/controller/multitap/multitap.hpp b/bsnes/sfc/controller/multitap/multitap.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/controller/superscope/superscope.cpp b/bsnes/sfc/controller/superscope/superscope.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/controller/superscope/superscope.hpp b/bsnes/sfc/controller/superscope/superscope.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/controller/usart/usart.cpp b/bsnes/sfc/controller/usart/usart.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/controller/usart/usart.hpp b/bsnes/sfc/controller/usart/usart.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/cpu/cpu.cpp b/bsnes/sfc/cpu/cpu.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/cpu/cpu.hpp b/bsnes/sfc/cpu/cpu.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/cpu/dma/dma.cpp b/bsnes/sfc/cpu/dma/dma.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/cpu/dma/dma.hpp b/bsnes/sfc/cpu/dma/dma.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/cpu/memory/memory.cpp b/bsnes/sfc/cpu/memory/memory.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/cpu/memory/memory.hpp b/bsnes/sfc/cpu/memory/memory.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/cpu/mmio/mmio.cpp b/bsnes/sfc/cpu/mmio/mmio.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/cpu/mmio/mmio.hpp b/bsnes/sfc/cpu/mmio/mmio.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/cpu/serialization.cpp b/bsnes/sfc/cpu/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/cpu/timing/irq.cpp b/bsnes/sfc/cpu/timing/irq.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/cpu/timing/joypad.cpp b/bsnes/sfc/cpu/timing/joypad.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/cpu/timing/timing.cpp b/bsnes/sfc/cpu/timing/timing.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/cpu/timing/timing.hpp b/bsnes/sfc/cpu/timing/timing.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/dsp/brr.cpp b/bsnes/sfc/dsp/brr.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/dsp/counter.cpp b/bsnes/sfc/dsp/counter.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/dsp/dsp.cpp b/bsnes/sfc/dsp/dsp.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/dsp/dsp.hpp b/bsnes/sfc/dsp/dsp.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/dsp/echo.cpp b/bsnes/sfc/dsp/echo.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/dsp/envelope.cpp b/bsnes/sfc/dsp/envelope.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/dsp/gaussian.cpp b/bsnes/sfc/dsp/gaussian.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/dsp/misc.cpp b/bsnes/sfc/dsp/misc.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/dsp/moduloarray.hpp b/bsnes/sfc/dsp/moduloarray.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/dsp/serialization.cpp b/bsnes/sfc/dsp/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/dsp/voice.cpp b/bsnes/sfc/dsp/voice.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/interface/interface.cpp b/bsnes/sfc/interface/interface.cpp
old mode 100755
new mode 100644
index dc4ebda6..61b51986
--- a/bsnes/sfc/interface/interface.cpp
+++ b/bsnes/sfc/interface/interface.cpp
@@ -285,7 +285,7 @@ void Interface::paletteUpdate() {
bool Interface::tracerEnable(bool trace) {
string pathname = {path(group(ID::ROM)), "debug/"};
- directory::create(pathname);
+ if(trace == true) directory::create(pathname);
if(trace == true && !tracer.open()) {
for(unsigned n = 0; n <= 999; n++) {
diff --git a/bsnes/sfc/interface/interface.hpp b/bsnes/sfc/interface/interface.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/memory/memory-inline.hpp b/bsnes/sfc/memory/memory-inline.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/memory/memory.cpp b/bsnes/sfc/memory/memory.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/memory/memory.hpp b/bsnes/sfc/memory/memory.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/ppu/background/background.cpp b/bsnes/sfc/ppu/background/background.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/ppu/background/background.hpp b/bsnes/sfc/ppu/background/background.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/ppu/background/mode7.cpp b/bsnes/sfc/ppu/background/mode7.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/ppu/counter/counter-inline.hpp b/bsnes/sfc/ppu/counter/counter-inline.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/ppu/counter/counter.hpp b/bsnes/sfc/ppu/counter/counter.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/ppu/mmio/mmio.cpp b/bsnes/sfc/ppu/mmio/mmio.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/ppu/mmio/mmio.hpp b/bsnes/sfc/ppu/mmio/mmio.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/ppu/ppu.cpp b/bsnes/sfc/ppu/ppu.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/ppu/ppu.hpp b/bsnes/sfc/ppu/ppu.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/ppu/screen/screen.cpp b/bsnes/sfc/ppu/screen/screen.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/ppu/screen/screen.hpp b/bsnes/sfc/ppu/screen/screen.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/ppu/serialization.cpp b/bsnes/sfc/ppu/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/ppu/sprite/list.cpp b/bsnes/sfc/ppu/sprite/list.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/ppu/sprite/sprite.cpp b/bsnes/sfc/ppu/sprite/sprite.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/ppu/sprite/sprite.hpp b/bsnes/sfc/ppu/sprite/sprite.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/ppu/window/window.cpp b/bsnes/sfc/ppu/window/window.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/ppu/window/window.hpp b/bsnes/sfc/ppu/window/window.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/profile-accuracy.hpp b/bsnes/sfc/profile-accuracy.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/profile-compatibility.hpp b/bsnes/sfc/profile-compatibility.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/profile-performance.hpp b/bsnes/sfc/profile-performance.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/random/random.cpp b/bsnes/sfc/random/random.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/random/random.hpp b/bsnes/sfc/random/random.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/scheduler/scheduler.cpp b/bsnes/sfc/scheduler/scheduler.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/scheduler/scheduler.hpp b/bsnes/sfc/scheduler/scheduler.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/sfc.hpp b/bsnes/sfc/sfc.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/smp/memory.cpp b/bsnes/sfc/smp/memory.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/smp/serialization.cpp b/bsnes/sfc/smp/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/smp/smp.cpp b/bsnes/sfc/smp/smp.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/smp/smp.hpp b/bsnes/sfc/smp/smp.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/smp/timing.cpp b/bsnes/sfc/smp/timing.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/system/audio.cpp b/bsnes/sfc/system/audio.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/system/audio.hpp b/bsnes/sfc/system/audio.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/system/input.cpp b/bsnes/sfc/system/input.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/system/input.hpp b/bsnes/sfc/system/input.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/system/serialization.cpp b/bsnes/sfc/system/serialization.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/system/system.cpp b/bsnes/sfc/system/system.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/system/system.hpp b/bsnes/sfc/system/system.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/system/video.cpp b/bsnes/sfc/system/video.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/sfc/system/video.hpp b/bsnes/sfc/system/video.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/Makefile b/bsnes/target-ethos/Makefile
old mode 100755
new mode 100644
index a7606d94..a42fcac5
--- a/bsnes/target-ethos/Makefile
+++ b/bsnes/target-ethos/Makefile
@@ -5,6 +5,7 @@ include fc/Makefile
include sfc/Makefile
include gb/Makefile
include gba/Makefile
+include nds/Makefile
name := bsnes
ui_objects := ui-ethos ui-configuration ui-interface ui-utility
@@ -56,8 +57,11 @@ obj/phoenix.o: phoenix/phoenix.cpp $(call rwildcard,phoenix/*)
$(call compile,$(phoenixflags))
obj/resource.o: $(ui)/resource.rc
-# windres --target=pe-i386 $(ui)/resource.rc obj/resource.o
+ifeq ($(arch),win32)
+ windres --target=pe-i386 $(ui)/resource.rc obj/resource.o
+else
windres $(ui)/resource.rc obj/resource.o
+endif
# targets
build: $(objects)
diff --git a/bsnes/target-ethos/bootstrap.cpp b/bsnes/target-ethos/bootstrap.cpp
old mode 100755
new mode 100644
index 00d8ff79..93b2f1d8
--- a/bsnes/target-ethos/bootstrap.cpp
+++ b/bsnes/target-ethos/bootstrap.cpp
@@ -2,6 +2,7 @@
#include
#include
#include
+#include
void Application::bootstrap() {
interface = new Interface;
@@ -10,6 +11,7 @@ void Application::bootstrap() {
emulator.append(new SuperFamicom::Interface);
emulator.append(new GameBoy::Interface);
emulator.append(new GameBoyAdvance::Interface);
+ emulator.append(new NintendoDS::Interface);
for(auto &system : emulator) system->bind = interface;
}
diff --git a/bsnes/target-ethos/configuration/configuration.cpp b/bsnes/target-ethos/configuration/configuration.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/configuration/configuration.hpp b/bsnes/target-ethos/configuration/configuration.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/ethos.cpp b/bsnes/target-ethos/ethos.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/ethos.hpp b/bsnes/target-ethos/ethos.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/general/browser.cpp b/bsnes/target-ethos/general/browser.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/general/browser.hpp b/bsnes/target-ethos/general/browser.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/general/dip-switches.cpp b/bsnes/target-ethos/general/dip-switches.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/general/dip-switches.hpp b/bsnes/target-ethos/general/dip-switches.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/general/general.cpp b/bsnes/target-ethos/general/general.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/general/general.hpp b/bsnes/target-ethos/general/general.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/general/presentation.cpp b/bsnes/target-ethos/general/presentation.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/general/presentation.hpp b/bsnes/target-ethos/general/presentation.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/input/hotkeys.cpp b/bsnes/target-ethos/input/hotkeys.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/input/input.cpp b/bsnes/target-ethos/input/input.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/input/input.hpp b/bsnes/target-ethos/input/input.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/interface/interface.cpp b/bsnes/target-ethos/interface/interface.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/interface/interface.hpp b/bsnes/target-ethos/interface/interface.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/resource.rc b/bsnes/target-ethos/resource.rc
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/resource/folder.png b/bsnes/target-ethos/resource/folder.png
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/resource/game.png b/bsnes/target-ethos/resource/game.png
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/resource/home.png b/bsnes/target-ethos/resource/home.png
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/resource/resource.cpp b/bsnes/target-ethos/resource/resource.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/resource/resource.hpp b/bsnes/target-ethos/resource/resource.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/resource/resource.xml b/bsnes/target-ethos/resource/resource.xml
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/resource/up.png b/bsnes/target-ethos/resource/up.png
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/settings/audio.cpp b/bsnes/target-ethos/settings/audio.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/settings/audio.hpp b/bsnes/target-ethos/settings/audio.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/settings/driver.cpp b/bsnes/target-ethos/settings/driver.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/settings/driver.hpp b/bsnes/target-ethos/settings/driver.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/settings/hotkey.cpp b/bsnes/target-ethos/settings/hotkey.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/settings/hotkey.hpp b/bsnes/target-ethos/settings/hotkey.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/settings/input.cpp b/bsnes/target-ethos/settings/input.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/settings/input.hpp b/bsnes/target-ethos/settings/input.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/settings/settings.cpp b/bsnes/target-ethos/settings/settings.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/settings/settings.hpp b/bsnes/target-ethos/settings/settings.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/settings/timing.cpp b/bsnes/target-ethos/settings/timing.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/settings/timing.hpp b/bsnes/target-ethos/settings/timing.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/settings/video.cpp b/bsnes/target-ethos/settings/video.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/settings/video.hpp b/bsnes/target-ethos/settings/video.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/tools/cheat-database.cpp b/bsnes/target-ethos/tools/cheat-database.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/tools/cheat-database.hpp b/bsnes/target-ethos/tools/cheat-database.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/tools/cheat-editor.cpp b/bsnes/target-ethos/tools/cheat-editor.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/tools/cheat-editor.hpp b/bsnes/target-ethos/tools/cheat-editor.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/tools/state-manager.cpp b/bsnes/target-ethos/tools/state-manager.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/tools/state-manager.hpp b/bsnes/target-ethos/tools/state-manager.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/tools/tools.cpp b/bsnes/target-ethos/tools/tools.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/tools/tools.hpp b/bsnes/target-ethos/tools/tools.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/utility/utility.cpp b/bsnes/target-ethos/utility/utility.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/utility/utility.hpp b/bsnes/target-ethos/utility/utility.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/window/window.cpp b/bsnes/target-ethos/window/window.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-ethos/window/window.hpp b/bsnes/target-ethos/window/window.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-laevateinn/Makefile b/bsnes/target-laevateinn/Makefile
old mode 100755
new mode 100644
diff --git a/bsnes/target-laevateinn/base.hpp b/bsnes/target-laevateinn/base.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-laevateinn/breakpoint/breakpoint.cpp b/bsnes/target-laevateinn/breakpoint/breakpoint.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-laevateinn/breakpoint/breakpoint.hpp b/bsnes/target-laevateinn/breakpoint/breakpoint.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-laevateinn/console/about.cpp b/bsnes/target-laevateinn/console/about.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-laevateinn/console/console.cpp b/bsnes/target-laevateinn/console/console.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-laevateinn/console/console.hpp b/bsnes/target-laevateinn/console/console.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-laevateinn/cpu/cpu.cpp b/bsnes/target-laevateinn/cpu/cpu.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-laevateinn/cpu/cpu.hpp b/bsnes/target-laevateinn/cpu/cpu.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-laevateinn/cpu/registers.cpp b/bsnes/target-laevateinn/cpu/registers.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-laevateinn/debugger/debugger.cpp b/bsnes/target-laevateinn/debugger/debugger.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-laevateinn/debugger/debugger.hpp b/bsnes/target-laevateinn/debugger/debugger.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-laevateinn/debugger/hook.cpp b/bsnes/target-laevateinn/debugger/hook.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-laevateinn/debugger/usage.cpp b/bsnes/target-laevateinn/debugger/usage.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-laevateinn/interface/interface.cpp b/bsnes/target-laevateinn/interface/interface.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-laevateinn/interface/interface.hpp b/bsnes/target-laevateinn/interface/interface.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-laevateinn/main.cpp b/bsnes/target-laevateinn/main.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-laevateinn/memory/memory.cpp b/bsnes/target-laevateinn/memory/memory.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-laevateinn/memory/memory.hpp b/bsnes/target-laevateinn/memory/memory.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-laevateinn/properties/properties.cpp b/bsnes/target-laevateinn/properties/properties.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-laevateinn/properties/properties.hpp b/bsnes/target-laevateinn/properties/properties.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-laevateinn/resource.rc b/bsnes/target-laevateinn/resource.rc
old mode 100755
new mode 100644
diff --git a/bsnes/target-laevateinn/settings/settings.cpp b/bsnes/target-laevateinn/settings/settings.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-laevateinn/settings/settings.hpp b/bsnes/target-laevateinn/settings/settings.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-laevateinn/smp/registers.cpp b/bsnes/target-laevateinn/smp/registers.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-laevateinn/smp/smp.cpp b/bsnes/target-laevateinn/smp/smp.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-laevateinn/smp/smp.hpp b/bsnes/target-laevateinn/smp/smp.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-laevateinn/tracer/tracer.cpp b/bsnes/target-laevateinn/tracer/tracer.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-laevateinn/tracer/tracer.hpp b/bsnes/target-laevateinn/tracer/tracer.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-laevateinn/video/video.cpp b/bsnes/target-laevateinn/video/video.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-laevateinn/video/video.hpp b/bsnes/target-laevateinn/video/video.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-laevateinn/vram/vram.cpp b/bsnes/target-laevateinn/vram/vram.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-laevateinn/vram/vram.hpp b/bsnes/target-laevateinn/vram/vram.hpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-laevateinn/window/window.cpp b/bsnes/target-laevateinn/window/window.cpp
old mode 100755
new mode 100644
diff --git a/bsnes/target-laevateinn/window/window.hpp b/bsnes/target-laevateinn/window/window.hpp
old mode 100755
new mode 100644
diff --git a/kaijuu/Makefile b/kaijuu/Makefile
new file mode 100644
index 00000000..63b1d771
--- /dev/null
+++ b/kaijuu/Makefile
@@ -0,0 +1,18 @@
+# for Linux only; to synchronize includes and resources
+# use cc32.bat and cc64.bat for Windows compilation
+
+include nall/Makefile
+
+resource: force
+ sourcery resource/resource.xml resource/resource.cpp resource/resource.hpp
+
+sync:
+ if [ -d ./nall ]; then rm -r ./nall; fi
+ if [ -d ./phoenix ]; then rm -r ./phoenix; fi
+ cp -r ../nall ./nall
+ cp -r ../phoenix ./phoenix
+ rm -r nall/test
+ rm -r phoenix/nall
+ rm -r phoenix/test
+
+force:
diff --git a/kaijuu/cc32.bat b/kaijuu/cc32.bat
new file mode 100755
index 00000000..60caa857
--- /dev/null
+++ b/kaijuu/cc32.bat
@@ -0,0 +1,8 @@
+windres --target=pe-i386 kaijuu.rc kaijuu-resource.o
+g++ -m32 -I. -std=gnu++0x -O3 -fomit-frame-pointer -c kaijuu.cpp
+g++ -m32 -shared -static-libgcc -Wl,kaijuu.def -Wl,-enable-stdcall-fixup -s -o kaijuu32.dll kaijuu.o -lm -lole32 -luuid -lshlwapi
+g++ -m32 -I. -std=gnu++0x -O3 -fomit-frame-pointer -o phoenix.o -c phoenix/phoenix.cpp -DPHOENIX_WINDOWS
+g++ -m32 -I. -std=gnu++0x -O3 -fomit-frame-pointer -c interface.cpp
+g++ -m32 -mwindows -s -o kaijuu32.exe interface.o kaijuu-resource.o phoenix.o -lkernel32 -luser32 -lgdi32 -ladvapi32 -lole32 -lcomctl32 -lcomdlg32 -lshlwapi
+@pause
+@del *.o
diff --git a/kaijuu/cc64.bat b/kaijuu/cc64.bat
new file mode 100755
index 00000000..01b65370
--- /dev/null
+++ b/kaijuu/cc64.bat
@@ -0,0 +1,8 @@
+windres kaijuu.rc kaijuu-resource.o
+g++ -m64 -I. -std=gnu++0x -O3 -fomit-frame-pointer -c kaijuu.cpp
+g++ -m64 -shared -static-libgcc -Wl,kaijuu.def -Wl,-enable-stdcall-fixup -s -o kaijuu64.dll kaijuu.o -lm -lole32 -luuid -lshlwapi
+g++ -m64 -I. -std=gnu++0x -O3 -fomit-frame-pointer -o phoenix.o -c phoenix/phoenix.cpp -DPHOENIX_WINDOWS
+g++ -m64 -I. -std=gnu++0x -O3 -fomit-frame-pointer -c interface.cpp
+g++ -m64 -mwindows -s -o kaijuu64.exe interface.o kaijuu-resource.o phoenix.o -lkernel32 -luser32 -lgdi32 -ladvapi32 -lole32 -lcomctl32 -lcomdlg32 -lshlwapi
+@pause
+@del *.o
diff --git a/kaijuu/extension.cpp b/kaijuu/extension.cpp
new file mode 100644
index 00000000..512a4184
--- /dev/null
+++ b/kaijuu/extension.cpp
@@ -0,0 +1,175 @@
+CShellExt::CShellExt() {
+ instanceCount = 0;
+ referenceCount++;
+}
+
+CShellExt::~CShellExt() {
+ referenceCount--;
+}
+
+STDMETHODIMP CShellExt::QueryInterface(REFIID riid, LPVOID *ppv) {
+ *ppv = nullptr;
+
+ if(IsEqualIID(riid, IID_IShellExtInit) || IsEqualIID(riid, IID_IUnknown)) {
+ *ppv = (IShellExtInit*)this;
+ } else if(IsEqualIID(riid, IID_IContextMenu)) {
+ *ppv = (IContextMenu*)this;
+ }
+
+ if(*ppv) {
+ AddRef();
+ return NOERROR;
+ }
+
+ return E_NOINTERFACE;
+}
+
+STDMETHODIMP_(ULONG) CShellExt::AddRef() {
+ return ++instanceCount;
+}
+
+STDMETHODIMP_(ULONG) CShellExt::Release() {
+ if(--instanceCount) return instanceCount;
+ delete this;
+ return 0;
+}
+
+STDMETHODIMP CShellExt::Initialize(LPCITEMIDLIST pIDFolder, IDataObject *pDataObject, HKEY hRegKey) {
+ fileList.reset();
+
+ if(pDataObject) {
+ wchar_t filename[PATH_MAX];
+ STGMEDIUM medium;
+ FORMATETC fe = {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
+ HDROP hDrop;
+
+ if(FAILED(pDataObject->GetData(&fe, &medium))) return E_INVALIDARG;
+ hDrop = (HDROP)GlobalLock(medium.hGlobal);
+ if(hDrop == NULL) return E_INVALIDARG;
+
+ fileList.reset();
+ unsigned count = DragQueryFileW(hDrop, 0xffffffff, NULL, 0);
+ for(unsigned i = 0; i < count; i++) {
+ DragQueryFileW((HDROP)medium.hGlobal, i, filename, PATH_MAX);
+ string name = (const char*)utf8_t(filename);
+ name.transform("/", "\\");
+ if(name.endswith("\\")) name.rtrim<1>("\\");
+ fileList.append(name);
+ }
+ GlobalUnlock(medium.hGlobal);
+ ReleaseStgMedium(&medium);
+ }
+
+ return S_OK;
+}
+
+STDMETHODIMP CShellExt::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags) {
+ settings.load();
+ unsigned idCmd = idCmdFirst;
+ bool firstDefault = true;
+
+ auto ruleIDs = matchedRules();
+ for(auto &ruleID : ruleIDs) {
+ auto &rule = settings.rules(ruleID);
+ if(idCmd < idCmdLast) {
+ InsertMenuW(hMenu, indexMenu, MF_STRING | MF_BYPOSITION, idCmd++, (const wchar_t*)utf16_t(rule.name));
+ if(rule.defaultAction && firstDefault) {
+ firstDefault = false; //there can be only one default menu item
+ SetMenuDefaultItem(hMenu, indexMenu, TRUE);
+ }
+ indexMenu++;
+ }
+ }
+
+ return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(idCmd - idCmdFirst));
+}
+
+STDMETHODIMP CShellExt::GetCommandString(UINT_PTR idCmd, UINT uFlags, LPUINT lpReserved, LPSTR pszName, UINT uMaxNameLen) {
+ if(idCmd < settings.rules.size()) return S_OK;
+ return E_INVALIDARG;
+}
+
+STDMETHODIMP CShellExt::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi) {
+ if(HIWORD(lpcmi->lpVerb) != 0) return E_INVALIDARG; //ignore actual string verbs
+
+ settings.load();
+ unsigned id = LOWORD(lpcmi->lpVerb);
+ auto ruleIDs = matchedRules();
+ auto &rule = settings.rules(ruleIDs(id));
+
+ string nameID = fileList(0);
+ string pathnameID = dir(nameID).rtrim<1>("\\");
+ string filenameID = notdir(nameID);
+ string basenameID = notdir(nall::basename(nameID));
+ string extensionID = extension(nameID);
+
+ string pathID = {"\"", pathnameID, "\""};
+ string fileID = {"\"", nameID, "\""};
+
+ string pathsID, filesID;
+ for(auto &filename : fileList) pathsID.append("\"", dir(filename).rtrim<1>("\\"), "\"", " ");
+ for(auto &filename : fileList) filesID.append("\"", filename, "\"", " ");
+ pathsID.rtrim<1>(" "), filesID.rtrim<1>(" ");
+
+ lstring params = rule.command.qsplit<1>(" ");
+ params(1).replace("{name}", nameID);
+ params(1).replace("{pathname}", pathnameID);
+ params(1).replace("{filename}", filenameID);
+ params(1).replace("{basename}", basenameID);
+ params(1).replace("{extension}", extensionID);
+
+ params(1).replace("{path}", pathID);
+ params(1).replace("{file}", fileID);
+
+ params(1).replace("{paths}", pathsID);
+ params(1).replace("{files}", filesID);
+
+ if((intptr_t)ShellExecuteW(NULL, L"open", utf16_t(params(0)), utf16_t(params(1)), utf16_t(pathnameID), SW_SHOWNORMAL) <= 32) {
+ MessageBoxW(0, L"Error opening associated program.", L"kaijuu", MB_OK);
+ }
+
+ return S_OK;
+}
+
+vector CShellExt::matchedRules() {
+ vector matched;
+ if(fileList.size() == 0) return matched;
+
+ for(unsigned id = 0; id < settings.rules.size(); id++) {
+ auto &rule = settings.rules(id);
+ if(rule.multiSelection == false && fileList.size() > 1) continue;
+ bool proceed = true;
+ for(auto &filename : fileList) {
+ string name = filename;
+ if(directory::exists(name)) {
+ if(rule.matchFolders == false) {
+ proceed = false;
+ break;
+ }
+ } else {
+ if(rule.matchFiles == false) {
+ proceed = false;
+ break;
+ }
+ }
+ name = notdir(name);
+
+ lstring patternList = rule.pattern.split(";");
+ bool found = false;
+ for(auto &pattern : patternList) {
+ if(name.wildcard(pattern)) {
+ found = true;
+ break;
+ }
+ }
+ if(found == false) {
+ proceed = false;
+ break;
+ }
+ }
+ if(proceed == false) continue;
+ matched.append(id);
+ }
+
+ return matched;
+}
diff --git a/kaijuu/extension.hpp b/kaijuu/extension.hpp
new file mode 100644
index 00000000..424ba4d5
--- /dev/null
+++ b/kaijuu/extension.hpp
@@ -0,0 +1,23 @@
+struct CShellExt : IContextMenu, IShellExtInit {
+protected:
+ unsigned instanceCount;
+ lstring fileList;
+
+public:
+ CShellExt();
+ ~CShellExt();
+
+ STDMETHODIMP QueryInterface(REFIID, LPVOID*);
+ STDMETHODIMP_(ULONG) AddRef();
+ STDMETHODIMP_(ULONG) Release();
+
+ STDMETHODIMP QueryContextMenu(HMENU, UINT, UINT, UINT, UINT);
+ STDMETHODIMP InvokeCommand(LPCMINVOKECOMMANDINFO);
+ STDMETHODIMP GetCommandString(UINT_PTR, UINT, UINT FAR*, LPSTR, UINT);
+ STDMETHODIMP Initialize(LPCITEMIDLIST, LPDATAOBJECT, HKEY);
+
+private:
+ vector matchedRules();
+};
+
+typedef CShellExt *LPCSHELLEXT;
\ No newline at end of file
diff --git a/kaijuu/factory.cpp b/kaijuu/factory.cpp
new file mode 100644
index 00000000..86503ab1
--- /dev/null
+++ b/kaijuu/factory.cpp
@@ -0,0 +1,40 @@
+CShellExtClassFactory::CShellExtClassFactory() {
+ instanceCount = 0;
+ referenceCount++;
+}
+
+CShellExtClassFactory::~CShellExtClassFactory() {
+ referenceCount--;
+}
+
+STDMETHODIMP CShellExtClassFactory::QueryInterface(REFIID riid, LPVOID *ppv) {
+ *ppv = NULL;
+ if(IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IClassFactory)) {
+ *ppv = (LPCLASSFACTORY)this;
+ AddRef();
+ return NOERROR;
+ }
+ return E_NOINTERFACE;
+}
+
+STDMETHODIMP_(ULONG) CShellExtClassFactory::AddRef() {
+ return ++instanceCount;
+}
+
+STDMETHODIMP_(ULONG) CShellExtClassFactory::Release() {
+ if(--instanceCount) return instanceCount;
+ delete this;
+ return 0;
+}
+
+STDMETHODIMP CShellExtClassFactory::CreateInstance(LPUNKNOWN pUnknownOuter, REFIID riid, LPVOID *ppv) {
+ *ppv = NULL;
+ if(pUnknownOuter) return CLASS_E_NOAGGREGATION;
+ CShellExt *pShellExt = new CShellExt();
+ if(pShellExt == NULL) return E_OUTOFMEMORY;
+ return pShellExt->QueryInterface(riid, ppv);
+}
+
+STDMETHODIMP CShellExtClassFactory::LockServer(BOOL fLock) {
+ return NOERROR;
+}
diff --git a/kaijuu/factory.hpp b/kaijuu/factory.hpp
new file mode 100644
index 00000000..48d305b1
--- /dev/null
+++ b/kaijuu/factory.hpp
@@ -0,0 +1,17 @@
+struct CShellExtClassFactory : IClassFactory {
+protected:
+ unsigned instanceCount;
+
+public:
+ CShellExtClassFactory();
+ ~CShellExtClassFactory();
+
+ STDMETHODIMP QueryInterface(REFIID, LPVOID FAR*);
+ STDMETHODIMP_(ULONG) AddRef();
+ STDMETHODIMP_(ULONG) Release();
+
+ STDMETHODIMP CreateInstance(LPUNKNOWN, REFIID, LPVOID FAR*);
+ STDMETHODIMP LockServer(BOOL);
+};
+
+typedef CShellExtClassFactory *LPCSHELLEXTCLASSFACTORY;
diff --git a/kaijuu/guid.hpp b/kaijuu/guid.hpp
new file mode 100644
index 00000000..815d6702
--- /dev/null
+++ b/kaijuu/guid.hpp
@@ -0,0 +1,11 @@
+#ifdef _WIN64
+ DEFINE_GUID(CLSID_ShellExtension, 0x5c8ee773, 0xb9dc, 0xcec7, 0x63, 0x31, 0x98, 0x6c, 0x16, 0x2b, 0x15, 0x0a);
+ const char classID[] = "{5c8ee773-b9dc-cec7-6331-986c162b150a}";
+ const char classDescription[] = "KaijuuOpenShEx64";
+ const char classDriver[] = "kaijuu64.dll";
+#else
+ DEFINE_GUID(CLSID_ShellExtension, 0xa2f1781c, 0x2e37, 0x9bcd, 0x66, 0x93, 0xc9, 0xe4, 0x52, 0x89, 0xc4, 0xc2);
+ const char classID[] = "{a2f1781c-2e37-9bcd-6693-c9e45289c4c2}";
+ const char classDescription[] = "KaijuuOpenShEx32";
+ const char classDriver[] = "kaijuu32.dll";
+#endif
diff --git a/kaijuu/interface.cpp b/kaijuu/interface.cpp
new file mode 100644
index 00000000..68b4b19f
--- /dev/null
+++ b/kaijuu/interface.cpp
@@ -0,0 +1,307 @@
+#include "interface.hpp"
+Application *application = nullptr;
+RuleEditor *ruleEditor = nullptr;
+
+#include "resource/resource.hpp"
+#include "resource/resource.cpp"
+
+Application::Application(const string &pathname) : pathname(pathname) {
+ setTitle("kaijuu v05");
+ setFrameGeometry({64, 64, 725, 480});
+
+ layout.setMargin(5);
+ statusLabel.setFont("Tahoma, 8, Bold");
+ uninstallButton.setText("Uninstall");
+ installButton.setText("Install");
+ settingList.setHeaderText("Name", "Default", "Match", "Pattern", "Command");
+ settingList.setHeaderVisible();
+ appendButton.setText("Append");
+ modifyButton.setText("Modify");
+ moveUpButton.setText("Move Up");
+ moveDownButton.setText("Move Down");
+ removeButton.setText("Remove");
+ resetButton.setText("Reset");
+ helpButton.setText("Help ...");
+
+ append(layout);
+ layout.append(installLayout, {~0, 0}, 5);
+ installLayout.append(statusLabel, {~0, 0}, 5);
+ installLayout.append(uninstallButton, {80, 0}, 5);
+ installLayout.append(installButton, {80, 0});
+ layout.append(settingLayout, {~0, ~0});
+ settingLayout.append(settingList, {~0, ~0}, 5);
+ settingLayout.append(controlLayout, {0, ~0});
+ controlLayout.append(appendButton, {80, 0}, 5);
+ controlLayout.append(modifyButton, {80, 0}, 5);
+ controlLayout.append(moveUpButton, {80, 0}, 5);
+ controlLayout.append(moveDownButton, {80, 0}, 5);
+ controlLayout.append(removeButton, {80, 0}, 5);
+ controlLayout.append(spacer, {0, ~0});
+ controlLayout.append(resetButton, {80, 0}, 5);
+ controlLayout.append(helpButton, {80, 0}, 5);
+ controlLayout.append(canvas, {80, 88});
+
+ canvas.setImage({resource::icon, sizeof resource::icon});
+ canvas.update();
+
+ onClose = &OS::quit;
+ installButton.onActivate = {&Application::install, this};
+ uninstallButton.onActivate = {&Application::uninstall, this};
+ settingList.onActivate = {&Application::modifyAction, this};
+ settingList.onChange = {&Application::synchronize, this};
+ appendButton.onActivate = {&Application::appendAction, this};
+ modifyButton.onActivate = {&Application::modifyAction, this};
+ moveUpButton.onActivate = {&Application::moveUpAction, this};
+ moveDownButton.onActivate = {&Application::moveDownAction, this};
+ removeButton.onActivate = {&Application::removeAction, this};
+ resetButton.onActivate = {&Application::resetAction, this};
+ helpButton.onActivate = [&] { nall::invoke("kaijuu.html"); };
+ refresh();
+ synchronize();
+ setVisible();
+}
+
+void Application::synchronize() {
+ if(registry::read({"HKLM/Software/Microsoft/Windows/CurrentVersion/Shell Extensions/Approved/", classID}) == classDescription) {
+ statusLabel.setText("Extension status: installed");
+ installButton.setEnabled(false);
+ uninstallButton.setEnabled(true);
+ } else {
+ statusLabel.setText("Extension status: not installed");
+ installButton.setEnabled(true);
+ uninstallButton.setEnabled(false);
+ }
+ modifyButton.setEnabled(settingList.selected());
+ moveUpButton.setEnabled(settingList.selected() && settings.rules.size() > 1 && settingList.selection() != 0);
+ moveDownButton.setEnabled(settingList.selected() && settings.rules.size() > 1 && settingList.selection() < settings.rules.size() - 1);
+ removeButton.setEnabled(settingList.selected());
+ resetButton.setEnabled(settings.rules.size() > 0);
+}
+
+void Application::refresh() {
+ settings.load();
+ settingList.reset();
+ for(auto &rule : settings.rules) {
+ string match = "Nothing";
+ if(rule.matchFiles && rule.matchFolders) match = "Everything";
+ else if(rule.matchFiles) match = "Files";
+ else if(rule.matchFolders) match = "Folders";
+ settingList.append(rule.name, rule.defaultAction ? "Yes" : "No", match, rule.pattern, rule.command);
+ }
+ settingList.autoSizeColumns();
+}
+
+void Application::install() {
+ string command = {"regsvr32 \"", pathname, classDriver, "\""};
+ _wsystem(utf16_t(command));
+ synchronize();
+}
+
+void Application::uninstall() {
+ string command = {"regsvr32 /u \"", pathname, classDriver, "\""};
+ _wsystem(utf16_t(command));
+ synchronize();
+}
+
+void Application::appendAction() {
+ ruleEditor->show();
+}
+
+void Application::modifyAction() {
+ if(settingList.selected() == false) return;
+ unsigned selection = settingList.selection();
+ ruleEditor->show(selection);
+}
+
+void Application::moveUpAction() {
+ if(settingList.selected() == false) return;
+ if(settingList.selection() == 0) return;
+ unsigned selection = settingList.selection();
+ auto temp = settings.rules(selection - 1);
+ settings.rules(selection - 1) = settings.rules(selection);
+ settings.rules(selection) = temp;
+ settings.save();
+ refresh();
+ settingList.setSelection(selection - 1);
+ synchronize();
+}
+
+void Application::moveDownAction() {
+ if(settingList.selected() == false) return;
+ if(settingList.selection() >= settings.rules.size() - 1) return;
+ unsigned selection = settingList.selection();
+ auto temp = settings.rules(selection + 1);
+ settings.rules(selection + 1) = settings.rules(selection);
+ settings.rules(selection) = temp;
+ settings.save();
+ refresh();
+ settingList.setSelection(selection + 1);
+ synchronize();
+}
+
+void Application::removeAction() {
+ if(settingList.selected() == false) return;
+ unsigned selection = settingList.selection();
+ settings.rules.remove(selection);
+ settings.save();
+ refresh();
+ synchronize();
+}
+
+void Application::resetAction() {
+ if(MessageWindow::question(*this, "Warning: this will permanently remove all rules! Are you sure you want to do this?")
+ == MessageWindow::Response::No) return;
+ settings.rules.reset();
+ settings.save();
+ refresh();
+ synchronize();
+}
+
+RuleEditor::RuleEditor() : index(-1) {
+ setTitle("Rule Editor");
+ setFrameGeometry({128, 256, 500, 160});
+
+ layout.setMargin(5);
+ nameLabel.setText("Name:");
+ patternLabel.setText("Pattern:");
+ commandLabel.setText("Command:");
+ commandSelect.setText("Select ...");
+ defaultAction.setText("Default Action");
+ filesAction.setText("Match Files");
+ foldersAction.setText("Match Folders");
+ assignButton.setText("Assign");
+
+ Font font("Tahoma, 8");
+ unsigned length = 0;
+ length = max(length, font.geometry("Name:").width);
+ length = max(length, font.geometry("Pattern:").width);
+ length = max(length, font.geometry("Command:").width);
+
+ append(layout);
+ layout.append(nameLayout, {~0, 0}, 5);
+ nameLayout.append(nameLabel, {length, 0}, 5);
+ nameLayout.append(nameValue, {~0, 0});
+ layout.append(patternLayout, {~0, 0}, 5);
+ patternLayout.append(patternLabel, {length, 0}, 5);
+ patternLayout.append(patternValue, {~0, 0});
+ layout.append(commandLayout, {~0, 0}, 5);
+ commandLayout.append(commandLabel, {length, 0}, 5);
+ commandLayout.append(commandValue, {~0, 0}, 5);
+ commandLayout.append(commandSelect, {80, 0});
+ layout.append(controlLayout, {~0, 0});
+ controlLayout.append(defaultAction, {0, 0}, 5);
+ controlLayout.append(filesAction, {0, 0}, 5);
+ controlLayout.append(foldersAction, {0, 0}, 5);
+ controlLayout.append(spacer, {~0, 0});
+ controlLayout.append(assignButton, {80, 0});
+
+ Geometry geometry = Window::geometry();
+ geometry.height = layout.minimumGeometry().height;
+ setGeometry(geometry);
+
+ onClose = [&] {
+ modal = false;
+ };
+
+ nameValue.onChange =
+ patternValue.onChange =
+ commandValue.onChange =
+ {&RuleEditor::synchronize, this};
+
+ commandSelect.onActivate = [&] {
+ string pathname = DialogWindow::fileOpen(*this, application->pathname, "Programs (*.exe)", "All Files (*)");
+ if(pathname.empty() == false) {
+ pathname.transform("/", "\\");
+ commandValue.setText({"\"", pathname, "\" {file}"});
+ }
+ synchronize();
+ };
+
+ nameValue.onActivate =
+ patternValue.onActivate =
+ commandValue.onActivate =
+ assignButton.onActivate = [&] {
+ Settings::Rule rule = {
+ nameValue.text(),
+ patternValue.text(),
+ defaultAction.checked(),
+ filesAction.checked(),
+ foldersAction.checked(),
+ commandValue.text()
+ };
+ if(index == -1) {
+ settings.rules.append(rule);
+ } else {
+ settings.rules(index) = rule;
+ }
+ settings.save();
+ application->refresh();
+ application->synchronize();
+ setVisible(false);
+ modal = false;
+ };
+}
+
+void RuleEditor::synchronize() {
+ bool enable = true;
+ if(nameValue.text().empty()) enable = false;
+ if(patternValue.text().empty()) enable = false;
+ if(commandValue.text().empty()) enable = false;
+ assignButton.setEnabled(enable);
+}
+
+void RuleEditor::show(signed ruleID) {
+ Settings::Rule rule{"", "", false, true, false, "", false};
+ if(ruleID >= 0) rule = settings.rules(ruleID);
+
+ index = ruleID;
+ nameValue.setText(rule.name);
+ patternValue.setText(rule.pattern);
+ commandValue.setText(rule.command);
+ defaultAction.setChecked(rule.defaultAction);
+ filesAction.setChecked(rule.matchFiles);
+ foldersAction.setChecked(rule.matchFolders);
+ synchronize();
+ setVisible();
+ setFocused();
+ nameValue.setFocused();
+
+ setModal(modal = true);
+ while(modal == true) {
+ OS::processEvents();
+ }
+ setModal(false);
+ application->setFocused();
+}
+
+typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS)(HANDLE, PBOOL);
+
+bool isWow64() {
+ LPFN_ISWOW64PROCESS fnIsWow64Process;
+ fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandleW(L"kernel32"), "IsWow64Process");
+ if(!fnIsWow64Process) return false;
+ BOOL result = FALSE;
+ fnIsWow64Process(GetCurrentProcess(), &result);
+ return result == TRUE;
+}
+
+int CALLBACK WinMain(HINSTANCE module, HINSTANCE, LPSTR, int) {
+ if(isWow64()) {
+ MessageWindow::critical(Window::none(), "Error: you must run kaijuu64.exe on 64-bit Windows.");
+ return 0;
+ }
+
+ wchar_t filename[MAX_PATH];
+ GetModuleFileNameW(module, filename, MAX_PATH);
+
+ string pathname = (const char*)utf8_t(filename);
+ pathname.transform("\\", "/");
+ pathname = dir(pathname);
+
+ application = new Application(pathname);
+ ruleEditor = new RuleEditor;
+ application->setFocused();
+ OS::main();
+
+ return 0;
+}
diff --git a/kaijuu/interface.hpp b/kaijuu/interface.hpp
new file mode 100644
index 00000000..656cb7e3
--- /dev/null
+++ b/kaijuu/interface.hpp
@@ -0,0 +1,72 @@
+#include
+#include
+#include
+#include
+using namespace nall;
+
+#include
+using namespace phoenix;
+
+#include "guid.hpp"
+#include "settings.hpp"
+
+struct Application : Window {
+ VerticalLayout layout;
+ HorizontalLayout installLayout;
+ Label statusLabel;
+ Button uninstallButton;
+ Button installButton;
+ HorizontalLayout settingLayout;
+ ListView settingList;
+ VerticalLayout controlLayout;
+ Button appendButton;
+ Button modifyButton;
+ Button moveUpButton;
+ Button moveDownButton;
+ Button removeButton;
+ Button resetButton;
+ Widget spacer;
+ Button helpButton;
+ Canvas canvas;
+
+ Application(const string &pathname);
+ void synchronize();
+ void refresh();
+ void install();
+ void uninstall();
+ void appendAction();
+ void modifyAction();
+ void moveUpAction();
+ void moveDownAction();
+ void removeAction();
+ void resetAction();
+
+ string pathname;
+};
+
+struct RuleEditor : Window {
+ VerticalLayout layout;
+ HorizontalLayout nameLayout;
+ Label nameLabel;
+ LineEdit nameValue;
+ HorizontalLayout patternLayout;
+ Label patternLabel;
+ LineEdit patternValue;
+ HorizontalLayout commandLayout;
+ Label commandLabel;
+ LineEdit commandValue;
+ Button commandSelect;
+ HorizontalLayout controlLayout;
+ CheckBox defaultAction;
+ CheckBox filesAction;
+ CheckBox foldersAction;
+ Widget spacer;
+ Button assignButton;
+
+ bool modal;
+ signed index;
+
+ RuleEditor();
+ void synchronize();
+ void show(signed rule = -1);
+};
diff --git a/kaijuu/kaijuu.Manifest b/kaijuu/kaijuu.Manifest
new file mode 100644
index 00000000..28987b10
--- /dev/null
+++ b/kaijuu/kaijuu.Manifest
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+
+
+
+
diff --git a/kaijuu/kaijuu.cpp b/kaijuu/kaijuu.cpp
new file mode 100644
index 00000000..d9eaa535
--- /dev/null
+++ b/kaijuu/kaijuu.cpp
@@ -0,0 +1,50 @@
+#include "kaijuu.hpp"
+#include "extension.cpp"
+#include "factory.cpp"
+
+extern "C" BOOL WINAPI DllMain(HINSTANCE hinstance, DWORD dwReason, LPVOID lpReserved) {
+ if(dwReason == DLL_PROCESS_ATTACH) {
+ module = hinstance;
+ }
+
+ if(dwReason == DLL_PROCESS_DETACH) {
+ }
+
+ return TRUE;
+}
+
+STDAPI DllCanUnloadNow() {
+ return referenceCount == 0 ? S_OK : S_FALSE;
+}
+
+STDAPI DllRegisterServer() {
+ wchar_t fileName[MAX_PATH];
+ GetModuleFileNameW(module, fileName, MAX_PATH);
+ registry::write({"HKCR/CLSID/", classID, "/"}, classDescription);
+ registry::write({"HKCR/CLSID/", classID, "/shellex/MayChangeDefaultMenu/"});
+ registry::write({"HKCR/CLSID/", classID, "/InprocServer32/"}, (const char*)utf8_t(fileName));
+ registry::write({"HKCR/CLSID/", classID, "/InprocServer32/ThreadingModel"}, "Apartment");
+ registry::write({"HKCR/*/shellex/ContextMenuHandlers/", classDescription, "/"}, classID);
+ registry::write({"HKCR/Directory/shellex/ContextMenuHandlers/", classDescription, "/"}, classID);
+ registry::write({"HKLM/Software/Microsoft/Windows/CurrentVersion/Shell Extensions/Approved/", classID}, classDescription);
+ SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
+ return S_OK;
+}
+
+STDAPI DllUnregisterServer() {
+ registry::remove({"HKCR/CLSID/", classID, "/"});
+ registry::remove({"HKCR/*/shellex/ContextMenuHandlers/", classDescription, "/"});
+ registry::remove({"HKCR/Directory/shellex/ContextMenuHandlers/", classDescription, "/"});
+ registry::remove({"HKLM/Software/Microsoft/Windows/CurrentVersion/Shell Extensions/Approved/", classID});
+ SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
+ return S_OK;
+}
+
+STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) {
+ *ppv = NULL;
+ if(IsEqualIID(rclsid, CLSID_ShellExtension)) {
+ CShellExtClassFactory *pcf = new CShellExtClassFactory;
+ return pcf->QueryInterface(riid, ppv);
+ }
+ return CLASS_E_CLASSNOTAVAILABLE;
+}
diff --git a/kaijuu/kaijuu.def b/kaijuu/kaijuu.def
new file mode 100644
index 00000000..ce78749c
--- /dev/null
+++ b/kaijuu/kaijuu.def
@@ -0,0 +1,5 @@
+EXPORTS
+ DllRegisterServer private
+ DllUnregisterServer private
+ DllCanUnloadNow private
+ DllGetClassObject private
diff --git a/kaijuu/kaijuu.hpp b/kaijuu/kaijuu.hpp
new file mode 100644
index 00000000..93e4f3ab
--- /dev/null
+++ b/kaijuu/kaijuu.hpp
@@ -0,0 +1,25 @@
+#include
+#include
+#include
+#include
+#include
+#include
+using namespace nall;
+
+#define INITGUID
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#define IDM_CFOPEN 0
+
+HINSTANCE module = NULL;
+unsigned referenceCount = 0;
+
+#include "guid.hpp"
+#include "settings.hpp"
+#include "extension.hpp"
+#include "factory.hpp"
diff --git a/kaijuu/kaijuu.html b/kaijuu/kaijuu.html
new file mode 100644
index 00000000..65bcdb59
--- /dev/null
+++ b/kaijuu/kaijuu.html
@@ -0,0 +1,200 @@
+
+
+ kaijuu User Manual
+
+
+
+ kaijuu v05
+ Author: byuu
+ License: ISC
+
+
+ Overview
+ kaijuu is a Windows context menu shell extension. The context
+ menu is the list you see when you right-click on a file or folder.
+ kaijuu allows you to add your own custom actions to this menu.
+
+ Think of opening an unknown file type: Windows will ask you to
+ associate a program with the file type. From there forward,
+ double-clicking the file will open the file with that program.
+
+ kaijuu is a far more powerful version of this same concept. With
+ kaijuu, you can assign as many rules as you want. You can apply the
+ same rule to multiple file patterns. You can have more complex
+ pattern matching for names. You can apply rules to folders. You can
+ specify rules about how to handle single-file versus multi-file
+ selection. You can send custom command-line parameters to the
+ program. You can have rules on a per-user basis. And you can do all
+ of this from an easy-to-use GUI.
+
+ Installation
+ kaijuu comes in 32-bit and 64-bit flavors, you will need to use
+ the one for your operating system. If you are unsure, try running
+ kaijuu32.exe. It will tell you if you need to use the 64-bit
+ version.
+
+ Now place the appropriate kaijuu EXE and DLL files into a folder
+ where you intend to keep them. The DLL cannot be moved after
+ installation, otherwise Explorer will not be able to locate the
+ shell extension. C:\Program Files\kaijuu would be a recommended
+ location.
+
+ Now run the kaijuu EXE, and click on Install. You must
+ have administrator access to use the kaijuu EXE, as this is
+ necessary to install and uninstall shell extensions.
+
+ Removal and Upgrading
+ To remove or upgrade kaijuu, you must first uninstall the shell
+ extension. Run the kaijuu EXE, and click on Uninstall. You
+ must now close all open instances of Windows Explorer, in order for
+ the DLL to be completely unloaded. In the worst case, restart the
+ computer.
+
+ If you intend to upgrade kaijuu, I recommend using the
+ Reset button to erase all saved settings. There is no
+ guarantee of backward-compatibility between kaijuu revisions.
+
+ Configuration
+ The kaijuu EXE not only handles installation and removal, it also
+ handles modifying the rules.
+
+ kaijuu stores a unique list of rules for every user account.
+ You are free to modify rules even while kaijuu is installed. They
+ will take immediate effect.
+
+ The main interface lists all rules, sorted in order of their
+ priority. For instance, if two rules match and both are marked as
+ the default action; the item higher in the list will be marked as
+ the default. You can also quickly determine if the extension is
+ currently installed.
+
+ Append will add new rules, Modify will edit an
+ existing rule, Move Up and Move Down can be used to
+ modify the priority ordering, Remove can delete the selected
+ rule, and Reset can delete all rules.
+
+ Rules
+ You can have as many rules as you like. You will see every
+ matched rule in the context menu when you right-click on files or
+ folders.
+
+ Name is the string that will show up in the context menu.
+ It would be wise to name the rule something like "Open with X" or
+ "Edit with Y"
+
+ Pattern is a semicolon-separated list of patterns to test
+ the selected file or folder names against. You must specify one or
+ more patterns.
+
+ Example 1: *.txt;*.doc will match anything ending
+ in .txt or in .doc.
+
+ Example 2: * will match everything always.
+
+ Example 3: Manifest will only match items named
+ Manifest.
+
+ Example 4: *.?? will match any two-letter
+ extension, such as .gb
+
+ Command is the program to be executed when a rule is
+ activated. You can use the Select button to quickly navigate
+ to a program to use.
+
+ Note the way the program name is typically quoted, for instance
+ "c:\my program.exe". If there is a space in the path, this is
+ required to differentiate the program name from its arguments. If
+ you were to type your own rule, you could take advantage of two
+ things: first, the PATH command-line variable allows
+ specifying system programs without the full path. For instance,
+ "cmd" will invoke the command-prompt; and second, if the
+ program path contains no spaces, the quotes are no longer necessary.
+ So you could say cmd to invoke the command-prompt.
+
+ After the program name, you can specify the program arguments.
+ kaijuu has many special identifiers built-in, that are replaced with
+ the file and/or folder names that were selected. When using the
+ Select button, {file} is automatically appended for
+ convenience, which should be sufficient for most cases. You can of
+ course customize the rule afterward with the following identifiers:
+
+
+
+{name} = c:\path\file.txt
+{pathname} = c:\path
+{filename} = file.txt
+{basename} = file
+{extension} = txt
+
+{path} = "c:\path"
+{file} = "c:\path\file.txt"
+
+{paths} = "c:\path1" "c:\path2"
+{files} = "c:\path1\file1.txt" "c:\path2\file2.txt"
+
+
+ Note that if you use the first group, you must add your own
+ quotes around the identifiers, eg notepad "{name}".
+
+ If the command includes {files} or {paths} within
+ the string, then kaijuu will match this rule when one or more files
+ are selected. If neither of these patterns are found, then kaijuu
+ will only check the rule if a single file is selected.
+
+ You will want to use {file} and {path} for programs
+ that can only open a single item a a time; and {files} and
+ {paths} for programs that can open multiple items at the same
+ time, such as music players.
+
+ Default Action, when checked, will mark this rule as the
+ default action to take when a file or folder is double-clicked on.
+
+
+ Match Files will allow selections with files in them to
+ be valid. If a file is selected without this checked, the rule will
+ fail.
+
+ Match Folders will allow selections with folders in them
+ to be valid. If a file is selected without this checked, the rule
+ will fail.
+
+ Assign will create the new rule or modify an existing
+ rule, depending upon which button you clicked from the main window.
+
+
+ Caution: be very careful when using a pattern of *
+ along with Default Action checked. For instance, you could
+ find that double-clicking executables no longer opens then, and
+ requires you to use the right-click context menu. In the worst case,
+ you will have to reboot into safe mode and delete the rule or kaijuu
+ DLL.
+
+ Rule Examples
+
+ Name | Default | Match | Pattern | Command |
+ Open terminal here | No | Folders | * | cmd /k cd /d {path} |
+ Edit Makefile | Yes | Files | Makefile | notepad {file} |
+ Play song(s) | No | Files | *.mp3 | "c:\winamp.exe" {files} |
+ Load as Game Folder | Yes | Folders | *.fc;*.sfc;*.gba | "c:\bsnes.exe" {path} |
+
+
+
diff --git a/kaijuu/kaijuu.rc b/kaijuu/kaijuu.rc
new file mode 100644
index 00000000..6de3fb51
--- /dev/null
+++ b/kaijuu/kaijuu.rc
@@ -0,0 +1 @@
+1 24 "kaijuu.manifest"
diff --git a/snesfilter/nall/Makefile b/kaijuu/nall/Makefile
old mode 100755
new mode 100644
similarity index 90%
rename from snesfilter/nall/Makefile
rename to kaijuu/nall/Makefile
index a542beeb..bbc4b029
--- a/snesfilter/nall/Makefile
+++ b/kaijuu/nall/Makefile
@@ -19,6 +19,9 @@ ifeq ($(platform),)
ifeq ($(uname),)
platform := win
delete = del $(subst /,\,$1)
+ else ifneq ($(findstring Windows,$(uname)),)
+ platform := win
+ delete = del $(subst /,\,$1)
else ifneq ($(findstring CYGWIN,$(uname)),)
platform := win
delete = del $(subst /,\,$1)
@@ -35,12 +38,15 @@ ifeq ($(compiler),)
ifeq ($(platform),win)
compiler := gcc
else ifeq ($(platform),osx)
- compiler := gcc-mp-4.6
+ compiler := gcc-mp-4.7
else
- compiler := gcc-4.6
+ compiler := gcc-4.7
endif
endif
+c := $(compiler) -std=gnu99
+cpp := $(subst cc,++,$(compiler)) -std=gnu++0x
+
ifeq ($(prefix),)
prefix := /usr/local
endif
diff --git a/snesfilter/nall/algorithm.hpp b/kaijuu/nall/algorithm.hpp
old mode 100755
new mode 100644
similarity index 100%
rename from snesfilter/nall/algorithm.hpp
rename to kaijuu/nall/algorithm.hpp
diff --git a/snesfilter/nall/any.hpp b/kaijuu/nall/any.hpp
old mode 100755
new mode 100644
similarity index 84%
rename from snesfilter/nall/any.hpp
rename to kaijuu/nall/any.hpp
index b31cff3c..7661a2a4
--- a/snesfilter/nall/any.hpp
+++ b/kaijuu/nall/any.hpp
@@ -2,17 +2,15 @@
#define NALL_ANY_HPP
#include
-#include
-#include
+#include
namespace nall {
- class any {
- public:
+ struct any {
bool empty() const { return container; }
const std::type_info& type() const { return container ? container->type() : typeid(void); }
template any& operator=(const T& value_) {
- typedef typename static_if<
+ typedef typename type_if<
std::is_array::value,
typename std::remove_extent::type>::type*,
T
@@ -28,8 +26,9 @@ namespace nall {
return *this;
}
- any() : container(0) {}
- template any(const T& value_) : container(0) { operator=(value_); }
+ any() : container(nullptr) {}
+ ~any() { if(container) delete container; }
+ template any(const T& value_) : container(nullptr) { operator=(value_); }
private:
struct placeholder {
@@ -61,12 +60,12 @@ namespace nall {
}
template T* any_cast(any *value) {
- if(!value || value->type() != typeid(T)) return 0;
+ if(!value || value->type() != typeid(T)) return nullptr;
return &static_cast*>(value->container)->value;
}
template const T* any_cast(const any *value) {
- if(!value || value->type() != typeid(T)) return 0;
+ if(!value || value->type() != typeid(T)) return nullptr;
return &static_cast*>(value->container)->value;
}
}
diff --git a/snesfilter/nall/atoi.hpp b/kaijuu/nall/atoi.hpp
old mode 100755
new mode 100644
similarity index 82%
rename from snesfilter/nall/atoi.hpp
rename to kaijuu/nall/atoi.hpp
index cec3e72d..26756c79
--- a/snesfilter/nall/atoi.hpp
+++ b/kaijuu/nall/atoi.hpp
@@ -1,6 +1,8 @@
#ifndef NALL_ATOI_HPP
#define NALL_ATOI_HPP
+#include
+
namespace nall {
//note: this header is intended to form the base for user-defined literals;
@@ -79,6 +81,19 @@ constexpr inline uintmax_t hex(const char *s) {
);
}
+constexpr inline intmax_t numeral(const char *s) {
+ return (
+ *s == '0' && *(s + 1) == 'X' ? hex_(s + 2) :
+ *s == '0' && *(s + 1) == 'x' ? hex_(s + 2) :
+ *s == '0' && *(s + 1) == 'B' ? binary_(s + 2) :
+ *s == '0' && *(s + 1) == 'b' ? binary_(s + 2) :
+ *s == '0' ? octal_(s + 1) :
+ *s == '+' ? +decimal_(s + 1) :
+ *s == '-' ? -decimal_(s + 1) :
+ decimal_(s)
+ );
+}
+
inline double fp(const char *s) {
return atof(s);
}
diff --git a/snesfilter/nall/base64.hpp b/kaijuu/nall/base64.hpp
old mode 100755
new mode 100644
similarity index 100%
rename from snesfilter/nall/base64.hpp
rename to kaijuu/nall/base64.hpp
diff --git a/kaijuu/nall/bit.hpp b/kaijuu/nall/bit.hpp
new file mode 100644
index 00000000..63403eb0
--- /dev/null
+++ b/kaijuu/nall/bit.hpp
@@ -0,0 +1,82 @@
+#ifndef NALL_BIT_HPP
+#define NALL_BIT_HPP
+
+#include
+
+namespace nall {
+ template
+ inline uintmax_t uclamp(const uintmax_t x) {
+ enum : uintmax_t { b = 1ull << (bits - 1), y = b * 2 - 1 };
+ return y + ((x - y) & -(x < y)); //min(x, y);
+ }
+
+ template
+ inline uintmax_t uclip(const uintmax_t x) {
+ enum : uintmax_t { b = 1ull << (bits - 1), m = b * 2 - 1 };
+ return (x & m);
+ }
+
+ template
+ inline intmax_t sclamp(const intmax_t x) {
+ enum : intmax_t { b = 1ull << (bits - 1), m = b - 1 };
+ return (x > m) ? m : (x < -b) ? -b : x;
+ }
+
+ template
+ inline intmax_t sclip(const intmax_t x) {
+ enum : uintmax_t { b = 1ull << (bits - 1), m = b * 2 - 1 };
+ return ((x & m) ^ b) - b;
+ }
+
+ namespace bit {
+ constexpr inline uintmax_t mask(const char *s, uintmax_t sum = 0) {
+ return (
+ *s == '0' || *s == '1' ? mask(s + 1, (sum << 1) | 1) :
+ *s == ' ' || *s == '_' ? mask(s + 1, sum) :
+ *s ? mask(s + 1, sum << 1) :
+ sum
+ );
+ }
+
+ constexpr inline uintmax_t test(const char *s, uintmax_t sum = 0) {
+ return (
+ *s == '0' || *s == '1' ? test(s + 1, (sum << 1) | (*s - '0')) :
+ *s == ' ' || *s == '_' ? test(s + 1, sum) :
+ *s ? test(s + 1, sum << 1) :
+ sum
+ );
+ }
+
+ //lowest(0b1110) == 0b0010
+ constexpr inline uintmax_t lowest(const uintmax_t x) {
+ return x & -x;
+ }
+
+ //clear_lowest(0b1110) == 0b1100
+ constexpr inline uintmax_t clear_lowest(const uintmax_t x) {
+ return x & (x - 1);
+ }
+
+ //set_lowest(0b0101) == 0b0111
+ constexpr inline uintmax_t set_lowest(const uintmax_t x) {
+ return x | (x + 1);
+ }
+
+ //count number of bits set in a byte
+ inline unsigned count(uintmax_t x) {
+ unsigned count = 0;
+ do count += x & 1; while(x >>= 1);
+ return count;
+ }
+
+ //round up to next highest single bit:
+ //round(15) == 16, round(16) == 16, round(17) == 32
+ inline uintmax_t round(uintmax_t x) {
+ if((x & (x - 1)) == 0) return x;
+ while(x & (x - 1)) x &= x - 1;
+ return x << 1;
+ }
+ }
+}
+
+#endif
diff --git a/snesfilter/nall/bmp.hpp b/kaijuu/nall/bmp.hpp
old mode 100755
new mode 100644
similarity index 100%
rename from snesfilter/nall/bmp.hpp
rename to kaijuu/nall/bmp.hpp
diff --git a/snesfilter/nall/bps/delta.hpp b/kaijuu/nall/bps/delta.hpp
old mode 100755
new mode 100644
similarity index 100%
rename from snesfilter/nall/bps/delta.hpp
rename to kaijuu/nall/bps/delta.hpp
diff --git a/snesfilter/nall/bps/linear.hpp b/kaijuu/nall/bps/linear.hpp
old mode 100755
new mode 100644
similarity index 100%
rename from snesfilter/nall/bps/linear.hpp
rename to kaijuu/nall/bps/linear.hpp
diff --git a/snesfilter/nall/bps/metadata.hpp b/kaijuu/nall/bps/metadata.hpp
old mode 100755
new mode 100644
similarity index 100%
rename from snesfilter/nall/bps/metadata.hpp
rename to kaijuu/nall/bps/metadata.hpp
diff --git a/snesfilter/nall/bps/patch.hpp b/kaijuu/nall/bps/patch.hpp
old mode 100755
new mode 100644
similarity index 100%
rename from snesfilter/nall/bps/patch.hpp
rename to kaijuu/nall/bps/patch.hpp
diff --git a/snesfilter/nall/compositor.hpp b/kaijuu/nall/compositor.hpp
old mode 100755
new mode 100644
similarity index 100%
rename from snesfilter/nall/compositor.hpp
rename to kaijuu/nall/compositor.hpp
diff --git a/snesfilter/nall/config.hpp b/kaijuu/nall/config.hpp
old mode 100755
new mode 100644
similarity index 76%
rename from snesfilter/nall/config.hpp
rename to kaijuu/nall/config.hpp
index 0c6602df..94be7dc1
--- a/snesfilter/nall/config.hpp
+++ b/kaijuu/nall/config.hpp
@@ -32,7 +32,7 @@ namespace nall {
string desc;
type_t type;
- string get() const {
+ inline string get() const {
switch(type) {
case boolean_t: return { *(bool*)data };
case signed_t: return { *(signed*)data };
@@ -43,7 +43,7 @@ namespace nall {
return "???";
}
- void set(string s) {
+ inline void set(string s) {
switch(type) {
case boolean_t: *(bool*)data = (s == "true"); break;
case signed_t: *(signed*)data = integer(s); break;
@@ -53,24 +53,27 @@ namespace nall {
}
}
};
- linear_vector list;
+ vector list;
template
- void attach(T &data, const char *name, const char *desc = "") {
- unsigned n = list.size();
- list[n].data = (uintptr_t)&data;
- list[n].name = name;
- list[n].desc = desc;
-
- if(configuration_traits::is_boolean::value) list[n].type = boolean_t;
- else if(configuration_traits::is_signed::value) list[n].type = signed_t;
- else if(configuration_traits::is_unsigned::value) list[n].type = unsigned_t;
- else if(configuration_traits::is_double::value) list[n].type = double_t;
- else if(configuration_traits::is_string::value) list[n].type = string_t;
- else list[n].type = unknown_t;
+ inline void append(T &data, const char *name, const char *desc = "") {
+ item_t item = { (uintptr_t)&data, name, desc };
+ if(configuration_traits::is_boolean::value) item.type = boolean_t;
+ else if(configuration_traits::is_signed::value) item.type = signed_t;
+ else if(configuration_traits::is_unsigned::value) item.type = unsigned_t;
+ else if(configuration_traits::is_double::value) item.type = double_t;
+ else if(configuration_traits::is_string::value) item.type = string_t;
+ else item.type = unknown_t;
+ list.append(item);
}
- virtual bool load(const string &filename) {
+ //deprecated
+ template
+ inline void attach(T &data, const char *name, const char *desc = "") {
+ append(data, name, desc);
+ }
+
+ inline virtual bool load(const string &filename) {
string data;
if(data.readfile(filename) == true) {
data.replace("\r", "");
@@ -100,7 +103,7 @@ namespace nall {
}
}
- virtual bool save(const string &filename) const {
+ inline virtual bool save(const string &filename) const {
file fp;
if(fp.open(filename, file::mode::write)) {
for(unsigned i = 0; i < list.size(); i++) {
diff --git a/snesfilter/nall/crc32.hpp b/kaijuu/nall/crc32.hpp
old mode 100755
new mode 100644
similarity index 100%
rename from snesfilter/nall/crc32.hpp
rename to kaijuu/nall/crc32.hpp
diff --git a/snesfilter/nall/directory.hpp b/kaijuu/nall/directory.hpp
old mode 100755
new mode 100644
similarity index 77%
rename from snesfilter/nall/directory.hpp
rename to kaijuu/nall/directory.hpp
index 31ca1e05..4dba2b70
--- a/snesfilter/nall/directory.hpp
+++ b/kaijuu/nall/directory.hpp
@@ -17,6 +17,8 @@
namespace nall {
struct directory {
+ static bool create(const string &pathname, unsigned permissions = 0755); //recursive
+ static bool remove(const string &pathname);
static bool exists(const string &pathname);
static lstring folders(const string &pathname, const string &pattern = "*");
static lstring files(const string &pathname, const string &pattern = "*");
@@ -24,8 +26,27 @@ struct directory {
};
#if defined(PLATFORM_WINDOWS)
+ inline bool directory::create(const string &pathname, unsigned permissions) {
+ string fullpath = pathname, path;
+ fullpath.transform("/", "\\");
+ fullpath.rtrim<1>("\\");
+ lstring pathpart = fullpath.split("\\");
+ bool result = false;
+ for(auto &part : pathpart) {
+ path.append(part, "\\");
+ result = _wmkdir(utf16_t(path)) == 0;
+ }
+ return result;
+ }
+
+ inline bool directory::remove(const string &pathname) {
+ return _wrmdir(utf16_t(pathname)) == 0;
+ }
+
inline bool directory::exists(const string &pathname) {
- DWORD result = GetFileAttributes(utf16_t(pathname));
+ string name = pathname;
+ name.trim<1>("\"");
+ DWORD result = GetFileAttributes(utf16_t(name));
if(result == INVALID_FILE_ATTRIBUTES) return false;
return (result & FILE_ATTRIBUTE_DIRECTORY);
}
@@ -56,7 +77,7 @@ struct directory {
}
FindClose(handle);
}
- if(list.size() > 0) sort(&list[0], list.size());
+ if(list.size() > 0) list.sort();
for(auto &name : list) name.append("/"); //must append after sorting
return list;
}
@@ -83,7 +104,7 @@ struct directory {
}
FindClose(handle);
}
- if(list.size() > 0) sort(&list[0], list.size());
+ if(list.size() > 0) list.sort();
return list;
}
@@ -94,6 +115,21 @@ struct directory {
return folders;
}
#else
+ inline bool directory::create(const string &pathname, unsigned permissions) {
+ string fullpath = pathname, path = "/";
+ fullpath.trim<1>("/");
+ lstring pathpart = fullpath.split("/");
+ for(auto &part : pathpart) {
+ if(!directory::exists(path)) mkdir(path, permissions);
+ path.append(part, "/");
+ }
+ return mkdir(path, permissions) == 0;
+ }
+
+ inline bool directory::remove(const string &pathname) {
+ return rmdir(pathname) == 0;
+ }
+
inline bool directory::exists(const string &pathname) {
DIR *dp = opendir(pathname);
if(!dp) return false;
@@ -116,7 +152,7 @@ struct directory {
}
closedir(dp);
}
- if(list.size() > 0) sort(&list[0], list.size());
+ if(list.size() > 0) list.sort();
for(auto &name : list) name.append("/"); //must append after sorting
return list;
}
@@ -136,7 +172,7 @@ struct directory {
}
closedir(dp);
}
- if(list.size() > 0) sort(&list[0], list.size());
+ if(list.size() > 0) list.sort();
return list;
}
diff --git a/snesfilter/nall/dl.hpp b/kaijuu/nall/dl.hpp
old mode 100755
new mode 100644
similarity index 100%
rename from snesfilter/nall/dl.hpp
rename to kaijuu/nall/dl.hpp
diff --git a/snesfilter/nall/dsp.hpp b/kaijuu/nall/dsp.hpp
old mode 100755
new mode 100644
similarity index 100%
rename from snesfilter/nall/dsp.hpp
rename to kaijuu/nall/dsp.hpp
diff --git a/snesfilter/nall/dsp/buffer.hpp b/kaijuu/nall/dsp/buffer.hpp
old mode 100755
new mode 100644
similarity index 100%
rename from snesfilter/nall/dsp/buffer.hpp
rename to kaijuu/nall/dsp/buffer.hpp
diff --git a/snesfilter/nall/dsp/core.hpp b/kaijuu/nall/dsp/core.hpp
old mode 100755
new mode 100644
similarity index 100%
rename from snesfilter/nall/dsp/core.hpp
rename to kaijuu/nall/dsp/core.hpp
diff --git a/snesfilter/nall/dsp/resample/average.hpp b/kaijuu/nall/dsp/resample/average.hpp
old mode 100755
new mode 100644
similarity index 100%
rename from snesfilter/nall/dsp/resample/average.hpp
rename to kaijuu/nall/dsp/resample/average.hpp
diff --git a/snesfilter/nall/dsp/resample/cosine.hpp b/kaijuu/nall/dsp/resample/cosine.hpp
old mode 100755
new mode 100644
similarity index 100%
rename from snesfilter/nall/dsp/resample/cosine.hpp
rename to kaijuu/nall/dsp/resample/cosine.hpp
diff --git a/snesfilter/nall/dsp/resample/cubic.hpp b/kaijuu/nall/dsp/resample/cubic.hpp
old mode 100755
new mode 100644
similarity index 100%
rename from snesfilter/nall/dsp/resample/cubic.hpp
rename to kaijuu/nall/dsp/resample/cubic.hpp
diff --git a/snesfilter/nall/dsp/resample/hermite.hpp b/kaijuu/nall/dsp/resample/hermite.hpp
old mode 100755
new mode 100644
similarity index 100%
rename from snesfilter/nall/dsp/resample/hermite.hpp
rename to kaijuu/nall/dsp/resample/hermite.hpp
diff --git a/snesfilter/nall/dsp/resample/lib/sinc.hpp b/kaijuu/nall/dsp/resample/lib/sinc.hpp
old mode 100755
new mode 100644
similarity index 100%
rename from snesfilter/nall/dsp/resample/lib/sinc.hpp
rename to kaijuu/nall/dsp/resample/lib/sinc.hpp
diff --git a/snesfilter/nall/dsp/resample/linear.hpp b/kaijuu/nall/dsp/resample/linear.hpp
old mode 100755
new mode 100644
similarity index 100%
rename from snesfilter/nall/dsp/resample/linear.hpp
rename to kaijuu/nall/dsp/resample/linear.hpp
diff --git a/snesfilter/nall/dsp/resample/nearest.hpp b/kaijuu/nall/dsp/resample/nearest.hpp
old mode 100755
new mode 100644
similarity index 100%
rename from snesfilter/nall/dsp/resample/nearest.hpp
rename to kaijuu/nall/dsp/resample/nearest.hpp
diff --git a/snesfilter/nall/dsp/resample/sinc.hpp b/kaijuu/nall/dsp/resample/sinc.hpp
old mode 100755
new mode 100644
similarity index 100%
rename from snesfilter/nall/dsp/resample/sinc.hpp
rename to kaijuu/nall/dsp/resample/sinc.hpp
diff --git a/snesfilter/nall/dsp/settings.hpp b/kaijuu/nall/dsp/settings.hpp
old mode 100755
new mode 100644
similarity index 100%
rename from snesfilter/nall/dsp/settings.hpp
rename to kaijuu/nall/dsp/settings.hpp
diff --git a/kaijuu/nall/emulation/famicom.hpp b/kaijuu/nall/emulation/famicom.hpp
new file mode 100644
index 00000000..84275d69
--- /dev/null
+++ b/kaijuu/nall/emulation/famicom.hpp
@@ -0,0 +1,182 @@
+#ifndef NALL_EMULATION_FAMICOM_HPP
+#define NALL_EMULATION_FAMICOM_HPP
+
+#include
+#include
+
+namespace nall {
+
+struct FamicomCartridge {
+ string markup;
+ inline FamicomCartridge(const uint8_t *data, unsigned size);
+
+//private:
+ unsigned mapper;
+ unsigned mirror;
+ unsigned prgrom;
+ unsigned prgram;
+ unsigned chrrom;
+ unsigned chrram;
+};
+
+FamicomCartridge::FamicomCartridge(const uint8_t *data, unsigned size) {
+ markup = "";
+ if(size < 16) return;
+ if(data[0] != 'N') return;
+ if(data[1] != 'E') return;
+ if(data[2] != 'S') return;
+ if(data[3] != 26) return;
+
+ markup.append("\n");
+
+ mapper = ((data[7] >> 4) << 4) | (data[6] >> 4);
+ mirror = ((data[6] & 0x08) >> 2) | (data[6] & 0x01);
+ prgrom = data[4] * 0x4000;
+ chrrom = data[5] * 0x2000;
+ prgram = 0u;
+ chrram = chrrom == 0u ? 8192u : 0u;
+
+ markup.append("\n");
+
+ switch(mapper) {
+ default:
+ markup.append(" \n");
+ markup.append(" \n");
+ break;
+
+ case 1:
+ markup.append(" \n");
+ markup.append(" \n");
+ prgram = 8192;
+ break;
+
+ case 2:
+ markup.append(" \n");
+ markup.append(" \n");
+ break;
+
+ case 3:
+ markup.append(" \n");
+ markup.append(" \n");
+ break;
+
+ case 4:
+ //MMC3
+ markup.append(" \n");
+ markup.append(" \n");
+ prgram = 8192;
+ //MMC6
+ //markup.append(" \n");
+ //markup.append(" \n");
+ //prgram = 1024;
+ break;
+
+ case 5:
+ markup.append(" \n");
+ markup.append(" \n");
+ prgram = 65536;
+ break;
+
+ case 7:
+ markup.append(" \n");
+ break;
+
+ case 9:
+ markup.append(" \n");
+ markup.append(" \n");
+ prgram = 8192;
+ break;
+
+ case 10:
+ markup.append(" \n");
+ markup.append(" \n");
+ prgram = 8192;
+ break;
+
+ case 16:
+ markup.append(" \n");
+ markup.append(" \n");
+ break;
+
+ case 21:
+ case 23:
+ case 25:
+ //VRC4
+ markup.append(" \n");
+ markup.append(" \n");
+ markup.append(" \n");
+ markup.append(" \n");
+ prgram = 8192;
+ break;
+
+ case 22:
+ //VRC2
+ markup.append(" \n");
+ markup.append(" \n");
+ markup.append(" \n");
+ markup.append(" \n");
+ break;
+
+ case 24:
+ markup.append(" \n");
+ markup.append(" \n");
+ break;
+
+ case 26:
+ markup.append(" \n");
+ markup.append(" \n");
+ prgram = 8192;
+ break;
+
+ case 34:
+ markup.append(" \n");
+ markup.append(" \n");
+ break;
+
+ case 66:
+ markup.append(" \n");
+ markup.append(" \n");
+ break;
+
+ case 69:
+ markup.append(" \n");
+ markup.append(" \n");
+ prgram = 8192;
+ break;
+
+ case 73:
+ markup.append(" \n");
+ markup.append(" \n");
+ markup.append(" \n");
+ prgram = 8192;
+ break;
+
+ case 75:
+ markup.append(" \n");
+ markup.append(" \n");
+ break;
+
+ case 85:
+ markup.append(" \n");
+ markup.append(" \n");
+ prgram = 8192;
+ break;
+ }
+
+ markup.append(" \n");
+ if(prgrom) markup.append(" \n");
+ if(prgram) markup.append(" \n");
+ markup.append(" \n");
+
+ markup.append(" \n");
+ if(chrrom) markup.append(" \n");
+ if(chrram) markup.append(" \n");
+ markup.append(" \n");
+
+ markup.append("\n");
+ markup.transform("'", "\"");
+}
+
+}
+
+#endif
diff --git a/kaijuu/nall/emulation/game-boy-advance.hpp b/kaijuu/nall/emulation/game-boy-advance.hpp
new file mode 100644
index 00000000..e16d0949
--- /dev/null
+++ b/kaijuu/nall/emulation/game-boy-advance.hpp
@@ -0,0 +1,68 @@
+#ifndef NALL_EMULATION_GAME_BOY_ADVANCE_HPP
+#define NALL_EMULATION_GAME_BOY_ADVANCE_HPP
+
+#include
+#include
+#include
+
+namespace nall {
+
+struct GameBoyAdvanceCartridge {
+ string markup;
+ string identifiers;
+ inline GameBoyAdvanceCartridge(const uint8_t *data, unsigned size);
+};
+
+GameBoyAdvanceCartridge::GameBoyAdvanceCartridge(const uint8_t *data, unsigned size) {
+ struct Identifier {
+ string name;
+ unsigned size;
+ };
+ vector idlist;
+ idlist.append({"SRAM_V", 6});
+ idlist.append({"SRAM_F_V", 8});
+ idlist.append({"EEPROM_V", 8});
+ idlist.append({"FLASH_V", 7});
+ idlist.append({"FLASH512_V", 10});
+ idlist.append({"FLASH1M_V", 9});
+
+ lstring list;
+ for(auto &id : idlist) {
+ for(signed n = 0; n < size - 16; n++) {
+ if(!memcmp(data + n, (const char*)id.name, id.size)) {
+ const char *p = (const char*)data + n + id.size;
+ if(p[0] >= '0' && p[0] <= '9'
+ && p[1] >= '0' && p[1] <= '9'
+ && p[2] >= '0' && p[2] <= '9'
+ ) {
+ char text[16];
+ memcpy(text, data + n, id.size + 3);
+ text[id.size + 3] = 0;
+ list.appendonce(text);
+ }
+ }
+ }
+ }
+ identifiers = list.concatenate(",");
+
+ markup = "";
+
+ markup.append("\n");
+ markup.append("\n");
+ markup.append(" \n");
+ if(0);
+ else if(identifiers.beginswith("SRAM_V" )) markup.append(" \n");
+ else if(identifiers.beginswith("SRAM_F_V" )) markup.append(" \n");
+ else if(identifiers.beginswith("EEPROM_V" )) markup.append(" \n");
+ else if(identifiers.beginswith("FLASH_V" )) markup.append(" \n");
+ else if(identifiers.beginswith("FLASH512_V")) markup.append(" \n");
+ else if(identifiers.beginswith("FLASH1M_V" )) markup.append(" \n");
+ if(identifiers.empty() == false) markup.append(" \n");
+
+ markup.append("\n");
+ markup.transform("'", "\"");
+}
+
+}
+
+#endif
diff --git a/snesfilter/nall/gameboy/cartridge.hpp b/kaijuu/nall/emulation/game-boy.hpp
old mode 100755
new mode 100644
similarity index 85%
rename from snesfilter/nall/gameboy/cartridge.hpp
rename to kaijuu/nall/emulation/game-boy.hpp
index 19ff065d..ef1f3da9
--- a/snesfilter/nall/gameboy/cartridge.hpp
+++ b/kaijuu/nall/emulation/game-boy.hpp
@@ -1,10 +1,12 @@
-#ifndef NALL_GAMEBOY_CARTRIDGE_HPP
-#define NALL_GAMEBOY_CARTRIDGE_HPP
+#ifndef NALL_EMULATION_GAME_BOY_HPP
+#define NALL_EMULATION_GAME_BOY_HPP
+
+#include
+#include
namespace nall {
-class GameBoyCartridge {
-public:
+struct GameBoyCartridge {
string markup;
inline GameBoyCartridge(uint8_t *data, unsigned size);
@@ -18,6 +20,9 @@ public:
unsigned romsize;
unsigned ramsize;
+
+ bool cgb;
+ bool cgbonly;
} info;
};
@@ -48,6 +53,9 @@ GameBoyCartridge::GameBoyCartridge(uint8_t *romdata, unsigned romsize) {
memcpy(romdata, header, 0x8000);
}
+ info.cgb = (romdata[0x0143] & 0x80) == 0x80;
+ info.cgbonly = (romdata[0x0143] & 0xc0) == 0xc0;
+
switch(romdata[0x0147]) {
case 0x00: info.mapper = "none"; break;
case 0x01: info.mapper = "MBC1"; break;
@@ -100,15 +108,13 @@ GameBoyCartridge::GameBoyCartridge(uint8_t *romdata, unsigned romsize) {
if(info.mapper == "MBC2") info.ramsize = 512; //512 x 4-bit
- markup.append("cartridge mapper=", info.mapper);
- if(info.rtc) markup.append(" rtc");
- if(info.rumble) markup.append(" rumble");
- markup.append("\n");
-
- markup.append("\t" "rom size=", hex(romsize), "\n"); //TODO: trust/check info.romsize?
-
- if(info.ramsize > 0)
- markup.append("\t" "ram size=", hex(info.ramsize), info.battery ? " non-volatile\n" : "\n");
+ markup = "\n";
+ markup.append("\n");
+ markup.append(" \n");
+ markup.append(" \n");
+ if(info.ramsize > 0) markup.append(" \n");
+ markup.append("\n");
+ markup.transform("'", "\"");
}
}
diff --git a/kaijuu/nall/emulation/satellaview.hpp b/kaijuu/nall/emulation/satellaview.hpp
new file mode 100644
index 00000000..ddae080c
--- /dev/null
+++ b/kaijuu/nall/emulation/satellaview.hpp
@@ -0,0 +1,26 @@
+#ifndef NALL_EMULATION_SATELLAVIEW_HPP
+#define NALL_EMULATION_SATELLAVIEW_HPP
+
+#include
+#include
+
+namespace nall {
+
+struct SatellaviewCartridge {
+ string markup;
+ inline SatellaviewCartridge(const uint8_t *data, unsigned size);
+};
+
+SatellaviewCartridge::SatellaviewCartridge(const uint8_t *data, unsigned size) {
+ markup = "";
+
+ markup.append("\n");
+ markup.append("\n");
+ markup.append(" \n");
+ markup.append("\n");
+ markup.transform("'", "\"");
+}
+
+}
+
+#endif
diff --git a/kaijuu/nall/emulation/sufami-turbo.hpp b/kaijuu/nall/emulation/sufami-turbo.hpp
new file mode 100644
index 00000000..0256360c
--- /dev/null
+++ b/kaijuu/nall/emulation/sufami-turbo.hpp
@@ -0,0 +1,33 @@
+#ifndef NALL_EMULATION_SUFAMI_TURBO_HPP
+#define NALL_EMULATION_SUFAMI_TURBO_HPP
+
+#include
+#include
+
+namespace nall {
+
+struct SufamiTurboCartridge {
+ string markup;
+ inline SufamiTurboCartridge(const uint8_t *data, unsigned size);
+};
+
+SufamiTurboCartridge::SufamiTurboCartridge(const uint8_t *data, unsigned size) {
+ markup = "";
+
+ if(size < 0x20000) return; //too small to be a valid game?
+ if(memcmp(data, "BANDAI SFC-ADX", 14)) return; //missing required header?
+ unsigned romsize = data[0x36] * 0x20000; //128KB
+ unsigned ramsize = data[0x37] * 0x800; //2KB
+ bool linkable = data[0x35] != 0x00; //TODO: unconfirmed
+
+ markup.append("\n");
+ markup.append("\n");
+ markup.append(" \n");
+ markup.append(" \n");
+ markup.append("\n");
+ markup.transform("'", "\"");
+}
+
+}
+
+#endif
diff --git a/kaijuu/nall/emulation/super-famicom-usart.hpp b/kaijuu/nall/emulation/super-famicom-usart.hpp
new file mode 100644
index 00000000..68dea605
--- /dev/null
+++ b/kaijuu/nall/emulation/super-famicom-usart.hpp
@@ -0,0 +1,103 @@
+#ifndef NALL_EMULATION_SUPER_FAMICOM_USART_HPP
+#define NALL_EMULATION_SUPER_FAMICOM_USART_HPP
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#define usartproc dllexport
+
+static nall::function usart_quit;
+static nall::function usart_usleep;
+static nall::function usart_readable;
+static nall::function usart_read;
+static nall::function usart_writable;
+static nall::function usart_write;
+
+extern "C" usartproc void usart_init(
+ nall::function quit,
+ nall::function usleep,
+ nall::function readable,
+ nall::function read,
+ nall::function writable,
+ nall::function write
+) {
+ usart_quit = quit;
+ usart_usleep = usleep;
+ usart_readable = readable;
+ usart_read = read;
+ usart_writable = writable;
+ usart_write = write;
+}
+
+extern "C" usartproc void usart_main(int, char**);
+
+//
+
+static nall::serial usart;
+static bool usart_is_virtual = true;
+static bool usart_sigint = false;
+
+static bool usart_virtual() {
+ return usart_is_virtual;
+}
+
+//
+
+static bool usarthw_quit() {
+ return usart_sigint;
+}
+
+static void usarthw_usleep(unsigned milliseconds) {
+ usleep(milliseconds);
+}
+
+static bool usarthw_readable() {
+ return usart.readable();
+}
+
+static uint8_t usarthw_read() {
+ while(true) {
+ uint8_t buffer[1];
+ signed length = usart.read((uint8_t*)&buffer, 1);
+ if(length > 0) return buffer[0];
+ }
+}
+
+static bool usarthw_writable() {
+ return usart.writable();
+}
+
+static void usarthw_write(uint8_t data) {
+ uint8_t buffer[1] = { data };
+ usart.write((uint8_t*)&buffer, 1);
+}
+
+static void sigint(int) {
+ signal(SIGINT, SIG_DFL);
+ usart_sigint = true;
+}
+
+int main(int argc, char **argv) {
+ setpriority(PRIO_PROCESS, 0, -20); //requires superuser privileges; otherwise priority = +0
+ signal(SIGINT, sigint);
+
+ if(usart.open("/dev/ttyACM0", 57600, true) == false) {
+ printf("error: unable to open USART hardware device\n");
+ return 0;
+ }
+
+ usart_is_virtual = false;
+ usart_init(usarthw_quit, usarthw_usleep, usarthw_readable, usarthw_read, usarthw_writable, usarthw_write);
+ usart_main(argc, argv);
+ usart.close();
+
+ return 0;
+}
+
+#endif
diff --git a/kaijuu/nall/emulation/super-famicom.hpp b/kaijuu/nall/emulation/super-famicom.hpp
new file mode 100644
index 00000000..597f9893
--- /dev/null
+++ b/kaijuu/nall/emulation/super-famicom.hpp
@@ -0,0 +1,800 @@
+#ifndef NALL_EMULATION_SUPER_FAMICOM_HPP
+#define NALL_EMULATION_SUPER_FAMICOM_HPP
+
+#include
+#include
+
+namespace nall {
+
+struct SuperFamicomCartridge {
+ string markup;
+ inline SuperFamicomCartridge(const uint8_t *data, unsigned size);
+
+//private:
+ inline void read_header(const uint8_t *data, unsigned size);
+ inline unsigned find_header(const uint8_t *data, unsigned size);
+ inline unsigned score_header(const uint8_t *data, unsigned size, unsigned addr);
+
+ enum HeaderField {
+ CartName = 0x00,
+ Mapper = 0x15,
+ RomType = 0x16,
+ RomSize = 0x17,
+ RamSize = 0x18,
+ CartRegion = 0x19,
+ Company = 0x1a,
+ Version = 0x1b,
+ Complement = 0x1c, //inverse checksum
+ Checksum = 0x1e,
+ ResetVector = 0x3c,
+ };
+
+ enum Mode {
+ ModeNormal,
+ ModeBsxSlotted,
+ ModeBsx,
+ ModeSufamiTurbo,
+ ModeSuperGameBoy,
+ };
+
+ enum Type {
+ TypeNormal,
+ TypeBsxSlotted,
+ TypeBsxBios,
+ TypeBsx,
+ TypeSufamiTurboBios,
+ TypeSufamiTurbo,
+ TypeSuperGameBoy1Bios,
+ TypeSuperGameBoy2Bios,
+ TypeGameBoy,
+ TypeUnknown,
+ };
+
+ enum Region {
+ NTSC,
+ PAL,
+ };
+
+ enum MemoryMapper {
+ LoROM,
+ HiROM,
+ ExLoROM,
+ ExHiROM,
+ SuperFXROM,
+ SA1ROM,
+ SPC7110ROM,
+ BSCLoROM,
+ BSCHiROM,
+ BSXROM,
+ STROM,
+ };
+
+ enum DSP1MemoryMapper {
+ DSP1Unmapped,
+ DSP1LoROM1MB,
+ DSP1LoROM2MB,
+ DSP1HiROM,
+ };
+
+ bool loaded; //is a base cartridge inserted?
+ unsigned crc32; //crc32 of all cartridges (base+slot(s))
+ unsigned rom_size;
+ unsigned ram_size;
+
+ Mode mode;
+ Type type;
+ Region region;
+ MemoryMapper mapper;
+ DSP1MemoryMapper dsp1_mapper;
+
+ bool has_bsx_slot;
+ bool has_superfx;
+ bool has_sa1;
+ bool has_srtc;
+ bool has_sdd1;
+ bool has_spc7110;
+ bool has_spc7110rtc;
+ bool has_cx4;
+ bool has_dsp1;
+ bool has_dsp2;
+ bool has_dsp3;
+ bool has_dsp4;
+ bool has_obc1;
+ bool has_st010;
+ bool has_st011;
+ bool has_st018;
+};
+
+SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size) {
+ markup = "";
+ if(size < 0x8000) return;
+
+ read_header(data, size);
+
+ markup = "";
+ if(type == TypeGameBoy) return;
+ if(type == TypeBsx) return;
+ if(type == TypeSufamiTurbo) return;
+
+ markup.append("\n");
+
+ const char *range = (rom_size > 0x200000) || (ram_size > 32 * 1024) ? "0000-7fff" : "0000-ffff";
+ markup.append("\n");
+
+ if(type == TypeSuperGameBoy1Bios || type == TypeSuperGameBoy2Bios) markup.append(
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ );
+
+ else if(has_cx4) markup.append(
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ );
+
+ else if(has_spc7110) markup.append(
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ );
+
+ else if(has_sdd1) markup.append(
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ );
+
+ else if(mapper == LoROM) {
+ markup.append(
+ " \n"
+ " \n"
+ " \n"
+ );
+ if(ram_size > 0) markup.append(
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ );
+ }
+
+ else if(mapper == HiROM) {
+ markup.append(
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ );
+ if(ram_size > 0) markup.append(
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ );
+ }
+
+ else if(mapper == ExLoROM) {
+ markup.append(
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ );
+ if(ram_size > 0) markup.append(
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ );
+ }
+
+ else if(mapper == ExHiROM) {
+ markup.append(
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ );
+ if(ram_size > 0) markup.append(
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ );
+ }
+
+ else if(mapper == SuperFXROM) {
+ markup.append(
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ );
+ if(ram_size > 0) markup.append(
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ );
+ markup.append(
+ " \n"
+ );
+ }
+
+ else if(mapper == SA1ROM) {
+ markup.append(
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ );
+ if(ram_size > 0) markup.append(
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ );
+ markup.append(
+ " \n"
+ );
+ }
+
+ else if(mapper == BSCLoROM) markup.append(
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ );
+
+ else if(mapper == BSCHiROM) markup.append(
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ );
+
+ else if(mapper == BSXROM) markup.append(
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ );
+
+ else if(mapper == STROM) markup.append(
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ );
+
+ if(has_spc7110rtc) markup.append(
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ );
+
+ if(has_srtc) markup.append(
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ );
+
+ if(has_obc1) markup.append(
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ );
+
+ if(has_dsp1) {
+ //91e87d11e1c30d172556bed2211cce2efa94ba595f58c5d264809ef4d363a97b dsp1.rom
+ markup.append(
+ " \n"
+ " \n"
+ );
+ if(dsp1_mapper == DSP1LoROM1MB) markup.append(
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ );
+ if(dsp1_mapper == DSP1LoROM2MB) markup.append(
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ );
+ if(dsp1_mapper == DSP1HiROM) markup.append(
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ );
+ markup.append(
+ " \n"
+ );
+ }
+
+ if(has_dsp2) markup.append(
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ );
+
+ if(has_dsp3) markup.append(
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ );
+
+ if(has_dsp4) markup.append(
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ );
+
+ if(has_st010) markup.append(
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ );
+
+ if(has_st011) markup.append(
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ );
+
+ if(has_st018) markup.append(
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ " \n"
+ );
+
+ markup.append("\n");
+ markup.transform("'", "\"");
+}
+
+void SuperFamicomCartridge::read_header(const uint8_t *data, unsigned size) {
+ type = TypeUnknown;
+ mapper = LoROM;
+ dsp1_mapper = DSP1Unmapped;
+ region = NTSC;
+ rom_size = size;
+ ram_size = 0;
+
+ has_bsx_slot = false;
+ has_superfx = false;
+ has_sa1 = false;
+ has_srtc = false;
+ has_sdd1 = false;
+ has_spc7110 = false;
+ has_spc7110rtc = false;
+ has_cx4 = false;
+ has_dsp1 = false;
+ has_dsp2 = false;
+ has_dsp3 = false;
+ has_dsp4 = false;
+ has_obc1 = false;
+ has_st010 = false;
+ has_st011 = false;
+ has_st018 = false;
+
+ //=====================
+ //detect Game Boy carts
+ //=====================
+
+ if(size >= 0x0140) {
+ if(data[0x0104] == 0xce && data[0x0105] == 0xed && data[0x0106] == 0x66 && data[0x0107] == 0x66
+ && data[0x0108] == 0xcc && data[0x0109] == 0x0d && data[0x010a] == 0x00 && data[0x010b] == 0x0b) {
+ type = TypeGameBoy;
+ return;
+ }
+ }
+
+ if(size < 32768) {
+ type = TypeUnknown;
+ return;
+ }
+
+ const unsigned index = find_header(data, size);
+ const uint8_t mapperid = data[index + Mapper];
+ const uint8_t rom_type = data[index + RomType];
+ const uint8_t rom_size = data[index + RomSize];
+ const uint8_t company = data[index + Company];
+ const uint8_t regionid = data[index + CartRegion] & 0x7f;
+
+ ram_size = 1024 << (data[index + RamSize] & 7);
+ if(ram_size == 1024) ram_size = 0; //no RAM present
+
+ //0, 1, 13 = NTSC; 2 - 12 = PAL
+ region = (regionid <= 1 || regionid >= 13) ? NTSC : PAL;
+
+ //=======================
+ //detect BS-X flash carts
+ //=======================
+
+ if(data[index + 0x13] == 0x00 || data[index + 0x13] == 0xff) {
+ if(data[index + 0x14] == 0x00) {
+ const uint8_t n15 = data[index + 0x15];
+ if(n15 == 0x00 || n15 == 0x80 || n15 == 0x84 || n15 == 0x9c || n15 == 0xbc || n15 == 0xfc) {
+ if(data[index + 0x1a] == 0x33 || data[index + 0x1a] == 0xff) {
+ type = TypeBsx;
+ mapper = BSXROM;
+ region = NTSC; //BS-X only released in Japan
+ return;
+ }
+ }
+ }
+ }
+
+ //=========================
+ //detect Sufami Turbo carts
+ //=========================
+
+ if(!memcmp(data, "BANDAI SFC-ADX", 14)) {
+ if(!memcmp(data + 16, "SFC-ADX BACKUP", 14)) {
+ type = TypeSufamiTurboBios;
+ } else {
+ type = TypeSufamiTurbo;
+ }
+ mapper = STROM;
+ region = NTSC; //Sufami Turbo only released in Japan
+ return; //RAM size handled outside this routine
+ }
+
+ //==========================
+ //detect Super Game Boy BIOS
+ //==========================
+
+ if(!memcmp(data + index, "Super GAMEBOY2", 14)) {
+ type = TypeSuperGameBoy2Bios;
+ return;
+ }
+
+ if(!memcmp(data + index, "Super GAMEBOY", 13)) {
+ type = TypeSuperGameBoy1Bios;
+ return;
+ }
+
+ //=====================
+ //detect standard carts
+ //=====================
+
+ //detect presence of BS-X flash cartridge connector (reads extended header information)
+ if(data[index - 14] == 'Z') {
+ if(data[index - 11] == 'J') {
+ uint8_t n13 = data[index - 13];
+ if((n13 >= 'A' && n13 <= 'Z') || (n13 >= '0' && n13 <= '9')) {
+ if(company == 0x33 || (data[index - 10] == 0x00 && data[index - 4] == 0x00)) {
+ has_bsx_slot = true;
+ }
+ }
+ }
+ }
+
+ if(has_bsx_slot) {
+ if(!memcmp(data + index, "Satellaview BS-X ", 21)) {
+ //BS-X base cart
+ type = TypeBsxBios;
+ mapper = BSXROM;
+ region = NTSC; //BS-X only released in Japan
+ return; //RAM size handled internally by load_cart_bsx() -> BSXCart class
+ } else {
+ type = TypeBsxSlotted;
+ mapper = (index == 0x7fc0 ? BSCLoROM : BSCHiROM);
+ region = NTSC; //BS-X slotted cartridges only released in Japan
+ }
+ } else {
+ //standard cart
+ type = TypeNormal;
+
+ if(index == 0x7fc0 && size >= 0x401000) {
+ mapper = ExLoROM;
+ } else if(index == 0x7fc0 && mapperid == 0x32) {
+ mapper = ExLoROM;
+ } else if(index == 0x7fc0) {
+ mapper = LoROM;
+ } else if(index == 0xffc0) {
+ mapper = HiROM;
+ } else { //index == 0x40ffc0
+ mapper = ExHiROM;
+ }
+ }
+
+ if(mapperid == 0x20 && (rom_type == 0x13 || rom_type == 0x14 || rom_type == 0x15 || rom_type == 0x1a)) {
+ has_superfx = true;
+ mapper = SuperFXROM;
+ ram_size = 1024 << (data[index - 3] & 7);
+ if(ram_size == 1024) ram_size = 0;
+ }
+
+ if(mapperid == 0x23 && (rom_type == 0x32 || rom_type == 0x34 || rom_type == 0x35)) {
+ has_sa1 = true;
+ mapper = SA1ROM;
+ }
+
+ if(mapperid == 0x35 && rom_type == 0x55) {
+ has_srtc = true;
+ }
+
+ if(mapperid == 0x32 && (rom_type == 0x43 || rom_type == 0x45)) {
+ has_sdd1 = true;
+ }
+
+ if(mapperid == 0x3a && (rom_type == 0xf5 || rom_type == 0xf9)) {
+ has_spc7110 = true;
+ has_spc7110rtc = (rom_type == 0xf9);
+ mapper = SPC7110ROM;
+ }
+
+ if(mapperid == 0x20 && rom_type == 0xf3) {
+ has_cx4 = true;
+ }
+
+ if((mapperid == 0x20 || mapperid == 0x21) && rom_type == 0x03) {
+ has_dsp1 = true;
+ }
+
+ if(mapperid == 0x30 && rom_type == 0x05 && company != 0xb2) {
+ has_dsp1 = true;
+ }
+
+ if(mapperid == 0x31 && (rom_type == 0x03 || rom_type == 0x05)) {
+ has_dsp1 = true;
+ }
+
+ if(has_dsp1 == true) {
+ if((mapperid & 0x2f) == 0x20 && size <= 0x100000) {
+ dsp1_mapper = DSP1LoROM1MB;
+ } else if((mapperid & 0x2f) == 0x20) {
+ dsp1_mapper = DSP1LoROM2MB;
+ } else if((mapperid & 0x2f) == 0x21) {
+ dsp1_mapper = DSP1HiROM;
+ }
+ }
+
+ if(mapperid == 0x20 && rom_type == 0x05) {
+ has_dsp2 = true;
+ }
+
+ if(mapperid == 0x30 && rom_type == 0x05 && company == 0xb2) {
+ has_dsp3 = true;
+ }
+
+ if(mapperid == 0x30 && rom_type == 0x03) {
+ has_dsp4 = true;
+ }
+
+ if(mapperid == 0x30 && rom_type == 0x25) {
+ has_obc1 = true;
+ }
+
+ if(mapperid == 0x30 && rom_type == 0xf6 && rom_size >= 10) {
+ has_st010 = true;
+ }
+
+ if(mapperid == 0x30 && rom_type == 0xf6 && rom_size < 10) {
+ has_st011 = true;
+ }
+
+ if(mapperid == 0x30 && rom_type == 0xf5) {
+ has_st018 = true;
+ }
+}
+
+unsigned SuperFamicomCartridge::find_header(const uint8_t *data, unsigned size) {
+ unsigned score_lo = score_header(data, size, 0x007fc0);
+ unsigned score_hi = score_header(data, size, 0x00ffc0);
+ unsigned score_ex = score_header(data, size, 0x40ffc0);
+ if(score_ex) score_ex += 4; //favor ExHiROM on images > 32mbits
+
+ if(score_lo >= score_hi && score_lo >= score_ex) {
+ return 0x007fc0;
+ } else if(score_hi >= score_ex) {
+ return 0x00ffc0;
+ } else {
+ return 0x40ffc0;
+ }
+}
+
+unsigned SuperFamicomCartridge::score_header(const uint8_t *data, unsigned size, unsigned addr) {
+ if(size < addr + 64) return 0; //image too small to contain header at this location?
+ int score = 0;
+
+ uint16_t resetvector = data[addr + ResetVector] | (data[addr + ResetVector + 1] << 8);
+ uint16_t checksum = data[addr + Checksum ] | (data[addr + Checksum + 1] << 8);
+ uint16_t complement = data[addr + Complement ] | (data[addr + Complement + 1] << 8);
+
+ uint8_t resetop = data[(addr & ~0x7fff) | (resetvector & 0x7fff)]; //first opcode executed upon reset
+ uint8_t mapper = data[addr + Mapper] & ~0x10; //mask off irrelevent FastROM-capable bit
+
+ //$00:[000-7fff] contains uninitialized RAM and MMIO.
+ //reset vector must point to ROM at $00:[8000-ffff] to be considered valid.
+ if(resetvector < 0x8000) return 0;
+
+ //some images duplicate the header in multiple locations, and others have completely
+ //invalid header information that cannot be relied upon.
+ //below code will analyze the first opcode executed at the specified reset vector to
+ //determine the probability that this is the correct header.
+
+ //most likely opcodes
+ if(resetop == 0x78 //sei
+ || resetop == 0x18 //clc (clc; xce)
+ || resetop == 0x38 //sec (sec; xce)
+ || resetop == 0x9c //stz $nnnn (stz $4200)
+ || resetop == 0x4c //jmp $nnnn
+ || resetop == 0x5c //jml $nnnnnn
+ ) score += 8;
+
+ //plausible opcodes
+ if(resetop == 0xc2 //rep #$nn
+ || resetop == 0xe2 //sep #$nn
+ || resetop == 0xad //lda $nnnn
+ || resetop == 0xae //ldx $nnnn
+ || resetop == 0xac //ldy $nnnn
+ || resetop == 0xaf //lda $nnnnnn
+ || resetop == 0xa9 //lda #$nn
+ || resetop == 0xa2 //ldx #$nn
+ || resetop == 0xa0 //ldy #$nn
+ || resetop == 0x20 //jsr $nnnn
+ || resetop == 0x22 //jsl $nnnnnn
+ ) score += 4;
+
+ //implausible opcodes
+ if(resetop == 0x40 //rti
+ || resetop == 0x60 //rts
+ || resetop == 0x6b //rtl
+ || resetop == 0xcd //cmp $nnnn
+ || resetop == 0xec //cpx $nnnn
+ || resetop == 0xcc //cpy $nnnn
+ ) score -= 4;
+
+ //least likely opcodes
+ if(resetop == 0x00 //brk #$nn
+ || resetop == 0x02 //cop #$nn
+ || resetop == 0xdb //stp
+ || resetop == 0x42 //wdm
+ || resetop == 0xff //sbc $nnnnnn,x
+ ) score -= 8;
+
+ //at times, both the header and reset vector's first opcode will match ...
+ //fallback and rely on info validity in these cases to determine more likely header.
+
+ //a valid checksum is the biggest indicator of a valid header.
+ if((checksum + complement) == 0xffff && (checksum != 0) && (complement != 0)) score += 4;
+
+ if(addr == 0x007fc0 && mapper == 0x20) score += 2; //0x20 is usually LoROM
+ if(addr == 0x00ffc0 && mapper == 0x21) score += 2; //0x21 is usually HiROM
+ if(addr == 0x007fc0 && mapper == 0x22) score += 2; //0x22 is usually ExLoROM
+ if(addr == 0x40ffc0 && mapper == 0x25) score += 2; //0x25 is usually ExHiROM
+
+ if(data[addr + Company] == 0x33) score += 2; //0x33 indicates extended header
+ if(data[addr + RomType] < 0x08) score++;
+ if(data[addr + RomSize] < 0x10) score++;
+ if(data[addr + RamSize] < 0x08) score++;
+ if(data[addr + CartRegion] < 14) score++;
+
+ if(score < 0) score = 0;
+ return score;
+}
+
+}
+
+#endif
diff --git a/snesfilter/nall/endian.hpp b/kaijuu/nall/endian.hpp
old mode 100755
new mode 100644
similarity index 100%
rename from snesfilter/nall/endian.hpp
rename to kaijuu/nall/endian.hpp
diff --git a/snesfilter/nall/file.hpp b/kaijuu/nall/file.hpp
old mode 100755
new mode 100644
similarity index 81%
rename from snesfilter/nall/file.hpp
rename to kaijuu/nall/file.hpp
index 8447f3ab..8a751041
--- a/snesfilter/nall/file.hpp
+++ b/kaijuu/nall/file.hpp
@@ -6,6 +6,7 @@
#include
#include
#include
+#include
namespace nall {
inline FILE* fopen_utf8(const string &utf8_filename, const char *mode) {
@@ -16,25 +17,61 @@ namespace nall {
#endif
}
- class file {
- public:
- enum class mode : unsigned { read, write, readwrite, writeread };
+ struct file {
+ enum class mode : unsigned { read, write, modify, append, readwrite = modify, writeread = append };
enum class index : unsigned { absolute, relative };
enum class time : unsigned { create, modify, access };
- static bool read(const string &filename, uint8_t *&data, unsigned &size) {
- data = 0;
- file fp;
- if(fp.open(filename, mode::read) == false) return false;
- size = fp.size();
- data = new uint8_t[size];
- fp.read(data, size);
- fp.close();
+ static bool copy(const string &sourcename, const string &targetname) {
+ file rd, wr;
+ if(rd.open(sourcename, mode::read) == false) return false;
+ if(wr.open(targetname, mode::write) == false) return false;
+ for(unsigned n = 0; n < rd.size(); n++) wr.write(rd.read());
return true;
}
- static bool read(const string &filename, const uint8_t *&data, unsigned &size) {
- return file::read(filename, (uint8_t*&)data, size);
+ static bool move(const string &sourcename, const string &targetname) {
+ #if !defined(_WIN32)
+ return rename(sourcename, targetname) == 0;
+ #else
+ return _wrename(utf16_t(sourcename), utf16_t(targetname)) == 0;
+ #endif
+ }
+
+ static bool remove(const string &filename) {
+ return unlink(filename) == 0;
+ }
+
+ static bool truncate(const string &filename, unsigned size) {
+ #if !defined(_WIN32)
+ return truncate(filename, size) == 0;
+ #else
+ bool result = false;
+ FILE *fp = fopen(filename, "rb+");
+ if(fp) {
+ result = _chsize(fileno(fp), size) == 0;
+ fclose(fp);
+ }
+ return result;
+ #endif
+ }
+
+ static vector read(const string &filename) {
+ vector memory;
+ file fp;
+ if(fp.open(filename, mode::read)) {
+ memory.resize(fp.size());
+ fp.read(memory.data(), memory.size());
+ }
+ return memory;
+ }
+
+ static bool read(const string &filename, uint8_t *data, unsigned size) {
+ file fp;
+ if(fp.open(filename, mode::read) == false) return false;
+ fp.read(data, size);
+ fp.close();
+ return true;
}
static bool write(const string &filename, const uint8_t *data, unsigned size) {
@@ -134,13 +171,13 @@ namespace nall {
file_offset = req_offset;
}
- int offset() {
- if(!fp) return -1; //file not open
+ unsigned offset() const {
+ if(!fp) return 0; //file not open
return file_offset;
}
- int size() {
- if(!fp) return -1; //file not open
+ unsigned size() const {
+ if(!fp) return 0; //file not open
return file_size;
}
@@ -194,7 +231,7 @@ namespace nall {
}
}
- bool open() {
+ bool open() const {
return fp;
}
@@ -232,7 +269,7 @@ namespace nall {
file() {
memset(buffer, 0, sizeof buffer);
- buffer_offset = -1;
+ buffer_offset = -1; //invalidate buffer
buffer_dirty = false;
fp = 0;
file_offset = 0;
diff --git a/snesfilter/nall/filemap.hpp b/kaijuu/nall/filemap.hpp
old mode 100755
new mode 100644
similarity index 99%
rename from snesfilter/nall/filemap.hpp
rename to kaijuu/nall/filemap.hpp
index 7eeac2b0..f57d933c
--- a/snesfilter/nall/filemap.hpp
+++ b/kaijuu/nall/filemap.hpp
@@ -1,6 +1,7 @@
#ifndef NALL_FILEMAP_HPP
#define NALL_FILEMAP_HPP
+#include
#include
#include
diff --git a/snesfilter/nall/function.hpp b/kaijuu/nall/function.hpp
old mode 100755
new mode 100644
similarity index 100%
rename from snesfilter/nall/function.hpp
rename to kaijuu/nall/function.hpp
diff --git a/snesfilter/nall/gzip.hpp b/kaijuu/nall/gzip.hpp
old mode 100755
new mode 100644
similarity index 83%
rename from snesfilter/nall/gzip.hpp
rename to kaijuu/nall/gzip.hpp
index 8f5d206b..a72a3faf
--- a/snesfilter/nall/gzip.hpp
+++ b/kaijuu/nall/gzip.hpp
@@ -11,20 +11,18 @@ struct gzip {
uint8_t *data;
unsigned size;
- bool decompress(const string &filename);
- bool decompress(const uint8_t *data, unsigned size);
+ inline bool decompress(const string &filename);
+ inline bool decompress(const uint8_t *data, unsigned size);
- gzip();
- ~gzip();
+ inline gzip();
+ inline ~gzip();
};
bool gzip::decompress(const string &filename) {
- uint8_t *data;
- unsigned size;
- if(file::read(filename, data, size) == false) return false;
- bool result = decompress(data, size);
- delete[] data;
- return result;
+ if(auto memory = file::read(filename)) {
+ return decompress(memory.data(), memory.size());
+ }
+ return false;
}
bool gzip::decompress(const uint8_t *data, unsigned size) {
diff --git a/snesfilter/nall/http.hpp b/kaijuu/nall/http.hpp
old mode 100755
new mode 100644
similarity index 99%
rename from snesfilter/nall/http.hpp
rename to kaijuu/nall/http.hpp
index 1b2eab4f..48aeb097
--- a/snesfilter/nall/http.hpp
+++ b/kaijuu/nall/http.hpp
@@ -7,9 +7,9 @@
#include
#include
#else
- #include
#include
#include
+ #include
#endif
#include
@@ -117,7 +117,7 @@ struct http {
}
}
} else if(auto position = header.iposition("\r\nContent-Length: ")) {
- unsigned length = decimal((const char*)header + position() + 16);
+ unsigned length = decimal((const char*)header + position() + 18);
while(length) {
char buffer[256];
int packetlength = recv(serversocket, buffer, min(256, length), 0);
diff --git a/snesfilter/nall/image.hpp b/kaijuu/nall/image.hpp
old mode 100755
new mode 100644
similarity index 75%
rename from snesfilter/nall/image.hpp
rename to kaijuu/nall/image.hpp
index c79655eb..552a3e30
--- a/snesfilter/nall/image.hpp
+++ b/kaijuu/nall/image.hpp
@@ -2,6 +2,7 @@
#define NALL_IMAGE_HPP
#include
+#include
#include
#include
#include
@@ -35,14 +36,21 @@ struct image {
inline image(const image &source);
inline image(image &&source);
inline image(bool endian, unsigned depth, uint64_t alphaMask, uint64_t redMask, uint64_t greenMask, uint64_t blueMask);
+ inline image(const string &filename);
+ inline image(const uint8_t *data, unsigned size);
+ inline image();
inline ~image();
inline uint64_t read(const uint8_t *data) const;
inline void write(uint8_t *data, uint64_t value) const;
inline void free();
+ inline bool empty() const;
inline void allocate(unsigned width, unsigned height);
+ inline void clear(uint64_t color);
inline bool load(const string &filename);
+//inline bool loadBMP(const uint8_t *data, unsigned size);
+ inline bool loadPNG(const uint8_t *data, unsigned size);
inline void scale(unsigned width, unsigned height, interpolation op);
inline void transform(bool endian, unsigned depth, uint64_t alphaMask, uint64_t redMask, uint64_t greenMask, uint64_t blueMask);
inline void alphaBlend(uint64_t alphaColor);
@@ -141,6 +149,52 @@ image::image(bool endian, unsigned depth, uint64_t alphaMask, uint64_t redMask,
blue.depth = bitDepth(blue.mask), blue.shift = bitShift(blue.mask);
}
+image::image(const string &filename) : data(nullptr) {
+ width = 0, height = 0, pitch = 0;
+
+ this->endian = 0;
+ this->depth = 32;
+ this->stride = 4;
+
+ alpha.mask = 255u << 24, red.mask = 255u << 16, green.mask = 255u << 8, blue.mask = 255u << 0;
+ alpha.depth = bitDepth(alpha.mask), alpha.shift = bitShift(alpha.mask);
+ red.depth = bitDepth(red.mask), red.shift = bitShift(red.mask);
+ green.depth = bitDepth(green.mask), green.shift = bitShift(green.mask);
+ blue.depth = bitDepth(blue.mask), blue.shift = bitShift(blue.mask);
+
+ load(filename);
+}
+
+image::image(const uint8_t *data, unsigned size) : data(nullptr) {
+ width = 0, height = 0, pitch = 0;
+
+ this->endian = 0;
+ this->depth = 32;
+ this->stride = 4;
+
+ alpha.mask = 255u << 24, red.mask = 255u << 16, green.mask = 255u << 8, blue.mask = 255u << 0;
+ alpha.depth = bitDepth(alpha.mask), alpha.shift = bitShift(alpha.mask);
+ red.depth = bitDepth(red.mask), red.shift = bitShift(red.mask);
+ green.depth = bitDepth(green.mask), green.shift = bitShift(green.mask);
+ blue.depth = bitDepth(blue.mask), blue.shift = bitShift(blue.mask);
+
+ loadPNG(data, size);
+}
+
+image::image() : data(nullptr) {
+ width = 0, height = 0, pitch = 0;
+
+ this->endian = 0;
+ this->depth = 32;
+ this->stride = 4;
+
+ alpha.mask = 255u << 24, red.mask = 255u << 16, green.mask = 255u << 8, blue.mask = 255u << 0;
+ alpha.depth = bitDepth(alpha.mask), alpha.shift = bitShift(alpha.mask);
+ red.depth = bitDepth(red.mask), red.shift = bitShift(red.mask);
+ green.depth = bitDepth(green.mask), green.shift = bitShift(green.mask);
+ blue.depth = bitDepth(blue.mask), blue.shift = bitShift(blue.mask);
+}
+
image::~image() {
free();
}
@@ -168,7 +222,14 @@ void image::free() {
data = nullptr;
}
+bool image::empty() const {
+ if(data == nullptr) return true;
+ if(width == 0 || height == 0) return true;
+ return false;
+}
+
void image::allocate(unsigned width, unsigned height) {
+ if(data != nullptr && this->width == width && this->height == height) return;
free();
data = new uint8_t[width * height * stride]();
pitch = width * stride;
@@ -176,6 +237,14 @@ void image::allocate(unsigned width, unsigned height) {
this->height = height;
}
+void image::clear(uint64_t color) {
+ uint8_t *dp = data;
+ for(unsigned n = 0; n < width * height; n++) {
+ write(dp, color);
+ dp += stride;
+ }
+}
+
bool image::load(const string &filename) {
if(loadBMP(filename) == true) return true;
if(loadPNG(filename) == true) return true;
@@ -183,8 +252,8 @@ bool image::load(const string &filename) {
}
void image::scale(unsigned outputWidth, unsigned outputHeight, interpolation op) {
- scaleX(outputWidth, op);
- scaleY(outputHeight, op);
+ if(width != outputWidth) scaleX(outputWidth, op);
+ if(height != outputHeight) scaleY(outputHeight, op);
}
void image::transform(bool outputEndian, unsigned outputDepth, uint64_t outputAlphaMask, uint64_t outputRedMask, uint64_t outputGreenMask, uint64_t outputBlueMask) {
@@ -209,7 +278,7 @@ void image::transform(bool outputEndian, unsigned outputDepth, uint64_t outputAl
g = normalize(g, green.depth, output.green.depth);
b = normalize(b, blue.depth, output.blue.depth);
- output.write(dp, (a << output.alpha.shift) + (r << output.red.shift) + (g << output.green.shift) + (b << output.blue.shift));
+ output.write(dp, (a << output.alpha.shift) | (r << output.red.shift) | (g << output.green.shift) | (b << output.blue.shift));
dp += output.stride;
}
}
@@ -239,7 +308,7 @@ void image::alphaBlend(uint64_t alphaColor) {
colorG = (colorG * alphaScale) + (alphaG * (1.0 - alphaScale));
colorB = (colorB * alphaScale) + (alphaB * (1.0 - alphaScale));
- write(dp, (colorA << alpha.shift) + (colorR << red.shift) + (colorG << green.shift) + (colorB << blue.shift));
+ write(dp, (colorA << alpha.shift) | (colorR << red.shift) | (colorG << green.shift) | (colorB << blue.shift));
dp += stride;
}
}
@@ -267,13 +336,14 @@ uint64_t image::interpolate(double mu, const uint64_t *s, double (*op)(double, d
G = max(0, min(G, (1 << green.depth) - 1));
B = max(0, min(B, (1 << blue.depth) - 1));
- return (A << alpha.shift) + (R << red.shift) + (G << green.shift) + (B << blue.shift);
+ return (A << alpha.shift) | (R << red.shift) | (G << green.shift) | (B << blue.shift);
}
void image::scaleX(unsigned outputWidth, interpolation op) {
uint8_t *outputData = new uint8_t[outputWidth * height * stride];
unsigned outputPitch = outputWidth * stride;
double step = (double)width / (double)outputWidth;
+ const uint8_t *terminal = data + pitch * height;
#pragma omp parallel for
for(unsigned y = 0; y < height; y++) {
@@ -281,15 +351,12 @@ void image::scaleX(unsigned outputWidth, interpolation op) {
uint8_t *sp = data + pitch * y;
double fraction = 0.0;
- uint64_t s[4] = { read(sp), read(sp), read(sp), read(sp) };
+ uint64_t s[4] = { sp < terminal ? read(sp) : 0 }; //B,C (0,1) = center of kernel { 0, 0, 1, 2 }
+ s[1] = s[0];
+ s[2] = sp + stride < terminal ? read(sp += stride) : s[1];
+ s[3] = sp + stride < terminal ? read(sp += stride) : s[2];
for(unsigned x = 0; x < width; x++) {
- if(sp >= data + pitch * height) break;
- s[0] = s[1];
- s[1] = s[2];
- s[2] = s[3];
- s[3] = read(sp);
-
while(fraction <= 1.0) {
if(dp >= outputData + outputPitch * height) break;
write(dp, interpolate(fraction, (const uint64_t*)&s, op));
@@ -297,7 +364,8 @@ void image::scaleX(unsigned outputWidth, interpolation op) {
fraction += step;
}
- sp += stride;
+ s[0] = s[1]; s[1] = s[2]; s[2] = s[3];
+ if(sp + stride < terminal) s[3] = read(sp += stride);
fraction -= 1.0;
}
}
@@ -311,6 +379,7 @@ void image::scaleX(unsigned outputWidth, interpolation op) {
void image::scaleY(unsigned outputHeight, interpolation op) {
uint8_t *outputData = new uint8_t[width * outputHeight * stride];
double step = (double)height / (double)outputHeight;
+ const uint8_t *terminal = data + pitch * height;
#pragma omp parallel for
for(unsigned x = 0; x < width; x++) {
@@ -318,15 +387,12 @@ void image::scaleY(unsigned outputHeight, interpolation op) {
uint8_t *sp = data + stride * x;
double fraction = 0.0;
- uint64_t s[4] = { read(sp), read(sp), read(sp), read(sp) };
+ uint64_t s[4] = { sp < terminal ? read(sp) : 0 };
+ s[1] = s[0];
+ s[2] = sp + pitch < terminal ? read(sp += pitch) : s[1];
+ s[3] = sp + pitch < terminal ? read(sp += pitch) : s[2];
for(unsigned y = 0; y < height; y++) {
- if(sp >= data + pitch * height) break;
- s[0] = s[1];
- s[1] = s[2];
- s[2] = s[3];
- s[3] = read(sp);
-
while(fraction <= 1.0) {
if(dp >= outputData + pitch * outputHeight) break;
write(dp, interpolate(fraction, (const uint64_t*)&s, op));
@@ -334,7 +400,8 @@ void image::scaleY(unsigned outputHeight, interpolation op) {
fraction += step;
}
- sp += pitch;
+ s[0] = s[1]; s[1] = s[2]; s[2] = s[3];
+ if(sp + pitch < terminal) s[3] = read(sp += pitch);
fraction -= 1.0;
}
}
@@ -360,7 +427,7 @@ bool image::loadBMP(const string &filename) {
uint64_t r = normalize((uint8_t)(color >> 16), 8, red.depth);
uint64_t g = normalize((uint8_t)(color >> 8), 8, green.depth);
uint64_t b = normalize((uint8_t)(color >> 0), 8, blue.depth);
- write(dp, (a << alpha.shift) + (r << red.shift) + (g << green.shift) + (b << blue.shift));
+ write(dp, (a << alpha.shift) | (r << red.shift) | (g << green.shift) | (b << blue.shift));
dp += stride;
}
}
@@ -369,9 +436,9 @@ bool image::loadBMP(const string &filename) {
return true;
}
-bool image::loadPNG(const string &filename) {
+bool image::loadPNG(const uint8_t *pngData, unsigned pngSize) {
png source;
- if(source.decode(filename) == false) return false;
+ if(source.decode(pngData, pngSize) == false) return false;
allocate(source.info.width, source.info.height);
const uint8_t *sp = source.data;
@@ -415,7 +482,7 @@ bool image::loadPNG(const string &filename) {
g = normalize(g, source.info.bitDepth, green.depth);
b = normalize(b, source.info.bitDepth, blue.depth);
- return (a << alpha.shift) + (r << red.shift) + (g << green.shift) + (b << blue.shift);
+ return (a << alpha.shift) | (r << red.shift) | (g << green.shift) | (b << blue.shift);
};
for(unsigned y = 0; y < height; y++) {
@@ -428,6 +495,12 @@ bool image::loadPNG(const string &filename) {
return true;
}
+bool image::loadPNG(const string &filename) {
+ filemap map;
+ if(map.open(filename, filemap::mode::read) == false) return false;
+ return loadPNG(map.data(), map.size());
+}
+
}
#endif
diff --git a/snesfilter/nall/inflate.hpp b/kaijuu/nall/inflate.hpp
old mode 100755
new mode 100644
similarity index 100%
rename from snesfilter/nall/inflate.hpp
rename to kaijuu/nall/inflate.hpp
diff --git a/snesfilter/nall/input.hpp b/kaijuu/nall/input.hpp
old mode 100755
new mode 100644
similarity index 100%
rename from snesfilter/nall/input.hpp
rename to kaijuu/nall/input.hpp
diff --git a/snesfilter/nall/interpolation.hpp b/kaijuu/nall/interpolation.hpp
old mode 100755
new mode 100644
similarity index 91%
rename from snesfilter/nall/interpolation.hpp
rename to kaijuu/nall/interpolation.hpp
index 46a09a49..afc7108b
--- a/snesfilter/nall/interpolation.hpp
+++ b/kaijuu/nall/interpolation.hpp
@@ -5,23 +5,23 @@ namespace nall {
struct Interpolation {
static inline double Nearest(double mu, double a, double b, double c, double d) {
- return (mu < 0.5 ? c : d);
+ return (mu <= 0.5 ? b : c);
}
static inline double Sublinear(double mu, double a, double b, double c, double d) {
mu = ((mu - 0.5) * 2.0) + 0.5;
if(mu < 0) mu = 0;
if(mu > 1) mu = 1;
- return c * (1.0 - mu) + d * mu;
+ return b * (1.0 - mu) + c * mu;
}
static inline double Linear(double mu, double a, double b, double c, double d) {
- return c * (1.0 - mu) + d * mu;
+ return b * (1.0 - mu) + c * mu;
}
static inline double Cosine(double mu, double a, double b, double c, double d) {
mu = (1.0 - cos(mu * 3.14159265)) / 2.0;
- return c * (1.0 - mu) + d * mu;
+ return b * (1.0 - mu) + c * mu;
}
static inline double Cubic(double mu, double a, double b, double c, double d) {
diff --git a/snesfilter/nall/intrinsics.hpp b/kaijuu/nall/intrinsics.hpp
old mode 100755
new mode 100644
similarity index 100%
rename from snesfilter/nall/intrinsics.hpp
rename to kaijuu/nall/intrinsics.hpp
diff --git a/kaijuu/nall/invoke.hpp b/kaijuu/nall/invoke.hpp
new file mode 100644
index 00000000..9dfb7d0b
--- /dev/null
+++ b/kaijuu/nall/invoke.hpp
@@ -0,0 +1,52 @@
+#ifndef NALL_INVOKE_HPP
+#define NALL_INVOKE_HPP
+
+//void invoke(const string &name, const string& args...);
+//if a program is specified, it is executed with the arguments provided
+//if a file is specified, the file is opened using the program associated with said file type
+//if a folder is specified, the folder is opened using the associated file explorer
+//if a URL is specified, the default web browser is opened and pointed at the URL requested
+//path environment variable is always consulted
+//execution is asynchronous (non-blocking); use system() for synchronous execution
+
+#include
+#ifdef _WIN32
+ #include
+#endif
+
+namespace nall {
+
+#ifdef _WIN32
+
+template
+inline void invoke(const string &name, Args&&... args) {
+ lstring argl(std::forward(args)...);
+ for(auto &arg : argl) if(arg.position(" ")) arg = {"\"", arg, "\""};
+ string arguments = argl.concatenate(" ");
+ ShellExecuteW(NULL, NULL, utf16_t(name), utf16_t(arguments), NULL, SW_SHOWNORMAL);
+}
+
+#else
+
+template
+inline void invoke(const string &name, Args&&... args) {
+ pid_t pid = fork();
+ if(pid == 0) {
+ const char *argv[1 + sizeof...(args) + 1], **argp = argv;
+ lstring argl(std::forward(args)...);
+ *argp++ = (const char*)name;
+ for(auto &arg : argl) *argp++ = (const char*)arg;
+ *argp++ = nullptr;
+
+ if(execvp(name, (char* const*)argv) < 0) {
+ execlp("xdg-open", "xdg-open", (const char*)name, nullptr);
+ }
+ exit(0);
+ }
+}
+
+#endif
+
+}
+
+#endif
diff --git a/snesfilter/nall/ips.hpp b/kaijuu/nall/ips.hpp
old mode 100755
new mode 100644
similarity index 89%
rename from snesfilter/nall/ips.hpp
rename to kaijuu/nall/ips.hpp
index 3071d038..473d74c5
--- a/snesfilter/nall/ips.hpp
+++ b/kaijuu/nall/ips.hpp
@@ -11,8 +11,6 @@ struct ips {
inline bool apply();
inline void source(const uint8_t *data, unsigned size);
inline void modify(const uint8_t *data, unsigned size);
- inline bool source(const string &filename);
- inline bool modify(const string &filename);
inline ips();
inline ~ips();
@@ -88,14 +86,6 @@ void ips::modify(const uint8_t *data, unsigned size) {
modifyData = data, modifySize = size;
}
-bool ips::source(const string &filename) {
- return file::read(filename, sourceData, sourceSize);
-}
-
-bool ips::modify(const string &filename) {
- return file::read(filename, modifyData, modifySize);
-}
-
ips::ips() : data(nullptr), sourceData(nullptr), modifyData(nullptr) {
}
diff --git a/snesfilter/nall/lzss.hpp b/kaijuu/nall/lzss.hpp
old mode 100755
new mode 100644
similarity index 100%
rename from snesfilter/nall/lzss.hpp
rename to kaijuu/nall/lzss.hpp
diff --git a/kaijuu/nall/map.hpp b/kaijuu/nall/map.hpp
new file mode 100644
index 00000000..938f0c2d
--- /dev/null
+++ b/kaijuu/nall/map.hpp
@@ -0,0 +1,117 @@
+#ifndef NALL_MAP_HPP
+#define NALL_MAP_HPP
+
+#include
+
+namespace nall {
+
+template
+struct map {
+ struct pair {
+ LHS name;
+ RHS data;
+ };
+
+ inline void reset() {
+ list.reset();
+ }
+
+ inline unsigned size() const {
+ return list.size();
+ }
+
+ //O(log n) find
+ inline optional find(const LHS &name) const {
+ signed first = 0, last = size() - 1;
+ while(first <= last) {
+ signed middle = (first + last) / 2;
+ if(name < list[middle].name) last = middle - 1; //search lower half
+ else if(list[middle].name < name) first = middle + 1; //search upper half
+ else return { true, (unsigned)middle }; //match found
+ }
+ return { false, 0u };
+ }
+
+ //O(n) insert + O(log n) find
+ inline RHS& insert(const LHS &name, const RHS &data) {
+ if(auto position = find(name)) {
+ list[position()].data = data;
+ return list[position()].data;
+ }
+ signed offset = size();
+ for(unsigned n = 0; n < size(); n++) {
+ if(name < list[n].name) { offset = n; break; }
+ }
+ list.insert(offset, { name, data });
+ return list[offset].data;
+ }
+
+ //O(log n) find
+ inline void modify(const LHS &name, const RHS &data) {
+ if(auto position = find(name)) list[position()].data = data;
+ }
+
+ //O(n) remove + O(log n) find
+ inline void remove(const LHS &name) {
+ if(auto position = find(name)) list.remove(position());
+ }
+
+ //O(log n) find
+ inline RHS& operator[](const LHS &name) {
+ if(auto position = find(name)) return list[position()].data;
+ throw;
+ }
+
+ inline const RHS& operator[](const LHS &name) const {
+ if(auto position = find(name)) return list[position()].data;
+ throw;
+ }
+
+ inline RHS& operator()(const LHS &name) {
+ if(auto position = find(name)) return list[position()].data;
+ return insert(name, RHS());
+ }
+
+ inline const RHS& operator()(const LHS &name, const RHS &data) const {
+ if(auto position = find(name)) return list[position()].data;
+ return data;
+ }
+
+ inline pair* begin() { return list.begin(); }
+ inline pair* end() { return list.end(); }
+ inline const pair* begin() const { return list.begin(); }
+ inline const pair* end() const { return list.end(); }
+
+protected:
+ vector list;
+};
+
+template
+struct bidirectional_map {
+ const map &lhs;
+ const map &rhs;
+
+ inline void reset() {
+ llist.reset();
+ rlist.reset();
+ }
+
+ inline unsigned size() const {
+ return llist.size();
+ }
+
+ inline void insert(const LHS &ldata, const RHS &rdata) {
+ llist.insert(ldata, rdata);
+ rlist.insert(rdata, ldata);
+ }
+
+ inline bidirectional_map() : lhs(llist), rhs(rlist) {}
+
+protected:
+ map llist;
+ map rlist;
+};
+
+}
+
+#endif
diff --git a/kaijuu/nall/mosaic.hpp b/kaijuu/nall/mosaic.hpp
new file mode 100644
index 00000000..16fd0bfd
--- /dev/null
+++ b/kaijuu/nall/mosaic.hpp
@@ -0,0 +1,10 @@
+#ifndef NALL_MOSAIC_HPP
+#define NALL_MOSAIC_HPP
+
+#define NALL_MOSAIC_INTERNAL_HPP
+#include
+#include
+#include
+#undef NALL_MOSAIC_INTERNAL_HPP
+
+#endif
diff --git a/kaijuu/nall/mosaic/bitstream.hpp b/kaijuu/nall/mosaic/bitstream.hpp
new file mode 100644
index 00000000..e2cb3bc5
--- /dev/null
+++ b/kaijuu/nall/mosaic/bitstream.hpp
@@ -0,0 +1,55 @@
+#ifdef NALL_MOSAIC_INTERNAL_HPP
+
+namespace nall {
+namespace mosaic {
+
+struct bitstream {
+ filemap fp;
+ uint8_t *data;
+ unsigned size;
+ bool readonly;
+ bool endian;
+
+ inline bool read(uint64_t addr) const {
+ if(data == nullptr || (addr >> 3) >= size) return 0;
+ unsigned mask = endian == 0 ? (0x01 << (addr & 7)) : (0x80 >> (addr & 7));
+ return data[addr >> 3] & mask;
+ }
+
+ inline void write(uint64_t addr, bool value) {
+ if(data == nullptr || readonly == true || (addr >> 3) >= size) return;
+ unsigned mask = endian == 0 ? (0x01 << (addr & 7)) : (0x80 >> (addr & 7));
+ if(value == 0) data[addr >> 3] &= ~mask;
+ if(value == 1) data[addr >> 3] |= mask;
+ }
+
+ inline bool open(const string &filename) {
+ readonly = false;
+ if(fp.open(filename, filemap::mode::readwrite) == false) {
+ readonly = true;
+ if(fp.open(filename, filemap::mode::read) == false) {
+ return false;
+ }
+ }
+ data = fp.data();
+ size = fp.size();
+ return true;
+ }
+
+ inline void close() {
+ fp.close();
+ data = nullptr;
+ }
+
+ inline bitstream() : data(nullptr), endian(1) {
+ }
+
+ inline ~bitstream() {
+ close();
+ }
+};
+
+}
+}
+
+#endif
diff --git a/kaijuu/nall/mosaic/context.hpp b/kaijuu/nall/mosaic/context.hpp
new file mode 100644
index 00000000..bc7a518a
--- /dev/null
+++ b/kaijuu/nall/mosaic/context.hpp
@@ -0,0 +1,224 @@
+#ifdef NALL_MOSAIC_INTERNAL_HPP
+
+namespace nall {
+namespace mosaic {
+
+struct context {
+ unsigned offset;
+ unsigned width;
+ unsigned height;
+ unsigned count;
+
+ bool endian; //0 = lsb, 1 = msb
+ bool order; //0 = linear, 1 = planar
+ unsigned depth; //1 - 24bpp
+
+ unsigned blockWidth;
+ unsigned blockHeight;
+ unsigned blockStride;
+ unsigned blockOffset;
+ vector block;
+
+ unsigned tileWidth;
+ unsigned tileHeight;
+ unsigned tileStride;
+ unsigned tileOffset;
+ vector tile;
+
+ unsigned mosaicWidth;
+ unsigned mosaicHeight;
+ unsigned mosaicStride;
+ unsigned mosaicOffset;
+ vector mosaic;
+
+ unsigned paddingWidth;
+ unsigned paddingHeight;
+ unsigned paddingColor;
+ vector palette;
+
+ inline unsigned objectWidth() const { return blockWidth * tileWidth * mosaicWidth + paddingWidth; }
+ inline unsigned objectHeight() const { return blockHeight * tileHeight * mosaicHeight + paddingHeight; }
+ inline unsigned objectSize() const {
+ unsigned size = blockStride * tileWidth * tileHeight * mosaicWidth * mosaicHeight
+ + blockOffset * tileHeight * mosaicWidth * mosaicHeight
+ + tileStride * mosaicWidth * mosaicHeight
+ + tileOffset * mosaicHeight;
+ return max(1u, size);
+ }
+
+ inline unsigned eval(const string &expression) {
+ intmax_t result;
+ if(fixedpoint::eval(expression, result) == false) return 0u;
+ return result;
+ }
+
+ inline void eval(vector &buffer, const string &expression_) {
+ string expression = expression_;
+ bool function = false;
+ for(auto &c : expression) {
+ if(c == '(') function = true;
+ if(c == ')') function = false;
+ if(c == ',' && function == true) c = ';';
+ }
+
+ lstring list = expression.split(",");
+ for(auto &item : list) {
+ item.trim();
+ if(item.wildcard("f(?*) ?*")) {
+ item.ltrim<1>("f(");
+ lstring part = item.split<1>(") ");
+ lstring args = part[0].split<3>(";");
+ for(auto &item : args) item.trim();
+
+ unsigned length = eval(args(0, "0"));
+ unsigned offset = eval(args(1, "0"));
+ unsigned stride = eval(args(2, "0"));
+ if(args.size() < 2) offset = buffer.size();
+ if(args.size() < 3) stride = 1;
+
+ for(unsigned n = 0; n < length; n++) {
+ string fn = part[1];
+ fn.replace("n", decimal(n));
+ fn.replace("o", decimal(offset));
+ fn.replace("p", decimal(buffer.size()));
+ buffer.resize(offset + 1);
+ buffer[offset] = eval(fn);
+ offset += stride;
+ }
+ } else if(item.wildcard("base64*")) {
+ unsigned offset = 0;
+ item.ltrim<1>("base64");
+ if(item.wildcard("(?*) *")) {
+ item.ltrim<1>("(");
+ lstring part = item.split<1>(") ");
+ offset = eval(part[0]);
+ item = part(1, "");
+ }
+ item.trim();
+ for(auto &c : item) {
+ if(c >= 'A' && c <= 'Z') buffer.append(offset + c - 'A' + 0);
+ if(c >= 'a' && c <= 'z') buffer.append(offset + c - 'a' + 26);
+ if(c >= '0' && c <= '9') buffer.append(offset + c - '0' + 52);
+ if(c == '-') buffer.append(offset + 62);
+ if(c == '_') buffer.append(offset + 63);
+ }
+ } else if(item.wildcard("file *")) {
+ item.ltrim<1>("file ");
+ item.trim();
+ //...
+ } else if(item.empty() == false) {
+ buffer.append(eval(item));
+ }
+ }
+ }
+
+ inline void parse(const string &data) {
+ reset();
+
+ lstring lines = data.split("\n");
+ for(auto &line : lines) {
+ lstring part = line.split<1>(":");
+ if(part.size() != 2) continue;
+ part[0].trim();
+ part[1].trim();
+
+ if(part[0] == "offset") offset = eval(part[1]);
+ if(part[0] == "width") width = eval(part[1]);
+ if(part[0] == "height") height = eval(part[1]);
+ if(part[0] == "count") count = eval(part[1]);
+
+ if(part[0] == "endian") endian = eval(part[1]);
+ if(part[0] == "order") order = eval(part[1]);
+ if(part[0] == "depth") depth = eval(part[1]);
+
+ if(part[0] == "blockWidth") blockWidth = eval(part[1]);
+ if(part[0] == "blockHeight") blockHeight = eval(part[1]);
+ if(part[0] == "blockStride") blockStride = eval(part[1]);
+ if(part[0] == "blockOffset") blockOffset = eval(part[1]);
+ if(part[0] == "block") eval(block, part[1]);
+
+ if(part[0] == "tileWidth") tileWidth = eval(part[1]);
+ if(part[0] == "tileHeight") tileHeight = eval(part[1]);
+ if(part[0] == "tileStride") tileStride = eval(part[1]);
+ if(part[0] == "tileOffset") tileOffset = eval(part[1]);
+ if(part[0] == "tile") eval(tile, part[1]);
+
+ if(part[0] == "mosaicWidth") mosaicWidth = eval(part[1]);
+ if(part[0] == "mosaicHeight") mosaicHeight = eval(part[1]);
+ if(part[0] == "mosaicStride") mosaicStride = eval(part[1]);
+ if(part[0] == "mosaicOffset") mosaicOffset = eval(part[1]);
+ if(part[0] == "mosaic") eval(mosaic, part[1]);
+
+ if(part[0] == "paddingWidth") paddingWidth = eval(part[1]);
+ if(part[0] == "paddingHeight") paddingHeight = eval(part[1]);
+ if(part[0] == "paddingColor") paddingColor = eval(part[1]);
+ if(part[0] == "palette") eval(palette, part[1]);
+ }
+
+ sanitize();
+ }
+
+ inline bool load(const string &filename) {
+ string filedata;
+ if(filedata.readfile(filename) == false) return false;
+ parse(filedata);
+ return true;
+ }
+
+ inline void sanitize() {
+ if(depth < 1) depth = 1;
+ if(depth > 24) depth = 24;
+
+ if(blockWidth < 1) blockWidth = 1;
+ if(blockHeight < 1) blockHeight = 1;
+
+ if(tileWidth < 1) tileWidth = 1;
+ if(tileHeight < 1) tileHeight = 1;
+
+ if(mosaicWidth < 1) mosaicWidth = 1;
+ if(mosaicHeight < 1) mosaicHeight = 1;
+ }
+
+ inline void reset() {
+ offset = 0;
+ width = 0;
+ height = 0;
+ count = 0;
+
+ endian = 1;
+ order = 0;
+ depth = 1;
+
+ blockWidth = 1;
+ blockHeight = 1;
+ blockStride = 0;
+ blockOffset = 0;
+ block.reset();
+
+ tileWidth = 1;
+ tileHeight = 1;
+ tileStride = 0;
+ tileOffset = 0;
+ tile.reset();
+
+ mosaicWidth = 1;
+ mosaicHeight = 1;
+ mosaicStride = 0;
+ mosaicOffset = 0;
+ mosaic.reset();
+
+ paddingWidth = 0;
+ paddingHeight = 0;
+ paddingColor = 0x000000;
+ palette.reset();
+ }
+
+ inline context() {
+ reset();
+ }
+};
+
+}
+}
+
+#endif
diff --git a/kaijuu/nall/mosaic/parser.hpp b/kaijuu/nall/mosaic/parser.hpp
new file mode 100644
index 00000000..b2c0b8ef
--- /dev/null
+++ b/kaijuu/nall/mosaic/parser.hpp
@@ -0,0 +1,126 @@
+#ifdef NALL_MOSAIC_INTERNAL_HPP
+
+namespace nall {
+namespace mosaic {
+
+struct parser {
+ image canvas;
+
+ //export from bitstream to canvas
+ inline void load(bitstream &stream, uint64_t offset, context &ctx, unsigned width, unsigned height) {
+ canvas.allocate(width, height);
+ canvas.clear(ctx.paddingColor);
+ parse(1, stream, offset, ctx, width, height);
+ }
+
+ //import from canvas to bitstream
+ inline bool save(bitstream &stream, uint64_t offset, context &ctx) {
+ if(stream.readonly) return false;
+ parse(0, stream, offset, ctx, canvas.width, canvas.height);
+ return true;
+ }
+
+ inline parser() : canvas(0, 32, 0u, 255u << 16, 255u << 8, 255u << 0) {
+ }
+
+private:
+ inline uint32_t read(unsigned x, unsigned y) const {
+ unsigned addr = y * canvas.width + x;
+ if(addr >= canvas.width * canvas.height) return 0u;
+ uint32_t *buffer = (uint32_t*)canvas.data;
+ return buffer[addr];
+ }
+
+ inline void write(unsigned x, unsigned y, uint32_t data) {
+ unsigned addr = y * canvas.width + x;
+ if(addr >= canvas.width * canvas.height) return;
+ uint32_t *buffer = (uint32_t*)canvas.data;
+ buffer[addr] = data;
+ }
+
+ inline void parse(bool load, bitstream &stream, uint64_t offset, context &ctx, unsigned width, unsigned height) {
+ stream.endian = ctx.endian;
+ unsigned canvasWidth = width / (ctx.mosaicWidth * ctx.tileWidth * ctx.blockWidth + ctx.paddingWidth);
+ unsigned canvasHeight = height / (ctx.mosaicHeight * ctx.tileHeight * ctx.blockHeight + ctx.paddingHeight);
+ unsigned bitsPerBlock = ctx.depth * ctx.blockWidth * ctx.blockHeight;
+
+ unsigned objectOffset = 0;
+ for(unsigned objectY = 0; objectY < canvasHeight; objectY++) {
+ for(unsigned objectX = 0; objectX < canvasWidth; objectX++) {
+ if(objectOffset >= ctx.count && ctx.count > 0) break;
+ unsigned objectIX = objectX * ctx.objectWidth();
+ unsigned objectIY = objectY * ctx.objectHeight();
+ objectOffset++;
+
+ unsigned mosaicOffset = 0;
+ for(unsigned mosaicY = 0; mosaicY < ctx.mosaicHeight; mosaicY++) {
+ for(unsigned mosaicX = 0; mosaicX < ctx.mosaicWidth; mosaicX++) {
+ unsigned mosaicData = ctx.mosaic(mosaicOffset, mosaicOffset);
+ unsigned mosaicIX = (mosaicData % ctx.mosaicWidth) * (ctx.tileWidth * ctx.blockWidth);
+ unsigned mosaicIY = (mosaicData / ctx.mosaicWidth) * (ctx.tileHeight * ctx.blockHeight);
+ mosaicOffset++;
+
+ unsigned tileOffset = 0;
+ for(unsigned tileY = 0; tileY < ctx.tileHeight; tileY++) {
+ for(unsigned tileX = 0; tileX < ctx.tileWidth; tileX++) {
+ unsigned tileData = ctx.tile(tileOffset, tileOffset);
+ unsigned tileIX = (tileData % ctx.tileWidth) * ctx.blockWidth;
+ unsigned tileIY = (tileData / ctx.tileWidth) * ctx.blockHeight;
+ tileOffset++;
+
+ unsigned blockOffset = 0;
+ for(unsigned blockY = 0; blockY < ctx.blockHeight; blockY++) {
+ for(unsigned blockX = 0; blockX < ctx.blockWidth; blockX++) {
+ if(load) {
+ unsigned palette = 0;
+ for(unsigned n = 0; n < ctx.depth; n++) {
+ unsigned index = blockOffset++;
+ if(ctx.order == 1) index = (index % ctx.depth) * ctx.blockWidth * ctx.blockHeight + (index / ctx.depth);
+ palette |= stream.read(offset + ctx.block(index, index)) << n;
+ }
+
+ write(
+ objectIX + mosaicIX + tileIX + blockX,
+ objectIY + mosaicIY + tileIY + blockY,
+ ctx.palette(palette, palette)
+ );
+ } else /* save */ {
+ uint32_t palette = read(
+ objectIX + mosaicIX + tileIX + blockX,
+ objectIY + mosaicIY + tileIY + blockY
+ );
+
+ for(unsigned n = 0; n < ctx.depth; n++) {
+ unsigned index = blockOffset++;
+ if(ctx.order == 1) index = (index % ctx.depth) * ctx.blockWidth * ctx.blockHeight + (index / ctx.depth);
+ stream.write(offset + ctx.block(index, index), palette & 1);
+ palette >>= 1;
+ }
+ }
+ } //blockX
+ } //blockY
+
+ offset += ctx.blockStride;
+ } //tileX
+
+ offset += ctx.blockOffset;
+ } //tileY
+
+ offset += ctx.tileStride;
+ } //mosaicX
+
+ offset += ctx.tileOffset;
+ } //mosaicY
+
+ offset += ctx.mosaicStride;
+ } //objectX
+
+ offset += ctx.mosaicOffset;
+ } //objectY
+ }
+};
+
+}
+}
+
+#endif
diff --git a/kaijuu/nall/nall.hpp b/kaijuu/nall/nall.hpp
new file mode 100644
index 00000000..9a8f1dfa
--- /dev/null
+++ b/kaijuu/nall/nall.hpp
@@ -0,0 +1,56 @@
+#ifndef NALL_HPP
+#define NALL_HPP
+
+//include the most common nall headers with one statement
+//does not include the most obscure components with high cost and low usage
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#if defined(PLATFORM_WINDOWS)
+ #include
+ #include
+#endif
+
+#if defined(PLATFORM_X)
+ #include
+#endif
+
+#endif
diff --git a/kaijuu/nall/platform.hpp b/kaijuu/nall/platform.hpp
new file mode 100644
index 00000000..a45a6723
--- /dev/null
+++ b/kaijuu/nall/platform.hpp
@@ -0,0 +1,86 @@
+#ifndef NALL_PLATFORM_HPP
+#define NALL_PLATFORM_HPP
+
+#if defined(_WIN32)
+ //minimum version needed for _wstat64, etc
+ #undef __MSVCRT_VERSION__
+ #define __MSVCRT_VERSION__ 0x0601
+ #include
+#endif
+
+//=========================
+//standard platform headers
+//=========================
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#if defined(_WIN32)
+ #include
+ #include
+ #include
+ #include
+ #undef interface
+ #define dllexport __declspec(dllexport)
+#else
+ #include
+ #include
+ #define dllexport
+#endif
+
+//==================
+//warning supression
+//==================
+
+//Visual C++
+#if defined(_MSC_VER)
+ //disable libc "deprecation" warnings
+ #pragma warning(disable:4996)
+#endif
+
+//================
+//POSIX compliance
+//================
+
+#if defined(_MSC_VER)
+ #define PATH_MAX _MAX_PATH
+ #define va_copy(dest, src) ((dest) = (src))
+#endif
+
+#if defined(_WIN32)
+ #define getcwd _getcwd
+ #define putenv _putenv
+ #define vsnprintf _vsnprintf
+ inline void usleep(unsigned milliseconds) { Sleep(milliseconds / 1000); }
+#endif
+
+//================
+//inline expansion
+//================
+
+#if defined(__GNUC__)
+ #define noinline __attribute__((noinline))
+ #define inline inline
+ #define alwaysinline inline __attribute__((always_inline))
+#elif defined(_MSC_VER)
+ #define noinline __declspec(noinline)
+ #define inline inline
+ #define alwaysinline inline __forceinline
+#else
+ #define noinline
+ #define inline inline
+ #define alwaysinline inline
+#endif
+
+#endif
diff --git a/snesfilter/nall/png.hpp b/kaijuu/nall/png.hpp
old mode 100755
new mode 100644
similarity index 98%
rename from snesfilter/nall/png.hpp
rename to kaijuu/nall/png.hpp
index 4b474724..f5ebaab4
--- a/snesfilter/nall/png.hpp
+++ b/kaijuu/nall/png.hpp
@@ -58,12 +58,10 @@ protected:
};
bool png::decode(const string &filename) {
- uint8_t *data;
- unsigned size;
- if(file::read(filename, data, size) == false) return false;
- bool result = decode(data, size);
- delete[] data;
- return result;
+ if(auto memory = file::read(filename)) {
+ return decode(memory.data(), memory.size());
+ }
+ return false;
}
bool png::decode(const uint8_t *sourceData, unsigned sourceSize) {
diff --git a/snesfilter/nall/priorityqueue.hpp b/kaijuu/nall/priority-queue.hpp
old mode 100755
new mode 100644
similarity index 97%
rename from snesfilter/nall/priorityqueue.hpp
rename to kaijuu/nall/priority-queue.hpp
index 443eac21..1aedc6f1
--- a/snesfilter/nall/priorityqueue.hpp
+++ b/kaijuu/nall/priority-queue.hpp
@@ -1,5 +1,5 @@
-#ifndef NALL_PRIORITYQUEUE_HPP
-#define NALL_PRIORITYQUEUE_HPP
+#ifndef NALL_PRIORITY_QUEUE_HPP
+#define NALL_PRIORITY_QUEUE_HPP
#include
#include
diff --git a/snesfilter/nall/property.hpp b/kaijuu/nall/property.hpp
old mode 100755
new mode 100644
similarity index 100%
rename from snesfilter/nall/property.hpp
rename to kaijuu/nall/property.hpp
diff --git a/snesfilter/nall/public_cast.hpp b/kaijuu/nall/public-cast.hpp
old mode 100755
new mode 100644
similarity index 100%
rename from snesfilter/nall/public_cast.hpp
rename to kaijuu/nall/public-cast.hpp
diff --git a/snesfilter/nall/random.hpp b/kaijuu/nall/random.hpp
old mode 100755
new mode 100644
similarity index 100%
rename from snesfilter/nall/random.hpp
rename to kaijuu/nall/random.hpp
diff --git a/snesfilter/nall/serial.hpp b/kaijuu/nall/serial.hpp
old mode 100755
new mode 100644
similarity index 73%
rename from snesfilter/nall/serial.hpp
rename to kaijuu/nall/serial.hpp
index 9ac8451a..da87ae50
--- a/snesfilter/nall/serial.hpp
+++ b/kaijuu/nall/serial.hpp
@@ -9,14 +9,39 @@
#include
namespace nall {
- class serial {
- public:
+ struct serial {
+ bool readable() {
+ if(port_open == false) return false;
+ fd_set fdset;
+ FD_ZERO(&fdset);
+ FD_SET(port, &fdset);
+ timeval timeout;
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 0;
+ int result = select(FD_SETSIZE, &fdset, nullptr, nullptr, &timeout);
+ if(result < 1) return false;
+ return FD_ISSET(port, &fdset);
+ }
+
//-1 on error, otherwise return bytes read
int read(uint8_t *data, unsigned length) {
if(port_open == false) return -1;
return ::read(port, (void*)data, length);
}
+ bool writable() {
+ if(port_open == false) return false;
+ fd_set fdset;
+ FD_ZERO(&fdset);
+ FD_SET(port, &fdset);
+ timeval timeout;
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 0;
+ int result = select(FD_SETSIZE, nullptr, &fdset, nullptr, &timeout);
+ if(result < 1) return false;
+ return FD_ISSET(port, &fdset);
+ }
+
//-1 on error, otherwise return bytes written
int write(const uint8_t *data, unsigned length) {
if(port_open == false) return -1;
diff --git a/snesfilter/nall/serializer.hpp b/kaijuu/nall/serializer.hpp
old mode 100755
new mode 100644
similarity index 94%
rename from snesfilter/nall/serializer.hpp
rename to kaijuu/nall/serializer.hpp
index ff2337ab..fcb39456
--- a/snesfilter/nall/serializer.hpp
+++ b/kaijuu/nall/serializer.hpp
@@ -55,10 +55,10 @@ namespace nall {
template void integer(T &value) {
enum { size = std::is_same::value ? 1 : sizeof(T) };
if(imode == Save) {
- for(unsigned n = 0; n < size; n++) idata[isize++] = value >> (n << 3);
+ for(unsigned n = 0; n < size; n++) idata[isize++] = (uintmax_t)value >> (n << 3);
} else if(imode == Load) {
value = 0;
- for(unsigned n = 0; n < size; n++) value |= idata[isize++] << (n << 3);
+ for(unsigned n = 0; n < size; n++) value |= (uintmax_t)idata[isize++] << (n << 3);
} else if(imode == Size) {
isize += size;
}
diff --git a/kaijuu/nall/set.hpp b/kaijuu/nall/set.hpp
new file mode 100644
index 00000000..c6d3d06e
--- /dev/null
+++ b/kaijuu/nall/set.hpp
@@ -0,0 +1,158 @@
+#ifndef NALL_SET_HPP
+#define NALL_SET_HPP
+
+//set
+//* unordered
+//* intended for unique items
+//* dynamic growth
+//* reference-based variant
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace nall {
+
+template struct set;
+
+template struct set::value>::type> {
+ struct exception_out_of_bounds{};
+
+protected:
+ T *pool;
+ unsigned poolsize, objectsize;
+
+public:
+ unsigned size() const { return objectsize; }
+ unsigned capacity() const { return poolsize; }
+};
+
+//reference set
+template struct set::value>::type> {
+ struct exception_out_of_bounds{};
+
+protected:
+ typedef typename std::remove_reference
::type T;
+ T **pool;
+ unsigned poolsize, objectsize;
+
+public:
+ unsigned size() const { return objectsize; }
+ unsigned capacity() const { return poolsize; }
+
+ void reset() {
+ if(pool) free(pool);
+ pool = nullptr;
+ poolsize = 0;
+ objectsize = 0;
+ }
+
+ void reserve(unsigned size) {
+ if(size == poolsize) return;
+ pool = (T**)realloc(pool, sizeof(T*) * size);
+ poolsize = size;
+ objectsize = min(objectsize, size);
+ }
+
+ void resize(unsigned size) {
+ if(size > poolsize) reserve(bit::round(size)); //amortize growth
+ objectsize = size;
+ }
+
+ bool append(T& data) {
+ if(find(data)) return false;
+ unsigned offset = objectsize++;
+ if(offset >= poolsize) resize(offset + 1);
+ pool[offset] = &data;
+ return true;
+ }
+
+ template
+ bool append(T& data, Args&&... args) {
+ bool result = append(data);
+ append(std::forward(args)...);
+ return result;
+ }
+
+ bool remove(T& data) {
+ if(auto position = find(data)) {
+ for(signed i = position(); i < objectsize - 1; i++) pool[i] = pool[i + 1];
+ resize(objectsize - 1);
+ return true;
+ }
+ return false;
+ }
+
+ optional find(const T& data) {
+ for(unsigned n = 0; n < objectsize; n++) if(pool[n] == &data) return {true, n};
+ return {false, 0u};
+ }
+
+ template set(Args&&... args) : pool(nullptr), poolsize(0), objectsize(0) {
+ construct(std::forward(args)...);
+ }
+
+ ~set() {
+ reset();
+ }
+
+ set& operator=(const set &source) {
+ if(&source == this) return *this;
+ if(pool) free(pool);
+ objectsize = source.objectsize;
+ poolsize = source.poolsize;
+ pool = (T**)malloc(sizeof(T*) * poolsize);
+ memcpy(pool, source.pool, sizeof(T*) * objectsize);
+ return *this;
+ }
+
+ set& operator=(const set &&source) {
+ if(&source == this) return *this;
+ if(pool) free(pool);
+ pool = source.pool;
+ poolsize = source.poolsize;
+ objectsize = source.objectsize;
+ source.pool = nullptr;
+ source.reset();
+ return *this;
+ }
+
+ T& operator[](unsigned position) const {
+ if(position >= objectsize) throw exception_out_of_bounds();
+ return *pool[position];
+ }
+
+ struct iterator {
+ bool operator!=(const iterator &source) const { return position != source.position; }
+ T& operator*() { return source.operator[](position); }
+ iterator& operator++() { position++; return *this; }
+ iterator(const set &source, unsigned position) : source(source), position(position) {}
+ private:
+ const set &source;
+ unsigned position;
+ };
+
+ iterator begin() { return iterator(*this, 0); }
+ iterator end() { return iterator(*this, objectsize); }
+ const iterator begin() const { return iterator(*this, 0); }
+ const iterator end() const { return iterator(*this, objectsize); }
+
+private:
+ void construct() {}
+ void construct(const set &source) { operator=(source); }
+ void construct(const set &&source) { operator=(std::move(source)); }
+ template void construct(T& data, Args&&... args) {
+ append(data);
+ construct(std::forward(args)...);
+ }
+};
+
+}
+
+#endif
diff --git a/snesfilter/nall/sha256.hpp b/kaijuu/nall/sha256.hpp
old mode 100755
new mode 100644
similarity index 100%
rename from snesfilter/nall/sha256.hpp
rename to kaijuu/nall/sha256.hpp
diff --git a/kaijuu/nall/sort.hpp b/kaijuu/nall/sort.hpp
new file mode 100644
index 00000000..36d91865
--- /dev/null
+++ b/kaijuu/nall/sort.hpp
@@ -0,0 +1,77 @@
+#ifndef NALL_SORT_HPP
+#define NALL_SORT_HPP
+
+#include
+#include
+
+//class: merge sort
+//average: O(n log n)
+//worst: O(n log n)
+//memory: O(n)
+//stack: O(log n)
+//stable?: yes
+
+//note: merge sort was chosen over quick sort, because:
+//* it is a stable sort
+//* it lacks O(n^2) worst-case overhead
+
+#define NALL_SORT_INSERTION
+//#define NALL_SORT_SELECTION
+
+namespace nall {
+ template
+ void sort(T list[], unsigned size, const Comparator &lessthan) {
+ if(size <= 1) return; //nothing to sort
+
+ //use insertion sort to quickly sort smaller blocks
+ if(size < 64) {
+ #if defined(NALL_SORT_INSERTION)
+ for(signed i = 1, j; i < size; i++) {
+ T copy = std::move(list[i]);
+ for(j = i - 1; j >= 0; j--) {
+ if(lessthan(list[j], copy)) break;
+ list[j + 1] = std::move(list[j]);
+ }
+ list[j + 1] = std::move(copy);
+ }
+ #elif defined(NALL_SORT_SELECTION)
+ for(unsigned i = 0; i < size; i++) {
+ unsigned min = i;
+ for(unsigned j = i + 1; j < size; j++) {
+ if(lessthan(list[j], list[min])) min = j;
+ }
+ if(min != i) std::swap(list[i], list[min]);
+ }
+ #endif
+ return;
+ }
+
+ //split list in half and recursively sort both
+ unsigned middle = size / 2;
+ sort(list, middle, lessthan);
+ sort(list + middle, size - middle, lessthan);
+
+ //left and right are sorted here; perform merge sort
+ T *buffer = new T[size];
+ unsigned offset = 0, left = 0, right = middle;
+ while(left < middle && right < size) {
+ if(lessthan(list[left], list[right])) {
+ buffer[offset++] = std::move(list[left++]);
+ } else {
+ buffer[offset++] = std::move(list[right++]);
+ }
+ }
+ while(left < middle) buffer[offset++] = std::move(list[left++]);
+ while(right < size) buffer[offset++] = std::move(list[right++]);
+
+ for(unsigned i = 0; i < size; i++) list[i] = std::move(buffer[i]);
+ delete[] buffer;
+ }
+
+ template
+ void sort(T list[], unsigned size) {
+ return sort(list, size, [](const T &l, const T &r) { return l < r; });
+ }
+}
+
+#endif
diff --git a/snesfilter/nall/stdint.hpp b/kaijuu/nall/stdint.hpp
old mode 100755
new mode 100644
similarity index 97%
rename from snesfilter/nall/stdint.hpp
rename to kaijuu/nall/stdint.hpp
index d8b6c788..c63f5912
--- a/snesfilter/nall/stdint.hpp
+++ b/kaijuu/nall/stdint.hpp
@@ -1,8 +1,6 @@
#ifndef NALL_STDINT_HPP
#define NALL_STDINT_HPP
-#include
-
#if defined(_MSC_VER)
typedef signed char int8_t;
typedef signed short int16_t;
diff --git a/kaijuu/nall/stream.hpp b/kaijuu/nall/stream.hpp
new file mode 100644
index 00000000..586ccda7
--- /dev/null
+++ b/kaijuu/nall/stream.hpp
@@ -0,0 +1,26 @@
+#ifndef NALL_STREAM_HPP
+#define NALL_STREAM_HPP
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define NALL_STREAM_INTERNAL_HPP
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#undef NALL_STREAM_INTERNAL_HPP
+
+#endif
diff --git a/kaijuu/nall/stream/auto.hpp b/kaijuu/nall/stream/auto.hpp
new file mode 100644
index 00000000..d1b6e2ba
--- /dev/null
+++ b/kaijuu/nall/stream/auto.hpp
@@ -0,0 +1,25 @@
+#ifndef NALL_STREAM_AUTO_HPP
+#define NALL_STREAM_AUTO_HPP
+
+namespace nall {
+
+#define autostream(...) (*makestream(__VA_ARGS__))
+
+inline std::unique_ptr makestream(const string &path) {
+ if(path.ibeginswith("http://")) return std::unique_ptr(new httpstream(path, 80));
+ if(path.iendswith(".gz")) return std::unique_ptr(new gzipstream(filestream{path}));
+ if(path.iendswith(".zip")) return std::unique_ptr(new zipstream(filestream{path}));
+ return std::unique_ptr(new mmapstream(path));
+}
+
+inline std::unique_ptr makestream(uint8_t *data, unsigned size) {
+ return std::unique_ptr(new memorystream(data, size));
+}
+
+inline std::unique_ptr makestream(const uint8_t *data, unsigned size) {
+ return std::unique_ptr(new memorystream(data, size));
+}
+
+}
+
+#endif
diff --git a/kaijuu/nall/stream/file.hpp b/kaijuu/nall/stream/file.hpp
new file mode 100644
index 00000000..878418cf
--- /dev/null
+++ b/kaijuu/nall/stream/file.hpp
@@ -0,0 +1,42 @@
+#ifndef NALL_STREAM_FILE_HPP
+#define NALL_STREAM_FILE_HPP
+
+#include
+
+namespace nall {
+
+struct filestream : stream {
+ using stream::read;
+ using stream::write;
+
+ bool seekable() const { return true; }
+ bool readable() const { return true; }
+ bool writable() const { return pwritable; }
+ bool randomaccess() const { return false; }
+
+ unsigned size() const { return pfile.size(); }
+ unsigned offset() const { return pfile.offset(); }
+ void seek(unsigned offset) const { pfile.seek(offset); }
+
+ uint8_t read() const { return pfile.read(); }
+ void write(uint8_t data) const { pfile.write(data); }
+
+ filestream(const string &filename) {
+ pfile.open(filename, file::mode::readwrite);
+ pwritable = pfile.open();
+ if(!pwritable) pfile.open(filename, file::mode::read);
+ }
+
+ filestream(const string &filename, file::mode mode) {
+ pfile.open(filename, mode);
+ pwritable = mode == file::mode::write || mode == file::mode::readwrite;
+ }
+
+private:
+ mutable file pfile;
+ bool pwritable;
+};
+
+}
+
+#endif
diff --git a/kaijuu/nall/stream/gzip.hpp b/kaijuu/nall/stream/gzip.hpp
new file mode 100644
index 00000000..0c270a72
--- /dev/null
+++ b/kaijuu/nall/stream/gzip.hpp
@@ -0,0 +1,34 @@
+#ifndef NALL_STREAM_GZIP_HPP
+#define NALL_STREAM_GZIP_HPP
+
+#include
+
+namespace nall {
+
+struct gzipstream : memorystream {
+ using stream::read;
+ using stream::write;
+
+ gzipstream(const stream &stream) {
+ unsigned size = stream.size();
+ uint8_t *data = new uint8_t[size];
+ stream.read(data, size);
+
+ gzip archive;
+ bool result = archive.decompress(data, size);
+ delete[] data;
+ if(result == false) return;
+
+ psize = archive.size;
+ pdata = new uint8_t[psize];
+ memcpy(pdata, archive.data, psize);
+ }
+
+ ~gzipstream() {
+ if(pdata) delete[] pdata;
+ }
+};
+
+}
+
+#endif
diff --git a/kaijuu/nall/stream/http.hpp b/kaijuu/nall/stream/http.hpp
new file mode 100644
index 00000000..2f9e45dd
--- /dev/null
+++ b/kaijuu/nall/stream/http.hpp
@@ -0,0 +1,49 @@
+#ifndef NALL_STREAM_HTTP_HPP
+#define NALL_STREAM_HTTP_HPP
+
+#include
+
+namespace nall {
+
+struct httpstream : stream {
+ using stream::read;
+ using stream::write;
+
+ bool seekable() const { return true; }
+ bool readable() const { return true; }
+ bool writable() const { return true; }
+ bool randomaccess() const { return true; }
+
+ unsigned size() const { return psize; }
+ unsigned offset() const { return poffset; }
+ void seek(unsigned offset) const { poffset = offset; }
+
+ uint8_t read() const { return pdata[poffset++]; }
+ void write(uint8_t data) const { pdata[poffset++] = data; }
+
+ uint8_t read(unsigned offset) const { return pdata[offset]; }
+ void write(unsigned offset, uint8_t data) const { pdata[offset] = data; }
+
+ httpstream(const string &url, unsigned port) : pdata(nullptr), psize(0), poffset(0) {
+ string uri = url;
+ uri.ltrim<1>("http://");
+ lstring part = uri.split<1>("/");
+ part[1] = { "/", part[1] };
+
+ http connection;
+ if(connection.connect(part[0], port) == false) return;
+ connection.download(part[1], pdata, psize);
+ }
+
+ ~httpstream() {
+ if(pdata) delete[] pdata;
+ }
+
+private:
+ mutable uint8_t *pdata;
+ mutable unsigned psize, poffset;
+};
+
+}
+
+#endif
diff --git a/kaijuu/nall/stream/memory.hpp b/kaijuu/nall/stream/memory.hpp
new file mode 100644
index 00000000..cf49b3b2
--- /dev/null
+++ b/kaijuu/nall/stream/memory.hpp
@@ -0,0 +1,47 @@
+#ifndef NALL_STREAM_MEMORY_HPP
+#define NALL_STREAM_MEMORY_HPP
+
+#include
+
+namespace nall {
+
+struct memorystream : stream {
+ using stream::read;
+ using stream::write;
+
+ bool seekable() const { return true; }
+ bool readable() const { return true; }
+ bool writable() const { return pwritable; }
+ bool randomaccess() const { return true; }
+
+ uint8_t *data() const { return pdata; }
+ unsigned size() const { return psize; }
+ unsigned offset() const { return poffset; }
+ void seek(unsigned offset) const { poffset = offset; }
+
+ uint8_t read() const { return pdata[poffset++]; }
+ void write(uint8_t data) const { pdata[poffset++] = data; }
+
+ uint8_t read(unsigned offset) const { return pdata[offset]; }
+ void write(unsigned offset, uint8_t data) const { pdata[offset] = data; }
+
+ memorystream() : pdata(nullptr), psize(0), poffset(0), pwritable(true) {}
+
+ memorystream(uint8_t *data, unsigned size) {
+ pdata = data, psize = size, poffset = 0;
+ pwritable = true;
+ }
+
+ memorystream(const uint8_t *data, unsigned size) {
+ pdata = (uint8_t*)data, psize = size, poffset = 0;
+ pwritable = false;
+ }
+
+protected:
+ mutable uint8_t *pdata;
+ mutable unsigned psize, poffset, pwritable;
+};
+
+}
+
+#endif
diff --git a/kaijuu/nall/stream/mmap.hpp b/kaijuu/nall/stream/mmap.hpp
new file mode 100644
index 00000000..ce30f810
--- /dev/null
+++ b/kaijuu/nall/stream/mmap.hpp
@@ -0,0 +1,42 @@
+#ifndef NALL_STREAM_MMAP_HPP
+#define NALL_STREAM_MMAP_HPP
+
+#include
+
+namespace nall {
+
+struct mmapstream : stream {
+ using stream::read;
+ using stream::write;
+
+ bool seekable() const { return true; }
+ bool readable() const { return true; }
+ bool writable() const { return pwritable; }
+ bool randomaccess() const { return true; }
+
+ unsigned size() const { return pmmap.size(); }
+ unsigned offset() const { return poffset; }
+ void seek(unsigned offset) const { poffset = offset; }
+
+ uint8_t read() const { return pdata[poffset++]; }
+ void write(uint8_t data) const { pdata[poffset++] = data; }
+
+ uint8_t read(unsigned offset) const { return pdata[offset]; }
+ void write(unsigned offset, uint8_t data) const { pdata[offset] = data; }
+
+ mmapstream(const string &filename) {
+ pmmap.open(filename, filemap::mode::readwrite);
+ pwritable = pmmap.open();
+ if(!pwritable) pmmap.open(filename, filemap::mode::read);
+ pdata = pmmap.data(), poffset = 0;
+ }
+
+private:
+ mutable filemap pmmap;
+ mutable uint8_t *pdata;
+ mutable unsigned pwritable, poffset;
+};
+
+}
+
+#endif
diff --git a/kaijuu/nall/stream/stream.hpp b/kaijuu/nall/stream/stream.hpp
new file mode 100644
index 00000000..9d937729
--- /dev/null
+++ b/kaijuu/nall/stream/stream.hpp
@@ -0,0 +1,92 @@
+#ifndef NALL_STREAM_STREAM_HPP
+#define NALL_STREAM_STREAM_HPP
+
+namespace nall {
+
+struct stream {
+ virtual bool seekable() const = 0;
+ virtual bool readable() const = 0;
+ virtual bool writable() const = 0;
+ virtual bool randomaccess() const = 0;
+
+ virtual uint8_t* data() const { return nullptr; }
+ virtual unsigned size() const = 0;
+ virtual unsigned offset() const = 0;
+ virtual void seek(unsigned offset) const = 0;
+
+ virtual uint8_t read() const = 0;
+ virtual void write(uint8_t data) const = 0;
+
+ virtual uint8_t read(unsigned) const { return 0; }
+ virtual void write(unsigned, uint8_t) const {}
+
+ operator bool() const {
+ return size();
+ }
+
+ bool empty() const {
+ return size() == 0;
+ }
+
+ bool end() const {
+ return offset() >= size();
+ }
+
+ uintmax_t readl(unsigned length = 1) const {
+ uintmax_t data = 0, shift = 0;
+ while(length--) { data |= read() << shift; shift += 8; }
+ return data;
+ }
+
+ uintmax_t readm(unsigned length = 1) const {
+ uintmax_t data = 0;
+ while(length--) data = (data << 8) | read();
+ return data;
+ }
+
+ void read(uint8_t *data, unsigned length) const {
+ while(length--) *data++ = read();
+ }
+
+ void writel(uintmax_t data, unsigned length = 1) const {
+ while(length--) {
+ write(data);
+ data >>= 8;
+ }
+ }
+
+ void writem(uintmax_t data, unsigned length = 1) const {
+ uintmax_t shift = 8 * length;
+ while(length--) {
+ shift -= 8;
+ write(data >> shift);
+ }
+ }
+
+ void write(const uint8_t *data, unsigned length) const {
+ while(length--) write(*data++);
+ }
+
+ struct byte {
+ operator uint8_t() const { return s.read(offset); }
+ byte& operator=(uint8_t data) { s.write(offset, data); return *this; }
+ byte(const stream &s, unsigned offset) : s(s), offset(offset) {}
+
+ private:
+ const stream &s;
+ const unsigned offset;
+ };
+
+ byte operator[](unsigned offset) const {
+ return byte(*this, offset);
+ }
+
+ stream() {}
+ virtual ~stream() {}
+ stream(const stream&) = delete;
+ stream& operator=(const stream&) = delete;
+};
+
+}
+
+#endif
diff --git a/kaijuu/nall/stream/vector.hpp b/kaijuu/nall/stream/vector.hpp
new file mode 100644
index 00000000..59f36c02
--- /dev/null
+++ b/kaijuu/nall/stream/vector.hpp
@@ -0,0 +1,39 @@
+#ifndef NALL_STREAM_VECTOR_HPP
+#define NALL_STREAM_VECTOR_HPP
+
+#include
+#include
+
+namespace nall {
+
+struct vectorstream : stream {
+ using stream::read;
+ using stream::write;
+
+ bool seekable() const { return true; }
+ bool readable() const { return true; }
+ bool writable() const { return pwritable; }
+ bool randomaccess() const { return true; }
+
+ uint8_t* data() const { return memory.data(); }
+ unsigned size() const { return memory.size(); }
+ unsigned offset() const { return poffset; }
+ void seek(unsigned offset) const { poffset = offset; }
+
+ uint8_t read() const { return memory[poffset++]; }
+ void write(uint8_t data) const { memory[poffset++] = data; }
+
+ uint8_t read(unsigned offset) const { return memory[offset]; }
+ void write(unsigned offset, uint8_t data) const { memory[offset] = data; }
+
+ vectorstream(vector &memory) : memory(memory), poffset(0), pwritable(true) {}
+ vectorstream(const vector &memory) : memory((vector&)memory), poffset(0), pwritable(false) {}
+
+protected:
+ vector &memory;
+ mutable unsigned poffset, pwritable;
+};
+
+}
+
+#endif
diff --git a/kaijuu/nall/stream/zip.hpp b/kaijuu/nall/stream/zip.hpp
new file mode 100644
index 00000000..975cdeff
--- /dev/null
+++ b/kaijuu/nall/stream/zip.hpp
@@ -0,0 +1,38 @@
+#ifndef NALL_STREAM_ZIP_HPP
+#define NALL_STREAM_ZIP_HPP
+
+#include
+
+namespace nall {
+
+struct zipstream : memorystream {
+ using stream::read;
+ using stream::write;
+
+ zipstream(const stream &stream, const string &filter = "*") {
+ unsigned size = stream.size();
+ uint8_t *data = new uint8_t[size];
+ stream.read(data, size);
+
+ zip archive;
+ if(archive.open(data, size) == false) return;
+ delete[] data;
+
+ for(auto &file : archive.file) {
+ if(file.name.wildcard(filter)) {
+ auto buffer = archive.extract(file);
+ psize = buffer.size();
+ pdata = buffer.move();
+ return;
+ }
+ }
+ }
+
+ ~zipstream() {
+ if(pdata) delete[] pdata;
+ }
+};
+
+}
+
+#endif
diff --git a/snesfilter/nall/string.hpp b/kaijuu/nall/string.hpp
old mode 100755
new mode 100644
similarity index 92%
rename from snesfilter/nall/string.hpp
rename to kaijuu/nall/string.hpp
index 288424bc..8c4f6b2c
--- a/snesfilter/nall/string.hpp
+++ b/kaijuu/nall/string.hpp
@@ -9,7 +9,6 @@
#include
#include
-#include
#include
#include
#include
@@ -25,21 +24,22 @@
#include
#include
#include
-#include
#include
#include
#include
+#include
#include
#include