home *** CD-ROM | disk | FTP | other *** search
/ Dream 55 / Amiga_Dream_55.iso / RISCOS / MAGAZINE / NEWS / PCE021.ZIP / Pce021 / Src / s / video < prev   
Text File  |  1998-07-24  |  29KB  |  1,159 lines

  1. ;    video.s
  2. ;    -------
  3. ;    PC Engine video emulation
  4. ;    by Paul Clifford
  5. ;
  6. ;    Started 16 August 1997
  7.  
  8.  
  9.     GET    hdr.SWINames
  10.     GET    hdr.defines
  11.  
  12.  
  13.             ^    0
  14. vdc_write_address    #    4        ; 0x00
  15. vdc_read_address    #    4        ; 0x01
  16. vdc_write        *    @        ; 0x02
  17. vdc_read        *    @        ; 0x02
  18.             ^    0x05 * 4
  19. vdc_control        #    4        ; 0x05
  20. vdc_raster_detect    #    4        ; 0x06
  21. vdc_bgx_scroll        #    4        ; 0x07
  22. vdc_bgy_scroll        #    4        ; 0x08
  23. vdc_memory_width    #    4        ; 0x09
  24. vdc_horizontal_period    #    4        ; 0x0a
  25. vdc_horizontal_display    #    4        ; 0x0b
  26. vdc_vertical_sync    #    4        ; 0x0c
  27. vdc_vertical_display    #    4        ; 0x0d
  28. vdc_vertical_end    #    4        ; 0x0e
  29. vdc_dma_control        #    4        ; 0x0f
  30. vdc_dma_source        #    4        ; 0x10
  31. vdc_dma_destination    #    4        ; 0x11
  32. vdc_dma_length        #    4        ; 0x12
  33. vdc_sprite_table    #    4        ; 0x13
  34.             ^    0x20 * 4
  35. vdc_bgy_counter        #    4
  36. vdc_display_rows    #    4
  37. vdc_event_mask        #    4
  38. vdc_status        #    4
  39. output_address        #    4
  40. output_line        #    4
  41. skip_frame        #    4
  42.  
  43.             ASSERT    @ < 0x100
  44.             ^    0x100
  45. cache_satb_count    #    (256 + 64 + 64) * 4
  46. cache_satb_data        #    (256 + 64 + 64) * 16 * (4 + 8) * 2
  47. vdc_size        *    @
  48.  
  49.  
  50.             ^    0
  51. sprite_y        #    2
  52. sprite_x        #    2
  53. sprite_data        #    2
  54. sprite_flags        #    2
  55. sprite_size        *    @
  56.  
  57.  
  58. ;IRQ2            *    1 << 0        ; IRQ2, generated by BRK instruction
  59. ;IRQ1            *    1 << 1        ; IRQ1, general interrupt
  60. ;TIQ            *    1 << 2        ; TIQ, timer interrupt
  61.  
  62. event_collision        *    1 << 0        ; collision between sprite 0 and any other sprite
  63. event_excess        *    1 << 1        ; too many sprites on one scanline
  64. event_coincide        *    1 << 2        ; vdc_raster_detect = current raster
  65. event_vram_satb        *    1 << 3        ; VRAM-SATB transfer complete
  66. event_vram_vram        *    1 << 4        ; VRAM-VRAM transfer complete
  67. event_retrace        *    1 << 5        ; vertical retrace
  68.  
  69. enable_collision    *    1 << 0        ; vdc_control (0x05)
  70. enable_excess        *    1 << 1        ; vdc_control (0x05)
  71. enable_coincide        *    1 << 2        ; vdc_control (0x05)
  72. enable_retrace        *    1 << 3        ; vdc_control (0x05)
  73. enable_vram_satb    *    1 << 0        ; vdc_dma_control (0x0f)
  74. enable_vram_vram    *    1 << 1        ; vdc_dma_control (0x0f)
  75.  
  76.  
  77. ;    ------------------------------------------------------------------------
  78.  
  79.     AREA    |video$$code|, CODE, READONLY
  80.  
  81.  
  82. ;    IMPORT    irq_status
  83. ;    IMPORT    irq_mask
  84.     IMPORT    vsync_flag
  85.  
  86.  
  87. ;    void VDC_Initialise(void)
  88. VDC_Initialise
  89.     EXPORT    VDC_Initialise
  90.     ldr    data, adrof_cpu_emulation_data
  91.     mov    r0, #100 - 1        ; *
  92.     adr    r1, Count_fps        ; *
  93.     adrl    r2, frame_counter    ; *
  94.     swi    OS_CallEvery        ; *
  95.     mov    r0, #0            ; *
  96.     str    r0, frame_counter    ; *
  97.     ldr    r1, adrof_video_registers
  98.     mov    r0, #0
  99.     str    r0, [r1, #vdc_horizontal_period]
  100.     mov    r0, #59
  101.     str    r0, [r1, #vdc_horizontal_display]
  102.     b    Resize_Screen
  103.  
  104. ;    void VDC_Finalise(void)
  105. VDC_Finalise
  106.     EXPORT    VDC_Finalise
  107.     adr    r0, Count_fps
  108.     adrl    r1, frame_counter
  109.     swi    OS_RemoveTickerEvent
  110.     movs    pc, r14
  111.  
  112. Count_fps
  113.     stmfd    r13!, {r0-r1, r14}
  114.     ldr    r1, [r12, #0]
  115.     mov    r0, #0
  116.     str    r0, [r12, #0]
  117.     adr    r0, Display_fps
  118.     swi    OS_AddCallBack
  119.     ldmfd    r13!, {r0-r1, pc}^
  120. Display_fps
  121.     stmfd    r13!, {r0-r2, r14}
  122.     swi    OS_WriteI + 31 ; move cursor
  123.     swi    OS_WriteI + 0 ; x
  124.     swi    OS_WriteI + 0 ; y
  125.     mov    r0, r12
  126.     mov    r2, #' '
  127.     orr    r2, r2, r2, lsl #8
  128.     orr    r2, r2, r2, lsl #16
  129.     stmfd    r13!, {r2, r3}
  130.     add    r1, r13, #4
  131.     mov    r2, #4
  132.     swi    OS_ConvertCardinal1
  133.     sub    r2, r2, #1
  134.     sub    r0, r0, r2
  135.     swi    OS_Write0
  136.     add    r13, r13, #8
  137.     ldmfd    r13!, {r0-r2, pc}^
  138.  
  139.  
  140. ;    void Cache_SATB(void)
  141. Cache_SATB
  142.     stmfd    r13!, {r4-r12, r14}
  143.     ldr    r0, adrof_video_registers    ; r0 = video registers
  144. Cache_SATB_Entry
  145.     ldr    r1, adrof_video_ram        ; r1 = PCE video ram
  146.     mov    r2, #65                ; r2 = sprite downcounter
  147.     ldr    r3, [r0, #vdc_sprite_table]
  148.     mov    r9, #0
  149.     add    r3, r1, r3, lsl #1        ; r3 = halfword aligned address of satb
  150. Cache_SATB_Next_Sprite
  151.     tst    r9, #0x0100
  152.     ldmnefd    r13!, {r4-r10}
  153.     bne    Cache_SATB_Next_Strip
  154. Cache_SATB_Next_Sprite_X
  155.     subs    r2, r2, #1
  156.     ldmeqfd    r13!, {r4-r12, pc}^
  157.     tst    r3, #2_11
  158.     bicnes    r4, r3, #2_11
  159.     ldmneia    r4, {r4-r6}
  160.     ldmeqia r3, {r4-r5}
  161.     add    r3, r3, #sprite_size        ; move SATB pointer onto address of next sprite
  162.     add    r7, r0, #cache_satb_count
  163.     add    r8, r0, #cache_satb_data
  164.     movne    r4, r4, lsr #16
  165.     orrne    r4, r4, r5, lsl #16
  166.     bic    r4, r4, #0xfc000000
  167.     bic    r4, r4, #0x0000fc00
  168.                         ; r4 = 0xXXXXYYYY (YYYY = Y coord, XXXX = X coord)
  169.     movne    r5, r5, lsr #16
  170.     orrne    r5, r5, r6, lsl #16
  171.                         ; r5 = 0xFFFFVVVV (FFFF = flags, VVVV = vram offset >> 6)
  172.     mov    r10, r5, lsl #16 + 5        ; r10 = 0xVVVV0000 (+5 to clear rubbish from upper 5 bits)
  173.     mov    r10, r10, lsr #16 - 1        ; r10 = 0x0000VVVV
  174.     mov    r9, r4, lsr #16            ;  r9 = 0x0000XXXX
  175.     mov    r9, r9, lsl #16            ;  r9 = 0xXXXX0000
  176.     bic    r6, r4, r9            ;  r6 = 0x0000YYYY
  177.     sub    r4, r6, #256
  178.     cmp    r4, #320 - 256            ; is y outside maximum visible area?
  179.     bgt    Cache_SATB_Next_Sprite_X    ; yes
  180.     orr    r9, r9, r5, lsr #16        ;  r9 = 0xXXXXFFFF
  181.  
  182.     teqp    pc, r9, lsl #16            ; N = flipped up-down, C = 4 x height, V = 2 x height
  183.     mov    r4, #0x10
  184.     movvs    r4, #0x20
  185.     movcs    r4, #0x40            ; r4 = height
  186.     addmi    r10, r10, #0x1e
  187.     submi    r11, r4, #0x10
  188.     addmi    r10, r10, r11, lsl #4
  189.     tst    r9, #0x0100            ; width x 2?
  190.     bicne    r10, r10, #0x80
  191.     tstne    r9, #0x0800            ; && flipped left-right?
  192.     orrne    r10, r10, #0x80
  193.     add    r10, r10, r1            ; r10 = start (or end) of sprite data
  194.     add    r7, r7, r6, lsl #2        ; r7 = cache_satb_count for first line
  195.     add    r8, r8, r6, lsl #9
  196.     sub    r8, r8, r6, lsl #7        ; r8 = cache_satb_data for first line
  197.     tst    r9, #0x0080
  198.     addeq    r8, r8, #192            ; adjust r8 if sprite is in the foreground
  199.     sub    r8, r8, #384
  200.  
  201.     sub    r4, r4, #1
  202.     mvn    r5, #1
  203.     tst    r9, #0x8000
  204.     subeq    r10, r10, #2
  205.     addne    r10, r10, #2
  206.  
  207.     tst    r9, #0x0100
  208.     bicne    r11, r9, #0x00000100
  209.     addne    r11, r11, #0x00100000
  210.     eorne    r12, r10, #0x80
  211.     stmnefd    r13!, {r4-r8, r11, r12}
  212. Cache_SATB_Next_Strip
  213.     ldr    r11, [r7], #4
  214.     add    r8, r8, #384
  215.     tst    r4, #2_1111
  216.     movne    r12, #2
  217.     moveq    r12, #2 + (0x100 - 32)
  218.     sub    r4, r4, #1
  219.     tst    r9, #0x8000
  220.     addeq    r10, r10, r12
  221.     subne    r10, r10, r12
  222.     tst    r11, r11, lsr #6        ; excess strips on this line?
  223.     teqcs    r4, r5
  224.     bhi    Cache_SATB_Next_Strip        ; excess strips && ~final line
  225.     bcs    Cache_SATB_Next_Sprite        ; excess strips && final line
  226.     tst    r9, #0x0080
  227.     addeq    r11, r11, #1 << 16        ; foreground
  228.     addne    r11, r11, #1 << 24        ; background
  229.     tst    r11, r11, lsr #5
  230.     orrcs    r12, r11, #2_100000        ; mark as having too many strips to display
  231.     addcc    r12, r11, #1
  232.     str    r12, [r7, #-4]
  233.     teqcs    r4, r5
  234.     bhi    Cache_SATB_Next_Strip
  235.     bcs    Cache_SATB_Next_Sprite
  236.     tst    r9, #0x0080
  237.     moveq    r11, r11, lsl #8
  238.     tst    r10, r10, lsr #2
  239.     biccs    r10, r10, #2_10
  240.     ldr    r12, [r10, #0x00]
  241.     mov    r11, r11, lsr #24 - 2
  242.     add    r11, r11, r11, lsl #1
  243.     ldr    r14, [r10, #0x20]
  244.     movcs    r12, r12, lsr #16        ; r12 = ????pln1
  245.     mov    r12, r12, lsl #16        ; r12 = pln10000
  246.     str    r9, [r11, r8]!            ; store X coordinate and flags
  247.     movcc    r14, r14, lsl #16        ; r14 = pln2????
  248.     orr    r12, r12, r14, lsr #16        ; r12 = pln1pln2
  249.     str    r12, [r11, #4]            ; store planes 1 and 2
  250.     ldr    r12, [r10, #0x40]
  251.     teq    r4, r5
  252.     ldr    r14, [r10, #0x60]
  253.     movcs    r12, r12, lsr #16        ; r12 = ????pln3
  254.     mov    r12, r12, lsl #16        ; r12 = pln30000
  255.     movcc    r14, r14, lsl #16        ; r14 = pln4????
  256.     orr    r12, r12, r14, lsr #16        ; r12 = pln3pln4
  257.     str    r12, [r11, #8]            ; store planes 3 and 4
  258.     orrcs    r10, r10, #2_10
  259.     bne    Cache_SATB_Next_Strip
  260.     b    Cache_SATB_Next_Sprite
  261.  
  262.  
  263. ;    void Read_Sprite_Table(void)
  264. Read_Sprite_Table
  265.     stmfd    r13!, {r0-r12, r14}
  266.     ldr    r0, =vsync_flag
  267.     ldr    r1, [r0, #4]
  268.     cmp    r1, #1
  269.     ldrlt    r1, [r0, #4]
  270.     sublt    pc, pc, #16
  271.     rsbgts    r14, r1, #8
  272.     sub    r1, r1, #1
  273.     str    r1, [r0, #4]
  274.     ldr    r0, adrof_video_registers
  275.     movgt    r14, #1
  276.     movle    r14, #0
  277.     str    r14, [r0, #skip_frame]
  278.     ldr    r14, frame_counter
  279.     add    r14, r14, #1
  280.     str    r14, frame_counter
  281. ;    mov    r3, #0                ; r3 = background plane
  282. Read_Sprite_Table_Plane
  283.     ldr    r0, adrof_video_registers
  284.     ldr    r1, adrof_video_ram        ; r1 = video ram
  285.     ldr    r0, [r0, #vdc_sprite_table]    ; r0 = offset of sprite table
  286.     mov    r2, #64                ; r2 = sprite downcounter
  287.     add    r0, r1, r0, lsl #1        ; r0 = address of sprite table
  288.     b    Read_Outer_Entry
  289. Read_Outer_Loop
  290.     subs    r2, r2, #1
  291. ;    ble    Read_Sprite_Table_End
  292.     ldmlefd    r13!, {r0-r12, pc}^
  293.     add    r0, r0, #sprite_size
  294. Read_Outer_Entry
  295.     add    r5, r0, #sprite_flags
  296.     ands    r6, r5, #2_11
  297.     ldr    r5, [r5, -r6]
  298.     add    r6, r0, #sprite_data
  299.     moveq    r5, r5, lsl #16
  300.     mov    r5, r5, lsr #16            ; r5 = flag bytes
  301.     movs    r4, r5, lsl #16 + 3
  302.     movpl    r4, #0x10            ; normal height
  303.     movmi    r4, #0x20            ; height x 2
  304.     movcs    r4, #0x40            ; height x 4
  305.     ; r4 = sprite height in pixels
  306. ;    and    r6, r5, r3
  307. ;    cmp    r6, r3                ; is sprite in the current plane?
  308.     ands    r7, r6, #2_11
  309.     add    r8, r0, #sprite_x
  310.     ldr    r6, [r6, -r7]
  311.     movne    r6, r6, lsr #16
  312.     tst    r5, #0x8000            ; flipped up-down?
  313.     mov    r6, r6, lsl #21
  314.     mov    r6, r6, lsr #15
  315.     ; r6 = VRAM byte offset to sprite data
  316.     addne    r6, r6, #0x1e            ; yes
  317.     subne    r7, r4, #0x10
  318.     addne    r6, r6, r7, lsl #4        ; skip however many tiles
  319.  
  320.     ands    r7, r8, #2_11
  321.     ldr    r7, [r8, -r7]
  322.     add    r8, r0, #sprite_y
  323.     moveq    r7, r7, lsl #16
  324.     mov    r7, r7, lsr #16            ; r7 = sprite x
  325.     ands    r9, r8, #2_11
  326.     ldr    r8, [r8, -r9]
  327.     moveq    r8, r8, lsl #16
  328.     mov    r8, r8, lsr #16
  329.     tst    r5, #0x0100            ; width x 2?
  330.     bicne    r6, r6, #0x80
  331.     tstne    r5, #0x0800            ; width x 2 && flipped left-right?
  332.     orrne    r6, r6, #0x80
  333.  
  334.     cmp    r7, #512            ; is x outside maximum visible area?
  335.     bgt    Read_Outer_Loop            ; yes
  336.     sub    r9, r8, #256
  337.     cmp    r9, #320 - 256            ; is y outside maximum visible area?
  338.     bgt    Read_Outer_Loop            ; yes
  339.     ldr    r9, adrof_sprite_cache_count
  340.     orr    r5, r5, r7, lsl #16        ; r5 = xxxxffff (x = sprite x, f = flags)
  341.     ldr    r10, adrof_sprite_cache_info
  342.     add    r9, r9, r8, lsl #2        ; r9 = cache_count[...
  343.     ldr    r11, adrof_sprite_cache_data
  344.     add    r10, r10, r8, lsl #6        ; r10 = cache_info[line][...
  345.     add    r11, r11, r8, lsl #6        ; r11 = cache_data[line][...
  346.     sub    r4, r4, #1
  347. Read_Inner_Loop
  348.     ldr    r7, [r9, #0]
  349.     add    r8, r7, #1
  350.     str    r8, [r9], #4            ; increment no. of sprites on this line
  351.     cmp    r7, #16
  352.     strlt    r6, [r11, r7, lsl #2]
  353.     add    r11, r11, #1 << 6        ; cache_data[line++]
  354.     strlt    r5, [r10, r7, lsl #2]
  355.     add    r10, r10, #1 << 6        ; cache_info[line++]
  356.     tst    r4, #2_1111
  357.     movne    r7, #2
  358.     moveq    r7, #2 + (0x100 - 32)
  359.     tst    r5, #0x8000            ; flipped up-down?
  360.     addeq    r6, r6, r7            ; no, so data += offset
  361.     subne    r6, r6, r7            ; yes, so data -= offset
  362.     subs    r4, r4, #1
  363.     bge    Read_Inner_Loop
  364.     subs    r2, r2, #1
  365.     addgt    r0, r0, #sprite_size
  366.     bgt    Read_Outer_Entry
  367. Read_Sprite_Table_End
  368.     ldmfd    r13!, {r0-r12, pc}^
  369.  
  370.  
  371. ;    void Update_Line(void)
  372. Update_Line
  373.     stmfd    r13!, {r0-r12, r14}
  374.     ldr    r14, adrof_physical_screen_width
  375.     cmp    r2, #64
  376.     ldr    r14, [r14, #0]
  377.     ldreq    r1, adrof_physical_screen
  378.     ldrne    r1, [r0, #output_address]
  379.     ldreq    r1, [r1, #0]
  380.     add    r14, r14, r1
  381.     str    r14, [r0, #output_address]
  382.     ldrne    r2, [r0, #vdc_bgy_counter]
  383.     ldreq    r2, [r0, #vdc_bgy_scroll]
  384.     add    r2, r2, #1
  385.     str    r2, [r0, #vdc_bgy_counter]
  386.     stmfd    r13!, {r1}
  387.  
  388.     ldr    r3, [r0, #vdc_control]
  389.     tst    r3, #0x0080            ; background on?
  390.     beq    No_Background
  391.  
  392.     add    r1, r1, #32
  393.     ; find the dimensions of the virtual screen
  394.     ldr    r3, [r0, #vdc_memory_width]
  395.     teqp    pc, r3, lsl #24 + 1
  396.     ; convert the y scroll into number of tiles from top of map
  397.     mov    r4, r2, lsr #3
  398.     and    r2, r2, #7
  399.     ; and mask this value against the virtual screen height
  400.     ldr    r6, adrof_video_ram
  401.     andmi    r4, r4, #64 - 1                    ; BG map is 64 tiles high
  402.     andpl    r4, r4, #32 - 1                    ; BG map is 32 tiles high
  403.     ; then calculate the address of the relevant part of the background map
  404.     add    r5, r6, r4, lsl #5 + 1                ; BG map is 32 tiles wide
  405.     addhi    r5, r6, r4, lsl #6 + 1                ; BG map is 64 tiles wide
  406.     addeq    r5, r6, r4, lsl #7 + 1                ; BG map is 128 tiles wide
  407.     ; make a mask for the horizontal tile index
  408.     mov    r4, #(1 << 5) - 1
  409.     movhi    r4, #(1 << 6) - 1
  410.     moveq    r4, #(1 << 7) - 1
  411.     ; calculate the number of tiles that need to be processed to form a line of output
  412.     ldr    r6, [r0, #vdc_bgx_scroll]
  413.     ldrb    r7, [r0, #vdc_horizontal_display]
  414.     tst    r6, #2_100
  415.     orr    r4, r4, r7, lsl #17                ; combine tile no. mask and horizontal no. of tiles
  416.     add    r4, r4, #1 << 17
  417.     orrne    r4, r4, #1 << 15                ; skip the first half tile?
  418.     ands    r12, r6, #2_11
  419.     orrne    r4, r4, #1 << 14                ; need to clip the display
  420.     addne    r4, r4, #1 << 16                ; if clipping, we need to use an extra half tile
  421.     rsbne    r12, r12, #4
  422.     movne    r12, r12, lsl #3                ; shift for "word"
  423.     rsb    r10, r12, #32
  424.     orr    r12, r12, r10, lsl #8                ; shift for "previous_word"
  425.     ; convert the x scroll into a tile index, then mask against the virtual screen width
  426.     mov    r6, r6, lsr #3
  427.     and    r6, r6, r4 ; , lsr #8
  428.     ; initialise the read cache if necessary
  429.     tst    r6, #1
  430.     addne    r14, r5, r6, lsl #1
  431.     ldrne    r8, [r14, #-2]
  432.     ; setup register to contain the 0x80808080 mask
  433.     mov    r10, #0x80
  434.     orr    r10, r10, r10, lsl #8
  435.     orr    r10, r10, r10, lsl #16
  436.     ; cache background colour 0
  437.     ldr    r14, adrof_background_vce
  438.     ldrb    r14, [r14, #0]
  439.     orr    r14, r12, r14, lsl #24
  440.     mov    r12, #0
  441. VDC_Draw_Line_Loop
  442.     ; get the current tile information from the background map
  443.     tst    r6, #1
  444.     ldreq    r8, [r5, r6, lsl #1]
  445.     movne    r8, r8, lsr #16
  446.     ; increment the tile number and mask it
  447.     add    r6, r6, #1
  448.     and    r6, r6, r4 ; , lsr #8
  449.     ; shift the tile palette and address to the upper 16 bits to lose the unncessary bits above
  450.     mov    r9, r8, lsl #16
  451.     ; extract the tile palette
  452.     mov    r11, r9, lsr #28
  453.     ; calculate the actual tile data address
  454.     ldr    r7, adrof_video_ram
  455.     bic    r9, r9, r11, lsl #28                ; lose the tile palette
  456.     add    r9, r7, r9, lsr #16 - 5                ; shift to get ARM address offset
  457.     ; read the planar tile data and find the address of the tile palette
  458.     ldr    r7, [r9, r2, lsl #1]!
  459.     mov    r11, r11, lsl #6
  460.     ldr    r9, [r9, #16]
  461.     mov    r7, r7, lsl #16                    ; 0xp2p10000
  462.     mov    r9, r9, lsl #16                    ; 0xp4p30000
  463.     orr    r7, r9, r7, lsr #16                ; 0xp4p3p2p1
  464.     ldr    r9, adrof_background_vce
  465.     tst    r4, #1 << 15
  466.     movne    r7, r7, lsl #4
  467.     add    r11, r11, r9
  468. VDC_Draw_BGTile_Loop
  469.     ; convert four pixels from planar to chunky format
  470.     ands    r9, r10, r7                    ; pixel 1
  471.     orrne    r9, r9, r9, lsl #7
  472.     orrne    r9, r9, r9, lsl #14
  473.     movnes    r9, r9, lsr #28 - 2
  474.     ldrneb    r9, [r11, r9]
  475.     moveq    r9, r14, lsr #24
  476.     ands    r3, r10, r7, lsl #1                ; pixel 2
  477.     orrne    r3, r3, r3, lsl #7
  478.     orrne    r3, r3, r3, lsl #14
  479.     movnes    r3, r3, lsr #28 - 2
  480.     ldrneb    r3, [r11, r3]
  481.     moveq    r3, r14, lsr #24
  482.     orr    r9, r9, r3, lsl #8
  483.     ands    r3, r10, r7, lsl #2                ; pixel 3
  484.     orrne    r3, r3, r3, lsl #7
  485.     orrne    r3, r3, r3, lsl #14
  486.     movnes    r3, r3, lsr #28 - 2
  487.     ldrneb    r3, [r11, r3]
  488.     moveq    r3, r14, lsr #24
  489.     orr    r9, r9, r3, lsl #16
  490.     ands    r3, r10, r7, lsl #3                ; pixel 4
  491.     orrne    r3, r3, r3, lsl #7
  492.     orrne    r3, r3, r3, lsl #14
  493.     movnes    r3, r3, lsr #28 - 2
  494.     ldrneb    r3, [r11, r3]
  495.     moveq    r3, r14, lsr #24
  496.     orr    r9, r9, r3, lsl #24
  497.     tst    r4, #1 << 14                    ; clip this half tile?
  498.     orreq    r3, r12, r9, lsl r14
  499.     bicne    r4, r4, #1 << 14                ; yep, but don't clip any others
  500.     streq    r3, [r1], #4
  501.     mov    r3, r14, lsr #8
  502.     mov    r12, r9, lsr r3
  503.     eor    r4, r4, #1 << 15
  504.     sub    r4, r4, #1 << 16
  505.     movs    r3, r4, lsr #16
  506.     movcs    r7, r7, lsl #4
  507.     bhi    VDC_Draw_BGTile_Loop
  508.     bne    VDC_Draw_Line_Loop
  509.     ldr    r3, [r0, #vdc_control]
  510.     tst    r3, #0x0040            ; sprites on?
  511.     addeq    r13, r13, #4
  512.     ldmeqfd    r13!, {r0-r12, pc}^
  513. Update_Sprites
  514.     ldmfd    r13!, {r2}
  515.     ldr    r1, [r0, #output_line]
  516.     ldr    r0, adrof_sprite_cache_count
  517. ;    add    r1, r1, #64            ; r1 = raster
  518.     ldr    r3, adrof_sprite_cache_info
  519.     ldr    r4, [r0, r1, lsl #2]
  520.     mov    r5, #0
  521.     str    r5, [r0, r1, lsl #2]
  522.     add    r3, r3, r1, lsl #6
  523.     ldr    r0, adrof_sprite_cache_data
  524.     cmp    r4, #16
  525.     blgt    Sprite_Excess
  526.     ; r4-r7, r14 are corrupted if r4 > 16
  527.     movgt    r4, #16
  528.     cmp    r4, #0
  529.     ldmeqfd    r13!, {r0-r12, pc}^
  530.     add    r0, r0, r1, lsl #6
  531.     ldr    r1, adrof_video_ram
  532.     add    r0, r0, r4, lsl #2
  533.     add    r3, r3, r4, lsl #2
  534.     ; r0 = sprite_cache_data[raster][...
  535.     ; r1 = address of PCE video RAM
  536.     ; r2 = output base
  537.     ; r3 = sprite_cache_info[raster][...
  538.     ; r4 = sprites on line (always >= 1)
  539. Update_Sprites_Loop
  540.     ldr    r5, [r3, #-4]!            ; r5 = xxxxffff (x = sprite x, f = flags)
  541.     ldr    r6, [r0, #-4]!            ; r6 = data address
  542.     add    r10, r2, r5, lsr #16        ; r10 = address to output sprite line to
  543.     ldr    r7, adrof_sprite_vce
  544.     and    r8, r5, #0xf
  545.     add    r11, r7, r8, lsl #4 + 2        ; r11 = address of sprite palette
  546. Update_Sprites_Setup
  547.     add    r7, r1, r6            ; r7 = half-word aligned address of sprite data
  548.     movs    r7, r7, lsr #2
  549.     mov    r7, r7, lsl #2
  550.     ldr    r8, [r7, #0x00]
  551.     eor    r6, r6, #0x80
  552.     ldr    r9, [r7, #0x20]
  553.     movcs    r8, r8, lsr #16
  554.     mov    r8, r8, lsl #16            ; r8 = pln10000
  555.     movcc    r9, r9, lsl #16            ; r9 = pln2????
  556.     orr    r8, r8, r9, lsr #16        ; r8 = pln1pln2
  557.     ldr    r9, [r7, #0x60]
  558.     mov    r12, #1 << 15
  559.     ldr    r7, [r7, #0x40]
  560.     movcc    r9, r9, lsl #16            ; r9 = pln4????
  561.     mov    r9, r9, lsr #16            ; r9 = 0000pln4
  562.     movcs    r7, r7, lsr #16            ; r7 = ????pln3
  563.     orr    r9, r9, r7, lsl #16        ; r9 = pln3pln4
  564.     ; r7 free
  565.     tst    r5, #0x0800            ; flipped left-right?
  566.     bic    r5, r5, #0x1f
  567.     moveq    r8, r8, ror #1            ; no
  568.     moveq    r9, r9, ror #1
  569.     orreq    r5, r5, #31
  570.     movne    r8, r8, ror #16            ; yes
  571.     movne    r9, r9, ror #16
  572.     orrne    r5, r5, #1
  573. Update_Sprites_Plot
  574.     movs    r8, r8, ror r5
  575.     subpl    r7, r11, #1
  576.     addmi    r7, r11, #(2_0001 << 2) - 1
  577.     tst    r8, r8, lsl #16 + 1
  578.     addcs    r7, r7, #2_0010 << 2
  579.     movs    r9, r9, ror r5
  580.     addmi    r7, r7, #2_0100 << 2
  581.     tst    r9, r9, lsl #16 + 1
  582.     addcs    r7, r7, #2_1000 << 2
  583.     cmp    r7, r11                ; carry clear if r7 < r11 (ie pixel is transparent)
  584.     ldrcsb    r7, [r7, #1]
  585.     addcc    r10, r10, #1
  586. ;    movcs    r7, r7, lsr #1
  587.     strcsb    r7, [r10], #1
  588.     movs    r12, r12, lsr #1
  589.     bcc    Update_Sprites_Plot
  590.     tst    r5, #0x0100
  591.     bicne    r5, r5, #0x0100
  592.     bne    Update_Sprites_Setup
  593.     subs    r4, r4, #1
  594.     bhi    Update_Sprites_Loop
  595.     ldmfd    r13!, {r0-r12, pc}^
  596. No_Background
  597.     ldrb    r4, [r0, #vdc_horizontal_display]
  598.     mov    r5, #0
  599.     mov    r6, #0
  600.     mov    r7, #0
  601.     mov    r8, #0
  602.     add    r9, r1, #32
  603. No_Background_Loop
  604.     stmia    r9!, {r5-r8}
  605.     subs    r4, r4, #2
  606.     stmgeia    r9!, {r5-r8}
  607.     subges    r4, r4, #2
  608.     stmgeia    r9!, {r5-r8}
  609.     subges    r4, r4, #2
  610.     stmgeia    r9!, {r5-r8}
  611.     subges    r4, r4, #2
  612.     stmgeia    r9!, {r5-r8}
  613.     subges    r4, r4, #2
  614.     stmgeia    r9!, {r5-r8}
  615.     subges    r4, r4, #2
  616.     stmgeia    r9!, {r5-r8}
  617.     subges    r4, r4, #2
  618.     stmgeia    r9!, {r5-r8}
  619.     subges    r4, r4, #2
  620.     bge    No_Background_Loop
  621.     tst    r3, #0x0040            ; sprites on?
  622.     bne    Update_Sprites
  623.     add    r13, r13, #4
  624.     ldmfd    r13!, {r0-r12, pc}^
  625. Sprite_Excess
  626.     ldr    r5, adrof_video_registers
  627.     ldr    r6, [r5, #vdc_status]
  628.     orr    r6, r6, #event_excess
  629.     str    r6, [r5, #vdc_status]        ; set VDC event high
  630.     movs    pc, r14
  631.  
  632.  
  633. ;    void Increment_Raster(void)
  634. ;    Move onto next raster line
  635. Increment_Raster
  636.     EXPORT    Increment_Raster
  637.     ldr    r0, adrof_video_registers
  638.     stmfd    r13!, {r14}
  639.     ldr    r2, [r0, #output_line]                ; current line (visible area starts at 64)
  640.     ldr    r3, [r0, #vdc_vertical_display]            ; lower 9 bits = visible height - 1
  641.     sub    r14, r2, #64
  642.     cmp    r14, r3                        ; within visible area?
  643.     ldrlo    r14, [r0, #skip_frame]
  644.     cmplo    r14, #1                        ; yes: and not skipping this frame?
  645.     bllo    Update_Line                    ; yes: draw the line
  646.     mov    r1, #0                        ; new VDC events
  647.     add    r2, r2, #1                    ; increment the raster
  648.     ldrb    r14, [r0, #vdc_vertical_end]            ; vertical front porch
  649.     add    r3, r3, #65                    ; line on which display ends
  650.     add    r3, r3, r14                    ; line on which vsync is generated
  651.     cmp    r2, r3
  652.     ldr    r14, [r0, #vdc_vertical_sync]            ; bits 4:0 = vsync width, 15:8 = vertical back porch
  653.     orreq    r1, r1, #event_retrace
  654.     mov    r14, r14, ror #5
  655.     add    r3, r3, r14, lsr #32 - 5            ; line on which wrap-around occurs
  656.     cmp    r2, r3
  657.     moveq    r14, r14, ror #32 - 5
  658.     rsbeq    r14, r14, #62 << 8
  659.     ldr    r3, [r0, #vdc_raster_detect]            ; line on which coincidence event occurs
  660.     moveq    r2, r14, asr #8
  661.     bleq    Read_Sprite_Table
  662.     str    r2, [r0, #output_line]                ; update current line
  663.     cmp    r2, r3                        ; time for coincidence event?
  664.     ldr    r2, [r0, #vdc_status]
  665.     orreq    r1, r1, #event_coincide                ; yes: generate coincidence event
  666.     ldr    r14, [r0, #vdc_event_mask]
  667.     orr    r2, r2, r1
  668.     str    r2, [r0, #vdc_status]
  669.     tst    r2, r14                        ; generate an IRQ?
  670.     orrne    r_p, r_p, #IRQ1 << 16                ; yes
  671.     ldmfd    r13!, {pc}^
  672. frame_counter                ; *
  673.     DCD    0            ; *
  674.  
  675.  
  676. ;    void VDC_Write(uhalf address, ubyte value)
  677. ;    Video Display Controller write port
  678. VDC_Write
  679.     EXPORT    VDC_Write
  680.     movs    r2, r0
  681.     mov    r0, r1                ; VDC_Write_x functions expect value in r0
  682.     beq    VDC_Write_0
  683.     cmp    r2, #2
  684.     beq    VDC_Write_2
  685.     cmp    r2, #3
  686.     movnes    pc, r14
  687. ;    void VDC_Write_3(ubyte value)
  688. ;    Write upper byte of data to VDC address
  689. VDC_Write_3
  690.     EXPORT    VDC_Write_3
  691.     ldr    r2, adrof_vdc_address
  692.     adr    r3, vdc_write_3_mask
  693.     ldr    r2, [r2, #0]            ; r2 = VDC address
  694.     ldr    r1, adrof_video_registers    ; r1 = video registers
  695.     ldrb    r3, [r3, r2]            ; r3 = mask value
  696.     cmp    r2, #vdc_dma_length >> 2
  697.     and    r0, r0, r3            ; r0 = masked write value
  698.     add    r3, r1, #1
  699.     strb    r0, [r3, r2, lsl #2]        ; store value in register
  700.     beq    VRAM_VRAM_Transfer
  701.     cmp    r2, #vdc_sprite_table >> 2
  702.     beq    VRAM_SATB_Transfer
  703.  
  704.     cmp    r2, #vdc_bgy_scroll >> 2
  705. ;    moveqs    pc, r14
  706.  
  707.     cmp    r2, #vdc_bgy_scroll >> 2
  708. ;    mvneq    r0, #0
  709. ;    streq    r0, [r1, #vdc_bgy_counter]
  710.     streqb    r0, [r3, #vdc_bgy_counter]
  711.     moveqs    pc, r14
  712.     cmp    r2, #vdc_horizontal_period >> 2
  713.     cmpne    r2, #vdc_horizontal_display >> 2
  714.     beq    Update_Video_Timing
  715.     cmp    r2, #vdc_write >> 2
  716.     ldreq    r2, [r1, #vdc_write_address]
  717.     movnes    pc, r14
  718.     ldr    r3, adrof_video_ram
  719.     ldr    r0, [r1, #vdc_write]
  720.     mov    r2, r2, lsl #16
  721.     strb    r0, [r3, r2, lsr #15]!
  722.     mov    r0, r0, lsr #8
  723.     strb    r0, [r3, #1]
  724.     ldr    r0, [r1, #vdc_control]
  725.     and    r0, r0, #3 << 11
  726.     cmp    r0, #1 << 11
  727.     addlt    r2, r2, #0x01 << 16
  728.     addeq    r2, r2, #0x20 << 16
  729.     cmp    r0, #2 << 11
  730.     addeq    r2, r2, #0x40 << 16
  731.     addgt    r2, r2, #0x80 << 16
  732.     mov    r2, r2, lsr #16
  733.     str    r2, [r1, #vdc_write_address]
  734.     movs    pc, r14
  735. vdc_write_3_mask
  736.     =    0xff, 0xff, 0xff, 0x00        ; 0x00-0x03
  737.     =    0x00, 0x1f, 0x03, 0x03        ; 0x04-0x07
  738.     =    0x01, 0x00, 0x7f, 0x7f        ; 0x08-0x0b
  739.     =    0xff, 0x01, 0x00, 0x00        ; 0x0c-0x0f
  740.     =    0xff, 0xff, 0xff, 0xff        ; 0x10-0x13
  741. ;    void VDC_Write_0(ubyte value)
  742. ;    Set VDC address
  743. VDC_Write_0
  744.     EXPORT    VDC_Write_0
  745.     ldr    r1, adrof_vdc_address
  746.     and    r0, r0, #0x1f
  747.     str    r0, [r1, #0]
  748.     movs    pc, r14
  749. ;    void VDC_Write_2(ubyte value)
  750. ;    Write lower byte of data to VDC address
  751. VDC_Write_2
  752.     EXPORT    VDC_Write_2
  753.     ldr    r2, adrof_vdc_address
  754.     adr    r3, vdc_write_2_mask
  755.     ldr    r2, [r2, #0]            ; r2 = VDC address
  756.     ldr    r1, adrof_video_registers    ; r1 = video registers
  757.     ldrb    r3, [r3, r2]            ; r3 = write mask
  758.     cmp    r2, #vdc_bgy_scroll >> 2
  759.     and    r0, r0, r3            ; r0 = masked value
  760.     strb    r0, [r1, r2, lsl #2]
  761. ;    mvneq    r0, #0
  762. ;    streq    r0, [r1, #vdc_bgy_counter]
  763.     streqb    r0, [r1, #vdc_bgy_counter]
  764.     moveqs    pc, r14
  765.     cmp    r2, #vdc_vertical_display >> 2
  766.     cmpne    r2, #vdc_horizontal_display >> 2
  767.     beq    Resize_Screen
  768.     cmp    r2, #vdc_horizontal_period >> 2
  769.     beq    Update_Video_Timing
  770.     cmp    r2, #vdc_control >> 2
  771.     cmpne    r2, #vdc_dma_control >> 2
  772.     movnes    pc, r14
  773.     ldr    r3, [r1, #vdc_event_mask]
  774.     tst    r0, r0, lsr #4
  775.     teq    r2, #vdc_dma_control >> 2
  776.     andeq    r0, r0, #2_000011
  777.     moveq    r0, r0, lsl #3
  778.     andne    r0, r0, #2_000111
  779.     orrhi    r0, r0, #2_100000        ; not vdc_dma_control and bit 4 of r0 set
  780.     biceq    r3, r3, #2_011000
  781.     bicne    r3, r3, #2_100111
  782.     orr    r3, r3, r0
  783.     str    r3, [r1, #vdc_event_mask]
  784.     movs    pc, r14
  785. vdc_write_2_mask
  786.     =    0xff, 0xff, 0xff, 0x00        ; 0x00-0x03
  787.     =    0x00, 0xff, 0xff, 0xff        ; 0x04-0x07
  788.     =    0xff, 0xff, 0x1f, 0x7f        ; 0x08-0x0b
  789.     =    0x1f, 0xff, 0xff, 0x1f        ; 0x0c-0x0f
  790.     =    0xff, 0xff, 0xff, 0xff        ; 0x10-0x13
  791.  
  792. VRAM_SATB_Transfer
  793.     ldr    r0, [r1, #vdc_status]
  794.     ldr    r3, [r1, #vdc_event_mask]
  795.     orr    r0, r0, #event_vram_satb
  796.     str    r0, [r1, #vdc_status]
  797.     tst    r0, r3
  798.     orrne    r_p, r_p, #IRQ1 << 16
  799.     movs    pc, r14
  800.  
  801. ; r1 = video registers
  802. ; r2 = VDC address
  803. VRAM_VRAM_Transfer
  804.     stmfd    r13!, {r4-r10}
  805.     ldr    r3, [r1, #vdc_dma_control]
  806.     ldr    r0, [r1, #vdc_dma_source]    ; r0 = VRAM source address
  807.     tst    r3, #1 << 3
  808.     ldr    r2, [r1, #vdc_dma_destination]    ; r2 = VRAM destination address
  809.     mov    r0, r0, lsl #17
  810.     mov    r2, r2, lsl #17
  811.     mvnne    r4, #0
  812.     moveq    r4, #1
  813.     ; r4 = source increment
  814.     ldr    r6, adrof_video_ram        ; r6 = video ram lower bytes
  815.     tst    r3, #1 << 2
  816.     ldr    r7, [r1, #vdc_dma_length]    ; r7 = length of transfer
  817.     mvnne    r5, #0
  818.     moveq    r5, #1
  819.     ; r5 = destination increment
  820.     add    r8, r6, #1            ; r8 = video ram upper bytes
  821. VRAM_VRAM_Loop
  822.     ldrb    r9, [r6, r0, lsr #16]
  823.     ldrb    r10, [r8, r0, lsr #16]
  824.     add    r0, r0, r4, lsl #17
  825.     strb    r9, [r6, r2, lsr #16]
  826.     strb    r10, [r8, r2, lsr #16]
  827.     add    r2, r2, r5, lsl #17
  828.     subs    r7, r7, #1
  829.     bgt    VRAM_VRAM_Loop
  830.     ldmfd    r13!, {r4-r10}
  831.     ldr    r2, [r1, #vdc_status]
  832.     orr    r2, r2, #event_vram_vram
  833.     str    r2, [r1, #vdc_status]        ; set VDC event high
  834.     movs    pc, r14
  835. Resize_Screen
  836.     stmfd    r13!, {r7, r14}
  837.     bl    Update_Video_Timing
  838.     mov    r7, r1
  839.     ldrb    r0, [r1, #vdc_horizontal_display]
  840.     mov    r2, #640
  841.     mov    r3, #480
  842.     ldr    r1, adrof_mode_block
  843.     cmp    r0, #(480 >> 3) - 1
  844.     movle    r2, #480
  845.     movle    r3, #352
  846.     cmp    r0, #(320 >> 3) - 1
  847.     ldmib    r1, {r0, r14}
  848.     movle    r2, #320
  849.     movle    r3, #256
  850.     cmp    r0, r2
  851.     cmpeq    r14, r3
  852.     ldmeqfd    r13!, {r7, pc}^
  853.     stmib    r1, {r2-r3}
  854.     mov    r0, #0
  855.     swi    OS_ScreenMode
  856.     swi    OS_RemoveCursors
  857.     adr    r0, vdu_variable
  858.     ldr    r1, adrof_physical_screen
  859.     swi    OS_ReadVduVariables
  860.     ldr    r1, adrof_physical_screen
  861.     ldr    r0, [r1, #0]
  862.     str    r0, [r7, #output_address]
  863. ;    ldr    r1, adrof_output_address
  864. ;    str    r0, [r1, #0]
  865.     mvn    r0, #0
  866.     mov    r1, #6
  867.     swi    OS_ReadModeVariable
  868.     ldr    r0, adrof_physical_screen_width
  869.     str    r2, [r0, #0]
  870.     mov    r2, #255
  871. Set_Palette
  872.     swi    OS_WriteI + 19
  873.     mov    r0, r2
  874.     swi    OS_WriteC ; colour number
  875.     swi    OS_WriteI + 16
  876.     and    r0, r2, #31
  877.     mov    r0, r0, lsl #3
  878.     add    r0, r0, r2, lsr #5
  879.     swi    OS_WriteC ; red
  880.     mov    r0, r2
  881.     swi    OS_WriteC ; green
  882.     and    r0, r2, #3
  883.     mov    r0, r0, lsl #6
  884.     add    r0, r0, r2, lsr #2
  885.     swi    OS_WriteC ; blue
  886.     subs    r2, r2, #1
  887.     bge    Set_Palette
  888.     ldmfd    r13!, {r7, pc}^
  889. vdu_variable
  890.     DCD    148
  891.     DCD    -1
  892. Update_Video_Timing
  893.     stmfd    r13!, {r1, r14}
  894.     ldr    r0, [r1, #vdc_vertical_sync]
  895.     ldr    r2, [r1, #vdc_vertical_display]
  896.     ldr    r3, [r1, #vdc_vertical_end]
  897.     bic    r2, r2, #2_11111110 << 8
  898.     and    r3, r3, #2_11111111
  899.     add    r2, r2, r3
  900.     add    r2, r2, r0, lsr #8
  901.     and    r3, r0, #2_00011111
  902.     ldr    r0, video_divider
  903.     add    r2, r2, r3
  904.     add    r2, r2, #4            ; r2 = vertical height
  905.     str    r2, [r1, #vdc_display_rows]
  906.  
  907.     add    r1, r2, r2, lsl #1
  908.     mov    r2, #0
  909.     adds    r0, r0, r0
  910.     rsb    r1, r1, #0
  911.     mov    r3, #32
  912. Division_Loop
  913.     adcs    r2, r1, r2, lsl #1
  914.     subcc    r2, r2, r1
  915.     adcs    r0, r0, r0
  916.     adcs    r2, r1, r2, lsl #1
  917.     subcc    r2, r2, r1
  918.     adcs    r0, r0, r0
  919.     adcs    r2, r1, r2, lsl #1
  920.     subcc    r2, r2, r1
  921.     adcs    r0, r0, r0
  922.     adcs    r2, r1, r2, lsl #1
  923.     subcc    r2, r2, r1
  924.     adcs    r0, r0, r0
  925.     sub    r3, r3, #4
  926.     teq    r3, #0
  927.     bne    Division_Loop
  928.  
  929.     mov    timer, timer, lsr #16
  930.     orr    timer, r0, timer, lsl #16
  931.     ldmfd    r13!, {r1, pc}^
  932. video_divider
  933.     DCD    358000
  934.  
  935.  
  936. ;    ubyte VDC_Read(uhalf address)
  937. ;    Video Display Controller read port
  938. VDC_Read
  939.     EXPORT    VDC_Read
  940.     ldr    r1, adrof_video_registers
  941.     cmp    r0, #1
  942.     moveq    r0, #0
  943.     ldrlt    r2, [r1, #vdc_status]
  944.     moveqs    pc, r14
  945.     blt    VDC_Read_Status
  946.     cmp    r0, #3
  947.     movgts    pc, r14
  948.  
  949. ;    ldr    r2, adrof_vdc_address
  950. ;    ldr    r2, [r2, #0]
  951. ;    cmp    r2, #3
  952. ;    bne    VDC_Read_X
  953. ;    cmp    r0, #3
  954.  
  955.     ldr    r3, [r1, #vdc_read_address]
  956.     ldr    r2, adrof_video_ram
  957.     mov    r3, r3, lsl #16
  958.     addeq    r2, r2, #1
  959.     ldrb    r0, [r2, r3, lsr #15]
  960.     ldreq    r2, [r1, #vdc_control]
  961.     movlts    pc, r14
  962.     and    r2, r2, #3 << 11
  963.     cmp    r2, #1 << 11
  964.     addlt    r3, r3, #0x01 << 16
  965.     addeq    r3, r3, #0x20 << 16
  966.     cmp    r2, #2 << 11
  967.     addeq    r3, r3, #0x40 << 16
  968.     addgt    r3, r3, #0x80 << 16
  969.     mov    r3, r3, lsr #16
  970.     str    r3, [r1, #vdc_read_address]
  971.     movs    pc, r14
  972. VDC_Read_Status
  973.     ldr    r3, [r1, #vdc_event_mask]
  974.     and    r0, r2, r3
  975. ;    orr    r3, r0, r0, lsr #1
  976. ;    orr    r3, r3, r3, lsr #2
  977. ;    orr    r3, r3, r3, lsr #3
  978. ;    bic    r3, r0, r3
  979.     bic    r2, r2, r3
  980.     str    r2, [r1, #vdc_status]
  981.     movs    pc, r14
  982. ;VDC_Read_X
  983. ;    ldr    r0, [r1, r0, lsl #2]
  984. ;    movs    pc, r14
  985.  
  986.  
  987. ;    void VCE_Write(uhalf address, ubyte value)
  988. ;    Video Colour Encoder write port
  989. VCE_Write
  990.     EXPORT    VCE_Write
  991.     cmp    r0, #1
  992.     ldrlt    r2, adrof_dot_width
  993.     andlt    r1, r1, #1
  994.     strlt    r1, [r2, #0]
  995.     movles    pc, r14
  996.     cmp    r0, #3
  997.     ldr    r2, adrof_vce_address
  998.     andeq    r1, r1, #1
  999.     strltb    r1, [r2, #0]
  1000.     streqb    r1, [r2, #1]
  1001.     movles    pc, r14
  1002.     cmp    r0, #5
  1003.     movgts    pc, r14
  1004.     ldr    r3, [r2, #0]
  1005.     mov    r3, r3, lsl #23
  1006.     addeq    r0, r3, #1 << 23
  1007.     moveq    r0, r0, lsr #23
  1008.     streq    r0, [r2, #0]
  1009.     ldr    r2, adrof_background_vce
  1010.     moveq    r1, r1, lsl #8
  1011.     ldr    r0, [r2, r3, lsr #21]!
  1012.     mov    r3, #0xff00
  1013.     bicne    r0, r0, r3, ror #1 + 8
  1014.     biceq    r0, r0, r3, ror #1
  1015.     orr    r0, r0, r1, ror #1
  1016.     str    r0, [r2, #0]
  1017.     movs    pc, r14
  1018.  
  1019. ;    ubyte VCE_Read(uhalf address)
  1020. ;    Video Colour Encoder read port
  1021. VCE_Read
  1022.     EXPORT    VCE_Read
  1023.     cmp    r0, #1
  1024.     movle    r0, #0
  1025.     movles    pc, r14
  1026.     ldr    r1, adrof_vce_address
  1027.     cmp    r0, #3
  1028.     ldrltb    r0, [r1, #0]
  1029.     ldreqb    r0, [r1, #1]
  1030.     movles    pc, r14
  1031.     cmp    r0, #5
  1032.     movgts    pc, r14
  1033.     ldr    r2, [r1, #0]
  1034.     ldr    r3, adrof_background_vce
  1035.     mov    r2, r2, lsl #23
  1036.     ldr    r0, [r3, r2, lsr #21]
  1037.     mov    r0, r0, ror #32 - 1
  1038.     moveq    r0, r0, lsr #8
  1039.     andlt    r0, r0, #0xff
  1040.     movlts    pc, r14
  1041.     add    r2, r2, #1 << 23
  1042.     mov    r2, r2, lsr #23
  1043.     str    r2, [r1, #0]
  1044.     movs    pc, r14
  1045.  
  1046.  
  1047. adrof_cpu_emulation_data
  1048.     IMPORT    cpu_emulation_data
  1049.     DCD    cpu_emulation_data
  1050. adrof_dot_width
  1051.     DCD    dot_width
  1052. adrof_background_line
  1053.     DCD    background_line
  1054. ;adrof_output_line
  1055. ;    DCD    output_line
  1056. adrof_physical_screen
  1057.     DCD    physical_screen
  1058. adrof_physical_screen_width
  1059.     DCD    physical_screen_width
  1060.  
  1061. adrof_vdc_address
  1062.     DCD    vdc_address
  1063. adrof_vce_address
  1064.     DCD    vce_address
  1065. adrof_mode_block
  1066.     DCD    mode_block
  1067.  
  1068. adrof_video_ram
  1069.     DCD    video_ram
  1070. adrof_sprite_cache_count
  1071.     DCD    sprite_cache_count
  1072. adrof_sprite_cache_info
  1073.     DCD    sprite_cache_info
  1074. adrof_sprite_cache_data
  1075.     DCD    sprite_cache_data
  1076. adrof_video_registers
  1077.     DCD    video_registers
  1078. adrof_background_vce
  1079.     DCD    background_vce
  1080. adrof_sprite_vce
  1081.     DCD    sprite_vce
  1082.  
  1083. ;adrof_irq_status
  1084. ;    DCD    irq_status
  1085. ;adrof_irq_mask
  1086. ;    DCD    irq_mask
  1087.  
  1088.  
  1089. ;    ------------------------------------------------------------------------
  1090.  
  1091.     AREA    |video$$data|, DATA
  1092.  
  1093.  
  1094. dot_width
  1095.     EXPORT    dot_width
  1096.     DCD    0
  1097. background_line
  1098.     EXPORT    background_line
  1099.     DCD    0
  1100. ;output_line
  1101. ;    EXPORT    output_line
  1102. ;    DCD    0
  1103. vdc_address
  1104.     EXPORT    vdc_address
  1105.     DCD    0
  1106. vce_address
  1107.     EXPORT    vce_address
  1108.     DCD    0
  1109. physical_screen
  1110.     EXPORT    physical_screen
  1111.     DCD    physical_screen
  1112. physical_screen_width ; must follow physical_screen
  1113.     EXPORT    physical_screen_width
  1114.     DCD    physical_screen_width
  1115. mode_block
  1116.     EXPORT    mode_block
  1117.     DCD    1
  1118.     DCD    -1
  1119.     DCD    -1
  1120.     DCD    3
  1121.     DCD    -1
  1122.     DCD    0
  1123.     DCD    128
  1124.     DCD    3
  1125.     DCD    255
  1126.     DCD    -1
  1127.  
  1128.  
  1129. ;    ------------------------------------------------------------------------
  1130.  
  1131.     AREA    |video$$zidata|, NOINIT
  1132.  
  1133.  
  1134. video_ram
  1135.     EXPORT    video_ram
  1136.     %    0x20000
  1137. sprite_cache_count
  1138.     EXPORT    sprite_cache_count
  1139.     %    (256 + 64 + 64) * 4
  1140. sprite_cache_info
  1141.     EXPORT    sprite_cache_info
  1142.     %    (256 + 64 + 64) * 16 * 4
  1143. sprite_cache_data
  1144.     EXPORT    sprite_cache_data
  1145.     %    (256 + 64 + 64) * 16 * 4
  1146. video_registers
  1147.     EXPORT    video_registers
  1148.     %    vdc_size
  1149. background_vce
  1150.     EXPORT    background_vce
  1151.     %    256 * 4
  1152. ; sprite_vce MUST follow background_vce
  1153. sprite_vce
  1154.     EXPORT    sprite_vce
  1155.     %    256 * 4
  1156.  
  1157.  
  1158.     END
  1159.