برنامه نویسی

SPO600 LAB 2 – انیمیشن در صفحه نمایش bitmap

مقدمه

خوش آمدید ، بیایید با 6502 مونتاژ بیشتر ادامه دهیم. در آخرین پست وبلاگ ، صفحه نمایش Bitmap معرفی شد و پر از رنگ های مختلف خواهد بود. از آن کشف شد که صفحه نمایش Bitmap از صفحه 2 به صفحه 5 (یعنی $0200 - $0500).

امروز یک تصویر از طریق صفحه نمایش bitmap متحرک می شود. در زیر کد استارت ارائه شده توسط کریس تایلر ، مربی دوره SPO600 ارائه شده است. ما به استفاده از شبیه ساز 6502 ادامه خواهیم داد.

;
; draw-image-subroutine.6502
;
; This is a routine that can place an arbitrary 
; rectangular image on to the screen at given
; coordinates.
;
; Chris Tyler 2024-09-17
; Licensed under GPLv2+
;

;
; The subroutine is below starting at the 
; label "DRAW:"
;

; Test code for our subroutine
; Moves an image diagonally across the screen

; Zero-page variables
define XPOS $20
define YPOS $21

START:

; Set up the width and height elements of the data structure
  LDA #$05
  STA $12       ; IMAGE WIDTH
  STA $13       ; IMAGE HEIGHT

; Set initial position X=Y=0
  LDA #$00
  STA XPOS
  STA YPOS

; Main loop for diagonal animation
MAINLOOP:

  ; Set pointer to the image
  ; Use G_O or G_X as desired
  ; The syntax #
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

کد استارت یک دایره آبی را در گوشه سمت چپ بالای صفحه نمایش Bitmap متحرک می کند و سپس آن را به صورت مورب به گوشه پایین سمت راست منتقل می کند و به طور نامحدود تکرار می شود. برای درک چگونگی عملکرد این کار ، بیایید هر روال/زیرروال را تجزیه کنیم و سپس نحوه کار آنها را توضیح دهیم.

تنظیم اولیه

متغیرهای صفحه صفر

; Zero-page variables
define XPOS $20
define YPOS $21
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

define یک کلمه کلیدی خاص است که ثابت را تعریف می کند. در این حالت ، XPOS وت YPOS مکان های حافظه مربوطه را برای مختصات تصویر نشان می دهد.

تنظیم موضع

START:
  LDA #$05
  STA $12       ; IMAGE WIDTH
  STA $13       ; IMAGE HEIGHT

  LDA #$00
  STA XPOS
  STA YPOS
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

تصویر ابعاد دارد 5x5 و مختصات اولیه از 0,0، گوشه سمت چپ بالای صفحه نمایش Bitmap.

حلقه انیمیشن اصلی

MAINLOOP:
  LDA #<G_O
  STA $10
  LDA #>G_O
  STA $11
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

حلقه های اصلی انیمیشن آدرس تصویر را در باتری بار می کند و سپس بایت کم و بالا و پایین خود را در مکان های حافظه ذخیره می کند $10 وت $11 به ترتیب

  ; Place the image on the screen
  LDA #$10  ; Address in zeropage of the data structure
  LDX XPOS  ; X position
  LDY YPOS  ; Y position
  JSR DRAW  ; Call the subroutine
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

بایت کم تصویر در مختصات x و y بارگذاری شده است – اینجاست DRAW Subroutine شروع به ترسیم تصویر به صفحه نمایش Bitmap می کند.

تاخیر

  LDY #$00
  LDX #$50
DELAY:
  DEY
  BNE DELAY
  DEX
  BNE DELAY
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

در DELAY روال کند می شود DRAW روال برای نمایش یک تصویر “جامد”. بدون DELAY، تصویر به سرعت چشمک می زند. 2 حلقه وجود دارد – یک حلقه بیرونی که 256 بار y را افزایش می دهد ، و یک حلقه داخلی که 80 بار کاهش می یابد. در مجموع 80 * 256 = 20480 تکرارها

متحرک تصویر

  ; Set pointer to the blank graphic
  LDA #<G_BLANK
  STA $10
  LDA #>G_BLANK
  STA $11

  ; Draw the blank graphic to clear the old image
  LDA #$10 
  LDX XPOS
  LDY YPOS
  JSR DRAW

  ; Increment the position
  INC XPOS
  INC YPOS

  LDA #28
  CMP XPOS
  BNE MAINLOOP

  ...
; Image of a black square
G_BLANK:
DCB $00,$00,$00,$00,$00
DCB $00,$00,$00,$00,$00
DCB $00,$00,$00,$00,$00
DCB $00,$00,$00,$00,$00
DCB $00,$00,$00,$00,$00
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

برای “تحریک” تصویر ، تصویر فعلی با جایگزینی تصویر با پیکسل های سیاه “خالی” می شود. بایت کم سپس در باتری بارگیری می شود ، موقعیت x و y تصویر در ثبت های مربوطه در جایی که افزایش می یابد بارگیری می شود. تصویر در موقعیت X ، Y جدید خود ترسیم می شود – تکمیل انیمیشن. پس از 29 “حرکات” و سپس همان انیمیشن به طور نامحدود تکمیل می شود.

DRAW زیرروال

در DRAW Subroutine مهمترین قسمت برنامه است – محاسبه می کند که در هر تکرار تصویر در کجا می رود.

define IMGPTR    $A0
define IMGPTRH   $A1
define IMGWIDTH  $A2
define IMGHEIGHT $A3
define SCRPTR    $A4
define SCRPTRH   $A5
define SCRX      $A6
define SCRY      $A7
...

DRAW:
  STY SCRY
  STX SCRX
  TAY
  LDA $0000,Y
  STA IMGPTR
  LDA $0001,Y
  STA IMGPTRH
  LDA $0002,Y
  STA IMGWIDTH
  LDA $0003,Y
  STA IMGHEIGHT

حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

این کار با بارگیری موقعیت مرزهای صفحه و خصوصیات تصویر (مختصات X ، Y ، ارتفاع و عرض) از آدرس های حافظه مربوطه شروع می شود و آنها را در آدرس های ثبت نام از پیش تعریف شده ذخیره می کند – این مقادیر بعداً هنگام محاسبه موقعیت به آنها دسترسی پیدا می کنند برای تصویر بعدی

محاسبه موقعیت صفحه نمایش

  LDA #$00
  STA SCRPTRH
  LDA SCRY
  STA SCRPTR
  LDY #$05
MULT:
  ASL SCRPTR
  ROL SCRPTRH
  DEY
  BNE MULT
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

مراحل محاسبه:

  1. باتری را پاک کنید ، اینجاست که محاسبه انجام می شود
  2. باتری را با هماهنگی Y تصویر بارگیری کنید
  3. هماهنگ y سپس با آن بارگیری می شود 5تعداد شیفت ها برای حرکت پیکسل از آنجا که هر ردیف 32 بایت طول دارد.

    1 | 2 | 4 | 8 | 16 | 32 
    ^ | 2 | 3 | 4 | 5  | 6 
    current
    
  4. در MULT روتین بیت ها را به سمت چپ تغییر می دهد ASL وت ROL حمل را به داخل می چرخاند SCRPTRH، رجیستری Y سپس کاهش می یابد و تا y = 0 تکرار می شود.

LDA SCRX
CLC
ADC SCRPTR
STA SCRPTR
LDA #$00
ADC SCRPTRH
STA SCRPTRH

حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

  1. محاسبه هماهنگ X علاوه بر این – جایی که بایت کم اضافه می شود و به دنبال بایت بالا اضافه می شود. در ADC SCRPTR بایت کم را با حمل به باتری اضافه می کند. این مقدار حمل سپس با حمل بایت بالا اضافه می شود.
  2. در این مرحله ، SCRPTR وت SCRPTRH آدرس های نهایی را برای تصویر تبدیل شده نگه دارید.

درج تصویر تبدیل شده

LDA #$02
CLC
ADC SCRPTRH
STA SCRPTRH
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

آدرس پایه نمایش bitmap از 02 بارگذاری شده است ، با پرچم حمل پاک شده است. نشانگر صفحه نمایش بایت بالا با اضافه کردن تنظیم می شود SCRPTRH در آخرین مرحله محاسبه می شود.

COPYROW:
  LDY #$00
ROWLOOP:
  LDA (IMGPTR),Y
  STA (SCRPTR),Y
  INY
  CPY IMGWIDTH
  BNE ROWLOOP
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

بایت ها از IMGPTR به باتری ، سپس به SCRPTR که حافظه مربوط به مکان در صفحه نمایش bitmap است. حلقه متوقف می شود وقتی ثبت Y به انتهای ردیف تصویر می رسد.

LDA IMGWIDTH
CLC
ADC IMGPTR
STA IMGPTR
LDA #$00
ADC IMGPTRH
STA IMGPTRH
LDA #32
CLC
ADC SCRPTR
STA SCRPTR
LDA #$00
ADC SCRPTRH
STA SCRPTRH
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

برای پیشرفت به ردیف بعدی ، عرض تصویر در باتری بارگذاری می شود. IMGPTR سپس به عرض تصویر اضافه می شود و ردیف بعدی را در تصویر پیش می برد. نشانگر تصویر به روز شده در آن ذخیره می شود IMGPTRبشر 32 توسط اضافه شده به SCRPTR در باتری پس از آن دوباره به داخل ذخیره می شود SCRPTRبشر همان فرآیندها با بایت بالا ، با بایت حمل انجام می شود.

بیایید با تغییر موقعیت شروع شروع کنیم. با بارگیری باتری با مقادیر مختلف و ذخیره آن در XPOS وت YPOSبشر

START:
  LDA #$05
  STA $12       ; IMAGE WIDTH
  STA $13       ; IMAGE HEIGHT

  LDA #$0F
  STA XPOS
  LDA #$0A
  STA YPOS
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

بعد بیایید وقتی با دیوار صفحه نمایش bitmap تماس برقرار کنیم ، گزاف گویی گرافیکی را انجام دهیم. برای انجام این کار ما می توانیم علامت را معکوس کنیم (به عنوان مثال +/- ) از جهت x و y هنگامی که گرافیک با دیوار تماس می گیرد.

برای انجام این کار بیایید یک مقدار ثابت را برای نشان دادن لبه صفحه تعریف کنیم:

; Zero-page variables
define XPOS $20
define YPOS $21
define MAXP $24
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

در مرحله بعد ما باید جهت تصویر را ردیابی کنیم ، آیا آن “به جلو” یا “به عقب” حرکت می کند؟ در این مورد “به عقب” حرکت می کند ، جهت می تواند معکوس شود و برعکس.

; Zero-page variables
define XPOS $20
define YPOS $21
define MAXP $24
define CURDIR $25
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

علامت X و Y نیز نیاز به ردیابی دارند تا بدانند محورهای مربوطه برای حرکت به چه جهت نیاز دارند.

; Zero-page variables
define XPOS $20
define YPOS $21
define MAXP $22
define CURDIR $23
define XFLAG $24
define YFLAG $25
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

ما متغیرهای لازم را ردیابی می کنیم ، اکنون بیایید منطق معکوس کردن علامت را هنگام رسیدن به لبه پیاده سازی کنیم.

ابتدا بیایید اولیه کنیم CURDIR برای داشتن یک ارزش 0 برای نشان دادن جهت رو به جلو و MAXP #$19، لبه صفحه.

START:
  LDA #$00
  STA CURDIR
  LDA #$19
  STA MAXP
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

بعد بیایید پرونده ای را که تصویر با یک زیرروال به لبه برخورد می کند ، پیاده سازی کنیم:

  1. مقدار مربوط به لبه را بارگیری کنید
  2. جریان را مقایسه کنید XPOS با مقدار لبه
  3. فراخوانی CHECK_START برای بررسی اینکه از گوشه سمت چپ بالا برخورد کرده است
    1. از آنجا که علائم معکوس هستند ، با توجه به موقعیت شروع جدید ، همیشه به گوشه سمت چپ می رسد.
CHECK_DIRECTION:
  LDA MAXP
  CMP XPOS
  BNE CHECK_START
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

CHECK_START:
  LDA XPOS
  CMP #$00
  BNE CONTINUE_LOOP
  LDA #$00
  STA CURDIR
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

CONTINUE_LOOP بررسی می کند که آیا انیمیشن به پایان رسیده است و آن را به طور نامحدود تکرار می کند. بیایید کد را با هم نگاه کنیم.

;
; draw-image-subroutine.6502
;
; This is a routine that can place an arbitrary 
; rectangular image on to the screen at given
; coordinates.
;
; Chris Tyler 2024-09-17
; Licensed under GPLv2+
;

;
; The subroutine is below starting at the 
; label "DRAW:"
;

; Test code for our subroutine
; Moves an image diagonally across the screen

; Zero-page variables
define XPOS $20
define YPOS $21
define MAXP $22 
define CURDIR $23
define XFLAG $24
define YFLAG $25

START:
  LDA #$00
  STA CURDIR

  LDA #$19
  STA MAXP

  ; Set up image width & height
  LDA #$05
  STA $12
  STA $13

  ; Set initial position X=Y=0
  LDA #$09
  STA XPOS
  LDA #$0A
  STA YPOS

MAINLOOP:

  ; Set pointer to the image
  LDA #<G_O
  STA $10
  LDA #>G_O
  STA $11

; Put image on bitmap display
  LDA #$10  
  LDX XPOS  
  LDY YPOS  
  JSR DRAW 

; Delay to show the image
  LDY #$00
  LDX #$50
DELAY:
  DEY
  BNE DELAY
  DEX
  BNE DELAY

  ; Put pointer to blank image
  LDA #<G_BLANK
  STA $10
  LDA #>G_BLANK
  STA $11

  ; Clear previous image position
  LDA #$10  
  LDX XPOS
  LDY YPOS
  JSR DRAW

  LDA CURDIR
  BEQ INCREMENT_POS

  DEC XPOS
  DEC YPOS
  JMP CHECK_DIRECTION

INCREMENT_POS:
  INC XPOS
  INC YPOS

CHECK_DIRECTION:
  LDA MAXP
  CMP XPOS
  BNE CHECK_START

  LDA XPOS
  STA CURDIR
  JMP CONTINUE_LOOP

CHECK_START:
  LDA XPOS
  CMP #$00
  BNE CONTINUE_LOOP
  LDA #$00
  STA CURDIR

CONTINUE_LOOP:
  LDA #28
  CMP XPOS
  BNE MAINLOOP
  ; Repeat infinitely
  JMP START

  ; ==========================================
  ;
  ; DRAW :: Subroutine to draw an image on 
  ;         the bitmapped display
  ;
  ; Entry conditions:
  ;    A - location in zero page of: 
  ;        a pointer to the image (2 bytes)
  ;        followed by the image width (1 byte)
  ;        followed by the image height (1 byte)
  ;    X - horizontal location to put the image
  ;    Y - vertical location to put the image
  ;
  ; Exit conditions:
  ;    All registers are undefined
  ;
  ; Zero-page memory locations
  define IMGPTR    $A0
  define IMGPTRH   $A1
  define IMGWIDTH  $A2
  define IMGHEIGHT $A3
  define SCRPTR    $A4
  define SCRPTRH   $A5
  define SCRX      $A6
  define SCRY      $A7

  DRAW:
    ; SAVE THE X AND Y REG VALUES
    STY SCRY
    STX SCRX

    ; GET THE DATA STRUCTURE
    TAY
    LDA $0000,Y
    STA IMGPTR
    LDA $0001,Y
    STA IMGPTRH
    LDA $0002,Y
    STA IMGWIDTH
    LDA $0003,Y
    STA IMGHEIGHT

    ; CALCULATE THE START OF THE IMAGE ON
    ; SCREEN AND PLACE IN SCRPTRH
    ;
    ; THIS IS $0200 (START OF SCREEN) +
    ; SCRX + SCRY * 32
    ; 
    ; WE'LL DO THE MULTIPLICATION FIRST
    ; START BY PLACING SCRY INTO SCRPTR
    LDA #$00
    STA SCRPTRH
    LDA SCRY
    STA SCRPTR
    ; NOW DO 5 LEFT SHIFTS TO MULTIPLY BY 32
    LDY #$05     ; NUMBER OF SHIFTS
  MULT:
    ASL SCRPTR   ; PERFORM 16-BIT LEFT SHIFT
    ROL SCRPTRH
    DEY
    BNE MULT

    ; NOW ADD THE X VALUE
    LDA SCRX
    CLC
    ADC SCRPTR
    STA SCRPTR
    LDA #$00
    ADC SCRPTRH
    STA SCRPTRH

    ; NOW ADD THE SCREEN BASE ADDRESS OF $0200
    ; SINCE THE LOW BYTE IS $00 WE CAN IGNORE IT
    LDA #$02
    CLC
    ADC SCRPTRH
    STA SCRPTRH
    ; NOTE WE COULD HAVE DONE TWO: INC SCRPTRH

    ; NOW WE HAVE A POINTER TO THE IMAGE IN MEM
    ; COPY A ROW OF IMAGE DATA
  COPYROW:
    LDY #$00
  ROWLOOP:
    LDA (IMGPTR),Y
    STA (SCRPTR),Y
    INY
    CPY IMGWIDTH
    BNE ROWLOOP

    ; NOW WE NEED TO ADVANCE TO THE NEXT ROW
    ; ADD IMGWIDTH TO THE IMGPTR
    LDA IMGWIDTH
    CLC
    ADC IMGPTR
    STA IMGPTR
    LDA #$00
    ADC IMGPTRH
    STA IMGPTRH

    ; ADD 32 TO THE SCRPTR
    LDA #32
    CLC
    ADC SCRPTR
    STA SCRPTR
    LDA #$00
    ADC SCRPTRH
    STA SCRPTRH

    ; DECREMENT THE LINE COUNT AND SEE IF WE'RE
    ; DONE
    DEC IMGHEIGHT
    BNE COPYROW

    RTS

  ; ==========================================

  ; 5x5 pixel images

  ; Image of a blue "O" on black background
  G_O:
  DCB $00,$0e,$0e,$0e,$00
  DCB $0e,$00,$00,$00,$0e
  DCB $0e,$00,$00,$00,$0e
  DCB $0e,$00,$00,$00,$0e
  DCB $00,$0e,$0e,$0e,$00

  ; Image of a yellow "X" on a black background
  G_X:
  DCB $07,$00,$00,$00,$07
  DCB $00,$07,$00,$07,$00
  DCB $00,$00,$07,$00,$00
  DCB $00,$07,$00,$07,$00
  DCB $07,$00,$00,$00,$07

  ; Image of a black square
  G_BLANK:
  DCB $00,$00,$00,$00,$00
  DCB $00,$00,$00,$00,$00
  DCB $00,$00,$00,$00,$00
  DCB $00,$00,$00,$00,$00
  DCB $00,$00,$00,$00,$00
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

منطق آزمایشگاه ساده است ، اما اجرای آن به دلیل چگونگی کلامی مونتاژ دشوار است. ماهیت کلامی مونتاژ باعث شده است که من از زبانهای سطح بالا قدردانی کنم و چقدر پنهان است.

از آزمایشگاه ، من در مورد موارد استفاده برای زیرمجموعه ها ، نحوه و زمان اجرای زیرروه ها در کارهای روزمره ، و BNE بیانیه ها این شبیه به استفاده از حلقه های “برای” و اظهارات “if” در زبان های برنامه نویسی سطح بالا است.

به طور کلی ، من با این آزمایشگاه دوران سختی داشتم اما به روشی خوب – من آنچه را که در مورد مونتاژ تا این مرحله فهمیدم سؤال کردم و مهارت های تحلیل خود را به چالش کشیدم ، یک مهارت قابل انتقال که فراتر از کد مونتاژ است. با تشکر از خواندن! به زودی می بینیم!

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا