i still dont know what im doing

This commit is contained in:
Nero 2020-03-01 16:43:23 +00:00
parent 4847eb4d88
commit bc238a3bf9
19 changed files with 203 additions and 1099 deletions

8
.gitignore vendored
View File

@ -1,2 +1,8 @@
*.com
*.bs
*.0
*.lst
*.img
*.bin
scripts/
*.rom
/scripts

View File

@ -1,17 +1,81 @@
.PHONY: default
FLOPPY = 360
cp437.bin: src/cp437.bmp scripts/bmp2font
scripts/bmp2font $< $@
PROGRAMS = $(patsubst %.asm,%.com,$(wildcard com/*.asm))
DISTFILES = $(PROGRAMS)
ROMS =
vga11.bin: src/vga11.asm cp437.bin
nasm -o $@ $<
QEMU_ARCH = $(shell uname -m)
QEMU = qemu-system-$(QEMU_ARCH)
QEMU_ARGS = $(addprefix --option-rom ,$(ROMS))
forth.bin: src/forth.asm
nasm -o $@ $<
NASM = nasm
NASM_ARGS = -s -Ilib -Plib/nasmcomp.asm -w-macro-params
scripts/%: src/scripts/%.c
mkdir -p scripts
gcc -o $@ $<
EMUL = utils/emul
ifdef KVM
QEMU_ARGS += --enable-kvm
endif
ifdef DEBUG
ROMS += rom/debug.rom
NASM_ARGS += -l $(basename $@).lst
endif
ifndef DISPLAY
QEMU_ARGS += --display curses
endif
.PHONY: default bootstrap clean qemu-rom qemu-floppy qemu-pxe
default: fdimage.img
# Host utils
utils/%: src/utils/%.c
mkdir -p utils
$(CC) -o $@ $<
cp437.bin: src/cp437.bmp utils/bmp2font
utils/bmp2font $< $@
# BIOS option roms
rom/%.rom: rom/%.asm utils/fix-rom
$(NASM) $(NASM_ARGS) -o $@ $< && utils/fix-rom $@
# COM programs
%.com: %.asm
$(NASM) $(NASM_ARGS) -DCOM -DBASE=0x0100 -o $@ $<
# Bootloaders, first sector on partition
%.bs: %.asm
$(NASM) $(NASM_ARGS) -DBOOT -DBASE=0x7C00 -o $@ $<
: check boot signature
test "$$(echo $$(xxd -p -l 2 -s 510 pxe.bs))" == 55aa
# Network bootstrap protocol as used for PXE
%.0: %.asm
$(NASM) $(NASM_ARGS) -DNBP -DBASE=0x7C00 -o $@ $<
fdimage.img: boot/fat.bs $(BDOSIMG) $(BIOSIMG) $(DISTFILES)
mformat -R 9 -C -i $@ -f $(FLOPPY) -B boot/fat.bs ::
dd if=$(BDOSIMG) bs=512 seek=1 count=4 conv=notrunc of=$@
dd if=$(BIOSIMG) bs=512 seek=5 count=4 conv=notrunc of=$@
mcopy -i $@ $(DISTFILES) ::
hdimage.img: boot/mbr.bs fdimage.img
cat boot/mbr.bs fdimage.img >$@
clean:
rm -f *.bin scripts/*
rm -f *.com *.bs *.0 *.lst *.img *.bin *.rom
qemu-floppy: fdimage.img $(ROMS)
$(QEMU) $(QEMU_ARGS) -boot a -fda fdimage.img
qemu-hdd: hdimage.img $(ROMS)
$(QEMU) $(QEMU_ARGS) -boot c -hda hdimage.img
qemu-pxe: pxe.bs $(ROMS)
$(QEMU) $(QEMU_ARGS) -boot n \
-option-rom /usr/share/qemu/pxe-rtl8139.rom \
-device e1000,netdev=mynet0,mac=52:54:00:12:34:56 \
-netdev user,id=mynet0,net=192.168.76.0/24,dhcpstart=192.168.76.9,tftp=$(CURDIR),bootfile=pxe.bs

View File

@ -1,234 +0,0 @@
ORG BDOS
%include "hdr/bios.asm"
%include "hdr/fcb.asm"
%include "hdr/bpb.asm"
DISKBUF: EQU (BDOS-0x200) ; deblocking
DISKBPB: EQU (DISKBUF-21) ; BPB of the current driv
DISKDRV: EQU (DISKBPB-1) ; BYTE denoting drive of current fcb (1=A, ...)
PROGBX: EQU (DISKDRV-2)
STACK: EQU (PROGBX & 0xFFFE) ; even address, grows down
DEFDRV: EQU 4 ; default drive when opening a FCB (1=A, ...)
SYSCALL:
MOV [PROGBX], BX
XOR BH, BH
MOV BL, CL
ADD BX, BX
ADD BX, FUNCS
MOV BX, [BX]
PUSH BX
MOV BX, [PROGBX]
SYSRET:
RET
FUNCS:
DW SETUP,GETC,PUTC,SYSRET
DW SYSRET,SYSRET,SYSRET,SYSRET
DW SYSRET,PUTS,GETS,STATUS
DW SYSRET,DISKRST,SETDEFDSK,FCBOPEN
DW SYSRET,SYSRET,SYSRET,SYSRET
DW SYSRET,SYSRET,SYSRET,SYSRET
SETUP:
MOV SP, STACK
MOV BYTE [DEFDRV], 0x01
MOV CX, DISKBUF
CALL SETDMA
SUB SP, 0x20
MOV BX, SP
CALL FCBOPEN
CLI
HALT:
HLT
JMP HALT
GETC:
CALL CONIN
TEST AL, AL
JZ GETC
PUSH DX
MOV DL, AL
CALL CONOUT
POP DX
ret
PUTC:
JMP CONOUT
PUTS:
PUSH SI
MOV SI, DX
PUTS_L:
MOV DL, BYTE [SI]
CMP DL, '$'
JZ PUTS_E
CALL CONOUT
INC SI
JMP PUTS_L
PUTS_E:
POP SI
RET
; BX base ptr to buffer
; CH maximum BL
; CL minimum BL
GETS:
PUSH AX
PUSH CX
PUSH DX
PUSH BX
; BX is base pointer
MOV BX, DX
; CL is maximum, CH is current position
MOV CX, [BX]
XOR CH, CH
; BX starts at actual character area
ADD BX, 2
GETS_L:
; Read and maybe handle control chars
CALL GETC
CMP AL, 0x0D
JE GETS_E
CMP AL, 8
JE GETS_BS
; Store character
PUSH BX
ADD BL, CH
ADC BH, 0
MOV [BX], AL
POP BX
; Loop if we arent full yet
INC CH
CMP CH, CL
JC GETS_L
GETS_E:
; Append LF to CR
MOV DL, 0x0A
CALL PUTC
; Write back length data
SUB BX, 2
MOV [BX], CX
; Restore registers
POP BX
POP DX
POP CX
POP AX
ret
GETS_BS:
TEST CH, CH
JZ GETS_L
MOV DL, 0x20
CALL PUTC
MOV DL, 8
CALL PUTC
DEC CL
JMP GETS_L
STATUS:
JMP CONST
DISKRST:
MOV BYTE [DISKDRV], 0xFF
RET
SETDEFDSK:
MOV BYTE [DEFDRV], DL
RET
FCBOPEN:
MOV CL, BYTE [BX]
TEST CL, CL
JNZ NODEFDRV
MOV CL, BYTE [DEFDRV]
MOV BYTE [BX], CL
NODEFDRV:
CALL LOADBPB
MOV CX, [DISKBPB+BPB_RDE]
CALL FATSIZE
ADD DX, WORD [DISKBPB+BPB_RSC]
CALL SETLSEC
CALL READ
MOV AX, [DISKBUF]
INT3
; TODO: search for file in rootdir
; TODO: init cluster number
RET
; Set logical sector number
; IN DX sector number
SETLSEC:
PUSH AX
PUSH CX
PUSH DX
XOR AX, AX
XCHG AX, DX
DIV WORD [DISKBPB+BPB_SPT]
MOV CX, AX
CALL SETTRK
MOV CX, DX
INC CX
CALL SETSEC
POP DX
POP CX
POP AX
RET
; OUT DX number of sectors by all FATs
FATSIZE:
PUSH AX
MOV DL, BYTE [DISKBPB+BPB_FN]
MOV AL, BYTE [DISKBPB+BPB_SF]
MUL DL
XCHG AX, DX
POP AX
RET:
RET
; IN CL drive num, 1=A, 2=B, 3=C
LOADBPB:
CMP BYTE [DISKDRV], CL
JE RET
PUSH CX
DEC CL
CALL SELDSK
; first track
MOV CX, 0
CALL SETTRK
; first sector
MOV CX, 1
CALL SETSEC
; into default diskbuf
MOV CX, DISKBUF
CALL SETDMA
POP CX
CALL READ
JC DISKRST
; copy BPB
PUSH CX
PUSH SI
PUSH DI
MOV CX, 21
MOV SI, DISKBUF+0x0B
MOV DI, DISKBPB
REP MOVSB
POP DI
POP SI
POP CX
; store drive number
MOV BYTE [DISKDRV], CL
RET

View File

@ -1,218 +0,0 @@
ORG BIOS
CPU 8086
DISKCX: EQU 0x8
DISKDX: EQU 0xA
DISKBX: EQU 0xC
JMP NEAR BOOT
JMP NEAR WBOOT
JMP NEAR CONST
JMP NEAR CONIN
JMP NEAR CONOUT
JMP NEAR LIST
JMP NEAR PUNCH
JMP NEAR READER
JMP NEAR HOME
JMP NEAR SELDSK
JMP NEAR SETTRK
JMP NEAR SETSEC
JMP NEAR SETDMA
JMP NEAR READ
JMP NEAR WRITE
JMP NEAR LISTST
BOOT:
MOV AL, 0x86
CALL MSG
DB "BIOS", 0
WBOOT:
XOR CX, CX
JMP BDOS
RET
; CHAR I/O
CONST:
MOV AH, 1
INT 0x16
JZ .END
MOV AL, 0xFF
RET
.END:
XOR AL, AL
RET
CONIN:
XOR AX, AX
INT 0x16
TEST AL, AL
JZ CONIN
RET
MSG:
POP SI
.LOOP:
MOV DL, BYTE [SI]
INC SI
TEST DL, DL
JZ .END
CALL CONOUT
JMP .LOOP
.END:
MOV DL, 0x20
CALL CONOUT
CALL PRINTAL
MOV DL, 0x0A
CALL CONOUT
MOV DL, 0x0D
CALL CONOUT
PUSH SI
RET
PRINTAL:
PUSH AX
PUSH DX
AAM 16
MOV DL, AH
CALL PRINTNIB
MOV DL, AL
CALL PRINTNIB
POP DX
POP AX
RET
PRINTNIB:
ADD DL, 0x30
CMP DL, 0x3a
JL CONOUT
ADD DL, 0x07
CONOUT:
PUSH AX
PUSH BX
MOV AH, 0x0E
MOV AL, DL
XOR BX, BX
INT 0x10
POP BX
POP AX
RET
LIST:
PUSH DX
XOR AH, AH
MOV AL, DL
INT 0x17
POP DX
RET
LISTST:
STC
RET
PUNCH:
STC
RET
READER:
STC
RET
; DISK I/O
HOME:
MOV WORD [DISKCX], 0x0001
MOV BYTE [DISKDX+1], 0x00
RET
SELDSK:
MOV BYTE [DISKDX], CL
XOR BX, BX
RET
SETTRK:
PUSH CX
PUSH DX
MOV DX, CX
; CH for headnum, CL for SAL
MOV CX, 0x0006
; Take off LSB as head number
XOR CH, CH
RCR DX, 1
RCL CH, 1
MOV BYTE [DISKDX+1], CH
; DX is sector number now
; Shift into format for int13
; DX ------9876543210
SAL DX, CL
; DX 9876543210------
ROL DX, 1
ROL DX, 1
; DX 76543210------98
SAL DL, CL
; DX 7654321098------
AND WORD [DISKCX], 0x003F
OR WORD [DISKCX], DX
POP DX
POP CX
RET
SETSEC:
AND WORD [DISKCX], 0xFFC0
OR BYTE [DISKCX], CL
RET
SETDMA:
MOV WORD [DISKBX], CX
RET
READ:
PUSH CX
PUSH DX
PUSH BX
MOV AX, 0x0201
MOV CX, [DISKCX]
MOV DX, [DISKDX]
MOV BX, [DISKBX]
INT 0x13
XCHG AH, AL
POP BX
POP DX
POP CX
JC DISKERR
RET
WRITE:
PUSH CX
PUSH DX
PUSH BX
MOV AX, 0x0301
MOV CX, [DISKCX]
MOV DX, [DISKDX]
MOV BX, [DISKBX]
INT 0x13
XCHG AH, AL
POP BX
POP DX
POP CX
JC DISKERR
RET
DISKERR:
PUSHF
PUSH SI
CALL MSG
DB "DISKERR", 0
POP SI
POPF
RET

View File

@ -1,21 +0,0 @@
org 0x100
jmp start
%include "fcbparse.asm"
fcb_asm:
times 36 db 0
fcb_bin:
times 36 db 0
fcb_lst:
times 36 db 0
start:
mov si, 0x81
mov bx, fcb_asm
mov ax, 0x1234
call fcb_parse
ret

View File

@ -1,17 +0,0 @@
org 0x0100
main:
mov si, hello
.loop:
lodsb
test al, al
jz .ret
mov dl, al
mov cl, 0x02
call 5
jmp .loop
.ret:
ret
hello:
db "Hello!", 0x0A, 0x0D, 0

View File

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -1,17 +0,0 @@
; Labels for BIOS entry points
BOOT: EQU (BIOS+0)
WBOOT: EQU (BIOS+3)
CONST: EQU (BIOS+6)
CONIN: EQU (BIOS+9)
CONOUT: EQU (BIOS+12)
LIST: EQU (BIOS+15)
PUNCH: EQU (BIOS+18)
READER: EQU (BIOS+21)
HOME: EQU (BIOS+24)
SELDSK: EQU (BIOS+27)
SETTRK: EQU (BIOS+30)
SETSEC: EQU (BIOS+33)
SETDMA: EQU (BIOS+36)
READ: EQU (BIOS+39)
WRITE: EQU (BIOS+42)
LISTST: EQU (BIOS+45)

View File

@ -1,12 +0,0 @@
; BPB from first sector on FAT fs, starting 0x0B
BPB_SS: EQU 0 ; WORD sector size
BPB_SC: EQU 2 ; BYTE sectors per cluster
BPB_RSC: EQU 3 ; WORD reserved sector count
BPB_FN: EQU 5 ; BYTE number of FATs
BPB_RDE: EQU 6 ; WORD number of root directory entries
BPB_TS: EQU 8 ; WORD total number of sectors
BPB_MI: EQU 10 ; BYTE medium identifier
BPB_SF: EQU 11 ; WORD sectors per FAT
BPB_SPT: EQU 13 ; WORD sectors per track
BPB_NOS: EQU 15 ; WORD number of sides/heads
BPB_PO: EQU 17 ; DWORD partition offset

View File

@ -1,10 +0,0 @@
; File control block
FCB_DRV: EQU 0 ; BYTE 0=A: 1=B: 2=C: ...
FCB_NAM: EQU 1 ; 8 BYTES, space padded
FCB_EXT: EQU 9 ; 3 BYTES, space padded
FCB_TYP: EQU 12 ; BYTE FCB type
; TYP=1: regular file
FCB_BLK: EQU 13 ; current 128b block in sector
FCB_CLU: EQU 14 ; current sector
FCB_LFT: EQU 16 ; bytes left to read in current file
FCB_END: EQU 20 ; FCB length

View File

@ -1,54 +1,22 @@
; print a word
; in: ax
print16:
xchg ah,al
call print8
xchg ah,al
; print a byte
; in: al
print8:
push ax ; avoid destroying ah
push bx
xor bx, bx
aam 16 ; high nibble moved into ah, low nibble into al
add ax, 0x3030
push ax
xchg al, ah
call .nib
pop ax
call .nib
pop bx
pop ax
ret
.nib:
cmp al, 0x3a
jl .out
add al, 0x07
.out:
mov dl, al
call CONOUT
ret
dump:
push ax
push cx
push dx
push bx
mov dl, 0x0A
call CONOUT
mov dl, 0x0D
call CONOUT
mov al, 0x0A
call putc
mov al, 0x0D
call putc
mov cx, 4
.loop_line:
push cx
push bx
mov ax, bx
call print16
mov dl, ':'
call CONOUT
mov dl, ' '
call CONOUT
mov al, ':'
call putc
mov al, ' '
call putc
mov cx, 0x8
.loop_bin:
mov ax, [bx]

113
pxe.asm Normal file
View File

@ -0,0 +1,113 @@
org BASE
main:
mov ax, [es:bx+0x0A]
mov [cs:pxejmp], ax
mov ax, [es:bx+0x0A+2]
mov [cs:pxejmp+2], ax
mov ax, cs
mov ds, ax
mov si, pxejmp
call dump
mov ax, cs
mov ds, ax
mov di, pxestat
mov bx, 0x0071
call UsePXEAPI
mov ax, cs
mov ds, ax
mov si, pxestat
call dump
call dump
hlt: hlt
jmp hlt
UsePXEAPI:
push ds
push di
push bx
int 3
call far [pxejmp]
int 3
add sp, 6
ret
pxejmp: dd 0
pxestat:
.Status dw 0
.PacketType dw 2
.BufferSize dw 0
.BufferOff dw 0
.BufferSeg dw 0
.BufferLimit dw 0
;tftp_open:
; .Status dw 0
; .SIP dd 0
; .GIP dd 0
; .Filename db "pxe.bs"
; times (128-6) db 0
; .Port dw 0
; .PacketSize dw 0
space:
mov al, 0x20
jmp putc
putbc:
cmp al, 0x80
jnc dot
cmp al, 0x20
jnc putc
dot:
mov al, '.'
putc:
push ax
push bx
mov ah, 0x0e
xor bx, bx
int 0x10
pop bx
pop ax
ret
dump: push cx
mov ax, ds
call print16
mov al, ':'
call putc
mov ax, si
call print16
call space
call space
mov cx, 0x08
push si
.hloop: lodsb
call print8
lodsb
call print8
call space
loop .hloop
pop si
call space
mov cx, 0x10
.aloop: lodsb
call putbc
loop .aloop
mov al, 0x0A
call putc
mov al, 0x0D
call putc
pop cx
ret
%include "print.asm"
%include "printf.asm"

View File

@ -1,518 +0,0 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
uint8_t mem[64*1024];
typedef struct flagbits {
unsigned int c : 1;
unsigned int u1 : 1;
unsigned int p : 1;
unsigned int u3 : 1;
unsigned int a : 1;
unsigned int u5 : 1;
unsigned int z : 1;
unsigned int s : 1;
} flagbits;
typedef struct reg {
uint8_t flags;
uint8_t a;
uint8_t c;
uint8_t b;
uint8_t e;
uint8_t d;
uint8_t l;
uint8_t h;
} reg;
typedef struct regp {
uint16_t psw;
uint16_t bc;
uint16_t de;
uint16_t hl;
} regp;
union regset {
struct reg reg;
struct regp regp;
} regset;
#define A regset.reg.a
#define B regset.reg.b
#define C regset.reg.c
#define D regset.reg.d
#define E regset.reg.e
#define H regset.reg.h
#define L regset.reg.l
#define M mem[HL]
#define BC regset.regp.bc
#define DE regset.regp.de
#define HL regset.regp.hl
#define flags (*(struct flagbits*)&regset.reg.flags)
uint16_t IP = 0x100;
uint16_t SP = 0;
unsigned int tmp;
// Dump registers
void dump() {
printf("\n");
printf("A=%02X BC=%04X DE=%04X HL=%04X M=%02X SP=%04X ", A, BC, DE, HL, M, SP);
printf("%c", flags.s ? 'S' : '-');
printf("%c", flags.z ? 'Z' : '-');
printf("%c", flags.a ? 'A' : '-');
printf("%c", flags.p ? 'P' : '-');
printf("%c", flags.c ? 'C' : '-');
printf("\n");
printf("IP=%04X : %02X %02X\n", IP, mem[IP], mem[IP+1]);
}
uint8_t imm8() {
uint8_t r = *(uint8_t*)&mem[IP];
IP++;
return r;
}
uint16_t imm16() {
uint16_t r = *(uint16_t*)&mem[IP];
IP+=2;
return r;
}
void push(uint16_t v) {
SP -= 2;
*(uint16_t*)&mem[SP] = v;
}
uint16_t pop() {
uint16_t v = *(uint16_t*)&mem[SP];
SP += 2;
return v;
}
void in(uint8_t port) {
}
void out(uint8_t port) {
}
int has_even_parity(uint8_t x){
unsigned int count = 0, i, b = 1;
for(i = 0; i < 8; i++){
if( x & (b << i) ){count++;}
}
if( (count % 2) ){return 0;}
return 1;
}
void cpm_syscall(int number) {
switch(number) {
case 0:
exit(0);
break;
case 2:
printf("%c", E);
break;
case 0x0C:
H=0x02;
L=0x00;
break;;
default:
fprintf(stderr, "Fatal: Unhandled CP/M syscall C=%02Xh\n", number);
exit(1);
}
}
void call(uint16_t v) {
switch(v) {
case 0:
exit(0);
break;;
case 5:
cpm_syscall(C);
break;;
default:
push(IP);
IP=v;
break;
}
}
void interrupt(int number) {
call(number << 3);
}
#define add16c(a, b) \
tmp = a + b; \
flags.c = (tmp >> 16) & 1
#define unarync(a, op) \
tmp=a; \
tmp op; \
flags.p = has_even_parity(tmp & 8); \
flags.z = !(tmp); \
flags.s = (tmp >> 7) & 1; \
a=tmp
#define aritht(a, op, b) \
tmp=a; \
tmp=a op b; \
flags.c = (tmp >> 8) & 1; \
flags.p = has_even_parity(tmp & 8); \
flags.z = !(tmp); \
flags.s = (tmp >> 7) & 1;
#define arith(a, op, b) \
aritht(a, op, b); \
a=tmp
// Execute a single instruction
void step() {
uint8_t opcode = mem[IP];
IP++;
switch(opcode) {
case 0x00: break;;
case 0x01: BC=imm16(); break;;
case 0x02: mem[BC]=A; break;;
case 0x03: BC++;
case 0x04: unarync(B, ++); break;;
case 0x05: unarync(B, --); break;;
case 0x06: B=imm8(); break;;
case 0x07: tmp=A; A = A << 1 | flags.c; flags.c = tmp >> 7; break;;
case 0x09: HL=add16c(HL,BC); break;;
case 0x0a: A=mem[BC]; break;;
case 0x0b: BC--;
case 0x0c: unarync(B, ++); break;;
case 0x0d: unarync(B, --); break;;
case 0x0e: C=imm8(); break;;
case 0x11: DE=imm16(); break;;
case 0x12: mem[DE]=A; break;;
case 0x13: DE++;
case 0x14: unarync(D, ++); break;;
case 0x15: unarync(D, --); break;;
case 0x16: D=imm8(); break;;
case 0x19: HL=add16c(HL,DE); break;;
case 0x1a: A=mem[DE]; break;;
case 0x1b: DE--;
case 0x1c: unarync(E, ++); break;;
case 0x1d: unarync(E, --); break;;
case 0x1e: E=imm8(); break;;
case 0x21: HL=imm16(); break;;
case 0x22: *(uint16_t*)&mem[imm16()]=HL; break;;
case 0x23: HL++;
case 0x24: unarync(H, ++); break;;
case 0x25: unarync(H, --); break;;
case 0x26: H=imm8(); break;;
case 0x29: HL=add16c(HL,HL); break;;
case 0x2a: HL=*(uint16_t*)&mem[imm16()]; break;;
case 0x2b: HL--;
case 0x2c: unarync(L, ++); break;;
case 0x2d: unarync(L, --); break;;
case 0x2e: L=imm8(); break;;
case 0x2f: A=~A; break;;
case 0x31: SP=imm16(); break;;
case 0x32: mem[imm16()]=A; break;;
case 0x33: SP++;
case 0x34: unarync(M, ++); break;;
case 0x35: unarync(M, --); break;;
case 0x36: M=imm8(); break;;
case 0x37: flags.c = 1; break;;
case 0x39: HL=add16c(HL,SP); break;;
case 0x3a: A=mem[imm16()]; break;;
case 0x3b: SP--;
case 0x3c: unarync(A, ++); break;;
case 0x3d: unarync(A, --); break;;
case 0x3e: A=imm8(); break;;
case 0x3f: flags.c = !flags.c; break;;
case 0x40: B=B; break;;
case 0x41: B=C; break;;
case 0x42: B=D; break;;
case 0x43: B=E; break;;
case 0x44: B=H; break;;
case 0x45: B=L; break;;
case 0x46: B=M; break;;
case 0x47: B=A; break;;
case 0x48: C=B; break;;
case 0x49: C=C; break;;
case 0x4a: C=D; break;;
case 0x4b: C=E; break;;
case 0x4c: C=H; break;;
case 0x4d: C=L; break;;
case 0x4e: C=M; break;;
case 0x4f: C=A; break;;
case 0x50: D=B; break;;
case 0x51: D=C; break;;
case 0x52: D=D; break;;
case 0x53: D=E; break;;
case 0x54: D=H; break;;
case 0x55: D=L; break;;
case 0x56: D=M; break;;
case 0x57: D=A; break;;
case 0x58: E=B; break;;
case 0x59: E=C; break;;
case 0x5a: E=D; break;;
case 0x5b: E=E; break;;
case 0x5c: E=H; break;;
case 0x5d: E=L; break;;
case 0x5e: E=M; break;;
case 0x5f: E=A; break;;
case 0x60: H=B; break;;
case 0x61: H=C; break;;
case 0x62: H=D; break;;
case 0x63: H=E; break;;
case 0x64: H=H; break;;
case 0x65: H=L; break;;
case 0x66: H=M; break;;
case 0x67: H=A; break;;
case 0x68: L=B; break;;
case 0x69: L=C; break;;
case 0x6a: L=D; break;;
case 0x6b: L=E; break;;
case 0x6c: L=H; break;;
case 0x6d: L=L; break;;
case 0x6e: L=M; break;;
case 0x6f: L=A; break;;
case 0x70: M=B; break;;
case 0x71: M=C; break;;
case 0x72: M=D; break;;
case 0x73: M=E; break;;
case 0x74: M=H; break;;
case 0x75: M=L; break;;
case 0x76: exit(0); break;;
case 0x77: M=A; break;;
case 0x78: A=B; break;;
case 0x79: A=C; break;;
case 0x7a: A=D; break;;
case 0x7b: A=E; break;;
case 0x7c: A=H; break;;
case 0x7d: A=L; break;;
case 0x7e: A=M; break;;
case 0x7f: A=A; break;;
case 0x80: arith(A, +, B); break;;
case 0x81: arith(A, +, C); break;;
case 0x82: arith(A, +, D); break;;
case 0x83: arith(A, +, E); break;;
case 0x84: arith(A, +, H); break;;
case 0x85: arith(A, +, L); break;;
case 0x86: arith(A, +, M); break;;
case 0x87: arith(A, +, A); break;;
case 0x88: arith(A, +flags.c+, B); break;;
case 0x89: arith(A, +flags.c+, C); break;;
case 0x8A: arith(A, +flags.c+, D); break;;
case 0x8B: arith(A, +flags.c+, E); break;;
case 0x8C: arith(A, +flags.c+, H); break;;
case 0x8D: arith(A, +flags.c+, L); break;;
case 0x8E: arith(A, +flags.c+, M); break;;
case 0x8F: arith(A, +flags.c+, A); break;;
case 0x90: arith(A, -, B); break;;
case 0x91: arith(A, -, C); break;;
case 0x92: arith(A, -, D); break;;
case 0x93: arith(A, -, E); break;;
case 0x94: arith(A, -, H); break;;
case 0x95: arith(A, -, L); break;;
case 0x96: arith(A, -, M); break;;
case 0x97: arith(A, -, A); break;;
case 0x98: arith(A, -flags.c-, B); break;;
case 0x99: arith(A, -flags.c-, C); break;;
case 0x9A: arith(A, -flags.c-, D); break;;
case 0x9B: arith(A, -flags.c-, E); break;;
case 0x9C: arith(A, -flags.c-, H); break;;
case 0x9D: arith(A, -flags.c-, L); break;;
case 0x9E: arith(A, -flags.c-, M); break;;
case 0x9F: arith(A, -flags.c-, A); break;;
case 0xA0: arith(A, &, B); break;;
case 0xA1: arith(A, &, C); break;;
case 0xA2: arith(A, &, D); break;;
case 0xA3: arith(A, &, E); break;;
case 0xA4: arith(A, &, H); break;;
case 0xA5: arith(A, &, L); break;;
case 0xA6: arith(A, &, M); break;;
case 0xA7: arith(A, &, A); break;;
case 0xA8: arith(A, ^, B); break;;
case 0xA9: arith(A, ^, C); break;;
case 0xAA: arith(A, ^, D); break;;
case 0xAB: arith(A, ^, E); break;;
case 0xAC: arith(A, ^, H); break;;
case 0xAD: arith(A, ^, L); break;;
case 0xAE: arith(A, ^, M); break;;
case 0xAF: arith(A, ^, A); break;;
case 0xB0: arith(A, |, B); break;;
case 0xB1: arith(A, |, C); break;;
case 0xB2: arith(A, |, D); break;;
case 0xB3: arith(A, |, E); break;;
case 0xB4: arith(A, |, H); break;;
case 0xB5: arith(A, |, L); break;;
case 0xB6: arith(A, |, M); break;;
case 0xB7: arith(A, |, A); break;;
case 0xB8: aritht(A, -, B); break;;
case 0xB9: aritht(A, -, C); break;;
case 0xBA: aritht(A, -, D); break;;
case 0xBB: aritht(A, -, E); break;;
case 0xBC: aritht(A, -, H); break;;
case 0xBD: aritht(A, -, L); break;;
case 0xBE: aritht(A, -, M); break;;
case 0xBF: aritht(A, -, A); break;;
case 0xC0: if (!flags.z) IP=pop(); break;;
case 0xC1: BC=pop(); break;;
case 0xC2: tmp=imm16(); if (!flags.z) IP=tmp; break;;
case 0xC3: IP=imm16(); break;;
case 0xC4: tmp=imm16(); if (!flags.z) call(tmp); break;;
case 0xC5: push(BC); break;;
case 0xC6: arith(A, +, imm8()); break;;
case 0xC7: interrupt(0); break;;
case 0xC8: if (flags.z) IP=pop(); break;;
case 0xC9: IP=pop(); break;;
case 0xCA: tmp=imm16(); if (flags.z) IP=tmp; break;;
case 0xCC: tmp=imm16(); if (flags.z) call(tmp); break;;
case 0xCD: call(imm16()); break;;
case 0xCE: arith(A, +flags.c+, imm8()); break;;
case 0xCF: interrupt(1); break;;
case 0xD0: if (!flags.c) IP=pop(); break;;
case 0xD1: DE=pop(); break;;
case 0xD2: tmp=imm16(); if (!flags.c) IP=tmp; break;;
case 0xD3: out(imm8()); break;;
case 0xD4: tmp=imm16(); if (!flags.c) call(tmp); break;;
case 0xD5: push(DE); break;;
case 0xD6: arith(A, -, imm8()); break;;
case 0xD7: interrupt(2); break;;
case 0xD8: if (flags.c) IP=pop(); break;;
case 0xDA: tmp=imm16(); if (flags.c) IP=tmp; break;;
case 0xDB: in(imm8()); break;;
case 0xDC: tmp=imm16(); if (flags.c) call(tmp); break;;
case 0xDE: arith(A, -flags.c-, imm8()); break;;
case 0xDF: interrupt(3); break;;
case 0xE0: if (!flags.p) IP=pop(); break;;
case 0xE1: HL=pop(); break;;
case 0xE2: tmp=imm16(); if (!flags.p) IP=tmp; break;;
case 0xE3: tmp=HL; HL=pop(); push(tmp); break;;
case 0xE4: tmp=imm16(); if (!flags.p) call(tmp); break;;
case 0xE5: push(HL); break;;
case 0xE6: arith(A, &, imm8()); break;;
case 0xE7: interrupt(4); break;;
case 0xE8: if (flags.p) IP=pop(); break;;
case 0xE9: IP=HL; break;;
case 0xEA: tmp=imm16(); if (flags.p) IP=tmp; break;;
case 0xEB: tmp=HL; HL=DE; DE=tmp;; break;;
case 0xEC: tmp=imm16(); if (flags.p) call(tmp); break;;
case 0xEE: arith(A, ^, imm8()); break;;
case 0xEF: interrupt(5); break;;
case 0xF0: if (!flags.s) IP=pop(); break;;
case 0xF1: regset.regp.psw=pop(); break;;
case 0xF2: tmp=imm16(); if (!flags.s) IP=tmp; break;;
case 0xF4: tmp=imm16(); if (!flags.s) call(tmp); break;;
case 0xF5: push(regset.regp.psw); break;;
case 0xF6: arith(A, |, imm8()); break;;
case 0xF7: interrupt(6); break;;
case 0xF8: if (flags.s) IP=pop(); break;;
case 0xF9: SP=HL; break;;
case 0xFA: tmp=imm16(); if (flags.s) IP=tmp; break;;
case 0xFC: tmp=imm16(); if (flags.s) call(tmp); break;;
case 0xFE: aritht(A, -, imm8()); break;;
case 0xFF: interrupt(7); break;;
default:
IP--;
dump();
fprintf(stderr, "Invalid opcode at IP=%04X\n", IP);
exit(1);
break;
}
}
void copy_cmdline(char* str) {
int i, c;
uint8_t *len = &mem[0x80];
char* ptr = (char*)&mem[0x81];
c = strlen(str);
// Clip at max length
if (c>0x7E) {
fprintf(stderr, "Command line too long, max is 126 bytes\n");
exit(1);
}
memcpy(ptr, str, c);
ptr[c]=0x0D;
*len=c;
}
int main(int argc, char** argv) {
memset(&mem, sizeof(mem), 0);
// Prepare default exit into int 20h
mem[0]=0x76;
push(0);
argc--;
argv++;
while(argc && argv[0][0]=='-') {
switch(argv[0][1]) {
default:
fprintf(stderr, "Unknown option %s\n", argv[0]);
exit(1);
break;
}
argc--;
argv++;
}
if (argc) {
FILE* fd = fopen(argv[0], "r");
fread(mem + IP, 1, sizeof(mem) - IP, fd);
argc--;
argv++;
} else {
fprintf(stderr, "No COM file specified\n");
exit(1);
}
if (argc) {
copy_cmdline(argv[0]);
} else {
copy_cmdline("");
}
while(1) {
dump();
step();
}
}