diff --git a/src/Block.c b/src/Block.c index 42d0983ff..c8c51b617 100644 --- a/src/Block.c +++ b/src/Block.c @@ -204,12 +204,12 @@ static void Block_CalcLightOffset(BlockID block) { int flags = 0xFF; Vec3 min = Blocks.MinBB[block], max = Blocks.MaxBB[block]; - if (min.x != 0) flags &= ~(1 << FACE_XMIN); - if (max.x != 1) flags &= ~(1 << FACE_XMAX); - if (min.z != 0) flags &= ~(1 << FACE_ZMIN); - if (max.z != 1) flags &= ~(1 << FACE_ZMAX); - if (min.y != 0) flags &= ~(1 << FACE_YMIN); - if (max.y != 1) flags &= ~(1 << FACE_YMAX); + if (min.x != 0) flags &= ~FACE_BIT_XMIN; + if (max.x != 1) flags &= ~FACE_BIT_XMAX; + if (min.z != 0) flags &= ~FACE_BIT_ZMIN; + if (max.z != 1) flags &= ~FACE_BIT_ZMAX; + if (min.y != 0) flags &= ~FACE_BIT_YMIN; + if (max.y != 1) flags &= ~FACE_BIT_YMAX; if ((min.y != 0 && max.y == 1) && Blocks.Draw[block] != DRAW_GAS) { flags &= ~(1 << LIGHT_FLAG_SHADES_FROM_BELOW); @@ -380,12 +380,12 @@ static void Block_CalcCulling(BlockID block, BlockID other) { occludedY = (bMin.x >= oMin.x && bMax.x <= oMax.x) && (bMin.z >= oMin.z && bMax.z <= oMax.z); occludedZ = (bMin.x >= oMin.x && bMax.x <= oMax.x) && (bMin.y >= oMin.y && bMax.y <= oMax.y); - f |= occludedX && oMax.x == 1.0f && bMin.x == 0.0f ? (1 << FACE_XMIN) : 0; - f |= occludedX && oMin.x == 0.0f && bMax.x == 1.0f ? (1 << FACE_XMAX) : 0; - f |= occludedZ && oMax.z == 1.0f && bMin.z == 0.0f ? (1 << FACE_ZMIN) : 0; - f |= occludedZ && oMin.z == 0.0f && bMax.z == 1.0f ? (1 << FACE_ZMAX) : 0; - f |= occludedY && (bothLiquid || (oMax.y == 1.0f && bMin.y == 0.0f)) ? (1 << FACE_YMIN) : 0; - f |= occludedY && (bothLiquid || (oMin.y == 0.0f && bMax.y == 1.0f)) ? (1 << FACE_YMAX) : 0; + f |= occludedX && oMax.x == 1.0f && bMin.x == 0.0f ? FACE_BIT_XMIN : 0; + f |= occludedX && oMin.x == 0.0f && bMax.x == 1.0f ? FACE_BIT_XMAX : 0; + f |= occludedZ && oMax.z == 1.0f && bMin.z == 0.0f ? FACE_BIT_ZMIN : 0; + f |= occludedZ && oMin.z == 0.0f && bMax.z == 1.0f ? FACE_BIT_ZMAX : 0; + f |= occludedY && (bothLiquid || (oMax.y == 1.0f && bMin.y == 0.0f)) ? FACE_BIT_YMIN : 0; + f |= occludedY && (bothLiquid || (oMin.y == 0.0f && bMax.y == 1.0f)) ? FACE_BIT_YMAX : 0; Blocks.Hidden[(block * BLOCK_COUNT) + other] = f; } diff --git a/src/Builder.c b/src/Builder.c index 85940ce1f..0629a5ce4 100644 --- a/src/Builder.c +++ b/src/Builder.c @@ -189,7 +189,7 @@ static void PrepareChunk(int x1, int y1, int z1) { if (Builder_Counts[index] == 0 || (x == 0 && (y < Builder_SidesLevel || (b >= BLOCK_WATER && b <= BLOCK_STILL_LAVA && y < Builder_EdgeLevel))) || - (x != 0 && (Blocks.Hidden[tileIdx + Builder_Chunk[cIndex - 1]] & (1 << FACE_XMIN)) != 0)) { + (x != 0 && (Blocks.Hidden[tileIdx + Builder_Chunk[cIndex - 1]] & FACE_BIT_XMIN) != 0)) { Builder_Counts[index] = 0; } else { Builder_Counts[index] = Builder_StretchZ(index, x, y, z, cIndex, b, FACE_XMIN); @@ -198,7 +198,7 @@ static void PrepareChunk(int x1, int y1, int z1) { index++; if (Builder_Counts[index] == 0 || (x == World.MaxX && (y < Builder_SidesLevel || (b >= BLOCK_WATER && b <= BLOCK_STILL_LAVA && y < Builder_EdgeLevel))) || - (x != World.MaxX && (Blocks.Hidden[tileIdx + Builder_Chunk[cIndex + 1]] & (1 << FACE_XMAX)) != 0)) { + (x != World.MaxX && (Blocks.Hidden[tileIdx + Builder_Chunk[cIndex + 1]] & FACE_BIT_XMAX) != 0)) { Builder_Counts[index] = 0; } else { Builder_Counts[index] = Builder_StretchZ(index, x, y, z, cIndex, b, FACE_XMAX); @@ -207,7 +207,7 @@ static void PrepareChunk(int x1, int y1, int z1) { index++; if (Builder_Counts[index] == 0 || (z == 0 && (y < Builder_SidesLevel || (b >= BLOCK_WATER && b <= BLOCK_STILL_LAVA && y < Builder_EdgeLevel))) || - (z != 0 && (Blocks.Hidden[tileIdx + Builder_Chunk[cIndex - EXTCHUNK_SIZE]] & (1 << FACE_ZMIN)) != 0)) { + (z != 0 && (Blocks.Hidden[tileIdx + Builder_Chunk[cIndex - EXTCHUNK_SIZE]] & FACE_BIT_ZMIN) != 0)) { Builder_Counts[index] = 0; } else { Builder_Counts[index] = Builder_StretchX(index, x, y, z, cIndex, b, FACE_ZMIN); @@ -216,7 +216,7 @@ static void PrepareChunk(int x1, int y1, int z1) { index++; if (Builder_Counts[index] == 0 || (z == World.MaxZ && (y < Builder_SidesLevel || (b >= BLOCK_WATER && b <= BLOCK_STILL_LAVA && y < Builder_EdgeLevel))) || - (z != World.MaxZ && (Blocks.Hidden[tileIdx + Builder_Chunk[cIndex + EXTCHUNK_SIZE]] & (1 << FACE_ZMAX)) != 0)) { + (z != World.MaxZ && (Blocks.Hidden[tileIdx + Builder_Chunk[cIndex + EXTCHUNK_SIZE]] & FACE_BIT_ZMAX) != 0)) { Builder_Counts[index] = 0; } else { Builder_Counts[index] = Builder_StretchX(index, x, y, z, cIndex, b, FACE_ZMAX); @@ -224,7 +224,7 @@ static void PrepareChunk(int x1, int y1, int z1) { index++; if (Builder_Counts[index] == 0 || y == 0 || - (Blocks.Hidden[tileIdx + Builder_Chunk[cIndex - EXTCHUNK_SIZE_2]] & (1 << FACE_YMIN)) != 0) { + (Blocks.Hidden[tileIdx + Builder_Chunk[cIndex - EXTCHUNK_SIZE_2]] & FACE_BIT_YMIN) != 0) { Builder_Counts[index] = 0; } else { Builder_Counts[index] = Builder_StretchX(index, x, y, z, cIndex, b, FACE_YMIN); @@ -232,7 +232,7 @@ static void PrepareChunk(int x1, int y1, int z1) { index++; if (Builder_Counts[index] == 0 || - (Blocks.Hidden[tileIdx + Builder_Chunk[cIndex + EXTCHUNK_SIZE_2]] & (1 << FACE_YMAX)) != 0) { + (Blocks.Hidden[tileIdx + Builder_Chunk[cIndex + EXTCHUNK_SIZE_2]] & FACE_BIT_YMAX) != 0) { Builder_Counts[index] = 0; } else if (b < BLOCK_WATER || b > BLOCK_STILL_LAVA) { Builder_Counts[index] = Builder_StretchX(index, x, y, z, cIndex, b, FACE_YMAX); diff --git a/src/Constants.h b/src/Constants.h index 5a9686341..5d0b18962 100644 --- a/src/Constants.h +++ b/src/Constants.h @@ -49,12 +49,12 @@ Copyright 2014-2023 ClassiCube | Licensed under BSD-3 #define GUI_MAX_CHATLINES 30 enum FACE_CONSTS { - FACE_XMIN = 0, /* Face X = 0 */ - FACE_XMAX = 1, /* Face X = 1 */ - FACE_ZMIN = 2, /* Face Z = 0 */ - FACE_ZMAX = 3, /* Face Z = 1 */ - FACE_YMIN = 4, /* Face Y = 0 */ - FACE_YMAX = 5, /* Face Y = 1 */ + FACE_XMIN = 0, FACE_BIT_XMIN = 1 << FACE_XMIN, /* Face X = 0 */ + FACE_XMAX = 1, FACE_BIT_XMAX = 1 << FACE_XMAX, /* Face X = 1 */ + FACE_ZMIN = 2, FACE_BIT_ZMIN = 1 << FACE_ZMIN, /* Face Z = 0 */ + FACE_ZMAX = 3, FACE_BIT_ZMAX = 1 << FACE_ZMAX, /* Face Z = 1 */ + FACE_YMIN = 4, FACE_BIT_YMIN = 1 << FACE_YMIN, /* Face Y = 0 */ + FACE_YMAX = 5, FACE_BIT_YMAX = 1 << FACE_YMAX, /* Face Y = 1 */ FACE_COUNT= 6 /* Number of faces on a cube */ }; diff --git a/src/Platform_Dreamcast.c b/src/Platform_Dreamcast.c index b2332a680..7db8b8270 100644 --- a/src/Platform_Dreamcast.c +++ b/src/Platform_Dreamcast.c @@ -107,6 +107,81 @@ void DateTime_CurrentLocal(struct DateTime* t) { } +/*########################################################################################################################* +*----------------------------------------------------VMU options file-----------------------------------------------------* +*#########################################################################################################################*/ +static volatile int vmu_write_FD = -10000; +static int VMUFile_Do(cc_file* file, int mode) { + void* data = NULL; + int fd, err = -1, len; + vmu_pkg_t pkg; + + errno = 0; + fd = fs_open("/vmu/a1/CCOPT.txt", O_RDONLY); + + // Try to extract stored data from the VMU + if (fd >= 0) { + len = fs_total(fd); + data = Mem_Alloc(len, 1, "VMU data"); + fs_read(fd, data, len); + + err = vmu_pkg_parse(data, &pkg); + fs_close(fd); + } + + // Copy VMU data into a RAM temp file + errno = 0; + fd = fs_open("/ram/ccopt", O_RDWR | O_CREAT | O_TRUNC); + if (fd < 0) return errno; + + if (err >= 0) { + fs_write(fd, pkg.data, pkg.data_len); + fs_seek(fd, 0, SEEK_SET); + } + Mem_Free(data); + + if (mode != O_RDONLY) vmu_write_FD = fd; + *file = fd; + return 0; +} + +static cc_result VMUFile_Close(cc_file file) { + void* data; + uint8* pkg_data; + int fd, err = -1, len, pkg_len; + vmu_pkg_t pkg = { 0 }; + vmu_write_FD = -10000; + + len = fs_total(file); + data = Mem_Alloc(len, 1, "VMU data"); + fs_seek(file, 0, SEEK_SET); + fs_read(file, data, len); + + fs_close(file); + fs_unlink("/ram/ccopt"); + + strcpy(pkg.desc_short, "CC options file"); + strcpy(pkg.desc_long, "ClassiCube config/settings"); + strcpy(pkg.app_id, "ClassiCube"); + pkg.eyecatch_type = VMUPKG_EC_NONE; + pkg.data_len = len; + pkg.data = data; + + err = vmu_pkg_build(&pkg, &pkg_data, &pkg_len); + if (err) { Mem_Free(data); return ERR_OUT_OF_MEMORY; } + + // Copy into VMU file + errno = 0; + fd = fs_open("/vmu/a1/CCOPT.txt", O_RDWR | O_CREAT | O_TRUNC); + if (fd < 0) return errno; + + fs_write(fd, pkg_data, pkg_len); + fs_close(fd); + free(pkg_data); + return 0; +} + + /*########################################################################################################################* *-----------------------------------------------------Directory/File------------------------------------------------------* *#########################################################################################################################*/ @@ -193,6 +268,11 @@ static cc_result File_Do(cc_file* file, const cc_string* path, int mode) { int err = res == -1 ? errno : 0; if (res == -1 && err == 0) err = ENOENT; + + // Read/Write VMU for options.txt, since that file is critical + if (err && Platform_ReadonlyFilesystem && String_CaselessEqualsConst(path, "options.txt")) { + return VMUFile_Do(file, mode); + } return err; } @@ -219,6 +299,9 @@ cc_result File_Write(cc_file file, const void* data, cc_uint32 count, cc_uint32* } cc_result File_Close(cc_file file) { + if (file == vmu_write_FD) + return VMUFile_Close(file); + int res = fs_close(file); return res == -1 ? errno : 0; } @@ -453,17 +536,17 @@ static void InitSDCard(void) { if (sd_blockdev_for_partition(0, &sd_dev, &partition_type)) { Platform_LogConst("Unable to find first partition on SD card"); return; - } - - if (fs_fat_init()) { + } + + if (fs_fat_init()) { Platform_LogConst("Failed to init FAT filesystem"); return; } - if (fs_fat_mount("/sd", &sd_dev, FS_FAT_MOUNT_READWRITE)) { + if (fs_fat_mount("/sd", &sd_dev, FS_FAT_MOUNT_READWRITE)) { Platform_LogConst("Failed to mount SD card"); return; - } - - root_path = String_FromReadonly("/sd/ClassiCube"); + } + + root_path = String_FromReadonly("/sd/ClassiCube"); fs_mkdir("/sd/ClassiCube"); Platform_ReadonlyFilesystem = false; }