[VM][FMTOWNS] Still not implement some devices.
[VM][FMTOWNS][YM2612] Add YM2612 (OPN2) to vm/fmtowns tree.
scsi_dev.cpp
scsi_hdd.cpp
scsi_cdrom.cpp
+
+ msm58321.cpp
+
)
set(VMFILES_LIB
noise.cpp
set(VM_FMTOWNS_DEV_SRCS
ad7820kr.cpp
rf5c68.cpp
+ ym2612.cpp
adpcm.cpp
cdc.cpp
*/
#include "./adpcm.h"
-#include "rf5c68.h"
#include "ad7820kr.h"
+#include "rf5c68.h"
+#include "ym2612.h"
#include "../i8259.h"
namespace FMTOWNS {
}
}
+uint32_t ADPCM::read_signal(int ch)
+{
+ return 0;
+}
#define STATE_VERSION 1
bool ADPCM::process_state(FILEIO* state_fio, bool loading)
*/
#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);
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()
dma_transfer = false;
pio_transfer = true;
+ command_type_play = false; // false = status command
+ stat_reply_intr = false;
+ req_status = false;
+
d_scsi_host->reset();
}
}
break;
default:
- if((addr & 0x01) == 0) {
+ if((address & 0x01) == 0) {
w_regs[address & 0x0f] = data;
}
break;
* 04C0h : Master status register
*/
uint32_t val = 0xff;
- switch(addr & 0x0f) {
+ switch(address & 0x0f) {
case 0x0: //Master status
{
val = 0x00;
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:
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;
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
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);
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);
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())) {
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);
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);
*/
#pragma once
-#include "../device.h"
#include "../../common.h"
-
+#include "../device.h"
#define SIG_TOWNS_CDC_DRQ 1
#define SIG_TOWNS_CDC_IRQ 2
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;
bool submpu_intr_mask;
bool busy_status;
- bool busy_status;
bool cd_status;
bool io_status;
bool msg_status;
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);
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);
}
};
#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"
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);
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"));
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);
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;
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
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);
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);
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); //
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;
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);
}
}
}
}
}
}
+ */
// initialize all devices
#if defined(__GIT_REPO_VERSION)
strncpy(_git_revision, __GIT_REPO_VERSION, sizeof(_git_revision) - 1);
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);
void VM::draw_screen()
{
- memory->draw_screen();
+ crtc->draw_screen();
}
uint32_t VM::is_floppy_disk_accessed()
// 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();
}
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:
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;
}
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);
}
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
}
}
// 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;
}
#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
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;
class TOWNS_MEMORY;
class TOWNS_CDROM;
- class SPRITE;
+ class TOWNS_SPRITE;
class JOYSTICK; // Mouse and Joystick.
}
I8253* pit0;
I8253* pit1;
- I8259* pic0;
- I8259* pic1;
+ I8259* pic;
I386* cpu; // i386DX/SX/486DX/486SX?/Pentium with FPU?
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;
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
// 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
#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;
}
+
}
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)
}
} 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]);
}
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);
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++) {
}
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));
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;
} 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);
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
// 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;
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);
+ }
+
};
}
*/
#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
[ FM-Towns CRTC ]
History: 2016.12.28 Initial from HD46505 .
*/
+#include "../../common.h"
#include "towns_crtc.h"
#include "towns_vram.h"
}
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));
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);
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)
{
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;
}
}
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;
}
-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:
{
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;
{
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;
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;
}
}
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;
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;
}
//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)
{
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;
}
{
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:
__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++) {
} 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;
}
}
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++) {
}
}
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];
k++;
if(k >= width) break;
}
- if(k >= width) break;
+ if(k >= width) return true;
}
}
}
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;
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++;
}
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]];
} 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;
}
}
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;
__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;
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) {
}
}
} 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)) {
memset(pp, 0x00, width * sizeof(scrntype_t));
}
}
- vm->unlock_vm();
+ emu->unlock_vm();
}
}
//display_linebuf = (display_linebuf + 1) & 3;
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;
}
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();
// }
} 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;
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);
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);
#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').
* #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
#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 {
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
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
// 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;
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)
~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;
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();
}
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;
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)
-#include "../towns_dmac.h"
+#include "./towns_dmac.h"
#include "debugger.h"
namespace FMTOWNS {
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;
}
}
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;
}
}
-
+}
#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);
#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()
{
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.
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);
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)
} 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;
}
} 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;
// 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;
}
}
// 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;
}
}
*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;
}
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;
}
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;
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.
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:
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:
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:
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:
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:
} 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();
}
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;
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);
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 {
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);
}
}
#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)
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;
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;
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
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) {
// common functions
void initialize();
+ void release();
void reset();
// Belows are SUBSET of MEMORY::. Because access patterns of Towns are differ per DEVICEs.
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);
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
{
machine_id = id;
}
- void set_context_vram(TOWNS_VRAM* device)
+ void set_context_vram(DEVICE* device)
{
d_vram = device;
}
{
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);
{
d_serialrom = device;
}
- void set_context_machine_id(uint16_t val)
+ void set_machine_id(uint16_t val)
{
machine_id = val & 0xfff8;
}
*/
#include "../../common.h"
+#include "./towns_vram.h"
#include "./towns_sprite.h"
namespace FMTOWNS {
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;
max_sprite_per_frame = 224;
frame_sprite_count = 0;
- vram_buffer = NULL;
- mask_buffer = NULL;
}
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;
}
// 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
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
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
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);
}
}
}
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];
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];
return;
}
-void FMTOWNS_SPRITE::event_frame()
+void TOWNS_SPRITE::event_frame()
{
uint16_t lot = reg_index & 0x3ff;
if(reg_spen && !(sprite_enabled)) {
}
}
-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;
}
// 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;
}
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);
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);
#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;
}
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];
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;
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)
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)
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)
#include "common.h"
#include "./towns_common.h"
+#include "./towns_crtc.h"
#include "./towns_vram.h"
#define _CLEAR_COLOR RGBA_COLOR(0,0,0,0)
}
+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;
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);
}
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);
}
}
-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) {
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;
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);
}
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;
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;
}
addr = addr & 0x7ffff;
if(is_wrap) {
- pair16_t a;
a.b.l = vram[addr];
a.b.h = vram[wrap_addr];
} else {
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]);
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;
}
}
} 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) {
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;
}
}
} 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]);
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) {
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;
}
}
-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:
return d_crtc->read_signal(SIG_TOWNS_CRTC_MMIO_CF882H);
break;
case 0xcff83:
- return (r50_gvramset << 4);
+ return (r50_gvramsel << 4);
break;
case 0xcff86:
{
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;
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;
// 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;
}
}
-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);
}
}
-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) {
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) {
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) {
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
#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];
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.
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.
};
--- /dev/null
+/*
+ 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;
+}
+
+
--- /dev/null
+/*
+ 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
+