MODE change code; OSWORD 10; Clear screen - 475 bytes (2.8%)
- §1. Initialise VDU variables and change MODE
- §2. Set MODE
- §3. OSWORD 10 - Read character definition
- §4. Screen clear routine
- §5. executeRequiredVDUFunction
§1. Initialise VDU variables and change MODE.
This is called at reset time On Entry: A = screen MODE number
.initialiseVDUVariablesAndSetMODE = $cb1d PHA save A (screen mode number) Clear all VDU variables (0-126) LDX #.vduVariablesEnd - .vduVariablesStart loop counter LDA #0 A=0 STA .vduStatusByte VDU status byte to set default conditions (zero) - STA .vduVariablesStart-1,X zero VDU variables (0-126) DEX with this loop BNE - implode character definitions JSR .osbyte20EntryPoint implode character definitions (A = 0) PLA get back A (screen mode number) Set teletext cursor LDX #$7F X=$7F STX .vduTeletextCharacterForCursor set mode 7 cursor character fall through...
On Entry: A = screen MODE number
.setMODE = $cb33 BIT .systemAvailableRAM test available RAM pages ($40 = 16k; $80 = 32k) BMI + if (32k available) then branch ORA #4 ensure only modes 4-7 are available + AND #7 X = A AND 7 (to ensure a legal mode) TAX X = mode Set characteristic vdu variables for the new mode STX .vduCurrentScreenMODE set screen mode LDA .numberOfColoursMinusOneInMODETable,X get number of colours -1 in mode from table STA .vduNumberOfLogicalColoursMinusOne set number of logical colours less 1 LDA .bytesPerCharacter,X get number of bytes /character from table STA .vduBytesPerCharacter set bytes per character LDA .pixelsPerByteMinusOneInMODETable,X get display mode pixels/byte from table STA .vduPixelsPerByteMinusOne set pixels per byte-1 BNE + if (in a graphics mode) then branch LDA #7 this is a text mode; set A = 7 + ASL A = A * 2 TAY Y = 2 * (pixels per byte-1), index into a table of colour masks LDA .sixteenColourMODEMaskTable - 1,Y mask table STA .vduColourMaskRight store as colour mask right - ASL shift A left BPL - until the top bit becomes set STA .vduColourMaskLeft store as colour mask left LDY .screenDisplayMemoryIndexTable,X screen display memory index table STY .vduCurrentScreenMODEGroup MODE group = screen memory size: 0 = 20k (MODE 0,1,2) 1 = 16k (MODE 3) 2 = 10k (MODE 4,5) 3 = 8k (MODE 6) 4 = 1k (MODE 7) LDA .systemVIAHardwareScrollTable2,Y get system VIA parameter for setting hardware scrolling value JSR .writeAToSystemVIARegisterB write hardware scrolling value to System VIA LDA .systemVIAHardwareScrollTable1,Y get system VIA parameter for setting hardware scrolling value JSR .writeAToSystemVIARegisterB write hardware scrolling value to System VIA LDA .screenMemorySizeInBytesHigh,Y screen RAM size high byte table STA .vduScreenSizeHighByte screen RAM size high byte LDA .screenMemoryStartHigh,Y screen ram address high byte STA .vduStartScreenAddressHighByte high byte of screen RAM address A=Y=the screen memory type TYA A = Y A = 0 1 2 3 4 ADC #2 A = A + 2 A = 2 3 4 5 6 EOR #7 A = A EOR 7 A = 5 4 3 2 1 LSR A = A / 2 A = 2 2 1 1 0 TAX X=A Index into multiplication table (0 = MODE 7 1 = MODE 4,5,6 2 = MODE 0,1,2,3) LDA .multiplicationTabletoUseLow,X load the low byte of the multiplication table to use STA .vduMultiplicationTableLow store LDA #>.multiplyBy640Table high byte of multiplication tables STA .vduMultiplicationTableHigh store. Now (.vduMultiplicationTableLow) points to 640x multiplication table or 40x. LDA .bytesPerRowLow,X get number of bytes per row (low byte) from table STA .vduBytesPerCharacterRowLow store bytes per character row STX .vduBytesPerCharacterRowHigh bytes per character row (high byte) LDA #%01000011 JSR .clearVDUStatusByteFlags clear bits 2,3,4,5,7 in .vduStatusByteFlags: bit 2 = paged scrolling selected bit 3 = software scrolling (text window) bit 4 = not used bit 5 = graphics cursor enabled (VDU 5) bit 7 = VDU disabled LDX .vduCurrentScreenMODE screen mode LDA .videoULAVideoControlRegisterDefaultValuesPerMODE,X get video ULA control setting JSR .setVideoULA set video ULA using OSBYTE 154 Set CRTC registers for the current mode PHP push flags SEI disable interrupts LDX .crtcCursorEndRegisterTable,Y get cursor end register data from table LDY #11 Y = 11 - LDA .crtcRegisters0to11ForMODEs012,X get entry from CRTC table JSR .setCRTCRegisterAY set CRTC Register Y to A DEX reduce pointers DEY BPL - if (still >=0) then branch (loop back) PLP pull flags JSR .vdu20EntryPoint set default colours JSR .vdu26EntryPoint set default windows .initializeDisplayAndHomeCursor = $cbc1 LDX #0 X = 0 LDA .vduStartScreenAddressHighByte high byte of screen RAM address STX .vduScreenTopLeftAddressLow screen start address low STA .vduScreenTopLeftAddressHigh screen start address high JSR .setTextCursorCRTCAddress use X and Y to set new cursor address LDY #.crtcStartScreenAddressHighRegister JSR .setTwoCRTCRegisters set registers 12 and 13 in CRTC LDA .vduBackgroundTextColour background text colour LDX .vduCurrentScreenMODEGroup MODE group = screen memory size 0=20k (MODE 0,1,2) 1=16k (MODE 3) 2=10k (MODE 4,5) 3=8k (MODE 6) 4=1k (MODE 7) LDY .clearScreenRoutineEntryPointLow,X get section control number STY .vduJumpVectorLow set it in jump vector low LDY #>.clearScreenRoutineEntryPointMODE012 high byte of address of screen clearing routine STY .vduJumpVectorHigh upper byte of link address LDX #0 X = 0 STX .pagedModeCounter paged mode counter STX .vduTextCursorXPosition text column STX .vduTextCursorYPosition current text line JMP (.vduJumpVectorLow) jump indirect - this calls the screen clearing routine
§3. OSWORD 10 - Read character definition.
On Entry: A = character to read .oswordX/Y = address of buffer to store the eight bytes of results
.osword10EntryPoint = $cbf3 JSR .getCharacterDefinitionAddress set up character definition pointers LDY #0 Y=0 - LDA (.vduTempStoreDE),Y get first byte INY Y=Y+1 STA (.oswordX),Y store it in YX CPY #8 until Y=8 BNE - RTS
On Entry: A contains byte for the background colour which is set in every byte of the screen To visualise the pattern of bytes that are cleared see:
.clearScreenRoutineEntryPointMODE012 = $cc02 STA $3000,X STA $3100,X STA $3200,X STA $3300,X STA $3400,X STA $3500,X STA $3600,X STA $3700,X STA $3800,X STA $3900,X STA $3A00,X STA $3B00,X STA $3C00,X STA $3D00,X STA $3E00,X STA $3F00,X .clearScreenRoutineEntryPointMODE3 = $cc32 STA $4000,X STA $4100,X STA $4200,X STA $4300,X STA $4400,X STA $4500,X STA $4600,X STA $4700,X STA $4800,X STA $4900,X STA $4A00,X STA $4B00,X STA $4C00,X STA $4D00,X STA $4E00,X STA $4F00,X STA $5000,X STA $5100,X STA $5200,X STA $5300,X STA $5400,X STA $5500,X STA $5600,X STA $5700,X .clearScreenRoutineEntryPointMODE45 = $cc7a STA $5800,X STA $5900,X STA $5A00,X STA $5B00,X STA $5C00,X STA $5D00,X STA $5E00,X STA $5F00,X .clearScreenRoutineEntryPointMODE6 = $cc92 STA $6000,X STA $6100,X STA $6200,X STA $6300,X STA $6400,X STA $6500,X STA $6600,X STA $6700,X STA $6800,X STA $6900,X STA $6A00,X STA $6B00,X STA $6C00,X STA $6D00,X STA $6E00,X STA $6F00,X STA $7000,X STA $7100,X STA $7200,X STA $7300,X STA $7400,X STA $7500,X STA $7600,X STA $7700,X STA $7800,X STA $7900,X STA $7A00,X STA $7B00,X .clearScreenRoutineEntryPointMODE7 = $cce6 STA $7C00,X STA $7D00,X STA $7E00,X STA $7F00,X INX BEQ .exit7 if (all done) then branch (exit) fall through...
§5. executeRequiredVDUFunction.
.executeRequiredVDUFunction = $ccf5 JMP (.vduJumpVectorLow) loop back (using the jump vector set up previously) to the appropriate address for the current MODE.