How to call MSX-BASIC CLEAR command in Assembly

By hope-hunter

Supporter (2)

hope-hunter's picture

21-06-2019, 16:50

Hi, I'm posting my solution here to archive it.
It was tested on MSX1, MSX2+ and MSX Turbo R.

	; ======     Run MSX-BASIC CLEAR from BLOAD,R to auto protect the assembly program on High Memory    =========
	; ===================================================================================================
	; By Carlos Olivi (Jun/2019)
	
	; Problem: When you directly call MSX-BASIC 'CLEAR' Handler in assembly, it don't back to assembly program.
	; Method: Create a special Return for CLEAR Handle (here called BAS.CLEAR) intercepting RUNLOOP by HNEWS hook.
	; Target: Program for a BLOAD ,R execution.
	
	pop	hl			; [6CF3H] Skip the return point of BLOAD,R handler
	pop	hl			; [8XXXH] Get the current MSX-BASIC program pointer
	exx				; Save the program pointer on HL'. (*You also could save it in memory)
	
	ld	a,0c3h			; [JP]
	ld	(HNEWS+0),a		; (4601H) Hook of Runloop New Statement in MSX-BASIC
	ld	hl,retFromCLEAR		; [FF3EH]
	ld	(HNEWS+1),hl		; Force to return here on the Runloop called immediately after CLEAR handler
	
	; Change HIMEM directly and run CLEAR with "200" because CLEAR X automatically update all vars. according HIMEM
	ld	hl,0D000H		; Set new Address for HIMEM here <==============================================
	ld	(HIMEM),hl		; Set HIMEM directly to avoid the need to string conversion to CLEAR statement
	ld	hl,STCLEAR		; CLEAR statement string
	add	a,h			; Set NZ flag to inform that CLEAR has arguments
	call	BAS.CLEAR		; (64AFH) BASIC CLEAR Handler. (Maybe also: LD IX,BAS.CLEAR | CALL CALBAS)
	
retFromCLEAR
	ld	a,0c9h			; [RET]
	ld	(HNEWS),a		; Clear HNEWS (*can be improved, restoring previous values from previous app.)
	pop	hl			; INC SP*2 to fix SP exactly like a standart CLEAR call (*it seems unnecessary)
	exx				; Restore BASIC program pointer from HL' to HL
	jp	BAS.RUNLOOP		; (4601H) Runloop New Statement. Back to BASIC and proceed to next statement.
	
STCLEAR	db	"200",0			; CLEAR command line "CLEAR200"  (Note: 200 is the default inital value for CLEAR)
Login or register to post comments

By hope-hunter

Supporter (2)

hope-hunter's picture

22-06-2019, 18:09

OPTION: If you don't want to use RUNLOOP address hardcoded, you can save the 3 address of Stack.
Note: It was checked only for a BLOAD ,R call. For a USR call is probably different.

After a BLOAD ,R the Stack has this 3 address:

POP BC  ; (Return point from BLOAD,R that has: POP HL / RET)
POP DE  ; (MSX-BASIC Program pointer)
POP HL  ; (RUNLOOP address: 4601H)
EXX     ; Save the 3 address from Stack

You can save this address on memory or using HL',DE',BC' (EXX) and after run CLEAR, you can put again this values on Stack and finish the assembly program using a simple RET.

EXX      ; Restore the 3 address from Stack
PUSH HL  ; Restore RUNLOOP return address
PUSH DE  ; Restore BASIC Program Pointer address (that will be used by RUNLOOP)
PUSH BC  ; Restore BLOAD,R CALL return. (that will restore the BASIC Pointer to RUN LOOP: POP HL|RET
RET      ; Exit assembly program

By shram86

Expert (88)

shram86's picture

25-07-2019, 18:45

Hi,
I tried using this code but it didn't work for me. I checked the redbook and discovered a very simple way of doing all the things the CLEAR statement does, without the need to call the routine itself.

This works great for my purposes, but I may have missed something. If anyone sees anything wrong, please let me know.

(Note that, if you are not using BASIC at all, you can set the "argument" value to 1). I also noticed that the IO allocation routine will shift these values, but I'm just going off of how the CLEAR statement handler behaves.

HIMEM: equ $f380
STKTOP: equ $f0a0
MEMSIZ: equ $f168
IOALLOC: equ $7e6b

    ld hl, $c5b7     ; example location, can be wherever you choose
    ld (HIMEM), hl     ; set the max memory location 
    ld hl, $c2d7        ; equals MEMSIZ value - 2 - 267*2 [i/o buffer size] - argument for CLEAR
    ld (STKTOP), hl   ; into the location for the top of the stack
    ld hl, $c39f        ; equals STKTOP + (size of CLEAR argument, in this case 200 (the default))
    ld (MEMSIZ), hl   ; top of string storage
    call IOALLOC      ; runs the setup routine necessary, and then returns