为 Sega Genesis #5 编写汇编

在这篇文章中,我将描述读取操纵杆、更改精灵位置、水平翻转、Sega Genesis 模拟器以及可能的控制台本身的过程。

读取点击并处理将棋操纵杆的“事件”按照以下方案进行:

  1. 请求按下按钮的位组合
  2. 读取按下的按钮的位
  3. 游戏逻辑级别的处理

要移动骨架精灵,我们需要存储当前位置的变量。

内存

游戏逻辑变量存储在RAM中;到目前为止人们还没有想出更好的办法。让我们声明变量地址并更改渲染代码:

skeletonYpos = $FF0002 
frameCounter = $FF0004 
skeletonHorizontalFlip = $FF0006

    move.w #$0100,skeletonXpos 
    move.w #$0100,skeletonYpos 
    move.w #$0001,skeletonHorizontalFlip 

FillSpriteTable: 
    move.l #$70000003,vdp_control_port 
    move.w skeletonYpos,vdp_data_port  
    move.w #$0F00,vdp_data_port 
    move.w skeletonHorizontalFlip,vdp_data_port 
    move.w skeletonXpos,vdp_data_port 

如您所见,可用于工作的地址从 0xFF0000 开始,到 0xFFFFFF 结束,总共有 64 KB 的内存可供我们使用。骨架位置在 sculptureXpos、sculptureYpos 处声明,水平翻转在 sculptureHorizo​​ntalFlip 处声明。

手柄

与 VDP 类比,游戏手柄的工作分别通过两个端口进行:控制端口和数据端口,第一个为0xA10009和0xA10003共号。使用游戏手柄时有一个有趣的功能——首先,您需要请求用于轮询的按钮组合,然后在等待总线上的更新后,读取所需的按键。对于 C/B 和 D-pad 按钮,这是 0x40,示例如下:

  move.b #$40,joypad_one_control_port; C/B/Dpad 
  nop ; bus sync 
  nop ; bus sync 
  move.b joypad_one_data_port,d2 
  rts 

在寄存器 d2 中,按钮按下或未按下的状态将保留,一般来说,通过日期端口请求的内容将保留。之后,转到您最喜欢的模拟器的 Motorola 68000 寄存器查看器,根据击键查看 d2 寄存器等于什么。您可以通过聪明的方式在手册中找到答案,但我们并不相信他们的话。进一步处理 d2

寄存器中按下的按钮

    cmp #$FFFFFF7B,d2; handle left 
    beq MoveLeft  
    cmp #$FFFFFF77,d2; handle right  
    beq MoveRight  
    cmp #$FFFFFF7E,d2; handle up  
    beq MoveUp  
    cmp #$FFFFFF7D,d2; handle down  
    beq MoveDown  
    rts

Проверять нужно конечно отдельные биты, а не целыми словами, но пока и так сойдет. Теперь осталось самое простое – написать обработчики всех событий перемещения по 4-м направлениям. Для этого меняем переменные в RAM, и запускаем процедуру перерисовки.

Пример для перемещения влево + изменение горизонтального флипа:

    move.w skeletonXpos,d0 
    sub.w #1,d0 
    move.w d0,skeletonXpos 
    move.w #$0801,skeletonHorizontalFlip 
    jmp FillSpriteTable

После добавления всех обработчиков и сборки, вы увидите как скелет перемещается и поворачивается по экрану, но слишком быстро, быстрее самого ежа Соника.

Не так быстро!

Чтобы замедлить скорость игрового цикла, существуют несколько техник, я выбрал самую простую и не затрагивающую работу с внешними портами – подсчет цифры через регистр пока она не станет равна нулю.

Пример замедляющего цикла и игрового цикла:

  move.w #512,frameCounter 
WaitFrame: 
  move.w frameCounter,d0 
  sub.w #1,d0 
  move.w d0,frameCounter 
  dbra d0,WaitFrame 
GameLoop: 
  jsr ReadJoypad 
  jsr HandleJoypad 
  jmp GameLoop 

此后,骨架运行速度变慢,这正是所需要的。据我所知,“放慢速度”的最常见选项是计算垂直同步标志;您可以计算屏幕被绘制的次数,从而与特定的 fps 相关联。

链接

https://gitlab .com/demensdeum/segagenesisamples/-/blob/main/8Joypad/vasm/main.asm

来源

https://www.chibiakumas.com/68000/platform2.php
https://huguesjohnson.com/programming/genesis/tiles-sprites/

Leave a Comment

Your email address will not be published. Required fields are marked *