wwarthen / RomWBW

System Software for Z80/Z180/Z280 Computers
GNU Affero General Public License v3.0
323 stars 93 forks source link

Text file corruption from FAT32 to CP/M, is it a bug or a feature ? #370

Closed skullandbones closed 7 months ago

skullandbones commented 8 months ago

@wwarthen I was noticing that my text files were being corrupted with garbage 0x1A characters at the end of the file after transferring the text file from CP/M to FAT32.

I ran the following experiment to show that the text file was being corrupted when being transferred from FAT32 to CP/M.

On Linux, I created an empty file called EMPTY.TXT and wrote the file to the FAT32 partition of the SD card.

Booted my SC126 and used

J>C:FAT COPY 4:EMPTY.TXT J:

then copied the file back to the FAT32 partition

J>C:FAT COPY J:EMPTY.TXT 4:

Using Linux, I confirmed that the copied EMPTY.TXT was still 0 bytes in length as expected.

Using Linux, I created the shorted text file which is "1\<LF>" which is 2 bytes. I called the file TWO.TXT.

I transferred TWO.TXT to CP/M

J>C:FAT COPY 4:TWO.TXT J:

In CP/M I dumped the contents of TWO.TXT

J>C:DUMP TWO.TXT

0000 31 0A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A
0010 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A
0020 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A
0030 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A
0040 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A
0050 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A
0060 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A
0070 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A

The original "1\<LF>" characters are present but with the addition of 126 0x1A control codes. This appears to be padding to a 128 byte boundary.

Subsequently, when TWO.TXT is copied back to the FAT32 partition, the addition of the 0x1A control codes remains present causing the file to be corrupted.

J>C:FAT COPY J:TWO.TXT 4:

The corruption can be seen in Linux, TWO.TXT_ORIG is a copy of the original TWO.TXT file. The file grew from 2 bytes to 128 bytes in size.

ls -al TWO*
-rw-r--r-- 1 pi pi 128 Oct 24 18:06 TWO.TXT
-rw-r--r-- 1 pi pi   2 Oct 24 18:01 TWO.TXT_ORIG

The copied TWO.TXT unexpectedly contains the 126 0x1A control codes so the file is corrupted.

hexdump -C TWO.TXT
00000000  31 0a 1a 1a 1a 1a 1a 1a  1a 1a 1a 1a 1a 1a 1a 1a  |1...............|
00000010  1a 1a 1a 1a 1a 1a 1a 1a  1a 1a 1a 1a 1a 1a 1a 1a  |................|
*
00000080

It is relatively easy to delete the corruption using a text editor in Linux.

I have also written a simple C program on CP/M to read out a text file's contents. The C program also reads the 0x1A control codes.

This suggests to me that the underlying BIOS in CP/M is only specifying file lengths in multiples of 128 bytes.

I think that this will also affect using XM.COM (xmodem) to transfer text files off out of CP/M.

Is this a bug or a feature ?

Thanks,

Dean

feilipu commented 8 months ago

A quick search would reveal the answer.

https://en.wikipedia.org/wiki/End-of-file

https://en.wikipedia.org/wiki/Substitute_character

wwarthen commented 8 months ago

Hi @skullandbones,

Really neither a bug nor a feature. More like a behavior of CP/M based on it's design.

As the links @feilipu has included indicate, 0x1A is the end-of-file character for CP/M. As you surmised, this is a characteristic of CP/M. It does not maintain a byte-level file size. It only maintains a record count (where a record is 128 bytes). CP/M 3 may have a better mechanism, but I don't remember offhand.

The FAT command operates consistently with other applications of the era and simply pads any file out to a full record using 0x1A.

In theory, FAT could look for the end-of-file character when writing files to the FAT filesystem and use that to set an accurate file size. However, there really is no reliable method for inferring a file type in CP/M. The best you could do is a flag on the command to indicate all files being transferred are to be treated as text files.

Thanks,

Wayne

skullandbones commented 8 months ago

@wwarthen well, the FAT utility is spanning the gap between the CP/M era and the modern era.

FAT32 -> CP/M : padding is added to extend the file to a 128 byte boundary. CP/M -> FAT32 : ideally the padding should be removed eg. do the opposite operation of FAT32 -> CP/M

If my understanding is correct, just like in MS-DOS, the file extensions are actively used by the OS to denote which files are executables and which files are text files.

So I agree that having a command line option for FAT to strip padding would be helpful. May be add a new command for doing CP/M -> FAT32 with padding free transfers so that the existing FAT COPY is retained ?

The padding only needs to be stripped from the last 128 byte block of the file. The real end of the text file should be detectable by searching backwards from the end of the last 128 byte block until the first non 0x1A character is detected.

COM files would be safe unless they have 0x1A bytes adjacent to the padding bytes so making the file boundary undetectable. However, even if the COM file were to be truncated, then writing the COM file back to CP/M should restore the missing 0x1A bytes of the COM file + padding. The only exception would be if the last 128 byte block was full of 0x1A bytes then in that case the end of the COM file + padding must remain in place.

At first glance, it looks to me that there is a reliable way of stripping the padding without worrying about text files versus executables.

It would be interesting to see how cpmtools deals with this issue. I have not yet tried to use cpmtools, so something else to play with.

Thanks,

Dean

wwarthen commented 8 months ago

Hi @skullandbones,

FAT32 -> CP/M : padding is added to extend the file to a 128 byte boundary. CP/M -> FAT32 : ideally the padding should be removed eg. do the opposite operation of FAT32 -> CP/M

Yes, that would be ideal. 😀

If my understanding is correct, just like in MS-DOS, the file extensions are actively used by the OS to denote which files are executables and which files are text files.

CP/M definitely does not use the extension to denote the type of file. The OS does not differentiate between text and binary files in any way. It is a convention though. It is probably reasonable to assume that a .DOC or .TXT is a text file. However, it gets messy. You will frequently find text files in the CP/M world with no extension that are sometimes text and sometimes binary.

So I agree that having a command line option for FAT to strip padding would be helpful. May be add a new command for doing CP/M -> FAT32 with padding free transfers so that the existing FAT COPY is retained ?

I would be inclined to add an option like /T to indicate text files are being copied. This is consistent with the COPY command in MS-DOS.

The padding only needs to be stripped from the last 128 byte block of the file. The real end of the text file should be detectable by searching backwards from the end of the last 128 byte block until the first non 0x1A character is detected.

COM files would be safe unless they have 0x1A bytes adjacent to the padding bytes so making the file boundary undetectable. However, even if the COM file were to be truncated, then writing the COM file back to CP/M should restore the missing 0x1A bytes of the COM file + padding. The only exception would be if the last 128 byte block was full of 0x1A bytes then in that case the end of the COM file + padding must remain in place.

At first glance, it looks to me that there is a reliable way of stripping the padding without worrying about text files versus executables.

This seems reasonable, but I would still not do it unless text file mode was explicitly requested.

It would be interesting to see how cpmtools deals with this issue. I have not yet tried to use cpmtools, so something else to play with.

I know that cpmtools has an option to turn on text file mode. I don't know what it does if it needs to pad a DOS file being transferred to CP/M. I suspect it adds 0x1A bytes as needed.

I don't have time to work on the FAT application in the near future. Feel free to work on enhancing it. However, before you start, please let me know how you are planning to approach this. I don't want to get in a situation where I don't want to accept a bunch of work!

Thanks,

Wayne

skullandbones commented 8 months ago

@wwarthen thanks for your comments. See end of this comment.

I have been looking at the end bytes of files in the CPM2.2 slice on my SC126 SD card.

C>DUMP README.TXT
<snipped>
1D80 0D 0A 4E 2E 42 2E 2C 20 61 74 20 61 20 6D 69 6E
1D90 69 6D 75 6D 2C 20 73 6F 6D 65 20 6F 66 20 74 68
1DA0 65 20 66 69 6C 65 73 20 69 6E 20 74 68 69 73 20
1DB0 75 73 65 72 20 61 72 65 61 20 6D 75 73 74 20 62
1DC0 65 20 63 6F 70 69 65 64 0D 0A 74 6F 20 75 73 65
1DD0 72 20 61 72 65 61 20 30 20 66 6F 72 20 43 50 2F
1DE0 4E 45 54 20 74 6F 20 77 6F 72 6B 20 70 72 6F 70
1DF0 65 72 6C 79 2E 0D 0A 0D 0A 2D 2D 20 57 42 57 20
1E00 33 3A 32 30 20 50 4D 20 38 2F 32 37 2F 32 30 32
1E10 31 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1E20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1E30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1E40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1E50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1E60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1E70 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

Unexpectedly, this text file has NUL padding instead of the expected 0x1A aka "SUB" aka "CTRL-Z" character padding.

I suspect that this is a slice build issue.

I attempted to add my own TE.CF into the build by placing my TE.CF file into Source/Images/Common/CPM22

In Linux I had deleted the 0x1A characters from the end of TE.CF. This is definitely a text file. However, I think my TE.COM variant is not reading it properly.

C>DUMP TE.CF
<snipped>
0280 6E 6F 6E 20 62 6C 61 6E 6B 0D 0A 23 20 63 68 61
0290 72 61 63 74 65 72 20 69 6E 20 61 20 6C 69 6E 65
02A0 20 69 73 20 6F 6E 65 20 6F 66 20 22 6C 69 73 74
02B0 42 75 6C 6C 65 74 73 22 20 2D 2D 20 6D 61 78 2E
02C0 0D 0A 23 20 37 20 63 68 61 72 61 63 74 65 72 73
02D0 20 69 6E 20 6C 6F 6E 67 0D 0A 65 64 69 74 6F 72
02E0 2E 61 75 74 6F 4C 69 73 74 20 3D 20 66 61 6C 73
02F0 65 0D 0A 65 64 69 74 6F 72 2E 6C 69 73 74 42 75
0300 6C 6C 65 74 73 20 3D 20 22 2D 2A 3E 22 0D 0A 00
0310 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0320 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0330 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0340 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0350 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0360 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0370 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

and this also has NUL character padding. The lack of a 0x1A character might be causing read problems for TE.COM.

So my question is the building of the slices expecting all pre-built files to be appropriately pre-padded to 128 byte boundaries or is the creation of the slice auto-magically inserting padding ?

FAT utility

My initial intention was just to play with CP/M but then I wanted a CP/M text editor that handles proper tab characters for Z80 assembly files (they have tab characters in) so I started to hack TE. This opened a can of worms because I built TE in CP/M instead of cross-building on Linux.

I am interested in looking at the internals of the FAT utility and its build environment as this would give me some insight. Lets see how that goes first before I commit to some proof of concept.

I think me looking at cpmtools would also give me some background understanding.

Thanks,

Dean

skullandbones commented 8 months ago

@wwarthen a follow-up to my previous comment.

I used my TE.COM to open and save TE.CF and now the 0x1A padding characters appeared.

C>DUMP TE.CF
<snipped>
0280 6E 6F 6E 20 62 6C 61 6E 6B 0D 0A 23 20 63 68 61
0290 72 61 63 74 65 72 20 69 6E 20 61 20 6C 69 6E 65
02A0 20 69 73 20 6F 6E 65 20 6F 66 20 22 6C 69 73 74
02B0 42 75 6C 6C 65 74 73 22 20 2D 2D 20 6D 61 78 2E
02C0 0D 0A 23 20 37 20 63 68 61 72 61 63 74 65 72 73
02D0 20 69 6E 20 6C 6F 6E 67 0D 0A 65 64 69 74 6F 72
02E0 2E 61 75 74 6F 4C 69 73 74 20 3D 20 66 61 6C 73
02F0 65 0D 0A 65 64 69 74 6F 72 2E 6C 69 73 74 42 75
0300 6C 6C 65 74 73 20 3D 20 22 2D 2A 3E 22 0D 0A 0D
0310 0A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A
0320 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A
0330 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A
0340 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A
0350 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A
0360 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A
0370 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A

so this suggests an issue with the slice image generation causing the 0x1A padding characters to be missing.

Dean

wwarthen commented 8 months ago

Hi @skullandbones,

@wwarthen thanks for your comments. See end of this comment.

I have been looking at the end bytes of files in the CPM2.2 slice on my SC126 SD card.

Unexpectedly, this text file has NUL padding instead of the expected 0x1A aka "SUB" aka "CTRL-Z" character padding.

I suspect that this is a slice build issue.

The slice build uses cpmtools to add all files. Looks like it is padding with nuls instead of 0x1A. This is not an issue per se because a CP/M text file should have the 0x1A end-of-file byte already in place.

I attempted to add my own TE.CF into the build by placing my TE.CF file into Source/Images/Common/CPM22

In Linux I had deleted the 0x1A characters from the end of TE.CF. This is definitely a text file. However, I think my TE.COM variant is not reading it properly.

C>DUMP TE.CF
<snipped>
0280 6E 6F 6E 20 62 6C 61 6E 6B 0D 0A 23 20 63 68 61
0290 72 61 63 74 65 72 20 69 6E 20 61 20 6C 69 6E 65
02A0 20 69 73 20 6F 6E 65 20 6F 66 20 22 6C 69 73 74
02B0 42 75 6C 6C 65 74 73 22 20 2D 2D 20 6D 61 78 2E
02C0 0D 0A 23 20 37 20 63 68 61 72 61 63 74 65 72 73
02D0 20 69 6E 20 6C 6F 6E 67 0D 0A 65 64 69 74 6F 72
02E0 2E 61 75 74 6F 4C 69 73 74 20 3D 20 66 61 6C 73
02F0 65 0D 0A 65 64 69 74 6F 72 2E 6C 69 73 74 42 75
0300 6C 6C 65 74 73 20 3D 20 22 2D 2A 3E 22 0D 0A 00
0310 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0320 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0330 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0340 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0350 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0360 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0370 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

and this also has NUL character padding. The lack of a 0x1A character might be causing read problems for TE.COM.

By deleting the 0x1A at the end of the file, you made it an invalid text file. I'm not surprised that would cause problems for TE.COM.

So my question is the building of the slices expecting all pre-built files to be appropriately pre-padded to 128 byte boundaries or is the creation of the slice auto-magically inserting padding ?

The slice build process is simply using cpmtools. cpmtools will definitely pad with something as needed to produce 128-byte aligned files. From your testing, I guess it is nuls.

FAT utility

My initial intention was just to play with CP/M but then I wanted a CP/M text editor that handles proper tab characters for Z80 assembly files (they have tab characters in) so I started to hack TE. This opened a can of worms because I built TE in CP/M instead of cross-building on Linux.

I am interested in looking at the internals of the FAT utility and its build environment as this would give me some insight. Lets see how that goes first before I commit to some proof of concept.

In case you haven't already found it, the FAT utility source is in GitHub at https://github.com/wwarthen/FAT. This utility is not built as part of RomWBW itself because it is a C application and I don't want to include the (very large) SDCC build tools for that. So, it is maintained separately.

I think me looking at cpmtools would also give me some background understanding.

Definitely worth a look.

Thanks,

Wayne

wwarthen commented 8 months ago

HI @skullandbones.

@wwarthen a follow-up to my previous comment.

I used my TE.COM to open and save TE.CF and now the 0x1A padding characters appeared.

C>DUMP TE.CF
<snipped>
0280 6E 6F 6E 20 62 6C 61 6E 6B 0D 0A 23 20 63 68 61
0290 72 61 63 74 65 72 20 69 6E 20 61 20 6C 69 6E 65
02A0 20 69 73 20 6F 6E 65 20 6F 66 20 22 6C 69 73 74
02B0 42 75 6C 6C 65 74 73 22 20 2D 2D 20 6D 61 78 2E
02C0 0D 0A 23 20 37 20 63 68 61 72 61 63 74 65 72 73
02D0 20 69 6E 20 6C 6F 6E 67 0D 0A 65 64 69 74 6F 72
02E0 2E 61 75 74 6F 4C 69 73 74 20 3D 20 66 61 6C 73
02F0 65 0D 0A 65 64 69 74 6F 72 2E 6C 69 73 74 42 75
0300 6C 6C 65 74 73 20 3D 20 22 2D 2A 3E 22 0D 0A 0D
0310 0A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A
0320 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A
0330 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A
0340 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A
0350 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A
0360 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A
0370 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A 1A

so this suggests an issue with the slice image generation causing the 0x1A padding characters to be missing.

This is what all CP/M text editors are expected to do. It does not mean there is an issue with slice generation because cpmtools expects the files to already include the 0x1A.

I do see that there is a "-t" option in the cpmtools cpmcp program. However, it just deals with line ending conversion between Unix-like and Windows OSes.

It is fair to say that the RomWBW slice build process does not make any attempt to detect text files and modify them for CP/M. This is by design. All slice source files are expected to be binary compatible with CP/M without modification.

Thanks,

Wayne

skullandbones commented 8 months ago

@wwarthen I have got the cpmtools to work on my Raspberry Pi 4.

I need to gather more results together but so far it seems that cpmcp is not adding any Ctrl-Z or NULs to the end of extracted text files from the SD card or slice image files.

Also the -t option is for converting between CP/M and UNIX file formats during the copy. Therefore, -t does not directly mean text file but in practice it would be operating on text files.

Thanks,

Dean

wwarthen commented 8 months ago

Hi @skullandbones,

I need to gather more results together but so far it seems that cpmcp is not adding any Ctrl-Z or NULs to the end of extracted text files from the SD card or slice image files.

That makes sense. cpmcp would expect any text file coming from CP/M to already have the ctrl-Z at the end. Additionally, any file coming from CP/M would already be padded to the 128-byte boundary, so no need to add anything.

Also the -t option is for converting between CP/M and UNIX file formats during the copy. Therefore, -t does not directly mean text file but in practice it would be operating on text files.

OK, that is consistent with my understanding of the -t option.

Thanks,

Wayne

MiguelVis commented 8 months ago

Hi @skullandbones.

TE is a CP/M application, so it expects CP/M conventions about text files: 0x1A at the end, except when the last record is full of valid text data.

As I use MESCC (a Small-C derived compiler) to build TE, its i/o file library takes care about padding records with 0x1A, etc.

Yes, I'm the TE author.

skullandbones commented 8 months ago

Hi @MiguelVis many thanks for your comment.

This RomWBW issue is concerning the operation of FAT.COM in how text files are transferred from the CP/M filesystem to the external FAT32 partition.

Off-topic: The TE.COM text editor.

I have just pushed my TE modifications to https://github.com/skullandbones/te

Looking in my repository, some files have multiple Ctrl-Z characters at the end of the file due to this issue. When I remember, I manually delete the excess characters.

I was trying to find a CP/M text editor that supports tab characters because tabs will save bytes over using spaces. Also many Z80 listings use tabs.

I found your TE.COM repository 2 years ago and played with the source code. I quickly realised that TE.COM does not support tab characters so I looked at what modifications I could do. I got stuck and I put this to one side. Now I have come back to it as I am playing with RomWBW and I need a CP/M text editor.

I added TEMINCOM.COM to the TE codebase to support the Linux minicom terminal program. So I added some character escape code handling.

I adapted the key mappings to my liking.

TEMINCOM.COM shows the contents of files that have tab characters but editing is not possible. I am trying to locate the left and right cursor code with needs to jump in tab width sizes when the cursor is on top of a tab character.

I suppose that I should open an issue in your TE repository to discuss tab character handling :)

Thanks,

Dean

skullandbones commented 8 months ago

Hi @wwarthen I have created a simple Unix2Dos clone for CP/M at https://github.com/skullandbones/u2d

I used the Hi-Tech C compiler to natively build U2D.COM by doing SUBMIT U2D.SUB

u2d.c and U2D.SUB were edited in CP/M and transferred to the FAT32 partition using FAT COPY.

A limitation is that the output file is called NEWDOS.TXT. I was unsure how to delete or rename files from within ANSI C.

Anyway, this program highlights the problem of detecting the end of the text file.

The main loop in u2d.c is:

    while (fgets(buf, 2, fp_in) != NULL)
    {
        if (buf[0] == 0x1A) /* EOF marker padding */
            break;

        if (buf[0] == 0x00) /* NUL marker padding */
            break;

        if (buf[0] == 0x0D) /* CR */
            mode = 0;       /* File is already in DOS format */

        if (buf[0] == 0x0A && mode == 1) /* LF */
            fputc(0x0D, fp_out); /* Inject a CR */

        fputc(buf[0], fp_out); /* Write to new file */
    }

The while loop runs and naturally terminates at the end of the last 128 byte block of the file.

Consequently, the loop has to check whether a Ctrl-Z or a NUL character has been received and that is used to break out of the loop. The Ctrl-Z or NUL character are not part of the contents of the text file and will be the padding in the last 128 byte block of the file.

I tried to use feof() but it failed to detect Ctrl-Z.

I suspect that the NUL padding is coming from the cpmtools when the slice is created.

Anyway, U2D.COM helps me to convert Linux text files in CP/M so that ZDE.COM can show the file contents. Note that TYPE.COM seems to handle Linux text files OK.

If you look at U2D.SUB, you will see the erroneous Ctrl-Z characters at the end of the file in git. I remembered to delete the Ctrl-Z characters in u2d.c before putting the file into git.

Thanks,

Dean

feilipu commented 8 months ago

I tried to use feof() but it failed to detect Ctrl-Z.

It is worth reading the HITECH-C fgetc.as code where _IOEOF is set and also noting that the feof(p) function is defined in the STDIO.H there.

https://github.com/agn453/HI-TECH-Z80-C/blob/master/stdio/FGETC.AS

wwarthen commented 7 months ago

Closing this issue due to lack of activity. I don't think there is any specific action required at this time.