背景信息
我目前正在为商品C64开发一个编程API,使用Beta中的KickC,以便更容易地开发小型程序、应用程序和可能的一些游戏;我突然意识到,我可能需要一种方法来检查我的代码是否运行在PAL或NTSC机器上,在后一种情况下,NTSC机器,因为旧的NTSC C64比较新的C64版本少一条扫描线。
在寻求帮助之后,Robin给我发送了一段代码片段,其中包括附带了一个CMD SuperCPU (我的最终目标机器)。当他将其作为程序集发送时,我不得不按原样使用其中的大部分,但在KickC中使用ASM指令,如下所示:
/**
* This is the initialisation will
* determine the machine type
* by setting the getMachineType global
* as follows:
* 37 is PAL
* 5 is NTSC (old)
* 6 is NTSC (new)
* 0 (or any other value) is unknown
*
* For safety, the initial value of 0xc000
* is stored into the accumulator and
* pushed onto the stack; it is then
* restored after the getMachineType
* global is set
*
* @author Robin Harbron
*/
void setMachineType() {
asm {
lda $c000
pha
sei
__br1:
lda $d011
bmi __br1
__br2:
lda $d011
bpl __br2
__br3:
lda $d012
bit $d011
bpl __ex1
sta $c000
bmi __br3
__ex1:
cli
}
getMachineType = peek(0xc000);
asm {
pla
sta $c000
}
}在我的脚本顶部,我在全局声明了getMachineType,如下所示:
unsigned byte getMachineType;目前,我的peek()函数是这样工作的:
/**
* Returns a single byte from a specific
* memory location
*/
unsigned char peek(unsigned short location) {
unsigned char* memory = (char*)location;
unsigned char returnByte = *memory;
return returnByte;
}因此,现在我可以确定运行我的程序的主机上可用的扫描线数,从而更容易地创建与PAL和NTSC兼容的可执行文件。
KickC可从CSDb.dk下载,并将使用踢汇编程序构建和组装。
发布于 2021-12-19 20:10:36
您共享的组装代码是使用国际中心-Ⅱ芯片的SCROLY寄存器($D011)和光栅寄存器($D012)。
$D011的高比特是当前光栅扫描线中最重要的位,而$D012包含较低的8位。
NTSC系统有262 (或261?)扫描线,PAL有312。
汇编程序例程等待设置高位的瞬间,即扫描线256。
如果设置了高位,它会循环,直到没有设置为止:
__br1:
lda $d011
bmi __br1 // read $d011 again if high bit is set然后在高比特清晰的时候循环,一旦设置好就退出循环:
__br2:
lda $d011
bpl __br2 // read $ d011 again if high bit is clear然后从$d012下载栅格扫描线的下8位。
这将在$c000中存储较低8位的扫描线值,同时测试高比特,直到它再次清除为止。如果已清除,请不要存储较低的8位,而是通过__ex1退出循环
__br3:
lda $d012
bit $d011
bpl __ex1
sta $c000
bmi __br3
__ex1:
cli结果应该是观察到的最高扫描线的数目- 256。对于有262条扫描线的NTSC,这是返回值6(或者其他NTSC模型的返回值5)的地方,它是基于零的,所以5将是262 scanline NTSC版本的值。从零开始的扫描线312将是311,- 256 = 55,十六进制$37。那里的评论应该明确指出37是十六进制的。
您可以在优秀的"测绘商品64“一书中找到有关这些寄存器的信息。
您可以将所有这些汇编程序转换为C(除了设置中断禁用位并清除它:sei、cli),只需分配一个char *指针值0xD 011,另一个0xD 012,并使用C代码执行相同的操作。
char machineType = 0;
signed char * SCROLY = 0xd011;
char * RASTER = 0xd012;
asm {
sei
}
while (*SCROLY < 0) ; // spin until scaline wraps
while (*SCROLY > 0) ; // spin until high bit set again
while (true) {
char lines = *RASTER;
if (*SCROLY > 0)
break;
machineType = lines;
}
asm {
cli
}https://stackoverflow.com/questions/69451591
复制相似问题