Reading into a buffer per-byte is inefficient though… better to read larger blocks at a time.
E.g. off the top of my head based on Sylvester’s example:
TINY buf[256]; … int size = fread(buf, 256, 1, fp); if (size != 39) { printf("Unexpected size."); } else if (buf[0] != 0xfe) { printf("Not a palette file."); } else { while (i = 0; i < 16; i++) { printf("%5x", ((int*)(buf + 7))[i]); } }
Note sure if the ((int*)(buf + 7))[i] expression produces the expected result, but you get the drift.
Could also define a struct { byte id, int start, int end, int exec, int[16] palette } and read straight into that, with block size sizeof(thestruct)… Seems like a really convenient way to do it actually .
Here goes an almost working code:
#include<stdio.h> #include<glib.h> #define REGISTROS 16 int paleta[REGISTROS]; int valores[REGISTROS]; NAT grbdat[16]={0x0442,0x0000,0x0400,0x0040,0x0200,0x0221,0x0231,0x0224,0x0346,0x0777,0x0436,0x0120,0x0555,0x0420,0x0250,0x0113}; readHex() { FILE *file; char *head; char str[2]; int i; int valor; printf("Loading pal...\n"); file=fopen("arthur4.pl5","rb"); fread(head,sizeof(char),7,file); /* Quitamos cabecera */ fread(paleta,sizeof(int),REGISTROS,file); printf("Loaded\n"); fclose(file); for(i=0;i<REGISTROS;i++) { printf("%x ",paleta[i]); /* 1st printf */ printf("%x ",grbdat[i]); /* 2nd printf */ sprintf(str,"%x", paleta[i]); sscanf(str,"%x",&valor); printf("%x ",valor); /* 3rd printf */ } } main() { readHex(); }
The 3 printf prints exactly the same, so it's supossed that palette is being readed correctly.
442 0 400 ...
However this funcion works (sets palete correctly):
loadplt() { TINY pal; iniplt(); for(pal=0;pal<16;pal++) { setplt(pal,grbdat[pal]); } rstplt(); }
And this one not:
ldplt() { FILE *fp; char *head; char str[2]; int i; NAT valor; TINY pal; fp=fopen("arthur4.pl5","rb"); if(fp==NULL) { printf("File read error!"); return; } fread(head,sizeof(char),7,fp); fread(paleta,sizeof(int),REGISTROS,fp); fclose(fp); iniplt(); for(pal=0;pal<16;pal++) { sprintf(str,"%x",paleta[i]); sscanf(str,"%x",&valor); setplt(pal,&valor); } rstplt(); }
What's wrong?
fread(head,sizeof(char),7,file); /* Quitamos cabecera */
Ai, scary, uninitialised head pointer, reading into unallocated space -> memory corruption.
char str[2];
C strings are null-terminated so you don’t allocate enough space to hold a 4-digit hexadecimal number + null terminator -> memory corruption.
sprintf(str,"%x",paleta[i]); sscanf(str,"%x",&valor);
Why do you sprintf and then sscanf? NAT is just an int right? You can pass paleta[i] directly to setplt() without first converting it to string and back.
Also, here’s an example of loading into a struct:
struct BinPalette { TINY head[7]; /* char */ NAT paleta[REGISTROS]; /* int */ }; ldplt() { FILE *fp; BinPalette binpal; int i; TINY pal; fp = fopen("arthur4.pl5", "rb"); if (fp == NULL) { printf("File read error!"); return; } fread(&binpal, sizeof(BinPalette), 1, fp); fclose(fp); iniplt(); for (pal = 0; pal < REGISTROS; pal++) { setplt(pal, binpal.paleta[i]); } rstplt(); }
Note that I’m unfamiliar with the exact syntax of K&R C so fingers crossed that it works , but hopefully it’ll illustrate the idea.
It seems a good way Grauw, as soon as I come back home I will try it thanks
What about this?
#define PALETTE_COLOR_COUNT 16 void ldplt(void) { FILE *f; NAT palette[PALETTE_COLOR_COUNT]; NAT palette_address; palette_address = 0x7680; // palette address on VRAM f = fopen("file.pl5", "rb"); if(f != NULL) { fseek(f, 7, SEEK_SET); // bypass the header fread(palette, sizeof(NAT), PALETTE_COLOR_COUNT, f); fclose(f); // copy palette to VRAM palette address ldirvm(palette_address, palette, sizeof(NAT)*PALETTE_COLOR_COUNT); // restore the palette rstplt(); } }
I've just tested @DarkSchneider code and works. Only one modification: fseek doesn't exist un MSX-C, replace with fread of 7 bytes to skip file header.
It would be useful to have a "seek", at least forward, function for files. Maybe this one works:
#define FSEEK_BUFFER_SIZE 32 #define FSEEK_STEPS_SHIFT 5 // FSEEK_STEPS_SHIFT = log2(FSEEK_BUFFER_SIZE) int ffwd(int size, FILE *f) { char buffer[FSEEK_BUFFER_SIZE]; int steps, remainder; steps = size >> FSEEK_STEPS_SHIFT; remainder = size - (steps << FSEEK_STEPS_SHIFT); // steps while(steps > 0) { fread(buffer, FSEEK_BUFFER_SIZE, 1, f); if(feof(f) || ferror(f)) { return 0; // fail } steps--; } // remainder if(remainder > 0) { fread(buffer, remainder, 1, f); if(feof(f) || ferror(f)) { return 0; // fail } } return 1; // success }
Let's go to the next quetion. Somebody knows how to reserve memory statically? This is, I'm not talking about malloc function (dinamically reserved), I'm talking about somekind of compiler option to tells it "I want to reserve memory from D800H to DC87H, not use it since I'm going to store here a asm function to be called during execution".
Is there any compiler directive to indicate it? Thanks.
A global byte array?
The space will be reserved statically, although you can’t tell it what start address it must have (idk if you need that).