1 /*
2 * libtilemcore - Graphing calculator emulation library
3 *
4 * Copyright (C) 2009 Benjamin Moody
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public License
8 * as published by the Free Software Foundation; either version 2.1 of
9 * the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see
18 * <http://www.gnu.org/licenses/>.
19 */
20
21 #ifdef HAVE_CONFIG_H
22 # include <config.h>
23 #endif
24
25 #include <stdio.h>
26 #include <string.h>
27 #include "tilem.h"
28 #include "z80.h"
29
30 extern const TilemHardware hardware_ti73, hardware_ti76,
31 hardware_ti81, hardware_ti82, hardware_ti83,
32 hardware_ti83p, hardware_ti83pse, hardware_ti84p,
33 hardware_ti84pse, hardware_ti84pns,
34 hardware_ti85, hardware_ti86;
35
36 const TilemHardware* hwmodels[] = {
37 &hardware_ti73,
38 &hardware_ti76,
39 &hardware_ti81,
40 &hardware_ti82,
41 &hardware_ti83,
42 &hardware_ti83p,
43 &hardware_ti83pse,
44 &hardware_ti84p,
45 &hardware_ti84pse,
46 &hardware_ti84pns,
47 &hardware_ti85,
48 &hardware_ti86 };
49
50 #define NUM_MODELS (sizeof(hwmodels) / sizeof(TilemHardware*))
51
tilem_get_supported_hardware(const TilemHardware *** models,int * nmodels)52 void tilem_get_supported_hardware(const TilemHardware*** models,
53 int* nmodels)
54 {
55 *models = hwmodels;
56 *nmodels = NUM_MODELS;
57 }
58
tilem_calc_reset(TilemCalc * calc)59 void tilem_calc_reset(TilemCalc* calc)
60 {
61 tilem_z80_reset(calc);
62 tilem_lcd_reset(calc);
63 tilem_linkport_reset(calc);
64 tilem_keypad_reset(calc);
65 tilem_flash_reset(calc);
66 tilem_md5_assist_reset(calc);
67 tilem_user_timers_reset(calc);
68 if (calc->hw.reset)
69 (*calc->hw.reset)(calc);
70 }
71
tilem_calc_new(char id)72 TilemCalc* tilem_calc_new(char id)
73 {
74 int i;
75 TilemCalc* calc;
76 dword msize;
77
78 for (i = 0; i < (int) NUM_MODELS; i++) {
79 if (hwmodels[i]->model_id == id) {
80 calc = tilem_try_new0(TilemCalc, 1);
81 if (!calc) {
82 return NULL;
83 }
84
85 calc->hw = *hwmodels[i];
86
87 calc->poweronhalt = 1;
88 calc->battery = 60;
89 calc->hwregs = tilem_try_new_atomic(dword, calc->hw.nhwregs);
90 if (!calc->hwregs) {
91 tilem_free(calc);
92 return NULL;
93 }
94
95 memset(calc->hwregs, 0, calc->hw.nhwregs * sizeof(dword));
96
97 msize = (calc->hw.romsize + calc->hw.ramsize
98 + calc->hw.lcdmemsize);
99
100 calc->mem = tilem_try_new_atomic(byte, msize);
101 if (!calc->mem) {
102 tilem_free(calc->hwregs);
103 tilem_free(calc);
104 return NULL;
105 }
106
107 calc->ram = calc->mem + calc->hw.romsize;
108 calc->lcdmem = calc->ram + calc->hw.ramsize;
109
110 memset(calc->ram, 0, msize - calc->hw.romsize);
111
112 calc->lcd.emuflags = TILEM_LCD_REQUIRE_DELAY;
113 calc->flash.emuflags = TILEM_FLASH_REQUIRE_DELAY;
114
115 tilem_calc_reset(calc);
116 return calc;
117 }
118 }
119
120 fprintf(stderr, "INTERNAL ERROR: invalid model ID '%c'\n", id);
121 return NULL;
122 }
123
tilem_calc_copy(TilemCalc * calc)124 TilemCalc* tilem_calc_copy(TilemCalc* calc)
125 {
126 TilemCalc* newcalc;
127 dword msize;
128
129 newcalc = tilem_try_new(TilemCalc, 1);
130 if (!newcalc)
131 return NULL;
132 memcpy(newcalc, calc, sizeof(TilemCalc));
133
134 newcalc->hwregs = tilem_try_new_atomic(dword, calc->hw.nhwregs);
135 if (!newcalc->hwregs) {
136 tilem_free(newcalc);
137 return NULL;
138 }
139 memcpy(newcalc->hwregs, calc->hwregs, calc->hw.nhwregs * sizeof(dword));
140
141 newcalc->z80.timers = tilem_try_new(TilemZ80Timer,
142 newcalc->z80.ntimers);
143 if (!newcalc->z80.timers) {
144 tilem_free(newcalc->hwregs);
145 tilem_free(newcalc);
146 return NULL;
147 }
148 memcpy(newcalc->z80.timers, calc->z80.timers,
149 newcalc->z80.ntimers * sizeof(TilemZ80Timer));
150
151 newcalc->z80.breakpoints = tilem_try_new(TilemZ80Breakpoint,
152 newcalc->z80.nbreakpoints);
153 if (!newcalc->z80.breakpoints) {
154 tilem_free(newcalc->z80.timers);
155 tilem_free(newcalc->hwregs);
156 tilem_free(newcalc);
157 return NULL;
158 }
159 memcpy(newcalc->z80.breakpoints, calc->z80.breakpoints,
160 newcalc->z80.nbreakpoints * sizeof(TilemZ80Breakpoint));
161
162 msize = (calc->hw.romsize + calc->hw.ramsize + calc->hw.lcdmemsize);
163 newcalc->mem = tilem_try_new_atomic(byte, msize);
164 if (!newcalc->mem) {
165 tilem_free(newcalc->z80.breakpoints);
166 tilem_free(newcalc->z80.timers);
167 tilem_free(newcalc->hwregs);
168 tilem_free(newcalc);
169 return NULL;
170 }
171 memcpy(newcalc->mem, calc->mem, msize * sizeof(byte));
172
173 newcalc->ram = newcalc->mem + calc->hw.romsize;
174 newcalc->lcdmem = newcalc->ram + calc->hw.ramsize;
175
176 return newcalc;
177 }
178
tilem_calc_free(TilemCalc * calc)179 void tilem_calc_free(TilemCalc* calc)
180 {
181 tilem_free(calc->mem);
182 tilem_free(calc->hwregs);
183 tilem_free(calc->z80.breakpoints);
184 tilem_free(calc->z80.timers);
185 tilem_free(calc);
186 }
187