evscript 0.1.0

An extensible bytecode-based scripting engine
Documentation
section "evscript Driver", rom0
; @param de: Variable pool
; @param hl: Script pointer
; @param bank: Script bank
; @return hl: New script pointer. 0 after a return.
; @return bank: New script bank.
; @preserves de
ExecuteScript::
	ld a, h
	or a, l
	ret z
.next
	ld a, [hli]
	push hl
	add a, low(EvscriptBytecodeTable >> 1)
	ld l, a
	adc a, high(EvscriptBytecodeTable >> 1)
	sub a, l
	ld h, a
	add hl, hl
	ld a, [hli]
	ld h, [hl]
	ld l, a
	ld b, h
	ld c, l
	pop hl
	push de
	call .callBC
	pop de
	jr ExecuteScript.next

.callBC
	push bc
	ret

section "evscript Bytecode table", rom0, ALIGN[1]
EvscriptBytecodeTable:
	; Control
	dw StdReturn
	dw StdYield
	; goto
	dw StdJump
	dw StdJumpIfTrue
	dw StdJumpIfFalse
	; Moves
	dw StdPut
	dw StdMove
	; 8-bit ops
	dw StdAdd
	dw StdSub
	dw StdBinaryAnd
	dw StdEqu
	dw StdNotEqu
	dw StdLessThan
	dw StdGreaterThan
	dw StdLessThanEqu
	dw StdGreaterThanEqu
	dw StdLogicalAnd
	dw StdLogicalOr

section "evscript Return", rom0
StdReturn:
	ld hl, 0
StdYield:
	pop de ; pop return address
	pop de ; pop pool pointer
	ret

section "evscript Goto", rom0
StdJump:
	ld a, [hli]
	ld h, [hl]
	ld l, a
	ret

StdJumpIfTrue:
	ld a, [hli]
	add a, e
	ld c, a
	adc a, d
	sub a, c
	ld b, a
	ld a, [bc]
	and a, a
	jr nz, StdJump
.fail
	inc hl
	inc hl
	ret

StdJumpIfFalse:
	ld a, [hli]
	add a, e
	ld c, a
	adc a, d
	sub a, c
	ld b, a
	ld a, [bc]
	and a, a
	jr z, StdJump
.fail
	inc hl
	inc hl
	ret

section "evscript Put", rom0
StdPut:
	ld a, [hli]
	add a, e
	ld c, a
	adc a, d
	sub a, c
	ld b, a
	ld a, [hli]
	ld [bc], a
	ret

section "evscript Mov", rom0
StdMove:
	; Load dest
	ld a, [hli]
	add a, e
	ld c, a
	adc a, d
	sub a, c
	ld b, a
	; Load source
	ld a, [hli]
	add a, e
	ld e, a
	adc a, d
	sub a, e
	ld d, a
	; Move
	ld a, [de]
	ld [bc], a
	ret

section "evscript 8-bit Operations", rom0
; @param de: pool
; @param hl: script pointer
; @return a: lhs
; @return b: rhs
OperandPrologue:
	ld a, [hli] ; lhs offset
	add a, e
	ld c, a
	adc a, d
	sub a, c
	ld b, a
	; de is preserved & variable is pointed to by bc
	ld a, [hli]
	push hl
		ld l, a
		ld h, 0
		add hl, de
		ld a, [bc]
		ld b, [hl]
	pop hl
	ret

StdAdd:
	call OperandPrologue
	add a, b ; Here is the actual operation
	jr StoreEpilogue

StdSub:
	call OperandPrologue
	sub a, b ; Here is the actual operation
	jr StoreEpilogue

StdBinaryAnd:
	call OperandPrologue
	and a, b
	jr StoreEpilogue

StdEqu:
	call OperandPrologue
	cp a, b
	ld a, 0
	jr nz, StoreEpilogue
	inc a
	jr StoreEpilogue

StdNotEqu:
	call OperandPrologue
	cp a, b
	ld a, 0
	jr z, StoreEpilogue
	inc a
	jr StoreEpilogue

StdLessThan:
	call OperandPrologue
	cp a, b
	ld a, 0
	jr nc, StoreEpilogue
	inc a
	jr StoreEpilogue

StdGreaterThan:
	call OperandPrologue
	cp a, b
	jr z, .zero
	jr nc, .zero
	ld a, 1
	jr StoreEpilogue
.zero
	xor a, a
	jr StoreEpilogue

StdLessThanEqu:
	call OperandPrologue
	cp a, b
	jr z, .one
	jr c, .one
	xor a, a
	jr StoreEpilogue
.one
	ld a, 1
	jr StoreEpilogue

StdGreaterThanEqu:
	call OperandPrologue
	cp a, b
	ld a, 0
	jr c, StoreEpilogue
	inc a
	jr StoreEpilogue

StdLogicalAnd:
	call OperandPrologue
	and a, a
	jr z, StoreEpilogue
	ld a, b
	and a, a
	jr z, StoreEpilogue
	ld a, 1
	jr StoreEpilogue

StdLogicalOr:
	call OperandPrologue
	and a, a
	jr nz, .true
	ld a, b
	and a, a
	jr z, StoreEpilogue
.true
	ld a, 1
	; fallthrough
; This is stored in the middle so both variable and constant operations can
; reach it.
StoreEpilogue:
	ld b, a
	ld a, [hli]
	add a, e
	ld e, a
	adc a, d
	sub a, e
	ld d, a
	ld a, b
	ld [de], a
	ret