Updated the RSP and RDP implementations to be largely bit-perfect and pixel-accurate. [angrylion, Harmony]

This commit is contained in:
Ryan Holtz 2010-12-31 07:29:47 +00:00
parent de94242bcc
commit 0ea11333c6
24 changed files with 6606 additions and 9133 deletions

7
.gitattributes vendored
View File

@ -365,6 +365,7 @@ src/emu/cpu/powerpc/ppcfe.h svneol=native#text/plain
src/emu/cpu/rsp/rsp.c svneol=native#text/plain
src/emu/cpu/rsp/rsp.h svneol=native#text/plain
src/emu/cpu/rsp/rsp_dasm.c svneol=native#text/plain
src/emu/cpu/rsp/rspdiv.h svneol=native#text/plain
src/emu/cpu/rsp/rspdrc.c svneol=native#text/plain
src/emu/cpu/rsp/rspfe.c svneol=native#text/plain
src/emu/cpu/rsp/rspfe.h svneol=native#text/plain
@ -3984,17 +3985,11 @@ src/mame/video/rdpblend.c svneol=native#text/plain
src/mame/video/rdpblend.h svneol=native#text/plain
src/mame/video/rdpfb.c svneol=native#text/plain
src/mame/video/rdpfb.h svneol=native#text/plain
src/mame/video/rdpfetch.c svneol=native#text/plain
src/mame/video/rdpfetch.h svneol=native#text/plain
src/mame/video/rdpfiltr.c svneol=native#text/plain
src/mame/video/rdpfrect.c svneol=native#text/plain
src/mame/video/rdpfrect.h svneol=native#text/plain
src/mame/video/rdpspn16.c svneol=native#text/plain
src/mame/video/rdpspn16.h svneol=native#text/plain
src/mame/video/rdptpipe.c svneol=native#text/plain
src/mame/video/rdptpipe.h svneol=native#text/plain
src/mame/video/rdptrect.c svneol=native#text/plain
src/mame/video/rdptrect.h svneol=native#text/plain
src/mame/video/rdptri.h svneol=native#text/plain
src/mame/video/realbrk.c svneol=native#text/plain
src/mame/video/redalert.c svneol=native#text/plain

File diff suppressed because it is too large Load Diff

View File

@ -139,51 +139,20 @@ void rspdrc_add_dmem(running_device *device, void *base);
#define RSPDRC_STRICT_VERIFY 0x0001 /* verify all instructions */
typedef struct
typedef union
{
union
{
UINT8 b[16];
UINT16 s[8];
UINT32 l[4];
UINT64 d[2];
};
UINT64 d[2];
UINT32 l[4];
INT16 s[8];
UINT8 b[16];
} VECTOR_REG;
typedef struct
typedef union
{
union
{
INT64 l;
#ifdef LSB_FIRST
struct
{
INT16 z;
INT16 low;
INT16 mid;
INT16 high;
} h;
struct
{
INT32 zl;
INT32 mh;
} w;
#else
struct
{
INT16 high;
INT16 mid;
INT16 low;
INT16 z;
} h;
struct
{
INT32 mh;
INT32 zl;
} w;
#endif
};
} ACCUMULATOR;
INT64 q;
INT32 l[2];
INT16 w[4];
} ACCUMULATOR_REG;
typedef struct _rspimp_state rspimp_state;
typedef struct _rsp_state rsp_state;
@ -199,11 +168,12 @@ struct _rsp_state
UINT32 sr;
UINT32 step_count;
ACCUMULATOR accum[8];
ACCUMULATOR_REG accum[8];
INT32 square_root_res;
INT32 square_root_high;
INT32 reciprocal_res;
INT32 reciprocal_high;
INT32 dp_allowed;
UINT32 ppc;
UINT32 nextpc;

1027
src/emu/cpu/rsp/rspdiv.h Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -390,10 +390,13 @@ static void sp_dma(int direction)
src = (UINT8*)&rdram[sp_dram_addr / 4];
dst = (sp_mem_addr & 0x1000) ? (UINT8*)&rsp_imem[(sp_mem_addr & 0xfff) / 4] : (UINT8*)&rsp_dmem[(sp_mem_addr & 0xfff) / 4];
//printf("CPU %08x -> RSP %08x\n", sp_dram_addr, 0x04000000 | sp_mem_addr);
for (i=0; i < sp_dma_length; i++)
{
dst[BYTE4_XOR_BE(i)] = src[BYTE4_XOR_BE(i)];
//printf("%02x ", src[i]);
dst[i] = src[i];
}
//printf("\n");
sp_mem_addr += sp_dma_length;
sp_dram_addr += sp_dma_length;
@ -408,10 +411,13 @@ static void sp_dma(int direction)
src = (sp_mem_addr & 0x1000) ? (UINT8*)&rsp_imem[(sp_mem_addr & 0xfff) / 4] : (UINT8*)&rsp_dmem[(sp_mem_addr & 0xfff) / 4];
dst = (UINT8*)&rdram[sp_dram_addr / 4];
//printf("RSP %08x -> CPU %08x\n", 0x04000000 | sp_mem_addr, sp_dram_addr);
for (i=0; i < sp_dma_length; i++)
{
dst[BYTE4_XOR_BE(i)] = src[BYTE4_XOR_BE(i)];
//printf("%02x ", src[i]);
dst[i] = src[i];
}
//printf("\n");
sp_mem_addr += sp_dma_length;
sp_dram_addr += sp_dma_length;
@ -729,6 +735,7 @@ READ32_DEVICE_HANDLER( n64_dp_reg_r )
{
_n64_state *state = device->machine->driver_data<_n64_state>();
//printf("%08x\n", offset);
switch (offset)
{
case 0x00/4: // DP_START_REG
@ -755,6 +762,7 @@ WRITE32_DEVICE_HANDLER( n64_dp_reg_w )
{
_n64_state *state = device->machine->driver_data<_n64_state>();
//printf("%08x: %08x\n", offset, data);
switch (offset)
{
case 0x00/4: // DP_START_REG
@ -1091,6 +1099,8 @@ static AUDIO_DMA *audio_fifo_get_top(void)
}
}
#define N64_ATTOTIME_NORMALIZE(a) do { while ((a).attoseconds >= ATTOSECONDS_PER_SECOND) { (a).seconds++; (a).attoseconds -= ATTOSECONDS_PER_SECOND; } } while (0)
static void start_audio_dma(running_machine *machine)
{
INT16 *ram = (INT16*)rdram;
@ -2011,7 +2021,7 @@ MACHINE_START( n64 )
/* configure fast RAM regions for DRC */
mips3drc_add_fastram(machine->device("maincpu"), 0x00000000, 0x007fffff, FALSE, rdram);
rspdrc_set_options(machine->device("rsp"), 0);
rspdrc_set_options(machine->device("rsp"), RSPDRC_STRICT_VERIFY);
rspdrc_add_imem(machine->device("rsp"), rsp_imem);
rspdrc_add_dmem(machine->device("rsp"), rsp_dmem);
rspdrc_flush_drc_cache(machine->device("rsp"));

View File

@ -1206,7 +1206,7 @@ $(MAMEOBJ)/seibu.a: \
$(DRIVERS)/feversoc.o \
$(MAMEOBJ)/seta.a: \
$(DRIVERS)/aleck64.o $(MACHINE)/n64.o $(VIDEO)/n64.o $(VIDEO)/rdpblend.o $(VIDEO)/rdpfb.o $(VIDEO)/rdpspn16.o $(VIDEO)/rdptrect.o $(VIDEO)/rdpfrect.o $(VIDEO)/rdpfetch.o $(VIDEO)/rdptpipe.o \
$(DRIVERS)/aleck64.o $(MACHINE)/n64.o $(VIDEO)/n64.o $(VIDEO)/rdpblend.o $(VIDEO)/rdpfb.o $(VIDEO)/rdpspn16.o $(VIDEO)/rdptpipe.o \
$(DRIVERS)/darkhors.o \
$(DRIVERS)/hanaawas.o $(VIDEO)/hanaawas.o \
$(DRIVERS)/macs.o \

File diff suppressed because it is too large Load Diff

View File

@ -5,11 +5,8 @@
#include "video/rdpblend.h"
#include "video/rdptri.h"
#include "video/rdpfb.h"
#include "video/rdpfrect.h"
#include "video/rdptrect.h"
#include "video/rdptpipe.h"
#include "video/rdpspn16.h"
#include "video/rdpfetch.h"
/*****************************************************************************/
@ -37,10 +34,54 @@
#define XOR_SWAP_WORD 2
#define XOR_SWAP_DWORD 1
#define FORMAT_RGBA 0
#define FORMAT_YUV 1
#define FORMAT_CI 2
#define FORMAT_IA 3
#define FORMAT_I 4
#if LSB_FIRST
#define BYTE_XOR_DWORD_SWAP 7
#define WORD_XOR_DWORD_SWAP 3
#else
#define BYTE_XOR_DWORD_SWAP 4
#define WORD_XOR_DWORD_SWAP 2
#endif
#define DWORD_XOR_DWORD_SWAP 1
#define GET_LOW_RGBA16_TMEM(x) (m_rdp->ReplicatedRGBA()[((x) >> 1) & 0x1f])
#define GET_MED_RGBA16_TMEM(x) (m_rdp->ReplicatedRGBA()[((x) >> 6) & 0x1f])
#define GET_HI_RGBA16_TMEM(x) (m_rdp->ReplicatedRGBA()[((x) >> 11) & 0x1f])
#define MEM8_LIMIT 0x7fffff
#define MEM16_LIMIT 0x3fffff
#define MEM32_LIMIT 0x1fffff
#define RREADADDR8(in) (((in) <= MEM8_LIMIT) ? (((UINT8*)rdram)[(in) ^ BYTE_ADDR_XOR]) : 0)
#define RREADIDX16(in) (((in) <= MEM16_LIMIT) ? (((UINT16*)rdram)[(in) ^ WORD_ADDR_XOR]) : 0)
#define RREADIDX32(in) (((in) <= MEM32_LIMIT) ? (rdram[(in)]) : 0)
#define RWRITEADDR8(in, val) {if ((in) <= MEM8_LIMIT) ((UINT8*)rdram)[(in) ^ BYTE_ADDR_XOR] = val;}
#define RWRITEIDX16(in, val) {if ((in) <= MEM16_LIMIT) ((UINT16*)rdram)[(in) ^ WORD_ADDR_XOR] = val;}
#define RWRITEIDX32(in, val) {if ((in) <= MEM32_LIMIT) rdram[(in)] = val;}
#define GETLOWCOL(x) (((x) & 0x3e) << 2)
#define GETMEDCOL(x) (((x) & 0x7c0) >> 3)
#define GETHICOL(x) (((x) & 0xf800) >> 8)
#define HREADADDR8(in) (((in) <= MEM8_LIMIT) ? (m_rdp->GetHiddenBits()[(in) ^ BYTE_ADDR_XOR]) : 0)
#define HWRITEADDR8(in, val) {if ((in) <= MEM8_LIMIT) m_rdp->GetHiddenBits()[(in) ^ BYTE_ADDR_XOR] = val;}
//sign-extension macros
#define SIGN22(x) (((x) & 0x200000) ? ((x) | ~0x3fffff) : ((x) & 0x3fffff))
#define SIGN17(x) (((x) & 0x10000) ? ((x) | ~0x1ffff) : ((x) & 0x1ffff))
#define SIGN16(x) (((x) & 0x8000) ? ((x) | ~0xffff) : ((x) & 0xffff))
#define SIGN13(x) (((x) & 0x1000) ? ((x) | ~0x1fff) : ((x) & 0x1fff))
#define SIGN11(x) (((x) & 0x400) ? ((x) | ~0x7ff) : ((x) & 0x7ff))
#define SIGN9(x) (((x) & 0x100) ? ((x) | ~0x1ff) : ((x) & 0x1ff))
#define SIGN8(x) (((x) & 0x80) ? ((x) | ~0xff) : ((x) & 0xff))
#define KURT_AKELEY_SIGN9(x) ((((x) & 0x180) == 0x180) ? ((x) | ~0x1ff) : ((x) & 0x1ff))
/*****************************************************************************/
@ -86,8 +127,8 @@ class Tile
public:
int format; // Image data format: RGBA, YUV, CI, IA, I
int size; // Size of texel element: 4b, 8b, 16b, 32b
UINT32 line; // Size of tile line in bytes
UINT32 tmem; // Starting tmem address for this tile in bytes
int line; // Size of tile line in bytes
int tmem; // Starting tmem address for this tile in bytes
int palette; // Palette number for 4b CI texels
int ct, mt, cs, ms; // Clamp / mirror enable bits for S / T direction
int mask_t, shift_t, mask_s, shift_s; // Mask values / LOD shifts
@ -101,6 +142,8 @@ class MiscState
MiscState()
{
m_curpixel_cvg = 0;
m_curpixel_memcvg = 0;
m_curpixel_cvbit = 0;
m_curpixel_overlap = 0;
m_max_level = 0;
@ -121,6 +164,8 @@ class MiscState
UINT32 m_ti_address;
UINT32 m_curpixel_cvg;
UINT32 m_curpixel_memcvg;
UINT32 m_curpixel_cvbit;
UINT32 m_curpixel_overlap;
UINT8 m_random_seed;
@ -232,6 +277,14 @@ class ColorInputs
UINT8 *blender2b_a[2];
};
struct Rectangle
{
UINT16 m_xl; // 10.2 fixed-point
UINT16 m_yl; // 10.2 fixed-point
UINT16 m_xh; // 10.2 fixed-point
UINT16 m_yh; // 10.2 fixed-point
};
class Processor
{
public:
@ -245,47 +298,6 @@ class Processor
m_current = 0;
m_status = 0x88;
for(int i = 0; i < (1 << 16); i++)
{
UINT8 r = ((i >> 8) & 0xf8) | (i >> 13);
UINT8 g = ((i >> 3) & 0xf8) | ((i >> 8) & 0x07);
UINT8 b = ((i << 2) & 0xf8) | ((i >> 3) & 0x07);
UINT8 a = (i & 1) ? 0xff : 0;
m_rgb16_to_rgb32_lut[i] = (r << 24) | (g << 16) | (b << 8) | a;
r = g = b = (i >> 8) & 0xff;
a = i & 0xff;
m_ia8_to_rgb32_lut[i] = (r << 24) | (g << 16) | (b << 8) | a;
}
for(int i = 0; i < (1 << 24); i++)
{
UINT8 A = (i >> 16) & 0x000000ff;
UINT8 B = (i >> 8) & 0x000000ff;
UINT8 C = i & 0x000000ff;
m_cc_lut1[i] = (INT16)((((((INT32)A - (INT32)B) * (INT32)C) + 0x80) >> 8) & 0x0000ffff);
}
for(int i = 0; i < (1 << 16); i++)
{
for(int j = 0; j < (1 << 8); j++)
{
INT32 temp = (INT32)((INT16)i) + j;
if(temp > 255)
{
m_cc_lut2[(i << 8) | j] = 255;
}
else if(temp < 0)
{
m_cc_lut2[(i << 8) | j] = 0;
}
else
{
m_cc_lut2[(i << 8) | j] = (UINT8)temp;
}
}
}
for (int i = 0; i < 8; i++)
{
m_tiles[i].num = i;
@ -325,7 +337,7 @@ class Processor
m_machine = NULL;
memset(m_hidden_bits, 3, 4194304); // Hack / fix for letters in Rayman 2
//memset(m_hidden_bits, 3, 8388608);
m_prim_lod_frac = 0;
m_lod_frac = 0;
@ -342,16 +354,72 @@ class Processor
m_gamma_dither_table[i] <<= 1;
}
BuildCompressedZTable();
z_build_com_table();
for (int i = 0; i < 0x4000; i++)
{
UINT32 exponent = (i >> 11) & 7;
UINT32 mantissa = i & 0x7ff;
z_complete_dec_table[i] = ((mantissa << z_dec_table[exponent].shift) + z_dec_table[exponent].add) & 0x3fffff;
}
precalc_cvmask_derivatives();
for(int i = 0; i < 0x200; i++)
{
switch((i >> 7) & 3)
{
case 0:
case 1:
m_special_9bit_clamptable[i] = i & 0xff;
break;
case 2:
m_special_9bit_clamptable[i] = 0xff;
break;
case 3:
m_special_9bit_clamptable[i] = 0;
break;
}
}
for(int i = 0; i < 32; i++)
{
m_replicated_rgba[i] = (i << 3) | ((i >> 2) & 7);
}
}
~Processor() { }
UINT8* ReplicatedRGBA() { return m_replicated_rgba; }
void Dasm(char *buffer);
void ProcessList();
UINT32 ReadData(UINT32 address);
void set_span_base(int dr, int dg, int db, int da, int ds, int dt, int dw, int dz, int dymax, int dzpix)
{
m_span_dr = dr;
m_span_dg = dg;
m_span_db = db;
m_span_da = da;
m_span_ds = ds;
m_span_dt = dt;
m_span_dw = dw;
m_span_dz = dz;
m_span_dymax = dymax;
m_span_dzpix = dzpix;
}
void set_span_base_y(int dr, int dg, int db, int da, int dz)
{
m_span_drdy = dr;
m_span_dgdy = dg;
m_span_dbdy = db;
m_span_dady = da;
m_span_dzdy = dz;
}
void InitInternalState()
{
if(m_machine)
@ -362,7 +430,7 @@ class Processor
UINT8 *normpoint = memory_region(m_machine, "normpoint");
UINT8 *normslope = memory_region(m_machine, "normslope");
for(int i = 0; i < 64; i++)
for(INT32 i = 0; i < 64; i++)
{
m_norm_point_rom[i] = (normpoint[(i << 1) + 1] << 8) | normpoint[i << 1];
m_norm_slope_rom[i] = (normslope[(i << 1) + 1] << 8) | normslope[i << 1];
@ -430,6 +498,9 @@ class Processor
Color* GetTexel1Color() { return &m_texel1_color; }
void SetTexel1Color(UINT32 color) { m_texel1_color.c = color; }
Color* GetNextTexelColor() { return &m_next_texel_color; }
void SetNextTexelColor(UINT32 color) { m_next_texel_color.c = color; }
Color* GetShadeColor() { return &m_shade_color; }
void SetShadeColor(UINT32 color) { m_shade_color.c = color; }
@ -442,13 +513,17 @@ class Processor
Color* GetOne() { return &m_one_color; }
Color* GetZero() { return &m_zero_color; }
UINT8* GetLODFrac() { return &m_lod_frac; }
UINT8 GetLODFrac() { return m_lod_frac; }
void SetLODFrac(UINT8 lod_frac) { m_lod_frac = lod_frac; }
UINT8* GetPrimLODFrac() { return &m_prim_lod_frac; }
UINT8 GetPrimLODFrac() { return m_prim_lod_frac; }
void SetPrimLODFrac(UINT8 prim_lod_frac) { m_prim_lod_frac = prim_lod_frac; }
// Color Combiner
INT32 ColorCombinerEquation(INT32 a, INT32 b, INT32 c, INT32 d);
INT32 AlphaCombinerEquation(INT32 a, INT32 b, INT32 c, INT32 d);
void ColorCombiner2Cycle(bool noisecompute);
void ColorCombiner1Cycle(bool noisecompute);
void SetSubAInputRGB(UINT8 **input_r, UINT8 **input_g, UINT8 **input_b, int code);
void SetSubBInputRGB(UINT8 **input_r, UINT8 **input_g, UINT8 **input_b, int code);
void SetMulInputRGB(UINT8 **input_r, UINT8 **input_g, UINT8 **input_b, int code);
@ -464,10 +539,6 @@ class Processor
Tile* GetTiles(){ return m_tiles; }
// Emulation Accelerators
UINT32 LookUp16To32(UINT16 in) const { return m_rgb16_to_rgb32_lut[in]; }
UINT32 LookUpIA8To32(UINT16 in) const { return m_ia8_to_rgb32_lut[in]; }
UINT16* GetCCLUT1() { return m_cc_lut1; }
UINT8* GetCCLUT2() { return m_cc_lut2; }
UINT8 GetRandom() { return m_misc_state.m_random_seed += 0x13; }
// YUV Factors
@ -485,8 +556,9 @@ class Processor
// Render-related (move into eventual drawing-related classes?)
Rectangle* GetScissor() { return &m_scissor; }
void TCDiv(INT32 ss, INT32 st, INT32 sw, INT32* sss, INT32* sst);
void TCDivNoPersp(INT32 ss, INT32 st, INT32 sw, INT32* sss, INT32* sst);
UINT32 GetLog2(UINT32 lod_clamp);
void RenderSpans(int start, int end, int tilenum, bool shade, bool texture, bool zbuffer, bool flip);
void RenderSpans(int start, int end, int tilenum, bool flip);
UINT8* GetHiddenBits() { return m_hidden_bits; }
void GetAlphaCvg(UINT8 *comb_alpha);
const UINT8* GetBayerMatrix() const { return s_bayer_matrix; }
@ -495,11 +567,12 @@ class Processor
int GetCurrFIFOIndex() const { return m_cmd_cur; }
UINT32 GetFillColor32() const { return m_fill_color; }
void ZStore(UINT16* zb, UINT8* zhb, UINT32 z, UINT32 deltaz);
UINT32 DecompressZ(UINT16 *zb);
UINT16 DecompressDZ(UINT16* zb, UINT8* zhb);
void ZStore(UINT32 zcurpixel, UINT32 dzcurpixel, UINT32 z);
UINT32 ZDecompress(UINT32 zcurpixel);
UINT32 DZDecompress(UINT32 zcurpixel, UINT32 dzcurpixel);
UINT32 DZCompress(UINT32 value);
INT32 NormalizeDZPix(INT32 sum);
bool ZCompare(void* fb, UINT8* hb, UINT16* zb, UINT8* zhb, UINT32 sz, UINT16 dzpix);
bool ZCompare(UINT32 zcurpixel, UINT32 dzcurpixel, UINT32 sz, UINT16 dzpix);
// Fullscreen update-related
void VideoUpdate(bitmap_t *bitmap);
@ -548,6 +621,31 @@ class Processor
UINT32 AddLeftCvg(UINT32 x, UINT32 k);
UINT32* GetCommandData() { return m_cmd_data; }
UINT32* GetTempRectData() { return m_temp_rect_data; }
void GetDitherValues(int x, int y, int* cdith, int* adith);
int m_span_dr;
int m_span_drdy;
int m_span_dg;
int m_span_dgdy;
int m_span_db;
int m_span_dbdy;
int m_span_da;
int m_span_dady;
int m_span_ds;
int m_span_dt;
int m_span_dw;
int m_span_dz;
int m_span_dzdy;
int m_span_dymax;
int m_span_dzpix;
UINT32* GetSpecial9BitClampTable() { return m_special_9bit_clamptable; }
UINT16 decompress_cvmask_frombyte(UINT8 x);
void lookup_cvmask_derivatives(UINT32 mask, UINT8* offx, UINT8* offy);
protected:
Blender m_blender;
@ -571,6 +669,7 @@ class Processor
Color m_combined_color;
Color m_texel0_color;
Color m_texel1_color;
Color m_next_texel_color;
Color m_shade_color;
Color m_key_scale;
Color m_noise_color;
@ -582,12 +681,22 @@ class Processor
UINT32 m_fill_color;
UINT16 m_cc_lut1[(1<<24)];
UINT8 m_cc_lut2[(1<<24)];
UINT32 m_rgb16_to_rgb32_lut[(1 << 16)];
UINT32 m_ia8_to_rgb32_lut[(1 << 16)];
typedef struct
{
UINT8 cvg;
UINT8 cvbit;
UINT8 xoff;
UINT8 yoff;
} CVMASKDERIVATIVE;
CVMASKDERIVATIVE cvarray[(1 << 8)];
UINT16 z_com_table[0x40000]; //precalced table of compressed z values, 18b: 512 KB array!
UINT32 z_complete_dec_table[0x4000]; //the same for decompressed z values, 14b
UINT8 compressed_cvmasks[0x10000]; //16bit cvmask -> to byte
UINT32 m_cmd_data[0x1000];
UINT32 m_temp_rect_data[0x1000];
int m_cmd_ptr;
int m_cmd_cur;
@ -627,6 +736,13 @@ class Processor
INT32 m_gamma_table[256];
INT32 m_gamma_dither_table[0x4000];
UINT32 m_special_9bit_clamptable[512];
UINT8 m_replicated_rgba[32];
INT32 m_dzpix_enc;
INT32 m_dz_enc;
class ZDecompressEntry
{
public:
@ -634,9 +750,9 @@ class Processor
UINT32 add;
};
void BuildCompressedZTable();
UINT16 m_z_compress_table[0x40000];
static const ZDecompressEntry m_z_decompress_table[8];
void precalc_cvmask_derivatives(void);
void z_build_com_table(void);
static const ZDecompressEntry z_dec_table[8];
// Internal screen-update functions
void VideoUpdate16(bitmap_t *bitmap);

View File

@ -5,537 +5,265 @@
namespace N64
{
bool RDP::Blender::Blend(void* in_fb, UINT8* hb, RDP::Color c1, RDP::Color c2, int dith)
namespace RDP
{
switch(m_misc_state->m_fb_size)
bool Blender::Blend1Cycle(UINT32* fr, UINT32* fg, UINT32* fb, int dith, int adseed, int partialreject, int special_bsel)
{
ColorInputs* ci = m_rdp->GetColorInputs();
INT32 r, g, b;
if (!m_other_modes->alpha_cvg_select)
{
case PIXEL_SIZE_16BIT:
return Blend16Bit((UINT16*)in_fb, hb, c1, c2, dith);
case PIXEL_SIZE_32BIT:
return Blend32Bit((UINT32*)in_fb, c1, c2);
default:
fatalerror("Unsupported bit depth: %d\n", m_misc_state->m_fb_size);
break;
DitherA(&m_rdp->GetPixelColor()->i.a, adseed);
}
return false;
}
DitherA(&m_rdp->GetShadeColor()->i.a, adseed);
bool RDP::Blender::Blend16Bit(UINT16* fb, UINT8* hb, RDP::Color c1, RDP::Color c2, int dith)
{
switch(m_other_modes->cycle_type)
if (!AlphaCompare(m_rdp->GetPixelColor()->i.a))
{
case CYCLE_TYPE_1:
return Blend16Bit1Cycle(fb, hb, c1, dith);
case CYCLE_TYPE_2:
return Blend16Bit2Cycle(fb, hb, c1, c2, dith);
default:
fatalerror("Unsupported cycle type for Blend16Bit: %d\n", m_other_modes->cycle_type);
break;
//return false;
}
return false;
}
bool RDP::Blender::Blend16Bit1Cycle(UINT16* fb, UINT8* hb, RDP::Color c, int dith)
{
UINT16 mem = *fb;
UINT32 memory_cvg = 7;
if(m_other_modes->image_read_en)
{
memory_cvg = ((mem & 1) << 2) + (*hb & 3);
}
// Alpha compare
if (!AlphaCompare(c.i.a))
if (m_other_modes->antialias_en ? (!m_misc_state->m_curpixel_cvg) : (!m_misc_state->m_curpixel_cvbit))
{
return false;
}
if (!m_misc_state->m_curpixel_cvg) // New coverage is zero, so abort
bool dontblend = (partialreject && m_rdp->GetPixelColor()->i.a >= 0xff);
if (!m_blend_enable || dontblend)
{
return false;
}
int special_bsel = 0;
if (m_rdp->GetColorInputs()->blender2b_a[0] == &m_rdp->GetMemoryColor()->i.a)
{
special_bsel = 1;
}
m_rdp->GetPixelColor()->c = c.c;
if(!m_other_modes->z_compare_en)
{
m_misc_state->m_curpixel_overlap = 0;
}
m_rdp->GetMemoryColor()->c = m_rdp->LookUp16To32(mem);
m_rdp->GetMemoryColor()->i.a = (memory_cvg << 5) & 0xe0;
int r;
int g;
int b;
if(m_other_modes->z_compare_en)
{
if(m_other_modes->force_blend)
{
m_rdp->GetInvPixelColor()->i.a = 0xff - *m_rdp->GetColorInputs()->blender1b_a[0];
BlendEquation0Force(&r, &g, &b, special_bsel);
}
else
{
if (!m_misc_state->m_curpixel_overlap)
{
r = *m_rdp->GetColorInputs()->blender1a_r[0];
g = *m_rdp->GetColorInputs()->blender1a_g[0];
b = *m_rdp->GetColorInputs()->blender1a_b[0];
}
else
{
m_rdp->GetInvPixelColor()->i.a = 0xff - *m_rdp->GetColorInputs()->blender1b_a[0];
BlendEquation0NoForce(&r, &g, &b, special_bsel);
}
}
r = *ci->blender1a_r[0];
g = *ci->blender1a_g[0];
b = *ci->blender1a_b[0];
}
else
{
if(m_other_modes->force_blend)
{
m_rdp->GetInvPixelColor()->i.a = 0xff - *m_rdp->GetColorInputs()->blender1b_a[0];
BlendEquation0Force(&r, &g, &b, special_bsel);
}
else
{
r = *m_rdp->GetColorInputs()->blender1a_r[0];
g = *m_rdp->GetColorInputs()->blender1a_g[0];
b = *m_rdp->GetColorInputs()->blender1a_b[0];
}
m_rdp->GetInvPixelColor()->i.a = 0xff - *ci->blender1b_a[0];
BlendEquationCycle0(&r, &g, &b, special_bsel);
}
if(!(m_other_modes->rgb_dither_sel & 2))
if (m_other_modes->rgb_dither_sel < 3)
{
// Hack to prevent "double-dithering" artifacts
if (!(((r & 0xf8)==(m_rdp->GetMemoryColor()->i.r&0xf8) && (g & 0xf8) == (m_rdp->GetMemoryColor()->i.g & 0xf8) &&(b&0xf8)==(m_rdp->GetMemoryColor()->i.b&0xf8))))
{
DitherRGB(&r, &g, &b, dith);
}
DitherRGB(&r, &g, &b, dith);
}
return m_rdp->GetFramebuffer()->Write(fb, hb, r, g, b);
*fr = r;
*fg = g;
*fb = b;
return true;
}
bool RDP::Blender::Blend16Bit2Cycle(UINT16* fb, UINT8* hb, RDP::Color c1, RDP::Color c2, int dith)
bool Blender::Blend2Cycle(UINT32* fr, UINT32* fg, UINT32* fb, int dith, int adseed, int partialreject, int special_bsel0, int special_bsel1)
{
UINT16 mem = *fb;
UINT32 memory_cvg = 7;
if(m_other_modes->image_read_en)
ColorInputs* ci = m_rdp->GetColorInputs();
if (!m_other_modes->alpha_cvg_select)
{
memory_cvg = ((mem & 1) << 2) + (*hb & 3);
DitherA(&m_rdp->GetPixelColor()->i.a, adseed);
}
// Alpha compare
if (!AlphaCompare(c2.i.a))
DitherA(&m_rdp->GetShadeColor()->i.a, adseed);
if (!AlphaCompare(m_rdp->GetPixelColor()->i.a))
{
//return false;
}
if (m_other_modes->antialias_en ? (!m_misc_state->m_curpixel_cvg) : (!m_misc_state->m_curpixel_cvbit))
{
return false;
}
if (!m_misc_state->m_curpixel_cvg)
{
return false;
}
m_rdp->GetInvPixelColor()->i.a = 0xff - *ci->blender1b_a[0];
int special_bsel = 0;
if (m_rdp->GetColorInputs()->blender2b_a[0] == &m_rdp->GetMemoryColor()->i.a)
{
special_bsel = 1;
}
m_rdp->GetPixelColor()->c = c2.c;
if(m_other_modes->z_compare_en)
{
m_misc_state->m_curpixel_overlap = 0;
}
m_rdp->GetMemoryColor()->c = m_rdp->LookUp16To32(mem);
m_rdp->GetMemoryColor()->i.a = (memory_cvg << 5) & 0xe0;
m_rdp->GetInvPixelColor()->i.a = 0xff - *m_rdp->GetColorInputs()->blender1b_a[0];
int r, g, b;
if(m_other_modes->force_blend)
{
BlendEquation0Force(&r, &g, &b, special_bsel);
}
else
{
BlendEquation0NoForce(&r, &g, &b, special_bsel);
}
INT32 r, g, b;
BlendEquationCycle0(&r, &g, &b, special_bsel0);
m_rdp->GetBlendedColor()->i.r = r;
m_rdp->GetBlendedColor()->i.g = g;
m_rdp->GetBlendedColor()->i.b = b;
m_rdp->GetBlendedColor()->i.a = m_rdp->GetPixelColor()->i.a;
m_rdp->GetPixelColor()->i.r = r;
m_rdp->GetPixelColor()->i.g = g;
m_rdp->GetPixelColor()->i.b = b;
m_rdp->GetInvPixelColor()->i.a = 0xff - *m_rdp->GetColorInputs()->blender1b_a[1];
if(m_other_modes->force_blend)
bool dontblend = (partialreject && m_rdp->GetPixelColor()->i.a >= 0xff);
if (!m_blend_enable || dontblend)
{
if (m_rdp->GetColorInputs()->blender2b_a[1] == &m_rdp->GetMemoryColor()->i.a)
{
special_bsel = 1;
}
else
{
special_bsel = 0;
}
BlendEquation1Force(&r, &g, &b, special_bsel);
r = *ci->blender1a_r[1];
g = *ci->blender1a_g[1];
b = *ci->blender1a_b[1];
}
else
{
if (!m_misc_state->m_curpixel_overlap)
{
r = *m_rdp->GetColorInputs()->blender1a_r[1];
g = *m_rdp->GetColorInputs()->blender1a_g[1];
b = *m_rdp->GetColorInputs()->blender1a_b[1];
}
else
{
if (m_rdp->GetColorInputs()->blender2b_a[1] == &m_rdp->GetMemoryColor()->i.a)
{
special_bsel = 1;
}
else
{
special_bsel = 0;
}
BlendEquation1NoForce(&r, &g, &b, special_bsel);
}
m_rdp->GetInvPixelColor()->i.a = 0xff - *ci->blender1b_a[1];
BlendEquationCycle1(&r, &g, &b, special_bsel1);
}
if(!(m_other_modes->rgb_dither_sel & 2))
if (m_other_modes->rgb_dither_sel < 3)
{
// Hack to prevent "double-dithering" artifacts
if (!(((r & 0xf8)==(m_rdp->GetMemoryColor()->i.r&0xf8) && (g & 0xf8) == (m_rdp->GetMemoryColor()->i.g & 0xf8) &&(b&0xf8)==(m_rdp->GetMemoryColor()->i.b&0xf8))))
{
DitherRGB(&r, &g, &b, dith);
}
DitherRGB(&r, &g, &b, dith);
}
return m_rdp->GetFramebuffer()->Write(fb, hb, r, g, b);
*fr = r;
*fg = g;
*fb = b;
return true;
}
bool RDP::Blender::Blend32Bit(UINT32* fb, RDP::Color c1, RDP::Color c2)
void Blender::BlendEquationCycle0(int* r, int* g, int* b, int bsel_special)
{
switch(m_other_modes->cycle_type)
{
case CYCLE_TYPE_1:
return Blend32Bit1Cycle(fb, c1);
ColorInputs* ci = m_rdp->GetColorInputs();
UINT8 blend1a = *ci->blender1b_a[0] >> 3;
UINT8 blend2a = *ci->blender2b_a[0] >> 3;
case CYCLE_TYPE_2:
return Blend32Bit2Cycle(fb, c1, c2);
default:
fatalerror("Unsupported cycle type for Blend16Bit: %d\n", m_other_modes->cycle_type);
break;
}
return false;
}
bool RDP::Blender::Blend32Bit1Cycle(UINT32* fb, RDP::Color c)
{
UINT32 mem = *fb;
int r, g, b;
// Alpha compare
if (!AlphaCompare(c.i.a))
{
return 0;
}
if (!m_misc_state->m_curpixel_cvg)
{
return 0;
}
m_rdp->GetPixelColor()->c = c.c;
if (!m_other_modes->z_compare_en)
{
m_misc_state->m_curpixel_overlap = 0;
}
m_rdp->GetMemoryColor()->i.r = (mem >> 24) & 0xff;
m_rdp->GetMemoryColor()->i.g = (mem >> 16) & 0xff;
m_rdp->GetMemoryColor()->i.b = (mem >> 8) & 0xff;
if (m_other_modes->image_read_en)
{
m_rdp->GetMemoryColor()->i.a = mem & 0xe0;
}
else
{
m_rdp->GetMemoryColor()->i.a = 0xe0;
}
if (!m_misc_state->m_curpixel_overlap && !m_other_modes->force_blend)
{
r = *m_rdp->GetColorInputs()->blender1a_r[0];
g = *m_rdp->GetColorInputs()->blender1a_g[0];
b = *m_rdp->GetColorInputs()->blender1a_b[0];
}
else
{
m_rdp->GetInvPixelColor()->i.a = 0xff - *m_rdp->GetColorInputs()->blender1b_a[0];
if(m_other_modes->force_blend)
{
BlendEquation0Force(&r, &g, &b, m_misc_state->m_special_bsel0);
}
else
{
BlendEquation0NoForce(&r, &g, &b, m_misc_state->m_special_bsel0);
}
}
return m_rdp->GetFramebuffer()->Write(fb, NULL, r, g, b);
}
bool RDP::Blender::Blend32Bit2Cycle(UINT32* fb, RDP::Color c1, RDP::Color c2)
{
UINT32 mem = *fb;
int r, g, b;
// Alpha compare
if (!AlphaCompare(c2.i.a))
{
return 0;
}
if (!m_misc_state->m_curpixel_cvg)
{
return 0;
}
m_rdp->GetPixelColor()->c = c2.c;
if (!m_other_modes->z_compare_en)
{
m_misc_state->m_curpixel_overlap = 0;
}
m_rdp->GetMemoryColor()->i.r = (mem >>24) & 0xff;
m_rdp->GetMemoryColor()->i.g = (mem >> 16) & 0xff;
m_rdp->GetMemoryColor()->i.b = (mem >> 8) & 0xff;
if (m_other_modes->image_read_en)
{
m_rdp->GetMemoryColor()->i.a = (mem & 0xe0);
}
else
{
m_rdp->GetMemoryColor()->i.a = 0xe0;
}
m_rdp->GetInvPixelColor()->i.a = 0xff - *m_rdp->GetColorInputs()->blender1b_a[0];
if(m_other_modes->force_blend)
{
BlendEquation0Force(&r, &g, &b, m_misc_state->m_special_bsel0);
}
else
{
BlendEquation0NoForce(&r, &g, &b, m_misc_state->m_special_bsel0);
}
m_rdp->GetBlendedColor()->i.r = r;
m_rdp->GetBlendedColor()->i.g = g;
m_rdp->GetBlendedColor()->i.b = b;
m_rdp->GetPixelColor()->i.r = r;
m_rdp->GetPixelColor()->i.g = g;
m_rdp->GetPixelColor()->i.b = b;
if (!m_misc_state->m_curpixel_overlap && !m_other_modes->force_blend)
{
r = *m_rdp->GetColorInputs()->blender1a_r[1];
g = *m_rdp->GetColorInputs()->blender1a_g[1];
b = *m_rdp->GetColorInputs()->blender1a_b[1];
}
else
{
m_rdp->GetInvPixelColor()->i.a = 0xff - *m_rdp->GetColorInputs()->blender1b_a[1];
if(m_other_modes->force_blend)
{
BlendEquation1Force(&r, &g, &b, m_misc_state->m_special_bsel1);
}
else
{
BlendEquation1NoForce(&r, &g, &b, m_misc_state->m_special_bsel1);
}
}
return m_rdp->GetFramebuffer()->Write(fb, NULL, r, g, b);
}
void RDP::Blender::BlendEquation0Force(INT32* r, INT32* g, INT32* b, int bsel_special)
{
int blend1a = *m_rdp->GetColorInputs()->blender1b_a[0];
if (bsel_special)
{
blend1a &= 0xe0;
blend1a = (blend1a >> m_shift_a) & 0x1C;
blend2a = (blend2a >> m_shift_b) & 0x1C;
}
INT32 tr = ((int)(*m_rdp->GetColorInputs()->blender1a_r[0]) * blend1a + (int)(*m_rdp->GetColorInputs()->blender2a_r[0]) * *m_rdp->GetColorInputs()->blender2b_a[0] + ((int)(*m_rdp->GetColorInputs()->blender2a_r[0]) << (3 + bsel_special))) >> 8;
INT32 tg = ((int)(*m_rdp->GetColorInputs()->blender1a_g[0]) * blend1a + (int)(*m_rdp->GetColorInputs()->blender2a_g[0]) * *m_rdp->GetColorInputs()->blender2b_a[0] + ((int)(*m_rdp->GetColorInputs()->blender2a_g[0]) << (3 + bsel_special))) >> 8;
INT32 tb = ((int)(*m_rdp->GetColorInputs()->blender1a_b[0]) * blend1a + (int)(*m_rdp->GetColorInputs()->blender2a_b[0]) * *m_rdp->GetColorInputs()->blender2b_a[0] + ((int)(*m_rdp->GetColorInputs()->blender2a_b[0]) << (3 + bsel_special))) >> 8;
UINT32 sum = ((blend1a >> 2) + (blend2a >> 2) + 1) & 0xf;
if (tr > 255) *r = 255; else *r = tr;
if (tg > 255) *g = 255; else *g = tg;
if (tb > 255) *b = 255; else *b = tb;
}
*r = (((int)(*ci->blender1a_r[0]) * (int)(blend1a))) +
(((int)(*ci->blender2a_r[0]) * (int)(blend2a)));
*g = (((int)(*ci->blender1a_g[0]) * (int)(blend1a))) +
(((int)(*ci->blender2a_g[0]) * (int)(blend2a)));
*b = (((int)(*ci->blender1a_b[0]) * (int)(blend1a))) +
(((int)(*ci->blender2a_b[0]) * (int)(blend2a)));
void RDP::Blender::BlendEquation0NoForce(INT32* r, INT32* g, INT32* b, int bsel_special)
{
UINT8 blend1a = *m_rdp->GetColorInputs()->blender1b_a[0];
UINT8 blend2a = *m_rdp->GetColorInputs()->blender2b_a[0];
if (bsel_special)
{
blend1a &= 0xe0;
}
UINT32 sum = (((blend1a >> 5) + (blend2a >> 5) + 1) & 0xf) << 5;
INT32 tr = (((int)(*m_rdp->GetColorInputs()->blender1a_r[0]) * (int)(blend1a))) +
(((int)(*m_rdp->GetColorInputs()->blender2a_r[0]) * (int)(blend2a)));
tr += (bsel_special) ? (((int)(*m_rdp->GetColorInputs()->blender2a_r[0])) << 5) : (((int)(*m_rdp->GetColorInputs()->blender2a_r[0])) << 3);
INT32 tg = (((int)(*m_rdp->GetColorInputs()->blender1a_g[0]) * (int)(blend1a))) +
(((int)(*m_rdp->GetColorInputs()->blender2a_g[0]) * (int)(blend2a)));
tg += (bsel_special) ? ((int)((*m_rdp->GetColorInputs()->blender2a_g[0])) << 5) : (((int)(*m_rdp->GetColorInputs()->blender2a_g[0])) << 3);
INT32 tb = (((int)(*m_rdp->GetColorInputs()->blender1a_b[0]) * (int)(blend1a))) +
(((int)(*m_rdp->GetColorInputs()->blender2a_b[0]) * (int)(blend2a)));
tb += (bsel_special) ? (((int)(*m_rdp->GetColorInputs()->blender2a_b[0])) << 5) : (((int)(*m_rdp->GetColorInputs()->blender2a_b[0])) << 3);
if (sum)
{
tr /= sum;
tg /= sum;
tb /= sum;
*r += (((int)*ci->blender2a_r[0]) << 2);
*g += (((int)*ci->blender2a_g[0]) << 2);
*b += (((int)*ci->blender2a_b[0]) << 2);
}
else
{
*r = *g = *b = 0xff;
return;
*r += (int)*ci->blender2a_r[0];
*g += (int)*ci->blender2a_g[0];
*b += (int)*ci->blender2a_b[0];
}
if (tr > 255) *r = 255; else *r = tr;
if (tg > 255) *g = 255; else *g = tg;
if (tb > 255) *b = 255; else *b = tb;
}
*r >>= 2;
*g >>= 2;
*b >>= 2;
void RDP::Blender::BlendEquation1Force(INT32* r, INT32* g, INT32* b, int bsel_special)
{
UINT8 blend1a = *m_rdp->GetColorInputs()->blender1b_a[1];
UINT8 blend2a = *m_rdp->GetColorInputs()->blender2b_a[1];
if (bsel_special)
if (m_other_modes->force_blend)
{
blend1a &= 0xe0;
}
INT32 tr = (((int)(*m_rdp->GetColorInputs()->blender1a_r[1]) * (int)(blend1a))) +
(((int)(*m_rdp->GetColorInputs()->blender2a_r[1]) * (int)(blend2a)));
tr += (bsel_special) ? (((int)(*m_rdp->GetColorInputs()->blender2a_r[1])) << 5) : (((int)(*m_rdp->GetColorInputs()->blender2a_r[1])) << 3);
INT32 tg = (((int)(*m_rdp->GetColorInputs()->blender1a_g[1]) * (int)(blend1a))) +
(((int)(*m_rdp->GetColorInputs()->blender2a_g[1]) * (int)(blend2a)));
tg += (bsel_special) ? ((int)((*m_rdp->GetColorInputs()->blender2a_g[1])) << 5) : (((int)(*m_rdp->GetColorInputs()->blender2a_g[1])) << 3);
INT32 tb = (((int)(*m_rdp->GetColorInputs()->blender1a_b[1]) * (int)(blend1a))) +
(((int)(*m_rdp->GetColorInputs()->blender2a_b[1]) * (int)(blend2a)));
tb += (bsel_special) ? (((int)(*m_rdp->GetColorInputs()->blender2a_b[1])) << 5) : (((int)(*m_rdp->GetColorInputs()->blender2a_b[1])) << 3);
tr >>= 8;
tg >>= 8;
tb >>= 8;
if (tr > 255) *r = 255; else *r = tr;
if (tg > 255) *g = 255; else *g = tg;
if (tb > 255) *b = 255; else *b = tb;
}
void RDP::Blender::BlendEquation1NoForce(INT32* r, INT32* g, INT32* b, int bsel_special)
{
UINT8 blend1a = *m_rdp->GetColorInputs()->blender1b_a[1];
UINT8 blend2a = *m_rdp->GetColorInputs()->blender2b_a[1];
if (bsel_special)
{
blend1a &= 0xe0;
}
UINT32 sum = (((blend1a >> 5) + (blend2a >> 5) + 1) & 0xf) << 5;
INT32 tr = (((int)(*m_rdp->GetColorInputs()->blender1a_r[1]) * (int)(blend1a))) +
(((int)(*m_rdp->GetColorInputs()->blender2a_r[1]) * (int)(blend2a)));
tr += (bsel_special) ? (((int)(*m_rdp->GetColorInputs()->blender2a_r[1])) << 5) : (((int)(*m_rdp->GetColorInputs()->blender2a_r[1])) << 3);
INT32 tg = (((int)(*m_rdp->GetColorInputs()->blender1a_g[1]) * (int)(blend1a))) +
(((int)(*m_rdp->GetColorInputs()->blender2a_g[1]) * (int)(blend2a)));
tg += (bsel_special) ? ((int)((*m_rdp->GetColorInputs()->blender2a_g[1])) << 5) : (((int)(*m_rdp->GetColorInputs()->blender2a_g[1])) << 3);
INT32 tb = (((int)(*m_rdp->GetColorInputs()->blender1a_b[1]) * (int)(blend1a))) +
(((int)(*m_rdp->GetColorInputs()->blender2a_b[1]) * (int)(blend2a)));
tb += (bsel_special) ? (((int)(*m_rdp->GetColorInputs()->blender2a_b[1])) << 5) : (((int)(*m_rdp->GetColorInputs()->blender2a_b[1])) << 3);
if (sum)
{
tr /= sum;
tg /= sum;
tb /= sum;
*r >>= 3;
*g >>= 3;
*b >>= 3;
}
else
{
*r = *g = *b = 0xff;
return;
}
if (tr > 255) *r = 255; else *r = tr;
if (tg > 255) *g = 255; else *g = tg;
if (tb > 255) *b = 255; else *b = tb;
}
bool RDP::Blender::AlphaCompare(UINT8 alpha)
{
if(m_other_modes->alpha_compare_en)
{
if(m_other_modes->dither_alpha_en)
if (sum)
{
return (alpha > m_rdp->GetRandom());
*r /= sum;
*g /= sum;
*b /= sum;
}
else
{
return (alpha > m_rdp->GetBlendColor()->i.a);
*r = *g = *b = 0xff;
}
}
if (*r > 255) *r = 255;
if (*g > 255) *g = 255;
if (*b > 255) *b = 255;
}
void Blender::BlendEquationCycle1(INT32* r, INT32* g, INT32* b, int bsel_special)
{
ColorInputs* ci = m_rdp->GetColorInputs();
UINT8 blend1a = *ci->blender1b_a[1] >> 3;
UINT8 blend2a = *ci->blender2b_a[1] >> 3;
if (bsel_special)
{
blend1a = (blend1a >> m_shift_a) & 0x1C;
blend2a = (blend2a >> m_shift_b) & 0x1C;
}
UINT32 sum = ((blend1a >> 2) + (blend2a >> 2) + 1) & 0xf;
*r = (((int)(*ci->blender1a_r[1]) * (int)(blend1a))) +
(((int)(*ci->blender2a_r[1]) * (int)(blend2a)));
*g = (((int)(*ci->blender1a_g[1]) * (int)(blend1a))) +
(((int)(*ci->blender2a_g[1]) * (int)(blend2a)));
*b = (((int)(*ci->blender1a_b[1]) * (int)(blend1a))) +
(((int)(*ci->blender2a_b[1]) * (int)(blend2a)));
if (bsel_special)
{
*r += (((int)*ci->blender2a_r[1]) << 2);
*g += (((int)*ci->blender2a_g[1]) << 2);
*b += (((int)*ci->blender2a_b[1]) << 2);
}
else
{
*r += (int)*ci->blender2a_r[1];
*g += (int)*ci->blender2a_g[1];
*b += (int)*ci->blender2a_b[1];
}
*r >>= 2;
*g >>= 2;
*b >>= 2;
if (m_other_modes->force_blend)
{
*r >>= 3;
*g >>= 3;
*b >>= 3;
}
else
{
if (sum)
{
*r /= sum;
*g /= sum;
*b /= sum;
}
else
{
*r = *g = *b = 0xff;
}
}
if (*r > 255) *r = 255;
if (*g > 255) *g = 255;
if (*b > 255) *b = 255;
}
bool Blender::AlphaCompare(UINT8 alpha)
{
INT32 threshold;
if (m_other_modes->alpha_compare_en)
{
threshold = (m_other_modes->dither_alpha_en) ? (mame_rand(m_machine) & 0xff) : m_rdp->GetBlendColor()->i.a;
if (alpha < threshold)
{
return false;
}
return true;
}
return true;
}
void RDP::Blender::DitherRGB(INT32 *r, INT32 *g, INT32 *b, int dith)
void Blender::DitherA(UINT8 *a, int dith)
{
INT32 new_a = *a + dith;
if(new_a & 0x100)
{
new_a = 0xff;
}
*a = (UINT8)new_a;
}
void Blender::DitherRGB(INT32 *r, INT32 *g, INT32 *b, int dith)
{
if ((*r & 7) > dith)
{
@ -563,4 +291,6 @@ void RDP::Blender::DitherRGB(INT32 *r, INT32 *g, INT32 *b, int dith)
}
}
} // namespace RDP
} // namespace N64

View File

@ -17,35 +17,42 @@ class Color;
class Blender
{
public:
Blender() { }
Blender()
{
m_blend_enable = false;
}
bool Blend(void* in_fb, UINT8* hb, Color c1, Color c2, int dith);
bool Blend2Cycle(UINT32* fr, UINT32* fg, UINT32* fb, int dith, int adseed, int partialreject, int bsel0, int bsel1);
bool Blend1Cycle(UINT32* fr, UINT32* fg, UINT32* fb, int dith, int adseed, int partialreject, int special_bsel);
void SetOtherModes(OtherModes* other_modes) { m_other_modes = other_modes; }
void SetMiscState(MiscState* misc_state) { m_misc_state = misc_state; }
void SetMachine(running_machine* machine) { m_machine = machine; }
void SetProcessor(Processor* rdp) { m_rdp = rdp; }
void SetBlendEnable(bool enable) { m_blend_enable = enable; }
bool GetBlendEnable() { return m_blend_enable; }
void SetShiftA(INT32 shift) { m_shift_a = shift; }
void SetShiftB(INT32 shift) { m_shift_b = shift; }
private:
running_machine* m_machine;
OtherModes* m_other_modes;
MiscState* m_misc_state;
Processor* m_rdp;
bool Blend16Bit(UINT16* fb, UINT8* hb, RDP::Color c1, RDP::Color c2, int dith);
bool Blend16Bit1Cycle(UINT16* fb, UINT8* hb, RDP::Color c, int dith);
bool Blend16Bit2Cycle(UINT16* fb, UINT8* hb, RDP::Color c1, RDP::Color c2, int dith);
bool Blend32Bit(UINT32* fb, RDP::Color c1, RDP::Color c2);
bool Blend32Bit1Cycle(UINT32* fb, RDP::Color c);
bool Blend32Bit2Cycle(UINT32* fb, RDP::Color c1, RDP::Color c2);
bool m_blend_enable;
INT32 m_shift_a;
INT32 m_shift_b;
void BlendEquationCycle0(INT32* r, INT32* g, INT32* b, int bsel_special);
void BlendEquationCycle1(INT32* r, INT32* g, INT32* b, int bsel_special);
bool AlphaCompare(UINT8 alpha);
void BlendEquation0Force(INT32* r, INT32* g, INT32* b, int bsel_special);
void BlendEquation0NoForce(INT32* r, INT32* g, INT32* b, int bsel_special);
void BlendEquation1Force(INT32* r, INT32* g, INT32* b, int bsel_special);
void BlendEquation1NoForce(INT32* r, INT32* g, INT32* b, int bsel_special);
void DitherRGB(INT32* r, INT32* g, INT32* b, int dith);
void DitherA(UINT8* a, int dith);
};
} // namespace RDP

View File

@ -5,161 +5,271 @@
namespace N64
{
bool RDP::Framebuffer::Write(void *fb, UINT8* hb, UINT32 r, UINT32 g, UINT32 b)
namespace RDP
{
void Framebuffer::Write(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b)
{
switch(m_misc_state->m_fb_size)
{
case PIXEL_SIZE_16BIT:
return Write16Bit((UINT16*)fb, hb, r, g, b);
Write16Bit(curpixel, r, g, b);
break;
case PIXEL_SIZE_32BIT:
return Write32Bit((UINT32*)fb, r, g, b);
Write32Bit(curpixel, r, g, b);
break;
default:
fatalerror("Unsupported bit depth: %d\n", m_misc_state->m_fb_size);
break;
}
return false;
}
bool RDP::Framebuffer::Write16Bit(UINT16 *fb, UINT8* hb, UINT32 r, UINT32 g, UINT32 b)
void Framebuffer::Write16Bit(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b)
{
#undef CVG_DRAW
//#define CVG_DRAW
#ifdef CVG_DRAW
int covdraw;
if (m_misc_state->m_curpixel_cvg == 8)
{
covdraw = 255;
}
else
{
covdraw = m_misc_state->m_curpixel_cvg << 5;
}
int covdraw = (curpixel_cvg - 1) << 5;
r = covdraw;
g = covdraw;
b = covdraw;
#endif
if (!m_other_modes->z_compare_en)
{
m_misc_state->m_curpixel_overlap = 0;
}
UINT32 fb = (m_misc_state->m_fb_address >> 1) + curpixel;
UINT32 hb = fb;
UINT32 memory_cvg = 8;
if (m_other_modes->image_read_en)
#if 0
if (m_misc_state->m_curpixel_cvg > 8 && m_other_modes->z_mode != 1)
{
memory_cvg = ((*fb & 1) << 2) + (*hb & 3) + 1;
stricterror("FBWRITE_16: curpixel_cvg %d", m_misc_state->m_curpixel_cvg);
}
UINT32 newcvg = m_misc_state->m_curpixel_cvg + memory_cvg;
bool wrapped = newcvg > 8;
#endif
UINT16 finalcolor = ((r >> 3) << 11) | ((g >> 3) << 6) | ((b >> 3) << 1);
UINT32 finalcvg = 0;
UINT32 clamped_cvg = wrapped ? 8 : newcvg;
newcvg = wrapped ? (newcvg - 8) : newcvg;
m_misc_state->m_curpixel_cvg--;
newcvg--;
memory_cvg--;
clamped_cvg--;
if (m_other_modes->color_on_cvg && !wrapped)
if (m_other_modes->color_on_cvg && !m_pre_wrap)
{
*fb &= 0xfffe;
*fb |= ((newcvg >> 2) & 1);
*hb = (newcvg & 3);
return false;
finalcolor = RREADIDX16(fb) & 0xfffe;
}
switch(m_other_modes->cvg_dest)
{
case 0:
if (!m_other_modes->force_blend && !m_misc_state->m_curpixel_overlap)
case 0:
if (!m_rdp->GetBlender()->GetBlendEnable())
{
finalcvg = (m_misc_state->m_curpixel_cvg - 1) & 7;
RWRITEIDX16(fb, finalcolor | ((finalcvg >> 2) & 1));
HWRITEADDR8(hb, finalcvg & 3);
}
else
{
finalcvg = m_misc_state->m_curpixel_cvg + m_misc_state->m_curpixel_memcvg;
if (finalcvg & 8)
{
*fb = finalcolor | ((m_misc_state->m_curpixel_cvg >> 2) & 1);
*hb = (m_misc_state->m_curpixel_cvg & 3);
finalcvg = 7;
}
else
{
*fb = finalcolor | ((clamped_cvg >> 2) & 1);
*hb = (clamped_cvg & 3);
}
break;
case 1:
*fb = finalcolor | ((newcvg >> 2) & 1);
*hb = (newcvg & 3);
break;
case 2:
*fb = finalcolor | 1;
*hb = 3;
break;
case 3:
*fb = finalcolor | ((memory_cvg >> 2) & 1);
*hb = (memory_cvg & 3);
break;
RWRITEIDX16(fb, finalcolor | ((finalcvg >> 2) & 1));
HWRITEADDR8(hb, finalcvg & 3);
}
break;
case 1:
finalcvg = (m_misc_state->m_curpixel_cvg + m_misc_state->m_curpixel_memcvg) & 7;
RWRITEIDX16(fb, finalcolor | ((finalcvg >> 2) & 1));
HWRITEADDR8(hb, finalcvg & 3);
break;
case 2:
RWRITEIDX16(fb, finalcolor | 1);
HWRITEADDR8(hb, 3);
break;
case 3:
RWRITEIDX16(fb, finalcolor | ((m_misc_state->m_curpixel_memcvg >> 2) & 1));
HWRITEADDR8(hb, m_misc_state->m_curpixel_memcvg & 3);
break;
}
return true;
}
bool RDP::Framebuffer::Write32Bit(UINT32 *fb, UINT32 r, UINT32 g, UINT32 b)
void Framebuffer::Write32Bit(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b)
{
UINT32 finalcolor = (r << 24) | (g << 16) | (b << 8);
UINT32 memory_alphachannel = *fb & 0xff;
UINT32 fb = (m_misc_state->m_fb_address >> 2) + curpixel;
UINT32 finalcolor = (r << 24) | (g << 16) | (b << 8);//cvg as 3 MSBs of alpha channel;
UINT32 finalcvg = 0;
UINT32 memory_cvg = 8;
#if 0
if (curpixel_cvg > 8 && m_other_modes->z_mode != 1)
{
stricterror("FBWRITE_16: curpixel_cvg %d", curpixel_cvg);
}
#endif
if (m_other_modes->color_on_cvg && !m_pre_wrap)
{
finalcolor = RREADIDX32(fb) & 0xffffff00;
}
switch(m_other_modes->cvg_dest)
{
case 0: //normal
if (!m_rdp->GetBlender()->GetBlendEnable())
{
finalcvg = (m_misc_state->m_curpixel_cvg - 1) & 7;
finalcolor |= (finalcvg << 5);
RWRITEIDX32(fb, finalcolor);
}
else
{
finalcvg = m_misc_state->m_curpixel_cvg + m_misc_state->m_curpixel_memcvg;
if (finalcvg & 8)
{
finalcvg = 7;
}
finalcolor |= (finalcvg << 5);
RWRITEIDX32(fb, finalcolor);
}
break;
case 1:
finalcvg = (m_misc_state->m_curpixel_cvg + m_misc_state->m_curpixel_memcvg) & 7;
finalcolor |= (finalcvg << 5);
RWRITEIDX32(fb, finalcolor);
break;
case 2:
RWRITEIDX32(fb, finalcolor | 0xE0);
break;
case 3:
finalcolor |= (m_misc_state->m_curpixel_memcvg << 5);
RWRITEIDX32(fb, finalcolor);
break;
}
}
void Framebuffer::Read(UINT32 curpixel)
{
switch(m_misc_state->m_fb_size)
{
case PIXEL_SIZE_16BIT:
Read16Bit(curpixel);
break;
case PIXEL_SIZE_32BIT:
Read32Bit(curpixel);
break;
default:
fatalerror("Unsupported bit depth: %d\n", m_misc_state->m_fb_size);
break;
}
}
void Framebuffer::Read16Bit(UINT32 curpixel)
{
UINT16 fword = RREADIDX16((m_misc_state->m_fb_address >> 1) + curpixel);
UINT8 hbyte = HREADADDR8((m_misc_state->m_fb_address >> 1) + curpixel);
m_rdp->GetMemoryColor()->i.r = GETHICOL(fword);
m_rdp->GetMemoryColor()->i.g = GETMEDCOL(fword);
m_rdp->GetMemoryColor()->i.b = GETLOWCOL(fword);
if (m_other_modes->image_read_en)
{
memory_cvg = ((*fb >>5) & 7) + 1;
m_misc_state->m_curpixel_memcvg = ((fword & 1) << 2) | (hbyte & 3);
m_rdp->GetMemoryColor()->i.a = m_misc_state->m_curpixel_memcvg << 5;
}
UINT32 newcvg = m_misc_state->m_curpixel_cvg + memory_cvg;
bool wrapped = (newcvg > 8);
UINT32 clamped_cvg = wrapped ? 8 : newcvg;
newcvg = (wrapped) ? (newcvg - 8) : newcvg;
m_misc_state->m_curpixel_cvg--;
newcvg--;
memory_cvg--;
clamped_cvg--;
if (m_other_modes->color_on_cvg && !wrapped)
else
{
*fb &= 0xffffff00;
*fb |= ((newcvg << 5) & 0xff);
return 0;
m_misc_state->m_curpixel_memcvg = 7;
m_rdp->GetMemoryColor()->i.a = 0xff;
}
switch(m_other_modes->cvg_dest)
{
case 0:
if (!m_other_modes->force_blend && !m_misc_state->m_curpixel_overlap)
{
*fb = finalcolor|(m_misc_state->m_curpixel_cvg << 5);
}
else
{
*fb = finalcolor|(clamped_cvg << 5);
}
break;
case 1:
*fb = finalcolor | (newcvg << 5);
break;
case 2:
*fb = finalcolor | 0xE0;
break;
case 3:
*fb = finalcolor | memory_alphachannel;
break;
}
return true;
}
void Framebuffer::Read32Bit(UINT32 curpixel)
{
UINT32 mem = RREADIDX32((m_misc_state->m_fb_address >> 2) + curpixel);
m_rdp->GetMemoryColor()->i.r = (mem >> 24) & 0xff;
m_rdp->GetMemoryColor()->i.g = (mem >> 16) & 0xff;
m_rdp->GetMemoryColor()->i.b = (mem >> 8) & 0xff;
if (m_other_modes->image_read_en)
{
m_misc_state->m_curpixel_memcvg = (mem >> 5) & 7;
m_rdp->GetMemoryColor()->i.a = (mem) & 0xff;
}
else
{
m_misc_state->m_curpixel_memcvg = 7;
m_rdp->GetMemoryColor()->i.a = 0xff;
}
}
void Framebuffer::Copy(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b)
{
switch(m_misc_state->m_fb_size)
{
case PIXEL_SIZE_16BIT:
Copy16Bit(curpixel, r, g, b);
break;
case PIXEL_SIZE_32BIT:
Copy32Bit(curpixel, r, g, b);
break;
default:
fatalerror("Unsupported bit depth: %d\n", m_misc_state->m_fb_size);
break;
}
}
void Framebuffer::Copy16Bit(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b)
{
UINT16 val = ((r >> 3) << 11) | ((g >> 3) << 6) | ((b >> 3) << 1) | ((m_misc_state->m_curpixel_cvg >> 2) & 1);
RWRITEIDX16((m_misc_state->m_fb_address >> 1) + curpixel, val);
HWRITEADDR8((m_misc_state->m_fb_address >> 1) + curpixel, m_misc_state->m_curpixel_cvg & 3);
}
void Framebuffer::Copy32Bit(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b)
{
UINT32 val = (r << 24) | (g << 16) | (b << 8) | (m_misc_state->m_curpixel_cvg << 5);
RWRITEIDX32((m_misc_state->m_fb_address >> 2) + curpixel, val);
}
void Framebuffer::Fill(UINT32 curpixel)
{
switch(m_misc_state->m_fb_size)
{
case PIXEL_SIZE_16BIT:
Fill16Bit(curpixel);
break;
case PIXEL_SIZE_32BIT:
Fill32Bit(curpixel);
break;
default:
fatalerror("Unsupported bit depth: %d\n", m_misc_state->m_fb_size);
break;
}
}
void Framebuffer::Fill16Bit(UINT32 curpixel)
{
UINT16 val;
if (curpixel & 1)
{
val = m_rdp->GetFillColor32() & 0xffff;
}
else
{
val = (m_rdp->GetFillColor32() >> 16) & 0xffff;
}
RWRITEIDX16((m_misc_state->m_fb_address >> 1) + curpixel, val);
HWRITEADDR8((m_misc_state->m_fb_address >> 1) + curpixel, ((val & 1) << 1) | (val & 1));
}
void Framebuffer::Fill32Bit(UINT32 curpixel)
{
UINT32 fill_color = m_rdp->GetFillColor32();
RWRITEIDX32((m_misc_state->m_fb_address >> 2) + curpixel, fill_color);
HWRITEADDR8((m_misc_state->m_fb_address >> 1) + (curpixel << 1), (fill_color & 0x10000) ? 3 : 0);
HWRITEADDR8((m_misc_state->m_fb_address >> 1) + (curpixel << 1) + 1, (fill_color & 0x1) ? 3 : 0);
}
} // namespace RDP
} // namespace N64

View File

@ -15,19 +15,35 @@ class MiscState;
class Framebuffer
{
public:
Framebuffer() { }
Framebuffer()
{
m_pre_wrap = false;
}
bool Write(void* fb, UINT8* hb, UINT32 r, UINT32 g, UINT32 b);
void Write(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b);
void Read(UINT32 index);
void Copy(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b);
void Fill(UINT32 curpixel);
void SetProcessor(Processor* rdp) { m_rdp = rdp; }
void SetOtherModes(OtherModes* other_modes) { m_other_modes = other_modes; }
void SetMiscState(MiscState* misc_state) { m_misc_state = misc_state; }
void SetPreWrap(bool prewrap) { m_pre_wrap = prewrap; }
private:
Processor* m_rdp;
OtherModes* m_other_modes;
MiscState* m_misc_state;
bool m_pre_wrap;
bool Write16Bit(UINT16* fb, UINT8* hb, UINT32 r, UINT32 g, UINT32 b);
bool Write32Bit(UINT32* fb, UINT32 r, UINT32 g, UINT32 b);
void Write16Bit(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b);
void Write32Bit(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b);
void Read16Bit(UINT32 curpixel);
void Read32Bit(UINT32 curpixel);
void Copy16Bit(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b);
void Copy32Bit(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b);
void Fill16Bit(UINT32 curpixel);
void Fill32Bit(UINT32 curpixel);
};
} // namespace RDP

View File

@ -1,465 +0,0 @@
#include "emu.h"
#include "includes/n64.h"
#include "video/n64.h"
namespace N64
{
namespace RDP
{
void TexFetch::SetMachine(running_machine *machine)
{
_n64_state *state = machine->driver_data<_n64_state>();
m_machine = machine;
m_rdp = &state->m_rdp;
m_other_modes = m_rdp->GetOtherModes();
m_misc_state = m_rdp->GetMiscState();
m_tiles = m_rdp->GetTiles();
}
UINT32 TexFetch::Fetch(UINT32 s, UINT32 t, Tile* tile)
{
UINT32 tformat = tile->format;
if (t < 0) t = 0;
if (s < 0) s = 0;
switch (tformat)
{
case 0: // RGBA
return FetchRGBA(s, t, tile);
case 1: // YUV: Bottom of the 9th, Pokemon Stadium, Ogre Battle 64
return FetchYUV(s, t, tile);
case 2: // Color Index
return FetchCI(s, t, tile);
case 3: // Intensity + Alpha
return FetchIA(s, t, tile);
case 4: // Intensity
return FetchI(s, t, tile);
default:
fatalerror("FETCH_TEXEL: unknown texture format %d\n", tformat);
return 0xffffffff;
}
return 0;
}
UINT32 TexFetch::FetchRGBA(UINT32 s, UINT32 t, Tile* tile)
{
UINT32 twidth = tile->line;
UINT32 tbase = tile->tmem;
UINT32 tpal = tile->palette & 0xf;
switch (tile->size)
{
case PIXEL_SIZE_4BIT:
{
UINT8 *tc = (UINT8*)m_rdp->GetTMEM();
int taddr = ((tbase + ((t) * twidth) + ((s) / 2)) ^ ((t & 1) ? XOR_SWAP_BYTE : 0)) & 0x7ff;
UINT8 p = ((s) & 1) ? (tc[taddr ^ BYTE_ADDR_XOR] & 0xf) : (tc[taddr ^ BYTE_ADDR_XOR] >> 4);
UINT16 c = m_rdp->GetTLUT()[(((tpal << 4) | p) ^ WORD_ADDR_XOR) << 2];
if (m_other_modes->en_tlut)
{
if (m_other_modes->tlut_type == 0)
{
return m_rdp->LookUp16To32(c);
}
else
{
return m_rdp->LookUpIA8To32(c);
}
}
else
{
return ((tpal << 4) | p) * 0x01010101;
}
break;
}
case PIXEL_SIZE_8BIT:
{
UINT8 *tc = m_rdp->GetTMEM();
int taddr = ((tbase + ((t) * twidth) + ((s))) ^ ((t & 1) ? XOR_SWAP_BYTE : 0)) & 0x7ff;
UINT8 p = tc[taddr ^ BYTE_ADDR_XOR];
UINT16 c = m_rdp->GetTLUT()[(p ^ WORD_ADDR_XOR) << 2];
if (m_other_modes->en_tlut)
{
if (m_other_modes->tlut_type == 0)
{
return m_rdp->LookUp16To32(c);
}
else
{
return m_rdp->LookUpIA8To32(c);
}
}
else
{
return p * 0x01010101;
}
break;
}
case PIXEL_SIZE_16BIT:
{
UINT16 *tc = m_rdp->GetTMEM16();
int taddr = ((tbase>>1) + ((t) * (twidth>>1)) + (s)) ^ ((t & 1) ? XOR_SWAP_WORD : 0);
UINT16 c = tc[(taddr & 0x7ff) ^ WORD_ADDR_XOR]; // PGA European Tour (U)
if (!m_other_modes->en_tlut)
{
return m_rdp->LookUp16To32(c);
}
else
{
if (m_other_modes->tlut_type == 0) //Golden Eye 007, sea, "frigate" level
{
return m_rdp->LookUp16To32(m_rdp->GetTLUT()[(c >> 8) << 2]);
}
else // Beetle Adventure Racing, Mount Mayhem
{
return m_rdp->LookUpIA8To32(m_rdp->GetTLUT()[(c >> 8) << 2]);
}
}
break;
}
case PIXEL_SIZE_32BIT:
{
UINT32 *tc = m_rdp->GetTMEM32();
int xorval = (m_misc_state->m_fb_size == PIXEL_SIZE_16BIT) ? XOR_SWAP_WORD : XOR_SWAP_DWORD; // Conker's Bad Fur Day, Jet Force Gemini, Super Smash Bros., Mickey's Speedway USA, Ogre Battle, Wave Race, Gex 3, South Park Rally
int taddr = (((tbase >> 2) + ((t) * (twidth >> 1)) + (s)) ^ ((t & 1) ? xorval : 0)) & 0x3ff;
if (!m_other_modes->en_tlut)
{
return tc[taddr];
}
else
{
if (!m_other_modes->tlut_type)
{
return m_rdp->LookUp16To32(m_rdp->GetTLUT()[(tc[taddr] >> 24) << 2]);
}
else
{
return m_rdp->LookUpIA8To32(m_rdp->GetTLUT()[(tc[taddr] >> 24) << 2]);
}
}
break;
}
default:
fatalerror("FETCH_TEXEL: unknown RGBA texture size %d\n", tile->size);
return 0xffffffff;
}
}
UINT32 TexFetch::FetchYUV(UINT32 s, UINT32 t, Tile* tile)
{
UINT32 twidth = tile->line;
UINT32 tsize = tile->size;
UINT32 tbase = tile->tmem;
Color out;
out.c = 0;
if(tsize == PIXEL_SIZE_16BIT)
{
INT32 newr = 0;
INT32 newg = 0;
INT32 newb = 0;
UINT16 *tc = m_rdp->GetTMEM16();
int taddr = ((tbase >> 1) + ((t) * (twidth)) + (s)) ^ ((t & 1) ? XOR_SWAP_WORD : 0);
UINT16 c1, c2;
INT32 y;
INT32 u, v;
c1 = tc[taddr ^ WORD_ADDR_XOR];
c2 = tc[taddr]; // other word
if (!(taddr & 1))
{
v = c2 >> 8;
u = c1 >> 8;
y = c1 & 0xff;
}
else
{
v = c1 >> 8;
u = c2 >> 8;
y = c1 & 0xff;
}
v -= 128;
u -= 128;
if (!m_other_modes->bi_lerp0)
{
newr = y + ((m_rdp->GetK0() * v) >> 8);
newg = y + ((m_rdp->GetK1() * u) >> 8) + ((m_rdp->GetK2() * v) >> 8);
newb = y + ((m_rdp->GetK2() * u) >> 8);
}
out.i.r = (newr < 0) ? 0 : ((newr > 0xff) ? 0xff : newr);
out.i.g = (newg < 0) ? 0 : ((newg > 0xff) ? 0xff : newg);
out.i.b = (newb < 0) ? 0 : ((newb > 0xff) ? 0xff : newb);
out.i.a = 0xff;
}
return out.c;
}
UINT32 TexFetch::FetchCI(UINT32 s, UINT32 t, Tile* tile)
{
UINT32 twidth = tile->line;
UINT32 tsize = tile->size;
UINT32 tbase = tile->tmem;
UINT32 tpal = tile->palette & 0xf;
switch (tsize)
{
case PIXEL_SIZE_4BIT:
{
UINT8 *tc = m_rdp->GetTMEM();
int taddr = ((tbase + ((t) * twidth) + ((s) / 2)) ^ ((t & 1) ? XOR_SWAP_BYTE : 0)) & 0x7ff;
UINT8 p = ((s) & 1) ? (tc[taddr ^ BYTE_ADDR_XOR] & 0xf) : (tc[taddr ^ BYTE_ADDR_XOR] >> 4);
UINT16 c = m_rdp->GetTLUT()[((tpal << 4) | p) << 2];
if (m_other_modes->en_tlut)
{
if (m_other_modes->tlut_type == 0)
{
return m_rdp->LookUp16To32(c);
}
else
{
return m_rdp->LookUpIA8To32(c);
}
}
else
{
return ((tpal << 4) | p) * 0x01010101;
}
break;
}
case PIXEL_SIZE_8BIT:
{
UINT8 *tc = m_rdp->GetTMEM();
int taddr = ((tbase + ((t) * twidth) + ((s))) ^ ((t & 1) ? XOR_SWAP_BYTE : 0)) & 0x7ff;
UINT8 p = tc[taddr ^ BYTE_ADDR_XOR];
UINT16 c = m_rdp->GetTLUT()[p << 2];
if (m_other_modes->en_tlut)
{
if (m_other_modes->tlut_type == 0)
{
return m_rdp->LookUp16To32(c);
}
else
{
return m_rdp->LookUpIA8To32(c);
}
}
else
{
return p * 0x01010101;
}
break;
}
case PIXEL_SIZE_16BIT:
{
// 16-bit CI is a "valid" mode; some games use it, it behaves the same as 16-bit RGBA
UINT16 *tc = m_rdp->GetTMEM16();
int taddr = ((tbase>>1) + ((t) * (twidth>>1)) + (s)) ^ ((t & 1) ? XOR_SWAP_WORD : 0);
UINT16 c = tc[(taddr & 0x7ff) ^ WORD_ADDR_XOR]; // PGA European Tour (U)
if (!m_other_modes->en_tlut)
{
return m_rdp->LookUp16To32(c);
}
else
{
if (!m_other_modes->tlut_type) // GoldenEye 007, sea, "frigate" level
{
return m_rdp->LookUp16To32(m_rdp->GetTLUT()[(c >> 8) << 2]);
}
else // Beetle Adventure Racing, Mount Mayhem
{
return m_rdp->LookUpIA8To32(m_rdp->GetTLUT()[(c >> 8) << 2]);
}
}
break;
}
default:
fatalerror("FETCH_TEXEL: unknown CI texture size %d\n", tsize);
return 0xffffffff;
}
return 0;
}
UINT32 TexFetch::FetchIA(UINT32 s, UINT32 t, Tile* tile)
{
UINT32 twidth = tile->line;
UINT32 tsize = tile->size;
UINT32 tbase = tile->tmem;
UINT32 tpal = tile->palette & 0xf;
switch (tsize)
{
case PIXEL_SIZE_4BIT:
{
UINT8 *tc = m_rdp->GetTMEM();
int taddr = (tbase + ((t) * twidth) + (s >> 1)) ^ ((t & 1) ? XOR_SWAP_BYTE : 0);
UINT8 p = ((s) & 1) ? (tc[taddr ^ BYTE_ADDR_XOR] & 0xf) : (tc[taddr ^ BYTE_ADDR_XOR] >> 4);
UINT8 i = ((p & 0xe) << 4) | ((p & 0xe) << 1) | (p & 0xe >> 2);
if (!m_other_modes->en_tlut)
{
return (i * 0x01010100) | ((p & 0x1) ? 0xff : 0);
}
else
{
UINT16 c = m_rdp->GetTLUT()[((tpal << 4) | p) << 2];
if (!m_other_modes->tlut_type)
{
return m_rdp->LookUp16To32(c);
}
else
{
return m_rdp->LookUpIA8To32(c);
}
}
break;
}
case PIXEL_SIZE_8BIT:
{
UINT8 *tc = m_rdp->GetTMEM();
int taddr = ((tbase + ((t) * twidth) + ((s))) ^ ((t & 1) ? XOR_SWAP_BYTE : 0)) & 0xfff;
UINT8 p = tc[taddr ^ BYTE_ADDR_XOR];
if (!m_other_modes->en_tlut)
{
UINT8 i = (p >> 4) | (p & 0xf0);
return (i * 0x01010100) | ((p & 0xf) | ((p << 4) & 0xf0));
}
else
{
UINT16 c = m_rdp->GetTLUT()[p << 2];
if (!m_other_modes->tlut_type)
{
return m_rdp->LookUp16To32(c);
}
else
{
return m_rdp->LookUpIA8To32(c);
}
}
break;
}
case PIXEL_SIZE_16BIT:
{
UINT16 *tc = m_rdp->GetTMEM16();
int taddr = ((tbase >> 1) + ((t) * (twidth >> 1)) + (s)) ^ ((t & 1) ? XOR_SWAP_WORD : 0);
UINT16 c = tc[taddr ^ WORD_ADDR_XOR];
if (m_other_modes->en_tlut)
{
c = m_rdp->GetTLUT()[(c >> 8) << 2];
if (m_other_modes->tlut_type == 0)
{
return m_rdp->LookUp16To32(c);
}
else
{
return m_rdp->LookUpIA8To32(c);
}
}
else
{
return m_rdp->LookUpIA8To32(c);
}
break;
}
default:
return 0xffffffff;
fatalerror("FETCH_TEXEL: unknown IA texture size %d\n", tsize);
break;
}
return 0;
}
UINT32 TexFetch::FetchI(UINT32 s, UINT32 t, Tile* tile)
{
UINT32 twidth = tile->line;
UINT32 tsize = tile->size;
UINT32 tbase = tile->tmem;
UINT32 tpal = tile->palette & 0xf;
switch (tsize)
{
case PIXEL_SIZE_4BIT:
{
UINT8 *tc = m_rdp->GetTMEM();
int taddr = ((tbase + ((t) * twidth) + ((s) / 2)) ^ ((t & 1) ? XOR_SWAP_BYTE : 0)) & 0xfff;
UINT8 c = ((s) & 1) ? (tc[taddr ^ BYTE_ADDR_XOR] & 0xf) : (tc[taddr ^ BYTE_ADDR_XOR] >> 4);
c |= (c << 4);
if (!m_other_modes->en_tlut)
{
return c * 0x01010101;
}
else
{
UINT16 k = m_rdp->GetTLUT()[((tpal << 4) | c) << 2];
if (!m_other_modes->tlut_type)
{
return m_rdp->LookUp16To32(k);
}
else
{
return m_rdp->LookUpIA8To32(k);
}
}
break;
}
case PIXEL_SIZE_8BIT:
{
UINT8 *tc = m_rdp->GetTMEM();
int taddr = ((tbase + ((t) * twidth) + ((s))) ^ ((t & 1) ? XOR_SWAP_BYTE : 0)) & 0xfff;
UINT8 c = tc[taddr ^ BYTE_ADDR_XOR];
if (!m_other_modes->en_tlut)
{
return c * 0x01010101;
}
else
{
UINT16 k = m_rdp->GetTLUT()[ c << 2];
if (!m_other_modes->tlut_type)
{
return m_rdp->LookUp16To32(k);
}
else
{
return m_rdp->LookUpIA8To32(k);
}
}
break;
}
default:
//fatalerror("FETCH_TEXEL: unknown I texture size %d\n", tsize);
return 0xffffffff;
}
return 0;
}
} // namespace RDP
} // namespace N64

View File

@ -1,44 +0,0 @@
#ifndef _VIDEO_RDPFETCH_H_
#define _VIDEO_RDPFETCH_H_
#include "emu.h"
namespace N64
{
namespace RDP
{
class Processor;
class OtherModes;
class MiscState;
class Tile;
class TexFetch
{
public:
TexFetch() { }
UINT32 Fetch(UINT32 s, UINT32 t, Tile* tile);
void SetMachine(running_machine* machine);
private:
running_machine* m_machine;
Processor* m_rdp;
OtherModes* m_other_modes;
MiscState* m_misc_state;
Tile* m_tiles;
UINT32 FetchRGBA(UINT32 s, UINT32 t, Tile* tile);
UINT32 FetchYUV(UINT32 s, UINT32 t, Tile* tile);
UINT32 FetchCI(UINT32 s, UINT32 t, Tile* tile);
UINT32 FetchIA(UINT32 s, UINT32 t, Tile* tile);
UINT32 FetchI(UINT32 s, UINT32 t, Tile* tile);
};
} // namespace RDP
} // namespace N64
#endif // _VIDEO_RDPFETCH_H_

View File

@ -1,510 +0,0 @@
#include "emu.h"
#include "includes/n64.h"
#include "video/n64.h"
namespace N64
{
namespace RDP
{
#define LookUpCC(A, B, C, D) m_rdp->GetCCLUT2()[(m_rdp->GetCCLUT1()[(A << 16) | (B << 8) | C] << 8) | D]
void Rectangle::SetMachine(running_machine* machine)
{
_n64_state *state = machine->driver_data<_n64_state>();
m_machine = machine;
m_rdp = &state->m_rdp;
m_misc_state = m_rdp->GetMiscState();
m_other_modes = m_rdp->GetOtherModes();
m_blender = m_rdp->GetBlender();
}
void Rectangle::Draw()
{
switch(m_other_modes->cycle_type)
{
case CYCLE_TYPE_1:
Draw1Cycle();
return;
case CYCLE_TYPE_2:
Draw2Cycle();
return;
case CYCLE_TYPE_FILL:
DrawFill();
return;
default:
fatalerror("Unsupported cycle type for Textured Rectangle: %d\n", m_other_modes->cycle_type);
return;
}
}
void Rectangle::Draw1Cycle()
{
UINT16 *fb = (UINT16*)&rdram[(m_misc_state->m_fb_address / 4)];
UINT8* hb = &m_rdp->GetHiddenBits()[m_misc_state->m_fb_address >> 1];
int index, i, j;
int x1 = m_xh >> 2;
int x2 = m_xl >> 2;
int y1 = m_yh >> 2;
int y2 = m_yl >> 2;
UINT16 fill_color1 = (m_rdp->GetFillColor32() >> 16) & 0xffff;
UINT16 fill_color2 = (m_rdp->GetFillColor32() >> 0) & 0xffff;
int fill_cvg1 = (fill_color1 & 1) ? 8 : 1;
int fill_cvg2 = (fill_color2 & 1) ? 8 : 1;
if (x2 <= x1)
{
x2=x1+1; // SCARS (E)
}
if (y2 == y1)
{
y2=y1+1; // Goldeneye
}
// clip
if (x1 < m_rdp->GetScissor()->m_xh)
{
x1 = m_rdp->GetScissor()->m_xh;
}
if (y1 < m_rdp->GetScissor()->m_yh)
{
y1 = m_rdp->GetScissor()->m_yh;
}
if (x2 >= m_rdp->GetScissor()->m_xl)
{
x2 = m_rdp->GetScissor()->m_xl - 1;
}
if (y2 >= m_rdp->GetScissor()->m_yl)
{
y2 = m_rdp->GetScissor()->m_yl - 1;
}
m_rdp->GetShadeColor()->c = 0; // Needed by Command & Conquer menus
if(m_other_modes->rgb_dither_sel == 0)
{
for (int j = y1; j <= y2; j++)
{
Color c1;
int dith = 0;
index = j * m_misc_state->m_fb_width;
for (i = x1; i <= x2; i++)
{
m_misc_state->m_curpixel_cvg = (i & 1) ? fill_cvg1 : fill_cvg2;
c1.i.r = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_r[1],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_r[1],
*m_rdp->GetColorInputs()->combiner_rgbmul_r[1],
*m_rdp->GetColorInputs()->combiner_rgbadd_r[1]);
c1.i.g = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_g[1],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_g[1],
*m_rdp->GetColorInputs()->combiner_rgbmul_g[1],
*m_rdp->GetColorInputs()->combiner_rgbadd_g[1]);
c1.i.b = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_b[1],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_b[1],
*m_rdp->GetColorInputs()->combiner_rgbmul_b[1],
*m_rdp->GetColorInputs()->combiner_rgbadd_b[1]);
c1.i.a = LookUpCC(*m_rdp->GetColorInputs()->combiner_alphasub_a[1],
*m_rdp->GetColorInputs()->combiner_alphasub_b[1],
*m_rdp->GetColorInputs()->combiner_alphamul[1],
*m_rdp->GetColorInputs()->combiner_alphaadd[1]);
m_rdp->GetAlphaCvg(&c1.i.a);
dith = m_rdp->GetMagicMatrix()[(((j) & 3) << 2) + ((i ^ WORD_ADDR_XOR) & 3)];
m_blender->Blend(&fb[(index + i) ^ WORD_ADDR_XOR], &hb[(index + i) ^ BYTE_ADDR_XOR], c1, *m_rdp->GetZero(), dith);
}
}
}
else if(m_other_modes->rgb_dither_sel == 1)
{
for (j = y1; j <= y2; j++)
{
Color c1;
int dith = 0;
index = j * m_misc_state->m_fb_width;
for (i = x1; i <= x2; i++)
{
m_misc_state->m_curpixel_cvg = (i & 1) ? fill_cvg1 : fill_cvg2;
c1.i.r = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_r[1],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_r[1],
*m_rdp->GetColorInputs()->combiner_rgbmul_r[1],
*m_rdp->GetColorInputs()->combiner_rgbadd_r[1]);
c1.i.g = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_g[1],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_g[1],
*m_rdp->GetColorInputs()->combiner_rgbmul_g[1],
*m_rdp->GetColorInputs()->combiner_rgbadd_g[1]);
c1.i.b = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_b[1],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_b[1],
*m_rdp->GetColorInputs()->combiner_rgbmul_b[1],
*m_rdp->GetColorInputs()->combiner_rgbadd_b[1]);
c1.i.a = LookUpCC(*m_rdp->GetColorInputs()->combiner_alphasub_a[1],
*m_rdp->GetColorInputs()->combiner_alphasub_b[1],
*m_rdp->GetColorInputs()->combiner_alphamul[1],
*m_rdp->GetColorInputs()->combiner_alphaadd[1]);
m_rdp->GetAlphaCvg(&c1.i.a);
dith = m_rdp->GetBayerMatrix()[(((j) & 3) << 2) + ((i ^ WORD_ADDR_XOR) & 3)];
m_blender->Blend(&fb[(index + i) ^ WORD_ADDR_XOR], &hb[(index + i) ^ BYTE_ADDR_XOR], c1, *m_rdp->GetZero(), dith);
}
}
}
else
{
for (j = y1; j <= y2; j++)
{
Color c1;
index = j * m_misc_state->m_fb_width;
for (i = x1; i <= x2; i++)
{
m_misc_state->m_curpixel_cvg = (i & 1) ? fill_cvg1 : fill_cvg2;
c1.i.r = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_r[1],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_r[1],
*m_rdp->GetColorInputs()->combiner_rgbmul_r[1],
*m_rdp->GetColorInputs()->combiner_rgbadd_r[1]);
c1.i.g = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_g[1],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_g[1],
*m_rdp->GetColorInputs()->combiner_rgbmul_g[1],
*m_rdp->GetColorInputs()->combiner_rgbadd_g[1]);
c1.i.b = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_b[1],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_b[1],
*m_rdp->GetColorInputs()->combiner_rgbmul_b[1],
*m_rdp->GetColorInputs()->combiner_rgbadd_b[1]);
c1.i.a = LookUpCC(*m_rdp->GetColorInputs()->combiner_alphasub_a[1],
*m_rdp->GetColorInputs()->combiner_alphasub_b[1],
*m_rdp->GetColorInputs()->combiner_alphamul[1],
*m_rdp->GetColorInputs()->combiner_alphaadd[1]);
m_rdp->GetAlphaCvg(&c1.i.a);
m_blender->Blend(&fb[(index + i) ^ WORD_ADDR_XOR], &hb[(index + i) ^ BYTE_ADDR_XOR], c1, *m_rdp->GetZero(), 0);
}
}
}
}
void Rectangle::Draw2Cycle()
{
UINT16 *fb = (UINT16*)&rdram[(m_misc_state->m_fb_address / 4)];
UINT8* hb = &m_rdp->GetHiddenBits()[m_misc_state->m_fb_address >> 1];
int index, i, j;
int x1 = m_xh >> 2;
int x2 = m_xl >> 2;
int y1 = m_yh >> 2;
int y2 = m_yl >> 2;
UINT16 fill_color1;
UINT16 fill_color2;
int fill_cvg1;
int fill_cvg2;
if (x2 <= x1)
{
x2=x1+1; // SCARS (E)
}
if (y2 == y1)
{
y2=y1+1; // Goldeneye
}
fill_color1 = (m_rdp->GetFillColor32() >> 16) & 0xffff;
fill_color2 = (m_rdp->GetFillColor32() >> 0) & 0xffff;
fill_cvg1 = (fill_color1 & 1) ? 8 : 1;
fill_cvg2 = (fill_color2 & 1) ? 8 : 1;
// clip
if (x1 < m_rdp->GetScissor()->m_xh)
{
x1 = m_rdp->GetScissor()->m_xh;
}
if (y1 < m_rdp->GetScissor()->m_yh)
{
y1 = m_rdp->GetScissor()->m_yh;
}
if (x2 >= m_rdp->GetScissor()->m_xl)
{
x2 = m_rdp->GetScissor()->m_xl - 1;
}
if (y2 >= m_rdp->GetScissor()->m_yl)
{
y2 = m_rdp->GetScissor()->m_yl - 1;
}
m_rdp->GetShadeColor()->c = 0; // Needed by Command & Conquer menus
if(m_other_modes->rgb_dither_sel == 0)
{
for (j=y1; j <= y2; j++)
{
Color c1;
Color c2;
int dith = 0;
index = j * m_misc_state->m_fb_width;
for (i=x1; i <= x2; i++)
{
m_misc_state->m_curpixel_cvg = (i & 1) ? fill_cvg1 : fill_cvg2;
c1.i.r = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_r[0],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_r[0],
*m_rdp->GetColorInputs()->combiner_rgbmul_r[0],
*m_rdp->GetColorInputs()->combiner_rgbadd_r[0]);
c1.i.g = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_g[0],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_g[0],
*m_rdp->GetColorInputs()->combiner_rgbmul_g[0],
*m_rdp->GetColorInputs()->combiner_rgbadd_g[0]);
c1.i.b = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_b[0],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_b[0],
*m_rdp->GetColorInputs()->combiner_rgbmul_b[0],
*m_rdp->GetColorInputs()->combiner_rgbadd_b[0]);
c1.i.a = LookUpCC(*m_rdp->GetColorInputs()->combiner_alphasub_a[0],
*m_rdp->GetColorInputs()->combiner_alphasub_b[0],
*m_rdp->GetColorInputs()->combiner_alphamul[0],
*m_rdp->GetColorInputs()->combiner_alphaadd[0]);
m_rdp->GetCombinedColor()->c = c1.c;
c2.c = m_rdp->GetTexel0Color()->c;
m_rdp->GetTexel0Color()->c = m_rdp->GetTexel1Color()->c;
m_rdp->GetTexel1Color()->c = c2.c;
c2.i.r = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_r[1],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_r[1],
*m_rdp->GetColorInputs()->combiner_rgbmul_r[1],
*m_rdp->GetColorInputs()->combiner_rgbadd_r[1]);
c2.i.g = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_g[1],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_g[1],
*m_rdp->GetColorInputs()->combiner_rgbmul_g[1],
*m_rdp->GetColorInputs()->combiner_rgbadd_g[1]);
c2.i.b = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_b[1],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_b[1],
*m_rdp->GetColorInputs()->combiner_rgbmul_b[1],
*m_rdp->GetColorInputs()->combiner_rgbadd_b[1]);
c2.i.a = LookUpCC(*m_rdp->GetColorInputs()->combiner_alphasub_a[1],
*m_rdp->GetColorInputs()->combiner_alphasub_b[1],
*m_rdp->GetColorInputs()->combiner_alphamul[1],
*m_rdp->GetColorInputs()->combiner_alphaadd[1]);
m_rdp->GetAlphaCvg(&c2.i.a);
dith = m_rdp->GetMagicMatrix()[(((j) & 3) << 2) + ((i ^ WORD_ADDR_XOR) & 3)];
m_blender->Blend(&fb[(index + i) ^ WORD_ADDR_XOR], &hb[(index + i) ^ BYTE_ADDR_XOR], c1, c2, dith);
}
}
}
else if(m_other_modes->rgb_dither_sel == 1)
{
for (j=y1; j <= y2; j++)
{
Color c1;
Color c2;
int dith = 0;
index = j * m_misc_state->m_fb_width;
for (i=x1; i <= x2; i++)
{
m_misc_state->m_curpixel_cvg = (i & 1) ? fill_cvg1 : fill_cvg2;
c1.i.r = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_r[0],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_r[0],
*m_rdp->GetColorInputs()->combiner_rgbmul_r[0],
*m_rdp->GetColorInputs()->combiner_rgbadd_r[0]);
c1.i.g = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_g[0],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_g[0],
*m_rdp->GetColorInputs()->combiner_rgbmul_g[0],
*m_rdp->GetColorInputs()->combiner_rgbadd_g[0]);
c1.i.b = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_b[0],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_b[0],
*m_rdp->GetColorInputs()->combiner_rgbmul_b[0],
*m_rdp->GetColorInputs()->combiner_rgbadd_b[0]);
c1.i.a = LookUpCC(*m_rdp->GetColorInputs()->combiner_alphasub_a[0],
*m_rdp->GetColorInputs()->combiner_alphasub_b[0],
*m_rdp->GetColorInputs()->combiner_alphamul[0],
*m_rdp->GetColorInputs()->combiner_alphaadd[0]);
m_rdp->GetCombinedColor()->c = c1.c;
c2.c = m_rdp->GetTexel0Color()->c;
m_rdp->GetTexel0Color()->c = m_rdp->GetTexel1Color()->c;
m_rdp->GetTexel1Color()->c = c2.c;
c2.i.r = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_r[1],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_r[1],
*m_rdp->GetColorInputs()->combiner_rgbmul_r[1],
*m_rdp->GetColorInputs()->combiner_rgbadd_r[1]);
c2.i.g = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_g[1],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_g[1],
*m_rdp->GetColorInputs()->combiner_rgbmul_g[1],
*m_rdp->GetColorInputs()->combiner_rgbadd_g[1]);
c2.i.b = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_b[1],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_b[1],
*m_rdp->GetColorInputs()->combiner_rgbmul_b[1],
*m_rdp->GetColorInputs()->combiner_rgbadd_b[1]);
c2.i.a = LookUpCC(*m_rdp->GetColorInputs()->combiner_alphasub_a[1],
*m_rdp->GetColorInputs()->combiner_alphasub_b[1],
*m_rdp->GetColorInputs()->combiner_alphamul[1],
*m_rdp->GetColorInputs()->combiner_alphaadd[1]);
m_rdp->GetAlphaCvg(&c2.i.a);
dith = m_rdp->GetBayerMatrix()[(((j) & 3) << 2) + ((i ^ WORD_ADDR_XOR) & 3)];
m_blender->Blend(&fb[(index + i) ^ WORD_ADDR_XOR], &hb[(index + i) ^ BYTE_ADDR_XOR], c1, c2, dith);
}
}
}
else
{
for (j=y1; j <= y2; j++)
{
Color c1, c2;
index = j * m_misc_state->m_fb_width;
for (i=x1; i <= x2; i++)
{
m_misc_state->m_curpixel_cvg = (i & 1) ? fill_cvg1 : fill_cvg2;
c1.i.r = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_r[0],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_r[0],
*m_rdp->GetColorInputs()->combiner_rgbmul_r[0],
*m_rdp->GetColorInputs()->combiner_rgbadd_r[0]);
c1.i.g = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_g[0],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_g[0],
*m_rdp->GetColorInputs()->combiner_rgbmul_g[0],
*m_rdp->GetColorInputs()->combiner_rgbadd_g[0]);
c1.i.b = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_b[0],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_b[0],
*m_rdp->GetColorInputs()->combiner_rgbmul_b[0],
*m_rdp->GetColorInputs()->combiner_rgbadd_b[0]);
c1.i.a = LookUpCC(*m_rdp->GetColorInputs()->combiner_alphasub_a[0],
*m_rdp->GetColorInputs()->combiner_alphasub_b[0],
*m_rdp->GetColorInputs()->combiner_alphamul[0],
*m_rdp->GetColorInputs()->combiner_alphaadd[0]);
m_rdp->GetCombinedColor()->c = c1.c;
c2.c = m_rdp->GetTexel0Color()->c;
m_rdp->GetTexel0Color()->c = m_rdp->GetTexel1Color()->c;
m_rdp->GetTexel1Color()->c = c2.c;
c2.i.r = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_r[1],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_r[1],
*m_rdp->GetColorInputs()->combiner_rgbmul_r[1],
*m_rdp->GetColorInputs()->combiner_rgbadd_r[1]);
c2.i.g = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_g[1],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_g[1],
*m_rdp->GetColorInputs()->combiner_rgbmul_g[1],
*m_rdp->GetColorInputs()->combiner_rgbadd_g[1]);
c2.i.b = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_b[1],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_b[1],
*m_rdp->GetColorInputs()->combiner_rgbmul_b[1],
*m_rdp->GetColorInputs()->combiner_rgbadd_b[1]);
c2.i.a = LookUpCC(*m_rdp->GetColorInputs()->combiner_alphasub_a[1],
*m_rdp->GetColorInputs()->combiner_alphasub_b[1],
*m_rdp->GetColorInputs()->combiner_alphamul[1],
*m_rdp->GetColorInputs()->combiner_alphaadd[1]);
m_rdp->GetAlphaCvg(&c2.i.a);
m_blender->Blend(&fb[(index + i) ^ WORD_ADDR_XOR], &hb[(index + i) ^ BYTE_ADDR_XOR], c1, c2, 0);
}
}
}
}
void Rectangle::DrawFill()
{
UINT16 *fb = (UINT16*)&rdram[(m_misc_state->m_fb_address / 4)];
UINT8* hb = &m_rdp->GetHiddenBits()[m_misc_state->m_fb_address >> 1];
int index, i, j;
int x1 = m_xh >> 2;
int x2 = m_xl >> 2;
int y1 = m_yh >> 2;
int y2 = m_yl >> 2;
UINT16 fill_color1;
UINT16 fill_color2;
int fill_cvg1;
int fill_cvg2;
if (x2 <= x1)
{
x2=x1+1; // SCARS (E)
}
if (y2 == y1)
{
y2=y1+1; // Goldeneye
}
fill_color1 = (m_rdp->GetFillColor32() >> 16) & 0xffff;
fill_color2 = (m_rdp->GetFillColor32() >> 0) & 0xffff;
fill_cvg1 = (fill_color1 & 1) ? 8 : 1;
fill_cvg2 = (fill_color2 & 1) ? 8 : 1;
// clip
if (x1 < m_rdp->GetScissor()->m_xh)
{
x1 = m_rdp->GetScissor()->m_xh;
}
if (y1 < m_rdp->GetScissor()->m_yh)
{
y1 = m_rdp->GetScissor()->m_yh;
}
if (x2 >= m_rdp->GetScissor()->m_xl)
{
x2 = m_rdp->GetScissor()->m_xl - 1;
}
if (y2 >= m_rdp->GetScissor()->m_yl)
{
y2 = m_rdp->GetScissor()->m_yl - 1;
}
m_rdp->GetShadeColor()->c = 0; // Needed by Command & Conquer menus
fill_cvg1 = (fill_color1 & 1) ? 3 : 0;
fill_cvg2 = (fill_color2 & 1) ? 3 : 0;
if(x1 & 1)
{
for (j=y1; j <= y2; j++)
{
index = j * m_misc_state->m_fb_width;
for (i=x1; i <= x2; i += 2)
{
int curpixel = index + i;
fb[curpixel ^ WORD_ADDR_XOR] = fill_color2;
hb[curpixel ^ BYTE_ADDR_XOR] = fill_cvg2;
}
}
for (j=y1; j <= y2; j++)
{
index = j * m_misc_state->m_fb_width;
for (i=x1+1; i <= x2; i += 2)
{
int curpixel = index + i;
fb[curpixel ^ WORD_ADDR_XOR] = fill_color1;
hb[curpixel ^ BYTE_ADDR_XOR] = fill_cvg1;
}
}
}
else
{
for (j=y1; j <= y2; j++)
{
index = j * m_misc_state->m_fb_width;
for (i=x1; i <= x2; i += 2)
{
int curpixel = index + i;
fb[curpixel ^ WORD_ADDR_XOR] = fill_color1;
hb[curpixel ^ BYTE_ADDR_XOR] = fill_cvg1;
}
}
for (j=y1; j <= y2; j++)
{
index = j * m_misc_state->m_fb_width;
for (i=x1+1; i <= x2; i += 2)
{
int curpixel = index + i;
fb[curpixel ^ WORD_ADDR_XOR] = fill_color2;
hb[curpixel ^ BYTE_ADDR_XOR] = fill_cvg2;
}
}
}
}
} // namespace RDP
} // namespace N64

View File

@ -1,54 +0,0 @@
#ifndef _VIDEO_RDPFILLRECT_H_
#define _VIDEO_RDPFILLRECT_H_
#include "emu.h"
#include "video/rdpblend.h"
namespace N64
{
namespace RDP
{
class OtherModes;
class MiscState;
class Processor;
class Blender;
class Color;
class Rectangle
{
public:
Rectangle() {}
Rectangle(running_machine *machine, UINT32 *data)
{
SetMachine(machine);
InitFromBuffer(data);
}
void Draw();
void SetMachine(running_machine *machine);
void InitFromBuffer(UINT32 *data);
UINT16 m_xl; // 10.2 fixed-point
UINT16 m_yl; // 10.2 fixed-point
UINT16 m_xh; // 10.2 fixed-point
UINT16 m_yh; // 10.2 fixed-point
private:
void Draw1Cycle();
void Draw2Cycle();
void DrawFill();
running_machine* m_machine;
Processor* m_rdp;
MiscState* m_misc_state;
OtherModes* m_other_modes;
Blender* m_blender;
};
} // namespace RDP
} // namespace N64
#endif // _VIDEO_RDPFILLRECT_H_

View File

@ -10,10 +10,8 @@ namespace RDP
#define LookUpCC(A, B, C, D) m_rdp->GetCCLUT2()[(m_rdp->GetCCLUT1()[(A << 16) | (B << 8) | C] << 8) | D]
void Processor::RenderSpans(int start, int end, int tilenum, bool shade, bool texture, bool zbuffer, bool flip)
void Processor::RenderSpans(int start, int end, int tilenum, bool flip)
{
m_tex_pipe.CalculateClampDiffs(tilenum);
int clipy1 = GetScissor()->m_yh;
int clipy2 = GetScissor()->m_yl;
@ -37,7 +35,14 @@ void Processor::RenderSpans(int start, int end, int tilenum, bool shade, bool te
for(int i = start; i <= end; i++)
{
m_span[i].SetMachine(m_machine);
m_span[i].Draw(i, tilenum, shade, texture, zbuffer, flip);
switch(m_other_modes.cycle_type)
{
case CYCLE_TYPE_1: m_span[i].Draw1Cycle(i, tilenum, flip); break;
case CYCLE_TYPE_2: m_span[i].Draw2Cycle(i, tilenum, flip); break;
case CYCLE_TYPE_COPY: m_span[i].DrawCopy(i, tilenum, flip); break;
case CYCLE_TYPE_FILL: m_span[i].DrawFill(i, tilenum, flip); break;
}
}
}
@ -60,17 +65,6 @@ void Span::Dump()
printf("%d", m_cvg[index]);
}
printf("\n");
printf(" m_dymax = %08x\n", m_dymax);
printf(" m_ds.w = %08x\n", m_ds.w);
printf(" m_dt.w = %08x\n", m_dt.w);
printf(" m_dw.w = %08x\n", m_dw.w);
printf(" m_dr.w = %08x\n", m_dr.w);
printf(" m_dg.w = %08x\n", m_dg.w);
printf(" m_db.w = %08x\n", m_db.w);
printf(" m_da.w = %08x\n", m_da.w);
printf(" m_dz.w = %08x\n", m_dz.w);
printf(" m_dzpix = %08x\n", m_dzpix);
}
void Span::SetMachine(running_machine *machine)
@ -83,7 +77,58 @@ void Span::SetMachine(running_machine *machine)
m_misc_state = m_rdp->GetMiscState();
}
void Span::Draw(int index, int tilenum, bool shade, bool texture, bool zbuffer, bool flip)
void Span::RGBAZClip(int sr, int sg, int sb, int sa, int *sz)
{
m_rdp->GetShadeColor()->i.r = m_rdp->GetSpecial9BitClampTable()[sr & 0x1ff];
m_rdp->GetShadeColor()->i.g = m_rdp->GetSpecial9BitClampTable()[sg & 0x1ff];
m_rdp->GetShadeColor()->i.b = m_rdp->GetSpecial9BitClampTable()[sb & 0x1ff];
m_rdp->GetShadeColor()->i.a = m_rdp->GetSpecial9BitClampTable()[sa & 0x1ff];
INT32 zanded = (*sz) & 0x60000;
zanded >>= 17;
switch(zanded)
{
case 0: *sz &= 0x3ffff; break;
case 1: *sz &= 0x3ffff; break;
case 2: *sz = 0x3ffff; break;
case 3: *sz = 0x3ffff; break;
}
}
void Span::RGBAZCorrectTriangle(INT32 offx, INT32 offy, INT32* r, INT32* g, INT32* b, INT32* a, INT32* z)
{
if (m_rdp->GetMiscState()->m_curpixel_cvg == 8)
{
*r >>= 2;
*g >>= 2;
*b >>= 2;
*a >>= 2;
*z = (*z >> 3) & 0x7ffff;
}
else
{
INT32 summand_xr = offx * SIGN13(m_rdp->m_span_dr >> 14);
INT32 summand_yr = offy * SIGN13(m_rdp->m_span_drdy >> 14);
INT32 summand_xb = offx * SIGN13(m_rdp->m_span_db >> 14);
INT32 summand_yb = offy * SIGN13(m_rdp->m_span_dbdy >> 14);
INT32 summand_xg = offx * SIGN13(m_rdp->m_span_dg >> 14);
INT32 summand_yg = offy * SIGN13(m_rdp->m_span_dgdy >> 14);
INT32 summand_xa = offx * SIGN13(m_rdp->m_span_da >> 14);
INT32 summand_ya = offy * SIGN13(m_rdp->m_span_dady >> 14);
INT32 summand_xz = offx * SIGN22(m_rdp->m_span_dz >> 10);
INT32 summand_yz = offy * SIGN22(m_rdp->m_span_dzdy >> 10);
*r = ((*r << 2) + summand_xr + summand_yr) >> 4;
*g = ((*g << 2) + summand_xg + summand_yg) >> 4;
*b = ((*b << 2) + summand_xb + summand_yb) >> 4;
*a = ((*a << 2) + summand_xa + summand_ya) >> 4;
*z = (((*z << 2) + summand_xz + summand_yz) >> 5) & 0x7ffff;
}
}
void Span::Draw1Cycle(int index, int tilenum, bool flip)
{
int clipx1 = m_rdp->GetScissor()->m_xh;
int clipx2 = m_rdp->GetScissor()->m_xl;
@ -97,356 +142,360 @@ void Span::Draw(int index, int tilenum, bool shade, bool texture, bool zbuffer,
SpanParam t = m_t;
SpanParam w = m_w;
UINT16 *fb = (UINT16*)&rdram[m_misc_state->m_fb_address / 4];
UINT16 *zb = (UINT16*)&rdram[m_misc_state->m_zb_address / 4];
UINT8 *hb = &m_rdp->GetHiddenBits()[m_misc_state->m_fb_address >> 1];
UINT8 *zhb = &m_rdp->GetHiddenBits()[m_misc_state->m_zb_address >> 1];
UINT32 zb = m_misc_state->m_zb_address >> 1;
UINT32 zhb = zb;
UINT8 offx = 0, offy = 0;
UINT32 prim_tile = tilenum;
UINT32 tilenum2 = 0;
INT32 tile1 = tilenum;
int dzpix = m_dzpix;
int drinc = flip ? (m_dr.w) : -m_dr.w;
int dginc = flip ? (m_dg.w) : -m_dg.w;
int dbinc = flip ? (m_db.w) : -m_db.w;
int dainc = flip ? (m_da.w) : -m_da.w;
int dzinc = flip ? (m_dz.w) : -m_dz.w;
int dsinc = flip ? (m_ds.w) : -m_ds.w;
int dtinc = flip ? (m_dt.w) : -m_dt.w;
int dwinc = flip ? (m_dw.w) : -m_dw.w;
m_rdp->GetTexPipe()->CalculateClampDiffs(tile1);
bool noisecompute = m_rdp->GetColorInputs()->combiner_rgbsub_a_r[1] == &m_rdp->GetNoiseColor()->i.r;
bool partialreject = (m_rdp->GetColorInputs()->blender2b_a[0] == &m_rdp->GetInvPixelColor()->i.a && m_rdp->GetColorInputs()->blender1b_a[0] == &m_rdp->GetPixelColor()->i.a);
bool bsel0 = (m_rdp->GetColorInputs()->blender2b_a[0] == &m_rdp->GetMemoryColor()->i.a);
int drinc = flip ? (m_rdp->m_span_dr) : -m_rdp->m_span_dr;
int dginc = flip ? (m_rdp->m_span_dg) : -m_rdp->m_span_dg;
int dbinc = flip ? (m_rdp->m_span_db) : -m_rdp->m_span_db;
int dainc = flip ? (m_rdp->m_span_da) : -m_rdp->m_span_da;
int dzinc = flip ? (m_rdp->m_span_dz) : -m_rdp->m_span_dz;
int dsinc = flip ? (m_rdp->m_span_ds) : -m_rdp->m_span_ds;
int dtinc = flip ? (m_rdp->m_span_dt) : -m_rdp->m_span_dt;
int dwinc = flip ? (m_rdp->m_span_dw) : -m_rdp->m_span_dw;
int dzpix = m_rdp->m_span_dzpix;
int xinc = flip ? 1 : -1;
int nexts;
int nextt;
int nextsw;
int fb_index = m_misc_state->m_fb_width * index;
int x = m_rx;
int cdith = 0;
int adith = 0;
int length = flip ? (m_lx - m_rx) : (m_rx - m_lx);
int xstart = m_lx;
int xend = m_unscissored_rx;
int xend_scissored = m_rx;
bool disable_lod = false;
if (m_other_modes->cycle_type != CYCLE_TYPE_2) // Used by World Driver Championship
{
disable_lod = true;
}
int x = xend;
if (m_other_modes->cycle_type == CYCLE_TYPE_2 && texture && !m_other_modes->tex_lod_en)
{
tilenum2 = (prim_tile + 1) & 7;
}
if (texture && !m_other_modes->tex_lod_en)
{
tilenum = prim_tile;
}
if(!shade)
{
m_rdp->GetShadeColor()->c = m_rdp->GetPrimColor()->c;
}
int length = flip ? (xstart - xend) : (xend - xstart);
m_rdp->GetTexPipe()->m_start_span = true;
UINT32 fir, fig, fib;
for (int j = 0; j <= length; j++)
{
int sr = 0;
int sg = 0;
int sb = 0;
int sa = 0;
int ss = 0;
int st = 0;
int sw = 0;
int sz = 0;
int sss = 0;
int sst = 0;
int sr = r.w >> 14;
int sg = g.w >> 14;
int sb = b.w >> 14;
int sa = a.w >> 14;
int ss = s.w >> 16;
int st = t.w >> 16;
int sw = w.w >> 16;
int sz = (z.w >> 10) & 0x3fffff;
INT32 sss = 0;
INT32 sst = 0;
if (m_other_modes->z_source_sel)
{
sz = (((UINT32)m_misc_state->m_primitive_z) << 6) & 0x3fffff;
dzpix = m_misc_state->m_primitive_delta_z;
dzinc = m_rdp->m_span_dz = m_rdp->m_span_dzdy = 0;
}
bool valid_x = (flip) ? (x >= xend_scissored) : (x <= xend_scissored);
if (x >= clipx1 && x < clipx2 && valid_x)
{
m_rdp->lookup_cvmask_derivatives(m_cvg[x], &offx, &offy);
if (m_rdp->GetTexPipe()->m_start_span)
{
if (m_other_modes->persp_tex_en)
{
m_rdp->TCDiv(ss, st, sw, &sss, &sst);
}
else
{
m_rdp->TCDivNoPersp(ss, st, sw, &sss, &sst);
}
}
else
{
sss = m_rdp->GetTexPipe()->m_precomp_s;
sst = m_rdp->GetTexPipe()->m_precomp_t;
}
m_rdp->GetTexPipe()->LOD1Cycle(&sss, &sst, s.w, t.w, w.w, dsinc, dtinc, dwinc);
RGBAZCorrectTriangle(offx, offy, &sr, &sg, &sb, &sa, &sz);
RGBAZClip(sr, sg, sb, sa, &sz);
m_rdp->GetTexPipe()->Cycle(m_rdp->GetTexel0Color(), m_rdp->GetTexel0Color(), sss, sst, tilenum, 0);
m_rdp->ColorCombiner1Cycle(noisecompute);
UINT32 curpixel = fb_index + x;
UINT32 zbcur = zb + curpixel;
UINT32 zhbcur = zhb + curpixel;
m_rdp->GetFramebuffer()->Read(curpixel);
if(m_rdp->ZCompare(zbcur, zhbcur, sz, dzpix))
{
m_rdp->GetDitherValues(index, j, &cdith, &adith);
bool rendered = m_rdp->GetBlender()->Blend1Cycle(&fir, &fig, &fib, cdith, adith, partialreject, bsel0);
if (rendered)
{
m_rdp->GetFramebuffer()->Write(curpixel, fir, fig, fib);
if (m_other_modes->z_update_en)
{
m_rdp->ZStore(zbcur, zhbcur, sz);
}
}
}
}
r.w += drinc;
g.w += dginc;
b.w += dbinc;
a.w += dainc;
s.w += dsinc;
t.w += dtinc;
w.w += dwinc;
z.w += dzinc;
x += xinc;
}
}
void Span::Draw2Cycle(int index, int tilenum, bool flip)
{
int clipx1 = m_rdp->GetScissor()->m_xh;
int clipx2 = m_rdp->GetScissor()->m_xl;
SpanParam r = m_r;
SpanParam g = m_g;
SpanParam b = m_b;
SpanParam a = m_a;
SpanParam z = m_z;
SpanParam s = m_s;
SpanParam t = m_t;
SpanParam w = m_w;
UINT32 zb = m_misc_state->m_zb_address >> 1;
UINT32 zhb = zb;
UINT8 offx = 0, offy = 0;
INT32 tile2 = (tilenum + 1) & 7;
INT32 tile1 = tilenum;
UINT32 prim_tile = tilenum;
int newtile1 = tile1;
INT32 news = 0;
INT32 newt = 0;
m_rdp->GetTexPipe()->CalculateClampDiffs(tile1);
bool noisecompute = (m_rdp->GetColorInputs()->combiner_rgbsub_a_r[0] == &m_rdp->GetNoiseColor()->i.r || m_rdp->GetColorInputs()->combiner_rgbsub_a_r[1] == &m_rdp->GetPixelColor()->i.r);
bool partialreject = (m_rdp->GetColorInputs()->blender2b_a[1] == &m_rdp->GetInvPixelColor()->i.a && m_rdp->GetColorInputs()->blender1b_a[1] == &m_rdp->GetPixelColor()->i.a);
bool bsel0 = (m_rdp->GetColorInputs()->blender2b_a[0] == &m_rdp->GetMemoryColor()->i.a);
bool bsel1 = (m_rdp->GetColorInputs()->blender2b_a[1] == &m_rdp->GetMemoryColor()->i.a);
int dzpix = m_rdp->m_span_dzpix;
int drinc = flip ? (m_rdp->m_span_dr) : -m_rdp->m_span_dr;
int dginc = flip ? (m_rdp->m_span_dg) : -m_rdp->m_span_dg;
int dbinc = flip ? (m_rdp->m_span_db) : -m_rdp->m_span_db;
int dainc = flip ? (m_rdp->m_span_da) : -m_rdp->m_span_da;
int dzinc = flip ? (m_rdp->m_span_dz) : -m_rdp->m_span_dz;
int dsinc = flip ? (m_rdp->m_span_ds) : -m_rdp->m_span_ds;
int dtinc = flip ? (m_rdp->m_span_dt) : -m_rdp->m_span_dt;
int dwinc = flip ? (m_rdp->m_span_dw) : -m_rdp->m_span_dw;
int xinc = flip ? 1 : -1;
int fb_index = m_misc_state->m_fb_width * index;
int cdith = 0;
int adith = 0;
int xstart = m_lx;
int xend = m_unscissored_rx;
int xend_scissored = m_rx;
int x = xend;
int length = flip ? (xstart - xend) : (xend - xstart);
m_rdp->GetTexPipe()->m_start_span = true;
UINT32 fir, fig, fib;
//printf( "Span length: %d\n", length);
for (int j = 0; j <= length; j++)
{
int sr = r.w >> 14;
int sg = g.w >> 14;
int sb = b.w >> 14;
int sa = a.w >> 14;
int ss = s.h.h;
int st = t.h.h;
int sw = w.h.h;
int sz = (z.w >> 10) & 0x3fffff;
INT32 sss = 0;
INT32 sst = 0;
Color c1;
Color c2;
if(shade)
if (m_other_modes->z_source_sel)
{
sr = r.h.h;
sg = g.h.h;
sb = b.h.h;
sa = a.h.h;
sz = (((UINT32)m_misc_state->m_primitive_z) << 6) & 0x3fffff;
dzpix = m_misc_state->m_primitive_delta_z;
dzinc = m_rdp->m_span_dz = m_rdp->m_span_dzdy = 0;
}
if(texture)
{
ss = s.h.h;
st = t.h.h;
sw = w.h.h;
}
bool valid_x = (flip) ? (x >= xend_scissored) : (x <= xend_scissored);
if(zbuffer)
if (x >= clipx1 && x < clipx2 && valid_x)
{
sz = z.w >> 13;
m_rdp->lookup_cvmask_derivatives(m_cvg[x], &offx, &offy);
if (m_other_modes->z_source_sel)
if (m_rdp->GetTexPipe()->m_start_span)
{
sz = (((UINT32)m_misc_state->m_primitive_z) << 3) & 0x3ffff;
dzpix = m_misc_state->m_primitive_delta_z;
if (m_other_modes->persp_tex_en)
{
m_rdp->TCDiv(ss, st, sw, &sss, &sst);
}
else
{
m_rdp->TCDivNoPersp(ss, st, sw, &sss, &sst);
}
}
else
{
sss = m_rdp->GetTexPipe()->m_precomp_s;
sst = m_rdp->GetTexPipe()->m_precomp_t;
}
m_rdp->GetTexPipe()->LOD2Cycle(&sss, &sst, s.w, t.w, w.w, dsinc, dtinc, dwinc, prim_tile, &tile1, &tile2);
news = m_rdp->GetTexPipe()->m_precomp_s;
newt = m_rdp->GetTexPipe()->m_precomp_t;
m_rdp->GetTexPipe()->LOD2CycleLimited(&news, &newt, s.w + dsinc, t.w + dtinc, w.w + dwinc, dsinc, dtinc, dwinc, prim_tile, &newtile1);
RGBAZCorrectTriangle(offx, offy, &sr, &sg, &sb, &sa, &sz);
RGBAZClip(sr, sg, sb, sa, &sz);
m_rdp->GetTexPipe()->Cycle(m_rdp->GetTexel0Color(), m_rdp->GetTexel0Color(), sss, sst, tile1, 0);
m_rdp->GetTexPipe()->Cycle(m_rdp->GetTexel1Color(), m_rdp->GetTexel0Color(), sss, sst, tile2, 1);
m_rdp->GetTexPipe()->Cycle(m_rdp->GetNextTexelColor(), m_rdp->GetNextTexelColor(), sss, sst, tile2, 1);
m_rdp->ColorCombiner2Cycle(noisecompute);
UINT32 curpixel = fb_index + x;
UINT32 zbcur = zb + curpixel;
UINT32 zhbcur = zhb + curpixel;
m_rdp->GetFramebuffer()->Read(curpixel);
if(m_rdp->ZCompare(zbcur, zhbcur, sz, dzpix))
{
m_rdp->GetDitherValues(index, j, &cdith, &adith);
bool rendered = m_rdp->GetBlender()->Blend2Cycle(&fir, &fig, &fib, cdith, adith, partialreject, bsel0, bsel1);
if (rendered)
{
m_rdp->GetFramebuffer()->Write(curpixel, fir, fig, fib);
if (m_other_modes->z_update_en)
{
m_rdp->ZStore(zbcur, zhbcur, sz);
}
}
}
}
r.w += drinc;
g.w += dginc;
b.w += dbinc;
a.w += dainc;
s.w += dsinc;
t.w += dtinc;
w.w += dwinc;
z.w += dzinc;
x += xinc;
}
}
void Span::DrawCopy(int index, int tilenum, bool flip)
{
int clipx1 = m_rdp->GetScissor()->m_xh;
int clipx2 = m_rdp->GetScissor()->m_xl;
SpanParam s = m_s;
SpanParam t = m_t;
int ds = m_rdp->m_span_ds / 4;
int dt = m_rdp->m_span_dt / 4;
int dsinc = flip ? (ds) : -ds;
int dtinc = flip ? (dt) : -dt;
int xinc = flip ? 1 : -1;
int fb_index = m_misc_state->m_fb_width * index;
int xstart = m_lx;
int xend = m_unscissored_rx;
int xend_scissored = m_rx;
int x = xend;
int length = flip ? (xstart - xend) : (xend - xstart);
for (int j = 0; j <= length; j++)
{
bool valid_x = (flip) ? (x >= xend_scissored) : (x <= xend_scissored);
if (x >= clipx1 && x < clipx2 && valid_x)
{
INT32 sss = s.h.h;
INT32 sst = t.h.h;
m_rdp->GetTexPipe()->Copy(m_rdp->GetTexel0Color(), sss, sst, tilenum);
UINT32 curpixel = fb_index + x;
m_misc_state->m_curpixel_cvg = m_rdp->GetTexel0Color()->i.a ? 7 : 0;
if ((m_rdp->GetTexel0Color()->i.a != 0) || (!m_other_modes->alpha_compare_en))
{
m_rdp->GetFramebuffer()->Copy(curpixel, m_rdp->GetTexel0Color()->i.r, m_rdp->GetTexel0Color()->i.g, m_rdp->GetTexel0Color()->i.b);
}
}
s.w += dsinc;
t.w += dtinc;
x += xinc;
}
}
void Span::DrawFill(int index, int tilenum, bool flip)
{
int clipx1 = m_rdp->GetScissor()->m_xh;
int clipx2 = m_rdp->GetScissor()->m_xl;
int xinc = flip ? 1 : -1;
int fb_index = m_misc_state->m_fb_width * index;
int xstart = m_lx;
int xend_scissored = m_rx;
int x = xend_scissored;
int length = flip ? (xstart - xend_scissored) : (xend_scissored - xstart);
for (int j = 0; j <= length; j++)
{
if (x >= clipx1 && x < clipx2)
{
bool z_compare_result = true;
m_misc_state->m_curpixel_cvg = m_cvg[x];
if (m_misc_state->m_curpixel_cvg)
{
int curpixel = fb_index + x;
UINT16* fbcur = &fb[curpixel ^ WORD_ADDR_XOR];
UINT16* zbcur = &zb[curpixel ^ WORD_ADDR_XOR];
UINT8* hbcur = &hb[curpixel ^ BYTE_ADDR_XOR];
UINT8* zhbcur = &zhb[curpixel ^ BYTE_ADDR_XOR];
if(texture)
{
if (m_other_modes->persp_tex_en)
{
m_rdp->TCDiv(ss, st, sw, &sss, &sst);
}
else // Hack for Bust-a-Move 2
{
sss = ss;
sst = st;
}
if (m_other_modes->tex_lod_en && !disable_lod)
{
if (m_other_modes->persp_tex_en)
{
nextsw = (w.w + dwinc) >> 16;
nexts = (s.w + dsinc) >> 16;
nextt = (t.w + dtinc) >> 16;
m_rdp->TCDiv(nexts, nextt, nextsw, &nexts, &nextt);
}
else
{
nexts = (s.w + dsinc)>>16;
nextt = (t.w + dtinc)>>16;
}
INT32 horstep = SIGN17(nexts & 0x1ffff) - SIGN17(sss & 0x1ffff);
INT32 vertstep = SIGN17(nextt & 0x1ffff) - SIGN17(sst & 0x1ffff);
if (horstep & 0x20000)
{
horstep = ~horstep & 0x1ffff;
}
if (vertstep & 0x20000)
{
vertstep = ~vertstep & 0x1ffff;
}
int LOD = (horstep >= vertstep) ? horstep : vertstep;
LOD = (LOD >= m_dymax) ? LOD : m_dymax;
if (LOD & 0x1c000)
{
LOD = 0x7fff;
}
if (LOD < m_misc_state->m_min_level)
{
LOD = m_misc_state->m_min_level;
}
bool magnify = (LOD < 32);
INT32 l_tile = m_rdp->GetLog2((LOD >> 5) & 0xff);
bool distant = ((LOD & 0x6000) || (l_tile >= m_misc_state->m_max_level));
m_rdp->SetLODFrac(((LOD << 3) >> l_tile) & 0xff);
if (distant)
{
l_tile = m_misc_state->m_max_level;
}
if(!m_other_modes->sharpen_tex_en && !m_other_modes->detail_tex_en && magnify)
{
m_rdp->SetLODFrac(0);
}
if(!m_other_modes->sharpen_tex_en && !m_other_modes->detail_tex_en && distant)
{
m_rdp->SetLODFrac(0xff);
}
if(m_other_modes->sharpen_tex_en && magnify)
{
m_rdp->SetLODFrac(*(m_rdp->GetLODFrac()) | 0x100);
}
if (!m_other_modes->detail_tex_en)
{
tilenum = (prim_tile + l_tile);
tilenum &= 7;
if (m_other_modes->sharpen_tex_en)
{
tilenum2 = (tilenum + 1) & 7;
}
else if (!distant)
{
tilenum2 = (tilenum + 1) & 7;
}
else
{
tilenum2 = tilenum;
}
}
else
{
if (!magnify)
{
tilenum = (prim_tile + l_tile + 1);
}
else
{
tilenum = (prim_tile + l_tile);
}
tilenum &= 7;
if (!distant && !magnify)
{
tilenum2 = (prim_tile + l_tile + 2) & 7;
}
else
{
tilenum2 = (prim_tile + l_tile + 1) & 7;
}
}
}
if (m_other_modes->cycle_type == CYCLE_TYPE_1)
{
m_rdp->GetTexel0Color()->c = m_rdp->GetTexPipe()->Fetch(sss, sst, &m_rdp->GetTiles()[tilenum]);
}
else
{
m_rdp->GetTexel0Color()->c = m_rdp->GetTexPipe()->Fetch(sss, sst, &m_rdp->GetTiles()[tilenum]);
m_rdp->GetTexel1Color()->c = m_rdp->GetTexPipe()->Fetch(sss, sst, &m_rdp->GetTiles()[tilenum2]);
}
}
if (shade)
{
if (sr > 0xff) sr = 0xff;
if (sg > 0xff) sg = 0xff;
if (sb > 0xff) sb = 0xff;
if (sa > 0xff) sa = 0xff;
if (sr < 0) sr = 0;
if (sg < 0) sg = 0;
if (sb < 0) sb = 0;
if (sa < 0) sa = 0;
m_rdp->GetShadeColor()->i.r = sr;
m_rdp->GetShadeColor()->i.g = sg;
m_rdp->GetShadeColor()->i.b = sb;
m_rdp->GetShadeColor()->i.a = sa;
}
if (m_other_modes->cycle_type == CYCLE_TYPE_1)
{
c1.i.r = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_r[1],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_r[1],
*m_rdp->GetColorInputs()->combiner_rgbmul_r[1],
*m_rdp->GetColorInputs()->combiner_rgbadd_r[1]);
c1.i.g = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_g[1],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_g[1],
*m_rdp->GetColorInputs()->combiner_rgbmul_g[1],
*m_rdp->GetColorInputs()->combiner_rgbadd_g[1]);
c1.i.b = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_b[1],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_b[1],
*m_rdp->GetColorInputs()->combiner_rgbmul_b[1],
*m_rdp->GetColorInputs()->combiner_rgbadd_b[1]);
c1.i.a = LookUpCC(*m_rdp->GetColorInputs()->combiner_alphasub_a[1],
*m_rdp->GetColorInputs()->combiner_alphasub_b[1],
*m_rdp->GetColorInputs()->combiner_alphamul[1],
*m_rdp->GetColorInputs()->combiner_alphaadd[1]);
m_rdp->GetAlphaCvg(&c1.i.a);
}
else if (m_other_modes->cycle_type == CYCLE_TYPE_2)
{
c1.i.r = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_r[0],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_r[0],
*m_rdp->GetColorInputs()->combiner_rgbmul_r[0],
*m_rdp->GetColorInputs()->combiner_rgbadd_r[0]);
c1.i.g = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_g[0],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_g[0],
*m_rdp->GetColorInputs()->combiner_rgbmul_g[0],
*m_rdp->GetColorInputs()->combiner_rgbadd_g[0]);
c1.i.b = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_b[0],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_b[0],
*m_rdp->GetColorInputs()->combiner_rgbmul_b[0],
*m_rdp->GetColorInputs()->combiner_rgbadd_b[0]);
c1.i.a = LookUpCC(*m_rdp->GetColorInputs()->combiner_alphasub_a[0],
*m_rdp->GetColorInputs()->combiner_alphasub_b[0],
*m_rdp->GetColorInputs()->combiner_alphamul[0],
*m_rdp->GetColorInputs()->combiner_alphaadd[0]);
m_rdp->GetCombinedColor()->c = c1.c;
c2.c = m_rdp->GetTexel0Color()->c;
m_rdp->GetTexel0Color()->c = m_rdp->GetTexel1Color()->c;
m_rdp->GetTexel1Color()->c = c2.c;
c2.i.r = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_r[1],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_r[1],
*m_rdp->GetColorInputs()->combiner_rgbmul_r[1],
*m_rdp->GetColorInputs()->combiner_rgbadd_r[1]);
c2.i.g = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_g[1],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_g[1],
*m_rdp->GetColorInputs()->combiner_rgbmul_g[1],
*m_rdp->GetColorInputs()->combiner_rgbadd_g[1]);
c2.i.b = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_b[1],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_b[1],
*m_rdp->GetColorInputs()->combiner_rgbmul_b[1],
*m_rdp->GetColorInputs()->combiner_rgbadd_b[1]);
c2.i.a = LookUpCC(*m_rdp->GetColorInputs()->combiner_alphasub_a[1],
*m_rdp->GetColorInputs()->combiner_alphasub_b[1],
*m_rdp->GetColorInputs()->combiner_alphamul[1],
*m_rdp->GetColorInputs()->combiner_alphaadd[1]);
m_rdp->GetAlphaCvg(&c2.i.a);
}
if ((zbuffer || m_other_modes->z_source_sel) && m_other_modes->z_compare_en)
{
z_compare_result = m_rdp->ZCompare(fbcur, hbcur, zbcur, zhbcur, sz, dzpix);
}
if(z_compare_result)
{
bool rendered = false;
int dith = 0;
if (!m_other_modes->rgb_dither_sel)
{
dith = m_rdp->GetMagicMatrix()[(((index) & 3) << 2) + ((x ^ WORD_ADDR_XOR) & 3)];
}
else if (m_other_modes->rgb_dither_sel == 1)
{
dith = m_rdp->GetBayerMatrix()[(((index) & 3) << 2) + ((x ^ WORD_ADDR_XOR) & 3)];
}
rendered = m_rdp->GetBlender()->Blend(fbcur, hbcur, c1, c2, dith);
if (m_other_modes->z_update_en && rendered)
{
m_rdp->ZStore(zbcur, zhbcur, sz, dzpix);
}
}
}
}
if (shade)
{
r.w += drinc;
g.w += dginc;
b.w += dbinc;
a.w += dainc;
}
if (texture)
{
s.w += dsinc;
t.w += dtinc;
w.w += dwinc;
}
if (zbuffer)
{
z.w += dzinc;
UINT32 curpixel = fb_index + x;
m_rdp->GetFramebuffer()->Fill(curpixel);
}
x += xinc;

View File

@ -34,13 +34,18 @@ class Span
public:
Span() { }
void Draw(int index, int tilenum, bool shade, bool texture, bool zbuffer, bool flip);
void Dump();
void SetMachine(running_machine* machine);
void Draw1Cycle(int index, int tilenum, bool flip);
void Draw2Cycle(int index, int tilenum, bool flip);
void DrawCopy(int index, int tilenum, bool flip);
void DrawFill(int index, int tilenum, bool flip);
public:
int m_lx;
int m_rx;
int m_unscissored_rx;
SpanParam m_s;
SpanParam m_t;
@ -51,22 +56,12 @@ class Span
SpanParam m_a;
SpanParam m_z;
UINT8 m_cvg[RDP_CVG_SPAN_MAX];
int m_dymax;
SpanParam m_ds;
SpanParam m_dt;
SpanParam m_dw;
SpanParam m_dr;
SpanParam m_dg;
SpanParam m_db;
SpanParam m_da;
SpanParam m_dz;
int m_dzpix;
UINT16 m_cvg[RDP_CVG_SPAN_MAX];
private:
void RGBAZClip(int sr, int sg, int sb, int sa, int *sz);
void RGBAZCorrectTriangle(INT32 offx, INT32 offy, INT32* r, INT32* g, INT32* b, INT32* a, INT32* z);
running_machine* m_machine;
Processor* m_rdp;
MiscState* m_misc_state;

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,6 @@
#define _VIDEO_RDPTEXPIPE_H_
#include "emu.h"
#include "video/rdpfetch.h"
namespace N64
{
@ -25,23 +24,39 @@ class TexturePipe
{
m_maskbits_table[i] = ((UINT16)(0xffff) >> (16 - i)) & 0x3ff;
}
m_start_span = false;
m_precomp_s = 0;
m_precomp_t = 0;
}
UINT32 Fetch(INT32 SSS, INT32 SST, Tile* tile);
void Cycle(Color* TEX, Color* prev, INT32 SSS, INT32 SST, UINT32 tilenum, UINT32 cycle);
void Copy(Color* TEX, INT32 SSS, INT32 SST, UINT32 tilenum);
UINT32 Fetch(INT32 SSS, INT32 SST, INT32 tile);
void CalculateClampDiffs(UINT32 prim_tile);
void LOD1Cycle(INT32* sss, INT32* sst, INT32 s, INT32 t, INT32 w, INT32 dsinc, INT32 dtinc, INT32 dwinc);
void LOD2Cycle(INT32* sss, INT32* sst, INT32 s, INT32 t, INT32 w, INT32 dsinc, INT32 dtinc, INT32 dwinc, INT32 prim_tile, INT32* t1, INT32* t2);
void LOD2CycleLimited(INT32* sss, INT32* sst, INT32 s, INT32 t, INT32 w, INT32 dsinc, INT32 dtinc, INT32 dwinc, INT32 prim_tile, INT32* t1);
void SetMachine(running_machine* machine);
bool m_start_span;
INT32 m_precomp_s;
INT32 m_precomp_t;
private:
void Mask(INT32* S, INT32* T, Tile* tile);
void TexShift(INT32* S, INT32* T, bool* maxs, bool* maxt, Tile *tile);
void Clamp(INT32* S, INT32* T, INT32* SFRAC, INT32* TFRAC, bool maxs, bool maxt, Tile* tile);
void ClampLight(INT32* S, INT32* T, bool maxs, bool maxt, Tile* tile);
void Mask(INT32* S, INT32* T, INT32 num);
void MaskCoupled(INT32* S, INT32* S1, INT32* T, INT32* T1, INT32 num);
void ShiftCycle(INT32* S, INT32* T, INT32* maxs, INT32* maxt, UINT32 num);
void ShiftCopy(INT32* S, INT32* T, UINT32 num);
void ClampCycle(INT32* S, INT32* T, INT32* SFRAC, INT32* TFRAC, INT32 maxs, INT32 maxt, INT32 num);
void ClampCycleLight(INT32* S, INT32* T, bool maxs, bool maxt, INT32 num);
running_machine* m_machine;
OtherModes* m_other_modes;
MiscState* m_misc_state;
Processor* m_rdp;
TexFetch m_tex_fetch;
INT32 m_maskbits_table[16];
INT32 m_clamp_t_diff[8];

View File

@ -1,460 +0,0 @@
#include "emu.h"
#include "includes/n64.h"
#include "video/n64.h"
namespace N64
{
namespace RDP
{
#define LookUpCC(A, B, C, D) m_rdp->GetCCLUT2()[(m_rdp->GetCCLUT1()[(A << 16) | (B << 8) | C] << 8) | D]
void TexRectangle::SetMachine(running_machine* machine)
{
_n64_state *state = machine->driver_data<_n64_state>();
m_machine = machine;
m_rdp = &state->m_rdp;
m_other_modes = m_rdp->GetOtherModes();
m_misc_state = m_rdp->GetMiscState();
}
void TexRectangle::Draw()
{
switch(m_other_modes->cycle_type)
{
case CYCLE_TYPE_1:
case CYCLE_TYPE_2:
DrawDefault();
return;
case CYCLE_TYPE_COPY:
DrawCopy();
return;
default:
fatalerror("Unsupported cycle type for Textured Rectangle: %d\n", m_other_modes->cycle_type);
return;
}
}
void TexRectangle::DrawDefault()
{
UINT16 *fb = (UINT16*)&rdram[(m_misc_state->m_fb_address / 4)];
UINT8 *hb = &m_rdp->GetHiddenBits()[m_misc_state->m_fb_address >> 1];
UINT16 *zb = (UINT16*)&rdram[m_misc_state->m_zb_address / 4];
UINT8 *zhb = &m_rdp->GetHiddenBits()[m_misc_state->m_zb_address >> 1];
UINT32 tilenum = m_tilenum;
N64::RDP::Tile *tex_tile = &m_rdp->GetTiles()[m_tilenum];
UINT32 tilenum2 = 0;
N64::RDP::Tile *tex_tile2 = NULL;
int x1 = m_xh >> 2;
int x2 = m_xl >> 2;
int y1 = m_yh >> 2;
int y2 = m_yl >> 2;
if (x2 <= x1)
{
x2 = x1 + 1;
}
if (y1 == y2)
{
y2 = y1 + 1; // Needed by Goldeneye
}
if ((m_xl & 3) == 3) // Needed by Mega Man 64
{
x2++;
}
if ((m_yl & 3) == 3)
{
y2++;
}
m_rdp->GetTexPipe()->CalculateClampDiffs(tilenum);
if(m_other_modes->cycle_type == CYCLE_TYPE_2)
{
if (!m_other_modes->tex_lod_en)
{
tilenum2 = (tilenum + 1) & 7;
tex_tile2 = &m_rdp->GetTiles()[tilenum2];
}
else
{
tilenum2 = (tilenum + 1) & 7;
tex_tile2 = &m_rdp->GetTiles()[tilenum2];
}
}
m_rdp->GetShadeColor()->c = 0; // Needed by Pilotwings 64
if(y1 < m_rdp->GetScissor()->m_yh)
{
m_t += m_dtdy * (m_rdp->GetScissor()->m_yh - y1);
y1 = m_rdp->GetScissor()->m_yh;
}
if(y2 > m_rdp->GetScissor()->m_yl)
{
y2 = m_rdp->GetScissor()->m_yl;
}
if(x1 < m_rdp->GetScissor()->m_xh)
{
m_s += m_dsdx * (m_rdp->GetScissor()->m_xh - x1);
x1 = m_rdp->GetScissor()->m_xh;
}
if(x2 > m_rdp->GetScissor()->m_xl)
{
x2 = m_rdp->GetScissor()->m_xl;
}
m_dsdx >>= 5;
m_dtdy >>= 5;
int t = ((int)(m_t));
if(m_flip)
{
for (int j = y1; j < y2; j++)
{
int fb_index = j * m_misc_state->m_fb_width;
int mline = 0;
if(!(m_other_modes->rgb_dither_sel & 2))
{
mline = (j & 3) << 2;
}
int s = ((int)(m_s));
for (int i = x1; i < x2; i++)
{
N64::RDP::Color c1;
N64::RDP::Color c2;
int dith = 0;
int curpixel = fb_index + i;
UINT16* fbcur = &fb[curpixel ^ WORD_ADDR_XOR];
UINT8* hbcur = &hb[curpixel ^ BYTE_ADDR_XOR];
UINT16* zbcur = &zb[curpixel ^ WORD_ADDR_XOR];
UINT8* zhbcur = &zhb[curpixel ^ BYTE_ADDR_XOR];
m_misc_state->m_curpixel_cvg = 8;
if(m_other_modes->cycle_type == CYCLE_TYPE_1)
{
m_rdp->GetTexel0Color()->c = m_rdp->GetTexPipe()->Fetch(t, s, tex_tile);
c1.i.r = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_r[1],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_r[1],
*m_rdp->GetColorInputs()->combiner_rgbmul_r[1],
*m_rdp->GetColorInputs()->combiner_rgbadd_r[1]);
c1.i.g = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_g[1],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_g[1],
*m_rdp->GetColorInputs()->combiner_rgbmul_g[1],
*m_rdp->GetColorInputs()->combiner_rgbadd_g[1]);
c1.i.b = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_b[1],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_b[1],
*m_rdp->GetColorInputs()->combiner_rgbmul_b[1],
*m_rdp->GetColorInputs()->combiner_rgbadd_b[1]);
c1.i.a = LookUpCC(*m_rdp->GetColorInputs()->combiner_alphasub_a[1],
*m_rdp->GetColorInputs()->combiner_alphasub_b[1],
*m_rdp->GetColorInputs()->combiner_alphamul[1],
*m_rdp->GetColorInputs()->combiner_alphaadd[1]);
m_rdp->GetAlphaCvg(&c1.i.a);
}
else
{
m_rdp->GetTexel0Color()->c = m_rdp->GetTexPipe()->Fetch(t, s, tex_tile);
m_rdp->GetTexel1Color()->c = m_rdp->GetTexPipe()->Fetch(t, s, tex_tile2);
c1.i.r = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_r[0],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_r[0],
*m_rdp->GetColorInputs()->combiner_rgbmul_r[0],
*m_rdp->GetColorInputs()->combiner_rgbadd_r[0]);
c1.i.g = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_g[0],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_g[0],
*m_rdp->GetColorInputs()->combiner_rgbmul_g[0],
*m_rdp->GetColorInputs()->combiner_rgbadd_g[0]);
c1.i.b = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_b[0],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_b[0],
*m_rdp->GetColorInputs()->combiner_rgbmul_b[0],
*m_rdp->GetColorInputs()->combiner_rgbadd_b[0]);
c1.i.a = LookUpCC(*m_rdp->GetColorInputs()->combiner_alphasub_a[0],
*m_rdp->GetColorInputs()->combiner_alphasub_b[0],
*m_rdp->GetColorInputs()->combiner_alphamul[0],
*m_rdp->GetColorInputs()->combiner_alphaadd[0]);
m_rdp->GetCombinedColor()->c = c1.c;
c2.c = m_rdp->GetTexel0Color()->c;
m_rdp->GetTexel0Color()->c = m_rdp->GetTexel1Color()->c;
m_rdp->GetTexel1Color()->c = c2.c;
c2.i.r = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_r[1],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_r[1],
*m_rdp->GetColorInputs()->combiner_rgbmul_r[1],
*m_rdp->GetColorInputs()->combiner_rgbadd_r[1]);
c2.i.g = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_g[1],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_g[1],
*m_rdp->GetColorInputs()->combiner_rgbmul_g[1],
*m_rdp->GetColorInputs()->combiner_rgbadd_g[1]);
c2.i.b = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_b[1],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_b[1],
*m_rdp->GetColorInputs()->combiner_rgbmul_b[1],
*m_rdp->GetColorInputs()->combiner_rgbadd_b[1]);
c2.i.a = LookUpCC(*m_rdp->GetColorInputs()->combiner_alphasub_a[1],
*m_rdp->GetColorInputs()->combiner_alphasub_b[1],
*m_rdp->GetColorInputs()->combiner_alphamul[1],
*m_rdp->GetColorInputs()->combiner_alphaadd[1]);
m_rdp->GetAlphaCvg(&c2.i.a);
}
if(m_other_modes->rgb_dither_sel == 0)
{
dith = m_rdp->GetMagicMatrix()[mline + ((i ^ WORD_ADDR_XOR) & 3)];
}
else if(m_other_modes->rgb_dither_sel == 1)
{
dith = m_rdp->GetBayerMatrix()[mline + ((i ^ WORD_ADDR_XOR) & 3)];
}
bool z_compare_result = true;
if(m_other_modes->z_compare_en)
{
z_compare_result = m_rdp->ZCompare(fbcur, hbcur, zbcur, zhbcur, ((UINT32)m_misc_state->m_primitive_z)<<3, m_misc_state->m_primitive_delta_z);
}
if(z_compare_result)
{
bool rendered = m_rdp->GetBlender()->Blend(fbcur, hbcur, c1, c2, dith);
if(m_other_modes->z_update_en && rendered)
{
m_rdp->ZStore(zbcur, zhbcur, ((UINT32)m_misc_state->m_primitive_z) << 3, m_misc_state->m_primitive_delta_z);
}
}
s += (int)(m_dsdx);
}
t += (int)(m_dtdy);
}
}
else
{
for (int j = y1; j < y2; j++)
{
int fb_index = j * m_misc_state->m_fb_width;
int mline = 0;
if(!(m_other_modes->rgb_dither_sel & 2))
{
mline = (j & 3) << 2;
}
int s = ((int)(m_s));
for (int i = x1; i < x2; i++)
{
N64::RDP::Color c1;
N64::RDP::Color c2;
int dith = 0;
int curpixel = fb_index + i;
UINT16* fbcur = &fb[curpixel ^ WORD_ADDR_XOR];
UINT8* hbcur = &hb[curpixel ^ BYTE_ADDR_XOR];
UINT16* zbcur = &zb[curpixel ^ WORD_ADDR_XOR];
UINT8* zhbcur = &zhb[curpixel ^ BYTE_ADDR_XOR];
m_misc_state->m_curpixel_cvg = 8;
if(m_other_modes->cycle_type == CYCLE_TYPE_1)
{
m_rdp->GetTexel0Color()->c = m_rdp->GetTexPipe()->Fetch(s, t, tex_tile);
c1.i.r = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_r[1],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_r[1],
*m_rdp->GetColorInputs()->combiner_rgbmul_r[1],
*m_rdp->GetColorInputs()->combiner_rgbadd_r[1]);
c1.i.g = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_g[1],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_g[1],
*m_rdp->GetColorInputs()->combiner_rgbmul_g[1],
*m_rdp->GetColorInputs()->combiner_rgbadd_g[1]);
c1.i.b = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_b[1],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_b[1],
*m_rdp->GetColorInputs()->combiner_rgbmul_b[1],
*m_rdp->GetColorInputs()->combiner_rgbadd_b[1]);
c1.i.a = LookUpCC(*m_rdp->GetColorInputs()->combiner_alphasub_a[1],
*m_rdp->GetColorInputs()->combiner_alphasub_b[1],
*m_rdp->GetColorInputs()->combiner_alphamul[1],
*m_rdp->GetColorInputs()->combiner_alphaadd[1]);
m_rdp->GetAlphaCvg(&c1.i.a);
}
else
{
m_rdp->GetTexel0Color()->c = m_rdp->GetTexPipe()->Fetch(s, t, tex_tile);
m_rdp->GetTexel1Color()->c = m_rdp->GetTexPipe()->Fetch(s, t, tex_tile2);
c1.i.r = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_r[0],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_r[0],
*m_rdp->GetColorInputs()->combiner_rgbmul_r[0],
*m_rdp->GetColorInputs()->combiner_rgbadd_r[0]);
c1.i.g = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_g[0],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_g[0],
*m_rdp->GetColorInputs()->combiner_rgbmul_g[0],
*m_rdp->GetColorInputs()->combiner_rgbadd_g[0]);
c1.i.b = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_b[0],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_b[0],
*m_rdp->GetColorInputs()->combiner_rgbmul_b[0],
*m_rdp->GetColorInputs()->combiner_rgbadd_b[0]);
c1.i.a = LookUpCC(*m_rdp->GetColorInputs()->combiner_alphasub_a[0],
*m_rdp->GetColorInputs()->combiner_alphasub_b[0],
*m_rdp->GetColorInputs()->combiner_alphamul[0],
*m_rdp->GetColorInputs()->combiner_alphaadd[0]);
m_rdp->GetCombinedColor()->c = c1.c;
c2.c = m_rdp->GetTexel0Color()->c;
m_rdp->GetTexel0Color()->c = m_rdp->GetTexel1Color()->c;
m_rdp->GetTexel1Color()->c = c2.c;
c2.i.r = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_r[1],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_r[1],
*m_rdp->GetColorInputs()->combiner_rgbmul_r[1],
*m_rdp->GetColorInputs()->combiner_rgbadd_r[1]);
c2.i.g = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_g[1],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_g[1],
*m_rdp->GetColorInputs()->combiner_rgbmul_g[1],
*m_rdp->GetColorInputs()->combiner_rgbadd_g[1]);
c2.i.b = LookUpCC(*m_rdp->GetColorInputs()->combiner_rgbsub_a_b[1],
*m_rdp->GetColorInputs()->combiner_rgbsub_b_b[1],
*m_rdp->GetColorInputs()->combiner_rgbmul_b[1],
*m_rdp->GetColorInputs()->combiner_rgbadd_b[1]);
c2.i.a = LookUpCC(*m_rdp->GetColorInputs()->combiner_alphasub_a[1],
*m_rdp->GetColorInputs()->combiner_alphasub_b[1],
*m_rdp->GetColorInputs()->combiner_alphamul[1],
*m_rdp->GetColorInputs()->combiner_alphaadd[1]);
m_rdp->GetAlphaCvg(&c2.i.a);
}
if(m_other_modes->rgb_dither_sel == 0)
{
dith = m_rdp->GetMagicMatrix()[mline + ((i ^ WORD_ADDR_XOR) & 3)];
}
else if(m_other_modes->rgb_dither_sel == 1)
{
dith = m_rdp->GetBayerMatrix()[mline + ((i ^ WORD_ADDR_XOR) & 3)];
}
bool z_compare_result = true;
if(m_other_modes->z_compare_en)
{
z_compare_result = m_rdp->ZCompare(fbcur, hbcur, zbcur, zhbcur, ((UINT32)m_misc_state->m_primitive_z)<<3, m_misc_state->m_primitive_delta_z);
}
if(z_compare_result)
{
bool rendered = m_rdp->GetBlender()->Blend(fbcur, hbcur, c1, c2, dith);
if(m_other_modes->z_update_en && rendered)
{
m_rdp->ZStore(zbcur, zhbcur, ((UINT32)m_misc_state->m_primitive_z) << 3, m_misc_state->m_primitive_delta_z);
}
}
s += (int)(m_dsdx);
}
t += (int)(m_dtdy);
}
}
}
void TexRectangle::DrawCopy()
{
UINT16 *fb = (UINT16*)&rdram[(m_misc_state->m_fb_address / 4)];
N64::RDP::Tile *tex_tile = &m_rdp->GetTiles()[m_tilenum];
int x1 = m_xh >> 2;
int x2 = m_xl >> 2;
int y1 = m_yh >> 2;
int y2 = m_yl >> 2;
if (x2 <= x1)
{
x2 = x1 + 1;
}
if (y1 == y2)
{
y2 = y1 + 1; // Needed by Goldeneye
}
m_dsdx /= 4;
x2 += 1;
y2 += 1;
m_rdp->GetShadeColor()->c = 0; // Needed by Pilotwings 64
if(y1 < m_rdp->GetScissor()->m_yh)
{
m_t += m_dtdy * (m_rdp->GetScissor()->m_yh - y1);
y1 = m_rdp->GetScissor()->m_yh;
}
if(y2 > m_rdp->GetScissor()->m_yl)
{
y2 = m_rdp->GetScissor()->m_yl;
}
if(x1 < m_rdp->GetScissor()->m_xh)
{
m_s += m_dsdx * (m_rdp->GetScissor()->m_xh - x1);
x1 = m_rdp->GetScissor()->m_xh;
}
if(x2 > m_rdp->GetScissor()->m_xl)
{
x2 = m_rdp->GetScissor()->m_xl;
}
m_dsdx >>= 5;
m_dtdy >>= 5;
int t = (int)m_t;
if(m_flip)
{
for (int j = y1; j < y2; j++)
{
int fb_index = j * m_misc_state->m_fb_width;
int s = (int)(m_s);
for (int i = x1; i < x2; i++)
{
m_rdp->GetTexel0Color()->c = m_rdp->GetTexPipe()->Fetch(t, s, tex_tile);
m_misc_state->m_curpixel_cvg = 8;
if ((m_rdp->GetTexel0Color()->i.a != 0)||(!m_other_modes->alpha_compare_en))
{
fb[(fb_index + i) ^ WORD_ADDR_XOR] = ((m_rdp->GetTexel0Color()->i.r >> 3) << 11) | ((m_rdp->GetTexel0Color()->i.g >> 3) << 6) | ((m_rdp->GetTexel0Color()->i.b >> 3) << 1)|1;
}
s += m_dsdx;
}
t += m_dtdy;
}
}
else
{
for (int j = y1; j < y2; j++)
{
int fb_index = j * m_misc_state->m_fb_width;
int s = (int)(m_s);
for (int i = x1; i < x2; i++)
{
m_rdp->GetTexel0Color()->c = m_rdp->GetTexPipe()->Fetch(s, t, tex_tile);
m_misc_state->m_curpixel_cvg = 8;
if ((m_rdp->GetTexel0Color()->i.a != 0)||(!m_other_modes->alpha_compare_en))
{
fb[(fb_index + i) ^ WORD_ADDR_XOR] = ((m_rdp->GetTexel0Color()->i.r >> 3) << 11) | ((m_rdp->GetTexel0Color()->i.g >> 3) << 6) | ((m_rdp->GetTexel0Color()->i.b >> 3) << 1)|1;
}
s += m_dsdx;
}
t += m_dtdy;
}
}
}
} // namespace RDP
} // namespace N64

View File

@ -1,57 +0,0 @@
#ifndef _VIDEO_RDPTEXRECT_H_
#define _VIDEO_RDPTEXRECT_H_
#include "emu.h"
namespace N64
{
namespace RDP
{
class OtherModes;
class MiscState;
class Processor;
class Color;
class TexRectangle
{
public:
TexRectangle() {}
TexRectangle(running_machine *machine, UINT32 *data, int flip)
{
SetMachine(machine);
InitFromBuffer(data);
m_flip = flip;
}
void Draw();
void SetMachine(running_machine *machine);
void InitFromBuffer(UINT32 *data);
int m_tilenum;
UINT16 m_xl; // 10.2 fixed-point
UINT16 m_yl; // 10.2 fixed-point
UINT16 m_xh; // 10.2 fixed-point
UINT16 m_yh; // 10.2 fixed-point
INT16 m_s; // 10.5 fixed-point
INT16 m_t; // 10.5 fixed-point
INT16 m_dsdx; // 5.10 fixed-point
INT16 m_dtdy; // 5.10 fixed-point
int m_flip;
private:
void DrawDefault();
void DrawCopy();
running_machine* m_machine;
Processor* m_rdp;
MiscState* m_misc_state;
OtherModes* m_other_modes;
};
} // namespace RDP
} // namespace N64
#endif // _VIDEO_RDPTEXRECT_H_

View File

@ -16,12 +16,15 @@ class Triangle
{
public:
Triangle() { fatalerror("Please don't use the default constructor for N64::RDP::Triangle\n"); }
Triangle(running_machine* machine, bool shade, bool texture, bool zbuffer);
Triangle(running_machine *machine, bool shade, bool texture, bool zbuffer, bool rect, bool flip);
void InitFromData(running_machine* machine, bool shade, bool texture, bool zbuffer);
void InitFromData(running_machine* machine, bool shade, bool texture, bool zbuffer, bool rect, bool flip);
void Draw();
private:
void compute_cvg_noflip(INT32* majorx, INT32* minorx, INT32* majorxint, INT32* minorxint, INT32 scanline, INT32 yh, INT32 yl);
void compute_cvg_flip(INT32* majorx, INT32* minorx, INT32* majorxint, INT32* minorxint, INT32 scanline, INT32 yh, INT32 yl);
running_machine* m_machine;
UINT32* m_cmd_data;
MiscState* m_misc_state;
@ -29,6 +32,7 @@ class Triangle
bool m_shade;
bool m_texture;
bool m_zbuffer;
bool m_rect;
};
} // namespace RDP