Checking Free RAM in ML

Basic and Machine Language

Moderator: Moderators

User avatar
GreyGhost
Vic 20 Nerd
Posts: 526
Joined: Wed Oct 05, 2005 11:10 pm

Checking Free RAM in ML

Post by GreyGhost »

Was wondering if their is a way to check free RAM in machine language. Was wanting to try writing a program similar to Mike's clock program that would show a running total of memory in the bottom 6 screen locations under the border as you were entering it into memory. Maybe even the line you are typing as you type it. That might be a feat in itself though. Might even be useful when a basic program is running to see memory being used.

Any ideas?
Rob
User avatar
Kweepa
Vic 20 Scientist
Posts: 1302
Joined: Fri Jan 04, 2008 5:11 pm
Location: Austin, Texas
Occupation: Game maker

Post by Kweepa »

Here's what BASIC does when you call FRE(0) (taken from http://www.mdawson.net/vic20chrome/vic2 ... sembly.txt):

Code: Select all

JSR $D526 ; go do garbage collection
SEC       ; set carry for subtract
LDA $33   ; get bottom of string space low byte
SBC $31   ; subtract end of arrays low byte
TAY       ; copy result to Y
LDA $34   ; get bottom of string space high byte
SBC $32   ; subtract end of arrays high byte
You should probably skip the garbage collection call if you're doing this in an interrupt, since it won't play nicely with BASIC.

You could print AY in hex to that part of the screen pretty easily. Alternatively you could use a routine from here:
http://www.codebase64.org/doku.php?id=b ... conversion
to convert to decimal first for printing.

Very nice idea, by the way!

As for the size of the line as you are entering it, as you say that would be a feat - as far as I know, the VIC doesn't attempt to "enter" the line until you press the RETURN key. You'd probably have to parse the line yourself, using the screen line link table at $D9 to find the start of the line.
User avatar
Jeff-20
Denial Founder
Posts: 5757
Joined: Wed Dec 31, 1969 6:00 pm

Post by Jeff-20 »

I'm also interested in your idea. Let us know when you have something ready. I'd be excited to test it.
High Scores, Links, and Jeff's Basic Games page.
Boray
Musical Smurf
Posts: 4064
Joined: Mon May 03, 2004 10:47 am

Post by Boray »

Where are you planning to put your code? The tape buffer could be a good choice.
PRG Starter - a VICE helper / Vic Software (Boray Gammon, SD2IEC music player, Vic Disk Menu, Tribbles, Mega Omega, How Many 8K etc.)
User avatar
GreyGhost
Vic 20 Nerd
Posts: 526
Joined: Wed Oct 05, 2005 11:10 pm

Post by GreyGhost »

Yeah, that was my first choice. If I can make it small enough, maybe the rs-232 buffer. I've been thinking of other things that might be interesting to implement as well. Having a running total of free memory will be nice, but I'm thinking about being able to toggle variable, array and string space used. Might be helpful while a program is running to see these on the fly. Maybe a CTRL-F7 to switch between them. Depends on what I can squeeze into one of the buffers. LOL or maybe both of them. I definitely don't want to use any basic ram. So, I'm thinking the bottom of the screen will look something like this:

F28159:for free ram
V00032:for variables
A:arrays, S:string ect...

Who knows, may even sound a buzzer and flash the screen red when free ram is getting short. Getting kinda bloated now.

I haven't touched any code in over a year now, so it is gonna be a relearning experience for me.

I noticed that their is a Start of Variables, an End of variables and only an End of Strings, and an End of Arrays. Is the Start of Variables and End of Variables all inclusive? Meaning does it include strings, arrays, integer ect...? Are all they variables grouped together? How are the stacked in memory? Which is first, second ect..?
Rob
User avatar
Kweepa
Vic 20 Scientist
Posts: 1302
Joined: Fri Jan 04, 2008 5:11 pm
Location: Austin, Texas
Occupation: Game maker

Post by Kweepa »

From the kernal disassembly again, here is the memory map:

Code: Select all

BASIC program
VARIABLES
ARRAYS

free space

STRINGS (growing down)
top of RAM
Note that every time you create a new variable, it has to move the arrays up in memory to accommodate it! You can see this in action at $D11D.

You could let the program cycle automatically through its outputs.
wimoos
Vic 20 Afficionado
Posts: 352
Joined: Tue Apr 14, 2009 8:15 am
Website: http://wimbasic.webs.com
Location: Netherlands
Occupation: farmer

WimBasic implementation

Post by wimoos »

You mention the RS232 buffer. In VIC20, when you open an RS232 device, a receive buffer and a transmit buffer of each 256 bytes is grabbed from the top of Basic RAM.

The following code is the implementation of the MEM command in WimBasic. The MEM command sits behind the f8 key per default.
It uses $DDCD to display A:X in decimal on the screen. You cannot use that while in an interrupt routine because it might conflict with STR$ or LIST.

Regards,

Wim.

Code: Select all

;
LA021	.BYTE $0D 	 
	.TEXT "MEMORY" 	 
	.BYTE $BA 	 
	.TEXT "PROGRAM" 	 
	.BYTE $BA 	 
	.TEXT "VARIABLES" 	 
	.BYTE $BA 	 
	.TEXT "ARRAYS" 	 
	.BYTE $BA 	 
	.TEXT "STRINGS" 	 
	.BYTE $BA 	 
	.TEXT "FREE" 	 
	.BYTE $BA
LA029	.TEXT "BYTES" 	 
	.BYTE $8D
; 	 
LTAB2	.BYTE $37
	.BYTE $2D
	.BYTE $2F
	.BYTE $31
	.BYTE $37
	.BYTE $33
;
LTAB3	.BYTE $2B
	.BYTE $2B
	.BYTE $2D
	.BYTE $2F
	.BYTE $33
	.BYTE $31
;
;
	LDX  #$FA
	LDY  #$00
	STY  $84
	STY  $86
	.BYTE $2C
LLOOP	LDY  $87
	LDA  LTAB2-$FA,X
	STA  $83
	LDA  LTAB3-$FA,X
	STA  $85
	TXA
	PHA
	JSR  LA87B
	STY  $87
	LDY  #$00
	LDA  ($83),Y
	SBC  ($85),Y
	TAX
	INY
	LDA  ($83),Y
	SBC  ($85),Y
	LDY  #$0A      	 
	STY  $D3       	 
	JSR  $DDCD     	 
	LDY  #$10      	 
	STY  $D3       	 
	LDY  #LA029-LA021      	
	JSR  LA87B
	PLA
	TAX
	INX
	BNE  LLOOP
	RTS
	 
LA87B	LDA  LA021,Y   	 
	PHP            	 
	AND  #$7F      	 
	JSR  $CB47     	 
	INY            	 
	PLP            	 
	BPL  LA87B     	 
	RTS            	 
VICE; selfwritten 65asmgen; tasm; maintainer of WimBasic
User avatar
GreyGhost
Vic 20 Nerd
Posts: 526
Joined: Wed Oct 05, 2005 11:10 pm

Post by GreyGhost »

My mistake. Not a buffer, but the memory area 664-767.

I'm glad you said something about $ddcd not working in an interrupt. I've been looking at about 50 bytes of code for the past 2 days wondering why it has been crashing on me. I'm using it right now just to get the rest of the program working. When finished, I'll have to STA each individual decimal number in it's place.

Thank you for the listing, this should be enough to get this thing working.

By the way, I have never ran into this before can you explain?

Code: Select all

LDY  #LA029-LA021     
Rob
tlr
Vic 20 Nerd
Posts: 588
Joined: Mon Oct 04, 2004 10:53 am

Post by tlr »

GreyGhost wrote:By the way, I have never ran into this before can you explain?

Code: Select all

LDY  #LA029-LA021     
That equates to the number of bytes between those labes.

Things like this are common practice:

Code: Select all

msg:
    dc.b "string"
MSG_LEN    equ *-msg
Last edited by tlr on Tue Oct 22, 2013 10:43 am, edited 1 time in total.
wimoos
Vic 20 Afficionado
Posts: 352
Joined: Tue Apr 14, 2009 8:15 am
Website: http://wimbasic.webs.com
Location: Netherlands
Occupation: farmer

Post by wimoos »

Hello Rob,

Just like tlr said. The assembler will compute the number of bytes between the two labels and will build an appriopriate LDY # instruction.
At runtime Y will be loaded with the value and the routine at LA87B will then print the text "BYTES", followed by <CR>.

Regards,

Wim.
VICE; selfwritten 65asmgen; tasm; maintainer of WimBasic
User avatar
Mike
Herr VC
Posts: 4976
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Post by Mike »

GreyGhost wrote:My mistake. Not a buffer, but the memory area 664-767.
The addresses from 659 to 672 inclusive are used by the KERNAL for the Pseudo 6551 registers. There's a 'free' area from 673 upwards, up to address 767 (the so-called program indirects). Actually, the Super Expander uses that area for workspace.
I'm glad you said something about $ddcd not working in an interrupt. I've been looking at about 50 bytes of code for the past 2 days wondering why it has been crashing on me.
That pretty much applies to *any* routine within BASIC interpreter and KERNAL. Most of these are not intended to be called from an interrupt. If you do so, it can happen that you re-enter a routine which has just half-executed as the interrupt occured. The second call from within the interrupt will then likely disturb internal state variables of that routine, and this leads to undefined behaviour once the interrupt exits to the foreground again.
User avatar
Mike
Herr VC
Posts: 4976
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: Checking Free RAM in ML

Post by Mike »

I thought it might be a good idea a post a working solution before this thread dies of old age ...

Code: Select all

10 FORT=828TO951:READA:POKET,A:NEXT:SYS828
11 DATA 120,169,83,141,20,3,169,3,141,21,3,173,3,144,41,128,9,48,141,3,144,88,96,216,56
12 DATA 165,51,229,49,133,251,165,52,229,50,133,252,248,169,0,133,3,133,4,133,5,162,16
13 DATA 6,251,38,252,165,3,101,3,133,3,165,4,101,4,133,4,165,5,101,5,133,5,202,208,231
14 DATA 216,169,250,133,251,133,253,174,136,2,232,134,252,138,41,3,9,148,133,254,160,0
15 DATA 169,3,162,4,6,3,38,4,38,5,42,202,208,246,145,251,173,134,2,145,253,200,192,6
16 DATA 208,230,76,191,234
The code doesn't quite fit into the area 673..767, for this reason I had to put it into the tape buffer.

What is output as 'free space' is the difference between 'top of arrays + 1' (stored at $31/$32) and 'bottom of string space' (stored at $33/$34), neatly converted from binary to BCD to PETSCII. I reused a routine in MINIPAINT which is used there to output the block counts in the directory display, except it now doesn't bother to crop the leading zeroes.

In both versions I took the bin to BCD conversion from an example by Andrew Jacobs posted at http://www.6502.org. Otherwise, I'm not going to provide source code this time - you'll have to infer yourself how it works ...

... and if anyone wants to put an equivalent routine into 673 .. 767 - go ahead. :)
wimoos
Vic 20 Afficionado
Posts: 352
Joined: Tue Apr 14, 2009 8:15 am
Website: http://wimbasic.webs.com
Location: Netherlands
Occupation: farmer

Re: Checking Free RAM in ML

Post by wimoos »

The code below takes 92 bytes and fits in the 673-767 area. Start with SYS673.

Regards,

Wim.

Code: Select all

	.org 673
	sei
	lda #ticket & $ff
	sta $0314
	lda #ticket >> 8
	sta $0315
	lda $9003
	and #$80
	ora #$30
	sta $9003
	cli
	rts

ticket	sec
	lda $33
	sbc $31
	sta $fb
	lda $34
	sbc $32
	sta $fc
	lda #$fa
	sta $03
	sta $05
	lda $0288
	adc #$00
	sta $04
	and #$03
	ora #$94
	sta $06
	ldy #$05
div3	ldx #$10
	lda #$00
div2	asl $fb
	rol $fc
	rol a
	cmp #$0a
	bcc div1
	sbc #$0a
	inc $fb
div1	dex
	bne div2
	ora #'0'
	sta ($03),y
	lda $0286
	sta ($05),y
	dey
	bpl div3
	jmp $eabf
	.end
VICE; selfwritten 65asmgen; tasm; maintainer of WimBasic
User avatar
Mike
Herr VC
Posts: 4976
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: Checking Free RAM in ML

Post by Mike »

wimoos wrote:The code below takes 92 bytes and fits in the 673-767 area. Start with SYS673.
Now, that's quite a feat. And you even kept the niceties I put in to adapt to the different RAM configurations, especially regarding the screen and colour RAM base addresses. 8)

I'd still keep the CLD in front of the interrupt server, though, in case the foreground program executes some instructions in decimal mode.

Cheers,

Michael

P.S. in case anyone is wondering about the use of the zeropage addresses 3..6 here, they're supposed to contain vectors to two routines for conversion between ASCII/PETSCII <-> FAC (floating point accumulator). As it happens, even though BASIC initialises these 4 bytes, neither BASIC itself, nor any program I know uses these vectors to jump to the corresponding routines, they're always directly called. Consequently, I regard these four bytes as essentially free (similar to $FB .. $FE) for own projects.
wimoos
Vic 20 Afficionado
Posts: 352
Joined: Tue Apr 14, 2009 8:15 am
Website: http://wimbasic.webs.com
Location: Netherlands
Occupation: farmer

Re: Checking Free RAM in ML

Post by wimoos »

I'd still keep the CLD in front of the interrupt server, though, in case the foreground program executes some instructions in decimal mode.
Just like the Zp $03-$06 and $FB-FE are never used in CBM Basic or the Kernal, there is no instance of a SED. So a CLD would not be needed.... :D

Regards,

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