static void VBlankIntr(void) { // Reflect virtual screen to VRAM DC_FlushRange( gTopScreen , sizeof( gTopScreen ) ); DC_FlushRange( gBottomScreen , sizeof( gBottomScreen ) ); GX_LoadBG0Scr( gTopScreen , 0 , sizeof( gTopScreen ) ); GXS_LoadBG0Scr( gBottomScreen , 0 , sizeof( gBottomScreen ) ); // Set IRQ check flag OS_SetIrqCheckFlag( OS_IE_V_BLANK ); }
void TextButton::init_vram( const void* source, u16*& vram_dest ) { vram_dest = oamAllocateGfx( this->get_oam(), this->sprite_size, SpriteColorFormat_Bmp ); DC_FlushRange( source, SPRITE_SIZE_PIXELS(this->sprite_size)*2 ); dmaCopy( source, vram_dest, SPRITE_SIZE_PIXELS(this->sprite_size)*2 ); set_16bpp_sprite_opague( vram_dest, SPRITE_SIZE_PIXELS(this->sprite_size)*2 ); }
// Returns index of passed paletteAsset in video memory. DMA copies it if needed uint8 assets::getPalette(paletteAsset *pal) { // Don't do anything if passed NULL if (!pal) return 0; // Return its index if it's already loaded if (pal->vmLoaded) return pal->index; // If it's not in main memory for some reason, load it if (!pal->mmLoaded) loadPalette(pal); // Keep track of which index a palette can be loaded into static int curIndex = 0; // TODO: add support for 256 color palettes static const int numColors = 16; DC_FlushRange(pal->data, pal->length); dmaCopyHalfWordsAsynch(3, pal->data, &SPRITE_PALETTE[curIndex * numColors], pal->length); // Update the paletteAsset's information pal->vmLoaded = true; pal->index = curIndex; //iprintf("pal vmLoaded -> %d\n", curIndex); // Update the index for the next call curIndex++; // return index return curIndex - 1; }
// returns the offset for the gfxAsset in video memory. DMA copies if needed uint16 *assets::getGfx(gfxAsset *gfx) { // Don't do anything if passed a NULL pointer if (!gfx) return 0; // If it's already loaded, just return its offset if (gfx->vmLoaded) return gfx->offset; // If the gfx isn't in main memory (which it should be), run loadGfx() if (!gfx->mmLoaded) loadGfx(gfx); // It would appear that the gfx is in main memory, but video memory. // So load it up! // Allocate video memory for the gfx uint16 *mem = oamAllocateGfx(oam, gfx->size, SpriteColorFormat_16Color); gfx->offset = mem; gfx->vmLoaded = true; // Start copying asynchronously uint16 length = gfx->length; DC_FlushRange(gfx->data, length); dmaCopyHalfWordsAsynch(3, gfx->data, mem, length); //iprintf("gfx vmLoaded -> %x\n", (unsigned int) gfx->offset); return mem; }
void CGbaLoader::LoadBorder(void) { videoSetMode(MODE_5_2D | DISPLAY_BG3_ACTIVE); videoSetModeSub(MODE_5_2D | DISPLAY_BG3_ACTIVE); vramSetMainBanks(VRAM_A_MAIN_BG_0x06000000, VRAM_B_MAIN_BG_0x06020000, VRAM_C_SUB_BG_0x06200000, VRAM_D_LCD); // for the main screen REG_BG3CNT = BG_BMP16_256x256 | BG_BMP_BASE(0) | BG_WRAP_OFF; REG_BG3PA = 1 << 8; //scale x REG_BG3PB = 0; //rotation x REG_BG3PC = 0; //rotation y REG_BG3PD = 1 << 8; //scale y REG_BG3X = 0; //translation x REG_BG3Y = 0; //translation y memset((void*)BG_BMP_RAM(0),0,0x18000); memset((void*)BG_BMP_RAM(8),0,0x18000); cBMP15 frameBMP=createBMP15FromFile(SFN_GBAFRAME); if(frameBMP.valid()&&frameBMP.width()==SCREEN_WIDTH&&frameBMP.height()==SCREEN_HEIGHT) { DC_FlushRange(frameBMP.buffer(),SCREEN_WIDTH*SCREEN_HEIGHT*2); dmaCopy(frameBMP.buffer(),(void*)BG_BMP_RAM(0),SCREEN_WIDTH*SCREEN_HEIGHT*2); dmaCopy(frameBMP.buffer(),(void*)BG_BMP_RAM(8),SCREEN_WIDTH*SCREEN_HEIGHT*2); } }
void gamestate::initLandscape() { // Sets up the palette landscape1.Palette[BLACK] = BLACK_15BIT; landscape1.Palette[RED] = RED_15BIT; landscape1.Palette[GREEN] = GREEN_15BIT; landscape1.Palette[BLUE] = BLUE_15BIT; landscape1.Palette[YELLOW] = YELLOW_15BIT; landscape1.Palette[TURQUIS] = TURQUIS_15BIT; landscape1.Palette[PURPLE] = PURPLE_15BIT; landscape1.Palette[WHITE] = WHITE_15BIT; landscape1.Palette[ORANGE] = ORANGE_15BIT; landscape1.Palette[MAGENTA] = MAGENTA_15BIT; landscape1.Palette[SALMON] = SALMON_15BIT; landscape1.Palette[DIRT] = DIRT_15BIT; landscape1.Palette[DARKBG] = DARKBG_15BIT; // Gets the DS ready to write to VRAM DC_FlushRange(landscape1.Palette, BG_PAL_LEN); // Writes Palette to VRAM dmaCopy(landscape1.Palette, BG_PALETTE, BG_PAL_LEN); landscape1.colorI = DIRT; landscape1.backgroundColorI = DARKBG; // makes all pixels of the background blue landscape1.fill(landscape1.backgroundColorI); landscape1.initCosLandscape(); //Calculates heights for a Landscape landscape1.fillLandscape(); // Sets the landscape based on heights object::landscape1 = &landscape1; }
static inline bool decompress(memchunk_t* pChunk, FILE* f, size_t compSize) { word_t compType = read32(f); word_t decompSize = compType >> 8; compType &= 0xF0; // Alloc first the uncompressed buffer in order to avoid heap fragmentation memchunk_t chunk = MemChunk_Alloc(decompSize); if (!chunk) return false; if (compType == 0) // Shortcut for uncompressed { if (decompSize != (compSize - 4)) { MemChunk_Free(chunk); return false; } fread(chunk, 1, decompSize, f); DC_FlushRange(chunk, decompSize); *pChunk = chunk; return true; } void* compBuf = malloc(compSize); if (!compBuf) { MemChunk_Free(chunk); return false; } bool bSuccess = true; fseek(f, -4, SEEK_CUR); fread(compBuf, 1, compSize, f); decompressAuto(compBuf, chunk, false); free(compBuf); if (bSuccess) { DC_FlushRange(chunk, decompSize); *pChunk = chunk; return true; } MemChunk_Free(chunk); return false; }
static bool LoadNDS(data_t* pData, const char* fname, const u32 Offset, const u32 Size) { FILE* f = fopen(fname, "rb"); if (!f) return false; fseek(f, Offset, SEEK_SET); pData->size = Size; pData->data = malloc(Size); fread(pData->data, 1, Size, f); fclose(f); DC_FlushRange(pData->data, Size); return true; }
static bool LoadFile(data_t* pData, const char* fname) { FILE* f = fopen(fname, "rb"); if (!f) return false; fseek(f, 0, SEEK_END); pData->size = ftell(f); rewind(f); pData->data = malloc(pData->size); fread(pData->data, 1, pData->size, f); fclose(f); DC_FlushRange(pData->data, pData->size); return true; }
static int NDS_UpdateWindowFramebuffer(_THIS, SDL_Window * window, SDL_Rect * rects, int numrects) { struct NDS_WindowData *wdata = window->driverdata; /* Copy everything. TODO: use rects/numrects. */ DC_FlushRange(wdata->pixels, wdata->pixels_length); swiWaitForVBlank(); dmaCopy(wdata->main.pixels, wdata->main.vram_pixels, wdata->main.length); dmaCopy(wdata->sub.pixels, wdata->sub.vram_pixels, wdata->sub.length); return 0; }
static void flush_frame(void) { uint8_t *fill_to = frame_base + FRAME_SIZE; while (wrptr < fill_to) *(wrptr++) = lastsample; DC_FlushRange(frame_base, FRAME_SIZE); frame_cycle_base += FRAME_CYCLES; frame_cycle = 0; flush_event->at_cycle = frame_cycle_base + FRAME_CYCLES; event_queue(&MACHINE_EVENT_LIST, flush_event); writing_buf ^= 1; frame_base = buf + (writing_buf * FRAME_SIZE); wrptr = frame_base; /* wait here */ if ((REG_IPC_SYNC & 1) == writing_buf) { swiIntrWait(1, IRQ_IPC_SYNC); } }
static void NDS_HW_Update() { /* TODO should be called md_bpm/2.5 times per second? */ md_player(); int i; DC_FlushRange(ipc, sizeof(*ipc)); for(i = 0; i < NDS_HW_MAXVOICES; i++) { NDS_HW_VOICE* v = ipc->voices + i; if(v->changes != 0) { MikMod9_SendCommand( (NDS_HW_CMD_VOICE_UPDATE << 28) | (v->changes << 8) | i); v->changes = 0; } } }
void gamestate::battleAction() { // applies Gravity to all objects (moves them) for(u8 i = 0; i < players_count; i += 1) { players[i].applyGravity(); } bombs[0].applyGravity(); //landscape1.dropLandscape(); swiWaitForVBlank(); // Wait for a good time to put stuff in OAM // Put objects in OAM for(u8 i = 0; i < players_count; i += 1) { players[i].updateOAM(); } bombs[0].updateOAM(); oamUpdate(&oamMain); // Updates the Landscape and Background DC_FlushRange(landscape1.Bitmap, BG_BITMAP_LEN); dmaCopy(landscape1.Bitmap, bgGetGfxPtr(bg[2]), BG_BITMAP_LEN); }
//--------------------------------------------------------------------------------- bool sdio_WriteSectors(sec_t sector, sec_t numSectors,const void* buffer) { //--------------------------------------------------------------------------------- FifoMessage msg; DC_FlushRange(buffer,numSectors * 512); msg.type = SDMMC_SD_WRITE_SECTORS; msg.sdParams.startsector = sector; msg.sdParams.numsectors = numSectors; msg.sdParams.buffer = (void*)buffer; fifoSendDatamsg(FIFO_SDMMC, sizeof(msg), (u8*)&msg); fifoWaitValue32(FIFO_SDMMC); int result = fifoGetValue32(FIFO_SDMMC); return result == 0; }
void Util_SetupStrideFixAffine(BG23AffineInfo* pAffineInfo, int srcStride, int dstStride, int xOffset, int yOffset, int xScale, int yScale) { int startoffset = -yOffset * srcStride; int x = startoffset & 0xFF; int y = startoffset >> 8; int realy = 128;//0; //setup affine shit for(int i = 0; i < 192; i++) { pAffineInfo[i].BG2PA = xScale; pAffineInfo[i].BG2PB = 0; pAffineInfo[i].BG2PC = 0; pAffineInfo[i].BG2PD = 256; pAffineInfo[i].BG3PA = xScale; pAffineInfo[i].BG3PB = 0; pAffineInfo[i].BG3PC = 0; pAffineInfo[i].BG3PD = 256; pAffineInfo[i].BG2X = x * 256 - xOffset * 256 + 128; pAffineInfo[i].BG2Y = y * 256; if(dstStride - x < srcStride) { pAffineInfo[i].BG3X = (x - dstStride) * 256 - xOffset * 256 + 128; pAffineInfo[i].BG3Y = (y + 1) * 256; } else { pAffineInfo[i].BG3X = x * 256 - xOffset * 256 + 128; pAffineInfo[i].BG3Y = y * 256; } //some lines need to be repeated if((realy & 0xFF) + yScale >= dstStride) { x += srcStride; if(x >= dstStride) { x -= dstStride; y++; } } realy += yScale; } DC_FlushRange(pAffineInfo, sizeof(BG23AffineInfo) * 192); }
void * bufferFile(const char * file, int * sz) { if (!hArc) return NULL; farfile_t hFile = FAR_GetFile(hArc, file); if (!hFile) return NULL; size_t size; if(sz) *sz = FAR_FileGetSize(hFile); void* mem = malloc(size = FAR_FileGetSize(hFile)); if (!mem) { FAR_FileClose(hFile); return NULL; } FAR_FileRead(hFile, mem, size); FAR_FileClose(hFile); DC_FlushRange(mem, size); return mem; }
static BOOL NDS_SW_PlayStart(void) { if(VC_PlayStart()) return 1; Player_SetPosition(0); ipc->prevTimer = 0; ipc->writeCursor = 0; ipc->readCursor = 0; int written = VC_WriteBytes(ipc->buffer, ipc->bufferSize); unsignedtosigned(ipc->buffer, written); DC_FlushRange(ipc, sizeof(*ipc)); MikMod9_SendCommand(NDS_SW_CMD_START << 28); return 0; }
static SWORD NDS_HW_SampleLoad(struct SAMPLOAD* sload, int type) { ASSERT(sload != NULL); SAMPLE *s = sload->sample; int handle; /* Find empty slot to put sample address in */ for(handle = 0; handle < NDS_HW_MAXSAMPLES; handle++) { if(ipc->samples[handle] == 0) { break; } } if(handle == MAXSAMPLEHANDLES) { _mm_errno = MMERR_OUT_OF_HANDLES; return -1; } /* Reality check for loop settings */ if (s->loopend > s->length) s->loopend = s->length; if (s->loopstart >= s->loopend) s->flags &= ~SF_LOOP; /* TODO difference between 8 and 16 bits? */ SL_SampleSigned(sload); ipc->samples[handle] = _mm_malloc(s->length * ((s->flags & SF_16BITS) ? 2 : 1)); if(ipc->samples[handle] == NULL) { _mm_errno = MMERR_SAMPLE_TOO_BIG; return -1; } /* read sample into buffer */ if (SL_Load(ipc->samples[handle], sload, s->length)) return -1; DC_FlushRange(ipc->samples[handle], s->length * ((s->flags & SF_16BITS) ? 2 : 1)); return handle; }
//--------------------------------------------------------------------------------- bool sdio_ReadSectors(sec_t sector, sec_t numSectors,void* buffer) { //--------------------------------------------------------------------------------- if (!REG_DSIMODE) return false; FifoMessage msg; DC_FlushRange(buffer,numSectors * 512); msg.type = SDMMC_SD_READ_SECTORS; msg.sdParams.startsector = sector; msg.sdParams.numsectors = numSectors; msg.sdParams.buffer = buffer; fifoSendDatamsg(FIFO_SDMMC, sizeof(msg), (u8*)&msg); while(!fifoCheckValue32(FIFO_SDMMC)); int result = fifoGetValue32(FIFO_SDMMC); return result == 0; }
//--------------------------------------------------------------------------------- void oamInit(OamState *oam, SpriteMapping mapping, bool extPalette) { //--------------------------------------------------------------------------------- int i; int extPaletteFlag = extPalette ? DISPLAY_SPR_EXT_PALETTE : 0; oam->gfxOffsetStep = (mapping & 3) + 5; oam->spriteMapping = mapping; dmaFillWords(0, oam->oamMemory, sizeof(OamMemory)); for(i = 0; i < 128; i++) { oam->oamMemory[i].isHidden = true; } for(i = 0; i < 32; i++) { oam->oamRotationMemory[i].hdx = (1<<8); oam->oamRotationMemory[i].vdy = (1<<8); } swiWaitForVBlank(); DC_FlushRange(oam->oamMemory, sizeof(OamMemory)); if(oam == &oamMain) { dmaCopy(oam->oamMemory, OAM, sizeof(OamMemory)); REG_DISPCNT &= ~DISPLAY_SPRITE_ATTR_MASK; REG_DISPCNT |= DISPLAY_SPR_ACTIVE | (mapping & 0xffffff0) | extPaletteFlag; } else { dmaCopy(oam->oamMemory, OAM_SUB, sizeof(OamMemory)); REG_DISPCNT_SUB &= ~DISPLAY_SPRITE_ATTR_MASK; REG_DISPCNT_SUB |= DISPLAY_SPR_ACTIVE | (mapping & 0xffffff0) | extPaletteFlag; } oamAllocReset(oam); }
static void NDS_SW_Update(void) { DC_InvalidateRange(&ipc->readCursor, sizeof(ipc->readCursor)); while(ipc->readCursor != ipc->writeCursor) { int todo = ipc->readCursor - ipc->writeCursor; if(todo < 0) todo = ipc->bufferSize - ipc->writeCursor; int written = VC_WriteBytes(ipc->buffer + ipc->writeCursor, todo); unsignedtosigned(ipc->buffer + ipc->writeCursor, written); int newCursor = ipc->writeCursor + written; if(ipc->writeCursor >= ipc->bufferSize) newCursor -= ipc->bufferSize; ipc->writeCursor = newCursor; } DC_FlushRange(&ipc->writeCursor, sizeof(ipc->writeCursor)); // we send this afterwards to give arm7 as much time as possible // to update MikMod9_SendCommand(NDS_SW_CMD_UPDATE << 28); }
//--------------------------------------------------------------------------------- static void playSoundBlock(TransferSound *snd) { //--------------------------------------------------------------------------------- DC_FlushRange( snd, sizeof(TransferSound) ); IPC->soundData = snd; }
void TextButton::update_vram(const void* source, u16* vram_dest) { DC_FlushRange( source, SPRITE_SIZE_PIXELS(this->sprite_size)*2 ); dmaCopy( source, vram_dest, SPRITE_SIZE_PIXELS(this->sprite_size)*2 ); set_16bpp_sprite_opague( vram_dest, SPRITE_SIZE_PIXELS(this->sprite_size)*2 ); }
//copy our sprite to object attribute memory void updateOAM(void) { DC_FlushRange(sprites,128*sizeof(SpriteEntry)); dmaCopy(sprites, OAM, 128 * sizeof(SpriteEntry)); }
void mode__intro__credits___init(void) { // initialize main screen videoSetMode(MODE_5_2D); // map main screen background fourth (128k) region to vram bank A vramSetBankA(VRAM_A_MAIN_BG_0x06060000); // set the secondary/sub screen for text and a background videoSetModeSub(MODE_5_2D); // map sub screen background (only? 1/4?) to vram bank C vramSetBankC(VRAM_C_SUB_BG); // FRAK, may need to reimplement this with mcp_bg_init... // XXX: time will tell if this flickers consoleInit(&bottom_screen, 0, BgType_Text4bpp, BgSize_T_256x256, 31, 0, false, true); // set printf sink consoleSelect(&bottom_screen); // set console background layer to top priority bgSetPriority(bottom_screen.bgId, 0); // note: this must be done _after_ consoleInit (as that resets it) // and _after_ loading our 8bit indexed bitmap reloads it // set to black to allow renderer to really control BG_PALETTE_SUB[255] = RGB15(0, 0, 0); // unfaded mcp_set_blend(MCP_MAIN_SCREEN, MCP_MAX_BLEND_LEVEL); mcp_set_blend(MCP_SUB_SCREEN, MCP_MAX_BLEND_LEVEL); // fade the mainscreen background to/from black, layer 3 REG_BLDCNT = BLEND_FADE_BLACK | BLEND_SRC_BG3; // fade the lava background to/from black, layer 3 REG_BLDCNT_SUB = BLEND_FADE_BLACK | BLEND_SRC_BG3; // init subscreen layer/background 3 // the mapbase offset of 24 here means 24*16k which means utilizing // the 4th of the possible main background memory regions that vram // bank A can be mapped to. I.e. above we mapped to the 4th. Had // we mapped to the 1st, we would have used offset 0. // note: vram bank A is 128k, i.e. 8 * 16k. // note: *16k is because of bitmap type, else would be *2k // bg3 = bgInit(3, BgType_Bmp16, BgSize_B16_256x256, 24, 0); bg3 = mcp_bg_init(MCP_MAIN_SCREEN, 3, MCP_BG_HIDE, BgType_Bmp16, BgSize_B16_256x256, 24, 0); // its initial priority, lowest (to emphasize lack of other enabled layers) // priorities 0..3, 0 highest priority bgSetPriority(bg3, 3); // bgHide(bg3); // load main splash screen into screen/background memory (bgs3) // note: if I wanted to do this quickly/perfectly/doublebufferred somehow // I'm not sure if I'd need to tweak the bgInitSub offset or pointer // here or some such. As it is, the fade to black ensures no tear // as this new image gets loaded into display memory. decompress(guitar_zyx_splash_creditsBitmap, (u16*)bgGetGfxPtr(bg3), LZ77Vram); bgShow(bg3); // note: using offset=4, because 4 will be 64k offset, where 31 above is 62k // (thus above using only 2k? seems plausible with tiles for console text chars // NOTE: if this flickers, could try 2 instead of 3 bgs3 = mcp_bg_init(MCP_SUB_SCREEN, 3, MCP_BG_HIDE, BgType_Bmp8, BgSize_B8_256x256, 4, 0); // its initial priority, lowest (to emphasize lack of other enabled layers) // priorities 0..3, 0 highest priority bgSetPriority(bgs3, 2); // bgHide(bgs3); // as per libnds doc on dma DC_FlushRange(dlavaBitmap, 256*256); dmaCopy(dlavaBitmap, bgGetGfxPtr(bgs3), 256*256); DC_FlushRange(dlavaPal, 256*2); dmaCopy(dlavaPal, BG_PALETTE_SUB, 256*2); bgShow(bgs3); BG_PALETTE_SUB[255] = RGB15(0, 0, 0); }
void updateOAM(void) { DC_FlushRange(d3dSprites, 128 * sizeof(SpriteEntry)); memcpy(OAM_SUB, d3dSprites, 128 * sizeof(SpriteEntry)); }
void mode__intro__main___init(void) { // ooh, ahh, earcandy mmEffectEx(&sounds[SFX_STARTUP]); // initialize main screen // edunote: had tried MODE_5_3D here, but after 3D was actually used, // it would interfere with the bitmap showing. I think I'm // effectively bghiding all layers in intermode init, but // maybe I'm not, or maybe there is another way to hide the 3D // layer. Probably I should figure out how to render 3D on // top of a bitmap successfully. Then the rest might follow. videoSetMode(MODE_5_2D); // map main screen background fourth (128k) region to vram bank A vramSetBankA(VRAM_A_MAIN_BG_0x06060000); // NOTE: current half educated assumption is that or-ing together // bg enabled layers here is nothing but effectively an // advanced call to bgShow, which is also a part of bgInit // NOTE2: after some time, I'm convinced of the above, and about // to write a function bg_init_hidden() videoSetModeSub(MODE_5_2D); // map sub screen background (only? 1/4?) to vram bank C vramSetBankC(VRAM_C_SUB_BG); mcp_console_init(&bottom_screen, MCP_SUB_SCREEN, 0, 1, 1, BgType_Text4bpp, BgSize_T_256x256, 31, 0); // set printf sink consoleSelect(&bottom_screen); // set console background layer to top priority bgSetPriority(bottom_screen.bgId, 0); // note: this must be done _after_ consoleInit (as that resets it) // and _after_ loading our 8bit indexed bitmap reloads it // set to black to allow renderer to really control BG_PALETTE_SUB[255] = RGB15(0, 0, 0); // show the console layer mcp_bg_show(MCP_SUB_SCREEN, 0); // default to fully faded (to black) mcp_set_blend(MCP_MAIN_SCREEN, MCP_MAX_BLEND_LEVEL); mcp_set_blend(MCP_SUB_SCREEN, MCP_MAX_BLEND_LEVEL); // fade the mainscreen background to/from black, layer 3 REG_BLDCNT = BLEND_FADE_BLACK | BLEND_SRC_BG3; // fade the lava background to/from black, layer 3 REG_BLDCNT_SUB = BLEND_FADE_BLACK | BLEND_SRC_BG2; // init subscreen layer/background 3 // the mapbase offset of 24 here means 24*16k which means utilizing // the 4th of the possible main background memory regions that vram // bank A can be mapped to. I.e. above we mapped to the 4th. Had // we mapped to the 1st, we would have used offset 0. // note: vram bank A is 128k, i.e. 8 * 16k. // note: *16k is because of bitmap type, else would be *2k // bg3 = bgInit(3, BgType_Bmp16, BgSize_B16_256x256, 24, 0); bg3 = mcp_bg_init(MCP_MAIN_SCREEN, 3, MCP_BG_HIDE, BgType_Bmp16, BgSize_B16_256x256, 24, 0); // its initial priority, lowest (to emphasize lack of other enabled layers) // note: priorities 0..3, 0 highest priority bgSetPriority(bg3, 3); // mcp_bg_init covers this // maybe this prevents flicker during decompress // bgHide(bg3); // load main splash screen into screen/background memory (bgs3) decompress(guitar_zyx_splash_mainBitmap, (u16*)bgGetGfxPtr(bg3), LZ77Vram); // maybe this prevents flicker during decompress mcp_bg_show(MCP_MAIN_SCREEN, 3); // note: using offset=4, because 4 will be 64k offset, where 31 above is 62k // (thus above using only 2k? seems plausible with tiles for console text chars // bgs2 = bgInitSub(2, BgType_Bmp8, BgSize_B8_256x256, 4, 0); bgs2 = mcp_bg_init(MCP_SUB_SCREEN, 2, MCP_BG_HIDE, BgType_Bmp8, BgSize_B8_256x256, 4, 0); // its initial priority, lowest (to emphasize lack of other enabled layers) // priorities 0..3, 0 highest priority bgSetPriority(bgs2, 2); // mcp_bg_init covers this // bgHide(bgs2); // note: as per libnds doc on dma, do the flush first DC_FlushRange(dlavaBitmap, 256*256); dmaCopy(dlavaBitmap, bgGetGfxPtr(bgs2), 256*256); DC_FlushRange(dlavaPal, 256*2); dmaCopy(dlavaPal, BG_PALETTE_SUB, 256*2); bgShow(bgs2); // reinitialize the text color BG_PALETTE_SUB[255] = RGB15(0, 0, 0); /* bad experiment, but probably will use later anyway) consoleInit(&bottom_screen_x, 3, BgType_ExRotation, BgSize_ER_256x256, 31, 1, false, false); // custom 8bpp font mcpfont.asciiOffset = 32; mcpfont.bpp = 8; mcpfont.convertSingleColor = false; mcpfont.gfx = (u16*)mcpfontTiles; mcpfont.numChars = 95; mcpfont.numColors = mcpfontPalLen / 2; mcpfont.pal = (u16*)mcpfontPal; consoleSetFont(&bottom_screen, &mcpfont); // set console background layer to top priority bgSetPriority(bottom_screen_x.bgId, 0); bgShow(bottom_screen_x.bgId); */ }