OSDN Git Service

[VM][STATE] Use namespace {VMNAME} to separate per VMs.
[csp-qt/common_source_project-fm7.git] / source / src / vm / qc10 / memory.cpp
1 /*
2         EPSON QC-10 Emulator 'eQC-10'
3
4         Author : Takeda.Toshiya
5         Date   : 2008.02.15 -
6
7         [ memory ]
8 */
9
10 #include "memory.h"
11 #include "../i8253.h"
12 #include "../pcm1bit.h"
13 #include "../upd765a.h"
14
15 namespace QC10 {
16
17 #define SET_BANK(s, e, w, r) {                  \
18         int sb = (s) >> 11, eb = (e) >> 11; \
19         for(int i = sb; i <= eb; i++) { \
20                 wbank[i] = (w) + 0x800 * (i - sb); \
21                 rbank[i] = (r) + 0x800 * (i - sb); \
22         } \
23 }
24
25 void MEMORY::initialize()
26 {
27         // init memory
28         memset(ram, 0, sizeof(ram));
29         memset(cmos, 0, sizeof(cmos));
30         memset(ipl, 0xff, sizeof(ipl));
31         memset(rdmy, 0xff, sizeof(rdmy));
32         
33         // load rom images
34         FILEIO* fio = new FILEIO();
35         if(fio->Fopen(create_local_path(_T("IPL.ROM")), FILEIO_READ_BINARY)) {
36                 fio->Fread(ipl, sizeof(ipl), 1);
37                 fio->Fclose();
38         }
39         if(fio->Fopen(create_local_path(_T("CMOS.BIN")), FILEIO_READ_BINARY)) {
40                 fio->Fread(cmos, sizeof(cmos), 1);
41                 fio->Fclose();
42         }
43         delete fio;
44         
45         cmos_crc32 = get_crc32(cmos, sizeof(cmos));
46 }
47
48 void MEMORY::release()
49 {
50         if(cmos_crc32 != get_crc32(cmos, sizeof(cmos))) {
51                 FILEIO* fio = new FILEIO();
52                 if(fio->Fopen(create_local_path(_T("CMOS.BIN")), FILEIO_WRITE_BINARY)) {
53                         fio->Fwrite(cmos, sizeof(cmos), 1);
54                         fio->Fclose();
55                 }
56                 delete fio;
57         }
58 }
59
60 void MEMORY::reset()
61 {
62         // init memory map
63         bank = 0x10;
64         psel = csel = 0;
65         update_map();
66         
67         // init pcm
68         pcm_on = pcm_cont = pcm_pit = false;
69         
70         // init fdc/fdd status
71         fdc_irq = motor = false;
72 }
73
74 void MEMORY::write_data8(uint32_t addr, uint32_t data)
75 {
76         addr &= 0xffff;
77         wbank[addr >> 11][addr & 0x7ff] = data;
78 }
79
80 uint32_t MEMORY::read_data8(uint32_t addr)
81 {
82         addr &= 0xffff;
83         return rbank[addr >> 11][addr & 0x7ff];
84 }
85
86 void MEMORY::write_io8(uint32_t addr, uint32_t data)
87 {
88         switch(addr & 0xff) {
89         case 0x18: case 0x19: case 0x1a: case 0x1b:
90                 bank = data;
91                 // timer gate signal
92                 d_pit->write_signal(SIG_I8253_GATE_0, data, 1);
93                 d_pit->write_signal(SIG_I8253_GATE_2, data, 2);
94                 // pcm on
95                 pcm_cont = ((data & 4) != 0);
96                 update_pcm();
97                 break;
98         case 0x1c: case 0x1d: case 0x1e: case 0x1f:
99                 psel = data;
100                 break;
101         case 0x20: case 0x21: case 0x22: case 0x23:
102                 csel = data;
103                 break;
104         }
105         update_map();
106 }
107
108 uint32_t MEMORY::read_io8(uint32_t addr)
109 {
110         switch(addr & 0xff) {
111         case 0x18: case 0x19: case 0x1a: case 0x1b:
112                 return ~config.dipswitch & 0xff;
113         case 0x30: case 0x31: case 0x32: case 0x33:
114                 return (bank & 0xf0) | (d_fdc->is_disk_inserted() ? 8 : 0) | (motor ? 0 : 2) | (fdc_irq ? 1 : 0);
115         }
116         return 0xff;
117 }
118
119 /*
120         0000-DFFF       : RAM * 4banks
121         E000-FFFF       : RAM
122         ----
123         0000-1FFF       : IPL
124         8000-87FF       : CMOS
125 */
126
127 void MEMORY::write_signal(int id, uint32_t data, uint32_t mask)
128 {
129         if(id == SIG_MEMORY_PCM) {
130                 // pcm on from pit
131                 pcm_pit = ((data & mask) != 0);
132                 update_pcm();
133         } else if(id == SIG_MEMORY_FDC_IRQ) {
134                 fdc_irq = ((data & mask) != 0);
135         } else if(id == SIG_MEMORY_MOTOR) {
136                 motor = ((data & mask) != 0);
137         }
138 }
139
140 void MEMORY::update_map()
141 {
142         if(!(psel & 1)) {
143                 SET_BANK(0x0000, 0x1fff, wdmy, ipl);
144                 SET_BANK(0x2000, 0xdfff, wdmy, rdmy);
145         } else if(csel & 1) {
146                 if(bank & 0x10) {
147                         SET_BANK(0x0000, 0x7fff, ram + 0x00000, ram + 0x00000);
148                 } else if(bank & 0x20) {
149                         SET_BANK(0x0000, 0x7fff, ram + 0x10000, ram + 0x10000);
150                 } else if(bank & 0x40) {
151                         SET_BANK(0x0000, 0x7fff, ram + 0x20000, ram + 0x20000);
152                 } else if(bank & 0x80) {
153                         SET_BANK(0x0000, 0x7fff, ram + 0x30000, ram + 0x30000);
154                 } else {
155                         SET_BANK(0x0000, 0x7fff, wdmy, rdmy);
156                 }
157                 SET_BANK(0x8000, 0x87ff, cmos, cmos);
158         } else {
159                 if(bank & 0x10) {
160                         SET_BANK(0x0000, 0xdfff, ram + 0x00000, ram + 0x00000);
161                 } else if(bank & 0x20) {
162                         SET_BANK(0x0000, 0xdfff, ram + 0x10000, ram + 0x10000);
163                 } else if(bank & 0x40) {
164                         SET_BANK(0x0000, 0xdfff, ram + 0x20000, ram + 0x20000);
165                 } else if(bank & 0x80) {
166                         SET_BANK(0x0000, 0xdfff, ram + 0x30000, ram + 0x30000);
167                 } else {
168                         SET_BANK(0x0000, 0xdfff, wdmy, rdmy);
169                 }
170         }
171         SET_BANK(0xe000, 0xffff, ram + 0xe000, ram + 0xe000);
172 }
173
174 void MEMORY::update_pcm()
175 {
176         if(!pcm_on && (pcm_cont || pcm_pit)) {
177                 d_pcm->write_signal(SIG_PCM1BIT_ON, 1, 1);
178                 pcm_on = true;
179         } else if(pcm_on && !(pcm_cont || pcm_pit)) {
180                 d_pcm->write_signal(SIG_PCM1BIT_ON, 0, 1);
181                 pcm_on = false;
182         }
183 }
184
185 #define STATE_VERSION   1
186
187 bool MEMORY::process_state(FILEIO* state_fio, bool loading)
188 {
189         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
190                 return false;
191         }
192         if(!state_fio->StateCheckInt32(this_device_id)) {
193                 return false;
194         }
195         state_fio->StateBuffer(ram, sizeof(ram), 1);
196         state_fio->StateBuffer(cmos, sizeof(cmos), 1);
197         state_fio->StateUint32(cmos_crc32);
198         state_fio->StateUint8(bank);
199         state_fio->StateUint8(psel);
200         state_fio->StateUint8(csel);
201         state_fio->StateBool(pcm_on);
202         state_fio->StateBool(pcm_cont);
203         state_fio->StateBool(pcm_pit);
204         state_fio->StateBool(fdc_irq);
205         state_fio->StateBool(motor);
206         
207         // post process
208         if(loading) {
209                 update_map();
210         }
211         return true;
212 }
213
214 }