/*

cc65 paint magic viewer

written by Tim Schuermann, tischuer@yahoo.de 2003-01-31
Thanks to Arndt Dettke (info@godot64.de) for the file-format
informations.

The paint magic viewer is based on the
"cc65 koala viewer" by MagerValp, so i put it under the same
license.

Original copyright notice from the koala viewer (loadkoala):

-------
Just a small example of how to load graphics into memory.
It's hereby put in the public domain, do whatever you want
with this source.

MagerValp@cling.gu.se 2002-11-29
-------

*/



#include <stdio.h>
#include <fcntl.h>


unsigned char loadtoram(FILE *fp, unsigned char *dest, unsigned int length) {
  int l;

  while (length) {
    /* try to read length bytes */
    l=fread(dest, sizeof(unsigned char),length, fp); 
    if (l != length) {
      return(1); /* something went wrong */
    } else {
      length -= l; /* decrease length by actualy amount read */
      dest += l; /* increase destination pointer by same amount */
    }
  }
  return(0); /* ok */
}

/*
   loadtotrash simulate the fseek(fp, length, SEEK_CUR) function
*/
unsigned char loadtotrash(FILE *fp, unsigned int length)
{

  while(length){
        fgetc(fp);
        if(ferror(fp)) return(1); /* return 1 if something went wrong */
        length--; /* decrease length by 1 */
  }

  return(0); /* ok */
}



#define poke(A,X) (*(unsigned char *)A) = (X)
#define peek(A) (*(unsigned char *)A)


unsigned char *filename = "pmpic";

int main(void) {

  unsigned char addr[2];

  FILE *fp;

  unsigned char colourram;  /* colour for the $d800-RAM (colour 3) */
  unsigned int i; /* counter in the $d800-RAM for-loop */


#ifdef __CBM__
   /*
      set filetype to 'prg' on CBM-machines;
      if your picture is not saved as prg,
      you have to change the filetype
   */
#ifndef _CBM_H
extern
#endif
   _filetype='p'; 
#endif


  /* open the file */
  fp=fopen(filename, "r");
  if(fp==NULL){
    printf("Couldn't open %s.\n", filename);
    return(1);
  }

  /* read file load address */
  if(loadtoram(fp, &addr, 2)){
    fclose(fp);
    printf("Couldn't read load address.\n");
    return(1);
  }

  /* make sure load address is $3f8e */
  if (addr[0] != 0x8e || (addr[1] != 0x3f )) {
    fclose(fp);
    printf("This doesn't look like a paint magic picture.\n");
    return(2);
  }

  /* load the display routine */
  if (loadtotrash(fp, 114)) {
    fclose(fp);
    printf("Error while reading display routine.\n");
    return(1);
  }

  /* load bitmap data */
  if (loadtoram(fp, (unsigned char *)0x2000, 8000)) {
    fclose(fp);
    printf("\fError while reading bitmap.\n");
    return(1);
  }

  /* load background colour into $d021 (colour 0) */
  if (loadtoram(fp, (unsigned char *)0xd021, 1)) {
    fclose(fp);
    printf("\fError while reading background colour.\n");
    return(1);
  }

  /* read two unused bytes */ 
  if (loadtotrash(fp, 2)){
    fclose(fp);
    printf("\fError while reading two unused bytes.\n");
    return(1);
  }

  /* load colour ram value... */
  if (loadtoram(fp, &colourram, 1)) {
    fclose(fp);
    printf("\fError while reading colour ram.\n");
    return(1);
  }
  /* ...and drop it into the colour ram */
  for(i=0; i<1000; i++) poke((0xd800+i), colourram); 

  /* load border colour into $d020 */
  if (loadtoram(fp, (unsigned char *)0xd020, 1)) {
    fclose(fp);
    printf("\fError while reading border colour.\n");
    return(1);
  }

  /* read 187 unused bytes */ 
  if (loadtotrash(fp, 187)){
    fclose(fp);
    printf("\fError while reading 187 unused bytes.\n");
    return(1);
  }

  /* load screen data */
  if (loadtoram(fp, (unsigned char *)0x0400, 1000)) {
    fclose(fp);
    printf("\fError while reading screen ram.\n");
    return(1);
  }



  /* done */
  if(fclose(fp)) {
     printf("\fCouldn't close the file\n");
     return(1);
  }

  poke(0xd011, 0x3b); /* enable bitmap mode */
  poke(0xd016, 0x18); /* enable multicolour */
  poke(0xd018, 0x1f); /* screen at $0400 bitmap at $2000 */

  while (!peek(0xc6)) { ; } /* wait for key */

  poke(0xd011, 0x1b);
  poke(0xd016, 0x08);
  poke(0xd018, 0x17);
  poke(0xd020, 0x0e);
  poke(0xd021, 0x06);

  printf("\f");
  poke(198,0); /* clear keyboard queue */
}

