2 Nintendo Family BASIC Emulator 'eFamilyBASIC'
5 Author : Takeda.Toshiya
11 #ifndef _FAMILYBASIC_H_
12 #define _FAMILYBASIC_H_
14 #define DEVICE_NAME "Nintendo Family BASIC"
15 #define CONFIG_NAME "familybasic"
17 // device informations for virtual machine
18 #define FRAMES_PER_SEC 59.98
19 //#define LINES_PER_FRAME 262
20 #define LINES_PER_FRAME 525 // 262.5*2
21 #define CPU_CLOCKS 1789772
22 #define SCREEN_WIDTH 256
23 #define SCREEN_HEIGHT 240
24 // pixel aspect should be 8:7
25 #define WINDOW_HEIGHT_ASPECT 210
28 // device informations for win32
29 #define SUPPORT_TV_RENDER
30 #define USE_BOOT_MODE 6
32 #define USE_AUTO_KEY 5
33 #define USE_AUTO_KEY_RELEASE 8
34 #define USE_AUTO_KEY_NO_CAPS
35 #define USE_SOUND_VOLUME 4
37 #define USE_JOY_BUTTON_CAPTIONS
41 #define USE_VM_AUTO_KEY_TABLE
42 #define USE_TWO_STROKE_AUTOKEY_HANDAKUON
43 #define USE_TWO_STROKE_AUTOKEY_DAKUON
45 #include "../../common.h"
46 #include "../../fileio.h"
47 #include "../vm_template.h"
49 #ifdef USE_SOUND_VOLUME
50 static const _TCHAR *sound_device_caption[] = {
51 _T("APU"), _T("VRC7"), _T("CMT (Signal)"), _T("Noise (CMT)"),
55 #ifdef USE_JOY_BUTTON_CAPTIONS
56 static const _TCHAR *joy_button_captions[] = {
68 #ifdef USE_VM_AUTO_KEY_TABLE
69 static const int vm_auto_key_table_base[][2] = {
70 // A,I,U,E,O -> 1,2,3,4,5
76 // KA,KI,KU,KE,KO -> Q,W,E,R,T
77 {0xb6, 0x200 | ((int)'Q')},
78 {0xb7, 0x200 | ((int)'W')},
79 {0xb8, 0x200 | ((int)'E')},
80 {0xb9, 0x200 | ((int)'R')},
81 {0xba, 0x200 | ((int)'T')},
82 // SA,SI,SU,SE,SO -> A,S,D,F,G
83 {0xbb, 0x200 | ((int)'A')},
84 {0xbc, 0x200 | ((int)'S')},
85 {0xbd, 0x200 | ((int)'D')},
86 {0xbe, 0x200 | ((int)'F')},
87 {0xbf, 0x200 | ((int)'G')},
88 // TA,TI,TU,TE,TO -> Z, X, C, V, B
89 {0xc0, 0x200 | ((int)'Z')},
90 {0xc1, 0x200 | ((int)'X')},
91 {0xc2, 0x200 | ((int)'C')},
92 {0xc3, 0x200 | ((int)'V')},
93 {0xc4, 0x200 | ((int)'B')},
94 // NA,NI,NU,NE,NO -> 6,7,8,9,0
100 // HA,HI,HU,HE,HO -> Y,U,I,O,P
101 {0xca, 0x200 | ((int)'Y')},
102 {0xcb, 0x200 | ((int)'U')},
103 {0xcc, 0x200 | ((int)'I')},
104 {0xcd, 0x200 | ((int)'O')},
105 {0xce, 0x200 | ((int)'P')},
106 // MA,MI,MU,ME,MO -> H,J,K,L,;
107 {0xcf, 0x200 | ((int)'H')},
108 {0xd0, 0x200 | ((int)'J')},
109 {0xd1, 0x200 | ((int)'K')},
110 {0xd2, 0x200 | ((int)'L')},
111 {0xd3, 0x200 | ((int)';')},
112 // YA,YU,YO,WA,W0,NN -> N,M,,,.,/,_
113 {0xd4, 0x200 | ((int)'N')},
114 {0xd5, 0x200 | ((int)'M')},
115 {0xd6, 0x200 | 0xbc},
116 {0xdc, 0x200 | 0xbe},
117 {0xa6, 0x200 | 0xbf},
118 {0xdd, 0x200 | 0xe2},
119 // RA,RI,RU,RE,RO -> -, ^, ¥, @, [
120 {0xd7, 0x200 | 0xbd},
121 {0xd8, 0x200 | 0xde},
122 {0xd9, 0x200 | 0xdc},
123 {0xda, 0x200 | 0xc0},
124 {0xdb, 0x200 | 0xdb},
125 // XA,XI,XU,XE,XO -> SHIFT+1, SHIFT+2, SHIFT+3, SHIFT+4, SHIFT+5
126 {0xa7, 0x300 | 0x31},
127 {0xa8, 0x300 | 0x32},
128 {0xa9, 0x300 | 0x33},
129 {0xaa, 0x300 | 0x34},
130 {0xab, 0x300 | 0x35},
131 // XYA,XYU,XYO -> SHIFT+N,SHIFT+M,SHIFT+,
132 {0xac, 0x300 | ((int)'N')},
133 {0xad, 0x300 | ((int)'M')},
134 {0xae, 0x300 | 0xbc},
136 {0xaf, 0x300 | ((int)'C')},
138 {0x5f, 0x200 | 0xbd},
139 {0xa1, 0x200 | 0xdd},
141 {0xa2, 0x300 | 0xbd},
142 {0xa3, 0x300 | 0xdd},
143 // '゙' -> Double Quotation
144 // {0xde, 0x100 | 0x32},
148 #ifdef USE_TWO_STROKE_AUTOKEY_HANDAKUON
149 static const int kana_handakuon_keyboard_table[][6] = {
150 // PA,PI,PU,PE,PO -> Y,U,I,O,P
151 {0xca, 0x300 | ((int)'Y'), 0x00, 0x00, 0x00, 0x00},
152 {0xcb, 0x300 | ((int)'U'), 0x00, 0x00, 0x00, 0x00},
153 {0xcc, 0x300 | ((int)'I'), 0x00, 0x00, 0x00, 0x00},
154 {0xcd, 0x300 | ((int)'O'), 0x00, 0x00, 0x00, 0x00},
155 {0xce, 0x300 | ((int)'P'), 0x00, 0x00, 0x00, 0x00},
159 #ifdef USE_TWO_STROKE_AUTOKEY_DAKUON
160 static const int kana_dakuon_keyboard_table[][6] = {
161 // GA,GI,GU,GE,GO -> Q,W,E,R,T
162 {0xb6, 0x1000 | 0x12, 0x200 | ((int)'Q'), 0x2000 | 0x12, 0x00, 0x00},
163 {0xb7, 0x1000 | 0x12, 0x200 | ((int)'W'), 0x2000 | 0x12, 0x00, 0x00},
164 {0xb8, 0x1000 | 0x12, 0x200 | ((int)'E'), 0x2000 | 0x12, 0x00, 0x00},
165 {0xb9, 0x1000 | 0x12, 0x200 | ((int)'R'), 0x2000 | 0x12, 0x00, 0x00},
166 {0xba, 0x1000 | 0x12, 0x200 | ((int)'T'), 0x2000 | 0x12, 0x00, 0x00},
167 // ZA,ZI,ZU,ZE,ZO -> A,S,D,F,G
168 {0xbb, 0x1000 | 0x12, 0x200 | ((int)'A'), 0x2000 | 0x12, 0x00, 0x00},
169 {0xbc, 0x1000 | 0x12, 0x200 | ((int)'S'), 0x2000 | 0x12, 0x00, 0x00},
170 {0xbd, 0x1000 | 0x12, 0x200 | ((int)'D'), 0x2000 | 0x12, 0x00, 0x00},
171 {0xbe, 0x1000 | 0x12, 0x200 | ((int)'F'), 0x2000 | 0x12, 0x00, 0x00},
172 {0xbf, 0x1000 | 0x12, 0x200 | ((int)'G'), 0x2000 | 0x12, 0x00, 0x00},
173 // DA,DI,DU,DE,DO -> Z, X, C, V, B
174 {0xc0, 0x1000 | 0x12, 0x200 | ((int)'Z'), 0x2000 | 0x12, 0x00, 0x00},
175 {0xc1, 0x1000 | 0x12, 0x200 | ((int)'X'), 0x2000 | 0x12, 0x00, 0x00},
176 {0xc2, 0x1000 | 0x12, 0x200 | ((int)'C'), 0x2000 | 0x12, 0x00, 0x00},
177 {0xc3, 0x1000 | 0x12, 0x200 | ((int)'V'), 0x2000 | 0x12, 0x00, 0x00},
178 {0xc4, 0x1000 | 0x12, 0x200 | ((int)'B'), 0x2000 | 0x12, 0x00, 0x00},
179 // BA,BI,BU,BE,BO -> Y,U,I,O,P
180 {0xca, 0x1000 | 0x12, 0x200 | ((int)'Y'), 0x2000 | 0x12, 0x00, 0x00},
181 {0xcb, 0x1000 | 0x12, 0x200 | ((int)'U'), 0x2000 | 0x12, 0x00, 0x00},
182 {0xcc, 0x1000 | 0x12, 0x200 | ((int)'I'), 0x2000 | 0x12, 0x00, 0x00},
183 {0xcd, 0x1000 | 0x12, 0x200 | ((int)'O'), 0x2000 | 0x12, 0x00, 0x00},
184 {0xce, 0x1000 | 0x12, 0x200 | ((int)'P'), 0x2000 | 0x12, 0x00, 0x00},
189 typedef struct header_s {
190 uint8_t id[3]; // 'NES'
191 uint8_t ctrl_z; // control-z
193 uint8_t num_8k_vrom_banks;
197 uint32_t num_16k_rom_banks()
199 return (dummy != 0) ? dummy : 256;
201 uint32_t num_8k_rom_banks()
203 return num_16k_rom_banks() * 2;
207 return (flags_1 >> 4) | (flags_2 & 0xf0);
219 namespace FAMILYBASIC {
225 class VM : public VM_TEMPLATE
229 //csp_state_utils* state_entry;
238 FAMILYBASIC::MEMORY* memory;
239 FAMILYBASIC::APU* apu;
240 FAMILYBASIC::PPU* ppu;
245 // ----------------------------------------
247 // ----------------------------------------
252 // ----------------------------------------
253 // for emulation class
254 // ----------------------------------------
256 // drive virtual machine
259 double get_frame_rate()
261 return FRAMES_PER_SEC;
266 DEVICE *get_cpu(int index);
273 void initialize_sound(int rate, int samples);
274 uint16_t* create_sound(int* extra_frames);
275 int get_sound_buffer_ptr();
276 #ifdef USE_SOUND_VOLUME
277 void set_sound_device_volume(int ch, int decibel_l, int decibel_r);
281 void play_tape(int drv, const _TCHAR* file_path);
282 void rec_tape(int drv, const _TCHAR* file_path);
283 void close_tape(int drv);
284 bool is_tape_inserted(int drv);
285 bool is_tape_playing(int drv);
286 bool is_tape_recording(int drv);
287 int get_tape_position(int drv);
288 const _TCHAR* get_tape_message(int drv);
289 void push_play(int drv);
290 void push_stop(int drv);
291 void push_fast_forward(int drv);
292 void push_fast_rewind(int drv);
293 void push_apss_forward(int drv) {}
294 void push_apss_rewind(int drv) {}
295 bool is_frame_skippable();
297 void update_config();
298 bool process_state(FILEIO* state_fio, bool loading);
300 // ----------------------------------------
302 // ----------------------------------------
305 DEVICE* get_device(int id);
307 //DEVICE* first_device;
308 //DEVICE* last_device;