标签: 6502

基本的NES仿真理论 - 我被困住了

事先,我为这个问题的开放性和一般的清醒道歉,因为老实说,我对这个话题的了解非常不完整,我发现很难描述我的问题.我真的不想发帖,但我完全被完全卡住了.

我已经启动了NES模拟器.它被解释(所以没有动态重新编译).

它可以加载和映射roms(mapper 0 roms)并执行init代码,直到我必须处理中断和PPU.那就是我被困住的地方.

这是我的emu atm的示例输出.执行从8000开始,我在800a处无限循环,我不知道如何从那里进步.

8002: LDA #$10    ; read immediate value to set PPU control registers 
8004: STA $2000   ; store value 
8007: LDX #$FF    ; load immediate value into X register 
8009: TXS         ; store X register into stack 
800a: LDA $2002   ; read PPU flags into accumulator (set N flag based on bit 7) 
800d: BPL         ; test N flag, branch to 800a if not positive, (N is set) 
800a: LDA $2002
800d: BPL
800a: …
Run Code Online (Sandbox Code Playgroud)

assembly interrupt 6502 emulation nintendo

6
推荐指数
1
解决办法
1434
查看次数

为什么6502的中断标志的初始状态为1?

我正在模拟6502处理器,我差不多完成了(现在处于测试阶段)并且我正在使用来自nesdev站点的一些NES测试,它告诉我中断标志和未使用的第5个标志都是最初应该设置为1(即禁用中断),但为什么呢?我可以理解未使用的标志部分,因为它......很好......未使用,但我不明白中断标志.我试过在Google上搜索,有些网站确认它应该设置为1,但没有人解释这背后的原因.为什么中断应该从程序开始被阻止?

flags interrupt 6502 emulation cpu-registers

6
推荐指数
1
解决办法
1518
查看次数

C/C++中的6502仿真器:如何将寻址模式代码与实际指令代码分开

在业余时间,我开始为6502 CPU编写一个非常简单的C++仿真器.我以前写了很多的汇编代码为这个CPU,这样所有的操作码,寻址方式和其他的东西是不是一个大问题.

6502具有56种不同的指令和13种寻址模式,总共有151种不同的操作码.对我来说速度不是问题,所以不要写一个巨大的switch-case语句并反复重复相同的代码(不同的操作码可以使用不同的寻址模式引用相同的指令)我想将实际的指令代码与寻址模式代码:我发现这个解决方案很整齐,因为它需要只写13寻址模式功能和56个指令功能,无需重复自己.

这里的寻址模式功能:

// Addressing modes
uint16_t Addr_ACC(); // ACCUMULATOR
uint16_t Addr_IMM(); // IMMEDIATE
uint16_t Addr_ABS(); // ABSOLUTE
uint16_t Addr_ZER(); // ZERO PAGE
uint16_t Addr_ZEX(); // INDEXED-X ZERO PAGE
uint16_t Addr_ZEY(); // INDEXED-Y ZERO PAGE
uint16_t Addr_ABX(); // INDEXED-X ABSOLUTE
uint16_t Addr_ABY(); // INDEXED-Y ABSOLUTE
uint16_t Addr_IMP(); // IMPLIED
uint16_t Addr_REL(); // RELATIVE
uint16_t Addr_INX(); // INDEXED-X INDIRECT
uint16_t Addr_INY(); // INDEXED-Y INDIRECT
uint16_t Addr_ABI(); // ABSOLUTE INDIRECT
Run Code Online (Sandbox Code Playgroud)

它们都返回指令用来读/写操作数/结果的实际存储器地址(16位)

指令函数原型是:

void Op_ADC(uint16_t addr);
void Op_AND(uint16_t addr);
void Op_ASL(uint16_t addr); …
Run Code Online (Sandbox Code Playgroud)

c++ assembly 6502 emulation addressing-mode

6
推荐指数
1
解决办法
1406
查看次数

到底是什么中断?

我想了解Logisim中类似我的6502工作处理器项目的确切中断是什么。我知道中断会执行以下步骤:

  1. 停止处理当前程序
  2. 将所有未完成的数据保存到堆栈中
  3. “某事”
  4. 装回未完成的数据,让程序继续正常运行。

    我的问题是:在“某些步骤中会发生什么?程序计数器是否重定向到要执行的特殊程序?像读取按钮的ASCII码并将其保存到寄存器或某个内存位置中一样?如果是这样,那个特殊程序通常存储在存储器中的什么位置?而且,您可以制造这样一种CPU来处理各种中断吗?也许如果您按下按钮“ a”,那么它的ASCII将被存储在A寄存器中,但是如果您按下按钮“ b”,那么它将被存储在X寄存器中?

任何帮助是极大的赞赏。

编辑:谢谢大家的答案。我学到了很多东西,现在可以继续进行我的项目了。

hardware interrupt 6502 cpu-architecture

6
推荐指数
1
解决办法
210
查看次数

CBM Program Studio汇编程序语法

我正在努力学习CBM Program Studio.但我不能让宏为我工作.在宏观上,代码还可以.但是当我添加宏部分时,它在第7行给出了"无匹配结束定义".

任何的想法?

        *=$c000 ; sys 49152

        ; set screen colors to black 
        lda #$00
        sta $d020
        sta $d021

defm    waitmacro ;akumulatörü hac?l?yor   
        TYA
mloop   DEY
        BNE mloop
        TAY     
        endm waitmacro

        ;color bars
        LDX #$FF
loop    LDY #$07
        STY $d020

        waitmacro

        INY
        STY $d020

        waitmacro

        DEX
        BNE loop
        RTS
Run Code Online (Sandbox Code Playgroud)

assembly c64 6502 6510

5
推荐指数
1
解决办法
916
查看次数

NMI和IRQ中断

我试图找到关于6502 proccesor如何处理中断的信息,但我很困惑.我已经看过一些关于它的例子,但它就像一个普通的subrutine.

我对8086处理器有一些经验,我记得有一些代码可以处理不同的中断.

首先,如果有人能用一些代码解释NMI和IRQ之间的差异,我将非常感激.甚至更多,如果您获得有关处理中断的更多信息(例如)处理键盘中断.

assembly 6502

5
推荐指数
2
解决办法
2733
查看次数

如何在6502 asm中将16位数除以2?

我想将16位数除以2.我对这个问题的解决方案如下

    lda $17 ;set high byte
    ldx $32    ;set low byte

divide:
    PHA         ;push A to stack        
    TXA         ;X > A  
    LSR         ;divide low byte by 2   
    TAX         ;A > X

    PLA         ;pull A from stack  
    LSR         ;divide high byte by 2
    BCC +       ;C=0, skip

    PHA         ;while C=1
    TXA         ;add $80 to the lsb
    ADC #$80
    TAX
    PLA 
+   
    +printDecimal $0400+120
Run Code Online (Sandbox Code Playgroud)

所有PHA/PLA技巧都是因为我的printDecimal宏从A读取MSB,从X读取LSB.

当我在网上检查替代品时,我发现了4个指令替代我的简单划分例程.但我不明白.

div2:
    LDA counter_hi       ;Load the MSB
    ASL                  ;Copy the sign bit into …
Run Code Online (Sandbox Code Playgroud)

assembly c64 6502

5
推荐指数
1
解决办法
1626
查看次数

自修改内存复制例程练习,6502 ASM

下面是我在 Commodore 64 上进行内存复制的自我修改例程。

我写了char codesnumber of repeats在一个表中,充满了screen_ram的这个套路。

我正在寻找优化建议。在这种情况下,我的优先事项是内存。

memCopy:    
  sourceAddress=*+1 ; mark self modifying addrres
fetchNewData:
  lda data_table    ; read char value into A
  ldx data_table+1  ; read repeat value into x
  inc sourceAddress     
  inc sourceAddress 

  cpx #00           ; if X=0 
  beq end           ; finish copying

  destination=*+1
- sta SCREEN_RAM
  inc destination
  dex
  bne -

  jmp fetchNewData

end:
  rts   

; data format:  <char>,<number of repeats>,[<char>,<number of repeats>,...],00,00

data_table: 
!by 01,03,02,02,......,00,00
Run Code Online (Sandbox Code Playgroud)

assembly 6502

5
推荐指数
1
解决办法
879
查看次数

6502 汇编语言中结构数组相对于并行数组的优点?

我从当时写的大量 6502 中了解到,并行数组比存储数据的结构更好。

想象一下,您想要一个怪物统计数据表,在 C 中可以像这样定义

struct Monster {
  unsigned char hitPoints;
  unsigned char damage;
  unsigned char shieldLevel;
  char* name;
};
Run Code Online (Sandbox Code Playgroud)

您可以将其存储为结构数组

static Monster s_monsters[] = {
  { 5,   1, 0, "orc", },
  { 50, 10, 5, "dragon", },
  { 10,  3, 1, "goblin", },
};
Run Code Online (Sandbox Code Playgroud)

或者您可以将其存储为并行数组(通常使用宏或工具来生成)。注意:我用 C 语言显示代码,但请想象它是 6502 汇编。

unsigned char Monster_hitPoints[] = { 5, 50, 10, };
unsigned char Monster_damage[] = { 1, 10, 3, },
unsigned char Monster_sheildLevel[] = { 0, 5, 1, };
unsigned char …
Run Code Online (Sandbox Code Playgroud)

assembly 6502

5
推荐指数
1
解决办法
2866
查看次数

我无法理解堆栈是如何工作的

我正在为 MOS6502 处理器构建一个模拟器,目前我正在尝试用代码模拟堆栈,但我真的无法理解堆栈在 6502 的上下文中是如何工作的。

6502 堆栈结构的特点之一是,当堆栈指针到达堆栈末尾时,它会回绕,但我什至不明白这个功能是如何工作的。

比方说,我们有64个最大值堆栈如果我们推值xyz压入堆栈,我们现在有以下结构。堆栈指针指向 address 0x62,因为这是压入堆栈的最后一个值。

+-------+
|   x   | 0x64
+-------+
|   y   | 0x63
+-------+
|   z   | 0x62 <-SP
+-------+
|       | ...
+-------+
Run Code Online (Sandbox Code Playgroud)

一切都很好。但是现在如果我们从堆栈中弹出这三个值,我们现在有一个空堆栈,堆栈指针指向 value0x64

+-------+
|       | 0x64 <-SP
+-------+
|       | 0x63
+-------+
|       | 0x62
+-------+
|       | ...
+-------+
Run Code Online (Sandbox Code Playgroud)

如果我们第四次弹出堆栈,堆栈指针会环绕指向 address 0x00,但是当0x00??没有值时,这样做还有什么意义?堆栈中什么都没有,那么将堆栈指针包裹起来有什么意义????

我可以在推送值时理解这个过程,如果堆栈已满并且需要将值推送到堆栈,它将覆盖堆栈中最旧的值。这不适用于弹出。

有人可以解释一下,因为它没有意义。

stack 6502

5
推荐指数
1
解决办法
1023
查看次数