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