byuu says:
Changelog:
- added higan/emulator/platform.hpp (moved out Emulator::Platform from
emulator/interface.hpp)
- moved gmake build paramter to nall/GNUmakefile; both higan and
icarus use it now
- added build=profile mode
- MD: added the region select I/O register
- MD: started to add region selection support internally (still no
external select or PAL support)
- PCE: added cycle stealing when reading/writing to the VDC or VCE;
and when using ST# instructions
- PCE: cleaned up PSG to match the behavior of Mednafen (doesn't
improve sound at all ;_;)
- note: need to remove loadWaveSample, loadWavePeriod
- HuC6280: ADC/SBC decimal mode consumes an extra cycle; does not set
V flag
- HuC6280: block transfer instructions were taking one cycle too many
- icarus: added code to strip out PC Engine ROM headers
- hiro: added options support to BrowserDialog
The last one sure ended in failure. The plan was to put a region
dropdown directly onto hiro::BrowserDialog, and I had all the code for
it working. But I forgot one important detail: the system loads
cartridges AFTER powering on, so even though I could technically change
the system region post-boot, I'd rather not do so.
So that means we have to know what region we want before we even select
a game. Shit.
byuu says:
Changelog:
- Super Game Boy support is functional once again
- new GameBoy::SuperGameBoyInterface class
- system.(dmg,cgb,sgb) is now Model::(Super)GameBoy(Color) ala the PC
Engine
- merged WonderSwanInterface, WonderSwanColorInterface shared
functions to WonderSwan::Interface
- merged GameBoyInterface, GameBoyColorInterface shared functions to
GameBoy::Interface
- Interface::unload() now calls Interface::save() for Master System,
Game Gear, Mega Drive, PC Engine, SuperGrafx
- PCE: emulated PCE-CD backup RAM; stored per-game as save.ram (2KiB
file)
- this means you can now save your progress in games like Neutopia
- the PCE-CD I/O registers like BRAM write protect are not
emulated yet
- PCE: IRQ sources now hold the IRQ line state, instead of the CPU
holding it
- this fixes most SuperGrafx games, which were fighting over the
VDC IRQ line previously
- PCE: CPU I/O $14xx should return the pending IRQ bits even if IRQs
are disabled
- PCE: VCE and the VDCs now synchronize to each other; fixes pixel
widths in all games
- PCE: greatly increased the accuracy of the VPC priority selection
code (windows may be buggy still)
- HuC6280: PLA, PLX, PLY should set Z, N flags; fixes many game bugs
[Jonas Quinn]
The big thing I wanted to do was enslave the VDC(s) to the VCE. But
unfortunately, I forgot about the asynchronous DMA channels that each
VDC supports, so this isn't going to be possible I'm afraid.
In the most demanding case, Daimakaimura in-game, we're looking at 85fps
on my Xeon E3 1276v3. So ... not great, and we don't even have sound
connected yet.
We are going to have to profile and optimize this code once sound
emulation and save states are in.
Basically, think of it like this: the VCE, VDC0, and VDC1 all have the
same overhead, scheduling wise (which is the bulk of the performance
loss) as the dot-renderer for the SNES core. So it's like there's three
bsnes-accuracy PPU threads running just for video.
-----
Oh, just a fair warning ... the hooks for the SGB are a work in
progress.
If anyone is working on higan or a fork and want to do something similar
to it, don't use it as a template, at least not yet.
Right now, higan looks like this:
- Emulator::Video handles the platform→videoRefresh calls
- Emulator::Audio handles the platform→audioSample calls
- each core hard-codes the platform→inputPoll, inputRumble calls
- each core hard-codes calls to path, open, load to process files
- dipSettings and notify are specialty hacks, neither are even hooked
up right now to anything
With the SGB, it's an emulation core inside an emulation core, so
ideally you want to hook all of those functions. Emulator::Video and
Emulator::Audio aren't really abstractions over that, as the GB core
calls them and we have to special case not calling them in SGB mode.
The path, open, load can be implemented without hooks, thanks to the UI
only using one instance of Emulator::Platform for all cores. All we have
to do is override the folder path ID for the "Game Boy.sys" folder, so
that it picks "Super Game Boy.sfc/" and loads its boot ROM instead.
That's just a simple argument to GameBoy::System::load() and we're done.
dipSettings, notify and inputRumble don't matter. But we do also have to
hook inputPoll as well.
The nice idea would be for SuperFamicom::ICD2 to inherit from
Emulator::Platform and provide the desired functions that we need to
overload. After that, we'd just need the GB core to keep an abstraction
over the global Emulator::platform\* handle, to select between the UI
version and the SFC::ICD2 version.
However ... that doesn't work because of Emulator::Video and
Emulator::Audio. They would also have to gain an abstraction over
Emulator::platform\*, and even worse ... you'd have to constantly swap
between the two so that the SFC core uses the UI, and the GB core uses
the ICD2.
And so, for right now, I'm checking Model::SuperGameBoy() -> bool
everywhere, and choosing between the UI and ICD2 targets that way. And
as such, the ICD2 doesn't really need Emulator::Platform inheritance,
although it certainly could do that and just use the functions it needs.
But the SGB is even weirder, because we need additional new signals
beyond just Emulator::Platform, like joypWrite(), etc.
I'd also like to work on the Emulator::Stream for the SGB core. I don't
see why we can't have the GB core create its own stream, and let the
ICD2 just use that instead. We just have to be careful about the ICD2's
CPU soft reset function, to make sure the GB core's Stream object
remains valid. What I think that needs is a way to release an
Emulator::Stream individually, rather than calling
Emulator::Audio::reset() to do it. They are shared\_pointer objects, so
I think if I added a destructor function to remove it from
Emulator::Audio::streams, then that should work.
byuu says:
Changelog:
- I caved on the `samples[] = {0.0}` thing, but I'm very unhappy about it
- if it's really invalid C++, then GCC needs to stop accepting it
in strict `-std=c++14` mode
- Emulator::Interface::Information::resettable is gone
- Emulator::Interface::reset() is gone
- FC, SFC, MD cores updated to remove soft reset behavior
- split GameBoy::Interface into GameBoyInterface,
GameBoyColorInterface
- split WonderSwan::Interface into WonderSwanInterface,
WonderSwanColorInterface
- PCE: fixed off-by-one scanline error [hex_usr]
- PCE: temporary hack to prevent crashing when VDS is set to < 2
- hiro: Cocoa: removed (u)int(#) constants; converted (u)int(#)
types to (u)int_(#)t types
- icarus: replaced usage of unique with strip instead (so we don't
mess up frameworks on macOS)
- libco: added macOS-specific section marker [Ryphecha]
So ... the major news this time is the removal of the soft reset
behavior. This is a major!! change that results in a 100KiB diff file,
and it's very prone to accidental mistakes!! If anyone is up for
testing, or even better -- looking over the code changes between v102r01
and v102r02 and looking for any issues, please do so. Ideally we'll want
to test every NES mapper type and every SNES coprocessor type by loading
said games and power cycling to make sure the games are all cleanly
resetting. It's too big of a change for me to cover there not being any
issues on my own, but this is truly critical code, so yeah ... please
help if you can.
We technically lose a bit of hardware documentation here. The soft reset
events do all kinds of interesting things in all kinds of different
chips -- or at least they do on the SNES. This is obviously not ideal.
But in the process of removing these portions of code, I found a few
mistakes I had made previously. It simplifies resetting the system state
a lot when not trying to have all the power() functions call the reset()
functions to share partial functionality.
In the future, the goal will be to come up with a way to add back in the
soft reset behavior via keyboard binding as with the Master System core.
What's going to have to happen is that the key binding will have to send
a "reset pulse" to every emulated chip, and those chips are going to
have to act independently to power() instead of reusing functionality.
We'll get there eventually, but there's many things of vastly greater
importance to work on right now, so it'll be a while. The information
isn't lost ... we'll just have to pull it out of v102 when we are ready.
Note that I left the SNES reset vector simulation code in, even though
it's not possible to trigger, for the time being.
Also ... the Super Game Boy core is still disconnected. To be honest, it
totally slipped my mind when I released v102 that it wasn't connected
again yet. This one's going to be pretty tricky to be honest. I'm
thinking about making a third GameBoy::Interface class just for SGB, and
coming up with some way of bypassing platform-> calls when in this
mode.
byuu says:
Changelog:
- MS, MD, PCE: remove controllers from scheduler in destructor
[hex_usr]
- PCE: no controller should return all bits set (still causing errant
key presses when swapping gamepads)
- PCE: emulate MDR for hardware I/O $0800-$17ff
- PCE: change video resolution to 1140x242
- PCE: added tertiary background Vscroll register (secondary cache)
- PCE: create classes out of VDC VRAM, SATB, CRAM for cleaner access
and I/O registers
- PCE: high bits of CRAM read should be set
- PCE: partially emulated VCE display registers: color frequency, HDS,
HDW, VDS, VDW
- PCE: 32-width sprites now split to two 16-width sprites to handle
overflow properly
- PCE: hopefully emulated sprite zero hit correctly (it's not well
documented, and not often used)
- PCE: trigger line coincidence interrupts during the previous
scanline's Hblank period
- tomoko: raise viewport from 320x240 to 326x242 to accommodate PC
Engine's max resolution
- nall: workaround for Clang compilation bug that can't figure out
that a char is an integral data type
byuu says:
Changelog:
- SMS: fixed controller connection bug
- SMS: fixed Z80 reset bug
- PCE: emulated HuC6280 MMU
- PCE: emulated HuC6280 RAM
- PCE: emulated HuCard ROM reading
- PCE: implemented 178 instructions
- tomoko: removed "soft reset" functionality
- tomoko: moved "power cycle" to just above "unload" option
I'm not sure of the exact number of HuC6280 instructions, but it's less
than 260.
Many of the ones I skipped are HuC6280-originals that I don't know how
to emulate just yet.
I'm also really unsure about the zero page stuff. I believe we should be
adding 0x2000 to the addresses to hit page 1, which is supposed to be
mapped to the zero page (RAM). But when I look at turboEMU's source, I
have no clue how the hell it could possibly be doing that. It looks to
be reading from page 0, which is almost always ROM, which would be ...
really weird.
I also don't know if I've emulated the T mode opcodes correctly or not.
The documentation on them is really confusing.
byuu says:
Changelog:
- converted Emulator::Interface::Bind to Emulator::Platform
- temporarily disabled SGB hooks
- SMS: emulated Game Gear palette (latching word-write behavior not
implemented yet)
- SMS: emulated Master System 'Reset' button, Game Gear 'Start' button
- SMS: removed reset() functionality, driven by the mappable input now
instead
- SMS: split interface class in two: one for Master System, one for
Game Gear
- SMS: emulated Game Gear video cropping to 160x144
- PCE: started on HuC6280 CPU core—so far only registers, NOP
instruction has been implemented
Errata:
- Super Game Boy support is broken and thus disabled
- if you switch between Master System and Game Gear without
restarting, bad things happen:
- SMS→GG, no video output on the GG
- GG→SMS, no input on the SMS
I'm not sure what's causing the SMS\<-\>GG switch bug, having a hard
time debugging it. Help would be very much appreciated, if anyone's up
for it. Otherwise I'll keep trying to track it down on my end.
byuu says:
Changelog:
- SMS: added cartridge ROM/RAM mirroring (fixes Alex Kidd)
- SMS: fixed 8x16 sprite mode (fixes Wonder Boy, Ys graphics)
- Z80: emulated "ex (sp),hl" instruction
- Z80: fixed INx NF (should be set instead of cleared)
- Z80: fixed loop condition check for CPxR, INxR, LDxR, OTxR (fixes
walking in Wonder Boy)
- SFC: removed Debugger and sfc/debugger.hpp
- icarus: connected MS, GG, MD importing to the scan dialog
- PCE: added emulation skeleton to higan and icarus
At this point, Master System games are fairly highly compatible, sans
audio. Game Gear games are running, but I need to crop the resolution
and support the higher color palette that they can utilize. It's really
something else the way they handled the resolution shrink on that thing.
The last change is obviously going to be the biggest news.
I'm very well aware it's not an ideal time to start on a new emulation
core, with the MS and MD cores only just now coming to life with no
audio support.
But, for whatever reason, my heart's really set on working on the PC
Engine. I wanted to write the final higan skeleton core, and get things
ready so that whenever I'm in the mood to work on the PCE, I can do so.
The skeleton is far and away the most tedious and obnoxious part of the
emulator development, because it's basically all just lots of
boilerplate templated code, lots of new files to create, etc.
I really don't know how things are going to proceed ... but I can say
with 99.9% certainty that this will be the final brand new core ever
added to higan -- at least one written by me, that is. This was
basically the last system from my childhood that I ever cared about.
It's the last 2D system with games that I really enjoy playing. No other
system is worth dividing my efforts and reducing the quality and amount
of time to work on the systems I have.
In the future, there will be potential for FDS, Mega CD and PCE-CD
support. But those will all be add-ons, and they'll all be really
difficult and challenge the entire design of higan's UI (it's entirely
cartridge-driven at this time.) None of them will be entirely new cores
like this one.
byuu says:
Changelog:
- SMS: background VDP clips partial tiles on the left (math may not be
right ... it's hard to reason about)
- SMS: fix background VDP scroll locks
- SMS: fix VDP sprite coordinates
- SMS: paint black after the end of the visible display
- todo: shouldn't be a brute force at the end of the main VDP
loop, should happen in each rendering unit
- higan: removed emulator/debugger.hpp
- higan: removed privileged: access specifier
- SFC: removed debugger hooks
- todo: remove sfc/debugger.hpp
- Z80: fixed disassembly of (fd,dd) cb (displacement) (opcode)
instructions
- Z80: fix to prevent interrupts from firing between ix/iy prefixes
and opcodes
- todo: this is a rather hacky fix that could, if exploited, crash
the stack frame
- Z80: fix BIT flags
- Z80: fix ADD hl,reg flags
- Z80: fix CPD, CPI flags
- Z80: fix IND, INI flags
- Z80: fix INDR, INIT loop flag check
- Z80: fix OUTD, OUTI flags
- Z80: fix OTDR, OTIR loop flag check
byuu says:
Changelog:
- SMS: emulated the remaining 240 instructions in the (0xfd, 0xdd)
0xcb (displacement) (opcode) set
- 1/8th of these were "legal" instructions, and apparently games
use them a lot
- SMS: emulated the standard gamepad controllers
- reset button not emulated yet
The reset button is tricky. In every other case, reset is a hardware
thing that instantly reboots the entire machine.
But on the SMS, it's more like a gamepad button that's attached to the
front of the device. When you press it, it fires off a reset vector
interrupt and the gamepad polling routine lets you query the status of
the button.
Just having a reset option in the "Master System" hardware menu is not
sufficient to fully emulate the behavior. Even more annoying is that the
Game Gear doesn't have such a button, yet the core information structs
aren't flexible enough for the Master System to have it, and the Game
Gear to not have it, in the main menu. But that doesn't matter anyway,
since it won't work having it in the menu for the Master System.
So as a result, I'm going to have to have a new "input device" called
"Hardware" that has the "Reset" button listed under there. And for the
sake of consistency, I'm not sure if we should treat the other systems
the same way or not :/
byuu says:
Changelog:
- SMS: emulated the generic Sega memory mapper (none of the more
limited forms of it yet)
- (missing ROM shift, ROM write enable emulation -- no commercial
games use either, though)
- SMS: bus I/O returns 0xff instead of 0x00 so games don't think every
key is being pressed at once
- (this is a hack until I implement proper controller pad reading)
- SMS: very limited protection against reading/writing past the end of
ROM/RAM (todo: should mirror)
- SMS: VDP background HSCROLL subtracts, rather than adds, to the
offset (unlike VSCROLL)
- SMS: VDP VSCROLL is 9-bit, modulates voffset+vscroll to 224 in
192-line mode (32x28 tilemap)
- SMS: VDP tiledata for backgrounds and sprites use `7-(x&7)` rather
than `(x&7)`
- SMS: fix output color to be 6-bit rather than 5-bit
- SMS: left clip uses register `#7`, not palette color `#7`
- (todo: do we want `color[reg7]` or `color[16 + reg7]`?)
- SMS: refined handling of 0xcb, 0xed prefixes in the Z80 core and its
disassembler
- SMS: emulated (0xfd, 0xdd) 0xcb opcodes 0x00-0x0f (still missing
0x10-0xff)
- SMS: fixed 0xcb 0b-----110 opcodes to use direct HL and never allow
(IX,IY)+d
- SMS: fixed major logic bug in (IX,IY)+d displacement
- (was using `read(x)` instead of `operand()` for the displacement
byte fetch before)
- icarus: fake there always being 32KiB of RAM in all SMS cartridges
for the time being
- (not sure how to detect this stuff yet; although I've read it's
not even really possible `>_>`)
TODO: remove processor/z80/dissassembler.cpp code block at line 396 (as it's unnecessary.)
Lots of commercial games are starting to show trashed graphical output now.
byuu says:
Changelog:
- Makefile: added $(windres), -lpthread to Windows port
- GBA: WAITCNT.prefetch is not writable (should fix Donkey Kong: King
of Swing) \[endrift\]
- SMS: fixed hcounter shift value \[hex\_usr\]
- SMS: emulated interrupts (reset button isn't hooked up anywhere, not
sure where to put it yet)
This WIP actually took a really long time because the documentation on
SMS interrupts was all over the place. I'm hoping I've emulated them
correctly, but I honestly have no idea. It's based off my best
understanding from four or five different sources. So it's probably
quite buggy.
However, a few interrupts fire in Sonic the Hedgehog, so that's
something to start with. Now I just have to hope I've gotten some games
far enough in that I can start seeing some data in the VDP VRAM. I need
that before I can start emulating graphics mode 4 to get some actual
screen output.
Or I can just say to hell with it and use a "Hello World" test ROM.
That'd probably be smarter.
byuu says:
Changelog:
- SMS: extended bus mapping of in/out ports: now decoding them fully
inside ms/bus
- SMS: moved Z80 disassembly code from processor/z80 to ms/cpu
(cosmetic)
- SMS: hooked up non-functional silent PSG sample generation, so I can
cap the framerate at 60fps
- SMS: hooked up the VDP main loop: 684 clocks/scanline, 262
scanlines/frame (no PAL support yet)
- SMS: emulated the VDP Vcounter and Hcounter polling ... hopefully
it's right, as it's very bizarre
- SMS: emulated VDP in/out ports (data read, data write, status read,
control write, register write)
- SMS: decoding and caching all VDP register flags (variable names
will probably change)
- nall: \#undef IN on Windows port (prevent compilation warning on
processor/z80)
Watching Sonic the Hedgehog, I can definitely see some VDP register
writes going through, which is a good sign.
Probably the big thing that's needed before I can get enough into the
VDP to start showing graphics is interrupt support. And interrupts are
never fun to figure out :/
What really sucks on this front is I'm flying blind on the Z80 CPU core.
Without a working VDP, I can't run any Z80 test ROMs to look for CPU
bugs. And the CPU is certainly too buggy still to run said test ROM
anyway. I can't find any SMS emulators with trace logging from reset.
Such logs vastly accelerate tracking down CPU logic bugs, so without
them, it's going to take a lot longer.
byuu says:
Changelog:
- added (poorly-named) castable<To, With> template
- Z80 debugger rewritten to make declaring instructions much simpler
- Z80 has more instructions implemented; supports displacement on
(IX), (IY) now
- added `Processor::M68K::Bus` to mirror `Processor::Z80::Bus`
- it does add a pointer indirection; so I'm not sure if I want to
do this for all of my emulator cores ...
byuu says:
Changelog:
- rewrote the Z80 core to properly handle 0xDD (IX0 and 0xFD (IY)
prefixes
- added Processor::Z80::Bus as a new type of abstraction
- all of the instructions implemented have their proper T-cycle counts
now
- added nall/certificates for my public keys
The goal of `Processor::Z80::Bus` is to simulate the opcode fetches being
2-read + 2-wait states; operand+regular reads/writes being 3-read. For
now, this puts the cycle counts inside the CPU core. At the moment, I
can't think of any CPU core where this wouldn't be appropriate. But it's
certainly possible that such a case exists. So this may not be the
perfect solution.
The reason for having it be a subclass of Processor::Z80 instead of
virtual functions for the MasterSystem::CPU core to define is due to
naming conflicts. I wanted the core to say `in(addr)` and have it take
the four clocks. But I also wanted a version of the function that didn't
consume time when called. One way to do that would be for the core to
call `Z80::in(addr)`, which then calls the regular `in(addr)` that goes to
`MasterSystem::CPU::in(addr)`. But I don't want to put the `Z80::`
prefix on all of the opcodes. Very easy to forget it, and then end up not
consuming any time. Another is to use uglier names in the
`MasterSystem::CPU` core, like `read_`, `write_`, `in_`, `out_`, etc. But,
yuck.
So ... yeah, this is an experiment. We'll see how it goes.
byuu says:
Changelog:
- MS: added ms/bus
- Z80: implemented JP/JR/CP/DI/IM/IN instructions
- MD/VDP: added window layer emulation
- MD/controller/gamepad: fixed d2,d3 bits (Altered Beast requires
this)
The Z80 is definitely a lot nastier than the LR35902. There's a lot of
table duplication with HL→IX→IY; and two of them nest two levels deep
(eg FD CB xx xx), so the design may change as I implement more.
byuu says:
Changelog:
- 68K: MOVEQ is 8-bit signed
- 68K: disassembler was print EOR for OR instructions
- 68K: address/program-counter indexed mode had the signed-word/long
bit backward
- 68K: ADDQ/SUBQ #n,aN always works in long mode; regardless of size
- 68K→VDP DMA needs to use `mode.bit(0)<<22|dmaSource`; increment by
one instead of two
- Z80: added registers and initial two instructions
- MS: hooked up enough to load and start running games
- Sonic the Hedgehog can execute exactly one instruction... whoo.