mirror of
https://github.com/catmeow72/b16viewer.git
synced 2024-11-24 14:28:26 -08:00
Update to rev5, implement decompression.
This commit is contained in:
parent
887773ec81
commit
7530376cce
5 changed files with 194 additions and 82 deletions
25
src/fill.s
25
src/fill.s
|
@ -6,22 +6,21 @@ vera_data0 := $9f23
|
||||||
.import popa
|
.import popa
|
||||||
.segment "CODE"
|
.segment "CODE"
|
||||||
_fill_vera:
|
_fill_vera:
|
||||||
sta vera_fill_data
|
sta vera_fill_data ; Save the value to fill the vera with
|
||||||
jsr popa
|
jsr popa ; Get the length parameter
|
||||||
sta max
|
sta max ; Store the max value
|
||||||
lda max
|
cmp #0 ; Make sure it's not 0
|
||||||
cmp #0
|
beq @end ; If it is, we're already done
|
||||||
beq @end
|
|
||||||
@fill:
|
@fill:
|
||||||
ldx #0
|
ldx #0 ; Initialize X
|
||||||
lda vera_fill_data
|
lda vera_fill_data ; Load the fill value
|
||||||
@loop:
|
@loop:
|
||||||
sta vera_data0
|
sta vera_data0 ; Store the fill value
|
||||||
inx
|
inx ; Increment X
|
||||||
cpx max
|
cpx max ; Compare it against the maximum value
|
||||||
bne @loop
|
bne @loop ; If it's not the max yet, do it again
|
||||||
@end:
|
@end:
|
||||||
rts
|
rts ; We're done!
|
||||||
.segment "BSS"
|
.segment "BSS"
|
||||||
max:
|
max:
|
||||||
.res 1
|
.res 1
|
||||||
|
|
27
src/macptr.s
27
src/macptr.s
|
@ -7,30 +7,31 @@ r1 := $04
|
||||||
r1l:= $04
|
r1l:= $04
|
||||||
r1h:= $05
|
r1h:= $05
|
||||||
.segment "CODE"
|
.segment "CODE"
|
||||||
|
; ASM wrapper for MACPTR
|
||||||
_cx16_k_macptr:
|
_cx16_k_macptr:
|
||||||
sta r0l
|
sta r0l ; Store pointer in ZP
|
||||||
stx r0h
|
stx r0h
|
||||||
jsr popa
|
jsr popa ; Store increment boolean
|
||||||
sta r1l
|
sta r1l
|
||||||
jsr popa
|
jsr popa ; Store size byte
|
||||||
sta r1h
|
sta r1h
|
||||||
ldx r0l
|
ldx r0l ; Load parameters
|
||||||
ldy r0h
|
ldy r0h
|
||||||
lda r1l
|
lda r1l
|
||||||
beq @increment
|
beq @increment ; If A is 0, set the carry flag
|
||||||
clc
|
clc ; Otherwise clear it
|
||||||
jmp @loadregs
|
jmp @loadregs ; And don't set it again
|
||||||
@increment:
|
@increment:
|
||||||
sec
|
sec ; Set the carry flag
|
||||||
@loadregs:
|
@loadregs:
|
||||||
lda r1h
|
lda r1h ; Load the size parameter
|
||||||
jsr $FF44
|
jsr $FF44 ; Call MACPTR
|
||||||
bcs @error
|
bcs @error ; If there was an error, return 0
|
||||||
txa
|
txa ; Otherwise, set up registers to hold the return value
|
||||||
sty r0
|
sty r0
|
||||||
ldx r0
|
ldx r0
|
||||||
rts
|
rts
|
||||||
@error:
|
@error:
|
||||||
lda #0
|
lda #0 ; Return 0 in case of error
|
||||||
ldx #0
|
ldx #0
|
||||||
rts
|
rts
|
||||||
|
|
197
src/main.c
197
src/main.c
|
@ -5,98 +5,138 @@
|
||||||
#include <cbm.h>
|
#include <cbm.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include "vera.h"
|
#include "vera.h"
|
||||||
#include "macptr.h"
|
#include "macptr.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
#include "memory_decompress.h"
|
||||||
#include "fill.h"
|
#include "fill.h"
|
||||||
uint8_t palette[512];
|
uint8_t palette[512];
|
||||||
uint8_t vera_bit_depth;
|
uint8_t vera_bit_depth;
|
||||||
uint8_t bitdepth;
|
uint8_t bitdepth;
|
||||||
uint16_t width, height;
|
uint16_t width, height;
|
||||||
|
bool compress;
|
||||||
|
bool direct_to_vera;
|
||||||
|
uint16_t imgdatastart;
|
||||||
uint32_t imgdatabytes;
|
uint32_t imgdatabytes;
|
||||||
uint8_t pixels_per_byte;
|
uint8_t pixels_per_byte;
|
||||||
uint8_t filleridx = 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;
|
||||||
|
uint8_t *image_start = BANK_RAM;
|
||||||
|
/// @brief Reads a 16 bit little endian value from LFN 2
|
||||||
|
/// @return The 16 bit value
|
||||||
uint16_t read16() {
|
uint16_t read16() {
|
||||||
cbm_k_chkin(2);
|
cbm_k_chkin(2);
|
||||||
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
|
||||||
|
/// @return The character
|
||||||
char readchar() {
|
char readchar() {
|
||||||
cbm_k_chkin(2);
|
cbm_k_chkin(2);
|
||||||
return cbm_k_chrin();
|
return cbm_k_chrin();
|
||||||
}
|
}
|
||||||
|
/// @brief Reads an unsigned 8 bit value and returns it as is
|
||||||
|
/// @return The unsigned 8 bit value
|
||||||
uint8_t read8() {
|
uint8_t read8() {
|
||||||
cbm_k_chkin(2);
|
cbm_k_chkin(2);
|
||||||
return cbm_k_getin();
|
return cbm_k_getin();
|
||||||
}
|
}
|
||||||
|
/// @brief Checks if the header in LFN 2 is correct
|
||||||
|
/// @return True if it is, false otherwise
|
||||||
bool checkheader() {
|
bool checkheader() {
|
||||||
char header[4] = {0x42, 0x4D, 0x58, 0}; // X16BM
|
char header[4] = {0x42, 0x4D, 0x58, 0}; // BMX
|
||||||
char tested[4] = {0, 0, 0, 0};
|
char tested[4] = {0, 0, 0, 0}; // The tested values, for debugging
|
||||||
uint8_t i = 0;
|
uint8_t i = 0;
|
||||||
bool valid = true;
|
bool valid = true; // Set to true so that if it's wrong, the loop can set it to false, but if it's correct, the loop doesn't have to set it
|
||||||
char chr = 0;
|
char chr = 0;
|
||||||
printf("Reading magic bytes...\n");
|
printf("Reading magic bytes...\n");
|
||||||
|
// Check the magic bytes one-by-one
|
||||||
for (; i < 3; i++) {
|
for (; i < 3; i++) {
|
||||||
chr = readchar();
|
chr = readchar(); // Get a character
|
||||||
tested[i] = chr;
|
tested[i] = chr; // Put it in the tested value list
|
||||||
printf("%2x%s", chr, i >= 4 ? "\n" : ", ");
|
printf("%2x%s", chr, i >= 4 ? "\n" : ", ");
|
||||||
if (chr != header[i]) {
|
if (chr != header[i]) { // Check the value
|
||||||
valid = false;
|
valid = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Make sure the tested values don't contain any unprintable characters
|
||||||
for (i = 0; i < 3; i++) {
|
for (i = 0; i < 3; i++) {
|
||||||
if (tested[i] < 0x20 || tested[i] >= 0x7F) {
|
if (tested[i] < 0x20 || tested[i] >= 0x7F) {
|
||||||
tested[i] = '.';
|
tested[i] = '.';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("%s%c=%s\n", tested, valid ? '=' : '!', header);
|
printf("%s%c=%s\n", tested, valid ? '=' : '!', header); // Display the comparison
|
||||||
return valid;
|
return valid;
|
||||||
}
|
}
|
||||||
|
/// @brief Updates the scale of the VERA based on the minimum required width/height to display the image
|
||||||
void updatescale() {
|
void updatescale() {
|
||||||
uint8_t hscale;
|
uint8_t hscale;
|
||||||
uint8_t vscale;
|
uint8_t vscale;
|
||||||
|
// Set DCSEL to 0
|
||||||
VERA.control &= 0b10000001;
|
VERA.control &= 0b10000001;
|
||||||
|
// Get the scale to check against and later set back to
|
||||||
hscale = VERA.display.hscale;
|
hscale = VERA.display.hscale;
|
||||||
vscale = VERA.display.vscale;
|
vscale = VERA.display.vscale;
|
||||||
|
// Back up the current scale
|
||||||
oldhscale = hscale;
|
oldhscale = hscale;
|
||||||
oldvscale = vscale;
|
oldvscale = vscale;
|
||||||
|
// If it's over 320, the scale's probably correct.
|
||||||
if (over320) return;
|
if (over320) return;
|
||||||
|
// Make sure the scale doesn't end up showing garbage data.
|
||||||
if (hscale > 64) VERA.display.hscale = 64;
|
if (hscale > 64) VERA.display.hscale = 64;
|
||||||
if (vscale > 64) VERA.display.vscale = 64;
|
if (vscale > 64) VERA.display.vscale = 64;
|
||||||
}
|
}
|
||||||
|
/// @brief Restores the scale to what it was before updating it to fit the image
|
||||||
void restorescale() {
|
void restorescale() {
|
||||||
VERA.control &= 0b10000001;
|
VERA.control &= 0b10000001;
|
||||||
VERA.display.hscale = oldhscale;
|
VERA.display.hscale = oldhscale;
|
||||||
VERA.display.vscale = oldvscale;
|
VERA.display.vscale = oldvscale;
|
||||||
}
|
}
|
||||||
|
/// @brief Loads and uploads an image to the VERA
|
||||||
|
/// @param filename The file to load
|
||||||
|
/// @return 0 on success, exit code on failure
|
||||||
int uploadimage(const char *filename) {
|
int uploadimage(const char *filename) {
|
||||||
|
// Used for decompression.
|
||||||
|
uint8_t *image_end = BANK_RAM;
|
||||||
|
// 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;
|
size_t vera_w = 320, vera_h = 240;
|
||||||
|
// The max address of the VERA
|
||||||
uint16_t vera_max = 0;
|
uint16_t vera_max = 0;
|
||||||
|
// 32 bit variables, used sparingly
|
||||||
uint32_t tmp = 0, vera_max_32 = 0;
|
uint32_t tmp = 0, vera_max_32 = 0;
|
||||||
uint16_t vera_adr_bak;
|
// The bank the VERA will be at when the operation finishes
|
||||||
uint8_t vera_adr_h_bak;
|
|
||||||
bool vera_max_bank = 1;
|
bool vera_max_bank = 1;
|
||||||
|
// Base layer config
|
||||||
uint8_t config = 0b00000100;
|
uint8_t config = 0b00000100;
|
||||||
|
// The counter for the amount of bytes read
|
||||||
uint16_t bytes_read;
|
uint16_t bytes_read;
|
||||||
|
// The version of the BMX format
|
||||||
uint8_t version;
|
uint8_t version;
|
||||||
|
// True if all palette entries are significant
|
||||||
bool all_significant;
|
bool all_significant;
|
||||||
|
// Open the file
|
||||||
cbm_k_setnam(filename);
|
cbm_k_setnam(filename);
|
||||||
cbm_k_setlfs(2, 8, 2);
|
cbm_k_setlfs(2, 8, 2);
|
||||||
cbm_k_open();
|
cbm_k_open();
|
||||||
|
// Check if the open was successful
|
||||||
if (cbm_k_readst()) {
|
if (cbm_k_readst()) {
|
||||||
printf("Error opening file.\n");
|
printf("Error opening file.\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
// Make sure it's a BMX file
|
||||||
if (!checkheader()) {
|
if (!checkheader()) {
|
||||||
printf("Invalid file!\n");
|
printf("Invalid file!\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
// Read the header
|
||||||
version = read8();
|
version = read8();
|
||||||
bitdepth = read8();
|
bitdepth = read8();
|
||||||
|
// Verify the bitdepth
|
||||||
if (bitdepth == 0) {
|
if (bitdepth == 0) {
|
||||||
printf("Error: bitdepth was 0.\n");
|
printf("Error: bitdepth was 0.\n");
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -104,19 +144,18 @@ int uploadimage(const char *filename) {
|
||||||
vera_bit_depth = read8();
|
vera_bit_depth = read8();
|
||||||
vera_bit_depth &= 0b11;
|
vera_bit_depth &= 0b11;
|
||||||
config |= vera_bit_depth;
|
config |= vera_bit_depth;
|
||||||
if (vera_bit_depth > 3) {
|
// Calculate the amount of pixels that can fit in a byte, used later
|
||||||
printf("Error: VERA bit depth was invalid!\n");
|
|
||||||
}
|
|
||||||
pixels_per_byte = 8 / bitdepth;
|
pixels_per_byte = 8 / bitdepth;
|
||||||
printf("Bit depth: %u => %u pixels per byte\n", bitdepth, pixels_per_byte);
|
printf("Bit depth: %u => %u pixels per byte\n", bitdepth, pixels_per_byte); // Debugging
|
||||||
width = read16();
|
width = read16(); // Get the image dimensions
|
||||||
height = read16();
|
height = read16();
|
||||||
printf("Width: %u, height: %u\n", width, height);
|
printf("Width: %u, height: %u\n", width, height);
|
||||||
|
// Make sure the later update_scale call sets the correct scale
|
||||||
over320 = width > 320 || height > 240;
|
over320 = width > 320 || height > 240;
|
||||||
filleridx = read8();
|
// Calculate the amount of bytes used within the image
|
||||||
printf("Border color: %02x\n", filleridx);
|
|
||||||
imgdatabytes = ((uint32_t)width * (uint32_t)height) / (uint32_t)pixels_per_byte;
|
imgdatabytes = ((uint32_t)width * (uint32_t)height) / (uint32_t)pixels_per_byte;
|
||||||
printf("Bytes: %lu\n", imgdatabytes);
|
printf("Bytes: %lu\n", imgdatabytes);
|
||||||
|
// Get the list of significant palette entires
|
||||||
significant_palette_entries = read8();
|
significant_palette_entries = read8();
|
||||||
significant_palette_start = read8();
|
significant_palette_start = read8();
|
||||||
if (significant_palette_entries == 0) {
|
if (significant_palette_entries == 0) {
|
||||||
|
@ -126,61 +165,115 @@ int uploadimage(const char *filename) {
|
||||||
} 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);
|
||||||
}
|
}
|
||||||
|
imgdatastart = read16();
|
||||||
|
--imgdatastart;
|
||||||
|
printf("Image starts at 0-indexed offset %4x\n", imgdatastart);
|
||||||
|
direct_to_vera = width == vera_w && height == vera_h;
|
||||||
|
if ((int8_t)read8() == -1) {
|
||||||
|
compress = true;
|
||||||
|
};
|
||||||
printf("Skipping reserved bytes...\n");
|
printf("Skipping reserved bytes...\n");
|
||||||
for (i = 0; i < 19; i++) {
|
for (i = 0; i < 16; i++) {
|
||||||
read8();
|
read8();
|
||||||
}
|
}
|
||||||
|
// Load the border color
|
||||||
|
borderidx = read8();
|
||||||
|
printf("Border color: %02x\n", borderidx);
|
||||||
printf("Reading palette entries...\n");
|
printf("Reading palette entries...\n");
|
||||||
for (i = 0; i < 512; i++) {
|
for (i = 0; i < (uint16_t)significant_palette_entries*2; i++) {
|
||||||
j = i >> 1;
|
j = i >> 1;
|
||||||
if (all_significant || j >= significant_palette_start && j <= significant_palette_entries) {
|
// Only load the required palette entries
|
||||||
|
if (all_significant || j >= significant_palette_start && j < significant_palette_start+significant_palette_entries || j == borderidx) {
|
||||||
palette[i] = read8();
|
palette[i] = read8();
|
||||||
} else {
|
} else {
|
||||||
read8();
|
read8();
|
||||||
palette[i] = get_from_backed_up_palette(i);
|
palette[i] = get_from_backed_up_palette(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 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 *= 2;
|
||||||
vera_h *= 2;
|
vera_h *= 2;
|
||||||
}
|
}
|
||||||
|
// 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;
|
||||||
|
// Get just the max address
|
||||||
vera_max = vera_max_32;
|
vera_max = vera_max_32;
|
||||||
|
// ... and the max bank all by itself
|
||||||
vera_max_bank = vera_max_32 >> 16;
|
vera_max_bank = vera_max_32 >> 16;
|
||||||
|
// Update the VERA layer config
|
||||||
VERA.layer0.config = config;
|
VERA.layer0.config = config;
|
||||||
|
// Make sure the TILEW value is set up correctly
|
||||||
VERA.layer0.tilebase = over320 ? 1 : 0;
|
VERA.layer0.tilebase = over320 ? 1 : 0;
|
||||||
printf("Loading image bytes: $%lx\n", imgdatabytes);
|
// Debugging
|
||||||
|
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);
|
||||||
|
i = 0;
|
||||||
|
// Calculate the border value.
|
||||||
|
value = 0;
|
||||||
|
bitmask = (1 << bitdepth) - 1;
|
||||||
|
|
||||||
|
if (compress && !direct_to_vera) {
|
||||||
|
printf("Error: The image cannot be loaded due to limitations in memory_decompress.");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
for (i = 0; i < pixels_per_byte; i++) {
|
||||||
|
value |= (borderidx & bitmask) << (i * bitdepth);
|
||||||
|
}
|
||||||
|
if (compress) {
|
||||||
|
RAM_BANK = 1;
|
||||||
|
do {
|
||||||
|
i = cx16_k_macptr(0, true, image_end);
|
||||||
|
image_end += i;
|
||||||
|
if (RAM_BANK > 1) {
|
||||||
|
printf("Error: Cannot decompress memory because compressed data is too large.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (i == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (i != 0);
|
||||||
|
}
|
||||||
|
// Set up the VERA's data0 address
|
||||||
VERA.control &= ~0b1;
|
VERA.control &= ~0b1;
|
||||||
VERA.address = 0;
|
VERA.address = 0;
|
||||||
VERA.address_hi = 0b00010000;
|
VERA.address_hi = 0b00010000;
|
||||||
i = 0;
|
if (direct_to_vera) {
|
||||||
// Calculate the filler value.
|
if (compress) {
|
||||||
value = 0;
|
RAM_BANK = 1;
|
||||||
bitmask = (1 << bitdepth) - 1;
|
image_start = BANK_RAM;
|
||||||
for (i = 0; i < pixels_per_byte; i++) {
|
memory_decompress(image_start, &VERA.data0);
|
||||||
value |= (filleridx & bitmask) << (i * bitdepth);
|
DEBUG_PORT1 = 0;
|
||||||
}
|
|
||||||
// Upload the bitmap
|
|
||||||
for (x = 0; VERA.address < vera_max || (vera_max_bank & 0b1) != (VERA.address_hi & 0b1);) {
|
|
||||||
tmp = ((((uint32_t)VERA.address) + ((uint32_t)(VERA.address_hi & 0b1) << 16)));
|
|
||||||
x = (tmp % (uint32_t)(vera_w/pixels_per_byte))*pixels_per_byte;
|
|
||||||
y = tmp / (uint32_t)(vera_w/pixels_per_byte);
|
|
||||||
#if 0
|
|
||||||
vera_adr_bak = VERA.address;
|
|
||||||
vera_adr_h_bak = VERA.address_hi;
|
|
||||||
printf("Y: %u, X: %u, tmp: %lu,\nvera_w: %u\nvera_adr: %u, vera_adr_h: %s\n", y, x, tmp, vera_w, vera_adr_bak, (vera_adr_h_bak & 1) ? "1" : "0");
|
|
||||||
VERA.address = vera_adr_bak;
|
|
||||||
VERA.address_hi = vera_adr_h_bak;
|
|
||||||
#endif
|
|
||||||
if (y >= height) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (x < width && y < height) {
|
|
||||||
bytes_read = cx16_k_macptr((((width) - x))/pixels_per_byte, false, &VERA.data0);
|
|
||||||
} else {
|
} else {
|
||||||
//VERA.data0 = value;
|
do {
|
||||||
tmp = (vera_w-x)/pixels_per_byte;
|
bytes_read = cx16_k_macptr(0, false, &VERA.data0);
|
||||||
|
} while (bytes_read > 0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Upload the bitmap
|
||||||
|
for (x = 0; VERA.address < vera_max || (vera_max_bank & 0b1) != (VERA.address_hi & 0b1);) {
|
||||||
|
tmp = ((((uint32_t)VERA.address) + ((uint32_t)(VERA.address_hi & 0b1) << 16)));
|
||||||
|
x = (tmp % (uint32_t)(vera_w/pixels_per_byte))*pixels_per_byte;
|
||||||
|
y = tmp / (uint32_t)(vera_w/pixels_per_byte);
|
||||||
|
if (y >= height) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (x < width && y < height) {
|
||||||
|
// 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);
|
||||||
|
} else {
|
||||||
|
// Fill the remaining pixels in the row with the border color using a fast assembly routine
|
||||||
|
tmp = (vera_w-x)/pixels_per_byte;
|
||||||
|
if (tmp >= ((uint32_t)1 << 8)) {
|
||||||
|
fill_vera(0xFF, value);
|
||||||
|
} else {
|
||||||
|
fill_vera(tmp, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Fill the rest of the image with the border color using the same fast assembly routine
|
||||||
|
for (; VERA.address < vera_max || (vera_max_bank & 0b1) != (VERA.address_hi & 0b1);) {
|
||||||
|
tmp = vera_max_32 - (((uint32_t)VERA.address) | ((uint32_t)(VERA.address_hi & 0b1) << 16));
|
||||||
if (tmp >= ((uint32_t)1 << 8)) {
|
if (tmp >= ((uint32_t)1 << 8)) {
|
||||||
fill_vera(0xFF, value);
|
fill_vera(0xFF, value);
|
||||||
} else {
|
} else {
|
||||||
|
@ -188,17 +281,11 @@ int uploadimage(const char *filename) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (; VERA.address < vera_max || (vera_max_bank & 0b1) != (VERA.address_hi & 0b1);) {
|
// Set up the VERA to display the bitmap
|
||||||
tmp = vera_max_32 - (((uint32_t)VERA.address) | ((uint32_t)(VERA.address_hi & 0b1) << 16));
|
|
||||||
if (tmp >= ((uint32_t)1 << 8)) {
|
|
||||||
fill_vera(0xFF, value);
|
|
||||||
} else {
|
|
||||||
fill_vera(tmp, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
upload_palette(palette);
|
upload_palette(palette);
|
||||||
updatescale();
|
updatescale();
|
||||||
vera_layer_enable(0b11);
|
vera_layer_enable(0b11);
|
||||||
|
// Close the file
|
||||||
cbm_k_clrch();
|
cbm_k_clrch();
|
||||||
cbm_k_close(2);
|
cbm_k_close(2);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
6
src/memory_decompress.h
Normal file
6
src/memory_decompress.h
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#ifndef MEMORY_DECOMPRESS_H
|
||||||
|
#define MEMORY_DECOMPRESS_H
|
||||||
|
|
||||||
|
extern void * __cdecl__ memory_decompress(const void *input, void *output);
|
||||||
|
|
||||||
|
#endif
|
19
src/memory_decompress.s
Normal file
19
src/memory_decompress.s
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
.export _memory_decompress
|
||||||
|
.import popax
|
||||||
|
r0 := $02
|
||||||
|
r0l := $02
|
||||||
|
r0h := $03
|
||||||
|
r1l := $04
|
||||||
|
r1h := $05
|
||||||
|
.segment "CODE"
|
||||||
|
_memory_decompress:
|
||||||
|
jsr popax
|
||||||
|
sta r1l
|
||||||
|
stx r1h
|
||||||
|
jsr popax
|
||||||
|
sta r0l
|
||||||
|
stx r0h
|
||||||
|
jsr $FEED
|
||||||
|
lda r1l
|
||||||
|
ldx r1h
|
||||||
|
rts
|
Loading…
Reference in a new issue