OSDN Git Service

[General][Qt] Merge upstream 2015-03-15.
[csp-qt/common_source_project-fm7.git] / source / src / vm / fmr30 / memory.cpp
1 /*
2         FUJITSU FMR-30 Emulator 'eFMR-30'
3
4         Author : Takeda.Toshiya
5         Date   : 2008.12.30 -
6
7         [ memory and crtc ]
8 */
9
10 #include "memory.h"
11 #include "../i8237.h"
12 #include "../i286.h"
13
14 static const uint8 bios1[] = {
15         0xFA,                           // cli
16         0xDB,0xE3,                      // fninit
17         0xB8,0x00,0x7F,                 // mov  ax,7F00
18         0x8E,0xD0,                      // mov  ss,ax
19         0xBC,0x64,0x0F,                 // mov  sp,0F64
20         // init i/o
21         0xB4,0x80,                      // mov  ah,80
22         0x9A,0x14,0x00,0xFB,0xFF,       // call far FFFB:0014
23         // boot from fdd
24         0xB4,0x81,                      // mov  ah,81
25         0x9A,0x14,0x00,0xFB,0xFF,       // call far FFFB:0014
26         0x73,0x0B,                      // jnb  $+11
27         0x74,0xF5,                      // jz   $-11
28         // boot from scsi-hdd
29         0xB4,0x82,                      // mov  ah,82
30         0x9A,0x14,0x00,0xFB,0xFF,       // call far FFFB:0014
31         0x72,0xEC,                      // jb   $-20
32         // goto ipl
33         0x9A,0x04,0x00,0x00,0xB0,       // call far B000:0004
34         0xEB,0xE7                       // jmp $-25
35 };
36
37 static const uint8 bios2[] = {
38         0xEA,0x00,0x00,0x00,0xFC,       // jmp  FC00:0000
39         0x00,0x00,0x00,
40         0xcf                            // iret
41 };
42
43 #define SET_BANK(s, e, w, r) { \
44         int sb = (s) >> 12, eb = (e) >> 12; \
45         for(int i = sb; i <= eb; i++) { \
46                 if((w) == wdmy) { \
47                         wbank[i] = wdmy; \
48                 } else { \
49                         wbank[i] = (w) + 0x1000 * (i - sb); \
50                 } \
51                 if((r) == rdmy) { \
52                         rbank[i] = rdmy; \
53                 } else { \
54                         rbank[i] = (r) + 0x1000 * (i - sb); \
55                 } \
56         } \
57 }
58
59 void MEMORY::initialize()
60 {
61         // init memory
62         memset(ram, 0, sizeof(ram));
63         memset(vram, 0, sizeof(vram));
64         memset(cvram, 0, sizeof(cvram));
65         memset(kvram, 0, sizeof(kvram));
66         memset(ipl, 0xff, sizeof(ipl));
67         memset(kanji16, 0xff, sizeof(kanji16));
68         memset(rdmy, 0xff, sizeof(rdmy));
69         
70         // load rom image
71         FILEIO* fio = new FILEIO();
72         if(fio->Fopen(emu->bios_path(_T("IPL.ROM")), FILEIO_READ_BINARY)) {
73                 fio->Fread(ipl, sizeof(ipl), 1);
74                 fio->Fclose();
75         } else {
76                 // load pseudo ipl
77                 memcpy(ipl + 0xc000, bios1, sizeof(bios1));
78                 memcpy(ipl + 0xfff0, bios2, sizeof(bios2));
79                 
80                 // ank8/16
81                 if(fio->Fopen(emu->bios_path(_T("ANK8.ROM")), FILEIO_READ_BINARY)) {
82                         fio->Fread(ipl, 0x800, 1);
83                         fio->Fclose();
84                 }
85                 if(fio->Fopen(emu->bios_path(_T("ANK16.ROM")), FILEIO_READ_BINARY)) {
86                         fio->Fread(ipl + 0x800, 0x1000, 1);
87                         fio->Fclose();
88                 }
89         }
90         if(fio->Fopen(emu->bios_path(_T("KANJI16.ROM")), FILEIO_READ_BINARY)) {
91                 fio->Fread(kanji16, sizeof(kanji16), 1);
92                 fio->Fclose();
93         }
94         delete fio;
95         
96         // set memory
97         SET_BANK(0x000000, 0xffffff, wdmy, rdmy);
98         SET_BANK(0x000000, sizeof(ram) - 1, ram, ram);
99         SET_BANK(0xff0000, 0xffffff, wdmy, ipl);
100         
101         // register event
102         register_frame_event(this);
103 }
104
105 void MEMORY::reset()
106 {
107         // reset crtc
108         lcdadr = 0;
109         memset(lcdreg, 0, sizeof(lcdreg));
110         dcr1 = dcr2 = 0;
111         kj_l = kj_h = kj_ofs = kj_row = 0;
112         blinkcnt = 0;
113         
114         // reset memory
115         mcr1 = 2;
116         mcr2 = a20 = 0;
117         update_bank();
118 }
119
120 void MEMORY::write_data8(uint32 addr, uint32 data)
121 {
122         addr &= 0xffffff;
123         wbank[addr >> 12][addr & 0xfff] = data;
124 }
125
126 uint32 MEMORY::read_data8(uint32 addr)
127 {
128         addr &= 0xffffff;
129         return rbank[addr >> 12][addr & 0xfff];
130 }
131
132 void MEMORY::write_io8(uint32 addr, uint32 data)
133 {
134         switch(addr & 0xffff) {
135         // memory controller
136         case 0x1d:
137                 mcr1 = data;
138                 update_bank();
139                 // protect mode ???
140 //              d_cpu->write_signal(SIG_I86_A20, data, 0x10);
141                 break;
142         case 0x1e:
143                 mcr2 = data;
144                 update_bank();
145                 break;
146         case 0x26:
147                 a20 = data;
148                 // protect mode ???
149                 d_cpu->write_signal(SIG_I86_A20, data, 0x80);
150                 break;
151         // dma bank
152         case 0x120:
153         case 0x121:
154         case 0x122:
155         case 0x123:
156                 d_dma->write_signal(SIG_I8237_BANK0 + (addr & 3), data, 0x0f);
157                 break;
158         // lcd controller
159         case 0x300:
160                 lcdadr = data;
161                 break;
162         case 0x302:
163                 lcdreg[lcdadr & 31] = data;
164                 break;
165         case 0x308:
166                 dcr1 = (dcr1 & 0xff00) | data;
167                 break;
168         case 0x309:
169                 dcr1 = (dcr1 & 0xff) | (data << 8);
170                 // bit11-10: vram bank
171                 update_bank();
172                 break;
173         case 0x30a:
174                 dcr1 = (dcr1 & 0xff00) | data;
175                 break;
176         case 0x30b:
177                 dcr1 = (dcr1 & 0xff) | (data << 8);
178                 break;
179         // kanji rom
180         case 0x30c:
181                 kj_h = data & 0x7f;
182                 break;
183         case 0x30d:
184                 kj_l = data & 0x7f;
185                 kj_row = 0;
186                 if(kj_h < 0x30) {
187                         kj_ofs = (((kj_l - 0x00) & 0x1f) <<  5) | (((kj_l - 0x20) & 0x20) <<  9) | (((kj_l - 0x20) & 0x40) <<  7) | (((kj_h - 0x00) & 0x07) << 10);
188                 } else if(kj_h < 0x70) {
189                         kj_ofs = (((kj_l - 0x00) & 0x1f) <<  5) + (((kj_l - 0x20) & 0x60) <<  9) + (((kj_h - 0x00) & 0x0f) << 10) + (((kj_h - 0x30) & 0x70) * 0xc00) + 0x08000;
190                 } else {
191                         kj_ofs = (((kj_l - 0x00) & 0x1f) <<  5) | (((kj_l - 0x20) & 0x20) <<  9) | (((kj_l - 0x20) & 0x40) <<  7) | (((kj_h - 0x00) & 0x07) << 10) | 0x38000;
192                 }
193                 break;
194         case 0x30e:
195                 kanji16[(kj_ofs | ((kj_row & 0x0f) << 1)) & 0x3ffff] = data;
196                 break;
197         case 0x30f:
198                 kanji16[(kj_ofs | ((kj_row++ & 0x0f) << 1) | 1) & 0x3ffff] = data;
199                 break;
200         }
201 }
202
203 uint32 MEMORY::read_io8(uint32 addr)
204 {
205         uint32 val = 0xff;
206         
207         switch(addr & 0xffff) {
208         case 0x1d:
209                 return mcr1;
210         case 0x1e:
211                 return mcr2;
212         case 0x26:
213                 return a20;
214         // lcd controller
215         case 0x300:
216                 return lcdadr;
217         case 0x302:
218                 return lcdreg[lcdadr & 31];
219         case 0x308:
220                 return dcr1 & 0xff;
221         case 0x309:
222                 return (dcr1 >> 8) & 0xff;
223         case 0x30a:
224                 return dcr2 & 0xff;
225         case 0x30b:
226                 return (dcr2 >> 8) & 0xff;
227         // kanji rom
228         case 0x30c:
229                 return kj_h;
230         case 0x30d:
231                 return kj_l;
232         case 0x30e:
233                 return kanji16[(kj_ofs | ((kj_row & 0x0f) << 1)) & 0x3ffff];
234         case 0x30f:
235                 return kanji16[(kj_ofs | ((kj_row++ & 0x0f) << 1) | 1) & 0x3ffff];
236         }
237         return 0xff;
238 }
239
240 void MEMORY::event_frame()
241 {
242         blinkcnt++;
243 }
244
245 void MEMORY::update_bank()
246 {
247         if(!(mcr2 & 1)) {
248                 // $c0000-$cffff: vram
249                 SET_BANK(0xc0000, 0xcffff, wdmy, rdmy);
250                 int bank = 0x8000 * ((dcr1 >> 10) & 3);
251                 SET_BANK(0xc0000, 0xc7fff, vram + bank, vram + bank);
252                 SET_BANK(0xc8000, 0xc8fff, cvram, cvram);
253                 SET_BANK(0xca000, 0xcafff, kvram, kvram);
254         } else {
255                 SET_BANK(0xc0000, 0xcffff, ram + 0xc0000, ram + 0xc0000);
256         }
257         if(!(mcr1 & 1)) {
258                 // $f000-$ffff: rom
259                 SET_BANK(0xf0000, 0xfffff, wdmy, ipl);
260         } else {
261                 SET_BANK(0xf0000, 0xfffff, ram + 0xf0000, ram + 0xf0000);
262         }
263 }
264
265 void MEMORY::draw_screen()
266 {
267         // render screen
268         memset(screen_txt, 0, sizeof(screen_txt));
269         memset(screen_cg, 0, sizeof(screen_cg));
270         if(dcr1 & 2) {
271                 if(dcr1 & 8) {
272                         draw_text40();
273                 } else {
274                         draw_text80();
275                 }
276         }
277         if(dcr1 & 1) {
278                 draw_cg();
279         }
280         
281         scrntype cd = RGB_COLOR(48, 56, 16);
282         scrntype cb = RGB_COLOR(160, 168, 160);
283         for(int y = 0; y < 400; y++) {
284                 scrntype* dest = emu->screen_buffer(y);
285                 uint8* txt = screen_txt[y];
286                 uint8* cg = screen_cg[y];
287                 
288                 for(int x = 0; x < 640; x++) {
289                         dest[x] = (txt[x] || cg[x]) ? cd : cb;
290                 }
291         }
292 }
293
294 void MEMORY::draw_text40()
295 {
296         uint8 *ank8 = ipl;
297         uint8 *ank16 = ipl + 0x800;
298         
299         int src = 0;//((lcdreg[12] << 9) | (lcdreg[13] << 1)) & 0xfff;
300         int caddr = (lcdreg[10] & 0x20) ? -1 : (((lcdreg[14] << 9) | (lcdreg[15] << 1)) & 0xfff);
301         int yofs = lcdreg[9] + 1;
302         int ymax = 400 / yofs;
303         int freq = (dcr1 >> 4) & 3;
304         bool blink = !((freq == 3) || (blinkcnt & (32 >> freq)));
305         
306         for(int y = 0; y < ymax; y++) {
307                 for(int x = 0; x < 40; x++) {
308                         bool cursor = (src == caddr);
309                         int cx = x;
310                         uint8 code = cvram[src];
311                         uint8 h = kvram[src] & 0x7f;
312                         src = (src + 1) & 0xfff;
313                         uint8 attr = cvram[src];
314                         uint8 l = kvram[src] & 0x7f;
315                         src = (src + 1) & 0xfff;
316                         uint8 col = attr & 0x27;
317                         bool blnk = blink && (attr & 0x10);
318                         bool rev = ((attr & 8) != 0);
319                         
320                         if(attr & 0x40) {
321                                 // kanji
322                                 int ofs;
323                                 if(h < 0x30) {
324                                         ofs = (((l - 0x00) & 0x1f) <<  5) | (((l - 0x20) & 0x20) <<  9) | (((l - 0x20) & 0x40) <<  7) | (((h - 0x00) & 0x07) << 10);
325                                 } else if(h < 0x70) {
326                                         ofs = (((l - 0x00) & 0x1f) <<  5) + (((l - 0x20) & 0x60) <<  9) + (((h - 0x00) & 0x0f) << 10) + (((h - 0x30) & 0x70) * 0xc00) + 0x08000;
327                                 } else {
328                                         ofs = (((l - 0x00) & 0x1f) <<  5) | (((l - 0x20) & 0x20) <<  9) | (((l - 0x20) & 0x40) <<  7) | (((h - 0x00) & 0x07) << 10) | 0x38000;
329                                 }
330                                 
331                                 for(int l = 0; l < 16 && l < yofs; l++) {
332                                         uint8 pat0 = kanji16[ofs + (l << 1) + 0];
333                                         uint8 pat1 = kanji16[ofs + (l << 1) + 1];
334                                         pat0 = blnk ? 0 : rev ? ~pat0 : pat0;
335                                         pat1 = blnk ? 0 : rev ? ~pat1 : pat1;
336                                         int yy = y * yofs + l;
337                                         if(yy >= 400) {
338                                                 break;
339                                         }
340                                         uint8* d = &screen_txt[yy][x << 4];
341                                         
342                                         d[ 0] = d[ 1] = (pat0 & 0x80) ? col : 0;
343                                         d[ 2] = d[ 3] = (pat0 & 0x40) ? col : 0;
344                                         d[ 4] = d[ 5] = (pat0 & 0x20) ? col : 0;
345                                         d[ 6] = d[ 7] = (pat0 & 0x10) ? col : 0;
346                                         d[ 8] = d[ 9] = (pat0 & 0x08) ? col : 0;
347                                         d[10] = d[11] = (pat0 & 0x04) ? col : 0;
348                                         d[12] = d[13] = (pat0 & 0x02) ? col : 0;
349                                         d[14] = d[15] = (pat0 & 0x01) ? col : 0;
350                                         d[16] = d[17] = (pat1 & 0x80) ? col : 0;
351                                         d[18] = d[19] = (pat1 & 0x40) ? col : 0;
352                                         d[20] = d[21] = (pat1 & 0x20) ? col : 0;
353                                         d[22] = d[23] = (pat1 & 0x10) ? col : 0;
354                                         d[24] = d[25] = (pat1 & 0x08) ? col : 0;
355                                         d[26] = d[27] = (pat1 & 0x04) ? col : 0;
356                                         d[28] = d[29] = (pat1 & 0x02) ? col : 0;
357                                         d[30] = d[31] = (pat1 & 0x01) ? col : 0;
358                                 }
359                                 src = (src + 2) & 0xfff;
360                                 x++;
361                         } else {
362                                 for(int l = 0; l < 16 && l < yofs; l++) {
363                                         uint8 pat = ank16[(code << 4) + l];
364                                         pat = blnk ? 0 : rev ? ~pat : pat;
365                                         int yy = y * yofs + l;
366                                         if(yy >= 400) {
367                                                 break;
368                                         }
369                                         uint8* d = &screen_txt[yy][x << 4];
370                                         
371                                         d[ 0] = d[ 1] = (pat & 0x80) ? col : 0;
372                                         d[ 2] = d[ 3] = (pat & 0x40) ? col : 0;
373                                         d[ 4] = d[ 5] = (pat & 0x20) ? col : 0;
374                                         d[ 6] = d[ 7] = (pat & 0x10) ? col : 0;
375                                         d[ 8] = d[ 9] = (pat & 0x08) ? col : 0;
376                                         d[10] = d[11] = (pat & 0x04) ? col : 0;
377                                         d[12] = d[13] = (pat & 0x02) ? col : 0;
378                                         d[14] = d[15] = (pat & 0x01) ? col : 0;
379                                 }
380                         }
381                         if(cursor && !blink) {
382                                 int st = lcdreg[10] & 0x1f;
383                                 int ed = lcdreg[11] & 0x1f;
384                                 for(int i = st; i <= ed && i < yofs; i++) {
385                                         memset(&screen_txt[y * yofs + i][cx << 4], 7, 8);
386                                 }
387                         }
388                 }
389         }
390 }
391
392 void MEMORY::draw_text80()
393 {
394         uint8 *ank8 = ipl;
395         uint8 *ank16 = ipl + 0x800;
396         
397         int src = 0;//((lcdreg[12] << 9) | (lcdreg[13] << 1)) & 0xfff;
398         int caddr = (lcdreg[10] & 0x20) ? -1 : (((lcdreg[14] << 9) | (lcdreg[15] << 1)) & 0xfff);
399         int yofs = lcdreg[9] + 1;
400         int ymax = 400 / yofs;
401         int freq = (dcr1 >> 4) & 3;
402         bool blink = !((freq == 3) || (blinkcnt & (32 >> freq)));
403         
404         for(int y = 0; y < ymax; y++) {
405                 for(int x = 0; x < 80; x++) {
406                         bool cursor = (src == caddr);
407                         int cx = x;
408                         uint8 code = cvram[src];
409                         uint8 h = kvram[src] & 0x7f;
410                         src = (src + 1) & 0xfff;
411                         uint8 attr = cvram[src];
412                         uint8 l = kvram[src] & 0x7f;
413                         src = (src + 1) & 0xfff;
414                         uint8 col = attr & 0x27;
415                         bool blnk = blink && (attr & 0x10);
416                         bool rev = ((attr & 8) != 0);
417                         
418                         if(attr & 0x40) {
419                                 // kanji
420                                 int ofs;
421                                 if(h < 0x30) {
422                                         ofs = (((l - 0x00) & 0x1f) <<  5) | (((l - 0x20) & 0x20) <<  9) | (((l - 0x20) & 0x40) <<  7) | (((h - 0x00) & 0x07) << 10);
423                                 } else if(h < 0x70) {
424                                         ofs = (((l - 0x00) & 0x1f) <<  5) + (((l - 0x20) & 0x60) <<  9) + (((h - 0x00) & 0x0f) << 10) + (((h - 0x30) & 0x70) * 0xc00) + 0x08000;
425                                 } else {
426                                         ofs = (((l - 0x00) & 0x1f) <<  5) | (((l - 0x20) & 0x20) <<  9) | (((l - 0x20) & 0x40) <<  7) | (((h - 0x00) & 0x07) << 10) | 0x38000;
427                                 }
428                                 
429                                 for(int l = 0; l < 16 && l < yofs; l++) {
430                                         uint8 pat0 = kanji16[ofs + (l << 1) + 0];
431                                         uint8 pat1 = kanji16[ofs + (l << 1) + 1];
432                                         pat0 = blnk ? 0 : rev ? ~pat0 : pat0;
433                                         pat1 = blnk ? 0 : rev ? ~pat1 : pat1;
434                                         int yy = y * yofs + l;
435                                         if(yy >= 400) {
436                                                 break;
437                                         }
438                                         uint8* d = &screen_txt[yy][x << 3];
439                                         
440                                         d[ 0] = (pat0 & 0x80) ? col : 0;
441                                         d[ 1] = (pat0 & 0x40) ? col : 0;
442                                         d[ 2] = (pat0 & 0x20) ? col : 0;
443                                         d[ 3] = (pat0 & 0x10) ? col : 0;
444                                         d[ 4] = (pat0 & 0x08) ? col : 0;
445                                         d[ 5] = (pat0 & 0x04) ? col : 0;
446                                         d[ 6] = (pat0 & 0x02) ? col : 0;
447                                         d[ 7] = (pat0 & 0x01) ? col : 0;
448                                         d[ 8] = (pat1 & 0x80) ? col : 0;
449                                         d[ 9] = (pat1 & 0x40) ? col : 0;
450                                         d[10] = (pat1 & 0x20) ? col : 0;
451                                         d[11] = (pat1 & 0x10) ? col : 0;
452                                         d[12] = (pat1 & 0x08) ? col : 0;
453                                         d[13] = (pat1 & 0x04) ? col : 0;
454                                         d[14] = (pat1 & 0x02) ? col : 0;
455                                         d[15] = (pat1 & 0x01) ? col : 0;
456                                 }
457                                 src = (src + 2) & 0xfff;
458                                 x++;
459                         } else {
460                                 for(int l = 0; l < 16 && l < yofs; l++) {
461                                         uint8 pat = ank16[(code << 4) + l];
462                                         pat = blnk ? 0 : rev ? ~pat : pat;
463                                         int yy = y * yofs + l;
464                                         if(yy >= 400) {
465                                                 break;
466                                         }
467                                         uint8* d = &screen_txt[yy][x << 3];
468                                         
469                                         d[0] = (pat & 0x80) ? col : 0;
470                                         d[1] = (pat & 0x40) ? col : 0;
471                                         d[2] = (pat & 0x20) ? col : 0;
472                                         d[3] = (pat & 0x10) ? col : 0;
473                                         d[4] = (pat & 0x08) ? col : 0;
474                                         d[5] = (pat & 0x04) ? col : 0;
475                                         d[6] = (pat & 0x02) ? col : 0;
476                                         d[7] = (pat & 0x01) ? col : 0;
477                                 }
478                         }
479                         if(cursor && !blink) {
480                                 int st = lcdreg[10] & 0x1f;
481                                 int ed = lcdreg[11] & 0x1f;
482                                 for(int i = st; i <= ed && i < yofs; i++) {
483                                         memset(&screen_txt[y * yofs + i][cx << 3], 7, 8);
484                                 }
485                         }
486                 }
487         }
488 }
489
490 void MEMORY::draw_cg()
491 {
492         uint8* plane = vram + ((dcr1 >> 8) & 3) * 0x8000;
493         int ptr = 0;
494         
495         for(int y = 0; y < 400; y++) {
496                 for(int x = 0; x < 640; x += 8) {
497                         uint8 pat = plane[ptr++];
498                         uint8* d = &screen_cg[y][x];
499                         
500                         d[0] = pat & 0x80;
501                         d[1] = pat & 0x40;
502                         d[2] = pat & 0x20;
503                         d[3] = pat & 0x10;
504                         d[4] = pat & 0x08;
505                         d[5] = pat & 0x04;
506                         d[6] = pat & 0x02;
507                         d[7] = pat & 0x01;
508                 }
509         }
510 }
511
512 #define STATE_VERSION   1
513
514 void MEMORY::save_state(FILEIO* state_fio)
515 {
516         state_fio->FputUint32(STATE_VERSION);
517         state_fio->FputInt32(this_device_id);
518         
519         state_fio->Fwrite(ram, sizeof(ram), 1);
520         state_fio->Fwrite(vram, sizeof(vram), 1);
521         state_fio->Fwrite(cvram, sizeof(cvram), 1);
522         state_fio->Fwrite(kvram, sizeof(kvram), 1);
523         state_fio->FputUint8(mcr1);
524         state_fio->FputUint8(mcr2);
525         state_fio->FputUint8(a20);
526         state_fio->FputUint8(lcdadr);
527         state_fio->Fwrite(lcdreg, sizeof(lcdreg), 1);
528         state_fio->FputUint16(dcr1);
529         state_fio->FputUint16(dcr2);
530         state_fio->FputInt32(kj_h);
531         state_fio->FputInt32(kj_l);
532         state_fio->FputInt32(kj_ofs);
533         state_fio->FputInt32(kj_row);
534         state_fio->FputInt32(blinkcnt);
535 }
536
537 bool MEMORY::load_state(FILEIO* state_fio)
538 {
539         if(state_fio->FgetUint32() != STATE_VERSION) {
540                 return false;
541         }
542         if(state_fio->FgetInt32() != this_device_id) {
543                 return false;
544         }
545         state_fio->Fread(ram, sizeof(ram), 1);
546         state_fio->Fread(vram, sizeof(vram), 1);
547         state_fio->Fread(cvram, sizeof(cvram), 1);
548         state_fio->Fread(kvram, sizeof(kvram), 1);
549         mcr1 = state_fio->FgetUint8();
550         mcr2 = state_fio->FgetUint8();
551         a20 = state_fio->FgetUint8();
552         lcdadr = state_fio->FgetUint8();
553         state_fio->Fread(lcdreg, sizeof(lcdreg), 1);
554         dcr1 = state_fio->FgetUint16();
555         dcr2 = state_fio->FgetUint16();
556         kj_h = state_fio->FgetInt32();
557         kj_l = state_fio->FgetInt32();
558         kj_ofs = state_fio->FgetInt32();
559         kj_row = state_fio->FgetInt32();
560         blinkcnt = state_fio->FgetInt32();
561         
562         // post process
563         update_bank();
564         return true;
565 }
566