Invoking the Basic interpreter from a ML program

By George

Supporter (7)

George's picture

07-10-2016, 15:22

I want to use some Basic functions, like the circle function, in my ML program. Is it possible to create a data block with tokenized Basic inside my ML program and then call the BASIC interpreter?

Login or register to post comments

By nikodr

Paladin (727)

nikodr's picture

07-10-2016, 17:49

When you go the asm way you dont need basic i think.
Do you have the bios references of msx? There you could find a lot of stuff to call much better than basic. Though you could make your own faster asm routines. Who needs circle, slow from basic?
I suspect it would be easier to make a basic program and insert ml as data and poke rin am the values.

By ARTRAG

Enlighted (6275)

ARTRAG's picture

07-10-2016, 22:33

This could be useful

	
FastCircle:

; credits to  Sean McLaughlin (<a href="mailto:sigma_zk@yahoo.com">sigma_zk@yahoo.com</a>) for his TI-83 code  -01/18/04 (mm/dd/yy)
; Note: this version clips the circle withing the 256x192 screen
;
;D = center_x
;E = center_y
;C = radius

	LD	A,C				;
	OR	A				;
	RET	Z				;
	RET	M				;
	
	LD	(_x),DE			;
	LD	B,0				; B = y
	LD	H,B				;
	LD	L,C				; 
	ADD	HL,HL			;
	LD	DE,3			;
	EX	DE,HL			;
	SBC	HL,DE			; HL = err = 3-radius*2

_loop:					;
	LD	DE,(_x)			; DE = (xc,yc)
	LD	A,C				; A = x
	CP	B				; nc if (x <= y)
	RET	C				;
;PSet(xc + x, yc + y)	;
	LD	A,E				; A = yc
	ADD	A,B				; A = yc + y
	LD	E,A				; E = yc + y
	EX	AF,AF'			;
	LD	A,D				; A = xc
	ADD	A,C				; A = xc + x
	LD	D,A				; DE = (xc+x,yc+y)
	push af				; save the C flag for X clipping
	CALL	nc,PSet		;
	
;PSet(xc + x, yc - y)	;
	LD	A,E				; A = yc + y
	SUB	B				; A = yc
	SUB	B				; A = yc - y
	LD	E,A				; DE = (xc+x,yc-y)
	pop	af				; restore the C flag for X clipping
	CALL	nc,PSet		;
	
;PSet(xc - x, yc - y)	;
	LD	A,D				; A = xc + x
	SUB	C				; A = xc
	SUB	C				; A = xc - x
	LD	D,A				; DE = (xc-x,yc-y)
	push af				; save the C flag for X clipping
	CALL	nc,PSet		;
;PSet(xc - x, yc + y)	;
	EX	AF,AF'			;
	LD	E,A				; DE = (xc-x,yc+y)
	pop	af				; restore the C flag for X clipping
	CALL	nc,PSet		;
;PSet(xc + y, yc + x)	;
	LD	A,E				; A = yc + y
	SUB	B				; A = yc
	ADD	A,C				; A = yc + x
	LD	E,A				; E = yc + x
	LD	A,D				; A = xc - x
	ADD	A,C				; A = xc
	ADD	A,B				; A = xc + y
	LD	D,A				; DE = (xc+y,yc+x)
	PUSH	AF			; save[XC+Y] and C flag for X clipping
	CALL	nc,PSet		;
;PSet(xc - y, yc + x)	;
	LD	A,D				; A = xc + y
	SUB	B				; A = xc
	SUB	B				; A = xc - y
	LD	D,A				; DE = (xc-y,yc+x)
	push	af			; save the C flag for X clipping
	CALL	nc,PSet		;
;PSet(xc - y, yc - x)	;
	LD	A,E				; A = yc + x
	SUB	C				; A = yc
	SUB	C				; A = yc - x
	LD	E,A				; DE = (xc-y,yc-x)
	pop	af				; restore the C flag for X clipping
	CALL	nc,PSet		;
;PSet(xc + y, yc - x)	;
	POP	AF				; A = xc + y		and C flag for X clipping
	LD	D,A				; DE = (xc+y,yc-x)
	CALL	nc,PSet		;

;if(d < 0) err += y << 2 + 6
	BIT	7,H				;
	JR	Z,_PosError
	EX	DE,HL			;
	LD	H,0				;
	LD	L,B				;
	ADD	HL,HL			;
	ADD	HL,HL
	ADD	HL,DE
	LD	DE,6
	ADD	HL,DE
	INC	B
	JP	_loop

_PosError:
;err += (y - x) << 2 + 10: y--
	LD	DE,10
	ADD	HL,DE
	DEC	D
	LD	A,B
	SUB	C
	ADD	A,A
	RL	D
	ADD	A,A
	RL	D
	LD	E,A
	ADD	HL,DE
	INC	B
	DEC	C
	JP	_loop

					
	global _tmp

PSet:
	ld	a,0C0h-1
	cp	e
	ret c					
	
	push de    ; D = x, E = y
	exx
	pop	bc
	
	;Y -> C
	;X -> B

	
	ld	hl,_tmp
	LD (HL),C
	LD A,B
	AND 7
	LD C,A
	XOR B
	XOR 6
	RRD
	di
	OUT (99h),A
	LD E,A
	LD A,(HL)
	RLCA
	LD D,A
	and	7fh
	OUT (99h),A
	LD H,0D8h
	LD A,(DE)
	LD L,C
	XOR (HL)
	LD (DE),A
	OUT (98h),A
	ei
	exx
	ret

psect	bss,class=DATA
	
_x:	defs	1
	defs	1

Note that _tmp is a byte in ram and _x is a word in ram

By samsaga2

Resident (53)

samsaga2's picture

08-10-2016, 08:45

You can call a msx basic program from assembler. http://karoshi.auic.es/index.php?topic=2684.0

The example basic code:
BSAVE"PATATA.BIN", &HC000 y &HC119

The asm code to execute the basic example:

10 		ORG  &HC000
   20 BSAVEDSK:	EQU  &H39CC
   30 CHGET:	EQU  &H9F
   40 CALBAS:	EQU  &H159
   50 		LD   HL, LINBAS
   60 		LD   IX, (BSAVEDSK)
   70 		CALL CALBAS
   80 		CALL CHGET
   90 		RET 
  100 LINBAS:	DEFB &H22
  110 		DEFM "PATATA.BIN"
  120 		DEFB &H22
  130 		DEFM ",&HC000"
  140 		DEFM ",&HC119"
  150 		DEFB &H00
  160 FIN:	NOP

By N.I

Master (165)

N.I's picture

08-10-2016, 11:05

There is also the following way.

ld hl,_basstr
call 42B2H  ;CRUNCH
ld hl,F41FH
call 4601H ;NEWSTT
ret
_basstr: defm ":CIRCLE(10,10),10,10:PAINT(10,10),10,10"
defb 0

By George

Supporter (7)

George's picture

09-10-2016, 07:23

Great! I will look at the proposed solutions. I am a newbie in assembly programming for the MSX and try to convert a BASIC program to assembly language for an exercise.

The proposed solution from ARTRAG is worth studying, but is in my case (for now) overdone. I have to do also some other graphical instructions and the performance in BASIC is fast enough in my case. I have written a program to dump a compressed image of the screen to the screen in assembly and some minor changes to the screen can be done in BASIC. It works in the BASIC program also fast enough.

I wonder if the the example from samsaga2 "PATATA.BIN" is to save it self.

I shall try the solution from N.I. now. Is it possible to create and use some BASIC variables with this method?
Like:
"A%=100"
"CIRCLE(A%,96),50,15"

By the way! I use OPENMSX and write assembly using the z80asm cross-assembler under linux.

By N.I

Master (165)

N.I's picture

09-10-2016, 09:33

George wrote:

I shall try the solution from N.I. now. Is it possible to create and use some BASIC variables with this method?

The method to call NEWSTT(4601H) can use the BASIC variables Smile
When NEWSTT is called, the program returns to BASIC prompt.
The following program will work well.

ld hl,_basstr1
call _execbas
ld hl,_basstr2
call _execbas
ld hl,_basstr3
call _execbas
ret

_execbas:
call 42B2H  ;CRUNCH
pop hl
ld a,0c3h
ld (0f55eh),a
ld (0f55fh),hl
ld hl,0f41fh
jp 4601h ;NEWSTT

_basstr1: defm ":DEFUSR1=&HF55E:X=USR1(0)"
defb 0
_basstr2: defm ":A=10:B=10:X=USR1(0)"
defb 0
_basstr3: defm ":PRINT A+B:X=USR1(0)"
defb 0

By George

Supporter (7)

George's picture

09-10-2016, 18:40

Thank you for your reaction N.I, I will try it. Face

By NYYRIKKI

Enlighted (5396)

NYYRIKKI's picture

10-10-2016, 12:20

Hmm... Instead of #F55E I would propably try HPRGE (#FEF8) or HREAD (#FF07) instead in order to get rid of that DEFUSR / USR stuff... Naturally this means that in this case you have to manually clear the hooks if you plan to exit the program.

By N.I

Master (165)

N.I's picture

12-10-2016, 07:31

NYYRIKKI wrote:

Hmm... Instead of #F55E I would propably try HPRGE (#FEF8) or HREAD (#FF07) instead in order to get rid of that DEFUSR / USR stuff... Naturally this means that in this case you have to manually clear the hooks if you plan to exit the program.

Thanks for your advice. The following corrected program also worked well.

HPRGE: equ 0fef8h

;--- save the hook
ld hl,HPRGE
ld de,_hprge_org
ld bc,5
ldir

;---
ld hl,_basstr1
call _execbas
ld hl,_basstr2
call _execbas
ld hl,_basstr3
call _execbas

;--- return the hook
ld hl,_hprge_org
ld de,HPRGE
ld bc,5
ldir

ret

_execbas:
call 42B2h  ;CRUNCH
pop hl
ld a,0c3h
ld (HPRGE),a
ld (HPRGE+1),hl
ld hl,0f41fh
jp 4601h ;NEWSTT

_basstr1: defm ":SCREEN1:WIDTH32:KEYOFF"
defb 0
_basstr2: defm ":A=10:B=10"
defb 0
_basstr3: defm ":PRINT A+B"
defb 0
_hprge_org:
defs 5