├── LICENSE ├── Makefile ├── README.md ├── cpuvariant ├── generic.c ├── pmx150.c ├── pmx154.c └── pmx173.c ├── depdk.c ├── disass ├── disass13.c ├── disass14.c ├── disass15.c └── disass16.c ├── dispdk.c ├── emucpu └── emucpu.c ├── emupdk.c ├── ihex └── fpdkihex8.c ├── include ├── cpuvariant.h ├── disass.h ├── emucpu.h ├── fpdkihex8.h ├── opcode.h └── pdkformat.h ├── opcode ├── opcode13.c ├── opcode14.c ├── opcode15.c └── opcode16.c └── pdkformat └── pdkformat.c /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 free-pdk 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC ?= gcc 2 | RM ?= rm -rf 3 | STRIP ?= strip 4 | 5 | ifeq ($(OS),Windows_NT) 6 | EXE_EXTENSION := .exe 7 | endif 8 | 9 | CFLAGS += -Wall -O2 -std=c99 -Iinclude 10 | 11 | DEP_CORE= $(wildcard include/*.h) 12 | 13 | SRC_CORE= pdkformat/pdkformat.c ihex/fpdkihex8.c 14 | SRC_CORE+= emucpu/emucpu.c 15 | SRC_CORE+= opcode/opcode13.c opcode/opcode14.c opcode/opcode15.c opcode/opcode16.c 16 | SRC_CORE+= disass/disass13.c disass/disass14.c disass/disass15.c disass/disass16.c 17 | SRC_CORE+= cpuvariant/generic.c cpuvariant/pmx150.c cpuvariant/pmx154.c cpuvariant/pmx173.c 18 | OBJ_CORE= $(subst .c,.o,$(SRC_CORE)) 19 | 20 | all: depdk dispdk emupdk 21 | 22 | depdk: $(DEP_CORE) $(OBJ_CORE) depdk.c 23 | $(CC) $(CFLAGS) $(LDFLAGS) -o depdk depdk.c pdkformat/pdkformat.o $(LIBS) 24 | $(STRIP) depdk$(EXE_EXTENSION) 25 | 26 | dispdk: $(DEP_CORE) $(OBJ_CORE) dispdk.c 27 | $(CC) $(CFLAGS) $(LDFLAGS) -o dispdk dispdk.c $(OBJ_CORE) $(LIBS) 28 | $(STRIP) dispdk$(EXE_EXTENSION) 29 | 30 | emupdk: $(DEP_CORE) $(OBJ_CORE) emupdk.c 31 | $(CC) $(CFLAGS) $(LDFLAGS) -o emupdk emupdk.c $(OBJ_CORE) $(LIBS) 32 | $(STRIP) emupdk$(EXE_EXTENSION) 33 | 34 | clean: 35 | $(RM) $(OBJ_CORE) 36 | $(RM) depdk$(EXE_EXTENSION) 37 | $(RM) dispdk$(EXE_EXTENSION) 38 | $(RM) emupdk$(EXE_EXTENSION) 39 | 40 | dist-clean: clean 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # fppa-pdk-tools 2 | 3 | 4 | Disassembler: dispdk 5 | supports 13 bit, 14 bit, 15 bit and 16 bit opcodes 6 | 7 | Emulator: emupdk 8 | supports 14 bit opcodes, no peripheral support yet 9 | requires mapping of processor ID in emucpu.c 10 | 11 | PDK converter: depdk 12 | convert/deobfuscate any PDK file to binary 13 | 14 | 15 | Documentation of instructionsets available here: 16 | https://free-pdk.github.io/ 17 | -------------------------------------------------------------------------------- /cpuvariant/generic.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "cpuvariant.h" 4 | #include "emucpu.h" 5 | #include "opcode.h" 6 | #include "disass.h" 7 | 8 | void generic_reset(struct emuCPU *cpu, bool clearRAM) 9 | { 10 | } 11 | 12 | char* generic_ioname(struct emuCPU *cpu, uint8_t io, uint8_t bit, char* buffer) 13 | { 14 | strcpy(buffer,"?"); 15 | return buffer; 16 | } 17 | 18 | void generic_peripherals(struct emuCPU *cpu) 19 | { 20 | } 21 | 22 | int generic_init(struct emuCPU *cpu) 23 | { 24 | cpu->fnReset = generic_reset; 25 | cpu->fnPeripherals = generic_peripherals; 26 | cpu->fnIOName = generic_ioname; 27 | 28 | switch( cpu->hdr.codesize ) 29 | { 30 | case 1024: 31 | cpu->maxIO = 32; 32 | cpu->maxMem = 60; 33 | cpu->maxCode = 1024; 34 | cpu->fnExecute = opcode13; 35 | cpu->fnDisassemble = disass13; 36 | break; 37 | 38 | case 2048: 39 | cpu->maxIO = 32; 40 | cpu->maxMem = 128; 41 | cpu->maxCode = 2048; 42 | cpu->fnExecute = opcode14; 43 | cpu->fnDisassemble = disass14; 44 | break; 45 | 46 | case 4096: 47 | cpu->maxIO = 64; 48 | cpu->maxMem = 256; 49 | cpu->maxCode = 4096; 50 | cpu->fnExecute = opcode15; 51 | cpu->fnDisassemble = disass15; 52 | break; 53 | 54 | case 8192: 55 | cpu->maxIO = 32; 56 | cpu->maxMem = 512; 57 | cpu->maxCode = 8192; 58 | cpu->fnExecute = opcode16; 59 | cpu->fnDisassemble = disass16; 60 | break; 61 | 62 | default: 63 | return -1; 64 | } 65 | return 0; 66 | } 67 | 68 | -------------------------------------------------------------------------------- /cpuvariant/pmx150.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "cpuvariant.h" 4 | #include "emucpu.h" 5 | #include "opcode.h" 6 | #include "disass.h" 7 | 8 | void pmx150_reset(struct emuCPU *cpu, bool clearRAM) 9 | { 10 | if( clearRAM ) 11 | memset( cpu->eMem, 0x55, cpu->maxMem ); 12 | 13 | memset( cpu->eIO, 0xFF, cpu->maxIO ); 14 | 15 | //setup default IO 16 | cpu->eIO[0x03] = 0xF4; 17 | cpu->eIO[0x0D] = 0xFF; 18 | cpu->eIO[0x0E] = 0xFF; 19 | 20 | ePC = 0; 21 | eA = 0; //??? 22 | eGINTEnabled = false; 23 | eInterruptActive = false; 24 | eCycle = 0; 25 | eT16 = 0; //??? 26 | } 27 | 28 | char* pmx150_ioname(struct emuCPU *cpu, uint8_t io, uint8_t bit, char* buffer) 29 | { 30 | char* r=0; 31 | switch( io ) 32 | { 33 | case 0x00: 34 | switch( bit ) 35 | { 36 | case 0: r="FLAG.ZF"; break; 37 | case 1: r="FLAG.CF"; break; 38 | case 2: r="FLAG.AC"; break; 39 | case 3: r="FLAG.OV"; break; 40 | default: r="FLAG"; 41 | } 42 | break; 43 | 44 | case 0x02: r="SP"; break; 45 | 46 | case 0x03: 47 | switch( bit ) 48 | { 49 | case 0: r="CLKMD.PA5 / PRST"; break; 50 | case 1: r="CLKMD.WD ENABLE"; break; 51 | case 2: r="CLKMD.ILRC ENABLE"; break; 52 | case 3: r="CLKMD.CLKTYPE"; break; 53 | case 4: r="CLKMD.IHRC ENABLE"; break; 54 | case 5: 55 | case 6: 56 | case 7: r="CLKMD.CLKSELECT"; break; 57 | default: r="CLKMD"; 58 | } 59 | break; 60 | 61 | case 0x04: 62 | switch( bit ) 63 | { 64 | case 0: r="INTEN PA0"; break; 65 | case 2: r="INTEN T16"; break; 66 | default: r="INTEN"; 67 | } 68 | break; 69 | 70 | case 0x05: 71 | switch( bit ) 72 | { 73 | case 0: r="INTRQ PA0"; break; 74 | case 2: r="INTRQ T16"; break; 75 | default: r="INTRQ"; 76 | } 77 | break; 78 | 79 | case 0x06: r="T16M"; break; 80 | 81 | case 0x09: r="TM2B"; break; 82 | case 0x0A: r="EOSCR"; break; 83 | case 0x0B: r="IHRCR"; break; 84 | case 0x0C: r="INTEGS"; break; 85 | case 0x0D: if(bit<8) sprintf(buffer,"PADIER.%d",bit); else r="PADIER"; break; 86 | 87 | case 0x10: if(bit<8) sprintf(buffer,"PA.%d",bit); else r="PA"; break; 88 | case 0x11: if(bit<8) sprintf(buffer,"PAC.%d",bit); else r="PAC"; break; 89 | case 0x12: if(bit<8) sprintf(buffer,"PAPH.%d",bit); else r="PAPH"; break; 90 | 91 | case 0x17: r="TM2S"; break; 92 | 93 | case 0x19: r="BGTR"; break; 94 | case 0x1A: r="GPCC"; break; 95 | case 0x1B: r="MISC"; break; 96 | case 0x1C: r="TM2C"; break; 97 | case 0x1D: r="TM2CT"; break; 98 | case 0x1E: r="GPCS"; break; 99 | case 0x1F: r="ILRCR"; break; 100 | 101 | default: 102 | r="?"; 103 | } 104 | 105 | if( r ) 106 | strcpy(buffer,r); 107 | 108 | return buffer; 109 | } 110 | 111 | void pmx150_peripherals(struct emuCPU *cpu) 112 | { 113 | //TODO: INTERRUPT EMU (PC=>[SP];SP+=2;} 114 | //TODO: TIMER EMU 115 | //TODO: WDCOUNTER, ... 116 | //TODO: PWM EMU 117 | //TODO: CLK EMU 118 | //TODO: PA / PB EMU 119 | //TODO: IO 0x3F ==> virtual putchar for easy emu 120 | } 121 | 122 | void pmx150_init(struct emuCPU *cpu, bool fixupHighCode) 123 | { 124 | cpu->maxIO = 32; 125 | cpu->maxMem = 60; 126 | cpu->maxCode = 1024; 127 | 128 | cpu->fnReset = pmx150_reset; 129 | cpu->fnExecute = opcode13; 130 | cpu->fnDisassemble = disass13; 131 | cpu->fnPeripherals = pmx150_peripherals; 132 | cpu->fnIOName = pmx150_ioname; 133 | 134 | if( fixupHighCode ) 135 | { 136 | //fixups, seems like writer is doing this... init stuff / rolling code / calibration data / ??? 137 | cpu->eCode[0x03F6] = 0x0100; //RET 0 138 | cpu->eCode[0x03ED] = 0x0100; //RET 0 139 | cpu->eCode[0x03EE] = 0x0100; //RET 0 140 | cpu->eCode[0x03FE] = 0x0100; //RET 0xXY - calibration code is NOT executed / RET 0xFF - calibration code is executed 141 | } 142 | 143 | pmx150_reset(cpu, true); 144 | } 145 | 146 | -------------------------------------------------------------------------------- /cpuvariant/pmx154.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "cpuvariant.h" 4 | #include "emucpu.h" 5 | #include "opcode.h" 6 | #include "disass.h" 7 | 8 | void pmx154_reset(struct emuCPU *cpu, bool clearRAM) 9 | { 10 | if( clearRAM ) 11 | memset( cpu->eMem, 0x55, cpu->maxMem ); 12 | 13 | memset( cpu->eIO, 0xFF, cpu->maxIO ); 14 | 15 | //setup default IO 16 | cpu->eIO[0x03] = 0xF4; 17 | cpu->eIO[0x0D] = 0xFF; 18 | cpu->eIO[0x0E] = 0xFF; 19 | 20 | ePC = 0; 21 | eA = 0; //??? 22 | eGINTEnabled = false; 23 | eInterruptActive = false; 24 | eCycle = 0; 25 | eT16 = 0; //??? 26 | } 27 | 28 | char* pmx154_ioname(struct emuCPU *cpu, uint8_t io, uint8_t bit, char* buffer) 29 | { 30 | char* r=0; 31 | switch( io ) 32 | { 33 | case 0x00: 34 | switch( bit ) 35 | { 36 | case 0: r="FLAG.ZF"; break; 37 | case 1: r="FLAG.CF"; break; 38 | case 2: r="FLAG.AC"; break; 39 | case 3: r="FLAG.OV"; break; 40 | default: r="FLAG"; 41 | } 42 | break; 43 | 44 | case 0x02: r="SP"; break; 45 | 46 | case 0x03: 47 | switch( bit ) 48 | { 49 | case 0: r="CLKMD.PA5 / PRST"; break; 50 | case 1: r="CLKMD.WD ENABLE"; break; 51 | case 2: r="CLKMD.ILRC ENABLE"; break; 52 | case 3: r="CLKMD.CLKTYPE"; break; 53 | case 4: r="CLKMD.IHRC ENABLE"; break; 54 | case 5: 55 | case 6: 56 | case 7: r="CLKMD.CLKSELECT"; break; 57 | default: r="CLKMD"; 58 | } 59 | break; 60 | 61 | case 0x04: 62 | switch( bit ) 63 | { 64 | case 0: r="INTEN PA0"; break; 65 | case 1: r="INTEN PB0"; break; 66 | case 2: r="INTEN T16"; break; 67 | default: r="INTEN"; 68 | } 69 | break; 70 | 71 | case 0x05: 72 | switch( bit ) 73 | { 74 | case 0: r="INTRQ PA0"; break; 75 | case 1: r="INTRQ PB0"; break; 76 | case 2: r="INTRQ T16"; break; 77 | default: r="INTRQ"; 78 | } 79 | break; 80 | 81 | case 0x06: r="T16M"; break; 82 | 83 | case 0x08: r="MISC"; break; 84 | case 0x09: r="TM2B"; break; 85 | case 0x0A: r="EOSCR"; break; 86 | case 0x0B: r="IHRCR"; break; 87 | case 0x0C: r="INTEGS"; break; 88 | case 0x0D: if(bit<8) sprintf(buffer,"PADIER.%d",bit); else r="PADIER"; break; 89 | case 0x0E: if(bit<8) sprintf(buffer,"PBDIER.%d",bit); else r="PBDIER"; break; 90 | case 0x0F: r="MISC2"; break; 91 | case 0x10: if(bit<8) sprintf(buffer,"PA.%d",bit); else r="PA"; break; 92 | case 0x11: if(bit<8) sprintf(buffer,"PAC.%d",bit); else r="PAC"; break; 93 | case 0x12: if(bit<8) sprintf(buffer,"PAPH.%d",bit); else r="PAPH"; break; 94 | 95 | case 0x14: if(bit<8) sprintf(buffer,"PB.%d",bit); else r="PB"; break; 96 | case 0x15: if(bit<8) sprintf(buffer,"PBC.%d",bit); else r="PBC"; break; 97 | case 0x16: if(bit<8) sprintf(buffer,"PBPH.%d",bit); else r="PBPH"; break; 98 | case 0x17: r="TM2S"; break; 99 | case 0x18: r="GPCC"; break; 100 | case 0x19: r="GPCS"; break; 101 | case 0x1A: r="BGTR"; break; 102 | case 0x1B: r="MISC_LVR"; break; 103 | case 0x1C: r="TM2C"; break; 104 | case 0x1D: r="TM2CT"; break; 105 | 106 | case 0x20: r="PWMG0C"; break; 107 | case 0x21: r="PWMG0S"; break; 108 | case 0x22: r="PWMG0DTH"; break; 109 | case 0x23: r="PWMG0DTL"; break; 110 | case 0x24: r="PWMG0CUBH"; break; 111 | case 0x25: r="PWMG0CUBL"; break; 112 | case 0x26: r="PWMG1C"; break; 113 | case 0x27: r="PWMG1S"; break; 114 | case 0x28: r="PWMG1DTH"; break; 115 | case 0x29: r="PWMG1DTL"; break; 116 | case 0x2A: r="PWMG1CUBH"; break; 117 | case 0x2B: r="PWMG1CUBL"; break; 118 | case 0x2C: r="PWMG2C"; break; 119 | case 0x2D: r="PWMG2S"; break; 120 | case 0x2E: r="PWMG2DTH"; break; 121 | case 0x2F: r="PWMG2DTL"; break; 122 | case 0x30: r="PWMG2CUBH"; break; 123 | case 0x31: r="PWMG2CUBL"; break; 124 | case 0x32: r="TM3C"; break; 125 | case 0x33: r="TM3CT"; break; 126 | case 0x34: r="TM3S"; break; 127 | case 0x35: r="TM3B"; break; 128 | 129 | case 0x39: r="ILRCR"; break; 130 | 131 | default: 132 | r="?"; 133 | } 134 | 135 | if( r ) 136 | strcpy(buffer,r); 137 | 138 | return buffer; 139 | } 140 | 141 | void pmx154_peripherals(struct emuCPU *cpu) 142 | { 143 | //TODO: INTERRUPT EMU (PC=>[SP];SP+=2;} 144 | //TODO: TIMER EMU 145 | //TODO: WDCOUNTER, ... 146 | //TODO: PWM EMU 147 | //TODO: CLK EMU 148 | //TODO: PA / PB EMU 149 | //TODO: IO 0x3F ==> virtual putchar for easy emu 150 | } 151 | 152 | void pmx154_init(struct emuCPU *cpu, bool fixupHighCode) 153 | { 154 | cpu->maxIO = 64; 155 | cpu->maxMem = 128; 156 | cpu->maxCode = 2048; 157 | 158 | cpu->fnReset = pmx154_reset; 159 | cpu->fnExecute = opcode14; 160 | cpu->fnDisassemble = disass14; 161 | cpu->fnPeripherals = pmx154_peripherals; 162 | cpu->fnIOName = pmx154_ioname; 163 | 164 | if( fixupHighCode ) 165 | { 166 | //fixups, seems like writer is doing this... init stuff / rolling code / calibration data / ??? 167 | cpu->eCode[0x07F6] = 0x0200; //RET 0 168 | cpu->eCode[0x07FE] = 0x0200; //RET 0xXY - calibration code is NOT executed / RET 0xFF - calibration code is executed 169 | } 170 | cpu->eCode[0x07ED] = 0x0283; //IHRCR factory calibration 171 | cpu->eCode[0x07EE] = 0x024a; //BGTR factory calibration 172 | 173 | pmx154_reset(cpu, true); 174 | } 175 | -------------------------------------------------------------------------------- /cpuvariant/pmx173.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "cpuvariant.h" 4 | #include "emucpu.h" 5 | #include "opcode.h" 6 | #include "disass.h" 7 | 8 | void pmx173_reset(struct emuCPU *cpu, bool clearRAM) 9 | { 10 | if( clearRAM ) 11 | memset( cpu->eMem, 0x55, cpu->maxMem ); 12 | 13 | memset( cpu->eIO, 0xFF, cpu->maxIO ); 14 | 15 | //setup default IO 16 | cpu->eIO[0x03] = 0xF4; 17 | cpu->eIO[0x0D] = 0xFF; 18 | cpu->eIO[0x0E] = 0xFF; 19 | 20 | ePC = 0; 21 | eA = 0; //??? 22 | eGINTEnabled = false; 23 | eInterruptActive = false; 24 | eCycle = 0; 25 | eT16 = 0; //??? 26 | } 27 | 28 | char* pmx173_ioname(struct emuCPU *cpu, uint8_t io, uint8_t bit, char* buffer) 29 | { 30 | char* r=0; 31 | switch( io ) 32 | { 33 | case 0x00: 34 | switch( bit ) 35 | { 36 | case 0: r="FLAG.ZF"; break; 37 | case 1: r="FLAG.CF"; break; 38 | case 2: r="FLAG.AC"; break; 39 | case 3: r="FLAG.OV"; break; 40 | default: r="FLAG"; 41 | } 42 | break; 43 | 44 | case 0x02: r="SP"; break; 45 | 46 | case 0x03: 47 | switch( bit ) 48 | { 49 | case 0: r="CLKMD.PA5 / PRST"; break; 50 | case 1: r="CLKMD.WD ENABLE"; break; 51 | case 2: r="CLKMD.ILRC ENABLE"; break; 52 | case 3: r="CLKMD.CLKTYPE"; break; 53 | case 4: r="CLKMD.IHRC ENABLE"; break; 54 | case 5: 55 | case 6: 56 | case 7: r="CLKMD.CLKSELECT"; break; 57 | default: r="CLKMD"; 58 | } 59 | break; 60 | 61 | case 0x04: 62 | switch( bit ) 63 | { 64 | case 0: r="INTEN PA0/PB5"; break; 65 | case 1: r="INTEN PB0/PA4"; break; 66 | case 2: r="INTEN T16"; break; 67 | case 3: r="INTEN ADC"; break; 68 | case 4: r="INTEN COMP"; break; 69 | case 5: r="INTEN PWMG"; break; 70 | case 6: r="INTEN TM2"; break; 71 | case 7: r="INTEN TM3"; break; 72 | default: r="INTEN"; 73 | } 74 | break; 75 | 76 | case 0x05: 77 | switch( bit ) 78 | { 79 | case 0: r="INTRQ PA0/PB5"; break; 80 | case 1: r="INTRQ PB0/PA4"; break; 81 | case 2: r="INTRQ T16"; break; 82 | case 3: r="INTRQ ADC"; break; 83 | case 4: r="INTRQ COMP"; break; 84 | case 5: r="INTRQ PWMG"; break; 85 | case 6: r="INTRQ TM2"; break; 86 | case 7: r="INTRQ TM3"; break; 87 | default: r="INTRQ"; 88 | } 89 | break; 90 | 91 | case 0x06: r="T16M"; break; 92 | 93 | case 0x0A: r="EOSCR"; break; 94 | case 0x0B: r="IHRCR"; break; 95 | case 0x0C: r="INTEGS"; break; 96 | case 0x0D: if(bit<8) sprintf(buffer,"PADIER.%d",bit); else r="PADIER"; break; 97 | case 0x0E: if(bit<8) sprintf(buffer,"PBDIER.%d",bit); else r="PBDIER"; break; 98 | case 0x0F: if(bit<8) sprintf(buffer,"PCDIER.%d",bit); else r="PCDIER"; break; 99 | case 0x10: if(bit<8) sprintf(buffer,"PA.%d",bit); else r="PA"; break; 100 | case 0x11: if(bit<8) sprintf(buffer,"PAC.%d",bit); else r="PAC"; break; 101 | case 0x12: if(bit<8) sprintf(buffer,"PAPH.%d",bit); else r="PAPH"; break; 102 | case 0x13: if(bit<8) sprintf(buffer,"PB.%d",bit); else r="PB"; break; 103 | case 0x14: if(bit<8) sprintf(buffer,"PBC.%d",bit); else r="PBC"; break; 104 | case 0x15: if(bit<8) sprintf(buffer,"PBPH.%d",bit); else r="PBPH"; break; 105 | case 0x16: if(bit<8) sprintf(buffer,"PC.%d",bit); else r="PC"; break; 106 | case 0x17: if(bit<8) sprintf(buffer,"PCC.%d",bit); else r="PCC"; break; 107 | case 0x18: if(bit<8) sprintf(buffer,"PCPH.%d",bit); else r="PCPH"; break; 108 | case 0x19: if(bit<8) sprintf(buffer,"PBPL.%d",bit); else r="PBPL"; break; 109 | case 0x1A: if(bit<8) sprintf(buffer,"PCPL.%d",bit); else r="PCPL"; break; 110 | 111 | case 0x20: r="ADCC"; break; 112 | case 0x21: r="ADCM"; break; 113 | case 0x22: r="ADCR"; break; 114 | 115 | case 0x24: r="ADCRGC"; break; 116 | 117 | case 0x26: r="MISC"; break; 118 | case 0x27: r="MISC2"; break; 119 | case 0x28: r="MISCLVR"; break; 120 | 121 | case 0x2B: r="GPCC"; break; 122 | case 0x2C: r="GPCS"; break; 123 | 124 | case 0x30: r="TM2C"; break; 125 | case 0x31: r="TM2CT"; break; 126 | case 0x32: r="TM2S"; break; 127 | case 0x33: r="TM2B"; break; 128 | case 0x34: r="TM3C"; break; 129 | case 0x35: r="TM3CT"; break; 130 | case 0x36: r="TM3S"; break; 131 | case 0x37: r="TM3B"; break; 132 | 133 | case 0x40: r="PWMG0C"; break; 134 | case 0x41: r="PWMGCLK"; break; 135 | case 0x42: r="PWMG0DTH"; break; 136 | case 0x43: r="PWMG0DTL"; break; 137 | case 0x44: r="PWMG0CUBH"; break; 138 | case 0x45: r="PWMG0CUBL"; break; 139 | case 0x46: r="PWMG1C"; break; 140 | 141 | case 0x48: r="PWMG1DTH"; break; 142 | case 0x49: r="PWMG1DTL"; break; 143 | 144 | case 0x4C: r="PWMG2C"; break; 145 | 146 | case 0x4E: r="PWMG2DTH"; break; 147 | case 0x4F: r="PWMG2DTL"; break; 148 | 149 | case 0x62: r="ILRCR"; break; 150 | case 0x63: r="BGTR"; break; 151 | 152 | case 0x67: r="ROP"; break; 153 | 154 | default: 155 | r="?"; 156 | } 157 | 158 | if( r ) 159 | strcpy(buffer,r); 160 | 161 | return buffer; 162 | } 163 | 164 | void pmx173_peripherals(struct emuCPU *cpu) 165 | { 166 | //TODO: INTERRUPT EMU (PC=>[SP];SP+=2;} 167 | //TODO: TIMER EMU 168 | //TODO: WDCOUNTER, ... 169 | //TODO: PWM EMU 170 | //TODO: CLK EMU 171 | //TODO: PA / PB EMU 172 | //TODO: IO 0x3F ==> virtual putchar for easy emu 173 | } 174 | 175 | void pmx173_init(struct emuCPU *cpu, bool fixupHighCode) 176 | { 177 | cpu->maxIO = 64; 178 | cpu->maxMem = 256; 179 | cpu->maxCode = 3096; 180 | 181 | cpu->fnReset = pmx173_reset; 182 | cpu->fnExecute = opcode15; 183 | cpu->fnDisassemble = disass15; 184 | cpu->fnPeripherals = pmx173_peripherals; 185 | cpu->fnIOName = pmx173_ioname; 186 | 187 | if( fixupHighCode ) 188 | { 189 | //fixups, seems like writer is doing this... init stuff / rolling code / calibration data / ??? 190 | cpu->eCode[0x0BF6] = 0x0200; //RET 0 191 | cpu->eCode[0x0BFE] = 0x0200; //RET 0xXY - calibration code is NOT executed / RET 0xFF - calibration code is executed 192 | } 193 | 194 | cpu->eCode[0x0BED] = 0x027F; //IHRCR factory calibration 195 | cpu->eCode[0x0BEE] = 0x026A; //BGTR factory calibration 196 | 197 | pmx173_reset(cpu, true); 198 | } 199 | -------------------------------------------------------------------------------- /depdk.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "pdkformat.h" 5 | 6 | int main( int argc, const char * argv [] ) 7 | { 8 | uint8_t datain[10000]; 9 | uint8_t dataout[10000]; 10 | 11 | if( 3 != argc ) { 12 | printf("usage: %s inputfile outputfile\n\n", argv[0]); 13 | return 0; 14 | } 15 | 16 | FILE* fin = fopen( argv[1], "rb"); 17 | if( !fin ) { printf("Could not open %s for reading.\n", argv[1]); return -1; } 18 | int32_t datainlen = fread( datain, 1, sizeof(datain), fin ); 19 | if( datainlen<=0 ) { printf("Error reading input file\n");return -1; } 20 | fclose(fin); 21 | 22 | int32_t dataoutlen = depdk( datain, datainlen, dataout, sizeof(dataout) ); 23 | if( dataoutlen<=0 ) { printf("Error decrypting input file\n");return -1; } 24 | 25 | int32_t hdrlen = pdkhdrlen(datain,datainlen); 26 | 27 | uint32_t fcsum; 28 | memcpy( &fcsum, &datain[0x0C], sizeof(fcsum) ); 29 | memset( &datain[0x0C], 0, 4 ); 30 | 31 | uint32_t csum1 = pdkchecksum( datain, hdrlen, 0 ); 32 | uint32_t csum2 = pdkchecksum( dataout, dataoutlen, 0 ); 33 | // uint32_t csum2 = pdkchecksum( datain+..., ..., csum2 ); 34 | 35 | uint32_t csumh = csum1+csum2; 36 | 37 | if(csumh!=fcsum) 38 | printf("WARNING: FILE CHECKSUM INCORRECT\n"); 39 | 40 | uint32_t csums = csum2&0xFFFFFF; 41 | if( 0xFFFF==(csums&0xFFFF) ) 42 | csums--; 43 | else 44 | if( 0==csums ) 45 | csums++; 46 | 47 | uint32_t fcsiz; 48 | memcpy( &fcsiz, &datain[0x20], sizeof(fcsiz) ); 49 | switch( fcsiz ) 50 | { 51 | case 1024: csums&=0xFF1FFF; break; 52 | case 2048: csums&=0xFF3FFF; break; 53 | case 4096: csums&=0xFF7FFF; break; 54 | } 55 | 56 | printf("CHECKSUM IDE: %06X\n", csums); 57 | 58 | FILE* fout = fopen( argv[2], "wb"); 59 | if( !fin ) { printf("Could not open %s for writing.\n", argv[2]); return -1; } 60 | if( dataoutlen != fwrite( dataout, 1, dataoutlen, fout ) ) { printf("Error writing output file\n"); return -1; } 61 | fclose(fout); 62 | 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /disass/disass13.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "emucpu.h" 6 | 7 | char* disass13(struct emuCPU *cpu, uint16_t position, char *buffer) 8 | { 9 | char* r=0; 10 | char tmp[32]; 11 | strcpy( buffer, "?????" ); 12 | 13 | uint16_t opcode = emuCPUcodeGet( cpu, position ) & 0x1FFF; 14 | 15 | //special opcode (should be a call, but makes no sense) 16 | if( 0x1FFF == opcode ) return buffer; 17 | 18 | //13 bit opcodes 0x0000 - 0x003F 19 | if( opcode<=0x003F ) 20 | { 21 | switch( opcode ) 22 | { 23 | case 0x0000: r="NOP"; break; 24 | 25 | case 0x0006: r="LDSPTL"; break; 26 | case 0x0007: r="LDSPTH"; break; 27 | 28 | case 0x0010: r="ADDC A"; break; 29 | case 0x0011: r="SUBC A"; break; 30 | case 0x0012: r="IZSN A"; break; 31 | case 0x0013: r="DZSN A"; break; 32 | 33 | case 0x0017: r="PCADD A"; break; 34 | case 0x0018: r="NOT A"; break; 35 | case 0x0019: r="NEG A"; break; 36 | case 0x001A: r="SR A"; break; 37 | case 0x001B: r="SL A"; break; 38 | case 0x001C: r="SRC A"; break; 39 | case 0x001D: r="SLC A"; break; 40 | case 0x001E: r="SWAP A"; break; 41 | 42 | case 0x0020: r="TRAP"; break; 43 | 44 | case 0x0030: r="WDRESET"; break; 45 | 46 | case 0x0032: r="PUSHAF"; break; 47 | case 0x0033: r="POPAF"; break; 48 | 49 | case 0x0035: r="RESET"; break; 50 | case 0x0036: r="STOPSYS"; break; 51 | case 0x0037: r="STOPEXE"; break; 52 | case 0x0038: r="ENGINT"; break; 53 | case 0x0039: r="DISGINT"; break; 54 | case 0x003A: r="RET"; break; 55 | case 0x003B: r="RETI"; break; 56 | case 0x003C: r="MUL"; break; 57 | } 58 | if(r) 59 | sprintf( buffer, "%s", r ); 60 | } 61 | else 62 | //8 bit opcodes 0x0060 - 0x00BF 63 | if( (opcode>=0x0060) && (opcode<=0x00BF) ) 64 | { 65 | uint8_t addr = opcode&0x1F; 66 | switch( opcode&0x1FE0 ) 67 | { 68 | case 0x0060: sprintf(buffer,"XOR IO(0x%02X), A ;%s", addr, emuCPUdecodeIO(cpu,addr,0xFF,tmp)); break; 69 | case 0x0080: sprintf(buffer,"MOV IO(0x%02X), A ;%s", addr, emuCPUdecodeIO(cpu,addr,0xFF,tmp)); break; 70 | case 0x00A0: sprintf(buffer,"MOV A, IO(0x%02X) ;%s", addr, emuCPUdecodeIO(cpu,addr,0xFF,tmp)); break; 71 | } 72 | } 73 | else 74 | //8 bit opcodes 0x00C0 - 0x00FF 75 | if( (opcode>=0x00C0) && (opcode<=0x00FF) ) 76 | { 77 | uint8_t addr = opcode&0x1E; 78 | switch( opcode & 0x1FE1 ) 79 | { 80 | case 0x00C0: r="STT16 [0x%02X]"; break; 81 | case 0x00C1: r="LDT16 [0x%02X]"; break; 82 | case 0x00E0: r="IDXM [[0x%02X]], A"; break; 83 | case 0x00E1: r="IDXM A, [[0x%02X]]"; break; 84 | } 85 | if(r) 86 | sprintf( buffer, r, addr ); 87 | } 88 | else 89 | //7 bit opcodes 0x0400 - 0x0BFF 90 | if( (opcode>=0x0400) && (opcode<=0x0BFF) ) 91 | { 92 | uint8_t addr = opcode&0x3F; 93 | switch( opcode & 0x1FC0 ) 94 | { 95 | case 0x0400: r="ADD [0x%02X], A"; break; 96 | case 0x0440: r="SUB [0x%02X], A"; break; 97 | case 0x0480: r="ADDC [0x%02X], A"; break; 98 | case 0x04C0: r="SUBC [0x%02X], A"; break; 99 | case 0x0500: r="AND [0x%02X], A"; break; 100 | case 0x0540: r="OR [0x%02X], A"; break; 101 | case 0x0580: r="XOR [0x%02X], A"; break; 102 | case 0x05C0: r="MOV [0x%02X], A"; break; 103 | case 0x0600: r="ADD A, [0x%02X]"; break; 104 | case 0x0640: r="SUB A, [0x%02X]"; break; 105 | case 0x0680: r="ADDC A, [0x%02X]"; break; 106 | case 0x06C0: r="SUBC A, [0x%02X]"; break; 107 | case 0x0700: r="AND A, [0x%02X]"; break; 108 | case 0x0740: r="OR A, [0x%02X]"; break; 109 | case 0x0780: r="XOR A, [0x%02X]"; break; 110 | case 0x07C0: r="MOV A, [0x%02X]"; break; 111 | case 0x0800: r="ADDC [0x%02X]"; break; 112 | case 0x0840: r="SUBC [0x%02X]"; break; 113 | case 0x0880: r="IZSN [0x%02X]"; break; 114 | case 0x08C0: r="DZSN [0x%02X]"; break; 115 | case 0x0900: r="INCM [0x%02X]"; break; 116 | case 0x0940: r="DECM [0x%02X]"; break; 117 | case 0x0980: r="CLEAR [0x%02X]"; break; 118 | case 0x09C0: r="XCH A, [0x%02X]"; break; 119 | case 0x0A00: r="NOT A, [0x%02X]"; break; 120 | case 0x0A40: r="NEG A, [0x%02X]"; break; 121 | case 0x0A80: r="SR [0x%02X]"; break; 122 | case 0x0AC0: r="SL [0x%02X]"; break; 123 | case 0x0B00: r="SRC [0x%02X]"; break; 124 | case 0x0B40: r="SLC [0x%02X]"; break; 125 | case 0x0B80: r="CEQSN A, [0x%02X]"; break; 126 | //case 0x0BC0: r="CNEQSN A, [0x%02X]"; break; //this INS is not implemented 127 | } 128 | if(r) 129 | sprintf( buffer, r, addr ); 130 | } 131 | else 132 | //5 bit opcodes 0x01.. , 0x1000 - 0x17FF 133 | if( (0x0100 == (opcode&0x1F00)) || (0x1000 == (opcode&0x1800)) ) 134 | { 135 | uint8_t k = opcode&0xFF; 136 | switch( opcode & 0x1F00 ) 137 | { 138 | case 0x0100: r="RET 0x%02X"; break; 139 | case 0x1000: r="ADD A, 0x%02X"; break; 140 | case 0x1100: r="SUB A, 0x%02X"; break; 141 | case 0x1200: r="CEQSN A, 0x%02X"; break; 142 | //case 0x1300: r="CNEQSN A, 0x%02X"; break; //this INS is not implemented 143 | case 0x1400: r="AND A, 0x%02X"; break; 144 | case 0x1500: r="OR A, 0x%02X"; break; 145 | case 0x1600: r="XOR A, 0x%02X"; break; 146 | case 0x1700: r="MOV A, 0x%02X"; break; 147 | } 148 | if(r) 149 | sprintf( buffer, r, k ); 150 | } 151 | else 152 | //5 bit opcodes 0x0200 - 0x03FF 153 | if( 0x0200 == (opcode&0x1E00) ) 154 | { 155 | uint8_t bit = (opcode>>5)&7; 156 | uint8_t addr = opcode&0xF; 157 | switch( opcode & 0x1F10 ) 158 | { 159 | case 0x0200: sprintf(buffer,"T0SN [0x%02X].%d", addr,bit); break; 160 | case 0x0210: sprintf(buffer,"T1SN [0x%02X].%d", addr,bit); break; 161 | case 0x0300: sprintf(buffer,"SET0 [0x%02X].%d", addr,bit); break; 162 | case 0x0310: sprintf(buffer,"SET1 [0x%02X].%d", addr,bit); break; 163 | } 164 | } 165 | else 166 | //5 bit opcodes 0x0C00 - 0x0FFF 167 | if( (opcode>=0x0C00) && (opcode<=0x0FFF) ) 168 | { 169 | uint8_t bit = (opcode>>5)&7; 170 | uint8_t addr = opcode&0x1F; 171 | switch( opcode & 0x1F00 ) 172 | { 173 | case 0x0C00: sprintf(buffer,"T0SN IO(0x%02X).%d ;%s", addr,bit,emuCPUdecodeIO(cpu,addr,bit,tmp)); break; 174 | case 0x0D00: sprintf(buffer,"T1SN IO(0x%02X).%d ;%s", addr,bit,emuCPUdecodeIO(cpu,addr,bit,tmp)); break; 175 | case 0x0E00: sprintf(buffer,"SET0 IO(0x%02X).%d ;%s", addr,bit,emuCPUdecodeIO(cpu,addr,bit,tmp)); break; 176 | case 0x0F00: sprintf(buffer,"SET1 IO(0x%02X).%d ;%s", addr,bit,emuCPUdecodeIO(cpu,addr,bit,tmp)); break; 177 | } 178 | } 179 | else 180 | //3 bit opcodes 0x1800 - 0x1FFF 181 | if( (0x1800 == (opcode&0x1800)) ) 182 | { 183 | if( opcode & 0x0400 ) 184 | sprintf(buffer,"CALL 0x%03X", opcode & 0x03FF); 185 | else 186 | sprintf(buffer,"GOTO 0x%03X", opcode & 0x03FF); 187 | } 188 | 189 | return buffer; 190 | } 191 | -------------------------------------------------------------------------------- /disass/disass14.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "emucpu.h" 6 | 7 | char* disass14(struct emuCPU *cpu, uint16_t position, char *buffer) 8 | { 9 | char* r=0; 10 | char tmp[32]; 11 | strcpy( buffer, "?????" ); 12 | 13 | uint16_t opcode = emuCPUcodeGet( cpu, position ) & 0x3FFF; 14 | 15 | //special opcode (should be a call, but makes no sense) 16 | if( 0x3FFF == opcode ) return buffer; 17 | 18 | //14 bit opcodes 0x0000 - 0x00BF 19 | if( opcode<=0x00BF ) 20 | { 21 | switch( opcode ) 22 | { 23 | case 0x0000: r="NOP"; break; 24 | 25 | case 0x0006: r="LDSPTL"; break; 26 | case 0x0007: r="LDSPTH"; break; 27 | 28 | case 0x0020: r="TRAP"; break; 29 | 30 | case 0x0060: r="ADDC A"; break; 31 | case 0x0061: r="SUBC A"; break; 32 | case 0x0062: r="IZSN A"; break; 33 | case 0x0063: r="DZSN A"; break; 34 | 35 | case 0x0067: r="PCADD A"; break; 36 | case 0x0068: r="NOT A"; break; 37 | case 0x0069: r="NEG A"; break; 38 | case 0x006A: r="SR A"; break; 39 | case 0x006B: r="SL A"; break; 40 | case 0x006C: r="SRC A"; break; 41 | case 0x006D: r="SLC A"; break; 42 | case 0x006E: r="SWAP A"; break; 43 | 44 | case 0x0070: r="WDRESET"; break; 45 | 46 | case 0x0072: r="PUSHAF"; break; 47 | case 0x0073: r="POPAF"; break; 48 | 49 | case 0x0075: r="RESET"; break; 50 | case 0x0076: r="STOPSYS"; break; 51 | case 0x0077: r="STOPEXE"; break; 52 | case 0x0078: r="ENGINT"; break; 53 | case 0x0079: r="DISGINT"; break; 54 | case 0x007A: r="RET"; break; 55 | case 0x007B: r="RETI"; break; 56 | case 0x007C: r="MUL"; break; 57 | } 58 | if(r) 59 | sprintf( buffer, "%s", r ); 60 | } 61 | else 62 | //8 bit opcodes 0x00C0 - 0x01FF 63 | if( (opcode>=0x00C0) && (opcode<=0x01FF) ) 64 | { 65 | uint8_t addr = opcode&0x3F; 66 | switch( opcode&0x3FC0 ) 67 | { 68 | case 0x00C0: sprintf(buffer,"XOR IO(0x%02X), A ;%s", addr, emuCPUdecodeIO(cpu,addr,0xFF,tmp)); break; 69 | case 0x0180: sprintf(buffer,"MOV IO(0x%02X), A ;%s", addr, emuCPUdecodeIO(cpu,addr,0xFF,tmp)); break; 70 | case 0x01C0: sprintf(buffer,"MOV A, IO(0x%02X) ;%s", addr, emuCPUdecodeIO(cpu,addr,0xFF,tmp)); break; 71 | } 72 | } 73 | else 74 | //7 bit opcodes 0x03.. 75 | if( 0x0300 == (opcode&0x3F00) ) 76 | { 77 | uint8_t addr = opcode&0x7E; 78 | switch( opcode & 0x3F81 ) 79 | { 80 | case 0x0300: r="STT16 [0x%02X]"; break; 81 | case 0x0301: r="LDT16 [0x%02X]"; break; 82 | case 0x0380: r="IDXM [[0x%02X]], A"; break; 83 | case 0x0381: r="IDXM A, [[0x%02X]]"; break; 84 | } 85 | if(r) 86 | sprintf( buffer, r, addr ); 87 | } 88 | else 89 | //7 bit opcodes 0x0600 - 0x17FF 90 | if( (opcode>=0x0600) && (opcode<=0x17FF) ) 91 | { 92 | uint8_t addr = opcode&0x7F; 93 | switch( opcode & 0x3F80 ) 94 | { 95 | case 0x0600: r="COMP A, [0x%02X]"; break; 96 | case 0x0680: r="COMP [0x%02X], A"; break; 97 | case 0x0700: r="NADD A, [0x%02X]"; break; 98 | case 0x0780: r="NADD [0x%02X], A"; break; 99 | case 0x0800: r="ADD [0x%02X], A"; break; 100 | case 0x0880: r="SUB [0x%02X], A"; break; 101 | case 0x0900: r="ADDC [0x%02X], A"; break; 102 | case 0x0980: r="SUBC [0x%02X], A"; break; 103 | case 0x0A00: r="AND [0x%02X], A"; break; 104 | case 0x0A80: r="OR [0x%02X], A"; break; 105 | case 0x0B00: r="XOR [0x%02X], A"; break; 106 | case 0x0B80: r="MOV [0x%02X], A"; break; 107 | case 0x0C00: r="ADD A, [0x%02X]"; break; 108 | case 0x0C80: r="SUB A, [0x%02X]"; break; 109 | case 0x0D00: r="ADDC A, [0x%02X]"; break; 110 | case 0x0D80: r="SUBC A, [0x%02X]"; break; 111 | case 0x0E00: r="AND A, [0x%02X]"; break; 112 | case 0x0E80: r="OR A, [0x%02X]"; break; 113 | case 0x0F00: r="XOR A, [0x%02X]"; break; 114 | case 0x0F80: r="MOV A, [0x%02X]"; break; 115 | case 0x1000: r="ADDC [0x%02X]"; break; 116 | case 0x1080: r="SUBC [0x%02X]"; break; 117 | case 0x1100: r="IZSN [0x%02X]"; break; 118 | case 0x1180: r="DZSN [0x%02X]"; break; 119 | case 0x1200: r="INCM [0x%02X]"; break; 120 | case 0x1280: r="DECM [0x%02X]"; break; 121 | case 0x1300: r="CLEAR [0x%02X]"; break; 122 | case 0x1380: r="XCH A, [0x%02X]"; break; 123 | case 0x1400: r="NOT A, [0x%02X]"; break; 124 | case 0x1480: r="NEG A, [0x%02X]"; break; 125 | case 0x1500: r="SR [0x%02X]"; break; 126 | case 0x1580: r="SL [0x%02X]"; break; 127 | case 0x1600: r="SRC [0x%02X]"; break; 128 | case 0x1680: r="SLC [0x%02X]"; break; 129 | case 0x1700: r="CEQSN A, [0x%02X]"; break; 130 | case 0x1780: r="CNEQSN A, [0x%02X]"; break; 131 | } 132 | if(r) 133 | sprintf( buffer, r, addr ); 134 | } 135 | else 136 | //6 bit opcodes 0x02.. , 0x2800 - 0x2FFF 137 | if( (0x0200 == (opcode&0x3F00)) || (0x2800 == (opcode&0x3800)) ) 138 | { 139 | uint8_t k = opcode&0xFF; 140 | switch( opcode & 0x3F00 ) 141 | { 142 | case 0x0200: r="RET 0x%02X"; break; 143 | case 0x2800: r="ADD A, 0x%02X"; break; 144 | case 0x2900: r="SUB A, 0x%02X"; break; 145 | case 0x2A00: r="CEQSN A, 0x%02X"; break; 146 | case 0x2B00: r="CNEQSN A, 0x%02X"; break; 147 | case 0x2C00: r="AND A, 0x%02X"; break; 148 | case 0x2D00: r="OR A, 0x%02X"; break; 149 | case 0x2E00: r="XOR A, 0x%02X"; break; 150 | case 0x2F00: r="MOV A, 0x%02X"; break; 151 | } 152 | if(r) 153 | sprintf( buffer, r, k ); 154 | } 155 | else 156 | //5 bit opcodes 0x0400 - 0x0500, 0x1800 - 0x27FF 157 | if( (0x0400 == (opcode&0x3E00)) || ((opcode>=0x1800) && (opcode<=0x27FF)) ) 158 | { 159 | uint8_t bit = (opcode>>6)&7; 160 | uint8_t addr = opcode&0x3F; 161 | switch( opcode & 0x3E00 ) 162 | { 163 | case 0x0400: sprintf(buffer,"SWAPC IO(0x%02X).%d ;%s", addr,bit,emuCPUdecodeIO(cpu,addr,bit,tmp)); break; 164 | case 0x1800: sprintf(buffer,"T0SN IO(0x%02X).%d ;%s", addr,bit,emuCPUdecodeIO(cpu,addr,bit,tmp)); break; 165 | case 0x1A00: sprintf(buffer,"T1SN IO(0x%02X).%d ;%s", addr,bit,emuCPUdecodeIO(cpu,addr,bit,tmp)); break; 166 | case 0x1C00: sprintf(buffer,"SET0 IO(0x%02X).%d ;%s", addr,bit,emuCPUdecodeIO(cpu,addr,bit,tmp)); break; 167 | case 0x1E00: sprintf(buffer,"SET1 IO(0x%02X).%d ;%s", addr,bit,emuCPUdecodeIO(cpu,addr,bit,tmp)); break; 168 | case 0x2000: sprintf(buffer,"T0SN [0x%02X].%d", addr,bit); break; 169 | case 0x2200: sprintf(buffer,"T1SN [0x%02X].%d", addr,bit); break; 170 | case 0x2400: sprintf(buffer,"SET0 [0x%02X].%d", addr,bit); break; 171 | case 0x2600: sprintf(buffer,"SET1 [0x%02X].%d", addr,bit); break; 172 | } 173 | } 174 | else 175 | //3 bit opcodes 0x3000 - 0x3FFF 176 | if( (0x3000 == (opcode&0x3000)) ) 177 | { 178 | if( opcode & 0x0800 ) 179 | sprintf(buffer,"CALL 0x%03X", opcode & 0x07FF); 180 | else 181 | sprintf(buffer,"GOTO 0x%03X", opcode & 0x07FF); 182 | } 183 | 184 | return buffer; 185 | } 186 | -------------------------------------------------------------------------------- /disass/disass15.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "emucpu.h" 6 | 7 | char* disass15(struct emuCPU *cpu, uint16_t position, char *buffer) 8 | { 9 | char* r=0; 10 | char tmp[32]; 11 | strcpy( buffer, "?????" ); 12 | 13 | uint16_t opcode = emuCPUcodeGet( cpu, position ) & 0x7FFF; 14 | 15 | //special opcode (should be a call, but makes no sense) 16 | if( 0x7FFF == opcode ) return buffer; 17 | 18 | //15 bit opcodes 0x0000 - 0x007F 19 | if( opcode<=0x007F ) 20 | { 21 | switch( opcode ) 22 | { 23 | case 0x0000: r="NOP"; break; 24 | 25 | case 0x0006: r="LDSPTL"; break; 26 | case 0x0007: r="LDSPTH"; break; 27 | 28 | case 0x0020: r="TRAP"; break; 29 | 30 | case 0x0060: r="ADDC A"; break; 31 | case 0x0061: r="SUBC A"; break; 32 | case 0x0062: r="IZSN A"; break; 33 | case 0x0063: r="DZSN A"; break; 34 | 35 | case 0x0067: r="PCADD A"; break; 36 | case 0x0068: r="NOT A"; break; 37 | case 0x0069: r="NEG A"; break; 38 | case 0x006A: r="SR A"; break; 39 | case 0x006B: r="SL A"; break; 40 | case 0x006C: r="SRC A"; break; 41 | case 0x006D: r="SLC A"; break; 42 | case 0x006E: r="SWAP A"; break; 43 | 44 | case 0x0070: r="WDRESET"; break; 45 | 46 | case 0x0072: r="PUSHAF"; break; 47 | case 0x0073: r="POPAF"; break; 48 | 49 | case 0x0075: r="RESET"; break; 50 | case 0x0076: r="STOPSYS"; break; 51 | case 0x0077: r="STOPEXE"; break; 52 | case 0x0078: r="ENGINT"; break; 53 | case 0x0079: r="DISGINT"; break; 54 | case 0x007A: r="RET"; break; 55 | case 0x007B: r="RETI"; break; 56 | case 0x007C: r="MUL"; break; 57 | } 58 | if(r) 59 | sprintf( buffer, "%s", r ); 60 | } 61 | else 62 | //9 bit opcodes 0x0080 - 0x01FF 63 | if( (opcode>=0x0080) && (opcode<=0x01FF) ) 64 | { 65 | uint8_t addr = opcode&0x7F; 66 | switch( opcode&0x7F80 ) 67 | { 68 | case 0x0080: sprintf(buffer,"XOR IO(0x%02X), A ;%s", addr, emuCPUdecodeIO(cpu,addr,0xFF,tmp)); break; 69 | case 0x0100: sprintf(buffer,"MOV IO(0x%02X), A ;%s", addr, emuCPUdecodeIO(cpu,addr,0xFF,tmp)); break; 70 | case 0x0180: sprintf(buffer,"MOV A, IO(0x%02X) ;%s", addr, emuCPUdecodeIO(cpu,addr,0xFF,tmp)); break; 71 | } 72 | } 73 | else 74 | //7 bit opcodes 0x0500-0x7FF 75 | if( (opcode>=0x0500) && (opcode<=0x07FF) ) 76 | { 77 | uint8_t addr = opcode&0xFE; 78 | switch( opcode & 0x7F01 ) 79 | { 80 | case 0x0500: r="LDTABL [0x%02X]"; break; 81 | case 0x0501: r="LDTABH [0x%02X]"; break; 82 | case 0x0600: r="STT16 [0x%02X]"; break; 83 | case 0x0601: r="LDT16 [0x%02X]"; break; 84 | case 0x0700: r="IDXM [[0x%02X]], A"; break; 85 | case 0x0701: r="IDXM A, [[0x%02X]]"; break; 86 | } 87 | if(r) 88 | sprintf( buffer, r, addr ); 89 | } 90 | else 91 | //7 bit opcodes 0x0C00 - 0x2FFF 92 | if( (opcode>=0x0C00) && (opcode<=0x2FFF) ) 93 | { 94 | uint8_t addr = opcode&0xFF; 95 | switch( opcode & 0x7F00 ) 96 | { 97 | case 0x0C00: r="COMP A, [0x%02X]"; break; 98 | case 0x0D00: r="COMP [0x%02X], A"; break; 99 | case 0x0E00: r="NADD A, [0x%02X]"; break; 100 | case 0x0F00: r="NADD [0x%02X], A"; break; 101 | case 0x1000: r="ADD [0x%02X], A"; break; 102 | case 0x1100: r="SUB [0x%02X], A"; break; 103 | case 0x1200: r="ADDC [0x%02X], A"; break; 104 | case 0x1300: r="SUBC [0x%02X], A"; break; 105 | case 0x1400: r="AND [0x%02X], A"; break; 106 | case 0x1500: r="OR [0x%02X], A"; break; 107 | case 0x1600: r="XOR [0x%02X], A"; break; 108 | case 0x1700: r="MOV [0x%02X], A"; break; 109 | case 0x1800: r="ADD A, [0x%02X]"; break; 110 | case 0x1900: r="SUB A, [0x%02X]"; break; 111 | case 0x1A00: r="ADDC A, [0x%02X]"; break; 112 | case 0x1B00: r="SUBC A, [0x%02X]"; break; 113 | case 0x1C00: r="AND A, [0x%02X]"; break; 114 | case 0x1D00: r="OR A, [0x%02X]"; break; 115 | case 0x1E00: r="XOR A, [0x%02X]"; break; 116 | case 0x1F00: r="MOV A, [0x%02X]"; break; 117 | case 0x2000: r="ADDC [0x%02X]"; break; 118 | case 0x2100: r="SUBC [0x%02X]"; break; 119 | case 0x2200: r="IZSN [0x%02X]"; break; 120 | case 0x2300: r="DZSN [0x%02X]"; break; 121 | case 0x2400: r="INCM [0x%02X]"; break; 122 | case 0x2500: r="DECM [0x%02X]"; break; 123 | case 0x2600: r="CLEAR [0x%02X]"; break; 124 | case 0x2700: r="XCH A, [0x%02X]"; break; 125 | case 0x2800: r="NOT A, [0x%02X]"; break; 126 | case 0x2900: r="NEG A, [0x%02X]"; break; 127 | case 0x2A00: r="SR [0x%02X]"; break; 128 | case 0x2B00: r="SL [0x%02X]"; break; 129 | case 0x2C00: r="SRC [0x%02X]"; break; 130 | case 0x2D00: r="SLC [0x%02X]"; break; 131 | case 0x2E00: r="CEQSN A, [0x%02X]"; break; 132 | case 0x2F00: r="CNEQSN A, [0x%02X]"; break; 133 | } 134 | if(r) 135 | sprintf( buffer, r, addr ); 136 | } 137 | else 138 | //7 bit opcodes 0x02.. , 0x5000 - 0x57FF 139 | if( (0x0200 == (opcode&0x7F00)) || (0x5000 == (opcode&0x7800)) ) 140 | { 141 | uint8_t k = opcode&0xFF; 142 | switch( opcode & 0x7F00 ) 143 | { 144 | case 0x0200: r="RET 0x%02X"; break; 145 | case 0x5000: r="ADD A, 0x%02X"; break; 146 | case 0x5100: r="SUB A, 0x%02X"; break; 147 | case 0x5200: r="CEQSN A, 0x%02X"; break; 148 | case 0x5300: r="CNEQSN A, 0x%02X"; break; 149 | case 0x5400: r="AND A, 0x%02X"; break; 150 | case 0x5500: r="OR A, 0x%02X"; break; 151 | case 0x5600: r="XOR A, 0x%02X"; break; 152 | case 0x5700: r="MOV A, 0x%02X"; break; 153 | } 154 | if(r) 155 | sprintf( buffer, r, k ); 156 | } 157 | else 158 | //5 bit opcodes 0x3000 - 0x4FFF, 0x5C00 - 0x5FFF 159 | if( ((opcode>=0x3000) && (opcode<=0x4FFF)) || (0x5C00 == (opcode&0x7C00)) ) 160 | { 161 | uint8_t bit = (opcode>>7)&7; 162 | uint8_t addr = opcode&0x7F; 163 | switch( opcode & 0x7C00 ) 164 | { 165 | case 0x3000: sprintf(buffer,"T0SN IO(0x%02X).%d ;%s", addr,bit,emuCPUdecodeIO(cpu,addr,bit,tmp)); break; 166 | case 0x3400: sprintf(buffer,"T1SN IO(0x%02X).%d ;%s", addr,bit,emuCPUdecodeIO(cpu,addr,bit,tmp)); break; 167 | case 0x3800: sprintf(buffer,"SET0 IO(0x%02X).%d ;%s", addr,bit,emuCPUdecodeIO(cpu,addr,bit,tmp)); break; 168 | case 0x3C00: sprintf(buffer,"SET1 IO(0x%02X).%d ;%s", addr,bit,emuCPUdecodeIO(cpu,addr,bit,tmp)); break; 169 | case 0x4000: sprintf(buffer,"T0SN [0x%02X].%d", addr,bit); break; 170 | case 0x4400: sprintf(buffer,"T1SN [0x%02X].%d", addr,bit); break; 171 | case 0x4800: sprintf(buffer,"SET0 [0x%02X].%d", addr,bit); break; 172 | case 0x4C00: sprintf(buffer,"SET1 [0x%02X].%d", addr,bit); break; 173 | case 0x5C00: sprintf(buffer,"SWAPC IO(0x%02X).%d ;%s", addr,bit,emuCPUdecodeIO(cpu,addr,bit,tmp)); break; 174 | } 175 | } 176 | else 177 | //3 bit opcodes 0x6000 - 0x7FFF 178 | if( (0x6000 == (opcode&0x6000)) ) 179 | { 180 | if( opcode & 0x1000 ) 181 | sprintf(buffer,"CALL 0x%03X", opcode & 0x0FFF); 182 | else 183 | sprintf(buffer,"GOTO 0x%03X", opcode & 0x0FFF); 184 | } 185 | 186 | return buffer; 187 | } 188 | -------------------------------------------------------------------------------- /disass/disass16.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "emucpu.h" 6 | 7 | char* disass16(struct emuCPU *cpu, uint16_t position, char *buffer) 8 | { 9 | char* r=0; 10 | char tmp[32]; 11 | strcpy( buffer, "?????" ); 12 | 13 | uint16_t opcode = emuCPUcodeGet( cpu, position ); 14 | 15 | //special opcode (should be a call, but makes no sense) 16 | if( 0xFFFF == opcode ) return buffer; 17 | 18 | //16 bit opcodes 0x0000 - 0x003F 19 | if( opcode<=0x003F ) 20 | { 21 | switch( opcode ) 22 | { 23 | case 0x0000: r="NOP"; break; 24 | 25 | case 0x0006: r="LDSPTL"; break; 26 | case 0x0007: r="LDSPTH"; break; 27 | 28 | case 0x0010: r="ADDC A"; break; 29 | case 0x0011: r="SUBC A"; break; 30 | case 0x0012: r="IZSN A"; break; 31 | case 0x0013: r="DZSN A"; break; 32 | 33 | case 0x0017: r="PCADD A"; break; 34 | case 0x0018: r="NOT A"; break; 35 | case 0x0019: r="NEG A"; break; 36 | case 0x001A: r="SR A"; break; 37 | case 0x001B: r="SL A"; break; 38 | case 0x001C: r="SRC A"; break; 39 | case 0x001D: r="SLC A"; break; 40 | case 0x001E: r="SWAP A"; break; 41 | case 0x001F: r="DELAY A"; break; 42 | 43 | case 0x0020: r="TRAP"; break; 44 | 45 | case 0x0030: r="WDRESET"; break; 46 | 47 | case 0x0032: r="PUSHAF"; break; 48 | case 0x0033: r="POPAF"; break; 49 | 50 | case 0x0035: r="RESET"; break; 51 | case 0x0036: r="STOPSYS"; break; 52 | case 0x0037: r="STOPEXE"; break; 53 | case 0x0038: r="ENGINT"; break; 54 | case 0x0039: r="DISGINT"; break; 55 | case 0x003A: r="RET"; break; 56 | case 0x003B: r="RETI"; break; 57 | case 0x003C: r="MUL"; break; 58 | } 59 | if(r) 60 | sprintf( buffer, "%s", r ); 61 | } 62 | else 63 | //11 bit opcode 0x0040 - 0x005F 64 | if( 0x0040 == (opcode&0xFFE0) ) 65 | { 66 | sprintf(buffer,"PMODE %d",opcode&0x1F); 67 | } 68 | //12 bit opcode 0x0060 - 0x007F 69 | if( 0x0060 == (opcode&0xFFE0) ) 70 | { 71 | switch( opcode&0xFFF0 ) 72 | { 73 | case 0x0060: sprintf(buffer,"POPW PC %d", opcode&0xF); break; 74 | case 0x0070: sprintf(buffer,"PUSHW PC %d", opcode&0xF); break; 75 | } 76 | } 77 | //10 bit opcodes 0x0080 - 0x00FF, 0x1000 - 0x1070 78 | if( (0x0080 == (opcode&0xFF80)) || (0x1000 == (opcode&0xFF80)) ) 79 | { 80 | uint8_t addr = opcode&0x3F; 81 | switch( opcode&0xFFC0 ) 82 | { 83 | case 0x0080: sprintf(buffer,"MOV IO(0x%02X), A ;%s", addr, emuCPUdecodeIO(cpu,addr,0xFF,tmp)); break; 84 | case 0x00C0: sprintf(buffer,"MOV A, IO(0x%02X) ;%s", addr, emuCPUdecodeIO(cpu,addr,0xFF,tmp)); break; 85 | case 0x1000: sprintf(buffer,"XOR IO(0x%02X), A ;%s", addr, emuCPUdecodeIO(cpu,addr,0xFF,tmp)); break; 86 | case 0x1040: sprintf(buffer,"XOR A, IO(0x%02X) ;%s", addr, emuCPUdecodeIO(cpu,addr,0xFF,tmp)); break; 87 | } 88 | } 89 | else 90 | //7 bit opcodes 0x0200 - 0x0BFF 91 | if( (opcode>=0x0200) && (opcode<=0x0BFF) ) 92 | { 93 | uint16_t addr = opcode&0x1FE; 94 | switch( opcode & 0xFE01 ) 95 | { 96 | case 0x0200: r="STT16 [0x%03X]"; break; 97 | case 0x0201: r="LDT16 [0x%03X]"; break; 98 | case 0x0400: r="POPW [0x%03X]"; break; 99 | case 0x0401: r="PUSHW [0x%03X]"; break; 100 | case 0x0600: r="IGOTO [0x%03X]"; break; 101 | case 0x0601: r="ICALL [0x%03X]"; break; 102 | case 0x0800: r="IDXM [[0x%03X]], A"; break; 103 | case 0x0801: r="IDXM A, [[0x%03X]]"; break; 104 | case 0x0A00: r="LDTABL [0x%03X]"; break; 105 | case 0x0A01: r="LDTABH [0x%03X]"; break; 106 | } 107 | if(r) 108 | sprintf( buffer, r, addr ); 109 | } 110 | else 111 | //7 bit opcodes 0x1400 - 0x17FF, 0x3000 - 0x7FFF 112 | if( ((opcode>=0x1400) && (opcode<=0x17FF)) || 113 | ((opcode>=0x3000) && (opcode<=0x7FFF)) ) 114 | { 115 | int16_t addr = opcode&0x1FF; 116 | switch( opcode & 0xFFE0 ) 117 | { 118 | case 0x1400: r="CNEQSN [0x%03X], A"; break; 119 | case 0x1600: r="CNEQSN A, [0x%03X]"; break; 120 | case 0x3000: r="NMOV [0x%03X], A"; break; 121 | case 0x3200: r="NMOV A, [0x%03X]"; break; 122 | case 0x3400: r="NADD [0x%03X], A"; break; 123 | case 0x3600: r="NADD A, [0x%03X]"; break; 124 | case 0x3800: r="CEQSN [0x%03X], A"; break; 125 | case 0x3A00: r="CEQSN A, [0x%03X]"; break; 126 | case 0x3C00: r="COMP [0x%03X], A"; break; 127 | case 0x3E00: r="COMP A, [0x%03X]"; break; 128 | case 0x4000: r="ADD [0x%03X], A"; break; 129 | case 0x4200: r="ADD A, [0x%03X]"; break; 130 | case 0x4400: r="SUB [0x%03X], A"; break; 131 | case 0x4600: r="SUB A, [0x%03X]"; break; 132 | case 0x4800: r="ADDC [0x%03X], A"; break; 133 | case 0x4A00: r="ADDC A, [0x%03X]"; break; 134 | case 0x4C00: r="SUBC [0x%03X], A"; break; 135 | case 0x4E00: r="SUBC A, [0x%03X]"; break; 136 | case 0x5000: r="AND [0x%03X], A"; break; 137 | case 0x5200: r="AND A, [0x%03X]"; break; 138 | case 0x5400: r="OR [0x%03X], A"; break; 139 | case 0x5600: r="OR A, [0x%03X]"; break; 140 | case 0x5800: r="XOR [0x%03X], A"; break; 141 | case 0x5A00: r="XOR A, [0x%03X]"; break; 142 | case 0x5C00: r="MOV [0x%03X], A"; break; 143 | case 0x5E00: r="MOV A, [0x%03X]"; break; 144 | case 0x6000: r="ADDC [0x%03X]"; break; 145 | case 0x6200: r="SUBC [0x%03X]"; break; 146 | case 0x6400: r="IZSN [0x%03X]"; break; 147 | case 0x6600: r="DZSN [0x%03X]"; break; 148 | case 0x6800: r="INCM [0x%03X]"; break; 149 | case 0x6A00: r="DECM [0x%03X]"; break; 150 | case 0x6C00: r="CLEAR [0x%03X]"; break; 151 | case 0x6E00: r="XCH A, [0x%03X]"; break; 152 | case 0x7000: r="NOT A, [0x%03X]"; break; 153 | case 0x7200: r="NEG A, [0x%03X]"; break; 154 | case 0x7400: r="SR [0x%03X]"; break; 155 | case 0x7600: r="SL [0x%03X]"; break; 156 | case 0x7800: r="SRC [0x%03X]"; break; 157 | case 0x7A00: r="SLC [0x%03X]"; break; 158 | case 0x7C00: r="SWAP [0x%03X]"; break; 159 | case 0x7E00: r="DELAY [0x%03X]"; break; 160 | } 161 | if(r) 162 | sprintf( buffer, r, addr ); 163 | } 164 | else 165 | //8 bit opcodes 0x0E00 - 0x0FFF, 0x1800 - 0x1FFF 166 | if( (0x0E00 == (opcode&0xFE00)) || (0x1800 == (opcode&0xF800)) ) 167 | { 168 | uint8_t k = opcode&0xFF; 169 | switch( opcode & 0xFF00 ) 170 | { 171 | case 0x0E00: r="DELAY 0x%02X"; break; 172 | case 0x0F00: r="RET 0x%02X"; break; 173 | case 0x1800: r="ADD A, 0x%02X"; break; 174 | case 0x1900: r="SUB A, 0x%02X"; break; 175 | case 0x1A00: r="CEQSN A, 0x%02X"; break; 176 | case 0x1B00: r="CNEQSN A, 0x%02X"; break; 177 | case 0x1C00: r="AND A, 0x%02X"; break; 178 | case 0x1D00: r="OR A, 0x%02X"; break; 179 | case 0x1E00: r="XOR A, 0x%02X"; break; 180 | case 0x1F00: r="MOV A, 0x%02X"; break; 181 | } 182 | if(r) 183 | sprintf( buffer, r, k ); 184 | } 185 | else 186 | //7 bit opcodes 0x2000 - 0x2FFF 187 | if( 0x2000 == (opcode&0xF000) ) 188 | { 189 | uint8_t bit = (opcode>>6)&7; 190 | uint8_t addr = opcode&0x3F; 191 | switch( opcode & 0xFE00 ) 192 | { 193 | case 0x2000: sprintf(buffer,"T0SN IO(0x%02X).%d ;%s", addr,bit,emuCPUdecodeIO(cpu,addr,bit,tmp)); break; 194 | case 0x2200: sprintf(buffer,"T1SN IO(0x%02X).%d ;%s", addr,bit,emuCPUdecodeIO(cpu,addr,bit,tmp)); break; 195 | case 0x2400: sprintf(buffer,"SET0 IO(0x%02X).%d ;%s", addr,bit,emuCPUdecodeIO(cpu,addr,bit,tmp)); break; 196 | case 0x2600: sprintf(buffer,"SET1 IO(0x%02X).%d ;%s", addr,bit,emuCPUdecodeIO(cpu,addr,bit,tmp)); break; 197 | case 0x2800: sprintf(buffer,"TOG IO(0x%02X).%d ;%s", addr,bit,emuCPUdecodeIO(cpu,addr,bit,tmp)); break; 198 | case 0x2A00: sprintf(buffer,"WAIT0 IO(0x%02X).%d ;%s", addr,bit,emuCPUdecodeIO(cpu,addr,bit,tmp)); break; 199 | case 0x2C00: sprintf(buffer,"WAIT1 IO(0x%02X).%d ;%s", addr,bit,emuCPUdecodeIO(cpu,addr,bit,tmp)); break; 200 | case 0x2E00: sprintf(buffer,"SWAPC IO(0x%02X).%d ;%s", addr,bit,emuCPUdecodeIO(cpu,addr,bit,tmp)); break; 201 | } 202 | } 203 | else 204 | //4 bit opcodes 0x8000 - 0xBFFF 205 | if( (opcode>=0x8000) && (opcode<=0xBFFF) ) 206 | { 207 | uint8_t bit = (opcode>>9)&7; 208 | uint16_t addr = opcode&0x1FF; 209 | switch( opcode & 0xF000 ) 210 | { 211 | case 0x8000: sprintf(buffer,"T0SN [0x%03X].%d", addr,bit); break; 212 | case 0x9000: sprintf(buffer,"T1SN [0x%03X].%d", addr,bit); break; 213 | case 0xA000: sprintf(buffer,"SET0 [0x%03X].%d", addr,bit); break; 214 | case 0xB000: sprintf(buffer,"SET1 [0x%03X].%d", addr,bit); break; 215 | } 216 | } 217 | else 218 | //3 bit opcodes 0xC000 - 0xFFFF 219 | if( (0xC000 == (opcode&0xC000)) ) 220 | { 221 | if( opcode & 0x4000 ) 222 | sprintf(buffer,"CALL 0x%03X", opcode & 0x1FFF); 223 | else 224 | sprintf(buffer,"GOTO 0x%03X", opcode & 0x1FFF); 225 | } 226 | 227 | return buffer; 228 | } 229 | -------------------------------------------------------------------------------- /dispdk.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "emucpu.h" 7 | 8 | int main( int argc, const char * argv [] ) 9 | { 10 | int rc; 11 | if( (argc<2) || (argc>3) ) { 12 | printf("usage: %s [otpidhex] inputfile\n" 13 | "example: %s input.pdk\n" 14 | "example: %s 2AA1 input.bin\n" 15 | "example: %s 2AA1 input.ihex\n", 16 | argv[0], argv[0], argv[0], argv[0]); 17 | return 0; 18 | } 19 | 20 | uint16_t otp_id; 21 | struct emuCPU cpu; 22 | 23 | if( 3 == argc ) 24 | { 25 | if( 1 != sscanf(argv[1], "%" SCNx16, &otp_id) ) 26 | { 27 | printf("Error wrong otp id: %s\n",argv[1]); 28 | return -1; 29 | } 30 | 31 | rc=emuCPUloadIHEX(&cpu, argv[2], otp_id); 32 | 33 | if( rc<0 ) 34 | rc=emuCPUloadBIN(&cpu, argv[2], false, otp_id); 35 | } 36 | else 37 | { 38 | rc=emuCPUloadPDK(&cpu, argv[1], false); 39 | if( 0 == rc ) 40 | { 41 | printf("MCU_NAME: %s\n", cpu.hdr.mcu_name); 42 | printf("OTP_ID: %04X\n", cpu.hdr.otp_id); 43 | } 44 | otp_id = cpu.hdr.otp_id; 45 | } 46 | 47 | if( rc < 0 ) { 48 | if( -4 == rc ) 49 | printf("Error unsupported CPU OTP_ID: %04X\n",otp_id); 50 | else 51 | if( -3 == rc ) 52 | printf("Error invalid PDK header\n"); 53 | else 54 | printf("Error reading input file: %d\n",rc); 55 | return -1; 56 | } 57 | 58 | printf("\n"); 59 | 60 | char buf[64] = "-----"; 61 | uint32_t p; 62 | for( p=0; p 2 | #include 3 | #include 4 | #include 5 | 6 | #include "emucpu.h" 7 | #include "pdkformat.h" 8 | #include "fpdkihex8.h" 9 | #include "cpuvariant.h" 10 | 11 | int emuCPUinit(struct emuCPU *cpu, uint8_t* hdr, uint32_t hdrlen, bool fixupHighCode) 12 | { 13 | cpu->maxIO = 0; 14 | cpu->maxMem = 0; 15 | cpu->maxCode = 0; 16 | 17 | cpu->fnReset = 0; 18 | cpu->fnExecute = 0; 19 | cpu->fnPeripherals = 0; 20 | cpu->fnException = 0; 21 | cpu->fnIORead = 0; 22 | cpu->fnIOWrite = 0; 23 | cpu->fnIOName = 0; 24 | 25 | if( hdrlen>sizeof(cpu->hdr) ) 26 | return -1; 27 | 28 | if( hdr && hdrlen) 29 | memcpy( &cpu->hdr, hdr, hdrlen ); 30 | cpu->hdrlen = hdrlen; 31 | 32 | switch( cpu->hdr.otp_id ) 33 | { 34 | case 0x0B80: // PMS150 / PMC150 35 | case 0x1E01: // PMS150B 36 | case 0x2A16: // PMS150C 37 | pmx150_init(cpu,fixupHighCode); break; 38 | 39 | case 0x2A06: // PMS154 40 | case 0x2C06: // PMS154B / PMS154C 41 | case 0x2AA1: // PFS154 //TODO: much different ? own impl? 42 | case 0x2AA4: // PFC154 //TODO: much different ? own impl? 43 | pmx154_init(cpu,fixupHighCode); break; 44 | 45 | case 0x2AA2: // PFS173 46 | pmx173_init(cpu,fixupHighCode); break; 47 | 48 | default: 49 | if( 0 != generic_init(cpu) ) 50 | return -3; 51 | } 52 | 53 | if( !cpu->fnReset ) 54 | return -2; 55 | 56 | return 0; 57 | } 58 | 59 | int emuCPUloadPDK(struct emuCPU *cpu, const char *filename, bool fixupHighCode) 60 | { 61 | memset( cpu, 0, sizeof(struct emuCPU) ); 62 | 63 | FILE* fin = fopen( filename, "rb"); 64 | if( !fin ) 65 | return -1; //could not open file 66 | 67 | uint8_t pdk[10000]; 68 | int pdklen =fread( pdk, 1, sizeof(pdk), fin ); 69 | if( pdklen<=0 ) 70 | return -2; //error reading input file 71 | fclose(fin); 72 | 73 | int32_t hdrlen = pdkhdrlen(pdk, pdklen); 74 | if( hdrlen<0 ) 75 | return -3; 76 | 77 | //pre init cpu to test if supported 78 | if( emuCPUinit(cpu, pdk, hdrlen, false) < 0 ) 79 | return -4; //no emulator found for cpu type 80 | 81 | if( (pdklen-hdrlen)>(cpu->maxCode*sizeof(uint16_t)) ) 82 | return -5; //code size to big 83 | 84 | memset( cpu->eCode, 0xFF, cpu->maxCode*sizeof(uint16_t) ); 85 | if( depdk( pdk, pdklen, (uint8_t*)cpu->eCode, cpu->maxCode*sizeof(uint16_t) ) < 0 ) 86 | return -6; //error decrypting input file 87 | 88 | //init cpu with loaded program 89 | if( emuCPUinit(cpu, pdk, hdrlen, fixupHighCode) < 0 ) 90 | return -7; //emulator error 91 | 92 | cpu->fnReset( cpu, true ); 93 | 94 | return 0; 95 | } 96 | 97 | int emuCPUloadBIN(struct emuCPU *cpu, const char *filename, bool fixupHighCode, uint16_t otp_id) 98 | { 99 | FILE* fin = fopen( filename, "rb"); 100 | if( !fin ) 101 | return -1; //could not open file 102 | 103 | uint8_t bin[10000]; 104 | int binlen =fread( bin, 1, sizeof(bin), fin ); 105 | if( binlen<=0 ) 106 | return -2; //error reading input file 107 | fclose(fin); 108 | 109 | //manually setup minimal cpu header 110 | memset( cpu, 0, sizeof(struct emuCPU) ); 111 | cpu->hdrlen = sizeof(cpu->hdr); 112 | cpu->hdr.otp_id = otp_id; 113 | 114 | //pre init cpu to test if supported 115 | if( emuCPUinit(cpu, 0, 0, false) < 0 ) 116 | return -4; //no emulator found for cpu type 117 | 118 | if( binlen>(cpu->maxCode*sizeof(uint16_t)) ) 119 | return -5; //code size to big 120 | 121 | memset( cpu->eCode, 0xFF, cpu->maxCode*sizeof(uint16_t) ); 122 | 123 | memcpy( cpu->eCode, bin, binlen ); 124 | cpu->hdr.codesize = binlen/sizeof(uint16_t); 125 | 126 | //init cpu with loaded program 127 | if( emuCPUinit(cpu, 0, 0, fixupHighCode) < 0 ) 128 | return -6; //no emulator found for cpu type 129 | 130 | cpu->fnReset( cpu, true ); 131 | 132 | return 0; 133 | } 134 | 135 | int emuCPUloadIHEX(struct emuCPU *cpu, const char *filename, uint16_t otp_id) 136 | { 137 | uint16_t bin[0x2000]; 138 | memset( bin, 0xff, 0x2000); 139 | if( FPDKIHEX8_ReadFile(filename, bin, 0x2000) < 0 ) 140 | return -1; //error reading input file 141 | 142 | //manually setup minimal cpu header 143 | memset( cpu, 0, sizeof(struct emuCPU) ); 144 | cpu->hdrlen = sizeof(cpu->hdr); 145 | cpu->hdr.otp_id = otp_id; 146 | 147 | //pre init cpu to test if supported 148 | if( emuCPUinit(cpu, 0, 0, false) < 0 ) 149 | return -4; //no emulator found for cpu type 150 | 151 | memset( cpu->eCode, 0xFF, cpu->maxCode*sizeof(uint16_t) ); 152 | 153 | uint32_t len = 0; 154 | for( uint32_t p=0; pmaxCode; p++) 155 | { 156 | if( (bin[p*2] & 0xFF00) || (bin[p*2+1] & 0xFF00) ) 157 | { 158 | cpu->eCode[p] = (bin[p*2]&0xFF) | ((bin[p*2+1]&0xFF)<<8); 159 | len = p + 1; 160 | } 161 | } 162 | 163 | //init cpu with loaded program 164 | if( emuCPUinit(cpu, 0, 0, false) < 0 ) 165 | return -6; //no emulator found for cpu type 166 | 167 | cpu->hdr.codesize = len; 168 | 169 | cpu->fnReset( cpu, true ); 170 | 171 | return 0; 172 | } 173 | 174 | 175 | 176 | void emuCPUexception(struct emuCPU *cpu, int code) 177 | { 178 | if( cpu->fnException ) 179 | cpu->fnException( cpu, code ); 180 | } 181 | 182 | uint8_t emuCPUioGet(struct emuCPU *cpu, uint8_t addr) 183 | { 184 | if( addrmaxIO ) 185 | { 186 | if( cpu->fnIORead ) 187 | return cpu->fnIORead(cpu, addr); 188 | else 189 | return cpu->eIO[addr]; 190 | } 191 | 192 | emuCPUexception(cpu, EXCEPTION_IO); //invalid io read 193 | return 0xFF; 194 | } 195 | 196 | void emuCPUioPut(struct emuCPU *cpu, uint8_t addr, uint8_t dat) 197 | { 198 | if( addrmaxIO ) 199 | { 200 | cpu->eIO[addr] = dat; 201 | if( cpu->fnIOWrite ) 202 | cpu->fnIOWrite( cpu, addr ); 203 | } 204 | else 205 | emuCPUexception(cpu, EXCEPTION_IO); //invalid io write 206 | } 207 | 208 | char* emuCPUdecodeIO(struct emuCPU *cpu, uint8_t addr, uint8_t bit, char* buffer) 209 | { 210 | if( cpu->fnIOName ) 211 | return cpu->fnIOName(cpu,addr,bit,buffer); 212 | 213 | *buffer = 0; 214 | return buffer; 215 | } 216 | 217 | 218 | 219 | uint8_t emuCPUmemGet(struct emuCPU *cpu, uint8_t addr) 220 | { 221 | if( addrmaxMem ) 222 | return cpu->eMem[addr]; 223 | 224 | emuCPUexception(cpu, EXCEPTION_MEMORY); //invalid memory read 225 | return 0xFF; 226 | } 227 | 228 | void emuCPUmemPut(struct emuCPU *cpu, uint8_t addr, uint8_t dat) 229 | { 230 | if( addrmaxMem ) 231 | cpu->eMem[addr] = dat; 232 | else 233 | emuCPUexception(cpu, EXCEPTION_MEMORY); //invalid memory write 234 | } 235 | 236 | uint16_t emuCPUcodeGet(struct emuCPU *cpu, uint16_t addr) 237 | { 238 | if( addrmaxCode ) 239 | return cpu->eCode[addr]; 240 | 241 | emuCPUexception(cpu, EXCEPTION_CODE); //invalid code read 242 | return 0xFFFF; 243 | } 244 | 245 | void emuCPUstackPush(struct emuCPU *cpu, uint8_t dat) 246 | { 247 | emuCPUmemPut( cpu, eSP++, dat ); 248 | } 249 | 250 | uint8_t emuCPUstackPop(struct emuCPU *cpu) 251 | { 252 | return emuCPUmemGet( cpu, --eSP ); 253 | } 254 | 255 | void emuCPUstackPushW(struct emuCPU *cpu, uint16_t dat) 256 | { 257 | emuCPUstackPush(cpu,dat); 258 | emuCPUstackPush(cpu,dat>>8); 259 | } 260 | 261 | uint16_t emuCPUstackPopW(struct emuCPU *cpu) 262 | { 263 | uint16_t dat; 264 | dat = emuCPUstackPop(cpu); 265 | dat <<= 8; 266 | dat |= emuCPUstackPop(cpu); 267 | return dat; 268 | } 269 | 270 | uint8_t emuCPUaddSolveFlagsVACZ(int16_t value1, int16_t value2, int16_t c) 271 | { 272 | int zr = !(((value1&0xFF)+(value2&0xFF)+c)&0xFF); 273 | int cy = (((value1&0xFF)+(value2&0xFF)+c)>>8)&1; 274 | int ac = (((value1&0xF)+(value2&0xF)+c)>>4)&1; 275 | int ov = ((((value1&0x7F)+(value2&0x7F)+c)>>7)&1)^cy; 276 | return( (ov<<3)|(ac<<2)|(cy<<1)|zr ); 277 | } 278 | 279 | uint8_t emuCPUsubSolveFlagsVACZ(int16_t value1, int16_t value2, int16_t c) 280 | { 281 | int zr = !(((value1&0xFF)-(value2&0xFF)-c)&0xFF); 282 | int cy = (((value1&0xFF)-(value2&0xFF)-c)>>8)&1; 283 | int ac = ((value1&0xF)<((value2&0xF)+c))?1:0; 284 | int ov = ((((value1&0x7F)-(value2&0x7F))>>7)&1)^cy; 285 | return( (ov<<3)|(ac<<2)|(cy<<1)|zr ); 286 | } 287 | -------------------------------------------------------------------------------- /emupdk.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "emucpu.h" 7 | 8 | void emuException(struct emuCPU *cpu, int code) 9 | { 10 | printf( "EXCEPTION: %d @0x%04x\n\n", ePC, code ); 11 | exit(0); 12 | } 13 | 14 | int main( int argc, const char * argv [] ) 15 | { 16 | if( (argc<2) || (argc>3) ) { 17 | printf("usage: %s [otpidhex] inputfile\n" 18 | "example: %s input.pdk\n" 19 | "example: %s 2AA1 input.bin\n" 20 | "example: %s 2AA1 input.ihex\n", 21 | argv[0], argv[0], argv[0], argv[0]); 22 | return 0; 23 | } 24 | 25 | struct emuCPU ecpu; 26 | struct emuCPU* cpu = &ecpu; 27 | 28 | if( 3 == argc ) 29 | { 30 | uint16_t otp_id; 31 | if( 1 != sscanf(argv[1], "%" SCNx16, &otp_id) ) 32 | { 33 | printf("Error wrong otp id: %s\n",argv[1]); 34 | return -1; 35 | } 36 | 37 | if( (emuCPUloadIHEX(cpu, argv[2], otp_id) < 0) && 38 | (emuCPUloadBIN(cpu, argv[2], false, otp_id) < 0) ) { 39 | printf("Error reading input file\n"); 40 | return -1; 41 | } 42 | } 43 | else 44 | { 45 | if( emuCPUloadPDK(cpu, argv[1], true) < 0 ) { 46 | printf("Error reading input file\n"); 47 | return -1; 48 | } 49 | } 50 | 51 | if( !cpu->fnReset || !cpu->fnExecute ) { 52 | printf("Missing emulator for this CPU\n"); 53 | return -2; 54 | } 55 | 56 | //set our own emulation exception handler 57 | cpu->fnException = emuException; 58 | 59 | //reset CPU 60 | cpu->fnReset(cpu,true); 61 | 62 | for( uint32_t i=0;i<2000;i++ ) 63 | { 64 | char disass[64] = ""; 65 | if( cpu->fnDisassemble ) 66 | cpu->fnDisassemble(cpu,ePC,disass); 67 | 68 | printf( "C:%10d A=0x%02x F=0x%02x SP=0x%02x PC=0x%04x: 0x%04x %s\n", eCycle, eA, eF, eSP, ePC, cpu->eCode[ePC]&0x3FFF, disass ); 69 | 70 | uint32_t oldPC = ePC; 71 | 72 | int rc = cpu->fnExecute(cpu); 73 | 74 | //todo: simulate peripherals 75 | 76 | if( 0 != rc ) 77 | break; 78 | 79 | //detect endless loop and stop 80 | if( oldPC == ePC ) 81 | break; 82 | } 83 | 84 | return 0; 85 | } 86 | -------------------------------------------------------------------------------- /ihex/fpdkihex8.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2019 freepdk https://free-pdk.github.io 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | #include "fpdkihex8.h" 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | static bool _X2UI8(const char* str, uint8_t* out) 26 | { 27 | char tmp[] = {str[0],str[1],0}; 28 | unsigned int r; 29 | if( 1 != sscanf(tmp, "%x", &r) ) 30 | return false; 31 | *out = r; 32 | return true; 33 | } 34 | 35 | static bool _FPDKIHEX8_ParseLine(const char* line, uint8_t* type, uint16_t* address, uint8_t* data, uint8_t* datcount) 36 | { 37 | uint8_t addrl, addrh; 38 | if( (strlen(line)<9) || (':' != line[0]) || 39 | !_X2UI8(&line[1], datcount) || !_X2UI8(&line[3], &addrh) || !_X2UI8(&line[5], &addrl) || !_X2UI8(&line[7], type) ) 40 | return false; 41 | *address = (((uint16_t)addrh)<<8) | addrl; 42 | 43 | uint8_t check; 44 | if( (strlen(line)<(9+2*(*datcount))) || !_X2UI8(&line[9+2*(*datcount)], &check) ) 45 | return false; 46 | check += (*datcount) + addrl + addrh + (*type); 47 | 48 | for( uint8_t p=0; p<(*datcount); p++ ) 49 | { 50 | if( !_X2UI8(&line[9+2*p], &data[p]) ) 51 | return false; 52 | check += data[p]; 53 | } 54 | return( 0 == check ); 55 | } 56 | 57 | static int _FPDKIHEX8_CreateLine(const uint8_t type, const uint16_t address, const uint8_t* data, const uint8_t datcount, char lineout[600]) 58 | { 59 | sprintf(lineout, ":%02X%04X%02X", datcount, address, type); 60 | uint8_t check = datcount + address + (address>>8) + type; 61 | char tmp[4]; 62 | for( uint8_t p=0; p1) ) 92 | { 93 | berr = true; 94 | break; 95 | } 96 | 97 | if( 1 == type ) 98 | break; 99 | 100 | if( (address+count) > datcount ) 101 | { 102 | berr = true; 103 | break; 104 | } 105 | 106 | for( uint8_t p=0; p=32 ) 136 | { 137 | int linelength = _FPDKIHEX8_CreateLine(0, lineaddr, data, lineitems, line); 138 | if( linelength != fwrite(line, 1, linelength, fout) ) 139 | { 140 | berr = true; 141 | break; 142 | } 143 | lineaddr += lineitems; 144 | lineitems = 0; 145 | } 146 | } 147 | 148 | int linelength = _FPDKIHEX8_CreateLine(1, 0, NULL, 0, line); 149 | if( linelength != fwrite(line, 1, linelength, fout) ) 150 | berr = true; 151 | 152 | fclose(fout); 153 | 154 | if( berr ) 155 | return -2; 156 | 157 | return 0; 158 | } 159 | -------------------------------------------------------------------------------- /include/cpuvariant.h: -------------------------------------------------------------------------------- 1 | #ifndef __INC_CPUVARIANT_H__ 2 | #define __INC_CPUVARIANT_H__ 3 | 4 | #include "emucpu.h" 5 | 6 | //void pmx130_init(struct emuCPU *cpu, bool fixupHighCode); 7 | 8 | void pmx150_init(struct emuCPU *cpu, bool fixupHighCode); 9 | 10 | void pmx154_init(struct emuCPU *cpu, bool fixupHighCode); 11 | 12 | void pmx173_init(struct emuCPU *cpu, bool fixupHighCode); 13 | 14 | int generic_init(struct emuCPU *cpu); 15 | 16 | 17 | #endif //__INC_CPUVARIANT_H__ 18 | -------------------------------------------------------------------------------- /include/disass.h: -------------------------------------------------------------------------------- 1 | #ifndef __INC_DISASS_H__ 2 | #define __INC_DISASS_H__ 3 | 4 | #include 5 | #include "emucpu.h" 6 | 7 | char* disass13(struct emuCPU *cpu, uint16_t position, char *buffer); 8 | char* disass14(struct emuCPU *cpu, uint16_t position, char *buffer); 9 | char* disass15(struct emuCPU *cpu, uint16_t position, char *buffer); 10 | char* disass16(struct emuCPU *cpu, uint16_t position, char *buffer); 11 | 12 | #endif //__INC_DISASS_H__ 13 | -------------------------------------------------------------------------------- /include/emucpu.h: -------------------------------------------------------------------------------- 1 | #ifndef __INC_EMUCPU_H__ 2 | #define __INC_EMUCPU_H__ 3 | 4 | #include 5 | #include 6 | 7 | #include "pdkformat.h" 8 | 9 | #define IO_MAX 64 10 | #define MEM_MAX 512 11 | #define CODEW_MAX 8192 12 | 13 | //flags: (1 1 1 1 V A C Z) 14 | 15 | #define eA cpu->eeA 16 | #define ePC cpu->eePC 17 | #define eF (*((volatile uint8_t*)&cpu->eIO[0x00])) 18 | #define eSP (*((volatile uint8_t*)&cpu->eIO[0x02])) 19 | #define eGINTEnabled cpu->eeGINTEnabled 20 | #define eInterruptActive cpu->eeInterruptActive 21 | #define eT16 cpu->eeT16 22 | #define eCycle cpu->eeCurrentCycle 23 | 24 | struct emuCPU; 25 | 26 | // reset cpu 27 | typedef void (*TemuCPUreset)(struct emuCPU *cpu, bool clearRAM); 28 | 29 | // execute next opcode: returns number of ticks the operation should take 30 | typedef int (*TemuCPUexecute)(struct emuCPU *cpu); 31 | 32 | // emulate peripherals 33 | typedef void (*TemuCPUperipherals)(struct emuCPU *cpu); 34 | 35 | // decodes opcode at position, and fills the buffer with the assembler code, returns string 36 | typedef char* (*TemuCPUdisassemble)(struct emuCPU *cpu, uint16_t position, char *buffer); 37 | 38 | // callback: some exceptional situation occurred. See CPU_EXCEPTION enum, below 39 | typedef void (*TemuCPUexception)(struct emuCPU *cpu, int code); 40 | 41 | // callback: an IO port is about to be read. Default is to return the value in IO register. Ports may act differently. 42 | typedef uint8_t (*TemuCPUioRead)(struct emuCPU *cpu, uint8_t port); 43 | 44 | // callback: an IO port has changed. Default is to do nothing. 45 | typedef void (*TemuCPUioWrite)(struct emuCPU *cpu, uint8_t port); 46 | 47 | // decodes IO name, and fills the buffer with the name / bitpos / ..., returns string 48 | typedef char* (*TemuCPUioName)(struct emuCPU *cpu, uint8_t io, uint8_t bit, char *buffer); 49 | 50 | 51 | struct emuCPU 52 | { 53 | struct T_PDK_HEADER hdr; //pdk header 54 | uint32_t hdrlen; 55 | 56 | uint8_t eIO[IO_MAX]; //io (special register) 57 | uint32_t maxIO; 58 | uint8_t eMem[MEM_MAX]; //memory (RAM) 59 | uint32_t maxMem; 60 | uint16_t eCode[CODEW_MAX]; //instruction words (ROM) 61 | uint32_t maxCode; 62 | 63 | uint32_t eePC; 64 | int16_t eeA; 65 | 66 | //eeF mapped with define to IO[0x00] (flags) 67 | //eeSP mapped with define to IO[0x02] (stack pointer) 68 | 69 | uint16_t eeT16; //timer T16 value 70 | 71 | bool eeGINTEnabled; //gloabl interrupt enabled 72 | bool eeInterruptActive; //internal status that cpu started interrupt 73 | 74 | uint32_t eeCurrentCycle; //keeps track of current CPU cycle (can be used to synchronize to real time) 75 | 76 | TemuCPUreset fnReset; 77 | TemuCPUexecute fnExecute; 78 | TemuCPUperipherals fnPeripherals; 79 | TemuCPUdisassemble fnDisassemble; 80 | TemuCPUexception fnException; 81 | TemuCPUioRead fnIORead; 82 | TemuCPUioWrite fnIOWrite; 83 | TemuCPUioName fnIOName; 84 | }; 85 | 86 | enum CPU_EXCEPTION 87 | { 88 | EXCEPTION_MEMORY, // illegal memory access 89 | EXCEPTION_IO, // illegal IO access 90 | EXCEPTION_CODE, // illegal code access 91 | EXCEPTION_IMEMORY, // indirect pointer outside of chip memory 92 | EXCEPTION_ILLEGAL_OPCODE // for the single 'reserved' opcode in the architecture 93 | }; 94 | 95 | //init cpu based on type set in cpu structure. Returns negative for errors. 96 | int emuCPUinit(struct emuCPU *cpu, uint8_t* hdr, uint32_t hdrlen, bool fixupHighCode); 97 | 98 | //load a PDK file. Returns negative for errors. 99 | int emuCPUloadPDK(struct emuCPU *cpu, const char *filename, bool fixupHighCode); 100 | 101 | //load a BIN file, rerquires OTP_ID as parameter to select CPU type. Returns negative for errors. 102 | int emuCPUloadBIN(struct emuCPU *cpu, const char *filename, bool fixupHighCode, uint16_t otp_id); 103 | 104 | //load a IHEX file, rerquires OTP_ID as parameter to select CPU type. Returns negative for errors. 105 | int emuCPUloadIHEX(struct emuCPU *cpu, const char *filename, uint16_t otp_id); 106 | 107 | //helper functions for all variants 108 | void emuCPUexception(struct emuCPU *cpu, int code); 109 | uint8_t emuCPUioGet(struct emuCPU *cpu, uint8_t addr); 110 | void emuCPUioPut(struct emuCPU *cpu, uint8_t addr, uint8_t dat); 111 | char* emuCPUdecodeIO(struct emuCPU *cpu, uint8_t addr, uint8_t bit, char* buffer); 112 | uint8_t emuCPUmemGet(struct emuCPU *cpu, uint8_t addr); 113 | void emuCPUmemPut(struct emuCPU *cpu, uint8_t addr, uint8_t dat); 114 | uint16_t emuCPUcodeGet(struct emuCPU *cpu, uint16_t addr); 115 | void emuCPUstackPush(struct emuCPU *cpu, uint8_t dat); 116 | uint8_t emuCPUstackPop(struct emuCPU *cpu); 117 | void emuCPUstackPushW(struct emuCPU *cpu, uint16_t dat); 118 | uint16_t emuCPUstackPopW(struct emuCPU *cpu); 119 | uint8_t emuCPUaddSolveFlagsVACZ(int16_t value1, int16_t value2, int16_t c); 120 | uint8_t emuCPUsubSolveFlagsVACZ(int16_t value1, int16_t value2, int16_t c); 121 | 122 | #endif // __INC_EMUCPU_H__ 123 | 124 | -------------------------------------------------------------------------------- /include/fpdkihex8.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2019 freepdk https://free-pdk.github.io 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | #ifndef __FPDKIHEX8_H_ 18 | #define __FPDKIHEX8_H_ 19 | 20 | #include 21 | 22 | int FPDKIHEX8_ReadFile(const char* filename, uint16_t* datout, const uint16_t datlen); 23 | int FPDKIHEX8_WriteFile(const char* filename, const uint8_t* datin, const uint16_t datlen); 24 | 25 | #endif //__FPDKIHEX8_H_ 26 | -------------------------------------------------------------------------------- /include/opcode.h: -------------------------------------------------------------------------------- 1 | #ifndef __INC_OPCODE_H__ 2 | #define __INC_OPCODE_H__ 3 | 4 | #include "emucpu.h" 5 | 6 | int opcode13(struct emuCPU *cpu); 7 | int opcode14(struct emuCPU *cpu); 8 | int opcode15(struct emuCPU *cpu); 9 | int opcode16(struct emuCPU *cpu); 10 | 11 | #endif //__INC_OPCODE_H__ 12 | -------------------------------------------------------------------------------- /include/pdkformat.h: -------------------------------------------------------------------------------- 1 | #ifndef __INC_PDKFORMAT_H__ 2 | #define __INC_PDKFORMAT_H__ 3 | 4 | #include 5 | 6 | #pragma pack(push,1) 7 | struct T_PDK_HEADER { 8 | uint32_t marker; //0x00 9 | uint32_t unk_0x04_1; //0x04 10 | uint32_t version; //0x08 11 | uint32_t checksum; //0x0C 12 | 13 | uint32_t tuning_freq_half; //0x10 14 | uint16_t unk_0x14_3; //0x14 15 | uint16_t tuning_voltage_mv; //0x16 16 | uint32_t unk_0x18_0x3F30; //0x18 17 | uint32_t unk_0x1C_0; //0x1C 18 | 19 | uint32_t codesize; //0x20 20 | uint16_t usable_codesize; //0x24 21 | uint16_t extra_length1; //0x26 22 | uint16_t extra_length2; //0x28 23 | uint16_t unk_0x2A_0; //0x2A 24 | uint16_t extra_length3; //0x2C 25 | uint16_t unk_0x2E_0; //0x2E 26 | 27 | uint8_t unk_0x30_0[0xC]; //0x30 28 | 29 | uint16_t otp_id; //0x3C 30 | uint8_t otp_way; //0x3E 31 | uint8_t boot_type; //0x3F 32 | 33 | uint8_t unk_0x40_0[9]; //0x40 34 | 35 | uint8_t extra_length_pinmap; //0x49 36 | 37 | uint8_t unk_0x4A_0[16]; //0x4A 38 | 39 | uint16_t remain_code_free; //0x5A 40 | 41 | uint16_t unk_0x5C; //0x5C 42 | uint16_t unk_0x5E_maybe_lvd; //0x5E 43 | 44 | uint8_t unk_0x60_0[0x20]; //0x60 45 | 46 | char mcu_name[16]; //0x80 47 | 48 | uint8_t unk_0x90_x[16]; //0x90 49 | 50 | char compiler[16]; //0xA0 51 | 52 | uint8_t unk_0xB0_0[32]; //0xB0 53 | 54 | uint16_t extra_length_4; //0xD0 55 | 56 | uint8_t unk_0xD2_0[14]; //0xD2 57 | 58 | uint8_t key[32]; //0xE0 59 | 60 | uint8_t extradata[256]; //0x100 61 | }; 62 | #pragma pack(pop) 63 | 64 | int32_t pdkhdrlen(uint8_t* datain, uint32_t datainlen); 65 | uint32_t pdkchecksum( uint8_t* datain, uint32_t datainlen, uint32_t initval); 66 | int32_t depdk(uint8_t* datain, uint32_t datainlen, uint8_t* dataout, uint32_t dataoutlen); 67 | int32_t enpdk(uint8_t* hdrin, uint32_t hdrinlen, uint8_t* datain, uint32_t datainlen, uint8_t* dataout, uint32_t dataoutlen); 68 | 69 | #endif //__INC_PDKFORMAT_H__ 70 | -------------------------------------------------------------------------------- /opcode/opcode13.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "emucpu.h" 5 | 6 | //execute next 13 bit opcode and advanced PC 7 | int opcode13(struct emuCPU *cpu) 8 | { 9 | emuCPUexception(cpu,EXCEPTION_ILLEGAL_OPCODE); 10 | return -1; 11 | } 12 | -------------------------------------------------------------------------------- /opcode/opcode14.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "emucpu.h" 5 | 6 | //execute next 14 bit opcode and advanced PC 7 | int opcode14(struct emuCPU *cpu) 8 | { 9 | int16_t T; //temp register 10 | uint16_t opcode = emuCPUcodeGet( cpu, ePC++ ) & 0x3FFF; //fetch next opcode and advance PC 11 | eCycle++; //increment current cycle counter 12 | 13 | //14 bit opcodes 0x0000 - 0x00BF 14 | if( opcode<=0x00BF ) 15 | { 16 | switch( opcode ) 17 | { 18 | case 0x0000: break; //NOP 19 | 20 | case 0x0006: eA=emuCPUcodeGet(cpu,emuCPUmemGet(cpu,eSP)|(((uint16_t)emuCPUmemGet(cpu,eSP+1))<<8))&0xFF; eCycle++; break; //LDSPTL //TODO: verify, Z? 21 | case 0x0007: eA=emuCPUcodeGet(cpu,emuCPUmemGet(cpu,eSP)|(((uint16_t)emuCPUmemGet(cpu,eSP+1))<<8))>>8; eCycle++; break; //LDSPTH //TODO: verify, Z? 22 | 23 | case 0x0060: T=(eF>>1)&1;eF=emuCPUaddSolveFlagsVACZ(eA,0,T); eA=(eA+T)&0xFF; break; //ADDC A 24 | case 0x0061: T=(eF>>1)&1;eF=emuCPUsubSolveFlagsVACZ(eA,0,T); eA=(eA-T)&0xFF; break; //SUBC A 25 | case 0x0062: eF=emuCPUaddSolveFlagsVACZ(eA, 1, 0); eA=(eA+1)&0xFF; if(!eA){ePC++; eCycle++;} break; //IZSN A 26 | case 0x0063: eF=emuCPUsubSolveFlagsVACZ(eA, 1, 0); eA=(eA-1)&0xFF; if(!eA){ePC++; eCycle++;} break; //DZSN A 27 | 28 | case 0x0067: ePC=(ePC-1)+eA; break; //PCADD A 29 | case 0x0068: eA=(~eA)&0xFF; eF=(eF&0xE)|(!eA); break; //NOT A 30 | case 0x0069: eA=(-((int8_t)eA))&0xFF; eF=(eF&0xE)|(!eA); break; //NEG A 31 | case 0x006A: eF=(eF&0xD)|((eA<<1)&2); eA>>=1; break; //SR A 32 | case 0x006B: eF=(eF&0xD)|((eA>>6)&2); eA=(eA<<1)&0xFF; break; //SL A 33 | case 0x006C: eA|=(eF&2)<<7; eF=(eF&0xD)|((eA<<1)&2); eA>>=1; break; //SRC A 34 | case 0x006D: T=(eF>>1)&1; eF=(eF&0xD)|((eA>>6)&2); eA=((eA<<1)&0xFF)|T; break; //SLC A 35 | case 0x006E: eA=((eA<<4)|(eA>>4))&0xFF; break; //SWAP A 36 | 37 | case 0x0070: /*TODO*/ break; //WDRESET 38 | 39 | case 0x0072: emuCPUstackPush(cpu,eA); emuCPUstackPush(cpu,eF); break; //PUSHAF 40 | case 0x0073: eF=emuCPUstackPop(cpu); eA=emuCPUstackPop(cpu); break; //POPAF 41 | 42 | case 0x0075: return 1; //RESET 43 | case 0x0076: ePC--; return 2; //STOPSYS 44 | case 0x0077: ePC--; return 3; //STOPEXE 45 | case 0x0078: eGINTEnabled=true; break; //ENGINT 46 | case 0x0079: eGINTEnabled=false; break; //DISGINT 47 | case 0x007A: ePC=emuCPUstackPopW(cpu); break; //RET 48 | case 0x007B: ePC=emuCPUstackPopW(cpu); eGINTEnabled=true; break; //RETI 49 | case 0x007C: /*TODO*/ break; //MUL 50 | 51 | default: 52 | emuCPUexception( cpu, EXCEPTION_ILLEGAL_OPCODE ); 53 | return -1; 54 | } 55 | } 56 | else 57 | //8 bit opcodes 0x00C0 - 0x01FF 58 | if( (opcode>=0x00C0) && (opcode<=0x01FF) ) 59 | { 60 | uint8_t addr = opcode&0x3F; 61 | switch( opcode&0x3FC0 ) 62 | { 63 | case 0x00C0: emuCPUioPut(cpu,addr,emuCPUioGet(cpu,addr)^eA);break; //XOR IO, A 64 | case 0x0180: emuCPUioPut(cpu,addr,eA);break; //MOV IO, A 65 | case 0x01C0: eA=emuCPUioGet(cpu,addr);eF=(eF&0xE)|(!eA);break; //MOV A, IO 66 | default: 67 | emuCPUexception(cpu,EXCEPTION_ILLEGAL_OPCODE); 68 | return -1; 69 | } 70 | } 71 | else 72 | //7 bit opcodes 0x03.. 73 | if( 0x0300 == (opcode&0x3F00) ) 74 | { 75 | uint8_t addr = opcode&0x7E; 76 | switch( opcode & 0x3F81 ) 77 | { 78 | case 0x0300: emuCPUmemPut(cpu, addr, eT16&0xFF); emuCPUmemPut(cpu, addr, eT16>>8); break; //STT16 M 79 | case 0x0301: eT16 = emuCPUmemGet(cpu, addr) | (((uint16_t)emuCPUmemGet(cpu, addr+1))<<8); break; //LDT16 M 80 | case 0x0380: T=emuCPUmemGet(cpu, addr); eCycle++; emuCPUmemPut(cpu, T,eA); break; //IDXM M,A 81 | case 0x0381: T=emuCPUmemGet(cpu, addr); eCycle++; eA=emuCPUmemGet(cpu, T); break; //IDXM A,M 82 | } 83 | } 84 | else 85 | //7 bit opcodes 0x0600 - 0x17FF 86 | if( (opcode>=0x0600) && (opcode<=0x17FF) ) 87 | { 88 | int8_t addr = opcode&0x7F; 89 | int16_t M = emuCPUmemGet(cpu, addr); 90 | switch( opcode & 0x3F80 ) 91 | { 92 | case 0x0600: eF=emuCPUsubSolveFlagsVACZ(eA,M,0); break; //COMP A, M 93 | case 0x0680: eF=emuCPUsubSolveFlagsVACZ(M,eA,0); break; //COMP M, A 94 | case 0x0700: eF=emuCPUaddSolveFlagsVACZ(eA,(-M)&0xFF,0); eA=(eA+((-M)&0xFF))&0xFF; break; //NADD A, M //TODO: verify 95 | case 0x0780: eF=emuCPUaddSolveFlagsVACZ(M,(-eA)&0xFF,0); M=(M+((-eA)&0xFF))&0xFF; break; //NADD M, A //TODO: verify 96 | case 0x0800: eF=emuCPUaddSolveFlagsVACZ(M,eA,0); emuCPUmemPut(cpu,addr,M+eA); break; //ADD M, A 97 | case 0x0880: eF=emuCPUsubSolveFlagsVACZ(M,eA,0); emuCPUmemPut(cpu,addr,M-eA); break; //SUB M, A 98 | case 0x0900: T=(eF>>1)&1;eF=emuCPUaddSolveFlagsVACZ(M,eA,T); emuCPUmemPut(cpu,addr,M+eA+T); break; //ADDC M, A 99 | case 0x0980: T=(eF>>1)&1;eF=emuCPUsubSolveFlagsVACZ(M,eA,T); emuCPUmemPut(cpu,addr,M-eA-T); break; //SUBC M, A 100 | case 0x0A00: M&=eA;emuCPUmemPut(cpu,addr,M);eF=(eF&0xE)|(!M); break; //AND M, A 101 | case 0x0A80: M|=eA;emuCPUmemPut(cpu,addr,M);eF=(eF&0xE)|(!M); break; //OR M, A 102 | case 0x0B00: M^=eA;emuCPUmemPut(cpu,addr,M);eF=(eF&0xE)|(!M); break; //XOR M, A 103 | case 0x0B80: emuCPUmemPut(cpu,addr,eA); break; //MOV M, A 104 | case 0x0C00: eF=emuCPUaddSolveFlagsVACZ(eA,M,0);eA=(eA+M)&0xFF; break; //ADD A, M 105 | case 0x0C80: eF=emuCPUsubSolveFlagsVACZ(eA,M,0);eA=(eA-M)&0xFF; break; //SUB A, M 106 | case 0x0D00: T=(eF>>1)&1;eF=emuCPUaddSolveFlagsVACZ(eA,M,T);eA=(eA+M+T)&0xFF; break; //ADDC A, M 107 | case 0x0D80: T=(eF>>1)&1;eF=emuCPUsubSolveFlagsVACZ(eA,M,T);eA=(eA-M-T)&0xFF; break; //SUBC A, M 108 | case 0x0E00: eA=eA&M;eF=(eF&0xE)|(!eA); break; //AND A, M 109 | case 0x0E80: eA=eA|M;eF=(eF&0xE)|(!eA); break; //OR A, M 110 | case 0x0F00: eA=eA^M;eF=(eF&0xE)|(!eA); break; //XOR A, M 111 | case 0x0F80: eA=M;eF=(eF&0xE)|(!eA); break; //MOV A, M 112 | case 0x1000: T=(eF>>1)&1;eF=emuCPUaddSolveFlagsVACZ(M,0,T); emuCPUmemPut(cpu,addr,M+T); break; //ADDC M 113 | case 0x1080: T=(eF>>1)&1;eF=emuCPUsubSolveFlagsVACZ(M,0,T); emuCPUmemPut(cpu,addr,M-T); break; //SUBC M 114 | case 0x1100: eF=emuCPUaddSolveFlagsVACZ(M,1,0);emuCPUmemPut(cpu,addr,M+1);if(!(eF&1)){ePC++;eCycle++;}break; //IZSN M 115 | case 0x1180: eF=emuCPUsubSolveFlagsVACZ(M,1,0);emuCPUmemPut(cpu,addr,M-1);if(!(eF&1)){ePC++;eCycle++;}break; //DZSN M 116 | case 0x1200: eF=emuCPUaddSolveFlagsVACZ(M,1,0);emuCPUmemPut(cpu,addr,M+1);break; //INC M 117 | case 0x1280: eF=emuCPUsubSolveFlagsVACZ(M,1,0);emuCPUmemPut(cpu,addr,M-1);break; //DEC M 118 | case 0x1300: emuCPUmemPut(cpu,addr,0); break; //CLEAR M 119 | case 0x1380: emuCPUmemPut(cpu,addr,eA); eA=M; break; //XCH A,M 120 | case 0x1400: M=(~M)&0xFF; eF=(eF&0xE)|(!M); emuCPUmemPut(cpu,addr,M); break; //NOT M 121 | case 0x1480: M=(-((int8_t)M))&0xFF; eF=(eF&0xE)|(!M); emuCPUmemPut(cpu,addr,M); break; //NEG M 122 | case 0x1500: eF=(eF&0xD)|((M<<1)&2); emuCPUmemPut(cpu,addr,M>>1); break; //SR M 123 | case 0x1580: eF=(eF&0xD)|((M>>6)&2); emuCPUmemPut(cpu,addr,M<<1); break; //SL M 124 | case 0x1600: M|=(eF&2)<<7; eF=(eF&0xD)|((M<<1)&2); emuCPUmemPut(cpu,addr,M>>1); break; //SRC M 125 | case 0x1680: T=(eF>>1)&1; eF=(eF&0xD)|((M>>6)&2); emuCPUmemPut(cpu,addr,(M<<1)|T); break; //SLC M 126 | case 0x1700: eF=emuCPUsubSolveFlagsVACZ(eA, M, 0); if( !((eA-M)&0xFF) ){ ePC++; eCycle++;} break; //CEQSN A,M 127 | case 0x1780: eF=emuCPUsubSolveFlagsVACZ(eA, M, 0); if( (eA-M)&0xFF ){ ePC++; eCycle++;} break; //CNEQSN A,M 128 | } 129 | } 130 | else 131 | //6 bit opcodes 0x02.. , 0x2800 - 0x2FFF 132 | if( (0x0200 == (opcode&0x3F00)) || (0x2800 == (opcode&0x3800)) ) 133 | { 134 | uint8_t k = opcode&0xFF; 135 | switch( opcode & 0x3F00 ) 136 | { 137 | case 0x0200: eA=k; ePC=emuCPUstackPopW(cpu); break; //RET k 138 | case 0x2800: eF=emuCPUaddSolveFlagsVACZ(eA, k, 0); eA=(eA+k)&0xFF; break; //ADD A,k 139 | case 0x2900: eF=emuCPUsubSolveFlagsVACZ(eA, k, 0); eA=(eA-k)&0xFF; break; //SUB A,k 140 | case 0x2A00: eF=emuCPUsubSolveFlagsVACZ(eA, k, 0); if( !((eA-k)&0xFF) ){ ePC++; eCycle++;} break; //CEQSN A,k 141 | case 0x2B00: eF=emuCPUsubSolveFlagsVACZ(eA, k, 0); if( (eA-k)&0xFF ){ ePC++; eCycle++;} break; //CNEQSN A,k 142 | case 0x2C00: eA &= k; eF=(eF&0xE)|(!eA); break; //AND A,k 143 | case 0x2D00: eA |= k; eF=(eF&0xE)|(!eA); break; //OR A,k 144 | case 0x2E00: eA ^= k; eF=(eF&0xE)|(!eA); break; //XOR A,k 145 | case 0x2F00: eA = k; break; //MOV A,k 146 | } 147 | } 148 | else 149 | //5 bit opcodes 0x0400 - 0x0500, 0x1800 - 0x27FF 150 | if( (0x0400 == (opcode&0x3E00)) || ((opcode>=0x1800) && (opcode<=0x27FF)) ) 151 | { 152 | uint8_t bit = 1<<((opcode>>6)&7); 153 | uint8_t addr = opcode&0x3F; 154 | switch( opcode & 0x3E00 ) 155 | { 156 | case 0x0400: T=emuCPUioGet(cpu,addr);emuCPUioPut(cpu,addr,eF&2?T|bit:T&~bit);eF=(eF&0xD)|((T&bit)?2:0); break; //SWAPC IO.n 157 | case 0x1800: if( !(emuCPUioGet(cpu,addr)&bit) ) { ePC++; eCycle++; } break; //T0SN IO.n 158 | case 0x1A00: if( emuCPUioGet(cpu,addr)&bit ) { ePC++; eCycle++; } break; //T1SN IO.n 159 | case 0x1C00: emuCPUioPut(cpu,addr,emuCPUioGet(cpu,addr)&~bit); break; //SET0 IO.n 160 | case 0x1E00: emuCPUioPut(cpu,addr,emuCPUioGet(cpu,addr)|bit); break; //SET1 IO.n 161 | case 0x2000: if( !(emuCPUmemGet(cpu,addr)&bit) ) { ePC++; eCycle++; } break; //T0SN M.n 162 | case 0x2200: if( emuCPUmemGet(cpu,addr)&bit ) { ePC++; eCycle++; } break; //T1SN M.n 163 | case 0x2400: emuCPUmemPut(cpu,addr,emuCPUmemGet(cpu,addr)&~bit);break; //SET0 M.n 164 | case 0x2600: emuCPUmemPut(cpu,addr,emuCPUmemGet(cpu,addr)|bit);break; //SET1 M.n 165 | } 166 | } 167 | else 168 | //3 bit opcodes 0x3000 - 0x3FFF 169 | if( (0x3000 == (opcode&0x3000)) ) 170 | { 171 | if( opcode & 0x0800 ) //CALL needs to put current PC on stack //CALL p 172 | emuCPUstackPushW(cpu,ePC); 173 | eCycle++; 174 | ePC = opcode & 0x07FF; //GOTO p 175 | } 176 | else 177 | { 178 | emuCPUexception( cpu, EXCEPTION_ILLEGAL_OPCODE ); 179 | return -1; 180 | } 181 | 182 | return 0; 183 | } 184 | -------------------------------------------------------------------------------- /opcode/opcode15.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "emucpu.h" 5 | 6 | //execute next 15 bit opcode and advanced PC 7 | int opcode15(struct emuCPU *cpu) 8 | { 9 | emuCPUexception(cpu,EXCEPTION_ILLEGAL_OPCODE); 10 | return -1; 11 | } 12 | -------------------------------------------------------------------------------- /opcode/opcode16.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "emucpu.h" 5 | 6 | //execute next 16 bit opcode and advanced PC 7 | int opcode16(struct emuCPU *cpu) 8 | { 9 | emuCPUexception(cpu,EXCEPTION_ILLEGAL_OPCODE); 10 | return -1; 11 | } 12 | -------------------------------------------------------------------------------- /pdkformat/pdkformat.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "pdkformat.h" 6 | 7 | int32_t pdkhdrlen(uint8_t* datain, uint32_t datainlen) 8 | { 9 | if( datainlen<0x100 ) 10 | return -1; 11 | 12 | uint8_t* hdrdata = datain; 13 | 14 | uint32_t version = *((uint32_t*)&hdrdata[0x08]); 15 | 16 | uint32_t marker = *((uint32_t*)&hdrdata[0x00]); 17 | 18 | if( 0xFFAA5512 != marker ) 19 | return -2; 20 | 21 | uint32_t extrahdr = *((uint16_t*)&hdrdata[0x26]) + 22 | *((uint16_t*)&hdrdata[0x28]) + 23 | *((uint16_t*)&hdrdata[0x2C]) + 24 | *((uint16_t*)&hdrdata[0xD0]); 25 | 26 | //package extra info (0 terminated ASCII string of pin names at end of header extra data) 27 | if( version>=0x1c ) 28 | extrahdr += hdrdata[0x49]; //length of the 0 terminated string (including terminating 0) 29 | 30 | return(0x100 + extrahdr); 31 | } 32 | 33 | uint32_t pdkchecksum( uint8_t* datain, uint32_t datainlen, uint32_t initval) 34 | { 35 | uint16_t* data = (uint16_t*)datain; 36 | 37 | uint32_t len = (datainlen >> 1) - 1; 38 | uint32_t csum = initval ^ data[len]; 39 | 40 | for(;len>0;) 41 | { 42 | len--; 43 | 44 | uint32_t v6 = *data++; 45 | uint32_t v5 = (v6 + len + (csum>>16))&0xFFFF; 46 | 47 | switch ( v5&7 ) 48 | { 49 | case 0: csum += v5 + (v6 << 8) + 1; break; 50 | case 1: csum ^= (v6 << 8) + v5 + 3; break; 51 | case 2: csum += 4 * v5; break; 52 | case 3: csum ^= 16 * v5; break; 53 | case 4: csum += 32 * v5; break; 54 | case 5: csum ^= (v6 >> 3) + (v5 << 6); break; 55 | case 6: csum += (v5 << 7) - (v6 >> 3); break; 56 | case 7: csum ^= v6 + (v5 << 8); break; 57 | } 58 | } 59 | return csum; 60 | } 61 | 62 | 63 | 64 | int32_t depdk(uint8_t* datain, uint32_t datainlen, uint8_t* dataout, uint32_t dataoutlen) 65 | { 66 | if( datainlen<0x100 ) 67 | return -1; 68 | 69 | uint8_t* hdrdata = datain; 70 | 71 | uint32_t version = *((uint32_t*)&hdrdata[0x08]); 72 | uint32_t datalen = *((uint32_t*)&hdrdata[0x20]); 73 | 74 | uint32_t extrahdr = *((uint16_t*)&hdrdata[0x26]) + 75 | *((uint16_t*)&hdrdata[0x28]) + 76 | *((uint16_t*)&hdrdata[0x2C]) + 77 | *((uint16_t*)&hdrdata[0xD0]); 78 | 79 | if( version>=0x1c ) 80 | extrahdr += hdrdata[0x49]; 81 | 82 | uint16_t key[0x10]; 83 | memcpy( key, &hdrdata[0xE0], sizeof(key) ); 84 | 85 | uint16_t kxorw7C92 = key[3]^key[14]; 86 | uint16_t kxorw7E8A = key[7]^key[15]; 87 | 88 | if( (version>=0x15) && (version<=0x17) ) { 89 | kxorw7C92 ^= 0x1234; kxorw7E8A ^= 0x5678; 90 | } 91 | if( version==0x1D ) { 92 | kxorw7C92 = key[4]^key[15]^0x1234; 93 | kxorw7E8A = key[8]^key[10]^0x57AE; 94 | } 95 | 96 | if( dataoutlen>1; 129 | kxorw7E8A = data[dataptr]; 130 | data[dataptr] = (data[dataptr] - tmp_xor_key1) ^ key[keyindex&0xF]; 131 | dataptr++; 132 | 133 | keyindex += kxorw7E8A; 134 | tmp_xor_key1 = data[dataptr]; 135 | data[dataptr] ^= key[keyindex&0xF]; 136 | dataptr++; 137 | key[kxorw7C92&0xF] += kxorw7E8A; 138 | 139 | keyindex ^= tmp_xor_key1; 140 | tmp_xor_key2 = data[dataptr]; 141 | data[dataptr] = (data[dataptr] ^ kxorw7E8A) ^ key[keyindex&0xF]; 142 | dataptr++; 143 | key[tmp_xor_key2&0xF] ^= tmp_xor_key1; 144 | 145 | keyindex ^= tmp_xor_key2; 146 | kxorw7C92 = data[dataptr]; 147 | data[dataptr] += key[keyindex&0xF]; 148 | dataptr++; 149 | key[tmp_xor_key1&0xF] += tmp_xor_key2; 150 | 151 | keyindex += kxorw7C92; 152 | kxorw7E8A = data[dataptr]; 153 | data[dataptr] = (data[dataptr] + tmp_xor_key1) ^ key[keyindex&0xF]; 154 | dataptr++; 155 | 156 | key[2] ^= tmp_xor_key1; 157 | key[4] += tmp_xor_key2; 158 | key[6] += kxorw7E8A; 159 | key[8] -= kxorw7C92; 160 | key[1] ^= key[15]; 161 | key[3] ^= key[14]; 162 | key[5] ^= key[13]; 163 | keyindex += j; 164 | } 165 | 166 | memcpy( dataout + fullpos*2, data, sizeof(data) ); 167 | } 168 | 169 | return datalen*2; 170 | } 171 | 172 | int32_t enpdk(uint8_t* hdrin, uint32_t hdrinlen, uint8_t* datain, uint32_t datainlen, uint8_t* dataout, uint32_t dataoutlen) 173 | { 174 | if( hdrinlen<0x100 ) 175 | return -1; 176 | 177 | uint8_t* hdrdata = datain; 178 | 179 | uint32_t version = *((uint32_t*)&hdrdata[0x08]); 180 | uint32_t datalen = *((uint32_t*)&hdrdata[0x20]); 181 | 182 | uint32_t extrahdr = *((uint16_t*)&hdrdata[0x26]) + 183 | *((uint16_t*)&hdrdata[0x28]) + 184 | *((uint16_t*)&hdrdata[0x2C]) + 185 | *((uint16_t*)&hdrdata[0xD0]); 186 | 187 | if( version>=0x1c ) 188 | extrahdr += hdrdata[0x49]; 189 | 190 | uint16_t key[0x10]; 191 | memcpy( key, &hdrdata[0xE0], sizeof(key) ); 192 | 193 | uint16_t kxorw7C92 = key[3]^key[14]; 194 | uint16_t kxorw7E8A = key[7]^key[15]; 195 | 196 | if( (version>=0x15) && (version<=0x17) ) { 197 | kxorw7C92 ^= 0x1234; kxorw7E8A ^= 0x5678; 198 | } 199 | 200 | if( dataoutlen < (hdrinlen+datalen) ) 201 | return -2; 202 | 203 | if( hdrinlen != (0x100 + extrahdr) ) 204 | return -3; 205 | 206 | memcpy( dataout, hdrdata, hdrinlen ); 207 | 208 | uint16_t keyindex = 0; 209 | 210 | for( uint32_t fullpos=0; fullpos>1; 235 | kxorw7E8A = (data[dataptr] ^ key[keyindex&0xF]) + tmp_xor_key1; 236 | data[dataptr] = kxorw7E8A; 237 | dataptr++; 238 | 239 | keyindex += kxorw7E8A; 240 | tmp_xor_key1 = data[dataptr] ^ key[keyindex&0xF]; 241 | data[dataptr] = tmp_xor_key1; 242 | dataptr++; 243 | key[kxorw7C92&0xF] += kxorw7E8A; 244 | 245 | keyindex ^= tmp_xor_key1; 246 | tmp_xor_key2 = (data[dataptr] ^ key[keyindex&0xF]) ^ kxorw7E8A; 247 | data[dataptr] = tmp_xor_key2; 248 | dataptr++; 249 | key[tmp_xor_key2&0xF] ^= tmp_xor_key1; 250 | 251 | keyindex ^= tmp_xor_key2; 252 | kxorw7C92 = data[dataptr] - key[keyindex&0xF]; 253 | data[dataptr] = kxorw7C92; 254 | dataptr++; 255 | key[tmp_xor_key1&0xF] += tmp_xor_key2; 256 | 257 | keyindex += kxorw7C92; 258 | kxorw7E8A = (data[dataptr] ^ key[keyindex&0xF]) - tmp_xor_key1; 259 | data[dataptr] = kxorw7E8A; 260 | dataptr++; 261 | 262 | key[2] ^= tmp_xor_key1; 263 | key[4] += tmp_xor_key2; 264 | key[6] += kxorw7E8A; 265 | key[8] -= kxorw7C92; 266 | key[1] ^= key[15]; 267 | key[3] ^= key[14]; 268 | key[5] ^= key[13]; 269 | keyindex += j; 270 | } 271 | 272 | memcpy( dataout + hdrinlen + fullpos*2, data, sizeof(data) ); 273 | } 274 | 275 | return hdrinlen + datalen*2; 276 | } 277 | --------------------------------------------------------------------------------