disk8: Initial commit
[pdp8.git] / sw / disk8 / src / file.c
CommitLineData
919757fd
PH
1/* File operations */
2
3#include <stdio.h>
4#include <stdlib.h>
5#include <fcntl.h>
6#include <string.h>
7#include <errno.h>
8#include <unistd.h>
9
10#include "logging.h"
11
12#include "structures.h"
13
14/*
15 * The following values are based on the address limitiations of OS/8.
16 * That guarantees that we'll never encounter a legal image that's
17 * bigger then calculated here.
18 */
19#define MAX_BLOCKS 4096
20#define WORDS_PER_BLOCK (129*2) /* Two physical 129 word DECTape blocks */
21#define BYTES_PER_WORD 2 /* That's the way we store 12 bit on the PC */
22#define PARTITIONS 2 /* An RK05 holds the whole circus twice! */
23#define READIN_SIZE (MAX_BLOCKS * WORDS_PER_BLOCK * BYTES_PER_WORD * PARTITIONS)
24
25
26/*!
27 *\brief The file read buffer
28 */
29static char file_buf[READIN_SIZE];
30
31/*!
32 * \brief Clear a disk image
33 * \arg image Pointer to an image_t structure.
34 *
35 * The image will be completely zeroed.
36 * Take care not to pass a bad pointer!
37 */
38void image_clear(image_t * image){
39 memset (image,0, sizeof(image_t));
40}
41
42
43/*!
44 * \brief Load and analyze an image file
45 *
46 * The image file is loaded into the file buffer.
47 * Then the data is copied into the image_t structure.
48 * 129 word blocks (DECTape) are eliminiated before copying.
49 *
50 * \param image Pointer to an allocated image_t structure.
51 * If image is NULL, a new image_t structure will be allocated
52 * and used.
53 * \param filename Name of the file to load from disk
54 * \return A Pointer to the initialized image_t structure.
55 * If image was not NULL, this is identical to image.
56 * \retval NULL on errors.
57 *
58 */
59image_t * image_load(image_t *image,
60 const char * filename
61 ){
62
63 /* Allocate memory if desired */
64 if (image==NULL){
65 image=(image_t *)malloc(sizeof(image_t));
66 }
67
68 MESSAGE("Loading file \"%s\":\n",filename);
69
70 /* We start with lots of zeroes.. */
71 image_clear(image);
72
73 int fd=open(filename,O_RDONLY);
74 if (fd <0){
75 ERROR("Could not open file! Reason:\"%s\"\n",strerror(errno));
76 return NULL;
77 } else DEBUG("File opened successfully.\n");
78
79 DEBUG("READIN_SIZE:%i\n",READIN_SIZE);
80
81 int res=0;
82 int fill=0;
83
84 do{
85 res=read(fd,file_buf+fill,READIN_SIZE-fill);
86 DBG ("Read %i bytes from file.\n",res);
87 fill+=res;
88 } while (res);
89
90 close(fd);
91 DBG("File closed.\n");
92 DBG("Image size is %i bytes\n",fill);
93
94 image->raw_size=fill;
95
96 /* Now determine image type */
97
98 if (fill%(sizeof(os8_block_t)+4)==0){
99 MESSAGE("Image type: DECtape 129\n");
100 image->size=fill/(sizeof(os8_block_t)+4);
101 image->type=IT_DECTAPE;
102
103 /* In this case, we have to eliminate word 129 of every block. */
104 int block;
105 for (block=0;block<image->size;block++){
106 memcpy(image->data+block*sizeof(os8_block_t),file_buf+block*sizeof(os8_block_t)+4,fill);
107 }
108 goto image_done;
109 }
110
111 if (fill%sizeof(os8_block_t)==0){
112 MESSAGE("Image type: Disk 128\n");
113 image->size=fill/sizeof(os8_block_t);
114 image->type=IT_DISK;
115 memcpy(image->data,file_buf,fill);
116 goto image_done;
117 }
118
119
120 MESSAGE ("Image length does not fit! Assuming disk image. Hope that's ok...\n");
121 image->type=IT_UNKNOWN;
122
123 /* We have an incomplete block. Then we simply create one block more. */
124 image->size=fill/(sizeof(os8_block_t))+1;
125 memcpy(image->data,file_buf,fill);
126
127 image_done:
128
129 /* Return successfully to the caller. */
130 return image;
131}