Commit MetaInfo

Revision9881e238851f40236430a3d767d6c27519dd2680 (tree)
Time2019-05-20 16:15:36
Authoringlorion <homemicro@ingl...>
Commiteringlorion

Log Message

partitioned emulator into hm1000.c, main.c, and xcb.c

Change Summary

Incremental Difference

diff -r 83cd56eb5378 -r 9881e238851f emulator/Makefile.in
--- a/emulator/Makefile.in Sun May 19 22:08:41 2019 -0700
+++ b/emulator/Makefile.in Mon May 20 00:15:36 2019 -0700
@@ -1,5 +1,5 @@
11 TARGETS = Makefile hm1000
2-OBJECTS = hm1000.o
2+OBJECTS = main.o xcb.o
33
44 CFLAGS = @CFLAGS@ @XCB_CFLAGS@
55 LIBS = @LIBS@ @XCB_LIBS@
@@ -15,7 +15,10 @@
1515 hm1000 : $(OBJECTS)
1616 $(CC) $(CFLAGS) -o hm1000 $(OBJECTS) $(LIBS)
1717
18-hm1000.o : hm1000.c ops.inc
19- $(CC) $(CFLAGS) -c hm1000.c
18+main.o : main.c hm1000.c hm1000.h ops.inc xcb.h
19+ $(CC) $(CFLAGS) -c main.c
20+
21+xcb.o : xcb.c xcb.h
22+ $(CC) $(CFLAGS) -c xcb.c
2023
2124 .PHONY : all clean distclean
diff -r 83cd56eb5378 -r 9881e238851f emulator/hm1000.c
--- a/emulator/hm1000.c Sun May 19 22:08:41 2019 -0700
+++ b/emulator/hm1000.c Mon May 20 00:15:36 2019 -0700
@@ -1,10 +1,12 @@
1+#include "hm1000.h"
2+#include "xcb.h"
3+
14 #include <stdbool.h>
25 #include <stdint.h>
36 #include <stdio.h>
47 #include <stdlib.h>
58 #include <string.h>
69 #include <time.h>
7-#include <xcb/xcb.h>
810
911 #include <errno.h>
1012
@@ -47,70 +49,6 @@
4749 #define FATALF(FMT, ...) { fprintf(stderr, FMT "\n", __VA_ARGS__); exit(1); }
4850 #define FATAL(MSG) FATALF("%s", MSG)
4951
50-#define POS(ROW, COL) (ROW | ((COL) << 3))
51-#define KEY_BS POS(4, 1)
52-#define KEY_CTL POS(2, 0)
53-#define KEY_TAB POS(1, 1)
54-#define KEY_RET POS(6, 1)
55-#define KEY_ESC POS(0, 0)
56-#define KEY_SH POS(2, 7)
57-#define KEY_SPC POS(3, 7)
58-#define KEY_LEFT POS(7, 3)
59-#define KEY_UP POS(7, 4)
60-#define KEY_DOWN POS(7, 5)
61-#define KEY_RIGHT POS(7, 6)
62-#define KEY_0 POS(4, 3)
63-#define KEY_1 POS(0, 1)
64-#define KEY_2 POS(0, 2)
65-#define KEY_3 POS(0, 3)
66-#define KEY_4 POS(0, 4)
67-#define KEY_5 POS(0, 5)
68-#define KEY_6 POS(0, 6)
69-#define KEY_7 POS(4, 6)
70-#define KEY_8 POS(4, 5)
71-#define KEY_9 POS(4, 4)
72-#define KEY_BACKTICK POS(1, 0)
73-#define KEY_MINUS POS(4, 2)
74-#define KEY_EQUALS POS(4, 0)
75-#define KEY_LBRACKET POS(5, 2)
76-#define KEY_RBRACKET POS(5, 0)
77-#define KEY_BACKSLASH POS(5, 1)
78-#define KEY_SEMICOLON POS(7, 2)
79-#define KEY_QUOTE POS(6, 0)
80-#define KEY_COMMA POS(3, 0)
81-#define KEY_PERIOD POS(7, 0)
82-#define KEY_SLASH POS(7, 1)
83-#define KEY_A POS(2, 1)
84-#define KEY_B POS(3, 5)
85-#define KEY_C POS(3, 3)
86-#define KEY_D POS(2, 4)
87-#define KEY_E POS(1, 3)
88-#define KEY_F POS(2, 5)
89-#define KEY_G POS(2, 6)
90-#define KEY_H POS(5, 6)
91-#define KEY_I POS(6, 4)
92-#define KEY_J POS(6, 5)
93-#define KEY_K POS(6, 3)
94-#define KEY_L POS(6, 2)
95-#define KEY_M POS(6, 6)
96-#define KEY_N POS(3, 6)
97-#define KEY_O POS(5, 4)
98-#define KEY_P POS(5, 3)
99-#define KEY_Q POS(1, 2)
100-#define KEY_R POS(1, 4)
101-#define KEY_S POS(2, 3)
102-#define KEY_T POS(1, 5)
103-#define KEY_U POS(5, 5)
104-#define KEY_V POS(3, 4)
105-#define KEY_W POS(2, 2)
106-#define KEY_X POS(3, 2)
107-#define KEY_Y POS(1, 6)
108-#define KEY_Z POS(3, 1)
109-/* Maps keysyms to hm1k keyboard codes.
110- * For example, keysym 13 (return) maps to row 6, column 1, which we
111- * encode as 6 | (1 << 3).
112- * Codes for which we don't have a key are marked as 0xff.
113- */
11452 /* TODO: Add control, shift, and the arrow keys. */
11553 const uint8_t key_map[] = {
11654 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
@@ -814,330 +752,3 @@
814752 add_ticks(s, op_cycles[op]);
815753 ops[op](s, op);
816754 }
817-
818-typedef struct {
819- xcb_connection_t *xcb;
820- xcb_screen_t *screen;
821- xcb_window_t win;
822- unsigned int scale;
823- unsigned int xoffset;
824- unsigned int yoffset;
825- xcb_gcontext_t gc;
826- xcb_pixmap_t pixmap;
827- uint8_t keymap[256];
828-} xcb_data;
829-
830-static void xcb_generate_pixmap(xcb_data *gui) {
831- uint32_t values[1];
832- unsigned int i, j, n;
833- xcb_rectangle_t rects[8];
834-
835- xcb_create_pixmap(gui->xcb,
836- gui->screen->root_depth,
837- gui->pixmap,
838- gui->screen->root,
839- gui->scale * 8,
840- gui->scale * 256);
841-
842- values[0] = gui->screen->black_pixel;
843- xcb_change_gc(gui->xcb, gui->gc, XCB_GC_FOREGROUND, values);
844- rects[0].x = 0;
845- rects[0].y = 0;
846- rects[0].width = gui->scale * 8;
847- rects[0].height = gui->scale * 256;
848- xcb_poly_fill_rectangle(gui->xcb, gui->pixmap, gui->gc, 1, rects);
849-
850- values[0] = gui->screen->white_pixel;
851- xcb_change_gc(gui->xcb, gui->gc, XCB_GC_FOREGROUND, values);
852- for (i = 0; i < 256; i++) {
853- n = 0;
854- for (j = 0; j < 8; j++) {
855- if (i & (0x80 >> j)) {
856- rects[n].x = j * gui->scale;
857- rects[n].y = i * gui->scale;
858- rects[n].width = gui->scale;
859- rects[n].height = gui->scale;
860- ++n;
861- }
862- }
863- if (n > 0) {
864- xcb_poly_fill_rectangle(gui->xcb, gui->pixmap, gui->gc, n, rects);
865- }
866- }
867-}
868-
869-static void get_window_size(xcb_data *gui,
870- unsigned int *width,
871- unsigned int *height) {
872- xcb_get_geometry_reply_t *geometry;
873- xcb_get_geometry_cookie_t cookie = xcb_get_geometry(gui->xcb, gui->win);
874- geometry = xcb_get_geometry_reply(gui->xcb, cookie, NULL);
875- *width = geometry->width;
876- *height = geometry->height;
877- free(geometry);
878-}
879-
880-static void resize(xcb_data *gui,
881- unsigned int width,
882- unsigned int height) {
883- unsigned int scale = height / 220;
884- gui->scale = width / 340;
885- if (scale < gui->scale) gui->scale = scale;
886- gui->xoffset = (width - scale * 320) / 2;
887- gui->yoffset = (height - scale * 200) / 2;
888- xcb_generate_pixmap(gui);
889-}
890-
891-static int init_xcb(xcb_data *gui) {
892- xcb_screen_iterator_t xcb_screen_iterator;
893- const xcb_setup_t *xcb_setup;
894- xcb_keysym_t *keysyms;
895- int i, idx;
896- uint32_t values[2];
897- unsigned int width, height;
898- xcb_get_keyboard_mapping_cookie_t gkm_cookie;
899- xcb_get_keyboard_mapping_reply_t *keyboard_mapping;
900-
901- gui->pixmap = 0;
902- gui->xcb = xcb_connect(NULL, NULL);
903- if (xcb_connection_has_error(gui->xcb)) goto error;
904-
905- xcb_setup = xcb_get_setup(gui->xcb);
906- xcb_screen_iterator = xcb_setup_roots_iterator(xcb_setup);
907- gui->screen = xcb_screen_iterator.data;
908-
909- gui->gc = xcb_generate_id(gui->xcb);
910- values[0] = gui->screen->white_pixel;
911- xcb_create_gc(gui->xcb, gui->gc, gui->screen->root, XCB_GC_FOREGROUND, values);
912-
913- gui->win = xcb_generate_id(gui->xcb);
914- values[0] = gui->screen->black_pixel;
915- values[1] = XCB_EVENT_MASK_EXPOSURE
916- | XCB_EVENT_MASK_KEY_PRESS
917- | XCB_EVENT_MASK_KEY_RELEASE
918- | XCB_EVENT_MASK_STRUCTURE_NOTIFY;
919- xcb_create_window(gui->xcb,
920- /* depth */ XCB_COPY_FROM_PARENT,
921- gui->win,
922- gui->screen->root,
923- 0, 0,
924- 1440, 960,
925- /* border */ 0,
926- XCB_WINDOW_CLASS_INPUT_OUTPUT,
927- gui->screen->root_visual,
928- XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK,
929- values);
930- xcb_map_window(gui->xcb, gui->win);
931- gui->pixmap = xcb_generate_id(gui->xcb);
932- get_window_size(gui, &width, &height);
933- resize(gui, width, height);
934- gkm_cookie = xcb_get_keyboard_mapping(
935- gui->xcb,
936- xcb_setup->min_keycode,
937- xcb_setup->max_keycode - xcb_setup->min_keycode + 1);
938- xcb_flush(gui->xcb);
939- if (xcb_connection_has_error(gui->xcb)) goto error;
940-
941- memset(gui->keymap, 0xff, 256);
942- keyboard_mapping = xcb_get_keyboard_mapping_reply(gui->xcb, gkm_cookie, NULL);
943- keysyms = xcb_get_keyboard_mapping_keysyms(keyboard_mapping);
944- for (i = 0, idx = xcb_setup->min_keycode;
945- i < xcb_get_keyboard_mapping_keysyms_length(keyboard_mapping);
946- i += keyboard_mapping->keysyms_per_keycode, idx++) {
947- if (keysyms[i] < 128) {
948- gui->keymap[idx] = key_map[keysyms[i]];
949- } else {
950- switch (keysyms[i]) {
951- case 0xff08:
952- gui->keymap[idx] = KEY_BS;
953- break;
954- case 0xff09:
955- gui->keymap[idx] = KEY_TAB;
956- break;
957- case 0xff0a:
958- case 0xff0d:
959- gui->keymap[idx] = KEY_RET;
960- break;
961- case 0xff1b:
962- gui->keymap[idx] = KEY_ESC;
963- break;
964- case 0xff51:
965- gui->keymap[idx] = KEY_LEFT;
966- break;
967- case 0xff52:
968- gui->keymap[idx] = KEY_UP;
969- break;
970- case 0xff53:
971- gui->keymap[idx] = KEY_RIGHT;
972- break;
973- case 0xff54:
974- gui->keymap[idx] = KEY_DOWN;
975- break;
976- case 0xffe1:
977- case 0xffe2:
978- gui->keymap[idx] = KEY_SH;
979- break;
980- case 0xffe3:
981- case 0xffe4:
982- gui->keymap[idx] = KEY_CTL;
983- break;
984- }
985- }
986- }
987- /* for (int i = 0; i < 256; i++) { */
988- /* printf("keymap[%d]: %u\n", i, gui->keymap[i]); */
989- /* } */
990- free(keyboard_mapping);
991-
992- return 0;
993-
994- error:
995- if (gui->pixmap) {
996- xcb_free_pixmap(gui->xcb, gui->pixmap);
997- gui->pixmap = 0;
998- }
999- xcb_disconnect(gui->xcb);
1000- return -1;
1001-}
1002-
1003-static void update_display(xcb_data *gui, const uint8_t *ram) {
1004- unsigned int x, y;
1005- for (y = 0; y < 200; y++) {
1006- for (x = 0; x < 40; x++) {
1007- xcb_copy_area(gui->xcb, gui->pixmap, gui->win, gui->gc,
1008- 0,
1009- ram[0x2000 + (320 * (y >> 3)) + (x << 3) + (y & 7)] * gui->scale,
1010- (x << 3) * gui->scale + gui->xoffset,
1011- y * gui->scale + gui->yoffset,
1012- 8 * gui->scale, gui->scale);
1013- }
1014- }
1015- xcb_flush(gui->xcb);
1016-}
1017-
1018-int main(int argc, char *argv[]) {
1019- hm1k_state state;
1020- uint8_t ram[RAM_SIZE];
1021- uint8_t rom[ROM_SIZE];
1022- bool redraw;
1023- xcb_generic_event_t *event;
1024- xcb_data gui;
1025-
1026- if (init_xcb(&gui)) {
1027- FATAL("error initializing xcb");
1028- return -1;
1029- }
1030-
1031- randomize(ram, sizeof(ram));
1032-
1033- {
1034- FILE *f = fopen("rom.bin", "rb");
1035- if (!f) {
1036- perror("rom.bin");
1037- fprintf(stderr,
1038- "Could not open rom.bin."
1039- " The emulator will not work without it.\n");
1040- return 1;
1041- }
1042- fread(rom, 1, ROM_SIZE, f);
1043- fclose(f);
1044- }
1045- init_6502(&state, ram);
1046- state.rom = rom;
1047- state.io_read[SERIR - IO_BASE] = read_serir;
1048- state.io_write[SERCR - IO_BASE] = write_sercr;
1049- state.kbdrow = 0;
1050- memset(state.keyboard, 0xff, sizeof(state.keyboard));
1051- state.io_read[KBDCOL - IO_BASE] = read_kbdcol;
1052- state.io_write[KBDROW - IO_BASE] = write_kbdrow;
1053- do {
1054- FILE *f = fopen("cartridge.bin", "rb");
1055- if (!f) break;
1056- fseek(f, 0, SEEK_END);
1057- state.cartridge_size = ftell(f);
1058- rewind(f);
1059- state.cartridge = malloc(state.cartridge_size);
1060- if (!state.cartridge) {
1061- fprintf(stderr,
1062- "failed to allocate memory (%lu bytes) for cartridge\n",
1063- (unsigned long) state.cartridge_size);
1064- perror("malloc");
1065- break;
1066- }
1067- memset(state.cartridge, 0xff, state.cartridge_size);
1068- fread(state.cartridge, 1, state.cartridge_size, f);
1069- fclose(f);
1070- } while (0);
1071- reset(&state);
1072-
1073- redraw = true;
1074- for (;;) {
1075- step_6502(&state);
1076- if (state.last_sync.tv_sec >= state.next_redraw.tv_sec &&
1077- (state.last_sync.tv_sec > state.next_redraw.tv_sec ||
1078- state.last_sync.tv_nsec > state.next_redraw.tv_nsec)) {
1079- redraw = true;
1080- state.next_redraw.tv_nsec += REDRAW_NS;
1081- if (state.next_redraw.tv_nsec >= 1000000000) {
1082- ++state.next_redraw.tv_sec;
1083- state.next_redraw.tv_nsec -= 1000000000;
1084- }
1085- }
1086-
1087- event = xcb_poll_for_event(gui.xcb);
1088- if (!event) {
1089- if (redraw) {
1090- update_display(&gui, ram);
1091- redraw = false;
1092- }
1093- continue;
1094- }
1095- switch (event->response_type & ~0x80) {
1096- case XCB_EXPOSE:
1097- redraw = true;
1098- break;
1099- case XCB_KEY_PRESS:
1100- {
1101- xcb_key_press_event_t *kpe =
1102- (xcb_key_press_event_t*) event;
1103- unsigned pos = gui.keymap[kpe->detail];
1104- // printf("key press: %u (%u)\n", kpe->detail, pos);
1105- if (pos != 0xff) {
1106- if (kpe->state & XCB_MOD_MASK_1) {
1107- // Special handling when mod1 is active.
1108- if (pos == KEY_Q) goto leave_event_loop;
1109- } else {
1110- state.keyboard[pos & 7] &= ~((1 << (pos >> 3)));
1111- }
1112- }
1113- }
1114- break;
1115- case XCB_KEY_RELEASE:
1116- {
1117- xcb_key_press_event_t *kpe =
1118- (xcb_key_press_event_t*) event;
1119- unsigned pos = gui.keymap[kpe->detail];
1120- if (pos != 0xff) state.keyboard[pos & 7] |= (1 << (pos >> 3));
1121- }
1122- break;
1123- case XCB_CONFIGURE_NOTIFY:
1124- {
1125- xcb_configure_notify_event_t *cne =
1126- (xcb_configure_notify_event_t*) event;
1127- resize(&gui, cne->width, cne->height);
1128- redraw = true;
1129- }
1130- break;
1131- case XCB_CLIENT_MESSAGE:
1132- goto leave_event_loop;
1133- }
1134- free(event);
1135- continue;
1136- leave_event_loop:
1137- free(event);
1138- break;
1139- }
1140-
1141- xcb_disconnect(gui.xcb);
1142- return 0;
1143-}
diff -r 83cd56eb5378 -r 9881e238851f emulator/hm1000.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emulator/hm1000.h Mon May 20 00:15:36 2019 -0700
@@ -0,0 +1,73 @@
1+#ifndef HOMEMICRO_HM1000
2+#define HOMEMICRO_HM1000
3+
4+#include <stdint.h>
5+
6+#define POS(ROW, COL) (ROW | ((COL) << 3))
7+#define KEY_BS POS(4, 1)
8+#define KEY_CTL POS(2, 0)
9+#define KEY_TAB POS(1, 1)
10+#define KEY_RET POS(6, 1)
11+#define KEY_ESC POS(0, 0)
12+#define KEY_SH POS(2, 7)
13+#define KEY_SPC POS(3, 7)
14+#define KEY_LEFT POS(7, 3)
15+#define KEY_UP POS(7, 4)
16+#define KEY_DOWN POS(7, 5)
17+#define KEY_RIGHT POS(7, 6)
18+#define KEY_0 POS(4, 3)
19+#define KEY_1 POS(0, 1)
20+#define KEY_2 POS(0, 2)
21+#define KEY_3 POS(0, 3)
22+#define KEY_4 POS(0, 4)
23+#define KEY_5 POS(0, 5)
24+#define KEY_6 POS(0, 6)
25+#define KEY_7 POS(4, 6)
26+#define KEY_8 POS(4, 5)
27+#define KEY_9 POS(4, 4)
28+#define KEY_BACKTICK POS(1, 0)
29+#define KEY_MINUS POS(4, 2)
30+#define KEY_EQUALS POS(4, 0)
31+#define KEY_LBRACKET POS(5, 2)
32+#define KEY_RBRACKET POS(5, 0)
33+#define KEY_BACKSLASH POS(5, 1)
34+#define KEY_SEMICOLON POS(7, 2)
35+#define KEY_QUOTE POS(6, 0)
36+#define KEY_COMMA POS(3, 0)
37+#define KEY_PERIOD POS(7, 0)
38+#define KEY_SLASH POS(7, 1)
39+#define KEY_A POS(2, 1)
40+#define KEY_B POS(3, 5)
41+#define KEY_C POS(3, 3)
42+#define KEY_D POS(2, 4)
43+#define KEY_E POS(1, 3)
44+#define KEY_F POS(2, 5)
45+#define KEY_G POS(2, 6)
46+#define KEY_H POS(5, 6)
47+#define KEY_I POS(6, 4)
48+#define KEY_J POS(6, 5)
49+#define KEY_K POS(6, 3)
50+#define KEY_L POS(6, 2)
51+#define KEY_M POS(6, 6)
52+#define KEY_N POS(3, 6)
53+#define KEY_O POS(5, 4)
54+#define KEY_P POS(5, 3)
55+#define KEY_Q POS(1, 2)
56+#define KEY_R POS(1, 4)
57+#define KEY_S POS(2, 3)
58+#define KEY_T POS(1, 5)
59+#define KEY_U POS(5, 5)
60+#define KEY_V POS(3, 4)
61+#define KEY_W POS(2, 2)
62+#define KEY_X POS(3, 2)
63+#define KEY_Y POS(1, 6)
64+#define KEY_Z POS(3, 1)
65+/* Maps keysyms to hm1k keyboard codes.
66+ * For example, keysym 13 (return) maps to row 6, column 1, which we
67+ * encode as 6 | (1 << 3).
68+ * Codes for which we don't have a key are marked as 0xff.
69+ */
70+const uint8_t key_map[128];
71+
72+#endif /* ndef HOMEMICRO_HM1000 */
73+
diff -r 83cd56eb5378 -r 9881e238851f emulator/main.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emulator/main.c Mon May 20 00:15:36 2019 -0700
@@ -0,0 +1,131 @@
1+#include "hm1000.h"
2+#include "xcb.h"
3+
4+#include "hm1000.c"
5+
6+int main(int argc, char *argv[]) {
7+ hm1k_state state;
8+ uint8_t ram[RAM_SIZE];
9+ uint8_t rom[ROM_SIZE];
10+ bool redraw;
11+ xcb_generic_event_t *event;
12+ xcb_data gui;
13+
14+ if (init_xcb(&gui)) {
15+ FATAL("error initializing xcb");
16+ return -1;
17+ }
18+
19+ randomize(ram, sizeof(ram));
20+
21+ {
22+ FILE *f = fopen("rom.bin", "rb");
23+ if (!f) {
24+ perror("rom.bin");
25+ fprintf(stderr,
26+ "Could not open rom.bin."
27+ " The emulator will not work without it.\n");
28+ return 1;
29+ }
30+ fread(rom, 1, ROM_SIZE, f);
31+ fclose(f);
32+ }
33+ init_6502(&state, ram);
34+ state.rom = rom;
35+ state.io_read[SERIR - IO_BASE] = read_serir;
36+ state.io_write[SERCR - IO_BASE] = write_sercr;
37+ state.kbdrow = 0;
38+ memset(state.keyboard, 0xff, sizeof(state.keyboard));
39+ state.io_read[KBDCOL - IO_BASE] = read_kbdcol;
40+ state.io_write[KBDROW - IO_BASE] = write_kbdrow;
41+ do {
42+ FILE *f = fopen("cartridge.bin", "rb");
43+ if (!f) break;
44+ fseek(f, 0, SEEK_END);
45+ state.cartridge_size = ftell(f);
46+ rewind(f);
47+ state.cartridge = malloc(state.cartridge_size);
48+ if (!state.cartridge) {
49+ fprintf(stderr,
50+ "failed to allocate memory (%lu bytes) for cartridge\n",
51+ (unsigned long) state.cartridge_size);
52+ perror("malloc");
53+ break;
54+ }
55+ memset(state.cartridge, 0xff, state.cartridge_size);
56+ fread(state.cartridge, 1, state.cartridge_size, f);
57+ fclose(f);
58+ } while (0);
59+ reset(&state);
60+
61+ redraw = true;
62+ for (;;) {
63+ step_6502(&state);
64+ if (state.last_sync.tv_sec >= state.next_redraw.tv_sec &&
65+ (state.last_sync.tv_sec > state.next_redraw.tv_sec ||
66+ state.last_sync.tv_nsec > state.next_redraw.tv_nsec)) {
67+ redraw = true;
68+ state.next_redraw.tv_nsec += REDRAW_NS;
69+ if (state.next_redraw.tv_nsec >= 1000000000) {
70+ ++state.next_redraw.tv_sec;
71+ state.next_redraw.tv_nsec -= 1000000000;
72+ }
73+ }
74+
75+ event = xcb_poll_for_event(gui.xcb);
76+ if (!event) {
77+ if (redraw) {
78+ update_display(&gui, ram);
79+ redraw = false;
80+ }
81+ continue;
82+ }
83+ switch (event->response_type & ~0x80) {
84+ case XCB_EXPOSE:
85+ redraw = true;
86+ break;
87+ case XCB_KEY_PRESS:
88+ {
89+ xcb_key_press_event_t *kpe =
90+ (xcb_key_press_event_t*) event;
91+ unsigned pos = gui.keymap[kpe->detail];
92+ // printf("key press: %u (%u)\n", kpe->detail, pos);
93+ if (pos != 0xff) {
94+ if (kpe->state & XCB_MOD_MASK_1) {
95+ // Special handling when mod1 is active.
96+ if (pos == KEY_Q) goto leave_event_loop;
97+ } else {
98+ state.keyboard[pos & 7] &= ~((1 << (pos >> 3)));
99+ }
100+ }
101+ }
102+ break;
103+ case XCB_KEY_RELEASE:
104+ {
105+ xcb_key_press_event_t *kpe =
106+ (xcb_key_press_event_t*) event;
107+ unsigned pos = gui.keymap[kpe->detail];
108+ if (pos != 0xff) state.keyboard[pos & 7] |= (1 << (pos >> 3));
109+ }
110+ break;
111+ case XCB_CONFIGURE_NOTIFY:
112+ {
113+ xcb_configure_notify_event_t *cne =
114+ (xcb_configure_notify_event_t*) event;
115+ resize(&gui, cne->width, cne->height);
116+ redraw = true;
117+ }
118+ break;
119+ case XCB_CLIENT_MESSAGE:
120+ goto leave_event_loop;
121+ }
122+ free(event);
123+ continue;
124+ leave_event_loop:
125+ free(event);
126+ break;
127+ }
128+
129+ xcb_disconnect(gui.xcb);
130+ return 0;
131+}
diff -r 83cd56eb5378 -r 9881e238851f emulator/xcb.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emulator/xcb.c Mon May 20 00:15:36 2019 -0700
@@ -0,0 +1,193 @@
1+#include "xcb.h"
2+#include "hm1000.h"
3+
4+#include <stdlib.h>
5+#include <string.h>
6+
7+void get_window_size(xcb_data *gui,
8+ unsigned int *width,
9+ unsigned int *height) {
10+ xcb_get_geometry_reply_t *geometry;
11+ xcb_get_geometry_cookie_t cookie = xcb_get_geometry(gui->xcb, gui->win);
12+ geometry = xcb_get_geometry_reply(gui->xcb, cookie, NULL);
13+ *width = geometry->width;
14+ *height = geometry->height;
15+ free(geometry);
16+}
17+
18+int init_xcb(xcb_data *gui) {
19+ xcb_screen_iterator_t xcb_screen_iterator;
20+ const xcb_setup_t *xcb_setup;
21+ xcb_keysym_t *keysyms;
22+ int i, idx;
23+ uint32_t values[2];
24+ unsigned int width, height;
25+ xcb_get_keyboard_mapping_cookie_t gkm_cookie;
26+ xcb_get_keyboard_mapping_reply_t *keyboard_mapping;
27+
28+ gui->pixmap = 0;
29+ gui->xcb = xcb_connect(NULL, NULL);
30+ if (xcb_connection_has_error(gui->xcb)) goto error;
31+
32+ xcb_setup = xcb_get_setup(gui->xcb);
33+ xcb_screen_iterator = xcb_setup_roots_iterator(xcb_setup);
34+ gui->screen = xcb_screen_iterator.data;
35+
36+ gui->gc = xcb_generate_id(gui->xcb);
37+ values[0] = gui->screen->white_pixel;
38+ xcb_create_gc(gui->xcb, gui->gc, gui->screen->root, XCB_GC_FOREGROUND, values);
39+
40+ gui->win = xcb_generate_id(gui->xcb);
41+ values[0] = gui->screen->black_pixel;
42+ values[1] = XCB_EVENT_MASK_EXPOSURE
43+ | XCB_EVENT_MASK_KEY_PRESS
44+ | XCB_EVENT_MASK_KEY_RELEASE
45+ | XCB_EVENT_MASK_STRUCTURE_NOTIFY;
46+ xcb_create_window(gui->xcb,
47+ /* depth */ XCB_COPY_FROM_PARENT,
48+ gui->win,
49+ gui->screen->root,
50+ 0, 0,
51+ 1440, 960,
52+ /* border */ 0,
53+ XCB_WINDOW_CLASS_INPUT_OUTPUT,
54+ gui->screen->root_visual,
55+ XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK,
56+ values);
57+ xcb_map_window(gui->xcb, gui->win);
58+ gui->pixmap = xcb_generate_id(gui->xcb);
59+ get_window_size(gui, &width, &height);
60+ resize(gui, width, height);
61+ gkm_cookie = xcb_get_keyboard_mapping(
62+ gui->xcb,
63+ xcb_setup->min_keycode,
64+ xcb_setup->max_keycode - xcb_setup->min_keycode + 1);
65+ xcb_flush(gui->xcb);
66+ if (xcb_connection_has_error(gui->xcb)) goto error;
67+
68+ memset(gui->keymap, 0xff, 256);
69+ keyboard_mapping = xcb_get_keyboard_mapping_reply(gui->xcb, gkm_cookie, NULL);
70+ keysyms = xcb_get_keyboard_mapping_keysyms(keyboard_mapping);
71+ for (i = 0, idx = xcb_setup->min_keycode;
72+ i < xcb_get_keyboard_mapping_keysyms_length(keyboard_mapping);
73+ i += keyboard_mapping->keysyms_per_keycode, idx++) {
74+ if (keysyms[i] < 128) {
75+ gui->keymap[idx] = key_map[keysyms[i]];
76+ } else {
77+ switch (keysyms[i]) {
78+ case 0xff08:
79+ gui->keymap[idx] = KEY_BS;
80+ break;
81+ case 0xff09:
82+ gui->keymap[idx] = KEY_TAB;
83+ break;
84+ case 0xff0a:
85+ case 0xff0d:
86+ gui->keymap[idx] = KEY_RET;
87+ break;
88+ case 0xff1b:
89+ gui->keymap[idx] = KEY_ESC;
90+ break;
91+ case 0xff51:
92+ gui->keymap[idx] = KEY_LEFT;
93+ break;
94+ case 0xff52:
95+ gui->keymap[idx] = KEY_UP;
96+ break;
97+ case 0xff53:
98+ gui->keymap[idx] = KEY_RIGHT;
99+ break;
100+ case 0xff54:
101+ gui->keymap[idx] = KEY_DOWN;
102+ break;
103+ case 0xffe1:
104+ case 0xffe2:
105+ gui->keymap[idx] = KEY_SH;
106+ break;
107+ case 0xffe3:
108+ case 0xffe4:
109+ gui->keymap[idx] = KEY_CTL;
110+ break;
111+ }
112+ }
113+ }
114+ /* for (int i = 0; i < 256; i++) { */
115+ /* printf("keymap[%d]: %u\n", i, gui->keymap[i]); */
116+ /* } */
117+ free(keyboard_mapping);
118+
119+ return 0;
120+
121+ error:
122+ if (gui->pixmap) {
123+ xcb_free_pixmap(gui->xcb, gui->pixmap);
124+ gui->pixmap = 0;
125+ }
126+ xcb_disconnect(gui->xcb);
127+ return -1;
128+}
129+
130+void resize(xcb_data *gui,
131+ unsigned int width,
132+ unsigned int height) {
133+ unsigned int scale = height / 220;
134+ gui->scale = width / 340;
135+ if (scale < gui->scale) gui->scale = scale;
136+ gui->xoffset = (width - scale * 320) / 2;
137+ gui->yoffset = (height - scale * 200) / 2;
138+ xcb_generate_pixmap(gui);
139+}
140+
141+void update_display(xcb_data *gui, const uint8_t *ram) {
142+ unsigned int x, y;
143+ for (y = 0; y < 200; y++) {
144+ for (x = 0; x < 40; x++) {
145+ xcb_copy_area(gui->xcb, gui->pixmap, gui->win, gui->gc,
146+ 0,
147+ ram[0x2000 + (320 * (y >> 3)) + (x << 3) + (y & 7)] * gui->scale,
148+ (x << 3) * gui->scale + gui->xoffset,
149+ y * gui->scale + gui->yoffset,
150+ 8 * gui->scale, gui->scale);
151+ }
152+ }
153+ xcb_flush(gui->xcb);
154+}
155+
156+void xcb_generate_pixmap(xcb_data *gui) {
157+ uint32_t values[1];
158+ unsigned int i, j, n;
159+ xcb_rectangle_t rects[8];
160+
161+ xcb_create_pixmap(gui->xcb,
162+ gui->screen->root_depth,
163+ gui->pixmap,
164+ gui->screen->root,
165+ gui->scale * 8,
166+ gui->scale * 256);
167+
168+ values[0] = gui->screen->black_pixel;
169+ xcb_change_gc(gui->xcb, gui->gc, XCB_GC_FOREGROUND, values);
170+ rects[0].x = 0;
171+ rects[0].y = 0;
172+ rects[0].width = gui->scale * 8;
173+ rects[0].height = gui->scale * 256;
174+ xcb_poly_fill_rectangle(gui->xcb, gui->pixmap, gui->gc, 1, rects);
175+
176+ values[0] = gui->screen->white_pixel;
177+ xcb_change_gc(gui->xcb, gui->gc, XCB_GC_FOREGROUND, values);
178+ for (i = 0; i < 256; i++) {
179+ n = 0;
180+ for (j = 0; j < 8; j++) {
181+ if (i & (0x80 >> j)) {
182+ rects[n].x = j * gui->scale;
183+ rects[n].y = i * gui->scale;
184+ rects[n].width = gui->scale;
185+ rects[n].height = gui->scale;
186+ ++n;
187+ }
188+ }
189+ if (n > 0) {
190+ xcb_poly_fill_rectangle(gui->xcb, gui->pixmap, gui->gc, n, rects);
191+ }
192+ }
193+}
diff -r 83cd56eb5378 -r 9881e238851f emulator/xcb.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emulator/xcb.h Mon May 20 00:15:36 2019 -0700
@@ -0,0 +1,28 @@
1+#ifndef HOMEMICRO_EMULATOR_XCB
2+#define HOMEMICRO_EMULATOR_XCB
3+
4+#include <xcb/xcb.h>
5+
6+typedef struct {
7+ xcb_connection_t *xcb;
8+ xcb_screen_t *screen;
9+ xcb_window_t win;
10+ unsigned int scale;
11+ unsigned int xoffset;
12+ unsigned int yoffset;
13+ xcb_gcontext_t gc;
14+ xcb_pixmap_t pixmap;
15+ uint8_t keymap[256];
16+} xcb_data;
17+
18+void get_window_size(xcb_data *gui,
19+ unsigned int *width,
20+ unsigned int *height);
21+int init_xcb(xcb_data *gui);
22+void resize(xcb_data *gui,
23+ unsigned int width,
24+ unsigned int height);
25+void update_display(xcb_data *gui, const uint8_t *ram);
26+void xcb_generate_pixmap(xcb_data *gui);
27+
28+#endif /* ndef HOMEMICRO_EMULATOR_XCB */
Show on old repository browser