[SOLVED]PVR Rendering Code not producing Output on Dreamcast

Whether you're a newbie or an experienced programmer, any questions, help, or just talk of any language will be welcomed here.

Moderator: Coders of Rage

User avatar
shmup73
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 11
Joined: Wed Jan 29, 2014 12:44 pm
Current Project: 2D Cross Platform Game Engine
Favorite Gaming Platforms: Playstation, Gameboy Advance, Dreamcast, PC
Programming Language of Choice: C, C++, C#

[SOLVED]PVR Rendering Code not producing Output on Dreamcast

Post by shmup73 »

Hey everyone,

First of all a big "Thank You" to all of you, especially the Development Team for kinda "lighting the Dreamcast - Spark inside me", in other words having made me interested in a Dreamcast, buy a Dreamcast and now program for a Dreamcast :)

Now to my Problem...
While flawlessly compiling and - after conversion to a .cdi Image with BootDreams - also running on nullDC w/ Chankast as Rendering Plugin, my .cdi just won't show any graphical output on the Dreamcast itself when burned on a Disk using Alocohol 120%.

What drives me crazy about this is, that the CD-R boots without problems, shows a red border and even receives Controller Input (i can close my Program using [START] as implemented).
This means the Application actually RUNS, but somehow no graphical output is to be seen. (besides the borders)

Can anyone maybe point me to what the Problem could be?
I'm gonna receive an SD-Adapter anytime near the next 3 weeks, but i'd really like to get something up running on a CD-R just as - you know - somewhat like a proof of concept.

Any help is appreciated.
Thanks alot, shmup.

[EDIT]
Okay so I've hunted It down and am now definitely able to blame my Code, as other KOS Example Projects run normally even when burned to CD-R and thrown into my DC.

Right now my Code looks like the following:
int main(int argc, char **argv) {

    //Quit Flag
    int finished = 0;
    srand(timer_ms_gettime64());

    //Reposition Cubes & Triangles randomly on Screen
    updatePrimitives();


    //Initialize Video Settings
    if(!castInitVideo()){
        return CAST_ERR_INITPVR;
    }


    //Main Loop
    while(!finished){

        //Update Controller Status
        castUpdateControllers();

        if(castGetButtonState(CAST_CONTROLLER_SLOT_1, CAST_BUTTON_RIGHT)){
            updatePrimitives();
        }

        //Exit Program with [START] Button
        if(castGetButtonState(CAST_CONTROLLER_SLOT_1, CAST_BUTTON_START)){
            ++finished;
        }

        //Draw Scene
        draw();
    }


    //Give the PVR his deserved Break
    pvr_shutdown();

    return CAST_ERR_NONE;
}
The Segments that are interesting for you are obviously the castInitVideo(void) and draw(void) Functions.
Here they are. I'm initializing the PVR as follows:

[Inside the Header File]
/****************************************************************************************************************/
#define CAST_VBUFSZ_TOTAL  (1024 * 1024) //1MB of Geometry VRAM
#define CAST_VBUFSZ_OPPOLY (1024 * 1024)
#define CAST_VBUFSZ_OPMOD   (256 * 1024)
#define CAST_VBUFSZ_TRPOLY  (512 * 1024)
#define CAST_VBUFSZ_TRMOD   (256 * 1024)
#define CAST_VBUFSZ_PTPOLY  (512 * 1024)
/****************************************************************************************************************/
[Inside the Source File]
/****************************************************************************************************************/
static uint8 CAST_VBUF_OPPOLY[CAST_VBUFSZ_OPPOLY] __attribute__((aligned(32))); //Opaque Polygon Buffer
static uint8 CAST_VBUF_OPMOD  [CAST_VBUFSZ_OPMOD] __attribute__((aligned(32))); //Opaque Modifier Buffer
static uint8 CAST_VBUF_TRPOLY[CAST_VBUFSZ_TRPOLY] __attribute__((aligned(32))); //Transparent Polygon Buffer
static uint8 CAST_VBUF_TRMOD  [CAST_VBUFSZ_TRMOD] __attribute__((aligned(32))); //Transparent Modifier Buffer
static uint8 CAST_VBUF_PTPOLY[CAST_VBUFSZ_PTPOLY] __attribute__((aligned(32))); //Punch-Thru Polygon Buffer
/****************************************************************************************************************/


/****************************************************************************************************************/
int castInitVideo(void){

    //Init PowerVR Rendering Features
    pvr_init_params_t pvrParams;

    pvrParams.dma_enabled = 1;
    pvrParams.fsaa_enabled = 0;
    pvrParams.vertex_buf_size = CAST_VBUFSZ_TOTAL;

    pvrParams.opb_sizes[PVR_LIST_OP_POLY]   = PVR_BINSIZE_32;
    pvrParams.opb_sizes[PVR_LIST_OP_MOD]    = PVR_BINSIZE_8;
    pvrParams.opb_sizes[PVR_LIST_TR_POLY]   = PVR_BINSIZE_16;
    pvrParams.opb_sizes[PVR_LIST_TR_MOD]    = PVR_BINSIZE_8;
    pvrParams.opb_sizes[PVR_LIST_PT_POLY]   = PVR_BINSIZE_16;

    //Abort on Failure
    if( pvr_init(&pvrParams) < 0 ){
        printf("Error Initializing PVR!\n");
        return CAST_ERR_INITPVR;
    }else{
        printf("Initialized PVR successfully!\n");
    }

    //Link Vertex Buffers
    pvr_set_vertbuf(PVR_LIST_OP_POLY, CAST_VBUF_OPPOLY, CAST_VBUFSZ_OPPOLY);
    printf("Set Vertex Buffer for Opaque Polygons to %ukB\n", CAST_VBUFSZ_OPPOLY / 1024);

    pvr_set_vertbuf(PVR_LIST_OP_MOD , CAST_VBUF_OPMOD,  CAST_VBUFSZ_OPMOD );
    printf("Set Vertex Buffer for Opaque Polygon Modifiers to %ukB\n", CAST_VBUFSZ_OPMOD / 1024);

    pvr_set_vertbuf(PVR_LIST_TR_POLY, CAST_VBUF_TRPOLY, CAST_VBUFSZ_TRPOLY);
    printf("Set Vertex Buffer for Transparent Polygons to %ukB\n", CAST_VBUFSZ_TRPOLY / 1024);

    pvr_set_vertbuf(PVR_LIST_TR_MOD , CAST_VBUF_TRMOD,  CAST_VBUFSZ_TRMOD );
    printf("Set Vertex Buffer for Transparent Polygon Modifiers to %ukB\n", CAST_VBUFSZ_TRMOD / 1024);

    pvr_set_vertbuf(PVR_LIST_PT_POLY, CAST_VBUF_PTPOLY, CAST_VBUFSZ_PTPOLY);
    printf("Set Vertex Buffer for Punch-Thru Polygons to %ukB\n", CAST_VBUFSZ_PTPOLY / 1024);

    pvr_set_pal_format(PVR_PAL_ARGB8888);
    pvr_set_bg_color(0, 0, 0);

    //Success
    return 1;
}
/****************************************************************************************************************/
This seems to run fine, as It doesn't throw any Errors, neither on nullDC nor on the Dreamcast.
So the next possible Source of Problems is the actual Rendering Code, this basically uses the technique demonstrated by Falco in his DMA / Store Queue Tutorial.

Inside the draw Function i'm basically doing this:

Prepare the next Frame:
void castBeginScene(void){

    vid_border_color(0xff, 0, 0);
    pvr_wait_ready();
    vid_border_color(0, 0xff, 0);
    pvr_scene_begin();
}
Prepare Geometry Transfer: (in my Case called with PVR_LIST_TR_POLY)
/****************************************************************************************************************/
static uint32  CAST_CURRENT_LIST        = 0;       //Current Vertex Buffer Type to write to
static uint32 *CAST_SUBMIT_START_PTR    = NULL;    //Address of the Begin of the current Vertex Data Batch
static uint32 *CAST_SUBMIT_CURRENT_PTR  = NULL;    //Address of Vertex Data currently pointed to
/****************************************************************************************************************/

void castStartSubmit(uint32 pvrListType){

    CAST_CURRENT_LIST = pvrListType;

    //Retrieve current Position in selected Vertex Buffer
    uint32 *ptr = (uint32*)pvr_vertbuf_tail(CAST_CURRENT_LIST);

    QACR0 = ((((uint32)ptr) >> 26) << 2) & 0x1c;
    QACR1 = ((((uint32)ptr) >> 26) << 2) & 0x1c;

    //Update Start & current Pointer
    CAST_SUBMIT_START_PTR = CAST_SUBMIT_CURRENT_PTR = (uint32 *) (0xe0000000 | (((uint32)ptr) & 0x03ffffe0));
}
What happens next is the actual Geometry, e.g. a Cube that get's sent this way:
void castDrawQuad(const Cast_Quad *quad, uint32 color){

    Cast_PolyHeader header;
    Cast_PolyContext context;
    castCreatePolyContextColored(&context, PVR_LIST_TR_POLY);
    castCompilePolyHeader(&header, &context);
    castSendPolyHeader(&header);


    //Begin Transparent Vertex List
    Cast_Vertex vertex;
    castVertexColor(&vertex, color);
    castVertexDepth(&vertex, 0);
    castVertexUV(&vertex, 0, 0);



    //Lower Left Corner
    castVertexPos(
                  &vertex,
                  quad->pos.x,
                  quad->pos.y + quad->h);
    castSendVertex(&vertex, PVR_CMD_VERTEX);
 
    //Upper Left Corner
    castVertexPos(
                  &vertex,
                  quad->pos.x,
                  quad->pos.y);
    castSendVertex(&vertex, PVR_CMD_VERTEX);

    //Lower Right Corner
    castVertexPos(
                  &vertex,
                  quad->pos.x + quad->w,
                  quad->pos.y + quad->h);
    castSendVertex(&vertex, PVR_CMD_VERTEX);

    //Upper Right Corner
    castVertexPos(
                  &vertex,
                  quad->pos.x + quad->w,
                  quad->pos.y);
    castSendVertex(&vertex, PVR_CMD_VERTEX_EOL);
}
Where most of the Functions and Types you see pretty much directly wrap PVR Functions, only to make them more readable. What should be more interesting for you though, as I think, are the castSendVertex- & PolyHeader Methods.
/****************************************************************************************************************/
#define CAST_PREFETCH( PTR ) __asm__ __volatile__( "pref @%0" : : "r" (PTR) )
/****************************************************************************************************************/

/****************************************************************************************************************/
void castSendPolyHeader(const Cast_PolyHeader *header){

    register uint32 *ptr = (uint32*)( CAST_SUBMIT_CURRENT_PTR + 8 );

    *--ptr = header->d4;        //Written 04 Bytes
    *--ptr = header->d3;        //Written 08 Bytes
    *--ptr = header->d2;        //Written 12 Bytes
    *--ptr = header->d1;        //Written 16 Bytes
    *--ptr = header->mode3;     //Written 20 Bytes
    *--ptr = header->mode2;     //Written 24 Bytes
    *--ptr = header->mode1;     //Written 28 Bytes
    *--ptr = header->cmd;       //Written 32 Bytes

    CAST_PREFETCH((void *)ptr); //Prefetch

    CAST_SUBMIT_CURRENT_PTR = (uint32*)( ptr + 8 );  //Point to next Position in Vertex Buffer
}
/****************************************************************************************************************/


/****************************************************************************************************************/
void castSendVertex(const Cast_Vertex *vertex, uint32 flags){

    register uint32 *ptr = (uint32*)( CAST_SUBMIT_CURRENT_PTR + 8 );

    *--ptr = vertex->oargb;         //Written 04 Bytes
    *--ptr = vertex->argb;          //Written 08 Bytes
    *(float*)--ptr = vertex->v;     //Written 12 Bytes
    *(float*)--ptr = vertex->u;     //Written 16 Bytes
    *(float*)--ptr = vertex->z;     //Written 20 Bytes
    *(float*)--ptr = vertex->y;     //Written 24 Bytes
    *(float*)--ptr = vertex->x;     //Written 28 Bytes
    *--ptr = flags;                 //Written 32 Bytes

    CAST_PREFETCH((void *)ptr);     //Prefetch

    CAST_SUBMIT_CURRENT_PTR = (uint32*)( ptr + 8 );  //Point to next Position in Vertex Buffer
}
/****************************************************************************************************************/
After all of that, the Frame is ended by a Call to
void castFinishSubmit(void){

    uint32 writtenBytes = (uint32)CAST_SUBMIT_CURRENT_PTR - (uint32)CAST_SUBMIT_START_PTR;

    //Send Information about written Data Size to PVR
    if(writtenBytes){
        pvr_vertbuf_written(CAST_CURRENT_LIST, writtenBytes);
    }
}
And finally
void castEndScene(void){

    vid_border_color(0, 0, 0xff);
    pvr_scene_finish();
}
All of this works perfectly fine on the Emulator, but as soon as I burn it and run it on the DC all I can see are the red border Lines telling me that pvr_wait_ready() never ever finishes (on the other hand the main loop obviously ...loops... :lol: :nono: ..as I receive "Live" controller input.

Because I'm somewhat new to the whole KOS / PVR Stuff I hope I'm just forgetting about something really obvious that needs to be done manually on the actual Hardware and is done automatically on the Emulator or such.

Sorry for spamming such a shitload of Code but i really wasn't able to spot the possible Problem more precisely. :roll:

Thanks in Advance,
shmup. :worship:
Last edited by shmup73 on Thu Feb 06, 2014 3:34 pm, edited 1 time in total.

Code: Select all

#ifndef SIGNATURE_H
#define SIGNATURE_H

#include <stdio.h>

//Maximum Length of Signature
#define SIGNATURE_MAX_LEN 512u

typedef struct{

    //ID of the Signature
    uint8  id;

    //Text included in the Signature
    char text[SIGNATURE_MAX_LEN];
} SIGNATURE;

//Set the Text of a Signature
void signatureSetText(SIGNATURE *signature, const char *text){
    strncpy(signature, text, strlen(text));
}

//Get the Length of a Signature's Text
void signatureGetLen(const SIGNATURE *signature, uint16 *len_out){
    *len_out = strlen(signature->text);
}

#endif //SIGNATURE_H
User avatar
Falco Girgis
Elysian Shadows Team
Elysian Shadows Team
Posts: 10294
Joined: Thu May 20, 2004 2:04 pm
Current Project: Elysian Shadows
Favorite Gaming Platforms: Dreamcast, SNES, NES
Programming Language of Choice: C/++
Location: Studio Vorbis, AL
Contact:

Re: PVR Rendering Code not producing Output on Dreamcast

Post by Falco Girgis »

Hey buddy.

Sorry, I haven't had time to sit down and work through this, been super busy staying up all night with ES, got a lot of shit going on at work, and I'm sitting in class right now.

Based on your symptoms of working in an emulator but not a hardware, you can almost count on it being some sort of hardware-specific low-level issue that is not being emulated.

Likely culprits are things like prefetches and store queue memory accesses that aren't on word boundaries. This will definitely cause the hardware to shit itself. Pay special attention to those kinds of operations and their alignments.
User avatar
shmup73
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 11
Joined: Wed Jan 29, 2014 12:44 pm
Current Project: 2D Cross Platform Game Engine
Favorite Gaming Platforms: Playstation, Gameboy Advance, Dreamcast, PC
Programming Language of Choice: C, C++, C#

Re: PVR Rendering Code not producing Output on Dreamcast

Post by shmup73 »

Hey Falco,

Well first of all thanks for taking the time to read my post despite being super busy. :worship:

Still all of this is really strange to me. First of all obviously because I'm not used to having to deal with problems like crippled memory alignment caused by the Hardware when having only coded for the PC before with all those cuddly "standards" friendly people have set up for my convenience. But well.. that's the challenge and what makes programming the DC and other consoles fun, atleast for me.

But despite all of that, my Code still shouldn't be any different to the Example you gave :/
That's why I don't really get what could possibly be wrong with it.

Does ist help to spam __attribute__((aligned(X))) after each and every variable of X bytes of size?
I think i might jzst give it a try as well as have a deeper look at the store queue & prefetch operations as you suggested!

If you or any one else happens to have the time to read through the code bit by bit and stumbles upon the solution it'd obviously still be highly appreciated.

Thanks alot & best wishes for futher ES Development ;)

Code: Select all

#ifndef SIGNATURE_H
#define SIGNATURE_H

#include <stdio.h>

//Maximum Length of Signature
#define SIGNATURE_MAX_LEN 512u

typedef struct{

    //ID of the Signature
    uint8  id;

    //Text included in the Signature
    char text[SIGNATURE_MAX_LEN];
} SIGNATURE;

//Set the Text of a Signature
void signatureSetText(SIGNATURE *signature, const char *text){
    strncpy(signature, text, strlen(text));
}

//Get the Length of a Signature's Text
void signatureGetLen(const SIGNATURE *signature, uint16 *len_out){
    *len_out = strlen(signature->text);
}

#endif //SIGNATURE_H
User avatar
Falco Girgis
Elysian Shadows Team
Elysian Shadows Team
Posts: 10294
Joined: Thu May 20, 2004 2:04 pm
Current Project: Elysian Shadows
Favorite Gaming Platforms: Dreamcast, SNES, NES
Programming Language of Choice: C/++
Location: Studio Vorbis, AL
Contact:

Re: PVR Rendering Code not producing Output on Dreamcast

Post by Falco Girgis »

shmup73 wrote:First of all obviously because I'm not used to having to deal with problems like crippled memory alignment caused by the Hardware when having only coded for the PC before with all those cuddly "standards" friendly people have set up for my convenience.
Believe it or not, the x86 architecture behaves the same way... If you were coding at a low-enough level to be manually prefetching cache lines or accessing any specific hardware subsystem like that, it would absolutely have to be word-aligned to not shit itself.

I'll try to take a deeper look at this after work today.
User avatar
shmup73
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 11
Joined: Wed Jan 29, 2014 12:44 pm
Current Project: 2D Cross Platform Game Engine
Favorite Gaming Platforms: Playstation, Gameboy Advance, Dreamcast, PC
Programming Language of Choice: C, C++, C#

Re: PVR Rendering Code not producing Output on Dreamcast

Post by shmup73 »

Thanks! Well... I never thought about it that way. But it totally makes sense of course.
Guess there's still a lot left to learn for me ;)
Falco Girgis wrote:I'll try to take a deeper look at this after work today.
That would be more than awesome. 8-)

Code: Select all

#ifndef SIGNATURE_H
#define SIGNATURE_H

#include <stdio.h>

//Maximum Length of Signature
#define SIGNATURE_MAX_LEN 512u

typedef struct{

    //ID of the Signature
    uint8  id;

    //Text included in the Signature
    char text[SIGNATURE_MAX_LEN];
} SIGNATURE;

//Set the Text of a Signature
void signatureSetText(SIGNATURE *signature, const char *text){
    strncpy(signature, text, strlen(text));
}

//Get the Length of a Signature's Text
void signatureGetLen(const SIGNATURE *signature, uint16 *len_out){
    *len_out = strlen(signature->text);
}

#endif //SIGNATURE_H
User avatar
Light-Dark
Dreamcast Developer
Dreamcast Developer
Posts: 307
Joined: Sun Mar 13, 2011 7:57 pm
Current Project: 2D RPG & NES Platformer
Favorite Gaming Platforms: NES,SNES,N64,Genesis,Dreamcast,PC,Xbox360
Programming Language of Choice: C/++
Location: Canada

Re: PVR Rendering Code not producing Output on Dreamcast

Post by Light-Dark »

I experienced a similar issue with the hardware not liking my non-32-byte aligned floats. After doing a quick look through KOS I found out it had to be 32-byte aligned and after doing a quick look at SQ.c(located in kos/kernel/arch/dreamcast/hardware) now, it appears you do indeed have to have it be 32-byte aligned:
/* KallistiOS 2.0.0

   kernel/arch/dreamcast/hardware/sq.c
   (c)2001 Andrew Kieschnick
*/

#include <dc/sq.h>

/*
    Functions to clear, copy, and set memory using the sh4 store queues

    Based on code by Marcus Comstedt (store_q_clear from tatest)
*/

///////////////////////////////////////////////////////////////////
/* clears n bytes at dest, dest must be 32-byte aligned */
///////////////////////////////////////////////////////////////////

void sq_clr(void *dest, int n) {
    unsigned int *d = (unsigned int *)(void *)
                      (0xe0000000 | (((unsigned long)dest) & 0x03ffffe0));

    /* Set store queue memory area as desired */
    QACR0 = ((((unsigned int)dest) >> 26) << 2) & 0x1c;
    QACR1 = ((((unsigned int)dest) >> 26) << 2) & 0x1c;
EDIT:
I went ahead and 32-byte aligned every pointer in your SQ rendering system code, did a test on actual hardware and as you can see in the image I have linked below it worked :)!
http://i.imgur.com/MAzIWQc.jpg
<tpw_rules> LightDark: java is a consequence of inverse moore's law: every 18 months, the average program will be twice as slow. therefore, computers always run at the same percevied speed. java's invention was a monumental step
Image
User avatar
Falco Girgis
Elysian Shadows Team
Elysian Shadows Team
Posts: 10294
Joined: Thu May 20, 2004 2:04 pm
Current Project: Elysian Shadows
Favorite Gaming Platforms: Dreamcast, SNES, NES
Programming Language of Choice: C/++
Location: Studio Vorbis, AL
Contact:

Re: PVR Rendering Code not producing Output on Dreamcast

Post by Falco Girgis »

Yes, the store queues operate on 32-byte data sets, and they do have to be aligned.
User avatar
shmup73
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 11
Joined: Wed Jan 29, 2014 12:44 pm
Current Project: 2D Cross Platform Game Engine
Favorite Gaming Platforms: Playstation, Gameboy Advance, Dreamcast, PC
Programming Language of Choice: C, C++, C#

Re: PVR Rendering Code not producing Output on Dreamcast

Post by shmup73 »

Well first thanks a lot to both of you guys! :)

Still i need to ask you how i would go about aligning these pointers correctly.
Sorry for being such a noob concerning this topic. I tried googling it, but it simply
won't do the trick. :oops:

What I came up with after reading a bit is this:
//Align a Pointer to 32 Byte Boundary
void *castAlignPtr32(void *in_ptr){

    uint8 *ptr __attribute__((aligned(32))) = NULL;
    ptr = (uint8*)in_ptr;

    return (void*) ( ( (uint32)( ptr + 31 ) ) & ( ~31 ) );
}

------------------------------------------------------------------------------

//Wherever a pointer happens to occur in my whole rendering Code:
TYPE *POINTER __attribute__((aligned(32)));
POINTER = castAlignPtr32(OTHER_POINTER);

------------------------------------------------------------------------------

//For example in this Function:
void castStartSubmit(uint32 pvrListType){

    CAST_CURRENT_LIST = pvrListType;

    //Retrieve current Position in selected Vertex Buffer
    uint32  *ptr        __attribute__((aligned(32))) = NULL;
    void    *vbuf_tail  __attribute__((aligned(32))) = pvr_vertbuf_tail(CAST_CURRENT_LIST);

    ptr = castAlignPtr32( vbuf_tail );

    //Value to write to Store Queue
    uint32 storeQueueValue;
    storeQueueValue = ((((uint32)ptr) >> 26) << 2) & 0x1c;

    QACR0 = storeQueueValue;
    QACR1 = storeQueueValue;

    //Update Start & current Pointer
    CAST_SUBMIT_START_PTR = CAST_SUBMIT_CURRENT_PTR = (uint32*)castAlignPtr32((void*)(0xe0000000 | (((uint32)ptr) & 0x03ffffe0)));
}
But apparently this is not doing what It's supposed to,
as spamming it in front of literally EVERY F'N pointer ever
being created or passed to any function doesn't seem to change
anything.
Light-Dark wrote:I went ahead and 32-byte aligned every pointer in your SQ rendering system code
Would you mind sharing your wisdom of how to align these fuckers correctly with me?
It'd be highly appreciated. :roll:
shmup!
User avatar
Light-Dark
Dreamcast Developer
Dreamcast Developer
Posts: 307
Joined: Sun Mar 13, 2011 7:57 pm
Current Project: 2D RPG & NES Platformer
Favorite Gaming Platforms: NES,SNES,N64,Genesis,Dreamcast,PC,Xbox360
Programming Language of Choice: C/++
Location: Canada

Re: PVR Rendering Code not producing Output on Dreamcast

Post by Light-Dark »

This is the exact code I have. To be honest the only code I used from you was the polygon header submitting routine the rest is directly from the tutorial blog. It works fine on hardware (I'm running it off my SD card reader, I also see you're going to get one in a couple of weeks and let me just say that so far it has served me very well and is 100000x better than burning through CD-Rs :)).

static uint8 op_poly_buf[OP_POLY_VBUFSIZE]__attribute__((aligned(32)));
static uint8 op_mod_buf[OP_MOD_VBUFSIZE]__attribute__((aligned(32)));
static uint8 tr_poly_buf[TR_POLY_VBUFSIZE]__attribute__((aligned(32)));
static uint8 tr_mod_buf[TR_MOD_VBUFSIZE]__attribute__((aligned(32)));
static uint8 pt_poly_buf[PT_POLY_VBUFSIZE]__attribute__((aligned(32)));

void Init_Video_DMA(void)
{
	vid_set_mode(DM_640x480,PM_RGB565);
	vid_border_color(0,255,0);
	//DMA Enabled
  pvr_init_params_t pvr_params;
  pvr_params.vertex_buf_size= GLOBAL_VBUFSIZE;
  pvr_params.dma_enabled= 1;
  pvr_params.fsaa_enabled= 0;
  pvr_params.opb_sizes[PVR_LIST_OP_POLY]= PVR_BINSIZE_32;
  pvr_params.opb_sizes[PVR_LIST_OP_MOD]= PVR_BINSIZE_8;
  pvr_params.opb_sizes[PVR_LIST_TR_POLY]= PVR_BINSIZE_16;
  pvr_params.opb_sizes[PVR_LIST_TR_MOD]= PVR_BINSIZE_8;
  pvr_params.opb_sizes[PVR_LIST_PT_POLY]= PVR_BINSIZE_16;
	
  pvr_init(&pvr_params);

	pvr_set_vertbuf( PVR_LIST_OP_POLY, op_poly_buf, OP_POLY_VBUFSIZE );
	pvr_set_vertbuf( PVR_LIST_OP_MOD,  op_mod_buf,  OP_MOD_VBUFSIZE  );
	pvr_set_vertbuf( PVR_LIST_TR_POLY, tr_poly_buf, TR_POLY_VBUFSIZE );
	pvr_set_vertbuf( PVR_LIST_TR_MOD,  tr_mod_buf,  TR_MOD_VBUFSIZE  );
	pvr_set_vertbuf( PVR_LIST_PT_POLY, pt_poly_buf, PT_POLY_VBUFSIZE );

	pvr_set_pal_format( PVR_PAL_ARGB4444 );
}


static pvr_list_t _current_list = PVR_LIST_OP_POLY;
static uint32* _start_ptr __attribute__((aligned(32))) = NULL;
static uint32* _current_ptr __attribute__((aligned(32))) = NULL;

void pvrBeginPrimitives( pvr_list_t list )
{
  _current_list = PVR_LIST_OP_POLY;
  uint32* ptr __attribute__((aligned(32)))  = (uint32*)pvr_vertbuf_tail( _current_list );
  QACR0 = ((((uint32)ptr) >> 26) << 2) & 0x1c;
  QACR1 = ((((uint32)ptr) >> 26) << 2) & 0x1c;
  _start_ptr = _current_ptr = (uint32 *) (0xe0000000 | (((uint32)ptr) & 0x03ffffe0));
}

void pvrEndPrimitives( void )
{
  uint32 bytes __attribute__((aligned(32))) = (uint32)_current_ptr - (uint32)_start_ptr;
  if ( bytes != 0 )
  pvr_vertbuf_written( _current_list, bytes );
}


void castSendPolyHeader(const pvr_poly_hdr_t *header){
 
    register uint32 *ptr __attribute__((aligned(32))) = (uint32*)( _current_ptr + 8 );
 
    *--ptr = header->d4;        //Written 04 Bytes
    *--ptr = header->d3;        //Written 08 Bytes
    *--ptr = header->d2;        //Written 12 Bytes
    *--ptr = header->d1;        //Written 16 Bytes
    *--ptr = header->mode3;     //Written 20 Bytes
    *--ptr = header->mode2;     //Written 24 Bytes
    *--ptr = header->mode1;     //Written 28 Bytes
    *--ptr = header->cmd;       //Written 32 Bytes
 
    PREFETCH((void *)ptr); //Prefetch
 
    _current_ptr = (uint32*)( ptr + 8 );  //Point to next Position in Vertex Buffer
}


void pvrSendVertex03( uint32 flags, float x, float y, float z, float u, float v, uint32 argb, uint32 oargb )
{
  register uint32* _ptr __attribute__((aligned(32))) = _current_ptr;
  _ptr += 8;
  *--_ptr= oargb;
  *--_ptr= argb;
  *(float*)--_ptr= v;
  *(float*)--_ptr= u;
  *(float*)--_ptr= z;
  *(float*)--_ptr= y;
  *(float*)--_ptr= x;
  *--_ptr= flags;
  PREFETCH((void *)_ptr);
  _ptr += 8;
  _current_ptr = _ptr;
}
void SQ_Draw_Rect(const float x, const float y,const float z, const float w,const float h,const Uint32 argb,const Uint8 tr)
{
	
	if(tr == 1)
	{
		p_cxt.gen.alpha = PVR_ALPHA_ENABLE;
		pvrBeginPrimitives(PVR_LIST_TR_POLY);
		//pvr_list_begin(PVR_LIST_TR_POLY);
		pvr_poly_cxt_col(&p_cxt,PVR_LIST_TR_POLY);
	}
	else
	{
		//pvr_list_begin(PVR_LIST_OP_POLY);
		pvrBeginPrimitives(PVR_LIST_OP_POLY);
		pvr_poly_cxt_col(&p_cxt,PVR_LIST_OP_POLY);
	}

	pvr_poly_compile(&p_hdr,&p_cxt);
	castSendPolyHeader(&p_hdr);

	pvrSendVertex03(PVR_CMD_VERTEX,x,y,z,0,0,argb,0);
	pvrSendVertex03(PVR_CMD_VERTEX,x+w,y,z,0,0,argb,0);
	pvrSendVertex03(PVR_CMD_VERTEX,x,y+h,z,0,0,argb,0);
	pvrSendVertex03(PVR_CMD_VERTEX_EOL,x+w,y+h,z,0,0,argb,0);

	pvrEndPrimitives();

}
Where p_cxt and p_hdr are just static globals for the standard PVR polygon contexts and lists. It seems to me what you're doing is making EVERYTHING aligned, all you really have to do is declare the pointer variables and other variables that are dealing with the hardware as 32-byte aligned. I hope this helps you in your quest good sir!
<tpw_rules> LightDark: java is a consequence of inverse moore's law: every 18 months, the average program will be twice as slow. therefore, computers always run at the same percevied speed. java's invention was a monumental step
Image
User avatar
shmup73
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 11
Joined: Wed Jan 29, 2014 12:44 pm
Current Project: 2D Cross Platform Game Engine
Favorite Gaming Platforms: Playstation, Gameboy Advance, Dreamcast, PC
Programming Language of Choice: C, C++, C#

Re: PVR Rendering Code not producing Output on Dreamcast

Post by shmup73 »

Thank you Light-Dark..

Actually, those were exactly the same pointers I aligned as well..
What my problem now is, is that even when I use EXACTLY the code you posted, it doesn't work..
It's not even showing anything on the Emulator anymore. I seriously don't know what the fuck is supposed to be wrong. :(

This is my loop right now:
//Draw a Frame
    vid_border_color(255, 0, 0);
    pvr_wait_ready();
    vid_border_color(0, 255, 0);
    pvr_scene_begin();

    int i=0;
    for(; i<12; ++i){

        SQ_Draw_Rect(0, 0, i-6, 640, 480, PVR_PACK_COLOR(255, 255, 255, 255), 0);
    }

    vid_border_color(0, 0, 255);
    pvr_scene_finish();
Which should produce atleast ONE white opaque quad covering the screen, right?
I'm using nothing but the Methods you posted. Seems to me I must be doing something in the wrong order..
User avatar
Light-Dark
Dreamcast Developer
Dreamcast Developer
Posts: 307
Joined: Sun Mar 13, 2011 7:57 pm
Current Project: 2D RPG & NES Platformer
Favorite Gaming Platforms: NES,SNES,N64,Genesis,Dreamcast,PC,Xbox360
Programming Language of Choice: C/++
Location: Canada

Re: PVR Rendering Code not producing Output on Dreamcast

Post by Light-Dark »

When you're packing the colour using the PVR packing macro this is pretty much what is going on:
#define PACK_COLOR_4(a,r,g,b) (  \
( ((uint8)( a * 255 ) ) << 24 ) | \
( ((uint8)( r * 255 ) ) << 16 ) | \
( ((uint8)( g * 255 ) ) << 8 ) | \
( ((uint8)( b * 255 ) ) << 0 ) )
So try writing it in the "floating point format" where 1.0 is the same as 255
PACK_COLOR_4(1,1,1,1)
Last edited by Light-Dark on Thu Feb 06, 2014 2:09 pm, edited 1 time in total.
<tpw_rules> LightDark: java is a consequence of inverse moore's law: every 18 months, the average program will be twice as slow. therefore, computers always run at the same percevied speed. java's invention was a monumental step
Image
User avatar
shmup73
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 11
Joined: Wed Jan 29, 2014 12:44 pm
Current Project: 2D Cross Platform Game Engine
Favorite Gaming Platforms: Playstation, Gameboy Advance, Dreamcast, PC
Programming Language of Choice: C, C++, C#

Re: PVR Rendering Code not producing Output on Dreamcast

Post by shmup73 »

Hmkay thanks, that atleast fixed the output on the Emulator..
Is there anything wrong about this line?
int i=0; for(; i<12; ++i){ SQ_Draw_Rect(640 / 12 * i, 0, 0, 640 / 12, 480, PVR_PACK_COLOR((float)rand() / (float)RAND_MAX, (float)rand() / (float)RAND_MAX, (float)rand() / (float)RAND_MAX, (float)rand() / (float)RAND_MAX), 1); }
As It works perfectly on the Emu but still doesn't on the DC.

Same goes for this:
SQ_Draw_Rect(640 / 12 * i, 0, 0, 640 / 12, 480, PVR_PACK_COLOR( 1, (float)(i%3) / 3.f, (float)(i%4) / 4.f, (float)(i%2) / 2.f ), 0);
Is it possible, that the PVR Initialization causes my problems?
Do I need to specify special Pixel - / Display Modes whatsoever, that differ from yours?
If it happens to be of significance, my DC is connected using the original Antenna cable..

Thanks in advance, Tom.
User avatar
Light-Dark
Dreamcast Developer
Dreamcast Developer
Posts: 307
Joined: Sun Mar 13, 2011 7:57 pm
Current Project: 2D RPG & NES Platformer
Favorite Gaming Platforms: NES,SNES,N64,Genesis,Dreamcast,PC,Xbox360
Programming Language of Choice: C/++
Location: Canada

Re: PVR Rendering Code not producing Output on Dreamcast

Post by Light-Dark »

There shouldn't be an issue with using an RF connector considering I have my Dreamcast hooked up to my tv using the RCA composite cables which according to video.h are essentially the same. Try setting the Z coordinate value to be 1.0 because I've had it where when the z coordinate was zero things wouldn't show up. Are you using a recent version(2.0.0) of KOS and the toolchain?
Last edited by Light-Dark on Thu Feb 06, 2014 4:06 pm, edited 1 time in total.
<tpw_rules> LightDark: java is a consequence of inverse moore's law: every 18 months, the average program will be twice as slow. therefore, computers always run at the same percevied speed. java's invention was a monumental step
Image
User avatar
shmup73
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 11
Joined: Wed Jan 29, 2014 12:44 pm
Current Project: 2D Cross Platform Game Engine
Favorite Gaming Platforms: Playstation, Gameboy Advance, Dreamcast, PC
Programming Language of Choice: C, C++, C#

Re: PVR Rendering Code not producing Output on Dreamcast

Post by shmup73 »

OMFG IT WORKS!!!
YOU HAVE NO IDEA OF HOW FUCKING GRATEFUL I AM RIGHT NOW! :mrgreen: :mrgreen:
(sry 4 caps)

Thanks a lot.. After all those pointer alignment obscurities it's been the damn Z coordinate....
....the Z coordinate...... :shock:

I've burned like 3k CD-Rs but it's been all worth It.
Now it's time to get onto some serious DC development! 8-)

(Well first things first, next step will be loading textures i guess^^)

Stay awesome!
Shmup aka. Tom.

PS: It's not KOS 2 i believe, as setting up the cygwin toolchain from the Git repo didn't wanna work, so I'm using version 1.2 or 1.3 i guess.. the one that came with the DC Dev Iso r4!
User avatar
Light-Dark
Dreamcast Developer
Dreamcast Developer
Posts: 307
Joined: Sun Mar 13, 2011 7:57 pm
Current Project: 2D RPG & NES Platformer
Favorite Gaming Platforms: NES,SNES,N64,Genesis,Dreamcast,PC,Xbox360
Programming Language of Choice: C/++
Location: Canada

Re: [SOLVED]PVR Rendering Code not producing Output on Dream

Post by Light-Dark »

Glad I could be of service my friend! And I know how much of a bitch it is to setup but it's worth it and if you're having issues with it check these things out:
http://dcemulation.org/phpBB/viewtopic. ... 0#p1041492
https://github.com/TimSimpson/KosVM

Good luck with your project :)!
<tpw_rules> LightDark: java is a consequence of inverse moore's law: every 18 months, the average program will be twice as slow. therefore, computers always run at the same percevied speed. java's invention was a monumental step
Image
Post Reply