OSDN Git Service

[VM][General][WIP] Start to merge upstream 2018-10-14.Open branch upstream_20181014 .
[csp-qt/common_source_project-fm7.git] / source / src / vm / smb80te / memory.cpp
1 /*
2         SHARP SM-B-80TE Emulator 'eSM-B-80TE'
3
4         Author : Takeda.Toshiya
5         Date   : 2016.12.29-
6
7         [ memory ]
8 */
9
10 #include "memory.h"
11 #include "../z80pio.h"
12
13 namespace SMB80TE {
14
15 #define SET_BANK(s, e, w, r) { \
16         int sb = (s) >> 11, eb = (e) >> 11; \
17         for(int i = sb; i <= eb; i++) { \
18                 if((w) == wdmy) { \
19                         wbank[i] = wdmy; \
20                 } else { \
21                         wbank[i] = (w) + 0x800 * (i - sb); \
22                 } \
23                 if((r) == rdmy) { \
24                         rbank[i] = rdmy; \
25                 } else { \
26                         rbank[i] = (r) + 0x800 * (i - sb); \
27                 } \
28         } \
29 }
30
31 void MEMORY::initialize()
32 {
33         // initialize memory
34         memset(ram, 0, sizeof(ram));
35         memset(mon, 0xff, sizeof(mon));
36         memset(user, 0xff, sizeof(user));
37         memset(rdmy, 0xff, sizeof(rdmy));
38         
39         // load rom images
40         FILEIO* fio = new FILEIO();
41         if(fio->Fopen(create_local_path(_T("MON.ROM")), FILEIO_READ_BINARY)) {
42                 fio->Fread(mon, sizeof(mon), 1);
43                 fio->Fclose();
44         }
45         if(fio->Fopen(create_local_path(_T("USER.ROM")), FILEIO_READ_BINARY)) {
46                 fio->Fread(user, sizeof(user), 1);
47                 fio->Fclose();
48         }
49         delete fio;
50         
51         SET_BANK(0x0000, 0x0fff, ram,  ram );
52         SET_BANK(0x1000, 0x7fff, wdmy, rdmy);
53         SET_BANK(0x8000, 0x87ff, wdmy, mon );
54         SET_BANK(0x8800, 0x8fff, wdmy, user);
55         SET_BANK(0x9000, 0xffff, wdmy, rdmy);
56         
57         pio1_pa = pio1_pb = 0;
58         
59         register_vline_event(this);
60 }
61
62 void MEMORY::reset()
63 {
64         if(config.dipswitch & 1) {
65                 a15_mask = 0x8000;
66         } else {
67                 a15_mask = 0x0000;
68         }
69         shift_reg = 0;
70 }
71
72 void MEMORY::write_data8(uint32_t addr, uint32_t data)
73 {
74         addr &= 0xffff;
75         addr |= a15_mask;
76         wbank[(addr >> 11) & 0x1f][addr & 0x7ff] = data;
77 }
78
79 uint32_t MEMORY::read_data8(uint32_t addr)
80 {
81         addr &= 0xffff;
82         addr |= a15_mask;
83         return rbank[(addr >> 11) & 0x1f][addr & 0x7ff];
84 }
85
86 uint32_t MEMORY::fetch_op(uint32_t addr, int *wait)
87 {
88         switch(shift_reg <<= 1) {
89         case 0x08: // QD
90                 d_cpu->write_signal(SIG_CPU_NMI, 1, 1);
91                 break;
92         case 0x10: // QE
93                 a15_mask = 0x8000;
94                 break;
95         }
96         *wait = 0;
97         return read_data8(addr);
98 }
99
100 void MEMORY::write_io8(uint32_t addr, uint32_t data)
101 {
102         switch(addr & 0xff) {
103         case 0xd8:
104                 // ARES
105                 a15_mask = 0x0000;
106                 break;
107         case 0xd9:
108                 // STEP
109                 shift_reg = 0x01;
110                 break;
111         case 0xda:
112                 // LED on
113                 led = true;
114                 break;
115         case 0xdb:
116                 // LED off
117                 led = false;
118                 break;
119         }
120 }
121
122 uint32_t MEMORY::read_io8(uint32_t addr)
123 {
124         return 0xff;
125 }
126
127 void MEMORY::write_signal(int id, uint32_t data, uint32_t mask)
128 {
129         switch(id) {
130         case SIG_MEMORY_PIO1_PA:
131                 pio1_pa = data & mask;
132                 break;
133         case SIG_MEMORY_PIO1_PB:
134                 pio1_pb = data & mask;
135                 update_kb();
136                 break;
137         }
138 }
139
140 void MEMORY::event_vline(int v, int clock)
141 {
142         if(!v) {
143                 update_kb();
144                 memset(seg, 0, sizeof(seg));
145         }
146         for(int i = 0; i < 8; i++) {
147                 if(((pio1_pb >> 3) & 7) == i) {
148                         for(int j = 0; j < 8; j++) {
149                                 if(!(pio1_pa & (1 << j))) {
150                                         seg[i][j]++;
151                                 }
152                         }
153                 }
154         }
155 }
156
157 void MEMORY::update_kb()
158 {
159         const uint8_t* key_stat = emu->get_key_buffer();
160         uint8_t val = 0xff;
161         
162         switch((pio1_pb >> 3) & 7) {
163         case 0:
164                 if(key_stat[0x80] || key_stat[0x30] || key_stat[0x60]) val &= ~0x01;    // 0
165                 if(key_stat[0x81] || key_stat[0x31] || key_stat[0x61]) val &= ~0x02;    // 1
166                 if(key_stat[0x82] || key_stat[0x32] || key_stat[0x62]) val &= ~0x04;    // 2
167                 break;
168         case 1:
169                 if(key_stat[0x83] || key_stat[0x33] || key_stat[0x63]) val &= ~0x01;    // 3
170                 if(key_stat[0x84] || key_stat[0x34] || key_stat[0x64]) val &= ~0x02;    // 4
171                 if(key_stat[0x85] || key_stat[0x35] || key_stat[0x65]) val &= ~0x04;    // 5
172                 break;
173         case 2:
174                 if(key_stat[0x86] || key_stat[0x36] || key_stat[0x66]) val &= ~0x01;    // 6
175                 if(key_stat[0x87] || key_stat[0x37] || key_stat[0x67]) val &= ~0x02;    // 7
176                 if(key_stat[0x88] || key_stat[0x38] || key_stat[0x68]) val &= ~0x04;    // 8
177                 break;
178         case 3:
179                 if(key_stat[0x89] || key_stat[0x39] || key_stat[0x69]) val &= ~0x01;    // 9
180                 if(key_stat[0x8a] || key_stat[0x41]                  ) val &= ~0x02;    // A
181                 if(key_stat[0x8b] || key_stat[0x42]                  ) val &= ~0x04;    // B
182                 break;
183         case 4:
184                 if(key_stat[0x8c] || key_stat[0x43]                  ) val &= ~0x01;    // C
185                 if(key_stat[0x8d] || key_stat[0x44]                  ) val &= ~0x02;    // D
186                 if(key_stat[0x8e] || key_stat[0x45]                  ) val &= ~0x04;    // E
187                 break;
188         case 5:
189                 if(key_stat[0x8f] || key_stat[0x46]                  ) val &= ~0x01;    // F
190                 if(key_stat[0x9d] || key_stat[0x75]                  ) val &= ~0x02;    // REG'/REG ... F6
191                 if(key_stat[0x9a] || key_stat[0x72] || key_stat[0x21]) val &= ~0x04;    // LD/INC   ... F3 or PgUp
192                 break;
193         case 6:
194                 if(key_stat[0x9b] || key_stat[0x73] || key_stat[0x22]) val &= ~0x01;    // STOR/DEC ... F4 or PgDn
195                 if(key_stat[0x98] || key_stat[0x70]                  ) val &= ~0x02;    // RUN      ... F1
196                 if(key_stat[0x99] || key_stat[0x71]                  ) val &= ~0x04;    // STEP     ... F2
197                 break;
198         case 7:
199                 if(key_stat[0x9f] || key_stat[0x77] || key_stat[0x0d]) val &= ~0x01;    // WR       ... F8 or Enter
200                 if(key_stat[0x9e] || key_stat[0x76]                  ) val &= ~0x02;    // ADRS     ... F7
201                 if(key_stat[0x9c] || key_stat[0x74] || key_stat[0x10]) val &= ~0x04;    // SHIFT    ... F5 or Shift
202                 break;
203         }
204         d_pio1->write_signal(SIG_Z80PIO_PORT_B, val, 0x07);
205
206
207
208
209 }
210
211 static const int led_pattern[LED_HEIGHT][LED_WIDTH] = {
212         {0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,2,0,0},
213         {0,0,6,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,2,2,0,0},
214         {0,0,6,6,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,2,2,2,0,0},
215         {0,0,6,6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0},
216         {0,0,6,6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0},
217         {0,0,6,6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0},
218         {0,0,6,6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0},
219         {0,6,6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0},
220         {0,6,6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0},
221         {0,6,6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0},
222         {0,0,6,0,7,7,7,7,7,7,7,7,7,7,7,7,7,7,0,2,0,0,0,0},
223         {0,0,0,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,0,0,0,0,0},
224         {0,0,5,0,7,7,7,7,7,7,7,7,7,7,7,7,7,7,0,3,0,0,0,0},
225         {0,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,0,0,0},
226         {0,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,0,0,0},
227         {0,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,0,0,0},
228         {5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,0,0,0,0},
229         {5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,0,0,0,0},
230         {5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,0,0,0,0},
231         {5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,0,0,0,0},
232         {5,5,0,4,4,4,4,4,4,4,4,4,4,4,4,4,0,3,3,3,0,0,0,0},
233         {5,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,3,3,0,8,8,8},
234         {0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,3,0,8,8,8},
235         {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,8,8},
236 };
237
238 void MEMORY::draw_screen()
239 {
240         scrntype_t color_on = RGB_COLOR(255, 8, 72);
241         scrntype_t color_off = RGB_COLOR(56, 0, 0);
242         scrntype_t color_led[9];
243         uint8_t* base = ram + (~(config.dipswitch >> 2) & 3) * 0x200;
244         color_led[0] = RGB_COLOR(37, 21, 22);
245         
246         for(int i = 0; i < 8; i++) {
247                 for(int b = 0; b < 8; b++) {
248                         color_led[b + 1] = (seg[i][b] > 8) ? color_on : color_off;
249                 }
250                 for(int y = 0; y < LED_HEIGHT; y++) {
251                         scrntype_t* dest = emu->get_screen_buffer(vm_ranges[i].y + y) + vm_ranges[i].x;
252                         for(int x = 0; x < LED_WIDTH; x++) {
253                                 dest[x] = color_led[led_pattern[y][x]];
254                         }
255                 }
256         }
257 }
258
259 void MEMORY::load_ram(const _TCHAR* file_path)
260 {
261         FILEIO* fio = new FILEIO();
262         
263         if(fio->Fopen(file_path, FILEIO_READ_BINARY)) {
264                 fio->Fread(ram, sizeof(ram), 1);
265                 fio->Fclose();
266         }
267         delete fio;
268 }
269
270 void MEMORY::save_ram(const _TCHAR* file_path)
271 {
272         FILEIO* fio = new FILEIO();
273         
274         if(fio->Fopen(file_path, FILEIO_WRITE_BINARY)) {
275                 fio->Fwrite(ram, sizeof(ram), 1);
276                 fio->Fclose();
277         }
278         delete fio;
279 }
280
281 #define STATE_VERSION   1
282
283 bool MEMORY::process_state(FILEIO* state_fio, bool loading)
284 {
285         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
286                 return false;
287         }
288         if(!state_fio->StateCheckInt32(this_device_id)) {
289                 return false;
290         }
291         state_fio->StateArray(ram, sizeof(ram), 1);
292         state_fio->StateValue(pio1_pa);
293         state_fio->StateValue(pio1_pb);
294         state_fio->StateValue(shift_reg);
295         state_fio->StateValue(a15_mask);
296         state_fio->StateValue(led);
297         return true;
298 }
299
300 }