From 578443610d569539d82cc2d7b300e5190a67700e Mon Sep 17 00:00:00 2001 From: izydorst Date: Mon, 23 Dec 2002 14:15:46 +0000 Subject: [PATCH] new TGI driver for interlaced VDC 640x480 mode git-svn-id: svn://svn.cc65.org/cc65/trunk@1830 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- asminc/tgi-mode.inc | 1 + include/tgi/tgi-mode.h | 1 + libsrc/Makefile | 1 + libsrc/c128/Makefile | 2 +- libsrc/c128/c128-640-200-2.s | 24 +- libsrc/c128/c128-640-480-2.s | 1287 ++++++++++++++++++++++++++++++++++ libsrc/c128/tgi_mode_table.s | 1 + 7 files changed, 1302 insertions(+), 15 deletions(-) create mode 100644 libsrc/c128/c128-640-480-2.s diff --git a/asminc/tgi-mode.inc b/asminc/tgi-mode.inc index cd97a2433..48c0273b8 100644 --- a/asminc/tgi-mode.inc +++ b/asminc/tgi-mode.inc @@ -37,6 +37,7 @@ TGI_MODE_320_200_2 = 1 ; 320x200, 2 colors (b/w) TGI_MODE_160_200_4 = 2 ; 160x200, 4 colors TGI_MODE_640_200_2 = 3 ; 640x200, 2 colors (b/w) +TGI_MODE_640_480_2 = 4 ; 640x480, 2 colors (b/w) diff --git a/include/tgi/tgi-mode.h b/include/tgi/tgi-mode.h index 5c48b5e7f..7f389c6c9 100644 --- a/include/tgi/tgi-mode.h +++ b/include/tgi/tgi-mode.h @@ -48,6 +48,7 @@ #define TGI_MODE_320_200_2 1U /* 320x200, 2 colors (b/w) */ #define TGI_MODE_160_200_4 2U /* 160x200, 4 colors */ #define TGI_MODE_640_200_2 3U /* 640x200, 2 colors (b/w) */ +#define TGI_MODE_640_480_2 4U /* 640x480, 2 colors (b/w) */ diff --git a/libsrc/Makefile b/libsrc/Makefile index 39b7f8a66..17f0383dc 100644 --- a/libsrc/Makefile +++ b/libsrc/Makefile @@ -145,6 +145,7 @@ c128lib: cp c128/*.emd . cp c128/*.joy . cp c128/c128-640-200-2.tgi c128-vdc.tgi + cp c128/c128-640-480-2.tgi c128-vdc2.tgi #----------------------------------------------------------------------------- # Commdore P500 / CBM 5x0 diff --git a/libsrc/c128/Makefile b/libsrc/c128/Makefile index 7d2cdf421..5aa753408 100644 --- a/libsrc/c128/Makefile +++ b/libsrc/c128/Makefile @@ -51,7 +51,7 @@ EMDS = c128-georam.emd c128-ram.emd c128-ramcart.emd c128-reu.emd c128-vdc.emd JOYS = c128-stdjoy.joy -TGIS = c128-640-200-2.tgi +TGIS = c128-640-200-2.tgi c128-640-480-2.tgi #-------------------------------------------------------------------------- # Targets diff --git a/libsrc/c128/c128-640-200-2.s b/libsrc/c128/c128-640-200-2.s index bb96599f7..26ab0b9d1 100644 --- a/libsrc/c128/c128-640-200-2.s +++ b/libsrc/c128/c128-640-200-2.s @@ -1,17 +1,14 @@ ; ; Graphics driver for the 640x200x2 mode on the C128 VDC -; Maciej 'YTM/Elysium' Witkowiak -; 22.12.2002 +; Maciej 'YTM/Elysium' Witkowiak +; 23.12.2002 ; ; NOTES: +; On the real machine there are some additional pixels appearing (probably bad reads) +; VICE emulator does not show them. Needs further investigation. ; ; Only DONE routine contains C128-mode specific stuff, everything else will work in -; C64-mode of C128. -; -; All Y-axis calculations are 16-bit, so this driver will support 640x400 (interlaced) -; mode only with gfx-mode initialization changed. -; (is the above true? I can't remember if interlace skips lines or takes them from two -; different places (same offset, different base)) +; C64-mode of C128 (C64 needs full VDC init then). ; ; X-axis resolution can be changed by manipulating xres header field so ; any resolution 8..708 is possible only with gfx-mode initialization and CALC changed. @@ -428,7 +425,7 @@ SETDRAWPAGE: ror ror sta SCRBASE - rts + rts ; ------------------------------------------------------------------------ ; SETCOLOR: Set the drawing color (in A). The new color is already checked @@ -1142,13 +1139,10 @@ OUTTEXT: rts ; ------------------------------------------------------------------------ -; Calculate all variables to plot the pixel at X1/Y1. If the point is out -; of range, a carry is returned and INRANGE is set to a value !0 zero. If -; the coordinates are valid, INRANGE is zero and the carry clear. - +; Calculate all variables to plot the pixel at X1/Y1. ;------------------------ ;< X1,Y1 - pixel -;> ADDR - address of card, INRANGE +;> ADDR - address of card ;> X - bit number (X1 & 7) CALC: lda Y1+1 @@ -1253,6 +1247,8 @@ VDCSetSourceAddr: sta VDC_DATA_REG dex tya +@L1: bit VDC_ADDR_REG + bpl @L1 stx VDC_ADDR_REG sta VDC_DATA_REG rts diff --git a/libsrc/c128/c128-640-480-2.s b/libsrc/c128/c128-640-480-2.s new file mode 100644 index 000000000..41c5429e2 --- /dev/null +++ b/libsrc/c128/c128-640-480-2.s @@ -0,0 +1,1287 @@ +; +; Graphics driver for the 640x480x2 mode on the C128 VDC +; (values for this mode based on Fred Bowen's document) +; Maciej 'YTM/Elysium' Witkowiak +; 23.12.2002 +; +; NOTES: +; On the real machine there are some additional pixels appearing (probably bad reads) +; VICE emulator does not show them. Needs further investigation. +; +; Only DONE routine contains C128-mode specific stuff, everything else will work in +; C64-mode of C128 (C64 needs full VDC init then). +; +; X-axis resolution can be changed by manipulating xres header field so +; any resolution 8..708 is possible only with gfx-mode initialization and CALC changed. +; +; With special initialization and CALC we can get 320x200 double-pixel mode. +; +; Color translation values for BROWN and GRAY3 are obviously wrong, they could +; be replaced by equiv. of ORANGE and GRAY2 but this would give only 14 of 16 colors available. +; +; Register 25 ($19) is said to require different value for VDC v1, but I couldn't find what +; it should be. + + .include "zeropage.inc" + + .include "tgi-kernel.inc" + .include "tgi-mode.inc" + .include "tgi-error.inc" + + + .macpack generic + +; ------------------------------------------------------------------------ +; Constants + +VDC_ADDR_REG = $D600 ; VDC address +VDC_DATA_REG = $D601 ; VDC data + +VDC_DSP_HI = 12 ; registers used +VDC_DSP_LO = 13 +VDC_DATA_HI = 18 +VDC_DATA_LO = 19 +VDC_VSCROLL = 24 +VDC_HSCROLL = 25 +VDC_COLORS = 26 +VDC_CSET = 28 +VDC_COUNT = 30 +VDC_DATA = 31 + +; ------------------------------------------------------------------------ +; Header. Includes jump table and constants. + +.segment "JUMPTABLE" + +; First part of the header is a structure that has a magic and defines the +; capabilities of the driver + + .byte $74, $67, $69 ; "tgi" + .byte $00 ; TGI version number +xres: .word 640 ; X resolution +yres: .word 480 ; Y resolution + .byte 2 ; Number of drawing colors +pages: .byte 0 ; Number of screens available + .byte 8 ; System font X size + .byte 8 ; System font Y size + .res 4, $00 ; Reserved for future extensions + +; Next comes the jump table. Currently all entries must be valid and may point +; to an RTS for test versions (function not implemented). A future version may +; allow for emulation: In this case the vector will be zero. Emulation means +; that the graphics kernel will emulate the function by using lower level +; primitives - for example ploting a line by using calls to SETPIXEL. + + .word INSTALL + .word DEINSTALL + .word INIT + .word DONE + .word GETERROR + .word CONTROL + .word CLEAR + .word SETVIEWPAGE + .word SETDRAWPAGE + .word SETCOLOR + .word SETPALETTE + .word GETPALETTE + .word GETDEFPALETTE + .word SETPIXEL + .word GETPIXEL + .word HORLINE + .word LINE + .word BAR + .word CIRCLE + .word TEXTSTYLE + .word OUTTEXT + +; ------------------------------------------------------------------------ +; Data. + +; Variables mapped to the zero page segment variables. Some of these are +; used for passing parameters to the driver. + +X1 = ptr1 +Y1 = ptr2 +X2 = ptr3 +Y2 = ptr4 +RADIUS = tmp1 + +ADDR = tmp1 ; (2) CALC +TEMP = tmp3 ; CALC icmp +TEMP2 = tmp4 ; icmp +TEMP3 = sreg ; LINE +TEMP4 = sreg+1 ; LINE + +; Line routine stuff (must be on zpage) +PB = ptr3 ; (2) LINE +UB = ptr4 ; (2) LINE +ERR = regsave ; (2) LINE +NX = regsave+2 ; (2) LINE +; Circle stuff +XX = ptr3 ; (2) CIRCLE +YY = ptr4 ; (2) CIRCLE +MaxO = sreg ; (overwritten by TEMP3+TEMP4, but restored from OG/OU anyway) +XS = regsave ; (2) CIRCLE +YS = regsave+2 ; (2) CIRCLE + +; Absolute variables used in the code + +.bss + +ERROR: .res 1 ; Error code +PALETTE: .res 2 ; The current palette + +BITMASK: .res 1 ; $00 = clear, $FF = set pixels + +OLDCOLOR: .res 1 ; colors before entering gfx mode + +; Line routine stuff (combined with CIRCLE to save space) + +OGora: +COUNT: .res 2 +OUkos: +NY: .res 2 +Y3: +DX: .res 1 +DY: .res 1 +AY: .res 1 + +; Text output stuff +TEXTMAGX: .res 1 +TEXTMAGY: .res 1 +TEXTDIR: .res 1 + +; Constants and tables + +.rodata + +DEFPALETTE: .byte $00, $0f ; White on black +PALETTESIZE = * - DEFPALETTE + +BITTAB: .byte $80,$40,$20,$10,$08,$04,$02,$01 + +BITMASKL: .byte %11111111, %01111111, %00111111, %00011111 + .byte %00001111, %00000111, %00000011, %00000001 + +BITMASKR: .byte %10000000, %11000000, %11100000, %11110000 + .byte %11111000, %11111100, %11111110, %11111111 + +; color translation table (indexed by VIC color) +COLTRANS: .byte $00, $0f, $08, $06, $0a, $04, $02, $0c + .byte $0d, $0b, $09, $01, $0e, $05, $03, $07 + ; colors BROWN and GRAY3 are wrong + +; VDC initialization table (reg),(val),...,$ff +InitVDCTab: + .byte VDC_DSP_HI, 0 ; viewpage 0 as default + .byte VDC_DSP_LO, 0 + .byte VDC_HSCROLL, $87 + .byte 2, $66 + .byte 4, $4c + .byte 5, $06 + .byte 6, $4c + .byte 7, $47 + .byte 8, $03 + .byte 9, $06 + .byte 27, $00 + .byte $ff + +SCN80CLR: .byte 27,88,147,27,88,0 + +.code + +; ------------------------------------------------------------------------ +; INSTALL routine. Is called after the driver is loaded into memory. May +; initialize anything that has to be done just once. Is probably empty +; most of the time. +; +; Must set an error code: NO +; + +INSTALL: + ; check for VDC version and update register $19 value + + ; check for VDC ram size and update number of available screens + + ldx #VDC_CSET ; determine size of RAM... + jsr VDCReadReg + sta tmp1 + ora #%00010000 + jsr VDCWriteReg ; turn on 64k + + jsr settestadr1 ; save original value of test byte + jsr VDCReadByte + sta tmp2 + + lda #$55 ; write $55 here + ldy #ptr1 + jsr test64k ; read it here and there + lda #$aa ; write $aa here + ldy #ptr2 + jsr test64k ; read it here and there + + jsr settestadr1 + lda tmp2 + jsr VDCWriteByte ; restore original value of test byte + + lda ptr1 ; do bytes match? + cmp ptr1+1 + bne @have64k + lda ptr2 + cmp ptr2+1 + bne @have64k + + ldx #VDC_CSET + lda tmp1 + jsr VDCWriteReg ; restore 16/64k flag + jmp @endok ; and leave default values for 16k + +@have64k: + lda #1 + sta pages +@endok: + rts + +test64k: + sta tmp1 + sty ptr3 + lda #0 + sta ptr3+1 + jsr settestadr1 + lda tmp1 + jsr VDCWriteByte ; write $55 + jsr settestadr1 + jsr VDCReadByte ; read here + pha + jsr settestadr2 + jsr VDCReadByte ; and there + ldy #1 + sta (ptr3),y + pla + dey + sta (ptr3),y + rts + +settestadr1: + ldy #$02 ; test page 2 (here) + .byte $2c +settestadr2: + ldy #$42 ; or page 64+2 (there) + lda #0 + jmp VDCSetSourceAddr + +; ------------------------------------------------------------------------ +; DEINSTALL routine. Is called before the driver is removed from memory. May +; clean up anything done by INSTALL but is probably empty most of the time. +; +; Must set an error code: NO +; + +DEINSTALL: + rts + + +; ------------------------------------------------------------------------ +; INIT: Changes an already installed device from text mode to graphics +; mode. The number of the graphics mode is passed to the function in A. +; Note that INIT/DONE may be called multiple times while the driver +; is loaded, while INSTALL is only called once, so any code that is needed +; to initializes variables and so on must go here. Setting palette and +; clearing the screen is not needed because this is called by the graphics +; kernel later. +; The graphics kernel will never call INIT when a graphics mode is already +; active, so there is no need to protect against that. +; +; Must set an error code: YES +; + +INIT: cmp #TGI_MODE_640_480_2 ; Correct mode? + beq @L1 ; Jump if yes + lda #TGI_ERR_INV_MODE ; ## Error + bne @L9 + +@L1: lda pages ; is there enough memory? + bne @L11 ; Jump if there is one screen + lda #TGI_ERR_INV_MODE ; ## Error + bne @L9 + +; Initialize variables + +@L11: ldx #$FF + stx BITMASK + +; Switch into graphics mode (set view page 0) + + ldy #0 +@L2: ldx InitVDCTab,y + bmi @L3 + iny + lda InitVDCTab,y + jsr VDCWriteReg + iny + bne @L2 +@L3: + +; Remeber current color value + ldx #VDC_COLORS + jsr VDCReadReg + sta OLDCOLOR + +; Done, reset the error code + + lda #TGI_ERR_OK +@L9: sta ERROR + rts + +; ------------------------------------------------------------------------ +; DONE: Will be called to switch the graphics device back into text mode. +; The graphics kernel will never call DONE when no graphics mode is active, +; so there is no need to protect against that. +; +; Must set an error code: YES +; + +DONE: + ; This part is C128-mode specific + jsr $e179 ; reload character set + jsr $ff62 + lda $d7 ; in 80-columns? + bne @L01 +@L0: lda SCN80CLR,y + beq @L1 + jsr $ffd2 ; print \xe,clr,\xe + iny + bne @L0 +@L01: lda #147 + jsr $ffd2 ; print clr +@L1: lda #0 ; restore view page + ldx #VDC_DSP_HI + jsr VDCWriteReg + lda OLDCOLOR + ldx #VDC_COLORS + jsr VDCWriteReg ; restore color (background) + lda #$47 + ldx #VDC_HSCROLL + jmp VDCWriteReg ; switch to text screen + +; ------------------------------------------------------------------------ +; GETERROR: Return the error code in A and clear it. + +GETERROR: + ldx #TGI_ERR_OK + lda ERROR + stx ERROR + rts + +; ------------------------------------------------------------------------ +; CONTROL: Platform/driver specific entry point. +; +; Must set an error code: YES +; + +CONTROL: + lda #TGI_ERR_INV_FUNC + sta ERROR + rts + +; ------------------------------------------------------------------------ +; CLEAR: Clears the screen. +; +; Must set an error code: NO +; + +CLEAR: + lda #0 + tay + jsr VDCSetSourceAddr + lda #0 + ldx #VDC_VSCROLL + jsr VDCWriteReg ; set fill mode + lda #0 + jsr VDCWriteByte ; put 1rst byte (fill value) + ldy #159 ; 159 times + lda #0 ; 256 bytes + ldx #VDC_COUNT +@L1: jsr VDCWriteReg + dey + bne @L1 + rts + +; ------------------------------------------------------------------------ +; SETVIEWPAGE: Set the visible page. Called with the new page in A (0..n). +; The page number is already checked to be valid by the graphics kernel. +; +; Must set an error code: NO (will only be called if page ok) +; + +SETVIEWPAGE: + rts + +; ------------------------------------------------------------------------ +; SETDRAWPAGE: Set the drawable page. Called with the new page in A (0..n). +; The page number is already checked to be valid by the graphics kernel. +; +; Must set an error code: NO (will only be called if page ok) +; + +SETDRAWPAGE: + rts + +; ------------------------------------------------------------------------ +; SETCOLOR: Set the drawing color (in A). The new color is already checked +; to be in a valid range (0..maxcolor-1). +; +; Must set an error code: NO (will only be called if color ok) +; + +SETCOLOR: + tax + beq @L1 + lda #$FF +@L1: sta BITMASK + rts + +; ------------------------------------------------------------------------ +; SETPALETTE: Set the palette (not available with all drivers/hardware). +; A pointer to the palette is passed in ptr1. Must set an error if palettes +; are not supported +; +; Must set an error code: YES +; + +SETPALETTE: + ldy #PALETTESIZE - 1 +@L1: lda (ptr1),y ; Copy the palette + and #$0F ; Make a valid color + sta PALETTE,y + dey + bpl @L1 + +; Get the color entries from the palette + + ldy PALETTE+1 ; Foreground color + lda COLTRANS,y + asl a + asl a + asl a + asl a + ldy PALETTE ; Background color + ora COLTRANS,y + + ldx #VDC_COLORS + jmp VDCWriteReg + +; ------------------------------------------------------------------------ +; GETPALETTE: Return the current palette in A/X. Must return NULL and set an +; error if palettes are not supported. +; +; Must set an error code: YES +; + +GETPALETTE: + lda #PALETTE + rts + +; ------------------------------------------------------------------------ +; GETDEFPALETTE: Return the default palette for the driver in A/X. Must +; return NULL and set an error of palettes are not supported. +; +; Must set an error code: YES +; + +GETDEFPALETTE: + lda #DEFPALETTE + rts + +; ------------------------------------------------------------------------ +; SETPIXEL: Draw one pixel at X1/Y1 = ptr1/ptr2 with the current drawing +; color. The coordinates passed to this function are never outside the +; visible screen area, so there is no need for clipping inside this function. +; +; Must set an error code: NO +; + +SETPIXELCLIP: + lda Y1+1 + bmi @finito ; y<0 + lda X1+1 + bmi @finito ; x<0 + lda xres + ldx xres+1 + sta ADDR + stx ADDR+1 + ldx #ADDR + lda X1 + ldy X1+1 + jsr icmp ; if (xres 0 + beq @L1 + sta TEMP2 ; do left byte only... + lda X1 + ldy X1+1 + jsr VDCSetSourceAddr + jsr VDCReadByte + sta TEMP + eor BITMASK + and TEMP2 + eor TEMP + pha + lda X1 + ldy X1+1 + jsr VDCSetSourceAddr + pla + jsr VDCWriteByte + inc X1 ; ... and proceed + bne @L1 + inc X1+1 + + ; do right byte (if Y2=0 ++ADDR and skip) +@L1: lda TEMP3 + cmp #%11111111 ; if right bit <> 7 + bne @L11 + inc ADDR ; right bit = 7 - the next one is the last + bne @L10 + inc ADDR+1 +@L10: bne @L2 + +@L11: lda ADDR ; do right byte only... + ldy ADDR+1 + jsr VDCSetSourceAddr + jsr VDCReadByte + sta TEMP + eor BITMASK + and TEMP3 + eor TEMP + pha + lda ADDR + ldy ADDR+1 + jsr VDCSetSourceAddr + pla + jsr VDCWriteByte + +@L2: ; do the fill in the middle + lda ADDR ; calculate offset in full bytes + sec + sbc X1 + beq @L3 ; if equal - there are no more bytes + sta ADDR + + lda X1 ; setup for the left side + ldy X1+1 + jsr VDCSetSourceAddr + lda BITMASK ; get color + jsr VDCWriteByte ; put 1st value + ldx ADDR + dex + beq @L3 ; 1 byte already written + + stx ADDR ; if there are more bytes - fill them... + ldx #VDC_VSCROLL + lda #0 + jsr VDCWriteReg ; setup for fill + ldx #VDC_COUNT + lda ADDR + jsr VDCWriteReg ; ... fill them NOW! + +@L3: pla + sta X1+1 + pla + sta X1 + rts + +; ------------------------------------------------------------------------ +; LINE: Draw a line from X1/Y1 to X2/Y2, where X1/Y1 = ptr1/ptr2 and +; X2/Y2 = ptr3/ptr4 using the current drawing color. +; +; Must set an error code: NO +; + +LINE: + ; if (x2>x1) { + ldx #X1 + lda X2 + ldy X2+1 + jsr icmp + bcc @L0137 + beq @L0137 + ; x2<->x1 } + lda X1 + ldx X2 + sta X2 + stx X1 + lda X1+1 + ldx X2+1 + sta X2+1 + stx X1+1 +@L0137: ; if (y2>y1) { + ldx #Y1 + lda Y2 + ldy Y2+1 + jsr icmp + bcc @L013F + bne @nequal + jmp HORLINE ; x1/x2 are sorted, y1==y2 - do faster horizontal line draw +@nequal: + ; y2<->y1 } + lda Y1 + ldx Y2 + sta Y2 + stx Y1 + lda Y1+1 + ldx Y2+1 + sta Y2+1 + stx Y1+1 +@L013F: + ; nx = x2 - x1 + lda X2 + sec + sbc X1 + sta NX + lda X2+1 + sbc X1+1 + sta NX+1 + ; ny = y2 - y1 + lda Y2 + sec + sbc Y1 + sta NY + lda Y2+1 + sbc Y1+1 + sta NY+1 + ; if (nx ny + lda NX + ldx NY + sta NY + stx NX + lda NX+1 + ldx NY+1 + sta NY+1 + stx NX+1 + ; dx = dy = 0; ax = ay = 1 } + ldy #1 + sty AY + dey + beq @L025A + ; else { dx = dy = 1; ax = ay = 0 } +@L041B: ldy #0 + sty AY + iny +@L025A: sty DX + sty DY + ; err = 0 + lda #0 + sta ERR + sta ERR+1 + ; for (count=nx;count>0;--count) { + lda NX + ldx NX+1 + sta COUNT + stx COUNT+1 +@L0166: lda COUNT ; count>0 + ora COUNT+1 + bne @L0167 + rts + ; setpixel(X1,Y1) +@L0167: jsr SETPIXELCLIP + ; pb = err - ny + lda ERR + sec + sbc NY + sta PB + lda ERR+1 + sbc NY+1 + sta PB+1 + tax + ; ub = pb + nx + lda PB + clc + adc NX + sta UB + txa + adc NX+1 + sta UB+1 + ; x1 = x1 + dx + lda X1 + clc + adc DX + sta X1 + bcc @L0254 + inc X1+1 + ; y1 = y1 + ay +@L0254: + lda Y1 + clc + adc AY + sta Y1 + bcc @L0255 + inc Y1+1 +@L0255: + ; if (abs(pb)= 0) && (X1 < XRES) +; (X2 >= 0) && (X2 < XRES) +; (Y1 >= 0) && (Y1 < YRES) +; (Y2 >= 0) && (Y2 < YRES) +; +; Must set an error code: NO +; + +BAR: + inc Y2 + bne @L0 + inc Y2+1 +@L0: jsr HORLINE + inc Y1 + bne @L1 + inc Y1+1 +@L1: lda Y1 + cmp Y2 + bne @L0 + lda Y1+1 + cmp Y2+1 + bne @L0 + rts + +; ------------------------------------------------------------------------ +; CIRCLE: Draw a circle around the center X1/Y1 (= ptr1/ptr2) with the +; radius in tmp1 and the current drawing color. +; +; Must set an error code: NO +; + +CIRCLE: + lda RADIUS + bne @L1 + jmp SETPIXELCLIP ; Plot as a point + +@L1: sta XX + ; x = r; + lda #0 + sta XX+1 + sta YY + sta YY+1 + sta MaxO + sta MaxO+1 + ; y =0; mo=0; + lda X1 + ldx X1+1 + sta XS + stx XS+1 + lda Y1 + ldx Y1+1 + sta YS + stx YS+1 ; XS/YS to remember the center + + ; while (y ADDR - address of card +;> X - bit number (X1 & 7) +CALC: + lda Y1 + pha + lda Y1+1 + pha + lsr + ror Y1 ; Y=Y/2 + sta Y1+1 + sta ADDR+1 + lda Y1 + asl + rol ADDR+1 + asl + rol ADDR+1 ; Y*4 + clc + adc Y1 + sta ADDR + lda Y1+1 + adc ADDR+1 + sta ADDR+1 ; Y*4+Y=Y*5 + lda ADDR + asl + rol ADDR+1 + asl + rol ADDR+1 + asl + rol ADDR+1 + asl + rol ADDR+1 + sta ADDR ; Y*5*16=Y*80 + lda X1+1 + sta TEMP + lda X1 + lsr TEMP + ror + lsr TEMP + ror + lsr TEMP + ror + clc + adc ADDR + sta ADDR + lda ADDR+1 ; ADDR = Y*80+x/8 + adc TEMP + sta ADDR+1 + pla + sta Y1+1 + pla + sta Y1 + and #1 + beq @even ; even line - no offset + lda ADDR + clc + adc #<21360 + sta ADDR + lda ADDR+1 + adc #>21360 + sta ADDR+1 ; odd lines are 21360 bytes farther +@even: lda X1 + and #7 + tax + rts + +;------------- +; copies of some runtime routines + +abs: + ; a/y := abs(a/y) + dey + iny + bpl @L1 + ; negay + clc + eor #$ff + adc #1 + pha + tya + eor #$ff + adc #0 + tay + pla +@L1: rts + +icmp: + ; compare a/y to zp,x + sta TEMP ; TEMP/TEMP2 - arg2 + sty TEMP2 + lda $0,x + pha + lda $1,x + tay + pla + tax + tya ; x/a - arg1 (a=high) + + sec + sbc TEMP2 + bne @L4 + cpx TEMP + beq @L3 + adc #$ff + ora #$01 +@L3: rts +@L4: bvc @L3 + eor #$ff + ora #$01 + rts + +;------------- +; VDC helpers + +VDCSetSourceAddr: + ldx #VDC_DATA_LO + stx VDC_ADDR_REG +@L0: bit VDC_ADDR_REG + bpl @L0 + sta VDC_DATA_REG + dex + tya + stx VDC_ADDR_REG + sta VDC_DATA_REG + rts + +VDCReadByte: + ldx #VDC_DATA +VDCReadReg: + stx VDC_ADDR_REG +@L0: bit VDC_ADDR_REG + bpl @L0 + lda VDC_DATA_REG + rts + +VDCWriteByte: + ldx #VDC_DATA +VDCWriteReg: + stx VDC_ADDR_REG +@L0: bit VDC_ADDR_REG + bpl @L0 + sta VDC_DATA_REG + rts + diff --git a/libsrc/c128/tgi_mode_table.s b/libsrc/c128/tgi_mode_table.s index 64973b606..4a61fcb10 100644 --- a/libsrc/c128/tgi_mode_table.s +++ b/libsrc/c128/tgi_mode_table.s @@ -18,4 +18,5 @@ _tgi_mode_table: .byte TGI_MODE_640_200_2, "c128-vdc.tgi", 0 + .byte TGI_MODE_640_480_2, "c128-vdc2.tgi", 0 .byte 0 ; End marker