Так получилось, что с дискеты раньше пользовались колоссальной популярностью в 1980-х годах. Как вы догадались, сейчас идет 202X год (11 декабря), и дискеты вообще забыли, даже не знают, как они выглядят. Это – нормально, поэтому надо сделать так, чтобы все что можно, загрузилось с дискеты.
Ладно. Это лирическое отступление. А теперь код.
#include <stdio.h>
#include <stdlib.h>
int size = 1440*1024;
int clst = 3;
int file_id = 0;
unsigned char* disk;
static const int crt_time = (18 << 11) | (54 << 5) | (30 >> 1);
static const int crt_date = ((2022 - 1980) << 9) | (12<<5) | 10;
void fat_write(int n, int v) {
n *= 3;
int m = 0x0200 + (n >> 1);
int w = disk[m] + 256*disk[m];
if (n & 1) {
w = (w & 0x000F) | (v << 4);
} else {
w = (w & 0xF000) | v;
}
disk[m ] = w & 255;
disk[m+1] = w >> 8;
disk[0x1200 + m] = disk[m];
disk[0x1201 + m] = disk[m+1];
}
void writeb(int offset, int v) {
disk[offset ] = v & 255;
}
void writew(int offset, int v) {
disk[offset ] = v & 255;
disk[offset+1] = (v >> 8) & 255;
}
void set_root_entry(const char* name, int id, int cluster, int fsize) {
int i = 0;
int n = 0;
int ptr = 0x2600 + 32*id;
for (int j = 0; j < 11; j++) disk[ptr + j] = ' ';
while (name[i] && n < 11) {
int ch = name[i];
if (ch >= 'a' && ch <= 'z') ch += ('A'-'a');
if (ch == '.') {
n = 8;
} else {
disk[ptr + n] = ch;
n++;
}
i++;
}
disk[ptr + 0x0B] = 0x20;
disk[ptr + 0x0C] = 0x00;
disk[ptr + 0x0D] = 0x64;
disk[ptr + 0x0E] = crt_time & 255;
disk[ptr + 0x0F] = crt_time >> 8;
disk[ptr + 0x10] = crt_date & 255;
disk[ptr + 0x11] = crt_date >> 8;
disk[ptr + 0x12] = crt_date & 255;
disk[ptr + 0x13] = crt_date >> 8;
disk[ptr + 0x14] = 0;
disk[ptr + 0x15] = 0;
disk[ptr + 0x16] = crt_time & 255;
disk[ptr + 0x17] = crt_time >> 8;
disk[ptr + 0x18] = crt_date & 255;
disk[ptr + 0x19] = crt_date >> 8;
disk[ptr + 0x1A] = cluster & 255;
disk[ptr + 0x1B] = cluster >> 8;
disk[ptr + 0x1C] = fsize & 255;
disk[ptr + 0x1D] = (fsize >> 8) & 255;
disk[ptr + 0x1E] = (fsize >> 16) & 255;
disk[ptr + 0x1F] = (fsize >> 24) & 255;
}
void writedisk() {
FILE* fp = fopen("a.img", "wb");
if (fp) {
disk[510] = 0x55;
disk[511] = 0xAA;
fwrite(disk, 1, size, fp);
fclose(fp);
}
}
void add_file(const char* fn, const char* name = NULL) {
FILE* fp = fopen(fn, "rb");
if (fp) {
fseek(fp, 0, SEEK_END);
int fsize = ftell(fp);
fseek(fp, 0, SEEK_SET);
fread(disk + (0x4200 + 512*(clst - 2)), 1, fsize, fp);
fclose(fp);
int reserve = fsize >> 9;
if (fsize % 512) reserve++;
for (int i = 0; i < reserve; i++) {
fat_write(clst + i, reserve == i + 1 ? 0xFFF : clst + i + 1);
}
set_root_entry(name ? name : fn, file_id, clst, fsize);
file_id++;
clst += reserve;
} else {
printf("File not found %s\n", fn);
exit(1);
}
}
void update_boot() {
FILE* fp = fopen("boot.bin", "rb");
if (fp) {
fread(disk, 1, 512, fp);
fclose(fp);
} else {
printf("Can't file file boot.bin\n");
exit(1);
}
}
int main(int argc, char* argv[]) {
disk = (unsigned char*) malloc(size);
for (int i = 0; i < size; i++) disk[i] = 0;
update_boot();
fat_write(0, 0xFF0);
fat_write(1, 0xFFF);
add_file("demo.bin");
writedisk();
free(disk);
return 0;
}