; AZVIDT24.asm - AZBK video controller tester, version 24 ; Target: BK Turbo8 Cross Assembler, BK-0010 + AZBK, ANDOS ; Status: all 60 1/2/4/8bpp modes HW + GID 4.6 PASS (AZVIDT18). ; UI: 512x256 mono (012100), 64x25 chars, BK10 ROM font. ; Base menu and 15x4 manual video-mode selector retained from HW PASS v07. ; Main/grid full redraw only upon entering view, not when moving selection. ; Main menu: RUN ALL 60 (2 seconds per mode), MANUAL GRID, EXIT. ; Main menu reads ONLY one event per physical press/release (no repeat). ; Batch: PING/PONG 1100/1300; 60Hz IRQ (vector 100) commits ready frames. ; Batch timer: 120 x 60Hz IRQ ticks after each committed frame = ~2 sec. ; ENTER in grid launches 1bpp rows 0..3, 2bpp rows 4..7, ; 4bpp rows 8..11, 8bpp rows 12..14 (all 60 single-layer modes). ; Navigation arrows have timer-driven repeat. A simple fixed-VRAM HUD ; displays real registers 177250/177252, moving with the test image. ; Horizontal scroll wraps at the selected VIDEO WORD PITCH. ; For all resolutions, X/Y text scaling follows physical pixel aspect ratio. ; Nibble LUT caches packed zoom scanlines; scroll HUD repaints changed digits only. ; Historical 768-line emulator diagnostics removed after HW + GID 4.6 PASS. ; Input fix: stale keyboard scan codes discarded on release, no typematic ; for ENTER/SPACE/KT in menu, grid, or manual test. ; ; BK10 font: 8x10 pixels, 10 bytes per glyph. ; ASCII space (040) begins at 112276 in Monitor-10 ROM. ; Font pointer = 111576 + ASCII_code*10(decimal). ; Bit 0 of each font row is the leftmost pixel. ; Critical: AZ ROM pages 134/135 explicitly mapped to 100000/110000, ; as in azboot.asm bk10 hardware path. No font copy and no TRAP. ; 160000 and 170000 windows are NOT used or altered by the program. ; Screen: AZ physical RAM pages 1000..1003, 120000 window for drawing. .LA 1000 AZMODE = 012100 SCRBASE = 1000 TESTBASE = 1100 ; PING: separate test VRAM, max 96 x 4-KiB pages TESTBASE2 = 1300 ; PONG: likewise 96 pages (1300..1437), no overlap WIN100 = 177320 WIN110 = 177322 WIN120 = 177324 WINDOWS = 177340 WINDOWRO = 177342 WINDOWDIS = 177344 SYSCTRL = 177346 SYSCTRL716 = 177716 SYSCTRL_SHADOW = 177352 FONTBASE = 111576 MONP0 = 134 MONP1 = 135 K_ESC = 3 K_SPACE = 40 K_ENTER = 12 K_LEFT = 10 K_RIGHT = 31 K_UP = 32 K_DOWN = 33 Begin: ; Presence check BEFORE accessing AZ-only video registers. mov @#4,OldBusPC mov @#6,OldBusPSW mov #ProbeBusErr,@#4 mov #340,@#6 clr BusFault clr ProbeValue mov @#177370,R0 ; FPGA version register (AZ only) mov R0,ProbeValue mov OldBusPC,@#4 mov OldBusPSW,@#6 tst BusFault bne NoAZ tst ProbeValue beq NoAZ cmp ProbeValue,#177777 beq NoAZ jmp AZPresent ProbeBusErr: inc BusFault add #4,(SP) ; skip 4-byte MOV @#177370,R0 rti NoAZ: mov #NoAZText,R3 NoAZNext: movb (R3)+,R0 beq NoAZExit EMT 16 ; BK monitor character output br NoAZNext NoAZExit: jmp @#100000 AZPresent: ; Save/restore contract patterned after blttst8.asm mov @#177230,-(SP) mov @#177232,-(SP) mov @#177250,-(SP) mov @#177252,-(SP) mov @#177324,-(SP) mov @#177326,-(SP) mov @#WIN100,-(SP) ; save BK10 monitor ROM windows mov @#WIN110,-(SP) mov @#100,-(SP) mov @#102,-(SP) mov @#177340,-(SP) mov @#177342,-(SP) mov @#177344,-(SP) mov @#177352,-(SP) mov @#177346,-(SP) bis #100,@#177660 mov #14020,@#177716 ; AZBOOT bk10 mapping: ROM 134/135 = MONIT10 8K. ; Keep 160000 and 170000 windows untouched. mov #MONP0,@#WIN100 mov #MONP1,@#WIN110 bis #1400,@#177340 ; enable 100000 + 110000 bic #1400,@#177344 ; permit windows to be mapped bis #6000,@#177340 ; enable video write 120000 bic #6000,@#177342 ; allow writes where needed clr @#177250 clr @#177252 mov #SCRBASE,@#177232 mov #AZMODE,@#177230 clr RepeatActive clr RepeatTimerUsed clr MainSelected clr BatchActive clr BatchStopped mov #TESTBASE,TestBufferBase mov #22,TestBufferHi clr BatchPal2Saved clr BatchPal4Saved clr BatchPal8Saved mov #2,GridRow ; default 512x256 mono, row=2 mov #1,GridCol jmp MainDraw ; ----------------------------- UI main menu ------------------------------ MainDraw: clr RepeatActive ; no carried-over arrow repeat in main menu jsr PC,ClearScreen mov #2,UX mov #1,UY mov #TitleText,R3 jsr PC,PrintString mov #2,UX mov #3,UY mov #VersionText,R3 jsr PC,PrintString mov @#177346,R1 bic #177774,R1 jsr PC,PrintOct6 mov #FPGAtext,R3 jsr PC,PrintString mov ProbeValue,R1 jsr PC,PrintOct6 mov #OptionalVersion,R3 jsr PC,PrintString mov #2,UX mov #6,UY mov #MenuText0,R3 jsr PC,PrintString mov #2,UX mov #10,UY mov #MenuText1,R3 jsr PC,PrintString mov #2,UX mov #12,UY ; third entry on line 10 decimal mov #MenuText2,R3 jsr PC,PrintString mov #2,UX mov #22.,UY mov #ControlsMain,R3 jsr PC,PrintString mov #'>,R0 jsr PC,MainPutCursor MainKey: jsr PC,ReadKeySingle ; one event per release, NO repeat cmp R0,#K_ESC beq DoExit cmp R0,#K_SPACE beq DoExit cmp R0,#K_UP beq MainUp cmp R0,#K_DOWN beq MainDown cmp R0,#K_ENTER beq MainEnter br MainKey MainUp: mov #40,R0 ; erase old arrow only jsr PC,MainPutCursor tst MainSelected bne MainUpStep mov #2,MainSelected br MainShowCursor MainUpStep: dec MainSelected br MainShowCursor MainDown: mov #40,R0 jsr PC,MainPutCursor inc MainSelected cmp MainSelected,#3 blo MainShowCursor clr MainSelected MainShowCursor: mov #'>,R0 jsr PC,MainPutCursor jmp MainKey MainEnter: tst MainSelected bne MainCheckGrid jmp BatchStart MainCheckGrid: cmp MainSelected,#1 bne DoExit jmp GridDraw DoExit: jmp ExitToANDOS ; R0 = ASCII cursor glyph; menu item rows 6,8,10 (decimal). MainPutCursor: mov #0,UX mov MainSelected,R1 asl R1 ; y = 6 + (selection * 2) add #6,R1 mov R1,UY jsr PC,PrintChar rts PC ; -------------------- AUTO / 60 SINGLE-LAYER MODES ------------------------ ; HW 60Hz AZ frame interrupt from blttst5.asm: vector 100, SYSCTRL 177346 ; BIT 4 selects 48Hz; clear BIT 4 for 60Hz. BIT 10 enables timer. ; Its handler commits BOTH video registers at the start of the same tick. ; Main drawing continues in the hidden PING/PONG buffer. No prep screen. ; Hold image for 120 frame interrupts (~2s), then prepare the next image. ; Preparation time is additional; no asynchronous writes to visible VRAM. ; Keep programmable BK timer 177706/177712 reserved for arrow repeat. BatchStart: mov GridRow,BatchSavedRow mov GridCol,BatchSavedCol clr GridRow clr GridCol mov #1,BatchActive clr BatchStopped clr RepeatActive clr BatchFlipPending clr BatchFrameTicks mov #TESTBASE,TestBufferBase mov #22,TestBufferHi clr BatchPal2Saved clr BatchPal4Saved clr BatchPal8Saved ; Save original timer settings and vector 100/102. ; Reinstall vector before enabling 60Hz source. mov @#SYSCTRL,BatchSavedSysCtrl bic #10,@#SYSCTRL mov @#100,BatchSavedVector100 mov @#102,BatchSavedVector102 mov #BatchFrameISR,@#100 mov #340,@#102 bic #4,@#SYSCTRL bis #10,@#SYSCTRL mov @#177662,R0 ; discard ENTER used to start jmp GridEnter ; draw the first frame offscreen ; IRQ handler deliberately uses no CPU registers, only memory operands. ; RTI restores the interrupted PSW. All variables are 16-bit words. ; On a pending flip, the new base and mode are committed at the IRQ. ; Start the 120-frame hold counter from THIS actual hardware flip. BatchFrameISR: tst BatchFlipPending beq BatchIRQCount mov BatchFlipBase,@#177232 mov BatchFlipMode,@#177230 clr BatchFrameTicks clr BatchFlipPending rti BatchIRQCount: cmp BatchFrameTicks,#120. bcc BatchIRQExit ; saturate at 120 inc BatchFrameTicks BatchIRQExit: rti ; Called only after the renderer has finished and HUD is drawn OFFSCREEN. ; The main loop must not write 177230/177232 directly in batch mode. BatchRequestFlip: mov TestBufferBase,BatchFlipBase mov TestMode,BatchFlipMode mov #1,BatchFlipPending BatchAwaitFlip: tst BatchFlipPending beq BatchWait jsr PC,BatchCheckAbort tst BatchStopped bne BatchAbort br BatchAwaitFlip BatchWait: BatchPoll: jsr PC,BatchCheckAbort tst BatchStopped bne BatchAbort cmp BatchFrameTicks,#120. blo BatchPoll jmp BatchNext ; Poll keyboard without delay; only ENTER / SPACE / KT abort batch. ; 177660 bit 200: keyboard data available (as in AZVIDT22). BatchCheckAbort: bit #200,@#177660 beq BatchCheckDone mov @#177662,R0 bic #177600,R0 cmp R0,#K_ENTER beq BatchMarkAbort cmp R0,#K_SPACE beq BatchMarkAbort cmp R0,#K_ESC bne BatchCheckDone BatchMarkAbort: mov #1,BatchStopped BatchCheckDone: rts PC BatchAbort: clr BatchFlipPending jmp BatchFinish BatchNext: inc GridCol cmp GridCol,#4 blo BatchSwapBuffer clr GridCol inc GridRow cmp GridRow,#15. bcc BatchFinish BatchSwapBuffer: ; TESTBASE=1100 DST_HI=022, TESTBASE2=1300 DST_HI=026. ; Switch the hidden target, never modify visible RAM. cmp TestBufferBase,#TESTBASE bne BatchUsePing mov #TESTBASE2,TestBufferBase mov #26,TestBufferHi br BatchRenderNext BatchUsePing: mov #TESTBASE,TestBufferBase mov #22,TestBufferHi BatchRenderNext:jmp GridEnter BatchFinish: ; Flip back to the already prepared main menu ON A TICK. mov #SCRBASE,BatchFlipBase mov #AZMODE,BatchFlipMode mov #1,BatchFlipPending BatchMenuFlipWait: tst BatchFlipPending bne BatchMenuFlipWait ; Timer must be disabled before restoring old IRQ vector. bic #10,@#SYSCTRL mov BatchSavedVector100,@#100 mov BatchSavedVector102,@#102 mov BatchSavedSysCtrl,@#SYSCTRL clr BatchFlipPending clr @#177250 clr @#177252 tst BatchPal2Saved beq BatchSkipPal2 jsr PC,ColorRestorePalette BatchSkipPal2: tst BatchPal4Saved beq BatchSkipPal4 jsr PC,FourRestorePalette BatchSkipPal4: tst BatchPal8Saved beq BatchSkipPal8 jsr PC,EightRestorePalette BatchSkipPal8: clr BatchPal2Saved clr BatchPal4Saved clr BatchPal8Saved mov #TESTBASE,TestBufferBase mov #22,TestBufferHi clr BatchActive mov BatchSavedRow,GridRow mov BatchSavedCol,GridCol jsr PC,RestoreRepeatTimer ; Wait release after abort, so MainKey cannot retrigger it. BatchKeyRelease: bit #100,@#177716 beq BatchKeyRelease mov @#177662,R0 jmp MainKey ; ------------------------- Manual modes grid ----------------------------- ; Table contains 15 rows x 4 columns (192,256,384,768 lines). ; These are provisional canonical configurations to be HW tested. GridDraw: jsr PC,ClearScreen mov #0,UX mov #0,UY mov #GridTitle,R3 jsr PC,PrintString mov #1,UX ; row 1 header starts at x=1 mov #1,UY mov #GridHeading,R3 jsr PC,PrintString mov #5,UY mov #GridLabels,R5 mov #ModeCodes,R4 clr RenderRow GridRowLoop: mov #1,UX mov (R5)+,R3 jsr PC,PrintString mov #15.,UX mov #4.,RenderCol GridColLoop: mov (R4)+,R1 jsr PC,PrintOct6 add #4.,UX dec RenderCol bne GridColLoop inc UY inc RenderRow cmp RenderRow,#15. blo GridRowLoop ; Brackets drawn once on entry; later updates are local. jsr PC,GridDrawCursor mov #2,UX mov #21.,UY mov #SelectedText,R3 jsr PC,PrintString jsr PC,GridUpdateSelected mov #2,UX mov #23.,UY mov #ControlsGrid,R3 jsr PC,PrintString GridKey: jsr PC,ReadKey cmp R0,#K_ESC beq GridBack cmp R0,#K_SPACE beq GridBack cmp R0,#K_ENTER beq GridEnter cmp R0,#K_LEFT beq GridLeft cmp R0,#K_RIGHT beq GridRight cmp R0,#K_UP beq GridUp cmp R0,#K_DOWN beq GridDown br GridKey GridBack: jmp MainDraw GridEnter: cmp GridRow,#4 blo GridEnterMono cmp GridRow,#8. blo GridEnterColor cmp GridRow,#12. blo GridEnterFour jmp EightTestStart GridEnterMono: jmp MonoTestStart GridEnterColor: jmp ColorTestStart GridEnterFour: jmp FourTestStart GridLeft: jsr PC,GridEraseCursor dec GridCol bpl GridMoveDone mov #3,GridCol br GridMoveDone GridRight: jsr PC,GridEraseCursor inc GridCol cmp GridCol,#4 blo GridMoveDone clr GridCol br GridMoveDone GridUp: jsr PC,GridEraseCursor dec GridRow bpl GridMoveDone mov #14.,GridRow br GridMoveDone GridDown: jsr PC,GridEraseCursor inc GridRow cmp GridRow,#15. blo GridMoveDone clr GridRow GridMoveDone: jsr PC,GridDrawCursor jsr PC,GridUpdateSelected jmp GridKey ; Refresh just two bracket glyphs and six selected mode digits. GridDrawCursor: mov #'[,R0 mov #'],R1 jsr PC,GridPutCursor rts PC GridEraseCursor: mov #40,R0 ; ASCII space mov #40,R1 jsr PC,GridPutCursor rts PC ; R0=left glyph, R1=right glyph; preserve both using stack. ; Mode digits start at x=15+10*col and span 6 characters. GridPutCursor: mov R0,-(SP) mov R1,-(SP) mov GridCol,R0 asl R0 mov R0,R1 asl R0 asl R0 add R1,R0 ; x = col*10 add #14.,R0 ; left bracket x=14+10*col mov R0,UX mov GridRow,R0 add #5,R0 mov R0,UY mov 2(SP),R0 ; saved left glyph jsr PC,PrintChar ; advances UX by one add #6,UX ; right bracket x=21+10*col mov (SP),R0 ; saved right glyph jsr PC,PrintChar mov (SP)+,R1 mov (SP)+,R0 rts PC GridUpdateSelected: mov #12.,UX ; after 'SELECTED: ' at x=2 mov #21.,UY jsr PC,GetSelectedMode jsr PC,PrintOct6 rts PC GetSelectedMode:; returns R1, preserves R0 and R2 mov R0,-(SP) mov R2,-(SP) mov GridRow,R0 asl R0 asl R0 add GridCol,R0 asl R0 mov #ModeCodes,R2 add R0,R2 mov (R2),R1 mov (SP)+,R2 mov (SP)+,R0 rts PC StubDraw: jsr PC,ClearScreen mov #5,UX mov #10,UY mov #StubText,R3 jsr PC,PrintString mov #5,UX mov #11.,UY mov #SelectedText,R3 jsr PC,PrintString jsr PC,GetSelectedMode jsr PC,PrintOct6 mov #5,UX mov #16.,UY mov #StubBackText,R3 jsr PC,PrintString StubKey: jsr PC,ReadKey cmp R0,#K_ESC beq StubBack cmp R0,#K_SPACE beq StubBack cmp R0,#K_ENTER bne StubKey StubBack: jmp GridDraw ; ------------------- Stage 2: monochrome 1bpp video modes -------------------- ; Active for GridRow=0..3 only (16 modes). Grid/menu buffer is NOT modified. ; Separate TESTBASE=1100 (max 24 pages: 1100..1127), command page 2000. ; Memory stride: 32 words for widths <=512; 64 words for width=1024. ; Blitter: legacy command 000, constant fill 0, up to 192 rows per command. ; No access to CPU windows 160000/170000; monitor font stays at 100/110. ; MonoTestStart: jsr PC,GetSelectedMode mov R1,TestMode mov GridCol,R0 asl R0 mov #MonoHeights,R1 add R0,R1 mov (R1),TestHeight mov GridRow,R0 asl R0 mov #MonoWidths,R1 add R0,R1 mov (R1),TestWidth mov #32.,TestPitchWords mov #64.,TestPitchBytes cmp GridRow,#3 bne MonoWidthReady mov #64.,TestPitchWords mov #128.,TestPitchBytes MonoWidthReady: mov TestWidth,R0 asr R0 asr R0 asr R0 mov R0,TestWidthChars asr R0 ; 16 pixels / word mov R0,TestVisibleWords ; Isolate blitter register state and temporary 120000 mapping. mov @#WIN120,TestSavedWin120 mov @#177270,TestSavedBlitCtrl mov @#177272,TestSavedBlitPage jsr PC,MonoClearBlitter jsr PC,MonoDrawBands jsr PC,ZoomSetParams jsr PC,ZoomInitLUT ; once per test, prior to scaled labels ; Zoom both axes by display dimensions; preserve baseline 128x192/256. cmp TestWidth,#128. bne MonoLabelsScaled cmp TestHeight,#384. blo MonoLabelsSmall MonoLabelsScaled: jsr PC,ZoomDrawLabels br MonoLabelsReady MonoLabelsSmall: jsr PC,MonoDrawLabels MonoLabelsReady: mov TestSavedBlitCtrl,@#177270 mov TestSavedBlitPage,@#177272 mov TestSavedWin120,@#WIN120 ; Commit the prepared, offscreen monochrome framebuffer. clr TestScrollX clr TestScrollY clr @#177250 clr @#177252 tst BatchActive beq MonoNormalCommit ; Build the HUD in *OFFSCREEN* RAM; no intermediate screen. jsr PC,HudDrawFull jmp BatchRequestFlip MonoNormalCommit: mov TestBufferBase,@#177232 mov TestMode,@#177230 jsr PC,HudDrawFull ; existing in-test register HUD MonoStartManual:jmp MonoKey ; Legacy blitter full-memory clear. Page 2000 carries one mutable packet. ; 8 words: SRC/DST high; SRC low; DST low; opcode; width-1 / rows; ; destination increment (+1 for a contiguous rectangle); Y; constant. ; 1100 pages => high 8 bits of physical WORD address = octal 22. ; Max visible framebuffer = 1024*768 bits = 96KiB = 49152 words, ; so destination low 16 bits never overflows into high address byte. MonoClearBlitter: mov #2000,@#WIN120 mov TestBufferHi,@#120000 ; high SRC=0, high DST=022 clr @#120002 clr @#120004 clr @#120006 ; legacy 000 = fill constant mov #1,@#120012 ; contiguous row after width words clr @#120014 clr @#120016 ; clear all pixels to zero mov TestHeight,TestRowsLeft clr TestDstLow MonoClearChunk: mov TestRowsLeft,R0 cmp R0,#192. blo MonoChunkSet beq MonoChunkSet mov #192.,R0 MonoChunkSet: mov R0,TestChunkRows mov #2000,@#WIN120 mov TestDstLow,@#120004 mov TestChunkRows,R1 swab R1 mov TestPitchWords,R0 dec R0 bis R1,R0 mov R0,@#120010 mov #2000,@#177272 mov #40001,@#177270 ; manual, 1 legacy command bis #10000,@#177270 MonoBWaitRead: bit #10000,@#177270 bne MonoBWaitRead MonoBWaitDone: bit #100000,@#177270 bne MonoBWaitDone ; dst += chunkRows * wordsPerRow (shift 5 or 6) mov TestChunkRows,R0 mov #5,R1 cmp TestPitchWords,#32. beq MonoShiftBegin inc R1 MonoShiftBegin: asl R0 sob R1,MonoShiftBegin add R0,TestDstLow sub TestChunkRows,TestRowsLeft bne MonoClearChunk rts PC ; MonoMapRow: R0=scanline (0..767). Returns R2 = CPU byte pointer ; in banked window 120000 and maps the right 4KiB TESTBASE page. ; Clobbers R1 and R2; safe for 64-byte and 128-byte row pitches. MonoMapRow: mov R0,R1 mov R0,R2 cmp TestPitchWords,#32. bne MonoMap128 bic #177700,R2 ; y & 63, bytes per row=64 asl R2 asl R2 asl R2 asl R2 asl R2 asl R2 asr R1 asr R1 asr R1 asr R1 asr R1 asr R1 br MonoMapCommit MonoMap128: bic #177740,R2 ; y & 31, bytes per row=128 asl R2 asl R2 asl R2 asl R2 asl R2 asl R2 asl R2 asr R1 asr R1 asr R1 asr R1 asr R1 MonoMapCommit: add TestBufferBase,R1 mov R1,@#WIN120 add #120000,R2 rts PC ; 16 nested 1-logical-pixel contours, black/white alternating. ; A zero-filled buffer means even contours are the black separator; ; odd contours are the white lines. One central pass per source row. MonoDrawBands: clr MonoY MonoDrawRow: mov MonoY,R0 cmp R0,TestHeight bcc MonoDrawDone jsr PC,MonoMapRow ; D = minimum distance from top/bottom edge. mov MonoY,R0 mov TestHeight,R1 dec R1 sub R0,R1 cmp R0,R1 blo MonoGotDist beq MonoGotDist mov R1,R0 MonoGotDist: cmp R0,#16. bcc MonoMiddleRow ; At top/bottom the white strip must not overwrite the ; earlier (outer) black contours. Patch both edge words. mov R0,MonoDist bit #1,R0 beq MonoPatchEdges mov TestVisibleWords,R1 mov R2,R3 MonoHWord: mov #177777,(R3)+ sob R1,MonoHWord MonoPatchEdges: mov MonoDist,R0 asl R0 mov #MonoLeftMasks,R1 add R0,R1 mov (R1),(R2) mov #MonoRightMasks,R1 add R0,R1 mov TestVisibleWords,R0 dec R0 asl R0 add R2,R0 mov (R1),(R0) br MonoNextDrawRow MonoMiddleRow: ; D>=16: only left and right sixteen-pixel stripe bands. mov #125252,(R2) ; 0xAAAA, bit0 is left pixel mov TestVisibleWords,R1 dec R1 asl R1 add R2,R1 mov #052525,(R1) ; 0x5555 mirrored at right edge MonoNextDrawRow: inc MonoY br MonoDrawRow MonoDrawDone: rts PC ; Text uses the same Monitor-10 ROM glyphs as the menu, ; but writes directly into TESTBASE using mode-specific row pitch. ; First line: "128x192x1" etc, second line: "MODE 003300". MonoDrawLabels: mov GridRow,R0 asl R0 asl R0 add GridCol,R0 asl R0 mov #MonoLabelPtrs,R1 add R0,R1 mov (R1),R3 mov TestWidthChars,R0 cmp GridRow,#3 beq MonoLen10 sub #9.,R0 br MonoLenReady MonoLen10: sub #10.,R0 MonoLenReady: asr R0 mov R0,MonoTextX mov TestHeight,R0 asr R0 sub #15.,R0 mov R0,MonoTextY jsr PC,MonoPrintString jsr PC,GetSelectedMode mov #MonoCodeLine+10.,R2 mov #6,R3 MonoOctDigit: mov R1,R0 bic #177770,R0 add #'0,R0 movb R0,(R2) dec R2 clc ror R1 clc ror R1 clc ror R1 sob R3,MonoOctDigit mov TestWidthChars,R0 sub #11.,R0 asr R0 mov R0,MonoTextX mov TestHeight,R0 asr R0 add #5,R0 mov R0,MonoTextY mov #MonoCodeLine,R3 jsr PC,MonoPrintString rts PC ; MonoPrintString R3 -> null-terminated ASCII. 8x10 glyphs, ; 1 output byte per scanline, already aligned to 8-pixel cell. MonoPrintString: mov R0,-(SP) mov R3,-(SP) MonoTextNext: movb (R3)+,R0 beq MonoTextDone jsr PC,MonoPrintChar inc MonoTextX br MonoTextNext MonoTextDone: mov (SP)+,R3 mov (SP)+,R0 rts PC MonoPrintChar: mov R0,-(SP) mov R1,-(SP) mov R2,-(SP) mov R3,-(SP) mov R4,-(SP) mov R5,-(SP) mov R0,R5 asl R5 mov R5,R1 asl R5 asl R5 add R1,R5 add #FONTBASE,R5 mov MonoTextY,R4 mov #10.,R3 MonoGlyphRow: mov R4,R0 jsr PC,MonoMapRow add MonoTextX,R2 movb (R5)+,(R2) inc R4 sob R3,MonoGlyphRow mov (SP)+,R5 mov (SP)+,R4 mov (SP)+,R3 mov (SP)+,R2 mov (SP)+,R1 mov (SP)+,R0 rts PC ; Cursor keys change scroll register by exactly one count per keypress. ; H one unit = one 16-bit WORD; wrap H at TestPitchWords, not 256. ; V one unit = one scanline. Software wraps Y modulo TestHeight. MonoKey: jsr PC,ReadKey cmp R0,#K_ESC beq MonoReturn cmp R0,#K_SPACE beq MonoReturn cmp R0,#K_ENTER ; ENTER also exits mono test beq MonoReturn cmp R0,#K_LEFT beq MonoScrollLeft cmp R0,#K_RIGHT beq MonoScrollRight cmp R0,#K_UP beq MonoScrollUp cmp R0,#K_DOWN beq MonoScrollDown br MonoKey MonoScrollLeft: tst TestScrollX bne MonoLeftDec mov TestPitchWords,TestScrollX MonoLeftDec: dec TestScrollX br MonoWriteH MonoScrollRight: inc TestScrollX cmp TestScrollX,TestPitchWords blo MonoWriteH clr TestScrollX MonoWriteH: mov TestScrollX,@#177252 jsr PC,HudDraw jmp MonoKey MonoScrollUp: ; fixed-VRAM status follows normal scroll tst TestScrollY bne MonoUpDec mov TestHeight,TestScrollY ; Y=0 -> H-1 MonoUpDec: dec TestScrollY br MonoWriteV MonoScrollDown: ; no HUD relocation or restoration inc TestScrollY cmp TestScrollY,TestHeight blo MonoWriteV clr TestScrollY ; Y=H -> 0 MonoWriteV: mov TestScrollY,@#177250 jsr PC,HudDraw jmp MonoKey MonoReturn: ; Immediately restore preserved table framebuffer; no redraw. clr @#177250 clr @#177252 mov #SCRBASE,@#177232 mov #AZMODE,@#177230 tst BatchActive beq MonoReturnManual jmp BatchNext MonoReturnManual: jmp GridKey ; ------------------- Stage 3: 2-bpp / four-color video modes ------------------- ; Active for GridRow=4..7 (16 modes). Hardware: pixels packed LSB-first: ; 8 pixels/word, bits 1:0 = leftmost pixel; word stride = 32/64/128. ; 16 one-pixel contours: palette codes 1,2,3 repeating (never code 0). ; Palette: VGA_SHOW22 reads bank 0400..0477 (16*4) based on 177662[11:8]. ; Instead of changing keyboard/video register 177662, set all 16 palette banks. ; Save+restore all 64 palette RAM entries AND palette address register. ; Unlike mono, 1024x768x2 uses 192KiB (98304 words); legacy fill must ; advance high destination-address byte on 64K WORD carry. ; ColorTestStart: jsr PC,GetSelectedMode mov R1,TestMode mov GridCol,R0 asl R0 mov #MonoHeights,R1 add R0,R1 mov (R1),TestHeight mov GridRow,R0 sub #4,R0 asl R0 mov #MonoWidths,R1 add R0,R1 mov (R1),TestWidth mov #32.,TestPitchWords cmp GridRow,#6 bne ColorCheck1024 mov #64.,TestPitchWords ColorCheck1024: cmp GridRow,#7 bne ColorPitchSet mov #128.,TestPitchWords ColorPitchSet: mov TestPitchWords,R0 asl R0 mov R0,TestPitchBytes mov TestWidth,R0 asr R0 asr R0 asr R0 mov R0,TestWidthChars mov R0,TestVisibleWords ; Prepare offscreen. Retain registers restored by mono path. mov @#WIN120,TestSavedWin120 mov @#177270,TestSavedBlitCtrl mov @#177272,TestSavedBlitPage jsr PC,ColorClearBlitter jsr PC,ColorDrawFrames jsr PC,ZoomSetParams jsr PC,ZoomInitLUT ; once per test, prior to scaled labels ; Zoom both axes by display dimensions; preserve baseline 128x192/256. cmp TestWidth,#128. bne ColorLabelsScaled cmp TestHeight,#384. blo ColorLabelsSmall ColorLabelsScaled: jsr PC,ZoomDrawLabels br ColorLabelsReady ColorLabelsSmall: jsr PC,ColorDrawLabels ColorLabelsReady: mov TestSavedBlitCtrl,@#177270 mov TestSavedBlitPage,@#177272 mov TestSavedWin120,@#WIN120 jsr PC,ColorSaveAndSetPalette clr TestScrollX clr TestScrollY clr @#177250 clr @#177252 tst BatchActive beq ColorNormalCommit ; Build the HUD in *OFFSCREEN* RAM; no intermediate screen. jsr PC,HudDrawFull jmp BatchRequestFlip ColorNormalCommit: mov TestBufferBase,@#177232 mov TestMode,@#177230 jsr PC,HudDrawFull ; existing in-test register HUD ColorStartManual:jmp ColorKey ; Fill full PHYSICAL stride. Uses same validated legacy opcode 000 ; command at physical page 2000; 1..4 chunks of <=192 scanlines. ; SRC_HI=0; DST_HI initially octal 22 (1100 * 4000 WORDS/page). ColorClearBlitter: mov #2000,@#WIN120 mov TestBufferHi,@#120000 clr @#120002 clr @#120004 clr @#120006 mov #1,@#120012 clr @#120014 clr @#120016 mov TestHeight,TestRowsLeft clr TestDstLow mov TestBufferHi,TestDstHi ColorClearChunk: mov TestRowsLeft,R0 cmp R0,#192. blo ColorChunkSet beq ColorChunkSet mov #192.,R0 ColorChunkSet: mov R0,TestChunkRows mov #2000,@#WIN120 mov TestDstHi,@#120000 mov TestDstLow,@#120004 mov TestChunkRows,R1 swab R1 mov TestPitchWords,R0 dec R0 bis R1,R0 mov R0,@#120010 mov #2000,@#177272 mov #40001,@#177270 bis #10000,@#177270 ColorBWaitRead: bit #10000,@#177270 bne ColorBWaitRead ColorBWaitDone: bit #100000,@#177270 bne ColorBWaitDone ; Add rows*stride in WORDS, carry into upper address. mov TestChunkRows,R0 mov #5,R1 cmp TestPitchWords,#32. beq ColorShiftStart inc R1 cmp TestPitchWords,#64. beq ColorShiftStart inc R1 ColorShiftStart: asl R0 sob R1,ColorShiftStart add R0,TestDstLow bcc ColorNoCarry inc TestDstHi ColorNoCarry: sub TestChunkRows,TestRowsLeft bne ColorClearChunk rts PC ; Input R0=y, output R2=CPU pointer into 120000 window, R1=page. ; Row pitch 64/128/256 bytes; bank=4096 bytes; no 160/170 window. ColorMapRow: mov R0,R1 mov R0,R2 cmp TestPitchWords,#32. bne ColorMap128 bic #177700,R2 ; y % 64 asl R2 asl R2 asl R2 asl R2 asl R2 asl R2 ; *64 asr R1 asr R1 asr R1 asr R1 asr R1 asr R1 ; /64 br ColorMapCommit ColorMap128: cmp TestPitchWords,#64. bne ColorMap256 bic #177740,R2 ; y % 32 asl R2 asl R2 asl R2 asl R2 asl R2 asl R2 asl R2 ; *128 asr R1 asr R1 asr R1 asr R1 asr R1 ; /32 br ColorMapCommit ColorMap256: bic #177760,R2 ; y % 16 asl R2 asl R2 asl R2 asl R2 asl R2 asl R2 asl R2 asl R2 ; *256 asr R1 asr R1 asr R1 asr R1 ; /16 ColorMapCommit: add TestBufferBase,R1 mov R1,@#WIN120 add #120000,R2 rts PC ; Row D=min(y,height-1-y,16). Top/bottom: fill all *visible* words ; with color C(D), then overlay outer frame colors in 4 edge words. ; Middle: only overlay 4 edge words onto zero-filled background. ; The 17x4 precomputed words avoid slow per-pixel CPU drawing. ColorDrawFrames: clr ColorY ColorDrawRow: mov ColorY,R0 cmp R0,TestHeight bcc ColorDrawDone jsr PC,ColorMapRow mov R2,ColorRowPtr mov ColorY,R0 mov TestHeight,R1 dec R1 sub R0,R1 cmp R0,R1 blo ColorDistReady beq ColorDistReady mov R1,R0 ColorDistReady: cmp R0,#16. blo ColorTopRow mov #16.,R0 br ColorEdges ColorTopRow: mov R0,ColorDist asl R0 mov #ColorFillWords,R1 add R0,R1 mov (R1),R0 mov TestVisibleWords,R1 mov ColorRowPtr,R2 ColorFillLine: mov R0,(R2)+ sob R1,ColorFillLine mov ColorDist,R0 ColorEdges: asl R0 asl R0 asl R0 ; 4 words * 2 bytes mov #ColorEdgeWords,R1 add R0,R1 mov ColorRowPtr,R2 mov (R1)+,(R2)+ mov (R1)+,(R2)+ mov ColorRowPtr,R2 mov TestVisibleWords,R0 sub #2,R0 asl R0 add R0,R2 mov (R1)+,(R2)+ mov (R1)+,(R2)+ inc ColorY jmp ColorDrawRow ColorDrawDone: rts PC ; Draw screen-centered labels in 2bpp with MONIT10 8x10 ROM glyphs. ; One 8-pixel character = ONE 16-bit word, expanded LSB-first. ; Use color index 3 for text; index 0 background behind glyph. ColorDrawLabels: mov GridRow,R0 sub #4,R0 asl R0 asl R0 add GridCol,R0 asl R0 mov #ColorLabelPtrs,R1 add R0,R1 mov (R1),R3 mov TestWidthChars,R0 cmp GridRow,#7 beq ColorLabel10 sub #9.,R0 br ColorLabelSizeOK ColorLabel10: sub #10.,R0 ColorLabelSizeOK: asr R0 mov R0,ColorTextX mov TestHeight,R0 asr R0 sub #15.,R0 mov R0,ColorTextY jsr PC,ColorPrintString ; Reuse the six-digit code formatter from mono module. jsr PC,GetSelectedMode mov #MonoCodeLine+10.,R2 mov #6,R3 ColorOctDigit: mov R1,R0 bic #177770,R0 add #'0,R0 movb R0,(R2) dec R2 clc ror R1 clc ror R1 clc ror R1 sob R3,ColorOctDigit mov TestWidthChars,R0 sub #11.,R0 asr R0 mov R0,ColorTextX mov TestHeight,R0 asr R0 add #5,R0 mov R0,ColorTextY mov #MonoCodeLine,R3 jsr PC,ColorPrintString rts PC ColorPrintString: mov R0,-(SP) mov R3,-(SP) ColorTextNext: movb (R3)+,R0 beq ColorTextDone jsr PC,ColorPrintChar inc ColorTextX br ColorTextNext ColorTextDone: mov (SP)+,R3 mov (SP)+,R0 rts PC ColorPrintChar: mov R0,-(SP) mov R1,-(SP) mov R2,-(SP) mov R3,-(SP) mov R4,-(SP) mov R5,-(SP) mov R0,R5 asl R5 mov R5,R1 asl R5 asl R5 add R1,R5 add #FONTBASE,R5 mov ColorTextY,R4 mov #10.,ColorLineLeft ColorGlyphRow: mov R4,R0 jsr PC,ColorMapRow mov ColorTextX,R0 asl R0 add R0,R2 movb (R5)+,R0 bic #177400,R0 clr R1 mov #3,R3 mov #8.,ColorBitLeft ColorGlyphBit: bit #1,R0 beq ColorGlyphZero bis R3,R1 ColorGlyphZero: asr R0 asl R3 asl R3 dec ColorBitLeft bne ColorGlyphBit mov R1,(R2) inc R4 dec ColorLineLeft bne ColorGlyphRow mov (SP)+,R5 mov (SP)+,R4 mov (SP)+,R3 mov (SP)+,R2 mov (SP)+,R1 mov (SP)+,R0 rts PC ; VGA 2bpp RGB555 palette. 0400..0477 all 16 banks, entries ; 0=dark blue BG, 1=red, 2=green, 3=yellow. We do not touch 177662. ; Restore EXACT prior palette contents; read data 177236 is available ; in VGA_SHOW22. Also restore the address pointer 177234. ColorSaveAndSetPalette: tst BatchActive beq ColorPaletteSaveFirst tst BatchPal2Saved bne ColorPaletteAlreadySet mov #1,BatchPal2Saved ColorPaletteSaveFirst: mov @#177234,ColorOldPalAddr mov #0400,R0 mov #ColorOldPalData,R4 ColorPalSave: mov R0,@#177234 mov @#177236,(R4)+ mov R0,R1 bic #177774,R1 ; index = addr modulo 4 asl R1 add #ColorNewPal,R1 mov (R1),@#177236 inc R0 cmp R0,#0500 blo ColorPalSave mov ColorOldPalAddr,@#177234 ColorPaletteAlreadySet: rts PC ColorRestorePalette: mov #0400,R0 mov #ColorOldPalData,R4 ColorPalRestore: mov R0,@#177234 mov (R4)+,@#177236 inc R0 cmp R0,#0500 blo ColorPalRestore mov ColorOldPalAddr,@#177234 rts PC ; Exactly same key semantics as mono. H unit = 16-bit memory WORD ; (8 pixels at 2bpp), V = one line; Y wraps at TestHeight. ColorKey: jsr PC,ReadKey cmp R0,#K_ESC beq ColorReturn cmp R0,#K_SPACE beq ColorReturn cmp R0,#K_ENTER beq ColorReturn cmp R0,#K_LEFT beq ColorScrollLeft cmp R0,#K_RIGHT beq ColorScrollRight cmp R0,#K_UP beq ColorScrollUp cmp R0,#K_DOWN beq ColorScrollDown br ColorKey ColorScrollLeft: tst TestScrollX bne ColorLeftDec mov TestPitchWords,TestScrollX ColorLeftDec: dec TestScrollX br ColorWriteH ColorScrollRight: inc TestScrollX cmp TestScrollX,TestPitchWords blo ColorWriteH clr TestScrollX ColorWriteH: mov TestScrollX,@#177252 jsr PC,HudDraw jmp ColorKey ColorScrollUp: ; fixed-VRAM status follows normal scroll tst TestScrollY bne ColorUpDec mov TestHeight,TestScrollY ; Y=0 -> H-1 ColorUpDec: dec TestScrollY br ColorWriteV ColorScrollDown: ; no HUD relocation or restoration inc TestScrollY cmp TestScrollY,TestHeight blo ColorWriteV clr TestScrollY ; Y=H -> 0 ColorWriteV: mov TestScrollY,@#177250 jsr PC,HudDraw jmp ColorKey ColorReturn: clr @#177250 clr @#177252 mov #SCRBASE,@#177232 mov #AZMODE,@#177230 jsr PC,ColorRestorePalette tst BatchActive beq ColorReturnManual jmp BatchNext ColorReturnManual: jmp GridKey ; Color test data TestDstHi: .word 0 ColorY: .word 0 ColorDist: .word 0 ColorRowPtr: .word 0 ColorTextX: .word 0 ColorTextY: .word 0 ColorLineLeft: .word 0 ColorBitLeft: .word 0 ColorOldPalAddr:.word 0 ; Exactly 64 words read back from current FPGA palette (0x100..0x13F) ColorOldPalData: .word 000000,000000,000000,000000,000000,000000,000000,000000 .word 000000,000000,000000,000000,000000,000000,000000,000000 .word 000000,000000,000000,000000,000000,000000,000000,000000 .word 000000,000000,000000,000000,000000,000000,000000,000000 .word 000000,000000,000000,000000,000000,000000,000000,000000 .word 000000,000000,000000,000000,000000,000000,000000,000000 .word 000000,000000,000000,000000,000000,000000,000000,000000 .word 000000,000000,000000,000000,000000,000000,000000,000000 ColorNewPal: .word 004112,076410,017752,077706 ; 16 full-row fill words (for D=0..15) and 17*4 edge words. ColorFillWords: .word 052525,125252,177777,052525,125252,177777,052525,125252 .word 177777,052525,125252,177777,052525,125252,177777,052525 ColorEdgeWords: .word 052525,052525,052525,052525 .word 125251,125252,125252,065252 .word 177771,177777,177777,067777 .word 052571,052525,052525,066525 .word 125171,125252,125252,066652 .word 177171,177777,177777,066677 .word 057171,052525,052525,066665 .word 117171,125252,125252,066666 .word 117171,177777,177777,066666 .word 117171,052527,152525,066666 .word 117171,125247,155252,066666 .word 117171,177747,155777,066666 .word 117171,052747,155525,066666 .word 117171,124747,155552,066666 .word 117171,174747,155557,066666 .word 117171,074747,155555,066666 .word 117171,074747,155555,066666 ColorLabelPtrs: .word CT00,CT01,CT02,CT03 .word CT04,CT05,CT06,CT07 .word CT08,CT09,CT10,CT11 .word CT12,CT13,CT14,CT15 CT00: .asciz "128x192x2" CT01: .asciz "128x256x2" CT02: .asciz "128x384x2" CT03: .asciz "128x768x2" CT04: .asciz "256x192x2" CT05: .asciz "256x256x2" CT06: .asciz "256x384x2" CT07: .asciz "256x768x2" CT08: .asciz "512x192x2" CT09: .asciz "512x256x2" CT10: .asciz "512x384x2" CT11: .asciz "512x768x2" CT12: .asciz "1024x192x2" CT13: .asciz "1024x256x2" CT14: .asciz "1024x384x2" CT15: .asciz "1024x768x2" .even ; ------------------- Stage 4: 4-bpp / 16-color video modes ------------------- ; GridRow=8..11, heights from MonoHeights. 16 modes. ; Per 16-bit word: four 4-bit pixels, leftmost pixel in bits 3..0. ; No dark frame: 16 contours use indices 1..15 then 1; 0 is background. ; RGB555 palette addresses 0500..0517 (VGA_SHOW22 mode 3'b010). ; Palette registers are saved and restored on the test's normal exit. ; Every scanline is 32,64,128,or 256 WORDS. Max 1024x768x4 is ; 384KiB/96 AZ 4KiB pages (1100..1237) = 196608 WORDS. ; FourTestStart: jsr PC,GetSelectedMode mov R1,TestMode mov GridCol,R0 asl R0 mov #MonoHeights,R1 add R0,R1 mov (R1),TestHeight mov GridRow,R0 sub #8.,R0 asl R0 mov #MonoWidths,R1 add R0,R1 mov (R1),TestWidth mov TestWidth,R0 asr R0 asr R0 ; four pixels per word mov R0,TestPitchWords mov R0,TestVisibleWords asl R0 mov R0,TestPitchBytes mov TestWidth,R0 asr R0 asr R0 asr R0 mov R0,TestWidthChars mov @#WIN120,TestSavedWin120 mov @#177270,TestSavedBlitCtrl mov @#177272,TestSavedBlitPage jsr PC,FourClearBlitter jsr PC,FourDrawFrames jsr PC,ZoomSetParams jsr PC,ZoomInitLUT ; once per test, prior to scaled labels ; Zoom both axes by display dimensions; preserve baseline 128x192/256. cmp TestWidth,#128. bne FourLabelsScaled cmp TestHeight,#384. blo FourLabelsSmall FourLabelsScaled: jsr PC,ZoomDrawLabels br FourLabelsReady FourLabelsSmall: jsr PC,FourDrawLabels FourLabelsReady: mov TestSavedBlitCtrl,@#177270 mov TestSavedBlitPage,@#177272 mov TestSavedWin120,@#WIN120 jsr PC,FourSaveAndSetPalette clr TestScrollX clr TestScrollY clr @#177250 clr @#177252 tst BatchActive beq FourNormalCommit ; Build the HUD in *OFFSCREEN* RAM; no intermediate screen. jsr PC,HudDrawFull jmp BatchRequestFlip FourNormalCommit: mov TestBufferBase,@#177232 mov TestMode,@#177230 jsr PC,HudDrawFull ; existing in-test register HUD FourStartManual:jmp FourKey ; Legacy command 000, max 192 scanlines per command. Unlike 1bpp, ; the high address byte is updated as 16-bit DST offset wraps. ; A single packet may internally cross 64K words (supported by blitter). FourClearBlitter: mov #2000,@#WIN120 mov TestBufferHi,@#120000 ; SRC_HI=0, DST_HI=octal 22 clr @#120002 clr @#120004 clr @#120006 ; opcode 000: constant fill mov #1,@#120012 clr @#120014 clr @#120016 mov TestHeight,TestRowsLeft clr TestDstLow mov TestBufferHi,TestDstHi FourClearChunk: mov TestRowsLeft,R0 cmp R0,#192. blo FourChunkSet beq FourChunkSet mov #192.,R0 FourChunkSet: mov R0,TestChunkRows mov #2000,@#WIN120 mov TestDstHi,@#120000 mov TestDstLow,@#120004 mov TestChunkRows,R1 swab R1 mov TestPitchWords,R0 dec R0 bis R1,R0 mov R0,@#120010 mov #2000,@#177272 mov #40001,@#177270 bis #10000,@#177270 FourBWaitRead: bit #10000,@#177270 bne FourBWaitRead FourBWaitDone: bit #100000,@#177270 bne FourBWaitDone ; Advance DST by chunkRows*pitch WORDS. mov TestChunkRows,R0 mov #5,R1 cmp TestPitchWords,#32. beq FourShiftStart inc R1 cmp TestPitchWords,#64. beq FourShiftStart inc R1 cmp TestPitchWords,#128. beq FourShiftStart inc R1 FourShiftStart: asl R0 sob R1,FourShiftStart add R0,TestDstLow bcc FourNoCarry inc TestDstHi FourNoCarry: sub TestChunkRows,TestRowsLeft bne FourClearChunk rts PC ; R0: scanline Y, R2: CPU pointer into mapped 120000 window. ; All supported pitches divide the 4KiB AZ page without straddling. FourMapRow: mov R3,-(SP) mov R4,-(SP) mov R0,R1 mov R0,R2 cmp TestPitchWords,#32. bne FourMap128 bic #177700,R2 ; y mod 64 mov #6,R3 mov #6,R4 br FourMapShift FourMap128: cmp TestPitchWords,#64. bne FourMap256 bic #177740,R2 ; y mod 32 mov #7,R3 mov #5,R4 br FourMapShift FourMap256: cmp TestPitchWords,#128. bne FourMap512 bic #177760,R2 ; y mod 16 mov #8.,R3 mov #4,R4 br FourMapShift FourMap512: bic #177770,R2 ; y mod 8 mov #9.,R3 mov #3,R4 FourMapShift: asl R2 sob R3,FourMapShift FourMapPage: asr R1 sob R4,FourMapPage add TestBufferBase,R1 mov R1,@#WIN120 add #120000,R2 mov (SP)+,R4 mov (SP)+,R3 rts PC ; FourEdgeWords stores [4 left words + 4 right words] for D=0..16. ; At rows near top/bottom: fill entire visible row with repeated C(D), ; then replace 4-word edge segments. In the middle only edges are drawn. FourDrawFrames: clr FourY FourDrawRow: mov FourY,R0 cmp R0,TestHeight bcc FourDrawDone jsr PC,FourMapRow mov R2,FourRowPtr mov FourY,R0 mov TestHeight,R1 dec R1 sub R0,R1 cmp R0,R1 blo FourDistReady beq FourDistReady mov R1,R0 FourDistReady: cmp R0,#16. blo FourTopRow mov #16.,R0 br FourEdges FourTopRow: mov R0,FourDist asl R0 mov #FourFillWords,R1 add R0,R1 mov (R1),R0 mov TestVisibleWords,R1 mov FourRowPtr,R2 FourFillLine: mov R0,(R2)+ sob R1,FourFillLine mov FourDist,R0 FourEdges: asl R0 asl R0 asl R0 asl R0 ; 8 words * 2 bytes = 16 mov #FourEdgeWords,R1 add R0,R1 mov FourRowPtr,R2 mov #4,R3 FourLeftWord: mov (R1)+,(R2)+ sob R3,FourLeftWord mov FourRowPtr,R2 mov TestVisibleWords,R0 sub #4,R0 asl R0 add R0,R2 mov #4,R3 FourRightWord: mov (R1)+,(R2)+ sob R3,FourRightWord inc FourY jmp FourDrawRow FourDrawDone: rts PC ; Two centered lines: WIDTHxHEIGHTx4 and MODE xxxxxx. ; Monitor-10 glyphs are 8x10, decoded directly into 4bpp pixels. FourDrawLabels: mov GridRow,R0 sub #8.,R0 asl R0 asl R0 add GridCol,R0 asl R0 mov #FourLabelPtrs,R1 add R0,R1 mov (R1),R3 mov TestWidthChars,R0 cmp GridRow,#11. beq FourLabel10 sub #9.,R0 br FourLabelOK FourLabel10: sub #10.,R0 FourLabelOK: asr R0 mov R0,FourTextX mov TestHeight,R0 asr R0 sub #15.,R0 mov R0,FourTextY jsr PC,FourPrintString jsr PC,GetSelectedMode mov #MonoCodeLine+10.,R2 mov #6,R3 FourOctDigit: mov R1,R0 bic #177770,R0 add #'0,R0 movb R0,(R2) dec R2 clc ror R1 clc ror R1 clc ror R1 sob R3,FourOctDigit mov TestWidthChars,R0 sub #11.,R0 asr R0 mov R0,FourTextX mov TestHeight,R0 asr R0 add #5,R0 mov R0,FourTextY mov #MonoCodeLine,R3 jsr PC,FourPrintString rts PC FourPrintString: mov R0,-(SP) mov R3,-(SP) FourTextNext: movb (R3)+,R0 beq FourTextDone jsr PC,FourPrintChar inc FourTextX br FourTextNext FourTextDone: mov (SP)+,R3 mov (SP)+,R0 rts PC ; 8 glyph pixels = two 16-bit words, four 4-bit nibbles per word. ; FourFontNibble expands a four-bit font fragment into 4 RGB indices. FourPrintChar: mov R0,-(SP) mov R1,-(SP) mov R2,-(SP) mov R3,-(SP) mov R4,-(SP) mov R5,-(SP) mov R0,R5 asl R5 mov R5,R1 asl R5 asl R5 add R1,R5 add #FONTBASE,R5 mov FourTextY,R4 mov #10.,FourLineLeft FourGlyphRow: mov R4,R0 jsr PC,FourMapRow mov FourTextX,R0 asl R0 asl R0 ; two words / four bytes per glyph add R0,R2 movb (R5)+,R0 bic #177400,R0 mov R0,R1 bic #177760,R1 ; low nibble asl R1 add #FourFontNibble,R1 mov (R1),(R2)+ asr R0 asr R0 asr R0 asr R0 bic #177760,R0 ; high nibble asl R0 add #FourFontNibble,R0 mov (R0),(R2) inc R4 dec FourLineLeft bne FourGlyphRow mov (SP)+,R5 mov (SP)+,R4 mov (SP)+,R3 mov (SP)+,R2 mov (SP)+,R1 mov (SP)+,R0 rts PC ; 0500..0517 = 16 entries of 4bpp palette in VGA_SHOW22. FourSaveAndSetPalette: tst BatchActive beq FourPaletteSaveFirst tst BatchPal4Saved bne FourPaletteAlreadySet mov #1,BatchPal4Saved FourPaletteSaveFirst: mov @#177234,FourOldPalAddr mov #0500,R0 mov #FourOldPalData,R4 FourPalSave: mov R0,@#177234 mov @#177236,(R4)+ mov R0,R1 sub #0500,R1 asl R1 add #FourNewPal,R1 mov (R1),@#177236 inc R0 cmp R0,#0520 blo FourPalSave mov FourOldPalAddr,@#177234 FourPaletteAlreadySet: rts PC FourRestorePalette: mov #0500,R0 mov #FourOldPalData,R4 FourPalRestore: mov R0,@#177234 mov (R4)+,@#177236 inc R0 cmp R0,#0520 blo FourPalRestore mov FourOldPalAddr,@#177234 rts PC ; Same key semantics as the hardware-tested mono/2bpp modules. FourKey: jsr PC,ReadKey cmp R0,#K_ESC beq FourReturn cmp R0,#K_SPACE beq FourReturn cmp R0,#K_ENTER beq FourReturn cmp R0,#K_LEFT beq FourScrollLeft cmp R0,#K_RIGHT beq FourScrollRight cmp R0,#K_UP beq FourScrollUp cmp R0,#K_DOWN beq FourScrollDown br FourKey FourScrollLeft: tst TestScrollX bne FourLeftDec mov TestPitchWords,TestScrollX FourLeftDec: dec TestScrollX br FourWriteH FourScrollRight: inc TestScrollX cmp TestScrollX,TestPitchWords blo FourWriteH clr TestScrollX FourWriteH: mov TestScrollX,@#177252 jsr PC,HudDraw jmp FourKey FourScrollUp: ; fixed-VRAM status follows normal scroll tst TestScrollY bne FourUpDec mov TestHeight,TestScrollY ; Y=0 -> H-1 FourUpDec: dec TestScrollY br FourWriteV FourScrollDown: ; no HUD relocation or restoration inc TestScrollY cmp TestScrollY,TestHeight blo FourWriteV clr TestScrollY ; Y=H -> 0 FourWriteV: mov TestScrollY,@#177250 jsr PC,HudDraw jmp FourKey FourReturn: clr @#177250 clr @#177252 mov #SCRBASE,@#177232 mov #AZMODE,@#177230 jsr PC,FourRestorePalette tst BatchActive beq FourReturnManual jmp BatchNext FourReturnManual: jmp GridKey ; New 4bpp module data --------------------------------------------------- FourY: .word 0 FourDist: .word 0 FourRowPtr: .word 0 FourTextX: .word 0 FourTextY: .word 0 FourLineLeft: .word 0 FourOldPalAddr: .word 0 FourOldPalData: .word 0,0,0,0,0,0,0,0 .word 0,0,0,0,0,0,0,0 ; High-contrast alternating colors. 0=dark blue background. ; Indices 1..15: red green yellow blue orange purple cyan magenta ; lime skyblue coral teal pink WHITE mint. 14 kept WHITE for text. ; Only palette data changes: frame pixel indices and font masks unchanged. FourNewPal: .word 000047,076143,007745,077740 .word 014337,076600,044137,001577 .word 076135,051742,000777,077112 .word 001765,076524,077777,035765 FourFontNibble: .word 000000,000016,000340,000356 .word 007000,007016,007340,007356 .word 160000,160016,160340,160356 .word 167000,167016,167340,167356 FourFillWords: .word 010421,021042,031463,042104,052525,063146,073567,104210 .word 114631,125252,135673,146314,156735,167356,177777,010421 FourEdgeWords: .word 010421,010421,010421,010421,010421,010421,010421,010421 .word 021041,021042,021042,021042,021042,021042,021042,011042 .word 031441,031463,031463,031463,031463,031463,031463,011063 .word 041441,042104,042104,042104,042104,042104,042104,011064 .word 041441,052525,052525,052525,052525,052525,052525,011064 .word 041441,063145,063146,063146,063146,063146,053146,011064 .word 041441,073545,073567,073567,073567,073567,053167,011064 .word 041441,103545,104210,104210,104210,104210,053170,011064 .word 041441,103545,114631,114631,114631,114631,053170,011064 .word 041441,103545,125251,125252,125252,115252,053170,011064 .word 041441,103545,135651,135673,135673,115273,053170,011064 .word 041441,103545,145651,146314,146314,115274,053170,011064 .word 041441,103545,145651,156735,156735,115274,053170,011064 .word 041441,103545,145651,167355,157356,115274,053170,011064 .word 041441,103545,145651,177755,157377,115274,053170,011064 .word 041441,103545,145651,017755,157361,115274,053170,011064 .word 041441,103545,145651,017755,157361,115274,053170,011064 FourLabelPtrs: .word FT00,FT01,FT02,FT03 .word FT04,FT05,FT06,FT07 .word FT08,FT09,FT10,FT11 .word FT12,FT13,FT14,FT15 FT00: .asciz "128x192x4" FT01: .asciz "128x256x4" FT02: .asciz "128x384x4" FT03: .asciz "128x768x4" FT04: .asciz "256x192x4" FT05: .asciz "256x256x4" FT06: .asciz "256x384x4" FT07: .asciz "256x768x4" FT08: .asciz "512x192x4" FT09: .asciz "512x256x4" FT10: .asciz "512x384x4" FT11: .asciz "512x768x4" FT12: .asciz "1024x192x4" FT13: .asciz "1024x256x4" FT14: .asciz "1024x384x4" FT15: .asciz "1024x768x4" .even ; ==================== STAGE 5: 8 BITS / 256 COLORS ========================== ; GridRow=12..14, GridCol=0..3. 12 single-layer video modes. ; Two 8-bit pixels per word: low byte is LEFT pixel, high byte is RIGHT. ; 128/256/512 px gives 64/128/256 16-bit words per scanline. ; Maximum: 512x768x8 = 393216 bytes = 96 x 4KiB VRAM pages. ; Frame colors: indices 1..16, index 0 is dark-blue background. ; Indices 0..17 in the 256-color palette are saved and restored. ; EightTestStart: jsr PC,GetSelectedMode mov R1,TestMode mov GridCol,R0 asl R0 mov #MonoHeights,R1 add R0,R1 mov (R1),TestHeight mov GridRow,R0 sub #12.,R0 asl R0 mov #MonoWidths,R1 add R0,R1 mov (R1),TestWidth mov TestWidth,R0 asr R0 ; 2 pixels/16-bit word mov R0,TestPitchWords mov R0,TestVisibleWords asl R0 mov R0,TestPitchBytes mov TestWidth,R0 asr R0 asr R0 asr R0 mov R0,TestWidthChars mov @#WIN120,TestSavedWin120 mov @#177270,TestSavedBlitCtrl mov @#177272,TestSavedBlitPage jsr PC,EightClearBlitter jsr PC,EightDrawFrames jsr PC,ZoomSetParams jsr PC,ZoomInitLUT jsr PC,ZoomDrawLabels mov TestSavedBlitCtrl,@#177270 mov TestSavedBlitPage,@#177272 mov TestSavedWin120,@#WIN120 jsr PC,EightSaveAndSetPalette clr TestScrollX clr TestScrollY clr @#177250 clr @#177252 tst BatchActive beq EightNormalCommit ; Build the HUD in *OFFSCREEN* RAM; no intermediate screen. jsr PC,HudDrawFull jmp BatchRequestFlip EightNormalCommit: mov TestBufferBase,@#177232 mov TestMode,@#177230 jsr PC,HudDrawFull ; existing in-test register HUD EightStartManual:jmp EightKey ; Legacy BLITTER command 000, 192-row maximum per packet. ; SrcHi zero, DstHi octal 022 = physical start page 1100. ; Each packet is 7 words and is executed in manual mode. ; Carry when the 16-bit word-offset wraps to the next high address. EightClearBlitter: mov #2000,@#WIN120 mov TestBufferHi,@#120000 clr @#120002 clr @#120004 clr @#120006 mov #1,@#120012 clr @#120014 clr @#120016 mov TestHeight,TestRowsLeft clr TestDstLow mov TestBufferHi,TestDstHi EightClearChunk: mov TestRowsLeft,R0 cmp R0,#192. blo EightChunkSet beq EightChunkSet mov #192.,R0 EightChunkSet: mov R0,TestChunkRows mov #2000,@#WIN120 mov TestDstHi,@#120000 mov TestDstLow,@#120004 mov TestChunkRows,R1 swab R1 mov TestPitchWords,R0 dec R0 bis R1,R0 mov R0,@#120010 mov #2000,@#177272 mov #40001,@#177270 bis #10000,@#177270 EightBWaitRead: bit #10000,@#177270 bne EightBWaitRead EightBWaitDone: bit #100000,@#177270 bne EightBWaitDone ; offset += TestChunkRows*TestPitchWords mov TestChunkRows,R0 mov #6,R1 cmp TestPitchWords,#64. beq EightShiftStart inc R1 cmp TestPitchWords,#128. beq EightShiftStart inc R1 EightShiftStart:asl R0 sob R1,EightShiftStart add R0,TestDstLow bcc EightNoCarry inc TestDstHi EightNoCarry: sub TestChunkRows,TestRowsLeft bne EightClearChunk rts PC ; Input R0=Y; maps 120000 CPU window onto its 4-KiB AZ page. ; The 64/128/256 words per scanline divide the page exactly. ; 64 words=128B => 32 rows/page, 128=>16, 256=>8. EightMapRow: mov R3,-(SP) mov R4,-(SP) mov R0,R1 mov R0,R2 cmp TestPitchWords,#64. bne EightMap256 bic #177740,R2 ; y modulo 32 mov #7,R3 ; byte offset = (y%32)*128 mov #5,R4 ; page = y/32 br EightMapShift EightMap256: cmp TestPitchWords,#128. bne EightMap512 bic #177760,R2 ; y modulo 16 mov #8.,R3 mov #4,R4 br EightMapShift EightMap512: bic #177770,R2 ; y modulo 8 mov #9.,R3 mov #3,R4 EightMapShift: asl R2 sob R3,EightMapShift EightMapPage: asr R1 sob R4,EightMapPage add TestBufferBase,R1 mov R1,@#WIN120 add #120000,R2 mov (SP)+,R4 mov (SP)+,R3 rts PC ; 16 single-pixel colored contours. Rows D<16: fill with C(D), ; then patch 16 pixels at either edge to form perpendicular contours. ; Middle rows: BLITTER zero background; only 8 words at each edge. EightDrawFrames:clr EightY EightDrawRow: mov EightY,R0 cmp R0,TestHeight bcc EightDrawDone jsr PC,EightMapRow mov R2,EightRowPtr mov EightY,R0 mov TestHeight,R1 dec R1 sub R0,R1 cmp R0,R1 blo EightDistReady beq EightDistReady mov R1,R0 EightDistReady:cmp R0,#16. blo EightTopRow mov #16.,R0 br EightEdges EightTopRow: mov R0,EightDist asl R0 mov #EightFillWords,R1 add R0,R1 mov (R1),R0 mov TestVisibleWords,R1 mov EightRowPtr,R2 EightFillLine: mov R0,(R2)+ sob R1,EightFillLine mov EightDist,R0 EightEdges: ; edge table: 16 words per D (8 left + 8 right) mov R0,R1 asl R1 asl R1 asl R1 asl R1 asl R1 ; D*32 bytes add #EightEdgeWords,R1 mov EightRowPtr,R2 mov #8.,R3 EightLeftWord: mov (R1)+,(R2)+ sob R3,EightLeftWord mov EightRowPtr,R2 mov TestVisibleWords,R0 sub #8.,R0 asl R0 add R0,R2 mov #8.,R3 EightRightWord:mov (R1)+,(R2)+ sob R3,EightRightWord inc EightY jmp EightDrawRow EightDrawDone: rts PC ; Palette: only indices 0..17 altered; all 18 original RGB555 entries saved. EightSaveAndSetPalette: tst BatchActive beq EightPaletteSaveFirst tst BatchPal8Saved bne EightPaletteAlreadySet mov #1,BatchPal8Saved EightPaletteSaveFirst: mov @#177234,EightOldPalAddr clr R0 mov #EightOldPalData,R4 mov #EightNewPal,R5 EightPalSave: mov R0,@#177234 mov @#177236,(R4)+ mov (R5)+,@#177236 inc R0 cmp R0,#18. blo EightPalSave mov EightOldPalAddr,@#177234 EightPaletteAlreadySet: rts PC EightRestorePalette: clr R0 mov #EightOldPalData,R4 EightPalRestore:mov R0,@#177234 mov (R4)+,@#177236 inc R0 cmp R0,#18. blo EightPalRestore mov EightOldPalAddr,@#177234 rts PC ; Key semantics exactly as 1/2/4bpp: arrows step per 16-bit WORD or ; scanline, 0.5s delay + 20Hz repeat, ENTER/SPACE/KT exits to matrix. EightKey: jsr PC,ReadKey cmp R0,#K_ESC beq EightReturn cmp R0,#K_SPACE beq EightReturn cmp R0,#K_ENTER beq EightReturn cmp R0,#K_LEFT beq EightScrollLeft cmp R0,#K_RIGHT beq EightScrollRight cmp R0,#K_UP beq EightScrollUp cmp R0,#K_DOWN beq EightScrollDown br EightKey EightScrollLeft: tst TestScrollX bne EightLeftDec mov TestPitchWords,TestScrollX EightLeftDec: dec TestScrollX br EightWriteH EightScrollRight: inc TestScrollX cmp TestScrollX,TestPitchWords blo EightWriteH clr TestScrollX EightWriteH: mov TestScrollX,@#177252 jsr PC,HudDraw jmp EightKey EightScrollUp: tst TestScrollY bne EightUpDec mov TestHeight,TestScrollY EightUpDec: dec TestScrollY br EightWriteV EightScrollDown: inc TestScrollY cmp TestScrollY,TestHeight blo EightWriteV clr TestScrollY EightWriteV: mov TestScrollY,@#177250 jsr PC,HudDraw jmp EightKey EightReturn: clr @#177250 clr @#177252 mov #SCRBASE,@#177232 mov #AZMODE,@#177230 jsr PC,EightRestorePalette tst BatchActive beq EightReturnManual jmp BatchNext EightReturnManual: jmp GridKey EightY: .word 0 EightDist: .word 0 EightRowPtr: .word 0 EightOldPalAddr:.word 0 EightOldPalData: .word 0,0,0,0,0,0,0,0,0 .word 0,0,0,0,0,0,0,0,0 EightNewPal: .word 000047, 076143, 007745, 077740, 014337, 076600 .word 044137, 001577, 076135, 051742, 000777, 077112 .word 001765, 076524, 077777, 035765, 073017, 077777 EightFillWords: .word 000401, 001002, 001403, 002004, 002405, 003006, 003407, 004010 .word 004411, 005012, 005413, 006014, 006415, 007016, 007417, 010020 EightEdgeWords: .word 000401, 000401, 000401, 000401, 000401, 000401, 000401, 000401 ; D=0 left .word 000401, 000401, 000401, 000401, 000401, 000401, 000401, 000401 ; D=0 right .word 001001, 001002, 001002, 001002, 001002, 001002, 001002, 001002 ; D=1 left .word 001002, 001002, 001002, 001002, 001002, 001002, 001002, 000402 ; D=1 right .word 001001, 001403, 001403, 001403, 001403, 001403, 001403, 001403 ; D=2 left .word 001403, 001403, 001403, 001403, 001403, 001403, 001403, 000402 ; D=2 right .word 001001, 002003, 002004, 002004, 002004, 002004, 002004, 002004 ; D=3 left .word 002004, 002004, 002004, 002004, 002004, 002004, 001404, 000402 ; D=3 right .word 001001, 002003, 002405, 002405, 002405, 002405, 002405, 002405 ; D=4 left .word 002405, 002405, 002405, 002405, 002405, 002405, 001404, 000402 ; D=4 right .word 001001, 002003, 003005, 003006, 003006, 003006, 003006, 003006 ; D=5 left .word 003006, 003006, 003006, 003006, 003006, 002406, 001404, 000402 ; D=5 right .word 001001, 002003, 003005, 003407, 003407, 003407, 003407, 003407 ; D=6 left .word 003407, 003407, 003407, 003407, 003407, 002406, 001404, 000402 ; D=6 right .word 001001, 002003, 003005, 004007, 004010, 004010, 004010, 004010 ; D=7 left .word 004010, 004010, 004010, 004010, 003410, 002406, 001404, 000402 ; D=7 right .word 001001, 002003, 003005, 004007, 004411, 004411, 004411, 004411 ; D=8 left .word 004411, 004411, 004411, 004411, 003410, 002406, 001404, 000402 ; D=8 right .word 001001, 002003, 003005, 004007, 005011, 005012, 005012, 005012 ; D=9 left .word 005012, 005012, 005012, 004412, 003410, 002406, 001404, 000402 ; D=9 right .word 001001, 002003, 003005, 004007, 005011, 005413, 005413, 005413 ; D=10 left .word 005413, 005413, 005413, 004412, 003410, 002406, 001404, 000402 ; D=10 right .word 001001, 002003, 003005, 004007, 005011, 006013, 006014, 006014 ; D=11 left .word 006014, 006014, 005414, 004412, 003410, 002406, 001404, 000402 ; D=11 right .word 001001, 002003, 003005, 004007, 005011, 006013, 006415, 006415 ; D=12 left .word 006415, 006415, 005414, 004412, 003410, 002406, 001404, 000402 ; D=12 right .word 001001, 002003, 003005, 004007, 005011, 006013, 007015, 007016 ; D=13 left .word 007016, 006416, 005414, 004412, 003410, 002406, 001404, 000402 ; D=13 right .word 001001, 002003, 003005, 004007, 005011, 006013, 007015, 007417 ; D=14 left .word 007417, 006416, 005414, 004412, 003410, 002406, 001404, 000402 ; D=14 right .word 001001, 002003, 003005, 004007, 005011, 006013, 007015, 010017 ; D=15 left .word 007420, 006416, 005414, 004412, 003410, 002406, 001404, 000402 ; D=15 right .word 001001, 002003, 003005, 004007, 005011, 006013, 007015, 010017 ; D=16 left .word 007420, 006416, 005414, 004412, 003410, 002406, 001404, 000402 ; D=16 right EightLabelPtrs: .word ET00,ET01,ET02,ET03 .word ET04,ET05,ET06,ET07 .word ET08,ET09,ET10,ET11 ET00: .asciz "128x192x8" ET01: .asciz "128x256x8" ET02: .asciz "128x384x8" ET03: .asciz "128x768x8" ET04: .asciz "256x192x8" ET05: .asciz "256x256x8" ET06: .asciz "256x384x8" ET07: .asciz "256x768x8" ET08: .asciz "512x192x8" ET09: .asciz "512x256x8" ET10: .asciz "512x384x8" ET11: .asciz "512x768x8" .even ; ------------------ Fixed-VRAM status, physically scaled ------------------ ; Labels are located at Y=H/4 in VRAM and scroll with the picture. ; Read real 177250/177252 values after each key; only 6 digits repaint. ; Scale 8x10 ROM glyphs INDEPENDENTLY: X=width/128, Y=height/192, ; with Y=1 at 192/256. 128 wide has 4 compact lines. HudDrawFull: clr HudDigitsOnly br HudDrawCore HudDraw: mov #1,HudDigitsOnly HudDrawCore: mov @#WIN120,-(SP) mov @#177250,R0 mov #HudTextV+13.,R2 jsr PC,HudFmtOct mov @#177252,R0 mov #HudTextH+13.,R2 jsr PC,HudFmtOct jsr PC,ZoomSetParams ; Status starts near a quarter of the logical roll. mov TestHeight,R0 asr R0 asr R0 mov R0,HudFixedY ; Scanline spacing = 10 x ZoomScaleY (10/20/40). mov #10.,R0 mov ZoomScaleY,R1 HudStepCalc: cmp R1,#1 beq HudStepReady asl R0 asr R1 br HudStepCalc HudStepReady: mov R0,HudStepY tst HudDigitsOnly beq HudDrawFullLines jsr PC,HudUpdateDigits br HudEnd HudDrawFullLines: cmp TestWidth,#128. beq HudNarrow tst HudDigitsOnly beq HudWideFull mov #HudTextV+7,R3 br HudWideTop HudWideFull: mov #HudTextV,R3 HudWideTop: mov HudFixedY,R1 jsr PC,HudPutString tst HudDigitsOnly beq HudWideFull2 mov #HudTextH+7,R3 br HudWideBottom HudWideFull2: mov #HudTextH,R3 HudWideBottom: mov HudFixedY,R1 add HudStepY,R1 jsr PC,HudPutString br HudEnd HudNarrow: ; 4 centred short lines, no collision with 16px frames. tst HudDigitsOnly bne HudNarrowDigits mov #HudRegV,R3 mov HudFixedY,R1 sub HudStepY,R1 jsr PC,HudPutString mov #HudRegH,R3 mov HudFixedY,R1 add HudStepY,R1 jsr PC,HudPutString HudNarrowDigits: mov #HudTextV+7,R3 mov HudFixedY,R1 jsr PC,HudPutString mov #HudTextH+7,R3 mov HudFixedY,R1 mov HudStepY,R0 asl R0 add R0,R1 jsr PC,HudPutString HudEnd: tst HudDigitsOnly bne HudRestoreWindow jsr PC,HudRememberDigits HudRestoreWindow: mov (SP)+,@#WIN120 rts PC ; Fast path: compare the current six octal ASCII digits with last draw. ; Only changed GLYPHS are rewritten (typically one per cursor repeat). ; The drawing continues to use the current X/Y zoom and fixed VRAM Y. HudRememberDigits: mov #HudTextV+7,R4 mov #HudOldV,R5 mov #6,R3 HudRememberV: movb (R4)+,(R5)+ sob R3,HudRememberV mov #HudTextH+7,R4 mov #HudOldH,R5 mov #6,R3 HudRememberH: movb (R4)+,(R5)+ sob R3,HudRememberH rts PC HudUpdateDigits: mov #HudTextV+7,HudNewPtr mov #HudOldV,HudOldPtr mov HudFixedY,HudLineY jsr PC,HudDiffOneLine mov #HudTextH+7,HudNewPtr mov #HudOldH,HudOldPtr mov HudFixedY,R0 add HudStepY,R0 mov R0,HudLineY jsr PC,HudDiffOneLine rts PC HudDiffOneLine: clr HudDigitIndex HudDiffLoop: mov HudNewPtr,R4 mov HudOldPtr,R5 movb (R4),R0 cmpb R0,(R5) beq HudDiffNext movb R0,(R5) movb R0,HudOneChar mov HudLineY,ZoomStartY mov HudDigitIndex,ZoomDigitIndex mov #1,ZoomHudSingle mov #HudOneChar,R3 jsr PC,ZoomDrawString clr ZoomHudSingle HudDiffNext: inc HudNewPtr inc HudOldPtr inc HudDigitIndex cmp HudDigitIndex,#6 blo HudDiffLoop rts PC HudOldV: .byte 0,0,0,0,0,0 HudOldH: .byte 0,0,0,0,0,0 HudOneChar: .byte 0,0 .even HudNewPtr: .word 0 HudOldPtr: .word 0 HudLineY: .word 0 HudDigitIndex: .word 0 ; Input R1=VRAM scanline, R3=null-terminated string. Text horizontally ; centred using ZoomScaleX, including when only six digits repaint. HudPutString: mov R1,ZoomStartY clr ZoomHudDigits cmp TestWidth,#128. beq HudPutDirect tst HudDigitsOnly beq HudPutDirect mov #1,ZoomHudDigits HudPutDirect: jsr PC,ZoomDrawString rts PC ; R0=word, R2=one byte past last of six octal digits. HudFmtOct: mov R3,-(SP) mov #6,R3 HudFmtNext: mov R0,R1 bic #177770,R1 add #'0,R1 movb R1,-(R2) clc ror R0 clc ror R0 clc ror R0 sob R3,HudFmtNext mov (SP)+,R3 rts PC HudTextV: .asciz "177250=000000" HudTextH: .asciz "177252=000000" HudRegV: .asciz "177250=" HudRegH: .asciz "177252=" .even HudDigitsOnly: .word 0 HudFixedY: .word 0 HudStepY: .word 0 ; ----------------- Physical-aspect-corrected test text -------------------- ; BK10 ROM 8x10. Pixel enlargement X and Y are independent. ; X: 128=>1, 256=>2, 512=>4, 1024=>8; ; Y: 192/256=>1, 384=>2, 768=>4. ; This keeps onscreen font dimensions similar for all mode geometries. ; The row buffer holds up to 8*8*4=256 bits (16 words). ZoomSetParams: mov #1,ZoomScaleX cmp TestWidth,#128. beq ZoomWidthReady mov #2,ZoomScaleX cmp TestWidth,#256. beq ZoomWidthReady mov #4,ZoomScaleX cmp TestWidth,#512. beq ZoomWidthReady mov #8.,ZoomScaleX ZoomWidthReady: mov #1,ZoomScaleY cmp TestHeight,#384. blo ZoomHeightReady mov #2,ZoomScaleY cmp TestHeight,#768. bne ZoomHeightReady mov #4,ZoomScaleY ZoomHeightReady:mov #1,ZoomBPP cmp GridRow,#4 blo ZoomParamsReady mov #2,ZoomBPP cmp GridRow,#8. blo ZoomParamsReady mov #4,ZoomBPP cmp GridRow,#12. blo ZoomParamsReady mov #8.,ZoomBPP ZoomParamsReady:rts PC ZoomDrawLabels: jsr PC,ZoomSetParams mov GridRow,R0 cmp R0,#4 blo ZoomLabelMono cmp R0,#8. blo ZoomLabelTwo cmp R0,#12. blo ZoomLabelFour sub #12.,R0 mov #EightLabelPtrs,R1 br ZoomLabelIndex ZoomLabelFour: sub #8.,R0 mov #FourLabelPtrs,R1 br ZoomLabelIndex ZoomLabelTwo: sub #4,R0 mov #ColorLabelPtrs,R1 br ZoomLabelIndex ZoomLabelMono: mov #MonoLabelPtrs,R1 ZoomLabelIndex: asl R0 asl R0 add GridCol,R0 asl R0 add R0,R1 mov (R1),R3 mov TestHeight,R0 asr R0 mov ZoomScaleY,R1 mov #15.,R2 ZoomTopYLoop: sub R1,R0 sob R2,ZoomTopYLoop mov R0,ZoomStartY jsr PC,ZoomDrawString jsr PC,GetSelectedMode mov R1,R0 mov #MonoCodeLine+11.,R2 jsr PC,HudFmtOct mov TestHeight,R0 asr R0 mov ZoomScaleY,R1 mov #5,R2 ZoomBottomYLoop:add R1,R0 sob R2,ZoomBottomYLoop mov R0,ZoomStartY mov #MonoCodeLine,R3 jsr PC,ZoomDrawString rts PC ; R3 -> ASCII string; ZoomStartY is physical scanline. ; Screen X position is centred according to expanded string width. ZoomDrawString: mov R3,ZoomStringPtr clr ZoomLen ZoomLengthLoop:movb (R3)+,R0 beq ZoomLengthDone inc ZoomLen br ZoomLengthLoop ZoomLengthDone:mov ZoomLen,R0 tst ZoomHudSingle beq ZoomCheckFullDigits mov #6,R0 ; one changed digit in narrow HUD cmp TestWidth,#128. beq ZoomActualWidth mov #13.,R0 ; full-line width on wide HUD br ZoomActualWidth ZoomCheckFullDigits: tst ZoomHudDigits beq ZoomActualWidth mov #13.,R0 ; keep full-label centring for digits ZoomActualWidth:mov ZoomScaleX,R1 ZoomLengthScale:cmp R1,#1 beq ZoomScaledReady asl R0 asr R1 br ZoomLengthScale ZoomScaledReady:mov TestWidthChars,R1 sub R0,R1 asr R1 ; For mono X>1, glyph writes require aligned words. cmp ZoomBPP,#1 bne ZoomEvenReady cmp ZoomScaleX,#1 beq ZoomEvenReady bic #1,R1 ZoomEvenReady: mov R1,ZoomXChar mov R1,R0 mov ZoomBPP,R1 cmp R1,#1 beq ZoomXReady ZoomXShift: asl R0 asr R1 cmp R1,#1 bne ZoomXShift ZoomXReady: mov R0,ZoomXByte mov ZoomBPP,R0 mov ZoomScaleX,R1 cmp R1,#1 beq ZoomStrideReady ZoomStrideLoop:asl R0 asr R1 cmp R1,#1 bne ZoomStrideLoop ZoomStrideReady:mov R0,ZoomCharStride tst ZoomHudSingle bne ZoomSinglePosition tst ZoomHudDigits beq ZoomOutputStart mov #7,R1 br ZoomDigitsX ZoomSinglePosition: mov ZoomDigitIndex,R1 cmp TestWidth,#128. beq ZoomDigitCheck add #7,R1 ZoomDigitCheck: tst R1 beq ZoomOutputStart ZoomDigitsX: add ZoomCharStride,ZoomXByte sob R1,ZoomDigitsX ZoomOutputStart:mov ZoomStringPtr,R3 ZoomStringNext:movb (R3)+,R0 beq ZoomStringDone mov R3,ZoomStringPtr jsr PC,ZoomDrawChar mov ZoomStringPtr,R3 add ZoomCharStride,ZoomXByte br ZoomStringNext ZoomStringDone:rts PC ; A glyph: 8x10 samples, X replicated 1,2,4,8 times, Y 1,2,4 times. ZoomDrawChar: mov R0,R5 asl R5 mov R5,R1 asl R5 asl R5 add R1,R5 add #FONTBASE,R5 clr ZoomScan ZoomGlyphScan: movb (R5)+,R0 bic #177400,R0 mov R0,ZoomFontBits jsr PC,ZoomReadCachedScan mov ZoomScan,R0 mov ZoomScaleY,R1 cmp R1,#1 beq ZoomYScaled ZoomYShift: asl R0 asr R1 cmp R1,#1 bne ZoomYShift ZoomYScaled: add ZoomStartY,R0 mov R0,ZoomPhysicalY mov ZoomScaleY,ZoomRepeatY ZoomGlyphRepeat: mov ZoomPhysicalY,R0 jsr PC,ZoomMapRow add ZoomXByte,R2 mov #ZoomRowData,R4 mov ZoomWordCount,R3 bne ZoomCopyWords ; 1bpp x1 requires a single byte/glyph. movb (R4),(R2) br ZoomCopied ZoomCopyWords: mov (R4)+,(R2)+ sob R3,ZoomCopyWords ZoomCopied: inc ZoomPhysicalY dec ZoomRepeatY bne ZoomGlyphRepeat inc ZoomScan cmp ZoomScan,#10. blo ZoomGlyphScan rts PC ; Build packed pixels into row words; flush an incomplete final word. ; Generate a compact 16-entry lookup once for the selected BPP/X scale. ; Each 4-pixel nibble expands into 4..128 bits, padded to 16 bytes. ; The expensive shift/add loops below run only 16 times per test, ; not 10 times per character across every full redraw and auto-repeat. ZoomInitLUT: mov R3,-(SP) mov R4,-(SP) mov R5,-(SP) mov ZoomBPP,R0 mov ZoomScaleX,R1 ZoomInitScale: cmp R1,#1 beq ZoomInitBits asl R0 asr R1 br ZoomInitScale ZoomInitBits: mov R0,R1 asl R1 asl R1 mov R1,ZoomNibbleBits ; 4*BPP*X, bits per half-byte mov R1,R0 asr R0 asr R0 asr R0 asr R0 mov R0,ZoomNibbleWords ; groups >= 16bits clr R4 mov #ZoomNibbleTable,R5 ZoomInitNext: mov R4,ZoomFontBits jsr PC,ZoomBuildScan mov ZoomNibbleWords,R3 bne ZoomInitCopy mov #1,R3 ZoomInitCopy: mov #ZoomRowData,R1 mov R5,R2 ZoomInitWord: mov (R1)+,(R2)+ sob R3,ZoomInitWord add #16.,R5 ; constant entry stride (8 words) inc R4 cmp R4,#16. blo ZoomInitNext mov (SP)+,R5 mov (SP)+,R4 mov (SP)+,R3 rts PC ; Input ZoomFontBits=one glyph scan byte, output ZoomRowData. ; Two nibble table lookups replace 8*scaleX shift/bit-building loops. ZoomReadCachedScan: mov R5,-(SP) ; glyph ROM scan pointer lives in R5 mov ZoomFontBits,R0 bic #177760,R0 ; low nibble asl R0 asl R0 asl R0 asl R0 ; each LUT entry 16 bytes add #ZoomNibbleTable,R0 mov R0,R1 mov ZoomFontBits,R0 asr R0 asr R0 asr R0 asr R0 ; high nibble asl R0 asl R0 asl R0 asl R0 add #ZoomNibbleTable,R0 mov R0,R5 mov ZoomNibbleWords,R3 beq ZoomCacheSmall mov #ZoomRowData,R2 ZoomCacheLow: mov (R1)+,(R2)+ sob R3,ZoomCacheLow mov ZoomNibbleWords,R3 ZoomCacheHigh: mov (R5)+,(R2)+ sob R3,ZoomCacheHigh br ZoomCacheDone ZoomCacheSmall: mov (R1),R2 mov (R5),R0 cmp ZoomNibbleBits,#4 bne ZoomCacheShift8 asl R0 asl R0 asl R0 asl R0 br ZoomCacheMerge ZoomCacheShift8:swab R0 ZoomCacheMerge: bis R0,R2 mov R2,ZoomRowData ZoomCacheDone: mov (SP)+,R5 rts PC ZoomNibbleBits: .word 0 ZoomNibbleWords:.word 0 ZoomNibbleTable: .word 0,0,0,0,0,0,0,0 .word 0,0,0,0,0,0,0,0 .word 0,0,0,0,0,0,0,0 .word 0,0,0,0,0,0,0,0 .word 0,0,0,0,0,0,0,0 .word 0,0,0,0,0,0,0,0 .word 0,0,0,0,0,0,0,0 .word 0,0,0,0,0,0,0,0 .word 0,0,0,0,0,0,0,0 .word 0,0,0,0,0,0,0,0 .word 0,0,0,0,0,0,0,0 .word 0,0,0,0,0,0,0,0 .word 0,0,0,0,0,0,0,0 .word 0,0,0,0,0,0,0,0 .word 0,0,0,0,0,0,0,0 .word 0,0,0,0,0,0,0,0 ZoomBuildScan: mov #ZoomRowData,ZoomDst clr ZoomPacked clr ZoomBitCount mov #8.,ZoomSrcCount ZoomSourceLoop:clr ZoomPixel bit #1,ZoomFontBits beq ZoomPixelReady mov #1,ZoomPixel cmp ZoomBPP,#2 bne ZoomPixelFour mov #3,ZoomPixel ZoomPixelFour: cmp ZoomBPP,#4 bne ZoomPixelEight mov #14.,ZoomPixel br ZoomPixelReady ZoomPixelEight: cmp ZoomBPP,#8. bne ZoomPixelReady mov #17.,ZoomPixel ; palette index 17, bright white ZoomPixelReady: mov ZoomScaleX,ZoomRepeatX ZoomExpandLoop: mov ZoomPixel,R0 mov ZoomBitCount,R1 beq ZoomNoShift ZoomShiftPixel:asl R0 sob R1,ZoomShiftPixel ZoomNoShift: bis R0,ZoomPacked add ZoomBPP,ZoomBitCount cmp ZoomBitCount,#16. bne ZoomNotFull mov ZoomDst,R2 mov ZoomPacked,(R2) add #2,ZoomDst clr ZoomPacked clr ZoomBitCount ZoomNotFull: dec ZoomRepeatX bne ZoomExpandLoop asr ZoomFontBits dec ZoomSrcCount bne ZoomSourceLoop tst ZoomBitCount beq ZoomFlushDone mov ZoomDst,R2 mov ZoomPacked,(R2) ZoomFlushDone: mov ZoomBPP,R0 mov ZoomScaleX,R1 cmp R1,#1 beq ZoomCountReady ZoomCountShift:asl R0 asr R1 cmp R1,#1 bne ZoomCountShift ZoomCountReady: asr R0 mov R0,ZoomWordCount rts PC ZoomMapRow: cmp GridRow,#4 blo ZoomMapMono cmp GridRow,#8. blo ZoomMapTwo cmp GridRow,#12. blo ZoomMapFour jsr PC,EightMapRow rts PC ZoomMapFour: jsr PC,FourMapRow rts PC ZoomMapTwo: jsr PC,ColorMapRow rts PC ZoomMapMono: jsr PC,MonoMapRow rts PC ZoomStringPtr: .word 0 ZoomLen: .word 0 ZoomStartY: .word 0 ZoomScaleX: .word 0 ZoomScaleY: .word 0 ZoomBPP: .word 0 ZoomXChar: .word 0 ZoomXByte: .word 0 ZoomCharStride:.word 0 ZoomHudDigits: .word 0 ZoomHudSingle: .word 0 ZoomDigitIndex: .word 0 ZoomScan: .word 0 ZoomFontBits: .word 0 ZoomSrcCount: .word 0 ZoomDst: .word 0 ZoomPacked: .word 0 ZoomPixel: .word 0 ZoomBitCount: .word 0 ZoomRepeatX: .word 0 ZoomRepeatY: .word 0 ZoomPhysicalY: .word 0 ZoomWordCount: .word 0 ZoomRowData: .word 0,0,0,0,0,0,0,0 .word 0,0,0,0,0,0,0,0 ; ----------------------- Test data and settings --------------------------- TestMode: .word 0 TestWidth: .word 0 TestHeight: .word 0 TestWidthChars: .word 0 TestVisibleWords: .word 0 TestPitchWords: .word 0 TestPitchBytes: .word 0 TestRowsLeft: .word 0 TestChunkRows: .word 0 TestDstLow: .word 0 TestScrollX: .word 0 TestScrollY: .word 0 TestSavedBlitCtrl: .word 0 TestSavedBlitPage: .word 0 TestSavedWin120: .word 0 MonoY: .word 0 MonoDist: .word 0 MonoTextX: .word 0 MonoTextY: .word 0 MonoCodeLine: .asciz "MODE 000000" .even ; Exact 16-frame masks for scanlines whose edge distance is 0..15. ; Bits are in logical pixel order (LSB = leftmost pixel). MonoLeftMasks: .word 000000,177776,000002,177772,000012,177752,000052,177652 .word 000252,177252,001252,175252,005252,165252,025252,125252 MonoRightMasks: .word 000000,077777,040000,057777,050000,053777,052000,052777 .word 052400,052577,052500,052537,052520,052527,052524,052525 MonoWidths: .word 128.,256.,512.,1024. MonoHeights: .word 192.,256.,384.,768. MonoLabelPtrs: .word MT00,MT01,MT02,MT03 .word MT04,MT05,MT06,MT07 .word MT08,MT09,MT10,MT11 .word MT12,MT13,MT14,MT15 MT00: .asciz "128x192x1" MT01: .asciz "128x256x1" MT02: .asciz "128x384x1" MT03: .asciz "128x768x1" MT04: .asciz "256x192x1" MT05: .asciz "256x256x1" MT06: .asciz "256x384x1" MT07: .asciz "256x768x1" MT08: .asciz "512x192x1" MT09: .asciz "512x256x1" MT10: .asciz "512x384x1" MT11: .asciz "512x768x1" MT12: .asciz "1024x192x1" MT13: .asciz "1024x256x1" MT14: .asciz "1024x384x1" MT15: .asciz "1024x768x1" .even ; ------------------------ BK10 mono text driver -------------------------- ; UI_X = character column [0..63], UI_Y = character row [0..24]. ; Pixel layout 512x256x1: 64 bytes per scanline; 4 pages x 4096B. ; Trampoline is independent from AZLIB00's 4bpp font rasterizer. ; ; ROM table: 111576 + ASCII_code*10(decimal), 10 rows per glyph. ; Space (040) starts at 112276; previous v05 base shifted all glyphs +16. ; ROM glyph addressing HW PASS in AZVIDT06, per supplied screenshots. PrintString: mov R0,-(SP) mov R3,-(SP) StrLoop: movb (R3)+,R0 beq StrDone jsr PC,PrintChar br StrLoop StrDone: mov (SP)+,R3 mov (SP)+,R0 rts PC PrintChar: mov R0,-(SP) mov R1,-(SP) mov R2,-(SP) mov R3,-(SP) mov R4,-(SP) mov R5,-(SP) cmp R0,#40 bcc CharHaveCode jmp CharDone CharHaveCode: cmp UX,#64. blo CharHaveX jmp CharDone CharHaveX: cmp UY,#25. blo CharHaveY jmp CharDone CharHaveY: ; R5 = font pointer, character_code * 10 (2+8). mov R0,R5 asl R5 mov R5,R1 asl R5 asl R5 add R1,R5 add #FONTBASE,R5 ; R4 = first scanline: y * 10 mov UY,R4 asl R4 mov R4,R1 asl R4 asl R4 add R1,R4 mov #10.,R3 CharScan: mov R4,R2 bic #177700,R2 ; (scanline mod 64) asl R2 asl R2 asl R2 asl R2 asl R2 asl R2 ; *64 bytes add UX,R2 add #120000,R2 mov R4,R1 asr R1 asr R1 asr R1 asr R1 asr R1 asr R1 ; page index = scanline/64 add #SCRBASE,R1 mov R1,@#WIN120 movb (R5)+,(R2) inc R4 sob R3,CharScan CharDone: inc UX mov (SP)+,R5 mov (SP)+,R4 mov (SP)+,R3 mov (SP)+,R2 mov (SP)+,R1 mov (SP)+,R0 rts PC ; Clear 4 consecutive 4KiB AZ video pages (16KiB total). ClearScreen: mov R0,-(SP) mov R1,-(SP) mov R2,-(SP) mov R3,-(SP) mov #SCRBASE,R0 mov #4.,R1 ClearPage: mov R0,@#WIN120 mov #120000,R2 mov #4000,R3 ClearWord: clr (R2)+ sob R3,ClearWord inc R0 sob R1,ClearPage mov (SP)+,R3 mov (SP)+,R2 mov (SP)+,R1 mov (SP)+,R0 rts PC ; R1 -> 6 octal digits, written by PrintString at UX, UY. PrintOct6: mov R0,-(SP) mov R1,-(SP) mov R2,-(SP) mov R3,-(SP) mov #OctBuf+6,R2 clr R0 movb R0,(R2) mov #6,R3 OctDigit: mov R1,R0 bic #177770,R0 add #'0,R0 movb R0,-(R2) clc ror R1 clc ror R1 clc ror R1 sob R3,OctDigit mov #OctBuf,R3 jsr PC,PrintString mov (SP)+,R3 mov (SP)+,R2 mov (SP)+,R1 mov (SP)+,R0 rts PC ; ---------------------- Main menu: single press only ------------------------ ; Separate keyboard path for the THREE-ENTRY main menu. ; Wait for the previous key to be physically released, purge any queued ; controller-generated repeats, then collect exactly ONE new key code. ; Do not return to MainKey until the same physical key has been released. ; Other views continue to use ReadKey with 500ms/20Hz arrow auto-repeat. ReadKeySingle: SingleOldRelease: bit #100,@#177716 ; 1 = released beq SingleOldRelease jsr PC,FlushReleasedKeys ; remove stale input before menu SingleWaitKey: bit #200,@#177660 ; new keyboard scan ready beq SingleWaitKey mov @#177662,R0 bic #177600,R0 mov R0,-(SP) ; preserve code across release SingleNewRelease: bit #100,@#177716 beq SingleNewRelease jsr PC,FlushReleasedKeys mov (SP)+,R0 rts PC ; ---------------------- Keyboard (repeating arrows) ------------------------- ; Exactly one command event per press/release; autorepeat is ONLY for ; K_LEFT/K_RIGHT/K_UP/K_DOWN (500ms delay, 20Hz thereafter). ; 177660 bit 200 is the only input-ready condition. Previously the code ; fell through to KeyReady on a PRESSED physical key with no new scan ; code, allowing stale ENTER in 177662 to trigger again after a test. ; Flush queued repeats AFTER command release and arrow release. ; BK timer: 177706 reload, 177712 control/status; 42.9us/tick at 1x. ReadKey: tst RepeatActive beq KeyFresh KeyHeldWait: bit #100,@#177716 ; 1 = physically released bne KeyStopRepeat bit #200,@#177712 ; repeat delay expired? beq KeyHeldWait mov #1165.,@#177706 ; 50ms = ~20 events/second mov #34,@#177712 mov RepeatCode,R0 rts PC KeyStopRepeat: clr RepeatActive jsr PC,FlushReleasedKeys KeyFresh: KeyWait: bit #200,@#177660 ; await a *NEW* scan code beq KeyWait KeyReady: mov @#177662,R0 bic #177600,R0 cmp R0,#K_UP beq KeyStartRepeat cmp R0,#K_DOWN beq KeyStartRepeat cmp R0,#K_LEFT beq KeyStartRepeat cmp R0,#K_RIGHT beq KeyStartRepeat ; ENTER, SPACE, KT (and other non-arrows): one event. KeyRelease: bit #100,@#177716 beq KeyRelease mov R0,-(SP) ; retain the one legitimate command jsr PC,FlushReleasedKeys mov (SP)+,R0 rts PC KeyStartRepeat: tst RepeatTimerUsed bne KeyTimerSaved mov @#177706,RepeatSavedPreset mov @#177712,RepeatSavedControl mov #1,RepeatTimerUsed KeyTimerSaved: mov R0,RepeatCode mov #1,RepeatActive mov #11655.,@#177706 ; 500ms initial delay mov #34,@#177712 rts PC ; Drain only ALREADY RELEASED keyboard scan codes. If the user presses ; another key while draining, do not consume it. The bounded loop avoids ; hanging if a broken emulator leaves the ready bit stuck at 1. ; Clobbers R0 and R1; callers preserve accepted key in stack. FlushReleasedKeys: mov #32.,R1 FlushReleasedLoop: bit #100,@#177716 beq FlushReleasedDone ; do not swallow a new keypress bit #200,@#177660 beq FlushReleasedDone mov @#177662,R0 sob R1,FlushReleasedLoop FlushReleasedDone: rts PC RestoreRepeatTimer: tst RepeatTimerUsed beq RestoreRepeatDone mov RepeatSavedPreset,@#177706 mov RepeatSavedControl,R0 bic #200,R0 ; ready bit is status, not command mov R0,@#177712 RestoreRepeatDone: clr RepeatActive clr RepeatTimerUsed rts PC RepeatActive: .word 0 RepeatTimerUsed:.word 0 RepeatCode: .word 0 RepeatSavedPreset:.word 0 RepeatSavedControl:.word 0 ; ----------------------- Finish / OS handoff ------------------------------ ExitToANDOS: ; Restore timer configuration if an arrow was ever held. jsr PC,RestoreRepeatTimer ; Restore exactly the hardware state that stage 1 changed. mov (SP)+,@#177346 mov (SP)+,@#177716 mov (SP)+,@#177344 mov (SP)+,@#177342 mov (SP)+,@#177340 mov (SP)+,@#102 mov (SP)+,@#100 mov (SP)+,@#WIN110 mov (SP)+,@#WIN100 mov (SP)+,@#177326 mov (SP)+,@#177324 mov (SP)+,@#177252 mov (SP)+,@#177250 mov (SP)+,@#177232 mov (SP)+,@#177230 bic #100,@#177660 jmp @#100000 ; same handoff as uploaded blttst8 ; ---------------------------------- Data ----------------------------------- UX: .word 0 UY: .word 0 MainSelected: .word 0 BatchActive: .word 0 BatchStopped: .word 0 TestBufferBase: .word TESTBASE TestBufferHi: .word 22 BatchPal2Saved: .word 0 BatchPal4Saved: .word 0 BatchPal8Saved: .word 0 BatchSavedRow: .word 0 BatchSavedCol: .word 0 BatchSavedSysCtrl: .word 0 BatchSavedVector100: .word 0 BatchSavedVector102: .word 0 BatchFlipPending: .word 0 BatchFlipBase: .word 0 BatchFlipMode: .word 0 BatchFrameTicks: .word 0 GridRow: .word 2 GridCol: .word 1 RenderRow: .word 0 RenderCol: .word 0 ProbeValue: .word 0 BusFault: .word 0 OldBusPC: .word 0 OldBusPSW: .word 0 OctBuf: .byte 0,0,0,0,0,0,0,0 .even NoAZText: .asciz "AZBK HARDWARE NOT FOUND" TitleText: .asciz "AZBK VIDEO CONTROLLER TEST - AZVIDT24" VersionText: .asciz "HW:" FPGAtext: .asciz " FPGA:" OptionalVersion:.asciz " BIOS/STM: -" MenuText0: .asciz "RUN ALL 60 MODES (2 SEC/MODE)" MenuText1: .asciz "SELECT VIDEO MODE" MenuText2: .asciz "EXIT TO ANDOS" ControlsMain: .asciz "UP/DOWN SELECT ENTER START KT/SPACE EXIT" GridTitle: .asciz "AZBK VIDEO MODE MATRIX - SINGLE LAYER" GridHeading: .asciz "W/BPP 192 256 384 768" SelectedText: .asciz "SELECTED: " ControlsGrid: .asciz "ARROWS SELECT ENTER START KT/SPACE BACK" StubText: .asciz "VIDEO TEST MODULE WILL BE ADDED NEXT" StubBackText: .asciz "ENTER/KT/SPACE: RETURN TO TABLE" ; 15 rows, 4 modes per row: 192,256,384,768 line display. .even GridLabels: .word L00,L01,L02,L03,L04,L05,L06,L07 .word L08,L09,L10,L11,L12,L13,L14 L00: .asciz "128x1" L01: .asciz "256x1" L02: .asciz "512x1" L03: .asciz "1024x1" L04: .asciz "128x2" L05: .asciz "256x2" L06: .asciz "512x2" L07: .asciz "1024x2" L08: .asciz "128x4" L09: .asciz "256x4" L10: .asciz "512x4" L11: .asciz "1024x4" L12: .asciz "128x8" L13: .asciz "256x8" L14: .asciz "512x8" .even ; 60 mode control words, OCTAL, to be confirmed against active FPGA. ModeCodes: .word 003300,012300,021300,040300 .word 003200,012200,021200,040200 .word 003100,012100,021100,040100 .word 023010,032010,041010,060010 .word 003301,012301,021301,040301 .word 003201,012201,021201,040201 .word 023111,032111,041111,060111 .word 043021,052021,061021,100021 .word 003302,012302,021302,040302 .word 023212,032212,041212,060212 .word 043122,052122,061122,100122 .word 063032,072032,101032,120032 .word 023313,032313,041313,060313 .word 043223,052223,061223,100223 .word 063133,072133,101133,120133 .END