2 FUJITSU FM Towns Emulator 'eFMTowns'
4 Author : Kyuma.Ohta <whatisthis.sowhat _at_ gmail.com>
7 [FM-Towns CD-ROM based on SCSI CDROM]
11 #include "../../common.h"
12 #include "../device.h"
15 // 0 - 9 : SCSI_CDROM::
17 #define SIG_TOWNS_CDROM_PLAYING 0
18 #define SIG_TOWNS_CDROM_SAMPLE_L 1
19 #define SIG_TOWNS_CDROM_SAMPLE_R 2
20 #define SIG_TOWNS_CDROM_CDDA_PLAY 3
21 #define SIG_TOWNS_CDROM_CDDA_STOP 4
22 #define SIG_TOWNS_CDROM_CDDA_PAUSE 5
24 #define SIG_TOWNS_CDROM_SET_TRACK 0x10
25 #define SIG_TOWNS_CDROM_MAX_TRACK 0x11
26 #define SIG_TOWNS_CDROM_IS_MEDIA_INSERTED 0x12
27 #define SIG_TOWNS_CDROM_REACHED_MAX_TRACK 0x13
28 #define SIG_TOWNS_CDROM_CURRENT_TRACK 0x14
29 #define SIG_TOWNS_CDROM_START_MSF 0x15
30 #define SIG_TOWNS_CDROM_START_MSF_AA 0x16
31 #define SIG_TOWNS_CDROM_GET_ADR 0x17
32 #define SIG_TOWNS_CDROM_SET_STAT_TRACK 0x18
33 #define SIG_TOWNS_CDROM_RELATIVE_MSF 0x20
34 #define SIG_TOWNS_CDROM_ABSOLUTE_MSF 0x21
35 #define SIG_TOWNS_CDROM_READ_DATA 0x22
36 #define SIG_TOWNS_CDROM_RESET 0x23
37 #define SIG_TOWNS_CDROM_DMAINT 0x24
38 #define SIG_TOWNS_CDROM_DMAACK 0x25
39 #define SIG_TOWNS_CDROM_MUTE_L 0x29
40 #define SIG_TOWNS_CDROM_MUTE_R 0x2a
41 #define SIG_TOWNS_CDROM_MUTE_ALL 0x2b
50 typedef union SUBC_u {
65 * @note Belows are CD-ROM sector structuer.
66 * @note See https://en.wikipedia.org/wiki/CD-ROM#Sector_structure .
74 uint8_t sector_type; //! 1 = MODE1, 2=MODE2
79 * @note ToDo: Still not implement crc32 and ecc.
83 cd_data_head_t header;
85 uint8_t crc32[4]; //! CRC32 checksum.
87 uint8_t ecc[276]; //! ERROR CORRECTIOM DATA; by read solomon code.
96 cd_data_head_t header;
107 * @note ToDo: Add fake header and crc and ecc.
119 typedef union cdimage_buffer_s {
120 uint8_t rawdata[2352]; //!< @note OK?
121 cd_data_mode1_t mode1;
122 cd_data_mode2_t mode2;
123 cd_audio_sector_t audio;
127 // From Towns Linux : include/linux/towns_cd.h
157 CCD_TOC_ENTRIES = 0x101,
160 CCD_PREGAP_MODE = 0x201,
165 CDROM_READ_MODE1 = 1,
166 CDROM_READ_MODE2 = 2,
168 CDROM_READ_AUDIO = 4,
172 CDROM_COMMAND_SEEK = 0x00,
173 CDROM_COMMAND_READ_MODE2 = 0x01,
174 CDROM_COMMAND_READ_MODE1 = 0x02,
175 CDROM_COMMAND_READ_RAW = 0x03,
176 CDROM_COMMAND_PLAY_TRACK = 0x04,
177 CDROM_COMMAND_READ_TOC = 0x05,
178 CDROM_COMMAND_READ_CDDA_STATE = 0x06,
179 CDROM_COMMAND_1F = 0x1f,
180 CDROM_COMMAND_SET_STATE = 0x80,
181 CDROM_COMMAND_SET_CDDASET = 0x81,
182 CDROM_COMMAND_STOP_CDDA = 0x84,
183 CDROM_COMMAND_PAUSE_CDDA = 0x85,
184 CDROM_COMMAND_RESUME_CDDA = 0x87,
188 // Update from Tsugaru Thanks to Yamakawa-San.
190 TOWNS_CD_STATUS_ACCEPT = 0x00,
191 TOWNS_CD_STATUS_NOT_ACCEPT = 0x01,
192 TOWNS_CD_STATUS_SEEK_COMPLETED = 0x04,
193 TOWNS_CD_STATUS_READ_DONE = 0x06,
194 TOWNS_CD_STATUS_PLAY_DONE = 0x07,
195 TOWNS_CD_STATUS_DOOR_OPEN_DONE = 0x09,
196 TOWNS_CD_STATUS_DISC_NOT_READY = 0x10,
197 TOWNS_CD_STATUS_DOOR_CLOSE_DONE = 0x10,
198 TOWNS_CD_STATUS_STOP_DONE = 0x11,
199 TOWNS_CD_STATUS_PAUSE_DONE = 0x12,
200 TOWNS_CD_STATUS_RESUME_DONE = 0x13,
201 TOWNS_CD_STATUS_TOC_ADDR = 0x16,
202 TOWNS_CD_STATUS_TOC_DATA = 0x17,
203 TOWNS_CD_STATUS_SUBQ_READ = 0x18,
204 TOWNS_CD_STATUS_SUBQ_READ2 = 0x18,
205 TOWNS_CD_STATUS_SUBQ_READ3 = 0x18,
206 TOWNS_CD_STATUS_CMD_ABEND = 0x21,
207 TOWNS_CD_STATUS_DATA_PIO = 0x21,
208 TOWNS_CD_STATUS_DATA_DMA = 0x22,
209 TOWNS_CD_STATUS_UNKNOWN = 0xff,
212 // status[1] @ status[0] == 00h
213 // From Tsugaru Thanks to Yamakawa-San.
214 // Belows are quote from cdrom/cdrom.h for Tsugaru.
215 //00H 04H xx xx CDROM BIOS re-shoots command A0H if CDROM returns this code. (0b00000100)
216 //00H 08H xx xx CDROM BIOS re-shoots command A0H if CDROM returns this code. (0b00001000)
217 //00H 0DH xx xx CDROM BIOS Checking (2ndByte)&0x0D and wait for it to be non zero. (0b00001101)
219 TOWNS_CD_ACCEPT_NOERROR = 0x00,
220 TOWNS_CD_ACCEPT_DATA_TRACK = 0x01,
221 TOWNS_CD_ACCEPT_CDDA_PAUSED = 0x01,
222 TOWNS_CD_ACCEPT_CDDA_PLAYING = 0x03,
223 TOWNS_CD_ACCEPT_04H_FOR_CMD_A0H = 0x04,
224 TOWNS_CD_ACCEPT_08H_FOR_CMD_A0H = 0x08,
225 TOWNS_CD_ACCEPT_MEDIA_CHANGED = 0x09,
226 TOWNS_CD_ACCEPT_WAIT = 0x0d,
229 // status[1] @ status[0] == 21h
230 // From Tsugaru Thanks to Yamakawa-San.
232 TOWNS_CD_ABEND_PARAMETER_ERROR = 0x01,
233 TOWNS_CD_ABEND_ERR02 = 0x02,
234 TOWNS_CD_ABEND_HARDWARE_ERROR_03 = 0x03,
235 TOWNS_CD_ABEND_HARDWARE_ERROR_04 = 0x04,
236 TOWNS_CD_ABEND_READ_AUDIO_TRACK = 0x05,
237 TOWNS_CD_ABEND_MEDIA_ERROR_06 = 0x06,
238 TOWNS_CD_ABEND_DRIVE_NOT_READY = 0x07,
239 TOWNS_CD_ABEND_MEDIA_CHANGED = 0x08,
240 TOWNS_CD_ABEND_HARDWARE_ERROR_09 = 0x09,
241 TOWNS_CD_ABEND_ERROR_0C = 0x0c,
242 TOWNS_CD_ABEND_HARDWARE_ERROR_0D = 0x0d,
243 TOWNS_CD_ABEND_RETRY = 0x0f, // Indicate RETRY ?
247 TOWNS_CD_READ_NONE = 0,
254 TOWNS_CD_UNPAUSE_CDDA,
257 /*class TOWNS_CDROM : public SCSI_CDROM */
258 class TOWNS_CDROM: public DEVICE {
260 outputs_t outputs_drq;
261 outputs_t outputs_mcuint;
262 outputs_t outputs_eot;
264 // FIFO* subq_buffer;
268 // For Debugging, will remove 20200822 K.O
272 uint32_t max_fifo_length;
273 uint32_t fifo_length;
281 bool dma_transfer_phase;
282 bool pio_transfer_phase;
287 SUBC_t subq_buffer[98]; // OK?
298 int32_t index0, index1, pregap;
305 _TCHAR track_data_path[101][_MAX_PATH];
306 _TCHAR img_file_path_bak[_MAX_PATH];
307 bool with_filename[101];
309 uint32_t cdda_start_frame;
310 uint32_t cdda_end_frame;
311 uint32_t cdda_playing_frame;
314 int cdda_repeat_count;
327 uint8_t prev_command;
328 uint8_t latest_command;
329 uint8_t reserved_command;
332 bool stat_reply_intr;
343 int event_next_sector;
344 int event_seek_completed;
346 int event_cdda_delay_play;
347 int event_cdda_delay_stop;
348 int event_delay_interrupt;
349 int event_delay_ready;
351 int event_delay_command;
367 static const uint16_t crc_table[256];
370 bool command_entered;
372 uint8_t param_pre_queue[8];
373 uint8_t param_queue[8];
375 bool command_received;
379 uint32_t max_logical_block;
389 void play_cdda_from_cmd();
390 void unpause_cdda_from_cmd();
391 void stop_cdda_from_cmd();
392 void pause_cdda_from_cmd();
394 bool is_device_ready();
397 virtual void read_a_cdda_sample();
399 void send_mcu_ready();
400 virtual void set_extra_status();
402 void set_status(bool _req_status, int extra, uint8_t s0, uint8_t s1, uint8_t s2, uint8_t s3);
403 void set_status_read_done(bool _req_status, int extra, uint8_t s0, uint8_t s1, uint8_t s2, uint8_t s3);
404 void set_status_cddareply(bool _req_status, int extra, uint8_t s0, uint8_t s1, uint8_t s2, uint8_t s3);
405 void set_status_immediate(bool _req_status, int extra, uint8_t s0, uint8_t s1, uint8_t s2, uint8_t s3);
406 virtual void set_status_extra(uint8_t s0, uint8_t s1, uint8_t s2, uint8_t s3);
407 void set_status_extra_toc_addr(uint8_t s1, uint8_t s2, uint8_t s3);
408 void set_status_extra_toc_data(uint8_t s1, uint8_t s2, uint8_t s3);
409 virtual int __FASTCALL check_cdda_track_boundary(uint32_t frame_no);
410 virtual bool seek_relative_frame_in_image(uint32_t frame_no);
411 virtual int prefetch_audio_sectors(int sectors);
412 virtual int __FASTCALL dequeue_audio_data(pair16_t& left, pair16_t& right);
414 virtual void read_cdrom();
415 virtual int read_sectors_image(int sectors, uint32_t& transferred_bytes);
417 bool check_notready_and_changed(bool force_int);
419 virtual void execute_command(uint8_t command);
421 bool __FASTCALL status_not_ready(bool forceint);
422 bool __FASTCALL status_media_changed(bool forceint);
423 bool __FASTCALL status_media_changed_or_not_ready(bool forceint);
425 void __FASTCALL status_hardware_error(bool forceint);
426 void __FASTCALL status_parameter_error(bool forceint);
427 void __FASTCALL status_read_done(bool forceint);
428 void __FASTCALL status_data_ready(bool forceint);
430 void __FASTCALL status_accept(int extra, uint8_t s2, uint8_t s3);
431 void __FASTCALL status_not_accept(int extra, uint8_t s1, uint8_t s2, uint8_t s3);
433 void __FASTCALL status_illegal_lba(int extra, uint8_t s1, uint8_t s2, uint8_t s3);
434 void set_delay_ready();
435 void set_delay_ready_nostatus();
436 void set_delay_ready_eot();
437 void set_delay_ready_cddareply();
439 uint32_t cdrom_get_adr(int trk);
441 void __FASTCALL set_dma_intr(bool val);
442 void __FASTCALL set_mcu_intr(bool val);
444 * @brief set interrupts without stat_reply_intr.
445 * @param mcu interrupt value to set.
446 * @param dma interrupt value to set.
447 * @param use_mask true when masking mcu and dma.
449 void __FASTCALL set_intrs_force(bool mcu, bool dma, bool use_mask = false);
451 void __FASTCALL make_bitslice_subc_q(uint8_t *data, int bitwidth);
452 uint16_t __FASTCALL calc_subc_crc16(uint8_t *databuf, int bytes, uint16_t initval);
454 bool open_cue_file(const _TCHAR* file_path);
455 bool parse_cue_file_args(std::string& _arg2, const _TCHAR *parent_dir, std::string& imgpath);
456 void parse_cue_track(std::string &_arg2, int& nr_current_track, std::string imgpath);
457 int parse_cue_index(std::string &_arg2, int nr_current_track);
459 virtual bool open_iso_file(const _TCHAR* file_path);
460 virtual bool open_ccd_file(const _TCHAR* file_path, _TCHAR* img_file_path);
462 virtual uint8_t read_subq();
463 virtual uint8_t get_subq_status();
464 virtual void set_subq(void);
466 virtual int get_track_noop(uint32_t lba);
467 virtual void get_track_by_track_num(int track);
468 virtual uint32_t get_image_cur_position();
470 uint32_t __FASTCALL lba_to_msf(uint32_t lba);
471 uint32_t __FASTCALL lba_to_msf_alt(uint32_t lba);
472 int __FASTCALL get_frames_from_msf(const char *s);
473 int64_t __FASTCALL hexatoi(const char *s);
474 int64_t __FASTCALL string_to_numeric(std::string s);
476 virtual void open_from_cmd(const _TCHAR* file_path);
477 virtual void close_from_cmd();
478 virtual void do_dma_eot(bool by_signal);
482 void __FASTCALL write_mcuint_signals(uint32_t val)
484 write_signals(&outputs_mcuint, val);
486 void cdrom_debug_log(const char *fmt, ...);
487 virtual const _TCHAR* __FASTCALL get_cdda_status_name(int _status);
488 virtual const _TCHAR* __FASTCALL get_command_name_from_command(uint8_t cmd);
490 inline void fetch_datareg_8()
492 data_reg.b.h = data_reg.b.l;
493 data_reg.b.l = (uint8_t)(databuffer->read() & 0xff);
495 inline void fetch_datareg_16()
497 data_reg.b.l = (uint8_t)(databuffer->read() & 0xff);
498 data_reg.b.h = (uint8_t)(databuffer->read() & 0xff);
500 bool __CDROM_DEBUG_LOG;
501 bool _USE_CDROM_PREFETCH;
504 TOWNS_CDROM(VM_TEMPLATE* parent_vm, EMU_TEMPLATE* parent_emu) : DEVICE(parent_vm, parent_emu)
506 // seek_time = 400000; // 400msec (temporary)
508 bytes_per_sec = 2048 * 75; // speed x1
509 max_logical_block = 0;
516 memset(subq_buffer, 0x00, sizeof(subq_buffer));
518 initialize_output_signals(&outputs_drq);
519 initialize_output_signals(&outputs_mcuint);
520 initialize_output_signals(&outputs_eot);
521 set_device_name(_T("FM-Towns CD-ROM drive"));
523 // For Debugging, will remove 20200822 K.O
527 virtual void initialize();
528 virtual void release();
530 virtual void reset();
531 virtual uint32_t __FASTCALL read_io8w(uint32_t addr, int *wait);
532 virtual void __FASTCALL write_io8w(uint32_t addr, uint32_t data, int *wait);
534 virtual uint32_t __FASTCALL read_io16w(uint32_t addr, int *wait);
535 virtual void __FASTCALL write_io16w(uint32_t addr, uint32_t data, int *wait);
537 virtual uint32_t __FASTCALL read_dma_io8w(uint32_t addr, int *wait);
538 virtual void __FASTCALL write_dma_io8w(uint32_t addr, uint32_t data, int *wait);
540 virtual uint32_t __FASTCALL read_dma_io16w(uint32_t addr, int *wait);
541 virtual void __FASTCALL write_dma_io16w(uint32_t addr, uint32_t data, int *wait);
543 virtual void __FASTCALL write_signal(int id, uint32_t data, uint32_t mask);
544 virtual uint32_t __FASTCALL read_signal(int id);
546 virtual void __FASTCALL event_callback(int event_id, int err);
547 virtual void __FASTCALL mix(int32_t* buffer, int cnt);
549 virtual bool process_state(FILEIO* state_fio, bool loading);
551 virtual bool mounted();
552 virtual bool accessed();
553 virtual void open(const _TCHAR* file_path);
554 virtual void close();
557 virtual void __FASTCALL write_debug_data8(uint32_t addr, uint32_t data);
558 virtual uint32_t __FASTCALL read_debug_data8(uint32_t addr);
559 virtual bool get_debug_regs_info(_TCHAR *buffer, size_t buffer_len);
560 virtual bool write_debug_reg(const _TCHAR *reg, uint32_t data);
561 bool is_debugger_available()
565 uint64_t get_debug_data_addr_space()
567 return 0x1fff; // Will change
571 virtual void set_volume(int ch, int decibel_l, int decibel_r);
572 virtual void get_volume(int ch, int& decibel_l, int& decibel_r);
573 virtual bool read_buffer(int sectors);
576 // Towns specified command
577 virtual void set_cdda_status(uint8_t status);
578 int get_track(uint32_t lba);
579 virtual double get_seek_time(uint32_t lba);
580 virtual uint8_t read_status();
581 virtual const int logical_block_size();
582 virtual const int physical_block_size();
583 virtual bool write_a_byte(uint8_t val)
587 // if(databuffer->count() >= fifo_length) {
590 databuffer->write((int)n);
593 virtual bool write_bytes(uint8_t* val, int bytes)
595 int n_count = databuffer->count();
597 (n_count >= max_fifo_length) || ((n_count + bytes) >= fifo_length)) {
600 for(int i = 0; i < bytes; i++) {
601 int d = ((int)val[i]) & 0xff ;
602 databuffer->write(d);
606 virtual bool change_buffer_size(int size)
608 if((size <= 0) || (size >= max_fifo_length) || (databuffer == NULL)) return false;
610 if(fifo_length > size) { // truncate
612 for(int i = 0; i < (fifo_length - size); i++) {
613 uint8_t dummy = (uint8_t)(databuffer->read() & 0xff);
615 for(int i = 0; i < size; i++) {
616 tbuf[i] = (uint8_t)(databuffer->read() & 0xff);
619 for(int i = 0; i < size; i++) {
620 databuffer->write(tbuf[i]);
622 } else if(fifo_length < size) {
623 for(int i = 0; i < fifo_length; i++) {
624 tbuf[i] = (uint8_t)(databuffer->read() & 0xff);
627 for(int i = 0; i < fifo_length; i++) {
628 databuffer->write(tbuf[i]);
630 // for(int i = 0; i < (size - fifo_size); i++) {
631 // databuffer->write(0);
637 uint8_t get_cdda_status()
642 void set_machine_id(uint16_t val)
644 machine_id = val & 0xfff8;
646 void set_cpu_id(uint16_t val)
651 void set_context_mpuint_line(DEVICE* dev, int id, uint32_t mask)
653 register_output_signal(&outputs_mcuint, dev, id, mask);
655 void set_context_drq_line(DEVICE* dev, int id, uint32_t mask)
657 register_output_signal(&outputs_drq, dev, id, mask);
659 void set_context_eot_line(DEVICE* dev, int id, uint32_t mask)
661 register_output_signal(&outputs_eot, dev, id, mask);
663 void set_context_dmac(DEVICE* d)
667 // For Debugging, will remove 20200822 K.O
668 void set_context_cpu(DEVICE* d)