gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

DS development > Display copy corruption

#63049 - Lazy1 - Thu Dec 08, 2005 4:10 am

[Edit]
Resolved stupid bug thx to natrium.
Still gotta fix the problem with darkness though :)
[/Edit]

I'm currently porting wolfenstein 3d to the DS, but unfortunately I have this screen on emulators aswell as hardware...
[Images not permitted - Click here to view it]

Is there anything horribly wrong with my drawing code?
Code:

#include <nds.h>
#include <nds/arm9/console.h>
#include <nds/bios.h>

#ifdef ROMDISKFS
#define stat_t unused_t
#include <kos/fs.h>
#include <kos/fs_romdisk.h>
#endif

#undef stat_t
#include <stdarg.h>
#include "wl_def.h"

/* Preprocessor definitions/macros */
#define NDS_PIXBUF_WIDTH 320
#define NDS_PIXBUF_HEIGHT 200
#define NDS_BG_WIDTH 512
#define NDS_BG_HEIGHT 256

/* RGB555TO888:
 * This macro converts RGB555 into RGB888
 *
 * colour15:   Unsigned 16 bit integer containing the RGB555 colour
 * r:      Unsigned 32 bit integer which receives the red value
 * g:      Unsigned 32 bit integer which receives the green value
 * b:      Unsigned 32 bit integer which receives the blue value
*/
#define RGB555TO888( colour15, r, g, b ) \
   r = colour15 & ~0xFFE0; \
   g = ( colour15 >> 5 ) & ~0xFFE0; \
   b = ( colour15 >> 10 ) & ~0xFFE0;

/* Function prototypes */
int nds_screen1_init( void );
int nds_screen2_init( void );
int nds_system_init( void );
void nds_sys_handle_interrupts( void );
void nds_sys_onexit( void );
void quadmemset( u32* pMemory, u32 iSetvalue, u32 iSize );
void quadcopy( u32* pSource, u32* pDest, u32 iSize );
int main( void );

/* Global variables */
#ifdef ROMDISKFS
extern char wolf3dromdisk[ ];
byte* wolf3d = ( byte* ) wolf3dromdisk;   /* Pointer to embedded wolf3d shareware romdisk */
#endif

byte* gfxbuf = NULL;   /* Pointer to the pixel buffer wolf3d writes video data to */

/* nds_sys_onexit:
 * Called if the program either returns or calls exit().
 * Since we have nothing to return to, an infinite loop should
 * do nicely.
*/
void nds_sys_onexit( void ) {
   printf( "FATAL: Application exiting!\n" );
   printf( "Hanging here.\n" );

   while ( 1 ) swiWaitForVBlank( );
}

/* quadcopy:
 * Copies memory 4 bytes at a time.
 *
 * pSource   : Source memory pointer
 * pDest   : Destination memory pointer
 * iSize   : Number of bytes to copy ( must by a multiple of 4 )
*/
void quadcopy( u32* pSource, u32* pDest, u32 iSize ) {
   while ( iSize-- ) {
      *pDest = *pSource;

      pDest++;
      pSource++;
   }
}

/* quadmemset:
 * Sets an area of memory 4 bytes at a time.
 *
 * pMemory   : Pointer to memory which will be set
 * iSetvalue   : Value to set memory to
 * iSize   : Size of memory ( must be a multiple of 4 )
*/
void quadmemset( u32* pMemory, u32 iSetvalue, u32 iSize ) {
   while ( iSize-- ) {
      *pMemory = iSetvalue;
      pMemory++;
   }
}

/* nds_screen1_init:
 * Initializes the main ( top ) screen on the Nintendo DS.
 *
 * Returns: Always 1
*/
int nds_screen1_init( void ) {
   /* Set mode 5 extended rotation background */
   videoSetMode( MODE_5_2D | DISPLAY_BG2_ACTIVE );
   vramSetBankA( VRAM_A_MAIN_BG_0x6000000 );

   /* Set background scaling, ect... */
   BG2_CR = BG_BMP8_512x256 | BG_BMP_BASE( 0 );
   BG2_XDX = ( ( NDS_PIXBUF_WIDTH / 256 ) << 8 ) | ( NDS_PIXBUF_WIDTH % 256 );
   BG2_YDY = ( ( NDS_PIXBUF_HEIGHT / 192 ) << 8 ) | ( ( NDS_PIXBUF_HEIGHT % 192 ) + ( NDS_PIXBUF_HEIGHT % 192 ) / 3 );
   BG2_XDY = 0;
   BG2_YDX = 0;
   BG2_CX = 0;
   BG2_CY = 0;

   /* Start off by clearing out the background memory */
   quadmemset( ( u32* ) BG_GFX, 0, ( NDS_BG_WIDTH * NDS_BG_HEIGHT ) );

   return 1;
}

/* nds_screen2_init:
 * Initializes the sub ( bottom/touch ) screen on the Nintendo DS.
 *
 * Returns: Always 1
*/
int nds_screen2_init( void ) {
   /* Set mode 0 for a text background */
   videoSetModeSub( MODE_0_2D | DISPLAY_BG0_ACTIVE );
   vramSetBankC( VRAM_C_SUB_BG );

   /* Setup text colour, ect... */
   BG_PALETTE_SUB[ 255 ] = RGB15( 31, 31, 31 );   
   SUB_BG0_CR = BG_MAP_BASE( 31 );

   /* Initialize the console with the default font */
   consoleInitDefault( ( u16* ) SCREEN_BASE_BLOCK_SUB( 31 ), ( u16* ) CHAR_BASE_BLOCK_SUB( 0 ), 16 );

   return 1;
}

/* nds_system_init:
 * Initializes the Nintendo DS and things like IRQs, ect...
 *
 * Returns: Always 1
*/
int nds_system_init( void ) {
   powerON( POWER_ALL_2D | POWER_SWAP_LCDS );   /* Enable both 2D cores and swap the lcds around */
   keysInit( );               /* Setup key usage */

   /* Setup the interrupt registers */
   REG_IME = 0;
   REG_IE = IRQ_VBLANK;
   REG_IF = ~0;
   IRQ_HANDLER = &nds_sys_handle_interrupts;
   REG_IME = 1;

   DISP_SR = DISP_VBLANK_IRQ;         /* Additional step for vblank */

   /* Make sure we don't exit into nothingness */
   atexit( nds_sys_onexit );

#ifdef ROMDISKFS
   fs_init( );
   fs_romdisk_mount( "/", ( const uint8* ) wolf3d, 0 );
#endif

   return 1;
}

/* nds_sys_handle_interrupts:
 * Interrupt handler for the nintendo DS.
*/
void nds_sys_handle_interrupts( void ) {
   /* Handle VBlank IRQ */
   if ( REG_IF & IRQ_VBLANK ) {
      /* Get the current = 4keystate each vblank */
      scanKeys( );
   
      /* VBlank IRQ handled */
      VBLANK_INTR_WAIT_FLAGS |= IRQ_VBLANK;
      REG_IF |= IRQ_VBLANK;
   }
}

/* main:
 * ARM9 binary entrypoint.
 *
 * Returns: Should never return
*/
int main( void ) {
   /* Initialize the system and both screens here */
   nds_screen1_init( );
   nds_screen2_init( );   
   nds_system_init( );

   /* Print welcome screen */
   printf( "Wolfenstein3D SDL port to\n" );
   printf( "the Nintendo DS.\n" );
   printf( "2005 - Lazy\n" );

   /* Enter the main application loop */
   WolfMain( 1, NULL );

   /* If we got here something bad happened that caused
    * WolfMain to return.
    * Since there is no OS to return to we must halt the
    * system here by entering an infinite loop.
   */
   printf( "FATAL: Broke out of WolfMain!\n" );
   printf( "Hanging here.\n" );
   while ( 1 ) swiWaitForVBlank( );

   return 1;
}

/* VL_WaitVBL:
 * Waits nVblanks, then returns.
*/
void VL_WaitVBL( int nVblanks ) {
   while ( nVblanks-- ) swiWaitForVBlank( );
}

/* VW_UpdateScreen:
 * Copies the contents of the pixel buffer to the screen.
*/
void VW_UpdateScreen( void ) {
   u32* pSource = ( u32* ) gfxbuf;
   u32* pDest = ( u32* ) BG_GFX;
   u32 iRow = 0;

   /* While we have more rows to draw... */
   while ( iRow < NDS_PIXBUF_HEIGHT ) {
      /* Copy the pixel data from the pixel buffer into the main background */
      //quadcopy( pSource, pDest, NDS_PIXBUF_WIDTH / 4 );
      //memcpy( pSource, pDest, NDS_PIXBUF_WIDTH );
      swiFastCopy( pSource, pDest, ( ( COPY_MODE_WORD | COPY_MODE_COPY ) << 24 ) + ( NDS_PIXBUF_WIDTH >> 2 ) );

      /* Point to the next row */
      pSource+= NDS_PIXBUF_WIDTH;
      pDest+= NDS_BG_WIDTH;
      iRow++;
   }
}

/* VL_Startup:
 * Initializes the video subsystem.
*/
void VL_Startup( void ) {
   /* Allocates a 320x200 pixel buffer for wolf3d to write to,
    * if it fails a warning is printed and the system halted.
   */
   if ( ( gfxbuf = ( byte* ) malloc( NDS_PIXBUF_WIDTH * NDS_PIXBUF_HEIGHT ) ) == NULL ) {
      printf( "VL_Startup: Failed to allocate pixel buffer\n" );
      printf( "Hanging here.\n" );

      while ( 1 ) swiWaitForVBlank( );
   }

   /* AHA! I forgot to set these! */
   vwidth = 320;
   vheight = 200;
}

/* VL_Shutdown:
 * Shuts down the video subsystem.
*/
void VL_Shutdown( void ) {
   /* If the pixel buffer was allocated, free it now */
   if ( gfxbuf )
      free( gfxbuf );
}

/* VL_SetPalette:
 * Sets an updated palette.
 *
 * pPalette   : Pointer to the 8 bit RGB palette
*/
void VL_SetPalette( const byte* pPalette ) {
   u32 i = 0;
   u32 r = 0;
   u32 g = 0;
   u32 b = 0;

   /* Wait until vblank before modifying the palette */
   swiWaitForVBlank( );

   /* For every palette entry... */
   for ( ; i < 256; i++, pPalette+= 3 ) {
      /* Shift each colour 3 bits to the right.
       * This divides them by 8 so they'll fit in
       * RGB555 format.
      */
      r = ( ( pPalette[ 0 ] + 4 < 256 ) ? pPalette[ 0 ] + 4 : 256 ) >> 3;
      g = ( ( pPalette[ 1 ] + 4 < 256 ) ? pPalette[ 1 ] + 4 : 256 ) >> 3;
      b = ( ( pPalette[ 2 ] + 4 < 256 ) ? pPalette[ 2 ] + 4 : 256 ) >> 3;

      r = r + ( r ^ 1 );
      g = g + ( g ^ 1 );
      b = b + ( b ^ 1 );

      /* Clamp colour values */
      if ( r > 31 ) r = 31;
      if ( g > 31 ) g = 31;
      if ( b > 31 ) b = 31;

      /* Set the palette entry */
      BG_PALETTE[ i ] = RGB15( r, g, b ) | ( 1 << 15 );
   }
}

/* VL_GetPalette:
 * Copies the current palette into pPalette.
 *
 * pPalette:   Pointer to receive RGB888 colour data
*/
void VL_GetPalette( byte* pPalette ) {
   u32 i = 0;
   u32 r = 0;
   u32 g = 0;
   u32 b = 0;

   /* For each palette entry... */
   for ( ; i < 256; i++, pPalette+= 3 ) {
      /* Use a macro to convert from RGB555 to RGB888 */
      RGB555TO888( BG_PALETTE[ i ], r, g, b );

      /* Clamp colour values */
      if ( r > 255 ) r = 255;
      if ( g > 255 ) g = 255;
      if ( b > 255 ) b = 255;

      /* Set palette */
      pPalette[ 0 ] = r;
      pPalette[ 1 ] = g;
      pPalette[ 2 ] = b;
   }
}

/* INL_Update:
 * TODO:
 * What is this supposed to do?
 * My guess: Updates input?
*/
void INL_Update( void ) {
}

/* IN_GetMouseDelta:
 * TODO:
 * What is this supposed to do?
 * My guess: Get the relative position from the last mouse move?
*/
void IN_GetMouseDelta( int* pX, int* pY ) {
   if ( pX ) *pX = 0;
   if ( pY ) *pY = 0;
}

/* IN_MouseButtons:
 * Returns a bitmask of the mouse button state?
 *
 * Returns: For NDS - always 0
*/
byte IN_MouseButtons( void ) {
   return 0;
}

/* Quit:
 * Supposed to quit with an error message but instead
 * this one prints the error then loops forever.
 *
 * pszError:   Error string
*/
void Quit( char* pszError ) {
#ifdef ROMDISKFS
   fs_romdisk_unmount( "/" );
#endif

   printf( "Error: %s\n", pszError );
   printf( "Hanging here.\n" );

   while ( 1 ) swiWaitForVBlank( );
}


Note: It gets much further than that on hardware, plays the demo for a while but crashes a few seconds into it.
On the bright side its more than fullspeed :)