// DOS save-file + disk-space HAL.
//
// SAVES/ is a real subdirectory next to the .EXE, made with POSIX mkdir;
// delete is stdio remove(); free space comes from DOS INT 21h AH=36h (Get
// Disk Free Space) on the default drive.

#include <dpmi.h>
#include <stdio.h>
#include <sys/stat.h>

#include "joey/file.h"
#include "port.h"


// FAT ignores mode bits; 0777 is the conventional "create it" request.
#define SAVE_DIR_MODE   0777
#define DOS_MAX_U32     0xFFFFFFFFu


uint32_t jlpDiskFree(void) {
    __dpmi_regs  r;
    uint32_t     bytesPerClus;

    r.h.ah = 0x36u;                 // Get Disk Free Space
    r.h.dl = 0x00u;                 // 0 = default drive
    __dpmi_int(0x21, &r);
    if (r.x.ax == 0xFFFFu) {
        return 0u;                  // invalid drive
    }
    // AX = sectors/cluster, CX = bytes/sector, BX = free clusters. Saturate
    // in 32-bit rather than pull a 64-bit multiply helper onto the target.
    bytesPerClus = (uint32_t)r.x.ax * (uint32_t)r.x.cx;   // <= 65535*65535 < 2^32
    if (bytesPerClus != 0u && (uint32_t)r.x.bx > DOS_MAX_U32 / bytesPerClus) {
        return DOS_MAX_U32;
    }
    return bytesPerClus * (uint32_t)r.x.bx;
}


bool jlpSaveDelete(const char *path) {
    return remove(path) == 0;
}


bool jlpSaveDirEnsure(const char *dir) {
    struct stat  st;

    if (mkdir(dir, SAVE_DIR_MODE) == 0) {
        return true;
    }
    // mkdir failed -- success only if it failed because a directory is there.
    return stat(dir, &st) == 0 && S_ISDIR(st.st_mode);
}
