aboutsummaryrefslogtreecommitdiffstats
path: root/tools/ioemu/gui/siminterface.h
blob: 9a028470c8dde1c3dd6f6e8ecade0a32b3052c8f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
/////////////////////////////////////////////////////////////////////////
// $Id: siminterface.h,v 1.113.2.2 2004/02/06 22:14:35 danielg4 Exp $
/////////////////////////////////////////////////////////////////////////
//
// Before I can describe what this file is for, I have to make the
// distinction between a configuration interface (CI) and the VGA display
// window (VGAW).  I will try to avoid the term 'GUI' because it is unclear 
// if that means CI or VGAW, and because not all interfaces are graphical 
// anyway.
//
// The traditional Bochs screen is a window with a large VGA display panel and
// a series of buttons (floppy, cdrom, snapshot, power).  Over the years, we
// have collected many implementations of the VGAW for different environments
// and platforms; each implementation is in a separate file under gui/*:
// x.cc, win32.cc, beos.cc, macintosh.cc, etc.  The files gui.h and gui.cc
// define the platform independent part of the VGAW, leaving about 15 methods
// of the bx_gui_c class undefined.  The platform dependent file must 
// implement the remaining 15 methods.
//
// The configuration interface is relatively new, started by Bryce Denney in
// June 2001.  The CI is intended to allow the user to edit a variety of
// configuration and runtime options.  Some options, such as memory size or
// enabling the ethernet card, should only be changed before the simulation
// begins; others, such as floppy disk image, instructions per second, and
// logging options can be safely changed at runtime.  The CI allows the user to
// make these changes.  Before the CI existed, only a few things could be
// changed at runtime, all linked to clicking on the VGAW buttons.
//
// At the time that the CI was conceived, we were still debating what form the
// user interface part would take: stdin/stdout menus, a graphical application
// with menus and dialogs running in a separate thread, or even a tiny web
// server that you can connect to with a web browser.  As a result the
// interface to the CI was designed so that the user interface of the CI 
// could be replaced easily at compile time, or maybe even at runtime via
// a plugin architecture.  To this end, we kept a clear separation between
// the user interface code and the siminterface, the code that interfaces with
// the simulator.  The same siminterface is used all the time, while 
// different implementations of the CI can be switched in reasonably easily.
// Only the CI code uses library specific graphics and I/O functions; the
// siminterface deals in portable abstractions and callback functions.
// The first CI implementation was a series of text mode menus implemented in
// control.cc.
//
// The configuration interface MUST use the siminterface methods to access the
// simulator.  It should not modify settings in some device with code like
// bx_floppy.s.media[2].heads = 17.  If such access is needed, then a
// siminterface method should be written to make the change on the CI's behalf.
// This separation is enforced by the fact that the CI does not even include
// bochs.h.  You'll notice that control.cc include osdep.h, control.h, and
// siminterface.h, so it doesn't know what bx_floppy or bx_cpu_c are.  I'm sure
// some people will say is overly restrictive and/or annoying.  When I set it
// up this way, we were still talking about making the CI in a seperate
// process, where direct method calls would be impossible.  Also, we have been
// considering turning devices into plugin modules which are dynamically 
// linked.  Any direct references to something like bx_floppy.s.media[2].heads
// would have to be reworked before a plugin interface was possible as well.
//
// The siminterface is the glue between the CI and the simulator.  There is
// just one global instance of the siminterface object, which can be referred
// to by the global variable bx_simulator_interface_c *SIM; The base class
// bx_simulator_interface_c, contains only virtual functions and it defines the
// interface that the CI is allowed to use.  In siminterface.cc, a class
// called bx_real_sim_c is defined with bx_simulator_interface_c as its parent
// class.  Bx_real_sim_c implements each of the functions.  The separation into
// parent class and child class leaves the possibility of making a different
// child class that talks to the simulator in a different way (networking for
// example).  If you were writing a user interface in a separate process, you
// could define a subclass of bx_simulator_interface_c called
// bx_siminterface_proxy_c which opens up a network port and turns all method
// calls into network sends and receives.  Because the interface is defined
// entirely by the base class, the code that calls the methods would not know
// the difference.
//
// An important part of the siminterface implementation is the use of parameter
// classes, or bx_param_*.  The parameter classes are described below, where
// they are declared.  Search for "parameter classes" below for detals.
//
// Also this header file declares data structures for certain events that pass
// between the siminterface and the CI.  Search for "event structures" below.



//////////////////////////////////////////////////////
// BX_UI_TEXT should be set to 1 when the text mode configuration interface
// is compiled in.  This gives each type of parameter a text_print and text_ask
// method (defined in gui/control.cc) so that you can call text_ask() on any
// kind of parameter to ask the user to edit the value.
//
// I have been considering whether to use the same strategy for the
// wxWindows interface, but I'm not sure if I like it.  One problem is
// that in order to declare member functions that are useful for
// wxWindows, the wxWindows header files would have to be included
// before the param object definitions.  That means that all the
// wxwindows headers would have be included when compiling every
// single bochs file.  One of the things I like about the separation
// between the simulator and CI is that the two parts can be
// compiled without any knowledge of the other.  Bochs doesn't include
// <wx.h>, and the wxwindows CI (wxmain.cc) doesn't need to include <bochs.h>.
// Aside from making compiles faster, this enforces the use of the siminterface
// so it keeps the interface clean (important when we may have multiple UI
// implementations for example).  This argues for keeping UI-specific
// structures out of the simulator interface.  It certainly works ok for the
// text interface, but that's because FILE* is standard and portable.
#define BX_UI_TEXT 1

//////////////////////////////////////////////////////

// list of possible types for bx_param_c and descendant objects
typedef enum {
  BXT_OBJECT = 201,
  BXT_PARAM,
  BXT_PARAM_NUM,
  BXT_PARAM_BOOL,
  BXT_PARAM_ENUM,
  BXT_PARAM_STRING,
  BXT_LIST
} bx_objtype;

// list if parameter id values.  The actual values are not important;
// it's only important that they all be different from each other.
typedef enum {
  BXP_NULL = 301,
  BXP_IPS,
  BXP_REALTIME_PIT,
  BXP_TEXT_SNAPSHOT_CHECK,
  BXP_VGA_UPDATE_INTERVAL,
  BXP_MOUSE_ENABLED,
  BXP_MEM_SIZE,
  BXP_ROM_PATH,
  BXP_ROM_ADDRESS,
  BXP_VGA_ROM_PATH,
  BXP_OPTROM1_PATH,
  BXP_OPTROM2_PATH,
  BXP_OPTROM3_PATH,
  BXP_OPTROM4_PATH,
  BXP_OPTROM1_ADDRESS,
  BXP_OPTROM2_ADDRESS,
  BXP_OPTROM3_ADDRESS,
  BXP_OPTROM4_ADDRESS,
  BXP_KBD_SERIAL_DELAY,
  BXP_KBD_PASTE_DELAY,
  BXP_KBD_TYPE,
  BXP_FLOPPY_CMD_DELAY,
  BXP_FLOPPYA_DEVTYPE,
  BXP_FLOPPYA_PATH,
  BXP_FLOPPYA_TYPE,
  BXP_FLOPPYA_STATUS,
  BXP_FLOPPYA,
  BXP_FLOPPYB_DEVTYPE,
  BXP_FLOPPYB_PATH,
  BXP_FLOPPYB_TYPE,
  BXP_FLOPPYB_STATUS,
  BXP_FLOPPYB,

  BXP_ATA0_MENU,
  BXP_ATA1_MENU,
  BXP_ATA2_MENU,
  BXP_ATA3_MENU,
#define BXP_ATAx_MENU(i) (BXP_ATA0_MENU + (i))
  BXP_ATA0,
  BXP_ATA1,
  BXP_ATA2,
  BXP_ATA3,
#define BXP_ATAx(i) (BXP_ATA0 + (i))
  BXP_ATA0_PRESENT,
  BXP_ATA1_PRESENT,
  BXP_ATA2_PRESENT,
  BXP_ATA3_PRESENT,
#define BXP_ATAx_PRESENT(i) (BXP_ATA0_PRESENT + (i))
  BXP_ATA0_IOADDR1,
  BXP_ATA1_IOADDR1,
  BXP_ATA2_IOADDR1,
  BXP_ATA3_IOADDR1,
#define BXP_ATAx_IOADDR1(i) (BXP_ATA0_IOADDR1 + (i))
  BXP_ATA0_IOADDR2,
  BXP_ATA1_IOADDR2,
  BXP_ATA2_IOADDR2,
  BXP_ATA3_IOADDR2,
#define BXP_ATAx_IOADDR2(i) (BXP_ATA0_IOADDR2 + (i))
  BXP_ATA0_IRQ,
  BXP_ATA1_IRQ,
  BXP_ATA2_IRQ,
  BXP_ATA3_IRQ,
#define BXP_ATAx_IRQ(i) (BXP_ATA0_IRQ + (i))

  BXP_ATA0_MASTER,
  BXP_ATA0_SLAVE,
  BXP_ATA1_MASTER,
  BXP_ATA1_SLAVE,
  BXP_ATA2_MASTER,
  BXP_ATA2_SLAVE,
  BXP_ATA3_MASTER,
  BXP_ATA3_SLAVE,
#define BXP_ATAx_DEVICE(i, s) (BXP_ATA0_MASTER + (2*(i)) + (s))

#define BXP_PARAMS_PER_ATA_DEVICE 12

  BXP_ATA0_MASTER_PRESENT,
  BXP_ATA0_SLAVE_PRESENT,
  BXP_ATA1_MASTER_PRESENT,
  BXP_ATA1_SLAVE_PRESENT,
  BXP_ATA2_MASTER_PRESENT,
  BXP_ATA2_SLAVE_PRESENT,
  BXP_ATA3_MASTER_PRESENT,
  BXP_ATA3_SLAVE_PRESENT,
#define BXP_ATAx_DEVICE_PRESENT(i, s) (BXP_ATA0_MASTER_PRESENT + (2*(i)) + (s))

  BXP_ATA0_MASTER_TYPE,
  BXP_ATA0_SLAVE_TYPE,
  BXP_ATA1_MASTER_TYPE,
  BXP_ATA1_SLAVE_TYPE,
  BXP_ATA2_MASTER_TYPE,
  BXP_ATA2_SLAVE_TYPE,
  BXP_ATA3_MASTER_TYPE,
  BXP_ATA3_SLAVE_TYPE,
#define BXP_ATAx_DEVICE_TYPE(i, s) (BXP_ATA0_MASTER_TYPE + (2*(i)) + (s))

  BXP_ATA0_MASTER_MODE,
  BXP_ATA0_SLAVE_MODE,
  BXP_ATA1_MASTER_MODE,
  BXP_ATA1_SLAVE_MODE,
  BXP_ATA2_MASTER_MODE,
  BXP_ATA2_SLAVE_MODE,
  BXP_ATA3_MASTER_MODE,
  BXP_ATA3_SLAVE_MODE,
#define BXP_ATAx_DEVICE_MODE(i, s) (BXP_ATA0_MASTER_MODE + (2*(i)) + (s))

  BXP_ATA0_MASTER_PATH,
  BXP_ATA0_SLAVE_PATH,
  BXP_ATA1_MASTER_PATH,
  BXP_ATA1_SLAVE_PATH,
  BXP_ATA2_MASTER_PATH,
  BXP_ATA2_SLAVE_PATH,
  BXP_ATA3_MASTER_PATH,
  BXP_ATA3_SLAVE_PATH,
#define BXP_ATAx_DEVICE_PATH(i, s) (BXP_ATA0_MASTER_PATH + (2*(i)) + (s))

  BXP_ATA0_MASTER_CYLINDERS,
  BXP_ATA0_SLAVE_CYLINDERS,
  BXP_ATA1_MASTER_CYLINDERS,
  BXP_ATA1_SLAVE_CYLINDERS,
  BXP_ATA2_MASTER_CYLINDERS,
  BXP_ATA2_SLAVE_CYLINDERS,
  BXP_ATA3_MASTER_CYLINDERS,
  BXP_ATA3_SLAVE_CYLINDERS,
#define BXP_ATAx_DEVICE_CYLINDERS(i, s) (BXP_ATA0_MASTER_CYLINDERS + (2*(i)) + (s))

  BXP_ATA0_MASTER_HEADS,
  BXP_ATA0_SLAVE_HEADS,
  BXP_ATA1_MASTER_HEADS,
  BXP_ATA1_SLAVE_HEADS,
  BXP_ATA2_MASTER_HEADS,
  BXP_ATA2_SLAVE_HEADS,
  BXP_ATA3_MASTER_HEADS,
  BXP_ATA3_SLAVE_HEADS,
#define BXP_ATAx_DEVICE_HEADS(i, s) (BXP_ATA0_MASTER_HEADS + (2*(i)) + (s))

  BXP_ATA0_MASTER_SPT,
  BXP_ATA0_SLAVE_SPT,
  BXP_ATA1_MASTER_SPT,
  BXP_ATA1_SLAVE_SPT,
  BXP_ATA2_MASTER_SPT,
  BXP_ATA2_SLAVE_SPT,
  BXP_ATA3_MASTER_SPT,
  BXP_ATA3_SLAVE_SPT,
#define BXP_ATAx_DEVICE_SPT(i, s) (BXP_ATA0_MASTER_SPT + (2*(i)) + (s))

  BXP_ATA0_MASTER_STATUS,
  BXP_ATA0_SLAVE_STATUS,
  BXP_ATA1_MASTER_STATUS,
  BXP_ATA1_SLAVE_STATUS,
  BXP_ATA2_MASTER_STATUS,
  BXP_ATA2_SLAVE_STATUS,
  BXP_ATA3_MASTER_STATUS,
  BXP_ATA3_SLAVE_STATUS,
#define BXP_ATAx_DEVICE_STATUS(i, s) (BXP_ATA0_MASTER_STATUS + (2*(i)) + (s))

  BXP_ATA0_MASTER_MODEL,
  BXP_ATA0_SLAVE_MODEL,
  BXP_ATA1_MASTER_MODEL,
  BXP_ATA1_SLAVE_MODEL,
  BXP_ATA2_MASTER_MODEL,
  BXP_ATA2_SLAVE_MODEL,
  BXP_ATA3_MASTER_MODEL,
  BXP_ATA3_SLAVE_MODEL,
#define BXP_ATAx_DEVICE_MODEL(i, s) (BXP_ATA0_MASTER_MODEL + (2*(i)) + (s))

  BXP_ATA0_MASTER_BIOSDETECT,
  BXP_ATA0_SLAVE_BIOSDETECT,
  BXP_ATA1_MASTER_BIOSDETECT,
  BXP_ATA1_SLAVE_BIOSDETECT,
  BXP_ATA2_MASTER_BIOSDETECT,
  BXP_ATA2_SLAVE_BIOSDETECT,
  BXP_ATA3_MASTER_BIOSDETECT,
  BXP_ATA3_SLAVE_BIOSDETECT,
#define BXP_ATAx_DEVICE_BIOSDETECT(i, s) (BXP_ATA0_MASTER_BIOSDETECT + (2*(i)) + (s))

  BXP_ATA0_MASTER_TRANSLATION,
  BXP_ATA0_SLAVE_TRANSLATION,
  BXP_ATA1_MASTER_TRANSLATION,
  BXP_ATA1_SLAVE_TRANSLATION,
  BXP_ATA2_MASTER_TRANSLATION,
  BXP_ATA2_SLAVE_TRANSLATION,
  BXP_ATA3_MASTER_TRANSLATION,
  BXP_ATA3_SLAVE_TRANSLATION,
#define BXP_ATAx_DEVICE_TRANSLATION(i, s) (BXP_ATA0_MASTER_TRANSLATION + (2*(i)) + (s))

  BXP_ATA0_MASTER_JOURNAL,
  BXP_ATA0_SLAVE_JOURNAL,
  BXP_ATA1_MASTER_JOURNAL,
  BXP_ATA1_SLAVE_JOURNAL,
  BXP_ATA2_MASTER_JOURNAL,
  BXP_ATA2_SLAVE_JOURNAL,
  BXP_ATA3_MASTER_JOURNAL,
  BXP_ATA3_SLAVE_JOURNAL,
#define BXP_ATAx_DEVICE_JOURNAL(i, s) (BXP_ATA0_MASTER_JOURNAL + (2*(i)) + (s))

#define BXP_PARAMS_PER_SERIAL_PORT 2
  BXP_COM1_ENABLED,
  BXP_COM1_PATH,
  BXP_COM2_ENABLED,
  BXP_COM2_PATH,
  BXP_COM3_ENABLED,
  BXP_COM3_PATH,
  BXP_COM4_ENABLED,
  BXP_COM4_PATH,
#define BXP_PARAMS_PER_USB_HUB 3
  BXP_USB1_ENABLED,
  BXP_USB1_IOADDR,
  BXP_USB1_IRQ,
  BXP_PRIVATE_COLORMAP,
  BXP_FULLSCREEN,
  BXP_SCREENMODE,
  BXP_I440FX_SUPPORT,
  BXP_NEWHARDDRIVESUPPORT,
  BXP_LOG_FILENAME,
  BXP_LOG_PREFIX,
  BXP_DEBUGGER_LOG_FILENAME,
  BXP_CMOS_PATH,
  BXP_CMOS_IMAGE,
  BXP_CLOCK,
  BXP_CLOCK_TIME0,
  BXP_CLOCK_SYNC,
  BXP_LOAD32BITOS_WHICH,
  BXP_LOAD32BITOS_PATH,
  BXP_LOAD32BITOS_IOLOG,
  BXP_LOAD32BITOS_INITRD,
  BXP_LOAD32BITOS,
  BXP_BOOTDRIVE,
  BXP_FLOPPYSIGCHECK,
  BXP_MENU_MAIN,
  BXP_MENU_MEMORY,
  BXP_MENU_INTERFACE,
  BXP_MENU_DISK,
  BXP_MENU_SERIAL_PARALLEL,
  BXP_MENU_SOUND,
  BXP_MENU_KEYBOARD,
  BXP_MENU_MISC,
  BXP_MENU_MISC_2,
  BXP_MENU_RUNTIME,
  BXP_MAX_IPS,
  BXP_NE2K_PRESENT,
  BXP_NE2K_IOADDR,
  BXP_NE2K_IRQ,
  BXP_NE2K_MACADDR,
  BXP_NE2K_ETHMOD,
  BXP_NE2K_ETHDEV,
  BXP_NE2K_SCRIPT,
  BXP_NE2K,
  BXP_SB16_PRESENT,
  BXP_SB16_MIDIFILE,
  BXP_SB16_WAVEFILE,
  BXP_SB16_LOGFILE,
  BXP_SB16_MIDIMODE,
  BXP_SB16_WAVEMODE,
  BXP_SB16_LOGLEVEL,
  BXP_SB16_DMATIMER,
  BXP_SB16,
#define BXP_PARAMS_PER_PARALLEL_PORT 2
  BXP_PARPORT1_ENABLED,
  BXP_PARPORT1_OUTFILE,
  BXP_PARPORT2_ENABLED,
  BXP_PARPORT2_OUTFILE,
  BXP_KEYBOARD_USEMAPPING,
  BXP_KEYBOARD_MAP,
  BXP_KEYBOARD,
  BXP_USER_SHORTCUT,
  BXP_ASK_FOR_PATHNAME,   // for general file selection dialog
  BXP_BOCHS_START,        // How Bochs starts
  // experiment: add params for CPU registers
  BXP_CPU_PARAMETERS,
  BXP_CPU_EAX,
  BXP_CPU_EBX,
  BXP_CPU_ECX,
  BXP_CPU_EDX,
  BXP_CPU_EBP,
  BXP_CPU_ESI,
  BXP_CPU_EDI,
  BXP_CPU_ESP,
  BXP_CPU_EIP,
  BXP_CPU_SEG_CS,
  BXP_CPU_SEG_DS,
  BXP_CPU_SEG_SS,
  BXP_CPU_SEG_ES,
  BXP_CPU_SEG_FS,
  BXP_CPU_SEG_GS,
  BXP_CPU_SEG_LDTR,
  BXP_CPU_SEG_TR,
  BXP_CPU_GDTR_BASE,
  BXP_CPU_GDTR_LIMIT,
  BXP_CPU_IDTR_BASE,
  BXP_CPU_IDTR_LIMIT,
  BXP_CPU_EFLAGS,
  BXP_CPU_EFLAGS_ID,
  BXP_CPU_EFLAGS_VIP,
  BXP_CPU_EFLAGS_VIF,
  BXP_CPU_EFLAGS_AC,
  BXP_CPU_EFLAGS_VM,
  BXP_CPU_EFLAGS_RF,
  BXP_CPU_EFLAGS_NT,
  BXP_CPU_EFLAGS_IOPL,
  BXP_CPU_EFLAGS_OF,
  BXP_CPU_EFLAGS_DF,
  BXP_CPU_EFLAGS_IF,
  BXP_CPU_EFLAGS_TF,
  BXP_CPU_EFLAGS_SF,
  BXP_CPU_EFLAGS_ZF,
  BXP_CPU_EFLAGS_AF,
  BXP_CPU_EFLAGS_PF,
  BXP_CPU_EFLAGS_CF,
  BXP_CPU_DR0,
  BXP_CPU_DR1,
  BXP_CPU_DR2,
  BXP_CPU_DR3,
  BXP_CPU_DR6,
  BXP_CPU_DR7,
  BXP_CPU_TR3,
  BXP_CPU_TR4,
  BXP_CPU_TR5,
  BXP_CPU_TR6,
  BXP_CPU_TR7,
  BXP_CPU_CR0,
  BXP_CPU_CR1,
  BXP_CPU_CR2,
  BXP_CPU_CR3,
  BXP_CPU_CR4,
  // a few parameters for the keyboard
  BXP_KBD_PARAMETERS,
  BXP_KBD_PARE,
  BXP_KBD_TIM ,
  BXP_KBD_AUXB,
  BXP_KBD_KEYL,
  BXP_KBD_C_D,
  BXP_KBD_SYSF,
  BXP_KBD_INPB,
  BXP_KBD_OUTB,
  BXP_KBD_TIMER_PENDING,
  BXP_KBD_IRQ1_REQ,
  BXP_KBD_IRQ12_REQ,
#if BX_DEBUGGER
  // in debugger, is the simulation running (continue command) or waiting.
  // This is only modified by debugger code, not by the user.
  BXP_DEBUG_RUNNING,
#endif
  BXP_SEL_CONFIG_INTERFACE,
  BXP_SEL_DISPLAY_LIBRARY,
  BXP_THIS_IS_THE_LAST    // used to determine length of list
} bx_id;

// use x=1,2,3,4
#define BXP_COMx_ENABLED(x) \
   (bx_id)(BXP_COM1_ENABLED + (((x)-1)*BXP_PARAMS_PER_SERIAL_PORT))
#define BXP_COMx_PATH(x) \
  (bx_id)(BXP_COM1_PATH + (((x)-1)*BXP_PARAMS_PER_SERIAL_PORT))

// use x=1
#define BXP_USBx_ENABLED(x) \
   (bx_id)(BXP_USB1_ENABLED + (((x)-1)*BXP_PARAMS_PER_USB_HUB))
#define BXP_USBx_IOADDR(x) \
   (bx_id)(BXP_USB1_IOADDR + (((x)-1)*BXP_PARAMS_PER_USB_HUB))
#define BXP_USBx_IRQ(x) \
   (bx_id)(BXP_USB1_IRQ + (((x)-1)*BXP_PARAMS_PER_USB_HUB))

// use x=1,2
#define BXP_PARPORTx_ENABLED(x) \
  (bx_id)(BXP_PARPORT1_ENABLED + (((x)-1)*BXP_PARAMS_PER_PARALLEL_PORT))
#define BXP_PARPORTx_OUTFILE(x) \
  (bx_id)(BXP_PARPORT1_OUTFILE + (((x)-1)*BXP_PARAMS_PER_PARALLEL_PORT))

typedef enum {
  BX_TOOLBAR_UNDEFINED,
  BX_TOOLBAR_FLOPPYA,
  BX_TOOLBAR_FLOPPYB,
  BX_TOOLBAR_CDROMD,
  BX_TOOLBAR_RESET,
  BX_TOOLBAR_POWER,
  BX_TOOLBAR_COPY,
  BX_TOOLBAR_PASTE,
  BX_TOOLBAR_SNAPSHOT,
  BX_TOOLBAR_CONFIG,
  BX_TOOLBAR_MOUSE_EN,
  BX_TOOLBAR_USER
} bx_toolbar_buttons;

// Log level defines
typedef enum {
  LOGLEV_DEBUG = 0,
  LOGLEV_INFO,
  LOGLEV_ERROR,
  LOGLEV_PANIC,
  LOGLEV_PASS,
  N_LOGLEV
} bx_log_levels;

// types of reset
#define BX_RESET_SOFTWARE 10
#define BX_RESET_HARDWARE 11

//cdrom
#define BX_EJECTED   10
#define BX_INSERTED  11

// boot devices
#define BX_BOOT_FLOPPYA 0
#define BX_BOOT_DISKC   1
#define BX_BOOT_CDROM   2

// loader hack
#define Load32bitOSNone        0
#define Load32bitOSLinux       1
#define Load32bitOSNullKernel  2 // being developed for plex86
#define Load32bitOSLast        2

///////////////////////////////////////////////////////////////////
// event structures for communication between simulator and CI
///////////////////////////////////////////////////////////////////
// Because the CI (configuration interface) might be in a different
// thread or even a different process, we pass events encoded in data
// structures to it instead of just calling functions.  Each type of
// event is declared as a different structure, and then all those
// structures are squished into a union in BxEvent.  (BTW, this is
// almost exactly how X windows event structs work.)
//
// These are simple structs, unblemished by C++ methods and tricks.
// No matter what event type it is, we allocate a BxEvent for each
// one, as opposed to trying to save a few bytes on small events by
// allocating only the bytes necessary for it.  This makes it easy and
// fast to store events in a queue, like this
//   BxEvent event_queue[MAX_EVENTS];
//
// Events come in two varieties: synchronous and asynchronous.  We
// have to worry about sync and async events because the CI and the
// simulation may be running in different threads.  An async event is
// the simplest.  Whichever thread originates the event just builds
// the data structure, sends it, and then continues with its business.
// Async events can go in either direction.  Synchronous events
// require the other thread to "respond" before the originating thread
// can continue.  It's like a function with a return value; you can't
// continue until you get the return value back.
//
// Examples:
//
// async event: In the wxWindows implementation, both the CI and the
// VGAW operate in the wxWindows GUI thread.  When the user presses a
// key, wxWindows sends a wxKeyEvent to the VGAW event handler code in
// wx.cc.  The VGAW handler then builds a BxEvent with
// type=BX_ASYNC_EVT_KEY, and fills in the bx_key and raw_scancode
// fields.  The asynchronous event is placed on the event_queue for
// the simulator, then the VGAW handler returns.  (With wxWindows and
// many other graphical libaries, the event handler must return
// quickly because the window will not be updated until it's done.)
// Some time later, the simulator reaches the point where it checks
// for new events from the user (actually controlled by
// bx_keyb_c::periodic() in iodev/keyboard.cc) and calls
// bx_gui.handle_events().  Then all the events in the queue are
// processed by the simulator.  There is no "response" sent back to
// the originating thread.
//
// sync event: Sometimes the simulator reaches a point where it needs
// to ask the user how to proceed.  In this case, the simulator sends
// a synchronous event because it requires a response before it can 
// continue.  It builds an event structure, perhaps with type
// BX_SYNC_EVT_ASK_PARAM, sends it to the user interface 
// using the event handler function defined by set_notify_callback(),
// and pauses the simulation.  The user interface asks the user the
// question, and puts the answer into the BxEvent.retcode field.  The
// event handler function returns the modified BxEvent with retcode
// filled in, and the simulation continues.  The details of this
// transaction can be complicated if the simulation and CI are not
// in the same thread, but the behavior is as described.
//

///// types and definitions used in event structures

#define BX_EVT_IS_ASYNC(type) ((type) > __ALL_EVENTS_BELOW_ARE_ASYNC__)

typedef enum {
  __ALL_EVENTS_BELOW_ARE_SYNCHRONOUS__ = 2000,
  BX_SYNC_EVT_GET_PARAM,          // CI -> simulator -> CI
  BX_SYNC_EVT_ASK_PARAM,          // simulator -> CI -> simulator
  BX_SYNC_EVT_TICK,               // simulator -> CI, wait for response.
  BX_SYNC_EVT_LOG_ASK,            // simulator -> CI, wait for response.
  BX_SYNC_EVT_GET_DBG_COMMAND,    // simulator -> CI, wait for response.
  __ALL_EVENTS_BELOW_ARE_ASYNC__,
  BX_ASYNC_EVT_KEY,               // vga window -> simulator
  BX_ASYNC_EVT_MOUSE,             // vga window -> simulator
  BX_ASYNC_EVT_SET_PARAM,         // CI -> simulator
  BX_ASYNC_EVT_LOG_MSG,           // simulator -> CI
  BX_ASYNC_EVT_DBG_MSG,           // simulator -> CI
  BX_ASYNC_EVT_VALUE_CHANGED,     // simulator -> CI
  BX_ASYNC_EVT_TOOLBAR,           // CI -> simulator
  BX_ASYNC_EVT_REFRESH            // simulator -> CI
} BxEventType;

typedef union {
  Bit32s s32;
  char *charptr;
} AnyParamVal;

// Define substructures which make up the interior of BxEvent.  The
// substructures, such as BxKeyEvent or BxMouseEvent, should never be
// allocated on their own.  They are only intended to be used within
// the union in the BxEvent structure.

// Event type: BX_SYNC_EVT_TICK
//
// A tick event is synchronous, sent from the simulator to the GUI.  The
// event doesn't do anything visible.  Primarily it gives the GUI a chance
// to tell the simulator to quit, if necessary.  There may be other uses
// for the tick in the future, such as giving some kind of regular
// status report or mentioning watched values that changed, but so far
// it's just for that one thing.  There is no data associated with a
// tick event.

// Event type: BX_ASYNC_EVT_KEY
//
// A key event can be sent from the VGA window to the Bochs simulator.  
// It is asynchronous.
typedef struct {
  // what was pressed?  This is a BX_KEY_* value.  For key releases,
  // BX_KEY_RELEASED is ORed with the base BX_KEY_*.
  Bit32u bx_key;
  bx_bool raw_scancode;
} BxKeyEvent;

// Event type: BX_ASYNC_EVT_MOUSE
//
// A mouse event can be sent from the VGA window to the Bochs
// simulator.  It is asynchronous.  Currently unused because mouse
// events aren't implemented in our wxWindows code yet.
typedef struct {
  // type is BX_EVT_MOUSE
  Bit16s dx, dy;           // mouse motion delta
  Bit8u buttons;           // which buttons are pressed.
                           // bit 0: 1=left button down, 0=up
                           // bit 1: 1=right button down, 0=up
} BxMouseEvent;

// Event type: BX_SYNC_EVT_GET_PARAM, BX_ASYNC_EVT_SET_PARAM
//
// Parameter set/get events are initiated by the CI, since Bochs can
// always access the parameters directly.  So far, I haven't used
// these event types.  In the CI I just call
// SIM->get_param(parameter_id) to get a pointer to the bx_param_c
// object and then call the get/set methods.  This is okay for
// configuration since bochs is not running.  However it could be
// dangerous for the GUI thread to poke around in Bochs structures
// while the thread is running.  For these cases, I may have to be
// more careful and actually build get/set events and place them on
// Bochs's event queue to be processed during SIM->periodic() or
// something.
typedef struct {
  // type is BX_EVT_GET_PARAM, BX_EVT_SET_PARAM
  class bx_param_c *param;         // pointer to param structure
  AnyParamVal val;
} BxParamEvent;

// Event type: BX_SYNC_EVT_ASK_PARAM
// Synchronous event sent from the simulator to the CI.  This tells the
// CI to ask the user to choose the value of a parameter.  The CI may 
// need to discover the type of parameter so that it can use the right
// kind of graphical display.  The BxParamEvent is used for these events
// too.
// FIXME: at the moment the GUI implements the ASK_PARAM event for just
// a few parameter types.  I need to implement the event for all parameter
// types.

// Event type: BX_ASYNC_EVT_VALUE_CHANGED
// 
// Asynchronous event sent from the simulator to the CI, telling it that
// some value that it (hopefully) cares about has changed.  This isn't
// being used yet, but a good example is in a debugger interface, you might
// want to maintain a reasonably current display of the PC or some other
// simulation state.  The CI would set some kind of event mask (which
// doesn't exist now of course) and then when certain values change, the
// simulator would send this event so that the CI can update.  We may need
// some kind of "flow control" since the simulator will be able to produce
// new events much faster than the gui can accept them.

// Event type: BX_ASYNC_EVT_LOG_MSG   (unused)
//
// Asynchronous event from the simulator to the CI.  When a BX_PANIC,
// BX_ERROR, BX_INFO, or BX_DEBUG is found in the simulator code, this 
// event type can be used to inform the CI of the condition.  There is
// no point in sending messages to the CI that will not be displayed; these
// would only slow the simulation.  So we will need some mechanism for 
// choosing what kinds of events will be delivered to the CI.  Normally,
// you wouldn't want to look at the log unless something is going wrong.
// At that point, you might want to open up a window to watch the debug
// messages from one or two devices only.
//
// Idea: Except for panics that require user attention to continue, it
// might be most efficient to just append log messages to a file.
// When the user wants to look at the log messages, the gui can reopen
// the file (read only), skip to the end, and look backward for a
// reasonable number of lines to display (200?).  This allows it to
// skip over huge bursts of log entries without allocating memory,
// synchronizing threads, etc. for each.
typedef struct {
  Bit8u level;
  const char *prefix;
  const char *msg;
} BxLogMsgEvent;

// Event type: BX_ASYNC_EVT_DBG_MSG   (unused)
//
// Also uses BxLogMsgEvent, but this is a message to be displayed in
// the debugger history window.

// Event type: BX_SYNC_EVT_LOG_ASK
//
// This is a synchronous version of BX_ASYNC_EVT_LOG_MSG, which is used
// when the "action=ask" setting is used.  If the simulator runs into a
// panic, it sends a synchronous BX_SYNC_EVT_LOG_ASK to the CI to be
// displayed.  The CI shows a dialog that asks if the user wants to 
// continue, quit, etc. and sends the answer back to the simulator.
// This event also uses BxLogMsgEvent.
enum {
  BX_LOG_ASK_CHOICE_CONTINUE,
  BX_LOG_ASK_CHOICE_CONTINUE_ALWAYS,
  BX_LOG_ASK_CHOICE_DIE,
  BX_LOG_ASK_CHOICE_DUMP_CORE,
  BX_LOG_ASK_CHOICE_ENTER_DEBUG,
  BX_LOG_ASK_N_CHOICES
};

// Event type: BX_SYNC_EVT_GET_DBG_COMMAND
//
// This is a synchronous event sent from the simulator to the debugger
// requesting the next action.  In a text mode debugger, this would prompt
// the user for the next command.  When a new command is ready, the
// synchronous event is sent back with its fields filled in.
typedef struct {
  char *command;   // null terminated string. allocated by debugger interface
                   // with new operator, freed by simulator with delete.
} BxDebugCommand;



// Event type: BX_EVT_TOOLBAR
// Asynchronous event from the VGAW to the simulator, sent when the user
// clicks on a toolbar button.  This may one day become something more 
// general, like a command event, but at the moment it's only needed for
// the toolbar events.
typedef struct {
  bx_toolbar_buttons button;
  bool on;   // for toggling buttons, on=true means the toolbar button is
             // pressed. on=false means it is not pressed.
} BxToolbarEvent;

// The BxEvent structure should be used for all events.  Every event has
// a type and a spot for a return code (only used for synchronous events).
typedef struct {
  BxEventType type; // what kind is this?
  Bit32s retcode;   // sucess or failure. only used for synchronous events.
  union {
    BxKeyEvent key;
    BxMouseEvent mouse;
    BxParamEvent param;
    BxLogMsgEvent logmsg;
    BxToolbarEvent toolbar;
    BxDebugCommand debugcmd;
  } u;
} BxEvent;


////////////////////////////////////////////////////////////////////
// parameter classes: bx_param_c and family
////////////////////////////////////////////////////////////////////
//
// All variables that can be configured through the CI are declared as
// "parameters" or objects of type bx_param_*.  There is a bx_param_*
// class for each type of data that the user would need to see and
// edit, e.g. integer, boolean, enum, string, filename, or list of
// other parameters.  The purpose of the bx_param_* class, in addition
// to storing the parameter's value, is to hold the name, description,
// and constraints on the value.  The bx_param_* class should hold
// everything that the CI would need to display the value and allow
// the user to modify it.  For integer parameters, the minimum and
// maximum allowed value can be defined, and the base in which it
// should be displayed and interpreted.  For enums, the
// bx_param_enum_c structure includes the list of values which the
// parameter can have.
//
// Also, some parameter classes support get/set callback functions to
// allow arbitrary code to be executed when the parameter is get/set. 
// An example of where this is useful: if you disable the NE2K card,
// the set() handler for that parameter can tell the user interface
// that the NE2K's irq, I/O address, and mac address should be
// disabled (greyed out, hidden, or made inaccessible).  The get/set
// methods can also check if the set() value is acceptable using
// whatever means and override it.
//
// The parameter concept is similar to the use of parameters in JavaBeans.

class bx_object_c;
class bx_param_c;
class bx_param_num_c;
class bx_param_enum_c;
class bx_param_bool_c;
class bx_param_string_c;
class bx_param_filename_c;
class bx_list_c;

class BOCHSAPI bx_object_c {
private:
  bx_id id;
  bx_objtype type;
protected:
  void set_type (bx_objtype type);
public:
  bx_object_c (bx_id id);
  bx_id get_id () { return id; }
  Bit8u get_type () { return type; }
};

class BOCHSAPI bx_param_c : public bx_object_c {
  BOCHSAPI_CYGONLY static const char *default_text_format;
protected:
  char *name;
  char *description;
  char *label; // label string for text menus and gui dialogs
  const char *text_format;  // printf format string. %d for ints, %s for strings, etc.
  char *ask_format;  // format string for asking for a new value
  int runtime_param;
  int enabled;
public:
  bx_param_c (bx_id id, char *name, char *description);
  void set_format (const char *format) {text_format = format;}
  const char *get_format () {return text_format;}
  void set_ask_format (char *format) {ask_format = format; }
  char *get_ask_format () {return ask_format;}
  void set_label (char *text) {label = text;}
  char *get_label () {return label;}
  void set_runtime_param (int val) { runtime_param = val; }
  int get_runtime_param () { return runtime_param; }
  char *get_name () { return name; }
  char *get_description () { return description; }
  int get_enabled () { return enabled; }
  virtual void set_enabled (int enabled) { this->enabled = enabled; }
  void reset () {}
  int getint () {return -1;}
  static const char* set_default_format (const char *f);
  static const char *get_default_format () { return default_text_format; }
  virtual bx_list_c *get_dependent_list () { return NULL; }
#if BX_UI_TEXT
  virtual void text_print (FILE *fp) {}
  virtual int text_ask (FILE *fpin, FILE *fpout) {return -1;}
#endif
};

typedef Bit64s (*param_event_handler)(class bx_param_c *, int set, Bit64s val);
typedef int (*param_enable_handler)(class bx_param_c *, int en);

class BOCHSAPI bx_param_num_c : public bx_param_c {
  BOCHSAPI_CYGONLY static Bit32u default_base;
  // The dependent_list is initialized to NULL.  If dependent_list is modified
  // to point to a bx_list_c of other parameters, the set() method of
  // bx_param_bool_c will enable those parameters when this bool is true, and
  // disable them when this bool is false.
  bx_list_c *dependent_list;
  void update_dependents ();
protected:
  Bit64s min, max, initial_val;
  union _uval_ {
    Bit64s number;   // used by bx_param_num_c
    Bit64s *p64bit;  // used by bx_shadow_num_c
    Bit32s *p32bit;  // used by bx_shadow_num_c
    Bit16s *p16bit;  // used by bx_shadow_num_c
    Bit8s  *p8bit;    // used by bx_shadow_num_c
    bx_bool *pbool;  // used by bx_shadow_bool_c
  } val;
  param_event_handler handler;
  param_enable_handler enable_handler;
  int base;
  Bit32u options;
public:
  enum {
    // When a bx_param_num_c is displayed in dialog, USE_SPIN_CONTROL controls
    // whether a spin control should be used instead of a simple text control.
    USE_SPIN_CONTROL = (1<<0)
  } bx_numopt_bits;
  bx_param_num_c (bx_id id,
      char *name,
      char *description,
      Bit64s min, Bit64s max, Bit64s initial_val);
  void reset ();
  void set_handler (param_event_handler handler);
  void set_enable_handler (param_enable_handler handler);
  virtual bx_list_c *get_dependent_list () { return dependent_list; }
  void set_dependent_list (bx_list_c *l);
  virtual void set_enabled (int enabled);
  virtual Bit32s get () { return (Bit32s) get64(); }
  virtual Bit64s get64 ();
  virtual void set (Bit64s val);
  void set_base (int base) { this->base = base; }
  void set_initial_val (Bit64s initial_val);
  int get_base () { return base; }
  void set_range (Bit64u min, Bit64u max);
  Bit64s get_min () { return min; }
  Bit64s get_max () { return max; }
  static Bit32u set_default_base (Bit32u val);
  static Bit32u get_default_base () { return default_base; }
  void set_options (Bit32u options) { this->options = options; }
  Bit32u get_options () { return options; }
#if BX_UI_TEXT
  virtual void text_print (FILE *fp);
  virtual int text_ask (FILE *fpin, FILE *fpout);
#endif
};

// a bx_shadow_num_c is like a bx_param_num_c except that it doesn't
// store the actual value with its data. Instead, it uses val.p32bit
// to keep a pointer to the actual data.  This is used to register
// existing variables as parameters, without have to access it via
// set/get methods.
class BOCHSAPI bx_shadow_num_c : public bx_param_num_c {
  Bit8u varsize;   // must be 64, 32, 16, or 8
  Bit8u lowbit;   // range of bits associated with this param
  Bit64u mask;     // mask is ANDed with value before it is returned from get
public:
  bx_shadow_num_c (bx_id id,
      char *name,
      char *description,
      Bit64s *ptr_to_real_val,
      Bit8u highbit = 63,
      Bit8u lowbit = 0);
  bx_shadow_num_c (bx_id id,
      char *name,
      char *description,
      Bit64u *ptr_to_real_val,
      Bit8u highbit = 63,
      Bit8u lowbit = 0);
  bx_shadow_num_c (bx_id id,
      char *name,
      char *description,
      Bit32s *ptr_to_real_val,
      Bit8u highbit = 31,
      Bit8u lowbit = 0);
  bx_shadow_num_c (bx_id id,
      char *name,
      char *description,
      Bit32u *ptr_to_real_val,
      Bit8u highbit = 31,
      Bit8u lowbit = 0);
  bx_shadow_num_c (bx_id id,
      char *name,
      char *description,
      Bit16s *ptr_to_real_val,
      Bit8u highbit = 15,
      Bit8u lowbit = 0);
  bx_shadow_num_c (bx_id id,
      char *name,
      char *description,
      Bit16u *ptr_to_real_val,
      Bit8u highbit = 15,
      Bit8u lowbit = 0);
  bx_shadow_num_c (bx_id id,
      char *name,
      char *description,
      Bit8s *ptr_to_real_val,
      Bit8u highbit = 7,
      Bit8u lowbit = 0);
  bx_shadow_num_c (bx_id id,
      char *name,
      char *description,
      Bit8u *ptr_to_real_val,
      Bit8u highbit = 7,
      Bit8u lowbit = 0);
  virtual Bit64s get64 ();
  virtual void set (Bit64s val);
};

class BOCHSAPI bx_param_bool_c : public bx_param_num_c {
  // many boolean variables are used to enable/disable modules.  In the
  // user interface, the enable variable should enable/disable all the
  // other parameters associated with that module.
public:
  bx_param_bool_c (bx_id id, 
      char *name,
      char *description,
      Bit64s initial_val);
#if BX_UI_TEXT
  virtual void text_print (FILE *fp);
  virtual int text_ask (FILE *fpin, FILE *fpout);
#endif
};

// a bx_shadow_bool_c is a shadow param based on bx_param_bool_c.
class BOCHSAPI bx_shadow_bool_c : public bx_param_bool_c {
  // each bit of a bitfield can be a separate value.  bitnum tells which
  // bit is used.  get/set will only modify that bit.
  Bit8u bitnum;
public:
  bx_shadow_bool_c (bx_id id,
      char *name,
      char *description,
      bx_bool *ptr_to_real_val,
      Bit8u bitnum = 0);
  virtual Bit64s get64 ();
  virtual void set (Bit64s val);
};


class BOCHSAPI bx_param_enum_c : public bx_param_num_c {
  char **choices;
public:
  bx_param_enum_c (bx_id id, 
      char *name,
      char *description,
      char **choices,
      Bit64s initial_val,
      Bit64s value_base = 0);
  char *get_choice (int n) { return choices[n]; }
  int find_by_name (const char *string);
  bool set_by_name (const char *string);
#if BX_UI_TEXT
  virtual void text_print (FILE *fp);
  virtual int text_ask (FILE *fpin, FILE *fpout);
#endif
};

typedef char* (*param_string_event_handler)(class bx_param_string_c *, int set, char *val, int maxlen);

class BOCHSAPI bx_param_string_c : public bx_param_c {
  int maxsize;
  char *val, *initial_val;
  param_string_event_handler handler;
  param_enable_handler enable_handler;
  bx_param_num_c *options;
  char separator;
public:
  enum {
    RAW_BYTES = 1,         // use binary text editor, like MAC addr
    IS_FILENAME = 2,       // 1=yes it's a filename, 0=not a filename.
                           // Some guis have a file browser. This
                           // bit suggests that they use it.
    SAVE_FILE_DIALOG = 4   // Use save dialog opposed to open file dialog
  } bx_string_opt_bits;
  bx_param_string_c (bx_id id,
      char *name,
      char *description,
      char *initial_val,
      int maxsize=-1);
  virtual ~bx_param_string_c ();
  void reset ();
  void set_handler (param_string_event_handler handler);
  void set_enable_handler (param_enable_handler handler);
  virtual void set_enabled (int enabled);
  Bit32s get (char *buf, int len);
  char *getptr () {return val; }
  void set (char *buf);
  bx_bool equals (const char *buf);
  bx_param_num_c *get_options () { return options; }
  void set_separator (char sep) {separator = sep; }
  char get_separator () {return separator; }
  int get_maxsize () {return maxsize; }
#if BX_UI_TEXT
  virtual void text_print (FILE *fp);
  virtual int text_ask (FILE *fpin, FILE *fpout);
#endif
};

// Declare a filename class.  It is identical to a string, except that
// it initializes the options differently.  This is just a shortcut
// for declaring a string param and setting the options with IS_FILENAME.
class BOCHSAPI bx_param_filename_c : public bx_param_string_c {
public:
  bx_param_filename_c (bx_id id,
      char *name,
      char *description,
      char *initial_val,
      int maxsize=-1);
};

class BOCHSAPI bx_list_c : public bx_param_c {
private:
  // just a list of bx_param_c objects.  size tells current number of
  // objects in the list, and maxsize tells how many list items are
  // allocated in the constructor.
  bx_param_c **list;
  int size, maxsize;
  // options is a bit field whose bits are defined by bx_listopt_bits ORed
  // together.  Options is a bx_param so that if necessary the bx_list could
  // install a handler to cause get/set of options to have side effects.
  bx_param_num_c *options;
  // for a menu, the value of choice before the call to "ask" is default.
  // After ask, choice holds the value that the user chose.  Choice defaults
  // to 1 in the constructor.
  bx_param_num_c *choice;
  // title of the menu or series
  bx_param_string_c *title;
  // if the menu shows a "return to previous menu" type of choice,
  // this controls where that choice will go.
  bx_param_c *parent;
  void init ();
public:
  enum {
    // When a bx_list_c is displayed as a menu, SHOW_PARENT controls whether or
    // not the menu shows a "Return to parent menu" choice or not.
    SHOW_PARENT = (1<<0),
    // Some lists are best displayed shown as menus, others as a series of
    // related questions.  This bit suggests to the CI that the series of
    // questions format is preferred.
    SERIES_ASK = (1<<1),
    // When a bx_list_c is displayed in a dialog, USE_TAB_WINDOW suggests
    // to the CI that each item in the list should be shown as a separate
    // tab.  This would be most appropriate when each item is another list
    // of parameters.
    USE_TAB_WINDOW = (1<<2),
    // When a bx_list_c is displayed in a dialog, the list name is used as the
    // label of the group box if USE_BOX_TITLE is set. This is only necessary if
    // more than one list appears in a dialog box.
    USE_BOX_TITLE = (1<<3)
  } bx_listopt_bits;
  bx_list_c (bx_id id, int maxsize);
  bx_list_c (bx_id id, char *name, char *description, bx_param_c **init_list);
  bx_list_c (bx_id id, char *name, char *description, int maxsize);
  virtual ~bx_list_c();
  bx_list_c *clone ();
  void add (bx_param_c *param);
  bx_param_c *get (int index);
  int get_size () { return size; }
  bx_param_num_c *get_options () { return options; }
  void set_options (bx_param_num_c *newopt) { options = newopt; }
  bx_param_num_c *get_choice () { return choice; }
  bx_param_string_c *get_title () { return title; }
  void set_parent (bx_param_c *newparent) { parent = newparent; }
  bx_param_c *get_parent () { return parent; }
#if BX_UI_TEXT
  virtual void text_print (FILE *);
  virtual int text_ask (FILE *fpin, FILE *fpout);
#endif
};

////////////////////////////////////////////////////////////////


// These are the different start modes.
enum {
  // Just start the simulation without running the configuration interface
  // at all, unless something goes wrong.
  BX_QUICK_START = 200,
  // Run the configuration interface.  The default action will be to load a
  // configuration file.  This makes sense if a config file could not be
  // loaded, either because it wasn't found or because it had errors.
  BX_LOAD_START,
  // Run the configuration interface.  The default action will be to
  // edit the configuration.
  BX_EDIT_START,
  // Run the configuration interface, but make the default action be to
  // start the simulation.
  BX_RUN_START
};

#define BX_FLOPPY_NONE   10 // floppy not present
#define BX_FLOPPY_1_2    11 // 1.2M  5.25"
#define BX_FLOPPY_1_44   12 // 1.44M 3.5"
#define BX_FLOPPY_2_88   13 // 2.88M 3.5"
#define BX_FLOPPY_720K   14 // 720K  3.5"
#define BX_FLOPPY_360K   15 // 360K  5.25"
#define BX_FLOPPY_160K   16 // 160K  5.25"
#define BX_FLOPPY_180K   17 // 180K  5.25"
#define BX_FLOPPY_320K   18 // 320K  5.25"
#define BX_FLOPPY_LAST   18 // last legal value of floppy type

#define BX_FLOPPY_GUESS  20 // decide based on image size

#define BX_ATA_DEVICE_DISK      0
#define BX_ATA_DEVICE_CDROM     1
#define BX_ATA_DEVICE_LAST      1

#define BX_ATA_BIOSDETECT_NONE      0
#define BX_ATA_BIOSDETECT_AUTO      1
#define BX_ATA_BIOSDETECT_CMOS      2

#define BX_ATA_TRANSLATION_NONE      0
#define BX_ATA_TRANSLATION_LBA       1
#define BX_ATA_TRANSLATION_LARGE     2
#define BX_ATA_TRANSLATION_RECHS     3
#define BX_ATA_TRANSLATION_AUTO      4
#define BX_ATA_TRANSLATION_LAST      4

#define BX_ATA_MODE_FLAT        0
#define BX_ATA_MODE_CONCAT      1
#define BX_ATA_MODE_EXTDISKSIM  2
#define BX_ATA_MODE_DLL_HD      3
#define BX_ATA_MODE_SPARSE      4
#define BX_ATA_MODE_VMWARE3     5
#define BX_ATA_MODE_UNDOABLE    6
#define BX_ATA_MODE_GROWING     7
#define BX_ATA_MODE_VOLATILE    8
#define BX_ATA_MODE_LAST        8
//#define BX_ATA_MODE_Z_UNDOABLE  9
//#define BX_ATA_MODE_Z_VOLATILE  10
//#define BX_ATA_MODE_SPLIT       6

#define BX_CLOCK_SYNC_NONE     0
#define BX_CLOCK_SYNC_REALTIME 1
#define BX_CLOCK_SYNC_SLOWDOWN 2
#define BX_CLOCK_SYNC_BOTH     3
#define BX_CLOCK_SYNC_LAST     3

#define BX_CLOCK_TIME0_LOCAL     1
#define BX_CLOCK_TIME0_UTC       2

BOCHSAPI extern char *bochs_start_names[];
BOCHSAPI extern int n_bochs_start_names;
BOCHSAPI extern char *floppy_type_names[];
BOCHSAPI extern int floppy_type_n_sectors[];
BOCHSAPI extern int n_floppy_type_names;
BOCHSAPI extern char *floppy_status_names[];
BOCHSAPI extern int n_floppy_status_names;
BOCHSAPI extern char *floppy_bootdisk_names[];
BOCHSAPI extern int n_floppy_bootdisk_names;
BOCHSAPI extern char *loader_os_names[];
BOCHSAPI extern int n_loader_os_names;
BOCHSAPI extern char *keyboard_type_names[];
BOCHSAPI extern int n_keyboard_type_names;
BOCHSAPI extern char *atadevice_type_names[];
BOCHSAPI extern int n_atadevice_type_names;
BOCHSAPI extern char *atadevice_mode_names[];
BOCHSAPI extern int n_atadevice_mode_names;
BOCHSAPI extern char *atadevice_status_names[];
BOCHSAPI extern int n_atadevice_status_names;
BOCHSAPI extern char *atadevice_biosdetect_names[];
BOCHSAPI extern int n_atadevice_biosdetect_names;
BOCHSAPI extern char *atadevice_translation_names[];
BOCHSAPI extern int n_atadevice_translation_names;
BOCHSAPI extern char *clock_sync_names[];
BOCHSAPI extern int clock_sync_n_names;

typedef struct {
  bx_param_enum_c *Odevtype;
  bx_param_string_c *Opath;
  bx_param_enum_c *Otype;
  bx_param_enum_c *Ostatus;
  } bx_floppy_options;

typedef struct {
  bx_list_c *Omenu;
  bx_param_bool_c *Opresent;
  bx_param_enum_c *Otype;
  bx_param_enum_c *Omode;
  bx_param_string_c *Opath;
  bx_param_string_c *Ojournal;
  bx_param_num_c *Ocylinders;
  bx_param_num_c *Oheads;
  bx_param_num_c *Ospt;
  bx_param_enum_c *Ostatus;
  bx_param_string_c *Omodel;
  bx_param_enum_c *Obiosdetect;
  bx_param_enum_c *Otranslation;
  } bx_atadevice_options;

typedef struct {
  bx_param_bool_c *Oenabled;
  bx_param_string_c *Odev;
  } bx_serial_options;

typedef struct {
  bx_param_bool_c *Oenabled;
  bx_param_num_c *Oioaddr;
  bx_param_num_c *Oirq;
  } bx_usb_options;


////////////////////////////////////////////////////////////////////
// base class simulator interface, contains just virtual functions.
// I'm not longer sure that having a base class is going to be of any
// use... -Bryce

#include <setjmp.h>

enum ci_command_t { CI_START, CI_RUNTIME_CONFIG, CI_SHUTDOWN };
enum ci_return_t { 
  CI_OK,                  // normal return value 
  CI_ERR_NO_TEXT_CONSOLE  // err: can't work because there's no text console
  };
typedef int (*config_interface_callback_t)(void *userdata, ci_command_t command);

// bx_gui->set_display_mode() changes the mode between the configuration
// interface and the simulation.  This is primarily intended for display
// libraries which have a full-screen mode such as SDL, term, and svgalib.  The
// display mode is set to DISP_MODE_CONFIG before displaying any configuration
// menus, for panics that requires user input, when entering the debugger, etc.
// It is set to DISP_MODE_SIM when the Bochs simulation resumes.  The constants
// are defined here so that configuration interfaces can use them with the
// bx_simulator_interface_c::set_display_mode() method.
enum disp_mode_t { DISP_MODE_CONFIG=100, DISP_MODE_SIM };

class BOCHSAPI bx_simulator_interface_c {
public:
  bx_simulator_interface_c ();
  virtual void set_quit_context (jmp_buf *context) {}
  virtual int get_init_done () { return -1; }
  virtual int set_init_done (int n) {return -1;}
  virtual void get_param_id_range (int *min, int *max) {}
  virtual int register_param (bx_id id, bx_param_c *it) {return -1;}
  virtual void reset_all_param () {}
  virtual bx_param_c *get_param (bx_id id) {return NULL;}
  virtual bx_param_num_c *get_param_num (bx_id id) {return NULL;}
  virtual bx_param_string_c *get_param_string (bx_id id) {return NULL;}
  virtual bx_param_bool_c *get_param_bool (bx_id id) {return NULL;}
  virtual bx_param_enum_c *get_param_enum (bx_id id) {return NULL;}
  virtual int get_n_log_modules () {return -1;}
  virtual char *get_prefix (int mod) {return 0;}
  virtual int get_log_action (int mod, int level) {return -1;}
  virtual void set_log_action (int mod, int level, int action) {}
  virtual int get_default_log_action (int level) {return -1;}
  virtual void set_default_log_action (int level, int action) {}
  virtual char *get_action_name (int action) {return 0;}
  virtual const char *get_log_level_name (int level) {return 0;}
  virtual int get_max_log_level () {return -1;}

  // exiting is somewhat complicated!  The preferred way to exit bochs is
  // to call BX_EXIT(exitcode).  That is defined to call 
  // SIM->quit_sim(exitcode).  The quit_sim function first calls
  // the cleanup functions in bochs so that it can destroy windows
  // and free up memory, then sends a notify message to the CI 
  // telling it that bochs has stopped.
  virtual void quit_sim (int code) {}

  virtual int get_exit_code () { return 0; }

  virtual int get_default_rc (char *path, int len) {return -1;}
  virtual int read_rc (char *path) {return -1;}
  virtual int write_rc (char *rc, int overwrite) {return -1;}
  virtual int get_log_file (char *path, int len) {return -1;}
  virtual int set_log_file (char *path) {return -1;}
  virtual int get_log_prefix (char *prefix, int len) {return -1;}
  virtual int set_log_prefix (char *prefix) {return -1;}
  virtual int get_debugger_log_file (char *path, int len) {return -1;}
  virtual int set_debugger_log_file (char *path) {return -1;}
  virtual int get_floppy_options (int drive, bx_floppy_options *out) {return -1;}
  virtual int get_cdrom_options (int drive, bx_atadevice_options *out, int *where = NULL) {return -1;}
  virtual char *get_floppy_type_name (int type) {return NULL;}

  // The CI calls set_notify_callback to register its event handler function.
  // This event handler function is called whenever the simulator needs to
  // send an event to the CI.  For example, if the simulator hits a panic and
  // wants to ask the user how to proceed, it would call the CI event handler
  // to ask the CI to display a dialog.
  //
  // NOTE: At present, the standard VGAW buttons (floppy, snapshot, power,
  // etc.) are displayed and handled by gui.cc, not by the CI or siminterface.
  // gui.cc uses its own callback functions to implement the behavior of
  // the buttons.  Some of these implementations call the siminterface.
  typedef BxEvent* (*bxevent_handler)(void *theclass, BxEvent *event);
  virtual void set_notify_callback (bxevent_handler func, void *arg) {}
  virtual void get_notify_callback (bxevent_handler *func, void **arg) {}

  // send an event from the simulator to the CI.
  virtual BxEvent* sim_to_ci_event (BxEvent *event) {return NULL;}

  // called from simulator when it hits serious errors, to ask if the user
  // wants to continue or not
  virtual int log_msg (const char *prefix, int level, const char *msg) {return -1;}

  // tell the CI to ask the user for the value of a parameter.
  virtual int ask_param (bx_id param) {return -1;}

  // ask the user for a pathname
  virtual int ask_filename (char *filename, int maxlen, char *prompt, char *the_default, int flags) {return -1;}
  // called at a regular interval, currently by the keyboard handler.
  virtual void periodic () {}
  virtual int create_disk_image (const char *filename, int sectors, bx_bool overwrite) {return -3;}
  // Tell the configuration interface (CI) that some parameter values have
  // changed.  The CI will reread the parameters and change its display if it's
  // appropriate.  Maybe later: mention which params have changed to save time.
  virtual void refresh_ci () {}
  // forces a vga update.  This was added so that a debugger can force
  // a vga update when single stepping, without having to wait thousands
  // of cycles for the normal vga refresh triggered by iodev/keyboard.cc.
  virtual void refresh_vga () {}
  // forces a call to bx_gui.handle_events.  This was added so that a debugger
  // can force the gui events to be handled, so that interactive things such
  // as a toolbar click will be processed.
  virtual void handle_events () {}
  // return first hard disk in ATA interface
  virtual bx_param_c *get_first_cdrom () {return NULL;}
  // return first cdrom in ATA interface
  virtual bx_param_c *get_first_hd () {return NULL;}
#if BX_DEBUGGER
  // for debugger: same behavior as pressing control-C
  virtual void debug_break () {}
  virtual void debug_interpret_cmd (char *cmd) {}
  virtual char *debug_get_next_command () {return NULL;}
  virtual void debug_puts (const char *text) {}
#endif
  virtual void register_configuration_interface (
    const char* name, 
    config_interface_callback_t callback,
    void *userdata) {}
  virtual int configuration_interface(const char* name, ci_command_t command) {return -1; }
  virtual int begin_simulation (int argc, char *argv[]) {return -1;}
  typedef bool (*is_sim_thread_func_t)();
  is_sim_thread_func_t is_sim_thread_func;
  virtual void set_sim_thread_func (is_sim_thread_func_t func) {
    is_sim_thread_func = func;
  }
  virtual bool is_sim_thread () {return true;}
  virtual bool is_wx_selected () {return false;}
  // provide interface to bx_gui->set_display_mode() method for config
  // interfaces to use.
  virtual void set_display_mode (disp_mode_t newmode) {}
  virtual bool test_for_text_console () { return true; }
};

BOCHSAPI extern bx_simulator_interface_c *SIM;

BOCHSAPI extern void bx_init_siminterface ();
BOCHSAPI extern int bx_init_main (int argc, char *argv[]);

#if defined(__WXMSW__) || defined(WIN32)
// Just to provide HINSTANCE, etc. in files that have not included bochs.h.
// I don't like this at all, but I don't see a way around it.
#include <windows.h>
#endif

// define structure to hold data that is passed into our main function.
typedef struct BOCHSAPI {
  // standard argc,argv
  int argc;
  char **argv;
#ifdef WIN32
  char initial_dir[MAX_PATH];
#endif
#ifdef __WXMSW__
  // these are only used when compiling with wxWindows.  This gives us a
  // place to store the data that was passed to WinMain.
  HINSTANCE hInstance;
  HINSTANCE hPrevInstance;
  LPSTR m_lpCmdLine;
  int nCmdShow;
#endif
} bx_startup_flags_t;

BOCHSAPI extern bx_startup_flags_t bx_startup_flags;
BOCHSAPI extern bx_bool bx_user_quit;