/* * libtilemcore - Graphing calculator emulation library * * Copyright (C) 2009 Benjamin Moody * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see * . */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include "tilem.h" #include "z80.h" extern const TilemHardware hardware_ti73, hardware_ti76, hardware_ti81, hardware_ti82, hardware_ti83, hardware_ti83p, hardware_ti83pse, hardware_ti84p, hardware_ti84pse, hardware_ti84pns, hardware_ti85, hardware_ti86; const TilemHardware* hwmodels[] = { &hardware_ti73, &hardware_ti76, &hardware_ti81, &hardware_ti82, &hardware_ti83, &hardware_ti83p, &hardware_ti83pse, &hardware_ti84p, &hardware_ti84pse, &hardware_ti84pns, &hardware_ti85, &hardware_ti86 }; #define NUM_MODELS (sizeof(hwmodels) / sizeof(TilemHardware*)) void tilem_get_supported_hardware(const TilemHardware*** models, int* nmodels) { *models = hwmodels; *nmodels = NUM_MODELS; } void tilem_calc_reset(TilemCalc* calc) { tilem_z80_reset(calc); tilem_lcd_reset(calc); tilem_linkport_reset(calc); tilem_keypad_reset(calc); tilem_flash_reset(calc); tilem_md5_assist_reset(calc); tilem_user_timers_reset(calc); if (calc->hw.reset) (*calc->hw.reset)(calc); } TilemCalc* tilem_calc_new(char id) { int i; TilemCalc* calc; dword msize; for (i = 0; i < (int) NUM_MODELS; i++) { if (hwmodels[i]->model_id == id) { calc = tilem_try_new0(TilemCalc, 1); if (!calc) { return NULL; } calc->hw = *hwmodels[i]; calc->poweronhalt = 1; calc->battery = 60; calc->hwregs = tilem_try_new_atomic(dword, calc->hw.nhwregs); if (!calc->hwregs) { tilem_free(calc); return NULL; } memset(calc->hwregs, 0, calc->hw.nhwregs * sizeof(dword)); msize = (calc->hw.romsize + calc->hw.ramsize + calc->hw.lcdmemsize); calc->mem = tilem_try_new_atomic(byte, msize); if (!calc->mem) { tilem_free(calc->hwregs); tilem_free(calc); return NULL; } calc->ram = calc->mem + calc->hw.romsize; calc->lcdmem = calc->ram + calc->hw.ramsize; memset(calc->ram, 0, msize - calc->hw.romsize); calc->lcd.emuflags = TILEM_LCD_REQUIRE_DELAY; calc->flash.emuflags = TILEM_FLASH_REQUIRE_DELAY; tilem_calc_reset(calc); return calc; } } fprintf(stderr, "INTERNAL ERROR: invalid model ID '%c'\n", id); return NULL; } TilemCalc* tilem_calc_copy(TilemCalc* calc) { TilemCalc* newcalc; dword msize; newcalc = tilem_try_new(TilemCalc, 1); if (!newcalc) return NULL; memcpy(newcalc, calc, sizeof(TilemCalc)); newcalc->hwregs = tilem_try_new_atomic(dword, calc->hw.nhwregs); if (!newcalc->hwregs) { tilem_free(newcalc); return NULL; } memcpy(newcalc->hwregs, calc->hwregs, calc->hw.nhwregs * sizeof(dword)); newcalc->z80.timers = tilem_try_new(TilemZ80Timer, newcalc->z80.ntimers); if (!newcalc->z80.timers) { tilem_free(newcalc->hwregs); tilem_free(newcalc); return NULL; } memcpy(newcalc->z80.timers, calc->z80.timers, newcalc->z80.ntimers * sizeof(TilemZ80Timer)); newcalc->z80.breakpoints = tilem_try_new(TilemZ80Breakpoint, newcalc->z80.nbreakpoints); if (!newcalc->z80.breakpoints) { tilem_free(newcalc->z80.timers); tilem_free(newcalc->hwregs); tilem_free(newcalc); return NULL; } memcpy(newcalc->z80.breakpoints, calc->z80.breakpoints, newcalc->z80.nbreakpoints * sizeof(TilemZ80Breakpoint)); msize = (calc->hw.romsize + calc->hw.ramsize + calc->hw.lcdmemsize); newcalc->mem = tilem_try_new_atomic(byte, msize); if (!newcalc->mem) { tilem_free(newcalc->z80.breakpoints); tilem_free(newcalc->z80.timers); tilem_free(newcalc->hwregs); tilem_free(newcalc); return NULL; } memcpy(newcalc->mem, calc->mem, msize * sizeof(byte)); newcalc->ram = newcalc->mem + calc->hw.romsize; newcalc->lcdmem = newcalc->ram + calc->hw.ramsize; return newcalc; } void tilem_calc_free(TilemCalc* calc) { tilem_free(calc->mem); tilem_free(calc->hwregs); tilem_free(calc->z80.breakpoints); tilem_free(calc->z80.timers); tilem_free(calc); }