2010-08-09 13:28:56 +00:00
|
|
|
#ifdef PPU_CPP
|
|
|
|
|
2010-09-24 13:15:21 +00:00
|
|
|
bool PPU::interlace() const {
|
|
|
|
return display.interlace;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool PPU::overscan() const {
|
|
|
|
return display.overscan;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool PPU::hires() const {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-08-09 13:28:56 +00:00
|
|
|
void PPU::latch_counters() {
|
|
|
|
cpu.synchronize_ppu();
|
|
|
|
regs.hcounter = hdot();
|
|
|
|
regs.vcounter = vcounter();
|
|
|
|
regs.counters_latched = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint16 PPU::get_vram_address() {
|
|
|
|
uint16 addr = regs.vram_addr;
|
|
|
|
switch(regs.vram_mapping) {
|
2013-05-05 09:21:30 +00:00
|
|
|
case 0: break; //direct mapping
|
|
|
|
case 1: addr = (addr & 0xff00) | ((addr & 0x001f) << 3) | ((addr >> 5) & 7); break;
|
|
|
|
case 2: addr = (addr & 0xfe00) | ((addr & 0x003f) << 3) | ((addr >> 6) & 7); break;
|
|
|
|
case 3: addr = (addr & 0xfc00) | ((addr & 0x007f) << 3) | ((addr >> 7) & 7); break;
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
return (addr << 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8 PPU::vram_read(unsigned addr) {
|
Update to v094r05 release.
byuu says:
Commands can be prefixed with: (cpu|smp|ppu|dsp|apu|vram|oam|cgram)/ to
set their source. Eg "vram/hex 0800" or "smp/breakpoints.append execute
ffc0"; default is cpu.
These overlap a little bit in odd ways, but that's just the way the SNES
works: it's not a very orthogonal system. CPU is both a processor and
the main bus (ROM, RAM, WRAM, etc), APU is the shared memory by the
SMP+DSP (eg use it to catch writes from either chip); PPU probably won't
ever be used since it's broken down into three separate buses (VRAM,
OAM, CGRAM), but DSP could be useful for tracking bugs like we found in
Koushien 2 with the DSP echo buffer corrupting SMP opcodes. Technically
the PPU memory pools are only ever tripped by the CPU poking at them, as
the PPU doesn't ever write.
I now have run.for, run.to, step.for, step.to. The difference is that
run only prints the next instruction after running, whereas step prints
all of the instructions along the way as well. run.to acts the same as
"step over" here. Although it's not quite as nice, since you have to
specify the address of the next instruction.
Logging the Field/Vcounter/Hcounter on instruction listings now, good
for timing information.
Added in the tracer mask, as well as memory export, as well as
VRAM/OAM/CGRAM/SMP read/write/execute breakpoints, as well as an APU
usage map (it tracks DSP reads/writes separately, although I don't
currently have debugger callbacks on DSP accesses just yet.)
Have not hooked up actual SMP debugging just yet, but I plan to soon.
Still thinking about how I want to allow / block interleaving of
instructions (terminal output and tracing.)
So ... remaining tasks at this point:
- full SMP debugging
- CPU+SMP interleave support
- aliases
- hotkeys
- save states (will be kind of tricky ... will have to suppress
breakpoints during synchronization, or abort a save in a break event.)
- keep track of window geometry between runs
2014-02-05 11:30:08 +00:00
|
|
|
uint8 data = 0x00;
|
Update to v068r12 release.
(there was no r11 release posted to the WIP thread)
byuu says:
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-04 03:36:03 +00:00
|
|
|
if(regs.display_disable || vcounter() >= (!regs.overscan ? 225 : 240)) {
|
Update to v094r05 release.
byuu says:
Commands can be prefixed with: (cpu|smp|ppu|dsp|apu|vram|oam|cgram)/ to
set their source. Eg "vram/hex 0800" or "smp/breakpoints.append execute
ffc0"; default is cpu.
These overlap a little bit in odd ways, but that's just the way the SNES
works: it's not a very orthogonal system. CPU is both a processor and
the main bus (ROM, RAM, WRAM, etc), APU is the shared memory by the
SMP+DSP (eg use it to catch writes from either chip); PPU probably won't
ever be used since it's broken down into three separate buses (VRAM,
OAM, CGRAM), but DSP could be useful for tracking bugs like we found in
Koushien 2 with the DSP echo buffer corrupting SMP opcodes. Technically
the PPU memory pools are only ever tripped by the CPU poking at them, as
the PPU doesn't ever write.
I now have run.for, run.to, step.for, step.to. The difference is that
run only prints the next instruction after running, whereas step prints
all of the instructions along the way as well. run.to acts the same as
"step over" here. Although it's not quite as nice, since you have to
specify the address of the next instruction.
Logging the Field/Vcounter/Hcounter on instruction listings now, good
for timing information.
Added in the tracer mask, as well as memory export, as well as
VRAM/OAM/CGRAM/SMP read/write/execute breakpoints, as well as an APU
usage map (it tracks DSP reads/writes separately, although I don't
currently have debugger callbacks on DSP accesses just yet.)
Have not hooked up actual SMP debugging just yet, but I plan to soon.
Still thinking about how I want to allow / block interleaving of
instructions (terminal output and tracing.)
So ... remaining tasks at this point:
- full SMP debugging
- CPU+SMP interleave support
- aliases
- hotkeys
- save states (will be kind of tricky ... will have to suppress
breakpoints during synchronization, or abort a save in a break event.)
- keep track of window geometry between runs
2014-02-05 11:30:08 +00:00
|
|
|
data = vram[addr];
|
|
|
|
debugger.vram_read(addr, data);
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
Update to v094r05 release.
byuu says:
Commands can be prefixed with: (cpu|smp|ppu|dsp|apu|vram|oam|cgram)/ to
set their source. Eg "vram/hex 0800" or "smp/breakpoints.append execute
ffc0"; default is cpu.
These overlap a little bit in odd ways, but that's just the way the SNES
works: it's not a very orthogonal system. CPU is both a processor and
the main bus (ROM, RAM, WRAM, etc), APU is the shared memory by the
SMP+DSP (eg use it to catch writes from either chip); PPU probably won't
ever be used since it's broken down into three separate buses (VRAM,
OAM, CGRAM), but DSP could be useful for tracking bugs like we found in
Koushien 2 with the DSP echo buffer corrupting SMP opcodes. Technically
the PPU memory pools are only ever tripped by the CPU poking at them, as
the PPU doesn't ever write.
I now have run.for, run.to, step.for, step.to. The difference is that
run only prints the next instruction after running, whereas step prints
all of the instructions along the way as well. run.to acts the same as
"step over" here. Although it's not quite as nice, since you have to
specify the address of the next instruction.
Logging the Field/Vcounter/Hcounter on instruction listings now, good
for timing information.
Added in the tracer mask, as well as memory export, as well as
VRAM/OAM/CGRAM/SMP read/write/execute breakpoints, as well as an APU
usage map (it tracks DSP reads/writes separately, although I don't
currently have debugger callbacks on DSP accesses just yet.)
Have not hooked up actual SMP debugging just yet, but I plan to soon.
Still thinking about how I want to allow / block interleaving of
instructions (terminal output and tracing.)
So ... remaining tasks at this point:
- full SMP debugging
- CPU+SMP interleave support
- aliases
- hotkeys
- save states (will be kind of tricky ... will have to suppress
breakpoints during synchronization, or abort a save in a break event.)
- keep track of window geometry between runs
2014-02-05 11:30:08 +00:00
|
|
|
return data;
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void PPU::vram_write(unsigned addr, uint8 data) {
|
Update to v068r12 release.
(there was no r11 release posted to the WIP thread)
byuu says:
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-04 03:36:03 +00:00
|
|
|
if(regs.display_disable || vcounter() >= (!regs.overscan ? 225 : 240)) {
|
Update to v074r11 release.
byuu says:
Changelog:
- debugger compiles on all three profiles
- libsnes compiles on all three platforms (no API changes to libsnes)
- memory.cpp : namespace memory removed (wram -> cpu, apuram -> smp,
vram, oam, cgram -> ppu)
- sa1.cpp : namespace memory removed (SA-1 specific functions merged
inline to SA1::bus_read,write)
- GameBoy: added serial link support with interrupts and proper 8192hz
timing, but obviously it acts as if no other GB is connected to it
- GameBoy: added STAT OAM interrupt, and better STAT d1,d0 mode values
- UI: since Qt is dead, I've renamed the config files back to bsnes.cfg
and bsnes-geometry.cfg
- SA1: IRAM was not syncing to CPU on SA-1 side
- PPU/Accuracy and PPU/Performance needed Sprite oam renamed to Sprite
sprite; so that I could add uint8 oam[544]
- makes more sense anyway, OAM = object attribute memory, obj or
sprite are better names for Sprite rendering class
- more cleanup
2011-01-24 09:03:17 +00:00
|
|
|
vram[addr] = data;
|
Update to v094r05 release.
byuu says:
Commands can be prefixed with: (cpu|smp|ppu|dsp|apu|vram|oam|cgram)/ to
set their source. Eg "vram/hex 0800" or "smp/breakpoints.append execute
ffc0"; default is cpu.
These overlap a little bit in odd ways, but that's just the way the SNES
works: it's not a very orthogonal system. CPU is both a processor and
the main bus (ROM, RAM, WRAM, etc), APU is the shared memory by the
SMP+DSP (eg use it to catch writes from either chip); PPU probably won't
ever be used since it's broken down into three separate buses (VRAM,
OAM, CGRAM), but DSP could be useful for tracking bugs like we found in
Koushien 2 with the DSP echo buffer corrupting SMP opcodes. Technically
the PPU memory pools are only ever tripped by the CPU poking at them, as
the PPU doesn't ever write.
I now have run.for, run.to, step.for, step.to. The difference is that
run only prints the next instruction after running, whereas step prints
all of the instructions along the way as well. run.to acts the same as
"step over" here. Although it's not quite as nice, since you have to
specify the address of the next instruction.
Logging the Field/Vcounter/Hcounter on instruction listings now, good
for timing information.
Added in the tracer mask, as well as memory export, as well as
VRAM/OAM/CGRAM/SMP read/write/execute breakpoints, as well as an APU
usage map (it tracks DSP reads/writes separately, although I don't
currently have debugger callbacks on DSP accesses just yet.)
Have not hooked up actual SMP debugging just yet, but I plan to soon.
Still thinking about how I want to allow / block interleaving of
instructions (terminal output and tracing.)
So ... remaining tasks at this point:
- full SMP debugging
- CPU+SMP interleave support
- aliases
- hotkeys
- save states (will be kind of tricky ... will have to suppress
breakpoints during synchronization, or abort a save in a break event.)
- keep track of window geometry between runs
2014-02-05 11:30:08 +00:00
|
|
|
debugger.vram_write(addr, data);
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Update to v085r08 release.
byuu says:
Changelog:
- follow the Laevateinn topic to get most of it
- also added NMI, IRQ step buttons to CPU debugger
- also added trace masking + trace mask reset
- also added memory export
- cartridge loading is entirely folder-based now
FitzRoy, I'll go ahead and make a second compromise with you for v086:
I'll match the following:
/path/to/SNES.sfc/*.sfc
/path/to/NES.fc/*.prg, *.chr (split format)
/path/to/NES.fc/*.fc (merged format)
/path/to/GB.gb/*.gb
/path/to/GBC.gbc/*.gbc
Condition will be that there can only be one of each file. If there's
more than one, it'll abort. That lets me name my ROMs as
"Game.fc/Game.fc", and you can name yours as "Game.fc/cartridge.prg,
cartridge.chr". Or whatever you want.
We'll just go with that, see what fares out as the most popular, and
then restrict it back to that method.
The folder must have the .fc, etc extension though. That will be how we
avoid false-positive folder matches.
[Editor's note - the Laevateinn topic mentions these changes for
v085r08:
Added SMP/PPU breakpoints, SMP debugger, SMP stepping / tracing,
memory editing on APU-bus / VRAM / OAM / CGRAM, save state menu,
WRAM mirroring on breakpoints, protected MMIO memory regions
(otherwise, viewing $002100 could crash your game.)
Major missing components:
- trace mask
- trace mask clear / usage map clear
- window geometry caching / sizing improvements
- VRAM viewer
- properties viewer
- working memory export button
The rest will most likely appear after v086 is released.
]
2012-02-12 05:35:40 +00:00
|
|
|
uint8 PPU::oam_read(unsigned addr) {
|
Update to v094r05 release.
byuu says:
Commands can be prefixed with: (cpu|smp|ppu|dsp|apu|vram|oam|cgram)/ to
set their source. Eg "vram/hex 0800" or "smp/breakpoints.append execute
ffc0"; default is cpu.
These overlap a little bit in odd ways, but that's just the way the SNES
works: it's not a very orthogonal system. CPU is both a processor and
the main bus (ROM, RAM, WRAM, etc), APU is the shared memory by the
SMP+DSP (eg use it to catch writes from either chip); PPU probably won't
ever be used since it's broken down into three separate buses (VRAM,
OAM, CGRAM), but DSP could be useful for tracking bugs like we found in
Koushien 2 with the DSP echo buffer corrupting SMP opcodes. Technically
the PPU memory pools are only ever tripped by the CPU poking at them, as
the PPU doesn't ever write.
I now have run.for, run.to, step.for, step.to. The difference is that
run only prints the next instruction after running, whereas step prints
all of the instructions along the way as well. run.to acts the same as
"step over" here. Although it's not quite as nice, since you have to
specify the address of the next instruction.
Logging the Field/Vcounter/Hcounter on instruction listings now, good
for timing information.
Added in the tracer mask, as well as memory export, as well as
VRAM/OAM/CGRAM/SMP read/write/execute breakpoints, as well as an APU
usage map (it tracks DSP reads/writes separately, although I don't
currently have debugger callbacks on DSP accesses just yet.)
Have not hooked up actual SMP debugging just yet, but I plan to soon.
Still thinking about how I want to allow / block interleaving of
instructions (terminal output and tracing.)
So ... remaining tasks at this point:
- full SMP debugging
- CPU+SMP interleave support
- aliases
- hotkeys
- save states (will be kind of tricky ... will have to suppress
breakpoints during synchronization, or abort a save in a break event.)
- keep track of window geometry between runs
2014-02-05 11:30:08 +00:00
|
|
|
uint8 data = oam[addr];
|
|
|
|
debugger.oam_read(addr, data);
|
|
|
|
return data;
|
Update to v085r08 release.
byuu says:
Changelog:
- follow the Laevateinn topic to get most of it
- also added NMI, IRQ step buttons to CPU debugger
- also added trace masking + trace mask reset
- also added memory export
- cartridge loading is entirely folder-based now
FitzRoy, I'll go ahead and make a second compromise with you for v086:
I'll match the following:
/path/to/SNES.sfc/*.sfc
/path/to/NES.fc/*.prg, *.chr (split format)
/path/to/NES.fc/*.fc (merged format)
/path/to/GB.gb/*.gb
/path/to/GBC.gbc/*.gbc
Condition will be that there can only be one of each file. If there's
more than one, it'll abort. That lets me name my ROMs as
"Game.fc/Game.fc", and you can name yours as "Game.fc/cartridge.prg,
cartridge.chr". Or whatever you want.
We'll just go with that, see what fares out as the most popular, and
then restrict it back to that method.
The folder must have the .fc, etc extension though. That will be how we
avoid false-positive folder matches.
[Editor's note - the Laevateinn topic mentions these changes for
v085r08:
Added SMP/PPU breakpoints, SMP debugger, SMP stepping / tracing,
memory editing on APU-bus / VRAM / OAM / CGRAM, save state menu,
WRAM mirroring on breakpoints, protected MMIO memory regions
(otherwise, viewing $002100 could crash your game.)
Major missing components:
- trace mask
- trace mask clear / usage map clear
- window geometry caching / sizing improvements
- VRAM viewer
- properties viewer
- working memory export button
The rest will most likely appear after v086 is released.
]
2012-02-12 05:35:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void PPU::oam_write(unsigned addr, uint8 data) {
|
|
|
|
oam[addr] = data;
|
|
|
|
sprite.update(addr, data);
|
Update to v094r05 release.
byuu says:
Commands can be prefixed with: (cpu|smp|ppu|dsp|apu|vram|oam|cgram)/ to
set their source. Eg "vram/hex 0800" or "smp/breakpoints.append execute
ffc0"; default is cpu.
These overlap a little bit in odd ways, but that's just the way the SNES
works: it's not a very orthogonal system. CPU is both a processor and
the main bus (ROM, RAM, WRAM, etc), APU is the shared memory by the
SMP+DSP (eg use it to catch writes from either chip); PPU probably won't
ever be used since it's broken down into three separate buses (VRAM,
OAM, CGRAM), but DSP could be useful for tracking bugs like we found in
Koushien 2 with the DSP echo buffer corrupting SMP opcodes. Technically
the PPU memory pools are only ever tripped by the CPU poking at them, as
the PPU doesn't ever write.
I now have run.for, run.to, step.for, step.to. The difference is that
run only prints the next instruction after running, whereas step prints
all of the instructions along the way as well. run.to acts the same as
"step over" here. Although it's not quite as nice, since you have to
specify the address of the next instruction.
Logging the Field/Vcounter/Hcounter on instruction listings now, good
for timing information.
Added in the tracer mask, as well as memory export, as well as
VRAM/OAM/CGRAM/SMP read/write/execute breakpoints, as well as an APU
usage map (it tracks DSP reads/writes separately, although I don't
currently have debugger callbacks on DSP accesses just yet.)
Have not hooked up actual SMP debugging just yet, but I plan to soon.
Still thinking about how I want to allow / block interleaving of
instructions (terminal output and tracing.)
So ... remaining tasks at this point:
- full SMP debugging
- CPU+SMP interleave support
- aliases
- hotkeys
- save states (will be kind of tricky ... will have to suppress
breakpoints during synchronization, or abort a save in a break event.)
- keep track of window geometry between runs
2014-02-05 11:30:08 +00:00
|
|
|
debugger.oam_write(addr, data);
|
Update to v085r08 release.
byuu says:
Changelog:
- follow the Laevateinn topic to get most of it
- also added NMI, IRQ step buttons to CPU debugger
- also added trace masking + trace mask reset
- also added memory export
- cartridge loading is entirely folder-based now
FitzRoy, I'll go ahead and make a second compromise with you for v086:
I'll match the following:
/path/to/SNES.sfc/*.sfc
/path/to/NES.fc/*.prg, *.chr (split format)
/path/to/NES.fc/*.fc (merged format)
/path/to/GB.gb/*.gb
/path/to/GBC.gbc/*.gbc
Condition will be that there can only be one of each file. If there's
more than one, it'll abort. That lets me name my ROMs as
"Game.fc/Game.fc", and you can name yours as "Game.fc/cartridge.prg,
cartridge.chr". Or whatever you want.
We'll just go with that, see what fares out as the most popular, and
then restrict it back to that method.
The folder must have the .fc, etc extension though. That will be how we
avoid false-positive folder matches.
[Editor's note - the Laevateinn topic mentions these changes for
v085r08:
Added SMP/PPU breakpoints, SMP debugger, SMP stepping / tracing,
memory editing on APU-bus / VRAM / OAM / CGRAM, save state menu,
WRAM mirroring on breakpoints, protected MMIO memory regions
(otherwise, viewing $002100 could crash your game.)
Major missing components:
- trace mask
- trace mask clear / usage map clear
- window geometry caching / sizing improvements
- VRAM viewer
- properties viewer
- working memory export button
The rest will most likely appear after v086 is released.
]
2012-02-12 05:35:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
uint8 PPU::cgram_read(unsigned addr) {
|
Update to v094r05 release.
byuu says:
Commands can be prefixed with: (cpu|smp|ppu|dsp|apu|vram|oam|cgram)/ to
set their source. Eg "vram/hex 0800" or "smp/breakpoints.append execute
ffc0"; default is cpu.
These overlap a little bit in odd ways, but that's just the way the SNES
works: it's not a very orthogonal system. CPU is both a processor and
the main bus (ROM, RAM, WRAM, etc), APU is the shared memory by the
SMP+DSP (eg use it to catch writes from either chip); PPU probably won't
ever be used since it's broken down into three separate buses (VRAM,
OAM, CGRAM), but DSP could be useful for tracking bugs like we found in
Koushien 2 with the DSP echo buffer corrupting SMP opcodes. Technically
the PPU memory pools are only ever tripped by the CPU poking at them, as
the PPU doesn't ever write.
I now have run.for, run.to, step.for, step.to. The difference is that
run only prints the next instruction after running, whereas step prints
all of the instructions along the way as well. run.to acts the same as
"step over" here. Although it's not quite as nice, since you have to
specify the address of the next instruction.
Logging the Field/Vcounter/Hcounter on instruction listings now, good
for timing information.
Added in the tracer mask, as well as memory export, as well as
VRAM/OAM/CGRAM/SMP read/write/execute breakpoints, as well as an APU
usage map (it tracks DSP reads/writes separately, although I don't
currently have debugger callbacks on DSP accesses just yet.)
Have not hooked up actual SMP debugging just yet, but I plan to soon.
Still thinking about how I want to allow / block interleaving of
instructions (terminal output and tracing.)
So ... remaining tasks at this point:
- full SMP debugging
- CPU+SMP interleave support
- aliases
- hotkeys
- save states (will be kind of tricky ... will have to suppress
breakpoints during synchronization, or abort a save in a break event.)
- keep track of window geometry between runs
2014-02-05 11:30:08 +00:00
|
|
|
uint8 data = cgram[addr];
|
|
|
|
debugger.cgram_read(addr, data);
|
|
|
|
return data;
|
Update to v085r08 release.
byuu says:
Changelog:
- follow the Laevateinn topic to get most of it
- also added NMI, IRQ step buttons to CPU debugger
- also added trace masking + trace mask reset
- also added memory export
- cartridge loading is entirely folder-based now
FitzRoy, I'll go ahead and make a second compromise with you for v086:
I'll match the following:
/path/to/SNES.sfc/*.sfc
/path/to/NES.fc/*.prg, *.chr (split format)
/path/to/NES.fc/*.fc (merged format)
/path/to/GB.gb/*.gb
/path/to/GBC.gbc/*.gbc
Condition will be that there can only be one of each file. If there's
more than one, it'll abort. That lets me name my ROMs as
"Game.fc/Game.fc", and you can name yours as "Game.fc/cartridge.prg,
cartridge.chr". Or whatever you want.
We'll just go with that, see what fares out as the most popular, and
then restrict it back to that method.
The folder must have the .fc, etc extension though. That will be how we
avoid false-positive folder matches.
[Editor's note - the Laevateinn topic mentions these changes for
v085r08:
Added SMP/PPU breakpoints, SMP debugger, SMP stepping / tracing,
memory editing on APU-bus / VRAM / OAM / CGRAM, save state menu,
WRAM mirroring on breakpoints, protected MMIO memory regions
(otherwise, viewing $002100 could crash your game.)
Major missing components:
- trace mask
- trace mask clear / usage map clear
- window geometry caching / sizing improvements
- VRAM viewer
- properties viewer
- working memory export button
The rest will most likely appear after v086 is released.
]
2012-02-12 05:35:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void PPU::cgram_write(unsigned addr, uint8 data) {
|
|
|
|
cgram[addr] = data;
|
Update to v094r05 release.
byuu says:
Commands can be prefixed with: (cpu|smp|ppu|dsp|apu|vram|oam|cgram)/ to
set their source. Eg "vram/hex 0800" or "smp/breakpoints.append execute
ffc0"; default is cpu.
These overlap a little bit in odd ways, but that's just the way the SNES
works: it's not a very orthogonal system. CPU is both a processor and
the main bus (ROM, RAM, WRAM, etc), APU is the shared memory by the
SMP+DSP (eg use it to catch writes from either chip); PPU probably won't
ever be used since it's broken down into three separate buses (VRAM,
OAM, CGRAM), but DSP could be useful for tracking bugs like we found in
Koushien 2 with the DSP echo buffer corrupting SMP opcodes. Technically
the PPU memory pools are only ever tripped by the CPU poking at them, as
the PPU doesn't ever write.
I now have run.for, run.to, step.for, step.to. The difference is that
run only prints the next instruction after running, whereas step prints
all of the instructions along the way as well. run.to acts the same as
"step over" here. Although it's not quite as nice, since you have to
specify the address of the next instruction.
Logging the Field/Vcounter/Hcounter on instruction listings now, good
for timing information.
Added in the tracer mask, as well as memory export, as well as
VRAM/OAM/CGRAM/SMP read/write/execute breakpoints, as well as an APU
usage map (it tracks DSP reads/writes separately, although I don't
currently have debugger callbacks on DSP accesses just yet.)
Have not hooked up actual SMP debugging just yet, but I plan to soon.
Still thinking about how I want to allow / block interleaving of
instructions (terminal output and tracing.)
So ... remaining tasks at this point:
- full SMP debugging
- CPU+SMP interleave support
- aliases
- hotkeys
- save states (will be kind of tricky ... will have to suppress
breakpoints during synchronization, or abort a save in a break event.)
- keep track of window geometry between runs
2014-02-05 11:30:08 +00:00
|
|
|
debugger.cgram_write(addr, data);
|
Update to v085r08 release.
byuu says:
Changelog:
- follow the Laevateinn topic to get most of it
- also added NMI, IRQ step buttons to CPU debugger
- also added trace masking + trace mask reset
- also added memory export
- cartridge loading is entirely folder-based now
FitzRoy, I'll go ahead and make a second compromise with you for v086:
I'll match the following:
/path/to/SNES.sfc/*.sfc
/path/to/NES.fc/*.prg, *.chr (split format)
/path/to/NES.fc/*.fc (merged format)
/path/to/GB.gb/*.gb
/path/to/GBC.gbc/*.gbc
Condition will be that there can only be one of each file. If there's
more than one, it'll abort. That lets me name my ROMs as
"Game.fc/Game.fc", and you can name yours as "Game.fc/cartridge.prg,
cartridge.chr". Or whatever you want.
We'll just go with that, see what fares out as the most popular, and
then restrict it back to that method.
The folder must have the .fc, etc extension though. That will be how we
avoid false-positive folder matches.
[Editor's note - the Laevateinn topic mentions these changes for
v085r08:
Added SMP/PPU breakpoints, SMP debugger, SMP stepping / tracing,
memory editing on APU-bus / VRAM / OAM / CGRAM, save state menu,
WRAM mirroring on breakpoints, protected MMIO memory regions
(otherwise, viewing $002100 could crash your game.)
Major missing components:
- trace mask
- trace mask clear / usage map clear
- window geometry caching / sizing improvements
- VRAM viewer
- properties viewer
- working memory export button
The rest will most likely appear after v086 is released.
]
2012-02-12 05:35:40 +00:00
|
|
|
}
|
|
|
|
|
2010-08-09 13:28:56 +00:00
|
|
|
void PPU::mmio_update_video_mode() {
|
|
|
|
switch(regs.bgmode) {
|
2013-05-05 09:21:30 +00:00
|
|
|
case 0:
|
|
|
|
bg1.regs.mode = Background::Mode::BPP2; bg1.regs.priority0 = 8; bg1.regs.priority1 = 11;
|
|
|
|
bg2.regs.mode = Background::Mode::BPP2; bg2.regs.priority0 = 7; bg2.regs.priority1 = 10;
|
|
|
|
bg3.regs.mode = Background::Mode::BPP2; bg3.regs.priority0 = 2; bg3.regs.priority1 = 5;
|
|
|
|
bg4.regs.mode = Background::Mode::BPP2; bg4.regs.priority0 = 1; bg4.regs.priority1 = 4;
|
|
|
|
sprite.regs.priority0 = 3; sprite.regs.priority1 = 6; sprite.regs.priority2 = 9; sprite.regs.priority3 = 12;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
bg1.regs.mode = Background::Mode::BPP4;
|
|
|
|
bg2.regs.mode = Background::Mode::BPP4;
|
|
|
|
bg3.regs.mode = Background::Mode::BPP2;
|
|
|
|
bg4.regs.mode = Background::Mode::Inactive;
|
|
|
|
if(regs.bg3_priority) {
|
|
|
|
bg1.regs.priority0 = 5; bg1.regs.priority1 = 8;
|
|
|
|
bg2.regs.priority0 = 4; bg2.regs.priority1 = 7;
|
|
|
|
bg3.regs.priority0 = 1; bg3.regs.priority1 = 10;
|
|
|
|
sprite.regs.priority0 = 2; sprite.regs.priority1 = 3; sprite.regs.priority2 = 6; sprite.regs.priority3 = 9;
|
|
|
|
} else {
|
|
|
|
bg1.regs.priority0 = 6; bg1.regs.priority1 = 9;
|
|
|
|
bg2.regs.priority0 = 5; bg2.regs.priority1 = 8;
|
|
|
|
bg3.regs.priority0 = 1; bg3.regs.priority1 = 3;
|
|
|
|
sprite.regs.priority0 = 2; sprite.regs.priority1 = 4; sprite.regs.priority2 = 7; sprite.regs.priority3 = 10;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
bg1.regs.mode = Background::Mode::BPP4;
|
|
|
|
bg2.regs.mode = Background::Mode::BPP4;
|
|
|
|
bg3.regs.mode = Background::Mode::Inactive;
|
|
|
|
bg4.regs.mode = Background::Mode::Inactive;
|
|
|
|
bg1.regs.priority0 = 3; bg1.regs.priority1 = 7;
|
|
|
|
bg2.regs.priority0 = 1; bg2.regs.priority1 = 5;
|
|
|
|
sprite.regs.priority0 = 2; sprite.regs.priority1 = 4; sprite.regs.priority2 = 6; sprite.regs.priority3 = 8;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 3:
|
|
|
|
bg1.regs.mode = Background::Mode::BPP8;
|
|
|
|
bg2.regs.mode = Background::Mode::BPP4;
|
|
|
|
bg3.regs.mode = Background::Mode::Inactive;
|
|
|
|
bg4.regs.mode = Background::Mode::Inactive;
|
|
|
|
bg1.regs.priority0 = 3; bg1.regs.priority1 = 7;
|
|
|
|
bg2.regs.priority0 = 1; bg2.regs.priority1 = 5;
|
|
|
|
sprite.regs.priority0 = 2; sprite.regs.priority1 = 4; sprite.regs.priority2 = 6; sprite.regs.priority3 = 8;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 4:
|
|
|
|
bg1.regs.mode = Background::Mode::BPP8;
|
|
|
|
bg2.regs.mode = Background::Mode::BPP2;
|
|
|
|
bg3.regs.mode = Background::Mode::Inactive;
|
|
|
|
bg4.regs.mode = Background::Mode::Inactive;
|
|
|
|
bg1.regs.priority0 = 3; bg1.regs.priority1 = 7;
|
|
|
|
bg2.regs.priority0 = 1; bg2.regs.priority1 = 5;
|
|
|
|
sprite.regs.priority0 = 2; sprite.regs.priority1 = 4; sprite.regs.priority2 = 6; sprite.regs.priority3 = 8;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 5:
|
|
|
|
bg1.regs.mode = Background::Mode::BPP4;
|
|
|
|
bg2.regs.mode = Background::Mode::BPP2;
|
|
|
|
bg3.regs.mode = Background::Mode::Inactive;
|
|
|
|
bg4.regs.mode = Background::Mode::Inactive;
|
|
|
|
bg1.regs.priority0 = 3; bg1.regs.priority1 = 7;
|
|
|
|
bg2.regs.priority0 = 1; bg2.regs.priority1 = 5;
|
|
|
|
sprite.regs.priority0 = 2; sprite.regs.priority1 = 4; sprite.regs.priority2 = 6; sprite.regs.priority3 = 8;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 6:
|
|
|
|
bg1.regs.mode = Background::Mode::BPP4;
|
|
|
|
bg2.regs.mode = Background::Mode::Inactive;
|
|
|
|
bg3.regs.mode = Background::Mode::Inactive;
|
|
|
|
bg4.regs.mode = Background::Mode::Inactive;
|
|
|
|
bg1.regs.priority0 = 2; bg1.regs.priority1 = 5;
|
|
|
|
sprite.regs.priority0 = 1; sprite.regs.priority1 = 3; sprite.regs.priority2 = 4; sprite.regs.priority3 = 6;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 7:
|
|
|
|
if(regs.mode7_extbg == false) {
|
|
|
|
bg1.regs.mode = Background::Mode::Mode7;
|
|
|
|
bg2.regs.mode = Background::Mode::Inactive;
|
2010-08-09 13:28:56 +00:00
|
|
|
bg3.regs.mode = Background::Mode::Inactive;
|
|
|
|
bg4.regs.mode = Background::Mode::Inactive;
|
2013-05-05 09:21:30 +00:00
|
|
|
bg1.regs.priority0 = 2; bg1.regs.priority1 = 2;
|
|
|
|
sprite.regs.priority0 = 1; sprite.regs.priority1 = 3; sprite.regs.priority2 = 4; sprite.regs.priority3 = 5;
|
|
|
|
} else {
|
|
|
|
bg1.regs.mode = Background::Mode::Mode7;
|
|
|
|
bg2.regs.mode = Background::Mode::Mode7;
|
2010-08-09 13:28:56 +00:00
|
|
|
bg3.regs.mode = Background::Mode::Inactive;
|
|
|
|
bg4.regs.mode = Background::Mode::Inactive;
|
2013-05-05 09:21:30 +00:00
|
|
|
bg1.regs.priority0 = 3; bg1.regs.priority1 = 3;
|
2010-08-09 13:28:56 +00:00
|
|
|
bg2.regs.priority0 = 1; bg2.regs.priority1 = 5;
|
2013-05-05 09:21:30 +00:00
|
|
|
sprite.regs.priority0 = 2; sprite.regs.priority1 = 4; sprite.regs.priority2 = 6; sprite.regs.priority3 = 7;
|
|
|
|
}
|
|
|
|
break;
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//INIDISP
|
|
|
|
void PPU::mmio_w2100(uint8 data) {
|
Update to v074r11 release.
byuu says:
Changelog:
- debugger compiles on all three profiles
- libsnes compiles on all three platforms (no API changes to libsnes)
- memory.cpp : namespace memory removed (wram -> cpu, apuram -> smp,
vram, oam, cgram -> ppu)
- sa1.cpp : namespace memory removed (SA-1 specific functions merged
inline to SA1::bus_read,write)
- GameBoy: added serial link support with interrupts and proper 8192hz
timing, but obviously it acts as if no other GB is connected to it
- GameBoy: added STAT OAM interrupt, and better STAT d1,d0 mode values
- UI: since Qt is dead, I've renamed the config files back to bsnes.cfg
and bsnes-geometry.cfg
- SA1: IRAM was not syncing to CPU on SA-1 side
- PPU/Accuracy and PPU/Performance needed Sprite oam renamed to Sprite
sprite; so that I could add uint8 oam[544]
- makes more sense anyway, OAM = object attribute memory, obj or
sprite are better names for Sprite rendering class
- more cleanup
2011-01-24 09:03:17 +00:00
|
|
|
if(regs.display_disable && vcounter() == (!regs.overscan ? 225 : 240)) sprite.address_reset();
|
Update to v068r12 release.
(there was no r11 release posted to the WIP thread)
byuu says:
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-04 03:36:03 +00:00
|
|
|
regs.display_disable = data & 0x80;
|
2010-08-09 13:28:56 +00:00
|
|
|
regs.display_brightness = data & 0x0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
//OBSEL
|
|
|
|
void PPU::mmio_w2101(uint8 data) {
|
Update to v074r11 release.
byuu says:
Changelog:
- debugger compiles on all three profiles
- libsnes compiles on all three platforms (no API changes to libsnes)
- memory.cpp : namespace memory removed (wram -> cpu, apuram -> smp,
vram, oam, cgram -> ppu)
- sa1.cpp : namespace memory removed (SA-1 specific functions merged
inline to SA1::bus_read,write)
- GameBoy: added serial link support with interrupts and proper 8192hz
timing, but obviously it acts as if no other GB is connected to it
- GameBoy: added STAT OAM interrupt, and better STAT d1,d0 mode values
- UI: since Qt is dead, I've renamed the config files back to bsnes.cfg
and bsnes-geometry.cfg
- SA1: IRAM was not syncing to CPU on SA-1 side
- PPU/Accuracy and PPU/Performance needed Sprite oam renamed to Sprite
sprite; so that I could add uint8 oam[544]
- makes more sense anyway, OAM = object attribute memory, obj or
sprite are better names for Sprite rendering class
- more cleanup
2011-01-24 09:03:17 +00:00
|
|
|
sprite.regs.base_size = (data >> 5) & 7;
|
|
|
|
sprite.regs.nameselect = (data >> 3) & 3;
|
|
|
|
sprite.regs.tiledata_addr = (data & 3) << 14;
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//OAMADDL
|
|
|
|
void PPU::mmio_w2102(uint8 data) {
|
2010-09-24 13:15:21 +00:00
|
|
|
regs.oam_baseaddr = (regs.oam_baseaddr & 0x0200) | (data << 1);
|
Update to v074r11 release.
byuu says:
Changelog:
- debugger compiles on all three profiles
- libsnes compiles on all three platforms (no API changes to libsnes)
- memory.cpp : namespace memory removed (wram -> cpu, apuram -> smp,
vram, oam, cgram -> ppu)
- sa1.cpp : namespace memory removed (SA-1 specific functions merged
inline to SA1::bus_read,write)
- GameBoy: added serial link support with interrupts and proper 8192hz
timing, but obviously it acts as if no other GB is connected to it
- GameBoy: added STAT OAM interrupt, and better STAT d1,d0 mode values
- UI: since Qt is dead, I've renamed the config files back to bsnes.cfg
and bsnes-geometry.cfg
- SA1: IRAM was not syncing to CPU on SA-1 side
- PPU/Accuracy and PPU/Performance needed Sprite oam renamed to Sprite
sprite; so that I could add uint8 oam[544]
- makes more sense anyway, OAM = object attribute memory, obj or
sprite are better names for Sprite rendering class
- more cleanup
2011-01-24 09:03:17 +00:00
|
|
|
sprite.address_reset();
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//OAMADDH
|
|
|
|
void PPU::mmio_w2103(uint8 data) {
|
|
|
|
regs.oam_priority = data & 0x80;
|
2010-09-24 13:15:21 +00:00
|
|
|
regs.oam_baseaddr = ((data & 0x01) << 9) | (regs.oam_baseaddr & 0x01fe);
|
Update to v074r11 release.
byuu says:
Changelog:
- debugger compiles on all three profiles
- libsnes compiles on all three platforms (no API changes to libsnes)
- memory.cpp : namespace memory removed (wram -> cpu, apuram -> smp,
vram, oam, cgram -> ppu)
- sa1.cpp : namespace memory removed (SA-1 specific functions merged
inline to SA1::bus_read,write)
- GameBoy: added serial link support with interrupts and proper 8192hz
timing, but obviously it acts as if no other GB is connected to it
- GameBoy: added STAT OAM interrupt, and better STAT d1,d0 mode values
- UI: since Qt is dead, I've renamed the config files back to bsnes.cfg
and bsnes-geometry.cfg
- SA1: IRAM was not syncing to CPU on SA-1 side
- PPU/Accuracy and PPU/Performance needed Sprite oam renamed to Sprite
sprite; so that I could add uint8 oam[544]
- makes more sense anyway, OAM = object attribute memory, obj or
sprite are better names for Sprite rendering class
- more cleanup
2011-01-24 09:03:17 +00:00
|
|
|
sprite.address_reset();
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//OAMDATA
|
|
|
|
void PPU::mmio_w2104(uint8 data) {
|
2010-09-24 13:15:21 +00:00
|
|
|
bool latch = regs.oam_addr & 1;
|
|
|
|
uint10 addr = regs.oam_addr++;
|
|
|
|
if(regs.display_disable == false && vcounter() < (!regs.overscan ? 225 : 240)) addr = regs.oam_iaddr;
|
|
|
|
if(addr & 0x0200) addr &= 0x021f;
|
2010-08-09 13:28:56 +00:00
|
|
|
|
2010-09-24 13:15:21 +00:00
|
|
|
if(latch == 0) regs.oam_latchdata = data;
|
|
|
|
if(addr & 0x0200) {
|
Update to v085r08 release.
byuu says:
Changelog:
- follow the Laevateinn topic to get most of it
- also added NMI, IRQ step buttons to CPU debugger
- also added trace masking + trace mask reset
- also added memory export
- cartridge loading is entirely folder-based now
FitzRoy, I'll go ahead and make a second compromise with you for v086:
I'll match the following:
/path/to/SNES.sfc/*.sfc
/path/to/NES.fc/*.prg, *.chr (split format)
/path/to/NES.fc/*.fc (merged format)
/path/to/GB.gb/*.gb
/path/to/GBC.gbc/*.gbc
Condition will be that there can only be one of each file. If there's
more than one, it'll abort. That lets me name my ROMs as
"Game.fc/Game.fc", and you can name yours as "Game.fc/cartridge.prg,
cartridge.chr". Or whatever you want.
We'll just go with that, see what fares out as the most popular, and
then restrict it back to that method.
The folder must have the .fc, etc extension though. That will be how we
avoid false-positive folder matches.
[Editor's note - the Laevateinn topic mentions these changes for
v085r08:
Added SMP/PPU breakpoints, SMP debugger, SMP stepping / tracing,
memory editing on APU-bus / VRAM / OAM / CGRAM, save state menu,
WRAM mirroring on breakpoints, protected MMIO memory regions
(otherwise, viewing $002100 could crash your game.)
Major missing components:
- trace mask
- trace mask clear / usage map clear
- window geometry caching / sizing improvements
- VRAM viewer
- properties viewer
- working memory export button
The rest will most likely appear after v086 is released.
]
2012-02-12 05:35:40 +00:00
|
|
|
oam_write(addr, data);
|
2010-09-24 13:15:21 +00:00
|
|
|
} else if(latch == 1) {
|
Update to v085r08 release.
byuu says:
Changelog:
- follow the Laevateinn topic to get most of it
- also added NMI, IRQ step buttons to CPU debugger
- also added trace masking + trace mask reset
- also added memory export
- cartridge loading is entirely folder-based now
FitzRoy, I'll go ahead and make a second compromise with you for v086:
I'll match the following:
/path/to/SNES.sfc/*.sfc
/path/to/NES.fc/*.prg, *.chr (split format)
/path/to/NES.fc/*.fc (merged format)
/path/to/GB.gb/*.gb
/path/to/GBC.gbc/*.gbc
Condition will be that there can only be one of each file. If there's
more than one, it'll abort. That lets me name my ROMs as
"Game.fc/Game.fc", and you can name yours as "Game.fc/cartridge.prg,
cartridge.chr". Or whatever you want.
We'll just go with that, see what fares out as the most popular, and
then restrict it back to that method.
The folder must have the .fc, etc extension though. That will be how we
avoid false-positive folder matches.
[Editor's note - the Laevateinn topic mentions these changes for
v085r08:
Added SMP/PPU breakpoints, SMP debugger, SMP stepping / tracing,
memory editing on APU-bus / VRAM / OAM / CGRAM, save state menu,
WRAM mirroring on breakpoints, protected MMIO memory regions
(otherwise, viewing $002100 could crash your game.)
Major missing components:
- trace mask
- trace mask clear / usage map clear
- window geometry caching / sizing improvements
- VRAM viewer
- properties viewer
- working memory export button
The rest will most likely appear after v086 is released.
]
2012-02-12 05:35:40 +00:00
|
|
|
oam_write((addr & ~1) + 0, regs.oam_latchdata);
|
|
|
|
oam_write((addr & ~1) + 1, data);
|
2010-09-24 13:15:21 +00:00
|
|
|
}
|
Update to v074r11 release.
byuu says:
Changelog:
- debugger compiles on all three profiles
- libsnes compiles on all three platforms (no API changes to libsnes)
- memory.cpp : namespace memory removed (wram -> cpu, apuram -> smp,
vram, oam, cgram -> ppu)
- sa1.cpp : namespace memory removed (SA-1 specific functions merged
inline to SA1::bus_read,write)
- GameBoy: added serial link support with interrupts and proper 8192hz
timing, but obviously it acts as if no other GB is connected to it
- GameBoy: added STAT OAM interrupt, and better STAT d1,d0 mode values
- UI: since Qt is dead, I've renamed the config files back to bsnes.cfg
and bsnes-geometry.cfg
- SA1: IRAM was not syncing to CPU on SA-1 side
- PPU/Accuracy and PPU/Performance needed Sprite oam renamed to Sprite
sprite; so that I could add uint8 oam[544]
- makes more sense anyway, OAM = object attribute memory, obj or
sprite are better names for Sprite rendering class
- more cleanup
2011-01-24 09:03:17 +00:00
|
|
|
sprite.set_first_sprite();
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//BGMODE
|
|
|
|
void PPU::mmio_w2105(uint8 data) {
|
|
|
|
bg4.regs.tile_size = (data & 0x80);
|
|
|
|
bg3.regs.tile_size = (data & 0x40);
|
|
|
|
bg2.regs.tile_size = (data & 0x20);
|
|
|
|
bg1.regs.tile_size = (data & 0x10);
|
|
|
|
regs.bg3_priority = (data & 0x08);
|
|
|
|
regs.bgmode = (data & 0x07);
|
|
|
|
mmio_update_video_mode();
|
|
|
|
}
|
|
|
|
|
|
|
|
//MOSAIC
|
|
|
|
void PPU::mmio_w2106(uint8 data) {
|
|
|
|
unsigned mosaic_size = (data >> 4) & 15;
|
|
|
|
bg4.regs.mosaic = (data & 0x08 ? mosaic_size : 0);
|
|
|
|
bg3.regs.mosaic = (data & 0x04 ? mosaic_size : 0);
|
|
|
|
bg2.regs.mosaic = (data & 0x02 ? mosaic_size : 0);
|
|
|
|
bg1.regs.mosaic = (data & 0x01 ? mosaic_size : 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
//BG1SC
|
|
|
|
void PPU::mmio_w2107(uint8 data) {
|
|
|
|
bg1.regs.screen_addr = (data & 0x7c) << 9;
|
|
|
|
bg1.regs.screen_size = data & 3;
|
|
|
|
}
|
|
|
|
|
|
|
|
//BG2SC
|
|
|
|
void PPU::mmio_w2108(uint8 data) {
|
|
|
|
bg2.regs.screen_addr = (data & 0x7c) << 9;
|
|
|
|
bg2.regs.screen_size = data & 3;
|
|
|
|
}
|
|
|
|
|
|
|
|
//BG3SC
|
|
|
|
void PPU::mmio_w2109(uint8 data) {
|
|
|
|
bg3.regs.screen_addr = (data & 0x7c) << 9;
|
|
|
|
bg3.regs.screen_size = data & 3;
|
|
|
|
}
|
|
|
|
|
|
|
|
//BG4SC
|
|
|
|
void PPU::mmio_w210a(uint8 data) {
|
|
|
|
bg4.regs.screen_addr = (data & 0x7c) << 9;
|
|
|
|
bg4.regs.screen_size = data & 3;
|
|
|
|
}
|
|
|
|
|
|
|
|
//BG12NBA
|
|
|
|
void PPU::mmio_w210b(uint8 data) {
|
|
|
|
bg1.regs.tiledata_addr = (data & 0x07) << 13;
|
|
|
|
bg2.regs.tiledata_addr = (data & 0x70) << 9;
|
|
|
|
}
|
|
|
|
|
|
|
|
//BG34NBA
|
|
|
|
void PPU::mmio_w210c(uint8 data) {
|
|
|
|
bg3.regs.tiledata_addr = (data & 0x07) << 13;
|
|
|
|
bg4.regs.tiledata_addr = (data & 0x70) << 9;
|
|
|
|
}
|
|
|
|
|
|
|
|
//BG1HOFS
|
|
|
|
void PPU::mmio_w210d(uint8 data) {
|
|
|
|
regs.mode7_hoffset = (data << 8) | regs.mode7_latchdata;
|
|
|
|
regs.mode7_latchdata = data;
|
|
|
|
|
|
|
|
bg1.regs.hoffset = (data << 8) | (regs.bgofs_latchdata & ~7) | ((bg1.regs.hoffset >> 8) & 7);
|
|
|
|
regs.bgofs_latchdata = data;
|
|
|
|
}
|
|
|
|
|
|
|
|
//BG1VOFS
|
|
|
|
void PPU::mmio_w210e(uint8 data) {
|
|
|
|
regs.mode7_voffset = (data << 8) | regs.mode7_latchdata;
|
|
|
|
regs.mode7_latchdata = data;
|
|
|
|
|
|
|
|
bg1.regs.voffset = (data << 8) | regs.bgofs_latchdata;
|
|
|
|
regs.bgofs_latchdata = data;
|
|
|
|
}
|
|
|
|
|
|
|
|
//BG2HOFS
|
|
|
|
void PPU::mmio_w210f(uint8 data) {
|
|
|
|
bg2.regs.hoffset = (data << 8) | (regs.bgofs_latchdata & ~7) | ((bg2.regs.hoffset >> 8) & 7);
|
|
|
|
regs.bgofs_latchdata = data;
|
|
|
|
}
|
|
|
|
|
|
|
|
//BG2VOFS
|
|
|
|
void PPU::mmio_w2110(uint8 data) {
|
|
|
|
bg2.regs.voffset = (data << 8) | regs.bgofs_latchdata;
|
|
|
|
regs.bgofs_latchdata = data;
|
|
|
|
}
|
|
|
|
|
|
|
|
//BG3HOFS
|
|
|
|
void PPU::mmio_w2111(uint8 data) {
|
|
|
|
bg3.regs.hoffset = (data << 8) | (regs.bgofs_latchdata & ~7) | ((bg3.regs.hoffset >> 8) & 7);
|
|
|
|
regs.bgofs_latchdata = data;
|
|
|
|
}
|
|
|
|
|
|
|
|
//BG3VOFS
|
|
|
|
void PPU::mmio_w2112(uint8 data) {
|
|
|
|
bg3.regs.voffset = (data << 8) | regs.bgofs_latchdata;
|
|
|
|
regs.bgofs_latchdata = data;
|
|
|
|
}
|
|
|
|
|
|
|
|
//BG4HOFS
|
|
|
|
void PPU::mmio_w2113(uint8 data) {
|
|
|
|
bg4.regs.hoffset = (data << 8) | (regs.bgofs_latchdata & ~7) | ((bg4.regs.hoffset >> 8) & 7);
|
|
|
|
regs.bgofs_latchdata = data;
|
|
|
|
}
|
|
|
|
|
|
|
|
//BG4VOFS
|
|
|
|
void PPU::mmio_w2114(uint8 data) {
|
|
|
|
bg4.regs.voffset = (data << 8) | regs.bgofs_latchdata;
|
|
|
|
regs.bgofs_latchdata = data;
|
|
|
|
}
|
|
|
|
|
|
|
|
//VMAIN
|
|
|
|
void PPU::mmio_w2115(uint8 data) {
|
|
|
|
regs.vram_incmode = data & 0x80;
|
|
|
|
regs.vram_mapping = (data >> 2) & 3;
|
|
|
|
switch(data & 3) {
|
2013-05-05 09:21:30 +00:00
|
|
|
case 0: regs.vram_incsize = 1; break;
|
|
|
|
case 1: regs.vram_incsize = 32; break;
|
|
|
|
case 2: regs.vram_incsize = 128; break;
|
|
|
|
case 3: regs.vram_incsize = 128; break;
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//VMADDL
|
|
|
|
void PPU::mmio_w2116(uint8 data) {
|
|
|
|
regs.vram_addr &= 0xff00;
|
|
|
|
regs.vram_addr |= (data << 0);
|
|
|
|
uint16 addr = get_vram_address();
|
|
|
|
regs.vram_readbuffer = vram_read(addr + 0) << 0;
|
|
|
|
regs.vram_readbuffer |= vram_read(addr + 1) << 8;
|
|
|
|
}
|
|
|
|
|
|
|
|
//VMADDH
|
|
|
|
void PPU::mmio_w2117(uint8 data) {
|
|
|
|
regs.vram_addr &= 0x00ff;
|
|
|
|
regs.vram_addr |= (data << 8);
|
|
|
|
uint16 addr = get_vram_address();
|
|
|
|
regs.vram_readbuffer = vram_read(addr + 0) << 0;
|
|
|
|
regs.vram_readbuffer |= vram_read(addr + 1) << 8;
|
|
|
|
}
|
|
|
|
|
|
|
|
//VMDATAL
|
|
|
|
void PPU::mmio_w2118(uint8 data) {
|
|
|
|
uint16 addr = get_vram_address() + 0;
|
|
|
|
vram_write(addr, data);
|
|
|
|
if(regs.vram_incmode == 0) regs.vram_addr += regs.vram_incsize;
|
|
|
|
}
|
|
|
|
|
|
|
|
//VMDATAH
|
|
|
|
void PPU::mmio_w2119(uint8 data) {
|
|
|
|
uint16 addr = get_vram_address() + 1;
|
|
|
|
vram_write(addr, data);
|
|
|
|
if(regs.vram_incmode == 1) regs.vram_addr += regs.vram_incsize;
|
|
|
|
}
|
|
|
|
|
|
|
|
//M7SEL
|
|
|
|
void PPU::mmio_w211a(uint8 data) {
|
|
|
|
regs.mode7_repeat = (data >> 6) & 3;
|
|
|
|
regs.mode7_vflip = data & 0x02;
|
|
|
|
regs.mode7_hflip = data & 0x01;
|
|
|
|
}
|
|
|
|
|
|
|
|
//M7A
|
|
|
|
void PPU::mmio_w211b(uint8 data) {
|
|
|
|
regs.m7a = (data << 8) | regs.mode7_latchdata;
|
|
|
|
regs.mode7_latchdata = data;
|
|
|
|
}
|
|
|
|
|
|
|
|
//M7B
|
|
|
|
void PPU::mmio_w211c(uint8 data) {
|
|
|
|
regs.m7b = (data << 8) | regs.mode7_latchdata;
|
|
|
|
regs.mode7_latchdata = data;
|
|
|
|
}
|
|
|
|
|
|
|
|
//M7C
|
|
|
|
void PPU::mmio_w211d(uint8 data) {
|
|
|
|
regs.m7c = (data << 8) | regs.mode7_latchdata;
|
|
|
|
regs.mode7_latchdata = data;
|
|
|
|
}
|
|
|
|
|
|
|
|
//M7D
|
|
|
|
void PPU::mmio_w211e(uint8 data) {
|
|
|
|
regs.m7d = (data << 8) | regs.mode7_latchdata;
|
|
|
|
regs.mode7_latchdata = data;
|
|
|
|
}
|
|
|
|
|
|
|
|
//M7X
|
|
|
|
void PPU::mmio_w211f(uint8 data) {
|
|
|
|
regs.m7x = (data << 8) | regs.mode7_latchdata;
|
|
|
|
regs.mode7_latchdata = data;
|
|
|
|
}
|
|
|
|
|
|
|
|
//M7Y
|
|
|
|
void PPU::mmio_w2120(uint8 data) {
|
|
|
|
regs.m7y = (data << 8) | regs.mode7_latchdata;
|
|
|
|
regs.mode7_latchdata = data;
|
|
|
|
}
|
|
|
|
|
|
|
|
//CGADD
|
|
|
|
void PPU::mmio_w2121(uint8 data) {
|
|
|
|
regs.cgram_addr = data << 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
//CGDATA
|
|
|
|
void PPU::mmio_w2122(uint8 data) {
|
2010-09-24 13:15:21 +00:00
|
|
|
bool latch = regs.cgram_addr & 1;
|
|
|
|
uint9 addr = regs.cgram_addr++;
|
|
|
|
if(regs.display_disable == false
|
|
|
|
&& vcounter() > 0 && vcounter() < (!regs.overscan ? 225 : 240)
|
|
|
|
&& hcounter() >= 88 && hcounter() < 1096
|
|
|
|
) addr = regs.cgram_iaddr;
|
|
|
|
|
|
|
|
if(latch == 0) {
|
2010-08-09 13:28:56 +00:00
|
|
|
regs.cgram_latchdata = data;
|
|
|
|
} else {
|
Update to v085r08 release.
byuu says:
Changelog:
- follow the Laevateinn topic to get most of it
- also added NMI, IRQ step buttons to CPU debugger
- also added trace masking + trace mask reset
- also added memory export
- cartridge loading is entirely folder-based now
FitzRoy, I'll go ahead and make a second compromise with you for v086:
I'll match the following:
/path/to/SNES.sfc/*.sfc
/path/to/NES.fc/*.prg, *.chr (split format)
/path/to/NES.fc/*.fc (merged format)
/path/to/GB.gb/*.gb
/path/to/GBC.gbc/*.gbc
Condition will be that there can only be one of each file. If there's
more than one, it'll abort. That lets me name my ROMs as
"Game.fc/Game.fc", and you can name yours as "Game.fc/cartridge.prg,
cartridge.chr". Or whatever you want.
We'll just go with that, see what fares out as the most popular, and
then restrict it back to that method.
The folder must have the .fc, etc extension though. That will be how we
avoid false-positive folder matches.
[Editor's note - the Laevateinn topic mentions these changes for
v085r08:
Added SMP/PPU breakpoints, SMP debugger, SMP stepping / tracing,
memory editing on APU-bus / VRAM / OAM / CGRAM, save state menu,
WRAM mirroring on breakpoints, protected MMIO memory regions
(otherwise, viewing $002100 could crash your game.)
Major missing components:
- trace mask
- trace mask clear / usage map clear
- window geometry caching / sizing improvements
- VRAM viewer
- properties viewer
- working memory export button
The rest will most likely appear after v086 is released.
]
2012-02-12 05:35:40 +00:00
|
|
|
cgram_write((addr & ~1) + 0, regs.cgram_latchdata);
|
|
|
|
cgram_write((addr & ~1) + 1, data & 0x7f);
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//W12SEL
|
|
|
|
void PPU::mmio_w2123(uint8 data) {
|
|
|
|
window.regs.bg2_two_enable = data & 0x80;
|
|
|
|
window.regs.bg2_two_invert = data & 0x40;
|
|
|
|
window.regs.bg2_one_enable = data & 0x20;
|
|
|
|
window.regs.bg2_one_invert = data & 0x10;
|
|
|
|
window.regs.bg1_two_enable = data & 0x08;
|
|
|
|
window.regs.bg1_two_invert = data & 0x04;
|
|
|
|
window.regs.bg1_one_enable = data & 0x02;
|
|
|
|
window.regs.bg1_one_invert = data & 0x01;
|
|
|
|
}
|
|
|
|
|
|
|
|
//W34SEL
|
|
|
|
void PPU::mmio_w2124(uint8 data) {
|
|
|
|
window.regs.bg4_two_enable = data & 0x80;
|
|
|
|
window.regs.bg4_two_invert = data & 0x40;
|
|
|
|
window.regs.bg4_one_enable = data & 0x20;
|
|
|
|
window.regs.bg4_one_invert = data & 0x10;
|
|
|
|
window.regs.bg3_two_enable = data & 0x08;
|
|
|
|
window.regs.bg3_two_invert = data & 0x04;
|
|
|
|
window.regs.bg3_one_enable = data & 0x02;
|
|
|
|
window.regs.bg3_one_invert = data & 0x01;
|
|
|
|
}
|
|
|
|
|
|
|
|
//WOBJSEL
|
|
|
|
void PPU::mmio_w2125(uint8 data) {
|
|
|
|
window.regs.col_two_enable = data & 0x80;
|
|
|
|
window.regs.col_two_invert = data & 0x40;
|
|
|
|
window.regs.col_one_enable = data & 0x20;
|
|
|
|
window.regs.col_one_invert = data & 0x10;
|
|
|
|
window.regs.oam_two_enable = data & 0x08;
|
|
|
|
window.regs.oam_two_invert = data & 0x04;
|
|
|
|
window.regs.oam_one_enable = data & 0x02;
|
|
|
|
window.regs.oam_one_invert = data & 0x01;
|
|
|
|
}
|
|
|
|
|
|
|
|
//WH0
|
|
|
|
void PPU::mmio_w2126(uint8 data) {
|
|
|
|
window.regs.one_left = data;
|
|
|
|
}
|
|
|
|
|
|
|
|
//WH1
|
|
|
|
void PPU::mmio_w2127(uint8 data) {
|
|
|
|
window.regs.one_right = data;
|
|
|
|
}
|
|
|
|
|
|
|
|
//WH2
|
|
|
|
void PPU::mmio_w2128(uint8 data) {
|
|
|
|
window.regs.two_left = data;
|
|
|
|
}
|
|
|
|
|
|
|
|
//WH3
|
|
|
|
void PPU::mmio_w2129(uint8 data) {
|
|
|
|
window.regs.two_right = data;
|
|
|
|
}
|
|
|
|
|
|
|
|
//WBGLOG
|
|
|
|
void PPU::mmio_w212a(uint8 data) {
|
|
|
|
window.regs.bg4_mask = (data >> 6) & 3;
|
|
|
|
window.regs.bg3_mask = (data >> 4) & 3;
|
|
|
|
window.regs.bg2_mask = (data >> 2) & 3;
|
|
|
|
window.regs.bg1_mask = (data >> 0) & 3;
|
|
|
|
}
|
|
|
|
|
|
|
|
//WOBJLOG
|
|
|
|
void PPU::mmio_w212b(uint8 data) {
|
|
|
|
window.regs.col_mask = (data >> 2) & 3;
|
|
|
|
window.regs.oam_mask = (data >> 0) & 3;
|
|
|
|
}
|
|
|
|
|
|
|
|
//TM
|
|
|
|
void PPU::mmio_w212c(uint8 data) {
|
Update to v074r11 release.
byuu says:
Changelog:
- debugger compiles on all three profiles
- libsnes compiles on all three platforms (no API changes to libsnes)
- memory.cpp : namespace memory removed (wram -> cpu, apuram -> smp,
vram, oam, cgram -> ppu)
- sa1.cpp : namespace memory removed (SA-1 specific functions merged
inline to SA1::bus_read,write)
- GameBoy: added serial link support with interrupts and proper 8192hz
timing, but obviously it acts as if no other GB is connected to it
- GameBoy: added STAT OAM interrupt, and better STAT d1,d0 mode values
- UI: since Qt is dead, I've renamed the config files back to bsnes.cfg
and bsnes-geometry.cfg
- SA1: IRAM was not syncing to CPU on SA-1 side
- PPU/Accuracy and PPU/Performance needed Sprite oam renamed to Sprite
sprite; so that I could add uint8 oam[544]
- makes more sense anyway, OAM = object attribute memory, obj or
sprite are better names for Sprite rendering class
- more cleanup
2011-01-24 09:03:17 +00:00
|
|
|
sprite.regs.main_enable = data & 0x10;
|
Update to v068r12 release.
(there was no r11 release posted to the WIP thread)
byuu says:
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-04 03:36:03 +00:00
|
|
|
bg4.regs.main_enable = data & 0x08;
|
|
|
|
bg3.regs.main_enable = data & 0x04;
|
|
|
|
bg2.regs.main_enable = data & 0x02;
|
|
|
|
bg1.regs.main_enable = data & 0x01;
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//TS
|
|
|
|
void PPU::mmio_w212d(uint8 data) {
|
Update to v074r11 release.
byuu says:
Changelog:
- debugger compiles on all three profiles
- libsnes compiles on all three platforms (no API changes to libsnes)
- memory.cpp : namespace memory removed (wram -> cpu, apuram -> smp,
vram, oam, cgram -> ppu)
- sa1.cpp : namespace memory removed (SA-1 specific functions merged
inline to SA1::bus_read,write)
- GameBoy: added serial link support with interrupts and proper 8192hz
timing, but obviously it acts as if no other GB is connected to it
- GameBoy: added STAT OAM interrupt, and better STAT d1,d0 mode values
- UI: since Qt is dead, I've renamed the config files back to bsnes.cfg
and bsnes-geometry.cfg
- SA1: IRAM was not syncing to CPU on SA-1 side
- PPU/Accuracy and PPU/Performance needed Sprite oam renamed to Sprite
sprite; so that I could add uint8 oam[544]
- makes more sense anyway, OAM = object attribute memory, obj or
sprite are better names for Sprite rendering class
- more cleanup
2011-01-24 09:03:17 +00:00
|
|
|
sprite.regs.sub_enable = data & 0x10;
|
Update to v068r12 release.
(there was no r11 release posted to the WIP thread)
byuu says:
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-04 03:36:03 +00:00
|
|
|
bg4.regs.sub_enable = data & 0x08;
|
|
|
|
bg3.regs.sub_enable = data & 0x04;
|
|
|
|
bg2.regs.sub_enable = data & 0x02;
|
|
|
|
bg1.regs.sub_enable = data & 0x01;
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//TMW
|
|
|
|
void PPU::mmio_w212e(uint8 data) {
|
|
|
|
window.regs.oam_main_enable = data & 0x10;
|
|
|
|
window.regs.bg4_main_enable = data & 0x08;
|
|
|
|
window.regs.bg3_main_enable = data & 0x04;
|
|
|
|
window.regs.bg2_main_enable = data & 0x02;
|
|
|
|
window.regs.bg1_main_enable = data & 0x01;
|
|
|
|
}
|
|
|
|
|
|
|
|
//TSW
|
|
|
|
void PPU::mmio_w212f(uint8 data) {
|
|
|
|
window.regs.oam_sub_enable = data & 0x10;
|
|
|
|
window.regs.bg4_sub_enable = data & 0x08;
|
|
|
|
window.regs.bg3_sub_enable = data & 0x04;
|
|
|
|
window.regs.bg2_sub_enable = data & 0x02;
|
|
|
|
window.regs.bg1_sub_enable = data & 0x01;
|
|
|
|
}
|
|
|
|
|
|
|
|
//CGWSEL
|
|
|
|
void PPU::mmio_w2130(uint8 data) {
|
|
|
|
window.regs.col_main_mask = (data >> 6) & 3;
|
|
|
|
window.regs.col_sub_mask = (data >> 4) & 3;
|
|
|
|
screen.regs.addsub_mode = data & 0x02;
|
|
|
|
screen.regs.direct_color = data & 0x01;
|
|
|
|
}
|
|
|
|
|
|
|
|
//CGADDSUB
|
|
|
|
void PPU::mmio_w2131(uint8 data) {
|
|
|
|
screen.regs.color_mode = data & 0x80;
|
|
|
|
screen.regs.color_halve = data & 0x40;
|
|
|
|
screen.regs.back_color_enable = data & 0x20;
|
|
|
|
screen.regs.oam_color_enable = data & 0x10;
|
|
|
|
screen.regs.bg4_color_enable = data & 0x08;
|
|
|
|
screen.regs.bg3_color_enable = data & 0x04;
|
|
|
|
screen.regs.bg2_color_enable = data & 0x02;
|
|
|
|
screen.regs.bg1_color_enable = data & 0x01;
|
|
|
|
}
|
|
|
|
|
|
|
|
//COLDATA
|
|
|
|
void PPU::mmio_w2132(uint8 data) {
|
|
|
|
if(data & 0x80) screen.regs.color_b = data & 0x1f;
|
|
|
|
if(data & 0x40) screen.regs.color_g = data & 0x1f;
|
|
|
|
if(data & 0x20) screen.regs.color_r = data & 0x1f;
|
|
|
|
}
|
|
|
|
|
|
|
|
//SETINI
|
|
|
|
void PPU::mmio_w2133(uint8 data) {
|
|
|
|
regs.mode7_extbg = data & 0x40;
|
|
|
|
regs.pseudo_hires = data & 0x08;
|
|
|
|
regs.overscan = data & 0x04;
|
Update to v074r11 release.
byuu says:
Changelog:
- debugger compiles on all three profiles
- libsnes compiles on all three platforms (no API changes to libsnes)
- memory.cpp : namespace memory removed (wram -> cpu, apuram -> smp,
vram, oam, cgram -> ppu)
- sa1.cpp : namespace memory removed (SA-1 specific functions merged
inline to SA1::bus_read,write)
- GameBoy: added serial link support with interrupts and proper 8192hz
timing, but obviously it acts as if no other GB is connected to it
- GameBoy: added STAT OAM interrupt, and better STAT d1,d0 mode values
- UI: since Qt is dead, I've renamed the config files back to bsnes.cfg
and bsnes-geometry.cfg
- SA1: IRAM was not syncing to CPU on SA-1 side
- PPU/Accuracy and PPU/Performance needed Sprite oam renamed to Sprite
sprite; so that I could add uint8 oam[544]
- makes more sense anyway, OAM = object attribute memory, obj or
sprite are better names for Sprite rendering class
- more cleanup
2011-01-24 09:03:17 +00:00
|
|
|
sprite.regs.interlace = data & 0x02;
|
2010-08-09 13:28:56 +00:00
|
|
|
regs.interlace = data & 0x01;
|
|
|
|
mmio_update_video_mode();
|
|
|
|
}
|
|
|
|
|
|
|
|
//MPYL
|
|
|
|
uint8 PPU::mmio_r2134() {
|
|
|
|
unsigned result = ((int16)regs.m7a * (int8)(regs.m7b >> 8));
|
|
|
|
regs.ppu1_mdr = (result >> 0);
|
|
|
|
return regs.ppu1_mdr;
|
|
|
|
}
|
|
|
|
|
|
|
|
//MPYM
|
|
|
|
uint8 PPU::mmio_r2135() {
|
|
|
|
unsigned result = ((int16)regs.m7a * (int8)(regs.m7b >> 8));
|
|
|
|
regs.ppu1_mdr = (result >> 8);
|
|
|
|
return regs.ppu1_mdr;
|
|
|
|
}
|
|
|
|
|
|
|
|
//MPYH
|
|
|
|
uint8 PPU::mmio_r2136() {
|
|
|
|
unsigned result = ((int16)regs.m7a * (int8)(regs.m7b >> 8));
|
|
|
|
regs.ppu1_mdr = (result >> 16);
|
|
|
|
return regs.ppu1_mdr;
|
|
|
|
}
|
|
|
|
|
|
|
|
//SLHV
|
|
|
|
uint8 PPU::mmio_r2137() {
|
|
|
|
if(cpu.pio() & 0x80) latch_counters();
|
|
|
|
return cpu.regs.mdr;
|
|
|
|
}
|
|
|
|
|
|
|
|
//OAMDATAREAD
|
|
|
|
uint8 PPU::mmio_r2138() {
|
2010-09-24 13:15:21 +00:00
|
|
|
uint10 addr = regs.oam_addr++;
|
|
|
|
if(regs.display_disable == false && vcounter() < (!regs.overscan ? 225 : 240)) addr = regs.oam_iaddr;
|
|
|
|
if(addr & 0x0200) addr &= 0x021f;
|
|
|
|
|
Update to v085r08 release.
byuu says:
Changelog:
- follow the Laevateinn topic to get most of it
- also added NMI, IRQ step buttons to CPU debugger
- also added trace masking + trace mask reset
- also added memory export
- cartridge loading is entirely folder-based now
FitzRoy, I'll go ahead and make a second compromise with you for v086:
I'll match the following:
/path/to/SNES.sfc/*.sfc
/path/to/NES.fc/*.prg, *.chr (split format)
/path/to/NES.fc/*.fc (merged format)
/path/to/GB.gb/*.gb
/path/to/GBC.gbc/*.gbc
Condition will be that there can only be one of each file. If there's
more than one, it'll abort. That lets me name my ROMs as
"Game.fc/Game.fc", and you can name yours as "Game.fc/cartridge.prg,
cartridge.chr". Or whatever you want.
We'll just go with that, see what fares out as the most popular, and
then restrict it back to that method.
The folder must have the .fc, etc extension though. That will be how we
avoid false-positive folder matches.
[Editor's note - the Laevateinn topic mentions these changes for
v085r08:
Added SMP/PPU breakpoints, SMP debugger, SMP stepping / tracing,
memory editing on APU-bus / VRAM / OAM / CGRAM, save state menu,
WRAM mirroring on breakpoints, protected MMIO memory regions
(otherwise, viewing $002100 could crash your game.)
Major missing components:
- trace mask
- trace mask clear / usage map clear
- window geometry caching / sizing improvements
- VRAM viewer
- properties viewer
- working memory export button
The rest will most likely appear after v086 is released.
]
2012-02-12 05:35:40 +00:00
|
|
|
regs.ppu1_mdr = oam_read(addr);
|
Update to v074r11 release.
byuu says:
Changelog:
- debugger compiles on all three profiles
- libsnes compiles on all three platforms (no API changes to libsnes)
- memory.cpp : namespace memory removed (wram -> cpu, apuram -> smp,
vram, oam, cgram -> ppu)
- sa1.cpp : namespace memory removed (SA-1 specific functions merged
inline to SA1::bus_read,write)
- GameBoy: added serial link support with interrupts and proper 8192hz
timing, but obviously it acts as if no other GB is connected to it
- GameBoy: added STAT OAM interrupt, and better STAT d1,d0 mode values
- UI: since Qt is dead, I've renamed the config files back to bsnes.cfg
and bsnes-geometry.cfg
- SA1: IRAM was not syncing to CPU on SA-1 side
- PPU/Accuracy and PPU/Performance needed Sprite oam renamed to Sprite
sprite; so that I could add uint8 oam[544]
- makes more sense anyway, OAM = object attribute memory, obj or
sprite are better names for Sprite rendering class
- more cleanup
2011-01-24 09:03:17 +00:00
|
|
|
sprite.set_first_sprite();
|
2010-08-09 13:28:56 +00:00
|
|
|
return regs.ppu1_mdr;
|
|
|
|
}
|
|
|
|
|
|
|
|
//VMDATALREAD
|
|
|
|
uint8 PPU::mmio_r2139() {
|
|
|
|
uint16 addr = get_vram_address() + 0;
|
|
|
|
regs.ppu1_mdr = regs.vram_readbuffer >> 0;
|
|
|
|
if(regs.vram_incmode == 0) {
|
|
|
|
addr &= ~1;
|
|
|
|
regs.vram_readbuffer = vram_read(addr + 0) << 0;
|
|
|
|
regs.vram_readbuffer |= vram_read(addr + 1) << 8;
|
|
|
|
regs.vram_addr += regs.vram_incsize;
|
|
|
|
}
|
|
|
|
return regs.ppu1_mdr;
|
|
|
|
}
|
|
|
|
|
|
|
|
//VMDATAHREAD
|
|
|
|
uint8 PPU::mmio_r213a() {
|
|
|
|
uint16 addr = get_vram_address() + 1;
|
|
|
|
regs.ppu1_mdr = regs.vram_readbuffer >> 8;
|
|
|
|
if(regs.vram_incmode == 1) {
|
|
|
|
addr &= ~1;
|
|
|
|
regs.vram_readbuffer = vram_read(addr + 0) << 0;
|
|
|
|
regs.vram_readbuffer |= vram_read(addr + 1) << 8;
|
|
|
|
regs.vram_addr += regs.vram_incsize;
|
|
|
|
}
|
|
|
|
return regs.ppu1_mdr;
|
|
|
|
}
|
|
|
|
|
|
|
|
//CGDATAREAD
|
|
|
|
uint8 PPU::mmio_r213b() {
|
2010-09-24 13:15:21 +00:00
|
|
|
bool latch = regs.cgram_addr & 1;
|
|
|
|
uint9 addr = regs.cgram_addr++;
|
|
|
|
if(regs.display_disable == false
|
|
|
|
&& vcounter() > 0 && vcounter() < (!regs.overscan ? 225 : 240)
|
|
|
|
&& hcounter() >= 88 && hcounter() < 1096
|
|
|
|
) addr = regs.cgram_iaddr;
|
|
|
|
|
|
|
|
if(latch == 0) {
|
Update to v085r08 release.
byuu says:
Changelog:
- follow the Laevateinn topic to get most of it
- also added NMI, IRQ step buttons to CPU debugger
- also added trace masking + trace mask reset
- also added memory export
- cartridge loading is entirely folder-based now
FitzRoy, I'll go ahead and make a second compromise with you for v086:
I'll match the following:
/path/to/SNES.sfc/*.sfc
/path/to/NES.fc/*.prg, *.chr (split format)
/path/to/NES.fc/*.fc (merged format)
/path/to/GB.gb/*.gb
/path/to/GBC.gbc/*.gbc
Condition will be that there can only be one of each file. If there's
more than one, it'll abort. That lets me name my ROMs as
"Game.fc/Game.fc", and you can name yours as "Game.fc/cartridge.prg,
cartridge.chr". Or whatever you want.
We'll just go with that, see what fares out as the most popular, and
then restrict it back to that method.
The folder must have the .fc, etc extension though. That will be how we
avoid false-positive folder matches.
[Editor's note - the Laevateinn topic mentions these changes for
v085r08:
Added SMP/PPU breakpoints, SMP debugger, SMP stepping / tracing,
memory editing on APU-bus / VRAM / OAM / CGRAM, save state menu,
WRAM mirroring on breakpoints, protected MMIO memory regions
(otherwise, viewing $002100 could crash your game.)
Major missing components:
- trace mask
- trace mask clear / usage map clear
- window geometry caching / sizing improvements
- VRAM viewer
- properties viewer
- working memory export button
The rest will most likely appear after v086 is released.
]
2012-02-12 05:35:40 +00:00
|
|
|
regs.ppu2_mdr = cgram_read(addr);
|
2010-08-09 13:28:56 +00:00
|
|
|
} else {
|
|
|
|
regs.ppu2_mdr &= 0x80;
|
Update to v085r08 release.
byuu says:
Changelog:
- follow the Laevateinn topic to get most of it
- also added NMI, IRQ step buttons to CPU debugger
- also added trace masking + trace mask reset
- also added memory export
- cartridge loading is entirely folder-based now
FitzRoy, I'll go ahead and make a second compromise with you for v086:
I'll match the following:
/path/to/SNES.sfc/*.sfc
/path/to/NES.fc/*.prg, *.chr (split format)
/path/to/NES.fc/*.fc (merged format)
/path/to/GB.gb/*.gb
/path/to/GBC.gbc/*.gbc
Condition will be that there can only be one of each file. If there's
more than one, it'll abort. That lets me name my ROMs as
"Game.fc/Game.fc", and you can name yours as "Game.fc/cartridge.prg,
cartridge.chr". Or whatever you want.
We'll just go with that, see what fares out as the most popular, and
then restrict it back to that method.
The folder must have the .fc, etc extension though. That will be how we
avoid false-positive folder matches.
[Editor's note - the Laevateinn topic mentions these changes for
v085r08:
Added SMP/PPU breakpoints, SMP debugger, SMP stepping / tracing,
memory editing on APU-bus / VRAM / OAM / CGRAM, save state menu,
WRAM mirroring on breakpoints, protected MMIO memory regions
(otherwise, viewing $002100 could crash your game.)
Major missing components:
- trace mask
- trace mask clear / usage map clear
- window geometry caching / sizing improvements
- VRAM viewer
- properties viewer
- working memory export button
The rest will most likely appear after v086 is released.
]
2012-02-12 05:35:40 +00:00
|
|
|
regs.ppu2_mdr |= cgram_read(addr);
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
return regs.ppu2_mdr;
|
|
|
|
}
|
|
|
|
|
|
|
|
//OPHCT
|
|
|
|
uint8 PPU::mmio_r213c() {
|
|
|
|
if(regs.latch_hcounter == 0) {
|
2010-09-24 13:15:21 +00:00
|
|
|
regs.ppu2_mdr = (regs.hcounter >> 0);
|
2010-08-09 13:28:56 +00:00
|
|
|
} else {
|
|
|
|
regs.ppu2_mdr &= 0xfe;
|
|
|
|
regs.ppu2_mdr |= (regs.hcounter >> 8) & 1;
|
|
|
|
}
|
|
|
|
regs.latch_hcounter ^= 1;
|
|
|
|
return regs.ppu2_mdr;
|
|
|
|
}
|
|
|
|
|
|
|
|
//OPVCT
|
|
|
|
uint8 PPU::mmio_r213d() {
|
|
|
|
if(regs.latch_vcounter == 0) {
|
2010-09-24 13:15:21 +00:00
|
|
|
regs.ppu2_mdr = (regs.vcounter >> 0);
|
2010-08-09 13:28:56 +00:00
|
|
|
} else {
|
|
|
|
regs.ppu2_mdr &= 0xfe;
|
|
|
|
regs.ppu2_mdr |= (regs.vcounter >> 8) & 1;
|
|
|
|
}
|
|
|
|
regs.latch_vcounter ^= 1;
|
|
|
|
return regs.ppu2_mdr;
|
|
|
|
}
|
|
|
|
|
|
|
|
//STAT77
|
|
|
|
uint8 PPU::mmio_r213e() {
|
|
|
|
regs.ppu1_mdr &= 0x10;
|
Update to v074r11 release.
byuu says:
Changelog:
- debugger compiles on all three profiles
- libsnes compiles on all three platforms (no API changes to libsnes)
- memory.cpp : namespace memory removed (wram -> cpu, apuram -> smp,
vram, oam, cgram -> ppu)
- sa1.cpp : namespace memory removed (SA-1 specific functions merged
inline to SA1::bus_read,write)
- GameBoy: added serial link support with interrupts and proper 8192hz
timing, but obviously it acts as if no other GB is connected to it
- GameBoy: added STAT OAM interrupt, and better STAT d1,d0 mode values
- UI: since Qt is dead, I've renamed the config files back to bsnes.cfg
and bsnes-geometry.cfg
- SA1: IRAM was not syncing to CPU on SA-1 side
- PPU/Accuracy and PPU/Performance needed Sprite oam renamed to Sprite
sprite; so that I could add uint8 oam[544]
- makes more sense anyway, OAM = object attribute memory, obj or
sprite are better names for Sprite rendering class
- more cleanup
2011-01-24 09:03:17 +00:00
|
|
|
regs.ppu1_mdr |= sprite.regs.time_over << 7;
|
|
|
|
regs.ppu1_mdr |= sprite.regs.range_over << 6;
|
2010-08-09 13:28:56 +00:00
|
|
|
regs.ppu1_mdr |= ppu1_version & 0x0f;
|
|
|
|
return regs.ppu1_mdr;
|
|
|
|
}
|
|
|
|
|
|
|
|
//STAT78
|
|
|
|
uint8 PPU::mmio_r213f() {
|
|
|
|
regs.latch_hcounter = 0;
|
|
|
|
regs.latch_vcounter = 0;
|
|
|
|
|
|
|
|
regs.ppu2_mdr &= 0x20;
|
|
|
|
regs.ppu2_mdr |= field() << 7;
|
|
|
|
if((cpu.pio() & 0x80) == 0) {
|
|
|
|
regs.ppu2_mdr |= 0x40;
|
|
|
|
} else if(regs.counters_latched) {
|
|
|
|
regs.ppu2_mdr |= 0x40;
|
|
|
|
regs.counters_latched = false;
|
|
|
|
}
|
|
|
|
regs.ppu2_mdr |= (system.region() == System::Region::NTSC ? 0 : 1) << 4;
|
|
|
|
regs.ppu2_mdr |= ppu2_version & 0x0f;
|
|
|
|
return regs.ppu2_mdr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PPU::mmio_reset() {
|
2011-04-27 08:57:31 +00:00
|
|
|
regs.ppu1_mdr = random(0xff);
|
|
|
|
regs.ppu2_mdr = random(0xff);
|
|
|
|
|
|
|
|
regs.vram_readbuffer = random(0x0000);
|
|
|
|
regs.oam_latchdata = random(0x00);
|
|
|
|
regs.cgram_latchdata = random(0x00);
|
|
|
|
regs.bgofs_latchdata = random(0x00);
|
|
|
|
regs.mode7_latchdata = random(0x00);
|
2010-08-09 13:28:56 +00:00
|
|
|
regs.counters_latched = false;
|
|
|
|
regs.latch_hcounter = 0;
|
|
|
|
regs.latch_vcounter = 0;
|
|
|
|
|
2010-09-24 13:15:21 +00:00
|
|
|
regs.oam_iaddr = 0x0000;
|
|
|
|
regs.cgram_iaddr = 0x00;
|
2010-08-09 13:28:56 +00:00
|
|
|
|
|
|
|
//$2100 INIDISP
|
Update to v068r12 release.
(there was no r11 release posted to the WIP thread)
byuu says:
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-04 03:36:03 +00:00
|
|
|
regs.display_disable = true;
|
2010-08-09 13:28:56 +00:00
|
|
|
regs.display_brightness = 0;
|
|
|
|
|
|
|
|
//$2102 OAMADDL
|
|
|
|
//$2103 OAMADDH
|
2011-04-27 08:57:31 +00:00
|
|
|
regs.oam_baseaddr = random(0x0000);
|
|
|
|
regs.oam_addr = random(0x0000);
|
|
|
|
regs.oam_priority = random(false);
|
2010-08-09 13:28:56 +00:00
|
|
|
|
|
|
|
//$2105 BGMODE
|
|
|
|
regs.bg3_priority = false;
|
|
|
|
regs.bgmode = 0;
|
|
|
|
|
|
|
|
//$210d BG1HOFS
|
2011-04-27 08:57:31 +00:00
|
|
|
regs.mode7_hoffset = random(0x0000);
|
2010-08-09 13:28:56 +00:00
|
|
|
|
|
|
|
//$210e BG1VOFS
|
2011-04-27 08:57:31 +00:00
|
|
|
regs.mode7_voffset = random(0x0000);
|
2010-08-09 13:28:56 +00:00
|
|
|
|
|
|
|
//$2115 VMAIN
|
2011-04-27 08:57:31 +00:00
|
|
|
regs.vram_incmode = random(1);
|
|
|
|
regs.vram_mapping = random(0);
|
2010-08-09 13:28:56 +00:00
|
|
|
regs.vram_incsize = 1;
|
|
|
|
|
|
|
|
//$2116 VMADDL
|
|
|
|
//$2117 VMADDH
|
2011-04-27 08:57:31 +00:00
|
|
|
regs.vram_addr = random(0x0000);
|
2010-08-09 13:28:56 +00:00
|
|
|
|
|
|
|
//$211a M7SEL
|
2011-04-27 08:57:31 +00:00
|
|
|
regs.mode7_repeat = random(0);
|
|
|
|
regs.mode7_vflip = random(false);
|
|
|
|
regs.mode7_hflip = random(false);
|
2010-08-09 13:28:56 +00:00
|
|
|
|
|
|
|
//$211b M7A
|
2011-04-27 08:57:31 +00:00
|
|
|
regs.m7a = random(0x0000);
|
2010-08-09 13:28:56 +00:00
|
|
|
|
|
|
|
//$211c M7B
|
2011-04-27 08:57:31 +00:00
|
|
|
regs.m7b = random(0x0000);
|
2010-08-09 13:28:56 +00:00
|
|
|
|
|
|
|
//$211d M7C
|
2011-04-27 08:57:31 +00:00
|
|
|
regs.m7c = random(0x0000);
|
2010-08-09 13:28:56 +00:00
|
|
|
|
|
|
|
//$211e M7D
|
2011-04-27 08:57:31 +00:00
|
|
|
regs.m7d = random(0x0000);
|
2010-08-09 13:28:56 +00:00
|
|
|
|
|
|
|
//$211f M7X
|
2011-04-27 08:57:31 +00:00
|
|
|
regs.m7x = random(0x0000);
|
2010-08-09 13:28:56 +00:00
|
|
|
|
|
|
|
//$2120 M7Y
|
2011-04-27 08:57:31 +00:00
|
|
|
regs.m7y = random(0x0000);
|
2010-08-09 13:28:56 +00:00
|
|
|
|
|
|
|
//$2121 CGADD
|
2011-04-27 08:57:31 +00:00
|
|
|
regs.cgram_addr = random(0x0000);
|
2010-08-09 13:28:56 +00:00
|
|
|
|
|
|
|
//$2133 SETINI
|
2011-04-27 08:57:31 +00:00
|
|
|
regs.mode7_extbg = random(false);
|
|
|
|
regs.pseudo_hires = random(false);
|
2010-08-09 13:28:56 +00:00
|
|
|
regs.overscan = false;
|
|
|
|
regs.interlace = false;
|
|
|
|
|
|
|
|
//$213c OPHCT
|
|
|
|
regs.hcounter = 0;
|
|
|
|
|
|
|
|
//$213d OPVCT
|
|
|
|
regs.vcounter = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8 PPU::mmio_read(unsigned addr) {
|
|
|
|
cpu.synchronize_ppu();
|
|
|
|
|
|
|
|
switch(addr & 0xffff) {
|
2013-05-05 09:21:30 +00:00
|
|
|
case 0x2104:
|
|
|
|
case 0x2105:
|
|
|
|
case 0x2106:
|
|
|
|
case 0x2108:
|
|
|
|
case 0x2109:
|
|
|
|
case 0x210a:
|
|
|
|
case 0x2114:
|
|
|
|
case 0x2115:
|
|
|
|
case 0x2116:
|
|
|
|
case 0x2118:
|
|
|
|
case 0x2119:
|
|
|
|
case 0x211a:
|
|
|
|
case 0x2124:
|
|
|
|
case 0x2125:
|
|
|
|
case 0x2126:
|
|
|
|
case 0x2128:
|
|
|
|
case 0x2129:
|
|
|
|
case 0x212a: return regs.ppu1_mdr;
|
|
|
|
case 0x2134: return mmio_r2134(); //MPYL
|
|
|
|
case 0x2135: return mmio_r2135(); //MPYM
|
|
|
|
case 0x2136: return mmio_r2136(); //MYPH
|
|
|
|
case 0x2137: return mmio_r2137(); //SLHV
|
|
|
|
case 0x2138: return mmio_r2138(); //OAMDATAREAD
|
|
|
|
case 0x2139: return mmio_r2139(); //VMDATALREAD
|
|
|
|
case 0x213a: return mmio_r213a(); //VMDATAHREAD
|
|
|
|
case 0x213b: return mmio_r213b(); //CGDATAREAD
|
|
|
|
case 0x213c: return mmio_r213c(); //OPHCT
|
|
|
|
case 0x213d: return mmio_r213d(); //OPVCT
|
|
|
|
case 0x213e: return mmio_r213e(); //STAT77
|
|
|
|
case 0x213f: return mmio_r213f(); //STAT78
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return cpu.regs.mdr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PPU::mmio_write(unsigned addr, uint8 data) {
|
|
|
|
cpu.synchronize_ppu();
|
|
|
|
|
|
|
|
switch(addr & 0xffff) {
|
2013-05-05 09:21:30 +00:00
|
|
|
case 0x2100: return mmio_w2100(data); //INIDISP
|
|
|
|
case 0x2101: return mmio_w2101(data); //OBSEL
|
|
|
|
case 0x2102: return mmio_w2102(data); //OAMADDL
|
|
|
|
case 0x2103: return mmio_w2103(data); //OAMADDH
|
|
|
|
case 0x2104: return mmio_w2104(data); //OAMDATA
|
|
|
|
case 0x2105: return mmio_w2105(data); //BGMODE
|
|
|
|
case 0x2106: return mmio_w2106(data); //MOSAIC
|
|
|
|
case 0x2107: return mmio_w2107(data); //BG1SC
|
|
|
|
case 0x2108: return mmio_w2108(data); //BG2SC
|
|
|
|
case 0x2109: return mmio_w2109(data); //BG3SC
|
|
|
|
case 0x210a: return mmio_w210a(data); //BG4SC
|
|
|
|
case 0x210b: return mmio_w210b(data); //BG12NBA
|
|
|
|
case 0x210c: return mmio_w210c(data); //BG34NBA
|
|
|
|
case 0x210d: return mmio_w210d(data); //BG1HOFS
|
|
|
|
case 0x210e: return mmio_w210e(data); //BG1VOFS
|
|
|
|
case 0x210f: return mmio_w210f(data); //BG2HOFS
|
|
|
|
case 0x2110: return mmio_w2110(data); //BG2VOFS
|
|
|
|
case 0x2111: return mmio_w2111(data); //BG3HOFS
|
|
|
|
case 0x2112: return mmio_w2112(data); //BG3VOFS
|
|
|
|
case 0x2113: return mmio_w2113(data); //BG4HOFS
|
|
|
|
case 0x2114: return mmio_w2114(data); //BG4VOFS
|
|
|
|
case 0x2115: return mmio_w2115(data); //VMAIN
|
|
|
|
case 0x2116: return mmio_w2116(data); //VMADDL
|
|
|
|
case 0x2117: return mmio_w2117(data); //VMADDH
|
|
|
|
case 0x2118: return mmio_w2118(data); //VMDATAL
|
|
|
|
case 0x2119: return mmio_w2119(data); //VMDATAH
|
|
|
|
case 0x211a: return mmio_w211a(data); //M7SEL
|
|
|
|
case 0x211b: return mmio_w211b(data); //M7A
|
|
|
|
case 0x211c: return mmio_w211c(data); //M7B
|
|
|
|
case 0x211d: return mmio_w211d(data); //M7C
|
|
|
|
case 0x211e: return mmio_w211e(data); //M7D
|
|
|
|
case 0x211f: return mmio_w211f(data); //M7X
|
|
|
|
case 0x2120: return mmio_w2120(data); //M7Y
|
|
|
|
case 0x2121: return mmio_w2121(data); //CGADD
|
|
|
|
case 0x2122: return mmio_w2122(data); //CGDATA
|
|
|
|
case 0x2123: return mmio_w2123(data); //W12SEL
|
|
|
|
case 0x2124: return mmio_w2124(data); //W34SEL
|
|
|
|
case 0x2125: return mmio_w2125(data); //WOBJSEL
|
|
|
|
case 0x2126: return mmio_w2126(data); //WH0
|
|
|
|
case 0x2127: return mmio_w2127(data); //WH1
|
|
|
|
case 0x2128: return mmio_w2128(data); //WH2
|
|
|
|
case 0x2129: return mmio_w2129(data); //WH3
|
|
|
|
case 0x212a: return mmio_w212a(data); //WBGLOG
|
|
|
|
case 0x212b: return mmio_w212b(data); //WOBJLOG
|
|
|
|
case 0x212c: return mmio_w212c(data); //TM
|
|
|
|
case 0x212d: return mmio_w212d(data); //TS
|
|
|
|
case 0x212e: return mmio_w212e(data); //TMW
|
|
|
|
case 0x212f: return mmio_w212f(data); //TSW
|
|
|
|
case 0x2130: return mmio_w2130(data); //CGWSEL
|
|
|
|
case 0x2131: return mmio_w2131(data); //CGADDSUB
|
|
|
|
case 0x2132: return mmio_w2132(data); //COLDATA
|
|
|
|
case 0x2133: return mmio_w2133(data); //SETINI
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|