Page 1 of 1

why ? why not... but why ?

Posted: Sun Sep 02, 2018 3:41 pm
by waskol
If I compile this simple test program in OSDK :

Code: Select all

#include <lib.h>
char rnd(char max);
int i,st;
char n=0;
char stat[4]={0,0,0,0};

void main()
{
	for(i=0;i<10;i++) {
		n=rnd(3);
		printf(" n : %d ",n);
		stat[n]=stat[n]+1;
		printf(" n : %d ",n);		
		printf(" stat[n] : %d\n",stat[n]);
		//printf("%d\n",rand());
	}
	printf("\n");
	for(i=0;i<4;i++) printf("%d : %d\n",i,stat[i]);
}
 
 char rnd(char max)
 {
	int i1,i2,i3;
	i1=rand();
	i2=32768/max;
	i3=i1/i2;	
	return (char)i3;
 }
the output is a total nonsense (n is changed just before the computation of stat[n] !)
Now, if I rename the n variable by nn, or if I remove the include line, everything works as expected.

Please, can you reproduce this ?
Where is my bug ?

Thank you very much for your help.

Re: why ? why not... but why ?

Posted: Sun Sep 02, 2018 5:19 pm
by Dbug
Looks like it's a conflict between the two implementations of the rand function.

When the include file is not used, it uses the rand function that calls the ROM, when the include file is used, it calls the rand32() through a macro which makes no sense to me, either I was drunk or I was tired:

#define rand() (rand32()?(randseedTop & 0x7fff):(randseedTop & 0x7fff))

So one one side we have:

rand.s

Code: Select all

_rand
_random
        ldx #$ff
        jsr $E355
        ldx $D2
        lda $D1
        rts

_srandom
        ldy #0
        lda (sp),y
        sta $FC
        sta $FE
        iny
        lda (sp),y
        sta $FB
        sta $FD
        lda #$80
        sta $FA
        rts
and on the other:

random.s

Code: Select all

;
; int random(void) ; return a random value in 0..32767
;

_rand
_random


;
; int srandom(int seed) ; initialize the random generator
;

_srandom
which suspiciously looks like some stuff is missing...

but we find that in mult32:

Code: Select all

/*
int rand(void)
{
    return( ((_holdrand = _holdrand * 214013L + 2531011L) >> 16) & 0x7fff );
}
*/

_randseedLow .byt 0,0
_randseedTop .byt 0,0

_rand32
	;jmp _pcrand
.(
	; Left side, old seed
	lda _randseedLow+0
	sta tmp0+0
	lda _randseedLow+1
	sta tmp0+1
	lda _randseedLow+2
	sta tmp0+2
	lda _randseedLow+3
	sta tmp0+3
	
	; Righ side, 214013 -> $00 03 43 FD
	lda #$FD
	sta tmp2+0
	lda #$43
	sta tmp2+1
	lda #$03
	sta tmp2+2
	lda #$00
	sta tmp2+3
	
	; Multiply
	; Result in tmp4/5/6/6/7
	jsr mul32u
	
	; Add 2531011 -> $00 26 9E C3
	clc
	lda tmp4+0	
	adc #$C3
	sta _randseedLow+0
	lda tmp4+1
	adc #$9E
	sta _randseedLow+1
	lda tmp4+2	
	adc #$26
	sta _randseedLow+2
	lda tmp4+3	
	adc #$00
	sta _randseedLow+3
	
	rts
.)


To me it looks like some unfinished stuff that I probably forgot when I was working on FreeCell: My game needed a random generator which worked *exactly* like the one used on the Windows version, so this rand32 is the real deal.

Now, why the 32bit version of rand corrupts your variables... I don't know...

Try to comment the #define rand() in lib.h, see if that solve the issue.

Re: why ? why not... but why ?

Posted: Sun Sep 02, 2018 6:04 pm
by waskol
Thank you sir !

I can confirm you that if I comment the #define rand() in lib.h, it works as expected, and I gain about 400 bytes of data.

What is surprising, is that the value of n is just good right after the call to rnd() in my snippet. and you can put 1 or 2 more printf(" n : %d ",n); between the rnd and the array access, the value of n is good. n changes only when we access the array and not before.