OSDN Git Service

[DOC] For release 2017-01-24.
[csp-qt/common_source_project-fm7.git] / source / src / vm / pc80s31k.cpp
1 /*
2         Skelton for retropc emulator
3
4         Author : Takeda.Toshiya
5         Date   : 2011.12.18-
6
7         [ PC-80S31K ]
8 */
9
10 #include "pc80s31k.h"
11 #include "disk.h"
12 #include "upd765a.h"
13
14 //#define _DEBUG_PC80S31K
15
16 #define SET_BANK(s, e, w, r) { \
17         int sb = (s) >> 13, eb = (e) >> 13; \
18         for(int i = sb; i <= eb; i++) { \
19                 if((w) == wdmy) { \
20                         wbank[i] = wdmy; \
21                 } else { \
22                         wbank[i] = (w) + 0x2000 * (i - sb); \
23                 } \
24                 if((r) == rdmy) { \
25                         rbank[i] = rdmy; \
26                 } else { \
27                         rbank[i] = (r) + 0x2000 * (i - sb); \
28                 } \
29         } \
30 }
31
32 void PC80S31K::initialize()
33 {
34         // init memory
35         memset(rom, 0xff, sizeof(rom));
36         memset(ram, 0, sizeof(ram));
37         memset(rdmy, 0xff, sizeof(rdmy));
38         
39         // load rom image
40         FILEIO* fio = new FILEIO();
41         if(fio->Fopen(create_local_path(_T("PC88.ROM")), FILEIO_READ_BINARY)) {
42                 fio->Fseek(0x14000, FILEIO_SEEK_CUR);
43                 fio->Fread(rom, sizeof(rom), 1);
44                 fio->Fclose();
45         } else if(fio->Fopen(create_local_path(_T("DISK.ROM")), FILEIO_READ_BINARY)) {
46                 fio->Fread(rom, sizeof(rom), 1);
47                 fio->Fclose();
48         } else {
49                 // stop cpu
50                 d_cpu->write_signal(SIG_CPU_BUSREQ, 1, 1);
51         }
52         delete fio;
53         
54         // init memory map
55         SET_BANK(0x0000, 0x1fff, wdmy, rom);
56         SET_BANK(0x2000, 0x3fff, wdmy, rdmy);
57         SET_BANK(0x4000, 0x7fff, ram, ram);
58         SET_BANK(0x8000, 0xffff, wdmy, rdmy);
59         
60         // XM8 version 1.20
61         // both drives always set force ready signal
62         d_fdc->write_signal(SIG_UPD765A_FREADY, 1, 1);
63 }
64
65 void PC80S31K::reset()
66 {
67         d_fdc->set_drive_type(0, DRIVE_TYPE_2D);
68         d_fdc->set_drive_type(1, DRIVE_TYPE_2D);
69         
70         // clear output
71         d_pio->write_io8(1, 0);
72         d_pio->write_io8(2, 0);
73 }
74
75 uint32_t PC80S31K::read_data8(uint32_t addr)
76 {
77         addr &= 0xffff;
78         return rbank[addr >> 13][addr & 0x1fff];
79 }
80
81 uint32_t PC80S31K::fetch_op(uint32_t addr, int *wait)
82 {
83         addr &= 0xffff;
84 #ifdef PC80S31K_NO_WAIT
85         // XM8 version 1.20
86         // no access wait (both ROM and RAM)
87         *wait = 0;
88 #else
89         *wait = (addr < 0x2000) ? 1 : 0;
90 #endif
91         return rbank[addr >> 13][addr & 0x1fff];
92 }
93
94 void PC80S31K::write_data8(uint32_t addr, uint32_t data)
95 {
96         addr &= 0xffff;
97         if(addr == 0x7f15 && data == 0x1f && d_cpu->get_pc() < 0x2000) {
98                 // ugly patch to enable both #1 and #2 drives
99                 data = 0x3f;
100         }
101         wbank[addr >> 13][addr & 0x1fff] = data;
102 }
103
104 uint32_t PC80S31K::read_io8(uint32_t addr)
105 {
106         uint32_t val;
107         
108         switch(addr & 0xff) {
109         case 0xf8:
110                 d_fdc->write_signal(SIG_UPD765A_TC, 1, 1);
111                 break;
112         case 0xfa:
113         case 0xfb:
114                 return d_fdc->read_io8(addr & 1);
115         case 0xfc:
116         case 0xfd:
117                 val = d_pio->read_io8(addr & 3);
118 #ifdef _DEBUG_PC80S31K
119                 this->out_debug_log(_T("SUB\tIN RECV(%d)=%2x\n"), addr & 3, val);
120 #endif
121                 return val;
122         case 0xfe:
123                 val = d_pio->read_io8(addr & 3);
124 #ifdef _DEBUG_PC80S31K
125                 {
126                         static uint32_t prev = -1;
127                         if(prev != val) {
128 //                              this->out_debug_log(_T("SUB\tIN DAV=%d,RFD=%d,DAC=%d,ATN=%d\n"), val&1, (val>>1)&1, (val>>2)&1, (val>>3)&1);
129                                 prev = val;
130                         }
131                 }
132 #endif
133                 return val;
134         }
135         return 0xff;
136 }
137
138 void PC80S31K::write_io8(uint32_t addr, uint32_t data)
139 {
140         switch(addr & 0xff) {
141         case 0xf4:
142                 // XM8 version 1.20
143                 // MR/MH/MA/MA2/MA... type ROM only
144                 if(rom[0x7ee] != 0xfe) {
145                         break;
146                 }
147                 for(int drv = 0; drv < 2; drv++) {
148                         uint32_t mode = data >> drv;
149                         if(mode & 1) {
150                                 d_fdc->set_drive_type(drv, DRIVE_TYPE_2HD);
151                         } else if(mode & 4) {
152                                 d_fdc->set_drive_type(drv, DRIVE_TYPE_2DD);
153                         } else {
154                                 d_fdc->set_drive_type(drv, DRIVE_TYPE_2D);
155                         }
156                 }
157                 break;
158         case 0xf7:
159                 // external printer port
160                 break;
161         case 0xf8:
162                 // TODO: we need to update uPD765A to let the motor of each drive on/off
163                 break;
164         case 0xfb:
165                 d_fdc->write_io8(addr & 1, data);
166                 break;
167         case 0xfc:
168         case 0xfd:
169 #ifdef _DEBUG_PC80S31K
170                 this->out_debug_log(_T("SUB\tOUT SEND(%d)=%2x\n"), addr & 3, data);
171 #endif
172                 d_pio->write_io8(addr & 3, data);
173                 break;
174         case 0xfe:
175 //              this->out_debug_log(_T("SUB\tOUT DAV=%d,RFD=%d,DAC=%d,ATN=%d\n"), (data>>4)&1, (data>>5)&1, (data>>6)&1, (data>>7)&1);
176                 d_pio->write_io8(addr & 3, data);
177                 break;
178         case 0xff:
179                 if(!(data & 0x80)) {
180                         int bit = (data >> 1) & 7;
181                         if(bit == 4) {
182 //                              this->out_debug_log(_T("SUB\tOUT DAV=%d\n"), data & 1);
183                         } else if(bit == 5) {
184 //                              this->out_debug_log(_T("SUB\tOUT RFD=%d\n"), data & 1);
185                         } else if(bit == 6) {
186 //                              this->out_debug_log(_T("SUB\tOUT DAC=%d\n"), data & 1);
187                         } else if(bit == 7) {
188 //                              this->out_debug_log(_T("SUB\tOUT ATN=%d\n"), data & 1);
189                         }
190                 }
191                 d_pio->write_io8(addr & 3, data);
192                 break;
193         }
194 }
195
196 uint32_t PC80S31K::get_intr_ack()
197 {
198         return 0;       // NOP
199 }
200
201 #define STATE_VERSION   1
202
203 void PC80S31K::save_state(FILEIO* state_fio)
204 {
205         state_fio->FputUint32(STATE_VERSION);
206         state_fio->FputInt32(this_device_id);
207         
208         state_fio->Fwrite(ram, sizeof(ram), 1);
209 }
210
211 bool PC80S31K::load_state(FILEIO* state_fio)
212 {
213         if(state_fio->FgetUint32() != STATE_VERSION) {
214                 return false;
215         }
216         if(state_fio->FgetInt32() != this_device_id) {
217                 return false;
218         }
219         state_fio->Fread(ram, sizeof(ram), 1);
220         return true;
221 }
222