; disassembly of Data Science XOR computer boot ROM version 185,
; by Jim Battle, 2005-07-11.
; Last updated: 2005-07-20.
; Aided in part by:
;
;	Disassembled by:
;		DASMx object code disassembler
;		(c) Copyright 1996-1999   Conquest Consultants
;		Version 1.30 (Oct  6 1999)
;
;	File:		monitor.bin
;
;	Size:		2048 bytes
;	Checksum:	16AB
;	CRC-32:		0D0BDA8D
;
;	Date:		Sun Jul 10 10:45:29 2005
;
;	CPU:		Zilog Z80 (Z80 family)

; serial port A
SER_A_DATA	equ	00H	; data register
SER_A_CMD	equ	01H	; out command
SER_A_STAT	equ	01H	; in status

; serial port B.  this is the primary terminal port.
SER_B_DATA	equ	02H	; data register
SER_B_CMD	equ	03H	; out command
SER_B_STAT	equ	03H	; in status

; parallel port interface
PPI_A		equ	04H	; Parallel Port Interface
PPI_B		equ	05H	; Parallel Port Interface
PPI_C		equ	06H	; Parallel Port Interface
PPI_CMD		equ	07H	; Parallel Port Interface

BANK_SEL	equ	08H	; memory bank select register, A16-A19

PROM_SEL	equ	09H	; writing 1 disables boot EPROM; 0 enables it

RAD		equ	0AH	; reset address decode
				; on reset EPROM monitor repeats every 2KB;
				; inputting from this location makes eprom appear only at F800

BAUD_RATE	equ	0BH   	; read baud rate switch; lower 4b control channel A; upper 4b for channel B
				; write baud rate to baud rate generator

; counter timer chip
CTC_CHAN_1	equ	0CH    
CTC_CHAN_2	equ	0DH    
CTC_CHAN_3	equ	0EH    
CTC_CMD   	equ	0FH    
	
; floppy disk controller
FDC_CMD		equ	0F8H   	; cmd/status register
FDC_STAT	equ	0F8H   	; cmd/status register
FDC_TRK		equ	0F9H   	; track register
FDC_SEC		equ	0FAH   	; sector register
FDC_DATA	equ	0FBH   	; data register
; these control logic external to the FDC chip
FDC_DONE	equ	0FCH	; indicates completion on read
				; reading this port causes a processor stall
				; until either DRQ or INTRQ are active.
				; bit 7 of the read will be 0 if INTRQ is
				; active, and 1 otherwise.
FDC_DRIVE	equ	0FCH	; sets drive select on write
FDC_DENS	equ	0FDH	; density select

; utility equates
CR		equ	0DH
LF		equ	0AH
Space		equ	20H

; start of the world

	org	0F800H

; this is a subroutine vector table of useful routines.
; however, what is documented in the XOR CPU manual doesn't
; match what is here.
	jp	MONINZ
	jp	MONTR
	jp	CONIN
	jp	GetInB
	jp	OutRegC
	jp	OutARegC
	jp	OutHex2
	jp	OutHex4
	jp	CONIN

; initialize monitor (warm start)
MONTR:
	ld	de,NextCmd	; where to jump after ...
	jp	TestMem		; ... determining the memory size
;
NewCmd:
	exx
	ld	sp,hl		; restore saved TOS
	exx
NextCmd:
	call	OutCRLF
	ld	a,'*'		; prompt
	call	OutRegA
	call	EchoInB		; get command byte and echo it
	ld	de,0003H	; three bytes per entry in the command table
	ld	hl,CmdTable
	ld	b,a		; save command character
	ld	c,0FFH		; end of table marker
NxtCmd1	ld	a,(hl)
	cp	b
	jp	z,CmdMatch
	cp	c
	jp	z,CmdUnknown
	add	hl,de
	jp	NxtCmd1
CmdUnknown:
	ld	a,'?'
	call	OutRegA
	jp	NewCmd

CmdTable:
	db	'L'
	dw	CmdL

	db	'G'
	dw	CmdG

	db	'D'
	dw	CmdD

	db	'M'
	dw	CmdM

	db	'V'
	dw	CmdV

	db	'F'
	dw	CmdF

	db	'X'
	dw	CmdX

	db	'H'
	dw	CmdH

	db	06H	; control-F
	dw	CmdCtlF

	db	03H	; control-C
	dw	CmdCtlF

	db	0FFH	; end of table marker

CmdMatch:
	call	OutSpace
	inc	hl
	ld	e,(hl)
	inc	hl
	ld	d,(hl)
	ex	de,hl
	jp	(hl)		; vector off to a command processing routine

; ========================================================================
;    H AAAA BBBB CC DD EE FF ...
; Supposedly finds a string of bytes "CC DD EE FF ..." between addresses
; AAAA and BBBB.  However, it doesn't work for me and the code below seems
; to be buggy.

CmdH:
	call	GetHex44
	push	hl
	push	hl
	inc	de
	push	de
	ld	d,0
CmdH1	push	de
	call	GetHex2
	pop	de
	ld	(ix+0),c	; HOW CAN THIS WORK?  ix isn't initialized
	or	a
	jp	nz,CmdH2
	dec	ix
	inc	d
	call	OutSpace
	jp	CmdH1
CmdH2	pop	bc
	call	OutCRLF
CmdH3	pop	hl
	pop	ix
	ld	e,d
	ld	a,(ix+0)
	cpir
	jp	po,NewCmd
	push	ix
	push	hl
CmdH4	dec	e
	jp	z,CmdH5
	ld	a,(ix-1)
	cp	(hl)
	jp	nz,CmdH3
	inc	hl
	dec	ix
	jp	CmdH4
CmdH5	pop	hl
	push	hl
	dec	hl
	push	bc
	call	OutHex4
	call	OutCRLF
	pop	bc
	jp	CmdH3

; check if there is a character waiting from the user.
; if one is waiting, abort everything and restart the monitor.
PollAbort:
	push	af
	call	PollInB
	jp	nz,NewCmd
	pop	af
	ret

; ========================================================================
;    L AAAA
; shows the current byte at address AAAA and waits for input.
; entering CR then moves to the next byte; entering a hex value
; replaces that value; entering "." exits this mode.

CmdL:
	call	GetHex4
CmdL1	call	OutCRLF
	call	OutHex4
	ld	a,'-'
	call	OutRegA
	ld	b,(hl)
	call	OutHex2
	call	OutSpace
	ld	a,'<'
	call	OutRegA
	call	OutSpace
	call	GetHex2
	cp	CR
	jp	z,CmdL2
	ld	(hl),c
CmdL2	inc	hl
	jp	CmdL1

; ========================================================================
;    D AAAA BBBB
; dump memory in hex from address AAAA to BBBB.
; hitting any key stops this mode and is taken as the first keystroke of
; a new command.

CmdD:
	call	GetHex44
CmdD1	call	OutCRLF
	call	OutHex4
	ld	b,08H
CmdD2	push	bc
	ld	b,(hl)
	call	OutHex2
	call	OutSpace
	ld	a,d
	or	e
	jp	z,NewCmd
	dec	de
	inc	hl
	pop	bc
	dec	b
	jp	nz,CmdD2
	call	PollAbort	; quit if a key is waiting
	jp	CmdD1

; ========================================================================
;    F AAAA BBBB CC
; fill memory from AAAA to BBBB-1 with byte CC

CmdF:
	call	OutSpace
	ld	hl,NewCmd
	push	hl
	call	GetHex4
	push	hl
	call	GetHex4
	push	hl
	call	GetHex2
	ld	b,c
	pop	de
	pop	hl
CmdF1	ld	(hl),b
	inc	hl
	ld	a,l
	cp	e
	jp	nz,CmdF1
	call	PollAbort	; quit if a key is waiting
	ld	a,h
	cp	d
	jp	nz,CmdF1
	ret

; ========================================================================
;    M AAAA BBBB CCCC
; block move from AAAA to BBBB for CCCC bytes.

CmdM:
	call	OutSpace
	ld	hl,NewCmd
	push	hl
	call	GetHex4
	push	hl
	call	GetHex4
	push	hl
	call	GetHex4
	pop	bc
	pop	de
	ex	de,hl
CmdM1	ld	a,(hl)
	ld	(bc),a
	inc	hl
	inc	bc
	dec	de
	ld	a,0
	cp	e
	jp	nz,CmdM1
	call	PollAbort	; quit if a key is waiting
	cp	d
	jp	nz,CmdM1
	ret

; get a character from port B and store it in reg A.
; echo that character back to port B.
EchoInB:
	call	GetInBToo
	call	OutRegA
	ret

; send CR and LF characters to port B.
OutCRLF:
	ld	a,CR
	call	OutRegAToo
	ld	a,LF
	jp	OutRegAToo

; classify the character in reg A.
; that value in reg A is retained on exit.
; if it is 0-9 or A-F, return with binary equivalent in register C,
; with the carry flag set.
; if it isn't one of these characters, return with the carry flag cleared.
ClassHex:
	ld	d,a		; D holds original character
	cp	'0'
	jp	m,ClssHx3	; jump if < '0'
	cp	'F'+1
	jp	p,ClssHx3	; jump if > 'F'
	cp	'9'+1
	jp	p,ClssHx2	; jump if > '9'
	and	0FH
ClssHx1	ld	c,a
	ld	a,d
	scf
	ret
ClssHx2	cp	'A'
	jp	m,ClssHx3	; jump if < 'A'
	and	0FH
	add	a,09H
	jp	ClssHx1
ClssHx3	or	a
	ret

; get a 16b hex number from port B.
; the binary value is returned in register pair HL,
; and four spaces are emitted to port B after the number is entered.
; if no digits are entered and CR comes first, HL returns with zero.
;
; Note: it matters to GetHex44 that if no digits are entered and CR
;       terminates things, reg A will contain $0D, otherwise it returns
;       with a non- $0D value (which just happens to always be $20).
GetHex4	ld	hl,0000H
	call	GetHex1
	ret	nc		; return with HL=0000 if immediate CR
	ld	l,c		; reg L = first nibble
	ld	b,c		; reg B = first nibble
	call	GetHex1
	jp	nc,OutSpace4	; CR after first nibble
	call	BldHex8		; reg L = first two nibbles
	call	GetHex1
	jp	nc,OutSpace4	; CR after two nibbles
	ld	h,b		; reg H = first nibble
	ld	b,l		; reg B = nibbles two and three
	call	BldHex8		; 12b value is (256*reg H) + (reg L)
	call	GetHex1
	jp	nc,OutSpace4
	ld	h,b		; reg H = first two nibbles
	call	BldHex8		; reg L = last two nibbles
; echo out four spaces to port B
OutSpace4:
	call	OutSpace
	call	OutSpace
	call	OutSpace
	call	OutSpace
	ret

; combine two nibbles (ms in reg L, ls in reg C)
; into an 8b value in regs A and L
BldHex8:
	ld	a,l
	and	0FH
	rlca
	rlca
	rlca
	rlca
	add	a,c
	ld	l,a
	ret

; get a character from the user.
; if it is '.', then abort the command in progress and get a new command.
; if the user enters carriage return, return with carry cleared.
; if the user enters 0-9 or A-F, echo the character and return with the
; character in reg A and carry set, and the binary value in reg C.
GetHex1:
	call	GetInBToo
	cp	CR
	ret	z		; terminate number early, with carry cleared
	cp	'.'
	jp	z,NewCmd	; '.' means abort current command
	call	ClassHex
	jp	nc,GetHex1
	call	OutRegA		; echo the hex character
	scf
	ret			; return with carry set

; get a two digit hex number from the user.
; if just a CR is entered, reg A returns $0D and reg C is unchanged.
; otherwise, reg A returns $00 and reg C returns the binary number.
GetHex2:
	push	hl
	ld	hl,0000H
	call	GetHex1
	jp	nc,GetHx2b	; jump if no digit entered, just CR
	ld	l,c		; reg L gets first nibble
	call	GetHex1
	jp	nc,GetHx2a
	call	BldHex8		; turn into 8b value
	ld	c,l		; restore reg C
GetHx2a	ld	a,0		; indicate a number was entered
GetHx2b	pop	hl
	ret

; send a space character to port B
OutSpace:
	ld	a,Space
OutRegAToo:
	call	OutRegA
	ret

; convert the 8b binary number in reg B to ASCII and emit it on port B
OutHex2:
	ld	a,b
	rrca
	rrca
	rrca
	rrca
	call	OutHex1
	ld	a,b
	call	OutHex1
	ret

; convert the 4b binary number in reg A to ASCII and emit it on port B
OutHex1:
	and	0FH
	cp	0AH
	jp	nc,GetHx1a
	add	a,'0'
	call	OutRegA
	ret
GetHx1a	add	a,'0'+7
	call	OutRegA
	ret

; convert the 16b binary number in reg pair HL to ASCII and emit it on port B
OutHex4:
	ld	b,h
	call	OutHex2
	ld	b,l
	call	OutHex2
	jp	OutSpace4

; ========================================================================
;    G AAAA
; jump to address AAAA (eg. G F800 reboots)

CmdG:
	call	GetHex4
	call	OutCRLF
	jp	(hl)		;INFO: index jump

; get two 16b hex numbers from the user.
; the first value is returned in register pair HL;
; ((second number)-(first number)) is returned in DE.
; if the difference is negative, the routine reports an error and the
; command is aborted.
;
; Oddly, if the second number is terminated early with a CR,
; HL returns with the first number and DE returns with $00B7.
; The reason for this is that in the dump command, 23 rows of eight bytes
; per row is 184 ($B8).  That is, to dump one page of memory at address
; AAAA, one can type "D AAAA <CR>".
;
; this function is used in argument parsing for CmdD and CmdH.
GetHex44:
	call	GetHex4
	push	hl
	call	GetHex4
	pop	de
	cp	CR
	jp	z,GetHx44a
	ld	a,l
	sub	e
	ld	l,a
	ld	a,h
	sbc	a,d
	jp	c,CmdUnknown	; jump if (2nd number) < (1st number)
	ld	h,a
	ex	de,hl
	ret
GetHx44a:
	ld	hl,000B7H	; weird special case
	ex	de,hl
	ret

; ========================================================================
;    V AAAA
; dumps memory in ASCII, 64 chars/line, stopping after each 24 lines,
; waiting for a CR.  Hitting space instead of CR stops this mode.

CmdV:
	ld	hl,NewCmd
	push	hl
	call	GetHex4
	ld	a,01H		; clear screen?
	call	OutRegA
	xor	a
CmdV1	ld	de,0000H
	call	OutCRLF
	call	OutCRLF
	call	OutHex4
	call	OutSpace4
CmdV2	ld	b,40H
CmdV3	ld	a,(hl)
	and	7FH		; strip parity bit
	cp	Space
	jp	p,CmdV4
	ld	a,Space
CmdV4	call	OutRegA
	inc	de
	inc	hl
	push	hl
	ld	hl,0600H	; 24 lines of 64 characters
	sbc	hl,de
	pop	hl
	jp	z,CmdV5
	dec	b
	jp	nz,CmdV3
	call	OutCRLF
	call	OutHex4
	call	OutSpace4
	jp	CmdV2
CmdV5	call	GetInBToo
	cp	Space
	jp	z,NewCmd
	cp	CR
	jp	z,CmdV1
	jp	CmdV5

; alias for GetInB
; (why does this exist?)
GetInBToo:
	call	GetInB
	ret

; emit character in reg A to port B.
; contents of pair BC are preserved.
OutRegA:
	push	bc
	ld	c,a
	call	OutRegC
	pop	bc
	ret

; ========================================================================
; Boot from floppy.  CmdCtlF/CmdCtlC are command entry points.

bootfail:
	pop	af		; recover retry count
	dec	a
	push	af
	jp	z,boot5
	ld	b,05H		; step five times
bfail1	ld	a,43H		; step in, unload head, 30 ms stepping rate
	out	(FDC_CMD),a
bfail2	in	a,(FDC_STAT)
	rrca
	jr	c,bfail2	; wait until not busy
	dec	b
	jr	nz,bfail1
	jr	boot1

CmdCtlF:
CmdCtlC:
	ld	a,05H		; retry booting five times
	push	af
boot1:
	ld	a,0D0H		; terminate any existing command, no interrupt
	out	(FDC_CMD),a
boot2:
	ex	(sp),hl		; kill ...
	ex	(sp),hl		; ... time
	in	a,(FDC_STAT)
	rrca
	jr	c,boot2		; wait for command to finish
	ld	a,01H		; restore, unload head, stepping rate=12 ms
	out	(FDC_CMD),a
	ld	hl,0000H	; timeout counter
boot3:
	ex	(sp),hl		; kill ...
	ex	(sp),hl		; ... time
	inc	hl
	ld	a,l
	or	h
	jp	z,bootfail
	in	a,(FDC_STAT)
	and	85H		; flags: not ready, track 0, busy
	cp	04H
	jp	nz,boot3	; wait until ready and not busy and track 0

	ld	a,02H
	out	(FDC_DENS),a	; single/double density select
	dec	a
	out	(FDC_SEC),a	; look for sector 1
	ld	hl,0000H	; address to save boot sector to
	ld	a,8CH		; read sector, side 0 (ignored), 15 ms delay
	out	(FDC_CMD),a
boot4:
	in	a,(FDC_DONE)	; stall until next byte available or done
	or	a
	jp	p,boot5		; bit 7==0 means completion of sector read
	in	a,(FDC_DATA)	; get next byte from track
	ld	(hl),a		; save it to the next location in memory
	inc	hl
	jr	boot4
boot5:
	ld	hl,MONINZ
	push	hl
	ld	hl,MsgNoSys
	in	a,(FDC_STAT)
	or	a
	jr	nz,boot6
	ld	a,(0000H)
	cp	31H		; make sure first instruction is LD SP,nnnn
	jr	nz,boot7	; print "No system" error
	rst	0000H		; everything seems in order: run the boot code
boot6:
	ld	(0100H),a	; save the FDC status byte (so user can Dump it)
	ld	hl,MsgDiskErr
	and	90H		; flags: not ready, Record Not Found
	jr	z,boot7
	ld	hl,MsgCRC
	and	10H		; flag: record not found (CRC is bit 3, not bit 4!)
	jr	nz,boot7
	ld	hl,MsgNotRdy	; disk never came ready
boot7:
	call	OutStr
	call	OutCRLF
boot8:
	in	a,(SER_B_STAT)
	and	01H		; wait for final character to finish transmission
	ret	nz
	jr	boot8

; send string pointed at by (hl) to serial port B until a "$" character
OutStr:
	ld	a,(hl)
	cp	'$'
	ret	z
	ld	c,a
	call	OutRegC
	inc	hl
	jp	OutStr

; ========================================================================
;   X
; gets a "Bank ?" message.  the value entered is used to set the memory
; bank register for systems with > 64KB of RAM.

CmdX:
	ld	hl,MsgBank
	call	OutStr
	call	GetInBToo
	and	07H		; allow only eight banks
	out	(BANK_SEL),a
	jp	NewCmd

; wait for a character from port B.
; the character is returned in reg A with bit 7 forced to zero.
GetInB:
	call	PollInB
	jr	z,GetInB
	in	a,(SER_B_DATA)
	and	07FH		; force 7b ASCII
	ret

; send out the character in reg C to port B.
OutRegC:
	in	a,(SER_B_STAT)
	and	01H		; wait for TxRdy
	jr	z,OutRegC
	ld	a,c
	out	(SER_B_DATA),a
	ret

; test if serial port B has received a character.
; return with A=00 and Z set if none is ready;
; return with A=FF and !Z if a character is waiting.
CONIN:
CONST:
	ld	hl,0185H
PollInB:
	in	a,(SER_B_STAT)
	and	02H		; test RxRdy
	ld	a,0
	ret	z
	cpl
	ret

; sends reg C to serial port A, with flow control
OutARegC:
	ex	(sp),hl		; kill ...
	ex	(sp),hl		; ... time
	in	a,(SER_A_STAT)
	and	85H		; flags: DSR, TxEmpty, TxRdy
	cp	85H
	jp	nz,OutARegC
	ld	a,c
	out	(SER_A_DATA),a
	ret

; full initialization after power on
MONINZ:
	in	a,(RAD)		; make EPROM map only once instead of everywhere
	in	a,(BAUD_RATE)	; read the baud rate dip switch
	out	(BAUD_RATE),a	; set the UARTs baud rates
	ld	de,InitUarts	; where to jump after ...
	jp	TestMem		; ... determining the memory size

; initialize serial ports A and B
InitUarts:
	ld	hl,SerInitTbl
InitUrt1:
	ld	b,(hl)		; get byte count
	inc	hl
	ld	c,(hl)		; get port address
	inc	hl
	dec	b
	inc	b
	jp	z,SignOn
	otir			; send the next B bytes to port (C)
	jp	InitUrt1
SignOn:
	ld	hl,MsgInit
	call	OutStr
	pop	hl
	call	OutHex4
	jp	NewCmd

; scan memory starting at address 0000H until a non-working location is
; found.  the test is pretty weak but can detect the boot ROM at F800 if
; nothing else.  the stack pointer is set to the end of RAM and it is
; also saved in the alternate HL register pair for later use.
; some complicated twiddling is done at the end that I haven't spent
; enough time figuring out.  finally, the routine returns to the address
; that was in the DE pair at the time the routine was called.

TestMem:
	ld	hl,0000H	; start at beginning of memory
TstMem1	ld	a,(hl)
	ld	b,a
	cpl
	ld	(hl),a
	cp	(hl)
	jp	nz,TstMem2	; jump means we hit non-storage
	ld	(hl),b
	inc	l
	jp	nz,TstMem1
	inc	h
	jp	TstMem1
TstMem2	ld	sp,hl		; TOS (top of stack)
	push	hl
	exx
	pop	hl		; save TOS in alternate HL pair
	push	hl		; save TOS on TOS for unknown reasons
	exx
	push	de		; this is the address to return to
	ld	de,0FFE0H
	add	hl,de		; subtract 32
	push	hl		; \__ why?
	pop	hl		; /
	ret			; jumps to address that was originally in DE

; message string table.
; the end of the message string is marked with a '$'.

MsgDiskErr:
	db	"Disk error$"
MsgNoSys:
	db	"No system$"
MsgCRC:
	db	"CRC error$"
MsgNotRdy:
	db	"Drive not ready$"
MsgBank:
	db	CR, LF
	db	"Bank ? $"
MsgInit:
	db	CR, LF, LF
	db	"XOR DATA SCIENCE", CR, LF
	db	"SYSTEM MONITOR", CR, LF
	db	"VERS 01.85", LF, CR, "$"

; serial port initialization table
SerInitTbl:
	db	004H	; byte count
	db	001H	; port address
	db	0AAH	; data stream ...
	db	040H
	db	04EH
	db	037H

	db	004H	; byte count
	db	003H	; port address
	db	0AAH	; data stream ...
	db	040H
	db	04EH
	db	037H

	db	00H, 00H	; end of table marker

; ========================================================================
; dead code?  junk dna?

	ld	a,(bc)
	inc	bc
	jr	LFC63
;
	nop
LFC63:
	inc	b
	ld	c,h
	dec	b
	ld	l,b
	inc	bc
	ld	b,c
	nop
	nop
	ld	(1EAAH),a
	ld	c,a
	ld	b,0
	ld	hl,(1F95H)
	add	hl,bc
	ld	a,(1EA8H)
	ld	(hl),a
	ld	a,(1EA8H)
	cp	3FH
	jp	nz,1486H
	ld	hl,01DF5H
	ld	(hl),01H
	ret
;
	ld	hl,01F9CH
	ld	(hl),c
	ld	hl,1EA8H
	ld	(hl),3FH
	ld	hl,01F9CH
	ld	a,(1EAAH)
	cp	(hl)
	jp	nc,14A0H
	call	1467H
	jp	1490H
	ret
;
	ld	hl,1F9DH
	ld	(hl),c
	ld	hl,(1F9DH)
	ld	h,0
	ex	de,hl
	ld	hl,(1F95H)
	add	hl,de
	ld	a,(hl)
	ret
;
	ld	hl,01DF6H
	ld	(hl),01H
	ld	a,(1EC0H)
	ld	(1EC1H),a
	call	11F2H
	ld	(1EA8H),a
	ld	a,(1EA8H)
	sub	0DH
	sub	01H
	sbc	a,a
	push	af
	ld	a,(1EA8H)
	sub	5DH
	sub	01H
	sbc	a,a
	pop	bc
	ld	c,b
	or	c
	rra
	jp	c,15BAH
	ld	a,(1EA8H)
	sub	41H
	ld	(1F9EH),a
	ld	c,a
	ld	a,19H
	cp	c
	jp	nc,1503H
	ld	a,(1EA8H)
	cp	20H
	jp	nz,14FAH
	call	11F2H
	ld	(1EA8H),a
	jp	1500H
;
	ld	bc,0308H
	call	09AFH
	ld	d,6AH
	inc	bc
	sra	h
	rla
	ld	a,a
	adc	a,a
	ld	a,l
	ld	c,l
	inc	l
;
	db	0FDH
;
	ld	c,l
	ld	a,76H
	and	(hl)
	xor	h
	call	z,392DH
	add	a,(hl)
;
	db	0EDH
;
	inc	b
	xor	b
	adc	a,h
	call	z,546CH
	inc	(hl)
	inc	(hl)
	jp	nz,0BA5H
	inc	e
	ld	hl,(6D23H)
	ld	c,h
	add	a,e
	ld	l,e
	ld	bc,05129H
	ld	c,b
	add	hl,hl
	rst	0028H
	ld	c,l
	ld	e,b
	ld	b,c
	call	po,7A09H
	ld	l,e
	call	nz,0FBEDH
	ld	a,a
	call	pe,0E02CH
	call	nz,0F528H
	ld	sp,hl
	adc	a,l
	cpl
	ei
	adc	a,c
	rst	0028H
	call	p,8D3BH
	or	l
	sbc	a,h
	ld	b,c
LFD4B:
	cpl
	ld	c,a
	ld	e,a
	ld	c,e
	rlca
	ld	l,h
	ld	a,h
	adc	a,c
	call	z,6C2DH
	dec	b
	inc	l
	ld	h,7EH
	jr	z,LFD95
	ld	a,a
	call	z,LFDB1
	xor	d
	ld	h,a
	inc	e
	jp	(hl)		;INFO: index jump
;
	ld	e,a
	add	hl,de
	ld	l,l
	xor	h
	ld	b,c
	ld	c,l
	and	b
	ld	l,h
	xor	l
	ld	h,l
	adc	a,(hl)
	xor	h
	adc	a,h
	ld	c,h
	pop	hl
	and	e
	rst	0008H
	rst	0008H
	ret	pe
	and	l
	nop
	adc	a,(hl)
	or	89H
	cpl
	ld	h,e
	ex	(sp),hl
	ld	e,e
	ld	h,c
	ld	e,0BCH
	add	a,(hl)
	ld	c,e
	ld	a,h
	rrca
	ld	b,a
	ld	(bc),a
	inc	(hl)
	ld	e,a
	ld	c,0AEH
	adc	a,a
	rra
	dec	l
	ld	a,a
	ld	l,(hl)
	ld	c,h
	add	a,0EAH
LFD95:
	push	de
	rst	0028H
	ld	b,e
	inc	sp
	ex	de,hl
	ld	sp,0651CH
	ld	(LFD4B),a
	dec	bc
	call	z,24D9H
	ld	a,(hl)
	push	bc
	ld	l,a
	or	09H
	jp	(hl)		;INFO: index jump
;
	ld	l,c
	ld	(hl),b
	nop
	ld	e,l
	dec	bc
;
	db	0DCH
	db	0C2H
LFDB1:
	db	8EH
;
LFDB2:
	inc	c
	xor	1EH
	ld	h,a
	ccf
	ld	a,a
	ld	(3068H),hl
	dec	h
	adc	a,0CFH
	cpl
	ld	l,a
	ex	de,hl
	jp	pe,484FH
	ld	e,l
	rrca
	ld	l,0AFH
	ld	a,l
	ld	l,(hl)
	ex	af,af'
	dec	l
	ld	e,69H
	adc	a,e
	ld	h,a
	inc	bc
	adc	a,60H
	ret	po
	ld	h,l
	cp	49H
	rrca
;
	db	0EDH
;
	rst	0028H
	ld	b,h
	inc	c
	call	c,0A1CFH
	ld	c,a
	dec	a
	ld	d,d
	cp	h
	add	hl,hl
	ld	c,l
	call	68FFH
	rlca
	ld	bc,0A80CH
	dec	sp
	inc	c
	add	hl,hl
	and	c
	and	0EBH
	ld	hl,01781H
	rst	0028H
	adc	a,d
	ld	l,(hl)
	jp	pe,6B6AH
	ld	a,(hl)
	ld	l,a
	rst	0038H
	adc	a,e
	xor	l
	inc	b
	ret	z
	jr	LFE6D
;
	ex	af,af'
	jr	LFE10
;
	ret	nc
	jr	c,LFDB2
	sub	c
	add	a,l
	rrca
	dec	b
	add	hl,bc
	nop
LFE10:
	adc	a,0DH
	rst	0008H
	dec	l
	add	hl,bc
	sbc	a,d
	rst	0030H
	dec	c
	ld	bc,0CA55H
	sbc	a,e
	ex	af,af'
	daa
LFE1E:
	ld	a,(bc)
	ld	e,a
	dec	h
	ld	b,l
	ld	c,d
	ld	d,e
	ld	a,(bc)
	rst	0030H
;
	db	22H
;
LFE27:
	inc	c
	inc	c
	ld	a,(bc)
	sbc	a,b
	cp	c
	ld	c,b
	adc	a,e
	dec	bc
	add	hl,bc
	ex	de,hl
	dec	bc
	adc	a,a
	sub	c
	sbc	a,2BH
	add	a,a
	cp	l
	add	a,b
	ld	a,(de)
	ld	b,a
	xor	h
	ld	e,e
	add	a,95H
	sbc	a,a
	dec	b
	ld	d,e
	sbc	a,(hl)
	ld	a,(0A983H)
	adc	a,c
	dec	sp
	nop
	sbc	a,h
	add	hl,bc
	sbc	a,d
	dec	de
	add	hl,bc
	inc	c
	jr	LFEAC
;
	ld	(bc),a
	or	d
	dec	l
	dec	e
	adc	a,a
	xor	e
	rst	0010H
	ld	c,d
	ld	b,84H
	add	hl,de
	rrca
	adc	a,6BH
	add	hl,bc
	jr	z,LFE27
	adc	a,l
	ret
;
	xor	a
	sbc	a,h
	rst	0008H
	ld	a,(bc)
	add	a,d
	djnz	LFE7B
	sub	d
	ld	l,l
LFE6D:
	adc	a,c
	add	a,l
	ld	c,e
	xor	a
	push	hl
	call	z,0CF0EH
	cp	a
	adc	a,d
	xor	a
	ret	nc
;
	db	0DDH
;
	ld	(bc),a
LFE7B:
	ret
;
	rra
	ret
;
	daa
	rrca
	ld	b,0C8H
	ld	e,l
	ret	m
	dec	c
	sub	e
	rst	0008H
	daa
	dec	e
	adc	a,e
	add	a,h
	adc	a,d
	ld	c,h
	ld	b,l
	adc	a,a
	sub	c
	jr	LFE1E
;
	ld	a,e
	or	(hl)
LFE94:
	ld	c,83H
	dec	de
	sub	c
	xor	e
	cp	a
	add	hl,bc
	xor	(hl)
	ld	e,48H
	rra
	ld	(hl),c
	ccf
	dec	e
	ld	(bc),a
	ld	b,h
	ld	c,l
	daa
	ld	c,0ADH
	dec	de
	adc	a,05H
	ret	nc
LFEAC:
	add	hl,de
	ld	c,e
	rra
	adc	a,c
	ld	(hl),h
	rst	0020H
	inc	de
	ld	(bc),a
	xor	c
	adc	a,e
	rst	0008H
	ld	e,h
	ld	e,0C3H
	add	a,b
	inc	c
	xor	(hl)
	dec	a
	adc	a,e
	in	a,(089H)
	ld	c,(hl)
	add	hl,bc
	call	c,1940H
;
	db	0EH
;
LFEC7:
	jp	z,01E19H
	ex	af,af'
	ld	e,2FH
	ld	b,48H
	ld	e,9AH
	ld	(hl),a
	ld	d,l
	sbc	a,h
	and	b
	adc	a,l
	cp	c
	adc	a,(hl)
	jr	z,LFEC7
	add	hl,de
	ld	e,8AH
	add	hl,sp
	cpl
	dec	c
	xor	e
	cpl
	adc	a,h
	halt
	cpl
	dec	sp
	dec	c
	pop	bc
	inc	(hl)
	push	bc
	sbc	a,l
	ex	af,af'
	ld	a,(bc)
	dec	d
	add	hl,bc
	ld	e,l
	ld	c,8DH
	inc	b
	djnz	LFE94
	ccf
	rst	0010H
	dec	sp
	ld	d,h
	dec	e
	add	a,2AH
	dec	c
	ld	b,0EH
	ld	h,2BH
	inc	l
	ld	c,e
	ld	h,h
	ld	b,l
	ret	p
	ld	a,a
	sbc	a,0EAH
	sbc	a,054H
	daa
	ld	h,(hl)
	adc	a,e
	call	z,4CABH
	ld	l,c
	ld	h,h
	add	a,h
	ld	(bc),a
	jp	po,0EF6AH
	ex	af,af'
	ret	po
	xor	c
	djnz	LFF22
	ld	a,a
	ld	c,e
	add	a,c
	add	a,b
	pop	hl
LFF22:
	ld	h,d
	ex	de,hl
	ld	l,a
	cpl
	ld	l,h
	ld	a,c
	ld	l,l
	jp	m,60ACH
	xor	a
	rst	0010H
	ld	h,(hl)
	xor	0E9H
	ld	(hl),e
	ld	a,d
	push	hl
	rst	0028H
	sbc	a,c
	add	a,d
;
	db	0EDH
;
	xor	0F9H
	jp	pe,6D3DH
	jp	(hl)		;INFO: index jump
;
	ld	l,e
	call	m,0EC26H
	cp	e
	rrca
	ccf
	cp	c
	push	hl
	ld	b,e
	inc	c
	jr	nz,LFF4C
	ccf
LFF4C:
	rrca
	ld	a,e
	ld	a,c
	ccf
	jp	po,44E8H
	ld	c,l
	add	hl,hl
	ret	p
	sub	b
	ld	c,a
	add	hl,hl
	ld	l,c
	ld	h,h
	ld	l,b
	sbc	a,a
	pop	hl
	adc	a,d
;
	db	0EDH
;
	dec	c
	ld	d,h
	dec	de
	cp	8FH
	adc	a,0ABH
	ld	a,d
	inc	l
	ld	c,b
	cpl
	cp	d
	rst	0028H
	ld	l,l
	add	a,b
	ld	l,h
	nop
	ret	m
	xor	b
	ld	l,(hl)
	ld	c,a
	dec	de
	jp	(hl)		;INFO: index jump
;
	xor	b
	and	l
	ret	pe
	adc	a,d
	rst	0030H
	xor	a
	ex	af,af'
	jr	z,LFF9F
	inc	a
	call	po,0C175H
	dec	b
	or	l
	ld	c,a
	ld	h,a
	ld	(hl),a
	rst	0018H
	add	a,l
	ld	h,h
	daa
	call	po,256FH
	ld	l,h
;
	db	0EDH
;
	ld	(hl),h
	ret	nz
	ld	l,c
	xor	d
	ld	c,e
	add	a,d
	nop
	ld	a,d
	ld	hl,0B818H
	ei
LFF9E:
	ld	e,a
LFF9F:
	jp	(hl)		;INFO: index jump
;
	ld	c,d
	ex	(sp),hl
	inc	a
	ld	a,d
	and	6FH
	ex	de,hl
;
	db	0EDH
;
	jr	0FFFEH
;
	ld	l,21H
	add	hl,bc
	ex	de,hl
	ld	bc,(486AH)
	nop
	ex	de,hl
	rrca
;
	db	0EDH
;
	rst	0028H
	ld	l,e
	ret	m
	ex	de,hl
	ld	c,b
	cpl
	add	hl,sp
	ld	l,a
	ld	a,a
	ret	z
	ld	(6BA2H),hl
	ld	b,(hl)
	ld	l,e
	inc	h
	adc	a,a
	sbc	a,l
	inc	d
	ld	b,h
;
	db	2AH
;
LFFCB:
	and	(hl)
	jr	z,0003BH
	ld	h,e
	rst	0010H
	add	hl,bc
	ret	p
	call	61E9H
	ret
;
	ld	b,h
	ret	c
	xor	58H
	ret
;
	ex	(sp),hl
	ld	(hl),e
	dec	h
	pop	hl
	inc	l
	ld	b,h
	ld	h,l
	ld	b,l
	ld	(hl),h
	ld	c,a
	ld	e,l
	jr	z,LFFCB
	ld	l,b
	djnz	0060H
	adc	a,a
	ld	c,l
	xor	a
	ld	h,e
	rst	0038H
	sbc	a,b
	jr	nz,LFF9E
	ld	a,l
	ld	l,l
	ex	(sp),hl
	ld	hl,(4061H)
	ld	l,d
	jr	c,0028H
	add	a,l
	sbc	a,e
	rrca
	db	0CDH
