📄 asm_prsm.s
字号:
| Routines to interface C to the graphics card in the Prisma| These replace the ROM routines.|| 0.1 16/02/99 G.Harvey first created| 0.11 19/02/99 G.Harvey optimise line drawing (c_ldraw4())| 0.2 20/02/99 G.Harvey add read/write pixel| 0.3 21/02/99 G.Harvey add video init routines| 0.4 23/02/99 G.Harvey add r1pix| 0.41 26/02/99 G.Harvey add w1pix| 0.5 27/02/99 G.Harvey add rd_rect, wr_rect| 0.51 02/03/99 G.Harvey add wr_rect5| Base addr of GC video buffer control registersGC_BASE = 0x200440| GC Video Buffer write registers (offsets from the base addr)GCW_CE = 0x00 | chip enableGCW_PSEL = 0x04 | plane selectGCW_INTEN = 0x08 | intensity write dataGCW_CMD = 0x0c | commandGCW_CMAP = 0x10 | colour map address / dataGCW_DAC = 0x14 | DAC / video controlGCW_PY_SM = 0x18 | pixel Y address / start single mem cycleGCW_IN_SM = 0x1c | intensity write data / start single mem cycleGCW_PX_SL = 0x20 | pixel X address / start lineGCW_PX_SM = 0x24 | pixel X address / start single mem cycleGCW_PY = 0x28 | pixel Y addressGCW_PX = 0x2c | pixel X addressGCW_LG1 = 0x30 | line generation algorithmGCW_LG2 = 0x34 | line generation algorithmGCW_LG3 = 0x38 | line generation algorithmGCW_LG4 = 0x3c | line generation algorithm| GC Video Buffer read registers (offsets from the base addr)GCR_INTEN = 0x00 | read intensityGCR_RESV = 0x04 | reservedGCR_CMAP = 0x08 | read colour mapGCR_STATUS = 0x0c | read VBUSY, VBLANK statusGCR_IN_SM = 0x10 | read intensity / start single mem cycle .text| Video init 1| from LAB_0367 at 0x00104760 .even.globl init_scrinit_scr:init1: movel d0,sp@- movel a0,sp@- lea GC_BASE,a0 | base of video control registers clrl a0@(GCW_LG3) tstl a0@(524) | 0x20064c - CMD reg but inhibit commandinit1_1: btst #6,a0@(524) | GCR_STATUS with command inhibit beq init1_1 | wait for VBLANK ? init1_2: btst #5,a0@(524) | GCR_STATUS bne init1_2 | VBLANK ? clrl a0@(GCW_CMAP) | colour map moveq #0x17,d0 clrl a0@(GCW_CMAP) movel d0,a0@(GCW_DAC) moveq #0x1b,d0 clrl a0@(GCW_CMAP) movel d0,a0@(GCW_DAC) moveq #0x1f,d0 clrl a0@(GCW_CMAP) movel d0,a0@(GCW_DAC) moveq #6,d0 moveb d0,init_flag1 | ?? moveq #7,d0 moveb d0,line_flag clrl d0 moveb line_flag,d1 btst #2,d1 beq init1_3 orw #0x100,d0init1_3: notb d1 andb #3,d1 orb d1,d0 clrl d1 moveb init_flag1,d1 lsll #5,d1 orl d1,d0 movel d0,a0@(GCW_DAC) movel #0x1ff,line_selmask bsr init3 bsr init2 moveal sp@+,a0 movel sp@+,d0 rts| Video init 2| LAB_036B at 0x0010047f4 .eveninit2: link a6,#0 moveml d2-d7/a2-a5,sp@- moveal #0x118808,a3 clrw init_flag2init2_1: moveq #0x10,d0 cmpw init_flag2,d0 ble init2_7 movew init_flag2,init_flag3 moveb a3@+,d7 andw #0xff,d7 moveb a3@+,d6 extw d6 moveb a3@+,d5 andw #0xff,d5 moveb a3@+,d4 extw d4 moveb a3@+,d3 andw 0xff,d3 moveb a3@+,d2 extw d2 moveal init_flag4,a2 clrw init_flag5init2_2: moveq #16,d0 cmpw init_flag5,d0 | 06F4 ble init2_6 movew init_flag3,d1 | 06F8 extl d1 moveq #24,d0 lsll d0,d1 movel d1,init_flag6 | 6F0 movew d7,d1 extl d1 moveq #16,d0 lsll d0,d1 orl d1,init_flag6 | 6F0 movew d5,d1 extl d1 lsll #8,d1 orl d1,init_flag6 | 6F0 movew d3,d1 extl d1 orl d1,init_flag6 movel init_flag6,a2@+ | store map entry in table movew d7,d1 extl d1 movew d6,d0 extl d0 addl d0,d1 movew d1,d7 movew d5,d0 extl d0 movew d4,d1 extl d1 addl d1,d0 movew d0,d5 movew d3,d0 extl d0 movew d2,d1 extl d1 addl d1,d0 movew d0,d3 cmpw #0xff,d7 ble init2_3 movew #0xff,d7init2_3: cmpw #0xff,d5 ble init2_4 movew #0xff,d5init2_4: cmpw #0xff,d3 ble init2_5 movew #0xff,d3init2_5: moveq #16,d0 addw d0,init_flag3 | 06F8 addqw #1,init_flag5 | 06F4 bra init2_2init2_6: pea init_flag4 | start of colour map moveq #16,d0 | no. of entries movel d0,sp@- bsr c_pcmap | write colour map to video board addql #8,sp addqw #1,init_flag2 | 06F6 bra init2_1init2_7: moveml sp@+,d2-d7/a2-a5 unlk a6 rts| C entry to program the colour map| c_pcmap(int len, int *map)|| the format of the map appears to be an array of longwords, each word| contains an index value and the values for R, G and B, all 8 bits.| Format is: :INDEX:RED:GREEN:BLUE: .even.globl c_pcmapc_pcmap: link a6,#0 movel a5,sp@- movel d7,sp@- moveal a6@(12),a5 | point to colour map movel a6@(8),d7 | no. of entries bsr pcmap1 movel sp@+,d7 moveal sp@+,a5 unlk a6 rts| program colour map 1| looks like you can only set a maximum of 127 entries at a time .evenpcmap1: moveml d0-d7/a0-a6,sp@- moveq #0x17,d0 moveq #0x1b,d1 moveq #0x1f,d2 subql #1,d7 btst #7,d7 bne pcmap1_1 | bra if more than 127 entries bsr pcmap2 bra pcmap1_2 | donepcmap1_1: subl #0x7f,d7 movel d7,sp@- moveq #0x7f,d7 bsr pcmap2 | first 127 entries movel sp@+,d7 bsr pcmap2 | remainder of entriespcmap1_2: moveml sp@+,d0-d7/a0-a6 rts| program colour map 2| this subroutine actually writes to the colour map on the video| board .evenpcmap2: lea GC_BASE,a0 | pint to control registers tstl a0@(524) | wait for VBLANKpcmap2_1: btst #6,a0@(524) beq pcmap2_1pcmap2_2: btst #6,a0@(524) bne pcmap2_2pcmap2_3: movel a5@+,d3 | map entry movew d3,d5 swap d3 movel d5,d4 rorl #8,d4 movel d3,a0@(GCW_CMAP) | upper 8 bits is addr, lower is data movel d0,a0@(GCW_DAC) | write RED moveb d4,d3 movel d3,a0@(GCW_CMAP) movel d1,a0@(GCW_DAC) | write GREEN moveb d5,d3 movel d3,a0@(GCW_CMAP) movel d2,a0@(GCW_DAC) | write BLUE tstw d7 dbeq d7,pcmap2_3 | loop clrl a0@(GCW_CMAP) clrl d0| moveb line_flag,d1 moveb #7,d1 | line_flag when ROM monitor active btst #2,d1 beq pcmap2_4 orw #0x100,d0 | overlay onpcmap2_4: notb d1 andb #3,d1 orb d1,d0 clrl d1| moveb init_flag1,d1 moveb #6,d1 | init_flag1 when ROM monitor active lsll #5,d1 | overlay colour ? orl d1,d0 movel d0,a0@(GCW_DAC) | set overlay colour & operating mode rts| Init 3| LAB_0389 at 0x001004b0c .eveninit3: moveml d0-d7/a0,sp@- movel line_selmask,d6 moveq #5,d7 clrl d0 clrl d5 moveq #-1,d1 movel d1,d2 movew #0xfb00,d1 movew #0xf602,d2 movel #0x04fe,d3 moveq #7,d4 lea GC_BASE,a0 | base of video control registersinit3_1: movel d0,a0@(GCW_INTEN) | intensity movel d6,a0@(GCW_PSEL) | plane select movel #0x0e,a0@(GCW_CMD) | command movel d1,a0@(GCW_LG2) | line draw movel d0,a0@(GCW_LG1) | line draw movel d2,a0@(GCW_LG2) | line draw movel d3,a0@(GCW_LG3) | line draw movel d4,a0@(GCW_LG4) | line draw movel d5,a0@(GCW_PY) | pixel Y addr movel d0,a0@(GCW_PX_SL) | pixel X addr, start line addql #1,d5 | incr Y addr cmpw d7,d5 bne init3_1 clrl d2 movel #0x03fc,d3 moveq #19,d0 moveq #27,d1 movel d6,a0@(GCW_PSEL) | plane select tstl a0@(524) | 0x20064c - CMD reg but inhibit cmdinit3_2: movel a0@(524),d4 btst #0x1e,d4 beq init3_2init3_3: movel a0@(524),d4 btst #0x1e,d4 bne init3_3 movel d0,a0@(GCW_CMD) | command movel d2,a0@(GCW_PY_SM) | pixel Y addr, start mem cycleinit3_4: movel d1,a0@(GCW_CMD) | command movel d3,a0@(GCW_PY_SM) | pixel Y addr, start mem cycle subql #4,d3 bpl init3_4 moveml sp@+,d0-d7/a0 rts| in-lined version of ldraw .even.globl c_ldraw4c_ldraw4: link a6,#0 moveml d0-d7/a0-a6,sp@- lea gr_data,a1 | point to data space movel a6@(8),d2 | x1 movel a6@(12),d3 | y1 movel a6@(16),d1 | x2 movel a6@(20),d0 | y2 moveb #0x03,line_flag | magic number ? moveq #1,d5 movel d5,a1@(40) | set x direction flag movel d5,a1@(44) | set y direction flag subl d2,d1 | (d1-d2)->d1, (x2 - x1) -> d1 movel d1,a1@(16) | delta-x subl d3,d0 | (y2 - y1) -> d0 movel d0,a1@(20) | delta-y cmpl d1,d0 | delta-y - delta-x bgt ldraw4_6 | bra if delta-y > delta-x movel d5,d0 | set d0 to 1 bra ldraw4_7ldraw4_6: clrl d0 | set d0 to 0ldraw4_7: movel d0,a1@(48) | set to 0 if delta-y > delta-x, else set to 1 beq ldraw4_8 | bra if delta-y > delta-x movel a1@(20),d5 | delta-y to d5 lsll #1,d5 | shift left (mul by 2) movel d5,d4 | copy to d4 subl a1@(16),d4 | (2 * dy) - dx -> d4 subl a1@(40),d4 | d4 - xdir -> d4 movel a1@(16),d6 | dx -> d6 movel a1@(20),d7 | dy -> d7 subl d6,d7 | dy - dx -> d7 lsll #1,d7 | shift left, d7 = ND/NA bra ldraw4_9ldraw4_8: movel a1@(16),d5 | dx lsll #1,d5 | shift left (mul by 2) movel d5,d4 subl a1@(20),d4 | (2 * dx) - dy subl a1@(44),d4 | ydir movel a1@(20),d6 | dy movel a1@(16),d7 | dx subl d6,d7 lsll #1,d7 | shift left, d7 = ND/NAldraw4_9:| by this point, d4 = ND/NA, d5 = NB subql #1,d6 | d6 = NC movel a1@(40),d0 | xdir lsll #1,d0 orl a1@(44),d0 | ydir lsll #1,d0 orl a1@(48),d0 | SX/SY lea GC_BASE,a0 | point to video control registers movel a6@(24),a0@(GCW_INTEN) | intensity movel a6@(28),a0@(GCW_PSEL) | plane select movel #0x0e,a0@(GCW_CMD) | write, 4x5, 1 of 20 tstl a1@(16) bne ldraw41 tstl a1@(20) bne ldraw41 movel d3,a0@(GCW_PY) | pixel Y addr movel d2,a0@(GCW_PX_SM) | pixel X addr, start single mem bra ldraw4_doneldraw41: movel d4,a0@(GCW_LG2) | line gen, ND15-ND0 movel d5,a0@(GCW_LG1) | line gen, NB15-NB0 movel d7,a0@(GCW_LG2) | line gen, ND15-ND0 movel d6,a0@(GCW_LG3) | line-gen, NC11-NC0 movel d0,a0@(GCW_LG4) | line-gen, SX, SY, XMAJ movel d3,a0@(GCW_PY) | pixel Y movel d2,a0@(GCW_PX_SL) | pixel X, start lineldraw4_done: moveml sp@+,d0-d7/a0-a6 unlk a6 rts| in-lined version of ldraw including y loop counter .even.globl c_ldraw4yc_ldraw4y: link a6,#0 moveml d0-d7/a0-a2,sp@- lea gr_data,a1 | point to data space movel a6@(8),d2 | x1 movel a6@(12),d3 | y1 movel a6@(20),a2 | y3ldraw4y_1: cmpl d3,a2 jge ldraw4y_2 jra ldraw4y_11ldraw4y_2: movel a6@(16),d1 | x2 movel a6@(12),d0 | y2 = y1 moveb #0x03,line_flag | magic number ? moveq #1,d5 movel d5,a1@(40) | set x direction flag movel d5,a1@(44) | set y direction flag subl d2,d1 | (d1-d2)->d1, (x2 - x1) -> d1 movel d1,a1@(16) | delta-x subl d3,d0 | (y2 - y1) -> d0 movel d0,a1@(20) | delta-y cmpl d1,d0 | delta-y - delta-x bgt ldraw4y_6 | bra if delta-y > delta-x movel d5,d0 | set d0 to 1 bra ldraw4y_7ldraw4y_6: clrl d0 | set d0 to 0ldraw4y_7: movel d0,a1@(48) | set to 0 if delta-y > delta-x, else set to 1 beq ldraw4y_8 | bra if delta-y > delta-x movel a1@(20),d5 | delta-y to d5 lsll #1,d5 | shift left (mul by 2) movel d5,d4 | copy to d4 subl a1@(16),d4 | (2 * dy) - dx -> d4 subl a1@(40),d4 | d4 - xdir -> d4 movel a1@(16),d6 | dx -> d6 movel a1@(20),d7 | dy -> d7 subl d6,d7 | dy - dx -> d7 lsll #1,d7 | shift left, d7 = ND/NA bra ldraw4y_9ldraw4y_8: movel a1@(16),d5 | dx lsll #1,d5 | shift left (mul by 2) movel d5,d4 subl a1@(20),d4 | (2 * dx) - dy subl a1@(44),d4 | ydir movel a1@(20),d6 | dy movel a1@(16),d7 | dx subl d6,d7 lsll #1,d7 | shift left, d7 = ND/NAldraw4y_9:| by this point, d4 = ND/NA, d5 = NB subql #1,d6 | d6 = NC movel a1@(40),d0 | xdir lsll #1,d0 orl a1@(44),d0 | ydir lsll #1,d0 orl a1@(48),d0 | SX/SY lea GC_BASE,a0 | point to video control registers movel a6@(24),a0@(GCW_INTEN) | intensity movel #0xff,a0@(GCW_PSEL) | plane select movel #0x0e,a0@(GCW_CMD) | write, 4x5, 1 of 20 tstl a1@(16) bne ldraw4y_10 tstl a1@(20) bne ldraw4y_10 movel d3,a0@(GCW_PY) | pixel Y addr movel d2,a0@(GCW_PX_SM) | pixel X addr, start single mem bra ldraw4y_doneldraw4y_10: movel d4,a0@(GCW_LG2) | line gen, ND15-ND0 movel d5,a0@(GCW_LG1) | line gen, NB15-NB0 movel d7,a0@(GCW_LG2) | line gen, ND15-ND0 movel d6,a0@(GCW_LG3) | line-gen, NC11-NC0 movel d0,a0@(GCW_LG4) | line-gen, SX, SY, XMAJ movel d3,a0@(GCW_PY) | pixel Y movel d2,a0@(GCW_PX_SL) | pixel X, start lineldraw4y_done: addql #1,d3 | y++ jra ldraw4y_1ldraw4y_11: moveml sp@+,d0-d7/a0-a2 unlk a6 rts| in-lined version of ldraw including y loop counter| this version optimised for horizontal lines .even.globl c_ldraw5yc_ldraw5y: link a6,#0 moveml d0-d7/a0-a2,sp@- lea gr_data,a1 | point to data space lea GC_BASE,a0 | base of video control registers movel a6@(24),a0@(GCW_INTEN) | intensity movel #0xff,a0@(GCW_PSEL) | plane select movel a6@(8),d2 | x1 movel a6@(12),d3 | y1 movel a6@(16),d1 | x2 movel a6@(20),a2 | y2 subl d2,d1 | (x2 - x1) -> d1 clrl d4 | d4 = (2 * dy) = NA clrl d5 | d5 = (2 * dy) = NB subl d1,d4 | (2 * dy) - dx -> d4 subql #1,d4 | d4 - SX -> d4 movel d1,d6 | dx -> d6 movel d5,d7 | dy -> d7 subl d6,d7 | dy - dx -> d7 lsll #1,d7 | shift left, d7 = ND| by this point, d4 = ND, d5 = NB subql #1,d6 | d6 = NC moveq #7,d0 | SX, SY, XMAJ| we are drawing a series of horizontal lines, all the same length| so no need to re-calculate all the magic numbers each timeldraw5y_1: cmpl d3,a2 | y1 <= y2 jge ldraw5y_2 jra ldraw5y_12ldraw5y_2: movel #0x0e,a0@(GCW_CMD) | write, 4x5, 1 of 20 tstl d1 | dx bne ldraw5y_10 movel d3,a0@(GCW_PY) | pixel Y addr movel d2,a0@(GCW_PX_SM) | pixel X addr, start single mem bra ldraw5y_11ldraw5y_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 lineldraw5y_11: addql #1,d3 | y++ jra ldraw5y_1ldraw5y_12: moveml sp@+,d0-d7/a0-a2 unlk a6 rts| in-lined version of ldraw including x loop counter| this version optimised for vertical lines .even.globl c_ldraw5xc_ldraw5x: link a6,#0 moveml d0-d7/a0-a2,sp@- lea gr_data,a1 | point to data space lea GC_BASE,a0 | base of video control registers movel a6@(24),a0@(GCW_INTEN) | intensity movel #0xff,a0@(GCW_PSEL) | plane select
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -