OSDN Git Service

[VM][FMTOWNS] May buildable, still not working.
authorK.Ohta <whatisthis.sowhat@gmail.com>
Sun, 19 Jan 2020 19:42:42 +0000 (04:42 +0900)
committerK.Ohta <whatisthis.sowhat@gmail.com>
Sun, 19 Jan 2020 19:42:42 +0000 (04:42 +0900)
[VM][FMTOWNS] Still not implement some devices.
[VM][FMTOWNS][YM2612] Add YM2612 (OPN2) to vm/fmtowns tree.

27 files changed:
source/build-cmake/cmake/config_fmtowns.cmake
source/src/vm/fmtowns/CMakeLists.txt
source/src/vm/fmtowns/adpcm.cpp
source/src/vm/fmtowns/cdc.cpp
source/src/vm/fmtowns/cdc.h
source/src/vm/fmtowns/fmtowns.cpp
source/src/vm/fmtowns/fmtowns.h
source/src/vm/fmtowns/keyboard.cpp
source/src/vm/fmtowns/keyboard.h
source/src/vm/fmtowns/serialrom.cpp
source/src/vm/fmtowns/towns_cdrom.cpp
source/src/vm/fmtowns/towns_cdrom.h
source/src/vm/fmtowns/towns_common.h
source/src/vm/fmtowns/towns_crtc.cpp
source/src/vm/fmtowns/towns_crtc.h
source/src/vm/fmtowns/towns_dictionary.cpp
source/src/vm/fmtowns/towns_dmac.cpp
source/src/vm/fmtowns/towns_dmac.h
source/src/vm/fmtowns/towns_memory.cpp
source/src/vm/fmtowns/towns_memory.h
source/src/vm/fmtowns/towns_sprite.cpp
source/src/vm/fmtowns/towns_sprite.h
source/src/vm/fmtowns/towns_sysrom.cpp
source/src/vm/fmtowns/towns_vram.cpp
source/src/vm/fmtowns/towns_vram.h
source/src/vm/fmtowns/ym2612.cpp [new file with mode: 0644]
source/src/vm/fmtowns/ym2612.h [new file with mode: 0644]

index 46ddc1e..ef9d7b8 100644 (file)
@@ -19,6 +19,9 @@ set(VMFILES
   scsi_dev.cpp
   scsi_hdd.cpp
   scsi_cdrom.cpp
+
+  msm58321.cpp
+  
 )
 set(VMFILES_LIB
    noise.cpp
index db63926..439a0e8 100644 (file)
@@ -5,6 +5,7 @@ message("* vm/fm-towns")
 set(VM_FMTOWNS_DEV_SRCS
        ad7820kr.cpp
        rf5c68.cpp
+       ym2612.cpp
        
        adpcm.cpp
        cdc.cpp
index 037e3d1..aa41429 100644 (file)
@@ -8,8 +8,9 @@
 */
 
 #include "./adpcm.h"
-#include "rf5c68.h"
 #include "ad7820kr.h"
+#include "rf5c68.h"
+#include "ym2612.h"
 #include "../i8259.h"
 
 namespace FMTOWNS {
@@ -240,6 +241,10 @@ void ADPCM::write_signal(int ch, uint32_t data, uint32_t mask)
        }
 }
 
+uint32_t ADPCM::read_signal(int ch)
+{
+       return 0;
+}
 #define STATE_VERSION  1
 
 bool ADPCM::process_state(FILEIO* state_fio, bool loading)
index 5001623..122c6b8 100644 (file)
@@ -6,19 +6,24 @@
 */
 
 #include "cdc.h"
-#include "towns_cdrom.h"
 #include "../../fifo.h"
 #include "../scsi_host.h"
-#include "../scsi_dev.h"
+#include "../upd71071.h"
+#include "towns_cdrom.h"
 
 namespace FMTOWNS {
 
+// SAME AS SCSI_CDROM::
+#define CDDA_OFF       0
+#define CDDA_PLAYING   1
+#define CDDA_PAUSED    2
+
 void CDC::set_context_scsi_host(SCSI_HOST* dev)
 {
        d_scsi_host = dev;
        d_scsi_host->set_context_irq(this, SIG_TOWNS_CDC_IRQ, 0xffffffff);
        d_scsi_host->set_context_drq(this, SIG_TOWNS_CDC_DRQ, 0xffffffff);
-       d_scsi_host->set_context_bsy(this, SIG_TOWNS_CDC_BUSY, 0xffffffff);
+       d_scsi_host->set_context_bsy(this, SIG_TOWNS_CDC_BSY, 0xffffffff);
        d_scsi_host->set_context_cd(this, SIG_TOWNS_CDC_CD, 0xffffffff);
        d_scsi_host->set_context_io(this, SIG_TOWNS_CDC_IO, 0xffffffff);
        d_scsi_host->set_context_msg(this, SIG_TOWNS_CDC_MSG, 0xffffffff);
@@ -30,7 +35,7 @@ void CDC::set_context_scsi_host(SCSI_HOST* dev)
 void CDC::set_context_cdrom(TOWNS_CDROM* dev)
 {
        d_cdrom = dev;
-       d_cdrom->set_context_done(this, SIG_TOWNS_CDC_CDROM_DONE, 0xffffffff);
+       dev->set_context_done(this, SIG_TOWNS_CDC_CDROM_DONE, 0xffffffff);
 }
 
 void CDC::reset()
@@ -52,6 +57,10 @@ void CDC::reset()
        
        dma_transfer = false;
        pio_transfer = true;
+       command_type_play = false; // false = status command
+       stat_reply_intr   = false;
+       req_status        = false;
+       
        d_scsi_host->reset();
 }
 
@@ -141,7 +150,7 @@ void CDC::write_io8(uint32_t address, uint32_t data)
                }                       
                break;
        default:
-               if((addr & 0x01) == 0) {
+               if((address & 0x01) == 0) {
                        w_regs[address & 0x0f] = data;
                }
                break;
@@ -154,7 +163,7 @@ uint32_t CDC::read_io8(uint32_t address)
         * 04C0h : Master status register
         */
        uint32_t val = 0xff;
-       switch(addr & 0x0f) {
+       switch(address & 0x0f) {
        case 0x0: //Master status
                {
                        val = 0x00;
@@ -212,11 +221,10 @@ uint32_t CDC::read_io8(uint32_t address)
                                                        extra_status++;
                                                        break;
                                                case 6:
-                                                       uint32_t msf = d_cdrom->read_signal
                                                        {
                                                                uint32_t msf = d_cdrom->read_signal(SIG_TOWNS_CDROM_START_MSF_AA);
                                                                write_status(0x17, (msf & 0x00ff0000) >> 16, (msf & 0x0000ff00) >> 8, msf & 0x000000ff);
-                                                               exra_status++;
+                                                               extra_status++;
                                                        }
                                                        break;
                                                default:
@@ -316,7 +324,10 @@ void CDC::read_cdrom(bool req_reply)
        uint32_t lba1 = ((uint32_t)m1 & 0x1f) * 0x10000 + ((uint32_t)s1) * 0x100 + (uint32_t)f1;
        uint32_t lba2 = ((uint32_t)m2 & 0x1f) * 0x10000 + ((uint32_t)s2) * 0x100 + (uint32_t)f2;
        uint32_t __remain;
-       int track = get_track(lba1);
+       int track = 0;
+       if(d_cdrom != NULL) {
+               track = d_cdrom->get_track(lba1);
+       }
        if(track < 2) {
                if(lba1 >= 150) {
                        lba1 = lba1 - 150;
@@ -329,14 +340,16 @@ void CDC::read_cdrom(bool req_reply)
                        lba2 = 0;
                }
        }
-       set_cdda_status(CDDA_OFF);
+       if(d_cdrom != NULL) {
+               d_cdrom->set_cdda_status(CDDA_OFF);
+       }
        if(lba1 > lba2) { // NOOP?
                extra_status = 0;
                write_status(0x01, 0x00, 0x00, 0x00);
                return;
        }
        __remain = lba2 - lba1;
-       seek_time = get_seek_time(lba1);
+       //seek_time = get_seek_time(lba1);
        
        command[0] = SCSI_CMD_READ12;
        command[1] = 0; // LUN = 0
@@ -377,7 +390,7 @@ void CDC::stop_cdda(bool req_reply)
        command[2] = 0;
        command[3] = (uint8_t)(param_fifo->read() & 0xff); 
        command[4] = (uint8_t)(param_fifo->read() & 0xff); 
-       commadn[5] = (uint8_t)(param_fifo->read() & 0xff); 
+       command[5] = (uint8_t)(param_fifo->read() & 0xff); 
        command[6] = 0;
        command[7] = (uint8_t)(param_fifo->read() & 0xff); 
        command[8] = (uint8_t)(param_fifo->read() & 0xff); 
@@ -402,7 +415,7 @@ void CDC::stop_cdda2(bool req_reply)
        command[2] = 0;
        command[3] = (uint8_t)(param_fifo->read() & 0xff); 
        command[4] = (uint8_t)(param_fifo->read() & 0xff); 
-       commadn[5] = (uint8_t)(param_fifo->read() & 0xff); 
+       command[5] = (uint8_t)(param_fifo->read() & 0xff); 
        command[6] = 0;
        command[7] = (uint8_t)(param_fifo->read() & 0xff); 
        command[8] = (uint8_t)(param_fifo->read() & 0xff); 
@@ -415,7 +428,7 @@ void CDC::stop_cdda2(bool req_reply)
        d_cdrom->start_command();
 }
 
-void CDC::unpause_cdda(bool rea_reply)
+void CDC::unpause_cdda(bool req_reply)
 {
        uint8_t* command = d_cdrom->command;
        if(!(d_cdrom->is_device_ready())) {
@@ -427,7 +440,7 @@ void CDC::unpause_cdda(bool rea_reply)
        command[2] = 0;
        command[3] = (uint8_t)(param_fifo->read() & 0xff); 
        command[4] = (uint8_t)(param_fifo->read() & 0xff); 
-       commadn[5] = (uint8_t)(param_fifo->read() & 0xff); 
+       command[5] = (uint8_t)(param_fifo->read() & 0xff); 
        command[6] = 0;
        command[7] = (uint8_t)(param_fifo->read() & 0xff); 
        command[8] = (uint8_t)(param_fifo->read() & 0xff); 
@@ -452,7 +465,7 @@ void CDC::play_cdda(bool req_reply)
        command[2] = 0;
        command[3] = (uint8_t)(param_fifo->read() & 0xff); 
        command[4] = (uint8_t)(param_fifo->read() & 0xff); 
-       commadn[5] = (uint8_t)(param_fifo->read() & 0xff); 
+       command[5] = (uint8_t)(param_fifo->read() & 0xff); 
        command[6] = 0;
        command[7] = (uint8_t)(param_fifo->read() & 0xff); 
        command[8] = (uint8_t)(param_fifo->read() & 0xff); 
index 5f257e6..4e45175 100644 (file)
@@ -6,9 +6,8 @@
 */
 #pragma once
 
-#include "../device.h"
 #include "../../common.h"
-
+#include "../device.h"
 
 #define SIG_TOWNS_CDC_DRQ 1
 #define SIG_TOWNS_CDC_IRQ 2
@@ -32,7 +31,8 @@ protected:
        outputs_t output_dma_line;
        outputs_t output_dma_intr;
        outputs_t output_submpu_intr;
-       
+
+       DEVICE*    d_dmac;
        SCSI_HOST* d_scsi_host;
        TOWNS_CDROM* d_cdrom;
        
@@ -52,7 +52,6 @@ protected:
        bool submpu_intr_mask;
        
        bool busy_status;
-       bool busy_status;
        bool cd_status;
        bool io_status;
        bool msg_status;
@@ -60,6 +59,8 @@ protected:
        bool ack_status;
 
        uint8_t w_regs[16];
+       bool command_type_play;
+       bool stat_reply_intr;
        
        virtual void read_cdrom(bool req_reply);
        virtual void stop_cdda(bool req_reply);
@@ -100,19 +101,23 @@ public:
        virtual void set_context_scsi_host(SCSI_HOST* dev);
        virtual void set_context_cdrom(TOWNS_CDROM* dev);
 
+       void set_context_dmac(DEVICE *dev)
+       {
+               d_dmac = dev;
+       }
        void set_context_dmareq_line(DEVICE* dev, int id, uint32_t mask)
        {
-               register_output_signals(&output_dma_line, dev, id, mask);
+               register_output_signal(&output_dma_line, dev, id, mask);
        }
        
        void set_context_dmaint_line(DEVICE* dev, int id, uint32_t mask)
        {
-               register_output_signals(&output_dma_intr, dev, id, mask);
+               register_output_signal(&output_dma_intr, dev, id, mask);
        }
        
        void set_context_mpuint_line(DEVICE* dev, int id, uint32_t mask)
        {
-               register_output_signals(&output_submpu_intr, dev, id, mask);
+               register_output_signal(&output_submpu_intr, dev, id, mask);
        }
 };
 
index a1a7c24..d7b0450 100644 (file)
@@ -24,6 +24,7 @@
 #include "../io.h"
 #include "../mb8877.h"
 #include "../msm58321.h"
+#include "../noise.h"
 #include "../pcm1bit.h"
 #include "../scsi_hdd.h"
 #include "../scsi_host.h"
 #include "rf5c68.h"
 //AD7820 ADC
 #include "ad7820kr.h"
+#include "ym2612.h"
 // 80387?
 
 #ifdef USE_DEBUGGER
 #include "../debugger.h"
 #endif
 
+#include "./adpcm.h"
+#include "./cdc.h"
 #include "./floppy.h"
+#include "./fontroms.h"
 #include "./keyboard.h"
 #include "./msdosrom.h"
 #include "./scsi.h"
@@ -133,20 +138,19 @@ VM::VM(EMU* parent_emu) : VM_TEMPLATE(parent_emu)
        sprite = new TOWNS_SPRITE(this, emu);
        sysrom = new SYSROM(this, emu);
        msdosrom = new MSDOSROM(this, emu);
-       fontrom = new FONT_ROM(this, emu);
+       fontrom = new FONT_ROMS(this, emu);
        dictionary = new DICTIONARY(this, emu);
 #if defined(HAS_20PIX_FONTS)
        fontrom_20pix = new FONT_ROM_20PIX(this, emu);
 #endif
        serialrom = new SERIAL_ROM(this, emu);
        adpcm = new ADPCM(this, emu);
-       mixer = new MIXER(this, emu); // Pseudo mixer.
-       
-       
+//     mixer = new MIXER(this, emu); // Pseudo mixer.
+               
        adc = new AD7820KR(this, emu);
        rf5c68 = new RF5C68(this, emu);
-       e_volume[0] = new MB87878(this, emu);
-       e_volume[1] = new MB87878(this, emu);
+//     e_volume[0] = new MB87878(this, emu);
+//     e_volume[1] = new MB87878(this, emu);
        
        sio = new I8251(this, emu);
        pit0 = new I8253(this, emu);
@@ -156,6 +160,10 @@ VM::VM(EMU* parent_emu) : VM_TEMPLATE(parent_emu)
        rtc = new MSM58321(this, emu);
        beep = new PCM1BIT(this, emu);
        opn2 = new YM2612(this, emu);
+
+       seek_sound = new NOISE(this, emu);
+       head_up_sound = new NOISE(this, emu);
+       head_down_sound = new NOISE(this, emu);
        
        scsi_host = new SCSI_HOST(this, emu);
        scsi_host->set_device_name(_T("SCSI HOST"));
@@ -177,7 +185,6 @@ VM::VM(EMU* parent_emu) : VM_TEMPLATE(parent_emu)
 
        floppy = new FLOPPY(this, emu);
        keyboard = new KEYBOARD(this, emu);
-       memory = new TOWNS_MEMORY(this, emu);
        scsi = new SCSI(this, emu);
        timer = new TIMER(this, emu);
        
@@ -245,6 +252,7 @@ VM::VM(EMU* parent_emu) : VM_TEMPLATE(parent_emu)
        mic_in_ch = -1;
 
        // Use pseudo mixer instead of event.Due to using ADC.
+#if 0
        line_mix_ch = -1;
        modem_mix_ch = -1;
        mic_mix_ch = -1;
@@ -256,12 +264,21 @@ VM::VM(EMU* parent_emu) : VM_TEMPLATE(parent_emu)
        opn2_mix_ch = mixer->set_context_sound(opn2);
        cdc_mix_ch = mixer->set_context_sound(cdc);
        mixer->set_interpolate_filter_freq(pcm_mix_ch, 4000); // channel, freq; disable if freq <= 0.
-       
        event->set_context_sound(mixer);
-       
-       if(fdc->load_sound_data(MB8877_SND_TYPE_SEEK, _T("FDDSEEK.WAV"))) {
-               event->set_context_sound(fdc);
-       }
+#else
+       // Temporally not use mixer.
+       event->set_context_sound(beep);
+       event->set_context_sound(opn2);
+       event->set_context_sound(rf5c68);
+       event->set_context_sound(cdrom);
+#endif
+       fdc->set_context_noise_seek(seek_sound);
+       fdc->set_context_noise_head_down(head_down_sound);
+       fdc->set_context_noise_head_up(head_up_sound);
+       event->set_context_sound(seek_sound);
+       event->set_context_sound(head_down_sound);
+       event->set_context_sound(head_up_sound);
+
        
 /*     pic     0       timer
                1       keyboard
@@ -321,40 +338,43 @@ VM::VM(EMU* parent_emu) : VM_TEMPLATE(parent_emu)
        keyboard->set_context_pic(pic);
        
        sprite->set_context_vram(vram);
+       vram->set_context_sprite(sprite);
+       vram->set_context_crtc(crtc);
 
        //e_volume[0]->set_context_ch0(line_in, MB87878_VOLUME_LEFT);
        //e_volume[0]->set_context_ch1(line_in, MB87878_VOLUME_RIGHT);
        //e_volume[0]->set_context_ch2(NULL, MB87878_VOLUME_LEFT);
        //e_volume[0]->set_context_ch3(NULL, MB87878_VOLUME_RIGHT);
-       e_volume[1]->set_context_ch0(cdc, MB87878_VOLUME_LEFT);
-       e_volume[1]->set_context_ch1(cdc, MB87878_VOLUME_RIGHT);
+//     e_volume[1]->set_context_ch0(cdc, MB87878_VOLUME_LEFT);
+//     e_volume[1]->set_context_ch1(cdc, MB87878_VOLUME_RIGHT);
        //e_volume[1]->set_context_ch2(mic, MB87878_VOLUME_LEFT | MB87878_VOLUME_RIGHT);
        //e_volume[1]->set_context_ch3(modem, MB87878_VOLUME_LEFT | MB87878_VOLUME_RIGHT);
        
        memory->set_context_vram(vram);
-       memory->set_context_rom(sys_rom);
-       memory->set_context_msdos(msdos_rom);
-       memory->set_context_dictionary(dict_rom);
+       memory->set_context_system_rom(sysrom);
+       memory->set_context_msdos(msdosrom);
+       memory->set_context_dictionary(dictionary);
        memory->set_context_beep(beep);
-       memory->set_context_serial_rom(serial_rom);
+       memory->set_context_serial_rom(serialrom);
        memory->set_context_sprite(sprite);
-       memory->set_context_machine_id(machine_id);
-       memory->set_context_cpu_id(cpu_id);
+       memory->set_machine_id(machine_id);
+       memory->set_cpu_id(cpu_id);
        memory->set_context_cpu(cpu);
 
        cdc->set_context_cdrom(cdrom);
        cdc->set_context_scsi_host(cdc_scsi);
-       cdc->set_context_drq(dma, SIG_UPD71071_CH3, 0xff);
-       cdc->set_context_pic(pic, SIG_I8259_CHIP1 | SIG_I8259_IR1);
+       cdc->set_context_dmareq_line(dma, SIG_UPD71071_CH3, 0xff);
+//     cdc->set_context_pic(pic, SIG_I8259_CHIP1 | SIG_I8259_IR1);
        
-       crtc->set_context_vsync(pic, SIG_I8259_CHIP1 | SIG_I8259_IR3); // VSYNC
-       adpcm->set_context_pic(pic, SIG_I8259_CHIP1 | SIG_I8259_IR5); // ADPCM AND OPN2
+       crtc->set_context_vsync(pic, SIG_I8259_CHIP1 | SIG_I8259_IR3, 0xffffffff); // VSYNC
        adpcm->set_context_opn2(opn2);
-       adpcm->set_context_adpcm(rf5c68);
+       adpcm->set_context_rf5c68(rf5c68);
        adpcm->set_context_adc(adc);
+       adpcm->set_context_pic(pic);
+       adpcm->set_context_intr_line(pic, SIG_I8259_CHIP1 | SIG_I8259_IR5, 0xffffffff); // ADPCM AND OPN2
 
        rf5c68->set_context_interrupt_boundary(adpcm, SIG_ADPCM_WRITE_INTERRUPT, 0xffffffff);
-       opn2->set_context_interrupt(adpcm, SIG_ADPCM_OPX_INTR, 0xffffffff);
+       opn2->set_context_irq(adpcm, SIG_ADPCM_OPX_INTR, 0xffffffff);
        
        adc->set_sample_rate(19200);
        adc->set_sound_bank(-1);
@@ -394,7 +414,7 @@ VM::VM(EMU* parent_emu) : VM_TEMPLATE(parent_emu)
        io->set_iomap_single_r(0x30, memory);   // cpu id
        io->set_iomap_single_r(0x31, memory);   // cpu id
        
-       io->set_iomap_single_rw(0x32, serial_rom);      // serial rom
+       io->set_iomap_single_rw(0x32, serialrom);       // serial rom
 
        io->set_iomap_alias_rw(0x40, pit0, 0);
        io->set_iomap_alias_rw(0x42, pit0, 1);
@@ -444,21 +464,24 @@ VM::VM(EMU* parent_emu) : VM_TEMPLATE(parent_emu)
        
        io->set_iomap_range_rw(0x4c0, 0x4cf, cdc); // CDROM
        // PAD, Sound
+#if 0
        io->set_iomap_alias_r(0x4d0, pad, 0); // Pad1
        io->set_iomap_alias_r(0x4d2, pad, 1); // Pad 2
-       io->set_iomap_single_rw(0x4d5, adpcm, 0); // mute 
+       io->set_iomap_alias_rw(0x4d5, adpcm, 0); // mute 
        io->set_iomap_alias_w(0x4d6, pad, 3); // Pad out
-       
+#else
+       io->set_iomap_alias_rw(0x4d5, adpcm, 0); // mute 
+#endif 
        // OPN2(YM2612)
        io->set_iomap_alias_rw(0x4d8, opn2, 0); // STATUS(R)/Addrreg 0(W)
        io->set_iomap_alias_w(0x4da, opn2, 1);  // Datareg 0(W)
        io->set_iomap_alias_w(0x4dc, opn2, 2);  // Addrreg 1(W)
        io->set_iomap_alias_w(0x4de, opn2, 3);  // Datareg 1(W)
        // Electrical volume
-       io->set_iomap_alias_rw(0x4e0, e_volume[0], 0);
-       io->set_iomap_alias_rw(0x4e1, e_volume[0], 1);
-       io->set_iomap_alias_rw(0x4e2, e_volume[1], 0);
-       io->set_iomap_alias_rw(0x4e3, e_volume[1], 1);
+//     io->set_iomap_alias_rw(0x4e0, e_volume[0], 0);
+//     io->set_iomap_alias_rw(0x4e1, e_volume[0], 1);
+//     io->set_iomap_alias_rw(0x4e2, e_volume[1], 0);
+//     io->set_iomap_alias_rw(0x4e3, e_volume[1], 1);
 
        // ADPCM
        io->set_iomap_range_w(0x4e7, 0x4ff, adpcm); // 
@@ -495,6 +518,7 @@ VM::VM(EMU* parent_emu) : VM_TEMPLATE(parent_emu)
        io->set_iomap_range_rw(0xfd90, 0xfda0, vram);   // Palette and CRTC
 
        // Vram allocation may be before initialize().
+       /*
        bool alloc_failed = false;
        for(int bank = 0; bank < 2; bank++) {
                if(alloc_failed) break;
@@ -514,7 +538,7 @@ VM::VM(EMU* parent_emu) : VM_TEMPLATE(parent_emu)
                                memset(p, 0x00, __size);
                                renderbuffer_size[bank][layer] = __size;
                                d_renderbuffer[bank][layer] = p;
-                               d_vram->set_context_renderbuffer(p, layer, bank, width, height, stride);
+//                             d_vram->set_context_renderbuffer(p, layer, bank, width, height, stride);
                        }
                }
        }
@@ -530,6 +554,7 @@ VM::VM(EMU* parent_emu) : VM_TEMPLATE(parent_emu)
                        }
                }
        }
+       */
        // initialize all devices
 #if defined(__GIT_REPO_VERSION)
        strncpy(_git_revision, __GIT_REPO_VERSION, sizeof(_git_revision) - 1);
@@ -566,42 +591,6 @@ void VM::set_machine_type(uint16_t machine_id, uint16_t cpu_id)
                memory->set_cpu_id(cpu_id);
                memory->set_machine_id(machine_id);
        }
-       if(vram != NULL) {
-               vram->set_cpu_id(cpu_id);
-               vram->set_machine_id(machine_id);
-       }
-       if(sprite != NULL) {
-               sprite->set_cpu_id(cpu_id);
-               sprite->set_machine_id(machine_id);
-       }
-       if(sys_rom != NULL) {
-               sysrom->set_cpu_id(cpu_id);
-               sysrom->set_machine_id(machine_id);
-       }
-       if(msdos_rom != NULL) {
-               msdosrom->set_cpu_id(cpu_id);
-               msdosrom->set_machine_id(machine_id);
-       }
-       if(dictinoary != NULL) {
-               dictionary->set_cpu_id(cpu_id);
-               dictionary->set_machine_id(machine_id);
-       }
-       if(fontrom != NULL) {
-               fontrom->set_cpu_id(cpu_id);
-               fontrom->set_machine_id(machine_id);
-       }
-       if(serialrom != NULL) {
-               serialrom->set_cpu_id(cpu_id);
-               serialrom->set_machine_id(machine_id);
-       }
-       if(crtc != NULL) {
-               crtc->set_cpu_id(cpu_id);
-               crtc->set_machine_id(machine_id);
-       }
-       if(cdc != NULL) {
-               cdc->set_cpu_id(cpu_id);
-               cdc->set_machine_id(machine_id);
-       }
 #if defined(HAS_20PIX_FONTS)
        if(fontrom_20pix != NULL) {
                fontrom_20pix->set_cpu_id(cpu_id);
@@ -653,7 +642,7 @@ DEVICE *VM::get_cpu(int index)
 
 void VM::draw_screen()
 {
-       memory->draw_screen();
+       crtc->draw_screen();
 }
 
 uint32_t VM::is_floppy_disk_accessed()
@@ -682,17 +671,18 @@ void VM::initialize_sound(int rate, int samples)
        
        // add_sound_in_source() must add after per initialize_sound().
        adc_in_ch = event->add_sound_in_source(rate, samples, 2);
-       mixer->set_context_out_line(adc_in_ch);
        adc->set_sample_rate(19200);
        adc->set_sound_bank(adc_in_ch);
+#if 0  
+       mixer->set_context_out_line(adc_in_ch);
        mixer->set_context_sample_out(adc_in_ch, rate, samples); // Must be 2ch.
-
        // ToDo: Check recording sample rate & channels.
        mic_in_ch = event->add_sound_in_source(rate, samples, 2);
        mixer->set_context_mic_in(mic_in_ch, rate, samples);
 
        line_in_ch = event->add_sound_in_source(rate, samples, 2);
        mixer->set_context_line_in(line_in_ch, rate, samples);
+#endif
        emu->unlock_vm();
 }
 
@@ -717,7 +707,7 @@ void VM::clear_sound_in()
 int VM::get_sound_in_data(int ch, int32_t* dst, int expect_samples, int expect_rate, int expect_channels)
 {
        if(dst == NULL) return 0;
-       if(samples <= 0) return 0;
+       if(expect_samples <= 0) return 0;
        int n_ch = -1;
        switch(ch) {
        case 0x00:
@@ -731,7 +721,7 @@ int VM::get_sound_in_data(int ch, int32_t* dst, int expect_samples, int expect_r
                break;
        }
        if(n_ch < 0) return 0;
-       samples = event->get_sound_in_data(n_ch, dst, expect_samples, expect_rate, expect_channels);
+       int samples = event->get_sound_in_data(n_ch, dst, expect_samples, expect_rate, expect_channels);
        return samples;
 }
 
@@ -767,17 +757,18 @@ int VM::sound_in(int ch, int32_t* src, int samples)
 void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
 {
 #ifndef HAS_LINEIN_SOUND
-       if(ch >= 4) ch++;
+//     if(ch >= 7) ch++;
 #endif
 #ifndef HAS_MIC_SOUND
-       if(ch >= 5) ch++;
+//     if(ch >= 8) ch++;
 #endif
 #ifndef HAS_MODEM_SOUND
-       if(ch >= 6) ch++;
+//     if(ch >= 9) ch++;
 #endif
 #ifndef HAS_2ND_ADPCM
-       if(ch >= 7) ch++;
+//     if(ch >= 10) ch++;
 #endif
+#if 0  
        if(ch == 0) { // BEEP
                mixer->set_volume(beep_mix_ch, decibel_l, decibel_r);
        }
@@ -812,7 +803,26 @@ void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r)
        else if(ch == 9) { // HDD(ToDo)
                fdc->set_volume(0, decibel_l, decibel_r);
        }       
-
+#else
+       if(ch == 0) { // BEEP
+               beep->set_volume(0, decibel_l, decibel_r);
+       }
+       else if(ch == 1) { // CD-ROM
+               cdrom->set_volume(0, decibel_l, decibel_r);
+       }       
+       else if(ch == 2) { // OPN2
+               opn2->set_volume(0, decibel_l, decibel_r);
+       }
+       else if(ch == 3) { // ADPCM
+               rf5c68->set_volume(0, decibel_l, decibel_r);
+       }
+       else if(ch == 4) { // SEEK, HEAD UP / DOWN
+               seek_sound->set_volume(0, decibel_l, decibel_r);
+               head_up_sound->set_volume(0, decibel_l, decibel_r);
+               head_down_sound->set_volume(0, decibel_l, decibel_r);
+       }
+       
+#endif
 }
 #endif
 
@@ -899,13 +909,15 @@ bool VM::process_state(FILEIO* state_fio, bool loading)
                }
        }
        // Machine specified.
+       state_fio->StateValue(beep_mix_ch);
+       state_fio->StateValue(cdc_mix_ch);
+       state_fio->StateValue(opn2_mix_ch);
+       state_fio->StateValue(pcm_mix_ch);
        state_fio->StateValue(line_mix_ch);
        state_fio->StateValue(modem_mix_ch);
        state_fio->StateValue(mic_mix_ch);
-       state_fio->StateValue(beep_mix_ch);
-       state_fio->StateValue(pcm_mix_ch);
-       state_fio->StateValue(opn2_mix_ch);
-       state_fio->StateValue(cdc_mix_ch);
+
+       
        return true;
 }
 
index 8428a07..0e1679e 100644 (file)
 
 #ifdef USE_SOUND_VOLUME
 static const _TCHAR *sound_device_caption[] = {
-       _T("Beep"), _T("FM SSG"), _T("FM OPNB"), _T("PCM"), _T("CD-DA"),
+       _T("Beep"), _T("CD-DA"), _T("FM OPN2"), _T("ADPCM"), 
 #if defined(USE_SOUND_FILES)
        _T("FDD SEEK"),
 #endif
@@ -160,11 +160,12 @@ class I8251;
 class I8253;
 class I8259;
 class I386;
+class NOISE;
 
 class IO;
 class RF5C68;      // DAC
 class YM2612;      // OPNB
-class MB87078;     // VOLUME
+//class MB87078;     // VOLUME
 class AD7820KR;    // A/D Converter.
 class PCM1BIT;
 
@@ -199,7 +200,7 @@ namespace FMTOWNS {
        class TOWNS_MEMORY;
 
        class TOWNS_CDROM;
-       class SPRITE;
+       class TOWNS_SPRITE;
        class JOYSTICK; // Mouse and Joystick.
 }
 
@@ -212,8 +213,7 @@ protected:
        I8253* pit0;
        I8253* pit1;
        
-       I8259* pic0;
-       I8259* pic1;
+       I8259* pic;
        
        I386* cpu; // i386DX/SX/486DX/486SX?/Pentium with FPU?
 
@@ -222,17 +222,23 @@ protected:
        MSM58321* rtc;
        UPD71071* dma;
        UPD71071* extra_dma;
-       RF5C68*   dac;
-       MB87078*  e_volumes;
+       NOISE*    seek_sound;
+       NOISE*    head_up_sound;
+       NOISE*    head_down_sound;
+       
+       RF5C68*   rf5c68;
+//     MB87078*  e_volumes;
        AD7820KR* adc;
-       RF5C68*   adpcm;
        PCM1BIT*  beep;
+       YM2612*   opn2;
        
+       FMTOWNS::ADPCM*          adpcm;
        FMTOWNS::TOWNS_CRTC*     crtc;
        FMTOWNS::FLOPPY*         floppy;
        FMTOWNS::KEYBOARD*       keyboard;
        FMTOWNS::TIMER*          timer;
-       FMTOWNS::TOWNS_VRAM*     sprite;
+       FMTOWNS::TOWNS_VRAM*     vram;
+       FMTOWNS::TOWNS_SPRITE*   sprite;
        FMTOWNS::TOWNS_MEMORY*   memory;
        FMTOWNS::DICTIONARY*     dictionary;
        FMTOWNS::SYSROM*         sysrom;
@@ -248,10 +254,24 @@ protected:
        
        FMTOWNS::SCSI* scsi;
        SCSI_HOST*     scsi_host;
-       SCSI_HDD*      hdd[4]; // 
-
+       SCSI_HDD*      hdd[4]; //
+
+       int adc_in_ch;
+       int line_in_ch;
+       int modem_in_ch;
+       int mic_in_ch;
+
+       int beep_mix_ch;
+       int cdc_mix_ch;
+       int opn2_mix_ch;
+       int pcm_mix_ch;
+       int line_mix_ch;
+       int modem_mix_ch;
+       int mic_mix_ch;
+/*
        scrntype_t *d_renderbuffer[2][2]; // [bank][layer]
        uint32_t renderbuffer_size[2][2];
+*/
 public:
        // ----------------------------------------
        // initialize
@@ -291,14 +311,19 @@ public:
        // user interface
        void open_floppy_disk(int drv, const _TCHAR* file_path, int bank);
        void close_floppy_disk(int drv);
+       uint32_t is_floppy_disk_accessed();
        bool is_floppy_disk_inserted(int drv);
        void is_floppy_disk_protected(int drv, bool value);
        bool is_floppy_disk_protected(int drv);
        bool is_frame_skippable();
-       
+       void set_machine_type(uint16_t machine_id, uint16_t cpu_id);
+
+       void clear_sound_in();
+       int get_sound_in_data(int ch, int32_t* dst, int expect_samples, int expect_rate, int expect_channels);
+       int sound_in(int ch, int32_t* src, int samples);
+
        void update_config();
-       void save_state(FILEIO* state_fio);
-       bool load_state(FILEIO* state_fio);
+       bool process_state(FILEIO* state_fio, bool loading);
        
        // ----------------------------------------
        // for each device
index c254727..8ef55ec 100644 (file)
@@ -102,36 +102,26 @@ void KEYBOARD::key_up(int code)
 
 #define STATE_VERSION  1
 
-void KEYBOARD::save_state(FILEIO* state_fio)
+bool KEYBOARD::process_state(FILEIO* state_fio, bool loading)
 {
-       state_fio->FputUint32(STATE_VERSION);
-       state_fio->FputInt32(this_device_id);
-       
-       key_buf->save_state((void *)state_fio);
-       state_fio->FputUint8(kbstat);
-       state_fio->FputUint8(kbdata);
-       state_fio->FputUint8(kbint);
-       state_fio->FputUint8(kbmsk);
-       state_fio->Fwrite(table, sizeof(table), 1);
-}
-
-bool KEYBOARD::load_state(FILEIO* state_fio)
-{
-       if(state_fio->FgetUint32() != STATE_VERSION) {
-               return false;
-       }
-       if(state_fio->FgetInt32() != this_device_id) {
+       if(!state_fio->StateCheckUint32(STATE_VERSION)) {
+               return false;
+       }
+       if(!state_fio->StateCheckInt32(this_device_id)) {
+               return false;
+       }
+       if(!(key_buf->process_state((void *)state_fio, loading))) {
                return false;
        }
-       if(!key_buf->load_state((void *)state_fio)) {
-               return false;
-       }
-       kbstat = state_fio->FgetUint8();
-       kbdata = state_fio->FgetUint8();
-       kbint = state_fio->FgetUint8();
-       kbmsk = state_fio->FgetUint8();
-       state_fio->Fread(table, sizeof(table), 1);
+
+       state_fio->StateValue(kbstat);
+       state_fio->StateValue(kbdata);
+       state_fio->StateValue(kbint);
+       state_fio->StateValue(kbmsk);
+       state_fio->StateArray(table, sizeof(table), 1);
+
        return true;
 }
+
 }
 
index fe7db90..d68ed49 100644 (file)
@@ -73,8 +73,7 @@ public:
        void write_io8(uint32_t addr, uint32_t data);
        uint32_t read_io8(uint32_t addr);
        void event_frame();
-       void save_state(FILEIO* state_fio);
-       bool load_state(FILEIO* state_fio);
+       bool process_state(FILEIO* state_fio, bool loading);
        
        // unique functions
        void set_context_pic(DEVICE* device)
index a29f499..13511c7 100644 (file)
@@ -83,7 +83,7 @@ void SERIAL_ROM::initialize()
                }
        } else {
                rom[255 >> 3] = rom[255 >> 3] & 0x0f; // Clear head of 4 bits.
-               static const _TCHAR signaure[] = _T("FUJITSU");
+               static const _TCHAR signature[] = _T("FUJITSU");
                for(int i = 0; i < strlen(signature); i++) {
                        store_reversed_byte((uint8_t)(244 - (i * 8)), signature[i]);
                }
@@ -99,7 +99,7 @@ void SERIAL_ROM::initialize()
                for(int i = 0; i < 4; i++) {
                        dst <<= 1;
                        dst = dst | (tmp2 & 0x01);
-                       tmps >>= 1;
+                       tmp2 >>= 1;
                }
                tmp1 = tmp1 & 0xf0;
                rom[48 >> 3] = tmp1 | (dst & 0x0f);
@@ -253,7 +253,7 @@ bool SERIAL_ROM::write_debug_reg(const _TCHAR *reg, uint32_t data)
                return true;
        } else if((reg[0] == 'B') || (reg[0] == 'b')){
                if(strlen(reg) < 2) return false;
-               if((reg[1] == 'R') || (reg[i] == 'r')) { // Reversed bit
+               if((reg[1] == 'R') || (reg[1] == 'r')) { // Reversed bit
                        noff = 1;
                }               
                for(int i = 0; i < 3; i++) {
@@ -263,11 +263,11 @@ bool SERIAL_ROM::write_debug_reg(const _TCHAR *reg, uint32_t data)
                }
                if(strlen(numseg) < 1) return false;
                int bitpos = atoi(numseg);
-               if((pos < 0) || (pos > 255)) return false;
+               if((bitpos < 0) || (bitpos > 255)) return false;
                int bytepos = bitpos >> 3;
                int offs = bitpos & 7;
                uint8_t dst = rom[bytepos];
-               if((reg[1] == 'R') || (reg[i] == 'r')) { // Reversed bit
+               if((reg[1] == 'R') || (reg[1] == 'r')) { // Reversed bit
                        offs = 7 - offs;
                }
                dst = dst & (~(0x01 << offs));
index 5d01891..3a0c39e 100644 (file)
@@ -101,19 +101,19 @@ uint32_t TOWNS_CDROM::read_signal(int id)
                        trk = track_num;
                }
                int index0 = toc_table[trk].index0;
-               int index1 = toc_table[trk].index1
-               int pregap = toc_table[trk].pregap
+               int index1 = toc_table[trk].index1;
+               int pregap = toc_table[trk].pregap;
                uint32_t lba = (uint32_t)index0;
                if(pregap > 0) lba = lba - pregap;
                if(lba < 150) lba = 150;
                uint32_t msf = lba_to_msf(lba); // Q:lba + 150?
                stat_track++;
                return msf;
-       } eise if(id == SIG_TOWNS_CDROM_START_MSF_AA) {
-               trk = track_num;
+       } else if(id == SIG_TOWNS_CDROM_START_MSF_AA) {
+               int trk = track_num;
                int index0 = toc_table[trk].index0;
-               int index1 = toc_table[trk].index1
-               int pregap = toc_table[trk].pregap
+               int index1 = toc_table[trk].index1;
+               int pregap = toc_table[trk].pregap;
                uint32_t lba = (uint32_t)index0;
                if(pregap > 0) lba = lba - pregap;
                if(lba < 150) lba = 150;
@@ -311,10 +311,10 @@ void TOWNS_CDROM::play_cdda_from_cmd()
                } else if(cdda_start_frame > max_logical_block) {
                        cdda_start_frame = 0;
                }
-               int track = current_track;
+               track = current_track;
                cdda_playing_frame = cdda_start_frame;
                if(cdda_end_frame > toc_table[track + 1].index1 && (cdda_end_frame - toc_table[track].pregap) <= toc_table[track + 1].index1) {
-                       auto_increment_track = true;
+                       //auto_increment_track = true;
                }
                if(event_cdda_delay_play >= 0) {
                        cancel_event(this, event_cdda_delay_play);
@@ -356,7 +356,7 @@ void TOWNS_CDROM::set_subq(void)
                                msf_rel = 0;
                        }
                }
-               uint32_t msf_abs = lba_to_msf_alt(frame);
+               msf_abs = lba_to_msf_alt(frame);
                subq_overrun = !(subq_buffer->empty());
                subq_buffer->clear();
                // http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-130.pdf
index f1685b0..0085563 100644 (file)
 
 // 0 - 9 : SCSI_CDROM::
 // 100 - : SCSI_DEV::
-#define SIG_TOWNS_CDROM_SET_TRACK 10
+#define SIG_TOWNS_CDROM_SET_TRACK         0x10
+#define SIG_TOWNS_CDROM_MAX_TRACK         0x11
+#define SIG_TOWNS_CDROM_IS_MEDIA_INSERTED 0x12
+#define SIG_TOWNS_CDROM_REACHED_MAX_TRACK 0x13
+#define SIG_TOWNS_CDROM_CURRENT_TRACK     0x14
+#define SIG_TOWNS_CDROM_START_MSF         0x15
+#define SIG_TOWNS_CDROM_START_MSF_AA      0x16
+#define SIG_TOWNS_CDROM_GET_ADR           0x17
+#define SIG_TOWNS_CDROM_SET_STAT_TRACK    0x18
+#define SIG_TOWNS_CDROM_RELATIVE_MSF      0x20
+#define SIG_TOWNS_CDROM_ABSOLUTE_MSF      0x21
 
 // Virtual (pseudo) SCSI command.
-#define TOWNS_CDROM_CDDA_PLAY    0xf0
-#define TOWNS_CDROM_CDDA_PAUSE   0xf1
-#define TOWNS_CDROM_CDDA_UNPAUSE 0xf2
-#define TOWNS_CDROM_CDDA_STOP    0xf3
+#define TOWNS_CDROM_CDDA_PLAY             0xf0
+#define TOWNS_CDROM_CDDA_PAUSE            0xf1
+#define TOWNS_CDROM_CDDA_UNPAUSE          0xf2
+#define TOWNS_CDROM_CDDA_STOP             0xf3
 
 class SCSI_HOST;
 class FIFO;
 class FILEIO;
 
-namespace TOWNS {
+namespace FMTOWNS {
        class CDC;
 }
 
-namespace TOWNS {
+namespace FMTOWNS {
 class TOWNS_CDROM : public SCSI_CDROM {
 protected:
        FIFO* subq_buffer;
@@ -77,6 +87,19 @@ public:
        virtual void set_subq(void);
        virtual uint8_t get_subq_status();
        virtual uint8_t read_subq();
+       virtual void set_cdda_status(uint8_t status)
+       {
+               SCSI_CDROM::set_cdda_status(status);
+       }
+       virtual int get_track(uint32_t lba)
+       {
+               return SCSI_CDROM::get_track(lba);
+       }
+       virtual double get_seek_time(uint32_t lba)
+       {
+               return SCSI_CDROM::get_seek_time(lba);
+       }
+
 };
 
 }
index d61263b..6059aa4 100644 (file)
@@ -8,11 +8,11 @@
 */
 #pragma once
 
-#include "../../common.h"
-#include "../device.h"
-
 // These are common definitions for FM-Towns.
-#define SIG_FMTOWNS_RAM_WAIT 0x10000000
-#define SIG_FMTOWNS_ROM_WAIT 0x10000001
+#define SIG_FMTOWNS_RAM_WAIT  0x10000000
+#define SIG_FMTOWNS_ROM_WAIT  0x10000001
+#define SIG_FMTOWNS_VRAM_WAIT 0x10000001
 
+#define TOWNS_CRTC_MAX_LINES  1024
+#define TOWNS_CRTC_MAX_PIXELS 1024
 
index b9f46f4..fee0c49 100644 (file)
@@ -7,6 +7,7 @@
        [ FM-Towns CRTC ]
        History: 2016.12.28 Initial from HD46505 .
 */
+#include "../../common.h"
 
 #include "towns_crtc.h"
 #include "towns_vram.h"
@@ -55,7 +56,7 @@ void TOWNS_CRTC::initialize()
        }               
        for(int i = 0; i < 4; i++) {
                // ToDo: Allocate at external buffer (when using compute shaders).
-               linebuffers[i] = malloc(sizeof(linebuffer_t ) * TOWNS_CRTC_MAX_LINES);
+               linebuffers[i] = (linebuffer_t *)malloc(sizeof(linebuffer_t ) * TOWNS_CRTC_MAX_LINES);
                if(linebuffers[i] != NULL) {
                        for(int l = 0; l < TOWNS_CRTC_MAX_LINES; l++) {
                                memset(&(linebuffers[i][l]), 0x00, sizeof(linebuffer_t));
@@ -83,30 +84,40 @@ void TOWNS_CRTC::release()
 void TOWNS_CRTC::reset()
 {
        // initialize
-       display = false;
+       display_enabled = false;
        vblank = vsync = hsync = true;
        
 //     memset(regs, 0, sizeof(regs));
-       ch = 0;
+       crtc_ch = 0;
        
        // initial settings for 1st frame
        req_recalc = false;
-       timing_changed = false;
-       disp_end_clock = 0;
        sprite_disp_page = 0; // OK?
        sprite_enabled = false;
 //     crtc_clock = 28.6363e6; // OK?
-
+       interlace_field = false;
+       
        line_count[0] = line_count[1] = 0;
        vert_line_count = -1;
        display_linebuf = 0;
        for(int i = 0; i < TOWNS_CRTC_MAX_LINES; i++) {
                line_changed[0][i] = true;
-               line_rendered[0][i] = false;
                line_changed[1][i] = true;
-               line_rendered[1][i] = false;
        }
-       
+       for(int i = 0; i < 2; i++) {
+               timing_changed[i] = true;
+               address_changed[i] = true;
+               mode_changed[i] = true;
+
+               impose_mode[i] = false; // OK?
+               carry_enable[i] = false; //OK?
+       }
+       for(int i = 0; i < 4; i++) {
+               frame_offset[i] = 0;
+               line_offset[i] = 0;
+               vstart_addr[i] = 0;
+               hstart_words[i] = 0;
+       }
        if(event_id_hsync  >= 0) cancel_event(this, event_id_hsync);
        if(event_id_hsw    >= 0) cancel_event(this, event_id_hsw);
        if(event_id_vsync  >= 0) cancel_event(this, event_id_vsync);
@@ -146,6 +157,22 @@ void TOWNS_CRTC::reset()
        force_recalc_crtc_param();
 //     register_event(this, EVENT_CRTC_VSTART, vstart_us, false, &event_id_vstart);
 }
+
+void TOWNS_CRTC::restart_display()
+{
+       // ToDo
+}
+
+void TOWNS_CRTC::stop_display()
+{
+       // ToDo
+}
+
+void TOWNS_CRTC::notify_mode_changed(int layer, uint8_t mode)
+{
+               // ToDo
+}
+
 // CRTC register #29
 void TOWNS_CRTC::set_crtc_clock(uint16_t val)
 {
@@ -154,8 +181,8 @@ void TOWNS_CRTC::set_crtc_clock(uint16_t val)
        static const double clocks[] = {
                28.6363e6, 24.5454e6, 25.175e6, 21.0525e6
        };
-       if(crtc_clock[clksel] != crtc_clock) {
-               crtc_clock = crtc_clock[clksel];
+       if(clocks[clksel] != crtc_clock) {
+               crtc_clock = clocks[clksel];
                req_recalc = true;
        }
 }
@@ -165,7 +192,7 @@ void TOWNS_CRTC::force_recalc_crtc_param(void)
        horiz_width_posi_us = crtc_clock * ((double)(regs[0] & 0x00fe)); // HSW1
        horiz_width_nega_us = crtc_clock * ((double)(regs[1] & 0x00fe)); // HSW2
        horiz_us = crtc_clock * ((double)((regs[4] & 0x07fe) + 1)); // HST
-       vsync_pre_us = ((double)(regs[5] & 0x1f)) * horiz_us; // VST1
+       vert_sync_pre_us = ((double)(regs[5] & 0x1f)) * horiz_us; // VST1
        
        double horiz_ref = horiz_us / 2.0;
        
@@ -188,7 +215,7 @@ void TOWNS_CRTC::force_recalc_crtc_param(void)
 }
 
 
-void TONWS_CRTC::write_io8(uint32_t addr, uint32_t data)
+void TOWNS_CRTC::write_io8(uint32_t addr, uint32_t data)
 {
        switch(addr) {
        case 0x0440:
@@ -198,7 +225,7 @@ void TONWS_CRTC::write_io8(uint32_t addr, uint32_t data)
                {
                        pair16_t rdata;
                        rdata.w = regs[crtc_ch];
-                       rdata.l = (uint8_t)data;
+                       rdata.b.l = (uint8_t)data;
                        write_io16(addr, rdata.w);
                }
                break;
@@ -206,7 +233,7 @@ void TONWS_CRTC::write_io8(uint32_t addr, uint32_t data)
                {
                        pair16_t rdata;
                        rdata.w = regs[crtc_ch];
-                       rdata.h = (uint8_t)data;
+                       rdata.b.h = (uint8_t)data;
                        write_io16(addr, rdata.w);
                }
                break;
@@ -261,10 +288,10 @@ void TOWNS_CRTC::write_io16(uint32_t addr, uint32_t data)
                                                        hstart_words[localch] = (uint32_t)(data & 0x07ff);
                                                        break;
                                                case 2: // FOx
-                                                       frame_offet[localch] = (uint32_t)(data & 0xffff);
+                                                       frame_offset[localch] = (uint32_t)(data & 0xffff);
                                                        break;
                                                case 3: // LOx
-                                                       line_offet[localch] = (uint32_t)(data & 0xffff);
+                                                       line_offset[localch] = (uint32_t)(data & 0xffff);
                                                        break;
                                                }                                       
                                        }
@@ -281,10 +308,10 @@ void TOWNS_CRTC::write_io16(uint32_t addr, uint32_t data)
                                                                uint8_t zfh[2];
                                                                pair16_t pd;
                                                                pd.w = (uint16_t)data;
-                                                               zfv[0] = ((pd.l & 0xf0) >> 4) + 1;
-                                                               zfh[0] = (pd.l & 0x0f) + 1;
-                                                               zfv[1] = ((pd.h & 0xf0) >> 4) + 1;
-                                                               zfh[1] = (pd.h & 0x0f) + 1;
+                                                               zfv[0] = ((pd.b.l & 0xf0) >> 4) + 1;
+                                                               zfh[0] = (pd.b.l & 0x0f) + 1;
+                                                               zfv[1] = ((pd.b.h & 0xf0) >> 4) + 1;
+                                                               zfh[1] = (pd.b.h & 0x0f) + 1;
                                                                if((zfv[0] != zoom_factor_vert[0]) || (zfh[0] != zoom_factor_horiz[0])) {
                                                                        timing_changed[0] = true;
                                                                        address_changed[0] = true;
@@ -367,13 +394,13 @@ void TOWNS_CRTC::write_io16(uint32_t addr, uint32_t data)
        case 0xfd9e:
        case 0xfd9f:
                {
-                       pair16_t n;
+                       pair32_t n;
                        n.d = data;
                        if(addr == 0xfd9f) {
-                               dpalette_regs[7] = n.l & 0x0f;
+                               dpalette_regs[7] = n.b.l & 0x0f;
                        } else {
-                               dpalette_regs[addr & 7] = n.l & 0x0f;
-                               dpalette_regs[(addr + 1) & 7] = n.h & 0x0f;
+                               dpalette_regs[addr & 7] = n.b.l & 0x0f;
+                               dpalette_regs[(addr + 1) & 7] = n.b.h & 0x0f;
                        }
                        dpalette_changed = true;
                }
@@ -400,7 +427,7 @@ uint16_t TOWNS_CRTC::read_reg30()
        //data |= ((sync_enable)  ? 0x0004 : 0);
        //data |= ((vcard_enable) ? 0x0002 : 0);
        //data |= ((sub_carry)    ? 0x0001 : 0);
-       
+       return data;
 }
 
 uint32_t TOWNS_CRTC::read_io16(uint32_t addr)
@@ -441,11 +468,11 @@ uint32_t TOWNS_CRTC::read_io16(uint32_t addr)
                {
                        pair16_t n;
                        if(addr == 0xfd9f) {
-                               n.l = dpalette_regs[7];
-                               n.h = 0xff;
+                               n.b.l = dpalette_regs[7];
+                               n.b.h = 0xff;
                        } else {
-                               n.l = dpalette_regs[addr & 0x07];
-                               n.h = dpalette_regs[(addr + 1) & 0x07];
+                               n.b.l = dpalette_regs[addr & 0x07];
+                               n.b.h = dpalette_regs[(addr + 1) & 0x07];
                        }
                        return n.w;
                }
@@ -472,22 +499,22 @@ uint32_t TOWNS_CRTC::read_io8(uint32_t addr)
                {
                        pair16_t d;
                        if(crtc_ch == 30) {
-                               d.w = read_reg32();
+                               d.w = read_reg30();
                        } else {
                                d.w = regs[crtc_ch];
                        }
-                       return (uint32_t)(d.l);
+                       return (uint32_t)(d.b.l);
                }
                break;
        case 0x0443:
                {
                        pair16_t d;
                        if(crtc_ch == 30) {
-                               d.w = read_reg32();
+                               d.w = read_reg30();
                        } else {
                                d.w = regs[crtc_ch];
                        }
-                       return (uint32_t)(d.h);
+                       return (uint32_t)(d.b.h);
                }
                break;
        case 0xfd98:
@@ -537,11 +564,14 @@ bool TOWNS_CRTC::render_32768(scrntype_t* dst, scrntype_t *mask, int y, int widt
        __DECL_ALIGNED(32) scrntype_t sbuf[8];
        __DECL_ALIGNED(32) scrntype_t abuf[8];
        __DECL_ALIGNED(32) uint8_t a2buf[8];
+       pair16_t ptmp16;
+       int rwidth = pwidth & 7;
        
        int k = 0;
-       for(x = 0; x < (pwidth >> 3); x++) {
+       for(int x = 0; x < (pwidth >> 3); x++) {
                for(int i = 0; i < 8; i++) {
-                       pbuf[i] = read_2bytes_le_from(p);
+                       ptmp16.read_2bytes_le_from(p);
+                       pbuf[i] = ptmp16.w;
                        p += 2;
                }
                for(int i = 0; i < 8; i++) {
@@ -593,13 +623,13 @@ bool TOWNS_CRTC::render_32768(scrntype_t* dst, scrntype_t *mask, int y, int widt
                } else {
                        for(int i = 0; i < 8; i++) {
                                int kbak = k;
-                               for(j = 0; j < magx; j++) {
+                               for(int j = 0; j < magx; j++) {
                                        *q++ = sbuf[i];
                                        k++;
                                        if(k >= width) break;
                                }
                                if(r != NULL) {
-                                       for(j = 0; j < magx; j++) {
+                                       for(int j = 0; j < magx; j++) {
                                                *r++ = abuf[i];
                                                kbak++;
                                                if(kbak >= width) break;
@@ -610,10 +640,11 @@ bool TOWNS_CRTC::render_32768(scrntype_t* dst, scrntype_t *mask, int y, int widt
                }
        }
        if(k >= width) return true;
+       
        if((pwidth & 7) != 0) {
-               int rwidth = pwidth & 7;
                for(int i = 0; i < rwidth; i++) {
-                       pbuf[i] = read_2bytes_le_from(p);
+                       ptmp16.read_2bytes_le_from(p);
+                       pbuf[i] = ptmp16.w;
                        p += 2;
                }
                for(int i = 0; i < rwidth; i++) {
@@ -657,10 +688,10 @@ bool TOWNS_CRTC::render_32768(scrntype_t* dst, scrntype_t *mask, int y, int widt
                                }
                        }
                        k += 8;
-                       if(k >= width) break;
+                       if(k >= width) return true;
                } else {
                        for(int i = 0; i < rwidth; i++) {
-                               if(j = 0; j < magx; j++) {
+                               for(int j = 0; j < magx; j++) {
                                        *q++ = sbuf[i];
                                        if(r != NULL) {
                                                *r++ = abuf[i];
@@ -668,7 +699,7 @@ bool TOWNS_CRTC::render_32768(scrntype_t* dst, scrntype_t *mask, int y, int widt
                                        k++;
                                        if(k >= width) break;
                                }
-                               if(k >= width) break;
+                               if(k >= width) return true;
                        }
                }
        }
@@ -677,12 +708,12 @@ bool TOWNS_CRTC::render_32768(scrntype_t* dst, scrntype_t *mask, int y, int widt
 
 bool TOWNS_CRTC::render_16(scrntype_t* dst, scrntype_t *mask, scrntype_t* pal, int y, int width, int layer, bool do_alpha)
 {
-       if(dst == NULL) return;
+       if(dst == NULL) return false;
        
        int trans = display_linebuf & 3;
        int magx = linebuffers[trans][y].mag[layer];
        int pwidth = linebuffers[trans][y].pixels[layer];
-       int num = linebuffers[trans][y].num[layer];
+       //int num = linebuffers[trans][y].num[layer];
        uint8_t *p = linebuffers[trans][y].pixels_layer[layer];
        scrntype_t *q = dst;
        scrntype_t *r = mask;
@@ -711,7 +742,7 @@ bool TOWNS_CRTC::render_16(scrntype_t* dst, scrntype_t *mask, scrntype_t* pal, i
                pal = palbuf;
        }
        int k = 0;
-       for(x = 0; x < (pwidth >> 3); x++) {
+       for(int x = 0; x < (pwidth >> 3); x++) {
                for(int i = 0; i < 8; i++) {
                        pbuf[i] = *p++;
                }
@@ -724,7 +755,7 @@ bool TOWNS_CRTC::render_16(scrntype_t* dst, scrntype_t *mask, scrntype_t* pal, i
                        hlbuf[i + 1] = hlbuf[i + 1] & 15;
                }
                for(int i = 0; i < 16; i++) {
-                       abuf[i] = (hlbuf[ii] == 0) ? 0 : (scrntype_t)(-1);
+                       abuf[i] = (hlbuf[i] == 0) ? 0 : (scrntype_t)(-1);
                }
                for(int i = 0; i < 16; i++) {
                        sbuf[i] = (hlbuf[i] == 0) ? RGBA_COLOR(0, 0, 0, 0) : pal[hlbuf[i]];
@@ -743,13 +774,13 @@ bool TOWNS_CRTC::render_16(scrntype_t* dst, scrntype_t *mask, scrntype_t* pal, i
                } else {
                        for(int i = 0; i < 16; i++) {
                                int kbak = k;
-                               if(j = 0; j < magx; j++) {
+                               for(int j = 0; j < magx; j++) {
                                        *q++ = sbuf[i];
                                        k++;
                                        if(k >= width) break;
                                }
                                if(r != NULL) {
-                                       for(j = 0; j < magx; j++) {
+                                       for(int j = 0; j < magx; j++) {
                                                *r++ = abuf[i];
                                                kbak++;
                                                if(kbak >= width) break;
@@ -760,12 +791,13 @@ bool TOWNS_CRTC::render_16(scrntype_t* dst, scrntype_t *mask, scrntype_t* pal, i
                }
        }
        if(k >= width) return true;
-       int rwidth = pwidth & 7;
        uint8_t tmpp;
        uint8_t tmph;
        uint8_t tmpl;
+       scrntype_t ah, al;
+       int rwidth = pwidth & 7;
        if(rwidth > 0) {
-               for(x = 0; x < rwidth; x++) {
+               for(int x = 0; x < rwidth; x++) {
                        tmpp = *p++;
                        tmph = tmpp >> 4;
                        tmpl = tmpp & 0x0f;
@@ -825,11 +857,11 @@ void TOWNS_CRTC::draw_screen()
        __DECL_ALIGNED(32)  scrntype_t apal256[256];
        
        {
-               vm->lock_vm();
+               emu->lock_vm();
                d_vram->get_analog_palette(0, &(apal16[0][0]));
                d_vram->get_analog_palette(0, &(apal16[1][0]));
                d_vram->get_analog_palette(2, apal256);
-               vm->unlock_vm();
+               emu->unlock_vm();
        }
        
        int lines = lines_per_frame;
@@ -850,13 +882,13 @@ void TOWNS_CRTC::draw_screen()
        for(int y = 0; y < lines; y++) {
                bool do_mix0 = false;
                bool do_mix1 = false;
-               if(linebuffers[trans].mode[0] == DISPMODE_256) {
+               if(linebuffers[trans]->mode[0] == DISPMODE_256) {
                        // 256 colors
                        do_mix0 = true;
-                       int magx = linebuffers[trans].mag[0];
-                       int pwidth = linebuffers[trans].pixels[0];
-                       int num = linebuffers[trans].num[0];
-                       uint8_t *p = linebuffers[trans].pixels_layer[0];
+                       int magx = linebuffers[trans]->mag[0];
+                       int pwidth = linebuffers[trans]->pixels[0];
+                       int num = linebuffers[trans]->num[0];
+                       uint8_t *p = linebuffers[trans]->pixels_layer[0];
                        __DECL_ALIGNED(16) uint8_t pbuf[16];
                        __DECL_ALIGNED(32) scrntype_t sbuf[16];
                        if(magx < 1) {
@@ -923,21 +955,21 @@ void TOWNS_CRTC::draw_screen()
                                }
                        }
                } else {
-                       if(linebuffers[trans].mode[1] == DISPMODE_16) { // Lower layer
-                               do_mix1 = render_16(lbuffer1, abuffer1, &(apal16[linebuffers[trans].num[1]][0]), y, width, 1, do_alpha);
-                       } else if(linebuffers[trans].mode[1] == DISPMODE_32768) { // Lower layer
+                       if(linebuffers[trans]->mode[1] == DISPMODE_16) { // Lower layer
+                               do_mix1 = render_16(lbuffer1, abuffer1, &(apal16[linebuffers[trans]->num[1]][0]), y, width, 1, do_alpha);
+                       } else if(linebuffers[trans]->mode[1] == DISPMODE_32768) { // Lower layer
                                do_mix1 = render_32768(lbuffer1, abuffer1, y, width, 1, do_alpha);
                        }
                        // Upper layer
-                       if(linebuffers[trans].mode[0] == DISPMODE_16) { // Lower layer
-                               do_mix0 = render_16(lbuffer0, abuffer0, &(apal16[linebuffers[trans].num[0]][0]), y, width, 0, do_alpha);
-                       } else if(linebuffers[trans].mode[1] == DISPMODE_32768) { // Lower layer
+                       if(linebuffers[trans]->mode[0] == DISPMODE_16) { // Lower layer
+                               do_mix0 = render_16(lbuffer0, abuffer0, &(apal16[linebuffers[trans]->num[0]][0]), y, width, 0, do_alpha);
+                       } else if(linebuffers[trans]->mode[1] == DISPMODE_32768) { // Lower layer
                                do_mix0 = render_32768(lbuffer0, abuffer0, y, width, 1, do_alpha);
                        }
                }
                // ToDo: alpha blending
                {
-                       vm->lock_vm();
+                       emu->lock_vm();
                        scrntype_t *pp = emu->get_screen_buffer(y);
                        if(pp != NULL) {
                                if((do_mix0) && (do_mix1)) {
@@ -987,7 +1019,7 @@ void TOWNS_CRTC::draw_screen()
                                        memset(pp, 0x00, width * sizeof(scrntype_t));
                                }
                        }
-                       vm->unlock_vm();
+                       emu->unlock_vm();
                }
        }
        //display_linebuf = (display_linebuf + 1) & 3;
@@ -1155,6 +1187,8 @@ void TOWNS_CRTC::transfer_line()
 void TOWNS_CRTC::update_timing(int new_clocks, double new_frames_per_sec, int new_lines_per_frame)
 {
        max_lines = new_lines_per_frame;
+       frames_per_sec = new_frames_per_sec;
+       cpu_clocks = new_clocks;
        req_recalc = true;
 }
 
@@ -1202,6 +1236,7 @@ void TOWNS_CRTC::event_pre_frame()
 void TOWNS_CRTC::event_frame()
 {
        display_linebuf = (display_linebuf + 1) & 3; // Incremant per vstart
+       lines_per_frame = max_lines;
 //             if(req_recalc) {
 //                     force_recalc_crtc_param();
 //             }
@@ -1337,7 +1372,7 @@ void TOWNS_CRTC::event_callback(int event_id, int err)
        } else if(eid2 == EVENT_CRTC_HDS) {
                int layer = event_id & 1;
                hdisp[layer] = true;
-               if((horiz_end_us[i] <= 0.0) || (horiz_end_us[i] <= horiz_start_us[i])) {
+               if((horiz_end_us[layer] <= 0.0) || (horiz_end_us[layer] <= horiz_start_us[layer])) {
                        hdisp[layer] = false;
                }
                event_id_hds[layer] = -1;
@@ -1411,6 +1446,8 @@ bool TOWNS_CRTC::process_state(FILEIO* state_fio, bool loading)
        state_fio->StateArray(regs, sizeof(regs), 1);
        state_fio->StateArray(regs_written, sizeof(regs_written), 1);
        state_fio->StateValue(crtc_ch);
+       state_fio->StateValue(interlace_field);
+
        state_fio->StateArray(timing_changed, sizeof(timing_changed), 1);
        state_fio->StateArray(address_changed, sizeof(address_changed), 1);
        state_fio->StateArray(mode_changed, sizeof(mode_changed), 1);
@@ -1420,14 +1457,19 @@ bool TOWNS_CRTC::process_state(FILEIO* state_fio, bool loading)
        state_fio->StateValue(crtc_clock);
        state_fio->StateValue(max_lines);
        state_fio->StateValue(frames_per_sec);
+       state_fio->StateValue(cpu_clocks);
 
        state_fio->StateArray(vstart_addr, sizeof(vstart_addr), 1);
        state_fio->StateArray(hstart_words, sizeof(hstart_words), 1);
        state_fio->StateArray(hend_words, sizeof(hend_words), 1);
        state_fio->StateArray(vstart_lines, sizeof(vstart_lines), 1);
        state_fio->StateArray(vend_lines, sizeof(vend_lines), 1);
+       state_fio->StateArray(line_offset, sizeof(line_offset), 1);
        state_fio->StateArray(frame_offset, sizeof(frame_offset), 1);
        state_fio->StateArray(head_address, sizeof(head_address), 1);
+       state_fio->StateArray(impose_mode,  sizeof(impose_mode), 1);
+       state_fio->StateArray(carry_enable, sizeof(carry_enable), 1);
+
        
        state_fio->StateArray(zoom_factor_vert, sizeof(zoom_factor_vert), 1);
        state_fio->StateArray(zoom_factor_horiz, sizeof(zoom_factor_horiz), 1);
index cf2ad90..0be963b 100644 (file)
@@ -15,6 +15,7 @@
 #include "../emu.h"
 #include "device.h"
 
+#include "towns_common.h"
 /*
  * I/O Address :
  *  0440H : Register address (8bit W/O : bit7 to 5 must be '0').
@@ -86,8 +87,6 @@
  *   #00 : Control registers.
  *   #01 : Priority registers.
  */
-#define TOWNS_CRTC_MAX_LINES  1024
-#define TOWNS_CRTC_MAX_PIXELS 1024
 
 #define SIG_TOWNS_CRTC_HSYNC          1
 #define SIG_TOWNS_CRTC_VSYNC          2
@@ -99,6 +98,7 @@
 #define SIG_TOWNS_CRTC_MMIO_CF882H    8
 #define SIG_TOWNS_CRTC_SPRITE_BUFFER  9
 #define SIG_TOWNS_CRTC_SPRITE_DISP    10
+#define SIG_TOWNS_CRTC_SPRITE_USING   11
 
 namespace FMTOWNS {
 
@@ -149,10 +149,10 @@ namespace FMTOWNS {
 namespace FMTOWNS {
        
 typedef struct {
-       int32_t mode[2];
-       int32_t pixels[2];
-       int32_t mag[2];
-       int32_t num[2];
+       int32_t mode[4];
+       int32_t pixels[4];
+       int32_t mag[4];
+       int32_t num[4];
        uint32_t prio;
        uint32_t pad[7];
        uint8_t pixels_layer[2][TOWNS_CRTC_MAX_PIXELS]; // RAW VALUE
@@ -174,38 +174,54 @@ protected:
        bool address_changed[2];
        bool mode_changed[2];
        
-       uint8_t display_mode[2]; 
+       uint8_t display_mode[2];
+       bool line_changed[2][TOWNS_CRTC_MAX_LINES];
        bool display_enabled;
        
-       double crtc_clock; // 
+       double crtc_clock; //
+       int cpu_clocks;
+       
        // They are not saved.Must be calculate when loading.
        double horiz_us, next_horiz_us; // (HST + 1) * clock
        double horiz_width_posi_us, horiz_width_nega_us; // HSW1, HSW2
        double vert_us, next_vert_us; // (VST +1) * horiz_us / 2.0
-       double vstart_us;
        double vert_sync_pre_us; // VST1 * horiz_us / 2.0
        double vert_sync_end_us; // VST2 * horiz_us / 2.0
        double eet_us;
        double frame_us;
+       double vst2_us;
+       double vert_start_us[2];
+       double vert_end_us[2];
+       double horiz_start_us[2];
+       double horiz_end_us[2];
        
        bool req_recalc;
        // End
 
        double frames_per_sec;
 
-       uint32_t vstart_addr[2];  // VSTART ADDRESS
-    uint32_t hstart_words[2]; // HSTART ((HDS[01] * clock) : Horizonal offset words (Related by ZH[01]). Maybe 0.
-    uint32_t hend_words[2];   // HEND   ((HDE[01] * clock) : Horizonal offset words (Related by ZH[01]). Maybe 0.
+       uint32_t vstart_addr[4];  // VSTART ADDRESS
+    uint32_t hstart_words[4]; // HSTART ((HDS[01] * clock) : Horizonal offset words (Related by ZH[01]). Maybe 0.
+    uint32_t hend_words[4];   // HEND   ((HDE[01] * clock) : Horizonal offset words (Related by ZH[01]). Maybe 0.
     uint32_t vstart_lines[2]; // VSTART ((VDS[01] * clock) : Horizonal offset words (Related by VH[01]).
-    uint32_t vend_lines[2];   // VEND   ((VDE[01] * clock) : Horizonal offset words (Related by VH[01]).
-       uint32_t frame_offset[2]; // FO.
+    uint32_t vend_lines[4];   // VEND   ((VDE[01] * clock) : Horizonal offset words (Related by VH[01]).
+       uint32_t frame_offset[4]; // FO.
+       uint32_t line_offset[4]; // FO.
        uint32_t head_address[2];
+       bool impose_mode[2]; // OK?
+       bool carry_enable[2]; //OK?
        
        uint8_t zoom_factor_vert[2]; // Related display resolutions of two layers and zoom factors.
        uint8_t zoom_factor_horiz[2]; // Related display resolutions of two layers and zoom factors.
        uint8_t zoom_count_vert[2];
-       
        uint32_t line_count[2]; // Separate per layer.
+
+       uint8_t scsel;
+       uint8_t clksel;
+       
+       int pixels_per_line;
+       int lines_per_frame;
+       int max_lines;
        
        int vert_line_count; // Not separate per layer.Total count.
        // Note: To display to real screen, use blending of OpenGL/DirectX
@@ -216,9 +232,9 @@ protected:
        
        // Not Saved?.
        // End.
-       
        bool vdisp, vblank, vsync, hsync, hdisp[2], frame_in[2];
-
+       bool interlace_field;
+       
        // around sprite
        uint8_t sprite_disp_page;
        bool sprite_enabled;
@@ -268,14 +284,16 @@ protected:
        void set_vblank(bool val);
        void set_vsync(bool val);
        void set_hsync(bool val);
-       void transfer_line(int line);
-
-protected:
-       bool render_a_line(int layer, int linenum, int xoffset, uint8_t *vramptr, uint32_t words);
-       void render_line_16(int layer, scrntype_t *framebuffer, uint8_t *vramptr, uint32_t words);
-       void render_line_256(int layer, scrntype_t *framebuffer, uint8_t *vramptr, uint32_t words);
-       void render_line_32768(int layer, scrntype_t *framebuffer, uint8_t *vramptr, uint32_t words);
-       void render_clear(int layer, scrntype_t *framebuffer);
+       void force_recalc_crtc_param(void);
+       void restart_display();
+       void stop_display();
+       void notify_mode_changed(int layer, uint8_t mode);
+       void set_crtc_clock(uint16_t val);
+       uint16_t read_reg30();
+       
+       bool __FASTCALL render_16(scrntype_t* dst, scrntype_t *mask, scrntype_t* pal, int y, int width, int layer, bool do_alpha);
+       bool __FASTCALL render_32768(scrntype_t* dst, scrntype_t *mask, int y, int width, int layer, bool do_alpha);
+       void transfer_line();
        
 public:
        TOWNS_CRTC(VM *parent_vm, EMU *parent_emu) : DEVICE(parent_vm, parent_emu)
@@ -291,31 +309,26 @@ public:
        ~TOWNS_CRTC() {}
 
        void initialize();
+       void release();
        void reset();
+       void draw_screen();
+       void update_timing(int new_clocks, double new_frames_per_sec, int new_lines_per_frame);
+       void event_pre_frame();
+       void event_frame();
        
-       void write_signal(int id, uint32_t data, uint32_t mask);
-       uint32_t read_signal(int ch);
-
-       void write_io8(uint32_t addr, uint32_t data);
-       uint32_t read_io8(uint32_t addr);
+       void __FASTCALL write_signal(int id, uint32_t data, uint32_t mask);
+       uint32_t __FASTCALL read_signal(int ch);
+       void __FASTCALL write_io8(uint32_t addr, uint32_t data);
+       uint32_t __FASTCALL read_io8(uint32_t addr);
 
-       void write_io16(uint32_t addr, uint32_t data);
-       uint32_t read_io16(uint32_t addr);
-       
-       uint32_t read_data8(uint32_t addr);
-       uint32_t read_data16(uint32_t addr);
-       uint32_t read_data32(uint32_t addr);
+       void __FASTCALL write_io16(uint32_t addr, uint32_t data);
+       uint32_t __FASTCALL read_io16(uint32_t addr);
        
-       void write_data8(uint32_t addr, uint32_t data);
-       void write_data16(uint32_t addr, uint32_t data);
-       void write_data32(uint32_t addr, uint32_t data);
        void event_callback(int event_id, int err);
-       //void update_timing(int new_clocks, double new_frames_per_sec, int new_lines_per_frame);
-       void save_state(FILEIO* state_fio);
-       bool load_state(FILEIO* state_fio);
+       bool process_state(FILEIO* state_fio, bool loading);
        
        // unique function
-       linebuffer_t* get_line_buffer(int page, int line)
+       linebuffer_t* __FASTCALL get_line_buffer(int page, int line)
        {
                page = page & 1;
                if(line < 0) return NULL;
index 1903fd1..fd9465e 100644 (file)
@@ -35,7 +35,7 @@ void DICTIONARY::initialize()
        cmos_dirty = true;
        if(fio->Fopen(create_local_path(_T("FMT_CMOS.BIN")), FILEIO_READ_BINARY)) {
                if(fio->Fread(dict_ram, sizeof(dict_ram), 1) == 1) {
-                       cmod_dirty = false;
+                       cmos_dirty = false;
                }
                fio->Fclose();
        }
@@ -149,7 +149,7 @@ uint32_t DICTIONARY::read_data16w(uint32_t addr, int* wait)
        return (uint32_t)(n.u16);
 }
 
-uint32_t DICTIONARY::read_data32(uint32_t addr)
+uint32_t DICTIONARY::read_data32w(uint32_t addr, int* wait)
 {
        pair32_t n;
        addr = addr & 0xfffffffc;
@@ -195,8 +195,8 @@ void DICTIONARY::write_data16w(uint32_t addr, uint32_t data, int* wait)
                return;
        }               
        int dummy;
-       write_data8(addr + 0, n.b.l, &dummy);
-       write_data8(addr + 1, n.b.h, wait);
+       write_data8w(addr + 0, n.b.l, &dummy);
+       write_data8w(addr + 1, n.b.h, wait);
 }
 
 void DICTIONARY::write_data32w(uint32_t addr, uint32_t data, int* wait)
index 61ec9ba..2b9c7b7 100644 (file)
@@ -1,5 +1,5 @@
 
-#include "../towns_dmac.h"
+#include "./towns_dmac.h"
 #include "debugger.h"
 
 namespace FMTOWNS {
@@ -23,22 +23,22 @@ void TOWNS_DMAC::write_io8(uint32_t addr, uint32_t data)
        switch(addr & 0x0f) {
        case 0x04:
                nba.b.l = data & 0xff;
-               ba.b.l = data & 0xff;
+               na.b.l = data & 0xff;
                addr_modified = true;
                break;
        case 0x05:
                nba.b.h = data & 0xff;
-               ba.b.h = data & 0xff;
+               na.b.h = data & 0xff;
                addr_modified = true;
                break;
        case 0x06:
                nba.b.h2 = data & 0xff;
-               ba.b.h2 = data & 0xff;
+               na.b.h2 = data & 0xff;
                addr_modified = true;
                break;
        case 0x07:
                nba.b.h3 = data & 0xff;
-               ba.b.h3 = data & 0xff;
+               na.b.h3 = data & 0xff;
                addr_modified = true;
                break;
        }
@@ -64,16 +64,16 @@ uint32_t TOWNS_DMAC::read_io8(uint32_t addr)
                }
                switch(addr & 0x0f) {
                case 0x04:
-                       val = nval.l;
+                       val = nval.b.l;
                        break;
                case 0x05:
-                       val = nval.h;
+                       val = nval.b.h;
                        break;
                case 0x06:
-                       val = nval.h2;
+                       val = nval.b.h2;
                        break;
                case 0x07:
-                       val = nval.h3;
+                       val = nval.b.h3;
                        break;
                }
                return val;
@@ -101,4 +101,4 @@ void TOWNS_DMAC::do_dma_inc_dec_ptr_16bit(int c)
        }
 }
        
-               
+}              
index d103585..be7531a 100644 (file)
@@ -4,7 +4,7 @@
 #include "../upd71071.h"
 
 namespace FMTOWNS {
-class TOWNS_DMAC : publiuc UPD71071
+class TOWNS_DMAC : public UPD71071
 {
 protected:
        virtual void __FASTCALL do_dma_inc_dec_ptr_8bit(int c);
index d01a030..5457d76 100644 (file)
 #include "../../fileio.h"
 #include "./towns_memory.h"
 #include "./towns_vram.h"
+#include "./serialrom.h"
 #include "../i386.h"
+#include "../pcm1bit.h"
 
 namespace FMTOWNS {
+#define EVENT_1US_WAIT 1
        
 void TOWNS_MEMORY::initialize()
 {
@@ -30,23 +33,23 @@ void TOWNS_MEMORY::initialize()
        memset(wr_dummy, 0x00, sizeof(wr_dummy));
        memset(rd_table, 0x00, sizeof(rd_table));
        memset(wr_table, 0x00, sizeof(wr_table));
-       for(int i = 0; i < ((0xffffffff / TOWNS_BANK_SIZE) + 1); i++) {
-               rd_table.dev = NULL;
-               rd_table.memory = rd_dummy;
-               rd_table.wait = 6;
+       for(int i = 0; i < (0x100000000 >> TOWNS_BANK_SHIFT); i++) {
+               rd_table[i].dev = NULL;
+               rd_table[i].memory = rd_dummy;
+               rd_table[i].wait = 6;
        }
-       for(int i = 0; i < ((0xffffffff / TOWNS_BANK_SIZE) + 1); i++) {
-               wr_table.dev = NULL;
-               wr_table.memory = rd_dummy;
-               wr_table.wait = 6;
+       for(int i = 0; i < (0x100000000 >> TOWNS_BANK_SHIFT); i++) {
+               wr_table[i].dev = NULL;
+               wr_table[i].memory = rd_dummy;
+               wr_table[i].wait = 6;
        }
        
-       extra_ram_size = extra_ram_size & 0x3ff00000;
-       if(extra_ram_size >= 0x00100000) {
-               extra_ram = malloc(extra_ram_size);
+       extram_size = extram_size & 0x3ff00000;
+       if(extram_size >= 0x00100000) {
+               extra_ram = (uint8_t*)malloc(extram_size);
                if(extra_ram != NULL) {
-                       set_memory_rw(0x00100000, (extra_ram_size + 0x00100000) - 1, extra_ram);
-                       memset(extra_ram, 0x00, extra_ram_size);
+                       set_memory_rw(0x00100000, (extram_size + 0x00100000) - 1, extra_ram);
+                       memset(extra_ram, 0x00, extram_size);
                }
        }               
        memset(ram_mmio, 0x00, sizeof(ram_mmio)); // ToDo: Move To Sprite.
@@ -66,7 +69,7 @@ void TOWNS_MEMORY::initialize()
 
 void TOWNS_MEMORY::set_wait_values()
 {
-       set_wait_rw(0x00000000, 0x00100000 + (extra_ram_size & 0x3ff00000) - 1, mem_wait_val);
+       set_wait_rw(0x00000000, 0x00100000 + (extram_size & 0x3ff00000) - 1, mem_wait_val);
        // ToDo: Extend I/O Slots
        set_wait_rw(0x80000000, 0x800fffff, vram_wait_val);
        set_wait_rw(0x80100000, 0x801fffff, vram_wait_val);
@@ -242,8 +245,8 @@ void TOWNS_MEMORY::copy_table_r(uint32_t to, uint32_t start, uint32_t end)
 
 void TOWNS_MEMORY::copy_table_rw(uint32_t to, uint32_t start, uint32_t end)
 {
-       copy_table_r(to, startm end);
-       copy_table_w(to, startm end);
+       copy_table_r(to, start, end);
+       copy_table_w(to, start, end);
 }      
 
 void TOWNS_MEMORY::set_wait_w(uint32_t start, uint32_t end, int wait)
@@ -305,9 +308,9 @@ uint32_t TOWNS_MEMORY::read_data16w(uint32_t addr, int *wait)
        } else if(rd_table[bank].memory != NULL) {
                // Internal memories may access with 32bit width.
                pair32_t nd;
-               nd.b.l = rd_table[bank].memory[addr & (TOWNS_BANK_SIZE - 2) + 0];
-               nd.b.h = rd_table[bank].memory[addr & (TOWNS_BANK_SIZE - 2) + 1];
-               return nd.w;
+               nd.b.l = rd_table[bank].memory[(addr & (TOWNS_BANK_SIZE - 2)) + 0];
+               nd.b.h = rd_table[bank].memory[(addr & (TOWNS_BANK_SIZE - 2)) + 1];
+               return nd.w.l;
        }
        return 0xffff;
 }
@@ -323,10 +326,10 @@ uint32_t TOWNS_MEMORY::read_data32w(uint32_t addr, int *wait)
        } else if(rd_table[bank].memory != NULL) {
                // Internal memories may access with 32bit width.
                pair32_t nd;
-               nd.b.l  = rd_table[bank].memory[addr & (TOWNS_BANK_SIZE - 4) + 0];
-               nd.b.h  = rd_table[bank].memory[addr & (TOWNS_BANK_SIZE - 4) + 1];
-               nd.b.h2 = rd_table[bank].memory[addr & (TOWNS_BANK_SIZE - 4) + 2];
-               nd.b.h3 = rd_table[bank].memory[addr & (TOWNS_BANK_SIZE - 4) + 3];
+               nd.b.l  = rd_table[bank].memory[(addr & (TOWNS_BANK_SIZE - 4)) + 0];
+               nd.b.h  = rd_table[bank].memory[(addr & (TOWNS_BANK_SIZE - 4)) + 1];
+               nd.b.h2 = rd_table[bank].memory[(addr & (TOWNS_BANK_SIZE - 4)) + 2];
+               nd.b.h3 = rd_table[bank].memory[(addr & (TOWNS_BANK_SIZE - 4)) + 3];
                return nd.d;
        }
        return 0xffffffff;
@@ -358,8 +361,8 @@ void TOWNS_MEMORY::write_data16w(uint32_t addr, uint32_t data, int *wait)
                // Internal memories may access with 32bit width.
                pair32_t nd;
                nd.d = data; 
-               wr_table[bank].memory[addr & (TOWNS_BANK_SIZE - 2) + 0] = nd.b.l;
-               wr_table[bank].memory[addr & (TOWNS_BANK_SIZE - 2) + 1] = nd.b.h;
+               wr_table[bank].memory[(addr & (TOWNS_BANK_SIZE - 2)) + 0] = nd.b.l;
+               wr_table[bank].memory[(addr & (TOWNS_BANK_SIZE - 2)) + 1] = nd.b.h;
        }
 }
 
@@ -375,10 +378,10 @@ void TOWNS_MEMORY::write_data32w(uint32_t addr, uint32_t data, int *wait)
                // Internal memories may access with 32bit width.
                pair32_t nd;
                nd.d = data; 
-               wr_table[bank].memory[addr & (TOWNS_BANK_SIZE - 4) + 0] = nd.b.l;
-               wr_table[bank].memory[addr & (TOWNS_BANK_SIZE - 4) + 1] = nd.b.h;
-               wr_table[bank].memory[addr & (TOWNS_BANK_SIZE - 4) + 2] = nd.b.h2;
-               wr_table[bank].memory[addr & (TOWNS_BANK_SIZE - 4) + 3] = nd.b.h3;
+               wr_table[bank].memory[(addr & (TOWNS_BANK_SIZE - 4)) + 0] = nd.b.l;
+               wr_table[bank].memory[(addr & (TOWNS_BANK_SIZE - 4)) + 1] = nd.b.h;
+               wr_table[bank].memory[(addr & (TOWNS_BANK_SIZE - 4)) + 2] = nd.b.h2;
+               wr_table[bank].memory[(addr & (TOWNS_BANK_SIZE - 4)) + 3] = nd.b.h3;
        }
 }
 
@@ -414,8 +417,8 @@ uint32_t TOWNS_MEMORY::read_dma_data16w(uint32_t addr, int* wait)
                        *wait = mem_wait_val;
                }
                pair16_t nd;
-               nd.b.l = rd_table[bank].memory[addr & (TOWNS_BANK_SIZE - 2) + 0];
-               nd.b.h = rd_table[bank].memory[addr & (TOWNS_BANK_SIZE - 2) + 1];
+               nd.b.l = rd_table[bank].memory[(addr & (TOWNS_BANK_SIZE - 2)) + 0];
+               nd.b.h = rd_table[bank].memory[(addr & (TOWNS_BANK_SIZE - 2)) + 1];
                return nd.w;
        }
        return 0xffff;
@@ -459,8 +462,8 @@ void TOWNS_MEMORY::write_dma_data16w(uint32_t addr, uint32_t data, int* wait)
                }
                pair32_t nd;
                nd.d = data;
-               wr_table[bank].memory[addr & (TOWNS_BANK_SIZE - 2) + 0] = nd.b.l;
-               wr_table[bank].memory[addr & (TOWNS_BANK_SIZE - 2) + 1] = nd.b.h;
+               wr_table[bank].memory[(addr & (TOWNS_BANK_SIZE - 2)) + 0] = nd.b.l;
+               wr_table[bank].memory[(addr & (TOWNS_BANK_SIZE - 2)) + 1] = nd.b.h;
        }
        return;
 }
@@ -572,10 +575,10 @@ uint32_t TOWNS_MEMORY::read_io8(uint32_t addr)
                break;
        case 0x0032:
                {
-                       //bool __cs = (d_serialrom->read_data8(SIG_SERIALROM_CS) == 0);
-                       bool __clk = (d_serialrom->read_data8(SIG_SERIALROM_CLK) != 0);
-                       bool __reset = (d_serialrom->read_data8(SIG_SERIALROM_RESET) != 0);
-                       bool __dat = (d_serialrom->read_data8(SIG_SERIALROM_DATA) != 0);
+                       //bool __cs = (d_serialrom->read_signal(SIG_SERIALROM_CS) == 0);
+                       bool __clk = (d_serialrom->read_signal(SIG_SERIALROM_CLK) != 0);
+                       bool __reset = (d_serialrom->read_signal(SIG_SERIALROM_RESET) != 0);
+                       bool __dat = (d_serialrom->read_signal(SIG_SERIALROM_DATA) != 0);
                        val = ((__reset) ? 0x80 : 0x00) | ((__clk) ? 0x40 : 0x00) | 0x3e | ((__dat) ? 0x01 : 0x00);
                }
                break;
@@ -671,9 +674,9 @@ void TOWNS_MEMORY::write_io8(uint32_t addr, uint32_t data)
                break;
        case 0x0032:
                {
-                       d_serialrom->write_data8(SIG_SERIALROM_CS, ~data, 0x20);
-                       d_serialrom->write_data8(SIG_SERIALROM_CLK, data, 0x40);
-                       d_serialrom->write_data8(SIG_SERIALROM_RESET, data, 0x80);
+                       d_serialrom->write_signal(SIG_SERIALROM_CS, ~data, 0x20);
+                       d_serialrom->write_signal(SIG_SERIALROM_CLK, data, 0x40);
+                       d_serialrom->write_signal(SIG_SERIALROM_RESET, data, 0x80);
                }
                break;
        case 0x006c: // Wait register.
@@ -728,22 +731,22 @@ uint32_t TOWNS_MEMORY::read_memory_mapped_io8(uint32_t addr)
        switch(addr & 0x7f) {
        case 0x00:
                if(d_vram != NULL) {
-                       val = d_vram->read_io8(FMTOWNS_VRAM_IO_CURSOR);
+                       //val = d_vram->read_io8(FMTOWNS_VRAM_IO_CURSOR);
                }
                break;
        case 0x01:
                if(d_vram != NULL) {
-                       val = d_vram->read_io8(FMTOWNS_VRAM_IO_FMR_RAMSELECT);
+                       //val = d_vram->read_io8(FMTOWNS_VRAM_IO_FMR_RAMSELECT);
                }
                break;
        case 0x02:
                if(d_vram != NULL) {
-                       val = d_vram->read_io8(FMTOWNS_VRAM_IO_FMR_DISPMODE);
+                       //val = d_vram->read_io8(FMTOWNS_VRAM_IO_FMR_DISPMODE);
                }
                break;
        case 0x03:
                if(d_vram != NULL) {
-                       val = d_vram->read_io8(FMTOWNS_VRAM_IO_FMR_PAGESEL);
+                       //val = d_vram->read_io8(FMTOWNS_VRAM_IO_FMR_PAGESEL);
                }
                break;
        case 0x04:
@@ -751,7 +754,7 @@ uint32_t TOWNS_MEMORY::read_memory_mapped_io8(uint32_t addr)
                break;
        case 0x06:
                if(d_vram != NULL) {
-                       val = d_vram->read_io8(FMTOWNS_VRAM_IO_SYNC_STATUS);
+                       //val = d_vram->read_io8(FMTOWNS_VRAM_IO_SYNC_STATUS);
                }
                break;
        //case 0x14:
@@ -759,12 +762,12 @@ uint32_t TOWNS_MEMORY::read_memory_mapped_io8(uint32_t addr)
        case 0x16:
        case 0x17:
                if(d_vram != NULL) {
-                       val = d_vram->read_io8(FMTOWNS_VRAM_KANJICG + (addr & 3));
+                       //val = d_vram->read_io8(FMTOWNS_VRAM_KANJICG + (addr & 3));
                }
                break;
        case 0x18:
                if(d_beep != NULL) {
-                       d_beep->write_signal(SIG_BEEP_ON, 1, 1);
+                       //d_beep->write_signal(SIG_BEEP_ON, 1, 1);
                }
                break;
        case 0x19:
@@ -791,22 +794,22 @@ void TOWNS_MEMORY::write_memory_mapped_io8(uint32_t addr, uint32_t data)
        switch(addr & 0x7f) {
        case 0x00:
                if(d_vram != NULL) {
-                       d_vram->write_io8(FMTOWNS_VRAM_IO_CURSOR, data);
+                       //d_vram->write_io8(FMTOWNS_VRAM_IO_CURSOR, data);
                }
                break;
        case 0x01:
                if(d_vram != NULL) {
-                       d_vram->write_io8(FMTOWNS_VRAM_IO_FMR_RAMSELECT, data);
+                       //d_vram->write_io8(FMTOWNS_VRAM_IO_FMR_RAMSELECT, data);
                }
                break;
        case 0x02:
                if(d_vram != NULL) {
-                       d_vram->write_io8(FMTOWNS_VRAM_IO_FMR_DISPMODE, data);
+                       //d_vram->write_io8(FMTOWNS_VRAM_IO_FMR_DISPMODE, data);
                }
                break;
        case 0x03:
                if(d_vram != NULL) {
-                       d_vram->write_io8(FMTOWNS_VRAM_IO_FMR_PAGESEL, data);
+                       //d_vram->write_io8(FMTOWNS_VRAM_IO_FMR_PAGESEL, data);
                }
                break;
        case 0x04:
@@ -818,12 +821,12 @@ void TOWNS_MEMORY::write_memory_mapped_io8(uint32_t addr, uint32_t data)
        case 0x16:
        case 0x17:
                if(d_vram != NULL) {
-                       d_vram->write_io8(FMTOWNS_VRAM_KANJICG + (addr & 3), data);
+                       //d_vram->write_io8(FMTOWNS_VRAM_KANJICG + (addr & 3), data);
                }
                break;
        case 0x18:
                if(d_beep != NULL) {
-                       d_beep->write_signal(SIG_BEEP_ON, 0, 1);
+                       //d_beep->write_signal(SIG_BEEP_ON, 0, 1);
                }
                break;
        case 0x19:
@@ -855,7 +858,7 @@ void TOWNS_MEMORY::write_signal(int ch, uint32_t data, uint32_t mask)
        } else if(ch == SIG_FMTOWNS_ROM_WAIT) {
 //             mem_wait_val = (int)data;
                set_wait_values();
-       } else if(ch == SIG_FMTOWNS_SET_VRAMWAIT) {
+       } else if(ch == SIG_FMTOWNS_VRAM_WAIT) {
                vram_wait_val = (int)data;
                set_wait_values();
        }
@@ -870,7 +873,7 @@ uint32_t TOWNS_MEMORY::read_signal(int ch)
                return (uint32_t)mem_wait_val;
        } else if(ch == SIG_FMTOWNS_ROM_WAIT) {
                return 6; // OK?
-       } else if(ch == SIG_FMTOWNS_SET_VRAMWAIT) {
+       } else if(ch == SIG_FMTOWNS_VRAM_WAIT) {
                return (uint32_t)vram_wait_val;
        } 
        return 0;
@@ -891,12 +894,13 @@ bool TOWNS_MEMORY::process_state(FILEIO* state_fio, bool loading)
        state_fio->StateValue(cpu_id);
        
        state_fio->StateValue(dma_is_vram);
-       state_ifo->StateValue(nmi_vector_protect);
-       state_ifo->StateValue(software_reset);
+       state_fio->StateValue(nmi_vector_protect);
+       state_fio->StateValue(software_reset);
 
        state_fio->StateValue(ankcg_enabled);
        state_fio->StateValue(event_wait_1us);
-
+       state_fio->StateValue(extra_nmi_val);
+       state_fio->StateValue(extra_nmi_mask);
        
        state_fio->StateArray(ram_page0, sizeof(ram_page0), 1);
        state_fio->StateArray(ram_page0, sizeof(ram_mmio), 1);
@@ -908,17 +912,17 @@ bool TOWNS_MEMORY::process_state(FILEIO* state_fio, bool loading)
                        extra_ram = NULL;
                }
                length_tmp = length_tmp & 0x3ff00000;
-               extra_ram_size = length_tmp;
+               extram_size = length_tmp;
                if(length_tmp > 0) {
                        extra_ram = (uint8_t*)malloc(length_tmp);
                }
                unset_memory_rw(0x00100000, 0x3fffffff);
                if(extra_ram == NULL) {
-                       extra_ram_size = 0;
+                       extram_size = 0;
                        return false;
                } else {
-                       state_fio->Fread(extra_ram, extra_ram_size, 1);
-                       set_memory_rw(0x00100000, (extra_ram_size + 0x00100000) - 1, extra_ram);
+                       state_fio->Fread(extra_ram, extram_size, 1);
+                       set_memory_rw(0x00100000, (extram_size + 0x00100000) - 1, extra_ram);
                }
                set_wait_values();
        } else {
@@ -926,8 +930,8 @@ bool TOWNS_MEMORY::process_state(FILEIO* state_fio, bool loading)
                if(extra_ram == NULL) {
                        state_fio->FputUint32_LE(0);
                } else {
-                       state_fio->FputUint32_LE(extra_ram_size & 0x3ff00000);
-                       state_fio->Fwrite(extra_ram, extra_ram_size, 1);
+                       state_fio->FputUint32_LE(extram_size & 0x3ff00000);
+                       state_fio->Fwrite(extra_ram, extram_size, 1);
                }
        }
                        
index 6e157b6..534d15b 100644 (file)
 #ifndef _TOWNS_MEMORY_H_
 #define _TOWNS_MEMORY_H_
 
-//#include "../vm.h"
-//#include "../../emu.h"
-#include "../device.h"
+#include "../vm.h"
+#include "../../emu.h"
+#include "device.h"
+#include "../../common.h"
 #include "../memory.h"
 #include "./towns_common.h"
 
 #define SIG_FMTOWNS_MACHINE_ID 1
+#define SIG_MEMORY_EXTNMI       2
 
-class I80386;
 // Page 0 (0000:00000 - 0000:fffff) is another routine.
 #define TOWNS_BANK_SHIFT 10
 #define TOWNS_BANK_SIZE (1 << TOWNS_BANK_SHIFT)
@@ -79,8 +80,10 @@ protected:
                int wait;
        } bank_t;
        
-       bank_t rd_table[(0xffffffff / TOWNS_BANK_SIZE) + 1];
-       bank_t wr_table[(0xffffffff / TOWNS_BANK_SIZE) + 1];
+       bank_t rd_table[0x100000000 >> TOWNS_BANK_SHIFT];
+       bank_t wr_table[0x100000000 >> TOWNS_BANK_SHIFT];
+       uint32_t bank_size;
+       uint32_t addr_mask;
        int addr_shift;
        bool initialized;
        
@@ -89,10 +92,10 @@ protected:
        
        I386 *d_cpu;
 
-       TOWNS_VRAM* d_vram;
-       TOWNS_SPRITE* d_sprite;       // 0x81000000 - 0x8101ffff ?
-       TOWNS_ROM_CARD* d_romcard[2]; // 0xc0000000 - 0xc0ffffff / 0xc1000000 - 0xc1ffffff
-       FMTOWNS::ADPCM* d_pcm;             // 0xc2200000 - 0xc2200fff 
+       DEVICE* d_vram;
+       DEVICE* d_sprite;       // 0x81000000 - 0x8101ffff ?
+       DEVICE* d_romcard[2]; // 0xc0000000 - 0xc0ffffff / 0xc1000000 - 0xc1ffffff
+       DEVICE* d_pcm;             // 0xc2200000 - 0xc2200fff 
        DEVICE* d_beep;
 
        DEVICE* d_dictionary;
@@ -116,11 +119,15 @@ protected:
        uint8_t ram_pagef[0x08000];       // 0x000f0000 - 0x000f7fff : RAM
 
        uint8_t *extra_ram;                  // 0x00100000 - (0x3fffffff) : Size is defined by extram_size;
-       uint32_t extra_ram_size;
+       uint32_t extram_size;
 
        uint32_t vram_wait_val;
        uint32_t mem_wait_val;
-
+       bool extra_nmi_mask;
+       bool extra_nmi_val;
+       bool software_reset;
+       bool nmi_vector_protect;
+       
        // ROM
        uint8_t rom_font1[0x40000];   // 0xc2100000 - 0xc23f0000
 #if 0
@@ -134,7 +141,10 @@ protected:
        DEVICE*   device_bank_adrs_cx[0x100000]; // Per 4KB.
        uint32_t type_bank_adrs_cx[0x100000]; // Per 4KB.
 
-       virtual void initialize_tables(void);
+       int event_wait_1us;
+
+//     virtual void initialize_tables(void);
+       virtual void set_wait_values();
        
 public:
        TOWNS_MEMORY(VM_TEMPLATE* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu) {
@@ -184,6 +194,7 @@ public:
        
        // common functions
        void initialize();
+       void release();
        void reset();
 
        // Belows are SUBSET of MEMORY::. Because access patterns of Towns are differ per DEVICEs.
@@ -225,11 +236,11 @@ public:
        uint32_t __FASTCALL read_dma_data16(uint32_t addr);
 
        // With wait
-       void __FASTCALL write_dma_data8w(uint32_t addr, uint32_t data, int wait);
-       uint32_t __FASTCALL read_dma_data8w(uint32_t addr, int wait);
+       void __FASTCALL write_dma_data8w(uint32_t addr, uint32_t data, int *wait);
+       uint32_t __FASTCALL read_dma_data8w(uint32_t addr, int *wait);
        // Using [read|write]_dma_data16 for DMAC 16bit mode (SCSI/CDROM?).
-       void __FASTCALL write_dma_data16w(uint32_t addr, uint32_t data, int wait);
-       uint32_t __FASTCALL read_dma_data16w(uint32_t addr, int wait);
+       void __FASTCALL write_dma_data16w(uint32_t addr, uint32_t data, int *wait);
+       uint32_t __FASTCALL read_dma_data16w(uint32_t addr, int *wait);
        
        virtual void     __FASTCALL write_io8(uint32_t addr, uint32_t data);
        virtual uint32_t __FASTCALL read_io8(uint32_t addr);
@@ -240,7 +251,9 @@ public:
        void __FASTCALL write_signal(int id, uint32_t data, uint32_t mask);
        uint32_t __FASTCALL read_signal(int ch);
        
-       void event_frame();
+       //void event_frame();
+       void event_callback(int id, int err);
+       
        bool process_state(FILEIO* state_fio, bool loading);
        
        // unique functions
@@ -252,7 +265,7 @@ public:
        {
                machine_id = id;
        }
-       void set_context_vram(TOWNS_VRAM* device)
+       void set_context_vram(DEVICE* device)
        {
                d_vram = device;
        }
@@ -278,17 +291,17 @@ public:
        {
                d_beep = device;
        }
-       void set_context_sprite(TOWNS_SPRITE* device)
+       void set_context_sprite(DEVICE* device)
        {
                d_sprite = device;
                register_output_signal(&outputs_ram_wait, device, SIG_FMTOWNS_RAM_WAIT, 0xffffffff);
                register_output_signal(&outputs_rom_wait, device, SIG_FMTOWNS_ROM_WAIT, 0xffffffff);
        }
-       void set_context_romcard(TOWNS_ROM_CARD* device, int num)
+       void set_context_romcard(DEVICE* device, int num)
        {
                d_romcard[num & 1] = device;
        }
-       void set_context_pcm(FMTOWNS::ADPCM* device)
+       void set_context_pcm(DEVICE* device)
        {
                d_pcm = device;
                register_output_signal(&outputs_ram_wait, device, SIG_FMTOWNS_RAM_WAIT, 0xffffffff);
@@ -298,7 +311,7 @@ public:
        {
                d_serialrom = device;
        }
-       void set_context_machine_id(uint16_t val)
+       void set_machine_id(uint16_t val)
        {
                machine_id = val & 0xfff8;
        }
index c9b2c7c..f5983cb 100644 (file)
@@ -8,6 +8,7 @@
 */
 
 #include "../../common.h"
+#include "./towns_vram.h"
 #include "./towns_sprite.h"
 
 namespace FMTOWNS {
@@ -18,6 +19,7 @@ void TOWNS_SPRITE::initialize(void)
        reg_ctrl = 0x0000; // REG#00, #01
        reg_voffset = 0x0000; // REG#02, #03
        reg_hoffset = 0x0000; // REG#04, #05
+       reg_index = 0x0000;
        disp_page1 = false;
        disp_page0 = false;
        reg_spen = false;
@@ -31,8 +33,6 @@ void TOWNS_SPRITE::initialize(void)
        max_sprite_per_frame = 224;
        frame_sprite_count = 0; 
 
-       vram_buffer = NULL;
-       mask_buffer = NULL;
 }
 
 void TOWNS_SPRITE::reset()
@@ -41,6 +41,7 @@ void TOWNS_SPRITE::reset()
        reg_ctrl = 0x0000; // REG#00, #01
        reg_voffset = 0x0000; // REG#02, #03
        reg_hoffset = 0x0000; // REG#04, #05
+       reg_index = 0x0000;
        disp_page1 = false;
        disp_page0 = false;
        reg_spen = false;
@@ -544,7 +545,7 @@ __DECL_VECTORIZED_LOOP
                        }
                        // void __FASTCALL VRAM::write_sprite_data(int x, int y, int xoffset, int yoffset, uint16_t *ptr __assume_aligned(16), int width);
                        if(d_vram != NULL) {
-                               d_vram->write_sprite_data(x, y + yy, xoffset, yoffset, lbuf, 16);
+                               //d_vram->write_sprite_data(x, y + yy, xoffset, yoffset, lbuf, 16);
                        }
                }
        } else if(is_halfx) { // halfx only
@@ -564,7 +565,7 @@ __DECL_VECTORIZED_LOOP
                                lbuf[xx] = ((lbuf[xx] >> 2) & 0x7fff) | mbuf[xx];
                        }
                        if(d_vram != NULL) {
-                               d_vram->write_sprite_data(x, y + yy, xoffset, yoffset, lbuf, 8);
+                               //d_vram->write_sprite_data(x, y + yy, xoffset, yoffset, lbuf, 8);
                        }
                }
        } else if(is_halfy) { // halfy only
@@ -586,7 +587,7 @@ __DECL_VECTORIZED_LOOP
                                lbuf[xx] = ((lbuf[xx] >> 1) & 0x7fff) | mbuf[xx];
                        }
                        if(d_vram != NULL) {
-                               d_vram->write_sprite_data(x, y + (yy >>1), xoffset, yoffset, lbuf, 16);
+                               //d_vram->write_sprite_data(x, y + (yy >>1), xoffset, yoffset, lbuf, 16);
                        }
                }
        } else { //halfx &&halfy
@@ -608,7 +609,7 @@ __DECL_VECTORIZED_LOOP
                                lbuf[xx] = ((lbuf[xx] >> 2) & 0x7fff) | mbuf[xx];
                        }
                        if(d_vram != NULL) {
-                               d_vram->write_sprite_data(x, y + (yy >>1), xoffset, yoffset, lbuf, 8);
+                               //d_vram->write_sprite_data(x, y + (yy >>1), xoffset, yoffset, lbuf, 8);
                        }
                }
        }
@@ -633,7 +634,7 @@ void TOWNS_SPRITE::render_full()
                for(; render_num < (int)lot; render_num++) {
                        
                        uint32_t addr = render_num << 3;
-                       pair16_t _nx, _ny, _nattr, _ny;
+                       pair16_t _nx, _ny, _nattr, _ncol;
                        _nx.b.l = pattern_ram[addr + 0];
                        _nx.b.h = pattern_ram[addr + 1];
                        _ny.b.l = pattern_ram[addr + 2];
@@ -666,7 +667,7 @@ void TOWNS_SPRITE::render_part(int start, int end)
                if((frame_sprite_count >= max_sprite_per_frame) && (max_sprite_per_frame > 0)) return;
                for(render_num = start; render_num < end; render_num++) {
                        uint32_t addr = render_num << 3;
-                       pair16_t _nx, _ny, _nattr, _ny;
+                       pair16_t _nx, _ny, _nattr, _ncol;
                        _nx.b.l = pattern_ram[addr + 0];
                        _nx.b.h = pattern_ram[addr + 1];
                        _ny.b.l = pattern_ram[addr + 2];
@@ -886,7 +887,7 @@ void TOWNS_SPRITE::write_data32(uint32_t addr, uint32_t data)
        return;
 }
 
-void FMTOWNS_SPRITE::event_frame()
+void TOWNS_SPRITE::event_frame()
 {
        uint16_t lot = reg_index & 0x3ff;
        if(reg_spen && !(sprite_enabled)) {
@@ -921,7 +922,7 @@ void FMTOWNS_SPRITE::event_frame()
        }
 }
 
-void FMTOWNS_SPRITE::do_vline_hook(int line)
+void TOWNS_SPRITE::do_vline_hook(int line)
 {
        int lot = reg_index & 0x3ff;
        if(!split_rendering) return;
@@ -941,7 +942,7 @@ void FMTOWNS_SPRITE::do_vline_hook(int line)
 }
 // Q: Is changing pages syncing to Frame?
 // ToDo: Implement VRAM.
-void FMTOWNS_SPRITE::write_signal(int id, uint32_t data, uint32_t mask)
+void TOWNS_SPRITE::write_signal(int id, uint32_t data, uint32_t mask)
 {
        if(id == SIG_TOWNS_SPRITE_HOOK_VLINE) {
                int line = data & 0x1ff;
@@ -963,6 +964,7 @@ bool TOWNS_SPRITE::process_state(FILEIO* state_fio, bool loading)
        }
        
        state_fio->StateValue(reg_addr);
+       state_fio->StateValue(reg_ctrl);
        state_fio->StateArray(reg_data, sizeof(reg_data), 1);
        // RAMs
        state_fio->StateArray(pattern_ram, sizeof(pattern_ram), 1);
@@ -975,6 +977,7 @@ bool TOWNS_SPRITE::process_state(FILEIO* state_fio, bool loading)
        state_fio->StateValue(disp_page1);
 
        state_fio->StateValue(sprite_enabled);
+       state_fio->StateValue(frame_sprite_count);
        
        state_fio->StateValue(render_num);
        state_fio->StateValue(render_mod);
index f305daa..685b73b 100644 (file)
@@ -5,9 +5,11 @@
 #include "../../emu.h"
 #include "../device.h"
 
-#define SIG_TOWNS_SPRITE_HOOK_VLINE 256
-#define SIG_TOWNS_SPRITE_SET_LINES  257
-
+#define SIG_TOWNS_SPRITE_HOOK_VLINE  256
+#define SIG_TOWNS_SPRITE_SET_LINES   257
+#define SIG_TOWNS_SPRITE_BUSY        258
+#define SIG_TOWNS_SPRITE_CALL_HSYNC  259
+#define SIG_TOWNS_SPRITE_CALL_VSTART 260
 namespace FMTOWNS {
        class TOWNS_VRAM;
 }
@@ -22,6 +24,8 @@ protected:
        uint8_t reg_addr;
        uint8_t reg_data[8];
        // #0, #1
+       uint16_t reg_ctrl;
+   
        bool reg_spen;
        uint16_t reg_index;
        uint8_t pattern_ram[0x20000];
@@ -30,13 +34,14 @@ protected:
        uint16_t reg_hoffset;
        bool disp_page0;
        bool disp_page1;
+       int frame_sprite_count;
+       bool sprite_enabled;
        
        bool now_transferring;
        
        int render_num;
        int render_mod;
        int render_lines;
-       bool sprite_enabled;
        
        bool split_rendering;
        int max_sprite_per_frame;
index 6e6bf58..5b8637d 100644 (file)
@@ -119,7 +119,7 @@ uint32_t SYSROM::read_data32w(uint32_t addr, int* wait)
        nd.b.h  = read_data8w((addr & 0xfffffffc) + 1, &dummy);
        nd.b.h2 = read_data8w((addr & 0xfffffffc) + 2, &dummy);
        nd.b.h3 = read_data8w((addr & 0xfffffffc) + 3, wait);
-       return nb.d;
+       return nd.d;
 }
        
 void SYSROM::write_data8w(uint32_t addr, uint32_t data, int* wait)
@@ -166,8 +166,8 @@ void SYSROM::write_data16w(uint32_t addr, uint32_t data, int* wait)
        int dummy;
        nd.w = (uint16_t)data;
        // OK?
-       write_data8w((addr & 0xfffffffe) + 0, nb.b.l, &dummy);
-       write_data8w((addr & 0xfffffffe) + 1, nb.b.h, wait);
+       write_data8w((addr & 0xfffffffe) + 0, nd.b.l, &dummy);
+       write_data8w((addr & 0xfffffffe) + 1, nd.b.h, wait);
 }
 
 void SYSROM::write_data32w(uint32_t addr, uint32_t data, int* wait)
@@ -175,10 +175,10 @@ void SYSROM::write_data32w(uint32_t addr, uint32_t data, int* wait)
        pair32_t nd;
        int dummy;
        nd.d = data;
-       write_data8w((addr & 0xfffffffc) + 0, nb.b.l, &dummy);
-       write_data8w((addr & 0xfffffffc) + 1, nb.b.h, &dummy);
-       write_data8w((addr & 0xfffffffc) + 2, nb.b.h2, &dummy);
-       write_data8w((addr & 0xfffffffc) + 3, nb.b.h3, wait);
+       write_data8w((addr & 0xfffffffc) + 0, nd.b.l, &dummy);
+       write_data8w((addr & 0xfffffffc) + 1, nd.b.h, &dummy);
+       write_data8w((addr & 0xfffffffc) + 2, nd.b.h2, &dummy);
+       write_data8w((addr & 0xfffffffc) + 3, nd.b.h3, wait);
 }
        
 void SYSROM::write_signal(int ch, uint32_t data, uint32_t mask)
index 8473c35..8db5139 100644 (file)
@@ -11,6 +11,7 @@
 
 #include "common.h"
 #include "./towns_common.h"
+#include "./towns_crtc.h"
 #include "./towns_vram.h"
 
 #define _CLEAR_COLOR RGBA_COLOR(0,0,0,0)
@@ -26,6 +27,22 @@ void TOWNS_VRAM::initialize()
 
 }
 
+void TOWNS_VRAM::make_dirty_vram(uint32_t addr, int bytes)
+{
+       if(bytes <= 0) return;
+       uint32_t naddr1 = (addr & 0x7ffff) >> 3;
+       uint32_t naddr2 = ((addr + bytes) & 0x7ffff) >> 3;
+       if(naddr1 != naddr2) {
+               for(uint32_t a = naddr1; a != naddr2;) {
+                       dirty_flag[a] = true;
+                       a = (a + 1) & (0x7ffff >> 3);
+               }
+               dirty_flag[naddr2] = true;
+       } else {
+               dirty_flag[naddr1] = true;
+       }
+}
+       
 void TOWNS_VRAM::write_memory_mapped_io8(uint32_t addr, uint32_t data)
 {
        uint32_t naddr = addr & 0xfff80000;
@@ -60,7 +77,9 @@ void TOWNS_VRAM::write_memory_mapped_io8(uint32_t addr, uint32_t data)
                case 0xcf000:
                        // Reserved
                        if((addr < 0xcff80) && (addr >= 0xcff88)) {
-                               d_sprite->write_data8(addr & 0x7fff, data);
+                               if(d_sprite != NULL) {
+                                       d_sprite->write_data8(addr & 0x7fff, data);
+                               }
                        } else {
                                write_mmio8(addr, data);
                        }                               
@@ -111,10 +130,12 @@ void TOWNS_VRAM::write_memory_mapped_io16(uint32_t addr, uint32_t data)
                case 0xcf000:
                        // Reserved
                        if((addr < (0xcff80 - 1)) && (addr >= 0xcff88)) {
-                               d_sprite->write_data16(addr & 0x7fff, data);
+                               if(d_sprite != NULL) {
+                                       d_sprite->write_data16(addr & 0x7fff, data);
+                               }
                        } else {
-                               pair16_t d;
-                               d.2 = data;
+                               pair32_t d;
+                               d.w.l = data;
                                write_mmio8(addr, d.b.l);
                                write_mmio8(addr + 1, d.b.h);
                        }                               
@@ -131,7 +152,7 @@ void TOWNS_VRAM::write_memory_mapped_io16(uint32_t addr, uint32_t data)
        
 }
        
-void TOWNS_VRAM::write_memory_mapped_io8(uint32_t addr, uint32_t data)
+void TOWNS_VRAM::write_memory_mapped_io32(uint32_t addr, uint32_t data)
 {
        uint32_t naddr = addr & 0xfff80000;
        switch(naddr) {
@@ -165,7 +186,9 @@ void TOWNS_VRAM::write_memory_mapped_io8(uint32_t addr, uint32_t data)
                case 0xcf000:
                        // Reserved
                        if((addr < (0xcff80 - 3)) && (addr >= 0xcff88)) {
-                               d_sprite->write_data32(addr & 0x7fff, data);
+                               if(d_sprite != NULL) {
+                                       d_sprite->write_data32(addr & 0x7fff, data);
+                               }
                        } else {
                                pair32_t d;
                                d.d = data;
@@ -220,7 +243,10 @@ uint32_t TOWNS_VRAM::read_memory_mapped_io8(uint32_t addr)
                case 0xcf000:
                        // Reserved
                        if((addr < 0xcff80) && (addr >= 0xcff88)) {
-                               return d_sprite->read_data8(addr & 0x7fff);
+                               if(d_sprite != NULL) {
+                                       return d_sprite->read_data8(addr & 0x7fff);
+                               }
+                               return 0xff;
                        } else {
                                return read_mmio8(addr);
                        }                               
@@ -268,11 +294,14 @@ uint32_t TOWNS_VRAM::read_memory_mapped_io16(uint32_t addr)
                case 0xcf000:
                        // Reserved
                        if((addr < (0xcff80 - 1)) && (addr >= 0xcff88)) {
-                               return d_sprite->read_data16(addr & 0x7fff);
+                               if(d_sprite != NULL) {
+                                       return d_sprite->read_data16(addr & 0x7fff);
+                               }
+                               return 0xff;
                        } else {
                                pair16_t d;
-                               d.l = read_mmio8(addr);
-                               d.h = read_mmio8(addr + 1);
+                               d.b.l = read_mmio8(addr);
+                               d.b.h = read_mmio8(addr + 1);
                                return d.w;
                        }                               
                        break;
@@ -320,13 +349,16 @@ uint32_t TOWNS_VRAM::read_memory_mapped_io32(uint32_t addr)
                case 0xcf000:
                        // Reserved
                        if((addr < (0xcff80 - 3)) && (addr >= 0xcff88)) {
-                               return d_sprite->read_data16(addr & 0x7fff);
+                               if(d_sprite != NULL) {
+                                       return d_sprite->read_data16(addr & 0x7fff);
+                               }
+                               return 0xff;
                        } else {
                                pair32_t d;
-                               d.l = read_mmio8(addr);
-                               d.h = read_mmio8(addr + 1);
-                               d.h2 = read_mmio8(addr + 2);
-                               d.h3 = read_mmio8(addr + 3);
+                               d.b.l = read_mmio8(addr);
+                               d.b.h = read_mmio8(addr + 1);
+                               d.b.h2 = read_mmio8(addr + 2);
+                               d.b.h3 = read_mmio8(addr + 3);
                                return d.d;
                        }                               
                        break;
@@ -359,7 +391,6 @@ uint32_t TOWNS_VRAM::read_raw_vram16(uint32_t addr)
        }
        addr = addr & 0x7ffff;
        if(is_wrap) {
-               pair16_t a;
                a.b.l = vram[addr];
                a.b.h = vram[wrap_addr];
        } else {
@@ -396,7 +427,7 @@ uint32_t TOWNS_VRAM::read_raw_vram32(uint32_t addr)
                a.b.h3 = vram[((addr + 3) & wrap_mask) | wrap_addr];
        } else {
 #ifdef __LITTLE_ENDIAN__
-               uint32_t* p = (uint32_t)(&vram[addr]);
+               uint32_t* p = (uint32_t*)(&vram[addr]);
                a.d = *p;
 #else
                a.read_4bytes_le_from(&vram[addr]);
@@ -462,7 +493,7 @@ void TOWNS_VRAM::write_raw_vram16(uint32_t addr, uint32_t data)
                b.b.h = vram[wrap_addr];
                c.w = b.w;
                if(mask != 0xffff) {
-                       b.w = b.w & ~(mask);
+                       b.w = b.w & ~mask;
                        a.w = a.w & mask;
                        a.w = a.w | b.w;
                }
@@ -474,15 +505,15 @@ void TOWNS_VRAM::write_raw_vram16(uint32_t addr, uint32_t data)
                }
        } else {
 #ifdef __LITTLE_ENDIAN__
-               uint16_t* p = (uint16_t)(&vram[addr]);
+               uint16_t* p = (uint16_t)(&vram[addr]);
                b.w = *p;
 #else
                b.read_2bytes_le_from(&vram[addr]);
 #endif
                c.w = b.w;
                if(mask != 0xffff) {
-                       b.w = b.w & ~(mask.w);
-                       a.w = a.w & mask.w;
+                       b.w = b.w & ~mask;
+                       a.w = a.w & mask;
                        a.w = a.w | b.w;
                }
                if(a.w != c.w) {
@@ -525,7 +556,7 @@ void TOWNS_VRAM::write_raw_vram32(uint32_t addr, uint32_t data)
                
                c.d = b.d;
                if(mask != 0xffffffff) {
-                       b.d = b.d & ~(mask);
+                       b.d = b.d & ~mask;
                        a.d = a.d & mask;
                        a.d = a.d | b.d;
                }
@@ -540,7 +571,7 @@ void TOWNS_VRAM::write_raw_vram32(uint32_t addr, uint32_t data)
                }
        } else {
 #ifdef __LITTLE_ENDIAN__
-               uint32_t* p = (uint32_t)(&vram[addr]);
+               uint32_t* p = (uint32_t)(&vram[addr]);
                b.d = *p;
 #else
                b.read_4bytes_le_from(&vram[addr]);
@@ -563,10 +594,12 @@ void TOWNS_VRAM::write_raw_vram32(uint32_t addr, uint32_t data)
        return;
 }
 
-void TOWNS_CRTC::write_mmio8(uint32_t addr, uint32_t data)
+void TOWNS_VRAM::write_mmio8(uint32_t addr, uint32_t data)
 {
        if((addr < 0xcff80) || (addr >= 0xcff88)) {
-               d_sprite->write_data8(addr & 0x7fff, data);
+               if(d_sprite != NULL) {
+                       d_sprite->write_data8(addr & 0x7fff, data);
+               }
                return;
        }
        switch(addr) {
@@ -578,10 +611,12 @@ void TOWNS_CRTC::write_mmio8(uint32_t addr, uint32_t data)
                r50_ramsel = data & 0x0f;
                break;
        case 0xcff82:
-               d_crtc->write_signal(SIG_TOWNS_CRTC_MMIO_CF882H, data);
+               if(d_crtc != NULL) {
+                       d_crtc->write_signal(SIG_TOWNS_CRTC_MMIO_CF882H, data, 0xffffffff);
+               }
                break;
        case 0xcff83:
-               r50_gvramset = (data & 0x10) >> 4;
+               r50_gvramsel = (data & 0x10) >> 4;
                break;
        case 0xcff86:
                break;
@@ -590,10 +625,13 @@ void TOWNS_CRTC::write_mmio8(uint32_t addr, uint32_t data)
        }
 }
 
-uint32_t TOWNS_CRTC::read_mmio8(uint32_t addr)
+uint32_t TOWNS_VRAM::read_mmio8(uint32_t addr)
 {
        if((addr < 0xcff80) || (addr >= 0xcff88)) {
-               return d_sprite->read_data8(addr & 0x7fff);
+               if(d_sprite != NULL) {
+                       return d_sprite->read_data8(addr & 0x7fff);
+               }
+               return 0xff;
        }
        switch(addr) {
        case 0xcff80:
@@ -606,7 +644,7 @@ uint32_t TOWNS_CRTC::read_mmio8(uint32_t addr)
                return d_crtc->read_signal(SIG_TOWNS_CRTC_MMIO_CF882H);
                break;
        case 0xcff83:
-               return (r50_gvramset << 4);
+               return (r50_gvramsel << 4);
                break;
        case 0xcff86:
                {
@@ -626,7 +664,6 @@ uint32_t TOWNS_CRTC::read_mmio8(uint32_t addr)
 uint32_t TOWNS_VRAM::read_plane_data8(uint32_t addr)
 {
        // Plane Access
-       pair_t data_p;
        uint32_t x_addr = 0;
        uint8_t *p = (uint8_t*)vram;
        uint32_t mod_pos;
@@ -686,7 +723,6 @@ uint32_t TOWNS_VRAM::read_plane_data32(uint32_t addr)
 void TOWNS_VRAM::write_plane_data8(uint32_t addr, uint32_t data)
 {
        // Plane Access
-       pair_t data_p;
        uint32_t x_addr = 0;
        uint8_t *p = (uint8_t*)vram;
        uint32_t mod_pos;
@@ -753,7 +789,7 @@ void TOWNS_VRAM::write_plane_data32(uint32_t addr, uint32_t data)
 
 // I/Os
 // Palette.
-void TOWNS_CRTC::calc_apalette16(int layer, int index)
+void TOWNS_VRAM::calc_apalette16(int layer, int index)
 {
        if(index < 0) return;
        if(index > 15) return;
@@ -768,11 +804,11 @@ void TOWNS_CRTC::calc_apalette16(int layer, int index)
        }
 }
 
-void TOWNS_CRTC::calc_apalette256(int index)
+void TOWNS_VRAM::calc_apalette256(int index)
 {
        if(index < 0) return;
        if(index > 255) return;
-       apalette_256_rgb[layer][index] =
+       apalette_256_rgb[index] =
                ((uint32_t)apalette_b) |
                ((uint32_t)apalette_r << 8) |
                ((uint32_t)apalette_g << 16);
@@ -783,7 +819,7 @@ void TOWNS_CRTC::calc_apalette256(int index)
        }
 }
 
-void TOWNS_CRTC::set_apalette_r(int layer, uint8_t val)
+void TOWNS_VRAM::set_apalette_r(int layer, uint8_t val)
 {
        apalette_r = val;
        if(apalette_code < 16) {
@@ -793,7 +829,7 @@ void TOWNS_CRTC::set_apalette_r(int layer, uint8_t val)
        calc_apalette256((int)apalette_code % 256);
 }
 
-void TOWNS_CRTC::set_apalette_g(int layer, uint8_t val)
+void TOWNS_VRAM::set_apalette_g(int layer, uint8_t val)
 {
        apalette_g = val;
        if(apalette_code < 16) {
@@ -803,7 +839,7 @@ void TOWNS_CRTC::set_apalette_g(int layer, uint8_t val)
        calc_apalette256((int)apalette_code % 256);
 }
 
-void TOWNS_CRTC::set_apalette_b(int layer, uint8_t val)
+void TOWNS_VRAM::set_apalette_b(int layer, uint8_t val)
 {
        apalette_b = val;
        if(apalette_code < 16) {
@@ -813,15 +849,19 @@ void TOWNS_CRTC::set_apalette_b(int layer, uint8_t val)
        calc_apalette256((int)apalette_code % 256);
 }
 
-void TOWNS_CRTC::set_apalette_num(int layer, uint8_t val)
+void TOWNS_VRAM::set_apalette_num(uint8_t val)
 {
        apalette_code = ((int)val) % 256;
 }
 
+void TOWNS_VRAM::write_signal(int id, uint32_t data, uint32_t mask)
+{
+       // ToDo
+}
 // Renderers
 
 
-
 }
+
 #undef _CLEAR_COLOR
 
index b06b2d7..e2d6ea6 100644 (file)
 #define _TOWNS_VRAM_H_
 
 #include "../vm.h"
-#include "../emu.h"
+#include "../../emu.h"
 #include "device.h"
 #include "../../common.h"
+#include "towns_common.h"
 
 #if defined(_USE_QT)
 #include <QMutex>
 #define TOWNS_VRAM_ADDR_MASK 0x7ffff
 // VRAM DIRECT ACCESS: For Sprite. You should access with 16bit
 // You can write raw data, drawing with colorkey is automatically.
-#define SIG_TOWNS_TRANSFER_SPRITE_DATA 0x100000
-#define SIG_TOWNS_SET_SPRITE_BANK      0x140000
-#define SIG_TOWNS_CLEAR_SPRITE_BUFFER  0x140001
+#define SIG_TOWNS_TRANSFER_SPRITE_DATA   0x100000
+#define SIG_TOWNS_SET_SPRITE_BANK        0x140000
+#define SIG_TOWNS_CLEAR_SPRITE_BUFFER    0x140001
 // Do render with any mode. You should set vline to arg.
-#define SIG_TOWNS_RENDER_RASTER    0x01
-#define SIG_TOWNS_RENDER_FULL      0x02
-#define SIG_TOWNS_VRAM_VSTART      0x03
-#define SIG_TOWNS_VRAM_VBLANK      0x04
-#define SIG_TOWNS_VRAM_VSYNC       0x05
-#define SIG_TOWNS_VRAM_HSYNC       0x06
-#define SIG_TOWNS_VRAM_SET_VLINE   0x07
-#define SIG_TOWNS_RENDER_FLAG      0x08
+#define SIG_TOWNS_RENDER_RASTER          0x01
+#define SIG_TOWNS_RENDER_FULL            0x02
+#define SIG_TOWNS_VRAM_VSTART            0x03
+#define SIG_TOWNS_VRAM_VBLANK            0x04
+#define SIG_TOWNS_VRAM_VSYNC             0x05
+#define SIG_TOWNS_VRAM_HSYNC             0x06
+#define SIG_TOWNS_VRAM_SET_VLINE         0x07
+#define SIG_TOWNS_RENDER_FLAG            0x08
+#define SIG_TOWNS_VRAM_DP0               0x0a
+#define SIG_TOWNS_VRAM_DP1               0x0b
+#define SIG_TOWNS_VRAM_FRAMEBUFFER_READY 0x10
+#define SIG_TOWNS_VRAM_SWAP_FRAMEBUFFER  0x11
 
 namespace FMTOWNS {
 class TOWNS_VRAM : public DEVICE
 {
 protected:
+       DEVICE* d_sprite;
+       DEVICE* d_crtc;
        uint32_t page_modes[4];
        bool line_rendered[2][TOWNS_CRTC_MAX_LINES];
        
@@ -58,8 +65,6 @@ protected:
        uint8_t packed_access_mask_hi;
 
        bool dirty_flag[0x80000 >> 3]; // Per 8bytes : 16pixels(16colors) / 8pixels(256) / 4pixels(32768)
-
-       
        
        // FMR50 Compatible registers. They are mostly dummy.
        // Digital paletts. I/O FD98H - FD9FH.
@@ -105,50 +110,96 @@ protected:
        bool has_hardware_blending;
        // End.
 
+       virtual void __FASTCALL write_raw_vram8(uint32_t addr, uint32_t data);
+       virtual void __FASTCALL write_raw_vram16(uint32_t addr, uint32_t data);
+       virtual void __FASTCALL write_raw_vram32(uint32_t addr, uint32_t data);
+       virtual uint32_t __FASTCALL read_raw_vram8(uint32_t addr);
+       virtual uint32_t __FASTCALL read_raw_vram16(uint32_t addr);
+       virtual uint32_t __FASTCALL read_raw_vram32(uint32_t addr);
+       virtual void __FASTCALL write_mmio8(uint32_t addr, uint32_t data);
+       virtual uint32_t __FASTCALL read_mmio8(uint32_t addr);
+
+       virtual uint32_t __FASTCALL read_plane_data8(uint32_t addr);
+       virtual uint32_t __FASTCALL read_plane_data16(uint32_t addr);
+       virtual uint32_t __FASTCALL read_plane_data32(uint32_t addr);
+       virtual void __FASTCALL write_plane_data8(uint32_t addr, uint32_t data);
+       virtual void __FASTCALL write_plane_data16(uint32_t addr, uint32_t data);
+       virtual void __FASTCALL write_plane_data32(uint32_t addr, uint32_t data);
+
+       virtual void __FASTCALL calc_apalette16(int layer, int index);
+       virtual void __FASTCALL calc_apalette256(int index);
+       virtual void __FASTCALL set_apalette_r(int layer, uint8_t val);
+       virtual void __FASTCALL set_apalette_g(int layer, uint8_t val);
+       virtual void __FASTCALL set_apalette_b(int layer, uint8_t val);
+       virtual void __FASTCALL set_apalette_num(uint8_t val);
+       virtual void __FASTCALL make_dirty_vram(uint32_t addr, int bytes);
 
 public:
        TOWNS_VRAM(VM_TEMPLATE* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
        {
                memset(vram, 0x00, sizeof(vram));
+               d_sprite = NULL;
+               d_crtc = NULL;
        }
        ~TOWNS_VRAM() {}
-       
-       virtual uint32_t read_memory_mapped_io8(uint32_t addr);
-       virtual uint32_t read_memory_mapped_io16(uint32_t addr);
-       virtual uint32_t read_memory_mapped_io32(uint32_t addr);
-       virtual void write_memory_mapped_io8(uint32_t addr, uint32_t data);
-       virtual void write_memory_mapped_io16(uint32_t addr, uint32_t data);
-       virtual void write_memory_mapped_io32(uint32_t addr, uint32_t data);
 
-       uint32_t read_io8(uint32_t addr);
-       void write_io8(uint32_t addr, uint32_t data);
+       virtual void initialize();
+       virtual uint32_t __FASTCALL read_memory_mapped_io8(uint32_t addr);
+       virtual uint32_t __FASTCALL read_memory_mapped_io16(uint32_t addr);
+       virtual uint32_t __FASTCALL read_memory_mapped_io32(uint32_t addr);
+       virtual void __FASTCALL write_memory_mapped_io8(uint32_t addr, uint32_t data);
+       virtual void __FASTCALL write_memory_mapped_io16(uint32_t addr, uint32_t data);
+       virtual void __FASTCALL write_memory_mapped_io32(uint32_t addr, uint32_t data);
 
        
-       void write_signal(int id, uint32_t data, uint32_t mask); // Do render
+       void __FASTCALL write_signal(int id, uint32_t data, uint32_t mask); // Do render
 
        // Unique Functions
-       uint8_t* get_vram_address(uint32_t offset)
+       virtual uint8_t* __FASTCALL get_vram_address(uint32_t offset)
        {
                if(offset >= 0x80000) return NULL; // ToDo
                return &(vram[offset]);
        }
-       uint32_t get_vram_size()
+       virtual uint32_t __FASTCALL get_vram_size()
        {
                return 0x80000; // ToDo
        }
-       void lock_framebuffer(int layer, int bank)
+       virtual void __FASTCALL lock_framebuffer(int layer, int bank)
        {
 #if defined(_USE_QT)
                vram_lock[bank][layer].lock();
 #endif
        }
-       void unlock_framebuffer(int layer, int bank)
+       virtual void __FASTCALL unlock_framebuffer(int layer, int bank)
        {
 #if defined(_USE_QT)
                vram_lock[bank][layer].unlock();
 #endif
        }
-       
+       void get_analog_palette(int ch, scrntype_t *dst)
+       {
+               scrntype_t *p;
+               if(dst == NULL) return;
+               switch(ch) {
+               case 0:
+               case 1:
+                       p = &(apalette_16_pixel[ch][0]);
+                       memcpy(dst, p, 16 * sizeof(scrntype_t));
+                       break;
+               case 2:
+                       p = &(apalette_256_pixel[0]);
+                       memcpy(dst, p, 256 * sizeof(scrntype_t));
+                       break;
+               }
+       }
+       void set_context_sprite(DEVICE *dev)
+       {
+               d_sprite = dev;
+       }
+       void set_context_crtc(DEVICE *dev)
+       {
+               d_crtc = dev;
+       }
        // New APIs?
        // End.
 };
diff --git a/source/src/vm/fmtowns/ym2612.cpp b/source/src/vm/fmtowns/ym2612.cpp
new file mode 100644 (file)
index 0000000..5f955d0
--- /dev/null
@@ -0,0 +1,559 @@
+/*
+       Skelton for retropc emulator
+
+       Author : Takeda.Toshiya
+       Date   : 2006.09.15-
+
+       [ YM2203 / YM2608 ]
+*/
+
+#include "ym2612.h"
+#include "debugger.h"
+#include <math.h>
+
+#define EVENT_FM_TIMER 0
+
+#ifdef SUPPORT_MAME_FM_DLL
+// thanks PC8801MA改
+#include "fmdll/fmdll.h"
+static CFMDLL* fmdll = NULL;
+static int chip_reference_counter = 0;
+static bool dont_create_multiple_chips = false;
+#endif
+
+void YM2612::initialize()
+{
+       DEVICE::initialize();
+       // ToDo: Set type via software interface for AY-3-891x.
+       if(this_device_name[0] == _T('\0')) {
+               set_device_name(_T("YM2612 OPN2"));
+       }
+       opn2 = new FM::OPN2;
+
+#ifdef SUPPORT_MAME_FM_DLL
+       if(!fmdll) {
+               fmdll = new CFMDLL(config.mame2608_dll_path);
+       }
+       dllchip = NULL;
+#endif
+       register_vline_event(this);
+       left_volume = right_volume = 256;
+       v_left_volume = v_right_volume = 256;
+       mute = false;
+       clock_prev = clock_accum = clock_busy = 0;
+       ch = 0;
+       addr_A1 = false;
+       
+       if(d_debugger != NULL) {
+               d_debugger->set_device_name(_T("Debugger (YM2612 OPN2)"));
+               d_debugger->set_context_mem(this);
+               d_debugger->set_context_io(vm->dummy);
+       }
+}
+
+void YM2612::release()
+{
+       delete opn2;
+#ifdef SUPPORT_MAME_FM_DLL
+       if(dllchip) {
+               fmdll->Release(dllchip);
+               dllchip = NULL;
+               chip_reference_counter--;
+       }
+       if(fmdll && !chip_reference_counter) {
+               delete fmdll;
+               fmdll = NULL;
+       }
+#endif
+}
+
+void YM2612::reset()
+{
+       touch_sound();
+       opn2->Reset();
+#ifdef SUPPORT_MAME_FM_DLL
+       if(dllchip) {
+               fmdll->Reset(dllchip);
+       }
+#endif
+       memset(port_log, 0, sizeof(port_log));
+       fnum2 = 0;
+       fnum21 = 0;
+       // stop timer
+       timer_event_id = -1;
+       this->set_reg(0x27, 0);
+       
+       port[0].first = port[1].first = true;
+       port[0].wreg = port[1].wreg = 0;//0xff;
+       mode = 0;
+       irq_prev = busy = false;
+}
+
+
+void YM2612::write_io8(uint32_t addr, uint32_t data)
+{
+       switch(addr & 3) {
+       case 0:
+               // write dummy data for prescaler
+               ch = data;
+               addr_A1 = false;
+               if(0x2d <= ch && ch <= 0x2f) {
+                       update_count();
+                       this->set_reg(ch, 0);
+                       update_interrupt();
+                       clock_busy = get_current_clock();
+                       busy = true;
+               }
+               break;
+       case 1:
+               if(!(addr_A1)) {
+                       if(d_debugger != NULL && d_debugger->now_device_debugging) {
+                               d_debugger->write_via_debugger_data8(ch, data);
+                       } else {
+                               this->write_via_debugger_data8(ch, data);
+                       }
+               }
+               break;
+       case 2:
+               ch1 = data1 = data;
+               addr_A1 = true;
+               break;
+       case 3:
+               if(addr_A1) {
+                       if(d_debugger != NULL && d_debugger->now_device_debugging) {
+                               d_debugger->write_via_debugger_data8(0x100 | ch1, data);
+                       } else {
+                               this->write_via_debugger_data8(0x100 | ch1, data);
+                       }
+               }
+               break;
+       default:
+               break;
+       }
+}
+
+uint32_t YM2612::read_io8(uint32_t addr)
+{
+       switch(addr & 3) {
+       case 0:
+       case 1:
+       case 2:
+       case 3:
+               {
+                               /* BUSY : x : x : x : x : x : FLAGB : FLAGA */
+                       update_count();
+                       update_interrupt();
+                       uint32_t status;
+                       status = opn2->ReadStatus() & ~0x80;
+                       if(busy) {
+                               // from PC-88 machine language master bible (XM8 version 1.00)
+                               if(get_passed_usec(clock_busy) < 2.13) {
+                                       status |= 0x80;
+                               } else {
+                                       busy = false;
+                               }
+                       }
+                       return status;
+               }
+               break;
+       default:
+               break;
+       }
+       return 0xff;
+}
+
+void YM2612::write_via_debugger_data8(uint32_t addr, uint32_t data)
+{
+       if(addr < 0x100) {
+               // YM2612
+               if(0x2d <= addr && addr <= 0x2f) {
+                       // don't write again for prescaler
+               } else if(0xa4 <= addr && addr <= 0xa6) {
+                       // XM8 version 1.20
+                       fnum2 = data;
+               } else {
+                       update_count();
+                       // XM8 version 1.20
+                       if(0xa0 <= addr && addr <= 0xa2) {
+                               this->set_reg(addr + 4, fnum2);
+                       }
+                       this->set_reg(addr, data);
+                       if(addr == 0x27) {
+                               update_event();
+                       }
+                       update_interrupt();
+                       clock_busy = get_current_clock();
+                       busy = true;
+               }
+       } else if(addr < 0x200) {
+               // YM2608
+               if(0x1a4 <= addr && addr <= 0x1a6) {
+                       // XM8 version 1.20
+                       fnum21 = data;
+               } else {
+                       update_count();
+                       // XM8 version 1.20
+                       if(0x1a0 <= addr && addr <= 0x1a2) {
+                               this->set_reg(addr + 4, fnum21);
+                       }
+                       this->set_reg(addr, data);
+                       data1 = data;
+                       update_interrupt();
+                       clock_busy = get_current_clock();
+                       busy = true;
+               }
+       }
+}
+
+uint32_t YM2612::read_via_debugger_data8(uint32_t addr)
+{
+       if(addr < 0x100) {
+               // YM2612
+               return opn2->GetReg(addr);
+       } else if(addr < 0x200) {
+               // YM2608
+               return port_log[addr].data;
+       }
+       return 0;
+}
+
+void YM2612::write_signal(int id, uint32_t data, uint32_t mask)
+{
+       if(id == SIG_YM2612_MUTE) {
+               mute = ((data & mask) != 0);
+       }
+}
+
+uint32_t YM2612::read_signal(int id)
+{
+       return 0x00;
+}      
+
+void YM2612::event_vline(int v, int clock)
+{
+       update_count();
+       update_interrupt();
+}
+
+void YM2612::event_callback(int event_id, int error)
+{
+       update_count();
+       update_interrupt();
+       timer_event_id = -1;
+       update_event();
+}
+
+void YM2612::update_count()
+{
+       clock_accum += clock_const * get_passed_clock(clock_prev);
+       uint32_t count = clock_accum >> 20;
+       if(count) {
+               opn2->Count(count);
+               clock_accum -= count << 20;
+       }
+       clock_prev = get_current_clock();
+}
+
+void YM2612::update_event()
+{
+       if(timer_event_id != -1) {
+               cancel_event(this, timer_event_id);
+               timer_event_id = -1;
+       }
+       
+       int count;
+       count = opn2->GetNextEvent();
+       if(count > 0) {
+               register_event(this, EVENT_FM_TIMER, 1000000.0 / (double)chip_clock * (double)count * 2.0, false, &timer_event_id);
+       }
+}
+
+void YM2612::update_interrupt()
+{
+       bool irq;
+       irq = opn2->ReadIRQ();
+       if(!irq_prev && irq) {
+               write_signals(&outputs_irq, 0xffffffff);
+       } else if(irq_prev && !irq) {
+               write_signals(&outputs_irq, 0);
+       }
+       irq_prev = irq;
+}
+
+inline int32_t VCALC(int32_t x, int32_t y)
+{
+       x = x * y;
+       x = x >> 8;
+       return x;
+}
+
+inline int32_t SATURATION_ADD(int32_t x, int32_t y)
+{
+       x = x + y;
+       if(x < -0x8000) x = -0x8000;
+       if(x >  0x7fff) x =  0x7fff;
+       return x;
+}
+
+
+void YM2612::mix(int32_t* buffer, int cnt)
+{
+       if(cnt > 0 && !mute) {
+               int32_t *dbuffer = (int32_t *)malloc((cnt * 2 + 2) * sizeof(int32_t));
+               memset((void *)dbuffer, 0x00, (cnt * 2 + 2) * sizeof(int32_t));
+               opn2->Mix(dbuffer, cnt);
+#ifdef SUPPORT_MAME_FM_DLL
+               if(dllchip) {
+                       fmdll->Mix(dllchip, dbuffer, cnt);
+               }
+#endif
+               int32_t *p = dbuffer;
+               int32_t *q = buffer;
+               int32_t tmp[8];
+               int32_t tvol[8] = {v_left_volume, v_right_volume,
+                                v_left_volume, v_right_volume,
+                                v_left_volume, v_right_volume,
+                                v_left_volume, v_right_volume};
+               int i;
+               // More EXCEPTS to optimize to SIMD features.
+               for(i = 0; i < cnt / 4; i++) {
+                       tmp[0] = VCALC(p[0], tvol[0]);
+                       tmp[1] = VCALC(p[1], tvol[1]);
+                       tmp[2] = VCALC(p[2], tvol[2]);
+                       tmp[3] = VCALC(p[3], tvol[3]);
+                       tmp[4] = VCALC(p[4], tvol[4]);
+                       tmp[5] = VCALC(p[5], tvol[5]);
+                       tmp[6] = VCALC(p[6], tvol[6]);
+                       tmp[7] = VCALC(p[7], tvol[7]);
+
+                       q[0] = SATURATION_ADD(q[0], tmp[0]);
+                       q[1] = SATURATION_ADD(q[1], tmp[1]);
+                       q[2] = SATURATION_ADD(q[2], tmp[2]);
+                       q[3] = SATURATION_ADD(q[3], tmp[3]);
+                  
+                       q[4] = SATURATION_ADD(q[4], tmp[4]);
+                       q[5] = SATURATION_ADD(q[5], tmp[5]);
+                       q[6] = SATURATION_ADD(q[6], tmp[6]);
+                       q[7] = SATURATION_ADD(q[7], tmp[7]);
+                       q += 8;
+                       p += 8;
+               }
+               if((cnt & 3) != 0) {
+                       for(i = 0; i < (cnt & 3); i++) {
+                               tmp[0] = VCALC(p[0], tvol[0]);
+                               tmp[1] = VCALC(p[1], tvol[1]);
+                          
+                               q[0] = SATURATION_ADD(q[0], tmp[0]);
+                               q[1] = SATURATION_ADD(q[1], tmp[1]);
+                               q += 2;
+                               p += 2;
+                       }
+               }
+               free(dbuffer);
+       }
+}
+
+void YM2612::set_volume(int _ch, int decibel_l, int decibel_r)
+{
+       v_right_volume = (int)(pow(10.0, (double)decibel_vol / 10.0) * (double)right_volume);
+       v_left_volume = (int)(pow(10.0, (double)decibel_vol / 10.0) * (double)left_volume);
+       opn2->SetVolumeFM(base_decibel_fm + decibel_l, base_decibel_fm + decibel_r);
+#ifdef SUPPORT_MAME_FM_DLL
+       if(dllchip) {
+               fmdll->SetVolumeFM(dllchip, base_decibel_fm + decibel_l);
+       }
+#endif
+}
+
+void YM2612::initialize_sound(int rate, int clock, int samples, int decibel_fm, int decibel_psg)
+{
+       opn2->Init(clock, rate, false, get_application_path());
+       opn2->SetVolumeFM(decibel_fm, decibel_fm);
+       opn2->SetVolumePSG(decibel_psg, decibel_psg);
+       base_decibel_fm = decibel_fm;
+       base_decibel_psg = decibel_psg;
+       
+#ifdef SUPPORT_MAME_FM_DLL
+       if(!dont_create_multiple_chips) {
+               fmdll->Create((LPVOID*)&dllchip, clock, rate);
+               if(dllchip) {
+                       chip_reference_counter++;
+                       
+                       fmdll->SetVolumeFM(dllchip, decibel_fm);
+                       fmdll->SetVolumePSG(dllchip, decibel_psg);
+                       
+                       DWORD mask = 0;
+                       DWORD dwCaps = fmdll->GetCaps(dllchip);
+                       if((dwCaps & SUPPORT_MULTIPLE) != SUPPORT_MULTIPLE) {
+                               dont_create_multiple_chips = true;
+                       }
+                       if((dwCaps & SUPPORT_FM_A) == SUPPORT_FM_A) {
+                               mask = 0x07;
+                       }
+                       if((dwCaps & SUPPORT_FM_B) == SUPPORT_FM_B) {
+                               mask |= 0x38;
+                       }
+                       if((dwCaps & SUPPORT_PSG) == SUPPORT_PSG) {
+                               mask |= 0x1c0;
+                       }
+                       if((dwCaps & SUPPORT_ADPCM_B) == SUPPORT_ADPCM_B) {
+                               mask |= 0x200;
+                       }
+                       if((dwCaps & SUPPORT_RHYTHM) == SUPPORT_RHYTHM) {
+                               mask |= 0xfc00;
+                       }
+                       opn2->SetChannelMask(mask);
+                       fmdll->SetChannelMask(dllchip, ~mask);
+               }
+       }
+#endif
+       chip_clock = clock;
+}
+
+void YM2612::set_reg(uint32_t addr, uint32_t data)
+{
+       touch_sound();
+       if((addr & 0x1f0) <= 0x010) {
+               return;
+       }
+       opn2->SetReg(addr, data);
+#ifdef SUPPORT_MAME_FM_DLL
+       if(dllchip) {
+               fmdll->SetReg(dllchip, addr, data);
+       }
+       if(0x2d <= addr && addr <= 0x2f) {
+               port_log[0x2d].written = port_log[0x2e].written = port_log[0x2f].written = false;
+       }
+#endif
+       port_log[addr].written = true;
+       port_log[addr].data = data;
+}
+
+void YM2612::update_timing(int new_clocks, double new_frames_per_sec, int new_lines_per_frame)
+{
+       clock_const = (uint32_t)((double)chip_clock * 1024.0 * 1024.0 / (double)new_clocks + 0.5);
+}
+
+bool YM2612::write_debug_reg(const _TCHAR *reg, uint32_t data)
+{
+       if((reg[0] == 'R') || (reg[0] == 'r')) {
+               if(strlen(reg) >= 2) {
+                       _TCHAR *eptr;
+                       int regnum = _tcstol(&(reg[1]), &eptr, 16);
+                       if(regnum < 0x200) {
+                               set_reg((uint32_t)regnum, data);
+                       } else {
+                               return false;
+                       }
+                       return true;
+               }
+               return false;
+       } else if(_tcsicmp(reg, _T("CH")) == 0) {
+               ch = data;
+               return true;
+       } else if(_tcsicmp(reg, _T("CH1")) == 0) {
+               ch1 = data;
+               return true;
+       } else if(_tcsicmp(reg, _T("FNUM2")) == 0) {
+               fnum2 = data;
+               return true;
+       } else if(_tcsicmp(reg, _T("DATA1")) == 0) {
+               data1 = data;
+               return true;
+       } else if(_tcsicmp(reg, _T("FNUM21")) == 0) {
+               fnum21 = data;
+               return true;
+       } 
+       return false;
+}
+
+bool YM2612::get_debug_regs_info(_TCHAR *buffer, size_t buffer_len)
+{
+       _TCHAR tmps[512] = {0};
+       _TCHAR tmps2[32 * 0x200] = {0};
+       _TCHAR tmps3[16];
+       int rows = 0x200 / 16;
+       for(uint32_t i = 0; i < rows; i++) {
+               memset(tmps3, 0x00, sizeof(tmps3));
+               my_stprintf_s(tmps3, 15, _T("+%02X :"), i * 16);
+               _tcsncat(tmps2, tmps3, sizeof(tmps2) - 1);
+               for(uint32_t j = 0; j < 16; j++) {
+                       memset(tmps3, 0x00, sizeof(tmps3));
+                       if(i == 0) {
+                               my_stprintf_s(tmps3, 7, _T(" %02X"), opn2->GetReg(j));
+                       } else {
+                               if((i * 16 + j) == 0xff) {
+                                       my_stprintf_s(tmps3, 7, _T(" %02X"), opn2->GetReg(i * 16 + j));
+                               } else {
+                                       my_stprintf_s(tmps3, 7, _T(" %02X"), port_log[i * 16 + j].data);
+                               }
+                       }
+                       _tcsncat(tmps2, tmps3, sizeof(tmps2) - 1);
+               }
+               _tcsncat(tmps2, "\n", sizeof(tmps2) - 1);
+       }
+       bool irqflag;
+       irqflag = opn2->ReadIRQ();
+       my_stprintf_s(buffer, buffer_len - 1, _T("%sCH=%02X  FNUM2=%02X CH1=%02X DATA1=%02X FNUM21=%02X\nIRQ=%s BUSY=%s CHIP_CLOCK=%d\nREG : +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F\n%s"),
+                                 tmps, ch, fnum2, ch1, data1, fnum21,
+                                 (irqflag) ? _T("Y") : _T("N"), (busy) ? _T("Y") : _T("N"), chip_clock, tmps2);
+       return true;
+}
+
+#define STATE_VERSION  1
+
+bool YM2612::process_state(FILEIO* state_fio, bool loading)
+{
+       if(!state_fio->StateCheckUint32(STATE_VERSION)) {
+               return false;
+       }
+
+       if(!state_fio->StateCheckInt32(this_device_id)) {
+               return false;
+       }
+       if(!opn2->ProcessState((void *)state_fio, loading)) {
+               return false;
+       }
+       for(int i = 0; i < array_length(port_log); i++) {
+               state_fio->StateValue(port_log[i].written);
+               state_fio->StateValue(port_log[i].data);
+       }
+       state_fio->StateValue(ch);
+       state_fio->StateValue(fnum2);
+       state_fio->StateValue(ch1);
+       state_fio->StateValue(data1);
+       state_fio->StateValue(fnum21);
+       for(int i = 0; i < 2; i++) {
+               state_fio->StateValue(port[i].wreg);
+               state_fio->StateValue(port[i].rreg);
+               state_fio->StateValue(port[i].first);
+       }
+       state_fio->StateValue(mode);
+       state_fio->StateValue(chip_clock);
+       state_fio->StateValue(irq_prev);
+       state_fio->StateValue(mute);
+       state_fio->StateValue(clock_prev);
+       state_fio->StateValue(clock_accum);
+       state_fio->StateValue(clock_const);
+       state_fio->StateValue(clock_busy);
+       state_fio->StateValue(timer_event_id);
+       state_fio->StateValue(busy);
+       state_fio->StateValue(addr_A1);
+       
+#ifdef SUPPORT_MAME_FM_DLL
+       // post process
+       if(loading && dllchip) {
+               fmdll->Reset(dllchip);
+               for(int i = 0; i < 0x200; i++) {
+                       // write fnum2 before fnum1
+                       int _ch = ((i >= 0xa0 && i <= 0xaf) || (i >= 0x1a0 && i <= 0x1a7)) ? (i ^ 4) : i;
+                       if(port_log[ch].written) {
+                               fmdll->SetReg(dllchip, _ch, port_log[ch].data);
+                       }
+               }
+       }
+#endif
+       return true;
+}
+
+
diff --git a/source/src/vm/fmtowns/ym2612.h b/source/src/vm/fmtowns/ym2612.h
new file mode 100644 (file)
index 0000000..aae77d1
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+       Skelton for retropc emulator
+
+       Author : Takeda.Toshiya
+       Date   : 2006.09.15-
+
+       [ YM2612 ]
+*/
+
+#ifndef _YM2612_H_
+#define _YM2612_H_
+
+//#include "vm.h"
+//#include "../emu.h"
+#include "device.h"
+#include "fmgen/opna.h"
+
+#ifdef SUPPORT_WIN32_DLL
+#define SUPPORT_MAME_FM_DLL
+//#include "fmdll/fmdll.h"
+#endif
+#define SIG_YM2612_MUTE                2
+
+class DEBUGGER;
+
+class YM2612 : public DEVICE
+{
+protected:
+       DEBUGGER *d_debugger;
+       FM::OPN2* opn2;
+#ifdef SUPPORT_MAME_FM_DLL
+//     CFMDLL* fmdll;
+       LPVOID* dllchip;
+#endif
+       struct {
+               bool written;
+               uint8_t data;
+       } port_log[0x200];
+       int base_decibel_fm, base_decibel_psg;
+       int decibel_vol;
+       
+       uint8_t ch;
+       uint8_t fnum2;
+       uint8_t ch1, data1;
+       uint8_t fnum21;
+
+       int32_t right_volume;
+       int32_t left_volume;
+       int32_t v_right_volume;
+       int32_t v_left_volume;
+       struct {
+               uint8_t wreg;
+               uint8_t rreg;
+               bool first;
+               // output signals
+               outputs_t outputs;
+       } port[2];
+       uint8_t mode;
+       
+       int chip_clock;
+       bool irq_prev, mute;
+       
+       uint32_t clock_prev;
+       uint32_t clock_accum;
+       uint32_t clock_const;
+       int timer_event_id;
+       
+       uint32_t clock_busy;
+       bool busy;
+       bool addr_A1;
+       
+       virtual void update_count();
+       virtual void update_event();
+       virtual void update_interrupt();
+       outputs_t outputs_irq;
+
+public:
+       YM2612(VM_TEMPLATE* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
+       {
+               base_decibel_fm = base_decibel_psg = 0;
+               decibel_vol = 0 + 5;
+               for(int i = 0; i < 2; i++) {
+                       initialize_output_signals(&port[i].outputs);
+                       port[i].wreg = port[i].rreg = 0;//0xff;
+               }
+               d_debugger = NULL;
+               initialize_output_signals(&outputs_irq);
+               set_device_name(_T("YM2612 OPN2"));
+       }
+       ~YM2612() {}
+       
+       // common functions
+       virtual void initialize();
+       virtual void release();
+       virtual void reset();
+       virtual void __FASTCALL write_io8(uint32_t addr, uint32_t data);
+       virtual uint32_t __FASTCALL read_io8(uint32_t addr);
+       virtual void __FASTCALL write_signal(int id, uint32_t data, uint32_t mask);
+       virtual uint32_t __FASTCALL read_signal(int id);
+       virtual void event_vline(int v, int clock);
+       virtual void event_callback(int event_id, int error);
+       virtual void mix(int32_t* buffer, int cnt);
+       virtual void set_volume(int _ch, int decibel_l, int decibel_r);
+       virtual void update_timing(int new_clocks, double new_frames_per_sec, int new_lines_per_frame);
+       // for debugging
+       virtual void __FASTCALL write_via_debugger_data8(uint32_t addr, uint32_t data);
+       virtual uint32_t __FASTCALL read_via_debugger_data8(uint32_t addr);
+       bool is_debugger_available()
+       {
+               return true;
+       }
+       void *get_debugger()
+       {
+               return d_debugger;
+       }
+       virtual uint64_t get_debug_data_addr_space()
+       {
+               return 0x200;
+       }
+       virtual void __FASTCALL write_debug_data8(uint32_t addr, uint32_t data)
+       {
+               if(addr < 0x200) {
+                       write_via_debugger_data8(addr, data);
+               }
+       }
+       virtual uint32_t __FASTCALL read_debug_data8(uint32_t addr)
+       {
+               if(addr < 0x200) {
+                       return read_via_debugger_data8(addr);
+               }
+               return 0;
+       }
+       virtual bool write_debug_reg(const _TCHAR *reg, uint32_t data);
+       virtual bool get_debug_regs_info(_TCHAR *buffer, size_t buffer_len);
+       
+       virtual bool process_state(FILEIO* state_fio, bool loading);
+       // unique functions
+       void set_context_irq(DEVICE* device, int id, uint32_t mask)
+       {
+               register_output_signal(&outputs_irq, device, id, mask);
+       }
+       virtual void set_context_debugger(DEBUGGER* device)
+       {
+               d_debugger = device;
+       }
+       virtual void initialize_sound(int rate, int clock, int samples, int decibel_fm, int decibel_psg);
+       virtual void set_reg(uint32_t addr, uint32_t data); // for patch
+};
+
+#endif
+