Skip to content

Commit 2a6dee1

Browse files
committed
Add RANDOMIZE command
We use our own RNG instead of the C library RNG; this should ensure that demo.6502 builds an identical demo.ssd on all platforms. Thanks to "sweh" for pointing out a bug (now fixed) in beebasm_rand() during development.
1 parent 474f160 commit 2a6dee1

10 files changed

+141
-5
lines changed

about.txt

+8
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,13 @@ ASSERT a [, b, c, ...]
657657
Abort assembly if any of the expressions is false.
658658

659659

660+
RANDOMIZE <n>
661+
662+
Seed the random number generator used by the RND() function. If this is
663+
not used, the random number generator is seeded based on the current time
664+
and so each build of a program using RND() will be different.
665+
666+
660667

661668

662669
7. TIPS AND TRICKS
@@ -763,6 +770,7 @@ based on the above demo, but it runs at a low address (&300).
763770

764771
9. VERSION HISTORY
765772

773+
23/04/2016 Added RANDOMIZE
766774
12/03/2016 Improved error handling in PUTFILE/PUTBASIC
767775
Added optional automatic line numbering for PUTBASIC
768776
Added ASSERT

demo.6502

+5
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ ORG 0
5050
.behindflag SKIP 1
5151

5252

53+
\\ Seed the random number generator so the build is repeatable
54+
55+
RANDOMIZE 42
56+
57+
5358
\\ Set start address
5459

5560
ORG &1100

demo.ssd

0 Bytes
Binary file not shown.

src/commands.cpp

+38-1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "asmexception.h"
3636
#include "discimage.h"
3737
#include "BASIC.h"
38+
#include "random.h"
3839

3940

4041
using namespace std;
@@ -75,7 +76,8 @@ const LineParser::Token LineParser::m_gaTokenTable[] =
7576
{ "MACRO", &LineParser::HandleMacro, &SourceFile::StartMacro },
7677
{ "ENDMACRO", &LineParser::HandleEndMacro, &SourceFile::EndMacro },
7778
{ "ERROR", &LineParser::HandleError, 0 },
78-
{ "COPYBLOCK", &LineParser::HandleCopyBlock, 0 }
79+
{ "COPYBLOCK", &LineParser::HandleCopyBlock, 0 },
80+
{ "RANDOMIZE", &LineParser::HandleRandomize, 0 }
7981
};
8082

8183

@@ -1986,3 +1988,38 @@ void LineParser::HandleCopyBlock()
19861988
throw AsmException_SyntaxError_UnexpectedComma( m_line, m_column );
19871989
}
19881990
}
1991+
1992+
1993+
/*************************************************************************************************/
1994+
/**
1995+
LineParser::HandleRandomize()
1996+
*/
1997+
/*************************************************************************************************/
1998+
void LineParser::HandleRandomize()
1999+
{
2000+
unsigned int value;
2001+
2002+
try
2003+
{
2004+
value = EvaluateExpressionAsUnsignedInt();
2005+
}
2006+
catch ( AsmException_SyntaxError_SymbolNotDefined& )
2007+
{
2008+
if ( GlobalData::Instance().IsFirstPass() )
2009+
{
2010+
value = 0;
2011+
}
2012+
else
2013+
{
2014+
throw;
2015+
}
2016+
}
2017+
2018+
beebasm_srand( value );
2019+
2020+
if ( m_column < m_line.length() && m_line[ m_column ] == ',' )
2021+
{
2022+
// Unexpected comma (remembering that an expression can validly end with a comma)
2023+
throw AsmException_SyntaxError_UnexpectedComma( m_line, m_column );
2024+
}
2025+
}

src/expression.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "globaldata.h"
3636
#include "objectcode.h"
3737
#include "sourcefile.h"
38+
#include "random.h"
3839

3940

4041
using namespace std;
@@ -1306,11 +1307,11 @@ void LineParser::EvalRnd()
13061307
}
13071308
else if ( val == 1.0f )
13081309
{
1309-
result = rand() / ( static_cast< double >( RAND_MAX ) + 1.0 );
1310+
result = beebasm_rand() / ( static_cast< double >( BEEBASM_RAND_MAX ) + 1.0 );
13101311
}
13111312
else
13121313
{
1313-
result = static_cast< double >( static_cast< int >( rand() / ( static_cast< double >( RAND_MAX ) + 1.0 ) * val ) );
1314+
result = static_cast< double >( static_cast< int >( beebasm_rand() / ( static_cast< double >( BEEBASM_RAND_MAX ) + 1.0 ) * val ) );
13141315
}
13151316

13161317
m_valueStack[ m_valueStackPtr - 1 ] = result;

src/globaldata.h

-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,6 @@ class GlobalData
7474
bool m_bUseDiscImage;
7575
DiscImage* m_pDiscImage;
7676
int m_forId;
77-
int m_randomSeed;
7877
bool m_bSaved;
7978
const char* m_pOutputFile;
8079
int m_numAnonSaves;

src/lineparser.h

+1
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ class LineParser
156156
void HandleEndMacro();
157157
void HandleError();
158158
void HandleCopyBlock();
159+
void HandleRandomize();
159160

160161
// expression evaluating methods
161162

src/main.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include "discimage.h"
3737
#include "BASIC.h"
3838
#include "macro.h"
39+
#include "random.h"
3940

4041

4142
using namespace std;
@@ -235,7 +236,7 @@ int main( int argc, char* argv[] )
235236
GlobalData::Instance().SetPass( pass );
236237
ObjectCode::Instance().InitialisePass();
237238
GlobalData::Instance().ResetForId();
238-
srand( static_cast< unsigned int >( randomSeed ) );
239+
beebasm_srand( static_cast< unsigned long >( randomSeed ) );
239240
SourceFile input( pInputFile );
240241
input.Process();
241242
}

src/random.cpp

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*************************************************************************************************/
2+
/**
3+
random.cpp
4+
5+
Simple Lehmer random number generator; used instead of the native C library's generator
6+
so RANDOMIZE+RND() gives consistent results on all platforms. The constants used are those
7+
for C++11's minstd_rand. See https://en.wikipedia.org/wiki/Lehmer_random_number_generator
8+
9+
Copyright (C) Rich Talbot-Watkins 2007 - 2012
10+
Copyright (C) Steven Flintham 2016
11+
12+
This file is part of BeebAsm.
13+
14+
BeebAsm is free software: you can redistribute it and/or modify it under the terms of the GNU
15+
General Public License as published by the Free Software Foundation, either version 3 of the
16+
License, or (at your option) any later version.
17+
18+
BeebAsm is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
19+
even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20+
GNU General Public License for more details.
21+
22+
You should have received a copy of the GNU General Public License along with BeebAsm, as
23+
COPYING.txt. If not, see <http://www.gnu.org/licenses/>.
24+
*/
25+
/*************************************************************************************************/
26+
27+
#include "random.h"
28+
29+
static unsigned long state = 19670512;
30+
31+
static unsigned long modulus = BEEBASM_RAND_MODULUS;
32+
33+
void beebasm_srand(unsigned long seed)
34+
{
35+
state = seed % modulus;
36+
if ( state == 0 )
37+
{
38+
state = 1;
39+
}
40+
}
41+
42+
unsigned long beebasm_rand()
43+
{
44+
state = ( BEEBASM_RAND_MULTIPLIER * state ) % modulus;
45+
// It's always true that 1 <= state <= (modulus - 1), so we return state - 1 to make
46+
// 0 a possible value. BEEBASM_RAND_MAX is modulus - 2, so we have 0 <= return value <=
47+
// BEEBASM_RAND_MAX as required for compatibility with the interface of rand().
48+
return state - 1;
49+
}

src/random.h

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*************************************************************************************************/
2+
/**
3+
random.h
4+
5+
6+
Copyright (C) Rich Talbot-Watkins 2007 - 2012
7+
Copyright (C) Steven Flintham 2016
8+
9+
This file is part of BeebAsm.
10+
11+
BeebAsm is free software: you can redistribute it and/or modify it under the terms of the GNU
12+
General Public License as published by the Free Software Foundation, either version 3 of the
13+
License, or (at your option) any later version.
14+
15+
BeebAsm is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
16+
even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
GNU General Public License for more details.
18+
19+
You should have received a copy of the GNU General Public License along with BeebAsm, as
20+
COPYING.txt. If not, see <http://www.gnu.org/licenses/>.
21+
*/
22+
/*************************************************************************************************/
23+
24+
#ifndef RANDOM_H_
25+
#define RANDOM_H_
26+
27+
#define BEEBASM_RAND_MULTIPLIER (48271UL)
28+
#define BEEBASM_RAND_MODULUS (2147483647UL)
29+
#define BEEBASM_RAND_MAX (BEEBASM_RAND_MODULUS - 2UL)
30+
31+
void beebasm_srand(unsigned long seed);
32+
33+
unsigned long beebasm_rand();
34+
35+
#endif // RANDOM_H_

0 commit comments

Comments
 (0)