Version 1.0

This commit is contained in:
Zachary Hall 2023-12-02 19:59:43 -08:00
parent 4805d60e4c
commit 217d0444ae

View file

@ -19,31 +19,77 @@ bool compress;
bool direct_to_vera; bool direct_to_vera;
uint16_t imgdatastart; uint16_t imgdatastart;
uint32_t imgdatabytes; uint32_t imgdatabytes;
size_t palette_size = 0;
size_t palette_entry_count = 0;
size_t palette_start_byte = 0;
size_t vera_w, vera_h;
uint8_t pixels_per_byte; uint8_t pixels_per_byte;
uint8_t borderidx = 255; uint8_t borderidx = 255;
bool over320; bool over320;
uint8_t oldhscale, oldvscale; uint8_t oldhscale, oldvscale;
uint8_t significant_palette_entries; uint8_t significant_palette_entries;
uint8_t significant_palette_start; uint8_t significant_palette_start;
size_t expected_data_begin = 0;
uint8_t *image_start = BANK_RAM; uint8_t *image_start = BANK_RAM;
typedef enum {
LZSA2 = -1,
NONE = 0,
} CompressionType;
CompressionType compression_type = 0;
uint32_t filepos = 0;
/// @brief Reads a 16 bit little endian value from LFN 2 /// @brief Reads a 16 bit little endian value from LFN 2
/// @return The 16 bit value /// @return The 16 bit value
uint16_t read16() { uint16_t read16() {
cbm_k_chkin(2); cbm_k_chkin(2);
filepos++;
filepos++;
return ((cbm_k_chrin())) | ((uint16_t)cbm_k_chrin() << 8); return ((cbm_k_chrin())) | ((uint16_t)cbm_k_chrin() << 8);
} }
/// @brief Reads an 8 bit value and returns it as a character /// @brief Reads an 8 bit value and returns it as a character
/// @return The character /// @return The character
char readchar() { char readchar() {
cbm_k_chkin(2); cbm_k_chkin(2);
filepos++;
return cbm_k_chrin(); return cbm_k_chrin();
} }
/// @brief Reads an unsigned 8 bit value and returns it as is /// @brief Reads an unsigned 8 bit value and returns it as is
/// @return The unsigned 8 bit value /// @return The unsigned 8 bit value
uint8_t read8() { uint8_t read8() {
cbm_k_chkin(2); cbm_k_chkin(2);
filepos++;
return cbm_k_getin(); return cbm_k_getin();
} }
size_t readbuf(void *ptr, size_t max, bool incr) {
size_t i = 0;
size_t read_bytes = 255;
// Do while loop for special case of max 0 where we read as many bytes as possible.
do {
if (max == 0) {
read_bytes = 0;
} else if (max - i > 255) {
read_bytes = 255;
} else {
read_bytes = max - i;
}
read_bytes = cx16_k_macptr(read_bytes, incr, ptr);
filepos += read_bytes;
i += read_bytes;
} while (max != 0 && i < max && read_bytes != 0);
return i;
}
void seek(uint32_t new_filepos) {
char buf[7];
buf[0] = 'p';
buf[1] = 2;
buf[2] = filepos & 0xFF;
buf[3] = (filepos >> 8) & 0xFF;
buf[4] = (filepos >> 16) & 0xFF;
buf[5] = (filepos >> 24) & 0xFF;
buf[6] = '\0';
filepos = new_filepos;
cbm_open(15, 8, 15, buf);
cbm_close(15);
}
/// @brief Checks if the header in LFN 2 is correct /// @brief Checks if the header in LFN 2 is correct
/// @return True if it is, false otherwise /// @return True if it is, false otherwise
bool checkheader() { bool checkheader() {
@ -103,8 +149,6 @@ int uploadimage(const char *filename) {
uint8_t *image_end = BANK_RAM; uint8_t *image_end = BANK_RAM;
// 16 bit variables // 16 bit variables
size_t i = 0, j = 0, x = 0, y = 0, value = 0, bitmask = 0; size_t i = 0, j = 0, x = 0, y = 0, value = 0, bitmask = 0;
// Variables for the VERA width and height values
size_t vera_w = 320, vera_h = 240;
// The max address of the VERA // The max address of the VERA
uint16_t vera_max = 0; uint16_t vera_max = 0;
// 32 bit variables, used sparingly // 32 bit variables, used sparingly
@ -119,6 +163,7 @@ int uploadimage(const char *filename) {
uint8_t version; uint8_t version;
// True if all palette entries are significant // True if all palette entries are significant
bool all_significant; bool all_significant;
vera_w = 320, vera_h = 240;
// Open the file // Open the file
cbm_k_setnam(filename); cbm_k_setnam(filename);
cbm_k_setlfs(2, 8, 2); cbm_k_setlfs(2, 8, 2);
@ -135,6 +180,9 @@ int uploadimage(const char *filename) {
} }
// Read the header // Read the header
version = read8(); version = read8();
if (version != 1) {
printf("Warning: Unknown version %u!\n", version);
}
bitdepth = read8(); bitdepth = read8();
// Verify the bitdepth // Verify the bitdepth
if (bitdepth == 0) { if (bitdepth == 0) {
@ -142,7 +190,14 @@ int uploadimage(const char *filename) {
return 1; return 1;
} }
vera_bit_depth = read8(); vera_bit_depth = read8();
if (vera_bit_depth & 0b11 != vera_bit_depth) {
printf("Warning: Invalid VERA bitdepth %2x\n", vera_bit_depth);
}
vera_bit_depth &= 0b11; vera_bit_depth &= 0b11;
if (1 << vera_bit_depth != bitdepth) {
printf("Warning: VERA bitdepth mismatch: %ubpp vs %ubpp\n", 1 << vera_bit_depth, bitdepth);
bitdepth = 1 << vera_bit_depth;
}
config |= vera_bit_depth; config |= vera_bit_depth;
// Calculate the amount of pixels that can fit in a byte, used later // Calculate the amount of pixels that can fit in a byte, used later
pixels_per_byte = 8 / bitdepth; pixels_per_byte = 8 / bitdepth;
@ -158,35 +213,59 @@ int uploadimage(const char *filename) {
// Get the list of significant palette entires // Get the list of significant palette entires
significant_palette_entries = read8(); significant_palette_entries = read8();
significant_palette_start = read8(); significant_palette_start = read8();
palette_entry_count = significant_palette_entries;
if (significant_palette_entries == 0) { if (significant_palette_entries == 0) {
printf("All palette entries significant.\n"); printf("All palette entries significant.\n");
all_significant = true; all_significant = true;
significant_palette_start = 0; significant_palette_start = 0;
palette_entry_count = 256;
} else { } else {
printf("%u palette entries significant\nstarting at %u.\n", significant_palette_entries, significant_palette_start); printf("%u palette entries significant\nstarting at %u.\n", significant_palette_entries, significant_palette_start);
} }
palette_size = palette_entry_count * 2;
palette_start_byte = ((uint16_t)significant_palette_start) * 2;
printf("Palette: $1f%03x -> $1f%03x (len: $%03x)\n", palette_start_byte + 0xA00, palette_start_byte + 0xA00 + palette_size, palette_size);
imgdatastart = read16(); imgdatastart = read16();
expected_data_begin = 32 + palette_size;
if (imgdatastart != expected_data_begin) {
printf("Warning: Unsupported or corrupted image file.\n");
printf("Image data start was incorrect!\n");
printf("Expected: %u, got: %u\n", expected_data_begin, imgdatastart);
imgdatastart = expected_data_begin;
} else {
printf("Image data start looks good!\n");
}
printf("Image starts at 0-indexed offset %4x\n", imgdatastart); printf("Image starts at 0-indexed offset %4x\n", imgdatastart);
direct_to_vera = width == vera_w && height == vera_h; direct_to_vera = width == vera_w && height == vera_h;
if ((int8_t)read8() == -1) { compression_type = (CompressionType)read8();
compress = true; switch (compression_type) {
}; case LZSA2: {
printf("Using LZSA2 compression\n");
} break;
case NONE: {
printf("Using no compression\n");
} break;
default: {
printf("ERROR: Invalid compression type!");
return -1;
}
}
// Load the border color // Load the border color
borderidx = read8(); borderidx = read8();
printf("Skipping reserved bytes...\n"); printf("Skipping reserved bytes...\n");
for (i = 0; i < 16; i++) { while (filepos < 32) {
read8(); read8();
} }
printf("Border color: %02x\n", borderidx); printf("Border color: %02x\n", borderidx);
printf("Reading palette entries...\n"); printf("Reading palette entries...\n");
for (i = 0; i < (all_significant ? 512 : (uint16_t)significant_palette_entries*2); i++) { for (i = 0; i < palette_size; i++) {
// Only load the required palette entries // Only load the required palette entries
palette[i+(significant_palette_start*2)] = read8(); palette[i+(significant_palette_start*2)] = read8();
} }
// If the VERA was set up for a 640p image, make sure to keep track of that // If the VERA was set up for a 640p image, make sure to keep track of that
if (over320) { if (over320) {
vera_w *= 2; vera_w = 640;
vera_h *= 2; vera_h = 480;
} }
// Calculate the maximum address and bank // Calculate the maximum address and bank
vera_max_32 = ((uint32_t)vera_w * (uint32_t)vera_h)/(uint32_t)pixels_per_byte; vera_max_32 = ((uint32_t)vera_w * (uint32_t)vera_h)/(uint32_t)pixels_per_byte;
@ -198,6 +277,20 @@ int uploadimage(const char *filename) {
VERA.layer0.config = config; VERA.layer0.config = config;
// Make sure the TILEW value is set up correctly // Make sure the TILEW value is set up correctly
VERA.layer0.tilebase = over320 ? 1 : 0; VERA.layer0.tilebase = over320 ? 1 : 0;
if (filepos != imgdatastart) {
printf("WARNING: The current file position does not\ncorrespond to the image data's start!\n");
printf("File position: %4x\nImage data beginning: %4x\n", filepos, imgdatastart);
if (imgdatastart == 0) {
printf("Assuming imgdatastart was left uninitialized. Not seeking.");
} else {
while (filepos < imgdatastart) {
read8();
}
if (filepos > imgdatastart) {
seek(imgdatastart);
}
}
}
// Debugging // Debugging
printf("Loading %simage bytes: $%lx\n", compress ? "compressed " : "", imgdatabytes); printf("Loading %simage bytes: $%lx\n", compress ? "compressed " : "", imgdatabytes);
printf("Image width: %u, image height: %u\npixels per byte: %u\n", width, height, pixels_per_byte); printf("Image width: %u, image height: %u\npixels per byte: %u\n", width, height, pixels_per_byte);
@ -216,7 +309,7 @@ int uploadimage(const char *filename) {
if (compress) { if (compress) {
RAM_BANK = 1; RAM_BANK = 1;
do { do {
i = cx16_k_macptr(0, true, image_end); i = readbuf(image_end, 0, true);
image_end += i; image_end += i;
if (RAM_BANK > 1) { if (RAM_BANK > 1) {
printf("Error: Cannot decompress memory because compressed data is too large.\n"); printf("Error: Cannot decompress memory because compressed data is too large.\n");
@ -239,7 +332,7 @@ int uploadimage(const char *filename) {
DEBUG_PORT1 = 0; DEBUG_PORT1 = 0;
} else { } else {
do { do {
bytes_read = cx16_k_macptr(0, false, &VERA.data0); bytes_read = readbuf(&VERA.data0, 0, false);
} while (bytes_read > 0); } while (bytes_read > 0);
} }
} else { } else {
@ -253,7 +346,7 @@ int uploadimage(const char *filename) {
} }
if (x < width && y < height) { if (x < width && y < height) {
// Load the image's bytes, up to the bytes per row - the x value in bytes // Load the image's bytes, up to the bytes per row - the x value in bytes
bytes_read = cx16_k_macptr((((width) - x))/pixels_per_byte, false, &VERA.data0); bytes_read = readbuf(&VERA.data0, (((width) - x))/pixels_per_byte, false);
} else { } else {
// Fill the remaining pixels in the row with the border color using a fast assembly routine // Fill the remaining pixels in the row with the border color using a fast assembly routine
tmp = (vera_w-x)/pixels_per_byte; tmp = (vera_w-x)/pixels_per_byte;
@ -299,13 +392,20 @@ void set_text_color(uint8_t color) {
VERA.data0 = color; VERA.data0 = color;
} }
} }
typedef enum {
LayerBoth = 0b11,
LayerGraphics = 0b01,
LayerText = 0b10
} LayerState;
int main(int argc, char **argv) { int main(int argc, char **argv) {
char *buf; char *buf;
int ret; int ret;
bool done, text_visible; bool done;
LayerState layers;
char ch; char ch;
uint8_t coloridx = 1; uint8_t coloridx = 1;
size_t i; size_t i;
bool second_row;
backup_palette(); backup_palette();
buf = (char*)malloc(81); buf = (char*)malloc(81);
printf("Enter viewable file name: "); printf("Enter viewable file name: ");
@ -324,20 +424,33 @@ int main(int argc, char **argv) {
set_text_256color(true); set_text_256color(true);
printf("Press arrow keys to change text colors."); printf("Press arrow keys to change text colors.");
gotoxy(0, 0); gotoxy(0, 0);
printf("[ESC] to exit, [SPACE] to toggle text.");
coloridx = significant_palette_start - 1; coloridx = significant_palette_start - 1;
set_text_color(coloridx); set_text_color(coloridx);
second_row = vera_h <= 320;
if (second_row) {
gotoxy(0, (vera_h>>3)-2);
printf("[F1] Text [F3] Both \n[F2] Graph [ESC] Exit ");
} else {
gotoxy(0, (vera_h>>3)-1);
printf("[F1] Text [F2] Graph [F3] Both [ESC] Exit ");
}
done = false; done = false;
text_visible = true; layers = LayerBoth;
while (!done) { while (!done) {
while (kbhit()) { while (kbhit()) {
ch = cgetc(); ch = cgetc();
if (ch == CH_ESC) { if (ch == CH_ESC) {
done = true; done = true;
break; break;
} else if (ch == ' ') { } else if (ch == CH_F1) {
text_visible = !text_visible; layers = LayerText;
vera_layer_enable(0b1 | (text_visible ? 0b10 : 0)); vera_layer_enable(layers);
} else if (ch == CH_F2) {
layers = LayerGraphics;
vera_layer_enable(layers);
} else if (ch == CH_F3) {
layers = LayerBoth;
vera_layer_enable(layers);
} else if (ch == CH_CURS_LEFT) { } else if (ch == CH_CURS_LEFT) {
set_text_color(--coloridx); set_text_color(--coloridx);
} else if (ch == CH_CURS_RIGHT) { } else if (ch == CH_CURS_RIGHT) {