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