From 6f32ff71d052b3af6bbde71d25d521dd916ef0d1 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Wed, 27 Nov 2019 23:18:11 +0100 Subject: [PATCH] independent Test_PRG()/Load_PRG() It will be easier to disable and also better if there Save_PRG() --- src/c64load.c | 9 ++- src/c64load.h | 2 +- src/const.h | 1 + src/fileformats.h | 3 + src/loadsave.c | 3 +- src/miscfileformats.c | 176 ++++++++++++++++++++++++++++-------------- 6 files changed, 131 insertions(+), 63 deletions(-) diff --git a/src/c64load.c b/src/c64load.c index 3d12a5ca..b0d47529 100644 --- a/src/c64load.c +++ b/src/c64load.c @@ -154,15 +154,15 @@ static void C64_mem_write(void *context, word address, byte value) c64->ram[address] = value; } -int C64_LoadPrg(struct c64state * c64, const byte * prg, long prg_size, word start) +int C64_LoadPrg(struct c64state * c64, FILE * file, word start) { M6502 cpu; zusize cycles = 0; zusize next_rasterline = 63; int i, count = 0; byte screen_min = 255; + int prg_size; - GFX2_Log(GFX2_DEBUG, "C64_LoadPrg(%p, %ld, $%04x)\n", prg, prg_size, start); if (c64->ram == NULL) { c64->ram = GFX2_malloc(65536); @@ -170,6 +170,10 @@ int C64_LoadPrg(struct c64state * c64, const byte * prg, long prg_size, word sta return 0; } memset(c64->ram, 0, 65536); + prg_size = fread(c64->ram + 0x801, 1, 38911, file); + GFX2_Log(GFX2_DEBUG, "C64_LoadPrg(%d, $%04x)\n", prg_size, start); + if (prg_size < 0) + return 0; c64->ram[0x00] = 0x2F; c64->ram[0x01] = 0x37; c64->ram[0x2B] = 0x01; @@ -199,7 +203,6 @@ int C64_LoadPrg(struct c64state * c64, const byte * prg, long prg_size, word sta c64->ram[0xd02d] = 0xF7; c64->ram[0xd02e] = 0xFC; c64->ram[0xdd00] = 0x97; - memcpy(c64->ram + 0x801, prg + 2, prg_size - 2); c64->cpu = &cpu; memset(&cpu, 0, sizeof(cpu)); diff --git a/src/c64load.h b/src/c64load.h index 728fefff..318d3e01 100644 --- a/src/c64load.h +++ b/src/c64load.h @@ -48,7 +48,7 @@ struct c64state { }; word C64_isBinaryProgram(FILE * f); -int C64_LoadPrg(struct c64state * c64, const byte * prg, long prg_size, word start); +int C64_LoadPrg(struct c64state * c64, FILE * file, word start); #endif diff --git a/src/const.h b/src/const.h index 487f0f75..3b5b3963 100644 --- a/src/const.h +++ b/src/const.h @@ -141,6 +141,7 @@ enum FILE_FORMATS FORMAT_CEL, ///< Atari ST Cyber Paint Cell FORMAT_NEO, ///< Atari ST NeoChrome FORMAT_C64, ///< Several C64 formats : Koala, FLI, BML, etc. + FORMAT_PRG, ///< C64 autoload picture FORMAT_GPX, ///< pixcen C64 format : .gpx FORMAT_KCF, ///< KiSS Color File FORMAT_PAL, ///< raw 6bit palette or Jasc Paint Shop Pro palette diff --git a/src/fileformats.h b/src/fileformats.h index 56926bfe..332dd6f4 100644 --- a/src/fileformats.h +++ b/src/fileformats.h @@ -111,6 +111,9 @@ void Test_C64(T_IO_Context *, FILE *); void Load_C64(T_IO_Context *); void Save_C64(T_IO_Context *); +void Test_PRG(T_IO_Context *, FILE *); +void Load_PRG(T_IO_Context *); + // -- GPX (pixcen C64) void Test_GPX(T_IO_Context *, FILE *); void Load_GPX(T_IO_Context *); diff --git a/src/loadsave.c b/src/loadsave.c index 2228ddf7..c7d983e0 100644 --- a/src/loadsave.c +++ b/src/loadsave.c @@ -144,7 +144,8 @@ const T_Format File_formats[] = { {FORMAT_PAL, " pal", Test_PAL, Load_PAL, Save_PAL, 1, 0, 0, "pal", "pal"}, {FORMAT_GPL, " gpl", Test_GPL, Load_GPL, Save_GPL, 1, 0, 0, "gpl", "gpl"}, {FORMAT_C64, " c64", Test_C64, Load_C64, Save_C64, 0, 1, 1, "c64", - "c64;p64;a64;pi;rp;aas;art;dd;iph;ipt;hpc;ocp;koa;koala;fli;bml;cdu;prg;pmg;rpm"}, + "c64;p64;a64;pi;rp;aas;art;dd;iph;ipt;hpc;ocp;koa;koala;fli;bml;cdu;pmg;rpm"}, + {FORMAT_PRG, " prg", Test_PRG, Load_PRG, NULL, 0, 1, 1, "prg", "prg"}, {FORMAT_GPX, " gpx", Test_GPX, Load_GPX, NULL, 0, 0, 0, "gpx", "gpx"}, {FORMAT_SCR, " cpc", Test_SCR, Load_SCR, Save_SCR, 0, 0, 0, "scr", "cpc;scr;win"}, {FORMAT_CM5, " cm5", Test_CM5, Load_CM5, Save_CM5, 0, 0, 1, "cm5", "cm5"}, diff --git a/src/miscfileformats.c b/src/miscfileformats.c index 74507aa0..b0c44d41 100644 --- a/src/miscfileformats.c +++ b/src/miscfileformats.c @@ -2725,19 +2725,7 @@ void Test_C64(T_IO_Context * context, FILE * file) File_error = 0; break; default: // then we don't know for now. - if (load_addr == 0x801) - { - // 6502 emulators : - // https://github.com/redcode/6502 - // http://rubbermallet.org/fake6502.c - // https://github.com/jamestn/cpu6502 - // https://github.com/dennis-chen/6502-Emu - // https://github.com/DavidBuchanan314/6502-emu - // basic program - if (C64_isBinaryProgram(file) != 0) - File_error = 0; - } - else if (load_addr == 0x6000 || load_addr == 0x5c00) + if (load_addr == 0x6000 || load_addr == 0x5c00) { long unpacked_size; byte * buffer = GFX2_malloc(file_size); @@ -2760,6 +2748,34 @@ void Test_C64(T_IO_Context * context, FILE * file) } } +/** + * Test for a C64 auto-load machine language program + * which could be a picture + */ +void Test_PRG(T_IO_Context * context, FILE * file) +{ + unsigned long file_size; + word load_addr; + (void)context; + + file_size = File_length_file(file); + if (file_size > (38911 + 2)) // maximum length of PRG loaded at $0801 + return; + if (!Read_word_le(file, &load_addr)) + return; + if (load_addr != 0x0801) + return; + // 6502 emulators : + // https://github.com/redcode/6502 + // http://rubbermallet.org/fake6502.c + // https://github.com/jamestn/cpu6502 + // https://github.com/dennis-chen/6502-Emu + // https://github.com/DavidBuchanan314/6502-emu + // basic program + if (C64_isBinaryProgram(file) != 0) + File_error = 0; +} + /** * Load C64 hires (320x200) * @@ -3147,20 +3163,17 @@ static long C64_unpack_doodle(byte ** file_buffer, long file_size) */ void Load_C64(T_IO_Context * context) { - int prg_loaded = 0; FILE* file; long file_size; byte hasLoadAddr=0; word load_addr; enum c64_format loadFormat = F_invalid; - struct c64state c64; byte *file_buffer; byte *bitmap, *screen_ram, *color_ram=NULL, *background=NULL; // Only pointers to existing data byte *temp_buffer = NULL; word width, height=200; - memset(&c64, 0, sizeof(c64)); file = Open_file_read(context); if (file) @@ -3183,50 +3196,21 @@ void Load_C64(T_IO_Context * context) fclose(file); return; } + fclose(file); // get load address (valid only if hasLoadAddr = 1) load_addr = file_buffer[0] | (file_buffer[1] << 8); - if (load_addr == 0x801) + // Unpack if needed + if (memcmp(file_buffer + 2, "DRAZPAINT", 9) == 0) + file_size = C64_unpack_draz(&file_buffer, file_size); + else if(load_addr == 0x4000 && file_buffer[file_size-2] == 0xC2 && file_buffer[file_size-1] == 0) + file_size = C64_unpack_amica(&file_buffer, file_size); + else if (file_size < 8000 && (load_addr == 0x6000 || load_addr == 0x5c00)) + file_size = C64_unpack_doodle(&file_buffer, file_size); + + switch (file_size) { - word start_addr = C64_isBinaryProgram(file); - if (start_addr != 0) - { - prg_loaded = C64_LoadPrg(&c64, file_buffer, file_size, start_addr); - if (prg_loaded) - { - background = c64.ram + 0xd021; - if (c64.vicmode & C64_VICMODE_FLI) - { - loadFormat = F_fli; - background = c64.backgrounds; - } - else if (c64.vicmode & C64_VICMODE_MULTI) - loadFormat = F_multi; - else - loadFormat = F_hires; - - hasLoadAddr = 1; - bitmap = c64.ram + c64.bitmap; - screen_ram = c64.ram + c64.screen; - color_ram = c64.ram + 0xd800; - } - } - } - fclose(file); - - if (!prg_loaded) - { - // Unpack if needed - if (memcmp(file_buffer + 2, "DRAZPAINT", 9) == 0) - file_size = C64_unpack_draz(&file_buffer, file_size); - else if(load_addr == 0x4000 && file_buffer[file_size-2] == 0xC2 && file_buffer[file_size-1] == 0) - file_size = C64_unpack_amica(&file_buffer, file_size); - else if (file_size < 8000 && (load_addr == 0x6000 || load_addr == 0x5c00)) - file_size = C64_unpack_doodle(&file_buffer, file_size); - - switch (file_size) - { case 8000: // raw bitmap hasLoadAddr=0; loadFormat=F_bitmap; @@ -3476,7 +3460,6 @@ void Load_C64(T_IO_Context * context) File_error = 1; free(file_buffer); return; - } } if (loadFormat == F_invalid) @@ -3530,13 +3513,90 @@ void Load_C64(T_IO_Context * context) free(file_buffer); if (temp_buffer) free(temp_buffer); - if (c64.ram) - free(c64.ram); } else File_error = 1; } +/** + * Load C64 autoload pictures + * + * @param context the IO context + */ +void Load_PRG(T_IO_Context * context) +{ + FILE* file; + unsigned long file_size; + struct c64state c64; + enum c64_format loadFormat = F_invalid; + word load_addr; + word width, height = 200; + + memset(&c64, 0, sizeof(c64)); + + File_error = 1; + file = Open_file_read(context); + if (file == NULL) + return; + file_size = File_length_file(file); + if (!Read_word_le(file, &load_addr)) + return; + if (load_addr == 0x801) + { + word start_addr = C64_isBinaryProgram(file); + if (start_addr == 0) + return; + if (fseek(file, 2, SEEK_SET) < 0) + return; + if (C64_LoadPrg(&c64, file, start_addr)) + { + File_error = 0; + if (c64.vicmode & C64_VICMODE_FLI) + loadFormat = F_fli; + else if (c64.vicmode & C64_VICMODE_MULTI) + loadFormat = F_multi; + else + loadFormat = F_hires; + + if (loadFormat == F_fli || loadFormat == F_multi) + { + context->Ratio = PIXEL_WIDE; + width = 160; + } + else + { + context->Ratio = PIXEL_SIMPLE; + width = 320; + } + + Pre_load(context, width, height, file_size, FORMAT_PRG, context->Ratio, 4); // Do this as soon as you can + + if (Config.Clear_palette) + memset(context->Palette, 0, sizeof(T_Palette)); + C64_set_palette(context->Palette); + context->Transparent_color = 16; + + switch(loadFormat) + { + case F_fli: + Load_C64_fli(context, c64.ram + c64.bitmap, c64.ram + c64.screen, c64.ram + 0xd800, c64.backgrounds); + Set_image_mode(context, IMAGE_MODE_C64FLI); + break; + case F_multi: + Load_C64_multi(context, c64.ram + c64.bitmap, c64.ram + c64.screen, c64.ram + 0xd800, c64.ram[0xd021]); + Set_image_mode(context, IMAGE_MODE_C64MULTI); + break; + default: + Load_C64_hires(context, c64.ram + c64.bitmap, c64.ram + c64.screen); + if (loadFormat == F_hires) + Set_image_mode(context, IMAGE_MODE_C64HIRES); + } + } + if (c64.ram != NULL) + free(c64.ram); + } +} + /** * Display the dialog for C64 save parameters *