1 /*
2 * amstrad_cpc.c - Copyright (c) 2001, 2006, 2007 Olivier Poncet
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18 #ifdef HAVE_CONFIG_H
19 #include "config.h"
20 #endif
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <errno.h>
26 #ifdef HAVE_SYS_IPC_H
27 #include <sys/ipc.h>
28 #endif
29 #ifdef HAVE_SYS_SHM_H
30 #include <sys/shm.h>
31 #endif
32 #include <X11/Intrinsic.h>
33 #include <X11/StringDefs.h>
34 #ifdef HAVE_XSHM
35 #include <X11/extensions/XShm.h>
36 #endif
37 #include <Xem/Emulator.h>
38 #include "amstrad_cpc.h"
39 #include "xcpc.h"
40
41 #define AMSTRAD_CPC_SCR_W 768
42 #define AMSTRAD_CPC_SCR_H 576
43
44 static gboolean *cfg_no_fps = FALSE;
45 #ifdef HAVE_XSHM
46 static gboolean *cfg_no_xshm = FALSE;
47 #endif
48 static gchar *cfg_model = NULL;
49 static gchar *cfg_monitor = NULL;
50 static gchar *cfg_keyboard = NULL;
51 static gchar *cfg_firmname = NULL;
52 static gchar *cfg_sys_rom = NULL;
53 static gchar *cfg_exp_rom[256] = {
54 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
55 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
56 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
57 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
58 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
59 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
60 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
61 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
62 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
63 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
64 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
65 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
66 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
67 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
68 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
69 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
70 };
71
72 static GOptionEntry options[] = {
73 { "no-fps" , 0, 0, G_OPTION_ARG_NONE , &cfg_no_fps , "Don't show fps statistics" , NULL },
74 #ifdef HAVE_XSHM
75 { "no-xshm" , 0, 0, G_OPTION_ARG_NONE , &cfg_no_xshm , "Don't use the X11-SHM extension" , NULL },
76 #endif
77 { "model" , 0, 0, G_OPTION_ARG_STRING , &cfg_model , "cpc464|cpc664|cpc6128" , "value" },
78 { "monitor" , 0, 0, G_OPTION_ARG_STRING , &cfg_monitor , "color|green" , "value" },
79 { "keyboard", 0, 0, G_OPTION_ARG_STRING , &cfg_keyboard , "qwerty|azerty" , "value" },
80 { "firmname", 0, 0, G_OPTION_ARG_STRING , &cfg_firmname , "isp|triumph|saisho|solavox|awa|schneider|orion|amstrad", "value" },
81 { "sysrom" , 0, 0, G_OPTION_ARG_FILENAME, &cfg_sys_rom , "32Kb system rom" , "filename" },
82 { "rom000" , 0, 0, G_OPTION_ARG_FILENAME, &cfg_exp_rom[0x0], "16Kb expansion rom #00" , "filename" },
83 { "rom001" , 0, 0, G_OPTION_ARG_FILENAME, &cfg_exp_rom[0x1], "16Kb expansion rom #01" , "filename" },
84 { "rom002" , 0, 0, G_OPTION_ARG_FILENAME, &cfg_exp_rom[0x2], "16Kb expansion rom #02" , "filename" },
85 { "rom003" , 0, 0, G_OPTION_ARG_FILENAME, &cfg_exp_rom[0x3], "16Kb expansion rom #03" , "filename" },
86 { "rom004" , 0, 0, G_OPTION_ARG_FILENAME, &cfg_exp_rom[0x4], "16Kb expansion rom #04" , "filename" },
87 { "rom005" , 0, 0, G_OPTION_ARG_FILENAME, &cfg_exp_rom[0x5], "16Kb expansion rom #05" , "filename" },
88 { "rom006" , 0, 0, G_OPTION_ARG_FILENAME, &cfg_exp_rom[0x6], "16Kb expansion rom #06" , "filename" },
89 { "rom007" , 0, 0, G_OPTION_ARG_FILENAME, &cfg_exp_rom[0x7], "16Kb expansion rom #07" , "filename" },
90 { "rom008" , 0, 0, G_OPTION_ARG_FILENAME, &cfg_exp_rom[0x8], "16Kb expansion rom #08" , "filename" },
91 { "rom009" , 0, 0, G_OPTION_ARG_FILENAME, &cfg_exp_rom[0x9], "16Kb expansion rom #09" , "filename" },
92 { "rom010" , 0, 0, G_OPTION_ARG_FILENAME, &cfg_exp_rom[0xa], "16Kb expansion rom #10" , "filename" },
93 { "rom011" , 0, 0, G_OPTION_ARG_FILENAME, &cfg_exp_rom[0xb], "16Kb expansion rom #11" , "filename" },
94 { "rom012" , 0, 0, G_OPTION_ARG_FILENAME, &cfg_exp_rom[0xc], "16Kb expansion rom #12" , "filename" },
95 { "rom013" , 0, 0, G_OPTION_ARG_FILENAME, &cfg_exp_rom[0xd], "16Kb expansion rom #13" , "filename" },
96 { "rom014" , 0, 0, G_OPTION_ARG_FILENAME, &cfg_exp_rom[0xe], "16Kb expansion rom #14" , "filename" },
97 { "rom015" , 0, 0, G_OPTION_ARG_FILENAME, &cfg_exp_rom[0xf], "16Kb expansion rom #15" , "filename" },
98 { NULL } /* end-of-options */
99 };
100
101 static unsigned short hw_palette[32][4] = {
102 { 0x8000, 0x8000, 0x8000, 0x8000 }, /* White */
103 { 0x8000, 0x8000, 0x8000, 0x8000 }, /* White (not official) */
104 { 0x0000, 0xffff, 0x8000, 0xa4dd }, /* Sea Green */
105 { 0xffff, 0xffff, 0x8000, 0xf168 }, /* Pastel Yellow */
106 { 0x0000, 0x0000, 0x8000, 0x0e97 }, /* Blue */
107 { 0xffff, 0x0000, 0x8000, 0x5b22 }, /* Purple */
108 { 0x0000, 0x8000, 0x8000, 0x59ba }, /* Cyan */
109 { 0xffff, 0x8000, 0x8000, 0xa645 }, /* Pink */
110 { 0xffff, 0x0000, 0x8000, 0x5b22 }, /* Purple (not official) */
111 { 0xffff, 0xffff, 0x8000, 0xf168 }, /* Pastel Yellow (not official) */
112 { 0xffff, 0xffff, 0x0000, 0xe2d0 }, /* Bright Yellow */
113 { 0xffff, 0xffff, 0xffff, 0xffff }, /* Bright White */
114 { 0xffff, 0x0000, 0x0000, 0x4c8b }, /* Bright Red */
115 { 0xffff, 0x0000, 0xffff, 0x69ba }, /* Bright Magenta */
116 { 0xffff, 0x8000, 0x0000, 0x97ad }, /* Orange */
117 { 0xffff, 0x8000, 0xffff, 0xb4dc }, /* Pastel Magenta */
118 { 0x0000, 0x0000, 0x8000, 0x0e97 }, /* Blue (not official) */
119 { 0x0000, 0xffff, 0x8000, 0xa4dd }, /* Sea Green (not official) */
120 { 0x0000, 0xffff, 0x0000, 0x9645 }, /* Bright Green */
121 { 0x0000, 0xffff, 0xffff, 0xb374 }, /* Bright Cyan */
122 { 0x0000, 0x0000, 0x0000, 0x0000 }, /* Black */
123 { 0x0000, 0x0000, 0xffff, 0x1d2f }, /* Bright Blue */
124 { 0x0000, 0x8000, 0x0000, 0x4b23 }, /* Green */
125 { 0x0000, 0x8000, 0xffff, 0x6852 }, /* Sky Blue */
126 { 0x8000, 0x0000, 0x8000, 0x34dd }, /* Magenta */
127 { 0x8000, 0xffff, 0x8000, 0xcb22 }, /* Pastel Green */
128 { 0x8000, 0xffff, 0x0000, 0xbc8b }, /* Lime */
129 { 0x8000, 0xffff, 0xffff, 0xd9ba }, /* Pastel Cyan */
130 { 0x8000, 0x0000, 0x0000, 0x2645 }, /* Red */
131 { 0x8000, 0x0000, 0xffff, 0x4374 }, /* Mauve */
132 { 0x8000, 0x8000, 0x0000, 0x7168 }, /* Yellow */
133 { 0x8000, 0x8000, 0xffff, 0x8e97 } /* Pastel Blue */
134 };
135
136 static guint8 font_bits[] = {
137 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
138 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
139 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
140 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
141 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
142 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
143 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
144 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
145 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
146 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
147 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
148 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
149 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
150 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
151 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
152 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
153 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
154 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
155 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
156 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
157 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
158 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
159 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x00, 0x36, 0x36, 0x36, 0x00,
160 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x7f, 0x36, 0x7f, 0x36, 0x36, 0x00,
161 0x18, 0x7c, 0x1a, 0x3c, 0x58, 0x3e, 0x18, 0x00, 0x00, 0x63, 0x33, 0x18,
162 0x0c, 0x66, 0x63, 0x00, 0x1c, 0x36, 0x1c, 0x6e, 0x3b, 0x33, 0x6e, 0x00,
163 0x18, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c,
164 0x0c, 0x18, 0x30, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x00,
165 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e,
166 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x0c,
167 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
168 0x00, 0x18, 0x18, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x01, 0x00,
169 0x3e, 0x63, 0x73, 0x6b, 0x67, 0x63, 0x3e, 0x00, 0x18, 0x1c, 0x18, 0x18,
170 0x18, 0x18, 0x7e, 0x00, 0x3c, 0x66, 0x60, 0x3c, 0x06, 0x66, 0x7e, 0x00,
171 0x3c, 0x66, 0x60, 0x38, 0x60, 0x66, 0x3c, 0x00, 0x38, 0x3c, 0x36, 0x33,
172 0x7f, 0x30, 0x78, 0x00, 0x7e, 0x46, 0x06, 0x3e, 0x60, 0x66, 0x3c, 0x00,
173 0x3c, 0x66, 0x06, 0x3e, 0x66, 0x66, 0x3c, 0x00, 0x7e, 0x66, 0x60, 0x30,
174 0x18, 0x18, 0x18, 0x00, 0x3c, 0x66, 0x66, 0x3c, 0x66, 0x66, 0x3c, 0x00,
175 0x3c, 0x66, 0x66, 0x7c, 0x60, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x18, 0x18,
176 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x0c,
177 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x7e, 0x00,
178 0x00, 0x7e, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x18, 0x0c, 0x06, 0x00,
179 0x3c, 0x66, 0x66, 0x30, 0x18, 0x00, 0x18, 0x00, 0x3e, 0x63, 0x7b, 0x7b,
180 0x7b, 0x03, 0x3e, 0x00, 0x18, 0x3c, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x00,
181 0x3f, 0x66, 0x66, 0x3e, 0x66, 0x66, 0x3f, 0x00, 0x3c, 0x66, 0x03, 0x03,
182 0x03, 0x66, 0x3c, 0x00, 0x1f, 0x36, 0x66, 0x66, 0x66, 0x36, 0x1f, 0x00,
183 0x7f, 0x46, 0x16, 0x1e, 0x16, 0x46, 0x7f, 0x00, 0x7f, 0x46, 0x16, 0x1e,
184 0x16, 0x06, 0x0f, 0x00, 0x3c, 0x66, 0x03, 0x03, 0x73, 0x66, 0x7c, 0x00,
185 0x66, 0x66, 0x66, 0x7e, 0x66, 0x66, 0x66, 0x00, 0x7e, 0x18, 0x18, 0x18,
186 0x18, 0x18, 0x7e, 0x00, 0x78, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1e, 0x00,
187 0x67, 0x66, 0x36, 0x1e, 0x36, 0x66, 0x67, 0x00, 0x0f, 0x06, 0x06, 0x06,
188 0x46, 0x66, 0x7f, 0x00, 0x63, 0x77, 0x7f, 0x7f, 0x6b, 0x63, 0x63, 0x00,
189 0x63, 0x67, 0x6f, 0x7b, 0x73, 0x63, 0x63, 0x00, 0x1c, 0x36, 0x63, 0x63,
190 0x63, 0x36, 0x1c, 0x00, 0x3f, 0x66, 0x66, 0x3e, 0x06, 0x06, 0x0f, 0x00,
191 0x1c, 0x36, 0x63, 0x63, 0x5b, 0x33, 0x6e, 0x00, 0x3f, 0x66, 0x66, 0x3e,
192 0x36, 0x66, 0x67, 0x00, 0x3c, 0x66, 0x06, 0x3c, 0x60, 0x66, 0x3c, 0x00,
193 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x66, 0x66, 0x66, 0x66,
194 0x66, 0x66, 0x3c, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00,
195 0x63, 0x63, 0x63, 0x6b, 0x7f, 0x77, 0x63, 0x00, 0x63, 0x36, 0x1c, 0x1c,
196 0x36, 0x63, 0x63, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x3c, 0x00,
197 0x7f, 0x63, 0x31, 0x18, 0x4c, 0x66, 0x7f, 0x00, 0x3c, 0x0c, 0x0c, 0x0c,
198 0x0c, 0x0c, 0x3c, 0x00, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x40, 0x00,
199 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c, 0x00, 0x18, 0x3c, 0x7e, 0x18,
200 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
201 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x30,
202 0x3e, 0x33, 0x6e, 0x00, 0x07, 0x06, 0x3e, 0x66, 0x66, 0x66, 0x3b, 0x00,
203 0x00, 0x00, 0x3c, 0x66, 0x06, 0x66, 0x3c, 0x00, 0x38, 0x30, 0x3e, 0x33,
204 0x33, 0x33, 0x6e, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x7e, 0x06, 0x3c, 0x00,
205 0x38, 0x6c, 0x0c, 0x1e, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x7c, 0x66,
206 0x66, 0x7c, 0x60, 0x3e, 0x07, 0x06, 0x36, 0x6e, 0x66, 0x66, 0x67, 0x00,
207 0x18, 0x00, 0x1c, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x60, 0x00, 0x70, 0x60,
208 0x60, 0x66, 0x66, 0x3c, 0x07, 0x06, 0x66, 0x36, 0x1e, 0x36, 0x67, 0x00,
209 0x1c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x36, 0x7f,
210 0x6b, 0x6b, 0x63, 0x00, 0x00, 0x00, 0x3b, 0x66, 0x66, 0x66, 0x66, 0x00,
211 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x3b, 0x66,
212 0x66, 0x3e, 0x06, 0x0f, 0x00, 0x00, 0x6e, 0x33, 0x33, 0x3e, 0x30, 0x78,
213 0x00, 0x00, 0x3b, 0x6e, 0x06, 0x06, 0x0f, 0x00, 0x00, 0x00, 0x3c, 0x06,
214 0x3c, 0x60, 0x3e, 0x00, 0x0c, 0x0c, 0x3e, 0x0c, 0x0c, 0x6c, 0x38, 0x00,
215 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x66, 0x66,
216 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x63, 0x6b, 0x6b, 0x7f, 0x36, 0x00,
217 0x00, 0x00, 0x63, 0x36, 0x1c, 0x36, 0x63, 0x00, 0x00, 0x00, 0x66, 0x66,
218 0x66, 0x7c, 0x60, 0x3e, 0x00, 0x00, 0x7e, 0x32, 0x18, 0x4c, 0x7e, 0x00,
219 0x70, 0x18, 0x18, 0x0e, 0x18, 0x18, 0x70, 0x00, 0x18, 0x18, 0x18, 0x18,
220 0x18, 0x18, 0x18, 0x00, 0x0e, 0x18, 0x18, 0x70, 0x18, 0x18, 0x0e, 0x00,
221 0x6e, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
222 0x00, 0x00, 0x00, 0x00
223 };
224
225 #ifdef HAVE_XSHM
226 static XErrorHandler xshm_erhnd = NULL;
227 static Bool xshm_error = False;
228
XShmErrorHandler(Display * dpy,XErrorEvent * evt)229 static int XShmErrorHandler(Display *dpy, XErrorEvent *evt)
230 {
231 if(evt->error_code == BadAccess) {
232 xshm_error = True;
233 }
234 else {
235 xshm_error = False;
236 }
237 return(xshm_error == False ? (*xshm_erhnd)(dpy, evt) : 0);
238 }
239 #endif
240
241 AMSTRAD_CPC amstrad_cpc;
242
amstrad_cpc_mem_select(AMSTRAD_CPC * self)243 static void amstrad_cpc_mem_select(AMSTRAD_CPC *self)
244 {
245 GdevGArray *garray = self->garray;
246
247 switch(garray->ram_cfg) {
248 case 0x00:
249 self->rd_bank[0] = self->wr_bank[0] = self->memory.total_ram + 0x00000;
250 self->rd_bank[1] = self->wr_bank[1] = self->memory.total_ram + 0x04000;
251 self->rd_bank[2] = self->wr_bank[2] = self->memory.total_ram + 0x08000;
252 self->rd_bank[3] = self->wr_bank[3] = self->memory.total_ram + 0x0c000;
253 break;
254 case 0x01:
255 self->rd_bank[0] = self->wr_bank[0] = self->memory.total_ram + 0x00000;
256 self->rd_bank[1] = self->wr_bank[1] = self->memory.total_ram + 0x04000;
257 self->rd_bank[2] = self->wr_bank[2] = self->memory.total_ram + 0x08000;
258 self->rd_bank[3] = self->wr_bank[3] = self->memory.total_ram + 0x1c000;
259 break;
260 case 0x02:
261 self->rd_bank[0] = self->wr_bank[0] = self->memory.total_ram + 0x10000;
262 self->rd_bank[1] = self->wr_bank[1] = self->memory.total_ram + 0x14000;
263 self->rd_bank[2] = self->wr_bank[2] = self->memory.total_ram + 0x18000;
264 self->rd_bank[3] = self->wr_bank[3] = self->memory.total_ram + 0x1c000;
265 break;
266 case 0x03:
267 self->rd_bank[0] = self->wr_bank[0] = self->memory.total_ram + 0x00000;
268 self->rd_bank[1] = self->wr_bank[1] = self->memory.total_ram + 0x04000;
269 self->rd_bank[2] = self->wr_bank[2] = self->memory.total_ram + 0x08000;
270 self->rd_bank[3] = self->wr_bank[3] = self->memory.total_ram + 0x1c000;
271 break;
272 case 0x04:
273 self->rd_bank[0] = self->wr_bank[0] = self->memory.total_ram + 0x00000;
274 self->rd_bank[1] = self->wr_bank[1] = self->memory.total_ram + 0x10000;
275 self->rd_bank[2] = self->wr_bank[2] = self->memory.total_ram + 0x08000;
276 self->rd_bank[3] = self->wr_bank[3] = self->memory.total_ram + 0x0c000;
277 break;
278 case 0x05:
279 self->rd_bank[0] = self->wr_bank[0] = self->memory.total_ram + 0x00000;
280 self->rd_bank[1] = self->wr_bank[1] = self->memory.total_ram + 0x14000;
281 self->rd_bank[2] = self->wr_bank[2] = self->memory.total_ram + 0x08000;
282 self->rd_bank[3] = self->wr_bank[3] = self->memory.total_ram + 0x0c000;
283 break;
284 case 0x06:
285 self->rd_bank[0] = self->wr_bank[0] = self->memory.total_ram + 0x00000;
286 self->rd_bank[1] = self->wr_bank[1] = self->memory.total_ram + 0x18000;
287 self->rd_bank[2] = self->wr_bank[2] = self->memory.total_ram + 0x08000;
288 self->rd_bank[3] = self->wr_bank[3] = self->memory.total_ram + 0x0c000;
289 break;
290 case 0x07:
291 self->rd_bank[0] = self->wr_bank[0] = self->memory.total_ram + 0x00000;
292 self->rd_bank[1] = self->wr_bank[1] = self->memory.total_ram + 0x1c000;
293 self->rd_bank[2] = self->wr_bank[2] = self->memory.total_ram + 0x08000;
294 self->rd_bank[3] = self->wr_bank[3] = self->memory.total_ram + 0x0c000;
295 break;
296 default:
297 (void) fprintf(stderr, "RAM-SELECT: Bad Configuration (%02x) !!\n", garray->ram_cfg);
298 (void) fflush(stderr);
299 break;
300 }
301 if((garray->rom_cfg & 0x04) == 0) {
302 if(self->memory.lower_rom != NULL) {
303 self->rd_bank[0] = self->memory.lower_rom->data;
304 }
305 }
306 if((garray->rom_cfg & 0x08) == 0) {
307 if(self->memory.upper_rom != NULL) {
308 self->rd_bank[3] = self->memory.upper_rom->data;
309 }
310 if(self->memory.expan_rom[self->memory.expansion] != NULL) {
311 self->rd_bank[3] = self->memory.expan_rom[self->memory.expansion]->data;
312 }
313 }
314 }
315
amstrad_cpc_render08(AMSTRAD_CPC * self)316 static void amstrad_cpc_render08(AMSTRAD_CPC *self)
317 {
318 GdevMC6845 *mc6845 = self->mc6845;
319 GdevGArray *garray = self->garray;
320 unsigned int sa = ((mc6845->reg_file[12] << 8) | mc6845->reg_file[13]);
321 unsigned int hd = (mc6845->reg_file[1] < 48 ? mc6845->reg_file[1] : 48);
322 unsigned int hp = ((AMSTRAD_CPC_SCR_W >> 0) - (hd << 4)) >> 1;
323 unsigned int mr = mc6845->reg_file[9] + 1;
324 unsigned int vt = mc6845->reg_file[4] + 1;
325 unsigned int vd = (mc6845->reg_file[6] < 39 ? mc6845->reg_file[6] : 39);
326 unsigned int vp = ((AMSTRAD_CPC_SCR_H >> 1) - (vd * mr)) >> 1;
327 struct _scanline *sl = NULL;
328 guint8 *dst = (guint8 *) self->ximage->data, *nxt = dst;
329 guint8 pixel;
330 unsigned int cx, cy, ra;
331 guint16 addr;
332 guint8 data;
333
334 #ifdef HAVE_XSHM
335 if(self->useshm != False) {
336 (void) XSync(DisplayOfScreen(self->screen), False);
337 }
338 #endif
339 sl = &self->scanline[(vt * mr) - (1 * vp)];
340 for(cy = 0; cy < vp; cy++) {
341 nxt += AMSTRAD_CPC_SCR_W;
342 pixel = sl->ink[16];
343 for(cx = 0; cx < AMSTRAD_CPC_SCR_W; cx++) {
344 *dst++ = *nxt++ = pixel;
345 }
346 dst = nxt; sl++;
347 }
348 sl = &self->scanline[4];
349 for(cy = 0; cy < vd; cy++) {
350 for(ra = 0; ra < mr; ra++) {
351 nxt += AMSTRAD_CPC_SCR_W;
352 switch(sl->mode) {
353 case 0x00:
354 pixel = sl->ink[16];
355 for(cx = 0; cx < hp; cx++) {
356 *dst++ = *nxt++ = pixel;
357 }
358 for(cx = 0; cx < hd; cx++) {
359 addr = ((sa & 0x3000) << 2) | ((ra & 0x0007) << 11) | (((sa + cx) & 0x03ff) << 1);
360 /* pixel 0 */
361 data = garray->mode0[self->memory.total_ram[(addr | 0) & 0xffff]];
362 pixel = sl->ink[data & 0x0f];
363 *dst++ = *nxt++ = pixel;
364 *dst++ = *nxt++ = pixel;
365 *dst++ = *nxt++ = pixel;
366 *dst++ = *nxt++ = pixel;
367 /* pixel 1 */
368 data >>= 4;
369 pixel = sl->ink[data & 0x0f];
370 *dst++ = *nxt++ = pixel;
371 *dst++ = *nxt++ = pixel;
372 *dst++ = *nxt++ = pixel;
373 *dst++ = *nxt++ = pixel;
374 /* pixel 0 */
375 data = garray->mode0[self->memory.total_ram[(addr | 1) & 0xffff]];
376 pixel = sl->ink[data & 0x0f];
377 *dst++ = *nxt++ = pixel;
378 *dst++ = *nxt++ = pixel;
379 *dst++ = *nxt++ = pixel;
380 *dst++ = *nxt++ = pixel;
381 /* pixel 1 */
382 data >>= 4;
383 pixel = sl->ink[data & 0x0f];
384 *dst++ = *nxt++ = pixel;
385 *dst++ = *nxt++ = pixel;
386 *dst++ = *nxt++ = pixel;
387 *dst++ = *nxt++ = pixel;
388 }
389 pixel = sl->ink[16];
390 for(cx = 0; cx < hp; cx++) {
391 *dst++ = *nxt++ = pixel;
392 }
393 break;
394 case 0x01:
395 pixel = sl->ink[16];
396 for(cx = 0; cx < hp; cx++) {
397 *dst++ = *nxt++ = pixel;
398 }
399 for(cx = 0; cx < hd; cx++) {
400 addr = ((sa & 0x3000) << 2) | ((ra & 0x0007) << 11) | (((sa + cx) & 0x03ff) << 1);
401 /* pixel 0 */
402 data = garray->mode1[self->memory.total_ram[(addr | 0) & 0xffff]];
403 pixel = sl->ink[data & 0x03];
404 *dst++ = *nxt++ = pixel;
405 *dst++ = *nxt++ = pixel;
406 /* pixel 1 */
407 data >>= 2;
408 pixel = sl->ink[data & 0x03];
409 *dst++ = *nxt++ = pixel;
410 *dst++ = *nxt++ = pixel;
411 /* pixel 2 */
412 data >>= 2;
413 pixel = sl->ink[data & 0x03];
414 *dst++ = *nxt++ = pixel;
415 *dst++ = *nxt++ = pixel;
416 /* pixel 3 */
417 data >>= 2;
418 pixel = sl->ink[data & 0x03];
419 *dst++ = *nxt++ = pixel;
420 *dst++ = *nxt++ = pixel;
421 /* pixel 0 */
422 data = garray->mode1[self->memory.total_ram[(addr | 1) & 0xffff]];
423 pixel = sl->ink[data & 0x03];
424 *dst++ = *nxt++ = pixel;
425 *dst++ = *nxt++ = pixel;
426 /* pixel 1 */
427 data >>= 2;
428 pixel = sl->ink[data & 0x03];
429 *dst++ = *nxt++ = pixel;
430 *dst++ = *nxt++ = pixel;
431 /* pixel 2 */
432 data >>= 2;
433 pixel = sl->ink[data & 0x03];
434 *dst++ = *nxt++ = pixel;
435 *dst++ = *nxt++ = pixel;
436 /* pixel 3 */
437 data >>= 2;
438 pixel = sl->ink[data & 0x03];
439 *dst++ = *nxt++ = pixel;
440 *dst++ = *nxt++ = pixel;
441 }
442 pixel = sl->ink[16];
443 for(cx = 0; cx < hp; cx++) {
444 *dst++ = *nxt++ = pixel;
445 }
446 break;
447 case 0x02:
448 pixel = sl->ink[16];
449 for(cx = 0; cx < hp; cx++) {
450 *dst++ = *nxt++ = pixel;
451 }
452 for(cx = 0; cx < hd; cx++) {
453 addr = ((sa & 0x3000) << 2) | ((ra & 0x0007) << 11) | (((sa + cx) & 0x03ff) << 1);
454 /* pixel 0 */
455 data = garray->mode2[self->memory.total_ram[(addr | 0) & 0xffff]];
456 pixel = sl->ink[data & 0x01];
457 *dst++ = *nxt++ = pixel;
458 /* pixel 1 */
459 data >>= 1;
460 pixel = sl->ink[data & 0x01];
461 *dst++ = *nxt++ = pixel;
462 /* pixel 2 */
463 data >>= 1;
464 pixel = sl->ink[data & 0x01];
465 *dst++ = *nxt++ = pixel;
466 /* pixel 3 */
467 data >>= 1;
468 pixel = sl->ink[data & 0x01];
469 *dst++ = *nxt++ = pixel;
470 /* pixel 4 */
471 data >>= 1;
472 pixel = sl->ink[data & 0x01];
473 *dst++ = *nxt++ = pixel;
474 /* pixel 5 */
475 data >>= 1;
476 pixel = sl->ink[data & 0x01];
477 *dst++ = *nxt++ = pixel;
478 /* pixel 6 */
479 data >>= 1;
480 pixel = sl->ink[data & 0x01];
481 *dst++ = *nxt++ = pixel;
482 /* pixel 7 */
483 data >>= 1;
484 pixel = sl->ink[data & 0x01];
485 *dst++ = *nxt++ = pixel;
486 /* pixel 0 */
487 data = garray->mode2[self->memory.total_ram[(addr | 1) & 0xffff]];
488 pixel = sl->ink[data & 0x01];
489 *dst++ = *nxt++ = pixel;
490 /* pixel 1 */
491 data >>= 1;
492 pixel = sl->ink[data & 0x01];
493 *dst++ = *nxt++ = pixel;
494 /* pixel 2 */
495 data >>= 1;
496 pixel = sl->ink[data & 0x01];
497 *dst++ = *nxt++ = pixel;
498 /* pixel 3 */
499 data >>= 1;
500 pixel = sl->ink[data & 0x01];
501 *dst++ = *nxt++ = pixel;
502 /* pixel 4 */
503 data >>= 1;
504 pixel = sl->ink[data & 0x01];
505 *dst++ = *nxt++ = pixel;
506 /* pixel 5 */
507 data >>= 1;
508 pixel = sl->ink[data & 0x01];
509 *dst++ = *nxt++ = pixel;
510 /* pixel 6 */
511 data >>= 1;
512 pixel = sl->ink[data & 0x01];
513 *dst++ = *nxt++ = pixel;
514 /* pixel 7 */
515 data >>= 1;
516 pixel = sl->ink[data & 0x01];
517 *dst++ = *nxt++ = pixel;
518 }
519 pixel = sl->ink[16];
520 for(cx = 0; cx < hp; cx++) {
521 *dst++ = *nxt++ = pixel;
522 }
523 break;
524 }
525 dst = nxt; sl++;
526 }
527 sa += hd;
528 }
529 sl = &self->scanline[(vd * mr) + (0 * vp)];
530 for(cy = 0; cy < vp; cy++) {
531 nxt += AMSTRAD_CPC_SCR_W;
532 pixel = sl->ink[16];
533 for(cx = 0; cx < AMSTRAD_CPC_SCR_W; cx++) {
534 *dst++ = *nxt++ = pixel;
535 }
536 dst = nxt; sl++;
537 }
538 if(cfg_no_fps == FALSE) {
539 char *str = self->status; int len = 0;
540 guint8 fg = self->palette[garray->ink[0x01]].pixel;
541 guint8 bg = self->palette[garray->ink[0x10]].pixel;
542 guint8 *pt0 = (guint8 *) ((guint8 *) self->ximage->data + ((self->ximage->height - 9) * self->ximage->bytes_per_line));
543 while(*str != 0) {
544 guint8 *pt1 = pt0;
545 for(cy = 0; cy < 8; cy++) {
546 guint8 *pt2 = pt1;
547 data = font_bits[((*str & 0x7f) << 3) + cy];
548 for(cx = 0; cx < 8; cx++) {
549 *pt2++ = (data & 0x01 ? fg : bg); data >>= 1;
550 }
551 pt1 = (guint8 *) (((guint8 *) pt1) + self->ximage->bytes_per_line);
552 }
553 pt0 += 8; str++; len++;
554 }
555 }
556 if(self->window != None) {
557 #ifdef HAVE_XSHM
558 if(self->useshm != False) {
559 (void) XShmPutImage(DisplayOfScreen(self->screen), self->window, DefaultGCOfScreen(self->screen), self->ximage, 0, 0, 0, 0, AMSTRAD_CPC_SCR_W, AMSTRAD_CPC_SCR_H, False);
560 (void) XFlush(DisplayOfScreen(self->screen));
561 }
562 else {
563 (void) XPutImage(DisplayOfScreen(self->screen), self->window, DefaultGCOfScreen(self->screen), self->ximage, 0, 0, 0, 0, AMSTRAD_CPC_SCR_W, AMSTRAD_CPC_SCR_H);
564 (void) XFlush(DisplayOfScreen(self->screen));
565 }
566 #else
567 (void) XPutImage(DisplayOfScreen(self->screen), self->window, DefaultGCOfScreen(self->screen), self->ximage, 0, 0, 0, 0, AMSTRAD_CPC_SCR_W, AMSTRAD_CPC_SCR_H);
568 (void) XFlush(DisplayOfScreen(self->screen));
569 #endif
570 }
571 }
572
amstrad_cpc_render16(AMSTRAD_CPC * self)573 static void amstrad_cpc_render16(AMSTRAD_CPC *self)
574 {
575 GdevMC6845 *mc6845 = self->mc6845;
576 GdevGArray *garray = self->garray;
577 unsigned int sa = ((mc6845->reg_file[12] << 8) | mc6845->reg_file[13]);
578 unsigned int hd = (mc6845->reg_file[1] < 48 ? mc6845->reg_file[1] : 48);
579 unsigned int hp = ((AMSTRAD_CPC_SCR_W >> 0) - (hd << 4)) >> 1;
580 unsigned int mr = mc6845->reg_file[9] + 1;
581 unsigned int vt = mc6845->reg_file[4] + 1;
582 unsigned int vd = (mc6845->reg_file[6] < 39 ? mc6845->reg_file[6] : 39);
583 unsigned int vp = ((AMSTRAD_CPC_SCR_H >> 1) - (vd * mr)) >> 1;
584 struct _scanline *sl = NULL;
585 guint16 *dst = (guint16 *) self->ximage->data, *nxt = dst;
586 guint16 pixel;
587 unsigned int cx, cy, ra;
588 guint16 addr;
589 guint8 data;
590
591 #ifdef HAVE_XSHM
592 if(self->useshm != False) {
593 (void) XSync(DisplayOfScreen(self->screen), False);
594 }
595 #endif
596 sl = &self->scanline[(vt * mr) - (1 * vp)];
597 for(cy = 0; cy < vp; cy++) {
598 nxt += AMSTRAD_CPC_SCR_W;
599 pixel = sl->ink[16];
600 for(cx = 0; cx < AMSTRAD_CPC_SCR_W; cx++) {
601 *dst++ = *nxt++ = pixel;
602 }
603 dst = nxt; sl++;
604 }
605 sl = &self->scanline[4];
606 for(cy = 0; cy < vd; cy++) {
607 for(ra = 0; ra < mr; ra++) {
608 nxt += AMSTRAD_CPC_SCR_W;
609 switch(sl->mode) {
610 case 0x00:
611 pixel = sl->ink[16];
612 for(cx = 0; cx < hp; cx++) {
613 *dst++ = *nxt++ = pixel;
614 }
615 for(cx = 0; cx < hd; cx++) {
616 addr = ((sa & 0x3000) << 2) | ((ra & 0x0007) << 11) | (((sa + cx) & 0x03ff) << 1);
617 /* pixel 0 */
618 data = garray->mode0[self->memory.total_ram[(addr | 0) & 0xffff]];
619 pixel = sl->ink[data & 0x0f];
620 *dst++ = *nxt++ = pixel;
621 *dst++ = *nxt++ = pixel;
622 *dst++ = *nxt++ = pixel;
623 *dst++ = *nxt++ = pixel;
624 /* pixel 1 */
625 data >>= 4;
626 pixel = sl->ink[data & 0x0f];
627 *dst++ = *nxt++ = pixel;
628 *dst++ = *nxt++ = pixel;
629 *dst++ = *nxt++ = pixel;
630 *dst++ = *nxt++ = pixel;
631 /* pixel 0 */
632 data = garray->mode0[self->memory.total_ram[(addr | 1) & 0xffff]];
633 pixel = sl->ink[data & 0x0f];
634 *dst++ = *nxt++ = pixel;
635 *dst++ = *nxt++ = pixel;
636 *dst++ = *nxt++ = pixel;
637 *dst++ = *nxt++ = pixel;
638 /* pixel 1 */
639 data >>= 4;
640 pixel = sl->ink[data & 0x0f];
641 *dst++ = *nxt++ = pixel;
642 *dst++ = *nxt++ = pixel;
643 *dst++ = *nxt++ = pixel;
644 *dst++ = *nxt++ = pixel;
645 }
646 pixel = sl->ink[16];
647 for(cx = 0; cx < hp; cx++) {
648 *dst++ = *nxt++ = pixel;
649 }
650 break;
651 case 0x01:
652 pixel = sl->ink[16];
653 for(cx = 0; cx < hp; cx++) {
654 *dst++ = *nxt++ = pixel;
655 }
656 for(cx = 0; cx < hd; cx++) {
657 addr = ((sa & 0x3000) << 2) | ((ra & 0x0007) << 11) | (((sa + cx) & 0x03ff) << 1);
658 /* pixel 0 */
659 data = garray->mode1[self->memory.total_ram[(addr | 0) & 0xffff]];
660 pixel = sl->ink[data & 0x03];
661 *dst++ = *nxt++ = pixel;
662 *dst++ = *nxt++ = pixel;
663 /* pixel 1 */
664 data >>= 2;
665 pixel = sl->ink[data & 0x03];
666 *dst++ = *nxt++ = pixel;
667 *dst++ = *nxt++ = pixel;
668 /* pixel 2 */
669 data >>= 2;
670 pixel = sl->ink[data & 0x03];
671 *dst++ = *nxt++ = pixel;
672 *dst++ = *nxt++ = pixel;
673 /* pixel 3 */
674 data >>= 2;
675 pixel = sl->ink[data & 0x03];
676 *dst++ = *nxt++ = pixel;
677 *dst++ = *nxt++ = pixel;
678 /* pixel 0 */
679 data = garray->mode1[self->memory.total_ram[(addr | 1) & 0xffff]];
680 pixel = sl->ink[data & 0x03];
681 *dst++ = *nxt++ = pixel;
682 *dst++ = *nxt++ = pixel;
683 /* pixel 1 */
684 data >>= 2;
685 pixel = sl->ink[data & 0x03];
686 *dst++ = *nxt++ = pixel;
687 *dst++ = *nxt++ = pixel;
688 /* pixel 2 */
689 data >>= 2;
690 pixel = sl->ink[data & 0x03];
691 *dst++ = *nxt++ = pixel;
692 *dst++ = *nxt++ = pixel;
693 /* pixel 3 */
694 data >>= 2;
695 pixel = sl->ink[data & 0x03];
696 *dst++ = *nxt++ = pixel;
697 *dst++ = *nxt++ = pixel;
698 }
699 pixel = sl->ink[16];
700 for(cx = 0; cx < hp; cx++) {
701 *dst++ = *nxt++ = pixel;
702 }
703 break;
704 case 0x02:
705 pixel = sl->ink[16];
706 for(cx = 0; cx < hp; cx++) {
707 *dst++ = *nxt++ = pixel;
708 }
709 for(cx = 0; cx < hd; cx++) {
710 addr = ((sa & 0x3000) << 2) | ((ra & 0x0007) << 11) | (((sa + cx) & 0x03ff) << 1);
711 /* pixel 0 */
712 data = garray->mode2[self->memory.total_ram[(addr | 0) & 0xffff]];
713 pixel = sl->ink[data & 0x01];
714 *dst++ = *nxt++ = pixel;
715 /* pixel 1 */
716 data >>= 1;
717 pixel = sl->ink[data & 0x01];
718 *dst++ = *nxt++ = pixel;
719 /* pixel 2 */
720 data >>= 1;
721 pixel = sl->ink[data & 0x01];
722 *dst++ = *nxt++ = pixel;
723 /* pixel 3 */
724 data >>= 1;
725 pixel = sl->ink[data & 0x01];
726 *dst++ = *nxt++ = pixel;
727 /* pixel 4 */
728 data >>= 1;
729 pixel = sl->ink[data & 0x01];
730 *dst++ = *nxt++ = pixel;
731 /* pixel 5 */
732 data >>= 1;
733 pixel = sl->ink[data & 0x01];
734 *dst++ = *nxt++ = pixel;
735 /* pixel 6 */
736 data >>= 1;
737 pixel = sl->ink[data & 0x01];
738 *dst++ = *nxt++ = pixel;
739 /* pixel 7 */
740 data >>= 1;
741 pixel = sl->ink[data & 0x01];
742 *dst++ = *nxt++ = pixel;
743 /* pixel 0 */
744 data = garray->mode2[self->memory.total_ram[(addr | 1) & 0xffff]];
745 pixel = sl->ink[data & 0x01];
746 *dst++ = *nxt++ = pixel;
747 /* pixel 1 */
748 data >>= 1;
749 pixel = sl->ink[data & 0x01];
750 *dst++ = *nxt++ = pixel;
751 /* pixel 2 */
752 data >>= 1;
753 pixel = sl->ink[data & 0x01];
754 *dst++ = *nxt++ = pixel;
755 /* pixel 3 */
756 data >>= 1;
757 pixel = sl->ink[data & 0x01];
758 *dst++ = *nxt++ = pixel;
759 /* pixel 4 */
760 data >>= 1;
761 pixel = sl->ink[data & 0x01];
762 *dst++ = *nxt++ = pixel;
763 /* pixel 5 */
764 data >>= 1;
765 pixel = sl->ink[data & 0x01];
766 *dst++ = *nxt++ = pixel;
767 /* pixel 6 */
768 data >>= 1;
769 pixel = sl->ink[data & 0x01];
770 *dst++ = *nxt++ = pixel;
771 /* pixel 7 */
772 data >>= 1;
773 pixel = sl->ink[data & 0x01];
774 *dst++ = *nxt++ = pixel;
775 }
776 pixel = sl->ink[16];
777 for(cx = 0; cx < hp; cx++) {
778 *dst++ = *nxt++ = pixel;
779 }
780 break;
781 }
782 dst = nxt; sl++;
783 }
784 sa += hd;
785 }
786 sl = &self->scanline[(vd * mr) + (0 * vp)];
787 for(cy = 0; cy < vp; cy++) {
788 nxt += AMSTRAD_CPC_SCR_W;
789 pixel = sl->ink[16];
790 for(cx = 0; cx < AMSTRAD_CPC_SCR_W; cx++) {
791 *dst++ = *nxt++ = pixel;
792 }
793 dst = nxt; sl++;
794 }
795 if(cfg_no_fps == FALSE) {
796 char *str = self->status; int len = 0;
797 guint16 fg = self->palette[garray->ink[0x01]].pixel;
798 guint16 bg = self->palette[garray->ink[0x10]].pixel;
799 guint16 *pt0 = (guint16 *) ((guint8 *) self->ximage->data + ((self->ximage->height - 9) * self->ximage->bytes_per_line));
800 while(*str != 0) {
801 guint16 *pt1 = pt0;
802 for(cy = 0; cy < 8; cy++) {
803 guint16 *pt2 = pt1;
804 data = font_bits[((*str & 0x7f) << 3) + cy];
805 for(cx = 0; cx < 8; cx++) {
806 *pt2++ = (data & 0x01 ? fg : bg); data >>= 1;
807 }
808 pt1 = (guint16 *) (((guint8 *) pt1) + self->ximage->bytes_per_line);
809 }
810 pt0 += 8; str++; len++;
811 }
812 }
813 if(self->window != None) {
814 #ifdef HAVE_XSHM
815 if(self->useshm != False) {
816 (void) XShmPutImage(DisplayOfScreen(self->screen), self->window, DefaultGCOfScreen(self->screen), self->ximage, 0, 0, 0, 0, AMSTRAD_CPC_SCR_W, AMSTRAD_CPC_SCR_H, False);
817 (void) XFlush(DisplayOfScreen(self->screen));
818 }
819 else {
820 (void) XPutImage(DisplayOfScreen(self->screen), self->window, DefaultGCOfScreen(self->screen), self->ximage, 0, 0, 0, 0, AMSTRAD_CPC_SCR_W, AMSTRAD_CPC_SCR_H);
821 (void) XFlush(DisplayOfScreen(self->screen));
822 }
823 #else
824 (void) XPutImage(DisplayOfScreen(self->screen), self->window, DefaultGCOfScreen(self->screen), self->ximage, 0, 0, 0, 0, AMSTRAD_CPC_SCR_W, AMSTRAD_CPC_SCR_H);
825 (void) XFlush(DisplayOfScreen(self->screen));
826 #endif
827 }
828 }
829
amstrad_cpc_render32(AMSTRAD_CPC * self)830 static void amstrad_cpc_render32(AMSTRAD_CPC *self)
831 {
832 GdevMC6845 *mc6845 = self->mc6845;
833 GdevGArray *garray = self->garray;
834 unsigned int sa = ((mc6845->reg_file[12] << 8) | mc6845->reg_file[13]);
835 unsigned int hd = (mc6845->reg_file[1] < 48 ? mc6845->reg_file[1] : 48);
836 unsigned int hp = ((AMSTRAD_CPC_SCR_W >> 0) - (hd << 4)) >> 1;
837 unsigned int mr = mc6845->reg_file[9] + 1;
838 unsigned int vt = mc6845->reg_file[4] + 1;
839 unsigned int vd = (mc6845->reg_file[6] < 39 ? mc6845->reg_file[6] : 39);
840 unsigned int vp = ((AMSTRAD_CPC_SCR_H >> 1) - (vd * mr)) >> 1;
841 struct _scanline *sl = NULL;
842 guint32 *dst = (guint32 *) self->ximage->data, *nxt = dst;
843 guint32 pixel;
844 unsigned int cx, cy, ra;
845 guint16 addr;
846 guint8 data;
847
848 #ifdef HAVE_XSHM
849 if(self->useshm != False) {
850 (void) XSync(DisplayOfScreen(self->screen), False);
851 }
852 #endif
853 sl = &self->scanline[(vt * mr) - (1 * vp)];
854 for(cy = 0; cy < vp; cy++) {
855 nxt += AMSTRAD_CPC_SCR_W;
856 pixel = sl->ink[16];
857 for(cx = 0; cx < AMSTRAD_CPC_SCR_W; cx++) {
858 *dst++ = *nxt++ = pixel;
859 }
860 dst = nxt; sl++;
861 }
862 sl = &self->scanline[4];
863 for(cy = 0; cy < vd; cy++) {
864 for(ra = 0; ra < mr; ra++) {
865 nxt += AMSTRAD_CPC_SCR_W;
866 switch(sl->mode) {
867 case 0x00:
868 pixel = sl->ink[16];
869 for(cx = 0; cx < hp; cx++) {
870 *dst++ = *nxt++ = pixel;
871 }
872 for(cx = 0; cx < hd; cx++) {
873 addr = ((sa & 0x3000) << 2) | ((ra & 0x0007) << 11) | (((sa + cx) & 0x03ff) << 1);
874 /* pixel 0 */
875 data = garray->mode0[self->memory.total_ram[(addr | 0) & 0xffff]];
876 pixel = sl->ink[data & 0x0f];
877 *dst++ = *nxt++ = pixel;
878 *dst++ = *nxt++ = pixel;
879 *dst++ = *nxt++ = pixel;
880 *dst++ = *nxt++ = pixel;
881 /* pixel 1 */
882 data >>= 4;
883 pixel = sl->ink[data & 0x0f];
884 *dst++ = *nxt++ = pixel;
885 *dst++ = *nxt++ = pixel;
886 *dst++ = *nxt++ = pixel;
887 *dst++ = *nxt++ = pixel;
888 /* pixel 0 */
889 data = garray->mode0[self->memory.total_ram[(addr | 1) & 0xffff]];
890 pixel = sl->ink[data & 0x0f];
891 *dst++ = *nxt++ = pixel;
892 *dst++ = *nxt++ = pixel;
893 *dst++ = *nxt++ = pixel;
894 *dst++ = *nxt++ = pixel;
895 /* pixel 1 */
896 data >>= 4;
897 pixel = sl->ink[data & 0x0f];
898 *dst++ = *nxt++ = pixel;
899 *dst++ = *nxt++ = pixel;
900 *dst++ = *nxt++ = pixel;
901 *dst++ = *nxt++ = pixel;
902 }
903 pixel = sl->ink[16];
904 for(cx = 0; cx < hp; cx++) {
905 *dst++ = *nxt++ = pixel;
906 }
907 break;
908 case 0x01:
909 pixel = sl->ink[16];
910 for(cx = 0; cx < hp; cx++) {
911 *dst++ = *nxt++ = pixel;
912 }
913 for(cx = 0; cx < hd; cx++) {
914 addr = ((sa & 0x3000) << 2) | ((ra & 0x0007) << 11) | (((sa + cx) & 0x03ff) << 1);
915 /* pixel 0 */
916 data = garray->mode1[self->memory.total_ram[(addr | 0) & 0xffff]];
917 pixel = sl->ink[data & 0x03];
918 *dst++ = *nxt++ = pixel;
919 *dst++ = *nxt++ = pixel;
920 /* pixel 1 */
921 data >>= 2;
922 pixel = sl->ink[data & 0x03];
923 *dst++ = *nxt++ = pixel;
924 *dst++ = *nxt++ = pixel;
925 /* pixel 2 */
926 data >>= 2;
927 pixel = sl->ink[data & 0x03];
928 *dst++ = *nxt++ = pixel;
929 *dst++ = *nxt++ = pixel;
930 /* pixel 3 */
931 data >>= 2;
932 pixel = sl->ink[data & 0x03];
933 *dst++ = *nxt++ = pixel;
934 *dst++ = *nxt++ = pixel;
935 /* pixel 0 */
936 data = garray->mode1[self->memory.total_ram[(addr | 1) & 0xffff]];
937 pixel = sl->ink[data & 0x03];
938 *dst++ = *nxt++ = pixel;
939 *dst++ = *nxt++ = pixel;
940 /* pixel 1 */
941 data >>= 2;
942 pixel = sl->ink[data & 0x03];
943 *dst++ = *nxt++ = pixel;
944 *dst++ = *nxt++ = pixel;
945 /* pixel 2 */
946 data >>= 2;
947 pixel = sl->ink[data & 0x03];
948 *dst++ = *nxt++ = pixel;
949 *dst++ = *nxt++ = pixel;
950 /* pixel 3 */
951 data >>= 2;
952 pixel = sl->ink[data & 0x03];
953 *dst++ = *nxt++ = pixel;
954 *dst++ = *nxt++ = pixel;
955 }
956 pixel = sl->ink[16];
957 for(cx = 0; cx < hp; cx++) {
958 *dst++ = *nxt++ = pixel;
959 }
960 break;
961 case 0x02:
962 pixel = sl->ink[16];
963 for(cx = 0; cx < hp; cx++) {
964 *dst++ = *nxt++ = pixel;
965 }
966 for(cx = 0; cx < hd; cx++) {
967 addr = ((sa & 0x3000) << 2) | ((ra & 0x0007) << 11) | (((sa + cx) & 0x03ff) << 1);
968 /* pixel 0 */
969 data = garray->mode2[self->memory.total_ram[(addr | 0) & 0xffff]];
970 pixel = sl->ink[data & 0x01];
971 *dst++ = *nxt++ = pixel;
972 /* pixel 1 */
973 data >>= 1;
974 pixel = sl->ink[data & 0x01];
975 *dst++ = *nxt++ = pixel;
976 /* pixel 2 */
977 data >>= 1;
978 pixel = sl->ink[data & 0x01];
979 *dst++ = *nxt++ = pixel;
980 /* pixel 3 */
981 data >>= 1;
982 pixel = sl->ink[data & 0x01];
983 *dst++ = *nxt++ = pixel;
984 /* pixel 4 */
985 data >>= 1;
986 pixel = sl->ink[data & 0x01];
987 *dst++ = *nxt++ = pixel;
988 /* pixel 5 */
989 data >>= 1;
990 pixel = sl->ink[data & 0x01];
991 *dst++ = *nxt++ = pixel;
992 /* pixel 6 */
993 data >>= 1;
994 pixel = sl->ink[data & 0x01];
995 *dst++ = *nxt++ = pixel;
996 /* pixel 7 */
997 data >>= 1;
998 pixel = sl->ink[data & 0x01];
999 *dst++ = *nxt++ = pixel;
1000 /* pixel 0 */
1001 data = garray->mode2[self->memory.total_ram[(addr | 1) & 0xffff]];
1002 pixel = sl->ink[data & 0x01];
1003 *dst++ = *nxt++ = pixel;
1004 /* pixel 1 */
1005 data >>= 1;
1006 pixel = sl->ink[data & 0x01];
1007 *dst++ = *nxt++ = pixel;
1008 /* pixel 2 */
1009 data >>= 1;
1010 pixel = sl->ink[data & 0x01];
1011 *dst++ = *nxt++ = pixel;
1012 /* pixel 3 */
1013 data >>= 1;
1014 pixel = sl->ink[data & 0x01];
1015 *dst++ = *nxt++ = pixel;
1016 /* pixel 4 */
1017 data >>= 1;
1018 pixel = sl->ink[data & 0x01];
1019 *dst++ = *nxt++ = pixel;
1020 /* pixel 5 */
1021 data >>= 1;
1022 pixel = sl->ink[data & 0x01];
1023 *dst++ = *nxt++ = pixel;
1024 /* pixel 6 */
1025 data >>= 1;
1026 pixel = sl->ink[data & 0x01];
1027 *dst++ = *nxt++ = pixel;
1028 /* pixel 7 */
1029 data >>= 1;
1030 pixel = sl->ink[data & 0x01];
1031 *dst++ = *nxt++ = pixel;
1032 }
1033 pixel = sl->ink[16];
1034 for(cx = 0; cx < hp; cx++) {
1035 *dst++ = *nxt++ = pixel;
1036 }
1037 break;
1038 }
1039 dst = nxt; sl++;
1040 }
1041 sa += hd;
1042 }
1043 sl = &self->scanline[(vd * mr) + (0 * vp)];
1044 for(cy = 0; cy < vp; cy++) {
1045 nxt += AMSTRAD_CPC_SCR_W;
1046 pixel = sl->ink[16];
1047 for(cx = 0; cx < AMSTRAD_CPC_SCR_W; cx++) {
1048 *dst++ = *nxt++ = pixel;
1049 }
1050 dst = nxt; sl++;
1051 }
1052 if(cfg_no_fps == FALSE) {
1053 char *str = self->status; int len = 0;
1054 guint32 fg = self->palette[garray->ink[0x01]].pixel;
1055 guint32 bg = self->palette[garray->ink[0x10]].pixel;
1056 guint32 *pt0 = (guint32 *) ((guint8 *) self->ximage->data + ((self->ximage->height - 9) * self->ximage->bytes_per_line));
1057 while(*str != 0) {
1058 guint32 *pt1 = pt0;
1059 for(cy = 0; cy < 8; cy++) {
1060 guint32 *pt2 = pt1;
1061 data = font_bits[((*str & 0x7f) << 3) + cy];
1062 for(cx = 0; cx < 8; cx++) {
1063 *pt2++ = (data & 0x01 ? fg : bg); data >>= 1;
1064 }
1065 pt1 = (guint32 *) (((guint8 *) pt1) + self->ximage->bytes_per_line);
1066 }
1067 pt0 += 8; str++; len++;
1068 }
1069 }
1070 if(self->window != None) {
1071 #ifdef HAVE_XSHM
1072 if(self->useshm != False) {
1073 (void) XShmPutImage(DisplayOfScreen(self->screen), self->window, DefaultGCOfScreen(self->screen), self->ximage, 0, 0, 0, 0, AMSTRAD_CPC_SCR_W, AMSTRAD_CPC_SCR_H, False);
1074 (void) XFlush(DisplayOfScreen(self->screen));
1075 }
1076 else {
1077 (void) XPutImage(DisplayOfScreen(self->screen), self->window, DefaultGCOfScreen(self->screen), self->ximage, 0, 0, 0, 0, AMSTRAD_CPC_SCR_W, AMSTRAD_CPC_SCR_H);
1078 (void) XFlush(DisplayOfScreen(self->screen));
1079 }
1080 #else
1081 (void) XPutImage(DisplayOfScreen(self->screen), self->window, DefaultGCOfScreen(self->screen), self->ximage, 0, 0, 0, 0, AMSTRAD_CPC_SCR_W, AMSTRAD_CPC_SCR_H);
1082 (void) XFlush(DisplayOfScreen(self->screen));
1083 #endif
1084 }
1085 }
1086
amstrad_cpc_init_palette(AMSTRAD_CPC * self)1087 static void amstrad_cpc_init_palette(AMSTRAD_CPC *self)
1088 {
1089 int type = 0, ix;
1090
1091 if(cfg_monitor != NULL) {
1092 if(strcmp("color", cfg_monitor) == 0) {
1093 type = 0;
1094 }
1095 if(strcmp("green", cfg_monitor) == 0) {
1096 type = 1;
1097 }
1098 }
1099 for(ix = 0; ix < 32; ix++) {
1100 XColor *color = &self->palette[ix];
1101 if(type == 1) {
1102 color->pixel = (unsigned long) -1;
1103 color->red = 0;
1104 color->green = hw_palette[ix][3];
1105 color->blue = 0;
1106 color->flags = DoRed | DoGreen | DoBlue;
1107 color->pad = 0;
1108 }
1109 else {
1110 color->pixel = (unsigned long) -1;
1111 color->red = hw_palette[ix][0];
1112 color->green = hw_palette[ix][1];
1113 color->blue = hw_palette[ix][2];
1114 color->flags = DoRed | DoGreen | DoBlue;
1115 color->pad = 0;
1116 }
1117 if(XAllocColor(DisplayOfScreen(self->screen), self->colmap, color) == False) {
1118 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, "cannot allocate color ... %04x/%04x/%04x\n", color->red, color->green, color->blue);
1119 }
1120 }
1121 }
1122
amstrad_cpc_fini_palette(AMSTRAD_CPC * self)1123 static void amstrad_cpc_fini_palette(AMSTRAD_CPC *self)
1124 {
1125 int ix;
1126
1127 for(ix = 0; ix < 32; ix++) {
1128 XColor *color = &self->palette[ix];
1129 if(color->pixel != (unsigned long) -1) {
1130 (void) XFreeColors(DisplayOfScreen(self->screen), self->colmap, &color->pixel, 1, 0);
1131 }
1132 }
1133 }
1134
amstrad_cpc_init_image(AMSTRAD_CPC * self)1135 static void amstrad_cpc_init_image(AMSTRAD_CPC *self)
1136 {
1137 amstrad_cpc_init_palette(self);
1138 #ifdef HAVE_XSHM
1139 if(cfg_no_xshm == FALSE) {
1140 if(XShmQueryExtension(DisplayOfScreen(self->screen)) != False) {
1141 int major = 0;
1142 int minor = 0;
1143 Bool shpix = False;
1144 if(XShmQueryVersion(DisplayOfScreen(self->screen), &major, &minor, &shpix) != False) {
1145 XShmSegmentInfo *shm_info = g_new(XShmSegmentInfo, 1);
1146 shm_info->shmseg = None;
1147 shm_info->shmid = -1;
1148 shm_info->shmaddr = (char *) -1;
1149 shm_info->readOnly = False;
1150 self->ximage = XShmCreateImage(DisplayOfScreen(self->screen), self->visual, self->depth, ZPixmap, NULL, shm_info, AMSTRAD_CPC_SCR_W, AMSTRAD_CPC_SCR_H);
1151 shm_info->shmid = shmget(IPC_PRIVATE, self->ximage->bytes_per_line * self->ximage->height, IPC_CREAT | 0666);
1152 if(shm_info->shmid != -1) {
1153 shm_info->shmaddr = (char *) shmat(shm_info->shmid, NULL, 0);
1154 if(shm_info->shmaddr != (char *) -1) {
1155 xshm_erhnd = XSetErrorHandler(XShmErrorHandler);
1156 (void) XShmAttach(DisplayOfScreen(self->screen), shm_info);
1157 (void) XSync(DisplayOfScreen(self->screen), False);
1158 (void) XSetErrorHandler(xshm_erhnd);
1159 if(xshm_error == False) {
1160 (void) shmctl(shm_info->shmid, IPC_RMID, NULL);
1161 self->ximage->data = shm_info->shmaddr;
1162 self->useshm = True;
1163 }
1164 else {
1165 (void) shmdt(shm_info->shmaddr);
1166 (void) shmctl(shm_info->shmid, IPC_RMID, NULL);
1167 g_free(self->ximage->obdata);
1168 self->ximage->obdata = NULL;
1169 (void) XDestroyImage(self->ximage);
1170 self->ximage = NULL;
1171 }
1172 }
1173 }
1174 }
1175 }
1176 }
1177 #endif
1178 if(self->ximage == NULL) {
1179 self->ximage = XCreateImage(DisplayOfScreen(self->screen), self->visual, DefaultDepthOfScreen(self->screen), ZPixmap, 0, NULL, AMSTRAD_CPC_SCR_W, AMSTRAD_CPC_SCR_H, 8, 0);
1180 self->ximage->data = (char *) malloc(self->ximage->bytes_per_line * self->ximage->height);
1181 (void) memset(self->ximage->data, 0, self->ximage->bytes_per_line * self->ximage->height);
1182 }
1183 switch(self->ximage->bits_per_pixel) {
1184 case 8:
1185 self->render = amstrad_cpc_render08;
1186 break;
1187 case 16:
1188 self->render = amstrad_cpc_render16;
1189 break;
1190 case 32:
1191 self->render = amstrad_cpc_render32;
1192 break;
1193 default:
1194 self->render = NULL;
1195 break;
1196 }
1197 }
1198
amstrad_cpc_fini_image(AMSTRAD_CPC * self)1199 static void amstrad_cpc_fini_image(AMSTRAD_CPC *self)
1200 {
1201 amstrad_cpc_fini_palette(self);
1202 if(self->ximage != NULL) {
1203 #ifdef HAVE_XSHM
1204 if(self->useshm != False) {
1205 XShmSegmentInfo *shm_info = (XShmSegmentInfo *) self->ximage->obdata;
1206 (void) XShmDetach(DisplayOfScreen(self->screen), shm_info);
1207 (void) XSync(DisplayOfScreen(self->screen), False);
1208 (void) shmdt(shm_info->shmaddr);
1209 shm_info->shmaddr = (char *) NULL;
1210 self->ximage->data = NULL;
1211 g_free(self->ximage->obdata);
1212 self->ximage->obdata = NULL;
1213 }
1214 #endif
1215 if(self->ximage->data != NULL) {
1216 free(self->ximage->data);
1217 self->ximage->data = NULL;
1218 }
1219 (void) XDestroyImage(self->ximage);
1220 self->ximage = NULL;
1221 }
1222 self->ximage = NULL;
1223 self->screen = NULL;
1224 self->visual = NULL;
1225 self->window = None;
1226 self->colmap = None;
1227 self->depth = 0;
1228 self->useshm = False;
1229 self->render = NULL;
1230 }
1231
amstrad_cpc_reset(void)1232 void amstrad_cpc_reset(void)
1233 {
1234 AMSTRAD_CPC *self = &amstrad_cpc;
1235
1236 self->memory.expansion = 0x00;
1237 gdev_device_reset(GDEV_DEVICE(self->z80cpu));
1238 gdev_device_reset(GDEV_DEVICE(self->garray));
1239 gdev_device_reset(GDEV_DEVICE(self->cpckbd));
1240 gdev_device_reset(GDEV_DEVICE(self->mc6845));
1241 gdev_device_reset(GDEV_DEVICE(self->ay8910));
1242 gdev_device_reset(GDEV_DEVICE(self->upd765));
1243 gdev_device_reset(GDEV_DEVICE(self->i8255));
1244 amstrad_cpc_mem_select(self);
1245 (void) gettimeofday(&self->timer1, NULL);
1246 (void) gettimeofday(&self->timer2, NULL);
1247 self->num_frames = 0;
1248 self->drw_frames = 0;
1249 self->status[0] = 0;
1250 }
1251
amstrad_cpc_parse(int * argc,char *** argv)1252 int amstrad_cpc_parse(int *argc, char ***argv)
1253 {
1254 GOptionContext *ctxt = g_option_context_new(NULL);
1255
1256 g_option_context_add_main_entries(ctxt, options, NULL);
1257 if(g_option_context_parse(ctxt, argc, argv, NULL) != FALSE) {
1258 }
1259 else {
1260 }
1261 g_option_context_free(ctxt);
1262 ctxt = (GOptionContext *) NULL;
1263 return(EXIT_SUCCESS);
1264 }
1265
amstrad_cpc_load_snapshot(char * filename)1266 void amstrad_cpc_load_snapshot(char *filename)
1267 {
1268 AMSTRAD_CPC *self = &amstrad_cpc;
1269 FILE *file;
1270 guint8 buffer[256], *bufptr = buffer;
1271 int ramsize= 0;
1272 int ix;
1273
1274 if((file = fopen(filename, "r")) == NULL) {
1275 perror("amstrad_cpc");
1276 return;
1277 }
1278 fread(buffer, 1, 256, file);
1279 if(memcmp(bufptr, "MV - SNA", 8)) {
1280 fprintf(stderr, "not a valid snapshot file (bad signature)\n");
1281 fclose(file);
1282 return;
1283 } bufptr += 8;
1284 bufptr += 8; /* not used */
1285 bufptr++; /* snapshot version */
1286 self->z80cpu->AF.B.l = *bufptr++;
1287 self->z80cpu->AF.B.h = *bufptr++;
1288 self->z80cpu->BC.B.l = *bufptr++;
1289 self->z80cpu->BC.B.h = *bufptr++;
1290 self->z80cpu->DE.B.l = *bufptr++;
1291 self->z80cpu->DE.B.h = *bufptr++;
1292 self->z80cpu->HL.B.l = *bufptr++;
1293 self->z80cpu->HL.B.h = *bufptr++;
1294 self->z80cpu->IR.B.l = *bufptr++;
1295 self->z80cpu->IR.B.h = *bufptr++;
1296 self->z80cpu->IF.W = (*bufptr++ != 0 ? self->z80cpu->IF.W | IFF_1 : self->z80cpu->IF.W & (~IFF_2));
1297 self->z80cpu->IF.W = (*bufptr++ != 0 ? self->z80cpu->IF.W | IFF_1 : self->z80cpu->IF.W & (~IFF_2));
1298 self->z80cpu->IX.B.l = *bufptr++;
1299 self->z80cpu->IX.B.h = *bufptr++;
1300 self->z80cpu->IY.B.l = *bufptr++;
1301 self->z80cpu->IY.B.h = *bufptr++;
1302 self->z80cpu->SP.B.l = *bufptr++;
1303 self->z80cpu->SP.B.h = *bufptr++;
1304 self->z80cpu->PC.B.l = *bufptr++;
1305 self->z80cpu->PC.B.h = *bufptr++;
1306 switch(*bufptr++) {
1307 case 1:
1308 self->z80cpu->IF.W = (self->z80cpu->IF.W | IFF_IM1) & ~(IFF_IM2);
1309 break;
1310 case 2:
1311 self->z80cpu->IF.W = (self->z80cpu->IF.W | IFF_IM2) & ~(IFF_IM1);
1312 break;
1313 default:
1314 self->z80cpu->IF.W = (self->z80cpu->IF.W) & ~(IFF_IM1 | IFF_IM2);
1315 break;
1316 }
1317 self->z80cpu->AF1.B.l = *bufptr++;
1318 self->z80cpu->AF1.B.h = *bufptr++;
1319 self->z80cpu->BC1.B.l = *bufptr++;
1320 self->z80cpu->BC1.B.h = *bufptr++;
1321 self->z80cpu->DE1.B.l = *bufptr++;
1322 self->z80cpu->DE1.B.h = *bufptr++;
1323 self->z80cpu->HL1.B.l = *bufptr++;
1324 self->z80cpu->HL1.B.h = *bufptr++;
1325 self->garray->pen = *bufptr++;
1326 for(ix = 0; ix < 17; ix++) {
1327 self->garray->ink[ix] = *bufptr++;
1328 }
1329 self->garray->rom_cfg = *bufptr++;
1330 self->garray->ram_cfg = *bufptr++;
1331 amstrad_cpc_mem_select(self);
1332 self->mc6845->addr_reg = *bufptr++;
1333 for(ix = 0; ix < 18; ix++) {
1334 self->mc6845->reg_file[ix] = *bufptr++;
1335 }
1336 self->memory.expansion = *bufptr++;
1337 self->i8255->port_a = *bufptr++;
1338 self->i8255->port_b = *bufptr++;
1339 self->i8255->port_c = *bufptr++;
1340 self->i8255->control = *bufptr++;
1341 self->ay8910->addr_reg = *bufptr++;
1342 for(ix = 0; ix < 16; ix++) {
1343 self->ay8910->reg_file[ix] = *bufptr++;
1344 }
1345 ramsize |= *bufptr++ << 0;
1346 ramsize |= *bufptr++ << 8;
1347 if(ramsize > self->ramsize) {
1348 fprintf(stderr, "snapshot file too large (%d Kb)\n", ramsize);
1349 amstrad_cpc_reset();
1350 fclose(file);
1351 return;
1352 }
1353 fread(self->memory.total_ram, 1, ramsize * 1024, file);
1354 fclose(file);
1355 }
1356
amstrad_cpc_save_snapshot(char * filename)1357 void amstrad_cpc_save_snapshot(char *filename)
1358 {
1359 AMSTRAD_CPC *self = &amstrad_cpc;
1360 FILE *file;
1361 guint8 buffer[256], *bufptr = buffer;
1362 int ramsize = 0;
1363 int ix;
1364
1365 if((file = fopen(filename, "w")) == NULL) {
1366 perror("amstrad_cpc");
1367 return;
1368 }
1369 memcpy(bufptr, "MV - SNA", 8); bufptr += 8;
1370 memset(bufptr, 0, 8); bufptr += 8; /* not used */
1371 *bufptr++ = 1; /* snapshot version */
1372 *bufptr++ = self->z80cpu->AF.B.l;
1373 *bufptr++ = self->z80cpu->AF.B.h;
1374 *bufptr++ = self->z80cpu->BC.B.l;
1375 *bufptr++ = self->z80cpu->BC.B.h;
1376 *bufptr++ = self->z80cpu->DE.B.l;
1377 *bufptr++ = self->z80cpu->DE.B.h;
1378 *bufptr++ = self->z80cpu->HL.B.l;
1379 *bufptr++ = self->z80cpu->HL.B.h;
1380 *bufptr++ = self->z80cpu->IR.B.l;
1381 *bufptr++ = self->z80cpu->IR.B.h;
1382 *bufptr++ = (self->z80cpu->IF.W & IFF_1 ? 0x01 : 0x00);
1383 *bufptr++ = (self->z80cpu->IF.W & IFF_2 ? 0x01 : 0x00);
1384 *bufptr++ = self->z80cpu->IX.B.l;
1385 *bufptr++ = self->z80cpu->IX.B.h;
1386 *bufptr++ = self->z80cpu->IY.B.l;
1387 *bufptr++ = self->z80cpu->IY.B.h;
1388 *bufptr++ = self->z80cpu->SP.B.l;
1389 *bufptr++ = self->z80cpu->SP.B.h;
1390 *bufptr++ = self->z80cpu->PC.B.l;
1391 *bufptr++ = self->z80cpu->PC.B.h;
1392 switch(self->z80cpu->IF.W & (IFF_IM1 | IFF_IM2)) {
1393 case IFF_IM1:
1394 *bufptr++ = 0x01;
1395 break;
1396 case IFF_IM2:
1397 *bufptr++ = 0x02;
1398 break;
1399 default:
1400 *bufptr++ = 0x00;
1401 break;
1402 }
1403 *bufptr++ = self->z80cpu->AF1.B.l;
1404 *bufptr++ = self->z80cpu->AF1.B.h;
1405 *bufptr++ = self->z80cpu->BC1.B.l;
1406 *bufptr++ = self->z80cpu->BC1.B.h;
1407 *bufptr++ = self->z80cpu->DE1.B.l;
1408 *bufptr++ = self->z80cpu->DE1.B.h;
1409 *bufptr++ = self->z80cpu->HL1.B.l;
1410 *bufptr++ = self->z80cpu->HL1.B.h;
1411 *bufptr++ = self->garray->pen;
1412 for(ix = 0; ix < 17; ix++) {
1413 *bufptr++ = self->garray->ink[ix];
1414 }
1415 *bufptr++ = self->garray->rom_cfg;
1416 *bufptr++ = self->garray->ram_cfg;
1417 *bufptr++ = self->mc6845->addr_reg;
1418 for(ix = 0; ix < 18; ix++) {
1419 *bufptr++ = self->mc6845->reg_file[ix];
1420 }
1421 *bufptr++ = self->memory.expansion;
1422 *bufptr++ = self->i8255->port_a;
1423 *bufptr++ = self->i8255->port_b;
1424 *bufptr++ = self->i8255->port_c;
1425 *bufptr++ = self->i8255->control;
1426 *bufptr++ = self->ay8910->addr_reg;
1427 for(ix = 0; ix < 16; ix++) {
1428 *bufptr++ = self->ay8910->reg_file[ix];
1429 }
1430 *bufptr++ = (self->ramsize >> 0) & 0xff;
1431 *bufptr++ = (self->ramsize >> 8) & 0xff;
1432 memset(bufptr, 0, 147);
1433 bufptr += 147;
1434 fwrite(buffer, 1, 256, file);
1435 fwrite(self->memory.total_ram, 1, self->ramsize * 1024, file);
1436 fclose(file);
1437 }
1438
1439 /**
1440 * amstrad_cpc::z80cpu::mreq_rd
1441 *
1442 * @param z80cpu
1443 * @param addr
1444 *
1445 * @return
1446 */
z80cpu_mreq_rd(GdevZ80CPU * z80cpu,guint16 addr)1447 static guint8 z80cpu_mreq_rd(GdevZ80CPU *z80cpu, guint16 addr)
1448 {
1449 return(amstrad_cpc.rd_bank[addr >> 14][addr & 0x3fff]);
1450 }
1451
1452 /**
1453 * amstrad_cpc::z80cpu::mreq_wr
1454 *
1455 * @param z80cpu
1456 * @param addr
1457 * @param data
1458 */
z80cpu_mreq_wr(GdevZ80CPU * z80cpu,guint16 addr,guint8 data)1459 static void z80cpu_mreq_wr(GdevZ80CPU *z80cpu, guint16 addr, guint8 data)
1460 {
1461 amstrad_cpc.wr_bank[addr >> 14][addr & 0x3fff] = data;
1462 }
1463
1464 /**
1465 * amstrad_cpc::z80cpu::iorq_rd
1466 *
1467 * @param z80cpu
1468 * @param port
1469 *
1470 * @return
1471 */
z80cpu_iorq_rd(GdevZ80CPU * z80cpu,guint16 port)1472 static guint8 z80cpu_iorq_rd(GdevZ80CPU *z80cpu, guint16 port)
1473 {
1474 guint8 data = 0x00;
1475
1476 /* Gate-Array [0-------xxxxxxxx] [0x7fxx] */
1477 if((port & 0x8000) == 0) {
1478 (void) fprintf(stderr, "IO_RD[0x%04x]: Gate-Array [---- Illegal ----]\n", port);
1479 (void) fflush(stderr);
1480 }
1481 /* CRTC-6845 [-0------xxxxxxxx] [0xbfxx] */
1482 if((port & 0x4000) == 0) {
1483 switch((port >> 8) & 3) {
1484 case 0: /* [-0----00xxxxxxxx] [0xbcxx] */
1485 (void) fprintf(stderr, "IO_RD[0x%04x]: CRTC-6845 [---- Illegal ----]\n", port);
1486 (void) fflush(stderr);
1487 break;
1488 case 1: /* [-0----01xxxxxxxx] [0xbdxx] */
1489 (void) fprintf(stderr, "IO_RD[0x%04x]: CRTC-6845 [---- Illegal ----]\n", port);
1490 (void) fflush(stderr);
1491 break;
1492 case 2: /* [-0----10xxxxxxxx] [0xbexx] */
1493 (void) fprintf(stderr, "IO_RD[0x%04x]: CRTC-6845 [- Not Supported -]\n", port);
1494 (void) fflush(stderr);
1495 break;
1496 case 3: /* [-0----11xxxxxxxx] [0xbfxx] */
1497 data = amstrad_cpc.mc6845->reg_file[amstrad_cpc.mc6845->addr_reg];
1498 break;
1499 }
1500 }
1501 /* ROM Select [--0-----xxxxxxxx] [0xdfxx] */
1502 if((port & 0x2000) == 0) {
1503 (void) fprintf(stderr, "IO_RD[0x%04x]: ROM Select [---- Illegal ----]\n", port);
1504 (void) fflush(stderr);
1505 }
1506 /* Printer Port [---0----xxxxxxxx] [0xefxx] */
1507 if((port & 0x1000) == 0) {
1508 (void) fprintf(stderr, "IO_RD[0x%04x]: Printer Port [---- Illegal ----]\n", port);
1509 (void) fflush(stderr);
1510 }
1511 /* PPI-8255 [----0---xxxxxxxx] [0xf7xx] */
1512 if((port & 0x0800) == 0) {
1513 switch((port >> 8) & 3) {
1514 case 0: /* [----0-00xxxxxxxx] [0xf4xx] */
1515 amstrad_cpc.i8255->port_a = amstrad_cpc.cpckbd->bits[amstrad_cpc.cpckbd->line];
1516 data = amstrad_cpc.i8255->port_a;
1517 break;
1518 case 1: /* [----0-01xxxxxxxx] [0xf5xx] */
1519 amstrad_cpc.i8255->port_b = ((0 & 0x01) << 7)
1520 | ((1 & 0x01) << 6)
1521 | ((1 & 0x01) << 5)
1522 | ((amstrad_cpc.refresh & 0x01) << 4)
1523 | ((amstrad_cpc.firmname & 0x07) << 1)
1524 | ((amstrad_cpc.mc6845->v_syn & 0x01) << 0);
1525 data = amstrad_cpc.i8255->port_b;
1526 break;
1527 case 2: /* [----0-10xxxxxxxx] [0xf6xx] */
1528 data = amstrad_cpc.i8255->port_c;
1529 break;
1530 case 3: /* [----0-11xxxxxxxx] [0xf7xx] */
1531 (void) fprintf(stderr, "IO_RD[0x%04x]: PPI-8255 [---- Illegal ----]\n", port);
1532 (void) fflush(stderr);
1533 break;
1534 }
1535 }
1536 /* FDC-765 [-----0--0xxxxxxx] [0xfb7f] */
1537 if((port & 0x0480) == 0) {
1538 switch(((port >> 7) & 2) | (port & 1)) {
1539 case 0: /* [-----0-00xxxxxx0] [0xfa7e] */
1540 (void) fprintf(stderr, "IO_RD[0x%04x]: FDC-765 [---- Illegal ----]\n", port);
1541 (void) fflush(stderr);
1542 break;
1543 case 1: /* [-----0-00xxxxxx1] [0xfa7f] */
1544 (void) fprintf(stderr, "IO_RD[0x%04x]: FDC-765 [---- Illegal ----]\n", port);
1545 (void) fflush(stderr);
1546 break;
1547 case 2: /* [-----0-10xxxxxx0] [0xfb7e] */
1548 GDEV_FDC765_GET_CLASS(amstrad_cpc.upd765->fdc)->rstat(amstrad_cpc.upd765->fdc, &data);
1549 break;
1550 case 3: /* [-----0-10xxxxxx1] [0xfb7f] */
1551 GDEV_FDC765_GET_CLASS(amstrad_cpc.upd765->fdc)->rdata(amstrad_cpc.upd765->fdc, &data);
1552 break;
1553 }
1554 }
1555 return(data);
1556 }
1557
1558 /**
1559 * amstrad_cpc::z80cpu::iorq_wr
1560 *
1561 * @param z80cpu
1562 * @param port
1563 * @param data
1564 */
z80cpu_iorq_wr(GdevZ80CPU * z80cpu,guint16 port,guint8 data)1565 static void z80cpu_iorq_wr(GdevZ80CPU *z80cpu, guint16 port, guint8 data)
1566 {
1567 /* Gate-Array [0-------xxxxxxxx] [0x7fxx] */
1568 if((port & 0x8000) == 0) {
1569 switch((data >> 6) & 3) {
1570 case 0: /* Select pen */
1571 amstrad_cpc.garray->pen = (data & 0x10 ? 0x10 : data & 0x0f);
1572 break;
1573 case 1: /* Select color */
1574 amstrad_cpc.garray->ink[amstrad_cpc.garray->pen] = data & 0x1f;
1575 break;
1576 case 2: /* Interrupt control, ROM configuration and screen mode */
1577 if((data & 0x10) != 0) {
1578 amstrad_cpc.garray->counter = 0;
1579 amstrad_cpc.garray->gen_irq = 0;
1580 }
1581 amstrad_cpc.garray->rom_cfg = data & 0x1f;
1582 amstrad_cpc_mem_select(&amstrad_cpc);
1583 break;
1584 case 3: /* RAM memory management */
1585 amstrad_cpc.garray->ram_cfg = data & 0x3f;
1586 amstrad_cpc_mem_select(&amstrad_cpc);
1587 break;
1588 }
1589 }
1590 /* CRTC-6845 [-0------xxxxxxxx] [0xbfxx] */
1591 if((port & 0x4000) == 0) {
1592 switch((port >> 8) & 3) {
1593 case 0: /* [-0----00xxxxxxxx] [0xbcxx] */
1594 amstrad_cpc.mc6845->addr_reg = data;
1595 break;
1596 case 1: /* [-0----01xxxxxxxx] [0xbdxx] */
1597 amstrad_cpc.mc6845->reg_file[amstrad_cpc.mc6845->addr_reg] = data;
1598 break;
1599 case 2: /* [-0----10xxxxxxxx] [0xbexx] */
1600 (void) fprintf(stderr, "IO_WR[0x%04x]: CRTC-6845 [- Not Supported -]\n", port);
1601 (void) fflush(stderr);
1602 break;
1603 case 3: /* [-0----11xxxxxxxx] [0xbfxx] */
1604 (void) fprintf(stderr, "IO_WR[0x%04x]: CRTC-6845 [---- Illegal ----]\n", port);
1605 (void) fflush(stderr);
1606 break;
1607 }
1608 }
1609 /* ROM Select [--0-----xxxxxxxx] [0xdfxx] */
1610 if((port & 0x2000) == 0) {
1611 amstrad_cpc.memory.expansion = data;
1612 amstrad_cpc_mem_select(&amstrad_cpc);
1613 }
1614 /* Printer Port [---0----xxxxxxxx] [0xefxx] */
1615 if((port & 0x1000) == 0) {
1616 }
1617 /* PPI-8255 [----0---xxxxxxxx] [0xf7xx] */
1618 if((port & 0x0800) == 0) {
1619 switch((port >> 8) & 3) {
1620 case 0: /* [----0-00xxxxxxxx] [0xf4xx] */
1621 amstrad_cpc.i8255->port_a = data;
1622 break;
1623 case 1: /* [----0-01xxxxxxxx] [0xf5xx] */
1624 /*amstrad_cpc.i8255->port_b = data;*/
1625 break;
1626 case 2: /* [----0-10xxxxxxxx] [0xf6xx] */
1627 amstrad_cpc.i8255->port_c = data;
1628 amstrad_cpc.cpckbd->line = data & 0x0F;
1629 break;
1630 case 3: /* [----0-11xxxxxxxx] [0xf7xx] */
1631 amstrad_cpc.i8255->control = data;
1632 break;
1633 }
1634 }
1635 /* FDC-765 [-----0--0xxxxxxx] [0xfb7f] */
1636 if((port & 0x0480) == 0) {
1637 switch(((port >> 7) & 2) | ((port >> 0) & 1)) {
1638 case 0: /* [-----0-00xxxxxx0] [0xfa7e] */
1639 gdev_upd765_set_motor(amstrad_cpc.upd765, ((data & 1) << 1) | ((data & 1) << 0));
1640 break;
1641 case 1: /* [-----0-00xxxxxx1] [0xfa7f] */
1642 gdev_upd765_set_motor(amstrad_cpc.upd765, ((data & 1) << 1) | ((data & 1) << 0));
1643 break;
1644 case 2: /* [-----0-10xxxxxx0] [0xfb7e] */
1645 GDEV_FDC765_GET_CLASS(amstrad_cpc.upd765->fdc)->wstat(amstrad_cpc.upd765->fdc, &data);
1646 break;
1647 case 3: /* [-----0-10xxxxxx1] [0xfb7f] */
1648 GDEV_FDC765_GET_CLASS(amstrad_cpc.upd765->fdc)->wdata(amstrad_cpc.upd765->fdc, &data);
1649 break;
1650 }
1651 }
1652 }
1653
mc6845_hsync(GdevMC6845 * mc6845)1654 static void mc6845_hsync(GdevMC6845 *mc6845)
1655 {
1656 GdevGArray *garray = amstrad_cpc.garray;
1657
1658 if(mc6845->h_syn != 0) {
1659 garray->counter++;
1660 if(garray->delayed > 0) {
1661 if(--garray->delayed == 0) {
1662 if(garray->counter >= 32) {
1663 garray->gen_irq = 1;
1664 }
1665 garray->counter = 0;
1666 }
1667 }
1668 else {
1669 if(garray->counter == 52) {
1670 garray->counter = 0;
1671 garray->gen_irq = 1;
1672 }
1673 }
1674 }
1675 }
1676
mc6845_vsync(GdevMC6845 * mc6845)1677 static void mc6845_vsync(GdevMC6845 *mc6845)
1678 {
1679 GdevGArray *garray = amstrad_cpc.garray;
1680
1681 if(mc6845->v_syn != 0) {
1682 garray->delayed = 2;
1683 }
1684 }
1685
amstrad_cpc_start_handler(Widget widget,XtPointer data)1686 void amstrad_cpc_start_handler(Widget widget, XtPointer data)
1687 {
1688 AMSTRAD_CPC *self = &amstrad_cpc;
1689 int ix;
1690 FILE *file;
1691 Arg arglist[8];
1692 Cardinal argcount;
1693
1694 /* Model */
1695 if(cfg_model == NULL) {
1696 if(cfg_sys_rom == NULL) {
1697 cfg_sys_rom = g_build_filename(ROMSDIR, "cpc6128.rom", NULL);
1698 }
1699 if(cfg_exp_rom[7] == NULL) {
1700 cfg_exp_rom[7] = g_build_filename(ROMSDIR, "amsdos.rom", NULL);
1701 }
1702 self->keybd_hnd = gdev_cpckbd_qwerty;
1703 self->ramsize = 128;
1704 self->refresh = 1;
1705 self->firmname = 7;
1706 }
1707 else if(strcmp("cpc464", cfg_model) == 0) {
1708 if(cfg_sys_rom == NULL) {
1709 cfg_sys_rom = g_build_filename(ROMSDIR, "cpc464.rom", NULL);
1710 }
1711 if(cfg_exp_rom[7] == NULL) {
1712 cfg_exp_rom[7] = NULL;
1713 }
1714 self->keybd_hnd = gdev_cpckbd_qwerty;
1715 self->ramsize = 64;
1716 self->refresh = 1;
1717 self->firmname = 7;
1718 }
1719 else if(strcmp("cpc664", cfg_model) == 0) {
1720 if(cfg_sys_rom == NULL) {
1721 cfg_sys_rom = g_build_filename(ROMSDIR, "cpc664.rom", NULL);
1722 }
1723 if(cfg_exp_rom[7] == NULL) {
1724 cfg_exp_rom[7] = g_build_filename(ROMSDIR, "amsdos.rom", NULL);
1725 }
1726 self->keybd_hnd = gdev_cpckbd_qwerty;
1727 self->ramsize = 64;
1728 self->refresh = 1;
1729 self->firmname = 7;
1730 }
1731 else if(strcmp("cpc6128", cfg_model) == 0) {
1732 if(cfg_sys_rom == NULL) {
1733 cfg_sys_rom = g_build_filename(ROMSDIR, "cpc6128.rom", NULL);
1734 }
1735 if(cfg_exp_rom[7] == NULL) {
1736 cfg_exp_rom[7] = g_build_filename(ROMSDIR, "amsdos.rom", NULL);
1737 }
1738 self->keybd_hnd = gdev_cpckbd_qwerty;
1739 self->ramsize = 128;
1740 self->refresh = 1;
1741 self->firmname = 7;
1742 }
1743 else {
1744 if(cfg_sys_rom == NULL) {
1745 cfg_sys_rom = g_build_filename(ROMSDIR, "cpc6128.rom", NULL);
1746 }
1747 if(cfg_exp_rom[7] == NULL) {
1748 cfg_exp_rom[7] = g_build_filename(ROMSDIR, "amsdos.rom", NULL);
1749 }
1750 self->keybd_hnd = gdev_cpckbd_qwerty;
1751 self->ramsize = 128;
1752 self->refresh = 1;
1753 self->firmname = 7;
1754 }
1755 /* Keyboard handler */
1756 if(cfg_keyboard == NULL) {
1757 self->keybd_hnd = gdev_cpckbd_qwerty;
1758 }
1759 else if(strcmp("qwerty", cfg_keyboard) == 0) {
1760 self->keybd_hnd = gdev_cpckbd_qwerty;
1761 }
1762 else if(strcmp("azerty", cfg_keyboard) == 0) {
1763 self->keybd_hnd = gdev_cpckbd_azerty;
1764 }
1765 else {
1766 self->keybd_hnd = gdev_cpckbd_qwerty;
1767 }
1768 /* FirmName */
1769 if(cfg_firmname == NULL) {
1770 self->firmname = 7;
1771 }
1772 else if(strcmp("isp", cfg_firmname) == 0) {
1773 self->firmname = 0;
1774 }
1775 else if(strcmp("triumph", cfg_firmname) == 0) {
1776 self->firmname = 1;
1777 }
1778 else if(strcmp("saisho", cfg_firmname) == 0) {
1779 self->firmname = 2;
1780 }
1781 else if(strcmp("solavox", cfg_firmname) == 0) {
1782 self->firmname = 3;
1783 }
1784 else if(strcmp("awa", cfg_firmname) == 0) {
1785 self->firmname = 4;
1786 }
1787 else if(strcmp("schneider", cfg_firmname) == 0) {
1788 self->firmname = 5;
1789 }
1790 else if(strcmp("orion", cfg_firmname) == 0) {
1791 self->firmname = 6;
1792 }
1793 else if(strcmp("amstrad", cfg_firmname) == 0) {
1794 self->firmname = 7;
1795 }
1796 else {
1797 self->firmname = 7;
1798 }
1799 self->ximage = NULL;
1800 self->screen = NULL;
1801 self->visual = NULL;
1802 self->window = None;
1803 self->colmap = None;
1804 self->depth = 0;
1805 self->useshm = False;
1806 self->render = NULL;
1807 if((self->memory.total_ram = (guint8 *) malloc(self->ramsize * 1024)) == NULL) {
1808 perror("amstrad_cpc"); exit(-1);
1809 }
1810 /* Load System ROM */
1811 self->memory.lower_rom = gdev_cpcmem_new_from_file(cfg_sys_rom, 0x0000);
1812 self->memory.upper_rom = gdev_cpcmem_new_from_file(cfg_sys_rom, 0x4000);
1813 /* Load Expansion ROMs */
1814 for(ix = 0; ix < 256; ix++) {
1815 if(cfg_exp_rom[ix] != NULL) {
1816 self->memory.expan_rom[ix] = gdev_cpcmem_new_from_file(cfg_exp_rom[ix], 0);
1817 }
1818 else {
1819 self->memory.expan_rom[ix] = NULL;
1820 }
1821 }
1822 switch(self->refresh) {
1823 default:
1824 case 1:
1825 self->cpu_period = (int) (4000000.0 / (50.0 * 312.5));
1826 break;
1827 case 0:
1828 self->cpu_period = (int) (4000000.0 / (60.0 * 312.5));
1829 break;
1830 }
1831 self->z80cpu = gdev_z80cpu_new();
1832 self->garray = gdev_garray_new();
1833 self->cpckbd = gdev_cpckbd_new();
1834 self->mc6845 = gdev_mc6845_new();
1835 self->ay8910 = gdev_ay8910_new();
1836 self->upd765 = gdev_upd765_new();
1837 self->i8255 = gdev_i8255_new();
1838 /* XXX */
1839 self->z80cpu->mreq_rd = z80cpu_mreq_rd;
1840 self->z80cpu->mreq_wr = z80cpu_mreq_wr;
1841 self->z80cpu->iorq_rd = z80cpu_iorq_rd;
1842 self->z80cpu->iorq_wr = z80cpu_iorq_wr;
1843 self->mc6845->hsync = mc6845_hsync;
1844 self->mc6845->vsync = mc6845_vsync;
1845 gdev_upd765_set_fdc(self->upd765, gdev_fdc765_new());
1846 gdev_upd765_set_fdd(self->upd765, gdev_fdd765_new(), 0);
1847 gdev_upd765_set_fdd(self->upd765, gdev_fdd765_new(), 1);
1848 amstrad_cpc_reset();
1849 (void) gettimeofday(&self->timer1, NULL);
1850 (void) gettimeofday(&self->timer2, NULL);
1851 self->gtimer = g_timer_new();
1852 self->num_frames = 0;
1853 self->drw_frames = 0;
1854 }
1855
amstrad_cpc_clock_handler(Widget widget,XtPointer data)1856 void amstrad_cpc_clock_handler(Widget widget, XtPointer data)
1857 {
1858 AMSTRAD_CPC *self = &amstrad_cpc;
1859 GdevZ80CPU *z80cpu = self->z80cpu;
1860 GdevDeviceClass *z80cpu_class = GDEV_DEVICE_GET_CLASS(z80cpu);
1861 GdevMC6845 *mc6845 = self->mc6845;
1862 GdevDeviceClass *mc6845_class = GDEV_DEVICE_GET_CLASS(mc6845);
1863 GdevGArray *garray = self->garray;
1864 long delay, ix;
1865 int scanline = 0;
1866
1867 do {
1868 struct _scanline *sl = &self->scanline[scanline];
1869 sl->mode = garray->rom_cfg & 0x03;
1870 for(ix = 0; ix < 17; ix++) {
1871 sl->ink[ix] = self->palette[garray->ink[ix]].pixel;
1872 }
1873 for(ix = 0; ix < self->cpu_period; ix += 4) {
1874 (*mc6845_class->clock)(GDEV_DEVICE(mc6845));
1875 if(garray->gen_irq > 0) {
1876 if(--garray->gen_irq == 0) {
1877 gdev_z80cpu_intr(z80cpu, INT_RST38);
1878 garray->counter &= 31;
1879 }
1880 }
1881 if((z80cpu->t_states += 4) > 0) {
1882 gint t_states = z80cpu->t_states;
1883 (*z80cpu_class->clock)(GDEV_DEVICE(z80cpu));
1884 z80cpu->t_states = t_states - ((t_states - z80cpu->t_states) + 3 & (~3));
1885 }
1886 }
1887 } while(++scanline < 312);
1888 (void) gettimeofday(&self->timer2, NULL);
1889 delay = ((long) (self->timer2.tv_sec - self->timer1.tv_sec) * 1000)
1890 + ((long) (self->timer2.tv_usec - self->timer1.tv_usec) / 1000);
1891 if(delay >= 1000) {
1892 *(&self->timer1) = *(&self->timer2); delay = 0;
1893 }
1894 switch(self->refresh) {
1895 case 1:
1896 if((delay >= 0) && (delay <= 20) && (self->render != NULL)) {
1897 (*self->render)(self); self->drw_frames++;
1898 }
1899 if((self->timer1.tv_usec += 20000) >= 1000000) {
1900 self->timer1.tv_usec -= 1000000; self->timer1.tv_sec++;
1901 }
1902 if(++self->num_frames == 50) {
1903 (void) sprintf(self->status, "%2d Hz / %.2f fps", self->num_frames, ((gdouble) self->drw_frames / g_timer_elapsed(self->gtimer, NULL)));
1904 self->num_frames = self->drw_frames = 0;
1905 g_timer_start(self->gtimer);
1906 }
1907 break;
1908 case 0:
1909 if((delay >= 0) && (delay <= 16) && (self->render != NULL)) {
1910 (*self->render)(self); self->drw_frames++;
1911 }
1912 if((self->timer1.tv_usec += 16667) >= 1000000) {
1913 self->timer1.tv_usec -= 1000000; self->timer1.tv_sec++;
1914 }
1915 if(++self->num_frames == 60) {
1916 (void) sprintf(self->status, "%2d Hz / %.2f fps", self->num_frames, ((gdouble) self->drw_frames / g_timer_elapsed(self->gtimer, NULL)));
1917 self->num_frames = self->drw_frames = 0;
1918 g_timer_start(self->gtimer);
1919 }
1920 break;
1921 }
1922 (void) gettimeofday(&self->timer2, NULL);
1923 delay = ((long) (self->timer1.tv_sec - self->timer2.tv_sec) * 1000)
1924 + ((long) (self->timer1.tv_usec - self->timer2.tv_usec) / 1000);
1925 if(delay > 0) {
1926 *((unsigned long *) data) = (unsigned long) (delay - 1);
1927 }
1928 else {
1929 *((unsigned long *) data) = (unsigned long) (1);
1930 }
1931 }
1932
amstrad_cpc_close_handler(Widget widget,XtPointer data)1933 void amstrad_cpc_close_handler(Widget widget, XtPointer data)
1934 {
1935 AMSTRAD_CPC *self = &amstrad_cpc;
1936 int ix;
1937
1938 if(self->gtimer != NULL) {
1939 g_timer_destroy(self->gtimer);
1940 self->gtimer = (GTimer *) NULL;
1941 }
1942 if(self->ximage != NULL) {
1943 amstrad_cpc_fini_image(self);
1944 }
1945 if(self->memory.lower_rom != NULL) {
1946 g_object_unref(self->memory.lower_rom);
1947 self->memory.lower_rom = NULL;
1948 }
1949 if(self->memory.upper_rom != NULL) {
1950 g_object_unref(self->memory.upper_rom);
1951 self->memory.upper_rom = NULL;
1952 }
1953 if(self->memory.total_ram != NULL) {
1954 free(self->memory.total_ram);
1955 self->memory.total_ram = NULL;
1956 }
1957 for(ix = 0; ix < 256; ix++) {
1958 if(self->memory.expan_rom[ix] != NULL) {
1959 g_object_unref(self->memory.expan_rom[ix]);
1960 self->memory.expan_rom[ix] = NULL;
1961 }
1962 }
1963 g_object_unref(self->z80cpu); self->z80cpu = NULL;
1964 g_object_unref(self->garray); self->garray = NULL;
1965 g_object_unref(self->cpckbd); self->cpckbd = NULL;
1966 g_object_unref(self->mc6845); self->mc6845 = NULL;
1967 g_object_unref(self->ay8910); self->ay8910 = NULL;
1968 g_object_unref(self->upd765); self->upd765 = NULL;
1969 g_object_unref(self->i8255); self->i8255 = NULL;
1970 }
1971
amstrad_cpc_input_handler(Widget widget,XEvent * xevent)1972 void amstrad_cpc_input_handler(Widget widget, XEvent *xevent)
1973 {
1974 if(amstrad_cpc.keybd_hnd != NULL) {
1975 (*amstrad_cpc.keybd_hnd)(amstrad_cpc.cpckbd, xevent);
1976 }
1977 }
1978
amstrad_cpc_paint_handler(Widget widget,XEvent * xevent)1979 void amstrad_cpc_paint_handler(Widget widget, XEvent *xevent)
1980 {
1981 AMSTRAD_CPC *self = &amstrad_cpc;
1982
1983 if(self->window == None) {
1984 XWindowAttributes xwinattr;
1985 if(XGetWindowAttributes(xevent->xexpose.display, xevent->xexpose.window, &xwinattr) != 0) {
1986 self->screen = xwinattr.screen;
1987 self->visual = xwinattr.visual;
1988 self->window = xevent->xexpose.window;
1989 self->colmap = xwinattr.colormap;
1990 self->depth = xwinattr.depth;
1991 self->useshm = False;
1992 }
1993 if(self->ximage == NULL) {
1994 amstrad_cpc_init_image(self);
1995 }
1996 (void) XResizeWindow(xevent->xexpose.display, xevent->xexpose.window, AMSTRAD_CPC_SCR_W, AMSTRAD_CPC_SCR_H);
1997 }
1998 if(self->ximage != NULL) {
1999 (void) XPutImage(xevent->xexpose.display,
2000 xevent->xexpose.window,
2001 DefaultGCOfScreen(self->screen),
2002 self->ximage,
2003 xevent->xexpose.x, xevent->xexpose.y,
2004 xevent->xexpose.x, xevent->xexpose.y,
2005 xevent->xexpose.width, xevent->xexpose.height);
2006 (void) XFlush(DisplayOfScreen(self->screen));
2007 }
2008 }
2009