The D88 file format is used across a number of emulators, but for the PC-9801, is primarily supported by the Neko Project 2 Emulator. It is the only FIVEC supported format that can contain multiple disks within a single file. The format is poorly honored by the various programs that utilize it, I've noted inconsistencies (beyond those already noted) below.
The below was compiled by sources other than me, and is reproduced here for reference. You can find the source on Github here, translated from Japanese to English by Ashura (of the FMV forums)
D88 (D68/D77/D98) File Structure ================================ - All values are stored in little-endian format. Image File Structure: ===================== Disk 1 Header Disk 1 Data Track 0 Sector 1 Header Sector 1 Data ... Track 1 Sector 1 Header ... ... Disk 2 Header Disk 2 Data Disk 3 Header ... Disk Header: ============ Size: 688 or 672 bytes. Offset Size Meaning ------------------------------------------------------------------------------------ 00h 16(CHAR) Disk name / comment. 10h 1 00h (ASCII comment terminator). 11h 9 Reserved (00h). 1Ah 1 Write protect flag. 00h = normal. 10h = write protected. *1 1Bh 1 Media flag. 00h = 2D, 10h = 2DD, 20h = 2HD. *2 1Ch 4(DWORD) Disk size (includes header size). 20h 4(DWORD) * 164 Track table. Offset of each track from disk start. *3 0 if track is unformatted or not used. *4 *1 Any non-zero value should be treated as write protected. *2 The tool "1DDITT" also defines the flags 30h for 1D and 40h for 1DD disks. *3 Older tools only allowed up to 160 entries. -> header size is 672 bytes. *4 At least one of the many D88 tools is known to set all unused entries at the end of the table to the end of the disk. - To get the maximum number of tracks check the first non-zero value in the table. It must be either 688 or 672. - If the disk is unformatted only the first value in the table is set (688 or 672) and the disk ends after the table. Disk Data Area: =============== Offset: 2A0h or 2B0h. Size: variable. Track: ------ - Each track starts at the offset (relative to start of disk) found in the track table. - Tracks don't have any header data. Sector: ------- Size: 10h (header) + variable data size Offset Size Meaning ------------------------------------------------------------------------------------------ 00h 1 C (cylinder) 01h 1 H (head). 02h 1 R (record/sector ID). 03h 1 N (sector size). Bytes in sector = 128 << N. 04h 2(WORD) Number of sectors in track. *1 06h 1 Density flag. 00h = double density. 40h = single density. (NP2kai comments call this the mfm_flag) 07h 1 Deleted data (DDAM) flag. 0 = normal, 10h = deleted. 08h 1 FDC status code. 00h = normal, B0h = Data CRC error, etc. 09h 5 Reserved (00h). *2 NP2Kai defines these 5 bytes as follows: 09h - Seek time (byte value) 010h-12h - Reserved 13h - RPM (byte value) "0:1.2 1:1.44" 0Eh 2(WORD) Actual data size following the sector header in bytes. --- End of sector header. 10h (variable) Sector data. *1 If this is not the same for all sectors within a certain track the disk is damaged. *2 Neko Project II stores values used for 1.44MB floppy disk emulation here. - Actual data length might not match N field value. - Sectors appear in the order in which they were read. - Sector headers without data are possible. - Sector header fields should be checked carefully since damaged image files are all too common.
Multiple Disks This format supports multiple disks in a tacked-on and haphazard manner. The only indication you have that a file contains multiple disks is the size of the file disagreeing with the indicated disk size as specified at Offset 0x1Ch. Sector Ordering: As stated above, sectors are in the order read, which may appear almost random. Because the disk geometry is specified for each sector alone, you have to deduce the total disk geometry (i.e. max cylinders, heads, etc) from inspecting all sector entries. Data Size in Sector Header: The value at offset 0x0Eh in the sector header is almost uniformly garbage in D88 images observed in the wild, and should not be used. It is additionally redundant, as you can calculate the value from the C/H/R/N values above. Although the documentation above specifies that the value should be used and could indicate an incomplete sector read, in all images observed in the wild with conflicting values, the sector data is padded out to actual size.