ML routines in BASIC programs

Basic and Machine Language

Moderator: Moderators

Post Reply
User avatar
Jeff-20
Denial Founder
Posts: 5759
Joined: Wed Dec 31, 1969 6:00 pm

ML routines in BASIC programs

Post by Jeff-20 »

I've never used ML routines in any game program, but the speed benefit is tempting. When I consider a joystick routine, it seems as if the ML code would take up more memory than a basic joystick code.

Is a memory efficient ML routine to read joysticks possible?

Let's say the code is to simply add 1, 22, -1, or -22 to a variable based on joystick input. The most memory efficient way to do this seems to be basic, right?
High Scores, Links, and Jeff's Basic Games page.
tlr
Vic 20 Nerd
Posts: 567
Joined: Mon Oct 04, 2004 10:53 am

Re: ML routines in BASIC programs

Post by tlr »

Jeff-20 wrote:I've never used ML routines in any game program, but the speed benefit is tempting. When I consider a joystick routine, it seems as if the ML code would take up more memory than a basic joystick code.

Is a memory efficient ML routine to read joysticks possible?

Let's say the code is to simply add 1, 22, -1, or -22 to a variable based on joystick input. The most memory efficient way to do this seems to be basic, right?
How would you code it in basic? I'll try to improve it in ml.
User avatar
Jeff-20
Denial Founder
Posts: 5759
Joined: Wed Dec 31, 1969 6:00 pm

Post by Jeff-20 »

notes:
(joystick variables) D=37154:P=37151:Q=37152
Y=character location on screen,J=temp variable

Code: Select all

1 POKE37154,255:P=37151:Q=P+1
routine:
2 M=PEEK(P): J=Y: IF(MAND4)=.THENJ=J-22 
3 IF(MAND8)=.THENJ=J+22 
4 IF(MAND16)=.THENJ=J-1 
5 IF(PEEK(Q)AND128)=.THENJ=J+1 
6 IFPEEK(J)>2THENPOKEY,33: Y=J: POKEY,2: GOTO2 
Can this routine be SYSed for greater speed without using up more memory? It seems pretty tight as a basic routine. I made four seperate IF lines because it seems faster for the computer to refuse each conditional and jump to the next line rather than all the computations if I combined all four possible joystick inputs into one line.
High Scores, Links, and Jeff's Basic Games page.
carlsson
Class of '6502
Posts: 5516
Joined: Wed Mar 10, 2004 1:41 am

Post by carlsson »

I think you mean POKE 37154,127 in order to be able to read that last direction?

Anyway, I came up with something like this. There are a few more improvements over your routine, like rough boundary checking etc. You can remove it if it doesn't matter if you run outside of the video matrix.

Code: Select all

#processor 6502
#seg code

jp eqm $fb ; pointer $fb-$fc
yp eqm $fd ; pointer $fd-$fe
m eqm $ff

	org 7168
	lda #10	; POKE 36879,10
	sta $900f
	lda #147	; PRINT"[CLR]"
	jsr $ffd2
	lda realy		; If Y is meant to come from a Basic variable,
	sta yp		; it gets slightly more complicated here..
	lda realy+1
	sta yp+1
main:	
	jsr joy
	lda #100
wrl$:	
	cmp $9004		; Some kind of delay loop, otherwise it gets
	bne wrl$		; much too fast
	jmp main

joy:
	lda #127
	sta 37154
loop:
	lda 37151
	eor #$ff	; invert byte
	and #28	; bits 2-4 (4+8+16)
	lsr	; shift down to bits 1-3 (2+4+8)
	sta m
	lda 37152
	and #128
	bne goon
	inc m	; effectively turn on bit 0
goon:
	lda yp
	sta jp
	lda yp+1
	sta jp+1
	ldy #4
compare:
	lsr m
	bcc nochg
	lda dir-1,y
	tax
	clc
	adc jp	; low/high
	sta jp	; handle carry/overflow below
	php
	txa
	bmi minus
	plp
	bcc nochg
	inc jp+1	; if positive addition, increase page
	bcs nochg
minus:
	plp
	bcs nochg ; this was a bit tricky, how to detect backwards page break
	dec jp+1
nochg:
	dey
	bne compare
	lda jp+1
	cmp #$1e                  ; boundary check
	bmi out		; loop
	cmp #$20
	bpl out		; loop
	cmp #$1f
	bmi chk
	lda jp
	cmp #$fa
	bcs out
chk:
	lda (jp),y
	cmp #2
	bcc out
	lda #33
	sta (yp),y
	lda jp
	sta yp
	lda jp+1
	sta yp+1
	lda #2
	sta (yp),y
			; bne loop
out:	
	rts

dir:	.byte -1,22,-22,1
realy:	.word 7680
I don't know if you really want to loop until you reach "B" or less. This routine assembles to 148 bytes, of which 32 are initialization, 2 byte (realy) may come from outside and 20 bytes are boundary check. It means the core joystick routine would be about 94 bytes, not counting the zero page locations used.
Anders Carlsson

Image Image Image Image Image
User avatar
Mike
Herr VC
Posts: 4816
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Post by Mike »

This is my version, a BASIC/ML hybrid:

Code: Select all

0 POKE1,18:POKE2,16:REM{39 Z's}
1 FORT=0TO38:READA:POKE4114+T,A:NEXT
2 DATA173,31,145,74,74,41,7,170,173,32,145,73,128,41,128,10,125,50,16,8
3 DATA168,173,57,16,40,16,2,169,255,76,145,211,255,21,233,255,255,22,234
RUN this once. After this you can delete the lines 1-3. Never edit line 0. Your routine then reduces to:

Code: Select all

1 POKE37154,127
2 J=Y+USR(0):IFPEEK(J)>2THENPOKEY,33:Y=J:POKEY,2:GOTO2
Greetings,

Michael
TMR
Vic 20 Amateur
Posts: 65
Joined: Fri Jul 01, 2005 3:00 am

Post by TMR »

One minor point; the code could be dumped into the tape buffer, that'll reduce it's memory footprint considerably...?
carlsson
Class of '6502
Posts: 5516
Joined: Wed Mar 10, 2004 1:41 am

Post by carlsson »

Or for that matter in the space 673-767. Otherwise, a very clever routine Mike. It looks something like this when disassembled:

Code: Select all

LDA 37151
LSR
LSR
AND #7 ; bits are 1 for unused directions
TAX
LDA 37152
EOR #128 ; invert upper bit
AND #128 
ASL ; shift it out as carry flag, and accumulator will contain zero
ADC dir,x
PHP
TAY
LDA dir+7 ; effectively zero
PLP
BPL out
LDA #255 ; make negative value
out: JMP $D391 ; convert integer in (A/Y) to FLPT in (FAC)
dir: .byte $FF,$15,$E9,$FF,$FF,$16,$EA,$00
It appears the routine as listed relies on the end-of-line byte 0, so if positioned elsewhere in memory, it should be extended with the last zero byte as shown above.
Anders Carlsson

Image Image Image Image Image
tlr
Vic 20 Nerd
Posts: 567
Joined: Mon Oct 04, 2004 10:53 am

Post by tlr »

TMR wrote:One minor point; the code could be dumped into the tape buffer, that'll reduce it's memory footprint considerably...?
I think the point is that once you run it and delete the lines after 0, you can save it to disk and get the code "inlined" in the basic program. The strange LDA to get a '0' is so you won't have any '0's in the code, messing up the basic rem line.

Very neatly done!
wimoos
Vic 20 Afficionado
Posts: 345
Joined: Tue Apr 14, 2009 8:15 am
Website: http://wimbasic.webs.com
Location: Netherlands
Occupation: farmer

Another 4 bytes saved

Post by wimoos »

Code: Select all

dir: 		.byte $FF,$15,$E9,$FF,$FF,$16,$EA,$00

		LDA 37151 
		LSR A
		LSR A
		AND #7 ; bits are 1 for unused directions 
		TAY
		LDA 37152
		EOR #128 ; invert upper bit 
		AND #128 
		ASL A ; shift it out as carry flag, and accumulator will contain zero 
		TAX
		ADC dir,y 
		BPL out
		DEX
out:		TAY
		TXA
		JMP $D391 ; convert integer in (A/Y) to FLPT in (FAC) 
I'm getting the hang of it...
VICE; selfwritten 65asmgen; tasm; maintainer of WimBasic
wimoos
Vic 20 Afficionado
Posts: 345
Joined: Tue Apr 14, 2009 8:15 am
Website: http://wimbasic.webs.com
Location: Netherlands
Occupation: farmer

Re: ML routines in BASIC programs

Post by wimoos »

I improved on this one:

Code: Select all

LA107	LDA  $911F     	 
	AND  #$1C
	LSR  A         	 
	LSR  A         	       	 
	TAY
	LDA  LA0FF-1,Y            	 
	LDX  $9122     	 
	LDY  #$7F      	 
	STY  $9122     	 
	BIT  $9120     	 
	STX  $9122
	BMI  LA109
	ADC  #$01	 
LA109	JMP  $DC3C
LA0FF	.BYTE $15 	 
	.BYTE $E9 	 
	.BYTE $FF 	 
	.BYTE $FF 	 
	.BYTE $16 	 
	.BYTE $EA 	 
	.BYTE $00
Regards,

Wim.
VICE; selfwritten 65asmgen; tasm; maintainer of WimBasic
Post Reply