2010-12-26 - bsnes_v073r01.tar.bz2 (Windows 32-bit compatibility binary included)
While perhaps not perfect, pretty good is better than nothing ... I've added emulation of auto-joypad poll timing.
Going off ikari_01's confirmation of what we suspected, that the strobe happens every 256 clocks, I've set up emulation as follows:
Upon reset, our clock counter is reset to zero.
At the start of each frame, our poll counter is reset to zero.
Every 256 clocks, we call the step_auto_joypad_poll() function.
If we are at V=225/240+ (based on overscan setting), we check the poll counter.
At zero, we poll the actual controller and set the joypad polling flag in $4212.d0 to 1.
From zero through fifteen, we read in one bit for each controller and shift it into the register.
At sixteen, we turn off the joypad polling flag.
The 256-clock divider allows the start point of polling for each frame to fluctuate wildly like real hardware.
I count regardless of auto joypad enable, as per $4212.d0's behavior; but only poll when it's actually enabled.
I do not consume any actual time from this polling. I honestly don't know if I even should, or if it manages to do it in the background.
If it should consume time, then this most likely happens between opcode edges and we'll have to adjust the code a good bit.
All commercial games should continue to work fine, but this will likely break some hacks/translations not tested on hardware.
Without the timing emulation, reading $4218-421f before V=~228 would basically give you the valid input controller values of the previous frame.
Now, like hardware, it should give you a state that is part previous frame, part current frame shifted into it. Button positions won't be reliable and will shift every 256 clocks.
I've also removed the Qt GUI, and renamed ui-phoenix to just ui. This removes 400kb of source code (phoenix is a lean 130kb), and drops the archive size from 564KB to 475KB. Combined with the DSP HLE, and we've knocked off ~570KB of source cruft from the entire project. I am looking forward to not having to specify which GUI is included anymore.
2010-12-24 - bsnes_v073.tar.bz2
This release marks a major step forward, offering full low-level emulation of all four DSP coprocessors based on the NEC uPD77C25 processor core. Many people were responsible for this milestone: Dr. Decapitator for the actual decapping and extraction; Lord Nightmare for the cartridges and some special analysis tools; myself, Jonas Quinn and Cydrak for the uPD77C25 emulation; and all of the donors who raised the necessary $1,000 for the necessary hardware and equipment needed to pull this all off. To say thanks to the donors, I am releasing the uPD77C25 emulation core to the public domain, so that everyone can benefit from it.
All four DSP emulations will be improved by this by way of having realistic timing; the DSP-4 will benefit further as the high-level emulation was incomplete and somewhat buggy; and the DSP-3 will benefit the most as the high-levle emulation there was not complete enough to be playable. As a result, most notably, this means bsnes v073 is the first emulator to fully be able to play SD Gundam GX (J)!
As bsnes' primary goal is accuracy, the LLE DSP support renders the old HLE DSP support obsolete. Ergo, I have removed the 166KB of HLE source code, and replaced it with the uPD77C25 core, which comprises a mere 20KB of source code. As this LLE module supports save states, this also means that for the first time, DSP-3 and DSP-4 games have save state support.
On the other hand, this also means that to run any DSP game, you will need the appropriate program ROM. As these are copyrighted, I cannot distribute them nor tell you where to get them. All I can do is provide you with the necessary filenames and hashes.
SHA256:
Code:
5f2e5ed06b362be023b978b5978813ecb9a07c76592454b45c2a1ed17a0de349 dsp1.bin
4d42db0f36faef263d6b93f508e8c1c4ae8fc2605fd35e3390ecc02905cd420c dsp1b.bin
5efbdf96ed0652790855225964f3e90e6a4d466cfa64df25b110933c6cf94ea1 dsp2.bin
2e635f72e4d4681148bc35429421c9b946e4f407590e74e31b93b8987b63ba90 dsp3.bin
63ede17322541c191ed1fdf683872554a0a57306496afc43c59de7c01a6e764a dsp4.bin
MD5SUM:
Code:
4865ac61cd758b0f9383fe3d4d3b8694 dsp1.bin
c8bfb983703a96e1c3d4683105112bc0 dsp1b.bin
e500ec7f6005e78cb935eea5289c8cc4 dsp2.bin
c037185c8bbef6313226200dbe5fd07f dsp3.bin
fe85065a7023551b0d84941a094435ba dsp4.bin
All of these files are exactly 8KB (8,192 bytes) in size.
Changelog:
added NEC uPD77C25 emulation core
added low-level emulation of the DSP-1, DSP-1B, DSP-2, DSP-3, DSP-4 coprocessors
removed high-level emulation of the DSP-n coprocessors
added blargg's libco::ppc.c module, which is far more portable, even running on the PS3
added software filter support via binary plugins
added debugger (currently Linux-only); but it is as yet unstable
added SNES::interface.message(const string&) so that the core can send messages for the GUI to display
failing to load a DSP-n ROM, or failing the DSP-n SHA256 hash (if there is one) will result in a warning message
all DSP-1 games by default once again use the DSP-1B program, now that it has been redumped and reverified
fixed bugs in uPD77C25 SHL2 and SHL4 opcodes; fixes DSP-2 and DSP-4 emulation
removed all DSP HLE (DSP-1, DSP-2, DSP-3, DSP-4)
as a result of LLE, DSP-3 and DSP-4 games can now load and save states
DSP-1 HLE: 66.9KB (no timing)
DSP-2 HLE: 9.7KB (no timing)
DSP-3 HLE: 24.8KB (no timing, missing opcodes, not bit-perfect, not playable, no save state support, GPLv2 or non-commercial license only)
DSP-4 HLE: 64.4KB (no timing, not bit-perfect, no save state support, GPLv2 or non-commercial license only)
Total HLE: 165.9KB
Versus:
uPD77C25 LLE: 19.8KB
2010-12-22 - bsnes_v072r13.tar.bz2 (source code only.)
The DSP-1 and DSP-3 emulation appears to be great.
However, there are bugs in the other two.
DSP-2, Dungeon Master: the graphics in-game appear corrupt. It looks like the first two pixels have the right color, the next six have the wrong color, resulting in vertical stripes.
DSP-4, Top Gear 3000: the car sprites appear to be showing 8x8 tiles instead of 16x16 files, resulting in 3/4ths of the cars being invisible, but only up close.
Dr. Decapitator and Lord Nightmare are supremely confident that our dumps are 100% accurate, there was no bus wavering at all this time.
We believe they are bugs in the uPD77C25 emulation.
I desperately need help! I have spent the past several hours trying to ascertain what the problem is, to no avail.
I've tried messing with just about every flag, every register, checking for use of OV1, S1, custom opcodes, etc ... I am having no luck.
I'm going to keep trying with even more sophisticated cross-analysis.
But Cydrak, if you would please rework that magic of yours, I'd be eternally grateful :D
2010-12-21 - bsnes_v072r12.tar.bz2 (source code only.)
This release defaults DSP-3 loading to use the uPD77C25 core. It also pre-emptively does the same for the DSP-2 and DSP-4. v072r11 did this for the DSP-1.
I've also renamed my string<>integer conversion function names:
strhex -> hex
strsigned -> integer
strunsigned -> decimal
strbin -> binary
strdouble -> fp (this one will no doubt be trouble since 'file fp' is a common idiom. floatingpoint is too long, float and double are already reserved.)
The reason for this is so that string building is not so hideous.
Pre-C++0x:
Code:
string output = string() << "A: " << strhex<4>(a) << " B: " << strhex<4>(b) << "\n";
Before:
Code:
string output = { "A: ", strhex<4>(a), " B: ", strhex<4>(b), "\n" };
After:
Code:
string output = { "A: ", hex<4>(a), " B: ", hex<4>(b), "\n" };
2010-12-18 - bsnes_v072r11.tar.bz2
This release marks a major milestone: low-level emulation of the DSP-1B coprocessor, used by the following games:
Ace Wo Nerae
Armored Trooper Votoms
Ballz 3D
Battle Racers
Bike Daisuki! Hashiriya Kon
Final Stretch
Korean League
Lock On/Super Air Diver
Michael Andretti's Indy Car Challenge
Pilotwings
Super 3D Baseball
Super Air Diver 2
Super Bases Loaded 2
Super F1 Circus Gaiden
Super Mario Kart
Suzuka 8 Hours
Syutoko Battle Racing 2
Syutoko Battle Racing 94
This represents a major advance in their accuracy. More specifically, this low-level emulation allows for absolutely perfect timings, whereas the DSP-1B had no timing whatsoever before with the previous high-level simulation code.
You can download the new release under the source section of the bsnes page, or from my Google Code page. Please note that you will need the DSP-1B program ROM to play these games now, and I absolutely cannot provide you with this or tell you where to get it, as it is a copyrighted work.
If you would like to read more on this feat, please see the latest article: The future of SNES coprocessor emulation.
Donations needed to advance SNES emulation:
Also, please see the bottom of that article: I need donations in order to have the DSP-2, DSP-3 and DSP-4 coprocessor program ROMs extracted. By helping with this, we will vastly improve the emulation accuracy of: Dungeon Master, SD Gundam GX and Top Gear 3000. SD Gundam GX is unplayable in any emulator as of yet, and Top Gear 3000 has various AI issues due to incomplete simulation.
Or simply jump straight to the donation info page: donations needed.
Thank you in advance to anyone who can help!
2010-12-18 - bsnes_v072r10.tar.bz2
Current code.
2010-12-16 - bsnes_v072r09.tar.bz2
Fixes OP/LD RQM=1 on DR modify, Mario Kart can get in-game, but the track is completely corrupted.
Reorders order of operations for OP, in an attempt to mimic parallelism.
Added support for OP KLM DST.
Added S1 flag setting, probably not correct.
I've updated the disassembly. It is now in: src,dest format, as that is what the official development tools use. Added $ to hex values for consistency with the S-CPU disassembly.
Now, here is a list of issues that need to be addressed, as far as I know.
Multiplication happens after each opcode, K*L is put into M,N. But it mentions the result is 30-bit with a sign bit. Isn't that the same thing as 31-bit? Or is it possible it is acting like the sign bit of the flag registers, and just mirroring the highest bit?
What is the order of operations for OP/RT? Take this example:
Code:
4eb inc a
mov a,rp
To dump the data ROM correctly, we have to do the mov first, and the inc second.
The way I've implemented it was to do the inc read, then the mov read, then the inc write, then the mov write.
Both have the ability to manipulate both the IDB register and any shared registers.
It is at least somewhat clear from the documentation that the DPL, DPHM and RP adjustments happen at the end of the opcode.
How in the hell do we calculate the OV1 flags? The documentation says it's set to 1 if there were an odd number of the three overflows. What three overflows?
What about the S1 flag? Is it set to 1 on a positive overflow, or set to 1 on a negative overflow? What happens if there is no overflow, does it get set to zero always then?
The SGN register may be a useful hint to figuring this one out.
Am I even calculating OV0 correctly?
CMP (one's complement) is just !Q, right? They would say NOT if they wanted ~Q.
How exactly does XCHG work? The document says it's an 8-bit exchange. Which 8-bits, the top eight or the bottom eight? It updates the S0 flag which is suspicious for the bottom eight.
What is up with KLM mode? The nicer doc says you read from RAM[DP | 0x40], while the uglier one says that you read from RAM[(DP & 0x3f) | 0x40]. They list it as HiRAM, yet it forces D6=1 rather than D7=1. And just out of curiosity, why the fuck does it force D6=1? What possible use is that?
The stack has four levels, and it is LIFO. So what happens when you pull an address off the stack? Does the now empty slot at the end get set to zero, or keep the previous address, or does it act more like a ring buffer and move the old first value to the last value?
When SR.DRC=0 (eg 16-bit DR transfer mode), does RQM get cleared for each 8-bit write, or only after two 8-bit writes (eg after a full 16-bit transfer)?
What happens to the high 8-bits of the 16-bit DR register when you write to it from the S-CPU in 8-bit DR transfer mode? Does it keep whatever was there, or is it forced to zero ala 65816 index registers?
Sadly, I think the only way we are going to be able to improve from here is going to be to log S-CPU DR reads from both the HLE and LLE emulation, find differences, and then start trying to parse the uPD disassembly code directly to figure out where the wrong results in the LLE log are coming from. Eg basically what I did with the simplest case of analyzing the data ROM dumping function.
2010-12-16 - bsnes_v072r08.tar.bz2
mariokart.tar.bz2
This WIP adds NEC uPD77C25 emulation. Unfortunately it's not at all functional yet, there are way too many things I don't understand about the chip.
I'm absolutely going to need help to complete this.
What I have is 'functionally' complete, but obviously wrong in probably dozens of places.
The biggest things I don't understand:
how does L decide whether to pull from data ROM or IDB?
how are OV1 and S1 calculated?
is my OV0 implementation correct?
how exactly is RQM set again from DR/IDB activity?
is RQM cleared after reading a full 16-bits of data or after each 8-bits in DRC=0 (16-bit) mode?
why is ALU op 15 called XCHG? The examples all move from P to Acc, so it's not really modifying P right?
what is the exact order of OP/RT opcode execution? Each instruction can do something like five different things.
Stuff I don't understand that doesn't seem to matter for the SNES usage scenario (no serial hookups, as far as I can tell):
what the hell is all the SI/SO shit about?
what about DMA?
what about interrupts? (these seem simple enough, just jump to PC=100 and push the address, and modify SR.EI)
Otherwise, we're definitely at a good starting point. For now, you need the included PCB XML to manually map the program/data ROM in, which are included with the archive. You'll have to rewrite the map yourself to run other DSP-1 games, unless they have the same layout as Mario Kart. I am using the US [!] version, name it mariokart.sfc and put all the archive files and the ROM together.
From here, bsnes will load up the ROMs, and start executing instructions. Since the emulation is so incomplete, it just deadlocks on the "Nintendo" logo as if there were no DSP on the cart at all, but if you enable tracing, you'll see it actually starts doing a lot of stuff before getting stuck in a really long and confusing loop.
2010-11-02 - bsnes_v072r07.tar.bz2
I'm happy enough with the debugger now. Not 100% up to par with the old one, but it also does some new things the old one didn't.
step into / step over are disabled unless they can be done safely
this means step over is usually grayed unless you hit step into first, due to bsnes not being opcode-based (you can't skip an opcode that is half-executed)
you can now trace console output to disk
stepping the CPU will print stepped SMP opcodes if the checkbox for it is on and vice versa
button added to clear the console log
The only things left are pretty minor:
add VRAM viewer
add OAM list viewer
add CGRAM viewer
add properties viewer
add "Proceed" support to CPU/SMP debuggers (glorified breakpoints, basically)
And then long-term vision stuff to follow that:
add SA-1 debugger
add SuperFX debugger
add "Trace for n opcodes" functionality
But yeah, overall good enough for now. So the next major undertaking is going to be gutting the bsnes/Qt debugger, which is required to port that GUI to libsnes.
Once done, bsnes/Qt will be a totally separate program, with a separate source distribution. I'll merge snesreader and old snesfilter directly into it. No DLLs.
And after all that is done, I'll spin the entire thing off. Maybe we can set up an SVN with a list of people who can commit patches to it and we can host binaries there.
2010-11-01 - bsnes_v072r06.tar.bz2
Updated libsnes to use new file and function names.
Also added EditBox::setCursorPosition for GTK+ and Qt, only used by the debugger so far so that when text is added, it auto-scrolls to the bottom.
2010-10-29 - bsnes_v072r04.tar.bz2
I guess two days is a while.
nall/snes/smp.hpp created, ~68 addressing modes compared to the CPU's ~27, ugh.
All hooked up, you can step into / step over / trace the S-SMP now as well.
Word of caution, not a good idea to try stepping over without stepping into at least once first. I'll make it a requirement later.
Reason is you may not be on an opcode edge at the time, because of course bsnes isn't an opcode-based emulator.
2010-10-27 - bsnes_v072r02.tar.bz2
Just debugger work here. About three or four hours to write nall/snes/cpu.hpp, which is basically opcode encoding information for disassembly.
The disassembler inside bsnes itself was kind of limited, it always spit out all register info, had no flexibility to insert custom symbols/labels for debugging information, and the disassembler was very limited because it relied on the current processor status register M/X flags, rather than what they were when the opcode was executed. That information is stored in my usage table.
So after hours of making that table by hand, I hooked that in and got proper forward+backward disassembly working, along with "step over". Still have to add "proceed".
Given what a pain in the ass that was, I'm probably going to put off the S-SMP debugger for a while :P
2010-10-26 - bsnes_v072r01.tar.bz2
includes Windows 64-bit performance binary
Changelog:
added pause shortcut ('P' key, as pause/break is too finicky)
pause and auto-pause show on status bar
added a debugger skeleton, very very primitive and completely unusable - don't try it yet
added software filter support
Also included is the new snesfilter library. It has all of the filters the old one had, as well as scanline filters since that's not in my GUI anymore
If you want scanlines and other software filters, then you can either make your own hybrid two-in-one software filter, or make a pixel shader (I don't have one of those yet.)
To use a software filter, go to video settings and pick the appropriate .filter from snesfilter/out/windows/name.filter
On Windows the pixel shader gets screwy when you change software filters, so just restart if you use both and see an issue.
2010-10-22 - bsnes_v072.tar.bz2
bsnes v072: there's no need to upgrade if you already have v071. This update just fixes some minor things and fixes Qt compilation on Windows.
Changelog:
fixed a compilation issue with bsnes/Qt on Windows
fixed a minor bug with UPS patching
Windows/OpenGL driver was not restoring pixel shader when toggling video synchronization
King of Chaos was nice enough to create Windows binaries of the Qt port, so if you want those, you can download those here. Check his signature for the links.
2010-10-22 - bsnes_v071.tar.bz2
It is very important to note if you choose to use my binaries, the phoenix port does not support ROM images with copier headers, ROM images that do not end in .sfc (for SNES cartridges), .st (for Sufami Turbo cartridges), .bs (for BS-X flash cartridges), or (.gb,.gbc,.sgb) for Game Boy cartridges, it does not support compressed images, it does not support software filters, rewind support, fullscreen mode, IPS patches, cheat searching, movie recording, native OS file dialog boxes, asciiPad simulation, video region cropping, layer/channel toggle, slowdown, etc. It is meant to be minimal, and if this is a problem for you, please stick with the Qt port.
Undoubtedly, no matter how much I emphasize this, people are going to not read this, use the phoenix port, and be put off and not use bsnes anymore. That's very unfortunate, but I am releasing this GUI anyway for those who do share my design goals and aesthetics.
So I will ask a favor of you all, if you see someone mentioning something of the phoenix port not working, please advise them that it is not the general use version, and that they should stick with the Qt port. Thanks in advance.
Changelog:
fixed a regression in the accuracy/compatibility CPU core with IRQ masking; fixes World Heroes 2
fixed OAM address reset on $2100 writes for performance PPU core; fixes Mahjongg 2 and others
DSP-1 always returns high 8-bits of status register; fixes Ace wo Nerae! freeze [Jonas Quinn]
performance core can now take advantage of serial support
pixel shaders now use a unified XML format; in the future they will support multi-pass shaders and textures
major code restructuring
first public release of phoenix GUI port
mightymo's cheat code pack is now an external file for the phoenix port
phoenix port stores cheat codes in XML format as well, unifying all file formats to the same markup language
2010-10-17 - bsnes_v070r17.tar.bz2
No binaries, basically the same as v070r16a on Google Code, only this one has source code
Changelog:
fixes DSP-1 status register for "Ace wo Nerae!"
fixes IRQ masking for "World Heroes II"
fixes compilation for the Qt port's debugger
I'm pretty much happy with the GUI at this point. So now I just need to add a debugger, and I'm calling it a day.
I'm probably going to go back to overclocking my E8400 and only use the accuracy core myself.
2010-10-13 - bsnes_v070r16a.tar.bz2
2010-10-11 - bsnes_v070r16.tar.bz2
Windows 64-bit non-PGO performance binary included.
This mostly contains improvements for nall, like path unification.
This should fix FitzRoy's issue with .. on Windows.
2010-10-09 - bsnes_v070r14.tar.bz2
Only source, I left v12 up if you want a Windows binary.
Changelog:
nall/string: trim and split functions now take the limit as a template parameter for clarity, trim_once variants are removed
-- quotable.trim<1>("\""); //remove quotes from string
-- cheatcode.split<3>(","); //split up to three times, third one is a description that may have commas
-- foobar.trim(" "); //remove any and all spaces
nall/string: added wildcard() and iwildcard() functions for pattern matching
nall/directory: accepts an optional pattern parameter to perform wildcard matching
-- lstring cartridges = directory::contents(path, ".sfc");
-- some people may prefer directory::contents("/path/to/files/.sfc"), but I like not having to build a string when you have the path separated already
nall/qt: removed entirely, now resides in bsnes/ui-qt/template; I do intend to replace the check/radio actions with native Qt versions later
bsnes/data: new folder, share the parts that both UIs use; bsnes.ico, bsnes.png, bsnes.Desktop, cheats.xml; simplify Makefile install target
Makefile: install target now creates .bsnes folder and copies cheats.xml there for you
Makefile: gconftool hack removed, not needed for phoenix, will work around with Qt later
will probably make bsnes/Qt read the cheats.xml file externally as well, as that file makes each profile 1MB bigger when embedded
-- as such, will probably make bsnes also look in the binary directory for that file, so Windows users don't have to copy it to their userdata folder
2010-10-08 - bsnes_v070r12.tar.bz2
Windows 64-bit non-PGO performance binary included.
Changelog:
removed support for images with copier headers
phoenix/Windows: Label properly refreshes on text changes, fixes video settings sliders
alt/ppu-performance: fixed mosaic Voffset bug, fixes Super Bowling et al
alt/cpu: fixed CPU::joylatch() reporting, allows serial applications to work with performance profile
hooked up SNES::cartridge.basename, allows MSU1 and serial support with the phoenix UI
updated UPS patching code for bsnes/Qt, allowing it to compile again, hidden config option file.bypassPatchCrc32 was removed
To automatically and recursively fix all SNES ROM extensions and remove all headers, use snespurify:
snespurify_v01.tar.bz2
Basically, put it in your ROM folder and run it. I strongly suggest you do this from a command-line so you can see the output. You can also see what it will do PRIOR to it actually doing it by using this syntax:
"snespurify /path/to/purify -analyzeonly"
If you stick it in "C:" or "/" and run it, expect it to break your entire OS. Thanks to the dumbasses that thought it'd be a good idea to distribute SNES ROMs with .bin as an extension, it will probably end up renaming your non-SNES .bin files to .sfc, and if any of those are important, you'll be in trouble.
When the preservation project finally happens, I'll be removing cartridge header parsing as well and requiring XML. I'll probably have an internal database for known commercial games, and allow snespurify to generate XML for the rest.
It also won't extract compressed images yet, nor will it fix overdumps, and I can probably do a better job ignoring non-SNES .bin files. It's v01, give it time people.
2010-10-08 - bsnes_v070r11.tar.bz2
Windows 64-bit non-PGO performance binary included.
Changelog:
phoenix/All: converted all instances of const char* to const nall::string&
-- above used to require: label.setText(string("FPS: ", fps)); but can now use: label.setText({"FPS", fps});
-- also avoids the need for the internal implementations to have to check for null string pointers
phoenix/GTK+: no longer disabling double buffering on the viewport. Does not cause flickering, and fixes redraw issue on window resize
phoenix/Qt: like phoenix/GTK+, it will use the default font on the menubar as well, so child menu items are consistently sized now
Linux: file browser can list contents of / and won't let you go higher; Windows needs a similar guard for n:/ or \
UPS soft-patching support added
external XML memory map loading support added
cartridge folder support added: if folder ends in .sfc and there is ONE .sfc ROM inside it, it will load the folder as if it were a ROM
input assignment refreshes text instead of reloading the list, this saves your position
-- auto-advance wasn't working very well, will try again later
input clear all button removed since it's pretty fast now to do clear+down:repeat
Remaining:
need to hook up SNES::cartridge.basepath for MSU1/serial support, can't believe I forgot that tonight
need to repaint on Label::setText() on phoenix/Windows
maybe some GUI hotkeys
maybe fullscreen
I'm probably going to put the last two off, and call it a day once MSU1/serial is hooked up.
2010-10-05 - bsnes_v070r10.tar.bz2
Windows 64-bit non-PGO performance binary included.
Changelog:
added workaround to phoenix/Windows to prevent horizontal scrollbar always being visible on single-column ListBoxes
phoenix gains Window::geometry()
added code to save and restore window positions, as in bsnes/Qt. Positions are saved to bsnes-phoenix-geometry.cfg this time
resizing the main window will keep its position onscreen now
There's one issue with GTK+, if you close a window and then call gtk_window_get_position(), it returns the previously set position rather than where you actually placed the window. My easy fix of calling gtk_window_get_position right before actually closing the window didn't work, so for now you'll have to live with it.
Overall, just as Qt had bugs, all toolkits and APIs have bugs. But at least these are minor, cosmetic, and mostly fixable.
2010-10-05 - bsnes_v070r09.tar.bz2
No binaries included.
Changelog:
removed native OS dialog option, I don't plan to add all the code required to make it optional everywhere
cheat database supported, although it's external now. Either in the .bsnes folder or with the binary, named cheats.xml
cheats.xml is external so that binaries can be much smaller, important for multiple profiles
added "find codes" button to cheat editor (need to gray it out permanently if cheats.xml isn't found)
added cheat database add window, works the same as bsnes/Qt, but it will also alert you if you run out of empty cheat slots upon import
note: I should rename that ok button to "Import"
hooked up callbacks for multitap/mouse/SS/justifier input
added mapping for mouse axes and buttons
used a simplified approach that only lets you map left/middle/right buttons, but doesn't need a separate popup window or fake controls
moved capture mouse command to tools menu
different from Qt where you'd click inside the main window, meant to be safer from accidental capture, escape still releases capture
made a skeleton for GUI hotkey support, but the only hotkey is escape
Remaining work:
hook up UPS patching, XML mapping and ROM folders
add GUI hotkeys
work out something for fullscreen support
maybe add Hotkey Settings window to reassign them (otherwise config file editing will be needed)
2010-10-04 - bsnes_v070r08.tar.bz2
No binaries included.
Changelog:
all three ports of phoenix gain the ability to use ListBox::setCheckable(), checked(row), setChecked(row, checked = true);
cheat editor updated to take advantage of this
Some fun differences between the implementations. Windows was the least flexible, it only lets you have a check at the start of each item. Luckily that's all I need for my purposes so it'll work. It's also a lot easier, as now I don't need a ton of extra code to try and set per-column checkboxes. Now both Windows and Qt can put text into the first item with the checkbox, but GTK+ cannot. Further, Qt needs this because even if you hide the checkbox column, it still tries to search for typed text from the checkbox column. GTK+ does this too, but unlike GTK+, Qt lacks an API call to set the search column. Since my code basically has to change this in real-time since you have to call the setProperty functions after create(), this means I always set up the checkbox columns regardless of whether or not they are used. For Qt, I had to work around this and it'll be an annoying edge case if you try and use setCheckable(true) and then setCheckable(false), because Qt has no way to clear the checkboxes from an item once
you've enabled them for the first time. But without doing it this way, there's no way for eg the ROM file loader to allow type-searching, so that's the way I do it. Windows works the same, and GTK+ has a separate column (hidden from the phoenix API standpoint) for the checkboxes, with no column header label text.
All in all, a major hassle, but it was the only really major GUI hit from leaving Qt, aside from the horror that's going to be the debugger, which needs all kinds of highly specialized controls.
2010-10-03 - bsnes_v070r07.tar.bz2
No binary included.
Changelog:
added menu options to select controller port devices, they do actually work too
however, input mapping can't map analog axes yet, and the mouse can't be captured yet, so it's of little use
added clear and clear all buttons to the input mapper window, mainly because there was no reason not to (escape clears active input too)
going to be adding a "special" button in the future that lets you map mouse axes and buttons
fixed phoenix/Qt port, both the video rendering and Window::focused() commands work now
The way I've implemented mouse mapping has always been screwy. So the special button is going to pop open another window. For digital mapping, it'll let you choose a mouse button, and for analog mapping, it'll let you choose an axis. May add in some manual joypad assignment stuff in there for analog joypad buttons, those things are impossible to auto-detect.
2010-10-02 - bsnes_v070r06.tar.bz2
No binary included.
Changelog:
bsnes/phoenix uses XML for per-game cheat codes, markup is identical to the main database
added clear and clear all buttons to the cheat code editor
phoenix/GTK+ sets all child menu elements to match the parent menu font
phoenix/Windows will draw a black canvas for the Viewport widget (phoenix/GTK+ still needs this)
2010-09-30 - bsnes_v070r04.tar.bz2
No binaries, sorry. Hopefully most of you can compile, especially now that Qt isn't required.
Changelog:
fixed new config file input driver name (you'll have to delete your old config, or change to a different driver and back and restart)
fixed slot loader windows' OK button placement
fixed nall/directory.hpp when list size was zero
rewrote nall/function.hpp, no longer requires or union tricks
added state manager
The state manager is a little bit different this time. It's functionally identical to bsnes/Qt, 100% of the way.
But when you save slots, it stores them in RAM. It only writes the BSA archive upon ROM unload / program exit.
Yes, this means that technically if the emulator crashes, you'll lose your states.
But a) that very rarely happens, and b) the old way was thrashing the disk like crazy, every letter you typed dumped up to 8MB to disk.
With this new method, I can simply store a boolean valid flag before each slot, and pack the file better.
Before, a save on only slot 3 would be 3*state size (~1.2mb), it will now be 3bytes+state size (~400kb.)
I have also added a proper signature because of this, so it will detect when you load an archive for a previous serializer version and ignore it.
When you go to save (unload the game), if there are no valid slots, the BSA archive gets unlinked (deleted.)
I am also planning a feature around the now-hidden "slot 0". My idea is for it to be a fallback slot.
How many times have you loaded a state when you meant to save and said, "shit, now I lost some of my progress"?
The idea is that whenever you load a state, right before loading, it will save to slot 0.
When you unload the game, or exit the emulator, it will also save to slot 0.
You will be able to load from slot 0 from the menu, but not save to it. It will appear at the bottom of the load list.
And lastly, I'll add an advanced option to auto-load slot 0 if it exists, which will enable "close the emulator and restart where you left off." functionality.
2010-09-29 - bsnes_v070r03.tar.bz2
Changelog:
fixed a bug in xml_element::parse() with <![CDATA[...]]> tags
merged FragmentShader and and VertexShader into Shader, which is an XML file that contains all relevant data
updated Qt port to reflect the above
added support for pixel shaders to the phoenix port
updated all pixel shaders to use the new format
ruby won't crash if you give an HLSL driver a GLSL shader or vice versa, but it will still crash on bad programs
phoenix::Viewport has its own window class, that paints a black brush background
I'll handle questions and whatever later, I'm too busy coding.
Example, Curvature.shader:
Code:
<?xml version="1.0" encoding="UTF-8"?>
Example, Pixellate.shader:
Code:
<?xml version="1.0" encoding="UTF-8"?>
Example, Sepia.shader:
Code:
<?xml version="1.0" encoding="UTF-8"?>
Format is subject to change, more specifically I may change the tag from HLSL shaders.
In the long-long term, it'd be nice to extend the format to allow multiple shaders to be chained together and to encode base64 texture files.
But for now, this is good enough.
2010-09-28 - bsnes_v070r02.tar.bz2
Changelog:
added NTSC/PAL TV output mode selection
added loading support for BSX Slotted, BSX, Sufami Turbo and Super Game Boy games
Super Game Boy requires libsupergameboy or the DLL.
Man, it feels like I've done more. Ah well. What's left ...
analog controller input mapping (mice/SS/Justifier)
controller port selection
pixel shader selection
fullscreen mode
maybe paths
some GUI hotkeys, maybe remappable
Don't know what to do about snesreader and snesfilter, which are Qt-dependent. I don't really mind them not being there myself, but nobody would ever consider using the phoenix port without them. Damn.
2010-09-27 - bsnes_v070r01.tar.bz2
Changelog:
phoenix supports onActivate, or return key pressed, on text boxes
phoenix supports setGeometry() on all widgets
input settings can now map analog axes and analog buttons
analog button support is simplified over bsnes/Qt, and it supports the trigger inversion you see between Xbox 360 and Thrustmaster controllers
load cartridge window lets you press enter in the path box to select the folder, but currently allows invalid folders (makes list empty)
load cartridge won't reset your view if the folder doesn't change
--- this means the last ROM you loaded is highlighted the next time you go to load cartridge; you're welcome, FitzRoy :P
removed quit system menu option
added dummy controller port system menu options, there's no code behind them yet
added power/reset menu options, dropped the power checkbox in favor of a standard power cycle option, removes unnecessary complexity
added video mode scaling, 1x to 5x; and aspect ratio correction
added video mode smooth toggle
added audio settings panel with volume and input frequency adjustment
--- config file is where you can control output frequency and latency, they are too niche for a GUI
fixed a realpath() crash on Linux when the bsnes binary was in /usr/bin
2010-09-25 - bsnes_v070.tar.bz2
This release represents the coup de grâce of bsnes/Qt.
Changelog:
configuration file is now called bsnes-qt.cfg; the first run of this release will start with a clean state
MSU1 now supports audio looping via new PCM file format
disabled state load/save menu due to a serious bug in Qt 4.6.0 for Windows
RawInput: all keyboards merged to KB0, it should no longer be required to reconfigure the keyboard out-of-the-box
RawInput: fixed a bug where Xbox 360 controller states were being overwritten by DirectInput controllers
RawInput: fixed a device sorting bug caused by moving ruby to Unicode
Direct3D: fixed a pixel shader bug caused by moving ruby to Unicode
Linux port: fixed sudo make install target
Linux port: default to gcc/g++ instead of gcc-4.5/g++-4.5 for one last release
updated to mightymo's 2010-09-20 cheat pack
2010-09-25 - bsnes_v069.tar.bz2
This release adds some nifty new user interface features, and improves both performance and accuracy. The performance core is now fast enough to maintain a constant 60fps on a first-gen Intel Atom N270 in 98% of games.
Changelog:
added new effect toggle tool window, which allows toggling of BG/OAM graphics layers and DSP audio channels
added an option to use the native OS file and folder open dialogs instead of my custom browser
added a new state selection window
added frame skipping support, which is only used during fast forwarding; as a result, fast forward is now ~80% faster
removed unnecessary icons, added workaround for checkbox/radiobox menu icons on Linux/GNOME
added RTS/CTS support to serial simulation
all cores: OAM high table even address writes should update OAM latch data register [blargg]
accuracy core: major improvements to mosaic emulation
accuracy core: added additional hardware-based caching, resulting in a ~15% speed boost
accuracy core: emulated CGRAM address invalidation for writes during active display
performance core: added new S-PPU renderer, resulting in a ~10% speed bost
Also, I'm looking for someone who would be willing to backport bsnes v069 from C++0x to C++98. With this, it should be possible to create a PS3 port of bsnes that runs at full speed with all games. bsnes does not use C++0x very much, so it shouldn't be very hard, a weekend project at best. I just don't have the time to do this myself. Note that I wouldn't be merging these changes, I intend to keep using C++0x, this is needed only because the PS3 SDK uses a really old version of GCC. Please post on the message board if you are interested in helping.
2010-09-24 - bsnes_v068r25.tar.bz2
Windows Qt/performance/32-bit/non-PGO/non-debugger (yeah it's getting ridiculous how many variants are possible) binary included
This is basically the v069 release candidate, heavy testing would really be appreciated. I'd like for v070 to be the first official phoenix release, but if a major bug slips past us that will ruin it.
The big change is that save state support was added to the PPU-performance core.
2010-09-24 - bsnes_v068r24.tar.bz2
Fixes OAM latchdata for all 3 cores and CGRAM address invalidation for the accuracy core (the only one that really does it because it needs cycle PPU timing.) Also removes the OAM/CGRAM read/write functions to put them inside the actual MMIO functions. Easier to handle all the special cases that way. VRAM is a bit more annoying since there's two read and two write functions.
This should fix battletech/mechwarrior 3050 palette at least.
2010-09-22 - bsnes_v068r22.tar.bz2
Includes 32-bit binary, with no profiling.
Wanted to torture myself, so I implemented the hardest window of all, the cheat code editor. I had to sacrifice checkboxes inside lists, unfortunately, but it's a necessary evil. Maybe some day if we can port checkboxes inside list items to Windows and GTK+, we can add it back. It should be the only really apparent GUI sacrifice, though. You toggle cheats by double-clicking them in the list. Easy to do, but not apparent.
I also added in the focus policy.
./sshots/bsnes_20100921b.png
As you can see, phoenix is looking amazing compared to Qt. No consistency issues, no non-native look anywhere. It looks really great in classic mode, too. Way better than Qt does in Windows classic, that's for sure.
And no, I can't use snesreader or snesfilter, because both create Qt GUI windows. I don't know what I am going to do about that yet.
2010-09-21 - bsnes_v068r21.tar.bz2
Has an unprofiled 64-bit Windows binary for some reason. I meant to make it 32-bit, but forgot to swap the PATH variable to MinGW32, oops.
Changelog:
adds synchronize video
adds synchronize audio
adds mute audio
adds advanced settings window with driver selection only
adds the pretty section header thing I started going toward with Qt
adds a configuration file, saves to bsnes-phoenix.cfg (I don't make the .bsnes folder yet)
the status bar shows [A] for accuracy, [C] for compatibility and [P] for carburetor
./sshots/bsnes_20100921.png
I've decided that the phoenix port is going to be strictly a no bullshit, no bloat port.
No warnings for idiot users, no safeties for things like setting a 0% gamma or 0% audio output, no bloatey stuff like wide-zoom scaling, no fullscreen trickery, no 500kb input driver, no movies, no rewind, just the basics. I want a UI port that I actually enjoy working on. The Qt port is a nightmare to maintain, and it's not because of bad code but because of TOO MUCH code.
The Qt port will fill the GUI-equivalent of the performance core, essentially.
2010-09-21 - bsnes_v068r20.tar.bz2
Changelog:
fixed window casting crash in phoenix
added perfect forwarding to nall::string variadic templates to fix file load dialog crash in phoenix
disabled copy constructors in utf8_t to prevent this problem from occurring again in the future
separated canvas window proc by creating a separate class for it (ironically it was a desktop window causing the first crash)
use processorArchitecture="*" to make compilation easier
fixed status bar font assignment in phoenix/Windows
added InitCommonControls + CoInitialize for XAudio2 on XP
had to use DirectSound for audio; XAudio2 is crashing on exit which breaks the profiling (only a problem because you can't change the drivers without recompiling, there's really no reason to profile XAudio2 anyway)
Included with the above source archive is a 64-bit profile-guided binary.
./sshots/bsnes_20100920c.png
As you can see, it's pretty fucking impressive. The PGO adds another 15-20% on top of things. This is the fastest binary I've ever released as a result. If I had fast forward (frameskip) support in phoenix, that framerate could reach 600fps, and if I overclocked my CPU again that would add another 20% on top of that.
Note that I don't intend to fix the DirectSound sound looping problem in phoenix, as that required some hideous hacks in the old hiro. Either get the DX SDK for XAudio2 or use Qt.
2010-09-20 - bsnes_v068r19.tar.bz2
This adds proper manifest files to get the nice XP/Vista controls. Need to find a way to auto-detect MinGW 32 vs 64 since I can't use $shell or `` on gcc -v on Windows. For now you have to edit the ui-phoenix/Makefile by hand.
I've implemented the video settings window. I am going to be using separate windows this time. As nice as having everything in one place was, I didn't like being forced to stretch things to fill out the one-size-fits-all tab window I was using before. That and I don't feel like implementing tab support with phoenix anyway.
The menu gets a load cartridge command, and bsnes writes save RAM files now. Loading by file dialog crashes on 64-bit. Something's fucked up there, but I don't know what. Again, help would be great here :)
For those worried about the GUI ending up like the old hiro, this should allay some concerns:
./sshots/bsnes_20100920a.png
./sshots/bsnes_20100920b.png
You would not believe what a pain in the ass it was to vertically center text within labels. I had to create my own replacement STATIC control, and even then DrawText alone can't center multi-line text, so I have to calculate the text size, and then manually place it vertically centered.
2010-09-20 - bsnes_v068r18.tar.bz2
This WIP fixes the Mode7 repeat issue in the accuracy core.
More importantly, it's the first build to include phoenix. There is a stub GUI that does basically nothing right now. It will give you a window, a command to close the emulator, and an FPS meter so you can tell how fast it is. To load a ROM, you have to drag the ROM on top of the binary. I don't know if it will work if the filename+path has spaces in it or not, so avoid that to be safe.
The big news is that there's both a 32-bit and 64-bit binary included, although neither are profiled because I really don't have enough of a GUI up to profile anyway.
Windows uses: Direct3D + XAudio2 + RawInput - get the latest DX SDK for XAudio2 to work
Linux uses: OpenGL + ALSA + SDL
You will have to compile yourself to change these driver settings.
For some reason, the 64-bit binary sometimes crashes on start, maybe 1:6 times. So just keep trying. I don't know what's up with that, I'd appreciate if someone here wanted to debug that for me though :D
One really good bit of news, there was that old hiro bug where keyboard input would cause the main window to beep. I spied on the main event loop and, as suspected, the status bar was getting focus and rejecting key presses. What. The. Fuck. Why would a status bar ever need focus? So I set WM_DISABLED on it, which luckily leaves the font color alone. I also had to use WM_DISABLED on the Viewport widget that I use for video output. These two combined let me have my main window with no keyboard beeping AND allow tab+shift-tab to work as you'd expect on other windows, so hooray.
Now, at the moment there's no Manifest included, because Microsoft for some reason includes the processorArcitecture in the file. So I can't use the same manifest for 32-bit and 64-bit mode, or the binary will crash on one or the other. Fuck. So the status bar may look old-school or something, whatever, it's only temporary.
Next up, my goal is to avoid the hiro icon corruption bullshit by making phoenix itself try and use an internal resource icon. So just compile your app with that resource icon and voila, perfect icon. Not in there yet so you get the white box.
Input is hard-coded, up/down/left/right/z/x/a/s/d/c/apostrophe/return.
Lastly, compilation is ... in a serious state of flux. The code is set to compile bsnes/phoenix-gtk right now. Try it at your own risk. Give me a few WIPs to get everything nice and refined. Ubuntu users will need gcc-4.5, which you can get by adding the Maverick Meerkat repository, updating apt, installing the gcc-4.5 + g++-4.5 packages, and then removing and re-updating your apt/sources.list file so you don't end up fucking your whole system when you run apt again in the future.
For anyone who can work with all of that, great! Please post a framerate comparison between 32-bit and 64-bit builds. Any game, any screen, so long as the FPS is not fluctuating when you measure it (eg don't do it during an attract sequence.)
If anyone complains about the 64-bit binary not working and it turns out they are on 32-bit Windows, they are going to be removed from this WIP forum :P
2010-09-09 - bsnes_v068r17.tar.bz2
This hopefully fixes vertical and horizontal mosaic with the accurate S-PPU core.
It also adds frame-skipping support to the compatibility and performance S-PPU cores. This is not visible to the user interface, because I feel that virtually nobody is going to play with frame-skipping on when they could use a faster emulation with it off. However, I did use it to enhance the 'Fast Forward' key. When you press it, it will now turn off video and audio sync, and set a frameskip of 9. This allows you to speed things up an additional ~60% over your max theoretical speed without frameskipping. ~35% with the compatible core, because the PPU is less of a bottleneck for it. Slowdown was improved, it will turn on audio sync if it is off until you release the key to ensure you actually get 30fps.
Eventually it'd probably be wise to set a cap on the fast forward speed, but I hardly think it's an issue on today's computers.
Image
Performance core, normal
Image
Performance core, fast forward key held down
Now if only we can increase that speed by another ten times ... perhaps Der Langrisser will be tolerable :)
2010-09-08 - bsnes_v068r16.tar.bz2
Non-profiled Windows compatibility binary is included. Testing this one and all the new features would be appreciated.
New features?
Image
2010-09-06 - bsnes_v068r15.tar.bz2
This adds a new "Effect Toggle" window to the tools tab list. There's no menu entry for it yet, oversight, but you can go to another tool and tab to it.
The effect toggle window lets you toggle background/OAM layers on a per-priority basis and DSP sound channels. This only works with the compatibility and performance cores, because I'm not going to allow accuracy-violating hacks like that into the core.
Non-essential icons have been removed, there's six of them left at the moment. I am too much of a consistency guy to only have some scattered around. I know other apps do that, but I'm not going to do that, and I grow tired of trying to hammer in icons that don't really represent the actions. Anyway, it still looks pretty good I think.
2010-09-06 - bsnes_v068r14.tar.bz2
Holy hell, that was a total brain twister. After hours of crazy bit twiddling and debug printf's, I finally figured out how to allow both lores and hires scrolling in the accurate PPU renderer. In the process, I modified the main loop to run from -7 to 255, regardless of the hires setting, and perform X adjustment inside the tile fetching. This fixed a strange main/subscreen misalignment issue, so I was able to restore the proper sub-then-main rendering for the final screen output stage. Code looks a good bit cleaner this way overall.
I also added load state and save state menus to the tools menu, so you can use the menubar to load and save to ten slots. I am thinking that I should nuke the icons. As pretty as they are, it's getting tiresome trying to find icons for everything, I have no pictures to represent loading or saving a slot, nor to represent individual slots. I'll just stick to radios and checkboxes.
2010-09-04 - bsnes_v068r13.tar.bz2
Bug-fix night for the new PPUs.
Accuracy:
Fixed BG palette clamping, which fixes Taz-Mania.
Added blocking for CGRAM writes during active display, to match the compatibility core. It really should override to the last fetched palette color, I'll probably try that out soon enough.
Performance:
Mosaic should match the other renderers. Unfortunately, as suspected, it murders speed. 290->275fps. It's now only 11fps faster, hardly worth it at all. But the old rendering code is really awful, so maybe it's for the best it gets refreshed.
It's really tough to understand why this is such a performance hit, it's just a decrement+compare check four times per pixel. But yeah, it hits it really, really hard.
Fixed a missing check in Mode4 offset-per-tile, fixes vertical alignment of a test image in the SNES Test Program.
2010-09-04 - bsnes_v068r12.tar.bz2
This took ten hours of mind boggling insanity to pull off.
It upgrades the S-PPU dot-based renderer to fetch one tile, and then output all of its pixels before fetching again. It sounds easy enough, but it's insanely difficult. I ended up taking one small shortcut, in that rather than fetch at -7, I fetch at the first instance where a tile is needed to plot to x=0. So if you have {-3 to +4 } as a tile, it fetches at -3. That won't work so well on hardware, if two BGs fetch at the same X offset, they won't have time.
I have had no luck staggering the reads at BG1=-7, BG3=-5, etc. While I can shift and fetch just fine, what happens is that when a new tile is fetched in, that gives a new palette, priority, etc; and this ends up happening between two tiles which results in the right-most edges of the screen ending up with the wrong colors and such.
Offset-per-tile is cheap as always. Although looking at it, I'm not sure how BG3 could pre-fetch, especially with the way one or two OPT modes can fetch two tiles.
There's no magic in Hoffset caching yet, so the SMW1 pixel issue is still there.
Mode 7 got a bugfix, it was off-by-one horizontally from the mosaic code. After re-designing the BG mosaic, I ended up needing a separate mosaic for Mode7, and in the process I fixed that bug. The obvious change is that the Chrono Trigger Mode7->Mode2 transition doesn't cause the pendulum to jump anymore.
Windows were simplified just a tad. The range testing is shared for all modes now. Ironically, it's a bit slower, but I'll take less code over more speed for the accuracy core.
Speaking of speed, because there's so much less calculations per pixel for BGs, performance for the entire emulator has gone up by 30% in the accuracy core. Pretty neat overall, I can maintain 60fps in all but, yeah you can guess can't you?
2010-09-02 - bsnes_v068r10.tar.bz2
It is feature-complete, but horizontal mosaic is less accurate. I have an idea for a mosaic color ring buffer to get it equally accurate, but I haven't implemented it yet. For now it's just a simple x & ~(mosaic >> 1) trick that is passable.
Hires blending was left out, as it's more processor intensive and blargg's NTSC does a better job with that anyway.
There's some OPT vertical positioning issues in the SNES Test Program's character test; Goodbye, Anthrox has some sort of fast CPU DMA issue; etc.
Total speedup is a mere 13.5%. Not quite the 50% I wanted in the best case, but I'll take what I can get.
254->289fps in Zelda 3 on my E8400 now. There's another 15% hiding with blargg's SMP and 5-10% with blargg's fast DSP, but they lose too much accuracy. It'd put me at or below Snes9X accuracy, while still being 50% slower.
SSE2 was performing worse this time, both on x86 and amd64, so I left that optimization off.
So, barring a miracle, this is about the best it's going to get.
2010-09-02 - bsnes_v068r07
Added hires and interlace support, fixed a color bug with CGRAM high-byte writes, added offset-per-tile mode, and added support for OAM color exemptions. What I did to avoid overhead was store different source layer IDs for OAM pixels with palettes 128-191 and 192-255. Sadly that's still 256 computations a scanline, but it's not horrible and is absolutely needed.
Really the only major things left are mosaic and Mode 7. One minor thing would be direct color mode.
I have some crazy ideas for light-adjusted CGRAM table caching, etc. so I'm hoping I can make up the speed penalty of implementing the above.
2010-09-01 - bsnes_v068r08.tar.bz2
Windows performance binary included, uses PGO and SSE2 optimizations.
This gets the basic new PPU skeleton up and running, still missing a lot:
Mode7
direct color mode
OAM color exemption (this one will impact performance negatively)
vertical mosaic
horizontal mosaic (this one may impact performance negatively)
offset per tile
interlace
hires
pseudo-hires
But it's correct enough to play most games okay.
So far, the new PPU is about 11% faster on my Atom, and 17% faster on my E8400. I was hoping for more, but the window masking and sprite calculation is just kicking my ass.
The 11/17 figure is total emulator overhead, so that means raw PPU vs PPU, the new one is at least 22-34% faster than the old one.
I don't really have any ideas for additional optimizations. I'm even using little-endian word reads where applicable. But at any rate, I need to get all the above implemented correctly before trying to push optimizations even further.
2010-09-01 - bsnes_v068r07
New PPU renderer is coming along. Lots of new ideas, especially with regards to the way the background renders in tiles rather than in pixels. That skips the need for tile caching and compares, and it even gets scrolling right.
The sprite item+tile lists are computing, but they are not rendering yet.
It's a good deal faster for now, obviously, because 90% of the PPU features are missing.
2010-08-30 - bsnes_v068r05.tar.bz2
Started over again on the new S-PPU, heh. Three hours wasted last night I guess.
I wanted to make the new one more like the accurate core in its structure: multiple class instances for each background. It makes the code easier to read, results in less structure insanity (regs.main_enabled[bg] -> main_enabled), and will probably make it a tad easier to parallelize if we want to go that route eg for the ARM.
Still very incomplete.
2010-08-30 - bsnes_v068r04.tar.bz2
This should provide hardware-accurate mosaic support in the accurate renderer, with the exception that I'm still not sure what mid-frame vertical mosaic or mid-scanline horizontal mosaic writes do. Either the code I have is correct, or it bypasses the mosaic adjust and gives the exact H/V positions.
I've also renamed the fast folder to alternative (thinking about naming it simply alt instead), and started on a brand new PPU renderer. So far it's just a barebones setup with some MMIO support and VRAM/OAM/CGRAM writing. I'm not even confident that I can get this to be faster than the current scanline renderer, but it's the only avenue that we have left for any kind of significant bsnes speedup, so I have to try. I'm going to finish up the MMIO stuff first, that way we have a clean slate with no actual rendering. And then from here we can try various different approaches.
2010-08-28 - bsnes_v068r02.tar.bz2
test_mode7.tar.bz2
This adds mosaic improvements to the S-PPU dot renderer. Specifically, it eliminates the mosaic_table entirely, and performs mosaic adjustment per pixel instead. It also moves from a mosaic countdown for mosaic Y to a mosaic counter (incrementing).
In the process, I realized Sim Earth's map was broken, so I fixed that. In doing so, I also fixed my old Mode7 demo that was always off-by-one, causing different results on real hardware versus emulation. But then I broke both Final Fantasy 5 and Air Strike Patrol effects that use Mode7 but no mosaic.
I'm not really sure what's going on, but I think I am close. This is the first time I can reproduce the Mode7 test ROM results without screwing with M7Y which was obviously wrong. I think that somehow a mosaic >= 1 is glitching the Ycounter for the BG layers to tick one extra time.
There's a workaround that's not very nice to get everything going right now. It could very well be that the workaround is hardware accurate, but I can't help but feel there's a more eloquent way of doing this.
2010-08-20 - bsnes_v068r01.tar.bz2
This adds RTS/CTS support to the serial communications emulation. Okay, well the PC acts as if it is always ready, because it always is even on the real thing, but the PC-waiting-for-SNES side works.
Source only, hardware communication only works on OS X and Linux (Windows serial communication is totally different, I don't feel like writing a Windows version), more documentation will come later.
2010-08-21 - bsnes_v068
This release officially introduces the accuracy and performance cores, alongside the previously-existing compatibility core. The accuracy core allows the most accurate SNES emulation ever seen, with every last processor running at the lowest possible clock synchronization level. The performance core allows slower computers the chance to finally use bsnes. It is capable of attaining 60fps in standard games even on an entry-level Intel Atom processor, commonly found in netbooks.
The accuracy core is absolutely not meant for casual gaming at all. It is meant solely for getting as close to 100% perfection as possible, no matter the cost to speed. It should only be used for testing, development or debugging.
The compatibility core is identical to bsnes v067 and earlier, but is now roughly 10% faster. This is the default and recommended core for casual gaming.
The performance core contains an entirely new S-CPU core, with range-tested IRQs; and uses blargg's heavily-optimized S-DSP core directly. Although there are very minor accuracy tradeoffs to increase speed, I am confident that the performance core is still more accurate and compatible than any other SNES emulator. The S-CPU, S-SMP, S-DSP, SuperFX and SA-1 processors are all clock-based, just as in the accuracy and compatibility cores; and as always, there are zero game-specific hacks. Its compatibility is still well above 99%, running even the most challenging games flawlessly.
If you have held off from using bsnes in the past due to its system requirements, please give the performance core a try. I think you will be impressed. I'm also not finished: I believe performance can be increased even further.
I would also strongly suggest Windows Vista and Windows 7 users to take advantage of the new XAudio2 driver by OV2. Not only does it give you a performance boost, it also lowers latency and provides better sound by way of skipping an API emulation layer.
Changelog:
Split core into three profiles: accuracy, compatibility and performance
Accuracy core now takes advantage of variable-bitlength integers (eg uint24_t)
Performance core uses a new S-CPU core, written from scratch for speed
Performance core uses blargg's snes_dsp library for S-DSP emulation
Binaries are now compiled using GCC 4.5
Added a workaround in the SA-1 core for a bug in GCC 4.5+
The clock-based S-PPU renderer has greatly improved OAM emulation; fixing Winter Gold and Megalomania rendering issues
Corrected pseudo-hires color math in the clock-based S-PPU renderer; fixing Super Buster Bros backgrounds
Fixed a clamping bug in the Cx4 16-bit triangle operation [Jonas Quinn]; fixing Mega Man X2 "gained weapon" star background effect
Updated video renderer to properly handle mixed-resolution screens with interlace enabled; fixing Air Strike Patrol level briefing screen
Added mightymo's 2010-08-19 cheat code pack
Windows port: added XAudio2 output support [OV2]
Source: major code restructuring; virtual base classes for processor cores removed, build system heavily modified, etc.
2010-08-20 - bsnes_v067r26.tar.bz2
Okay, I'm pretty much ready to release the next version, so heavy testing on this would be appreciated. To test the debugger (built with the compatibility core for moderate speed and PPU debugging support), rename the DLL to an EXE.
bsnes_v067r26.tar.bz2
I think I'd rather play it safe though and go with v068. While the performance core is definitely major, I only have one shot at v1.0. It would at least be nice to have perfect mapping and the BGnxOFS caching for SMW1 in there first.
Anyway, changelog:
Re-added blargg's DSP, but this time I merged only spc_dsp and also fixed the initial regs for Dual Orb II. Which restores the 5-10% speedup on the compatibility and performance cores. Fixed the initial register values for the fast CPU core, which fixes Armored Police and the other Atlus game's title screen in the performance core. Added a missing debugvirtual prefix to op_step, which fixes CPU stepping in the performance core. I was using the description field for profile identification in savestates, but that was of course the description for the state manager. Whoops. Added a new field for profile name to the save states, and fixed the state manager to work with that change. Adjusted the about screen colors, which is how you can tell which core you're using without it being annoying. Probably did some other stuff too, meh.
2010-08-19 - bsnes_v067r25.tar.bz2
Removed snes_spc, and the fast/smp + fast/dsp wrappers around it.
Cloned dsp to fast/dsp, and re-added the state machine, affects Compatibility and Performance cores.
Added debugger support to fast/cpu, with full properties list and Qt debugger functionality.
Rewrote all debugger property functions to return data directly:
this avoids some annoying conflicts where ChipDebugger::foo() overshadows Chip::foo()
this removes the need for an extra 20-200 functions per debugger core
this makes the overall code size a good bit smaller
this currently makes PPU::oam_basesize() inaccessible, so the OAM viewer will show wrong sprite sizes
Used an evil trick to simplify MMIO read/write address decoding:
MMIO *mmio[0x8000], where only 0x2000-5fff are used, allows direct indexing without -0x2000 adjust
So end result: both save states and debugger support work on all three cores now. Dual Orb II sound is fixed. The speed hit was worse than I thought, -7% for compatibility, and -10% for performance. At this point, the compatibility core is the exact same code and speed as v067 official, and the performance core is now only ~36-40% faster than the compatibility core. Sigh, so much for my dream of using this on my netbook. At 53fps average now, compared to 39fps before. Profiling will only get that to ~58fps, and that's way too low for the more intensive scenes (Zelda 3 rain, CT black omen, etc.)
It would probably be a good idea to find out why my DSP is so much slower than blargg's, given that it's based upon the same code. The simple ring buffer stuff can't possibly slow things down that much.
More precisely, it would probably be best to leave blargg's DSP in the performance core since it's a pretty minor issue, but then I'd have to have three DSPs: accuracy=threaded, compatibility=state-machine, performance=blargg. Too much hassle.
Only code in the core emulator now that wasn't at the very least rewritten for bsnes would be the DSP-3 and DSP-4 modules, which are really, really lazily done #define hacks around the original C code.
2010-08-18 - bsnes_v067r24.tar.bz2
Windows binaries and source included
Fixed bsnes launcher on Windows XP
Fixed Windows bsnes launcher internationalization support (emulator can be in a folder with spaces and Japanese characters, and you can drag a Japanese file name onto the launcher, and it will load it properly)
Moved fast CPU to use a switch table for MMIO, unfortunately for no speed gain
Bus::read/write take uint24 parameters for address, luckily no speed penalty
MMIOAccess gained a handle() function, and hid the mmio[] table. Makes hooking it cleaner
Added malloc.h header to nall/function.hpp to fix a ridiculous GCC 4.5.0 error
Fixed a fairly large bug in the fast CPU IRQ handler, which fixes Robocop et al
Forgot to bump revision to .24 in the compiled binaries, too lazy to recompile or hex edit to change them
Unfortunately, in order to add nice battery usage, I have to add the sleep calls to the video and audio wait loops. But they don't know anything about the GUI and its settings, nor do I really want to make them know about this setting. I do not want to force allow it. Even with the media timer trick, Sleep(0) makes Vsync+Async fail a lot more frequently than never sleeping at all. I would rather laptop users suffer 100% utilization of a single core than for all users to not be able to get good audio+video sync. Not sure what to do about that, so I'll probably just remove the battery usage comment from performance mode for now.
2010-08-16 - bsnes_v067r23.tar.bz2
Source only, previous link with Windows binaries is still valid for now.
Added missing $4200 IRQ lock, which fixes Chou Aniki on the fast CPU core, so slower PCs can get their brotherly love on.
Added range-based controller IOBit latching to the fast CPU core, which enables Super Scope and Justifier support. Uses the priority queue as well, so there is zero speed-hit. Given the way range-testing works, the trigger point may vary by 1-2 pixels when firing at the same spot. Not really a big deal when it avoids a massive speed penalty.
Fixed PAL and interlace-mode HVIRQs at V=0,H<2 on the fast CPU core.
Added the dot-renderer's sprite list update-on-OAM-write functionality to the scanline-based PPU renderer. Unfortunately it looks like all the speed gain was already taken from the global dirty flag I was using before, but this certainly won't hurt speed any, so whatever.
Added #ifdef to stop CoInitialize(0) on non-Windows ports.
Added #ifdefs to stop gradient fade on Windows port. Not going to fuck over the Linux port aesthetic because of Qt bug #47,326,927. If there's a way to tell what Qt theme is being used, I can leave it enabled for XP/Vista themes.
Moved HDMA trigger from 1104 to 1112, and reduced channel overhead from 24 to 16, to better simulate one-cycle DMA->CPU sync.
Code clarity: I've re-added my varint.hpp classes, and am actively using them in the accuracy cores. So far, I haven't done anything that would detriment speed, but it is certainly cool. The APU ports exposed by the CPU and SMP now take uint2 address arguments, the CPU WRAM address register is a uint17, and the IRQ H/VTIME values are uint10. This basically allows the source to clearly convey the data sizes, and eliminates the need to manually mask values when writing to registers or reading from memory. I'm going to be doing this everywhere, and it will have a speed impact eventually, because the automation means we can't skip masks when we know the data is already masked off.
Source: archive contains the launcher code, so that I can look into why it's crashing on XP tomorrow.
It doesn't look like Circuit USA's flags are going to work too well with this new CPU core. Still not sure what the hell Robocop vs The Terminator is doing, I'll read through the mega SNES thread for clues tomorrow. Speedy Gonzales is definitely broken, as modifying the MDR was breaking things with my current core. Probably because the new CPU core doesn't wait for a cycle edge to trigger.
I was thinking that perhaps we could keep some form of cheat codes list to work as game-specific hacks for the performance core. Keeps the hacks out of the emulator, but could allow the remaining bugs to be worked around for people who have no choice but to use the performance core.
2010-08-16 - bsnes_v067r22.tar.bz2
Added OV2's XAudio2 driver (it's better and faster than the DirectSound one)
Fixed DirectInput keypad number codes
Added launcher to make the profiles work
Profiles now called: Accuracy, Compatibility, Performance (not debating names anymore)
The launcher isn't going to work on OS X because of the .app folder bullshit (yes, yes, .sfc folders.)
It also crashes on Windows XP for god only knows what reason. Works fine on Windows 7 and Linux. So XP users, rename the .dll files to .exe to test this release. I'll fix it on Monday.
The color highlighting fucks up the radio boxes on the Windows classic theme, because Nokia can't afford a god damn QA team.
Lastly, I forgot to add launcher to the make archive-all command, so the source for it will be in the next WIP.
2010-08-14 - bsnes_v067r21.tar.bz2
This moves toward a profile-selection mode. Right now, it is incomplete. There are three binaries, one for each profile. The GUI selection doesn't actually do anything yet. There will be a launcher in a future release that loads each profile's respective binary.
I reverted away from blargg's SMP library for the time being, in favor of my own. This will fix most of the csnes/bsnes-performance bugs. This causes a 10% speed hit on 64-bit platforms, and a 15% speed hit on 32-bit platforms. I hope to be able to regain that speed in the future, I may also experiment with creating my own fast-SMP core which drops bus hold delays and TEST register support (never used by anything, ever.)
Save states now work in all three cores, but they are not cross-compatible. The profile name is stored in the description field of the save states, and it won't load a state if the profile name doesn't match.
The debugger only works on the research target for now. Give it time and it will return for the other targets.
Other than that, let's please resume testing on all three once again. See how far we get this time :)
I can confirm the following games have issues on the performance profile:
Armored Police Metal Jacket (minor logo flickering, not a big deal)
Chou Aniki (won't start, so obviously unplayable)
Robocop vs The Terminator (major in-game flickering, unplayable)
Anyone still have that gigantic bsnes thread archive from the ZSNES forum? Maybe I posted about how to fix those two broken games in there, heh.
I really want to release this as v1.0, but my better judgment says we need to give it another week. Damn.
2010-08-13 - bsnes-20100813.tar.bz2
Since we're now talking about three splits, that's getting a bit out of hand.
This WIP combines everything back into one project again. Added the src/fast folder that has all the speed-oriented cores.
A slight slowdown to csnes from what it was before, I'm using blargg's accurate DSP. I just don't like the idea of releasing a less accurate DSP core than Snes9X v1.52 has. Plus the fast DSP core doesn't serialize yet.
I moved back to snes_spc 0.9.0 because I care more about Tales and Star Ocean than I do about Earthworm Jim 2. So if you try EWJ2 on csnes, expect it to sound like it does on Snes9X. In other words, don't wear headphones if you value your hearing.
The middle-of-the-road bsnes core uses blargg's accurate DSP, because it's about 3% faster than mine which removes all of blargg's optimizations. There is absolutely no accuracy loss here. bsnes v067.20 that is included should be equal to v067 official.
Performance:
Code:
asnes = 58fps
bsnes = 172fps +2.97x
csnes = 274fps +1.59x +4.72x
The binaries are not profiled, so that's an additional 15% slower from the previous builds.
Save states only work on asnes, as I don't know how to serialize blargg's cores yet. The copy_func thing is very confusing to me for some reason. The debugger won't work anywhere.
Outside of that, please go ahead and bug test. Once I get the debugger and save states working, I'll build some profiled v1.0 releases for all three, and we can test that for a bit and then release.
2010-08-11 - snes-20100811.tar.bz2
12-15% faster than v067.10, and my Atom never goes below 58fps for normal lo-res games at this point. Just a little more and I can leave Async on. That's pretty much it though for the low hanging fruit. Everything else will be a lot of work for a little gain. Speedups are from range testing across scanline boundaries and from using blargg's fast DSP core.
Snes9X is now only 1.93x faster than bsnes, and bsnes is now faster than Super Sleuth.
I also fixed the Circuit USA menus (HDMA timing adjustment), Wild Guns flickering (IRQ lock) and Jumpin' Derby (external IRQ triggering.) There's definitely a lot of troublesome games, mostly the same ones we had in the past (Koushien 2, Robocop vs The Terminator, etc.) I'm definitely going to debug Starfox, but I may not bother with some of the more obscure ones.
EDIT: Starfox 1.2 runs fine on this PC ... weird.
2010-08-10 - snes-20100810-2.tar.bz2
I wrote a new CPU core from scratch. It has range-based IRQs, and is good enough even to run F-1 Grand Prix and Sink or Swim. It also uses a binary min-heap array for the timing priority queue. This resulted in a ~40% speedup.
I also added in blargg's snes_spc library, which is an S-SMP + S-DSP emulator. I am still using his accurate DSP core, and not the fast one. This gives an additional ~10% speedup.
THIS IS NOT PERFECT, THERE WILL BE BUGS!
I already know that Tales of Phantasia and Star Ocean are hitting some edge cases. Now that it's fast enough, hopefully blargg can take a look at it. Something he couldn't test before because you can't rip SPCs of these games, so it's probably something simple.
My CPU core also doesn't nail every last possible edge case. So things like Wild Guns and the two or three games that rely on NMI/IRQ hold aren't going to work ... yet. Be patient.
The SuperFX and SA-1 cores are still cycle-accurate. It wouldn't hurt compatibility to reduce their precision a bit.
End result is that you can now get well over 60fps in normal games even on a first-generation Intel Atom.
snes-20100810-2.tar.bz2
Windows profiled binary is in out/bsnes.exe.
2010-08-09 - snes-20100809.tar.bz2
Code cleanups, no binaries. I'll leave the previous WIP up so you can get Windows binaries for now.
This adds some sync.sh improvements to make it handle errors more gracefully.
It also updates asnes a good bit. All of the four base processors now have all publicly accessible functions right at the top of the main headers, and everything else is private. This is to allow these headers to essentially take the place of the previous base classes in the old bsnes-merged format. So if there's something public there, you need to implement that exact function to make your own module.
I removed the frame counter from the PPU, as it has nothing to do with emulation. That now resides inside the Qt -> SNES interface code. Quite amazing, I was actually saving the frame counter into the save state files before, yuck.
Removed some baggage in the System class: it was friending a bunch of long-dead functions and classes.
Forgot to re-add the CHEAT_SYSTEM define to info.hpp, so that's been put back.
Need to think of something to do about the documentation and about screen, kind of silly for asnes to display bsnes in certain areas. I'll also play around with tar --transform sometime tomorrow, no promises on whether or not I'll use it.
2010-08-08 - snes-20100808.tar.bz2
This fixes libsnes and debugger builds, and collapses bsnes/ppu/bppu to bsnes/ppu and bsnes/dsp/sdsp to bsnes/dsp. It also introduces bsnes/sync.sh, which will synchronize all of asnes/ with bsnes/, excepting the custom speed-focused modules. So far, that's bsnes/ppu (scanline renderer) and bsnes/dsp (state machine.)
Should make keeping the two ports in sync much, much easier. It's basically the same thing as before, only you run sync.sh and have a few duplicated folders now. May make it clearer by creating a stub/ or src/ folder inside bsnes to do all of the copying, so that you only see the custom folders in bsnes/' root directory.
There are binaries for asnes and bsnes in the above archive. I would appreciate testing, especially on the new bsnes.exe in this archive. I'd like to make the v1.0 releases, but I really, really need to wait and have that one tested. I do not want v1.0 to be a buggy, broken release.
2010-08-07 - snes-20100807.tar.bz2
This represents a major code restructuring. The dot-based and scanline-based renderers are now split into two separate core libraries, asnes and bsnes.
For now at least, these are -internal- names. I'm not entirely decided on how I'm going to handle releasing these two separate builds. Regardless, the folders need names.
asnes has had all of the processor subfolders collapsed back into their parent folders. In other words, ppu's functions were moved into ppu/sppu, and then ppu was deleted, and then ppu/sppu became the new ppu. Repeat this for the cpu, smp and dsp and there you go.
asnes/dsp also removed the DSP_STATE_MACHINE option. This was done for the sake of consistency with the rest of the core.
asnes' debugger mode is currently extremely broken, but I will be fixing it in time.
And for now, bsnes has kept the processor abstraction layer. I may keep it around, not sure yet. It doesn't hurt speed or anything, so I'm not too worried about making a decision right away.
I may throw snesfilter, snesreader and supergameboy into this folder, just to have everything in one place. The alternate GUI forks are definitely going in there as dotnet, cocoa and python.
Compiled output goes to the out/ folder now, to prevent conflicts with a file and folder named bsnes, for instance.
2010-08-07 - v067r05 (Windows binary + source)
This will be the final release with the current source structure.
This WIP contains a bugfix so that the last scanline does not fetch OAM items. This fixes flickering in Ninja Warriors and Lord of the Rings.
2010-08-06 - v067r04 (Windows binary [sPPU] + source)
This build simplifies the tile cache significantly, and it now builds the cache and fetches the VRAM data during Hblank, the VRAM reads are modeled after real hardware.
This fixes Mega lo Mania without regressing Winter Gold or Adventures of Dr. Franken.
I also fixed a pseudo-hires back color glitch in Super Buster Bros.
2010-08-05 - v067r03 (Windows binary [sPPU] + source)
This substantially improves the S-PPU dot-renderer's sprite processing. Instead of happening immediately at the start of the scanline, each pixel is rendered one at a time. It eliminates the SpriteList caching, sprite width/height caching, oam_palette caching and oam_priority caching.
I'll explain it in more detail in the public thread in a bit.
Most noticeable is that Winter Olympics is now perfect, with no known regressions on any of the sprite-sensitive games.
2010-08-04 - v067r01 (source code)
v067r01 (64-bit Windows binary, profiled with MinGW GCC 4.5.0)
v067-dotnet
v067-snowleopard
This adds the SA-1 compiler bug workaround for GCC 4.5.0, and updates the load special libsnes functions to also generate XML mapping data if given empty strings.
I built the binary above with GCC 4.5.0, so let me know if any new problems appear. What I've noticed is that when not profiled, 4.5.0 is about 3-5% faster, but when profiled, they are equivalent in speed.
Lastly, I did some more work on the .NET/C# and Snow Leopard/Cocoa ports. They can both load all special types of ROMs, including Super Game Boy.
For .NET, you need to be on a 64-bit version of Windows, have .NET 3.5 installed, and have SlimDX installed (I used February 2010, but anything later should be fine.)
For Snow Leopard, you may want to build and install libsupergameboy, but you don't have to. Just don't try loading SGB games without it.
Yes, the .NET one is pure 64-bit. I built snes.dll and supergameboy.dll using MinGW64-GCC 4.5.0. Since the core library doesn't use Qt, it builds fine in 64-bit mode.
2010-08-01 - v067
I apologize, bsnes v066 had a small error in the source that resulted in the PPU not synchronizing properly to the CPU. This bug was not exposed in the images I use to test releases. I have also updated the cheat code database, which is maintained by mightymo.
2010-07-31 - v066
Major features in this release are: serial controller emulation, a brand new scheduler that supports multiple simultaneous coprocessors, and accuracy improvements.
The serial controller is something devised by blargg. With the proper voltage adjustments (5v-9v), it is possible to wire an SNES controller to a serial port, which can then be used for bidirectional communication between the SNES, and (usually, but not only) a PC. The support in bsnes was added so that such programs could be debugged and ran from within an emulator, and not just on real hardware.
The scheduler rewrite was meant to allow the combination of coprocessors. It was specifically meant to allow the serial controller thread to run alongside the SuperFX and SA-1 coprocessor threads, but it also allows fun things like MSU1 support in SuperFX and SA-1 games, and even creating dev cartridges that utilize both the SuperFX and SA-1 at the same time. The one thing not yet allowed is running multiple instances of the exact same coprocessor at the same time, as this is due to design constraints favoring code inlining.
There are two important accuracy updates. The first is that when PAL video mode is used without being in overscan mode, black bars are shown. Emulators have always shown this black bar at the bottom of the screen, but this is actually incorrect. resxto took pictures from his PAL TV that shows the image is in fact vertically centered in the screen. bsnes has been updated to reflect this.
Also interesting is that I have backported some code from the dot-based PPU renderer. In the game Uniracers, it writes to OAM during Hblank, and expects the write to go to a specific address. In previous releases, that address was hard-coded to go to the required memory location. But the way the hardware really works is that the write goes to the extended attribute address for the last sprite that the PPU fetched, as the PPU is still asserting the OAM address bus. Now, due to the precision limitations, I was not able to also port timing access during the active display period. However, this is sufficient to at least remove the last global hack from the older, speed-focused scanline renderer.
2010-07-29 - v065r05
Fairly major changes here, I'd appreciate some testing if anyone's not busy. Note that the save state version has been bumped, so consider WIP saves unstable until v066 official.
Rewrote the entire scheduling system. Instead of having a global class that all of the chips call into, each class now contains its own thread, clock and frequency information. They also implement their own syncing primitives, but with a tiny bit of standardization.
void step(unsigned clocks) -- add to/subtract from counter based on master/slave select.
void synchronize_chip() -- make sure chip is caught up to our current thread before continuing.
So we go from scheduler.sync_copcpu() to sa1.synchronize_cpu(); with the sa1. being omitted inside the SA1 class itself.
The S-CPU implementation also adds an array<Processor*> coprocessors; list, and iterates them all. This allows bsnes to have an infinite number of additional coprocessors at the same time. But there is still the limitation of only one of each type. So you can use the XML memory mapping to make a cartridge that contains a SuperFX2 chip, an SA-1 chip, an MSU1 chip and that can be debugged via serial communications. However, you can't make a cart that has two SA-1 chips. That limitation probably could be overcome as well, but it's less important. I mainly wanted to be able to use MSU1 and Serial on special chip games.
I implemented the synchronization primitives in the chip base classes, which means that for inlining purposes I had to make it all global, so you'll have src/cpu/synchronization.hpp, etc now. This was to reduce some redundancy of having the same exact code inside both bPPU and sPPU, etc. I'll probably make a Coprocessor : Processor class to automatically implement the step+synchronize_cpu functions for the five coprocessors next.
The Scheduler class is actually still around, but it's very trivial now. It simply saves the program thread and last active emulation thread for the purpose of entering and exiting emulation. Because I killed Scheduler::init(), which was responsible for destroying and re-creating threads, I had to create the threads inside ChipName::create(), which I call at power and reset. This means that to load a save state, the system needs to be reset to destroy those threads.
This caused some troubles with the SA-1, specifically in Kirby's Dreamland 3, but no other games I tried. I had to move the SA-1 bus initialization to the power-on event, and only reset when loading a save state. It would appear that the SA-1 is leaking bus mapping state information, presumably from the SA-1 MMIO registers that control some of the mapping layout. If I add remapping of those sections into the SA1::serialize() function, it should take care of that problem and I can move sa1bus.init() back into SA1::reset().
All of this results in a 2-3% speed hit for normal games, and a 6-7% speed hit for special chip games. The former should not have any speed hit, so I will have to look into what's going on there. The latter we have no choice on, to allow for more than one coprocessor, the coprocessor synchronization needs to iterate a list, compared to a single hard-coded check in the previous builds. If I can figure out what is happening with the regular game speeds, it should drop the special chip hit to 4%. Worst part is this hit is in addition to the 10-15% speed hit from v065 official where I wasn't syncing the special chips up to the CPU except once per scanline and on MMIO accesses.
But that's progress. v065 is definitely going to be the preferred build for playing SuperFX/SA-1 games for a long time to come.
2010-07-16 - v065r04
Only posting because the link changed, it's the exact same as r03.
Only difference is some improvements to nall:
string class gains lower(), upper(), transform(), *trim(_once)
2010-07-12 - v065r03
Polishing work. My dlopen wrapper accepts an optional path argument now, and the basename setting is universal instead of just for MSU1, so serial-based games can load in a dynamic client library directly.
Still need to update snesserver to accept another argument for the program library name to load.
Upped the serial polling frequency to 8x UART speed per blargg.
And a very tricky change, I updated nall/string to remove sprint(). At first, I used:
Code:
string name = string() << path << basename << ".msu";
I then improved upon that with:
Code:
string name = sprint(path, basename, ".msu");
Tonight I went ahead and finished this by taking advantage of variadic templates for the constructor itself. Very tricky because my conversion functions created new strings to copy data into, which would create an infinite loop; then of course I also had to leave the copy constructor behind even after this. So the end result is the following:
Code:
string name(path, basename, ".msu");
Oh, and I found a typo in MSU1, it wasn't using the proper extension when loading a save state for the data file.
2010-07-11 - v065r02
Be warned, this is going to get complicated.
To start out with, serial.tar.bz2 is a simple SNES program that is right now being used for integrity testing. The important part is here:
Code:
serial_read:
lda #$01
-; bit $4017; bne -
-; bit $4017; beq -
nop #24
pha; lda $4017; eor #$01; ror; pla; ror; nop #18
pha; lda $4017; eor #$01; ror; pla; ror; nop #18
pha; lda $4017; eor #$01; ror; pla; ror; nop #18
pha; lda $4017; eor #$01; ror; pla; ror; nop #18
pha; lda $4017; eor #$01; ror; pla; ror; nop #18
pha; lda $4017; eor #$01; ror; pla; ror; nop #18
pha; lda $4017; eor #$01; ror; pla; ror; nop #18
pha; lda $4017; eor #$01; ror; pla; ror; rts
serial_write:
pha #6; pla #6; wdm #$00; stz $4016; sec
pha #6; pla #6; wdm #$00; sta $4016; ror
pha #6; pla #6; wdm #$00; sta $4016; ror
pha #6; pla #6; wdm #$00; sta $4016; ror
pha #6; pla #6; wdm #$00; sta $4016; ror
pha #6; pla #6; wdm #$00; sta $4016; ror
pha #6; pla #6; wdm #$00; sta $4016; ror
pha #6; pla #6; wdm #$00; sta $4016; ror
pha #6; pla #6; wdm #$00; sta $4016; ror
pha #6; pla #6; wdm #$00; sta $4016; rts
Fairly ugly, but it works.
Next, I needed a way to be able to execute the client in such a way that it would work with both bsnes and real hardware, with no recompilation or changes needed. The nice way would be some form of inter-process communication, but well, I don't really do that. And it's probably extremely platform-dependent.
So I used what was available to me already, a cross-platform dlopen wrapper for dynamic library support. The client application is written and compiled into a shared library that exports a single function, snesserial_main, which runs as if it is its own program and never returns. It takes three parameters, the time tick(), read() and write() function pointers. It can call them to do its work. This process is put in a folder called snesserial for now. It's the accompanying program to serial.sfc.
Now I have both bsnes (v065.02 above) and snesserver, they both act the same way. They load in snesserial, and give it those three functions and call its main entry point. The difference is that the read/write functions in bsnes simulate a serial strobe to the emulator, and the read/write functions in snesserver actually read and write to the TTY device you specify as the program argument, eg for me I use: ./snesserver /dev/ttyUSB0
Mmm, USB<>SNES for the win.
There's a limitation in my dlopen wrapper, it adds the libN.so or N.dll stuff automatically, making it difficult to also specify a path. That means that for now you have to put libsnesserial.so into /usr/local/lib. Obviously you don't want to be limited to just one program. The plan is to have it load the library that matches the game name:
zelda.sfc + zelda.so/zelda.dll/zelda.dylib (yeah, no libzelda.so.)
Now, the bsnes+serial emulation works on any platform. However, snesserver only works on Linux. You can blame that one on Microsoft. They make you require special kernel drivers to be able to access the serial port. I'm not going through the trouble. OS X can probably use it if it makes the appropriate /dev/tty device, but I'm not going to test it.
Activating the module can only be done with a custom XML file, as before. Still need to work on integration with the controller port options, as it's not really a special chip.
Lastly, the timing is "pretty good", but not perfect. It accepted a 374 cycle-per-bit loop for serial writes from the SNES to the PC, but snesserver did not. I had to adjust to 364 cycle-per-bit loop for it to work on both.
This is really bad, because the goal here is to use the PC as the testbed to make sure it'll work on the real thing. On the plus side, you only have to get it working one time, and stick with the serial_read/serial_write functions like at the top of this post. But I do need to address this. I'm not entirely sure how to more accurately simulate a serial port at this point though.
Oh, and I am thinking I need to expand the read/write functions to process more than one byte at a time. That should greatly speed up transfer time on the real thing. I also need to add some slowdown so the emulator more closely matches hardware speeds.
2010-07-09 - v065r01
In order to fully decode the 16MB address maps, I am going to need to use blargg's stop-and-swap, which will require a serial-communications program. To develop this program, and others in the future, as well as for testing automation, it would be very beneficial to have a way to debug these programs through bsnes.
So what I'm working on now is emulating a serial port inside bsnes. The basic premise is to start with a custom XML map that specifies its presence:
Code:
<?xml version="1.0" encoding="UTF-8"?>
I am essentially treating the serial communication as a special chip. One could argue this belongs as an option under controllers, and one would be right. But as I can't have two coprocessor threads at the same time, this is how it is for right now. Eventually it'll probably be under controller port 2, and only enabled in the debugger builds.
So, this pseudo-coprocessor ... it's basically emulating the PC-side communications program.
Meaning I still need to externalize this somehow so that any program can be run.
The below program writes 0x96 six times, and then reads in data six times. Well, technically forever, but the SNES ROM only writes six times at the end.
Code:
void Serial::enter() {
scheduler.clock.cop_freq = cartridge.serial_baud_rate() * 2;
latch = 0;
add_clocks(512);
for(unsigned i = 0; i < 6; i++) {
latch = 1; add_clocks(2);
uint8 data = 0;
for(unsigned i = 0; i < 8; i++) {
add_clocks(2);
data = (data << 1) | cpu.joylatch();
}
print("Read ", strhex<2>(data), "\n");
}
}
The SNES code looks like this:
Code:
//21,477,272hz cpu / 57,600hz serial = ~372.87 clocks/tick
org $8000
xce; rep #$10
ldx #$01ff; txs
jsr serial_read; sta $700000
jsr serial_read; sta $700001
jsr serial_read; sta $700002
jsr serial_read; sta $700003
jsr serial_read; sta $700004
jsr serial_read; sta $700005
lda $4017; and #$01; asl $00; ora $00; sta $00; lda $00; nop #13
lda $4017; and #$01; asl $00; ora $00; sta $00; lda $00; nop #13
lda $4017; and #$01; asl $00; ora $00; sta $00; lda $00; nop #13
lda $4017; and #$01; asl $00; ora $00; sta $00; lda $00; nop #13
lda $4017; and #$01; asl $00; ora $00; sta $00; lda $00; nop #13
lda $4017; and #$01; asl $00; ora $00; sta $00; lda $00; nop #13
lda $4017; and #$01; asl $00; ora $00; sta $00; lda $00; nop #13
lda $4017; and #$01; asl $00; ora $00; sta $00; lda $00; nop #13
rts
serial_write:
lda #$01; sta $4016; nop #23
lda #$00; sta $4016; nop #23
lda #$01; sta $4016; nop #23
lda #$00; sta $4016; nop #23
lda #$00; sta $4016; nop #23
lda #$01; sta $4016; nop #23
lda #$00; sta $4016; nop #23
lda #$01; sta $4016; nop #23
lda #$01; sta $4016; nop #23
lda #$00; sta $4016; nop #23
lda #$01; sta $4016; nop #23
rts
That reads six times, and then writes six times.
I haven't made the test do an infinite PC->SNES transfer, but I have for SNES->PC. No errors after millions of bytes, even if I stride the CPU timing.
As this is just an example, it's pretty lousy with actual timing, but I guess that's a good thing as it still works quite well. More tolerance = less potential for errors.
Now, this part is important.
While debugging this, I noticed that my serial coprocessor was only running when Vcounter=n,Hcounter=0. In other words, nothing was making the CPU synchronize back to the coprocessor, except the once-per-scanline synchronization that was there in case of CPU stalls.
That's ... really bad. MSU1 worked only because it buffers a few hundred samples for audio mixing. I don't really know why this didn't cause an issue for SuperFX, SA-1 or Super Game Boy games; but in theory they were at most 682x less precise than they should have been in terms of CPU->coprocessor synchronization.
Making it sync after every add_clocks() call results in a 10% speed hit to SuperFX, SA-1 and Super Game Boy emulation, unfortunately.
I don't notice any quality improvements in emulation, but in theory the lack of this syncing before effectively eliminated the benefits of the SuperFX and SA-1 being cycle based.
I'm going to have to look into this more to understand if I was intentionally not doing this sync before, or if I really did forget it. I'm thinking it was an oversight right now. The SuperFX and SA-1 don't really talk back and forth a whole hell of a lot, so once a scanline probably wouldn't be that noticeable.
But holy hell ... now that I'm thinking about it, I wonder if this was the cause of all that craziness in trying to sync up the Super Game Boy's VRAM transfers. Yeah, definitely need to look into this more ...
2010-06-26 - v065
It's been a while, so here is a new release of bsnes.
Unfortunately I don't have a full changelog this time. Most of the work went into stabilizing libsnes (which is used by the experimental .NET, Cocoa and Python UIs; as well as by Richard Bannister's OS X port).
The Windows binary package now comes with all three variants included: bsnes.exe, the standard version that casual users should run; bsnes-debugger.exe, for SNES programmers and ROM hackers only; and bsnes-accurate.exe, which should not be used by anybody, ever.
In all seriousness, bsnes-accurate.exe is bsnes with the dot-based S-PPU renderer. It's twice as slow as the normal build, and you won't really notice any differences except in Air Strike Patrol. It's there for the curious and for any SNES programmers who want to try making some really awesome video demos.
Changelog:
OS X port builds once again; now requires gcc44 from Macports
libsnes API finalized
fixed a bug with S-CPU debugger breakpoints
various source cleanup
2010-04-25 - v064r05
swaps the video_refresh output from BGR555 to RGB555, for the sake of direct copying for certain APIs. Not going to do RGB565 because the G5 bit doesn't exist, and faking it is lame.
bsnesui_2010-04-24.tar.bz2
bsnes.python:
adds more icons and stuff.
bsnes.net:
new port, targets C#, binds every function in libsnes
targets .NET 3.5 ... I honestly would have went with 4.0 for the nicer IntPtr addition alone, but the SP3 requirement may put off a lot of people
video output that doesn't scale (or clean up when dropping to a smaller size)
Port1 joypad input support via keyboard only
bsnes.cocoa:
stuck in a time/space wormhole until Apple gets their heads out of their asses and updates GCC
2010-04-20 - v064r04
Fixes S-CPU debugger breakpoint issue.
libsnes always returns 0 for "no memory present" now, never -1U.
bsnes-python-20100420
Won't error if there's no joypad present.
Swaps menu and status bars with a toolbar.
Adds keyboard support - you can use both a keyboard and joypad for input now.
Won't crash if RAM doesn't exist yet.
Won't crash if game uses no RAM.
2010-04-19 - v064r03
bsnes-python-20100419
Some changes to libsnes. Really hoping the API will be stable from this point out ...
2010-04-18 - v064r02
Nothing interesting, just added bsnes-qt.py to ui_python. No input handling, but OpenGL-based video resizing and libao audio. Doesn't use numpy, found a workaround for that. It's obvious that we need video/audio/input handled by an external library for this to work, so I'm thinking now about a rewrite of ruby to a C-like interface.
2010-04-16 - v064r01
Adds bool snes_get_region(void) to libsnes (permanent).
Adds snes_blit_colortable and snes_blit to libsnes (temporary).
Adds src/ui_python with a basic Python GUI, and abstraction between the libsnes wrapper and PyGTK (so it can be reused for PyQt, etc.)
The GUI has:
menubar
video output (2x scale, supports NTSC/PAL, hires, overscan and interlace correctly)
audio output (libao through ALSA)
input (very lousy key press events, they toggle off and on if you hold a key down ...)
I'm getting full-speed, so that's good.
Not sure where I want to take all of this stuff yet, but it's kind of neat for now I suppose. It would be kinda fun to go really out there with completely new GUI design styles that aren't just your standard menubar+video. Things like a toolbar, mouse gestures, really deep platform integration, AVI-based recording, frame analysis shit, game-specific GUI shit (perhaps map touch-screen input + gyroscope on top of a simulated gamepad; or perhaps read the contents of RAM and provide statistical information on the sides of the video output screen?), I dunno ... whatever. It's there, it's possible, but it's certainly not good enough to replace the official C++ Qt port, and I don't really have the time or patience to make it that good myself.
2010-04-14 - v064
A thank you to everyone who helped test the RC to ensure stability. I've uploaded the official v064 release to Google Code.
The most important change in this release is the cycle-based PPU renderer; but due to performance reasons the scanline-based renderer remains the default in the Windows binary. If you want to try out the cycle-based renderer, you will need to compile from source for now.
Another major change is the introduction of libsnes, which allows one to build bsnes as a shared library that can be used from other programming languages. It is intended both to create a regression testing framework, and to provide API stability for the various projects that use the bsnes core. While I can't guarantee the API to libsnes won't change, I will properly revision it and do everything I can to avoid changing it if possible.
2010-04-13 - v063r14
libsnes updated ... should be the official syntax now, I don't expect any more changes
added kode54's patch for HQ2x
NOT going to add the libjma Windows Unicode fix, I want something more elegant than hijacking all of std::ifstream, so that can wait for now
fixed status.irq_lock for Power Rangers
went back to blargg's 1.024MHz S-DSP for the fast build
updated mightymo's cheat pack to the latest version
2010-04-14 - v064rc1
I'm posting a release candidate for v064, for which I am looking for beta testers. If you would like to help out, please give it a try and report any bugs or regressions on the forum. If all goes well, this will be posted as v064 official shortly.
Note that you will need the Qt run-times from bsnes v063 official to use this. Also, this build does not use the new cycle-based PPU. Official builds are going to continue using the scanline-based renderer. This build should be about 10% faster than v063 was, which should lower the system requirements further.
2010-04-11 - v063r12
Well I really don't want to think about a caching system right now, so I skipped that.
added sPPU::Background::get_tile(), which computes its own copies of mask_xy, screen_xy, tile_size, etc; allows BG3 offset-per-tile to compute tile correctly
fixed two V=(start of Vblank) checks that lacked overscan tests
removed fade stuff from video output, going to rely exclusively on filters for that stuff now
modified state. to t. for brevity
cached regs.overscan for overscan() function
PPUDebugger uses interlace_enable() and overscan_enable() to avoid conflicts with the base classes; forgot to move PPUcounter to PPUCounter
added controller selection capability to libsnes; still needs cheat code and save state support
Should fix that Adventure Island thing, confirmation would be appreciated.
I tried some quick hacks and was able to get mode7 caching (NHL '94) and OAM caching (Winter Gold) working without breaking anything, but it's too scanline-PPU for my tastes. There's really no reason to half-ass this just to get games playable, so I'll wait and do it the right way later on.
Only worked on this for about an hour today ... I must be burned out. Think I'll try messing around with Python or something, since Ruby is a dead-end for using libsnes.
2010-04-09 - v063r11
Writing to SETINI will update video mode priorities for EXTBG mode.
Merged pixel output { main, sub { valid, priority } } into just priority. A priority of zero is considered invalid now.
Merged pixel output { main, sub { palette_index, palette_number } } into just palette with the tiledata bits for direct color mode at d8-d10.
This cuts a lot of copying and extra comparisons out of the final screen rendering pass, though it doesn't really help speed.
Output is always 512x448 now. Having trouble deciding on how to do video for that, but I'll post more on that later.
Really need to figure out how offset-per-tile fetches in regards to lores v hires and SC size, tile size and wrapping.
For now, I simplified it to constants; whereas the scanline-renderer uses the BG3 settings.
I also made it not perform OPT lookup on BG3 and BG4 anymore. Skips a pointless trickery of setting the OPT valid bit to zero for BG3,BG4 and is faster.
Forgot an overscan check in sprite drawing, should draw sprites properly to V=225-239 now.
Made the mode7 variable names more consistent.
2010-04-05 - v063r10
With this release, the final last-generation holdout, the scanline-based PPU renderer, has been replaced with a true, accurate, cycle-level PPU that renders one dot at a time. Finally, this fulfills the greatest milestone remaining in the SNES emulation scene. With every processor emulated at the lowest possible level, SNES emulation finally rivals the accuracy levels that NES emulators have offered for years.
Now, please do understand that this release is not a beta, nor is it even an alpha. It is simply a preview of things to come, and as such you can consider it a pre-alpha. There are many caveats at this time.
First, it is very slow. More than twice as slow as v063 official. There have been absolutely no optimizations whatsoever to the new dot-based renderer. I do expect to be able to speed this up significantly in future releases.
Second, this may lock up on Windows Vista and later for unknown reasons. I haven't had a chance to look into it; so stick with Windows XP or Linux for now.
Third, save states are not supported yet. If you try and use them anyway, bad things will happen.
Fourth, and most importantly, this isn't 100% bit-perfect by any stretch of the imagination. Off the top of my head, memory is accessed far too often, the OAM and CGRAM address lines are not controlled by the S-PPU during active display, none of the various glitches are supported, and the OAM renderer does not pre-cache the next scanline's sprites, it happens on the same line for now.
I will obviously be doing my best to improve the accuracy of the aforementioned things. But even with those missing, this is still leaps and bounds above a pure scanline-based renderer. It essentially provides 682 times the parallelism. It is enough to finally properly emulate the shadow effect in Air Strike Patrol, and it finally eliminates the "PPU Hclock render position" hack once and for all.
Lastly, you'll need the DLLs from v063 official. I didn't bother to include them this time.
Enjoy!
2010-04-05 - v063r09
Windows binary w/sPPU enabled included
So that's about 24 solid hours worth of programming in two days. Holy fuck am I exhausted. Don't expect the last bits any time soon.
Missing features:
Mode 7 renderer
OAM previous-line caching
offset-per-tile mode
some edge cases in color add/sub
hires
interlace
overscan
S-PPU control over VRAM, OAM, CGRAM during active display
Speed hit is about as bad as I had feared. 172fps with scanline rendering to 80fps with dot rendering. I'm guessing that with optimizations I can make it to ~100-110fps.
2010-04-05 - v063r08
No binary, this is just a point release.
I have basic lores BG1-4 rendering with mosaic added. No offset-per-tile, no windowing, no color math (requires windowing), no sprites, no hires, no interlace, no mode7.
It's enough to see how powerful the concept is already, though.
Battle Blaze intro looks just fine (can't beat a battle because I can't see my sprites or save states yet)
Dai Kaijuu Monogatari II stat bar looks fine (no duplicated line)
Super Metroid looks fine (no extra status bar line)
Air Strike Patrol shows the translucent shadow for your plane (but the left-hand scrolling is glitchy ... not sure what's up yet)
Speed is ... yeah, it's bad. About 50-60% speed. But it can get better, I'm being really lazy and completely recomputing everything for each pixel. A very large number of these operations can be cached. I'm going to wait until the renderer matches the quality of the scanline-renderer before optimizing; and I'm not going to push too far on optimizing this (eg I probably won't bring back the tiledata planar->packed conversion cache.)
I'm designing this similar to MooglyGuy's N64 renderer, putting each component in its own class. So far I'm really liking the concept.
2010-04-04 - v063r07
src/lib is no more, merged libco, nall and ruby into src/.
libsnes has been improved, builds in when you "make library" now.
XML memory map generation happens from a nall template header, so both libsnes (used by ui_sdl) and ui_qt can run again without snesreader.
ui_sdl improved, can run any game via command-line, but doesn't load or save RAM yet.
And most importantly, much work has gone into sPPU, the new cycle-based PPU renderer. It has enough support to be compatible with all games ($2134-213f are mostly complete, just missing range/time over flags and VRAM/OAM/CGRAM blocking.) It only renders the back color, as if you had all BG and OAM layers disabled.
At this point, if you run Air Strike Patrol, thanks to its gradient fade highlighting, you can see the plane's shadow, just as on real hardware now. It also runs test_hello and test_noise, which I will upload shortly.
2010-04-02 - v063r03
Extremely substantial code structure changes this time. Probably the most in four years.
All of the SNES core now resides in src/snes, and the contents of system have been unrolled into this directory as well. This folder gets its own Makefile now, and some special build commands, "make library" and "make install-library". This creates static and dynamic link libraries of the core, completely devoid of Qt, ruby, the GUI, etc.
There's a new module as well, src/snes/libsnes. This is a C interface that will let you initialize and control the bsnes core without the need for anything more than a 1KB header file.
To test this, I've created a UI fork, ui_sdl. Very very simple, 2KB, nothing there at all really, it just boots up Zelda 3 and runs it directly with keyboard input support and video only. The important point here is that the ui_sdl project does not reference the core, or ruby, or Qt, or anything else, and is fully C++98 (though it could also be C89 if desired.)
Now I'm being a bit lazy and using the compiled objects directly, but it'd be just as easy to replace them with a library include directive, or even dynamically link against the shared library and use an entirely different language.
It's not actually my goal to make a C++ SDL port, what I really want to do is make a port using Ruby only. May not be so easy, we'll have to see how one accesses shared libraries in it.
The main src/Makefile was also simplified for the sake of supporting non-Qt code. All of the Qt and ruby references were moved into the src/ui_qt/Makefile.
I fixed up aDSP to compile again, but you still have to manually comment out sDSP and comment in aDSP. Doing so will net you a 6-12% speedup at the cost of some accuracy.
Lastly, I added a workaround for the Battletech 3050 splash screen.
2010-03-31 - v063r02
It would be a really good idea to test all of the HDMA-sensitive games with this WIP, if anyone's up for it.
Rewrote most of sCPU::DMA. It now implements a parallel two-stage pipeline to more closely model the hardware. Even if it turns out to be wrong, simply making dma_write() immediate would revert it to the old behavior. Fixed a bug where HDMA init and run were always syncing to the DMA counter, even when a DMA was already in progress. Will speed up the S-CPU in a very, very small number of games, namely College Football '97. Most games avoid this because it can crash CPUr1. New DMA variables means new save state version, sorry.
I did not add the MDR override code, because it's too fucking insane. Speedy Gonzales still works.
Removed the status bar size grip entirely. There's really no point in it being there in windowed mode since you can already grip the sides of the window anyway. Added space to each side of the status text so that it doesn't nail the very edge of the monitor.
Added checks in XML mapping to not map in special chip sections when you try and load BIOSes directly, which will stop the SGB and BS-X BIOSes from crashing the emulator. Load it the right way and it'll work fine, as always.
Fixed the loader window to display screenshots properly when you have HTML entities in the filename, eg &, < and >.
2010-03-29 - v063r01
I've had enough of idiots incapable of finding fullscreen settings. The menubar is enabled in fullscreen mode by default. A new option in settings->configuration->video will let you hide it as with v063 official. I don't want to hear about how I shouldn't allow any settings to be configured differently in fullscreen mode, or how it should be in a GUI panel, or whatever. I will ignore you if you bring it up.
I've also added the strpos / qstrpos function->class code, as mentioned in the programming section.
2010-03-28 - v063
Time for another (hopefully) stable release. The changelog has all updates since the last stable release.
Most notably, this release features substantial accuracy improvements all around. Almost all of them represent brand new findings never before seen in any SNES emulator.
Changelog:
fixed off-by-one buffer size issue in S-PPU RTO calculations [PiCiJi]
added XML parser
added XML-based memory mapping system
moved header-based memory mapping code into snesreader library
added some linker flags for Fedora [belegdol]
added cheat code database; with codes for over 1,500 games [mightymo]
fixed a bug where S-CPU IRQs were being tested one cycle early on direct page indexed read opcodes
added global cheat system enable/disable checkbox to cheat code editor
fixed bug in overflow calculation of S-CPU ADC and SBC opcodes in BCD mode [blargg]
emulated the S-CPU ALU MUL and DIV hardware delays with partial result calculation steps [blargg]
controller port read now returns real-time results of B button when strobe latch is raised
major improvements to emulation of the S-SMP TEST register [blargg, byuu]
fixed DSP2 memory map [Overload]
"Apply Patch" checkbox will now scan UPS patch folder if one is set in the paths section
fixed S-CPU TSC negative flag calculation in emulation mode [address]
added "make uninstall" command to Makefile for Linux users
S-CPU (H)DMA now updates the S-CPU MDR; fixes a freeze in Speedy Gonzales - Stage 6-1
very substantial code cleanups and optimizations as a result of moving from C++98 to C++0x
2010-03-24 - v062.10
Added make uninstall, and fixed up nall::function to also bind lambdas that don't yet exist in GCC 4.4.
2010-03-23 - v062.09
Mostly minor stuff again.
Fixes:
array, linear_vector and pointer_vector need to set source.pool = 0 before calling reset() to avoid destroying the object we're trying to move.
All of nall::string is inside namespace nall now. No idea what I was trying to do before with the half-global approach.
nall::function gains a reset() function, more obvious than func = (void*)0;
The movie file loader wasn't binding the right action when changing files and clicking load, can't believe nobody noticed that one.
2010-03-20 - v062.08
This WIP has bsnes.exe, snesreader.dll, and src/. If you need anything else, get it from past releases, please.
I fixed TSC negative flag calculation in emulation mode. Will pass this test now:
snes_test_tsc.zip
Way too obscure to affect anything, but definitely good to get it right.
Also rewrote nall/function.hpp to use C++0x variadic templates. New version is ~85 lines instead of ~190, 40% smaller, doesn't require recursively including itself, doesn't require the C preprocessor, evaluates to ensure the member function pointer is big enough to hold what you're assigning statically (at compile time) instead of dynamically (at run time), and supports infinite arguments instead of zero to eight now.
2010-03-19 - v062.07
This is source code only, no binaries. Sorry, worn out after spending four hours straight writing crazy ass Julian<>Gregorian date functions. Holy fucking hell that is crazy shit. Tell me, how many days have passed since 01-01-4731 BC on the Julian calendar?
Okay, this really was just about taking advantage of vectors inside of vectors. I've updated the XML parser to use vectors of actual objects instead of pointers. This makes cleanup free, and turns countless ->'s into .'s -- much nicer to look at. I may take advantage of overloaded operators for something now, not sure yet.
2010-03-18 - v062.06
You'll need snesreader's DLL from my last WIP post to use the above.
This initializes mode, region and ram_size again in Cartridge::load() to stop the phantom SRAM files from being generated.
This fixes DSP-2 mapping to match Overload's findings (which requires an unposted snesreader, so Dungeon Master won't run for you guys yet.)
This removes nall/traits.hpp and uses std::tr1::type_traits instead. It also drops move, forward and identity in favor of those from std::tr1::utility*.
This fixes linear_vector and pointer_vector to not crash when using vectors of vectors and copying them.
This fixed linear_vector, pointer_vector and array to initialize all internal variables for all constructors.
This fixes the file browser to look for patches in your patch directory, so the "Apply Patch" box should work correctly now.
I have no objection to using functions from the C++ standard library when they don't suck.
2010-03-17 - v062.05
snesreader_2010-03-16
To run this, you'll need the DLLs from v062r04's public beta, and the updated snesreader.dll from the above in the same folder as the WIP. No profiling.
This fixes UPS patching, and it also modifies snesreader to generate the XML map separately, so that the map can be generated post-patching.
The new enum classes weren't attaching properly to the config file, so the input settings, expansion port and region settings are saved again.
It also converts the S-SMP timers back to unsigned integers instead of using floating point, no accuracy improvement but much more in line with hardware.
Lastly, it makes the div register shift left 16 places and pre-shifts on divide, which is just for aesthetics.
And I'll wait on your tests, FitzRoy. I really hope that Big Run Jaleco Rally is correct, because I don't have the first idea how to debug that one. Speedy I can probably handle.
2010-03-15 - v062.04
I suppose I should start calling these nightlies, heh. blargg went ahead and verified every last possible edge case with regards to the S-CPU MUL / DIV registers. It uncovered a few errors in my implementation, which have since been corrected. The design used now should be a direct reflection of the hardware implementation: no actual multiplication, no actual division, and no variable-length bit-shifting.
We also spent about eight hours straight hammering away at the S-SMP test register. We have a partial understanding of TEST.d3 and TEST.d0, and a complete understanding of the other six bits. All of this has been implemented as well.
Lastly, snesreader gets a tiny update to fix Test Drive II, which broke due to a slight regression when porting the mapping code to XML.
2010-03-15 - v062.03
blargg and I sat around for a good 8+ hours today hacking away at the S-SMP Pandora's Box: the TEST register. What better way to spend Pi Day, right?
We came up with the following tests:
http://byuusan.kuro-hitsuji.net/blargg_2010-03-14.zip
First, controller_strobebehavior.smc improves emulation of $4016. When the joypad strobe latch = 1, reading $4016 returns the current value of the B button. As in, you can keep reading it over and over. It won't increment the shift register, and it will keep telling you the actual current state of the button. This is very much like the NES behavior. One more TODO in the S-CPU code taken care of.
Next, all kinds of S-SMP TEST register improvements. Turns out d7-d6 alone controls the actual S-SMP clock rate. 0 = 100%, 1 = 50%, 2 = 0% (locks the S-SMP forever), 3 = 10%. Wild stuff, you can actually permanently slow the S-SMP relative to the S-CPU.
d6-d5 is a timer tick control, but it actually uses d7-d4 overlaid. The algorithm is fucking nuts, and is really my only contribution to today's work. The rest was all blargg's research.
We had d2 wrong, it's not MMIO disable, it's RAM disable. As in, disable read and write. Returns 0x5a on regular SNES, 0xff on mini-SNES. 0x5a is not the S-SMP MDR. IPLROM is still readable when RAM is disabled. d1 was correct, just RAM write disable. Can still write to $f8 and $f9, of course. But it won't go through to RAM.
d3 and d0, we are still a little unsure on. The T0-T2 timers seem to have a low and high phase, and if you strobe them you can force ticks of stage 2 to happen, and you can disable them in such a manner than stage 2 never ticks at all.
blargg is still uncovering all sorts of crazy things in $xB mode, so emulation of these two bits is not perfect.
But overall we are leaps and bounds further now toward complete emulation. I'd say we went from 10% to 80% with today's work. But we'll have to see how deep the rabbit hole goes on d3+d0 first.
Current register map:
Code:
case 0xf0: { //TEST
if(regs.p.p) break; //writes only valid when P flag is clear
Fairly confident that no emulator prior to this WIP could pass any of blargg's tests, so this is all brand new information. Fun stuff :)
2010-03-14 - v062
Major accuracy improvements have happened over the past few days. They easily warrant a new beta release.
First, it turns out that every emulator to date; not only for the SNES, but for the Apple II GS as well, incorrectly computed ADC (add) and SBC (subtract) flags in BCD (binary-coded decimal) mode. At least fifteen years of emulating the 65816 processor, at least five known investigations into their behavior, and we all still had it wrong.
So I wrote some tests that dumped every possible combination of adc and sbc with every possible input and every possible flag, and recorded both the accumulator result and status flag register. From here, blargg figured out the underlying trick: the CPU was computing overflow before the top-nibble's BCD correction pass. With the routines rewritten, bsnes perfectly matches real hardware now.
Next, some background. The whole reason I got into SNES emulation was because I was tired of writing code that ran perfectly fine on emulators, but failed miserably on real hardware. The number one problem was emulators allowing video RAM to be written while the screen was being rendered. This single bug has broken dozens of fan translations and ROM hacks. Some have been updated to work around this bug, and many others are left in a permanently broken state (such as the translations of Dragon Quest I & II and Sailor Moon: Another Story, to name just two.) After asking emulator authors to fix this since 1997, I finally had enough in 2004 and started on bsnes. For this particular bug, I'm very happy to report that all but one SNES emulator now properly blocks these invalid accesses. Although sadly one still offers a configuration setting for backwards compatibility with these translations. What an ironic shame ... emulating an emulator. And in the process, sapping the motivation to ever go back and fix these
titles to ever run on real hardware. But I digress ...
The second biggest problem that causes software created under emulation to break on real hardware has, without a doubt, been the hardware delays as the S-CPU computes MUL (multiplication) and DIV (division) results. To date, whenever you used this hardware functionality, emulators have immmediately furnished the correct results. But on real hardware, multiplication requires eight CPU cycles, and division requires sixteen. Each step computes one bit of the source operand and updates the results. Reading the output registers early thus provides the partially computed results.
This is obscure. It isn't well known, and many people writing software for the SNES probably aren't even aware of this limitation. Because of the partial computation results, outright delaying the computation would break many commercial software titles. But by not emulating the delay at all, we were causing a great disservice to anyone wishing to use an emulator for development purposes.
Now, once again, thanks to blargg's algorithm help, he has determined the underlying multiplication and division algorithms. Combined with my expertise of SNES analysis and hardware testing, I was able to determine when and how the ALU (arithmetic logic unit) stepped through each work cycle. Our work combined, bsnes now also perfectly emulates the hardware MUL and DIV delays.
Again, this isn't going to fix commercial software titles. They would have realized that they were reading back invalid MUL and DIV values, and fixed their code. This is for all of the software developed using emulators. This is an extension of my commitment to create a hardware emulator, and not a video game emulator.
We also verified that the S-PPU multiplication interface does indeed return instant results with no delay. So emulation of that interface was already correct.
I'm only labelling this release a beta because it hasn't been tested. But I'm fairly confident that it is stable, and I seriously recommend upgrading from v060 or prior releases. This is easily one of the last major pieces missing from emulation.
The last notable elements are: S-CPU auto joypad poll timing, S-CPUr1 HDMA crash detection, S-CPU<>S-SMP port ORing, S-SMP timer glitching, S-DSP mute pulse, and full cycle-level emulation of the S-PPU. With all of the aforementioned items, I will consider a v1.0 release of bsnes ;)
Lastly, I'll post this screenshot just for fun. When d4s translated Breath of Fire II to German, he added some code that relies on the incorrect emulation of the DIV register to detect emulators. With this emulated properly, you now see the following screen:
./sshots/bs_349.png
Sorry to spoil that, but the secret's already out, as the MESS team reported on it publicly already.
I intend to add pseudo-randomness support shortly, which should eliminate one of the last vectors possible to distinguish bsnes from real hardware :)
A million thanks to blargg for making this release possible.
2010-03-08 - v061.01
Found the cause of the issue breaking SuperFX games after loading SA-1 games. Seems the XML mapping tree wasn't being cleared. It's also not a good idea to use bsnes/ as the folder name when the Makefile generates a binary by the same name in the same directory, so back to src/ for the main emulator it is.
With those fixes, this release should be fully stable; but again my intentions are to keep v060 as the stable release for a while.
Nonetheless, you can grab the new beta at Google Code. It should be the last update for at least a few weeks.
2010-03-07 - v061
Please keep in mind that bsnes v060 remains the current stable release. v061 has been released as a work-in-progress build. As such, it is only available at Google Code.
I am releasing this WIP to allow the public to test out and comment on the new XML mapping system, as well as the integration of mightymo's cheat code database into the cheat editor. I would greatly appreciate feedback on these two on the forums.
There are some important issues with this release. The biggest is the move to C++0x. This requires GCC 4.4.0 or newer to compile, thus it is not currently possible to build this on OS X using Xcode. Nor would it be possible on certain BSDs or older distros. If you have an older compiler, please stick with v060, or use a binary release where available.
Another issue is that TDM/GCC 4.4.1 for Windows crashes with an internal compiler error when attempting to generate a profile for the DSP-1 module. This is a bug in the compiler, and not in the code itself. The workaround is to simply omit profile-guided optimization for this one object.
Lastly, there's also a known bug in the memory mapping. If you load an SA-1 game, SuperFX games will not load properly afterward unless you restart the emulator. I'm looking into the cause now, but it didn't seem serious enough to hold up a WIP release.
So, yes. If you want a good gaming experience that's been fully tested and stable, please stick with v060. If you want to see some bleeding edge features, I'd appreciate feedback on v061. Thanks for reading this.
Changelog:
added mightymo's cheat code database, access via "Find Cheat Codes" button on cheat editor window
added an option to temporarily disable all cheat codes quickly
debugger now properly uses S-SMP IPLROM when needed for disassembling and tracing
indexed indirect read opcodes in the S-CPU were testing for IRQs one cycle too early [someone42]
fix an off-by-one array iteration in S-PPU OAM rendering [PiCiJi]
added some implicit linked libraries to linker flags for Fedora [belegdol]
moved from C++98 to C++0x, resulting in substantial code cleanups and simplifications
C++0x: implemented foreach() concept for linear container iteration
C++0x: implemented concept system using SFINAE and type traits
C++0x: utilized auto keyword to increase source readability
C++0x: moved to strongly-typed enumerators
C++0x: rewrote va_list-based code to use type-safe variadic templates
C++0x: replaced noncopyable class with deleted default copy functions
C++0x: replaced custom static_assert template class with built-in version
C++0x: utilized rvalue references to implement move semantics into string, array, vector and serialization classes
C++0x: utilized std::initializer_list for { ... } initialization support to lstring, array and vector classes
2010-02-08 - v060
This is a long-term stable release. A full changelog will be available at the forum link below later in the day. Also, please note that I have merged all of the various distributions into two packages. The Windows binary package now contains both the profile-optimized (fast) build, and the debugger build. The source code package now contains sources for bsnes, snesreader, snesfilter and supergameboy.
Changelog:
added Direct3D HLSL pixel shader support [mudlord]
fixed a signal issue that caused loading games to take 1-2 seconds longer in v059
21fx API revised to its final form, S-MSU (public documentation pending)
worked around QTBUG-7188 to fix multi-file 7-zip file listbox to update when scrolling
added scale max - normal, wide, and wide zoom modes to fullscreen mode
added overscan cropping tool (needed for wide zoom mode; useful for developers simulating games on a real TV)
added "go up one folder" button to file load dialog
added group (un)assignment to the input settings window
now honors input.allowInvalidInput setting; defaults to false [Jonas Quinn]
to load folders as game images, folders must end in .sfc, .bs, .st, .gb now
debugger: added S-CPU (H)DMA registers; S-SMP registers; S-DSP registers to properties list
snesfilter: HQ2x filter is now multi-threaded (scales infinitely: the more cores you have, the less overhead required)
pixelshaders: added screen curvature shader to simulate curved CRT tubes
source: lots of code cleanup, as always
2010-01-24 - v0.059.06
This is an experimental release, as such it is posted only to Google Code.
Changelog:
21fx API moved to pre-finalized form as S-MSU1; more about this on the forum
OpenGL driver now uses GL_CLAMP_TO_BORDER instead of GL_CLAMP_TO_EDGE to support screen curvature shader
rewrote file open dialog; code is greatly simplified, interface is improved
all cheat code columns are now enquoted, and empty codes at the bottom of the file are omitted (format is compatible with previous releases still)
debugger: added missing DMA variables to S-CPU properties viewer
snesfilter: added OpenMP (multi-threading) support to HQ2x filter
lots of other miscellaneous code cleanup work
2010-01-11 - v0.059.02
Changelog:
added folder-up button to the file loading window
hid new-folder button except on path selection window
removed "Assign Modifiers as Keys" button; replaced with input.modifierEnable in the configuration file
fixed a Qt signal issue that was causing ROM loading to take an extra second or two longer than necessary
scale 5x setting will now maintain an exact multiple in both width and height for both NTSC and PAL modes
re-added group assignment and unassignment to the input settings window
re-wrote mouse capture code to be more intuitive, now uses buttons to set assignment
re-added input.allowInvalidInput check to stop up+down and left+right key combinations by default [Jonas Quinn]
split "Tools Dialog" menu option into separate items for each tool (Cheat Editor, Cheat Finder, State Manager)
added S-SMP and S-DSP property information readouts to the debugger
2010-01-06 - v0.059
This is mostly a polishing release. There's lots of nice little improvements over the last release, so it should be well worth the update.
Changelog:
fixed a bug in the save state manager that was allowing saves for unsupported special chips
added save state support for SuperFX games
added save state support for SA-1 games
the "Apply UPS" checkbox actually works now; allows bypassing of patching prior to ROM loading
ROM loader will display internal ROM title and header info for uncompressed files ending in ".sfc"
added Shift JIS to UTF-8 conversion for internal ROM titles
"open-folder" concept now requires folders to end in ".sfc" to avoid false positives
shrunk all GUI buttons and right-aligned them, as some of them were ridiculously long before
rewrote settings and tools windows to be driven via tabs instead of lists; this saves a lot of screen space
rewrote input mapping system to use a tree view instead of the confusing combo box hierarchy; hopefully more people will find the user interface GUI hotkey remapping section now
added support to map modifiers as individual keys (eg you can map the shift key to the SNES select button)
rewrote the cheat code editor, it behaves exactly like the state manager now; there are 128 pre-defined slots, and it is easy to clear any or all of them
the cheat file will auto erase itself upon exit if all codes and descriptions have been erased
fixed title bar game name ordering; was "bsnes v058 - Game Name", is now "Game Name - bsnes v059"
fixed a bug where pressing escape inside the main window's menus would cause the program to quit
Windows: worked around QTBUG-7188 to fix the multi-file archive loading dialog; it was not updating properly before
Linux: added full-API PulseAudio driver with synchronization and latency control [RedDwarf]
Linux: fixed a crashing bug involving OpenGL and glXSwapIntervalEXT()
Linux: X-Video driver texture now resizes dynamically to support > 1024x1024 for any future filters to use
Debugger: single-stepping instructions now updates all windows marked to "auto update"
Debugger: fixed execute breakpoints, they were disassembling at the wrong offset
Debugger: S-CPU bus breakpoints now mirror WRAM $7e:0000-1fff to $00-3f|80-bf:0000-1fff
Debugger: fixed a rendering issue when stepping through hires games
Debugger: added property system; can now view internal register states of all S-CPU and S-PPU registers (S-SMP and S-DSP coming soon)
Debugger: added CGRAM palette viewer
Debugger: added OAM sprite viewer (no graphical output yet)
Debugger: added options window -- so far only to control output of memory / execution usage tables
Debugger: updated usage and memory export file names to start with the loaded cartridge name
Source: cleaned Utility class, split some of the functionality out to Cartridge class
Source: greatly simplified SNES::Cheat class, SNES::Cartridge class; etc
A note to Windows Vista and Windows 7 users: there is still an open bug in Qt 4.6.0 that causes menus attached to popup buttons to initially appear invisible. See QTBUG-6645 for reference. As it is a bug with Qt itself, there is nothing I can do about it but wait patiently. You can work around this by pressing the tab key after you click the button. This affects the options buttons on the file load dialog, and on the input settings window.
Also, mudlord has submitted an updated Direct3D driver that adds HLSL pixel shader support. It was too close to get into this release, I'd like some time to test it. But hopefully it will get in by v060, or at the very worst, v061. Many, many thanks to mudlord for the awesome work :D
So that we can also find results with the github search and do not have to search on another site. Source: https://gitlab.com/higan/bsnes-history-kit/-/blob/master/sources/tukuyomi/misc/bsnes_changelog.txt
2010-12-26 - bsnes_v073r01.tar.bz2 (Windows 32-bit compatibility binary included) While perhaps not perfect, pretty good is better than nothing ... I've added emulation of auto-joypad poll timing. Going off ikari_01's confirmation of what we suspected, that the strobe happens every 256 clocks, I've set up emulation as follows: Upon reset, our clock counter is reset to zero. At the start of each frame, our poll counter is reset to zero. Every 256 clocks, we call the step_auto_joypad_poll() function. If we are at V=225/240+ (based on overscan setting), we check the poll counter. At zero, we poll the actual controller and set the joypad polling flag in $4212.d0 to 1. From zero through fifteen, we read in one bit for each controller and shift it into the register. At sixteen, we turn off the joypad polling flag. The 256-clock divider allows the start point of polling for each frame to fluctuate wildly like real hardware. I count regardless of auto joypad enable, as per $4212.d0's behavior; but only poll when it's actually enabled. I do not consume any actual time from this polling. I honestly don't know if I even should, or if it manages to do it in the background. If it should consume time, then this most likely happens between opcode edges and we'll have to adjust the code a good bit. All commercial games should continue to work fine, but this will likely break some hacks/translations not tested on hardware. Without the timing emulation, reading $4218-421f before V=~228 would basically give you the valid input controller values of the previous frame. Now, like hardware, it should give you a state that is part previous frame, part current frame shifted into it. Button positions won't be reliable and will shift every 256 clocks. I've also removed the Qt GUI, and renamed ui-phoenix to just ui. This removes 400kb of source code (phoenix is a lean 130kb), and drops the archive size from 564KB to 475KB. Combined with the DSP HLE, and we've knocked off ~570KB of source cruft from the entire project. I am looking forward to not having to specify which GUI is included anymore.
2010-12-24 - bsnes_v073.tar.bz2 This release marks a major step forward, offering full low-level emulation of all four DSP coprocessors based on the NEC uPD77C25 processor core. Many people were responsible for this milestone: Dr. Decapitator for the actual decapping and extraction; Lord Nightmare for the cartridges and some special analysis tools; myself, Jonas Quinn and Cydrak for the uPD77C25 emulation; and all of the donors who raised the necessary $1,000 for the necessary hardware and equipment needed to pull this all off. To say thanks to the donors, I am releasing the uPD77C25 emulation core to the public domain, so that everyone can benefit from it. All four DSP emulations will be improved by this by way of having realistic timing; the DSP-4 will benefit further as the high-level emulation was incomplete and somewhat buggy; and the DSP-3 will benefit the most as the high-levle emulation there was not complete enough to be playable. As a result, most notably, this means bsnes v073 is the first emulator to fully be able to play SD Gundam GX (J)! As bsnes' primary goal is accuracy, the LLE DSP support renders the old HLE DSP support obsolete. Ergo, I have removed the 166KB of HLE source code, and replaced it with the uPD77C25 core, which comprises a mere 20KB of source code. As this LLE module supports save states, this also means that for the first time, DSP-3 and DSP-4 games have save state support. On the other hand, this also means that to run any DSP game, you will need the appropriate program ROM. As these are copyrighted, I cannot distribute them nor tell you where to get them. All I can do is provide you with the necessary filenames and hashes. SHA256: Code: 5f2e5ed06b362be023b978b5978813ecb9a07c76592454b45c2a1ed17a0de349 dsp1.bin 4d42db0f36faef263d6b93f508e8c1c4ae8fc2605fd35e3390ecc02905cd420c dsp1b.bin 5efbdf96ed0652790855225964f3e90e6a4d466cfa64df25b110933c6cf94ea1 dsp2.bin 2e635f72e4d4681148bc35429421c9b946e4f407590e74e31b93b8987b63ba90 dsp3.bin 63ede17322541c191ed1fdf683872554a0a57306496afc43c59de7c01a6e764a dsp4.bin MD5SUM: Code: 4865ac61cd758b0f9383fe3d4d3b8694 dsp1.bin c8bfb983703a96e1c3d4683105112bc0 dsp1b.bin e500ec7f6005e78cb935eea5289c8cc4 dsp2.bin c037185c8bbef6313226200dbe5fd07f dsp3.bin fe85065a7023551b0d84941a094435ba dsp4.bin All of these files are exactly 8KB (8,192 bytes) in size. Changelog:
2010-12-23 - bsnes_v072r14.tar.bz2 (source code only.) Changelog:
2010-12-22 - bsnes_v072r13.tar.bz2 (source code only.) The DSP-1 and DSP-3 emulation appears to be great. However, there are bugs in the other two. DSP-2, Dungeon Master: the graphics in-game appear corrupt. It looks like the first two pixels have the right color, the next six have the wrong color, resulting in vertical stripes. DSP-4, Top Gear 3000: the car sprites appear to be showing 8x8 tiles instead of 16x16 files, resulting in 3/4ths of the cars being invisible, but only up close. Dr. Decapitator and Lord Nightmare are supremely confident that our dumps are 100% accurate, there was no bus wavering at all this time. We believe they are bugs in the uPD77C25 emulation. I desperately need help! I have spent the past several hours trying to ascertain what the problem is, to no avail. I've tried messing with just about every flag, every register, checking for use of OV1, S1, custom opcodes, etc ... I am having no luck. I'm going to keep trying with even more sophisticated cross-analysis. But Cydrak, if you would please rework that magic of yours, I'd be eternally grateful :D
2010-12-21 - bsnes_v072r12.tar.bz2 (source code only.) This release defaults DSP-3 loading to use the uPD77C25 core. It also pre-emptively does the same for the DSP-2 and DSP-4. v072r11 did this for the DSP-1. I've also renamed my string<>integer conversion function names: strhex -> hex strsigned -> integer strunsigned -> decimal strbin -> binary strdouble -> fp (this one will no doubt be trouble since 'file fp' is a common idiom. floatingpoint is too long, float and double are already reserved.) The reason for this is so that string building is not so hideous. Pre-C++0x: Code: string output = string() << "A: " << strhex<4>(a) << " B: " << strhex<4>(b) << "\n"; Before: Code: string output = { "A: ", strhex<4>(a), " B: ", strhex<4>(b), "\n" }; After: Code: string output = { "A: ", hex<4>(a), " B: ", hex<4>(b), "\n" };
2010-12-18 - bsnes_v072r11.tar.bz2 This release marks a major milestone: low-level emulation of the DSP-1B coprocessor, used by the following games:
2010-12-18 - bsnes_v072r10.tar.bz2 Current code.
2010-12-16 - bsnes_v072r09.tar.bz2 Fixes OP/LD RQM=1 on DR modify, Mario Kart can get in-game, but the track is completely corrupted. Reorders order of operations for OP, in an attempt to mimic parallelism. Added support for OP KLM DST. Added S1 flag setting, probably not correct. I've updated the disassembly. It is now in: src,dest format, as that is what the official development tools use. Added $ to hex values for consistency with the S-CPU disassembly. Now, here is a list of issues that need to be addressed, as far as I know. Multiplication happens after each opcode, K*L is put into M,N. But it mentions the result is 30-bit with a sign bit. Isn't that the same thing as 31-bit? Or is it possible it is acting like the sign bit of the flag registers, and just mirroring the highest bit? What is the order of operations for OP/RT? Take this example: Code: 4eb inc a mov a,rp To dump the data ROM correctly, we have to do the mov first, and the inc second. The way I've implemented it was to do the inc read, then the mov read, then the inc write, then the mov write. Both have the ability to manipulate both the IDB register and any shared registers. It is at least somewhat clear from the documentation that the DPL, DPHM and RP adjustments happen at the end of the opcode. How in the hell do we calculate the OV1 flags? The documentation says it's set to 1 if there were an odd number of the three overflows. What three overflows? What about the S1 flag? Is it set to 1 on a positive overflow, or set to 1 on a negative overflow? What happens if there is no overflow, does it get set to zero always then? The SGN register may be a useful hint to figuring this one out. Am I even calculating OV0 correctly? CMP (one's complement) is just !Q, right? They would say NOT if they wanted ~Q. How exactly does XCHG work? The document says it's an 8-bit exchange. Which 8-bits, the top eight or the bottom eight? It updates the S0 flag which is suspicious for the bottom eight. What is up with KLM mode? The nicer doc says you read from RAM[DP | 0x40], while the uglier one says that you read from RAM[(DP & 0x3f) | 0x40]. They list it as HiRAM, yet it forces D6=1 rather than D7=1. And just out of curiosity, why the fuck does it force D6=1? What possible use is that? The stack has four levels, and it is LIFO. So what happens when you pull an address off the stack? Does the now empty slot at the end get set to zero, or keep the previous address, or does it act more like a ring buffer and move the old first value to the last value? When SR.DRC=0 (eg 16-bit DR transfer mode), does RQM get cleared for each 8-bit write, or only after two 8-bit writes (eg after a full 16-bit transfer)? What happens to the high 8-bits of the 16-bit DR register when you write to it from the S-CPU in 8-bit DR transfer mode? Does it keep whatever was there, or is it forced to zero ala 65816 index registers?
Sadly, I think the only way we are going to be able to improve from here is going to be to log S-CPU DR reads from both the HLE and LLE emulation, find differences, and then start trying to parse the uPD disassembly code directly to figure out where the wrong results in the LLE log are coming from. Eg basically what I did with the simplest case of analyzing the data ROM dumping function.
2010-12-16 - bsnes_v072r08.tar.bz2 mariokart.tar.bz2 This WIP adds NEC uPD77C25 emulation. Unfortunately it's not at all functional yet, there are way too many things I don't understand about the chip. I'm absolutely going to need help to complete this. What I have is 'functionally' complete, but obviously wrong in probably dozens of places. The biggest things I don't understand:
2010-11-02 - bsnes_v072r07.tar.bz2 I'm happy enough with the debugger now. Not 100% up to par with the old one, but it also does some new things the old one didn't.
2010-11-01 - bsnes_v072r06.tar.bz2 Updated libsnes to use new file and function names. Also added EditBox::setCursorPosition for GTK+ and Qt, only used by the debugger so far so that when text is added, it auto-scrolls to the bottom.
2010-10-29 - bsnes_v072r04.tar.bz2 I guess two days is a while. nall/snes/smp.hpp created, ~68 addressing modes compared to the CPU's ~27, ugh. All hooked up, you can step into / step over / trace the S-SMP now as well. Word of caution, not a good idea to try stepping over without stepping into at least once first. I'll make it a requirement later. Reason is you may not be on an opcode edge at the time, because of course bsnes isn't an opcode-based emulator.
2010-10-27 - bsnes_v072r02.tar.bz2 Just debugger work here. About three or four hours to write nall/snes/cpu.hpp, which is basically opcode encoding information for disassembly. The disassembler inside bsnes itself was kind of limited, it always spit out all register info, had no flexibility to insert custom symbols/labels for debugging information, and the disassembler was very limited because it relied on the current processor status register M/X flags, rather than what they were when the opcode was executed. That information is stored in my usage table. So after hours of making that table by hand, I hooked that in and got proper forward+backward disassembly working, along with "step over". Still have to add "proceed". Given what a pain in the ass that was, I'm probably going to put off the S-SMP debugger for a while :P
2010-10-26 - bsnes_v072r01.tar.bz2
2010-10-22 - bsnes_v072.tar.bz2 bsnes v072: there's no need to upgrade if you already have v071. This update just fixes some minor things and fixes Qt compilation on Windows. Changelog:
2010-10-22 - bsnes_v071.tar.bz2 It is very important to note if you choose to use my binaries, the phoenix port does not support ROM images with copier headers, ROM images that do not end in .sfc (for SNES cartridges), .st (for Sufami Turbo cartridges), .bs (for BS-X flash cartridges), or (.gb,.gbc,.sgb) for Game Boy cartridges, it does not support compressed images, it does not support software filters, rewind support, fullscreen mode, IPS patches, cheat searching, movie recording, native OS file dialog boxes, asciiPad simulation, video region cropping, layer/channel toggle, slowdown, etc. It is meant to be minimal, and if this is a problem for you, please stick with the Qt port. Undoubtedly, no matter how much I emphasize this, people are going to not read this, use the phoenix port, and be put off and not use bsnes anymore. That's very unfortunate, but I am releasing this GUI anyway for those who do share my design goals and aesthetics. So I will ask a favor of you all, if you see someone mentioning something of the phoenix port not working, please advise them that it is not the general use version, and that they should stick with the Qt port. Thanks in advance. Changelog:
2010-10-17 - bsnes_v070r17.tar.bz2 No binaries, basically the same as v070r16a on Google Code, only this one has source code Changelog:
2010-10-13 - bsnes_v070r16a.tar.bz2
2010-10-11 - bsnes_v070r16.tar.bz2 Windows 64-bit non-PGO performance binary included. This mostly contains improvements for nall, like path unification. This should fix FitzRoy's issue with .. on Windows.
2010-10-09 - bsnes_v070r14.tar.bz2 Only source, I left v12 up if you want a Windows binary. Changelog:
2010-10-08 - bsnes_v070r12.tar.bz2 Windows 64-bit non-PGO performance binary included. Changelog:
2010-10-08 - bsnes_v070r11.tar.bz2 Windows 64-bit non-PGO performance binary included. Changelog:
2010-10-05 - bsnes_v070r10.tar.bz2 Windows 64-bit non-PGO performance binary included. Changelog:
2010-10-05 - bsnes_v070r09.tar.bz2 No binaries included. Changelog:
2010-10-04 - bsnes_v070r08.tar.bz2 No binaries included. Changelog:
2010-10-03 - bsnes_v070r07.tar.bz2 No binary included. Changelog:
2010-10-02 - bsnes_v070r06.tar.bz2 No binary included. Changelog:
2010-09-30 - bsnes_v070r04.tar.bz2 No binaries, sorry. Hopefully most of you can compile, especially now that Qt isn't required. Changelog:
2010-09-29 - bsnes_v070r03.tar.bz2 Changelog:
phoenix::Viewport has its own window class, that paints a black brush background I'll handle questions and whatever later, I'm too busy coding. Example, Curvature.shader: Code: <?xml version="1.0" encoding="UTF-8"?>
Example, Pixellate.shader: Code: <?xml version="1.0" encoding="UTF-8"?>
Example, Sepia.shader: Code: <?xml version="1.0" encoding="UTF-8"?>
Format is subject to change, more specifically I may change the tag from HLSL shaders.
In the long-long term, it'd be nice to extend the format to allow multiple shaders to be chained together and to encode base64 texture files.
But for now, this is good enough.
2010-09-28 - bsnes_v070r02.tar.bz2 Changelog:
2010-09-27 - bsnes_v070r01.tar.bz2 Changelog:
2010-09-25 - bsnes_v070.tar.bz2 This release represents the coup de grâce of bsnes/Qt. Changelog:
2010-09-25 - bsnes_v069.tar.bz2 This release adds some nifty new user interface features, and improves both performance and accuracy. The performance core is now fast enough to maintain a constant 60fps on a first-gen Intel Atom N270 in 98% of games. Changelog:
2010-09-24 - bsnes_v068r25.tar.bz2 Windows Qt/performance/32-bit/non-PGO/non-debugger (yeah it's getting ridiculous how many variants are possible) binary included This is basically the v069 release candidate, heavy testing would really be appreciated. I'd like for v070 to be the first official phoenix release, but if a major bug slips past us that will ruin it. The big change is that save state support was added to the PPU-performance core.
2010-09-24 - bsnes_v068r24.tar.bz2 Fixes OAM latchdata for all 3 cores and CGRAM address invalidation for the accuracy core (the only one that really does it because it needs cycle PPU timing.) Also removes the OAM/CGRAM read/write functions to put them inside the actual MMIO functions. Easier to handle all the special cases that way. VRAM is a bit more annoying since there's two read and two write functions. This should fix battletech/mechwarrior 3050 palette at least.
2010-09-22 - bsnes_v068r22.tar.bz2 Includes 32-bit binary, with no profiling. Wanted to torture myself, so I implemented the hardest window of all, the cheat code editor. I had to sacrifice checkboxes inside lists, unfortunately, but it's a necessary evil. Maybe some day if we can port checkboxes inside list items to Windows and GTK+, we can add it back. It should be the only really apparent GUI sacrifice, though. You toggle cheats by double-clicking them in the list. Easy to do, but not apparent. I also added in the focus policy. ./sshots/bsnes_20100921b.png As you can see, phoenix is looking amazing compared to Qt. No consistency issues, no non-native look anywhere. It looks really great in classic mode, too. Way better than Qt does in Windows classic, that's for sure. And no, I can't use snesreader or snesfilter, because both create Qt GUI windows. I don't know what I am going to do about that yet.
2010-09-21 - bsnes_v068r21.tar.bz2 Has an unprofiled 64-bit Windows binary for some reason. I meant to make it 32-bit, but forgot to swap the PATH variable to MinGW32, oops. Changelog:
2010-09-21 - bsnes_v068r20.tar.bz2 Changelog:
2010-09-20 - bsnes_v068r19.tar.bz2 This adds proper manifest files to get the nice XP/Vista controls. Need to find a way to auto-detect MinGW 32 vs 64 since I can't use $shell or `` on gcc -v on Windows. For now you have to edit the ui-phoenix/Makefile by hand. I've implemented the video settings window. I am going to be using separate windows this time. As nice as having everything in one place was, I didn't like being forced to stretch things to fill out the one-size-fits-all tab window I was using before. That and I don't feel like implementing tab support with phoenix anyway. The menu gets a load cartridge command, and bsnes writes save RAM files now. Loading by file dialog crashes on 64-bit. Something's fucked up there, but I don't know what. Again, help would be great here :) For those worried about the GUI ending up like the old hiro, this should allay some concerns: ./sshots/bsnes_20100920a.png ./sshots/bsnes_20100920b.png You would not believe what a pain in the ass it was to vertically center text within labels. I had to create my own replacement STATIC control, and even then DrawText alone can't center multi-line text, so I have to calculate the text size, and then manually place it vertically centered.
2010-09-20 - bsnes_v068r18.tar.bz2 This WIP fixes the Mode7 repeat issue in the accuracy core. More importantly, it's the first build to include phoenix. There is a stub GUI that does basically nothing right now. It will give you a window, a command to close the emulator, and an FPS meter so you can tell how fast it is. To load a ROM, you have to drag the ROM on top of the binary. I don't know if it will work if the filename+path has spaces in it or not, so avoid that to be safe. The big news is that there's both a 32-bit and 64-bit binary included, although neither are profiled because I really don't have enough of a GUI up to profile anyway. Windows uses: Direct3D + XAudio2 + RawInput - get the latest DX SDK for XAudio2 to work Linux uses: OpenGL + ALSA + SDL You will have to compile yourself to change these driver settings. For some reason, the 64-bit binary sometimes crashes on start, maybe 1:6 times. So just keep trying. I don't know what's up with that, I'd appreciate if someone here wanted to debug that for me though :D One really good bit of news, there was that old hiro bug where keyboard input would cause the main window to beep. I spied on the main event loop and, as suspected, the status bar was getting focus and rejecting key presses. What. The. Fuck. Why would a status bar ever need focus? So I set WM_DISABLED on it, which luckily leaves the font color alone. I also had to use WM_DISABLED on the Viewport widget that I use for video output. These two combined let me have my main window with no keyboard beeping AND allow tab+shift-tab to work as you'd expect on other windows, so hooray. Now, at the moment there's no Manifest included, because Microsoft for some reason includes the processorArcitecture in the file. So I can't use the same manifest for 32-bit and 64-bit mode, or the binary will crash on one or the other. Fuck. So the status bar may look old-school or something, whatever, it's only temporary. Next up, my goal is to avoid the hiro icon corruption bullshit by making phoenix itself try and use an internal resource icon. So just compile your app with that resource icon and voila, perfect icon. Not in there yet so you get the white box. Input is hard-coded, up/down/left/right/z/x/a/s/d/c/apostrophe/return. Lastly, compilation is ... in a serious state of flux. The code is set to compile bsnes/phoenix-gtk right now. Try it at your own risk. Give me a few WIPs to get everything nice and refined. Ubuntu users will need gcc-4.5, which you can get by adding the Maverick Meerkat repository, updating apt, installing the gcc-4.5 + g++-4.5 packages, and then removing and re-updating your apt/sources.list file so you don't end up fucking your whole system when you run apt again in the future. For anyone who can work with all of that, great! Please post a framerate comparison between 32-bit and 64-bit builds. Any game, any screen, so long as the FPS is not fluctuating when you measure it (eg don't do it during an attract sequence.) If anyone complains about the 64-bit binary not working and it turns out they are on 32-bit Windows, they are going to be removed from this WIP forum :P
2010-09-09 - bsnes_v068r17.tar.bz2 This hopefully fixes vertical and horizontal mosaic with the accurate S-PPU core. It also adds frame-skipping support to the compatibility and performance S-PPU cores. This is not visible to the user interface, because I feel that virtually nobody is going to play with frame-skipping on when they could use a faster emulation with it off. However, I did use it to enhance the 'Fast Forward' key. When you press it, it will now turn off video and audio sync, and set a frameskip of 9. This allows you to speed things up an additional ~60% over your max theoretical speed without frameskipping. ~35% with the compatible core, because the PPU is less of a bottleneck for it. Slowdown was improved, it will turn on audio sync if it is off until you release the key to ensure you actually get 30fps. Eventually it'd probably be wise to set a cap on the fast forward speed, but I hardly think it's an issue on today's computers. Image Performance core, normal Image Performance core, fast forward key held down Now if only we can increase that speed by another ten times ... perhaps Der Langrisser will be tolerable :)
2010-09-08 - bsnes_v068r16.tar.bz2 Non-profiled Windows compatibility binary is included. Testing this one and all the new features would be appreciated. New features? Image
2010-09-06 - bsnes_v068r15.tar.bz2 This adds a new "Effect Toggle" window to the tools tab list. There's no menu entry for it yet, oversight, but you can go to another tool and tab to it. The effect toggle window lets you toggle background/OAM layers on a per-priority basis and DSP sound channels. This only works with the compatibility and performance cores, because I'm not going to allow accuracy-violating hacks like that into the core. Non-essential icons have been removed, there's six of them left at the moment. I am too much of a consistency guy to only have some scattered around. I know other apps do that, but I'm not going to do that, and I grow tired of trying to hammer in icons that don't really represent the actions. Anyway, it still looks pretty good I think.
2010-09-06 - bsnes_v068r14.tar.bz2 Holy hell, that was a total brain twister. After hours of crazy bit twiddling and debug printf's, I finally figured out how to allow both lores and hires scrolling in the accurate PPU renderer. In the process, I modified the main loop to run from -7 to 255, regardless of the hires setting, and perform X adjustment inside the tile fetching. This fixed a strange main/subscreen misalignment issue, so I was able to restore the proper sub-then-main rendering for the final screen output stage. Code looks a good bit cleaner this way overall. I also added load state and save state menus to the tools menu, so you can use the menubar to load and save to ten slots. I am thinking that I should nuke the icons. As pretty as they are, it's getting tiresome trying to find icons for everything, I have no pictures to represent loading or saving a slot, nor to represent individual slots. I'll just stick to radios and checkboxes.
2010-09-04 - bsnes_v068r13.tar.bz2 Bug-fix night for the new PPUs. Accuracy: Fixed BG palette clamping, which fixes Taz-Mania. Added blocking for CGRAM writes during active display, to match the compatibility core. It really should override to the last fetched palette color, I'll probably try that out soon enough. Performance: Mosaic should match the other renderers. Unfortunately, as suspected, it murders speed. 290->275fps. It's now only 11fps faster, hardly worth it at all. But the old rendering code is really awful, so maybe it's for the best it gets refreshed. It's really tough to understand why this is such a performance hit, it's just a decrement+compare check four times per pixel. But yeah, it hits it really, really hard. Fixed a missing check in Mode4 offset-per-tile, fixes vertical alignment of a test image in the SNES Test Program.
2010-09-04 - bsnes_v068r12.tar.bz2 This took ten hours of mind boggling insanity to pull off. It upgrades the S-PPU dot-based renderer to fetch one tile, and then output all of its pixels before fetching again. It sounds easy enough, but it's insanely difficult. I ended up taking one small shortcut, in that rather than fetch at -7, I fetch at the first instance where a tile is needed to plot to x=0. So if you have {-3 to +4 } as a tile, it fetches at -3. That won't work so well on hardware, if two BGs fetch at the same X offset, they won't have time. I have had no luck staggering the reads at BG1=-7, BG3=-5, etc. While I can shift and fetch just fine, what happens is that when a new tile is fetched in, that gives a new palette, priority, etc; and this ends up happening between two tiles which results in the right-most edges of the screen ending up with the wrong colors and such. Offset-per-tile is cheap as always. Although looking at it, I'm not sure how BG3 could pre-fetch, especially with the way one or two OPT modes can fetch two tiles. There's no magic in Hoffset caching yet, so the SMW1 pixel issue is still there. Mode 7 got a bugfix, it was off-by-one horizontally from the mosaic code. After re-designing the BG mosaic, I ended up needing a separate mosaic for Mode7, and in the process I fixed that bug. The obvious change is that the Chrono Trigger Mode7->Mode2 transition doesn't cause the pendulum to jump anymore. Windows were simplified just a tad. The range testing is shared for all modes now. Ironically, it's a bit slower, but I'll take less code over more speed for the accuracy core. Speaking of speed, because there's so much less calculations per pixel for BGs, performance for the entire emulator has gone up by 30% in the accuracy core. Pretty neat overall, I can maintain 60fps in all but, yeah you can guess can't you?
2010-09-02 - bsnes_v068r10.tar.bz2 It is feature-complete, but horizontal mosaic is less accurate. I have an idea for a mosaic color ring buffer to get it equally accurate, but I haven't implemented it yet. For now it's just a simple x & ~(mosaic >> 1) trick that is passable. Hires blending was left out, as it's more processor intensive and blargg's NTSC does a better job with that anyway. There's some OPT vertical positioning issues in the SNES Test Program's character test; Goodbye, Anthrox has some sort of fast CPU DMA issue; etc. Total speedup is a mere 13.5%. Not quite the 50% I wanted in the best case, but I'll take what I can get. 254->289fps in Zelda 3 on my E8400 now. There's another 15% hiding with blargg's SMP and 5-10% with blargg's fast DSP, but they lose too much accuracy. It'd put me at or below Snes9X accuracy, while still being 50% slower. SSE2 was performing worse this time, both on x86 and amd64, so I left that optimization off. So, barring a miracle, this is about the best it's going to get.
2010-09-02 - bsnes_v068r07 Added hires and interlace support, fixed a color bug with CGRAM high-byte writes, added offset-per-tile mode, and added support for OAM color exemptions. What I did to avoid overhead was store different source layer IDs for OAM pixels with palettes 128-191 and 192-255. Sadly that's still 256 computations a scanline, but it's not horrible and is absolutely needed. Really the only major things left are mosaic and Mode 7. One minor thing would be direct color mode. I have some crazy ideas for light-adjusted CGRAM table caching, etc. so I'm hoping I can make up the speed penalty of implementing the above.
2010-09-01 - bsnes_v068r08.tar.bz2 Windows performance binary included, uses PGO and SSE2 optimizations. This gets the basic new PPU skeleton up and running, still missing a lot:
2010-09-01 - bsnes_v068r07 New PPU renderer is coming along. Lots of new ideas, especially with regards to the way the background renders in tiles rather than in pixels. That skips the need for tile caching and compares, and it even gets scrolling right. The sprite item+tile lists are computing, but they are not rendering yet. It's a good deal faster for now, obviously, because 90% of the PPU features are missing.
2010-08-30 - bsnes_v068r05.tar.bz2 Started over again on the new S-PPU, heh. Three hours wasted last night I guess. I wanted to make the new one more like the accurate core in its structure: multiple class instances for each background. It makes the code easier to read, results in less structure insanity (regs.main_enabled[bg] -> main_enabled), and will probably make it a tad easier to parallelize if we want to go that route eg for the ARM. Still very incomplete.
2010-08-30 - bsnes_v068r04.tar.bz2 This should provide hardware-accurate mosaic support in the accurate renderer, with the exception that I'm still not sure what mid-frame vertical mosaic or mid-scanline horizontal mosaic writes do. Either the code I have is correct, or it bypasses the mosaic adjust and gives the exact H/V positions. I've also renamed the fast folder to alternative (thinking about naming it simply alt instead), and started on a brand new PPU renderer. So far it's just a barebones setup with some MMIO support and VRAM/OAM/CGRAM writing. I'm not even confident that I can get this to be faster than the current scanline renderer, but it's the only avenue that we have left for any kind of significant bsnes speedup, so I have to try. I'm going to finish up the MMIO stuff first, that way we have a clean slate with no actual rendering. And then from here we can try various different approaches.
2010-08-28 - bsnes_v068r02.tar.bz2 test_mode7.tar.bz2 This adds mosaic improvements to the S-PPU dot renderer. Specifically, it eliminates the mosaic_table entirely, and performs mosaic adjustment per pixel instead. It also moves from a mosaic countdown for mosaic Y to a mosaic counter (incrementing). In the process, I realized Sim Earth's map was broken, so I fixed that. In doing so, I also fixed my old Mode7 demo that was always off-by-one, causing different results on real hardware versus emulation. But then I broke both Final Fantasy 5 and Air Strike Patrol effects that use Mode7 but no mosaic. I'm not really sure what's going on, but I think I am close. This is the first time I can reproduce the Mode7 test ROM results without screwing with M7Y which was obviously wrong. I think that somehow a mosaic >= 1 is glitching the Ycounter for the BG layers to tick one extra time. There's a workaround that's not very nice to get everything going right now. It could very well be that the workaround is hardware accurate, but I can't help but feel there's a more eloquent way of doing this.
2010-08-20 - bsnes_v068r01.tar.bz2 This adds RTS/CTS support to the serial communications emulation. Okay, well the PC acts as if it is always ready, because it always is even on the real thing, but the PC-waiting-for-SNES side works. Source only, hardware communication only works on OS X and Linux (Windows serial communication is totally different, I don't feel like writing a Windows version), more documentation will come later.
2010-08-21 - bsnes_v068 This release officially introduces the accuracy and performance cores, alongside the previously-existing compatibility core. The accuracy core allows the most accurate SNES emulation ever seen, with every last processor running at the lowest possible clock synchronization level. The performance core allows slower computers the chance to finally use bsnes. It is capable of attaining 60fps in standard games even on an entry-level Intel Atom processor, commonly found in netbooks. The accuracy core is absolutely not meant for casual gaming at all. It is meant solely for getting as close to 100% perfection as possible, no matter the cost to speed. It should only be used for testing, development or debugging. The compatibility core is identical to bsnes v067 and earlier, but is now roughly 10% faster. This is the default and recommended core for casual gaming. The performance core contains an entirely new S-CPU core, with range-tested IRQs; and uses blargg's heavily-optimized S-DSP core directly. Although there are very minor accuracy tradeoffs to increase speed, I am confident that the performance core is still more accurate and compatible than any other SNES emulator. The S-CPU, S-SMP, S-DSP, SuperFX and SA-1 processors are all clock-based, just as in the accuracy and compatibility cores; and as always, there are zero game-specific hacks. Its compatibility is still well above 99%, running even the most challenging games flawlessly. If you have held off from using bsnes in the past due to its system requirements, please give the performance core a try. I think you will be impressed. I'm also not finished: I believe performance can be increased even further. I would also strongly suggest Windows Vista and Windows 7 users to take advantage of the new XAudio2 driver by OV2. Not only does it give you a performance boost, it also lowers latency and provides better sound by way of skipping an API emulation layer. Changelog:
2010-08-20 - bsnes_v067r26.tar.bz2 Okay, I'm pretty much ready to release the next version, so heavy testing on this would be appreciated. To test the debugger (built with the compatibility core for moderate speed and PPU debugging support), rename the DLL to an EXE. bsnes_v067r26.tar.bz2 I think I'd rather play it safe though and go with v068. While the performance core is definitely major, I only have one shot at v1.0. It would at least be nice to have perfect mapping and the BGnxOFS caching for SMW1 in there first. Anyway, changelog: Re-added blargg's DSP, but this time I merged only spc_dsp and also fixed the initial regs for Dual Orb II. Which restores the 5-10% speedup on the compatibility and performance cores. Fixed the initial register values for the fast CPU core, which fixes Armored Police and the other Atlus game's title screen in the performance core. Added a missing debugvirtual prefix to op_step, which fixes CPU stepping in the performance core. I was using the description field for profile identification in savestates, but that was of course the description for the state manager. Whoops. Added a new field for profile name to the save states, and fixed the state manager to work with that change. Adjusted the about screen colors, which is how you can tell which core you're using without it being annoying. Probably did some other stuff too, meh.
2010-08-19 - bsnes_v067r25.tar.bz2 Removed snes_spc, and the fast/smp + fast/dsp wrappers around it. Cloned dsp to fast/dsp, and re-added the state machine, affects Compatibility and Performance cores. Added debugger support to fast/cpu, with full properties list and Qt debugger functionality. Rewrote all debugger property functions to return data directly:
2010-08-18 - bsnes_v067r24.tar.bz2 Windows binaries and source included Fixed bsnes launcher on Windows XP Fixed Windows bsnes launcher internationalization support (emulator can be in a folder with spaces and Japanese characters, and you can drag a Japanese file name onto the launcher, and it will load it properly) Moved fast CPU to use a switch table for MMIO, unfortunately for no speed gain Bus::read/write take uint24 parameters for address, luckily no speed penalty MMIOAccess gained a handle() function, and hid the mmio[] table. Makes hooking it cleaner Added malloc.h header to nall/function.hpp to fix a ridiculous GCC 4.5.0 error Fixed a fairly large bug in the fast CPU IRQ handler, which fixes Robocop et al Forgot to bump revision to .24 in the compiled binaries, too lazy to recompile or hex edit to change them Unfortunately, in order to add nice battery usage, I have to add the sleep calls to the video and audio wait loops. But they don't know anything about the GUI and its settings, nor do I really want to make them know about this setting. I do not want to force allow it. Even with the media timer trick, Sleep(0) makes Vsync+Async fail a lot more frequently than never sleeping at all. I would rather laptop users suffer 100% utilization of a single core than for all users to not be able to get good audio+video sync. Not sure what to do about that, so I'll probably just remove the battery usage comment from performance mode for now.
2010-08-16 - bsnes_v067r23.tar.bz2 Source only, previous link with Windows binaries is still valid for now. Added missing $4200 IRQ lock, which fixes Chou Aniki on the fast CPU core, so slower PCs can get their brotherly love on. Added range-based controller IOBit latching to the fast CPU core, which enables Super Scope and Justifier support. Uses the priority queue as well, so there is zero speed-hit. Given the way range-testing works, the trigger point may vary by 1-2 pixels when firing at the same spot. Not really a big deal when it avoids a massive speed penalty. Fixed PAL and interlace-mode HVIRQs at V=0,H<2 on the fast CPU core. Added the dot-renderer's sprite list update-on-OAM-write functionality to the scanline-based PPU renderer. Unfortunately it looks like all the speed gain was already taken from the global dirty flag I was using before, but this certainly won't hurt speed any, so whatever. Added #ifdef to stop CoInitialize(0) on non-Windows ports. Added #ifdefs to stop gradient fade on Windows port. Not going to fuck over the Linux port aesthetic because of Qt bug #47,326,927. If there's a way to tell what Qt theme is being used, I can leave it enabled for XP/Vista themes. Moved HDMA trigger from 1104 to 1112, and reduced channel overhead from 24 to 16, to better simulate one-cycle DMA->CPU sync. Code clarity: I've re-added my varint.hpp classes, and am actively using them in the accuracy cores. So far, I haven't done anything that would detriment speed, but it is certainly cool. The APU ports exposed by the CPU and SMP now take uint2 address arguments, the CPU WRAM address register is a uint17, and the IRQ H/VTIME values are uint10. This basically allows the source to clearly convey the data sizes, and eliminates the need to manually mask values when writing to registers or reading from memory. I'm going to be doing this everywhere, and it will have a speed impact eventually, because the automation means we can't skip masks when we know the data is already masked off. Source: archive contains the launcher code, so that I can look into why it's crashing on XP tomorrow. It doesn't look like Circuit USA's flags are going to work too well with this new CPU core. Still not sure what the hell Robocop vs The Terminator is doing, I'll read through the mega SNES thread for clues tomorrow. Speedy Gonzales is definitely broken, as modifying the MDR was breaking things with my current core. Probably because the new CPU core doesn't wait for a cycle edge to trigger. I was thinking that perhaps we could keep some form of cheat codes list to work as game-specific hacks for the performance core. Keeps the hacks out of the emulator, but could allow the remaining bugs to be worked around for people who have no choice but to use the performance core.
2010-08-16 - bsnes_v067r22.tar.bz2 Added OV2's XAudio2 driver (it's better and faster than the DirectSound one) Fixed DirectInput keypad number codes Added launcher to make the profiles work Profiles now called: Accuracy, Compatibility, Performance (not debating names anymore) The launcher isn't going to work on OS X because of the .app folder bullshit (yes, yes, .sfc folders.) It also crashes on Windows XP for god only knows what reason. Works fine on Windows 7 and Linux. So XP users, rename the .dll files to .exe to test this release. I'll fix it on Monday. The color highlighting fucks up the radio boxes on the Windows classic theme, because Nokia can't afford a god damn QA team. Lastly, I forgot to add launcher to the make archive-all command, so the source for it will be in the next WIP.
2010-08-14 - bsnes_v067r21.tar.bz2 This moves toward a profile-selection mode. Right now, it is incomplete. There are three binaries, one for each profile. The GUI selection doesn't actually do anything yet. There will be a launcher in a future release that loads each profile's respective binary. I reverted away from blargg's SMP library for the time being, in favor of my own. This will fix most of the csnes/bsnes-performance bugs. This causes a 10% speed hit on 64-bit platforms, and a 15% speed hit on 32-bit platforms. I hope to be able to regain that speed in the future, I may also experiment with creating my own fast-SMP core which drops bus hold delays and TEST register support (never used by anything, ever.) Save states now work in all three cores, but they are not cross-compatible. The profile name is stored in the description field of the save states, and it won't load a state if the profile name doesn't match. The debugger only works on the research target for now. Give it time and it will return for the other targets. Other than that, let's please resume testing on all three once again. See how far we get this time :) I can confirm the following games have issues on the performance profile:
2010-08-13 - bsnes-20100813.tar.bz2 Since we're now talking about three splits, that's getting a bit out of hand. This WIP combines everything back into one project again. Added the src/fast folder that has all the speed-oriented cores. A slight slowdown to csnes from what it was before, I'm using blargg's accurate DSP. I just don't like the idea of releasing a less accurate DSP core than Snes9X v1.52 has. Plus the fast DSP core doesn't serialize yet. I moved back to snes_spc 0.9.0 because I care more about Tales and Star Ocean than I do about Earthworm Jim 2. So if you try EWJ2 on csnes, expect it to sound like it does on Snes9X. In other words, don't wear headphones if you value your hearing. The middle-of-the-road bsnes core uses blargg's accurate DSP, because it's about 3% faster than mine which removes all of blargg's optimizations. There is absolutely no accuracy loss here. bsnes v067.20 that is included should be equal to v067 official. Performance: Code: asnes = 58fps bsnes = 172fps +2.97x csnes = 274fps +1.59x +4.72x The binaries are not profiled, so that's an additional 15% slower from the previous builds. Save states only work on asnes, as I don't know how to serialize blargg's cores yet. The copy_func thing is very confusing to me for some reason. The debugger won't work anywhere. Outside of that, please go ahead and bug test. Once I get the debugger and save states working, I'll build some profiled v1.0 releases for all three, and we can test that for a bit and then release.
2010-08-11 - snes-20100811.tar.bz2 12-15% faster than v067.10, and my Atom never goes below 58fps for normal lo-res games at this point. Just a little more and I can leave Async on. That's pretty much it though for the low hanging fruit. Everything else will be a lot of work for a little gain. Speedups are from range testing across scanline boundaries and from using blargg's fast DSP core. Snes9X is now only 1.93x faster than bsnes, and bsnes is now faster than Super Sleuth. I also fixed the Circuit USA menus (HDMA timing adjustment), Wild Guns flickering (IRQ lock) and Jumpin' Derby (external IRQ triggering.) There's definitely a lot of troublesome games, mostly the same ones we had in the past (Koushien 2, Robocop vs The Terminator, etc.) I'm definitely going to debug Starfox, but I may not bother with some of the more obscure ones. EDIT: Starfox 1.2 runs fine on this PC ... weird.
2010-08-10 - snes-20100810-2.tar.bz2 I wrote a new CPU core from scratch. It has range-based IRQs, and is good enough even to run F-1 Grand Prix and Sink or Swim. It also uses a binary min-heap array for the timing priority queue. This resulted in a ~40% speedup. I also added in blargg's snes_spc library, which is an S-SMP + S-DSP emulator. I am still using his accurate DSP core, and not the fast one. This gives an additional ~10% speedup. THIS IS NOT PERFECT, THERE WILL BE BUGS! I already know that Tales of Phantasia and Star Ocean are hitting some edge cases. Now that it's fast enough, hopefully blargg can take a look at it. Something he couldn't test before because you can't rip SPCs of these games, so it's probably something simple. My CPU core also doesn't nail every last possible edge case. So things like Wild Guns and the two or three games that rely on NMI/IRQ hold aren't going to work ... yet. Be patient. The SuperFX and SA-1 cores are still cycle-accurate. It wouldn't hurt compatibility to reduce their precision a bit. End result is that you can now get well over 60fps in normal games even on a first-generation Intel Atom. snes-20100810-2.tar.bz2 Windows profiled binary is in out/bsnes.exe.
2010-08-09 - snes-20100809.tar.bz2 Code cleanups, no binaries. I'll leave the previous WIP up so you can get Windows binaries for now. This adds some sync.sh improvements to make it handle errors more gracefully. It also updates asnes a good bit. All of the four base processors now have all publicly accessible functions right at the top of the main headers, and everything else is private. This is to allow these headers to essentially take the place of the previous base classes in the old bsnes-merged format. So if there's something public there, you need to implement that exact function to make your own module. I removed the frame counter from the PPU, as it has nothing to do with emulation. That now resides inside the Qt -> SNES interface code. Quite amazing, I was actually saving the frame counter into the save state files before, yuck. Removed some baggage in the System class: it was friending a bunch of long-dead functions and classes. Forgot to re-add the CHEAT_SYSTEM define to info.hpp, so that's been put back. Need to think of something to do about the documentation and about screen, kind of silly for asnes to display bsnes in certain areas. I'll also play around with tar --transform sometime tomorrow, no promises on whether or not I'll use it.
2010-08-08 - snes-20100808.tar.bz2 This fixes libsnes and debugger builds, and collapses bsnes/ppu/bppu to bsnes/ppu and bsnes/dsp/sdsp to bsnes/dsp. It also introduces bsnes/sync.sh, which will synchronize all of asnes/ with bsnes/, excepting the custom speed-focused modules. So far, that's bsnes/ppu (scanline renderer) and bsnes/dsp (state machine.) Should make keeping the two ports in sync much, much easier. It's basically the same thing as before, only you run sync.sh and have a few duplicated folders now. May make it clearer by creating a stub/ or src/ folder inside bsnes to do all of the copying, so that you only see the custom folders in bsnes/' root directory. There are binaries for asnes and bsnes in the above archive. I would appreciate testing, especially on the new bsnes.exe in this archive. I'd like to make the v1.0 releases, but I really, really need to wait and have that one tested. I do not want v1.0 to be a buggy, broken release.
2010-08-07 - snes-20100807.tar.bz2 This represents a major code restructuring. The dot-based and scanline-based renderers are now split into two separate core libraries, asnes and bsnes. For now at least, these are -internal- names. I'm not entirely decided on how I'm going to handle releasing these two separate builds. Regardless, the folders need names. asnes has had all of the processor subfolders collapsed back into their parent folders. In other words, ppu's functions were moved into ppu/sppu, and then ppu was deleted, and then ppu/sppu became the new ppu. Repeat this for the cpu, smp and dsp and there you go. asnes/dsp also removed the DSP_STATE_MACHINE option. This was done for the sake of consistency with the rest of the core. asnes' debugger mode is currently extremely broken, but I will be fixing it in time. And for now, bsnes has kept the processor abstraction layer. I may keep it around, not sure yet. It doesn't hurt speed or anything, so I'm not too worried about making a decision right away. I may throw snesfilter, snesreader and supergameboy into this folder, just to have everything in one place. The alternate GUI forks are definitely going in there as dotnet, cocoa and python. Compiled output goes to the out/ folder now, to prevent conflicts with a file and folder named bsnes, for instance.
2010-08-07 - v067r05 (Windows binary + source) This will be the final release with the current source structure. This WIP contains a bugfix so that the last scanline does not fetch OAM items. This fixes flickering in Ninja Warriors and Lord of the Rings.
2010-08-06 - v067r04 (Windows binary [sPPU] + source) This build simplifies the tile cache significantly, and it now builds the cache and fetches the VRAM data during Hblank, the VRAM reads are modeled after real hardware. This fixes Mega lo Mania without regressing Winter Gold or Adventures of Dr. Franken. I also fixed a pseudo-hires back color glitch in Super Buster Bros.
2010-08-05 - v067r03 (Windows binary [sPPU] + source) This substantially improves the S-PPU dot-renderer's sprite processing. Instead of happening immediately at the start of the scanline, each pixel is rendered one at a time. It eliminates the SpriteList caching, sprite width/height caching, oam_palette caching and oam_priority caching. I'll explain it in more detail in the public thread in a bit. Most noticeable is that Winter Olympics is now perfect, with no known regressions on any of the sprite-sensitive games.
2010-08-04 - v067r01 (source code) v067r01 (64-bit Windows binary, profiled with MinGW GCC 4.5.0) v067-dotnet v067-snowleopard This adds the SA-1 compiler bug workaround for GCC 4.5.0, and updates the load special libsnes functions to also generate XML mapping data if given empty strings. I built the binary above with GCC 4.5.0, so let me know if any new problems appear. What I've noticed is that when not profiled, 4.5.0 is about 3-5% faster, but when profiled, they are equivalent in speed. Lastly, I did some more work on the .NET/C# and Snow Leopard/Cocoa ports. They can both load all special types of ROMs, including Super Game Boy. For .NET, you need to be on a 64-bit version of Windows, have .NET 3.5 installed, and have SlimDX installed (I used February 2010, but anything later should be fine.) For Snow Leopard, you may want to build and install libsupergameboy, but you don't have to. Just don't try loading SGB games without it. Yes, the .NET one is pure 64-bit. I built snes.dll and supergameboy.dll using MinGW64-GCC 4.5.0. Since the core library doesn't use Qt, it builds fine in 64-bit mode.
2010-08-01 - v067 I apologize, bsnes v066 had a small error in the source that resulted in the PPU not synchronizing properly to the CPU. This bug was not exposed in the images I use to test releases. I have also updated the cheat code database, which is maintained by mightymo.
2010-07-31 - v066 Major features in this release are: serial controller emulation, a brand new scheduler that supports multiple simultaneous coprocessors, and accuracy improvements. The serial controller is something devised by blargg. With the proper voltage adjustments (5v-9v), it is possible to wire an SNES controller to a serial port, which can then be used for bidirectional communication between the SNES, and (usually, but not only) a PC. The support in bsnes was added so that such programs could be debugged and ran from within an emulator, and not just on real hardware. The scheduler rewrite was meant to allow the combination of coprocessors. It was specifically meant to allow the serial controller thread to run alongside the SuperFX and SA-1 coprocessor threads, but it also allows fun things like MSU1 support in SuperFX and SA-1 games, and even creating dev cartridges that utilize both the SuperFX and SA-1 at the same time. The one thing not yet allowed is running multiple instances of the exact same coprocessor at the same time, as this is due to design constraints favoring code inlining. There are two important accuracy updates. The first is that when PAL video mode is used without being in overscan mode, black bars are shown. Emulators have always shown this black bar at the bottom of the screen, but this is actually incorrect. resxto took pictures from his PAL TV that shows the image is in fact vertically centered in the screen. bsnes has been updated to reflect this. Also interesting is that I have backported some code from the dot-based PPU renderer. In the game Uniracers, it writes to OAM during Hblank, and expects the write to go to a specific address. In previous releases, that address was hard-coded to go to the required memory location. But the way the hardware really works is that the write goes to the extended attribute address for the last sprite that the PPU fetched, as the PPU is still asserting the OAM address bus. Now, due to the precision limitations, I was not able to also port timing access during the active display period. However, this is sufficient to at least remove the last global hack from the older, speed-focused scanline renderer.
2010-07-29 - v065r05 Fairly major changes here, I'd appreciate some testing if anyone's not busy. Note that the save state version has been bumped, so consider WIP saves unstable until v066 official. Rewrote the entire scheduling system. Instead of having a global class that all of the chips call into, each class now contains its own thread, clock and frequency information. They also implement their own syncing primitives, but with a tiny bit of standardization. void step(unsigned clocks) -- add to/subtract from counter based on master/slave select. void synchronize_chip() -- make sure chip is caught up to our current thread before continuing. So we go from scheduler.sync_copcpu() to sa1.synchronize_cpu(); with the sa1. being omitted inside the SA1 class itself. The S-CPU implementation also adds an array<Processor*> coprocessors; list, and iterates them all. This allows bsnes to have an infinite number of additional coprocessors at the same time. But there is still the limitation of only one of each type. So you can use the XML memory mapping to make a cartridge that contains a SuperFX2 chip, an SA-1 chip, an MSU1 chip and that can be debugged via serial communications. However, you can't make a cart that has two SA-1 chips. That limitation probably could be overcome as well, but it's less important. I mainly wanted to be able to use MSU1 and Serial on special chip games. I implemented the synchronization primitives in the chip base classes, which means that for inlining purposes I had to make it all global, so you'll have src/cpu/synchronization.hpp, etc now. This was to reduce some redundancy of having the same exact code inside both bPPU and sPPU, etc. I'll probably make a Coprocessor : Processor class to automatically implement the step+synchronize_cpu functions for the five coprocessors next. The Scheduler class is actually still around, but it's very trivial now. It simply saves the program thread and last active emulation thread for the purpose of entering and exiting emulation. Because I killed Scheduler::init(), which was responsible for destroying and re-creating threads, I had to create the threads inside ChipName::create(), which I call at power and reset. This means that to load a save state, the system needs to be reset to destroy those threads. This caused some troubles with the SA-1, specifically in Kirby's Dreamland 3, but no other games I tried. I had to move the SA-1 bus initialization to the power-on event, and only reset when loading a save state. It would appear that the SA-1 is leaking bus mapping state information, presumably from the SA-1 MMIO registers that control some of the mapping layout. If I add remapping of those sections into the SA1::serialize() function, it should take care of that problem and I can move sa1bus.init() back into SA1::reset(). All of this results in a 2-3% speed hit for normal games, and a 6-7% speed hit for special chip games. The former should not have any speed hit, so I will have to look into what's going on there. The latter we have no choice on, to allow for more than one coprocessor, the coprocessor synchronization needs to iterate a list, compared to a single hard-coded check in the previous builds. If I can figure out what is happening with the regular game speeds, it should drop the special chip hit to 4%. Worst part is this hit is in addition to the 10-15% speed hit from v065 official where I wasn't syncing the special chips up to the CPU except once per scanline and on MMIO accesses. But that's progress. v065 is definitely going to be the preferred build for playing SuperFX/SA-1 games for a long time to come.
2010-07-16 - v065r04 Only posting because the link changed, it's the exact same as r03. Only difference is some improvements to nall:
file::print now accepts variadic arguments like print Examples: Code: strtr(item, "ABCDEF", "abcdef"); -> item.transform("ABCDEF", "abcdef"); strlower(item); -> item.lower(); fp.print(string("Age: ", age, "\n")); -> fp.print("Age: ", age, "\n");
2010-07-12 - v065r03 Polishing work. My dlopen wrapper accepts an optional path argument now, and the basename setting is universal instead of just for MSU1, so serial-based games can load in a dynamic client library directly. Still need to update snesserver to accept another argument for the program library name to load. Upped the serial polling frequency to 8x UART speed per blargg. And a very tricky change, I updated nall/string to remove sprint(). At first, I used: Code: string name = string() << path << basename << ".msu"; I then improved upon that with: Code: string name = sprint(path, basename, ".msu"); Tonight I went ahead and finished this by taking advantage of variadic templates for the constructor itself. Very tricky because my conversion functions created new strings to copy data into, which would create an infinite loop; then of course I also had to leave the copy constructor behind even after this. So the end result is the following: Code: string name(path, basename, ".msu"); Oh, and I found a typo in MSU1, it wasn't using the proper extension when loading a save state for the data file.
2010-07-11 - v065r02 Be warned, this is going to get complicated. To start out with, serial.tar.bz2 is a simple SNES program that is right now being used for integrity testing. The important part is here: Code: serial_read: lda #$01 -; bit $4017; bne - -; bit $4017; beq - nop #24 pha; lda $4017; eor #$01; ror; pla; ror; nop #18 pha; lda $4017; eor #$01; ror; pla; ror; nop #18 pha; lda $4017; eor #$01; ror; pla; ror; nop #18 pha; lda $4017; eor #$01; ror; pla; ror; nop #18 pha; lda $4017; eor #$01; ror; pla; ror; nop #18 pha; lda $4017; eor #$01; ror; pla; ror; nop #18 pha; lda $4017; eor #$01; ror; pla; ror; nop #18 pha; lda $4017; eor #$01; ror; pla; ror; rts
serial_write: pha #6; pla #6; wdm #$00; stz $4016; sec pha #6; pla #6; wdm #$00; sta $4016; ror pha #6; pla #6; wdm #$00; sta $4016; ror pha #6; pla #6; wdm #$00; sta $4016; ror pha #6; pla #6; wdm #$00; sta $4016; ror pha #6; pla #6; wdm #$00; sta $4016; ror pha #6; pla #6; wdm #$00; sta $4016; ror pha #6; pla #6; wdm #$00; sta $4016; ror pha #6; pla #6; wdm #$00; sta $4016; ror pha #6; pla #6; wdm #$00; sta $4016; rts Fairly ugly, but it works. Next, I needed a way to be able to execute the client in such a way that it would work with both bsnes and real hardware, with no recompilation or changes needed. The nice way would be some form of inter-process communication, but well, I don't really do that. And it's probably extremely platform-dependent. So I used what was available to me already, a cross-platform dlopen wrapper for dynamic library support. The client application is written and compiled into a shared library that exports a single function, snesserial_main, which runs as if it is its own program and never returns. It takes three parameters, the time tick(), read() and write() function pointers. It can call them to do its work. This process is put in a folder called snesserial for now. It's the accompanying program to serial.sfc. Now I have both bsnes (v065.02 above) and snesserver, they both act the same way. They load in snesserial, and give it those three functions and call its main entry point. The difference is that the read/write functions in bsnes simulate a serial strobe to the emulator, and the read/write functions in snesserver actually read and write to the TTY device you specify as the program argument, eg for me I use: ./snesserver /dev/ttyUSB0 Mmm, USB<>SNES for the win. There's a limitation in my dlopen wrapper, it adds the libN.so or N.dll stuff automatically, making it difficult to also specify a path. That means that for now you have to put libsnesserial.so into /usr/local/lib. Obviously you don't want to be limited to just one program. The plan is to have it load the library that matches the game name: zelda.sfc + zelda.so/zelda.dll/zelda.dylib (yeah, no libzelda.so.) Now, the bsnes+serial emulation works on any platform. However, snesserver only works on Linux. You can blame that one on Microsoft. They make you require special kernel drivers to be able to access the serial port. I'm not going through the trouble. OS X can probably use it if it makes the appropriate /dev/tty device, but I'm not going to test it. Activating the module can only be done with a custom XML file, as before. Still need to work on integration with the controller port options, as it's not really a special chip. Lastly, the timing is "pretty good", but not perfect. It accepted a 374 cycle-per-bit loop for serial writes from the SNES to the PC, but snesserver did not. I had to adjust to 364 cycle-per-bit loop for it to work on both. This is really bad, because the goal here is to use the PC as the testbed to make sure it'll work on the real thing. On the plus side, you only have to get it working one time, and stick with the serial_read/serial_write functions like at the top of this post. But I do need to address this. I'm not entirely sure how to more accurately simulate a serial port at this point though. Oh, and I am thinking I need to expand the read/write functions to process more than one byte at a time. That should greatly speed up transfer time on the real thing. I also need to add some slowdown so the emulator more closely matches hardware speeds.
2010-07-09 - v065r01 In order to fully decode the 16MB address maps, I am going to need to use blargg's stop-and-swap, which will require a serial-communications program. To develop this program, and others in the future, as well as for testing automation, it would be very beneficial to have a way to debug these programs through bsnes. So what I'm working on now is emulating a serial port inside bsnes. The basic premise is to start with a custom XML map that specifies its presence: Code: <?xml version="1.0" encoding="UTF-8"?>
I am essentially treating the serial communication as a special chip. One could argue this belongs as an option under controllers, and one would be right. But as I can't have two coprocessor threads at the same time, this is how it is for right now. Eventually it'll probably be under controller port 2, and only enabled in the debugger builds. So, this pseudo-coprocessor ... it's basically emulating the PC-side communications program. Meaning I still need to externalize this somehow so that any program can be run. The below program writes 0x96 six times, and then reads in data six times. Well, technically forever, but the SNES ROM only writes six times at the end. Code: void Serial::enter() { scheduler.clock.cop_freq = cartridge.serial_baud_rate() * 2;
latch = 0; add_clocks(512);
for(unsigned i = 0; i < 6; i++) { latch = 1; add_clocks(2);
}
while(true) { while(cpu.joylatch() == 0) add_clocks(1); while(cpu.joylatch() == 1) add_clocks(1); add_clocks(1);
} } The SNES code looks like this: Code: //21,477,272hz cpu / 57,600hz serial = ~372.87 clocks/tick
org $8000 xce; rep #$10 ldx #$01ff; txs
jsr serial_read; sta $700000 jsr serial_read; sta $700001 jsr serial_read; sta $700002 jsr serial_read; sta $700003 jsr serial_read; sta $700004 jsr serial_read; sta $700005
nop #46
jsr serial_write jsr serial_write jsr serial_write jsr serial_write jsr serial_write jsr serial_write
//hang -; bra -
serial_read: -; lda $4017; and #$01; bne - -; lda $4017; and #$01; beq - nop #23; lda $00; nop #10
lda $4017; and #$01; asl $00; ora $00; sta $00; lda $00; nop #13 lda $4017; and #$01; asl $00; ora $00; sta $00; lda $00; nop #13 lda $4017; and #$01; asl $00; ora $00; sta $00; lda $00; nop #13 lda $4017; and #$01; asl $00; ora $00; sta $00; lda $00; nop #13 lda $4017; and #$01; asl $00; ora $00; sta $00; lda $00; nop #13 lda $4017; and #$01; asl $00; ora $00; sta $00; lda $00; nop #13 lda $4017; and #$01; asl $00; ora $00; sta $00; lda $00; nop #13 lda $4017; and #$01; asl $00; ora $00; sta $00; lda $00; nop #13
rts
serial_write: lda #$01; sta $4016; nop #23
lda #$00; sta $4016; nop #23
lda #$01; sta $4016; nop #23 lda #$00; sta $4016; nop #23 lda #$00; sta $4016; nop #23 lda #$01; sta $4016; nop #23 lda #$00; sta $4016; nop #23 lda #$01; sta $4016; nop #23 lda #$01; sta $4016; nop #23 lda #$00; sta $4016; nop #23
lda #$01; sta $4016; nop #23
rts That reads six times, and then writes six times. I haven't made the test do an infinite PC->SNES transfer, but I have for SNES->PC. No errors after millions of bytes, even if I stride the CPU timing. As this is just an example, it's pretty lousy with actual timing, but I guess that's a good thing as it still works quite well. More tolerance = less potential for errors. Now, this part is important. While debugging this, I noticed that my serial coprocessor was only running when Vcounter=n,Hcounter=0. In other words, nothing was making the CPU synchronize back to the coprocessor, except the once-per-scanline synchronization that was there in case of CPU stalls. That's ... really bad. MSU1 worked only because it buffers a few hundred samples for audio mixing. I don't really know why this didn't cause an issue for SuperFX, SA-1 or Super Game Boy games; but in theory they were at most 682x less precise than they should have been in terms of CPU->coprocessor synchronization. Making it sync after every add_clocks() call results in a 10% speed hit to SuperFX, SA-1 and Super Game Boy emulation, unfortunately. I don't notice any quality improvements in emulation, but in theory the lack of this syncing before effectively eliminated the benefits of the SuperFX and SA-1 being cycle based. I'm going to have to look into this more to understand if I was intentionally not doing this sync before, or if I really did forget it. I'm thinking it was an oversight right now. The SuperFX and SA-1 don't really talk back and forth a whole hell of a lot, so once a scanline probably wouldn't be that noticeable. But holy hell ... now that I'm thinking about it, I wonder if this was the cause of all that craziness in trying to sync up the Super Game Boy's VRAM transfers. Yeah, definitely need to look into this more ...
2010-06-26 - v065 It's been a while, so here is a new release of bsnes. Unfortunately I don't have a full changelog this time. Most of the work went into stabilizing libsnes (which is used by the experimental .NET, Cocoa and Python UIs; as well as by Richard Bannister's OS X port). The Windows binary package now comes with all three variants included: bsnes.exe, the standard version that casual users should run; bsnes-debugger.exe, for SNES programmers and ROM hackers only; and bsnes-accurate.exe, which should not be used by anybody, ever. In all seriousness, bsnes-accurate.exe is bsnes with the dot-based S-PPU renderer. It's twice as slow as the normal build, and you won't really notice any differences except in Air Strike Patrol. It's there for the curious and for any SNES programmers who want to try making some really awesome video demos. Changelog:
2010-04-25 - v064r05
2010-04-20 - v064r04 Fixes S-CPU debugger breakpoint issue. libsnes always returns 0 for "no memory present" now, never -1U. bsnes-python-20100420 Won't error if there's no joypad present. Swaps menu and status bars with a toolbar. Adds keyboard support - you can use both a keyboard and joypad for input now. Won't crash if RAM doesn't exist yet. Won't crash if game uses no RAM.
2010-04-19 - v064r03 bsnes-python-20100419 Some changes to libsnes. Really hoping the API will be stable from this point out ...
2010-04-18 - v064r02 Nothing interesting, just added bsnes-qt.py to ui_python. No input handling, but OpenGL-based video resizing and libao audio. Doesn't use numpy, found a workaround for that. It's obvious that we need video/audio/input handled by an external library for this to work, so I'm thinking now about a rewrite of ruby to a C-like interface.
2010-04-16 - v064r01 Adds bool snes_get_region(void) to libsnes (permanent). Adds snes_blit_colortable and snes_blit to libsnes (temporary). Adds src/ui_python with a basic Python GUI, and abstraction between the libsnes wrapper and PyGTK (so it can be reused for PyQt, etc.) The GUI has:
2010-04-14 - v064 A thank you to everyone who helped test the RC to ensure stability. I've uploaded the official v064 release to Google Code. The most important change in this release is the cycle-based PPU renderer; but due to performance reasons the scanline-based renderer remains the default in the Windows binary. If you want to try out the cycle-based renderer, you will need to compile from source for now. Another major change is the introduction of libsnes, which allows one to build bsnes as a shared library that can be used from other programming languages. It is intended both to create a regression testing framework, and to provide API stability for the various projects that use the bsnes core. While I can't guarantee the API to libsnes won't change, I will properly revision it and do everything I can to avoid changing it if possible.
2010-04-13 - v063r14
2010-04-14 - v064rc1 I'm posting a release candidate for v064, for which I am looking for beta testers. If you would like to help out, please give it a try and report any bugs or regressions on the forum. If all goes well, this will be posted as v064 official shortly. Note that you will need the Qt run-times from bsnes v063 official to use this. Also, this build does not use the new cycle-based PPU. Official builds are going to continue using the scanline-based renderer. This build should be about 10% faster than v063 was, which should lower the system requirements further.
2010-04-11 - v063r12 Well I really don't want to think about a caching system right now, so I skipped that.
2010-04-09 - v063r11 Writing to SETINI will update video mode priorities for EXTBG mode. Merged pixel output { main, sub { valid, priority } } into just priority. A priority of zero is considered invalid now. Merged pixel output { main, sub { palette_index, palette_number } } into just palette with the tiledata bits for direct color mode at d8-d10. This cuts a lot of copying and extra comparisons out of the final screen rendering pass, though it doesn't really help speed. Output is always 512x448 now. Having trouble deciding on how to do video for that, but I'll post more on that later. Really need to figure out how offset-per-tile fetches in regards to lores v hires and SC size, tile size and wrapping. For now, I simplified it to constants; whereas the scanline-renderer uses the BG3 settings. I also made it not perform OPT lookup on BG3 and BG4 anymore. Skips a pointless trickery of setting the OPT valid bit to zero for BG3,BG4 and is faster. Forgot an overscan check in sprite drawing, should draw sprites properly to V=225-239 now. Made the mode7 variable names more consistent.
2010-04-05 - v063r10 With this release, the final last-generation holdout, the scanline-based PPU renderer, has been replaced with a true, accurate, cycle-level PPU that renders one dot at a time. Finally, this fulfills the greatest milestone remaining in the SNES emulation scene. With every processor emulated at the lowest possible level, SNES emulation finally rivals the accuracy levels that NES emulators have offered for years. Now, please do understand that this release is not a beta, nor is it even an alpha. It is simply a preview of things to come, and as such you can consider it a pre-alpha. There are many caveats at this time. First, it is very slow. More than twice as slow as v063 official. There have been absolutely no optimizations whatsoever to the new dot-based renderer. I do expect to be able to speed this up significantly in future releases. Second, this may lock up on Windows Vista and later for unknown reasons. I haven't had a chance to look into it; so stick with Windows XP or Linux for now. Third, save states are not supported yet. If you try and use them anyway, bad things will happen. Fourth, and most importantly, this isn't 100% bit-perfect by any stretch of the imagination. Off the top of my head, memory is accessed far too often, the OAM and CGRAM address lines are not controlled by the S-PPU during active display, none of the various glitches are supported, and the OAM renderer does not pre-cache the next scanline's sprites, it happens on the same line for now. I will obviously be doing my best to improve the accuracy of the aforementioned things. But even with those missing, this is still leaps and bounds above a pure scanline-based renderer. It essentially provides 682 times the parallelism. It is enough to finally properly emulate the shadow effect in Air Strike Patrol, and it finally eliminates the "PPU Hclock render position" hack once and for all. Lastly, you'll need the DLLs from v063 official. I didn't bother to include them this time. Enjoy!
2010-04-05 - v063r09 Windows binary w/sPPU enabled included So that's about 24 solid hours worth of programming in two days. Holy fuck am I exhausted. Don't expect the last bits any time soon. Missing features:
2010-04-05 - v063r08 No binary, this is just a point release. I have basic lores BG1-4 rendering with mosaic added. No offset-per-tile, no windowing, no color math (requires windowing), no sprites, no hires, no interlace, no mode7. It's enough to see how powerful the concept is already, though.
2010-04-04 - v063r07 src/lib is no more, merged libco, nall and ruby into src/. libsnes has been improved, builds in when you "make library" now. XML memory map generation happens from a nall template header, so both libsnes (used by ui_sdl) and ui_qt can run again without snesreader. ui_sdl improved, can run any game via command-line, but doesn't load or save RAM yet. And most importantly, much work has gone into sPPU, the new cycle-based PPU renderer. It has enough support to be compatible with all games ($2134-213f are mostly complete, just missing range/time over flags and VRAM/OAM/CGRAM blocking.) It only renders the back color, as if you had all BG and OAM layers disabled. At this point, if you run Air Strike Patrol, thanks to its gradient fade highlighting, you can see the plane's shadow, just as on real hardware now. It also runs test_hello and test_noise, which I will upload shortly.
2010-04-02 - v063r03 Extremely substantial code structure changes this time. Probably the most in four years. All of the SNES core now resides in src/snes, and the contents of system have been unrolled into this directory as well. This folder gets its own Makefile now, and some special build commands, "make library" and "make install-library". This creates static and dynamic link libraries of the core, completely devoid of Qt, ruby, the GUI, etc. There's a new module as well, src/snes/libsnes. This is a C interface that will let you initialize and control the bsnes core without the need for anything more than a 1KB header file. To test this, I've created a UI fork, ui_sdl. Very very simple, 2KB, nothing there at all really, it just boots up Zelda 3 and runs it directly with keyboard input support and video only. The important point here is that the ui_sdl project does not reference the core, or ruby, or Qt, or anything else, and is fully C++98 (though it could also be C89 if desired.) Now I'm being a bit lazy and using the compiled objects directly, but it'd be just as easy to replace them with a library include directive, or even dynamically link against the shared library and use an entirely different language. It's not actually my goal to make a C++ SDL port, what I really want to do is make a port using Ruby only. May not be so easy, we'll have to see how one accesses shared libraries in it. The main src/Makefile was also simplified for the sake of supporting non-Qt code. All of the Qt and ruby references were moved into the src/ui_qt/Makefile. I fixed up aDSP to compile again, but you still have to manually comment out sDSP and comment in aDSP. Doing so will net you a 6-12% speedup at the cost of some accuracy. Lastly, I added a workaround for the Battletech 3050 splash screen.
2010-03-31 - v063r02 It would be a really good idea to test all of the HDMA-sensitive games with this WIP, if anyone's up for it. Rewrote most of sCPU::DMA. It now implements a parallel two-stage pipeline to more closely model the hardware. Even if it turns out to be wrong, simply making dma_write() immediate would revert it to the old behavior. Fixed a bug where HDMA init and run were always syncing to the DMA counter, even when a DMA was already in progress. Will speed up the S-CPU in a very, very small number of games, namely College Football '97. Most games avoid this because it can crash CPUr1. New DMA variables means new save state version, sorry. I did not add the MDR override code, because it's too fucking insane. Speedy Gonzales still works. Removed the status bar size grip entirely. There's really no point in it being there in windowed mode since you can already grip the sides of the window anyway. Added space to each side of the status text so that it doesn't nail the very edge of the monitor. Added checks in XML mapping to not map in special chip sections when you try and load BIOSes directly, which will stop the SGB and BS-X BIOSes from crashing the emulator. Load it the right way and it'll work fine, as always. Fixed the loader window to display screenshots properly when you have HTML entities in the filename, eg &, < and >.
2010-03-29 - v063r01 I've had enough of idiots incapable of finding fullscreen settings. The menubar is enabled in fullscreen mode by default. A new option in settings->configuration->video will let you hide it as with v063 official. I don't want to hear about how I shouldn't allow any settings to be configured differently in fullscreen mode, or how it should be in a GUI panel, or whatever. I will ignore you if you bring it up. I've also added the strpos / qstrpos function->class code, as mentioned in the programming section.
2010-03-28 - v063 Time for another (hopefully) stable release. The changelog has all updates since the last stable release. Most notably, this release features substantial accuracy improvements all around. Almost all of them represent brand new findings never before seen in any SNES emulator. Changelog:
2010-03-24 - v062.10 Added make uninstall, and fixed up nall::function to also bind lambdas that don't yet exist in GCC 4.4.
2010-03-23 - v062.09 Mostly minor stuff again. Fixes: array, linear_vector and pointer_vector need to set source.pool = 0 before calling reset() to avoid destroying the object we're trying to move. All of nall::string is inside namespace nall now. No idea what I was trying to do before with the half-global approach. nall::function gains a reset() function, more obvious than func = (void*)0; The movie file loader wasn't binding the right action when changing files and clicking load, can't believe nobody noticed that one.
2010-03-20 - v062.08 This WIP has bsnes.exe, snesreader.dll, and src/. If you need anything else, get it from past releases, please. I fixed TSC negative flag calculation in emulation mode. Will pass this test now: snes_test_tsc.zip Way too obscure to affect anything, but definitely good to get it right. Also rewrote nall/function.hpp to use C++0x variadic templates. New version is ~85 lines instead of ~190, 40% smaller, doesn't require recursively including itself, doesn't require the C preprocessor, evaluates to ensure the member function pointer is big enough to hold what you're assigning statically (at compile time) instead of dynamically (at run time), and supports infinite arguments instead of zero to eight now.
2010-03-19 - v062.07 This is source code only, no binaries. Sorry, worn out after spending four hours straight writing crazy ass Julian<>Gregorian date functions. Holy fucking hell that is crazy shit. Tell me, how many days have passed since 01-01-4731 BC on the Julian calendar? Okay, this really was just about taking advantage of vectors inside of vectors. I've updated the XML parser to use vectors of actual objects instead of pointers. This makes cleanup free, and turns countless ->'s into .'s -- much nicer to look at. I may take advantage of overloaded operators for something now, not sure yet.
2010-03-18 - v062.06 You'll need snesreader's DLL from my last WIP post to use the above. This initializes mode, region and ram_size again in Cartridge::load() to stop the phantom SRAM files from being generated. This fixes DSP-2 mapping to match Overload's findings (which requires an unposted snesreader, so Dungeon Master won't run for you guys yet.) This removes nall/traits.hpp and uses std::tr1::type_traits instead. It also drops move, forward and identity in favor of those from std::tr1::utility*. This fixes linear_vector and pointer_vector to not crash when using vectors of vectors and copying them. This fixed linear_vector, pointer_vector and array to initialize all internal variables for all constructors. This fixes the file browser to look for patches in your patch directory, so the "Apply Patch" box should work correctly now.
I have no objection to using functions from the C++ standard library when they don't suck.
2010-03-17 - v062.05 snesreader_2010-03-16 To run this, you'll need the DLLs from v062r04's public beta, and the updated snesreader.dll from the above in the same folder as the WIP. No profiling. This fixes UPS patching, and it also modifies snesreader to generate the XML map separately, so that the map can be generated post-patching. The new enum classes weren't attaching properly to the config file, so the input settings, expansion port and region settings are saved again. It also converts the S-SMP timers back to unsigned integers instead of using floating point, no accuracy improvement but much more in line with hardware. Lastly, it makes the div register shift left 16 places and pre-shifts on divide, which is just for aesthetics. And I'll wait on your tests, FitzRoy. I really hope that Big Run Jaleco Rally is correct, because I don't have the first idea how to debug that one. Speedy I can probably handle.
2010-03-15 - v062.04 I suppose I should start calling these nightlies, heh. blargg went ahead and verified every last possible edge case with regards to the S-CPU MUL / DIV registers. It uncovered a few errors in my implementation, which have since been corrected. The design used now should be a direct reflection of the hardware implementation: no actual multiplication, no actual division, and no variable-length bit-shifting. We also spent about eight hours straight hammering away at the S-SMP test register. We have a partial understanding of TEST.d3 and TEST.d0, and a complete understanding of the other six bits. All of this has been implemented as well. Lastly, snesreader gets a tiny update to fix Test Drive II, which broke due to a slight regression when porting the mapping code to XML.
2010-03-15 - v062.03 blargg and I sat around for a good 8+ hours today hacking away at the S-SMP Pandora's Box: the TEST register. What better way to spend Pi Day, right? We came up with the following tests: http://byuusan.kuro-hitsuji.net/blargg_2010-03-14.zip First, controller_strobebehavior.smc improves emulation of $4016. When the joypad strobe latch = 1, reading $4016 returns the current value of the B button. As in, you can keep reading it over and over. It won't increment the shift register, and it will keep telling you the actual current state of the button. This is very much like the NES behavior. One more TODO in the S-CPU code taken care of. Next, all kinds of S-SMP TEST register improvements. Turns out d7-d6 alone controls the actual S-SMP clock rate. 0 = 100%, 1 = 50%, 2 = 0% (locks the S-SMP forever), 3 = 10%. Wild stuff, you can actually permanently slow the S-SMP relative to the S-CPU. d6-d5 is a timer tick control, but it actually uses d7-d4 overlaid. The algorithm is fucking nuts, and is really my only contribution to today's work. The rest was all blargg's research. We had d2 wrong, it's not MMIO disable, it's RAM disable. As in, disable read and write. Returns 0x5a on regular SNES, 0xff on mini-SNES. 0x5a is not the S-SMP MDR. IPLROM is still readable when RAM is disabled. d1 was correct, just RAM write disable. Can still write to $f8 and $f9, of course. But it won't go through to RAM. d3 and d0, we are still a little unsure on. The T0-T2 timers seem to have a low and high phase, and if you strobe them you can force ticks of stage 2 to happen, and you can disable them in such a manner than stage 2 never ticks at all. blargg is still uncovering all sorts of crazy things in $xB mode, so emulation of these two bits is not perfect. But overall we are leaps and bounds further now toward complete emulation. I'd say we went from 10% to 80% with today's work. But we'll have to see how deep the rabbit hole goes on d3+d0 first. Current register map: Code: case 0xf0: { //TEST if(regs.p.p) break; //writes only valid when P flag is clear
Fairly confident that no emulator prior to this WIP could pass any of blargg's tests, so this is all brand new information. Fun stuff :)
2010-03-14 - v062 Major accuracy improvements have happened over the past few days. They easily warrant a new beta release. First, it turns out that every emulator to date; not only for the SNES, but for the Apple II GS as well, incorrectly computed ADC (add) and SBC (subtract) flags in BCD (binary-coded decimal) mode. At least fifteen years of emulating the 65816 processor, at least five known investigations into their behavior, and we all still had it wrong. So I wrote some tests that dumped every possible combination of adc and sbc with every possible input and every possible flag, and recorded both the accumulator result and status flag register. From here, blargg figured out the underlying trick: the CPU was computing overflow before the top-nibble's BCD correction pass. With the routines rewritten, bsnes perfectly matches real hardware now. Next, some background. The whole reason I got into SNES emulation was because I was tired of writing code that ran perfectly fine on emulators, but failed miserably on real hardware. The number one problem was emulators allowing video RAM to be written while the screen was being rendered. This single bug has broken dozens of fan translations and ROM hacks. Some have been updated to work around this bug, and many others are left in a permanently broken state (such as the translations of Dragon Quest I & II and Sailor Moon: Another Story, to name just two.) After asking emulator authors to fix this since 1997, I finally had enough in 2004 and started on bsnes. For this particular bug, I'm very happy to report that all but one SNES emulator now properly blocks these invalid accesses. Although sadly one still offers a configuration setting for backwards compatibility with these translations. What an ironic shame ... emulating an emulator. And in the process, sapping the motivation to ever go back and fix these titles to ever run on real hardware. But I digress ... The second biggest problem that causes software created under emulation to break on real hardware has, without a doubt, been the hardware delays as the S-CPU computes MUL (multiplication) and DIV (division) results. To date, whenever you used this hardware functionality, emulators have immmediately furnished the correct results. But on real hardware, multiplication requires eight CPU cycles, and division requires sixteen. Each step computes one bit of the source operand and updates the results. Reading the output registers early thus provides the partially computed results. This is obscure. It isn't well known, and many people writing software for the SNES probably aren't even aware of this limitation. Because of the partial computation results, outright delaying the computation would break many commercial software titles. But by not emulating the delay at all, we were causing a great disservice to anyone wishing to use an emulator for development purposes. Now, once again, thanks to blargg's algorithm help, he has determined the underlying multiplication and division algorithms. Combined with my expertise of SNES analysis and hardware testing, I was able to determine when and how the ALU (arithmetic logic unit) stepped through each work cycle. Our work combined, bsnes now also perfectly emulates the hardware MUL and DIV delays. Again, this isn't going to fix commercial software titles. They would have realized that they were reading back invalid MUL and DIV values, and fixed their code. This is for all of the software developed using emulators. This is an extension of my commitment to create a hardware emulator, and not a video game emulator. We also verified that the S-PPU multiplication interface does indeed return instant results with no delay. So emulation of that interface was already correct. I'm only labelling this release a beta because it hasn't been tested. But I'm fairly confident that it is stable, and I seriously recommend upgrading from v060 or prior releases. This is easily one of the last major pieces missing from emulation. The last notable elements are: S-CPU auto joypad poll timing, S-CPUr1 HDMA crash detection, S-CPU<>S-SMP port ORing, S-SMP timer glitching, S-DSP mute pulse, and full cycle-level emulation of the S-PPU. With all of the aforementioned items, I will consider a v1.0 release of bsnes ;) Lastly, I'll post this screenshot just for fun. When d4s translated Breath of Fire II to German, he added some code that relies on the incorrect emulation of the DIV register to detect emulators. With this emulated properly, you now see the following screen: ./sshots/bs_349.png Sorry to spoil that, but the secret's already out, as the MESS team reported on it publicly already. I intend to add pseudo-randomness support shortly, which should eliminate one of the last vectors possible to distinguish bsnes from real hardware :) A million thanks to blargg for making this release possible.
2010-03-08 - v061.01 Found the cause of the issue breaking SuperFX games after loading SA-1 games. Seems the XML mapping tree wasn't being cleared. It's also not a good idea to use bsnes/ as the folder name when the Makefile generates a binary by the same name in the same directory, so back to src/ for the main emulator it is. With those fixes, this release should be fully stable; but again my intentions are to keep v060 as the stable release for a while. Nonetheless, you can grab the new beta at Google Code. It should be the last update for at least a few weeks.
2010-03-07 - v061 Please keep in mind that bsnes v060 remains the current stable release. v061 has been released as a work-in-progress build. As such, it is only available at Google Code. I am releasing this WIP to allow the public to test out and comment on the new XML mapping system, as well as the integration of mightymo's cheat code database into the cheat editor. I would greatly appreciate feedback on these two on the forums. There are some important issues with this release. The biggest is the move to C++0x. This requires GCC 4.4.0 or newer to compile, thus it is not currently possible to build this on OS X using Xcode. Nor would it be possible on certain BSDs or older distros. If you have an older compiler, please stick with v060, or use a binary release where available. Another issue is that TDM/GCC 4.4.1 for Windows crashes with an internal compiler error when attempting to generate a profile for the DSP-1 module. This is a bug in the compiler, and not in the code itself. The workaround is to simply omit profile-guided optimization for this one object. Lastly, there's also a known bug in the memory mapping. If you load an SA-1 game, SuperFX games will not load properly afterward unless you restart the emulator. I'm looking into the cause now, but it didn't seem serious enough to hold up a WIP release. So, yes. If you want a good gaming experience that's been fully tested and stable, please stick with v060. If you want to see some bleeding edge features, I'd appreciate feedback on v061. Thanks for reading this. Changelog:
2010-02-08 - v060 This is a long-term stable release. A full changelog will be available at the forum link below later in the day. Also, please note that I have merged all of the various distributions into two packages. The Windows binary package now contains both the profile-optimized (fast) build, and the debugger build. The source code package now contains sources for bsnes, snesreader, snesfilter and supergameboy. Changelog:
2010-01-24 - v0.059.06 This is an experimental release, as such it is posted only to Google Code. Changelog:
2010-01-11 - v0.059.02 Changelog:
2010-01-06 - v0.059 This is mostly a polishing release. There's lots of nice little improvements over the last release, so it should be well worth the update. Changelog: