From 634f2e4f1f6cf32e5546f5a6445c0f719cc757bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomislav=20Kopi=C4=87?= Date: Tue, 11 Jun 2024 18:36:51 +0200 Subject: [PATCH] first commit --- Cubegotchi.ino | 380 +++++++++ bitmaps.h | 85 ++ cpu.c | 2003 +++++++++++++++++++++++++++++++++++++++++++++ cpu.h | 164 ++++ hal.h | 89 ++ hal_types.h | 34 + hardcoded_state.h | 25 + hw.c | 142 ++++ hw.h | 59 ++ rom_12bit.h | 514 ++++++++++++ savestate.cpp | 96 +++ savestate.h | 15 + tamalib.c | 171 ++++ tamalib.h | 76 ++ 14 files changed, 3853 insertions(+) create mode 100644 Cubegotchi.ino create mode 100644 bitmaps.h create mode 100644 cpu.c create mode 100644 cpu.h create mode 100644 hal.h create mode 100644 hal_types.h create mode 100644 hardcoded_state.h create mode 100644 hw.c create mode 100644 hw.h create mode 100644 rom_12bit.h create mode 100644 savestate.cpp create mode 100644 savestate.h create mode 100644 tamalib.c create mode 100644 tamalib.h diff --git a/Cubegotchi.ino b/Cubegotchi.ino new file mode 100644 index 0000000..8723f61 --- /dev/null +++ b/Cubegotchi.ino @@ -0,0 +1,380 @@ +#include +#include +#include "tamalib.h" +#include "hw.h" +#include "bitmaps.h" +#include "hardcoded_state.h" +#include "savestate.h" + +/***** U8g2 SSD1306 Library Setting *****/ +#define DISPLAY_I2C_ADDRESS 0x3C +#define SCREEN_WIDTH 128 // OLED display width, in pixels +#define SCREEN_HEIGHT 64 // OLED display height, in pixels +/****************************************/ + +/***** Tama Setting and Features *****/ +#define TAMA_DISPLAY_FRAMERATE 10 +//#define ENABLE_TAMA_SOUND +#define ENABLE_REAL_TIME +#define ENABLE_SAVE_STATUS +#define AUTO_SAVE_MINUTES 5 // Auto save for every hour (to preserve EEPROM lifespan) +#define ENABLE_LOAD_STATE_FROM_EEPROM +//#define ENABLE_DUMP_STATE_TO_SERIAL_WHEN_START +// #define ENABLE_SERIAL_DUMP +//#define ENABLE_SERIAL_DEBUG_INPUT +//#define ENABLE_LOAD_HARCODED_STATE_WHEN_START +/***************************/ + +/***** Set display orientation, U8G2_MIRROR_VERTICAL is not supported *****/ +//#define U8G2_LAYOUT_NORMAL +#define U8G2_LAYOUT_ROTATE_180 +//#define U8G2_LAYOUT_MIRROR +/**************************************************************************/ + +#ifdef U8G2_LAYOUT_NORMAL +U8G2_SSD1306_128X64_NONAME_2_HW_I2C display(U8G2_R0); +#endif + +#ifdef U8G2_LAYOUT_ROTATE_180 +U8G2_SSD1306_128X64_NONAME_2_HW_I2C display(U8G2_R2); +#endif + +#ifdef U8G2_LAYOUT_MIRROR +U8G2_SSD1306_128X64_NONAME_2_HW_I2C display(U8G2_MIRROR); +#endif + +#define PIN_BTN_L 12 // D6 +#define PIN_BTN_M 13 // D7 +#define PIN_BTN_R 15 // D8 +//define PIN_BTN_SAVE 3 +#define PIN_BUZZER 14 // D5 + +/**** TamaLib Specific Variables ****/ +static uint16_t current_freq = 0; +static bool_t matrix_buffer[LCD_HEIGHT][LCD_WIDTH/8] = {{0}}; +static byte runOnceBool = 0; +static bool_t icon_buffer[ICON_NUM] = {0}; +static cpu_state_t cpuState; +static unsigned long lastSaveTimestamp = 0; +/************************************/ + +static void hal_halt(void) { + //Serial.println("Halt!"); +} + +static void hal_log(log_level_t level, char *buff, ...) { + Serial.println(buff); +} + +static void hal_sleep_until(timestamp_t ts) { + #ifdef ENABLE_REAL_TIME + while (true) { + // Calculate the remaining time until the target timestamp + int32_t remaining = (int32_t)(ts - hal_get_timestamp()); + // Exit the loop if the target time has been reached or passed + if (remaining <= 0) { + break; + } + delayMicroseconds(remaining+5000); // Delay for remaining microseconds + Serial.println(remaining); + } + #endif +} + +// Get the current timestamp in microseconds +static timestamp_t hal_get_timestamp(void) { + return micros(); +} + +static void hal_update_screen(void) { + displayTama(); +} + +static void hal_set_lcd_matrix(u8_t x, u8_t y, bool_t val) { + uint8_t mask; + if (val) { + mask = 0b10000000 >> (x % 8); + matrix_buffer[y][x/8] = matrix_buffer[y][x/8] | mask; + } else { + mask = 0b01111111; + for(byte i=0;i<(x % 8);i++) { + mask = (mask >> 1) | 0b10000000; + } + matrix_buffer[y][x/8] = matrix_buffer[y][x/8] & mask; + } +} + +static void hal_set_lcd_icon(u8_t icon, bool_t val) { + icon_buffer[icon] = val; +} + +static void hal_set_frequency(u32_t freq) { + current_freq = freq; +} + +static void hal_play_frequency(bool_t en) { +#ifdef ENABLE_TAMA_SOUND + if (en) { + tone(PIN_BUZZER, current_freq); + } else { + noTone(PIN_BUZZER); + } +#endif +} + +static bool_t button4state = 0; + +static int hal_handler(void) { +#ifdef ENABLE_SERIAL_DUMP + if (Serial.available() > 0) { + int incomingByte = Serial.read(); + Serial.println(incomingByte, DEC); + if (incomingByte==48) { // 0 + dumpStateToSerial(); + } + } +#endif +#ifdef ENABLE_SERIAL_DEBUG_INPUT + if (Serial.available() > 0) { + int incomingByte = Serial.read(); + Serial.println(incomingByte, DEC); + if (incomingByte==49) { // 1 + hw_set_button(BTN_LEFT, BTN_STATE_PRESSED ); + } else if (incomingByte==52) { // 4 which is above 1 on a pad + hw_set_button(BTN_LEFT, BTN_STATE_RELEASED ); + } else if (incomingByte==50) { // 2 + hw_set_button(BTN_MIDDLE, BTN_STATE_PRESSED ); + } else if (incomingByte==53) { // 5 which is above 2 on a pad + hw_set_button(BTN_MIDDLE, BTN_STATE_RELEASED ); + } else if (incomingByte==51) { // 3 + hw_set_button(BTN_RIGHT, BTN_STATE_PRESSED ); + } else if (incomingByte==54) { // 6 which is above 3 on a pad + hw_set_button(BTN_RIGHT, BTN_STATE_RELEASED ); + } + } +#else + if (digitalRead(PIN_BTN_L) == HIGH) { + hw_set_button(BTN_LEFT, BTN_STATE_PRESSED ); + } else { + hw_set_button(BTN_LEFT, BTN_STATE_RELEASED ); + } + if (digitalRead(PIN_BTN_M) == HIGH) { + hw_set_button(BTN_MIDDLE, BTN_STATE_PRESSED ); + } else { + hw_set_button(BTN_MIDDLE, BTN_STATE_RELEASED ); + } + if (digitalRead(PIN_BTN_R) == HIGH) { + hw_set_button(BTN_RIGHT, BTN_STATE_PRESSED ); + } else { + hw_set_button(BTN_RIGHT, BTN_STATE_RELEASED ); + } + #ifdef ENABLE_SAVE_STATUS + if (digitalRead(PIN_BTN_L) == HIGH && digitalRead(PIN_BTN_M) == HIGH && digitalRead(PIN_BTN_R) == HIGH) { + if (button4state==0) { + + saveStateToEEPROM(&cpuState); + + noTone(PIN_BUZZER); + tone(PIN_BUZZER, 700,100); + delay(120); + noTone(PIN_BUZZER); + tone(PIN_BUZZER, 880,100); + delay(120); + noTone(PIN_BUZZER); + tone(PIN_BUZZER, 1175,100); + delay(120); + noTone(PIN_BUZZER); + } + button4state = 1; + } else { + button4state = 0; + } + #endif + +#endif + return 0; +} + +static hal_t hal = { + .halt = &hal_halt, + .log = &hal_log, + .sleep_until = &hal_sleep_until, + .get_timestamp = &hal_get_timestamp, + .update_screen = &hal_update_screen, + .set_lcd_matrix = &hal_set_lcd_matrix, + .set_lcd_icon = &hal_set_lcd_icon, + .set_frequency = &hal_set_frequency, + .play_frequency = &hal_play_frequency, + .handler = &hal_handler, +}; + +/* +void drawTriangle(uint8_t x, uint8_t y) { + //display.drawLine(x,y,x+6,y); + display.drawLine(x+1,y+1,x+5,y+1); + display.drawLine(x+2,y+2,x+4,y+2); + display.drawLine(x+3,y+3,x+3,y+3); +} +*/ + +void drawTamaRow(uint8_t tamaLCD_y, uint8_t ActualLCD_y, uint8_t thick) { + uint8_t i; + for (i = 0; i < LCD_WIDTH; i++) { + uint8_t mask = 0b10000000; + mask = mask >> (i % 8); + if ( (matrix_buffer[tamaLCD_y][i/8] & mask) != 0) { + display.drawBox(i+i+i+16,ActualLCD_y,2,thick); + } + } +} + +void drawTamaSelection(uint8_t y) { + uint8_t i; + for(i=0;i<8;i++) { + if (icon_buffer[i]) { + // drawTriangle(i*16+5,y); + display.drawXBMP(i*16+4,y+6,8,8,bitmaps+i*8); + } + } +} + +void displayTama() { + uint8_t j; + display.firstPage(); +#ifdef U8G2_LAYOUT_ROTATE_180 + drawTamaSelection(49); + display.nextPage(); + + for (j = 11; j < LCD_HEIGHT; j++) { + drawTamaRow(j,j+j+j,2); + } + display.nextPage(); + + for (j = 5; j <= 10; j++) { + if (j==5) { + drawTamaRow(j,j+j+j+1,1); + } else { + drawTamaRow(j,j+j+j,2); + } + } + display.nextPage(); + + for (j = 0; j <= 5; j++) { + if (j==5) { + drawTamaRow(j,j+j+j,1); + } else { + drawTamaRow(j,j+j+j,2); + } + } + display.nextPage(); +#else + for (j = 0; j < LCD_HEIGHT; j++) { + if (j!=5) drawTamaRow(j,j+j+j,2); + if (j==5) { + drawTamaRow(j,j+j+j,1); + display.nextPage(); + drawTamaRow(j,j+j+j+1,1); + } + if (j==10) display.nextPage(); + } + display.nextPage(); + drawTamaSelection(49); + display.nextPage(); +#endif +} + +#if defined(ENABLE_DUMP_STATE_TO_SERIAL_WHEN_START) || defined(ENABLE_SERIAL_DUMP) +void dumpStateToSerial() { + uint16_t i, count=0; + char tmp[10]; + cpu_get_state(&cpuState); + u4_t *memTemp = cpuState.memory; + uint8_t *cpuS = (uint8_t *)&cpuState; + + Serial.println(""); + Serial.println("static const uint8_t hardcodedState[] PROGMEM = {"); + for(i=0;i (AUTO_SAVE_MINUTES * 60 * 1000)) { + lastSaveTimestamp = millis(); + saveStateToEEPROM(&cpuState); + } +#endif +} diff --git a/bitmaps.h b/bitmaps.h new file mode 100644 index 0000000..2e3c3e8 --- /dev/null +++ b/bitmaps.h @@ -0,0 +1,85 @@ +static const uint8_t bitmaps[] PROGMEM = { +0xA9,0xAB,0xFB,0x77,0x27,0x23,0x21,0x21, +0x42,0x18,0xA5,0x24,0x18,0x42,0x18,0x00, +0xE7,0xAF,0xEF,0x1E,0x38,0x30,0xC0,0xC0, +0x1C,0x0E,0x1F,0x37,0x6D,0x78,0xF0,0xC0, +0x60,0x93,0x9D,0x53,0x4D,0x41,0x63,0x3E, +0x00,0x7E,0x81,0xAB,0xAB,0x91,0x4A,0x3C, +0x00,0x02,0x05,0x75,0xE5,0xCA,0xE0,0x70, +0x00,0x70,0x88,0xDE,0xA5,0x7B,0x11,0x0E +}; + + static uint8_t bitmaps_raw[] = { + +0b10101001, +0b10101011, +0b11111011, +0b01110111, +0b00100111, +0b00100011, +0b00100001, +0b00100001, + +0b01000010, +0b00011000, +0b10100101, +0b00100100, +0b00011000, +0b01000010, +0b00011000, +0b00000000, + +0b11100111, +0b10101111, +0b11101111, +0b00011110, +0b00111000, +0b00110000, +0b11000000, +0b11000000, + +0b00011100, +0b00001110, +0b00011111, +0b00110111, +0b01101101, +0b01111000, +0b11110000, +0b11000000, + +0b01100000, +0b10010011, +0b10011101, +0b01010011, +0b01001101, +0b01000001, +0b01100011, +0b00111110, + +0b00000000, +0b01111110, +0b10000001, +0b10101011, +0b10101011, +0b10010001, +0b01001010, +0b00111100, + +0b00000000, +0b00000010, +0b00000101, +0b01110101, +0b11100101, +0b11001010, +0b11100000, +0b01110000, + +0b00000000, +0b01110000, +0b10001000, +0b11011110, +0b10100101, +0b01111011, +0b00010001, +0b00001110, +}; diff --git a/cpu.c b/cpu.c new file mode 100644 index 0000000..7d0711f --- /dev/null +++ b/cpu.c @@ -0,0 +1,2003 @@ +/* + * TamaLIB - A hardware agnostic Tamagotchi P1 emulation library + * + * Copyright (C) 2021 Jean-Christophe Rona + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include +#include "cpu.h" +#include "hw.h" +#include "hal.h" +//#include "rom_new.h" +#include "rom_12bit.h" + +#define CPU_SPEED_RATIO 1 +#define TICK_FREQUENCY 32768 // Hz + +#define TIMER_1HZ_PERIOD 32768 // in ticks +#define TIMER_256HZ_PERIOD 128 // in ticks + +#define MASK_4B 0xF00 +#define MASK_6B 0xFC0 +#define MASK_7B 0xFE0 +#define MASK_8B 0xFF0 +#define MASK_10B 0xFFC +#define MASK_12B 0xFFF + +#define PCS (pc & 0xFF) +#define PCSL (pc & 0xF) +#define PCSH ((pc >> 4) & 0xF) +#define PCP ((pc >> 8) & 0xF) +#define PCB ((pc >> 12) & 0x1) +#define TO_PC(bank, page, step) ((step & 0xFF) | ((page & 0xF) << 8) | (bank & 0x1) << 12) +#define NBP ((np >> 4) & 0x1) +#define NPP (np & 0xF) +#define TO_NP(bank, page) ((page & 0xF) | (bank & 0x1) << 4) +#define XHL (x & 0xFF) +#define XL1 (x & 0xF) +#define XH1 ((x >> 4) & 0xF) +#define XP ((x >> 8) & 0xF) +#define YHL (y & 0xFF) +#define YL1 (y & 0xF) +#define YH1 ((y >> 4) & 0xF) +#define YP ((y >> 8) & 0xF) +#define M(n) get_memory(n) +#define SET_M(n, v) set_memory(n, v) +#define RQ(i) get_rq(i) +#define SET_RQ(i, v) set_rq(i, v) +#define SPL1 (sp & 0xF) +#define SPH1 ((sp >> 4) & 0xF) + +#define FLAG_C (0x1 << 0) +#define FLAG_Z (0x1 << 1) +#define FLAG_D (0x1 << 2) +#define FLAG_I (0x1 << 3) + +#define C !!(flags & FLAG_C) +#define Z !!(flags & FLAG_Z) +#define D !!(flags & FLAG_D) +#define I !!(flags & FLAG_I) + +#define SET_C() {flags |= FLAG_C;} +#define CLEAR_C() {flags &= ~FLAG_C;} +#define SET_Z() {flags |= FLAG_Z;} +#define CLEAR_Z() {flags &= ~FLAG_Z;} +#define SET_D() {flags |= FLAG_D;} +#define CLEAR_D() {flags &= ~FLAG_D;} +#define SET_I() {flags |= FLAG_I;} +#define CLEAR_I() {flags &= ~FLAG_I;} + +#define REG_CLK_INT_FACTOR_FLAGS 0xF00 +#define REG_SW_INT_FACTOR_FLAGS 0xF01 +#define REG_PROG_INT_FACTOR_FLAGS 0xF02 +#define REG_SERIAL_INT_FACTOR_FLAGS 0xF03 +#define REG_K00_K03_INT_FACTOR_FLAGS 0xF04 +#define REG_K10_K13_INT_FACTOR_FLAGS 0xF05 +#define REG_CLOCK_INT_MASKS 0xF10 +#define REG_SW_INT_MASKS 0xF11 +#define REG_PROG_INT_MASKS 0xF12 +#define REG_SERIAL_INT_MASKS 0xF13 +#define REG_K00_K03_INT_MASKS 0xF14 +#define REG_K10_K13_INT_MASKS 0xF15 +#define REG_PROG_TIMER_DATA_L 0xF24 +#define REG_PROG_TIMER_DATA_H 0xF25 +#define REG_PROG_TIMER_RELOAD_DATA_L 0xF26 +#define REG_PROG_TIMER_RELOAD_DATA_H 0xF27 +#define REG_K00_K03_INPUT_PORT 0xF40 +#define REG_K10_K13_INPUT_PORT 0xF42 +#define REG_K40_K43_BZ_OUTPUT_PORT 0xF54 +#define REG_CPU_OSC3_CTRL 0xF70 +#define REG_LCD_CTRL 0xF71 +#define REG_LCD_CONTRAST 0xF72 +#define REG_SVD_CTRL 0xF73 +#define REG_BUZZER_CTRL1 0xF74 +#define REG_BUZZER_CTRL2 0xF75 +#define REG_CLK_WD_TIMER_CTRL 0xF76 +#define REG_SW_TIMER_CTRL 0xF77 +#define REG_PROG_TIMER_CTRL 0xF78 +#define REG_PROG_TIMER_CLK_SEL 0xF79 + +#define INPUT_PORT_NUM 2 + +typedef struct { + //char *log; + u12_t code; + u12_t mask; +// u12_t shift_arg1; +// u12_t mask_arg1; // != 0 only if there are two arguments + u8_t cycles; + // void (*cb0)(u8_t arg0, u8_t arg1); +} op_t0; + +typedef struct { + //char *log; +// u12_t code; +// u12_t mask; +// u12_t shift_arg1; +// u12_t mask_arg1; // != 0 only if there are two arguments +// u8_t cycles; + void (*cb1)(u8_t arg0, u8_t arg1); +} op_t1; + +typedef struct { + u4_t states; +} input_port_t; + +/* Registers */ +static u13_t pc, next_pc; +static u12_t x, y; +static u4_t a, b; +static u5_t np; +static u8_t sp; + +/* Flags */ +static u4_t flags; + +//static const u12_t *g_program = NULL; +static u4_t memory[MEMORY_SIZE]; +//static u4_t io_memory[MEM_IO_SIZE]; + +static input_port_t inputs[INPUT_PORT_NUM] = {{0}}; + +//static u8_t maxNumber = 0; + +/* Interrupts (in priority order) */ +static interrupt_t interrupts[INT_SLOT_NUM] = { + {0x0, 0x0, 0, 0x0C}, // Prog timer + {0x0, 0x0, 0, 0x0A}, // Serial interface + {0x0, 0x0, 0, 0x08}, // Input (K10-K13) + {0x0, 0x0, 0, 0x06}, // Input (K00-K03) + {0x0, 0x0, 0, 0x04}, // Stopwatch timer + {0x0, 0x0, 0, 0x02}, // Clock timer +}; + +//static breakpoint_t *g_breakpoints = NULL; + +static u32_t call_depth = 0; + +static u32_t clk_timer_timestamp = 0; // in ticks +static u32_t prog_timer_timestamp = 0; // in ticks +static bool_t prog_timer_enabled = 0; +static u8_t prog_timer_data = 0; +static u8_t prog_timer_rld = 0; + +static u32_t tick_counter = 0; +static u32_t ts_freq; +//static u8_t speed_ratio = 0; +static timestamp_t ref_ts; + +/* +static state_t cpu_state = { + .pc = &pc, + .x = &x, + .y = &y, + .a = &a, + .b = &b, + .np = &np, + .sp = &sp, + .flags = &flags, + + .tick_counter = &tick_counter, + .clk_timer_timestamp = &clk_timer_timestamp, + .prog_timer_timestamp = &prog_timer_timestamp, + .prog_timer_enabled = &prog_timer_enabled, + .prog_timer_data = &prog_timer_data, + .prog_timer_rld = &prog_timer_rld, + + .call_depth = &call_depth, + + .interrupts = interrupts, + + .memory = memory, +}; */ + + +void cpu_add_bp(breakpoint_t **list, u13_t addr) +{ +/* breakpoint_t *bp; + + bp = (breakpoint_t *) g_hal->malloc(sizeof(breakpoint_t)); + if (!bp) { + g_hal->log(LOG_ERROR, "Cannot allocate memory for breakpoint 0x%04X!\n", addr); + return; + } + + bp->addr = addr; + + if (*list != NULL) { + bp->next = *list; + } else { + bp->next = NULL; + } + + *list = bp; */ +} + +void cpu_free_bp(breakpoint_t **list) +{ +/* breakpoint_t *bp = *list, *tmp; + while (bp != NULL) { + tmp = bp->next; + g_hal->free(bp); + bp = tmp; + } + *list = NULL; */ +} +/* +void cpu_set_speed(u8_t speed) +{ + speed_ratio = speed; +}*/ + + +void cpu_get_state(cpu_state_t *cpustate) +{ + cpustate->pc = pc; + cpustate->x = x; + cpustate->y = y; + cpustate->a = a; + cpustate->b = b; + cpustate->np = np; + cpustate->sp = sp; + + cpustate->flags = flags; + cpustate->tick_counter = tick_counter; + cpustate->clk_timer_timestamp = clk_timer_timestamp; + cpustate->prog_timer_timestamp = prog_timer_timestamp; + cpustate->prog_timer_enabled = prog_timer_enabled; + cpustate->prog_timer_data = prog_timer_data; + cpustate->prog_timer_rld = prog_timer_rld; + cpustate->call_depth = call_depth; + cpustate->memory = (u4_t *)memory; + uint8_t i; + for(i=0;i<6;i++) { + cpustate->interrupts[i].factor_flag_reg = interrupts[i].factor_flag_reg; + cpustate->interrupts[i].mask_reg = interrupts[i].mask_reg; + cpustate->interrupts[i].triggered = interrupts[i].triggered; + cpustate->interrupts[i].vector = interrupts[i].vector; + } +} + +void cpu_set_state(cpu_state_t *cpustate) +{ + pc = cpustate->pc; + x = cpustate->x; + y = cpustate->y; + a = cpustate->a; + b = cpustate->b; + np = cpustate->np; + sp = cpustate->sp; + flags = cpustate->flags; + tick_counter = cpustate->tick_counter; + clk_timer_timestamp = cpustate->clk_timer_timestamp; + prog_timer_timestamp = cpustate->prog_timer_timestamp; + prog_timer_enabled = cpustate->prog_timer_enabled; + prog_timer_data = cpustate->prog_timer_data; + prog_timer_rld = cpustate->prog_timer_rld; + call_depth = cpustate->call_depth; + //memory = (u4_t *)cpustate->memory; + uint8_t i; + for(i=0;i<6;i++) { + interrupts[i].factor_flag_reg = cpustate->interrupts[i].factor_flag_reg; + interrupts[i].mask_reg = cpustate->interrupts[i].mask_reg; + interrupts[i].triggered = cpustate->interrupts[i].triggered; + interrupts[i].vector = cpustate->interrupts[i].vector; + } +} + +u32_t cpu_get_depth(void) +{ + return call_depth; +} + +static void generate_interrupt(int_slot_t slot, u8_t bit) +{ + /* Set the factor flag no matter what */ + interrupts[slot].factor_flag_reg = interrupts[slot].factor_flag_reg | (0x1 << bit); + + /* Trigger the INT only if not masked */ + if (interrupts[slot].mask_reg & (0x1 << bit)) { + interrupts[slot].triggered = 1; + } +} + +void cpu_set_input_pin(pin_t pin, pin_state_t state) +{ + /* Set the I/O */ + inputs[pin & 0x4].states = (inputs[pin & 0x4].states & ~(0x1 << (pin & 0x3))) | (state << (pin & 0x3)); + + /* Trigger the interrupt (TODO: handle relation register) */ + if (state == PIN_STATE_LOW) { + switch ((pin & 0x4) >> 2) { + case 0: + generate_interrupt(INT_K00_K03_SLOT, pin & 0x3); + break; + + case 1: + generate_interrupt(INT_K10_K13_SLOT, pin & 0x3); + break; + } + } +} + +void cpu_sync_ref_timestamp(void) +{ + ref_ts = g_hal->get_timestamp(); +} + +static u4_t get_io(u12_t n) +{ + u4_t tmp; + + switch (n) { + case REG_CLK_INT_FACTOR_FLAGS: + /* Interrupt factor flags (clock timer) */ + tmp = interrupts[INT_CLOCK_TIMER_SLOT].factor_flag_reg; + interrupts[INT_CLOCK_TIMER_SLOT].factor_flag_reg = 0; + return tmp; + + case REG_SW_INT_FACTOR_FLAGS: + /* Interrupt factor flags (stopwatch) */ + tmp = interrupts[INT_STOPWATCH_SLOT].factor_flag_reg; + interrupts[INT_STOPWATCH_SLOT].factor_flag_reg = 0; + return tmp; + + case REG_PROG_INT_FACTOR_FLAGS: + /* Interrupt factor flags (prog timer) */ + tmp = interrupts[INT_PROG_TIMER_SLOT].factor_flag_reg; + interrupts[INT_PROG_TIMER_SLOT].factor_flag_reg = 0; + return tmp; + + case REG_SERIAL_INT_FACTOR_FLAGS: + /* Interrupt factor flags (serial) */ + tmp = interrupts[INT_SERIAL_SLOT].factor_flag_reg; + interrupts[INT_SERIAL_SLOT].factor_flag_reg = 0; + return tmp; + + case REG_K00_K03_INT_FACTOR_FLAGS: + /* Interrupt factor flags (K00-K03) */ + tmp = interrupts[INT_K00_K03_SLOT].factor_flag_reg; + interrupts[INT_K00_K03_SLOT].factor_flag_reg = 0; + return tmp; + + case REG_K10_K13_INT_FACTOR_FLAGS: + /* Interrupt factor flags (K10-K13) */ + tmp = interrupts[INT_K10_K13_SLOT].factor_flag_reg; + interrupts[INT_K10_K13_SLOT].factor_flag_reg = 0; + return tmp; + + case REG_CLOCK_INT_MASKS: + /* Clock timer interrupt masks */ + return interrupts[INT_CLOCK_TIMER_SLOT].mask_reg; + + case REG_SW_INT_MASKS: + /* Stopwatch interrupt masks */ + return interrupts[INT_STOPWATCH_SLOT].mask_reg & 0x3; + + case REG_PROG_INT_MASKS: + /* Prog timer interrupt masks */ + return interrupts[INT_PROG_TIMER_SLOT].mask_reg & 0x1; + + case REG_SERIAL_INT_MASKS: + /* Serial interface interrupt masks */ + return interrupts[INT_SERIAL_SLOT].mask_reg & 0x1; + + case REG_K00_K03_INT_MASKS: + /* Input (K00-K03) interrupt masks */ + return interrupts[INT_K00_K03_SLOT].mask_reg; + + case REG_K10_K13_INT_MASKS: + /* Input (K10-K13) interrupt masks */ + return interrupts[INT_K10_K13_SLOT].mask_reg; + + case REG_PROG_TIMER_DATA_L: + /* Prog timer data (low) */ + return prog_timer_data & 0xF; + + case REG_PROG_TIMER_DATA_H: + /* Prog timer data (high) */ + return (prog_timer_data >> 4) & 0xF; + + case REG_PROG_TIMER_RELOAD_DATA_L: + /* Prog timer reload data (low) */ + return prog_timer_rld & 0xF; + + case REG_PROG_TIMER_RELOAD_DATA_H: + /* Prog timer reload data (high) */ + return (prog_timer_rld >> 4) & 0xF; + + case REG_K00_K03_INPUT_PORT: + /* Input port (K00-K03) */ + return inputs[0].states; + + case REG_K10_K13_INPUT_PORT: + /* Input port (K10-K13) */ + return inputs[1].states; + + case REG_K40_K43_BZ_OUTPUT_PORT: + /* Output port (R40-R43) */ + //return io_memory[n - MEM_IO_ADDR_OFS]; + return 0xf; + case REG_CPU_OSC3_CTRL: + /* CPU/OSC3 clocks switch, CPU voltage switch */ + //return io_memory[n - MEM_IO_ADDR_OFS]; + return 0; + case REG_LCD_CTRL: + /* LCD control */ + //return io_memory[n - MEM_IO_ADDR_OFS]; + return 0x8; + case REG_LCD_CONTRAST: + /* LCD contrast */ + break; + + case REG_SVD_CTRL: + /* SVD */ + //return io_memory[n - MEM_IO_ADDR_OFS] & 0x7; // Voltage always OK + return 0; + case REG_BUZZER_CTRL1: + /* Buzzer config 1 */ + //return memory[n - MEM_IO_ADDR_OFS]; + return 0; + case REG_BUZZER_CTRL2: + /* Buzzer config 2 */ + //return io_memory[n - MEM_IO_ADDR_OFS] & 0x3; // Buzzer ready + return 0; + case REG_CLK_WD_TIMER_CTRL: + /* Clock/Watchdog timer reset */ + break; + + case REG_SW_TIMER_CTRL: + /* Stopwatch stop/run/reset */ + break; + + case REG_PROG_TIMER_CTRL: + /* Prog timer stop/run/reset */ + return !!prog_timer_enabled; + + case REG_PROG_TIMER_CLK_SEL: + /* Prog timer clock selection */ + break; + + default: + break; + //g_hal->log(LOG_ERROR, "Read from unimplemented I/O 0x%03X - PC = 0x%04X\n", n, pc); + } + + return 0; +} + +static void set_io(u12_t n, u4_t v) +{ + switch (n) { + case REG_CLOCK_INT_MASKS: + /* Clock timer interrupt masks */ + /* Assume 1Hz timer INT enabled (0x8) */ + interrupts[INT_CLOCK_TIMER_SLOT].mask_reg = v; + break; + + case REG_SW_INT_MASKS: + /* Stopwatch interrupt masks */ + /* Assume all INT disabled */ + interrupts[INT_STOPWATCH_SLOT].mask_reg = v; + break; + + case REG_PROG_INT_MASKS: + /* Prog timer interrupt masks */ + /* Assume Prog timer INT enabled (0x1) */ + interrupts[INT_PROG_TIMER_SLOT].mask_reg = v; + break; + + case REG_SERIAL_INT_MASKS: + /* Serial interface interrupt masks */ + /* Assume all INT disabled */ + interrupts[INT_K10_K13_SLOT].mask_reg = v; + break; + + case REG_K00_K03_INT_MASKS: + /* Input (K00-K03) interrupt masks */ + /* Assume all INT disabled */ + interrupts[INT_SERIAL_SLOT].mask_reg = v; + break; + + case REG_K10_K13_INT_MASKS: + /* Input (K10-K13) interrupt masks */ + /* Assume all INT disabled */ + interrupts[INT_K10_K13_SLOT].mask_reg = v; + break; + + case REG_PROG_TIMER_RELOAD_DATA_L: + /* Prog timer reload data (low) */ + prog_timer_rld = v | (prog_timer_rld & 0xF0); + break; + + case REG_PROG_TIMER_RELOAD_DATA_H: + /* Prog timer reload data (high) */ + prog_timer_rld = (prog_timer_rld & 0xF) | (v << 4); + break; + + case REG_K00_K03_INPUT_PORT: + /* Input port (K00-K03) */ + /* Write not allowed */ + break; + + case REG_K40_K43_BZ_OUTPUT_PORT: + /* Output port (R40-R43) */ + //g_hal->log(LOG_INFO, "Output/Buzzer: 0x%X\n", v); + hw_enable_buzzer(!(v & 0x8)); + break; + + case REG_CPU_OSC3_CTRL: + /* CPU/OSC3 clocks switch, CPU voltage switch */ + /* Assume 32,768 OSC1 selected, OSC3 off, battery >= 3,1V (0x1) */ + break; + + case REG_LCD_CTRL: + /* LCD control */ + break; + + case REG_LCD_CONTRAST: + /* LCD contrast */ + /* Assume medium contrast (0x8) */ + break; + + case REG_SVD_CTRL: + /* SVD */ + /* Assume battery voltage always OK (0x6) */ + break; + + case REG_BUZZER_CTRL1: + /* Buzzer config 1 */ + hw_set_buzzer_freq(v & 0x7); + break; + + case REG_BUZZER_CTRL2: + /* Buzzer config 2 */ + break; + + case REG_CLK_WD_TIMER_CTRL: + /* Clock/Watchdog timer reset */ + /* Ignore watchdog */ + break; + + case REG_SW_TIMER_CTRL: + /* Stopwatch stop/run/reset */ + break; + + case REG_PROG_TIMER_CTRL: + /* Prog timer stop/run/reset */ + if (v & 0x2) { + prog_timer_data = prog_timer_rld; + } + + if ((v & 0x1) && !prog_timer_enabled) { + prog_timer_timestamp = tick_counter; + } + + prog_timer_enabled = v & 0x1; + break; + + case REG_PROG_TIMER_CLK_SEL: + /* Prog timer clock selection */ + /* Assume 256Hz, output disabled */ + break; + + default: + break; + //g_hal->log(LOG_ERROR, "Write 0x%X to unimplemented I/O 0x%03X - PC = 0x%04X\n", v, n, pc); + } +} + +static void set_lcd(u12_t n, u4_t v) +{ + u8_t i; + u8_t seg, com0; + + seg = ((n & 0x7F) >> 1); + com0 = (((n & 0x80) >> 7) * 8 + (n & 0x1) * 4); + + for (i = 0; i < 4; i++) { + hw_set_lcd_pin(seg, com0 + i, (v >> i) & 0x1); + } +} + +/* +#define MEMORY_SIZE 1280 // 4096 x 4 bits (640 x 4 bits of RAM) + +#define MEM_RAM_ADDR 0x000 +#define MEM_RAM_SIZE 0x280 // 640 +#define MEM_DISPLAY1_ADDR 0xE00 // 3584 0x280 +#define MEM_DISPLAY1_ADDR_OFS 0xB80 +#define MEM_DISPLAY1_SIZE 0x050 // 80 +#define MEM_DISPLAY2_ADDR 0xE80 // 3712 0x2D0 +#define MEM_DISPLAY2_ADDR_OFS 0xBB0 +#define MEM_DISPLAY2_SIZE 0x050 // 80 +#define MEM_IO_ADDR 0xF00 // 3840 0x320 +#define MEM_IO_ADDR_OFS 0xBE0 +#define MEM_IO_SIZE 0x080 // 128 0x3a0 + +*/ +/* +u8_t cpu_get_max_number() { + return maxNumber; +} +*/ +static u4_t get_memory(u12_t n) +{ + u4_t res = 0; + + + if (n < MEM_RAM_SIZE) { + /* RAM */ + //g_hal->log(LOG_MEMORY, "RAM - "); + //if (n > max_memory_addr_access) max_memory_addr_access = n; + if ((n & 0x1)==0) { + res = memory[n>>1] >> 4; + } else { + res = memory[n>>1] & 0b00001111; + } + + } else if (n >= MEM_DISPLAY1_ADDR && n < (MEM_DISPLAY1_ADDR + MEM_DISPLAY1_SIZE)) { + /* Display Memory 1 */ + //g_hal->log(LOG_MEMORY, "Display Memory 1 - "); + //res = memory[n - MEM_DISPLAY1_ADDR_OFS]; + res = 0; + + } else if (n >= MEM_DISPLAY2_ADDR && n < (MEM_DISPLAY2_ADDR + MEM_DISPLAY2_SIZE)) { + /* Display Memory 2 */ + //g_hal->log(LOG_MEMORY, "Display Memory 2 - "); + //res = memory[n - MEM_DISPLAY2_ADDR_OFS]; + res = 0; + } else if (n >= MEM_IO_ADDR && n < (MEM_IO_ADDR + MEM_IO_SIZE)) { + /* I/O Memory */ + //g_hal->log(LOG_MEMORY, "I/O - "); + res = get_io(n); + } else { + //g_hal->log(LOG_ERROR, "Read from invalid memory address 0x%03X - PC = 0x%04X\n", n, pc); + return 0; + } + + //g_hal->log(LOG_MEMORY, "Read 0x%X - Address 0x%03X - PC = 0x%04X\n", res, n, pc); + + return res; +} + +static void set_memory(u12_t n, u4_t v) +{ + if (n < MEM_RAM_SIZE) { + /* RAM */ + //g_hal->log(LOG_MEMORY, "RAM - "); + if ((n & 0x1)==0) { + memory[n>>1] = (memory[n>>1] & 0x0F) | (v << 4); + } else { + memory[n>>1] = (memory[n>>1] & 0xF0) | v; + } + //memory[n] = v; + } else if (n >= MEM_DISPLAY1_ADDR && n < (MEM_DISPLAY1_ADDR + MEM_DISPLAY1_SIZE)) { + /* Display Memory 1 */ + set_lcd(n, v); + //memory[n - MEM_DISPLAY1_ADDR_OFS] = v; + //g_hal->log(LOG_MEMORY, "Display Memory 1 - "); + } else if (n >= MEM_DISPLAY2_ADDR && n < (MEM_DISPLAY2_ADDR + MEM_DISPLAY2_SIZE)) { + /* Display Memory 2 */ + set_lcd(n, v); + //memory[n - MEM_DISPLAY2_ADDR_OFS] = v; + //g_hal->log(LOG_MEMORY, "Display Memory 2 - "); + } else if (n >= MEM_IO_ADDR && n < (MEM_IO_ADDR + MEM_IO_SIZE)) { + /* I/O Memory */ + set_io(n, v); + //g_hal->log(LOG_MEMORY, "I/O - "); + } else { + //g_hal->log(LOG_ERROR, "Write 0x%X to invalid memory address 0x%03X - PC = 0x%04X\n", v, n, pc); + return; + } + //g_hal->log(LOG_MEMORY, "Write 0x%X - Address 0x%03X - PC = 0x%04X\n", v, n, pc); +} +/* +void cpu_refresh_hw(void) +{ + static const struct range { + u12_t addr; + u12_t size; + } refresh_locs[] = { + { MEM_DISPLAY1_ADDR, MEM_DISPLAY1_SIZE }, // Display Memory 1 + { MEM_DISPLAY2_ADDR, MEM_DISPLAY2_SIZE }, // Display Memory 2 + { REG_BUZZER_CTRL1, 1 }, // Buzzer frequency + { REG_K40_K43_BZ_OUTPUT_PORT, 1 }, // Buzzer enabled + + { 0, 0 }, // end of list + }; + + for (int i = 0; refresh_locs[i].size != 0; i++) { + for (u12_t n = refresh_locs[i].addr; n < (refresh_locs[i].addr + refresh_locs[i].size); n++) { + set_memory(n, memory[n]); + } + } +}*/ + +static u4_t get_rq(u12_t rq) +{ + switch (rq & 0x3) { + case 0x0: return a; + case 0x1: return b; + case 0x2: return M(x); + case 0x3: return M(y); + } + return 0; +} + +static void set_rq(u12_t rq, u4_t v) +{ + switch (rq & 0x3) { + case 0x0: a = v; break; + case 0x1: b = v; break; + case 0x2: SET_M(x, v); break; + case 0x3: SET_M(y, v); break; + } +} + +/* Instructions */ +static void op_pset_cb(u8_t arg0, u8_t arg1) +{ + np = arg0; +} + +static void op_jp_cb(u8_t arg0, u8_t arg1) +{ + next_pc = arg0 | (np << 8); +} + +static void op_jp_c_cb(u8_t arg0, u8_t arg1) +{ + if (flags & FLAG_C) { + next_pc = arg0 | (np << 8); + } +} + +static void op_jp_nc_cb(u8_t arg0, u8_t arg1) +{ + if (!(flags & FLAG_C)) { + next_pc = arg0 | (np << 8); + } +} + +static void op_jp_z_cb(u8_t arg0, u8_t arg1) +{ + if (flags & FLAG_Z) { + next_pc = arg0 | (np << 8); + } +} + +static void op_jp_nz_cb(u8_t arg0, u8_t arg1) +{ + if (!(flags & FLAG_Z)) { + next_pc = arg0 | (np << 8); + } +} + +static void op_jpba_cb(u8_t arg0, u8_t arg1) +{ + next_pc = a | (b << 4) | (np << 8); +} + +static void op_call_cb(u8_t arg0, u8_t arg1) +{ + pc = (pc + 1) & 0x1FFF; // This does not actually change the PC register + SET_M(sp - 1, PCP); + SET_M(sp - 2, PCSH); + SET_M(sp - 3, PCSL); + sp = (sp - 3) & 0xFF; + next_pc = TO_PC(PCB, NPP, arg0); + call_depth++; +} + +static void op_calz_cb(u8_t arg0, u8_t arg1) +{ + pc = (pc + 1) & 0x1FFF; // This does not actually change the PC register + SET_M(sp - 1, PCP); + SET_M(sp - 2, PCSH); + SET_M(sp - 3, PCSL); + sp = (sp - 3) & 0xFF; + next_pc = TO_PC(PCB, 0, arg0); + call_depth++; +} + +static void op_ret_cb(u8_t arg0, u8_t arg1) +{ + next_pc = M(sp) | (M(sp + 1) << 4) | (M(sp + 2) << 8) | (PCB << 12); + sp = (sp + 3) & 0xFF; + call_depth--; +} + +static void op_rets_cb(u8_t arg0, u8_t arg1) +{ + next_pc = M(sp) | (M(sp + 1) << 4) | (M(sp + 2) << 8) | (PCB << 12); + sp = (sp + 3) & 0xFF; + next_pc = (pc + 1) & 0x1FFF; + call_depth--; +} + +static void op_retd_cb(u8_t arg0, u8_t arg1) +{ + next_pc = M(sp) | (M(sp + 1) << 4) | (M(sp + 2) << 8) | (PCB << 12); + sp = (sp + 3) & 0xFF; + SET_M(x, arg0 & 0xF); + SET_M(x + 1, (arg0 >> 4) & 0xF); + x = ((x + 2) & 0xFF) | (XP << 8); + call_depth--; +} + +static void op_nop5_cb(u8_t arg0, u8_t arg1) +{ +} + +static void op_nop7_cb(u8_t arg0, u8_t arg1) +{ +} + +static void op_halt_cb(u8_t arg0, u8_t arg1) +{ + g_hal->halt(); +} + +static void op_inc_x_cb(u8_t arg0, u8_t arg1) +{ + x = ((x + 1) & 0xFF) | (XP << 8); +} + +static void op_inc_y_cb(u8_t arg0, u8_t arg1) +{ + y = ((y + 1) & 0xFF) | (YP << 8); +} + +static void op_ld_x_cb(u8_t arg0, u8_t arg1) +{ + x = arg0 | (XP << 8); +} + +static void op_ld_y_cb(u8_t arg0, u8_t arg1) +{ + y = arg0 | (YP << 8); +} + +static void op_ld_xp_r_cb(u8_t arg0, u8_t arg1) +{ + x = XHL | (RQ(arg0) << 8); +} + +static void op_ld_xh_r_cb(u8_t arg0, u8_t arg1) +{ + x = XL1 | (RQ(arg0) << 4) | (XP << 8); +} + +static void op_ld_xl_r_cb(u8_t arg0, u8_t arg1) +{ + x = RQ(arg0) | (XH1 << 4) | (XP << 8); +} + +static void op_ld_yp_r_cb(u8_t arg0, u8_t arg1) +{ + y = YHL | (RQ(arg0) << 8); +} + +static void op_ld_yh_r_cb(u8_t arg0, u8_t arg1) +{ + y = YL1 | (RQ(arg0) << 4) | (YP << 8); +} + +static void op_ld_yl_r_cb(u8_t arg0, u8_t arg1) +{ + y = RQ(arg0) | (YH1 << 4) | (YP << 8); +} + +static void op_ld_r_xp_cb(u8_t arg0, u8_t arg1) +{ + SET_RQ(arg0, XP); +} + +static void op_ld_r_xh_cb(u8_t arg0, u8_t arg1) +{ + SET_RQ(arg0, XH1); +} + +static void op_ld_r_xl_cb(u8_t arg0, u8_t arg1) +{ + SET_RQ(arg0, XL1); +} + +static void op_ld_r_yp_cb(u8_t arg0, u8_t arg1) +{ + SET_RQ(arg0, YP); +} + +static void op_ld_r_yh_cb(u8_t arg0, u8_t arg1) +{ + SET_RQ(arg0, YH1); +} + +static void op_ld_r_yl_cb(u8_t arg0, u8_t arg1) +{ + SET_RQ(arg0, YL1); +} + +static void op_adc_xh_cb(u8_t arg0, u8_t arg1) +{ + u8_t tmp; + + tmp = XH1 + arg0 + C; + x = XL1 | ((tmp & 0xF) << 4)| (XP << 8); + if (tmp >> 4) { SET_C(); } else { CLEAR_C(); } + if (!(tmp & 0xF)) { SET_Z(); } else { CLEAR_Z(); } +} + +static void op_adc_xl_cb(u8_t arg0, u8_t arg1) +{ + u8_t tmp; + + tmp = XL1 + arg0 + C; + x = (tmp & 0xF) | (XH1 << 4) | (XP << 8); + if (tmp >> 4) { SET_C(); } else { CLEAR_C(); } + if (!(tmp & 0xF)) { SET_Z(); } else { CLEAR_Z(); } +} + +static void op_adc_yh_cb(u8_t arg0, u8_t arg1) +{ + u8_t tmp; + + tmp = YH1 + arg0 + C; + y = YL1 | ((tmp & 0xF) << 4)| (YP << 8); + if (tmp >> 4) { SET_C(); } else { CLEAR_C(); } + if (!(tmp & 0xF)) { SET_Z(); } else { CLEAR_Z(); } +} + +static void op_adc_yl_cb(u8_t arg0, u8_t arg1) +{ + u8_t tmp; + + tmp = YL1 + arg0 + C; + y = (tmp & 0xF) | (YH1 << 4) | (YP << 8); + if (tmp >> 4) { SET_C(); } else { CLEAR_C(); } + if (!(tmp & 0xF)) { SET_Z(); } else { CLEAR_Z(); } +} + +static void op_cp_xh_cb(u8_t arg0, u8_t arg1) +{ + if (XH1 < arg0) { SET_C(); } else { CLEAR_C(); } + if (XH1 == arg0) { SET_Z(); } else { CLEAR_Z(); } +} + +static void op_cp_xl_cb(u8_t arg0, u8_t arg1) +{ + if (XL1 < arg0) { SET_C(); } else { CLEAR_C(); } + if (XL1 == arg0) { SET_Z(); } else { CLEAR_Z(); } +} + +static void op_cp_yh_cb(u8_t arg0, u8_t arg1) +{ + if (YH1 < arg0) { SET_C(); } else { CLEAR_C(); } + if (YH1 == arg0) { SET_Z(); } else { CLEAR_Z(); } +} + +static void op_cp_yl_cb(u8_t arg0, u8_t arg1) +{ + if (YL1 < arg0) { SET_C(); } else { CLEAR_C(); } + if (YL1 == arg0) { SET_Z(); } else { CLEAR_Z(); } +} + +static void op_ld_r_i_cb(u8_t arg0, u8_t arg1) +{ + SET_RQ(arg0, arg1); +} + +static void op_ld_r_q_cb(u8_t arg0, u8_t arg1) +{ + SET_RQ(arg0, RQ(arg1)); +} + +static void op_ld_a_mn_cb(u8_t arg0, u8_t arg1) +{ + a = M(arg0); +} + +static void op_ld_b_mn_cb(u8_t arg0, u8_t arg1) +{ + b = M(arg0); +} + +static void op_ld_mn_a_cb(u8_t arg0, u8_t arg1) +{ + SET_M(arg0, a); +} + +static void op_ld_mn_b_cb(u8_t arg0, u8_t arg1) +{ + SET_M(arg0, b); +} + +static void op_ldpx_mx_cb(u8_t arg0, u8_t arg1) +{ + SET_M(x, arg0); + x = ((x + 1) & 0xFF) | (XP << 8); +} + +static void op_ldpx_r_cb(u8_t arg0, u8_t arg1) +{ + SET_RQ(arg0, RQ(arg1)); + x = ((x + 1) & 0xFF) | (XP << 8); +} + +static void op_ldpy_my_cb(u8_t arg0, u8_t arg1) +{ + SET_M(y, arg0); + y = ((y + 1) & 0xFF) | (YP << 8); +} + +static void op_ldpy_r_cb(u8_t arg0, u8_t arg1) +{ + SET_RQ(arg0, RQ(arg1)); + y = ((y + 1) & 0xFF) | (YP << 8); +} + +static void op_lbpx_cb(u8_t arg0, u8_t arg1) +{ + SET_M(x, arg0 & 0xF); + SET_M(x + 1, (arg0 >> 4) & 0xF); + x = ((x + 2) & 0xFF) | (XP << 8); +} + +static void op_set_cb(u8_t arg0, u8_t arg1) +{ + flags |= arg0; +} + +static void op_rst_cb(u8_t arg0, u8_t arg1) +{ + flags &= arg0; +} + +static void op_scf_cb(u8_t arg0, u8_t arg1) +{ + SET_C(); +} + +static void op_rcf_cb(u8_t arg0, u8_t arg1) +{ + CLEAR_C(); +} + +static void op_szf_cb(u8_t arg0, u8_t arg1) +{ + SET_Z(); +} + +static void op_rzf_cb(u8_t arg0, u8_t arg1) +{ + CLEAR_Z(); +} + +static void op_sdf_cb(u8_t arg0, u8_t arg1) +{ + SET_D(); +} + +static void op_rdf_cb(u8_t arg0, u8_t arg1) +{ + CLEAR_D(); +} + +static void op_ei_cb(u8_t arg0, u8_t arg1) +{ + SET_I(); +} + +static void op_di_cb(u8_t arg0, u8_t arg1) +{ + CLEAR_I(); +} + +static void op_inc_sp_cb(u8_t arg0, u8_t arg1) +{ + sp = (sp + 1) & 0xFF; +} + +static void op_dec_sp_cb(u8_t arg0, u8_t arg1) +{ + sp = (sp - 1) & 0xFF; +} + +static void op_push_r_cb(u8_t arg0, u8_t arg1) +{ + sp = (sp - 1) & 0xFF; + SET_M(sp, RQ(arg0)); +} + +static void op_push_xp_cb(u8_t arg0, u8_t arg1) +{ + sp = (sp - 1) & 0xFF; + SET_M(sp, XP); +} + +static void op_push_xh_cb(u8_t arg0, u8_t arg1) +{ + sp = (sp - 1) & 0xFF; + SET_M(sp, XH1); +} + +static void op_push_xl_cb(u8_t arg0, u8_t arg1) +{ + sp = (sp - 1) & 0xFF; + SET_M(sp, XL1); +} + +static void op_push_yp_cb(u8_t arg0, u8_t arg1) +{ + sp = (sp - 1) & 0xFF; + SET_M(sp, YP); +} + +static void op_push_yh_cb(u8_t arg0, u8_t arg1) +{ + sp = (sp - 1) & 0xFF; + SET_M(sp, YH1); +} + +static void op_push_yl_cb(u8_t arg0, u8_t arg1) +{ + sp = (sp - 1) & 0xFF; + SET_M(sp, YL1); +} + +static void op_push_f_cb(u8_t arg0, u8_t arg1) +{ + sp = (sp - 1) & 0xFF; + SET_M(sp, flags); +} + +static void op_pop_r_cb(u8_t arg0, u8_t arg1) +{ + SET_RQ(arg0, M(sp)); + sp = (sp + 1) & 0xFF; +} + +static void op_pop_xp_cb(u8_t arg0, u8_t arg1) +{ + x = XL1 | (XH1 << 4)| (M(sp) << 8); + sp = (sp + 1) & 0xFF; +} + +static void op_pop_xh_cb(u8_t arg0, u8_t arg1) +{ + x = XL1 | (M(sp) << 4)| (XP << 8); + sp = (sp + 1) & 0xFF; +} + +static void op_pop_xl_cb(u8_t arg0, u8_t arg1) +{ + x = M(sp) | (XH1 << 4)| (XP << 8); + sp = (sp + 1) & 0xFF; +} + +static void op_pop_yp_cb(u8_t arg0, u8_t arg1) +{ + y = YL1 | (YH1 << 4)| (M(sp) << 8); + sp = (sp + 1) & 0xFF; +} + +static void op_pop_yh_cb(u8_t arg0, u8_t arg1) +{ + y = YL1 | (M(sp) << 4)| (YP << 8); + sp = (sp + 1) & 0xFF; +} + +static void op_pop_yl_cb(u8_t arg0, u8_t arg1) +{ + y = M(sp) | (YH1 << 4)| (YP << 8); + sp = (sp + 1) & 0xFF; +} + +static void op_pop_f_cb(u8_t arg0, u8_t arg1) +{ + flags = M(sp); + sp = (sp + 1) & 0xFF; +} + +static void op_ld_sph_r_cb(u8_t arg0, u8_t arg1) +{ + sp = SPL1 | (RQ(arg0) << 4); +} + +static void op_ld_spl_r_cb(u8_t arg0, u8_t arg1) +{ + sp = RQ(arg0) | (SPH1 << 4); +} + +static void op_ld_r_sph_cb(u8_t arg0, u8_t arg1) +{ + SET_RQ(arg0, SPH1); +} + +static void op_ld_r_spl_cb(u8_t arg0, u8_t arg1) +{ + SET_RQ(arg0, SPL1); +} + +static void op_add_r_i_cb(u8_t arg0, u8_t arg1) +{ + u8_t tmp; + + tmp = RQ(arg0) + arg1; + if (D) { + if (tmp >= 10) { + SET_RQ(arg0, (tmp - 10) & 0xF); + SET_C(); + } else { + SET_RQ(arg0, tmp); + CLEAR_C(); + } + } else { + SET_RQ(arg0, tmp & 0xF); + if (tmp >> 4) { SET_C(); } else { CLEAR_C(); } + } + if (!RQ(arg0)) { SET_Z(); } else { CLEAR_Z(); } +} + +static void op_add_r_q_cb(u8_t arg0, u8_t arg1) +{ + u8_t tmp; + + tmp = RQ(arg0) + RQ(arg1); + if (D) { + if (tmp >= 10) { + SET_RQ(arg0, (tmp - 10) & 0xF); + SET_C(); + } else { + SET_RQ(arg0, tmp); + CLEAR_C(); + } + } else { + SET_RQ(arg0, tmp & 0xF); + if (tmp >> 4) { SET_C(); } else { CLEAR_C(); } + } + if (!RQ(arg0)) { SET_Z(); } else { CLEAR_Z(); } +} + +static void op_adc_r_i_cb(u8_t arg0, u8_t arg1) +{ + u8_t tmp; + + tmp = RQ(arg0) + arg1 + C; + if (D) { + if (tmp >= 10) { + SET_RQ(arg0, (tmp - 10) & 0xF); + SET_C(); + } else { + SET_RQ(arg0, tmp); + CLEAR_C(); + } + } else { + SET_RQ(arg0, tmp & 0xF); + if (tmp >> 4) { SET_C(); } else { CLEAR_C(); } + } + if (!RQ(arg0)) { SET_Z(); } else { CLEAR_Z(); } +} + +static void op_adc_r_q_cb(u8_t arg0, u8_t arg1) +{ + u8_t tmp; + + tmp = RQ(arg0) + RQ(arg1) + C; + if (D) { + if (tmp >= 10) { + SET_RQ(arg0, (tmp - 10) & 0xF); + SET_C(); + } else { + SET_RQ(arg0, tmp); + CLEAR_C(); + } + } else { + SET_RQ(arg0, tmp & 0xF); + if (tmp >> 4) { SET_C(); } else { CLEAR_C(); } + } + if (!RQ(arg0)) { SET_Z(); } else { CLEAR_Z(); } +} + +static void op_sub_cb(u8_t arg0, u8_t arg1) +{ + u8_t tmp; + + tmp = RQ(arg0) - RQ(arg1); + if (D) { + if (tmp >> 4) { + SET_RQ(arg0, (tmp - 6) & 0xF); + } else { + SET_RQ(arg0, tmp); + } + } else { + SET_RQ(arg0, tmp & 0xF); + } + if (tmp >> 4) { SET_C(); } else { CLEAR_C(); } + if (!RQ(arg0)) { SET_Z(); } else { CLEAR_Z(); } +} + +static void op_sbc_r_i_cb(u8_t arg0, u8_t arg1) +{ + u8_t tmp; + + tmp = RQ(arg0) - arg1 - C; + if (D) { + if (tmp >> 4) { + SET_RQ(arg0, (tmp - 6) & 0xF); + } else { + SET_RQ(arg0, tmp); + } + } else { + SET_RQ(arg0, tmp & 0xF); + } + if (tmp >> 4) { SET_C(); } else { CLEAR_C(); } + if (!RQ(arg0)) { SET_Z(); } else { CLEAR_Z(); } +} + +static void op_sbc_r_q_cb(u8_t arg0, u8_t arg1) +{ + u8_t tmp; + + tmp = RQ(arg0) - RQ(arg1) - C; + if (D) { + if (tmp >> 4) { + SET_RQ(arg0, (tmp - 6) & 0xF); + } else { + SET_RQ(arg0, tmp); + } + } else { + SET_RQ(arg0, tmp & 0xF); + } + if (tmp >> 4) { SET_C(); } else { CLEAR_C(); } + if (!RQ(arg0)) { SET_Z(); } else { CLEAR_Z(); } +} + +static void op_and_r_i_cb(u8_t arg0, u8_t arg1) +{ + SET_RQ(arg0, RQ(arg0) & arg1); + if (!RQ(arg0)) { SET_Z(); } else { CLEAR_Z(); } +} + +static void op_and_r_q_cb(u8_t arg0, u8_t arg1) +{ + SET_RQ(arg0, RQ(arg0) & RQ(arg1)); + if (!RQ(arg0)) { SET_Z(); } else { CLEAR_Z(); } +} + +static void op_or_r_i_cb(u8_t arg0, u8_t arg1) +{ + SET_RQ(arg0, RQ(arg0) | arg1); + if (!RQ(arg0)) { SET_Z(); } else { CLEAR_Z(); } +} + +static void op_or_r_q_cb(u8_t arg0, u8_t arg1) +{ + SET_RQ(arg0, RQ(arg0) | RQ(arg1)); + if (!RQ(arg0)) { SET_Z(); } else { CLEAR_Z(); } +} + +static void op_xor_r_i_cb(u8_t arg0, u8_t arg1) +{ + SET_RQ(arg0, RQ(arg0) ^ arg1); + if (!RQ(arg0)) { SET_Z(); } else { CLEAR_Z(); } +} + +static void op_xor_r_q_cb(u8_t arg0, u8_t arg1) +{ + SET_RQ(arg0, RQ(arg0) ^ RQ(arg1)); + if (!RQ(arg0)) { SET_Z(); } else { CLEAR_Z(); } +} + +static void op_cp_r_i_cb(u8_t arg0, u8_t arg1) +{ + if (RQ(arg0) < arg1) { SET_C(); } else { CLEAR_C(); } + if (RQ(arg0) == arg1) { SET_Z(); } else { CLEAR_Z(); } +} + +static void op_cp_r_q_cb(u8_t arg0, u8_t arg1) +{ + if (RQ(arg0) < RQ(arg1)) { SET_C(); } else { CLEAR_C(); } + if (RQ(arg0) == RQ(arg1)) { SET_Z(); } else { CLEAR_Z(); } +} + +static void op_fan_r_i_cb(u8_t arg0, u8_t arg1) +{ + if (!(RQ(arg0) & arg1)) { SET_Z(); } else { CLEAR_Z(); } +} + +static void op_fan_r_q_cb(u8_t arg0, u8_t arg1) +{ + if (!(RQ(arg0) & RQ(arg1))) { SET_Z(); } else { CLEAR_Z(); } +} + +static void op_rlc_cb(u8_t arg0, u8_t arg1) +{ + u8_t tmp; + + tmp = (RQ(arg0) << 1) | C; + if (RQ(arg0) & 0x8) { SET_C(); } else { CLEAR_C(); } + SET_RQ(arg0, tmp & 0xF); + /* No need to set Z (issue in DS) */ +} + +static void op_rrc_cb(u8_t arg0, u8_t arg1) +{ + u8_t tmp; + + tmp = (RQ(arg0) >> 1) | (C << 3); + if (RQ(arg0) & 0x1) { SET_C(); } else { CLEAR_C(); } + SET_RQ(arg0, tmp & 0xF); + /* No need to set Z (issue in DS) */ +} + +static void op_inc_mn_cb(u8_t arg0, u8_t arg1) +{ + u8_t tmp; + + tmp = M(arg0) + 1; + SET_M(arg0, tmp & 0xF); + if (tmp >> 4) { SET_C(); } else { CLEAR_C(); } + if (!M(arg0)) { SET_Z(); } else { CLEAR_Z(); } +} + +static void op_dec_mn_cb(u8_t arg0, u8_t arg1) +{ + u8_t tmp; + + tmp = M(arg0) - 1; + SET_M(arg0, tmp & 0xF); + if (tmp >> 4) { SET_C(); } else { CLEAR_C(); } + if (!M(arg0)) { SET_Z(); } else { CLEAR_Z(); } +} + +static void op_acpx_cb(u8_t arg0, u8_t arg1) +{ + u8_t tmp; + + tmp = M(x) + RQ(arg0) + C; + if (D) { + if (tmp >= 10) { + SET_M(x, (tmp - 10) & 0xF); + SET_C(); + } else { + SET_M(x, tmp); + CLEAR_C(); + } + } else { + SET_M(x, tmp & 0xF); + if (tmp >> 4) { SET_C(); } else { CLEAR_C(); } + } + if (!M(x)) { SET_Z(); } else { CLEAR_Z(); } + x = ((x + 1) & 0xFF) | (XP << 8); +} + +static void op_acpy_cb(u8_t arg0, u8_t arg1) +{ + u8_t tmp; + + tmp = M(y) + RQ(arg0) + C; + if (D) { + if (tmp >= 10) { + SET_M(y, (tmp - 10) & 0xF); + SET_C(); + } else { + SET_M(y, tmp); + CLEAR_C(); + } + } else { + SET_M(y, tmp & 0xF); + if (tmp >> 4) { SET_C(); } else { CLEAR_C(); } + } + if (!M(y)) { SET_Z(); } else { CLEAR_Z(); } + y = ((y + 1) & 0xFF) | (YP << 8); +} + +static void op_scpx_cb(u8_t arg0, u8_t arg1) +{ + u8_t tmp; + + tmp = M(x) - RQ(arg0) - C; + if (D) { + if (tmp >> 4) { + SET_M(x, (tmp - 6) & 0xF); + } else { + SET_M(x, tmp); + } + } else { + SET_M(x, tmp & 0xF); + } + if (tmp >> 4) { SET_C(); } else { CLEAR_C(); } + if (!M(x)) { SET_Z(); } else { CLEAR_Z(); } + x = ((x + 1) & 0xFF) | (XP << 8); +} + +static void op_scpy_cb(u8_t arg0, u8_t arg1) +{ + u8_t tmp; + + tmp = M(y) - RQ(arg0) - C; + if (D) { + if (tmp >> 4) { + SET_M(y, (tmp - 6) & 0xF); + } else { + SET_M(y, tmp); + } + } else { + SET_M(y, tmp & 0xF); + } + if (tmp >> 4) { SET_C(); } else { CLEAR_C(); } + if (!M(y)) { SET_Z(); } else { CLEAR_Z(); } + y = ((y + 1) & 0xFF) | (YP << 8); +} + +static void op_not_cb(u8_t arg0, u8_t arg1) +{ + SET_RQ(arg0, ~RQ(arg0) & 0xF); + if (!RQ(arg0)) { SET_Z(); } else { CLEAR_Z(); } +} + +/* The E0C6S46 supported instructions */ +static const op_t0 ops0[] PROGMEM = { + {0xE40, MASK_7B , 5 }, // PSET + {0x000, MASK_4B , 5 }, // JP + {0x200, MASK_4B , 5 }, // JP_C + {0x300, MASK_4B , 5 }, // JP_NC + {0x600, MASK_4B , 5 }, // JP_Z + {0x700, MASK_4B , 5 }, // JP_NZ + {0xFE8, MASK_12B , 5 }, // JPBA + {0x400, MASK_4B , 7 }, // CALL + {0x500, MASK_4B , 7 }, // CALZ + {0xFDF, MASK_12B , 7 }, // RET + {0xFDE, MASK_12B , 12}, // RETS + {0x100, MASK_4B , 12}, // RETD + {0xFFB, MASK_12B , 5 }, // NOP5 + {0xFFF, MASK_12B , 7 }, // NOP7 + {0xFF8, MASK_12B , 5 }, // HALT + {0xEE0, MASK_12B , 5 }, // INC_X + {0xEF0, MASK_12B , 5 }, // INC_Y + {0xB00, MASK_4B , 5 }, // LD_X + {0x800, MASK_4B , 5 }, // LD_Y + {0xE80, MASK_10B , 5 }, // LD_XP_R + {0xE84, MASK_10B , 5 }, // LD_XH_R + {0xE88, MASK_10B , 5 }, // LD_XL_R + {0xE90, MASK_10B , 5 }, // LD_YP_R + {0xE94, MASK_10B , 5 }, // LD_YH_R + {0xE98, MASK_10B , 5 }, // LD_YL_R + {0xEA0, MASK_10B , 5 }, // LD_R_XP + {0xEA4, MASK_10B , 5 }, // LD_R_XH + {0xEA8, MASK_10B , 5 }, // LD_R_XL + {0xEB0, MASK_10B , 5 }, // LD_R_YP + {0xEB4, MASK_10B , 5 }, // LD_R_YH + {0xEB8, MASK_10B , 5 }, // LD_R_YL + {0xA00, MASK_8B , 7 }, // ADC_XH + {0xA10, MASK_8B , 7 }, // ADC_XL + {0xA20, MASK_8B , 7 }, // ADC_YH + {0xA30, MASK_8B , 7 }, // ADC_YL + {0xA40, MASK_8B , 7 }, // CP_XH + {0xA50, MASK_8B , 7 }, // CP_XL + {0xA60, MASK_8B , 7 }, // CP_YH + {0xA70, MASK_8B , 7 }, // CP_YL + {0xFA0, MASK_8B , 5 }, // LD_A_MN + {0xFB0, MASK_8B , 5 }, // LD_B_MN + {0xF80, MASK_8B , 5 }, // LD_MN_A + {0xF90, MASK_8B , 5 }, // LD_MN_B + {0xE60, MASK_8B , 5 }, // LDPX_MX + {0xE70, MASK_8B , 5 }, // LDPY_MY + {0x900, MASK_4B , 5 }, // LBPX + {0xF40, MASK_8B , 7 }, // SET + {0xF50, MASK_8B , 7 }, // RST + {0xF41, MASK_12B , 7 }, // SCF + {0xF5E, MASK_12B , 7 }, // RCF + {0xF42, MASK_12B , 7 }, // SZF + {0xF5D, MASK_12B , 7 }, // RZF + {0xF44, MASK_12B , 7 }, // SDF + {0xF5B, MASK_12B , 7 }, // RDF + {0xF48, MASK_12B , 7 }, // EI + {0xF57, MASK_12B , 7 }, // DI + {0xFDB, MASK_12B , 5 }, // INC_SP + {0xFCB, MASK_12B , 5 }, // DEC_SP + {0xFC0, MASK_10B , 5 }, // PUSH_R + {0xFC4, MASK_12B , 5 }, // PUSH_XP + {0xFC5, MASK_12B , 5 }, // PUSH_XH + {0xFC6, MASK_12B , 5 }, // PUSH_XL + {0xFC7, MASK_12B , 5 }, // PUSH_YP + {0xFC8, MASK_12B , 5 }, // PUSH_YH + {0xFC9, MASK_12B , 5 }, // PUSH_YL + {0xFCA, MASK_12B , 5 }, // PUSH_F + {0xFD0, MASK_10B , 5 }, // POP_R + {0xFD4, MASK_12B , 5 }, // POP_XP + {0xFD5, MASK_12B , 5 }, // POP_XH + {0xFD6, MASK_12B , 5 }, // POP_XL + {0xFD7, MASK_12B , 5 }, // POP_YP + {0xFD8, MASK_12B , 5 }, // POP_YH + {0xFD9, MASK_12B , 5 }, // POP_YL + {0xFDA, MASK_12B , 5 }, // POP_F + {0xFE0, MASK_10B , 5 }, // LD_SPH_R + {0xFF0, MASK_10B , 5 }, // LD_SPL_R + {0xFE4, MASK_10B , 5 }, // LD_R_SPH + {0xFF4, MASK_10B , 5 }, // LD_R_SPL + {0xC00, MASK_6B , 7 }, // ADD_R_I + {0xC40, MASK_6B , 7 }, // ADC_R_I + {0xB40, MASK_6B , 7 }, // SBC_R_I + {0xC80, MASK_6B , 7 }, // AND_R_I + {0xCC0, MASK_6B , 7 }, // OR_R_I + {0xD00, MASK_6B , 7 }, // XOR_R_I + {0xDC0, MASK_6B , 7 }, // CP_R_I + {0xD80, MASK_6B , 7 }, // FAN_R_I + {0xE00, MASK_6B , 5 }, // LD_R_I + {0xA80, MASK_8B , 7 }, // ADD_R_Q + {0xA90, MASK_8B , 7 }, // ADC_R_Q + {0xAA0, MASK_8B , 7 }, // SUB + {0xAB0, MASK_8B , 7 }, // SBC_R_Q + {0xAC0, MASK_8B , 7 }, // AND_R_Q + {0xAD0, MASK_8B , 7 }, // OR_R_Q + {0xAE0, MASK_8B , 7 }, // XOR_R_Q + {0xEC0, MASK_8B , 5 }, // LD_R_Q + {0xEE0, MASK_8B , 5 }, // LDPX_R + {0xEF0, MASK_8B , 5 }, // LDPY_R + {0xF00, MASK_8B , 7 }, // CP_R_Q + {0xF10, MASK_8B , 7 }, // FAN_R_Q + + {0xAF0, MASK_8B , 7 }, // RLC + {0xE8C, MASK_10B , 5 }, // RRC + {0xF60, MASK_8B , 7 }, // INC_MN + {0xF70, MASK_8B , 7 }, // DEC_MN + {0xF28, MASK_10B , 7 }, // ACPX + {0xF2C, MASK_10B , 7 }, // ACPY + {0xF38, MASK_10B , 7 }, // SCPX + {0xF3C, MASK_10B , 7 }, // SCPY + {0xD0F, 0xFCF , 7 }, // NOT + {NULL, 0, 0, 0, NULL}, +}; + +/* The E0C6S46 supported instructions */ +static const op_t1 ops1[] PROGMEM = { + {&op_pset_cb}, // PSET + {&op_jp_cb}, // JP + {&op_jp_c_cb}, // JP_C + {&op_jp_nc_cb}, // JP_NC + {&op_jp_z_cb}, // JP_Z + {&op_jp_nz_cb}, // JP_NZ + {&op_jpba_cb}, // JPBA + {&op_call_cb}, // CALL + {&op_calz_cb}, // CALZ + {&op_ret_cb}, // RET + {&op_rets_cb}, // RETS + {&op_retd_cb}, // RETD + {&op_nop5_cb}, // NOP5 + {&op_nop7_cb}, // NOP7 + {&op_halt_cb}, // HALT + {&op_inc_x_cb}, // INC_X + {&op_inc_y_cb}, // INC_Y + {&op_ld_x_cb}, // LD_X + {&op_ld_y_cb}, // LD_Y + {&op_ld_xp_r_cb}, // LD_XP_R + {&op_ld_xh_r_cb}, // LD_XH_R + {&op_ld_xl_r_cb}, // LD_XL_R + {&op_ld_yp_r_cb}, // LD_YP_R + {&op_ld_yh_r_cb}, // LD_YH_R + {&op_ld_yl_r_cb}, // LD_YL_R + {&op_ld_r_xp_cb}, // LD_R_XP + {&op_ld_r_xh_cb}, // LD_R_XH + {&op_ld_r_xl_cb}, // LD_R_XL + {&op_ld_r_yp_cb}, // LD_R_YP + {&op_ld_r_yh_cb}, // LD_R_YH + {&op_ld_r_yl_cb}, // LD_R_YL + {&op_adc_xh_cb}, // ADC_XH + {&op_adc_xl_cb}, // ADC_XL + {&op_adc_yh_cb}, // ADC_YH + {&op_adc_yl_cb}, // ADC_YL + {&op_cp_xh_cb}, // CP_XH + {&op_cp_xl_cb}, // CP_XL + {&op_cp_yh_cb}, // CP_YH + {&op_cp_yl_cb}, // CP_YL + {&op_ld_a_mn_cb}, // LD_A_MN + {&op_ld_b_mn_cb}, // LD_B_MN + {&op_ld_mn_a_cb}, // LD_MN_A + {&op_ld_mn_b_cb}, // LD_MN_B + {&op_ldpx_mx_cb}, // LDPX_MX + {&op_ldpy_my_cb}, // LDPY_MY + {&op_lbpx_cb}, // LBPX + {&op_set_cb}, // SET + {&op_rst_cb}, // RST + {&op_scf_cb}, // SCF + {&op_rcf_cb}, // RCF + {&op_szf_cb}, // SZF + {&op_rzf_cb}, // RZF + {&op_sdf_cb}, // SDF + {&op_rdf_cb}, // RDF + {&op_ei_cb}, // EI + {&op_di_cb}, // DI + {&op_inc_sp_cb}, // INC_SP + {&op_dec_sp_cb}, // DEC_SP + {&op_push_r_cb}, // PUSH_R + {&op_push_xp_cb}, // PUSH_XP + {&op_push_xh_cb}, // PUSH_XH + {&op_push_xl_cb}, // PUSH_XL + {&op_push_yp_cb}, // PUSH_YP + {&op_push_yh_cb}, // PUSH_YH + {&op_push_yl_cb}, // PUSH_YL + {&op_push_f_cb}, // PUSH_F + {&op_pop_r_cb}, // POP_R + {&op_pop_xp_cb}, // POP_XP + {&op_pop_xh_cb}, // POP_XH + {&op_pop_xl_cb}, // POP_XL + {&op_pop_yp_cb}, // POP_YP + {&op_pop_yh_cb}, // POP_YH + {&op_pop_yl_cb}, // POP_YL + {&op_pop_f_cb}, // POP_F + {&op_ld_sph_r_cb}, // LD_SPH_R + {&op_ld_spl_r_cb}, // LD_SPL_R + {&op_ld_r_sph_cb}, // LD_R_SPH + {&op_ld_r_spl_cb}, // LD_R_SPL + {&op_add_r_i_cb}, // ADD_R_I + {&op_adc_r_i_cb}, // ADC_R_I + {&op_sbc_r_i_cb}, // SBC_R_I + {&op_and_r_i_cb}, // AND_R_I + {&op_or_r_i_cb}, // OR_R_I + {&op_xor_r_i_cb}, // XOR_R_I + {&op_cp_r_i_cb}, // CP_R_I + {&op_fan_r_i_cb}, // FAN_R_I + {&op_ld_r_i_cb}, // LD_R_I + {&op_add_r_q_cb}, // ADD_R_Q + {&op_adc_r_q_cb}, // ADC_R_Q + {&op_sub_cb}, // SUB + {&op_sbc_r_q_cb}, // SBC_R_Q + {&op_and_r_q_cb}, // AND_R_Q + {&op_or_r_q_cb}, // OR_R_Q + {&op_xor_r_q_cb}, // XOR_R_Q + {&op_ld_r_q_cb}, // LD_R_Q + {&op_ldpx_r_cb}, // LDPX_R + {&op_ldpy_r_cb}, // LDPY_R + {&op_cp_r_q_cb}, // CP_R_Q + {&op_fan_r_q_cb}, // FAN_R_Q + + {&op_rlc_cb}, // RLC + {&op_rrc_cb}, // RRC + {&op_inc_mn_cb}, // INC_MN + {&op_dec_mn_cb}, // DEC_MN + {&op_acpx_cb}, // ACPX + {&op_acpy_cb}, // ACPY + {&op_scpx_cb}, // SCPX + {&op_scpy_cb}, // SCPY + {&op_not_cb}, // NOT + {NULL} +}; + +u12_t getShiftArg0(u12_t code, u12_t mask) { + if (mask==MASK_6B || mask==0xFCF) return 4; + if (code==0xA80 || code==0xA90 || code==0xAA0 || code==0xAB0 || code==0xAC0 || code==0xAD0 || code==0xAE0 || code==0xEC0 || code==0xEE0 || code==0xEF0 || code==0xF00 || code==0xF10) return 2; + return 0; +} + +u12_t getMaskArg0(u12_t shiftArg, u12_t mask) { + if (mask==MASK_6B) return 0x030; + if (mask==MASK_8B && shiftArg==2) return 0x00C; + return 0; +} + +static timestamp_t wait_for_cycles(timestamp_t since, u8_t cycles) { + timestamp_t deadline; + + tick_counter += cycles; + + if (CPU_SPEED_RATIO == 0) { + /* Emulation will be as fast as possible */ + return g_hal->get_timestamp(); + } + + deadline = since + (cycles * ts_freq)/(TICK_FREQUENCY * CPU_SPEED_RATIO); + g_hal->sleep_until(deadline); + + return deadline; +} + +static void process_interrupts(void) +{ + u8_t i; + + /* Process interrupts in priority order */ + for (i = 0; i < INT_SLOT_NUM; i++) { + if (interrupts[i].triggered) { + //printf("IT %u !\n", i); + SET_M(sp - 1, PCP); + SET_M(sp - 2, PCSH); + SET_M(sp - 3, PCSL); + sp = (sp - 3) & 0xFF; + CLEAR_I(); + np = TO_NP(NBP, 1); + pc = TO_PC(PCB, 1, interrupts[i].vector); + call_depth++; + + ref_ts = wait_for_cycles(ref_ts, 12); + interrupts[i].triggered = 0; + } + } +} + +static void print_state(u8_t op_num, u12_t op, u13_t addr) +{ +} + +//static char logMsg[40]; + +void cpu_reset(void) +{ + u13_t i; + + /* Registers and variables init */ + pc = TO_PC(0, 1, 0x00); // PC starts at bank 0, page 1, step 0 + np = TO_NP(0, 1); // NP starts at page 1 + a = 0; // undef + b = 0; // undef + x = 0; // undef + y = 0; // undef + sp = 0; // undef + flags = 0; + + //sprintf(logMsg, "Start pc 1:0x%04X, %d", pc, pc); g_hal->log(LOG_ERROR, logMsg); + + /* Init RAM to zeros */ + for (i = 0; i < MEMORY_SIZE; i++) { + memory[i] = 0; + } + /*for (i = 0; i < MEM_IO_SIZE; i++) { + io_memory[i] = 0; + } */ + + //io_memory[REG_K40_K43_BZ_OUTPUT_PORT - MEM_IO_ADDR_OFS] = 0xF; // Output port (R40-R43) + //io_memory[REG_LCD_CTRL - MEM_IO_ADDR_OFS] = 0x8; // LCD control + /* TODO: Input relation register */ + + cpu_sync_ref_timestamp(); +} + +bool_t cpu_init(u32_t freq) +{ + //g_program = program; + //g_breakpoints = breakpoints; + ts_freq = freq; + cpu_reset(); + return 0; +} + +void cpu_release(void) +{ +} + +u12_t getProgramOpCode(u12_t pc) { + u12_t i = pc >> 1; // divided by 2 + if ((pc & 0x1)==0) { // if pc is a even number + return (pgm_read_byte_near(g_program_b12+i+i+i) << 4) | ((pgm_read_byte_near(g_program_b12+i+i+i+1) >> 4) & 0xF); + } + return (pgm_read_byte_near(g_program_b12+i+i+i+1) << 8) | pgm_read_byte_near(g_program_b12+i+i+i+2); +} + +/* +typedef struct { + u12_t code; + u12_t mask; + u8_t cycles; +} op_t0; +*/ + +int cpu_step(void) +{ + u12_t op; + u8_t i; + //breakpoint_t *bp = g_breakpoints; + static u8_t previous_cycles = 0; + + op = getProgramOpCode(pc); + + //op_t0 *ops = (op_t0 *)pgm_read_ptr_near(ops0); + + /* Lookup the OP code */ + for (i = 0; pgm_read_byte_near(&ops0[i].cycles) != 0; i++) { + if ((op & pgm_read_word_near(&ops0[i].mask)) == pgm_read_word_near(&ops0[i].code)) { + break; + } + } + + //sprintf(logMsg, "op-code 0x%X (pc = 0x%04X)", op, pc); g_hal->log(LOG_ERROR, logMsg); + + if (pgm_read_byte_near(&ops0[i].cycles) == 0) { + //printf(logMsg, "Unknown op-code 0x%X (pc = 0x%04X)\n", op, pc); g_hal->log(LOG_ERROR, logMsg); + return 1; + } + + op_t0 ops; + ops.code=pgm_read_word_near(&ops0[i].code); + ops.mask=pgm_read_word_near(&ops0[i].mask); + ops.cycles=pgm_read_byte_near(&ops0[i].cycles); + + next_pc = (pc + 1) & 0x1FFF; + + /* Display the operation along with the current state of the processor */ + print_state(i, op, pc); + + /* Match the speed of the real processor + * NOTE: For better accuracy, the final wait should happen here, however + * the downside is that all interrupts will likely be delayed by one OP + */ + ref_ts = wait_for_cycles(ref_ts, previous_cycles); + + op_t1 ops11; + ops11.cb1 = pgm_read_ptr_near(&ops1[i].cb1); + + /* Process the OP code */ + if (ops11.cb1 != NULL) { + u12_t shiftArg0 = getShiftArg0(ops.code,ops.mask); + u12_t maskArg0 = getMaskArg0(shiftArg0,ops.mask); + if (maskArg0 != 0) { + /* Two arguments */ + //ops[i].cb((op & ops[i].mask_arg0) >> ops[i].shift_arg0, op & ~(ops[i].mask | ops[i].mask_arg0)); + ops11.cb1((op & maskArg0) >> shiftArg0, op & ~(ops.mask | maskArg0)); + } else { + /* One arguments */ + //ops[i].cb((op & ~ops[i].mask) >> ops[i].shift_arg0, 0); + ops11.cb1((op & ~ops.mask) >> shiftArg0, 0); + } + } + + /* Prepare for the next instruction */ + pc = next_pc; + previous_cycles = ops.cycles; + + if (i > 0) { + /* OP code is not PSET, reset NP */ + np = (pc >> 8) & 0x1F; + } + + /* Handle timers using the internal tick counter */ + if (tick_counter - clk_timer_timestamp >= TIMER_1HZ_PERIOD) { + do { + clk_timer_timestamp += TIMER_1HZ_PERIOD; + } while (tick_counter - clk_timer_timestamp >= TIMER_1HZ_PERIOD); + + generate_interrupt(INT_CLOCK_TIMER_SLOT, 3); + } + + if (prog_timer_enabled && tick_counter - prog_timer_timestamp >= TIMER_256HZ_PERIOD) { + do { + prog_timer_timestamp += TIMER_256HZ_PERIOD; + prog_timer_data--; + + if (prog_timer_data == 0) { + prog_timer_data = prog_timer_rld; + generate_interrupt(INT_PROG_TIMER_SLOT, 0); + } + } while (tick_counter - prog_timer_timestamp >= TIMER_256HZ_PERIOD); + } + + /* Check if there is any pending interrupt */ + if (I && i > 0) { // Do not process interrupts after a PSET operation + process_interrupts(); + } + + /* Check if we could pause the execution */ + /*while (bp != NULL) { + if (bp->addr == pc) { + return 1; + } + + bp = bp->next; + } */ + + return 0; +} diff --git a/cpu.h b/cpu.h new file mode 100644 index 0000000..edc5961 --- /dev/null +++ b/cpu.h @@ -0,0 +1,164 @@ +/* + * TamaLIB - A hardware agnostic Tamagotchi P1 emulation library + * + * Copyright (C) 2021 Jean-Christophe Rona + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#ifndef _CPU_H_ +#define _CPU_H_ + +#include "hal.h" + +#define MEMORY_SIZE 0x140 // MEM_RAM_SIZE + MEM_IO_SIZE + +#define MEM_RAM_ADDR 0x000 +#define MEM_RAM_SIZE 0x280 + +#define MEM_DISPLAY1_ADDR 0xE00 +#define MEM_DISPLAY1_ADDR_OFS 0xB80 +#define MEM_DISPLAY1_SIZE 0x050 + +#define MEM_DISPLAY2_ADDR 0xE80 +#define MEM_DISPLAY2_ADDR_OFS 0xBB0 +#define MEM_DISPLAY2_SIZE 0x050 + +#define MEM_IO_ADDR 0xF00 +//#define MEM_IO_ADDR_OFS 0xBE0 +#define MEM_IO_ADDR_OFS 0xF00 +#define MEM_IO_SIZE 0x080 + +typedef struct breakpoint { + u13_t addr; + struct breakpoint *next; +} breakpoint_t; + + +typedef struct { + u4_t factor_flag_reg; + u4_t mask_reg; + bool_t triggered; /* 1 if triggered, 0 otherwise */ + u8_t vector; +} interrupt_t; + +typedef struct { + u13_t pc; + u12_t x; + u12_t y; + u4_t a; + u4_t b; + u5_t np; + u8_t sp; + u4_t flags; + u32_t tick_counter; + u32_t clk_timer_timestamp; + u32_t prog_timer_timestamp; + bool_t prog_timer_enabled; + u8_t prog_timer_data; + u8_t prog_timer_rld; + u32_t call_depth; + u4_t *memory; + interrupt_t interrupts[6]; + } cpu_state_t; + +/* Pins (TODO: add other pins) */ +typedef enum { + PIN_K00 = 0x0, + PIN_K01 = 0x1, + PIN_K02 = 0x2, + PIN_K03 = 0x3, + PIN_K10 = 0X4, + PIN_K11 = 0X5, + PIN_K12 = 0X6, + PIN_K13 = 0X7, +} pin_t; + +typedef enum { + PIN_STATE_LOW = 0, + PIN_STATE_HIGH = 1, +} pin_state_t; + +typedef enum { + INT_PROG_TIMER_SLOT = 0, + INT_SERIAL_SLOT = 1, + INT_K10_K13_SLOT = 2, + INT_K00_K03_SLOT = 3, + INT_STOPWATCH_SLOT = 4, + INT_CLOCK_TIMER_SLOT = 5, + INT_SLOT_NUM, +} int_slot_t; + + +/* +typedef struct { + u13_t *pc; + u12_t *x; + u12_t *y; + u4_t *a; + u4_t *b; + u5_t *np; + u8_t *sp; + u4_t *flags; + + u32_t *tick_counter; + u32_t *clk_timer_timestamp; + u32_t *prog_timer_timestamp; + bool_t *prog_timer_enabled; + u8_t *prog_timer_data; + u8_t *prog_timer_rld; + + u32_t *call_depth; + + interrupt_t *interrupts; + + u4_t *memory; +} state_t; */ + +#ifdef __cplusplus + extern "C" { +#endif + +void cpu_add_bp(breakpoint_t **list, u13_t addr); +void cpu_free_bp(breakpoint_t **list); + +//void cpu_set_speed(u8_t speed); + +void cpu_get_state(cpu_state_t *cpustate); +void cpu_set_state(cpu_state_t *cpustate); + +u32_t cpu_get_depth(void); + +void cpu_set_input_pin(pin_t pin, pin_state_t state); + +void cpu_sync_ref_timestamp(void); + +void cpu_refresh_hw(void); + +void cpu_reset(void); + +//u8_t cpu_get_max_number(void); + +//bool_t cpu_init(breakpoint_t *breakpoints, u32_t freq); + +bool_t cpu_init(u32_t freq); +void cpu_release(void); + +int cpu_step(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _CPU_H_ */ diff --git a/hal.h b/hal.h new file mode 100644 index 0000000..4b6d315 --- /dev/null +++ b/hal.h @@ -0,0 +1,89 @@ +/* + * TamaLIB - A hardware agnostic Tamagotchi P1 emulation library + * + * Copyright (C) 2021 Jean-Christophe Rona + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#ifndef _HAL_H_ +#define _HAL_H_ + +#include "hal_types.h" + +#ifndef NULL + #define NULL 0 +#endif + +typedef enum { + LOG_ERROR = 0x1, + LOG_INFO = (0x1 << 1), + LOG_MEMORY = (0x1 << 2), + LOG_CPU = (0x1 << 3), +} log_level_t; + +/* The Hardware Abstraction Layer + * NOTE: This structure acts as an abstraction layer between TamaLIB and the OS/SDK. + * All pointers MUST be implemented, but some implementations can be left empty. + */ +typedef struct { + /* Memory allocation functions + * NOTE: Needed only if breakpoints support is required. + */ + //void * (*malloc)(u32_t size); + //void (*free)(void *ptr); + + /* What to do if the CPU has halted + */ + void (*halt)(void); + + /* Log related function + * NOTE: Needed only if log messages are required. + */ + //bool_t (*is_log_enabled)(log_level_t level); + void (*log)(log_level_t level, char *buff, ...); + + /* Clock related functions + * NOTE: Timestamps granularity is configured with tamalib_init(), an accuracy + * of ~30 us (1/32768) is required for a cycle accurate emulation. + */ + void (*sleep_until)(timestamp_t ts); + timestamp_t (*get_timestamp)(void); + + /* Screen related functions + * NOTE: In case of direct hardware access to pixels, the set_XXXX() functions + * (called for each pixel/icon update) can directly drive them, otherwise they + * should just store the data in a buffer and let update_screen() do the actual + * rendering (at 30 fps). + */ + void (*update_screen)(void); + void (*set_lcd_matrix)(u8_t x, u8_t y, bool_t val); + void (*set_lcd_icon)(u8_t icon, bool_t val); + + /* Sound related functions + * NOTE: set_frequency() changes the output frequency of the sound, while + * play_frequency() decides whether the sound should be heard or not. + */ + void (*set_frequency)(u32_t freq); + void (*play_frequency)(bool_t en); + + /* Event handler from the main app (if any) + * NOTE: This function usually handles button related events, states loading/saving ... + */ + int (*handler)(void); +} hal_t; + +extern hal_t *g_hal; + +#endif /* _HAL_H_ */ diff --git a/hal_types.h b/hal_types.h new file mode 100644 index 0000000..5bceef2 --- /dev/null +++ b/hal_types.h @@ -0,0 +1,34 @@ +/* + * TamaTool - A cross-platform Tamagotchi P1 explorer + * + * Copyright (C) 2021 Jean-Christophe Rona + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#ifndef _HAL_TYPES_H_ +#define _HAL_TYPES_H_ + +#include + +typedef uint8_t bool_t; +typedef uint8_t u4_t; +typedef uint8_t u5_t; +typedef uint8_t u8_t; +typedef uint16_t u12_t; +typedef uint16_t u13_t; +typedef uint32_t u32_t; +typedef uint32_t timestamp_t; // WARNING: Must be an unsigned type to properly handle wrapping (u32 wraps in around 1h11m when expressed in us) + +#endif /* _HAL_TYPES_H_ */ diff --git a/hardcoded_state.h b/hardcoded_state.h new file mode 100644 index 0000000..28c3217 --- /dev/null +++ b/hardcoded_state.h @@ -0,0 +1,25 @@ +static const uint8_t hardcodedState[] PROGMEM = { +0x7E,0x01,0x40,0x0F,0x2D,0x00,0x01,0x08,0x01,0xED,0x01,0x00,0x31,0x9F,0xAB,0xAD, +0x00,0x80,0xAB,0xAD,0xDC,0x9E,0xAB,0xAD,0x01,0x06,0x07,0x00,0x04,0x00,0x00,0x00, +0x1A,0xE6,0xFE,0x3F,0x00,0x01,0x00,0x0C,0x00,0x00,0x00,0x0A,0x00,0x00,0x00,0x08, +0x07,0x00,0x00,0x06,0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x02,0x17,0x40,0xF0,0x75, +0x70,0x00,0x00,0x00,0x42,0x31,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x82,0x00, +0x00,0x00,0x00,0x17,0x5B,0x48,0x80,0xD7,0xCD,0xC8,0xF0,0xF0,0xFF,0x08,0x00,0x03, +0x70,0x0F,0x00,0x00,0xF1,0x00,0x70,0x09,0x0F,0x70,0x06,0x10,0x00,0x10,0xBC,0x20, +0xDF,0x0E,0xC0,0x12,0xC0,0x00,0xF0,0x8A,0x00,0x0F,0xFF,0x70,0x30,0x05,0x80,0x00, +0x00,0x00,0x00,0x00,0x13,0x23,0x33,0xFF,0xC1,0xC1,0xC1,0xC1,0x01,0x36,0x03,0x92, +0x32,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0xB1,0x77,0x17,0x71,0x77,0x17,0x71,0xD7, +0x0B,0x77,0x13,0x00,0x17,0x23,0x49,0x2E,0x44,0x50,0x24,0x50,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x8F,0x40,0xA2,0x24,0x64,0x64,0x64,0x24,0xA2,0x40,0x8F, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0xD2,0xFF,0x99, +0x00,0x00,0x08,0xDA,0x01,0xC7,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x90,0x61,0x15,0xB5,0x8F,0xA8,0x03,0x99,0x03,0xC7,0x88,0x11, +0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,}; diff --git a/hw.c b/hw.c new file mode 100644 index 0000000..437e249 --- /dev/null +++ b/hw.c @@ -0,0 +1,142 @@ +/* + * TamaLIB - A hardware agnostic Tamagotchi P1 emulation library + * + * Copyright (C) 2021 Jean-Christophe Rona + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +//#include +#include "hw.h" +#include "cpu.h" +#include "hal.h" + +/* SEG -> LCD mapping */ +const static u8_t seg_pos[40] = {0, 1, 2, 3, 4, 5, 6, 7, 32, 8, 9, 10, 11, 12 ,13 ,14, 15, 33, 34, 35, 31, 30, 29, 28, 27, 26, 25, 24, 36, 23, 22, 21, 20, 19, 18, 17, 16, 37, 38, 39}; + + +bool_t hw_init(void) +{ + /* Buttons are active LOW */ + cpu_set_input_pin(PIN_K00, PIN_STATE_HIGH); + cpu_set_input_pin(PIN_K01, PIN_STATE_HIGH); + cpu_set_input_pin(PIN_K02, PIN_STATE_HIGH); + return 0; +} + +void hw_release(void) +{ +} + +void hw_set_lcd_pin(u8_t seg, u8_t com, u8_t val) +{ + if (seg_pos[seg] < LCD_WIDTH) { + g_hal->set_lcd_matrix(seg_pos[seg], com, val); + } else { + /* + * IC n -> seg-com|... + * IC 0 -> 8-0 |18-3 |19-2 + * IC 1 -> 8-1 |17-0 |19-3 + * IC 2 -> 8-2 |17-1 |37-12|38-13|39-14 + * IC 3 -> 8-3 |17-2 |18-1 |19-0 + * IC 4 -> 28-12|37-13|38-14|39-15 + * IC 5 -> 28-13|37-14|38-15 + * IC 6 -> 28-14|37-15|39-12 + * IC 7 -> 28-15|38-12|39-13 + */ + if (seg == 8 && com < 4) { + g_hal->set_lcd_icon(com, val); + } else if (seg == 28 && com >= 12) { + g_hal->set_lcd_icon(com - 8, val); + } + } +} + +void hw_set_button(button_t btn, btn_state_t state) +{ + pin_state_t pin_state = (state == BTN_STATE_PRESSED) ? PIN_STATE_LOW : PIN_STATE_HIGH; + + switch (btn) { + case BTN_LEFT: + cpu_set_input_pin(PIN_K02, pin_state); + break; + + case BTN_MIDDLE: + cpu_set_input_pin(PIN_K01, pin_state); + break; + + case BTN_RIGHT: + cpu_set_input_pin(PIN_K00, pin_state); + break; + } +} + +const static uint16_t snd_freq[]= {4096,3279,2731,2341,2048,1638,1365,1170}; +void hw_set_buzzer_freq(u4_t freq) +{ + if (freq>7) return; + g_hal->set_frequency(snd_freq[freq]); + /*u32_t snd_freq = 0; + + switch (freq) { + case 0: + // 4096.0 Hz + snd_freq = 4096; + break; + + case 1: + // 3276.8 Hz + snd_freq = 3279; + break; + + case 2: + // 2730.7 Hz + snd_freq = 2731; + break; + + case 3: + // 2340.6 Hz + snd_freq = 2341; + break; + + case 4: + // 2048.0 Hz + snd_freq = 2048; + break; + + case 5: + // 1638.4 Hz + snd_freq = 1638; + break; + + case 6: + // 1365.3 Hz + snd_freq = 1365; + break; + + case 7: + // 1170.3 Hz + snd_freq = 1170; + break; + } + + if (snd_freq != 0) { + g_hal->set_frequency(snd_freq); + }*/ +} + +void hw_enable_buzzer(bool_t en) +{ + g_hal->play_frequency(en); +} diff --git a/hw.h b/hw.h new file mode 100644 index 0000000..2fb7454 --- /dev/null +++ b/hw.h @@ -0,0 +1,59 @@ +/* + * TamaLIB - A hardware agnostic Tamagotchi P1 emulation library + * + * Copyright (C) 2021 Jean-Christophe Rona + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#ifndef _HW_H_ +#define _HW_H_ + +#include "hal.h" + +#define LCD_WIDTH 32 +#define LCD_HEIGHT 16 + +#define ICON_NUM 8 + +typedef enum { + BTN_STATE_RELEASED = 0, + BTN_STATE_PRESSED, +} btn_state_t; + +typedef enum { + BTN_LEFT = 0, + BTN_MIDDLE, + BTN_RIGHT, +} button_t; + + +#ifdef __cplusplus + extern "C" { +#endif + +bool_t hw_init(void); +void hw_release(void); + +void hw_set_lcd_pin(u8_t seg, u8_t com, u8_t val); +void hw_set_button(button_t btn, btn_state_t state); + +void hw_set_buzzer_freq(u4_t freq); +void hw_enable_buzzer(bool_t en); + +#ifdef __cplusplus +} +#endif + +#endif /* _HW_H_ */ diff --git a/rom_12bit.h b/rom_12bit.h new file mode 100644 index 0000000..bbcf545 --- /dev/null +++ b/rom_12bit.h @@ -0,0 +1,514 @@ +static const unsigned char g_program_b12[] PROGMEM = { + 0xFA,0x2C,0x87, 0xE1,0x0A,0x80, 0xA8,0x0A,0x95, 0x51,0x2E,0x50, 0x02,0x0F,0xC4, 0xFC,0x5F,0xC6, + 0xFC,0x05,0xEF, 0xB7,0xDE,0x2F, 0xF4,0x80,0x1A, 0xFC,0x4F,0xC5, 0xFC,0x6F,0xC0, 0x5E,0xFB,0x7D, + 0xE2,0x0F,0x57, 0xFD,0x0F,0xD6, 0xFD,0x5F,0xD4, 0xFD,0xFB,0x02, 0x53,0xCE,0x00, 0xE8,0x0B,0x26, + 0x51,0x2E,0xE2, 0xEC,0x6E,0x60, 0x50,0x9E,0xE8, 0xEC,0x9F,0xDF, 0xE0,0x0E,0x90, 0x82,0x25,0x12, + 0xEA,0xBE,0xF0, 0xEA,0x75,0x09, 0xFD,0xFE,0x00, 0xE9,0x08,0x23, 0xEC,0x38,0x22, 0xAD,0x3F,0xDF, + 0x42,0xC4,0x35, 0x73,0xDF,0xDF, 0x5E,0xFB,0x2A, 0x90,0x0E,0x01, 0xE1,0x0E,0x80, 0xB0,0x09,0x00, + 0x90,0x09,0x00, 0x90,0x09,0x00, 0x90,0x09,0x00, 0x90,0x0C,0x1F, 0x74,0x7F,0xDF, 0xE4,0x44,0x86, + 0xE4,0x44,0x00, 0x5E,0xFB,0x2A, 0xE9,0xAE,0xE0, 0xE9,0x6E,0x01, 0xE9,0x0E,0x0E, 0xE8,0x0B,0x00, + 0x48,0xDF,0x5E, 0xA2,0x7B,0x80, 0x48,0xDF,0x5E, 0xA2,0x8B,0x12, 0x48,0xDF,0x5E, 0xA2,0x7B,0x92, + 0x48,0xDF,0x5E, 0xA2,0x8B,0x48, 0xF4,0x14,0x9F, 0xB3,0xEF,0x41, 0x4A,0x7F,0x5E, 0xA2,0x7B,0xC8, + 0xF4,0x14,0x9F, 0xBB,0xEF,0x41, 0x4A,0x7F,0x5E, 0xA2,0x8B,0x36, 0xF4,0x14,0xA3, 0xB2,0xEF,0x41, + 0x4A,0x3F,0x5E, 0xA2,0x7B,0xB6, 0xF4,0x14,0xA3, 0xBA,0xEF,0x41, 0x0A,0x34,0x8F, 0xEE,0x0E,0xFB, + 0xEE,0x0E,0xFB, 0xEE,0x0E,0xFB, 0xEE,0x0E,0xFB, 0xEE,0x0E,0xFB, 0xEE,0x0E,0xFB, 0xEE,0x0E,0xFB, + 0xEE,0x0E,0xFB, 0xFD,0xFE,0xFB, 0xEE,0x0E,0xFB, 0xA1,0xCE,0xFB, 0xEE,0x0E,0xFB, 0xA1,0xCE,0xFB, + 0xEE,0x0E,0xFB, 0xA1,0xCE,0xFB, 0xEE,0x0E,0xFB, 0xA1,0xCE,0xFB, 0xEE,0x0E,0xFB, 0xFD,0xF5,0xEF, + 0xB4,0xAD,0xA8, 0xFD,0xF5,0xF2, 0x0B,0xF5,0xEF, 0x0B,0xF8,0x94, 0xE1,0xFE,0x00, 0xE8,0x0B,0x7B, + 0xDE,0x06,0xCD, 0xB3,0x25,0x12, 0x90,0x0B,0x36, 0xEB,0xAE,0xE0, 0xEB,0x6B,0x58, 0xEE,0x8E,0xC9, + 0x50,0x9F,0xDF, 0xE0,0x0E,0x80, 0xB2,0xA9,0x40, 0xB3,0xAF,0xDF, 0x51,0x2E,0xF3, 0x0D,0xB5,0x12, + 0xEF,0x3A,0xD3, 0xEF,0x0A,0xD3, 0x50,0x9F,0xDF, 0x5C,0xE9,0x40, 0xE4,0x70,0x92, 0xB1,0x2F,0x44, + 0xC2,0x1E,0xE0, 0xC6,0x0D,0xE6, 0x2E,0xAE,0x20, 0xF5,0xBF,0xDF, 0xE0,0x0E,0x47, 0x0C,0x0E,0x00, + 0xE8,0x0F,0xDF, 0xE1,0x0E,0x81, 0xFD,0xFE,0x01, 0xE8,0x0F,0xDF, 0xB5,0xDD,0xE1, 0xFD,0xFE,0x00, + 0xE8,0x0B,0x48, 0xDA,0x8F,0xDF, 0x01,0x00,0x16, 0x01,0xD0,0x16, 0x01,0x60,0x16, 0x01,0x60,0x16, + 0x01,0x60,0x16, 0x01,0x60,0x16, 0x06,0xF0,0x16, 0x01,0x60,0x16, 0xF5,0x0E,0x0F, 0xFE,0x0F,0xF0, + 0xE4,0x20,0x2A, 0xFC,0xAF,0xC0, 0xFC,0x1F,0xC4, 0xFC,0x5F,0xC6, 0x05,0xBF,0xCA, 0xFC,0x0F,0xC1, + 0xFC,0x4F,0xC5, 0xFC,0x6F,0x5B, 0xE0,0xFE,0x80, 0xB0,0x0E,0xC2, 0xB7,0x69,0x01, 0x92,0x1B,0x12, + 0xE2,0x1E,0x00, 0xE8,0x0B,0x57, 0xDE,0x06,0x33, 0xC2,0xFB,0x3C, 0xDE,0x06,0x4A, 0xF4,0x4B,0x2E, + 0xE2,0x1B,0x10, 0xC2,0x1E,0xE0, 0xC6,0x0D,0xE6, 0x24,0x9E,0x60, 0x5E,0x42,0x47, 0xB1,0x4E,0xE2, + 0xEE,0x6B,0x14, 0x4F,0x4E,0x4C, 0x47,0xAF,0x5B, 0xE0,0x0E,0x80, 0xB2,0xFC,0x21, 0xEE,0x0F,0x28, + 0xC6,0x03,0x5B, 0xE0,0xFE,0x80, 0xB7,0x0D,0xA3, 0x65,0xB4,0xE5, 0x65,0xBB,0x70, 0xE2,0x0E,0x00, + 0xE8,0x0B,0x7D, 0xDE,0x06,0x68, 0xFD,0x6F,0xD5, 0xFD,0x4F,0xD1, 0xFD,0x0F,0xDA, 0xF4,0x8F,0xDF, + 0xFD,0x6F,0xD5, 0xFD,0x4F,0xD1, 0xFD,0x0F,0xDA, 0xFD,0xFF,0xCA, 0xFC,0x0F,0xC1, 0xFC,0x4F,0xC5, + 0xFC,0x6F,0x5B, 0x4A,0x0E,0x0F, 0xE8,0x0B,0x02, 0xEC,0x2B,0x40, 0xEC,0x6D,0x1F, 0xC9,0x7E,0x00, + 0xE8,0x0B,0x5A, 0xC2,0x1B,0x22, 0xC2,0xFE,0xE0, 0xC6,0xF2,0x8A, 0xB2,0x29,0x00, 0xB2,0x6E,0xC2, + 0xEE,0x9A,0xE1, 0xAC,0x1A,0xD8, 0xB3,0xDF,0x09, 0x69,0x7E,0xC9, 0xB3,0xEE,0x20, 0x09,0xFB,0x3E, + 0xC2,0x17,0x9F, 0xE2,0x8B,0x3F, 0xAC,0x6B,0x27, 0xAD,0x90,0x5B, 0xE0,0x0E,0x80, 0xB3,0x2C,0x2F, + 0xEE,0x0C,0x6F, 0x3A,0xBB,0x34, 0xDA,0x87,0xD7, 0xFD,0xFB,0x36, 0xEC,0x2C,0x22, 0xEE,0x0E,0xC6, + 0xC6,0x0B,0x32, 0xE4,0xE4,0x7C, 0xA5,0x66,0xC1, 0xB5,0x9D,0xEF, 0x6C,0x1B,0x58, 0xC2,0xFE,0xE0, + 0xC6,0xF2,0xC1, 0xB3,0x69,0x7D, 0x0A,0xBB,0x34, 0xDA,0x87,0xD7, 0xB3,0x89,0x58, 0xE0,0xFE,0x80, + 0xB7,0x1C,0xE1, 0xFC,0x4E,0x00, 0xE8,0x0B,0x34, 0xEE,0x2E,0xC6, 0xFD,0x4B,0x74, 0xEE,0x8E,0xC9, + 0xB5,0x4C,0xA7, 0xFD,0xFB,0x38, 0xC2,0xFE,0xE0, 0xC6,0xFE,0x0F, 0xE8,0x02,0xE0, 0xB7,0x1C,0xAE, + 0xB5,0x4C,0xE8, 0xFD,0xFE,0x0F, 0xE8,0x0B,0x73, 0xE2,0x6F,0xFB, 0xEC,0x2E,0x20, 0xC8,0x8F,0xDF, + 0xB7,0x5E,0x60, 0xEE,0x8E,0xE9, 0xB5,0x7E,0xE9, 0x52,0x1F,0xDF, 0xC0,0x1C,0x50, 0xDD,0x12,0xFD, + 0x7F,0xBD,0xC8, 0x2F,0xDE,0x00, 0xE1,0x0E,0xE8, 0xEE,0x9F,0xDF, 0x55,0x65,0x21, 0xDC,0x56,0x06, + 0xD9,0x1F,0xDF, 0x51,0x25,0xEF, 0xE0,0x2E,0x90, 0xB1,0x08,0x72, 0x42,0x7F,0x50, 0xE0,0xFF,0xE0, + 0xFF,0x04,0x42, 0xE0,0x0E,0x90, 0xE0,0x2E,0x80, 0x81,0x0B,0x72, 0x42,0x75,0x09, 0x88,0x05,0xBC, + 0xE4,0x74,0x61, 0xE4,0x44,0x65, 0xB3,0xCE,0x2F, 0x52,0x1D,0x87, 0x72,0x2E,0x45, 0x01,0x7E,0x52, + 0x02,0x2F,0xDF, 0xE4,0x14,0xE3, 0x72,0xFB,0x70, 0xE2,0x1E,0x0F, 0xE8,0x0B,0x40, 0xE0,0x2E,0x90, + 0x87,0x0E,0xCE, 0xCB,0x74,0x42, 0x50,0x98,0x80, 0x5B,0xCE,0x02, 0xE8,0x0B,0x70, 0xDE,0x36,0x56, + 0xE4,0x90,0x7F, 0xE5,0x10,0xE0, 0xE0,0x0E,0x1E, 0x54,0x5E,0x01, 0xE1,0x05,0x45, 0xE0,0x2E,0x17, + 0x54,0x5E,0x0E, 0xE1,0x55,0x45, 0xE1,0x5B,0x80, 0x54,0x7E,0x52, 0x00,0x0F,0xDF, 0xB2,0xC9,0xFF, + 0x8F,0xFE,0x12, 0x46,0xBB,0x2C, 0x95,0xA8,0xA5, 0xE1,0x14,0x6B, 0xB2,0xC9,0xA5, 0x85,0xAE,0x14, + 0x46,0xBB,0x2C, 0x90,0x0E,0x12, 0x48,0x1E,0x49, 0x07,0xFF,0x90, 0x5F,0x5B,0x00, 0xEB,0x4E,0xB9, + 0xEE,0x8E,0xE8, 0xEE,0x9E,0xE9, 0xA4,0x07,0x70, 0xA5,0x07,0x70, 0xE4,0x74,0xE1, 0x55,0x65,0x21, + 0xFB,0x0F,0x01, 0x77,0xB5,0xBB, 0xFD,0xFF,0x90, 0x5F,0x5B,0x00, 0x90,0x1A,0x48, 0x78,0x49,0x80, + 0xA4,0x07,0x87, 0xB0,0x09,0xFF, 0xB3,0xE9,0xFF, 0xB8,0x09,0xFF, 0xBB,0xE9,0xFF, 0x07,0x8E,0x00, + 0x5E,0xD5,0x40, 0x52,0x15,0xCE, 0x9C,0x4E,0x45, 0x4A,0x6E,0x15, 0xF9,0x5F,0xA4, 0xDC,0x62,0xA1, + 0xC0,0x3F,0x84, 0x5F,0x5B,0xE2, 0xF7,0x4F,0xA4, 0xAF,0x0E,0x05, 0xAF,0x0E,0x45, 0x4E,0xFF,0x75, + 0x7A,0x45,0x56, 0xE4,0xF4,0x00, 0x7C,0x05,0x1F, 0xD9,0x2E,0x45, 0x70,0x8D,0xC5, 0xE4,0x56,0x53, + 0xB7,0xCD,0xE0, 0xE4,0x56,0x08, 0xB2,0xED,0xE0, 0x6B,0x10,0x97, 0xE4,0x34,0x07, 0x09,0x35,0x21, + 0xAD,0x1D,0x87, 0x6C,0xDB,0x77, 0xEC,0x2D,0xC0, 0x6C,0xDB,0x57, 0xEC,0x8B,0x29, 0xDA,0x46,0xD9, + 0x5B,0xBB,0x76, 0xEC,0x2B,0x75, 0xC2,0x1F,0x08, 0x2E,0xEE,0x20, 0x0E,0xED,0xA2, 0x6D,0xF5,0xBB, + 0xF5,0xEF,0x42, 0x0F,0x0D,0xA1, 0x6E,0x55,0xBB, 0xF4,0x1F,0x42, 0x0F,0x0B,0x57, 0xDE,0x07,0xEE, + 0xB7,0x7D,0xE0, 0x6E,0xEF,0x41, 0xF5,0xD0,0xF0, 0xF5,0xEF,0x5D, 0xB7,0x5E,0xC2, 0xFD,0xFF,0xFF, + 0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF, + 0xFD,0xF0,0x0C, 0x01,0xC0,0x24, 0x02,0x90,0x4B, 0x07,0x45,0xF2, 0xB5,0xCE,0xC2, 0xE2,0x0F,0xE8, + 0xB4,0xAE,0x2F, 0xB5,0xDE,0xC6, 0xE0,0x2E,0x80, 0xB0,0x4D,0xD1, 0x61,0x79,0x00, 0x01,0x89,0x3D, + 0xE0,0x88,0xA5, 0x5B,0x7F,0xDF, 0xB5,0xDE,0x02, 0xE9,0x08,0x08, 0xDE,0x17,0x27, 0xE3,0xD0,0x18, + 0xE0,0x2E,0x90, 0x80,0x9E,0x31, 0x01,0x6B,0x4B, 0xFC,0x2E,0x2F, 0xE0,0x4E,0x18, 0x80,0x24,0xD5, + 0xE0,0x0E,0x90, 0x84,0xBF,0xD3, 0xE0,0x2E,0x80, 0xB0,0x69,0xB4, 0x85,0xDD,0xF1, 0x73,0xDB,0x06, + 0x91,0x98,0x4D, 0xC3,0x1D,0xF8, 0x24,0xAE,0x38, 0x84,0x8D,0xB8, 0x74,0xAB,0x0D, 0x51,0x29,0x00, + 0xE2,0x05,0x09, 0xFD,0xFE,0x03, 0x8A,0xE5,0xB7, 0x4F,0xCE,0x13, 0xE4,0x84,0x9E, 0x4F,0xC5,0xEF, + 0xB5,0x0E,0xC2, 0xE4,0xD4,0xC6, 0xB5,0x1E,0xC6, 0xB4,0x2E,0xC2, 0xB9,0x0F,0x02, 0xEE,0x02,0x62, + 0xF0,0x63,0x66, 0xEE,0x0E,0xE0, 0xEE,0x00,0x5D, 0xEE,0x0E,0xE2, 0xEC,0x6B,0x50, 0xEC,0x8B,0x5D, + 0xEC,0x9E,0x44, 0x46,0x5E,0x14, 0xE4,0x84,0x9E, 0xE4,0xD0,0xD2, 0x5E,0xC4,0xFC, 0x5E,0xFB,0x74, + 0xE6,0x0B,0x48, 0x90,0x09,0xF0, 0x90,0x0B,0x5D, 0xEC,0x2F,0x86, 0x8B,0xF5,0xBC, 0x4D,0x24,0xD2, + 0x4D,0x24,0xD2, 0x8C,0x45,0xBC, 0x4D,0x28,0xC9, 0x5B,0xC4,0xD2, 0x5E,0xFB,0x5D, 0xE2,0x0B,0x4E, + 0xDE,0x06,0x9E, 0x4D,0x7B,0x1B, 0x53,0xCB,0x48, 0x52,0xC4,0xD7, 0x54,0x04,0xE4, 0x53,0x57,0x97, + 0xB1,0xB5,0x3C, 0x8C,0xE5,0xBC, 0x52,0x15,0x40, 0x5F,0x2B,0x80, 0xC2,0x8E,0xC6, 0xB3,0xA9,0x00, + 0xE0,0x34,0xEE, 0x5F,0x2B,0x3A, 0x92,0x0E,0x04, 0x4E,0xDE,0x42, 0x40,0x06,0xA1, 0x5B,0xB5,0xF5, + 0xBD,0x0E,0x11, 0xE0,0x94,0xD0, 0xE1,0x0E,0x91, 0x85,0x4E,0xF3, 0xB5,0x04,0xD0, 0xE1,0x0E,0xC3, + 0xDC,0x06,0xC4, 0xB4,0x04,0xD0, 0xE0,0x2E,0x12, 0xE4,0xA4,0xF0, 0xE4,0x24,0x00, 0x6C,0x85,0xBB, + 0xE1,0xEE,0x45, 0x40,0x00,0xA1, 0xE4,0x70,0xA5, 0xE0,0xAE,0x1A, 0x80,0x5E,0x48, 0x0A,0x95,0x40, + 0x5E,0xFF,0xB6, 0xB5,0xDE,0xC9, 0xE0,0x4B,0x00, 0xE4,0xA4,0xBD, 0xFA,0x1B,0x3A, 0x90,0x04,0xED, + 0x5F,0x2B,0x5D, 0xE2,0x0E,0x00, 0xB3,0xA9,0x20, 0x4E,0xD5,0x56, 0xFD,0xFE,0x10, 0xFC,0x15,0xF2, + 0xFD,0x1F,0xC1, 0xFC,0x0E,0x49, 0x42,0x8F,0xD0, 0x5F,0x2F,0xD1, 0xB3,0xBC,0x28, 0xE4,0x90,0x39, + 0xE4,0x90,0x06, 0xFF,0xFF,0xFF, 0x5E,0xFB,0x4B, 0xDE,0x07,0x1B, 0x5F,0x5E,0x90, 0xB0,0x08,0x80, + 0xE6,0xFE,0x7F, 0xA4,0x42,0x08, 0x5B,0x36,0x1A, 0xC2,0x1C,0xE8, 0xEC,0x2E,0x8C, 0xC8,0x1C,0x00, + 0xE1,0x1E,0x81, 0xE1,0x2B,0x20, 0xE4,0x74,0xA5, 0xFD,0xF5,0xB3, 0x62,0xAC,0x21, 0xCE,0x8E,0xC2, + 0xE8,0xCC,0x81, 0xC0,0xAE,0x11, 0xE8,0x1E,0x13, 0xB3,0x0E,0x47, 0x4A,0x50,0x32, 0x5F,0xB6,0x32, + 0x5F,0x5B,0x30, 0xE1,0x2E,0x02, 0xE4,0x74,0xA5, 0x5E,0xFB,0x7E, 0xC2,0x1E,0xC2, 0xE8,0xCC,0x81, + 0xC0,0xEF,0x84, 0xB4,0xDE,0xC2, 0xDC,0x82,0x3F, 0xE0,0x8F,0x83, 0xC0,0xD3,0x56, 0xE8,0xCC,0x83, + 0xC0,0x18,0x00, 0xE9,0x45,0xF5, 0xE9,0x0B,0x00, 0xEE,0xBE,0xF0, 0xA4,0x42,0x4A, 0xF5,0xEA,0x04, + 0xF5,0xEA,0x24, 0xEE,0xBE,0xF0, 0xA4,0xC2,0x52, 0x5F,0x5B,0xB0, 0xF6,0x3F,0x73, 0x66,0x4E,0x11, + 0xFA,0x4E,0x47, 0x4A,0x5F,0x5E, 0xA0,0x72,0x59, 0xA0,0xF0,0x59, 0xFD,0xF5,0xEF, 0xB5,0xFE,0x60, + 0xB6,0x69,0x00, 0xB5,0xDE,0xE6, 0xEC,0x2B,0x6E, 0xE4,0xA4,0xBD, 0xB5,0xDE,0xE6, 0xEC,0x2B,0x00, + 0x48,0x4E,0x10, 0xFA,0x1C,0x0B, 0xC5,0x8B,0x6A, 0x48,0x2E,0x10, 0xFA,0x0C,0x00, 0xC5,0xCB,0x64, + 0xE4,0xBF,0xE8, 0xE4,0x9F,0xE8, 0xE4,0xBF,0xE8, 0x5E,0xFB,0x5F, 0xC2,0xF2,0x96, 0xB6,0x4E,0xC2, + 0xC2,0x1E,0xE0, 0xEC,0x6C,0x60, 0xB6,0x24,0xE3, 0xB6,0x2E,0xC2, 0xB5,0xFE,0xC8, 0xB6,0x6C,0x2F, + 0xEE,0x0C,0x6F, 0x2A,0x8B,0x6A, 0xEC,0x2C,0x22, 0xEE,0x0E,0xC6, 0xC6,0x0B,0x66, 0x4E,0x5B,0x67, + 0xEC,0x2C,0xA0, 0xB7,0x0E,0xC8, 0xB6,0x8E,0xE2, 0xEE,0x6D,0x81, 0x6B,0x2C,0x8E, 0xB6,0xCA,0x82, + 0xEE,0x0A,0x96, 0xB6,0xCE,0xE8, 0xEE,0x9B,0x3A, 0xEE,0x8E,0xE9, 0xB7,0x0D,0xA8, 0x6C,0xBB,0x63, + 0xEC,0x6B,0x6E, 0xD9,0x26,0xC1, 0xB6,0xFE,0xC2, 0xB7,0x0E,0xC6, 0xA8,0x5A,0x85, 0xB6,0x3A,0xE6, + 0xC9,0x8E,0x49, 0x42,0x85,0xEF, 0xB3,0xBC,0x28, 0xB7,0x0D,0xA4, 0x6E,0x2B,0x63, 0xEC,0x6B,0x6E, + 0xD9,0x16,0xD7, 0xB6,0xFE,0xC2, 0xB7,0x0E,0xC6, 0xA8,0x5A,0x85, 0xB6,0x3A,0xE6, 0xA8,0x5C,0x98, + 0xE4,0x94,0x39, 0xFD,0xFE,0x4B, 0xFE,0x8E,0x49, 0xFE,0x8B,0x40, 0xE0,0x0E,0x48, 0x40,0xDB,0xC0, + 0xE0,0x0E,0x48, 0x40,0xD5,0xEF, 0xB3,0xA9,0xC4, 0xE4,0x54,0xA6, 0xB7,0x0E,0x04, 0xE4,0x84,0x0D, + 0xE0,0x4E,0x14, 0xE4,0xA4,0xF0, 0xE4,0x20,0x93, 0xFF,0xFF,0xFF, 0x55,0x65,0xEF, 0xB2,0xAA,0x89, + 0xEE,0x0C,0x6F, 0x20,0x0F,0xDF, 0x5B,0xB5,0xEC, 0x5C,0xE4,0x96, 0xE4,0x44,0x86, 0xE4,0x44,0x00, + 0xE1,0xC4,0x00, 0xB7,0xCD,0xE0, 0x71,0x7E,0x4F, 0x4E,0xC5,0xEF, 0xBA,0x0E,0x60, 0xE1,0xA5,0xEF, + 0xE0,0x1B,0x7C, 0xDE,0xF7,0x21, 0xE0,0x8E,0x41, 0x4E,0xCB,0xA0, 0xEE,0x2B,0x75, 0xEE,0x85,0xED, + 0x5E,0xFB,0x7C, 0xDE,0x06,0x12, 0xE4,0xF4,0x00, 0x74,0xAE,0x42, 0x4C,0x3F,0xCA, 0xFD,0x1B,0x28, + 0xDE,0x3D,0xE5, 0x73,0xAB,0x29, 0xDA,0x57,0x4D, 0xD9,0x17,0x17, 0xD9,0x27,0x43, 0x5E,0xD5,0x40, + 0x49,0x65,0x52, 0x02,0x85,0xF2, 0xBA,0x0E,0xC8, 0xA8,0x0A,0x95, 0xE4,0x7F,0xE8, 0xE4,0x34,0x07, + 0x01,0x7B,0x7B, 0xD2,0xFE,0x1F, 0x89,0x75,0xC2, 0x01,0x75,0xBB, 0xE0,0x05,0xED, 0x54,0x05,0xF5, + 0xBE,0x0E,0x0C, 0xE1,0x0E,0x47, 0x4A,0x5E,0x0D, 0xE1,0x0E,0x47, 0x4A,0x55,0xEF, 0xB3,0xCE,0x20, + 0xB1,0x09,0x00, 0xB3,0xFE,0x26, 0x49,0x15,0x21, 0xDC,0x07,0x69, 0x49,0x15,0x21, 0xDA,0x17,0x86, + 0xDA,0x26,0x76, 0x5B,0xB5,0xE2, 0xB2,0xEE,0x2F, 0xB2,0x9D,0xA4, 0x68,0x25,0xBB, 0xB1,0x4E,0xE2, + 0xEE,0x6C,0x91, 0xB1,0x4E,0x41, 0x4F,0x40,0x85, 0xB2,0xED,0xE0, 0x66,0xD0,0x6C, 0x5B,0xBB,0x3F, + 0xE2,0x0B,0x15, 0xDE,0x2E,0x49, 0x37,0xFB,0x3C, 0xE2,0xFE,0x42, 0x09,0x35,0xCE, 0x9C,0x44,0xA6, + 0x55,0x6F,0xDF, 0x5B,0x37,0x9E, 0x5F,0xD7,0x9C, 0xE0,0x10,0x9F, 0xE0,0x90,0x9F, 0xE0,0x3B,0x5E, + 0xF0,0x86,0xA5, 0xEC,0x8E,0x44, 0x46,0x5F,0xDF, 0x5E,0xFB,0x2E, 0x51,0x2E,0x20, 0xB1,0x0E,0xE2, + 0xF8,0x4E,0xE2, 0xF8,0x5E,0xE2, 0xF8,0x6E,0xE2, 0xF8,0x7E,0xE2, 0xEE,0x65,0x09, 0xB0,0x84,0xE3, + 0xB3,0xAE,0xE2, 0xE8,0x6E,0x88, 0x5F,0x5F,0xA9, 0xE8,0xCE,0x8C, 0xE8,0xCC,0x81, 0xCC,0xAE,0x10, + 0xE4,0x74,0xA5, 0xE4,0x74,0xB8, 0xF5,0xEA,0x06, 0xFA,0x9C,0x83, 0x7D,0x0E,0x47, 0x4B,0xC0,0xD1, + 0x4F,0x39,0x00, 0xFA,0x84,0xF3, 0x90,0x09,0x22, 0x90,0x0F,0xA7, 0x4F,0x39,0x00, 0xFA,0x64,0xF3, + 0x90,0x09,0x00, 0xFA,0x54,0xEF, 0x90,0x0F,0xA4, 0x0E,0xFD,0xD1, 0x2E,0x97,0xE8, 0xDC,0x82,0xE9, + 0x10,0x0C,0x06, 0xF8,0x0C,0x5E, 0xF9,0x1E,0x05, 0x0F,0xBE,0x10, 0xC0,0xAC,0x50, 0x0F,0x4E,0x10, + 0xA8,0x0A,0x95, 0xA8,0x0A,0x95, 0xF8,0x0F,0x91, 0xE0,0x5F,0x82, 0xE4,0x00,0x00, 0xFF,0xFF,0xFF, + 0x5B,0x37,0x1C, 0x5F,0xB7,0x06, 0xE4,0x60,0x1E, 0xCA,0x7E,0x08, 0xE1,0x58,0x03, 0xE4,0x84,0xA9, + 0xE0,0x2E,0x90, 0x83,0xB5,0xEF, 0xB4,0x8C,0xE8, 0xA8,0xBD,0xA8, 0x71,0xCE,0x02, 0xE8,0x0B,0x0D, + 0x83,0x85,0x12, 0x59,0x95,0x09, 0xE4,0x50,0x1A, 0xE0,0x6E,0x15, 0xE4,0x84,0xA8, 0xE4,0x50,0x1A, + 0x5B,0x37,0x22, 0x5F,0xB7,0x1E, 0xE0,0x2E,0x90, 0x80,0x9D,0xF0, 0x71,0xEB,0x5E, 0xE2,0x5E,0x44, + 0x46,0x55,0x40, 0xE4,0x44,0x86, 0xE4,0x44,0x00, 0x5E,0xFB,0x90, 0x9F,0xF9,0x1C, 0x9F,0xF9,0x1C, + 0x91,0xD9,0xFF, 0x91,0xD9,0xFF, 0x8D,0x65,0xBC, 0x5D,0xE5,0x56, 0xB0,0xD5,0x3C, 0xE1,0xCE,0x45, + 0x40,0x0B,0x82, 0xE6,0x5E,0x60, 0x5E,0xFE,0x02, 0xE9,0x0B,0x81, 0xE6,0x08,0x46, 0xB8,0x0E,0xEB, + 0xB8,0x4E,0x28, 0x84,0x5E,0xC3, 0xE4,0x94,0x00, 0x26,0x08,0x47, 0xB8,0x0E,0xEB, 0xB8,0x4E,0x20, + 0xB5,0xEE,0x25, 0xE4,0x44,0x65, 0x52,0x1B,0x57, 0xE2,0xF8,0x97, 0x5B,0xC5,0x40, 0xE4,0x44,0x86, + 0x4D,0x45,0x54, 0x52,0x1D,0xA1, 0x7C,0x5B,0x57, 0xDE,0x06,0xC5, 0xB8,0x1D,0xE0, 0x77,0xAD,0x96, + 0x66,0x7E,0xC9, 0xB8,0x0C,0x2F, 0x76,0x75,0xBB, 0x54,0x05,0xEF, 0xB8,0x4E,0xC6, 0xB8,0x1D,0xA4, + 0x68,0x6D,0x18, 0xB3,0xA9,0x10, 0xE4,0x34,0xEE, 0x4D,0x45,0x54, 0xB2,0x95,0x3C, 0x5E,0xFB,0x84, + 0xDE,0x06,0x96, 0xB8,0x3C,0x21, 0x4C,0x80,0x97, 0x4C,0xD5,0xEF, 0xB8,0x2C,0x2F, 0x74,0xCB,0x90, + 0xE4,0xC4,0xF5, 0xB8,0x3E,0xC2, 0xB9,0x8E,0xC8, 0xE1,0x5A,0xA4, 0xB9,0xCE,0xC9, 0x8E,0x55,0xBC, + 0x5D,0xE5,0x56, 0xB5,0x25,0x3C, 0x5E,0xFB,0x83, 0xDE,0x32,0xB5, 0xB4,0x1E,0x4C, 0x4E,0x54,0xC8, + 0x0B,0x64,0xCD, 0x5E,0xFB,0x46, 0xF4,0x4C,0x29, 0xEE,0x0C,0x69, 0xF5,0xBE,0x46, 0x4E,0x5B,0x29, + 0xDA,0x17,0xC5, 0xE4,0xF4,0x00, 0x62,0x65,0xBB, 0xE4,0x50,0x17, 0x88,0x35,0xBC, 0xE0,0x78,0x06, + 0x0D,0x18,0x9E, 0x5B,0xCE,0x08, 0x80,0x3E,0x15, 0xE4,0x80,0xA9, 0x5E,0xFB,0x81, 0xDE,0x06,0xE4, + 0xEC,0x6B,0xB0, 0xE0,0x7D,0x94, 0x6D,0xFB,0x80, 0xE0,0x6E,0x11, 0xE8,0x1E,0x12, 0xE4,0x74,0xA5, + 0xFD,0xF5,0xEF, 0xE0,0x2E,0x90, 0x83,0xD4,0xF6, 0x2F,0x08,0x3F, 0x4F,0x62,0xF5, 0x83,0xE0,0xF1, + 0x83,0xCB,0x46, 0x51,0x25,0x9B, 0x50,0x9F,0xDF, 0xB4,0x7F,0x0B, 0x2F,0xD7,0xFD, 0xB4,0x6A,0x3F, + 0xF0,0xBF,0xDF, 0xFF,0xFF,0xFF, 0xE4,0x40,0xE7, 0xE4,0x70,0x10, 0xE4,0xA0,0xBE, 0xE4,0x60,0x24, + 0xE4,0x60,0x00, 0xE4,0xD0,0x7E, 0xE4,0x80,0x14, 0xE4,0xA0,0xDA, 0x5B,0x37,0x20, 0x5E,0xFB,0x73, + 0xEC,0x2B,0x78, 0xEC,0x8B,0x90, 0xE4,0xB4,0xE8, 0xE1,0xAE,0x4E, 0x45,0xA3,0x22, 0xE4,0x57,0x17, + 0xE4,0x50,0x1A, 0x5F,0x2B,0x73, 0xEE,0x8D,0xC0, 0x73,0x98,0x0C, 0x5F,0xD7,0x51, 0xE0,0x2E,0x80, + 0xB0,0x9D,0xE0, 0x75,0x15,0xEF, 0xB4,0x0D,0xEF, 0x65,0x1E,0x4C, 0x4E,0x5E,0x01, 0x45,0x68,0x08, + 0x04,0x9B,0x41, 0xE4,0xC4,0xE5, 0x5F,0xD7,0x46, 0xE0,0x2E,0x80, 0xB0,0xD5,0x12, 0xE4,0xC4,0xC8, + 0x50,0x95,0xEF, 0xE0,0x24,0x56, 0x80,0xAE,0x02, 0xE8,0x0B,0x48, 0xDA,0x16,0x4F, 0xEF,0x0E,0x02, + 0x05,0x2E,0x06, 0xE1,0x5E,0x48, 0x4A,0x90,0x12, 0xF4,0x4B,0x46, 0xA8,0x8E,0xE0, 0xC6,0x03,0x5E, + 0xB4,0x69,0x99, 0xF5,0xBE,0x46, 0x0E,0x55,0xEF, 0xB5,0xD9,0x10, 0xB7,0x3E,0x60, 0xB4,0x0E,0x61, + 0xE6,0x1E,0x60, 0xE6,0x0B,0x46, 0x90,0x5B,0x54, 0x90,0x0B,0x48, 0xE6,0x0E,0x60, 0xE6,0x0E,0x6F, + 0xE6,0x0E,0x60, 0xE6,0x0E,0x60, 0xE6,0x0E,0x60, 0xB5,0xCE,0x60, 0xE0,0x2E,0x80, 0xB0,0x09,0x00, + 0x90,0x29,0xFF, 0x90,0xFE,0x60, 0xE6,0x05,0x12, 0x90,0x0E,0x60, 0x50,0x9B,0x0F, 0xE6,0xFB,0x12, + 0xE6,0xFB,0x15, 0xE6,0x5B,0x16, 0x92,0x8F,0xDF, 0xE0,0x0E,0x90, 0x5F,0x58,0x3A, 0xE8,0xBE,0xF0, + 0xE8,0x78,0x90, 0x4A,0x34,0xA3, 0x4A,0x34,0xA3, 0xF5,0xEA,0x04, 0x4A,0x34,0xA3, 0x4A,0x3E,0xF3, + 0xEF,0x7F,0xC1, 0xE1,0x0E,0x8C, 0xE8,0xDF,0x90, 0xFD,0x1D,0xD4, 0xE4,0x73,0xB8, 0xA8,0x0F,0x5E, + 0xE8,0xDE,0x8C, 0xC0,0x0C,0x56, 0xF8,0x1F,0x92, 0xE4,0x00,0x00, 0x90,0x09,0x00, 0x90,0x09,0x00, + 0x90,0x09,0x00, 0x90,0x01,0x00, 0x5F,0x2B,0x2C, 0x4D,0x55,0xB3, 0xE0,0x2E,0x80, 0x6C,0xBB,0x05, + 0xDE,0x42,0xD1, 0x0E,0x1B,0x08, 0xDE,0x07,0xD1, 0xB0,0x9D,0xE0, 0x6E,0x15,0xEF, 0xB2,0xDC,0xE8, + 0x0E,0x1C,0x08, 0xC5,0xDF,0xE8, 0x10,0x01,0x01, 0x10,0x21,0x04, 0x10,0x81,0x10, 0x12,0x01,0x40, + 0x18,0x0E,0x0E, 0xE8,0x0E,0x00, 0xE9,0x08,0x2C, 0xEF,0x3E,0xC7, 0xB1,0x0E,0xC8, 0xE8,0xCB,0x22, + 0xEC,0x8E,0x8C, 0xB2,0x4E,0xC8, 0xE8,0xCB,0x26, 0xEC,0x8B,0xB9, 0xEC,0x9A,0xF5, 0xBC,0xBE,0xC9, + 0xAF,0x5B,0xCD, 0xEC,0x9A,0xF5, 0xBC,0xFE,0xC9, 0xFD,0xFF,0xFF, 0x12,0x01,0x08, 0x10,0x11,0x40, + 0x10,0x21,0x80, 0x11,0x01,0x04, 0xD8,0x86,0x0B, 0x10,0x0E,0x10, 0xFE,0x8E,0x11, 0xE8,0x19,0x00, + 0x90,0x0C,0x0F, 0x70,0xFF,0xDF, 0x5E,0xFB,0x80, 0xE2,0x04,0x36, 0x5D,0xE5,0xEF, 0xB8,0x1D,0xE0, + 0x61,0xE4,0x67, 0x55,0x65,0x21, 0xB5,0x7E,0x2F, 0x52,0x1B,0x57, 0xDE,0x06,0x33, 0xD9,0x17,0x33, + 0xD9,0x66,0x22, 0x5B,0xBB,0x80, 0xC2,0x1D,0xE4, 0x23,0x0E,0x20, 0xE4,0xF4,0x00, 0x61,0x75,0xBB, + 0xE4,0x50,0x1A, 0x5F,0x2E,0x91, 0xB8,0x0E,0xE2, 0xE6,0x0C,0x0F, 0xC5,0x3B,0x90, 0xFE,0x80,0x43, + 0x05,0xC0,0x83, 0x08,0x99,0x18, 0x85,0x5E,0xEB, 0xE1,0x0D,0xF0, 0x74,0xAE,0x1F, 0xEE,0x98,0x54, + 0xEE,0xBE,0x60, 0x91,0x99,0x1A, 0x84,0x7E,0xEB, 0xE1,0x0D,0xF0, 0x75,0x6E,0x1F, 0xEE,0x98,0x46, + 0xEE,0xBE,0x60, 0x91,0xBF,0xDF, 0x93,0x49,0x35, 0x93,0x69,0x37, 0x9F,0xF9,0xFF, 0x9F,0xF9,0xFF, + 0x88,0x1E,0x31, 0xFD,0xF5,0xF5, 0xBC,0x29,0x3D, 0x47,0xD9,0x43, 0x47,0xD9,0x3D, 0xE0,0x0E,0x90, + 0x84,0x3E,0xC3, 0xDC,0x07,0x75, 0xE0,0x1F,0x80, 0xBC,0x6F,0x70, 0x68,0x29,0x5A, 0xEE,0x0E,0xE0, + 0x07,0x7E,0x0E, 0xF8,0x09,0x42, 0xF7,0x07,0x7F, 0xFD,0xF9,0x2E, 0x92,0xF9,0x30, 0x9F,0xF8,0x40, + 0x08,0xCE,0x4B, 0x4F,0x88,0x41, 0xE0,0x4D,0xFF, 0x39,0x4E,0xC3, 0xC0,0x1E,0x8C, 0xE8,0xCC,0x83, + 0xE1,0x4D,0xC0, 0x79,0x99,0x1D, 0x09,0xBC,0x0F, 0x91,0xCC,0x1F, 0x79,0x5F,0xDF, 0x80,0x0F,0xC1, + 0xFC,0x8F,0xC9, 0xE4,0x54,0x96, 0xFD,0x9F,0xD8, 0x5E,0xF0,0xAD, 0x80,0x0F,0xC1, 0x5F,0x2B,0x5E, + 0xEE,0x8B,0x57, 0xFD,0x2E,0xB8, 0xEB,0x5B,0xA6, 0xE4,0xE4,0x0D, 0xBA,0xAE,0x60, 0xE4,0x44,0x65, + 0x52,0x15,0x40, 0xE4,0x44,0x86, 0x5E,0xFE,0x90, 0xBA,0xAC,0x2F, 0x2D,0x5B,0xA6, 0xEC,0x2C,0x22, + 0xEE,0x0E,0xC6, 0xC6,0x0B,0xA2, 0xE4,0xE4,0x0D, 0xBA,0x28,0xA8, 0xEE,0xEE,0xF0, 0xEC,0xEC,0xB3, + 0x8A,0xAE,0xCE, 0xE8,0xFE,0x8F, 0xCB,0x3B,0xA8, 0xDE,0xF7,0xDB, 0xEE,0x0D,0xE3, 0x6F,0x48,0xA4, + 0xE8,0xBE,0xF0, 0xE8,0x78,0x5D, 0xDF,0x17,0xF0, 0xEA,0x4D,0xC0, 0x6E,0x6C,0xC8, 0xE8,0x4F,0x5E, + 0xA1,0x8A,0x0F, 0xEA,0x4C,0xC8, 0xDC,0xF7,0xF0, 0xF5,0xEA,0x01, 0x5F,0x58,0xA8, 0xE4,0x74,0xA3, + 0x55,0x45,0x21, 0xB5,0x7D,0xE0, 0x6F,0xFB,0x74, 0xDE,0x06,0xB9, 0xD9,0x76,0xB9, 0x5B,0xBF,0xDF, + 0xDC,0x06,0x05, 0xB5,0xAF,0x41, 0xA9,0x8F,0xDF, 0xE0,0x0F,0x82, 0xE0,0x8F,0x83, 0x41,0x35,0x56, + 0xB0,0x15,0x3C, 0xF6,0x2F,0x73, 0x70,0xA5,0x40, 0xFD,0xF5,0xEF, 0xB0,0x0F,0xA2, 0xE4,0x84,0x08, + 0x5F,0x5B,0x00, 0xFA,0x0F,0xB1, 0xF5,0xEA,0xD8, 0xEE,0x0A,0xD8, 0xEE,0x0A,0xD9, 0xEE,0x0A,0xD9, + 0xA1,0x1A,0x00, 0x31,0xDF,0xDF, 0xF8,0x0F,0x93, 0xB5,0xDE,0xC2, 0xE1,0x0B,0x01, 0xE4,0xC4,0x79, + 0xFA,0x1F,0xB0, 0xA8,0x1F,0xB2, 0xC5,0x0B,0x24, 0xE4,0xC4,0x79, 0x04,0x9F,0x80, 0xF9,0x3B,0x5D, + 0xEC,0x2E,0x10, 0xB0,0x1E,0x4D, 0x47,0xDF,0xA1, 0xFB,0x0A,0x81, 0xFB,0x2C,0x50, 0xB2,0x4E,0x4D, + 0x47,0xDF,0xA3, 0xC8,0x8B,0x25, 0xAE,0x8E,0x49, 0x04,0xF5,0xEF, 0xF8,0x0B,0x24, 0xEE,0x2E,0xE6, + 0xC9,0x7C,0x03, 0xC5,0x0D,0xD8, 0x37,0xEF,0x92, 0xF8,0x1B,0x3A, 0xEE,0x2E,0xE6, 0xE8,0x8E,0x85, + 0x5F,0x55,0x00, 0x5E,0xFB,0x25, 0xDA,0x86,0x7E, 0xB3,0xAE,0xE2, 0xEE,0x6E,0x88, 0xE8,0x5C,0x0E, + 0xE9,0x8C,0x51, 0xE9,0x55,0xF5, 0xE9,0x0E,0x08, 0xF8,0x0E,0xC2, 0xEE,0xBE,0xFC, 0xEC,0x2E,0xEB, + 0xEC,0xCF,0x5E, 0xA3,0xDA,0x2F, 0xF7,0x07,0x73, 0xFD,0xFE,0x47, 0x46,0x1E,0x44, 0x46,0x55,0xEC, + 0x54,0x05,0x52, 0x52,0x1D,0xA2, 0x68,0x4E,0x45, 0x05,0x31,0x9B, 0x19,0xE1,0xB1, 0x1B,0xE1,0xC3, + 0x1C,0xE1,0xD3, 0x1D,0xC1,0xE5, 0x1E,0xC1,0xF1, 0x10,0x01,0x00, 0x10,0x01,0x00, 0x10,0x09,0xCF, + 0x91,0x01,0x9B, 0x9C,0x01,0x12, 0x9C,0x01,0x12, 0x9C,0x01,0x14, 0x9C,0x01,0x12, 0x9C,0x01,0x12, + 0x9C,0x01,0x12, 0x9C,0x01,0x14, 0x9C,0x01,0x12, 0x9C,0x79,0x08, 0x1A,0xE9,0xC0, 0x11,0x09,0xC1, + 0x1F,0xB9,0xF0, 0x10,0xC9,0xC0, 0x10,0x89,0xF2, 0x10,0x79,0xC0, 0x91,0x41,0xB1, 0x9C,0x51,0x10, + 0x9C,0x19,0x0E, 0x1B,0xE9,0xC0, 0x11,0x09,0xC2, 0x1F,0xD9,0xF3, 0x10,0x59,0xC1, 0x1F,0xD9,0xF3, + 0x90,0x31,0xC3, 0x9C,0x51,0x10, 0x9D,0x09,0x10, 0x1C,0xE9,0xC0, 0x11,0x09,0xC3, 0x1F,0xF9,0xF7, + 0x10,0x39,0xC2, 0x9F,0xF1,0xD3, 0x9C,0x01,0x10, 0x9C,0x21,0xFD, 0x9F,0x51,0x05, 0x9C,0x19,0xFD, + 0x1D,0xC9,0xC7, 0x11,0x09,0xD3, 0x11,0x09,0xCB, 0x91,0x01,0xE5, 0x9C,0x71,0x10, 0x9F,0x79,0x10, + 0x1E,0xC9,0xC0, 0x11,0x09,0xC1, 0x11,0x29,0xC0, 0x11,0x09,0xC0, 0x11,0x29,0xC0, 0x11,0x09,0xC1, + 0x11,0x29,0xC7, 0x91,0x01,0xFD, 0x10,0x01,0x10, 0x12,0x11,0x33, 0x14,0x41,0x00, 0x10,0x01,0x00, + 0x10,0x01,0x00, 0x10,0x01,0x00, 0x10,0x01,0x00, 0x10,0x01,0x00, 0x10,0x01,0x15, 0x11,0x21,0x33, + 0x14,0x31,0x45, 0x10,0x01,0x41, 0x16,0x11,0x13, 0x13,0x31,0x00, 0x10,0x01,0x00, 0x10,0x01,0x00, + 0x10,0x01,0x15, 0x10,0x31,0x87, 0x1B,0x91,0x25, 0x1A,0x91,0xB1, 0x14,0x71,0x78, 0x18,0x81,0x00, + 0x10,0x01,0x00, 0x10,0x01,0x00, 0x10,0x01,0x13, 0x10,0x21,0x44, 0x16,0x51,0x87, 0x19,0x91,0xA1, + 0x1C,0xB1,0xBB, 0x1B,0xB1,0x00, 0x10,0x01,0x00, 0x10,0x01,0x00, 0x10,0x01,0x10, 0x10,0x31,0x65, + 0x14,0x71,0x22, 0x17,0x71,0x42, 0x18,0x71,0x78, 0x18,0x81,0x00, 0x10,0x01,0x00, 0x10,0x01,0x00, + 0x10,0x01,0x11, 0x10,0x21,0x33, 0x12,0x41,0x51, 0x17,0x61,0x81, 0x17,0x61,0x66, 0x16,0x61,0x00, + 0x10,0x01,0x00, 0x10,0x01,0x00, 0x10,0x01,0x21, 0x10,0x31,0x44, 0x13,0x51,0x11, 0x18,0x51,0x60, + 0x17,0x51,0x75, 0x15,0x51,0x00, 0x10,0x01,0x00, 0x10,0x01,0x00, 0x10,0x01,0x10, 0x13,0x21,0x55, + 0x12,0x61,0x77, 0x19,0x81,0x47, 0x12,0x61,0x66, 0x16,0x61,0x00, 0x10,0x01,0x00, 0x10,0x01,0x00, + 0x10,0x01,0x10, 0x10,0x21,0x33, 0x12,0x41,0x76, 0x15,0x41,0x80, 0x19,0x41,0x94, 0x14,0x41,0x00, + 0x10,0x01,0x00, 0x10,0x01,0x00, 0x10,0x01,0x21, 0x14,0x31,0x55, 0x13,0x61,0x87, 0x19,0x61,0x3A, + 0x1B,0xB1,0x5B, 0x1B,0xB1,0x00, 0x10,0x01,0x00, 0x10,0x01,0x00, 0x10,0x01,0x01, 0x11,0x21,0x33, + 0x12,0x41,0x22, 0x15,0x41,0x22, 0x16,0x41,0x54, 0x14,0x41,0x00, 0x10,0x01,0x00, 0x10,0x01,0x00, + 0x10,0x01,0x10, 0x10,0x21,0x33, 0x12,0x11,0x44, 0x15,0x51,0x44, 0x15,0x11,0x11, 0x11,0x11,0x11, + 0x10,0x0F,0xE8, 0x5E,0xFB,0x4B, 0xEC,0x2C,0x81, 0xD0,0x1B,0x78, 0xEC,0x8B,0x90, 0xE4,0xB4,0xF0, + 0xE1,0xAE,0x4E, 0x45,0xA3,0xCF, 0xE4,0x57,0x17, 0x0D,0x85,0xF2, 0xB4,0xBD,0xC0, 0x6D,0x7E,0x20, + 0xE0,0x2E,0x80, 0xB0,0x5E,0x2F, 0xE4,0x50,0x1A, 0x5B,0x37,0xEE, 0xE0,0x2E,0x80, 0xB0,0x9D,0xE0, + 0x6E,0x9E,0x20, 0x5E,0xFB,0x43, 0xC2,0x43,0xE7, 0xE2,0xF8,0xF0, 0x5B,0xCE,0x08, 0xE1,0x58,0x03, + 0xE4,0x84,0xA9, 0xE4,0x50,0x1A, 0xF8,0x05,0xEF, 0xB2,0xA9,0x00, 0x55,0x65,0xEF, 0xFA,0x0B,0x2B, + 0xF0,0x83,0xFF, 0xB2,0xAA,0x89, 0xEE,0x0C,0x60, 0x0F,0x4F,0xDF, 0x10,0x01,0x00, 0x1A,0x11,0x00, + 0x10,0x01,0x00, 0x10,0x01,0x00, 0x10,0x01,0x00, 0x10,0x01,0x00, 0x10,0x01,0x00, 0x10,0x01,0x00, + 0x10,0x01,0x20, 0x10,0x01,0x30, 0x11,0x11,0x02, 0x10,0x51,0x00, 0x10,0x01,0x00, 0x10,0x01,0x00, + 0x10,0x01,0x00, 0x10,0x01,0x00, 0x10,0x01,0x40, 0x10,0x01,0x00, 0x11,0x11,0x02, 0x10,0x01,0x00, + 0x10,0x31,0x00, 0x10,0x01,0x00, 0x10,0x01,0x00, 0x10,0x01,0x00, 0x10,0x01,0x00, 0x10,0x71,0x51, + 0x11,0x11,0x02, 0x10,0x51,0x00, 0x10,0x61,0x05, 0x10,0x01,0x00, 0x10,0x01,0x00, 0x10,0x01,0x00, + 0x10,0x01,0x60, 0x10,0x01,0x00, 0x11,0x11,0x04, 0x10,0x51,0x00, 0x10,0x01,0x00, 0x10,0x01,0x00, + 0x10,0x01,0x00, 0x10,0x01,0x00, 0x10,0x01,0x05, 0x10,0x71,0x00, 0x11,0x11,0x02, 0x10,0x01,0x00, + 0x10,0x01,0x05, 0x10,0x01,0x00, 0x10,0x01,0x00, 0x10,0x01,0x00, 0x10,0x01,0x70, 0x10,0x71,0x80, + 0x11,0x11,0x04, 0x10,0x01,0x00, 0x10,0x01,0x00, 0x10,0x01,0x00, 0x10,0x01,0x00, 0x10,0x01,0x00, + 0x10,0x01,0x70, 0x10,0x71,0x50, 0x11,0x11,0x04, 0x10,0x01,0x00, 0x10,0x01,0x05, 0x10,0x01,0x00, + 0x10,0x01,0x00, 0x10,0x01,0x00, 0x10,0x01,0x40, 0x10,0x71,0x50, 0x11,0x11,0x02, 0x10,0x01,0x00, + 0x10,0x01,0x00, 0x10,0x01,0x00, 0x10,0x01,0x00, 0x10,0x01,0x00, 0x10,0x01,0x60, 0x10,0x01,0x80, + 0x11,0x11,0x02, 0x10,0x01,0x00, 0x10,0x01,0x00, 0x10,0x01,0x00, 0x10,0x01,0x00, 0x10,0x01,0x00, + 0x10,0x01,0x00, 0x10,0x71,0x50, 0x11,0x11,0x04, 0x10,0x01,0x05, 0x10,0x01,0x05, 0x10,0x01,0x00, + 0x10,0x01,0x00, 0x10,0x01,0x00, 0x10,0x01,0x90, 0x10,0x71,0x50, 0x11,0x11,0x04, 0x10,0x51,0x05, + 0x10,0x01,0x05, 0x10,0x01,0x00, 0x10,0x01,0x00, 0x10,0x01,0x00, 0x1C,0xA1,0xCD, 0x1D,0x01,0xD3, + 0x1D,0x81,0xDB, 0x1D,0xE1,0xE3, 0x1E,0x81,0xE8, 0x10,0x19,0x31, 0x1C,0xA1,0x07, 0x93,0x71,0xCE, + 0x10,0x09,0x30, 0x1D,0x01,0x01, 0x13,0x11,0x01, 0x9F,0x11,0xD3, 0x10,0x09,0xF0, 0x1D,0x81,0x01, + 0x9F,0x11,0xDB, 0x10,0x11,0x31, 0x10,0x19,0xB1, 0x1D,0xE1,0x01, 0x13,0x11,0x01, 0x93,0x11,0xE6, + 0x9F,0xF9,0x28, 0x92,0x99,0x2A, 0x9F,0xF9,0x2B, 0x92,0xC1,0x2D, 0x9F,0xF9,0x38, 0x93,0x99,0xFF, + 0x9F,0xF9,0x0E, 0x91,0x71,0xFF, 0x93,0x19,0x32, 0x93,0x31,0xFF, 0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF, + 0x10,0xC1,0x11, 0x11,0x81,0x24, 0x13,0x11,0x3A, 0x14,0x31,0x4C, 0x15,0x61,0x60, 0x16,0xC1,0x73, + 0x14,0x31,0x45, 0x14,0x71,0x49, 0x14,0xB1,0x7F, 0x17,0xF1,0x7F, 0x17,0xF1,0x7F, 0x17,0xF1,0x7F, + 0x10,0xC1,0x09, 0x10,0x91,0x0A, 0x10,0xA1,0x07, 0x18,0xC1,0x0D, 0x10,0xD1,0x0F, 0x18,0xF1,0x10, + 0x10,0xC1,0x09, 0x10,0xA1,0x11, 0x10,0xD1,0x0F, 0x11,0x01,0x11, 0x10,0x91,0x0F, 0x11,0x01,0x0D, + 0x10,0xA1,0x17, 0x11,0x81,0x18, 0x11,0x91,0x19, 0x11,0xA1,0x1A, 0x19,0xA1,0x9A, 0x12,0x01,0xA2, + 0x12,0x41,0xA6, 0x1A,0x61,0x22, 0x1A,0x61,0x26, 0x12,0x41,0x27, 0x12,0x81,0x29, 0x12,0xB1,0x2C, + 0x1A,0xC1,0x2B, 0x1A,0xC1,0x2C, 0x12,0xD1,0x2D, 0x13,0x01,0x31, 0x13,0x01,0x32, 0x13,0x21,0x33, + 0x13,0x41,0xB4, 0x11,0x71,0x18, 0x11,0x91,0x1A, 0x19,0xA1,0x1A, 0x1B,0x81,0x38, 0x11,0x91,0x9A, + 0x11,0x71,0x17, 0x11,0x81,0x19, 0x11,0x71,0x1A, 0x19,0xA1,0x18, 0x19,0x81,0x97, 0x19,0x81,0x9A, + 0x13,0x51,0x35, 0x13,0x61,0x37, 0x13,0x71,0xB7, 0x13,0x71,0x3C, 0x13,0xE1,0x40, 0x14,0x11,0x42, + 0x14,0x1F,0xE8, 0xF5,0xBB,0x7C, 0xDE,0x06,0x81, 0xDE,0xF6,0x82, 0xC2,0xFF,0xDF, 0xB4,0xAD,0xA8, + 0x69,0x65,0xF8, 0xE0,0x2E,0x80, 0x78,0xEB,0x15, 0xC2,0xF2,0x8D, 0xE2,0x0F,0xDF, 0xB0,0x4C,0x21, + 0xEE,0x0C,0x60, 0x39,0x5B,0x04, 0x9F,0xFF,0xDF, 0x5F,0x8E,0x02, 0xE8,0x07,0xA1, 0xB1,0x6C,0x2F, + 0xEE,0x0C,0x6F, 0x2A,0x1B,0x16, 0x90,0x0B,0x00, 0x4D,0x2B,0x02, 0x4D,0x2B,0x08, 0x4D,0x9B,0x09, + 0x4D,0x9B,0x06, 0x4D,0x25,0xEF, 0xB4,0x0D,0xE0, 0x6B,0x8B,0x41, 0xDE,0x06,0xB8, 0xE0,0x2E,0x80, + 0xB0,0xA9,0x00, 0xE2,0x00,0xBC, 0xE0,0x2E,0x80, 0xB0,0xA4,0xDF, 0x5F,0xB6,0xC3, 0xE0,0x2E,0x80, + 0xB0,0xD4,0xDF, 0x0C,0x7E,0x02, 0xE8,0x0B,0x0D, 0x4C,0x8B,0x10, 0xC2,0xFE,0xE0, 0xC6,0xFE,0xE0, + 0xC6,0xF2,0xD1, 0xA1,0xE9,0x00, 0xE2,0x0F,0xDF, 0xC2,0xFE,0xE0, 0xC6,0xF2,0xD8, 0xA1,0xF9,0x00, + 0xFD,0xFD,0xE0, 0x6D,0xEC,0x21, 0x3D,0xEE,0x2F, 0xFD,0xFC,0x21, 0xEE,0x0C,0x60, 0xEE,0x0C,0x60, + 0xFD,0xFC,0x24, 0x3E,0x8E,0x2F, 0xB4,0x0D,0xE0, 0x6F,0x4B,0x41, 0xDE,0x06,0xF4, 0xE0,0x2E,0x80, + 0xB0,0x8E,0x20, 0xE0,0x0E,0x80, 0xFD,0xF9,0x18, 0x9F,0xF9,0x1D, 0x9F,0xF9,0x00, 0x90,0xF9,0x00, + 0x1F,0xFF,0xFF, 0xFF,0xFF,0xFF, 0x11,0x01,0x15, 0x11,0xC1,0x28, 0x13,0x51,0x3E, 0x14,0x71,0x50, + 0x15,0xA1,0x64, 0x17,0x01,0x77, 0x17,0xD1,0x7D, 0x17,0xD1,0x7D, 0x14,0x41,0x46, 0x14,0x81,0x4A, + 0x14,0xC1,0x05, 0x10,0x11,0x02, 0x10,0x31,0x04, 0x10,0x01,0x06, 0x10,0x81,0x0B, 0x10,0x81,0x08, + 0x10,0xB1,0x08, 0x10,0x81,0x08, 0x10,0xB1,0x08, 0x10,0x81,0x0B, 0x11,0x41,0x92, 0x11,0x31,0x12, + 0x11,0x51,0x13, 0x11,0x21,0x13, 0x19,0x31,0x12, 0x11,0x61,0x12, 0x19,0x21,0x08, 0x10,0xB1,0x08, + 0x10,0x81,0x0B, 0x10,0x81,0x0B, 0x10,0x81,0x0B, 0x12,0x11,0xA3, 0x12,0x51,0x15, 0x12,0x11,0xA3, + 0x1A,0x31,0xA3, 0x11,0x61,0x21, 0x1A,0x31,0x2A, 0x12,0x51,0x15, 0x12,0x11,0x16, 0x12,0x51,0x21, + 0x12,0xE1,0x2F, 0x12,0xF1,0x2E, 0x1A,0xE1,0x15, 0x12,0xE1,0x2E, 0x12,0xE1,0x2E, 0x12,0x11,0x25, + 0x12,0x51,0x15, 0x12,0x11,0x21, 0x1A,0x31,0x23, 0x11,0x61,0x25, 0x13,0x91,0x3A, 0x13,0x91,0x39, + 0x13,0xB1,0x3B, 0x13,0xA1,0x3B, 0x13,0xB1,0x3A, 0x1B,0xA1,0x3B, 0x1A,0xE1,0x2E, 0x1A,0xE1,0x15, + 0x12,0xE1,0x2E, 0x12,0xF1,0x3D, 0x13,0xF1,0x2F, 0x11,0x51,0x2E, 0x13,0xDF,0xE8, 0x5B,0x37,0x92, + 0x5F,0x5B,0x40, 0x49,0x4B,0xC0, 0x49,0x4E,0x04, 0xE1,0x4E,0x4A, 0x4F,0x0B,0x4D, 0xDE,0x06,0x92, + 0xE2,0x0E,0x07, 0xE1,0x58,0x06, 0xE4,0x84,0xA9, 0xE4,0x50,0x1A, 0x94,0x49,0xEE, 0x9B,0xB9,0x55, + 0x9A,0xA9,0x11, 0x90,0x01,0x00, 0x90,0x01,0x21, 0x93,0x39,0x45, 0x90,0x39,0x44, 0x93,0x09,0x33, + 0x90,0x01,0x32, 0x94,0x39,0xAF, 0x92,0x39,0x9F, 0x90,0x39,0x8F, 0x92,0x09,0x7F, 0x91,0x09,0x6F, + 0x90,0x01,0x5F, 0x98,0x49,0xAF, 0x90,0x49,0x9F, 0x92,0x09,0x76, 0x90,0x01,0x6F, 0x93,0x09,0xAF, + 0x92,0x09,0x9F, 0x90,0x01,0x8F, 0x96,0x09,0xAF, 0x90,0x01,0x9F, 0x90,0x01,0xBF, 0xB9,0x0E,0x10, + 0xC0,0xBC,0x5C, 0xFE,0x80,0x9C, 0x09,0xE0,0xA6, 0x0B,0x20,0xBA, 0x0C,0x00,0xC4, 0x5F,0x2E,0x91, + 0xB4,0x9E,0x20, 0xB5,0xDE,0xC2, 0xC0,0x8C,0x55, 0xF8,0x0F,0x91, 0xE0,0x5F,0x82, 0xE0,0x2E,0x80, + 0xB3,0x05,0x00, 0x84,0x8E,0xC3, 0xE1,0x2E,0x91, 0xB1,0x08,0x40, 0x51,0x25,0x99, 0xD8,0x87,0xEF, + 0xB0,0xD8,0x38, 0x59,0x95,0x09, 0x84,0x3B,0x13, 0xEC,0xB5,0xEF, 0x84,0x4B,0x43, 0xEC,0xBB,0x50, + 0xDE,0x26,0xFC, 0xDE,0x47,0xFE, 0xB4,0x3E,0x28, 0xE4,0x60,0xE5, 0x10,0xE1,0x11, 0x11,0x61,0x1F, + 0x12,0x41,0x24, 0x12,0x91,0x2E, 0x13,0x11,0x3C, 0x14,0x51,0x4E, 0x15,0x5F,0xE8, 0x9F,0xF9,0x50, + 0x10,0xE9,0x60, 0x13,0x09,0x61, 0x93,0x01,0x11, 0x9F,0xF1,0x50, 0x9F,0xF1,0x50, 0x95,0xE1,0xA8, + 0x95,0xF9,0xA8, 0x11,0xA9,0x65, 0x13,0x09,0x64, 0x93,0x01,0x1F, 0x96,0x21,0x30, 0x97,0xF9,0x50, + 0x12,0x49,0x7F, 0x15,0x09,0x63, 0x93,0x01,0x29, 0x9D,0x79,0xB0, 0x12,0xE9,0x10, 0x10,0x09,0x10, + 0x18,0x09,0xD1, 0x18,0x09,0xD2, 0x18,0x09,0xD3, 0x98,0x01,0x39, 0x91,0x01,0x00, 0x91,0x01,0x80, + 0x95,0x21,0x80, 0x95,0x39,0x80, 0x14,0x29,0x14, 0x10,0x09,0x14, 0x18,0x09,0xD5, 0x18,0x09,0xD6, + 0x98,0x01,0x0E, 0x91,0x41,0x00, 0x91,0x41,0x80, 0x95,0x69,0x80, 0x10,0xE9,0x10, 0x10,0x09,0xD0, + 0x98,0x01,0x57, 0x5E,0xFE,0x02, 0xE4,0x14,0xEC, 0x5C,0xE9,0x40, 0xB7,0x8E,0xE2, 0xB7,0x5E,0xE8, + 0xE4,0x24,0xC3, 0x27,0x96,0x79, 0xB9,0x09,0xFF, 0xB9,0x89,0xFF, 0xB9,0x0D,0xC0, 0x67,0x0B,0x98, + 0x92,0x7E,0x47, 0x49,0x25,0x56, 0xE4,0xF4,0x00, 0x66,0x45,0xEF, 0xF4,0x1B,0x78, 0xEE,0x8F,0xDF, + 0xFE,0x89,0xFF, 0x90,0x81,0x7D, 0x93,0x09,0x03, 0x17,0xD9,0x00, 0x10,0x79,0x00, 0x10,0x69,0x00, + 0x10,0x59,0x00, 0x10,0x49,0x00, 0x10,0x39,0x00, 0x10,0x29,0x00, 0x10,0x19,0x00, 0x90,0x01,0x7D, + 0x90,0x19,0x04, 0x17,0xD9,0x01, 0x10,0x59,0x01, 0x10,0x89,0x01, 0x90,0x31,0x7D, 0x90,0x51,0x07, + 0x90,0x31,0x08, 0x90,0xB9,0x07, 0x17,0xD9,0x01, 0x10,0x29,0x01, 0x10,0x89,0x07, 0x10,0x39,0x07, + 0x90,0x81,0xA5, 0x90,0x21,0x01, 0x90,0x21,0x04, 0x90,0x21,0x02, 0x90,0x21,0x05, 0x90,0x21,0x03, + 0x90,0x21,0x06, 0x90,0x21,0x04, 0x90,0x29,0x07, 0x1A,0xE9,0x12, 0x10,0x39,0x19, 0x90,0x81,0xBF, + 0x91,0x81,0x03, 0x92,0x89,0x08, 0x1C,0x49,0x1C, 0x10,0x39,0x44, 0x90,0x81,0xC9, 0x95,0x09,0x03, + 0x17,0xD9,0x03, 0x10,0x49,0x02, 0x90,0x21,0xD1, 0x90,0xC1,0x02, 0x90,0xC1,0x04, 0x90,0xC1,0x06, + 0x90,0xC1,0x04, 0x90,0xC1,0x02, 0x90,0xC1,0x08, 0x91,0x09,0x01, 0x17,0xD9,0x0C, 0x10,0x49,0x06, + 0x10,0x29,0x0C, 0x10,0x39,0x06, 0x10,0x49,0x10, 0x90,0x51,0x7D, 0x90,0x61,0x01, 0x90,0x71,0x02, + 0x90,0x81,0x03, 0x90,0xA1,0x04, 0x90,0xC1,0x05, 0x90,0xE9,0x06, 0x17,0xDF,0xFF, 0xFF,0xFF,0xFF, + 0xE0,0x2E,0x90, 0x5E,0xFB,0x7C, 0xDE,0xF7,0xD6, 0xB5,0xCD,0xE0, 0x7D,0x6B,0x14, 0x51,0x2E,0xE2, + 0xEC,0x65,0x09, 0xB4,0xAD,0xA8, 0x64,0xA5,0xF8, 0x71,0x78,0x15, 0xDF,0x06,0x1D, 0x0D,0x68,0x31, + 0x4D,0x92,0x35, 0x83,0x34,0xD9, 0x33,0x5B,0x4B, 0xE2,0xFB,0x4A, 0xE2,0x0F,0x44, 0xB5,0x4C,0x21, + 0xEE,0x0C,0x60, 0xF5,0xB3,0x2A, 0xB5,0x49,0x99, 0xB5,0x0D,0xEF, 0x7D,0x68,0x10, 0x5D,0x77,0xD6, + 0x83,0x44,0x3D, 0x83,0x64,0x3D, 0x0D,0x68,0x05, 0xDF,0xF6,0x3C, 0xDF,0x42,0x3C, 0xE3,0xF4,0xDF, + 0x0D,0x6E,0xF3, 0xEC,0x7E,0x8D, 0xE8,0xCE,0x8D, 0xE8,0xCC,0x93, 0xF5,0xEA,0x3F, 0xAA,0xCE,0xF0, + 0xAB,0xDF,0xDF, 0x5F,0x87,0x53, 0x81,0x5D,0xF0, 0x65,0xB8,0x16, 0x5D,0x47,0x5B, 0x05,0x98,0x33, + 0x4D,0x93,0x59, 0x83,0x14,0xD9, 0x35,0xBE,0x01, 0x0D,0x4B,0x49, 0xDE,0x33,0x74, 0x5F,0x87,0x63, + 0x5F,0xD6,0x71, 0x07,0x18,0x0C, 0xDF,0x22,0x69, 0x80,0xBD,0xFD, 0x37,0x45,0xFD, 0x67,0x18,0x0F, + 0xDF,0x12,0x71, 0x80,0xED,0xF6, 0x37,0x4B,0x4F, 0xDE,0x52,0x76, 0xE0,0x60,0xD4, 0x81,0x05,0xD7, + 0x78,0x0B,0x50, 0xDE,0xF3,0x7E, 0xE0,0x50,0xD4, 0xB4,0xEE,0x2F, 0x80,0x65,0xD4, 0x78,0x5E,0x04, + 0x0D,0x45,0xFD, 0x78,0xD8,0x0D, 0x5D,0x77,0x8D, 0xE2,0xFB,0x49, 0xC2,0x18,0x00, 0x5D,0x47,0xA2, + 0x83,0x4E,0xF3, 0xEC,0x78,0x00, 0x51,0x2E,0xFC, 0xEC,0xD5,0x09, 0xB4,0x0C,0x2C, 0x29,0xEE,0x20, + 0xE0,0x20,0xD4, 0x81,0x3C,0x3F, 0x2A,0x2E,0x30, 0x80,0x25,0xD4, 0x7B,0x78,0x36, 0xEF,0x3E,0xC7, + 0x80,0x25,0x12, 0xEF,0xCE,0xCD, 0x50,0x9B,0x41, 0xC2,0xC2,0xB3, 0xE2,0x0E,0x02, 0x0D,0x48,0x13, + 0xC3,0xF2,0xB7, 0xE3,0x08,0x43, 0xEC,0x38,0x13, 0xDF,0x07,0xC6, 0xEC,0xC8,0x14, 0xB4,0x3F,0x41, + 0xA9,0xE2,0xC6, 0x5F,0x86,0xC6, 0xE0,0x30,0xD4, 0x80,0x8D,0xFF, 0x7C,0xDE,0x30, 0x5F,0x86,0xCD, + 0x4D,0xF8,0x09, 0xDF,0xF7,0xD3, 0xE3,0x0B,0x51, 0x4E,0x80,0xD6, 0xB5,0xCE,0xC8, 0xB5,0xCD,0xE0, + 0xFD,0xFF,0x07, 0x7D,0xEA,0x3F, 0xA2,0xFF,0x03, 0xFD,0xFB,0x42, 0x4E,0x8B,0x50, 0xDE,0xF7,0xEB, + 0x81,0x05,0xD7, 0x7E,0xBB,0x4F, 0xC2,0x13,0xEB, 0xE2,0xFF,0xDF, 0x5E,0xFB,0x7C, 0xE2,0xFE,0x06, + 0x8D,0x15,0xB7, 0xE0,0x2E,0x14, 0xE4,0x84,0xA8, 0x5E,0xFB,0x74, 0xE6,0xFB,0x5D, 0x91,0x1E,0x44, + 0x46,0x5E,0x4D, 0x0D,0x2F,0xFF, 0xFA,0x0F,0xB1, 0xE5,0x0F,0xE8, 0xFA,0x0F,0xB1, 0xE5,0x1F,0xE8, + 0xFA,0x0F,0xB1, 0xE5,0x2F,0xE8, 0xFA,0x0F,0xB1, 0xE5,0x3F,0xE8, 0xFA,0x0F,0xB1, 0xE5,0x4F,0xE8, + 0xFA,0x0F,0xB1, 0xE5,0x5F,0xE8, 0xFA,0x0F,0xB1, 0xE5,0x6F,0xE8, 0xFA,0x0F,0xB1, 0xE5,0x7F,0xE8, + 0x42,0x3E,0x40, 0x00,0x9F,0xE8, 0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF, 0x90,0x09,0x00, 0x90,0x09,0x00, 0x90,0x09,0x3C, 0x97,0xA9,0x6E, + 0x96,0xE9,0x7A, 0x93,0xC9,0x00, 0x90,0x09,0x00, 0x90,0x01,0x00, 0x90,0x09,0x00, 0x90,0x09,0x00, + 0x98,0x09,0xC0, 0x9A,0x09,0xE0, 0x9E,0x09,0xA0, 0x9C,0x09,0x80, 0x90,0x09,0x00, 0x90,0x01,0x00, + 0x90,0x09,0x00, 0x90,0x09,0x00, 0x90,0x09,0x40, 0x94,0x39,0x67, 0x97,0xE9,0x6E, 0x93,0x89,0x00, + 0x90,0x09,0x00, 0x90,0x01,0x00, 0x90,0x09,0x00, 0x90,0x09,0x00, 0x9C,0x09,0xA0, 0x9A,0x09,0xE0, + 0x9E,0x09,0xA0, 0x9A,0x09,0xC0, 0x90,0x09,0x00, 0x90,0x01,0x00, 0x90,0x09,0x00, 0x90,0x09,0x00, + 0x90,0x09,0x1E, 0x93,0xD9,0x27, 0x92,0x79,0x3D, 0x91,0xE9,0x00, 0x90,0x09,0x00, 0x90,0x01,0x00, + 0x90,0x09,0x00, 0x90,0x09,0x00, 0x90,0x09,0x2C, 0x96,0xE9,0x7A, 0x97,0xA9,0x7E, 0x93,0xC9,0x00, + 0x90,0x09,0x00, 0x90,0x01,0x00, 0x90,0x09,0x00, 0x90,0x09,0x00, 0x90,0xE9,0x3D, 0x97,0xB9,0x4F, + 0x94,0xF9,0x7B, 0x93,0xD9,0x0E, 0x90,0x09,0x00, 0x90,0x01,0x00, 0x90,0x09,0x00, 0x90,0x09,0xE0, + 0x91,0x09,0x08, 0x92,0x89,0x88, 0x98,0x89,0x28, 0x90,0x89,0x10, 0x9E,0x09,0x00, 0x90,0x01,0x00, + 0x90,0x09,0x00, 0x90,0x09,0x03, 0x90,0x49,0x08, 0x90,0x89,0x08, 0x90,0x89,0x08, 0x90,0x89,0x04, + 0x90,0x39,0x00, 0x90,0x01,0x00, 0x90,0x09,0x00, 0x90,0x09,0xE0, 0x91,0x09,0x28, 0x90,0x89,0xC8, + 0x9C,0x89,0x08, 0x92,0x89,0x10, 0x9E,0x09,0x00, 0x90,0x01,0x00, 0x90,0x09,0x00, 0x90,0x09,0xC0, + 0x98,0x69,0xCD, 0x99,0x99,0xF1, 0x90,0x19,0x11, 0x91,0x29,0x04, 0x9F,0x89,0x00, 0x90,0x01,0x00, + 0x90,0x09,0x00, 0x90,0x09,0x01, 0x90,0x29,0x04, 0x90,0x49,0x04, 0x90,0x49,0x04, 0x90,0x49,0x02, + 0x90,0x19,0x00, 0x90,0x01,0x00, 0x90,0x09,0x00, 0x90,0x09,0xE0, 0x99,0x09,0x88, 0x98,0x89,0x28, + 0x90,0x89,0x08, 0x90,0x89,0x10, 0x9E,0x09,0x00, 0x90,0x01,0x00, 0x90,0x09,0x00, 0x90,0x09,0xE0, + 0x91,0x09,0x28, 0x92,0x89,0x88, 0x98,0x89,0x28, 0x92,0x89,0x10, 0x9E,0x09,0x00, 0x90,0x01,0x00, + 0x9F,0xF9,0xFF, 0x9F,0xF9,0xFF, 0x9F,0xF9,0xFF, 0x9F,0xF9,0xFF, 0x9F,0xF9,0xFF, 0x9F,0xF9,0xFF, + 0x9F,0xF9,0xFF, 0x9F,0xF1,0xFF, 0x90,0x09,0x00, 0x90,0x09,0xE0, 0x99,0x09,0x88, 0x98,0x89,0x28, + 0x92,0x89,0x08, 0x90,0x89,0x10, 0x9E,0x09,0x00, 0x90,0x01,0x00, 0x90,0x09,0x00, 0x90,0x09,0xFC, + 0x90,0x29,0x79, 0x9F,0x39,0xF1, 0x9F,0x19,0xF3, 0x97,0x99,0x02, 0x9F,0xC9,0x00, 0x90,0x01,0x00, + 0x90,0x09,0x00, 0x90,0x09,0xE0, 0x91,0x09,0x08, 0x92,0x89,0x88, 0x98,0x89,0x28, 0x90,0x89,0x10, + 0x9E,0x09,0x00, 0x90,0x01,0x00, 0x90,0x09,0x00, 0x90,0x19,0x07, 0x91,0x89,0x20, 0x91,0x89,0x08, + 0x90,0x89,0x08, 0x91,0x09,0x09, 0x90,0x79,0x01, 0x90,0x01,0x00, 0x90,0x09,0x00, 0x90,0x09,0x03, + 0x90,0x49,0x18, 0x92,0x09,0x18, 0x91,0x89,0x28, 0x91,0x89,0x04, 0x90,0x39,0x00, 0x90,0x01,0x00, + 0x90,0x09,0x00, 0x90,0x09,0x03, 0x91,0xC9,0x28, 0x91,0x89,0x08, 0x90,0x89,0x10, 0x92,0x09,0x3C, + 0x90,0x39,0x00, 0x90,0x01,0x00, 0x90,0x09,0x7E, 0x98,0x19,0x99, 0x9A,0xF9,0xB5, 0x9A,0xD9,0xB5, + 0x9A,0xD9,0xB5, 0x9A,0xD9,0xB5, 0x9A,0xF9,0x99, 0x98,0x11,0x7E, 0x90,0x09,0x03, 0x90,0x59,0x0C, + 0x91,0x09,0x10, 0x92,0x09,0x10, 0x91,0x09,0x20, 0x91,0x09,0x10, 0x90,0xC9,0x05, 0x90,0x31,0x00, + 0x95,0x09,0xA8, 0x9A,0x89,0xA8, 0x90,0x49,0x0A, 0x90,0x29,0x02, 0x90,0x29,0x0A, 0x90,0x49,0x08, + 0x9F,0x09,0x00, 0x90,0x01,0x00, 0x96,0xC9,0x92, 0x95,0x49,0xD4, 0x90,0x29,0x06, 0x90,0x29,0x02, + 0x90,0xA9,0x02, 0x90,0x49,0x08, 0x9F,0x09,0x00, 0x90,0x01,0x00, 0x94,0x49,0xAA, 0x9A,0xA9,0xBA, + 0x90,0x29,0x02, 0x90,0x69,0x02, 0x90,0x29,0x22, 0x90,0x49,0x08, 0x9F,0x09,0x00, 0x90,0x01,0x00, + 0x90,0x09,0x00, 0x90,0x09,0xF0, 0x90,0x89,0x04, 0x90,0xA9,0x0A, 0x90,0x29,0x0A, 0x90,0xA9,0x04, + 0x9A,0x89,0xA8, 0x9A,0x81,0x50, 0xE0,0xFE,0x80, 0xB1,0x0E,0x68, 0xE6,0x0E,0x61, 0xE6,0x0E,0x60, + 0xE6,0x0B,0x26, 0x90,0x7B,0x54, 0xE6,0xFB,0x71, 0xE6,0x8E,0x68, 0xB7,0x6E,0x63, 0xE6,0x2E,0x62, + 0xE6,0x2E,0x42, 0x04,0x4F,0xFF, 0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF, + 0xE0,0x0E,0x80, 0xB2,0x49,0x00, 0xB1,0x49,0x20, 0xB3,0x29,0x00, 0xB3,0x69,0x7D, 0xB5,0x89,0xFF, + 0xB7,0xBE,0x6F, 0xB7,0xDE,0x2F, 0xB3,0xCE,0x20, 0xB7,0x4E,0x60, 0xB7,0xCE,0x25, 0xE0,0xFE,0x80, + 0xB7,0x1E,0x20, 0xB7,0x8E,0x21, 0xB0,0x0E,0xE2, 0xEE,0x2E,0xC2, 0xE4,0x20,0x55, 0xEE,0xEE,0xF0, + 0xEE,0xEE,0xF0, 0xEE,0xEE,0xF0, 0xEE,0xEE,0xF0, 0xEE,0xEE,0xF0, 0xEE,0xEE,0x42, 0x02,0x9F,0xFF, + 0x90,0x09,0x00, 0x96,0x09,0x90, 0x90,0xE9,0x57, 0x94,0x69,0x04, 0x90,0x49,0x14, 0x90,0x69,0x0F, + 0x91,0xE9,0xF0, 0x90,0x01,0x00, 0x90,0x09,0x00, 0x90,0x09,0x07, 0x90,0x89,0x30, 0x94,0x09,0x30, + 0x91,0x39,0x34, 0x94,0x39,0x30, 0x90,0x89,0x07, 0x90,0x01,0x00, 0x90,0x09,0x60, 0x99,0xE9,0x07, + 0x90,0x79,0x16, 0x94,0x49,0x44, 0x94,0x49,0x16, 0x90,0x79,0x07, 0x99,0xE9,0x60, 0x90,0x01,0x00, + 0x90,0x09,0x00, 0x90,0x79,0x0A, 0x91,0x39,0x20, 0x91,0x09,0x10, 0x93,0x09,0x40, 0x93,0x19,0x0A, + 0x90,0x69,0x01, 0x90,0x01,0x00, 0x90,0x09,0x00, 0x97,0x09,0x88, 0x90,0x49,0x74, 0x97,0x29,0x73, + 0x97,0x79,0x06, 0x90,0xC9,0x2C, 0x91,0xC9,0xFC, 0x91,0x81,0x00, 0x90,0x09,0x00, 0x90,0x09,0x0F, + 0x93,0x09,0x40, 0x93,0x09,0x30, 0x94,0x19,0x32, 0x91,0x19,0x10, 0x90,0x89,0x07, 0x90,0x01,0x00, + 0x90,0x09,0x60, 0x99,0xE9,0x0F, 0x91,0x79,0x16, 0x90,0x49,0x44, 0x90,0x49,0x16, 0x91,0x79,0x0F, + 0x99,0xE9,0x60, 0x90,0x01,0x00, 0x90,0x09,0x60, 0x9D,0x09,0x58, 0x94,0x49,0x4A, 0x94,0x29,0x46, + 0x94,0x29,0x2A, 0x90,0x69,0x1C, 0x9F,0x89,0xF0, 0x90,0x01,0x00, 0x90,0x09,0x00, 0x90,0x09,0xF8, + 0x90,0x49,0x2A, 0x94,0x29,0x46, 0x94,0x69,0x46, 0x94,0x29,0x2A, 0x90,0x49,0xF8, 0x90,0x01,0x00, + 0x90,0x09,0x00, 0x9F,0x89,0x04, 0x90,0xE9,0x1E, 0x93,0xE9,0x7E, 0x97,0xE9,0x3E, 0x91,0xE9,0x04, + 0x9F,0x89,0x00, 0x90,0x01,0x00, 0x90,0x09,0x00, 0x90,0x79,0x08, 0x91,0x09,0x20, 0x91,0x69,0x14, + 0x93,0x49,0x42, 0x93,0x09,0x08, 0x90,0x69,0x01, 0x90,0x01,0x00, 0x93,0x09,0x28, 0x9A,0x89,0xA8, + 0x9A,0x49,0xA4, 0x96,0xC9,0x04, 0x90,0x49,0x04, 0x92,0xC9,0x1C, 0x9F,0x89,0xF0, 0x90,0x01,0x00, + 0x90,0x09,0x00, 0x9F,0x09,0xF8, 0x91,0xC9,0x0E, 0x90,0xA9,0x02, 0x94,0x69,0x42, 0x94,0xA9,0x4C, + 0x95,0x89,0xD0, 0x96,0x01,0x00, 0x90,0x09,0xC0, 0x9F,0x89,0xAC, 0x98,0xE9,0x7E, 0x91,0xE9,0x1E, + 0x91,0xF9,0x3F, 0x93,0xF9,0x3F, 0x97,0xC9,0xF8, 0x90,0x01,0x00, 0x90,0x09,0x40, 0x96,0x09,0x53, + 0x91,0x49,0x08, 0x91,0x09,0x10, 0x91,0x09,0x10, 0x91,0x09,0x10, 0x90,0x89,0x44, 0x96,0xB1,0x58, + 0x90,0x09,0x00, 0x90,0xD9,0x52, 0x96,0x29,0x44, 0x90,0x49,0x04, 0x90,0x49,0x04, 0x90,0x49,0x02, + 0x94,0xE9,0x71, 0x94,0x01,0x00, 0x90,0x09,0x00, 0x9F,0xC9,0x02, 0x97,0x99,0xB5, 0x9F,0xD9,0xB5, + 0x9B,0x59,0xFD, 0x9B,0x59,0x79, 0x90,0x29,0xFC, 0x90,0x01,0x00, 0x90,0x09,0x00, 0x9F,0xC9,0x02, + 0x91,0x19,0x11, 0x91,0x19,0x11, 0x91,0x19,0x11, 0x91,0x19,0x11, 0x90,0x29,0xFC, 0x90,0x01,0x00, + 0x90,0x09,0x00, 0x9F,0x89,0x1C, 0x97,0xF9,0xDF, 0x9D,0xE9,0xFE, 0x9F,0xE9,0xDE, 0x9D,0xF9,0x7F, + 0x91,0xC9,0xF8, 0x90,0x01,0x00, 0x90,0x09,0x00, 0x9F,0x89,0x1C, 0x97,0xF9,0x8F, 0x9A,0xE9,0xFE, + 0x9F,0xE9,0x8E, 0x9A,0xF9,0x7F, 0x91,0xC9,0xF8, 0x90,0x01,0x00, 0x90,0x09,0xC0, 0x9F,0x89,0xDC, + 0x9D,0xE9,0x7E, 0x91,0xE9,0x1E, 0x91,0xF9,0x3F, 0x93,0xF9,0x3F, 0x97,0xC9,0xF8, 0x90,0x01,0x00, + 0x90,0x09,0xF8, 0x9A,0x89,0xAC, 0x9A,0xA9,0xA9, 0x9E,0xD9,0x39, 0x90,0x19,0x05, 0x90,0x39,0x07, + 0x90,0xE9,0xFC, 0x90,0x01,0x00, 0x9E,0x79,0xA5, 0x9B,0xD9,0xBD, 0x9B,0xD9,0xFD, 0x90,0x79,0x01, + 0x91,0x19,0x09, 0x91,0x19,0x02, 0x9F,0xC9,0x00, 0x90,0x01,0x00, 0x90,0x09,0xF8, 0x9A,0x89,0xAC, + 0x9A,0xA9,0xAD, 0x9E,0xD9,0x39, 0x90,0x19,0x09, 0x90,0xB9,0x07, 0x90,0xE9,0xFC, 0x90,0x01,0x00, + 0x90,0x09,0x00, 0x9F,0x89,0x04, 0x90,0xA9,0x02, 0x9A,0x29,0xA2, 0x9A,0x29,0x02, 0x90,0xA9,0x04, + 0x9F,0x89,0x00, 0x90,0x01,0x00, 0x90,0x09,0x00, 0x90,0x09,0x01, 0x90,0x29,0x04, 0x90,0x49,0x1C, + 0x93,0xC9,0x64, 0x94,0x49,0x62, 0x91,0x19,0x20, 0x94,0x01,0x20, 0x90,0x09,0x00, 0x90,0x09,0x01, + 0x90,0x29,0x24, 0x97,0x49,0x5C, 0x94,0xC9,0x24, 0x92,0x49,0x42, 0x94,0x19,0x30, 0x90,0x01,0x00, + 0x90,0x09,0x00, 0x90,0x09,0x01, 0x94,0x29,0x64, 0x95,0x49,0x6C, 0x97,0xC9,0x74, 0x96,0x49,0x42, + 0x94,0x99,0x30, 0x90,0x01,0x00, 0x90,0x09,0xC0, 0x9A,0x69,0xB9, 0x9A,0x59,0x35, 0x92,0x59,0x05, + 0x90,0x59,0x25, 0x90,0x59,0x19, 0x91,0x29,0x92, 0x96,0xC1,0x00, 0x90,0x09,0x50, 0x96,0xB9,0x44, + 0x90,0xE9,0x12, 0x91,0xA9,0x12, 0x91,0x29,0x12, 0x91,0x89,0x08, 0x94,0x49,0x6B, 0x95,0x01,0x00, + 0x90,0x09,0x00, 0x99,0xC9,0xE2, 0x99,0x29,0x8A, 0x98,0xA9,0x1A, 0x92,0xA9,0xAA, 0x9A,0xA9,0x12, + 0x92,0x49,0x24, 0x9D,0x81,0x00, 0x90,0x09,0x53, 0x96,0xE9,0x52, 0x97,0xA9,0x48, 0x96,0x89,0x48, + 0x94,0x89,0x50, 0x96,0x09,0x60, 0x95,0x09,0x6F, 0x95,0x01,0x00, 0x94,0x09,0xA0, 0x9F,0x89,0x04, + 0x97,0xA9,0xEA, 0x9B,0xF9,0xE9, 0x9B,0xD9,0xEA, 0x97,0xA9,0x02, 0x90,0x49,0xF8, 0x9A,0x01,0x40, + 0x90,0x09,0xC0, 0x9A,0x69,0xB9, 0x9A,0x59,0x25, 0x92,0x59,0x05, 0x91,0x59,0x25, 0x92,0x59,0x09, + 0x91,0x29,0x92, 0x96,0xC1,0x00, 0x90,0x09,0x00, 0x90,0x09,0xFC, 0x94,0x29,0x81, 0x98,0x19,0x81, + 0x98,0x29,0x81, 0x98,0x19,0x81, 0x98,0x19,0x42, 0x9F,0xC1,0x00, 0x90,0x09,0x00, 0x90,0x09,0xC0, + 0x9F,0x09,0xC8, 0x9E,0x49,0x7C, 0x97,0xC9,0xCC, 0x9D,0x89,0xF0, 0x9C,0x09,0x00, 0x90,0x01,0x00, + 0x90,0x09,0x00, 0x90,0x09,0x03, 0x91,0x59,0x19, 0x91,0xB9,0x1E, 0x91,0x69,0x17, 0x91,0xC9,0x16, + 0x90,0x39,0x00, 0x90,0x01,0x00, 0x90,0x09,0x00, 0x98,0x09,0xC0, 0x92,0x09,0x90, 0x9F,0x09,0xF8, + 0x9F,0x89,0xF0, 0x99,0x09,0xA0, 0x9C,0x09,0x80, 0x90,0x01,0x00, 0x90,0x09,0x00, 0x90,0x39,0x15, + 0x91,0x99,0x1B, 0x91,0xF9,0x1C, 0x91,0xC9,0x1F, 0x91,0x39,0x1B, 0x91,0x79,0x03, 0x90,0x01,0x00, + 0x93,0x89,0xA6, 0x91,0x39,0x0F, 0x90,0x39,0xE0, 0x9D,0x09,0x31, 0x93,0x09,0xD0, 0x9E,0x29,0x0F, + 0x91,0x39,0x16, 0x94,0x81,0x01, 0x90,0x09,0x10, 0x90,0x09,0x03, 0x91,0x59,0x19, 0x91,0xB9,0x1F, + 0x91,0x79,0x17, 0x91,0xD9,0x16, 0x90,0x39,0x00, 0x90,0x81,0x00, 0x94,0x19,0x2A, 0x90,0x89,0x36, + 0x90,0x89,0x2A, 0x94,0x19,0x00, 0x90,0x09,0x00, 0x90,0x89,0x14, 0x90,0x89,0x00, 0x90,0x01,0x00, + 0x90,0x09,0x00, 0x92,0x09,0x50, 0x92,0x09,0x00, 0x90,0x09,0x00, 0x90,0x09,0x22, 0x90,0x89,0x14, + 0x90,0x89,0x22, 0x90,0x01,0x00, 0x98,0x09,0x40, 0x9F,0x09,0x08, 0x92,0x49,0x8E, 0x99,0x69,0x06, + 0x92,0x49,0x08, 0x9F,0x09,0x40, 0x94,0x09,0x80, 0x90,0x01,0x00, 0x90,0x79,0x08, 0x90,0x49,0x05, + 0x90,0xE9,0x12, 0x92,0x29,0x22, 0x96,0x29,0x15, 0x93,0xC9,0x04, 0x90,0x89,0x07, 0x90,0x01,0x00, + 0x93,0xE9,0x41, 0x94,0x11,0x3E, 0x90,0x09,0x00, 0x90,0x21,0x7F, 0x96,0x29,0x51, 0x94,0x91,0x46, + 0x94,0x19,0x49, 0x94,0x91,0x36, 0x93,0xC9,0x22, 0x97,0xF1,0x20, 0x94,0xF9,0x49, 0x94,0x91,0x31, + 0x93,0xE9,0x49, 0x94,0x91,0x32, 0x90,0x79,0x01, 0x97,0x11,0x0F, 0x93,0x69,0x49, 0x94,0x91,0x36, + 0x90,0x69,0x49, 0x94,0x91,0x3E, 0x97,0xC9,0x44, 0x17,0xC1,0x00, 0x90,0x09,0x00, 0x17,0xC1,0x00, + 0x97,0x49,0x54, 0x15,0xC1,0x00, 0x95,0x49,0x54, 0x17,0xC1,0x00, 0x91,0xC9,0x10, 0x17,0xC1,0x00, + 0x95,0xC9,0x54, 0x17,0x41,0x00, 0x97,0xC9,0x54, 0x17,0x41,0x00, 0x90,0xC9,0x04, 0x17,0xC1,0x00, + 0x97,0xC9,0x54, 0x17,0xC1,0x00, 0x95,0xC9,0x54, 0x17,0xC1,0x00, 0x97,0xC9,0x38, 0x11,0x01,0x00, + 0x94,0x49,0x28, 0x11,0x01,0x00, 0x06,0x40,0x64, 0x07,0x10,0x7E, 0x08,0xB0,0x98, 0x0A,0x50,0xB2, + 0x0B,0xF0,0xCC, 0x0D,0x90,0x98, 0x9F,0xF9,0xFF, 0x90,0x39,0x04, 0x92,0xD9,0xC0, 0x90,0x59,0x05, + 0x93,0xC9,0xF0, 0x98,0x09,0x11, 0x10,0x09,0x09, 0x91,0x49,0x32, 0x93,0xC9,0xDE, 0x9C,0x39,0x10, + 0x99,0x99,0x64, 0x96,0x59,0x80, 0x91,0x11,0x00, 0x90,0x99,0x15, 0x94,0xB9,0x55, 0x97,0x89,0xC6, + 0x92,0x09,0x99, 0x9A,0xC9,0x68, 0x98,0x09,0x11, 0x10,0x19,0x09, 0x91,0x59,0x4B, 0x95,0x59,0x94, + 0x9C,0x29,0x20, 0x99,0x99,0x64, 0x96,0x59,0x80, 0x91,0x11,0x00, 0x90,0x99,0x16, 0x95,0x19,0x5B, + 0x93,0xC9,0x8F, 0x93,0x09,0x99, 0x9F,0xF9,0xFF, 0x98,0xF9,0x11, 0x10,0x19,0x09, 0x91,0x69,0x51, + 0x95,0xB9,0xF8, 0x98,0xA9,0x30, 0x99,0x99,0x30, 0x97,0xC9,0x88, 0x91,0x11,0x01, 0x90,0xB9,0x17, + 0x93,0x79,0x41, 0x92,0x09,0x8A, 0x93,0x09,0x99, 0x94,0x09,0x7B, 0x9B,0x09,0x23, 0x10,0x19,0x09, + 0x91,0x69,0x3C, 0x94,0x69,0x92, 0x9C,0x49,0x20, 0x99,0x99,0x18, 0x9F,0x69,0x5F, 0x94,0x31,0x01, + 0x90,0x99,0x16, 0x93,0xC9,0x46, 0x96,0x89,0xD1, 0x91,0x09,0x99, 0x90,0xC9,0x73, 0x98,0x89,0x11, + 0x10,0x09,0x0A, 0x91,0x69,0x2D, 0x93,0x29,0x94, 0x9C,0x29,0x20, 0x99,0x99,0xA0, 0x97,0x59,0x80, + 0x91,0x11,0x01, 0x11,0x21,0x01, 0x10,0x21,0x03, 0x10,0x41,0x05, 0x10,0x61,0x07, 0x10,0x81,0x09, + 0x11,0x01,0x11, 0x19,0x21,0x81, 0x18,0x21,0x83, 0x18,0x41,0x85, 0x18,0x61,0x87, 0x18,0x81,0x89, + 0x19,0x01,0x91, 0xFF,0xFF,0xFF, 0x90,0x09,0x00, 0x97,0xC9,0x82, 0x98,0x29,0x7C, 0x90,0x01,0x00, + 0x90,0x09,0x00, 0x90,0x09,0x04, 0x9F,0xE9,0x00, 0x90,0x01,0x00, 0x90,0x09,0x00, 0x9C,0xC9,0xA2, + 0x99,0x29,0x8C, 0x90,0x01,0x00, 0x90,0x09,0x00, 0x94,0x49,0x82, 0x99,0x29,0x6C, 0x90,0x01,0x00, + 0x90,0x09,0x00, 0x93,0xC9,0x22, 0x9F,0xE9,0x20, 0x90,0x01,0x00, 0x90,0x09,0x00, 0x99,0xE9,0x92, + 0x99,0x29,0x62, 0x90,0x01,0x00, 0x90,0x09,0x00, 0x97,0xC9,0x92, 0x99,0x29,0x64, 0x90,0x01,0x00, + 0x90,0x09,0x00, 0x90,0x69,0xE2, 0x91,0x29,0x0E, 0x90,0x01,0x00, 0x90,0x09,0x00, 0x96,0xC9,0x92, + 0x99,0x29,0x6C, 0x90,0x01,0x00, 0x90,0x09,0x00, 0x94,0xC9,0x92, 0x99,0x29,0x7C, 0x90,0x01,0x00, + 0x90,0x09,0xEE, 0x92,0x59,0xC5, 0x92,0x59,0xEF, 0x9E,0xE1,0x00, 0x90,0x09,0xEF, 0x92,0xF9,0xC5, + 0x92,0x59,0xE5, 0x9E,0x21,0x00, 0x90,0x09,0x00, 0x94,0xC9,0x92, 0x99,0x29,0x64, 0x90,0x01,0xFE, + 0x99,0x29,0x92, 0x90,0x09,0x02, 0x9F,0xE9,0x02, 0x90,0x01,0x00, 0x90,0x09,0x3C, 0x94,0x29,0x42, + 0x94,0x29,0x3C, 0x90,0x01,0x7E, 0x90,0x09,0x3E, 0x9C,0x09,0x3E, 0x90,0x09,0xCE, 0x99,0x21,0xE6, + 0x90,0xC9,0xF2, 0x98,0x29,0x82, 0x9F,0x29,0x8E, 0x9F,0x21,0x0C, 0x90,0xC9,0xF2, 0x98,0x49,0x88, + 0x9F,0x89,0x88, 0x9F,0x81,0x00, 0x90,0x09,0xF0, 0x99,0x09,0xA0, 0x9E,0x09,0xA0, 0x9E,0x01,0x00, + 0x90,0x09,0x00, 0x90,0x09,0x00, 0x90,0x09,0x00, 0x90,0x01,0x00, 0x90,0x49,0x06, 0x93,0xF9,0x34, + 0x92,0xC9,0xFC, 0x96,0x01,0x20, 0x90,0x09,0x00, 0x93,0x89,0x30, 0x92,0x89,0xFC, 0x96,0x01,0x20, + 0x90,0x09,0x00, 0x92,0x09,0x30, 0x92,0x09,0xF0, 0x96,0x01,0x20, 0x90,0xA9,0x0A, 0x90,0x29,0x00, + 0x97,0xE9,0x0A, 0x90,0xA1,0x02, 0x90,0x09,0x3C, 0x97,0xA9,0x6E, 0x96,0xE9,0x7A, 0x93,0xC1,0x00, + 0x90,0x09,0x9C, 0x9A,0x09,0x7C, 0x90,0x09,0x7C, 0x90,0x81,0x04, 0x90,0x09,0x86, 0x9F,0x49,0x94, + 0x9D,0xC9,0x94, 0x9F,0x41,0x86, 0x90,0x09,0xFC, 0x98,0x49,0xFC, 0x90,0x09,0xC4, 0x9B,0x41,0x8C, + 0x91,0xC9,0x32, 0x97,0xE9,0xFC, 0x97,0xE9,0x3E, 0x91,0xC1,0x00, 0x91,0xC9,0x22, 0x94,0x29,0x84, + 0x94,0x29,0x22, 0x91,0xC1,0x00, 0x90,0x59,0xC2, 0x9A,0x09,0xF8, 0x9D,0x09,0xE0, 0x9C,0xA1,0x04, + 0x90,0x49,0xCA, 0x9E,0x09,0xF8, 0x9D,0x09,0xA0, 0x9C,0x21,0x05, 0x9F,0xF9,0x3B, 0x95,0xB9,0x6B, + 0x97,0x39,0xFF, 0x9F,0xF1,0xFF, 0x9D,0xF9,0xFF, 0x9E,0xF9,0xFF, 0x9E,0x69,0xEA, 0x9E,0xC1,0xFF, + 0x90,0x09,0x3C, 0x9F,0x69,0x76, 0x9D,0xE9,0x76, 0x9F,0x61,0x3C, 0x90,0x89,0x42, 0x91,0x89,0x25, + 0x9A,0x49,0x18, 0x94,0x21,0x10, 0x90,0x09,0x40, 0x90,0x09,0x0C, 0x90,0xF9,0x1F, 0x91,0xE1,0x06, + 0x90,0x09,0x00, 0x92,0x09,0x18, 0x91,0x89,0x00, 0x90,0x01,0x00, 0x90,0x09,0x10, 0x93,0x89,0x7C, + 0x9F,0xE9,0x38, 0x93,0x81,0x00, 0x90,0x09,0x38, 0x93,0x89,0xFE, 0x97,0xC9,0x38, 0x91,0x01,0x00, + 0x97,0xE9,0x02, 0x93,0xC9,0x02, 0x97,0xE9,0x00, 0x93,0x81,0x54, 0x95,0x49,0x58, 0x90,0x09,0x30, + 0x95,0x49,0x54, 0x93,0xC1,0x40, 0x90,0x09,0x7E, 0x90,0x09,0x00, 0x90,0x09,0x00, 0x90,0x01,0x00, + 0x92,0x69,0x49, 0x94,0x99,0x32, 0x90,0x09,0x7C, 0x90,0x41,0x04, 0x97,0xC9,0x00, 0x93,0x09,0x54, + 0x95,0x49,0x3C, 0x94,0x01,0x38, 0x94,0x49,0x44, 0x92,0x89,0x00, 0x97,0xF9,0x10, 0x96,0x81,0x00, + 0x97,0xF9,0x08, 0x90,0x89,0x7F, 0x90,0x09,0x7C, 0x94,0x01,0x7C, 0x90,0x09,0x7C, 0x90,0x49,0x7C, + 0x90,0x09,0xBC, 0x9A,0x41,0xFC, 0x90,0x09,0x7C, 0x90,0x89,0x04, 0x90,0x09,0x9C, 0x9A,0x01,0x7C, + 0x90,0x09,0x7F, 0x90,0x89,0x08, 0x97,0xF9,0x00, 0x93,0x01,0x54, 0x95,0x49,0x3C, 0x94,0x09,0x00, + 0x9F,0xC9,0x24, 0x93,0xC1,0x00, 0x9F,0xC9,0x24, 0x93,0xC9,0x00, 0x99,0xC9,0xA0, 0x97,0xC1,0x00, + 0x90,0x09,0x7F, 0x94,0x19,0x41, 0x93,0xE9,0x00, 0x97,0x41,0x00, 0x95,0xC9,0x74, 0x90,0x09,0x7C, + 0x94,0x49,0x00, 0x97,0x41,0x00, 0x9F,0xC9,0x24, 0x93,0xC9,0x00, 0x97,0xF9,0x00, 0x97,0x41,0x00, + 0x97,0xC9,0x04, 0x97,0xC9,0x00, 0x97,0xC9,0x54, 0x95,0xC1,0x00, 0x90,0x09,0x3C, 0x94,0x29,0x42, + 0x94,0x29,0x3C, 0x90,0x01,0x00, 0x90,0x09,0x7E, 0x90,0x29,0x0C, 0x93,0x09,0x40, 0x97,0xE1,0x00, + 0x90,0x09,0xC4, 0x9A,0x49,0x94, 0x98,0xC9,0x00, 0x90,0x01,0x00, 0x92,0x09,0x00, 0x91,0x09,0x00, + 0x91,0x99,0x15, 0x91,0x31,0x00, 0x90,0x09,0x00, 0x90,0x09,0x00, 0x90,0x09,0x00, 0x90,0x01,0x00, + 0x90,0x09,0x00, 0x90,0x09,0x00, 0x90,0x09,0x00, 0x90,0x01,0x00, 0x90,0x09,0x00, 0x90,0x09,0x00, + 0x90,0x09,0x00, 0x90,0x01,0x00, 0x90,0x09,0x00, 0x90,0x09,0x00, 0x90,0x09,0x00, 0x90,0x01,0x00, +}; diff --git a/savestate.cpp b/savestate.cpp new file mode 100644 index 0000000..54adf2f --- /dev/null +++ b/savestate.cpp @@ -0,0 +1,96 @@ +#include +#include +#include "cpu.h" +#include "savestate.h" +#include "hardcoded_state.h" + +void initEEPROM() +{ +#if defined(ESP8266) || defined(ESP32) + EEPROM.begin(1 + sizeof(cpu_state_t) + MEMORY_SIZE); +#endif +} + +bool validEEPROM() +{ + return EEPROM.read(0) == EEPROM_MAGIC_NUMBER; +} + +void loadStateFromEEPROM(cpu_state_t* cpuState) +{ + cpu_get_state(cpuState); + u4_t *memTemp = cpuState->memory; + EEPROM.get(1, *cpuState); + cpu_set_state(cpuState); + uint32_t i = 0; + for (i = 0; i < MEMORY_SIZE; i++) + { + memTemp[i] = EEPROM.read(1 + sizeof(cpu_state_t) + i); + } +#ifdef ENABLE_DUMP_STATE_TO_SERIAL_WHEN_START + Serial.print(F("Loaded ")); + Serial.print(1 + sizeof(cpu_state_t) + MEMORY_SIZE); + Serial.println(F(" bytes")); +#endif +} + +void eraseStateFromEEPROM() { + for (uint32_t i = 0; i < EEPROM.length(); i++) + EEPROM.write(i, 0); +#if defined(ESP8266) || defined(ESP32) + EEPROM.commit(); +#endif +} + +void saveStateToEEPROM(cpu_state_t* cpuState) +{ + uint32_t i = 0; + if (EEPROM.read(0) != EEPROM_MAGIC_NUMBER) + eraseStateFromEEPROM(); + +#if defined(ESP8266) || defined(ESP32) + EEPROM.write(0, EEPROM_MAGIC_NUMBER); +#else + EEPROM.update(0, EEPROM_MAGIC_NUMBER); +#endif + + cpu_get_state(cpuState); + EEPROM.put(1, *cpuState); + for (i = 0; i < MEMORY_SIZE; i++) + { +#if defined(ESP8266) || defined(ESP32) + EEPROM.write(1 + sizeof(cpu_state_t) + i, cpuState->memory[i]); +#else + EEPROM.update(1 + sizeof(cpu_state_t) + i, cpuState->memory[i]); +#endif + } + +#if defined(ESP8266) || defined(ESP32) + EEPROM.commit(); +#endif + +#ifdef ENABLE_DUMP_STATE_TO_SERIAL_WHEN_START + Serial.print(F("Saved ")); + Serial.print(1 + sizeof(cpu_state_t) + MEMORY_SIZE); + Serial.println(F(" bytes")); +#endif +} + +void loadHardcodedState(cpu_state_t* cpuState) +{ + cpu_get_state(cpuState); + u4_t *memTemp = cpuState->memory; + uint16_t i; + uint8_t *cpuS = (uint8_t *)cpuState; + for (i = 0; i < sizeof(cpu_state_t); i++) + { + cpuS[i] = pgm_read_byte_near(hardcodedState + i); + } + for (i = 0; i < MEMORY_SIZE; i++) + { + memTemp[i] = pgm_read_byte_near(hardcodedState + sizeof(cpu_state_t) + i); + } + cpuState->memory = memTemp; + cpu_set_state(cpuState); + Serial.println("Hardcoded"); +} diff --git a/savestate.h b/savestate.h new file mode 100644 index 0000000..2e46d81 --- /dev/null +++ b/savestate.h @@ -0,0 +1,15 @@ +#pragma once + +#define EEPROM_MAGIC_NUMBER 0x12 + +void initEEPROM(); + +bool validEEPROM(); + +void loadStateFromEEPROM(cpu_state_t* cpuState); + +void eraseStateFromEEPROM(); + +void saveStateToEEPROM(cpu_state_t* cpuState); + +void loadHardcodedState(cpu_state_t* cpuState); diff --git a/tamalib.c b/tamalib.c new file mode 100644 index 0000000..00dbde5 --- /dev/null +++ b/tamalib.c @@ -0,0 +1,171 @@ +/* + * TamaLIB - A hardware agnostic Tamagotchi P1 emulation library + * + * Copyright (C) 2021 Jean-Christophe Rona + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include "tamalib.h" +#include "hw.h" +#include "cpu.h" +#include "hal.h" + +#define DEFAULT_FRAMERATE 6// fps + +static exec_mode_t exec_mode = EXEC_MODE_RUN; + +static u32_t step_depth = 0; + +static timestamp_t screen_ts = 0; + +static u32_t ts_freq; + +static u8_t g_framerate = DEFAULT_FRAMERATE; + +hal_t *g_hal; + + +bool_t tamalib_init(u32_t freq) +//bool_t tamalib_init(breakpoint_t *breakpoints, u32_t freq) +{ + bool_t res = 0; + res |= cpu_init( freq); + +// res |= cpu_init(program, breakpoints, freq); + res |= hw_init(); + + ts_freq = freq; + + return res; +} + +/* +void tamalib_release(void) +{ + hw_release(); + cpu_release(); +}*/ + + +void tamalib_set_framerate(u8_t framerate) +{ + g_framerate = framerate; +} +/* +u8_t tamalib_get_framerate(void) +{ + + //return g_framerate; + return DEFAULT_FRAMERATE; +} +*/ +void tamalib_register_hal(hal_t *hal) +{ + g_hal = hal; +} +/* +void tamalib_set_exec_mode(exec_mode_t mode) +{ + exec_mode = mode; + step_depth = cpu_get_depth(); + cpu_sync_ref_timestamp(); +} +*/ + +/* +void tamalib_step(void) +{ + if (exec_mode == EXEC_MODE_PAUSE) { + return; + } + + if (cpu_step()) { + exec_mode = EXEC_MODE_PAUSE; + step_depth = cpu_get_depth(); + } else { + switch (exec_mode) { + case EXEC_MODE_PAUSE: + case EXEC_MODE_RUN: + break; + + case EXEC_MODE_STEP: + exec_mode = EXEC_MODE_PAUSE; + break; + + case EXEC_MODE_NEXT: + if (cpu_get_depth() <= step_depth) { + exec_mode = EXEC_MODE_PAUSE; + step_depth = cpu_get_depth(); + } + break; + + case EXEC_MODE_TO_CALL: + if (cpu_get_depth() > step_depth) { + exec_mode = EXEC_MODE_PAUSE; + step_depth = cpu_get_depth(); + } + break; + + case EXEC_MODE_TO_RET: + if (cpu_get_depth() < step_depth) { + exec_mode = EXEC_MODE_PAUSE; + step_depth = cpu_get_depth(); + } + break; + } + } +} +*/ +/* +void tamalib_mainloop(void) +{ + timestamp_t ts; + + while (!g_hal->handler()) { + tamalib_step(); + + ts = g_hal->get_timestamp(); + if (ts - screen_ts >= ts_freq/g_framerate) { + screen_ts = ts; + g_hal->update_screen(); + } + } +} */ + +void tamalib_mainloop_step_by_step(void) +{ + timestamp_t ts; + + if (!g_hal->handler()) { + //tamalib_step(); + + if (exec_mode == EXEC_MODE_RUN) { + if (cpu_step()) { + exec_mode = EXEC_MODE_PAUSE; + step_depth = cpu_get_depth(); + } + } + + + /* Update the screen @ g_framerate fps */ + ts = g_hal->get_timestamp(); + + if (ts - screen_ts >= ts_freq/g_framerate) { + //if (ts - screen_ts >= ts_freq/DEFAULT_FRAMERATE) { + screen_ts = ts; + g_hal->update_screen(); + } + } +} diff --git a/tamalib.h b/tamalib.h new file mode 100644 index 0000000..76d659f --- /dev/null +++ b/tamalib.h @@ -0,0 +1,76 @@ +/* + * TamaLIB - A hardware agnostic Tamagotchi P1 emulation library + * + * Copyright (C) 2021 Jean-Christophe Rona + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#ifndef _TAMALIB_H_ +#define _TAMALIB_H_ + +#include "cpu.h" +#include "hw.h" +#include "hal.h" + +#define tamalib_set_button(btn, state) hw_set_button(btn, state) + +#define tamalib_set_speed(speed) cpu_set_speed(speed) + +//#define tamalib_get_state() cpu_get_state() +#define tamalib_refresh_hw() cpu_refresh_hw() + +#define tamalib_reset() cpu_reset() + +//#define tamalib_add_bp(list, addr) cpu_add_bp(list, addr) +//#define tamalib_free_bp(list) cpu_free_bp(list) + +typedef enum { + EXEC_MODE_PAUSE, + EXEC_MODE_RUN, + EXEC_MODE_STEP, + EXEC_MODE_NEXT, + EXEC_MODE_TO_CALL, + EXEC_MODE_TO_RET, +} exec_mode_t; + + +#ifdef __cplusplus + extern "C" { +#endif + +//void tamalib_release(void); +bool_t tamalib_init(u32_t freq); +//bool_t tamalib_init( breakpoint_t *breakpoints, u32_t freq); + + +void tamalib_set_framerate(u8_t framerate); +//u8_t tamalib_get_framerate(void); + +void tamalib_register_hal(hal_t *hal); + +//void tamalib_set_exec_mode(exec_mode_t mode); + +/* NOTE: Only one of these two functions must be used in the main application + * (tamalib_step() should be used only if tamalib_mainloop() does not fit the + * main application execution flow). + */ +//void tamalib_step(void); +//void tamalib_mainloop(void); +void tamalib_mainloop_step_by_step(void); +#ifdef __cplusplus +} +#endif + +#endif /* _TAMALIB_H_ */