This commit is contained in:
Dennis Gunia
2022-12-16 20:45:34 +01:00
parent aabf475b67
commit bc1b9a399d
40 changed files with 13208 additions and 5377 deletions

View File

@@ -0,0 +1,51 @@
CS_BANK equ 0000000b
CS_DIP equ 0000001b
CS_CTC_0 equ 0000100b
CS_CTC_1 equ 0000101b
CS_CTC_2 equ 0000110b
CS_CTC_3 equ 0000111b
CS_SIO_A_D equ 0001000b
CS_SIO_A_C equ 0001001b
CS_SIO_B_D equ 0001010b
CS_SIO_B_C equ 0001011b
IO_RTC_SEC0 equ 00100000b
IO_RTC_SEC1 equ 00100001b
IO_RTC_MIN0 equ 00100010b
IO_RTC_MIN1 equ 00100011b
IO_RTC_HOUR equ 00100100b
IO_RTC_AMPM equ 00100101b
IO_RTC_DAY0 equ 00100110b
IO_RTC_DAY1 equ 00100111b
IO_RTC_MON0 equ 00101000b
IO_RTC_MON1 equ 00101001b
IO_RTC_YERR0 equ 00101010b
IO_RTC_YEAR1 equ 00101011b
IO_RTC_WEEK equ 00101100b
IO_RTC_CTR_D equ 00101101b
IO_RTC_CTR_E equ 00101110b
IO_RTC_CTR_F equ 00101111b
IO_AY0_ADDR equ 01000000b ;64
IO_AY0_DATA equ 01000001b ;65
IO_AY1_ADDR equ 01000010b ;66
IO_AY1_DATA equ 01000011b ;67
START_ROM equ 0x0000
IO_REG0 equ 0x20
VDP_REG equ 0x81
VDP_MEM equ 0x80
PROG_ROM_START equ 0x0100
PROG_MEM_START equ 04000h
IO_PIO_0_A_D equ 0x60
IO_PIO_0_A_C equ 0x61
IO_PIO_0_B_D equ 0x62
IO_PIO_0_B_C equ 0x63
IO_PIO_1_A_D equ 0x64 ;PS2
IO_PIO_1_A_C equ 0x65
IO_PIO_1_B_D equ 0x66
IO_PIO_1_B_C equ 0x67

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,115 @@
; Z8C Bootloader
; 2022 by Dennis Gunia
BTLDR_ENTRY:
;ld SP, 0ffffh ; set stack pointer
;Setup Serial Interface
LD A,01001111b ; External Trigger, Time Constant Follows
OUT (CS_CTC_0),A
IN A,(CS_DIP) ; Read BAUD from DIP-Switches
OUT (CS_CTC_0),A
LD A,00110000b ;write into WR0: error reset, select WR0
OUT (CS_SIO_A_C),A
LD a,018h ;write into WR0: channel reset
OUT (CS_SIO_A_C),A
LD a,004h ;write into WR0: select WR4
OUT (CS_SIO_A_C),A
;LD a,04h ;write into WR4: clkx1,1 stop bit, no parity
LD a,01000100b ;write into WR4: clkx16,1 stop bit, no parity
OUT (CS_SIO_A_C),A
LD a,005h ;write into WR0: select WR5
OUT (CS_SIO_A_C),A
LD a,11101000b ;DTR inactive, TX 8bit, BREAK off, TX on, RTS inactive
OUT (CS_SIO_A_C),A
LD a,01h ;write into WR0: select WR1
OUT (CS_SIO_A_C),A
LD a,00000100b ;no interrupt in CH B, special RX condition affects vect
OUT (CS_SIO_A_C),A
LD a,02h ;write into WR0: select WR2
OUT (CS_SIO_A_C),A
LD a,0h ;write into WR2: cmd line int vect (see int vec table)
;bits D3,D2,D1 are changed according to RX condition
OUT (CS_SIO_A_C),A
LD a,003h ;write into WR0: select WR3
OUT (CS_SIO_A_C),A
LD a,0C1h ;RX 8bit, auto enable off, RX on
OUT (CS_SIO_A_C),A
BTLDR_STARTUP_MSG:
LD HL,[S_BTLDR_STARTUP_MSG]
BTLDR_STARTUP_MSG_LOOP:
LD A,(HL)
OR A
JR Z, BTLDR_INPUT
CALL BTLDR_SUB_WRITEA
INC HL
JR BTLDR_STARTUP_MSG_LOOP
BTLDR_INPUT:
; Byte 1 & 2 = Length
CALL BTLDR_SUB_INPUT_READ
LD B, A
CALL BTLDR_SUB_INPUT_READ
LD C, A
; Byte 3 & 4 = Offset / Start address
CALL BTLDR_SUB_INPUT_READ
LD H, A
CALL BTLDR_SUB_INPUT_READ
LD L, A
; Byte 5+ = Payload
BTLDR_INPUT_1:
CALL BTLDR_SUB_INPUT_READ
LD (HL),A ;Store byte
DEC BC
LD A,H
OR A.L
JR Z, BTLDR_DONE
INC HL
JR BTLDR_INPUT_1
BTLDR_DONE:
RET
; Strings
S_BTLDR_STARTUP_MSG:
db "Z8C BTLDR.S V0.1 by Dennis Gunia [RDY] ",0
; Subroutines
BTLDR_SUB_WRITEA:
OUT (CS_SIO_A_D),A
BTLDR_SUB_WRITEA_WAIT:
XOR A
INC A
OUT (CS_SIO_A_C),A
IN A,(CS_SIO_A_C)
BIT 0,A
JR Z, BTLDR_SUB_WRITEA_WAIT
RET
BTLDR_SUB_RTS_OFF:
ld a,005h ;write into WR0: select WR5
out (CS_SIO_A_C),A
ld a,0E8h ;DTR active, TX 8bit, BREAK off, TX on, RTS inactive
out (CS_SIO_A_C),A
ret
BTLDR_SUB_RTS_ON:
ld a,005h ;write into WR0: select WR5
out (CS_SIO_A_C),A
ld a,0EAh ;DTR active, TX 8bit, BREAK off, TX on, RTS active
out (CS_SIO_A_C),A
ret
BTLDR_SUB_INPUT_READ:
CALL BTLDR_SUB_RTS_ON
XOR A
OUT (CS_SIO_A_C), a
IN A, (CS_SIO_A_C)
AND 1
JR Z, BTLDR_SUB_INPUT_READ ;LOOP IF BUFFER EMPTY
CALL BTLDR_SUB_RTS_OFF
IN A, (CS_SIO_A_D)
RET

View File

@@ -0,0 +1,136 @@
;DIP SWICTHES
;1843200 CLK / x16 SIO CLOCK MODE = 115200
;MAX BAUD RATE = 115200
;DIP VALUE = 115200/<BAUD>
;
;9600 -> 12 / 00110000
;
CONSOLE_INIT:
CONSOLE_INIT_CTC:
;LD A,00001111b ; Set /16 Divider, CPU Trigger, Time COnstant Follows
LD A,01001111b ; External Trigger, Time COnstant Follows
OUT (CS_CTC_0),A
IN A,(CS_DIP) ; Read BAUD from DIP-Switches
;LD A,39
OUT (CS_CTC_0),A
CONSOLE_INIT_SIO:
LD A,00110000b ;write into WR0: error reset, select WR0
OUT (CS_SIO_A_C),A
LD a,018h ;write into WR0: channel reset
OUT (CS_SIO_A_C),A
LD a,004h ;write into WR0: select WR4
OUT (CS_SIO_A_C),A
LD a,01000100b ;write into WR4: clkx16,1 stop bit, no parity
OUT (CS_SIO_A_C),A
LD a,005h ;write into WR0: select WR5
OUT (CS_SIO_A_C),A
LD a,11101000b ;DTR inactive, TX 8bit, BREAK off, TX on, RTS inactive
OUT (CS_SIO_A_C),A
LD a,01h ;write into WR0: select WR1
OUT (CS_SIO_A_C),A
LD a,00000100b ;no interrupt in CH B, special RX condition affects vect
OUT (CS_SIO_A_C),A
LD a,02h ;write into WR0: select WR2
OUT (CS_SIO_A_C),A
LD a,0h ;write into WR2: cmd line int vect (see int vec table)
;bits D3,D2,D1 are changed according to RX condition
OUT (CS_SIO_A_C),A
LD a,003h ;write into WR0: select WR3
OUT (CS_SIO_A_C),A
LD a,0C1h ;RX 8bit, auto enable off, RX on
OUT (CS_SIO_A_C),A
;Channel A RX active
RET
; A contains char
; Destroys A
print_char:
push af
out (CS_SIO_A_D),a
call print_wait_out
pop af
;call print_char
ret
; HL contains pointer to string
; Destroy A, HL
print_str:
ld a, (hl)
or a
jr z,print_str_end
call print_char
inc hl
jr print_str
print_str_end:
ret
print_clear:
ld hl, [MSG_CLEAR]
call print_str
ret
print_newLine:
ld a,10
call print_char
ld a,13
call print_char
ret
; destroys a
print_wait_out:
; check for TX buffer empty
sub a ;clear a, write into WR0: select RR0
inc a ;select RR1
out (CS_SIO_A_C),A
in A,(CS_SIO_A_C) ;read RRx
bit 0,A
jr z,print_wait_out
ret
print_a_hex:
push af
push bc
push de
call STRCONV_BYTES_TO_HEX
ld a,b
call print_char
ld a,c
call print_char
pop de
pop bc
pop af
read_char:
call A_RTS_ON
nop
xor a ; a = 0
out (CS_SIO_A_C), a ; select reg 0
in a, (CS_SIO_A_C) ; read reg 0
and 1 ; mask D0 (recieve char available)
call A_RTS_OFF
ret Z ; return 0 if no char
in a, (CS_SIO_A_D) ; read char if avail
ret ; return
;MSG_CRSR_0:
; db 0x1B, "[?25h",0
;MSG_CRSR_1:
; db 0x1B, "[?25l",0
MSG_CLEAR:
db 27, '[2J', 27, '[H',0
; Serial Util Functions
A_RTS_OFF:
ld a,005h ;write into WR0: select WR5
out (CS_SIO_A_C),A
ld a,068h ;DTR inactiveh, TX 8bit, BREAK off, TX on, RTS inactive
out (CS_SIO_A_C),A
ret
A_RTS_ON:
ld a,005h ;write into WR0: select WR5
out (CS_SIO_A_C),A
ld a,0EAh ;DTR active, TX 8bit, BREAK off, TX on, RTS active
out (CS_SIO_A_C),A
ret

View File

@@ -0,0 +1,89 @@
; HL Contains Address to string
; E is 0xFF if error
; E is 0x00 if okay
; A returns byte
; A,DE are destroyed
DHEX_TO_BYTE:
PUSH HL ;Backup pointer
; Load First Byte
LD A,(HL) ;Load first char (high)
CALL HEX_TO_BIN ;Conv chart to 4bit
jr C, DHEX_TO_BYTE_FAILED ;If error jmp to DHEX_TO_BYTE_FAILED
SLA A ;shift result to upper 4 bits
SLA A
SLA A
SLA A
LD D,A ;store result in D
INC HL ;next byte
LD A,(HL) ;load 2nd char (lower)
CALL HEX_TO_BIN ;Conv chart to 4bit
jr C, DHEX_TO_BYTE_FAILED ;If error jmp to DHEX_TO_BYTE_FAILED
OR D ;merge D with accumulator
POP HL ;restor original pointer
LD E,0x00 ;set error to 0x00 = no error
RET
DHEX_TO_BYTE_FAILED:
LD E,0xFF ;set error to oxFF
;LD A,0x00
POP HL
RET
; REG A Contains CHAR-Low
; If failed, Carry is set
HEX_TO_BIN:
SUB 48 ; 0 is 0
jp PE, HEX_TO_INVALID_2; to low (SUB overflow)
CP 10 ; Value is between 0 and 9
JR C, HEX_TO_BIN_2
SUB 7
jp PE, HEX_TO_INVALID_2; to low (SUB overflow)
HEX_TO_BIN_2:
CP 16
JR NC, HEX_TO_INVALID_2; if bigger than 15-> fail
AND 0x0F
RET
HEX_TO_INVALID_2:
SCF ;set carry flag
RET
;*****************
; Convert Byte to Hex Char (ASCII)
;*****************
;Description: the StrLength function inline
;
;Inputs: A contains input byte
;
;Outputs: BC contains 2 Bytes of ASCII (HEX)
;
;Destroys: A, BC,
STRCONV_BYTES_TO_HEX:
PUSH AF;Backup A Register
RRA
RRA
RRA
RRA
CALL STRCONV_BYTES_TO_HEX_1
;LD A,D
LD B,A
POP AF ; Reload first Byte
CALL STRCONV_BYTES_TO_HEX_1
;LD A,D
LD C,A
RET
STRCONV_BYTES_TO_HEX_1:
AND 0x0F
ADD 48
CP 58 ; Check if less than 58 (less than ASCII 9)
;JR C, STRCONV_BYTES_TO_HEX_2
RET C
ADD 7 ; A-F
RET
STRCONV_BYTES_TO_HEX_2:
;LD D,A
RET

View File

@@ -0,0 +1,78 @@
debug_init:
ld A,VAR_CONSOLE_CONF ; Setup CTC
out (IO_CTC0_C0),A ; Controll word, software reset, time constant follows, CLK/TRG starts timer
ld A,VAR_CONSOLE_BAUD ; Setup timer const
out (IO_CTC0_C0),A ; Load timer const into CTC (Setup Baud generator)
;set up TX and RX:W
ld a,00110000b ;write into WR0: error reset, select WR0
out (IO_SIO0A_C),A
ld a,018h ;write into WR0: channel reset
out (IO_SIO0A_C),A
ld a,004h ;write into WR0: select WR4
out (IO_SIO0A_C),A
ld a,04h ;44h write into WR4: clkx1,1 stop bit, no parity
out (IO_SIO0A_C),A
ld a,005h ;write into WR0: select WR5
out (IO_SIO0A_C),A
ld a,068h ;DTR active, TX 8bit, BREAK off, TX on, RTS inactive
out (IO_SIO0A_C),A
ld a,01h ;write into WR0: select WR1
out (IO_SIO0A_C),A
ld a,00000100b ;no interrupt in CH B, special RX condition affects vect
out (IO_SIO0A_C),A
;enable SIO channel A RX
ld a,003h ;write into WR0: select WR3
out (IO_SIO0A_C),A
ld a,0C1h ;RX 8bit, auto enable off, RX on
out (IO_SIO0A_C),A
;Channel A RX active
ld hl,[MSG_START_DBG]
call debug_print_str
ret
debug_print_char:
out (IO_SIO0A_D),a
call debug_wait_out
ret
debug_print_str:
ld a, (hl)
or a
ret z
call debug_print_char
inc hl
jr debug_print_str
debug_print_newLine:
ld a,10
call debug_print_char
ld a,13
call debug_print_char
ret
debug_wait_out:
; check for TX buffer empty
sub a ;clear a, write into WR0: select RR0
inc a ;select RR1
out (IO_SIO0A_C),A
in A,(IO_SIO0A_C) ;read RRx
bit 0,A
jr z,debug_wait_out
ret
MSG_START_DBG:
db "Debug interface active!",13,10,0
debug_a_hex:
push BC
push AF
call STRCONV_BYTES_TO_HEX
ld a, b
call debug_print_char
ld a, c
call debug_print_char
pop AF
pop BC
ret

View File

@@ -0,0 +1,322 @@
; HL contains start address
; B contains length
disassemble:
call dasm_print16hex_addr ;print address (HL)
call disassemble_table_seek
xor a
or b
or c
jr z, disassemble_err ;if bc==0000h
ld a,(hl) ;load first byte
call dasm_print8hex ;print value
ld a,(hl)
cp 0xC3 ;C3 JPnn
jp z, dasm_C3
;start getting value
disassemble_err:
ld a,(hl)
call dasm_print8hex ;print value
push hl
ld hl, [dasm_UU]
call print_str
pop hl
disassemble_continue:
call print_newLine
inc hl
dec b
jp nz, disassemble
ret
;A contains char
;BC contains returned position
disassemble_table_seek:
push hl
ld c,a
disassemble_table_seek_loop:
ld a,(hl)
cp c ; if match
jr z, disassemble_table_found
or a ; if null
jp z, disassemble_table_notfound
ld b,0
ld c,4
add hl,bc
ld a,(hl)
ld c,a
add hl,bc
inc hl
jr disassemble_table_seek_loop
disassemble_table_found
ld b,H
ld c,l
pop hl
ret
disassemble_table_notfound
ld b,0
ld c,0
pop hl
ret
dasm_C3: ;JP nn (276)
inc hl
ld e, (HL)
inc hl
ld d, (HL)
inc hl
;de now has jmp value
push hl
ld hl, [dasm_C3_str]
call print_str
ld h,d
ld l,e
call dasm_print16hex_addr
pop hl
jp disassemble_continue
dasm_C3_str:
db "JP ",0x00
dasm_JPccnn: ;JP nn (276)
rra
rra
rra
and 0x07
call dasm_printFlags
ld a, ","
call print_char
inc hl
ld e, (HL)
inc hl
ld d, (HL)
inc hl
;de now has jmp value
push hl
ld hl, [dasm_C3_str]
call print_str
ld h,d
ld l,e
call dasm_print16hex_addr
pop hl
jp disassemble_continue
dasm_18: ;JR e
inc hl
ld e, (HL)
inc hl
;de now has jmp value
push hl
ld hl, [dasm_18_str]
call print_str
ld a,e
call dasm_print8relhex
pop hl
jp disassemble_continue
dasm_18_str:
db "JR ",0x00
dasm_38: ;JR C,e
inc hl
ld e, (HL)
inc hl
;de now has jmp value
push hl
ld hl, [dasm_38_str]
call print_str
ld a,e
call dasm_print8relhex
pop hl
jp disassemble_continue
dasm_38_str:
db "JR C, ",0x00
dasm_30: ;JR NC,e
inc hl
ld e, (HL)
inc hl
;de now has jmp value
push hl
ld hl, [dasm_30_str]
call print_str
ld a,e
call dasm_print8relhex
pop hl
jp disassemble_continue
dasm_30_str:
db "JR NC, ",0x00
dasm_28: ;JR Z,e
inc hl
ld e, (HL)
inc hl
;de now has jmp value
push hl
ld hl, [dasm_28_str]
call print_str
ld a,e
call dasm_print8relhex
pop hl
jp disassemble_continue
dasm_28_str:
db "JR Z, ",0x00
dasm_20: ;JR NZ,e
inc hl
ld e, (HL)
inc hl
;de now has jmp value
push hl
ld hl, [dasm_20_str]
call print_str
ld a,e
call dasm_print8relhex
pop hl
jp disassemble_continue
dasm_20_str:
db "JR NZ, ",0x00
dasm_E9: ;JR NZ,e
inc hl
push hl
ld hl, [dasm_20_str]
call print_str
pop hl
jp disassemble_continue
dasm_E9_str:
db "JP (HL), ",0x00
dasm_E9: ;JP (HL)
inc hl
push hl
ld hl, [dasm_E9_str]
call print_str
pop hl
jp disassemble_continue
dasm_E9_str:
db "JP (HL)",0x00
dasm_E9: ;JP (IX)
inc hl
push hl
ld hl, [dasm_E9_str]
call print_str
pop hl
jp disassemble_continue
dasm_E9_str:
db "JP (IX)",0x00
dasm_E9: ;JP (IY)
inc hl
push hl
ld hl, [dasm_E9_str]
call print_str
pop hl
jp disassemble_continue
dasm_E9_str:
db "JP (IY)",0x00
dasm_00: ;JP nn (276)
inc hl
push hl
ld hl, [dasm_00_str]
call print_str
pop hl
jp disassemble_continue
dasm_00_str:
db "NOP",0x00
dasm_FF: ;JP nn (276)
inc hl
push hl
ld hl, [dasm_FF_str]
call print_str
pop hl
jp disassemble_continue
dasm_FF_str:
db "---",0x00
dasm_print16hex_addr:
ld a,"$"
call print_char
ld a,h
call print_a_hex
ld a,l
call print_a_hex
ld a,"h"
call print_char
ld a," "
call print_char
ret
dasm_print8hex:
call print_a_hex
ld a,"h"
call print_char
ld a," "
call print_char
ret
dasm_print8relhex:
push af
and 0x80
jp nz, dasm_print8relhex_neg
ld a,"$"
call print_char
ld a,"+"
call print_char
pop af
call print_a_hex
ld a,"h"
call print_char
ret
dasm_print8relhex_neg:
ld a,"$"
call print_char
ld a,"-"
call print_char
pop af
neg
call print_a_hex
ld a,"h"
call print_char
ret
dasm_printFlags:
push hl
ld hl, [dasm_printFlags_table]
rlca
ld b,0
ld c,a
add hl,bc
call print_str
ld a, " "
call print_char
pop hl
ret
dasm_printFlags_table:
db "NZ",0
db "Z",0,0
db "NC"
db "C",0,0
db "PO",0
db "PE",0
db "P",0,0
db "M",0,0

View File

@@ -0,0 +1,569 @@
var_opcode_start equ PRG_RAM_START ;16 bit pointer to opcode in mem
var_opcode_table equ PRG_RAM_START+2 ;16 bit pointer to opcode in table
var_opcode equ PRG_RAM_START+4 ;8 bit opcode value
var_opcode_x equ PRG_RAM_START+5 ;8 bit opcode extension value
var_opcode_length equ PRG_RAM_START+6 ;8 bit opcode length (in bytes)
var_opcode_string equ PRG_RAM_START+7 ;16 bit pointer to opcode string
var_opcode_pcount equ PRG_RAM_START+9 ;8 bit opcode param count
var_bytes_count equ PRG_RAM_START+10 ;bytes to examine
; HL contains start address
; B contains length
disassemble:
ld a,b
ld (var_bytes_count),a
disassemble_next:
ld (var_opcode_start), hl ;16 bit pointer to opcode in mem
ld a,(hl) ;load opcode to find in A
ld (var_opcode), a ;8 bit opcode value
inc hl
ld a,(hl) ;load opcode to find in A
ld (var_opcode_x), a ;8 bit opcode extended value
dec hl
call disassemble_table_seek
ld a,b
or c
jp z, disassemble_err ;if bc==0000h
ld (var_opcode_table), bc ;16 bit pointer to opcode in table
;load params
inc bc
inc bc
inc bc
inc bc
ld a,(bc)
ld (var_opcode_length),A ;8 bit opcode length (in bytes)
inc bc
ld a, (bc)
ld e,a
inc bc
ld a, (bc)
ld d,a
ld (var_opcode_string),de ;16 bit pointer to opcode string
inc bc
ld a,(bc)
ld (var_opcode_pcount),A ;8 bit opcode param count
;values are prepared. Continue with print
ld hl,(var_opcode_start) ;print address
call dasm_print16hex_addr
ld a,(var_opcode_length)
ld b, a
;print up to 4 opcode bytes
ld hl,(var_opcode_start)
disassemble_print_opcode_raw
ld a,(hl) ;load first byte
call print_a_hex
inc hl
djnz disassemble_print_opcode_raw
ld a,"h"
call print_char
;fill empty spots
ld a,(var_opcode_length)
ld b,a
ld a,6
sub b
ld b,a
disassemble_print_opcode_raw_fill:
ld a," "
call print_char
ld a," "
call print_char
djnz disassemble_print_opcode_raw_fill
ld a," "
call print_char
push hl
;print opcode
ld hl,(var_opcode_string)
call print_str
;print params
ld a,(var_opcode_pcount)
or a
jp z, disassemble_print_opcode_params_end ;skip if no params
ld hl,(var_opcode_table)
ld bc, 8
add hl,bc ;hl now has address of first param
ld a,(var_opcode_pcount)
ld b,a
disassemble_print_opcode_params_loop:
;ld a,(hl) ;load param
;call print_a_hex
ld a,(hl) ;load param
cp 0x01
call z, param_01
cp 0x02
call z, param_02
cp 0x03
call z, param_03
cp 0x04
call z, param_04
cp 0x05
call z, param_05
cp 0x06
call z, param_06
cp 0x07
call z, param_07
cp 0x08
call z, param_08
cp 0x09
call z, param_09
cp 0x10
call z, param_10
cp 0x11
call z, param_11
cp 0x12
call z, param_12
cp 0x13
call z, param_13
cp 0x0A
call z, param_0A
;strings
cp 0x80
call z, param_80
cp 0x81
call z, param_81
inc hl
djnz disassemble_print_opcode_params_loop
disassemble_print_opcode_params_end:
pop hl
jr disassemble_continue
disassemble_err:
call dasm_print16hex_addr
ld a,(hl)
call dasm_print8hex ;print value
inc hl
push hl
ld hl, [dasm_UU]
call print_str
pop hl
disassemble_continue:
call print_newLine
;inc hl
ld a,(var_bytes_count)
dec a
ld (var_bytes_count),a
jp nz, disassemble_next
ret
;A contains opcode
;BC contains returned position
disassemble_table_seek:
push hl
ld hl, [dasm_opcode_table]
disassemble_table_seek_loop:
ld a,(var_opcode)
ld c,a
ld a,(hl)
cp 0xFF ; if null
jp z, disassemble_table_notfound
;apply mask
push af
inc hl
ld b,(hl) ;load mask
dec hl
ld a,c
and b ;apply mask
ld c,a
pop af
cp c ; if match
jr z, disassemble_table_first_match
ld b,0
ld c,7
add hl,bc
ld a,(hl)
ld c,a
add hl,bc
inc hl
jr disassemble_table_seek_loop
disassemble_table_first_match
inc hl
inc hl
ld c,(hl) ;load opcode x from table
inc hl
ld a,(var_opcode_x) ;load current opcode x
ld b,(hl) ;load mask
and b ;apply mask
cp c ;compare to table
dec hl
dec hl
dec hl
jr z, disassemble_table_found ;IF FOUND
ld b,0 ;else continue with next
ld c,7
add hl,bc
ld a,(hl)
ld c,a
add hl,bc
inc hl
jr disassemble_table_seek_loop
disassemble_table_found
ld b,H
ld c,l
pop hl
ret
disassemble_table_notfound
ld b,0
ld c,0
pop hl
ret
dasm_print16hex_addr:
ld a,"$"
call print_char
ld a,h
call print_a_hex
ld a,l
call print_a_hex
ld a,"h"
call print_char
ld a," "
call print_char
ret
dasm_print8hex:
call print_a_hex
ld a,"h"
call print_char
ld a," "
call print_char
ret
param_01: ; 0x01 16bit address pointer
push hl
ld de,(var_opcode_start)
inc de
ld a,(de)
ld l,a
inc de
ld a,(de)
ld h,a
ld a,"$"
call print_char
ld a,h
call print_a_hex
ld a,l
call print_a_hex
ld a,"h"
call print_char
ld a," "
call print_char
call param_comma
pop hl
ret
param_02:
push bc
ld de,(var_opcode_start)
ld a,(de)
rra
rra
and 0x0E
push hl
ld hl, [dasm_printFlags_table]
ld b,0
ld c,a
add hl,bc
call print_str
ld a, " "
call print_char
pop hl
pop bc
ret
param_03:
ld de,(var_opcode_start)
inc de
ld a,(de)
push af
and 0x80
jp nz, param_03_neg
ld a,"$"
call print_char
ld a,"+"
call print_char
pop af
call print_a_hex
ld a,"h"
call print_char
jr param_03_done
param_03_neg:
ld a,"$"
call print_char
ld a,"-"
call print_char
pop af
neg
call print_a_hex
ld a,"h"
call print_char
jr param_03_done
param_03_done:
call param_comma
ret
param_04:
ld de,(var_opcode_start)
inc de
ld a,(de)
cp 0x4D
jr z,param_04_i
ld a,"N"
call print_char
ret
param_04_i:
ld a,"I"
call print_char
ret
param_05:
push bc
ld de,(var_opcode_start)
ld a,(de)
and 0x38
; print hex char
call dasm_print8hex
pop bc
ret
param_06:
push bc
ld de,(var_opcode_start)
ld a,(de)
rra
rra
rra
and 0x07
call param_printRegister
ld a," "
call print_char
ld a,","
call print_char
pop bc
ret
param_07:
push bc
ld de,(var_opcode_start)
ld a,(de)
and 0x07
call param_printRegister
pop bc
ret
param_08:
push bc
ld de,(var_opcode_start)
inc de
ld a,(de)
call dasm_print8hex
pop bc
ret
param_0A:
push hl
ld de,(var_opcode_start)
inc de
inc de
jr param_09_0A
param_09:
push hl
ld de,(var_opcode_start)
inc de
param_09_0A:
ld a,(de)
ld l,a
inc de
ld a,(de)
ld h,a
ld a,h
call print_a_hex
ld a,l
call print_a_hex
pop hl
ret
param_10:
push bc
ld de,(var_opcode_start)
ld a,(de)
rra
rra
rra
and 0x07
call param_printRegister
pop bc
ret
param_11:
push hl
push bc
ld de,(var_opcode_start)
jr param_11_12
param_12:
push hl
push bc
ld de,(var_opcode_start)
inc de
param_11_12:
ld a,(de)
rra
rra
rra
and 0x06
push af
;check which table to use
ld hl, (var_opcode_start)
ld a,(hl)
cp 0xDD
jr z,param_11_12_ix
cp 0xFD
jr z,param_11_12_iy
param_11_12_def:
ld hl, [dasm_printRegister8_table]
jr param_11_12_all
param_11_12_ix:
ld hl, [dasm_printRegisterIX_table]
jr param_11_12_all
param_11_12_iy:
ld hl, [dasm_printRegisterIY_table]
param_11_12_all:
pop af
ld b,0
ld c,a
add hl, bc
ld a,(hl)
call print_char
inc hl
ld a,(hl)
call print_char
pop bc
pop hl
ret
param_13:
push hl
push bc
ld de,(var_opcode_start)
ld a,(de)
rra
rra
rra
and 0x06
push af
;check which table to use
ld hl, (var_opcode_start)
ld a,(hl)
ld hl, [dasm_printRegisterSP_table]
jr param_11_12_all ;reuse code from 11_12
param_81:
push hl
push bc
ld hl, (var_opcode_string)
ld b,2
jr param_80_seek
param_80:
push hl
push bc
ld hl, (var_opcode_string)
ld b,1
param_80_seek:
ld a,(hl)
inc hl
and a
jr nz, param_80_seek
;found
dec b ;found but counter too high
jp nz, param_80_seek
call print_str
pop bc
pop hl
ret
param_printRegister:
push hl
cp 0x06
jr z, param_printRegisterHL
cp 0x07
jr z, param_printRegisterA
ld hl, [dasm_printRegister8_table]
ld b,0
ld c,a
add hl,bc
ld a, (hl)
call print_char
pop hl
ret
param_printRegisterHL:
ld hl, [dasm_printRegister8_table_HL]
call print_str
pop hl
ret
param_printRegisterA:
ld a,"A"
call print_char
pop hl
ret
param_comma:
ld a,b
cp 1
ret z
ld a," "
call print_char
ld a,","
call print_char
ret

View File

@@ -0,0 +1,333 @@
;disassembler tables
dasm_opcode_table:
;byte 0 = opcode
;byte 1 = opcode mask
;byte 2 = opcode extended
;byte 3 = opcode extended mask
;byte 4 = length
;byte 5+6 = pointer to string
;byte 7 = params = count of paramters
;byte 8+ = paramters
; 0x01 16bit address pointer
; 0x02 flag bit 3-5
; 0x03 relative jmp address
; 0x04 RETI/RETN
; 0x05 RST Vector
; 0x06 register (r)
; 0x07 register (r')
; 0x08 8-Bit value
; 0x09 16-Bit value
; 0x0A 16-bit value with offset +1
; 0x10 same as 0x06 without ","
; 0x11 print 16 bit register from 1st byte
; 0x12 print 16 bit register from 2nd byte
; 0x13 push/pop register lookup
; 0x80 print string suffix
; 0x81 print string suffix 2
defb 0x00, 0xFF, 0x00, 0x00, 1, [dasm_00], [dasm_00]>>8,0 ;NOP
;General-Purpose Arithmetic and CPU Control Groups
defb 0x27, 0xFF, 0x00, 0x00, 1, [dasm_27], [dasm_27]>>8, 0 ;DAA
defb 0x2F, 0xFF, 0x00, 0x00, 1, [dasm_2F], [dasm_2F]>>8, 0 ;CPL
defb 0xED, 0xFF, 0x44, 0xFF, 2, [dasm_ED_44], [dasm_ED_44]>>8, 0 ;NEG
defb 0x3f, 0xFF, 0x00, 0x00, 1, [dasm_3F], [dasm_3F]>>8, 0 ;CCF
defb 0x37, 0xFF, 0x00, 0x00, 1, [dasm_37], [dasm_37]>>8, 0 ;SCF
;defb 0x00, 0xFF, 0x00, 0x00, 1, [dasm_00], [dasm_00]>>8,0 ;NOP -> already at top for performance reasons
defb 0x76, 0xFF, 0x00, 0x00, 1, [dasm_76], [dasm_76]>>8, 0 ;HALT
defb 0xF3, 0xFF, 0x00, 0x00, 1, [dasm_F3], [dasm_F3]>>8, 0 ;DI
defb 0xFB, 0xFF, 0x00, 0x00, 1, [dasm_FB], [dasm_FB]>>8, 0 ;EI
defb 0xED, 0xFF, 0x46, 0xFF, 2, [dasm_ED_46], [dasm_ED_46]>>8, 0 ;IM 0
defb 0xED, 0xFF, 0x56, 0xFF, 2, [dasm_ED_56], [dasm_ED_56]>>8, 0 ;IM 1
defb 0xED, 0xFF, 0x5E, 0xFF, 2, [dasm_ED_5E], [dasm_ED_5E]>>8, 0 ;IM 2
;Exchange, Block Transfer, and Search Group
defb 0xEB, 0xFF, 0x00, 0x00, 1, [dasm_BE], [dasm_BE]>>8, 0 ;EX DE, HL
defb 0x08, 0xFF, 0x00, 0x00, 1, [dasm_08], [dasm_08]>>8, 0 ;EX AF, AF
defb 0xD9, 0xFF, 0x00, 0x00, 1, [dasm_D9], [dasm_D9]>>8, 0 ;EXX
defb 0xE3, 0xFF, 0x00, 0x00, 1, [dasm_E3], [dasm_E3]>>8, 0 ;EX (SP), HL
defb 0xDD, 0xFF, 0xE3, 0xFF, 2, [dasm_DD_E3], [dasm_DD_E3]>>8, 0 ;EX (SP), IX
defb 0xFD, 0xFF, 0xE3, 0xFF, 2, [dasm_FD_E3], [dasm_FD_E3]>>8, 0 ;EX (SP), IY
defb 0xED, 0xFF, 0xA0, 0xFF, 2, [dasm_ED_A0], [dasm_ED_A0]>>8, 0 ;LDI
defb 0xED, 0xFF, 0xB0, 0xFF, 2, [dasm_ED_B0], [dasm_ED_B0]>>8, 0 ;LDIR
defb 0xED, 0xFF, 0xA8, 0xFF, 2, [dasm_ED_A8], [dasm_ED_A8]>>8, 0 ;LDD
defb 0xED, 0xFF, 0xB8, 0xFF, 2, [dasm_ED_B8], [dasm_ED_B8]>>8, 0 ;LDDR
defb 0xED, 0xFF, 0xA1, 0xFF, 2, [dasm_ED_A1], [dasm_ED_A1]>>8, 0 ;CPI
defb 0xED, 0xFF, 0xB1, 0xFF, 2, [dasm_ED_B1], [dasm_ED_B1]>>8, 0 ;CPIR
defb 0xED, 0xFF, 0xA9, 0xFF, 2, [dasm_ED_A9], [dasm_ED_A9]>>8, 0 ;CPD
defb 0xED, 0xFF, 0xB9, 0xFF, 2, [dasm_ED_B9], [dasm_ED_B9]>>8, 0 ;CPDR
;JUMP Group
defb 0xC3, 0xFF, 0x00, 0x00, 3, [dasm_C3], [dasm_C3]>>8,1, 0x01 ;JP nn
defb 0xC2, 0xC7, 0x00, 0x00, 3, [dasm_C3], [dasm_C3]>>8,3, 0x02, 0x80, 0x01 ;JP cc,nn
defb 0x18, 0xFF, 0x00, 0x00, 2, [dasm_18], [dasm_18]>>8,1, 0x03 ;JR e
defb 0x38, 0xFF, 0x00, 0x00, 2, [dasm_38], [dasm_38]>>8,1, 0x03 ;JR C,e
defb 0x30, 0xFF, 0x00, 0x00, 2, [dasm_30], [dasm_30]>>8,1, 0x03 ;JR NC,e
defb 0x28, 0xFF, 0x00, 0x00, 2, [dasm_28], [dasm_28]>>8,1, 0x03 ;JR Z,e
defb 0x20, 0xFF, 0x00, 0x00, 2, [dasm_20], [dasm_20]>>8,1, 0x03 ;JR NZ,e
defb 0xE9, 0xFF, 0x00, 0x00, 2, [dasm_E9], [dasm_E9]>>8,0 ;JP (HL)
defb 0xDD, 0xFF, 0xE9, 0xFF, 2, [dasm_DD], [dasm_DD]>>8,0 ;JP (IX)
defb 0xFD, 0xFF, 0xE9, 0xFF, 2, [dasm_FD], [dasm_FD]>>8,0 ;JP (IY)
defb 0x10, 0xFF, 0x00, 0x00, 2, [dasm_10], [dasm_10]>>8,1, 0x03 ;DJNZ, e
;Call and Return Group
defb 0xCD, 0xFF, 0x00, 0x00, 3, [dasm_CD], [dasm_CD]>>8,1, 0x01 ;CALL nn
defb 0xC4, 0xC7, 0x00, 0x00, 3, [dasm_CD], [dasm_CD]>>8,2, 0x02, 0x01 ;CALL cc,nn
defb 0xC9, 0xFF, 0x00, 0x00, 1, [dasm_C9], [dasm_C9]>>8,0 ;RET
defb 0xC0, 0xC7, 0x00, 0x00, 1, [dasm_C9], [dasm_C9]>>8,1, 0x02 ;RET cc
defb 0xED, 0xFF, 0x4D, 0xFF, 2, [dasm_ED_4D], [dasm_ED_4D]>>8,0 ;RETI
defb 0xED, 0xFF, 0x45, 0xFF, 2, [dasm_ED_45], [dasm_ED_45]>>8,0 ;RETN
defb 0xC7, 0xC7, 0x00, 0x00, 1, [dasm_FF], [dasm_FF]>>8,1, 0x05 ;RST
;8-Bit load group
defb 0x0A, 0xFF, 0x00, 0x00, 1, [dasm_0A], [dasm_0A]>>8, 0 ;LD A, (BC)
defb 0x1A, 0xFF, 0x00, 0x00, 1, [dasm_1A], [dasm_1A]>>8, 0 ;LD A, (DE)
defb 0x3A, 0xFF, 0x00, 0x00, 3, [dasm_3A], [dasm_3A]>>8, 2, 0x09, 0x80 ;LD A, (nn)
defb 0x02, 0xFF, 0x00, 0x00, 1, [dasm_02], [dasm_02]>>8, 0 ;LD (BC), A
defb 0x12, 0xFF, 0x00, 0x00, 1, [dasm_12], [dasm_12]>>8, 0 ;LD (DE), A
defb 0x32, 0xFF, 0x00, 0x00, 3, [dasm_32], [dasm_32]>>8, 2, 0x09, 0x80 ;LD (nn), A
defb 0xED, 0xFF, 0x57, 0xFF, 2, [dasm__ED_57], [dasm__ED_57]>>8, 0 ;LD A, I
defb 0xED, 0xFF, 0x5F, 0xFF, 2, [dasm__ED_5F], [dasm__ED_5F]>>8, 0 ;LD A, R
defb 0xED, 0xFF, 0x47, 0xFF, 2, [dasm__ED_47], [dasm__ED_47]>>8, 0 ;LD I, A
defb 0xED, 0xFF, 0x4F, 0xFF, 2, [dasm__ED_4F], [dasm__ED_4F]>>8, 0 ;LD R, A
defb 0x06, 0xC7, 0x00, 0x00, 2, [dasm__LD], [dasm__LD]>>8, 2, 0x06, 0x08 ;LD r, n
defb 0x40, 0xC0, 0x00, 0x00, 1, [dasm__LD], [dasm__LD]>>8, 2, 0x06, 0x07 ;LD r, r' / LD r, (HL) / LD (HL), r
;8-Bit Arithmetic Group
defb 0x80, 0xF8, 0x00, 0x00, 1, [dasm_80C6], [dasm_80C6]>>8, 1, 0x07 ;ADD A, r / ADD A, (HL)
defb 0xC6, 0xFF, 0x00, 0x00, 2, [dasm_80C6], [dasm_80C6]>>8, 1, 0x08 ;ADD A, n
defb 0xDD, 0xFF, 0x86, 0xFF, 3, [dasm_DD_86], [dasm_DD_86]>>8, 2, 0x08, 0x80 ;ADD A, (IX + d)
defb 0xFD, 0xFF, 0x86, 0xFF, 3, [dasm_FD_86], [dasm_FD_86]>>8, 2, 0x08, 0x80 ;ADD A, (IY + d)
defb 0xC8, 0xF8, 0x00, 0x00, 1, [dasm_C88E], [dasm_C88E]>>8, 1, 0x07 ;ADC A, r / ADC A, (HL)
defb 0x8E, 0xF8, 0x00, 0x00, 2, [dasm_C88E], [dasm_C88E]>>8, 1, 0x08 ;ADC A, n
defb 0xDD, 0xFF, 0x8E, 0xFF, 3, [dasm_DD_8E], [dasm_DD_8E]>>8, 2, 0x08, 0x80 ;ADC A, (IX + d)
defb 0xFD, 0xFF, 0x8E, 0xFF, 3, [dasm_FD_8E], [dasm_FD_8E]>>8, 2, 0x08, 0x80 ;ADC A, (IY + d)
defb 0x90, 0xF8, 0x00, 0x00, 1, [dasm__SUB], [dasm__SUB]>>8, 1, 0x07 ;SUB r / SUB A, (HL)
defb 0xD6, 0xFF, 0x00, 0x00, 2, [dasm__SUB], [dasm__SUB]>>8, 1, 0x08 ;SUB n
defb 0xDD, 0xFF, 0x96, 0xFF, 3, [dasm_DD_96], [dasm_DD_96]>>8, 2, 0x08, 0x80 ;SUB (IX + d)
defb 0xFD, 0xFF, 0x96, 0xFF, 3, [dasm_FD_96], [dasm_FD_96]>>8, 2, 0x08, 0x80 ;SUB (IY + d)
defb 0x94, 0xF8, 0x00, 0x00, 1, [dasm__SBC], [dasm__SBC]>>8, 1, 0x07 ;SBC A,r / SBC A, (HL)
defb 0xDE, 0xFF, 0x00, 0x00, 2, [dasm__SBC], [dasm__SBC]>>8, 1, 0x08 ;SBC A,n
defb 0xDD, 0xFF, 0x9E, 0xFF, 3, [dasm_DD_9E], [dasm_DD_9E]>>8, 2, 0x08, 0x80 ;SBC A,(IX + d)
defb 0xFD, 0xFF, 0x9E, 0xFF, 3, [dasm_FD_9E], [dasm_FD_9E]>>8, 2, 0x08, 0x80 ;SBC A,(IY + d)
defb 0xA0, 0xF8, 0x00, 0x00, 1, [dasm__AND], [dasm__AND]>>8, 1, 0x07 ;AND A,r / AND A, (HL)
defb 0xE6, 0xFF, 0x00, 0x00, 2, [dasm__AND], [dasm__AND]>>8, 1, 0x08 ;AND A,n
defb 0xDD, 0xFF, 0xA6, 0xFF, 3, [dasm_DD_A6], [dasm_DD_A6]>>8, 2, 0x08, 0x80 ;AND A,(IX + d)
defb 0xFD, 0xFF, 0xA6, 0xFF, 3, [dasm_FD_A6], [dasm_FD_A6]>>8, 2, 0x08, 0x80 ;AND A,(IY + d)
defb 0xB0, 0xF8, 0x00, 0x00, 1, [dasm__OR], [dasm__OR]>>8, 1, 0x07 ;OR A,r / OR A, (HL)
defb 0xF6, 0xFF, 0x00, 0x00, 2, [dasm__OR], [dasm__OR]>>8, 1, 0x08 ;OR A,n
defb 0xDD, 0xFF, 0xB6, 0xFF, 3, [dasm_DD_B6], [dasm_DD_B6]>>8, 2, 0x08, 0x80 ;OR A,(IX + d)
defb 0xFD, 0xFF, 0xB6, 0xFF, 3, [dasm_FD_B6], [dasm_FD_B6]>>8, 2, 0x08, 0x80 ;OR A,(IY + d)
defb 0xA8, 0xF8, 0x00, 0x00, 1, [dasm__XOR], [dasm__XOR]>>8, 1, 0x07 ;XOR A,r / XOR A, (HL)
defb 0xEE, 0xFF, 0x00, 0x00, 2, [dasm__XOR], [dasm__XOR]>>8, 1, 0x08 ;XOR A,n
defb 0xDD, 0xFF, 0xAE, 0xFF, 3, [dasm_DD_AE], [dasm_DD_AE]>>8, 2, 0x08, 0x80 ;XOR A,(IX + d)
defb 0xFD, 0xFF, 0xAE, 0xFF, 3, [dasm_FD_AE], [dasm_FD_AE]>>8, 2, 0x08, 0x80 ;XOR A,(IY + d)
defb 0xB8, 0xF8, 0x00, 0x00, 1, [dasm__CP], [dasm__CP]>>8, 1, 0x07 ;CP A,r / CP A, (HL)
defb 0xFE, 0xFF, 0x00, 0x00, 2, [dasm__CP], [dasm__CP]>>8, 1, 0x08 ;CP A,n
defb 0xDD, 0xFF, 0xBE, 0xFF, 3, [dasm_DD_BE], [dasm_DD_BE]>>8, 2, 0x08, 0x80 ;CP A,(IX + d)
defb 0xFD, 0xFF, 0xBE, 0xFF, 3, [dasm_FD_BE], [dasm_FD_BE]>>8, 2, 0x08, 0x80 ;CP A,(IY + d)
defb 0x04, 0xC7, 0x00, 0x00, 1, [dasm__INC], [dasm__INC]>>8, 1, 0x10 ;INC r / INC (HL)
defb 0xDD, 0xFF, 0x34, 0xFF, 3, [dasm_DD_34], [dasm_DD_34]>>8, 2, 0x08, 0x80 ;INC (IX + d)
defb 0xFD, 0xFF, 0x34, 0xFF, 3, [dasm_FD_34], [dasm_FD_34]>>8, 2, 0x08, 0x80 ;INC (IY + d)
defb 0x05, 0xC7, 0x00, 0x00, 1, [dasm__DEC], [dasm__DEC]>>8, 1, 0x10 ;DEC r / DEC (HL)
defb 0xDD, 0xFF, 0x35, 0xFF, 3, [dasm_DD_35], [dasm_DD_35]>>8, 2, 0x08, 0x80 ;DEC (IX + d)
defb 0xFD, 0xFF, 0x35, 0xFF, 3, [dasm_FD_35], [dasm_FD_35]>>8, 2, 0x08, 0x80 ;DEC (IY + d)
;16-Bit Arithmetic Group
defb 0x09, 0xCF, 0x00, 0x00, 1, [dasm_09], [dasm_09]>>8, 1, 0x11 ;ADD HL, ss
defb 0xED, 0xFF, 0x4A, 0xCF, 2, [dasm_ED_4A], [dasm_ED_4A]>>8, 1, 0x12 ;ADC HL, ss
defb 0xED, 0xFF, 0x42, 0xCF, 2, [dasm_ED_42], [dasm_ED_42]>>8, 1, 0x12 ;SBC HL, ss
defb 0xDD, 0xFF, 0x09, 0xCF, 2, [dasm_DD_09], [dasm_DD_09]>>8, 1, 0x12 ;ADD IX, ss
defb 0xFD, 0xFF, 0x09, 0xCF, 2, [dasm_FD_09], [dasm_FD_09]>>8, 1, 0x12 ;ADD IY, ss
defb 0x03, 0xCF, 0x00, 0x00, 1, [dasm_03], [dasm_03]>>8, 1, 0x11 ;INC ss
defb 0xDD, 0xFF, 0x23, 0xFF, 2, [dasm_DD_23], [dasm_DD_23]>>8, 0 ;INC IX
defb 0xFD, 0xFF, 0x23, 0xFF, 2, [dasm_FD_23], [dasm_FD_23]>>8, 0 ;INC IY
defb 0x0B, 0xCF, 0x00, 0x00, 1, [dasm_0B], [dasm_0B]>>8, 1, 0x11 ;DEC ss
defb 0xDD, 0xFF, 0x2B, 0xFF, 2, [dasm_DD_2B], [dasm_DD_2B]>>8, 0 ;DEC IX
defb 0xFD, 0xFF, 0x2B, 0xFF, 2, [dasm_FD_2B], [dasm_FD_2B]>>8, 0 ;DEC IY
;16-Bit Load Group
defb 0x01, 0xCF, 0x00, 0x00, 3, [dasm_01], [dasm_01]>>8, 3, 0x11, 0x80, 0x09 ;LD dd, nn
defb 0xDD, 0xFF, 0x21, 0xFF, 4, [dasm_DD_01], [dasm_DD_01]>>8, 1, 0x0A ;LD IX, nn
defb 0xFD, 0xFF, 0x21, 0xFF, 4, [dasm_FD_01], [dasm_FD_01]>>8, 1, 0x0A ;LD IY, nn
defb 0x2A, 0xFF, 0x00, 0x00, 3, [dasm_2A], [dasm_2A]>>8, 2, 0x09, 0x80 ;LD HL, (nn)
defb 0xED, 0xFF, 0x4B, 0xCF, 4, [dasm_ED_4B], [dasm_ED_4B]>>8, 4, 0x12, 0x80, 0x0A, 0x81 ;LD dd, (nn)
defb 0xDD, 0xFF, 0x2A, 0xFF, 4, [dasm_DD_2A], [dasm_DD_2A]>>8, 1, 0x0A ;LD IX, (nn)
defb 0xFD, 0xFF, 0x2A, 0xFF, 4, [dasm_FD_2A], [dasm_FD_2A]>>8, 1, 0x0A ;LD IY, (nn)
defb 0x22, 0xFF, 0x00, 0x00, 3, [dasm_22], [dasm_22]>>8, 2, 0x0A, 0x80 ;LD (nn), HL
defb 0xED, 0xFF, 0x43, 0xCF, 4, [dasm_ED_43], [dasm_ED_43]>>8, 3, 0x0A, 0x80, 0x12 ;LD (nn), dd
defb 0xDD, 0xFF, 0x22, 0xCF, 4, [dasm_DD_22], [dasm_DD_22]>>8, 2, 0x0A, 0x80 ;LD (nn), IX
defb 0xFD, 0xFF, 0x22, 0xCF, 4, [dasm_FD_22], [dasm_FD_22]>>8, 2, 0x0A, 0x80 ;LD (nn), IY
defb 0xF9, 0xFF, 0x00, 0x00, 1, [dasm_F9], [dasm_F9]>>8, 0 ;LD SP, HL
defb 0xDD, 0xFF, 0xF9, 0xFF, 2, [dasm_DD_F9], [dasm_DD_F9]>>8, 0 ;LD SP, IX
defb 0xFD, 0xFF, 0xF9, 0xFF, 2, [dasm_FD_F9], [dasm_FD_F9]>>8, 0 ;LD SP, IY
defb 0xC5, 0xCF, 0x00, 0x00, 1, [dasm_E5], [dasm_E5]>>8, 1, 0x13 ;PUSH qq
defb 0xDD, 0xFF, 0xE5, 0xFF, 2, [dasm_DD_E5], [dasm_DD_E5]>>8, 0 ;PUSH IX
defb 0xFD, 0xFF, 0xE5, 0xFF, 2, [dasm_FD_E5], [dasm_FD_E5]>>8, 0 ;PUSH IY
defb 0xC1, 0xCF, 0x00, 0x00, 1, [dasm_E1], [dasm_E1]>>8, 1, 0x13 ;POP qq
defb 0xDD, 0xFF, 0xE1, 0xFF, 2, [dasm_DD_E1], [dasm_DD_E1]>>8, 0 ;POP IX
defb 0xFD, 0xFF, 0xE1, 0xFF, 2, [dasm_FD_E1], [dasm_FD_E1]>>8, 0 ;POP IY
dasm_00: db "NOP",0x00
;JUMP Group
dasm_C3: db "JP ",0x00,", ",0x00
dasm_18: db "JR ",0x00
dasm_38: db "JR C, ",0x00
dasm_30: db "JR NC, ",0x00
dasm_28: db "JR Z, ",0x00
dasm_20: db "JR NZ, ",0x00
dasm_E9: db "JP (HL) ",0x00
dasm_DD: db "JP (IX) ",0x00
dasm_FD: db "JP (IY) ",0x00
dasm_10: db "DJNZ ",0x00
;Call and Return Group
dasm_CD: db "CALL ",0x00
dasm_C9: db "RET ",0x00
dasm_ED_4D: db "RETI",0x00
dasm_ED_45: db "RETN",0x00
dasm_FF: db "RST ",0x00
;8-Bit load group
dasm_0A: db "LD A,(BC)",0x00
dasm_1A: db "LD A,(DE)",0x00
dasm_3A: db "LD A,(",0x00, "h)",0x00
dasm_02: db "LD (BC), A",0x00
dasm_12: db "LD (DE), A",0x00
dasm_32: db "LD (",0x00, "h), A",0x00
dasm__LD: db "LD ",0x00
dasm__ED_57: db "LD A, I",0x00
dasm__ED_5F: db "LD A, R",0x00
dasm__ED_47: db "LD I, A",0x00
dasm__ED_4F: db "LD R, A",0x00
;General-Purpose Arithmetic and CPU Control Groups
dasm_27: db "DAA",0x00
dasm_2F: db "CPL",0x00
dasm_ED_44: db "NEG",0x00
dasm_3F: db "CCF",0x00
dasm_37: db "SCF",0x00
dasm_76: db "HALT",0x00
dasm_F3: db "DI",0x00
dasm_FB: db "EI",0x00
dasm_ED_46: db "IM 0",0x00
dasm_ED_56: db "IM 1",0x00
dasm_ED_5E: db "IM 2",0x00
;Exchange, Block Transfer, and Search Group
dasm_BE: db "EX DE, HL",0x00
dasm_08: db "EX AF, AF",0x00
dasm_D9: db "EXX",0x00
dasm_E3: db "EX (SP), HL",0x00
dasm_DD_E3: db "EX (SP), IX",0x00
dasm_FD_E3: db "EX (SP), IY",0x00
dasm_ED_A0: db "LDI",0x00
dasm_ED_B0: db "LDIR",0x00
dasm_ED_A8: db "LDD",0x00
dasm_ED_B8: db "LDDR",0x00
dasm_ED_A1: db "CPI",0x00
dasm_ED_B1: db "CPIR",0x00
dasm_ED_A9: db "CPD",0x00
dasm_ED_B9: db "CPDR",0x00
;8-Bit Arithmetic Group
dasm_80C6: db "ADD A, ", 0x00
dasm_DD_86: db "ADD A, (IX+", 0x00, "h)",0x00
dasm_FD_86: db "ADD A, (IY+", 0x00, "h)",0x00
dasm_C88E: db "ADC A, ", 0x00
dasm_DD_8E: db "ADC A, (IX+", 0x00, "h)",0x00
dasm_FD_8E: db "ADC A, (IY+", 0x00, "h)",0x00
dasm__SUB: db "SUB ", 0x00
dasm_DD_96: db "SUB (IX+", 0x00, "h)",0x00
dasm_FD_96: db "SUB (IY+", 0x00, "h)",0x00
dasm__SBC: db "SBC A, ", 0x00
dasm_DD_9E: db "SBC A,(IX+", 0x00, "h)",0x00
dasm_FD_9E: db "SBC A,(IY+", 0x00, "h)",0x00
dasm__AND: db "AND ", 0x00
dasm_DD_A6: db "AND (IX+", 0x00, "h)",0x00
dasm_FD_A6: db "AND (IY+", 0x00, "h)",0x00
dasm__OR: db "OR ", 0x00
dasm_DD_B6: db "OR (IX+", 0x00, "h)",0x00
dasm_FD_B6: db "OR (IY+", 0x00, "h)",0x00
dasm__XOR: db "XOR ", 0x00
dasm_DD_AE: db "XOR (IX+", 0x00, "h)",0x00
dasm_FD_AE: db "XOR (IY+", 0x00, "h)",0x00
dasm__CP: db "CP ", 0x00
dasm_DD_BE: db "CP (IX+", 0x00, "h)",0x00
dasm_FD_BE: db "CP (IY+", 0x00, "h)",0x00
dasm__INC: db "INC ", 0x00
dasm_DD_34: db "INC (IX+", 0x00, "h)",0x00
dasm_FD_34: db "INC (IY+", 0x00, "h)",0x00
dasm__DEC: db "DEC ", 0x00
dasm_DD_35: db "DEC (IX+", 0x00, "h)",0x00
dasm_FD_35: db "DEC (IY+", 0x00, "h)",0x00
;16-Bit Arithmetic Group
dasm_09: db "ADD HL, ",0x00
dasm_ED_4A: db "ADC HL, ",0x00
dasm_ED_42: db "SBC HL, ",0x00
dasm_DD_09: db "ADD IX, ",0x00
dasm_FD_09: db "ADD IY, ",0x00
dasm_03: db "INC ",0x00
dasm_DD_23: db "INC IX, ",0x00
dasm_FD_23: db "INC IY, ",0x00
dasm_0B: db "DEC ",0x00
dasm_DD_2B: db "DEC IX, ",0x00
dasm_FD_2B: db "DEC IY, ",0x00
;16-Bit Load Group
dasm_01: db "LD ",0x00, ", ",0x00
dasm_DD_01: db "LD IX, ",0x00
dasm_FD_01: db "LD IY, ",0x00
dasm_2A: db "LD HL, (",0x00,"h)",0x00
dasm_ED_4B: db "LD ",0x00,", (",0x00,"h)",0x00
dasm_DD_2A: db "LD IX, (",0x00,"h)",0x00
dasm_FD_2A: db "LD IY, (",0x00,"h)",0x00
dasm_22: db "LD (",0x00,"h), HL",0x00
dasm_ED_43: db "LD (",0x00,"h), ",0x00
dasm_DD_22: db "LD (",0x00,"h), IX",0x00
dasm_FD_22: db "LD (",0x00,"h), IY",0x00
dasm_F9: db "LD SP, HL",0x00
dasm_DD_F9: db "LD SP, IX",0x00
dasm_FD_F9: db "LD SP, IY",0x00
dasm_E5: db "PUSH ",0x00
dasm_DD_E5: db "PUSH IX",0x00
dasm_FD_E5: db "PUSH IY",0x00
dasm_E1: db "PUSH ",0x00
dasm_DD_E1: db "PUSH IX",0x00
dasm_FD_E1: db "PUSH IY",0x00
;Misc
dasm_UU: db ".?.",0x00
dasm_UW: db " ",0x00
dasm_printFlags_table:
db "NZ"
db "Z",0
db "NC"
db "C",0
db "PO"
db "PE"
db "P",0
db "M",0
dasm_printRegister8_table:
db "B"
db "C"
db "D"
db "E"
db "H"
db "L"
db "S" ;only 18 bit (SP)
db "P" ;only 18 bit (SP)
dasm_printRegisterIX_table:
db "BC"
db "DE"
db "IX"
db "SP"
dasm_printRegisterIY_table:
db "BC"
db "DE"
db "IY"
db "SP"
dasm_printRegisterSP_table:
db "BC"
db "DE"
db "HL"
db "AF"
dasm_printRegister8_table_HL:
db "(HL)", 0

View File

@@ -0,0 +1,158 @@
;----------------------------------------------------------------
;Keyboard input library for Z8C
;by Dennis Gunia (04/2022)
;----------------------------------------------------------------
var_ps2_extension equ var_ps2mem+4 ;extension code
var_ps2_shift equ var_ps2mem+5 ;shift down = 0xFF, up = 0x00
var_ps2_raw equ var_ps2mem+6 ;raw scan code
keybd_read:
xor a
ld (var_ps2_extension), a
call keybd_read_wait
cp 0xE0
jr z, keybd_read_extended ;handle extended scancodes
cp 0xE1
jr z, keybd_read_extended_E1 ;handle extended scancodes for stupid pause button ....
;else fall through to keybd_read_simple
keybd_read_simple:
cp 0xF0 ;check if break
jr z, keybd_read_break ;handle break code logic
cp 0x12
jr z, keybd_shift_down
cp 0x59
jr z, keybd_shift_down
;else process key
jr keybd_read_return
keybd_read_extended:
ld (var_ps2_extension), a ;store first byte to ram
call keybd_read_wait ;read key
cp 0xF0 ;check if break
jr z, keybd_read_break_extended ;handle break code logic
;else process key
jr keybd_read_return
keybd_read_extended_E1: ;pause key
call keybd_read_wait ;read realeased key
call keybd_read_wait ;read realeased key
call keybd_read_wait ;read realeased key
call keybd_read_wait ;read realeased key
call keybd_read_wait ;read realeased key
call keybd_read_wait ;read realeased key
;fall-thorugh for last byte
keybd_read_break_extended:
call keybd_read_wait ;read realeased key
jr keybd_read
keybd_read_break:
call keybd_read_wait ;read realeased key
cp 0x12
jr z, keybd_shift_up
cp 0x59
jr z, keybd_shift_up
jp keybd_read
keybd_read_return:
;a contains scan code
ret
keybd_shift_down:
ld a,0x01
ld (var_ps2_shift),a
jr keybd_read
keybd_shift_up:
xor a
ld (var_ps2_shift),a
jr keybd_read
;wait for keyboard input
keybd_read_wait:
call keyboard_read
jr z, keybd_read_wait ;read again if error
ret
keybd_read_ascii:
call keybd_read
;push af
;call print_a_hex
;pop af
ld ix, [keybd_lut] ;LUT base address
ld bc, 4 ;increments
ld d, a ;Load scancode into d
keybd_read_ascii_seekloop:
ld a, (ix) ;load scancode from table
or a ;test if scancode is 0x00 -> indicates end of list
jr z, keybd_read_ascii_notfound ;reached end of list wizhout match
cp d ;compare scancode
jr z, keybd_read_ascii_match ;found entry
add ix,bc
jr keybd_read_ascii_seekloop
keybd_read_ascii_match:
ld b,0
ld a, (var_ps2_shift) ;if shift offset+1
inc a ;add ofset for column1
ld c,a
add ix,bc ;add column address to row address
ld a,(ix)
ret
keybd_read_ascii_notfound:
jr keybd_read_ascii
keybd_lut:
defb 0x1C, "a", "A", "@"
defb 0x32, "b", "B", 0x00
defb 0x21, "c", "C", 0x00
defb 0x23, "d", "D", 0x00
defb 0x24, "e", "E", 0x00
defb 0x2B, "f", "F", 0x00
defb 0x34, "g", "G", 0x00
defb 0x33, "h", "H", 0x00
defb 0x43, "i", "I", 0x00
defb 0x3B, "j", "J", 0x00
defb 0x42, "k", "K", 0x00
defb 0x4B, "l", "L", 0x00
defb 0x3A, "m", "M", 0x00
defb 0x31, "n", "N", 0x00
defb 0x44, "o", "O", 0x00
defb 0x4D, "p", "P", 0x00
defb 0x15, "q", "Q", 0x00
defb 0x2D, "r", "R", 0x00
defb 0x1B, "s", "S", 0x00
defb 0x2C, "t", "T", 0x00
defb 0x3C, "u", "U", 0x00
defb 0x2A, "v", "V", 0x00
defb 0x1D, "w", "W", 0x00
defb 0x22, "x", "X", 0x00
defb 0x1A, "y", "Y", 0x00
defb 0x35, "z", "Z", 0x00
defb 0x45, "0", "=", "}"
defb 0x16, "1", "!", 0x00
defb 0x1E, "2", 0x22, 0x00
defb 0x26, "3", "3", 0x00
defb 0x25, "4", "$", 0x00
defb 0x2E, "5", "%", 0x00
defb 0x36, "6", "&", 0x00
defb 0x3D, "7", "/", "{"
defb 0x3E, "8", "(", "["
defb 0x46, "9", ")", "]"
defb 0x41, ",", ";", 0x00
defb 0x49, ".", ":", 0x00
defb 0x4A, "-", "_", 0x00
defb 0x5D, "#", "'", 0x00
defb 0x5B, "+", "*", "~"
defb 0x4E, "s", "?", 0x5C
defb 0x61, "<", ">", "|"
defb 0x5A, 13, 13, 13 ;enter
defb 0x66, 0x08, 0x08, 0x08 ;backspace
defb 0x29, " ", " ", 0x00 ;space
defb 0x00 ;end of LUT

View File

@@ -0,0 +1,16 @@
; a contains data
; bc destroied
; carry is set if odd, reset if even
calc_parity:
ld c,0 ;parity data
ld b,8 ;bit counter
calc_parity_loop:
rrca
jr nc,calc_parity_loop_2 ;if not zero then skip increment
inc c
calc_parity_loop_2:
djnz calc_parity_loop
ld a,c
rra ;carry is set to bit 0 of high-counter.
;if bit1 is set -> odd # of 1s else even # of 1s
ret

View File

@@ -0,0 +1,22 @@
EXEC_RST_08:
call print_char
ret
EXEC_RST_10:
push bc
push de
push hl
;call vdp_cursor_on
call read_char
push af
;call vdp_cursor_off
pop af
pop hl
pop de
pop bc
ret
EXEC_RST_18:
ld a,0
ret

View File

@@ -0,0 +1,96 @@
;----------------------------------------------------------------
;Keyboard interface driver for Z8C
;Controller used: vt82c42
;Datasheet: http://www.s100computers.com/My%20System%20Pages/MSDOS%20Board/vt82c42%20PC%20Keyboard%20conrtroller.pdf
;by Dennis Gunia (04/2022)
;----------------------------------------------------------------
;IO Ports
CS_VT82C42_DATA .EQU F0h
CS_VT82C42_CTRL .EQU F1h
keyboard_init_io: ;Subroutine for initializing keyboard controller
LD A, A7h ;Disable Mouse
OUT (CS_VT82C42_CTRL), A
LD A, ADh ;Disable Keyboard
OUT (CS_VT82C42_CTRL), A
_keyboard_init_flush_buffer:
IN A,(CS_VT82C42_DATA) ;Read buffer
IN A,(CS_VT82C42_CTRL) ;Read status byte
BIT 0,A ;Test if buffer is empty
JR Z, _keyboard_init_flush_buffer
;buffer is now flushed. Now set the Controller Configuration Byte
IN A,(CS_VT82C42_CTRL) ;Disable bits 0,1,6 (disablee IRQ and Translation)
AND 10111100
OUT (CS_VT82C42_CTRL),A
;Perform Controller Self Test
LD A, AAh
OUT (CS_VT82C42_CTRL), A
NOP
IN A,(CS_VT82C42_CTRL) ;Check results
CP 55h
JR NZ, keyboard_init_failed
;Perform Interface Tests
LD A, ABh
OUT (CS_VT82C42_CTRL), A
NOP
IN A,(CS_VT82C42_CTRL) ;Check results
CP 00h
JR NZ, _keyboard_init_failed
;Enable Devices
LD A,AEh
OUT (CS_VT82C42_CTRL), A
;Reset Devices
LD A,FFh
OUT (CS_VT82C42_DATA), A ;Send reset to keboard (0xFF command)
NOP
IN A,(CS_VT82C42_CTRL) ;Read status byte
BIT 0,A ;Test if buffer is empty -> no keyboard found
JP NZ, _keyboard_init_dev_missing
CP A, 0xFC
JR Z, _keyboard_init_okay ; 0xFC -> Success. Init done!
;Else device error
LD HL, [STR_keyboard_init_failed]
CALL print_str
HALT
_keyboard_init_failed:
LD HL, [STR_keyboard_init_err]
CALL print_str
HALT
_keyboard_init_dev_missing:
LD HL, [STR_keyboard_init_missing]
CALL print_str
HALT
_keyboard_init_okay:
LD HL, [STR_keyboard_init_okay]
CALL print_str
RET
;Keyboard IO functions
keyboard_read:
IN A,(CS_VT82C42_CTRL) ;Read status byte
BIT 0,A ;Test if buffer is empty
RET NZ ;Return if empty
IN A,(CS_VT82C42_DATA)
RET ;Return with data in A
keyboard_write:
PUSH AF
_keyboard_write_wait:
IN A,(CS_VT82C42_CTRL) ;Read status byte
BIT 1,A ;Test if buffer is full
JR Z, _keyboard_write_wait ;Wait if input buffer is full
POP AF
OUT (CS_VT82C42_DATA), A
RET
;Status message strings
STR_keyboard_init_okay:
.BYTE "PS/2 Keyboard initialized.",0
STR_keyboard_init_err:
.BYTE "PS/2 Controller error! System HALT!",0
STR_keyboard_init_failed:
.BYTE "PS/2 Keyboard error! System HALT!",0
STR_keyboard_init_missing:
.BYTE "PS/2 no keyboard found!",0

View File

@@ -0,0 +1,286 @@
;-------------------------------------------------------------------------
; Z80 XMODEM implementation by Dennis Gunia
; 2022 - www,dennisgunia.de
;
; important doc: https://web.mit.edu/6.115/www/amulet/xmodem.htm
; http://www.blunk-electronic.de/train-z/pdf/xymodem.pdf
;-------------------------------------------------------------------------
;Symbols
SYM_SOH equ 0x01
SYM_EOT equ 0x04
SYM_ACK equ 0x06
SYM_NAK equ 0x15
SYM_ETB equ 0x17
SYM_CAN equ 0x18
SYM_C equ 0x43
;Memory locations
MEM_VAR_BLOCK equ 0x40FB ;last block
MEM_VAR_TIMEA equ 0x40FC ;timer var (mills)
MEM_VAR_TIMER equ 0x40FE ;timer var (seconds)
MEM_INT_VEC_T equ 0x40FE ;interrupt vector table
MEM_LOC_LOAD equ 0x4400 ;load location for program
;XMODEM routine
xmodem_init:
call A_RTS_OFF
LD A,10100111b ; Init CTC Channel 3
OUT (CS_CTC_2),A
LD A,14 ; 1028.57Hz ISR
OUT (CS_CTC_2),A
LD A,00h ; Set CTC Ch3 Interrupt Vector
OUT (CS_CTC_0),A
;load int vector to ram
ld hl,xmodem_int ;CTC Ch3 INT routine
ld (0x4200 + 0x04),hl
;reset timer vars
ld hl,0x0000
ld (MEM_VAR_TIMEA),hl
ld (MEM_VAR_TIMER),hl
ld a,0x42 ; Set interrupt vector register
ld i,a
im 2 ; Z80 Interrupt mode
ld hl,MSG_START ; Print start banner
call print_str
ei ; Enable interrupts
; init done. Continue with xmodem_await_conn
call xmodem_wait
xmodem_await_conn: ;Wait for initial connection
ld a, SYM_C ;Send C to notify sender, that we want CRC
call xmodem_out
call xmodem_read_wait ;Read with timeout
jp c, xmodem_await_conn ;Carry flag set = timeout -> repeat
;else continue
xmodem_packet: ;XmodemCRC packet start
;use 1st byte to decide further processing
cp SYM_EOT ;End of Transmission
jp z, xmodem_packet_EOT
cp SYM_CAN ;Cancel (Force receiver to start sending C's)
jp z, xmodem_await_conn
cp SYM_SOH ;Start of
jp z, xmodem_packet_get
jp xmodem_err ;anything else is an error -> abort transmission
xmodem_packet_get: ;if first byte == SYM_SOH -> receive block
call xmodem_read_wait ;get byte 2 => block ID
jp c, xmodem_nak
ld b,a
ld (MEM_VAR_BLOCK), a ;store block id to memory
call xmodem_read_wait ;get byte 3 => block ID complement
jp c, xmodem_nak
add b
cp 255 ;both size infos should always sum to 255
jp nz,xmodem_err ;if not 255 then its an error
;calculate block start address in RAM
;multiply by 128
;use more efficient bit-wise operations
dec a ;a-1 to remove 1 sector offset
ld a,b
rra ;shift 1 bit to the right
and 0x7F
ld h,a
ld a,b
dec a ;a-1 to remove 1 sector offset
rrca ;shift bit0 to bit 7
and 0x80 ;mask out all other bits
ld l,a
;result:
;hl = 0aaaaaaa a000000
ld de,MEM_LOC_LOAD
add hl,de ;add calculated offset to base address
;hl now contains the true start address of this sector
ld b,128 ;preload counter for data baytes
ld c,0 ;packet length counter ( used for overflow error )
xmodem_packet_get_data: ;get 128 data bytes (loop)
push hl ;push hl onto stack because xmodem_read_wait destroys hl
call xmodem_read_wait ;read byte or timeout
jp c, xmodem_nak ;if timeout -> nak and retry
pop hl ;restore hl
ld (hl), a ;store received byte in memory
inc hl ;increment pointer
inc c ;increment packet length counter
dec b ;decerment data bytes remmaining
jp nz, xmodem_packet_get_data ;if bytes remaining, loop
;else continue with crc bytes
xmodem_packet_get_crc: ;get 16-Bit CRC
call xmodem_read_wait
jp c, xmodem_nak
ld d,a
inc c
call xmodem_read_wait
jp c, xmodem_nak
ld e,a
inc c
;de now contains CRC value
;check if c is not bigger than 130 byte (128 data + 2crc)
;TODO if so NACK
;de contains 16-bit CRC
;TODO if crc error NACK
jp xmodem_ack ;ack block -> then jump to start again
xmodem_packet_EOT: ;End of transmission SUB.
ld a, SYM_ACK ;Acknowledge EOT
call xmodem_out
jp xmodem_end ;and end xmodem
xmodem_err: ;non recoverable error -> abort
ld a, SYM_CAN
call xmodem_out
ld a, SYM_CAN
call xmodem_out
ld a, SYM_CAN
call xmodem_out
ld a, SYM_CAN
call xmodem_out
ld a, SYM_CAN
call xmodem_out
ld a, SYM_CAN
call xmodem_out
ld a, SYM_CAN
call xmodem_out
ld a, SYM_CAN
call xmodem_out
ld a, SYM_CAN
call xmodem_out
ld a, SYM_CAN
call xmodem_out
ld a, SYM_CAN
ld hl, MSG_ERROR
call print_str
;overflow to end
xmodem_end:
di ;disable interrupts
call print_newLine ;print new line
jp PROMPT_BEGIN ;return ti prompt
;isr is used as counter for timeouts
xmodem_int:
di ;setup ISR (disable further interrupts, exchange registers)
ex AF,AF'
exx
ld hl,(MEM_VAR_TIMEA) ;millis counter
inc hl
ld (MEM_VAR_TIMEA),hl
ld de,1028 ;every 1028 millis counter
sbc hl,de
jp nz, xmodem_int_cont ;if less than 1028 millis, loop
ld hl,0 ;reset millis
ld (MEM_VAR_TIMEA),hl
ld hl,(MEM_VAR_TIMER) ;incement seconds
inc hl
ld (MEM_VAR_TIMER),hl
xmodem_int_cont: ;end isr
ex AF,AF' ;restore registers
exx
EI ;enable interrupts
reti ;exit ISR
; A returns char
; Carry is set if timeout
xmodem_read_timeount equ 3 ;3 seconds timeout
xmodem_read_wait:
di
ld hl,0
ld (MEM_VAR_TIMEA),hl
ld (MEM_VAR_TIMER),hl
ei
call A_RTS_ON
xmodem_read_wait_loop:
;check timeout
ld hl,(MEM_VAR_TIMER)
ld a, l
cp xmodem_read_timeount
jp z, xmodem_read_wait_timeout ;if timeout retry
; if no timeout
xor a ; a = 0
out (CS_SIO_A_C), a ; select reg 0
in a, (CS_SIO_A_C) ; read reg 0
and 1 ; mask D0 (recieve char available)
jp Z,xmodem_read_wait_loop ; wait if no char
; if char avail
in a, (CS_SIO_A_D) ; read char
;call debug_a_hex
push af
call A_RTS_OFF
pop af
scf
ccf
ret ; return
xmodem_read_wait_timeout:
scf
ret
xmodem_out:
out (CS_SIO_A_D), a
call xmodem_wait_out
ret
xmodem_wait_out:
sub a ;clear a, write into WR0: select RR0
inc a ;select RR1
out (CS_SIO_A_C),A
in A,(CS_SIO_A_C) ;read RRx
bit 0,A
jr z,xmodem_wait_out
ret
MSG_ERROR:
db "Error: unexpected byte",13,10,0
MSG_START:
db "Await xmodem connection",13,10,0
xmodem_ack: ;ack routine. Only use when expecting transmission afterwards.
ld a, SYM_ACK ;send ACK
call xmodem_out
call xmodem_read_wait ;wait for response
jp c, xmodem_ack ;if timeout repeat
jp xmodem_packet ;if received, continue with new packet
xmodem_nak: ;nak routine. Only use when expecting transmission afterwards.
ld a, SYM_NAK ;send NAK
call xmodem_out
call xmodem_read_wait ;wait for response
jp c, xmodem_nak ;if timeout repeat
jp xmodem_packet ;if received, continue with new packet
xmodem_wait:
ld hl, 0xFF
ld bc, 0x01
xmodem_wait_1:
nop
nop
nop
nop
sbc hl,bc
ret Z
jr xmodem_wait_1