/* mode5_scrolling ARM9 Code Chris Double (chris.double@double.co.nz) http://www.double.co.nz/nintendo_ds */ #include #include "nds/arm9/console.h" #include #include #include #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[] = { "duddie.jpg", "pitcairn_leaf.jpg", "bell.jpg", "brave_bird.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(REG_IF & IRQ_VBLANK) { // Handle vertical blank interrupt printf("\x1b[2J"); printf("Width: %d\n", width); printf("Height: %d\n", height); printf("scrolly: %d\n", scrolly); printf("scrollx: %d\n", scrollx); VBLANK_INTR_WAIT_FLAGS |= IRQ_VBLANK; REG_IF |= IRQ_VBLANK; } else { // Ignore all other interrupts REG_IF = REG_IF; } } void InitInterruptHandler() { REG_IME = 0; IRQ_HANDLER = on_irq; REG_IE = IRQ_VBLANK; REG_IF = ~0; DISP_SR = DISP_VBLANK_IRQ; REG_IME = 1; } int main(void) { powerON(POWER_ALL); // 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; // Setup console screen to display information about the jpeg. videoSetModeSub(MODE_0_2D | DISPLAY_BG0_ACTIVE); vramSetBankC(VRAM_C_SUB_BG); 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); // Initialize and enable VBlank interrupt InitInterruptHandler(); lcdSwap(); // 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(); BltImage(images[current_image], BG_GFX, 256, 256); GetImageSize(images[current_image], &width, &height); while(1) { scanKeys(); swiWaitForVBlank(); if(keysHeld() & KEY_DOWN) { scrolly++; BG2_CY = (scrolly<<8); } if(keysHeld() & KEY_UP) { scrolly--; BG2_CY = (scrolly<<8); } if(keysHeld() & KEY_RIGHT) { scrollx++; BG2_CX = (scrollx<<8); } if(keysHeld() & KEY_LEFT) { scrollx--; BG2_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]; } if(keysDown() & KEY_B) { scale--; if(scale <1) scale = 1; BG2_XDX = scale_settings[scale]; BG2_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); BltImage(images[current_image], BG_GFX, 256, 256); GetImageSize(images[current_image], &width, &height); } } return 0; }