📄 asm_prsm.s
字号:
movel a6@(8),d2 | x1
movel a6@(12),d3 | y1
movel a6@(20),d1 | y2
movel a6@(16),a2 | x2
subl d3,d1 | (y2 - y1) -> d1
clrl d4 | d4 = (2 * dx) = NA
clrl d5 | d5 = (2 * dx) = NB
subl d1,d4 | (2 * dx) - dy -> d4
subql #1,d4 | d4 - SY -> d4
movel d1,d6 | dy -> d6
movel d5,d7 | dx -> d7
subl d6,d7 | dx - dy -> d7
lsll #1,d7 | shift left, d7 = ND
| by this point, d4 = ND, d5 = NB
subql #1,d6 | d6 = NC
moveq #6,d0 | SX, SY, XMAJ
| we are drawing a series of vertical lines, all the same length
| so no need to re-calculate all the magic numbers each time
ldraw5x_1:
cmpl d2,a2 | x1 <= x2
jge ldraw5x_2
jra ldraw5x_12
ldraw5x_2:
movel #0x0e,a0@(GCW_CMD) | write, 4x5, 1 of 20
tstl d1 | dy
bne ldraw5x_10
movel d3,a0@(GCW_PY) | pixel Y addr
movel d2,a0@(GCW_PX_SM) | pixel X addr, start single mem
bra ldraw5x_11
ldraw5x_10:
movel d4,a0@(GCW_LG2) | NA
movel d5,a0@(GCW_LG1) | NB
movel d7,a0@(GCW_LG2) | ND
movel d6,a0@(GCW_LG3) | NC
movel d0,a0@(GCW_LG4) | SX, SY, XMAJ
movel d3,a0@(GCW_PY) | pixel Y
movel d2,a0@(GCW_PX_SL) | pixel X, start line
ldraw5x_11:
addql #1,d2 | x++
jra ldraw5x_1
ldraw5x_12:
moveml sp@+,d0-d7/a0-a2
unlk a6
rts
| read 1 pixel from the screen, handle the bizarre layout
.even
.globl r1pix3
r1pix3:
link a6,#0
moveml d1-d5/a0,sp@-
movew #1023,d5
subw a6@(14),d5 | d5 is y as 16-bit value
movew d5,d4
andib #0xfc,d4 | d4 is y0
movew #3,d0
andw d5,d0 | y & 3
movel #3,d3 | ensure top word is clear
subw d0,d3 | 3 - (y & 3)
aslw #3,d3 | << 3
movel a6@(8),d0 | x
divuw #20,d0 | x % 20
clrw d0 | clear quotient
swap d0 | put remainder in lower 16 bits
divuw #5,d0 | (x % 20) / 5
aslw #3,d0 | << 3
addw d0,d3 | ys in d3
movew #24,d0
cmpw d3,d0
jge r1pix3_1
movew #-32,d0
addw d0,d3
r1pix3_1:
lea GC_BASE,a0 | base of video control registers
movel a6@(16),a0@(GCW_PSEL) | plane select mask
movel #0x07,a0@(GCW_LG4)
movel #0x66,a0@(GCW_CMD)
movel a6@(8),a0@(GCW_PX) | x
movel d4,a0@(GCW_PY) | y
movel a0@(GCR_IN_SM),d0 | read intensity, start single mem cycle
movel a0@(GCR_IN_SM),d0
movel d0,d1
moveq #0,d0
notb d0 | d0 = 0xff
asll d3,d0 | << fs
andl d1,d0 | (ic & (0xff << fs)
asrl d3,d0 | >> ys
andl #0xff,d0
moveml sp@+,d1-d5/a0
unlk a6
rts
| read a rectangular array of pixels from the screen
| void rd_rect(int x1, int y1, int x2, int y2, char *buf)
.even
.globl rd_rect2
rd_rect2:
link a6,#0
moveml d1-d7/a0-a1,sp@-
movel #1023,d7
subl a6@(20),d7 | d7 is y2 as 16-bit value
movel d7,a6@(20)
movel #1023,d6
subl a6@(12),d6 | d6 is y1 as 16-bit value
movel d6,a6@(12)
movel a6@(8),d5 | d5 is x
lea GC_BASE,a0 | base of video control registers
movel a6@(24),a1 | buf
rd_rect2_1:
cmpw a6@(18),d5 | x < x2
jlt rd_rect2_2
jra rd_rect2_8
rd_rect2_2:
movel d5,d4 | d4 is xs
divuw #20,d4 | x % 20
clrw d4 | clear quotient
swap d4 | remainder in lower word
divuw #5,d4 | (x % 20) / 5
aslw #3,d4 | ((x % 20) / 5) << 3
rd_rect2_3:
cmpw d7,d6 | y > y2
jgt rd_rect2_4
jra rd_rect2_7
rd_rect2_4:
movel d6,d3 | d3 is y0
andib #0xfc,d3 | y & 0xfffc
moveq #3,d0
andw d6,d0 | y & 3
moveq #3,d2 | ensure top word is clear
subw d0,d2 | 3 - (y & 3)
aslw #3,d2 | << 3
addw d4,d2 | ys in d2
moveq #24,d0
cmpw d2,d0
jge rd_rect2_5
movew #-32,d0
addw d0,d2
rd_rect2_5:
movel #0xff,a0@(GCW_PSEL) | plane select mask
movel #0x07,a0@(GCW_LG4)
movel #0x66,a0@(GCW_CMD)
movel d5,a0@(GCW_PX) | x
movel d3,a0@(GCW_PY) | y0
movel a0@(GCR_IN_SM),d1 | read intensity, start single mem cycle
movel a0@(GCR_IN_SM),d1
moveq #0,d0
notb d0 | d0 = 0xff
asll d2,d0 | << fs
andl d1,d0 | (ic & (0xff << fs)
asrl d2,d0 | >> ys
andl #0xff,d0
moveb d0,a1@+ | *buf++
rd_rect2_6:
subqw #1,d6 | y--
jra rd_rect2_3
rd_rect2_7:
addqw #1,d5 | x++
movel a6@(12),d6 | y = y1
jra rd_rect2_1
rd_rect2_8:
moveml sp@+,d1-d7/a0-a1
unlk a6
rts
| write a rectangular array of pixels to the screen
| void wr_rect(int x1, int y1, int x2, int y2, char *buf)
.even
.globl wr_rect2
wr_rect2:
link a6,#0
moveml d1-d7/a0-a1,sp@-
movel #1023,d7
subl a6@(20),d7 | d7 is y2 as 16-bit value
movel d7,a6@(20)
movel #1023,d6
subl a6@(12),d6 | d6 is y1 as 16-bit value
movel d6,a6@(12)
movel a6@(8),d5 | d5 is x
lea GC_BASE,a0 | base of video control registers
movel a6@(24),a1 | buf
wr_rect2_1:
cmpw a6@(18),d5 | x < x2
jlt wr_rect2_2
jra wr_rect2_8
wr_rect2_2:
movel d5,d4 | d4 is xs
divuw #20,d4 | x % 20
clrw d4 | clear quotient
swap d4 | remainder in lower word
divuw #5,d4 | (x % 20) / 5
aslw #3,d4 | ((x % 20) / 5) << 3
wr_rect2_3:
cmpw d7,d6 | y > y2
jgt wr_rect2_4
jra wr_rect2_7
wr_rect2_4:
movel d6,d3 | d3 is y0
andib #0xfc,d3 | y & 0xfffc
movel #0xff,a0@(GCW_PSEL) | plane select mask
movel #0x07,a0@(GCW_LG4)
movel #0x66,a0@(GCW_CMD)
movel d5,a0@(GCW_PX) | x
movel d3,a0@(GCW_PY) | y0
movel a0@(GCR_IN_SM),d1 | read intensity, start single mem cycle
movel a0@(GCR_IN_SM),d1 | d1 is ic
moveq #3,d0
andw d6,d0 | y & 3
moveq #3,d2 | ensure top word is clear
subw d0,d2 | 3 - (y & 3)
aslw #3,d2 | << 3
addw d4,d2 | ys in d2
moveq #24,d0
cmpw d2,d0
jge wr_rect2_5
movew #-32,d0
addw d0,d2
wr_rect2_5:
moveq #0,d0
notb d0 | d0 = 0xff
asll d2,d0 | <<fs
notl d0 | invert
andl d1,d0 | (ic & (0cff << ys))
clrl d1
moveb a1@+,d1 | *buf++
asll d2,d1 | << ys
orl d1,d0
movel #0xff,a0@(GCW_PSEL) | plane select mask
movel #0x07,a0@(GCW_LG4)
movel #0x6e,a0@(GCW_CMD)
movel d5,a0@(GCW_PX) | x
movel d3,a0@(GCW_PY) | y0
movel d0,a0@(GCW_IN_SM) | write inten, start single mem cycle
wr_rect2_6:
subqw #1,d6 | y--
jra wr_rect2_3
wr_rect2_7:
addqw #1,d5 | x++
movel a6@(12),d6 | y = y1
jra wr_rect2_1
wr_rect2_8:
moveml sp@+,d1-d7/a0-a1
unlk a6
rts
| write a rectangular array of pixels to the screen
| void wr_rect4(int x1, int y1, int x2, int y2, char *buf)
|
| This version writes the block with the x axis as the inner loop,
| this is slower than wr_rect2() but is necessary for the VNC
| CopyDataToScreen() function.
.even
.globl wr_rect4
wr_rect4:
link a6,#0
moveml d1-d7/a0-a1,sp@-
movel #1023,d7
subl a6@(20),d7 | d7 is y2 as 16-bit value
movel d7,a6@(20)
movel #1023,d6
subl a6@(12),d6 | d6 is y1 as 16-bit value
movel d6,a6@(12)
movel a6@(8),d5 | d5 is x
lea GC_BASE,a0 | base of video control registers
movel a6@(24),a1 | buf
wr_rect4_1:
cmpw d7,d6 | y > y2
jgt wr_rect4_2
jra wr_rect4_8
wr_rect4_2:
movel d6,d3 | d3 is y0
andib #0xfc,d3 | y & 0xfffc
moveq #3,d0
andw d6,d0 | y & 3
moveq #3,d2 | ensure top word is clear
subw d0,d2 | 3 - (y & 3)
aslw #3,d2 | << 3
wr_rect4_3:
cmpw a6@(18),d5 | x < x2
jlt wr_rect4_4
jra wr_rect4_7
wr_rect4_4:
movel #0xff,a0@(GCW_PSEL) | plane select mask
movel #0x07,a0@(GCW_LG4)
movel #0x66,a0@(GCW_CMD)
movel d5,a0@(GCW_PX) | x
movel d3,a0@(GCW_PY) | y0
movel a0@(GCR_IN_SM),d1 | read intensity, start single mem cycle
movel a0@(GCR_IN_SM),d1 | d1 is ic
movel d5,d4 | d4 is xs
divuw #20,d4 | x % 20
clrw d4 | clear quotient
swap d4 | remainder in lower word
divuw #5,d4 | (x % 20) / 5
aslw #3,d4 | ((x % 20) / 5) << 3
addw d2,d4 | ys in d2, xs in d4
moveq #24,d0
cmpw d4,d0
jge wr_rect4_5
movew #-32,d0
addw d0,d4
wr_rect4_5:
moveq #0,d0
notb d0 | d0 = 0xff
asll d4,d0 | <<fs
notl d0 | invert
andl d1,d0 | (ic & (0cff << ys))
clrl d1
moveb a1@+,d1 | *buf++
asll d4,d1 | << ys
orl d1,d0
movel #0xff,a0@(GCW_PSEL) | plane select mask
movel #0x07,a0@(GCW_LG4)
movel #0x6e,a0@(GCW_CMD)
movel d5,a0@(GCW_PX) | x
movel d3,a0@(GCW_PY) | y0
movel d0,a0@(GCW_IN_SM) | write inten, start single mem cycle
wr_rect4_6:
addqw #1,d5 | x++
jra wr_rect4_3
wr_rect4_7:
subqw #1,d6 | y--
movel a6@(8),d5 | x = x1
jra wr_rect4_1
wr_rect4_8:
moveml sp@+,d1-d7/a0-a1
unlk a6
rts
| write a rectangular array of pixels to the screen
| void wr_rect5(int x1, int y1, int x2, int y2, char *buf)
|
| This version writes the block with the x axis as the inner loop,
| this is slower than wr_rect2() but is necessary for the VNC
| CopyDataToScreen() function.
|
| This version uses a lookup table for the pixel mask and shift count.
| This removes one of the divide instructions (divides are slow).
.even
.globl wr_rect5
wr_rect5:
link a6,#0
moveml d1-d7/a0-a2,sp@-
movel #1023,d7
subl a6@(20),d7 | d7 is y2
movel #1023,d6
subl a6@(12),d6 | d6 is y1
movel a6@(8),d5 | d5 is x
lea GC_BASE,a0 | base of video control registers
movel a6@(24),a1 | buf
lea pm_tab,a2 | base of lookup table
movel #0xff,a0@(GCW_PSEL) | plane select mask
wr_rect5_1:
cmpl d7,d6 | y > y2
jle wr_rect5_8
movel d6,d3 | d3 is y0
andib #0xfc,d3 | y & 0xfffc
moveq #3,d2
andl d6,d2 | y & 3
asll #3,d2 | (y & 3) * 8
wr_rect5_3:
cmpl a6@(16),d5 | x < x2
jge wr_rect5_7
movel #0x07,a0@(GCW_LG4)
movel #0x66,a0@(GCW_CMD)
movel d5,a0@(GCW_PX) | x
movel d3,a0@(GCW_PY) | y0
movel a0@(GCR_IN_SM),d1 | read intensity, start single mem cycle
movel a0@(GCR_IN_SM),d1 | d1 is ic
movel d5,d4 | d4 is xs
divuw #20,d4 | x % 20
clrw d4 | clear quotient
swap d4 | remainder in lower word
asll #5,d4 | *32
addl d2,d4 | ((x % 20) * 32) + ((y % 4) * 8)
movel a2@(d4:w:1),d0 | fetch mask
andl d1,d0 | (ic & mask)
| andl a2@(d4:w:1),d0 | (ic & mask)
clrl d1
moveb a1@+,d1 | *buf++
addql #4,d4
movel a2@(d4:w:1),d4 | fetch shift count
asll d4,d1 | << ys
orl d1,d0
movel #0x07,a0@(GCW_LG4)
movel #0x6e,a0@(GCW_CMD)
movel d5,a0@(GCW_PX) | x
movel d3,a0@(GCW_PY) | y0
movel d0,a0@(GCW_IN_SM) | write inten, start single mem cycle
wr_rect5_6:
addql #1,d5 | x++
jra wr_rect5_3
wr_rect5_7:
subql #1,d6 | y--
movel a6@(8),d5 | x = x1
jra wr_rect5_1
wr_rect5_8:
moveml sp@+,d1-d7/a0-a2
unlk a6
rts
| write 1 pixel to the screen, handle the bizarre layout
.even
.globl w1pix3
w1pix3:
link a6,#0
moveml d1-d5/a0,sp@-
movew #1023,d5
subw a6@(14),d5 | d5 is y as 16-bit value
movew d5,d4
andib #0xfc,d4 | d4 is y0
lea GC_BASE,a0 | base of video control registers
movel a6@(16),a0@(GCW_PSEL) | plane select mask
movel #0x07,a0@(GCW_LG4)
movel #0x66,a0@(GCW_CMD)
movel a6@(8),a0@(GCW_PX) | x
movel d4,a0@(GCW_PY) | y0
movel a0@(GCR_IN_SM),d0 | read intensity, start single mem cycle
movel a0@(GCR_IN_SM),d0 | 4 pixels in d0
movel d0,d3 | ic in d3
movew #3,d0
andw d5,d0 | y & 3
movel #3,d2 | ensure top word is clear
subw d0,d2 | 3 - (y & 3)
aslw #3,d2 | << 3
movel a6@(8),d0 | x
divuw #20,d0 | x % 20
clrw d0 | clear quotient
swap d0 | put remainder in lower 16 bits
divuw #5,d0 | (x % 20) / 5
aslw #3,d0 | << 3
addw d0,d2 | ys in d2
movew #24,d0
cmpw d2,d0
jge w1pix3_1
movew #-32,d0
addw d0,d2
w1pix3_1:
moveq #0,d0
notb d0 | d0 = 0xff
asll d2,d0 | << ys
notl d0 | invert
andl d3,d0 | (ic & (0xff << ys)
movel a6@(20),d1 | i
asll d2,d1 | i << ys
orl d1,d0
movel a6@(16),a0@(GCW_PSEL) | plane select mask
movel #0x07,a0@(GCW_LG4)
movel #0x6e,a0@(GCW_CMD)
movel a6@(8),a0@(GCW_PX) | x
movel d4,a0@(GCW_PY) | y0
movel d0,a0@(GCW_IN_SM) | write inten, start single mem cycle
moveml sp@+,d1-d5/a0
unlk a6
rts
| data
.data
| lookup table for wr_rect5()
| this gives the pixel mask and shift count to locate each pixel in
| the 4 x 20 array pattern used by the Prisma video board
pm_tab: .long 0x00ffffff, 24 | 0,0
.long 0xff00ffff, 16 | 0,1
.long 0xffff00ff, 8 | 0,2
.long 0xffffff00, 0 | 0,3
.long 0x00ffffff, 24 | 1,0
.long 0xff00ffff, 16 | 1,1
.long 0xffff00ff, 8 | 1,2
.long 0xffffff00, 0 | 1,3
.long 0x00ffffff, 24 | 2,0
.long 0xff00ffff, 16 | 2,1
.long 0xffff00ff, 8 | 2,2
.long 0xffffff00, 0 | 2,3
.long 0x00ffffff, 24 | 3,0
.long 0xff00ffff, 16 | 3,1
.long 0xffff00ff, 8 | 3,2
.long 0xffffff00, 0 | 3,3
.long 0x00ffffff, 24 | 4,0
.long 0xff00ffff, 16 | 4,1
.long 0xffff00ff, 8 | 4,2
.long 0xffffff00, 0 | 4,3
.long 0xffffff00, 0 | 5,0
.long 0x00ffffff, 24 | 5,1
.long 0xff00ffff, 16 | 5,2
.long 0xffff00ff, 8 | 5,3
.long 0xffffff00, 0 | 6,0
.long 0x00ffffff, 24 | 6,1
.long 0xff00ffff, 16 | 6,2
.long 0xffff00ff, 8 | 6,3
.long 0xffffff00, 0 | 7,0
.long 0x00ffffff, 24 | 7,1
.long 0xff00ffff, 16 | 7,2
.long 0xffff00ff, 8 | 7,3
.long 0xffffff00, 0 | 8,0
.long 0x00ffffff, 24 | 8,1
.long 0xff00ffff, 16 | 8,2
.long 0xffff00ff, 8 | 8,3
.long 0xffffff00, 0 | 9,0
.long 0x00ffffff, 24 | 9,1
.long 0xff00ffff, 16 | 9,2
.long 0xffff00ff, 8 | 9,3
.long 0xffff00ff, 8 | 10,0
.long 0xffffff00, 0 | 10,1
.long 0x00ffffff, 24 | 10,2
.long 0xff00ffff, 16 | 10,3
.long 0xffff00ff, 8 | 11,0
.long 0xffffff00, 0 | 11,1
.long 0x00ffffff, 24 | 11,2
.long 0xff00ffff, 16 | 11,3
.long 0xffff00ff, 8 | 12,0
.long 0xffffff00, 0 | 12,1
.long 0x00ffffff, 24 | 12,2
.long 0xff00ffff, 16 | 12,3
.long 0xffff00ff, 8 | 13,0
.long 0xffffff00, 0 | 13,1
.long 0x00ffffff, 24 | 13,2
.long 0xff00ffff, 16 | 13,3
.long 0xffff00ff, 8 | 14,0
.long 0xffffff00, 0 | 14,1
.long 0x00ffffff, 24 | 14,2
.long 0xff00ffff, 16 | 14,3
.long 0xff00ffff, 16 | 15,0
.long 0xffff00ff, 8 | 15,1
.long 0xffffff00, 0 | 15,2
.long 0x00ffffff, 24 | 15,3
.long 0xff00ffff, 16 | 16,0
.long 0xffff00ff, 8 | 16,1
.long 0xffffff00, 0 | 16,2
.long 0x00ffffff, 24 | 16,3
.long 0xff00ffff, 16 | 17,0
.long 0xffff00ff, 8 | 17,1
.long 0xffffff00, 0 | 17,2
.long 0x00ffffff, 24 | 17,3
.long 0xff00ffff, 16 | 18,0
.long 0xffff00ff, 8 | 18,1
.long 0xffffff00, 0 | 18,2
.long 0x00ffffff, 24 | 18,3
.long 0xff00ffff, 16 | 19,0
.long 0xffff00ff, 8 | 19,1
.long 0xffffff00, 0 | 19,2
.long 0x00ffffff, 24 | 19,3
| temporary storage for line drawing routine
gr_data:
line_x1: .long 0 | 0 (668)
line_y1: .long 0 | 4 (66c)
line_x2: .long 0 | 8 (670)
line_y2: .long 0 | 12 (674)
.long 0 | 16 (678)
.long 0 | 20 (67c)
.long 0 | 24 (680)
.long 0 | 28 (684)
.long 0 | 32 (688)
.long 0 | 36 (68c)
line_xdir: .long 0 | 40 (690)
line_ydir: .long 0 | 44 (694)
.long 0 | 48 (698)
line_selmask: .long 0 | 52 (69c)
line_inten: .long 0 | 56 (6A0)
line_flag: .word 0 | 60 (6a4)
init_flag1: .word 0 | 62 (6a6)
.long 0 | 64 (6a8)
.long 0 | 64 (6ac)
init_flag4: .long 0 | 64 (6b0)
.long 0 | 64 (6b4)
.long 0 | 64 (6b8)
.long 0 | 64 (6bc)
.long 0 | 64 (6c0)
.long 0 | 64 (6c4)
.long 0 | 64 (6c8)
.long 0 | 64 (6cc)
.long 0 | 64 (6d0)
.long 0 | 64 (6d4)
.long 0 | 64 (6d8)
.long 0 | 64 (6dc)
.long 0 | 64 (6e0)
.long 0 | 64 (6e4)
.long 0 | 64 (6e8)
.long 0 | 64 (6ec)
init_flag6: .long 0 | 64 (6f0)
init_flag5: .word 0 | 64 (6f4)
init_flag2: .word 0 | 64 (6f6)
init_flag3: .word 0 | 64 (6f8)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -