News: 11 March 2016 - Forum Rules

Author Topic: RDP emulation?  (Read 5372 times)

Yoshimaster96

  • Jr. Member
  • **
  • Posts: 26
    • View Profile
RDP emulation?
« on: June 14, 2014, 06:55:08 pm »
Hello once again! I have a question:
Code: [Select]
#include <stdio.h>
#include <math.h>
#include "glut.h"
#pragma comment (lib,"glut32.lib")

unsigned char redfr,greenfr,bluefr,alphafr;
float redfo,greenfo,bluefo,alphafo;
float redenv,greenenv,blueenv,alphaenv;
float redbl,greenbl,bluebl,alphabl;
float redpr,greenpr,bluepr,alphapr;
float cr,cg,cb,sr,sg,sb,wr,wg,wb;
short k0,k1,k2,k3,k4,k5;

void execucode(unsigned char ucode[176])
{
switch(ucode[0]&0x3F)
{
case 0x00:
{
//NOOP
break;
}
case 0x08:
{
//TRI
float fucode[176];
for(int i=0; i<176; i++)
{
fucode[i] = ucode[i];
}
bool flip = (ucode[1]&0x80) ? true : false;
char mipmaps = (ucode[1]&0x38)>>3;
char tile = ucode[1]&0x07;
float yl = (ucode[2]&0x1F)*64 + (fucode[3]/4);
if(ucode[2]&0x20) yl -= 2048;
float ym = (ucode[4]&0x1F)*64 + (fucode[5]/4);
if(ucode[4]&0x20) ym -= 2048;
float yh = (ucode[6]&0x1F)*64 + (fucode[7]/4);
if(ucode[6]&0x20) yl -= 2048;
float xl = (fucode[8]*256) + (fucode[9]) + (fucode[10]/256) + (fucode[11]/65536);
if(ucode[8]&0x80) xl -= 65536;
float dxldy = (fucode[12]*256) + (fucode[13]) + (fucode[14]/256) + (fucode[15]/65536);
if(ucode[12]&0x80) dxldy -= 65536;
float xh = (fucode[16]*256) + (fucode[17]) + (fucode[18]/256) + (fucode[19]/65536);
if(ucode[16]&0x80) xh -= 65536;
float dxhdy = (fucode[20]*256) + (fucode[21]) + (fucode[22]/256) + (fucode[23]/65536);
if(ucode[20]&0x80) dxhdy -= 65536;
float xm = (fucode[24]*256) + (fucode[25]) + (fucode[26]/256) + (fucode[27]/65536);
if(ucode[24]&0x80) xm -= 65536;
float dxmdy = (fucode[28]*256) + (fucode[29]) + (fucode[30]/256) + (fucode[31]/65536);
if(ucode[28]&0x80) dxmdy -= 65536;
if(flip)
{
glBegin(GL_TRIANGLES);
glVertex2f(xh-(dxhdy*(yl-floor(yh))),yl);
glVertex2f(xl+(dxldy*(ceil(ym)-ym)),ym);
glVertex2f(xm+(dxmdy*(yh-floor(yh))),yh);
glEnd();
}
else
{
glBegin(GL_TRIANGLES);
glVertex2f(xh+(dxhdy*(yl-floor(yh))),yl);
glVertex2f(xl-(dxldy*(ceil(ym)-ym)),ym);
glVertex2f(xm-(dxmdy*(yh-floor(yh))),yh);
glEnd();
}
break;
}
case 0x09:
{
//TRI_Z
float fucode[176];
for(int i=0; i<176; i++)
{
fucode[i] = ucode[i];
}
bool flip = (ucode[1]&0x80) ? true : false;
char mipmaps = (ucode[1]&0x38)>>3;
char tile = ucode[1]&0x07;
float yl = (ucode[2]&0x1F)*64 + (fucode[3]/4);
if(ucode[2]&0x20) yl -= 2048;
float ym = (ucode[4]&0x1F)*64 + (fucode[5]/4);
if(ucode[4]&0x20) ym -= 2048;
float yh = (ucode[6]&0x1F)*64 + (fucode[7]/4);
if(ucode[6]&0x20) yl -= 2048;
float xl = (fucode[8]*256) + (fucode[9]) + (fucode[10]/256) + (fucode[11]/65536);
if(ucode[8]&0x80) xl -= 65536;
float dxldy = (fucode[12]*256) + (fucode[13]) + (fucode[14]/256) + (fucode[15]/65536);
if(ucode[12]&0x80) dxldy -= 65536;
float xh = (fucode[16]*256) + (fucode[17]) + (fucode[18]/256) + (fucode[19]/65536);
if(ucode[16]&0x80) xh -= 65536;
float dxhdy = (fucode[20]*256) + (fucode[21]) + (fucode[22]/256) + (fucode[23]/65536);
if(ucode[20]&0x80) dxhdy -= 65536;
float xm = (fucode[24]*256) + (fucode[25]) + (fucode[26]/256) + (fucode[27]/65536);
if(ucode[24]&0x80) xm -= 65536;
float dxmdy = (fucode[28]*256) + (fucode[29]) + (fucode[30]/256) + (fucode[31]/65536);
if(ucode[28]&0x80) dxmdy -= 65536;
float z = (fucode[28]*256) + (fucode[29]) + (fucode[30]/256) + (fucode[31]/65536);
if(ucode[28]&0x80) z -= 65536;
float dzdx = (fucode[28]*256) + (fucode[29]) + (fucode[30]/256) + (fucode[31]/65536);
if(ucode[28]&0x80) dzdx -= 65536;
float dzde = (fucode[28]*256) + (fucode[29]) + (fucode[30]/256) + (fucode[31]/65536);
if(ucode[28]&0x80) dzde -= 65536;
float dzdy = (fucode[28]*256) + (fucode[29]) + (fucode[30]/256) + (fucode[31]/65536);
if(ucode[28]&0x80) dzdy -= 65536;
if(flip)
{
glBegin(GL_TRIANGLES);
glVertex3f(xh-(dxhdy*(yl-floor(yh))),yl,0);
glVertex3f(xl+(dxldy*(ceil(ym)-ym)),ym,0);
glVertex3f(xm+(dxmdy*(yh-floor(yh))),yh,0);
glEnd();
}
else
{
glBegin(GL_TRIANGLES);
glVertex3f(xh+(dxhdy*(yl-floor(yh))),yl,0);
glVertex3f(xl-(dxldy*(ceil(ym)-ym)),ym,0);
glVertex3f(xm-(dxmdy*(yh-floor(yh))),yh,0);
glEnd();
}
break;
}
case 0x0A:
{
//TRI_TEX
break;
}
case 0x0B:
{
//TRI_TEX_Z
break;
}
case 0x0C:
{
//TRI_SHADE
break;
}
case 0x0D:
{
//TRI_SHADE_Z
break;
}
case 0x0E:
{
//TRI_TEX_SHADE
break;
}
case 0x0F:
{
//TRI_TEX_SHADE_Z
break;
}
case 0x24:
{
//TEX_RECT
float x1 = (ucode[1]*4) + ((ucode[2]&0xF0)/64);
float y1 = ((ucode[2]&0x0F)*64) + (ucode[3]/4);
char tile = ucode[4]&0x07;
float x2 = (ucode[5]*4) + ((ucode[6]&0xF0)/64);
float y2 = ((ucode[6]&0x0F)*64) + (ucode[7]/4);
float s = (ucode[8]*32) + (ucode[9]/8);
if(ucode[8]&0x80) s *= -1;
float t = (ucode[10]*32) + (ucode[11]/8);
if(ucode[10]&0x80) s *= -1;
float dsdx = (ucode[12]/8) + (ucode[13]/2048);
if(ucode[12]&0x80) dsdx *= -1;
float dtdy = (ucode[14]/8) + (ucode[15]/2048);
if(ucode[14]&0x80) dtdy *= -1;
glBegin(GL_QUADS);
glTexCoord2f(s,t);
glVertex2f(x1,y1);
glTexCoord2f(s,t+(dtdy*(y2-y1)));
glVertex2f(x1,y2);
glTexCoord2f(s+(dsdx*(x2-x1)),t+(dtdy*(y2-y1)));
glVertex2f(x2,y2);
glTexCoord2f(s+(dsdx*(x2-x1)),t);
glVertex2f(x2,y1);
glEnd();
break;
}
case 0x25:
{
//TEX_RECT_FLIP
float x1 = (ucode[1]*4) + ((ucode[2]&0xF0)/64);
float y1 = ((ucode[2]&0x0F)*64) + (ucode[3]/4);
char tile = ucode[4]&0x07;
float x2 = (ucode[5]*4) + ((ucode[6]&0xF0)/64);
float y2 = ((ucode[6]&0x0F)*64) + (ucode[7]/4);
float s = (ucode[8]*32) + (ucode[9]/8);
if(ucode[8]&0x80) s *= -1;
float t = (ucode[10]*32) + (ucode[11]/8);
if(ucode[10]&0x80) s *= -1;
float dsdx = (ucode[12]/8) + (ucode[13]/2048);
if(ucode[12]&0x80) dsdx *= -1;
float dtdy = (ucode[14]/8) + (ucode[15]/2048);
if(ucode[14]&0x80) dtdy *= -1;
glBegin(GL_QUADS);
glTexCoord2f(-s,-t);
glVertex2f(x1,y1);
glTexCoord2f(-s,-t-(dtdy*(y2-y1)));
glVertex2f(x1,y2);
glTexCoord2f(-s-(dsdx*(x2-x1)),-t-(dtdy*(y2-y1)));
glVertex2f(x2,y2);
glTexCoord2f(-s-(dsdx*(x2-x1)),-t);
glVertex2f(x2,y1);
glEnd();
break;
}
case 0x26:
{
//SYNC_LOAD
break;
}
case 0x27:
{
//SYNC_PIPE
break;
}
case 0x28:
{
//SYNC_TILE
break;
}
case 0x29:
{
//SYNC_FULL
break;
}
case 0x2A:
{
//KEY_GB
cg = ucode[4]/255;
sg = ucode[5]/255;
wg = (ucode[1]<<4 + (ucode[2]&0xF0)>>4)/255;
cb = ucode[6]/255;
sb = ucode[7]/255;
wb = ((ucode[2]&0x0F)<<8 + ucode[3])/255;
break;
}
case 0x2B:
{
//KEY_R
cr = ucode[6]/255;
sr = ucode[7]/255;
wr = ((ucode[4]&0x0F)<<8 + ucode[5])/255;
break;
}
case 0x2C:
{
//SET_CONVERT
k0 = (ucode[1]&0x3F)<<3 + (ucode[2]&0xE0)>>5;
k1 = (ucode[2]&0x1F)<<4 + (ucode[3]&0xF0)>>4;
k2 = (ucode[3]&0x0F)<<5 + (ucode[2]&0xF8)>>3;
k3 = (ucode[2]&0x07)<<6 + (ucode[3]&0xFC)>>2;
k4 = (ucode[1]&0x03)<<7 + (ucode[2]&0xFE)>>1;
k5 = (ucode[2]&0x01)<<8 + (ucode[3]&0xFF);
break;
}
case 0x2D:
{
//SET_SCISSOR
float x1 = (ucode[1]*16) + ((ucode[2]&0xF0)/16);
float y1 = ((ucode[2]&0x0F)*256) + ucode[3];
float x2 = (ucode[5]*16) + ((ucode[6]&0xF0)/16);
float y2 = ((ucode[6]&0x0F)*256) + ucode[7];
glOrtho(x1,y2,x2,y1,-128,128);
break;
}
case 0x2E:
{
//SET_PRIM_DEPTH
break;
}
case 0x2F:
{
//SET_OTHER_MODE
break;
}
case 0x30:
{
//LOAD_TLUT
break;
}
case 0x32:
{
//SET_TILE_SIZE
break;
}
case 0x33:
{
//LOAD_BLOCK
break;
}
case 0x34:
{
//LOAD_TILE
break;
}
case 0x35:
{
//SET_TILE
break;
}
case 0x36:
{
//FILL_RECT
glColor4ub(redfr,greenfr,bluefr,alphafr);
short x1 = (ucode[1]*4) + ((ucode[2]&0xF0)/64);
short y1 = ((ucode[2]&0x0F)*64) + (ucode[3]/4);
short x2 = (ucode[5]*4) + ((ucode[6]&0xF0)/64);
short y2 = ((ucode[6]&0x0F)*64) + (ucode[7]/4);
glBegin(GL_QUADS);
glVertex2f(x1,y1);
glVertex2f(x1,y2);
glVertex2f(x2,y2);
glVertex2f(x2,y1);
glEnd();
glColor4ub(255,255,255,255);
break;
}
case 0x37:
{
//SET_FILL_COLOR
redfr = ucode[4];
greenfr = ucode[5];
bluefr = ucode[6];
alphafr = ucode[7];
break;
}
case 0x38:
{
//SET_FOG_COLOR
redfo = ucode[4]/255;
greenfo = ucode[5]/255;
bluefo = ucode[6]/255;
alphafo = ucode[7]/255;
glEnable(GL_FOG);
float fo[4] = {redfo,greenfo,bluefo,alphafo};
glFogfv(GL_FOG_COLOR,fo);
glFogi(GL_FOG_MODE, GL_LINEAR);
glFogi(GL_FOG_START,-128);
glFogi(GL_FOG_END,128);
break;
}
case 0x39:
{
//SET_BLEND_COLOR
redbl = ucode[4]/255;
greenbl = ucode[5]/255;
bluebl = ucode[6]/255;
alphabl = ucode[7]/255;
break;
}
case 0x3A:
{
//SET_PRIM_COLOR
redpr = ucode[4]/255;
greenpr = ucode[5]/255;
bluepr = ucode[6]/255;
alphapr = ucode[7]/255;
break;
}
case 0x3B:
{
//SET_ENV_COLOR
redenv = ucode[4]/255;
greenenv = ucode[5]/255;
blueenv = ucode[6]/255;
alphaenv = ucode[7]/255;
glClearColor(redenv,greenenv,blueenv,alphaenv);
glClear(GL_COLOR_BUFFER_BIT);
break;
}
case 0x3C:
{
//SET_COMBINE
break;
}
case 0x3D:
{
//SET_TEXTURE_IMAGE
char format = (ucode[1]&0xE0)>>5;
char psize = (ucode[1]&0x18)>>3;
short size = (ucode[2]&0x03)<<8 + ucode[3];
long addr = ((ucode[4]&0x03)<<24) + (ucode[5]<<16) + (ucode[6]<<8) + ucode[7];
break;
}
case 0x3E:
{
//SET_MASK_IMAGE
long addr = ((ucode[4]&0x03)<<24) + (ucode[5]<<16) + (ucode[6]<<8) + ucode[7];
break;
}
case 0x3F:
{
//SET_COLOR_IMAGE
char format = (ucode[1]&0xE0)>>5;
char psize = (ucode[1]&0x18)>>3;
short size = (ucode[2]&0x03)<<8 + ucode[3];
long addr = ((ucode[4]&0x03)<<24) + (ucode[5]<<16) + (ucode[6]<<8) + ucode[7];
break;
}
}
}

void display()
{
unsigned char inst[176];
inst[0] = 0x08;
inst[1] = 0x00;
inst[2] = 0x03;
inst[3] = 0x00;
inst[4] = 0x02;
inst[5] = 0x00;
inst[6] = 0x01;
inst[7] = 0x00;
inst[8] = 0x00;
inst[9] = 0x40;
inst[10] = 0x00;
inst[11] = 0x00;
inst[12] = 0x00;
inst[13] = 0x02;
inst[14] = 0x00;
inst[15] = 0x00;
inst[16] = 0x00;
inst[17] = 0x80;
inst[18] = 0x00;
inst[19] = 0x00;
inst[20] = 0x00;
inst[21] = 0x00;
inst[22] = 0x80;
inst[23] = 0x00;
inst[24] = 0x00;
inst[25] = 0x80;
inst[26] = 0x00;
inst[27] = 0x00;
inst[28] = 0xFF;
inst[29] = 0xFF;
inst[30] = 0x00;
inst[31] = 0x00;
execucode(inst);
glFlush();
}

int main(int argc, char ** argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA);
glutInitWindowPosition(0,0);
glutInitWindowSize(256,256);
glutCreateWindow("UCODE");
glClearColor(0,0,0,0);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
glOrtho(0,256,256,0,-128,128);
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
On the TRI_Z command, what X and Y coordinate is the z variable based on? I need to know so I can use it, dzdx, dzde, and dzdy to find the Z coordinate for each vertex.

MathOnNapkins

  • Forum Moderator
  • Hero Member
  • *****
  • Posts: 647
  • Who ya gonna call
    • View Profile
    • Arc-Nova - Rohmackin' and Chiptunin'
Re: RDP emulation?
« Reply #1 on: June 16, 2014, 11:25:29 am »
Since you provide no frame of reference, can you tell me what RDP you're talking about? I assume it's remote desktop protocol, but I don't understand why you would refer to this as "emulation"...

Yoshimaster96

  • Jr. Member
  • **
  • Posts: 26
    • View Profile
Re: RDP emulation?
« Reply #2 on: June 16, 2014, 12:19:47 pm »
Since you provide no frame of reference, can you tell me what RDP you're talking about? I assume it's remote desktop protocol, but I don't understand why you would refer to this as "emulation"...
I'm talking about N64 RDP.

MathOnNapkins

  • Forum Moderator
  • Hero Member
  • *****
  • Posts: 647
  • Who ya gonna call
    • View Profile
    • Arc-Nova - Rohmackin' and Chiptunin'
Re: RDP emulation?
« Reply #3 on: June 16, 2014, 01:42:06 pm »
Oh right, that thing. That explains why your code looks like Open GL code or something similar.

Yoshimaster96

  • Jr. Member
  • **
  • Posts: 26
    • View Profile
Re: RDP emulation?
« Reply #4 on: June 16, 2014, 04:19:14 pm »
So then where would the z variable be relative to x and y in the TRI_Z case? I mean what x and y coordinate would the depth be equal to the z variable?

Yoshimaster96

  • Jr. Member
  • **
  • Posts: 26
    • View Profile
Re: RDP emulation?
« Reply #5 on: July 05, 2014, 06:35:09 pm »
Hello? Someone's got to know.

Klarth

  • Sr. Member
  • ****
  • Posts: 498
    • View Profile
Re: RDP emulation?
« Reply #6 on: July 10, 2014, 07:35:52 pm »
I don't think anyone is going to attempt deciphering badly written code with no comments. The aim of the code is not obvious to me.

Yoshimaster96

  • Jr. Member
  • **
  • Posts: 26
    • View Profile
Re: RDP emulation?
« Reply #7 on: July 12, 2014, 03:26:45 pm »
I don't think anyone is going to attempt deciphering badly written code with no comments. The aim of the code is not obvious to me.
It's meant to decipher RDP commands and display them in a window. I'll admit, though, it has very little comments. What I want to know is how to find the z coordinate at each vertex. Unfortunately, I can't find it without knowing the z origin, (the x-y coordinate where the given z value in the command is equal to the depth). Then, I can use dzdx and dzdy to determine the z coordinates of each vertex.

Zoinkity

  • Hero Member
  • *****
  • Posts: 565
    • View Profile
Re: RDP emulation?
« Reply #8 on: July 16, 2014, 12:31:56 pm »
If I remember correctly, the difference between an RDP tri and RDP tri_z is tri_z uses the depth buffer.  Computing depth eats the RDP alive though, which is why there's a non-z-buffer variants for the base commands (trifill, tritxtr, trishade, trishadetxtr) in the first place.

I'd advise you to reference either the MAME/MESS source or CEN64 for an accurate method for projection.  Glide was the first plugin to even attempt to interpret the low-level opcodes because, well, you usually don't use these directly; the RSP generates them from microcode.  There are a small number of exceptions; somewhat more famous among them are the skies and water in Rare's FPS titles.  Anyway, that was only a few years ago, and the documents used as reference were copyrighted first-party material (which is why you can't find them).  As far as I know MESS redid the work from scratch so their source and notes would be your best bet for a proper explaination.

What are you actually trying to do though?  As in, what's the application?  Are you trying to rip models, building a projector, reversing some microcode, or something else?