From 3bd4d05598cab5855a287a0ec47932cae6c9755b Mon Sep 17 00:00:00 2001 From: Richard Halkyard Date: Sun, 27 Oct 2019 10:22:35 -0500 Subject: [PATCH 01/60] TGI driver and matching linker config for Plus/4 --- cfg/plus4-hires.cfg | 57 +++ doc/plus4.sgml | 20 +- include/cbm264.h | 19 +- include/plus4.h | 2 +- libsrc/plus4/cgetc.s | 5 + libsrc/plus4/crt0.s | 7 +- libsrc/plus4/libref.s | 3 +- libsrc/plus4/tgi/ted-hi.s | 883 +++++++++++++++++++++++++++++++++ libsrc/plus4/tgi_stat_stddrv.s | 14 + libsrc/plus4/tgi_stddrv.s | 13 + samples/Makefile | 24 +- samples/tgidemo.c | 4 +- 12 files changed, 1040 insertions(+), 11 deletions(-) create mode 100644 cfg/plus4-hires.cfg create mode 100644 libsrc/plus4/tgi/ted-hi.s create mode 100644 libsrc/plus4/tgi_stat_stddrv.s create mode 100644 libsrc/plus4/tgi_stddrv.s diff --git a/cfg/plus4-hires.cfg b/cfg/plus4-hires.cfg new file mode 100644 index 000000000..f3040a2db --- /dev/null +++ b/cfg/plus4-hires.cfg @@ -0,0 +1,57 @@ +# Linker configuration that allows for a hi-res bitmap at $C000-$DF3F, but +# puts the stack (and a "HIBSS" segment) in the remaining RAM at $DF40-$FD00. + +FEATURES { + STARTADDRESS: default = $1001; +} +SYMBOLS { + __LOADADDR__: type = import; + __EXEHDR__: type = import; + __STACKSIZE__: type = weak, value = $0800; # 2k stack + __HIMEM__: type = weak, value = $FD00; + __RESERVED_C000__: type = weak, value = 8000; # Reserve 8000 bytes for hi-res bitmap +} +MEMORY { + # Memory reserved for bitmap + RESERVED: file = "", define = yes, start = $C000, size = __RESERVED_C000__; + + ZP: file = "", define = yes, start = $0002, size = $001A; + LOADADDR: file = %O, start = %S - 2, size = $0002; + HEADER: file = %O, define = yes, start = %S, size = $000D; + MAIN: file = %O, define = yes, start = __HEADER_LAST__, size = __RESERVED_START__ - __MAIN_START__; + + # Space between bitmap and top of memory + HIRAM: file = "", define = yes, start = __RESERVED_LAST__, size = __HIMEM__ - __HIRAM_START__ - __STACKSIZE__; +} +SEGMENTS { + ZEROPAGE: load = ZP, type = zp; + LOADADDR: load = LOADADDR, type = ro; + EXEHDR: load = HEADER, type = ro; + STARTUP: load = MAIN, type = ro; + LOWCODE: load = MAIN, type = ro, optional = yes; + CODE: load = MAIN, type = ro; + ONCE: load = MAIN, type = ro, optional = yes; + RODATA: load = MAIN, type = ro; + DATA: load = MAIN, type = rw; + INIT: load = MAIN, type = bss; + BSS: load = MAIN, type = bss, define = yes; + + # Allow data between bitmap and top of memory to be used as a second BSS + # space. Define symbols for it so that it can be supplied to _heapadd(). + HIBSS: load = HIRAM, type = bss, optional = yes, define = yes; +} +FEATURES { + CONDES: type = constructor, + label = __CONSTRUCTOR_TABLE__, + count = __CONSTRUCTOR_COUNT__, + segment = ONCE; + CONDES: type = destructor, + label = __DESTRUCTOR_TABLE__, + count = __DESTRUCTOR_COUNT__, + segment = RODATA; + CONDES: type = interruptor, + label = __INTERRUPTOR_TABLE__, + count = __INTERRUPTOR_COUNT__, + segment = RODATA, + import = __CALLIRQ__; +} diff --git a/doc/plus4.sgml b/doc/plus4.sgml index 11468bb33..c74854ffb 100644 --- a/doc/plus4.sgml +++ b/doc/plus4.sgml @@ -164,8 +164,26 @@ The names in the parentheses denote the symbols to be used for static linking of Graphics drivers

-No graphics drivers are currently available for the Plus/4. + + + This driver features a resolution of 320*200 with two colors and an + adjustable palette (that means that the two colors can be chosen out of a + palette of the 121 TED colors). + Note that the text-mode character matrix and color data are destroyed by this + driver. The driver calls the Kernal

Extended memory drivers

diff --git a/include/cbm264.h b/include/cbm264.h index 5e8a242a7..5b8b3d6ff 100644 --- a/include/cbm264.h +++ b/include/cbm264.h @@ -112,7 +112,24 @@ #define COLOR_LIGHTBLUE (BCOLOR_LIGHTBLUE | CATTR_LUMA7) #define COLOR_GRAY3 (BCOLOR_WHITE | CATTR_LUMA5) - +/* TGI color defines */ +#define TGI_COLOR_BLACK COLOR_BLACK +#define TGI_COLOR_WHITE COLOR_WHITE +#define TGI_COLOR_RED COLOR_RED +#define TGI_COLOR_CYAN COLOR_CYAN +#define TGI_COLOR_VIOLET COLOR_VIOLET +#define TGI_COLOR_PURPLE COLOR_PURPLE +#define TGI_COLOR_GREEN COLOR_GREEN +#define TGI_COLOR_BLUE COLOR_BLUE +#define TGI_COLOR_YELLOW COLOR_YELLOW +#define TGI_COLOR_ORANGE COLOR_ORANGE +#define TGI_COLOR_BROWN COLOR_BROWN +#define TGI_COLOR_LIGHTRED COLOR_LIGHTRED +#define TGI_COLOR_GRAY1 COLOR_GRAY1 +#define TGI_COLOR_GRAY2 COLOR_GRAY2 +#define TGI_COLOR_LIGHTGREEN COLOR_LIGHTGREEN +#define TGI_COLOR_LIGHTBLUE COLOR_LIGHTBLUE +#define TGI_COLOR_GRAY3 COLOR_GRAY3 /* Masks for joy_read */ #define JOY_UP_MASK 0x01 diff --git a/include/plus4.h b/include/plus4.h index c8aaf2eaf..7ff73fc94 100644 --- a/include/plus4.h +++ b/include/plus4.h @@ -57,7 +57,7 @@ /* The addresses of the static drivers */ extern void plus4_stdjoy_joy[]; /* Referred to by joy_static_stddrv[] */ extern void plus4_stdser_ser[]; - +extern void ted_hi_tgi[]; /* End of plus4.h */ diff --git a/libsrc/plus4/cgetc.s b/libsrc/plus4/cgetc.s index 62863c06e..8c8bb0082 100644 --- a/libsrc/plus4/cgetc.s +++ b/libsrc/plus4/cgetc.s @@ -18,11 +18,16 @@ _cgetc: lda KEY_COUNT ; Get number of characters ora FKEY_COUNT ; Or with number of function key chars bne L2 ; Jump if there are already chars waiting + lda #%00100000 + bit $FF06 + bne L2 ; always disable cursor if in bitmap mode + ; Switch on the cursor if needed ldy CURS_X lda (CRAM_PTR),y ; Get current char pha ; And save it + lda CHARCOLOR sta (CRAM_PTR),y diff --git a/libsrc/plus4/crt0.s b/libsrc/plus4/crt0.s index 2262b4c42..268914ef8 100644 --- a/libsrc/plus4/crt0.s +++ b/libsrc/plus4/crt0.s @@ -9,8 +9,7 @@ .import callirq_y, initlib, donelib .import callmain, zerobss .import __INTERRUPTOR_COUNT__ - .import __MAIN_START__, __MAIN_SIZE__ ; Linker generated - .import __STACKSIZE__ ; Linker generated + .import __HIMEM__ ; Linker generated .importzp ST .include "zeropage.inc" @@ -52,8 +51,8 @@ L1: lda sp,x tsx stx spsave ; Save system stk ptr - lda #<(__MAIN_START__ + __MAIN_SIZE__ + __STACKSIZE__) - ldx #>(__MAIN_START__ + __MAIN_SIZE__ + __STACKSIZE__) + lda #<__HIMEM__ + ldx #>__HIMEM__ sta sp stx sp+1 diff --git a/libsrc/plus4/libref.s b/libsrc/plus4/libref.s index 0bda1e7e8..62c78b8c5 100644 --- a/libsrc/plus4/libref.s +++ b/libsrc/plus4/libref.s @@ -2,8 +2,9 @@ ; Oliver Schmidt, 2013-05-31 ; - .export joy_libref, ser_libref + .export joy_libref, ser_libref, tgi_libref .import _exit joy_libref := _exit ser_libref := _exit +tgi_libref := _exit diff --git a/libsrc/plus4/tgi/ted-hi.s b/libsrc/plus4/tgi/ted-hi.s new file mode 100644 index 000000000..e3207600a --- /dev/null +++ b/libsrc/plus4/tgi/ted-hi.s @@ -0,0 +1,883 @@ +; +; Graphics driver for the 320x200x2 mode on Commodore Plus/4 systems. +; +; Luminance/Chrominance matrices at $800/$C00, overwriting text-mode character +; and color data. Bitmap is at $C000-$DF3F. Programs using this driver should +; either be linked with the option '-D __HIMEM__=0xC000'. +; +; Based on the c64-hi TGI driver, which in turn was based on Stephen L. Judd's +; GRLIB code. +; +; 2017-01-13, Greg King +; 2018-03-13, Sven Klose +; 2019-10-23, Richard Halkyard +; + .include "zeropage.inc" + + .include "tgi-kernel.inc" + .include "tgi-error.inc" + + .include "cbm_kernal.inc" + .include "plus4.inc" + + .macpack generic + .macpack module + +; ------------------------------------------------------------------------ +; Header. Includes jump table and constants. + + module_header _ted_hi_tgi + +; 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 + .addr $0000 ; Library reference + .word 320 ; X resolution + .word 200 ; Y resolution + .byte 2 ; Number of drawing colors + .byte 1 ; Number of screens available + .byte 8 ; System font X size + .byte 8 ; System font Y size + .word $00D4 ; Aspect ratio (based on 4/3 display) + .byte 0 ; TGI driver flags + +; Next comes the jump table. With the exception of IRQ, all entries must be +; valid and may point to an RTS for test versions (function not implemented). + + .addr INSTALL + .addr UNINSTALL + .addr INIT + .addr DONE + .addr GETERROR + .addr CONTROL + .addr CLEAR + .addr SETVIEWPAGE + .addr SETDRAWPAGE + .addr SETCOLOR + .addr SETPALETTE + .addr GETPALETTE + .addr GETDEFPALETTE + .addr SETPIXEL + .addr GETPIXEL + .addr LINE + .addr BAR + .addr TEXTSTYLE + .addr 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 +TEXT := ptr3 + +TEMP := tmp4 +TEMP2 := sreg +POINT := regsave + +CHUNK := X2 ; Used in the line routine +OLDCHUNK := X2+1 ; Dito + +; 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 + +; Line routine stuff +DX: .res 2 +DY: .res 2 + +; BAR variables +X1SAVE: .res 2 +Y1SAVE: .res 2 +X2SAVE: .res 2 +Y2SAVE: .res 2 + +; Text output stuff +TEXTMAGX: .res 1 +TEXTMAGY: .res 1 +TEXTDIR: .res 1 + +; Constants and tables + +.rodata + +DEFPALETTE: .byte $00, $71 ; White on black +PALETTESIZE = * - DEFPALETTE + +BITTAB: .byte $80,$40,$20,$10,$08,$04,$02,$01 +BITCHUNK: .byte $FF,$7F,$3F,$1F,$0F,$07,$03,$01 + +CHARROM := $D000 ; Character rom base address + +; The TED uses the CPU's memory configuration to fetch color data! Although +; we run with ROMs banked out, putting color data in banked RAM (above $8000) +; will result in color artifacts appearing when we bank ROM back in for +; interrupts and Kernal calls. Bitmap data is not affected by this limitation, +; but since there is no way to access RAM under IO (FE00-FF40), we can't put the +; bitmap at $E000 like we do on the C64, and have to use the next lowest +; position at $C000. + +LBASE := $0800 ; Luminance memory base address +VBASE := $C000 ; Bitmap base address + +CBASE := LBASE + $400 ; Chrominance memory base address (fixed relative to LBASE) +CHRBASE := $0800 ; Base address of text mode data + +.assert LBASE .mod $0800 = 0, error, "Luma/Chroma memory base address must be a multiple of 2K" +.assert VBASE .mod $2000 = 0, error, "Bitmap base address must be a multiple of 8K" +.assert LBASE + $800 < $8000, warning, "Luma/Chroma memory overlaps ROM. This will produce color artifacts." +.assert VBASE + $2000 < $FE00, error, "Bitmap overlaps IO space" + +.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: +; rts ; fall through + + +; ------------------------------------------------------------------------ +; 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: + +; Initialize variables + + ldx #$FF + stx BITMASK + +; Switch into graphics mode + lda $FF12 ; Set bitmap address and enable fetch from RAM + and #%00000011 + ora #(>VBASE >> 2) + sta $FF12 + +.if LBASE <> CHRBASE + lda #>LBASE ; Set color memory address + sta $FF14 +.endif + + lda $FF06 ; Enable bitmap mode + ora #%00100000 + sta $FF06 + +; 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: lda $FF12 + ora #%00000100 ; fetch from ROM + sta $FF12 + +.if LBASE <> CHRBASE + lda #>CHRBASE ; Reset character/color matrix address + sta $FF14 +.else + sta ENABLE_ROM ; Clear text display since we clobbered it + jsr CLRSCR + sta ENABLE_RAM +.endif + + lda $FF06 + and #%11011111 ; exit bitmap mode + sta $FF06 + + rts + +; ------------------------------------------------------------------------ +; 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: ldy #$00 + tya +@L1: sta VBASE+$0000,y + sta VBASE+$0100,y + sta VBASE+$0200,y + sta VBASE+$0300,y + sta VBASE+$0400,y + sta VBASE+$0500,y + sta VBASE+$0600,y + sta VBASE+$0700,y + sta VBASE+$0800,y + sta VBASE+$0900,y + sta VBASE+$0A00,y + sta VBASE+$0B00,y + sta VBASE+$0C00,y + sta VBASE+$0D00,y + sta VBASE+$0E00,y + sta VBASE+$0F00,y + sta VBASE+$1000,y + sta VBASE+$1100,y + sta VBASE+$1200,y + sta VBASE+$1300,y + sta VBASE+$1400,y + sta VBASE+$1500,y + sta VBASE+$1600,y + sta VBASE+$1700,y + sta VBASE+$1800,y + sta VBASE+$1900,y + sta VBASE+$1A00,y + sta VBASE+$1B00,y + sta VBASE+$1C00,y + sta VBASE+$1D00,y + sta VBASE+$1E00,y + sta VBASE+$1E40,y + iny + 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 ; fall through + +; ------------------------------------------------------------------------ +; 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 + sta PALETTE,y + dey + bpl @L1 + +; Get luma values from the high nybble of the palette entries + lda PALETTE+1 ; Foreground luma + lsr a + lsr a + lsr a + lsr a + sta TEMP ; Foreground -> low nybble + lda PALETTE ; Background luma + and #$F0 + ora TEMP ; Background -> high nybble + +; Initialize the luma map with the new luma values + ldy #0 +@L2: sta LBASE+$0000,y + sta LBASE+$0100,y + sta LBASE+$0200,y + sta LBASE+$02e8,y + iny + bne @L2 + + +; Get chroma values from the low nybble of the palette entries + lda PALETTE+1 ; Foreground chroma + and #$0F + asl a + asl a + asl a + asl a + sta TEMP ; Foreground -> high nybble + lda PALETTE ; Background chroma + and #$0F + ora TEMP ; Background -> low nybble + +; Initialize the chroma map with the new chroma values + ldy #0 +@L3: sta CBASE+$0000,y + sta CBASE+$0100,y + sta CBASE+$0200,y + sta CBASE+$02e8,y + iny + bne @L3 + +; Done, reset the error code + lda #TGI_ERR_OK + 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: + lda #PALETTE + rts + +; ------------------------------------------------------------------------ +; 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 +; + +SETPIXEL: + jsr CALC ; Calculate coordinates + + lda (POINT),Y + eor BITMASK + and BITTAB,X + eor (POINT),Y + sta (POINT),Y + +@L9: rts + +; ------------------------------------------------------------------------ +; 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: + jsr CALC ; Calculate coordinates + + lda (POINT),Y + ldy #$00 + and BITTAB,X + beq @L1 + iny + +@L1: + tya ; Get color value into A + ldx #$00 ; Clear high byte + 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. +; +; X1,X2 etc. are set up above (x2=LINNUM in particular) +; Format is LINE x2,y2,x1,y1 +; +; Must set an error code: NO +; + +LINE: + +@CHECK: lda X2 ;Make sure x1=y1? + lda Y1 ;Otherwise dy=y1-y2 + sec + sbc Y2 + tay + ldx #$88 ;DEY + +@DYPOS: sty DY ; 8-bit DY -- FIX ME? + stx YINCDEC + stx XINCDEC + + jsr CALC ; Set up .X, .Y, and POINT + lda BITCHUNK,X + sta OLDCHUNK + sta CHUNK + + ldx DY + cpx DX ;Who's bigger: dy or dx? + bcc STEPINX ;If dx, then... + lda DX+1 + bne STEPINX + +; +; Big steps in Y +; +; To simplify my life, just use PLOT to plot points. +; +; No more! +; Added special plotting routine -- cool! +; +; X is now counter, Y is y-coordinate +; +; On entry, X=DY=number of loop iterations, and Y= +; Y1 AND #$07 +STEPINY: + lda #00 + sta OLDCHUNK ;So plotting routine will work right + lda CHUNK + lsr ;Strip the bit + eor CHUNK + sta CHUNK + txa + beq YCONT2 ;If dy=0, it's just a point +@CONT: lsr ;Init counter to dy/2 +; +; Main loop +; +YLOOP: sta TEMP + + lda (POINT),y + eor BITMASK + and CHUNK + eor (POINT),y + sta (POINT),y +YINCDEC: + iny ;Advance Y coordinate + cpy #8 + bcc @CONT ;No prob if Y=0..7 + jsr FIXY +@CONT: lda TEMP ;Restore A + sec + sbc DX + bcc YFIXX +YCONT: dex ;X is counter + bne YLOOP +YCONT2: lda (POINT),y ;Plot endpoint + eor BITMASK + and CHUNK + eor (POINT),y + sta (POINT),y + rts + +YFIXX: ;x=x+1 + adc DY + lsr CHUNK + bne YCONT ;If we pass a column boundary... + ror CHUNK ;then reset CHUNK to $80 + sta TEMP2 + lda POINT ;And add 8 to POINT + adc #8 + sta POINT + bcc @CONT + inc POINT+1 +@CONT: lda TEMP2 + dex + bne YLOOP + beq YCONT2 + +; +; Big steps in X direction +; +; On entry, X=DY=number of loop iterations, and Y= +; Y1 AND #$07 + +.bss +COUNTHI: + .byte $00 ;Temporary counter + ;only used once +.code +STEPINX: + ldx DX + lda DX+1 + sta COUNTHI + cmp #$80 + ror ;Need bit for initialization + sta Y1 ;High byte of counter + txa + bne @CONT ;Could be $100 + dec COUNTHI +@CONT: ror +; +; Main loop +; +XLOOP: lsr CHUNK + beq XFIXC ;If we pass a column boundary... +XCONT1: sbc DY + bcc XFIXY ;Time to step in Y? +XCONT2: dex + bne XLOOP + dec COUNTHI ;High bits set? + bpl XLOOP + + lsr CHUNK ;Advance to last point + jmp LINEPLOT ;Plot the last chunk +; +; CHUNK has passed a column, so plot and increment pointer +; and fix up CHUNK, OLDCHUNK. +; +XFIXC: sta TEMP + jsr LINEPLOT + lda #$FF + sta CHUNK + sta OLDCHUNK + lda POINT + clc + adc #8 + sta POINT + lda TEMP + bcc XCONT1 + inc POINT+1 + jmp XCONT1 +; +; Check to make sure there isn't a high bit, plot chunk, +; and update Y-coordinate. +; +XFIXY: dec Y1 ;Maybe high bit set + bpl XCONT2 + adc DX + sta TEMP + lda DX+1 + adc #$FF ;Hi byte + sta Y1 + + jsr LINEPLOT ;Plot chunk + lda CHUNK + sta OLDCHUNK + + lda TEMP +XINCDEC: + iny ;Y-coord + cpy #8 ;0..7 is ok + bcc XCONT2 + sta TEMP + jsr FIXY + lda TEMP + jmp XCONT2 + +; +; Subroutine to plot chunks/points (to save a little +; room, gray hair, etc.) +; +LINEPLOT: ; Plot the line chunk + lda (POINT),Y + eor BITMASK + ora CHUNK + and OLDCHUNK + eor CHUNK + eor (POINT),Y + sta (POINT),Y + rts + +; +; Subroutine to fix up pointer when Y decreases through +; zero or increases through 7. +; +FIXY: cpy #255 ;Y=255 or Y=8 + beq @DECPTR + +@INCPTR: ;Add 320 to pointer + ldy #0 ;Y increased through 7 + lda POINT + adc #<320 + sta POINT + lda POINT+1 + adc #>320 + sta POINT+1 + rts + +@DECPTR: ;Okay, subtract 320 then + ldy #7 ;Y decreased through 0 + lda POINT + sec + sbc #<320 + sta POINT + lda POINT+1 + sbc #>320 + sta POINT+1 + rts + +; ------------------------------------------------------------------------ +; BAR: Draw a filled rectangle with the corners X1/Y1, X2/Y2, where +; X1/Y1 = ptr1/ptr2 and X2/Y2 = ptr3/ptr4 using the current drawing color. +; Contrary to most other functions, the graphics kernel will sort and clip +; the coordinates before calling the driver, so on entry the following +; conditions are valid: +; X1 <= X2 +; Y1 <= Y2 +; (X1 >= 0) && (X1 < XRES) +; (X2 >= 0) && (X2 < XRES) +; (Y1 >= 0) && (Y1 < YRES) +; (Y2 >= 0) && (Y2 < YRES) +; +; Must set an error code: NO +; + +; Note: This function needs optimization. It's just a cheap translation of +; the original C wrapper and could be written much smaller (besides that, +; calling LINE is not a good idea either). + +BAR: lda Y2 + sta Y2SAVE + lda Y2+1 + sta Y2SAVE+1 + + lda X2 + sta X2SAVE + lda X2+1 + sta X2SAVE+1 + + lda Y1 + sta Y1SAVE + lda Y1+1 + sta Y1SAVE+1 + + lda X1 + sta X1SAVE + lda X1+1 + sta X1SAVE+1 + +@L1: lda Y1 + sta Y2 + lda Y1+1 + sta Y2+1 + jsr LINE + + lda Y1SAVE + cmp Y2SAVE + bne @L2 + lda Y1SAVE + cmp Y2SAVE + beq @L4 + +@L2: inc Y1SAVE + bne @L3 + inc Y1SAVE+1 + +@L3: lda Y1SAVE + sta Y1 + lda Y1SAVE+1 + sta Y1+1 + + lda X1SAVE + sta X1 + lda X1SAVE+1 + sta X1+1 + + lda X2SAVE + sta X2 + lda X2SAVE+1 + sta X2+1 + jmp @L1 + +@L4: rts + + +; ------------------------------------------------------------------------ +; TEXTSTYLE: Set the style used when calling OUTTEXT. Text scaling in X and Y +; direction is passend in X/Y, the text direction is passed in A. +; +; Must set an error code: NO +; + +TEXTSTYLE: + stx TEXTMAGX + sty TEXTMAGY + sta TEXTDIR + rts + + +; ------------------------------------------------------------------------ +; OUTTEXT: Output text at X/Y = ptr1/ptr2 using the current color and the +; current text style. The text to output is given as a zero terminated +; string with address in ptr3. +; +; Must set an error code: NO +; + +OUTTEXT: + +; Calculate a pointer to the representation of the character in the +; character ROM + +; ldx #((>(CHARROM + $0800)) >> 3) +; ldy #0 +; lda (TEXT),y +; bmi @L1 +; ldx #((>(CHARROM + $0000)) >> 3) +; @L1: stx ptr4+1 +; asl a +; rol ptr4+1 +; asl a +; rol ptr4+1 +; asl a +; rol ptr4+1 +; sta ptr4 + + + + + + rts + +; ------------------------------------------------------------------------ +; Calculate all variables to plot the pixel at X1/Y1. + +CALC: lda Y1 + sta TEMP2 + and #7 + tay + lda Y1+1 + lsr ; Neg is possible + ror TEMP2 + lsr + ror TEMP2 + lsr + ror TEMP2 + + lda #00 + sta POINT + lda TEMP2 + cmp #$80 + ror + ror POINT + cmp #$80 + ror + ror POINT ; row*64 + adc TEMP2 ; +row*256 + clc + adc #>VBASE ; +bitmap base + sta POINT+1 + + lda X1 + tax + and #$F8 + clc + adc POINT ; +(X AND #$F8) + sta POINT + lda X1+1 + adc POINT+1 + sta POINT+1 + txa + and #7 + tax + rts diff --git a/libsrc/plus4/tgi_stat_stddrv.s b/libsrc/plus4/tgi_stat_stddrv.s new file mode 100644 index 000000000..dc918eb8b --- /dev/null +++ b/libsrc/plus4/tgi_stat_stddrv.s @@ -0,0 +1,14 @@ +; +; Address of the static standard tgi driver +; +; Oliver Schmidt, 2012-11-01 +; +; const void tgi_static_stddrv[]; +; + + .export _tgi_static_stddrv + .import _ted_hi_tgi + +.rodata + +_tgi_static_stddrv := _ted_hi_tgi diff --git a/libsrc/plus4/tgi_stddrv.s b/libsrc/plus4/tgi_stddrv.s new file mode 100644 index 000000000..eac16905d --- /dev/null +++ b/libsrc/plus4/tgi_stddrv.s @@ -0,0 +1,13 @@ +; +; Name of the standard tgi driver +; +; Oliver Schmidt, 2011-05-02 +; +; const char tgi_stddrv[]; +; + + .export _tgi_stddrv + +.rodata + +_tgi_stddrv: .asciiz "ted-hi.tgi" diff --git a/samples/Makefile b/samples/Makefile index 69efbe43b..fd75695cd 100644 --- a/samples/Makefile +++ b/samples/Makefile @@ -94,6 +94,7 @@ ifneq ($(filter disk samples.%,$(MAKECMDGOALS)),) DIR2ATR ?= dir2atr DISK_c64 = samples.d64 + DISK_plus4 = samples.d64 DISK_apple2 = samples.dsk DISK_apple2enh = samples.dsk DISK_atari = samples.atr @@ -111,6 +112,9 @@ LDFLAGS_mandelbrot_apple2enh = --start-addr 0x4000 LDFLAGS_tgidemo_apple2 = --start-addr 0x4000 LDFLAGS_tgidemo_apple2enh = --start-addr 0x4000 +LDFLAGS_mandelbrot_plus4 = -C plus4-hires.cfg +LDFLAGS_tgidemo_plus4 = -C plus4-hires.cfg + # The Apple ][ needs the start address adjusted for the mousedemo LDFLAGS_mousedemo_apple2 = --start-addr 0x4000 @@ -168,6 +172,16 @@ EXELIST_c64 = \ sieve \ tgidemo +EXELIST_plus4 = \ + ascii \ + enumdevdir \ + gunzip65 \ + hello \ + mandelbrot \ + plasma \ + sieve \ + tgidemo + EXELIST_apple2 = \ ascii \ diodemo \ @@ -228,7 +242,15 @@ multdemo: multidemo.o ovrldemo: overlaydemo.o $(LD) $(LDFLAGS) -o $@ -C $(SYS)-overlay.cfg -m $@.map $^ $(SYS).lib -OVERLAYLIST := $(foreach I,1 2 3,multdemo.$I ovrldemo.$I) +OVERLAYLIST := + +ifneq ($(filter ovrldemo,$(EXELIST_$(SYS))),) +OVERLAYLIST += $(foreach I,1 2 3,ovrldemo.$I) +endif + +ifneq ($(filter multdemo,$(EXELIST_$(SYS))),) +OVERLAYLIST += $(foreach I,1 2 3,multdemo.$I) +endif # -------------------------------------------------------------------------- # Rule to make a CBM disk with all samples. Needs the c1541 program that comes diff --git a/samples/tgidemo.c b/samples/tgidemo.c index de743314e..23b10a540 100644 --- a/samples/tgidemo.c +++ b/samples/tgidemo.c @@ -12,8 +12,8 @@ # define DYN_DRV 1 #endif -#define COLOR_BACK TGI_COLOR_BLACK -#define COLOR_FORE TGI_COLOR_WHITE +#define COLOR_BACK 0 +#define COLOR_FORE 1 /*****************************************************************************/ From 89c8a988bfb72023824cf8ef8b528d2ad22dcff4 Mon Sep 17 00:00:00 2001 From: Richard Halkyard Date: Tue, 29 Oct 2019 22:44:29 -0500 Subject: [PATCH 02/60] Use Kernal locations for serial buffer ptrs --- libsrc/plus4/ser/plus4-stdser.s | 39 +++++++++++++++++---------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/libsrc/plus4/ser/plus4-stdser.s b/libsrc/plus4/ser/plus4-stdser.s index bb44a4cf9..9cdde2fc1 100644 --- a/libsrc/plus4/ser/plus4-stdser.s +++ b/libsrc/plus4/ser/plus4-stdser.s @@ -64,15 +64,15 @@ ACIA_STATUS := ACIA+1 ; Status register ACIA_CMD := ACIA+2 ; Command register ACIA_CTRL := ACIA+3 ; Control register +RecvHead := $07D1 ; Head of receive buffer +RecvTail := $07D2 ; Tail of receive buffer +RecvFreeCnt := $07D3 ; Number of bytes in receive buffer ;---------------------------------------------------------------------------- ; ; Global variables ; .bss -RecvHead: .res 1 ; Head of receive buffer -RecvTail: .res 1 ; Tail of receive buffer -RecvFreeCnt: .res 1 ; Number of bytes in receive buffer SendHead: .res 1 ; Head of send buffer SendTail: .res 1 ; Tail of send buffer SendFreeCnt: .res 1 ; Number of bytes in send buffer @@ -353,26 +353,27 @@ SER_IOCTL: ; SER_IRQ: - lda ACIA_STATUS ; Check ACIA status for receive interrupt - and #$08 - beq @L9 ; Jump if no ACIA interrupt (carry still clear) - lda ACIA_DATA ; Get byte from ACIA - ldx RecvFreeCnt ; Check if we have free space left - beq @L1 ; Jump if no space in receive buffer - ldy RecvTail ; Load buffer pointer - sta RecvBuf,y ; Store received byte in buffer - inc RecvTail ; Increment buffer pointer - dec RecvFreeCnt ; Decrement free space counter - cpx #33 ; Check for buffer space low - bcc @L1 ; Assert flow control if buffer space low + lda ACIA_STATUS ;(4) ;status ;check for byte received + and #$08 ;(2) + beq @L9 ;(2*) + +@L1: lda ACIA_DATA ;(4) data ;get byte and put into receive buffer + ldy RecvTail ;(4) + ldx RecvFreeCnt ;(4) + beq @L3 ;(2*) Jump if no space in receive buffer + sta RecvBuf,y ;(5) + inc RecvTail ;(6) + dec RecvFreeCnt ;(6) + cpx #33 ;(2) check for buffer space low + bcc @L2 ;(2*) rts ; Return with carry set (interrupt handled) ; Assert flow control if buffer space too low -@L1: lda RtsOff - sta ACIA_CMD - sta Stopped - sec ; Interrupt handled +@L2: lda RtsOff ;(3) assert flow control if buffer space too low + sta ACIA_CMD ;(4) command + sta Stopped ;(3) +@L3: sec ; Interrupt handled @L9: rts ;---------------------------------------------------------------------------- From bf4c9c3c8c9d94e1ad404b69cd60e37e2b421b4a Mon Sep 17 00:00:00 2001 From: Richard Halkyard Date: Tue, 29 Oct 2019 22:45:22 -0500 Subject: [PATCH 03/60] Fix handling of IRQs that occur when ROM is active --- libsrc/plus4/crt0.s | 51 +++++++++++++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/libsrc/plus4/crt0.s b/libsrc/plus4/crt0.s index 268914ef8..610bc3116 100644 --- a/libsrc/plus4/crt0.s +++ b/libsrc/plus4/crt0.s @@ -64,6 +64,15 @@ L1: lda sp,x sta ENABLE_RAM stx $FFFE ; Install interrupt handler sty $FFFF + ldx IRQVec + ldy IRQVec+1 + stx IRQInd+1 + sty IRQInd+2 + ldx #IRQStub + stx IRQVec + sty IRQVec+1 + cli ; Allow interrupts ; Clear the BSS data. @@ -94,6 +103,13 @@ _exit: pha ; Save the return code lda #0 sta irqcount ; Disable custom IRQ handlers + sei + ldx IRQInd+1 + ldy IRQInd+2 + stx IRQVec + sty IRQVec+1 + cli + ; Copy back the zero-page stuff. ldx #zpspace-1 @@ -121,9 +137,13 @@ L2: lda zpsave,x ; IRQ handler. The handler in the ROM enables the Kernal, and jumps to ; $CE00, where the ROM code checks for a BRK or IRQ, and branches via the ; indirect vectors at $314/$316. -; To make our stub as fast as possible, we skip the whole part of the ROM -; handler, and jump to the indirect vectors directly. We do also call our -; own interrupt handlers if we have any; so, they need not use $314. +; +; When RAM is banked in, we skip the whole part of the ROM handler, and jump to +; the indirect vectors directly, after calling our own interrupt handlers. +; +; When ROM is banked in, a stub installed in the $314 indirect vector ensures +; that our interrupt handlers are still called (otherwise, interrupts that are +; not serviced by the ROM handler may cause a deadlock). .segment "LOWCODE" @@ -138,15 +158,6 @@ IRQ: cld ; Just to be sure and #$10 ; Test for BRK bit bne dobreak -; It's an IRQ; and, RAM is enabled. If we have handlers, call them. We will use -; a flag here instead of loading __INTERRUPTOR_COUNT__ directly, since the -; condes function is not reentrant. The irqcount flag will be set/reset from -; the main code, to avoid races. - - ldy irqcount - beq @L1 - jsr callirq_y ; Call the IRQ functions - ; Since the ROM handler will end with an RTI, we have to fake an IRQ return ; on the stack, so that we get control of the CPU after the ROM handler, ; and can switch back to RAM. @@ -160,7 +171,7 @@ IRQ: cld ; Just to be sure pha ; Push faked X register pha ; Push faked Y register sta ENABLE_ROM ; Switch to ROM - jmp (IRQVec) ; Jump indirect to Kernal IRQ handler + jmp (IRQVec) ; Jump indirect to IRQ stub irq_ret: sta ENABLE_RAM ; Switch back to RAM @@ -182,6 +193,20 @@ nohandler: sta ENABLE_ROM jmp (BRKVec) ; Jump indirect to the break vector + +; IRQ stub called by the Kernal IRQ handler, via $314. +; If we have handlers, call them. We will use a flag here instead of loading +; __INTERRUPTOR_COUNT__ directly, since the condes function is not reentrant. +; The irqcount flag will be set/reset from the main code, to avoid races. +IRQStub: + cld ; Just to be sure + sta ENABLE_RAM + ldy irqcount + beq @L1 + jsr callirq_y ; Call the IRQ functions +@L1: sta ENABLE_ROM + jmp (IRQInd+1) ; Jump to the saved IRQ vector + ; ------------------------------------------------------------------------ ; Data From 917e5d4f011ecea4111348f301d9ae53380099cd Mon Sep 17 00:00:00 2001 From: Richard Halkyard Date: Thu, 31 Oct 2019 11:01:00 -0500 Subject: [PATCH 04/60] Code-style fixes as per PR feedback --- cfg/plus4-hires.cfg | 2 +- libsrc/plus4/crt0.s | 34 +++++---- libsrc/plus4/ser/plus4-stdser.s | 34 ++++----- libsrc/plus4/tgi/ted-hi.s | 127 +++++++++++++------------------- 4 files changed, 88 insertions(+), 109 deletions(-) diff --git a/cfg/plus4-hires.cfg b/cfg/plus4-hires.cfg index f3040a2db..054e8c7f5 100644 --- a/cfg/plus4-hires.cfg +++ b/cfg/plus4-hires.cfg @@ -38,7 +38,7 @@ SEGMENTS { # Allow data between bitmap and top of memory to be used as a second BSS # space. Define symbols for it so that it can be supplied to _heapadd(). - HIBSS: load = HIRAM, type = bss, optional = yes, define = yes; + HIBSS: load = HIRAM, type = bss, optional = yes, define = yes; } FEATURES { CONDES: type = constructor, diff --git a/libsrc/plus4/crt0.s b/libsrc/plus4/crt0.s index 610bc3116..539c12641 100644 --- a/libsrc/plus4/crt0.s +++ b/libsrc/plus4/crt0.s @@ -58,20 +58,20 @@ L1: lda sp,x ; Set up the IRQ vector in the banked RAM; and, switch off the ROM. - ldx #IRQ + lda #IRQ sei ; No ints, handler not yet in place sta ENABLE_RAM - stx $FFFE ; Install interrupt handler - sty $FFFF - ldx IRQVec - ldy IRQVec+1 - stx IRQInd+1 - sty IRQInd+2 - ldx #IRQStub - stx IRQVec - sty IRQVec+1 + sta $FFFE ; Install interrupt handler + stx $FFFF + lda IRQVec + ldx IRQVec+1 + sta IRQInd+1 + stx IRQInd+2 + lda #IRQStub + sta IRQVec + stx IRQVec+1 cli ; Allow interrupts @@ -194,18 +194,20 @@ nohandler: jmp (BRKVec) ; Jump indirect to the break vector -; IRQ stub called by the Kernal IRQ handler, via $314. +; IRQ stub installed at $314, called by our handler above if RAM is banked in, +; or the Kernal IRQ handler if ROM is banked in. + ; If we have handlers, call them. We will use a flag here instead of loading ; __INTERRUPTOR_COUNT__ directly, since the condes function is not reentrant. ; The irqcount flag will be set/reset from the main code, to avoid races. IRQStub: - cld ; Just to be sure + cld ; Just to be sure sta ENABLE_RAM ldy irqcount beq @L1 - jsr callirq_y ; Call the IRQ functions + jsr callirq_y ; Call the IRQ functions @L1: sta ENABLE_ROM - jmp (IRQInd+1) ; Jump to the saved IRQ vector + jmp (IRQInd+1) ; Jump to the saved IRQ vector ; ------------------------------------------------------------------------ ; Data diff --git a/libsrc/plus4/ser/plus4-stdser.s b/libsrc/plus4/ser/plus4-stdser.s index 9cdde2fc1..ceb997214 100644 --- a/libsrc/plus4/ser/plus4-stdser.s +++ b/libsrc/plus4/ser/plus4-stdser.s @@ -88,7 +88,7 @@ SendBuf: .res 256 ; Tables used to translate RS232 params into register values -BaudTable: ; bit7 = 1 means setting is invalid +BaudTable: ; Bit7 = 1 means setting is invalid .byte $FF ; SER_BAUD_45_5 .byte $01 ; SER_BAUD_50 .byte $02 ; SER_BAUD_75 @@ -353,26 +353,26 @@ SER_IOCTL: ; SER_IRQ: - lda ACIA_STATUS ;(4) ;status ;check for byte received - and #$08 ;(2) - beq @L9 ;(2*) + lda ACIA_STATUS ; (4) Check for byte received + and #$08 ; (2) + beq @L9 ; (2*) -@L1: lda ACIA_DATA ;(4) data ;get byte and put into receive buffer - ldy RecvTail ;(4) - ldx RecvFreeCnt ;(4) - beq @L3 ;(2*) Jump if no space in receive buffer - sta RecvBuf,y ;(5) - inc RecvTail ;(6) - dec RecvFreeCnt ;(6) - cpx #33 ;(2) check for buffer space low - bcc @L2 ;(2*) + lda ACIA_DATA ; (4) Get byte and put into receive buffer + ldy RecvTail ; (4) + ldx RecvFreeCnt ; (4) + beq @L3 ; (2*) Jump if no space in receive buffer + sta RecvBuf,y ; (5) + inc RecvTail ; (6) + dec RecvFreeCnt ; (6) + cpx #33 ; (2) Check for buffer space low + bcc @L2 ; (2*) rts ; Return with carry set (interrupt handled) ; Assert flow control if buffer space too low -@L2: lda RtsOff ;(3) assert flow control if buffer space too low - sta ACIA_CMD ;(4) command - sta Stopped ;(3) +@L2: lda RtsOff ; (3) + sta ACIA_CMD ; (4) + sta Stopped ; (3) @L3: sec ; Interrupt handled @L9: rts @@ -396,7 +396,7 @@ SER_IRQ: @L2: lda ACIA_STATUS and #$10 bne @L4 - bit tmp1 ;keep trying if must try hard + bit tmp1 ; Keep trying if must try hard bmi @L0 @L3: rts diff --git a/libsrc/plus4/tgi/ted-hi.s b/libsrc/plus4/tgi/ted-hi.s index e3207600a..5a804c304 100644 --- a/libsrc/plus4/tgi/ted-hi.s +++ b/libsrc/plus4/tgi/ted-hi.s @@ -129,11 +129,11 @@ CHARROM := $D000 ; Character rom base address ; bitmap at $E000 like we do on the C64, and have to use the next lowest ; position at $C000. -LBASE := $0800 ; Luminance memory base address -VBASE := $C000 ; Bitmap base address +LBASE := $0800 ; Luminance memory base address +VBASE := $C000 ; Bitmap base address -CBASE := LBASE + $400 ; Chrominance memory base address (fixed relative to LBASE) -CHRBASE := $0800 ; Base address of text mode data +CBASE := LBASE + $400 ; Chrominance memory base address (fixed relative to LBASE) +CHRBASE := $0800 ; Base address of text mode data .assert LBASE .mod $0800 = 0, error, "Luma/Chroma memory base address must be a multiple of 2K" .assert VBASE .mod $2000 = 0, error, "Bitmap base address must be a multiple of 8K" @@ -151,7 +151,7 @@ CHRBASE := $0800 ; Base address of text mode data ; INSTALL: -; rts ; fall through +; rts ; Fall through ; ------------------------------------------------------------------------ @@ -216,7 +216,7 @@ INIT: ; DONE: lda $FF12 - ora #%00000100 ; fetch from ROM + ora #%00000100 ; Fetch from ROM sta $FF12 .if LBASE <> CHRBASE @@ -229,7 +229,7 @@ DONE: lda $FF12 .endif lda $FF06 - and #%11011111 ; exit bitmap mode + and #%11011111 ; Exit bitmap mode sta $FF06 rts @@ -306,7 +306,7 @@ CLEAR: ldy #$00 ; SETVIEWPAGE: -; rts ; fall through +; rts ; Fall through ; ------------------------------------------------------------------------ ; SETDRAWPAGE: Set the drawable page. Called with the new page in A (0..n). @@ -472,14 +472,14 @@ GETPIXEL: LINE: -@CHECK: lda X2 ;Make sure x1=y1? - lda Y1 ;Otherwise dy=y1-y2 + bpl @DYPOS ; Is y2>=y1? + lda Y1 ; Otherwise dy=y1-y2 sec sbc Y2 tay - ldx #$88 ;DEY + ldx #$88 ; DEY @DYPOS: sty DY ; 8-bit DY -- FIX ME? stx YINCDEC @@ -524,8 +524,8 @@ LINE: sta CHUNK ldx DY - cpx DX ;Who's bigger: dy or dx? - bcc STEPINX ;If dx, then... + cpx DX ; Who's bigger: dy or dx? + bcc STEPINX ; If dx, then... lda DX+1 bne STEPINX @@ -543,14 +543,14 @@ LINE: ; Y1 AND #$07 STEPINY: lda #00 - sta OLDCHUNK ;So plotting routine will work right + sta OLDCHUNK ; So plotting routine will work right lda CHUNK - lsr ;Strip the bit + lsr ; Strip the bit eor CHUNK sta CHUNK txa - beq YCONT2 ;If dy=0, it's just a point -@CONT: lsr ;Init counter to dy/2 + beq YCONT2 ; If dy=0, it's just a point +@CONT: lsr ; Init counter to dy/2 ; ; Main loop ; @@ -562,30 +562,30 @@ YLOOP: sta TEMP eor (POINT),y sta (POINT),y YINCDEC: - iny ;Advance Y coordinate + iny ; Advance Y coordinate cpy #8 - bcc @CONT ;No prob if Y=0..7 + bcc @CONT ; No prob if Y=0..7 jsr FIXY -@CONT: lda TEMP ;Restore A +@CONT: lda TEMP ; Restore A sec sbc DX bcc YFIXX -YCONT: dex ;X is counter +YCONT: dex ; X is counter bne YLOOP -YCONT2: lda (POINT),y ;Plot endpoint +YCONT2: lda (POINT),y ; Plot endpoint eor BITMASK and CHUNK eor (POINT),y sta (POINT),y rts -YFIXX: ;x=x+1 +YFIXX: ; X=x+1 adc DY lsr CHUNK - bne YCONT ;If we pass a column boundary... - ror CHUNK ;then reset CHUNK to $80 + bne YCONT ; If we pass a column boundary... + ror CHUNK ; Then reset CHUNK to $80 sta TEMP2 - lda POINT ;And add 8 to POINT + lda POINT ; And add 8 to POINT adc #8 sta POINT bcc @CONT @@ -603,34 +603,33 @@ YFIXX: ;x=x+1 .bss COUNTHI: - .byte $00 ;Temporary counter - ;only used once + .byte $00 ; Temporary counter, only used once. .code STEPINX: ldx DX lda DX+1 sta COUNTHI cmp #$80 - ror ;Need bit for initialization - sta Y1 ;High byte of counter + ror ; Need bit for initialization + sta Y1 ; High byte of counter txa - bne @CONT ;Could be $100 + bne @CONT ; Could be $100 dec COUNTHI @CONT: ror ; ; Main loop ; XLOOP: lsr CHUNK - beq XFIXC ;If we pass a column boundary... + beq XFIXC ; If we pass a column boundary... XCONT1: sbc DY - bcc XFIXY ;Time to step in Y? + bcc XFIXY ; Time to step in Y? XCONT2: dex bne XLOOP - dec COUNTHI ;High bits set? + dec COUNTHI ; High bits set? bpl XLOOP - lsr CHUNK ;Advance to last point - jmp LINEPLOT ;Plot the last chunk + lsr CHUNK ; Advance to last point + jmp LINEPLOT ; Plot the last chunk ; ; CHUNK has passed a column, so plot and increment pointer ; and fix up CHUNK, OLDCHUNK. @@ -652,22 +651,22 @@ XFIXC: sta TEMP ; Check to make sure there isn't a high bit, plot chunk, ; and update Y-coordinate. ; -XFIXY: dec Y1 ;Maybe high bit set +XFIXY: dec Y1 ; Maybe high bit set bpl XCONT2 adc DX sta TEMP lda DX+1 - adc #$FF ;Hi byte + adc #$FF ; Hi byte sta Y1 - jsr LINEPLOT ;Plot chunk + jsr LINEPLOT ; Plot chunk lda CHUNK sta OLDCHUNK lda TEMP XINCDEC: - iny ;Y-coord - cpy #8 ;0..7 is ok + iny ; Y-coord + cpy #8 ; 0..7 is ok bcc XCONT2 sta TEMP jsr FIXY @@ -692,11 +691,11 @@ LINEPLOT: ; Plot the line chunk ; Subroutine to fix up pointer when Y decreases through ; zero or increases through 7. ; -FIXY: cpy #255 ;Y=255 or Y=8 +FIXY: cpy #255 ; Y=255 or Y=8 beq @DECPTR -@INCPTR: ;Add 320 to pointer - ldy #0 ;Y increased through 7 +@INCPTR: ; Add 320 to pointer + ldy #0 ; Y increased through 7 lda POINT adc #<320 sta POINT @@ -705,8 +704,8 @@ FIXY: cpy #255 ;Y=255 or Y=8 sta POINT+1 rts -@DECPTR: ;Okay, subtract 320 then - ldy #7 ;Y decreased through 0 +@DECPTR: ; Okay, subtract 320 then + ldy #7 ; Y decreased through 0 lda POINT sec sbc #<320 @@ -815,28 +814,6 @@ TEXTSTYLE: ; OUTTEXT: - -; Calculate a pointer to the representation of the character in the -; character ROM - -; ldx #((>(CHARROM + $0800)) >> 3) -; ldy #0 -; lda (TEXT),y -; bmi @L1 -; ldx #((>(CHARROM + $0000)) >> 3) -; @L1: stx ptr4+1 -; asl a -; rol ptr4+1 -; asl a -; rol ptr4+1 -; asl a -; rol ptr4+1 -; sta ptr4 - - - - - rts ; ------------------------------------------------------------------------ @@ -862,10 +839,10 @@ CALC: lda Y1 ror POINT cmp #$80 ror - ror POINT ; row*64 - adc TEMP2 ; +row*256 + ror POINT ; Row * 64 + adc TEMP2 ; + Row * 256 clc - adc #>VBASE ; +bitmap base + adc #>VBASE ; + Bitmap base sta POINT+1 lda X1 From 2c9c7045229fffc6415a18209da2adc08b390449 Mon Sep 17 00:00:00 2001 From: Richard Halkyard Date: Thu, 31 Oct 2019 11:03:21 -0500 Subject: [PATCH 05/60] Use cl65 for linking samples ld65 doesn't accept a config option (needed for plus4 TGI demos) combined with -t, but cl65 does. --- samples/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/Makefile b/samples/Makefile index fd75695cd..1577cf955 100644 --- a/samples/Makefile +++ b/samples/Makefile @@ -149,9 +149,9 @@ LDFLAGS_tgidemo_atarixl = --start-addr 0x4000 .o: ifeq ($(SYS),vic20) - $(LD) $(LDFLAGS_$(@F)_$(SYS)) $(LDFLAGS) -o $@ -C vic20-32k.cfg -m $@.map $^ $(SYS).lib + $(CL) $(LDFLAGS_$(@F)_$(SYS)) $(LDFLAGS) -o $@ -C vic20-32k.cfg -m $@.map $^ $(SYS).lib else - $(LD) $(LDFLAGS_$(@F)_$(SYS)) $(LDFLAGS) -o $@ -t $(SYS) -m $@.map $^ $(SYS).lib + $(CL) $(LDFLAGS_$(@F)_$(SYS)) $(LDFLAGS) -o $@ -t $(SYS) -m $@.map $^ $(SYS).lib endif # -------------------------------------------------------------------------- From 44065f5e12a8c45bac5423780c2a7ce41f0d307e Mon Sep 17 00:00:00 2001 From: Richard Halkyard Date: Thu, 31 Oct 2019 11:05:57 -0500 Subject: [PATCH 06/60] Remove unncessary symbol --- cfg/plus4-hires.cfg | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/cfg/plus4-hires.cfg b/cfg/plus4-hires.cfg index 054e8c7f5..0426c8d8c 100644 --- a/cfg/plus4-hires.cfg +++ b/cfg/plus4-hires.cfg @@ -9,16 +9,15 @@ SYMBOLS { __EXEHDR__: type = import; __STACKSIZE__: type = weak, value = $0800; # 2k stack __HIMEM__: type = weak, value = $FD00; - __RESERVED_C000__: type = weak, value = 8000; # Reserve 8000 bytes for hi-res bitmap } MEMORY { - # Memory reserved for bitmap - RESERVED: file = "", define = yes, start = $C000, size = __RESERVED_C000__; + # Reserve 8000 bytes at $C000 for 320x200 bitmap + RESERVED: file = "", define = yes, start = $C000, size = 8000; - ZP: file = "", define = yes, start = $0002, size = $001A; - LOADADDR: file = %O, start = %S - 2, size = $0002; - HEADER: file = %O, define = yes, start = %S, size = $000D; - MAIN: file = %O, define = yes, start = __HEADER_LAST__, size = __RESERVED_START__ - __MAIN_START__; + ZP: file = "", define = yes, start = $0002, size = $001A; + LOADADDR: file = %O, start = %S - 2, size = $0002; + HEADER: file = %O, define = yes, start = %S, size = $000D; + MAIN: file = %O, define = yes, start = __HEADER_LAST__, size = __RESERVED_START__ - __MAIN_START__; # Space between bitmap and top of memory HIRAM: file = "", define = yes, start = __RESERVED_LAST__, size = __HIMEM__ - __HIRAM_START__ - __STACKSIZE__; From 0402fbd4b86a086e9a037e1f5eb469de46dc5e94 Mon Sep 17 00:00:00 2001 From: Richard Halkyard Date: Thu, 31 Oct 2019 11:07:33 -0500 Subject: [PATCH 07/60] Fix comment alignment --- libsrc/plus4/ser/plus4-stdser.s | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libsrc/plus4/ser/plus4-stdser.s b/libsrc/plus4/ser/plus4-stdser.s index ceb997214..5ce207634 100644 --- a/libsrc/plus4/ser/plus4-stdser.s +++ b/libsrc/plus4/ser/plus4-stdser.s @@ -64,9 +64,9 @@ ACIA_STATUS := ACIA+1 ; Status register ACIA_CMD := ACIA+2 ; Command register ACIA_CTRL := ACIA+3 ; Control register -RecvHead := $07D1 ; Head of receive buffer -RecvTail := $07D2 ; Tail of receive buffer -RecvFreeCnt := $07D3 ; Number of bytes in receive buffer +RecvHead := $07D1 ; Head of receive buffer +RecvTail := $07D2 ; Tail of receive buffer +RecvFreeCnt := $07D3 ; Number of bytes in receive buffer ;---------------------------------------------------------------------------- ; ; Global variables From 81ca41b73633a87ed03467cbf83b803ada570c3c Mon Sep 17 00:00:00 2001 From: Bob Andrews Date: Sun, 1 Jun 2025 23:19:51 +0200 Subject: [PATCH 08/60] kill dangling spaces --- libsrc/plus4/tgi/ted-hi.s | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libsrc/plus4/tgi/ted-hi.s b/libsrc/plus4/tgi/ted-hi.s index 5a804c304..61dd9c2c4 100644 --- a/libsrc/plus4/tgi/ted-hi.s +++ b/libsrc/plus4/tgi/ted-hi.s @@ -218,7 +218,7 @@ INIT: DONE: lda $FF12 ora #%00000100 ; Fetch from ROM sta $FF12 - + .if LBASE <> CHRBASE lda #>CHRBASE ; Reset character/color matrix address sta $FF14 @@ -366,7 +366,7 @@ SETPALETTE: sta LBASE+$02e8,y iny bne @L2 - + ; Get chroma values from the low nybble of the palette entries lda PALETTE+1 ; Foreground chroma @@ -455,7 +455,7 @@ GETPIXEL: beq @L1 iny -@L1: +@L1: tya ; Get color value into A ldx #$00 ; Clear high byte rts From d7c84d1434388eccf574cb4a385e4a8e5908d681 Mon Sep 17 00:00:00 2001 From: Bob Andrews Date: Sun, 1 Jun 2025 23:20:51 +0200 Subject: [PATCH 09/60] kill spaces --- libsrc/plus4/crt0.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsrc/plus4/crt0.s b/libsrc/plus4/crt0.s index 890ff6c2c..d1eea9472 100644 --- a/libsrc/plus4/crt0.s +++ b/libsrc/plus4/crt0.s @@ -197,7 +197,7 @@ nohandler: ; IRQ stub installed at $314, called by our handler above if RAM is banked in, ; or the Kernal IRQ handler if ROM is banked in. -; If we have handlers, call them. We will use a flag here instead of loading +; If we have handlers, call them. We will use a flag here instead of loading ; __INTERRUPTOR_COUNT__ directly, since the condes function is not reentrant. ; The irqcount flag will be set/reset from the main code, to avoid races. IRQStub: From a1fe6b84654d51f1a54a408b28b6dbed2e752fca Mon Sep 17 00:00:00 2001 From: Bob Andrews Date: Sun, 1 Jun 2025 23:22:44 +0200 Subject: [PATCH 10/60] kill spaces --- samples/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/Makefile b/samples/Makefile index 03835f06b..abdaa4ee8 100644 --- a/samples/Makefile +++ b/samples/Makefile @@ -451,7 +451,7 @@ multdemo: multidemo.o ovrldemo: overlaydemo.o $(LD) $(LDFLAGS) -o $@ -C $(SYS)-overlay.cfg -m $@.map $^ $(SYS).lib -OVERLAYLIST := +OVERLAYLIST := ifneq ($(filter ovrldemo,$(EXELIST_$(SYS))),) OVERLAYLIST += $(foreach I,1 2 3,ovrldemo.$I) From de524a6561a86e218225f3b21e3ca5881e4a2861 Mon Sep 17 00:00:00 2001 From: Konstantin Date: Wed, 4 Jun 2025 22:51:17 +0300 Subject: [PATCH 11/60] Initial Agat support --- asminc/agat.inc | 38 ++++++++++++++ cfg/agat.cfg | 44 ++++++++++++++++ include/agat.h | 67 ++++++++++++++++++++++++ libsrc/Makefile | 3 +- libsrc/agat/break.s | 113 ++++++++++++++++++++++++++++++++++++++++ libsrc/agat/cclear.s | 17 ++++++ libsrc/agat/cgetc.s | 23 ++++++++ libsrc/agat/clrscr.s | 10 ++++ libsrc/agat/color.s | 21 ++++++++ libsrc/agat/cout.s | 14 +++++ libsrc/agat/cputc.s | 45 ++++++++++++++++ libsrc/agat/crt0.s | 25 +++++++++ libsrc/agat/exehdr.s | 40 ++++++++++++++ libsrc/agat/gotoxy.s | 28 ++++++++++ libsrc/agat/gotoy.s | 18 +++++++ libsrc/agat/home.s | 15 ++++++ libsrc/agat/kbhit.s | 19 +++++++ libsrc/agat/randomize.s | 18 +++++++ libsrc/agat/revers.s | 38 ++++++++++++++ libsrc/agat/vtabz.s | 24 +++++++++ libsrc/agat/wherex.s | 19 +++++++ libsrc/agat/wherey.s | 17 ++++++ libsrc/agat/write.s | 50 ++++++++++++++++++ src/ca65/main.c | 4 ++ src/cc65/main.c | 4 ++ src/common/target.c | 22 +++++++- src/common/target.h | 1 + 27 files changed, 735 insertions(+), 2 deletions(-) create mode 100644 asminc/agat.inc create mode 100644 cfg/agat.cfg create mode 100644 include/agat.h create mode 100644 libsrc/agat/break.s create mode 100644 libsrc/agat/cclear.s create mode 100644 libsrc/agat/cgetc.s create mode 100644 libsrc/agat/clrscr.s create mode 100644 libsrc/agat/color.s create mode 100644 libsrc/agat/cout.s create mode 100644 libsrc/agat/cputc.s create mode 100644 libsrc/agat/crt0.s create mode 100644 libsrc/agat/exehdr.s create mode 100644 libsrc/agat/gotoxy.s create mode 100644 libsrc/agat/gotoy.s create mode 100644 libsrc/agat/home.s create mode 100644 libsrc/agat/kbhit.s create mode 100644 libsrc/agat/randomize.s create mode 100644 libsrc/agat/revers.s create mode 100644 libsrc/agat/vtabz.s create mode 100644 libsrc/agat/wherex.s create mode 100644 libsrc/agat/wherey.s create mode 100644 libsrc/agat/write.s diff --git a/asminc/agat.inc b/asminc/agat.inc new file mode 100644 index 000000000..84d21dbc2 --- /dev/null +++ b/asminc/agat.inc @@ -0,0 +1,38 @@ + +;----------------------------------------------------------------------------- +; Zero page stuff + +WNDLFT := $20 ; Text window left +WNDWDTH := $21 ; Text window width +WNDTOP := $22 ; Text window top +WNDBTM := $23 ; Text window bottom+1 +CH := $24 ; Cursor horizontal position +CV := $25 ; Cursor vertical position +BASL := $28 ; Text base address low +BASH := $29 ; Text base address high +CURSOR := $2D ; Cursor character +TATTR := $32 ; Text attributes +PROMPT := $33 ; Used by GETLN +VCOUT := $36 ; COUT Subroutine Vector +VCIN := $38 ; CIN Subroutine Vector +RNDL := $4E ; Random counter low +RNDH := $4F ; Random counter high +HIMEM := $73 ; Highest available memory address+1 + +;----------------------------------------------------------------------------- +; Vectors + +BRKVec := $03F0 ; Break vector +SOFTEV := $03F2 ; Vector for warm start +PWREDUP := $03F4 ; This must be = EOR #$A5 of SOFTEV+1 + +;----------------------------------------------------------------------------- +; Hardware + +; Keyboard input +KBD := $C000 ; Read keyboard +KBDSTRB := $C010 ; Clear keyboard strobe + +; Game controller +BUTN0 := $C061 ; Open-Apple Key +BUTN1 := $C062 ; Closed-Apple Key diff --git a/cfg/agat.cfg b/cfg/agat.cfg new file mode 100644 index 000000000..1a740cfc7 --- /dev/null +++ b/cfg/agat.cfg @@ -0,0 +1,44 @@ +# Default configuration + +FEATURES { + STARTADDRESS: default = $1903; +} +SYMBOLS { + __EXEHDR__: type = import; + __FILETYPE__: type = weak, value = $0006; # file type + __STACKSIZE__: type = weak, value = $0400; # 1k stack + __HIMEM__: type = weak, value = $C000; # Presumed RAM end +} +MEMORY { + ZP: file = "", define = yes, start = $0080, size = $001A; + HEADER: file = %O, start = %S - $003A, size = $003A; + MAIN: file = %O, define = yes, start = %S, size = __HIMEM__ - %S; + BSS: file = "", start = __ONCE_RUN__, size = __HIMEM__ - __STACKSIZE__ - __ONCE_RUN__; +} +SEGMENTS { + ZEROPAGE: load = ZP, type = zp; + EXEHDR: load = HEADER, type = ro, optional = yes; + STARTUP: load = MAIN, type = ro, optional = yes; + LOWCODE: load = MAIN, type = ro, optional = yes; + CODE: load = MAIN, type = ro; + RODATA: load = MAIN, type = ro; + DATA: load = MAIN, type = rw; + INIT: load = MAIN, type = rw, optional = yes; + ONCE: load = MAIN, type = ro, define = yes; + BSS: load = BSS, type = bss, define = yes; +} +FEATURES { + CONDES: type = constructor, + label = __CONSTRUCTOR_TABLE__, + count = __CONSTRUCTOR_COUNT__, + segment = ONCE; + CONDES: type = destructor, + label = __DESTRUCTOR_TABLE__, + count = __DESTRUCTOR_COUNT__, + segment = RODATA; + CONDES: type = interruptor, + label = __INTERRUPTOR_TABLE__, + count = __INTERRUPTOR_COUNT__, + segment = RODATA, + import = __CALLIRQ__; +} diff --git a/include/agat.h b/include/agat.h new file mode 100644 index 000000000..a8ed98bb0 --- /dev/null +++ b/include/agat.h @@ -0,0 +1,67 @@ +#ifndef _AGAT_H +#define _AGAT_H + +/* Check for errors */ +#if !defined(__AGAT__) +# error This module may only be used when compiling for the Agat! +#endif + + +/*****************************************************************************/ +/* Data */ +/*****************************************************************************/ + + + +/* Color defines */ +#define COLOR_BLACK 0x00 +#define COLOR_RED 0x01 +#define COLOR_GREEN 0x02 +#define COLOR_YELLOW 0x03 +#define COLOR_BLUE 0x04 +#define COLOR_MAGENTA 0x05 +#define COLOR_CYAN 0x06 +#define COLOR_WHITE 0x07 + +/* Characters codes */ +#define CH_ENTER 0x0D +#define CH_ESC 0x1B +#define CH_CURS_LEFT 0x08 +#define CH_CURS_RIGHT 0x15 + + +/* Masks for joy_read */ +#define JOY_UP_MASK 0x10 +#define JOY_DOWN_MASK 0x20 +#define JOY_LEFT_MASK 0x04 +#define JOY_RIGHT_MASK 0x08 +#define JOY_BTN_1_MASK 0x40 +#define JOY_BTN_2_MASK 0x80 + +/* Return codes for get_ostype */ +#define AGAT_UNKNOWN 0x00 +#define AGAT_7 0x10 /* Agat 7 */ +#define AGAT_9 0x20 /* Agat 9 */ + + +/*****************************************************************************/ +/* Code */ +/*****************************************************************************/ + +unsigned char get_ostype (void); +/* Get the machine type. Returns one of the AGAT_xxx codes. */ + +void rebootafterexit (void); +/* Reboot machine after program termination has completed. */ + +/* The following #defines will cause the matching functions calls in conio.h +** to be overlaid by macros with the same names, saving the function call +** overhead. +*/ +#define _bgcolor(color) COLOR_BLACK +#define _bordercolor(color) COLOR_BLACK + +/* End of agat.h */ + + +#endif //_AGAT_H diff --git a/libsrc/Makefile b/libsrc/Makefile index 8a4f11414..2f1b604d7 100644 --- a/libsrc/Makefile +++ b/libsrc/Makefile @@ -15,7 +15,8 @@ CBMS = c128 \ GEOS = geos-apple \ geos-cbm -TARGETS = apple2 \ +TARGETS = agat \ + apple2 \ apple2enh \ atari \ atarixl \ diff --git a/libsrc/agat/break.s b/libsrc/agat/break.s new file mode 100644 index 000000000..d46679ba2 --- /dev/null +++ b/libsrc/agat/break.s @@ -0,0 +1,113 @@ +; +; Ullrich von Bassewitz, 27.09.1998 +; Oleg A. Odintsov, Moscow, 2024 +; +; void __fastcall__ set_brk (unsigned Addr); +; void reset_brk (void); +; + + .export _set_brk, _reset_brk + .destructor _reset_brk + + ; Be sure to export the following variables absolute + .export _brk_a: abs, _brk_x: abs, _brk_y: abs + .export _brk_sr: abs, _brk_pc: abs + + .include "agat.inc" + +_brk_a = $45 +_brk_x = $46 +_brk_y = $47 +_brk_sr = $48 +_brk_sp = $49 +_brk_pc = $3A + +.bss +oldvec: .res 2 ; Old vector + + +.data +uservec: jmp $FFFF ; Patched at runtime + + +.code + +; Set the break vector +.proc _set_brk + + sta uservec+1 + stx uservec+2 ; Set the user vector + + lda oldvec + ora oldvec+1 ; Did we save the vector already? + bne L1 ; Jump if we installed the handler already + + lda BRKVec + sta oldvec + lda BRKVec+1 + sta oldvec+1 ; Save the old vector + +L1: lda #brk_handler + sta BRKVec + stx BRKVec+1 + rts + +.endproc + + +; Reset the break vector +.proc _reset_brk + + lda oldvec + ldx oldvec+1 + beq @L9 ; Jump if vector not installed + sta BRKVec + stx BRKVec+1 + lda #$00 + sta oldvec ; Clear the old vector + stx oldvec+1 +@L9: rts + +.endproc + + + +; Break handler, called if a break occurs + +.proc brk_handler + + sec + lda _brk_pc + sbc #$02 ; Point to start of brk + sta _brk_pc + lda _brk_pc+1 + sbc #$00 + sta _brk_pc+1 + + clc + lda _brk_sp + adc #$04 ; Adjust stack pointer + sta _brk_sp + + lda _brk_sr ; Clear brk + and #$EF + sta _brk_sr + + jsr uservec ; Call the user's routine + + lda _brk_pc+1 + pha + lda _brk_pc + pha + lda _brk_sr + pha + + ldx _brk_x + ldy _brk_y + lda _brk_a + + rti ; Jump back... + +.endproc + diff --git a/libsrc/agat/cclear.s b/libsrc/agat/cclear.s new file mode 100644 index 000000000..65ae10049 --- /dev/null +++ b/libsrc/agat/cclear.s @@ -0,0 +1,17 @@ +; +; Oleg A. Odintsov, Moscow, 2024 +; +; void __fastcall__ cclear (unsigned char length); +; + + .export _cclear + .import COUT + .include "zeropage.inc" + +_cclear: + sta ptr1 + lda #$A0 +next: jsr COUT + dec ptr1 + bne next + rts diff --git a/libsrc/agat/cgetc.s b/libsrc/agat/cgetc.s new file mode 100644 index 000000000..a4b1389d2 --- /dev/null +++ b/libsrc/agat/cgetc.s @@ -0,0 +1,23 @@ +; +; Oleg A. Odintsov, Moscow, 2024 +; +; char cgetc (void); +; + + .export _cgetc + .import cursor + .include "agat.inc" + +_cgetc: + lda #$DF ; _ + bit cursor + bne hascur + lda #$00 +hascur: sta CURSOR + jsr j1 + cmp #$A0 + bpl :+ + and #$7F +: rts +j1: jmp (VCIN) + diff --git a/libsrc/agat/clrscr.s b/libsrc/agat/clrscr.s new file mode 100644 index 000000000..2fe54607a --- /dev/null +++ b/libsrc/agat/clrscr.s @@ -0,0 +1,10 @@ +; +; Kevin Ruland +; +; void clrscr (void); +; + + .export _clrscr + .import HOME + +_clrscr := HOME diff --git a/libsrc/agat/color.s b/libsrc/agat/color.s new file mode 100644 index 000000000..c68b6c3f6 --- /dev/null +++ b/libsrc/agat/color.s @@ -0,0 +1,21 @@ +; +; Oleg A. Odintsov, Moscow, 2024 +; +; unsigned char __fastcall__ textcolor (unsigned char color); +; + + + .export _textcolor + .include "agat.inc" + + +_textcolor: + ldx TATTR + eor TATTR + and #$07 + eor TATTR + sta TATTR + txa + and #$0F + rts + diff --git a/libsrc/agat/cout.s b/libsrc/agat/cout.s new file mode 100644 index 000000000..30b054b7e --- /dev/null +++ b/libsrc/agat/cout.s @@ -0,0 +1,14 @@ +; +; Oleg A. Odintsov, Moscow, 2024 +; +; COUT routine +; + + .export COUT + .include "agat.inc" + +COUT: + cmp #$10 + bpl out + ora #$80 +out: jmp (VCOUT) diff --git a/libsrc/agat/cputc.s b/libsrc/agat/cputc.s new file mode 100644 index 000000000..b30b6c45c --- /dev/null +++ b/libsrc/agat/cputc.s @@ -0,0 +1,45 @@ +; +; Oleg A. Odintsov, Moscow, 2024 +; +; void __fastcall__ cputcxy (unsigned char x, unsigned char y, char c); +; void __fastcall__ cputc (char c); +; + + .import COUT + .export _cputcxy, _cputc + .import gotoxy, VTABZ + .include "agat.inc" + +_cputcxy: + pha + jsr gotoxy + pla +_cputc: + cmp #$0D + bne notleft + ldy #$00 + sty CH + rts +notleft:cmp #$0A + beq newline +putchar: + ldy CH + sta (BASL),Y + iny + lda TATTR + bmi wch + sta (BASL),Y + iny +wch: sty CH + cpy WNDWDTH + bcc noend + ldy #$00 + sty CH +newline:inc CV + lda CV + cmp WNDBTM + bcc :+ + lda WNDTOP + sta CV +: jmp VTABZ +noend: rts diff --git a/libsrc/agat/crt0.s b/libsrc/agat/crt0.s new file mode 100644 index 000000000..d678a79c8 --- /dev/null +++ b/libsrc/agat/crt0.s @@ -0,0 +1,25 @@ +; +; Startup code for cc65 (Agat version) +; + + .export __STARTUP__ : absolute = 1 ; Mark as startup + + .import initlib, donelib + .import zerobss, callmain + .import __ONCE_LOAD__, __ONCE_SIZE__ ; Linker generated + + .include "zeropage.inc" + .include "agat.inc" + +; ------------------------------------------------------------------------ + + .segment "STARTUP" + lda HIMEM + ldx HIMEM+1 + sta sp + stx sp+1 + jsr initlib + jsr zerobss + jsr callmain + jsr donelib + rts diff --git a/libsrc/agat/exehdr.s b/libsrc/agat/exehdr.s new file mode 100644 index 000000000..72ea390e9 --- /dev/null +++ b/libsrc/agat/exehdr.s @@ -0,0 +1,40 @@ +; +; Oliver Schmidt, 2012-06-10 +; +; This module supplies an AppleSingle version 2 file header + entry with +; ID 11 according to https://tools.ietf.org/rfc/rfc1740.txt Appendix A. +; + + .export __EXEHDR__ : absolute = 1 ; Linker referenced + .import __FILETYPE__ ; Linker generated + .import __MAIN_START__, __MAIN_LAST__ ; Linker generated + +; ------------------------------------------------------------------------ + +; Data Fork +ID01_LENGTH = __MAIN_LAST__ - __MAIN_START__ +ID01_OFFSET = ID01 - START + +; ProDOS File Info +ID11_LENGTH = ID01 - ID11 +ID11_OFFSET = ID11 - START + +; ------------------------------------------------------------------------ + + .segment "EXEHDR" + +START: .byte $00, $05, $16, $00 ; Magic number + .byte $00, $02, $00, $00 ; Version number + .res 16 ; Filler + .byte 0, 2 ; Number of entries + .byte 0, 0, 0, 1 ; Entry ID 1 - Data Fork + .byte 0, 0, >ID01_OFFSET, ID01_LENGTH, ID11_OFFSET, ID11_LENGTH, __FILETYPE__, <__FILETYPE__ ; File Type + .byte 0, 0 ; Auxiliary Type high + .byte >__MAIN_START__, <__MAIN_START__ ; Auxiliary Type low +ID01: diff --git a/libsrc/agat/gotoxy.s b/libsrc/agat/gotoxy.s new file mode 100644 index 000000000..2f9580c91 --- /dev/null +++ b/libsrc/agat/gotoxy.s @@ -0,0 +1,28 @@ +; +; Ullrich von Bassewitz, 06.08.1998 +; Oleg A. Odintsov, Moscow, 2024 +; +; void __fastcall__ gotoxy (unsigned char x, unsigned char y); +; void __fastcall__ gotox (unsigned char x); +; + + .export gotoxy, _gotoxy, _gotox + .import popa, VTABZ + + .include "agat.inc" + +gotoxy: + jsr popa ; Get Y +_gotoxy: + clc + adc WNDTOP + sta CV ; Store Y + jsr VTABZ + jsr popa ; Get X +_gotox: + bit TATTR + bmi t64 + asl +t64: + sta CH ; Store X + rts diff --git a/libsrc/agat/gotoy.s b/libsrc/agat/gotoy.s new file mode 100644 index 000000000..f4a8a4c4e --- /dev/null +++ b/libsrc/agat/gotoy.s @@ -0,0 +1,18 @@ +; +; Ullrich von Bassewitz, 06.08.1998 +; Oleg A. Odintsov, Moscow, 2024 +; +; void __fastcall__ gotoy (unsigned char y); +; + + .import VTABZ + .export _gotoy + .include "agat.inc" + +_gotoy: + clc + adc WNDTOP + sta CV + jmp VTABZ + + diff --git a/libsrc/agat/home.s b/libsrc/agat/home.s new file mode 100644 index 000000000..d3f000d25 --- /dev/null +++ b/libsrc/agat/home.s @@ -0,0 +1,15 @@ +; +; Oleg A. Odintsov, Moscow, 2024 +; +; HOME routine +; + + .export HOME + .import COUT + + .include "agat.inc" + +HOME: + lda #$8C + jsr COUT + rts diff --git a/libsrc/agat/kbhit.s b/libsrc/agat/kbhit.s new file mode 100644 index 000000000..f2bc4fc9f --- /dev/null +++ b/libsrc/agat/kbhit.s @@ -0,0 +1,19 @@ +; +; Kevin Ruland +; Ullrich von Bassewitz, 2005-03-25 +; Oleg A. Odintsov, Moscow, 2024 +; +; unsigned char kbhit (void); +; + + .export _kbhit + + .include "agat.inc" + +_kbhit: + lda KBD ; Reading KBD checks for keypress + rol ; if high bit is set, key was pressed + lda #$00 + tax + rol + rts diff --git a/libsrc/agat/randomize.s b/libsrc/agat/randomize.s new file mode 100644 index 000000000..914f40634 --- /dev/null +++ b/libsrc/agat/randomize.s @@ -0,0 +1,18 @@ +; +; Ullrich von Bassewitz, 07.11.2002 +; Oleg A. Odintsov, Moscow, 2024 +; +; void _randomize (void); +; /* Initialize the random number generator */ +; + + .export __randomize + .import _srand + + .include "apple2.inc" + +__randomize: + ldx RNDH ; Use random value supplied by ROM + lda RNDL + jmp _srand ; Initialize generator + diff --git a/libsrc/agat/revers.s b/libsrc/agat/revers.s new file mode 100644 index 000000000..ceca7cf5b --- /dev/null +++ b/libsrc/agat/revers.s @@ -0,0 +1,38 @@ +; +; Ullrich von Bassewitz, 2005-03-28 +; Oleg A. Odintsov, Moscow, 2024 +; +; unsigned char __fastcall__ revers (unsigned char onoff) +; unsigned char __fastcall__ flash (unsigned char onoff) +; + + .export _revers, _flash + + .include "agat.inc" + +_revers: + tax + beq noinv + lda TATTR + and #$D7 + sta TATTR + rts +noinv: + lda TATTR + ora #$20 + sta TATTR + rts + +_flash: + tax + beq noflash + lda TATTR + and #$DF + ora #$08 + sta TATTR + rts +noflash: + lda TATTR + ora #$20 + sta TATTR + rts diff --git a/libsrc/agat/vtabz.s b/libsrc/agat/vtabz.s new file mode 100644 index 000000000..a711a87c9 --- /dev/null +++ b/libsrc/agat/vtabz.s @@ -0,0 +1,24 @@ +; +; Oleg A. Odintsov, Moscow, 2024 +; +; VTABZ routine +; + + .export VTABZ + .include "agat.inc" + +VTABZ: + lda CV + ror + ror + ror + and #$C0 + sta BASL + lda CV + lsr + lsr + eor BASH + and #$07 + eor BASH + sta BASH + rts diff --git a/libsrc/agat/wherex.s b/libsrc/agat/wherex.s new file mode 100644 index 000000000..b6d277680 --- /dev/null +++ b/libsrc/agat/wherex.s @@ -0,0 +1,19 @@ +; +; Kevin Ruland +; Oleg A. Odintsov, Moscow, 2024 +; +; unsigned char wherex (void); +; + + .export _wherex + + .include "agat.inc" + +_wherex: + lda CH + bit TATTR + bmi t64 + lsr +t64: + ldx #$00 + rts diff --git a/libsrc/agat/wherey.s b/libsrc/agat/wherey.s new file mode 100644 index 000000000..4660a55f9 --- /dev/null +++ b/libsrc/agat/wherey.s @@ -0,0 +1,17 @@ +; +; Kevin Ruland +; Oleg A. Odintsov, Moscow, 2024 +; +; unsigned char wherey (void); +; + + .export _wherey + + .include "agat.inc" + +_wherey: + lda CV + sec + sbc WNDTOP + ldx #$00 + rts diff --git a/libsrc/agat/write.s b/libsrc/agat/write.s new file mode 100644 index 000000000..6ac28f32c --- /dev/null +++ b/libsrc/agat/write.s @@ -0,0 +1,50 @@ +; +; Oleg A. Odintsov, Moscow, 2024 +; +; int __fastcall__ write (int fd, const void* buf, unsigned count); +; + + .export _write + .import popax, popptr1 + .import COUT + + .include "zeropage.inc" + +_write: + sta ptr2 + stx ptr2+1 + jsr popptr1 + jsr popax + + ; Check for zero count + ora ptr2 + beq done + + ; Get char from buf +next: ldy #$00 + lda (ptr1),y + + ; Replace '\n' with '\r' + cmp #$0A + bne output + lda #$8D + + ; Set hi bit and write to device +output: + jsr COUT ; Preserves X and Y + + ; Increment pointer + inc ptr1 + bne :+ + inc ptr1+1 + + ; Decrement count +: dec ptr2 + bne next + dec ptr2+1 + bpl next + + ; Return success +done: lda #$00 + rts + diff --git a/src/ca65/main.c b/src/ca65/main.c index f3100162a..c99ce06c6 100644 --- a/src/ca65/main.c +++ b/src/ca65/main.c @@ -350,6 +350,10 @@ static void SetSys (const char* Sys) NewSymbol ("__RP6502__", 1); break; + case TGT_AGAT: + NewSymbol ("__AGAT__", 1); + break; + default: AbEnd ("Invalid target name: '%s'", Sys); diff --git a/src/cc65/main.c b/src/cc65/main.c index 47435757c..baf6f2f17 100644 --- a/src/cc65/main.c +++ b/src/cc65/main.c @@ -306,6 +306,10 @@ static void SetSys (const char* Sys) case TGT_RP6502: DefineNumericMacro ("__RP6502__", 1); break; + + case TGT_AGAT: + DefineNumericMacro ("__AGAT__", 1); + break; default: AbEnd ("Unknown target system '%s'", Sys); diff --git a/src/common/target.c b/src/common/target.c index b50478e16..761f7c3fd 100644 --- a/src/common/target.c +++ b/src/common/target.c @@ -129,7 +129,25 @@ static const unsigned char CTPET[256] = { 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF, }; - +/* Translation table KOI8-R -> Agat-9 */ +static unsigned char CTAgat[256] = { + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F, + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, + 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, + 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F, + 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F, + 0x1B,0x5C,0x10,0x12,0x1D,0x1F,0x13,0x1C,0x11,0x1E,0x14,0x8B,0x8C,0x8D,0x8E,0x8F, + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, + 0xA0,0xA1,0xA2,0x0F,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, + 0xB0,0xB1,0xB2,0x9F,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, + 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F, + 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F, + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF, +}; /* One entry in the target map */ typedef struct TargetEntry TargetEntry; @@ -142,6 +160,7 @@ struct TargetEntry { ** Allows multiple entries for one target ID (target name aliases). */ static const TargetEntry TargetMap[] = { + { "agat", TGT_AGAT }, { "apple2", TGT_APPLE2 }, { "apple2enh", TGT_APPLE2ENH }, { "atari", TGT_ATARI }, @@ -223,6 +242,7 @@ static const TargetProperties PropertyTable[TGT_COUNT] = { { "sym1", CPU_6502, BINFMT_BINARY, CTNone }, { "kim1", CPU_6502, BINFMT_BINARY, CTNone }, { "rp6502", CPU_65C02, BINFMT_BINARY, CTNone }, + { "agat", CPU_6502, BINFMT_BINARY, CTAgat }, }; /* Target system */ diff --git a/src/common/target.h b/src/common/target.h index 730b8211e..d6c9fc35b 100644 --- a/src/common/target.h +++ b/src/common/target.h @@ -89,6 +89,7 @@ typedef enum { TGT_SYM1, TGT_KIM1, TGT_RP6502, + TGT_AGAT, TGT_COUNT /* Number of target systems */ } target_t; From 5ff18c1ebc7179002b9be74262ea536d968ffaea Mon Sep 17 00:00:00 2001 From: Konstantin Date: Wed, 4 Jun 2025 23:11:13 +0300 Subject: [PATCH 12/60] Updates --- asminc/agat.inc | 1 + include/agat.h | 12 ++++++---- libsrc/agat/crt0.s | 57 ++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 62 insertions(+), 8 deletions(-) diff --git a/asminc/agat.inc b/asminc/agat.inc index 84d21dbc2..b96d31834 100644 --- a/asminc/agat.inc +++ b/asminc/agat.inc @@ -22,6 +22,7 @@ HIMEM := $73 ; Highest available memory address+1 ;----------------------------------------------------------------------------- ; Vectors +DOSWARM := $03D0 ; DOS warmstart vector BRKVec := $03F0 ; Break vector SOFTEV := $03F2 ; Vector for warm start PWREDUP := $03F4 ; This must be = EOR #$A5 of SOFTEV+1 diff --git a/include/agat.h b/include/agat.h index a8ed98bb0..6333170c7 100644 --- a/include/agat.h +++ b/include/agat.h @@ -24,10 +24,14 @@ #define COLOR_WHITE 0x07 /* Characters codes */ -#define CH_ENTER 0x0D -#define CH_ESC 0x1B -#define CH_CURS_LEFT 0x08 -#define CH_CURS_RIGHT 0x15 +#define CH_CTRL_C 0x03 +#define CH_ENTER 0x0D +#define CH_ESC 0x1B +#define CH_CURS_LEFT 0x08 +#define CH_CURS_RIGHT 0x15 +#define CH_CURS_UP 0x19 +#define CH_CURS_DOWN 0x1A +#define CH_ESC 0x1B /* Masks for joy_read */ diff --git a/libsrc/agat/crt0.s b/libsrc/agat/crt0.s index d678a79c8..9f8993332 100644 --- a/libsrc/agat/crt0.s +++ b/libsrc/agat/crt0.s @@ -3,6 +3,7 @@ ; .export __STARTUP__ : absolute = 1 ; Mark as startup + .export _exit .import initlib, donelib .import zerobss, callmain @@ -14,12 +15,60 @@ ; ------------------------------------------------------------------------ .segment "STARTUP" + jsr init + jsr zerobss + jsr callmain +_exit: ldx #exit + jsr reset + jsr donelib +exit: ldx #$02 +: lda rvsave,x + sta SOFTEV,x + dex + bpl :- + ldx #zpspace-1 +: lda zpsave,x + sta sp,x + dex + bpl :- + ldx #$FF + txs + jmp DOSWARM + + + + .segment "ONCE" + +init: ldx #zpspace-1 +: lda sp,x + sta zpsave,x + dex + bpl :- + + ldx #$02 +: lda SOFTEV,x + sta rvsave,x + dex + bpl :- + lda HIMEM ldx HIMEM+1 sta sp stx sp+1 - jsr initlib - jsr zerobss - jsr callmain - jsr donelib + ldx #<_exit + lda #>_exit + jsr reset + jmp initlib + + .code + +reset: stx SOFTEV + sta SOFTEV+1 + eor #$A5 + sta PWREDUP rts + + .segment "INIT" +zpsave: .res zpspace +rvsave: .res 3 From 79ecb2071cc15964467165fb2a756ed2d8a25c6f Mon Sep 17 00:00:00 2001 From: Bob Andrews Date: Thu, 5 Jun 2025 02:09:11 +0200 Subject: [PATCH 13/60] Update Makefile - use ld65, not cl65, for linking --- samples/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/Makefile b/samples/Makefile index abdaa4ee8..f0c6835bb 100644 --- a/samples/Makefile +++ b/samples/Makefile @@ -149,9 +149,9 @@ LDFLAGS_tgidemo_atarixl = --start-addr 0x4000 .o: ifeq ($(SYS),vic20) - $(CL) $(LDFLAGS_$(@F)_$(SYS)) $(LDFLAGS) -o $@ -C vic20-32k.cfg -m $@.map $^ $(SYS).lib + $(LD) $(LDFLAGS_$(@F)_$(SYS)) $(LDFLAGS) -o $@ -C vic20-32k.cfg -m $@.map $^ $(SYS).lib else - $(CL) $(LDFLAGS_$(@F)_$(SYS)) $(LDFLAGS) -o $@ -t $(SYS) -m $@.map $^ $(SYS).lib + $(LD) $(LDFLAGS_$(@F)_$(SYS)) $(LDFLAGS) -o $@ -t $(SYS) -m $@.map $^ $(SYS).lib endif # -------------------------------------------------------------------------- From c3b87779b7bf711dd35f8922e08886f7a6df9eee Mon Sep 17 00:00:00 2001 From: Bob Andrews Date: Thu, 5 Jun 2025 02:23:29 +0200 Subject: [PATCH 14/60] Update Makefile - link all Plus4 samples with plus4-hires.cfg - using the LDFLAGS mechanism for this does not work --- samples/Makefile | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/samples/Makefile b/samples/Makefile index f0c6835bb..44ef4377e 100644 --- a/samples/Makefile +++ b/samples/Makefile @@ -112,9 +112,6 @@ LDFLAGS_mandelbrot_apple2enh = --start-addr 0x4000 LDFLAGS_tgidemo_apple2 = --start-addr 0x4000 LDFLAGS_tgidemo_apple2enh = --start-addr 0x4000 -LDFLAGS_mandelbrot_plus4 = -C plus4-hires.cfg -LDFLAGS_tgidemo_plus4 = -C plus4-hires.cfg - # The Apple ][ needs the start address adjusted for the mousedemo LDFLAGS_mousedemo_apple2 = --start-addr 0x4000 @@ -150,6 +147,8 @@ LDFLAGS_tgidemo_atarixl = --start-addr 0x4000 .o: ifeq ($(SYS),vic20) $(LD) $(LDFLAGS_$(@F)_$(SYS)) $(LDFLAGS) -o $@ -C vic20-32k.cfg -m $@.map $^ $(SYS).lib +else ifeq ($(SYS),plus4) + $(LD) $(LDFLAGS_$(@F)_$(SYS)) $(LDFLAGS) -o $@ -C plus4-hires.cfg -m $@.map $^ $(SYS).lib else $(LD) $(LDFLAGS_$(@F)_$(SYS)) $(LDFLAGS) -o $@ -t $(SYS) -m $@.map $^ $(SYS).lib endif From 1a109c0b3438928e1dce045799ae678a576584d0 Mon Sep 17 00:00:00 2001 From: Konstantin Date: Sat, 7 Jun 2025 12:36:49 +0300 Subject: [PATCH 15/60] Fix codestyle --- include/agat.h | 50 +++++++++++----------- libsrc/agat/cclear.s | 18 ++++---- libsrc/agat/cgetc.s | 29 +++++++------ libsrc/agat/clrscr.s | 4 +- libsrc/agat/color.s | 21 +++++----- libsrc/agat/cout.s | 12 +++--- libsrc/agat/cputc.s | 68 +++++++++++++++--------------- libsrc/agat/crt0.s | 98 ++++++++++++++++++++++---------------------- libsrc/agat/gotoxy.s | 22 +++++----- libsrc/agat/gotoy.s | 16 ++++---- libsrc/agat/home.s | 6 +-- libsrc/agat/revers.s | 46 ++++++++++----------- libsrc/agat/vtabz.s | 32 +++++++-------- libsrc/agat/wherex.s | 12 +++--- 14 files changed, 215 insertions(+), 219 deletions(-) diff --git a/include/agat.h b/include/agat.h index 6333170c7..2cdf24ae6 100644 --- a/include/agat.h +++ b/include/agat.h @@ -14,38 +14,38 @@ /* Color defines */ -#define COLOR_BLACK 0x00 -#define COLOR_RED 0x01 -#define COLOR_GREEN 0x02 -#define COLOR_YELLOW 0x03 -#define COLOR_BLUE 0x04 -#define COLOR_MAGENTA 0x05 -#define COLOR_CYAN 0x06 -#define COLOR_WHITE 0x07 +#define COLOR_BLACK 0x00 +#define COLOR_RED 0x01 +#define COLOR_GREEN 0x02 +#define COLOR_YELLOW 0x03 +#define COLOR_BLUE 0x04 +#define COLOR_MAGENTA 0x05 +#define COLOR_CYAN 0x06 +#define COLOR_WHITE 0x07 /* Characters codes */ -#define CH_CTRL_C 0x03 -#define CH_ENTER 0x0D -#define CH_ESC 0x1B -#define CH_CURS_LEFT 0x08 -#define CH_CURS_RIGHT 0x15 -#define CH_CURS_UP 0x19 -#define CH_CURS_DOWN 0x1A -#define CH_ESC 0x1B +#define CH_CTRL_C 0x03 +#define CH_ENTER 0x0D +#define CH_ESC 0x1B +#define CH_CURS_LEFT 0x08 +#define CH_CURS_RIGHT 0x15 +#define CH_CURS_UP 0x19 +#define CH_CURS_DOWN 0x1A +#define CH_ESC 0x1B /* Masks for joy_read */ -#define JOY_UP_MASK 0x10 -#define JOY_DOWN_MASK 0x20 -#define JOY_LEFT_MASK 0x04 -#define JOY_RIGHT_MASK 0x08 -#define JOY_BTN_1_MASK 0x40 -#define JOY_BTN_2_MASK 0x80 +#define JOY_UP_MASK 0x10 +#define JOY_DOWN_MASK 0x20 +#define JOY_LEFT_MASK 0x04 +#define JOY_RIGHT_MASK 0x08 +#define JOY_BTN_1_MASK 0x40 +#define JOY_BTN_2_MASK 0x80 /* Return codes for get_ostype */ -#define AGAT_UNKNOWN 0x00 -#define AGAT_7 0x10 /* Agat 7 */ -#define AGAT_9 0x20 /* Agat 9 */ +#define AGAT_UNKNOWN 0x00 +#define AGAT_7 0x10 /* Agat 7 */ +#define AGAT_9 0x20 /* Agat 9 */ /*****************************************************************************/ diff --git a/libsrc/agat/cclear.s b/libsrc/agat/cclear.s index 65ae10049..dcc5834ad 100644 --- a/libsrc/agat/cclear.s +++ b/libsrc/agat/cclear.s @@ -4,14 +4,14 @@ ; void __fastcall__ cclear (unsigned char length); ; - .export _cclear - .import COUT - .include "zeropage.inc" + .export _cclear + .import COUT + .include "zeropage.inc" _cclear: - sta ptr1 - lda #$A0 -next: jsr COUT - dec ptr1 - bne next - rts + sta ptr1 + lda #$A0 +next: jsr COUT + dec ptr1 + bne next + rts diff --git a/libsrc/agat/cgetc.s b/libsrc/agat/cgetc.s index a4b1389d2..18bba2fd8 100644 --- a/libsrc/agat/cgetc.s +++ b/libsrc/agat/cgetc.s @@ -4,20 +4,19 @@ ; char cgetc (void); ; - .export _cgetc - .import cursor - .include "agat.inc" + .export _cgetc + .import cursor + .include "agat.inc" _cgetc: - lda #$DF ; _ - bit cursor - bne hascur - lda #$00 -hascur: sta CURSOR - jsr j1 - cmp #$A0 - bpl :+ - and #$7F -: rts -j1: jmp (VCIN) - + lda #$DF ; _ + bit cursor + bne hascur + lda #$00 +hascur: sta CURSOR + jsr j1 + cmp #$A0 + bpl :+ + and #$7F +: rts +j1: jmp (VCIN) diff --git a/libsrc/agat/clrscr.s b/libsrc/agat/clrscr.s index 2fe54607a..8b2d7100b 100644 --- a/libsrc/agat/clrscr.s +++ b/libsrc/agat/clrscr.s @@ -4,7 +4,7 @@ ; void clrscr (void); ; - .export _clrscr - .import HOME + .export _clrscr + .import HOME _clrscr := HOME diff --git a/libsrc/agat/color.s b/libsrc/agat/color.s index c68b6c3f6..0992bb860 100644 --- a/libsrc/agat/color.s +++ b/libsrc/agat/color.s @@ -5,17 +5,16 @@ ; - .export _textcolor - .include "agat.inc" + .export _textcolor + .include "agat.inc" _textcolor: - ldx TATTR - eor TATTR - and #$07 - eor TATTR - sta TATTR - txa - and #$0F - rts - + ldx TATTR + eor TATTR + and #$07 + eor TATTR + sta TATTR + txa + and #$0F + rts diff --git a/libsrc/agat/cout.s b/libsrc/agat/cout.s index 30b054b7e..ae9d8a177 100644 --- a/libsrc/agat/cout.s +++ b/libsrc/agat/cout.s @@ -4,11 +4,11 @@ ; COUT routine ; - .export COUT - .include "agat.inc" + .export COUT + .include "agat.inc" COUT: - cmp #$10 - bpl out - ora #$80 -out: jmp (VCOUT) + cmp #$10 + bpl out + ora #$80 +out: jmp (VCOUT) diff --git a/libsrc/agat/cputc.s b/libsrc/agat/cputc.s index b30b6c45c..6bf9b604f 100644 --- a/libsrc/agat/cputc.s +++ b/libsrc/agat/cputc.s @@ -5,41 +5,41 @@ ; void __fastcall__ cputc (char c); ; - .import COUT - .export _cputcxy, _cputc - .import gotoxy, VTABZ - .include "agat.inc" + .import COUT + .export _cputcxy, _cputc + .import gotoxy, VTABZ + .include "agat.inc" _cputcxy: - pha - jsr gotoxy - pla + pha + jsr gotoxy + pla _cputc: - cmp #$0D - bne notleft - ldy #$00 - sty CH - rts -notleft:cmp #$0A - beq newline + cmp #$0D + bne notleft + ldy #$00 + sty CH + rts +notleft:cmp #$0A + beq newline putchar: - ldy CH - sta (BASL),Y - iny - lda TATTR - bmi wch - sta (BASL),Y - iny -wch: sty CH - cpy WNDWDTH - bcc noend - ldy #$00 - sty CH -newline:inc CV - lda CV - cmp WNDBTM - bcc :+ - lda WNDTOP - sta CV -: jmp VTABZ -noend: rts + ldy CH + sta (BASL),Y + iny + lda TATTR + bmi wch + sta (BASL),Y + iny +wch:sty CH + cpy WNDWDTH + bcc noend + ldy #$00 + sty CH +newline:inc CV + lda CV + cmp WNDBTM + bcc :+ + lda WNDTOP + sta CV +: jmp VTABZ +noend: rts diff --git a/libsrc/agat/crt0.s b/libsrc/agat/crt0.s index 9f8993332..78fef06bc 100644 --- a/libsrc/agat/crt0.s +++ b/libsrc/agat/crt0.s @@ -14,61 +14,61 @@ ; ------------------------------------------------------------------------ - .segment "STARTUP" - jsr init - jsr zerobss - jsr callmain -_exit: ldx #exit - jsr reset - jsr donelib -exit: ldx #$02 -: lda rvsave,x - sta SOFTEV,x - dex - bpl :- - ldx #zpspace-1 -: lda zpsave,x - sta sp,x - dex - bpl :- - ldx #$FF - txs - jmp DOSWARM + .segment "STARTUP" + jsr init + jsr zerobss + jsr callmain +_exit: ldx #exit + jsr reset + jsr donelib +exit: ldx #$02 +: lda rvsave,x + sta SOFTEV,x + dex + bpl :- + ldx #zpspace-1 +: lda zpsave,x + sta sp,x + dex + bpl :- + ldx #$FF + txs + jmp DOSWARM - .segment "ONCE" + .segment "ONCE" -init: ldx #zpspace-1 -: lda sp,x - sta zpsave,x - dex - bpl :- +init: ldx #zpspace-1 +: lda sp,x + sta zpsave,x + dex + bpl :- - ldx #$02 -: lda SOFTEV,x - sta rvsave,x - dex - bpl :- + ldx #$02 +: lda SOFTEV,x + sta rvsave,x + dex + bpl :- - lda HIMEM - ldx HIMEM+1 - sta sp - stx sp+1 - ldx #<_exit - lda #>_exit - jsr reset - jmp initlib + lda HIMEM + ldx HIMEM+1 + sta sp + stx sp+1 + ldx #<_exit + lda #>_exit + jsr reset + jmp initlib - .code + .code -reset: stx SOFTEV - sta SOFTEV+1 - eor #$A5 - sta PWREDUP - rts +reset: stx SOFTEV + sta SOFTEV+1 + eor #$A5 + sta PWREDUP + rts - .segment "INIT" -zpsave: .res zpspace -rvsave: .res 3 + .segment "INIT" +zpsave: .res zpspace +rvsave: .res 3 diff --git a/libsrc/agat/gotoxy.s b/libsrc/agat/gotoxy.s index 2f9580c91..13e7cb747 100644 --- a/libsrc/agat/gotoxy.s +++ b/libsrc/agat/gotoxy.s @@ -12,17 +12,17 @@ .include "agat.inc" gotoxy: - jsr popa ; Get Y + jsr popa ; Get Y _gotoxy: - clc - adc WNDTOP - sta CV ; Store Y - jsr VTABZ - jsr popa ; Get X + clc + adc WNDTOP + sta CV ; Store Y + jsr VTABZ + jsr popa ; Get X _gotox: - bit TATTR - bmi t64 - asl + bit TATTR + bmi t64 + asl t64: - sta CH ; Store X - rts + sta CH ; Store X + rts diff --git a/libsrc/agat/gotoy.s b/libsrc/agat/gotoy.s index f4a8a4c4e..ea0eadbf2 100644 --- a/libsrc/agat/gotoy.s +++ b/libsrc/agat/gotoy.s @@ -5,14 +5,12 @@ ; void __fastcall__ gotoy (unsigned char y); ; - .import VTABZ - .export _gotoy - .include "agat.inc" + .import VTABZ + .export _gotoy + .include "agat.inc" _gotoy: - clc - adc WNDTOP - sta CV - jmp VTABZ - - + clc + adc WNDTOP + sta CV + jmp VTABZ diff --git a/libsrc/agat/home.s b/libsrc/agat/home.s index d3f000d25..5067a782a 100644 --- a/libsrc/agat/home.s +++ b/libsrc/agat/home.s @@ -10,6 +10,6 @@ .include "agat.inc" HOME: - lda #$8C - jsr COUT - rts + lda #$8C + jsr COUT + rts diff --git a/libsrc/agat/revers.s b/libsrc/agat/revers.s index ceca7cf5b..20c1b9bdb 100644 --- a/libsrc/agat/revers.s +++ b/libsrc/agat/revers.s @@ -6,33 +6,33 @@ ; unsigned char __fastcall__ flash (unsigned char onoff) ; - .export _revers, _flash + .export _revers, _flash - .include "agat.inc" + .include "agat.inc" _revers: - tax - beq noinv - lda TATTR - and #$D7 - sta TATTR - rts + tax + beq noinv + lda TATTR + and #$D7 + sta TATTR + rts noinv: - lda TATTR - ora #$20 - sta TATTR - rts + lda TATTR + ora #$20 + sta TATTR + rts _flash: - tax - beq noflash - lda TATTR - and #$DF - ora #$08 - sta TATTR - rts + tax + beq noflash + lda TATTR + and #$DF + ora #$08 + sta TATTR + rts noflash: - lda TATTR - ora #$20 - sta TATTR - rts + lda TATTR + ora #$20 + sta TATTR + rts diff --git a/libsrc/agat/vtabz.s b/libsrc/agat/vtabz.s index a711a87c9..88166eb35 100644 --- a/libsrc/agat/vtabz.s +++ b/libsrc/agat/vtabz.s @@ -4,21 +4,21 @@ ; VTABZ routine ; - .export VTABZ - .include "agat.inc" + .export VTABZ + .include "agat.inc" VTABZ: - lda CV - ror - ror - ror - and #$C0 - sta BASL - lda CV - lsr - lsr - eor BASH - and #$07 - eor BASH - sta BASH - rts + lda CV + ror + ror + ror + and #$C0 + sta BASL + lda CV + lsr + lsr + eor BASH + and #$07 + eor BASH + sta BASH + rts diff --git a/libsrc/agat/wherex.s b/libsrc/agat/wherex.s index b6d277680..a83f7cd75 100644 --- a/libsrc/agat/wherex.s +++ b/libsrc/agat/wherex.s @@ -10,10 +10,10 @@ .include "agat.inc" _wherex: - lda CH - bit TATTR - bmi t64 - lsr + lda CH + bit TATTR + bmi t64 + lsr t64: - ldx #$00 - rts + ldx #$00 + rts From cbf1b1d5a7857e7e3248787f61cf9d9058a784f5 Mon Sep 17 00:00:00 2001 From: Konstantin Date: Sat, 7 Jun 2025 14:00:10 +0300 Subject: [PATCH 16/60] Updated translation table --- src/common/target.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/common/target.c b/src/common/target.c index 761f7c3fd..fc1a9df25 100644 --- a/src/common/target.c +++ b/src/common/target.c @@ -138,11 +138,11 @@ static unsigned char CTAgat[256] = { 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F, - 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F, - 0x1B,0x5C,0x10,0x12,0x1D,0x1F,0x13,0x1C,0x11,0x1E,0x14,0x8B,0x8C,0x8D,0x8E,0x8F, - 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, - 0xA0,0xA1,0xA2,0x0F,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, - 0xB0,0xB1,0xB2,0x9F,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, + 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0xA0, + 0x1B,0x5C,0x10,0x12,0x1D,0x1F,0x13,0x1C,0x11,0x1E,0x14,0xA0,0x02,0x5F,0xA0,0xA0, + 0xA0,0xA0,0xA0,0xA0,0xA0,0x9E,0x04,0xA0,0x3C,0x3E,0xA0,0xA0,0x30,0x32,0xA0,0x2F, + 0xA0,0xA0,0xA0,0x0F,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0, + 0xA0,0xA0,0xA0,0x9F,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0, 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F, 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F, 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, From 34daf33d932eaf4f0ea832b7656b591b4b47ee21 Mon Sep 17 00:00:00 2001 From: Konstantin Date: Sat, 7 Jun 2025 14:10:50 +0300 Subject: [PATCH 17/60] Remove dangling spaces --- src/ca65/main.c | 2 +- src/cc65/main.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ca65/main.c b/src/ca65/main.c index c99ce06c6..682e9be7f 100644 --- a/src/ca65/main.c +++ b/src/ca65/main.c @@ -353,7 +353,7 @@ static void SetSys (const char* Sys) case TGT_AGAT: NewSymbol ("__AGAT__", 1); break; - + default: AbEnd ("Invalid target name: '%s'", Sys); diff --git a/src/cc65/main.c b/src/cc65/main.c index baf6f2f17..f56974361 100644 --- a/src/cc65/main.c +++ b/src/cc65/main.c @@ -306,7 +306,7 @@ static void SetSys (const char* Sys) case TGT_RP6502: DefineNumericMacro ("__RP6502__", 1); break; - + case TGT_AGAT: DefineNumericMacro ("__AGAT__", 1); break; From 41a82f7165030ec0e0cddf225c720398aab813ec Mon Sep 17 00:00:00 2001 From: Konstantin Date: Sun, 8 Jun 2025 23:20:21 +0300 Subject: [PATCH 18/60] fix codestyle --- libsrc/agat/_scrsize.s | 17 +++++++++++++++++ libsrc/agat/cclear.s | 3 ++- libsrc/agat/cgetc.s | 3 ++- libsrc/agat/cputc.s | 12 ++++++++---- libsrc/agat/crt0.s | 12 ++++++++---- libsrc/agat/randomize.s | 2 +- 6 files changed, 38 insertions(+), 11 deletions(-) create mode 100644 libsrc/agat/_scrsize.s diff --git a/libsrc/agat/_scrsize.s b/libsrc/agat/_scrsize.s new file mode 100644 index 000000000..f9d7c3785 --- /dev/null +++ b/libsrc/agat/_scrsize.s @@ -0,0 +1,17 @@ +; +; Ullrich von Bassewitz, 26.10.2000 +; +; Screen size variables +; + + .export screensize + + .include "agat.inc" + +screensize: + ldx WNDWDTH + lda WNDBTM + sec + sbc WNDTOP + tay + rts diff --git a/libsrc/agat/cclear.s b/libsrc/agat/cclear.s index dcc5834ad..93a561ef4 100644 --- a/libsrc/agat/cclear.s +++ b/libsrc/agat/cclear.s @@ -11,7 +11,8 @@ _cclear: sta ptr1 lda #$A0 -next: jsr COUT +next: + jsr COUT dec ptr1 bne next rts diff --git a/libsrc/agat/cgetc.s b/libsrc/agat/cgetc.s index 18bba2fd8..839e4314a 100644 --- a/libsrc/agat/cgetc.s +++ b/libsrc/agat/cgetc.s @@ -13,7 +13,8 @@ _cgetc: bit cursor bne hascur lda #$00 -hascur: sta CURSOR +hascur: + sta CURSOR jsr j1 cmp #$A0 bpl :+ diff --git a/libsrc/agat/cputc.s b/libsrc/agat/cputc.s index 6bf9b604f..b8d99aaea 100644 --- a/libsrc/agat/cputc.s +++ b/libsrc/agat/cputc.s @@ -20,7 +20,8 @@ _cputc: ldy #$00 sty CH rts -notleft:cmp #$0A +notleft: + cmp #$0A beq newline putchar: ldy CH @@ -30,16 +31,19 @@ putchar: bmi wch sta (BASL),Y iny -wch:sty CH +wch: + sty CH cpy WNDWDTH bcc noend ldy #$00 sty CH -newline:inc CV +newline: + inc CV lda CV cmp WNDBTM bcc :+ lda WNDTOP sta CV : jmp VTABZ -noend: rts +noend: + rts diff --git a/libsrc/agat/crt0.s b/libsrc/agat/crt0.s index 78fef06bc..41f03b24d 100644 --- a/libsrc/agat/crt0.s +++ b/libsrc/agat/crt0.s @@ -18,11 +18,13 @@ jsr init jsr zerobss jsr callmain -_exit: ldx #exit jsr reset jsr donelib -exit: ldx #$02 +exit: + ldx #$02 : lda rvsave,x sta SOFTEV,x dex @@ -40,7 +42,8 @@ exit: ldx #$02 .segment "ONCE" -init: ldx #zpspace-1 +init: + ldx #zpspace-1 : lda sp,x sta zpsave,x dex @@ -63,7 +66,8 @@ init: ldx #zpspace-1 .code -reset: stx SOFTEV +reset: + stx SOFTEV sta SOFTEV+1 eor #$A5 sta PWREDUP diff --git a/libsrc/agat/randomize.s b/libsrc/agat/randomize.s index 914f40634..9eef16f05 100644 --- a/libsrc/agat/randomize.s +++ b/libsrc/agat/randomize.s @@ -9,7 +9,7 @@ .export __randomize .import _srand - .include "apple2.inc" + .include "agat.inc" __randomize: ldx RNDH ; Use random value supplied by ROM From 4d5a290135950b5f5c97e9d6b9a5a25f992ba98e Mon Sep 17 00:00:00 2001 From: Konstantin Date: Sun, 8 Jun 2025 23:30:34 +0300 Subject: [PATCH 19/60] add docs and readme.md --- README.md | 1 + doc/agat.sgml | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++ doc/index.sgml | 3 ++ 3 files changed, 83 insertions(+) create mode 100644 doc/agat.sgml diff --git a/README.md b/README.md index e3f1ab30f..4c1003179 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,7 @@ the [cc65 web site](https://cc65.github.io): | Dr. Jozo Dujmović | Picocomputer (RP6502) | | Watara | Watura/QuickShot Supervision | | Synertek | SYM-1 | +| USSR | Agat 7/9 | A generic configuration to adapt cc65 to new targets is also around. diff --git a/doc/agat.sgml b/doc/agat.sgml new file mode 100644 index 000000000..1238dd394 --- /dev/null +++ b/doc/agat.sgml @@ -0,0 +1,79 @@ + + +

+Agat-7/9 - specific information for cc65 + +<author><url url="https://sourceforge.net/u/olegodintsov/profile/" name="Oleg A. Odintsov">,<newline> +<url url="mailto:sintechs@gmail.com" name="Konstantin Fedorov"> + +<abstract> +An overview over the Agat-7 and Agat-9 and theirs interfaces to the cc65 C +compiler. +</abstract> + +<!-- Table of contents --> +<toc> + +<!-- Begin the document --> + +<sect>Overview + +<p>The Agat was a series of 8-bit computers produced in the Soviet Union from 1983 to 1993. +It was based on Apple II architecture with all electronic components made in the Soviet Union except for 6502 microprocessors supplied by UMC (UM6502A). +<p>If compared to Apple II, Agat had many improvements such as color text mode, additional graphic modes and flexible memory controller. +Agat-7 had an Apple II compatibility card called "Module 121", while Agat-9 had a built-in Apple II+ mode activated by soft-switch. +<p>All mass-produced Agat models were disk-based systems, 2K ROM contained only basic machine language monitor and disassembler. +Agat-7 had 140K floppy-drive based on Apple DISK II, while Agat-9 was supplied with 840K drive having its own sector format and controller. + +<sect>Binary format<p> + +The standard binary file format generated by the linker for the Agat target is +an AppleSingle file to be compatible with AppleCommander <url url="https://applecommander.github.io/">. +The default load address is $1903. + + + +<sect>Platform-specific header files<p> + +Programs containing Agat-specific code may use the <tt/agat.h/ or +<tt/agat.inc/ include files. + +<sect>Usefull info<p> + +<sect1>Emulation<p> + +<enum> +<item> Oleg Odintsov's Agat Emulator - <url url="https://agatemulator.sourceforge.net/english.html"> +<item> MAME - <url url="https://www.mamedev.org/"> +</enum> + +<sect1>Links<p> +<enum> +<item> Most informative source on Agat (in russian) - <url url="https://agatcomp.ru"> +<item> Wikipedia - <url url="https://en.wikipedia.org/wiki/Agat_(computer)"> +<item> Controversial article on Agat from <url name="BYTE Magazine November 1984 Vol. 9, No. 12" url="https://archive.org/details/byte-magazine-1984-11/page/n135/mode/2up?view=theater">. +The author reviewed custom-build mockup Agat bearing little relation to even the early Agat systems. +</enum> + + +<sect>License<p> + +This software is provided "as-is", without any expressed or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: +<enum> +<item> The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated, but is not required. +<item> Altered source versions must be plainly marked as such, and must not + be misrepresented as being the original software. +<item> This notice may not be removed or altered from any source + distribution. +</enum> + +</article> diff --git a/doc/index.sgml b/doc/index.sgml index 92df5e018..e39fd11b4 100644 --- a/doc/index.sgml +++ b/doc/index.sgml @@ -109,6 +109,9 @@ <descrip> + <tag><htmlurl url="agat.html" name="agat.html"></tag> + Topics specific to the Agat machines. + <tag><htmlurl url="apple2.html" name="apple2.html"></tag> Topics specific to the Apple ][. From fb421d7a81e3cc89f17f26e50621a3382864626f Mon Sep 17 00:00:00 2001 From: Konstantin <sintechs@gmail.com> Date: Sun, 8 Jun 2025 23:44:51 +0300 Subject: [PATCH 20/60] Remove dangling spaces --- doc/agat.sgml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/agat.sgml b/doc/agat.sgml index 1238dd394..ca5338c5f 100644 --- a/doc/agat.sgml +++ b/doc/agat.sgml @@ -18,16 +18,16 @@ compiler. <sect>Overview -<p>The Agat was a series of 8-bit computers produced in the Soviet Union from 1983 to 1993. +<p>The Agat was a series of 8-bit computers produced in the Soviet Union from 1983 to 1993. It was based on Apple II architecture with all electronic components made in the Soviet Union except for 6502 microprocessors supplied by UMC (UM6502A). -<p>If compared to Apple II, Agat had many improvements such as color text mode, additional graphic modes and flexible memory controller. +<p>If compared to Apple II, Agat had many improvements such as color text mode, additional graphic modes and flexible memory controller. Agat-7 had an Apple II compatibility card called "Module 121", while Agat-9 had a built-in Apple II+ mode activated by soft-switch. -<p>All mass-produced Agat models were disk-based systems, 2K ROM contained only basic machine language monitor and disassembler. +<p>All mass-produced Agat models were disk-based systems, 2K ROM contained only basic machine language monitor and disassembler. Agat-7 had 140K floppy-drive based on Apple DISK II, while Agat-9 was supplied with 840K drive having its own sector format and controller. <sect>Binary format<p> -The standard binary file format generated by the linker for the Agat target is +The standard binary file format generated by the linker for the Agat target is an AppleSingle file to be compatible with AppleCommander <url url="https://applecommander.github.io/">. The default load address is $1903. From ba80de5efc99b4173fe3b0946fc480e4fa459dac Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Mon, 9 Jun 2025 17:58:58 +0200 Subject: [PATCH 21/60] fix bsearch tables that must be sorted, add comment to all tables that must be sorted --- src/ca65/instr.c | 9 +++++++++ src/ca65/scanner.c | 1 + src/cc65/codeinfo.c | 10 ++++++---- src/cc65/codeopt.c | 18 ++++++++++-------- src/cc65/codeoptutil.c | 8 ++++---- src/cc65/coptstop.c | 2 ++ src/cc65/opcodes.c | 1 + src/cc65/pragma.c | 1 + src/cc65/preproc.c | 1 + src/cc65/scanner.c | 1 + src/cc65/stdfunc.c | 5 ++--- src/common/filetype.c | 1 + src/common/target.c | 3 ++- src/dbginfo/dbginfo.c | 1 + src/sp65/convert.c | 3 ++- src/sp65/input.c | 3 ++- src/sp65/output.c | 3 ++- src/sp65/palconv.c | 3 ++- 18 files changed, 50 insertions(+), 24 deletions(-) diff --git a/src/ca65/instr.c b/src/ca65/instr.c index da6bd6e44..f1d8d706a 100644 --- a/src/ca65/instr.c +++ b/src/ca65/instr.c @@ -169,6 +169,7 @@ static const struct { unsigned Count; InsDesc Ins[56]; } InsTab6502 = { + /* CAUTION: table must be sorted for bsearch */ sizeof (InsTab6502.Ins) / sizeof (InsTab6502.Ins[0]), { { "ADC", 0x080A26C, 0x60, 0, PutAll }, @@ -235,6 +236,7 @@ static const struct { unsigned Count; InsDesc Ins[75]; } InsTab6502X = { + /* CAUTION: table must be sorted for bsearch */ sizeof (InsTab6502X.Ins) / sizeof (InsTab6502X.Ins[0]), { { "ADC", 0x080A26C, 0x60, 0, PutAll }, @@ -324,6 +326,7 @@ static const struct { unsigned Count; InsDesc Ins[71]; } InsTab6502DTV = { + /* CAUTION: table must be sorted for bsearch */ sizeof (InsTab6502DTV.Ins) / sizeof (InsTab6502DTV.Ins[0]), { { "ADC", 0x080A26C, 0x60, 0, PutAll }, @@ -405,6 +408,7 @@ static const struct { unsigned Count; InsDesc Ins[66]; } InsTab65SC02 = { + /* CAUTION: table must be sorted for bsearch */ sizeof (InsTab65SC02.Ins) / sizeof (InsTab65SC02.Ins[0]), { { "ADC", 0x080A66C, 0x60, 0, PutAll }, @@ -481,6 +485,7 @@ static const struct { unsigned Count; InsDesc Ins[100]; } InsTab65C02 = { + /* CAUTION: table must be sorted for bsearch */ sizeof (InsTab65C02.Ins) / sizeof (InsTab65C02.Ins[0]), { { "ADC", 0x080A66C, 0x60, 0, PutAll }, @@ -591,6 +596,7 @@ static const struct { unsigned Count; InsDesc Ins[133]; } InsTab4510 = { + /* CAUTION: table must be sorted for bsearch */ sizeof (InsTab4510.Ins) / sizeof (InsTab4510.Ins[0]), { { "ADC", 0x080A66C, 0x60, 0, PutAll }, @@ -734,6 +740,7 @@ static const struct { unsigned Count; InsDesc Ins[100]; } InsTab65816 = { + /* CAUTION: table must be sorted for bsearch */ sizeof (InsTab65816.Ins) / sizeof (InsTab65816.Ins[0]), { { "ADC", 0x0b8f6fc, 0x60, 0, PutAll }, @@ -844,6 +851,7 @@ static const struct { unsigned Count; InsDesc Ins[26]; } InsTabSweet16 = { + /* CAUTION: table must be sorted for bsearch */ sizeof (InsTabSweet16.Ins) / sizeof (InsTabSweet16.Ins[0]), { { "ADD", AMSW16_REG, 0xA0, 0, PutSweet16 }, @@ -880,6 +888,7 @@ static const struct { unsigned Count; InsDesc Ins[135]; } InsTabHuC6280 = { + /* CAUTION: table must be sorted for bsearch */ sizeof (InsTabHuC6280.Ins) / sizeof (InsTabHuC6280.Ins[0]), { { "ADC", 0x080A66C, 0x60, 0, PutAll }, diff --git a/src/ca65/scanner.c b/src/ca65/scanner.c index da9883e52..11beb4d63 100644 --- a/src/ca65/scanner.c +++ b/src/ca65/scanner.c @@ -131,6 +131,7 @@ static int C = 0; /* Current input character */ int ForcedEnd = 0; /* List of dot keywords with the corresponding tokens */ +/* CAUTION: table must be sorted for bsearch */ struct DotKeyword { const char* Key; /* MUST be first field */ token_t Tok; diff --git a/src/cc65/codeinfo.c b/src/cc65/codeinfo.c index 435794613..8396ecfd5 100644 --- a/src/cc65/codeinfo.c +++ b/src/cc65/codeinfo.c @@ -90,6 +90,7 @@ struct FuncInfo { ** routines are marked to use only the A register. The remainder is ignored ** anyway. */ +/* CAUTION: table must be sorted for bsearch */ static const FuncInfo FuncInfoTable[] = { { "addeq0sp", SLV_TOP | REG_AX, PSTATE_ALL | REG_AXY }, { "addeqysp", SLV_IND | REG_AXY, PSTATE_ALL | REG_AXY }, @@ -190,12 +191,12 @@ static const FuncInfo FuncInfoTable[] = { { "ldeaxysp", SLV_IND | REG_Y, PSTATE_ALL | REG_EAXY }, { "leaa0sp", REG_SP | REG_A, PSTATE_ALL | REG_AX }, { "leaaxsp", REG_SP | REG_AX, PSTATE_ALL | REG_AX }, - { "leave00", REG_SP, PSTATE_ALL | REG_SP | REG_AXY }, - { "leave0", REG_SP, PSTATE_ALL | REG_SP | REG_XY }, { "leave", REG_SP, PSTATE_ALL | REG_SP | REG_Y }, - { "leavey00", REG_SP, PSTATE_ALL | REG_SP | REG_AXY }, - { "leavey0", REG_SP, PSTATE_ALL | REG_SP | REG_XY }, + { "leave0", REG_SP, PSTATE_ALL | REG_SP | REG_XY }, + { "leave00", REG_SP, PSTATE_ALL | REG_SP | REG_AXY }, { "leavey", REG_SP | REG_Y, PSTATE_ALL | REG_SP | REG_Y }, + { "leavey0", REG_SP, PSTATE_ALL | REG_SP | REG_XY }, + { "leavey00", REG_SP, PSTATE_ALL | REG_SP | REG_AXY }, { "lsubeq", REG_EAXY | REG_PTR1_LO, PSTATE_ALL | REG_EAXY | REG_PTR1_HI }, { "lsubeq0sp", SLV_TOP | REG_EAX, PSTATE_ALL | REG_EAXY }, { "lsubeq1", REG_Y | REG_PTR1_LO, PSTATE_ALL | REG_EAXY | REG_PTR1_HI }, @@ -380,6 +381,7 @@ static const FuncInfo FuncInfoTable[] = { #define FuncInfoCount (sizeof(FuncInfoTable) / sizeof(FuncInfoTable[0])) /* Table with names of zero page locations used by the compiler */ +/* CAUTION: table must be sorted for bsearch */ static const ZPInfo ZPInfoTable[] = { { 0, "ptr1", 2, REG_PTR1_LO, REG_PTR1 }, { 0, "ptr1+1", 1, REG_PTR1_HI, REG_PTR1 }, diff --git a/src/cc65/codeopt.c b/src/cc65/codeopt.c index a716ad431..9de2ab7ba 100644 --- a/src/cc65/codeopt.c +++ b/src/cc65/codeopt.c @@ -102,6 +102,7 @@ struct OptFunc { /* A list of all the function descriptions */ +/* CAUTION: should be sorted by "name" */ static OptFunc DOpt65C02BitOps = { Opt65C02BitOps, "Opt65C02BitOps", 66, 0, 0, 0, 0, 0 }; static OptFunc DOpt65C02Ind = { Opt65C02Ind, "Opt65C02Ind", 100, 0, 0, 0, 0, 0 }; static OptFunc DOpt65C02Stores = { Opt65C02Stores, "Opt65C02Stores", 100, 0, 0, 0, 0, 0 }; @@ -152,18 +153,13 @@ static OptFunc DOptJumpTarget3 = { OptJumpTarget3, "OptJumpTarget3", 100, 0, static OptFunc DOptLoad1 = { OptLoad1, "OptLoad1", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptLoad2 = { OptLoad2, "OptLoad2", 200, 0, 0, 0, 0, 0 }; static OptFunc DOptLoad3 = { OptLoad3, "OptLoad3", 0, 0, 0, 0, 0, 0 }; +static OptFunc DOptLoadStoreLoad= { OptLoadStoreLoad,"OptLoadStoreLoad", 0, 0, 0, 0, 0, 0 }; static OptFunc DOptLongAssign = { OptLongAssign, "OptLongAssign", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptLongCopy = { OptLongCopy, "OptLongCopy", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptNegAX1 = { OptNegAX1, "OptNegAX1", 165, 0, 0, 0, 0, 0 }; static OptFunc DOptNegAX2 = { OptNegAX2, "OptNegAX2", 200, 0, 0, 0, 0, 0 }; static OptFunc DOptPrecalc = { OptPrecalc, "OptPrecalc", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptPtrLoad1 = { OptPtrLoad1, "OptPtrLoad1", 100, 0, 0, 0, 0, 0 }; -static OptFunc DOptPtrLoad2 = { OptPtrLoad2, "OptPtrLoad2", 100, 0, 0, 0, 0, 0 }; -static OptFunc DOptPtrLoad3 = { OptPtrLoad3, "OptPtrLoad3", 100, 0, 0, 0, 0, 0 }; -static OptFunc DOptPtrLoad4 = { OptPtrLoad4, "OptPtrLoad4", 100, 0, 0, 0, 0, 0 }; -static OptFunc DOptPtrLoad5 = { OptPtrLoad5, "OptPtrLoad5", 50, 0, 0, 0, 0, 0 }; -static OptFunc DOptPtrLoad6 = { OptPtrLoad6, "OptPtrLoad6", 60, 0, 0, 0, 0, 0 }; -static OptFunc DOptPtrLoad7 = { OptPtrLoad7, "OptPtrLoad7", 140, 0, 0, 0, 0, 0 }; static OptFunc DOptPtrLoad11 = { OptPtrLoad11, "OptPtrLoad11", 92, 0, 0, 0, 0, 0 }; static OptFunc DOptPtrLoad12 = { OptPtrLoad12, "OptPtrLoad12", 50, 0, 0, 0, 0, 0 }; static OptFunc DOptPtrLoad13 = { OptPtrLoad13, "OptPtrLoad13", 65, 0, 0, 0, 0, 0 }; @@ -173,6 +169,12 @@ static OptFunc DOptPtrLoad16 = { OptPtrLoad16, "OptPtrLoad16", 100, 0, static OptFunc DOptPtrLoad17 = { OptPtrLoad17, "OptPtrLoad17", 190, 0, 0, 0, 0, 0 }; static OptFunc DOptPtrLoad18 = { OptPtrLoad18, "OptPtrLoad18", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptPtrLoad19 = { OptPtrLoad19, "OptPtrLoad19", 65, 0, 0, 0, 0, 0 }; +static OptFunc DOptPtrLoad2 = { OptPtrLoad2, "OptPtrLoad2", 100, 0, 0, 0, 0, 0 }; +static OptFunc DOptPtrLoad3 = { OptPtrLoad3, "OptPtrLoad3", 100, 0, 0, 0, 0, 0 }; +static OptFunc DOptPtrLoad4 = { OptPtrLoad4, "OptPtrLoad4", 100, 0, 0, 0, 0, 0 }; +static OptFunc DOptPtrLoad5 = { OptPtrLoad5, "OptPtrLoad5", 50, 0, 0, 0, 0, 0 }; +static OptFunc DOptPtrLoad6 = { OptPtrLoad6, "OptPtrLoad6", 60, 0, 0, 0, 0, 0 }; +static OptFunc DOptPtrLoad7 = { OptPtrLoad7, "OptPtrLoad7", 140, 0, 0, 0, 0, 0 }; static OptFunc DOptPtrStore1 = { OptPtrStore1, "OptPtrStore1", 65, 0, 0, 0, 0, 0 }; static OptFunc DOptPtrStore2 = { OptPtrStore2, "OptPtrStore2", 65, 0, 0, 0, 0, 0 }; static OptFunc DOptPtrStore3 = { OptPtrStore3, "OptPtrStore3", 100, 0, 0, 0, 0, 0 }; @@ -202,7 +204,6 @@ static OptFunc DOptStore3 = { OptStore3, "OptStore3", 120, 0, static OptFunc DOptStore4 = { OptStore4, "OptStore4", 50, 0, 0, 0, 0, 0 }; static OptFunc DOptStore5 = { OptStore5, "OptStore5", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptStoreLoad = { OptStoreLoad, "OptStoreLoad", 0, 0, 0, 0, 0, 0 }; -static OptFunc DOptLoadStoreLoad= { OptLoadStoreLoad,"OptLoadStoreLoad", 0, 0, 0, 0, 0, 0 }; static OptFunc DOptSub1 = { OptSub1, "OptSub1", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptSub2 = { OptSub2, "OptSub2", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptSub3 = { OptSub3, "OptSub3", 100, 0, 0, 0, 0, 0 }; @@ -217,6 +218,7 @@ static OptFunc DOptUnusedStores = { OptUnusedStores, "OptUnusedStores", 0, 0, /* Table containing all the steps in alphabetical order */ +/* CAUTION: table must be sorted for bsearch */ static OptFunc* OptFuncs[] = { &DOpt65C02BitOps, &DOpt65C02Ind, @@ -268,6 +270,7 @@ static OptFunc* OptFuncs[] = { &DOptLoad1, &DOptLoad2, &DOptLoad3, + &DOptLoadStoreLoad, &DOptLongAssign, &DOptLongCopy, &DOptNegAX1, @@ -318,7 +321,6 @@ static OptFunc* OptFuncs[] = { &DOptStore4, &DOptStore5, &DOptStoreLoad, - &DOptLoadStoreLoad, &DOptSub1, &DOptSub2, &DOptSub3, diff --git a/src/cc65/codeoptutil.c b/src/cc65/codeoptutil.c index 43b1dee22..c18ccf18b 100644 --- a/src/cc65/codeoptutil.c +++ b/src/cc65/codeoptutil.c @@ -1225,6 +1225,10 @@ static int CmpHarmless (const void* Key, const void* Entry) } +/* CAUTION: table must be sorted for bsearch */ +static const char* const Tab[] = { + "_abs", +}; int HarmlessCall (const CodeEntry* E, int PushedBytes) /* Check if this is a call to a harmless subroutine that will not interrupt @@ -1252,10 +1256,6 @@ int HarmlessCall (const CodeEntry* E, int PushedBytes) } return 1; } else { - static const char* const Tab[] = { - "_abs", - }; - void* R = bsearch (E->Arg, Tab, sizeof (Tab) / sizeof (Tab[0]), diff --git a/src/cc65/coptstop.c b/src/cc65/coptstop.c index 402f16b97..90ab78c50 100644 --- a/src/cc65/coptstop.c +++ b/src/cc65/coptstop.c @@ -1464,6 +1464,7 @@ static unsigned Opt_a_tosxor (StackOpData* D) /* The first column of these two tables must be sorted in lexical order */ +/* CAUTION: table must be sorted for bsearch */ static const OptFuncDesc FuncTable[] = { { "___bzero", Opt___bzero, REG_NONE, OP_X_ZERO | OP_A_KNOWN }, { "staspidx", Opt_staspidx, REG_NONE, OP_NONE }, @@ -1487,6 +1488,7 @@ static const OptFuncDesc FuncTable[] = { { "tosxorax", Opt_tosxorax, REG_NONE, OP_NONE }, }; +/* CAUTION: table must be sorted for bsearch */ static const OptFuncDesc FuncRegATable[] = { { "tosandax", Opt_a_tosand, REG_NONE, OP_RHS_REMOVE_DIRECT | OP_RHS_LOAD_DIRECT }, { "toseqax", Opt_a_toseq, REG_NONE, OP_NONE }, diff --git a/src/cc65/opcodes.c b/src/cc65/opcodes.c index aeea0297b..c591c4ea3 100644 --- a/src/cc65/opcodes.c +++ b/src/cc65/opcodes.c @@ -55,6 +55,7 @@ /* Opcode description table */ +/* CAUTION: table must be sorted by mnemonic for bsearch */ const OPCDesc OPCTable[OP65_COUNT] = { /* 65XX opcodes */ diff --git a/src/cc65/pragma.c b/src/cc65/pragma.c index ee71b42d8..5de4c8dfc 100644 --- a/src/cc65/pragma.c +++ b/src/cc65/pragma.c @@ -89,6 +89,7 @@ typedef enum { } pragma_t; /* Pragma table */ +/* CAUTION: table must be sorted for bsearch */ static const struct Pragma { const char* Key; /* Keyword */ pragma_t Tok; /* Token */ diff --git a/src/cc65/preproc.c b/src/cc65/preproc.c index 5cdec3142..d70c28147 100644 --- a/src/cc65/preproc.c +++ b/src/cc65/preproc.c @@ -216,6 +216,7 @@ typedef enum { /* Preprocessor directive tokens mapping table */ +/* CAUTION: table must be sorted for bsearch */ static const struct PPDType { const char* Tok; /* Token */ ppdirective_t Type; /* Type */ diff --git a/src/cc65/scanner.c b/src/cc65/scanner.c index f0ff664fd..1549b51bd 100644 --- a/src/cc65/scanner.c +++ b/src/cc65/scanner.c @@ -87,6 +87,7 @@ enum { }; /* Token table */ +/* CAUTION: table must be sorted for bsearch */ static const struct Keyword { char* Key; /* Keyword name */ unsigned char Tok; /* The token */ diff --git a/src/cc65/stdfunc.c b/src/cc65/stdfunc.c index 2889a176e..3bd3f3552 100644 --- a/src/cc65/stdfunc.c +++ b/src/cc65/stdfunc.c @@ -78,8 +78,8 @@ static void StdFunc_strlen (FuncDesc*, ExprDesc*); -/* Table with all known functions and their handlers. Must be sorted -** alphabetically! +/* Table with all known functions and their handlers. +** CAUTION: table must be alphabetically sorted for bsearch */ static struct StdFuncDesc { const char* Name; @@ -90,7 +90,6 @@ static struct StdFuncDesc { { "strcmp", StdFunc_strcmp }, { "strcpy", StdFunc_strcpy }, { "strlen", StdFunc_strlen }, - }; #define FUNC_COUNT (sizeof (StdFuncs) / sizeof (StdFuncs[0])) diff --git a/src/common/filetype.c b/src/common/filetype.c index ae8b636dc..4aececa78 100644 --- a/src/common/filetype.c +++ b/src/common/filetype.c @@ -48,6 +48,7 @@ +/* CAUTION: table must be sorted for bsearch */ static const FileId TypeTable[] = { /* Upper case stuff for obsolete operating systems */ { "A", FILETYPE_LIB }, diff --git a/src/common/target.c b/src/common/target.c index b50478e16..18da67b00 100644 --- a/src/common/target.c +++ b/src/common/target.c @@ -138,8 +138,9 @@ struct TargetEntry { target_t Id; /* Target ID */ }; -/* Table that maps target names to IDs. Sorted alphabetically for bsearch(). +/* Table that maps target names to IDs. ** Allows multiple entries for one target ID (target name aliases). +** CAUTION: must be alphabetically for bsearch(). */ static const TargetEntry TargetMap[] = { { "apple2", TGT_APPLE2 }, diff --git a/src/dbginfo/dbginfo.c b/src/dbginfo/dbginfo.c index 1f693e513..4fe7a37ec 100644 --- a/src/dbginfo/dbginfo.c +++ b/src/dbginfo/dbginfo.c @@ -2523,6 +2523,7 @@ static void NextChar (InputData* D) +/* CAUTION: table must be sorted for bsearch */ static void NextToken (InputData* D) /* Read the next token from the input stream */ { diff --git a/src/sp65/convert.c b/src/sp65/convert.c index a9047ffb0..71c9d09a6 100644 --- a/src/sp65/convert.c +++ b/src/sp65/convert.c @@ -61,7 +61,8 @@ struct ConverterMapEntry { StrBuf* (*ConvertFunc) (const Bitmap*, const Collection*); }; -/* Converter table, alphabetically sorted */ +/* Converter table */ +/* CAUTION: table must be alphabetically sorted for bsearch */ static const ConverterMapEntry ConverterMap[] = { { "geos-bitmap", GenGeosBitmap }, { "geos-icon", GenGeosIcon }, diff --git a/src/sp65/input.c b/src/sp65/input.c index f1df247ae..22cfb1678 100644 --- a/src/sp65/input.c +++ b/src/sp65/input.c @@ -69,7 +69,8 @@ static InputFormatDesc InputFormatTable[ifCount] = { { ReadPCXFile }, }; -/* Table that maps extensions to input formats. Must be sorted alphabetically */ +/* Table that maps extensions to input formats. */ +/* CAUTION: table must be alphabetically sorted for bsearch */ static const FileId FormatTable[] = { /* Upper case stuff for obsolete operating systems */ { "PCX", ifPCX }, diff --git a/src/sp65/output.c b/src/sp65/output.c index c12d1f612..8b569502b 100644 --- a/src/sp65/output.c +++ b/src/sp65/output.c @@ -78,7 +78,8 @@ static OutputFormatDesc OutputFormatTable[ofCount] = { { WriteCFile }, }; -/* Table that maps extensions to Output formats. Must be sorted alphabetically */ +/* Table that maps extensions to Output formats. */ +/* CAUTION: table must be alphabetically sorted for bsearch */ static const FileId FormatTable[] = { /* Upper case stuff for obsolete operating systems */ { "A", ofAsm }, diff --git a/src/sp65/palconv.c b/src/sp65/palconv.c index e92f3c22e..ff5891b99 100644 --- a/src/sp65/palconv.c +++ b/src/sp65/palconv.c @@ -56,7 +56,8 @@ struct PaletteMapEntry { StrBuf* (*PaletteFunc) (const Bitmap*, const Collection*); }; -/* Converter table, alphabetically sorted */ +/* Converter table */ +/* CAUTION: table must be alphabetically sorted for bsearch */ static const PaletteMapEntry PaletteMap[] = { { "lynx-palette", GenLynxPalette }, }; From d368f3d0ea3e93ddd7933831932f3f068926fb7f Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Mon, 9 Jun 2025 18:26:41 +0200 Subject: [PATCH 22/60] simple script(s) to check if bsearch tables are sorted correctly --- .github/checks/Makefile | 12 +++- .github/checks/sorted.sh | 117 +++++++++++++++++++++++++++++++ .github/checks/sorted_codeopt.sh | 42 +++++++++++ Makefile | 1 + 4 files changed, 170 insertions(+), 2 deletions(-) create mode 100755 .github/checks/sorted.sh create mode 100755 .github/checks/sorted_codeopt.sh diff --git a/.github/checks/Makefile b/.github/checks/Makefile index 93eeddd19..8245958c1 100644 --- a/.github/checks/Makefile +++ b/.github/checks/Makefile @@ -5,14 +5,18 @@ endif ifdef CMD_EXE -.PHONY: checkstyle +.PHONY: checkstyle sorted checkstyle: $(info INFO: style checks require bash.) +sorted: + $(info INFO: table checks require bash.) else -.PHONY: checkstyle lineendings tabs lastline spaces noexec +.PHONY: checkstyle lineendings tabs lastline spaces noexec sorted + +all: checkstyle sorted checkstyle: lineendings tabs lastline spaces noexec @@ -31,4 +35,8 @@ spaces: spaces.sh noexec: noexec.sh @./noexec.sh +sorted: sorted.sh sorted_codeopt.sh + @./sorted.sh + @./sorted_codeopt.sh + endif diff --git a/.github/checks/sorted.sh b/.github/checks/sorted.sh new file mode 100755 index 000000000..4311225cd --- /dev/null +++ b/.github/checks/sorted.sh @@ -0,0 +1,117 @@ +#! /bin/bash +OLDCWD=`pwd` +SCRIPT_PATH=`dirname $0` + +SORT_OPT=-u + +function checkarray_quoted_name +{ + CHECK_FILE="$1" + + awk '/'"$2"'/{flag=1;next}/};/{flag=0}flag' "$CHECK_FILE" | \ + sed -e 's:.*\"\(.*\)\".*:\1:g' | \ + sed '/^\s*$/d' > .a.tmp + + if [[ -z $(grep '[^[:space:]]' .a.tmp) ]] ; then + echo "error: "$2" table is empty" + exit -1 + fi + + LC_COLLATE=C sort $SORT_OPT .a.tmp > .b.tmp + + if cmp --silent -- .a.tmp .b.tmp; then + echo ""$2" definitions OK" + else + echo "error: "$2" definitions are not sorted." + diff -y .a.tmp .b.tmp + exit -1 + fi + rm -rf .a.tmp .b.tmp +} + +function checkinstr_quoted_name +{ + CHECK_FILE="$1" + + awk '/'"$2"'/{flag=1;next}/};/{flag=0}flag' "$CHECK_FILE" | \ + sed -e 's:^ *{$::g' | \ + sed -e 's:^ *}$::g' | \ + sed -e 's:.*\"\(.*\)\".*:\1:g' | \ + sed '/^\s*$/d' > .a.tmp + + if [[ -z $(grep '[^[:space:]]' .a.tmp) ]] ; then + echo "error: "$2" table is empty" + exit -1 + fi + + LC_COLLATE=C sort $SORT_OPT .a.tmp > .b.tmp + + if cmp --silent -- .a.tmp .b.tmp; then + echo ""$2" definitions OK" + else + echo "error: "$2" definitions are not sorted." + diff -y .a.tmp .b.tmp + exit -1 + fi + rm -rf .a.tmp .b.tmp +} + +function checkopcodes_quoted_name +{ + CHECK_FILE="$1" + + awk '/'"$2"'/{flag=1;next}/};/{flag=0}flag' "$CHECK_FILE" | \ + grep "^ *\".*\"," | \ + sed '/^\s*$/d' > .a.tmp + + if [[ -z $(grep '[^[:space:]]' .a.tmp) ]] ; then + echo "error: "$2" table is empty" + exit -1 + fi + + LC_COLLATE=C sort $SORT_OPT .a.tmp > .b.tmp + + if cmp --silent -- .a.tmp .b.tmp; then + echo ""$2" definitions OK" + else + echo "error: "$2" definitions are not sorted." + diff -y .a.tmp .b.tmp + exit -1 + fi + rm -rf .a.tmp .b.tmp +} + +checkinstr_quoted_name ../../src/ca65/instr.c "sizeof \(InsTab6502\.Ins\) \/ sizeof \(InsTab6502\.Ins\[0\]\)," +checkinstr_quoted_name ../../src/ca65/instr.c "sizeof \(InsTab6502X\.Ins\) \/ sizeof \(InsTab6502X\.Ins\[0\]\)," +checkinstr_quoted_name ../../src/ca65/instr.c "sizeof \(InsTab6502DTV\.Ins\) \/ sizeof \(InsTab6502DTV\.Ins\[0\]\)," +checkinstr_quoted_name ../../src/ca65/instr.c "sizeof \(InsTab65C02\.Ins\) \/ sizeof \(InsTab65C02\.Ins\[0\]\)," +checkinstr_quoted_name ../../src/ca65/instr.c "sizeof \(InsTab4510\.Ins\) \/ sizeof \(InsTab4510\.Ins\[0\]\)," +checkinstr_quoted_name ../../src/ca65/instr.c "sizeof \(InsTab65816\.Ins\) \/ sizeof \(InsTab65816\.Ins\[0\]\)," +checkinstr_quoted_name ../../src/ca65/instr.c "sizeof \(InsTabSweet16\.Ins\) \/ sizeof \(InsTabSweet16\.Ins\[0\]\)," +checkinstr_quoted_name ../../src/ca65/instr.c "sizeof \(InsTabHuC6280\.Ins\) \/ sizeof \(InsTabHuC6280\.Ins\[0\]\)," + +checkarray_quoted_name ../../src/ca65/scanner.c "} DotKeywords \[\] = {" + +checkarray_quoted_name ../../src/cc65/codeinfo.c "static const FuncInfo FuncInfoTable\[\]" +checkarray_quoted_name ../../src/cc65/codeinfo.c "static const ZPInfo ZPInfoTable\[\]" +checkarray_quoted_name ../../src/cc65/codeoptutil.c "static const char\* const Tab\[\]" + +checkarray_quoted_name ../../src/cc65/coptstop.c "static const OptFuncDesc FuncTable\[\]" +checkarray_quoted_name ../../src/cc65/coptstop.c "static const OptFuncDesc FuncRegATable\[\]" + +checkopcodes_quoted_name ../../src/cc65/opcodes.c "const OPCDesc OPCTable\[OP65_COUNT\] = {" +checkarray_quoted_name ../../src/cc65/pragma.c "} Pragmas\[\] = {" +checkarray_quoted_name ../../src/cc65/preproc.c "} PPDTypes\[\] = {" +checkarray_quoted_name ../../src/cc65/scanner.c "} Keywords \[\] = {" +checkarray_quoted_name ../../src/cc65/stdfunc.c "} StdFuncs\[\] = {" + +checkarray_quoted_name ../../src/common/filetype.c "static const FileId TypeTable\[\]" +checkarray_quoted_name ../../src/common/target.c "static const TargetEntry TargetMap\[\]" + +checkarray_quoted_name ../../src/dbginfo/dbginfo.c "} KeywordTable\[\] = {" + +checkarray_quoted_name ../../src/sp65/convert.c "static const ConverterMapEntry ConverterMap\[\]" +checkarray_quoted_name ../../src/sp65/input.c "static const FileId FormatTable\[\]" +checkarray_quoted_name ../../src/sp65/output.c "static const FileId FormatTable\[\]" +checkarray_quoted_name ../../src/sp65/palconv.c "static const PaletteMapEntry PaletteMap\[\]" + diff --git a/.github/checks/sorted_codeopt.sh b/.github/checks/sorted_codeopt.sh new file mode 100755 index 000000000..a248ebc07 --- /dev/null +++ b/.github/checks/sorted_codeopt.sh @@ -0,0 +1,42 @@ +#! /bin/bash +OLDCWD=`pwd` +SCRIPT_PATH=`dirname $0` +CHECK_FILE=../../src/cc65/codeopt.c + +SORT_OPT=-u + +grep "^static OptFunc " $CHECK_FILE | \ + sed -e 's:.*"\(.*\)",.*:\1:g' > .a.tmp + +if [[ -z $(grep '[^[:space:]]' .a.tmp) ]] ; then + echo "error: OptFunc table is empty" + exit -1 +fi + +LC_COLLATE=C sort $SORT_OPT .a.tmp > .b.tmp + +if cmp --silent -- .a.tmp .b.tmp; then + echo "static OptFunc definitions OK" +else + echo "error: static OptFunc definitions are not sorted." + diff -y .a.tmp .b.tmp + exit -1 +fi + +awk '/static OptFunc\* OptFuncs\[\] = {/{flag=1;next}/}/{flag=0}flag' $CHECK_FILE | \ + sed -e 's:.*&D\(.*\),:\1:g' > .a.tmp + +if [[ -z $(grep '[^[:space:]]' .a.tmp) ]] ; then + echo "error: OptFuncs table is empty" + exit -1 +fi + +if cmp --silent -- .a.tmp .b.tmp; then + echo "static OptFuncs* OptFuncs[] definitions OK" +else + echo "error: static OptFuncs* OptFuncs[] definitions are not sorted." + diff -y .a.tmp .b.tmp + exit -1 +fi + +rm -rf .a.tmp .b.tmp diff --git a/Makefile b/Makefile index 29fcbbf96..edfd8166c 100644 --- a/Makefile +++ b/Makefile @@ -50,6 +50,7 @@ test: # GNU "check" target, which runs all tests check: @$(MAKE) -C .github/checks checkstyle --no-print-directory + @$(MAKE) -C .github/checks sorted --no-print-directory @$(MAKE) test @$(MAKE) -C targettest platforms --no-print-directory @$(MAKE) -C samples platforms --no-print-directory From 58ff844d04361332d3d37886eb11e3ceebc6d1a5 Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Mon, 9 Jun 2025 18:42:52 +0200 Subject: [PATCH 23/60] add to GHA --- .github/workflows/build-on-pull-request.yml | 3 +++ .github/workflows/snapshot-on-push-master.yml | 3 +++ 2 files changed, 6 insertions(+) diff --git a/.github/workflows/build-on-pull-request.yml b/.github/workflows/build-on-pull-request.yml index 7b762844b..3cb628529 100644 --- a/.github/workflows/build-on-pull-request.yml +++ b/.github/workflows/build-on-pull-request.yml @@ -24,6 +24,9 @@ jobs: - name: Do some simple style checks shell: bash run: make -j2 checkstyle + - name: Check bsearch tables + shell: bash + run: make -j2 sorted - name: Build the tools. shell: bash run: make -j2 bin USER_CFLAGS=-Werror diff --git a/.github/workflows/snapshot-on-push-master.yml b/.github/workflows/snapshot-on-push-master.yml index 42794f10b..557ba24af 100644 --- a/.github/workflows/snapshot-on-push-master.yml +++ b/.github/workflows/snapshot-on-push-master.yml @@ -49,6 +49,9 @@ jobs: - name: Do some simple style checks shell: bash run: make -j2 checkstyle + - name: Check bsearch tables + shell: bash + run: make -j2 sorted - name: Build the tools. shell: bash run: | From 717e32ba6aab6f6eecfb87aa0b287efd4cc52dd1 Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Mon, 9 Jun 2025 18:45:52 +0200 Subject: [PATCH 24/60] add "sorted" target --- Makefile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index edfd8166c..0a12490fc 100644 --- a/Makefile +++ b/Makefile @@ -41,7 +41,11 @@ util: # check the code style checkstyle: - @$(MAKE) -C .github/checks --no-print-directory $@ + @$(MAKE) -C .github/checks --no-print-directory $@ + +# check bsearch tables +sorted: + @$(MAKE) -C .github/checks --no-print-directory $@ # runs regression tests, requires libtest target libraries test: From 1e80269c6b22371927a35ae19803f0b30be261e5 Mon Sep 17 00:00:00 2001 From: Konstantin <sintechs@gmail.com> Date: Mon, 9 Jun 2025 21:14:01 +0300 Subject: [PATCH 25/60] Add comment about why AppleSingle header is needed --- libsrc/agat/exehdr.s | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libsrc/agat/exehdr.s b/libsrc/agat/exehdr.s index 72ea390e9..3f3047bf9 100644 --- a/libsrc/agat/exehdr.s +++ b/libsrc/agat/exehdr.s @@ -4,6 +4,9 @@ ; This module supplies an AppleSingle version 2 file header + entry with ; ID 11 according to https://tools.ietf.org/rfc/rfc1740.txt Appendix A. ; +; Agat target uses this header only for compatibility with Apple Commander +; because Agat's 140K disk filesystem is identical to Apple II DOS 3.3 and +; "ac.jar -as" option can be used to import binaries into disk images. .export __EXEHDR__ : absolute = 1 ; Linker referenced .import __FILETYPE__ ; Linker generated From 9afe980124a6ffe349664aa14e7413de1df80166 Mon Sep 17 00:00:00 2001 From: Konstantin <sintechs@gmail.com> Date: Mon, 9 Jun 2025 21:17:47 +0300 Subject: [PATCH 26/60] Add dash for naming consistency --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4c1003179..891c31e86 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ the [cc65 web site](https://cc65.github.io): | Dr. Jozo Dujmović | Picocomputer (RP6502) | | Watara | Watura/QuickShot Supervision | | Synertek | SYM-1 | -| USSR | Agat 7/9 | +| USSR | Agat-7/9 | A generic configuration to adapt cc65 to new targets is also around. From aaa1058d32fbb9a67fed7d707fe03fd37304f731 Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Mon, 9 Jun 2025 21:48:20 +0200 Subject: [PATCH 27/60] use explicit markers (comments) for the bsearch table checking, simplifies the scripts and makes them more robust too :) --- .github/checks/Makefile | 3 +- .github/checks/sorted.sh | 105 +++++-------------------------- .github/checks/sorted_codeopt.sh | 77 ++++++++++++++--------- .github/checks/sorted_opcodes.sh | 42 +++++++++++++ src/ca65/instr.c | 18 ++++++ src/ca65/scanner.c | 2 + src/cc65/codeinfo.c | 4 ++ src/cc65/codeopt.c | 4 ++ src/cc65/codeoptutil.c | 2 + src/cc65/coptstop.c | 4 ++ src/cc65/opcodes.c | 3 + src/cc65/pragma.c | 2 + src/cc65/preproc.c | 2 + src/cc65/scanner.c | 2 + src/cc65/stdfunc.c | 2 + src/common/filetype.c | 3 +- src/common/target.c | 2 + src/dbginfo/dbginfo.c | 2 + src/sp65/convert.c | 2 + src/sp65/input.c | 3 +- src/sp65/output.c | 3 +- src/sp65/palconv.c | 2 + 22 files changed, 165 insertions(+), 124 deletions(-) create mode 100755 .github/checks/sorted_opcodes.sh diff --git a/.github/checks/Makefile b/.github/checks/Makefile index 8245958c1..ee373d53d 100644 --- a/.github/checks/Makefile +++ b/.github/checks/Makefile @@ -35,8 +35,9 @@ spaces: spaces.sh noexec: noexec.sh @./noexec.sh -sorted: sorted.sh sorted_codeopt.sh +sorted: sorted.sh sorted_codeopt.sh sorted_opcodes.sh @./sorted.sh @./sorted_codeopt.sh + @./sorted_opcodes.sh endif diff --git a/.github/checks/sorted.sh b/.github/checks/sorted.sh index 4311225cd..58d82ed67 100755 --- a/.github/checks/sorted.sh +++ b/.github/checks/sorted.sh @@ -2,116 +2,39 @@ OLDCWD=`pwd` SCRIPT_PATH=`dirname $0` +CHECK_DIR=../../src + SORT_OPT=-u function checkarray_quoted_name { CHECK_FILE="$1" + START="\\/\\* BEGIN SORTED.SH \\*\\/" + END="\\/\\* END SORTED.SH \\*\\/" - awk '/'"$2"'/{flag=1;next}/};/{flag=0}flag' "$CHECK_FILE" | \ - sed -e 's:.*\"\(.*\)\".*:\1:g' | \ - sed '/^\s*$/d' > .a.tmp + awk '/'"$START"'/{flag=1; count++; next} /'"$END"'/{flag=0;} flag {print count,"##",$0}' "$CHECK_FILE" | \ + sed -e 's:\(.*\) ##.*\"\(.*\)\".*:\1##\2:g' > .a.tmp if [[ -z $(grep '[^[:space:]]' .a.tmp) ]] ; then - echo "error: "$2" table is empty" + echo "error: "$1" table is empty" + rm -rf .a.tmp exit -1 fi LC_COLLATE=C sort $SORT_OPT .a.tmp > .b.tmp if cmp --silent -- .a.tmp .b.tmp; then - echo ""$2" definitions OK" + echo ""$1" tables OK" else - echo "error: "$2" definitions are not sorted." + echo "error: "$1" tables are not sorted." diff -y .a.tmp .b.tmp + rm -rf .a.tmp .b.tmp exit -1 fi rm -rf .a.tmp .b.tmp } -function checkinstr_quoted_name -{ - CHECK_FILE="$1" - - awk '/'"$2"'/{flag=1;next}/};/{flag=0}flag' "$CHECK_FILE" | \ - sed -e 's:^ *{$::g' | \ - sed -e 's:^ *}$::g' | \ - sed -e 's:.*\"\(.*\)\".*:\1:g' | \ - sed '/^\s*$/d' > .a.tmp - - if [[ -z $(grep '[^[:space:]]' .a.tmp) ]] ; then - echo "error: "$2" table is empty" - exit -1 - fi - - LC_COLLATE=C sort $SORT_OPT .a.tmp > .b.tmp - - if cmp --silent -- .a.tmp .b.tmp; then - echo ""$2" definitions OK" - else - echo "error: "$2" definitions are not sorted." - diff -y .a.tmp .b.tmp - exit -1 - fi - rm -rf .a.tmp .b.tmp -} - -function checkopcodes_quoted_name -{ - CHECK_FILE="$1" - - awk '/'"$2"'/{flag=1;next}/};/{flag=0}flag' "$CHECK_FILE" | \ - grep "^ *\".*\"," | \ - sed '/^\s*$/d' > .a.tmp - - if [[ -z $(grep '[^[:space:]]' .a.tmp) ]] ; then - echo "error: "$2" table is empty" - exit -1 - fi - - LC_COLLATE=C sort $SORT_OPT .a.tmp > .b.tmp - - if cmp --silent -- .a.tmp .b.tmp; then - echo ""$2" definitions OK" - else - echo "error: "$2" definitions are not sorted." - diff -y .a.tmp .b.tmp - exit -1 - fi - rm -rf .a.tmp .b.tmp -} - -checkinstr_quoted_name ../../src/ca65/instr.c "sizeof \(InsTab6502\.Ins\) \/ sizeof \(InsTab6502\.Ins\[0\]\)," -checkinstr_quoted_name ../../src/ca65/instr.c "sizeof \(InsTab6502X\.Ins\) \/ sizeof \(InsTab6502X\.Ins\[0\]\)," -checkinstr_quoted_name ../../src/ca65/instr.c "sizeof \(InsTab6502DTV\.Ins\) \/ sizeof \(InsTab6502DTV\.Ins\[0\]\)," -checkinstr_quoted_name ../../src/ca65/instr.c "sizeof \(InsTab65C02\.Ins\) \/ sizeof \(InsTab65C02\.Ins\[0\]\)," -checkinstr_quoted_name ../../src/ca65/instr.c "sizeof \(InsTab4510\.Ins\) \/ sizeof \(InsTab4510\.Ins\[0\]\)," -checkinstr_quoted_name ../../src/ca65/instr.c "sizeof \(InsTab65816\.Ins\) \/ sizeof \(InsTab65816\.Ins\[0\]\)," -checkinstr_quoted_name ../../src/ca65/instr.c "sizeof \(InsTabSweet16\.Ins\) \/ sizeof \(InsTabSweet16\.Ins\[0\]\)," -checkinstr_quoted_name ../../src/ca65/instr.c "sizeof \(InsTabHuC6280\.Ins\) \/ sizeof \(InsTabHuC6280\.Ins\[0\]\)," - -checkarray_quoted_name ../../src/ca65/scanner.c "} DotKeywords \[\] = {" - -checkarray_quoted_name ../../src/cc65/codeinfo.c "static const FuncInfo FuncInfoTable\[\]" -checkarray_quoted_name ../../src/cc65/codeinfo.c "static const ZPInfo ZPInfoTable\[\]" -checkarray_quoted_name ../../src/cc65/codeoptutil.c "static const char\* const Tab\[\]" - -checkarray_quoted_name ../../src/cc65/coptstop.c "static const OptFuncDesc FuncTable\[\]" -checkarray_quoted_name ../../src/cc65/coptstop.c "static const OptFuncDesc FuncRegATable\[\]" - -checkopcodes_quoted_name ../../src/cc65/opcodes.c "const OPCDesc OPCTable\[OP65_COUNT\] = {" -checkarray_quoted_name ../../src/cc65/pragma.c "} Pragmas\[\] = {" -checkarray_quoted_name ../../src/cc65/preproc.c "} PPDTypes\[\] = {" -checkarray_quoted_name ../../src/cc65/scanner.c "} Keywords \[\] = {" -checkarray_quoted_name ../../src/cc65/stdfunc.c "} StdFuncs\[\] = {" - -checkarray_quoted_name ../../src/common/filetype.c "static const FileId TypeTable\[\]" -checkarray_quoted_name ../../src/common/target.c "static const TargetEntry TargetMap\[\]" - -checkarray_quoted_name ../../src/dbginfo/dbginfo.c "} KeywordTable\[\] = {" - -checkarray_quoted_name ../../src/sp65/convert.c "static const ConverterMapEntry ConverterMap\[\]" -checkarray_quoted_name ../../src/sp65/input.c "static const FileId FormatTable\[\]" -checkarray_quoted_name ../../src/sp65/output.c "static const FileId FormatTable\[\]" -checkarray_quoted_name ../../src/sp65/palconv.c "static const PaletteMapEntry PaletteMap\[\]" +for N in `grep -rl "BEGIN SORTED.SH" "$CHECK_DIR"`; do + checkarray_quoted_name $N +done diff --git a/.github/checks/sorted_codeopt.sh b/.github/checks/sorted_codeopt.sh index a248ebc07..f15295990 100755 --- a/.github/checks/sorted_codeopt.sh +++ b/.github/checks/sorted_codeopt.sh @@ -1,42 +1,61 @@ #! /bin/bash OLDCWD=`pwd` SCRIPT_PATH=`dirname $0` -CHECK_FILE=../../src/cc65/codeopt.c + +CHECK_DIR=../../src SORT_OPT=-u -grep "^static OptFunc " $CHECK_FILE | \ - sed -e 's:.*"\(.*\)",.*:\1:g' > .a.tmp +function checkarray +{ + CHECK_FILE="$1" + START="\\/\\* BEGIN DECL SORTED_CODEOPT.SH \\*\\/" + END="\\/\\* END DECL SORTED_CODEOPT.SH \\*\\/" -if [[ -z $(grep '[^[:space:]]' .a.tmp) ]] ; then - echo "error: OptFunc table is empty" - exit -1 -fi + awk '/'"$START"'/{flag=1; count++; next} /'"$END"'/{flag=0;} flag {print count,"##",$0}' "$CHECK_FILE" | \ + sed -e 's:\(.*##\).*"\(.*\)",.*:\1\2:g' > .a.tmp -LC_COLLATE=C sort $SORT_OPT .a.tmp > .b.tmp + if [[ -z $(grep '[^[:space:]]' .a.tmp) ]] ; then + echo "error: "$1" table is empty" + rm -rf .a.tmp + exit -1 + fi -if cmp --silent -- .a.tmp .b.tmp; then - echo "static OptFunc definitions OK" -else - echo "error: static OptFunc definitions are not sorted." - diff -y .a.tmp .b.tmp - exit -1 -fi + LC_COLLATE=C sort $SORT_OPT .a.tmp > .b.tmp -awk '/static OptFunc\* OptFuncs\[\] = {/{flag=1;next}/}/{flag=0}flag' $CHECK_FILE | \ - sed -e 's:.*&D\(.*\),:\1:g' > .a.tmp + if cmp --silent -- .a.tmp .b.tmp; then + echo ""$1" decls OK" + else + echo "error: "$1" decls are not sorted." + diff -y .a.tmp .b.tmp + rm -rf .a.tmp .b.tmp + exit -1 + fi -if [[ -z $(grep '[^[:space:]]' .a.tmp) ]] ; then - echo "error: OptFuncs table is empty" - exit -1 -fi + START="\\/\\* BEGIN SORTED_CODEOPT.SH \\*\\/" + END="\\/\\* END SORTED_CODEOPT.SH \\*\\/" + awk '/'"$START"'/{flag=1; count++; next} /'"$END"'/{flag=0;} flag {print count,"##",$0}' "$CHECK_FILE" | \ + sed -e 's:\(.*##\).*&D\(.*\),.*:\1\2:g' > .a.tmp -if cmp --silent -- .a.tmp .b.tmp; then - echo "static OptFuncs* OptFuncs[] definitions OK" -else - echo "error: static OptFuncs* OptFuncs[] definitions are not sorted." - diff -y .a.tmp .b.tmp - exit -1 -fi + if [[ -z $(grep '[^[:space:]]' .a.tmp) ]] ; then + echo "error: "$1" table is empty" + rm -rf .a.tmp + exit -1 + fi -rm -rf .a.tmp .b.tmp + if cmp --silent -- .a.tmp .b.tmp; then + echo ""$1" tables OK" + else + echo "error: "$1" tables are not sorted." + diff -y .a.tmp .b.tmp + rm -rf .a.tmp .b.tmp + exit -1 + fi + + rm -rf .a.tmp .b.tmp +} + + +for N in `grep -rl "BEGIN DECL SORTED_CODEOPT.SH" "$CHECK_DIR"`; do + checkarray $N +done diff --git a/.github/checks/sorted_opcodes.sh b/.github/checks/sorted_opcodes.sh new file mode 100755 index 000000000..a1f8fcbfa --- /dev/null +++ b/.github/checks/sorted_opcodes.sh @@ -0,0 +1,42 @@ +#! /bin/bash +OLDCWD=`pwd` +SCRIPT_PATH=`dirname $0` + +CHECK_DIR=../../src + +SORT_OPT=-u + +function checkarray_quoted_name +{ + CHECK_FILE="$1" + START="\\/\\* BEGIN SORTED_OPCODES.SH \\*\\/" + END="\\/\\* END SORTED_OPCODES.SH \\*\\/" + + awk '/'"$START"'/{flag=1; count++; next} /'"$END"'/{flag=0;} flag {print count,"##",$0}' "$CHECK_FILE" | \ + sed 's:/\*.*::g' | \ + grep '".*",' | \ + sed -e 's:\(.*\) ##.*\"\(.*\)\".*:\1##\2:g' > .a.tmp + + if [[ -z $(grep '[^[:space:]]' .a.tmp) ]] ; then + echo "error: "$1" table is empty" + rm -rf .a.tmp + exit -1 + fi + + LC_COLLATE=C sort $SORT_OPT .a.tmp > .b.tmp + + if cmp --silent -- .a.tmp .b.tmp; then + echo ""$1" tables OK" + else + echo "error: "$1" tables are not sorted." + diff -y .a.tmp .b.tmp + rm -rf .a.tmp .b.tmp + exit -1 + fi + rm -rf .a.tmp .b.tmp +} + +for N in `grep -rl "BEGIN SORTED_OPCODES.SH" "$CHECK_DIR"`; do + checkarray_quoted_name $N +done + diff --git a/src/ca65/instr.c b/src/ca65/instr.c index f1d8d706a..c7a68006c 100644 --- a/src/ca65/instr.c +++ b/src/ca65/instr.c @@ -172,6 +172,7 @@ static const struct { /* CAUTION: table must be sorted for bsearch */ sizeof (InsTab6502.Ins) / sizeof (InsTab6502.Ins[0]), { +/* BEGIN SORTED.SH */ { "ADC", 0x080A26C, 0x60, 0, PutAll }, { "AND", 0x080A26C, 0x20, 0, PutAll }, { "ASL", 0x000006e, 0x02, 1, PutAll }, @@ -228,6 +229,7 @@ static const struct { { "TXA", 0x0000001, 0x8a, 0, PutAll }, { "TXS", 0x0000001, 0x9a, 0, PutAll }, { "TYA", 0x0000001, 0x98, 0, PutAll } +/* END SORTED.SH */ } }; @@ -239,6 +241,7 @@ static const struct { /* CAUTION: table must be sorted for bsearch */ sizeof (InsTab6502X.Ins) / sizeof (InsTab6502X.Ins[0]), { +/* BEGIN SORTED.SH */ { "ADC", 0x080A26C, 0x60, 0, PutAll }, { "ALR", 0x0800000, 0x4B, 0, PutAll }, /* X */ { "ANC", 0x0800000, 0x0B, 0, PutAll }, /* X */ @@ -314,6 +317,7 @@ static const struct { { "TXA", 0x0000001, 0x8a, 0, PutAll }, { "TXS", 0x0000001, 0x9a, 0, PutAll }, { "TYA", 0x0000001, 0x98, 0, PutAll } +/* END SORTED.SH */ } }; @@ -329,6 +333,7 @@ static const struct { /* CAUTION: table must be sorted for bsearch */ sizeof (InsTab6502DTV.Ins) / sizeof (InsTab6502DTV.Ins[0]), { +/* BEGIN SORTED.SH */ { "ADC", 0x080A26C, 0x60, 0, PutAll }, { "ALR", 0x0800000, 0x4B, 0, PutAll }, /* X */ { "ANC", 0x0800000, 0x0B, 0, PutAll }, /* X */ @@ -400,6 +405,7 @@ static const struct { { "TXA", 0x0000001, 0x8a, 0, PutAll }, { "TXS", 0x0000001, 0x9a, 0, PutAll }, { "TYA", 0x0000001, 0x98, 0, PutAll } +/* END SORTED.SH */ } }; @@ -411,6 +417,7 @@ static const struct { /* CAUTION: table must be sorted for bsearch */ sizeof (InsTab65SC02.Ins) / sizeof (InsTab65SC02.Ins[0]), { +/* BEGIN SORTED.SH */ { "ADC", 0x080A66C, 0x60, 0, PutAll }, { "AND", 0x080A66C, 0x20, 0, PutAll }, { "ASL", 0x000006e, 0x02, 1, PutAll }, @@ -477,6 +484,7 @@ static const struct { { "TXA", 0x0000001, 0x8a, 0, PutAll }, { "TXS", 0x0000001, 0x9a, 0, PutAll }, { "TYA", 0x0000001, 0x98, 0, PutAll } +/* END SORTED.SH */ } }; @@ -488,6 +496,7 @@ static const struct { /* CAUTION: table must be sorted for bsearch */ sizeof (InsTab65C02.Ins) / sizeof (InsTab65C02.Ins[0]), { +/* BEGIN SORTED.SH */ { "ADC", 0x080A66C, 0x60, 0, PutAll }, { "AND", 0x080A66C, 0x20, 0, PutAll }, { "ASL", 0x000006e, 0x02, 1, PutAll }, @@ -588,6 +597,7 @@ static const struct { { "TXS", 0x0000001, 0x9a, 0, PutAll }, { "TYA", 0x0000001, 0x98, 0, PutAll }, { "WAI", 0x0000001, 0xcb, 0, PutAll } +/* END SORTED.SH */ } }; @@ -599,6 +609,7 @@ static const struct { /* CAUTION: table must be sorted for bsearch */ sizeof (InsTab4510.Ins) / sizeof (InsTab4510.Ins[0]), { +/* BEGIN SORTED.SH */ { "ADC", 0x080A66C, 0x60, 0, PutAll }, { "AND", 0x080A66C, 0x20, 0, PutAll }, { "ASL", 0x000006e, 0x02, 1, PutAll }, @@ -732,6 +743,7 @@ static const struct { { "TYA", 0x0000001, 0x98, 0, PutAll }, { "TYS", 0x0000001, 0x2b, 0, PutAll }, { "TZA", 0x0000001, 0x6b, 0, PutAll }, +/* END SORTED.SH */ } }; @@ -743,6 +755,7 @@ static const struct { /* CAUTION: table must be sorted for bsearch */ sizeof (InsTab65816.Ins) / sizeof (InsTab65816.Ins[0]), { +/* BEGIN SORTED.SH */ { "ADC", 0x0b8f6fc, 0x60, 0, PutAll }, { "AND", 0x0b8f6fc, 0x20, 0, PutAll }, { "ASL", 0x000006e, 0x02, 1, PutAll }, @@ -843,6 +856,7 @@ static const struct { { "WDM", 0x0800004, 0x42, 6, PutAll }, { "XBA", 0x0000001, 0xeb, 0, PutAll }, { "XCE", 0x0000001, 0xfb, 0, PutAll } +/* END SORTED.SH */ } }; @@ -854,6 +868,7 @@ static const struct { /* CAUTION: table must be sorted for bsearch */ sizeof (InsTabSweet16.Ins) / sizeof (InsTabSweet16.Ins[0]), { +/* BEGIN SORTED.SH */ { "ADD", AMSW16_REG, 0xA0, 0, PutSweet16 }, { "BC", AMSW16_BRA, 0x03, 0, PutSweet16Branch }, { "BK", AMSW16_IMP, 0x0A, 0, PutSweet16 }, @@ -880,6 +895,7 @@ static const struct { { "STD", AMSW16_IND, 0x70, 0, PutSweet16 }, { "STP", AMSW16_IND, 0x90, 0, PutSweet16 }, { "SUB", AMSW16_REG, 0xB0, 0, PutSweet16 }, +/* END SORTED.SH */ } }; @@ -891,6 +907,7 @@ static const struct { /* CAUTION: table must be sorted for bsearch */ sizeof (InsTabHuC6280.Ins) / sizeof (InsTabHuC6280.Ins[0]), { +/* BEGIN SORTED.SH */ { "ADC", 0x080A66C, 0x60, 0, PutAll }, { "AND", 0x080A66C, 0x20, 0, PutAll }, { "ASL", 0x000006e, 0x02, 1, PutAll }, @@ -1026,6 +1043,7 @@ static const struct { { "TXA", 0x0000001, 0x8a, 0, PutAll }, { "TXS", 0x0000001, 0x9a, 0, PutAll }, { "TYA", 0x0000001, 0x98, 0, PutAll } +/* END SORTED.SH */ } }; diff --git a/src/ca65/scanner.c b/src/ca65/scanner.c index 11beb4d63..94c84d897 100644 --- a/src/ca65/scanner.c +++ b/src/ca65/scanner.c @@ -136,6 +136,7 @@ struct DotKeyword { const char* Key; /* MUST be first field */ token_t Tok; } DotKeywords [] = { +/* BEGIN SORTED.SH */ { ".A16", TOK_A16 }, { ".A8", TOK_A8 }, { ".ADDR", TOK_ADDR }, @@ -307,6 +308,7 @@ struct DotKeyword { { ".XMATCH", TOK_XMATCH }, { ".XOR", TOK_BOOLXOR }, { ".ZEROPAGE", TOK_ZEROPAGE }, +/* END SORTED.SH */ }; diff --git a/src/cc65/codeinfo.c b/src/cc65/codeinfo.c index 8396ecfd5..29f18cb78 100644 --- a/src/cc65/codeinfo.c +++ b/src/cc65/codeinfo.c @@ -92,6 +92,7 @@ struct FuncInfo { */ /* CAUTION: table must be sorted for bsearch */ static const FuncInfo FuncInfoTable[] = { +/* BEGIN SORTED.SH */ { "addeq0sp", SLV_TOP | REG_AX, PSTATE_ALL | REG_AXY }, { "addeqysp", SLV_IND | REG_AXY, PSTATE_ALL | REG_AXY }, { "addysp", REG_SP | REG_Y, PSTATE_ALL | REG_SP }, @@ -377,12 +378,14 @@ static const FuncInfo FuncInfoTable[] = { { "tosxoreax", SLV_TOP | REG_EAX, PSTATE_ALL | REG_SP | REG_EAXY | REG_TMP1 }, { "tsteax", REG_EAX, PSTATE_ALL | REG_Y }, { "utsteax", REG_EAX, PSTATE_ALL | REG_Y }, +/* END SORTED.SH */ }; #define FuncInfoCount (sizeof(FuncInfoTable) / sizeof(FuncInfoTable[0])) /* Table with names of zero page locations used by the compiler */ /* CAUTION: table must be sorted for bsearch */ static const ZPInfo ZPInfoTable[] = { +/* BEGIN SORTED.SH */ { 0, "ptr1", 2, REG_PTR1_LO, REG_PTR1 }, { 0, "ptr1+1", 1, REG_PTR1_HI, REG_PTR1 }, { 0, "ptr2", 2, REG_PTR2_LO, REG_PTR2 }, @@ -400,6 +403,7 @@ static const ZPInfo ZPInfoTable[] = { { 0, "tmp2", 1, REG_NONE, REG_NONE }, { 0, "tmp3", 1, REG_NONE, REG_NONE }, { 0, "tmp4", 1, REG_NONE, REG_NONE }, +/* END SORTED.SH */ }; #define ZPInfoCount (sizeof(ZPInfoTable) / sizeof(ZPInfoTable[0])) diff --git a/src/cc65/codeopt.c b/src/cc65/codeopt.c index 9de2ab7ba..c8d7d2ce9 100644 --- a/src/cc65/codeopt.c +++ b/src/cc65/codeopt.c @@ -103,6 +103,7 @@ struct OptFunc { /* A list of all the function descriptions */ /* CAUTION: should be sorted by "name" */ +/* BEGIN DECL SORTED_CODEOPT.SH */ static OptFunc DOpt65C02BitOps = { Opt65C02BitOps, "Opt65C02BitOps", 66, 0, 0, 0, 0, 0 }; static OptFunc DOpt65C02Ind = { Opt65C02Ind, "Opt65C02Ind", 100, 0, 0, 0, 0, 0 }; static OptFunc DOpt65C02Stores = { Opt65C02Stores, "Opt65C02Stores", 100, 0, 0, 0, 0, 0 }; @@ -215,11 +216,13 @@ static OptFunc DOptTransfers3 = { OptTransfers3, "OptTransfers3", 65, 0, static OptFunc DOptTransfers4 = { OptTransfers4, "OptTransfers4", 65, 0, 0, 0, 0, 0 }; static OptFunc DOptUnusedLoads = { OptUnusedLoads, "OptUnusedLoads", 0, 0, 0, 0, 0, 0 }; static OptFunc DOptUnusedStores = { OptUnusedStores, "OptUnusedStores", 0, 0, 0, 0, 0, 0 }; +/* END DECL SORTED_CODEOPT.SH */ /* Table containing all the steps in alphabetical order */ /* CAUTION: table must be sorted for bsearch */ static OptFunc* OptFuncs[] = { +/* BEGIN SORTED_CODEOPT.SH */ &DOpt65C02BitOps, &DOpt65C02Ind, &DOpt65C02Stores, @@ -332,6 +335,7 @@ static OptFunc* OptFuncs[] = { &DOptTransfers4, &DOptUnusedLoads, &DOptUnusedStores, +/* END SORTED_CODEOPT.SH */ }; #define OPTFUNC_COUNT (sizeof(OptFuncs) / sizeof(OptFuncs[0])) diff --git a/src/cc65/codeoptutil.c b/src/cc65/codeoptutil.c index c18ccf18b..7547ef5ba 100644 --- a/src/cc65/codeoptutil.c +++ b/src/cc65/codeoptutil.c @@ -1227,7 +1227,9 @@ static int CmpHarmless (const void* Key, const void* Entry) /* CAUTION: table must be sorted for bsearch */ static const char* const Tab[] = { +/* BEGIN SORTED.SH */ "_abs", +/* END SORTED.SH */ }; int HarmlessCall (const CodeEntry* E, int PushedBytes) diff --git a/src/cc65/coptstop.c b/src/cc65/coptstop.c index 90ab78c50..e5d686d1a 100644 --- a/src/cc65/coptstop.c +++ b/src/cc65/coptstop.c @@ -1466,6 +1466,7 @@ static unsigned Opt_a_tosxor (StackOpData* D) /* CAUTION: table must be sorted for bsearch */ static const OptFuncDesc FuncTable[] = { +/* BEGIN SORTED.SH */ { "___bzero", Opt___bzero, REG_NONE, OP_X_ZERO | OP_A_KNOWN }, { "staspidx", Opt_staspidx, REG_NONE, OP_NONE }, { "staxspidx", Opt_staxspidx, REG_AX, OP_NONE }, @@ -1486,10 +1487,12 @@ static const OptFuncDesc FuncTable[] = { { "tosuleax", Opt_tosuleax, REG_NONE, OP_RHS_REMOVE_DIRECT | OP_RHS_LOAD_DIRECT }, { "tosultax", Opt_tosultax, REG_NONE, OP_RHS_REMOVE_DIRECT | OP_RHS_LOAD_DIRECT }, { "tosxorax", Opt_tosxorax, REG_NONE, OP_NONE }, +/* END SORTED.SH */ }; /* CAUTION: table must be sorted for bsearch */ static const OptFuncDesc FuncRegATable[] = { +/* BEGIN SORTED.SH */ { "tosandax", Opt_a_tosand, REG_NONE, OP_RHS_REMOVE_DIRECT | OP_RHS_LOAD_DIRECT }, { "toseqax", Opt_a_toseq, REG_NONE, OP_NONE }, { "tosgeax", Opt_a_tosuge, REG_NONE, OP_NONE }, @@ -1505,6 +1508,7 @@ static const OptFuncDesc FuncRegATable[] = { { "tosuleax", Opt_a_tosule, REG_NONE, OP_NONE }, { "tosultax", Opt_a_tosult, REG_NONE, OP_NONE }, { "tosxorax", Opt_a_tosxor, REG_NONE, OP_RHS_REMOVE_DIRECT | OP_RHS_LOAD_DIRECT }, +/* END SORTED.SH */ }; #define FUNC_COUNT(Table) (sizeof(Table) / sizeof(Table[0])) diff --git a/src/cc65/opcodes.c b/src/cc65/opcodes.c index c591c4ea3..49363769e 100644 --- a/src/cc65/opcodes.c +++ b/src/cc65/opcodes.c @@ -59,6 +59,8 @@ const OPCDesc OPCTable[OP65_COUNT] = { /* 65XX opcodes */ + +/* BEGIN SORTED_OPCODES.SH */ { OP65_ADC, /* opcode */ "adc", /* mnemonic */ 0, /* size */ @@ -587,6 +589,7 @@ const OPCDesc OPCTable[OP65_COUNT] = { REG_Y, /* use */ REG_A | PSTATE_ZN /* chg */ }, +/* END SORTED_OPCODES.SH */ }; diff --git a/src/cc65/pragma.c b/src/cc65/pragma.c index 5de4c8dfc..c9fdefd9b 100644 --- a/src/cc65/pragma.c +++ b/src/cc65/pragma.c @@ -94,6 +94,7 @@ static const struct Pragma { const char* Key; /* Keyword */ pragma_t Tok; /* Token */ } Pragmas[] = { +/* BEGIN SORTED.SH */ { "align", PRAGMA_ALIGN }, { "allow-eager-inline", PRAGMA_ALLOW_EAGER_INLINE }, { "allow_eager_inline", PRAGMA_ALLOW_EAGER_INLINE }, @@ -128,6 +129,7 @@ static const struct Pragma { { "writable-strings", PRAGMA_WRITABLE_STRINGS }, { "writable_strings", PRAGMA_WRITABLE_STRINGS }, { "zpsym", PRAGMA_ZPSYM }, +/* END SORTED.SH */ }; #define PRAGMA_COUNT (sizeof (Pragmas) / sizeof (Pragmas[0])) diff --git a/src/cc65/preproc.c b/src/cc65/preproc.c index d70c28147..96fa565f2 100644 --- a/src/cc65/preproc.c +++ b/src/cc65/preproc.c @@ -221,6 +221,7 @@ static const struct PPDType { const char* Tok; /* Token */ ppdirective_t Type; /* Type */ } PPDTypes[] = { +/* BEGIN SORTED.SH */ { "define", PPD_DEFINE }, { "elif", PPD_ELIF }, { "else", PPD_ELSE }, @@ -234,6 +235,7 @@ static const struct PPDType { { "pragma", PPD_PRAGMA }, { "undef", PPD_UNDEF }, { "warning", PPD_WARNING }, +/* END SORTED.SH */ }; /* Number of preprocessor directive types */ diff --git a/src/cc65/scanner.c b/src/cc65/scanner.c index 1549b51bd..dda857f07 100644 --- a/src/cc65/scanner.c +++ b/src/cc65/scanner.c @@ -93,6 +93,7 @@ static const struct Keyword { unsigned char Tok; /* The token */ unsigned char Std; /* Token supported in which standards? */ } Keywords [] = { +/* BEGIN SORTED.SH */ { "_Pragma", TOK_PRAGMA, TT_C89 | TT_C99 | TT_CC65 }, /* !! */ { "_Static_assert", TOK_STATIC_ASSERT, TT_CC65 }, /* C11 */ { "__AX__", TOK_AX, TT_C89 | TT_C99 | TT_CC65 }, @@ -146,6 +147,7 @@ static const struct Keyword { { "void", TOK_VOID, TT_C89 | TT_C99 | TT_CC65 }, { "volatile", TOK_VOLATILE, TT_C89 | TT_C99 | TT_CC65 }, { "while", TOK_WHILE, TT_C89 | TT_C99 | TT_CC65 }, +/* END SORTED.SH */ }; #define KEY_COUNT (sizeof (Keywords) / sizeof (Keywords [0])) diff --git a/src/cc65/stdfunc.c b/src/cc65/stdfunc.c index 3bd3f3552..3f33cdcce 100644 --- a/src/cc65/stdfunc.c +++ b/src/cc65/stdfunc.c @@ -85,11 +85,13 @@ static struct StdFuncDesc { const char* Name; void (*Handler) (FuncDesc*, ExprDesc*); } StdFuncs[] = { +/* BEGIN SORTED.SH */ { "memcpy", StdFunc_memcpy }, { "memset", StdFunc_memset }, { "strcmp", StdFunc_strcmp }, { "strcpy", StdFunc_strcpy }, { "strlen", StdFunc_strlen }, +/* END SORTED.SH */ }; #define FUNC_COUNT (sizeof (StdFuncs) / sizeof (StdFuncs[0])) diff --git a/src/common/filetype.c b/src/common/filetype.c index 4aececa78..074f8800a 100644 --- a/src/common/filetype.c +++ b/src/common/filetype.c @@ -51,6 +51,7 @@ /* CAUTION: table must be sorted for bsearch */ static const FileId TypeTable[] = { /* Upper case stuff for obsolete operating systems */ +/* BEGIN SORTED.SH */ { "A", FILETYPE_LIB }, { "A65", FILETYPE_ASM }, { "ASM", FILETYPE_ASM }, @@ -66,7 +67,6 @@ static const FileId TypeTable[] = { { "S", FILETYPE_ASM }, { "SER", FILETYPE_O65 }, { "TGI", FILETYPE_O65 }, - { "a", FILETYPE_LIB }, { "a65", FILETYPE_ASM }, { "asm", FILETYPE_ASM }, @@ -82,6 +82,7 @@ static const FileId TypeTable[] = { { "s", FILETYPE_ASM }, { "ser", FILETYPE_O65 }, { "tgi", FILETYPE_O65 }, +/* END SORTED.SH */ }; #define FILETYPE_COUNT (sizeof (TypeTable) / sizeof (TypeTable[0])) diff --git a/src/common/target.c b/src/common/target.c index 18da67b00..24e9f4495 100644 --- a/src/common/target.c +++ b/src/common/target.c @@ -143,6 +143,7 @@ struct TargetEntry { ** CAUTION: must be alphabetically for bsearch(). */ static const TargetEntry TargetMap[] = { +/* BEGIN SORTED.SH */ { "apple2", TGT_APPLE2 }, { "apple2enh", TGT_APPLE2ENH }, { "atari", TGT_ATARI }, @@ -181,6 +182,7 @@ static const TargetEntry TargetMap[] = { { "sym1", TGT_SYM1 }, { "telestrat", TGT_TELESTRAT }, { "vic20", TGT_VIC20 }, +/* END SORTED.SH */ }; #define MAP_ENTRY_COUNT (sizeof (TargetMap) / sizeof (TargetMap[0])) diff --git a/src/dbginfo/dbginfo.c b/src/dbginfo/dbginfo.c index 4fe7a37ec..896043cb6 100644 --- a/src/dbginfo/dbginfo.c +++ b/src/dbginfo/dbginfo.c @@ -2531,6 +2531,7 @@ static void NextToken (InputData* D) const char Keyword[12]; Token Tok; } KeywordTable[] = { +/* BEGIN SORTED.SH */ { "abs", TOK_ABSOLUTE }, { "addrsize", TOK_ADDRSIZE }, { "auto", TOK_AUTO }, @@ -2579,6 +2580,7 @@ static void NextToken (InputData* D) { "var", TOK_VAR }, { "version", TOK_VERSION }, { "zp", TOK_ZEROPAGE }, +/* END SORTED.SH */ }; diff --git a/src/sp65/convert.c b/src/sp65/convert.c index 71c9d09a6..3ffdbab7d 100644 --- a/src/sp65/convert.c +++ b/src/sp65/convert.c @@ -64,12 +64,14 @@ struct ConverterMapEntry { /* Converter table */ /* CAUTION: table must be alphabetically sorted for bsearch */ static const ConverterMapEntry ConverterMap[] = { +/* BEGIN SORTED.SH */ { "geos-bitmap", GenGeosBitmap }, { "geos-icon", GenGeosIcon }, { "koala", GenKoala }, { "lynx-sprite", GenLynxSprite }, { "raw", GenRaw }, { "vic2-sprite", GenVic2Sprite }, +/* END SORTED.SH */ }; diff --git a/src/sp65/input.c b/src/sp65/input.c index 22cfb1678..ac3aeaf99 100644 --- a/src/sp65/input.c +++ b/src/sp65/input.c @@ -73,9 +73,10 @@ static InputFormatDesc InputFormatTable[ifCount] = { /* CAUTION: table must be alphabetically sorted for bsearch */ static const FileId FormatTable[] = { /* Upper case stuff for obsolete operating systems */ +/* BEGIN SORTED.SH */ { "PCX", ifPCX }, - { "pcx", ifPCX }, +/* END SORTED.SH */ }; diff --git a/src/sp65/output.c b/src/sp65/output.c index 8b569502b..0c8fa59a7 100644 --- a/src/sp65/output.c +++ b/src/sp65/output.c @@ -82,19 +82,20 @@ static OutputFormatDesc OutputFormatTable[ofCount] = { /* CAUTION: table must be alphabetically sorted for bsearch */ static const FileId FormatTable[] = { /* Upper case stuff for obsolete operating systems */ +/* BEGIN SORTED.SH */ { "A", ofAsm }, { "ASM", ofAsm }, { "BIN", ofBin }, { "C", ofC }, { "INC", ofAsm }, { "S", ofAsm }, - { "a", ofAsm }, { "asm", ofAsm }, { "bin", ofBin }, { "c", ofC }, { "inc", ofAsm }, { "s", ofAsm }, +/* END SORTED.SH */ }; diff --git a/src/sp65/palconv.c b/src/sp65/palconv.c index ff5891b99..42adb1b33 100644 --- a/src/sp65/palconv.c +++ b/src/sp65/palconv.c @@ -59,7 +59,9 @@ struct PaletteMapEntry { /* Converter table */ /* CAUTION: table must be alphabetically sorted for bsearch */ static const PaletteMapEntry PaletteMap[] = { +/* BEGIN SORTED.SH */ { "lynx-palette", GenLynxPalette }, +/* END SORTED.SH */ }; From d1def100ddfebe54eb2dd000b4f239646a805dbd Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Mon, 9 Jun 2025 22:28:19 +0200 Subject: [PATCH 28/60] use sort -c --- .github/checks/sorted.sh | 12 +++++------- .github/checks/sorted_codeopt.sh | 31 +++++++++++++++++++------------ .github/checks/sorted_opcodes.sh | 12 +++++------- 3 files changed, 29 insertions(+), 26 deletions(-) diff --git a/.github/checks/sorted.sh b/.github/checks/sorted.sh index 58d82ed67..0a4a90db7 100755 --- a/.github/checks/sorted.sh +++ b/.github/checks/sorted.sh @@ -4,8 +4,9 @@ SCRIPT_PATH=`dirname $0` CHECK_DIR=../../src -SORT_OPT=-u +SORT_OPT="-u -c" +# $1: filename function checkarray_quoted_name { CHECK_FILE="$1" @@ -21,17 +22,14 @@ function checkarray_quoted_name exit -1 fi - LC_COLLATE=C sort $SORT_OPT .a.tmp > .b.tmp - - if cmp --silent -- .a.tmp .b.tmp; then + if `LC_COLLATE=C sort $SORT_OPT .a.tmp`; then echo ""$1" tables OK" else echo "error: "$1" tables are not sorted." - diff -y .a.tmp .b.tmp - rm -rf .a.tmp .b.tmp + rm -rf .a.tmp exit -1 fi - rm -rf .a.tmp .b.tmp + rm -rf .a.tmp } diff --git a/.github/checks/sorted_codeopt.sh b/.github/checks/sorted_codeopt.sh index f15295990..e90e32b4a 100755 --- a/.github/checks/sorted_codeopt.sh +++ b/.github/checks/sorted_codeopt.sh @@ -4,8 +4,9 @@ SCRIPT_PATH=`dirname $0` CHECK_DIR=../../src -SORT_OPT=-u +SORT_OPT="-u -c" +# $1: filename function checkarray { CHECK_FILE="$1" @@ -21,32 +22,38 @@ function checkarray exit -1 fi - LC_COLLATE=C sort $SORT_OPT .a.tmp > .b.tmp - - if cmp --silent -- .a.tmp .b.tmp; then - echo ""$1" decls OK" + if `LC_COLLATE=C sort $SORT_OPT .a.tmp`; then + echo ""$1" decls sorted." else echo "error: "$1" decls are not sorted." - diff -y .a.tmp .b.tmp - rm -rf .a.tmp .b.tmp + rm -rf .a.tmp exit -1 fi START="\\/\\* BEGIN SORTED_CODEOPT.SH \\*\\/" END="\\/\\* END SORTED_CODEOPT.SH \\*\\/" - awk '/'"$START"'/{flag=1; count++; next} /'"$END"'/{flag=0;} flag {print count,"##",$0}' "$CHECK_FILE" | \ - sed -e 's:\(.*##\).*&D\(.*\),.*:\1\2:g' > .a.tmp - if [[ -z $(grep '[^[:space:]]' .a.tmp) ]] ; then + awk '/'"$START"'/{flag=1; count++; next} /'"$END"'/{flag=0;} flag {print count,"##",$0}' "$CHECK_FILE" | \ + sed -e 's:\(.*##\).*&D\(.*\),.*:\1\2:g' > .b.tmp + + if [[ -z $(grep '[^[:space:]]' .b.tmp) ]] ; then echo "error: "$1" table is empty" - rm -rf .a.tmp + rm -rf .a.tmp .b.tmp + exit -1 + fi + + if `LC_COLLATE=C sort $SORT_OPT .b.tmp`; then + echo ""$1" tables sorted." + else + echo "error: "$1" tables are not sorted." + rm -rf .a.tmp .b.tmp exit -1 fi if cmp --silent -- .a.tmp .b.tmp; then echo ""$1" tables OK" else - echo "error: "$1" tables are not sorted." + echo "error: "$1" tables are different." diff -y .a.tmp .b.tmp rm -rf .a.tmp .b.tmp exit -1 diff --git a/.github/checks/sorted_opcodes.sh b/.github/checks/sorted_opcodes.sh index a1f8fcbfa..b18b841c8 100755 --- a/.github/checks/sorted_opcodes.sh +++ b/.github/checks/sorted_opcodes.sh @@ -4,8 +4,9 @@ SCRIPT_PATH=`dirname $0` CHECK_DIR=../../src -SORT_OPT=-u +SORT_OPT="-u -c" +# $1: filename function checkarray_quoted_name { CHECK_FILE="$1" @@ -23,17 +24,14 @@ function checkarray_quoted_name exit -1 fi - LC_COLLATE=C sort $SORT_OPT .a.tmp > .b.tmp - - if cmp --silent -- .a.tmp .b.tmp; then + if `LC_COLLATE=C sort $SORT_OPT .a.tmp`; then echo ""$1" tables OK" else echo "error: "$1" tables are not sorted." - diff -y .a.tmp .b.tmp - rm -rf .a.tmp .b.tmp + rm -rf .a.tmp exit -1 fi - rm -rf .a.tmp .b.tmp + rm -rf .a.tmp } for N in `grep -rl "BEGIN SORTED_OPCODES.SH" "$CHECK_DIR"`; do From 51da666210db583b18aea8d325a83ba102cae056 Mon Sep 17 00:00:00 2001 From: Gorilla Sapiens <embracetheape@gmail.com> Date: Wed, 11 Jun 2025 02:21:39 +0000 Subject: [PATCH 29/60] fixes #2608 --- src/cc65/pragma.c | 7 +------ test/val/bug2151.c | 5 +++-- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/cc65/pragma.c b/src/cc65/pragma.c index ee71b42d8..b7384e2f1 100644 --- a/src/cc65/pragma.c +++ b/src/cc65/pragma.c @@ -433,12 +433,7 @@ static void ApplySegNamePragma (pragma_t Token, int PushPop, const char* Name, u SetSegAddrSize (Name, AddrSize); } - /* BSS variables are output at the end of the compilation. Don't - ** bother to change their segment, now. - */ - if (Seg != SEG_BSS) { - g_segname (Seg); - } + g_segname (Seg); } diff --git a/test/val/bug2151.c b/test/val/bug2151.c index 25f145506..1277961ef 100644 --- a/test/val/bug2151.c +++ b/test/val/bug2151.c @@ -47,10 +47,11 @@ _Pragma _Pragma ( #pragma bss-name("BSS") { extern int y; -#pragma bss-name("BSS2") +#pragma bss-name("BSS") // used to be BSS2, but fix for #2608 means + // that now causes ld65 to fail, so we use BSS instead static #pragma zpsym ("y") - int x; // TODO: currently in "BSS", but supposed to be in "BSS2"? + int x; x = 0; if (memcmp(str, "aBC", 3)) From ccdc5b9fea5840ee233e371ec26f5146e4606a19 Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Wed, 11 Jun 2025 20:50:04 +0200 Subject: [PATCH 30/60] massaged repro case from #2608 into a test --- test/todo/bug2608.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 test/todo/bug2608.c diff --git a/test/todo/bug2608.c b/test/todo/bug2608.c new file mode 100644 index 000000000..c0685d28c --- /dev/null +++ b/test/todo/bug2608.c @@ -0,0 +1,40 @@ + +/* bug #2608: "zp_bss" is placed in BSS and NOT placed in ZEROPAGE as expected. */ + +#include <stdlib.h> +#include <stdio.h> + +int err = 0; + +int is_zeropage(void *p) +{ + if (/*(p >= ((void*)0)) &&*/ + (p <= ((void*)0xff))) { + return 1; + } + return 0; +} + +void foo(void) { +#pragma bss-name(push,"ZEROPAGE") +#pragma data-name(push,"ZEROPAGE") + static int zp_data = 5; + static char zp_bss; +#pragma bss-name(pop) +#pragma data-name(pop) + printf("zp_data at 0x%04x (%szp)\n", &zp_data, is_zeropage(&zp_data) ? "" : "NOT "); + printf("zp_bss at 0x%04x (%szp)\n", &zp_bss, is_zeropage(&zp_bss) ? "" : "NOT "); + if (!is_zeropage(&zp_data)) { + err++; + } + if (!is_zeropage(&zp_bss)) { + err++; + } +} + +int main(void) +{ + foo(); + printf("errors: %d\n", err); + return err; +} From 3b79c92f394cf84e21d4e29dbbca8340c83c0adf Mon Sep 17 00:00:00 2001 From: Bob Andrews <mrdudz@users.noreply.github.com> Date: Wed, 11 Jun 2025 21:06:58 +0200 Subject: [PATCH 31/60] Update pragma.c just retrigger the checks From cd769b3a9f077e5a9bd8c4be78a1fa4def94bc5f Mon Sep 17 00:00:00 2001 From: Bob Andrews <mrdudz@users.noreply.github.com> Date: Thu, 12 Jun 2025 00:32:09 +0200 Subject: [PATCH 32/60] Update cbm264.h - TGI_COLOR defines should be indices into the default palette --- include/cbm264.h | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/include/cbm264.h b/include/cbm264.h index e017a7bf3..82ecdc4d8 100644 --- a/include/cbm264.h +++ b/include/cbm264.h @@ -110,24 +110,25 @@ #define COLOR_LIGHTBLUE (BCOLOR_LIGHTBLUE | CATTR_LUMA7) #define COLOR_GRAY3 (BCOLOR_WHITE | CATTR_LUMA5) -/* TGI color defines */ -#define TGI_COLOR_BLACK COLOR_BLACK -#define TGI_COLOR_WHITE COLOR_WHITE -#define TGI_COLOR_RED COLOR_RED -#define TGI_COLOR_CYAN COLOR_CYAN -#define TGI_COLOR_VIOLET COLOR_VIOLET -#define TGI_COLOR_PURPLE COLOR_PURPLE -#define TGI_COLOR_GREEN COLOR_GREEN -#define TGI_COLOR_BLUE COLOR_BLUE -#define TGI_COLOR_YELLOW COLOR_YELLOW -#define TGI_COLOR_ORANGE COLOR_ORANGE -#define TGI_COLOR_BROWN COLOR_BROWN -#define TGI_COLOR_LIGHTRED COLOR_LIGHTRED -#define TGI_COLOR_GRAY1 COLOR_GRAY1 -#define TGI_COLOR_GRAY2 COLOR_GRAY2 -#define TGI_COLOR_LIGHTGREEN COLOR_LIGHTGREEN -#define TGI_COLOR_LIGHTBLUE COLOR_LIGHTBLUE -#define TGI_COLOR_GRAY3 COLOR_GRAY3 +/* TGI color defines (these are indices into the default palette) */ +#define TGI_COLOR_BLACK 0 +#define TGI_COLOR_WHITE 1 +/* +#define TGI_COLOR_RED 2 +#define TGI_COLOR_CYAN 3 +#define TGI_COLOR_PURPLE 4 +#define TGI_COLOR_GREEN 5 +#define TGI_COLOR_BLUE 6 +#define TGI_COLOR_YELLOW 7 +#define TGI_COLOR_ORANGE 8 +#define TGI_COLOR_BROWN 9 +#define TGI_COLOR_LIGHTRED 10 +#define TGI_COLOR_GRAY1 11 +#define TGI_COLOR_GRAY2 12 +#define TGI_COLOR_LIGHTGREEN 13 +#define TGI_COLOR_LIGHTBLUE 14 +#define TGI_COLOR_GRAY3 15 +*/ /* Masks for joy_read */ #define JOY_UP_MASK 0x01 From 1c71d4c609c7f650ad3a3524b2afc132d8e0f7fa Mon Sep 17 00:00:00 2001 From: Bob Andrews <mrdudz@users.noreply.github.com> Date: Thu, 12 Jun 2025 00:35:29 +0200 Subject: [PATCH 33/60] Update tgidemo.c TGI color defines should be indices into the default palette --- samples/tgidemo.c | 44 +++++++++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/samples/tgidemo.c b/samples/tgidemo.c index 8a7ce2bfb..d6ae545dc 100644 --- a/samples/tgidemo.c +++ b/samples/tgidemo.c @@ -12,8 +12,11 @@ # define DYN_DRV 1 #endif -#define COLOR_BACK 0 -#define COLOR_FORE 1 + +/* TGI colors are indices into the default palette. So keep in mind that, if + you redefine the palette, those names may no more match the actual colors. */ +#define COLOR_BACK TGI_COLOR_BLACK +#define COLOR_FORE TGI_COLOR_WHITE /*****************************************************************************/ @@ -65,17 +68,36 @@ static void DoWarning (void) #endif +/* + * Note that everywhere else in the TGI API, colors are referred to via TGI_COLOR_ + * color indices, which in turn refer to the default TGI palette. + * + * Redefining the colors (changing the palette) is a target dependend operation, + * and the colors/values in the palette itself are not portable. + * + * That said, for some (perhaps most?) targets, the COLOR_ values may work here. + */ +static void DoPalette (int n) +{ + static const unsigned char Palette[4][2] = { +/* FIXME: add some ifdefs with proper values for targets that need it */ + { COLOR_BLACK, COLOR_BLUE }, + { COLOR_WHITE, COLOR_BLACK }, + { COLOR_RED, COLOR_BLACK }, + { COLOR_BLACK, COLOR_BLACK } + }; + tgi_setpalette (Palette[n]); +} + static void DoCircles (void) { - static const unsigned char Palette[2] = { TGI_COLOR_WHITE, TGI_COLOR_BLUE }; unsigned char I; unsigned char Color = COLOR_BACK; const unsigned X = MaxX / 2; const unsigned Y = MaxY / 2; const unsigned Limit = (X < Y) ? Y : X; - tgi_setpalette (Palette); tgi_setcolor (COLOR_FORE); tgi_clear (); tgi_line (0, 0, MaxX, MaxY); @@ -95,11 +117,9 @@ static void DoCircles (void) static void DoCheckerboard (void) { - static const unsigned char Palette[2] = { TGI_COLOR_WHITE, TGI_COLOR_BLACK }; unsigned X, Y; unsigned char Color = COLOR_BACK; - tgi_setpalette (Palette); tgi_clear (); while (1) { @@ -123,13 +143,11 @@ static void DoCheckerboard (void) static void DoDiagram (void) { - static const unsigned char Palette[2] = { TGI_COLOR_WHITE, TGI_COLOR_BLACK }; int XOrigin, YOrigin; int Amp; int X, Y; unsigned I; - tgi_setpalette (Palette); tgi_setcolor (COLOR_FORE); tgi_clear (); @@ -167,11 +185,9 @@ static void DoDiagram (void) static void DoLines (void) { - static const unsigned char Palette[2] = { TGI_COLOR_WHITE, TGI_COLOR_BLACK }; unsigned X; const unsigned Min = (MaxX < MaxY) ? MaxX : MaxY; - tgi_setpalette (Palette); tgi_setcolor (COLOR_FORE); tgi_clear (); @@ -216,10 +232,12 @@ int main (void) Border = bordercolor (COLOR_BLACK); /* Do graphics stuff */ + + /* first uses the default palette */ DoCircles (); - DoCheckerboard (); - DoDiagram (); - DoLines (); + DoPalette (0); DoCheckerboard (); + DoPalette (1); DoDiagram (); + DoPalette (2); DoLines (); #if DYN_DRV /* Unload the driver */ From 2f16defd6fed0dfa0fd00671ed30e26508897600 Mon Sep 17 00:00:00 2001 From: Bob Andrews <mrdudz@users.noreply.github.com> Date: Thu, 12 Jun 2025 00:45:17 +0200 Subject: [PATCH 34/60] Update tgidemo.c - apple2 fix --- samples/tgidemo.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/samples/tgidemo.c b/samples/tgidemo.c index d6ae545dc..9fa81fa82 100644 --- a/samples/tgidemo.c +++ b/samples/tgidemo.c @@ -81,15 +81,23 @@ static void DoPalette (int n) { static const unsigned char Palette[4][2] = { /* FIXME: add some ifdefs with proper values for targets that need it */ +#if !defined(__APPLE2__) { COLOR_BLACK, COLOR_BLUE }, { COLOR_WHITE, COLOR_BLACK }, { COLOR_RED, COLOR_BLACK }, { COLOR_BLACK, COLOR_BLACK } +#else + { COLOR_WHITE, COLOR_BLACK }, + { COLOR_BLACK, COLOR_BLACK }, + { COLOR_WHITE, COLOR_BLACK }, + { COLOR_BLACK, COLOR_BLACK } +#endif }; tgi_setpalette (Palette[n]); } + static void DoCircles (void) { unsigned char I; From c3defc1b1c48b2f8db7719aa30e7bc7c9136e7cd Mon Sep 17 00:00:00 2001 From: Bob Andrews <mrdudz@users.noreply.github.com> Date: Thu, 12 Jun 2025 01:00:17 +0200 Subject: [PATCH 35/60] Update tgidemo.c - i really like BLACK but that was a bit much :) --- samples/tgidemo.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/samples/tgidemo.c b/samples/tgidemo.c index 9fa81fa82..132697182 100644 --- a/samples/tgidemo.c +++ b/samples/tgidemo.c @@ -85,12 +85,12 @@ static void DoPalette (int n) { COLOR_BLACK, COLOR_BLUE }, { COLOR_WHITE, COLOR_BLACK }, { COLOR_RED, COLOR_BLACK }, - { COLOR_BLACK, COLOR_BLACK } + { COLOR_BLACK, COLOR_WHITE } #else { COLOR_WHITE, COLOR_BLACK }, - { COLOR_BLACK, COLOR_BLACK }, + { COLOR_BLACK, COLOR_WHITE }, { COLOR_WHITE, COLOR_BLACK }, - { COLOR_BLACK, COLOR_BLACK } + { COLOR_BLACK, COLOR_WHITE } #endif }; tgi_setpalette (Palette[n]); From 880322a5ae936c868398bd4233866b2fcbb5f436 Mon Sep 17 00:00:00 2001 From: Gorilla Sapiens <embracetheape@gmail.com> Date: Thu, 12 Jun 2025 06:06:52 +0000 Subject: [PATCH 36/60] renamed test as requested. --- test/{todo => val}/bug2608.c | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test/{todo => val}/bug2608.c (100%) diff --git a/test/todo/bug2608.c b/test/val/bug2608.c similarity index 100% rename from test/todo/bug2608.c rename to test/val/bug2608.c From ace81bd36a5c6df0880a2722a1fe34112ce1e1e7 Mon Sep 17 00:00:00 2001 From: Kugel Fuhr <98353208+kugelfuhr@users.noreply.github.com> Date: Thu, 12 Jun 2025 14:42:38 +0200 Subject: [PATCH 37/60] Add macros to check for CPU type and supported instruction set. --- doc/cc65.sgml | 90 +++++++++++++++++++++++++++++++++++++++++++++++++ src/cc65/main.c | 84 +++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 172 insertions(+), 2 deletions(-) diff --git a/doc/cc65.sgml b/doc/cc65.sgml index 6793603d5..55b84ed5c 100644 --- a/doc/cc65.sgml +++ b/doc/cc65.sgml @@ -1154,6 +1154,96 @@ The compiler defines several macros at startup: <item><tt/__CC65_STD_CC65__/ </itemize> + <label id="macro-CPU"> + <tag><tt>__CPU__</tt></tag> + + This macro contains a bitset that allows to check if a specific instruction + set is supported. For example, the 65C02 CPU supports all instructions of the + 65SC02. So testing for the instruction set of the 65SC02 using the following + check will succeed for both CPUs (and also for the 65816 and HUC6280). + + <tscreen><verb> + #if (__CPU__ & __CPU_ISET_65SC02__) + </verb></tscreen> + + This is much simpler and more future proof than checking for specific CPUs. + + The compiler defines a set of constants named <tt/__CPU_ISET_xxx/ to do the + checks. The <tt/__CPU__/ variable is usually derived from the target system + given, but can be changed using the <tt/<ref id="option--cpu" name="--cpu">/ + command line option. + + <tag><tt>__CPU_6502__</tt></tag> + + This macro is defined if the code is compiled for a 6502 CPU. + + <tag><tt>__CPU_6502X__</tt></tag> + + This macro is defined if the code is compiled for a 6502 CPU with invalid + opcodes. + + <tag><tt>__CPU_6502DTV__</tt></tag> + + This macro is defined if the code is compiled for a DTV CPU. + + <tag><tt>__CPU_65SC02__</tt></tag> + + This macro is defined if the code is compiled for a 65SC02 CPU. + + <tag><tt>__CPU_65C02__</tt></tag> + + This macro is defined if the code is compiled for a 65C02 CPU. + + <tag><tt>__CPU_65816__</tt></tag> + + This macro is defined if the code is compiled for a 65816 CPU. + + <tag><tt>__CPU_HUC6280__</tt></tag> + + This macro is defined if the code is compiled for a HUC6280 CPU. + + <tag><tt>__CPU_ISET_6502__</tt></tag> + + This macro expands to a numeric constant that can be used to check the + <tt/<ref id="macro-CPU" name="__CPU__">/ macro for the instruction set + of the 6502 CPU. + + <tag><tt>__CPU_ISET_6502X__</tt></tag> + + This macro expands to a numeric constant that can be used to check the + <tt/<ref id="macro-CPU" name="__CPU__">/ macro for the instruction set + of the 6502X CPU. + + <tag><tt>__CPU_ISET_6502DTV__</tt></tag> + + This macro expands to a numeric constant that can be used to check the + <tt/<ref id="macro-CPU" name="__CPU__">/ macro for the instruction set + of the 6502DTV CPU. + + <tag><tt>__CPU_ISET_65SC02__</tt></tag> + + This macro expands to a numeric constant that can be used to check the + <tt/<ref id="macro-CPU" name="__CPU__">/ macro for the instruction set + of the 65SC02 CPU. + + <tag><tt>__CPU_ISET_65C02__</tt></tag> + + This macro expands to a numeric constant that can be used to check the + <tt/<ref id="macro-CPU" name="__CPU__">/ macro for the instruction set + of the 65C02 CPU. + + <tag><tt>__CPU_ISET_65816__</tt></tag> + + This macro expands to a numeric constant that can be used to check the + <tt/<ref id="macro-CPU" name="__CPU__">/ macro for the instruction set + of the 65816 CPU. + + <tag><tt>__CPU_ISET_HUC6280__</tt></tag> + + This macro expands to a numeric constant that can be used to check the + <tt/<ref id="macro-CPU" name="__CPU__">/ macro for the instruction set + of the HUC6280 CPU. + <tag><tt>__CX16__</tt></tag> This macro is defined if the target is the Commander X16 (-t cx16). diff --git a/src/cc65/main.c b/src/cc65/main.c index 47435757c..a0c4848c9 100644 --- a/src/cc65/main.c +++ b/src/cc65/main.c @@ -317,6 +317,81 @@ static void SetSys (const char* Sys) +static void DefineCpuMacros (void) +/* Define macros for the target CPU */ +{ + const char* CPUName; + + /* Note: The list of CPUs handled here must match the one checked in + ** OptCPU(). + */ + switch (CPU) { + + /* The following ones are legal CPUs as far as the assembler is + ** concerned but are ruled out earlier in the compiler, so this + ** function should never see them. + */ + case CPU_NONE: + case CPU_SWEET16: + case CPU_M740: + case CPU_4510: + case CPU_UNKNOWN: + CPUName = (CPU == CPU_UNKNOWN)? "unknown" : CPUNames[CPU]; + Internal ("Invalid CPU \"%s\"", CPUName); + break; + + case CPU_6502: + DefineNumericMacro ("__CPU_6502__", 1); + break; + + case CPU_6502X: + DefineNumericMacro ("__CPU_6502X__", 1); + break; + + case CPU_6502DTV: + DefineNumericMacro ("__CPU_6502DTV__", 1); + break; + + case CPU_65SC02: + DefineNumericMacro ("__CPU_65SC02__", 1); + break; + + case CPU_65C02: + DefineNumericMacro ("__CPU_65C02__", 1); + break; + + case CPU_65816: + DefineNumericMacro ("__CPU_65816__", 1); + break; + + case CPU_HUC6280: + DefineNumericMacro ("__CPU_HUC6280__", 1); + break; + + default: + FAIL ("Unexpected value in switch"); + break; + } + + /* Define the macros for instruction sets. We only include the ones for + ** the available CPUs. + */ + DefineNumericMacro ("__CPU_ISET_6502__", CPU_ISET_6502); + DefineNumericMacro ("__CPU_ISET_6502X__", CPU_ISET_6502X); + DefineNumericMacro ("__CPU_ISET_6502DTV__", CPU_ISET_6502DTV); + DefineNumericMacro ("__CPU_ISET_65SC02__", CPU_ISET_65SC02); + DefineNumericMacro ("__CPU_ISET_65C02__", CPU_ISET_65C02); + DefineNumericMacro ("__CPU_ISET_65816__", CPU_ISET_65816); + DefineNumericMacro ("__CPU_ISET_HUC6280__", CPU_ISET_HUC6280); + + /* Now define the macro that contains the bit set with the available + ** cpu instructions. + */ + DefineNumericMacro ("__CPU__", CPUIsets[CPU]); +} + + + static void FileNameOption (const char* Opt, const char* Arg, StrBuf* Name) /* Handle an option that remembers a file name for later */ { @@ -477,7 +552,9 @@ static void OptCreateFullDep (const char* Opt attribute ((unused)), static void OptCPU (const char* Opt, const char* Arg) /* Handle the --cpu option */ { - /* Find the CPU from the given name */ + /* Find the CPU from the given name. We do only accept a certain number + ** of CPUs. If the list is changed, be sure to adjust SetCpuMacros(). + */ CPU = FindCPU (Arg); if (CPU != CPU_6502 && CPU != CPU_6502X && CPU != CPU_65SC02 && CPU != CPU_65C02 && CPU != CPU_65816 && CPU != CPU_HUC6280 && @@ -1063,7 +1140,9 @@ int main (int argc, char* argv[]) /* Create the output file name if it was not explicitly given */ MakeDefaultOutputName (InputFile); - /* If no CPU given, use the default CPU for the target */ + /* If no CPU given, use the default CPU for the target. Define macros that + ** allow to query the CPU. + */ if (CPU == CPU_UNKNOWN) { if (Target != TGT_UNKNOWN) { CPU = GetTargetProperties (Target)->DefaultCPU; @@ -1071,6 +1150,7 @@ int main (int argc, char* argv[]) CPU = CPU_6502; } } + DefineCpuMacros (); /* If no memory model was given, use the default */ if (MemoryModel == MMODEL_UNKNOWN) { From ffd667c2c9d20682b5c4ebb41d2a5102ee9b727c Mon Sep 17 00:00:00 2001 From: Colin Leroy-Mira <colin@colino.net> Date: Tue, 10 Jun 2025 19:40:18 +0200 Subject: [PATCH 38/60] Fix temporary file name creation. Use the original name as template for readability in the map file, and use the process PID instead of platform-dependant or deprecated random filename functions to make unique temporary filenames. Also, create these temporary files in the output directory. --- src/cl65/main.c | 15 ++++++++--- src/common/fname.c | 65 +++++++++++++++++++++++++++++----------------- src/common/fname.h | 10 ++++--- 3 files changed, 60 insertions(+), 30 deletions(-) diff --git a/src/cl65/main.c b/src/cl65/main.c index 42126e6d7..528e64e56 100644 --- a/src/cl65/main.c +++ b/src/cl65/main.c @@ -122,6 +122,11 @@ static int DoAssemble = 1; /* The name of the output file, NULL if none given */ static const char* OutputName = 0; +/* The path part of the output file, NULL if none given +** or the OutputName is just a filename with no path +** information. */ +static char *OutputDirectory = 0; + /* The name of the linker configuration file if given */ static const char* LinkerConfig = 0; @@ -555,7 +560,7 @@ static void AssembleFile (const char* File, const char* TmpFile, unsigned ArgCou if (TmpFile) { ObjName = MakeFilename (TmpFile, ".o"); } else { - ObjName = MakeTmpFilename (".o"); + ObjName = MakeTmpFilename (OutputDirectory, File, ".o"); } CmdSetOutput (&CA65, ObjName); CmdAddFile (&LD65, ObjName); @@ -684,7 +689,7 @@ static void Compile (const char* File) if (DoAssemble) { /* set a temporary output file name */ - TmpFile = MakeTmpFilename(".s"); + TmpFile = MakeTmpFilename(OutputDirectory, File, ".s"); CmdSetOutput (&CC65, TmpFile); } @@ -729,7 +734,7 @@ static void CompileRes (const char* File) ** BEFORE adding the file */ if (DoAssemble && DoLink) { - AsmName = MakeTmpFilename(".s"); + AsmName = MakeTmpFilename(OutputDirectory, File, ".s"); CmdSetAsmOutput(&GRC, AsmName); } @@ -1623,6 +1628,7 @@ int main (int argc, char* argv []) case 'o': /* Name the output file */ OutputName = GetArg (&I, 2); + OutputDirectory = GetFileDirectory(OutputName); break; case 'r': @@ -1713,6 +1719,9 @@ int main (int argc, char* argv []) } RemoveTempFiles (); + if (OutputDirectory != NULL) { + xfree(OutputDirectory); + } /* Return an apropriate exit code */ return EXIT_SUCCESS; diff --git a/src/common/fname.c b/src/common/fname.c index e67470b33..d835ee7a0 100644 --- a/src/common/fname.c +++ b/src/common/fname.c @@ -33,8 +33,17 @@ +#include <errno.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> +#include <time.h> + +#if defined(_MSC_VER) +# include <process.h> +#else +# include <unistd.h> +#endif #include "xmalloc.h" #include "fname.h" @@ -93,7 +102,28 @@ const char* FindName (const char* Path) return Path + Len; } +char *GetFileDirectory (const char* File) +/* Return a copy of the path part of a File, or NULL if there is none. */ +{ + char *Out, *P; + if (File == NULL) { + return NULL; + } + + Out = xmalloc (strlen (File) + 1); + strcpy(Out, File); + + P = (char *)FindName (Out); + if (P == Out) { + /* This is a simple filename. */ + xfree (Out); + return NULL; + } + *P = '\0'; + + return Out; +} char* MakeFilename (const char* Origin, const char* Ext) /* Make a new file name from Origin and Ext. If Origin has an extension, it @@ -119,35 +149,22 @@ char* MakeFilename (const char* Origin, const char* Ext) -char* MakeTmpFilename (const char* Ext) -/* Make a new temporary file name from Ext. tmpnam(3) is called -** and Ext is appended to generate the filename. +char* MakeTmpFilename (const char *Directory, const char *Origin, const char* Ext) +/* Make a new temporary file name from Origin and Ext. ** The result is placed in a malloc'ed buffer and returned. */ { char* Out; - char Buffer[L_tmpnam * 2]; /* a lazy way to ensure we have space for Ext */ + size_t Len = 0; - /* - ** gcc emits the following warning here: - ** - ** warning: the use of `tmpnam' is dangerous, better use `mkstemp' - ** - ** however, mkstemp actually opens a file, which we do not want. - ** tmpfile() is unsuitable for the same reason. - ** - ** we could write our own version, but then we would have to struggle - ** with supporting multiple build environments. - ** - ** tmpnam(3) is safe here, because ca65 / cc65 / ld65 will simply clobber - ** an existing file, or exit if with an error if they are unable to. - ** - ** gcc will also complain, if you don't use the return value from tmpnam(3) - */ - strcat(tmpnam(Buffer), Ext); - - Out = xmalloc (strlen (Buffer) + 1); - strcpy (Out, Buffer); + /* Allocate template */ + if (Directory != NULL) { + Len = strlen (Directory); + } + Len += strlen (Origin) + strlen (".2147483648") + strlen (Ext) + 1; + Out = xmalloc (Len); + snprintf (Out, Len, "%s%s.%u%s", (Directory != NULL ? Directory : ""), + FindName(Origin), getpid(), Ext); return Out; } diff --git a/src/common/fname.h b/src/common/fname.h index 852c4ae56..ede34152d 100644 --- a/src/common/fname.h +++ b/src/common/fname.h @@ -52,6 +52,9 @@ const char* FindName (const char* Path); ** the file, the function returns Path as name. */ +char *GetFileDirectory (const char* File); +/* Return a copy of the path part of a File, or NULL if there is none. */ + char* MakeFilename (const char* Origin, const char* Ext); /* Make a new file name from Origin and Ext. If Origin has an extension, it ** is removed and Ext is appended. If Origin has no extension, Ext is simply @@ -59,9 +62,10 @@ char* MakeFilename (const char* Origin, const char* Ext); ** The function may be used to create "foo.o" from "foo.s". */ -char* MakeTmpFilename (const char* Ext); -/* Make a new temporary file name from Ext. tmpnam(3) is called -** and Ext is appended to generate the filename. +char* MakeTmpFilename (const char *Directory, const char *Origin, const char* Ext); +/* Make a new temporary file name from Directory, Origin, and Ext. +** A temporary path is generated from the Directory, +** the Origin filename, the compiler's PID and the Extension. ** The result is placed in a malloc'ed buffer and returned. */ From 149b2b69efc46935a55903bbe225a7b0df84c1a0 Mon Sep 17 00:00:00 2001 From: Colin Leroy-Mira <colin@colino.net> Date: Thu, 12 Jun 2025 19:21:57 +0200 Subject: [PATCH 39/60] Use new CPU macro to optimize ntohs on 65c02 --- include/arpa/inet.h | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/include/arpa/inet.h b/include/arpa/inet.h index cd353a2bb..3d715766f 100644 --- a/include/arpa/inet.h +++ b/include/arpa/inet.h @@ -40,6 +40,20 @@ /*****************************************************************************/ +#if (__CPU__ & __CPU_ISET_65SC02__) +/* Always inline, three bytes is not more than a jsr */ + +#define ntohs(x) \ + ( \ + __AX__=(x), \ + asm("phx"), \ + asm("tax"), \ + asm("pla"), \ + __AX__ \ + ) +#define htons(x) ntohs(x) + +#else #if (__OPT_i__ < 200) int __fastcall__ ntohs (int val); @@ -56,12 +70,12 @@ int __fastcall__ htons (int val); ) #define htons(x) ntohs(x) -#endif +#endif /* __OPT_i__ < 200 */ + +#endif /* __CPU__ & __CPU_ISET_65SC02__ */ long __fastcall__ ntohl (long val); long __fastcall__ htonl (long val); - - /* End of arpa/inet.h */ #endif From 86cf60d0e62da6889e863a1ee90700ef1da6758f Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Thu, 12 Jun 2025 20:53:55 +0200 Subject: [PATCH 40/60] add dbginfo to src/Makefile, add building dbginfo example to CI. Fixes #2681, supersedes #2682 --- .github/workflows/build-on-pull-request.yml | 3 +++ Makefile | 1 + src/Makefile | 5 ++++- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-on-pull-request.yml b/.github/workflows/build-on-pull-request.yml index 7b762844b..9158f7731 100644 --- a/.github/workflows/build-on-pull-request.yml +++ b/.github/workflows/build-on-pull-request.yml @@ -27,6 +27,9 @@ jobs: - name: Build the tools. shell: bash run: make -j2 bin USER_CFLAGS=-Werror + - name: Build the dbginfo example + shell: bash + run: make -j2 src dbginfo - name: Build the utilities. shell: bash run: make -j2 util diff --git a/Makefile b/Makefile index 29fcbbf96..0eb18f94b 100644 --- a/Makefile +++ b/Makefile @@ -50,6 +50,7 @@ test: # GNU "check" target, which runs all tests check: @$(MAKE) -C .github/checks checkstyle --no-print-directory + @$(MAKE) -C src dbginfo --no-print-directory @$(MAKE) test @$(MAKE) -C targettest platforms --no-print-directory @$(MAKE) -C samples platforms --no-print-directory diff --git a/src/Makefile b/src/Makefile index 034a2230f..27724028c 100644 --- a/src/Makefile +++ b/src/Makefile @@ -21,7 +21,7 @@ PROGS = ar65 \ sim65 \ sp65 -.PHONY: all mostlyclean clean install zip avail unavail bin $(PROGS) +.PHONY: all mostlyclean clean install zip avail unavail bin $(PROGS) dbginfo .SUFFIXES: @@ -168,4 +168,7 @@ $(eval $(call OBJS_template,common)) $(foreach prog,$(PROGS),$(eval $(call PROG_template,$(prog)))) +dbginfo: +$(eval $(call PROG_template,dbginfo)) + -include $(DEPS) From b2616eac0dc80d277e99e99cb2b542a84a1799e5 Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Thu, 12 Jun 2025 20:58:36 +0200 Subject: [PATCH 41/60] use -C correctly :) --- .github/workflows/build-on-pull-request.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-on-pull-request.yml b/.github/workflows/build-on-pull-request.yml index 9158f7731..376dc9560 100644 --- a/.github/workflows/build-on-pull-request.yml +++ b/.github/workflows/build-on-pull-request.yml @@ -29,7 +29,7 @@ jobs: run: make -j2 bin USER_CFLAGS=-Werror - name: Build the dbginfo example shell: bash - run: make -j2 src dbginfo + run: make -j2 -C src dbginfo - name: Build the utilities. shell: bash run: make -j2 util From 505160f169859a270675d45850a740c4b17e9adb Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Thu, 12 Jun 2025 21:31:05 +0200 Subject: [PATCH 42/60] a bit cleaner, also build dbgsh --- .github/workflows/build-on-pull-request.yml | 2 +- Makefile | 2 +- src/Makefile | 18 +++++++++++++++--- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build-on-pull-request.yml b/.github/workflows/build-on-pull-request.yml index 376dc9560..8f68b024c 100644 --- a/.github/workflows/build-on-pull-request.yml +++ b/.github/workflows/build-on-pull-request.yml @@ -29,7 +29,7 @@ jobs: run: make -j2 bin USER_CFLAGS=-Werror - name: Build the dbginfo example shell: bash - run: make -j2 -C src dbginfo + run: make -j2 -C src test - name: Build the utilities. shell: bash run: make -j2 util diff --git a/Makefile b/Makefile index 0eb18f94b..9e30d2bb4 100644 --- a/Makefile +++ b/Makefile @@ -50,7 +50,7 @@ test: # GNU "check" target, which runs all tests check: @$(MAKE) -C .github/checks checkstyle --no-print-directory - @$(MAKE) -C src dbginfo --no-print-directory + @$(MAKE) -C src test --no-print-directory @$(MAKE) test @$(MAKE) -C targettest platforms --no-print-directory @$(MAKE) -C samples platforms --no-print-directory diff --git a/src/Makefile b/src/Makefile index 27724028c..c5d91ce5a 100644 --- a/src/Makefile +++ b/src/Makefile @@ -21,7 +21,7 @@ PROGS = ar65 \ sim65 \ sp65 -.PHONY: all mostlyclean clean install zip avail unavail bin $(PROGS) dbginfo +.PHONY: all mostlyclean clean install zip avail unavail bin $(PROGS) .SUFFIXES: @@ -168,7 +168,19 @@ $(eval $(call OBJS_template,common)) $(foreach prog,$(PROGS),$(eval $(call PROG_template,$(prog)))) -dbginfo: -$(eval $(call PROG_template,dbginfo)) + +.PHONY: dbginfo dbgsh test + +test: dbginfo dbgsh + +$(eval $(call OBJS_template,dbginfo)) + +dbginfo: $(dbginfo_OBJS) + +../wrk/dbgsh$(EXE_SUFFIX): $(dbginfo_OBJS) ../wrk/common/common.a + $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS) + +dbgsh: ../wrk/dbgsh$(EXE_SUFFIX) + -include $(DEPS) From a6b94ebba240d9263b2e328a13abc9d800bde660 Mon Sep 17 00:00:00 2001 From: Kugel Fuhr <98353208+kugelfuhr@users.noreply.github.com> Date: Thu, 12 Jun 2025 21:50:20 +0200 Subject: [PATCH 43/60] Implement -dD, -dM and -dN command line switches to output macro definitions. --- doc/cc65.sgml | 23 +++++++++++ src/cc65/compile.c | 11 +++++ src/cc65/global.c | 5 ++- src/cc65/global.h | 5 ++- src/cc65/macrotab.c | 99 ++++++++++++++++++++++++++++++++++++++++++--- src/cc65/macrotab.h | 16 ++++++-- src/cc65/main.c | 31 +++++++++++++- src/cc65/preproc.c | 2 +- 8 files changed, 179 insertions(+), 13 deletions(-) diff --git a/doc/cc65.sgml b/doc/cc65.sgml index 55b84ed5c..b53007e46 100644 --- a/doc/cc65.sgml +++ b/doc/cc65.sgml @@ -63,6 +63,9 @@ Short options: -V Print the compiler version number -W [-+]warning[,...] Control warnings ('-' disables, '+' enables) -d Debug mode + -dD Output all macro definitions (needs -E) + -dM Output user defined macros (needs -E) + -dN Output user defined macro names (needs -E) -g Add debug info to object file -h Help (this text) -j Default characters are signed @@ -199,6 +202,26 @@ Here is a description of all the command line options: Enables debug mode, for debugging the behavior of cc65. + <label id="option-dD"> + <tag><tt>-dD</tt></tag> + + Like <tt/<ref id="option-dM" name="-dM">/ but does not include the predefined + macros. + + + <label id="option-dM"> + <tag><tt>-dM</tt></tag> + + When used with -E, will output <tt>#define</tt> directives for all the macros + defined during execution of the preprocessor, including predefined macros. + + + <tag><tt>-dN</tt></tag> + + Like <tt/<ref id="option-dD" name="-dD">/ but will only output the macro names, + not their definitions. + + <tag><tt>--debug-tables name</tt></tag> Writes symbol table information to a file, which includes details on structs, unions diff --git a/src/cc65/compile.c b/src/cc65/compile.c index e08a829e6..5b9ef1551 100644 --- a/src/cc65/compile.c +++ b/src/cc65/compile.c @@ -496,6 +496,17 @@ void Compile (const char* FileName) while (PreprocessNextLine ()) { /* Nothing */ } + /* Output macros if requested by the user */ + if (DumpAllMacrosFull) { + OutputAllMacrosFull (); + } + if (DumpUserMacros) { + OutputUserMacros (); + } + if (DumpUserMacrosFull) { + OutputUserMacrosFull (); + } + /* Close the output file */ CloseOutputFile (); diff --git a/src/cc65/global.c b/src/cc65/global.c index b2c3ef0a0..6fcc5d9d7 100644 --- a/src/cc65/global.c +++ b/src/cc65/global.c @@ -44,12 +44,15 @@ unsigned char AddSource = 0; /* Add source lines as comments */ +unsigned char AllowNewComments = 0; /* Allow new style comments in C89 mode */ unsigned char AutoCDecl = 0; /* Make functions default to __cdecl__ */ unsigned char DebugInfo = 0; /* Add debug info to the obj */ +unsigned char DumpAllMacrosFull = 0; /* Output all macro defs */ +unsigned char DumpUserMacros = 0; /* Output user macro names */ +unsigned char DumpUserMacrosFull= 0; /* Output user macro defs */ unsigned char PreprocessOnly = 0; /* Just preprocess the input */ unsigned char DebugOptOutput = 0; /* Output debug stuff */ unsigned RegisterSpace = 6; /* Space available for register vars */ -unsigned AllowNewComments = 0; /* Allow new style comments in C89 mode */ /* Stackable options */ IntStack WritableStrings = INTSTACK(0); /* Literal strings are r/w */ diff --git a/src/cc65/global.h b/src/cc65/global.h index ba7105130..d475c73e5 100644 --- a/src/cc65/global.h +++ b/src/cc65/global.h @@ -52,12 +52,15 @@ /* Options */ extern unsigned char AddSource; /* Add source lines as comments */ +extern unsigned char AllowNewComments; /* Allow new style comments in C89 mode */ extern unsigned char AutoCDecl; /* Make functions default to __cdecl__ */ extern unsigned char DebugInfo; /* Add debug info to the obj */ +extern unsigned char DumpAllMacrosFull; /* Output all macro defs */ +extern unsigned char DumpUserMacros; /* Output user macro names */ +extern unsigned char DumpUserMacrosFull; /* Output user macro defs */ extern unsigned char PreprocessOnly; /* Just preprocess the input */ extern unsigned char DebugOptOutput; /* Output debug stuff */ extern unsigned RegisterSpace; /* Space available for register vars */ -extern unsigned AllowNewComments; /* Allow new style comments in C89 mode */ /* Stackable options */ extern IntStack WritableStrings; /* Literal strings are r/w */ diff --git a/src/cc65/macrotab.c b/src/cc65/macrotab.c index 3bfae0811..41345db8a 100644 --- a/src/cc65/macrotab.c +++ b/src/cc65/macrotab.c @@ -1,4 +1,4 @@ -/*****************************************************************************/ + /* */ /* macrotab.h */ /* */ @@ -42,6 +42,7 @@ /* cc65 */ #include "error.h" +#include "output.h" #include "preproc.h" #include "macrotab.h" @@ -60,6 +61,67 @@ static Macro* MacroTab[MACRO_TAB_SIZE]; /* The undefined macros list head */ static Macro* UndefinedMacrosListHead; +/* Some defines for better readability when calling OutputMacros() */ +#define ALL_MACROS 0 +#define USER_MACROS 1 +#define NAME_ONLY 0 +#define FULL_DEFINITION 1 + + + +/*****************************************************************************/ +/* helpers */ +/*****************************************************************************/ + + + +static void OutputMacro (const Macro* M, int Full) +/* Output one macro. If Full is true, the replacement is also output. */ +{ + WriteOutput ("#define %s", M->Name); + int ParamCount = M->ParamCount; + if (M->ParamCount >= 0) { + int I; + if (M->Variadic) { + CHECK (ParamCount > 0); + --ParamCount; + } + WriteOutput ("("); + for (I = 0; I < ParamCount; ++I) { + const char* Name = CollConstAt (&M->Params, I); + WriteOutput ("%s%s", (I == 0)? "" : ",", Name); + } + if (M->Variadic) { + WriteOutput ("%s...", (ParamCount == 0)? "" : ","); + } + WriteOutput (")"); + } + WriteOutput (" "); + if (Full) { + WriteOutput ("%.*s", + SB_GetLen (&M->Replacement), + SB_GetConstBuf (&M->Replacement)); + } + WriteOutput ("\n"); +} + + + +static void OutputMacros (int UserOnly, int Full) +/* Output macros to the output file depending on the flags given */ +{ + unsigned I; + for (I = 0; I < MACRO_TAB_SIZE; ++I) { + const Macro* M = MacroTab [I]; + while (M) { + if (!UserOnly || !M->Predefined) { + OutputMacro (M, Full); + } + M = M->Next; + } + } +} + /*****************************************************************************/ @@ -68,7 +130,7 @@ static Macro* UndefinedMacrosListHead; -Macro* NewMacro (const char* Name) +Macro* NewMacro (const char* Name, unsigned char Predefined) /* Allocate a macro structure with the given name. The structure is not ** inserted into the macro table. */ @@ -84,6 +146,7 @@ Macro* NewMacro (const char* Name) M->ParamCount = -1; /* Flag: Not a function-like macro */ InitCollection (&M->Params); SB_Init (&M->Replacement); + M->Predefined = Predefined; M->Variadic = 0; memcpy (M->Name, Name, Len+1); @@ -116,7 +179,7 @@ Macro* CloneMacro (const Macro* M) ** Use FreeMacro for that. */ { - Macro* New = NewMacro (M->Name); + Macro* New = NewMacro (M->Name, M->Predefined); unsigned I; for (I = 0; I < CollCount (&M->Params); ++I) { @@ -134,7 +197,7 @@ Macro* CloneMacro (const Macro* M) void DefineNumericMacro (const char* Name, long Val) -/* Define a macro for a numeric constant */ +/* Define a predefined macro for a numeric constant */ { char Buf[64]; @@ -148,10 +211,10 @@ void DefineNumericMacro (const char* Name, long Val) void DefineTextMacro (const char* Name, const char* Val) -/* Define a macro for a textual constant */ +/* Define a predefined macro for a textual constant */ { /* Create a new macro */ - Macro* M = NewMacro (Name); + Macro* M = NewMacro (Name, 1); /* Set the value as replacement text */ SB_CopyStr (&M->Replacement, Val); @@ -350,3 +413,27 @@ void PrintMacroStats (FILE* F) } } } + + + +void OutputAllMacrosFull (void) +/* Output all macros to the output file */ +{ + OutputMacros (ALL_MACROS, FULL_DEFINITION); +} + + + +void OutputUserMacros (void) +/* Output the names of all user defined macros to the output file */ +{ + OutputMacros (USER_MACROS, NAME_ONLY); +} + + + +void OutputUserMacrosFull (void) +/* Output all user defined macros to the output file */ +{ + OutputMacros (USER_MACROS, FULL_DEFINITION); +} diff --git a/src/cc65/macrotab.h b/src/cc65/macrotab.h index 52b812b2f..8d2a04755 100644 --- a/src/cc65/macrotab.h +++ b/src/cc65/macrotab.h @@ -58,6 +58,7 @@ struct Macro { int ParamCount; /* Number of parameters, -1 = no parens */ Collection Params; /* Parameter list (char*) */ StrBuf Replacement; /* Replacement text */ + unsigned char Predefined; /* True if this is a predefined macro */ unsigned char Variadic; /* C99 variadic macro */ char Name[1]; /* Name, dynamically allocated */ }; @@ -70,7 +71,7 @@ struct Macro { -Macro* NewMacro (const char* Name); +Macro* NewMacro (const char* Name, unsigned char Predefined); /* Allocate a macro structure with the given name. The structure is not ** inserted into the macro table. */ @@ -87,10 +88,10 @@ Macro* CloneMacro (const Macro* M); */ void DefineNumericMacro (const char* Name, long Val); -/* Define a macro for a numeric constant */ +/* Define a predefined macro for a numeric constant */ void DefineTextMacro (const char* Name, const char* Val); -/* Define a macro for a textual constant */ +/* Define a predefined macro for a textual constant */ void InsertMacro (Macro* M); /* Insert the given macro into the macro table. */ @@ -132,6 +133,15 @@ int MacroCmp (const Macro* M1, const Macro* M2); void PrintMacroStats (FILE* F); /* Print macro statistics to the given text file. */ +void OutputAllMacrosFull (void); +/* Output all macros to the output file */ + +void OutputUserMacros (void); +/* Output the names of all user defined macros to the output file */ + +void OutputUserMacrosFull (void); +/* Output all user defined macros to the output file */ + /* End of macrotab.h */ diff --git a/src/cc65/main.c b/src/cc65/main.c index a0c4848c9..72a7ebd82 100644 --- a/src/cc65/main.c +++ b/src/cc65/main.c @@ -93,6 +93,9 @@ static void Usage (void) " -V\t\t\t\tPrint the compiler version number\n" " -W [-+]warning[,...]\t\tControl warnings ('-' disables, '+' enables)\n" " -d\t\t\t\tDebug mode\n" + " -dD\t\t\t\tOutput all macro definitions (needs -E)\n" + " -dM\t\t\t\tOutput user defined macros (needs -E)\n" + " -dN\t\t\t\tOutput user defined macro names (needs -E)\n" " -g\t\t\t\tAdd debug info to object file\n" " -h\t\t\t\tHelp (this text)\n" " -j\t\t\t\tDefault characters are signed\n" @@ -1022,7 +1025,26 @@ int main (int argc, char* argv[]) break; case 'd': - OptDebug (Arg, 0); + switch (Arg[2]) { + case '\0': + OptDebug (Arg, 0); + break; + case 'D': + DumpUserMacrosFull = 1; + break; + case 'M': + DumpAllMacrosFull = 1; + break; + case 'N': + DumpUserMacros = 1; + break; + default: + UnknownOption (Arg); + break; + } + if (Arg[2] && Arg[3]) { + UnknownOption (Arg); + } break; case 'h': @@ -1134,6 +1156,13 @@ int main (int argc, char* argv[]) AbEnd ("No input files"); } + /* The options to output macros can only be used with -E */ + if (DumpAllMacrosFull || DumpUserMacros || DumpUserMacrosFull) { + if (!PreprocessOnly) { + AbEnd ("Preprocessor macro output can only be used together with -E"); + } + } + /* Add the default include search paths. */ FinishIncludePaths (); diff --git a/src/cc65/preproc.c b/src/cc65/preproc.c index d70c28147..feba933cf 100644 --- a/src/cc65/preproc.c +++ b/src/cc65/preproc.c @@ -2573,7 +2573,7 @@ static void DoDefine (void) CheckForBadIdent (Ident, Std, 0); /* Create a new macro definition */ - M = NewMacro (Ident); + M = NewMacro (Ident, 0); /* Check if this is a function-like macro */ if (CurC == '(') { From 40aced6d6d5331072986c9ae6f9a583909a32b44 Mon Sep 17 00:00:00 2001 From: Kugel Fuhr <98353208+kugelfuhr@users.noreply.github.com> Date: Thu, 12 Jun 2025 22:02:35 +0200 Subject: [PATCH 44/60] Command line switches -dD and -Dm were swapped in the usage information. --- doc/cc65.sgml | 8 ++++---- src/cc65/main.c | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/cc65.sgml b/doc/cc65.sgml index b53007e46..368d3269c 100644 --- a/doc/cc65.sgml +++ b/doc/cc65.sgml @@ -63,8 +63,8 @@ Short options: -V Print the compiler version number -W [-+]warning[,...] Control warnings ('-' disables, '+' enables) -d Debug mode - -dD Output all macro definitions (needs -E) - -dM Output user defined macros (needs -E) + -dD Output user defined macros (needs -E) + -dM Output all macro definitions (needs -E) -dN Output user defined macro names (needs -E) -g Add debug info to object file -h Help (this text) @@ -200,13 +200,13 @@ Here is a description of all the command line options: <tag><tt>-d, --debug</tt></tag> Enables debug mode, for debugging the behavior of cc65. - + <label id="option-dD"> <tag><tt>-dD</tt></tag> Like <tt/<ref id="option-dM" name="-dM">/ but does not include the predefined - macros. + macros. <label id="option-dM"> diff --git a/src/cc65/main.c b/src/cc65/main.c index 72a7ebd82..4ff17ada9 100644 --- a/src/cc65/main.c +++ b/src/cc65/main.c @@ -93,8 +93,8 @@ static void Usage (void) " -V\t\t\t\tPrint the compiler version number\n" " -W [-+]warning[,...]\t\tControl warnings ('-' disables, '+' enables)\n" " -d\t\t\t\tDebug mode\n" - " -dD\t\t\t\tOutput all macro definitions (needs -E)\n" - " -dM\t\t\t\tOutput user defined macros (needs -E)\n" + " -dD\t\t\t\tOutput user defined macros (needs -E)\n" + " -dM\t\t\t\tOutput all macro definitions (needs -E)\n" " -dN\t\t\t\tOutput user defined macro names (needs -E)\n" " -g\t\t\t\tAdd debug info to object file\n" " -h\t\t\t\tHelp (this text)\n" From b7a5ec86c53fbf4d360541d862dfd207cc003025 Mon Sep 17 00:00:00 2001 From: Kugel Fuhr <98353208+kugelfuhr@users.noreply.github.com> Date: Thu, 12 Jun 2025 22:09:53 +0200 Subject: [PATCH 45/60] Remove trailing spaces. --- doc/cc65.sgml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/cc65.sgml b/doc/cc65.sgml index 368d3269c..a78f1a00a 100644 --- a/doc/cc65.sgml +++ b/doc/cc65.sgml @@ -200,13 +200,13 @@ Here is a description of all the command line options: <tag><tt>-d, --debug</tt></tag> Enables debug mode, for debugging the behavior of cc65. - + <label id="option-dD"> <tag><tt>-dD</tt></tag> Like <tt/<ref id="option-dM" name="-dM">/ but does not include the predefined - macros. + macros. <label id="option-dM"> From c28bafa581b6f3b498b9f02868955bee8b4b7723 Mon Sep 17 00:00:00 2001 From: Konstantin <sintechs@gmail.com> Date: Fri, 13 Jun 2025 12:50:39 +0300 Subject: [PATCH 46/60] add chline, cvline functions --- include/agat.h | 9 +++++++-- libsrc/agat/chline.s | 33 +++++++++++++++++++++++++++++++++ libsrc/agat/cputc.s | 19 +++++++++++++++---- libsrc/agat/cvline.s | 29 +++++++++++++++++++++++++++++ libsrc/agat/home.s | 2 +- 5 files changed, 85 insertions(+), 7 deletions(-) create mode 100644 libsrc/agat/chline.s create mode 100644 libsrc/agat/cvline.s diff --git a/include/agat.h b/include/agat.h index 2cdf24ae6..04ec16984 100644 --- a/include/agat.h +++ b/include/agat.h @@ -32,7 +32,12 @@ #define CH_CURS_UP 0x19 #define CH_CURS_DOWN 0x1A #define CH_ESC 0x1B - +#define CH_HLINE 0x1B +#define CH_VLINE 0x5C +#define CH_ULCORNER 0x10 +#define CH_URCORNER 0x12 +#define CH_LLCORNER 0x1D +#define CH_LRCORNER 0x1F /* Masks for joy_read */ #define JOY_UP_MASK 0x10 @@ -68,4 +73,4 @@ void rebootafterexit (void); /* End of agat.h */ -#endif //_AGAT_H +#endif diff --git a/libsrc/agat/chline.s b/libsrc/agat/chline.s new file mode 100644 index 000000000..bc95b2a16 --- /dev/null +++ b/libsrc/agat/chline.s @@ -0,0 +1,33 @@ +; +; Ullrich von Bassewitz, 08.08.1998 +; Colin Leroy-Mira, 26.05.2025 +; Konstantin Fedorov, 12.06.2025 +; +; void chlinexy (unsigned char x, unsigned char y, unsigned char length); +; void chline (unsigned char length); +; + + .export _chlinexy, _chline, chlinedirect + .import gotoxy, putchar + + .include "zeropage.inc" + +_chlinexy: + pha ; Save the length + jsr gotoxy ; Call this one, will pop params + pla ; Restore the length and run into _chline + +_chline: + ldx #$1B ; horizontal line character + +chlinedirect: + stx tmp1 + cmp #$00 ; Is the length zero? + beq done ; Jump if done + sta tmp2 +: lda tmp1 ; Screen code + jsr putchar ; Direct output + dec tmp2 + bne :- +done: rts + diff --git a/libsrc/agat/cputc.s b/libsrc/agat/cputc.s index b8d99aaea..b82ce22e6 100644 --- a/libsrc/agat/cputc.s +++ b/libsrc/agat/cputc.s @@ -1,12 +1,13 @@ ; ; Oleg A. Odintsov, Moscow, 2024 +; Konstantin Fedorov, 12.06.2025 ; ; void __fastcall__ cputcxy (unsigned char x, unsigned char y, char c); ; void __fastcall__ cputc (char c); ; .import COUT - .export _cputcxy, _cputc + .export _cputcxy, _cputc, newline, putchar,putchardirect .import gotoxy, VTABZ .include "agat.inc" @@ -15,20 +16,21 @@ _cputcxy: jsr gotoxy pla _cputc: - cmp #$0D + cmp #$0D ; Test for \r = carriage return bne notleft ldy #$00 sty CH rts notleft: - cmp #$0A + cmp #$0A ; Test for \n = line feed beq newline + putchar: ldy CH sta (BASL),Y iny lda TATTR - bmi wch + bmi wch ; Skip if t64 sta (BASL),Y iny wch: @@ -47,3 +49,12 @@ newline: : jmp VTABZ noend: rts + +putchardirect: + ldy CH + sta (BASL),Y + lda TATTR + bmi :+ + iny + sta (BASL),Y +: rts diff --git a/libsrc/agat/cvline.s b/libsrc/agat/cvline.s new file mode 100644 index 000000000..63c0d4daf --- /dev/null +++ b/libsrc/agat/cvline.s @@ -0,0 +1,29 @@ +; +; Ullrich von Bassewitz, 08.08.1998 +; Colin Leroy-Mira, 26.05.2025 +; Konstantin Fedorov, 12.06.2025 +; +; void cvlinexy (unsigned char x, unsigned char y, unsigned char length); +; void cvline (unsigned char length); +; + + .export _cvlinexy, _cvline + .import gotoxy, putchardirect, newline + + .include "zeropage.inc" + +_cvlinexy: + pha ; Save the length + jsr gotoxy ; Call this one, will pop params + pla ; Restore the length and run into _cvline + +_cvline: + cmp #$00 ; Is the length zero? + beq done ; Jump if done + sta tmp2 +: lda #$5C ; vertical line character + jsr putchardirect ; Write, no cursor advance + jsr newline ; Advance cursor to next line + dec tmp2 + bne :- +done: rts diff --git a/libsrc/agat/home.s b/libsrc/agat/home.s index 5067a782a..a0434c9bb 100644 --- a/libsrc/agat/home.s +++ b/libsrc/agat/home.s @@ -11,5 +11,5 @@ HOME: lda #$8C - jsr COUT + jmp COUT rts From 8202b520b262cc0f27a4fa48eddc93e07d6d6042 Mon Sep 17 00:00:00 2001 From: Konstantin <sintechs@gmail.com> Date: Fri, 13 Jun 2025 12:51:41 +0300 Subject: [PATCH 47/60] add Agat to samples --- include/target.h | 2 ++ libsrc/agat/_scrsize.s | 12 +++++++++--- samples/Makefile | 6 ++++++ samples/sieve.c | 2 +- 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/include/target.h b/include/target.h index 7663a39dd..5f9d8859c 100644 --- a/include/target.h +++ b/include/target.h @@ -37,6 +37,8 @@ # include <apple2enh.h> #elif defined(__APPLE2__) # include <apple2.h> +#elif defined(__AGAT__) +# include <agat.h> #elif defined(__ATARI__) # include <atari.h> #elif defined(__ATARI2600__) diff --git a/libsrc/agat/_scrsize.s b/libsrc/agat/_scrsize.s index f9d7c3785..09d7e879f 100644 --- a/libsrc/agat/_scrsize.s +++ b/libsrc/agat/_scrsize.s @@ -1,5 +1,6 @@ ; ; Ullrich von Bassewitz, 26.10.2000 +; Konstantin Fedorov, 12.06.2025 ; ; Screen size variables ; @@ -9,9 +10,14 @@ .include "agat.inc" screensize: - ldx WNDWDTH - lda WNDBTM + lda WNDWDTH + bit TATTR + bmi t64 + lsr +t64: + tax + lda WNDBTM sec - sbc WNDTOP + sbc WNDTOP tay rts diff --git a/samples/Makefile b/samples/Makefile index 3680f542c..295b6883d 100644 --- a/samples/Makefile +++ b/samples/Makefile @@ -158,6 +158,11 @@ DIRLIST = tutorial geos atari2600 atari5200 apple2 gamate lynx supervision sym1 # -------------------------------------------------------------------------- # Lists of executables +EXELIST_agat = \ + ascii \ + checkversion \ + hello \ + sieve EXELIST_apple2 = \ ascii \ @@ -390,6 +395,7 @@ all: # -------------------------------------------------------------------------- # List of every supported platform TARGETS := \ + agat \ apple2 \ apple2enh \ atari \ diff --git a/samples/sieve.c b/samples/sieve.c index 7c3b9cd75..5ffc97b62 100644 --- a/samples/sieve.c +++ b/samples/sieve.c @@ -12,7 +12,7 @@ /* Workaround missing clock stuff */ -#ifdef __APPLE2__ +#if defined(__APPLE2__) || defined(__AGAT__) # define clock() 0 # define CLOCKS_PER_SEC 1 #endif From 215f51a23033f68e5b23d1839fec8d13eb588985 Mon Sep 17 00:00:00 2001 From: Colin Leroy-Mira <colin@colino.net> Date: Fri, 13 Jun 2025 13:55:05 +0200 Subject: [PATCH 48/60] Fix temporary filenames again. Outputting temp files in the output directory means we have to distinguish source files in different source directories that happen to have the same name. --- src/common/fname.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/common/fname.c b/src/common/fname.c index d835ee7a0..7c52869e2 100644 --- a/src/common/fname.c +++ b/src/common/fname.c @@ -156,15 +156,22 @@ char* MakeTmpFilename (const char *Directory, const char *Origin, const char* Ex { char* Out; size_t Len = 0; + static unsigned int Counter = 0; - /* Allocate template */ + /* Allocate enough for the directory, ... */ if (Directory != NULL) { Len = strlen (Directory); } - Len += strlen (Origin) + strlen (".2147483648") + strlen (Ext) + 1; + + /* ... plus the the original name, the maximum length of the PID, the + * maximum length of the counter, the extension, and the terminator. + */ + Len += strlen (Origin) + (strlen (".2147483648") * 2) + strlen (Ext) + 1; Out = xmalloc (Len); - snprintf (Out, Len, "%s%s.%u%s", (Directory != NULL ? Directory : ""), - FindName(Origin), getpid(), Ext); + snprintf (Out, Len, "%s%s.%u%u%s", (Directory != NULL ? Directory : ""), + FindName(Origin), getpid(), Counter, Ext); + Counter++; + return Out; } From e3f9a5f05267fb24433d0868c39b5ac0e8f2030d Mon Sep 17 00:00:00 2001 From: Colin Leroy-Mira <colin@colino.net> Date: Sat, 14 Jun 2025 13:02:28 +0200 Subject: [PATCH 49/60] Make sure pid and counter don't interfere --- src/common/fname.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/fname.c b/src/common/fname.c index 7c52869e2..10d38f38a 100644 --- a/src/common/fname.c +++ b/src/common/fname.c @@ -169,7 +169,7 @@ char* MakeTmpFilename (const char *Directory, const char *Origin, const char* Ex Len += strlen (Origin) + (strlen (".2147483648") * 2) + strlen (Ext) + 1; Out = xmalloc (Len); - snprintf (Out, Len, "%s%s.%u%u%s", (Directory != NULL ? Directory : ""), + snprintf (Out, Len, "%s%s.%u.%u%s", (Directory != NULL ? Directory : ""), FindName(Origin), getpid(), Counter, Ext); Counter++; From 1ac8a51c580870a43e79eb9d6733d9b92c891df4 Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Sat, 14 Jun 2025 21:39:00 +0200 Subject: [PATCH 50/60] added repro cases from #2172 as tests --- test/todo/bug2172_invalid_code.c | 56 +++++++++++++++++++++++++++++++ test/todo/bug2172b_invalid_code.c | 51 ++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 test/todo/bug2172_invalid_code.c create mode 100644 test/todo/bug2172b_invalid_code.c diff --git a/test/todo/bug2172_invalid_code.c b/test/todo/bug2172_invalid_code.c new file mode 100644 index 000000000..74522c029 --- /dev/null +++ b/test/todo/bug2172_invalid_code.c @@ -0,0 +1,56 @@ + +// bug #2172 - Invalid code generated for switch statement + +#include <stdlib.h> +#include <stdio.h> + +// cc65 -o bug2172.s -Cl -Oirs -T -t c64 bug2172.c +int func(int expr) +{ + switch (expr) { + int i; + case 0: + i = 17; + return i; + default: + i = 16; + return i; + } +} + +int err = 0; + +int main(void) +{ + int i = 0; + int n = 42; + for (i = -3; i < 0; i++) { + n = func(i); + if ((i < -3) || (i >= 0)) { + goto stackerr; + } + printf("i:%d expect:16 got:%d\n", i, n); + if (n != 16) { + err++; + } + } + n = func(0); + printf("i:%d expect:17 got:%d\n", 0, n); + if (n != 17) { + err++; + } + for (i = 1; i < 4; i++) { + n = func(i); + if ((i < 1) || (i >= 4)) { + goto stackerr; + } + printf("i:%d expect:16 got:%d\n", i, n); + if (n != 16) { + err++; + } + } + return err; +stackerr: + fputs("stack messed up?\n", stdout); + return -1; +} diff --git a/test/todo/bug2172b_invalid_code.c b/test/todo/bug2172b_invalid_code.c new file mode 100644 index 000000000..13d983123 --- /dev/null +++ b/test/todo/bug2172b_invalid_code.c @@ -0,0 +1,51 @@ + +#include <stdlib.h> +#include <stdio.h> + +/* Just some arbitrary code, more fun with goto */ +int func(int m) +{ + long x = -42; /* sp: -4 */ + switch (x) { + /* return 0; // C99 only */ + int i = 42; /* sp: -6 */ +L0: + --i; +default: + if (i != 0) { + long j = 13; /* sp: -10 */ + goto L1; +L1: +case 0x7FFF01: + m--; +case 0x7EFF0001: +case 0x7FFF0001: + i++; + } /* sp: -6 */ +case 0x7FFF00: +case 0x7FFF0000: + break; + goto L0; + { + int skipped = 42; /* sp: -8 */ +case 0x7EFF00: +case 0x7EFF0000: + ++skipped; + } /* sp: -6 */ + } /* sp: -4 */ + + return m; +} + +int err = 0; + +int main(void) +{ + int n = 42; + n = func(7); + if (n != 7) { + err++; + } + printf("n:%d\n", n); + return err; +} From 7620e551eedf13ec0f21defd868d4f71ed79af94 Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Sat, 14 Jun 2025 22:40:29 +0200 Subject: [PATCH 51/60] add test --- test/standard/null.c | 162 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 162 insertions(+) create mode 100644 test/standard/null.c diff --git a/test/standard/null.c b/test/standard/null.c new file mode 100644 index 000000000..cd4bd0a44 --- /dev/null +++ b/test/standard/null.c @@ -0,0 +1,162 @@ + + +/* test headers which should define NULL */ + +#include <locale.h> +#ifndef NULL +#error "NULL should be defined in locale.h" +#endif +#undef NULL + +#include <stdlib.h> +#ifndef NULL +#error "NULL should be defined in stdlib.h" +#endif +#undef NULL + +#include <string.h> +#ifndef NULL +#error "NULL should be defined in string.h" +#endif +#undef NULL + +#include <stddef.h> +#ifndef NULL +#error "NULL should be defined in stddef.h" +#endif +#undef NULL + +#include <stdio.h> +#ifndef NULL +#error "NULL should be defined in stdio.h" +#endif +#undef NULL + +#include <time.h> +#ifndef NULL +#error "NULL should be defined in time.h" +#endif +#undef NULL + +/* does not exist in cc65 (yet) +#include <wchar.h> +#ifndef NULL +#error "NULL should be defined in wchar.h" +#endif */ +#undef NULL + + +/* test headers which should NOT define NULL */ + +#include <assert.h> +#ifdef NULL +#error "NULL should NOT be defined in assert.h" +#undef NULL +#endif + +/* does not exist in cc65 (yet) +#include <complex.h> +#ifdef NULL +#error "NULL should NOT be defined in complex.h" +#undef NULL +#endif */ + +#include <ctype.h> +#ifdef NULL +#error "NULL should NOT be defined in ctype.h" +#undef NULL +#endif + +#include <errno.h> +#ifdef NULL +#error "NULL should NOT be defined in errno.h" +#undef NULL +#endif + +/* does not exist in cc65 (yet) +#include <fenv.h> +#ifdef NULL +#error "NULL should NOT be defined in fenv.h" +#undef NULL +#endif */ + +/* does not exist in cc65 (yet) +#include <float.h> +#ifdef NULL +#error "NULL should NOT be defined in float.h" +#undef NULL +#endif */ + +#include <inttypes.h> +#ifdef NULL +#error "NULL should NOT be defined in inttypes.h" +#undef NULL +#endif + +#include <iso646.h> +#ifdef NULL +#error "NULL should NOT be defined in iso646.h" +#undef NULL +#endif + +#include <limits.h> +#ifdef NULL +#error "NULL should NOT be defined in limits.h" +#undef NULL +#endif + +/* does not exist in cc65 (yet) +#include <math.h> +#ifdef NULL +#error "NULL should NOT be defined in math.h" +#undef NULL +#endif */ + +#include <setjmp.h> +#ifdef NULL +#error "NULL should NOT be defined in setjmp.h" +#undef NULL +#endif + +#include <signal.h> +#ifdef NULL +#error "NULL should NOT be defined in signal.h" +#undef NULL +#endif + +#include <stdarg.h> +#ifdef NULL +#error "NULL should NOT be defined in stdarg.h" +#undef NULL +#endif + +#include <stdbool.h> +#ifdef NULL +#error "NULL should NOT be defined in stdbool.h" +#undef NULL +#endif + +#include <stdint.h> +#ifdef NULL +#error "NULL should NOT be defined in stdint.h" +#undef NULL +#endif + +/* does not exist in cc65 (yet) +#include <tgmath.h> +#ifdef NULL +#error "NULL should NOT be defined in tgmath.h" +#undef NULL +#endif */ + +/* does not exist in cc65 (yet) +#include <wctype.h> +#ifdef NULL +#error "NULL should NOT be defined in wctype.h" +#undef NULL +#endif */ + +int main(void) +{ + return 0; +} From 990d65e4e463d1dc95913bc7624369636861f7f5 Mon Sep 17 00:00:00 2001 From: Colin Leroy-Mira <colin@colino.net> Date: Thu, 12 Jun 2025 08:51:55 +0200 Subject: [PATCH 52/60] Apple2: Setup IRQ/RST vectors in LC if needed Programs running under DOS3.3 need to setup correct reset and IRQ vectors in the language card. --- asminc/apple2.inc | 2 ++ doc/apple2.sgml | 2 +- doc/apple2enh.sgml | 2 +- libsrc/apple2/crt0.s | 24 +++++++++++++++++++++++- 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/asminc/apple2.inc b/asminc/apple2.inc index fb4a1b2f0..bde383882 100644 --- a/asminc/apple2.inc +++ b/asminc/apple2.inc @@ -24,6 +24,8 @@ DOSWARM := $03D0 ; DOS warmstart vector BRKVec := $03F0 ; Break vector SOFTEV := $03F2 ; Vector for warm start PWREDUP := $03F4 ; This must be = EOR #$A5 of SOFTEV+1 +ROM_RST := $FFFC ; 6502 reset vector +ROM_IRQ := $FFFE ; 6502 IRQ vector ;----------------------------------------------------------------------------- ; 80 column firmware diff --git a/doc/apple2.sgml b/doc/apple2.sgml index 719e799f4..ec9598d04 100644 --- a/doc/apple2.sgml +++ b/doc/apple2.sgml @@ -87,7 +87,7 @@ several useful settings: exit then a plain vanilla ProDOS 8 doesn't make use of the Language Card bank 2 at all. - <tag>LC address: $D000, LC size: $3000</tag> + <tag>LC address: $D000, LC size: $2FFC</tag> For plain vanilla DOS 3.3 which doesn't make use of the Language Card at all. </descrip><p> diff --git a/doc/apple2enh.sgml b/doc/apple2enh.sgml index 094ddd93e..1e94d3b60 100644 --- a/doc/apple2enh.sgml +++ b/doc/apple2enh.sgml @@ -88,7 +88,7 @@ several useful settings: exit then a plain vanilla ProDOS 8 doesn't make use of the Language Card bank 2 at all. - <tag>LC address: $D000, LC size: $3000</tag> + <tag>LC address: $D000, LC size: $2FFC</tag> For plain vanilla DOS 3.3 which doesn't make use of the Language Card at all. </descrip><p> diff --git a/libsrc/apple2/crt0.s b/libsrc/apple2/crt0.s index 628303687..ce14cc1e3 100644 --- a/libsrc/apple2/crt0.s +++ b/libsrc/apple2/crt0.s @@ -58,6 +58,7 @@ init: ldx #zpspace-1 ; Check for ProDOS. ldy $BF00 ; MLI call entry point cpy #$4C ; Is MLI present? (JMP opcode) + php ; Remember whether we're running ProDOS bne basic ; Check the ProDOS system bit map. @@ -99,7 +100,20 @@ basic: lda HIMEM bit $C081 bit $C081 - ; Set the source start address. + plp ; Are we running ProDOS? + beq :+ ; Yes, no need to patch vectors + + lda #<reset_6502 + ldx #>reset_6502 + sta ROM_RST + stx ROM_RST+1 + + lda #<irq_6502 + ldx #>irq_6502 + sta ROM_IRQ + stx ROM_IRQ+1 + +: ; Set the source start address. ; Aka __LC_LOAD__ iff segment LC exists. lda #<(__ONCE_LOAD__ + __ONCE_SIZE__) ldy #>(__ONCE_LOAD__ + __ONCE_SIZE__) @@ -144,6 +158,14 @@ quit: jsr $BF00 ; MLI call entry point .byte $65 ; Quit .word q_param +reset_6502: ; Used with DOS3.3 programs + bit $C082 ; Switch in ROM + jmp (ROM_RST) ; Jump to ROM's RESET vector + +irq_6502: ; Used with DOS3.3 programs + bit $C082 ; Switch in ROM + jmp (ROM_IRQ) ; Jump to ROM's IRQ/BRK vector + ; ------------------------------------------------------------------------ .rodata From 24b7d1fec754756a46943688aae37160494cf8f6 Mon Sep 17 00:00:00 2001 From: Oliver <ol.sc@web.de> Date: Sun, 15 Jun 2025 20:01:16 +0200 Subject: [PATCH 53/60] Make use of dynamic box drawing --- samples/diodemo.c | 1 + samples/hello.c | 1 + 2 files changed, 2 insertions(+) diff --git a/samples/diodemo.c b/samples/diodemo.c index 3e52f2fa9..46656246d 100644 --- a/samples/diodemo.c +++ b/samples/diodemo.c @@ -30,6 +30,7 @@ +#define DYN_BOX_DRAW #include <stddef.h> #include <stdlib.h> #include <limits.h> diff --git a/samples/hello.c b/samples/hello.c index 255dccd00..2eac0d8bb 100644 --- a/samples/hello.c +++ b/samples/hello.c @@ -7,6 +7,7 @@ +#define DYN_BOX_DRAW #include <stdlib.h> #include <string.h> #include <conio.h> From c0a0ba1483f92199dfa6e01b99406a1f13add588 Mon Sep 17 00:00:00 2001 From: Gorilla Sapiens <embracetheape@gmail.com> Date: Mon, 16 Jun 2025 02:46:10 +0000 Subject: [PATCH 54/60] added reporting of fatal/error/warning/note location generation with "-d" --- src/cc65/error.c | 76 +++++++++++++++++++++++++++++++++++++++++------- src/cc65/error.h | 33 ++++++++++++++------- 2 files changed, 87 insertions(+), 22 deletions(-) diff --git a/src/cc65/error.c b/src/cc65/error.c index db0debf8c..90577c0ad 100644 --- a/src/cc65/error.c +++ b/src/cc65/error.c @@ -39,6 +39,7 @@ /* common */ #include "coll.h" +#include "debugflag.h" #include "print.h" #include "strbuf.h" @@ -183,11 +184,15 @@ static unsigned GetDiagnosticLineNum (void) -void Fatal (const char* Format, ...) +void _Fatal (const char *file, int line, const char* Format, ...) /* Print a message about a fatal error and die */ { va_list ap; + if (Debug) { + fprintf(stderr, "[%s:%d] ", file, line); + } + fprintf (stderr, "%s:%u: Fatal: ", GetDiagnosticFileName (), GetDiagnosticLineNum ()); va_start (ap, Format); @@ -203,11 +208,15 @@ void Fatal (const char* Format, ...) -void Internal (const char* Format, ...) +void _Internal (const char *file, int line, const char* Format, ...) /* Print a message about an internal compiler error and die */ { va_list ap; + if (Debug) { + fprintf(stderr, "[%s:%d] ", file, line); + } + fprintf (stderr, "%s:%u: Internal compiler error:\n", GetDiagnosticFileName (), GetDiagnosticLineNum ()); @@ -270,10 +279,15 @@ static void IntError (errcat_t EC, LineInfo* LI, const char* Msg, va_list ap) -void LIError (errcat_t EC, LineInfo* LI, const char* Format, ...) +void _LIError (const char *file, int line, errcat_t EC, LineInfo* LI, const char* Format, ...) /* Print an error message with the line info given explicitly */ { va_list ap; + + if (Debug) { + fprintf(stderr, "[%s:%d] ", file, line); + } + va_start (ap, Format); IntError (EC, LI, Format, ap); va_end (ap); @@ -281,10 +295,15 @@ void LIError (errcat_t EC, LineInfo* LI, const char* Format, ...) -void Error (const char* Format, ...) +void _Error (const char *file, int line, const char* Format, ...) /* Print an error message */ { va_list ap; + + if (Debug) { + fprintf(stderr, "[%s:%d] ", file, line); + } + va_start (ap, Format); IntError (EC_PARSER, GetDiagnosticLI (), Format, ap); va_end (ap); @@ -292,10 +311,15 @@ void Error (const char* Format, ...) -void PPError (const char* Format, ...) +void _PPError (const char *file, int line, const char* Format, ...) /* Print an error message. For use within the preprocessor */ { va_list ap; + + if (Debug) { + fprintf(stderr, "[%s:%d] ", file, line); + } + va_start (ap, Format); IntError (EC_PP, GetCurLineInfo (), Format, ap); va_end (ap); @@ -346,10 +370,15 @@ static void IntWarning (errcat_t EC, LineInfo* LI, const char* Msg, va_list ap) -void LIWarning (errcat_t EC, LineInfo* LI, const char* Format, ...) +void _LIWarning (const char *file, int line, errcat_t EC, LineInfo* LI, const char* Format, ...) /* Print a warning message with the line info given explicitly */ { va_list ap; + + if (Debug) { + fprintf(stderr, "[%s:%d] ", file, line); + } + va_start (ap, Format); IntWarning (EC, LI, Format, ap); va_end (ap); @@ -357,10 +386,15 @@ void LIWarning (errcat_t EC, LineInfo* LI, const char* Format, ...) -void Warning (const char* Format, ...) +void _Warning (const char *file, int line, const char* Format, ...) /* Print a warning message */ { va_list ap; + + if (Debug) { + fprintf(stderr, "[%s:%d] ", file, line); + } + va_start (ap, Format); IntWarning (EC_PARSER, GetDiagnosticLI (), Format, ap); va_end (ap); @@ -368,10 +402,15 @@ void Warning (const char* Format, ...) -void PPWarning (const char* Format, ...) +void _PPWarning (const char *file, int line, const char* Format, ...) /* Print a warning message. For use within the preprocessor */ { va_list ap; + + if (Debug) { + fprintf(stderr, "[%s:%d] ", file, line); + } + va_start (ap, Format); IntWarning (EC_PP, GetCurLineInfo (), Format, ap); va_end (ap); @@ -436,10 +475,15 @@ static void IntNote (const LineInfo* LI, const char* Msg, va_list ap) -void LINote (const LineInfo* LI, const char* Format, ...) +void _LINote (const char *file, int line, const LineInfo* LI, const char* Format, ...) /* Print a note message with the line info given explicitly */ { va_list ap; + + if (Debug) { + fprintf(stderr, "[%s:%d] ", file, line); + } + va_start (ap, Format); IntNote (LI, Format, ap); va_end (ap); @@ -447,10 +491,15 @@ void LINote (const LineInfo* LI, const char* Format, ...) -void Note (const char* Format, ...) +void _Note (const char *file, int line, const char* Format, ...) /* Print a note message */ { va_list ap; + + if (Debug) { + fprintf(stderr, "[%s:%d] ", file, line); + } + va_start (ap, Format); IntNote (GetDiagnosticLI (), Format, ap); va_end (ap); @@ -458,10 +507,15 @@ void Note (const char* Format, ...) -void PPNote (const char* Format, ...) +void _PPNote (const char *file, int line, const char* Format, ...) /* Print a note message. For use within the preprocessor */ { va_list ap; + + if (Debug) { + fprintf(stderr, "[%s:%d] ", file, line); + } + va_start (ap, Format); IntNote (GetDiagnosticLI (), Format, ap); va_end (ap); diff --git a/src/cc65/error.h b/src/cc65/error.h index b3cdc49ab..63158b3bd 100644 --- a/src/cc65/error.h +++ b/src/cc65/error.h @@ -103,28 +103,36 @@ struct StrBuf; void PrintFileInclusionInfo (const LineInfo* LI); /* Print hierarchy of file inclusion */ -void Fatal (const char* Format, ...) attribute ((noreturn, format (printf, 1, 2))); +void _Fatal (const char *file, int line, const char* Format, ...) attribute ((noreturn, format (printf, 3, 4))); +#define Fatal(...) _Fatal(__FILE__, __LINE__, __VA_ARGS__) /* Print a message about a fatal error and die */ -void Internal (const char* Format, ...) attribute ((noreturn, format (printf, 1, 2))); +void _Internal (const char *file, int line, const char* Format, ...) attribute ((noreturn, format (printf, 3, 4))); +#define Internal(...) _Internal(__FILE__, __LINE__, __VA_ARGS__) /* Print a message about an internal compiler error and die */ -void Error (const char* Format, ...) attribute ((format (printf, 1, 2))); +void _Error (const char *file, int line, const char* Format, ...) attribute ((format (printf, 3, 4))); +#define Error(...) _Error(__FILE__, __LINE__, __VA_ARGS__) /* Print an error message */ -void LIError (errcat_t EC, LineInfo* LI, const char* Format, ...) attribute ((format (printf, 3, 4))); +void _LIError (const char *file, int line, errcat_t EC, LineInfo* LI, const char* Format, ...) attribute ((format (printf, 5, 6))); +#define LIError(...) _LIError(__FILE__, __LINE__, __VA_ARGS__) /* Print an error message with the line info given explicitly */ -void PPError (const char* Format, ...) attribute ((format (printf, 1, 2))); +void _PPError (const char *file, int line, const char* Format, ...) attribute ((format (printf, 3, 4))); +#define PPError(...) _PPError(__FILE__, __LINE__, __VA_ARGS__) /* Print an error message. For use within the preprocessor */ -void Warning (const char* Format, ...) attribute ((format (printf, 1, 2))); +void _Warning (const char *file, int line, const char* Format, ...) attribute ((format (printf, 3, 4))); +#define Warning(...) _Warning(__FILE__, __LINE__, __VA_ARGS__) /* Print a warning message */ -void LIWarning (errcat_t EC, LineInfo* LI, const char* Format, ...) attribute ((format (printf, 3, 4))); +void _LIWarning (const char *file, int line, errcat_t EC, LineInfo* LI, const char* Format, ...) attribute ((format (printf, 5, 6))); +#define LIWarning(...) _LIWarning(__FILE__, __LINE__, __VA_ARGS__) /* Print a warning message with the line info given explicitly */ -void PPWarning (const char* Format, ...) attribute ((format (printf, 1, 2))); +void _PPWarning (const char *file, int line, const char* Format, ...) attribute ((format (printf, 3, 4))); +#define PPWarning(...) _PPWarning(__FILE__, __LINE__, __VA_ARGS__) /* Print a warning message. For use within the preprocessor */ void UnreachableCodeWarning (void); @@ -140,13 +148,16 @@ IntStack* FindWarning (const char* Name); void ListWarnings (FILE* F); /* Print a list of warning types/names to the given file */ -void Note (const char* Format, ...) attribute ((format (printf, 1, 2))); +void _Note (const char *file, int line, const char* Format, ...) attribute ((format (printf, 3, 4))); +#define Note(...) _Note(__FILE__, __LINE__, __VA_ARGS__) /* Print a note message */ -void LINote (const LineInfo* LI, const char* Format, ...) attribute ((format (printf, 2, 3))); +void _LINote (const char *file, int line, const LineInfo* LI, const char* Format, ...) attribute ((format (printf, 4, 5))); +#define LINote(...) _LINote(__FILE__, __LINE__, __VA_ARGS__) /* Print a note message with the line info given explicitly */ -void PPNote (const char* Format, ...) attribute ((format (printf, 1, 2))); +void _PPNote (const char *file, int line, const char* Format, ...) attribute ((format (printf, 3, 4))); +#define PPNote(...) _PPNote(__FILE__, __LINE__, __VA_ARGS__) /* Print a note message. For use within the preprocessor */ unsigned GetTotalErrors (void); From adc9ddc2807597290ab9e0e36951cb9cc360b3e6 Mon Sep 17 00:00:00 2001 From: Kugel Fuhr <98353208+kugelfuhr@users.noreply.github.com> Date: Mon, 16 Jun 2025 11:16:13 +0200 Subject: [PATCH 55/60] Change the available options to -dM and -dP. The former prints user macros, the latter predefined macros. Can be combined by using -dMP or -dPM. --- doc/cc65.sgml | 31 +++++++++++++++-------------- src/cc65/compile.c | 7 ++----- src/cc65/global.c | 5 ++--- src/cc65/global.h | 5 ++--- src/cc65/macrotab.c | 27 +++++++++++-------------- src/cc65/macrotab.h | 7 ++----- src/cc65/main.c | 48 +++++++++++++++++++++------------------------ 7 files changed, 57 insertions(+), 73 deletions(-) diff --git a/doc/cc65.sgml b/doc/cc65.sgml index a78f1a00a..383a6dd6a 100644 --- a/doc/cc65.sgml +++ b/doc/cc65.sgml @@ -63,9 +63,8 @@ Short options: -V Print the compiler version number -W [-+]warning[,...] Control warnings ('-' disables, '+' enables) -d Debug mode - -dD Output user defined macros (needs -E) - -dM Output all macro definitions (needs -E) - -dN Output user defined macro names (needs -E) + -dM Output all user macros (needs -E) + -dP Output all predefined macros (needs -E) -g Add debug info to object file -h Help (this text) -j Default characters are signed @@ -202,24 +201,26 @@ Here is a description of all the command line options: Enables debug mode, for debugging the behavior of cc65. - <label id="option-dD"> - <tag><tt>-dD</tt></tag> - - Like <tt/<ref id="option-dM" name="-dM">/ but does not include the predefined - macros. - <label id="option-dM"> <tag><tt>-dM</tt></tag> + When used with -E, will output <tt>#define</tt> directives for all the user + macros defined during execution of the preprocessor. This does not include + macros defined by the compiler. + + Note: Can be combined with <tt/<ref id="option-dP" name="-dP">/ by using + <tt/-dMP/. + + + <label id="option-dP"> + <tag><tt>-dP</tt></tag> + When used with -E, will output <tt>#define</tt> directives for all the macros - defined during execution of the preprocessor, including predefined macros. + defined by the compiler itself. This does not include any user defined macros. - - <tag><tt>-dN</tt></tag> - - Like <tt/<ref id="option-dD" name="-dD">/ but will only output the macro names, - not their definitions. + Note: Can be combined with <tt/<ref id="option-dM" name="-dM">/ by using + <tt/-dMP/. <tag><tt>--debug-tables name</tt></tag> diff --git a/src/cc65/compile.c b/src/cc65/compile.c index 5b9ef1551..9083891aa 100644 --- a/src/cc65/compile.c +++ b/src/cc65/compile.c @@ -497,15 +497,12 @@ void Compile (const char* FileName) { /* Nothing */ } /* Output macros if requested by the user */ - if (DumpAllMacrosFull) { - OutputAllMacrosFull (); + if (DumpPredefMacros) { + OutputPredefMacros (); } if (DumpUserMacros) { OutputUserMacros (); } - if (DumpUserMacrosFull) { - OutputUserMacrosFull (); - } /* Close the output file */ CloseOutputFile (); diff --git a/src/cc65/global.c b/src/cc65/global.c index 6fcc5d9d7..64278df77 100644 --- a/src/cc65/global.c +++ b/src/cc65/global.c @@ -47,9 +47,8 @@ unsigned char AddSource = 0; /* Add source lines as comments */ unsigned char AllowNewComments = 0; /* Allow new style comments in C89 mode */ unsigned char AutoCDecl = 0; /* Make functions default to __cdecl__ */ unsigned char DebugInfo = 0; /* Add debug info to the obj */ -unsigned char DumpAllMacrosFull = 0; /* Output all macro defs */ -unsigned char DumpUserMacros = 0; /* Output user macro names */ -unsigned char DumpUserMacrosFull= 0; /* Output user macro defs */ +unsigned char DumpPredefMacros = 0; /* Output predefined macros */ +unsigned char DumpUserMacros = 0; /* Output user macros */ unsigned char PreprocessOnly = 0; /* Just preprocess the input */ unsigned char DebugOptOutput = 0; /* Output debug stuff */ unsigned RegisterSpace = 6; /* Space available for register vars */ diff --git a/src/cc65/global.h b/src/cc65/global.h index d475c73e5..c781f6de4 100644 --- a/src/cc65/global.h +++ b/src/cc65/global.h @@ -55,9 +55,8 @@ extern unsigned char AddSource; /* Add source lines as comments extern unsigned char AllowNewComments; /* Allow new style comments in C89 mode */ extern unsigned char AutoCDecl; /* Make functions default to __cdecl__ */ extern unsigned char DebugInfo; /* Add debug info to the obj */ -extern unsigned char DumpAllMacrosFull; /* Output all macro defs */ -extern unsigned char DumpUserMacros; /* Output user macro names */ -extern unsigned char DumpUserMacrosFull; /* Output user macro defs */ +extern unsigned char DumpPredefMacros; /* Output predefined macros */ +extern unsigned char DumpUserMacros; /* Output user macros */ extern unsigned char PreprocessOnly; /* Just preprocess the input */ extern unsigned char DebugOptOutput; /* Output debug stuff */ extern unsigned RegisterSpace; /* Space available for register vars */ diff --git a/src/cc65/macrotab.c b/src/cc65/macrotab.c index 41345db8a..2817403c1 100644 --- a/src/cc65/macrotab.c +++ b/src/cc65/macrotab.c @@ -62,8 +62,8 @@ static Macro* MacroTab[MACRO_TAB_SIZE]; static Macro* UndefinedMacrosListHead; /* Some defines for better readability when calling OutputMacros() */ -#define ALL_MACROS 0 -#define USER_MACROS 1 +#define USER_MACROS 0 +#define PREDEF_MACROS 1 #define NAME_ONLY 0 #define FULL_DEFINITION 1 @@ -107,14 +107,17 @@ static void OutputMacro (const Macro* M, int Full) -static void OutputMacros (int UserOnly, int Full) -/* Output macros to the output file depending on the flags given */ +static void OutputMacros (int Predefined, int Full) +/* Output macros to the output file depending on the flags given. */ { + /* Note: The Full flag is currently not used by any callers but is left in + ** place for possible future changes. + */ unsigned I; for (I = 0; I < MACRO_TAB_SIZE; ++I) { const Macro* M = MacroTab [I]; while (M) { - if (!UserOnly || !M->Predefined) { + if ((Predefined != 0) == (M->Predefined != 0)) { OutputMacro (M, Full); } M = M->Next; @@ -416,23 +419,15 @@ void PrintMacroStats (FILE* F) -void OutputAllMacrosFull (void) -/* Output all macros to the output file */ +void OutputPredefMacros (void) +/* Output all predefined macros to the output file */ { - OutputMacros (ALL_MACROS, FULL_DEFINITION); + OutputMacros (PREDEF_MACROS, FULL_DEFINITION); } void OutputUserMacros (void) -/* Output the names of all user defined macros to the output file */ -{ - OutputMacros (USER_MACROS, NAME_ONLY); -} - - - -void OutputUserMacrosFull (void) /* Output all user defined macros to the output file */ { OutputMacros (USER_MACROS, FULL_DEFINITION); diff --git a/src/cc65/macrotab.h b/src/cc65/macrotab.h index 8d2a04755..00fb1d55a 100644 --- a/src/cc65/macrotab.h +++ b/src/cc65/macrotab.h @@ -133,13 +133,10 @@ int MacroCmp (const Macro* M1, const Macro* M2); void PrintMacroStats (FILE* F); /* Print macro statistics to the given text file. */ -void OutputAllMacrosFull (void); -/* Output all macros to the output file */ +void OutputPredefMacros (void); +/* Output all predefined macros to the output file */ void OutputUserMacros (void); -/* Output the names of all user defined macros to the output file */ - -void OutputUserMacrosFull (void); /* Output all user defined macros to the output file */ diff --git a/src/cc65/main.c b/src/cc65/main.c index 4ff17ada9..0500a52f3 100644 --- a/src/cc65/main.c +++ b/src/cc65/main.c @@ -93,9 +93,8 @@ static void Usage (void) " -V\t\t\t\tPrint the compiler version number\n" " -W [-+]warning[,...]\t\tControl warnings ('-' disables, '+' enables)\n" " -d\t\t\t\tDebug mode\n" - " -dD\t\t\t\tOutput user defined macros (needs -E)\n" - " -dM\t\t\t\tOutput all macro definitions (needs -E)\n" - " -dN\t\t\t\tOutput user defined macro names (needs -E)\n" + " -dM\t\t\t\tOutput all user macros (needs -E)\n" + " -dP\t\t\t\tOutput all predefined macros (needs -E)\n" " -g\t\t\t\tAdd debug info to object file\n" " -h\t\t\t\tHelp (this text)\n" " -j\t\t\t\tDefault characters are signed\n" @@ -1025,25 +1024,24 @@ int main (int argc, char* argv[]) break; case 'd': - switch (Arg[2]) { - case '\0': - OptDebug (Arg, 0); - break; - case 'D': - DumpUserMacrosFull = 1; - break; - case 'M': - DumpAllMacrosFull = 1; - break; - case 'N': - DumpUserMacros = 1; - break; - default: - UnknownOption (Arg); - break; - } - if (Arg[2] && Arg[3]) { - UnknownOption (Arg); + P = Arg + 2; + if (*P == '\0') { + OptDebug (Arg, 0); + } else { + while (*P) { + switch (*P) { + case 'M': + DumpUserMacros = 1; + break; + case 'P': + DumpPredefMacros = 1; + break; + default: + UnknownOption (Arg); + break; + } + ++P; + } } break; @@ -1157,10 +1155,8 @@ int main (int argc, char* argv[]) } /* The options to output macros can only be used with -E */ - if (DumpAllMacrosFull || DumpUserMacros || DumpUserMacrosFull) { - if (!PreprocessOnly) { - AbEnd ("Preprocessor macro output can only be used together with -E"); - } + if ((DumpPredefMacros || DumpUserMacros) && !PreprocessOnly) { + AbEnd ("Preprocessor macro output can only be used together with -E"); } /* Add the default include search paths. */ From c90c61f08f74abc1d164d926e48a13b130fd2d91 Mon Sep 17 00:00:00 2001 From: Gorilla Sapiens <embracetheape@gmail.com> Date: Mon, 16 Jun 2025 23:30:46 +0000 Subject: [PATCH 56/60] rename functions --- src/cc65/error.c | 22 +++++++++++----------- src/cc65/error.h | 44 ++++++++++++++++++++++---------------------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/src/cc65/error.c b/src/cc65/error.c index 90577c0ad..ae2d6f27d 100644 --- a/src/cc65/error.c +++ b/src/cc65/error.c @@ -184,7 +184,7 @@ static unsigned GetDiagnosticLineNum (void) -void _Fatal (const char *file, int line, const char* Format, ...) +void Fatal_ (const char *file, int line, const char* Format, ...) /* Print a message about a fatal error and die */ { va_list ap; @@ -208,7 +208,7 @@ void _Fatal (const char *file, int line, const char* Format, ...) -void _Internal (const char *file, int line, const char* Format, ...) +void Internal_ (const char *file, int line, const char* Format, ...) /* Print a message about an internal compiler error and die */ { va_list ap; @@ -279,7 +279,7 @@ static void IntError (errcat_t EC, LineInfo* LI, const char* Msg, va_list ap) -void _LIError (const char *file, int line, errcat_t EC, LineInfo* LI, const char* Format, ...) +void LIError_ (const char *file, int line, errcat_t EC, LineInfo* LI, const char* Format, ...) /* Print an error message with the line info given explicitly */ { va_list ap; @@ -295,7 +295,7 @@ void _LIError (const char *file, int line, errcat_t EC, LineInfo* LI, const char -void _Error (const char *file, int line, const char* Format, ...) +void Error_ (const char *file, int line, const char* Format, ...) /* Print an error message */ { va_list ap; @@ -311,7 +311,7 @@ void _Error (const char *file, int line, const char* Format, ...) -void _PPError (const char *file, int line, const char* Format, ...) +void PPError_ (const char *file, int line, const char* Format, ...) /* Print an error message. For use within the preprocessor */ { va_list ap; @@ -370,7 +370,7 @@ static void IntWarning (errcat_t EC, LineInfo* LI, const char* Msg, va_list ap) -void _LIWarning (const char *file, int line, errcat_t EC, LineInfo* LI, const char* Format, ...) +void LIWarning_ (const char *file, int line, errcat_t EC, LineInfo* LI, const char* Format, ...) /* Print a warning message with the line info given explicitly */ { va_list ap; @@ -386,7 +386,7 @@ void _LIWarning (const char *file, int line, errcat_t EC, LineInfo* LI, const ch -void _Warning (const char *file, int line, const char* Format, ...) +void Warning_ (const char *file, int line, const char* Format, ...) /* Print a warning message */ { va_list ap; @@ -402,7 +402,7 @@ void _Warning (const char *file, int line, const char* Format, ...) -void _PPWarning (const char *file, int line, const char* Format, ...) +void PPWarning_ (const char *file, int line, const char* Format, ...) /* Print a warning message. For use within the preprocessor */ { va_list ap; @@ -475,7 +475,7 @@ static void IntNote (const LineInfo* LI, const char* Msg, va_list ap) -void _LINote (const char *file, int line, const LineInfo* LI, const char* Format, ...) +void LINote_ (const char *file, int line, const LineInfo* LI, const char* Format, ...) /* Print a note message with the line info given explicitly */ { va_list ap; @@ -491,7 +491,7 @@ void _LINote (const char *file, int line, const LineInfo* LI, const char* Format -void _Note (const char *file, int line, const char* Format, ...) +void Note_ (const char *file, int line, const char* Format, ...) /* Print a note message */ { va_list ap; @@ -507,7 +507,7 @@ void _Note (const char *file, int line, const char* Format, ...) -void _PPNote (const char *file, int line, const char* Format, ...) +void PPNote_ (const char *file, int line, const char* Format, ...) /* Print a note message. For use within the preprocessor */ { va_list ap; diff --git a/src/cc65/error.h b/src/cc65/error.h index 63158b3bd..0a18d51a4 100644 --- a/src/cc65/error.h +++ b/src/cc65/error.h @@ -103,36 +103,36 @@ struct StrBuf; void PrintFileInclusionInfo (const LineInfo* LI); /* Print hierarchy of file inclusion */ -void _Fatal (const char *file, int line, const char* Format, ...) attribute ((noreturn, format (printf, 3, 4))); -#define Fatal(...) _Fatal(__FILE__, __LINE__, __VA_ARGS__) +void Fatal_ (const char *file, int line, const char* Format, ...) attribute ((noreturn, format (printf, 3, 4))); +#define Fatal(...) Fatal_(__FILE__, __LINE__, __VA_ARGS__) /* Print a message about a fatal error and die */ -void _Internal (const char *file, int line, const char* Format, ...) attribute ((noreturn, format (printf, 3, 4))); -#define Internal(...) _Internal(__FILE__, __LINE__, __VA_ARGS__) +void Internal_ (const char *file, int line, const char* Format, ...) attribute ((noreturn, format (printf, 3, 4))); +#define Internal(...) Internal_(__FILE__, __LINE__, __VA_ARGS__) /* Print a message about an internal compiler error and die */ -void _Error (const char *file, int line, const char* Format, ...) attribute ((format (printf, 3, 4))); -#define Error(...) _Error(__FILE__, __LINE__, __VA_ARGS__) +void Error_ (const char *file, int line, const char* Format, ...) attribute ((format (printf, 3, 4))); +#define Error(...) Error_(__FILE__, __LINE__, __VA_ARGS__) /* Print an error message */ -void _LIError (const char *file, int line, errcat_t EC, LineInfo* LI, const char* Format, ...) attribute ((format (printf, 5, 6))); -#define LIError(...) _LIError(__FILE__, __LINE__, __VA_ARGS__) +void LIError_ (const char *file, int line, errcat_t EC, LineInfo* LI, const char* Format, ...) attribute ((format (printf, 5, 6))); +#define LIError(...) LIError_(__FILE__, __LINE__, __VA_ARGS__) /* Print an error message with the line info given explicitly */ -void _PPError (const char *file, int line, const char* Format, ...) attribute ((format (printf, 3, 4))); -#define PPError(...) _PPError(__FILE__, __LINE__, __VA_ARGS__) +void PPError_ (const char *file, int line, const char* Format, ...) attribute ((format (printf, 3, 4))); +#define PPError(...) PPError_(__FILE__, __LINE__, __VA_ARGS__) /* Print an error message. For use within the preprocessor */ -void _Warning (const char *file, int line, const char* Format, ...) attribute ((format (printf, 3, 4))); -#define Warning(...) _Warning(__FILE__, __LINE__, __VA_ARGS__) +void Warning_ (const char *file, int line, const char* Format, ...) attribute ((format (printf, 3, 4))); +#define Warning(...) Warning_(__FILE__, __LINE__, __VA_ARGS__) /* Print a warning message */ -void _LIWarning (const char *file, int line, errcat_t EC, LineInfo* LI, const char* Format, ...) attribute ((format (printf, 5, 6))); -#define LIWarning(...) _LIWarning(__FILE__, __LINE__, __VA_ARGS__) +void LIWarning_ (const char *file, int line, errcat_t EC, LineInfo* LI, const char* Format, ...) attribute ((format (printf, 5, 6))); +#define LIWarning(...) LIWarning_(__FILE__, __LINE__, __VA_ARGS__) /* Print a warning message with the line info given explicitly */ -void _PPWarning (const char *file, int line, const char* Format, ...) attribute ((format (printf, 3, 4))); -#define PPWarning(...) _PPWarning(__FILE__, __LINE__, __VA_ARGS__) +void PPWarning_ (const char *file, int line, const char* Format, ...) attribute ((format (printf, 3, 4))); +#define PPWarning(...) PPWarning_(__FILE__, __LINE__, __VA_ARGS__) /* Print a warning message. For use within the preprocessor */ void UnreachableCodeWarning (void); @@ -148,16 +148,16 @@ IntStack* FindWarning (const char* Name); void ListWarnings (FILE* F); /* Print a list of warning types/names to the given file */ -void _Note (const char *file, int line, const char* Format, ...) attribute ((format (printf, 3, 4))); -#define Note(...) _Note(__FILE__, __LINE__, __VA_ARGS__) +void Note_ (const char *file, int line, const char* Format, ...) attribute ((format (printf, 3, 4))); +#define Note(...) Note_(__FILE__, __LINE__, __VA_ARGS__) /* Print a note message */ -void _LINote (const char *file, int line, const LineInfo* LI, const char* Format, ...) attribute ((format (printf, 4, 5))); -#define LINote(...) _LINote(__FILE__, __LINE__, __VA_ARGS__) +void LINote_ (const char *file, int line, const LineInfo* LI, const char* Format, ...) attribute ((format (printf, 4, 5))); +#define LINote(...) LINote_(__FILE__, __LINE__, __VA_ARGS__) /* Print a note message with the line info given explicitly */ -void _PPNote (const char *file, int line, const char* Format, ...) attribute ((format (printf, 3, 4))); -#define PPNote(...) _PPNote(__FILE__, __LINE__, __VA_ARGS__) +void PPNote_ (const char *file, int line, const char* Format, ...) attribute ((format (printf, 3, 4))); +#define PPNote(...) PPNote_(__FILE__, __LINE__, __VA_ARGS__) /* Print a note message. For use within the preprocessor */ unsigned GetTotalErrors (void); From bae58ae419d369a140e275009fe991b11a978f4d Mon Sep 17 00:00:00 2001 From: Bob Andrews <mrdudz@users.noreply.github.com> Date: Tue, 17 Jun 2025 20:29:01 +0200 Subject: [PATCH 57/60] Update cbm264.h - fix misunderstanding about TGI colors --- include/cbm264.h | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/include/cbm264.h b/include/cbm264.h index 82ecdc4d8..c220bf407 100644 --- a/include/cbm264.h +++ b/include/cbm264.h @@ -110,25 +110,23 @@ #define COLOR_LIGHTBLUE (BCOLOR_LIGHTBLUE | CATTR_LUMA7) #define COLOR_GRAY3 (BCOLOR_WHITE | CATTR_LUMA5) -/* TGI color defines (these are indices into the default palette) */ -#define TGI_COLOR_BLACK 0 -#define TGI_COLOR_WHITE 1 -/* -#define TGI_COLOR_RED 2 -#define TGI_COLOR_CYAN 3 -#define TGI_COLOR_PURPLE 4 -#define TGI_COLOR_GREEN 5 -#define TGI_COLOR_BLUE 6 -#define TGI_COLOR_YELLOW 7 -#define TGI_COLOR_ORANGE 8 -#define TGI_COLOR_BROWN 9 -#define TGI_COLOR_LIGHTRED 10 -#define TGI_COLOR_GRAY1 11 -#define TGI_COLOR_GRAY2 12 -#define TGI_COLOR_LIGHTGREEN 13 -#define TGI_COLOR_LIGHTBLUE 14 -#define TGI_COLOR_GRAY3 15 -*/ +/* TGI color defines */ +#define TGI_COLOR_BLACK (BCOLOR_BLACK) +#define TGI_COLOR_WHITE (BCOLOR_WHITE | CATTR_LUMA7) +#define TGI_COLOR_RED (BCOLOR_RED | CATTR_LUMA4) +#define TGI_COLOR_CYAN (BCOLOR_CYAN | CATTR_LUMA7) +#define TGI_COLOR_PURPLE (BCOLOR_LIGHTVIOLET | CATTR_LUMA7) +#define TGI_COLOR_GREEN (BCOLOR_GREEN | CATTR_LUMA7) +#define TGI_COLOR_BLUE (BCOLOR_BLUE | CATTR_LUMA7) +#define TGI_COLOR_YELLOW (BCOLOR_YELLOW | CATTR_LUMA7) +#define TGI_COLOR_ORANGE (BCOLOR_ORANGE | CATTR_LUMA7) +#define TGI_COLOR_BROWN (BCOLOR_BROWN | CATTR_LUMA7) +#define TGI_COLOR_LIGHTRED (BCOLOR_RED | CATTR_LUMA7) +#define TGI_COLOR_GRAY1 (BCOLOR_WHITE | CATTR_LUMA1) +#define TGI_COLOR_GRAY2 (BCOLOR_WHITE | CATTR_LUMA3) +#define TGI_COLOR_LIGHTGREEN (BCOLOR_LIGHTGREEN | CATTR_LUMA7) +#define TGI_COLOR_LIGHTBLUE (BCOLOR_LIGHTBLUE | CATTR_LUMA7) +#define TGI_COLOR_GRAY3 (BCOLOR_WHITE | CATTR_LUMA5) /* Masks for joy_read */ #define JOY_UP_MASK 0x01 From 0b0bead6348b8e03cbe47fe3a57861676895dd5d Mon Sep 17 00:00:00 2001 From: Bob Andrews <mrdudz@users.noreply.github.com> Date: Tue, 17 Jun 2025 20:29:41 +0200 Subject: [PATCH 58/60] Update tgidemo.c - fix misunderstanding about TGI colors --- samples/tgidemo.c | 45 +++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/samples/tgidemo.c b/samples/tgidemo.c index 132697182..cdb4c3ad9 100644 --- a/samples/tgidemo.c +++ b/samples/tgidemo.c @@ -13,10 +13,9 @@ #endif -/* TGI colors are indices into the default palette. So keep in mind that, if - you redefine the palette, those names may no more match the actual colors. */ -#define COLOR_BACK TGI_COLOR_BLACK -#define COLOR_FORE TGI_COLOR_WHITE +/* Color values passed to TGI functions are indices into the default palette. */ +#define COLOR_BACK 0 +#define COLOR_FORE 1 /*****************************************************************************/ @@ -69,35 +68,30 @@ static void DoWarning (void) /* - * Note that everywhere else in the TGI API, colors are referred to via TGI_COLOR_ - * color indices, which in turn refer to the default TGI palette. + * Note that everywhere else in the TGI API, colors are referred to via an index + * to the current palette. * - * Redefining the colors (changing the palette) is a target dependend operation, - * and the colors/values in the palette itself are not portable. - * - * That said, for some (perhaps most?) targets, the COLOR_ values may work here. + * TGI_COLOR_ values can be used (ONLY!) for setting the palette, using them + * with other TGI functions only works by chance, on some targets. */ static void DoPalette (int n) { static const unsigned char Palette[4][2] = { /* FIXME: add some ifdefs with proper values for targets that need it */ #if !defined(__APPLE2__) - { COLOR_BLACK, COLOR_BLUE }, - { COLOR_WHITE, COLOR_BLACK }, - { COLOR_RED, COLOR_BLACK }, - { COLOR_BLACK, COLOR_WHITE } + { TGI_COLOR_BLACK, TGI_COLOR_BLUE }, + { TGI_COLOR_WHITE, TGI_COLOR_BLACK }, + { TGI_COLOR_RED, TGI_COLOR_BLACK }, #else - { COLOR_WHITE, COLOR_BLACK }, - { COLOR_BLACK, COLOR_WHITE }, - { COLOR_WHITE, COLOR_BLACK }, - { COLOR_BLACK, COLOR_WHITE } + { TGI_COLOR_WHITE, TGI_COLOR_BLACK }, + { TGI_COLOR_BLACK, TGI_COLOR_WHITE }, + { TGI_COLOR_WHITE, TGI_COLOR_BLACK }, #endif }; tgi_setpalette (Palette[n]); } - static void DoCircles (void) { unsigned char I; @@ -117,7 +111,9 @@ static void DoCircles (void) tgi_ellipse (X, Y, I, tgi_imulround (I, AspectRatio)); } } - + while (kbhit ()) { + cgetc (); + } cgetc (); } @@ -186,6 +182,9 @@ static void DoDiagram (void) tgi_lineto (XOrigin + X, YOrigin + Y); } + while (kbhit ()) { + cgetc (); + } cgetc (); } @@ -206,6 +205,9 @@ static void DoLines (void) tgi_line (Min, Min, Min-X, 0); } + while (kbhit ()) { + cgetc (); + } cgetc (); } @@ -241,8 +243,7 @@ int main (void) /* Do graphics stuff */ - /* first uses the default palette */ - DoCircles (); + /* use default palette */ DoCircles (); DoPalette (0); DoCheckerboard (); DoPalette (1); DoDiagram (); DoPalette (2); DoLines (); From 5a3aa1fd51d6509515c63382f3215021914dbd68 Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Tue, 17 Jun 2025 23:34:23 +0200 Subject: [PATCH 59/60] fix/add missing .ifp02x and .p02x pseudo ops, update test --- doc/ca65.sgml | 18 +++ src/ca65/condasm.c | 11 ++ src/ca65/pseudo.c | 190 +++++++++++++------------ src/ca65/scanner.c | 2 + src/ca65/token.h | 2 + test/asm/cpudetect/6502x-cpudetect.ref | Bin 29 -> 31 bytes test/asm/cpudetect/cpudetect.s | 14 ++ 7 files changed, 148 insertions(+), 89 deletions(-) diff --git a/doc/ca65.sgml b/doc/ca65.sgml index 80224a84e..a12a4accb 100644 --- a/doc/ca65.sgml +++ b/doc/ca65.sgml @@ -3234,6 +3234,12 @@ See: <tt><ref id=".ASCIIZ" name=".ASCIIZ"></tt>,<tt><ref id=".CHARMAP" name=".CH (see <tt><ref id=".P02" name=".P02"></tt> command). +<sect1><tt>.IFP02X</tt><label id=".IFP02X"><p> + + Conditional assembly: Check if the assembler is currently in 6502X mode + (see <tt><ref id=".P02X" name=".P02X"></tt> command). + + <sect1><tt>.IFP4510</tt><label id=".IFP4510"><p> Conditional assembly: Check if the assembler is currently in 4510 mode @@ -3621,6 +3627,16 @@ See: <tt><ref id=".ASCIIZ" name=".ASCIIZ"></tt>,<tt><ref id=".BYTE" name=".BYTE" <tt><ref id=".P4510" name=".P4510"></tt> +<sect1><tt>.P02X</tt><label id=".P02X"><p> + + Enable the 6502X instruction set, disable 65SC02, 65C02 and 65816 + instructions. + + See: <tt><ref id=".PC02" name=".PC02"></tt>, <tt><ref id=".PSC02" + name=".PSC02"></tt>, <tt><ref id=".P816" name=".P816"></tt> and + <tt><ref id=".P4510" name=".P4510"></tt> + + <sect1><tt>.P4510</tt><label id=".P4510"><p> Enable the 4510 instruction set. This is a superset of the 65C02 and @@ -4016,11 +4032,13 @@ See: <tt><ref id=".ASCIIZ" name=".ASCIIZ"></tt>,<tt><ref id=".BYTE" name=".BYTE" See: <tt><ref id=".CPU" name=".CPU"></tt>, <tt><ref id=".IFP02" name=".IFP02"></tt>, + <tt><ref id=".IFP02X" name=".IFP02X"></tt>, <tt><ref id=".IFPDTV" name=".IFPDTV"></tt>, <tt><ref id=".IFP816" name=".IFP816"></tt>, <tt><ref id=".IFPC02" name=".IFPC02"></tt>, <tt><ref id=".IFPSC02" name=".IFPSC02"></tt>, <tt><ref id=".P02" name=".P02"></tt>, + <tt><ref id=".P02X" name=".P02X"></tt>, <tt><ref id=".P816" name=".P816"></tt>, <tt><ref id=".P4510" name=".P4510"></tt>, <tt><ref id=".PC02" name=".PC02"></tt>, diff --git a/src/ca65/condasm.c b/src/ca65/condasm.c index f872ec9ed..60e8ab0c1 100644 --- a/src/ca65/condasm.c +++ b/src/ca65/condasm.c @@ -394,6 +394,16 @@ void DoConditionals (void) CalcOverallIfCond (); break; + case TOK_IFP02X: + D = AllocIf (".IFP02X", 1); + NextTok (); + if (IfCond) { + SetIfCond (D, GetCPU() == CPU_6502X); + } + ExpectSep (); + CalcOverallIfCond (); + break; + case TOK_IFP4510: D = AllocIf (".IFP4510", 1); NextTok (); @@ -485,6 +495,7 @@ int CheckConditionals (void) case TOK_IFNDEF: case TOK_IFNREF: case TOK_IFP02: + case TOK_IFP02X: case TOK_IFP4510: case TOK_IFP816: case TOK_IFPC02: diff --git a/src/ca65/pseudo.c b/src/ca65/pseudo.c index 2ce1ae087..37dcd78da 100644 --- a/src/ca65/pseudo.c +++ b/src/ca65/pseudo.c @@ -1562,6 +1562,14 @@ static void DoP02 (void) +static void DoP02X (void) +/* Switch to 6502 CPU */ +{ + SetCPU (CPU_6502X); +} + + + static void DoPC02 (void) /* Switch to 65C02 CPU */ { @@ -2057,70 +2065,72 @@ struct CtrlDesc { void (*Handler) (void); /* Command handler */ }; +/* NOTE: .AND, .BITAND, .BITNOT, .BITOR, .BITXOR, .MOD, .NOT, .OR, .SHL, .SHR + and .XOR do NOT go into this table */ #define PSEUDO_COUNT (sizeof (CtrlCmdTab) / sizeof (CtrlCmdTab [0])) static CtrlDesc CtrlCmdTab [] = { - { ccNone, DoA16 }, - { ccNone, DoA8 }, + { ccNone, DoA16 }, /* .A16 */ + { ccNone, DoA8 }, /* .A8 */ { ccNone, DoAddr }, /* .ADDR */ { ccNone, DoUnexpected }, /* .ADDRSIZE */ - { ccNone, DoAlign }, - { ccNone, DoASCIIZ }, + { ccNone, DoAlign }, /* .ALIGN */ + { ccNone, DoASCIIZ }, /* .ASCIIZ */ { ccNone, DoUnexpected }, /* .ASIZE */ - { ccNone, DoAssert }, - { ccNone, DoAutoImport }, + { ccNone, DoAssert }, /* .ASSERT */ + { ccNone, DoAutoImport }, /* .AUTOIMPORT */ { ccNone, DoUnexpected }, /* .BANK */ { ccNone, DoUnexpected }, /* .BANKBYTE */ - { ccNone, DoBankBytes }, + { ccNone, DoBankBytes }, /* .BANKBYTES */ { ccNone, DoUnexpected }, /* .BLANK */ - { ccNone, DoBss }, - { ccNone, DoByte }, - { ccNone, DoCase }, - { ccNone, DoCharMap }, - { ccNone, DoCode }, + { ccNone, DoBss }, /* .BSS */ + { ccNone, DoByte }, /* .BYT, .BYTE */ + { ccNone, DoCase }, /* .CASE */ + { ccNone, DoCharMap }, /* .CHARMAP */ + { ccNone, DoCode }, /* .CODE */ { ccNone, DoUnexpected, }, /* .CONCAT */ - { ccNone, DoConDes }, + { ccNone, DoConDes }, /* .CONDES */ { ccNone, DoUnexpected }, /* .CONST */ - { ccNone, DoConstructor }, + { ccNone, DoConstructor }, /* .CONSTRUCTOR */ { ccNone, DoUnexpected }, /* .CPU */ - { ccNone, DoData }, - { ccNone, DoDbg, }, - { ccNone, DoDByt }, - { ccNone, DoDebugInfo }, - { ccKeepToken, DoDefine }, + { ccNone, DoData }, /* .DATA */ + { ccNone, DoDbg, }, /* .DBG */ + { ccNone, DoDByt }, /* .DBYT */ + { ccNone, DoDebugInfo }, /* .DEBUGINFO */ + { ccKeepToken, DoDefine }, /* .DEF, .DEFINE */ { ccNone, DoUnexpected }, /* .DEFINED */ { ccNone, DoUnexpected }, /* .DEFINEDMACRO */ - { ccNone, DoDelMac }, - { ccNone, DoDestructor }, - { ccNone, DoDWord }, + { ccNone, DoDelMac }, /* .DELMAC, .DELMACRO */ + { ccNone, DoDestructor }, /* .DESTRUCTOR */ + { ccNone, DoDWord }, /* .DWORD */ { ccKeepToken, DoConditionals }, /* .ELSE */ { ccKeepToken, DoConditionals }, /* .ELSEIF */ - { ccKeepToken, DoEnd }, + { ccKeepToken, DoEnd }, /* .END */ { ccNone, DoUnexpected }, /* .ENDENUM */ { ccKeepToken, DoConditionals }, /* .ENDIF */ - { ccNone, DoUnexpected }, /* .ENDMACRO */ - { ccNone, DoEndProc }, - { ccNone, DoUnexpected }, /* .ENDREPEAT */ - { ccNone, DoEndScope }, + { ccNone, DoUnexpected }, /* .ENDMAC, .ENDMACRO */ + { ccNone, DoEndProc }, /* .ENDPROC */ + { ccNone, DoUnexpected }, /* .ENDREP, .ENDREPEAT */ + { ccNone, DoEndScope }, /* .ENDSCOPE */ { ccNone, DoUnexpected }, /* .ENDSTRUCT */ { ccNone, DoUnexpected }, /* .ENDUNION */ - { ccNone, DoEnum }, - { ccNone, DoError }, - { ccNone, DoExitMacro }, - { ccNone, DoExport }, - { ccNone, DoExportZP }, - { ccNone, DoFarAddr }, - { ccNone, DoFatal }, - { ccNone, DoFeature }, - { ccNone, DoFileOpt }, - { ccNone, DoForceImport }, + { ccNone, DoEnum }, /* .ENUM */ + { ccNone, DoError }, /* .ERROR */ + { ccNone, DoExitMacro }, /* .EXITMAC, .EXITMACRO */ + { ccNone, DoExport }, /* .EXPORT */ + { ccNone, DoExportZP }, /* .EXPORTZP */ + { ccNone, DoFarAddr }, /* .FARADDR */ + { ccNone, DoFatal }, /* .FATAL */ + { ccNone, DoFeature }, /* .FEATURE */ + { ccNone, DoFileOpt }, /* .FOPT, .FILEOPT */ + { ccNone, DoForceImport }, /* .FORCEIMPORT */ { ccNone, DoUnexpected }, /* .FORCEWORD */ - { ccNone, DoGlobal }, - { ccNone, DoGlobalZP }, + { ccNone, DoGlobal }, /* .GLOBAL */ + { ccNone, DoGlobalZP }, /* .GLOBALZP */ { ccNone, DoUnexpected }, /* .HIBYTE */ - { ccNone, DoHiBytes }, + { ccNone, DoHiBytes }, /* .HIBYTES */ { ccNone, DoUnexpected }, /* .HIWORD */ - { ccNone, DoI16 }, - { ccNone, DoI8 }, + { ccNone, DoI16 }, /* .I16 */ + { ccNone, DoI8 }, /* .I8 */ { ccNone, DoUnexpected }, /* .IDENT */ { ccKeepToken, DoConditionals }, /* .IF */ { ccKeepToken, DoConditionals }, /* .IFBLANK */ @@ -2131,81 +2141,83 @@ static CtrlDesc CtrlCmdTab [] = { { ccKeepToken, DoConditionals }, /* .IFNDEF */ { ccKeepToken, DoConditionals }, /* .IFNREF */ { ccKeepToken, DoConditionals }, /* .IFP02 */ + { ccKeepToken, DoConditionals }, /* .IFP02X */ { ccKeepToken, DoConditionals }, /* .IFP4510 */ { ccKeepToken, DoConditionals }, /* .IFP816 */ { ccKeepToken, DoConditionals }, /* .IFPC02 */ { ccKeepToken, DoConditionals }, /* .IFPDTV */ { ccKeepToken, DoConditionals }, /* .IFPSC02 */ { ccKeepToken, DoConditionals }, /* .IFREF */ - { ccNone, DoImport }, - { ccNone, DoImportZP }, - { ccNone, DoIncBin }, - { ccNone, DoInclude }, - { ccNone, DoInterruptor }, + { ccNone, DoImport }, /* .IMPORT */ + { ccNone, DoImportZP }, /* .IMPORTZP */ + { ccNone, DoIncBin }, /* .INCBIN */ + { ccNone, DoInclude }, /* .INCLUDE */ + { ccNone, DoInterruptor }, /* .INTERRUPTPOR */ { ccNone, DoUnexpected }, /* .ISIZE */ { ccNone, DoUnexpected }, /* .ISMNEMONIC */ { ccNone, DoInvalid }, /* .LEFT */ - { ccNone, DoLineCont }, - { ccNone, DoList }, - { ccNone, DoListBytes }, - { ccNone, DoLiteral }, + { ccNone, DoLineCont }, /* .LINECONT */ + { ccNone, DoList }, /* .LIST */ + { ccNone, DoListBytes }, /* .LISTBYTES */ + { ccNone, DoLiteral }, /* .LITERAL */ { ccNone, DoUnexpected }, /* .LOBYTE */ - { ccNone, DoLoBytes }, + { ccNone, DoLoBytes }, /* .LOBYTES */ { ccNone, DoUnexpected }, /* .LOCAL */ - { ccNone, DoLocalChar }, + { ccNone, DoLocalChar }, /* .LOCALCHAR */ { ccNone, DoUnexpected }, /* .LOWORD */ - { ccNone, DoMacPack }, - { ccNone, DoMacro }, + { ccNone, DoMacPack }, /* .MACPACK */ + { ccNone, DoMacro }, /* .MAC, .MACRO */ { ccNone, DoUnexpected }, /* .MATCH */ { ccNone, DoUnexpected }, /* .MAX */ { ccNone, DoInvalid }, /* .MID */ { ccNone, DoUnexpected }, /* .MIN */ - { ccNone, DoNull }, - { ccNone, DoOrg }, - { ccNone, DoOut }, - { ccNone, DoP02 }, - { ccNone, DoP4510 }, - { ccNone, DoP816 }, - { ccNone, DoPageLength }, + { ccNone, DoNull }, /* .NULL */ + { ccNone, DoOrg }, /* .ORG */ + { ccNone, DoOut }, /* .OUT */ + { ccNone, DoP02 }, /* .P02 */ + { ccNone, DoP02X }, /* .P02X */ + { ccNone, DoP4510 }, /* .P4510 */ + { ccNone, DoP816 }, /* .P816 */ + { ccNone, DoPageLength }, /* .PAGELEN, .PAGELENGTH */ { ccNone, DoUnexpected }, /* .PARAMCOUNT */ - { ccNone, DoPC02 }, - { ccNone, DoPDTV }, - { ccNone, DoPopCharmap }, - { ccNone, DoPopCPU }, - { ccNone, DoPopSeg }, - { ccNone, DoProc }, - { ccNone, DoPSC02 }, - { ccNone, DoPushCharmap }, - { ccNone, DoPushCPU }, - { ccNone, DoPushSeg }, - { ccNone, DoUnexpected }, /* .REFERENCED */ - { ccNone, DoReferTo }, /* .REFERTO */ - { ccNone, DoReloc }, - { ccNone, DoRepeat }, - { ccNone, DoRes }, + { ccNone, DoPC02 }, /* .PSC02 */ + { ccNone, DoPDTV }, /* .PDTV */ + { ccNone, DoPopCharmap }, /* .POPCHARMAP */ + { ccNone, DoPopCPU }, /* .POPCPU */ + { ccNone, DoPopSeg }, /* .POPSEG */ + { ccNone, DoProc }, /* .PROC */ + { ccNone, DoPSC02 }, /* .PSC02 */ + { ccNone, DoPushCharmap }, /* .PUSHCHARMAP */ + { ccNone, DoPushCPU }, /* .PUSHCPU */ + { ccNone, DoPushSeg }, /* .PUSHSEG */ + { ccNone, DoUnexpected }, /* .REF, .REFERENCED */ + { ccNone, DoReferTo }, /* .REFTO, .REFERTO */ + { ccNone, DoReloc }, /* .RELOC */ + { ccNone, DoRepeat }, /* .REPEAT */ + { ccNone, DoRes }, /* .RES */ { ccNone, DoInvalid }, /* .RIGHT */ - { ccNone, DoROData }, - { ccNone, DoScope }, - { ccNone, DoSegment }, + { ccNone, DoROData }, /* .RODATA */ + { ccNone, DoScope }, /* .SCOPE */ + { ccNone, DoSegment }, /* .SEGMENT */ { ccNone, DoUnexpected }, /* .SET */ - { ccNone, DoSetCPU }, + { ccNone, DoSetCPU }, /* .SETCPU */ { ccNone, DoUnexpected }, /* .SIZEOF */ - { ccNone, DoSmart }, + { ccNone, DoSmart }, /* .SMART */ { ccNone, DoUnexpected }, /* .SPRINTF */ { ccNone, DoUnexpected }, /* .STRAT */ { ccNone, DoUnexpected }, /* .STRING */ { ccNone, DoUnexpected }, /* .STRLEN */ - { ccNone, DoStruct }, - { ccNone, DoTag }, + { ccNone, DoStruct }, /* .STRUCT */ + { ccNone, DoTag }, /* .TAG */ { ccNone, DoUnexpected }, /* .TCOUNT */ { ccNone, DoUnexpected }, /* .TIME */ - { ccKeepToken, DoUnDef }, - { ccNone, DoUnion }, + { ccKeepToken, DoUnDef }, /* .UNDEF, .UNDEFINE */ + { ccNone, DoUnion }, /* .UNION */ { ccNone, DoUnexpected }, /* .VERSION */ - { ccNone, DoWarning }, - { ccNone, DoWord }, + { ccNone, DoWarning }, /* .WARNING */ + { ccNone, DoWord }, /* .WORD */ { ccNone, DoUnexpected }, /* .XMATCH */ - { ccNone, DoZeropage }, + { ccNone, DoZeropage }, /* .ZEROPAGE */ }; diff --git a/src/ca65/scanner.c b/src/ca65/scanner.c index 94c84d897..157702897 100644 --- a/src/ca65/scanner.c +++ b/src/ca65/scanner.c @@ -221,6 +221,7 @@ struct DotKeyword { { ".IFNDEF", TOK_IFNDEF }, { ".IFNREF", TOK_IFNREF }, { ".IFP02", TOK_IFP02 }, + { ".IFP02X", TOK_IFP02X }, { ".IFP4510", TOK_IFP4510 }, { ".IFP816", TOK_IFP816 }, { ".IFPC02", TOK_IFPC02 }, @@ -259,6 +260,7 @@ struct DotKeyword { { ".ORG", TOK_ORG }, { ".OUT", TOK_OUT }, { ".P02", TOK_P02 }, + { ".P02X", TOK_P02X }, { ".P4510", TOK_P4510 }, { ".P816", TOK_P816 }, { ".PAGELEN", TOK_PAGELENGTH }, diff --git a/src/ca65/token.h b/src/ca65/token.h index 8f935f7a1..aeae7166a 100644 --- a/src/ca65/token.h +++ b/src/ca65/token.h @@ -193,6 +193,7 @@ typedef enum token_t { TOK_IFNDEF, TOK_IFNREF, TOK_IFP02, + TOK_IFP02X, TOK_IFP4510, TOK_IFP816, TOK_IFPC02, @@ -226,6 +227,7 @@ typedef enum token_t { TOK_ORG, TOK_OUT, TOK_P02, + TOK_P02X, TOK_P4510, TOK_P816, TOK_PAGELENGTH, diff --git a/test/asm/cpudetect/6502x-cpudetect.ref b/test/asm/cpudetect/6502x-cpudetect.ref index 3434ecbea7fb1e119879fae346989933fd09bacd..9e7abe573ffc65dce67d2b8b95d1c3ef9827bd71 100644 GIT binary patch delta 7 Ocmb1@XIlMgf-C?CJpzFM literal 29 ZcmZQ@4hW6+40a8PH#0RbVnE?V0042#2dMx6 diff --git a/test/asm/cpudetect/cpudetect.s b/test/asm/cpudetect/cpudetect.s index 7b2363b7f..6ee07ae3c 100644 --- a/test/asm/cpudetect/cpudetect.s +++ b/test/asm/cpudetect/cpudetect.s @@ -8,6 +8,10 @@ lda #$ea .endif +.ifp02x + lax #$ea +.endif + .ifpsc02 jmp ($1234,x) .endif @@ -72,3 +76,13 @@ .byte 0,"CPU_ISET_6502DTV" .endif + +; step 3: switch through all supported cpus to verify the pseudo-op is there + +.p02 +.p02X +.psc02 +.pc02 +.p816 +.p4510 +.pdtv From 4daba00d4780524d998e95faf93c74cb4e3a7d38 Mon Sep 17 00:00:00 2001 From: mrdudz <mrdudz@users.noreply.github.com> Date: Wed, 18 Jun 2025 00:28:53 +0200 Subject: [PATCH 60/60] don't make script choke with more than 9 tables --- .github/checks/sorted.sh | 4 ++-- .github/checks/sorted_codeopt.sh | 4 ++-- .github/checks/sorted_opcodes.sh | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/checks/sorted.sh b/.github/checks/sorted.sh index 0a4a90db7..4f53b0484 100755 --- a/.github/checks/sorted.sh +++ b/.github/checks/sorted.sh @@ -13,8 +13,8 @@ function checkarray_quoted_name START="\\/\\* BEGIN SORTED.SH \\*\\/" END="\\/\\* END SORTED.SH \\*\\/" - awk '/'"$START"'/{flag=1; count++; next} /'"$END"'/{flag=0;} flag {print count,"##",$0}' "$CHECK_FILE" | \ - sed -e 's:\(.*\) ##.*\"\(.*\)\".*:\1##\2:g' > .a.tmp + awk '/'"$START"'/{flag=1; count++; next} /'"$END"'/{flag=0;} flag {printf("%04d##%s\n", count, $0)}' "$CHECK_FILE" | \ + sed -e 's:\(.*\)##.*\"\(.*\)\".*:\1##\2:g' > .a.tmp if [[ -z $(grep '[^[:space:]]' .a.tmp) ]] ; then echo "error: "$1" table is empty" diff --git a/.github/checks/sorted_codeopt.sh b/.github/checks/sorted_codeopt.sh index e90e32b4a..c78662b9d 100755 --- a/.github/checks/sorted_codeopt.sh +++ b/.github/checks/sorted_codeopt.sh @@ -13,7 +13,7 @@ function checkarray START="\\/\\* BEGIN DECL SORTED_CODEOPT.SH \\*\\/" END="\\/\\* END DECL SORTED_CODEOPT.SH \\*\\/" - awk '/'"$START"'/{flag=1; count++; next} /'"$END"'/{flag=0;} flag {print count,"##",$0}' "$CHECK_FILE" | \ + awk '/'"$START"'/{flag=1; count++; next} /'"$END"'/{flag=0;} flag {printf("%04d##%s\n", count, $0)}' "$CHECK_FILE" | \ sed -e 's:\(.*##\).*"\(.*\)",.*:\1\2:g' > .a.tmp if [[ -z $(grep '[^[:space:]]' .a.tmp) ]] ; then @@ -33,7 +33,7 @@ function checkarray START="\\/\\* BEGIN SORTED_CODEOPT.SH \\*\\/" END="\\/\\* END SORTED_CODEOPT.SH \\*\\/" - awk '/'"$START"'/{flag=1; count++; next} /'"$END"'/{flag=0;} flag {print count,"##",$0}' "$CHECK_FILE" | \ + awk '/'"$START"'/{flag=1; count++; next} /'"$END"'/{flag=0;} flag {printf("%04d##%s\n", count, $0)}' "$CHECK_FILE" | \ sed -e 's:\(.*##\).*&D\(.*\),.*:\1\2:g' > .b.tmp if [[ -z $(grep '[^[:space:]]' .b.tmp) ]] ; then diff --git a/.github/checks/sorted_opcodes.sh b/.github/checks/sorted_opcodes.sh index b18b841c8..3e45ea752 100755 --- a/.github/checks/sorted_opcodes.sh +++ b/.github/checks/sorted_opcodes.sh @@ -13,10 +13,10 @@ function checkarray_quoted_name START="\\/\\* BEGIN SORTED_OPCODES.SH \\*\\/" END="\\/\\* END SORTED_OPCODES.SH \\*\\/" - awk '/'"$START"'/{flag=1; count++; next} /'"$END"'/{flag=0;} flag {print count,"##",$0}' "$CHECK_FILE" | \ + awk '/'"$START"'/{flag=1; count++; next} /'"$END"'/{flag=0;} flag {printf("%04d##%s\n", count, $0)}' "$CHECK_FILE" | \ sed 's:/\*.*::g' | \ grep '".*",' | \ - sed -e 's:\(.*\) ##.*\"\(.*\)\".*:\1##\2:g' > .a.tmp + sed -e 's:\(.*\)##.*\"\(.*\)\".*:\1##\2:g' > .a.tmp if [[ -z $(grep '[^[:space:]]' .a.tmp) ]] ; then echo "error: "$1" table is empty"