2 NEC PC-9801VX Emulator 'ePC-9801VX'
3 NEC PC-9801RA Emulator 'ePC-9801RA'
4 NEC PC-98XA Emulator 'ePC-98XA'
5 NEC PC-98XL Emulator 'ePC-98XL'
6 NEC PC-98RL Emulator 'ePC-98RL'
8 Author : Takeda.Toshiya
17 #if defined(SUPPORT_32BIT_ADDRESS) || defined(UPPER_I386)
18 #include "../i386_np21.h"
19 //#include "../i386.h"
21 //#include "../i286_np21.h"
24 #if defined(HAS_SUB_V30)
33 void CPUREG::initialize()
37 #if defined(HAS_SUB_V30)
38 if(d_v30 != nullptr) {
39 reg_0f0 = reg_0f0 | ((cpu_mode) ? 1 : 0);
46 d_cpu->set_address_mask(0x000fffff);
48 init_clock = get_current_clock_uint64() & 0x000000ffffffffff;
49 #if defined(HAS_SUB_V30)
51 d_cpu->write_signal(SIG_CPU_BUSREQ, reg_0f0, 1);
53 d_v30->write_signal(SIG_CPU_BUSREQ, ~reg_0f0, 1);
54 cpu_mode = ((reg_0f0 & 1) != 0);
55 d_pio->write_signal(SIG_I8255_PORT_B, reg_0f0 << 1, 2);
59 d_cpu->write_signal(SIG_CPU_BUSREQ, 0, 1);
60 d_pio->write_signal(SIG_I8255_PORT_B, 0, 2);
65 void CPUREG::write_io8(uint32_t addr, uint32_t data)
75 // ToDo: Both Pseudo BIOS.
76 d_cpu->write_signal(SIG_CPU_BUSREQ, 1, 1);
77 #if defined(HAS_SUB_V30)
79 d_v30->write_signal(SIG_CPU_BUSREQ, 1, 1);
83 cancel_event(this, event_wait);
86 register_event(this, EVENT_WAIT, 0.6, false, &event_wait);
89 out_debug_log(_T("00F0h=%02X"), data);
91 #if defined(HAS_SUB_V30)
93 write_signals(&outputs_cputype, ((reg_0f0 & 0x01) != 0) ? 0xffffffff : 0x00000000);
95 write_signals(&outputs_cputype, 0);
98 write_signals(&outputs_cputype, 0);
101 d_cpu->set_address_mask(0x000fffff);
102 #if defined(HAS_SUB_V30)
104 d_cpu->write_signal(SIG_CPU_BUSREQ, reg_0f0, 1);
106 d_v30->write_signal(SIG_CPU_BUSREQ, ~reg_0f0, 1);
107 cpu_mode = ((reg_0f0 & 1) != 0);
108 d_pio->write_signal(SIG_I8255_PORT_B, reg_0f0 << 1, 2);
112 d_pio->write_signal(SIG_I8255_PORT_B, 0, 2);
117 #if defined(SUPPORT_32BIT_ADDRESS)
118 d_cpu->set_address_mask(0xffffffff);
120 d_cpu->set_address_mask(0x00ffffff);
123 #if defined(SUPPORT_32BIT_ADDRESS)
127 d_cpu->set_address_mask(0xffffffff);
130 d_cpu->set_address_mask(0x000fffff);
138 uint32_t CPUREG::read_io8(uint32_t addr)
148 // Timestamp register (from MAME 0.208)
154 c = get_current_clock_uint64() & 0x000000ffffffffff;
156 elapsed = c + 0x0000010000000000 - init_clock;
158 elapsed = c - init_clock;
160 uint64_t ticks = (elapsed * 307200) / get_cpu_clock(0);
161 n.d = (uint32_t)ticks;
163 switch(addr & 0x03) {
168 case 2: // OK? From NP2 v0.83 20190619
171 case 3: // OK? From NP2 v0.83 20190619
183 //#if defined(_PC9821_VARIANTS) || defined(_PC9801NA)
184 // value |= 0x80; // 1 = PC-9801NA, 0 = PC-9801NA/C
185 // value |= 0x80; // 1 = PC-9821modelS1, 0 = PC-9821modelS2
186 // value |= 0x80; // 1 = PC-9821CemodelS1, 0 = PC-9821CemodelS2
187 // value |= 0x80; // 1 = PC-9821Xt, 0 = PC-9821Xa
188 // value |= 0x80; // CPU MODE, 1 = High/Low, 0 = Middle (PC-9821Ap/As/Ae/Af)
189 // value |= 0x40; // ODP, 1 = Existing (PC-9821Ts)
191 #if defined(SUPPORT_SCSI_IF)
192 // value |= 0x40; // Internal 55-type SCSI-HDD, 0 = Existing
194 #if defined(SUPPORT_SASI_IF)
195 // value |= 0x20; // Internal 27-type SASI-HDD, 0 = Existing
197 #if defined(_PC9801RA) || defined(_PC9801RS) || defined(_PC9821_VARIANTS) || \
198 defined(_PC98NOTE_VARIANTS) || defined(_PC98DOPLUS)
199 #if !defined(SUPPORT_SASI_IF) || defined(SUPPORT_IDE_IF)
200 value |= 0x20; // Internal 27-type SASI-HDD, 0 = Existing
206 // value |= 0x10; // Unknown
207 value |= 0x08; // RAM access, 1 = Internal-standard/External-enhanced RAM, 0 = Internal-enhanced RAM
208 // value |= 0x04; // Refresh mode, 1 = Standard, 0 = High speed
209 #if defined(HAS_SUB_V30)
210 if((cpu_mode) && (d_v30 != nullptr)) {
211 // Q: When defined HAS_I86 ?
212 value |= 0x02; // CPU mode, 1 = V30, 0 = 80286/80386
215 value |= 0x01; // RAM access, 1 = Internal RAM, 0 = External-enhanced RAM
218 return ((d_cpu->get_address_mask() & (1 << 20)) ? 0x00 : 0x01) | 0xfe;
220 case 0x00f4: // ToDo: DMA SPEED (after 9801DA)
223 #if defined(SUPPORT_32BIT_ADDRESS)
226 #if defined(SUPPORT_HIRESO) && !defined(_PC98RL)
227 value |= 0x10; // SASI-HDD, 1 = DMA ch0, 0 = DMA ch1
230 value |= 0x02; // NMI, 1 = Enabled
232 return ((d_cpu->get_address_mask() & (1 << 20)) ? 0x00 : 0x01) | value;
238 void CPUREG::event_callback(int id, int err)
240 if(id == EVENT_WAIT) {
241 // Reset WAIT (Temporally BUSREQ).
242 //#if !defined(SUPPORT_HIRESO)
243 // ToDo: Both Pseudo BIOS.
244 uint32_t haltvalue = 0;
245 uint32_t haltvalue_v30 = 1;
246 #if defined(HAS_SUB_V30)
252 d_v30->write_signal(SIG_CPU_BUSREQ, haltvalue_v30, 1);
255 d_cpu->write_signal(SIG_CPU_BUSREQ, haltvalue, 1);
261 //#if !defined(SUPPORT_HIRESO)
262 void CPUREG::set_intr_line(bool line, bool pending, uint32_t bit)
264 #if defined(HAS_SUB_V30)
266 if(((reg_0f0 & 1) != 0)){
267 d_v30->set_intr_line(line, pending, bit);
269 d_cpu->set_intr_line(line, pending, bit);
274 d_cpu->set_intr_line(line, pending, bit);
278 void CPUREG::write_signal(int ch, uint32_t data, uint32_t mask)
280 if(ch == SIG_CPU_NMI) {
281 out_debug_log("NMI\n");
283 write_signals(&outputs_nmi, data);
285 } else if(ch == SIG_CPUREG_RESET) {
286 // This don't need at PC9801?
287 // out_debug_log("RESET FROM CPU!!!\n");
291 void CPUREG::set_extra_clock(int clock)
293 #if defined(HAS_SUB_V30)
295 d_v30->set_extra_clock(clock);
297 d_cpu->set_extra_clock(clock);
303 #define STATE_VERSION 3
305 bool CPUREG::process_state(FILEIO* state_fio, bool loading)
307 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
310 if(!state_fio->StateCheckInt32(this_device_id)) {
313 state_fio->StateValue(reg_0f0);
314 #if defined(HAS_SUB_V30)
315 state_fio->StateValue(cpu_mode);
317 state_fio->StateValue(nmi_enabled);
318 state_fio->StateValue(init_clock);
319 state_fio->StateValue(event_wait);