* EXECUTABLE CART IMAGE * Erik Piehl (C) 2022 November * Test the multicolor mode. * Assemble with: * xas99.py -L multicolor.lst -R -c multicolor.asm * unzip -o multicolor.rpk * The result is multicolor.bin IDT 'MULTICOL' VDPWD EQU >8C00 * VDP write data VDPWA EQU >8C02 * VDP set read/write address VDPRD EQU >8800 * VDP read data VDPPTR EQU >8890 * VDP extension: VRAM address pointer TESTLOC EQU >8340 *--------------------------------------------- * Locations in workspace RAM for scrolling, * and other similar parameters WRKSP EQU >8300 * Workspace memory in fast RAM (for paging tests) R0LB EQU WRKSP+1 * Register zero low byte address SCRLINES EQU >10 ; Pixel lines to scroll. STRIPBUF EQU >8320 ; Scratchpad location for 2*SCRLINES bytes of storage. STRIPBU2 EQU STRIPBUF+(2*SCRLINES) COLOFFS EQU >40 ; Offset to next column ; I think there should be at least >20 bytes here for the key routine. ; The SCROLLSTRIP2 code would go there to go faster. SPSCROLL EQU >8340 *--------------------------------------------- EVEN *--------------------------------------------- * Set VDP read address from R0 *--------------------------------------------- VDPREADA ANDI R0,>3FFF * make sure it is a read command SWPB R0 MOVB R0,@VDPWA * Send low byte of VDP RAM write address SWPB R0 MOVB R0,@VDPWA * Send high byte of VDP RAM write address RT *--------------------------------------------- * Set VDP address from R0 *--------------------------------------------- SETUPVDPA SWPB R0 MOVB R0,@VDPWA * Send low byte of VDP RAM write address SWPB R0 ORI R0,>4000 * Set read/write bits 14 and 15 to write (01) MOVB R0,@VDPWA * Send high byte of VDP RAM write address RT *--------------------------------------------- * Write VDP register *--------------------------------------------- VWREG ORI R0,>8000 CMD SWPB R0 MOVB R0,@>8C02 SWPB R0 MOVB R0,@>8C02 B *R11 *--------------------------------------------- * VDP Modes *--------------------------------------------- ; VDPREGS 0 1 2 3 4 5 6 7 VDP_GM1 BYTE >01,>E2,>F0,>0E, >F9,>86,>F8,>01 * INVADERS *R0 00 R1 E2 16K /Blank Int_on 16x16 *m1=0 m2=0 m3=0 m4=0: Graphics 1 mode *Image table at 0000 R2, character numbers. *Color table at 0380 R3 (not used in text mode, multicolor mode) *Character table at 0800 R4, character table, i.e. fonts *Sprite attribute table 0300 R5, 4 bytes per sprite *Sprite pattern table 0000 R6, 8 or 32 bytes per sprite *Foreground color F R7 high nibble *Background color 1 R7 low nibble VDP_MC BYTE >01, >EA, >F0,>0E, >F9,>86,>F8,>01 * VR1: 7 6 5 4 3 2 1 0 * VR1: 16K Blank Int Text Multi 0 Size4 Mag 2x * 1 . 1 . 1 . 1 . 0 . 0 . 1 . 0 *--------------------------------------------- * MAIN *--------------------------------------------- MAIN LIMI 0 * Disable interrupts LWPI WRKSP * Load the workspace pointer to fast RAM ; Switch to multicolor mode LI R1,VDP_MC CLR R0 LI R2,8 ! SWPB R0 ; Move VDP reg number to lower byte MOVB *R1+,R0 ; Fetch register value byte SWPB R0 ; Now reg num in high byte, data in low byte BL @VWREG AI R0,>0100 ; Inc reg number DEC R2 JNE -! ;---------------------------------------------------------------------------- ; Setup screen in multicolor mode. Fill the screen image (character) table. ;---------------------------------------------------------------------------- LI R0,>0 BL @SETUPVDPA ; VDP write pointer at 0 ; Fill the screen with 0..1F four times, then add >20 for the next four lines and so on. ; Total 768 bytes. CLR R2 ; counts blocks of 4 lines (each 32 bytes) MCS2 LI R3,4 ; four lines with same stuff MCS1 CLR R1 ; column counter ! MOV R1,R4 SOC R2,R4 SWPB R4 MOVB R4,@VDPWD ; Write low byte INC R1 CI R1,>20 JNE -! DEC R3 JNE MCS1 AI R2,>20 CI R2,192 JNE MCS2 ; Init done. Color data comes the pattern table in this mode. Yes it is weird. LI R0,>0800 BL @SETUPVDPA ; VDP write pointer at 0 ; The pattern table is 1536 bytes. Let's just write some stuff and see what happens. LI R0,0 LI R1,VDPWD ! SWPB R0 MOVB R0,*R1 SWPB R0 INC R0 CI R0,1536 JNE -! ; Draw a flashing line on line 15. Each line is 32 bytes (64 pixels). ; Two horizontally adjancent pixels are in the same byte. ; Thus X coordinate is really 5 bits: x5 x4 x3 x2 x1 ; With Y coordinate as 6 bits too: y5 y4 y3 y2 y1 y0 ; The address of a given pixel pair is: ; base + [y5 y4 y3 x5 x4 x3 x2 x1 y2 y1 y0] LI R8,0 ; X LI R9,15 ; Y LI R2,>1100 ; Top byte contains the color for 2 pixels DEMOLP BL @MULTICOLADDR LI R1,VDPWD ; Point to VDP write data register MCLP2 MOV R5,R0 ; R0 = target VDP address LI R3,32 ; Number of pixels / 2 per line. MCLP1 BL @SETUPVDPA MOVB R2,*R1 ; write two pixels. AI R0,8 ; Next column of 2 pixels DEC R3 JNE MCLP1 AI R2,>0100 ; increment pixel value ANDI R2,>0F00 ; duplicate to another nibble MOV R2,R3 SLA R3,4 SOC R3,R2 CI R2,0 ; did we reach color 0? JNE ! ; No: jump ahead LI R2,>1100 ; Yes: init color ! * CI R2,0 ; did we reach color 0? * JNE MCLP2 ; No: do again this line INC R9 ; Yes: inc Y CI R9,48 ; Did we get last pixel line? JNE DEMOLP ; No: continue on this line CLR R9 ; Yes: go back to top line ; Draw a stupid graph. LI R8,24 ; X LI R9,38 ; Y LI R7,GRAPH1 ! BL @MULTICOLADDR MOV R5,R0 BL @SETUPVDPA MOVB *R7+,*R1 ; 2 pixels AI R0,8 BL @SETUPVDPA MOVB *R7+,*R1 ; 2 pixels AI R0,8 BL @SETUPVDPA MOVB *R7+,*R1 ; 2 pixels AI R0,8 BL @SETUPVDPA MOVB *R7+,*R1 ; 2 pixels AI R0,8 BL @SETUPVDPA MOVB *R7+,*R1 ; 2 pixels AI R0,8 BL @SETUPVDPA MOVB *R7+,*R1 ; 2 pixels INC R9 CI R7,GRAPH1END JNE -! * Get ready for next screenful CLR R8 CLR R9 JMP DEMOLP ;---------------------------------------------------------------------------- ; Multicolor "sprite" i.e. just some graphics ;---------------------------------------------------------------------------- GRAPH1: DATA >ABCD,>EEFF,>DCBA DATA >ABCD,>EFFE,>DCBA DATA >0000,>FFEE,>0000 DATA >0000,>FFEE,>0000 DATA >0000,>FFEE,>0000 DATA >0000,>FFEE,>0000 DATA >0000,>FFEE,>0000 GRAPH1END: ;---------------------------------------------------------------------------- MULTICOLADDR: * Routine to calculate screen address of multicolor pixel. ;---------------------------------------------------------------------------- * R8 = X, R9 = Y MOV R8,R4 MOV R9,R5 SRL R4,1 ; half the X component MOV R5,R6 ANDI R6,7 ; y2 y1 y0 ANDI R5,>38 ; y5 y4 y3 0 0 0 SLA R5,5 ; y5 y4 y3 0 0 0 0 0 0 0 0 SOC R6,R5 ; y5 y4 y3 0 0 0 0 0 y2 y1 y0 ANDI R4,>F ; x5 x4 x3 x2 x1 SLA R4,3 ; x5 x4 x3 x2 x1 0 0 0 SOC R4,R5 ; y5 y4 y3 x5 x4 x3 x2 x1 y2 y1 y0 * Now screen offseet in R5. AI R5,>0800 ; base address of pattern table RT END MAIN