2015-11-16 08:38:05 +00:00
|
|
|
enum : uint { OBJ = 0, BG0 = 1, BG1 = 2, BG2 = 3, BG3 = 4, SFX = 5 };
|
|
|
|
enum : uint { In0 = 0, In1 = 1, Obj = 2, Out = 3 };
|
Update to v087r22 release.
byuu says:
Changelog:
- fixed below pixel green channel on color blending
- added semi-transparent objects [Exophase's method]
- added full support for windows (both inputs, OBJ windows, and output, with optional color effect disable)
- EEPROM uses nall::bitarray now to be friendlier to saving memory to disk
- removed incomplete mosaic support for now (too broken, untested)
- improved sprite priority. Hopefully it's right now.
Just about everything should look great now. It took 25 days, but we
finally have the BIOS rendering correctly.
In order to do OBJ windows, I had to drop my above/below buffers
entirely. I went with the nuclear option. There's separate layers for
all BGs and objects. I build the OBJ window table during object
rendering. So as a result, after rendering I go back and apply windows
(and the object window that now exists.) After that, I have to do
a painful Z-buffer select of the top two most important pixels. Since
I now know the layers, the blending enable tests are a lot nicer, at
least. But this obviously has quite a speed hit: 390fps to 325fps for
Mr. Driller 2 title screen.
TONC says that "bad" window coordinates do really insane things. GBAtek
says it's a simple y2 < y1 || y2 > 160 ? 160 : y2; x2 < x1 || x2 > 240
? 240 : x2; I like the GBAtek version more, so I went with that. I sure
hope it's right ... but my guess is the hardware does this with
a counter that wraps around or something. Also, say you have two OBJ
mode 2 sprites that overlap each other, but with different priorities.
The lower (more important) priority sprite has a clear pixel, but the
higher priority sprite has a set pixel. Do we set the "inside OBJ
window" flag to true here? Eg does the value OR, or does it hold the
most important sprite's pixel value? Cydrak suspects it's OR-based,
I concur from what I can see.
Mosaic, I am at a loss. I really need a lot more information in order to
implement it. For backgrounds, does it apply to the Vcounter of the
entire screen? Or does it apply post-scroll? Or does it even apply after
every adjust in affine/bitmap modes? I'm betting the hcounter
background mosaic starts at the leftmost edge of the screen, and repeats
previous pixels to apply the effect. Like SNES, very simple. For
sprites, the SNES didn't have this. Does the mosaic grid start at (0,0)
of the screen, or at (0,0) of each sprite? The latter will look a lot
nicer, but be a lot more complex. Is mosaic on affine objects any
different than mosaic of linear(tiled) objects?
With that out of the way, we still have to fix the CPU memory access
timing, add the rest of the CPU penalty cycles, the memory rotation
/ alignment / extend behavior needs to be fixed, the shifter desperately
needs to be moved from loops to single shift operations, and I need to
add flash memory support.
2012-04-13 11:49:32 +00:00
|
|
|
|
2012-03-31 08:14:31 +00:00
|
|
|
struct Registers {
|
|
|
|
struct Control {
|
|
|
|
uint3 bgmode;
|
Update to v087r22 release.
byuu says:
Changelog:
- fixed below pixel green channel on color blending
- added semi-transparent objects [Exophase's method]
- added full support for windows (both inputs, OBJ windows, and output, with optional color effect disable)
- EEPROM uses nall::bitarray now to be friendlier to saving memory to disk
- removed incomplete mosaic support for now (too broken, untested)
- improved sprite priority. Hopefully it's right now.
Just about everything should look great now. It took 25 days, but we
finally have the BIOS rendering correctly.
In order to do OBJ windows, I had to drop my above/below buffers
entirely. I went with the nuclear option. There's separate layers for
all BGs and objects. I build the OBJ window table during object
rendering. So as a result, after rendering I go back and apply windows
(and the object window that now exists.) After that, I have to do
a painful Z-buffer select of the top two most important pixels. Since
I now know the layers, the blending enable tests are a lot nicer, at
least. But this obviously has quite a speed hit: 390fps to 325fps for
Mr. Driller 2 title screen.
TONC says that "bad" window coordinates do really insane things. GBAtek
says it's a simple y2 < y1 || y2 > 160 ? 160 : y2; x2 < x1 || x2 > 240
? 240 : x2; I like the GBAtek version more, so I went with that. I sure
hope it's right ... but my guess is the hardware does this with
a counter that wraps around or something. Also, say you have two OBJ
mode 2 sprites that overlap each other, but with different priorities.
The lower (more important) priority sprite has a clear pixel, but the
higher priority sprite has a set pixel. Do we set the "inside OBJ
window" flag to true here? Eg does the value OR, or does it hold the
most important sprite's pixel value? Cydrak suspects it's OR-based,
I concur from what I can see.
Mosaic, I am at a loss. I really need a lot more information in order to
implement it. For backgrounds, does it apply to the Vcounter of the
entire screen? Or does it apply post-scroll? Or does it even apply after
every adjust in affine/bitmap modes? I'm betting the hcounter
background mosaic starts at the leftmost edge of the screen, and repeats
previous pixels to apply the effect. Like SNES, very simple. For
sprites, the SNES didn't have this. Does the mosaic grid start at (0,0)
of the screen, or at (0,0) of each sprite? The latter will look a lot
nicer, but be a lot more complex. Is mosaic on affine objects any
different than mosaic of linear(tiled) objects?
With that out of the way, we still have to fix the CPU memory access
timing, add the rest of the CPU penalty cycles, the memory rotation
/ alignment / extend behavior needs to be fixed, the shifter desperately
needs to be moved from loops to single shift operations, and I need to
add flash memory support.
2012-04-13 11:49:32 +00:00
|
|
|
uint1 cgbmode;
|
|
|
|
uint1 frame;
|
|
|
|
uint1 hblank;
|
|
|
|
uint1 objmapping;
|
|
|
|
uint1 forceblank;
|
|
|
|
uint1 enable[5];
|
|
|
|
uint1 enablewindow[3];
|
2012-03-31 08:14:31 +00:00
|
|
|
|
|
|
|
operator uint16() const;
|
2015-11-16 08:38:05 +00:00
|
|
|
auto operator=(uint16 source) -> uint16;
|
|
|
|
auto operator=(const Control&) -> Control& = delete;
|
2012-03-31 08:14:31 +00:00
|
|
|
} control;
|
|
|
|
|
Update to v087r22 release.
byuu says:
Changelog:
- fixed below pixel green channel on color blending
- added semi-transparent objects [Exophase's method]
- added full support for windows (both inputs, OBJ windows, and output, with optional color effect disable)
- EEPROM uses nall::bitarray now to be friendlier to saving memory to disk
- removed incomplete mosaic support for now (too broken, untested)
- improved sprite priority. Hopefully it's right now.
Just about everything should look great now. It took 25 days, but we
finally have the BIOS rendering correctly.
In order to do OBJ windows, I had to drop my above/below buffers
entirely. I went with the nuclear option. There's separate layers for
all BGs and objects. I build the OBJ window table during object
rendering. So as a result, after rendering I go back and apply windows
(and the object window that now exists.) After that, I have to do
a painful Z-buffer select of the top two most important pixels. Since
I now know the layers, the blending enable tests are a lot nicer, at
least. But this obviously has quite a speed hit: 390fps to 325fps for
Mr. Driller 2 title screen.
TONC says that "bad" window coordinates do really insane things. GBAtek
says it's a simple y2 < y1 || y2 > 160 ? 160 : y2; x2 < x1 || x2 > 240
? 240 : x2; I like the GBAtek version more, so I went with that. I sure
hope it's right ... but my guess is the hardware does this with
a counter that wraps around or something. Also, say you have two OBJ
mode 2 sprites that overlap each other, but with different priorities.
The lower (more important) priority sprite has a clear pixel, but the
higher priority sprite has a set pixel. Do we set the "inside OBJ
window" flag to true here? Eg does the value OR, or does it hold the
most important sprite's pixel value? Cydrak suspects it's OR-based,
I concur from what I can see.
Mosaic, I am at a loss. I really need a lot more information in order to
implement it. For backgrounds, does it apply to the Vcounter of the
entire screen? Or does it apply post-scroll? Or does it even apply after
every adjust in affine/bitmap modes? I'm betting the hcounter
background mosaic starts at the leftmost edge of the screen, and repeats
previous pixels to apply the effect. Like SNES, very simple. For
sprites, the SNES didn't have this. Does the mosaic grid start at (0,0)
of the screen, or at (0,0) of each sprite? The latter will look a lot
nicer, but be a lot more complex. Is mosaic on affine objects any
different than mosaic of linear(tiled) objects?
With that out of the way, we still have to fix the CPU memory access
timing, add the rest of the CPU penalty cycles, the memory rotation
/ alignment / extend behavior needs to be fixed, the shifter desperately
needs to be moved from loops to single shift operations, and I need to
add flash memory support.
2012-04-13 11:49:32 +00:00
|
|
|
uint1 greenswap;
|
2012-03-31 08:17:36 +00:00
|
|
|
|
|
|
|
struct Status {
|
Update to v087r22 release.
byuu says:
Changelog:
- fixed below pixel green channel on color blending
- added semi-transparent objects [Exophase's method]
- added full support for windows (both inputs, OBJ windows, and output, with optional color effect disable)
- EEPROM uses nall::bitarray now to be friendlier to saving memory to disk
- removed incomplete mosaic support for now (too broken, untested)
- improved sprite priority. Hopefully it's right now.
Just about everything should look great now. It took 25 days, but we
finally have the BIOS rendering correctly.
In order to do OBJ windows, I had to drop my above/below buffers
entirely. I went with the nuclear option. There's separate layers for
all BGs and objects. I build the OBJ window table during object
rendering. So as a result, after rendering I go back and apply windows
(and the object window that now exists.) After that, I have to do
a painful Z-buffer select of the top two most important pixels. Since
I now know the layers, the blending enable tests are a lot nicer, at
least. But this obviously has quite a speed hit: 390fps to 325fps for
Mr. Driller 2 title screen.
TONC says that "bad" window coordinates do really insane things. GBAtek
says it's a simple y2 < y1 || y2 > 160 ? 160 : y2; x2 < x1 || x2 > 240
? 240 : x2; I like the GBAtek version more, so I went with that. I sure
hope it's right ... but my guess is the hardware does this with
a counter that wraps around or something. Also, say you have two OBJ
mode 2 sprites that overlap each other, but with different priorities.
The lower (more important) priority sprite has a clear pixel, but the
higher priority sprite has a set pixel. Do we set the "inside OBJ
window" flag to true here? Eg does the value OR, or does it hold the
most important sprite's pixel value? Cydrak suspects it's OR-based,
I concur from what I can see.
Mosaic, I am at a loss. I really need a lot more information in order to
implement it. For backgrounds, does it apply to the Vcounter of the
entire screen? Or does it apply post-scroll? Or does it even apply after
every adjust in affine/bitmap modes? I'm betting the hcounter
background mosaic starts at the leftmost edge of the screen, and repeats
previous pixels to apply the effect. Like SNES, very simple. For
sprites, the SNES didn't have this. Does the mosaic grid start at (0,0)
of the screen, or at (0,0) of each sprite? The latter will look a lot
nicer, but be a lot more complex. Is mosaic on affine objects any
different than mosaic of linear(tiled) objects?
With that out of the way, we still have to fix the CPU memory access
timing, add the rest of the CPU penalty cycles, the memory rotation
/ alignment / extend behavior needs to be fixed, the shifter desperately
needs to be moved from loops to single shift operations, and I need to
add flash memory support.
2012-04-13 11:49:32 +00:00
|
|
|
uint1 vblank;
|
|
|
|
uint1 hblank;
|
|
|
|
uint1 vcoincidence;
|
|
|
|
uint1 irqvblank;
|
|
|
|
uint1 irqhblank;
|
|
|
|
uint1 irqvcoincidence;
|
2012-03-31 08:17:36 +00:00
|
|
|
uint8 vcompare;
|
|
|
|
|
|
|
|
operator uint16() const;
|
2015-11-16 08:38:05 +00:00
|
|
|
auto operator=(uint16 source) -> uint16;
|
|
|
|
auto operator=(const Status&) -> Status& = delete;
|
2012-03-31 08:17:36 +00:00
|
|
|
} status;
|
|
|
|
|
|
|
|
uint16 vcounter;
|
|
|
|
|
|
|
|
struct BackgroundControl {
|
|
|
|
uint2 priority;
|
|
|
|
uint2 characterbaseblock;
|
Update to v095r05 release.
byuu says:
Changelog:
- GBA: lots of emulation improvements
- PPU PRAM is 16-bits wide
- DMA masks &~1/Half, &~3/Word
- VRAM OBJ 8-bit writes are ignored
- OAM 8-bit writes are ignored
- BGnCNT unused bits are writable*
- BG(0,1)CNT can't set the d13
- BLDALPHA is readable (fixes Donkey Kong Country, etc)
- SNES: lots of code cleanups
- sfc/chip => sfc/coprocessor
- UI: save most recent controller selection
GBA test scores: 1552/1552, 37/38, 1020/1260
(* forgot to add the value to the read function, so endrift's I/O tests
for them will fail. Fixed locally.)
Note: SNES is the only system with multiple controller/expansion port
options, and as such is the only one with a "None" option. Because it's
shared by the controller and expansion port, it ends up sorted first in
the list. This means that on your first run, you'll need to go to Super
Famicom->Controller Port 1 and select "Gamepad", otherwise input won't
work.
Also note that changing the expansion port device requires loading a new
cart. Unlike controllers, you aren't meant to hotplug expansion port
devices.
2015-11-12 10:15:03 +00:00
|
|
|
uint2 unused;
|
2012-03-31 08:17:36 +00:00
|
|
|
uint1 mosaic;
|
|
|
|
uint1 colormode;
|
|
|
|
uint5 screenbaseblock;
|
2012-04-07 08:17:49 +00:00
|
|
|
uint1 affinewrap; //BG2,3 only
|
2012-03-31 08:17:36 +00:00
|
|
|
uint2 screensize;
|
|
|
|
|
|
|
|
operator uint16() const;
|
2015-11-16 08:38:05 +00:00
|
|
|
auto operator=(uint16 source) -> uint16;
|
|
|
|
auto operator=(const BackgroundControl&) -> BackgroundControl& = delete;
|
2012-03-31 08:17:36 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct Background {
|
|
|
|
BackgroundControl control;
|
|
|
|
uint9 hoffset;
|
|
|
|
uint9 voffset;
|
|
|
|
|
|
|
|
//BG2,3 only
|
2012-04-07 08:17:49 +00:00
|
|
|
int16 pa, pb, pc, pd;
|
|
|
|
int28 x, y;
|
|
|
|
|
|
|
|
//internal
|
|
|
|
int28 lx, ly;
|
2015-11-16 08:38:05 +00:00
|
|
|
uint vmosaic;
|
|
|
|
uint hmosaic;
|
|
|
|
uint id;
|
2012-03-31 08:17:36 +00:00
|
|
|
} bg[4];
|
|
|
|
|
|
|
|
struct WindowFlags {
|
Update to v087r22 release.
byuu says:
Changelog:
- fixed below pixel green channel on color blending
- added semi-transparent objects [Exophase's method]
- added full support for windows (both inputs, OBJ windows, and output, with optional color effect disable)
- EEPROM uses nall::bitarray now to be friendlier to saving memory to disk
- removed incomplete mosaic support for now (too broken, untested)
- improved sprite priority. Hopefully it's right now.
Just about everything should look great now. It took 25 days, but we
finally have the BIOS rendering correctly.
In order to do OBJ windows, I had to drop my above/below buffers
entirely. I went with the nuclear option. There's separate layers for
all BGs and objects. I build the OBJ window table during object
rendering. So as a result, after rendering I go back and apply windows
(and the object window that now exists.) After that, I have to do
a painful Z-buffer select of the top two most important pixels. Since
I now know the layers, the blending enable tests are a lot nicer, at
least. But this obviously has quite a speed hit: 390fps to 325fps for
Mr. Driller 2 title screen.
TONC says that "bad" window coordinates do really insane things. GBAtek
says it's a simple y2 < y1 || y2 > 160 ? 160 : y2; x2 < x1 || x2 > 240
? 240 : x2; I like the GBAtek version more, so I went with that. I sure
hope it's right ... but my guess is the hardware does this with
a counter that wraps around or something. Also, say you have two OBJ
mode 2 sprites that overlap each other, but with different priorities.
The lower (more important) priority sprite has a clear pixel, but the
higher priority sprite has a set pixel. Do we set the "inside OBJ
window" flag to true here? Eg does the value OR, or does it hold the
most important sprite's pixel value? Cydrak suspects it's OR-based,
I concur from what I can see.
Mosaic, I am at a loss. I really need a lot more information in order to
implement it. For backgrounds, does it apply to the Vcounter of the
entire screen? Or does it apply post-scroll? Or does it even apply after
every adjust in affine/bitmap modes? I'm betting the hcounter
background mosaic starts at the leftmost edge of the screen, and repeats
previous pixels to apply the effect. Like SNES, very simple. For
sprites, the SNES didn't have this. Does the mosaic grid start at (0,0)
of the screen, or at (0,0) of each sprite? The latter will look a lot
nicer, but be a lot more complex. Is mosaic on affine objects any
different than mosaic of linear(tiled) objects?
With that out of the way, we still have to fix the CPU memory access
timing, add the rest of the CPU penalty cycles, the memory rotation
/ alignment / extend behavior needs to be fixed, the shifter desperately
needs to be moved from loops to single shift operations, and I need to
add flash memory support.
2012-04-13 11:49:32 +00:00
|
|
|
uint1 enable[6];
|
2012-03-31 08:17:36 +00:00
|
|
|
|
|
|
|
operator uint8() const;
|
2015-11-16 08:38:05 +00:00
|
|
|
auto operator=(uint8 source) -> uint8;
|
|
|
|
auto operator=(const WindowFlags&) -> WindowFlags& = delete;
|
2012-03-31 08:17:36 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct Window {
|
|
|
|
uint8 x1, x2;
|
|
|
|
uint8 y1, y2;
|
|
|
|
} window[2];
|
|
|
|
|
Update to v087r22 release.
byuu says:
Changelog:
- fixed below pixel green channel on color blending
- added semi-transparent objects [Exophase's method]
- added full support for windows (both inputs, OBJ windows, and output, with optional color effect disable)
- EEPROM uses nall::bitarray now to be friendlier to saving memory to disk
- removed incomplete mosaic support for now (too broken, untested)
- improved sprite priority. Hopefully it's right now.
Just about everything should look great now. It took 25 days, but we
finally have the BIOS rendering correctly.
In order to do OBJ windows, I had to drop my above/below buffers
entirely. I went with the nuclear option. There's separate layers for
all BGs and objects. I build the OBJ window table during object
rendering. So as a result, after rendering I go back and apply windows
(and the object window that now exists.) After that, I have to do
a painful Z-buffer select of the top two most important pixels. Since
I now know the layers, the blending enable tests are a lot nicer, at
least. But this obviously has quite a speed hit: 390fps to 325fps for
Mr. Driller 2 title screen.
TONC says that "bad" window coordinates do really insane things. GBAtek
says it's a simple y2 < y1 || y2 > 160 ? 160 : y2; x2 < x1 || x2 > 240
? 240 : x2; I like the GBAtek version more, so I went with that. I sure
hope it's right ... but my guess is the hardware does this with
a counter that wraps around or something. Also, say you have two OBJ
mode 2 sprites that overlap each other, but with different priorities.
The lower (more important) priority sprite has a clear pixel, but the
higher priority sprite has a set pixel. Do we set the "inside OBJ
window" flag to true here? Eg does the value OR, or does it hold the
most important sprite's pixel value? Cydrak suspects it's OR-based,
I concur from what I can see.
Mosaic, I am at a loss. I really need a lot more information in order to
implement it. For backgrounds, does it apply to the Vcounter of the
entire screen? Or does it apply post-scroll? Or does it even apply after
every adjust in affine/bitmap modes? I'm betting the hcounter
background mosaic starts at the leftmost edge of the screen, and repeats
previous pixels to apply the effect. Like SNES, very simple. For
sprites, the SNES didn't have this. Does the mosaic grid start at (0,0)
of the screen, or at (0,0) of each sprite? The latter will look a lot
nicer, but be a lot more complex. Is mosaic on affine objects any
different than mosaic of linear(tiled) objects?
With that out of the way, we still have to fix the CPU memory access
timing, add the rest of the CPU penalty cycles, the memory rotation
/ alignment / extend behavior needs to be fixed, the shifter desperately
needs to be moved from loops to single shift operations, and I need to
add flash memory support.
2012-04-13 11:49:32 +00:00
|
|
|
WindowFlags windowflags[4];
|
2012-03-31 08:17:36 +00:00
|
|
|
|
|
|
|
struct Mosaic {
|
|
|
|
uint4 bghsize;
|
|
|
|
uint4 bgvsize;
|
|
|
|
uint4 objhsize;
|
|
|
|
uint4 objvsize;
|
|
|
|
} mosaic;
|
|
|
|
|
|
|
|
struct BlendControl {
|
Update to v087r22 release.
byuu says:
Changelog:
- fixed below pixel green channel on color blending
- added semi-transparent objects [Exophase's method]
- added full support for windows (both inputs, OBJ windows, and output, with optional color effect disable)
- EEPROM uses nall::bitarray now to be friendlier to saving memory to disk
- removed incomplete mosaic support for now (too broken, untested)
- improved sprite priority. Hopefully it's right now.
Just about everything should look great now. It took 25 days, but we
finally have the BIOS rendering correctly.
In order to do OBJ windows, I had to drop my above/below buffers
entirely. I went with the nuclear option. There's separate layers for
all BGs and objects. I build the OBJ window table during object
rendering. So as a result, after rendering I go back and apply windows
(and the object window that now exists.) After that, I have to do
a painful Z-buffer select of the top two most important pixels. Since
I now know the layers, the blending enable tests are a lot nicer, at
least. But this obviously has quite a speed hit: 390fps to 325fps for
Mr. Driller 2 title screen.
TONC says that "bad" window coordinates do really insane things. GBAtek
says it's a simple y2 < y1 || y2 > 160 ? 160 : y2; x2 < x1 || x2 > 240
? 240 : x2; I like the GBAtek version more, so I went with that. I sure
hope it's right ... but my guess is the hardware does this with
a counter that wraps around or something. Also, say you have two OBJ
mode 2 sprites that overlap each other, but with different priorities.
The lower (more important) priority sprite has a clear pixel, but the
higher priority sprite has a set pixel. Do we set the "inside OBJ
window" flag to true here? Eg does the value OR, or does it hold the
most important sprite's pixel value? Cydrak suspects it's OR-based,
I concur from what I can see.
Mosaic, I am at a loss. I really need a lot more information in order to
implement it. For backgrounds, does it apply to the Vcounter of the
entire screen? Or does it apply post-scroll? Or does it even apply after
every adjust in affine/bitmap modes? I'm betting the hcounter
background mosaic starts at the leftmost edge of the screen, and repeats
previous pixels to apply the effect. Like SNES, very simple. For
sprites, the SNES didn't have this. Does the mosaic grid start at (0,0)
of the screen, or at (0,0) of each sprite? The latter will look a lot
nicer, but be a lot more complex. Is mosaic on affine objects any
different than mosaic of linear(tiled) objects?
With that out of the way, we still have to fix the CPU memory access
timing, add the rest of the CPU penalty cycles, the memory rotation
/ alignment / extend behavior needs to be fixed, the shifter desperately
needs to be moved from loops to single shift operations, and I need to
add flash memory support.
2012-04-13 11:49:32 +00:00
|
|
|
uint1 above[6];
|
|
|
|
uint1 below[6];
|
2012-04-10 11:41:35 +00:00
|
|
|
uint2 mode;
|
2012-03-31 08:17:36 +00:00
|
|
|
|
|
|
|
operator uint16() const;
|
2015-11-16 08:38:05 +00:00
|
|
|
auto operator=(uint16 source) -> uint16;
|
|
|
|
auto operator=(const BlendControl&) -> BlendControl& = delete;
|
2012-03-31 08:17:36 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct Blend {
|
|
|
|
BlendControl control;
|
|
|
|
uint5 eva;
|
|
|
|
uint5 evb;
|
|
|
|
uint5 evy;
|
|
|
|
} blend;
|
2012-03-31 08:14:31 +00:00
|
|
|
} regs;
|