尝试使用JSR $E09A在我的Commodore 64(C64)上生成一系列随机数,并从$63和$64中检索数字。(根据我所看到的所有文档,当你从BASIC中使用RND(0)时,它是同一个例程。但不能让它迭代。下面的代码将工作,并在自己执行时在$63和$64中放置不同的数字。
. C000 A5 00 LDA $00
. C002 20 9A E0 JSR $E09A
. C005 00 BRK
现在,当我尝试用下面的代码迭代10次时,它永远不会返回。
. C000 A0 0A LDY #$0A
. C002 A9 00 LDA #$00
. C004 20 9A E0 JSR $E09A
. C007 88 DEY
. C008 D0 F8 BNE $C002
. C00A 00 BRK
我是不是错过了什么太明显的东西了。我不担心它有多“随机”。在这一点上,我只想要一系列随机数字。
8条答案
按热度按时间mzmfm0qo1#
感谢Ross Ridge建议被调用的函数改变了Y寄存器中的值。我就知道这一定是显而易见的事情!
通过将Y存储在
JSR
之前,并在之后恢复,它现在将正确地迭代。以下是快速解决方案:编辑:更新7/10/17 -显示完整的代码并纳入JeremyP的建议。这本质上是一个抛硬币迭代器(50000次重复),用于试验随机
我可以在循环中通过
LDA $63
或LDA $64
获得随机数,并将其用于我的目的。结果证明,这比预期的要慢得多,只花了BASIC中一半的时间。RND函数需要很多周期,但是,我发现这个Compute! article使用SID芯片作为随机数生成器。
一旦打开,它会独立生成数字,并且不必再次执行。重复调用
LDA $D41B
的循环将在每次迭代中获得一个新的随机数。在我的测试中,50,000次迭代耗时1.25秒,百万次迭代耗时24秒多一点。对于一台1 MHz的计算机来说,这是相当令人印象深刻的!33qvvth12#
您实际上是在调用
RND(0)
,它使用计时器生成一个种子。然而,这在组装中不能直接使用。首先尝试切换到一个正数(任何数字),看看它是否开始产生值。slhcrj9b3#
如果你没有定时光栅IRQ或类似的程序,你可以用
lda $d012
得到一个“随机”数。px9o7tmv4#
我发现这个线程在C64汇编中搜索更通用的RND(开始,结束)例程。如以下BASIC示例所实现的:
虽然这里有很多有用的答案,但我错过了这种解决方案,所以我必须找到自己的;这可能对另一个来这个帖子的人有帮助,所以这里是:
该例程使用范围为0 - 32767的16位数字。争论始于251,252;结束于253,254.在$14中找到16位结果。
niknxzdl5#
C64上的真实的问题是:
1.光栅位置不是随机的。
c64中真正的随机性的唯一来源是用户输入。
所以我要做的是:
1.初始化SID噪声波形
1.在启动时获取cia定时器1 LSB(这在普通c64上很好,但在仿真器上不是随机的)
1.启动cia定时器2
1.等待用户按下任意键(或操纵杆方向/按钮)
1.获取cia定时器2 LSB
1.获取SID幅度值
1.可选地获取光栅位置,但取决于你是从basic还是汇编程序调用这个例程,你可能不会得到一个完全随机的值。
然后,你有你最喜欢的伪随机例程的随机种子。或者只是一个16/24/32位随机数。
在游戏中,例如,当用户移动操纵杆时,您可以获得cia计时器并获得随机字节。
注意:在模拟器中删除prg或d 64与写入“load...”有很大的不同,因为每个用户每次写入的内容都不同,在这种情况下,计时器LSB是“随机的”。
在一些仿真器中,由于这个原因,随机延迟被添加到计算机启动。
eeq64g8w6#
pxq42qpu7#
现在已经很晚了,但根据需求,您也可以自己滚动PRNG。有些算法很容易实现,例如,我将在这里使用参数
[3,25,24]
展示一个32位xorshift实现(因为这使得其中两个移位使用很少的代码)。返回的随机数有16位:使用示例:
mkh04yzy8#
SID芯片实际上可以产生比BASIC的伪随机数更随机的数字。启动发生器:
然后你可以随时获得随机数,只要你想: