• R/O
  • HTTP
  • SSH
  • HTTPS

common_source_project-fm7: Commit

Common Source Code Project for Qt (a.k.a for FM-7).


Commit MetaInfo

Revision8e87b770d1495e38439682db0df7083b1cbb8a42 (tree)
Time2019-01-12 18:39:04
AuthorK.Ohta <whatisthis.sowhat@gmai...>
CommiterK.Ohta

Log Message

[General] Merge Upstream 2018-12-27.

Change Summary

Incremental Difference

--- a/source/history.txt
+++ b/source/history.txt
@@ -1,3 +1,24 @@
1+12/27/2018
2+
3+[PC6001/PSUB] improve keyboard irq
4+[PC8801/PC88] improve initial memory map when CD BIOS is loaded
5+[PC8801/PC88] support CD-DA fade in/out
6+
7+
8+12/18/2018
9+
10+[VM/I386] improve i386 core based on MAME 0.204
11+[VM/SCSI_CDROM] improve vendor specific command for NEC CD-ROM^2
12+[VM/SCSI_DEV] fix to write buffer when current command is not WRITE6/10/12
13+[VM/SCSI_DEV] fix Request Sense command to get correct data length
14+[VM/SCSI_HDD] fix not to write buffer when current command is not WRITE6/10/12
15+
16+[PC8801/PC88] improve initial memory map when CD BIOS is loaded
17+[PC8801/PC88] revert screen renderer fixes in 12/1/2018 except scanline issues
18+[PC8801/PC88] fix dmac registers to clear higher 16bits of pair32_t
19+[PC8801/PC88] fix dmac to read i/o in verify mode
20+
21+
122 12/9/2018
223
324 [VM/SCSI_CDROM] add vendor specific command for NEC CD-ROM^2
--- a/source/src/vm/common_vm/CMakeLists.txt
+++ b/source/src/vm/common_vm/CMakeLists.txt
@@ -1,6 +1,6 @@
11 message("* vm/common_vm")
22
3-SET(THIS_LIB_VERSION 2.5.0)
3+SET(THIS_LIB_VERSION 2.5.1)
44
55 #include(cotire)
66 set(s_vm_common_vm_srcs
--- a/source/src/vm/fm7/display.cpp
+++ b/source/src/vm/fm7/display.cpp
@@ -960,8 +960,8 @@ void DISPLAY::copy_vram_blank_area(void)
960960 void DISPLAY::copy_vram_per_line(int begin, int end)
961961 {
962962 uint32_t src_offset;
963- uint32_t yoff_d1;
964- uint32_t yoff_d2;
963+ uint32_t yoff_d1 = 0;
964+ uint32_t yoff_d2 = 0;
965965 uint32_t yoff_d;
966966 uint32_t poff = 0;
967967 uint32_t src_base;
--- a/source/src/vm/fm7/vram.cpp
+++ b/source/src/vm/fm7/vram.cpp
@@ -355,7 +355,7 @@ void DISPLAY::draw_screen2()
355355 if(text_width40) {
356356 xlim = 40;
357357 } else {
358- ylim = 80;
358+ xlim = 80;
359359 }
360360
361361 for(x = 0; x < xlim; x++) {
--- a/source/src/vm/libcpu_newdev/libcpu_i386/i386_opdef.cpp
+++ b/source/src/vm/libcpu_newdev/libcpu_i386/i386_opdef.cpp
@@ -131,8 +131,10 @@ void I386_OPS_BASE::i386_load_segment_descriptor( int segment )
131131 if (!V8086_MODE)
132132 {
133133 i386_load_protected_mode_segment(&cpustate->sreg[segment], NULL );
134- if(cpustate->sreg[segment].selector)
135- i386_set_descriptor_accessed(cpustate->sreg[segment].selector);
134+ {
135+ i386_set_descriptor_accessed(cpustate, cpustate->sreg[segment].selector);
136+ cpustate->sreg[segment].flags |= 0x0001;
137+ }
136138 }
137139 else
138140 {
@@ -142,6 +144,8 @@ void I386_OPS_BASE::i386_load_segment_descriptor( int segment )
142144 cpustate->sreg[segment].d = 0;
143145 cpustate->sreg[segment].valid = true;
144146 }
147+// if (segment == CS && cpustate->sreg[segment].flags != old_flags)
148+// debugger_privilege_hook();
145149 }
146150 else
147151 {
@@ -215,6 +219,7 @@ UINT32 I386_OPS_BASE::get_flags()
215219
216220 void I386_OPS_BASE::set_flags( UINT32 f )
217221 {
222+ f &= cpustate->eflags_mask;;
218223 cpustate->CF = (f & 0x1) ? 1 : 0;
219224 cpustate->PF = (f & 0x4) ? 1 : 0;
220225 cpustate->AF = (f & 0x10) ? 1 : 0;
@@ -233,7 +238,7 @@ void I386_OPS_BASE::set_flags( UINT32 f )
233238 cpustate->VIF = (f & 0x80000) ? 1 : 0;
234239 cpustate->VIP = (f & 0x100000) ? 1 : 0;
235240 cpustate->ID = (f & 0x200000) ? 1 : 0;
236- cpustate->eflags = f & cpustate->eflags_mask;
241+ cpustate->eflags = f;
237242 }
238243
239244 void I386_OPS_BASE::sib_byte(UINT8 mod, UINT32* out_ea, UINT8* out_segment)
--- a/source/src/vm/libcpu_newdev/libcpu_i386/i386op32.cpp
+++ b/source/src/vm/libcpu_newdev/libcpu_i386/i386op32.cpp
@@ -325,7 +325,7 @@ void I386_OPS_BASE::I386OP(bsr_r32_rm32)() // Opcode 0x0f bd
325325 } else {
326326 cpustate->ZF = 0;
327327 dst = temp = 31;
328- while( (src & (1 << temp)) == 0 ) {
328+ while( (src & (1U << temp)) == 0 ) {
329329 temp--;
330330 dst = temp;
331331 CYCLES(CYCLES_BSR);
--- a/source/src/vm/libcpu_newdev/libcpu_i386/i386ops.cpp
+++ b/source/src/vm/libcpu_newdev/libcpu_i386/i386ops.cpp
@@ -704,6 +704,8 @@ void I386_OPS_BASE::I386OP(mov_cr_r32)() // Opcode 0x0f 22
704704 case 0:
705705 data &= 0xfffeffff; // wp not supported on 386
706706 CYCLES(CYCLES_MOV_REG_CR0);
707+// if (PROTECTED_MODE != BIT(data, 0))
708+// debugger_privilege_hook();
707709 break;
708710 case 2: CYCLES(CYCLES_MOV_REG_CR2); break;
709711 case 3:
--- a/source/src/vm/libcpu_newdev/libcpu_i386/i486ops.cpp
+++ b/source/src/vm/libcpu_newdev/libcpu_i386/i486ops.cpp
@@ -156,14 +156,16 @@ void I386_OPS_BASE::I486OP(xadd_rm8_r8)() // Opcode 0x0f c0
156156 if( modrm >= 0xc0 ) {
157157 UINT8 dst = LOAD_RM8(modrm);
158158 UINT8 src = LOAD_REG8(modrm);
159+ UINT8 sum = ADD8(cpustate, dst, src);
159160 STORE_REG8(modrm, dst);
160- STORE_RM8(modrm, dst + src);
161+ STORE_RM8(modrm, sum);
161162 CYCLES(CYCLES_XADD_REG_REG);
162163 } else {
163164 UINT32 ea = GetEA(modrm, 1, 1);
164165 UINT8 dst = READ8(ea);
165166 UINT8 src = LOAD_REG8(modrm);
166- WRITE8(ea, dst + src);
167+ UINT8 sum = ADD8(cpustate, dst, src);
168+ WRITE8(ea, sum);
167169 STORE_REG8(modrm, dst);
168170 CYCLES(CYCLES_XADD_REG_MEM);
169171 }
@@ -175,14 +177,16 @@ void I386_OPS_BASE::I486OP(xadd_rm16_r16)() // Opcode 0x0f c1
175177 if( modrm >= 0xc0 ) {
176178 UINT16 dst = LOAD_RM16(modrm);
177179 UINT16 src = LOAD_REG16(modrm);
180+ UINT16 sum = ADD16(cpustate, dst, src);
178181 STORE_REG16(modrm, dst);
179- STORE_RM16(modrm, dst + src);
182+ STORE_RM16(modrm, sum);
180183 CYCLES(CYCLES_XADD_REG_REG);
181184 } else {
182185 UINT32 ea = GetEA(modrm, 1, 2);
183186 UINT16 dst = READ16(ea);
184187 UINT16 src = LOAD_REG16(modrm);
185- WRITE16(ea, dst + src);
188+ UINT16 sum = ADD16(cpustate, dst, src);
189+ WRITE16(ea, sum);
186190 STORE_REG16(modrm, dst);
187191 CYCLES(CYCLES_XADD_REG_MEM);
188192 }
@@ -194,14 +198,16 @@ void I386_OPS_BASE::I486OP(xadd_rm32_r32)() // Opcode 0x0f c1
194198 if( modrm >= 0xc0 ) {
195199 UINT32 dst = LOAD_RM32(modrm);
196200 UINT32 src = LOAD_REG32(modrm);
197- STORE_REG32(modrm, dst);
198- STORE_RM32(modrm, dst + src);
201+ UINT32 sum = ADD32(cpustate, dst, src);
202+ STORE_REG32(modrm, dst);
203+ STORE_RM32(modrm, sum);
199204 CYCLES(CYCLES_XADD_REG_REG);
200205 } else {
201206 UINT32 ea = GetEA(modrm, 1, 4);
202207 UINT32 dst = READ32(ea);
203208 UINT32 src = LOAD_REG32(modrm);
204- WRITE32(ea, dst + src);
209+ UINT32 sum = ADD32(cpustate, dst, src);
210+ WRITE32(ea, sum);
205211 STORE_REG32(modrm, dst);
206212 CYCLES(CYCLES_XADD_REG_MEM);
207213 }
@@ -224,7 +230,7 @@ void I386_OPS_BASE::I486OP(group0F01_16)() // Opcode 0x0f 01
224230 ea = GetEA(modrm, 1, 6);
225231 }
226232 WRITE16(ea, cpustate->gdtr.limit);
227- WRITE32(ea + 2, cpustate->gdtr.base & 0xffffff);
233+ WRITE32(ea + 2, cpustate->gdtr.base);
228234 CYCLES(CYCLES_SGDT);
229235 break;
230236 }
@@ -240,7 +246,7 @@ void I386_OPS_BASE::I486OP(group0F01_16)() // Opcode 0x0f 01
240246 ea = GetEA(modrm, 1, 6);
241247 }
242248 WRITE16(ea, cpustate->idtr.limit);
243- WRITE32(ea + 2, cpustate->idtr.base & 0xffffff);
249+ WRITE32(ea + 2, cpustate->idtr.base);
244250 CYCLES(CYCLES_SIDT);
245251 break;
246252 }
@@ -288,9 +294,9 @@ void I386_OPS_BASE::I486OP(group0F01_16)() // Opcode 0x0f 01
288294 }
289295 case 6: /* LMSW */
290296 {
291- UINT16 b;
292297 if(PROTECTED_MODE && cpustate->CPL)
293298 FAULT(FAULT_GP,0)
299+ UINT16 b;
294300 if( modrm >= 0xc0 ) {
295301 b = LOAD_RM16(modrm);
296302 CYCLES(CYCLES_LMSW_REG);
@@ -505,6 +511,8 @@ void I386_OPS_BASE::I486OP(mov_cr_r32)() // Opcode 0x0f 22
505511 CYCLES(CYCLES_MOV_REG_CR0);
506512 if((oldcr ^ cpustate->cr[cr]) & 0x80010000)
507513 vtlb_flush_dynamic(cpustate->vtlb);
514+// if (PROTECTED_MODE != BIT(data, 0))
515+// debugger_privilege_hook();
508516 break;
509517 case 2: CYCLES(CYCLES_MOV_REG_CR2); break;
510518 case 3:
--- a/source/src/vm/libcpu_newdev/libcpu_i386/pentops.cpp
+++ b/source/src/vm/libcpu_newdev/libcpu_i386/pentops.cpp
@@ -15,11 +15,14 @@ void I386_OPS_BASE::PENTIUMOP(rdmsr)() // Opcode 0x0f 32
1515 UINT8 valid_msr = 0;
1616
1717 data = MSR_READ(REG32(ECX),&valid_msr);
18- REG32(EDX) = data >> 32;
19- REG32(EAX) = data & 0xffffffff;
2018
2119 if(cpustate->CPL != 0 || valid_msr == 0) // if current privilege level isn't 0 or the register isn't recognized ...
2220 FAULT(FAULT_GP,0) // ... throw a general exception fault
21+ else
22+ {
23+ REG32(EDX) = data >> 32;
24+ REG32(EAX) = data & 0xffffffff;
25+ }
2326
2427 CYCLES(CYCLES_RDMSR);
2528 }
--- a/source/src/vm/libcpu_newdev/libcpu_i386/readme_takeda.txt
+++ b/source/src/vm/libcpu_newdev/libcpu_i386/readme_takeda.txt
@@ -1,5 +1,5 @@
11 Based on MAME 0.152.
2-Fixes in MAME 0.154 to 0.197 are applied.
2+Fixes in MAME 0.154 to 0.204 are applied.
33
44 cycle_table_rm/pm are changed from dynamic array to static array.
55 convert char to _TCHAR in disassembler.
--- a/source/src/vm/mame/emu/cpu/i386/i386.c
+++ b/source/src/vm/mame/emu/cpu/i386/i386.c
@@ -144,11 +144,15 @@ static void i386_load_segment_descriptor(i386_state *cpustate, int segment )
144144 {
145145 if (PROTECTED_MODE)
146146 {
147+ UINT16 old_flags = cpustate->sreg[segment].flags;
147148 if (!V8086_MODE)
148149 {
149150 i386_load_protected_mode_segment(cpustate, &cpustate->sreg[segment], NULL );
150151 if(cpustate->sreg[segment].selector)
152+ {
151153 i386_set_descriptor_accessed(cpustate, cpustate->sreg[segment].selector);
154+ cpustate->sreg[segment].flags |= 0x0001;
155+ }
152156 }
153157 else
154158 {
@@ -158,6 +162,8 @@ static void i386_load_segment_descriptor(i386_state *cpustate, int segment )
158162 cpustate->sreg[segment].d = 0;
159163 cpustate->sreg[segment].valid = true;
160164 }
165+// if (segment == CS && cpustate->sreg[segment].flags != old_flags)
166+// debugger_privilege_hook();
161167 }
162168 else
163169 {
@@ -231,6 +237,7 @@ static UINT32 get_flags(i386_state *cpustate)
231237
232238 static void set_flags(i386_state *cpustate, UINT32 f )
233239 {
240+ f &= cpustate->eflags_mask;;
234241 cpustate->CF = (f & 0x1) ? 1 : 0;
235242 cpustate->PF = (f & 0x4) ? 1 : 0;
236243 cpustate->AF = (f & 0x10) ? 1 : 0;
@@ -249,7 +256,7 @@ static void set_flags(i386_state *cpustate, UINT32 f )
249256 cpustate->VIF = (f & 0x80000) ? 1 : 0;
250257 cpustate->VIP = (f & 0x100000) ? 1 : 0;
251258 cpustate->ID = (f & 0x200000) ? 1 : 0;
252- cpustate->eflags = f & cpustate->eflags_mask;
259+ cpustate->eflags = f;
253260 }
254261
255262 static void sib_byte(i386_state *cpustate,UINT8 mod, UINT32* out_ea, UINT8* out_segment)
--- a/source/src/vm/mame/emu/cpu/i386/i386op32.c
+++ b/source/src/vm/mame/emu/cpu/i386/i386op32.c
@@ -318,7 +318,7 @@ static void I386OP(bsr_r32_rm32)(i386_state *cpustate) // Opcode 0x0f bd
318318 } else {
319319 cpustate->ZF = 0;
320320 dst = temp = 31;
321- while( (src & (1 << temp)) == 0 ) {
321+ while( (src & (1U << temp)) == 0 ) {
322322 temp--;
323323 dst = temp;
324324 CYCLES(cpustate,CYCLES_BSR);
--- a/source/src/vm/mame/emu/cpu/i386/i386ops.c
+++ b/source/src/vm/mame/emu/cpu/i386/i386ops.c
@@ -697,6 +697,8 @@ static void I386OP(mov_cr_r32)(i386_state *cpustate) // Opcode 0x0f 22
697697 case 0:
698698 data &= 0xfffeffff; // wp not supported on 386
699699 CYCLES(cpustate,CYCLES_MOV_REG_CR0);
700+// if (PROTECTED_MODE != BIT(data, 0))
701+// debugger_privilege_hook();
700702 break;
701703 case 2: CYCLES(cpustate,CYCLES_MOV_REG_CR2); break;
702704 case 3:
--- a/source/src/vm/mame/emu/cpu/i386/i486ops.c
+++ b/source/src/vm/mame/emu/cpu/i386/i486ops.c
@@ -152,14 +152,16 @@ static void I486OP(xadd_rm8_r8)(i386_state *cpustate) // Opcode 0x0f c0
152152 if( modrm >= 0xc0 ) {
153153 UINT8 dst = LOAD_RM8(modrm);
154154 UINT8 src = LOAD_REG8(modrm);
155+ UINT8 sum = ADD8(cpustate, dst, src);
155156 STORE_REG8(modrm, dst);
156- STORE_RM8(modrm, dst + src);
157+ STORE_RM8(modrm, sum);
157158 CYCLES(cpustate,CYCLES_XADD_REG_REG);
158159 } else {
159160 UINT32 ea = GetEA(cpustate,modrm,1,1);
160161 UINT8 dst = READ8(cpustate,ea);
161162 UINT8 src = LOAD_REG8(modrm);
162- WRITE8(cpustate,ea, dst + src);
163+ UINT8 sum = ADD8(cpustate, dst, src);
164+ WRITE8(cpustate,ea, sum);
163165 STORE_REG8(modrm, dst);
164166 CYCLES(cpustate,CYCLES_XADD_REG_MEM);
165167 }
@@ -171,14 +173,16 @@ static void I486OP(xadd_rm16_r16)(i386_state *cpustate) // Opcode 0x0f c1
171173 if( modrm >= 0xc0 ) {
172174 UINT16 dst = LOAD_RM16(modrm);
173175 UINT16 src = LOAD_REG16(modrm);
176+ UINT16 sum = ADD16(cpustate, dst, src);
174177 STORE_REG16(modrm, dst);
175- STORE_RM16(modrm, dst + src);
178+ STORE_RM16(modrm, sum);
176179 CYCLES(cpustate,CYCLES_XADD_REG_REG);
177180 } else {
178181 UINT32 ea = GetEA(cpustate,modrm,1,2);
179182 UINT16 dst = READ16(cpustate,ea);
180183 UINT16 src = LOAD_REG16(modrm);
181- WRITE16(cpustate,ea, dst + src);
184+ UINT16 sum = ADD16(cpustate, dst, src);
185+ WRITE16(cpustate,ea, sum);
182186 STORE_REG16(modrm, dst);
183187 CYCLES(cpustate,CYCLES_XADD_REG_MEM);
184188 }
@@ -190,14 +194,16 @@ static void I486OP(xadd_rm32_r32)(i386_state *cpustate) // Opcode 0x0f c1
190194 if( modrm >= 0xc0 ) {
191195 UINT32 dst = LOAD_RM32(modrm);
192196 UINT32 src = LOAD_REG32(modrm);
197+ UINT32 sum = ADD32(cpustate, dst, src);
193198 STORE_REG32(modrm, dst);
194- STORE_RM32(modrm, dst + src);
199+ STORE_RM32(modrm, sum);
195200 CYCLES(cpustate,CYCLES_XADD_REG_REG);
196201 } else {
197202 UINT32 ea = GetEA(cpustate,modrm,1,4);
198203 UINT32 dst = READ32(cpustate,ea);
199204 UINT32 src = LOAD_REG32(modrm);
200- WRITE32(cpustate,ea, dst + src);
205+ UINT32 sum = ADD32(cpustate, dst, src);
206+ WRITE32(cpustate,ea, sum);
201207 STORE_REG32(modrm, dst);
202208 CYCLES(cpustate,CYCLES_XADD_REG_MEM);
203209 }
@@ -220,7 +226,7 @@ static void I486OP(group0F01_16)(i386_state *cpustate) // Opcode 0x0f 01
220226 ea = GetEA(cpustate,modrm,1,6);
221227 }
222228 WRITE16(cpustate,ea, cpustate->gdtr.limit);
223- WRITE32(cpustate,ea + 2, cpustate->gdtr.base & 0xffffff);
229+ WRITE32(cpustate,ea + 2, cpustate->gdtr.base);
224230 CYCLES(cpustate,CYCLES_SGDT);
225231 break;
226232 }
@@ -236,7 +242,7 @@ static void I486OP(group0F01_16)(i386_state *cpustate) // Opcode 0x0f 01
236242 ea = GetEA(cpustate,modrm,1,6);
237243 }
238244 WRITE16(cpustate,ea, cpustate->idtr.limit);
239- WRITE32(cpustate,ea + 2, cpustate->idtr.base & 0xffffff);
245+ WRITE32(cpustate,ea + 2, cpustate->idtr.base);
240246 CYCLES(cpustate,CYCLES_SIDT);
241247 break;
242248 }
@@ -284,9 +290,9 @@ static void I486OP(group0F01_16)(i386_state *cpustate) // Opcode 0x0f 01
284290 }
285291 case 6: /* LMSW */
286292 {
287- UINT16 b;
288293 if(PROTECTED_MODE && cpustate->CPL)
289294 FAULT(FAULT_GP,0)
295+ UINT16 b;
290296 if( modrm >= 0xc0 ) {
291297 b = LOAD_RM16(modrm);
292298 CYCLES(cpustate,CYCLES_LMSW_REG);
@@ -501,6 +507,8 @@ static void I486OP(mov_cr_r32)(i386_state *cpustate) // Opcode 0x0f 22
501507 CYCLES(cpustate,CYCLES_MOV_REG_CR0);
502508 if((oldcr ^ cpustate->cr[cr]) & 0x80010000)
503509 vtlb_flush_dynamic(cpustate->vtlb);
510+// if (PROTECTED_MODE != BIT(data, 0))
511+// debugger_privilege_hook();
504512 break;
505513 case 2: CYCLES(cpustate,CYCLES_MOV_REG_CR2); break;
506514 case 3:
--- a/source/src/vm/mame/emu/cpu/i386/pentops.c
+++ b/source/src/vm/mame/emu/cpu/i386/pentops.c
@@ -59,11 +59,14 @@ static void PENTIUMOP(rdmsr)(i386_state* cpustate) // Opcode 0x0f 32
5959 UINT8 valid_msr = 0;
6060
6161 data = MSR_READ(cpustate,REG32(ECX),&valid_msr);
62- REG32(EDX) = data >> 32;
63- REG32(EAX) = data & 0xffffffff;
6462
6563 if(cpustate->CPL != 0 || valid_msr == 0) // if current privilege level isn't 0 or the register isn't recognized ...
6664 FAULT(FAULT_GP,0) // ... throw a general exception fault
65+ else
66+ {
67+ REG32(EDX) = data >> 32;
68+ REG32(EAX) = data & 0xffffffff;
69+ }
6770
6871 CYCLES(cpustate,CYCLES_RDMSR);
6972 }
--- a/source/src/vm/mame/emu/cpu/i386/readme_takeda.txt
+++ b/source/src/vm/mame/emu/cpu/i386/readme_takeda.txt
@@ -1,5 +1,5 @@
11 Based on MAME 0.152.
2-Fixes in MAME 0.154 to 0.197 are applied.
2+Fixes in MAME 0.154 to 0.204 are applied.
33
44 cycle_table_rm/pm are changed from dynamic array to static array.
55
--- a/source/src/vm/pc6001/memory.cpp
+++ b/source/src/vm/pc6001/memory.cpp
@@ -698,12 +698,12 @@ void MEMORY::event_vline(int v, int clock)
698698 #ifdef _PC6001
699699 if (v < 192) {
700700 d_cpu->write_signal(SIG_CPU_BUSREQ, 1, 1);
701- register_event_by_clock(this, EVENT_HBLANK, (double)CPU_CLOCKS / FRAMES_PER_SEC / LINES_PER_FRAME * 296 / 455, false, NULL);
701+ register_event_by_clock(this, EVENT_HBLANK, (uint64_t)((double)CPU_CLOCKS / FRAMES_PER_SEC / LINES_PER_FRAME * 296 / 455), false, NULL);
702702 }
703703 #else
704704 if (v < (CRTMode1 ? 200 : 192)) {
705705 d_cpu->write_signal(SIG_CPU_BUSREQ, 1, 1);
706- register_event_by_clock(this, EVENT_HBLANK, (double)CPU_CLOCKS / FRAMES_PER_SEC / LINES_PER_FRAME * (CRTMode1 ? 368 : 304) / 456, false, NULL);
706+ register_event_by_clock(this, EVENT_HBLANK, (uint64_t)((double)CPU_CLOCKS / FRAMES_PER_SEC / LINES_PER_FRAME * (CRTMode1 ? 368 : 304) / 456), false, NULL);
707707 }
708708 #endif
709709 }
--- a/source/src/vm/pc6001/psub.cpp
+++ b/source/src/vm/pc6001/psub.cpp
@@ -632,18 +632,18 @@ uint8_t Keys7[256][2] =
632632 {0,0x00},{0,0x00},{0,0x00},{0,0x00},{0,0x00},{0,0x00},{0,0x00},{0,0x7f},
633633 };
634634
635-void PSUB::update_keyboard()
635+void PSUB::update_keyboard(int code)
636636 {
637- for (int code=0; code < 256; code++) {
638- if (key_stat[code] & 0x80) {
637+// for (int code=0; code < 256; code++) {
638+// if (key_stat[code] & 0x80) {
639639 if (code == VK_LSHIFT || code == VK_LCONTROL || code == VK_LMENU ||
640- code == VK_RSHIFT || code == VK_RCONTROL || code == VK_RMENU) continue;
641- if (code == VK_SHIFT || code == VK_CONTROL) continue;
642- key_stat[code]=0;
643- if (code == 0x75) {kanaMode = -1 * (kanaMode-1);continue;} // VK_F6
644- if (code == 0x76) {katakana = -1 * (katakana-1);continue;} // VK_F7
645- if (code == 0x77) {kbFlagGraph = -1 * (kbFlagGraph-1);continue;} // VK_F8
646- p6key=code;
640+ code == VK_RSHIFT || code == VK_RCONTROL || code == VK_RMENU) return;
641+ if (code == VK_SHIFT || code == VK_CONTROL) return;
642+// key_stat[code]=0;
643+ if (code == 0x75) {kanaMode = -1 * (kanaMode-1);return;} // VK_F6
644+ if (code == 0x76) {katakana = -1 * (katakana-1);return;} // VK_F7
645+ if (code == 0x77) {kbFlagGraph = -1 * (kbFlagGraph-1);return;} // VK_F8
646+// p6key=code;
647647 uint8_t *Keys;
648648 uint8_t ascii=0;
649649 if (kbFlagGraph) {
@@ -667,9 +667,13 @@ void PSUB::update_keyboard()
667667 if ((kbFlagCtrl == 1) && (code >= 0x41) && (code <= 0x5a)) ascii = code - 0x41 + 1;
668668 /* function key */
669669 if (!kanaMode && (ascii>0xef && ascii<0xfa)) kbFlagFunc=1;
670+ /* send key code and raise irq */
671+ if (!ascii) return;
672+ p6key = ascii;
670673 d_pio->write_signal(SIG_I8255_PORT_A, ascii, 0xff);
671- }
672- }
674+ d_timer->write_signal(SIG_TIMER_IRQ_SUB_CPU, 1, 1);
675+// }
676+// }
673677 }
674678
675679 bool PSUB::play_tape(const _TCHAR* file_path)
@@ -876,8 +880,8 @@ void PSUB::initialize()
876880 fio = new FILEIO();
877881 play = rec = false;
878882
879-// key_stat = emu->get_key_buffer();
880- memset(key_stat, 0, sizeof(key_stat));
883+ key_stat = emu->get_key_buffer();
884+// memset(key_stat, 0, sizeof(key_stat));
881885
882886 kbFlagCtrl=0;
883887 kbFlagGraph=0;
@@ -928,8 +932,8 @@ void PSUB::event_frame()
928932 if (key_stat[VK_UP]) stick0 |= STICK0_UP;
929933 if (key_stat[VK_F9]) stick0 |= STICK0_STOP;
930934 if (key_stat[VK_SHIFT]) stick0 |= STICK0_SHIFT;
931- update_keyboard();
932- if (p6key) d_timer->write_signal(SIG_TIMER_IRQ_SUB_CPU, 1, 1);
935+// update_keyboard();
936+// if (p6key) d_timer->write_signal(SIG_TIMER_IRQ_SUB_CPU, 1, 1);
933937
934938 if(CasSkipFlag != 0) {
935939 request_skip_frames();
@@ -1053,12 +1057,13 @@ uint32_t PSUB::read_io8(uint32_t addr)
10531057
10541058 void PSUB::key_down(int code)
10551059 {
1056- key_stat[code] = 0x80;
1060+// key_stat[code] = 0x80;
1061+ update_keyboard(code);
10571062 }
10581063
10591064 void PSUB::key_up(int code)
10601065 {
1061- key_stat[code] = 0x00;
1066+// key_stat[code] = 0x00;
10621067 }
10631068
10641069 #define STATE_VERSION 1
--- a/source/src/vm/pc6001/psub.h
+++ b/source/src/vm/pc6001/psub.h
@@ -40,8 +40,8 @@ private:
4040 int CasLength;
4141 int CasSkipFlag;
4242
43-// const uint8_t* key_stat;
44- uint8_t key_stat[256];
43+ const uint8_t* key_stat;
44+// uint8_t key_stat[256];
4545 int kbFlagFunc;
4646 int kbFlagGraph;
4747 int kbFlagCtrl;
@@ -51,7 +51,7 @@ private:
5151 int stick0;
5252 int StrigIntFlag;
5353 int StrigEventID;
54- void update_keyboard();
54+ void update_keyboard(int code);
5555
5656 public:
5757 PSUB(VM_TEMPLATE* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
--- a/source/src/vm/pc8801/pc88.cpp
+++ b/source/src/vm/pc8801/pc88.cpp
@@ -18,7 +18,7 @@
1818 #include "../z80.h"
1919
2020 #ifdef SUPPORT_PC88_CDROM
21-//#include "../scsi_cdrom.h"
21+#include "../scsi_cdrom.h"
2222 #include "../scsi_host.h"
2323 #endif
2424
@@ -31,6 +31,10 @@
3131 #define EVENT_CMT_SEND 2
3232 #define EVENT_CMT_DCD 3
3333 #define EVENT_BEEP 4
34+#ifdef SUPPORT_PC88_CDROM
35+#define EVENT_FADE_IN 5
36+#define EVENT_FADE_OUT 6
37+#endif
3438
3539 #define IRQ_USART 0
3640 #define IRQ_VRTC 1
@@ -292,7 +296,7 @@ void PC88::initialize()
292296 }
293297 #endif
294298 #ifdef SUPPORT_PC88_CDROM
295- if(config.boot_mode != MODE_PC88_N) {
299+ if(config.boot_mode == MODE_PC88_V2) {
296300 if(fio->Fopen(create_local_path(_T("CDBIOS.ROM")), FILEIO_READ_BINARY)) {
297301 fio->Fread(cdbios, 0x10000, 1);
298302 fio->Fclose();
@@ -380,6 +384,9 @@ void PC88::initialize()
380384 // hack to update config.scan_line at first
381385 hireso = !(config.monitor_type == 0);
382386 #endif
387+#ifdef SUPPORT_PC88_CDROM
388+ cdda_register_id = -1;
389+#endif
383390 }
384391
385392 void PC88::release()
@@ -410,7 +417,11 @@ void PC88::reset()
410417 }
411418 // port[0x70] = 0x80; // XM8 version 1.10
412419 port[0x71] = port[0xf1] = 0xff;
413-
420+#if defined(SUPPORT_PC88_CDROM)
421+ if (cdbios_loaded) {
422+ port[0x99] = 0x10;
423+ }
424+#endif
414425 memset(alu_reg, 0, sizeof(alu_reg));
415426 gvram_plane = gvram_sel = 0;
416427
@@ -423,8 +434,9 @@ void PC88::reset()
423434 }
424435 SET_BANK(0x8000, 0xffff, ram + 0x8000, ram + 0x8000);
425436 #else
426- SET_BANK(0x0000, 0x7fff, ram, n88rom);
437+// SET_BANK(0x0000, 0x7fff, ram, n88rom);
427438 SET_BANK(0x8000, 0xefff, ram + 0x8000, ram + 0x8000);
439+ update_low_memmap();
428440 update_tvram_memmap(); // XM8 version 1.10
429441 #endif
430442
@@ -506,6 +518,14 @@ void PC88::reset()
506518 write_io8(2, 0);
507519 write_io8(3, 0);
508520 #endif
521+#ifdef SUPPORT_PC88_CDROM
522+ if(cdda_register_id != -1) {
523+ cancel_event(this, cdda_register_id);
524+ cdda_register_id = -1;
525+ }
526+ cdda_volume = 100.0;
527+ d_scsi_cdrom->set_volume((int)cdda_volume);
528+#endif
509529 #ifdef NIPPY_PATCH
510530 // dirty patch for NIPPY
511531 nippy_patch = false;
@@ -653,7 +673,7 @@ void PC88::write_io8(uint32_t addr, uint32_t data)
653673 {
654674 addr &= 0xff;
655675 #ifdef _IO_DEBUG_LOG
656- this->out_debug_log(_T("%6x\tOUT8\t%02x,%02x\n"), d_cpu->get_pc(), addr, data);
676+ this->out_debug_log(_T("%06x\tOUT8\t%02x,%02x\n"), d_cpu->get_pc(), addr, data);
657677 #endif
658678 #ifdef NIPPY_PATCH
659679 // dirty patch for NIPPY
@@ -982,7 +1002,7 @@ void PC88::write_io8(uint32_t addr, uint32_t data)
9821002 break;
9831003 #else
9841004 case 0x71:
985- if(mod) {
1005+ if(mod & 0x01) {
9861006 update_low_memmap();
9871007 }
9881008 break;
@@ -1021,6 +1041,54 @@ void PC88::write_io8(uint32_t addr, uint32_t data)
10211041 d_scsi_host->write_signal(SIG_SCSI_RST, data, 0x80);
10221042 }
10231043 break;
1044+ case 0x98:
1045+ if(cdbios_loaded) {
1046+ switch(data & 7) {
1047+ case 0:
1048+ case 1:
1049+ if(cdda_register_id != -1) {
1050+ cancel_event(this, cdda_register_id);
1051+ }
1052+ d_scsi_cdrom->set_volume((int)(cdda_volume = 100.0));
1053+ break;
1054+ case 2:
1055+ case 3:
1056+ if(cdda_register_id != -1) {
1057+ cancel_event(this, cdda_register_id);
1058+ }
1059+ d_scsi_cdrom->set_volume((int)(cdda_volume = 0.0));
1060+ break;
1061+ case 4:
1062+ if(cdda_register_id != -1) {
1063+ cancel_event(this, cdda_register_id);
1064+ }
1065+ register_event(this, EVENT_FADE_IN, 100, true, &cdda_register_id); // 100ms
1066+ d_scsi_cdrom->set_volume((int)(cdda_volume = 0.0));
1067+ break;
1068+ case 5:
1069+ if(cdda_register_id != -1) {
1070+ cancel_event(this, cdda_register_id);
1071+ }
1072+ register_event(this, EVENT_FADE_IN, 1500, true, &cdda_register_id); // 1500ms
1073+ d_scsi_cdrom->set_volume((int)(cdda_volume = 0.0));
1074+ break;
1075+ case 6:
1076+ if(cdda_register_id != -1) {
1077+ cancel_event(this, cdda_register_id);
1078+ }
1079+ register_event(this, EVENT_FADE_OUT, 100, true, &cdda_register_id); // 100ms
1080+ d_scsi_cdrom->set_volume((int)(cdda_volume = 100.0));
1081+ break;
1082+ case 7:
1083+ if(cdda_register_id != -1) {
1084+ cancel_event(this, cdda_register_id);
1085+ }
1086+ register_event(this, EVENT_FADE_OUT, 5000, true, &cdda_register_id); // 5000ms
1087+ d_scsi_cdrom->set_volume((int)(cdda_volume = 100.0));
1088+ break;
1089+ }
1090+ }
1091+ break;
10241092 case 0x99:
10251093 if(cdbios_loaded && (mod & 0x10)) {
10261094 update_low_memmap();
@@ -1056,8 +1124,14 @@ void PC88::write_io8(uint32_t addr, uint32_t data)
10561124 }
10571125 break;
10581126 case 0xe3:
1127+#ifdef PC88_IODATA_EXRAM
10591128 if(mod) {
1060- update_low_memmap();
1129+#else
1130+ if(mod & 0x0f) {
1131+#endif
1132+ if(PortE2_RDEN || PortE2_WREN) {
1133+ update_low_memmap();
1134+ }
10611135 }
10621136 break;
10631137 #endif
@@ -1261,9 +1335,9 @@ uint32_t PC88::read_io8_debug(uint32_t addr)
12611335 val &= ~(0x80 | 0x20 | 0x10 | 0x08);
12621336 val |= (port[0x9f] & 0x01); // correct ???
12631337 }
1264-#ifdef _SCSI_DEBUG_LOG
1265- this->out_debug_log(_T("[SCSI_PC88] Status = %02X\n"), val);
1266-#endif
1338+ #ifdef _SCSI_DEBUG_LOG
1339+ this->out_debug_log(_T("[SCSI_PC88] Status = %02X\n"), val);
1340+ #endif
12671341 return val;
12681342 }
12691343 break;
@@ -1275,9 +1349,14 @@ uint32_t PC88::read_io8_debug(uint32_t addr)
12751349 case 0x92:
12761350 case 0x93:
12771351 case 0x96:
1352+ if(cdbios_loaded) {
1353+ return 0x00;
1354+ }
1355+ break;
12781356 case 0x99:
12791357 if(cdbios_loaded) {
1280- return 0;
1358+// return 0xcd; // PC-8801MC
1359+ return 0x00;
12811360 }
12821361 break;
12831362 case 0x98:
@@ -1379,6 +1458,7 @@ uint32_t PC88::read_io8_debug(uint32_t addr)
13791458
13801459 uint32_t PC88::read_dma_data8(uint32_t addr)
13811460 {
1461+ // from ram
13821462 #if defined(_PC8001SR)
13831463 return ram[addr & 0xffff];
13841464 #else
@@ -1390,6 +1470,12 @@ uint32_t PC88::read_dma_data8(uint32_t addr)
13901470 #endif
13911471 }
13921472
1473+void PC88::write_dma_data8(uint32_t addr, uint32_t data)
1474+{
1475+ // to ram
1476+ ram[addr & 0xffff] = data;
1477+}
1478+
13931479 void PC88::write_dma_io8(uint32_t addr, uint32_t data)
13941480 {
13951481 // to crtc
@@ -1797,6 +1883,24 @@ void PC88::event_callback(int event_id, int err)
17971883 beep_signal = !beep_signal;
17981884 d_pcm->write_signal(SIG_PCM1BIT_SIGNAL, ((beep_on && beep_signal) || sing_signal) ? 1 : 0, 1);
17991885 break;
1886+#ifdef SUPPORT_PC88_CDROM
1887+ case EVENT_FADE_IN:
1888+ if((cdda_volume += 0.1) >= 100.0) {
1889+ cancel_event(this, cdda_register_id);
1890+ cdda_register_id = -1;
1891+ cdda_volume = 100.0;
1892+ }
1893+ d_scsi_cdrom->set_volume((int)cdda_volume);
1894+ break;
1895+ case EVENT_FADE_OUT:
1896+ if((cdda_volume -= 0.1) <= 0) {
1897+ cancel_event(this, cdda_register_id);
1898+ cdda_register_id = -1;
1899+ cdda_volume = 0.0;
1900+ }
1901+ d_scsi_cdrom->set_volume((int)cdda_volume);
1902+ break;
1903+#endif
18001904 }
18011905 }
18021906
@@ -2103,38 +2207,8 @@ bool PC88::check_data_carrier()
21032207
21042208 void PC88::draw_screen()
21052209 {
2106- // from ePC-8801MA改
2107- uint8_t ct = 0;
2108-
2109- if(crtc.status & 0x88) {
2110- // dma underrun
2111- crtc.status &= ~0x80;
2112- ct = crtc.reverse ? 3 : 2;
2113- memset(crtc.attrib.expand, ct, 200 * 80);
2114-#if 0
2115- ct = 0;
2116- memset(crtc.text.expand, 0, 200 * 80);
2117-#endif
2118- }
2119- // for Advanced Fantasian Opening (20line) (XM8 version 1.00)
2120- if(!(crtc.status & 0x10) || Port53_TEXTDS) {
2121-// if(!(crtc.status & 0x10) || (crtc.status & 8) || Port53_TEXTDS) {
2122- ct = 2;
2123- }
2124- if(ct) {
2125- memset(crtc.text.expand, 0, 200 * 80);
2126- for(int y = 0; y < 200; y++) {
2127- for(int x = 0; x < 80; x++) {
2128- crtc.attrib.expand[y][x] &= 0xe0;
2129- crtc.attrib.expand[y][x] |= ct;
2130- }
2131- }
2132-// memset(crtc.attrib.expand, 2, 200 * 80);
2133- }
2134-
2135- // for Xak2 opening
2136- memset(text, 8, sizeof(text));
2137- memset(graph, 0, sizeof(graph));
2210+ // render text screen
2211+ draw_text();
21382212
21392213 // render graph screen
21402214 bool disp_color_graph = true;
@@ -2146,8 +2220,10 @@ void PC88::draw_screen()
21462220 } else if(Port31_V1_MONO) {
21472221 draw_640x200_mono_graph();
21482222 } else {
2223+ if(hireso) {
2224+ draw_scanline_black = false;
2225+ }
21492226 draw_640x200_attrib_graph();
2150- draw_scanline_black = false;
21512227 }
21522228 emu->set_vm_screen_lines(200);
21532229 } else {
@@ -2164,7 +2240,9 @@ void PC88::draw_screen()
21642240 } else {
21652241 draw_640x200_attrib_graph();
21662242 }
2167- draw_scanline_black = false;
2243+ if(hireso) {
2244+ draw_scanline_black = false;
2245+ }
21682246 emu->set_vm_screen_lines(200);
21692247 }
21702248 }
@@ -2173,21 +2251,22 @@ void PC88::draw_screen()
21732251 disp_color_graph = draw_640x200_color_graph();
21742252 emu->set_vm_screen_lines(200);
21752253 } else if(!Port31_400LINE) {
2254+ if(hireso) {
2255+ draw_scanline_black = false;
2256+ }
21762257 draw_640x200_attrib_graph();
21772258 // draw_640x200_mono_graph();
2178- draw_scanline_black = false;
21792259 emu->set_vm_screen_lines(200);
21802260 } else {
2261+ if(hireso) {
2262+ draw_scanline_black = false;
2263+ }
21812264 draw_640x400_attrib_graph();
21822265 // draw_640x400_mono_graph();
2183- draw_scanline_black = false;
21842266 emu->set_vm_screen_lines(400);
21852267 }
21862268 #endif
21872269
2188- // render text screen
2189- draw_text();
2190-
21912270 // create palette for each scanline
21922271 #if !defined(_PC8001SR)
21932272 int disp_line = crtc.height * crtc.char_height;
@@ -2283,7 +2362,7 @@ void PC88::draw_screen()
22832362 if(!Port31_HCOLOR && Port31_400LINE) {
22842363 for(int y = 0; y < 400; y++) {
22852364 scrntype_t* dest = emu->get_screen_buffer(y);
2286- uint8_t* src_t = text[y];
2365+ uint8_t* src_t = text[y >> 1];
22872366 uint8_t* src_g = graph[y];
22882367 scrntype_t* pal_t;
22892368 scrntype_t* pal_g;
@@ -2310,7 +2389,7 @@ void PC88::draw_screen()
23102389 {
23112390 for(int y = 0; y < 400; y++) {
23122391 scrntype_t* dest = emu->get_screen_buffer(y);
2313- uint8_t* src_t = text[y];
2392+ uint8_t* src_t = text[y >> 1];
23142393 uint8_t* src_g = graph[y];
23152394 scrntype_t* pal_t;
23162395 scrntype_t* pal_g;
@@ -2351,25 +2430,6 @@ void PC88::draw_screen()
23512430 }
23522431 }
23532432
2354-int PC88::get_char_height()
2355-{
2356- int char_height = crtc.char_height;
2357-
2358- if(!hireso) {
2359- char_height <<= 1;
2360- }
2361-// if(Port31_400LINE || !crtc.skip_line) {
2362-// char_height >>= 1;
2363-// }
2364- if(crtc.skip_line) {
2365- char_height <<= 1;
2366- }
2367- if(char_height == 0) {
2368- char_height = 16;
2369- }
2370- return char_height;
2371-}
2372-
23732433 /*
23742434 attributes:
23752435
@@ -2385,12 +2445,45 @@ int PC88::get_char_height()
23852445
23862446 void PC88::draw_text()
23872447 {
2388- int char_height = get_char_height();
2448+ if(crtc.status & 0x88) {
2449+ // dma underrun
2450+ crtc.status &= ~0x80;
2451+ memset(crtc.text.expand, 0, 200 * 80);
2452+ memset(crtc.attrib.expand, crtc.reverse ? 3 : 2, 200 * 80);
2453+ }
2454+ // for Advanced Fantasian Opening (20line) (XM8 version 1.00)
2455+ if(!(crtc.status & 0x10) || Port53_TEXTDS) {
2456+// if(!(crtc.status & 0x10) || (crtc.status & 8) || Port53_TEXTDS) {
2457+ memset(crtc.text.expand, 0, 200 * 80);
2458+ for(int y = 0; y < 200; y++) {
2459+ for(int x = 0; x < 80; x++) {
2460+ crtc.attrib.expand[y][x] &= 0xe0;
2461+ crtc.attrib.expand[y][x] |= 0x02;
2462+ }
2463+ }
2464+// memset(crtc.attrib.expand, 2, 200 * 80);
2465+ }
2466+
2467+ // for Xak2 opening
2468+ memset(text, 8, sizeof(text));
2469+ memset(text_color, 7, sizeof(text_color));
2470+ memset(text_reverse, 0, sizeof(text_reverse));
2471+
2472+ int char_height = crtc.char_height;
23892473 uint8_t color_mask = Port30_COLOR ? 0 : 7;
23902474 uint8_t code_expand, attr_expand;
23912475
2392- for(int cy = 0, ytop = 0; cy < 64 && ytop < 400; cy++, ytop += char_height) {
2393-// for(int cy = 0, ytop = 0; cy < crtc.height && ytop < 400; cy++, ytop += char_height) {
2476+ if(!hireso) {
2477+ char_height <<= 1;
2478+ }
2479+// if(Port31_400LINE || !crtc.skip_line) {
2480+// char_height >>= 1;
2481+// }
2482+ if(crtc.skip_line) {
2483+ char_height <<= 1;
2484+ }
2485+// for(int cy = 0, ytop = 0; cy < 64 && ytop < 400; cy++, ytop += char_height) {
2486+ for(int cy = 0, ytop = 0; cy < crtc.height && ytop < 400; cy++, ytop += char_height) {
23942487 for(int x = 0, cx = 0; cx < crtc.width; x += 8, cx++) {
23952488 if(Port30_40 && (cx & 1)) {
23962489 // don't update code/attrib
@@ -2399,26 +2492,23 @@ void PC88::draw_text()
23992492 attr_expand = crtc.attrib.expand[cy][cx];
24002493 }
24012494 uint8_t attrib = attr_expand;//crtc.attrib.expand[cy][cx];
2495+// uint8_t color = !(Port30_COLOR && (attrib & 8)) ? 7 : (attrib & 0xe0) ? (attrib >> 5) : 8;
2496+ uint8_t color = (attrib & 0xe0) ? ((attrib >> 5) | color_mask) : 8;
24022497 bool under_line = ((attrib & 8) != 0);
24032498 bool upper_line = ((attrib & 4) != 0);
24042499 bool secret = ((attrib & 2) != 0);
24052500 bool reverse = ((attrib & 1) != 0);
24062501
2407- uint8_t color_fore = (attrib & 0xe0) ? ((attrib >> 5) | color_mask) : 8;
2408- uint8_t color_back = 0;
2409-#if 1
2502+ uint8_t color_tmp = color;
2503+ bool reverse_tmp = reverse;
2504+
24102505 // from ePC-8801MA改
24112506 if(Port31_GRAPH && !Port31_HCOLOR) {
24122507 if(reverse) {
24132508 reverse = false;
2414- color_back = 0;//color_fore & 7;
2415- color_fore = 8;
2416- } else {
2417-// color_back = 8;
2509+ color = 8;
24182510 }
24192511 }
2420-#endif
2421-
24222512 uint8_t code = secret ? 0 : code_expand;//crtc.text.expand[cy][cx];
24232513 #ifdef SUPPORT_PC88_PCG8100
24242514 uint8_t *pattern = ((attrib & 0x10) ? sg_pattern : pcg_pattern) + code * 8;
@@ -2442,57 +2532,19 @@ void PC88::draw_text()
24422532 if(reverse) {
24432533 pat ^= 0xff;
24442534 }
2445- uint8_t *dest0 = &text[y ][x];
2446- uint8_t *dest1 = &text[y + 1][x];
2447-#if 1
2448- // from ePC-8801MA改
2449- uint8_t *src0 = &graph[y ][x];
2450- uint8_t *src1 = &graph[y + 1][x];
2535+ uint8_t *dest = &text[y >> 1][x];
2536+ dest[0] = (pat & 0x80) ? color : 0;
2537+ dest[1] = (pat & 0x40) ? color : 0;
2538+ dest[2] = (pat & 0x20) ? color : 0;
2539+ dest[3] = (pat & 0x10) ? color : 0;
2540+ dest[4] = (pat & 0x08) ? color : 0;
2541+ dest[5] = (pat & 0x04) ? color : 0;
2542+ dest[6] = (pat & 0x02) ? color : 0;
2543+ dest[7] = (pat & 0x01) ? color : 0;
24512544
2452- if(Port31_GRAPH && !Port31_HCOLOR) {
2453- dest0[0] = (pat & 0x80) ? color_fore : src0[0] ? 0 : color_back;
2454- dest0[1] = (pat & 0x40) ? color_fore : src0[1] ? 0 : color_back;
2455- dest0[2] = (pat & 0x20) ? color_fore : src0[2] ? 0 : color_back;
2456- dest0[3] = (pat & 0x10) ? color_fore : src0[3] ? 0 : color_back;
2457- dest0[4] = (pat & 0x08) ? color_fore : src0[4] ? 0 : color_back;
2458- dest0[5] = (pat & 0x04) ? color_fore : src0[5] ? 0 : color_back;
2459- dest0[6] = (pat & 0x02) ? color_fore : src0[6] ? 0 : color_back;
2460- dest0[7] = (pat & 0x01) ? color_fore : src0[7] ? 0 : color_back;
2461-/*
2462- if(Port31_400LINE) {
2463-*/
2464- dest1[0] = (pat & 0x80) ? color_fore : src1[0] ? 0 : color_back;
2465- dest1[1] = (pat & 0x40) ? color_fore : src1[1] ? 0 : color_back;
2466- dest1[2] = (pat & 0x20) ? color_fore : src1[2] ? 0 : color_back;
2467- dest1[3] = (pat & 0x10) ? color_fore : src1[3] ? 0 : color_back;
2468- dest1[4] = (pat & 0x08) ? color_fore : src1[4] ? 0 : color_back;
2469- dest1[5] = (pat & 0x04) ? color_fore : src1[5] ? 0 : color_back;
2470- dest1[6] = (pat & 0x02) ? color_fore : src1[6] ? 0 : color_back;
2471- dest1[7] = (pat & 0x01) ? color_fore : src1[7] ? 0 : color_back;
2472-/*
2473- } else {
2474- dest1[0] = (pat & 0x80) ? color_fore : color_back;
2475- dest1[1] = (pat & 0x40) ? color_fore : color_back;
2476- dest1[2] = (pat & 0x20) ? color_fore : color_back;
2477- dest1[3] = (pat & 0x10) ? color_fore : color_back;
2478- dest1[4] = (pat & 0x08) ? color_fore : color_back;
2479- dest1[5] = (pat & 0x04) ? color_fore : color_back;
2480- dest1[6] = (pat & 0x02) ? color_fore : color_back;
2481- dest1[7] = (pat & 0x01) ? color_fore : color_back;
2482- }
2483-*/
2484- } else
2485-#endif
2486- {
2487- dest0[0] = dest1[0] = (pat & 0x80) ? color_fore : 0;
2488- dest0[1] = dest1[1] = (pat & 0x40) ? color_fore : 0;
2489- dest0[2] = dest1[2] = (pat & 0x20) ? color_fore : 0;
2490- dest0[3] = dest1[3] = (pat & 0x10) ? color_fore : 0;
2491- dest0[4] = dest1[4] = (pat & 0x08) ? color_fore : 0;
2492- dest0[5] = dest1[5] = (pat & 0x04) ? color_fore : 0;
2493- dest0[6] = dest1[6] = (pat & 0x02) ? color_fore : 0;
2494- dest0[7] = dest1[7] = (pat & 0x01) ? color_fore : 0;
2495- }
2545+ // store text attributes for monocolor graph screen
2546+ text_color[y >> 1][cx] = color_tmp;
2547+ text_reverse[y >> 1][cx] = reverse_tmp;
24962548 }
24972549 }
24982550 }
@@ -2607,26 +2659,20 @@ void PC88::draw_320x200_attrib_graph()
26072659 uint8_t *gvram_r1 = Port53_G4DS ? gvram_null : (gvram + 0x6000);
26082660 uint8_t *gvram_g1 = Port53_G5DS ? gvram_null : (gvram + 0xa000);
26092661
2610- int char_height = get_char_height();
2611- uint8_t color_mask = Port30_COLOR ? 0 : 7;
2612-
26132662 if(Port30_40) {
26142663 for(int y = 0, addr = 0; y < 400; y += 2) {
2615- int cy = y / char_height;
26162664 for(int x = 0, cx = 0; x < 640; x += 16, cx += 2) {
2665+ uint8_t color = text_color[y >> 1][cx];
26172666 uint8_t brg0 = gvram_b0[addr] | gvram_r0[addr] | gvram_g0[addr] |
26182667 gvram_b1[addr] | gvram_r1[addr] | gvram_g1[addr];
2619- uint8_t brg1 = config.scan_line ? 0 : brg0;
2620- uint8_t attrib = crtc.attrib.expand[cy][cx];
2621- uint8_t color = (attrib >> 5) | color_mask;
2622- bool reverse = ((attrib & 1) != 0);
2623- if(reverse) {
2668+ uint8_t brg1 = 0;
2669+ if(text_reverse[y >> 1][cx]) {
26242670 brg0 ^= 0xff;
26252671 brg1 ^= 0xff;
26262672 }
26272673 addr++;
2628- uint8_t *dest1 = &graph[y ][x];
2629- uint8_t *dest0 = &graph[y + 1][x];
2674+ uint8_t *dest0 = &graph[y ][x];
2675+ uint8_t *dest1 = &graph[y + 1][x];
26302676 dest0[ 0] = dest0[ 1] = (brg0 & 0x80) ? color : 0;
26312677 dest0[ 2] = dest0[ 3] = (brg0 & 0x40) ? color : 0;
26322678 dest0[ 4] = dest0[ 5] = (brg0 & 0x20) ? color : 0;
@@ -2635,6 +2681,7 @@ void PC88::draw_320x200_attrib_graph()
26352681 dest0[10] = dest0[11] = (brg0 & 0x04) ? color : 0;
26362682 dest0[12] = dest0[13] = (brg0 & 0x02) ? color : 0;
26372683 dest0[14] = dest0[15] = (brg0 & 0x01) ? color : 0;
2684+ if(!hireso) continue;
26382685 dest1[ 0] = dest1[ 1] = (brg1 & 0x80) ? color : 0;
26392686 dest1[ 2] = dest1[ 3] = (brg1 & 0x40) ? color : 0;
26402687 dest1[ 4] = dest1[ 5] = (brg1 & 0x20) ? color : 0;
@@ -2644,31 +2691,33 @@ void PC88::draw_320x200_attrib_graph()
26442691 dest1[12] = dest1[13] = (brg1 & 0x02) ? color : 0;
26452692 dest1[14] = dest1[15] = (brg1 & 0x01) ? color : 0;
26462693 }
2694+ if(!hireso) {
2695+ if(config.scan_line) {
2696+ memset(graph[y + 1], 0, 640);
2697+ } else {
2698+ memcpy(graph[y + 1], graph[y], 640);
2699+ }
2700+ }
26472701 }
26482702 } else {
26492703 for(int y = 0, addr = 0; y < 400; y += 2) {
2650- int cy = y / char_height;
26512704 for(int x = 0, cx = 0; x < 640; x += 16, cx += 2) {
2705+ uint8_t color_l = text_color[y >> 1][cx + 0];
2706+ uint8_t color_r = text_color[y >> 1][cx + 1];
26522707 uint8_t brg0 = gvram_b0[addr] | gvram_r0[addr] | gvram_g0[addr] |
26532708 gvram_b1[addr] | gvram_r1[addr] | gvram_g1[addr];
2654- uint8_t brg1 = config.scan_line ? 0 : brg0;
2655- uint8_t attrib_l = crtc.attrib.expand[cy][cx + 0];
2656- uint8_t color_l = (attrib_l >> 5) | color_mask;
2657- bool reverse_l = ((attrib_l & 1) != 0);
2658- uint8_t attrib_r = crtc.attrib.expand[cy][cx + 1];
2659- uint8_t color_r = (attrib_r >> 5) | color_mask;
2660- bool reverse_r = ((attrib_r & 1) != 0);
2661- if(reverse_l) {
2709+ uint8_t brg1 = 0;
2710+ if(text_reverse[y >> 1][cx + 0]) {
26622711 brg0 ^= 0xf0;
26632712 brg0 ^= 0xf0;
26642713 }
2665- if(reverse_r) {
2714+ if(text_reverse[y >> 1][cx + 1]) {
26662715 brg1 ^= 0x0f;
26672716 brg1 ^= 0x0f;
26682717 }
26692718 addr++;
2670- uint8_t *dest1 = &graph[y ][x];
2671- uint8_t *dest0 = &graph[y + 1][x];
2719+ uint8_t *dest0 = &graph[y ][x];
2720+ uint8_t *dest1 = &graph[y + 1][x];
26722721 dest0[ 0] = dest0[ 1] = (brg0 & 0x80) ? color_l : 0;
26732722 dest0[ 2] = dest0[ 3] = (brg0 & 0x40) ? color_l : 0;
26742723 dest0[ 4] = dest0[ 5] = (brg0 & 0x20) ? color_l : 0;
@@ -2677,6 +2726,7 @@ void PC88::draw_320x200_attrib_graph()
26772726 dest0[10] = dest0[11] = (brg0 & 0x04) ? color_r : 0;
26782727 dest0[12] = dest0[13] = (brg0 & 0x02) ? color_r : 0;
26792728 dest0[14] = dest0[15] = (brg0 & 0x01) ? color_r : 0;
2729+ if(!hireso) continue;
26802730 dest1[ 0] = dest1[ 1] = (brg1 & 0x80) ? color_l : 0;
26812731 dest1[ 2] = dest1[ 3] = (brg1 & 0x40) ? color_l : 0;
26822732 dest1[ 4] = dest1[ 5] = (brg1 & 0x20) ? color_l : 0;
@@ -2686,6 +2736,13 @@ void PC88::draw_320x200_attrib_graph()
26862736 dest1[12] = dest1[13] = (brg1 & 0x02) ? color_r : 0;
26872737 dest1[14] = dest1[15] = (brg1 & 0x01) ? color_r : 0;
26882738 }
2739+ if(!hireso) {
2740+ if(config.scan_line) {
2741+ memset(graph[y + 1], 0, 640);
2742+ } else {
2743+ memcpy(graph[y + 1], graph[y], 640);
2744+ }
2745+ }
26892746 }
26902747 }
26912748 }
@@ -2772,23 +2829,12 @@ void PC88::draw_640x200_attrib_graph()
27722829 uint8_t *gvram_r = Port53_G1DS ? gvram_null : (gvram + 0x4000);
27732830 uint8_t *gvram_g = Port53_G2DS ? gvram_null : (gvram + 0x8000);
27742831
2775- int char_height = get_char_height();
2776- uint8_t color_mask = Port30_COLOR ? 0 : 7, color;
2777- bool reverse;
2778-
27792832 for(int y = 0, addr = 0; y < 400; y += 2) {
2780- int cy = y / char_height;
27812833 for(int x = 0, cx = 0; x < 640; x += 8, cx++) {
2834+ uint8_t color = text_color[y >> 1][cx];
27822835 uint8_t brg0 = gvram_b[addr] | gvram_r[addr] | gvram_g[addr];
2783- uint8_t brg1 = config.scan_line ? 0 : brg0;
2784- if(Port30_40 && (cx & 1)) {
2785- // don't update color
2786- } else {
2787- uint8_t attrib = crtc.attrib.expand[cy][cx];
2788- color = (attrib >> 5) | color_mask;
2789- reverse = ((attrib & 1) != 0);
2790- }
2791- if(reverse) {
2836+ uint8_t brg1 = 0;
2837+ if(text_reverse[y >> 1][cx]) {
27922838 brg0 ^= 0xff;
27932839 brg1 ^= 0xff;
27942840 }
@@ -2803,6 +2849,7 @@ void PC88::draw_640x200_attrib_graph()
28032849 dest0[5] = (brg0 & 0x04) ? color : 0;
28042850 dest0[6] = (brg0 & 0x02) ? color : 0;
28052851 dest0[7] = (brg0 & 0x01) ? color : 0;
2852+ if(!hireso) continue;
28062853 dest1[0] = (brg1 & 0x80) ? color : 0;
28072854 dest1[1] = (brg1 & 0x40) ? color : 0;
28082855 dest1[2] = (brg1 & 0x20) ? color : 0;
@@ -2812,6 +2859,13 @@ void PC88::draw_640x200_attrib_graph()
28122859 dest1[6] = (brg1 & 0x02) ? color : 0;
28132860 dest1[7] = (brg1 & 0x01) ? color : 0;
28142861 }
2862+ if(!hireso) {
2863+ if(config.scan_line) {
2864+ memset(graph[y + 1], 0, 640);
2865+ } else {
2866+ memcpy(graph[y + 1], graph[y], 640);
2867+ }
2868+ }
28152869 }
28162870 }
28172871
@@ -2866,22 +2920,11 @@ void PC88::draw_640x400_attrib_graph()
28662920 uint8_t *gvram_b = Port53_G0DS ? gvram_null : (gvram + 0x0000);
28672921 uint8_t *gvram_r = Port53_G1DS ? gvram_null : (gvram + 0x4000);
28682922
2869- int char_height = get_char_height();
2870- uint8_t color_mask = Port30_COLOR ? 0 : 7, color;
2871- bool reverse;
2872-
28732923 for(int y = 0, addr = 0; y < 200; y++) {
2874- int cy = y / char_height;
28752924 for(int x = 0, cx = 0; x < 640; x += 8, cx++) {
2925+ uint8_t color = text_color[y >> 1][cx];
28762926 uint8_t b = gvram_b[addr];
2877- if(Port30_40 && (cx & 1)) {
2878- // don't update color
2879- } else {
2880- uint8_t attrib = crtc.attrib.expand[cy][cx];
2881- color = (attrib >> 5) | color_mask;
2882- reverse = ((attrib & 1) != 0);
2883- }
2884- if(reverse) {
2927+ if(text_reverse[y >> 1][cx]) {
28852928 b ^= 0xff;
28862929 }
28872930 addr++;
@@ -2897,17 +2940,10 @@ void PC88::draw_640x400_attrib_graph()
28972940 }
28982941 }
28992942 for(int y = 200, addr = 0; y < 400; y++) {
2900- int cy = y / char_height;
29012943 for(int x = 0, cx = 0; x < 640; x += 8, cx++) {
2944+ uint8_t color = text_color[y >> 1][cx];
29022945 uint8_t r = gvram_r[addr];
2903- if(Port30_40 && (cx & 1)) {
2904- // don't update color
2905- } else {
2906- uint8_t attrib = crtc.attrib.expand[cy][cx];
2907- color = (attrib >> 5) | color_mask;
2908- reverse = ((attrib & 1) != 0);
2909- }
2910- if(reverse) {
2946+ if(text_reverse[y >> 1][cx]) {
29112947 r ^= 0xff;
29122948 }
29132949 addr++;
@@ -3229,9 +3265,9 @@ underrun:
32293265 if(exitline != -1) {
32303266 for(int cy = exitline; cy < 200; cy++) {
32313267 memset(&text.expand[cy][0], 0, width);
3232-#if 0
3268+#if 1
32333269 // SORCERIAN Music Library ver-2.1
3234- memset(&attrib.expand[cy][0], 0xe0, width);
3270+ memset(&attrib.expand[cy][0], 0xe0, width); // color=7
32353271 #else
32363272 // from ePC-8801MA改
32373273 memset(&attrib.expand[cy][0], 0x00, width);
@@ -3279,8 +3315,10 @@ void pc88_dmac_t::write_io8(uint32_t addr, uint32_t data)
32793315 } else {
32803316 if((mode & 0x80) && c == 2) {
32813317 ch[3].addr.b.h = data;
3318+ ch[3].addr.b.h2 = ch[3].addr.b.h3 = 0;
32823319 }
32833320 ch[c].addr.b.h = data;
3321+ ch[c].addr.b.h2 = ch[c].addr.b.h3 = 0;
32843322 }
32853323 high_low = !high_low;
32863324 break;
@@ -3296,9 +3334,11 @@ void pc88_dmac_t::write_io8(uint32_t addr, uint32_t data)
32963334 } else {
32973335 if((mode & 0x80) && c == 2) {
32983336 ch[3].count.b.h = data & 0x3f;
3337+ ch[3].count.b.h2 = ch[3].count.b.h3 = 0;
32993338 ch[3].mode = data & 0xc0;
33003339 }
33013340 ch[c].count.b.h = data & 0x3f;
3341+ ch[c].count.b.h2 = ch[c].count.b.h3 = 0;
33023342 ch[c].mode = data & 0xc0;
33033343 }
33043344 high_low = !high_low;
@@ -3350,11 +3390,6 @@ uint32_t pc88_dmac_t::read_io8(uint32_t addr)
33503390 void pc88_dmac_t::start(int c)
33513391 {
33523392 if(mode & (1 << c)) {
3353-#ifdef _SCSI_DEBUG_LOG
3354- if(c == 1) {
3355- mem->out_debug_log(_T("[SCSI_PC88] DMA Start\n"));
3356- }
3357-#endif
33583393 status &= ~(1 << c);
33593394 ch[c].running = true;
33603395 } else {
@@ -3367,19 +3402,11 @@ void pc88_dmac_t::run(int c, int nbytes)
33673402 if(ch[c].running) {
33683403 while(nbytes > 0 && ch[c].count.sd >= 0) {
33693404 if(ch[c].mode == 0x80) {
3370-#ifdef _SCSI_DEBUG_LOG
3371- if(c == 1) {
3372- mem->out_debug_log(_T("[SCSI_PC88] DMA Transfer Memory->I/O Addr=%04X\n"), ch[c].addr.w.l);
3373- }
3374-#endif
33753405 ch[c].io->write_dma_io8(0, mem->read_dma_data8(ch[c].addr.w.l));
33763406 } else if(ch[c].mode == 0x40) {
3377-#ifdef _SCSI_DEBUG_LOG
3378- if(c == 1) {
3379- mem->out_debug_log(_T("[SCSI_PC88] DMA Trasfer I/O->Memory Addr=%04X\n"), ch[c].addr.w.l);
3380- }
3381-#endif
33823407 mem->write_dma_data8(ch[c].addr.w.l, ch[c].io->read_dma_io8(0));
3408+ } else if(ch[c].mode == 0x00) {
3409+ ch[c].io->read_dma_io8(0); // verify
33833410 }
33843411 ch[c].addr.sd++;
33853412 ch[c].count.sd--;
@@ -3395,11 +3422,13 @@ void pc88_dmac_t::finish(int c)
33953422 {
33963423 if(ch[c].running) {
33973424 while(ch[c].count.sd >= 0) {
3398-// if(ch[c].mode == 0x80) {
3425+ if(ch[c].mode == 0x80) {
33993426 ch[c].io->write_dma_io8(0, mem->read_dma_data8(ch[c].addr.w.l));
3400-// } else if(ch[c].mode == 0x40) {
3401-// mem->write_dma_data8(ch[c].addr.w.l, ch[c].io->read_dma_io8(0));
3402-// }
3427+ } else if(ch[c].mode == 0x40) {
3428+ mem->write_dma_data8(ch[c].addr.w.l, ch[c].io->read_dma_io8(0));
3429+ } else if(ch[c].mode == 0x00) {
3430+ ch[c].io->read_dma_io8(0); // verify
3431+ }
34033432 ch[c].addr.sd++;
34043433 ch[c].count.sd--;
34053434 }
@@ -3412,15 +3441,10 @@ void pc88_dmac_t::finish(int c)
34123441 }
34133442 status |= (1 << c);
34143443 ch[c].running = false;
3415-#ifdef _SCSI_DEBUG_LOG
3416- if(c == 1) {
3417- mem->out_debug_log(_T("[SCSI_PC88] DMA Finish\n"));
3418- }
3419-#endif
34203444 }
34213445 }
34223446
3423-#define STATE_VERSION 9
3447+#define STATE_VERSION 10
34243448
34253449 bool PC88::process_state(FILEIO* state_fio, bool loading)
34263450 {
@@ -3578,6 +3602,10 @@ bool PC88::process_state(FILEIO* state_fio, bool loading)
35783602 state_fio->StateValue(pcg_ctrl);
35793603 state_fio->StateArray(pcg_pattern, sizeof(pcg_pattern), 1);
35803604 #endif
3605+#ifdef SUPPORT_PC88_CDROM
3606+ state_fio->StateValue(cdda_register_id);
3607+ state_fio->StateValue(cdda_volume);
3608+#endif
35813609 #ifdef NIPPY_PATCH
35823610 state_fio->StateValue(nippy_patch);
35833611 #endif
--- a/source/src/vm/pc8801/pc88.h
+++ b/source/src/vm/pc8801/pc88.h
@@ -40,7 +40,7 @@ class YM2203;
4040 class Z80;
4141 #ifdef SUPPORT_PC88_CDROM
4242 class SCSI_HOST;
43-//class SCSI_CDROM;
43+class SCSI_CDROM;
4444 #endif
4545
4646 namespace PC88DEV {
@@ -117,7 +117,7 @@ private:
117117 DEVICE *d_pcm, *d_pio, *d_prn, *d_rtc, *d_sio;
118118 #ifdef SUPPORT_PC88_CDROM
119119 SCSI_HOST* d_scsi_host;
120-// SCSI_CDROM* d_scsi_cdrom;
120+ SCSI_CDROM* d_scsi_cdrom;
121121 #endif
122122 #ifdef SUPPORT_PC88_HMB20
123123 DEVICE *d_opm;
@@ -203,7 +203,9 @@ private:
203203 bool hireso;
204204
205205 uint8_t sg_pattern[0x800];
206- uint8_t text[400][640];
206+ uint8_t text[200][640];
207+ uint8_t text_color[200][80];
208+ bool text_reverse[200][80];
207209 uint8_t graph[400][640];
208210
209211 palette_t palette_digital[9];
@@ -215,7 +217,6 @@ private:
215217 scrntype_t palette_vab_pc[0x10000];
216218 #endif
217219
218- int get_char_height();
219220 void draw_text();
220221 #if defined(_PC8001SR)
221222 bool draw_320x200_color_graph();
@@ -281,6 +282,11 @@ private:
281282 uint8_t pcg_pattern[0x800];
282283 #endif
283284
285+#ifdef SUPPORT_PC88_CDROM
286+ int cdda_register_id;
287+ double cdda_volume;
288+#endif
289+
284290 #ifdef NIPPY_PATCH
285291 // dirty patch for NIPPY
286292 bool nippy_patch;
@@ -311,6 +317,7 @@ public:
311317 #endif
312318
313319 uint32_t read_dma_data8(uint32_t addr);
320+ void write_dma_data8(uint32_t addr, uint32_t data);
314321 void write_dma_io8(uint32_t addr, uint32_t data);
315322
316323 void write_signal(int id, uint32_t data, uint32_t mask);
@@ -369,10 +376,10 @@ public:
369376 {
370377 d_scsi_host = device;
371378 }
372-// void set_context_scsi_cdrom(SCSI_CDROM* device)
373-// {
374-// d_scsi_cdrom = device;
375-// }
379+ void set_context_scsi_cdrom(SCSI_CDROM* device)
380+ {
381+ d_scsi_cdrom = device;
382+ }
376383 #endif
377384 #ifdef SUPPORT_PC88_HMB20
378385 void set_context_opm(DEVICE* device)
--- a/source/src/vm/pc8801/pc8801.cpp
+++ b/source/src/vm/pc8801/pc8801.cpp
@@ -220,7 +220,7 @@ VM::VM(EMU* parent_emu) : VM_TEMPLATE(parent_emu)
220220 pc88->set_context_sio(pc88sio);
221221 #ifdef SUPPORT_PC88_CDROM
222222 pc88->set_context_scsi_host(pc88scsi_host);
223-// pc88->set_context_scsi_cdrom(pc88scsi_cdrom);
223+ pc88->set_context_scsi_cdrom(pc88scsi_cdrom);
224224 #endif
225225 #ifdef SUPPORT_PC88_HMB20
226226 pc88->set_context_opm(pc88opm);
--- a/source/src/vm/scsi_cdrom.h
+++ b/source/src/vm/scsi_cdrom.h
@@ -121,6 +121,7 @@ public:
121121 int get_command_length(int value);
122122 void start_command();
123123 bool read_buffer(int length);
124+ bool write_buffer(int length);
124125
125126 // unique functions
126127 void set_context_done(DEVICE* device, int id, uint32_t mask)
Show on old repository browser