#52122 - cybereality - Sat Aug 27, 2005 12:05 am
I have just started wih NDS development, but I have read a good amount of what is on the web and the examples given with devkitPro. I started by going through Chris Double's tutorials and while I understand all the logic, I am having trouble with the VRAM allocations. I took Chris' demo to display a JPEG and edited it with my own images. Then I added an extra BG layer on the sub screen so I could display a large image over both screens. I did this by duplicating the image data in both main and sub BG buffers and offseting the Y value in hardware. That works fine, no problem. Now I want to add the console output on one screen (over the image) and it doesn't work. The main screen displays the image fine, the sub screen has a bunch of random ASCII characters on i but colored like the image should be. If I move the image around, I can tell it is writing the the correct VRAM, but the console text garbles it up. I need some help with this from someone who knows what they are talking about.
The lines I have a feeling are wrong are:
Basically, it seems that I am writing the sub image and the console output to the same VRAM bank. I tried a bunch of different things, but I am not all that experienced with low-level memory coding and I can't find any simple demos that do this. I have posted the code below, hopefully someone can make some sense out of it for me. I dont understand what (u16*)SCREEN_BASE_BLOCK_SUB(31) refers to (it sets the map buffer base for the consoleInit I know, but where is this coming from?). Also I couldn't find any info on BG_GFX or BG_GFX_SUB and what other constants could be used for these. If you can, please help me out. Thanks.
[/code]
The lines I have a feeling are wrong are:
Code: |
consoleInitDefault((u16*)SCREEN_BASE_BLOCK_SUB(31), (u16*)CHAR_BASE_BLOCK_SUB(0), 16); |
Code: |
BltImage(images[current_image], BG_GFX_SUB, 256, 256); |
Basically, it seems that I am writing the sub image and the console output to the same VRAM bank. I tried a bunch of different things, but I am not all that experienced with low-level memory coding and I can't find any simple demos that do this. I have posted the code below, hopefully someone can make some sense out of it for me. I dont understand what (u16*)SCREEN_BASE_BLOCK_SUB(31) refers to (it sets the map buffer base for the consoleInit I know, but where is this coming from?). Also I couldn't find any info on BG_GFX or BG_GFX_SUB and what other constants could be used for these. If you can, please help me out. Thanks.
Code: |
/*
mode5_scrolling ARM9 Code Chris Double (chris.double@double.co.nz) http://www.double.co.nz/nintendo_ds edits by: cybereality */ #include <nds.h> #include "nds/arm9/console.h" #include <stdlib.h> #include <string.h> #include "gba-jpeg.h" #include "gba-jpeg-decode.h" #include "gbfs.h" // Given the name of a file, look it up in the GBFS archive and use // the JPEG routines to return the width and height of the image. void GetImageSize(char* name, int* width, int* height) { WAIT_CR &= ~0x80; GBFS_FILE const* gbfs_file = find_first_gbfs_file((void*)0x08000000); const unsigned char* image = (const unsigned char*)gbfs_get_obj(gbfs_file, name, 0); JPEG_Decoder decoder; JPEG_Decoder_ReadHeaders(&decoder, &image); *width = decoder.frame.width; *height = decoder.frame.height; WAIT_CR |= 0x80; } // Decode the jpeg file with the given name to the VRAM location // specified. The height and width are the height and width of the // output bitmap. void BltImage(char* name, u16* vram, int output_width, int output_height) { WAIT_CR &= ~0x80; GBFS_FILE const* gbfs_file = find_first_gbfs_file((void*)0x08000000); uint8* image = (uint8*)gbfs_get_obj(gbfs_file, name, 0); JPEG_DecompressImage(image, vram, output_width, output_height); WAIT_CR |= 0x80; } static int scrolly = 0; static int scrollx = 0; static int scale_settings[] = { 1 << 4, 1 << 5, 1 << 6, 1 << 7, 1 << 8, 2 << 8, 3 << 8, 4 << 8, 5 << 8, 6 << 8, 7 << 8, 8 << 8, 9 << 8, 10 << 8 }; static int scale_count = sizeof(scale_settings) / sizeof(int); static int scale = 4; static char* images[] = { "shadowrun1.jpg", "shadowrun2.jpg", "shadowrun3.jpg", "shadowrun4.jpg" }; static int image_count = sizeof(images) / sizeof(char*); int current_image = 0; static int height = 0; static int width = 0; void on_irq() { if(IF & IRQ_VBLANK) { // Handle vertical blank interrupt // debug traces consoleClear(); consolePrintf("// cybereality\n\n"); consolePrintf("Width: %d\n", width); consolePrintf("Height: %d\n", height); consolePrintf("scrolly: %d\n", scrolly); consolePrintf("scrollx: %d\n", scrollx); // Tell the DS we handled the VBLANK interrupt VBLANK_INTR_WAIT_FLAGS |= IRQ_VBLANK; IF |= IRQ_VBLANK; } else { // Ignore all other interrupts IF = IF; } } void InitInterruptHandler() { IME = 0; IRQ_HANDLER = on_irq; IE = IRQ_VBLANK; IF = ~0; DISP_SR = DISP_VBLANK_IRQ; IME = 1; } int main(void) { powerON(POWER_ALL); // WAIT_CR=0xe800; // POWER_CR=0x30F; // Mode5: Backgrounds 0 and 1 are text. Background 2 and 3 are // extended rotation backgrounds. Background 0 can be used for 3D. videoSetMode(MODE_5_2D | DISPLAY_BG2_ACTIVE); vramSetBankA(VRAM_A_MAIN_BG_0x6000000); BG2_CR = BG_BMP16_256x256; // Set translations BG2_XDX = scale_settings[scale]; BG2_XDY = 0; BG2_YDX = 0; BG2_YDY = scale_settings[scale]; BG2_CY = 0; BG2_CX = 0; // top screen videoSetModeSub(MODE_5_2D | DISPLAY_BG0_ACTIVE | DISPLAY_BG3_ACTIVE); vramSetBankC(VRAM_C_SUB_BG_0x6200000); SUB_BG3_CR = BG_BMP16_256x256; // console text output on bg0 SUB_BG0_CR = BG_MAP_BASE(31); BG_PALETTE_SUB[255] = RGB15(31,31,31); consoleInitDefault((u16*)SCREEN_BASE_BLOCK_SUB(31), (u16*)CHAR_BASE_BLOCK_SUB(0), 16); // allocate memory for main banks //vramSetMainBanks(VRAM_A_MAIN_BG_0x6000000,VRAM_B_MAIN_BG_0x6020000,VRAM_C_SUB_BG_0x6200000,VRAM_D_LCD); // Set translations SUB_BG3_XDX = scale_settings[scale]; SUB_BG3_XDY = 0; SUB_BG3_YDX = 0; SUB_BG3_YDY = scale_settings[scale]; SUB_BG3_CY = (-260<<8); SUB_BG3_CX = 0; // Initialize and enable VBlank interrupt InitInterruptHandler(); // Initialiaze key handler keysInit(); // Wait for the vertical blank interrupt before decoding the image to // VRAM. This prevents seeing the image being drawn as its written to // memory. swiWaitForVBlank(); // draw image to main screen (bottom) BltImage(images[current_image], BG_GFX, 256, 256); // draw image to sub screen (top) // BltImage(images[current_image], BG_GFX_SUB, 256, 256); GetImageSize(images[current_image], &width, &height); while(1) { scanKeys(); swiWaitForVBlank(); if(keysHeld() & KEY_DOWN) { scrolly++; BG2_CY = (scrolly<<8); SUB_BG3_CY = (scrolly-260<<8); } if(keysHeld() & KEY_UP) { scrolly--; BG2_CY = (scrolly<<8); SUB_BG3_CY = (scrolly-260<<8); } if(keysHeld() & KEY_RIGHT) { scrollx++; BG2_CX = (scrollx<<8); SUB_BG3_CX = (scrollx<<8); } if(keysHeld() & KEY_LEFT) { scrollx--; BG2_CX = (scrollx<<8); SUB_BG3_CX = (scrollx<<8); } if(keysDown() & KEY_A) { scale++; if(scale >= scale_count) scale = scale_count - 1; BG2_XDX = scale_settings[scale]; BG2_YDY = scale_settings[scale]; SUB_BG3_XDX = scale_settings[scale]; SUB_BG3_YDY = scale_settings[scale]; } if(keysDown() & KEY_B) { scale--; if(scale <1) scale = 1; BG2_XDX = scale_settings[scale]; BG2_YDY = scale_settings[scale]; SUB_BG3_XDX = scale_settings[scale]; SUB_BG3_YDY = scale_settings[scale]; } if(keysDown() & KEY_SELECT) { current_image++; if(current_image >= image_count) current_image = 0; memset(BG_GFX, 0, 256*256*2); memset(BG_GFX_SUB, 0, 256*256*2); BltImage(images[current_image], BG_GFX, 256, 256); BltImage(images[current_image], BG_GFX_SUB, 256, 256); GetImageSize(images[current_image], &width, &height); } } return 0; } |