Update to v100r02 release.
byuu says:
Sigh ... I'm really not a good person. I'm inherently selfish.
My responsibility and obligation right now is to work on loki, and
then on the Tengai Makyou Zero translation, and then on improving the
Famicom emulation.
And yet ... it's not what I really want to do. That shouldn't matter;
I should work on my responsibilities first.
Instead, I'm going to be a greedy, self-centered asshole, and work on
what I really want to instead.
I'm really sorry, guys. I'm sure this will make a few people happy,
and probably upset even more people.
I'm also making zero guarantees that this ever gets finished. As always,
I wish I could keep these things secret, so if I fail / give up, I could
just drop it with no shame. But I would have to cut everyone out of the
WIP process completely to make it happen. So, here goes ...
This WIP adds the initial skeleton for Sega Mega Drive / Genesis
emulation. God help us.
(minor note: apparently the new extension for Mega Drive games is .md,
neat. That's what I chose for the folders too. I thought it was .smd,
so that'll be fixed in icarus for the next WIP.)
(aside: this is why I wanted to get v100 out. I didn't want this code in
a skeleton state in v100's source. Nor did I want really broken emulation,
which the first release is sure to be, tarring said release.)
...
So, basically, I've been ruminating on the legacy I want to leave behind
with higan. 3D systems are just plain out. I'm never going to support
them. They're too complex for my abilities, and they would run too slowly
with my design style. I'm not willing to compromise my design ideals. And
I would never want to play a 3D game system at native 240p/480i resolution
... but 1080p+ upscaling is not accurate, so that's a conflict I want
to avoid entirely. It's also never going to emulate computer systems
(X68K, PC-98, FM-Towns, etc) because holy shit that would completely
destroy me. It's also never going emulate arcade machines.
So I think of higan as a collection of 2D emulators for consoles
and handhelds. I've gone over every major 2D gaming system there is,
looking for ones with games I actually care about and enjoy. And I
basically have five of those systems supported already. Looking at the
remaining list, I see only three systems left that I have any interest
in whatsoever: PC-Engine, Master System, Mega Drive. Again, I'm not in
any way committing to emulating any of these, but ... if I had all of
those in higan, I think I'd be content to really, truly, finally stop
writing more emulators for the rest of my life.
And so I decided to tackle the most difficult system first. If I'm
successful, the Z80 core should cover a lot of the work on the SMS. And
the HuC6280 should land somewhere between the NES and SNES in terms of
difficulty ... closer to the NES.
The systems that just don't appeal to me at all, which I will never touch,
include, but are not limited to:
* Atari 2600/5200/7800
* Lynx
* Jaguar
* Vectrex
* Colecovision
* Commodore 64
* Neo-Geo
* Neo-Geo Pocket / Color
* Virtual Boy
* Super A'can
* 32X
* CD-i
* etc, etc, etc.
And really, even if something were mildly interesting in there ... we
have to stop. I can't scale infinitely. I'm already way past my limit,
but I'm doing this anyway. Too many cores bloats everything and kills
quality on everything. I don't want higan to become MESS v2.
I don't know what I'll do about the Famicom Disk System, PC-Engine CD,
and Mega CD. I don't think I'll be able to achieve 60fps emulating the
Mega CD, even if I tried to.
I don't know what's going to happen here with even the Mega Drive. Maybe
I'll get driven crazy with the documentation and quit. Maybe it'll end
up being too complicated and I'll quit. Maybe the emulation will end up
way too slow and I'll give up. Maybe it'll take me seven years to get
any games playable at all. Maybe Steve Snake, AamirM and Mike Pavone
will pool money to hire a hitman to come after me. Who knows.
But this is what I want to do, so ... here goes nothing.
2016-07-09 04:21:37 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
//Zilog Z80
|
|
|
|
|
|
|
|
namespace Processor {
|
|
|
|
|
|
|
|
struct Z80 {
|
Update to v101r14 release.
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.
2016-09-03 11:26:04 +00:00
|
|
|
struct Bus {
|
|
|
|
virtual auto read(uint16 addr) -> uint8 = 0;
|
|
|
|
virtual auto write(uint16 addr, uint8 data) -> void = 0;
|
|
|
|
virtual auto in(uint8 addr) -> uint8 = 0;
|
|
|
|
virtual auto out(uint8 addr, uint8 data) -> void = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
virtual auto step(uint clocks) -> void = 0;
|
2016-08-19 14:11:26 +00:00
|
|
|
|
|
|
|
//z80.cpp
|
2016-09-04 13:51:27 +00:00
|
|
|
auto power() -> void;
|
2016-08-19 14:11:26 +00:00
|
|
|
auto reset() -> void;
|
|
|
|
|
2016-09-04 13:51:27 +00:00
|
|
|
auto parity(uint8) const -> bool;
|
2016-08-27 04:48:21 +00:00
|
|
|
|
Update to v101r14 release.
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.
2016-09-03 11:26:04 +00:00
|
|
|
//memory.cpp
|
|
|
|
auto wait(uint clocks = 1) -> void;
|
|
|
|
auto opcode() -> uint8;
|
|
|
|
auto operand() -> uint8;
|
2016-09-06 00:09:33 +00:00
|
|
|
auto operands() -> uint16;
|
2016-10-31 21:10:33 +00:00
|
|
|
auto push(uint16) -> void;
|
|
|
|
auto pop() -> uint16;
|
2016-09-04 13:51:27 +00:00
|
|
|
auto displace(uint16&) -> uint16;
|
Update to v101r14 release.
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.
2016-09-03 11:26:04 +00:00
|
|
|
auto read(uint16 addr) -> uint8;
|
|
|
|
auto write(uint16 addr, uint8 data) -> void;
|
|
|
|
auto in(uint8 addr) -> uint8;
|
|
|
|
auto out(uint8 addr, uint8 data) -> void;
|
|
|
|
|
2016-08-19 14:11:26 +00:00
|
|
|
//instruction.cpp
|
|
|
|
auto instruction() -> void;
|
Update to v101r14 release.
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.
2016-09-03 11:26:04 +00:00
|
|
|
auto instruction__(uint8 code) -> void;
|
|
|
|
auto instructionCB(uint8 code) -> void;
|
|
|
|
auto instructionED(uint8 code) -> void;
|
2016-08-19 14:11:26 +00:00
|
|
|
|
|
|
|
//instructions.cpp
|
2016-09-06 00:09:33 +00:00
|
|
|
auto ADD(uint8, uint8, bool = false) -> uint8;
|
|
|
|
auto AND(uint8, uint8) -> uint8;
|
2016-10-29 00:33:30 +00:00
|
|
|
auto BIT(uint3, uint8) -> void;
|
2016-09-06 13:53:14 +00:00
|
|
|
auto DEC(uint8) -> uint8;
|
|
|
|
auto INC(uint8) -> uint8;
|
2016-09-06 00:09:33 +00:00
|
|
|
auto OR (uint8, uint8) -> uint8;
|
2016-10-29 00:33:30 +00:00
|
|
|
auto RES(uint3, uint8) -> uint8;
|
|
|
|
auto RL (uint8) -> uint8;
|
|
|
|
auto RLC(uint8) -> uint8;
|
|
|
|
auto RR (uint8) -> uint8;
|
|
|
|
auto RRC(uint8) -> uint8;
|
|
|
|
auto SET(uint3, uint8) -> uint8;
|
|
|
|
auto SLA(uint8) -> uint8;
|
|
|
|
auto SLL(uint8) -> uint8;
|
|
|
|
auto SRA(uint8) -> uint8;
|
|
|
|
auto SRL(uint8) -> uint8;
|
2016-09-06 00:09:33 +00:00
|
|
|
auto SUB(uint8, uint8, bool = false) -> uint8;
|
|
|
|
auto XOR(uint8, uint8) -> uint8;
|
|
|
|
|
|
|
|
auto instructionADC_a_irr(uint16&) -> void;
|
2016-10-31 21:10:33 +00:00
|
|
|
auto instructionADC_a_n() -> void;
|
2016-09-06 00:09:33 +00:00
|
|
|
auto instructionADC_a_r(uint8&) -> void;
|
2016-11-01 11:42:25 +00:00
|
|
|
auto instructionADC_hl_rr(uint16&) -> void;
|
2016-09-06 00:09:33 +00:00
|
|
|
auto instructionADD_a_irr(uint16&) -> void;
|
2016-10-31 21:10:33 +00:00
|
|
|
auto instructionADD_a_n() -> void;
|
2016-09-06 00:09:33 +00:00
|
|
|
auto instructionADD_a_r(uint8&) -> void;
|
2016-11-01 11:42:25 +00:00
|
|
|
auto instructionADD_hl_rr(uint16&) -> void;
|
2016-09-06 00:09:33 +00:00
|
|
|
auto instructionAND_a_irr(uint16&) -> void;
|
2016-10-31 21:10:33 +00:00
|
|
|
auto instructionAND_a_n() -> void;
|
2016-09-06 00:09:33 +00:00
|
|
|
auto instructionAND_a_r(uint8&) -> void;
|
2016-10-29 00:33:30 +00:00
|
|
|
auto instructionBIT_o_irr(uint3, uint16&) -> void;
|
|
|
|
auto instructionBIT_o_r(uint3, uint8&) -> void;
|
2016-10-31 21:10:33 +00:00
|
|
|
auto instructionCALL_c_nn(bool c) -> void;
|
|
|
|
auto instructionCALL_nn() -> void;
|
2016-09-06 13:53:14 +00:00
|
|
|
auto instructionCCF() -> void;
|
2016-09-06 00:09:33 +00:00
|
|
|
auto instructionCP_a_irr(uint16& x) -> void;
|
|
|
|
auto instructionCP_a_n() -> void;
|
|
|
|
auto instructionCP_a_r(uint8& x) -> void;
|
2016-10-29 00:33:30 +00:00
|
|
|
auto instructionCPD() -> void;
|
|
|
|
auto instructionCPDR() -> void;
|
|
|
|
auto instructionCPI() -> void;
|
|
|
|
auto instructionCPIR() -> void;
|
2016-09-06 13:53:14 +00:00
|
|
|
auto instructionCPL() -> void;
|
2016-10-31 21:10:33 +00:00
|
|
|
auto instructionDAA() -> void;
|
2016-09-06 13:53:14 +00:00
|
|
|
auto instructionDEC_irr(uint16&) -> void;
|
|
|
|
auto instructionDEC_r(uint8&) -> void;
|
|
|
|
auto instructionDEC_rr(uint16&) -> void;
|
2016-08-19 14:11:26 +00:00
|
|
|
auto instructionDI() -> void;
|
2016-10-31 21:10:33 +00:00
|
|
|
auto instructionDJNZ_e() -> void;
|
Update to v101r14 release.
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.
2016-09-03 11:26:04 +00:00
|
|
|
auto instructionEI() -> void;
|
2016-09-06 13:53:14 +00:00
|
|
|
auto instructionEX_rr_rr(uint16&, uint16&) -> void;
|
2016-10-31 21:10:33 +00:00
|
|
|
auto instructionEXX() -> void;
|
2016-09-06 00:09:33 +00:00
|
|
|
auto instructionHALT() -> void;
|
Update to v101r14 release.
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.
2016-09-03 11:26:04 +00:00
|
|
|
auto instructionIM_o(uint2) -> void;
|
2016-08-27 04:48:21 +00:00
|
|
|
auto instructionIN_a_in() -> void;
|
2016-10-31 21:10:33 +00:00
|
|
|
auto instructionIN_r_ic(uint8&) -> void;
|
2016-09-06 13:53:14 +00:00
|
|
|
auto instructionINC_irr(uint16&) -> void;
|
|
|
|
auto instructionINC_r(uint8&) -> void;
|
|
|
|
auto instructionINC_rr(uint16&) -> void;
|
2016-10-29 00:33:30 +00:00
|
|
|
auto instructionIND() -> void;
|
|
|
|
auto instructionINDR() -> void;
|
|
|
|
auto instructionINI() -> void;
|
|
|
|
auto instructionINIR() -> void;
|
2016-08-27 04:48:21 +00:00
|
|
|
auto instructionJP_c_nn(bool) -> void;
|
2016-10-31 21:10:33 +00:00
|
|
|
auto instructionJP_rr(uint16&) -> void;
|
Update to v101r14 release.
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.
2016-09-03 11:26:04 +00:00
|
|
|
auto instructionJR_c_e(bool) -> void;
|
2016-09-06 13:53:14 +00:00
|
|
|
auto instructionLD_a_inn() -> void;
|
|
|
|
auto instructionLD_a_irr(uint16& x) -> void;
|
2016-09-04 13:51:27 +00:00
|
|
|
auto instructionLD_inn_a() -> void;
|
2016-09-06 13:53:14 +00:00
|
|
|
auto instructionLD_inn_rr(uint16&) -> void;
|
|
|
|
auto instructionLD_irr_a(uint16&) -> void;
|
2016-09-04 13:51:27 +00:00
|
|
|
auto instructionLD_irr_n(uint16&) -> void;
|
|
|
|
auto instructionLD_irr_r(uint16&, uint8&) -> void;
|
|
|
|
auto instructionLD_r_n(uint8&) -> void;
|
2016-09-06 00:09:33 +00:00
|
|
|
auto instructionLD_r_irr(uint8&, uint16&) -> void;
|
|
|
|
auto instructionLD_r_r(uint8&, uint8&) -> void;
|
2016-11-01 11:42:25 +00:00
|
|
|
auto instructionLD_r_r1(uint8&, uint8&) -> void;
|
2016-09-06 13:53:14 +00:00
|
|
|
auto instructionLD_rr_inn(uint16&) -> void;
|
2016-09-04 13:51:27 +00:00
|
|
|
auto instructionLD_rr_nn(uint16&) -> void;
|
2016-10-31 21:10:33 +00:00
|
|
|
auto instructionLD_sp_rr(uint16&) -> void;
|
2016-10-29 00:33:30 +00:00
|
|
|
auto instructionLDD() -> void;
|
|
|
|
auto instructionLDDR() -> void;
|
|
|
|
auto instructionLDI() -> void;
|
|
|
|
auto instructionLDIR() -> void;
|
2016-10-31 21:10:33 +00:00
|
|
|
auto instructionNEG() -> void;
|
2016-08-19 14:11:26 +00:00
|
|
|
auto instructionNOP() -> void;
|
2016-09-06 00:09:33 +00:00
|
|
|
auto instructionOR_a_irr(uint16&) -> void;
|
2016-10-31 21:10:33 +00:00
|
|
|
auto instructionOR_a_n() -> void;
|
2016-09-06 00:09:33 +00:00
|
|
|
auto instructionOR_a_r(uint8&) -> void;
|
2016-10-29 00:33:30 +00:00
|
|
|
auto instructionOTDR() -> void;
|
|
|
|
auto instructionOTIR() -> void;
|
2016-10-31 21:10:33 +00:00
|
|
|
auto instructionOUT_ic_r(uint8&) -> void;
|
|
|
|
auto instructionOUT_n_a() -> void;
|
2016-10-29 00:33:30 +00:00
|
|
|
auto instructionOUTD() -> void;
|
|
|
|
auto instructionOUTI() -> void;
|
2016-10-31 21:10:33 +00:00
|
|
|
auto instructionPOP_rr(uint16&) -> void;
|
|
|
|
auto instructionPUSH_rr(uint16&) -> void;
|
2016-10-29 00:33:30 +00:00
|
|
|
auto instructionRES_o_irr(uint3, uint16&) -> void;
|
|
|
|
auto instructionRES_o_r(uint3, uint8&) -> void;
|
2016-10-31 21:10:33 +00:00
|
|
|
auto instructionRET() -> void;
|
|
|
|
auto instructionRET_c(bool c) -> void;
|
|
|
|
auto instructionRETI() -> void;
|
|
|
|
auto instructionRETN() -> void;
|
2016-10-29 00:33:30 +00:00
|
|
|
auto instructionRL_irr(uint16&) -> void;
|
|
|
|
auto instructionRL_r(uint8&) -> void;
|
2016-09-06 13:53:14 +00:00
|
|
|
auto instructionRLA() -> void;
|
2016-10-29 00:33:30 +00:00
|
|
|
auto instructionRLC_irr(uint16&) -> void;
|
|
|
|
auto instructionRLC_r(uint8&) -> void;
|
2016-09-06 13:53:14 +00:00
|
|
|
auto instructionRLCA() -> void;
|
2016-11-01 11:42:25 +00:00
|
|
|
auto instructionRLD() -> void;
|
2016-10-29 00:33:30 +00:00
|
|
|
auto instructionRR_irr(uint16&) -> void;
|
|
|
|
auto instructionRR_r(uint8&) -> void;
|
2016-09-06 13:53:14 +00:00
|
|
|
auto instructionRRA() -> void;
|
2016-10-29 00:33:30 +00:00
|
|
|
auto instructionRRC_irr(uint16&) -> void;
|
|
|
|
auto instructionRRC_r(uint8&) -> void;
|
2016-09-06 13:53:14 +00:00
|
|
|
auto instructionRRCA() -> void;
|
2016-11-01 11:42:25 +00:00
|
|
|
auto instructionRRD() -> void;
|
2016-10-31 21:10:33 +00:00
|
|
|
auto instructionRST_o(uint3) -> void;
|
2016-09-06 00:09:33 +00:00
|
|
|
auto instructionSBC_a_irr(uint16&) -> void;
|
2016-10-31 21:10:33 +00:00
|
|
|
auto instructionSBC_a_n() -> void;
|
2016-09-06 00:09:33 +00:00
|
|
|
auto instructionSBC_a_r(uint8&) -> void;
|
2016-11-01 11:42:25 +00:00
|
|
|
auto instructionSBC_hl_rr(uint16&) -> void;
|
2016-09-06 13:53:14 +00:00
|
|
|
auto instructionSCF() -> void;
|
2016-10-29 00:33:30 +00:00
|
|
|
auto instructionSET_o_irr(uint3, uint16&) -> void;
|
|
|
|
auto instructionSET_o_r(uint3, uint8&) -> void;
|
|
|
|
auto instructionSLA_irr(uint16&) -> void;
|
|
|
|
auto instructionSLA_r(uint8&) -> void;
|
|
|
|
auto instructionSLL_irr(uint16&) -> void;
|
|
|
|
auto instructionSLL_r(uint8&) -> void;
|
|
|
|
auto instructionSRA_irr(uint16&) -> void;
|
|
|
|
auto instructionSRA_r(uint8&) -> void;
|
|
|
|
auto instructionSRL_irr(uint16&) -> void;
|
|
|
|
auto instructionSRL_r(uint8&) -> void;
|
2016-09-06 00:09:33 +00:00
|
|
|
auto instructionSUB_a_irr(uint16&) -> void;
|
2016-10-31 21:10:33 +00:00
|
|
|
auto instructionSUB_a_n() -> void;
|
2016-09-06 00:09:33 +00:00
|
|
|
auto instructionSUB_a_r(uint8&) -> void;
|
|
|
|
auto instructionXOR_a_irr(uint16&) -> void;
|
2016-10-31 21:10:33 +00:00
|
|
|
auto instructionXOR_a_n() -> void;
|
2016-09-06 00:09:33 +00:00
|
|
|
auto instructionXOR_a_r(uint8&) -> void;
|
2016-08-19 14:11:26 +00:00
|
|
|
|
2016-08-27 04:48:21 +00:00
|
|
|
//disassembler.cpp
|
|
|
|
auto disassemble(uint16 pc) -> string;
|
Update to v101r14 release.
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.
2016-09-03 11:26:04 +00:00
|
|
|
auto disassemble__(uint16 pc, uint8 prefix, uint8 code) -> string;
|
|
|
|
auto disassembleCB(uint16 pc, uint8 prefix, uint8 code) -> string;
|
|
|
|
auto disassembleED(uint16 pc, uint8 prefix, uint8 code) -> string;
|
2016-08-27 04:48:21 +00:00
|
|
|
|
2016-08-19 14:11:26 +00:00
|
|
|
struct Registers {
|
2016-09-06 13:53:14 +00:00
|
|
|
union Pair {
|
|
|
|
Pair() : word(0) {}
|
|
|
|
uint16 word;
|
|
|
|
struct Byte { uint8 order_msb2(hi, lo); } byte;
|
2016-08-19 14:11:26 +00:00
|
|
|
};
|
|
|
|
|
2016-09-06 13:53:14 +00:00
|
|
|
Pair af, af_;
|
|
|
|
Pair bc, bc_;
|
|
|
|
Pair de, de_;
|
|
|
|
Pair hl, hl_;
|
|
|
|
Pair ix;
|
|
|
|
Pair iy;
|
|
|
|
Pair ir;
|
|
|
|
uint16 sp;
|
|
|
|
uint16 pc;
|
2016-08-19 14:11:26 +00:00
|
|
|
|
2016-09-06 00:09:33 +00:00
|
|
|
boolean halt; //HALT instruction executed
|
Update to v101r14 release.
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.
2016-09-03 11:26:04 +00:00
|
|
|
boolean iff1; //interrupt flip-flop 1
|
|
|
|
boolean iff2; //interrupt flip-flop 2
|
|
|
|
uint2 im; //interrupt mode (0-2)
|
2016-08-27 04:48:21 +00:00
|
|
|
|
2016-09-06 13:53:14 +00:00
|
|
|
Pair* hlp = nullptr;
|
2016-08-19 14:11:26 +00:00
|
|
|
} r;
|
|
|
|
|
Update to v101r14 release.
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.
2016-09-03 11:26:04 +00:00
|
|
|
Bus* bus = nullptr;
|
Update to v100r02 release.
byuu says:
Sigh ... I'm really not a good person. I'm inherently selfish.
My responsibility and obligation right now is to work on loki, and
then on the Tengai Makyou Zero translation, and then on improving the
Famicom emulation.
And yet ... it's not what I really want to do. That shouldn't matter;
I should work on my responsibilities first.
Instead, I'm going to be a greedy, self-centered asshole, and work on
what I really want to instead.
I'm really sorry, guys. I'm sure this will make a few people happy,
and probably upset even more people.
I'm also making zero guarantees that this ever gets finished. As always,
I wish I could keep these things secret, so if I fail / give up, I could
just drop it with no shame. But I would have to cut everyone out of the
WIP process completely to make it happen. So, here goes ...
This WIP adds the initial skeleton for Sega Mega Drive / Genesis
emulation. God help us.
(minor note: apparently the new extension for Mega Drive games is .md,
neat. That's what I chose for the folders too. I thought it was .smd,
so that'll be fixed in icarus for the next WIP.)
(aside: this is why I wanted to get v100 out. I didn't want this code in
a skeleton state in v100's source. Nor did I want really broken emulation,
which the first release is sure to be, tarring said release.)
...
So, basically, I've been ruminating on the legacy I want to leave behind
with higan. 3D systems are just plain out. I'm never going to support
them. They're too complex for my abilities, and they would run too slowly
with my design style. I'm not willing to compromise my design ideals. And
I would never want to play a 3D game system at native 240p/480i resolution
... but 1080p+ upscaling is not accurate, so that's a conflict I want
to avoid entirely. It's also never going to emulate computer systems
(X68K, PC-98, FM-Towns, etc) because holy shit that would completely
destroy me. It's also never going emulate arcade machines.
So I think of higan as a collection of 2D emulators for consoles
and handhelds. I've gone over every major 2D gaming system there is,
looking for ones with games I actually care about and enjoy. And I
basically have five of those systems supported already. Looking at the
remaining list, I see only three systems left that I have any interest
in whatsoever: PC-Engine, Master System, Mega Drive. Again, I'm not in
any way committing to emulating any of these, but ... if I had all of
those in higan, I think I'd be content to really, truly, finally stop
writing more emulators for the rest of my life.
And so I decided to tackle the most difficult system first. If I'm
successful, the Z80 core should cover a lot of the work on the SMS. And
the HuC6280 should land somewhere between the NES and SNES in terms of
difficulty ... closer to the NES.
The systems that just don't appeal to me at all, which I will never touch,
include, but are not limited to:
* Atari 2600/5200/7800
* Lynx
* Jaguar
* Vectrex
* Colecovision
* Commodore 64
* Neo-Geo
* Neo-Geo Pocket / Color
* Virtual Boy
* Super A'can
* 32X
* CD-i
* etc, etc, etc.
And really, even if something were mildly interesting in there ... we
have to stop. I can't scale infinitely. I'm already way past my limit,
but I'm doing this anyway. Too many cores bloats everything and kills
quality on everything. I don't want higan to become MESS v2.
I don't know what I'll do about the Famicom Disk System, PC-Engine CD,
and Mega CD. I don't think I'll be able to achieve 60fps emulating the
Mega CD, even if I tried to.
I don't know what's going to happen here with even the Mega Drive. Maybe
I'll get driven crazy with the documentation and quit. Maybe it'll end
up being too complicated and I'll quit. Maybe the emulation will end up
way too slow and I'll give up. Maybe it'll take me seven years to get
any games playable at all. Maybe Steve Snake, AamirM and Mike Pavone
will pool money to hire a hitman to come after me. Who knows.
But this is what I want to do, so ... here goes nothing.
2016-07-09 04:21:37 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
}
|