/* casm - Simple, portable assembler Copyright (C) 2003-2015 Ian Cowburn (ianc@noddybox.demon.co.uk) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . ------------------------------------------------------------------------- Commodore T64 tape output handler. */ #include #include #include "global.h" #include "codepage.h" #include "t64out.h" /* ---------------------------------------- MACROS & TYPES */ #define NOT_USED 0 /* ---------------------------------------- PRIVATE FUNCTIONS */ static void WriteByte(FILE *fp, Byte b) { putc(b, fp); } static void WriteWord(FILE *fp, int w) { WriteByte(fp, w & 0xff); WriteByte(fp, (w & 0xff00) >> 8); } static void WriteLong(FILE *fp, unsigned long l) { int f; for(f = 0; f < 4; f++) { WriteByte(fp, l & 0xff); l >>= 8u; } } static void WriteString(FILE *fp, const char *p, int len, Byte fill, Codepage cp) { while(len--) { WriteByte(fp, *p ? CodeFromNative(cp, *p++) : CodeFromNative(cp, fill)); } } /* ---------------------------------------- INTERFACES */ const ValueTable *T64OutputOptions(void) { return NULL; } CommandStatus T64OutputSetOption(int opt, int argc, char *argv[], int quoted[], char *error, size_t error_size) { return CMD_NOT_KNOWN; } int T64Output(const char *filename, const char *filename_bank, MemoryBank **bank, int count, char *error, size_t error_size) { FILE *fp = fopen(filename, "wb"); int f; int offset; if (!fp) { snprintf(error, error_size, "Failed to create %s\n", filename); return FALSE; } /* Write signature */ WriteString(fp, "C64 tape image file", 32, 0, CP_ASCII); /* Write directory header */ WriteWord(fp, 0x1010); WriteWord(fp, count); WriteWord(fp, count); WriteWord(fp, NOT_USED); WriteString(fp, filename, 24, ' ', CP_CBM); /* Offset to tape data */ offset = 64 + 32 * count; /* Write directory entries */ for(f = 0; f < count; f++) { WriteByte(fp, 1); WriteByte(fp, 0x82); WriteWord(fp, bank[f]->min_address_used); WriteWord(fp, bank[f]->max_address_used); WriteWord(fp, NOT_USED); WriteLong(fp, offset); WriteWord(fp, NOT_USED); WriteWord(fp, NOT_USED); offset += bank[f]->max_address_used - bank[f]->min_address_used + 1; } /* Write actual contents */ for(f = 0; f < count; f++) { Byte *mem; int min, max, len; mem = bank[f]->memory; min = bank[f]->min_address_used; max = bank[f]->max_address_used; len = max - min + 1; fwrite(mem, len, 1, fp); } fclose(fp); return TRUE; } /* vim: ai sw=4 ts=8 expandtab */