mirror of
https://github.com/hch12907/orbum.git
synced 2024-05-20 05:00:48 -04:00
Implement gif packed mode
This commit is contained in:
parent
30ad98be49
commit
48c4efcce6
|
@ -58,26 +58,58 @@ int CGif::time_step(const int ticks_available)
|
|||
|
||||
for (auto& fifo : paths)
|
||||
{
|
||||
if (!fifo->has_read_available(NUMBER_BYTES_IN_QWORD))
|
||||
continue;
|
||||
|
||||
uqword data;
|
||||
fifo->read(reinterpret_cast<ubyte*>(&data), NUMBER_BYTES_IN_QWORD);
|
||||
|
||||
if (!ctrl.transfer_started)
|
||||
{
|
||||
if (!fifo->has_read_available(NUMBER_BYTES_IN_QWORD))
|
||||
continue;
|
||||
|
||||
uqword data;
|
||||
fifo->read(reinterpret_cast<ubyte*>(&data), NUMBER_BYTES_IN_QWORD);
|
||||
|
||||
ctrl.transfer_started = true;
|
||||
handle_tag(Giftag(data));
|
||||
}
|
||||
else
|
||||
{
|
||||
handle_data(data);
|
||||
switch (ctrl.tag.flg())
|
||||
{
|
||||
case Giftag::DataFormat::Packed:
|
||||
{
|
||||
if (!fifo->has_read_available(NUMBER_BYTES_IN_QWORD))
|
||||
continue;
|
||||
|
||||
uqword data;
|
||||
fifo->read(reinterpret_cast<ubyte*>(&data), NUMBER_BYTES_IN_QWORD);
|
||||
|
||||
handle_data_packed(data);
|
||||
}
|
||||
case Giftag::DataFormat::Reglist:
|
||||
{
|
||||
if (!fifo->has_read_available(NUMBER_BYTES_IN_DWORD))
|
||||
continue;
|
||||
|
||||
uqword data;
|
||||
fifo->read(reinterpret_cast<ubyte*>(&data), NUMBER_BYTES_IN_DWORD);
|
||||
|
||||
handle_data_packed(data);
|
||||
}
|
||||
case Giftag::DataFormat::Image:
|
||||
case Giftag::DataFormat::Disabled:
|
||||
{
|
||||
if (!fifo->has_read_available(NUMBER_BYTES_IN_QWORD))
|
||||
continue;
|
||||
|
||||
uqword data;
|
||||
fifo->read(reinterpret_cast<ubyte*>(&data), NUMBER_BYTES_IN_QWORD);
|
||||
|
||||
handle_data_image(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ctrl.transfer_end_of_packet)
|
||||
if (ctrl.tag.eop())
|
||||
{
|
||||
if (ctrl.transfer_data_count == ctrl.transfer_data_target)
|
||||
ctrl.transfer_started = false;
|
||||
throw std::runtime_error("End of GS packet reached");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -89,13 +121,258 @@ void CGif::handle_tag(const Giftag tag)
|
|||
auto& r = core->get_resources();
|
||||
auto& ctrl = r.ee.gif.ctrl;
|
||||
|
||||
ctrl.transfer_data_count = 0;
|
||||
ctrl.tag = tag;
|
||||
ctrl.transfer_register_count = 0;
|
||||
ctrl.transfer_loop_count = 0;
|
||||
|
||||
// Initialise the RGBAQ.Q value on every tag read.
|
||||
// See EE Users manual page 153.
|
||||
ctrl.rgbaq_q = 1.0f;
|
||||
|
||||
// Some special processing when the NLOOP field is non-zero
|
||||
// "Values other than the EOP field are disregarded."
|
||||
// See EE Users Manual page 151.
|
||||
if (tag.nloop())
|
||||
{
|
||||
if (tag.flg() == Giftag::DataFormat::Packed)
|
||||
{
|
||||
// Output the packed PRIM data to GS if the PRE bit is set.
|
||||
if (tag.pre())
|
||||
{
|
||||
throw std::runtime_error("Sending GIFtag packed PRIM data not implemented yet");
|
||||
//uhword prim_value = tag.prim();
|
||||
//auto& prim = r.gs.prim;
|
||||
//prim.write_udword(prim_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CGif::handle_data(const uqword data)
|
||||
void CGif::handle_data_packed(const uqword data)
|
||||
{
|
||||
auto& r = core->get_resources();
|
||||
auto& ctrl = r.ee.gif.ctrl;
|
||||
|
||||
// Get the register descirptor.
|
||||
size_t register_descirptor = ctrl.tag.regs(ctrl.transfer_register_count);
|
||||
|
||||
// Process the data given, and write to the GS register.
|
||||
// See EE Users Manual page 152 onwards for processing details.
|
||||
switch (register_descirptor)
|
||||
{
|
||||
case 0x0:
|
||||
{
|
||||
// PRIM
|
||||
constexpr Bitfield PRIM = Bitfield(0, 11);
|
||||
|
||||
udword prim_value = PRIM.extract_from<udword>(data);
|
||||
|
||||
//auto& prim = r.gs.prim;
|
||||
//prim.write_udword(prim_value);
|
||||
}
|
||||
case 0x1:
|
||||
{
|
||||
// RGBAQ
|
||||
constexpr Bitfield R = Bitfield(0, 8);
|
||||
constexpr Bitfield G = Bitfield(32, 8);
|
||||
constexpr Bitfield B = Bitfield(64, 8);
|
||||
constexpr Bitfield A = Bitfield(96, 8);
|
||||
|
||||
udword r_value = R.extract_from<udword>(data);
|
||||
udword g_value = G.extract_from<udword>(data);
|
||||
udword b_value = B.extract_from<udword>(data);
|
||||
udword a_value = A.extract_from<udword>(data);
|
||||
udword q_value = *reinterpret_cast<udword*>(&ctrl.rgbaq_q);
|
||||
|
||||
//auto& rgbaq = r.gs.rgbaq;
|
||||
//rgbaq.write_field(GsRegister_Rgbaq::R, r_value);
|
||||
//rgbaq.write_field(GsRegister_Rgbaq::G, g_value);
|
||||
//rgbaq.write_field(GsRegister_Rgbaq::B, b_value);
|
||||
//rgbaq.write_field(GsRegister_Rgbaq::A, a_value);
|
||||
//rgbaq.write_field(GsRegister_Rgbaq::Q, q_value);
|
||||
}
|
||||
case 0x2:
|
||||
{
|
||||
// ST
|
||||
constexpr Bitfield S = Bitfield(0, 32);
|
||||
constexpr Bitfield T = Bitfield(32, 32);
|
||||
constexpr Bitfield Q = Bitfield(64, 32);
|
||||
|
||||
// Store the Q value internally, used when handling RGBAQ register descriptor (see above).
|
||||
uword q_value = Q.extract_from<uword>(data);
|
||||
ctrl.rgbaq_q = *reinterpret_cast<f32*>(&q_value);
|
||||
|
||||
udword s_value = S.extract_from<udword>(data);
|
||||
udword t_value = T.extract_from<udword>(data);
|
||||
|
||||
//auto& st = r.gs.st;
|
||||
//st.write_field(GsRegister_St::S, s_value);
|
||||
//st.write_field(GsRegister_St::T, t_value);
|
||||
}
|
||||
case 0x3:
|
||||
{
|
||||
// UV
|
||||
constexpr Bitfield U = Bitfield(0, 14);
|
||||
constexpr Bitfield V = Bitfield(32, 14);
|
||||
|
||||
udword u_value = U.extract_from<udword>(data);
|
||||
udword v_value = V.extract_from<udword>(data);
|
||||
|
||||
//auto& uv = r.gs.uv;
|
||||
//uv.write_field(GsRegister_Uv::U, u_value);
|
||||
//uv.write_field(GsRegister_Uv::V, v_value);
|
||||
}
|
||||
case 0x4:
|
||||
{
|
||||
// XYZF2/3
|
||||
constexpr Bitfield X = Bitfield(0, 16);
|
||||
constexpr Bitfield Y = Bitfield(32, 16);
|
||||
constexpr Bitfield Z = Bitfield(68, 24);
|
||||
constexpr Bitfield F = Bitfield(100, 8);
|
||||
constexpr Bitfield ADC = Bitfield(111, 1);
|
||||
|
||||
udword x_value = X.extract_from<udword>(data);
|
||||
udword y_value = Y.extract_from<udword>(data);
|
||||
udword z_value = Z.extract_from<udword>(data);
|
||||
udword f_value = F.extract_from<udword>(data);
|
||||
udword adc_value = ADC.extract_from<udword>(data);
|
||||
|
||||
//GsRegister_Xyzf * xyzf = adc_value ? &r.gs.xyzf2 : &r.gs.xyzf3;
|
||||
//xyzf->write_field(GsRegister_Xyzf::X, x_value);
|
||||
//xyzf->write_field(GsRegister_Xyzf::Y, y_value);
|
||||
//xyzf->write_field(GsRegister_Xyzf::Z, z_value);
|
||||
//xyzf->write_field(GsRegister_Xyzf::F, f_value);
|
||||
}
|
||||
case 0x5:
|
||||
{
|
||||
// XYZ2
|
||||
constexpr Bitfield X = Bitfield(0, 16);
|
||||
constexpr Bitfield Y = Bitfield(32, 16);
|
||||
constexpr Bitfield Z = Bitfield(64, 32);
|
||||
constexpr Bitfield ADC = Bitfield(111, 1);
|
||||
|
||||
udword x_value = X.extract_from<udword>(data);
|
||||
udword y_value = Y.extract_from<udword>(data);
|
||||
udword z_value = Z.extract_from<udword>(data);
|
||||
udword adc_value = ADC.extract_from<udword>(data);
|
||||
|
||||
//GsRegister_Xyzf * xyz = adc_value ? &r.gs.xyz2 : &r.gs.xyz3;
|
||||
//xyz->write_field(GsRegister_Xyzf::X, x_value);
|
||||
//xyz->write_field(GsRegister_Xyzf::Y, y_value);
|
||||
//xyz->write_field(GsRegister_Xyzf::Z, z_value);
|
||||
}
|
||||
case 0x6:
|
||||
{
|
||||
// TEX0_1
|
||||
//auto& tex0_1 = r.gs.tex0_1;
|
||||
//tex0_1.write_udword(data.lo);
|
||||
}
|
||||
case 0x7:
|
||||
{
|
||||
// TEX0_2
|
||||
//auto& tex0_2 = r.gs.tex0_2;
|
||||
//tex0_2.write_udword(data.lo);
|
||||
}
|
||||
case 0x8:
|
||||
{
|
||||
// CLAMP_1
|
||||
//auto& clamp_1 = r.gs.clamp_1;
|
||||
//clamp_1.write_udword(data.lo);
|
||||
}
|
||||
case 0x9:
|
||||
{
|
||||
// CLAMP_2
|
||||
//auto& clamp_2 = r.gs.clamp_2;
|
||||
//clamp_2.write_udword(data.lo);
|
||||
}
|
||||
case 0xA:
|
||||
{
|
||||
// FOG
|
||||
// TODO: Not sure if we need to extract the integral part? Wording a bit unclear.
|
||||
// See EE Users Manual page 155.
|
||||
constexpr Bitfield F = Bitfield(100, 8);
|
||||
|
||||
udword f_value = F.extract_from<udword>(data);
|
||||
|
||||
//auto& fog = r.gs.fog;
|
||||
//fog.write_field(GsRegister_Fog::F, f_value);
|
||||
}
|
||||
case 0xB:
|
||||
{
|
||||
// Reserved
|
||||
throw std::runtime_error("Reserved register descriptor read from GIFtag");
|
||||
}
|
||||
case 0xC:
|
||||
{
|
||||
// XYZF3
|
||||
//auto& xyzf3 = r.gs.xyzf3;
|
||||
//xyzf3.write_udword(data.lo);
|
||||
}
|
||||
case 0xD:
|
||||
{
|
||||
// XYZ3
|
||||
//auto& xyz3 = r.gs.xyz3;
|
||||
//xyz3.write_udword(data.lo);
|
||||
}
|
||||
case 0xE:
|
||||
{
|
||||
// A+D (packed address + data)
|
||||
constexpr Bitfield ADDR = Bitfield(64, 8);
|
||||
|
||||
uptr addr_value = ADDR.extract_from<uptr>(data);
|
||||
udword data_value = data.lo;
|
||||
|
||||
//r.gs.bus.write_udword(BusContext::Gif, addr_value, data_value);
|
||||
}
|
||||
case 0xF:
|
||||
{
|
||||
// NOP
|
||||
}
|
||||
default:
|
||||
{
|
||||
throw std::runtime_error("Unknown register descriptor given");
|
||||
}
|
||||
}
|
||||
|
||||
ctrl.transfer_register_count += 1;
|
||||
if (ctrl.transfer_register_count == ctrl.tag.nreg())
|
||||
{
|
||||
ctrl.transfer_register_count = 0;
|
||||
ctrl.transfer_loop_count += 1;
|
||||
}
|
||||
|
||||
if (ctrl.transfer_loop_count == ctrl.tag.nloop())
|
||||
ctrl.transfer_started = false;
|
||||
}
|
||||
|
||||
void CGif::handle_data_reglist(const udword data)
|
||||
{
|
||||
auto& r = core->get_resources();
|
||||
auto& ctrl = r.ee.gif.ctrl;
|
||||
|
||||
ctrl.transfer_data_count += 1;
|
||||
ctrl.transfer_register_count += 1;
|
||||
if (ctrl.transfer_register_count == ctrl.tag.nreg())
|
||||
{
|
||||
ctrl.transfer_register_count = 0;
|
||||
ctrl.transfer_loop_count += 1;
|
||||
}
|
||||
|
||||
if (ctrl.transfer_loop_count == ctrl.tag.nloop())
|
||||
ctrl.transfer_started = false;
|
||||
}
|
||||
|
||||
void CGif::handle_data_image(const uqword data)
|
||||
{
|
||||
auto& r = core->get_resources();
|
||||
auto& ctrl = r.ee.gif.ctrl;
|
||||
|
||||
ctrl.transfer_register_count += 1;
|
||||
if (ctrl.transfer_register_count == ctrl.tag.nreg())
|
||||
{
|
||||
ctrl.transfer_register_count = 0;
|
||||
ctrl.transfer_loop_count += 1;
|
||||
}
|
||||
|
||||
if (ctrl.transfer_loop_count == ctrl.tag.nloop())
|
||||
ctrl.transfer_started = false;
|
||||
}
|
|
@ -19,5 +19,9 @@ public:
|
|||
|
||||
void handle_tag(const Giftag tag);
|
||||
|
||||
void handle_data(const uqword data);
|
||||
void handle_data_packed(const uqword data);
|
||||
|
||||
void handle_data_reglist(const udword data);
|
||||
|
||||
void handle_data_image(const uqword data);
|
||||
};
|
||||
|
|
|
@ -2,8 +2,9 @@
|
|||
|
||||
GifRegister_Ctrl::GifRegister_Ctrl() :
|
||||
transfer_started(false),
|
||||
transfer_data_target(0),
|
||||
transfer_data_count(0),
|
||||
transfer_end_of_packet(false)
|
||||
tag(),
|
||||
transfer_register_count(0),
|
||||
transfer_loop_count(0),
|
||||
rgbaq_q(1.0f)
|
||||
{
|
||||
}
|
|
@ -6,6 +6,8 @@
|
|||
#include "Common/Types/Bitfield.hpp"
|
||||
#include "Common/Types/Register/SizedWordRegister.hpp"
|
||||
|
||||
#include "Resources/Ee/Gif/Giftag.hpp"
|
||||
|
||||
class GifRegister_Ctrl : public SizedWordRegister
|
||||
{
|
||||
public:
|
||||
|
@ -14,17 +16,20 @@ public:
|
|||
|
||||
GifRegister_Ctrl();
|
||||
|
||||
/// Indicates whether the GIF is currently processing a GS primitive
|
||||
/// (excluding the tag). Reset upon finishing a GS primitive.
|
||||
/// Indicates whether the GIF is currently processing GS primitive
|
||||
/// data (otherwise read a tag). Reset upon finishing a GS primitive.
|
||||
bool transfer_started;
|
||||
|
||||
/// Number of qwords total/left for the current GS primitive.
|
||||
/// Set by the tag read.
|
||||
size_t transfer_data_target;
|
||||
size_t transfer_data_count;
|
||||
/// Current transfer tag being processed.
|
||||
Giftag tag;
|
||||
|
||||
/// End of GS packet indicator. Set by the tag read.
|
||||
bool transfer_end_of_packet;
|
||||
/// Number of registers / loops processed for the current tag.
|
||||
size_t transfer_register_count;
|
||||
size_t transfer_loop_count;
|
||||
|
||||
/// Special holding area for the RGBAQ.Q value, set when the ST
|
||||
/// register descriptor is written to. See EE Users manual page 153/154.
|
||||
f32 rgbaq_q;
|
||||
|
||||
public:
|
||||
template<class Archive>
|
||||
|
@ -33,9 +38,9 @@ public:
|
|||
archive(
|
||||
cereal::base_class<SizedWordRegister>(this),
|
||||
CEREAL_NVP(transfer_started),
|
||||
CEREAL_NVP(transfer_data_target),
|
||||
CEREAL_NVP(transfer_data_count),
|
||||
CEREAL_NVP(transfer_end_of_packet)
|
||||
CEREAL_NVP(tag),
|
||||
CEREAL_NVP(transfer_register_count),
|
||||
CEREAL_NVP(transfer_loop_count),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -39,14 +39,16 @@ public:
|
|||
Disabled // Disabled means the same operation mode as Image.
|
||||
};
|
||||
|
||||
Giftag() = default;
|
||||
|
||||
Giftag(const uqword tag) :
|
||||
tag(tag)
|
||||
{
|
||||
}
|
||||
|
||||
int nloop() const
|
||||
size_t nloop() const
|
||||
{
|
||||
return NLOOP.extract_from<int>(tag);
|
||||
return NLOOP.extract_from<size_t>(tag);
|
||||
}
|
||||
|
||||
bool eop() const
|
||||
|
@ -59,6 +61,12 @@ public:
|
|||
return EOP.extract_from<int>(tag) > 0;
|
||||
}
|
||||
|
||||
udword prim() const
|
||||
{
|
||||
// The PRIM register is dword in size.
|
||||
return PRIM.extract_from<udword>(tag);
|
||||
}
|
||||
|
||||
DataFormat flg() const
|
||||
{
|
||||
switch (FLG.extract_from<int>(tag))
|
||||
|
@ -76,94 +84,108 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
int nreg() const
|
||||
size_t nreg() const
|
||||
{
|
||||
int nreg = NREG.extract_from<int>(tag);
|
||||
size_t nreg = NREG.extract_from<size_t>(tag);
|
||||
|
||||
if (nreg >= 16 || nreg < 0)
|
||||
if (nreg >= 16)
|
||||
throw std::runtime_error("Unknown nreg value");
|
||||
|
||||
return (nreg == 0) ? 16 : nreg;
|
||||
}
|
||||
|
||||
int regs0() const
|
||||
size_t regs0() const
|
||||
{
|
||||
return REGS0.extract_from<int>(tag);
|
||||
return REGS0.extract_from<size_t>(tag);
|
||||
}
|
||||
|
||||
int regs1() const
|
||||
size_t regs1() const
|
||||
{
|
||||
return REGS1.extract_from<int>(tag);
|
||||
return REGS1.extract_from<size_t>(tag);
|
||||
}
|
||||
|
||||
int regs2() const
|
||||
size_t regs2() const
|
||||
{
|
||||
return REGS2.extract_from<int>(tag);
|
||||
return REGS2.extract_from<size_t>(tag);
|
||||
}
|
||||
|
||||
int regs3() const
|
||||
size_t regs3() const
|
||||
{
|
||||
return REGS3.extract_from<int>(tag);
|
||||
return REGS3.extract_from<size_t>(tag);
|
||||
}
|
||||
|
||||
int regs4() const
|
||||
size_t regs4() const
|
||||
{
|
||||
return REGS4.extract_from<int>(tag);
|
||||
return REGS4.extract_from<size_t>(tag);
|
||||
}
|
||||
|
||||
int regs5() const
|
||||
size_t regs5() const
|
||||
{
|
||||
return REGS5.extract_from<int>(tag);
|
||||
return REGS5.extract_from<size_t>(tag);
|
||||
}
|
||||
|
||||
int regs6() const
|
||||
size_t regs6() const
|
||||
{
|
||||
return REGS6.extract_from<int>(tag);
|
||||
return REGS6.extract_from<size_t>(tag);
|
||||
}
|
||||
|
||||
int regs7() const
|
||||
size_t regs7() const
|
||||
{
|
||||
return REGS7.extract_from<int>(tag);
|
||||
return REGS7.extract_from<size_t>(tag);
|
||||
}
|
||||
|
||||
int regs8() const
|
||||
size_t regs8() const
|
||||
{
|
||||
return REGS8.extract_from<int>(tag);
|
||||
return REGS8.extract_from<size_t>(tag);
|
||||
}
|
||||
|
||||
int regs9() const
|
||||
size_t regs9() const
|
||||
{
|
||||
return REGS9.extract_from<int>(tag);
|
||||
return REGS9.extract_from<size_t>(tag);
|
||||
}
|
||||
|
||||
int regs10() const
|
||||
size_t regs10() const
|
||||
{
|
||||
return REGS10.extract_from<int>(tag);
|
||||
return REGS10.extract_from<size_t>(tag);
|
||||
}
|
||||
|
||||
int regs11() const
|
||||
size_t regs11() const
|
||||
{
|
||||
return REGS11.extract_from<int>(tag);
|
||||
return REGS11.extract_from<size_t>(tag);
|
||||
}
|
||||
|
||||
int regs12() const
|
||||
size_t regs12() const
|
||||
{
|
||||
return REGS12.extract_from<int>(tag);
|
||||
return REGS12.extract_from<size_t>(tag);
|
||||
}
|
||||
|
||||
int regs13() const
|
||||
size_t regs13() const
|
||||
{
|
||||
return REGS13.extract_from<int>(tag);
|
||||
return REGS13.extract_from<size_t>(tag);
|
||||
}
|
||||
|
||||
int regs14() const
|
||||
size_t regs14() const
|
||||
{
|
||||
return REGS14.extract_from<int>(tag);
|
||||
return REGS14.extract_from<size_t>(tag);
|
||||
}
|
||||
|
||||
int regs15() const
|
||||
size_t regs15() const
|
||||
{
|
||||
return REGS15.extract_from<int>(tag);
|
||||
return REGS15.extract_from<size_t>(tag);
|
||||
}
|
||||
|
||||
size_t regs(const size_t descriptor_index) const
|
||||
{
|
||||
using RegisterDescriptor = size_t(Giftag::*)() const;
|
||||
static const RegisterDescriptor register_descriptors[] = {
|
||||
&Giftag::regs0, &Giftag::regs1, &Giftag::regs2, &Giftag::regs3,
|
||||
&Giftag::regs4, &Giftag::regs5, &Giftag::regs6, &Giftag::regs7,
|
||||
&Giftag::regs8, &Giftag::regs9, &Giftag::regs10, &Giftag::regs11,
|
||||
&Giftag::regs12, &Giftag::regs13, &Giftag::regs14, &Giftag::regs15
|
||||
};
|
||||
|
||||
auto fn = register_descriptors[descriptor_index];
|
||||
return (this->*fn)();
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
Loading…
Reference in a new issue