nitro-engine/source/NEFAT.c
Antonio Niño Díaz 82171bbf69 chore: Simplify copyright years in notices
Instead of listing every individual year, keep only the first and last
years.
2024-03-09 01:42:29 +00:00

209 lines
5.2 KiB
C

// SPDX-License-Identifier: MIT
//
// Copyright (c) 2008-2022 Antonio Niño Díaz
//
// This file is part of Nitro Engine
#include "NEMain.h"
/// @file NEFAT.c
char *NE_FATLoadData(const char *filename)
{
FILE *f = fopen(filename, "rb");
if (f == NULL)
{
NE_DebugPrint("%s could't be opened", filename);
return NULL;
}
if (fseek(f, 0, SEEK_END) != 0)
{
NE_DebugPrint("Failed to fseek: %s", filename);
fclose(f);
return NULL;
}
size_t size = ftell(f);
rewind(f);
char *buffer = malloc(size);
if (buffer == NULL)
{
NE_DebugPrint("Not enought memory to load %s", filename);
fclose(f);
return NULL;
}
if (fread(buffer, 1, size, f) != size)
{
NE_DebugPrint("Failed to read data of %s", filename);
fclose(f);
return NULL;
}
fclose(f);
return buffer;
}
size_t NE_FATFileSize(const char *filename)
{
FILE *f = fopen(filename, "rb");
if (f == NULL)
{
NE_DebugPrint("%s could't be opened", filename);
return -1;
}
if (fseek(f, 0, SEEK_END) != 0)
{
NE_DebugPrint("Failed to fseek: %s", filename);
fclose(f);
return -1;
}
size_t size = ftell(f);
fclose(f);
return size;
}
static void NE_write16(u16 *address, u16 value)
{
u8 *first = (u8 *)address;
u8 *second = first + 1;
*first = value & 0xff;
*second = value >> 8;
}
static void NE_write32(u32 *address, u32 value)
{
u8 *first = (u8 *) address;
u8 *second = first + 1;
u8 *third = first + 2;
u8 *fourth = first + 3;
*first = value & 0xff;
*second = (value >> 8) & 0xff;
*third = (value >> 16) & 0xff;
*fourth = (value >> 24) & 0xff;
}
int NE_ScreenshotBMP(const char *filename)
{
FILE *f = fopen(filename, "wb");
if (f == NULL)
{
NE_DebugPrint("%s could't be opened", filename);
return 0;
}
NE_SpecialEffectPause(true);
// In normal 3D mode we need to capture the composited (3D+2D output)
// and save it to VRAM. In dual 3D mode it already is in VRAM.
if (NE_CurrentExecutionMode() == NE_ModeSingle3D)
{
// TODO: VRAM_D needs to be saved somewhere and then restored!
vramSetBankD(VRAM_D_LCD);
REG_DISPCAPCNT = DCAP_BANK(DCAP_BANK_VRAM_D)
| DCAP_SIZE(DCAP_SIZE_256x192)
| DCAP_MODE(DCAP_MODE_A)
| DCAP_SRC_A(DCAP_SRC_A_COMPOSITED)
| DCAP_ENABLE;
while (REG_DISPCAPCNT & DCAP_ENABLE);
}
int ysize = 0;
if (NE_CurrentExecutionMode() == NE_ModeSingle3D)
ysize = 192;
else
ysize = 384;
u8 *temp = malloc(256 * ysize * 3
+ sizeof(NE_BMPInfoHeader)
+ sizeof(NE_BMPHeader));
NE_BMPHeader *header = (NE_BMPHeader *) temp;
NE_BMPInfoHeader *infoheader =
(NE_BMPInfoHeader *)(temp + sizeof(NE_BMPHeader));
NE_write16(&header->type, 0x4D42);
NE_write32(&header->size, 256 * ysize * 3 + sizeof(NE_BMPInfoHeader)
+ sizeof(NE_BMPHeader));
NE_write32(&header->offset,
sizeof(NE_BMPInfoHeader) + sizeof(NE_BMPHeader));
NE_write16(&header->reserved1, 0);
NE_write16(&header->reserved2, 0);
NE_write16(&infoheader->bits, 24);
NE_write32(&infoheader->size, sizeof(NE_BMPInfoHeader));
NE_write32(&infoheader->compression, 0);
NE_write32(&infoheader->width, 256);
NE_write32(&infoheader->height, ysize);
NE_write16(&infoheader->planes, 1);
NE_write32(&infoheader->imagesize, 256 * ysize * 3);
NE_write32(&infoheader->xresolution, 0);
NE_write32(&infoheader->yresolution, 0);
NE_write32(&infoheader->importantcolors, 0);
NE_write32(&infoheader->ncolors, 0);
// Allow CPU to access VRAM
uint32_t vramTemp = 0;
if (NE_CurrentExecutionMode() != NE_ModeSingle3D)
{
vramTemp = vramSetPrimaryBanks(VRAM_A_LCD, VRAM_B_LCD,
VRAM_C_LCD, VRAM_D_LCD);
}
for (int y = 0; y < ysize; y++)
{
for (int x = 0; x < 256; x++)
{
u16 color = 0;
if (NE_CurrentExecutionMode() == NE_ModeSingle3D)
{
color = VRAM_D[256 * 192 - (y + 1) * 256 + x];
}
else
{
if (y > 191)
color = VRAM_C[256 * 192 - (y - 192 + 1) * 256 + x];
else
color = VRAM_D[256 * 192 - (y + 1) * 256 + x];
}
u8 b = (color & 31) << 3;
u8 g = ((color >> 5) & 31) << 3;
u8 r = ((color >> 10) & 31) << 3;
int index = ((y * 256) + x) * 3
+ sizeof(NE_BMPInfoHeader)
+ sizeof(NE_BMPHeader);
temp[index + 0] = r;
temp[index + 1] = g;
temp[index + 2] = b;
}
}
if (NE_CurrentExecutionMode() != NE_ModeSingle3D)
vramRestorePrimaryBanks(vramTemp);
fwrite(temp, 1, 256 * ysize * 3 + sizeof(NE_BMPInfoHeader)
+ sizeof(NE_BMPHeader), f);
fclose(f);
free(temp);
// TODO: Restore previous value, not just unpause
NE_SpecialEffectPause(false);
return 1;
}