From: K.Ohta Date: Fri, 24 May 2019 14:46:45 +0000 (+0900) Subject: [VM][I386][PC9801] Add MEMORY/IO WAIT feature via foo_data[8|16|32]w().(excepts ... X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=5085dddfb5707d32444edb6189cfa32c631f1ed2;p=csp-qt%2Fcommon_source_project-fm7.git [VM][I386][PC9801] Add MEMORY/IO WAIT feature via foo_data[8|16|32]w().(excepts [read|write_]_memory_mapped_io[8|16|32]w()). --- diff --git a/source/src/vm/mame/emu/cpu/i386/i386.c b/source/src/vm/mame/emu/cpu/i386/i386.c index a6a4a6267..15dc963be 100644 --- a/source/src/vm/mame/emu/cpu/i386/i386.c +++ b/source/src/vm/mame/emu/cpu/i386/i386.c @@ -52,7 +52,7 @@ static void pentium_smi(i386_state* cpustate); #define FAULT(fault,error) {\ logerror("FAULT(%s , %s) PC=%08x V8086=%s PROTECTED=%s SP=%08X:%08X\n", #fault, #error, cpustate->pc, (cpustate->VM) ? "YES" : "NO", (PROTECTED_MODE) ? "YES" : "NO", (PROTECTED_MODE) ? cpustate->sreg[SS].base : (cpustate->sreg[SS].selector << 4), REG32(ESP)); \ if(cpustate->is_report_exception) { \ - cpustate->exception_code = ((UINT64)error << 32) | (UINT64)fault; \ + cpustate->exception_code = (((UINT64)error) << 32) | (UINT64)fault; \ cpustate->exception_pc = cpustate->prev_pc; \ cpustate->exception_caused = 1; \ cpustate->ext = 1; \ @@ -204,9 +204,14 @@ static void cpu_reset_generic(i386_state* cpustate) addr = base + (selector & ~7) + 5; i386_translate_address(cpustate, TRANSLATE_READ, &addr, NULL); - rights = cpustate->program->read_data8(addr); + int wait0 = cpustate->memory_wait; + int wait; + rights = cpustate->program->read_data8w(addr, &wait); + wait0 += wait; // Should a fault be thrown if the table is read only? - cpustate->program->write_data8(addr, rights | 1); + cpustate->program->write_data8w(addr, rights | 1, &wait); + wait0 += wait; + cpustate->memory_wait += wait0; } /*static*/INLINE void i386_load_segment_descriptor(i386_state *cpustate, int segment ) @@ -3648,7 +3653,7 @@ static void i386_set_irq_line(i386_state *cpustate,int irqline, int state) } if ( state ) { try { - i386_trap(cpustate,2, 1, 0); + i386_trap(cpustate,2, 1, 0); // OK? } catch(UINT64 e) { logdebug("EXCEPTION %08X VIA making INT02h at i386_set_irq_line() ADDR=%08X\n", e, cpustate->pc); } catch(UINT32 e) { @@ -3716,6 +3721,8 @@ static CPU_EXECUTE( i386 ) cpustate->total_cycles += passed_cycles; //#endif cpu_wait_i386(cpustate, passed_cycles); + cpustate->extra_cycles += cpustate->memory_wait; + cpustate->memory_wait = 0; return passed_cycles; } else { cpustate->cycles += cycles; @@ -3735,6 +3742,8 @@ static CPU_EXECUTE( i386 ) cpustate->total_cycles += passed_cycles; //#endif cpu_wait_i386(cpustate, passed_cycles); + cpustate->extra_cycles += cpustate->memory_wait; + cpustate->memory_wait = 0; return passed_cycles; } } @@ -3748,7 +3757,7 @@ static CPU_EXECUTE( i386 ) /* adjust for any interrupts that came in */ //#ifdef USE_DEBUGGER - cpustate->total_cycles += cpustate->extra_cycles; + cpustate->total_cycles -= cpustate->extra_cycles; //#endif cpustate->cycles -= cpustate->extra_cycles; cpustate->extra_cycles = 0; @@ -3951,6 +3960,8 @@ static CPU_EXECUTE( i386 ) int passed_cycles = cpustate->base_cycles - cpustate->cycles; cpustate->tsc += passed_cycles; cpu_wait_i386(cpustate, passed_cycles); + cpustate->extra_cycles += cpustate->memory_wait; + cpustate->memory_wait = 0; return passed_cycles; } diff --git a/source/src/vm/mame/emu/cpu/i386/i386op16.c b/source/src/vm/mame/emu/cpu/i386/i386op16.c index bb25a8366..513d2bd3c 100644 --- a/source/src/vm/mame/emu/cpu/i386/i386op16.c +++ b/source/src/vm/mame/emu/cpu/i386/i386op16.c @@ -3194,7 +3194,7 @@ static void I386OP(group0F00_16)(i386_state *cpustate) // Opcode 0x0f 0 UINT8 modrm = FETCH(cpustate); I386_SREG seg; UINT8 result; - + int wait; switch( (modrm >> 3) & 0x7 ) { case 0: /* SLDT */ @@ -3287,8 +3287,9 @@ static void I386OP(group0F00_16)(i386_state *cpustate) // Opcode 0x0f 0 UINT32 addr = ((seg.selector & 4) ? cpustate->ldtr.base : cpustate->gdtr.base) + (seg.selector & ~7) + 5; i386_translate_address(cpustate, TRANSLATE_READ, &addr, NULL); - cpustate->program->write_data16(addr, (seg.flags & 0xff) | 2); - + + cpustate->program->write_data16w(addr, (seg.flags & 0xff) | 2, &wait); + cpustate->memory_wait += wait; cpustate->task.limit = seg.limit; cpustate->task.base = seg.base; cpustate->task.flags = seg.flags | 2; diff --git a/source/src/vm/mame/emu/cpu/i386/i386op32.c b/source/src/vm/mame/emu/cpu/i386/i386op32.c index 57f0dfa28..0528c9c66 100644 --- a/source/src/vm/mame/emu/cpu/i386/i386op32.c +++ b/source/src/vm/mame/emu/cpu/i386/i386op32.c @@ -2969,7 +2969,7 @@ static void I386OP(group0F00_32)(i386_state *cpustate) // Opcode 0x0f 0 UINT8 modrm = FETCH(cpustate); I386_SREG seg; UINT8 result; - + int wait; switch( (modrm >> 3) & 0x7 ) { case 0: /* SLDT */ @@ -3058,8 +3058,8 @@ static void I386OP(group0F00_32)(i386_state *cpustate) // Opcode 0x0f 0 UINT32 addr = ((seg.selector & 4) ? cpustate->ldtr.base : cpustate->gdtr.base) + (seg.selector & ~7) + 5; i386_translate_address(cpustate, TRANSLATE_READ, &addr, NULL); - cpustate->program->write_data8(addr, (seg.flags & 0xff) | 2); - + cpustate->program->write_data8w(addr, (seg.flags & 0xff) | 2, &wait); + cpustate->memory_wait += wait; cpustate->task.limit = seg.limit; cpustate->task.base = seg.base; cpustate->task.flags = seg.flags | 2; diff --git a/source/src/vm/mame/emu/cpu/i386/i386priv.h b/source/src/vm/mame/emu/cpu/i386/i386priv.h index 3f9042d4e..54464be30 100644 --- a/source/src/vm/mame/emu/cpu/i386/i386priv.h +++ b/source/src/vm/mame/emu/cpu/i386/i386priv.h @@ -372,7 +372,6 @@ INLINE UINT8 sreg_get_flags(UINT32 high) INLINE UINT8 sreg_get_flags_from_u64(UINT64 src) { - pair32_t ret; pair64_t pa; pa.q = src; @@ -675,6 +674,7 @@ struct i386_state bool lock; UINT32 waitfactor; UINT64 waitcount; + int memory_wait; // Below is only for debugging, no need to save/load state. UINT64 exception_code; UINT32 exception_pc; @@ -866,6 +866,7 @@ INLINE int i386_translate_address(i386_state *cpustate, int intention, offs_t *a bool user = (intention & TRANSLATE_USER_MASK) ? true : false; bool write = (intention & TRANSLATE_WRITE) ? true : false; bool debug = (intention & TRANSLATE_DEBUG_MASK) ? true : false; + int wait; if(!(cpustate->cr[0] & I386_CR0_PG)) // paging is disabled { @@ -874,7 +875,8 @@ INLINE int i386_translate_address(i386_state *cpustate, int intention, offs_t *a return TRUE; } // Paging is enabled - UINT32 page_dir = cpustate->program->read_data32(pdbr + directory * 4); + UINT32 page_dir = cpustate->program->read_data32w(pdbr + directory * 4, &wait); + cpustate->memory_wait += wait; if(page_dir & 1) { if ((page_dir & 0x80) && (cpustate->cr[4] & I386_CR4_PSE)) @@ -894,16 +896,21 @@ INLINE int i386_translate_address(i386_state *cpustate, int intention, offs_t *a { if(write) perm |= VTLB_FLAG_DIRTY; - if(!(page_dir & 0x40) && write) - cpustate->program->write_data32(pdbr + directory * 4, page_dir | 0x60); - else if(!(page_dir & 0x20)) - cpustate->program->write_data32(pdbr + directory * 4, page_dir | 0x20); + if(!(page_dir & 0x40) && write) { + cpustate->program->write_data32w(pdbr + directory * 4, page_dir | 0x60, &wait); + cpustate->memory_wait += wait; + } + else if(!(page_dir & 0x20)) { + cpustate->program->write_data32w(pdbr + directory * 4, page_dir | 0x20, &wait); + cpustate->memory_wait += wait; + } ret = TRUE; } } else { - UINT32 page_entry = cpustate->program->read_data32((page_dir & 0xfffff000) + (table * 4)); + UINT32 page_entry = cpustate->program->read_data32w((page_dir & 0xfffff000) + (table * 4), &wait); + cpustate->memory_wait += wait; if(!(page_entry & 1)) ret = FALSE; else @@ -923,12 +930,18 @@ INLINE int i386_translate_address(i386_state *cpustate, int intention, offs_t *a { if(write) perm |= VTLB_FLAG_DIRTY; - if(!(page_dir & 0x20)) - cpustate->program->write_data32(pdbr + directory * 4, page_dir | 0x20); - if(!(page_entry & 0x40) && write) - cpustate->program->write_data32((page_dir & 0xfffff000) + (table * 4), page_entry | 0x60); - else if(!(page_entry & 0x20)) - cpustate->program->write_data32((page_dir & 0xfffff000) + (table * 4), page_entry | 0x20); + if(!(page_dir & 0x20)) { + cpustate->program->write_data32w(pdbr + directory * 4, page_dir | 0x20, &wait); + cpustate->memory_wait += wait; + } + if(!(page_entry & 0x40) && write) { + cpustate->program->write_data32w((page_dir & 0xfffff000) + (table * 4), page_entry | 0x60, &wait); + cpustate->memory_wait += wait; + } + else if(!(page_entry & 0x20)) { + cpustate->program->write_data32w((page_dir & 0xfffff000) + (table * 4), page_entry | 0x20, &wait); + cpustate->memory_wait += wait; + } ret = TRUE; } } @@ -954,6 +967,7 @@ INLINE int i386_translate_address_with_width(i386_state *cpustate, int intention bool user = (intention & TRANSLATE_USER_MASK) ? true : false; bool write = (intention & TRANSLATE_WRITE) ? true : false; bool debug = (intention & TRANSLATE_DEBUG_MASK) ? true : false; + int wait = 0; if(!(cpustate->cr[0] & I386_CR0_PG)) // paging is disabled { @@ -962,7 +976,8 @@ INLINE int i386_translate_address_with_width(i386_state *cpustate, int intention return TRUE; } // Paging is enabled - UINT32 page_dir = cpustate->program->read_data32(pdbr + directory * 4); + UINT32 page_dir = cpustate->program->read_data32w(pdbr + directory * 4, &wait); + cpustate->memory_wait += wait; if(page_dir & 1) { if ((page_dir & 0x80) && (cpustate->cr[4] & I386_CR4_PSE)) @@ -985,16 +1000,21 @@ INLINE int i386_translate_address_with_width(i386_state *cpustate, int intention { if(write) perm |= VTLB_FLAG_DIRTY; - if(!(page_dir & 0x40) && write) - cpustate->program->write_data32(pdbr + directory * 4, page_dir | 0x60); - else if(!(page_dir & 0x20)) - cpustate->program->write_data32(pdbr + directory * 4, page_dir | 0x20); + if(!(page_dir & 0x40) && write) { + cpustate->program->write_data32w(pdbr + directory * 4, page_dir | 0x60, &wait); + cpustate->memory_wait += wait; + } + else if(!(page_dir & 0x20)) { + cpustate->program->write_data32w(pdbr + directory * 4, page_dir | 0x20, &wait); + cpustate->memory_wait += wait; + } ret = TRUE; } } else { - UINT32 page_entry = cpustate->program->read_data32((page_dir & 0xfffff000) + (table * 4)); + UINT32 page_entry = cpustate->program->read_data32w((page_dir & 0xfffff000) + (table * 4), &wait); + cpustate->memory_wait += wait; if(!(page_entry & 1)) ret = FALSE; else @@ -1018,12 +1038,18 @@ INLINE int i386_translate_address_with_width(i386_state *cpustate, int intention { if(write) perm |= VTLB_FLAG_DIRTY; - if(!(page_dir & 0x20)) - cpustate->program->write_data32(pdbr + directory * 4, page_dir | 0x20); - if(!(page_entry & 0x40) && write) - cpustate->program->write_data32((page_dir & 0xfffff000) + (table * 4), page_entry | 0x60); - else if(!(page_entry & 0x20)) - cpustate->program->write_data32((page_dir & 0xfffff000) + (table * 4), page_entry | 0x20); + if(!(page_dir & 0x20)) { + cpustate->program->write_data32w(pdbr + directory * 4, page_dir | 0x20, &wait); + cpustate->memory_wait += wait; + } + if(!(page_entry & 0x40) && write) { + cpustate->program->write_data32w((page_dir & 0xfffff000) + (table * 4), page_entry | 0x60, &wait); + cpustate->memory_wait += wait; + } + else if(!(page_entry & 0x20)) { + cpustate->program->write_data32w((page_dir & 0xfffff000) + (table * 4), page_entry | 0x20, &wait); + cpustate->memory_wait += wait; + } ret = TRUE; } } @@ -1148,11 +1174,13 @@ INLINE UINT8 FETCH(i386_state *cpustate) { UINT8 value; UINT32 address = cpustate->pc, error; - + int wait; if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_FETCH,&address,&error)) PF_THROW(error); - value = cpustate->program->read_data8(address & cpustate->a20_mask); + value = cpustate->program->read_data8w(address & cpustate->a20_mask, &wait); + cpustate->memory_wait += wait; + #ifdef DEBUG_MISSING_OPCODE cpustate->opcode_bytes[cpustate->opcode_bytes_length] = value; cpustate->opcode_bytes_length = (cpustate->opcode_bytes_length + 1) & 15; @@ -1165,15 +1193,17 @@ INLINE UINT16 FETCH16(i386_state *cpustate) { UINT16 value; UINT32 address = cpustate->pc, error; - + int wait; if( !WORD_ALIGNED(address) ) { /* Unaligned read */ if(!translate_address_with_width(cpustate,cpustate->CPL,TRANSLATE_FETCH,2,&address,&error)) { value = (FETCH(cpustate) << 0); value |= (FETCH(cpustate) << 8); } else { UINT32 mask = cpustate->a20_mask; - value = ((cpustate->program->read_data8((address + 0) & mask)) << 0); - value |= ((cpustate->program->read_data8((address + 1) & mask)) << 8); + value = ((cpustate->program->read_data8w((address + 0) & mask, &wait)) << 0); + cpustate->memory_wait += wait; + value |= ((cpustate->program->read_data8w((address + 1) & mask, &wait)) << 8); + cpustate->memory_wait += wait; cpustate->eip += 2; cpustate->pc += 2; } @@ -1181,7 +1211,8 @@ INLINE UINT16 FETCH16(i386_state *cpustate) if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_FETCH,&address,&error)) PF_THROW(error); address &= cpustate->a20_mask; - value = cpustate->program->read_data16(address); + value = cpustate->program->read_data16w(address, &wait); + cpustate->memory_wait += wait; cpustate->eip += 2; cpustate->pc += 2; } @@ -1191,7 +1222,7 @@ INLINE UINT32 FETCH32(i386_state *cpustate) { UINT32 value; UINT32 address = cpustate->pc, error; - + int wait; if( !DWORD_ALIGNED(cpustate->pc) ) { /* Unaligned read */ if(!translate_address_with_width(cpustate,cpustate->CPL,TRANSLATE_FETCH,4,&address,&error)) { value = (FETCH(cpustate) << 0); @@ -1202,13 +1233,19 @@ INLINE UINT32 FETCH32(i386_state *cpustate) } else { UINT32 mask = cpustate->a20_mask; if(WORD_ALIGNED(cpustate->pc)) { - value = ((cpustate->program->read_data16((address + 0) & mask)) << 0); - value |= ((cpustate->program->read_data16((address + 2) & mask)) << 16); + value = (cpustate->program->read_data16w((address + 0) & mask, &wait) << 0); + cpustate->memory_wait += wait; + value |= (cpustate->program->read_data16w((address + 2) & mask, &wait) << 16); + cpustate->memory_wait += wait; } else { - value = ((cpustate->program->read_data8((address + 0) & mask)) << 0); - value |= ((cpustate->program->read_data8((address + 1) & mask)) << 8); - value |= ((cpustate->program->read_data8((address + 2) & mask)) << 16); - value |= ((cpustate->program->read_data8((address + 3) & mask)) << 24); + value = ((cpustate->program->read_data8w((address + 0) & mask, &wait)) << 0); + cpustate->memory_wait += wait; + value |= ((cpustate->program->read_data8w((address + 1) & mask, &wait)) << 8); + cpustate->memory_wait += wait; + value |= ((cpustate->program->read_data8w((address + 2) & mask, &wait)) << 16); + cpustate->memory_wait += wait; + value |= ((cpustate->program->read_data8w((address + 3) & mask, &wait)) << 24); + cpustate->memory_wait += wait; } cpustate->eip += 4; cpustate->pc += 4; @@ -1218,7 +1255,8 @@ INLINE UINT32 FETCH32(i386_state *cpustate) PF_THROW(error); address &= cpustate->a20_mask; - value = cpustate->program->read_data32(address); + value = cpustate->program->read_data32w(address, &wait); + cpustate->memory_wait += wait; cpustate->eip += 4; cpustate->pc += 4; } @@ -1228,18 +1266,21 @@ INLINE UINT32 FETCH32(i386_state *cpustate) INLINE UINT8 READ8(i386_state *cpustate,UINT32 ea) { UINT32 address = ea, error; + int wait; if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_READ,&address, &error)) PF_THROW(error); address &= cpustate->a20_mask; - return cpustate->program->read_data8(address); + uint32_t val = cpustate->program->read_data8w(address, &wait); + cpustate->memory_wait += wait; + return val; } INLINE UINT16 READ16(i386_state *cpustate,UINT32 ea) { UINT16 value; UINT32 address = ea, error; - + int wait; if( !WORD_ALIGNED(ea) ) { /* Unaligned read */ if(!translate_address_with_width(cpustate,cpustate->CPL,TRANSLATE_READ,2,&address,&error)) { // PF_THROW(error); @@ -1247,15 +1288,18 @@ INLINE UINT16 READ16(i386_state *cpustate,UINT32 ea) value |= (READ8( cpustate, address+1 ) << 8); } else { UINT32 mask = cpustate->a20_mask; - value = ((cpustate->program->read_data8((address + 0) & mask)) << 0); - value |= ((cpustate->program->read_data8((address + 1) & mask)) << 8); + value = ((cpustate->program->read_data8w((address + 0) & mask, &wait)) << 0); + cpustate->memory_wait += wait; + value |= ((cpustate->program->read_data8w((address + 1) & mask, &wait)) << 8); + cpustate->memory_wait += wait; } } else { if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_READ,&address,&error)) PF_THROW(error); address &= cpustate->a20_mask; - value = cpustate->program->read_data16( address ); + value = cpustate->program->read_data16w( address , &wait); + cpustate->memory_wait += wait; } return value; } @@ -1263,7 +1307,7 @@ INLINE UINT32 READ32(i386_state *cpustate,UINT32 ea) { UINT32 value; UINT32 address = ea, error; - + int wait; if( !DWORD_ALIGNED(ea) ) { /* Unaligned read */ if(!translate_address_with_width(cpustate,cpustate->CPL,TRANSLATE_READ,4,&address,&error)) { value = (READ8( cpustate, address+0 ) << 0); @@ -1273,13 +1317,19 @@ INLINE UINT32 READ32(i386_state *cpustate,UINT32 ea) } else { UINT32 mask = cpustate->a20_mask; if(WORD_ALIGNED(ea)) { - value = ((cpustate->program->read_data16((address + 0) & mask)) << 0); - value |= ((cpustate->program->read_data16((address + 2) & mask)) << 16); + value = ((cpustate->program->read_data16w((address + 0) & mask, &wait)) << 0); + cpustate->memory_wait += wait; + value |= ((cpustate->program->read_data16w((address + 2) & mask, &wait)) << 16); + cpustate->memory_wait += wait; } else { - value = ((cpustate->program->read_data8((address + 0) & mask)) << 0); - value |= ((cpustate->program->read_data8((address + 1) & mask)) << 8); - value |= ((cpustate->program->read_data8((address + 2) & mask)) << 16); - value |= ((cpustate->program->read_data8((address + 3) & mask)) << 24); + value = ((cpustate->program->read_data8w((address + 0) & mask, &wait)) << 0); + cpustate->memory_wait += wait; + value |= ((cpustate->program->read_data8w((address + 1) & mask, &wait)) << 8); + cpustate->memory_wait += wait; + value |= ((cpustate->program->read_data8w((address + 2) & mask, &wait)) << 16); + cpustate->memory_wait += wait; + value |= ((cpustate->program->read_data8w((address + 3) & mask, &wait)) << 24); + cpustate->memory_wait += wait; } } } else { @@ -1287,7 +1337,8 @@ INLINE UINT32 READ32(i386_state *cpustate,UINT32 ea) PF_THROW(error); address &= cpustate->a20_mask; - value = cpustate->program->read_data32( address ); + value = cpustate->program->read_data32w( address , &wait); + cpustate->memory_wait += wait; } return value; } @@ -1296,7 +1347,7 @@ INLINE UINT64 READ64(i386_state *cpustate,UINT32 ea) { UINT64 value; UINT32 address = ea, error; - + int wait; if( !QWORD_ALIGNED(ea) ) { /* Unaligned read */ if(!translate_address_with_width(cpustate,cpustate->CPL,TRANSLATE_READ,8,&address,&error)) { value = (((UINT64) READ8( cpustate, address+0 )) << 0); @@ -1312,23 +1363,37 @@ INLINE UINT64 READ64(i386_state *cpustate,UINT32 ea) UINT32 mask = cpustate->a20_mask; if(!DWORD_ALIGNED(ea)) { if(WORD_ALIGNED(ea)) { // Aligned by 2 - value = (((UINT64)cpustate->program->read_data16((address + 0) & mask)) << 0); - value |= (((UINT64)cpustate->program->read_data16((address + 2) & mask)) << 16); - value |= (((UINT64)cpustate->program->read_data16((address + 4) & mask)) << 32); - value |= (((UINT64)cpustate->program->read_data16((address + 6) & mask)) << 48); + value = (((UINT64)cpustate->program->read_data16w((address + 0) & mask, &wait)) << 0); + cpustate->memory_wait += wait; + value |= (((UINT64)cpustate->program->read_data16w((address + 2) & mask, &wait)) << 16); + cpustate->memory_wait += wait; + value |= (((UINT64)cpustate->program->read_data16w((address + 4) & mask, &wait)) << 32); + cpustate->memory_wait += wait; + value |= (((UINT64)cpustate->program->read_data16w((address + 6) & mask, &wait)) << 48); + cpustate->memory_wait += wait; } else { // never aligned - value = (((UINT64)cpustate->program->read_data8((address + 0) & mask)) << 0); - value |= (((UINT64)cpustate->program->read_data8((address + 1) & mask)) << 8); - value |= (((UINT64)cpustate->program->read_data8((address + 2) & mask)) << 16); - value |= (((UINT64)cpustate->program->read_data8((address + 3) & mask)) << 24); - value |= (((UINT64)cpustate->program->read_data8((address + 4) & mask)) << 32); - value |= (((UINT64)cpustate->program->read_data8((address + 5) & mask)) << 40); - value |= (((UINT64)cpustate->program->read_data8((address + 6) & mask)) << 48); - value |= (((UINT64)cpustate->program->read_data8((address + 7) & mask)) << 56); + value = (((UINT64)cpustate->program->read_data8w((address + 0) & mask, &wait)) << 0); + cpustate->memory_wait += wait; + value |= (((UINT64)cpustate->program->read_data8w((address + 1) & mask, &wait)) << 8); + cpustate->memory_wait += wait; + value |= (((UINT64)cpustate->program->read_data8w((address + 2) & mask, &wait)) << 16); + cpustate->memory_wait += wait; + value |= (((UINT64)cpustate->program->read_data8w((address + 3) & mask, &wait)) << 24); + cpustate->memory_wait += wait; + value |= (((UINT64)cpustate->program->read_data8w((address + 4) & mask, &wait)) << 32); + cpustate->memory_wait += wait; + value |= (((UINT64)cpustate->program->read_data8w((address + 5) & mask, &wait)) << 40); + cpustate->memory_wait += wait; + value |= (((UINT64)cpustate->program->read_data8w((address + 6) & mask, &wait)) << 48); + cpustate->memory_wait += wait; + value |= (((UINT64)cpustate->program->read_data8w((address + 7) & mask, &wait)) << 56); + cpustate->memory_wait += wait; } } else { // Align of 4 - value = (((UINT64) cpustate->program->read_data32( (address+0) & mask )) << 0); - value |= (((UINT64) cpustate->program->read_data32( (address+4) & mask )) << 32); + value = (((UINT64) cpustate->program->read_data32w( (address+0) & mask, &wait )) << 0); + cpustate->memory_wait += wait; + value |= (((UINT64) cpustate->program->read_data32w( (address+4) & mask, &wait )) << 32); + cpustate->memory_wait += wait; } } } else { @@ -1336,41 +1401,48 @@ INLINE UINT64 READ64(i386_state *cpustate,UINT32 ea) PF_THROW(error); address &= cpustate->a20_mask; - value = (((UINT64) cpustate->program->read_data32( address+0 )) << 0); - value |= (((UINT64) cpustate->program->read_data32( address+4 )) << 32); + value = (((UINT64) cpustate->program->read_data32w( address+0, &wait )) << 0); + cpustate->memory_wait += wait; + value |= (((UINT64) cpustate->program->read_data32w( address+4, &wait )) << 32); + cpustate->memory_wait += wait; } return value; } INLINE UINT8 READ8PL0(i386_state *cpustate,UINT32 ea) { UINT32 address = ea, error; - + int wait; if(!translate_address(cpustate,0,TRANSLATE_READ,&address,&error)) PF_THROW(error); address &= cpustate->a20_mask; - return cpustate->program->read_data8(address); + uint32_t val = cpustate->program->read_data8w(address, &wait); + cpustate->memory_wait += wait; + return val; } INLINE UINT16 READ16PL0(i386_state *cpustate,UINT32 ea) { UINT16 value; UINT32 address = ea, error; - + int wait; if( !WORD_ALIGNED(ea) ) { /* Unaligned read */ UINT32 mask = cpustate->a20_mask; if(!translate_address_with_width(cpustate,0,TRANSLATE_READ,2,&address,&error)) { value = READ8PL0(cpustate, ea + 0); value |= (READ8PL0(cpustate, ea + 1) << 8); } else { - value = cpustate->program->read_data8((address + 0) & mask); - value |= (cpustate->program->read_data8((address + 1) & mask) << 8); + value = cpustate->program->read_data8w((address + 0) & mask, &wait); + cpustate->memory_wait += wait; + value |= (cpustate->program->read_data8w((address + 1) & mask, &wait) << 8); + cpustate->memory_wait += wait; } } else { if(!translate_address(cpustate,0,TRANSLATE_READ,&address,&error)) PF_THROW(error); address &= cpustate->a20_mask; - value = cpustate->program->read_data16( address ); + value = cpustate->program->read_data16w( address, &wait ); + cpustate->memory_wait += wait; } return value; } @@ -1379,7 +1451,8 @@ INLINE UINT32 READ32PL0(i386_state *cpustate,UINT32 ea) { UINT32 value; UINT32 address = ea, error; - + int wait; + if( !DWORD_ALIGNED(ea) ) { /* Unaligned read */ UINT32 mask = cpustate->a20_mask; if(!translate_address_with_width(cpustate,0,TRANSLATE_READ,4,&address,&error)) { @@ -1389,13 +1462,19 @@ INLINE UINT32 READ32PL0(i386_state *cpustate,UINT32 ea) value |= (READ8PL0(cpustate, ea + 3) << 24); } else { if(WORD_ALIGNED(ea)) { - value = cpustate->program->read_data16((address + 0) & mask); - value |= (cpustate->program->read_data16((address + 2) & mask) << 16); + value = cpustate->program->read_data16w((address + 0) & mask, &wait); + cpustate->memory_wait += wait; + value |= (cpustate->program->read_data16w((address + 2) & mask, &wait) << 16); + cpustate->memory_wait += wait; } else { - value = cpustate->program->read_data8((address + 0) & mask); - value |= (cpustate->program->read_data8((address + 1) & mask) << 8); - value |= (cpustate->program->read_data8((address + 2) & mask) << 16); - value |= (cpustate->program->read_data8((address + 3) & mask) << 24); + value = cpustate->program->read_data8w((address + 0) & mask, &wait); + cpustate->memory_wait += wait; + value |= (cpustate->program->read_data8w((address + 1) & mask, &wait) << 8); + cpustate->memory_wait += wait; + value |= (cpustate->program->read_data8w((address + 2) & mask, &wait) << 16); + cpustate->memory_wait += wait; + value |= (cpustate->program->read_data8w((address + 3) & mask, &wait) << 24); + cpustate->memory_wait += wait; } } } else { @@ -1403,7 +1482,8 @@ INLINE UINT32 READ32PL0(i386_state *cpustate,UINT32 ea) PF_THROW(error); address &= cpustate->a20_mask; - value = cpustate->program->read_data32( address ); + value = cpustate->program->read_data32w( address, &wait); + cpustate->memory_wait += wait; } return value; } @@ -1421,10 +1501,12 @@ INLINE void WRITE8(i386_state *cpustate,UINT32 ea, UINT8 value) if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_WRITE,&address,&error)) PF_THROW(error); - + int wait = 0; address &= cpustate->a20_mask; - cpustate->program->write_data8(address, value); + cpustate->program->write_data8w(address, value, &wait); + cpustate->memory_wait += wait; } + INLINE void WRITE16(i386_state *cpustate,UINT32 ea, UINT16 value) { UINT32 address = ea, error; @@ -1435,15 +1517,21 @@ INLINE void WRITE16(i386_state *cpustate,UINT32 ea, UINT16 value) WRITE8( cpustate, address+1, (value >> 8) & 0xff ); } else { uint32_t mask = cpustate->a20_mask; - cpustate->program->write_data8((address + 0) & mask, value & 0xff); - cpustate->program->write_data8((address + 1) & mask, (value >> 8) & 0xff); + int wait; + cpustate->program->write_data8w((address + 0) & mask, value & 0xff, &wait); + cpustate->memory_wait += wait; + + cpustate->program->write_data8w((address + 1) & mask, (value >> 8) & 0xff, &wait); + cpustate->memory_wait += wait; + } } else { if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_WRITE,&address,&error)) PF_THROW(error); - + int wait; address &= cpustate->a20_mask; - cpustate->program->write_data16(address, value); + cpustate->program->write_data16w(address, value, &wait); + cpustate->memory_wait += wait; } } INLINE void WRITE32(i386_state *cpustate,UINT32 ea, UINT32 value) @@ -1457,30 +1545,38 @@ INLINE void WRITE32(i386_state *cpustate,UINT32 ea, UINT32 value) WRITE8( cpustate, address+2, (value >> 16) & 0xff ); WRITE8( cpustate, address+3, (value >> 24) & 0xff ); } else { + int wait; uint32_t mask = cpustate->a20_mask; if(!WORD_ALIGNED(ea)) { - cpustate->program->write_data8((address + 0) & mask, value & 0xff); - cpustate->program->write_data8((address + 1) & mask, (value >> 8) & 0xff); - cpustate->program->write_data8((address + 2) & mask, (value >> 16) & 0xff); - cpustate->program->write_data8((address + 3) & mask, (value >> 24) & 0xff); + cpustate->program->write_data8w((address + 0) & mask, value & 0xff, &wait); + cpustate->memory_wait += wait; + cpustate->program->write_data8w((address + 1) & mask, (value >> 8) & 0xff, &wait); + cpustate->memory_wait += wait; + cpustate->program->write_data8w((address + 2) & mask, (value >> 16) & 0xff, &wait); + cpustate->memory_wait += wait; + cpustate->program->write_data8w((address + 3) & mask, (value >> 24) & 0xff, &wait); + cpustate->memory_wait += wait; } else { // Aligned by 2 - cpustate->program->write_data16((address + 0) & mask, value & 0xffff); - cpustate->program->write_data16((address + 2) & mask, (value >> 16) & 0xffff); + cpustate->program->write_data16w((address + 0) & mask, value & 0xffff, &wait); + cpustate->memory_wait += wait; + cpustate->program->write_data16w((address + 2) & mask, (value >> 16) & 0xffff, &wait); + cpustate->memory_wait += wait; } } } else { if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_WRITE,&address,&error)) PF_THROW(error); - + int wait; address &= cpustate->a20_mask; - cpustate->program->write_data32(address, value); + cpustate->program->write_data32w(address, value, &wait); + cpustate->memory_wait += wait; } } INLINE void WRITE64(i386_state *cpustate,UINT32 ea, UINT64 value) { UINT32 address = ea, error; - + int wait; if( !QWORD_ALIGNED(ea) ) { /* Unaligned write */ if(!translate_address_with_width(cpustate,cpustate->CPL,TRANSLATE_WRITE,8,&address,&error)) { WRITE8( cpustate, address+0, value & 0xff ); @@ -1494,22 +1590,36 @@ INLINE void WRITE64(i386_state *cpustate,UINT32 ea, UINT64 value) } else { uint32_t mask = cpustate->a20_mask; if(DWORD_ALIGNED(ea)) { // Aligned by 4 - cpustate->program->write_data32((address + 0) & mask, value & 0xffffffff); - cpustate->program->write_data32((address + 4) & mask, (value >> 32) & 0xffffffff); + cpustate->program->write_data32w((address + 0) & mask, value & 0xffffffff, &wait); + cpustate->memory_wait += wait; + cpustate->program->write_data32w((address + 4) & mask, (value >> 32) & 0xffffffff, &wait); + cpustate->memory_wait += wait; } else if(!WORD_ALIGNED(ea)) { // Never aligned - cpustate->program->write_data8((address + 0) & mask, value & 0xff); - cpustate->program->write_data8((address + 1) & mask, (value >> 8) & 0xff); - cpustate->program->write_data8((address + 2) & mask, (value >> 16) & 0xff); - cpustate->program->write_data8((address + 3) & mask, (value >> 24) & 0xff); - cpustate->program->write_data8((address + 4) & mask, (value >> 32) & 0xff); - cpustate->program->write_data8((address + 5) & mask, (value >> 40) & 0xff); - cpustate->program->write_data8((address + 6) & mask, (value >> 48) & 0xff); - cpustate->program->write_data8((address + 7) & mask, (value >> 56) & 0xff); + cpustate->program->write_data8w((address + 0) & mask, value & 0xff, &wait); + cpustate->memory_wait += wait; + cpustate->program->write_data8w((address + 1) & mask, (value >> 8) & 0xff, &wait); + cpustate->memory_wait += wait; + cpustate->program->write_data8w((address + 2) & mask, (value >> 16) & 0xff, &wait); + cpustate->memory_wait += wait; + cpustate->program->write_data8w((address + 3) & mask, (value >> 24) & 0xff, &wait); + cpustate->memory_wait += wait; + cpustate->program->write_data8w((address + 4) & mask, (value >> 32) & 0xff, &wait); + cpustate->memory_wait += wait; + cpustate->program->write_data8w((address + 5) & mask, (value >> 40) & 0xff, &wait); + cpustate->memory_wait += wait; + cpustate->program->write_data8w((address + 6) & mask, (value >> 48) & 0xff, &wait); + cpustate->memory_wait += wait; + cpustate->program->write_data8w((address + 7) & mask, (value >> 56) & 0xff, &wait); + cpustate->memory_wait += wait; } else { // Aligned by 2 - cpustate->program->write_data16((address + 0) & mask, value & 0xffff); - cpustate->program->write_data16((address + 2) & mask, (value >> 16) & 0xffff); - cpustate->program->write_data16((address + 4) & mask, (value >> 32) & 0xffff); - cpustate->program->write_data16((address + 6) & mask, (value >> 48) & 0xffff); + cpustate->program->write_data16w((address + 0) & mask, value & 0xffff, &wait); + cpustate->memory_wait += wait; + cpustate->program->write_data16w((address + 2) & mask, (value >> 16) & 0xffff, &wait); + cpustate->memory_wait += wait; + cpustate->program->write_data16w((address + 4) & mask, (value >> 32) & 0xffff, &wait); + cpustate->memory_wait += wait; + cpustate->program->write_data16w((address + 6) & mask, (value >> 48) & 0xffff, &wait); + cpustate->memory_wait += wait; } } } else { @@ -1517,8 +1627,10 @@ INLINE void WRITE64(i386_state *cpustate,UINT32 ea, UINT64 value) PF_THROW(error); address &= cpustate->a20_mask; - cpustate->program->write_data32(address+0, value & 0xffffffff); - cpustate->program->write_data32(address+4, (value >> 32) & 0xffffffff); + cpustate->program->write_data32w(address+0, value & 0xffffffff, &wait); + cpustate->memory_wait += wait; + cpustate->program->write_data32w(address+4, (value >> 32) & 0xffffffff, &wait); + cpustate->memory_wait += wait; } } @@ -1878,13 +1990,18 @@ INLINE void check_ioperm(i386_state *cpustate, offs_t port, UINT8 mask) INLINE UINT8 READPORT8(i386_state *cpustate, offs_t port) { check_ioperm(cpustate, port, 1); - return cpustate->io->read_io8(port); + int wait; + UINT8 val = cpustate->io->read_io8w(port, &wait); + cpustate->memory_wait += wait; + return val; } INLINE void WRITEPORT8(i386_state *cpustate, offs_t port, UINT8 value) { check_ioperm(cpustate, port, 1); - cpustate->io->write_io8(port, value); + int wait; + cpustate->io->write_io8w(port, value, &wait); + cpustate->memory_wait += wait; } INLINE UINT16 READPORT16(i386_state *cpustate, offs_t port) @@ -1897,8 +2014,11 @@ INLINE UINT16 READPORT16(i386_state *cpustate, offs_t port) } else { + int wait; check_ioperm(cpustate, port, 3); - return cpustate->io->read_io16(port); + UINT16 val = cpustate->io->read_io16w(port, &wait); + cpustate->memory_wait += wait; + return val; } } @@ -1912,7 +2032,9 @@ INLINE void WRITEPORT16(i386_state *cpustate, offs_t port, UINT16 value) else { check_ioperm(cpustate, port, 3); - cpustate->io->write_io16(port, value); + int wait; + cpustate->io->write_io16w(port, value, &wait); + cpustate->memory_wait += wait; } } @@ -1929,7 +2051,10 @@ INLINE UINT32 READPORT32(i386_state *cpustate, offs_t port) else { check_ioperm(cpustate, port, 0xf); - return cpustate->io->read_io32(port); + int wait; + UINT32 val = cpustate->io->read_io32w(port, &wait); + cpustate->memory_wait += wait; + return val; } } @@ -1945,7 +2070,9 @@ INLINE void WRITEPORT32(i386_state *cpustate, offs_t port, UINT32 value) else { check_ioperm(cpustate, port, 0xf); - cpustate->io->write_io32(port, value); + int wait; + cpustate->io->write_io32w(port, value, &wait); + cpustate->memory_wait += wait; } } diff --git a/source/src/vm/pc9801/display.cpp b/source/src/vm/pc9801/display.cpp index 68d6d16de..f325e0da2 100644 --- a/source/src/vm/pc9801/display.cpp +++ b/source/src/vm/pc9801/display.cpp @@ -430,23 +430,37 @@ void DISPLAY::event_frame() void DISPLAY::write_signal(int ch, uint32_t data, uint32_t mask) { - if(ch == SIG_DISPLAY98_SET_PAGE_A0) { - data = data & 0x000e0000; // ToDo: Hi RESO - if((data < 0x000a0000) || (data >= 0x000f0000)) data = 0x80000000; - bank_table[0x0a] = data; - bank_table[0x0b] = data + 0x00010000; - } else if(ch == SIG_DISPLAY98_SET_PAGE_80) { - data = data & 0x000e0000; // ToDo: Hi RESO - if((data < 0x000a0000) || (data >= 0x000f0000)) data = 0x80000000; - bank_table[0x08] = data; - bank_table[0x09] = data + 0x00010000; - } else if(ch == SIG_DISPLAY98_SET_BANK) { + switch(ch) { + case SIG_DISPLAY98_SET_PAGE_A0: + { + data = data & 0x000e0000; // ToDo: Hi RESO + if((data < 0x000a0000) || (data >= 0x000f0000)) data = 0x80000000; + bank_table[0x0a] = data; + bank_table[0x0b] = data + 0x00010000; + } + break; + case SIG_DISPLAY98_SET_PAGE_80: + { + data = data & 0x000e0000; // ToDo: Hi RESO + if((data < 0x000a0000) || (data >= 0x000f0000)) data = 0x80000000; + bank_table[0x08] = data; + bank_table[0x09] = data + 0x00010000; + } + break; + case SIG_DISPLAY98_SET_BANK: // WIP: Still dummy. vram_bank = ((data & mask) != 0) ? 0x10000 : 0x00000; - } /*else if(ch == SIG_DISPLAY98_HIGH_RESOLUTION) { - display_high = ((data & mask) != 0); - printf("DISP MODE=%d\n", display_high); - }*/ + break; + /*case SIG_DISPLAY98_HIGH_RESOLUTION: + { + display_high = ((data & mask) != 0); + printf("DISP MODE=%d\n", display_high); + } + break; + */ + default: + break; + } } void DISPLAY::write_io8(uint32_t addr, uint32_t data) @@ -980,7 +994,7 @@ void DISPLAY::write_memory_mapped_io16(uint32_t addr, uint32_t data) uint32_t DISPLAY::read_memory_mapped_io8(uint32_t addr) { uint32_t idx = (addr & 0x000f0000) >> 16; - if(bank_table[idx] >= 0x80000000) return; + if(bank_table[idx] >= 0x80000000) return 0xff; addr = bank_table[idx] | (addr & 0x0000ffff); addr = addr & 0x000fffff; // For 32bit @@ -1059,7 +1073,7 @@ uint32_t DISPLAY::read_memory_mapped_io8(uint32_t addr) uint32_t DISPLAY::read_memory_mapped_io16(uint32_t addr) { uint32_t idx = (addr & 0x000f0000) >> 16; - if(bank_table[idx] >= 0x80000000) return; + if(bank_table[idx] >= 0x80000000) return 0xffff; addr = bank_table[idx] | (addr & 0x0000ffff); addr = addr & 0x000fffff; // For 32bit @@ -2995,7 +3009,7 @@ void DISPLAY::draw_gfx_screen() } } -#define STATE_VERSION 7 +#define STATE_VERSION 8 bool DISPLAY::process_state(FILEIO* state_fio, bool loading) { @@ -3075,11 +3089,12 @@ bool DISPLAY::process_state(FILEIO* state_fio, bool loading) // state_fio->StateValue(font_lr); state_fio->StateValue(b_gfx_ff); // state_fio->StateValue(vram_bank); + state_fio->StateArray(bank_table, sizeof(bank_table), 1); // post process -#if defined(SUPPORT_2ND_VRAM) && !defined(SUPPORT_HIRESO) if(loading) { +#if defined(SUPPORT_2ND_VRAM) && !defined(SUPPORT_HIRESO) if(vram_disp_sel & 1) { vram_disp_b = vram + 0x28000; vram_disp_r = vram + 0x30000; @@ -3110,8 +3125,8 @@ bool DISPLAY::process_state(FILEIO* state_fio, bool loading) grcg_tile_word[i] = ((uint16_t)(grcg_tile[i]) << 8) | grcg_tile[i]; } #endif - } #endif + } return true; } diff --git a/source/src/vm/pc9801/display.h b/source/src/vm/pc9801/display.h index 2fdfa7052..448dbc9cf 100644 --- a/source/src/vm/pc9801/display.h +++ b/source/src/vm/pc9801/display.h @@ -28,6 +28,7 @@ #define SIG_DISPLAY98_SET_PAGE_A0 2 #define SIG_DISPLAY98_SET_BANK 3 //#define SIG_DISPLAY98_HIGH_RESOLUTION 4 + class UPD7220; namespace PC9801 { @@ -219,6 +220,7 @@ private: void egc_writeb(uint32_t addr1, uint8_t value); void egc_writew(uint32_t addr1, uint16_t value); #endif + void draw_chr_screen(); void draw_gfx_screen(); void init_memsw(); @@ -239,6 +241,10 @@ public: void event_frame(); void write_io8(uint32_t addr, uint32_t data); uint32_t read_io8(uint32_t addr); +// void write_memory_mapped_io8w(uint32_t addr, uint32_t data, int* wait); +// void write_memory_mapped_io16w(uint32_t addr, uint32_t data, int* wait); +// uint32_t read_memory_mapped_io8w(uint32_t addr, int* wait); +// uint32_t read_memory_mapped_io16w(uint32_t addr, int* wait); void write_memory_mapped_io8(uint32_t addr, uint32_t data); void write_memory_mapped_io16(uint32_t addr, uint32_t data); uint32_t read_memory_mapped_io8(uint32_t addr); diff --git a/source/src/vm/pc9801/membus.cpp b/source/src/vm/pc9801/membus.cpp index 000c98c2c..9249f403d 100644 --- a/source/src/vm/pc9801/membus.cpp +++ b/source/src/vm/pc9801/membus.cpp @@ -97,6 +97,8 @@ void MEMBUS::initialize() // RAM memset(ram, 0x00, sizeof(ram)); // VRAM + gvram_wait_val = 1; + tvram_wait_val = 4; // BIOS memset(bios, 0xff, sizeof(bios)); @@ -176,6 +178,13 @@ void MEMBUS::initialize() last_access_is_interam = false; config_intram(); update_bios(); + + intram_wait = 1; + bank08_wait = 10; + exmem_wait = 2; + slotmem_wait = 2; + exboards_wait = 4; + introm_wait = 1; } void MEMBUS::reset() @@ -559,6 +568,47 @@ void MEMBUS::write_dma_data8(uint32_t addr, uint32_t data) } #endif +void MEMBUS::write_signal(int ch, uint32_t data, uint32_t mask) +{ + switch(ch) { + case SIG_INTRAM_WAIT: + intram_wait = (int)(data & 0xff); + update_bios(); + break; + case SIG_BANK08_WAIT: + bank08_wait = (int)(data & 0xff); + update_bios(); + break; + case SIG_EXMEM_WAIT: + exmem_wait = (int)(data & 0xff); + update_bios(); + break; + case SIG_SLOTMEM_WAIT: + slotmem_wait = (int)(data & 0xff); + update_bios(); + break; + case SIG_EXBOARDS_WAIT: + exboards_wait = (int)(data & 0xff); + update_bios(); + break; + case SIG_INTROM_WAIT: + introm_wait = (int)(data & 0xff); + update_bios(); + break; + case SIG_GVRAM_WAIT: + gvram_wait_val = (int)(data & 0xff); + update_bios(); + break; + case SIG_TVRAM_WAIT: + tvram_wait_val = (int)(data & 0xff); + update_bios(); + break; + default: + break; + } +} + + uint32_t MEMBUS::read_signal(int ch) { switch(ch) { @@ -600,8 +650,12 @@ void MEMBUS::update_bios() #endif set_memory_mapped_io_rw(0xa0000, 0xa4fff, d_display); set_memory_mapped_io_rw(0xa8000, 0xbffff, d_display); + set_wait_rw(0xa0000, 0xbffff, gvram_wait_val); // OK? + set_wait_r(0xa0000, 0xa4fff, tvram_wait_val); + set_wait_w(0xa0000, 0xa4fff, tvram_wait_val); #else unset_memory_rw(0xc0000, 0xe4fff); + set_wait_rw(0xc0000, 0xe4fff, intram_wait); #endif #if !defined(SUPPORT_HIRESO) { @@ -613,6 +667,7 @@ void MEMBUS::update_bios() #endif #if defined(SUPPORT_16_COLORS) set_memory_mapped_io_rw(0xe0000, 0xe7fff, d_display); + set_wait_rw(0xe0000, 0xe7fff, gvram_wait_val); // OK? #endif update_sound_bios(); @@ -631,9 +686,11 @@ void MEMBUS::update_bios() #if defined(SUPPORT_BIOS_RAM) && defined(SUPPORT_32BIT_ADDRESS) if(shadow_ram_selected) { set_memory_rw(0xc0000, 0xe7fff, &(ram[0xc0000])); // OK? + set_wait_rw(0xc0000, 0xe7fff, intram_wait); } #endif #endif + set_wait_rw(0x00100000 - sizeof(bios), 0xfffff, introm_wait); { #if defined(SUPPORT_BIOS_RAM) if(bios_ram_selected) { @@ -671,7 +728,11 @@ void MEMBUS::update_bios() } } #endif + if(sizeof(ram) > 0x10000) { + set_wait_rw(0x00100000, (sizeof(ram) >= 0x00e00000) ? 0x00dfffff : (sizeof(ram) - 1), exmem_wait); + } if((page08_intram_selected) /*&& (shadow_ram_selected)*/){ + set_wait_rw(0x80000, 0x9ffff, bank08_wait); if((window_80000h == 0xc0000)) { #if defined(UPPER_I386) && defined(SUPPORT_BIOS_RAM) if(shadow_ram_selected) { @@ -715,6 +776,7 @@ void MEMBUS::update_bios() } else { // Internal RAM is not selected. // ToDo: Hi reso + set_wait_rw(0x80000, 0x9ffff, bank08_wait); if(window_80000h < 0x80000) { #if defined(SUPPORT_BIOS_RAM) if(!(bios_ram_selected)) { @@ -731,7 +793,12 @@ void MEMBUS::update_bios() copy_table_rw(0x00080000, window_80000h, window_80000h + 0x1ffff); } } - + if(shadow_ram_selected) { +// set_wait_rw(0xa0000, 0xbffff, bank08_wait); + set_wait_rw(0xa0000, 0xbffff, intram_wait); + } else { + set_wait_rw(0xa0000, 0xbffff, intram_wait); + } /*if((page08_intram_selected) )*/{ if((window_a0000h == 0xc0000)) { #if defined(UPPER_I386) && defined(SUPPORT_BIOS_RAM) @@ -814,6 +881,7 @@ void MEMBUS::update_sound_bios() } else { unset_memory_rw(0xcc000, 0xcffff); } + set_wait_rw(0xcc000, 0xcffff, exboards_wait); } #if defined(SUPPORT_SASI_IF) @@ -831,6 +899,7 @@ void MEMBUS::update_sasi_bios() } else { unset_memory_rw(0xd7000, 0xd7fff); } + set_wait_rw(0xd7000, 0xd7fff, exboards_wait); } #endif @@ -847,6 +916,7 @@ void MEMBUS::update_scsi_bios() } else { unset_memory_rw(0xdc000, 0xdcfff); } + set_wait_rw(0xdc000, 0xdcfff, exboards_wait); } #endif @@ -861,6 +931,7 @@ void MEMBUS::update_ide_bios() } else { unset_memory_rw(0xd8000, 0xdbfff); } + set_wait_rw(0xd8000, 0xdbfff, exboards_wait); } #endif @@ -874,11 +945,12 @@ void MEMBUS::update_nec_ems() unset_memory_rw(0xb0000, 0xbffff); set_memory_mapped_io_rw(0xb0000, 0xbffff, d_display); } + set_wait_rw(0xb0000, 0xbffff, slotmem_wait); } #endif -#define STATE_VERSION 12 +#define STATE_VERSION 13 bool MEMBUS::process_state(FILEIO* state_fio, bool loading) { @@ -931,7 +1003,16 @@ bool MEMBUS::process_state(FILEIO* state_fio, bool loading) state_fio->StateValue(page08_intram_selected); state_fio->StateValue(shadow_ram_selected); state_fio->StateValue(last_access_is_interam); - + + state_fio->StateValue(intram_wait); + state_fio->StateValue(bank08_wait); + state_fio->StateValue(exmem_wait); + state_fio->StateValue(slotmem_wait); + state_fio->StateValue(exboards_wait); + state_fio->StateValue(introm_wait); + state_fio->StateValue(gvram_wait_val); + state_fio->StateValue(tvram_wait_val); + if(!MEMORY::process_state(state_fio, loading)) { return false; } diff --git a/source/src/vm/pc9801/membus.h b/source/src/vm/pc9801/membus.h index e8808e42d..c0bf15f66 100644 --- a/source/src/vm/pc9801/membus.h +++ b/source/src/vm/pc9801/membus.h @@ -40,7 +40,15 @@ namespace PC9801 { namespace PC9801 { #define SIG_LAST_ACCESS_INTERAM 1 - +#define SIG_INTRAM_WAIT 2 +#define SIG_BANK08_WAIT 3 +#define SIG_EXMEM_WAIT 4 +#define SIG_SLOTMEM_WAIT 5 +#define SIG_EXBOARDS_WAIT 6 +#define SIG_INTROM_WAIT 7 +#define SIG_TVRAM_WAIT 8 +#define SIG_GVRAM_WAIT 9 + class MEMBUS : public MEMORY { private: @@ -69,6 +77,15 @@ private: uint8_t itf[0x8000]; bool itf_selected; #endif + + int intram_wait; + int bank08_wait; + int exmem_wait; + int slotmem_wait; + int exboards_wait; + int introm_wait; + int gvram_wait_val; + int tvram_wait_val; void update_bios(); #if !defined(SUPPORT_HIRESO) @@ -136,6 +153,7 @@ public: void initialize(); void reset(); uint32_t read_signal(int ch); + void write_signal(int ch, uint32_t data, uint32_t mask); void write_io8(uint32_t addr, uint32_t data); uint32_t read_io8(uint32_t addr); #if defined(SUPPORT_24BIT_ADDRESS) || defined(SUPPORT_32BIT_ADDRESS) diff --git a/source/src/vm/pc9801/pc9801.cpp b/source/src/vm/pc9801/pc9801.cpp index 88f3edc58..9601afe33 100644 --- a/source/src/vm/pc9801/pc9801.cpp +++ b/source/src/vm/pc9801/pc9801.cpp @@ -1085,6 +1085,180 @@ void VM::set_cpu_clock_with_switch(int speed_type) pit->set_constant_clock(2, pit_clocks); } +void VM::set_wait(int dispmode, int clock) +{ + // by PC-9800 Technical Data Book (HARDWARE), ASCII, 1993. + int io_wait = 8; // I/O + int slotmem_wait = 4; // Extra RAM on extra bus. + int exmem_wait = 1; // Extra RAM on extra memory slot. + int exboards_wait = 8; // BANK 0C, 0D + int introm_wait = 0; // INTERNAL ROM (BIOS, ITF) + int bank08_wait = 2/*8*/; + int intram_wait = 0; + int cpuclock = 8000000; + // TODO: INTA +#if defined(_PC9801RA) || defined(_PC9801RL) + // PC-9801RA21 + intram_wait = 0; + if(clock == 0) { // FAST CLOCK (20MHz) + cpuclock = 20000000; +#if defined(_SUPPORT_HIRESO) + if(dispmode != 0) { // Low RESO + exboards_wait = 12; + } else { + introm_wait = 6; + } +#else + exboards_wait = 12; +#endif + io_wait = 10; + } else { + cpuclock = 16000000; +#if defined(_SUPPORT_HIRESO) + if(dispmode != 0) { // Low RESO + exboards_wait = 10; + } else { + introm_wait = 4; + } +#else + exboards_wait = 10; +#endif + io_wait = 8; + } + +#elif defined(_PC98XL2) + // ToDo: V30 + cpuclock = 16000000; + if(dispmode == 0) { + intram_wait = 1; + bank08_wait = 1; + io_wait = 10; + introm_wait = 6; + slotmem_wait = 6; + exmem_wait = 1; + exboards_wait = 4; + // inta_wait = 14; + } else { // Normal + intram_wait = 1; + bank08_wait = 1; + io_wait = 10; + introm_wait = 1; + slotmem_wait = 6; + exmem_wait = 1; + exboards_wait = 12; + // inta_wait = 14; + } + +#elif defined(_PC98XL) + if(dispmode == 0) { + intram_wait = 1; + bank08_wait = 1; + io_wait = 3; + introm_wait = 1; + slotmem_wait = 1; + exmem_wait = 1; + exboards_wait = 4; + cpuclock = 8000000; + if(clock == 0) { // FAST CLOCK (10MHz) + io_wait += 1; + exboards_wait = 1; + cpuclock = 10000000; + } + // inta_wait = 5; + } else { // Normal + intram_wait = 0; + bank08_wait = 0; + io_wait = 3; + introm_wait = 0; + slotmem_wait = 0; + exmem_wait = 1; + exboards_wait = 4; + cpuclock = (clock == 0) ? 10000000 : 8000000; + } + +#elif defined(_PC9801VM21) || defined(_PC9801VX) + // ToDo: V30 + // They are for 80286. + if(clock == 0) { // FAST CLOCK (10MHz) + cpuclock = 10000000; + intram_wait = 0; + bank08_wait = 5; + io_wait = 4; + introm_wait = 0; + slotmem_wait = 1; + exmem_wait = 1; + exboards_wait = 5; + } else { // SLOW (8MHz) + cpuclock = 8000000; + intram_wait = 0; + io_wait = 3; + bank08_wait = 4; + introm_wait = 0; + slotmem_wait = 1; + exmem_wait = 1; + exboards_wait = 4; + // inta_wait = 5; + } +#elif defined(_PC9801U) || defined(_PC9801VF) || defined(_PC9801VM) || defined(_PC9801UV) + if(clock == 0) { // FAST CLOCK (10MHz) + cpuclock = 10000000; + intram_wait = 1; + io_wait = 3; + } else { // SLOW (8MHz) + cpuclock = 8000000; + intram_wait = 0; + io_wait = 2; + } + slotmem_wait = intram_wait; + exmem_wait = intram_wait; + exboards_wait = intram_wait; + introm_wait = intram_wait; + bank08_wait = intram_wait; +#elif defined(_PC98XA) + cpuclock = 8000000; + intram_wait = 1; + io_wait = 3; + // inta_wait = 2; + slotmem_wait = intram_wait; + exmem_wait = intram_wait; + exboards_wait = intram_wait; + introm_wait = intram_wait; + bank08_wait = intram_wait; +#elif defined(_PC9801E) || defined(_PC9801F) || defined(_PC9801M) || defined(_PC9801) + // ToDo: Others. + if(clock == 0) { // FAST CLOCK (8MHz) + cpuclock = 8000000; + intram_wait = 1; + io_wait = 2; + } else { + cpuclock = 5000000; + intram_wait = 0; + io_wait = 1; + } + slotmem_wait = intram_wait; + exmem_wait = intram_wait; + exboards_wait = intram_wait; + introm_wait = intram_wait; + bank08_wait = intram_wait; +#endif + memory->write_signal(SIG_INTRAM_WAIT, intram_wait, 0xff); + memory->write_signal(SIG_BANK08_WAIT, bank08_wait, 0xff); + memory->write_signal(SIG_EXMEM_WAIT, exmem_wait, 0xff); + memory->write_signal(SIG_SLOTMEM_WAIT, slotmem_wait, 0xff); + memory->write_signal(SIG_EXBOARDS_WAIT, exboards_wait, 0xff); + memory->write_signal(SIG_INTROM_WAIT, introm_wait, 0xff); + // IO + io->set_iowait_range_r(0x0000, 0xffff, io_wait); + io->set_iowait_range_w(0x0000, 0xffff, io_wait); + // ToDo: Wait factor + int waitval; + waitval = (int)round(((double)cpuclock) / (1.0e6 / 1.6)); + if(waitval < 1) waitval = 0; + memory->write_signal(SIG_TVRAM_WAIT, waitval, 0xfffff); // OK? + memory->write_signal(SIG_GVRAM_WAIT, intram_wait, 0xfffff); // OK? +// memory->write_signal(SIG_GVRAM_WAIT, waitval, 0xfffff); // OK? +} + void VM::reset() { // Set resolution before resetting. @@ -1095,6 +1269,7 @@ void VM::reset() io->set_iovalue_single_r(0x0431, 0x00); gdc_gfx->set_horiz_freq(24830); gdc_chr->set_horiz_freq(24830); + } else { // WIP io->set_iovalue_single_r(0x0431, 0x04); // bit2: 1 = Normal mode, 0 = Hireso mode gdc_gfx->set_horiz_freq(15750); @@ -1114,6 +1289,11 @@ void VM::reset() #endif set_cpu_clock_with_switch((config.cpu_type != 0) ? 1 : 0); +#if defined(USE_MONITOR_TYPE) + set_wait(config.monitor_type, config.cpu_type); +#else + set_wait(0, config.cpu_type); +#endif port_a = 0x00; // port_a |= 0x80; // DIP SW 2-8, 1 = GDC 2.5MHz, 0 = GDC 5MHz port_a |= 0x40; // DIP SW 2-7, 1 = Do not control FD motor @@ -1715,9 +1895,15 @@ bool VM::is_frame_skippable() return event->is_frame_skippable(); } + void VM::update_config() { set_cpu_clock_with_switch((config.cpu_type != 0) ? 1 : 0); +#if defined(USE_MONITOR_TYPE) + set_wait(config.monitor_type, config.cpu_type); +#else + set_wait(0, config.cpu_type); +#endif { uint8_t mouse_port_b = pio_mouse->read_signal(SIG_I8255_PORT_B); mouse_port_b = mouse_port_b & ~0x40; @@ -1801,6 +1987,11 @@ bool VM::process_state(FILEIO* state_fio, bool loading) state_fio->StateValue(sound_type); if(loading) { set_cpu_clock_with_switch((config.cpu_type != 0) ? 1 : 0); +#if defined(USE_MONITOR_TYPE) + set_wait(config.monitor_type, config.cpu_type); +#else + set_wait(0, config.cpu_type); +#endif } return true; } diff --git a/source/src/vm/pc9801/pc9801.h b/source/src/vm/pc9801/pc9801.h index 07dece0a7..b73dc9869 100644 --- a/source/src/vm/pc9801/pc9801.h +++ b/source/src/vm/pc9801/pc9801.h @@ -665,6 +665,7 @@ public: // for each device // ---------------------------------------- void set_cpu_clock_with_switch(int speed_type); // 0 = High / 1 = Low / Others = (WIP) + void set_wait(int dispmode, int clock); // Set waitfor memories and IOs. // devices DEVICE* get_device(int id);