vdudriver 89.7 KB
Newer Older
Neil Turton's avatar
Neil Turton committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
; Copyright 1996 Acorn Computers Ltd
;
; Licensed under the Apache License, Version 2.0 (the "License");
; you may not use this file except in compliance with the License.
; You may obtain a copy of the License at
;
;     http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing, software
; distributed under the License is distributed on an "AS IS" BASIS,
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; See the License for the specific language governing permissions and
; limitations under the License.
;
; > $.Source.VduDriver
;
; ARTHUR OPERATING SYSTEM - Vdu Drivers
; =======================
;
; Vdu driver code - Vdu queue, mode, default windows etc.
;
; Author R C Manby
; Date   5.9.86
;
Neil Turton's avatar
Neil Turton committed
25

Neil Turton's avatar
Neil Turton committed
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
        GET s.vdu.VduGrafDec

        MACRO
        RMVT    $var, $BW
        [ "$BW"="B"
        =       (wk$var-wkstart)*2
        |
        [ "$BW"="W"
        =       (wk$var-wkstart)*2 +1
        |
        .... Invalid option on RMVT ....
        ]
        ]
        MEND

        MACRO
        RVVT    $var
        ASSERT  ($var >= 0) :LAND: ($var < &400) :LAND: (($var :AND: 3)=0)
        =       $var :SHR: 2
        MEND

        MACRO
        IssueService
        BL      Issue_Service
        MEND

        MACRO
        MALIGN  $length, $phase
        LCLA    temp
        LCLS    string
temp    SETA    .-ArthurVduDriver
        [ "$phase"=""
string  SETS    "ALIGN $length"
        |
string  SETS    "ALIGN $length, $phase"
        ]
        $string
temp    SETA    .-ArthurVduDriver-temp
        [ temp=0
        !       0, string :CC: " fitted exactly"
        |
        !       0, string :CC: " wasted " :CC: :STR: temp
        ]
        MEND


; Macro to load up video bandwidth and video memory size

        MACRO
        GetBandwidthAndSize  $bw, $size
Jeffrey Lee's avatar
Jeffrey Lee committed
76
        LDR     $size, =ZeroPage
77
        LDR     $size, [$size, #VideoSizeFlags]
78
        MOV     $bw, #100*1024*1024
79 80
        MOV     $size, $size, LSR #12
        MOV     $size, $size, LSL #12
81
        !       0, "Sort out GetBandwidthAndSize"
Neil Turton's avatar
Neil Turton committed
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
        MEND

; *****************************************************************************

; Vdu status bits

Vdu2ModeBitPosn *       0
Vdu2Mode        *       1 :SHL: Vdu2ModeBitPosn
Windowing       *       1 :SHL: 3
Shadowing       *       1 :SHL: 4

; *****************************************************************************

ArthurVduDriver

; *****************************************************************************
;
; VduInit - Once only initialisation of Vdu drivers eg after Break
; =======
;
VduInit ROUT
        Push    R14
Jeffrey Lee's avatar
Jeffrey Lee committed
104
        LDR     R0, =ZeroPage
105
        LDR     R14, [R0, #VideoPhysAddr]
Jeffrey Lee's avatar
Jeffrey Lee committed
106
        ASSERT (ZeroPage :AND: 255) = 0
Neil Turton's avatar
Neil Turton committed
107 108
        STRB    R0, [R0, #OsbyteVars + :INDEX: VDUqueueItems] ;purge queue
        STRB    R0, [WsPtr, #ScreenBlankFlag]   ; not blanked
Jeffrey Lee's avatar
Jeffrey Lee committed
109 110 111
      [ ZeroPage <> 0
        MOV     R0, #0
      ]
Neil Turton's avatar
Neil Turton committed
112 113 114
        STR     R0, [WsPtr, #CursorCounter]
        STR     R0, [WsPtr, #CursorDesiredState]
        STR     R0, [WsPtr, #VduStatus]
115 116 117 118 119
        STRB    R0, [WsPtr, #PointerShapeNumber]  ; make sure pointer off
        STR     R0, [WsPtr, #PointerShapeLA]      ; no shape passed to HAL yet
        STR     R0, [WsPtr, #CursorStack]         ; 0 bits => on
        STR     R0, [WsPtr, #VduSaveAreaPtr]      ; indicate no save area yet
        STR     R0, [WsPtr, #ClipBoxEnable]       ; no clip box calculating
Kevin Bracey's avatar
Kevin Bracey committed
120
        STRB    R0, [WsPtr, #ExternalFramestore]
Jeffrey Lee's avatar
Jeffrey Lee committed
121 122 123 124 125 126 127 128 129
        STR     R0, [WsPtr, #GraphicsVFeatures]
        MOV     R3, #MaxGraphicsVDrivers
        LDR     R2, =ZeroPage+VduDriverWorkSpace+GraphicsVDrivers
01
        STR     R0, [R2], #4
        SUBS    R3, R3, #1
        BNE     %BT01
        MOV     R0, #GraphicsVInvalid
        STR     R0, [WsPtr, #CurrentGraphicsVDriver]
130
        STR     R14, [WsPtr, #TrueVideoPhysAddr]  ; init TrueVideoPhysAddr for internal RAM/VRAM framestore case
Neil Turton's avatar
Neil Turton committed
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150

        LDR     R0, =RangeC+SpriteReason_SwitchOutputToSprite
        STR     R0, [WsPtr, #SpriteMaskSelect]

        MOV     R0, #InitialCursorFlags         ; TMD 25/9/86
        STR     R0, [WsPtr, #CursorFlags]

        ADRL    R0, NUL                 ; point to MOV PC,R14
        STR     R0, [WsPtr, #WrchNbit]  ; just in case ...

        ADRL    R0, ExportedHLine
        STR     R0, [WsPtr, #HLineAddr]
        ADD     R0, WsPtr, #FgEcfOraEor
        STR     R0, [WsPtr, #GcolOraEorAddr]

        MOV     R0, #maxmode
        STR     R0, [WsPtr, #MaxMode]   ; constant now


        LDROSB  R0, LastBREAK           ; is it a hard reset ?
151
        TEQ     R0, #SoftReset
Neil Turton's avatar
Neil Turton committed
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
        BEQ     %FT10                   ; [no, don't reset font]


; allocate buffer for Tim's whizzy text expansion.  This now lives
; in the system heap, unless the claim request fails.  If the request
; fails then the pointer points at the original buffer in the Vdu
; driver workspace.

; This allows the user to access depths upto 16 bit per pixel before
; strings things things become afoot at the Circle K.

        LDR     R3, =TextExpandArea_Size
        BL      ClaimSysHeapNode        ; allocate buffer for heap data
        ADDVS   R2, WsPtr, #TextExpand
        STR     R2, [WsPtr, #TextExpandArea]

        LDR     R3, =ModeSelector_MaxSize+4     ; get block for two overlapping copies
        BL      ClaimSysHeapNode                ; of mode selector, 1 word apart
        STR     R2, [WsPtr, #KernelModeSelector]


; now reset soft font from hard font

        MOV     R1, #1                  ; start at character 1*32
        STRB    R1, [WsPtr, #ScreenMemoryClaimed]
                                        ; can't claim memory till a mode change
        MOV     R2, #7                  ; copy 7 pages
        BL      DoResetFont

181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
;initialise the 6 pointer shape pointers and blocks
;(shape buffers are 6 * &100 starting at CursorData)
;
        ADD     r0, WsPtr, #PointerShapes
        LDR     r2, =CursorData
        MOV     r3, #6
        ADD     r4, WsPtr, #PointerShapeBlocks
02
        STR     r4, [r0]                 ; attach pointer to block
        STR     r2, [r4, #PointerBuffLA]
        Push    "r0-r2"
        MOV     r1, #0
        STRB    r1, [r4, #PointerWidth]  ; zero width
        STRB    r1, [r4, #PointerHeight] ; zero height (no shape)
        SUB     sp, sp, #3*4             ; room for one entry of OS_Memory page block
        MOV     r1, sp
        STR     r2, [r1, #4]             ; provide logical address
        MOV     r2, #1
        MOV     r0, #&2200               ; convert logical to physical address
        SWI     XOS_Memory
        LDR     r2, [r1, #8]             ; read physical address
        STR     r2, [r4, #PointerBuffPA]
        ADD     sp, sp, #3*4
        Pull    "r0-r2"
        ADD     r4, r4, #PointerBlkSize
        ADD     r2, r2, #&100
        ADD     r0, r0, #4
        SUBS    r3, r3, #1
        BNE     %BT02

; palette space (256 normal + 1 border + 3 pointer = 260), and allowing for Gamma Correction
;   this space is: blank palette, 260 words
;                  logical and physical copies of both flash states, 260*4 words
;                  3 lookup tables for r,g,b mapping, 3*256 bytes
;
216
        LDR     r3, =Pal_Blocksize
217 218
        BL      ClaimSysHeapNode           ; this had better succeed!

219
        ASSERT  :INDEX:Pal_Blank = 0
220
        STR     r2, [WsPtr, #BlankPalAddr]
221
        ADD     r3, r2, #Pal_LogFirst
222
        STR     r3, [WsPtr, #FirPalAddr]
223
        ADD     r3, r2, #Pal_LogSecond
Neil Turton's avatar
Neil Turton committed
224 225
        STR     r3, [WsPtr, #SecPalAddr]

226
; initialise blank palette to all solid black
227 228
; zero-init the other palettes too, to make sure log & phys palettes are
; consistent
Neil Turton's avatar
Neil Turton committed
229

230
        MOV     r3, #0
231
        LDR     r4, =PalEntries*5
232 233 234
04      STR     r3, [r2], #4
        SUBS    r4, r4, #1
        BNE     %BT04
Neil Turton's avatar
Neil Turton committed
235

236
        ASSERT  Pal_RTable = Pal_Blank + PalEntries*5*4
Neil Turton's avatar
Neil Turton committed
237 238 239 240 241

; initialise red, green and blue transfer function tables to 1-1 mapping

        MOV     r0, #0
05
242 243 244 245
        STRB    r0, [r2, #Pal_STable-Pal_RTable] ; store in supremacy table
        STRB    r0, [r2, #Pal_BTable-Pal_RTable] ; store in blue table
        STRB    r0, [r2, #Pal_GTable-Pal_RTable] ; store in green table
        STRB    r0, [r2], #1                     ; store in red table, and advance
Neil Turton's avatar
Neil Turton committed
246 247 248 249 250 251
        ADD     r0, r0, #1
        CMP     r0, #256
        BCC     %BT05
10
        BL      SpriteInit

Kevin Bracey's avatar
Kevin Bracey committed
252
        LDR     R14, [WsPtr, #ScreenEndAddr]
Neil Turton's avatar
Neil Turton committed
253
        LDR     R0, [WsPtr, #TotalScreenSize]
Kevin Bracey's avatar
Kevin Bracey committed
254
        RSB     R0, R0, R14
Neil Turton's avatar
Neil Turton committed
255
        STR     R0, [WsPtr, #DisplayStart]
Robert Sprowson's avatar
Robert Sprowson committed
256
        BL      SetDisplayScreenStart
Neil Turton's avatar
Neil Turton committed
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
        STR     R0, [WsPtr, #ScreenStart]
        STR     R0, [WsPtr, #CursorAddr]
        STR     R0, [WsPtr, #InputCursorAddr]

        Pull    PC

        LTORG

; *****************************************************************************
;
;       InitialiseMode - Select mode number given by ModeNo variable
;
;       Called by MOS once before initialisation, and then afterwards
;       before printing "RISC OS ..."
;
; in:   -
Jeffrey Lee's avatar
Jeffrey Lee committed
273 274
; out:  r0 = corrupt, or error pointer
;       All other registers preserved
Neil Turton's avatar
Neil Turton committed
275 276
;

Jeffrey Lee's avatar
Jeffrey Lee committed
277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293
InitialiseMode ROUT
; if we don't have a video driver yet, now is a good time to check if the HAL
; provides one
        LDR     r0, =ZeroPage+VduDriverWorkSpace+CurrentGraphicsVDriver
        LDR     r0, [r0]
        CMP     r0, #GraphicsVInvalid
        BEQ     VduGrafHAL_Init         ; tail-call since InitialiseMode will get called again when the HAL registers itself

        Entry   "r1-r12"

        ; Refresh cached features flags before we start calling this new driver
        MOV     r4, r0, LSL #24
        ORR     R4, R4, #GraphicsV_DisplayFeatures
        BL      CallGraphicsV
        VDWS    WsPtr
        STR     r0, [WsPtr, #GraphicsVFeatures]

Jeffrey Lee's avatar
Jeffrey Lee committed
294 295 296 297 298 299 300 301 302 303 304 305 306
        ; Update screen memory information
        ASSERT  GVDisplayFeature_SeparateFramestore < 256
        ANDS    r1, r0, #GVDisplayFeature_SeparateFramestore
        STRB    r1, [WsPtr, #ExternalFramestore]
        BNE     %FT20
        ; Screen DA is in use
        LDR     r0, =ZeroPage
        LDR     r0, [r0, #VideoPhysAddr]
        STR     r0, [WsPtr, #TrueVideoPhysAddr] ; Point TrueVideoPhysAddr at the base of screen DA
        MOV     r0, #2
        SWI     XOS_ReadDynamicArea
        MOVVS   r1, #0                  ; shouldn't happen, but set a safe size just in case
        STR     r1, [WsPtr, #TotalScreenSize] ; Ensure TotalScreenSize consistent with DA size
307 308 309 310 311 312
        ; Reinitialise a few more variables which are used by the screen DA handler
        ADD     r1, r0, r1
        STR     r1, [WsPtr, #ScreenEndAddr]
        STR     r0, [WsPtr, #DisplayStart]
        BL      SetDisplayScreenStart
        STR     r0, [WsPtr, #ScreenStart]
Jeffrey Lee's avatar
Jeffrey Lee committed
313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330
        B       %FT30
20
        ; Driver manages memory itself
        TST     r0, #GVDisplayFeature_VariableFramestore
        BNE     %FT30                   ; Framestore changes with mode, we can't read its info here
        ; Framestore is fixed, get its info and remember it (ModeChangeSub currently relies on this for VRAM limit checking)
        LDR     r0, =ZeroPage+VduDriverWorkSpace+CurrentGraphicsVDriver
        LDR     r0, [r0]
        MOV     r4, r0, LSL #24
        ORR     r4, r4, #GraphicsV_FramestoreAddress
        BL      CallGraphicsV
        CMP     r4, #0
        MOVNE   r1, #0                  ; If call wasn't claimed, claim 0 screen memory. Mode change will then fail with out of memory error, which is about the best we can do.
        STR     r0, [WsPtr, #TrueVideoPhysAddr]
        STR     r1, [WsPtr, #TotalScreenSize]

30

Neil Turton's avatar
Neil Turton committed
331 332
        MOV     r0, #1                  ; no need to check for soft reset,
        SWI     XOS_ReadSysInfo         ; always use configured value
333
        MOV     r1, r0
334

Neil Turton's avatar
Neil Turton committed
335 336
        MOV     r0, #ScreenModeReason_SelectMode
        SWI     XOS_ScreenMode
337
        BVC     %FT40
Neil Turton's avatar
Neil Turton committed
338 339 340 341 342 343

        MOV     r0, #114                ; failed, so get rid of any shadow
        MOV     r1, #1
        SWI     XOS_Byte
        SWI     XOS_WriteI+22
        SWIVC   XOS_WriteI+0            ; and if we can't get mode 0, we're really fooked!!!
344 345
40
        BLVC    UpdateAllPalette        ; make sure GV driver is aware of the pointer colours (this will also redundantly set the main palette + border colour, but re-using this routine as-is avoids duplicating a bunch of code)
Neil Turton's avatar
Neil Turton committed
346 347
        EXIT

348
;
Neil Turton's avatar
Neil Turton committed
349 350 351 352 353 354 355 356 357 358 359 360
;
;------------------------------------------------------------------------------
;
; Vdu -  Main VDU driver entry point
; ===    Queue up bytes and dispatch via JVec
;
; in:   R0 = character to be printed
;
; out:  C=1 <=> send character to printer if enabled
;

Vdu     ROUT
Jeffrey Lee's avatar
Jeffrey Lee committed
361
        LDR     R11, =ZeroPage          ; NB used later in Vdu07 as well
Neil Turton's avatar
Neil Turton committed
362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382
        LDRB    R10, [R11, #OsbyteVars + :INDEX: VDUqueueItems]
        MOVS    R9, R10, LSL #24        ; move up to top byte (for sign extend)
        BEQ     Vdu07                   ; not queueing, then start Vdu sequence

; *****Comment made by DJS: Changing this to fall through if not queueing
; and branch if queueing might be a good idea - it would speed up all
; printable characters and simple cursor movements.

        LDR     R8, [WsPtr, #QOffset]
        STRB    R0, [R8, R9, ASR #24]   ; add byte to queue

        ADD     R10, R10, #1            ; move on pointer
        STRB    R10, [R11, #OsbyteVars + :INDEX: VDUqueueItems]

        CMP     R10, #&100              ; finished sequence ?
        MOVCC   PC, R14                 ; no, then return (no printing)

        Push    "R0, R14"
        BL      PreWrchCursor           ; exits with R6 = CursorFlags
        Pull    "R0"
05
Kevin Bracey's avatar
Kevin Bracey committed
383
        ADR     R14, VduPrintExit
Neil Turton's avatar
Neil Turton committed
384 385 386 387
        Push    R14
        BL      Vdu05
        BL      PostWrchCursor
        CLC                             ; also clears V
Jeffrey Lee's avatar
Jeffrey Lee committed
388 389
        ADD     SP,SP,#4
        Pull    PC
Neil Turton's avatar
Neil Turton committed
390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454

VduPrintExit                             ; exit used if print required
        BL      PostWrchCursor
        SEC                             ; also clears V
        Pull    PC

; *****************************************************************************

Vdu05   ROUT
        TST     R6, #VduDisabled        ; VDU enabled ?
        LDREQ   PC, [WsPtr, #JVec]      ; yes, then do it (no printing)

; Queue sequence has just completed, but VDU is disabled
; Only interesting case is VDU 1 (SOH), which must still print
; the character if the printer is enabled

        LDR     R10, [WsPtr, #JVec]
        ADR     R11, SOH
        TEQ     R10, R11                ; JVec -> SOH ?
        MOVNE   PC, R14                 ; no, then return (no printing)
SOH
        LDR     R1, [WsPtr, #VduStatus]  ; in VDU 2 mode ?
        TST     R1, #Vdu2Mode
        MOVEQ   PC, R14                 ; no, then return

        Push    R14
        BL      MOSDoPrint
        Pull    PC, VC                  ; good exit, so return

        Pull    R14                     ; bad exit, return with error
        B       VduBadExit

; *****************************************************************************

Vdu07   ROUT
        AND     R0, R0, #&FF            ; Only look at bottom byte!

        CMP     R0,#127                 ;If DELETE, change R0 to 32 and
        MOVEQ   R0,#32                  ;  drop through to control char code
        CMPNE   R0,#31                  ;Otherwise, branch to printable char
        BHI     Vdu20                   ;  code if not a control char

; *****Further desirable change: Make printable characters fall through,
; control characters take the branch - speeding up printable characters is
; important!

        ADR     R10, VduJTb             ; Address of beginning of jump table
        LDR     R9, [R10, R0, LSL #2]   ; Get routine address from VduJTB
        STR     R9, [WsPtr, #JVec]      ; save address

        ADD     R10, R10, #(VduQTb-VduJTb)

        LDRB    R9, [R10, R0]           ; Pick up QQ + length of queue
        RSBS    R10, R9, #QQ            ; -(length of queue) & test if none

        STRNEB  R10, [R11, #OsbyteVars + :INDEX: VDUqueueItems]
                                        ; yes, then set up Osbyte variable
        ADDNE   R9, R9, WsPtr
        STRNE   R9, [WsPtr, #QOffset]   ; and QOffset
        MOVNE   PC, R14

        Push    "R0,R14"
        BL      PreWrchCursor           ; exits with R6 = CursorFlags
        Pull    "R0"
10
Jeffrey Lee's avatar
Jeffrey Lee committed
455
        ADR     R14, VduPrintExit
Neil Turton's avatar
Neil Turton committed
456 457 458 459
        Push    R14
        BL      Vdu10
        BL      PostWrchCursor
        CLC                             ; also clears V
Jeffrey Lee's avatar
Jeffrey Lee committed
460 461
        ADD     SP, SP, #4
        Pull    PC
Neil Turton's avatar
Neil Turton committed
462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515

;
; This is the only byte of a single byte Vdu sequence
;
;       R6 = CursorFlags
;       R11 = 0 (used to index VDUqueueItems)
;

Vdu10   ROUT
        TST     R6, #CursorsSplit       ; are we cursor editing ?
        BNE     Vdu15
Vdu10Continue

; TMD 31/7/87; bug fixed here - chars 8 to 13 should still go to printer if
; enabled, even if VDU is disabled

        CMP     R0, #8                  ; is char in range 8-13 ?
        RSBCSS  R1, R0, #13             ; if so then we want to print it
        LDRCS   R1, [WsPtr, #VduStatus]
        MOVCSS  R1, R1, LSR #(Vdu2ModeBitPosn +1) ; providing printer enabled
        Pull    R14, CS                 ; so pull old R14

        TST     R6, #VduDisabled        ; are we disabled
        LDREQ   PC, [WsPtr, #JVec]      ; enabled, so go get em floyd !

        TEQ     R0, #6                  ; disabled, so is it ACK (enable VDU)
        BICEQ   R6, R6, #VduDisabled
        STREQ   R6, [WsPtr, #CursorFlags]

NUL ;Does nothing
ESC ;Does nothing
        MOV     PC, R14                 ; return anyway

; *****************************************************************************

Vdu15
        TEQ     R0, #13                 ; and is it a carriage return ?
        BNE     Vdu10Continue

        Push    "R0, R14"
        BIC     R6, R6, #CursorsSplit   ; then stop cursor editing
        STR     R6, [WsPtr, #CursorFlags]
        MOV     R1, #1                  ; restore old Reg10Copy
        BL      CursorOnOff
        Pull    "R0, R14"
        B       Vdu10Continue

; *****************************************************************************

Vdu20   ROUT
        Push    "R0,R14"
        BL      PreWrchCursor           ; exits with R6 = CursorFlags
        Pull    "R0"
05
Jeffrey Lee's avatar
Jeffrey Lee committed
516
        ADR     R14, VduPrintExit
Neil Turton's avatar
Neil Turton committed
517 518 519 520
        Push    R14
        BL      TimWrch
        BL      PostWrchCursor
        CLC                             ; also clears V
Jeffrey Lee's avatar
Jeffrey Lee committed
521 522
        ADD     SP, SP, #4
        Pull    PC
Neil Turton's avatar
Neil Turton committed
523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589

; *****************************************************************************

VduJTb                  ; Table of addresses
 & NUL                          ; Does nothing
 & SOH                          ; Next char to printer only
 & STX                          ; Enable printer
 & ETX                          ; Disable printer
 & EOT                          ; Write text at text cursor
 & ENQ                          ; Write text at graphics cursor
 & NUL                          ; Enable VDU drivers
 & BEL                          ; Beep
 & BS                           ; Cursor left
 & HT                           ; Cursor right
 & VduLF                        ; Cursor down
 & VT                           ; Cursor up
 & FF                           ; Clear text area (CLS)
 & VduCR                        ; Carriage return
 & SO                           ; Page mode on
 & SI                           ; Page mode off
 & DLE                          ; Clear graphics area (CLG)
 & DC1                          ; Define text colour (COLOUR)
 & DC2                          ; Define graphics colour and action (GCOL)
 & DC3                          ; Define logical colour
 & VDU20                        ; Restore default logical colours
 & NAK                          ; Disable VDU drivers
 & SYN                          ; Select screen mode (MODE)
 & ETB                          ; Reprogram display character (VDU23,...)
 & CAN                          ; Define graphics window
 & EM                           ; (PLOT k,x,x,y,y)
 & DefaultWindows               ; Restore default windows
 & ESC                          ; Does nothing
 & FS                           ; Define text window
 & GS                           ; Define graphics origin
 & RS                           ; Home cursor to "top left"
 & US                           ; Move text cursor (TAB x,y)
 & Delete                       ; Delete character (127)

        ASSERT  QQ+9 < 256

VduQTb          ; QQ + length of queue for each of the above
        DCB     QQ+0, QQ+1, QQ+0, QQ+0, QQ+0, QQ+0, QQ+0, QQ+0
        DCB     QQ+0, QQ+0, QQ+0, QQ+0, QQ+0, QQ+0, QQ+0, QQ+0
        DCB     QQ+0, QQ+1, QQ+2, QQ+5, QQ+0, QQ+0, QQ+1, QQ+9
        DCB     QQ+8, QQ+5, QQ+0, QQ+0, QQ+4, QQ+4, QQ+0, QQ+2
        DCB     QQ+0 ; (delete)
        ALIGN

; *****************************************************************************

WrchNbitTab
        &       Wrch1bit-WrchNbitTab
        &       Wrch2bit-WrchNbitTab
        &       Wrch4bit-WrchNbitTab
        &       Wrch8bit-WrchNbitTab
        &       Wrch16bit-WrchNbitTab
        &       Wrch32bit-WrchNbitTab
WrchNbitDoubleTab
        &       Wrch1bitDouble-WrchNbitDoubleTab

CursorNbitTab
        &       Cursor1bit-CursorNbitTab
        &       Cursor2bit-CursorNbitTab
        &       Cursor4bit-CursorNbitTab
        &       Cursor8bit-CursorNbitTab
        &       Cursor16bit-CursorNbitTab
        &       Cursor32bit-CursorNbitTab
590
        &       Cursor64bit-CursorNbitTab
Neil Turton's avatar
Neil Turton committed
591

592

Neil Turton's avatar
Neil Turton committed
593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613
; *****************************************************************************
;
;       SYN - Perform MODE change
;
;       External routine
;
; in:   Vdu queue contains mode number
;

SYN     ROUT                            ; Select screen mode (MODE)
        Push    lr
        LDRB    R2, [WsPtr, #QQ]        ; Read mode number from queue
        BL      ModeChangeSub
        Pull    lr
        MOVVC   pc, lr                  ; if no error, exit to Vdu
                                        ; (which calls PostWrchCursor)
; else drop thru into ...

VduBadExit                              ; jumped to if an error in VDU code
        Push    R0                      ; save error pointer
        BL      PostWrchCursor
Jeffrey Lee's avatar
Jeffrey Lee committed
614
        LDR     R0, [R13], #8           ; get error pointer, junk next entry
Neil Turton's avatar
Neil Turton committed
615
        SETV
Jeffrey Lee's avatar
Jeffrey Lee committed
616
        Pull    PC
Neil Turton's avatar
Neil Turton committed
617

618
; in: R2 = mode number / selector block
Neil Turton's avatar
Neil Turton committed
619
ModeChangeSub ROUT
620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637
        ; Wrap the bulk of ModeChangeSub in some code that will free any new
        ; TTX workspace pointer if the mode change fails (or the pointer isn't
        ; claimed for any other reason)
        Entry
        MOV     r0, #0
        STR     r0, [WsPtr, #TTXNewWorkspace]
        BL      %FT01
        LDR     r2, [WsPtr, #TTXNewWorkspace]
        TEQ     r2, #0
        EXIT    EQ
        MRS     r3, CPSR
        MOV     r4, r0
        BL      FreeSysHeapNode
        MSR     CPSR_c, r3
        MOV     r0, r4
        EXIT

01
Neil Turton's avatar
Neil Turton committed
638
        Push    lr
639

Neil Turton's avatar
Neil Turton committed
640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668
        MOV     R1, #Service_PreModeChange
        IssueService
        TEQ     R1, #0                  ; was service claimed ?
        BNE     %FT03                   ; no, so continue
        CMP     R0, #0                  ; service claimed; generate error ?
        Pull    PC, EQ                  ; no, just exit (V=0 from CMP)
        B       %FT07                   ; yes, then generate error
03
        MOV     R0, R2                  ; put mode (possibly changed) in R0
        MOV     R2, R0, LSR #7          ; R2 = 0/1 if bit 7 of mode clear/set
        CMP     r2, #2                  ; if mode number >= 256 then mode selector
        MOVCS   r2, #0                  ; so no shadow
        LDROSB  R1, Shadow
        TEQ     R1, #0                  ; if shadow 0 then force shadow mode
        MOVEQ   R2, #1

        BL      FindOKMode              ; out: R1 = mode we are going to use
        BVS     %FT07

        TEQ     R0, R1                  ; if substitute mode
        MOVNE   R2, #0                  ; then don't use shadow

        CMP     r1, #&100
        BICCC   r10, r1, #&80
        MOVCS   r10, r1
        MOV     R11, R10
        BL      PushModeInfo
        BVS     %FT07                   ; [probably duff mode selector]

669 670 671 672 673 674 675
        ; Allocate new teletext workspace if required
        LDR     R0, [R13, #wkModeFlags]
        TST     R0, #ModeFlag_Teletext
        MOVNE   R0, R13
        BLNE    TeletextAlloc
        BVS     %FT07

Neil Turton's avatar
Neil Turton committed
676
        Push    R1                      ; save proper mode
Jeffrey Lee's avatar
Jeffrey Lee committed
677

678 679 680 681 682 683 684 685
        ; Vet the mode - both to make sure the driver really is happy with it,
        ; and to cope with drivers which want to switch to different framebuffer
        ; types
        ADD     R0, R13, #wkwordsize+4
        Push    "R2"
        BL      DoFullVetMode
        Pull    "R2"
        SUB     R13, R13, #12
686
        BEQ     %FT041                  ; not supported, complain
687
        TST     R0, #GVVetMode2_ExtraBytes_Invalid
688
        BNE     %FT041                  ; Service_ModeExtension should have made sure ExtraBytes was valid
689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704
        ; R0, R3, R5 may contain important info
        STMIA   R13, {R0, R3, R5}
        AND     R0, R0, #GVVetMode2_ResultMask
        CMP     R0, #GVVetMode2_Result_UnkFramestore
        BEQ     %FT08                   ; Driver doesn't know where mode is going to be, so we can't vet the memory requirement

        LDR     R11, [R13, #16 + wkScreenSize] ; get screen size for this mode
        MOV     R11, R11, LSL R2        ; total amount needed

        CMP     R0, #GVVetMode2_Result_SysFramestore
        BNE     %FT045

        MOV     R0, #2
        SWI     XOS_ReadDynamicArea
        SUBS    R1, R11, R1
        BLE     %FT08
Kevin Bracey's avatar
Kevin Bracey committed
705

Neil Turton's avatar
Neil Turton committed
706 707
; try to extend the amount of screen memory

708 709
        ! 0, "Need to fix ModeChangeSub to not leave CursorAddr, etc. pointing to unmapped pages during DA resize. Causes bad stuff should an abort occur/screen output be attempted!" ; Note that even enlarging the DA can leave the pointers in a bad state, due to the way the screen DA handler shuffles down/unmaps the lower mapping of VRAM before the higher copy is enlarged

Neil Turton's avatar
Neil Turton committed
710 711 712
        MOV     R0, #2                  ; expand screen memory
        SWI     XOS_ChangeDynamicArea
        BVC     %FT08
Kevin Bracey's avatar
Kevin Bracey committed
713
06
Neil Turton's avatar
Neil Turton committed
714
        ADR     R0, ErrorBlock_BadMODE
715 716
065
        ADD     R13, R13, #PushedInfoSize + 4*4 ; junk stacked info + mode no + vetmode2 info
Neil Turton's avatar
Neil Turton committed
717 718 719 720 721 722 723
      [ International
        BL      TranslateError
      ]
07
        SETV                            ; indicate error
        Pull    PC

724 725 726 727
041
        ADRL    R0, ErrorBlock_ModeNotAvailable
        B       %BT065

728 729 730 731
045
        CMP     R11, R5
        BHI     %BT06                   ; ext. framestore not big enough

Neil Turton's avatar
Neil Turton committed
732 733 734
; valid mode and enough memory

08
735
        LDR     r0, [sp, #12]          ; restore mode we are using
Neil Turton's avatar
Neil Turton committed
736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784
        CMP     r0, #&100               ; if not mode selector
        BICCC   r0, r0, #&80            ; then knock off shadow bit
        BCC     %FT12

; it's a mode selector, so copy it to our static mode selector block

        LDR     r1, [WsPtr, #KernelModeSelector] ; point at block

        SUBS    r3, r0, r1              ; if r0 -> 1st mode block position
        TEQNE   r3, #4                  ; or r0 -> 2nd mode block position
        MOVEQ   r1, r0                  ; then use it in place
        BEQ     %FT09

        LDR     r3, [WsPtr, #DisplayModeNo] ; else check if current mode is a mode selector
        SUB     r3, r3, r1              ; r3 = offset from start of block
        CMP     r3, #8                  ; if 0 or 4
        EORCC   r3, r3, #4              ; then make 4 or 0 (ie toggle between them)
        ADDCC   r1, r1, r3              ; and add on base

        ASSERT  (ModeSelector_ModeVars+4) :AND: 7 = 0
09
        MOV     r3, #0
10
        LDR     r6, [r0, r3]            ; copy 1st word - after fixed bit this will be previous var value
        STR     r6, [r1, r3]
        ADD     r3, r3, #4
        LDR     r6, [r0, r3]            ; copy 2nd word - after fixed bit this will be next var index
        STR     r6, [r1, r3]
        ADD     r3, r3, #4
        CMP     r3, #ModeSelector_ModeVars + 4  ; only exit if we've done the essential bit
        CMPCS   r6, #-1                 ; AND we've had a -1 as the var index (NOT as the value)
        CMPCC   r3, #ModeSelector_MaxSize ; OR we've gone off the end of our block
        BCC     %BT10                   ; [we haven't, so loop]

        CMP     r3, #ModeSelector_MaxSize       ; if we did go off the end
        MOVCS   r6, #-1
        STRCS   r6, [r1, #ModeSelector_MaxSize-4] ; then terminate it properly

        MOV     r0, r1                  ; point at static block
12
        STR     R0, [WsPtr, #DisplayModeNo] ; store the new display mode

; now issue Service_ModeChanging

        MOV     R1, #Service_ModeChanging
        BL      IssueModeService

; R13 -> mode variables

785
13      LDR     R3, [R13, #16+wkScreenSize]
Neil Turton's avatar
Neil Turton committed
786 787 788
        STR     R3, [WsPtr, #ScreenSize] ; store screensize BEFORE calling
                                        ; ConvertBankToAddress (was a bug!)

789
        Push    "r0-r6"
790 791

; If driver handles memory allocation, must change mode before asking for memory
792 793 794 795 796 797 798 799 800 801 802 803 804
; (the case where we change mode after setting up the memory is only retained for backwards-compatibility, just in case something special like Aemulor is relying on it)

        LDR     r0, [sp, #7*4]
        AND     r0, r0, #GVVetMode2_ResultMask
        CMP     r0, #GVVetMode2_Result_SysFramestore
        BEQ     %FT581
        CMP     r0, #GVVetMode2_Result_ExtFramestore
        LDREQ   r0, [sp, #8*4]
        LDREQ   r1, [sp, #9*4]
        BEQ     %FT580
        ; Must be UnkFramestore
        ADD     R0, R13, #wkwordsize+7*4+16     ; R0 -> VIDCList3
        BL      HardwareModeChange
Jeffrey Lee's avatar
Jeffrey Lee committed
805 806 807
        LDR     r4, [WsPtr, #CurrentGraphicsVDriver]
        MOV     r4, r4, LSL #24
        ORR     r4, r4, #GraphicsV_FramestoreAddress
Kevin Bracey's avatar
Kevin Bracey committed
808
        BL      CallGraphicsV
809

810
580
811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826
; for mapping in, round start address down and size up to megabyte boundaries
; r0 = physical start, r1= size
; so frame buffer is wholly contained within the mapped in area
        MOV     r3, #1<<20                      ; 1 Megabyte
        SUB     r3, r3, #1                      ; convert to mask
        MOV     r4, r1                          ; remember what was asked for
        AND     r5, r0, r3                      ; and offset from megabyte base
        TST     r1, r3                          ; non integer megabyte?
        BIC     r2, r1, r3                      ; (clear the bits)
        ADDNE   r2, r2, #1<<20                  ; yes.. up to next megabyte
        BIC     r1, r0, r3                      ; ensure megabyte boundary at start
        MOV     r0, #13                         ; map in permanently
        ORR     r0, r0, #1:SHL:8                ; buffered, uncached
        ORR     r0, r0, #1:SHL:16+1:SHL:17      ; doubly map, access permission specified
        SWI     XOS_Memory
        BVS     %FT581
827 828
        ADD     r0, r1, r5                      ; reconstruct base phys address
        STR     r0, [WsPtr, #TrueVideoPhysAddr] ; and update our copy
829 830 831 832 833 834
        STR     r4, [WsPtr, #TotalScreenSize]   ; what we asked for
        ADD     r3, r3, r4                      ; compute end
        ADD     r3, r3, r5                      ; and allow offset dfrom start
        STR     r3, [WsPtr, #ScreenEndAddr]     ; actual screen end
        MOV     r14, #1
        B       %FT582
835

Kevin Bracey's avatar
Kevin Bracey committed
836
581
837 838 839 840
        LDR     r0, =ZeroPage
        LDR     r0, [r0, #VideoPhysAddr]
        STR     r0, [WsPtr, #TrueVideoPhysAddr] ; Point TrueVideoPhysAddr at the base of screen DA
        MOV     r0, #2
Kevin Bracey's avatar
Kevin Bracey committed
841 842 843 844 845 846
        SWI     XOS_ReadDynamicArea
        STRVC   r1, [WsPtr, #TotalScreenSize]
        ADDVC   r0, r0, r1
        STRVC   r0, [WsPtr, #ScreenEndAddr]
        MOV     r14, #0
582
847
        Pull    "r0-r6"
Kevin Bracey's avatar
Kevin Bracey committed
848 849
        STRB    r14, [WsPtr, #ExternalFramestore]

Neil Turton's avatar
Neil Turton committed
850 851 852 853 854 855 856 857 858 859 860 861 862
        TEQ     R2, #0                  ; Shadowing or not ?
        LDR     R3, [WsPtr, #VduStatus]
        BICEQ   R3, R3, #Shadowing
        ORRNE   R3, R3, #Shadowing
        STR     R3, [WsPtr, #VduStatus]

        STRB    R2, [WsPtr, #ScreenMemoryClaimed] ; only allow ADFS to claim
                                        ; if non-shadow (simplifies things!)

        BL      ConvertBankToAddress    ; R3 := default start for this bank
        STR     R3, [WsPtr, #DriverBankAddr]
        STR     R3, [WsPtr, #DisplayBankAddr]

Jeffrey Lee's avatar
Jeffrey Lee committed
863 864
        LDR     R6, =ZeroPage
        ASSERT  (ZeroPage :AND: 255) = 0
Neil Turton's avatar
Neil Turton committed
865 866 867
        STRB    R6, [R6, #OsbyteVars + :INDEX:MemDriver]  ; indicate default
        STRB    R6, [R6, #OsbyteVars + :INDEX:MemDisplay] ; for both of these

868
        LDR     R6, [R13, #16+wkModeFlags]
Neil Turton's avatar
Neil Turton committed
869 870
        STR     R6, [WsPtr, #DisplayModeFlags]

871 872
; initialise any values which SwitchOutput refers to

873
        LDR     R4, [R13, #16+wkLineLength]
874 875
        STR     R4, [WsPtr, #DisplayLineLength]

Neil Turton's avatar
Neil Turton committed
876 877 878
; now set up other mode variables by calling SwitchOutput

        ADD     R3, WsPtr, #VduSaveArea+InitFlag
879 880
        MOV     R2, #0
        STR     R2, [R3]                ; indicate uninitialised
881
        TST     R6, #ModeFlag_Teletext
Neil Turton's avatar
Neil Turton committed
882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909
        MOVNE   R3, #0                  ; if teletext, then no save area
        MOVEQ   R3, #1                  ; else MOS's save area
        MOV     R1, #0                  ; just in case
        MOV     R0, #SpriteReason_SwitchOutputToSprite
        SWI     XOS_SpriteOp

; now create other variables from simple ones

        LDR     R3, [WsPtr, #NColour]
        STR     R3, [WsPtr, #DisplayNColour]

        ASSERT  YWindLimit = XWindLimit +4
        ASSERT  DisplayYWindLimit = DisplayXWindLimit +4
        ADD     R0, WsPtr, #XWindLimit
        LDMIA   R0, {R3, R4}
        ADD     R0, WsPtr, #DisplayXWindLimit
        STMIA   R0, {R3, R4}

        ASSERT  YEigFactor = XEigFactor +4
        ASSERT  DisplayYEigFactor = DisplayXEigFactor +4
        ADD     R0, WsPtr, #XEigFactor
        LDMIA   R0, {R3, R4}
        ADD     R0, WsPtr, #DisplayXEigFactor
        STMIA   R0, {R3, R4}

        ASSERT  Log2BPP = Log2BPC +4
        ADD     R0, WsPtr, #Log2BPC
        LDMIA   R0, {R0, R1}                    ; R0 = Log2BPC; R1 = Log2BPP
910
        STRB    R1, [WsPtr, #DisplayLog2BPP]
Neil Turton's avatar
Neil Turton committed
911 912
        SUB     R3, R3, R0                      ; adjust XEig for double pixels
        ADD     R3, R3, R1
913
        STRB    R3, [WsPtr, #PointerXEigFactor]
Neil Turton's avatar
Neil Turton committed
914

915
        LDR     R3, [R13, #16+wkModeFlags]
916 917
        STR     R3, [WsPtr, #ModeFlags]

Neil Turton's avatar
Neil Turton committed
918 919
; finished doing other variables

920
; tell hardware to change mode, unless already done
921 922 923 924 925
        LDR     r0, [r13], #16
        AND     r0, r0, #GVVetMode2_ResultMask
        CMP     r0, #GVVetMode2_Result_UnkFramestore
        ADDNE   R0, R13, #wkwordsize            ; R0 -> VIDCList3
        BLNE    HardwareModeChange
926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973

        ADD     R13, R13, #PushedInfoSize       ; junk stacked data

        ; for backward compatibility, show that video DMA is enabled in
        ; MEMC soft copy (DON'T call OS_UpdateMEMC, which would also
        ; make redundant call to HAL)
        ;
        SavePSR R2
        LDR     R0, =ZeroPage
        WritePSRc SVC_mode+I_bit+F_bit, R14
        LDR     R1, [R0, #MEMC_CR_SoftCopy]
        ORR     R1, R1, #(1 :SHL: 10)
        STR     R1, [R0, #MEMC_CR_SoftCopy]
        RestPSR R2

        BL      SetVendDefault

        LDR     R1, [WsPtr, #ScreenEndAddr]     ; need to reload cos corrupt
        LDR     R2, [WsPtr, #TotalScreenSize]
        SUB     R0, R1, R2                      ; R0 = Vstart
        BL      SetVstart
        MOV     R0, #0
        STRB    R0, [WsPtr, #PointerShapeNumber]
        STR     R0, [WsPtr, #TeletextOffset]
        STR     R0, [WsPtr, #CursorStack]       ; restore cursor on a mode

        BL      PalInit                 ; set default palette
        BL      UnblankScreen
        BL      SetMouseRectangle
        BL      FF

        MOV     R1, #Service_ModeChange
        BL      IssueModeService

        CLRV                            ; indicate no error
        Pull    PC                      ; return to caller

; *****************************************************************************
;
;       HardwareModeChange - Tell the video driver to change the mode
;
; in:   R0 = VIDC list
;
; out:  All regs preserved
;

HardwareModeChange
        Push    "R0-R4, LR"
974

Ben Avison's avatar
Ben Avison committed
975
;remember pixel rate (kHz) and border settings from VIDCList3
976 977 978
;
        LDR     R2, [R0, #VIDCList3_PixelRate]
        STR     R2, [WsPtr, #PixelRate]
Ben Avison's avatar
Ben Avison committed
979 980 981 982 983 984 985 986
        LDR     R2, [R0, #VIDCList3_HorizLeftBorder]
        STR     R2, [WsPtr, #BorderL]
        LDR     R2, [R0, #VIDCList3_VertiBottomBorder]
        STR     R2, [WsPtr, #BorderB]
        LDR     R2, [R0, #VIDCList3_HorizRightBorder]
        STR     R2, [WsPtr, #BorderR]
        LDR     R2, [R0, #VIDCList3_VertiTopBorder]
        STR     R2, [WsPtr, #BorderT]
987 988 989 990 991 992 993 994 995 996 997 998 999 1000

;remember DPMSState (if specified) from VIDCList3
;
        MOV     R2, #0                      ; DPMSState = 0 if not specified in list
        ADD     R1, R0, #VIDCList3_ControlList
20      LDR     R3, [R1], #8                ; loop over the control parameter list
        CMP     R3, #-1
        BEQ     %FT30                       ; didn't find the DPMSState entry
        TEQ     R3, #ControlList_DPMSState
        BNE     %BT20                       ; next control parameter
        LDR     R2, [R1, #-4]               ; read DPMSState value
        AND     R2, R2, #3                  ; only bits 0,1 valid
30
        STRB    R2, [WsPtr, #ScreenBlankDPMSState]
Neil Turton's avatar
Neil Turton committed
1001

1002
;kernel/HAL split - call the HAL to program video controller for mode,
Neil Turton's avatar
Neil Turton committed
1003
;
Jeffrey Lee's avatar
Jeffrey Lee committed
1004 1005 1006 1007 1008 1009 1010 1011
        LDR     R4, [WsPtr, #CurrentGraphicsVDriver]
        MOV     R4, R4, LSL #24
        ORR     R4, R4, #GraphicsV_SetMode
        BL      CallGraphicsV

        LDR     R4, [WsPtr, #CurrentGraphicsVDriver]
        MOV     R4, R4, LSL #24
        ORR     R4, R4, #GraphicsV_DisplayFeatures
Kevin Bracey's avatar
Kevin Bracey committed
1012
        BL      CallGraphicsV
Jeffrey Lee's avatar
Jeffrey Lee committed
1013
        STR     R0, [WsPtr, #GraphicsVFeatures] ; refresh cached features just in case something's happened to change them
1014
        BL      UpdateFalseVsync
Neil Turton's avatar
Neil Turton committed
1015

1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041
; claim/release memory needed for software pointer
        TST     R0, #GVDisplayFeature_HardwarePointer
        LDR     R2, [WsPtr, #SWP_Under]
        BEQ     %FT40
        TEQ     R2, #0
        MOVNE   R0, #0
        STRNE   R0, [WsPtr, #SWP_Under]
        MOVNE   R0, #ModHandReason_Free
        SWINE   XOS_Module
        B       %FT50

40
        TEQ     R2, #0
        BNE     %FT50
        ; Claim maximum amount needed
        MOV     R0, #ModHandReason_Claim
        MOV     R3, #32*32*4
        SWI     XOS_Module
        STRVC   R2, [WsPtr, #SWP_Under]
50
        ; Release mutex and reset state
        ; Note that we do this even if the pointer isn't needed, to ensure we
        ; don't get confused about its state
        MOV     R2, #0
        STR     R2, [WsPtr, #SWP_Pos]
        STRB    R2, [WsPtr, #SWP_Mutex]
1042
        Pull    "R0-R4, PC"
Neil Turton's avatar
Neil Turton committed
1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066

        MakeErrorBlock BadMODE

        LTORG

; The following symbols, apart from being used in NColourTable,
; are also used in constructing mode selectors for mode numbers in VduModes

NColour_0       *       1
NColour_1       *       3
NColour_2       *       15
NColour_3       *       63
NColour_4       *       &FFFF
NColour_5       *       &FFFFFFFF

; *****************************************************************************
;
;       IssueModeService - Issue service (either ModeChanging or ModeChange)
;
; in:   R1 = service code
;
; out:  R1 corrupted
;

1067
IssueModeService Entry "r2,r3"
Neil Turton's avatar
Neil Turton committed
1068 1069 1070
        BL      ReadMonitorType
        LDR     r2, [WsPtr, #DisplayModeNo]
        IssueService
Kevin Bracey's avatar
Kevin Bracey committed
1071
        EXIT
Neil Turton's avatar
Neil Turton committed
1072 1073 1074

; *****************************************************************************
;
1075
;       PushModeInfo - Push appropriate mode table and video controller params
Neil Turton's avatar
Neil Turton committed
1076 1077
;       onto stack, having generated it by possibly issuing service
;
1078
; in:   R10 = mode to try for
1079
;       R11 = mode to use if service not claimed (and R10 is mode number)
1080
;       R10 and R11 should have bit 7 CLEAR (if mode numbers)
Neil Turton's avatar
Neil Turton committed
1081 1082 1083 1084
;
; out:  If r10 is an invalid mode selector or invalid new format sprite word then
;         V=1
;         r0 -> error
1085
;         stack flat (no pushed info)
Neil Turton's avatar
Neil Turton committed
1086
;       else
1087 1088 1089
;         V=0
;         Stack holds a mode table (size wkwordsize) and VIDCList
;         type 3 (size VIDCList3Size) (total size PushedInfoSize)
Neil Turton's avatar
Neil Turton committed
1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110
;       endif
;       All other registers preserved
;

PushModeInfoAnyMonitor ROUT
        SUB     sp, sp, #PushedInfoSize
        Push    "r2-r4,r7-r11, lr"
        MOV     r3, #-1
        MOV     r7, #-1                 ; indicate no VIDC stuff necessary
        CMP     r10, #&100              ; is it a mode selector
        BCS     PushModeInfoCommonNoService
        BranchIfKnownMode r10, PushModeInfoCommonNoService
        B       PushModeInfoCommon

PushModeInfo ROUT
        SUB     sp, sp, #PushedInfoSize
        Push    "r2-r4,r7-r11, lr"
        MOV     r7, #0                  ; indicate VIDC stuff IS necessary
        BL      ReadMonitorType
PushModeInfoCommon
        MOV     r2, r10                 ; r2 = original mode
1111 1112
        BL      OfferModeExtension
        BEQ     %FT30                   ; [service claimed]
Neil Turton's avatar
Neil Turton committed
1113 1114 1115 1116 1117

        CMP     r2, #&100               ; service not claimed - check if mode selector
        MOVCC   r10, r11                ; unrecognised mode number, so use substitute
        BCC     PushModeInfoCommonNoService

1118
25
Neil Turton's avatar
Neil Turton committed
1119 1120 1121
; service not claimed and it's a mode selector - return error "Screen mode not available"

        ADR     r0, ErrorBlock_ModeNotAvailable
1122
26
Neil Turton's avatar
Neil Turton committed
1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178
  [ International
        BL      TranslateError
  ]
        B       %FT40

        MakeErrorBlock ModeNotAvailable

30
        TEQ     r4, #0                  ; if r4 returned zero, then a mode selector was used
                                        ; either initially or after translation from mode number
        BEQ     %FT35                   ; so no ws list
        LDR     r2, [r4, #4]!           ; else if claimed, then find ws base mode
        CMP     r2, #&100               ; if ws base mode is a mode selector, it's invalid
        ANDCC   r2, r2, #&7F            ; else knock off shadow bit
        BCC     %FT35
        MOV     r10, r11                ; invalid ws base mode, so pretend service not responded to

; and drop thru to PushModeInfoCommonNoService

PushModeInfoCommonNoService
        MOV     r2, r10                 ; else use provided mode
        MOV     r3, #0
        MOV     r4, #0
35
        ADD     r9, sp, #9*4            ; adjust for pushed registers
        CMP     r2, #&100
        BCC     %FT45
        BL      GenerateModeSelectorVars ; also copes with new sprite mode word
        BVC     %FT55

; we got an error

40
        SETV
        Pull    "r2-r4,r7-r11,lr"       ; restore registers
        ADD     sp, sp, #PushedInfoSize ; junk stack frame
        MOV     pc, lr                  ; exit VS, r0 -> error

45
        ADRL    r14, Vwstab
        LDR     r10, [r14, r2, LSL #2]
        ADD     r14, r14, r10           ; r14 -> mode table
        MOV     r10, #wkwordsize-4
50
        LDR     r2, [r14, r10]
        STR     r2, [r9, r10]
        SUBS    r10, r10, #4
        BCS     %BT50

; now change any variables specified in workspace block or mode selector overrides

55
        TEQ     r4, #0                  ; if service was claimed
        ADDNE   r4, r4, #4              ; then skip ws base mode
        BLNE    ProcessModeVarPairs

1179

Neil Turton's avatar
Neil Turton committed
1180 1181 1182 1183 1184
; hopefully, R7 is still set from up there to be NZ if no VIDC stuff necessary

        CMP     r7, #0
        Pull    "r2-r4,r7-r11, pc", NE  ; if no VIDC stuff required, exit (NB V=0 from CMP)

1185 1186
; mjs Kernel/HAL split
; pushed video controller info is now hardware independent, it is a VIDCList type 3
Neil Turton's avatar
Neil Turton committed
1187 1188 1189 1190

        TEQ     R3, #0                  ; if no module claimed service
        MOVEQ   R2, R11                 ; then use provided mode
        BEQ     %FT62
1191 1192
59
        ADD     R14, R9, #wkwordsize    ; R14 -> space for VIDCList3
1193 1194 1195 1196 1197 1198 1199 1200
        ASSERT  VIDCList3BaseSize = 64
        LDMIA   R3!, {R2,R4,R7-R11}     ; 28 bytes
        STMIA   R14!, {R2,R4,R7-R11}
        LDMIA   R3!, {R2,R4,R7-R11}     ; 56 bytes
        STMIA   R14!, {R2,R4,R7-R11}
        LDMIA   R3!, {R2,R4}            ; 64 bytes
        STMIA   R14!, {R2,R4}
        MOV     R10, #VIDCList3Size-(VIDCList3BaseSize+4) ; this much space left for control list items (excluding terminator)
1201
60
1202 1203
        LDR     R8, [R3], #4
        SUBS    R10, R10, #8
1204
        BLT     %FT65                   ; List too long, throw an error
1205
        CMP     R8, #-1
1206 1207
        LDRNE   R9, [R3], #4
        STMNEIA R14!, {R8-R9}
1208
        BNE     %BT60
1209
        STR     R8, [R14]
1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246

        ; Recalculate LineLength, ScreenSize based on the contents of the VIDC
        ; list
        ADD     R9, SP, #9*4            ; adjust for pushed registers
        LDR     R2, [R9, #wkwordsize + VIDCList3_PixelDepth]
        LDR     R4, [R9, #wkwordsize + VIDCList3_HorizDisplaySize]
        MOV     R4, R4, LSL R2
        ADD     R4, R4, #7
        MOV     R4, R4, LSR #3
        ADD     R14, R9, #wkwordsize + VIDCList3_ControlList
        MOV     R10, #0
61
        LDMIA   R14!, {R7, R8}
        CMP     R7, #ControlList_ExtraBytes
        ADDEQ   R4, R4, R8
        CMP     R7, #ControlList_Interlaced
        MOVEQ   R10, R8
        CMP     R7, #ControlList_Terminator
        BNE     %BT61
        STR     R4, [R9, #wkLineLength]
        LDR     R2, [R9, #wkwordsize + VIDCList3_VertiDisplaySize]
        MOV     R2, R2, LSL R10         ; Calculate height from VIDC list too (YWindLimit may have been tampered with?)
        MUL     R2, R4, R2
        LDR     R4, [R9, #wkModeFlags]
        TST     R4, #ModeFlag_Teletext
        MOVNE   R2, R2, LSL #1          ; teletext ScreenSize is actually enough for two screens
        STR     R2, [R9, #wkScreenSize]

        CMP     R10, #0
        ORRNE   R4, R4, #ModeFlag_InterlacedMode
        STRNE   R4, [R9, #wkModeFlags]  ; Make sure interlace is flagged as such

        LDR     R2, [WsPtr, #GraphicsVFeatures]
        TST     R2, #GVDisplayFeature_HardwareScroll
        ORREQ   R4, R4, #ModeFlag_HardScrollDisabled
        STREQ   R4, [R9, #wkModeFlags]

1247 1248
        CLRV
        Pull    "R2-R4,R7-R11, PC"      ; done
Neil Turton's avatar
Neil Turton committed
1249

1250
62                                      ; arrive here if service not claimed, R2 = provided mode number
1251 1252 1253 1254 1255 1256
        ; XXX possible to exit earlier? (right after OfferModeExtension?)
        B       %BT25

65
        ADRL    r0, ErrorBlock_BuffOverflow
        B       %BT26
Neil Turton's avatar
Neil Turton committed
1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278

; *****************************************************************************
;
;       GenerateModeSelectorVars - Work out mode variables from mode selector
;                                    or new format sprite mode word
;
; Note: the algorithms used to generate these variables are duplicated in
; s.vdu.vduswis in the OS_ReadModeVariable code.

; in:   r2 = new format sprite word or pointer to mode selector
;       r9 -> stack frame to store vars in
;
; out:  If valid then
;           V=0
;           r0 preserved
;       else
;           V=1
;           r0 -> error
;       endif
;       All other registers preserved
;

1279
GenerateModeSelectorVars Entry "r0,r1,r3-r8,r10-r12"
Neil Turton's avatar
Neil Turton committed
1280 1281 1282 1283 1284
        ASSERT  ModeSelector_Flags = 0
        ASSERT  ModeSelector_XRes = 4
        ASSERT  ModeSelector_YRes = 8
        ASSERT  ModeSelector_PixelDepth = 12
        TST     r2, #1                          ; is it a new format sprite mode word?
1285
        BNE     %FT10                           ; [yes, so skip]
Neil Turton's avatar
Neil Turton committed
1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306
        MOV     r0, r2
        BL      ValidateModeSelector
        BVS     %FT95                           ; invalid - return error
        LDMIB   r2, {r4-r6}                     ; r4 = xres; r5 = yres; r6 = pixdepth

        STR     r6, [r9, #wkLog2BPC]            ; log2bpc = log2bpp = pixdepth
        STR     r6, [r9, #wkLog2BPP]
        ADR     lr, NColourTable
        LDR     lr, [lr, r6, LSL #2]            ; load NColour value
        STR     lr, [r9, #wkNColour]

        MOV     lr, #0
        STR     lr, [r9, #wkYShftFactor]        ; yshftfactor = 0 (obsolete)
        STR     lr, [r9, #wkModeFlags]          ; modeflags = 0

        MOV     lr, #1
        STR     lr, [r9, #wkXEigFactor]         ; xeig = 1
        CMP     r5, r4, LSR #1                  ; if yres < xres/2
        MOVCC   r7, #2                          ; then yeig = 2
        MOVCS   r7, #1                          ; else yeig = 1
        STR     r7, [r9, #wkYEigFactor]
Jeffrey Lee's avatar
Jeffrey Lee committed
1307

Neil Turton's avatar
Neil Turton committed
1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328
        RSB     r7, lr, r4, LSR #3              ; scrrcol = (xres >> 3) -1
        STR     r7, [r9, #wkScrRCol]
        RSB     r7, lr, r5, LSR #3              ; scrbrow = (yres >> 3) -1
        STR     r7, [r9, #wkScrBRow]

        SUB     r7, r4, #1
        STR     r7, [r9, #wkXWindLimit]         ; xwindlimit = xres-1
        SUB     r7, r5, #1
        STR     r7, [r9, #wkYWindLimit]         ; ywindlimit = yres-1

        MOV     r7, r4, LSL r6                  ; r7 = xres << pixdepth
        MOV     lr, r7, LSR #3
        STR     lr, [r9, #wkLineLength]         ; linelen = (xres << pixdepth) >> 3

        MUL     r7, r5, r7                      ; r7 = (xres * yres) << pixdepth
        MOV     lr, r7, LSR #3
        STR     lr, [r9, #wkScreenSize]         ; screensize = ((xres * yres) << pixdepth) >> 3

        ADD     r4, r2, #ModeSelector_ModeVars  ; now do pairs of mode variables
        BL      ProcessModeVarPairs

1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381
        ; Fixup teletext modes
        LDR     r0, [r9, #wkModeFlags]
        TST     r0, #ModeFlag_Teletext
        BEQ     %FT09
        ; Force the mode flags to be correct for our implementation
      [ HiResTTX
        ORR     r0, r0, #ModeFlag_NonGraphic+ModeFlag_GapMode+ModeFlag_DoubleVertical
      |
        BIC     r0, r0, #ModeFlag_DoubleVertical
        ORR     r0, r0, #ModeFlag_NonGraphic+ModeFlag_GapMode
      ]
        STR     r0, [r9, #wkModeFlags]
        ; Ensure colour depth is acceptable
        LDR     r0, [r9, #wkNColour]
        CMP     r0, #15
      [ HiResTTX
        ADRLOL  r0, ErrorBlock_BadPixelDepth
        BLO     %FT90
        CMP     r0, #63
        ADREQL  r0, ErrorBlock_BadPixelDepth
        BEQ     %FT90
      |
        ADRNEL  r0, ErrorBlock_BadPixelDepth
        BNE     %FT90
      ]
        ; Massage ScreenSize, needs to be large enough for two screen banks
        LDR     r0, [r9, #wkScreenSize]
        MOV     r0, r0, LSL #1
        STR     r0, [r9, #wkScreenSize]
        ; Clamp ScrRCol, ScrBRow
        LDR     r0, [r9, #wkScrRCol]
        CMP     r0, #254 ; TTXDoubleCounts is a byte array
        MOVHI   r0, #254
        LDR     r7, [r2, #ModeSelector_XRes]
        MOV     lr, #1
      [ HiResTTX
        RSB     r7, lr, r7, LSR #4
      |
        RSB     r7, lr, r7, LSR #3
      ]
        CMP     r0, r7
        MOVHI   r0, r7
        STR     r0, [r9, #wkScrRCol]
        LDR     r0, [r9, #wkScrBRow]
      [ HiResTTX
        DivRem  r7, r5, #20, lr, norem
      |
        DivRem  r7, r5, #10, lr, norem
      ]
        CMP     r0, r7
        SUBHS   r0, r7, #1
        STR     r0, [r9, #wkScrBRow]

1382 1383 1384
        CLRV
        EXIT

1385
09
1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407
        ; We only have double-vertical char plotting routines for 1bpp
        LDR     r0, [r9, #wkModeFlags]
        LDR     r1, [r9, #wkLog2BPP]
        LDR     r3, [r9, #wkLog2BPC]
        TST     r0, #ModeFlag_DoubleVertical
        BEQ     %FT091
        CMP     r1, #0
        ; Also can't mix double-vertical with double-pixel, since that would also require another char plotting routine
        CMPEQ   r3, #0
        ADRNEL  r0, ErrorBlock_BadPixelDepth
        BNE     %FT90
091
        ; We only support 2bpp BBC gap modes
        TST     r0, #ModeFlag_BBCGapMode
        CMPNE   r1, #1
        ADRNEL  r0, ErrorBlock_BadPixelDepth
        BNE     %FT90
        ; We don't support double-pixel modes higher than 16bpp (or regular modes higher than 32bpp)
        CMP     r3, #5
        ADRHIL  r0, ErrorBlock_BadPixelDepth
        BHI     %FT90

Neil Turton's avatar
Neil Turton committed
1408 1409 1410