├── testcases ├── block0 │ ├── Readme.md │ ├── testcase00e │ ├── testcase00f │ ├── testcase010 │ ├── testcase011 │ ├── testcase012 │ ├── testcase012.asm │ ├── testcase013 │ ├── testcase014 │ ├── testcase015 │ ├── testcase016 │ ├── testcase017 │ ├── testcase013.asm │ ├── testcase016.asm │ ├── testcase011.asm │ ├── testcase00f.asm │ ├── testcase010.asm │ ├── testcase014.asm │ ├── testcase00e.asm │ ├── testcase017.asm │ └── testcase015.asm ├── block1 │ ├── Readme.md │ ├── testcase000.asm │ ├── testcase000 │ ├── testcase001 │ ├── testcase002 │ ├── testcase003 │ ├── testcase004 │ ├── testcase005 │ ├── testcase006 │ ├── testcase001.asm │ ├── testcase002.asm │ ├── testcase006.asm │ ├── testcase003.asm │ ├── testcase004.asm │ └── testcase005.asm ├── block2 │ ├── Readme.md │ ├── testcase007 │ ├── testcase008 │ ├── testcase009 │ ├── testcase00a │ ├── testcase00b │ ├── testcase00c │ ├── testcase00d │ ├── testcase008.asm │ ├── testcase007.asm │ ├── testcase009.asm │ ├── testcase00a.asm │ ├── testcase00d.asm │ ├── testcase00c.asm │ └── testcase00b.asm ├── block3 │ ├── Readme.md │ ├── testcase018 │ ├── testcase019 │ ├── testcase01a │ ├── testcase01b │ ├── testcase01c │ ├── testcase01d │ ├── testcase01e │ ├── testcase01f │ ├── testcase020 │ ├── testcase021 │ ├── testcase022 │ ├── testcase023 │ ├── testcase024 │ ├── testcase025 │ ├── testcase026 │ ├── testcase027 │ ├── testcase028 │ ├── testcase029 │ ├── testcase02a │ ├── testcase02b │ ├── testcase02c │ ├── testcase02d │ ├── testcase02e │ ├── testcase02f │ ├── testcase030 │ ├── testcase031 │ ├── testcase021.asm │ ├── testcase02f.asm │ ├── testcase031.asm │ ├── testcase02c.asm │ ├── testcase02e.asm │ ├── testcase030.asm │ ├── testcase02d.asm │ ├── testcase01b.asm │ ├── testcase01c.asm │ ├── testcase018.asm │ ├── testcase01d.asm │ ├── testcase01f.asm │ ├── testcase019.asm │ ├── testcase022.asm │ ├── testcase023.asm │ ├── testcase01a.asm │ ├── testcase024.asm │ ├── testcase025.asm │ ├── testcase026.asm │ ├── testcase027.asm │ ├── testcase028.asm │ ├── testcase029.asm │ ├── testcase02a.asm │ ├── testcase02b.asm │ ├── testcase01e.asm │ └── testcase020.asm ├── block4 │ ├── Readme.md │ ├── testcase032 │ ├── testcase033 │ ├── testcase034 │ ├── testcase035 │ ├── testcase036 │ ├── testcase034.c │ ├── testcase034.asm │ ├── testcase036.asm │ ├── testcase035.asm │ ├── testcase036.c │ ├── testcase032.c │ ├── testcase032.asm │ ├── testcase035.c │ ├── testcase033.c │ └── testcase033.asm └── Readme.md ├── bin ├── Nightfall └── Readme.md ├── how-to-make ├── 8080 Programmers Manual.pdf └── Readme.md ├── src ├── Makefile ├── Readme.md ├── mov.c ├── stack.c ├── codeExec.c ├── debugUtils.c ├── flagSet.c ├── Nightfall.c ├── utills.c ├── math.c ├── Nightfall.h ├── debugCmds.c ├── disass.c └── emulate.c ├── README.md └── disassembler ├── disassemble.py └── Readme.md /testcases/block0/Readme.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /testcases/block1/Readme.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /testcases/block2/Readme.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /testcases/block3/Readme.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /testcases/block4/Readme.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /testcases/block1/testcase000.asm: -------------------------------------------------------------------------------- 1 | 0x0: mvi b, 0xde 2 | 0x2: end 0x66 3 | -------------------------------------------------------------------------------- /bin/Nightfall: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/bin/Nightfall -------------------------------------------------------------------------------- /bin/Readme.md: -------------------------------------------------------------------------------- 1 | # Bin 2 | 3 | Here is just a copy of the source code compiled, as a `64` bit elf. 4 | -------------------------------------------------------------------------------- /testcases/block0/testcase00e: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block0/testcase00e -------------------------------------------------------------------------------- /testcases/block0/testcase00f: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block0/testcase00f -------------------------------------------------------------------------------- /testcases/block0/testcase010: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block0/testcase010 -------------------------------------------------------------------------------- /testcases/block0/testcase011: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block0/testcase011 -------------------------------------------------------------------------------- /testcases/block0/testcase012: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block0/testcase012 -------------------------------------------------------------------------------- /testcases/block0/testcase012.asm: -------------------------------------------------------------------------------- 1 | 0x0: mvi a, 0xaa 2 | 0x2: daa 3 | 0x3: stc 4 | 0x4: rlc 5 | 0x5: ral 6 | 0x6: end 0x66 7 | -------------------------------------------------------------------------------- /testcases/block0/testcase013: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block0/testcase013 -------------------------------------------------------------------------------- /testcases/block0/testcase014: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block0/testcase014 -------------------------------------------------------------------------------- /testcases/block0/testcase015: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block0/testcase015 -------------------------------------------------------------------------------- /testcases/block0/testcase016: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block0/testcase016 -------------------------------------------------------------------------------- /testcases/block0/testcase017: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block0/testcase017 -------------------------------------------------------------------------------- /testcases/block1/testcase000: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block1/testcase000 -------------------------------------------------------------------------------- /testcases/block1/testcase001: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block1/testcase001 -------------------------------------------------------------------------------- /testcases/block1/testcase002: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block1/testcase002 -------------------------------------------------------------------------------- /testcases/block1/testcase003: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block1/testcase003 -------------------------------------------------------------------------------- /testcases/block1/testcase004: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block1/testcase004 -------------------------------------------------------------------------------- /testcases/block1/testcase005: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block1/testcase005 -------------------------------------------------------------------------------- /testcases/block1/testcase006: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block1/testcase006 -------------------------------------------------------------------------------- /testcases/block2/testcase007: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block2/testcase007 -------------------------------------------------------------------------------- /testcases/block2/testcase008: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block2/testcase008 -------------------------------------------------------------------------------- /testcases/block2/testcase009: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block2/testcase009 -------------------------------------------------------------------------------- /testcases/block2/testcase00a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block2/testcase00a -------------------------------------------------------------------------------- /testcases/block2/testcase00b: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block2/testcase00b -------------------------------------------------------------------------------- /testcases/block2/testcase00c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block2/testcase00c -------------------------------------------------------------------------------- /testcases/block2/testcase00d: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block2/testcase00d -------------------------------------------------------------------------------- /testcases/block3/testcase018: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block3/testcase018 -------------------------------------------------------------------------------- /testcases/block3/testcase019: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block3/testcase019 -------------------------------------------------------------------------------- /testcases/block3/testcase01a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block3/testcase01a -------------------------------------------------------------------------------- /testcases/block3/testcase01b: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block3/testcase01b -------------------------------------------------------------------------------- /testcases/block3/testcase01c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block3/testcase01c -------------------------------------------------------------------------------- /testcases/block3/testcase01d: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block3/testcase01d -------------------------------------------------------------------------------- /testcases/block3/testcase01e: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block3/testcase01e -------------------------------------------------------------------------------- /testcases/block3/testcase01f: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block3/testcase01f -------------------------------------------------------------------------------- /testcases/block3/testcase020: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block3/testcase020 -------------------------------------------------------------------------------- /testcases/block3/testcase021: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block3/testcase021 -------------------------------------------------------------------------------- /testcases/block3/testcase022: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block3/testcase022 -------------------------------------------------------------------------------- /testcases/block3/testcase023: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block3/testcase023 -------------------------------------------------------------------------------- /testcases/block3/testcase024: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block3/testcase024 -------------------------------------------------------------------------------- /testcases/block3/testcase025: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block3/testcase025 -------------------------------------------------------------------------------- /testcases/block3/testcase026: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block3/testcase026 -------------------------------------------------------------------------------- /testcases/block3/testcase027: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block3/testcase027 -------------------------------------------------------------------------------- /testcases/block3/testcase028: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block3/testcase028 -------------------------------------------------------------------------------- /testcases/block3/testcase029: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block3/testcase029 -------------------------------------------------------------------------------- /testcases/block3/testcase02a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block3/testcase02a -------------------------------------------------------------------------------- /testcases/block3/testcase02b: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block3/testcase02b -------------------------------------------------------------------------------- /testcases/block3/testcase02c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block3/testcase02c -------------------------------------------------------------------------------- /testcases/block3/testcase02d: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block3/testcase02d -------------------------------------------------------------------------------- /testcases/block3/testcase02e: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block3/testcase02e -------------------------------------------------------------------------------- /testcases/block3/testcase02f: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block3/testcase02f -------------------------------------------------------------------------------- /testcases/block3/testcase030: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block3/testcase030 -------------------------------------------------------------------------------- /testcases/block3/testcase031: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block3/testcase031 -------------------------------------------------------------------------------- /testcases/block4/testcase032: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block4/testcase032 -------------------------------------------------------------------------------- /testcases/block4/testcase033: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block4/testcase033 -------------------------------------------------------------------------------- /testcases/block4/testcase034: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block4/testcase034 -------------------------------------------------------------------------------- /testcases/block4/testcase035: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block4/testcase035 -------------------------------------------------------------------------------- /testcases/block4/testcase036: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/testcases/block4/testcase036 -------------------------------------------------------------------------------- /testcases/block3/testcase021.asm: -------------------------------------------------------------------------------- 1 | 0x0: call 0x08 2 | 0x3: end 0x66 3 | 0x5: inr a 4 | 0x6: inr a 5 | 0x7: inr a 6 | 0x8: ret 7 | -------------------------------------------------------------------------------- /testcases/block3/testcase02f.asm: -------------------------------------------------------------------------------- 1 | 0x0: mvi h, 0x0 2 | 0x2: mvi l, 0x6 3 | 0x4: pchl 4 | 0x5: inr a 5 | 0x6: nop 6 | 0x7: end 0x66 7 | -------------------------------------------------------------------------------- /testcases/block3/testcase031.asm: -------------------------------------------------------------------------------- 1 | 0x0: ori 0x66 2 | 0x2: ani 0xd6 3 | 0x5: inr m 4 | 0x7: mov m, d 5 | 0x8: nop 6 | 0x9: end 0x66 7 | -------------------------------------------------------------------------------- /testcases/block3/testcase02c.asm: -------------------------------------------------------------------------------- 1 | 0x0: out 0x66 2 | 0x3: mov h, m 3 | 0x4: di 4 | 0x5: nop 5 | 0x6: ei 6 | 0x7: nop 7 | 0x8: end 0x66 8 | -------------------------------------------------------------------------------- /testcases/block3/testcase02e.asm: -------------------------------------------------------------------------------- 1 | 0x0: mvi h, 0x0 2 | 0x2: mvi l, 0x55 3 | 0x4: sphl 4 | 0x5: push h 5 | 0x6: nop 6 | 0x7: end 0x66 7 | -------------------------------------------------------------------------------- /testcases/block3/testcase030.asm: -------------------------------------------------------------------------------- 1 | 0x0: adi 0x7c 2 | 0x2: aci 0x47 3 | 0x4: sui 0xcb 4 | 0x6: sbi 0x2a 5 | 0x8: nop 6 | 0x9: end 0x66 7 | -------------------------------------------------------------------------------- /testcases/block1/testcase001.asm: -------------------------------------------------------------------------------- 1 | 0x0: mvi d, 0xde 2 | 0x2: mov c, d 3 | 0x3: mov e, c 4 | 0x4: mov b, l 5 | 0x5: mov d, b 6 | 0x6: end 0x66 7 | -------------------------------------------------------------------------------- /how-to-make/8080 Programmers Manual.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guyinatuxedo/Nightfall-Emulator/HEAD/how-to-make/8080 Programmers Manual.pdf -------------------------------------------------------------------------------- /testcases/block0/testcase013.asm: -------------------------------------------------------------------------------- 1 | 0x0: lxi b 0x7295 2 | 0x3: lxi d 0xadde 3 | 0x7: shld 0x922 4 | 0xa: dad d 5 | 0xb: dad h 6 | 0xc: dad sp 7 | 0xd: end 0x66 8 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | all: Nightfall.c 2 | gcc Nightfall.c emulate.c debugCmds.c disass.c flagSet.c math.c stack.c utills.c debugUtils.c codeExec.c mov.c -o Nightfall 3 | clean: 4 | $(RM) Nightfall 5 | -------------------------------------------------------------------------------- /testcases/block0/testcase016.asm: -------------------------------------------------------------------------------- 1 | 0x0: mvi a, 0x66 2 | 0x2: rlc 3 | 0x3: rrc 4 | 0x4: cmc 5 | 0x5: ral 6 | 0x6: mvi a, 0x5f 7 | 0x8: cmc 8 | 0x9: rar 9 | 0xa: cma 10 | 0xb: end 0x66 11 | -------------------------------------------------------------------------------- /testcases/block3/testcase02d.asm: -------------------------------------------------------------------------------- 1 | 0x0: mvi h, 0x15 2 | 0x2: mvi l, 0x93 3 | 0x4: mvi d, 0x57 4 | 0x6: mvi e, 0x28 5 | 0x8: xchg 6 | 0x9: push d 7 | 0xa: xthl 8 | 0xb: nop 9 | 0xc: end 0x66 10 | -------------------------------------------------------------------------------- /testcases/block0/testcase011.asm: -------------------------------------------------------------------------------- 1 | 0x0: nop 2 | 0x1: nop 3 | 0x2: nop 4 | 0x3: nop 5 | 0x4: nop 6 | 0x5: lxi b 0x31 7 | 0x8: lxi d 0xbc3a 8 | 0xb: lxi h 0x6666 9 | 0xf: dcr d 10 | 0x10: sub e 11 | 0x11: end 0x66 12 | -------------------------------------------------------------------------------- /testcases/block0/testcase00f.asm: -------------------------------------------------------------------------------- 1 | 0x0: mvi b, 0x66 2 | 0x2: mvi c, 0x34 3 | 0x4: mvi d, 0x74 4 | 0x6: mvi e, 0x24 5 | 0x8: mvi h, 0xde 6 | 0xa: mvi l, 0x1 7 | 0xc: mvi m, 0x99 8 | 0xe: mvi a, 0x45 9 | 0x10: mov b, m 10 | 0x11: end 0x66 11 | -------------------------------------------------------------------------------- /testcases/block3/testcase01b.asm: -------------------------------------------------------------------------------- 1 | 0x0: jmp 0x08 2 | 0x3: inr a 3 | 0x4: inr a 4 | 0x5: inr a 5 | 0x6: inr a 6 | 0x7: inr a 7 | 0x8: out 0x0 8 | 0xa: mvi b, 0x15 9 | 0xc: mvi c, 0x93 10 | 0xe: push b 11 | 0xf: xthl 12 | 0x10: di 13 | 0x11: nop 14 | 0x12: end 0x66 15 | -------------------------------------------------------------------------------- /testcases/block3/testcase01c.asm: -------------------------------------------------------------------------------- 1 | 0x0: call 0x0a 2 | 0x3: dcr a 3 | 0x4: dcr a 4 | 0x5: dcr a 5 | 0x6: dcr a 6 | 0x7: dcr a 7 | 0x8: end 0x66 8 | 0xa: inr a 9 | 0xb: inr a 10 | 0xc: inr a 11 | 0xd: inr a 12 | 0xe: inr a 13 | 0xf: ret 14 | 0x10: nop 15 | 0x11: nop 16 | -------------------------------------------------------------------------------- /testcases/block3/testcase018.asm: -------------------------------------------------------------------------------- 1 | 0x0: mvi b, 0xde 2 | 0x2: mvi c, 0xad 3 | 0x4: mvi d, 0xbe 4 | 0x6: mvi e, 0xef 5 | 0x8: mvi h, 0x15 6 | 0xa: mvi l, 0x93 7 | 0xc: mvi a, 0x66 8 | 0xe: push b 9 | 0xf: push d 10 | 0x10: push h 11 | 0x11: push psw 12 | 0x12: end 0x66 13 | -------------------------------------------------------------------------------- /testcases/block1/testcase002.asm: -------------------------------------------------------------------------------- 1 | 0x0: mvi h, 0x66 2 | 0x2: mov b, h 3 | 0x3: mov a, b 4 | 0x4: mov c, a 5 | 0x5: mov e, c 6 | 0x6: mov d, e 7 | 0x7: mvi b, 0x0 8 | 0x9: mov b, b 9 | 0xa: mov a, b 10 | 0xb: mov a, a 11 | 0xc: mov d, c 12 | 0xd: mov d, d 13 | 0xe: mov c, c 14 | 0xf: end 0x66 15 | -------------------------------------------------------------------------------- /testcases/block0/testcase010.asm: -------------------------------------------------------------------------------- 1 | 0x0: mvi b, 0x36 2 | 0x2: mvi c, 0x72 3 | 0x4: mvi d, 0xb7 4 | 0x6: mvi e, 0xff 5 | 0x8: mvi h, 0xff 6 | 0xa: mvi l, 0xff 7 | 0xc: inx b 8 | 0xd: inx d 9 | 0xe: inx h 10 | 0xf: inx sp 11 | 0x10: inr c 12 | 0x11: dcx d 13 | 0x12: dcx h 14 | 0x13: dcx sp 15 | 0x14: end 0x66 16 | -------------------------------------------------------------------------------- /testcases/block1/testcase006.asm: -------------------------------------------------------------------------------- 1 | 0x0: mvi d, 0x66 2 | 0x2: mov h, d 3 | 0x3: mvi e, 0x13 4 | 0x5: mov h, e 5 | 0x6: mov c, e 6 | 0x7: mov e, h 7 | 0x8: mov l, e 8 | 0x9: mov a, h 9 | 0xa: mov a, c 10 | 0xb: mov l, b 11 | 0xc: mov l, c 12 | 0xd: mov h, l 13 | 0xe: mov l, a 14 | 0xf: hlt 15 | 0x10: end 0x66 16 | -------------------------------------------------------------------------------- /testcases/block1/testcase003.asm: -------------------------------------------------------------------------------- 1 | 0x0: mvi c, 0x66 2 | 0x2: mov b, c 3 | 0x3: mov h, b 4 | 0x4: mov l, h 5 | 0x5: mov e, l 6 | 0x6: mov a, e 7 | 0x7: mov d, a 8 | 0x8: mvi a, 0x0 9 | 0xa: mov h, a 10 | 0xb: mov e, a 11 | 0xc: mov c, h 12 | 0xd: mov e, e 13 | 0xe: mov l, l 14 | 0xf: mov h, h 15 | 0x10: end 0x66 16 | -------------------------------------------------------------------------------- /testcases/block0/testcase014.asm: -------------------------------------------------------------------------------- 1 | 0x0: mvi a, 0x10 2 | 0x2: mvi b, 0x20 3 | 0x4: mvi c, 0x20 4 | 0x6: stax b 5 | 0x7: mvi a, 0x20 6 | 0x9: mvi d, 0x40 7 | 0xb: mvi e, 0x40 8 | 0xd: stax d 9 | 0xe: mvi h, 0x30 10 | 0x10: mvi l, 0x30 11 | 0x12: shld 0x6060 12 | 0x15: mvi a, 0x90 13 | 0x17: sta 0x9090 14 | 0x1a: end 0x66 15 | -------------------------------------------------------------------------------- /testcases/block2/testcase008.asm: -------------------------------------------------------------------------------- 1 | 0x0: mvi b, 0xad 2 | 0x2: mvi c, 0xde 3 | 0x4: mvi d, 0x7f 4 | 0x6: mvi e, 0x30 5 | 0x8: mvi h, 0x20 6 | 0xa: mvi l, 0x20 7 | 0xc: mvi m, 0x66 8 | 0xe: adc m 9 | 0xf: adc b 10 | 0x10: adc c 11 | 0x11: adc d 12 | 0x12: adc e 13 | 0x13: adc h 14 | 0x14: adc l 15 | 0x15: adc a 16 | 0x16: end 0x66 17 | -------------------------------------------------------------------------------- /testcases/block3/testcase01d.asm: -------------------------------------------------------------------------------- 1 | 0x0: mvi b, 0x0 2 | 0x2: mvi c, 0x0 3 | 0x4: push b 4 | 0x5: pop psw 5 | 0x6: cz 0x00 6 | 0x9: cc 0x00 7 | 0xc: cpe 0x00 8 | 0xf: cm 0x00 9 | 0x12: call 0x017 10 | 0x15: end 0x66 11 | 0x17: nop 12 | 0x18: nop 13 | 0x19: nop 14 | 0x1a: rz 15 | 0x1b: rc 16 | 0x1c: rpe 17 | 0x1d: rm 18 | 0x1e: ret 19 | -------------------------------------------------------------------------------- /testcases/block3/testcase01f.asm: -------------------------------------------------------------------------------- 1 | 0x0: mvi b, 0xff 2 | 0x2: mvi c, 0xff 3 | 0x4: push b 4 | 0x5: pop psw 5 | 0x6: cnz 0x00 6 | 0x9: cnc 0x00 7 | 0xc: cpo 0x00 8 | 0xf: cp 0x00 9 | 0x12: call 0x017 10 | 0x15: end 0x66 11 | 0x17: nop 12 | 0x18: nop 13 | 0x19: nop 14 | 0x1a: rnz 15 | 0x1b: rnc 16 | 0x1c: rpo 17 | 0x1d: rp 18 | 0x1e: ret 19 | -------------------------------------------------------------------------------- /testcases/block2/testcase007.asm: -------------------------------------------------------------------------------- 1 | 0x0: mvi b, 0x4 2 | 0x2: mvi c, 0x10 3 | 0x4: mvi d, 0x88 4 | 0x6: mvi e, 0xba 5 | 0x8: mvi h, 0x5 6 | 0xa: mvi l, 0x6 7 | 0xc: mvi m, 0x27 8 | 0xe: mvi a, 0x4 9 | 0x10: add b 10 | 0x11: add c 11 | 0x12: add d 12 | 0x13: add e 13 | 0x14: add h 14 | 0x15: add l 15 | 0x16: add m 16 | 0x17: add a 17 | 0x18: end 0x66 18 | -------------------------------------------------------------------------------- /testcases/block2/testcase009.asm: -------------------------------------------------------------------------------- 1 | 0x0: mvi b, 0xab 2 | 0x2: mvi c, 0xbe 3 | 0x4: mvi d, 0x13 4 | 0x6: mvi e, 0x27 5 | 0x8: mvi h, 0x20 6 | 0xa: mvi l, 0x20 7 | 0xc: mvi m, 0x66 8 | 0xe: mvi a, 0xff 9 | 0x10: sub b 10 | 0x11: sub c 11 | 0x12: sub d 12 | 0x13: sub e 13 | 0x14: sub h 14 | 0x15: sub l 15 | 0x16: sub m 16 | 0x17: sub a 17 | 0x18: end 0x66 18 | -------------------------------------------------------------------------------- /testcases/block2/testcase00a.asm: -------------------------------------------------------------------------------- 1 | 0x0: mvi b, 0xab 2 | 0x2: mvi c, 0xbe 3 | 0x4: mvi d, 0x13 4 | 0x6: mvi e, 0x27 5 | 0x8: mvi h, 0x20 6 | 0xa: mvi l, 0x20 7 | 0xc: mvi m, 0x66 8 | 0xe: mvi a, 0xff 9 | 0x10: sbb b 10 | 0x11: sbb c 11 | 0x12: sbb d 12 | 0x13: sbb e 13 | 0x14: sbb h 14 | 0x15: sbb l 15 | 0x16: sbb m 16 | 0x17: sbb a 17 | 0x18: end 0x66 18 | -------------------------------------------------------------------------------- /testcases/block2/testcase00d.asm: -------------------------------------------------------------------------------- 1 | 0x0: mvi b, 0xab 2 | 0x2: mvi c, 0xbe 3 | 0x4: mvi d, 0x13 4 | 0x6: mvi e, 0x27 5 | 0x8: mvi h, 0x20 6 | 0xa: mvi l, 0x20 7 | 0xc: mvi m, 0x66 8 | 0xe: mvi a, 0x54 9 | 0x10: cmp b 10 | 0x11: cmp c 11 | 0x12: cmp d 12 | 0x13: cmp e 13 | 0x14: cmp h 14 | 0x15: cmp l 15 | 0x16: cmp m 16 | 0x17: cmp a 17 | 0x18: end 0x66 18 | -------------------------------------------------------------------------------- /testcases/block3/testcase019.asm: -------------------------------------------------------------------------------- 1 | 0x0: mvi b, 0xde 2 | 0x2: mvi c, 0xad 3 | 0x4: mvi d, 0xbe 4 | 0x6: mvi e, 0xef 5 | 0x8: mvi h, 0x15 6 | 0xa: mvi l, 0x93 7 | 0xc: mvi a, 0x66 8 | 0xe: push b 9 | 0xf: push d 10 | 0x10: push h 11 | 0x11: push psw 12 | 0x12: pop h 13 | 0x13: pop psw 14 | 0x14: pop b 15 | 0x15: pop d 16 | 0x16: nop 17 | 0x17: end 0x66 18 | -------------------------------------------------------------------------------- /testcases/block2/testcase00c.asm: -------------------------------------------------------------------------------- 1 | 0x0: mvi b, 0xab 2 | 0x2: mvi c, 0xbe 3 | 0x4: mvi d, 0x13 4 | 0x6: mvi e, 0x27 5 | 0x8: mvi h, 0x20 6 | 0xa: mvi l, 0x20 7 | 0xc: mvi m, 0x66 8 | 0xe: mvi a, 0x0 9 | 0x10: ora b 10 | 0x11: ora c 11 | 0x12: ora d 12 | 0x13: ora e 13 | 0x14: xra a 14 | 0x15: ora h 15 | 0x16: ora l 16 | 0x17: ora m 17 | 0x18: ora a 18 | 0x19: end 0x66 19 | -------------------------------------------------------------------------------- /testcases/block1/testcase004.asm: -------------------------------------------------------------------------------- 1 | 0x0: mvi h, 0x20 2 | 0x2: mvi l, 0x40 3 | 0x4: mov c, l 4 | 0x5: mov a, l 5 | 0x6: mov d, h 6 | 0x7: mov b, a 7 | 0x8: mvi c, 0x0 8 | 0xa: mov c, b 9 | 0xb: mov e, b 10 | 0xc: mov e, d 11 | 0xd: mov m, b 12 | 0xe: mov m, c 13 | 0xf: mov m, d 14 | 0x10: mov m, e 15 | 0x11: mov m, h 16 | 0x12: mov m, l 17 | 0x13: mov m, a 18 | 0x14: end 0x66 19 | -------------------------------------------------------------------------------- /src/Readme.md: -------------------------------------------------------------------------------- 1 | # Source code 2 | 3 | Here is the source code for the emulator. Here is how you can compile the source code: 4 | 5 | ``` 6 | $ git clone git@github.com:guyinatuxedo/Nightfall-Emulator.git 7 | $ cd Nightfall-Emulator/src/ 8 | $ make 9 | gcc Nightfall.c emulate.c debugCmds.c disass.c flagSet.c math.c stack.c utills.c debugUtils.c codeExec.c mov.c -o Nightfall 10 | ``` 11 | -------------------------------------------------------------------------------- /testcases/block4/testcase034.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void testcase34(void) 4 | { 5 | uint8_t x, y, z; 6 | y = 0x25; 7 | z = 0x3; 8 | for (x = 0; x < 0xa; x++) 9 | { 10 | if (i == 0x7) 11 | { 12 | x = x + 0x1; 13 | } 14 | else if(x == y) 15 | { 16 | x = 0x6; 17 | } 18 | else if(x == z) 19 | { 20 | x = 0x23; 21 | } 22 | } 23 | 24 | return; 25 | } -------------------------------------------------------------------------------- /testcases/block4/testcase034.asm: -------------------------------------------------------------------------------- 1 | 0x0: mvi a, 0x0 2 | 0x2: mvi b, 0x25 3 | 0x4: mvi c, 0x3 4 | 0x6: cpi, 0xa 5 | 0x8: jnc, 0x0023 6 | 0xb: cpi, 0x7 7 | 0xd: jnz, 0x0012 8 | 0x10: adi, 0x1 9 | 0x12: cmp b 10 | 0x13: jnz, 0x0018 11 | 0x16: mvi a, 0x6 12 | 0x18: cmp c 13 | 0x19: jnz, 0x001e 14 | 0x1c: mvi a, 0x23 15 | 0x1e: adi, 0x1 16 | 0x20: jmp, 0x0006 17 | 0x23: nop 18 | 0x24: end 0x66 19 | -------------------------------------------------------------------------------- /testcases/block4/testcase036.asm: -------------------------------------------------------------------------------- 1 | 0x0: mvi a, 0x0 2 | 0x2: mvi b, 0x25 3 | 0x4: mvi c, 0x3 4 | 0x6: cpi, 0x2 5 | 0x8: jnz, 0x0011 6 | 0xb: call, 0x0027 7 | 0xe: jmp, 0x0023 8 | 0x11: cpi, 0x17 9 | 0x13: jnz, 0x001b 10 | 0x16: mvi a, 0x3 11 | 0x18: jmp, 0x0023 12 | 0x1b: cpi, 0x4 13 | 0x1d: jnz, 0x0023 14 | 0x20: nop 15 | 0x21: end 0x66 16 | 0x23: inr a 17 | 0x24: jmp, 0x0006 18 | 0x27: mov d, a 19 | 0x28: add d 20 | 0x29: add d 21 | 0x2a: ret 22 | -------------------------------------------------------------------------------- /testcases/block1/testcase005.asm: -------------------------------------------------------------------------------- 1 | 0x0: mvi h, 0x40 2 | 0x2: mvi l, 0x40 3 | 0x4: mov m, h 4 | 0x5: mov b, m 5 | 0x6: mov d, m 6 | 0x7: mov h, m 7 | 0x8: mov c, m 8 | 0x9: mov e, m 9 | 0xa: mov l, m 10 | 0xb: mov a, m 11 | 0xc: mvi l, 0x20 12 | 0xe: mov b, l 13 | 0xf: mov d, l 14 | 0x10: mov h, c 15 | 0x11: mov b, d 16 | 0x12: mov d, d 17 | 0x13: mov b, e 18 | 0x14: mov d, e 19 | 0x15: mov c, d 20 | 0x16: mov l, d 21 | 0x17: mov a, d 22 | 0x18: end 0x66 23 | -------------------------------------------------------------------------------- /testcases/block0/testcase00e.asm: -------------------------------------------------------------------------------- 1 | 0x0: mvi b, 0x45 2 | 0x2: mvi c, 0x85 3 | 0x4: mvi d, 0x66 4 | 0x6: mvi e, 0xb 5 | 0x8: mvi h, 0x12 6 | 0xa: mvi l, 0xbc 7 | 0xc: mvi m, 0x25 8 | 0xe: mvi a, 0x13 9 | 0x10: inr b 10 | 0x11: dcr b 11 | 0x12: dcr c 12 | 0x13: dcr c 13 | 0x14: inr d 14 | 0x15: dcr d 15 | 0x16: inr e 16 | 0x17: dcr e 17 | 0x18: inr h 18 | 0x19: dcr h 19 | 0x1a: inr l 20 | 0x1b: dcr l 21 | 0x1c: inr m 22 | 0x1d: dcr m 23 | 0x1e: inr a 24 | 0x1f: dcr a 25 | 0x20: end 0x66 26 | -------------------------------------------------------------------------------- /testcases/block2/testcase00b.asm: -------------------------------------------------------------------------------- 1 | 0x0: mvi b, 0xab 2 | 0x2: mvi c, 0xbe 3 | 0x4: mvi d, 0x13 4 | 0x6: mvi e, 0x27 5 | 0x8: mvi h, 0x20 6 | 0xa: mvi l, 0x20 7 | 0xc: mvi m, 0x66 8 | 0xe: mvi a, 0xff 9 | 0x10: ana b 10 | 0x11: xra b 11 | 0x12: ana c 12 | 0x13: xra c 13 | 0x14: ana d 14 | 0x15: xra d 15 | 0x16: ana e 16 | 0x17: xra e 17 | 0x18: ana h 18 | 0x19: xra h 19 | 0x1a: ana l 20 | 0x1b: xra l 21 | 0x1c: ana m 22 | 0x1d: xra m 23 | 0x1e: ana a 24 | 0x1f: xra a 25 | 0x20: end 0x66 26 | -------------------------------------------------------------------------------- /testcases/block4/testcase035.asm: -------------------------------------------------------------------------------- 1 | 0x0: mvi a, 0x0 2 | 0x2: mvi b, 0x25 3 | 0x4: mvi c, 0x3 4 | 0x6: cpi, 0xa 5 | 0x8: jnc, 0x0025 6 | 0xb: cpi, 0x7 7 | 0xd: jnz, 0x0013 8 | 0x10: call, 0x0028 9 | 0x13: cmp b 10 | 0x14: jnz, 0x001a 11 | 0x17: call, 0x002a 12 | 0x1a: cmp c 13 | 0x1b: jnz, 0x0021 14 | 0x1e: call, 0x002d 15 | 0x21: inr a 16 | 0x22: jmp, 0x0006 17 | 0x25: nop 18 | 0x26: end 0x66 19 | 0x28: inr a 20 | 0x29: ret 21 | 0x2a: mvi a, 0x6 22 | 0x2c: ret 23 | 0x2d: mvi a, 0x23 24 | 0x2f: ret 25 | -------------------------------------------------------------------------------- /testcases/block4/testcase036.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void testcase36(void) 4 | { 5 | uint8_t x, y, z; 6 | y = 0x25; 7 | z = 0x3; 8 | x = 0x0; 9 | 10 | while (1) 11 | { 12 | switch (x) 13 | { 14 | case 0x2: 15 | x = dawn(x); 16 | break; 17 | case 0x17: 18 | x = 0x3; 19 | break; 20 | case 0x4: 21 | return; 22 | break; 23 | default: 24 | x = x + 1; 25 | 26 | } 27 | } 28 | } 29 | 30 | void dawn(uint8_t x) 31 | { 32 | return x * 3; 33 | } -------------------------------------------------------------------------------- /testcases/block0/testcase017.asm: -------------------------------------------------------------------------------- 1 | 0x0: nop 2 | 0x1: nop 3 | 0x2: nop 4 | 0x3: nop 5 | 0x4: nop 6 | 0x5: nop 7 | 0x6: nop 8 | 0x7: nop 9 | 0x8: nop 10 | 0x9: nop 11 | 0xa: nop 12 | 0xb: nop 13 | 0xc: nop 14 | 0xd: nop 15 | 0xe: nop 16 | 0xf: nop 17 | 0x10: nop 18 | 0x11: inr a 19 | 0x12: inr a 20 | 0x13: inr a 21 | 0x14: inr a 22 | 0x15: inr a 23 | 0x16: inr a 24 | 0x17: inr a 25 | 0x18: inr a 26 | 0x19: inr a 27 | 0x1a: inr a 28 | 0x1b: inr a 29 | 0x1c: inr a 30 | 0x1d: inr a 31 | 0x1e: inr a 32 | 0x1f: inr a 33 | 0x20: end 0x66 34 | -------------------------------------------------------------------------------- /testcases/block0/testcase015.asm: -------------------------------------------------------------------------------- 1 | 0x0: mvi h, 0x22 2 | 0x2: mvi l, 0x22 3 | 0x4: shld 0x2020 4 | 0x7: mvi h, 0x33 5 | 0x9: mvi l, 0x33 6 | 0xb: shld 0x3030 7 | 0xe: mvi b, 0x20 8 | 0x10: mvi c, 0x20 9 | 0x12: mvi d, 0x30 10 | 0x14: mvi e, 0x30 11 | 0x16: ldax b 12 | 0x17: ldax d 13 | 0x18: mvi h, 0x44 14 | 0x1a: mvi l, 0x44 15 | 0x1c: shld 0x4040 16 | 0x1f: mvi h, 0x0 17 | 0x21: mvi l, 0x0 18 | 0x23: lhld 0x4040 19 | 0x26: mvi h, 0x55 20 | 0x28: mvi l, 0x55 21 | 0x2a: shld 0x5050 22 | 0x2d: lda 0x5050 23 | 0x30: nop 24 | 0x31: end 0x66 25 | -------------------------------------------------------------------------------- /testcases/block4/testcase032.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void testcase32(void) 4 | { 5 | uint8_t x, y, z; 6 | x = 0x66 7 | y = 0x78; 8 | z = 0; 9 | if (x == 0x66) 10 | { 11 | if ((x - y) == 0) 12 | { 13 | x = 0x15; 14 | } 15 | else 16 | { 17 | x = 0x93; 18 | } 19 | } 20 | else if (x == y) 21 | { 22 | if ((x - y) != 0) 23 | { 24 | x = 0x57; 25 | } 26 | else 27 | { 28 | x = 0x28; 29 | } 30 | } 31 | else 32 | { 33 | if ((z - y) != 0) 34 | { 35 | x = 0x35; 36 | } 37 | else 38 | { 39 | x = 0x79; 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /testcases/block4/testcase032.asm: -------------------------------------------------------------------------------- 1 | 0x0: mvi a, 0x66 2 | 0x2: mvi b, 0x78 3 | 0x5: mov h, m 4 | 0x6: jz 0x014 5 | 0x9: cmp b 6 | 0xa: jz 0x022 7 | 0xd: cmp d 8 | 0xe: jz 0x030 9 | 0x11: jmp 0x03e 10 | 0x14: cmp b 11 | 0x15: jnz 0x01d 12 | 0x18: mvi a, 0x15 13 | 0x1a: jmp 0x03e 14 | 0x1d: mvi a, 0x93 15 | 0x1f: jmp 0x03e 16 | 0x22: cmp b 17 | 0x23: jz 0x02b 18 | 0x26: mvi a, 0x57 19 | 0x28: jmp 0x03e 20 | 0x2b: mvi a, 0x28 21 | 0x2d: jmp 0x03e 22 | 0x30: cmp d 23 | 0x31: jz 0x039 24 | 0x34: mvi a, 0x35 25 | 0x36: jmp 0x03e 26 | 0x39: mvi a, 0x79 27 | 0x3b: jmp 0x03e 28 | 0x3e: end 0x66 29 | -------------------------------------------------------------------------------- /testcases/block3/testcase022.asm: -------------------------------------------------------------------------------- 1 | 0x0: jmp 0x04 2 | 0x3: inr a 3 | 0x4: mvi b, 0x0 4 | 0x6: mvi c, 0x0 5 | 0x8: push b 6 | 0x9: pop psw 7 | 0xa: jz 0x00 8 | 0xd: jc 0x00 9 | 0x10: jpe 0x00 10 | 0x13: jm 0x00 11 | 0x16: mvi b, 0x0 12 | 0x18: mvi c, 0xff 13 | 0x1a: push b 14 | 0x1b: pop psw 15 | 0x1c: jz 0x022 16 | 0x1f: inr a 17 | 0x20: inr a 18 | 0x21: inr a 19 | 0x22: jc 0x028 20 | 0x25: inr a 21 | 0x26: inr a 22 | 0x27: inr a 23 | 0x28: jpe 0x02e 24 | 0x2b: inr a 25 | 0x2c: inr a 26 | 0x2d: inr a 27 | 0x2e: jm 0x034 28 | 0x31: inr a 29 | 0x32: inr a 30 | 0x33: inr a 31 | 0x34: nop 32 | 0x35: end 0x66 33 | -------------------------------------------------------------------------------- /testcases/block3/testcase023.asm: -------------------------------------------------------------------------------- 1 | 0x0: jmp 0x04 2 | 0x3: inr a 3 | 0x4: mvi b, 0xff 4 | 0x6: mvi c, 0xff 5 | 0x8: push b 6 | 0x9: pop psw 7 | 0xa: jnz 0x00 8 | 0xd: jnc 0x00 9 | 0x10: jpo 0x00 10 | 0x13: jp 0x00 11 | 0x16: mvi b, 0x0 12 | 0x18: mvi c, 0x0 13 | 0x1a: push b 14 | 0x1b: pop psw 15 | 0x1c: jnz 0x022 16 | 0x1f: inr a 17 | 0x20: inr a 18 | 0x21: inr a 19 | 0x22: jnc 0x028 20 | 0x25: inr a 21 | 0x26: inr a 22 | 0x27: inr a 23 | 0x28: jpo 0x02e 24 | 0x2b: inr a 25 | 0x2c: inr a 26 | 0x2d: inr a 27 | 0x2e: jp 0x034 28 | 0x31: inr a 29 | 0x32: inr a 30 | 0x33: inr a 31 | 0x34: nop 32 | 0x35: end 0x66 33 | -------------------------------------------------------------------------------- /testcases/block4/testcase035.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void testcase35(void) 4 | { 5 | uint8_t x, y, z; 6 | y = 0x25; 7 | z = 0x3; 8 | x = 0x0; 9 | 10 | while (x < 0xa) 11 | { 12 | if (i == 0x7) 13 | { 14 | x = foo0(x); 15 | } 16 | else if(x == y) 17 | { 18 | x = foo1(x); 19 | } 20 | else if(x == z) 21 | { 22 | x = foo2(x); 23 | } 24 | x = x + 1; 25 | } 26 | 27 | return; 28 | } 29 | 30 | void foo0(uint8_t x) 31 | { 32 | return x + 0x1; 33 | } 34 | 35 | void foo1(uint8_t x) 36 | { 37 | return 0x6; 38 | } 39 | 40 | void foo2(uint8_t x) 41 | { 42 | return 0x23 43 | } -------------------------------------------------------------------------------- /testcases/block3/testcase01a.asm: -------------------------------------------------------------------------------- 1 | 0x0: mvi b, 0xff 2 | 0x2: mvi c, 0xff 3 | 0x4: push b 4 | 0x5: pop psw 5 | 0x6: jnc 0x00 6 | 0x9: jpo 0x00 7 | 0xc: jp 0x00 8 | 0xf: mvi b, 0x0 9 | 0x11: mvi c, 0x0 10 | 0x13: push b 11 | 0x14: pop psw 12 | 0x15: jnz 0x01d 13 | 0x18: inr a 14 | 0x19: inr a 15 | 0x1a: inr a 16 | 0x1b: inr a 17 | 0x1c: inr a 18 | 0x1d: jnc 0x023 19 | 0x20: inr a 20 | 0x21: inr a 21 | 0x22: inr a 22 | 0x23: jpo 0x02b 23 | 0x26: inr a 24 | 0x27: inr a 25 | 0x28: inr a 26 | 0x29: inr a 27 | 0x2a: inr a 28 | 0x2b: jp 0x034 29 | 0x2e: inr a 30 | 0x2f: inr a 31 | 0x30: inr a 32 | 0x31: inr a 33 | 0x32: inr a 34 | 0x33: nop 35 | 0x34: end 0x66 36 | -------------------------------------------------------------------------------- /testcases/block4/testcase033.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void testcase33(void) 4 | { 5 | uint8_t x, y, z; 6 | x = 0x66 7 | y = 0x78; 8 | z = 0; 9 | if (x == 0x66) 10 | { 11 | if ((x - y) == 0) 12 | { 13 | x = add(y, 0x93); 14 | } 15 | else 16 | { 17 | x = add(y, 0x15); 18 | } 19 | } 20 | else if (x == y) 21 | { 22 | if ((x - y) != 0) 23 | { 24 | x = add(y, 0x57); 25 | } 26 | else 27 | { 28 | x = add(y, 0x28); 29 | } 30 | } 31 | else 32 | { 33 | if ((z - y) != 0) 34 | { 35 | x = add(y, 0x35); 36 | } 37 | else 38 | { 39 | x = add(y, 0x79); 40 | } 41 | } 42 | } 43 | 44 | uint8_t add(uint8_t x, uint8_t y) 45 | { 46 | return x + y; 47 | } -------------------------------------------------------------------------------- /testcases/block4/testcase033.asm: -------------------------------------------------------------------------------- 1 | 0x0: mvi a, 0x66 2 | 0x2: mvi b, 0x78 3 | 0x4: cpi, 0x66 4 | 0x6: jz, 0x0010 5 | 0x9: cmp b 6 | 0xa: jz, 0x0024 7 | 0xd: jmp, 0x0038 8 | 0x10: cmp b 9 | 0x11: jnz, 0x001c 10 | 0x14: mvi a, 0x15 11 | 0x16: call, 0x004f 12 | 0x19: jmp, 0x004c 13 | 0x1c: mvi a, 0x93 14 | 0x1e: call, 0x004f 15 | 0x21: jmp, 0x004c 16 | 0x24: cmp b 17 | 0x25: jz, 0x0030 18 | 0x28: mvi a, 0x57 19 | 0x2a: call, 0x004f 20 | 0x2d: jmp, 0x004c 21 | 0x30: mvi a, 0x28 22 | 0x32: call, 0x004f 23 | 0x35: jmp, 0x004c 24 | 0x38: cmp d 25 | 0x39: jz, 0x0044 26 | 0x3c: mvi a, 0x35 27 | 0x3e: call, 0x004f 28 | 0x41: jmp, 0x004c 29 | 0x44: mvi a, 0x79 30 | 0x46: call, 0x004f 31 | 0x49: jmp, 0x004c 32 | 0x4c: nop 33 | 0x4d: end 0x66 34 | 0x4f: add b 35 | 0x50: ret -------------------------------------------------------------------------------- /src/mov.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Nightfall.h" 4 | 5 | // Here is the code for mov (and mov - like) operationa 6 | 7 | void mvi(cpu8080 *cpu, uint8_t *reg, uint8_t arg) 8 | { 9 | *(reg) = arg; 10 | cpu->pc += 1; 11 | } 12 | 13 | void ldax(cpu8080 *cpu, uint8_t x, uint8_t y) 14 | { 15 | cpu->a = (uint8_t)cpu->memory[uintConvert(x, y)]; 16 | } 17 | 18 | void stax(cpu8080 *cpu, uint8_t x, uint8_t y) 19 | { 20 | cpu->memory[uintConvert(x, y)] = cpu->a; 21 | } 22 | 23 | void lxi(cpu8080 *cpu, uint8_t *x, uint8_t *y) 24 | { 25 | (*x) = cpu->memory[cpu->pc + 1]; 26 | (*y) = cpu->memory[cpu->pc + 2]; 27 | cpu->pc += 2; 28 | } 29 | 30 | void lxi16(cpu8080 *cpu, uint16_t *x) 31 | { 32 | uint16_t y; 33 | y = cpu->memory[cpu->pc + 1]; 34 | y = y << 8; 35 | y = y | cpu->memory[cpu->pc + 2]; 36 | (*x) = y; 37 | cpu->pc += 2; 38 | } -------------------------------------------------------------------------------- /testcases/block3/testcase024.asm: -------------------------------------------------------------------------------- 1 | 0x0: jz 0x020 2 | 0x3: cmp a 3 | 0x4: rst 0 4 | 0x5: end 0x66 5 | 0x7: nop 6 | 0x8: nop 7 | 0x9: nop 8 | 0xa: nop 9 | 0xb: nop 10 | 0xc: nop 11 | 0xd: nop 12 | 0xe: nop 13 | 0xf: nop 14 | 0x10: nop 15 | 0x11: nop 16 | 0x12: nop 17 | 0x13: nop 18 | 0x14: nop 19 | 0x15: nop 20 | 0x16: nop 21 | 0x17: nop 22 | 0x18: nop 23 | 0x19: nop 24 | 0x1a: nop 25 | 0x1b: nop 26 | 0x1c: nop 27 | 0x1d: nop 28 | 0x1e: nop 29 | 0x1f: nop 30 | 0x20: ret 31 | 0x21: nop 32 | 0x22: nop 33 | 0x23: nop 34 | 0x24: nop 35 | 0x25: nop 36 | 0x26: nop 37 | 0x27: nop 38 | 0x28: nop 39 | 0x29: nop 40 | 0x2a: nop 41 | 0x2b: nop 42 | 0x2c: nop 43 | 0x2d: nop 44 | 0x2e: nop 45 | 0x2f: nop 46 | 0x30: nop 47 | 0x31: nop 48 | 0x32: nop 49 | 0x33: nop 50 | 0x34: nop 51 | 0x35: nop 52 | 0x36: nop 53 | 0x37: nop 54 | 0x38: nop 55 | 0x39: nop 56 | 0x3a: nop 57 | 0x3b: nop 58 | 0x3c: nop 59 | 0x3d: nop 60 | 0x3e: nop 61 | 0x3f: nop 62 | -------------------------------------------------------------------------------- /testcases/block3/testcase025.asm: -------------------------------------------------------------------------------- 1 | 0x0: rst 1 2 | 0x1: end 0x66 3 | 0x3: nop 4 | 0x4: nop 5 | 0x5: nop 6 | 0x6: nop 7 | 0x7: nop 8 | 0x8: inr a 9 | 0x9: inr a 10 | 0xa: inr a 11 | 0xb: ret 12 | 0xc: nop 13 | 0xd: nop 14 | 0xe: nop 15 | 0xf: nop 16 | 0x10: nop 17 | 0x11: nop 18 | 0x12: nop 19 | 0x13: nop 20 | 0x14: nop 21 | 0x15: nop 22 | 0x16: nop 23 | 0x17: nop 24 | 0x18: nop 25 | 0x19: nop 26 | 0x1a: nop 27 | 0x1b: nop 28 | 0x1c: nop 29 | 0x1d: nop 30 | 0x1e: nop 31 | 0x1f: nop 32 | 0x20: nop 33 | 0x21: nop 34 | 0x22: nop 35 | 0x23: nop 36 | 0x24: nop 37 | 0x25: nop 38 | 0x26: nop 39 | 0x27: nop 40 | 0x28: nop 41 | 0x29: nop 42 | 0x2a: nop 43 | 0x2b: nop 44 | 0x2c: nop 45 | 0x2d: nop 46 | 0x2e: nop 47 | 0x2f: nop 48 | 0x30: nop 49 | 0x31: nop 50 | 0x32: nop 51 | 0x33: nop 52 | 0x34: nop 53 | 0x35: nop 54 | 0x36: nop 55 | 0x37: nop 56 | 0x38: nop 57 | 0x39: nop 58 | 0x3a: nop 59 | 0x3b: nop 60 | 0x3c: nop 61 | 0x3d: nop 62 | 0x3e: nop 63 | 0x3f: nop 64 | -------------------------------------------------------------------------------- /testcases/block3/testcase026.asm: -------------------------------------------------------------------------------- 1 | 0x0: rst 2 2 | 0x1: end 0x66 3 | 0x3: nop 4 | 0x4: nop 5 | 0x5: nop 6 | 0x6: nop 7 | 0x7: nop 8 | 0x8: nop 9 | 0x9: nop 10 | 0xa: nop 11 | 0xb: nop 12 | 0xc: nop 13 | 0xd: nop 14 | 0xe: nop 15 | 0xf: nop 16 | 0x10: inr a 17 | 0x11: inr a 18 | 0x12: inr a 19 | 0x13: ret 20 | 0x14: nop 21 | 0x15: nop 22 | 0x16: nop 23 | 0x17: nop 24 | 0x18: nop 25 | 0x19: nop 26 | 0x1a: nop 27 | 0x1b: nop 28 | 0x1c: nop 29 | 0x1d: nop 30 | 0x1e: nop 31 | 0x1f: nop 32 | 0x20: nop 33 | 0x21: nop 34 | 0x22: nop 35 | 0x23: nop 36 | 0x24: nop 37 | 0x25: nop 38 | 0x26: nop 39 | 0x27: nop 40 | 0x28: nop 41 | 0x29: nop 42 | 0x2a: nop 43 | 0x2b: nop 44 | 0x2c: nop 45 | 0x2d: nop 46 | 0x2e: nop 47 | 0x2f: nop 48 | 0x30: nop 49 | 0x31: nop 50 | 0x32: nop 51 | 0x33: nop 52 | 0x34: nop 53 | 0x35: nop 54 | 0x36: nop 55 | 0x37: nop 56 | 0x38: nop 57 | 0x39: nop 58 | 0x3a: nop 59 | 0x3b: nop 60 | 0x3c: nop 61 | 0x3d: nop 62 | 0x3e: nop 63 | 0x3f: nop 64 | -------------------------------------------------------------------------------- /testcases/block3/testcase027.asm: -------------------------------------------------------------------------------- 1 | 0x0: rst 3 2 | 0x1: end 0x66 3 | 0x3: nop 4 | 0x4: nop 5 | 0x5: nop 6 | 0x6: nop 7 | 0x7: nop 8 | 0x8: nop 9 | 0x9: nop 10 | 0xa: nop 11 | 0xb: nop 12 | 0xc: nop 13 | 0xd: nop 14 | 0xe: nop 15 | 0xf: nop 16 | 0x10: nop 17 | 0x11: nop 18 | 0x12: nop 19 | 0x13: nop 20 | 0x14: nop 21 | 0x15: nop 22 | 0x16: nop 23 | 0x17: nop 24 | 0x18: inr a 25 | 0x19: inr a 26 | 0x1a: inr a 27 | 0x1b: ret 28 | 0x1c: nop 29 | 0x1d: nop 30 | 0x1e: nop 31 | 0x1f: nop 32 | 0x20: nop 33 | 0x21: nop 34 | 0x22: nop 35 | 0x23: nop 36 | 0x24: nop 37 | 0x25: nop 38 | 0x26: nop 39 | 0x27: nop 40 | 0x28: nop 41 | 0x29: nop 42 | 0x2a: nop 43 | 0x2b: nop 44 | 0x2c: nop 45 | 0x2d: nop 46 | 0x2e: nop 47 | 0x2f: nop 48 | 0x30: nop 49 | 0x31: nop 50 | 0x32: nop 51 | 0x33: nop 52 | 0x34: nop 53 | 0x35: nop 54 | 0x36: nop 55 | 0x37: nop 56 | 0x38: nop 57 | 0x39: nop 58 | 0x3a: nop 59 | 0x3b: nop 60 | 0x3c: nop 61 | 0x3d: nop 62 | 0x3e: nop 63 | 0x3f: nop 64 | -------------------------------------------------------------------------------- /testcases/block3/testcase028.asm: -------------------------------------------------------------------------------- 1 | 0x0: rst 4 2 | 0x1: end 0x66 3 | 0x3: nop 4 | 0x4: nop 5 | 0x5: nop 6 | 0x6: nop 7 | 0x7: nop 8 | 0x8: nop 9 | 0x9: nop 10 | 0xa: nop 11 | 0xb: nop 12 | 0xc: nop 13 | 0xd: nop 14 | 0xe: nop 15 | 0xf: nop 16 | 0x10: nop 17 | 0x11: nop 18 | 0x12: nop 19 | 0x13: nop 20 | 0x14: nop 21 | 0x15: nop 22 | 0x16: nop 23 | 0x17: nop 24 | 0x18: nop 25 | 0x19: nop 26 | 0x1a: nop 27 | 0x1b: nop 28 | 0x1c: nop 29 | 0x1d: nop 30 | 0x1e: nop 31 | 0x1f: nop 32 | 0x20: inr a 33 | 0x21: inr a 34 | 0x22: inr a 35 | 0x23: ret 36 | 0x24: nop 37 | 0x25: nop 38 | 0x26: nop 39 | 0x27: nop 40 | 0x28: nop 41 | 0x29: nop 42 | 0x2a: nop 43 | 0x2b: nop 44 | 0x2c: nop 45 | 0x2d: nop 46 | 0x2e: nop 47 | 0x2f: nop 48 | 0x30: nop 49 | 0x31: nop 50 | 0x32: nop 51 | 0x33: nop 52 | 0x34: nop 53 | 0x35: nop 54 | 0x36: nop 55 | 0x37: nop 56 | 0x38: nop 57 | 0x39: nop 58 | 0x3a: nop 59 | 0x3b: nop 60 | 0x3c: nop 61 | 0x3d: nop 62 | 0x3e: nop 63 | 0x3f: nop 64 | -------------------------------------------------------------------------------- /testcases/block3/testcase029.asm: -------------------------------------------------------------------------------- 1 | 0x0: rst 5 2 | 0x1: end 0x66 3 | 0x3: nop 4 | 0x4: nop 5 | 0x5: nop 6 | 0x6: nop 7 | 0x7: nop 8 | 0x8: nop 9 | 0x9: nop 10 | 0xa: nop 11 | 0xb: nop 12 | 0xc: nop 13 | 0xd: nop 14 | 0xe: nop 15 | 0xf: nop 16 | 0x10: nop 17 | 0x11: nop 18 | 0x12: nop 19 | 0x13: nop 20 | 0x14: nop 21 | 0x15: nop 22 | 0x16: nop 23 | 0x17: nop 24 | 0x18: nop 25 | 0x19: nop 26 | 0x1a: nop 27 | 0x1b: nop 28 | 0x1c: nop 29 | 0x1d: nop 30 | 0x1e: nop 31 | 0x1f: nop 32 | 0x20: nop 33 | 0x21: nop 34 | 0x22: nop 35 | 0x23: nop 36 | 0x24: nop 37 | 0x25: nop 38 | 0x26: nop 39 | 0x27: nop 40 | 0x28: inr a 41 | 0x29: inr a 42 | 0x2a: inr a 43 | 0x2b: ret 44 | 0x2c: nop 45 | 0x2d: nop 46 | 0x2e: nop 47 | 0x2f: nop 48 | 0x30: nop 49 | 0x31: nop 50 | 0x32: nop 51 | 0x33: nop 52 | 0x34: nop 53 | 0x35: nop 54 | 0x36: nop 55 | 0x37: nop 56 | 0x38: nop 57 | 0x39: nop 58 | 0x3a: nop 59 | 0x3b: nop 60 | 0x3c: nop 61 | 0x3d: nop 62 | 0x3e: nop 63 | 0x3f: nop 64 | -------------------------------------------------------------------------------- /testcases/block3/testcase02a.asm: -------------------------------------------------------------------------------- 1 | 0x0: rst 6 2 | 0x1: end 0x66 3 | 0x3: nop 4 | 0x4: nop 5 | 0x5: nop 6 | 0x6: nop 7 | 0x7: nop 8 | 0x8: nop 9 | 0x9: nop 10 | 0xa: nop 11 | 0xb: nop 12 | 0xc: nop 13 | 0xd: nop 14 | 0xe: nop 15 | 0xf: nop 16 | 0x10: nop 17 | 0x11: nop 18 | 0x12: nop 19 | 0x13: nop 20 | 0x14: nop 21 | 0x15: nop 22 | 0x16: nop 23 | 0x17: nop 24 | 0x18: nop 25 | 0x19: nop 26 | 0x1a: nop 27 | 0x1b: nop 28 | 0x1c: nop 29 | 0x1d: nop 30 | 0x1e: nop 31 | 0x1f: nop 32 | 0x20: nop 33 | 0x21: nop 34 | 0x22: nop 35 | 0x23: nop 36 | 0x24: nop 37 | 0x25: nop 38 | 0x26: nop 39 | 0x27: nop 40 | 0x28: nop 41 | 0x29: nop 42 | 0x2a: nop 43 | 0x2b: nop 44 | 0x2c: nop 45 | 0x2d: nop 46 | 0x2e: nop 47 | 0x2f: nop 48 | 0x30: inr a 49 | 0x31: inr a 50 | 0x32: inr a 51 | 0x33: ret 52 | 0x34: nop 53 | 0x35: nop 54 | 0x36: nop 55 | 0x37: nop 56 | 0x38: nop 57 | 0x39: nop 58 | 0x3a: nop 59 | 0x3b: nop 60 | 0x3c: nop 61 | 0x3d: nop 62 | 0x3e: nop 63 | 0x3f: nop 64 | -------------------------------------------------------------------------------- /testcases/block3/testcase02b.asm: -------------------------------------------------------------------------------- 1 | 0x0: rst 7 2 | 0x1: end 0x66 3 | 0x3: nop 4 | 0x4: nop 5 | 0x5: nop 6 | 0x6: nop 7 | 0x7: nop 8 | 0x8: nop 9 | 0x9: nop 10 | 0xa: nop 11 | 0xb: nop 12 | 0xc: nop 13 | 0xd: nop 14 | 0xe: nop 15 | 0xf: nop 16 | 0x10: nop 17 | 0x11: nop 18 | 0x12: nop 19 | 0x13: nop 20 | 0x14: nop 21 | 0x15: nop 22 | 0x16: nop 23 | 0x17: nop 24 | 0x18: nop 25 | 0x19: nop 26 | 0x1a: nop 27 | 0x1b: nop 28 | 0x1c: nop 29 | 0x1d: nop 30 | 0x1e: nop 31 | 0x1f: nop 32 | 0x20: nop 33 | 0x21: nop 34 | 0x22: nop 35 | 0x23: nop 36 | 0x24: nop 37 | 0x25: nop 38 | 0x26: nop 39 | 0x27: nop 40 | 0x28: nop 41 | 0x29: nop 42 | 0x2a: nop 43 | 0x2b: nop 44 | 0x2c: nop 45 | 0x2d: nop 46 | 0x2e: nop 47 | 0x2f: nop 48 | 0x30: nop 49 | 0x31: nop 50 | 0x32: nop 51 | 0x33: nop 52 | 0x34: nop 53 | 0x35: nop 54 | 0x36: nop 55 | 0x37: nop 56 | 0x38: inr a 57 | 0x39: inr a 58 | 0x3a: inr a 59 | 0x3b: ret 60 | 0x3c: nop 61 | 0x3d: nop 62 | 0x3e: nop 63 | 0x3f: nop 64 | -------------------------------------------------------------------------------- /testcases/Readme.md: -------------------------------------------------------------------------------- 1 | # Testcases 2 | 3 | Here are the testcases that I wrote to test the functionallity of my emulator. All of the opcodes (with the exception of the ones that aren't documented). The first four blocks are dedicated to testing out the following commands: 4 | 5 | ``` 6 | block0: instructions 0x00 - 0x3f 7 | block1: instructions 0x40 - 0x7f 8 | block2: instructions 0x80 - 0xbf 9 | block3: instructions 0xc0 - 0xff 10 | ``` 11 | 12 | All of the test cases for those blocks, can be found in the corresponding folders. Also all of those testcases have the assembly code stored in a `.asm` file. 13 | 14 | The final block `block4` is dedicated to programs with more complicated code paths then what you would find in the first four blocks. This includes for loops, while loops, if then and switch statements, and a bit more branching / jumping. Also all of the testcases in this block also have a corresponding `.c` file which shows the C equivalent of the binary. 15 | -------------------------------------------------------------------------------- /src/stack.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Nightfall.h" 4 | 5 | // This file holds code for push / pop functions 6 | 7 | void pop(cpu8080 *cpu, uint8_t *x, uint8_t *y) 8 | { 9 | *y = cpu->memory[cpu->sp]; 10 | cpu->sp += 1; 11 | *x = cpu->memory[cpu->sp]; 12 | cpu->sp += 1; 13 | } 14 | 15 | void push(cpu8080 *cpu, uint8_t x, uint8_t y) 16 | { 17 | cpu->sp -= 1; 18 | cpu->memory[cpu->sp] = x; 19 | cpu->sp -= 1; 20 | cpu->memory[cpu->sp] = y; 21 | } 22 | 23 | void push16(cpu8080 *cpu, uint16_t x) 24 | { 25 | uint8_t y; 26 | y = (uint8_t)(x >> 8); 27 | cpu->sp -= 1; 28 | cpu->memory[cpu->sp] = y; 29 | cpu->sp -= 1; 30 | y = (uint8_t)(x); 31 | cpu->memory[cpu->sp] = y; 32 | } 33 | 34 | void popPsw(cpu8080 *cpu) 35 | { 36 | uint8_t x; 37 | x = cpu->memory[cpu->sp]; 38 | setSpecificFlagPsw(cpu, x, 0x1, &(cpu->carry)); 39 | setSpecificFlagPsw(cpu, x, 0x4, &(cpu->parity)); 40 | setSpecificFlagPsw(cpu, x, 0x10, &(cpu->aux)); 41 | setSpecificFlagPsw(cpu, x, 0x40, &(cpu->zero)); 42 | setSpecificFlagPsw(cpu, x, 0x80, &(cpu->sign)); 43 | cpu->sp += 1; 44 | cpu->a = cpu->memory[cpu->sp]; 45 | cpu->sp += 1; 46 | } -------------------------------------------------------------------------------- /src/codeExec.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Nightfall.h" 4 | 5 | // Here is the code for operations dealing with comparisons, and redirecting code execution 6 | 7 | void cmp(cpu8080 *cpu, uint8_t x) 8 | { 9 | uint8_t y = ((~x) + 1); 10 | 11 | uint16_t z = (cpu->a + y); 12 | 13 | carryFlagSub(cpu, z); 14 | 15 | signFlag(cpu, z); 16 | 17 | zeroFlag(cpu, z); 18 | 19 | parityFlag(cpu, z); 20 | 21 | auxiliaryFlag(cpu, cpu->a, x, 0); 22 | } 23 | 24 | void jmp(cpu8080 *cpu, uint8_t x, uint8_t y) 25 | { 26 | uint16_t z; 27 | z = (uint16_t)y; 28 | z = z << 8; 29 | z = z | x; 30 | cpu->pc = (z - 1); 31 | } 32 | 33 | void call(cpu8080 *cpu, uint8_t x, uint8_t y) 34 | { 35 | uint16_t z; 36 | z = (y << 8); 37 | z = z | x; 38 | z = z - 1; 39 | push16(cpu, (cpu->pc + 3)); 40 | cpu->pc = z; 41 | } 42 | 43 | void ret(cpu8080 *cpu) 44 | { 45 | uint8_t x; 46 | uint16_t y; 47 | x = (uint16_t)cpu->memory[cpu->sp]; 48 | cpu->sp += 1; 49 | y = (uint16_t)cpu->memory[cpu->sp]; 50 | cpu->sp += 1; 51 | y = (y << 8); 52 | y = y | x; 53 | cpu->pc = y - 1; 54 | } 55 | 56 | void rst(cpu8080 *cpu, uint16_t x) 57 | { 58 | push16(cpu, (cpu->pc+1)); 59 | cpu->pc = x - 1; 60 | } -------------------------------------------------------------------------------- /src/debugUtils.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "Nightfall.h" 5 | 6 | // This file contains some utillity functions for the debugger 7 | 8 | int isBreakPoint(cpu8080 *cpu) 9 | { 10 | if (cpu->breakpoints == NULL) 11 | { 12 | return 1; 13 | } 14 | else 15 | { 16 | return checkBreakPoint(cpu->breakpoints, cpu->pc); 17 | } 18 | } 19 | 20 | breakpoints *findLastBreakpoint(breakpoints *breakpoint) 21 | { 22 | if (breakpoint == NULL) 23 | { 24 | return NULL; 25 | } 26 | else 27 | { 28 | if (breakpoint->next == NULL) 29 | { 30 | return breakpoint; 31 | } 32 | else 33 | { 34 | return findLastBreakpoint(breakpoint->next); 35 | } 36 | } 37 | } 38 | 39 | breakpoints *allocateBreakpoint(uint16_t x) 40 | { 41 | breakpoints *b; 42 | b = malloc(sizeof(breakpoints)); 43 | b->breakp = x; 44 | b->next = NULL; 45 | return b; 46 | } 47 | 48 | int checkBreakPoint(breakpoints * breakpt, uint16_t x) 49 | { 50 | if (breakpt->breakp == x && breakpt->active == true) 51 | { 52 | return 0; 53 | puts("sam"); 54 | } 55 | else if (breakpt->next != NULL) 56 | { 57 | return checkBreakPoint(breakpt->next, x); 58 | } 59 | else 60 | { 61 | return 1; 62 | } 63 | } -------------------------------------------------------------------------------- /src/flagSet.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Nightfall.h" 4 | 5 | // This code contains functions for setting flags after operations 6 | 7 | void auxiliaryFlag(cpu8080 *cpu, uint8_t x, uint8_t y, uint8_t z) 8 | { 9 | if (z == 0) 10 | { 11 | if (((x & 0x8) == 0) && (y & 0x8)) 12 | { 13 | cpu->aux = true; 14 | } 15 | else 16 | { 17 | cpu->aux = false; 18 | } 19 | } 20 | else if (z == 1) 21 | { 22 | if ((x & 0x8) && (y & 0x8)) 23 | { 24 | cpu->aux = true; 25 | } 26 | else 27 | { 28 | cpu->aux = false; 29 | } 30 | } 31 | } 32 | 33 | void zeroFlag(cpu8080 *cpu, uint16_t x) 34 | { 35 | if ((x & 0xff) == 0) 36 | { 37 | cpu->zero = true; 38 | } 39 | else 40 | { 41 | cpu->zero = false; 42 | } 43 | } 44 | 45 | void signFlag(cpu8080 *cpu, uint16_t x) 46 | { 47 | if ((x & 0x80) != 0) 48 | { 49 | cpu->sign = true; 50 | } 51 | else 52 | { 53 | cpu->sign = false; 54 | } 55 | } 56 | 57 | void parityFlag(cpu8080 *cpu, uint16_t x) 58 | { 59 | int i, y, z; 60 | z = 0; 61 | for (i = 0; i < 8; i++) 62 | { 63 | y = x >> i; 64 | 65 | if (y & 0x1) 66 | { 67 | z += 1; 68 | } 69 | } 70 | if ((z % 2) == 0) 71 | { 72 | cpu->parity = true; 73 | } 74 | else 75 | { 76 | cpu->parity = false; 77 | } 78 | } 79 | 80 | void carryFlag(cpu8080 *cpu, uint16_t x) 81 | { 82 | if (x & 0x100) 83 | { 84 | cpu->carry = true; 85 | } 86 | else 87 | { 88 | cpu->carry = false; 89 | } 90 | } 91 | 92 | void carryFlagSub(cpu8080 *cpu, uint16_t x) 93 | { 94 | if (x & 0x100) 95 | { 96 | cpu->carry = false; 97 | } 98 | else 99 | { 100 | cpu->carry = true; 101 | } 102 | } 103 | 104 | void carryFlag16(cpu8080 *cpu, uint32_t x) 105 | { 106 | if ((x & 0x10000) != 0) 107 | { 108 | cpu->carry = true; 109 | } 110 | else 111 | { 112 | cpu->carry = false; 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/Nightfall.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "Nightfall.h" 5 | 6 | // This is the main code file, it holds the menu function for the debugger, and the main function 7 | 8 | void menu(cpu8080 *cpu) 9 | { 10 | uint16_t breakpoint; 11 | 12 | char *menuChoice; 13 | menuChoice = malloc(menuInputSize); 14 | while (1) 15 | { 16 | printf("ndb> "); 17 | fgets(menuChoice, menuInputSize - 1, stdin); 18 | switch (menuChoice[0]) 19 | { 20 | case 'a': 21 | activateBreakpoint(cpu, menuChoice); 22 | break; 23 | case 'b': 24 | createBreakpoint(cpu, menuChoice); 25 | break; 26 | case 'c': 27 | emulate(cpu); 28 | break; 29 | case 'd': 30 | deactivateBreakpoint(cpu, menuChoice); 31 | break; 32 | case 'e': 33 | disassembleAll(cpu); 34 | break; 35 | case 'h': 36 | printHelp(); 37 | break; 38 | case 'i': 39 | printRegisters(cpu); 40 | break; 41 | case 'j': 42 | jumpExec(cpu, menuChoice); 43 | break; 44 | case 'm': 45 | printMemoryRegions(cpu); 46 | break; 47 | case 'p': 48 | printRegister(cpu, menuChoice); 49 | break; 50 | case 'q': 51 | resetExecution(cpu); 52 | destroyCpu(cpu); 53 | free(menuChoice); 54 | return; 55 | break; 56 | case 'r': 57 | resetExecution(cpu); 58 | emulate(cpu); 59 | break; 60 | case 's': 61 | stepInstruction(cpu); 62 | emulate(cpu); 63 | break; 64 | case 't': 65 | toggleDisassExec(cpu); 66 | break; 67 | case 'u': 68 | dumpMemory(cpu); 69 | break; 70 | case 'x': 71 | examineMemory(cpu, menuChoice); 72 | break; 73 | case 'y': 74 | set(cpu, menuChoice); 75 | break; 76 | case 'z': 77 | showBreakpoints(cpu->breakpoints, 0); 78 | break; 79 | } 80 | } 81 | } 82 | 83 | int main(int argc, char **argv) 84 | { 85 | cpu8080 *cpu; 86 | char *binaryCode; 87 | 88 | if (argc != 2) 89 | { 90 | puts("Takes single argument, filename of binary to emulate / debug\nex: ./Nightfall block0/testcase00e"); 91 | exit(0); 92 | } 93 | 94 | cpu = createCpu(); 95 | 96 | scanBinary(argv[1], cpu); 97 | 98 | puts("Nightfall 8080 Emulator / Debugger / Disassembler"); 99 | 100 | menu(cpu); 101 | 102 | return 0; 103 | } 104 | -------------------------------------------------------------------------------- /testcases/block3/testcase01e.asm: -------------------------------------------------------------------------------- 1 | 0x0: mvi b, 0xff 2 | 0x2: mvi c, 0xff 3 | 0x4: push b 4 | 0x5: pop psw 5 | 0x6: cz 0x0a0 6 | 0x9: cc 0x0a7 7 | 0xc: cpe 0x0ae 8 | 0xf: cm 0x0b5 9 | 0x12: nop 10 | 0x13: end 0x66 11 | 0x15: nop 12 | 0x16: nop 13 | 0x17: nop 14 | 0x18: nop 15 | 0x19: nop 16 | 0x1a: nop 17 | 0x1b: nop 18 | 0x1c: nop 19 | 0x1d: nop 20 | 0x1e: nop 21 | 0x1f: nop 22 | 0x20: nop 23 | 0x21: nop 24 | 0x22: nop 25 | 0x23: nop 26 | 0x24: nop 27 | 0x25: nop 28 | 0x26: nop 29 | 0x27: nop 30 | 0x28: nop 31 | 0x29: nop 32 | 0x2a: nop 33 | 0x2b: nop 34 | 0x2c: nop 35 | 0x2d: nop 36 | 0x2e: nop 37 | 0x2f: nop 38 | 0x30: nop 39 | 0x31: nop 40 | 0x32: nop 41 | 0x33: nop 42 | 0x34: nop 43 | 0x35: nop 44 | 0x36: nop 45 | 0x37: nop 46 | 0x38: nop 47 | 0x39: nop 48 | 0x3a: nop 49 | 0x3b: nop 50 | 0x3c: nop 51 | 0x3d: nop 52 | 0x3e: nop 53 | 0x3f: nop 54 | 0x40: nop 55 | 0x41: nop 56 | 0x42: nop 57 | 0x43: nop 58 | 0x44: nop 59 | 0x45: nop 60 | 0x46: nop 61 | 0x47: nop 62 | 0x48: nop 63 | 0x49: nop 64 | 0x4a: nop 65 | 0x4b: nop 66 | 0x4c: nop 67 | 0x4d: nop 68 | 0x4e: nop 69 | 0x4f: nop 70 | 0x50: nop 71 | 0x51: nop 72 | 0x52: nop 73 | 0x53: nop 74 | 0x54: nop 75 | 0x55: nop 76 | 0x56: nop 77 | 0x57: nop 78 | 0x58: nop 79 | 0x59: nop 80 | 0x5a: nop 81 | 0x5b: nop 82 | 0x5c: nop 83 | 0x5d: nop 84 | 0x5e: nop 85 | 0x5f: nop 86 | 0x60: nop 87 | 0x61: nop 88 | 0x62: nop 89 | 0x63: nop 90 | 0x64: nop 91 | 0x65: nop 92 | 0x66: nop 93 | 0x67: nop 94 | 0x68: nop 95 | 0x69: nop 96 | 0x6a: nop 97 | 0x6b: nop 98 | 0x6c: nop 99 | 0x6d: nop 100 | 0x6e: nop 101 | 0x6f: nop 102 | 0x70: nop 103 | 0x71: nop 104 | 0x72: nop 105 | 0x73: nop 106 | 0x74: nop 107 | 0x75: nop 108 | 0x76: nop 109 | 0x77: nop 110 | 0x78: nop 111 | 0x79: nop 112 | 0x7a: nop 113 | 0x7b: nop 114 | 0x7c: nop 115 | 0x7d: nop 116 | 0x7e: nop 117 | 0x7f: nop 118 | 0x80: nop 119 | 0x81: nop 120 | 0x82: nop 121 | 0x83: nop 122 | 0x84: nop 123 | 0x85: nop 124 | 0x86: nop 125 | 0x87: nop 126 | 0x88: nop 127 | 0x89: nop 128 | 0x8a: nop 129 | 0x8b: nop 130 | 0x8c: nop 131 | 0x8d: nop 132 | 0x8e: nop 133 | 0x8f: nop 134 | 0x90: nop 135 | 0x91: nop 136 | 0x92: nop 137 | 0x93: nop 138 | 0x94: nop 139 | 0x95: nop 140 | 0x96: nop 141 | 0x97: nop 142 | 0x98: nop 143 | 0x99: nop 144 | 0x9a: nop 145 | 0x9b: nop 146 | 0x9c: nop 147 | 0x9d: nop 148 | 0x9e: nop 149 | 0x9f: nop 150 | 0xa0: nop 151 | 0xa1: nop 152 | 0xa2: nop 153 | 0xa3: nop 154 | 0xa4: nop 155 | 0xa5: rz 156 | 0xa6: nop 157 | 0xa7: nop 158 | 0xa8: nop 159 | 0xa9: nop 160 | 0xaa: nop 161 | 0xab: nop 162 | 0xac: rc 163 | 0xad: nop 164 | 0xae: nop 165 | 0xaf: nop 166 | 0xb0: nop 167 | 0xb1: nop 168 | 0xb2: nop 169 | 0xb3: rpe 170 | 0xb4: nop 171 | 0xb5: nop 172 | 0xb6: nop 173 | 0xb7: nop 174 | 0xb8: nop 175 | 0xb9: nop 176 | 0xba: rm 177 | 0xbb: nop 178 | 0xbc: nop 179 | 0xbd: nop 180 | 0xbe: nop 181 | 0xbf: nop 182 | -------------------------------------------------------------------------------- /testcases/block3/testcase020.asm: -------------------------------------------------------------------------------- 1 | 0x0: mvi b, 0x0 2 | 0x2: mvi c, 0x0 3 | 0x4: push b 4 | 0x5: pop psw 5 | 0x6: cnz 0x0a0 6 | 0x9: cnc 0x0a7 7 | 0xc: cpo 0x0ae 8 | 0xf: cp 0x0b5 9 | 0x12: nop 10 | 0x13: end 0x66 11 | 0x15: nop 12 | 0x16: nop 13 | 0x17: nop 14 | 0x18: nop 15 | 0x19: nop 16 | 0x1a: nop 17 | 0x1b: nop 18 | 0x1c: nop 19 | 0x1d: nop 20 | 0x1e: nop 21 | 0x1f: nop 22 | 0x20: nop 23 | 0x21: nop 24 | 0x22: nop 25 | 0x23: nop 26 | 0x24: nop 27 | 0x25: nop 28 | 0x26: nop 29 | 0x27: nop 30 | 0x28: nop 31 | 0x29: nop 32 | 0x2a: nop 33 | 0x2b: nop 34 | 0x2c: nop 35 | 0x2d: nop 36 | 0x2e: nop 37 | 0x2f: nop 38 | 0x30: nop 39 | 0x31: nop 40 | 0x32: nop 41 | 0x33: nop 42 | 0x34: nop 43 | 0x35: nop 44 | 0x36: nop 45 | 0x37: nop 46 | 0x38: nop 47 | 0x39: nop 48 | 0x3a: nop 49 | 0x3b: nop 50 | 0x3c: nop 51 | 0x3d: nop 52 | 0x3e: nop 53 | 0x3f: nop 54 | 0x40: nop 55 | 0x41: nop 56 | 0x42: nop 57 | 0x43: nop 58 | 0x44: nop 59 | 0x45: nop 60 | 0x46: nop 61 | 0x47: nop 62 | 0x48: nop 63 | 0x49: nop 64 | 0x4a: nop 65 | 0x4b: nop 66 | 0x4c: nop 67 | 0x4d: nop 68 | 0x4e: nop 69 | 0x4f: nop 70 | 0x50: nop 71 | 0x51: nop 72 | 0x52: nop 73 | 0x53: nop 74 | 0x54: nop 75 | 0x55: nop 76 | 0x56: nop 77 | 0x57: nop 78 | 0x58: nop 79 | 0x59: nop 80 | 0x5a: nop 81 | 0x5b: nop 82 | 0x5c: nop 83 | 0x5d: nop 84 | 0x5e: nop 85 | 0x5f: nop 86 | 0x60: nop 87 | 0x61: nop 88 | 0x62: nop 89 | 0x63: nop 90 | 0x64: nop 91 | 0x65: nop 92 | 0x66: nop 93 | 0x67: nop 94 | 0x68: nop 95 | 0x69: nop 96 | 0x6a: nop 97 | 0x6b: nop 98 | 0x6c: nop 99 | 0x6d: nop 100 | 0x6e: nop 101 | 0x6f: nop 102 | 0x70: nop 103 | 0x71: nop 104 | 0x72: nop 105 | 0x73: nop 106 | 0x74: nop 107 | 0x75: nop 108 | 0x76: nop 109 | 0x77: nop 110 | 0x78: nop 111 | 0x79: nop 112 | 0x7a: nop 113 | 0x7b: nop 114 | 0x7c: nop 115 | 0x7d: nop 116 | 0x7e: nop 117 | 0x7f: nop 118 | 0x80: nop 119 | 0x81: nop 120 | 0x82: nop 121 | 0x83: nop 122 | 0x84: nop 123 | 0x85: nop 124 | 0x86: nop 125 | 0x87: nop 126 | 0x88: nop 127 | 0x89: nop 128 | 0x8a: nop 129 | 0x8b: nop 130 | 0x8c: nop 131 | 0x8d: nop 132 | 0x8e: nop 133 | 0x8f: nop 134 | 0x90: nop 135 | 0x91: nop 136 | 0x92: nop 137 | 0x93: nop 138 | 0x94: nop 139 | 0x95: nop 140 | 0x96: nop 141 | 0x97: nop 142 | 0x98: nop 143 | 0x99: nop 144 | 0x9a: nop 145 | 0x9b: nop 146 | 0x9c: nop 147 | 0x9d: nop 148 | 0x9e: nop 149 | 0x9f: nop 150 | 0xa0: nop 151 | 0xa1: nop 152 | 0xa2: nop 153 | 0xa3: nop 154 | 0xa4: nop 155 | 0xa5: rnz 156 | 0xa6: nop 157 | 0xa7: nop 158 | 0xa8: nop 159 | 0xa9: nop 160 | 0xaa: nop 161 | 0xab: nop 162 | 0xac: rnc 163 | 0xad: nop 164 | 0xae: nop 165 | 0xaf: nop 166 | 0xb0: nop 167 | 0xb1: nop 168 | 0xb2: nop 169 | 0xb3: rpo 170 | 0xb4: nop 171 | 0xb5: nop 172 | 0xb6: nop 173 | 0xb7: nop 174 | 0xb8: nop 175 | 0xb9: nop 176 | 0xba: rp 177 | 0xbb: nop 178 | 0xbc: nop 179 | 0xbd: nop 180 | 0xbe: nop 181 | 0xbf: nop 182 | -------------------------------------------------------------------------------- /src/utills.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "Nightfall.h" 6 | 7 | // This file holds functions which help with various parts of the code 8 | 9 | uint8_t convertFlagsRegister(cpu8080 *cpu) 10 | { 11 | uint8_t x = 0x2; 12 | x = x | ((uint8_t)(cpu->sign == true) << 7); 13 | x = x | ((uint8_t)(cpu->zero == true) << 6); 14 | x = x | ((uint8_t)(cpu->aux == true) << 4); 15 | x = x | ((uint8_t)(cpu->parity == true) << 2); 16 | x = x | ((uint8_t)(cpu->carry == true) << 1); 17 | return x; 18 | } 19 | 20 | int uintConvert(uint8_t x, uint8_t y) 21 | { 22 | uint16_t z = 0; 23 | 24 | z = z | x; 25 | z = z << 8; 26 | z = z | y; 27 | 28 | return z; 29 | } 30 | 31 | int charToInt(char * inp) 32 | { 33 | char *arg; 34 | int x; 35 | 36 | arg = removeBeginning(inp); 37 | if (strncmp(arg, "0x", 2) == 0) 38 | { 39 | x = strtoumax(arg, NULL, 16); 40 | 41 | } 42 | else 43 | { 44 | x = strtoumax(arg, NULL, 10); 45 | } 46 | free(arg); 47 | return x; 48 | } 49 | 50 | char *removeBeginning(char *inp) 51 | { 52 | int x, i; 53 | char *result; 54 | 55 | x = strlen(inp); 56 | result = malloc(x); 57 | for (i = 2; i < x; i++) 58 | { 59 | result[i - 2] = inp[i]; 60 | } 61 | return result; 62 | } 63 | 64 | int hexDecimaltoInt(char *arg) 65 | { 66 | int x; 67 | if (strncmp(arg, "0x", 2) == 0) 68 | { 69 | x = strtoumax(arg, NULL, 16); 70 | 71 | } 72 | else 73 | { 74 | x = strtoumax(arg, NULL, 10); 75 | } 76 | return x; 77 | } 78 | 79 | void printTwoArgs(cpu8080 *cpu, int pc) 80 | { 81 | uint8_t x = cpu->memory[pc + 1]; 82 | uint8_t y = cpu->memory[pc + 2]; 83 | if ((x > 0xf) && (y > 0xf)) 84 | { 85 | printf("0x%x%x\n", x, y); 86 | return; 87 | } 88 | else if ((x < 0xf) && (y < 0xf)) 89 | { 90 | printf("0x0%x0%x\n", x, y); 91 | return; 92 | } 93 | else if (x < 0xf) 94 | { 95 | printf("0x0%x%x\n", x, y); 96 | return; 97 | } 98 | else 99 | { 100 | printf("0x%x0%x\n", x, y); 101 | return; 102 | } 103 | } 104 | 105 | void printTwoArgsBack(cpu8080 *cpu, int pc) 106 | { 107 | uint8_t x = cpu->memory[pc + 1]; 108 | uint8_t y = cpu->memory[pc + 2]; 109 | if ((x > 0xf) && (y > 0xf)) 110 | { 111 | printf("0x%x%x\n", y, x); 112 | return; 113 | } 114 | else if ((x < 0xf) && (y < 0xf)) 115 | { 116 | printf("0x0%x0%x\n", y, x); 117 | return; 118 | } 119 | else if (y < 0xf) 120 | { 121 | printf("0x0%x%x\n", y, x); 122 | return; 123 | } 124 | else 125 | { 126 | printf("0x%x0%x\n", y, x); 127 | return; 128 | } 129 | } 130 | 131 | void setSpecificFlagPsw(cpu8080 *cpu, int x, int cmp, bool *flag) 132 | { 133 | if (x & cmp) 134 | { 135 | *flag = true; 136 | } 137 | else 138 | { 139 | *flag = false; 140 | } 141 | } 142 | 143 | void setCode(cpu8080 *cpu, char *code, int size) 144 | { 145 | memcpy(cpu->memory, code, size); 146 | cpu->codeEnd = (size - 1); 147 | cpu->codeBeg = 0x0; 148 | return; 149 | } 150 | 151 | void scanBinary(char *fileName, cpu8080 *cpu) 152 | { 153 | FILE *fp; 154 | char *code; 155 | int size; 156 | int bytesRead; 157 | 158 | fp = fopen(fileName, "r"); 159 | if (fp == NULL) 160 | { 161 | puts("File not found"); 162 | exit(0); 163 | } 164 | 165 | size = getFileSize(fp); 166 | code = calloc(1, (size + 1)); 167 | 168 | fseek(fp, 0, SEEK_SET); 169 | 170 | bytesRead = fread(code, sizeof(char), size, fp); 171 | 172 | fclose(fp); 173 | 174 | memcpy(cpu->memory, code, size); 175 | cpu->codeBeg = 0x0; 176 | cpu->codeEnd = (uint16_t)(size - 0x1); 177 | free(code); 178 | return; 179 | } 180 | 181 | long int getFileSize(FILE *fp) 182 | { 183 | long int size = 0; 184 | fseek(fp, 0, SEEK_END); 185 | size = ftell(fp); 186 | return size; 187 | } -------------------------------------------------------------------------------- /src/math.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Nightfall.h" 4 | 5 | // This file has functions which handle various math operations 6 | 7 | void add(cpu8080 *cpu, uint8_t x) 8 | { 9 | uint16_t z = ((uint16_t)x + (cpu->a)); 10 | 11 | carryFlag(cpu, z); 12 | 13 | signFlag(cpu, z); 14 | 15 | zeroFlag(cpu, z); 16 | 17 | parityFlag(cpu, z); 18 | 19 | auxiliaryFlag(cpu, cpu->a, x, 1); 20 | 21 | cpu->a = (uint8_t)z; 22 | } 23 | 24 | void adc(cpu8080 *cpu, uint8_t x) 25 | { 26 | uint16_t z = ((uint16_t)x + (cpu->a) + ((uint16_t)cpu->carry)); 27 | 28 | carryFlag(cpu, z); 29 | 30 | signFlag(cpu, z); 31 | 32 | zeroFlag(cpu, z); 33 | 34 | parityFlag(cpu, z); 35 | 36 | auxiliaryFlag(cpu, cpu->a, x, 1); 37 | 38 | cpu->a = (uint8_t)z; 39 | } 40 | 41 | void sub(cpu8080 *cpu, uint8_t x) 42 | { 43 | uint8_t y = ((~x) + 1); 44 | 45 | uint16_t z = (cpu->a + y); 46 | 47 | carryFlagSub(cpu, z); 48 | 49 | signFlag(cpu, z); 50 | 51 | zeroFlag(cpu, z); 52 | 53 | parityFlag(cpu, z); 54 | 55 | auxiliaryFlag(cpu, cpu->a, x, 0); 56 | 57 | cpu->a = (uint8_t)z; 58 | } 59 | 60 | void sbb(cpu8080 *cpu, uint8_t x) 61 | { 62 | uint8_t y = ((~(x + (int)cpu->carry)) + 1); 63 | 64 | uint16_t z = (cpu->a + y); 65 | 66 | carryFlagSub(cpu, z); 67 | 68 | signFlag(cpu, z); 69 | 70 | zeroFlag(cpu, z); 71 | 72 | parityFlag(cpu, z); 73 | 74 | auxiliaryFlag(cpu, cpu->a, x, 0); 75 | 76 | cpu->a = (uint8_t)z; 77 | } 78 | 79 | void and(cpu8080 *cpu, uint8_t x) 80 | { 81 | uint16_t z = (uint16_t)cpu->a & x; 82 | 83 | cpu->carry = false; 84 | 85 | zeroFlag(cpu, z); 86 | 87 | signFlag(cpu, z); 88 | 89 | parityFlag(cpu, z); 90 | 91 | cpu->a = (uint8_t)z; 92 | } 93 | 94 | void xor(cpu8080 *cpu, uint8_t x) 95 | { 96 | uint16_t z = (uint16_t)cpu->a ^ x; 97 | 98 | cpu->carry = false; 99 | 100 | zeroFlag(cpu, z); 101 | 102 | signFlag(cpu, z); 103 | 104 | parityFlag(cpu, z); 105 | 106 | cpu->aux = false; 107 | 108 | cpu->a = (uint8_t)z; 109 | } 110 | 111 | void or(cpu8080 *cpu, uint8_t x) 112 | { 113 | uint16_t z = (uint16_t)cpu->a | x; 114 | 115 | cpu->carry = false; 116 | 117 | zeroFlag(cpu, z); 118 | 119 | signFlag(cpu, z); 120 | 121 | parityFlag(cpu, z); 122 | 123 | cpu->a = (uint8_t)z; 124 | } 125 | 126 | void inr(cpu8080 *cpu, uint8_t *reg) 127 | { 128 | (*reg) += 1; 129 | zeroFlag(cpu, *reg); 130 | signFlag(cpu, *reg); 131 | parityFlag(cpu, *reg); 132 | auxiliaryFlag(cpu, *reg, 1, 1); 133 | carryFlag(cpu, *reg); 134 | } 135 | 136 | void dcr(cpu8080 *cpu, uint8_t *reg) 137 | { 138 | (*reg) -= 1; 139 | zeroFlag(cpu, *reg); 140 | signFlag(cpu, *reg); 141 | parityFlag(cpu, *reg); 142 | auxiliaryFlag(cpu, *reg, 1, 0); 143 | carryFlag(cpu, *reg); 144 | } 145 | 146 | void inx8(uint8_t *x, uint8_t *y) 147 | { 148 | if ((*y) < 0xff) 149 | { 150 | (*y) += 1; 151 | } 152 | 153 | else if ((*x) != 0xff) 154 | { 155 | (*y) = 0; 156 | (*x) += 1; 157 | } 158 | 159 | else 160 | { 161 | (*y) = 0; 162 | (*x) = 0; 163 | } 164 | } 165 | 166 | void inx16(uint16_t *x) 167 | { 168 | if ((*x) != 0xffff) 169 | { 170 | (*x) += 1; 171 | } 172 | 173 | else 174 | { 175 | (*x) = 0; 176 | } 177 | } 178 | 179 | void dcx8(uint8_t *x, uint8_t *y) 180 | { 181 | if ((*y) > 0x00) 182 | { 183 | (*y) -= 1; 184 | } 185 | else if ((*x) != 0x00) 186 | { 187 | (*y) = 0xff; 188 | (*x) -= 1; 189 | } 190 | else 191 | { 192 | (*y) = 0xff; 193 | (*x) = 0xff; 194 | } 195 | } 196 | 197 | void dcx16(uint16_t *x) 198 | { 199 | if ((*x) != 0xffff) 200 | { 201 | (*x) = (*x) - 1; 202 | } 203 | else 204 | { 205 | (*x) = 0x0; 206 | } 207 | } 208 | 209 | void dad(cpu8080 *cpu, uint8_t *x, uint8_t *y) 210 | { 211 | uint16_t x1, y1; 212 | uint32_t z; 213 | 214 | x1 = (uint16_t)(*x); 215 | x1 = x1 << 8; 216 | x1 = x1 | (uint16_t)(*y); 217 | 218 | y1 = (uint16_t)cpu->h; 219 | y1 = y1 << 8; 220 | y1 = y1 | (uint16_t)cpu->l; 221 | 222 | z = x1 + y1; 223 | 224 | carryFlag16(cpu, z); 225 | cpu->l = (uint8_t)(z); 226 | cpu->h = (uint8_t)(z >> 8); 227 | } 228 | 229 | void dad16(cpu8080 *cpu, uint16_t *z) 230 | { 231 | uint16_t x, y; 232 | uint32_t z1; 233 | 234 | x = (uint16_t)(*z); 235 | y = (uint16_t)cpu->h; 236 | y = y << 8; 237 | y = y | (uint16_t)cpu->l; 238 | 239 | z1 = x + y; 240 | 241 | carryFlag16(cpu, z1); 242 | cpu->l = (uint8_t)(z1); 243 | cpu->h = (uint8_t)(z1 >> 8); 244 | } -------------------------------------------------------------------------------- /src/Nightfall.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | typedef struct breakpoints { 4 | uint16_t breakp; 5 | bool active; 6 | struct breakpoints *next; 7 | } breakpoints; 8 | 9 | typedef struct cpu8080 { 10 | // Arithmetic register 11 | uint8_t a; 12 | 13 | // BC register 14 | uint8_t b; 15 | uint8_t c; 16 | 17 | // DE register 18 | uint8_t d; 19 | uint8_t e; 20 | 21 | // HL register 22 | uint8_t h; 23 | uint8_t l; 24 | 25 | // Flags 26 | bool carry; 27 | bool one; 28 | bool parity; 29 | bool zero1; 30 | bool aux; 31 | bool zero2; 32 | bool zero; 33 | bool sign; 34 | 35 | // stack (sp) and program counter (pc) registers 36 | uint16_t sp; 37 | uint16_t pc; 38 | 39 | // a ptr to the memory region 40 | uint8_t *memory; 41 | 42 | // The rest of these are variables for debugging purposes 43 | 44 | // a ptr to the breakpoints 45 | breakpoints *breakpoints; 46 | 47 | // a bool to indicate if it is running 48 | bool running; 49 | 50 | bool breaked; 51 | 52 | // Here are some values, which will keep track of where the various regions of memory are 53 | uint16_t memBeg; // Beginning of entire memory region 54 | uint16_t memEnd; // End of entrie memory region 55 | uint16_t codeBeg; // Beginning of where code is loaded 56 | uint16_t codeEnd; // End of where code is loaded 57 | uint16_t stackBeg; // Beginning of the stack 58 | // the end of the code is kept by codeEnd, and the end of the stack is kep by sp 59 | 60 | bool disasAsExec; // A bool to keep track of whether or not to disassmble intructions as they are executed 61 | 62 | uint8_t step; // A value to keep track of the staus of steeping through instructions, for the step instruction command 63 | 64 | // a bit which controls whether interrupts can happen, currently don't use it for anything. 1 for allow, 0 for disable. 65 | bool allowInterrupt; 66 | 67 | } cpu8080; 68 | 69 | // Here are some constants I declared, for things such as size of memory region, 70 | // where the stack starts, and the file which memory is dumped to 71 | 72 | #define menuInputSize 20 73 | #define memorySize 0xffff 74 | #define startStack 0x4000 75 | #define memoryOutputFile "memory.dat" 76 | 77 | // functions for emulation and disassembling 78 | 79 | void emulate(cpu8080 *cpu); 80 | 81 | int disass(cpu8080 *cpu, int i); 82 | 83 | // Here are the functions which deal with setting flags 84 | 85 | void auxiliaryFlag(cpu8080 *cpu, uint8_t x, uint8_t y, uint8_t z); 86 | 87 | void zeroFlag(cpu8080 *cpu, uint16_t x); 88 | 89 | void signFlag(cpu8080 *cpu, uint16_t x); 90 | 91 | void parityFlag(cpu8080 *cpu, uint16_t x); 92 | 93 | void carryFlag(cpu8080 *cpu, uint16_t x); 94 | 95 | void carryFlagSub(cpu8080 *cpu, uint16_t x); 96 | 97 | void carryFlag16(cpu8080 *cpu, uint32_t x); 98 | 99 | // Here are the functions which deal with math functions, incrementing and decrementing 100 | 101 | void add(cpu8080 *cpu, uint8_t x); 102 | 103 | void adc(cpu8080 *cpu, uint8_t x); 104 | 105 | void sub(cpu8080 *cpu, uint8_t x); 106 | 107 | void sbb(cpu8080 *cpu, uint8_t x); 108 | 109 | void and(cpu8080 *cpu, uint8_t x); 110 | 111 | void xor(cpu8080 *cpu, uint8_t x); 112 | 113 | void or(cpu8080 *cpu, uint8_t x); 114 | 115 | void inr(cpu8080 *cpu, uint8_t *reg); 116 | 117 | void dcr(cpu8080 *cpu, uint8_t *reg); 118 | 119 | void inx8(uint8_t *x, uint8_t *y); 120 | 121 | void inx16(uint16_t *x); 122 | 123 | void dcx8(uint8_t *x, uint8_t *y); 124 | 125 | void dcx16(uint16_t *x); 126 | 127 | // These are functions which essentially deal with moving values around 128 | 129 | void stax(cpu8080 *cpu, uint8_t x, uint8_t y); 130 | 131 | void ldax(cpu8080 *cpu, uint8_t x, uint8_t y); 132 | 133 | void mvi(cpu8080 *cpu, uint8_t *reg, uint8_t arg); 134 | 135 | void lxi(cpu8080 *cpu, uint8_t *x, uint8_t *y); 136 | 137 | void lxi16(cpu8080 *cpu, uint16_t *x); 138 | 139 | void dad(cpu8080 *cpu, uint8_t *x, uint8_t *y); 140 | 141 | void dad16(cpu8080 *cpu, uint16_t *z); 142 | 143 | // Here are the functions which deal with poping / pushing 144 | 145 | void pop(cpu8080 *cpu, uint8_t *x, uint8_t *y); 146 | 147 | void push(cpu8080 *cpu, uint8_t x, uint8_t y); 148 | 149 | void push16(cpu8080 *cpu, uint16_t x); 150 | 151 | void popPsw(cpu8080 *cpu); 152 | 153 | // Here are the functions which deal with comparisons, and redircting code execution 154 | 155 | void cmp(cpu8080 *cpu, uint8_t x); 156 | 157 | void jmp(cpu8080 *cpu, uint8_t x, uint8_t y); 158 | 159 | void call(cpu8080 *cpu, uint8_t x, uint8_t y); 160 | 161 | void ret(cpu8080 *cpu); 162 | 163 | void rst(cpu8080 *cpu, uint16_t x); 164 | 165 | // Here are some functions to help with various parts of the code 166 | 167 | uint8_t convertFlagsRegister(cpu8080 *cpu); 168 | 169 | int uintConvert(uint8_t x, uint8_t y); 170 | 171 | int charToInt(char * inp); 172 | 173 | char *removeBeginning(char *inp); 174 | 175 | int hexDecimaltoInt(char *arg); 176 | 177 | void printTwoArgs(cpu8080 *cpu, int pc); 178 | 179 | void printTwoArgsBack(cpu8080 *cpu, int pc); 180 | 181 | void setSpecificFlagPsw(cpu8080 *cpu, int x, int cmp, bool *flag); 182 | 183 | void setCode(cpu8080 *cpu, char *code, int size); 184 | 185 | void scanBinary(char *fileName, cpu8080 *cpu); 186 | 187 | long int getFileSize(FILE *fp); 188 | 189 | // Here are some functions to help with the debugging functionallity 190 | 191 | int isBreakPoint(cpu8080 *cpu); 192 | 193 | breakpoints *findLastBreakpoint(breakpoints *breakpoint); 194 | 195 | breakpoints *allocateBreakpoint(uint16_t x); 196 | 197 | int checkBreakPoint(breakpoints * breakpt, uint16_t x); 198 | 199 | // Here are functions which handle the debugger commands 200 | 201 | void activateBreakpoint(cpu8080 *cpu, char *menuInput); 202 | 203 | void createBreakpoint(cpu8080 *cpu, char *menuInput); 204 | 205 | void deactivateBreakpoint(cpu8080 *cpu, char *menuInput); 206 | 207 | void disassembleAll(cpu8080 *cpu); 208 | 209 | void printHelp(void); 210 | 211 | void printRegisters(cpu8080 *cpu); 212 | 213 | void showBreakpoints(breakpoints *breakpoint, int n); 214 | 215 | void printFlags(cpu8080 *cpu); 216 | 217 | void jumpExec(cpu8080 *cpu, char *input); 218 | 219 | void printMemoryRegions(cpu8080 *cpu); 220 | 221 | void printRegister(cpu8080 *cpu, char *menuInput); 222 | 223 | void resetExecution(cpu8080 *cpu); 224 | 225 | cpu8080 *createCpu(void); 226 | 227 | void destroyCpu(cpu8080 *cpu); 228 | 229 | void stepInstruction(cpu8080 *cpu); 230 | 231 | void toggleDisassExec(cpu8080 *cpu); 232 | 233 | void dumpMemory(cpu8080 *cpu); 234 | 235 | void examineMemory(cpu8080 *cpu, char *inp); 236 | 237 | void resetExecution(cpu8080 *cpu); 238 | 239 | void set(cpu8080 *cpu, char *inp); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Nightfall 2 | ## 8080 Emulator / Debugger / Disassembler 3 | 4 | This is a custom emulator that I wrote for the 16 bit intel 8080 architecture, that is also a debugger, and a disassembler. I mainly wrote this, so I could learn how to make these things. 5 | 6 | ## Compiling 7 | 8 | To compile the code, you can just use make. All of the source code is under `src`: 9 | 10 | ``` 11 | $ git clone git@github.com:guyinatuxedo/Nightfall-Emulator.git 12 | $ cd Nightfall-Emulator/src/ 13 | $ make 14 | gcc Nightfall.c emulate.c debugCmds.c disass.c flagSet.c math.c stack.c utills.c debugUtils.c codeExec.c mov.c -o Nightfall 15 | ``` 16 | 17 | ## Disassembler 18 | 19 | When I was first working on this, I made a python disassembler, which you can find under `disassembler`. 20 | 21 | ## How to make 22 | 23 | I documented how to make an emulator, debugger, and disassembler under `how-to-make`. 24 | 25 | ## Use 26 | 27 | To use the emulator, it takes a single argument which is the binary file you wish to emulate: 28 | 29 | ``` 30 | $ ./Nightfall block2/testcase007 31 | Nightfall 8080 Emualtor / Debugger / Disassembler 32 | ndb> 33 | ``` 34 | 35 | you can disassemble a loaded file with the `e` command: 36 | ``` 37 | ndb> e 38 | 0x0: mvi b, 0x4 39 | 0x2: mvi c, 0x10 40 | 0x4: mvi d, 0x88 41 | 0x6: mvi e, 0xba 42 | 0x8: mvi h, 0x5 43 | 0xa: mvi l, 0x6 44 | 0xc: mvi m, 0x27 45 | 0xe: mvi a, 0x4 46 | 0x10: add b 47 | 0x11: add c 48 | 0x12: add d 49 | 0x13: add e 50 | 0x14: add h 51 | 0x15: add l 52 | 0x16: add m 53 | 0x17: add a 54 | 0x18: end 0x66 55 | ``` 56 | 57 | to emulate the binary, use `r`: 58 | ``` 59 | ndb> r 60 | ``` 61 | 62 | to set a breakpoint for `0x6`, use `b `: 63 | ``` 64 | ndb> b 0x6 65 | ndb> r 66 | Breakpoint hit at 0x6 67 | ``` 68 | 69 | to list all breakpoints, use `z`: 70 | ``` 71 | ndb> z 72 | Breakpoint 0x0 at 6 (active: 1) 73 | Breakpoint 0x1 at a (active: 1) 74 | Breakpoint 0x2 at e (active: 1) 75 | ``` 76 | 77 | to deactivate a breakpoint, use `d `: 78 | ``` 79 | ndb> d 0x2 80 | ndb> z 81 | Breakpoint 0x0 at 6 (active: 1) 82 | Breakpoint 0x1 at a (active: 1) 83 | Breakpoint 0x2 at e (active: 0) 84 | ``` 85 | 86 | to activate a breakpoint, use `a `: 87 | ``` 88 | ndb> a 0x2 89 | ndb> z 90 | Breakpoint 0x0 at 6 (active: 1) 91 | Breakpoint 0x1 at a (active: 1) 92 | Breakpoint 0x2 at e (active: 1) 93 | ``` 94 | 95 | to continue execution after you have hit a breakpoint, use `c`: 96 | 97 | ``` 98 | ndb> r 99 | Breakpoint hit at 0x6 100 | ndb> c 101 | Breakpoint hit at 0xa 102 | ndb> c 103 | Breakpoint hit at 0xe 104 | ndb> c 105 | ``` 106 | 107 | to list the contents of all of the registers and flags, use `i`: 108 | ``` 109 | ndb> r 110 | Breakpoint hit at 0x6 111 | ndb> i 112 | 8 bit registers 113 | register a: 0x0 114 | register b: 0x4 115 | register c: 0x10 116 | register d: 0x88 117 | register e: 0x0 118 | register h: 0x0 119 | register l: 0x0 120 | 121 | 16 bit registers 122 | register bc: 0x410 123 | register de: 0x8800 124 | register hl: 0x0 125 | register af: 0x2 126 | 127 | Flags 128 | 7: Sign flag: 0 129 | 6: Zero flag: 0 130 | 5: zero1 flag (value shouldn't change): 0 131 | 4: Auxillary flag: 0 132 | 3: zero2 flag (value shouldn't change): 0 133 | 2: Parity flag: 0 134 | 1: one flag (value shouldn't change): 1 135 | 0: Carry flag: 0 136 | 137 | Stack registers (16 bit) 138 | register pc: 0x6 139 | register sp: 0x4000 140 | 141 | Interrupt bit: 0x1 142 | ``` 143 | 144 | to jump to a different place of the code manually, use `j` (you will need to continue using `c` afterwards): 145 | ``` 146 | ndb> z 147 | Breakpoint 0x0 at 6 (active: 1) 148 | Breakpoint 0x1 at a (active: 1) 149 | Breakpoint 0x2 at e (active: 1) 150 | ndb> r 151 | Breakpoint hit at 0x6 152 | ndb> j 0xe 153 | ndb> c 154 | Breakpoint hit at 0xe 155 | ``` 156 | 157 | to list the memory mapping use `m`(just tells you where the stack, code, and total memroy regions are): 158 | 159 | ``` 160 | ndb> r 161 | Breakpoint hit at 0x6 162 | ndb> m 163 | Total Memory Region: 0x0 - 0xffff 164 | Code Memory Region: 0x0 - 0x19 165 | Stack Memory Region: 0x4000 - 0x4000 166 | ``` 167 | 168 | to print the contents of a register, use `p `: 169 | ``` 170 | ndb> r 171 | Breakpoint hit at 0x6 172 | ndb> p d 173 | register d: 0x88 174 | ndb> p de 175 | register de: 0x8800 176 | ``` 177 | 178 | to quit the debugger, use `q`: 179 | ``` 180 | ndb> r 181 | Breakpoint hit at 0x6 182 | ndb> q 183 | ``` 184 | 185 | to step an instruction, use `s` (just execute the next instruction): 186 | ``` 187 | ndb> r 188 | Breakpoint hit at 0x6 189 | ndb> p e 190 | register e: 0x0 191 | ndb> s 192 | Stepped to 0x8 193 | ndb> p e 194 | register e: 0xba 195 | ``` 196 | 197 | to toggle disassemble use `t` (disassembles all instructions that are ran): 198 | ``` 199 | ndb> t 200 | ndb> r 201 | 0x0: mvi b, 0x4 202 | 0x2: mvi c, 0x10 203 | 0x4: mvi d, 0x88 204 | Breakpoint hit at 0x6 205 | ndb> c 206 | 0x6: mvi e, 0xba 207 | 0x8: mvi h, 0x5 208 | Breakpoint hit at 0xa 209 | ndb> c 210 | 0xa: mvi l, 0x6 211 | 0xc: mvi m, 0x27 212 | Breakpoint hit at 0xe 213 | ndb> c 214 | 0xe: mvi a, 0x4 215 | 0x10: add b 216 | 0x11: add c 217 | 0x12: add d 218 | 0x13: add e 219 | 0x14: add h 220 | 0x15: add l 221 | 0x16: add m 222 | 0x17: add a 223 | 0x18: end 0x66 224 | ``` 225 | 226 | to dump the contents of the memory to the file `memory.dat`, use `u` (dumps all memory between `0x0` - `0xffff`): 227 | ``` 228 | ndb> r 229 | Breakpoint hit at 0x6 230 | ndb> u 231 | ndb> q 232 | $ ls | grep memory.dat 233 | memory.dat 234 | ``` 235 | 236 | to examine a memory address, use `x ` (this example uses a different testcase): 237 | ``` 238 | ./Nightfall block1/testcase004 239 | Nightfall 8080 Emualtor / Debugger / Disassembler 240 | ndb> e 241 | 0x0: mvi h, 0x20 242 | 0x2: mvi l, 0x40 243 | 0x4: mov c, l 244 | 0x5: mov a, l 245 | 0x6: mov d, h 246 | 0x7: mov b, a 247 | 0x8: mvi c, 0x0 248 | 0xa: mov c, b 249 | 0xb: mov e, b 250 | 0xc: mov e, d 251 | 0xd: mov m, b 252 | 0xe: mov m, c 253 | 0xf: mov m, d 254 | 0x10: mov m, e 255 | 0x11: mov m, h 256 | 0x12: mov m, l 257 | 0x13: mov m, a 258 | 0x14: end 0x66 259 | ndb> b 0xd 260 | ndb> r 261 | Breakpoint hit at 0xd 262 | ndb> p b 263 | register b: 0x40 264 | ndb> p hl 265 | register hl: 0x2040 266 | ndb> x 0x2040 267 | 0x2040: 0x0 268 | ndb> s 269 | Stepped to 0xe 270 | ndb> x 0x2040 271 | 0x2040: 0x40 272 | ``` 273 | 274 | to set a register, or memory address to a specific `8` bit value, use either `y ` or `y `. This uses testcase004 (same as `x`) : 275 | ``` 276 | ndb> r 277 | Breakpoint hit at 0xd 278 | ndb> p hl 279 | register hl: 0x2040 280 | ndb> x 0x2040 281 | 0x2040: 0x0 282 | ndb> p b 283 | register b: 0x40 284 | ndb> y b 0x66 285 | ndb> p b 286 | register b: 0x66 287 | ndb> s 288 | Stepped to 0xe 289 | ndb> x 0x2040 290 | 0x2040: 0x66 291 | ``` 292 | or to set an address equal to a value: 293 | 294 | ``` 295 | ndb> x 0x2040 296 | 0x2040: 0x40 297 | ndb> y 0x2040 0x66 298 | ndb> x 0x2040 299 | 0x2040: 0x66 300 | ``` 301 | 302 | to print the help menu: 303 | ``` 304 | ndb> h 305 | Help Menu 306 | a - Activate a previously deacticated breakpoint 307 | b - Set a breakpoint at the address 308 | c - Continue execution from a breakpoint 309 | d - Deactivate a breakpoint 310 | e - Disassemble all code in binary 311 | h - Print help menu 312 | i - Display values of all registers and flags 313 | j - Set the next address to be executed (essentially a jump, but need to continue) 314 | m - Print the addresses for memory regions 315 | p - Prints contents of register 316 | q - Quit the emulator/debugger 317 | r - Run the emulator from the start 318 | s - Step to the next instruction 319 | t - Toggle running disassembly, which disassembles instructions as they are ran 320 | u - Dump the contents of memory to the file memory.dat 321 | x - Print amnt 8 bit segments starting at adr (if single argument given, amnt is 1) 322 | y - Set target register or address to value 323 | z - Show all breakpoints, and if they are activated 324 | ``` 325 | 326 | ## Sources 327 | 328 | Here are some sources which have really helped me with writing this: 329 | ``` 330 | https://pmd85.borik.net/instrset/instuction-set.html 331 | http://www.emulator101.com/reference/8080-by-opcode.html 332 | http://pastraiser.com/cpu/i8080/i8080_opcodes.html 333 | http://altairclone.com/downloads/manuals/8080%20Programmers%20Manual.pdf 334 | ^8080 manual 335 | http://www.emulator101.com/ 336 | ``` 337 | 338 | ## End Instruction 339 | 340 | I implemented the opcode `0xdd` to include end functionallity with the emulator. It takes a single argument indicating what you want to do, and at them moment I have only one option which is `0x66` which ends the program. So if you see `0xdd66` or `end 0x66` that ends the program. 341 | -------------------------------------------------------------------------------- /src/debugCmds.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "Nightfall.h" 6 | 7 | // This source file holds functions which deal with various debugger commands 8 | 9 | void activateBreakpoint(cpu8080 *cpu, char *menuInput) 10 | { 11 | int i, n; 12 | breakpoints *b; 13 | b = cpu->breakpoints; 14 | 15 | if (b == NULL) 16 | { 17 | puts("There are no breakpoints."); 18 | return; 19 | } 20 | 21 | n = charToInt(menuInput); 22 | for (i = 0; i < n; i++) 23 | { 24 | b = b->next; 25 | if (b == NULL) 26 | { 27 | puts("That breakpoint doesn't exist"); 28 | return; 29 | } 30 | } 31 | 32 | b->active = true; 33 | } 34 | 35 | void createBreakpoint(cpu8080 *cpu, char *menuInput) 36 | { 37 | char *arg; 38 | int x; 39 | breakpoints *last, *next; 40 | last = findLastBreakpoint(cpu->breakpoints); 41 | 42 | x = charToInt(menuInput); 43 | 44 | next = allocateBreakpoint((uint16_t) x); 45 | next->active = true; 46 | if (last == NULL) 47 | { 48 | cpu->breakpoints = next; 49 | } 50 | else 51 | { 52 | last->next = next; 53 | } 54 | } 55 | 56 | void deactivateBreakpoint(cpu8080 *cpu, char *menuInput) 57 | { 58 | int i, n; 59 | breakpoints *b; 60 | b = cpu->breakpoints; 61 | 62 | if (b == NULL) 63 | { 64 | puts("There are no breakpoints."); 65 | return; 66 | } 67 | 68 | n = charToInt(menuInput); 69 | for (i = 0; i < n; i++) 70 | { 71 | b = b->next; 72 | if (b == NULL) 73 | { 74 | puts("That breakpoint doesn't exist"); 75 | return; 76 | } 77 | } 78 | 79 | b->active = false; 80 | } 81 | 82 | void disassembleAll(cpu8080 *cpu) 83 | { 84 | int i; 85 | i = 0; 86 | while (i < (cpu->codeEnd + 1)) 87 | { 88 | i = disass(cpu, i); 89 | } 90 | } 91 | 92 | void printHelp(void) 93 | { 94 | puts("Help Menu"); 95 | puts("a - Activate a previously deacticated breakpoint"); 96 | puts("b - Set a breakpoint at the address"); 97 | puts("c - Continue execution from a breakpoint"); 98 | puts("d - Deactivate a breakpoint"); 99 | puts("e - Disassemble all code in binary"); 100 | puts("h - Print help menu"); 101 | puts("i - Display values of all registers and flags"); 102 | puts("j - Set the next address to be executed (essentially a jump, but need to continue)"); 103 | puts("m - Print the addresses for memory regions"); 104 | puts("p - Prints contents of register"); 105 | puts("q - Quit the emulator/debugger"); 106 | puts("r - Run the emulator from the start"); 107 | puts("s - Step to the next instruction"); 108 | puts("t - Toggle running disassembly, which disassembles instructions as they are ran"); 109 | puts("u - Dump the contents of memory to the file memory.dat"); 110 | puts("x - Print amnt 8 bit segments starting at adr (if single argument given, amnt is 1)"); 111 | puts("y - Set target register or address to value"); 112 | puts("z - Show all breakpoints, and if they are activated"); 113 | } 114 | 115 | void printRegisters(cpu8080 *cpu) 116 | { 117 | puts("8 bit registers"); 118 | printf("register a: 0x%x\n", (int)cpu->a); 119 | printf("register b: 0x%x\n", (int)cpu->b); 120 | printf("register c: 0x%x\n", (int)cpu->c); 121 | printf("register d: 0x%x\n", (int)cpu->d); 122 | printf("register e: 0x%x\n", (int)cpu->e); 123 | printf("register h: 0x%x\n", (int)cpu->h); 124 | printf("register l: 0x%x\n", (int)cpu->l); 125 | 126 | puts("\n16 bit registers"); 127 | printf("register bc: 0x%x\n", (int)uintConvert(cpu->b, cpu->c)); 128 | printf("register de: 0x%x\n", (int)uintConvert(cpu->d, cpu->e)); 129 | printf("register hl: 0x%x\n", (int)uintConvert(cpu->h, cpu->l)); 130 | printf("register af: 0x%x\n", (int)uintConvert(cpu->a, convertFlagsRegister(cpu))); 131 | 132 | printFlags(cpu); 133 | 134 | puts("\nStack registers (16 bit)"); 135 | printf("register pc: 0x%x\n", (int)cpu->pc); 136 | printf("register sp: 0x%x\n", (int)cpu->sp); 137 | 138 | printf("\nInterrupt bit: 0x%x\n", cpu->allowInterrupt); 139 | return; 140 | } 141 | 142 | void printFlags(cpu8080 *cpu) 143 | { 144 | puts("\nFlags"); 145 | printf("7: Sign flag: %d\n", (int)cpu->sign); 146 | printf("6: Zero flag: %d\n", (int)cpu->zero); 147 | printf("5: zero1 flag (value shouldn't change): %d\n", cpu->zero1); 148 | printf("4: Auxillary flag: %d\n", (int)cpu->aux); 149 | printf("3: zero2 flag (value shouldn't change): %d\n", cpu->zero2); 150 | printf("2: Parity flag: %d\n", (int)cpu->parity); 151 | printf("1: one flag (value shouldn't change): %d\n", cpu->one); 152 | printf("0: Carry flag: %d\n", (int)cpu->carry); 153 | } 154 | 155 | void jumpExec(cpu8080 *cpu, char *input) 156 | { 157 | int instr; 158 | instr = charToInt(input); 159 | cpu->pc = instr - 1; 160 | } 161 | 162 | void printMemoryRegions(cpu8080 *cpu) 163 | { 164 | printf("Total Memory Region:\t 0x%x - 0x%x\n", (int)cpu->memBeg, (int)cpu->memEnd); 165 | printf("Code Memory Region:\t 0x%x - 0x%x\n", (int)cpu->codeBeg, (int)cpu->codeEnd); 166 | printf("Stack Memory Region:\t 0x%x - 0x%x\n", (int)cpu->stackBeg, (int)cpu->sp); 167 | } 168 | 169 | void printRegister(cpu8080 *cpu, char *menuInput) 170 | { 171 | char *arg; 172 | 173 | arg = removeBeginning(menuInput); 174 | 175 | if (strncmp(arg, "bc", 2) == 0) 176 | { 177 | printf("register bc: 0x%x\n", (int)uintConvert(cpu->b, cpu->c)); 178 | } 179 | 180 | else if (strncmp(arg, "de", 2) == 0) 181 | { 182 | printf("register de: 0x%x\n", (int)uintConvert(cpu->d, cpu->e)); 183 | } 184 | 185 | else if (strncmp(arg, "hl", 2) == 0) 186 | { 187 | printf("register hl: 0x%x\n", (int)uintConvert(cpu->h, cpu->l)); 188 | } 189 | 190 | else if (strncmp(arg, "af", 2) == 0) 191 | { 192 | printf("register af: 0x%x\n", (int)uintConvert(cpu->h, convertFlagsRegister(cpu))); 193 | } 194 | 195 | else if (strncmp(arg, "pc", 2) == 0) 196 | { 197 | printf("register pc: 0x%x\n", (int)cpu->pc); 198 | } 199 | 200 | else if (strncmp(arg, "sp", 2) == 0) 201 | { 202 | printf("register sp: 0x%x\n", (int)cpu->sp); 203 | } 204 | 205 | else 206 | { 207 | switch(arg[0]) 208 | { 209 | case 'a': 210 | printf("register a: 0x%x\n", (uint16_t)cpu->a); 211 | break; 212 | case 'b': 213 | printf("register b: 0x%x\n", (uint16_t)cpu->b); 214 | break; 215 | case 'c': 216 | printf("register c: 0x%x\n", (uint16_t)cpu->c); 217 | break; 218 | case 'd': 219 | printf("register d: 0x%x\n", (uint16_t)cpu->d); 220 | break; 221 | case 'e': 222 | printf("register e: 0x%x\n", (uint16_t)cpu->e); 223 | break; 224 | case 'h': 225 | printf("register h: 0x%x\n", (uint16_t)cpu->h); 226 | break; 227 | case 'l': 228 | printf("register l: 0x%x\n", (uint16_t)cpu->l); 229 | break; 230 | case 'f': 231 | printFlags(cpu); 232 | break; 233 | } 234 | } 235 | 236 | free(arg); 237 | return; 238 | } 239 | 240 | void resetExecution(cpu8080 *cpu) 241 | { 242 | // Set the flags to their default values 243 | cpu->carry = 0; 244 | cpu->one = 1; 245 | cpu->parity = 0; 246 | cpu->zero = 0; 247 | cpu->aux = 0; 248 | cpu->zero1 = 0; 249 | cpu->sign = 0; 250 | 251 | // Set the registers to their default values 252 | cpu->a = 0x0; 253 | cpu->b = 0x0; 254 | cpu->c = 0x0; 255 | cpu->d = 0x0; 256 | cpu->e = 0x0; 257 | cpu->h = 0x0; 258 | cpu->l = 0x0; 259 | 260 | // Initialize the stack pointer, and the program counter 261 | cpu->sp = startStack; 262 | cpu->pc = 0x0; 263 | 264 | cpu->running = false; 265 | cpu->breaked = false; 266 | 267 | cpu->step = 0; 268 | } 269 | 270 | cpu8080 *createCpu(void) 271 | { 272 | cpu8080 *cpu; 273 | 274 | // Allocate memory for the cpu 275 | cpu = calloc(1, sizeof(cpu8080)); 276 | 277 | // Allocate the memory for the cpu 278 | cpu->memory = calloc(1, memorySize); 279 | 280 | // Set the flags to their default values 281 | cpu->carry = 0; 282 | cpu->one = 1; 283 | cpu->parity = 0; 284 | cpu->zero = 0; 285 | cpu->aux = 0; 286 | cpu->zero1 = 0; 287 | cpu->sign = 0; 288 | 289 | // Set the registers to their default values 290 | cpu->a = 0x0; 291 | cpu->b = 0x0; 292 | cpu->c = 0x0; 293 | cpu->d = 0x0; 294 | cpu->e = 0x0; 295 | cpu->h = 0x0; 296 | cpu->l = 0x0; 297 | 298 | // Initialize the stack pointer, and the program counter 299 | cpu->sp = (uint16_t)startStack; 300 | cpu->pc = 0x0; 301 | 302 | cpu->allowInterrupt = 1; 303 | 304 | cpu->breakpoints = NULL; 305 | 306 | cpu->running = false; 307 | 308 | cpu->breaked = false; 309 | 310 | // Set the values for the memory locations 311 | cpu->memBeg = (uint16_t)0; 312 | cpu->memEnd = (uint16_t)memorySize; 313 | cpu->stackBeg = (uint16_t)startStack; 314 | 315 | cpu->disasAsExec = false; 316 | 317 | return cpu; 318 | } 319 | 320 | void freeBreakpoints(breakpoints *breakpoint) 321 | { 322 | breakpoints *next; 323 | if (breakpoint == NULL) 324 | { 325 | return; 326 | } 327 | else 328 | { 329 | next = breakpoint->next; 330 | free(breakpoint); 331 | freeBreakpoints(next); 332 | } 333 | } 334 | 335 | void destroyCpu(cpu8080 *cpu) 336 | { 337 | free(cpu->memory); 338 | cpu->memory = 0; 339 | freeBreakpoints(cpu->breakpoints); 340 | free(cpu); 341 | cpu = 0; 342 | return; 343 | } 344 | 345 | void stepInstruction(cpu8080 *cpu) 346 | { 347 | cpu->step = 1; 348 | } 349 | 350 | void toggleDisassExec(cpu8080 *cpu) 351 | { 352 | if (cpu->disasAsExec == false) 353 | { 354 | cpu->disasAsExec = true; 355 | } 356 | else 357 | { 358 | cpu->disasAsExec = false; 359 | } 360 | } 361 | 362 | void dumpMemory(cpu8080 *cpu) 363 | { 364 | FILE *fp = fopen(memoryOutputFile, "w"); 365 | if (fp == NULL) 366 | { 367 | puts("Could not open output file"); 368 | } 369 | 370 | fwrite(cpu->memory, sizeof(uint8_t), memorySize, fp); 371 | fclose(fp); 372 | return; 373 | } 374 | 375 | void examineMemory(cpu8080 *cpu, char *inp) 376 | { 377 | char *arg0, *arg1; 378 | int x, y, i; 379 | 380 | arg0 = strtok(inp, " "); 381 | if (arg0 == NULL) 382 | { 383 | puts("No args"); 384 | return; 385 | } 386 | 387 | arg0 = strtok(NULL, " "); 388 | if (arg0 == NULL) 389 | { 390 | puts("one args"); 391 | return; 392 | } 393 | 394 | arg1 = strtok(NULL, " "); 395 | if (arg1 == NULL) 396 | { 397 | x = hexDecimaltoInt(arg0); 398 | printf("0x%x: 0x%x\n", x, cpu->memory[x]); 399 | return; 400 | } 401 | else 402 | { 403 | x = hexDecimaltoInt(arg0); 404 | y = hexDecimaltoInt(arg1); 405 | for (i = 0; i < x; i++) 406 | { 407 | printf("0x%x: 0x%x\n", y + i, cpu->memory[y + i]); 408 | } 409 | return; 410 | } 411 | } 412 | 413 | void showBreakpoints(breakpoints *breakpoint, int n) 414 | { 415 | if (breakpoint == NULL) 416 | { 417 | return; 418 | } 419 | else 420 | { 421 | printf("Breakpoint 0x%x at %x\t\t(active: %d)\n", n, breakpoint->breakp, (int)breakpoint->active); 422 | return showBreakpoints(breakpoint->next, n + 1); 423 | } 424 | } 425 | 426 | void set(cpu8080 *cpu, char *inp) 427 | { 428 | char *arg0, *arg1; 429 | int x, y, i; 430 | 431 | arg0 = strtok(inp, " "); 432 | if (arg0 == NULL) 433 | { 434 | puts("This command requires two arguments."); 435 | return; 436 | } 437 | 438 | arg0 = strtok(NULL, " "); 439 | if (arg0 == NULL) 440 | { 441 | puts("This command requires two arguments."); 442 | return; 443 | } 444 | 445 | arg1 = strtok(NULL, " "); 446 | if (arg1 == NULL) 447 | { 448 | puts("This command requires two arguments."); 449 | return; 450 | } 451 | else 452 | { 453 | y = hexDecimaltoInt(arg1); 454 | switch (*arg0) 455 | { 456 | case 0x61: 457 | cpu->a = y; 458 | break; 459 | 460 | case 0x62: 461 | cpu->b = y; 462 | break; 463 | 464 | case 0x63: 465 | cpu->c = y; 466 | break; 467 | 468 | case 0x64: 469 | cpu->d = y; 470 | break; 471 | 472 | case 0x65: 473 | cpu->e = y; 474 | break; 475 | 476 | case 0x68: 477 | cpu->h = y; 478 | break; 479 | 480 | case 0x6c: 481 | cpu->l = y; 482 | break; 483 | 484 | default: 485 | if (strncmp(arg0, "sp", 2) == 0) 486 | { 487 | cpu->sp = y; 488 | return; 489 | } 490 | if (strncmp(arg0, "pc", 2) == 0) 491 | { 492 | cpu->pc = y; 493 | return; 494 | } 495 | x = hexDecimaltoInt(arg0); 496 | cpu->memory[x] = y; 497 | break; 498 | } 499 | return; 500 | } 501 | } -------------------------------------------------------------------------------- /disassembler/disassemble.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | 4 | def decompile(contents): 5 | i = 0 6 | limit = len(contents) 7 | while i < limit: 8 | if contents[i] == "\x00": 9 | print hex(i) + ": nop" 10 | elif contents[i] == "\x01": 11 | print hex(i) + ": lxi b " + hex(ord(contents[i + 2])) + hex(ord(contents[i + 1])).replace("0x", "") 12 | i += 2 13 | elif contents[i] == "\x02": 14 | print hex(i) + ": stax b" 15 | elif contents[i] == "\x03": 16 | print hex(i) + ": inx b" 17 | elif contents[i] == "\x04": 18 | print hex(i) + ": inr b" 19 | elif contents[i] == "\x05": 20 | print hex(i) + ": dcr b" 21 | elif contents[i] == "\x06": 22 | print hex(i) + ": mvi b, " + hex(ord(contents[i + 1])) 23 | i += 1 24 | elif contents[i] == "\x07": 25 | print hex(i) + ": rlc" 26 | elif contents[i] == "\x09": 27 | print hex(i) + ": dad b" 28 | elif contents[i] == "\x0a": 29 | print hex(i) + ": ldax b" 30 | elif contents[i] == "\x0b": 31 | print hex(i) + ": inr c" 32 | elif contents[i] == "\x0c": 33 | print hex(i) + ": dcr c" 34 | elif contents[i] == "\x0d": 35 | print hex(i) + ": dcr c" 36 | elif contents[i] == "\x0e": 37 | print hex(i) + ": mvi c, " + hex(ord(contents[i + 1])) 38 | i += 1 39 | elif contents[i] == "\x0f": 40 | print hex(i) + ": rrc" 41 | 42 | 43 | elif contents[i] == "\x11": 44 | print hex(i) + ": lxi d " + hex(ord(contents[i + 2])) + hex(ord(contents[i + 1])).replace("0x", "") 45 | i += 2 46 | elif contents[i] == "\x12": 47 | print hex(i) + ": stax d" 48 | elif contents[i] == "\x13": 49 | print hex(i) + ": inx d" 50 | elif contents[i] == "\x14": 51 | print hex(i) + ": inr d" 52 | elif contents[i] == "\x15": 53 | print hex(i) + ": dcr d" 54 | elif contents[i] == "\x16": 55 | print hex(i) + ": mvi d, " + hex(ord(contents[i + 1])) 56 | i += 1 57 | elif contents[i] == "\x17": 58 | print hex(i) + ": ral" 59 | elif contents[i] == "\x19": 60 | print hex(i) + ": dad d" 61 | elif contents[i] == "\x1a": 62 | print hex(i) + ": ldax d" 63 | elif contents[i] == "\x1b": 64 | print hex(i) + ": dcx d" 65 | elif contents[i] == "\x1c": 66 | print hex(i) + ": inr e" 67 | elif contents[i] == "\x1d": 68 | print hex(i) + ": dcr e" 69 | elif contents[i] == "\x1e": 70 | print hex(i) + ": mvi e, " + hex(ord(contents[i + 1])) 71 | i += 1 72 | elif contents[i] == "\x1f": 73 | print hex(i) + ": rar" 74 | 75 | 76 | elif contents[i] == "\x21": 77 | print hex(i) + ": lxi h " + hex(ord(contents[i + 2])) + hex(ord(contents[i + 1])).replace("0x", "") 78 | i += 2 79 | elif contents[i] == "\x22": 80 | print hex(i) + ": shld " + hex(ord(contents[i + 2])) + hex(ord(contents[i + 1])).replace("0x", "") 81 | i += 2 82 | elif contents[i] == "\x23": 83 | print hex(i) + ": inx h" 84 | elif contents[i] == "\x24": 85 | print hex(i) + ": inr h" 86 | elif contents[i] == "\x25": 87 | print hex(i) + ": dcr h" 88 | elif contents[i] == "\x26": 89 | print hex(i) + ": mvi h, " + hex(ord(contents[i + 1])) 90 | i += 1 91 | elif contents[i] == "\x27": 92 | print hex(i) + ": daa" 93 | elif contents[i] == "\x29": 94 | print hex(i) + ": dad h" 95 | elif contents[i] == "\x2a": 96 | print hex(i) + ": lhld " + hex(ord(contents[i + 2])) + hex(ord(contents[i + 1])).replace("0x", "") 97 | i += 2 98 | elif contents[i] == "\x2b": 99 | print hex(i) + ": dcx h" 100 | elif contents[i] == "\x2c": 101 | print hex(i) + ": inr l" 102 | elif contents[i] == "\x2d": 103 | print hex(i) + ": dcr l" 104 | elif contents[i] == "\x2e": 105 | print hex(i) + ": mvi l, " + hex(ord(contents[i + 1])) 106 | i += 1 107 | elif contents[i] == "\x2f": 108 | print hex(i) + ": cma" 109 | 110 | elif contents[i] == "\x21": 111 | print hex(i) + ": lxi sp " + hex(ord(contents[i + 2])) + hex(ord(contents[i + 1])).replace("0x", "") 112 | i += 2 113 | elif contents[i] == "\x32": 114 | print hex(i) + ": sta " + hex(ord(contents[i + 2])) + hex(ord(contents[i + 1])).replace("0x", "") 115 | i += 2 116 | elif contents[i] == "\x33": 117 | print hex(i) + ": inx sp" 118 | elif contents[i] == "\x34": 119 | print hex(i) + ": inr m" 120 | elif contents[i] == "\x35": 121 | print hex(i) + ": dcr m" 122 | elif contents[i] == "\x36": 123 | print hex(i) + ": mvi m, " + hex(ord(contents[i + 1])) 124 | i += 1 125 | elif contents[i] == "\x37": 126 | print hex(i) + ": stc" 127 | elif contents[i] == "\x39": 128 | print hex(i) + ": dad sp" 129 | elif contents[i] == "\x3a": 130 | print hex(i) + ": lda " + hex(ord(contents[i + 2])) + hex(ord(contents[i + 1])).replace("0x", "") 131 | i += 2 132 | elif contents[i] == "\x3b": 133 | print hex(i) + ": dcx sp" 134 | elif contents[i] == "\x3c": 135 | print hex(i) + ": inr a" 136 | elif contents[i] == "\x3d": 137 | print hex(i) + ": dcr a" 138 | elif contents[i] == "\x3e": 139 | print hex(i) + ": mvi a, " + hex(ord(contents[i + 1])) 140 | i += 1 141 | elif contents[i] == "\x3f": 142 | print hex(i) + ": cmc" 143 | 144 | elif contents[i] == "\x40": 145 | print hex(i) + ": mov b, b" 146 | elif contents[i] == "\x41": 147 | print hex(i) + ": mov b, c" 148 | elif contents[i] == "\x42": 149 | print hex(i) + ": mov b, d" 150 | elif contents[i] == "\x43": 151 | print hex(i) + ": mov b, e" 152 | elif contents[i] == "\x44": 153 | print hex(i) + ": mov b, h" 154 | elif contents[i] == "\x45": 155 | print hex(i) + ": mov b, l" 156 | elif contents[i] == "\x46": 157 | print hex(i) + ": mov b, m" 158 | elif contents[i] == "\x47": 159 | print hex(i) + ": mov b, a" 160 | elif contents[i] == "\x48": 161 | print hex(i) + ": mov c, b" 162 | elif contents[i] == "\x49": 163 | print hex(i) + ": mov c, c" 164 | elif contents[i] == "\x4a": 165 | print hex(i) + ": mov c, d" 166 | elif contents[i] == "\x4b": 167 | print hex(i) + ": mov c, e" 168 | elif contents[i] == "\x4c": 169 | print hex(i) + ": mov c, h" 170 | elif contents[i] == "\x4d": 171 | print hex(i) + ": mov c, l" 172 | elif contents[i] == "\x4e": 173 | print hex(i) + ": mov c, m" 174 | elif contents[i] == "\x4f": 175 | print hex(i) + ": mov c, a" 176 | 177 | 178 | 179 | elif contents[i] == "\x50": 180 | print hex(i) + ": mov d, b" 181 | elif contents[i] == "\x51": 182 | print hex(i) + ": mov d, c" 183 | elif contents[i] == "\x52": 184 | print hex(i) + ": mov d, d" 185 | elif contents[i] == "\x53": 186 | print hex(i) + ": mov d, e" 187 | elif contents[i] == "\x54": 188 | print hex(i) + ": mov d, h" 189 | elif contents[i] == "\x55": 190 | print hex(i) + ": mov d, l" 191 | elif contents[i] == "\x56": 192 | print hex(i) + ": mov d, m" 193 | elif contents[i] == "\x57": 194 | print hex(i) + ": mov d, a" 195 | elif contents[i] == "\x58": 196 | print hex(i) + ": mov e, b" 197 | elif contents[i] == "\x59": 198 | print hex(i) + ": mov e, c" 199 | elif contents[i] == "\x5a": 200 | print hex(i) + ": mov e, d" 201 | elif contents[i] == "\x5b": 202 | print hex(i) + ": mov e, e" 203 | elif contents[i] == "\x5c": 204 | print hex(i) + ": mov e, h" 205 | elif contents[i] == "\x5d": 206 | print hex(i) + ": mov e, l" 207 | elif contents[i] == "\x5e": 208 | print hex(i) + ": mov e, m" 209 | elif contents[i] == "\x5f": 210 | print hex(i) + ": mov e, a" 211 | 212 | 213 | elif contents[i] == "\x60": 214 | print hex(i) + ": mov h, b" 215 | elif contents[i] == "\x61": 216 | print hex(i) + ": mov h, c" 217 | elif contents[i] == "\x62": 218 | print hex(i) + ": mov h, d" 219 | elif contents[i] == "\x63": 220 | print hex(i) + ": mov h, e" 221 | elif contents[i] == "\x64": 222 | print hex(i) + ": mov h, h" 223 | elif contents[i] == "\x65": 224 | print hex(i) + ": mov h, l" 225 | elif contents[i] == "\x66": 226 | print hex(i) + ": mov h, m" 227 | elif contents[i] == "\x67": 228 | print hex(i) + ": mov h, a" 229 | elif contents[i] == "\x68": 230 | print hex(i) + ": mov l, b" 231 | elif contents[i] == "\x69": 232 | print hex(i) + ": mov l, c" 233 | elif contents[i] == "\x6a": 234 | print hex(i) + ": mov l, d" 235 | elif contents[i] == "\x6b": 236 | print hex(i) + ": mov l, e" 237 | elif contents[i] == "\x6c": 238 | print hex(i) + ": mov l, h" 239 | elif contents[i] == "\x6d": 240 | print hex(i) + ": mov l, l" 241 | elif contents[i] == "\x6e": 242 | print hex(i) + ": mov l, m" 243 | elif contents[i] == "\x6f": 244 | print hex(i) + ": mov l, a" 245 | 246 | 247 | elif contents[i] == "\x70": 248 | print hex(i) + ": mov m, b" 249 | elif contents[i] == "\x71": 250 | print hex(i) + ": mov m, c" 251 | elif contents[i] == "\x72": 252 | print hex(i) + ": mov m, d" 253 | elif contents[i] == "\x73": 254 | print hex(i) + ": mov m, e" 255 | elif contents[i] == "\x74": 256 | print hex(i) + ": mov m, h" 257 | elif contents[i] == "\x75": 258 | print hex(i) + ": mov m, l" 259 | elif contents[i] == "\x76": 260 | print hex(i) + ": hlt" 261 | elif contents[i] == "\x77": 262 | print hex(i) + ": mov m, a" 263 | elif contents[i] == "\x78": 264 | print hex(i) + ": mov a, b" 265 | elif contents[i] == "\x79": 266 | print hex(i) + ": mov a, c" 267 | elif contents[i] == "\x7a": 268 | print hex(i) + ": mov a, d" 269 | elif contents[i] == "\x7b": 270 | print hex(i) + ": mov a, e" 271 | elif contents[i] == "\x7c": 272 | print hex(i) + ": mov a, h" 273 | elif contents[i] == "\x7d": 274 | print hex(i) + ": mov a, l" 275 | elif contents[i] == "\x7e": 276 | print hex(i) + ": mov a, m" 277 | elif contents[i] == "\x7f": 278 | print hex(i) + ": mov a, a" 279 | 280 | 281 | elif contents[i] == "\x80": 282 | print hex(i) + ": add b" 283 | elif contents[i] == "\x81": 284 | print hex(i) + ": add c" 285 | elif contents[i] == "\x82": 286 | print hex(i) + ": add d" 287 | elif contents[i] == "\x83": 288 | print hex(i) + ": add e" 289 | elif contents[i] == "\x84": 290 | print hex(i) + ": add h" 291 | elif contents[i] == "\x85": 292 | print hex(i) + ": add l" 293 | elif contents[i] == "\x86": 294 | print hex(i) + ": add m" 295 | elif contents[i] == "\x87": 296 | print hex(i) + ": add a" 297 | elif contents[i] == "\x88": 298 | print hex(i) + ": adc b" 299 | elif contents[i] == "\x89": 300 | print hex(i) + ": adc c" 301 | elif contents[i] == "\x8a": 302 | print hex(i) + ": adc d" 303 | elif contents[i] == "\x8b": 304 | print hex(i) + ": adc e" 305 | elif contents[i] == "\x8c": 306 | print hex(i) + ": adc h" 307 | elif contents[i] == "\x8d": 308 | print hex(i) + ": adc l" 309 | elif contents[i] == "\x8e": 310 | print hex(i) + ": adc m" 311 | elif contents[i] == "\x8f": 312 | print hex(i) + ": adc a" 313 | 314 | 315 | 316 | 317 | 318 | elif contents[i] == "\x90": 319 | print hex(i) + ": sub b" 320 | elif contents[i] == "\x91": 321 | print hex(i) + ": sub c" 322 | elif contents[i] == "\x92": 323 | print hex(i) + ": sub d" 324 | elif contents[i] == "\x93": 325 | print hex(i) + ": sub e" 326 | elif contents[i] == "\x94": 327 | print hex(i) + ": sub h" 328 | elif contents[i] == "\x95": 329 | print hex(i) + ": sub l" 330 | elif contents[i] == "\x96": 331 | print hex(i) + ": sub m" 332 | elif contents[i] == "\x97": 333 | print hex(i) + ": sub a" 334 | elif contents[i] == "\x98": 335 | print hex(i) + ": sbb b" 336 | elif contents[i] == "\x99": 337 | print hex(i) + ": sbb c" 338 | elif contents[i] == "\x9a": 339 | print hex(i) + ": sbb d" 340 | elif contents[i] == "\x9b": 341 | print hex(i) + ": sbb e" 342 | elif contents[i] == "\x9c": 343 | print hex(i) + ": sbb h" 344 | elif contents[i] == "\x9d": 345 | print hex(i) + ": sbb l" 346 | elif contents[i] == "\x9e": 347 | print hex(i) + ": sbb m" 348 | elif contents[i] == "\x9f": 349 | print hex(i) + ": sbb a" 350 | 351 | 352 | 353 | 354 | elif contents[i] == "\xa0": 355 | print hex(i) + ": ana b" 356 | elif contents[i] == "\xa1": 357 | print hex(i) + ": ana c" 358 | elif contents[i] == "\xa2": 359 | print hex(i) + ": ana d" 360 | elif contents[i] == "\xa3": 361 | print hex(i) + ": ana e" 362 | elif contents[i] == "\xa4": 363 | print hex(i) + ": ana h" 364 | elif contents[i] == "\xa5": 365 | print hex(i) + ": ana l" 366 | elif contents[i] == "\xa6": 367 | print hex(i) + ": ana m" 368 | elif contents[i] == "\xa7": 369 | print hex(i) + ": ana a" 370 | elif contents[i] == "\xa8": 371 | print hex(i) + ": xra b" 372 | elif contents[i] == "\xa9": 373 | print hex(i) + ": xra c" 374 | elif contents[i] == "\xaa": 375 | print hex(i) + ": xra d" 376 | elif contents[i] == "\xab": 377 | print hex(i) + ": xra e" 378 | elif contents[i] == "\xac": 379 | print hex(i) + ": xra h" 380 | elif contents[i] == "\xad": 381 | print hex(i) + ": xra l" 382 | elif contents[i] == "\xae": 383 | print hex(i) + ": xra m" 384 | elif contents[i] == "\xaf": 385 | print hex(i) + ": xra a" 386 | 387 | 388 | elif contents[i] == "\xb0": 389 | print hex(i) + ": ora b" 390 | elif contents[i] == "\xb1": 391 | print hex(i) + ": ora c" 392 | elif contents[i] == "\xb2": 393 | print hex(i) + ": ora d" 394 | elif contents[i] == "\xb3": 395 | print hex(i) + ": ora e" 396 | elif contents[i] == "\xb4": 397 | print hex(i) + ": ora h" 398 | elif contents[i] == "\xb5": 399 | print hex(i) + ": ora l" 400 | elif contents[i] == "\xb6": 401 | print hex(i) + ": ora m" 402 | elif contents[i] == "\xb7": 403 | print hex(i) + ": ora a" 404 | elif contents[i] == "\xb8": 405 | print hex(i) + ": cmp b" 406 | elif contents[i] == "\xb9": 407 | print hex(i) + ": cmp c" 408 | elif contents[i] == "\xba": 409 | print hex(i) + ": cmp d" 410 | elif contents[i] == "\xbb": 411 | print hex(i) + ": cmp e" 412 | elif contents[i] == "\xbc": 413 | print hex(i) + ": cmp h" 414 | elif contents[i] == "\xbd": 415 | print hex(i) + ": cmp l" 416 | elif contents[i] == "\xbe": 417 | print hex(i) + ": cmp m" 418 | elif contents[i] == "\xbf": 419 | print hex(i) + ": cmp a" 420 | 421 | 422 | 423 | elif contents[i] == "\xc0": 424 | print hex(i) + ": rnz" 425 | elif contents[i] == "\xc1": 426 | print hex(i) + ": pop b" 427 | elif contents[i] == "\xc2": 428 | print hex(i) + ": jnz " + hex(ord(contents[i + 2])) + hex(ord(contents[i + 1])).replace("0x", "") 429 | i += 2 430 | elif contents[i] == "\xc3": 431 | print hex(i) + ": jmp " + hex(ord(contents[i + 2])) + hex(ord(contents[i + 1])).replace("0x", "") 432 | i += 2 433 | elif contents[i] == "\xc4": 434 | print hex(i) + ": cnz " + hex(ord(contents[i + 2])) + hex(ord(contents[i + 1])).replace("0x", "") 435 | i += 2 436 | elif contents[i] == "\xc5": 437 | print hex(i) + ": push b" 438 | elif contents[i] == "\xc6": 439 | print hex(i) + ": adi " + hex(ord(contents[i + 1])) 440 | i += 1 441 | elif contents[i] == "\xc7": 442 | print hex(i) + ": rst 0" 443 | elif contents[i] == "\xc8": 444 | print hex(i) + ": rz" 445 | elif contents[i] == "\xc9": 446 | print hex(i) + ": ret" 447 | elif contents[i] == "\xca": 448 | print hex(i) + ": jz " + hex(ord(contents[i + 2])) + hex(ord(contents[i + 1])).replace("0x", "") 449 | i += 2 450 | elif contents[i] == "\xcc": 451 | print hex(i) + ": cz " + hex(ord(contents[i + 2])) + hex(ord(contents[i + 1])).replace("0x", "") 452 | i += 2 453 | elif contents[i] == "\xcd": 454 | print hex(i) + ": call " + hex(ord(contents[i + 2])) + hex(ord(contents[i + 1])).replace("0x", "") 455 | i += 2 456 | elif contents[i] == "\xce": 457 | print hex(i) + ": aci " + hex(ord(contents[i + 1])) 458 | i += 1 459 | elif contents[i] == "\xcf": 460 | print hex(i) + ": rst 1" 461 | 462 | 463 | 464 | elif contents[i] == "\xd0": 465 | print hex(i) + ": rnc" 466 | elif contents[i] == "\xd1": 467 | print hex(i) + ": pop d" 468 | elif contents[i] == "\xd2": 469 | print hex(i) + ": jnc " + hex(ord(contents[i + 2])) + hex(ord(contents[i + 1])).replace("0x", "") 470 | i += 2 471 | elif contents[i] == "\xd3": 472 | print hex(i) + ": out " + hex(ord(contents[i + 1])) 473 | i += 1 474 | elif contents[i] == "\xd4": 475 | print hex(i) + ": cnc " + hex(ord(contents[i + 2])) + hex(ord(contents[i + 1])).replace("0x", "") 476 | i += 2 477 | elif contents[i] == "\xd5": 478 | print hex(i) + ": push d" 479 | elif contents[i] == "\xd6": 480 | print hex(i) + ": sui " + hex(ord(contents[i + 1])) 481 | i += 1 482 | elif contents[i] == "\xd7": 483 | print hex(i) + ": rst 2" 484 | elif contents[i] == "\xd8": 485 | print hex(i) + ": rc" 486 | elif contents[i] == "\xda": 487 | print hex(i) + ": jc " + hex(ord(contents[i + 2])) + hex(ord(contents[i + 1])).replace("0x", "") 488 | i += 2 489 | elif contents[i] == "\xdc": 490 | print hex(i) + ": cc " + hex(ord(contents[i + 2])) + hex(ord(contents[i + 1])).replace("0x", "") 491 | i += 2 492 | elif contents[i] == "\xdd": 493 | print hex(i) + ": end " + hex(ord(contents[i + 1])) 494 | i += 1 495 | elif contents[i] == "\xde": 496 | print hex(i) + ": sbi " + hex(ord(contents[i + 1])) 497 | i += 1 498 | elif contents[i] == "\xdf": 499 | print hex(i) + ": rst 3" 500 | 501 | 502 | 503 | 504 | elif contents[i] == "\xe0": 505 | print hex(i) + ": rpo" 506 | elif contents[i] == "\xe1": 507 | print hex(i) + ": pop h" 508 | elif contents[i] == "\xe2": 509 | print hex(i) + ": jpo " + hex(ord(contents[i + 2])) + hex(ord(contents[i + 1])).replace("0x", "") 510 | i += 2 511 | elif contents[i] == "\xe3": 512 | print hex(i) + ": xthl " 513 | elif contents[i] == "\xe4": 514 | print hex(i) + ": cpo " + hex(ord(contents[i + 2])) + hex(ord(contents[i + 1])).replace("0x", "") 515 | i += 2 516 | elif contents[i] == "\xe5": 517 | print hex(i) + ": push h" 518 | elif contents[i] == "\xe6": 519 | print hex(i) + ": ani " + hex(ord(contents[i + 1])) 520 | i += 1 521 | elif contents[i] == "\xe7": 522 | print hex(i) + ": rst 4" 523 | elif contents[i] == "\xe8": 524 | print hex(i) + ": rpe" 525 | elif contents[i] == "\xe9": 526 | print hex(i) + ": pchl" 527 | elif contents[i] == "\xea": 528 | print hex(i) + ": jpe " + hex(ord(contents[i + 2])) + hex(ord(contents[i + 1])).replace("0x", "") 529 | i += 2 530 | elif contents[i] == "\xeb": 531 | print hex(i) + ": xchg" 532 | elif contents[i] == "\xec": 533 | print hex(i) + ": cpe " + hex(ord(contents[i + 2])) + hex(ord(contents[i + 1])).replace("0x", "") 534 | i += 2 535 | elif contents[i] == "\xed": 536 | print hex(i) + ": xri " + hex(ord(contents[i + 1])) 537 | i += 1 538 | elif contents[i] == "\xef": 539 | print hex(i) + ": rst 5" 540 | 541 | 542 | 543 | 544 | elif contents[i] == "\xf0": 545 | print hex(i) + ": rp" 546 | elif contents[i] == "\xf1": 547 | print hex(i) + ": pop psw" 548 | elif contents[i] == "\xf2": 549 | print hex(i) + ": jp " + hex(ord(contents[i + 2])) + hex(ord(contents[i + 1])).replace("0x", "") 550 | i += 2 551 | elif contents[i] == "\xf3": 552 | print hex(i) + ": di" 553 | elif contents[i] == "\xf4": 554 | print hex(i) + ": cp " + hex(ord(contents[i + 2])) + hex(ord(contents[i + 1])).replace("0x", "") 555 | i += 2 556 | elif contents[i] == "\xf5": 557 | print hex(i) + ": push psw" 558 | elif contents[i] == "\xf6": 559 | print hex(i) + ": ori " + hex(ord(contents[i + 1])) 560 | i += 1 561 | elif contents[i] == "\xf7": 562 | print hex(i) + ": rst 6" 563 | elif contents[i] == "\xf8": 564 | print hex(i) + ": rm" 565 | elif contents[i] == "\xf9": 566 | print hex(i) + ": sphl" 567 | elif contents[i] == "\xfa": 568 | print hex(i) + ": jm " + hex(ord(contents[i + 2])) + hex(ord(contents[i + 1])).replace("0x", "") 569 | i += 2 570 | elif contents[i] == "\xfb": 571 | print hex(i) + ": ei" 572 | elif contents[i] == "\xfc": 573 | print hex(i) + ": cm " + hex(ord(contents[i + 2])) + hex(ord(contents[i + 1])).replace("0x", "") 574 | i += 2 575 | elif contents[i] == "\xfd": 576 | print hex(i) + ": cpi " + hex(ord(contents[i + 1])) 577 | i += 1 578 | elif contents[i] == "\xff": 579 | print hex(i) + ": rst 7" 580 | i += 1 581 | 582 | 583 | if len(sys.argv) != 2: 584 | print "usage: python disassemble.py " 585 | print len(sys.argv) 586 | exit() 587 | 588 | fp = open(sys.argv[1], "r") 589 | if fp.mode == "r": 590 | contents = fp.read() 591 | decompile(contents) 592 | -------------------------------------------------------------------------------- /how-to-make/Readme.md: -------------------------------------------------------------------------------- 1 | # How to Make 2 | 3 | This is a little writeup on how I designed the emulator, disassembler, and debugger. I won't get into much detail, since the source code is in this repo. Also in this directory I threw in a copy of the 8080 instruction manual that I used to make it, which is from `http://altairclone.com/downloads/manuals/8080%20Programmers%20Manual.pdf`. 4 | 5 | ## Disassembler 6 | 7 | For this, first I read the contents of the binary file, then fed it through a switch statement. It would map the op codes to the respective instructions. Since all of the opcodes are only one byte, for each loop of the switch statement I would increment the index which the switch statement reads by one, so it would move on to the next opcode for the next loop. For some of the opcodes that take 1 argument, I would print the agrument along with the instruction then increment the index by 2, so it moves on to the next instruction and doesn't try to map the argument to an instruction. For opcodes with two arguments, I would print the two arguments with the instruction, and increment the index by 3 for the same reason. 8 | 9 | ## Emulator 10 | 11 | #### Registers / Memory Mapping 12 | 13 | When I designed this portion, I made a struct which represents the portions of the 8080 cpu / ram that we would need to keep track of for this emulator: 14 | 15 | ``` 16 | typedef struct cpu8080 { 17 | // Arithmetic register 18 | uint8_t a; 19 | 20 | // BC register 21 | uint8_t b; 22 | uint8_t c; 23 | 24 | // DE register 25 | uint8_t d; 26 | uint8_t e; 27 | 28 | // HL register 29 | uint8_t h; 30 | uint8_t l; 31 | 32 | // Flags 33 | bool carry; 34 | bool one; 35 | bool parity; 36 | bool zero1; 37 | bool aux; 38 | bool zero2; 39 | bool zero; 40 | bool sign; 41 | 42 | // stack (sp) and program counter (pc) registers 43 | uint16_t sp; 44 | uint16_t pc; 45 | 46 | // a ptr to the memory region 47 | uint8_t *memory; 48 | 49 | // I excluded the rest of the struct, since it deals with the debugger aspect 50 | ``` 51 | 52 | Since the registers `a`, `b`, `c`, `d`, `e`, `h`, and `l` hold 8 bits, I just established a `uint8_t` which is an unsigned integer which can only hold 8 bits. When I would need to reference one of the 16 bit registers `bc`, `de`, or `hl` I would just have a function that would convert the `uint8_t` values into the corresponding 16 bit value. For the flags, I decided to just make 8 bools. each representing one of the flags, since a lot of our use for them deals with individual bits. For the 16 bit registers `sp` and `pc`, I decided to just make them 16 bit `uint16_t`, since we usually want the whole 16 bits when we deal with them. 53 | 54 | For the memory of the emulator, since we are dealing with a 16 bit architecture, we have 16 bit addresses. As a result all possible memory must map to somewhere between `0x0000 - 0xffff`. Since this is about a half of a megabyte, I decided to just allocate it all with malloc, to get one massive array that contains all of the memory. Then I would treat addresses as indexes for the array. I loaded the code which is run starting at `0x0`, and I started the stack at `0x4000` (rememeber the stack grows downwards, towards `0x0`). I don't recall ever seeing what the standard was for where to start the stack / code regions, so I just picked those values for no concrete reason other than convinience. 55 | 56 | Also for the `m` register, since that is just the memory address pointed to by the `hl` register, I would just convert the `hl` register contents into an address, then treat that as a register. 57 | 58 | Also another thing to keep in mind, the stack pointer is stored in the `sp` register, and the program counter is stored in the `pc` register (points the current instruction being ran). 59 | 60 | #### Flags 61 | 62 | Setting flags is something that we would have to do for a lot of different functions. So I just wrote some functions to handle it for me, and called them whenever I need to set the flags. Also if you don't know what binary anding, oring, and shifting is, you will probably want to look that up. 63 | 64 | ##### Zero 65 | 66 | Since this flag I just checked to see if the result is equal to zero, and if it is, I would set the zero fla to true. 67 | 68 | ##### Sign 69 | 70 | The sign bit is the last bit (the seventh bit, remember it is 0 indexed), and this flag essentially just checks to see if that bit is set. So to set this flag, we can just see if that bit is set, by anding it with `0x80` since in binary it is `0b10000000`, if it isn't zero, that means that the sign bit is set. After that we would set the flag accordingly. 71 | 72 | ##### Auxiliary 73 | 74 | This flag checks if there is a carry out of bit 3. A carry out occurs when the operation of one bit affects the next bit, so with addition it is when both values are `1`, and with subtraction it is when you subtract a `1` from a `0`. To see if this bit is set for a value, we can just and it with `0x8` since that maps to `0b1000` which is the third bit. For this function I also passed it a value to indicate whether it is a subtraction, or addition operation, and I would also pass it the two values instead of the final result. For addition if both of the third bits were set, I would set the auxillary flag. For subtraction, if the value being subtracted had the third bit set, and the value being subtracted from didn't I would set the auxillary flag. 75 | 76 | ##### Parity 77 | 78 | This flag is a bit different from the rest. If it is set it indicates that the result of whatever operation happened has an even number of `1`s (for the binary string). If it isn't set then the number of `1`s is odd. So for the value `0x73` it's binary string is `0b1110011`, which has 5 `1`s, and since that is odd, the Parity flag would not be set. So to figure this out, I just ran the result through a for loop that would and the result with `0x1` (which in binary is just 0b1), increment an integer by one if the result isn't one (meaning that that bit is set), shift it over by 1, and repeat seven times. Then the count integer would tell us how many bits are set. Proceeding that we could just mod the count by `2`, and if the result wasn't `0` we knew that the amount of `1`s in the result was odd (and vice versa). 79 | 80 | ##### Carry 81 | 82 | Like the Auxiliary flag, whether this is a subtraction or addition operation changes if the flag is set (but we only need to look at the result). This flag looks at if the eight bit is set or not (which maps to `0x100` or `0b100000000`). This can only happen if there is a carry out of the seventh bit, since we are dealing wiht 8 bit values. This flag is extreamly useful since if we add two values together such as `0xac` and `0x66`, although it would yeild `0x112` it would only store `0x12` since we are dealing with 8 bit values. This allows us to determine if the 8 bits captures the entire picture. For addition, we just check if the 8th bit is set, and if it is we set the Carry flag. However for subtraction it works the opposite way, if the 8th bit is set, the Carry flag isn't set. 83 | 84 | Also for 16 bit values, we use the same logic, however we check if the 16th bit (which maps to `0x10000` or `0b10000000000000000`) is set. 85 | 86 | #### Instructions 87 | 88 | Here is what I did for all of the instructions. Also for instructions that took arguments, I would increment the index by the length of the argument, to account for that (just like with the disassembler). 89 | 90 | Also one thing I would like to say, how the manual describes subtraction is with the use of twos complement logic. How that works is it takes the value that will be subtracted from something, inverts it, then adds one to it. It then takes this new value and adds it to whatever it is being added to. I have implemented this logic at some places throughout the code for my emulator. 91 | 92 | ##### Nop 93 | 94 | For this I just had it do nothing, since that's what a NOP essentially does. 95 | 96 | ##### lxi 97 | 98 | For these instructions, I would just load the next two bytes into the corresponding 16 bit register. 99 | 100 | ##### stax 101 | 102 | For this, I would treat the contents of either the `bc` or `de` register as an address, then store the contents of the `a` register in it. 103 | 104 | ##### shld & sta 105 | 106 | For this, I would treat the next two bytes (which are args) as an address, then store the contents of either the `a` or `hl` register (depends on the instruction used) in there. 107 | 108 | ##### inx & dcx 109 | 110 | These just increment or decrement a 16 bit register by one. For the 16 bit register pairs `bc`, `de`, and `hl`, for incrementing I would check to see if the lower eight bits is lower than `0xff`. If it is, I would just increment the lower 8 bit register by one. If the lower 8 bits is `0xff`, then I would set the lower 8 bits to `0x0`, then increment the higher 8 bits. Also if the 16 bit register pair was `0xffff`, I would follow the standard and set it the pair to `0x0000`. For subtracting from a 16 bit register pair, I used the same sort of logic. If the last 8 bits was greater than `0x0`, I would just decrement it by one. If it wasn't I would set it equal to `0xff` and decrement the higher 8 bits by one. And if the 16 bit register pair is `0x0000` I would have it wrap around to `0xffff`. 111 | 112 | When dealing with the `sp` register, since it isn't a register pair it's a bit simpler. I check to see that there isn't a wrap around, and if there isn't I just either increment or decrement the regitser. 113 | 114 | ##### inr & dcr 115 | 116 | This just increments / decrements the 8 bit register passed to it. It also takes the result and runs it through the flag set functions for the flags zero, sign, parity, auxiliary, and carry. 117 | 118 | ##### mvi 119 | 120 | For this, I would just move the one byte argument into the corresponding register. 121 | 122 | ##### rlc & rrc 123 | 124 | For these instructions, I would rotate the contents of the `a` register to either the right or the left. For the bit that would loop around (when shifting to the left it would be the leftmost bit, and vice versa) it would also be copied to the carry bit. 125 | 126 | ##### ral & rar 127 | 128 | Pretty similar to the rlc & rrc, except the bit that would of been looped around gets moved to the carry bit, and whatever was in the carry bit gets looped around. 129 | 130 | ##### daa 131 | 132 | For this, I just read the manual, and implemented it the best way I thought of. 133 | 134 | ##### stc 135 | 136 | This just sets the carry flag, so the carry flag is equal to true. 137 | 138 | ##### cma & cmc 139 | 140 | These instructions just invert the `a` register, and carry flags, so that is what I did. 141 | 142 | ##### dad 143 | 144 | this just moves the contents of the `16` bit register into hl, so that's what I did. For the register pairs, it was pretty straight forward. For mocing the sp register, there was a bit of shifting involved due to the difference in data types. 145 | 146 | ##### ldax, lhld, lda 147 | 148 | For all of these instructions, they all deal with with dereferencing an address and loading that value somewhere. For ldax, I would conver the register pair into a 16 bit value, then treat that as an address. Lda is pretty similar to ldax, except the address is from an argument. Also with lhld we load a 16 bit value instead of an 8 bit value. 149 | 150 | ##### mov 151 | 152 | All of the mov instructions are pretty straight forward. We just set one register equal to another. For the m register, we just treat the contents of the hl register as an address, dereference it, then treat that as a register, 153 | 154 | ##### hlt 155 | 156 | For this instruction, since I didn't implement hardware interrupts I essentially just had it be a NOP. 157 | 158 | ##### add & sub 159 | 160 | For these instructions, I would just subtract the contents of the eight bit register from the a register, store the result as a 16 bit `uint16_t` to store because of the carry flag, run it through the set flag functions for Carry, Sign, Zero, Parity, and Auxiliary, then store the lower 8 bits of the result in a. 161 | 162 | ##### adc & sbb 163 | 164 | This is pretty similar to add & sub. The only difference is the number being added to, or subtracted from A has the int conversion of the carry flag added to it (`1` if it is set, `0` if not). 165 | 166 | ##### ana 167 | 168 | For this, I just and whatever 8 bit register is being used with the A register, store the result in A, and run the result through the Zero, Sign, Parity. Since anding does not lead to a binary carry out, the Carry flag will always be 0. According to the manual, the auxiliary bit isn't affected, otherwise like the Carry flag I would set it to 0. 169 | 170 | ##### xra & ora 171 | 172 | Like the ana instruction, it performs it's respective binary operation (either xor or or) on whatever register is being used against the A register, and stores the result in the A register. Unlike the ana instruction, the Auxiliary flag is affected and since a binary carryout cannot happen with xor or or, both of those flags are set equal to zero. The result is also sent through the flag set functions for Zero, Sign, and Parity. 173 | 174 | ##### cmp 175 | 176 | This instruction compares a value against the A register, by simply subtracting it from A, but the value of A is not changed. So what I did is I just had a value be equal to `A - `, then ran that value through the set flag functions for Carry, Sign, Zero, Parity, and Auxiliary. 177 | 178 | ##### push 179 | 180 | This instruction moves the contents of a 16 bit register to the stack. It does so by decrementing the stack pointer by 1 (since each value is just 8 bits, which is 1 byte, and the stack grows downards), sets the next value equal to the higher 8 bits of the register, decrements it again, then sets the new value equal to the lower 8 bits. The contents of the 16 bit register are not changed. 181 | 182 | ##### pop 183 | 184 | This instruction is like push in reverse, and the 16 bit register's value is affected. It sets the lower eight bits of the register equal to whatever the current stack pointer points to, increments by one, sets the higher eight bits equal to whatever the new stack pointer points to, then increments it again by one. 185 | 186 | ##### jmp 187 | 188 | For this, I would just take the two byte address as the argument, shift it around into a 16 bit address assuming that the arguments were in least endian (least signifcant byte first), then set the program counter (which controls which instruction is being executed) equal to that address. 189 | 190 | ##### call 191 | 192 | This is pretty similar to the jmp instrunction. The only difference is the address of the next instruction (which at the time it is called is pc + 3) onto the stack, which will act as a return address. That way when the branch ends, it will be able to continue execution right after the call. 193 | 194 | ##### ret 195 | 196 | This instruction happens at the end of a branch. Essentially it just pops the 16 bits pointed to by the stack pointer (which should be the return address) into the `pc` register. That way the branch finishes and the execution continues on from the call instruction. 197 | 198 | ##### rest of ret, call, and jmp instructions 199 | 200 | there are about 24 other instructions for jmp, call, and ret. All of these due is just check the condition of one of the flags, and based upon it's value it may or may not run the instruction. I just implement the same logic for the instructions. 201 | 202 | ##### out & in 203 | 204 | Since I didn't implement other hardware interfaces, I just had these be NOPs essentially. 205 | 206 | ##### xthl 207 | 208 | For this, I dereferenced the addresses stored in sp (and the address of sp + 1), and swapped it's contents with that of the H and L registers. 209 | 210 | ##### xchg 211 | 212 | For this I just swa[[ed the contents of the DE and HL registers. 213 | 214 | ##### di & ei 215 | 216 | Even though I did not implement hardware interrupts, with the cup8080 struct, I included a bool value which storred whether or not hardware interrupts were allowed. These instructions would just assing that bit it's corresponding value. 217 | 218 | ##### spchl & pchl 219 | 220 | Using a bit of binary logic, I would just move the contents of the HL register into the SP and PC registers. 221 | 222 | ##### adi, aci, sui, and sbi 223 | 224 | Basically the same as the add, adc, sub, and sbb instructions, except instead of dealing with a separate register, we deal with an argument to the instruction. 225 | 226 | ##### ani, xri, ori, cpi 227 | 228 | Basically the same as the ana, xra, ora, and cmp instructions, except instead of dealing with a separate register, we deal with an argument to the instruction. 229 | 230 | ##### rst 231 | 232 | For this I just push the current program counter plus one onto the stack to act as a return address, then load the corresponding address (based upon which rst instruction it is) into the `pc` register. 233 | 234 | ## Debugger 235 | 236 | Here I'm just going to go through breifly how implemented the various debugging functionallity for my debugger. Also here is the portion of the `cpu8080` struct which deals with the debugging functionalities. 237 | 238 | ``` 239 | // a ptr to the breakpoints 240 | breakpoints *breakpoints; 241 | 242 | // a bool to indicate if it is running 243 | bool running; 244 | 245 | bool breaked; 246 | 247 | // Here are some values, which will keep track of where the various regions of memory are 248 | uint16_t memBeg; // Beginning of entire memory region 249 | uint16_t memEnd; // End of entrie memory region 250 | uint16_t codeBeg; // Beginning of where code is loaded 251 | uint16_t codeEnd; // End of where code is loaded 252 | uint16_t stackBeg; // Beginning of the stack 253 | // the end of the code is kept by codeEnd, and the end of the stack is kep by sp 254 | 255 | bool disasAsExec; // A bool to keep track of whether or not to disassmble intructions as they are executed 256 | 257 | uint8_t step; // A value to keep track of the staus of steeping through instructions, for the step instruction command 258 | 259 | // a bit which controls whether interrupts can happen, currently don't use it for anything. 1 for allow, 0 for disable. 260 | bool allowInterrupt; 261 | 262 | } cpu8080; 263 | ``` 264 | ##### Help 265 | 266 | This is essentially just a puts statement. 267 | 268 | ##### Disassembly 269 | 270 | For this, I just run a for loop feeding the code through the disassemble function, untill I reach the codeend, which is determined when the code is loaded. Also another thing to note, the disassemble function returns the index of the next instruction. 271 | 272 | ##### toggle disassembly 273 | 274 | Every time a new instruction is ran, I check to see if the toggle disassembly bool is true. If it is, I run the instruction being ran through the disasAsExec function. 275 | 276 | ##### dump memory 277 | 278 | I just open up the file `memory.dat` (create it if it's not made) and just write the contents of all of the memory to it. 279 | 280 | ##### display register / registers 281 | 282 | This is for the `i` and `p` commands. Depending on the command and the argument, I just print the contetns of the registers. 283 | 284 | ##### run 285 | 286 | Starting off I run it through the `resetExeuction` function to essentially clear out the state of the emulation so we start it from scratch, then run it through the `emulate` function which actually handles the emulation. 287 | 288 | ##### continue 289 | 290 | Basically the run function, howoever we don't run it through the `resetExecution` function, so it continues from where you left off versus starting from scratch. 291 | 292 | ##### quit 293 | 294 | For this, I essentially free up the dynamically allocated memory using `destroyCpu` function, and freeing `menuChoice`, then returning from the `menu` function (which sould close the emulator). 295 | 296 | ##### breakpoints 297 | 298 | For breakpoints, I have them be a linked list (I could probably get a better runtime with a different data structure, but due to time constraints I didn't do that) which I maintain a head ptr. The struct for the breakpoints is this: 299 | 300 | ``` 301 | typedef struct breakpoints { 302 | uint16_t breakp; 303 | bool active; 304 | struct breakpoints *next; 305 | } breakpoints; 306 | ``` 307 | 308 | Essentially I just keep track of whether or not the breakpoint is active, what instruction the breakpoint is, and what the next breakpoint address is. Also I keep the head pointer for the breakpoints in the cpu in the ptr `breakpoints`. Each time I want to check for a breakpoint, I just loop through the list untill I either get to the end, or find a breakpoint in the linked list with the instruction (hence the thing about their being a data structure with a better run time). For adding / editing breakpoints, it's pretty much standard linked list operations. 309 | 310 | Also when a breakpoint is reached, I just exit the emulate function, which brings us back to the debugger menu. 311 | 312 | ##### jump 313 | 314 | For this, I just convert the argument into an integer, and then set the `pc` register equal to it. 315 | 316 | ##### view memory mappings 317 | 318 | When a cpu8080 struct is created, I store pointers to the various memory regions in the cpu struct (things like `stackBeg` and `codeEnd`), which then I just print those addresses. 319 | 320 | ##### step 321 | 322 | For this, I kept a value `step` in the cpu8080 struct. Essentially there is a three stage process to this. First it sets `step` equal to 1, then runs it through the emulate function. Then the `step` value would get switched to `2` indicating that an instruction has been run, then switched back to `0`, and it would go back to the the debug menu. The checking occurs towards the start of each iteration of the for loop in the `emulate` function. 323 | 324 | ##### examine 325 | 326 | For this, we take the address that we are given, dereferences it, then prints the value as an 8 bit byte. If the argument is given, then we will print `` bytes from the address given, in an ascending order. 327 | 328 | ##### set 329 | 330 | If the argument that is given is a register, we then set the corresponding to register to the given value. If an address is given, then I dereference the address and set the corresponding value to the given argument. 331 | -------------------------------------------------------------------------------- /src/disass.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Nightfall.h" 4 | 5 | // This source file deals with disassembly 6 | // It's essentially just a giant switch statement 7 | 8 | int disass(cpu8080 *cpu, int i) 9 | { 10 | switch (cpu->memory[i]) 11 | { 12 | case 0x00: 13 | printf("0x%x: nop\n", i); 14 | return i + 1; 15 | 16 | case 0x01: 17 | printf("0x%x: lxi b, ", i); 18 | printTwoArgs(cpu, i); 19 | return i + 3; 20 | 21 | case 0x02: 22 | printf("0x%x: stax b\n", i); 23 | return i + 1; 24 | 25 | case 0x03: 26 | printf("0x%x: inx b\n", i); 27 | return i + 1; 28 | 29 | case 0x04: 30 | printf("0x%x: inr b\n", i); 31 | return i + 1; 32 | 33 | case 0x05: 34 | printf("0x%x: dcr b\n", i); 35 | return i + 1; 36 | 37 | case 0x06: 38 | printf("0x%x: mvi b, 0x%x\n", i, cpu->memory[i + 1]); 39 | return i + 2; 40 | 41 | case 0x07: 42 | printf("0x%x: rlc\n", i); 43 | return i + 1; 44 | 45 | case 0x08: 46 | printf("0x%x: 0x08 instruction not implemented.\n", i); 47 | return i + 1; 48 | 49 | case 0x09: 50 | printf("0x%x: dad b\n", i); 51 | return i + 1; 52 | 53 | case 0x0a: 54 | printf("0x%x: ldax b\n", i); 55 | return i + 1; 56 | 57 | case 0x0b: 58 | printf("0x%x: dcx b\n", i); 59 | return i + 1; 60 | 61 | case 0x0c: 62 | printf("0x%x: inr c\n", i); 63 | return i + 1; 64 | 65 | case 0x0d: 66 | printf("0x%x: dcr c\n", i); 67 | return i + 1; 68 | 69 | case 0x0e: 70 | printf("0x%x: mvi c, 0x%x\n", i, cpu->memory[i + 1]); 71 | return i + 2; 72 | 73 | case 0x0f: 74 | printf("0x%x: rrc\n", i); 75 | return i + 1; 76 | 77 | case 0x10: 78 | printf("0x%x: 0x10 instruction not implemented.\n", i); 79 | return i + 1; 80 | 81 | case 0x11: 82 | printf("0x%x: lxi d, ", i); 83 | printTwoArgs(cpu, i); 84 | return i + 3; 85 | 86 | case 0x12: 87 | printf("0x%x: stax d\n", i); 88 | return i + 1; 89 | 90 | case 0x13: 91 | printf("0x%x: inx d\n", i); 92 | return i + 1; 93 | 94 | case 0x14: 95 | printf("0x%x: inr d\n", i); 96 | return i + 1; 97 | 98 | case 0x15: 99 | printf("0x%x: dcr d\n", i); 100 | return i + 1; 101 | 102 | case 0x16: 103 | printf("0x%x: mvi d, 0x%x\n", i, cpu->memory[i + 1]); 104 | return i + 2; 105 | 106 | case 0x17: 107 | printf("0x%x: ral\n", i); 108 | return i + 1; 109 | 110 | case 0x18: 111 | printf("0x%x: 0x18 instruction not implemented.\n", i); 112 | return i + 1; 113 | 114 | case 0x19: 115 | printf("0x%x: dad d\n", i); 116 | return i + 1; 117 | 118 | case 0x1a: 119 | printf("0x%x: ldax d\n", i); 120 | return i + 1; 121 | 122 | case 0x1b: 123 | printf("0x%x: dcx d\n", i); 124 | return i + 1; 125 | 126 | case 0x1c: 127 | printf("0x%x: inr e\n", i); 128 | return i + 1; 129 | 130 | case 0x1d: 131 | printf("0x%x: dcr e\n", i); 132 | return i + 1; 133 | 134 | case 0x1e: 135 | printf("0x%x: mvi e, 0x%x\n", i, cpu->memory[i + 1]); 136 | return i + 2; 137 | 138 | case 0x1f: 139 | printf("0x%x: rar\n", i); 140 | return i + 1; 141 | 142 | case 0x20: 143 | printf("0x%x: 0x20 instruction not implemented.\n", i); 144 | return i + 1; 145 | 146 | case 0x21: 147 | printf("0x%x: lxi h, ", i); 148 | printTwoArgs(cpu, i); 149 | return i + 3; 150 | 151 | case 0x22: 152 | printf("0x%x: shld, ", i); 153 | printTwoArgs(cpu, i); 154 | return i + 3; 155 | 156 | case 0x23: 157 | printf("0x%x: inx h\n", i); 158 | return i + 1; 159 | 160 | case 0x24: 161 | printf("0x%x: inr h\n", i); 162 | return i + 1; 163 | 164 | case 0x25: 165 | printf("0x%x: dcr h\n", i); 166 | return i + 1; 167 | 168 | case 0x26: 169 | printf("0x%x: mvi h, 0x%x\n", i, cpu->memory[i + 1]); 170 | return i + 2; 171 | 172 | case 0x27: 173 | printf("0x%x: daa\n", i); 174 | return i + 1; 175 | 176 | case 0x28: 177 | printf("0x%x: 0x28 instruction not implemented.\n", i); 178 | return i + 1; 179 | 180 | case 0x29: 181 | printf("0x%x: dad h\n", i); 182 | return i + 1; 183 | 184 | case 0x2a: 185 | printf("0x%x: lhld, ", i); 186 | printTwoArgs(cpu, i); 187 | return i + 3; 188 | 189 | case 0x2b: 190 | printf("0x%x: dcx h\n", i); 191 | return i + 1; 192 | 193 | case 0x2c: 194 | printf("0x%x: inr l\n", i); 195 | return i + 1; 196 | 197 | case 0x2d: 198 | printf("0x%x: dcr l\n", i); 199 | return i + 1; 200 | 201 | case 0x2e: 202 | printf("0x%x: mvi l, 0x%x\n", i, cpu->memory[i + 1]); 203 | return i + 2; 204 | 205 | case 0x2f: 206 | printf("0x%x: cma\n", i); 207 | return i + 1; 208 | 209 | case 0x30: 210 | printf("0x%x: 0x30 instruction not implemented.\n", i); 211 | return i + 1; 212 | 213 | case 0x31: 214 | printf("0x%x: lxi sp, ", i); 215 | printTwoArgs(cpu, i); 216 | return i + 3; 217 | 218 | case 0x32: 219 | printf("0x%x: sta, ", i); 220 | printTwoArgs(cpu, i); 221 | return i + 3; 222 | 223 | case 0x33: 224 | printf("0x%x: inx sp\n", i); 225 | return i + 1; 226 | 227 | case 0x34: 228 | printf("0x%x: inr m\n", i); 229 | return i + 1; 230 | 231 | case 0x35: 232 | printf("0x%x: dcr m\n", i); 233 | return i + 1; 234 | 235 | case 0x36: 236 | printf("0x%x: mvi m, 0x%x\n", i, cpu->memory[i + 1]); 237 | return i + 2; 238 | 239 | case 0x37: 240 | printf("0x%x: stc\n", i); 241 | return i + 1; 242 | 243 | case 0x38: 244 | printf("0x%x: 0x38 instruction not implemented.\n", i); 245 | return i + 1; 246 | 247 | case 0x39: 248 | printf("0x%x: dad sp\n", i); 249 | return i + 1; 250 | 251 | case 0x3a: 252 | printf("0x%x: lda, ", i); 253 | printTwoArgs(cpu, i); 254 | return i + 3; 255 | 256 | case 0x3b: 257 | printf("0x%x: dcx sp\n", i); 258 | return i + 1; 259 | 260 | case 0x3c: 261 | printf("0x%x: inr a\n", i); 262 | return i + 1; 263 | 264 | case 0x3d: 265 | printf("0x%x: dcr a\n", i); 266 | return i + 1; 267 | 268 | case 0x3e: 269 | printf("0x%x: mvi a, 0x%x\n", i, cpu->memory[i + 1]); 270 | return i + 2; 271 | 272 | case 0x3f: 273 | printf("0x%x: cmc\n", i); 274 | return i + 1; 275 | 276 | 277 | case 0x40: 278 | printf("0x%x: mov b, b\n", i); 279 | return i + 1; 280 | 281 | case 0x41: 282 | printf("0x%x: mov b, c\n", i); 283 | return i + 1; 284 | 285 | case 0x42: 286 | printf("0x%x: mov b, d\n", i); 287 | return i + 1; 288 | 289 | case 0x43: 290 | printf("0x%x: mov b, e\n", i); 291 | return i + 1; 292 | 293 | case 0x44: 294 | printf("0x%x: mov b, h\n", i); 295 | return i + 1; 296 | 297 | case 0x45: 298 | printf("0x%x: mov b, l\n", i); 299 | return i + 1; 300 | 301 | case 0x46: 302 | printf("0x%x: mov b, m\n", i); 303 | return i + 1; 304 | 305 | case 0x47: 306 | printf("0x%x: mov b, a\n", i); 307 | return i + 1; 308 | 309 | case 0x48: 310 | printf("0x%x: mov c, b\n", i); 311 | return i + 1; 312 | 313 | case 0x49: 314 | printf("0x%x: mov c, c\n", i); 315 | return i + 1; 316 | 317 | case 0x4a: 318 | printf("0x%x: mov c, d\n", i); 319 | return i + 1; 320 | 321 | case 0x4b: 322 | printf("0x%x: mov c, e\n", i); 323 | return i + 1; 324 | 325 | case 0x4c: 326 | printf("0x%x: mov c, h\n", i); 327 | return i + 1; 328 | 329 | case 0x4d: 330 | printf("0x%x: mov c, l\n", i); 331 | return i + 1; 332 | 333 | case 0x4e: 334 | printf("0x%x: mov c, m\n", i); 335 | return i + 1; 336 | 337 | case 0x4f: 338 | printf("0x%x: mov c, a\n", i); 339 | return i + 1; 340 | 341 | case 0x50: 342 | printf("0x%x: mov d, b\n", i); 343 | return i + 1; 344 | 345 | case 0x51: 346 | printf("0x%x: mov d, c\n", i); 347 | return i + 1; 348 | 349 | case 0x52: 350 | printf("0x%x: mov d, d\n", i); 351 | return i + 1; 352 | 353 | case 0x53: 354 | printf("0x%x: mov d, e\n", i); 355 | return i + 1; 356 | 357 | case 0x54: 358 | printf("0x%x: mov d, h\n", i); 359 | return i + 1; 360 | 361 | case 0x55: 362 | printf("0x%x: mov d, l\n", i); 363 | return i + 1; 364 | 365 | case 0x56: 366 | printf("0x%x: mov d, m\n", i); 367 | return i + 1; 368 | 369 | case 0x57: 370 | printf("0x%x: mov d, a\n", i); 371 | return i + 1; 372 | 373 | case 0x58: 374 | printf("0x%x: mov e, b\n", i); 375 | return i + 1; 376 | 377 | case 0x59: 378 | printf("0x%x: mov e, c\n", i); 379 | return i + 1; 380 | 381 | case 0x5a: 382 | printf("0x%x: mov e, d\n", i); 383 | return i + 1; 384 | 385 | case 0x5b: 386 | printf("0x%x: mov e, e\n", i); 387 | return i + 1; 388 | 389 | case 0x5c: 390 | printf("0x%x: mov e, h\n", i); 391 | return i + 1; 392 | 393 | case 0x5d: 394 | printf("0x%x: mov e, l\n", i); 395 | return i + 1; 396 | 397 | case 0x5e: 398 | printf("0x%x: mov e, m\n", i); 399 | return i + 1; 400 | 401 | case 0x5f: 402 | printf("0x%x: mov e, a\n", i); 403 | return i + 1; 404 | 405 | case 0x60: 406 | printf("0x%x: mov h, b\n", i); 407 | return i + 1; 408 | 409 | case 0x61: 410 | printf("0x%x: mov h, c\n", i); 411 | return i + 1; 412 | 413 | case 0x62: 414 | printf("0x%x: mov h, d\n", i); 415 | return i + 1; 416 | 417 | case 0x63: 418 | printf("0x%x: mov h, e\n", i); 419 | return i + 1; 420 | 421 | case 0x64: 422 | printf("0x%x: mov h, h\n", i); 423 | return i + 1; 424 | 425 | case 0x65: 426 | printf("0x%x: mov h, l\n", i); 427 | return i + 1; 428 | 429 | case 0x66: 430 | printf("0x%x: mov h, m\n", i); 431 | return i + 1; 432 | 433 | case 0x67: 434 | printf("0x%x: mov h, a\n", i); 435 | return i + 1; 436 | 437 | case 0x68: 438 | printf("0x%x: mov l, b\n", i); 439 | return i + 1; 440 | 441 | case 0x69: 442 | printf("0x%x: mov l, c\n", i); 443 | return i + 1; 444 | 445 | case 0x6a: 446 | printf("0x%x: mov l, d\n", i); 447 | return i + 1; 448 | 449 | case 0x6b: 450 | printf("0x%x: mov l, e\n", i); 451 | return i + 1; 452 | 453 | case 0x6c: 454 | printf("0x%x: mov l, h\n", i); 455 | return i + 1; 456 | 457 | case 0x6d: 458 | printf("0x%x: mov l, l\n", i); 459 | return i + 1; 460 | 461 | case 0x6e: 462 | printf("0x%x: mov l, m\n", i); 463 | return i + 1; 464 | 465 | case 0x6f: 466 | printf("0x%x: mov l, a\n", i); 467 | return i + 1; 468 | 469 | case 0x70: 470 | printf("0x%x: mov m, b\n", i); 471 | return i + 1; 472 | 473 | case 0x71: 474 | printf("0x%x: mov m, c\n", i); 475 | return i + 1; 476 | 477 | case 0x72: 478 | printf("0x%x: mov m, d\n", i); 479 | return i + 1; 480 | 481 | case 0x73: 482 | printf("0x%x: mov m, e\n", i); 483 | return i + 1; 484 | 485 | case 0x74: 486 | printf("0x%x: mov m, h\n", i); 487 | return i + 1; 488 | 489 | case 0x75: 490 | printf("0x%x: mov m, l\n", i); 491 | return i + 1; 492 | 493 | case 0x76: 494 | printf("0x%x: hlt\n", i); 495 | return i + 1; 496 | 497 | case 0x77: 498 | printf("0x%x: mov m, a\n", i); 499 | return i + 1; 500 | 501 | case 0x78: 502 | printf("0x%x: mov a, b\n", i); 503 | return i + 1; 504 | 505 | case 0x79: 506 | printf("0x%x: mov a, c\n", i); 507 | return i + 1; 508 | 509 | case 0x7a: 510 | printf("0x%x: mov a, d\n", i); 511 | return i + 1; 512 | 513 | case 0x7b: 514 | printf("0x%x: mov a, e\n", i); 515 | return i + 1; 516 | 517 | case 0x7c: 518 | printf("0x%x: mov a, h\n", i); 519 | return i + 1; 520 | 521 | case 0x7d: 522 | printf("0x%x: mov a, l\n", i); 523 | return i + 1; 524 | 525 | case 0x7e: 526 | printf("0x%x: mov a, m\n", i); 527 | return i + 1; 528 | 529 | case 0x7f: 530 | printf("0x%x: mov a, a\n", i); 531 | return i + 1; 532 | 533 | case 0x80: 534 | printf("0x%x: add b\n", i); 535 | return i + 1; 536 | 537 | case 0x81: 538 | printf("0x%x: add c\n", i); 539 | return i + 1; 540 | 541 | case 0x82: 542 | printf("0x%x: add d\n", i); 543 | return i + 1; 544 | 545 | case 0x83: 546 | printf("0x%x: add e\n", i); 547 | return i + 1; 548 | 549 | case 0x84: 550 | printf("0x%x: add h\n", i); 551 | return i + 1; 552 | 553 | case 0x85: 554 | printf("0x%x: add l\n", i); 555 | return i + 1; 556 | 557 | case 0x86: 558 | printf("0x%x: add m\n", i); 559 | return i + 1; 560 | 561 | case 0x87: 562 | printf("0x%x: add a\n", i); 563 | return i + 1; 564 | 565 | case 0x88: 566 | printf("0x%x: adc b\n", i); 567 | return i + 1; 568 | 569 | case 0x89: 570 | printf("0x%x: adc c\n", i); 571 | return i + 1; 572 | 573 | case 0x8a: 574 | printf("0x%x: adc d\n", i); 575 | return i + 1; 576 | 577 | case 0x8b: 578 | printf("0x%x: adc e\n", i); 579 | return i + 1; 580 | 581 | case 0x8c: 582 | printf("0x%x: adc h\n", i); 583 | return i + 1; 584 | 585 | case 0x8d: 586 | printf("0x%x: adc l\n", i); 587 | return i + 1; 588 | 589 | case 0x8e: 590 | printf("0x%x: adc m\n", i); 591 | return i + 1; 592 | 593 | case 0x8f: 594 | printf("0x%x: adc a\n", i); 595 | return i + 1; 596 | 597 | case 0x90: 598 | printf("0x%x: sub b\n", i); 599 | return i + 1; 600 | 601 | case 0x91: 602 | printf("0x%x: sub c\n", i); 603 | return i + 1; 604 | 605 | case 0x92: 606 | printf("0x%x: sub d\n", i); 607 | return i + 1; 608 | 609 | case 0x93: 610 | printf("0x%x: sub e\n", i); 611 | return i + 1; 612 | 613 | case 0x94: 614 | printf("0x%x: sub h\n", i); 615 | return i + 1; 616 | 617 | case 0x95: 618 | printf("0x%x: sub l\n", i); 619 | return i + 1; 620 | 621 | case 0x96: 622 | printf("0x%x: sub m\n", i); 623 | return i + 1; 624 | 625 | case 0x97: 626 | printf("0x%x: sub a\n", i); 627 | return i + 1; 628 | 629 | case 0x98: 630 | printf("0x%x: sbb b\n", i); 631 | return i + 1; 632 | 633 | case 0x99: 634 | printf("0x%x: sbb c\n", i); 635 | return i + 1; 636 | 637 | case 0x9a: 638 | printf("0x%x: sbb d\n", i); 639 | return i + 1; 640 | 641 | case 0x9b: 642 | printf("0x%x: sbb e\n", i); 643 | return i + 1; 644 | 645 | case 0x9c: 646 | printf("0x%x: sbb h\n", i); 647 | return i + 1; 648 | 649 | case 0x9d: 650 | printf("0x%x: sbb l\n", i); 651 | return i + 1; 652 | 653 | case 0x9e: 654 | printf("0x%x: sbb m\n", i); 655 | return i + 1; 656 | 657 | case 0x9f: 658 | printf("0x%x: sbb a\n", i); 659 | return i + 1; 660 | 661 | case 0xa0: 662 | printf("0x%x: ana b\n", i); 663 | return i + 1; 664 | 665 | case 0xa1: 666 | printf("0x%x: ana c\n", i); 667 | return i + 1; 668 | 669 | case 0xa2: 670 | printf("0x%x: ana d\n", i); 671 | return i + 1; 672 | 673 | case 0xa3: 674 | printf("0x%x: ana e\n", i); 675 | return i + 1; 676 | 677 | case 0xa4: 678 | printf("0x%x: ana h\n", i); 679 | return i + 1; 680 | 681 | case 0xa5: 682 | printf("0x%x: ana l\n", i); 683 | return i + 1; 684 | 685 | case 0xa6: 686 | printf("0x%x: ana m\n", i); 687 | return i + 1; 688 | 689 | case 0xa7: 690 | printf("0x%x: ana a\n", i); 691 | return i + 1; 692 | 693 | case 0xa8: 694 | printf("0x%x: xra b\n", i); 695 | return i + 1; 696 | 697 | case 0xa9: 698 | printf("0x%x: xra c\n", i); 699 | return i + 1; 700 | 701 | case 0xaa: 702 | printf("0x%x: xra d\n", i); 703 | return i + 1; 704 | 705 | case 0xab: 706 | printf("0x%x: xra e\n", i); 707 | return i + 1; 708 | 709 | case 0xac: 710 | printf("0x%x: xra h\n", i); 711 | return i + 1; 712 | 713 | case 0xad: 714 | printf("0x%x: xra l\n", i); 715 | return i + 1; 716 | 717 | case 0xae: 718 | printf("0x%x: xra m\n", i); 719 | return i + 1; 720 | 721 | case 0xaf: 722 | printf("0x%x: xra a\n", i); 723 | return i + 1; 724 | 725 | case 0xb0: 726 | printf("0x%x: ora b\n", i); 727 | return i + 1; 728 | 729 | case 0xb1: 730 | printf("0x%x: ora c\n", i); 731 | return i + 1; 732 | 733 | case 0xb2: 734 | printf("0x%x: ora d\n", i); 735 | return i + 1; 736 | 737 | case 0xb3: 738 | printf("0x%x: ora e\n", i); 739 | return i + 1; 740 | 741 | case 0xb4: 742 | printf("0x%x: ora h\n", i); 743 | return i + 1; 744 | 745 | case 0xb5: 746 | printf("0x%x: ora l\n", i); 747 | return i + 1; 748 | 749 | case 0xb6: 750 | printf("0x%x: ora m\n", i); 751 | return i + 1; 752 | 753 | case 0xb7: 754 | printf("0x%x: ora a\n", i); 755 | return i + 1; 756 | 757 | case 0xb8: 758 | printf("0x%x: cmp b\n", i); 759 | return i + 1; 760 | 761 | case 0xb9: 762 | printf("0x%x: cmp c\n", i); 763 | return i + 1; 764 | 765 | case 0xba: 766 | printf("0x%x: cmp d\n", i); 767 | return i + 1; 768 | 769 | case 0xbb: 770 | printf("0x%x: cmp e\n", i); 771 | return i + 1; 772 | 773 | case 0xbc: 774 | printf("0x%x: cmp h\n", i); 775 | return i + 1; 776 | 777 | case 0xbd: 778 | printf("0x%x: cmp l\n", i); 779 | return i + 1; 780 | 781 | case 0xbe: 782 | printf("0x%x: cmp m\n", i); 783 | return i + 1; 784 | 785 | case 0xbf: 786 | printf("0x%x: cmp a\n", i); 787 | return i + 1; 788 | 789 | case 0xc0: 790 | printf("0x%x: rnz\n", i); 791 | return i + 1; 792 | 793 | case 0xc1: 794 | printf("0x%x: pop b\n", i); 795 | return i + 1; 796 | 797 | case 0xc2: 798 | printf("0x%x: jnz, ", i); 799 | printTwoArgsBack(cpu, i); 800 | return i + 3; 801 | 802 | case 0xc3: 803 | printf("0x%x: jmp, ", i); 804 | printTwoArgsBack(cpu, i); 805 | return i + 3; 806 | 807 | case 0xc4: 808 | printf("0x%x: cnz ", i); 809 | printTwoArgsBack(cpu, i); 810 | return i + 3; 811 | 812 | case 0xc5: 813 | printf("0x%x: push b\n", i); 814 | return i + 1; 815 | 816 | case 0xc6: 817 | printf("0x%x: adi, 0x%x\n", i, cpu->memory[i + 1]); 818 | return i + 2; 819 | 820 | case 0xc7: 821 | printf("0x%x: rst 0\n", i); 822 | return i + 1; 823 | 824 | case 0xc8: 825 | printf("0x%x: rz\n", i); 826 | return i + 1; 827 | 828 | case 0xc9: 829 | printf("0x%x: ret\n", i); 830 | return i + 1; 831 | 832 | case 0xca: 833 | printf("0x%x: jz, ", i); 834 | printTwoArgsBack(cpu, i); 835 | return i + 3; 836 | 837 | case 0xcb: 838 | printf("0x%x: 0xcb instruction not implemented.\n", i); 839 | return i + 1; 840 | 841 | case 0xcc: 842 | printf("0x%x: cz, ", i); 843 | printTwoArgsBack(cpu, i); 844 | return i + 3; 845 | 846 | case 0xcd: 847 | printf("0x%x: call, ", i); 848 | printTwoArgsBack(cpu, i); 849 | return i + 3; 850 | 851 | case 0xce: 852 | printf("0x%x: aci, 0x%x\n", i, cpu->memory[i + 1]); 853 | return i + 2; 854 | 855 | case 0xcf: 856 | printf("0x%x: rst 1\n", i); 857 | return i + 1; 858 | 859 | case 0xd0: 860 | printf("0x%x: rnc\n", i); 861 | return i + 1; 862 | 863 | case 0xd1: 864 | printf("0x%x: pop d\n", i); 865 | return i + 1; 866 | 867 | case 0xd2: 868 | printf("0x%x: jnc, ", i); 869 | printTwoArgsBack(cpu, i); 870 | return i + 3; 871 | 872 | case 0xd3: 873 | printf("0x%x: out 0x%x\n", i, cpu->memory[i + 1]); 874 | return i + 2; 875 | 876 | case 0xd4: 877 | printf("0x%x: cnc ", i); 878 | printTwoArgsBack(cpu, i); 879 | return i + 3; 880 | 881 | case 0xd5: 882 | printf("0x%x: push d\n", i); 883 | return i + 1; 884 | 885 | case 0xd6: 886 | printf("0x%x: sui, 0x%x\n", i, cpu->memory[i + 1]); 887 | return i + 2; 888 | 889 | case 0xd7: 890 | printf("0x%x: rst 2\n", i); 891 | return i + 1; 892 | 893 | case 0xd8: 894 | printf("0x%x: rc\n", i); 895 | return i + 1; 896 | 897 | case 0xd9: 898 | printf("0x%x: 0xd9 instruction not implemented.\n", i); 899 | return i + 1; 900 | 901 | case 0xda: 902 | printf("0x%x: jc, ", i); 903 | printTwoArgsBack(cpu, i); 904 | return i + 3; 905 | 906 | case 0xdb: 907 | printf("0x%x: in 0x%x\n", i, cpu->memory[i + 1]); 908 | return i + 2; 909 | 910 | case 0xdc: 911 | printf("0x%x: cc, ", i); 912 | printTwoArgsBack(cpu, i); 913 | return i + 3; 914 | 915 | case 0xdd: 916 | printf("0x%x: end 0x%x\n", i, cpu->memory[i + 1]); 917 | return i + 2; 918 | case 0xde: 919 | printf("0x%x: sbi, 0x%x\n", i, cpu->memory[i + 1]); 920 | return i + 2; 921 | 922 | case 0xdf: 923 | printf("0x%x: rst 3\n", i); 924 | return i + 1; 925 | 926 | case 0xe0: 927 | printf("0x%x: rpo\n", i); 928 | return i + 1; 929 | 930 | case 0xe1: 931 | printf("0x%x: pop h\n", i); 932 | return i + 1; 933 | 934 | case 0xe2: 935 | printf("0x%x: jpo, ", i); 936 | printTwoArgsBack(cpu, i); 937 | return i + 3; 938 | 939 | case 0xe3: 940 | printf("0x%x: xthl\n", i); 941 | return i + 1; 942 | 943 | case 0xe4: 944 | printf("0x%x: cpo ", i); 945 | printTwoArgsBack(cpu, i); 946 | return i + 3; 947 | 948 | case 0xe5: 949 | printf("0x%x: push h\n", i); 950 | return i + 1; 951 | 952 | case 0xe6: 953 | printf("0x%x: ani, 0x%x\n", i, cpu->memory[i + 1]); 954 | return i + 2; 955 | 956 | case 0xe7: 957 | printf("0x%x: rst 4\n", i); 958 | return i + 1; 959 | 960 | case 0xe8: 961 | printf("0x%x: rpe\n", i); 962 | return i + 1; 963 | 964 | case 0xe9: 965 | printf("0x%x: pchl\n", i); 966 | return i + 1; 967 | 968 | case 0xea: 969 | printf("0x%x: jpe, ", i); 970 | printTwoArgsBack(cpu, i); 971 | return i + 3; 972 | 973 | case 0xeb: 974 | printf("0x%x: xchg\n", i); 975 | return i + 1; 976 | 977 | case 0xec: 978 | printf("0x%x: cpe, ", i); 979 | printTwoArgsBack(cpu, i); 980 | return i + 3; 981 | 982 | case 0xed: 983 | printf("0x%x: 0xed instruction not implemented.\n", i); 984 | return i + 1; 985 | 986 | case 0xee: 987 | printf("0x%x: xri, 0x%x\n", i, cpu->memory[i + 1]); 988 | return i + 2; 989 | 990 | case 0xef: 991 | printf("0x%x: rst 5\n", i); 992 | return i + 1; 993 | 994 | case 0xf0: 995 | printf("0x%x: rp\n", i); 996 | return i + 1; 997 | 998 | case 0xf1: 999 | printf("0x%x: pop psw\n", i); 1000 | return i + 1; 1001 | 1002 | case 0xf2: 1003 | printf("0x%x: jp, ", i); 1004 | printTwoArgsBack(cpu, i); 1005 | return i + 3; 1006 | 1007 | case 0xf3: 1008 | printf("0x%x: di\n", i); 1009 | return i + 1; 1010 | 1011 | case 0xf4: 1012 | printf("0x%x: cp ", i); 1013 | printTwoArgsBack(cpu, i); 1014 | return i + 3; 1015 | 1016 | case 0xf5: 1017 | printf("0x%x: push psw\n", i); 1018 | return i + 1; 1019 | 1020 | case 0xf6: 1021 | printf("0x%x: ori, 0x%x\n", i, cpu->memory[i + 1]); 1022 | return i + 2; 1023 | 1024 | case 0xf7: 1025 | printf("0x%x: rst 6\n", i); 1026 | return i + 1; 1027 | 1028 | case 0xf8: 1029 | printf("0x%x: rm\n", i); 1030 | return i + 1; 1031 | 1032 | case 0xf9: 1033 | printf("0x%x: sphl\n", i); 1034 | return i + 1; 1035 | 1036 | case 0xfa: 1037 | printf("0x%x: jm, ", i); 1038 | printTwoArgsBack(cpu, i); 1039 | return i + 3; 1040 | 1041 | case 0xfb: 1042 | printf("0x%x: ei\n", i); 1043 | return i + 1; 1044 | 1045 | case 0xfc: 1046 | printf("0x%x: cm, ", i); 1047 | printTwoArgsBack(cpu, i); 1048 | return i + 3; 1049 | 1050 | case 0xfd: 1051 | printf("0x%x: 0xfd instruction not implemented.\n", i); 1052 | return i + 1; 1053 | 1054 | case 0xfe: 1055 | printf("0x%x: cpi, 0x%x\n", i, cpu->memory[i + 1]); 1056 | return i + 2; 1057 | 1058 | case 0xff: 1059 | printf("0x%x: rst 7\n", i); 1060 | return i + 1; 1061 | } 1062 | return i + 1; 1063 | } -------------------------------------------------------------------------------- /disassembler/Readme.md: -------------------------------------------------------------------------------- 1 | # Python Disassembler 2 | 3 | When I was first working on this project, my first step was to write a chart mapping the instructions and what they do to specific opcodes, understanding how the registers/flags for this architecture worked, and writing a disassembler for it (which I did in python). 4 | 5 | 6 | ## Sources 7 | 8 | This information you see here is based off of the following resources: 9 | 10 | ``` 11 | https://pmd85.borik.net/instrset/instuction-set.html 12 | http://www.emulator101.com/reference/8080-by-opcode.html 13 | http://pastraiser.com/cpu/i8080/i8080_opcodes.html 14 | ``` 15 | 16 | ## Use 17 | 18 | to use this disassembler, just provide the binary file you wish to disassemble as an argument: 19 | 20 | ``` 21 | python disassemble.py block4/testcase034 22 | 0x0: mvi a, 0x0 23 | 0x2: mvi b, 0x25 24 | 0x4: mvi c, 0x3 25 | 0x7: ldax b 26 | 0x8: jnc 0x023 27 | 0xc: rlc 28 | 0xd: jnz 0x012 29 | 0x10: adi 0x1 30 | 0x12: cmp b 31 | 0x13: jnz 0x018 32 | 0x16: mvi a, 0x6 33 | 0x18: cmp c 34 | 0x19: jnz 0x01e 35 | 0x1c: mvi a, 0x23 36 | 0x1e: adi 0x1 37 | 0x20: jmp 0x06 38 | 0x23: nop 39 | 0x24: end 0x66 40 | ``` 41 | 42 | ## Registers 43 | 44 | This architecture has seven `8` bit registers, and three `16` bit registers. It also has 5 flags. In addition to that, the `8080` architecture uses `16` bit addresses: 45 | 46 | ``` 47 | A: 0x8 bit register Accumulator register 48 | B: 0x8 bit register Higher 8 bits of BC Register 49 | C: 0x8 bit register Lower 8 bits of BC Register 50 | D: 0x8 bit register Higher 8 bits of DE Register 51 | E: 0x8 bit register Lower 8 bits of DE Register 52 | H: 0x8 bit register Higher 8 bits of HL Register 53 | L: 0x8 bit register Lower 8 bits of the HL Register 54 | 55 | BC: 0x10 bit register 56 | DE: 0x10 bit register 57 | HL: 0x10 bit register 58 | 59 | SP: 0x10 bit Stack Pointer Register 60 | PC: 0x10 bit Program Counter Register 61 | 62 | F: 0x8 bit register Each bit holds one of the following severn flags 63 | 64 | 7: Sign (S Flag) 65 | 6: Zero (Z Flag) 66 | 5: 0 (It always holds the value 0) 67 | 4: Auxillary (AC or H Flag) 68 | 3: 0 (It always holds the value 0) 69 | 2: Parity (P Flag) 70 | 1: 1 (It always holds the value 1) 71 | 0: Carry (C Flag) 72 | ``` 73 | In addition to that, there are two registers we see `AF` and `m`, which are a bit different: 74 | ``` 75 | m - The register m, isn't a register, it just reference the memory address stored in the HL register. 76 | AF - A 0x10 (16) bit register, the higher 8 bits are the A register, and the lower 8 bits are the flags. 77 | ``` 78 | 79 | ## Chart 80 | 81 | Here is a chrart mapping the individual instructions and their functionallity to specific opcodes 82 | 83 | ``` 84 | 0x00 nop 1 byte Move forward to next instruction 85 | 0x01 lxi B, x, y 3 bytes Moves the second byte (x) into the C register, and the third byte (y) into the B register 86 | 0x02 stax b 1 byte Move contents of A register into the memory address stored in the BC register 87 | 0x03 inx b 1 byte Adds the value one to the BC register 88 | 0x04 inr b 1 byte Adds the value one to the B register 89 | 0x05 dcr b 1 byte Subtracts the value one from the B register 90 | 0x06 mov b, x 2 bytes Moves the value of x into the B register, where X is the second byte 91 | 0x07 rlc 1 byte The contents of the A regisrer are shifted by one to the left. The contents of the seventh bit are moved to the carry flag, and bit 0 92 | 0x08 No instruction 93 | 0x09 dad b 1 byte The value of BC is added to the HL register 94 | 0x0a ldax b 1 byte It dereferences the BC register, and moves that value into the A register 95 | 0x0b dcx b 1 byte Subtracts the value one from the BC register 96 | 0x0c inr c 1 byte Adds the value one to the C register 97 | 0x0d dcr c 1 byte Subtracts the value one from the C register 98 | 0x0e mov c, x 2 bytes Moves the value of x into the C register, where X is the second byte 99 | 0x0f rrc 1 byte The contents of the A register are shifted by one to the right. The contents of the 0th bit are moved to the 7th bit, and the carry flag. 100 | 101 | 102 | 103 | 104 | 0x10 No instruction 105 | 0x11 lxi d, x, y 3 bytes Moves the second byte (x) into the D register, and the third byte (y) into the E register 106 | 0x12 stax d 1 byte Move contents of A register into the memory address stored in the DC register 107 | 0x13 inx d 1 byte Increments the value of the DE register by 1 108 | 0x14 inr d 1 byte Increments the value of the D register by one 109 | 0x15 dcr d 1 byte Decrements the value of the D register by one 110 | 0x16 mov d, x 2 bytes Moves the value of x into the D register, where X is the second byte 111 | 0x17 ral 1 byte Rotate the contents of the A register by one to the left. The contents of the seventh bit are moved into the Carry flag, and the contents of the carry flag are moved into bit 0. 112 | 0x18 No instruction 113 | 0x19 dad d 1 byte Adds the contents of the register D to the HL register 114 | 0x1a ldax d 1 byte It dereferences the DE register, and moves it's contents into the A register. 115 | 0x1b dcx d 1 byte This decrements the value of the DE register by one. 116 | 0x1c inr e 1 byte This increments the value of the E register by one. 117 | 0x1d dcr e 1 byte This decrements the value of the E register by one. 118 | 0x1e mov e, x 2 bytes Moves the value of x into the E register, where X is the second byte 119 | 0x1f rar 1 byte This rotates the contents of the A register by one to the right. The contents of the 0 bit are moved into the carry flag, and the contents of the carry flag are moved into bit 7. 120 | 121 | 122 | 123 | 124 | 0x20 No instruction 125 | 0x21 lxi h, x, y 3 bytes Moves the second byte (x) into the L register, and the third byte (y) into the H register 126 | 0x22 shld addr 3 bytes Takes the address stored in addr, moves the contents of the L register where it points to, and moves the contents of the H register where addr+1 points to 127 | 0x23 inx h 1 byte Increments the value of the HL register by one 128 | 0x24 inr h 1 byte Increments the value of the H register by one 129 | 0x25 dcr h 1 byte Decrements the value of the H register by one 130 | 0x26 mov h, x 2 bytes Moves the value of x into the h register, where X is the second byte 131 | 0x27 daa 1 byte This is an instruction used after an add instruction, to convert from hex to decimal. The source and destination is the AL register. 132 | 0x28 No instruction 133 | 0x29 dad h 1 byte This adds the contents of the H register to the HL register. 134 | 0x2a lhld addr 3 bytes This takes the two byte (16 bit) address stored in addr, stores the derferenced value in the L register, and the derferenced value of addr+1 into the H register 135 | 0x2b dcx h 1 byte This decrements the value of the HL register by one. 136 | 0x2c inr l 1 byte This increments the value of the L register by one. 137 | 0x2d dcr l 1 byte This decrements the value of the L register by one. 138 | 0x2e mov l, x 2 bytes Moves the value of x into the L register, where X is the second byte 139 | 0x2f cma 1 byte Performs the compliment (bitwise not) on the A register 140 | 141 | 142 | 143 | 144 | 0x30 No instruction 145 | 0x31 lxi sp, x, y 3 bytes Moves the second byte (x) into the lower 8 bits of the SP register, and the third byte (y) into the higher 8 bits of the SP register 146 | 0x32 sta addr 3 bytes Moves the value of the A register into the area pointed to by the two byte address stored in addr 147 | 0x33 inx sp 1 byte Increments the value of the SP register by one. 148 | 0x34 inr m 1 byte This dereferences the HL register, and increments it's value by one. 149 | 0x35 dcr m 1 byte This dereferences the HL register, and decrements it's value by one. 150 | 0x36 mov m, x 2 bytes Moves the value of x into the address pointed to by the HL register, where X is the second byte 151 | 0x37 stc 1 byte Sets the carry flag equal to one 152 | 0x38 No instruction 153 | 0x39 dad sp 1 byte Adds the contents of the SP register to the HL register 154 | 0x3a lda addr 3 bytes This dereferences the two byte address stored in addr, and loads it's contents into the A register 155 | 0x3b dcx sp 1 byte This decrements the value of the SP register by one. 156 | 0x3c inr a 1 byte This increments the value of the A register by one 157 | 0x3d dcr a 1 byte This decrements the vlaue of the A register by one 158 | 0x3e mov a, x 2 bytes Moves the value of x into the A register, where X is the second byte 159 | 0x3f cmc 1 byte Performs the compliment (bitwise not) on the carry flag 160 | 161 | 162 | 163 | 164 | 0x40 mov b, b 1 byte Moves the contents of the B register, into the B register 165 | 0x41 mov b, c 1 byte Moves the contents of the C register, into the B register 166 | 0x42 mov b, d 1 byte Moves the contents of the D register, into the B register 167 | 0x43 mov b, e 1 byte Moves the contents of the E register, into the B register 168 | 0x44 mov b, h 1 byte Moves the contents of the H register, into the B register 169 | 0x45 mov b, l 1 byte Moves the contents of the L register, into the B register 170 | 0x46 mov b, m 1 byte Moves the value pointed to by the address stored in the HL register, into the B register 171 | 0x47 mov b, a 1 byte Moves the contents of the A register, into the B register 172 | 0x48 mov c, b 1 byte Moves the contents of the B register, into the C register 173 | 0x49 mov c, c 1 byte Moves the contents of the C register, into the C register 174 | 0x4a mov c, d 1 byte Moves the contents of the D register, into the C register 175 | 0x4b mov c, e 1 byte Moves the contents of the E register, into the C register 176 | 0x4c mov c, h 1 byte Moves the contents of the H register, into the C register 177 | 0x4d mov c, l 1 byte Moves the contents of the L register, into the C register 178 | 0x4e mov c, m 1 byte Moves the value pointed to by the address stored in the HL register, into the C register 179 | 0x4f mov c, a 1 byte Moves the contents of the A register, into the C register 180 | 181 | 182 | 183 | 184 | 0x50 mov d, b 1 byte Moves the contents of the B register, into the D register 185 | 0x51 mov d, c 1 byte Moves the contents of the C register, into the D register 186 | 0x52 mov d, d 1 byte Moves the contents of the D register, into the D register 187 | 0x53 mov d, e 1 byte Moves the contents of the E register, into the D register 188 | 0x54 mov d, h 1 byte Moves the contents of the H register, into the D register 189 | 0x55 mov d, l 1 byte Moves the contents of the L register, into the D register 190 | 0x56 mov d, m 1 byte Moves the value pointed to by the address stored in the HL register, into the D register 191 | 0x57 mov d, a 1 byte Moves the contents of the A register, into the D register 192 | 0x58 mov e, b 1 byte Moves the contents of the B register, into the E register 193 | 0x59 mov e, c 1 byte Moves the contents of the C register, into the E register 194 | 0x5a mov e, d 1 byte Moves the contents of the D register, into the E register 195 | 0x5b mov e, e 1 byte Moves the contents of the E register, into the E register 196 | 0x5c mov e, h 1 byte Moves the contents of the H register, into the E register 197 | 0x5d mov e, l 1 byte Moves the contents of the L register, into the E register 198 | 0x5e mov e, m 1 byte Moves the value pointed to by the address stored in the HL register, into the E register 199 | 0x5f mov e, a 1 byte Moves the contents of the A register, into the E register 200 | 201 | 202 | 203 | 204 | 0x60 mov h, b 1 byte Moves the contents of the B register, into the H register 205 | 0x61 mov h, c 1 byte Moves the contents of the C register, into the H register 206 | 0x62 mov h, d 1 byte Moves the contents of the D register, into the H register 207 | 0x63 mov h, e 1 byte Moves the contents of the E register, into the H register 208 | 0x64 mov h, h 1 byte Moves the contents of the H register, into the H register 209 | 0x65 mov h, l 1 byte Moves the contents of the L register, into the H register 210 | 0x66 mov h, m 1 byte Moves the value pointed to by the address stored in the HL register, into the H register 211 | 0x67 mov h, a 1 byte Moves the contents of the A register, into the H register 212 | 0x68 mov l, b 1 byte Moves the contents of the B register, into the L register 213 | 0x69 mov l, c 1 byte Moves the contents of the C register, into the L register 214 | 0x6a mov l, d 1 byte Moves the contents of the D register, into the l register 215 | 0x6b mov l, e 1 byte Moves the contents of the E register, into the l register 216 | 0x6c mov l, h 1 byte Moves the contents of the H register, into the l register 217 | 0x6d mov l, l 1 byte Moves the contents of the L register, into the L register 218 | 0x6e mov l, m 1 byte Moves the value pointed to by the address stored in the HL register, into the L register 219 | 0x6f mov l, a 1 byte Moves the contents of the A register, into the L register 220 | 221 | 222 | 223 | 224 | 0x70 mov m, b 1 byte Moves the contents of the B register, into the area pointed to by the address stored in the HL register 225 | 0x71 mov m, c 1 byte Moves the contents of the C register, into the area pointed to by the address stored in the HL register 226 | 0x72 mov m, d 1 byte Moves the contents of the D register, into the area pointed to by the address stored in the HL register 227 | 0x73 mov m, e 1 byte Moves the contents of the E register, into the area pointed to by the address stored in the HL register 228 | 0x74 mov m, h 1 byte Moves the contents of the H register, into the area pointed to by the address stored in the HL register 229 | 0x75 mov m, l 1 byte Moves the contents of the L register, into the area pointed to by the address stored in the HL registerr 230 | 0x76 hlt 1 byte Halts the CPU, untill the next external interrupt is fired 231 | 0x77 mov m, a 1 byte Moves the contents of the A register, into the area pointed to by the address stored in the HL register 232 | 0x78 mov a, b 1 byte Moves the contents of the B register, into the A register 233 | 0x79 mov a, c 1 byte Moves the contents of the C register, into the A register 234 | 0x7a mov a, d 1 byte Moves the contents of the D register, into the A register 235 | 0x7b mov a, e 1 byte Moves the contents of the E register, into the A register 236 | 0x7c mov a, h 1 byte Moves the contents of the H register, into the A register 237 | 0x7d mov a, l 1 byte Moves the contents of the L register, into the A register 238 | 0x7e mov a, m 1 byte Moves the value pointed to by the address stored in the HL register, into the A register 239 | 0x7f mov a, a 1 byte Moves the contents of the A register, into the A register 240 | 241 | 242 | 243 | 244 | 0x80 add b 1 byte Adds the contents of the A and B registers, and stores it in the A register 245 | 0x81 add c 1 byte Adds the contents of the A and C registers, and stores it in the A register 246 | 0x82 add d 1 byte Adds the contents of the A and D registers, and stores it in the A register 247 | 0x83 add e 1 byte Adds the contents of the A and E registers, and stores it in the A register 248 | 0x84 add h 1 byte Adds the contents of the A and H registers, and stores it in the A register 249 | 0x85 add l 1 byte Adds the contents of the A and L registers, and stores it in the A register 250 | 0x86 add m 1 byte Adds the contents of the A and what the address in the HL register points to, and stores it in the A register 251 | 0x87 add a 1 byte Adds the contents of the A and A registers, and stores it in the A register 252 | 0x88 adc b 1 byte Adds the contents of the A and B registers, and the Carry flag and stores it in the A register 253 | 0x89 adc c 1 byte Adds the contents of the A and C registers, and the Carry flag and stores it in the A register 254 | 0x8a adc d 1 byte Adds the contents of the A and D registers, and the Carry flag and stores it in the A register 255 | 0x8b adc e 1 byte Adds the contents of the A and E registers, and the Carry flag and stores it in the A register 256 | 0x8c adc h 1 byte Adds the contents of the A and H registers, and the Carry flag and stores it in the A register 257 | 0x8d adc l 1 byte Adds the contents of the A and L registers, and the Carry flag and stores it in the A register 258 | 0x8e adc m 1 byte Adds the contents of the A and what the address in the HL register points to, and the Carry flag and stores it in the A register 259 | 0x8f adc a 1 byte Adds the contents of the A and A registers, and the Carry flag and stores it in the A register 260 | 261 | 262 | 263 | 264 | 0x90 sub b 1 byte Subtracts the contents of the B register from the contents of the A, and stores it in the A register 265 | 0x91 sub c 1 byte Subtracts the contents of the C register from the contents of the A, and stores it in the A register 266 | 0x92 sub d 1 byte Subtracts the contents of the D register from the contents of the A, and stores it in the A register 267 | 0x93 sub e 1 byte Subtracts the contents of the E register from the contents of the A, and stores it in the A register 268 | 0x94 sub h 1 byte Subtracts the contents of the H register from the contents of the A, and stores it in the A register 269 | 0x95 sub l 1 byte Subtracts the contents of the L register from the contents of the A, and stores it in the A register 270 | 0x96 sub m 1 byte Subtracts the contents of what the address stored in the HL register points to, from the contents of the A, and stores it in the A register 271 | 0x97 sub a 1 byte Subtracts the contents of the A register from the contents of the A, and stores it in the A register 272 | 0x98 sbb b 1 byte Subtracts the contents of the B register and the Carry flag from the contents of the A, and stores it in the A register 273 | 0x99 sbb c 1 byte Subtracts the contents of the C register and the Carry flag from the contents of the A, and stores it in the A register 274 | 0x9a sbb d 1 byte Subtracts the contents of the D register and the Carry flag from the contents of the A, and stores it in the A register 275 | 0x9b sbb e 1 byte Subtracts the contents of the E register and the Carry flag from the contents of the A, and stores it in the A register 276 | 0x9c sbb h 1 byte Subtracts the contents of the H register and the Carry flag from the contents of the A, and stores it in the A register 277 | 0x9d sbb l 1 byte Subtracts the contents of the L register and the Carry flag from the contents of the A, and stores it in the A register 278 | 0x9e sbb m 1 byte Subtracts the contents of what the address stored in the HL register points to and the Carry flag, from the contents of the A, and stores it in the A register 279 | 0x9f sbb a 1 byte Subtracts the contents of the A register and the Carry flag from the contents of the A, and stores it in the A register 280 | 281 | 282 | 283 | 284 | 0xa0 ana b 1 byte Ands the contents of the B and A registers, and stores it in the A register 285 | 0xa1 ana c 1 byte Ands the contents of the C and A registers, and stores it in the A register 286 | 0xa2 ana d 1 byte Ands the contents of the D and A registers, and stores it in the A register 287 | 0xa3 ana e 1 byte Ands the contents of the E and A registers, and stores it in the A register 288 | 0xa4 ana h 1 byte Ands the contents of the H and A registers, and stores it in the A register 289 | 0xa5 ana l 1 byte Ands the contents of the L and A registers, and stores it in the A register 290 | 0xa6 ana m 1 byte Ands the contents of the value pointed to by the address stored in the HL register and the A register, and stores it in the A register 291 | 0xa7 ana a 1 byte Ands the contents of the A and A registers, and stores it in the A register 292 | 0xa8 xra b 1 byte Xors the contents of the B and A registers, and stores it in the A register 293 | 0xa9 xra c 1 byte Xors the contents of the C and A registers, and stores it in the A register 294 | 0xaa xra d 1 byte Xors the contents of the D and A registers, and stores it in the A register 295 | 0xab xra e 1 byte Xors the contents of the E and A registers, and stores it in the A register 296 | 0xac xra h 1 byte Xors the contents of the H and A registers, and stores it in the A register 297 | 0xad xra l 1 byte Xors the contents of the L and A registers, and stores it in the A register 298 | 0xae xra m 1 byte Xors the contents of the value pointed to by the address stored in the HL register and the A register, and stores it in the A register 299 | 0xaf xra a 1 byte Xors the contents of the B and A registers, and stores it in the A register 300 | 301 | 302 | 303 | 0xb0 ora b 1 byte Ors the contents of the B and A registers, and stores it in the A register 304 | 0xb1 ora c 1 byte Ors the contents of the C and A registers, and stores it in the A register 305 | 0xb2 ora d 1 byte Ors the contents of the D and A registers, and stores it in the A register 306 | 0xb3 ora e 1 byte Ors the contents of the E and A registers, and stores it in the A register 307 | 0xb4 ora h 1 byte Ors the contents of the H and A registers, and stores it in the A register 308 | 0xb5 ora l 1 byte Ors the contents of the L and A registers, and stores it in the A register 309 | 0xb6 ora m 1 byte Ors the contents of the value pointed to by the address stored in the HL register and the A register, and stores it in the A register 310 | 0xb7 ora a 1 byte Ors the contents of the A and A registers, and stores it in the A register 311 | 0xb8 cmp b 1 byte Subtracts the contents of the B register from the A register, if it is equal to zero the Zero flag is set equal to 1, if not then the Zero flag is set to 0 312 | 0xb9 cmp c 1 byte Subtracts the contents of the C register from the A register, if it is equal to zero the Zero flag is set equal to 1, if not then the Zero flag is set to 0 313 | 0xba cmp d 1 byte Subtracts the contents of the D register from the A register, if it is equal to zero the Zero flag is set equal to 1, if not then the Zero flag is set to 0 314 | 0xbb cmp e 1 byte Subtracts the contents of the E register from the A register, if it is equal to zero the Zero flag is set equal to 1, if not then the Zero flag is set to 0 315 | 0xbc cmp h 1 byte Subtracts the contents of the H register from the A register, if it is equal to zero the Zero flag is set equal to 1, if not then the Zero flag is set to 0 316 | 0xbd cmp l 1 byte Subtracts the contents of the L register from the A register, if it is equal to zero the Zero flag is set equal to 1, if not then the Zero flag is set to 0 317 | 0xbe cmp m 1 byte Subtracts the value pointed to by the address stored in the HL register from the A register, if it is equal to zero the Zero flag is set equal to 1, if not then the Zero flag is set to 0 HL register and the A register, and stores it in the A register 318 | 0xbf cmp a 1 byte Subtracts the contents of the A register from the A register, if it is equal to zero the Zero flag is set equal to 1, if not then the Zero flag is set to 0 319 | 320 | 321 | 322 | 323 | 0xc0 rnz 1 byte If the Zero flag is equal to 0, return 324 | 0xc1 pop b 1 byte The memory location pointed to by the address stored in the SP register, is moved into the C register. Then the SP register is incremented, and then the value pointed to by it's address is moved into the B register, and the SP register is incremented again 325 | 0xc2 jnz adr 3 bytes If the Zero flag is equal to 0 jump to the address where adr is (last two bytes of instruction) 326 | 0xc3 jmp adr 3 bytes Jump to the address stored in adr 327 | 0xc4 cnz adr 3 bytes If the Zero flag is equal to 0, push the current PC plus 3 onto the stack, and call the address where adr is the last two bytes of the instruction 328 | 0xc5 push b 1 byte The SP register is decremented, and the contents of B is stored where the address of SP points to. The SP register is decremented again, and the contents of C is stored where the address os SP points to 329 | 0xc6 adi x 2 bytes Adds the value of x (the second byte of the instruction) to the A register 330 | 0xc7 rst 0 1 byte Pushes the value of the PC register plus one onto the stack, then the PC register has the value 0x0000 moved into it 331 | 0xc8 rz 1 byte If the value of the Zero flag is equal to one, pop the top stack value into the PC register 332 | 0xc9 ret 1 byte The top stack value is popped into the PC register 333 | 0xca jz adr 3 bytes If the zero flag is equal to one, the value adr (last two bytes of the instruction) are moved into the PC register 334 | 0xcb No instruction 335 | 0xcc cz adr 3 bytes If the zero flag is equal to 1, the current value of the PC register plus three is pushed onto the stack, then adr (last two bytes of the instruction) is moved into the PC register 336 | 0xcd call adr 3 bytes The current value of the PC register plus three is pushed onto the stack, then adr (last two bytes of the instruction) is moved into the PC register 337 | 0xce aci x 2 bytes The value of the Carry flag and x (second byte of the instruction) are added to the A register 338 | 0xcf rst 1 1 byte Pushes the value of the PC register plus one onto the stack, then the PC register has the value 0x0008 moved into it 339 | 340 | 341 | 342 | 343 | 0xd0 rnc 1 byte If the Carry flag is equal to 0, return 344 | 0xd1 pop d 1 byte The memory location pointed to by the address stored in the SP register, is moved into the E register. Then the SP register is incremented, and then the value pointed to by it's address is moved into the D register, and the SP register is incremented again 345 | 0xd2 jnc adr 3 bytes If the Carry flag is equal to 0 jump to the address where adr is (last two bytes of instruction) 346 | 0xd3 out x 2 bytes The value of A is written to the port x (x is the second byte of the instruction) 347 | 0xd4 cnc adr 3 bytes If the Carry flag is equal to 0, push the current PC plus 3 onto the stack, and call the address where adr is the last two bytes of the instruction 348 | 0xd5 push d 1 byte The SP register is decremented, and the contents of D is stored where the address of SP points to. The SP register is decremented again, and the contents of E is stored where the address os SP points to 349 | 0xd6 sui x 2 bytes Subtracts the value of x (the second byte of the instruction) from the A register 350 | 0xd7 rst 2 1 byte Pushes the value of the PC register plus one onto the stack, then the PC register has the value 0x0010 moved into it 351 | 0xd8 rc 1 byte If the value of the Carry flag is equal to one, pop the top stack value into the PC register 352 | 0xd9 No instruction 353 | 0xda jc adr 3 bytes If the Carry flag is equal to one, the value adr (last two bytes of the instruction) are moved into the PC register 354 | 0xdb in x 2 bytes A byte from port x is written to the A register 355 | 0xdc cc adr 3 bytes If the Carry flag is equal to 1, the current value of the PC register plus three is pushed onto the stack, then adr (last two bytes of the instruction) is moved into the PC register 356 | 0xdd No instruction 357 | 0xde sbi x 2 bytes The value of the Carry flag and x (second byte of the instruction) are subtracted from the A register 358 | 0xdf rst 3 1 byte Pushes the value of the PC register plus one onto the stack, then the PC register has the value 0x0018 moved into it 359 | 360 | 361 | 362 | 363 | 0xe0 rpo 1 byte If the Parity flag is equal to 0, return 364 | 0xe1 pop h 1 byte The memory location pointed to by the address stored in the SP register, is moved into the L register. Then the SP register is incremented, and then the value pointed to by it's address is moved into the H register, and the SP register is incremented again 365 | 0xe2 jpo adr 3 bytes If the Parity flag is equal to 0 jump to the address where adr is (last two bytes of instruction) 366 | 0xe3 xthl 1 byte Moves the pointer stored in the L location into SP, and the pointer stored in H into SP+1 367 | 0xe4 cpo adr 3 bytes If the Parity flag is equal to 0, push the current PC plus 3 onto the stack, and call the address where adr is the last two bytes of the instruction 368 | 0xe5 push h 1 byte The SP register is decremented, and the contents of H is stored where the address of SP points to. The SP register is decremented again, and the contents of L is stored where the address os SP points to 369 | 0xe6 ani x 2 bytes Performs a bitwise and on the A register, and x (second byte of the instruction) 370 | 0xe7 rst 4 1 byte Pushes the value of the PC register plus one onto the stack, then the PC register has the value 0x0020 moved into it 371 | 0xe8 rpe 1 byte If the value of the Parity flag is equal to one, pop the top stack value into the PC register 372 | 0xe9 pchl 1 byte Loads the contents of the HL register into the PC register 373 | 0xea jpe adr 3 bytes If the Parity flag is equal to one, the value adr (last two bytes of the instruction) are moved into the PC register 374 | 0xeb xchg 1 byte Exchanges the contents of the DE and HL registers 375 | 0xec cpe adr 3 bytes If the Parity flag is equal to 1, the current value of the PC register plus three is pushed onto the stack, then adr (last two bytes of the instruction) is moved into the PC register 376 | 0xed No instruction 377 | 0xee xri x 2 bytes The value of the x (second byte of the instruction) is xored with the A register 378 | 0xef rst 5 1 byte Pushes the value of the PC register plus one onto the stack, then the PC register has the value 0x0028 moved into it 379 | 380 | 381 | 382 | 383 | 0xf0 rp 1 byte If the Sign flag is equal to 0, return 384 | 0xf1 pop psw 1 byte The memory location pointed to by the address stored in the SP register, is moved into the F register. Then the SP register is incremented, and then the value pointed to by it's address is moved into the A register, and the SP register is incremented again 385 | 0xf2 jp adr 3 bytes If the Sign flag is equal to 0 jump to the address where adr is (last two bytes of instruction) 386 | 0xf3 di 1 byte This resets the interrupt flip-flops, which prevents interrupt from triggering 387 | 0xf4 cp adr 3 bytes If the Sign flag is equal to 0, push the current PC plus 3 onto the stack, and call the address where adr is the last two bytes of the instruction 388 | 0xf5 push psw 1 byte The SP register is decremented, and the contents of A is stored where the address of SP points to. The SP register is decremented again, and the contents of F is stored where the address os SP points to 389 | 0xf6 ori x 2 bytes Performs a bitwise or on the A register, and x (second byte of the instruction) 390 | 0xf7 rst 6 1 byte Pushes the value of the PC register plus one onto the stack, then the PC register has the value 0x0030 moved into it 391 | 0xf8 rm 1 byte If the value of the Sign flag is equal to one, pop the top stack value into the PC register 392 | 0xf9 sphl 1 byte Loads the contents of the HL register into the SP register 393 | 0xfa jm adr 3 bytes If the Sign flag is equal to one, the value adr (last two bytes of the instruction) are moved into the PC register 394 | 0xfb ei 1 byte This sets the interrupt flip-flops, which allows for interrupts 395 | 0xfc cm adr 3 bytes If the Parity flag is equal to 1, the current value of the PC register plus three is pushed onto the stack, then adr (last two bytes of the instruction) is moved into the PC register 396 | 0xfd No instruction 397 | 0xfe cpi x 2 bytes The value of the x (second byte of the instruction) is subtracted from the A register, and sets the corresponding flags based off of it. The value of the A register isn't changed. 398 | 0xff rst 7 1 byte Pushes the value of the PC register plus one onto the stack, then the PC register has the value 0x0038 moved into it 399 | 400 | ``` 401 | -------------------------------------------------------------------------------- /src/emulate.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Nightfall.h" 4 | 5 | // This file has the code which actually runs the operations for each opcode 6 | 7 | void emulate(cpu8080 *cpu) 8 | { 9 | // Variables for helping us tell what code we are executing 10 | int running; 11 | int stepIns; 12 | uint8_t op; 13 | 14 | // Variables for helping with calculations 15 | uint8_t x0; 16 | uint16_t x; 17 | uint16_t y; 18 | uint32_t z; 19 | 20 | // This variable just keeps track if we are running 21 | running = 1; 22 | 23 | // Run it as a for loop for every possible instruction between 0 - 0xffff (all 16 bits of memory), and while we are running 24 | for (cpu->pc = cpu->pc; cpu->pc < 0x1000 && running == 1; cpu->pc++) 25 | { 26 | // Set the opcode to the next instruction 27 | op = (uint8_t)cpu->memory[cpu->pc]; 28 | 29 | // Check if we hit a breakpoint 30 | if (isBreakPoint(cpu) == 0 && cpu->breaked == false) 31 | { 32 | printf("Breakpoint hit at 0x%x\n", (int)cpu->pc); 33 | cpu->breaked = true; 34 | return; 35 | } 36 | else 37 | { 38 | cpu->breaked = false; 39 | } 40 | 41 | // See if we are stepping through an instruction, and break accordingly 42 | 43 | if (cpu->step == 1) 44 | { 45 | cpu->step = 2; 46 | } 47 | 48 | else if (cpu->step == 2) 49 | { 50 | printf("Stepped to 0x%x\n", (int)cpu->pc); 51 | cpu->step = 0; 52 | return; 53 | } 54 | 55 | // See if we are disassembling the instructions as they are ran 56 | if (cpu->disasAsExec == true) 57 | { 58 | disass(cpu, cpu->pc); 59 | } 60 | 61 | // Here is a switch statement which maps specific op codes to their respective functionallity 62 | 63 | switch (op) 64 | { 65 | // nop 66 | case 0x00: 67 | break; 68 | 69 | // lxi b, xx 70 | case 0x01: 71 | lxi(cpu, (&cpu->b), (&cpu->c)); 72 | break; 73 | 74 | // stax b 75 | case 0x02: 76 | stax(cpu, cpu->b, cpu->c); 77 | break; 78 | 79 | // inx b 80 | case 0x03: 81 | inx8((&cpu->b), (&cpu->c)); 82 | break; 83 | 84 | // inr b 85 | case 0x04: 86 | inr(cpu, &cpu->b); 87 | break; 88 | 89 | // dcr b 90 | case 0x05: 91 | dcr(cpu, &(cpu->b)); 92 | break; 93 | 94 | // mvi b, x 95 | case 0x06: 96 | mvi(cpu, &(cpu->b), cpu->memory[cpu->pc + 1]); 97 | break; 98 | 99 | // rlc 100 | case 0x07: 101 | x = ((cpu->a & 0x80) >> 7); 102 | cpu->carry = (x); 103 | cpu->a = (cpu->a << 1); 104 | cpu->a = (cpu->a | x); 105 | break; 106 | 107 | // dad b 108 | case 0x09: 109 | dad(cpu, (&cpu->b), (&cpu->c)); 110 | break; 111 | 112 | // ldax b 113 | case 0x0a: 114 | ldax(cpu, cpu->b, cpu->c); 115 | break; 116 | 117 | // dcx b 118 | case 0x0b: 119 | dcx8((&cpu->b), (&cpu->c)); 120 | break; 121 | 122 | // inr c 123 | case 0x0c: 124 | inr(cpu, &(cpu->c)); 125 | break; 126 | 127 | // dcr c 128 | case 0x0d: 129 | dcr(cpu, &(cpu->c)); 130 | break; 131 | 132 | // mvi c, x 133 | case 0x0e: 134 | mvi(cpu, &(cpu->c), cpu->memory[cpu->pc + 1]); 135 | break; 136 | 137 | 138 | // rrc 139 | case 0x0f: 140 | x = (cpu->a & 0x1); 141 | cpu->carry = x; 142 | cpu->a = (cpu->a >> 1); 143 | cpu->a = (cpu->a | (x << 7)); 144 | break; 145 | 146 | 147 | // lxi d, xx 148 | case 0x11: 149 | lxi(cpu, (&cpu->d), (&cpu->e)); 150 | break; 151 | 152 | // stax d 153 | case 0x12: 154 | stax(cpu, cpu->d, cpu->e); 155 | break; 156 | 157 | // inx d 158 | case 0x13: 159 | inx8((&cpu->d), (&cpu->e)); 160 | break; 161 | 162 | // inr d 163 | case 0x14: 164 | inr(cpu, &(cpu->d)); 165 | break; 166 | 167 | // dcr d 168 | case 0x15: 169 | dcr(cpu, &(cpu->d)); 170 | break; 171 | 172 | // mvi d, x 173 | case 0x16: 174 | mvi(cpu, &(cpu->d), cpu->memory[cpu->pc + 1]); 175 | break; 176 | 177 | // ral 178 | case 0x17: 179 | x = (cpu->a & 0x80) >> 7; 180 | y = (int)cpu->carry; 181 | cpu->carry = (x); 182 | cpu->a = (cpu->a << 1); 183 | cpu->a = cpu->a & 0xfe; 184 | cpu->a = cpu->a | (y); 185 | break; 186 | 187 | // dad d 188 | case 0x19: 189 | dad(cpu, (&cpu->d), (&cpu->e)); 190 | break; 191 | 192 | // ldax d 193 | case 0x1a: 194 | ldax(cpu, cpu->d, cpu->e); 195 | break; 196 | 197 | // dcx d 198 | case 0x1b: 199 | dcx8((&cpu->d), (&cpu->e)); 200 | break; 201 | 202 | // inr e 203 | case 0x1c: 204 | inr(cpu, &(cpu->e)); 205 | break; 206 | 207 | // dcr e 208 | case 0x1d: 209 | dcr(cpu, &(cpu->e)); 210 | break; 211 | 212 | // mvi e, x 213 | case 0x1e: 214 | mvi(cpu, &(cpu->e), cpu->memory[cpu->pc + 1]); 215 | break; 216 | 217 | // rar 218 | case 0x1f: 219 | x = cpu->a & 0x01; 220 | y = (int)cpu->carry; 221 | cpu->carry = x; 222 | cpu->a = (cpu->a >> 1); 223 | cpu->a = cpu->a & 0x7f; 224 | cpu->a = cpu->a | (y << 7); 225 | break; 226 | 227 | 228 | // lxi h, xx 229 | case 0x21: 230 | lxi(cpu, (&cpu->h), (&cpu->l)); 231 | break; 232 | 233 | // shld xx 234 | case 0x22: 235 | cpu->memory[uintConvert(cpu->memory[cpu->pc + 1], cpu->memory[cpu->pc + 2])] = cpu->l; 236 | cpu->memory[uintConvert(cpu->memory[cpu->pc + 1], cpu->memory[cpu->pc + 2]) + 1] = cpu->h; 237 | cpu->pc += 2; 238 | break; 239 | 240 | // inx h 241 | case 0x23: 242 | inx8((&cpu->h), (&cpu->l)); 243 | break; 244 | 245 | // inr h 246 | case 0x24: 247 | inr(cpu, &(cpu->h)); 248 | break; 249 | 250 | // dcr h 251 | case 0x25: 252 | dcr(cpu, &(cpu->h)); 253 | break; 254 | 255 | // mvi h, x 256 | case 0x26: 257 | mvi(cpu, &(cpu->h), cpu->memory[cpu->pc + 1]); 258 | break; 259 | 260 | // daa 261 | case 0x27: 262 | x = cpu->a; 263 | if ((x & 0xf) > 9 || cpu->aux == true) 264 | { 265 | x = cpu->a += 6; 266 | cpu->a += x; 267 | auxiliaryFlag(cpu, (cpu->a & 0xf), 6, 1); 268 | } 269 | if ((x >> 4) > 9 || cpu->carry == true) 270 | { 271 | y = (x >> 4) + 6; 272 | x = x & 0xf; 273 | x = x | y; 274 | cpu->a = x; 275 | auxiliaryFlag(cpu, (cpu->a & 0xf0), 6, 1); 276 | } 277 | zeroFlag(cpu, x); 278 | signFlag(cpu, x); 279 | parityFlag(cpu, x); 280 | carryFlag(cpu, x); 281 | break; 282 | 283 | // dad h 284 | case 0x29: 285 | dad(cpu, (&cpu->h), (&cpu->l)); 286 | break; 287 | 288 | // lhld xx 289 | case 0x2a: 290 | cpu->l = cpu->memory[uintConvert(cpu->memory[cpu->pc + 1], cpu->memory[cpu->pc + 2])]; 291 | cpu->h = cpu->memory[(uintConvert(cpu->memory[cpu->pc + 1], cpu->memory[cpu->pc + 2])) + 1]; 292 | cpu->pc += 2; 293 | break; 294 | 295 | // dcx h 296 | case 0x2b: 297 | dcx8((&cpu->h), (&cpu->l)); 298 | break; 299 | 300 | // inr l 301 | case 0x2c: 302 | inr(cpu, &(cpu->l)); 303 | break; 304 | 305 | // dcr l 306 | case 0x2d: 307 | dcr(cpu, &(cpu->l)); 308 | break; 309 | 310 | // mvi l, x 311 | case 0x2e: 312 | mvi(cpu, &(cpu->l), cpu->memory[cpu->pc + 1]); 313 | break; 314 | 315 | // cma 316 | case 0x2f: 317 | cpu->a = ~(cpu->a); 318 | break; 319 | 320 | // lxi sp xx 321 | case 0x31: 322 | lxi16(cpu, (&cpu->sp)); 323 | break; 324 | 325 | // sta xx 326 | case 0x32: 327 | cpu->memory[uintConvert(cpu->memory[cpu->pc + 1], cpu->memory[cpu->pc + 2])] = cpu->a; 328 | cpu->pc += 2; 329 | break; 330 | 331 | // inx sp 332 | case 0x33: 333 | inx16(&cpu->sp); 334 | break; 335 | 336 | // inr m 337 | case 0x34: 338 | inr(cpu, &(cpu->memory[uintConvert(cpu->h, cpu->l)])); 339 | break; 340 | 341 | // dcr m 342 | case 0x35: 343 | dcr(cpu, &(cpu->memory[uintConvert(cpu->h, cpu->l)])); 344 | break; 345 | 346 | // mvi m, x 347 | case 0x36: 348 | mvi(cpu, &(cpu->memory[uintConvert(cpu->h, cpu->l)]), cpu->memory[cpu->pc + 1]); 349 | break; 350 | 351 | // stc 352 | case 0x37: 353 | cpu->carry = true; 354 | 355 | // dad sp 356 | case 0x39: 357 | dad16(cpu, (&cpu->sp)); 358 | break; 359 | 360 | // lda xx 361 | case 0x3a: 362 | cpu->a = cpu->memory[uintConvert(cpu->memory[cpu->pc + 1], cpu->memory[cpu->pc + 2])]; 363 | cpu->pc += 2; 364 | break; 365 | 366 | // dcx sp 367 | case 0x3b: 368 | dcx16(&cpu->sp); 369 | break; 370 | 371 | // inr a 372 | case 0x3c: 373 | inr(cpu, &(cpu->a)); 374 | break; 375 | 376 | // dcr a 377 | case 0x3d: 378 | dcr(cpu, &(cpu->a)); 379 | break; 380 | 381 | // mvi a, x 382 | case 0x3e: 383 | mvi(cpu, &(cpu->a), cpu->memory[cpu->pc + 1]); 384 | break; 385 | 386 | // cmc 387 | case 0x3f: 388 | cpu->carry = ~(cpu->carry); 389 | break; 390 | 391 | // mov b, b 392 | case 0x40: 393 | cpu->b = cpu->b; 394 | break; 395 | 396 | // mov b, c 397 | case 0x41: 398 | cpu->b = cpu->c; 399 | break; 400 | 401 | // mov b, d 402 | case 0x42: 403 | cpu->b = cpu->d; 404 | break; 405 | 406 | // mov b, e 407 | case 0x43: 408 | cpu->b = cpu->e; 409 | break; 410 | 411 | // mov b, h 412 | case 0x44: 413 | cpu->b = cpu->h; 414 | break; 415 | 416 | // mov b, l 417 | case 0x45: 418 | cpu->b = cpu->l; 419 | break; 420 | 421 | // mov b, m 422 | case 0x46: 423 | cpu->b = cpu->memory[uintConvert(cpu->h, cpu->l)]; 424 | break; 425 | 426 | // mov b, a 427 | case 0x47: 428 | cpu->b = cpu->a; 429 | break; 430 | 431 | // mov c, b 432 | case 0x48: 433 | cpu->c = cpu->b; 434 | break; 435 | 436 | // mov c, c 437 | case 0x49: 438 | cpu->c = cpu->c; 439 | break; 440 | 441 | // mov c, d 442 | case 0x4a: 443 | cpu->c = cpu->d; 444 | break; 445 | 446 | // mov c, e 447 | case 0x4b: 448 | cpu->c = cpu->e; 449 | break; 450 | 451 | // mov c, h 452 | case 0x4c: 453 | cpu->c = cpu->h; 454 | break; 455 | 456 | // mov c, l 457 | case 0x4d: 458 | cpu->c = cpu->l; 459 | break; 460 | 461 | // mov c, m 462 | case 0x4e: 463 | cpu->c = cpu->memory[uintConvert(cpu->h, cpu->l)]; 464 | break; 465 | 466 | // mov c, a 467 | case 0x4f: 468 | cpu->c = cpu->a; 469 | break; 470 | 471 | // mov d, b 472 | case 0x50: 473 | cpu->d = cpu->b; 474 | break; 475 | 476 | // mov d, c 477 | case 0x51: 478 | cpu->d = cpu->c; 479 | break; 480 | 481 | // mov d, d 482 | case 0x52: 483 | cpu->d = cpu->d; 484 | break; 485 | 486 | // mov d, e 487 | case 0x53: 488 | cpu->d = cpu->e; 489 | break; 490 | 491 | // mov d, h 492 | case 0x54: 493 | cpu->d = cpu->h; 494 | break; 495 | 496 | // mov d, l 497 | case 0x55: 498 | cpu->d = cpu->l; 499 | break; 500 | 501 | // mov d, m 502 | case 0x56: 503 | cpu->d = cpu->memory[uintConvert(cpu->h, cpu->l)]; 504 | break; 505 | 506 | // mov d, a 507 | case 0x57: 508 | cpu->d = cpu->a; 509 | break; 510 | 511 | // mov e, b 512 | case 0x58: 513 | cpu->e = cpu->b; 514 | break; 515 | 516 | // mov e, c 517 | case 0x59: 518 | cpu->e = cpu->c; 519 | break; 520 | 521 | // mov e, d 522 | case 0x5a: 523 | cpu->e = cpu->d; 524 | break; 525 | 526 | // mov e, e 527 | case 0x5b: 528 | cpu->e = cpu->e; 529 | break; 530 | 531 | // mov e, h 532 | case 0x5c: 533 | cpu->e = cpu->h; 534 | break; 535 | 536 | // mov e, l 537 | case 0x5d: 538 | cpu->e = cpu->l; 539 | break; 540 | 541 | // mov e, m 542 | case 0x5e: 543 | cpu->e = cpu->memory[uintConvert(cpu->h, cpu->l)]; 544 | break; 545 | 546 | // mov e, a 547 | case 0x5f: 548 | cpu->e = cpu->a; 549 | break; 550 | 551 | // mov h, b 552 | case 0x60: 553 | cpu->h = cpu->b; 554 | break; 555 | 556 | // mov h, c 557 | case 0x61: 558 | cpu->h = cpu->c; 559 | break; 560 | 561 | // mov h, d 562 | case 0x62: 563 | cpu->h = cpu->d; 564 | break; 565 | 566 | // mov h, e 567 | case 0x63: 568 | cpu->h = cpu->e; 569 | break; 570 | 571 | // mov h, h 572 | case 0x64: 573 | cpu->h = cpu->h; 574 | break; 575 | 576 | // mov h, l 577 | case 0x65: 578 | cpu->h = cpu->l; 579 | break; 580 | 581 | // mov h, m 582 | case 0x66: 583 | cpu->h = cpu->memory[uintConvert(cpu->h, cpu->l)]; 584 | break; 585 | 586 | // mov h, a 587 | case 0x67: 588 | cpu->h = cpu->a; 589 | break; 590 | 591 | // mov l, b 592 | case 0x68: 593 | cpu->l = cpu->b; 594 | break; 595 | 596 | // mov l, c 597 | case 0x69: 598 | cpu->l = cpu->c; 599 | break; 600 | 601 | // mov l, d 602 | case 0x6a: 603 | cpu->l = cpu->d; 604 | break; 605 | 606 | // mov l, e 607 | case 0x6b: 608 | cpu->l = cpu->e; 609 | break; 610 | 611 | // mov l, h 612 | case 0x6c: 613 | cpu->l = cpu->h; 614 | break; 615 | 616 | // mov l, l 617 | case 0x6d: 618 | cpu->l = cpu->l; 619 | break; 620 | 621 | // mov l, m 622 | case 0x6e: 623 | cpu->l = cpu->memory[uintConvert(cpu->h, cpu->l)]; 624 | break; 625 | 626 | // mov l, a 627 | case 0x6f: 628 | cpu->l = cpu->a; 629 | break; 630 | 631 | // mov m, b 632 | case 0x70: 633 | cpu->memory[uintConvert(cpu->h, cpu->l)] = cpu->b; 634 | break; 635 | 636 | // mov m, c 637 | case 0x71: 638 | cpu->memory[uintConvert(cpu->h, cpu->l)] = cpu->c; 639 | break; 640 | 641 | // mov m, d 642 | case 0x72: 643 | cpu->memory[uintConvert(cpu->h, cpu->l)] = cpu->d; 644 | break; 645 | 646 | // mov m, e 647 | case 0x73: 648 | cpu->memory[uintConvert(cpu->h, cpu->l)] = cpu->e; 649 | break; 650 | 651 | // mov m, h 652 | case 0x74: 653 | cpu->memory[uintConvert(cpu->h, cpu->l)] = cpu->h; 654 | break; 655 | 656 | // mov m, l 657 | case 0x75: 658 | cpu->memory[uintConvert(cpu->h, cpu->l)] = cpu->l; 659 | break; 660 | 661 | // hlt I don't have interrupts implemented, so it's just a NOP 662 | case 0x76: 663 | break; 664 | 665 | // mov m, a 666 | case 0x77: 667 | cpu->memory[uintConvert(cpu->h, cpu->l)] = cpu->a; 668 | break; 669 | 670 | // mov a, b 671 | case 0x78: 672 | cpu->a = cpu->b; 673 | break; 674 | 675 | // mov a, c 676 | case 0x79: 677 | cpu->a = cpu->c; 678 | break; 679 | 680 | // mov a, d 681 | case 0x7a: 682 | cpu->a = cpu->d; 683 | break; 684 | 685 | // mov a, e 686 | case 0x7b: 687 | cpu->a = cpu->e; 688 | break; 689 | 690 | // mov a, h 691 | case 0x7c: 692 | cpu->a = cpu->h; 693 | break; 694 | 695 | // mov a, l 696 | case 0x7d: 697 | cpu->a = cpu->l; 698 | break; 699 | 700 | // mov a, m 701 | case 0x7e: 702 | cpu->a = cpu->memory[uintConvert(cpu->h, cpu->l)]; 703 | break; 704 | 705 | // mov a, a 706 | case 0x7f: 707 | cpu->a = cpu->a; 708 | break; 709 | 710 | // add b 711 | case 0x80: 712 | add(cpu, cpu->b); 713 | break; 714 | 715 | // add c 716 | case 0x81: 717 | add(cpu, cpu->c); 718 | break; 719 | 720 | // add d 721 | case 0x82: 722 | add(cpu, cpu->d); 723 | break; 724 | 725 | // add e 726 | case 0x83: 727 | add(cpu, cpu->e); 728 | break; 729 | 730 | // add h 731 | case 0x84: 732 | add(cpu, cpu->h); 733 | break; 734 | 735 | // add l 736 | case 0x85: 737 | add(cpu, cpu->l); 738 | break; 739 | 740 | // add m 741 | case 0x86: 742 | add(cpu, cpu->memory[uintConvert(cpu->h, cpu->l)]); 743 | break; 744 | 745 | // add a 746 | case 0x87: 747 | add(cpu, cpu->a); 748 | break; 749 | 750 | // adc b 751 | case 0x88: 752 | adc(cpu, cpu->b); 753 | break; 754 | 755 | // adc c 756 | case 0x89: 757 | adc(cpu, cpu->c); 758 | break; 759 | 760 | // adc d 761 | case 0x8a: 762 | adc(cpu, cpu->d); 763 | break; 764 | 765 | // adc e 766 | case 0x8b: 767 | adc(cpu, cpu->e); 768 | break; 769 | 770 | // adc h 771 | case 0x8c: 772 | adc(cpu, cpu->h); 773 | break; 774 | 775 | // adc l 776 | case 0x8d: 777 | adc(cpu, cpu->l); 778 | break; 779 | 780 | // adc m 781 | case 0x8e: 782 | adc(cpu, cpu->memory[(int)uintConvert(cpu->h, cpu->l)]); 783 | break; 784 | 785 | // adc a 786 | case 0x8f: 787 | adc(cpu, cpu->a); 788 | break; 789 | 790 | // sub b 791 | case 0x90: 792 | sub(cpu, cpu->b); 793 | break; 794 | 795 | // sub c 796 | case 0x91: 797 | sub(cpu, cpu->c); 798 | break; 799 | 800 | // sub d 801 | case 0x92: 802 | sub(cpu, cpu->d); 803 | break; 804 | 805 | // sub e 806 | case 0x93: 807 | sub(cpu, cpu->e); 808 | break; 809 | 810 | // sub h 811 | case 0x94: 812 | sub(cpu, cpu->h); 813 | break; 814 | 815 | // sub l 816 | case 0x95: 817 | sub(cpu, cpu->l); 818 | break; 819 | 820 | // sub m 821 | case 0x96: 822 | sub(cpu, cpu->memory[uintConvert(cpu->h, cpu->l)]); 823 | break; 824 | 825 | // sub a 826 | case 0x97: 827 | sub(cpu, cpu->a); 828 | break; 829 | 830 | // sbb b 831 | case 0x98: 832 | sbb(cpu, cpu->b); 833 | break; 834 | 835 | // sbb c 836 | case 0x99: 837 | sbb(cpu, cpu->c); 838 | break; 839 | 840 | // sbb d 841 | case 0x9a: 842 | sbb(cpu, cpu->d); 843 | break; 844 | 845 | // sbb e 846 | case 0x9b: 847 | sbb(cpu, cpu->e); 848 | break; 849 | 850 | // sbb h 851 | case 0x9c: 852 | sbb(cpu, cpu->h); 853 | break; 854 | 855 | // sbb l 856 | case 0x9d: 857 | sbb(cpu, cpu->l); 858 | break; 859 | 860 | // sbb m 861 | case 0x9e: 862 | sbb(cpu, cpu->memory[uintConvert(cpu->h, cpu->l)]); 863 | break; 864 | 865 | // sbb a 866 | case 0x9f: 867 | sbb(cpu, cpu->a); 868 | break; 869 | 870 | // ana b 871 | case 0xa0: 872 | and(cpu, cpu->b); 873 | break; 874 | 875 | // ana c 876 | case 0xa1: 877 | and(cpu, cpu->c); 878 | break; 879 | 880 | // ana d 881 | case 0xa2: 882 | and(cpu, cpu->d); 883 | break; 884 | 885 | // ana e 886 | case 0xa3: 887 | and(cpu, cpu->e); 888 | break; 889 | 890 | // ana h 891 | case 0xa4: 892 | and(cpu, cpu->h); 893 | break; 894 | 895 | // ana l 896 | case 0xa5: 897 | and(cpu, cpu->l); 898 | break; 899 | 900 | // ana m 901 | case 0xa6: 902 | and(cpu, cpu->memory[uintConvert(cpu->h, cpu->l)]); 903 | break; 904 | 905 | // ana a 906 | case 0xa7: 907 | and(cpu, cpu->a); 908 | break; 909 | 910 | // xra b 911 | case 0xa8: 912 | xor(cpu, cpu->b); 913 | break; 914 | 915 | // xra c 916 | case 0xa9: 917 | xor(cpu, cpu->c); 918 | break; 919 | 920 | // xra d 921 | case 0xaa: 922 | xor(cpu, cpu->d); 923 | break; 924 | 925 | // xra e 926 | case 0xab: 927 | xor(cpu, cpu->e); 928 | break; 929 | 930 | // xra h 931 | case 0xac: 932 | xor(cpu, cpu->h); 933 | break; 934 | 935 | // xra l 936 | case 0xad: 937 | xor(cpu, cpu->l); 938 | break; 939 | 940 | // xra m 941 | case 0xae: 942 | xor(cpu, cpu->memory[uintConvert(cpu->h, cpu->l)]); 943 | break; 944 | 945 | // xra a 946 | case 0xaf: 947 | xor(cpu, cpu->a); 948 | break; 949 | 950 | // ora b 951 | case 0xb0: 952 | or(cpu, cpu->b); 953 | break; 954 | 955 | // ora c 956 | case 0xb1: 957 | or(cpu, cpu->c); 958 | break; 959 | 960 | // ora d 961 | case 0xb2: 962 | or(cpu, cpu->d); 963 | break; 964 | 965 | // ora e 966 | case 0xb3: 967 | or(cpu, cpu->e); 968 | break; 969 | 970 | // ora h 971 | case 0xb4: 972 | or(cpu, cpu->h); 973 | break; 974 | 975 | // ora l 976 | case 0xb5: 977 | or(cpu, cpu->l); 978 | break; 979 | 980 | // ora m 981 | case 0xb6: 982 | or(cpu, cpu->memory[uintConvert(cpu->h, cpu->l)]); 983 | break; 984 | 985 | // ora a 986 | case 0xb7: 987 | or(cpu, cpu->a); 988 | break; 989 | 990 | // cmp b 991 | case 0xb8: 992 | cmp(cpu, cpu->b); 993 | break; 994 | 995 | // cmp c 996 | case 0xb9: 997 | cmp(cpu, cpu->c); 998 | break; 999 | 1000 | // cmp d 1001 | case 0xba: 1002 | cmp(cpu, cpu->d); 1003 | break; 1004 | 1005 | // cmp e 1006 | case 0xbb: 1007 | cmp(cpu, cpu->e); 1008 | break; 1009 | 1010 | // cmp h 1011 | case 0xbc: 1012 | cmp(cpu, cpu->h); 1013 | break; 1014 | 1015 | // cmp l 1016 | case 0xbd: 1017 | cmp(cpu, cpu->l); 1018 | break; 1019 | 1020 | // cmp m 1021 | case 0xbe: 1022 | cmp(cpu, cpu->memory[uintConvert(cpu->h, cpu->l)]); 1023 | break; 1024 | 1025 | // cmp a 1026 | case 0xbf: 1027 | cmp(cpu, cpu->a); 1028 | break; 1029 | 1030 | // rnz 1031 | case 0xc0: 1032 | if (cpu->zero == 0) 1033 | { 1034 | ret(cpu); 1035 | } 1036 | break; 1037 | 1038 | // pop b 1039 | case 0xc1: 1040 | pop(cpu, &cpu->b, &cpu->c); 1041 | break; 1042 | 1043 | // jnz xx 1044 | case 0xc2: 1045 | if (cpu->zero == 0) 1046 | { 1047 | jmp(cpu, (uint8_t)cpu->memory[cpu->pc + 1], (uint8_t)cpu->memory[cpu->pc + 2]); 1048 | } 1049 | else 1050 | { 1051 | cpu->pc += 2; 1052 | } 1053 | break; 1054 | 1055 | // jmp xx 1056 | case 0xc3: 1057 | jmp(cpu, (uint8_t)cpu->memory[cpu->pc + 1], (uint8_t)cpu->memory[cpu->pc + 2]); 1058 | break; 1059 | 1060 | // cnz xx 1061 | case 0xc4: 1062 | if (cpu->zero == 0) 1063 | { 1064 | call(cpu, cpu->memory[cpu->pc + 1], cpu->memory[cpu->pc + 2]); 1065 | } 1066 | else 1067 | { 1068 | cpu->pc += 2; 1069 | } 1070 | break; 1071 | 1072 | // push b 1073 | case 0xc5: 1074 | push(cpu, cpu->b, cpu->c); 1075 | break; 1076 | 1077 | // adi n 1078 | case 0xc6: 1079 | add(cpu, cpu->memory[cpu->pc + 1]); 1080 | cpu->pc += 1; 1081 | break; 1082 | 1083 | // rst 0 1084 | case 0xc7: 1085 | rst(cpu, (uint8_t)0x0000); 1086 | break; 1087 | 1088 | // rz 1089 | case 0xc8: 1090 | if (cpu->zero == 1) 1091 | { 1092 | ret(cpu); 1093 | } 1094 | break; 1095 | 1096 | // ret 1097 | case 0xc9: 1098 | ret(cpu); 1099 | break; 1100 | 1101 | // jz xx 1102 | case 0xca: 1103 | if (cpu->zero == 1) 1104 | { 1105 | jmp(cpu, cpu->memory[cpu->pc + 1], cpu->memory[cpu->pc + 2]); 1106 | } 1107 | else 1108 | { 1109 | cpu->pc += 2; 1110 | } 1111 | break; 1112 | 1113 | // cz xx 1114 | case 0xcc: 1115 | if (cpu->zero == 1) 1116 | { 1117 | call(cpu, cpu->memory[cpu->pc + 1], cpu->memory[cpu->pc + 2]); 1118 | } 1119 | else 1120 | { 1121 | cpu->pc += 2; 1122 | } 1123 | break; 1124 | 1125 | // call xx 1126 | case 0xcd: 1127 | call(cpu, cpu->memory[cpu->pc + 1], cpu->memory[cpu->pc + 2]); 1128 | break; 1129 | 1130 | // aci x 1131 | case 0xce: 1132 | adc(cpu, cpu->memory[cpu->pc + 1]); 1133 | cpu->pc += 1; 1134 | break; 1135 | 1136 | 1137 | // rst 1 1138 | case 0xcf: 1139 | rst(cpu, 0x8); 1140 | break; 1141 | 1142 | 1143 | // rnc 1144 | case 0xd0: 1145 | if (cpu->carry == 0) 1146 | { 1147 | ret(cpu); 1148 | } 1149 | break; 1150 | 1151 | // pop d 1152 | case 0xd1: 1153 | pop(cpu, &cpu->d, &cpu->e); 1154 | break; 1155 | 1156 | // jnc xx 1157 | case 0xd2: 1158 | if (cpu->carry == 0) 1159 | { 1160 | jmp(cpu, (uint8_t)cpu->memory[cpu->pc + 1], (uint8_t)cpu->memory[cpu->pc + 2]); 1161 | } 1162 | else 1163 | { 1164 | cpu->pc += 2; 1165 | } 1166 | break; 1167 | 1168 | // out x, I haven't implemented other hardware devices so this is essentially a NOP with an arg 1169 | case 0xd3: 1170 | cpu->pc += 1; 1171 | break; 1172 | 1173 | // cnc xx 1174 | case 0xd4: 1175 | if (cpu->carry == 0) 1176 | { 1177 | call(cpu, cpu->memory[cpu->pc + 1], cpu->memory[cpu->pc + 2]); 1178 | } 1179 | else 1180 | { 1181 | cpu->pc += 2; 1182 | } 1183 | break; 1184 | 1185 | // push d 1186 | case 0xd5: 1187 | push(cpu, cpu->d, cpu->e); 1188 | break; 1189 | 1190 | // sui x 1191 | case 0xd6: 1192 | sub(cpu, cpu->memory[cpu->pc + 1]); 1193 | cpu->pc += 1; 1194 | break; 1195 | 1196 | // rst 2 1197 | case 0xd7: 1198 | rst(cpu, (uint8_t)0x0010); 1199 | break; 1200 | 1201 | // rc 1202 | case 0xd8: 1203 | if (cpu->carry == 1) 1204 | { 1205 | ret(cpu); 1206 | } 1207 | break; 1208 | 1209 | // jc xx 1210 | case 0xda: 1211 | if (cpu->zero == 1) 1212 | { 1213 | jmp(cpu, cpu->memory[cpu->pc + 1], cpu->memory[cpu->pc + 2]); 1214 | } 1215 | else 1216 | { 1217 | cpu->pc += 2; 1218 | } 1219 | break; 1220 | 1221 | // in x, I haven't implemented other hardware devices so this is essentially a NOP with an arg 1222 | case 0xdb: 1223 | cpu->pc += 1; 1224 | break; 1225 | 1226 | // cc xx 1227 | case 0xdc: 1228 | if (cpu->carry == 1) 1229 | { 1230 | call(cpu, cpu->memory[cpu->pc + 1], cpu->memory[cpu->pc + 2]); 1231 | } 1232 | else 1233 | { 1234 | cpu->pc += 2; 1235 | } 1236 | break; 1237 | 1238 | 1239 | // sbi x 1240 | case 0xde: 1241 | sbb(cpu, cpu->memory[cpu->pc + 1]); 1242 | cpu->pc += 1; 1243 | break; 1244 | 1245 | // End Of Assembly : This insturction is to signify the end, with an arg of 0x66 meaning to end the code 1246 | case 0xdd: 1247 | x = cpu->memory[cpu->pc + 1]; 1248 | switch (x) 1249 | { 1250 | case 0x66: 1251 | running = 0; 1252 | resetExecution(cpu); 1253 | break; 1254 | } 1255 | break; 1256 | 1257 | 1258 | 1259 | // rst 3 1260 | case 0xdf: 1261 | rst(cpu, 0x18); 1262 | break; 1263 | 1264 | 1265 | // rpo 1266 | case 0xe0: 1267 | if (cpu->parity == 0) 1268 | { 1269 | ret(cpu); 1270 | } 1271 | break; 1272 | 1273 | // pop h 1274 | case 0xe1: 1275 | pop(cpu, &cpu->h, &cpu->l); 1276 | break; 1277 | 1278 | // jpo xx 1279 | case 0xe2: 1280 | if (cpu->parity == 0) 1281 | { 1282 | jmp(cpu, (uint8_t)cpu->memory[cpu->pc + 1], (uint8_t)cpu->memory[cpu->pc + 2]); 1283 | } 1284 | else 1285 | { 1286 | cpu->pc += 2; 1287 | } 1288 | break; 1289 | 1290 | // xthl 1291 | case 0xe3: 1292 | x = cpu->l; 1293 | y = cpu->h; 1294 | cpu->l = cpu->memory[cpu->sp]; 1295 | cpu->h = cpu->memory[cpu->sp + 1]; 1296 | cpu->memory[cpu->sp] = x; 1297 | cpu->memory[cpu->sp + 1] = y; 1298 | break; 1299 | 1300 | // cpo xx 1301 | case 0xe4: 1302 | if (cpu->parity == 0) 1303 | { 1304 | call(cpu, cpu->memory[cpu->pc + 1], cpu->memory[cpu->pc + 2]); 1305 | } 1306 | else 1307 | { 1308 | cpu->pc += 2; 1309 | } 1310 | break; 1311 | 1312 | // push h 1313 | case 0xe5: 1314 | push(cpu, cpu->h, cpu->l); 1315 | break; 1316 | 1317 | // ani x 1318 | case 0xe6: 1319 | and(cpu, cpu->memory[cpu->pc + 1]); 1320 | cpu->pc += 1; 1321 | break; 1322 | 1323 | // rst 4 1324 | case 0xe7: 1325 | rst(cpu, (uint8_t)0x0020); 1326 | break; 1327 | 1328 | // rpe 1329 | case 0xe8: 1330 | if (cpu->parity == 1) 1331 | { 1332 | ret(cpu); 1333 | } 1334 | break; 1335 | 1336 | // pchl 1337 | case 0xe9: 1338 | x = cpu->h; 1339 | x = (x << 8); 1340 | x = (x | cpu->l); 1341 | cpu->pc = (x - 1); 1342 | break; 1343 | 1344 | // jpe xx 1345 | case 0xea: 1346 | if (cpu->parity == 1) 1347 | { 1348 | jmp(cpu, cpu->memory[cpu->pc + 1], cpu->memory[cpu->pc + 2]); 1349 | } 1350 | else 1351 | { 1352 | cpu->pc += 2; 1353 | } 1354 | break; 1355 | 1356 | // xchg 1357 | case 0xeb: 1358 | x = cpu->d; 1359 | y = cpu->e; 1360 | cpu->d = cpu->h; 1361 | cpu->e = cpu->l; 1362 | cpu->h = x; 1363 | cpu->l = y; 1364 | break; 1365 | 1366 | // cpe xx 1367 | case 0xec: 1368 | if (cpu->parity == 1) 1369 | { 1370 | call(cpu, cpu->memory[cpu->pc + 1], cpu->memory[cpu->pc + 2]); 1371 | } 1372 | else 1373 | { 1374 | cpu->pc += 2; 1375 | } 1376 | break; 1377 | 1378 | 1379 | // xri x 1380 | case 0xee: 1381 | xor(cpu, cpu->memory[cpu->pc + 1]); 1382 | cpu->pc += 1; 1383 | break; 1384 | 1385 | 1386 | // rst 5 1387 | case 0xef: 1388 | rst(cpu, 0x28); 1389 | break; 1390 | 1391 | // rp 1392 | case 0xf0: 1393 | if (cpu->sign == 0) 1394 | { 1395 | ret(cpu); 1396 | } 1397 | break; 1398 | 1399 | // pop psw 1400 | case 0xf1: 1401 | popPsw(cpu); 1402 | break; 1403 | 1404 | // jp xx 1405 | case 0xf2: 1406 | if (cpu->sign == 0) 1407 | { 1408 | jmp(cpu, (uint8_t)cpu->memory[cpu->pc + 1], (uint8_t)cpu->memory[cpu->pc + 2]); 1409 | } 1410 | else 1411 | { 1412 | cpu->pc += 2; 1413 | } 1414 | break; 1415 | 1416 | // di 1417 | case 0xf3: 1418 | cpu->allowInterrupt = 0; 1419 | break; 1420 | 1421 | // cp xx 1422 | case 0xf4: 1423 | if (cpu->sign == 0) 1424 | { 1425 | call(cpu, cpu->memory[cpu->pc + 1], cpu->memory[cpu->pc + 2]); 1426 | } 1427 | else 1428 | { 1429 | cpu->pc += 2; 1430 | } 1431 | break; 1432 | 1433 | // push psw 1434 | case 0xf5: 1435 | push(cpu, cpu->a, convertFlagsRegister(cpu)); 1436 | break; 1437 | 1438 | // ori x 1439 | case 0xf6: 1440 | or(cpu, cpu->memory[cpu->pc + 1]); 1441 | cpu->pc += 1; 1442 | break; 1443 | 1444 | // rst 6 1445 | case 0xf7: 1446 | rst(cpu, (uint8_t)0x0030); 1447 | break; 1448 | 1449 | // rm 1450 | case 0xf8: 1451 | if (cpu->sign == 1) 1452 | { 1453 | ret(cpu); 1454 | } 1455 | break; 1456 | 1457 | // sphl 1458 | case 0xf9: 1459 | x = cpu->h; 1460 | x = (x << 8); 1461 | x = (x | cpu->l); 1462 | cpu->sp = x; 1463 | break; 1464 | 1465 | // jm xx 1466 | case 0xfa: 1467 | if (cpu->sign == 1) 1468 | { 1469 | jmp(cpu, cpu->memory[cpu->pc + 1], cpu->memory[cpu->pc + 2]); 1470 | } 1471 | else 1472 | { 1473 | cpu->pc += 2; 1474 | } 1475 | break; 1476 | 1477 | // ei 1478 | case 0xfb: 1479 | cpu->allowInterrupt = 1; 1480 | break; 1481 | 1482 | // cm xx 1483 | case 0xfc: 1484 | if (cpu->sign == 1) 1485 | { 1486 | call(cpu, cpu->memory[cpu->pc + 1], cpu->memory[cpu->pc + 2]); 1487 | } 1488 | else 1489 | { 1490 | cpu->pc += 2; 1491 | } 1492 | break; 1493 | 1494 | 1495 | // cpi x 1496 | case 0xfe: 1497 | cmp(cpu, cpu->memory[cpu->pc + 1]); 1498 | cpu->pc += 1; 1499 | break; 1500 | 1501 | 1502 | // rst 7 1503 | case 0xff: 1504 | rst(cpu, 0x38); 1505 | break; 1506 | } 1507 | } 1508 | } --------------------------------------------------------------------------------