Compare commits

...

47 Commits
v087 ... v089

Author SHA1 Message Date
Tim Allen
73ebe093b8 Update to v089 release.
byuu says:

Changelog to v089:
- fix SA-1 Mini Yonku Shining Scorpion
- load from command-line
- remove SNES::Cartridge::NVRAM
- fix SGB save RAM
- update cheats.xml
- already mapped inputs cancel input assign

BS-X wasn't broken after all. I forgot that I ran purify on my BS-X
images, and that the BS Zelda ZIP I have has the disable ROM bit set.
Whoops.
2012-05-12 12:34:35 +10:00
Tim Allen
c3f9d421da Update to v088r16 release.
byuu says:

Changelog:
- fixed BGnxOFS to not cache when MOSAIC is not in effect [fixes Air
  Strike Patrol "Good Luck" text]
- added GameBoy::Interface::Hook for SGB bindings [SGB works again]
- do not create bsnes/ folder unless it is absolutely needed (eg you
  create a save state or state manager archive)
- SuperFX works [needed to call system.init() in Interface::Interface()]

Last chance for any bug reports, at this point I pretty much consider
ethos to be finished. It's shipping without BS-X BIOS game loading
support. Sorry, I can't figure that one out.
2012-05-10 09:35:29 +10:00
Tim Allen
689fc49047 Update to v088r15 release.
byuu says:

Changelog:
- default placement of presentation window optimized for 1024x768
  displays or larger (sorry if yours is smaller, move the window
  yourself.)
- Direct3D waits until a previous Vblank ends before waiting for the
  next Vblank to begin (fixes video timing analysis, and ---really---
  fast computers.)
- Window::setVisible(false) clears modality, but also fixed in Browser
  code as well (fixes loading images on Windows hanging)
- Browser won't consume full CPU resources (but timing analysis will,
  I don't want stalls to affect the results.)
- closing settings window while analyzing stops analysis
- you can load the SGB BIOS without a game (why the hell you would want
  to ...)
- escape closes the Browser window (it won't close other dialogs, it has
  to be hooked up per-window)
- just for fun, joypad hat up/down moves in Browser file list, any
  joypad button loads selected game [not very useful, lacks repeat, and
  there aren't GUI load file open buttons]
- Super Scope and Justifier crosshairs render correctly (probably
  doesn't belong in the core, but it's not something I suspect people
  want to do themselves ...)
- you can load GB, SGB, GB, SGB ... without problems (not happy with how
  I did this, but I don't want to add an Interface::setInterface()
  function yet)
- PAL timing works as I want now (if you want 50fps on a 60hz monitor,
  you must not use sync video) [needed to update the DSP frequency when
  toggling video/audio sync]
- not going to save input port selection for now (lot of work), but it
  will properly keep your port setting across cartridge loads at least
  [just goes to controller on emulator restart]
- SFC overscan on and off both work as expected now (off centers image,
  on shows entire image)
- laevateinn compiles properly now
- ethos goes to ~/.config/bsnes now that target-ui is dead [honestly,
  I recommend deleting the old folder and starting over]
- Emulator::Interface callbacks converted to virtual binding structure
  that GUI inherits from (simplifies binding callbacks)
    - this breaks Super Game Boy for a bit, I need to rethink
      system-specific bindings without direct inheritance

Timing analysis works spectacularly well on Windows, too. You won't get
your 100% perfect rate (unless maybe you leave the analysis running
overnight?), but it'll get really freaking close this way.
2012-05-08 09:29:03 +10:00
Tim Allen
cb97d98ad2 Update to v088r14 release.
byuu says:

Changelog:
- added NSS DIP switch settings window (when loading NSS carts with
  appropriate manifest.xml file)
- added video shader selection (they go in ~/.config/bsnes/Video
  Shaders/ now)
- added driver selection
- added timing settings (not only allows video/audio settings, also has
  code to dynamically compute the values for you ... and it actually
  works pretty good!)
- moved "None" controller device to bottom of list (it is the least
  likely to be used, after all)
- added Interface::path() to support MSU1, USART, Link
- input and hotkey mappings remember list position after assignment
- and more!

target-ethos now has all of the functionality of target-ui, and more.
Final code size for the port is 101.2KB (ethos) vs 167.6KB (ui).
A ~67% reduction in code size, yet it does even more! And you can add or
remove an entire system with only three lines of code (Makefile include,
header include, interface append.)

The only problem left is that the BS-X BIOS won't load the BS Zelda no
Densetsu file.
I can't figure out why it's not working, would appreciate any
assistance, but otherwise I'm probably just going to leave it broken for
v089, sorry.

So the show stoppers for a new release at this point are:
- fix laevateinn to compile with the new interface changes (shouldn't be
  too hard, it'll still use the old, direct interface.)
- clean up Emulator::Interface as much as possible (trim down
  Information, mediaRequest should use an alternate struct designed to
  load firmware / slots separately)
- enhance purify to strip SNES ROM headers, and it really needs a GUI
  interface
- it would be highly desirable to make a launcher that can create
  a cartridge folder from an existing ROM set (* ethos will need to
  accept command-line arguments for this.)
- probably need to remember which controller was selected in each port
  for each system across runs
- need to fix the cursor for Super Scope / Justifier games (move from
  19-bit to 32-bit colors broke it)
- have to refactor that cache.(hv)offset thing to fix ASP
2012-05-07 09:27:42 +10:00
Tim Allen
3cb04b101b Update to v088r13 release.
byuu says:

Changelog:
- fixed Super Game Boy input
- Sufami Turbo prompts to load second slot now (you can cancel to leave
  it empty)
- NEC/Hitachi/ARM DSP firmware is loaded; NEC RAM is saved
- folders are grouped properly: Sufami Turbo save RAM saves to its slot
  folder, etc.
- title shows properly (SGB shows GB game name only, BS-X slotted shows
  game name and optional slot name, etc.)
    - above extends to saving cheats and such in their correct folders
      as well
- added cheat editor and cheat database
    - and hooked up the requisite SGB mode loads and can use GB cheats,
      because that's kinda cool
- added state manager
- input settings, cheat editor and state manager all have erase (one)
  and reset (all) buttons now
- lots of cleanup and restructuring on Emulator::Interface; *almost*
  finished with it now

Remaining:
- BS-X BIOS won't show the data pack
- need XML mapping information window
- need NSS DIP switch settings window
- need video shaders
- need driver selection
- need to hide controllers that have no inputs from the input mapping
  list (tempted to just remove "None" as a controller option ...)

ethos is currently 88KB of code, ui is 167KB. We're missing about 5-10KB
of code in ethos to complete it, so the rewrite nearly cut the GUI code
size in half, while support all of the same functionality and allowing
the easy addition and removal of entire systems.
2012-05-06 16:34:46 +10:00
Tim Allen
5d273c5265 Update to v088r12 release.
byuu says:

Changelog:
- all hotkeys from target-ui now exist in target-ethos
- controller port menus now show up when you load a system (hidden if
  there are no options to choose from)
- tools menu auto-hides with no game open ... not much point to it then
- since we aren't using RawInput's multi-KB/MS support anyway, input and
  hotkey mappings remove KB0:: and turn MS0:: into Mouse::, makes it
  a lot easier to read
- added mute audio, sync video, sync audio, mask overscan
- added video settings: saturation, gamma, luminance, overscan
  horizontal, overscan vertical
- added audio settings: frequency, latency, resampler, volume
- added input settings: when focus is lost [ ] pause emulator [ ] allow
  input
- pausing and autopausing works
- status messages hooked up (show a message in status bar for a few
  seconds, then revert to normal status text)
- sub systems (SGB, BSX, ST) sorted below primary systems list
- added geometry settings cache
- Emulator::Interface cleanups and simplifications
- save states go into (cart foldername.extension/bsnes/state-#.bsa) now.
  Idea is to put emulator-specific data in their own subfolders

Caveats / Missing:
- SGB input does not work
- Sufami Turbo second slot doesn't work yet
- BS-X BIOS won't show the data pack
- need XML mapping information window
- need cheat editor and cheat database
- need state manager
- need video shaders
- need driver selection
- need NSS DIP switch settings
- need to hide controllers that have no inputs from the input mapping
  list

So for video settings, I used to have contrast/brightness/gamma.
Contrast was just a multiplier on intensity of each channel, and
brightness was an addition or subtraction against each channel. They
kind of overlapped and weren't that effective. The new setup has
saturation, gamma and luminance.

Saturation of 100% is normal. If you lower it, color information goes
away. 0% = grayscale. If you raise it, color intensity increases (and
clamps.) This is wonderful for GBA games, since they are oversaturated
to fucking death. Of course we'll want to normalize that inside the
core, so the same sat. value works on all systems, but for now it's
nice. If you raise saturation above 100%, it basically acts like
contrast used to. It's just that lowering it fades to grayscale rather
than black.

Adding doesn't really work well for brightness, it throws off the
relative distance between channels and looks like shit.  So now we have
luminance, which takes over the old contrast <100% role, and just fades
the pixels toward black. Obviously, luminance > 100% would be the same
as saturation > 100%, so that isn't allowed, it caps at 100% now.
Gamma's the same old function. Gamma curve on the lower-half of the
color range.
Effects are applied in the order they appear in the GUI: color ->
saturate -> gammify -> luminate -> output.
2012-05-04 22:47:41 +10:00
Tim Allen
8703d57030 Update to v088r11 release.
byuu says:

Changelog:
- phoenix has added Window::setModal(bool modal = true);
- file dialog is now modal. This allows emulation cores to request data
  and get it immediately before continuing the loading process
- save data is hooked up for most systems, still need to handle
  subsystem slot saves (Sufami Turbo, basically.)
- toggle fullscreen key binding added (Alt+Enter for now. I think F11 is
  probably better though, Enter is often mapped to game start button.)
- video scaling is in (center, scale, stretch), works the same in
  windowed and fullscreen mode (stretch hides resize window option), all
  in the settings menu now
- enough structure to map all saved paths for the browser and to load
  BS-X slotted carts, BS-X carts, single Sufami Turbo carts

Caveats / Missing:
- Super Game Boy input doesn't work yet (due to change in callback
  binding)
- doesn't load secondary Sufami Turbo slot yet
- BS-X BIOS isn't show the data pack games to load for some reason (ugh,
  I hate the shit out of debugging BS-X stuff ...)
- need mute audio, sync audio+video toggle, save/load state menu and
  quick keys, XML mapping information window
- need cheat editor and cheat database
- need state manager
- need to sort subsystems below main systems in load menu (basically
  just see if media.slot.size() > 0)
- need video shaders (will probably leave off filters for the time being
  ... due to that 24/30-bit thing)
- need video adjustments (contrast etc, overscan masks)
- need audio adjustments (frequency, latency, resampler, volume,
  per-system frequency)
- need driver selection and input focus policy (driver crash detection
  would be nice too)
- need NSS DIP switch settings (that one will be really fun)
- need to save and load window geometry settings
- need to hook up controller selection (won't be fun), create a map to
  hide controllers with no inputs to reassign
2012-05-03 22:36:47 +10:00
Tim Allen
9ad8b7eaac Update to v088r10 release.
byuu says:

ethos is going to be absolutely amazing. You guys are in for a treat :D
I'm impressing the hell out of myself with how well-structured this code
is, it's allowing me to do amazing new things.

Just a small sampling of what's in store (and already implemented):

The file browser will display folders as "[ folder name ]", and
cartridge folders as "Game Name" (no extension, no /) [icons would be
nicer, but well ... phoenix.]
Folders are sorted above cartridge folders.
Cartridge folders for other systems do not show up in the list.
Not only are unique paths stored for each image type, your position in
the list is saved across runs.
Some voodoo was added to GTK+ so that all targets even scroll directly
to that item when you open the list. Load->System->Enter restarts your
last game.
That sounds really simple and obvious, but it makes an -incredible-
difference. Didn't realize it until I tried an implementation of it,
wow.

The input mapping list now lets you bind as many hotkeys as you want to
any given input.
So SFC::Port1::Joypad::B = Keyboard::Z or Joypad::Button1 ... no need to
remap everything to switch between keyboard and joypad. Either one
activates the key.
There is a separate Hotkeys tab now. This should hopefully end the
confusion about how to remap hotkeys that users experience.
Hotkeys are different, too. Instead of OR logic, they use AND logic.
So Fullscreen = Keyboard::Alt and Keyboard::Enter. Both must be pressed
to enter the key. This lets you easily implement "super" modifier keys.

The actual codebase has new features the old UI never had, and has about
~50% of the old functionality (so far, of course), yet is only ~25% as
much code.
The entire GUI no longer needs to pull in all the headers for each
emulated system. It just needs a small interface header file.
Then bind the entire system with exactly **two** lines of code.
Everything is dynamically generated for you after that.
2012-05-01 22:27:50 +10:00
Tim Allen
76553756a2 Update to v088r09 release.
byuu says:

Lots of work on ethos, nothing more.
Settings window is in, InputManager pulls all the inputs from all cores
and binds them to ruby inputs, main window adds menu and dynamically
maps in all systems and cartridge slots and options and such, file
browser's back in, RAM is loaded and saved, etc. It's barely usable, but
you have to set up your inputs from the config file by hand for now.
2012-05-01 22:27:50 +10:00
Tim Allen
4fd20f0ae0 Update to v088r08 release.
byuu says:

From this WIP, I'm starting on the impossible task of
a declarative-based GUI, which I'm calling Ethos.
base/ becomes emulator/, and we add emulator/interface.hpp, which is
a base API that all emulation cores must implement in full.
(Right now, it's kind of a hybrid to work with the old GUI and the new
GUI at the same time, of course.)
Unlike the old interfaces, the new base class also provides all general
usability hooks: loading and saving files and states, cheat codes, etc.
The new interface also contains information and vector structs to
describe all possible loading methods, controller bindings, etc; and
gives names for them all.
The actual GUI in fact should not include eg <gba/gba.hpp> anymore.
Should speed up GUI compilation.

So the idea going forward is that ethos will build a list of emulators
right when the application starts up.
Once you've appended an emulator to that list, you're done. No more GUI
changes are needed to support that system.
The GUI will have code to parse the emulator interfaces list, and build
all the requisite GUI options dynamically, declarative style.

Ultimately, once the project is finished, the new GUI should look ~99%
identical to the current GUI. But it'll probably be a whole lot smaller.
2012-05-01 22:27:48 +10:00
Tim Allen
bb4db22a7d Update to v088r07 release.
byuu says:

(r05 and r06 were save points between large core modifications)

I would really appreciate extensive regression testing (especially
around SuperFX, Cx4, ST018, DSP-n, ST-01n, NES, GB) at this point.
The most critical core changes should be completed now. And it was an
unbelievable amount of restructuring.

Changelog:
- SuperFX core moved to Processor::GSU
- SNES::CPU core moved to Processor::R65816
- SNES::SMP core moved to Processor::SPC700
- NES::CPU core renamed to Processor::R6502
- use filestream to load RAM files from interface
- save states store SHA256 instead of CRC32 (CRC32 usage removed
  entirely from bsnes)
- nes/ -> fc/ and NES -> FC
- snes/ -> sfc/ and SNES -> SFC
- SuperFamicom::MappedRAM::copy uses stream instead of data+size
- Linux port uses gcc-4.7 (still using only gcc-4.6 subset, so you can
  make a gcc-4.6 symlink for now if you like.)
- all profiles and all targets compile and work properly

All eight instruction set cores have been moved to processor/ now.
Consistency's a wonderful thing.
The last remnants of NES/SNES are now limited to target-ui code; and the
nall/(system) folder names.
I'm building with gcc-4.7 on my Linux box now because the resultant
binaries are up to 20% faster (seriously) than gcc-4.6.
2012-05-01 22:02:14 +10:00
Tim Allen
67c13f749f Update to v088r04 release.
byuu says:

This will hopefully be a short-lived WIP, I just want to save
a breakpoint before I attempt something else.
NES, GB, GBC and GBA all load via const stream& now.
NES CPU core moved to Processor::RP2A03.
2012-04-28 16:35:51 +10:00
Tim Allen
616372e96b Update to v088r03 release.
byuu says:

static vector<uint8_t> file::read(const string &filename); replaces:
static bool file::read(const string &filename, uint8_t *&data, unsigned
&size); This allows automatic deletion of the underlying data.

Added vectorstream, which is obviously a vector<uint8_t> wrapper for
a data stream.  Plan is for all data accesses inside my emulation cores
to take stream objects, especially MSU1.  This lets you feed the core
anything: memorystream, filestream, zipstream, gzipstream, httpstream,
etc.  There will still be exceptions for link and serial, those need
actual library files on disk. But those aren't official hardware devices
anyway.

So to help with speed a bit, I'm rethinking the video rendering path.

Previous system:
- core outputs system-native samples (SNES = 19-bit LRGB, NES = 9-bit
  emphasis+palette, DMG = 2-bit grayscale, etc.)
- interfaceSystem transforms samples to 30-bit via lookup table inside
  the emulation core
- interfaceSystem masks off overscan areas, if enabled
- interfaceUI runs filter to produce new target buffer, if enabled
- interfaceUI transforms 30-bit video to native display depth (24-bit or
  30-bit), and applies color-adjustments (gamma, etc) at the same time

New system:
- all cores now generate an internal palette, and call
  Interface::videoColor(uint32_t source, uint16_t red, uint16_t green,
  uint16_t blue) to get native display color post-adjusted (gamma, etc
  applied already.)
- all cores output to uint32_t* buffer now (output video.palette[color]
  instead of just color)
- interfaceUI runs filter to produce new target buffer, if enabled
- interfaceUI memcpy()'s buffer to the video card

videoColor() is pretty neat. source is the raw pixel (as per the
old-format, 19-bit SNES, 9-bit NES, etc), and you can create a color
from that if you really want to. Or return that value to get a buffer
just like v088 and below.  red, green, blue are 16-bits per channel,
because why the hell not, right? Just lop off all the bits you don't
want. If you have more bits on your display than that, fuck you :P

The last step is extremely difficult to avoid. Video cards can and do
have pitches that differ from the width of the texture.  Trying to make
the core account for this would be really awful. And even if we did
that, the emulation routine would need to write directly to a video card
RAM buffer.  Some APIs require you to lock the video buffer while
writing, so this would leave the video buffer locked for a long time.
Probably not catastrophic, but still awful.  And lastly, if the
emulation core tried writing directly to the display texture, software
filters would no longer be possible (unless you -really- jump through
hooks and divert to a memory buffer when a filter is enabled, but ...
fuck.)

Anyway, the point of all that work was to eliminate an extra video copy,
and the need for a really painful 30-bit to 24-bit conversion (three
shifts, three masks, three array indexes.) So this basically reverts us,
performance-wise, to where we were pre-30 bit support.

[...]

The downside to this is that we're going to need a filter for each
output depth. Since the array type is uint32_t*, and I don't intend to
support higher or lower depths, we really only need 24+30-bit versions
of each filter.  Kinda shitty, but oh well.
2012-04-27 22:12:53 +10:00
Tim Allen
bba597fc6f Update to v088r02 release.
byuu says:

Basically, the current implementation of nall/array is deprecated now.
The old method was for non-reference types, it acted like a vector for
POD types (raw memory allocation instead of placement new construction.)
And for reference types, it acted like an unordered set. Yeah, not good.

As of right now, nall/array is no longer used. The vector type usage was
replaced with actual vectors.
I've created nall/set, which now contains the specialization for
reference types.
nall/set basically acts much like std::unordered_set. No auto-sort, only
one of each type is allowed, automatic growth.
This will be the same both for reference and non-reference types ...
however, the non-reference type wasn't implemented just yet.
Future plans for nall/array are for it to be a statically allocated
block of memory, ala array<type, size>, which is meant for RAII memory
usage.
Have to work on the specifics, eg the size as a template parameter may
be problematic. I'd like to return allocated chunks of memory (eg
file::read) in this container so that I don't have to manually free the
data anymore.

I also removed nall/moduloarray, and moved that into the SNES DSP class,
since that's the only thing that uses it.
2012-04-26 20:56:15 +10:00
Tim Allen
abe639ea91 Update to v088r01 release.
byuu says:

- GB::CPU::Core -> Processor::LR35902
- Processor::LR35902 -> jump table to switch table
- GB::LCD -> GB::PPU
- static frequency for DMG (no multiplication on clock ticks)
- GB::PPU::interface->videoRefresh() moved outside scheduler (use host
  thread)
- namespace NES  -> Famicom
- namespace SNES -> SuperFamicom
- namespace GB   -> GameBoy
- namespace GBA  -> GameBoyAdvance
- removed boot.rom writeout in GB::System
2012-04-26 20:51:13 +10:00
Tim Allen
77bb5b7891 Update to v088 release.
byuu says:

Changes to v088:
- OBJ mosaic Y fix
- Laevateinn compilation
- Remove filebrowser extra code
- Fix -march=native on Windows
- Fix purify mkdir
- GBA sound volume
- Add .gbb
- free firmware memory after file load
- Add GBA game to profile list (Yoshi's Island should work)
2012-04-24 23:17:52 +10:00
Tim Allen
4b2944c39b Update to v087r30 release.
byuu says:

Changelog:
- DMA channel masks added (some are 27-bit source/target and some are
  14-bit length -- hooray, varuint_t class.)
- No more state.pending flags. Instead, we set dma.pending flag when we
  want a transfer (fixes GBA Video - Pokemon audio) [Cydrak]
- fixed OBJ Vmosaic [Cydrak, krom]
- OBJ cannot read <=0x13fff in BG modes 3-5 (fixes the garbled tile at
  the top-left of some games)
- DMA timing should be much closer to hardware now, but probably not
  perfect
- PPU frame blending uses blargg's bit-perfect, rounded method (slower,
  but what can you do?)
- GBA carts really unload now
- added nall/gba/cartridge.hpp: used when there is no manifest. Scans
  ROMs for library tags, and selects the first valid one found
- added EEPROM auto-detection when EEPROM size=0. Forces disk/save state
  size to 8192 (otherwise states could crash between pre and post
  detect.)
    - detects first read after a set read address command when the size
      is zero, and sets all subsequent bit-lengths to that value, prints
      detected size to terminal
- added nall/nes/cartridge.hpp: moves iNES detection out of emulation
  core.

Important to note: long-term goal is to remove all
nall/(system)/cartridge.hpp detections from the core and replace with
databases. All in good time.
Anyway, the GBA workarounds should work for ~98.5% of the library, if my
pre-scanning was correct (~40 games with odd tags. I reject ones without
numeric versions now, too.)

I think we're basically at a point where we can release a new version
now. Compatibility should be relatively high (at least for a first
release), and fixes are only going to affect one or two games at a time.
I'd like to start doing some major cleaning house internally (rename
NES->Famicom, SNES->SuperFamicom and such.) Would be much wiser to do
that on a .01 WIP to minimize regressions.

The main problems with a release now:
- speed is pretty bad, haven't really optimized much yet (not sure how
  much we can improve it yet, this usually isn't easy)
- sound isn't -great-, but the GBA audio sucks anyway :P
- couple of known bugs (Sonic X video, etc.)
2012-04-22 20:49:19 +10:00
Tim Allen
4c29e6fbab Update to v087r29 release.
byuu says:

Changelog:
- revised NES XML tag nesting
- program.rom is going to refer to PRG+CHR combined. Split is going to
  have to use different file names
- slot loader is gone (good riddance!)
- "Cartridge -> Load Game Boy Advance Cartridge ..." has become "Load ->
  Game Boy Advance ..."
- Load Satellaview Slotted Cartridge is gone. If you load an SNES
  cartridge and it sees <bsx><slot>, it asks if you want to load a BS-X
  data pack
- If you load a Sufami Turbo cartridge with <cartridge linkable="true">,
  it asks if you want to link in another Sufami Turbo cartridge
- if you try and load the same exact Sufami Turbo cartridge in both
  slots, it yells at you for being an idiot :P
2012-04-20 22:48:09 +10:00
Tim Allen
a454e9d927 Update to v087r28 release.
byuu says:

Be sure to run make install, and move required images to their appropriate system profile folders.
I still have no warnings in place if those images aren't present.

Changelog:
- OBJ mosaic should hopefully be emulated correctly now (thanks to krom
  and Cydrak for testing the hardware behavior)
- emulated dummy serial registers, fixes Sonic Advance (you may still
  need to specify 512KB FlashROM with an appropriate ID, I used
  Panaonic's)
- GBA core exits scheduler (PPU thread) and calls
  interface->videoRefresh() from main thread (not required, just nice)
- SRAM, FRAM, EEPROM and FlashROM initialized to 0xFF if it does not
  exist (probably not needed, but FlashROM likes to reset to 0xFF
  anyway)
- GBA manifest.xml for file-mode will now use "gamename.xml" instead of
  "gamename.gba.xml"
- started renaming "NES" to "Famicom" and "SNES" to "Super Famicom" in
  the GUI (may or may not change source code in the long-term)
- removed target-libsnes/
- added profile/

Profiles are the major new feature. So far we have:

    Famicom.sys/{nothing (yet?)}
    Super Famicom.sys/{ipl.rom}
    Game Boy.sys/{boot.rom}
    Game Boy Color.sys/{boot.rom}
    Game Boy Advance.sys/{bios.rom[not included]}
    Super Game Boy.sfc/{boot.rom,program.rom[not included]}
    BS-X Satellaview.sfc/{program.rom,bsx.ram,bsx.pram}
    Sufami Turbo.sfc/{program.rom}

The SGB, BSX and ST cartridges ask you to load GB, BS or ST cartridges
directly now. No slot loader for them.  So the obvious downsides: you
can't quickly pick between different SGB BIOSes, but why would you want
to? Just use SGB2/JP.  It's still possible, so I'll sacrifice a little
complexity for a rare case to make it a lot easier for the more common
case.  ST cartridges currently won't let you load the secondary slot.
BS-X Town cart is the only useful game to load with nothing in the slot,
but only barely, since games are all seeded on flash and not on PSRAM
images. We can revisit a way to boot the BIOS directly if and when we
get the satellite uplink emulated and data can be downloaded onto the
PSRAM :P BS-X slotted cartridges still require the secondary slot.

My plan for BS-X slotted cartridges is to require a manifest.xml to
specify that it has the BS-X slot present.  Otherwise, we have to load
the ROM into the SNES cartridge class, and parse its header before we
can find out if it has one. Screw that.  If it's in the XML, I can tell
before loading the ROM if I need to present you with an optional slot
loading dialog.  I will probably do something similar for Sufami Turbo.
Not all games even work with a secondary slot, so why ask you to load
a second slot for them? Let the XML request a second slot. A complete
Sufami Turbo ROM set will be trivial anyway.  Not sure how I want to do
the sub dialog yet. We want basic file loading, but we don't want it to
look like the dialog 'didn't do anything' if it pops back open
immediately again. Maybe change the background color of the dialog to
a darker gray? Tacky, but it'd give you the visual cue without the need
for some subtle text changes.
2012-04-18 23:58:04 +10:00
Tim Allen
d2241f1931 Update to v087r27 release.
byuu says:

Changelog:
- serialize processor.pc.data, not processor.pc
- call CPU processor.setMode() in ARM serialize
- serialize BIOS.mdr
- support SRAM > 32KB
- EEPROM, FlashROM serialize
- EEPROM lose nall/bitarray.hpp
- noise line feed after envelope
- space out PSR read
- ST018 needs byte reads fixed (don't align) [fixes HNMS2]
- flush sram/eeprom/flashrom to 0 on cartridge load
- APU/PPU dont sync back to CPU if syncing for state
- fixed APU sync problems in GB/GBC core that could possibly wreck save
  states as well

Quite a lot of little problems there. I believe GBA save states are
fixed now.
2012-04-17 22:16:54 +10:00
Tim Allen
0cd0dcd811 Update to v087r26 release.
byuu says:

Changelog:
- fixed FIFO[1] reset behavior (fixes audio in Sword of Mana)
- added FlashROM emulation (both sizes)
- GBA parses RAM settings from manifest.xml now
- save RAM is written to disk now
- added save state support (it's currently broken, though)
- fixed ROM/RAM access timings
- open bus should mostly work (we don't do the PC+12 stuff yet)
- emulated the undocumented memory control register (mirror IWRAM,
  disable I+EWRAM, EWRAM wait state count)
- emulated keypad interrupts
- emulated STOP (freezes video, audio, DMA and timers; only breaks on
  keypad IRQs)
- probably a lot more, it was a long night ...

Show stoppers, missing things, broken things, etc:
- ST018 is still completely broken
- GBC audio sequencer apparently needs work
- GBA audio FIFO buffer seems too quiet
- PHI / ROM prefetch needs to be emulated (no idea on how to do this,
  especially PHI)
- SOUNDBIAS 64/128/256khz modes should output at that resolution
  (really, we need to simulate PWM properly, no idea on how to do this)
- object mosaic top-left coordinates are wrong (minor, fixing will
  actually make the effect look worse)
- need to emulate PPU greenswap and color palette distortion (no idea on
  how do this)
- need GBA save type database (I would also LIKE to blacklist
  / patch-out trainers, but that's a discussion for another day.)
- some ARM ops advance the prefetch buffer, so you can read PC+12 in
  some cases
2012-04-16 22:19:39 +10:00
Tim Allen
1c18812f47 Update to v087r25 release.
byuu says:

(r24 was a point release during merging of changes.)

This release is almost entirely Cydrak's direct work:
- Added ARM::sequential() and some WAITCNT timings
- Added Bus::io(uint32 pc), intended for prefetch timing
- Added ARM::load() with data rotation (fixed Mother 3 graphics)
- Added ARM::store() for data mirroring
- LDM, STM, and instruction fetch still use read/write()
- ARM::vector() no longer unmasks FIQs
- Set THUMB shifter flags via bit(), consistent with ARM
- Replace shifter loops with conditional tests

My changes:
- fixed sprite clipping on left-edge of screen
- added first system folder, GBA.system
- sudo make install is now make install
- make install will create GBA.system for you in your home folder

Windows users, take data/GBA.system and put it in the same folder as
bsnes.exe, and give it a BIOS named bios.rom
Or place it in your home folder (%APPDATA%/bsnes)
Also note that this is highly experimental, I'll probably be changing
things a lot before release.

EDIT: I botched the cartridge timing change. Will fix in r26. It'll
still run a bit too fast for now, unfortunately.
2012-04-15 16:49:56 +10:00
Tim Allen
28885db586 Update to v087r23 release.
byuu says:

Changelog:
- fixed cascading timers and readouts (speed hit from 320fps to 240fps;
  would be 155fps with r20 timers) (fixes Spyro)
- OBJ mode 3 acts like OBJ mode 2 now (may not be correct, but nobody
  has info on it)
- added background + object vertical+horizontal mosaic in all modes
  (linear+affine+bitmap)
- object mosaic uses sprite (0,0) for start coordinates, not screen
  (0,0) (again, nobody seems to have info on it)
- BIOS cannot be read by r(15)>=0x02000000; returns last BIOS read
  instead (I can't believe games rely on this to work ... fixes SMA
  Mario Bros.)

Mosaic is what concerns me the most, I've no idea if I'm doing it
correctly. But anything is probably better than nothing, so there's
that. I don't really notice the effect in Metroid Fusion. So either it's
broken, or it's really subtle.
2012-04-14 17:26:45 +10:00
Tim Allen
d423ae0a29 Update to v087r22 release.
byuu says:

Changelog:
- fixed below pixel green channel on color blending
- added semi-transparent objects [Exophase's method]
- added full support for windows (both inputs, OBJ windows, and output, with optional color effect disable)
- EEPROM uses nall::bitarray now to be friendlier to saving memory to disk
- removed incomplete mosaic support for now (too broken, untested)
- improved sprite priority. Hopefully it's right now.

Just about everything should look great now. It took 25 days, but we
finally have the BIOS rendering correctly.

In order to do OBJ windows, I had to drop my above/below buffers
entirely. I went with the nuclear option.  There's separate layers for
all BGs and objects. I build the OBJ window table during object
rendering.  So as a result, after rendering I go back and apply windows
(and the object window that now exists.) After that, I have to do
a painful Z-buffer select of the top two most important pixels.  Since
I now know the layers, the blending enable tests are a lot nicer, at
least.  But this obviously has quite a speed hit: 390fps to 325fps for
Mr. Driller 2 title screen.

TONC says that "bad" window coordinates do really insane things. GBAtek
says it's a simple y2 < y1 || y2 > 160 ? 160 : y2; x2 < x1 || x2 > 240
? 240 : x2; I like the GBAtek version more, so I went with that. I sure
hope it's right ... but my guess is the hardware does this with
a counter that wraps around or something.  Also, say you have two OBJ
mode 2 sprites that overlap each other, but with different priorities.
The lower (more important) priority sprite has a clear pixel, but the
higher priority sprite has a set pixel. Do we set the "inside OBJ
window" flag to true here? Eg does the value OR, or does it hold the
most important sprite's pixel value? Cydrak suspects it's OR-based,
I concur from what I can see.

Mosaic, I am at a loss. I really need a lot more information in order to
implement it.  For backgrounds, does it apply to the Vcounter of the
entire screen? Or does it apply post-scroll? Or does it even apply after
every adjust in affine/bitmap modes?  I'm betting the hcounter
background mosaic starts at the leftmost edge of the screen, and repeats
previous pixels to apply the effect. Like SNES, very simple.  For
sprites, the SNES didn't have this. Does the mosaic grid start at (0,0)
of the screen, or at (0,0) of each sprite? The latter will look a lot
nicer, but be a lot more complex. Is mosaic on affine objects any
different than mosaic of linear(tiled) objects?

With that out of the way, we still have to fix the CPU memory access
timing, add the rest of the CPU penalty cycles, the memory rotation
/ alignment / extend behavior needs to be fixed, the shifter desperately
needs to be moved from loops to single shift operations, and I need to
add flash memory support.
2012-04-13 21:50:53 +10:00
Tim Allen
303a0a67d0 Update to v087r21 release.
byuu says:

Timer speedup added. Boosts Mr. Driller 2 title from 170fps to 400fps.
Other games still benefit, but not as amazingly. I don't dip below
160fps ever here.
Reverted the memory speed to 2 for everything for now, to fix
Castlevania slowdown. We obviously need to add the N/S stuff before we
do that.
Added linear BG and linear OBJ mosaic-Y. Did not add mosaic-X, or any
mosaic to the affine/bitmap modes, because I'm not sure when to apply
the compensation.
Rewrote layer stuff. It now has two layers (above and below), and it
performs the four blending modes as needed.
Didn't add semi-transparent sprites because the docs are too confusing.
Added a blur filter directly into the PPU for now. This obviously
violates my interface, but F-Zero needed it for HUD display. We can
remove it when we have an official release with a blur filter available.
The filter still doesn't warp colors like a real GBA, because I don't
know the formula.
2012-04-10 21:41:35 +10:00
Tim Allen
01b4cb9919 Update to v087r20 release.
byuu says:

Changelog:
- HALT waits 16 cycles before testing IRQs instead of 1 (probably less
  precise, but provides a massive speedup) [we will need to work on this
  later]
- MMIO regs for CPU/PPU simplified by combining array accesses
- custom VRAM/PRAM/OAM read/write functions that emulate 8->16-bit
  writes
- 16-bit PRAM data (decent speedup)
- emulated memory access speed (but don't handle non-sequential
  penalties or PPU access penalties yet) [amazingly, doesn't help speed
  at all]
- misc. code cleanups

For this WIP, FPS for Mr. Driller 2 went from 88fps to 172fps.
Compatibility should be unchanged. Timers are still an interesting
avenue to increase performance, but will be very tough to handle the
16MHz timers with eg a period of 65535 (overflow every single tick.) And
that's basically the last major speed boost we'll be able to get.
Blending and windowing is going to hurt performance, but it remains to
be seen how much.
2012-04-09 16:41:27 +10:00
Tim Allen
17b5bae86a Update to v087r19 release.
byuu says:

Changelog:
- added FIFO buffer emulation (with DMA and all that jazz) [Cydrak]
- fixed timers and vcounter assign [Cydrak]
- emulated EEPROM (you have to change size manually for 14-bit mode, we
  need a database badly now) [SMA runs now]
- removed OAM array, now decoding directly to struct Object {} [128] and
  ObjectParam {} [32] (faster this way)
- check forceblank (still doesn't remove all garble between transitions,
  though??)
- lots of other stuff

Delete your settings.cfg, or manually change frequencyGBA to 32768, or
bad things will happen (this may change back to 256KHz-4MHz later.)

15 of 16 games are fully playable now, and look and sound great.
The major missing detail right now is PPU blending support, and we
really need to optimize the hell out of the code.
2012-04-09 16:19:32 +10:00
Tim Allen
6189c93f3d Update to v087r18 release.
byuu says:

Merged Cydrak's r17c changes:
- BG affine mode added
- BG bitmap mode added
- OBJ affine mode added
- fixed IRQ bug in THUMB mode (fixed almost every game)
- timers added (broke almost every game, whee.)

Cydrak is absolutely amazingly awesome and patient. This really wouldn't
be happening without him.

Also fixed some things from my end, including greatly improved sprite
priorities, and a much better priority sorter. Mr. Driller looks a lot
better now.
2012-04-07 18:17:49 +10:00
Tim Allen
1de484262c Update to v087r17 release.
byuu says:

Emulated GBC sound plus the new extensions to it.
I am kind of surprised by how little developers utilized the GBC audio
portion.
Mr. Driller now has sound effects, and Pinobee no Daibouken has BGM.
I still have yet to emulate the GBA extra sound channels and PWM. Need
to emulate timers and DMA 2 refresh mode before I can do that.

Also, I moved both GBC and GBA audio to use length = data; if(++length
== 0); rather than length = 64 - data; if(--length == 0); so that
I could return literal values for register reads.
I thought there was a good reason we used the latter version, but
I can't hear any audible difference even in GBC games, so oh well.
Lastly, I think the pattern[++offset] in the wave channel was a bug in
the DMG/GBC only. I really, really hope it doesn't apply to the GBA,
because that will make bank selection a serious pain in the ass.
2012-04-06 14:29:50 +10:00
Tim Allen
b8d0ec29b2 Update to v087r16 release.
byuu says:

Fixed the r15 mask per Cydrak.
Added DMA support (immediate + Vblank + Hblank + HDMA) with IRQ support.
Basically only missing FIFO reload mode for the APU on channel 2.
Added background linear renderer (tilemap mode.)
Added really inefficient pixel priority selector, so that all BGs+OBJ
could be visible onscreen at the same time.

As a result of the above:
* Mr. Driller is our first fully playable game
* Bakunetsu Dodge Ball Fighters is also fully playable
* Pinobee no Daibouken is also fully playable

Most games (15 of 16 tested) are now showing *something*, many things
look really really good in fact.

Absolutely essential missing components:
- APU
- CPU timers and their interrupts
- DMA FIFO mode
- OBJ affine mode
- BG affine mode
- BG bitmap mode
- PPU windows (BG and OBJ)
- PPU mosaic
- PPU blending modes
- SRAM / EEPROM (going to rely on a database, not heuristics. Homebrew
  will require a manifest file.)
2012-04-04 09:50:40 +10:00
Tim Allen
79a47d133a Update to v087r15 release.
byuu says:

Added linear (eg non-affine) sprite rendering, 4bpp and 8bpp with hflip
and vflip. Nothing else.
You can now see the Nintendo logo and Gameboy text at the end of the BIOS.
It's a start =)
2012-04-03 10:47:28 +10:00
Tim Allen
c8bb4949b1 Update to v087r14 release.
byuu says:

Fixed aforementioned issues.

[From a previous post:
- mul was using r(d) instead of r(n) for accumulate.
- mull didn't remove c/v clear.
- APU register mask was broken, so SOUNDBIAS was reading out wrong.
- APU was only mapping 0x088 and not 0x089 as well.
- Halfword reads in CPU+PPU+APU were all reading from the low address
  each time.]

All CPU+PPU registers are now hooked up (not that they do anything.)
SOUNDBIAS for APU was hooked up, got tired of working on it for the rest :P
I recall from the GB APU that you can't just assign values for the APU
MMIO regs. They do odd reload things as well.
Also, was using MMIO read code like this:

    return (
       (flaga << 0)
    || (flagb << 1)
    || (flagc << 2)
    );

Logical or doesn't work so well with building flags :P
Bad habit from how I split multiple conditionals across several lines.

So ... r14 is basically what r13 should have been yesterday, delaying my
schedule by yet another day :(
2012-04-01 11:41:15 +10:00
Tim Allen
f587cb0dcc Update to v087r13 release.
byuu says:

Contains all of Cydrak's fixes, sans PPU.
On the PPU front, I've hooked up 100% of read and write registers.
All three DISPSTAT IRQs (Vblank, Hblank, Vcoincidence) are connected now
as well.
Super Mario Advance now runs without *appearing* to crash, although it's
hard to tell since I have no video or sound :P
ARM Wrestler is known to run, as is the BIOS.
2012-03-31 19:17:36 +11:00
Tim Allen
ea086fe33f Update to v087r12 release.
byuu says:

Enough to get through the BIOS and into cartridge ROM.
I am a bit annoyed that I was basically told that the GBA PPU wasn't
that bad. Sprites are a clusterfuck, easily worse than Mode7, docs don't
even begin to explain them in enough detail.
This is going to be fun.
2012-03-31 19:14:31 +11:00
Tim Allen
c66cc73374 Update to v087r11 release.
byuu says:

Added all of the above fixes and changes. [A lot of individual fixes for
the ARM core from Cydrak - Ed.] Also new is pipeline_decode() to fetch
data, and IME/IE/IF support, and an ARM::processor.irqline flag that
triggers IRQs at 0x18. Only Vblank is hooked up, which is what SWI 4 was
waiting on previously.
I'm sure my interrupt support is horribly broken and wrong. I was never
able to really figure out IE/IF on the Game Boy, so there's no question
this is even worse.
It's now going crazy and writing 0 to IE forever now after the Vblank
IRQ triggers.
2012-03-29 22:58:10 +11:00
Tim Allen
5a1dcf5079 Update to v087r10 release.
byuu says:

Changelog:
- fixed THUMB hi immediate reads (immediate * 4)
- cartridge is properly mirrored to 32MB (eg 12mbit repeats as
  lo8+hi4+hi4+lo8+hi4+hi4) [so it's a bit slower than a standard memcpy
  fill]
- added ARM - load/store halfword register offset
- added ARM - load/store halfword immediate offset
- added ARM - load signed halfword/byte register offset
- added ARM - load signed halfword/byte immediate offset
- added decode() function to make opcode bit testing a lot clearer
  (didn't apply it to the debugger yet)

All ARMv4M and all THUMBv4 instructions should now be implemented.
Although I'm not sure if my implementations of the new instructions are
correct.
2012-03-27 22:02:57 +11:00
Tim Allen
e16dd58184 Update to v087r09 release.
byuu says:

Split apart necdsp: core is now in processor/upd96050 (wish I had
a better name for it, but there's no family name that is maskable.)
I would like to support the uPD7720 in the core as well, just for
completeness' sake, but I'll have to modify the decoder to drop one bit
from each mode.
So ... I'll do that later. Worst part is even if I do, I won't be able
to test it :(

Added all of Cydrak's changes. I also simplified LDMIA/STMIA and
PUSH/POP by merging the outer loops.
Probably infinitesimally slower, but less code is nicer. Maybe GCC
optimization will expand it, who knows.
2012-03-26 21:13:02 +11:00
Tim Allen
395e5a5639 Update to v087r08 release.
byuu says:

Added some more ARM opcodes, hooked up MMIO. Bind it with mmio[(addr
000-3ff)] = this; inside CPU/PPU/APU, goes to read(), write().
Also moved the Hitachi HG51B core to processor/, and split it apart from
the snes/chip/hitachidsp implementation.
This one actually worked really well. Very clean split between MMIO/DMA
and the processor core. I may move a more generic DMA function inside
the core, not sure yet.

I still believe the HG51B169 to be a variant of the HG51BS family, but
given they're meant to be incredibly flexible microcontrollers, it's
possible that each variant gets its own instruction set.
So, who knows. We'll worry about it if we ever find another HG51B DSP,
I guess.

GBA BIOS is constantly reading from 04000300, but it never writes. If
I return prng()&1, I can get it to proceed until it hits a bad opcode
(stc opcode, which the GBA lacks a coprocessor so ... bad codepath.)
Without it, it just reads that register forever and keeps resetting the
system, or something ...

I guess we're going to have to try and get ARMwrestler working, because
the BIOS seems to need too much emulation code to do anything at all.
2012-03-24 18:52:36 +11:00
Tim Allen
ec939065bd Update to v087r07 release.
There was a "v087r07pre" release that I unfortunately missed.

byuu says (about v087r07pre):

Creates the bsnes/processor folder. This has a shared ARM core there
which both the GBA and ST018 inherit.
There are going to be separate decoders, and revision-specific checks,
to support the differences between v3+.
In the future, I also want to move the other processor cores here:
- GBZ80 (GB, GBC)
- 65816 (SNES CPU, SA-1)
- NEC uPD (7725, 96050, maybe 7720 just for fun)
- Hitachi HG51B169
- SuperFX
- SPC700
- 65(C?)02

Basically, the GBA/ST018 forces my hand to start coding a bit more like
a multi-system emulator.

Right now, the ST018 is broken. Hence the pre. Apparently the GBA core
being used now has some bugs. So this'll be a nice way to stress-test
the GBA core a bit before we make it to ARMwrestler.

byuu says (about v087r07):

Both snes/chip/armdsp and gba/cpu use processor/arm now.
Fixed THUMB to execute the BL prefix and suffix separately. I can now
get the GBA BIOS stuck in some kind of infinite loop. Hooray ...
I guess?
2012-03-23 21:43:39 +11:00
Tim Allen
77578cd0a4 Update to v087r06 release.
byuu says:

I believe I've implemented every THUMB instruction now, although I'm
sure there are dozens of bugs in the implementation.

It seems that the last jump taken is ending up being off-by-two. It's
probably due to not masking/adjusting PC correctly at certain points.

I don't know if any other bugs are being hit prior to this or not.
I don't implement any I/O registers yet, and the BIOS seems to be poking
at a few of them along the way, so ... who knows.
I could also be reading the log wrong, but it looks to me like there's
some PSR setting the mode flag register to 0, which is supposed to be an
undefined behavior mode ... perhaps mrs has no effect on the m/t bits,
and it just affects the i/f bits?
2012-03-22 22:47:25 +11:00
Tim Allen
04087a74b0 Update to v087r05 release.
byuu says:

Implemented all of the ARMv3 instructions, and the bx rm instruction as
well. Already hit THUMB mode right at the start of the BIOS, sigh.
Implemented the first THUMB instruction to get that rolling. Also tried
to support the S flag to LDM/STM, but not sure how successful I was.
2012-03-21 22:08:16 +11:00
Tim Allen
6701403745 Update to v087r04 release.
byuu says:

GBA stuff re-added. Only thing missing that was there before is the ARM
branch opcode.
Since we're going to be staring at it for a very long time, I added
a more interesting test video pattern.

Went from 6fps to 912fps. Amazing what being able to divide can do for
a frame rate.
2012-03-19 22:19:53 +11:00
Tim Allen
95c62f92ac Update to v087r03 release.
byuu says:

Fixing the PPU stepping increased FPS to 250. Promising, at least, since
the ARM core is still severely overclocked.
However, I reverted back to r02. This one patches gameboy/ and GameBoy::
to gb/ and GB:: and that's it.
Sorry, I just couldn't shake this bad feeling about the code. There were
some poorly hacked-together constructs. I'd rather just redo two days of
work than feel bad about the codebase for the next several years. Going
to attempt the GBA bridge again. Third time's a charm, I suppose (there
was a pre-r03 WIP I abandoned as well.)
This isn't unprecedented, GB core took a few attempts like this as well.
2012-03-19 21:27:40 +11:00
Tim Allen
0f54be93b7 Update to v087r04 release.
byuu says:

Changelog:
- gameboy/ -> gb/
- GameBoy -> GB
- basic memory map for GBA
- enough code to execute the first BIOS instruction (b 0x68)

I have the code resetting r(15) to 0 on an exception just as a test.
Since that flushes the pipeline, that means we're basically executing "b
0x68" at 8MHz, and nothing else.
... and I am getting __6 motherfucking FPS__ at 4.4GHz on an i7.

Something is seriously, horribly, unfuckingbelievably wrong here, and
I can't figure out what it is.
My *fully complete* ARM core on the ST018 is even less efficient and
runs at 21.47MHz, and yet I get 60fps even after emulating the SNES
CPU+PPU @ 10+MHz each as well.

... I'm stuck. I can't proceed until we figure out what in the holy fuck
is going on here. So ... if anyone can help, please do. If we can't fix
this, the GBA emulation is dead.
I was able to profile on Windows, and I've included that in this WIP
under out/log.txt.
But it looks normal to me. But yeah, there's NO. FUCKING. WAY. This code
should be running this slowly.
2012-03-18 23:35:53 +11:00
Tim Allen
8db134843f Update to v087r03 release.
byuu says:

I wanted to keep this a secret, but unlike other recent additions, this
will easily take several weeks, maybe months, to show anything.
Assuming I can even pull it off. Nothing technically overwhelming here,
I'm more worried about the near-impossibility of debugging the CPU.
2012-03-18 12:04:22 +11:00
Tim Allen
06e83c6154 Update to v087r02 release.
byuu says:

Changelog:
- extended USART with quit(), readable(), writable() [both emulation and
  hardware]
    - quit() returns true on hardware when Ctrl+C (SIGINT) is generated
      (breaks main loop); no effect under emulation yet (hard to
      simulate)
    - readable() returns true when data is ready to be read
      (non-blocking support for read())
    - writable() returns true when data can be written (non-blocking
      support for write()) [always true under emulation, since we have
      no buffer size limit]
2012-03-10 23:47:19 +11:00
Tim Allen
cbfbec4dc3 Update to v087r01 release.
byuu says:

Changelog:
- fixes ARM core unaligned memory reads (fixes HNMS2 AI, hopefully completely,
  we'll see though) [Cydrak]
- ARM 40000010 writes are now connected to d2 rather than the timer
- ARM bus_readbyte() removed (would love to do the same for writebyte if
  we can ... then we can drop back to bus_read + bus_write only)
- USART with IObit set acts as a regular gamepad now (don't have this
  hooked up with real hardware, but oh well, it's technically possible
  so there's that)
- OpenGL/GLX will use 30-bit when you have a 30-bit display; no need for
  config file video.depth anymore
2012-03-10 23:37:36 +11:00
1231 changed files with 151584 additions and 130884 deletions

3
.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
purify/*.o
purify/purify
purify/analyze-gba

View File

@@ -1,10 +1,12 @@
include nall/Makefile
nes := nes
snes := snes
gameboy := gameboy
fc := fc
sfc := sfc
gb := gb
gba := gba
profile := accuracy
target := ui
target := ethos
# options += console
@@ -12,7 +14,7 @@ target := ui
c := $(compiler) -std=gnu99
cpp := $(subst cc,++,$(compiler)) -std=gnu++0x
flags := -I. -O3 -fomit-frame-pointer
link :=
link := -s
objects := libco
# profile-guided optimization mode
@@ -28,11 +30,12 @@ endif
# platform
ifeq ($(platform),x)
link += -s -ldl -lX11 -lXext
flags += -march=native
link += -ldl -lX11 -lXext
else ifeq ($(platform),osx)
else ifeq ($(platform),win)
link += $(if $(findstring console,$(options)),-mconsole,-mwindows)
link += -mthreads -s -luuid -lkernel32 -luser32 -lgdi32 -lcomctl32 -lcomdlg32 -lshell32 -lole32
link += -mthreads -luuid -lkernel32 -luser32 -lgdi32 -lcomctl32 -lcomdlg32 -lshell32 -lole32
link += -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc
else
unknown_platform: help;
@@ -90,7 +93,8 @@ sync:
rm -r phoenix/nall
rm -r phoenix/test
archive-all:
tar -cjf bsnes.tar.bz2 base data gameboy libco nall nes obj out phoenix ruby snes target-debugger target-libsnes target-ui Makefile cc.bat purge.bat
archive:
if [ -f bsnes.tar.bz2 ]; then rm bsnes.tar.bz2; fi
tar -cjf bsnes.tar.bz2 `ls`
help:;

File diff suppressed because it is too large Load Diff

View File

@@ -1,29 +1,36 @@
#ifndef BASE_HPP
#define BASE_HPP
#ifndef EMULATOR_HPP
#define EMULATOR_HPP
const char Version[] = "087";
namespace Emulator {
static const char Name[] = "bsnes";
static const char Version[] = "089";
static const char Author[] = "byuu";
static const char License[] = "GPLv3";
}
#include <nall/platform.hpp>
#include <nall/algorithm.hpp>
#include <nall/any.hpp>
#include <nall/array.hpp>
#include <nall/dl.hpp>
#include <nall/dsp.hpp>
#include <nall/endian.hpp>
#include <nall/file.hpp>
#include <nall/function.hpp>
#include <nall/moduloarray.hpp>
#include <nall/priorityqueue.hpp>
#include <nall/property.hpp>
#include <nall/random.hpp>
#include <nall/serializer.hpp>
#include <nall/sha256.hpp>
#include <nall/stdint.hpp>
#include <nall/string.hpp>
#include <nall/utility.hpp>
#include <nall/varint.hpp>
#include <nall/vector.hpp>
#include <nall/stream/memory.hpp>
#include <nall/stream/vector.hpp>
using namespace nall;
#include "interface.hpp"
//debugging function hook:
//no overhead (and no debugger invocation) if not compiled with -DDEBUGGER
//wraps testing of function to allow invocation without a defined callback
@@ -42,8 +49,8 @@ template<typename R, typename... P> struct hook<R (P...)> {
hook(const hook &hook) { callback = hook.callback; }
hook(void *function) { callback = function; }
hook(R (*function)(P...)) { callback = function; }
template<typename C> hook(R (C::*function)(P...), C *object) { callback = { function, object }; }
template<typename C> hook(R (C::*function)(P...) const, C *object) { callback = { function, object }; }
template<typename C> hook(R (C::*function)(P...), C *object) { callback = {function, object}; }
template<typename C> hook(R (C::*function)(P...) const, C *object) { callback = {function, object}; }
template<typename L> hook(const L& function) { callback = function; }
hook& operator=(const hook& hook) { callback = hook.callback; return *this; }
@@ -55,15 +62,15 @@ template<typename R, typename... P> struct hook<R (P...)> {
#define privileged private
#endif
typedef int1_t int1;
typedef int2_t int2;
typedef int3_t int3;
typedef int4_t int4;
typedef int5_t int5;
typedef int6_t int6;
typedef int7_t int7;
typedef int8_t int8;
typedef int9_t int9;
typedef int1_t int1;
typedef int2_t int2;
typedef int3_t int3;
typedef int4_t int4;
typedef int5_t int5;
typedef int6_t int6;
typedef int7_t int7;
typedef int8_t int8;
typedef int9_t int9;
typedef int10_t int10;
typedef int11_t int11;
typedef int12_t int12;
@@ -89,15 +96,15 @@ typedef int31_t int31;
typedef int32_t int32;
typedef int64_t int64;
typedef uint1_t uint1;
typedef uint2_t uint2;
typedef uint3_t uint3;
typedef uint4_t uint4;
typedef uint5_t uint5;
typedef uint6_t uint6;
typedef uint7_t uint7;
typedef uint8_t uint8;
typedef uint9_t uint9;
typedef uint1_t uint1;
typedef uint2_t uint2;
typedef uint3_t uint3;
typedef uint4_t uint4;
typedef uint5_t uint5;
typedef uint6_t uint6;
typedef uint7_t uint7;
typedef uint8_t uint8;
typedef uint9_t uint9;
typedef uint10_t uint10;
typedef uint11_t uint11;
typedef uint12_t uint12;
@@ -124,6 +131,6 @@ typedef uint32_t uint32;
typedef uint_t<33> uint33;
typedef uint64_t uint64;
typedef varuint_t varuint;
typedef varuint_t<unsigned> varuint;
#endif

108
bsnes/emulator/interface.hpp Executable file
View File

@@ -0,0 +1,108 @@
#ifndef EMULATOR_INTERFACE_HPP
#define EMULATOR_INTERFACE_HPP
namespace Emulator {
struct Interface {
struct Information {
string name;
unsigned width;
unsigned height;
bool overscan;
double aspectRatio;
bool resettable;
} information;
struct Media {
unsigned id;
string name;
string type;
string path;
string extension;
};
vector<Media> firmware;
vector<Media> media;
struct Memory {
unsigned id;
string name;
};
vector<Memory> memory;
struct Device {
unsigned id;
unsigned portmask;
string name;
struct Input {
unsigned id;
unsigned type; //0 = digital, 1 = analog
string name;
unsigned guid;
};
vector<Input> input;
vector<unsigned> order;
};
struct Port {
unsigned id;
string name;
vector<Device> device;
};
vector<Port> port;
struct Bind {
virtual void loadRequest(unsigned, const string&) {}
virtual void loadRequest(unsigned, const string&, const string&, const string&) {}
virtual uint32_t videoColor(unsigned, uint16_t, uint16_t, uint16_t) { return 0u; }
virtual void videoRefresh(const uint32_t*, unsigned, unsigned, unsigned) {}
virtual void audioSample(int16_t, int16_t) {}
virtual int16_t inputPoll(unsigned, unsigned, unsigned) { return 0; }
virtual unsigned dipSettings(const XML::Node&) { return 0; }
virtual string path(unsigned) { return ""; }
} *bind;
//callback bindings (provided by user interface)
void loadRequest(unsigned id, const string &path) { return bind->loadRequest(id, path); }
void loadRequest(unsigned id, const string &name, const string &type, const string &path) { return bind->loadRequest(id, name, type, path); }
uint32_t videoColor(unsigned source, uint16_t red, uint16_t green, uint16_t blue) { return bind->videoColor(source, red, green, blue); }
void videoRefresh(const uint32_t *data, unsigned pitch, unsigned width, unsigned height) { return bind->videoRefresh(data, pitch, width, height); }
void audioSample(int16_t lsample, int16_t rsample) { return bind->audioSample(lsample, rsample); }
int16_t inputPoll(unsigned port, unsigned device, unsigned input) { return bind->inputPoll(port, device, input); }
unsigned dipSettings(const XML::Node &node) { return bind->dipSettings(node); }
string path(unsigned group) { return bind->path(group); }
//information
virtual double videoFrequency() = 0;
virtual double audioFrequency() = 0;
//media interface
virtual bool loaded() { return false; }
virtual string sha256() { return ""; }
virtual unsigned group(unsigned id) { return 0u; }
virtual void load(unsigned id, const stream &memory, const string &markup = "") {}
virtual void save(unsigned id, const stream &memory) {}
virtual void unload() {}
//system interface
virtual void connect(unsigned port, unsigned device) {}
virtual void power() {}
virtual void reset() {}
virtual void run() {}
//state functions
virtual serializer serialize() = 0;
virtual bool unserialize(serializer&) = 0;
//cheat functions
virtual void cheatSet(const lstring& = lstring{}) {}
//utility functions
virtual void updatePalette() {}
Interface() : bind(nullptr) {}
};
}
#endif

16
bsnes/fc/Makefile Executable file
View File

@@ -0,0 +1,16 @@
fc_objects := fc-interface fc-system fc-scheduler fc-input
fc_objects += fc-memory fc-cartridge fc-cpu fc-apu fc-ppu
fc_objects += fc-cheat fc-video
objects += $(fc_objects)
obj/fc-interface.o: $(fc)/interface/interface.cpp $(call rwildcard,$(fc)/interface/)
obj/fc-system.o: $(fc)/system/system.cpp $(call rwildcard,$(fc)/system/)
obj/fc-scheduler.o: $(fc)/scheduler/scheduler.cpp $(call rwildcard,$(fc)/scheduler/)
obj/fc-input.o: $(fc)/input/input.cpp $(call rwildcard,$(fc)/input/)
obj/fc-memory.o: $(fc)/memory/memory.cpp $(call rwildcard,$(fc)/memory/)
obj/fc-cartridge.o: $(fc)/cartridge/cartridge.cpp $(call rwildcard,$(fc)/cartridge/)
obj/fc-cpu.o: $(fc)/cpu/cpu.cpp $(call rwildcard,$(fc)/cpu/)
obj/fc-apu.o: $(fc)/apu/apu.cpp $(call rwildcard,$(fc)/apu/)
obj/fc-ppu.o: $(fc)/ppu/ppu.cpp $(call rwildcard,$(fc)/ppu/)
obj/fc-cheat.o: $(fc)/cheat/cheat.cpp $(call rwildcard,$(fc)/cheat/)
obj/fc-video.o: $(fc)/video/video.cpp $(call rwildcard,$(fc)/video/)

View File

@@ -1,6 +1,6 @@
#include <nes/nes.hpp>
#include <fc/fc.hpp>
namespace NES {
namespace Famicom {
#include "envelope.cpp"
#include "sweep.cpp"
@@ -60,7 +60,7 @@ void APU::main() {
//output = filter.run_lopass(output);
output = sclamp<16>(output);
interface->audioSample(output);
interface->audioSample(output, output);
tick();
}
@@ -92,7 +92,7 @@ void APU::power() {
}
void APU::reset() {
Processor::create(APU::Main, 21477272);
create(APU::Main, 21477272);
pulse[0].reset();
pulse[1].reset();

View File

@@ -1,4 +1,4 @@
struct APU : Processor {
struct APU : Thread {
static void Main();
void main();
void tick();

View File

@@ -1,5 +1,5 @@
void APU::serialize(serializer &s) {
Processor::serialize(s);
Thread::serialize(s);
filter.serialize(s);

View File

@@ -111,7 +111,7 @@ void serialize(serializer &s) {
s.integer(irq_latch);
}
BandaiFCG(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
BandaiFCG(XML::Document &document, const stream &memory) : Board(document, memory) {
}
};

View File

@@ -0,0 +1,167 @@
#include "bandai-fcg.cpp"
#include "konami-vrc1.cpp"
#include "konami-vrc2.cpp"
#include "konami-vrc3.cpp"
#include "konami-vrc4.cpp"
#include "konami-vrc6.cpp"
#include "konami-vrc7.cpp"
#include "nes-axrom.cpp"
#include "nes-bnrom.cpp"
#include "nes-cnrom.cpp"
#include "nes-exrom.cpp"
#include "nes-fxrom.cpp"
#include "nes-gxrom.cpp"
#include "nes-hkrom.cpp"
#include "nes-nrom.cpp"
#include "nes-pxrom.cpp"
#include "nes-sxrom.cpp"
#include "nes-txrom.cpp"
#include "nes-uxrom.cpp"
#include "sunsoft-5b.cpp"
uint8 Board::Memory::read(unsigned addr) const {
return data[mirror(addr, size)];
}
void Board::Memory::write(unsigned addr, uint8 byte) {
if(writable) data[mirror(addr, size)] = byte;
}
unsigned Board::mirror(unsigned addr, unsigned size) {
unsigned base = 0;
if(size) {
unsigned mask = 1 << 23;
while(addr >= size) {
while(!(addr & mask)) mask >>= 1;
addr -= mask;
if(size > mask) {
size -= mask;
base += mask;
}
mask >>= 1;
}
base += addr;
}
return base;
}
void Board::main() {
while(true) {
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
}
cartridge.clock += 12 * 4095;
tick();
}
}
void Board::tick() {
cartridge.clock += 12;
if(cartridge.clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(cpu.thread);
}
uint8 Board::chr_read(unsigned addr) {
if(chrram.size) return chrram.data[mirror(addr, chrram.size)];
if(chrrom.size) return chrrom.data[mirror(addr, chrrom.size)];
return 0u;
}
void Board::chr_write(unsigned addr, uint8 data) {
if(chrram.size) chrram.data[mirror(addr, chrram.size)] = data;
}
Board::Memory& Board::memory() {
return prgram;
}
void Board::power() {
}
void Board::reset() {
}
void Board::serialize(serializer &s) {
if(prgram.size) s.array(prgram.data, prgram.size);
if(chrram.size) s.array(chrram.data, chrram.size);
}
Board::Board(XML::Document &document, const stream &memory) {
auto &cartridge = document["cartridge"];
information.type = cartridge["board"]["type"].data;
information.battery = cartridge["prg"]["ram"]["nonvolatile"].data == "true";
prgrom.size = numeral(cartridge["prg"]["rom"]["size"].data);
prgram.size = numeral(cartridge["prg"]["ram"]["size"].data);
chrrom.size = numeral(cartridge["chr"]["rom"]["size"].data);
chrram.size = numeral(cartridge["chr"]["ram"]["size"].data);
if(prgrom.size) prgrom.data = new uint8[prgrom.size]();
if(prgram.size) prgram.data = new uint8[prgram.size]();
if(chrrom.size) chrrom.data = new uint8[chrrom.size]();
if(chrram.size) chrram.data = new uint8[chrram.size]();
if(prgrom.size) memory.read(prgrom.data, prgrom.size);
if(chrrom.size) memory.read(chrrom.data, chrrom.size);
prgram.writable = true;
chrram.writable = true;
}
Board::~Board() {
}
Board* Board::load(const string &markup, const stream &memory) {
XML::Document document(markup);
string type = document["cartridge"]["board"]["type"].data;
if(type == "BANDAI-FCG") return new BandaiFCG(document, memory);
if(type == "KONAMI-VRC-1") return new KonamiVRC1(document, memory);
if(type == "KONAMI-VRC-2") return new KonamiVRC2(document, memory);
if(type == "KONAMI-VRC-3") return new KonamiVRC3(document, memory);
if(type == "KONAMI-VRC-4") return new KonamiVRC4(document, memory);
if(type == "KONAMI-VRC-6") return new KonamiVRC6(document, memory);
if(type == "KONAMI-VRC-7") return new KonamiVRC7(document, memory);
if(type == "NES-AMROM" ) return new NES_AxROM(document, memory);
if(type == "NES-ANROM" ) return new NES_AxROM(document, memory);
if(type == "NES-AN1ROM" ) return new NES_AxROM(document, memory);
if(type == "NES-AOROM" ) return new NES_AxROM(document, memory);
if(type == "NES-BNROM" ) return new NES_BNROM(document, memory);
if(type == "NES-CNROM" ) return new NES_CNROM(document, memory);
if(type == "NES-EKROM" ) return new NES_ExROM(document, memory);
if(type == "NES-ELROM" ) return new NES_ExROM(document, memory);
if(type == "NES-ETROM" ) return new NES_ExROM(document, memory);
if(type == "NES-EWROM" ) return new NES_ExROM(document, memory);
if(type == "NES-FJROM" ) return new NES_FxROM(document, memory);
if(type == "NES-FKROM" ) return new NES_FxROM(document, memory);
if(type == "NES-GNROM" ) return new NES_GxROM(document, memory);
if(type == "NES-MHROM" ) return new NES_GxROM(document, memory);
if(type == "NES-HKROM" ) return new NES_HKROM(document, memory);
if(type == "NES-NROM-128") return new NES_NROM(document, memory);
if(type == "NES-NROM-256") return new NES_NROM(document, memory);
if(type == "NES-PEEOROM" ) return new NES_PxROM(document, memory);
if(type == "NES-PNROM" ) return new NES_PxROM(document, memory);
if(type == "NES-SNROM" ) return new NES_SxROM(document, memory);
if(type == "NES-SXROM" ) return new NES_SxROM(document, memory);
if(type == "NES-TLROM" ) return new NES_TxROM(document, memory);
if(type == "NES-UNROM" ) return new NES_UxROM(document, memory);
if(type == "NES-UOROM" ) return new NES_UxROM(document, memory);
if(type == "SUNSOFT-5B" ) return new Sunsoft5B(document, memory);
return nullptr;
}

View File

@@ -31,10 +31,10 @@ struct Board {
virtual void reset();
virtual void serialize(serializer&);
Board(XML::Node &board, const uint8_t *data, unsigned size);
Board(XML::Document &document, const stream &memory);
virtual ~Board();
static Board* load(const string &markup, const uint8_t *data, unsigned size);
static Board* load(const string &markup, const stream &memory);
struct Information {
string type;

View File

@@ -34,7 +34,7 @@ void serialize(serializer &s) {
vrc1.serialize(s);
}
KonamiVRC1(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), vrc1(*this) {
KonamiVRC1(XML::Document &document, const stream &memory) : Board(document, memory), vrc1(*this) {
}
};

View File

@@ -49,9 +49,9 @@ void serialize(serializer &s) {
vrc2.serialize(s);
}
KonamiVRC2(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), vrc2(*this) {
settings.pinout.a0 = 1 << decimal(board["chip"]["pinout"]["a0"].data);
settings.pinout.a1 = 1 << decimal(board["chip"]["pinout"]["a1"].data);
KonamiVRC2(XML::Document &document, const stream &memory) : Board(document, memory), vrc2(*this) {
settings.pinout.a0 = 1 << decimal(document["cartridge"]["chip"]["pinout"]["a0"].data);
settings.pinout.a1 = 1 << decimal(document["cartridge"]["chip"]["pinout"]["a1"].data);
}
};

View File

@@ -50,8 +50,8 @@ void serialize(serializer &s) {
vrc3.serialize(s);
}
KonamiVRC3(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), vrc3(*this) {
settings.mirror = board["mirror"]["mode"].data == "vertical" ? 1 : 0;
KonamiVRC3(XML::Document &document, const stream &memory) : Board(document, memory), vrc3(*this) {
settings.mirror = document["cartridge"]["mirror"]["mode"].data == "vertical" ? 1 : 0;
}
};

View File

@@ -53,9 +53,9 @@ void serialize(serializer &s) {
vrc4.serialize(s);
}
KonamiVRC4(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), vrc4(*this) {
settings.pinout.a0 = 1 << decimal(board["chip"]["pinout"]["a0"].data);
settings.pinout.a1 = 1 << decimal(board["chip"]["pinout"]["a1"].data);
KonamiVRC4(XML::Document &document, const stream &memory) : Board(document, memory), vrc4(*this) {
settings.pinout.a0 = 1 << decimal(document["cartridge"]["chip"]["pinout"]["a0"].data);
settings.pinout.a1 = 1 << decimal(document["cartridge"]["chip"]["pinout"]["a1"].data);
}
};

View File

@@ -36,7 +36,7 @@ void main() { vrc6.main(); }
void power() { vrc6.power(); }
void reset() { vrc6.reset(); }
KonamiVRC6(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), vrc6(*this) {
KonamiVRC6(XML::Document &document, const stream &memory) : Board(document, memory), vrc6(*this) {
}
};

View File

@@ -41,7 +41,7 @@ void serialize(serializer &s) {
vrc7.serialize(s);
}
KonamiVRC7(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), vrc7(*this) {
KonamiVRC7(XML::Document &document, const stream &memory) : Board(document, memory), vrc7(*this) {
}
};

View File

@@ -45,7 +45,7 @@ void serialize(serializer &s) {
s.integer(mirror_select);
}
NES_AxROM(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
NES_AxROM(XML::Document &document, const stream &memory) : Board(document, memory) {
}
};

View File

@@ -45,8 +45,8 @@ void serialize(serializer &s) {
s.integer(prg_bank);
}
NES_BNROM(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
settings.mirror = board["mirror"]["mode"].data == "vertical" ? 1 : 0;
NES_BNROM(XML::Document &document, const stream &memory) : Board(document, memory) {
settings.mirror = document["cartridge"]["mirror"]["mode"].data == "vertical" ? 1 : 0;
}
};

View File

@@ -47,8 +47,8 @@ void serialize(serializer &s) {
s.integer(chr_bank);
}
NES_CNROM(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
settings.mirror = board["mirror"]["mode"].data == "vertical" ? 1 : 0;
NES_CNROM(XML::Document &document, const stream &memory) : Board(document, memory) {
settings.mirror = document["cartridge"]["mirror"]["mode"].data == "vertical" ? 1 : 0;
}
};

View File

@@ -46,7 +46,7 @@ void serialize(serializer &s) {
mmc5.serialize(s);
}
NES_ExROM(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), mmc5(*this) {
NES_ExROM(XML::Document &document, const stream &memory) : Board(document, memory), mmc5(*this) {
revision = Revision::ELROM;
}

View File

@@ -84,7 +84,7 @@ void serialize(serializer &s) {
s.array(latch);
}
NES_FxROM(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
NES_FxROM(XML::Document &document, const stream &memory) : Board(document, memory) {
revision = Revision::FKROM;
}

View File

@@ -54,8 +54,8 @@ void serialize(serializer &s) {
s.integer(chr_bank);
}
NES_GxROM(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
settings.mirror = board["mirror"]["mode"].data == "vertical" ? 1 : 0;
NES_GxROM(XML::Document &document, const stream &memory) : Board(document, memory) {
settings.mirror = document["cartridge"]["mirror"]["mode"].data == "vertical" ? 1 : 0;
}
};

View File

@@ -42,7 +42,7 @@ void serialize(serializer &s) {
mmc6.serialize(s);
}
NES_HKROM(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), mmc6(*this) {
NES_HKROM(XML::Document &document, const stream &memory) : Board(document, memory), mmc6(*this) {
}
};

View File

@@ -36,8 +36,8 @@ void serialize(serializer &s) {
Board::serialize(s);
}
NES_NROM(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
settings.mirror = board["mirror"]["mode"].data == "vertical" ? 1 : 0;
NES_NROM(XML::Document &document, const stream &memory) : Board(document, memory) {
settings.mirror = document["cartridge"]["mirror"]["mode"].data == "vertical" ? 1 : 0;
}
};

View File

@@ -90,7 +90,7 @@ void serialize(serializer &s) {
s.array(latch);
}
NES_PxROM(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
NES_PxROM(XML::Document &document, const stream &memory) : Board(document, memory) {
revision = Revision::PNROM;
}

View File

@@ -94,7 +94,7 @@ void serialize(serializer &s) {
mmc1.serialize(s);
}
NES_SxROM(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), mmc1(*this) {
NES_SxROM(XML::Document &document, const stream &memory) : Board(document, memory), mmc1(*this) {
revision = Revision::SXROM;
}

View File

@@ -60,7 +60,7 @@ void serialize(serializer &s) {
mmc3.serialize(s);
}
NES_TxROM(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), mmc3(*this) {
NES_TxROM(XML::Document &document, const stream &memory) : Board(document, memory), mmc3(*this) {
revision = Revision::TLROM;
}

View File

@@ -48,8 +48,8 @@ void serialize(serializer &s) {
s.integer(prg_bank);
}
NES_UxROM(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
settings.mirror = board["mirror"]["mode"].data == "vertical" ? 1 : 0;
NES_UxROM(XML::Document &document, const stream &memory) : Board(document, memory) {
settings.mirror = document["cartridge"]["mirror"]["mode"].data == "vertical" ? 1 : 0;
}
};

View File

@@ -220,7 +220,7 @@ void serialize(serializer &s) {
pulse[2].serialize(s);
}
Sunsoft5B(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
Sunsoft5B(XML::Document &document, const stream &memory) : Board(document, memory) {
}
};

View File

@@ -1,8 +1,7 @@
#include <nes/nes.hpp>
#include <fc/fc.hpp>
namespace NES {
namespace Famicom {
#include "ines.cpp"
#include "chip/chip.cpp"
#include "board/board.cpp"
Cartridge cartridge;
@@ -15,18 +14,25 @@ void Cartridge::main() {
board->main();
}
void Cartridge::load(const string &markup, const uint8_t *data, unsigned size) {
if((size & 0xff) == 0) {
sha256 = nall::sha256(data, size);
board = Board::load(markup, data, size);
} else {
//unsigned crc32 = crc32_calculate(data + 16, size - 16);
//print(hex<8>(crc32), "\n");
sha256 = nall::sha256(data + 16, size - 16);
board = Board::load(!markup.empty() ? markup : iNES(data, size), data + 16, size - 16);
}
void Cartridge::load(const string &markup, const stream &memory) {
information.markup = markup;
board = Board::load(markup, memory);
if(board == nullptr) return;
interface->memory.append({ID::RAM, "save.ram"});
sha256_ctx sha;
uint8_t hash[32];
sha256_init(&sha);
sha256_chunk(&sha, board->prgrom.data, board->prgrom.size);
sha256_chunk(&sha, board->chrrom.data, board->chrrom.size);
sha256_final(&sha);
sha256_hash(&sha, hash);
string result;
for(auto &byte : hash) result.append(hex<2>(byte));
sha256 = result;
system.load();
loaded = true;
}
@@ -78,7 +84,7 @@ void Cartridge::scanline(unsigned y) {
}
void Cartridge::serialize(serializer &s) {
Processor::serialize(s);
Thread::serialize(s);
return board->serialize(s);
}

View File

@@ -1,11 +1,11 @@
#include "chip/chip.hpp"
#include "board/board.hpp"
struct Cartridge : Processor, property<Cartridge> {
struct Cartridge : Thread, property<Cartridge> {
static void Main();
void main();
void load(const string &markup, const uint8_t *data, unsigned size);
void load(const string &markup, const stream &memory);
void unload();
unsigned ram_size();
@@ -17,6 +17,10 @@ struct Cartridge : Processor, property<Cartridge> {
readonly<bool> loaded;
readonly<string> sha256;
struct Information {
string markup;
} information;
void serialize(serializer&);
Cartridge();

View File

@@ -1,6 +1,6 @@
#include <nes/nes.hpp>
#include <fc/fc.hpp>
namespace NES {
namespace Famicom {
Cheat cheat;

View File

@@ -1,40 +1,30 @@
#include <nes/nes.hpp>
#include <fc/fc.hpp>
namespace NES {
namespace Famicom {
#include "core/core.cpp"
#include "memory/memory.cpp"
#include "timing.cpp"
#include "serialization.cpp"
CPU cpu;
void CPU::Main() {
cpu.main();
}
void CPU::main() {
//trace = true;
//FILE *fp = fopen("/home/byuu/Desktop/log.txt", "wb");
unsigned lpc = 0xffff;
void CPU::Enter() {
while(true) {
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
}
if(status.interrupt_pending) {
interrupt();
continue;
}
if(trace) {
if(lpc != regs.pc) { print(disassemble(), "\n"); } lpc = regs.pc;
//if(lpc != regs.pc) { fprintf(fp, "%s\n", (const char*)disassemble()); fflush(fp); } lpc = regs.pc;
}
op_exec();
cpu.main();
}
}
void CPU::main() {
if(status.interrupt_pending) {
interrupt();
return;
}
exec();
}
void CPU::add_clocks(unsigned clocks) {
apu.clock -= clocks;
if(apu.clock < 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(apu.thread);
@@ -47,11 +37,7 @@ void CPU::add_clocks(unsigned clocks) {
}
void CPU::power() {
regs.a = 0x00;
regs.x = 0x00;
regs.y = 0x00;
regs.s = 0x00;
regs.p = 0x04;
R6502::power();
for(unsigned addr = 0; addr < 0x0800; addr++) ram[addr] = 0xff;
ram[0x0008] = 0xf7;
@@ -61,11 +47,8 @@ void CPU::power() {
}
void CPU::reset() {
Processor::create(CPU::Main, 21477272);
regs.mdr = 0x00;
regs.s -= 3;
regs.p.i = 1;
R6502::reset();
create(CPU::Enter, 21477272);
regs.pc = bus.read(0xfffc) << 0;
regs.pc |= bus.read(0xfffd) << 8;
@@ -87,16 +70,8 @@ void CPU::reset() {
status.controller_port1 = 0;
}
uint8 CPU::mdr() const {
return regs.mdr;
}
void CPU::set_rdy_line(bool line) {
status.rdy_line = line;
}
void CPU::set_rdy_addr(optional<uint16> addr) {
status.rdy_addr = addr;
uint8 CPU::debugger_read(uint16 addr) {
return bus.read(addr);
}
uint8 CPU::ram_read(uint16 addr) {
@@ -132,11 +107,4 @@ void CPU::write(uint16 addr, uint8 data) {
return apu.write(addr, data);
}
void CPU::oam_dma() {
for(unsigned n = 0; n < 256; n++) {
uint8 data = op_read((status.oam_dma_page << 8) + n);
op_write(0x2004, data);
}
}
}

View File

@@ -1,6 +1,4 @@
struct CPU : Processor {
#include "core/core.hpp"
#include "memory/memory.hpp"
struct CPU : Processor::R6502, Thread {
uint8 ram[0x0800];
struct Status {
@@ -21,16 +19,14 @@ struct CPU : Processor {
unsigned controller_port1;
} status;
static void Main();
static void Enter();
void main();
void add_clocks(unsigned clocks);
void power();
void reset();
uint8 mdr() const;
void set_rdy_line(bool);
void set_rdy_addr(optional<uint16>);
uint8 debugger_read(uint16 addr);
uint8 ram_read(uint16 addr);
void ram_write(uint16 addr, uint8 data);
@@ -38,12 +34,22 @@ struct CPU : Processor {
uint8 read(uint16 addr);
void write(uint16 addr, uint8 data);
void oam_dma();
void serialize(serializer&);
//internal:
bool trace;
//timing.cpp
uint8 op_read(uint16 addr);
void op_write(uint16 addr, uint8 data);
void last_cycle();
void nmi(uint16 &vector);
void oam_dma();
void set_nmi_line(bool);
void set_irq_line(bool);
void set_irq_apu_line(bool);
void set_rdy_line(bool);
void set_rdy_addr(optional<uint16>);
};
extern CPU cpu;

View File

@@ -1,27 +1,9 @@
void CPU::serialize(serializer &s) {
Processor::serialize(s);
R6502::serialize(s);
Thread::serialize(s);
s.array(ram);
s.integer(regs.mdr);
s.integer(regs.pc);
s.integer(regs.a);
s.integer(regs.x);
s.integer(regs.y);
s.integer(regs.s);
s.integer(regs.p.n);
s.integer(regs.p.v);
s.integer(regs.p.d);
s.integer(regs.p.i);
s.integer(regs.p.z);
s.integer(regs.p.c);
s.integer(abs.w);
s.integer(iabs.w);
s.integer(rd);
s.integer(zp);
s.integer(aa);
s.integer(status.interrupt_pending);
s.integer(status.nmi_pending);
s.integer(status.nmi_line);

63
bsnes/fc/cpu/timing.cpp Executable file
View File

@@ -0,0 +1,63 @@
uint8 CPU::op_read(uint16 addr) {
if(status.oam_dma_pending) {
status.oam_dma_pending = false;
op_read(addr);
oam_dma();
}
while(status.rdy_line == 0) {
regs.mdr = bus.read(status.rdy_addr ? status.rdy_addr() : addr);
add_clocks(12);
}
regs.mdr = bus.read(addr);
add_clocks(12);
return regs.mdr;
}
void CPU::op_write(uint16 addr, uint8 data) {
bus.write(addr, regs.mdr = data);
add_clocks(12);
}
void CPU::last_cycle() {
status.interrupt_pending = ((status.irq_line | status.irq_apu_line) & ~regs.p.i) | status.nmi_pending;
}
void CPU::nmi(uint16 &vector) {
if(status.nmi_pending) {
status.nmi_pending = false;
vector = 0xfffa;
}
}
void CPU::oam_dma() {
for(unsigned n = 0; n < 256; n++) {
uint8 data = op_read((status.oam_dma_page << 8) + n);
op_write(0x2004, data);
}
}
void CPU::set_nmi_line(bool line) {
//edge-sensitive (0->1)
if(!status.nmi_line && line) status.nmi_pending = true;
status.nmi_line = line;
}
void CPU::set_irq_line(bool line) {
//level-sensitive
status.irq_line = line;
}
void CPU::set_irq_apu_line(bool line) {
//level-sensitive
status.irq_apu_line = line;
}
void CPU::set_rdy_line(bool line) {
status.rdy_line = line;
}
void CPU::set_rdy_addr(optional<uint16> addr) {
status.rdy_addr = addr;
}

62
bsnes/fc/fc.hpp Executable file
View File

@@ -0,0 +1,62 @@
#ifndef FC_HPP
#define FC_HPP
#include <emulator/emulator.hpp>
#include <processor/r6502/r6502.hpp>
namespace Famicom {
namespace Info {
static const char Name[] = "bnes";
static const unsigned SerializerVersion = 2;
}
}
/*
bnes - Famicom emulator
authors: byuu, Ryphecha
license: GPLv3
project started: 2011-09-05
*/
#include <libco/libco.h>
namespace Famicom {
struct Thread {
cothread_t thread;
unsigned frequency;
int64 clock;
inline void create(void (*entrypoint)(), unsigned frequency) {
if(thread) co_delete(thread);
thread = co_create(65536 * sizeof(void*), entrypoint);
this->frequency = frequency;
clock = 0;
}
inline void serialize(serializer &s) {
s.integer(frequency);
s.integer(clock);
}
inline Thread() : thread(nullptr) {
}
inline ~Thread() {
if(thread) co_delete(thread);
}
};
#include <fc/system/system.hpp>
#include <fc/scheduler/scheduler.hpp>
#include <fc/input/input.hpp>
#include <fc/memory/memory.hpp>
#include <fc/cartridge/cartridge.hpp>
#include <fc/cpu/cpu.hpp>
#include <fc/apu/apu.hpp>
#include <fc/ppu/ppu.hpp>
#include <fc/cheat/cheat.hpp>
#include <fc/video/video.hpp>
#include <fc/interface/interface.hpp>
}
#endif

View File

@@ -1,6 +1,6 @@
#include <nes/nes.hpp>
#include <fc/fc.hpp>
namespace NES {
namespace Famicom {
#include "serialization.cpp"
Input input;

121
bsnes/fc/interface/interface.cpp Executable file
View File

@@ -0,0 +1,121 @@
#include <fc/fc.hpp>
namespace Famicom {
Interface *interface = nullptr;
double Interface::videoFrequency() {
return 21477272.0 / (262.0 * 1364.0 - 4.0);
}
double Interface::audioFrequency() {
return 21477272.0 / 12.0;
}
bool Interface::loaded() {
return cartridge.loaded();
}
string Interface::sha256() {
return cartridge.sha256();
}
void Interface::load(unsigned id, const stream &stream, const string &markup) {
if(id == ID::ROM) {
cartridge.load(markup, stream);
system.power();
input.connect(0, Input::Device::Joypad);
input.connect(1, Input::Device::Joypad);
}
if(id == ID::RAM) {
stream.read(cartridge.ram_data(), min(stream.size(), cartridge.ram_size()));
}
}
void Interface::save(unsigned id, const stream &stream) {
if(id == ID::RAM) {
stream.write(cartridge.ram_data(), cartridge.ram_size());
}
}
void Interface::unload() {
cartridge.unload();
}
void Interface::power() {
system.power();
}
void Interface::reset() {
system.reset();
}
void Interface::run() {
system.run();
}
serializer Interface::serialize() {
system.runtosave();
return system.serialize();
}
bool Interface::unserialize(serializer &s) {
return system.unserialize(s);
}
void Interface::cheatSet(const lstring &list) {
cheat.reset();
for(auto &code : list) {
lstring codelist = code.split("+");
for(auto &part : codelist) {
unsigned addr, data, comp;
if(Cheat::decode(part, addr, data, comp)) cheat.append({addr, data, comp});
}
}
cheat.synchronize();
}
void Interface::updatePalette() {
video.generate_palette();
}
Interface::Interface() {
interface = this;
information.name = "Famicom";
information.width = 256;
information.height = 240;
information.overscan = true;
information.aspectRatio = 8.0 / 7.0;
information.resettable = true;
media.append({ID::ROM, "Famicom", "sys", "program.rom", "fc"});
{
Device device{0, ID::Port1 | ID::Port2, "Controller"};
device.input.append({0, 0, "A" });
device.input.append({1, 0, "B" });
device.input.append({2, 0, "Select"});
device.input.append({3, 0, "Start" });
device.input.append({4, 0, "Up" });
device.input.append({5, 0, "Down" });
device.input.append({6, 0, "Left" });
device.input.append({7, 0, "Right" });
device.order = {4, 5, 6, 7, 1, 0, 2, 3};
this->device.append(device);
}
port.append({0, "Port 1"});
port.append({1, "Port 2"});
for(auto &device : this->device) {
for(auto &port : this->port) {
if(device.portmask & (1 << port.id)) {
port.device.append(device);
}
}
}
}
}

View File

@@ -0,0 +1,48 @@
#ifndef FC_HPP
namespace Famicom {
#endif
struct ID {
enum : unsigned {
ROM,
RAM,
};
enum : unsigned {
Port1 = 1,
Port2 = 2,
};
};
struct Interface : Emulator::Interface {
double videoFrequency();
double audioFrequency();
bool loaded();
string sha256();
void load(unsigned id, const stream &stream, const string &markup = "");
void save(unsigned id, const stream &stream);
void unload();
void power();
void reset();
void run();
serializer serialize();
bool unserialize(serializer&);
void cheatSet(const lstring&);
void updatePalette();
Interface();
private:
vector<Device> device;
};
extern Interface *interface;
#ifndef FC_HPP
}
#endif

View File

@@ -1,6 +1,6 @@
#include <nes/nes.hpp>
#include <fc/fc.hpp>
namespace NES {
namespace Famicom {
Bus bus;

View File

@@ -1,6 +1,6 @@
#include <nes/nes.hpp>
#include <fc/fc.hpp>
namespace NES {
namespace Famicom {
#include "serialization.cpp"
PPU ppu;
@@ -47,7 +47,6 @@ void PPU::scanline() {
void PPU::frame() {
status.field ^= 1;
interface->videoRefresh(buffer);
scheduler.exit(Scheduler::ExitReason::FrameEvent);
}
@@ -282,7 +281,7 @@ void PPU::scrolly_increment() {
//
void PPU::raster_pixel() {
uint16 *output = buffer + status.ly * 256;
uint32 *output = buffer + status.ly * 256;
unsigned mask = 0x8000 >> (status.xaddr + (status.lx & 7));
unsigned palette = 0, object_palette = 0;
@@ -325,7 +324,7 @@ void PPU::raster_pixel() {
}
if(raster_enable() == false) palette = 0;
output[status.lx] = (status.emphasis << 6) | cgram_read(palette);
output[status.lx] = video.palette[(status.emphasis << 6) | cgram_read(palette)];
}
void PPU::raster_sprite() {

View File

@@ -1,4 +1,4 @@
struct PPU : Processor {
struct PPU : Thread {
static void Main();
void main();
void tick();
@@ -98,7 +98,7 @@ struct PPU : Processor {
} oam[8], soam[8];
} raster;
uint16 buffer[256 * 262];
uint32 buffer[256 * 262];
uint8 ciram[2048];
uint8 cgram[32];
uint8 oam[256];

View File

@@ -1,5 +1,5 @@
void PPU::serialize(serializer &s) {
Processor::serialize(s);
Thread::serialize(s);
s.integer(status.mdr);

View File

@@ -1,6 +1,6 @@
#include <nes/nes.hpp>
#include <fc/fc.hpp>
namespace NES {
namespace Famicom {
Scheduler scheduler;

View File

@@ -1,13 +1,14 @@
serializer System::serialize() {
serializer s(serialize_size);
unsigned signature = 0x31545342, version = Info::SerializerVersion, crc32 = 0;
char description[512];
unsigned signature = 0x31545342, version = Info::SerializerVersion;
char hash[64], description[512];
memcpy(&hash, (const char*)cartridge.sha256(), 64);
memset(&description, 0, sizeof description);
s.integer(signature);
s.integer(version);
s.integer(crc32);
s.array(hash);
s.array(description);
serialize_all(s);
@@ -15,17 +16,16 @@ serializer System::serialize() {
}
bool System::unserialize(serializer &s) {
unsigned signature, version, crc32;
char description[512];
unsigned signature, version;
char hash[64], description[512];
s.integer(signature);
s.integer(version);
s.integer(crc32);
s.array(hash);
s.array(description);
if(signature != 0x31545342) return false;
if(version != Info::SerializerVersion) return false;
//if(crc32 != 0) return false;
power();
serialize_all(s);
@@ -47,12 +47,12 @@ void System::serialize_all(serializer &s) {
void System::serialize_init() {
serializer s;
unsigned signature = 0, version = 0, crc32 = 0;
char description[512];
unsigned signature = 0, version = 0;
char hash[64], description[512];
s.integer(signature);
s.integer(version);
s.integer(crc32);
s.array(hash);
s.array(description);
serialize_all(s);

View File

@@ -1,12 +1,15 @@
#include <nes/nes.hpp>
#include <fc/fc.hpp>
namespace NES {
namespace Famicom {
#include "serialization.cpp"
System system;
void System::run() {
scheduler.enter();
if(scheduler.exit_reason() == Scheduler::ExitReason::FrameEvent) {
interface->videoRefresh(ppu.buffer, 4 * 256, 256, 240);
}
}
void System::runtosave() {
@@ -32,7 +35,9 @@ void System::runthreadtosave() {
while(true) {
scheduler.enter();
if(scheduler.exit_reason() == Scheduler::ExitReason::SynchronizeEvent) break;
if(scheduler.exit_reason() == Scheduler::ExitReason::FrameEvent);
if(scheduler.exit_reason() == Scheduler::ExitReason::FrameEvent) {
interface->videoRefresh(ppu.buffer, 4 * 256, 256, 240);
}
}
}

View File

@@ -1,11 +1,23 @@
#include <nes/nes.hpp>
#include <fc/fc.hpp>
#define VIDEO_CPP
namespace NES {
namespace Famicom {
Video video;
unsigned Video::palette30(
void Video::generate_palette() {
for(unsigned n = 0; n < (1 << 9); n++) palette[n] = generate_color(n, 2.0, 0.0, 1.0, 1.0, 1.8);
}
Video::Video() {
palette = new unsigned[1 << 9];
}
Video::~Video() {
delete[] palette;
}
uint32_t Video::generate_color(
unsigned n, double saturation, double hue,
double contrast, double brightness, double gamma
) {
@@ -46,43 +58,11 @@ unsigned Video::palette30(
q *= saturation;
auto gammaAdjust = [=](double f) { return f < 0.0 ? 0.0 : std::pow(f, 2.2 / gamma); };
unsigned r = 1023.0 * gammaAdjust(y + 0.946882 * i + 0.623557 * q);
unsigned g = 1023.0 * gammaAdjust(y + -0.274788 * i + -0.635691 * q);
unsigned b = 1023.0 * gammaAdjust(y + -1.108545 * i + 1.709007 * q);
return (uclamp<10>(r) << 20) + (uclamp<10>(g) << 10) + (uclamp<10>(b) << 0);
}
unsigned r = 65535.0 * gammaAdjust(y + 0.946882 * i + 0.623557 * q);
unsigned g = 65535.0 * gammaAdjust(y + -0.274788 * i + -0.635691 * q);
unsigned b = 65535.0 * gammaAdjust(y + -1.108545 * i + 1.709007 * q);
void Video::generate(Format format) {
for(unsigned n = 0; n < (1 << 9); n++) palette[n] = palette30(n, 2.0, 0.0, 1.0, 1.0, 1.8);
if(format == Format::RGB24) {
for(unsigned n = 0; n < (1 << 9); n++) {
unsigned color = palette[n];
palette[n] = ((color >> 6) & 0xff0000) + ((color >> 4) & 0x00ff00) + ((color >> 2) & 0x0000ff);
}
}
if(format == Format::RGB16) {
for(unsigned n = 0; n < (1 << 9); n++) {
unsigned color = palette[n];
palette[n] = ((color >> 14) & 0xf800) + ((color >> 9) & 0x07e0) + ((color >> 5) & 0x001f);
}
}
if(format == Format::RGB15) {
for(unsigned n = 0; n < (1 << 9); n++) {
unsigned color = palette[n];
palette[n] = ((color >> 15) & 0x7c00) + ((color >> 10) & 0x03e0) + ((color >> 5) & 0x001f);
}
}
}
Video::Video() {
palette = new unsigned[1 << 9];
}
Video::~Video() {
delete[] palette;
return interface->videoColor(n, uclamp<16>(r), uclamp<16>(g), uclamp<16>(b));
}
}

12
bsnes/fc/video/video.hpp Executable file
View File

@@ -0,0 +1,12 @@
struct Video {
unsigned *palette;
void generate_palette();
Video();
~Video();
private:
uint32_t generate_color(unsigned, double, double, double, double, double);
};
extern Video video;

View File

@@ -1,18 +0,0 @@
options += gameboy
gameboy_objects := gameboy-interface gameboy-system gameboy-scheduler
gameboy_objects += gameboy-memory gameboy-cartridge
gameboy_objects += gameboy-cpu gameboy-apu gameboy-lcd
gameboy_objects += gameboy-cheat gameboy-video
objects += $(gameboy_objects)
obj/gameboy-interface.o: $(gameboy)/interface/interface.cpp $(call rwildcard,$(gameboy)/interface/)
obj/gameboy-system.o: $(gameboy)/system/system.cpp $(call rwildcard,$(gameboy)/system/)
obj/gameboy-scheduler.o: $(gameboy)/scheduler/scheduler.cpp $(call rwildcard,$(gameboy)/scheduler/)
obj/gameboy-cartridge.o: $(gameboy)/cartridge/cartridge.cpp $(call rwildcard,$(gameboy)/cartridge/)
obj/gameboy-memory.o: $(gameboy)/memory/memory.cpp $(call rwildcard,$(gameboy)/memory/)
obj/gameboy-cpu.o: $(gameboy)/cpu/cpu.cpp $(call rwildcard,$(gameboy)/cpu/)
obj/gameboy-apu.o: $(gameboy)/apu/apu.cpp $(call rwildcard,$(gameboy)/apu/)
obj/gameboy-lcd.o: $(gameboy)/lcd/lcd.cpp $(call rwildcard,$(gameboy)/lcd/)
obj/gameboy-cheat.o: $(gameboy)/cheat/cheat.cpp $(call rwildcard,$(gameboy)/cheat/)
obj/gameboy-video.o: $(gameboy)/video/video.cpp $(call rwildcard,$(gameboy)/video/)

View File

@@ -1,145 +0,0 @@
#include "registers.hpp"
void (CPU::*opcode_table[256])();
void (CPU::*opcode_table_cb[256])();
void initialize_opcode_table();
void op_xx();
void op_cb();
//8-bit load commands
template<unsigned x, unsigned y> void op_ld_r_r();
template<unsigned x> void op_ld_r_n();
template<unsigned x> void op_ld_r_hl();
template<unsigned x> void op_ld_hl_r();
void op_ld_hl_n();
template<unsigned x> void op_ld_a_rr();
void op_ld_a_nn();
template<unsigned x> void op_ld_rr_a();
void op_ld_nn_a();
void op_ld_a_ffn();
void op_ld_ffn_a();
void op_ld_a_ffc();
void op_ld_ffc_a();
void op_ldi_hl_a();
void op_ldi_a_hl();
void op_ldd_hl_a();
void op_ldd_a_hl();
//16-bit load commands
template<unsigned x> void op_ld_rr_nn();
void op_ld_nn_sp();
void op_ld_sp_hl();
template<unsigned x> void op_push_rr();
template<unsigned x> void op_pop_rr();
//8-bit arithmetic commands
void opi_add_a(uint8 x);
template<unsigned x> void op_add_a_r();
void op_add_a_n();
void op_add_a_hl();
void opi_adc_a(uint8 x);
template<unsigned x> void op_adc_a_r();
void op_adc_a_n();
void op_adc_a_hl();
void opi_sub_a(uint8 x);
template<unsigned x> void op_sub_a_r();
void op_sub_a_n();
void op_sub_a_hl();
void opi_sbc_a(uint8 x);
template<unsigned x> void op_sbc_a_r();
void op_sbc_a_n();
void op_sbc_a_hl();
void opi_and_a(uint8 x);
template<unsigned x> void op_and_a_r();
void op_and_a_n();
void op_and_a_hl();
void opi_xor_a(uint8 x);
template<unsigned x> void op_xor_a_r();
void op_xor_a_n();
void op_xor_a_hl();
void opi_or_a(uint8 x);
template<unsigned x> void op_or_a_r();
void op_or_a_n();
void op_or_a_hl();
void opi_cp_a(uint8 x);
template<unsigned x> void op_cp_a_r();
void op_cp_a_n();
void op_cp_a_hl();
template<unsigned x> void op_inc_r();
void op_inc_hl();
template<unsigned x> void op_dec_r();
void op_dec_hl();
void op_daa();
void op_cpl();
//16-bit arithmetic commands
template<unsigned x> void op_add_hl_rr();
template<unsigned x> void op_inc_rr();
template<unsigned x> void op_dec_rr();
void op_add_sp_n();
void op_ld_hl_sp_n();
//rotate/shift commands
void op_rlca();
void op_rla();
void op_rrca();
void op_rra();
template<unsigned x> void op_rlc_r();
void op_rlc_hl();
template<unsigned x> void op_rl_r();
void op_rl_hl();
template<unsigned x> void op_rrc_r();
void op_rrc_hl();
template<unsigned x> void op_rr_r();
void op_rr_hl();
template<unsigned x> void op_sla_r();
void op_sla_hl();
template<unsigned x> void op_swap_r();
void op_swap_hl();
template<unsigned x> void op_sra_r();
void op_sra_hl();
template<unsigned x> void op_srl_r();
void op_srl_hl();
//single-bit commands
template<unsigned b, unsigned x> void op_bit_n_r();
template<unsigned b> void op_bit_n_hl();
template<unsigned b, unsigned x> void op_set_n_r();
template<unsigned b> void op_set_n_hl();
template<unsigned b, unsigned x> void op_res_n_r();
template<unsigned b> void op_res_n_hl();
//control commands
void op_ccf();
void op_scf();
void op_nop();
void op_halt();
void op_stop();
void op_di();
void op_ei();
//jump commands
void op_jp_nn();
void op_jp_hl();
template<unsigned x, bool y> void op_jp_f_nn();
void op_jr_n();
template<unsigned x, bool y> void op_jr_f_n();
void op_call_nn();
template<unsigned x, bool y> void op_call_f_nn();
void op_ret();
template<unsigned x, bool y> void op_ret_f();
void op_reti();
template<unsigned n> void op_rst_n();
//disassembler.cpp
string disassemble(uint16 pc);
string disassemble_opcode(uint16 pc);
string disassemble_opcode_cb(uint16 pc);

View File

@@ -1,519 +0,0 @@
#ifdef CPU_CPP
void CPU::initialize_opcode_table() {
opcode_table[0x00] = &CPU::op_nop;
opcode_table[0x01] = &CPU::op_ld_rr_nn<BC>;
opcode_table[0x02] = &CPU::op_ld_rr_a<BC>;
opcode_table[0x03] = &CPU::op_inc_rr<BC>;
opcode_table[0x04] = &CPU::op_inc_r<B>;
opcode_table[0x05] = &CPU::op_dec_r<B>;
opcode_table[0x06] = &CPU::op_ld_r_n<B>;
opcode_table[0x07] = &CPU::op_rlca;
opcode_table[0x08] = &CPU::op_ld_nn_sp;
opcode_table[0x09] = &CPU::op_add_hl_rr<BC>;
opcode_table[0x0a] = &CPU::op_ld_a_rr<BC>;
opcode_table[0x0b] = &CPU::op_dec_rr<BC>;
opcode_table[0x0c] = &CPU::op_inc_r<C>;
opcode_table[0x0d] = &CPU::op_dec_r<C>;
opcode_table[0x0e] = &CPU::op_ld_r_n<C>;
opcode_table[0x0f] = &CPU::op_rrca;
opcode_table[0x10] = &CPU::op_stop;
opcode_table[0x11] = &CPU::op_ld_rr_nn<DE>;
opcode_table[0x12] = &CPU::op_ld_rr_a<DE>;
opcode_table[0x13] = &CPU::op_inc_rr<DE>;
opcode_table[0x14] = &CPU::op_inc_r<D>;
opcode_table[0x15] = &CPU::op_dec_r<D>;
opcode_table[0x16] = &CPU::op_ld_r_n<D>;
opcode_table[0x17] = &CPU::op_rla;
opcode_table[0x18] = &CPU::op_jr_n;
opcode_table[0x19] = &CPU::op_add_hl_rr<DE>;
opcode_table[0x1a] = &CPU::op_ld_a_rr<DE>;
opcode_table[0x1b] = &CPU::op_dec_rr<DE>;
opcode_table[0x1c] = &CPU::op_inc_r<E>;
opcode_table[0x1d] = &CPU::op_dec_r<E>;
opcode_table[0x1e] = &CPU::op_ld_r_n<E>;
opcode_table[0x1f] = &CPU::op_rra;
opcode_table[0x20] = &CPU::op_jr_f_n<ZF, 0>;
opcode_table[0x21] = &CPU::op_ld_rr_nn<HL>;
opcode_table[0x22] = &CPU::op_ldi_hl_a;
opcode_table[0x23] = &CPU::op_inc_rr<HL>;
opcode_table[0x24] = &CPU::op_inc_r<H>;
opcode_table[0x25] = &CPU::op_dec_r<H>;
opcode_table[0x26] = &CPU::op_ld_r_n<H>;
opcode_table[0x27] = &CPU::op_daa;
opcode_table[0x28] = &CPU::op_jr_f_n<ZF, 1>;
opcode_table[0x29] = &CPU::op_add_hl_rr<HL>;
opcode_table[0x2a] = &CPU::op_ldi_a_hl;
opcode_table[0x2b] = &CPU::op_dec_rr<HL>;
opcode_table[0x2c] = &CPU::op_inc_r<L>;
opcode_table[0x2d] = &CPU::op_dec_r<L>;
opcode_table[0x2e] = &CPU::op_ld_r_n<L>;
opcode_table[0x2f] = &CPU::op_cpl;
opcode_table[0x30] = &CPU::op_jr_f_n<CF, 0>;
opcode_table[0x31] = &CPU::op_ld_rr_nn<SP>;
opcode_table[0x32] = &CPU::op_ldd_hl_a;
opcode_table[0x33] = &CPU::op_inc_rr<SP>;
opcode_table[0x34] = &CPU::op_inc_hl;
opcode_table[0x35] = &CPU::op_dec_hl;
opcode_table[0x36] = &CPU::op_ld_hl_n;
opcode_table[0x37] = &CPU::op_scf;
opcode_table[0x38] = &CPU::op_jr_f_n<CF, 1>;
opcode_table[0x39] = &CPU::op_add_hl_rr<SP>;
opcode_table[0x3a] = &CPU::op_ldd_a_hl;
opcode_table[0x3b] = &CPU::op_dec_rr<SP>;
opcode_table[0x3c] = &CPU::op_inc_r<A>;
opcode_table[0x3d] = &CPU::op_dec_r<A>;
opcode_table[0x3e] = &CPU::op_ld_r_n<A>;
opcode_table[0x3f] = &CPU::op_ccf;
opcode_table[0x40] = &CPU::op_ld_r_r<B, B>;
opcode_table[0x41] = &CPU::op_ld_r_r<B, C>;
opcode_table[0x42] = &CPU::op_ld_r_r<B, D>;
opcode_table[0x43] = &CPU::op_ld_r_r<B, E>;
opcode_table[0x44] = &CPU::op_ld_r_r<B, H>;
opcode_table[0x45] = &CPU::op_ld_r_r<B, L>;
opcode_table[0x46] = &CPU::op_ld_r_hl<B>;
opcode_table[0x47] = &CPU::op_ld_r_r<B, A>;
opcode_table[0x48] = &CPU::op_ld_r_r<C, B>;
opcode_table[0x49] = &CPU::op_ld_r_r<C, C>;
opcode_table[0x4a] = &CPU::op_ld_r_r<C, D>;
opcode_table[0x4b] = &CPU::op_ld_r_r<C, E>;
opcode_table[0x4c] = &CPU::op_ld_r_r<C, H>;
opcode_table[0x4d] = &CPU::op_ld_r_r<C, L>;
opcode_table[0x4e] = &CPU::op_ld_r_hl<C>;
opcode_table[0x4f] = &CPU::op_ld_r_r<C, A>;
opcode_table[0x50] = &CPU::op_ld_r_r<D, B>;
opcode_table[0x51] = &CPU::op_ld_r_r<D, C>;
opcode_table[0x52] = &CPU::op_ld_r_r<D, D>;
opcode_table[0x53] = &CPU::op_ld_r_r<D, E>;
opcode_table[0x54] = &CPU::op_ld_r_r<D, H>;
opcode_table[0x55] = &CPU::op_ld_r_r<D, L>;
opcode_table[0x56] = &CPU::op_ld_r_hl<D>;
opcode_table[0x57] = &CPU::op_ld_r_r<D, A>;
opcode_table[0x58] = &CPU::op_ld_r_r<E, B>;
opcode_table[0x59] = &CPU::op_ld_r_r<E, C>;
opcode_table[0x5a] = &CPU::op_ld_r_r<E, D>;
opcode_table[0x5b] = &CPU::op_ld_r_r<E, E>;
opcode_table[0x5c] = &CPU::op_ld_r_r<E, H>;
opcode_table[0x5d] = &CPU::op_ld_r_r<E, L>;
opcode_table[0x5e] = &CPU::op_ld_r_hl<E>;
opcode_table[0x5f] = &CPU::op_ld_r_r<E, A>;
opcode_table[0x60] = &CPU::op_ld_r_r<H, B>;
opcode_table[0x61] = &CPU::op_ld_r_r<H, C>;
opcode_table[0x62] = &CPU::op_ld_r_r<H, D>;
opcode_table[0x63] = &CPU::op_ld_r_r<H, E>;
opcode_table[0x64] = &CPU::op_ld_r_r<H, H>;
opcode_table[0x65] = &CPU::op_ld_r_r<H, L>;
opcode_table[0x66] = &CPU::op_ld_r_hl<H>;
opcode_table[0x67] = &CPU::op_ld_r_r<H, A>;
opcode_table[0x68] = &CPU::op_ld_r_r<L, B>;
opcode_table[0x69] = &CPU::op_ld_r_r<L, C>;
opcode_table[0x6a] = &CPU::op_ld_r_r<L, D>;
opcode_table[0x6b] = &CPU::op_ld_r_r<L, E>;
opcode_table[0x6c] = &CPU::op_ld_r_r<L, H>;
opcode_table[0x6d] = &CPU::op_ld_r_r<L, L>;
opcode_table[0x6e] = &CPU::op_ld_r_hl<L>;
opcode_table[0x6f] = &CPU::op_ld_r_r<L, A>;
opcode_table[0x70] = &CPU::op_ld_hl_r<B>;
opcode_table[0x71] = &CPU::op_ld_hl_r<C>;
opcode_table[0x72] = &CPU::op_ld_hl_r<D>;
opcode_table[0x73] = &CPU::op_ld_hl_r<E>;
opcode_table[0x74] = &CPU::op_ld_hl_r<H>;
opcode_table[0x75] = &CPU::op_ld_hl_r<L>;
opcode_table[0x76] = &CPU::op_halt;
opcode_table[0x77] = &CPU::op_ld_hl_r<A>;
opcode_table[0x78] = &CPU::op_ld_r_r<A, B>;
opcode_table[0x79] = &CPU::op_ld_r_r<A, C>;
opcode_table[0x7a] = &CPU::op_ld_r_r<A, D>;
opcode_table[0x7b] = &CPU::op_ld_r_r<A, E>;
opcode_table[0x7c] = &CPU::op_ld_r_r<A, H>;
opcode_table[0x7d] = &CPU::op_ld_r_r<A, L>;
opcode_table[0x7e] = &CPU::op_ld_r_hl<A>;
opcode_table[0x7f] = &CPU::op_ld_r_r<A, A>;
opcode_table[0x80] = &CPU::op_add_a_r<B>;
opcode_table[0x81] = &CPU::op_add_a_r<C>;
opcode_table[0x82] = &CPU::op_add_a_r<D>;
opcode_table[0x83] = &CPU::op_add_a_r<E>;
opcode_table[0x84] = &CPU::op_add_a_r<H>;
opcode_table[0x85] = &CPU::op_add_a_r<L>;
opcode_table[0x86] = &CPU::op_add_a_hl;
opcode_table[0x87] = &CPU::op_add_a_r<A>;
opcode_table[0x88] = &CPU::op_adc_a_r<B>;
opcode_table[0x89] = &CPU::op_adc_a_r<C>;
opcode_table[0x8a] = &CPU::op_adc_a_r<D>;
opcode_table[0x8b] = &CPU::op_adc_a_r<E>;
opcode_table[0x8c] = &CPU::op_adc_a_r<H>;
opcode_table[0x8d] = &CPU::op_adc_a_r<L>;
opcode_table[0x8e] = &CPU::op_adc_a_hl;
opcode_table[0x8f] = &CPU::op_adc_a_r<A>;
opcode_table[0x90] = &CPU::op_sub_a_r<B>;
opcode_table[0x91] = &CPU::op_sub_a_r<C>;
opcode_table[0x92] = &CPU::op_sub_a_r<D>;
opcode_table[0x93] = &CPU::op_sub_a_r<E>;
opcode_table[0x94] = &CPU::op_sub_a_r<H>;
opcode_table[0x95] = &CPU::op_sub_a_r<L>;
opcode_table[0x96] = &CPU::op_sub_a_hl;
opcode_table[0x97] = &CPU::op_sub_a_r<A>;
opcode_table[0x98] = &CPU::op_sbc_a_r<B>;
opcode_table[0x99] = &CPU::op_sbc_a_r<C>;
opcode_table[0x9a] = &CPU::op_sbc_a_r<D>;
opcode_table[0x9b] = &CPU::op_sbc_a_r<E>;
opcode_table[0x9c] = &CPU::op_sbc_a_r<H>;
opcode_table[0x9d] = &CPU::op_sbc_a_r<L>;
opcode_table[0x9e] = &CPU::op_sbc_a_hl;
opcode_table[0x9f] = &CPU::op_sbc_a_r<A>;
opcode_table[0xa0] = &CPU::op_and_a_r<B>;
opcode_table[0xa1] = &CPU::op_and_a_r<C>;
opcode_table[0xa2] = &CPU::op_and_a_r<D>;
opcode_table[0xa3] = &CPU::op_and_a_r<E>;
opcode_table[0xa4] = &CPU::op_and_a_r<H>;
opcode_table[0xa5] = &CPU::op_and_a_r<L>;
opcode_table[0xa6] = &CPU::op_and_a_hl;
opcode_table[0xa7] = &CPU::op_and_a_r<A>;
opcode_table[0xa8] = &CPU::op_xor_a_r<B>;
opcode_table[0xa9] = &CPU::op_xor_a_r<C>;
opcode_table[0xaa] = &CPU::op_xor_a_r<D>;
opcode_table[0xab] = &CPU::op_xor_a_r<E>;
opcode_table[0xac] = &CPU::op_xor_a_r<H>;
opcode_table[0xad] = &CPU::op_xor_a_r<L>;
opcode_table[0xae] = &CPU::op_xor_a_hl;
opcode_table[0xaf] = &CPU::op_xor_a_r<A>;
opcode_table[0xb0] = &CPU::op_or_a_r<B>;
opcode_table[0xb1] = &CPU::op_or_a_r<C>;
opcode_table[0xb2] = &CPU::op_or_a_r<D>;
opcode_table[0xb3] = &CPU::op_or_a_r<E>;
opcode_table[0xb4] = &CPU::op_or_a_r<H>;
opcode_table[0xb5] = &CPU::op_or_a_r<L>;
opcode_table[0xb6] = &CPU::op_or_a_hl;
opcode_table[0xb7] = &CPU::op_or_a_r<A>;
opcode_table[0xb8] = &CPU::op_cp_a_r<B>;
opcode_table[0xb9] = &CPU::op_cp_a_r<C>;
opcode_table[0xba] = &CPU::op_cp_a_r<D>;
opcode_table[0xbb] = &CPU::op_cp_a_r<E>;
opcode_table[0xbc] = &CPU::op_cp_a_r<H>;
opcode_table[0xbd] = &CPU::op_cp_a_r<L>;
opcode_table[0xbe] = &CPU::op_cp_a_hl;
opcode_table[0xbf] = &CPU::op_cp_a_r<A>;
opcode_table[0xc0] = &CPU::op_ret_f<ZF, 0>;
opcode_table[0xc1] = &CPU::op_pop_rr<BC>;
opcode_table[0xc2] = &CPU::op_jp_f_nn<ZF, 0>;
opcode_table[0xc3] = &CPU::op_jp_nn;
opcode_table[0xc4] = &CPU::op_call_f_nn<ZF, 0>;
opcode_table[0xc5] = &CPU::op_push_rr<BC>;
opcode_table[0xc6] = &CPU::op_add_a_n;
opcode_table[0xc7] = &CPU::op_rst_n<0x00>;
opcode_table[0xc8] = &CPU::op_ret_f<ZF, 1>;
opcode_table[0xc9] = &CPU::op_ret;
opcode_table[0xca] = &CPU::op_jp_f_nn<ZF, 1>;
opcode_table[0xcb] = &CPU::op_cb;
opcode_table[0xcc] = &CPU::op_call_f_nn<ZF, 1>;
opcode_table[0xcd] = &CPU::op_call_nn;
opcode_table[0xce] = &CPU::op_adc_a_n;
opcode_table[0xcf] = &CPU::op_rst_n<0x08>;
opcode_table[0xd0] = &CPU::op_ret_f<CF, 0>;
opcode_table[0xd1] = &CPU::op_pop_rr<DE>;
opcode_table[0xd2] = &CPU::op_jp_f_nn<CF, 0>;
opcode_table[0xd3] = &CPU::op_xx;
opcode_table[0xd4] = &CPU::op_call_f_nn<CF, 0>;
opcode_table[0xd5] = &CPU::op_push_rr<DE>;
opcode_table[0xd6] = &CPU::op_sub_a_n;
opcode_table[0xd7] = &CPU::op_rst_n<0x10>;
opcode_table[0xd8] = &CPU::op_ret_f<CF, 1>;
opcode_table[0xd9] = &CPU::op_reti;
opcode_table[0xda] = &CPU::op_jp_f_nn<CF, 1>;
opcode_table[0xdb] = &CPU::op_xx;
opcode_table[0xdc] = &CPU::op_call_f_nn<CF, 1>;
opcode_table[0xdd] = &CPU::op_xx;
opcode_table[0xde] = &CPU::op_sbc_a_n;
opcode_table[0xdf] = &CPU::op_rst_n<0x18>;
opcode_table[0xe0] = &CPU::op_ld_ffn_a;
opcode_table[0xe1] = &CPU::op_pop_rr<HL>;
opcode_table[0xe2] = &CPU::op_ld_ffc_a;
opcode_table[0xe3] = &CPU::op_xx;
opcode_table[0xe4] = &CPU::op_xx;
opcode_table[0xe5] = &CPU::op_push_rr<HL>;
opcode_table[0xe6] = &CPU::op_and_a_n;
opcode_table[0xe7] = &CPU::op_rst_n<0x20>;
opcode_table[0xe8] = &CPU::op_add_sp_n;
opcode_table[0xe9] = &CPU::op_jp_hl;
opcode_table[0xea] = &CPU::op_ld_nn_a;
opcode_table[0xeb] = &CPU::op_xx;
opcode_table[0xec] = &CPU::op_xx;
opcode_table[0xed] = &CPU::op_xx;
opcode_table[0xee] = &CPU::op_xor_a_n;
opcode_table[0xef] = &CPU::op_rst_n<0x28>;
opcode_table[0xf0] = &CPU::op_ld_a_ffn;
opcode_table[0xf1] = &CPU::op_pop_rr<AF>;
opcode_table[0xf2] = &CPU::op_ld_a_ffc;
opcode_table[0xf3] = &CPU::op_di;
opcode_table[0xf4] = &CPU::op_xx;
opcode_table[0xf5] = &CPU::op_push_rr<AF>;
opcode_table[0xf6] = &CPU::op_or_a_n;
opcode_table[0xf7] = &CPU::op_rst_n<0x30>;
opcode_table[0xf8] = &CPU::op_ld_hl_sp_n;
opcode_table[0xf9] = &CPU::op_ld_sp_hl;
opcode_table[0xfa] = &CPU::op_ld_a_nn;
opcode_table[0xfb] = &CPU::op_ei;
opcode_table[0xfc] = &CPU::op_xx;
opcode_table[0xfd] = &CPU::op_xx;
opcode_table[0xfe] = &CPU::op_cp_a_n;
opcode_table[0xff] = &CPU::op_rst_n<0x38>;
opcode_table_cb[0x00] = &CPU::op_rlc_r<B>;
opcode_table_cb[0x01] = &CPU::op_rlc_r<C>;
opcode_table_cb[0x02] = &CPU::op_rlc_r<D>;
opcode_table_cb[0x03] = &CPU::op_rlc_r<E>;
opcode_table_cb[0x04] = &CPU::op_rlc_r<H>;
opcode_table_cb[0x05] = &CPU::op_rlc_r<L>;
opcode_table_cb[0x06] = &CPU::op_rlc_hl;
opcode_table_cb[0x07] = &CPU::op_rlc_r<A>;
opcode_table_cb[0x08] = &CPU::op_rrc_r<B>;
opcode_table_cb[0x09] = &CPU::op_rrc_r<C>;
opcode_table_cb[0x0a] = &CPU::op_rrc_r<D>;
opcode_table_cb[0x0b] = &CPU::op_rrc_r<E>;
opcode_table_cb[0x0c] = &CPU::op_rrc_r<H>;
opcode_table_cb[0x0d] = &CPU::op_rrc_r<L>;
opcode_table_cb[0x0e] = &CPU::op_rrc_hl;
opcode_table_cb[0x0f] = &CPU::op_rrc_r<A>;
opcode_table_cb[0x10] = &CPU::op_rl_r<B>;
opcode_table_cb[0x11] = &CPU::op_rl_r<C>;
opcode_table_cb[0x12] = &CPU::op_rl_r<D>;
opcode_table_cb[0x13] = &CPU::op_rl_r<E>;
opcode_table_cb[0x14] = &CPU::op_rl_r<H>;
opcode_table_cb[0x15] = &CPU::op_rl_r<L>;
opcode_table_cb[0x16] = &CPU::op_rl_hl;
opcode_table_cb[0x17] = &CPU::op_rl_r<A>;
opcode_table_cb[0x18] = &CPU::op_rr_r<B>;
opcode_table_cb[0x19] = &CPU::op_rr_r<C>;
opcode_table_cb[0x1a] = &CPU::op_rr_r<D>;
opcode_table_cb[0x1b] = &CPU::op_rr_r<E>;
opcode_table_cb[0x1c] = &CPU::op_rr_r<H>;
opcode_table_cb[0x1d] = &CPU::op_rr_r<L>;
opcode_table_cb[0x1e] = &CPU::op_rr_hl;
opcode_table_cb[0x1f] = &CPU::op_rr_r<A>;
opcode_table_cb[0x20] = &CPU::op_sla_r<B>;
opcode_table_cb[0x21] = &CPU::op_sla_r<C>;
opcode_table_cb[0x22] = &CPU::op_sla_r<D>;
opcode_table_cb[0x23] = &CPU::op_sla_r<E>;
opcode_table_cb[0x24] = &CPU::op_sla_r<H>;
opcode_table_cb[0x25] = &CPU::op_sla_r<L>;
opcode_table_cb[0x26] = &CPU::op_sla_hl;
opcode_table_cb[0x27] = &CPU::op_sla_r<A>;
opcode_table_cb[0x28] = &CPU::op_sra_r<B>;
opcode_table_cb[0x29] = &CPU::op_sra_r<C>;
opcode_table_cb[0x2a] = &CPU::op_sra_r<D>;
opcode_table_cb[0x2b] = &CPU::op_sra_r<E>;
opcode_table_cb[0x2c] = &CPU::op_sra_r<H>;
opcode_table_cb[0x2d] = &CPU::op_sra_r<L>;
opcode_table_cb[0x2e] = &CPU::op_sra_hl;
opcode_table_cb[0x2f] = &CPU::op_sra_r<A>;
opcode_table_cb[0x30] = &CPU::op_swap_r<B>;
opcode_table_cb[0x31] = &CPU::op_swap_r<C>;
opcode_table_cb[0x32] = &CPU::op_swap_r<D>;
opcode_table_cb[0x33] = &CPU::op_swap_r<E>;
opcode_table_cb[0x34] = &CPU::op_swap_r<H>;
opcode_table_cb[0x35] = &CPU::op_swap_r<L>;
opcode_table_cb[0x36] = &CPU::op_swap_hl;
opcode_table_cb[0x37] = &CPU::op_swap_r<A>;
opcode_table_cb[0x38] = &CPU::op_srl_r<B>;
opcode_table_cb[0x39] = &CPU::op_srl_r<C>;
opcode_table_cb[0x3a] = &CPU::op_srl_r<D>;
opcode_table_cb[0x3b] = &CPU::op_srl_r<E>;
opcode_table_cb[0x3c] = &CPU::op_srl_r<H>;
opcode_table_cb[0x3d] = &CPU::op_srl_r<L>;
opcode_table_cb[0x3e] = &CPU::op_srl_hl;
opcode_table_cb[0x3f] = &CPU::op_srl_r<A>;
opcode_table_cb[0x40] = &CPU::op_bit_n_r<0, B>;
opcode_table_cb[0x41] = &CPU::op_bit_n_r<0, C>;
opcode_table_cb[0x42] = &CPU::op_bit_n_r<0, D>;
opcode_table_cb[0x43] = &CPU::op_bit_n_r<0, E>;
opcode_table_cb[0x44] = &CPU::op_bit_n_r<0, H>;
opcode_table_cb[0x45] = &CPU::op_bit_n_r<0, L>;
opcode_table_cb[0x46] = &CPU::op_bit_n_hl<0>;
opcode_table_cb[0x47] = &CPU::op_bit_n_r<0, A>;
opcode_table_cb[0x48] = &CPU::op_bit_n_r<1, B>;
opcode_table_cb[0x49] = &CPU::op_bit_n_r<1, C>;
opcode_table_cb[0x4a] = &CPU::op_bit_n_r<1, D>;
opcode_table_cb[0x4b] = &CPU::op_bit_n_r<1, E>;
opcode_table_cb[0x4c] = &CPU::op_bit_n_r<1, H>;
opcode_table_cb[0x4d] = &CPU::op_bit_n_r<1, L>;
opcode_table_cb[0x4e] = &CPU::op_bit_n_hl<1>;
opcode_table_cb[0x4f] = &CPU::op_bit_n_r<1, A>;
opcode_table_cb[0x50] = &CPU::op_bit_n_r<2, B>;
opcode_table_cb[0x51] = &CPU::op_bit_n_r<2, C>;
opcode_table_cb[0x52] = &CPU::op_bit_n_r<2, D>;
opcode_table_cb[0x53] = &CPU::op_bit_n_r<2, E>;
opcode_table_cb[0x54] = &CPU::op_bit_n_r<2, H>;
opcode_table_cb[0x55] = &CPU::op_bit_n_r<2, L>;
opcode_table_cb[0x56] = &CPU::op_bit_n_hl<2>;
opcode_table_cb[0x57] = &CPU::op_bit_n_r<2, A>;
opcode_table_cb[0x58] = &CPU::op_bit_n_r<3, B>;
opcode_table_cb[0x59] = &CPU::op_bit_n_r<3, C>;
opcode_table_cb[0x5a] = &CPU::op_bit_n_r<3, D>;
opcode_table_cb[0x5b] = &CPU::op_bit_n_r<3, E>;
opcode_table_cb[0x5c] = &CPU::op_bit_n_r<3, H>;
opcode_table_cb[0x5d] = &CPU::op_bit_n_r<3, L>;
opcode_table_cb[0x5e] = &CPU::op_bit_n_hl<3>;
opcode_table_cb[0x5f] = &CPU::op_bit_n_r<3, A>;
opcode_table_cb[0x60] = &CPU::op_bit_n_r<4, B>;
opcode_table_cb[0x61] = &CPU::op_bit_n_r<4, C>;
opcode_table_cb[0x62] = &CPU::op_bit_n_r<4, D>;
opcode_table_cb[0x63] = &CPU::op_bit_n_r<4, E>;
opcode_table_cb[0x64] = &CPU::op_bit_n_r<4, H>;
opcode_table_cb[0x65] = &CPU::op_bit_n_r<4, L>;
opcode_table_cb[0x66] = &CPU::op_bit_n_hl<4>;
opcode_table_cb[0x67] = &CPU::op_bit_n_r<4, A>;
opcode_table_cb[0x68] = &CPU::op_bit_n_r<5, B>;
opcode_table_cb[0x69] = &CPU::op_bit_n_r<5, C>;
opcode_table_cb[0x6a] = &CPU::op_bit_n_r<5, D>;
opcode_table_cb[0x6b] = &CPU::op_bit_n_r<5, E>;
opcode_table_cb[0x6c] = &CPU::op_bit_n_r<5, H>;
opcode_table_cb[0x6d] = &CPU::op_bit_n_r<5, L>;
opcode_table_cb[0x6e] = &CPU::op_bit_n_hl<5>;
opcode_table_cb[0x6f] = &CPU::op_bit_n_r<5, A>;
opcode_table_cb[0x70] = &CPU::op_bit_n_r<6, B>;
opcode_table_cb[0x71] = &CPU::op_bit_n_r<6, C>;
opcode_table_cb[0x72] = &CPU::op_bit_n_r<6, D>;
opcode_table_cb[0x73] = &CPU::op_bit_n_r<6, E>;
opcode_table_cb[0x74] = &CPU::op_bit_n_r<6, H>;
opcode_table_cb[0x75] = &CPU::op_bit_n_r<6, L>;
opcode_table_cb[0x76] = &CPU::op_bit_n_hl<6>;
opcode_table_cb[0x77] = &CPU::op_bit_n_r<6, A>;
opcode_table_cb[0x78] = &CPU::op_bit_n_r<7, B>;
opcode_table_cb[0x79] = &CPU::op_bit_n_r<7, C>;
opcode_table_cb[0x7a] = &CPU::op_bit_n_r<7, D>;
opcode_table_cb[0x7b] = &CPU::op_bit_n_r<7, E>;
opcode_table_cb[0x7c] = &CPU::op_bit_n_r<7, H>;
opcode_table_cb[0x7d] = &CPU::op_bit_n_r<7, L>;
opcode_table_cb[0x7e] = &CPU::op_bit_n_hl<7>;
opcode_table_cb[0x7f] = &CPU::op_bit_n_r<7, A>;
opcode_table_cb[0x80] = &CPU::op_res_n_r<0, B>;
opcode_table_cb[0x81] = &CPU::op_res_n_r<0, C>;
opcode_table_cb[0x82] = &CPU::op_res_n_r<0, D>;
opcode_table_cb[0x83] = &CPU::op_res_n_r<0, E>;
opcode_table_cb[0x84] = &CPU::op_res_n_r<0, H>;
opcode_table_cb[0x85] = &CPU::op_res_n_r<0, L>;
opcode_table_cb[0x86] = &CPU::op_res_n_hl<0>;
opcode_table_cb[0x87] = &CPU::op_res_n_r<0, A>;
opcode_table_cb[0x88] = &CPU::op_res_n_r<1, B>;
opcode_table_cb[0x89] = &CPU::op_res_n_r<1, C>;
opcode_table_cb[0x8a] = &CPU::op_res_n_r<1, D>;
opcode_table_cb[0x8b] = &CPU::op_res_n_r<1, E>;
opcode_table_cb[0x8c] = &CPU::op_res_n_r<1, H>;
opcode_table_cb[0x8d] = &CPU::op_res_n_r<1, L>;
opcode_table_cb[0x8e] = &CPU::op_res_n_hl<1>;
opcode_table_cb[0x8f] = &CPU::op_res_n_r<1, A>;
opcode_table_cb[0x90] = &CPU::op_res_n_r<2, B>;
opcode_table_cb[0x91] = &CPU::op_res_n_r<2, C>;
opcode_table_cb[0x92] = &CPU::op_res_n_r<2, D>;
opcode_table_cb[0x93] = &CPU::op_res_n_r<2, E>;
opcode_table_cb[0x94] = &CPU::op_res_n_r<2, H>;
opcode_table_cb[0x95] = &CPU::op_res_n_r<2, L>;
opcode_table_cb[0x96] = &CPU::op_res_n_hl<2>;
opcode_table_cb[0x97] = &CPU::op_res_n_r<2, A>;
opcode_table_cb[0x98] = &CPU::op_res_n_r<3, B>;
opcode_table_cb[0x99] = &CPU::op_res_n_r<3, C>;
opcode_table_cb[0x9a] = &CPU::op_res_n_r<3, D>;
opcode_table_cb[0x9b] = &CPU::op_res_n_r<3, E>;
opcode_table_cb[0x9c] = &CPU::op_res_n_r<3, H>;
opcode_table_cb[0x9d] = &CPU::op_res_n_r<3, L>;
opcode_table_cb[0x9e] = &CPU::op_res_n_hl<3>;
opcode_table_cb[0x9f] = &CPU::op_res_n_r<3, A>;
opcode_table_cb[0xa0] = &CPU::op_res_n_r<4, B>;
opcode_table_cb[0xa1] = &CPU::op_res_n_r<4, C>;
opcode_table_cb[0xa2] = &CPU::op_res_n_r<4, D>;
opcode_table_cb[0xa3] = &CPU::op_res_n_r<4, E>;
opcode_table_cb[0xa4] = &CPU::op_res_n_r<4, H>;
opcode_table_cb[0xa5] = &CPU::op_res_n_r<4, L>;
opcode_table_cb[0xa6] = &CPU::op_res_n_hl<4>;
opcode_table_cb[0xa7] = &CPU::op_res_n_r<4, A>;
opcode_table_cb[0xa8] = &CPU::op_res_n_r<5, B>;
opcode_table_cb[0xa9] = &CPU::op_res_n_r<5, C>;
opcode_table_cb[0xaa] = &CPU::op_res_n_r<5, D>;
opcode_table_cb[0xab] = &CPU::op_res_n_r<5, E>;
opcode_table_cb[0xac] = &CPU::op_res_n_r<5, H>;
opcode_table_cb[0xad] = &CPU::op_res_n_r<5, L>;
opcode_table_cb[0xae] = &CPU::op_res_n_hl<5>;
opcode_table_cb[0xaf] = &CPU::op_res_n_r<5, A>;
opcode_table_cb[0xb0] = &CPU::op_res_n_r<6, B>;
opcode_table_cb[0xb1] = &CPU::op_res_n_r<6, C>;
opcode_table_cb[0xb2] = &CPU::op_res_n_r<6, D>;
opcode_table_cb[0xb3] = &CPU::op_res_n_r<6, E>;
opcode_table_cb[0xb4] = &CPU::op_res_n_r<6, H>;
opcode_table_cb[0xb5] = &CPU::op_res_n_r<6, L>;
opcode_table_cb[0xb6] = &CPU::op_res_n_hl<6>;
opcode_table_cb[0xb7] = &CPU::op_res_n_r<6, A>;
opcode_table_cb[0xb8] = &CPU::op_res_n_r<7, B>;
opcode_table_cb[0xb9] = &CPU::op_res_n_r<7, C>;
opcode_table_cb[0xba] = &CPU::op_res_n_r<7, D>;
opcode_table_cb[0xbb] = &CPU::op_res_n_r<7, E>;
opcode_table_cb[0xbc] = &CPU::op_res_n_r<7, H>;
opcode_table_cb[0xbd] = &CPU::op_res_n_r<7, L>;
opcode_table_cb[0xbe] = &CPU::op_res_n_hl<7>;
opcode_table_cb[0xbf] = &CPU::op_res_n_r<7, A>;
opcode_table_cb[0xc0] = &CPU::op_set_n_r<0, B>;
opcode_table_cb[0xc1] = &CPU::op_set_n_r<0, C>;
opcode_table_cb[0xc2] = &CPU::op_set_n_r<0, D>;
opcode_table_cb[0xc3] = &CPU::op_set_n_r<0, E>;
opcode_table_cb[0xc4] = &CPU::op_set_n_r<0, H>;
opcode_table_cb[0xc5] = &CPU::op_set_n_r<0, L>;
opcode_table_cb[0xc6] = &CPU::op_set_n_hl<0>;
opcode_table_cb[0xc7] = &CPU::op_set_n_r<0, A>;
opcode_table_cb[0xc8] = &CPU::op_set_n_r<1, B>;
opcode_table_cb[0xc9] = &CPU::op_set_n_r<1, C>;
opcode_table_cb[0xca] = &CPU::op_set_n_r<1, D>;
opcode_table_cb[0xcb] = &CPU::op_set_n_r<1, E>;
opcode_table_cb[0xcc] = &CPU::op_set_n_r<1, H>;
opcode_table_cb[0xcd] = &CPU::op_set_n_r<1, L>;
opcode_table_cb[0xce] = &CPU::op_set_n_hl<1>;
opcode_table_cb[0xcf] = &CPU::op_set_n_r<1, A>;
opcode_table_cb[0xd0] = &CPU::op_set_n_r<2, B>;
opcode_table_cb[0xd1] = &CPU::op_set_n_r<2, C>;
opcode_table_cb[0xd2] = &CPU::op_set_n_r<2, D>;
opcode_table_cb[0xd3] = &CPU::op_set_n_r<2, E>;
opcode_table_cb[0xd4] = &CPU::op_set_n_r<2, H>;
opcode_table_cb[0xd5] = &CPU::op_set_n_r<2, L>;
opcode_table_cb[0xd6] = &CPU::op_set_n_hl<2>;
opcode_table_cb[0xd7] = &CPU::op_set_n_r<2, A>;
opcode_table_cb[0xd8] = &CPU::op_set_n_r<3, B>;
opcode_table_cb[0xd9] = &CPU::op_set_n_r<3, C>;
opcode_table_cb[0xda] = &CPU::op_set_n_r<3, D>;
opcode_table_cb[0xdb] = &CPU::op_set_n_r<3, E>;
opcode_table_cb[0xdc] = &CPU::op_set_n_r<3, H>;
opcode_table_cb[0xdd] = &CPU::op_set_n_r<3, L>;
opcode_table_cb[0xde] = &CPU::op_set_n_hl<3>;
opcode_table_cb[0xdf] = &CPU::op_set_n_r<3, A>;
opcode_table_cb[0xe0] = &CPU::op_set_n_r<4, B>;
opcode_table_cb[0xe1] = &CPU::op_set_n_r<4, C>;
opcode_table_cb[0xe2] = &CPU::op_set_n_r<4, D>;
opcode_table_cb[0xe3] = &CPU::op_set_n_r<4, E>;
opcode_table_cb[0xe4] = &CPU::op_set_n_r<4, H>;
opcode_table_cb[0xe5] = &CPU::op_set_n_r<4, L>;
opcode_table_cb[0xe6] = &CPU::op_set_n_hl<4>;
opcode_table_cb[0xe7] = &CPU::op_set_n_r<4, A>;
opcode_table_cb[0xe8] = &CPU::op_set_n_r<5, B>;
opcode_table_cb[0xe9] = &CPU::op_set_n_r<5, C>;
opcode_table_cb[0xea] = &CPU::op_set_n_r<5, D>;
opcode_table_cb[0xeb] = &CPU::op_set_n_r<5, E>;
opcode_table_cb[0xec] = &CPU::op_set_n_r<5, H>;
opcode_table_cb[0xed] = &CPU::op_set_n_r<5, L>;
opcode_table_cb[0xee] = &CPU::op_set_n_hl<5>;
opcode_table_cb[0xef] = &CPU::op_set_n_r<5, A>;
opcode_table_cb[0xf0] = &CPU::op_set_n_r<6, B>;
opcode_table_cb[0xf1] = &CPU::op_set_n_r<6, C>;
opcode_table_cb[0xf2] = &CPU::op_set_n_r<6, D>;
opcode_table_cb[0xf3] = &CPU::op_set_n_r<6, E>;
opcode_table_cb[0xf4] = &CPU::op_set_n_r<6, H>;
opcode_table_cb[0xf5] = &CPU::op_set_n_r<6, L>;
opcode_table_cb[0xf6] = &CPU::op_set_n_hl<6>;
opcode_table_cb[0xf7] = &CPU::op_set_n_r<6, A>;
opcode_table_cb[0xf8] = &CPU::op_set_n_r<7, B>;
opcode_table_cb[0xf9] = &CPU::op_set_n_r<7, C>;
opcode_table_cb[0xfa] = &CPU::op_set_n_r<7, D>;
opcode_table_cb[0xfb] = &CPU::op_set_n_r<7, E>;
opcode_table_cb[0xfc] = &CPU::op_set_n_r<7, H>;
opcode_table_cb[0xfd] = &CPU::op_set_n_r<7, L>;
opcode_table_cb[0xfe] = &CPU::op_set_n_hl<7>;
opcode_table_cb[0xff] = &CPU::op_set_n_r<7, A>;
}
#endif

View File

@@ -1,4 +0,0 @@
unsigned wram_addr(uint16 addr) const;
void mmio_joyp_poll();
uint8 mmio_read(uint16 addr);
void mmio_write(uint16 addr, uint8 data);

View File

@@ -1,13 +0,0 @@
void add_clocks(unsigned clocks);
void timer_262144hz();
void timer_65536hz();
void timer_16384hz();
void timer_8192hz();
void timer_4096hz();
void hblank();
//opcode.cpp
void op_io();
uint8 op_read(uint16 addr);
void op_write(uint16 addr, uint8 data);
void cycle_edge();

View File

@@ -1,60 +0,0 @@
#ifndef GAMEBOY_HPP
#define GAMEBOY_HPP
#include <base/base.hpp>
namespace GameBoy {
namespace Info {
static const char Name[] = "bgameboy";
static const unsigned SerializerVersion = 3;
}
}
/*
bgameboy - Game Boy, Super Game Boy, and Game Boy Color emulator
author: byuu
license: GPLv3
project started: 2010-12-27
*/
#include <libco/libco.h>
#include <nall/gameboy/cartridge.hpp>
namespace GameBoy {
struct Processor {
cothread_t thread;
unsigned frequency;
int64 clock;
inline void create(void (*entrypoint)(), unsigned frequency) {
if(thread) co_delete(thread);
thread = co_create(65536 * sizeof(void*), entrypoint);
this->frequency = frequency;
clock = 0;
}
inline void serialize(serializer &s) {
s.integer(frequency);
s.integer(clock);
}
inline Processor() : thread(nullptr) {
}
inline ~Processor() {
if(thread) co_delete(thread);
}
};
#include <gameboy/memory/memory.hpp>
#include <gameboy/system/system.hpp>
#include <gameboy/scheduler/scheduler.hpp>
#include <gameboy/cartridge/cartridge.hpp>
#include <gameboy/cpu/cpu.hpp>
#include <gameboy/apu/apu.hpp>
#include <gameboy/lcd/lcd.hpp>
#include <gameboy/cheat/cheat.hpp>
#include <gameboy/video/video.hpp>
};
#endif

View File

@@ -1,27 +0,0 @@
#include <gameboy/gameboy.hpp>
namespace GameBoy {
Interface *interface = nullptr;
void Interface::lcdScanline() {
}
void Interface::joypWrite(bool p15, bool p14) {
}
void Interface::videoRefresh(const uint16_t *data) {
}
void Interface::audioSample(int16_t center, int16_t left, int16_t right) {
}
bool Interface::inputPoll(unsigned id) {
return false;
}
void Interface::message(const string &text) {
print(text, "\n");
}
}

View File

@@ -1,12 +0,0 @@
struct Interface {
virtual void lcdScanline();
virtual void joypWrite(bool p15, bool p14);
virtual void videoRefresh(const uint16_t *data);
virtual void audioSample(int16_t center, int16_t left, int16_t right);
virtual bool inputPoll(unsigned id);
virtual void message(const string &text);
};
extern Interface *interface;

View File

@@ -1,3 +0,0 @@
unsigned vram_addr(uint16 addr) const;
uint8 mmio_read(uint16 addr);
void mmio_write(uint16 addr, uint8 data);

View File

@@ -1,135 +0,0 @@
#ifdef SYSTEM_CPP
//SHA256 = 4bf5021be357ce523a59ac5f4efff5d6371ae50112a6db0adf4a75916ad760a9
const uint8_t System::BootROM::cgb[2048] = {
0x31,0xfe,0xff,0x3e,0x02,0xc3,0x7c,0x00,0xd3,0x00,0x98,0xa0,0x12,0xd3,0x00,0x80,
0x00,0x40,0x1e,0x53,0xd0,0x00,0x1f,0x42,0x1c,0x00,0x14,0x2a,0x4d,0x19,0x8c,0x7e,
0x00,0x7c,0x31,0x6e,0x4a,0x45,0x52,0x4a,0x00,0x00,0xff,0x53,0x1f,0x7c,0xff,0x03,
0x1f,0x00,0xff,0x1f,0xa7,0x00,0xef,0x1b,0x1f,0x00,0xef,0x1b,0x00,0x7c,0x00,0x00,
0xff,0x03,0xce,0xed,0x66,0x66,0xcc,0x0d,0x00,0x0b,0x03,0x73,0x00,0x83,0x00,0x0c,
0x00,0x0d,0x00,0x08,0x11,0x1f,0x88,0x89,0x00,0x0e,0xdc,0xcc,0x6e,0xe6,0xdd,0xdd,
0xd9,0x99,0xbb,0xbb,0x67,0x63,0x6e,0x0e,0xec,0xcc,0xdd,0xdc,0x99,0x9f,0xbb,0xb9,
0x33,0x3e,0x3c,0x42,0xb9,0xa5,0xb9,0xa5,0x42,0x3c,0x58,0x43,0xe0,0x70,0x3e,0xfc,
0xe0,0x47,0xcd,0x75,0x02,0xcd,0x00,0x02,0x26,0xd0,0xcd,0x03,0x02,0x21,0x00,0xfe,
0x0e,0xa0,0xaf,0x22,0x0d,0x20,0xfc,0x11,0x04,0x01,0x21,0x10,0x80,0x4c,0x1a,0xe2,
0x0c,0xcd,0xc6,0x03,0xcd,0xc7,0x03,0x13,0x7b,0xfe,0x34,0x20,0xf1,0x11,0x72,0x00,
0x06,0x08,0x1a,0x13,0x22,0x23,0x05,0x20,0xf9,0xcd,0xf0,0x03,0x3e,0x01,0xe0,0x4f,
0x3e,0x91,0xe0,0x40,0x21,0xb2,0x98,0x06,0x4e,0x0e,0x44,0xcd,0x91,0x02,0xaf,0xe0,
0x4f,0x0e,0x80,0x21,0x42,0x00,0x06,0x18,0xf2,0x0c,0xbe,0x20,0xfe,0x23,0x05,0x20,
0xf7,0x21,0x34,0x01,0x06,0x19,0x78,0x86,0x2c,0x05,0x20,0xfb,0x86,0x20,0xfe,0xcd,
0x1c,0x03,0x18,0x02,0x00,0x00,0xcd,0xd0,0x05,0xaf,0xe0,0x70,0x3e,0x11,0xe0,0x50,
0x21,0x00,0x80,0xaf,0x22,0xcb,0x6c,0x28,0xfb,0xc9,0x2a,0x12,0x13,0x0d,0x20,0xfa,
0xc9,0xe5,0x21,0x0f,0xff,0xcb,0x86,0xcb,0x46,0x28,0xfc,0xe1,0xc9,0x11,0x00,0xff,
0x21,0x03,0xd0,0x0e,0x0f,0x3e,0x30,0x12,0x3e,0x20,0x12,0x1a,0x2f,0xa1,0xcb,0x37,
0x47,0x3e,0x10,0x12,0x1a,0x2f,0xa1,0xb0,0x4f,0x7e,0xa9,0xe6,0xf0,0x47,0x2a,0xa9,
0xa1,0xb0,0x32,0x47,0x79,0x77,0x3e,0x30,0x12,0xc9,0x3e,0x80,0xe0,0x68,0xe0,0x6a,
0x0e,0x6b,0x2a,0xe2,0x05,0x20,0xfb,0x4a,0x09,0x43,0x0e,0x69,0x2a,0xe2,0x05,0x20,
0xfb,0xc9,0xc5,0xd5,0xe5,0x21,0x00,0xd8,0x06,0x01,0x16,0x3f,0x1e,0x40,0xcd,0x4a,
0x02,0xe1,0xd1,0xc1,0xc9,0x3e,0x80,0xe0,0x26,0xe0,0x11,0x3e,0xf3,0xe0,0x12,0xe0,
0x25,0x3e,0x77,0xe0,0x24,0x21,0x30,0xff,0xaf,0x0e,0x10,0x22,0x2f,0x0d,0x20,0xfb,
0xc9,0xcd,0x11,0x02,0xcd,0x62,0x02,0x79,0xfe,0x38,0x20,0x14,0xe5,0xaf,0xe0,0x4f,
0x21,0xa7,0x99,0x3e,0x38,0x22,0x3c,0xfe,0x3f,0x20,0xfa,0x3e,0x01,0xe0,0x4f,0xe1,
0xc5,0xe5,0x21,0x43,0x01,0xcb,0x7e,0xcc,0x89,0x05,0xe1,0xc1,0xcd,0x11,0x02,0x79,
0xd6,0x30,0xd2,0x06,0x03,0x79,0xfe,0x01,0xca,0x06,0x03,0x7d,0xfe,0xd1,0x28,0x21,
0xc5,0x06,0x03,0x0e,0x01,0x16,0x03,0x7e,0xe6,0xf8,0xb1,0x22,0x15,0x20,0xf8,0x0c,
0x79,0xfe,0x06,0x20,0xf0,0x11,0x11,0x00,0x19,0x05,0x20,0xe7,0x11,0xa1,0xff,0x19,
0xc1,0x04,0x78,0x1e,0x83,0xfe,0x62,0x28,0x06,0x1e,0xc1,0xfe,0x64,0x20,0x07,0x7b,
0xe0,0x13,0x3e,0x87,0xe0,0x14,0xfa,0x02,0xd0,0xfe,0x00,0x28,0x0a,0x3d,0xea,0x02,
0xd0,0x79,0xfe,0x01,0xca,0x91,0x02,0x0d,0xc2,0x91,0x02,0xc9,0x0e,0x26,0xcd,0x4a,
0x03,0xcd,0x11,0x02,0xcd,0x62,0x02,0x0d,0x20,0xf4,0xcd,0x11,0x02,0x3e,0x01,0xe0,
0x4f,0xcd,0x3e,0x03,0xcd,0x41,0x03,0xaf,0xe0,0x4f,0xcd,0x3e,0x03,0xc9,0x21,0x08,
0x00,0x11,0x51,0xff,0x0e,0x05,0xcd,0x0a,0x02,0xc9,0xc5,0xd5,0xe5,0x21,0x40,0xd8,
0x0e,0x20,0x7e,0xe6,0x1f,0xfe,0x1f,0x28,0x01,0x3c,0x57,0x2a,0x07,0x07,0x07,0xe6,
0x07,0x47,0x3a,0x07,0x07,0x07,0xe6,0x18,0xb0,0xfe,0x1f,0x28,0x01,0x3c,0x0f,0x0f,
0x0f,0x47,0xe6,0xe0,0xb2,0x22,0x78,0xe6,0x03,0x5f,0x7e,0x0f,0x0f,0xe6,0x1f,0xfe,
0x1f,0x28,0x01,0x3c,0x07,0x07,0xb3,0x22,0x0d,0x20,0xc7,0xe1,0xd1,0xc1,0xc9,0x0e,
0x00,0x1a,0xe6,0xf0,0xcb,0x49,0x28,0x02,0xcb,0x37,0x47,0x23,0x7e,0xb0,0x22,0x1a,
0xe6,0x0f,0xcb,0x49,0x20,0x02,0xcb,0x37,0x47,0x23,0x7e,0xb0,0x22,0x13,0xcb,0x41,
0x28,0x0d,0xd5,0x11,0xf8,0xff,0xcb,0x49,0x28,0x03,0x11,0x08,0x00,0x19,0xd1,0x0c,
0x79,0xfe,0x18,0x20,0xcc,0xc9,0x47,0xd5,0x16,0x04,0x58,0xcb,0x10,0x17,0xcb,0x13,
0x17,0x15,0x20,0xf6,0xd1,0x22,0x23,0x22,0x23,0xc9,0x3e,0x19,0xea,0x10,0x99,0x21,
0x2f,0x99,0x0e,0x0c,0x3d,0x28,0x08,0x32,0x0d,0x20,0xf9,0x2e,0x0f,0x18,0xf3,0xc9,
0x3e,0x01,0xe0,0x4f,0xcd,0x00,0x02,0x11,0x07,0x06,0x21,0x80,0x80,0x0e,0xc0,0x1a,
0x22,0x23,0x22,0x23,0x13,0x0d,0x20,0xf7,0x11,0x04,0x01,0xcd,0x8f,0x03,0x01,0xa8,
0xff,0x09,0xcd,0x8f,0x03,0x01,0xf8,0xff,0x09,0x11,0x72,0x00,0x0e,0x08,0x23,0x1a,
0x22,0x13,0x0d,0x20,0xf9,0x21,0xc2,0x98,0x06,0x08,0x3e,0x08,0x0e,0x10,0x22,0x0d,
0x20,0xfc,0x11,0x10,0x00,0x19,0x05,0x20,0xf3,0xaf,0xe0,0x4f,0x21,0xc2,0x98,0x3e,
0x08,0x22,0x3c,0xfe,0x18,0x20,0x02,0x2e,0xe2,0xfe,0x28,0x20,0x03,0x21,0x02,0x99,
0xfe,0x38,0x20,0xed,0x21,0xd8,0x08,0x11,0x40,0xd8,0x06,0x08,0x3e,0xff,0x12,0x13,
0x12,0x13,0x0e,0x02,0xcd,0x0a,0x02,0x3e,0x00,0x12,0x13,0x12,0x13,0x13,0x13,0x05,
0x20,0xea,0xcd,0x62,0x02,0x21,0x4b,0x01,0x7e,0xfe,0x33,0x20,0x0b,0x2e,0x44,0x1e,
0x30,0x2a,0xbb,0x20,0x49,0x1c,0x18,0x04,0x2e,0x4b,0x1e,0x01,0x2a,0xbb,0x20,0x3e,
0x2e,0x34,0x01,0x10,0x00,0x2a,0x80,0x47,0x0d,0x20,0xfa,0xea,0x00,0xd0,0x21,0xc7,
0x06,0x0e,0x00,0x2a,0xb8,0x28,0x08,0x0c,0x79,0xfe,0x4f,0x20,0xf6,0x18,0x1f,0x79,
0xd6,0x41,0x38,0x1c,0x21,0x16,0x07,0x16,0x00,0x5f,0x19,0xfa,0x37,0x01,0x57,0x7e,
0xba,0x28,0x0d,0x11,0x0e,0x00,0x19,0x79,0x83,0x4f,0xd6,0x5e,0x38,0xed,0x0e,0x00,
0x21,0x33,0x07,0x06,0x00,0x09,0x7e,0xe6,0x1f,0xea,0x08,0xd0,0x7e,0xe6,0xe0,0x07,
0x07,0x07,0xea,0x0b,0xd0,0xcd,0xe9,0x04,0xc9,0x11,0x91,0x07,0x21,0x00,0xd9,0xfa,
0x0b,0xd0,0x47,0x0e,0x1e,0xcb,0x40,0x20,0x02,0x13,0x13,0x1a,0x22,0x20,0x02,0x1b,
0x1b,0xcb,0x48,0x20,0x02,0x13,0x13,0x1a,0x22,0x13,0x13,0x20,0x02,0x1b,0x1b,0xcb,
0x50,0x28,0x05,0x1b,0x2b,0x1a,0x22,0x13,0x1a,0x22,0x13,0x0d,0x20,0xd7,0x21,0x00,
0xd9,0x11,0x00,0xda,0xcd,0x64,0x05,0xc9,0x21,0x12,0x00,0xfa,0x05,0xd0,0x07,0x07,
0x06,0x00,0x4f,0x09,0x11,0x40,0xd8,0x06,0x08,0xe5,0x0e,0x02,0xcd,0x0a,0x02,0x13,
0x13,0x13,0x13,0x13,0x13,0xe1,0x05,0x20,0xf0,0x11,0x42,0xd8,0x0e,0x02,0xcd,0x0a,
0x02,0x11,0x4a,0xd8,0x0e,0x02,0xcd,0x0a,0x02,0x2b,0x2b,0x11,0x44,0xd8,0x0e,0x02,
0xcd,0x0a,0x02,0xc9,0x0e,0x60,0x2a,0xe5,0xc5,0x21,0xe8,0x07,0x06,0x00,0x4f,0x09,
0x0e,0x08,0xcd,0x0a,0x02,0xc1,0xe1,0x0d,0x20,0xec,0xc9,0xfa,0x08,0xd0,0x11,0x18,
0x00,0x3c,0x3d,0x28,0x03,0x19,0x20,0xfa,0xc9,0xcd,0x1d,0x02,0x78,0xe6,0xff,0x28,
0x0f,0x21,0xe4,0x08,0x06,0x00,0x2a,0xb9,0x28,0x08,0x04,0x78,0xfe,0x0c,0x20,0xf6,
0x18,0x2d,0x78,0xea,0x05,0xd0,0x3e,0x1e,0xea,0x02,0xd0,0x11,0x0b,0x00,0x19,0x56,
0x7a,0xe6,0x1f,0x5f,0x21,0x08,0xd0,0x3a,0x22,0x7b,0x77,0x7a,0xe6,0xe0,0x07,0x07,
0x07,0x5f,0x21,0x0b,0xd0,0x3a,0x22,0x7b,0x77,0xcd,0xe9,0x04,0xcd,0x28,0x05,0xc9,
0xcd,0x11,0x02,0xfa,0x43,0x01,0xcb,0x7f,0x28,0x04,0xe0,0x4c,0x18,0x28,0x3e,0x04,
0xe0,0x4c,0x3e,0x01,0xe0,0x6c,0x21,0x00,0xda,0xcd,0x7b,0x05,0x06,0x10,0x16,0x00,
0x1e,0x08,0xcd,0x4a,0x02,0x21,0x7a,0x00,0xfa,0x00,0xd0,0x47,0x0e,0x02,0x2a,0xb8,
0xcc,0xda,0x03,0x0d,0x20,0xf8,0xc9,0x01,0x0f,0x3f,0x7e,0xff,0xff,0xc0,0x00,0xc0,
0xf0,0xf1,0x03,0x7c,0xfc,0xfe,0xfe,0x03,0x07,0x07,0x0f,0xe0,0xe0,0xf0,0xf0,0x1e,
0x3e,0x7e,0xfe,0x0f,0x0f,0x1f,0x1f,0xff,0xff,0x00,0x00,0x01,0x01,0x01,0x03,0xff,
0xff,0xe1,0xe0,0xc0,0xf0,0xf9,0xfb,0x1f,0x7f,0xf8,0xe0,0xf3,0xfd,0x3e,0x1e,0xe0,
0xf0,0xf9,0x7f,0x3e,0x7c,0xf8,0xe0,0xf8,0xf0,0xf0,0xf8,0x00,0x00,0x7f,0x7f,0x07,
0x0f,0x9f,0xbf,0x9e,0x1f,0xff,0xff,0x0f,0x1e,0x3e,0x3c,0xf1,0xfb,0x7f,0x7f,0xfe,
0xde,0xdf,0x9f,0x1f,0x3f,0x3e,0x3c,0xf8,0xf8,0x00,0x00,0x03,0x03,0x07,0x07,0xff,
0xff,0xc1,0xc0,0xf3,0xe7,0xf7,0xf3,0xc0,0xc0,0xc0,0xc0,0x1f,0x1f,0x1e,0x3e,0x3f,
0x1f,0x3e,0x3e,0x80,0x00,0x00,0x00,0x7c,0x1f,0x07,0x00,0x0f,0xff,0xfe,0x00,0x7c,
0xf8,0xf0,0x00,0x1f,0x0f,0x0f,0x00,0x7c,0xf8,0xf8,0x00,0x3f,0x3e,0x1c,0x00,0x0f,
0x0f,0x0f,0x00,0x7c,0xff,0xff,0x00,0x00,0xf8,0xf8,0x00,0x07,0x0f,0x0f,0x00,0x81,
0xff,0xff,0x00,0xf3,0xe1,0x80,0x00,0xe0,0xff,0x7f,0x00,0xfc,0xf0,0xc0,0x00,0x3e,
0x7c,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x16,0x36,0xd1,0xdb,0xf2,0x3c,0x8c,
0x92,0x3d,0x5c,0x58,0xc9,0x3e,0x70,0x1d,0x59,0x69,0x19,0x35,0xa8,0x14,0xaa,0x75,
0x95,0x99,0x34,0x6f,0x15,0xff,0x97,0x4b,0x90,0x17,0x10,0x39,0xf7,0xf6,0xa2,0x49,
0x4e,0x43,0x68,0xe0,0x8b,0xf0,0xce,0x0c,0x29,0xe8,0xb7,0x86,0x9a,0x52,0x01,0x9d,
0x71,0x9c,0xbd,0x5d,0x6d,0x67,0x3f,0x6b,0xb3,0x46,0x28,0xa5,0xc6,0xd3,0x27,0x61,
0x18,0x66,0x6a,0xbf,0x0d,0xf4,0x42,0x45,0x46,0x41,0x41,0x52,0x42,0x45,0x4b,0x45,
0x4b,0x20,0x52,0x2d,0x55,0x52,0x41,0x52,0x20,0x49,0x4e,0x41,0x49,0x4c,0x49,0x43,
0x45,0x20,0x52,0x7c,0x08,0x12,0xa3,0xa2,0x07,0x87,0x4b,0x20,0x12,0x65,0xa8,0x16,
0xa9,0x86,0xb1,0x68,0xa0,0x87,0x66,0x12,0xa1,0x30,0x3c,0x12,0x85,0x12,0x64,0x1b,
0x07,0x06,0x6f,0x6e,0x6e,0xae,0xaf,0x6f,0xb2,0xaf,0xb2,0xa8,0xab,0x6f,0xaf,0x86,
0xae,0xa2,0xa2,0x12,0xaf,0x13,0x12,0xa1,0x6e,0xaf,0xaf,0xad,0x06,0x4c,0x6e,0xaf,
0xaf,0x12,0x7c,0xac,0xa8,0x6a,0x6e,0x13,0xa0,0x2d,0xa8,0x2b,0xac,0x64,0xac,0x6d,
0x87,0xbc,0x60,0xb4,0x13,0x72,0x7c,0xb5,0xae,0xae,0x7c,0x7c,0x65,0xa2,0x6c,0x64,
0x85,0x80,0xb0,0x40,0x88,0x20,0x68,0xde,0x00,0x70,0xde,0x20,0x78,0x20,0x20,0x38,
0x20,0xb0,0x90,0x20,0xb0,0xa0,0xe0,0xb0,0xc0,0x98,0xb6,0x48,0x80,0xe0,0x50,0x1e,
0x1e,0x58,0x20,0xb8,0xe0,0x88,0xb0,0x10,0x20,0x00,0x10,0x20,0xe0,0x18,0xe0,0x18,
0x00,0x18,0xe0,0x20,0xa8,0xe0,0x20,0x18,0xe0,0x00,0x20,0x18,0xd8,0xc8,0x18,0xe0,
0x00,0xe0,0x40,0x28,0x28,0x28,0x18,0xe0,0x60,0x20,0x18,0xe0,0x00,0x00,0x08,0xe0,
0x18,0x30,0xd0,0xd0,0xd0,0x20,0xe0,0xe8,0xff,0x7f,0xbf,0x32,0xd0,0x00,0x00,0x00,
0x9f,0x63,0x79,0x42,0xb0,0x15,0xcb,0x04,0xff,0x7f,0x31,0x6e,0x4a,0x45,0x00,0x00,
0xff,0x7f,0xef,0x1b,0x00,0x02,0x00,0x00,0xff,0x7f,0x1f,0x42,0xf2,0x1c,0x00,0x00,
0xff,0x7f,0x94,0x52,0x4a,0x29,0x00,0x00,0xff,0x7f,0xff,0x03,0x2f,0x01,0x00,0x00,
0xff,0x7f,0xef,0x03,0xd6,0x01,0x00,0x00,0xff,0x7f,0xb5,0x42,0xc8,0x3d,0x00,0x00,
0x74,0x7e,0xff,0x03,0x80,0x01,0x00,0x00,0xff,0x67,0xac,0x77,0x13,0x1a,0x6b,0x2d,
0xd6,0x7e,0xff,0x4b,0x75,0x21,0x00,0x00,0xff,0x53,0x5f,0x4a,0x52,0x7e,0x00,0x00,
0xff,0x4f,0xd2,0x7e,0x4c,0x3a,0xe0,0x1c,0xed,0x03,0xff,0x7f,0x5f,0x25,0x00,0x00,
0x6a,0x03,0x1f,0x02,0xff,0x03,0xff,0x7f,0xff,0x7f,0xdf,0x01,0x12,0x01,0x00,0x00,
0x1f,0x23,0x5f,0x03,0xf2,0x00,0x09,0x00,0xff,0x7f,0xea,0x03,0x1f,0x01,0x00,0x00,
0x9f,0x29,0x1a,0x00,0x0c,0x00,0x00,0x00,0xff,0x7f,0x7f,0x02,0x1f,0x00,0x00,0x00,
0xff,0x7f,0xe0,0x03,0x06,0x02,0x20,0x01,0xff,0x7f,0xeb,0x7e,0x1f,0x00,0x00,0x7c,
0xff,0x7f,0xff,0x3f,0x00,0x7e,0x1f,0x00,0xff,0x7f,0xff,0x03,0x1f,0x00,0x00,0x00,
0xff,0x03,0x1f,0x00,0x0c,0x00,0x00,0x00,0xff,0x7f,0x3f,0x03,0x93,0x01,0x00,0x00,
0x00,0x00,0x00,0x42,0x7f,0x03,0xff,0x7f,0xff,0x7f,0x8c,0x7e,0x00,0x7c,0x00,0x00,
0xff,0x7f,0xef,0x1b,0x80,0x61,0x00,0x00,0xff,0x7f,0x00,0x7c,0xe0,0x03,0x1f,0x7c,
0x1f,0x00,0xff,0x03,0x40,0x41,0x42,0x20,0x21,0x22,0x80,0x81,0x82,0x10,0x11,0x12,
0x12,0xb0,0x79,0xb8,0xad,0x16,0x17,0x07,0xba,0x05,0x7c,0x13,0x00,0x00,0x00,0x00,
};
#endif

View File

@@ -1,23 +0,0 @@
#ifdef SYSTEM_CPP
//SHA256 = cf053eccb4ccafff9e67339d4e78e98dce7d1ed59be819d2a1ba2232c6fce1c7
const uint8_t System::BootROM::dmg[256] = {
0x31,0xfe,0xff,0xaf,0x21,0xff,0x9f,0x32,0xcb,0x7c,0x20,0xfb,0x21,0x26,0xff,0x0e,
0x11,0x3e,0x80,0x32,0xe2,0x0c,0x3e,0xf3,0xe2,0x32,0x3e,0x77,0x77,0x3e,0xfc,0xe0,
0x47,0x11,0x04,0x01,0x21,0x10,0x80,0x1a,0xcd,0x95,0x00,0xcd,0x96,0x00,0x13,0x7b,
0xfe,0x34,0x20,0xf3,0x11,0xd8,0x00,0x06,0x08,0x1a,0x13,0x22,0x23,0x05,0x20,0xf9,
0x3e,0x19,0xea,0x10,0x99,0x21,0x2f,0x99,0x0e,0x0c,0x3d,0x28,0x08,0x32,0x0d,0x20,
0xf9,0x2e,0x0f,0x18,0xf3,0x67,0x3e,0x64,0x57,0xe0,0x42,0x3e,0x91,0xe0,0x40,0x04,
0x1e,0x02,0x0e,0x0c,0xf0,0x44,0xfe,0x90,0x20,0xfa,0x0d,0x20,0xf7,0x1d,0x20,0xf2,
0x0e,0x13,0x24,0x7c,0x1e,0x83,0xfe,0x62,0x28,0x06,0x1e,0xc1,0xfe,0x64,0x20,0x06,
0x7b,0xe2,0x0c,0x3e,0x87,0xe2,0xf0,0x42,0x90,0xe0,0x42,0x15,0x20,0xd2,0x05,0x20,
0x4f,0x16,0x20,0x18,0xcb,0x4f,0x06,0x04,0xc5,0xcb,0x11,0x17,0xc1,0xcb,0x11,0x17,
0x05,0x20,0xf5,0x22,0x23,0x22,0x23,0xc9,0xce,0xed,0x66,0x66,0xcc,0x0d,0x00,0x0b,
0x03,0x73,0x00,0x83,0x00,0x0c,0x00,0x0d,0x00,0x08,0x11,0x1f,0x88,0x89,0x00,0x0e,
0xdc,0xcc,0x6e,0xe6,0xdd,0xdd,0xd9,0x99,0xbb,0xbb,0x67,0x63,0x6e,0x0e,0xec,0xcc,
0xdd,0xdc,0x99,0x9f,0xbb,0xb9,0x33,0x3e,0x3c,0x42,0xb9,0xa5,0xb9,0xa5,0x42,0x3c,
0x21,0x04,0x01,0x11,0xa8,0x00,0x1a,0x13,0xbe,0x20,0xfe,0x23,0x7d,0xfe,0x34,0x20,
0xf5,0x06,0x19,0x78,0x86,0x23,0x05,0x20,0xfb,0x86,0x20,0xfe,0x3e,0x01,0xe0,0x50,
};
#endif

View File

@@ -1,23 +0,0 @@
#ifdef SYSTEM_CPP
//SHA256 = 0e4ddff32fc9d1eeaae812a157dd246459b00c9e14f2f61751f661f32361e360
const uint8_t System::BootROM::sgb[256] = {
0x31,0xfe,0xff,0x3e,0x30,0xe0,0x00,0xaf,0x21,0xff,0x9f,0x32,0xcb,0x7c,0x20,0xfb,
0x21,0x26,0xff,0x0e,0x11,0x3e,0x80,0x32,0xe2,0x0c,0x3e,0xf3,0xe2,0x32,0x3e,0x77,
0x77,0x3e,0xfc,0xe0,0x47,0x21,0x5f,0xc0,0x0e,0x08,0xaf,0x32,0x0d,0x20,0xfc,0x11,
0x4f,0x01,0x3e,0xfb,0x0e,0x06,0xf5,0x06,0x00,0x1a,0x1b,0x32,0x80,0x47,0x0d,0x20,
0xf8,0x32,0xf1,0x32,0x0e,0x0e,0xd6,0x02,0xfe,0xef,0x20,0xea,0x11,0x04,0x01,0x21,
0x10,0x80,0x1a,0xcd,0xd3,0x00,0xcd,0xd4,0x00,0x13,0x7b,0xfe,0x34,0x20,0xf3,0x11,
0xe6,0x00,0x06,0x08,0x1a,0x13,0x22,0x23,0x05,0x20,0xf9,0x3e,0x19,0xea,0x10,0x99,
0x21,0x2f,0x99,0x0e,0x0c,0x3d,0x28,0x08,0x32,0x0d,0x20,0xf9,0x2e,0x0f,0x18,0xf3,
0x3e,0x91,0xe0,0x40,0x21,0x00,0xc0,0x0e,0x00,0x3e,0x00,0xe2,0x3e,0x30,0xe2,0x06,
0x10,0x1e,0x08,0x2a,0x57,0xcb,0x42,0x3e,0x10,0x20,0x02,0x3e,0x20,0xe2,0x3e,0x30,
0xe2,0xcb,0x1a,0x1d,0x20,0xef,0x05,0x20,0xe8,0x3e,0x20,0xe2,0x3e,0x30,0xe2,0xcd,
0xc2,0x00,0x7d,0xfe,0x60,0x20,0xd2,0x0e,0x13,0x3e,0xc1,0xe2,0x0c,0x3e,0x07,0xe2,
0x18,0x3a,0x16,0x04,0xf0,0x44,0xfe,0x90,0x20,0xfa,0x1e,0x00,0x1d,0x20,0xfd,0x15,
0x20,0xf2,0xc9,0x4f,0x06,0x04,0xc5,0xcb,0x11,0x17,0xc1,0xcb,0x11,0x17,0x05,0x20,
0xf5,0x22,0x23,0x22,0x23,0xc9,0x3c,0x42,0xb9,0xa5,0xb9,0xa5,0x42,0x3c,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x01,0xe0,0x50,
};
#endif

View File

@@ -1,82 +0,0 @@
#include <gameboy/gameboy.hpp>
#define VIDEO_CPP
namespace GameBoy {
Video video;
unsigned Video::palette_dmg(unsigned color) const {
unsigned R = monochrome[color][0] * 1023.0;
unsigned G = monochrome[color][1] * 1023.0;
unsigned B = monochrome[color][2] * 1023.0;
return (R << 20) + (G << 10) + (B << 0);
}
unsigned Video::palette_sgb(unsigned color) const {
unsigned R = (3 - color) * 341;
unsigned G = (3 - color) * 341;
unsigned B = (3 - color) * 341;
return (R << 20) + (G << 10) + (B << 0);
}
unsigned Video::palette_cgb(unsigned color) const {
unsigned r = (color >> 0) & 31;
unsigned g = (color >> 5) & 31;
unsigned b = (color >> 10) & 31;
unsigned R = (r * 26 + g * 4 + b * 2);
unsigned G = ( g * 24 + b * 8);
unsigned B = (r * 6 + g * 4 + b * 22);
R = min(960, R);
G = min(960, G);
B = min(960, B);
return (R << 20) + (G << 10) + (B << 0);
}
void Video::generate(Format format) {
if(system.dmg()) for(unsigned n = 0; n < 4; n++) palette[n] = palette_dmg(n);
if(system.sgb()) for(unsigned n = 0; n < 4; n++) palette[n] = palette_sgb(n);
if(system.cgb()) for(unsigned n = 0; n < (1 << 15); n++) palette[n] = palette_cgb(n);
if(format == Format::RGB24) {
for(unsigned n = 0; n < (1 << 15); n++) {
unsigned color = palette[n];
palette[n] = ((color >> 6) & 0xff0000) + ((color >> 4) & 0x00ff00) + ((color >> 2) & 0x0000ff);
}
}
if(format == Format::RGB16) {
for(unsigned n = 0; n < (1 << 15); n++) {
unsigned color = palette[n];
palette[n] = ((color >> 14) & 0xf800) + ((color >> 9) & 0x07e0) + ((color >> 5) & 0x001f);
}
}
if(format == Format::RGB15) {
for(unsigned n = 0; n < (1 << 15); n++) {
unsigned color = palette[n];
palette[n] = ((color >> 15) & 0x7c00) + ((color >> 10) & 0x03e0) + ((color >> 5) & 0x001f);
}
}
}
Video::Video() {
palette = new unsigned[1 << 15];
}
Video::~Video() {
delete[] palette;
}
const double Video::monochrome[4][3] = {
{ 0.605, 0.734, 0.059 },
{ 0.543, 0.672, 0.059 },
{ 0.188, 0.383, 0.188 },
{ 0.059, 0.219, 0.059 },
};
}

View File

@@ -1,17 +0,0 @@
struct Video {
enum class Format : unsigned { RGB30, RGB24, RGB16, RGB15 };
unsigned *palette;
unsigned palette_dmg(unsigned color) const;
unsigned palette_sgb(unsigned color) const;
unsigned palette_cgb(unsigned color) const;
void generate(Format format);
Video();
~Video();
private:
static const double monochrome[4][3];
};
extern Video video;

16
bsnes/gb/Makefile Executable file
View File

@@ -0,0 +1,16 @@
gb_objects := gb-interface gb-system gb-scheduler
gb_objects += gb-memory gb-cartridge
gb_objects += gb-cpu gb-ppu gb-apu
gb_objects += gb-cheat gb-video
objects += $(gb_objects)
obj/gb-interface.o: $(gb)/interface/interface.cpp $(call rwildcard,$(gb)/interface/)
obj/gb-system.o: $(gb)/system/system.cpp $(call rwildcard,$(gb)/system/)
obj/gb-scheduler.o: $(gb)/scheduler/scheduler.cpp $(call rwildcard,$(gb)/scheduler/)
obj/gb-cartridge.o: $(gb)/cartridge/cartridge.cpp $(call rwildcard,$(gb)/cartridge/)
obj/gb-memory.o: $(gb)/memory/memory.cpp $(call rwildcard,$(gb)/memory/)
obj/gb-cpu.o: $(gb)/cpu/cpu.cpp $(call rwildcard,$(gb)/cpu/)
obj/gb-ppu.o: $(gb)/ppu/ppu.cpp $(call rwildcard,$(gb)/ppu/)
obj/gb-apu.o: $(gb)/apu/apu.cpp $(call rwildcard,$(gb)/apu/)
obj/gb-cheat.o: $(gb)/cheat/cheat.cpp $(call rwildcard,$(gb)/cheat/)
obj/gb-video.o: $(gb)/video/video.cpp $(call rwildcard,$(gb)/video/)

View File

@@ -1,4 +1,4 @@
#include <gameboy/gameboy.hpp>
#include <gb/gb.hpp>
#define APU_CPP
namespace GameBoy {
@@ -46,10 +46,10 @@ void APU::main() {
noise.run();
master.run();
interface->audioSample(master.center, master.left, master.right);
interface->audioSample(master.left, master.right);
clock += 1 * cpu.frequency;
if(clock >= 0) co_switch(scheduler.active_thread = cpu.thread);
clock += cpu.frequency;
if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(scheduler.active_thread = cpu.thread);
}
}

View File

@@ -1,4 +1,4 @@
struct APU : Processor, MMIO {
struct APU : Thread, MMIO {
#include "square1/square1.hpp"
#include "square2/square2.hpp"
#include "wave/wave.hpp"

View File

@@ -20,36 +20,18 @@ void APU::Master::run() {
if(channel2_left_enable) sample += apu.square2.output;
if(channel3_left_enable) sample += apu.wave.output;
if(channel4_left_enable) sample += apu.noise.output;
left = (sample * 512) - 16384;
switch(left_volume) {
case 0: left >>= 3; break; // 12.5%
case 1: left >>= 2; break; // 25.0%
case 2: left = (left >> 2) + (left >> 3); break; // 37.5%
case 3: left >>= 1; break; // 50.0%
case 4: left = (left >> 1) + (left >> 3); break; // 62.5%
case 5: left -= (left >> 2); break; // 75.0%
case 6: left -= (left >> 3); break; // 87.5%
//case 7: break; //100.0%
}
sample = (sample * 512) - 16384;
sample = (sample * (left_volume + 1)) / 8;
left = sample;
sample = 0;
if(channel1_right_enable) sample += apu.square1.output;
if(channel2_right_enable) sample += apu.square2.output;
if(channel3_right_enable) sample += apu.wave.output;
if(channel4_right_enable) sample += apu.noise.output;
right = (sample * 512) - 16384;
switch(right_volume) {
case 0: right >>= 3; break; // 12.5%
case 1: right >>= 2; break; // 25.0%
case 2: right = (right >> 2) + (right >> 3); break; // 37.5%
case 3: right >>= 1; break; // 50.0%
case 4: right = (right >> 1) + (right >> 3); break; // 62.5%
case 5: right -= (right >> 2); break; // 75.0%
case 6: right -= (right >> 3); break; // 87.5%
//case 7: break; //100.0%
}
sample = (sample * 512) - 16384;
sample = (sample * (right_volume + 1)) / 8;
right = sample;
}
void APU::Master::write(unsigned r, uint8 data) {

Some files were not shown because too many files have changed in this diff Show More