|
2020/01/14
Alone In The Dark for FM TOWNS could start from external SCSI CD-ROM using YSSCSICD.SYS, but it didn't play CDDA BGM. Now patch is available to enable CDDA BGM from external CD-ROM drive.
Dai Koukai Jidai 2 initially didn't start, but it was because the data disk (called data disk, but it has executable programs) was bad. I was able to start it from Towns OS V2.1 L31 GUI by double-clicking AUTOEXEC.BAT.
Newly confirmed titles:
Confirmed not to work:
TAITO Chase HQ can now run from an external SCSI CD-ROM. It was pretty difficult. The code was encrypted to begin with, but for this problem I could use the same technique that I used for Rainbow Island.
But, when I simply replaced I/O access with CD-ROM BIOS call (and YSSCSICD.SYS expanded function), it just froze. The RS232C command dump showed me an interesting output. It entered my function, but never exited. Apparently it was stuck inside my driver. Turned out Chase HQ disabled SCSI IRQ, and therefore my SCSI BIOS call never returned.
I also knew that Chase HQ reads CD-ROM files. So, the IRQs must be enabled while reading files. I looked for INT 21H for finding a file-reading function. From there I found a function in Chase HQ code that temporarily enable IRQ and then disable again. I modified my patch so that it calls IRQ-enabling function, then issues CD-ROM BIOS calls, and then calls the IRQ-disabling function. Then it appeared to be working find, until the remaining time reaches 16.999999 seconds.
It turned out while the integer part of the remaining time is 16 the program continuously sending a request to play a warning "Hurry Up" message to the CD-ROM drive. Since FM TOWNS Chase HQ was controlling the frame rate to 60 frames per seconds, I had to wait 60 times of CDDAPlay requests. Original Chase HQ program got away by just sending I/O requests without checking Drive-Ready signal nor command success or failure. If I do it with BIOS, it pretty much takes more than 1 minute, and probably not good for CD-ROM servo motor.
But, the fix was easy. I first inserted a trap code so that it sends the return address (DWORD PTR [ESP] at the beginning of CD-ROM command function, and found where it was sending the CDDAPlay command continuously. Then I modified one jump instruction so that it only plays the warning message only once when the integer part of the remaining time gets 16.
I am not that a good driver to test it all the way, but I played two rounds, and worked fine. I suppose it works ok for the rest.
By the way, if someone is trying to preserve a FM TOWNS in working condition, I assumed such a person would have no difficulty in compiling and run a C program, but is it nicer if I also upload a compiled executable? (In .EXP format)
Thanks nabe-abk (https://github.com/nabe-abk) for the file format of .EXP! Rainbow Island executable was encrypted, and it was difficult to create a patch. But, I was able to append a code to apply patches after the code is decrypted thanks to the EXP file format.
I thought the same method should work for Chase HQ, but this one crashed inside YSSCSICD.SYS. Simply sending CD Stop (AH=52H) crashes the driver, so I am suspecting it is something to do with the IRQ handler that Chase HQ may be setting up in it. (Wing Commander's CDDA didn't play due to the similar problem until I figured what was happening.)
I already took full disassembly of Chase HQ executable. I'll look into if it is setting up its own IRQ handler in it next.
YSSCSICD.SYS was returning 2-second shorter overall duration in ReadTOC (AH=54H). This issue was preventing Operation Wolf from starting. Well, while I was reading CDSD.SYS source, I thought it was returning 2 second shorter than the duration returned from the SCSI device, so I just was following it. I might have been reading the source wrong, or CDSD.SYS was wrong, or CDSD.SYS was for MSCDEX.EXE not for replacing FM TOWNS CD-ROM BIOS after all. Operation Wolf now starts from a SCSI CD-ROM drive with the newest YSSCSICD.SYS. No patch necessary.
Just to make sure some other titles happened to be working and stop functioning with the update, I have tested 5 or 6 game titles with the newest YSSCSICD.SYS and all worked fine.
The newest version is from the following.
https://github.com/captainys/FM/tree/master/TOWNS/YSSCSICD
Also a patch for running Afterburner 3 from a SCSI CD-ROM drive is ready. The program was directly beating CD-ROM I/O ports. The patch forces it to use CD-ROM BIOS. Also I patched the program so that it does not use 15KHz display mode. Other CRI games for FM TOWNS used 31KHz display mode if you start the program with the game-pad A button held down. I wonder why Afterburner 3 is different. Actually the source code revealed that if BYTE PTR DS:[00020DF4H]==1, the program uses 31KHz display mode. However, nowhere in the disassembly was writing 1 to that location. My patch forces this byte to be 1. But, the movie corrupts a little bit. Afterburner 3 is using a display mode that is not officially supported by FM TOWNS graphics BIOS. Maybe CRI could not prevent movie playback corrupt and gave up 31KHz display mode.
You will see some garbage on the right edge of the screen while playing, but shouldn't be an issue for playing.
This was a little bit tricky. I failed a few days ago, but I was forgetting about the copy protection (I though I was using the one that the protection was broken.) If you are able to read disassembly of SETUP.EXP, unprotecting it is not too difficult.
So, put Augusta CD-ROM in the SCSI drive, Program/User disk in the A drive, Towns OS V1.1 boot disk in the B drive, and boot from the B drive (REIPL B:). If you want to run it on 486DX or faster FM TOWNS FAST mode, copy TBIOS.BIN and TBIOS.SYS from Towns OS V2.1 to the Towns OS V1.1 boot floppy disk.
The executable needs to be patched, but it does run. It only starts from Towns OS V1.1 boot disk though.
If the internal CD-ROM is healthy, it can start from V2.1 L20 (with all drivers ripped), but I cannot tell why the patched version can only start from Towns OS V1.1 boot disk
YSSCSICD.SYS now supports CD-ROM BIOS function INT 93H, AH=05H/15H, CH=0FFH. This function reads CD-ROM sectors into anywhere in the low-4GB physical memory location. The original FM TOWNS CD-ROM BIOS does it with DMA. But, a real-mode driver cannot emulate this function. So, I use Unreal Mode (https://wiki.osdev.org/Unreal_Mode) to transfer sector data to high memory. With this update, RAYXANBER boots with no problem from a V1.1 L30 boot floppy disk.
I have also written a patch for starting Galaxy Force 2. Galaxy Force 2 was directly accessing I/O. This patch forces it to use BIOS. Also it makes Galaxy Force 2 run with DOS-Extender that comes with Towns OS V2.1. The difference of V1.1 and V2.1 DOS-Extender is (apparently) V1.1 DOS-Extender does not aware of any usage of UMB (640KB to 1MB area). V2.1 DOS-Extender does avoid UMB memory blocks used by the system. Also PUYOPUYO could start, but with no CDDA BGM. I have also written a patch for playing CDDA. Patches are in the GitHub.
At least Rayxanber is confirmed to be using AH=50H, CH=FFH. It is for direct reading into 32-bit address space. The original CD-ROM BIOS is most likely using DMA to implement this function. It is impossible to emulate this functionality with a real-mode driver. So, I am now looking into Unreal Mode (https://wiki.osdev.org/Unreal_Mode). Based on the example on this wiki, I wrote an experiment code that runs on FM TOWNS.
As an independent EXE, I succeeded in transferring data to high-memory. I was surprised that it is so easy to enter the Protected Mode. I was thinking I needed a bigger ritual to safely enter and exit the Protected Mode.
But, I need to do it in INT 93H handler called from the DOS Extender without breaking it. Is it possible? I am looking into the possibility right now.
Solved Wing Commander CDDA Problem!
I've written details in here Revision section.
Wing Commander CDDA Problem.
Wing Commander stubbornly does not play CDDA. At one time, it started playing, and thought I fixed the problem, and turned out I was using CDSD.SYS + CDISC2.SYS. I'm going back and forth for testing purposes.
I took a command dump using RS232C. When I start Wing Commander from Towns OS V2.1 L20, Start_Play command (AH=050H) is coming in, but both start time and end time were 00:00:00. If I start from V2.1 L31, Start_Play comman doesn't even come in during the opening demo. Instead, if I go into the Tigers' Claw Bar and press M key, the command is sent, but the times were both 00:00:00.
I can imagine two possibilities:
(1) AH=54H (Read_TOC) is not able to pass information to the protected mode.
(2) Track number for CDDA is not right.
If I am able to see memory and register dumps, I will have a better idea. Agh!!! I need FM TOWNS version of 386DEBUG.EXE!!!! Why did I throw away when I left Japan!!!! Curse me!!!!
I at least confirmed that the TOC is read to DS:DI during Read_TOC BIOS command (54H). But, what I cannot tell is if the information was passed to the protected mode by DOS Extender.
So, I am writing a device driver that sends register dump via RS232C. Wing Commander code looks to be written in C, and it is not too tight. I have a space to insert INT 77H different places.
Also, I am writing a program to write a memory dump to a specified file by INT 68H. I can only take low 1MB, but hopefully that will give a better idea of what's going on.
At least I am able to take disassembly with objdump command, but it is not very easy to read because it is in GAS expression. I want a better disassembler....
I have also succeeded in TownsOS V1.1 L30 Boot Floppy Disk. CONTROL.EXE of TownsOS V1.1 was not using I/O 3C32H. Instead, it was looking at DOS Default Drive for the path to look for RUN386.EXE and TMENU.EXP. Below is the disassembly of that part.
26c: b4 19 mov $0x19,%ah Get Current Default Drive 26e: cd 21 int $0x21 270: a2 cb 00 mov %al,0xcb Remember default drive in 0xCb, DS base is offset 0x0A50 -> 0x0A50+0xC4=0xB1B 273: a2 c4 00 mov %al,0xc4 Remember default drive in 0xC4, DS base is offset 0x0A50 -> 0x0A50+0xC4=0xB14 276: 04 41 add $0x41,%al AL=AL+'A' 278: a2 31 00 mov %al,0x31 DS base is offset 0x0A50 0x0A50+0x31=0x0A81. Drive letter for TMENU.EXP 27b: a2 16 00 mov %al,0x16 DS base is offset 0x0A50 0x0A50+0x16=0x0A66. Drive letter for RUN386.EXE 27e: a2 3e 00 mov %al,0x3e DS base is offset 0x0A50 0x0A50+0x3E=0x0A8E. Drive letter for T_OAK2.EXE 281: 3c 51 cmp $0x51,%al 'Q' drive? 283: 75 0a jne 0x28f Jump if not Q drive. 285: c6 06 c4 00 11 movb $0x11,0xc4 0x0A50+0xC4=0xB14 (0x11 is 'Q'-'A') 28a: c6 06 16 00 52 movb $0x52,0x16 Use R drive for RUN386.EXE
So, instead of writing to I/O 3C32H, I needed to use DOS INT 21H AH=0EH to change the default drive. But, if I do it in YSSCSICD.SYS, what's going to happen to AUTOEXEC.BAT? After reading through CONFIG.SYS, DOS may look for AUTOEXEC.BAT in the then-default drive which is Q. But, Q drive is not ready until MSCDEX.EXE is registered in AUTOEXEC.BAT.
So, instead of doing it in YSSCSICD.SYS, I added INT 21H AH=0EH call in SYSDRV.EXE. By using SYSDRV.EXE at the beginning of AUTOEXEC.BAT, I successfully booted from the boot floppy disk into the Towns System Software V1.1 L30 in the SCSI CD-ROM drive.
Probably most of the V1.1-based software would work with this boot disk including Wing Commander.
By the way, if you start Towns OS V1.1 in 486DX models, the CPU is too fast and mouse cursor will jump around unless you choose "Slow" mode.
Separated pages:
BIOS Redirector YSSCSICD.SYS and System Drive Changer SYSDRV.EXE
FM TOWNS Unpublished BIOS Functions and I/O Ports
As of yesterday I was able to boot from a floppy disk and then start Towns System Software V2.1 L20 in an external SCSI CD-ROM drive. But, the system software was not fully functional.
For example, if I went down to Command Mode, and then tried to go back to Towns MENU, I saw an error saying Towns OS Disc was not in the drive. Also, if I register MSCDEX.EXE at the beginning of AUTOEXEC.BAT and use files in the CD for the rest of initialization, I saw a message saying insufficient memory for TownsOS. Towns MENU somehow started, but I saw a warning message saying voice message was unavailable. V2.1 L31 was not that fortunate. After seeing insufficient memory error message, it just rebooted. Only way to start Towns MENU without that error message was postpone MSCDEX.EXE. If I placed MSCDEX.EXE immediately before CONTROL.EXE, I was able to start partially functional Towns System Software.
I knew why. FM TOWNS remembers the boot drive somewhere. Very often Towns OS look for files in the boot drive. If I am able to find where the boot-drive information is stored and re-point to the CD-ROM drive (Q drive), this problem should be gone.
The problem was, nobody knew where that information was stored. In fact, I searched hard when I was using FM TOWNS as my primary PC but could not find it. But, this time I was better equipped. I didn't have a good 8086 disassembler then, but now I can take binary to Linux and use objdump command to take disassembly. Also, I cannot run PharLap 386DEBUG on FM TOWNS, but at least I can start debugging in DOSBOX to find the entry address.
If I do nothing, CONTROL.EXE will start TMENU.EXP located in the root directory of the boot drive. Therefore, somewhere in CONTROL.EXE must be reading this information. I took disassembly of CONTROL.EXE with objdump.
As I was reading from the entry address, what caught my attention was offset 0B00H. It reads DS:[1016H] into AL, then far call to 12AB:0000, and then store returned AL back to DS:[1016H]. Immediately after that, 41H (character code of 'A') is added to AL, which is then stored to various locations preceding file names. If DS:[1016H] is the boot drive, it explains.
Then, where is this value coming from? At offset 0AFAH, IN AL,DX. The boot drive was hidden in an I/O port. The line above was telling it was I/O port 3C32H.
aee: 07 pop %es aef: 1f pop %ds af0: fc cld af1: 6a 01 push $0x1 af3: e8 ac 0e call 0x19a2 (17A2 in debugger) af6: 5a pop %dx af7: ba 32 3c mov $0x3c32,%dx I/O Unpublished afa: ec in (%dx),%al afb: c0 e8 02 shr $0x2,%al afe: 24 1f and $0x1f,%al b00: a2 16 10 mov %al,0x1016 DS:[0x1016] Base Drive, Probably. b03: 9a 00 00 80 01 lcall $0x180,$0x0 12AB:0000 runtime b08: a0 16 10 mov 0x1016,%al b0b: a2 0f 10 mov %al,0x100f b0e: 04 41 add $0x41,%al AL=AL+'A' ! Drive Letter! b10: a2 fe 0d mov %al,0xdfe Drive Letter for "TMENU.EXP" (File offset 0xFFE) b13: a2 95 0e mov %al,0xe95 Drive Letter for "\HCOPY\DELDRV.EXP" (File offset 0x1095) b16: a2 b4 0e mov %al,0xeb4 b19: a2 c8 0e mov %al,0xec8 b1c: a2 e0 0e mov %al,0xee0 b1f: a2 fa 0e mov %al,0xefa b22: a2 0e 0f mov %al,0xf0e b25: a2 17 0d mov %al,0xd17 Drive Letter for "RUN386.EXE" b28: a2 27 0d mov %al,0xd27 Drive Letter for "RUN386.EXE" b2b: a2 b7 0d mov %al,0xdb7 b2e: a2 ce 0d mov %al,0xdce b31: a2 e4 0d mov %al,0xde4
Then located 12AB:0000 using 386DEBUG. It was offset 1A00H. Among them I found a function that was recognizing command parameters.
12AB:0000 1A00: e8 0d 00 CALL 0x1A10 Console Clear Screen 1A03: e8 0f 00 CALL 0x1A15 1A06: e8 1e 00 CALL 0x1A27 1A09: e8 1f 01 CALL 0x1B2B Command Parameters 1A0C: e8 e5 00 CALL 0x1AF4 Calling CD-ROM BIOS Set Idle Auto-Stop Time 1a0f: cb lret
Turned out, by /D option, I could overwrite I/O 3C32H.
'D' option 1ba0: e8 4b 00 call 0x1bee 1ba3: 74 46 je 0x1beb 1ba5: 3c 41 cmp $0x41,%al 1ba7: 7c 92 jl 0x1b3b If AL<'A' ignore. 1ba9: 3c 5a cmp $0x5a,%al 1bab: 7f 8e jg 0x1b3b IF AL>'Z' ignore. 1bad: 2c 41 sub $0x41,%al 1baf: 26 a2 16 10 mov %al,%es:0x1016 1bb3: 26 a2 0f 10 mov %al,%es:0x100f 1bb7: ba 32 3c mov $0x3c32,%dx 1bba: 8a e0 mov %al,%ah 1bbc: c0 e4 02 shl $0x2,%ah 1bbf: ec in (%dx),%al Read from I/O 0x3c32 1bc0: 80 e4 7c and $0x7c,%ah Leave Bit2 to Bit6 1bc3: 24 83 and $0x83,%al Leave Bit7, Bit1, and Bit0 1bc5: 0a c4 or %ah,%al 1bc7: ee out %al,(%dx) Write to I/O [0x3c32] 1bc8: e9 70 ff jmp 0x1b3b
So I adde /D:Q option to CONTROL.EXE, and I was able to boot from a floppy disk, and then start Towns System Software in the SCSI CD-ROM drive. That was yesterday.
However, if I wrote MSCDEX.EXE at the beginning of AUTOEXEC.BAT and then used files in the CD-ROM drive to continue initialization, I saw a message telling insufficient memory for TownsOS. This message was coming from SYSINIT.EXE. First I took this message as is, and thought if I put MSCDEX.EXE before SYSINIT.EXE, probably MSCDEX.EXE took a memory location that blocks initialization of SYSINIT.EXE.
Actually it had nothing to do with the memory. I took disassembly of SYSINIT.EXE. I couldn't find a place where it was failing to allocate memory. Actually I couldn't find it because I was not familiar with high-memory access from real mode. The code seemed to be using what's called Unreal Mode. I was not familiar with it.
I changed the strategy to carpet bombing. I searched everywhere firing INT 21H. Actually I found a function that seemed to be showing debug messages.
PUTC a12: 52 push %dx a13: 50 push %ax a14: 8a e2 mov %dl,%ah a16: ba 34 3a mov $0x3a34,%dx IO[3A34]? a19: ec in (%dx),%al a1a: 3c 52 cmp $0x52,%al 'R' a1c: 75 0e jne 0xa2c a1e: 83 c2 02 add $0x2,%dx IO[3A36]? a21: ec in (%dx),%al a22: 3c 41 cmp $0x41,%al 'A' a24: 75 06 jne 0xa2c a26: 8a d4 mov %ah,%dl a28: b4 02 mov $0x2,%ah Display Output a2a: cd 21 int $0x21 a2c: 58 pop %ax a2d: 5a pop %dx a2e: c3 ret PRINT DEBUG STRING from DX a2f: 56 push %si a30: 8b f2 mov %dx,%si a32: b4 02 mov $0x2,%ah a34: ac lods %ds:(%si),%al a35: 84 c0 test %al,%al a37: 74 07 je 0xa40 a39: 8a d0 mov %al,%dl a3b: e8 d4 ff call 0xa12 a3e: eb f4 jmp 0xa34 a40: 5e pop %si a41: c3 ret
But SYSINIT.EXE was not showing anything useful. Apparently SYSINIT.EXE shows those information only if I/O [3A34H] and [3A36H] are 'R' and 'A' respectively. I wanted to see the debug messages. I altered SYSINIT.EXE. I wrote zero to offset 0A1DH and 0A25H so that the jump instruction didn't really jump.
It worked, and SYSINIT.EXE spit out all useful information.
Then, it told that even though I changed the current working drive to Q (CD-ROM drive), SYSINIT.EXE was looking for files in the A (floppy) drive.
SYSINIT.EXE is called before CONTROL.EXE. Therefore, it was too late to change the boot drive information in CONTROL.EXE. By the way, it turned out [3A34H] and [3A36H] are for both read and write. I made a utility SYSINIW.EXE that enables debugging output from SYSINIT.EXE. If you run this program at the beginning of AUTOEXEC.BAT, SYSINIT.EXE will show debug information.
So, to solve this problem, I needed to modify the boot-drive information before SYSINIT.EXE by writing to I/O 3C32H. For that purpose, I made SYSDRV.EXE. Both available from GitHub.
I have added SYSDRV.EXE at the beginning of AUTOEXEC.BAT, enabled Q drive with MSCDEX.EXE before all other initializations, and used files in the CD drive for the subsequent initialization. It worked perfectly.
I am now able to boot from floppy disk into fully-functional Towns System Software V2.1 L20 in SCSI CD-ROM drive. Details of making a boot disk is in here.
FM TOWNS Internal CD-ROM to SCSI CD-ROM Redirector Driver Ver. 0.5
I need to write a lot of findings. But, I went ahead and released my FM TOWNS Internal CD-ROM to SCSI CD-ROM Redirector driver.
https://github.com/captainys/FM
I've just uploaded binary YSCDSD.SYS in there, too. I've never imagined I could come all the way here in 20 days.
A very simple explanation is this driver is for saving Fujitsu FM TOWNS with a dead internal CD-ROM drive. FM TOWNS was the world first computer that had CD-ROM drive as a standard equipment. Therefore, all FM TOWNS has an internal CD-ROM drive. However, because it was done very early, the CD-ROM is neither SCSI nor IDE. The specification is not open. Once broken, there was little hope of repair. Already there had been drivers called CDSD.SYS and CDISC2.SYS. But, I cannot make a boot floppy image or a boot hd image public because the licensing term of CDSD.SYS tells I can redistribute the source code, but not binary. I wanted to get a permission from the developer, but I cannot find a contact information. And, the emulation was far from perfect anyway. If you know how to use CDSD.SYS and CDISC2.SYS, you may have lines in CONFIG.SYS like:
DEVICE=CDSD.SYS ....
DEVICE=CDISC2.SYS ....
You can simply replace these two lines with:
DEVICE=YSSCSICD.SYS
The driver automatically searches for a SCSI CD-ROM drive. Therefore you don't have to specify SCSI ID. Once loaded and found a SCSI CD-ROM drive, it will redirect internal CD-ROM BIOS call to SCSI BIOS call. By making a boot floppy or boot partition in the hard drive, you can start a CD-ROM based game titles. I think it emulates CD-ROM BIOS better than CDSD.SYS and CDISC2.SYS. At least I confirmed Afterburner II and Splatter House works.
Also, with CDSD.SYS and CDISC2.SYS, you had to reboot FM TOWNS every time you change a CD-ROM media. My driver, YSSCSICD.SYS, detects media change.
CDISC2.SYS was doing very complicated thing. It receives commands from MSCDEX.EXE and pass to CDSD.SYS. Also it translates direct CD-ROM BIOS calls in a format that MSCDEX.EXE would send, which is then passed to CDSD.SYS. The result is also re-translated to the format of CD-ROM BIOS. I just keep my YSSCSICD.SYS simple. It just overrides CD-ROM BIOS. MSCDEX.EXE sends requests to TOWNS_CD device driver, which then calls CD-ROM BIOS, which is intercepted by my driver, and translated to SCSI BIOS call.
As a side product, I finally figured where the system drive was written. FM TOWNS always look for TMENU.EXP in the boot drive. If you boot from A drive, it looks for A:\TMENU.EXP. If you boot from Q drive, it looks for Q:\TMENU.EXP . When I was using an FM TOWNS as my primary PC, I was always wondering where the information was written.
It is in bit2 to bit6 of I/O address 0x3c32. This is an unpublished I/O. I found by reading disassembly of CONTROL.EXE. This I/O address is for R/W. And, bit7, bit1, and bit0 may have a meaning. CONTROL.EXE when /D option is used to change the system drive, also updates 0x3c32, but it first read 0x3c32 and preserved bits 7, 1, and 0.
I should be able to make a boot floppy that starts Towns MENU. I tried on the emulator UNZ.EXE, but it crashed. I'll see if it works in the real hardware. Wing Commander is started from Towns MENU. I am hoping I find a way to do so.
Although there are some issues, I really thank developers of CDSD.SYS and CDISC2.SYS for releasing the source code.
Major development in the new driver for replacing CDSD.SYS and CDISC2.SYS. I was able to:
I was worried about unpublished functions 61H and 0FH, and indeed my driver crashed after issuing 0FH at first. But, it turned out the cause of crash was my implementation of AH=053H which returns the play state. When CDDA is playing, this function must return AL=1, and play state in the 10-byte buffer from DS:DI. If not playing, it should return AL=0, and do not touch the 10-byte buffer. However, my driver was destroying this 10-byte buffer when CDDA was not playing. I modified my code so that it does not touch the buffer, and it started working.
But, currently I can pause but cannot stop. Also the play state is incorrect when CDDA is paused. SCSI2 command Read Sub-Channel (42H) gives the play state, which should be 11H if playing and 12H if paused. But, I have a feeling that this function is actually returning play state=11H even when CDDA is paused. I'll verify tomorrow. CDISC2.SYS source looks to be caching PAUSE state. Maybe many SCSI drives incorrectly report play state=11H even when CDDA is paused.
Also STOP PLAY/SCAN command (4EH) may be either non-standard command or SCSI-3 command, and SCSI2 CD drive may not understand it. I can force CDDA by Seek command, but I don't want to move the head unnecessarily. I may have to use PAUSE command and cache if it is pause or stop.
I'm going to open source and binary here once all the functions are working.
I have been playing with INT 93H, AH=0FDH on actual FM TOWNS II MX unit. So far I was able to get meaningful return from INQURY and READ_TOC commands.
I initially thought I can make a small modification to CDISC2.SYS to bypass CDSD.SYS. But, I have realized that CDISC2.SYS was doing two things:
I don't understand why CDISC2.SYS needs to receive calls from MSCDEX.EXE and redirect to CDSD.SYS. If the only purpose is to redirect internal CD-ROM to external SCSI CD-ROM, only redirecting INT 93H, AL=0C0H to CDSD.SYS should be adequate. If redirection of MSCDEX.EXE is necessary, I cannot make a small program that allows to use external SCSI CD-ROM drive in place for internal CD-ROM drive.
But, there is a high probability that CDSD.SYS has a lot of cache, which did not allow in-place call. If so, I may be able to make even simpler redirector, but I need to write the driver from scratch.
Success in finding and adding un-emulated function in CDISC2.SYS was very encouraging to me. Actually, I wish I could upload boot floppy images that can start a game title from an external SCSI CD-ROM drive for as many game titles as possible in here, but what's blocking me is the license clause of CDSD.SYS. I am allowed to redistribute source files. But, I am not allowed to redistribute binary. I have a feeling that the developer wouldn't care at this time. But, I cannot find a contact of the developer.
Rather I am looking into the possibility of eliminating the dependency of CDISC2.SYS on CDSD.SYS. The source files of CDSD.SYS is open. So, I just need to replicate the functionality of CDSD.SYS inside CDISC2.SYS. The source file of CDSD.SYS is using an unpublished function of FM-R/TOWNS SCSI BIOS, INT 93H AH=0FDH. A comment in the CDSD.SYS tells it is "Direct Command Function". I looked for the exact definition of this function. I looked in:
Interblog, Official Technical Manual for Fujitsu FM-R Series, BNN, 1989
Noriaki Chiba, FM TOWNS Technical Guidebook, ASCII, 1989
Both has a section talking about SCSI BIOS (rather described as Disk BIOS), but INT 93H AH=0FDH was nowhere to find. What I could guess from the CDSD.SYS source files are:
INT 93H | |
AH | Command Code 0FDH |
DS:DI | Pointer to the SCSI-command structure |
CH | LUN (Unit number) LUN looks to be different from SCSI ID. But, looks like I can just say 0. Maybe SCSI adapter ID? If so, FM TOWNS has just one. |
CL | 00H |
AL | Lower 4 bits: SCSI ID Higher 4 bits 1011 (SCSI device) |
DS:DI | |
Word Ptr [DS:DI] | Data Read Buffer Address |
Word Ptr [DS:DI+2] | Data Read Buffer Segment |
[DS:DI+4~] | SCSI Command (Max 12 bytes) |
Return | |
CH | Error Coe 0:No error 2: Probably parameter error 4:Meaning unknown |
AX | A value is returned, but the meaning is unknown. |
CDSD.SYS source file is using this function as:
int 93h
xchg al,ah
or ah,ah
jz ExPhase2
stc
ExPhase2:
It is using AL as the error code. As far as I tested, it is incorrect. Another bug in CDSD.SYS for FM-R/TOWNS.
I have tested this function from my test program on FM TOWNS emulator UNZ.EXE. I issued INQUIRY command to a virtual hard drive. If I issue INQUIRY to a SCSI ID where the virtual hard drive is connected, I had CH=0. Otherwise I had CH=2. In both cases AX=0.
Apparently INT 93H AH=0FDH does not tell how many bytes were read from the device. I first suspected AX should be it, but I got zero from INQUIRY. I then checked first two bytes of the data buffer, but it was zero, too.
I also tried to read disassembly of this function. I was able to figure that this function is using DMA to read data from a SCSI device. It is using DMA, but it runs a busy wait until the operation is over. I also found a location where looks to be sending SCSI commands, but I couldn't find a place calling this routine.
567b: 8b 1e 1c 05 mov 0x51c,%bx 0x051c=Counter. 567f: 8b 14 mov (%si),%dx -> AH=0FDH, SCSI Disk -> DX=0x0C30 IO[0x0C30]=SCSI Data Register RedBook pp. 262 5681: 1e push %ds 5682: 8b 3e 12 05 mov 0x512,%di Pointer to SCSI command array 5686: 8e 1e 14 05 mov 0x514,%ds Pointer to SCSI command array 568a: 8a 01 mov (%bx,%di),%al 568c: ee out %al,(%dx) 568d: 1f pop %ds 568e: ff 06 1c 05 incw 0x51c 5692: c3 ret
This may be called as an IRQ handler for Data Request from a SCSI device. Well, then I don't know why it is not returning by IRET.
And, I figured AX and CH carry some return information by reading the disassembly, but the meaning of AX is yet to be determined. But, CDSD.SYS is not using AX anyway. So, it may not matter for my purpose.
By the way, this SCSI BIOS function is internally using unpublished function of the timer BIOS, INT 97H AH=010H/011H. It looks to be an interval timer, but the meaning is yet to be found.
Updated CDISC2.SYS!
First thing first, I've uploaded the updated CDISC2.SYS here.
Please do not throw away a FM TOWNS with a dead internal CD!
You just need a boot floppy disk or boot partition on your hard drive, but I have written how you can set up your CDSD.SYS and CDISC2.SYS to emulate the internal CD-ROM drive with an external SCSI CD-ROM drive. The problem was that many popular game titles didn't run from an external SCSI CD-ROM drive. I found one of the reasons. CDISC2.SYS was not emulating one function, specifying idle time before stopping the CD-drive motor.
The situation was INT 93H with AH=052H and CH=0FFH. Splatterhouse (namco ported by VING) was stopping in an infinite loop in the following location. By the way I figured that I can trace very beginning of .EXP in a DOS Emulator and the original Pharlap 386DEBUG.
15334B MOV AX,052C0H MOV CX,0FF00H INT 93H CMP AH,00 JNE 15334B
The fix for this problem was extremely easy:
CDStop proc near ; YS This function (CH==0FFH) does not exist in SCSI-2 command ; YS But, at least it shouldn't return an error. ; AH=52H, CH=0FFH means set sleep timer. cmp ch,0ffh jne @f mov ah, 0 ret @@:
With this fix, now I can start Splatterhouse and Flying Shark. Due to time constraints I tested only these two titles. But I suspect more titles would run with this fix. Either case, you would need a boot floppy or boot partition to start a game. Have I written how to set up a boot floppy? Maybe not. In short, what you need to do is:
Or, if you have a working hard drive, or hard drive emulator like SCSI2SD, you can make a small bootable partition with all device drivers from the games you want to boot, and write a launcher batch file that only update CONFIG.SYS and AUTOEXEC.BAT and REIPL to the drive. REIPL is a FM TOWNS's command that allows you to boot from any bootable drive.
I really want to make a bunch of boot-floppy images for the games I have and open here. BUT, CDSD.SYS does not permit re-distribution of binary. I want to get a permission from the developer, but the contact information is not on README. Even if there is, I don't know if the same EMail is active, and I'm stuck.
Maybe I should learn how to control SCSI from FM Towns and write my own. I'll see.
Since I was able to enable at least two additional games with CDISC2.SYS, I'll go into this track deeper. I'm still looking for a reason why no BGM from Wing Commander for FM TOWNS if I start from the external SCSI drive.
Sad news. I was hoping those titles that do not run with CDSD.SYS and CDISC2.SYS were not running because those were using unpublished CD-ROM BIOS functions. I was wrong. I have tested on the emulator Splatter House and Hishozame (Flying Shark) with modified CDISC2.SYS that would fall into an infinite loop if a hidden function is used. Then I would be able to see what hidden function was used in the emulator's register dump. Actually by that I found MSCDEX.EXE was using a hidden function 0FCH, but the purpose is unknown. It just passes. But both Splatter House and Flying Shark did not hit my trap.
The possibilities are either CDISC2.SYS emulation is imperfect or those titles are directly beating CD-ROM I/O.
Damn! If only I had 386DEBUG.EXE for FM TOWNS! Actually I had a chance to try Pharlap's original 386DEBUG.EXE, but it uses INT 15H, which is not implemented on FM TOWNS. Therefore it didn't run. Whoever outbid me in Yahoo! auction, I hope you are really using them for a good purpose! If you are just keeping for your collection, I'll curse you!
The hope is it is simply because CDISC2.SYS's emulation is imperfect. Then I should be able to improve it so that more titles can run. If at least I can capture commands shot at CD-ROM BIOS.... I can catch them by modifying CDISC2.SYS, but the problem is how can I transmit them to outside of FM TOWNS's RAM?
Serial port! I should be able to transmit all the commands shot at CDISC2.SYS via RS232C! But I don't know if it is ok to call RS232C BIOS from inside of CDISC2.SYS. I feel it would be better if I directly beat RS232C I/O. What is RS232C I/O of FM TOWNS?
That's just Intel 8251! I have used that chip intensively while I was writing RS232C utilities for FM-7. I know how to use it! So, I wrote a short test code with MASM. I knew 8251, but I first could not figure how I should configure timer that generates baud rate. I had to read disassembly of RS232C BIOS, but I figured it. I was able to send letters "YS" at 19200bps from FM TOWNS to Tera Term from 8086 assembly. I think my assembly programming skill is as sharp as when I was an undergrad. Only it doesn't do anything good for my real job :-P
If you assemble and run on FM TOWNS, FM TOWNS will send two letters "YS" at 19200bps, 1 stop bit, No parity to RS232C port.
Then I should modify CDISC2.SYS so that it transmit every CD-ROM BIOS commands and maybe parameters to RS232C. Then at least I'll know the last CD-ROM BIOS command before the program crashed.
I was believing that CD-ROM BIOS (and disk bios) is installed from the ROM since FM TOWNS needs to boot from the CD-ROM drive. I was wrong. CD-ROM BIOS is from IO.SYS on the CD. It depends on the different TownsOS version then.
I guess in that case it would also be better disassembling the boot ROM before putting my FM TOWNS on the logic analyzer. Since that will receive the byte data from the first sectors of IO.SYS, I should be able to intercept those bytes.
What's next? My short-term goal is to increase titles that runs with CDISC2.SYS and CDSD.SYS. Maybe I should look into individual titles. I spent some time to check which titles work with current CDISC2.SYS and CDSD.SYS. I didn't have too much time actually, and was able to test only a handful of game titles, but below are what I had:
By the way, when I was using FM TOWNS as my primary computer, I didn't buy Afterburner III. I in general don't like a product that uses a famous name but that is different. For this reason, I didn't like Afterburner III. There was no such arcade. If I knew it was pretty much G-LOC, I probably bought it and played nights after nights. Why did they call it Afterburner III? They lost at least one customer just because they didn't call it appropriately G-LOC.
I believe I could play Wing Commander with CDISC2.SYS + CDSD.SYS, but no BGM. If the executable is directly accessing I/O, I need to modify the code (which is possible), but if not I could make it run by improving the emulation of CDISC2.SYS, which I also can do. In particular, if the program is using function 16H for playing CDDA, and if it is checking if the CDDA started for the presence of the CD, just redirecting function 16H to function 50H might make more titles work.
I'm experiencing light muscle pain after carrying heavy FM TOWNS 2F, II MX, FM-7, FM77AV, and FM77AV40 to the event location, deploying them, putting them on display for two days, and then packing and stored behind my desk.
I already found interesting things while reading disassembly of CD-ROM BIOS extracted from my FM TOWNS II MX. The following BIOS commands are published by Fujitsu.
This is all. However, looking at the disassembly of CD-ROM BIOS, BIOS is taking FBH to 16H are data/status commands, and 4FH to 62H are CDDA commands. Then, jump table for these commands are as follows.
00005700 02 B5 02 80 FD FF 74 E1 C3 80 3E 29 05
80 75 0C ......t...>)..u.
00005710 C6 06 29 05 82 A0 28 05 B4 11 CD 97 C3 91
14 6B ..)...(........k
00005720 14 91 14 91 14 91 14 83 14 91 14 8A 14 B8 47
0D ..............G.
00005730 8E D8 BE 39 05 8B 54 02 EC A8 80 74 0D 24 70 C0
...9..T....t.$p.
00005740 E8 03 98 8B D8 2E FF 97 0D 15 CB B8 47 0D 8E D8
............G...
00005750 80 3E 29 05 80 75 05 C6 06 29 05 81 CB 00
00 00 .>)..u...)......
00005760
4E 1C 0E 16 0E 16 0E 16
11 16 45 16 8C 16 F4 16 N.........E.....
00005770 03 17 3F 17 0E 16 0E 16 0E 16 0E 16 0E 16 0E
16 ..?.............
00005780 71 17 0E 16 82
17 B8 17 1D 18 40 18 0E 16 0E 16 q.........@.....
00005790
FB 16 43 18
70 18 DE 18 1B 19 6E
19 F0 19 D1 1A ..C.p.....n.....
000057a0 0F 1B 46 1B A3 1B 0E 16 0E 16 0E 16 0E 16 0E
16 ..F.............
000057b0 0E 16 0E 16 C9
1B F9 1B 00 00 00 00 00 68 47 0D .............hG.
000057c0 1F 8A 46 03
BF 58 15 3C 16 7F 04 3C FB 7D 0F 2C ..F..X.<..<.}.,
000057d0 50 BF 84 15 3C
12 7F 04 3C FF 7D 02 33 FF B4 01 P...<..<.}.3...
000057e0 0B FF 74 14 98 8B
D8 8A 46 02 24 0F B4 80 B9 04 ..t.....F.$.....
000057f0 00 3C 01 73 03 E8 19
00 80 FC 80 75 03 89 4E 06 .<.s.......u..N.
-------------------------------------
Light blue bytes and following yellow bytes and blue bytes are for command 00H to 16H. Pink bytes are for FBH to FFH. Blue bytes and green bytes are for 50H to 62H. Actually yellow bytes also correspond to 4FH. Among them 0E 16 (160EH) are no function, and just returns error code. Other addresses are assigned a function. If CD-ROM BIOS is called with command code AH=FBH, it will jump to CS:0000, which is the re-entrance of the IRQ handler. It probably would crash the system with stack overflow. Command FCH will jump to 1C4EH, which is the same function as 00H, but it does not check the value of the drive mode.
Also, because there is overlap on yellow and blue bytes, command 16H must work same as 50H, and 4FH as 15H. Also 57H, 58H, 60H, and 61H have an assigned function, but I haven't explored yet.
Looking at the source code of CDISC2.SYS, it is only re-directing BIOS call for the published commands. Those game titles that do not work with CDISC2.sys may be directly accessing internal CD-ROM I/O (in which case I need to patch the executable), or may simply be using unpublished commands, or using 16H as 50H, or 4FH as 15H. More titles may work if I add support for those commands in CDISC2.SYS.
I should be able to verify if the program is using these functions by patching a state file of FM TOWNS emulator UNZ.exe. I continue exploration.
My work on FM-7 and FM77AV has achieved pretty much what I wanted to do. I shift my focus to FM TOWNS. I had grown up with FM TOWNS series. I don't let them die without resisting. I have one FM TOWNS II MX unit with a half-functioning internal CDROM drive. It barely boot from the pressed CDs, but no CDDA. It doesn't even recognize CD-Rs. Apparently broken internal CDROM is a common problem in preserving FM TOWNS units in working condition.
I have heard about reverse-engineering projects, but none seems to have succeeded. What makes me somewhat sad is all of those projects starts outside of Japan. FM TOWNS was born in Japan, but Japanese people doesn't seem to care about preserving the heritage. It is similar to Japanese Zero fighters. All of the flyable Zero fighters are outside of Japan. One person tried to keep one flyable in Japan, but could not get funding, and I believe it is no longer flying. Quite sad, isn't it.
I have a technical specification called the "Red Book" that I salvaged from my parents' home (before thrown away.) For experimenting, there is an excellent FM TOWNS emulator called UNZ, and MAME seems to have certain level of emulation of FM TOWNS. The source code gives good information, too. UNZ actually is converting internal CDROM commands to SCSI command to emulate the internal CDROM. If so, if I make a hardware emulator that translates FM TOWNS's internal CDROM commands to SCSI command, I should be able to build an adapter that is inserted between FM TOWNS motherboard and a SCSI CDROM drive. Once I finds the specification, it should be doable with an FPGA or maybe even Arduino.
The problem is between the I/O port and the CDROM unit. FM TOWNS has a one-chip microcomputer that translates I/O write to the command that CDROM drive can understand, and then translates CDROM command feedback to the I/O port. What this one-chip microcomputer does is not open. Internal CDROM drive's pinout is not open either. GND pins I must be able to figure by tester. If I can pin point the one-chip microcomputer, I may able to use tester to find which of the 40pins are data pins. Actually two of the 40 pins may be for audio, in which case I should not connect my FPGA pins to those.
Here are my goals.
Long term:
Mid term:
Short term:
Comments are welcome. Send E-Mail to: |