From 8579e0ec01300f260ebad5accad232a083715355 Mon Sep 17 00:00:00 2001 From: cuz Date: Tue, 9 Dec 2003 20:46:38 +0000 Subject: [PATCH] New apple2 tgi driver from Stefan Haubenthal git-svn-id: svn://svn.cc65.org/cc65/trunk@2724 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- libsrc/Makefile | 3 +- libsrc/apple2/Makefile | 2 +- libsrc/apple2/apple2-40-40-16.s | 814 ++++++++++++++++++++++++++++++++ 3 files changed, 817 insertions(+), 2 deletions(-) create mode 100644 libsrc/apple2/apple2-40-40-16.s diff --git a/libsrc/Makefile b/libsrc/Makefile index 91befe1ed..2d38a0049 100644 --- a/libsrc/Makefile +++ b/libsrc/Makefile @@ -50,7 +50,8 @@ apple2lib: $(AR) a apple2.lib $$i/*.o;\ done mv apple2/crt0.o apple2.o - cp apple2/*.tgi . + cp apple2/apple2-280-192-6.tgi apple2.hi.tgi + cp apple2/apple2-40-40-16.tgi apple2.lo.tgi cp apple2/apple2-stdjoy.joy a2-stdjoy.joy #----------------------------------------------------------------------------- diff --git a/libsrc/apple2/Makefile b/libsrc/apple2/Makefile index fbe9418c0..3040da0c5 100644 --- a/libsrc/apple2/Makefile +++ b/libsrc/apple2/Makefile @@ -59,7 +59,7 @@ EMDS = JOYS = apple2-stdjoy.joy -TGIS = apple2-280-192-6.tgi +TGIS = apple2-40-40-16.tgi apple2-280-192-6.tgi #-------------------------------------------------------------------------- # Targets diff --git a/libsrc/apple2/apple2-40-40-16.s b/libsrc/apple2/apple2-40-40-16.s new file mode 100644 index 000000000..e222cb8c0 --- /dev/null +++ b/libsrc/apple2/apple2-40-40-16.s @@ -0,0 +1,814 @@ +; +; Graphics driver for the 40x40x16 mode on the Apple II +; +; Stefan Haubenthal +; Based on Maciej Witkowiak's line and circle routine +; + + .include "zeropage.inc" + + .include "tgi-kernel.inc" + .include "tgi-mode.inc" + .include "tgi-error.inc" + .include "apple2.inc" + + .macpack generic + +; ------------------------------------------------------------------------ +; Constants + +H2 = $2C +PLOT = $F800 +HLINE = $F819 +CLRTOP = $F836 +SETCOL = $F864 +SCRN = $F871 +SETGR = $FB40 + +; ------------------------------------------------------------------------ +; 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 TGI_API_VERSION ; TGI API version number +xres: .word 40 ; X resolution +yres: .word 40 ; Y resolution + .byte 16 ; Number of drawing colors + .byte 1 ; 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). + + .word INSTALL + .word UNINSTALL + .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 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 +TEMP = tmp3 +TEMP2 = tmp4 +TEMP3 = sreg +TEMP4 = sreg+1 + +; 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 + +; 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 + +; Constants and tables + +.rodata + +DEFPALETTE: .byte $0, $f, $1, $e, $3, $4, $2, $d + .byte $9, $8, $b, $5, $a, $c, $6, $7 + +.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: + + +; ------------------------------------------------------------------------ +; UNINSTALL 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 +; + +UNINSTALL: + rts + + +; ------------------------------------------------------------------------ +; INIT: Changes an already installed device from text mode to graphics +; mode. +; 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: + +; Switch into graphics mode + + jsr SETGR + +; Done, reset the error code + + lda #TGI_ERR_OK + 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: NO +; + +DONE = TEXT + +; ------------------------------------------------------------------------ +; 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 = CLRTOP + +; ------------------------------------------------------------------------ +; 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: + +; ------------------------------------------------------------------------ +; 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 = SETCOL + +; ------------------------------------------------------------------------ +; 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: + lda #TGI_ERR_INV_FUNC + sta ERROR + rts + +; ------------------------------------------------------------------------ +; GETPALETTE: Return the current palette in A/X. Even drivers that cannot +; set the palette should return the default palette here, so there's no +; way for this function to fail. +; +; Must set an error code: NO +; + +GETPALETTE: + +; ------------------------------------------------------------------------ +; GETDEFPALETTE: Return the default palette for the driver in A/X. All +; drivers should return something reasonable here, even drivers that don't +; support palettes, otherwise the caller has no way to determine the colors +; of the (not changeable) palette. +; +; Must set an error code: NO (all drivers must have a default palette) +; + +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 X1 + ldx X1+1 + sta ADDR + stx ADDR+1 + ldx #ADDR + lda xres + ldy xres+1 + jsr icmp ; ( x < xres ) ... + bcs @finito + lda Y1 + ldx Y1+1 + sta ADDR + stx ADDR+1 + ldx #ADDR + lda yres + ldy yres+1 + jsr icmp ; ... && ( y < yres ) + bcc SETPIXEL +@finito:rts + +SETPIXEL: + lda X1 + ldy Y1 + jmp PLOT + +; ------------------------------------------------------------------------ +; GETPIXEL: Read the color value of a pixel and return it in A/X. The +; coordinates passed to this function are never outside the visible screen +; area, so there is no need for clipping inside this function. + + +GETPIXEL: + lda X1 + ldy Y1 + jsr SCRN + ldx #0 + 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: + ; nx = abs(x2 - x1) + lda X2 + sub X1 + sta NX + lda X2+1 + sbc X1+1 + tay + lda NX + jsr abs + sta NX + sty NX+1 + ; ny = abs(y2 - y1) + lda Y2 + sub Y1 + sta NY + lda Y2+1 + sbc Y1+1 + tay + lda NY + jsr abs + sta NY + sty NY+1 + ; if (x2>x1) + ldx #X2 + lda X1 + ldy X1+1 + jsr icmp + bcc @L0243 + beq @L0243 + ; dx = 1; + lda #1 + bne @L0244 + ; else + ; dx = -1; +@L0243: lda #$ff +@L0244: sta DX + ; if (y2>y1) + ldx #Y2 + lda Y1 + ldy Y1+1 + jsr icmp + bcc @L024A + beq @L024A + ; dy = 1; + lda #1 + bne @L024B + ; else + ; dy = -1; +@L024A: lda #$ff +@L024B: sta DY + ; err = ay = 0; + lda #0 + sta ERR + sta ERR+1 + sta AY + + ; if (nx ny + lda NX + ldx NY + sta NY + stx NX + lda NX+1 + ldx NY+1 + sta NY+1 + stx NX+1 + ; ay = dx + lda DX + sta AY + ; dx = dy = 0; + lda #0 + sta DX + sta DY + ; ny = - ny; +@L0255: lda NY + ldy NY+1 + jsr neg + sta NY + sty NY+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 + add NY + sta PB + lda ERR+1 + adc NY+1 + sta PB+1 + tax + ; ub = pb + nx + lda PB + add NX + sta UB + txa + adc NX+1 + sta UB+1 + ; x1 = x1 + dx + ldx #0 + lda DX + bpl @L027B + dex +@L027B: add X1 + sta X1 + txa + adc X1+1 + sta X1+1 + ; y1 = y1 + ay + ldx #0 + lda AY + bpl @L027E + dex +@L027E: add Y1 + sta Y1 + txa + adc Y1+1 + sta Y1+1 + ; 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 + ldx X2 + stx H2 +@L1: ldy X1 + lda Y1 + jsr HLINE + inc Y1 + lda Y2 + cmp Y1 + bne @L1 + 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