From 0f4f1efb41c9bda81e212445d1f50ad4ec8e0ffd Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Tue, 13 Feb 2024 19:00:47 +0100 Subject: [PATCH 01/39] added switch for 40/80 columns for Apple ][ --- src/arch/apple2e/apple2e.S | 38 ++++++++++++++++++++++++++++++++++++-- src/arch/apple2e/build.py | 2 ++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/arch/apple2e/apple2e.S b/src/arch/apple2e/apple2e.S index 2b96fa4a..06d2b28f 100644 --- a/src/arch/apple2e/apple2e.S +++ b/src/arch/apple2e/apple2e.S @@ -57,6 +57,28 @@ dma: .word 0 disk_sixes_buffer = 0x300 track_buffer = 0xd000 +//#define APPLE2 +//#define APPLE2PLUS +//#define APPLE2EUROPLUS +//#define APPLE2JPLUS +//#define APPLE2E +//#define APPLE2EENHANCED +//#define APPLE2C +//#define APPLE2GS + +#define TTY_MODE_40COLUMNS 1 +#define TTY_MODE_80COLUMNS 2 +#if defined APPLE2GS || defined APPLE2EENHANCED || defined APPLE2E +#define TTY_MODE TTY_MODE_80COLUMNS +SCREEN_WIDTH = 80 +#elif defined APPLE2C || defined APPLE2JPLUS || defined APPLE2EUROPLUS || defined APPLE2PLUS || defined APPLE2 +#define TTY_MODE TTY_MODE_40COLUMNS +SCREEN_WIDTH = 40 +#else +#error Unknown Apple II model +#endif +SCREEN_HEIGHT = 24 + ; --- Initialisation code --------------------------------------------------- ; Boot sector and relocator. Loaded at 0x0800 when the disk boots. Called once @@ -67,9 +89,11 @@ _start: cli lda MEM_BANKING+0xb ; R/W 0xe000 RAM; bank 1 in 0xd000 lda MEM_BANKING+0xb ; yes, I'm sure +#if TTY_MODE == TTY_MODE_80COLUMNS sta SCREEN_80COLON sta SCREEN_80STOREON sta SCREEN_PAGE2OFF +#endif ldx #0xff txs ; reset stack @@ -275,7 +299,7 @@ zproc tty_conout inc cursorx lda cursorx - cmp #80 + cmp #SCREEN_WIDTH zif_eq lda #0 sta cursorx @@ -287,7 +311,7 @@ zendproc zproc write_nl inc cursory lda cursory - cmp #24 + cmp #SCREEN_HEIGHT zif_eq dec cursory jmp scroll_up @@ -311,10 +335,12 @@ zproc scroll_up ldy #39 zrepeat +#if TTY_MODE == TTY_MODE_80COLUMNS sta SCREEN_PAGE2OFF lda (ptr), y sta (ptr1), y sta SCREEN_PAGE2ON +#endif lda (ptr), y sta (ptr1), y dey @@ -326,9 +352,11 @@ zproc scroll_up ldy #39 lda #32|0x80 zrepeat +#if TTY_MODE == TTY_MODE_80COLUMNS sta SCREEN_PAGE2OFF sta (ptr), y sta SCREEN_PAGE2ON +#endif sta (ptr), y dey zuntil_mi @@ -342,13 +370,17 @@ zproc prepare_for_screen_write lda cursory jsr calculate_screen_address lda cursorx +#if TTY_MODE == TTY_MODE_80COLUMNS lsr a +#endif tay lda #0 rol eor #1 tax +#if TTY_MODE == TTY_MODE_80COLUMNS sta SCREEN_PAGE2OFF, x +#endif rts zendproc @@ -392,9 +424,11 @@ zproc clear_screen lda #32|0x80 zrepeat dey +#if TTY_MODE == TTY_MODE_80COLUMNS sta SCREEN_PAGE2ON sta (ptr), y sta SCREEN_PAGE2OFF +#endif sta (ptr), y zuntil_eq diff --git a/src/arch/apple2e/build.py b/src/arch/apple2e/build.py index c20484bb..323faba9 100644 --- a/src/arch/apple2e/build.py +++ b/src/arch/apple2e/build.py @@ -12,6 +12,8 @@ llvmcfile( name="bios_obj", srcs=["./apple2e.S"], +# cflags=["-DAPPLE2E"], + cflags=["-DAPPLE2PLUS"], deps=["include", "src/lib+bioslib"], ) From 5586f592f5b99790f3f60a3beb51b3e6e4f6dd72 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Tue, 13 Feb 2024 19:21:09 +0100 Subject: [PATCH 02/39] added a preliminary screen driver for Apple ][ --- src/arch/apple2e/apple2e.S | 262 +++++++++++++++++++++++++++++++++++-- src/arch/apple2e/build.py | 7 +- 2 files changed, 256 insertions(+), 13 deletions(-) diff --git a/src/arch/apple2e/apple2e.S b/src/arch/apple2e/apple2e.S index 06d2b28f..218eb15a 100644 --- a/src/arch/apple2e/apple2e.S +++ b/src/arch/apple2e/apple2e.S @@ -6,6 +6,7 @@ #include "cpm65.inc" #include "wait.inc" #include "driver.inc" +#include "jumptables.inc" SCREEN_80STOREOFF = 0xc000 SCREEN_80STOREON = 0xc001 @@ -94,6 +95,8 @@ _start: sta SCREEN_80STOREON sta SCREEN_PAGE2OFF #endif + lda #1 + sta cursorvisible ldx #0xff txs ; reset stack @@ -239,13 +242,206 @@ zproc bios_SETBANK rts zendproc +; --- SCREEN driver --------------------------------------------------------- + +defdriver SCREEN, DRVID_SCREEN, drvstrat_SCREEN, 0 + +; SCREEN driver strategy routine. +; Y=SCREEN opcode. +zproc drvstrat_SCREEN + jmpdispatch screen_jmptable_lo, screen_jmptable_hi + +screen_jmptable_lo: + jmptablo screen_version + jmptablo screen_getsize + jmptablo screen_clear + jmptablo screen_setcursor + jmptablo screen_getcursor + jmptablo screen_putchar + jmptablo screen_putstring + jmptablo screen_getchar + jmptablo screen_showcursor + jmptablo screen_scrollup + jmptablo screen_scrolldown + jmptablo screen_cleartoeol +; jmptablo screen_setstyle + jmptablo fail +screen_jmptable_hi: + jmptabhi screen_version + jmptabhi screen_getsize + jmptabhi screen_clear + jmptabhi screen_setcursor + jmptabhi screen_getcursor + jmptabhi screen_putchar + jmptabhi screen_putstring + jmptabhi screen_getchar + jmptabhi screen_showcursor + jmptabhi screen_scrollup + jmptabhi screen_scrolldown + jmptabhi screen_cleartoeol +; jmptabhi screen_setstyle + jmptabhi fail +zendproc + +zproc screen_version + lda #0 + rts +zendproc + +zproc screen_getsize + lda #SCREEN_WIDTH-1 + ldx #SCREEN_HEIGHT-1 + rts +zendproc + +zproc screen_clear + jmp clear_screen +zendproc + +zproc screen_setcursor + sta cursorx + stx cursory + rts +zendproc + +zproc screen_getcursor + lda cursorx + ldx cursory + rts +zendproc + +zproc cursor_on + jsr prepare_for_screen_write + lda (ptr), y + sta cursork + ldx cursorvisible + cpx #1 + zif_eq + lda #0x60 ; flashing block + sta (ptr), y + zendif + rts +zendproc + +zproc cursor_off + ;ldx cursorvisible + ;cpx #1 + ;zif_eq + tax + lda cursork + sta (ptr), y + txa + ;zendif + rts +zendproc + +zproc screen_getchar + jsr cursor_on + + ; A,X contain the timeout, TODO: respect timeout + + zrepeat + lda KBD_READ + zuntil_mi + bpl nokey + sta KBD_STROBERESET + and #0x7f + +nokey: + jsr cursor_off + + ; return character in A + ; TODO: carry clear on keyboard event, carry set on timeout? + clc + rts +zendproc + +zproc screen_showcursor + sta cursorvisible + rts +zendproc + +zproc screen_putchar + ; TODO: we have to check how the various machines do this, + ; especially for lower-case characters + ;sec + ;sbc stylemask + jmp tty_conout +zendproc + +zproc screen_putstring + sta ptr1+0 + stx ptr1+1 + zrepeat + ldy #0 + lda (ptr1), y + zbreakif_eq + jsr screen_putchar + inc ptr1+0 + zif_eq + inc ptr1+1 + zendif + zuntil_eq + rts +zendproc + +zproc screen_scrollup + jmp scroll_up +zendproc + +zproc screen_scrolldown + ;~ jmp scroll_down +zendproc + +zproc screen_cleartoeol + lda cursory + jsr calculate_screen_address ; ptr is source pointer + ldy cursorx + lda #32|0x80 + zrepeat +#if TTY_MODE == TTY_MODE_80COLUMNS + sta SCREEN_PAGE2OFF + sta (ptr), y + sta SCREEN_PAGE2ON +#endif + sta (ptr), y + iny + cpy #40 + zuntil_eq + rts +zendproc + +;zproc setcolour +; ; colours, are you kidding? ;-) +; rts +;zendproc + +;zproc screen_setstyle +; ; TODO: see "Using 6502 Assembly Language, appendix A-2" +; ; TODO: see how we handle inverse with lowercase in Apple IIe and clone case +; and #STYLE_REVERSE +; zif_eq +; lda #0x00 +; sta stylemask +; zelse +; lda #0x80 +; sta stylemask +; zendif +; rts +;zendproc + +zproc fail + sec + rts +zendproc + ; --- TTY driver ------------------------------------------------------------ .data .global drvtop drvtop: .word drv_TTY -defdriver TTY, DRVID_TTY, drvstrat_TTY, 0 +defdriver TTY, DRVID_TTY, drvstrat_TTY, drv_SCREEN ; TTY driver strategy routine. ; Y=TTY opcode. @@ -363,6 +559,48 @@ zproc scroll_up rts zendproc +;~ zproc scroll_down + ;~ ldx #22 ; current line + ;~ zrepeat + ;~ txa + ;~ jsr calculate_screen_address + ;~ lda ptr+0 + ;~ sta ptr1+0 + ;~ lda ptr+1 + ;~ sta ptr1+1 ; ptr1 is dest pointer + + ;~ dex + ;~ txa + ;~ jsr calculate_screen_address ; ptr is source pointer + + ;~ ldy #39 + ;~ zrepeat +;~ #if TTY_MODE == TTY_MODE_80COLUMNS + ;~ sta SCREEN_PAGE2OFF + ;~ lda (ptr), y + ;~ sta (ptr1), y + ;~ sta SCREEN_PAGE2ON +;~ #endif + ;~ lda (ptr), y + ;~ sta (ptr1), y + ;~ dey + ;~ zuntil_mi + + ;~ cpx #0 + ;~ zuntil_eq + + ;~ ldy #39 + ;~ lda #32|0x80 + ;~ zrepeat + ;~ ;sta SCREEN_PAGE2OFF + ;~ sta (ptr), y + ;~ ;sta SCREEN_PAGE2ON + ;~ ;sta (ptr), y + ;~ dey + ;~ zuntil_mi + ;~ rts +;~ zendproc + ; Sets ptr to the current cursor row address; also sets up the page stuff. ; Leaves Y to the screen line offset. @@ -474,11 +712,12 @@ zproc tty_conin ; Display the cursor. - jsr prepare_for_screen_write - lda (ptr), y - sta cursork - lda #0x60 ; flashing block - sta (ptr), y + jsr cursor_on + ;~ jsr prepare_for_screen_write + ;~ lda (ptr), y + ;~ sta cursork + ;~ lda #0x60 ; flashing block + ;~ sta (ptr), y ; Wait for the key. @@ -491,10 +730,11 @@ zproc tty_conin ; Cursor off again. - tax - lda cursork - sta (ptr), y - txa + jsr cursor_off + ;~ tax + ;~ lda cursork + ;~ sta (ptr), y + ;~ txa rts zendproc @@ -1129,6 +1369,8 @@ encode_tab: .fill 64 ; must be within one page cursorx: .fill 1 cursory: .fill 1 cursork: .fill 1 +;stylemask: .fill 1 +cursorvisible: .fill 1 current_bank: .fill 1 current_phase: .fill 1 directory_buffer: .fill 128 diff --git a/src/arch/apple2e/build.py b/src/arch/apple2e/build.py index 323faba9..a82e03f3 100644 --- a/src/arch/apple2e/build.py +++ b/src/arch/apple2e/build.py @@ -12,8 +12,8 @@ llvmcfile( name="bios_obj", srcs=["./apple2e.S"], -# cflags=["-DAPPLE2E"], - cflags=["-DAPPLE2PLUS"], + cflags=["-DAPPLE2E"], +# cflags=["-DAPPLE2PLUS"], deps=["include", "src/lib+bioslib"], ) @@ -57,7 +57,8 @@ | MINIMAL_APPS | MINIMAL_APPS_SRCS | BIG_APPS - | BIG_APPS_SRCS, + | BIG_APPS_SRCS + | SCREEN_APPS, ) mametest( From 70a00c21d78b05cd00f3ade4f8c83ca247587a11 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Mon, 19 Feb 2024 21:03:18 +0100 Subject: [PATCH 03/39] moved Apple ][ screen driver to external SCRNDRV.COM, using a common library for shared code (not working) --- src/arch/apple2e/apple2e.S | 466 +------------------------------ src/arch/apple2e/apple2e.inc | 33 +++ src/arch/apple2e/build.py | 26 +- src/arch/apple2e/common.S | 224 +++++++++++++++ src/arch/apple2e/utils/build.py | 12 + src/arch/apple2e/utils/scrndrv.S | 304 ++++++++++++++++++++ 6 files changed, 604 insertions(+), 461 deletions(-) create mode 100644 src/arch/apple2e/apple2e.inc create mode 100644 src/arch/apple2e/common.S create mode 100644 src/arch/apple2e/utils/build.py create mode 100644 src/arch/apple2e/utils/scrndrv.S diff --git a/src/arch/apple2e/apple2e.S b/src/arch/apple2e/apple2e.S index 218eb15a..9a863f93 100644 --- a/src/arch/apple2e/apple2e.S +++ b/src/arch/apple2e/apple2e.S @@ -4,20 +4,11 @@ #include "zif.inc" #include "cpm65.inc" +#include "apple2e.inc" #include "wait.inc" #include "driver.inc" #include "jumptables.inc" -SCREEN_80STOREOFF = 0xc000 -SCREEN_80STOREON = 0xc001 -SCREEN_80COLOFF = 0xc00c -SCREEN_80COLON = 0xc00d -SCREEN_PAGE2OFF = 0xc054 -SCREEN_PAGE2ON = 0xc055 - -KBD_READ = 0xc000 -KBD_STROBERESET = 0xc010 - ; It's tempting to bake in the 0x60 offset for the drive unit at slot 6... but this ; changes the timing of the instructions which access these registers, and then ; writes don't work! You _must_ use lda , x or sta , x instructions @@ -49,37 +40,11 @@ DECODE_TABLE_START = 0x96 .global _start ZEROPAGE -.global ptr -.global ptr1 -ptr: .word 0 -ptr1: .word 0 dma: .word 0 disk_sixes_buffer = 0x300 track_buffer = 0xd000 -//#define APPLE2 -//#define APPLE2PLUS -//#define APPLE2EUROPLUS -//#define APPLE2JPLUS -//#define APPLE2E -//#define APPLE2EENHANCED -//#define APPLE2C -//#define APPLE2GS - -#define TTY_MODE_40COLUMNS 1 -#define TTY_MODE_80COLUMNS 2 -#if defined APPLE2GS || defined APPLE2EENHANCED || defined APPLE2E -#define TTY_MODE TTY_MODE_80COLUMNS -SCREEN_WIDTH = 80 -#elif defined APPLE2C || defined APPLE2JPLUS || defined APPLE2EUROPLUS || defined APPLE2PLUS || defined APPLE2 -#define TTY_MODE TTY_MODE_40COLUMNS -SCREEN_WIDTH = 40 -#else -#error Unknown Apple II model -#endif -SCREEN_HEIGHT = 24 - ; --- Initialisation code --------------------------------------------------- ; Boot sector and relocator. Loaded at 0x0800 when the disk boots. Called once @@ -242,206 +207,13 @@ zproc bios_SETBANK rts zendproc -; --- SCREEN driver --------------------------------------------------------- - -defdriver SCREEN, DRVID_SCREEN, drvstrat_SCREEN, 0 - -; SCREEN driver strategy routine. -; Y=SCREEN opcode. -zproc drvstrat_SCREEN - jmpdispatch screen_jmptable_lo, screen_jmptable_hi - -screen_jmptable_lo: - jmptablo screen_version - jmptablo screen_getsize - jmptablo screen_clear - jmptablo screen_setcursor - jmptablo screen_getcursor - jmptablo screen_putchar - jmptablo screen_putstring - jmptablo screen_getchar - jmptablo screen_showcursor - jmptablo screen_scrollup - jmptablo screen_scrolldown - jmptablo screen_cleartoeol -; jmptablo screen_setstyle - jmptablo fail -screen_jmptable_hi: - jmptabhi screen_version - jmptabhi screen_getsize - jmptabhi screen_clear - jmptabhi screen_setcursor - jmptabhi screen_getcursor - jmptabhi screen_putchar - jmptabhi screen_putstring - jmptabhi screen_getchar - jmptabhi screen_showcursor - jmptabhi screen_scrollup - jmptabhi screen_scrolldown - jmptabhi screen_cleartoeol -; jmptabhi screen_setstyle - jmptabhi fail -zendproc - -zproc screen_version - lda #0 - rts -zendproc - -zproc screen_getsize - lda #SCREEN_WIDTH-1 - ldx #SCREEN_HEIGHT-1 - rts -zendproc - -zproc screen_clear - jmp clear_screen -zendproc - -zproc screen_setcursor - sta cursorx - stx cursory - rts -zendproc - -zproc screen_getcursor - lda cursorx - ldx cursory - rts -zendproc - -zproc cursor_on - jsr prepare_for_screen_write - lda (ptr), y - sta cursork - ldx cursorvisible - cpx #1 - zif_eq - lda #0x60 ; flashing block - sta (ptr), y - zendif - rts -zendproc - -zproc cursor_off - ;ldx cursorvisible - ;cpx #1 - ;zif_eq - tax - lda cursork - sta (ptr), y - txa - ;zendif - rts -zendproc - -zproc screen_getchar - jsr cursor_on - - ; A,X contain the timeout, TODO: respect timeout - - zrepeat - lda KBD_READ - zuntil_mi - bpl nokey - sta KBD_STROBERESET - and #0x7f - -nokey: - jsr cursor_off - - ; return character in A - ; TODO: carry clear on keyboard event, carry set on timeout? - clc - rts -zendproc - -zproc screen_showcursor - sta cursorvisible - rts -zendproc - -zproc screen_putchar - ; TODO: we have to check how the various machines do this, - ; especially for lower-case characters - ;sec - ;sbc stylemask - jmp tty_conout -zendproc - -zproc screen_putstring - sta ptr1+0 - stx ptr1+1 - zrepeat - ldy #0 - lda (ptr1), y - zbreakif_eq - jsr screen_putchar - inc ptr1+0 - zif_eq - inc ptr1+1 - zendif - zuntil_eq - rts -zendproc - -zproc screen_scrollup - jmp scroll_up -zendproc - -zproc screen_scrolldown - ;~ jmp scroll_down -zendproc - -zproc screen_cleartoeol - lda cursory - jsr calculate_screen_address ; ptr is source pointer - ldy cursorx - lda #32|0x80 - zrepeat -#if TTY_MODE == TTY_MODE_80COLUMNS - sta SCREEN_PAGE2OFF - sta (ptr), y - sta SCREEN_PAGE2ON -#endif - sta (ptr), y - iny - cpy #40 - zuntil_eq - rts -zendproc - -;zproc setcolour -; ; colours, are you kidding? ;-) -; rts -;zendproc - -;zproc screen_setstyle -; ; TODO: see "Using 6502 Assembly Language, appendix A-2" -; ; TODO: see how we handle inverse with lowercase in Apple IIe and clone case -; and #STYLE_REVERSE -; zif_eq -; lda #0x00 -; sta stylemask -; zelse -; lda #0x80 -; sta stylemask -; zendif -; rts -;zendproc - -zproc fail - sec - rts -zendproc - ; --- TTY driver ------------------------------------------------------------ .data .global drvtop drvtop: .word drv_TTY -defdriver TTY, DRVID_TTY, drvstrat_TTY, drv_SCREEN +defdriver TTY, DRVID_TTY, drvstrat_TTY, 0 ; TTY driver strategy routine. ; Y=TTY opcode. @@ -467,218 +239,9 @@ zendproc ; Writes the character in A. zproc tty_conout - cmp #13 - zif_eq - lda #0 - sta cursorx - rts - zendif - cmp #127 - zif_eq - dec cursorx - zif_mi - inc cursorx - zendif - jsr prepare_for_screen_write - lda #0xa0 - sta (ptr), y - rts - zendif - cmp #10 - beq write_nl - - pha - jsr prepare_for_screen_write - pla - eor #0x80 - sta (ptr), y - - inc cursorx - lda cursorx - cmp #SCREEN_WIDTH - zif_eq - lda #0 - sta cursorx - jmp write_nl - zendif - rts + jmp conout zendproc -zproc write_nl - inc cursory - lda cursory - cmp #SCREEN_HEIGHT - zif_eq - dec cursory - jmp scroll_up - zendif - rts -zendproc - -zproc scroll_up - ldx #0 ; current line - zrepeat - txa - jsr calculate_screen_address - lda ptr+0 - sta ptr1+0 - lda ptr+1 - sta ptr1+1 ; ptr1 is dest pointer - - inx - txa - jsr calculate_screen_address ; ptr is source pointer - - ldy #39 - zrepeat -#if TTY_MODE == TTY_MODE_80COLUMNS - sta SCREEN_PAGE2OFF - lda (ptr), y - sta (ptr1), y - sta SCREEN_PAGE2ON -#endif - lda (ptr), y - sta (ptr1), y - dey - zuntil_mi - - cpx #23 - zuntil_eq - - ldy #39 - lda #32|0x80 - zrepeat -#if TTY_MODE == TTY_MODE_80COLUMNS - sta SCREEN_PAGE2OFF - sta (ptr), y - sta SCREEN_PAGE2ON -#endif - sta (ptr), y - dey - zuntil_mi - rts -zendproc - -;~ zproc scroll_down - ;~ ldx #22 ; current line - ;~ zrepeat - ;~ txa - ;~ jsr calculate_screen_address - ;~ lda ptr+0 - ;~ sta ptr1+0 - ;~ lda ptr+1 - ;~ sta ptr1+1 ; ptr1 is dest pointer - - ;~ dex - ;~ txa - ;~ jsr calculate_screen_address ; ptr is source pointer - - ;~ ldy #39 - ;~ zrepeat -;~ #if TTY_MODE == TTY_MODE_80COLUMNS - ;~ sta SCREEN_PAGE2OFF - ;~ lda (ptr), y - ;~ sta (ptr1), y - ;~ sta SCREEN_PAGE2ON -;~ #endif - ;~ lda (ptr), y - ;~ sta (ptr1), y - ;~ dey - ;~ zuntil_mi - - ;~ cpx #0 - ;~ zuntil_eq - - ;~ ldy #39 - ;~ lda #32|0x80 - ;~ zrepeat - ;~ ;sta SCREEN_PAGE2OFF - ;~ sta (ptr), y - ;~ ;sta SCREEN_PAGE2ON - ;~ ;sta (ptr), y - ;~ dey - ;~ zuntil_mi - ;~ rts -;~ zendproc - -; Sets ptr to the current cursor row address; also sets up the page stuff. -; Leaves Y to the screen line offset. - -zproc prepare_for_screen_write - lda cursory - jsr calculate_screen_address - lda cursorx -#if TTY_MODE == TTY_MODE_80COLUMNS - lsr a -#endif - tay - lda #0 - rol - eor #1 - tax -#if TTY_MODE == TTY_MODE_80COLUMNS - sta SCREEN_PAGE2OFF, x -#endif - rts -zendproc - -; Given a row number in A, set ptr to the address of that -; row of video memory. -; -; Given a row 000abcde, the address is 000001cd eabab000. -; Preserves X and Y. -zproc calculate_screen_address - pha - lsr a - and #0x03 - ora #0x04 - sta ptr+1 - pla - - lsr a ; 0000abcd, e -> carry - php - and #0x0c ; 0000ab00 - sta ptr+0 - lsr a - lsr a ; 000000ab - ora ptr+0 ; 0000abab - asl a - asl a - asl a - asl a ; abab0000 - plp - ror a ; eabab000 - sta ptr+0 - rts -zendproc - -zproc clear_screen - lda #24 - sta ptr1 - zrepeat - lda ptr1 - jsr calculate_screen_address - ldy #40 - lda #32|0x80 - zrepeat - dey -#if TTY_MODE == TTY_MODE_80COLUMNS - sta SCREEN_PAGE2ON - sta (ptr), y - sta SCREEN_PAGE2OFF -#endif - sta (ptr), y - zuntil_eq - - dec ptr1 - zuntil_mi - lda #0 - sta cursorx - sta cursory - rts -zendproc - - ; --- Keyboard -------------------------------------------------------------- zproc tty_const @@ -711,13 +274,7 @@ zproc tty_conin sta motor_countdown ; Display the cursor. - jsr cursor_on - ;~ jsr prepare_for_screen_write - ;~ lda (ptr), y - ;~ sta cursork - ;~ lda #0x60 ; flashing block - ;~ sta (ptr), y ; Wait for the key. @@ -729,12 +286,8 @@ zproc tty_conin clc ; Cursor off again. - jsr cursor_off - ;~ tax - ;~ lda cursork - ;~ sta (ptr), y - ;~ txa + rts zendproc @@ -1366,11 +919,6 @@ encode_tab: .fill 64 ; must be within one page .global directory_buffer .bss -cursorx: .fill 1 -cursory: .fill 1 -cursork: .fill 1 -;stylemask: .fill 1 -cursorvisible: .fill 1 current_bank: .fill 1 current_phase: .fill 1 directory_buffer: .fill 128 @@ -1382,6 +930,12 @@ motor_countdown: .fill 1 buffered_track: .fill 1 buffer_dirty: .fill 1 track_flags: .fill 16 +; this is in common.S and gets attacked here (in link order) +;cursorx: .fill 1 +;cursory: .fill 1 +;cursork: .fill 1 +;cursorstylemask: .fill 1 +;cursorvisible: .fill 1 ; This must go last --- it's the three 6502 vectors. .text diff --git a/src/arch/apple2e/apple2e.inc b/src/arch/apple2e/apple2e.inc new file mode 100644 index 00000000..222e76a8 --- /dev/null +++ b/src/arch/apple2e/apple2e.inc @@ -0,0 +1,33 @@ +; Apple ][ OS defines + +SCREEN_80STOREOFF = 0xc000 +SCREEN_80STOREON = 0xc001 +SCREEN_80COLOFF = 0xc00c +SCREEN_80COLON = 0xc00d +SCREEN_PAGE2OFF = 0xc054 +SCREEN_PAGE2ON = 0xc055 + +KBD_READ = 0xc000 +KBD_STROBERESET = 0xc010 + +//#define APPLE2 +//#define APPLE2PLUS +//#define APPLE2EUROPLUS +//#define APPLE2JPLUS +//#define APPLE2E +//#define APPLE2EENHANCED +//#define APPLE2C +//#define APPLE2GS + +#define TTY_MODE_40COLUMNS 1 +#define TTY_MODE_80COLUMNS 2 +#if defined APPLE2GS || defined APPLE2EENHANCED || defined APPLE2E +#define TTY_MODE TTY_MODE_80COLUMNS +SCREEN_WIDTH = 80 +#elif defined APPLE2C || defined APPLE2JPLUS || defined APPLE2EUROPLUS || defined APPLE2PLUS || defined APPLE2 +#define TTY_MODE TTY_MODE_40COLUMNS +SCREEN_WIDTH = 40 +#else +#error Unknown Apple II model +#endif +SCREEN_HEIGHT = 24 diff --git a/src/arch/apple2e/build.py b/src/arch/apple2e/build.py index a82e03f3..45ba4990 100644 --- a/src/arch/apple2e/build.py +++ b/src/arch/apple2e/build.py @@ -1,5 +1,5 @@ from tools.build import mkcpmfs, shuffle, mametest -from build.llvm import llvmrawprogram, llvmcfile +from build.llvm import llvmrawprogram, llvmcfile, llvmclibrary from config import ( MINIMAL_APPS, MINIMAL_APPS_SRCS, @@ -9,18 +9,29 @@ SCREEN_APPS_SRCS, ) +llvmclibrary( + name="common", + srcs="./common.S", + hdrs={"apple2e.inc": "./apple2e.inc"}, + deps=["include"], +# cflags=["-DAPPLE2E"], + cflags=["-DAPPLE2PLUS"], +) + llvmcfile( name="bios_obj", srcs=["./apple2e.S"], - cflags=["-DAPPLE2E"], -# cflags=["-DAPPLE2PLUS"], +# cflags=["-DAPPLE2E"], + cflags=["-DAPPLE2PLUS"], deps=["include", "src/lib+bioslib"], ) llvmrawprogram( name="bios_prelink", srcs=[".+bios_obj"], - deps=["src/lib+bioslib"], + deps=["src/lib+bioslib", "src/arch/apple2e+common"], +# cflags=["-DAPPLE2E"], + cflags=["-DAPPLE2PLUS"], linkscript="./apple2e-prelink.ld", ldflags=["--defsym=BIOS_SIZE=0x4000"], ) @@ -32,6 +43,7 @@ ".+bios_prelink", "scripts/size.awk", "src/lib+bioslib", + "src/arch/apple2e+common", ], linkscript="./apple2e.ld", ldflags=[ @@ -53,7 +65,11 @@ format="appleiie", bootimage=".+bios_shuffled", size=143360, - items={"0:ccp.sys@sr": "src+ccp", "0:bdos.sys@sr": "src/bdos"} + items={ + "0:ccp.sys@sr": "src+ccp", + "0:bdos.sys@sr": "src/bdos", + "0:scrndrv.com": "src/arch/apple2e/utils+scrndrv", + } | MINIMAL_APPS | MINIMAL_APPS_SRCS | BIG_APPS diff --git a/src/arch/apple2e/common.S b/src/arch/apple2e/common.S new file mode 100644 index 00000000..0cb5ccf1 --- /dev/null +++ b/src/arch/apple2e/common.S @@ -0,0 +1,224 @@ +#include "zif.inc" +#include "apple2e.inc" +#include "cpm65.inc" + +ZEROPAGE + +.global ptr +.global ptr1 + +ptr: .word 0 +ptr1: .word 0 + +.data + +; Writes the character in A. + +zproc conout + cmp #13 + zif_eq + lda #0 + sta cursorx + rts + zendif + cmp #127 + zif_eq + dec cursorx + zif_mi + inc cursorx + zendif + jsr prepare_for_screen_write + lda #0xa0 + sta (ptr), y + rts + zendif + cmp #10 + beq write_nl + + pha + jsr prepare_for_screen_write + pla + eor #0x80 + sta (ptr), y + + inc cursorx + lda cursorx + cmp #SCREEN_WIDTH + zif_eq + lda #0 + sta cursorx + jmp write_nl + zendif + rts +zendproc + +zproc write_nl + inc cursory + lda cursory + cmp #SCREEN_HEIGHT + zif_eq + dec cursory + jmp scroll_up + zendif + rts +zendproc + +zproc scroll_up + ldx #0 ; current line + zrepeat + txa + jsr calculate_screen_address + lda ptr+0 + sta ptr1+0 + lda ptr+1 + sta ptr1+1 ; ptr1 is dest pointer + + inx + txa + jsr calculate_screen_address ; ptr is source pointer + + ldy #39 + zrepeat +#if TTY_MODE == TTY_MODE_80COLUMNS + sta SCREEN_PAGE2OFF + lda (ptr), y + sta (ptr1), y + sta SCREEN_PAGE2ON +#endif + lda (ptr), y + sta (ptr1), y + dey + zuntil_mi + + cpx #23 + zuntil_eq + + ldy #39 + lda #32|0x80 + zrepeat +#if TTY_MODE == TTY_MODE_80COLUMNS + sta SCREEN_PAGE2OFF + sta (ptr), y + sta SCREEN_PAGE2ON +#endif + sta (ptr), y + dey + zuntil_mi + rts +zendproc + +; Sets ptr to the current cursor row address; also sets up the page stuff. +; Leaves Y to the screen line offset. + +zproc prepare_for_screen_write + lda cursory + jsr calculate_screen_address + lda cursorx +#if TTY_MODE == TTY_MODE_80COLUMNS + lsr a +#endif + tay + lda #0 + rol + eor #1 + tax +#if TTY_MODE == TTY_MODE_80COLUMNS + sta SCREEN_PAGE2OFF, x +#endif + rts +zendproc + +; Given a row number in A, set ptr to the address of that +; row of video memory. +; +; Given a row 000abcde, the address is 000001cd eabab000. +; Preserves X and Y. +zproc calculate_screen_address + pha + lsr a + and #0x03 + ora #0x04 + sta ptr+1 + pla + + lsr a ; 0000abcd, e -> carry + php + and #0x0c ; 0000ab00 + sta ptr+0 + lsr a + lsr a ; 000000ab + ora ptr+0 ; 0000abab + asl a + asl a + asl a + asl a ; abab0000 + plp + ror a ; eabab000 + sta ptr+0 + rts +zendproc + +zproc clear_screen + lda #24 + sta ptr1 + zrepeat + lda ptr1 + jsr calculate_screen_address + ldy #40 + lda #32|0x80 + zrepeat + dey +#if TTY_MODE == TTY_MODE_80COLUMNS + sta SCREEN_PAGE2ON + sta (ptr), y + sta SCREEN_PAGE2OFF +#endif + sta (ptr), y + zuntil_eq + + dec ptr1 + zuntil_mi + lda #0 + sta cursorx + sta cursory + rts +zendproc + +zproc cursor_on + ldx cursorvisible + cpx #1 + zif_eq + jsr prepare_for_screen_write + lda (ptr), y + sta cursork + lda #0x60 ; flashing block + sta (ptr), y + zendif + rts +zendproc + +zproc cursor_off + ldx cursorvisible + cpx #1 + zif_eq + tax + lda cursork + sta (ptr), y + txa + zendif + rts +zendproc + +.bss + +.global cursorx +.global cursory +.global cursork +.global cursorvisible +.global cursorstylemask +.global conout +cursorx: .fill 1 +cursory: .fill 1 +cursork: .fill 1 +cursorvisible: .fill 1 +cursorstylemask: .fill 1 diff --git a/src/arch/apple2e/utils/build.py b/src/arch/apple2e/utils/build.py new file mode 100644 index 00000000..6ebcb354 --- /dev/null +++ b/src/arch/apple2e/utils/build.py @@ -0,0 +1,12 @@ +from build.llvm import llvmprogram + +llvmprogram( + name="scrndrv", + srcs=["./scrndrv.S"], +# cflags=["-DAPPLE2E"], + cflags=["-DAPPLE2PLUS"], + deps=[ + "include", + "src/arch/apple2e+common", + ], +) diff --git a/src/arch/apple2e/utils/scrndrv.S b/src/arch/apple2e/utils/scrndrv.S new file mode 100644 index 00000000..e88a1c81 --- /dev/null +++ b/src/arch/apple2e/utils/scrndrv.S @@ -0,0 +1,304 @@ +; CP/M-65 Copyright © 2022 David Given +; This file is licensed under the terms of the 2-clause BSD license. Please +; see the COPYING file in the root project directory for the full text. +; +; 40/80 columns TTY/SCREEN driver for the Apple ][ +; Copyright © 2024 Andreas Baumann +; This file is licensed under the terms of the 2-clause BSD license. Please +; see the COPYING file in the root project directory for the full text. + +#include "zif.inc" +#include "cpm65.inc" +#include "apple2e.inc" +#include "driver.inc" +#include "jumptables.inc" + +; ------------------------------------------------------------------------- + +zproc main + jmp init +zendproc + +; --- SCREEN driver --------------------------------------------------------- + +defdriver SCREEN, DRVID_SCREEN, drvstrat_SCREEN, 0 + +; SCREEN driver strategy routine. +; Y=SCREEN opcode. +zproc drvstrat_SCREEN + jmpdispatch screen_jmptable_lo, screen_jmptable_hi + +screen_jmptable_lo: + jmptablo screen_version + jmptablo screen_getsize + jmptablo screen_clear + jmptablo screen_setcursor + jmptablo screen_getcursor + jmptablo screen_putchar + jmptablo screen_putstring + jmptablo screen_getchar + jmptablo screen_showcursor + jmptablo screen_scrollup + jmptablo screen_scrolldown + jmptablo screen_cleartoeol + jmptablo screen_setstyle + +screen_jmptable_hi: + jmptabhi screen_version + jmptabhi screen_getsize + jmptabhi screen_clear + jmptabhi screen_setcursor + jmptabhi screen_getcursor + jmptabhi screen_putchar + jmptabhi screen_putstring + jmptabhi screen_getchar + jmptabhi screen_showcursor + jmptabhi screen_scrollup + jmptabhi screen_scrolldown + jmptabhi screen_cleartoeol + jmptabhi screen_setstyle +zendproc + +zproc fail + sec + rts +zendproc + +; ------------------------------------------------------------------------- + +; INITIALIZE DRIVER + +zproc init + +; BDOS: where is the BIOS + ldy #BDOS_GET_BIOS + jsr BDOS + sta BIOS+1 + stx BIOS+2 + +; register new driver + lda #drv_SCREEN + ldy #BIOS_ADDDRV + jsr BIOS + +; claim memory for our driver (TODO: compute this) + zif_cc + ldy #BIOS_GETTPA + jsr BIOS + clc + adc #4 + ldy #BIOS_SETTPA + jsr BIOS + + ldy #BIOS_GETZP + jsr BIOS + clc + adc #4 + ldy #BIOS_SETZP + jsr BIOS + + zif_cc +; print that we are loaded + lda #banner + ldy #BDOS_WRITE_STRING + jsr BDOS + +; just returning works + rts + zendif + zendif + +; print we failed to load + lda #failed + ldy #BDOS_WRITE_STRING + jsr BDOS + + rts +zendproc + +zproc screen_version + lda #0 + rts +zendproc + +zproc screen_getsize + lda #SCREEN_WIDTH-1 + ldx #SCREEN_HEIGHT-1 + rts +zendproc + +zproc screen_clear + jmp clear_screen +zendproc + +zproc screen_setcursor + sta cursorx + stx cursory + rts +zendproc + +zproc screen_getcursor + lda cursorx + ldx cursory + rts +zendproc + +zproc screen_getchar + jsr cursor_on + + ; A,X contain the timeout, TODO: respect timeout + + zrepeat + lda KBD_READ + zuntil_mi + bpl nokey + sta KBD_STROBERESET + and #0x7f + +nokey: + jsr cursor_off + + ; return character in A + ; TODO: carry clear on keyboard event, carry set on timeout? + clc + rts +zendproc + +zproc screen_showcursor + sta cursorvisible + rts +zendproc + +zproc screen_putchar + ;~ ; TODO: we have to check how the various machines do this, + ;~ ; especially for lower-case characters + ;~ ;sec + ;~ ;sbc stylemask + jmp conout +zendproc + +zproc screen_putstring + sta ptr1+0 + stx ptr1+1 + zrepeat + ldy #0 + lda (ptr1), y + zbreakif_eq + jsr screen_putchar + inc ptr1+0 + zif_eq + inc ptr1+1 + zendif + zuntil_eq + rts +zendproc + +zproc screen_scrollup + jmp scroll_up +zendproc + +zproc screen_scrolldown + jmp scroll_down +zendproc + +zproc screen_cleartoeol + lda cursory + jsr calculate_screen_address ; ptr is source pointer + ldy cursorx + lda #32|0x80 + zrepeat +#if TTY_MODE == TTY_MODE_80COLUMNS + sta SCREEN_PAGE2OFF + sta (ptr), y + sta SCREEN_PAGE2ON +#endif + sta (ptr), y + iny + cpy #40 + zuntil_eq + rts +zendproc + +zproc setcolour + ; colours, are you kidding? ;-) + rts +zendproc + +zproc screen_setstyle + ; TODO: see "Using 6502 Assembly Language, appendix A-2" + ; TODO: see how we handle inverse with lowercase in Apple IIe and clone case + and #STYLE_REVERSE + zif_eq + lda #0x00 + sta cursorstylemask + zelse + lda #0x80 + sta cursorstylemask + zendif + rts +zendproc + +zproc scroll_down + ldx #22 ; current line + zrepeat + txa + jsr calculate_screen_address + lda ptr+0 + sta ptr1+0 + lda ptr+1 + sta ptr1+1 ; ptr1 is dest pointer + + dex + txa + jsr calculate_screen_address ; ptr is source pointer + + ldy #39 + zrepeat +#if TTY_MODE == TTY_MODE_80COLUMNS + sta SCREEN_PAGE2OFF + lda (ptr), y + sta (ptr1), y + sta SCREEN_PAGE2ON +#endif + lda (ptr), y + sta (ptr1), y + dey + zuntil_mi + + cpx #0 + zuntil_eq + + ldy #39 + lda #32|0x80 + zrepeat +#if TTY_MODE == TTY_MODE_80COLUMNS + sta SCREEN_PAGE2OFF + sta (ptr), y + sta SCREEN_PAGE2ON +#endif + sta (ptr), y + dey + zuntil_mi + rts +zendproc + +zproc BIOS + jmp $1234 +zendproc + +.data + +banner: + .ascii "Apple II screen driver loaded." + .byte 13, 10, 0 + +failed: + .ascii "Failed!" + .byte 13, 10, 0 + +; Increase TPA bottom to here + +reserve_tpa_end: From 23b10cecf7ae8ace8c8a25a29abcde10a1b577b9 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Tue, 20 Feb 2024 21:32:58 +0100 Subject: [PATCH 04/39] combined a tty/screen driver into scrndrv, works, but has some copy paste code and issues around stopping the disk drive motor --- src/arch/apple2e/apple2e.S | 196 ++++++++++++++++- src/arch/apple2e/build.py | 4 +- src/arch/apple2e/utils/scrndrv.S | 359 ++++++++++++++++++++++++++++--- 3 files changed, 510 insertions(+), 49 deletions(-) diff --git a/src/arch/apple2e/apple2e.S b/src/arch/apple2e/apple2e.S index 9a863f93..c54c5cf6 100644 --- a/src/arch/apple2e/apple2e.S +++ b/src/arch/apple2e/apple2e.S @@ -40,6 +40,10 @@ DECODE_TABLE_START = 0x96 .global _start ZEROPAGE +.global ptr +.global ptr1 +ptr: .word 0 +ptr1: .word 0 dma: .word 0 disk_sixes_buffer = 0x300 @@ -60,8 +64,6 @@ _start: sta SCREEN_80STOREON sta SCREEN_PAGE2OFF #endif - lda #1 - sta cursorvisible ldx #0xff txs ; reset stack @@ -239,7 +241,173 @@ zendproc ; Writes the character in A. zproc tty_conout - jmp conout + cmp #13 + zif_eq + lda #0 + sta cursorx + rts + zendif + cmp #127 + zif_eq + dec cursorx + zif_mi + inc cursorx + zendif + jsr prepare_for_screen_write + lda #0xa0 + sta (ptr), y + rts + zendif + cmp #10 + beq write_nl + + pha + jsr prepare_for_screen_write + pla + eor #0x80 + sta (ptr), y + + inc cursorx + lda cursorx + cmp #SCREEN_WIDTH + zif_eq + lda #0 + sta cursorx + jmp write_nl + zendif + rts +zendproc + +zproc write_nl + inc cursory + lda cursory + cmp #SCREEN_HEIGHT + zif_eq + dec cursory + jmp scroll_up + zendif + rts +zendproc + +zproc scroll_up + ldx #0 ; current line + zrepeat + txa + jsr calculate_screen_address + lda ptr+0 + sta ptr1+0 + lda ptr+1 + sta ptr1+1 ; ptr1 is dest pointer + + inx + txa + jsr calculate_screen_address ; ptr is source pointer + + ldy #39 + zrepeat +#if TTY_MODE == TTY_MODE_80COLUMNS + sta SCREEN_PAGE2OFF + lda (ptr), y + sta (ptr1), y + sta SCREEN_PAGE2ON +#endif + lda (ptr), y + sta (ptr1), y + dey + zuntil_mi + + cpx #23 + zuntil_eq + + ldy #39 + lda #32|0x80 + zrepeat +#if TTY_MODE == TTY_MODE_80COLUMNS + sta SCREEN_PAGE2OFF + sta (ptr), y + sta SCREEN_PAGE2ON +#endif + sta (ptr), y + dey + zuntil_mi + rts +zendproc + +; Sets ptr to the current cursor row address; also sets up the page stuff. +; Leaves Y to the screen line offset. + +zproc prepare_for_screen_write + lda cursory + jsr calculate_screen_address + lda cursorx +#if TTY_MODE == TTY_MODE_80COLUMNS + lsr a +#endif + tay + lda #0 + rol + eor #1 + tax +#if TTY_MODE == TTY_MODE_80COLUMNS + sta SCREEN_PAGE2OFF, x +#endif + rts +zendproc + +; Given a row number in A, set ptr to the address of that +; row of video memory. +; +; Given a row 000abcde, the address is 000001cd eabab000. +; Preserves X and Y. +zproc calculate_screen_address + pha + lsr a + and #0x03 + ora #0x04 + sta ptr+1 + pla + + lsr a ; 0000abcd, e -> carry + php + and #0x0c ; 0000ab00 + sta ptr+0 + lsr a + lsr a ; 000000ab + ora ptr+0 ; 0000abab + asl a + asl a + asl a + asl a ; abab0000 + plp + ror a ; eabab000 + sta ptr+0 + rts +zendproc + +zproc clear_screen + lda #24 + sta ptr1 + zrepeat + lda ptr1 + jsr calculate_screen_address + ldy #40 + lda #32|0x80 + zrepeat + dey +#if TTY_MODE == TTY_MODE_80COLUMNS + sta SCREEN_PAGE2ON + sta (ptr), y + sta SCREEN_PAGE2OFF +#endif + sta (ptr), y + zuntil_eq + + dec ptr1 + zuntil_mi + lda #0 + sta cursorx + sta cursory + rts zendproc ; --- Keyboard -------------------------------------------------------------- @@ -274,7 +442,11 @@ zproc tty_conin sta motor_countdown ; Display the cursor. - jsr cursor_on + jsr prepare_for_screen_write + lda (ptr), y + sta cursork + lda #0x60 ; flashing block + sta (ptr), y ; Wait for the key. @@ -286,7 +458,10 @@ zproc tty_conin clc ; Cursor off again. - jsr cursor_off + tax + lda cursork + sta (ptr), y + txa rts zendproc @@ -919,6 +1094,11 @@ encode_tab: .fill 64 ; must be within one page .global directory_buffer .bss +cursorx: .fill 1 +cursory: .fill 1 +cursork: .fill 1 +;~ cursorstylemask: .fill 1 +;~ cursorvisible: .fill 1 current_bank: .fill 1 current_phase: .fill 1 directory_buffer: .fill 128 @@ -930,12 +1110,6 @@ motor_countdown: .fill 1 buffered_track: .fill 1 buffer_dirty: .fill 1 track_flags: .fill 16 -; this is in common.S and gets attacked here (in link order) -;cursorx: .fill 1 -;cursory: .fill 1 -;cursork: .fill 1 -;cursorstylemask: .fill 1 -;cursorvisible: .fill 1 ; This must go last --- it's the three 6502 vectors. .text diff --git a/src/arch/apple2e/build.py b/src/arch/apple2e/build.py index 45ba4990..8997ae24 100644 --- a/src/arch/apple2e/build.py +++ b/src/arch/apple2e/build.py @@ -11,7 +11,6 @@ llvmclibrary( name="common", - srcs="./common.S", hdrs={"apple2e.inc": "./apple2e.inc"}, deps=["include"], # cflags=["-DAPPLE2E"], @@ -29,7 +28,7 @@ llvmrawprogram( name="bios_prelink", srcs=[".+bios_obj"], - deps=["src/lib+bioslib", "src/arch/apple2e+common"], + deps=["src/lib+bioslib"], # cflags=["-DAPPLE2E"], cflags=["-DAPPLE2PLUS"], linkscript="./apple2e-prelink.ld", @@ -43,7 +42,6 @@ ".+bios_prelink", "scripts/size.awk", "src/lib+bioslib", - "src/arch/apple2e+common", ], linkscript="./apple2e.ld", ldflags=[ diff --git a/src/arch/apple2e/utils/scrndrv.S b/src/arch/apple2e/utils/scrndrv.S index e88a1c81..b648e6ab 100644 --- a/src/arch/apple2e/utils/scrndrv.S +++ b/src/arch/apple2e/utils/scrndrv.S @@ -13,15 +13,280 @@ #include "driver.inc" #include "jumptables.inc" +ZEROPAGE + +drv_zp_begin: + +ptr: .word 0 +ptr1: .word 0 + +drv_zp_end: + ; ------------------------------------------------------------------------- zproc main jmp init zendproc +; --- TTY driver --------------------------------------------------------- + +drv_TTY: + .word DRVID_TTY + .word drvstrat_TTY + .word 0 + .ascii "TTY" + .byte 0 + +zproc drvstrat_TTY + jmpdispatch tty_jmptable_lo, tty_jmptable_hi + +tty_jmptable_lo: + jmptablo tty_const + jmptablo tty_conin + jmptablo tty_conout + +tty_jmptable_hi: + jmptabhi tty_const + jmptabhi tty_conin + jmptabhi tty_conout + +zendproc + +zproc tty_const + jmp next_tty +zendproc + +zproc tty_conin + ; Display the cursor. + jsr prepare_for_screen_write + lda (ptr), y + sta cursork + lda #0x60 ; flashing block + sta (ptr), y + + ; Wait for the key. + + zrepeat + lda KBD_READ + zuntil_mi + sta KBD_STROBERESET + and #0x7f + clc + + ; Cursor off again. + tax + lda cursork + sta (ptr), y + txa + + rts +zendproc + +; Writes the character in A. + +zproc tty_conout + cmp #13 + zif_eq + lda #0 + sta cursorx + rts + zendif + cmp #127 + zif_eq + dec cursorx + zif_mi + inc cursorx + zendif + jsr prepare_for_screen_write + lda #0xa0 + sta (ptr), y + rts + zendif + cmp #10 + beq write_nl + + pha + jsr prepare_for_screen_write + pla + eor #0x80 + sta (ptr), y + + inc cursorx + lda cursorx + cmp #SCREEN_WIDTH + zif_eq + lda #0 + sta cursorx + jmp write_nl + zendif + rts +zendproc + +zproc write_nl + inc cursory + lda cursory + cmp #SCREEN_HEIGHT + zif_eq + dec cursory + jmp scroll_up + zendif + rts +zendproc + +zproc scroll_up + ldx #0 ; current line + zrepeat + txa + jsr calculate_screen_address + lda ptr+0 + sta ptr1+0 + lda ptr+1 + sta ptr1+1 ; ptr1 is dest pointer + + inx + txa + jsr calculate_screen_address ; ptr is source pointer + + ldy #39 + zrepeat +#if TTY_MODE == TTY_MODE_80COLUMNS + sta SCREEN_PAGE2OFF + lda (ptr), y + sta (ptr1), y + sta SCREEN_PAGE2ON +#endif + lda (ptr), y + sta (ptr1), y + dey + zuntil_mi + + cpx #23 + zuntil_eq + + ldy #39 + lda #32|0x80 + zrepeat +#if TTY_MODE == TTY_MODE_80COLUMNS + sta SCREEN_PAGE2OFF + sta (ptr), y + sta SCREEN_PAGE2ON +#endif + sta (ptr), y + dey + zuntil_mi + rts +zendproc + +; Sets ptr to the current cursor row address; also sets up the page stuff. +; Leaves Y to the screen line offset. + +zproc prepare_for_screen_write + lda cursory + jsr calculate_screen_address + lda cursorx +#if TTY_MODE == TTY_MODE_80COLUMNS + lsr a +#endif + tay + lda #0 + rol + eor #1 + tax +#if TTY_MODE == TTY_MODE_80COLUMNS + sta SCREEN_PAGE2OFF, x +#endif + rts +zendproc + +; Given a row number in A, set ptr to the address of that +; row of video memory. +; +; Given a row 000abcde, the address is 000001cd eabab000. +; Preserves X and Y. +zproc calculate_screen_address + pha + lsr a + and #0x03 + ora #0x04 + sta ptr+1 + pla + + lsr a ; 0000abcd, e -> carry + php + and #0x0c ; 0000ab00 + sta ptr+0 + lsr a + lsr a ; 000000ab + ora ptr+0 ; 0000abab + asl a + asl a + asl a + asl a ; abab0000 + plp + ror a ; eabab000 + sta ptr+0 + rts +zendproc + +zproc clear_screen + lda #24 + sta ptr1 + zrepeat + lda ptr1 + jsr calculate_screen_address + ldy #40 + lda #32|0x80 + zrepeat + dey +#if TTY_MODE == TTY_MODE_80COLUMNS + sta SCREEN_PAGE2ON + sta (ptr), y + sta SCREEN_PAGE2OFF +#endif + sta (ptr), y + zuntil_eq + + dec ptr1 + zuntil_mi + lda #0 + sta cursorx + sta cursory + rts +zendproc + +zproc cursor_on + ldx cursorvisible + cpx #1 + zif_eq + jsr prepare_for_screen_write + lda (ptr), y + sta cursork + lda #0x60 ; flashing block + sta (ptr), y + zendif + rts +zendproc + +zproc cursor_off + ldx cursorvisible + cpx #1 + zif_eq + tax + lda cursork + sta (ptr), y + txa + zendif + rts +zendproc + ; --- SCREEN driver --------------------------------------------------------- -defdriver SCREEN, DRVID_SCREEN, drvstrat_SCREEN, 0 +drv_SCREEN: + .word DRVID_SCREEN + .word drvstrat_SCREEN + .word 0 + .ascii "SCREEN" + .byte 0 ; SCREEN driver strategy routine. ; Y=SCREEN opcode. @@ -76,46 +341,62 @@ zproc init sta BIOS+1 stx BIOS+2 -; register new driver +; find current TTY driver which we overload (we do not call it), +; so that the TTY driver shares the same variables as the SCREEN +; driver (not so easy to to if the BDOS gets relocated during boot). +; This leads to some code duplications, which is not good. + lda #DRVID_TTY + ldy #BIOS_FINDDRV + jsr BIOS + sta next_tty+1 + stx next_tty+2 + +; register new drivers lda #drv_SCREEN ldy #BIOS_ADDDRV jsr BIOS + lda #drv_TTY + ldy #BIOS_ADDDRV + jsr BIOS + ; claim memory for our driver (TODO: compute this) - zif_cc - ldy #BIOS_GETTPA - jsr BIOS - clc - adc #4 - ldy #BIOS_SETTPA - jsr BIOS - - ldy #BIOS_GETZP - jsr BIOS - clc - adc #4 - ldy #BIOS_SETZP - jsr BIOS - - zif_cc -; print that we are loaded - lda #banner - ldy #BDOS_WRITE_STRING - jsr BDOS + ldy #BIOS_GETTPA + jsr BIOS + clc + adc #10 + ;~ lda #>reserve_tpa_end + ldy #BIOS_SETTPA + jsr BIOS -; just returning works - rts - zendif - zendif + ldy #BIOS_GETZP + jsr BIOS + clc + adc #drv_zp_end-drv_zp_begin + ldy #BIOS_SETZP + jsr BIOS + +; initialize variables + lda #0 + sta cursorx + sta cursory + lda #1 + sta cursorvisible -; print we failed to load - lda #failed +; as we cannot get the position of the TTY cursor, +; so just clear the screen + jsr clear_screen + +; print that we are loaded + lda #banner ldy #BDOS_WRITE_STRING jsr BDOS - + +; just returning works rts zendproc @@ -177,7 +458,7 @@ zproc screen_putchar ;~ ; especially for lower-case characters ;~ ;sec ;~ ;sbc stylemask - jmp conout + jmp tty_conout zendproc zproc screen_putstring @@ -289,15 +570,23 @@ zproc BIOS jmp $1234 zendproc +zproc next_tty + jmp $1234 +zendproc + .data banner: .ascii "Apple II screen driver loaded." .byte 13, 10, 0 -failed: - .ascii "Failed!" - .byte 13, 10, 0 +.bss + +cursorx: .fill 1 +cursory: .fill 1 +cursork: .fill 1 +cursorvisible: .fill 1 +cursorstylemask: .fill 1 ; Increase TPA bottom to here From 0eec4aecd4d44a084e3307d6c8e57737332e1807 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Thu, 22 Feb 2024 20:18:04 +0100 Subject: [PATCH 05/39] ported a tetris in C to test the screen driver (has issues with screen_getchar and missing timeout and randomness) --- apps/build.py | 2 +- apps/tetris.c | 303 ++++++++++++++++++++++++++++++++++++++++++++++++++ config.py | 1 + lib/screen.S | 7 ++ 4 files changed, 312 insertions(+), 1 deletion(-) create mode 100644 apps/tetris.c diff --git a/apps/build.py b/apps/build.py index c787eff6..d9807cb6 100644 --- a/apps/build.py +++ b/apps/build.py @@ -38,5 +38,5 @@ def asm(self, name, src: Target = None, deps: Targets = []): # Simple C programs. -for prog in ["asm", "copy", "stat", "submit", "objdump", "qe", "life", "ansiterm"]: +for prog in ["asm", "copy", "stat", "submit", "tetris", "objdump", "qe", "life", "ansiterm"]: llvmprogram(name=prog, srcs=["./%s.c" % prog], deps=["lib+cpm65"]) diff --git a/apps/tetris.c b/apps/tetris.c new file mode 100644 index 00000000..e035c470 --- /dev/null +++ b/apps/tetris.c @@ -0,0 +1,303 @@ +/* + * Copyright (c) 2022 Eugene P. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Adapted to CP/M-65, Andreas Baumann, 2024 + */ + +#include +#include +#include +#include +#include "lib/screen.h" + +#define WIDTH 12 +#define HEIGHT 20 + +#define W (WIDTH + 2) +#define H (HEIGHT + 1) +#define WXH (W * H) + +#define E '.' +#define F '#' + +// Simple acceleration calculation (unplayable over 9000 points) +#define ACCEL (100 - score / 100) + +/* Example: figure "J" rotation 0 + * 0b0100010001100000 + * + * 0 1 0 0 + * 0 1 0 0 + * 0 1 1 0 + * 0 0 0 0 + */ +uint16_t figure[][4] = { + {0b0010001000100010, 0b0000111100000000, 0b0010001000100010, 0b0000111100000000}, // I + {0b0010001001100000, 0b0000010001110000, 0b0110010001000000, 0b0000011100010000}, // J + {0b0100010001100000, 0b0000011101000000, 0b0110001000100000, 0b0000000101110000}, // L + {0b0110011000000000, 0b0110011000000000, 0b0110011000000000, 0b0110011000000000}, // O + {0b0100011000100000, 0b0000001101100000, 0b0100011000100000, 0b0000001101100000}, // S + {0b1110010000000000, 0b0010011000100000, 0b0000010011100000, 0b1000110010000000}, // T + {0b0010011001000000, 0b0000110001100000, 0b0010011001000000, 0b0000110001100000} // Z +}; + +uint8_t field[WXH]; + +struct player { + uint8_t figure_index, rot, x, y; +} gp; + +static void cr() +{ + cpm_printstring("\n\r"); +} + +static void fatal(char* msg) +{ + cpm_printstring("Error: "); + cpm_printstring(msg); + cr(); + cpm_warmboot(); +} + +static uint8_t rnd; + +void srand(uint8_t seed) +{ + rnd = seed; +} + +uint8_t rand(void) +{ + rnd = rnd * 5 + 17; + return rnd; +} + +int init() +{ + // Init screen + if(!screen_init()) + fatal("No SCREEN driver, exiting"); + screen_clear(); + screen_showcursor(0); // invisible cursor + + // Init random generator + srand(42); + + // Init field + memset(field, E, WXH-W); + + + /* Draw glass + * + * | | + * | | + * +--+ + */ + uint8_t i; + + memset(field + WXH-W+1, '-', W-2); + + for (i = 0; i < H - 1; i++) + field[i * W] = field[i * W + W-1] = '|'; + field[i * W] = field[i * W + W-1] = '+'; + + return 0; +} + +int figure_draw(char ch, struct player p) +{ + uint16_t mask = 0b1000000000000000; + uint8_t x, y; + + for (y = 0; y < 4; y++) { + for (x = 0; x < 4; x++) { + if (figure[p.figure_index][p.rot] & mask) { + int offset = (y + p.y) * W + x + p.x; + + if (ch == F && field[offset] != E) + return 0; + + if (gp.x == p.x && gp.y == p.y && gp.rot == p.rot) + field[offset] = ch; + } + mask >>= 1; + } + } + + return 1; +} + +int remove_lines() +{ + int16_t x, y; + uint16_t c, shift, lines = 0; + + for (y = 0; y < H - 1; y++) { + for (x = 1, c = 0; x < W - 1; x++) + if (field[y * W + x] == F) + c++; + + if (c == W - 2) { + lines++; + memset(field + y*W + 1, 0, W - 2); + } + } + // Full line(s) now filled with zeros + if (!lines) + return 0; + + // Remove them and move the blocks down + for (x = 1; x < W - 1; x++) { + shift = 0; + for (y = H - 2; y >= 0; y--) { + if (!field[y * W + x]) + shift++; + if (shift) { + if (field[y * W + x] == F) + field[(y + shift) * W + x] = F; + field[y * W + x] = E; + } + } + } + + uint16_t score = 10; + + if (lines > 1) + score += 20; + if (lines > 2) + score += 40; + if (lines > 3) + score += 80; + + return score; +} + +void end(uint16_t score) +{ + screen_clear(); + printf("Final score: %d\n", score); + cpm_warmboot(); +} + +void field_print(int score) +{ + uint8_t y, x, sy, sx; + + screen_getsize(&sx, &sy); + sy = (sy - H) / 2; + sx = (sx - W) / 2; + + for (y = 0; y < H; y++) { + for (x = 0; x < W; x++) { + screen_setcursor(sx+x, sy+y); + screen_putchar(field[y * W + x]); + } + } + + screen_setcursor(sx, sy + H + 1); + printf("Score: %d", score); +} + +int main() +{ + uint16_t counter = 0; + uint8_t drop = 0, draw_next = 1; + uint8_t key = 0; + uint16_t score = 0; + struct player p; + + init(); + + do { + if (draw_next == 1) { + draw_next = 0; + + gp.figure_index = rand() % 7; + gp.x = W / 2 - 2; + gp.y = 0; + gp.rot = 0; + + drop = 0; + counter = 0; + score += remove_lines(); + + if (!figure_draw(F, gp)) + break; // game over + + field_print(score); + } + + p = gp; + key = screen_getchar(10); + + switch (key) { + case 'w': + case 'W': + p.rot = gp.rot == 3 ? 0 : gp.rot + 1; + break; + case 'a': + case 'A': + p.x = gp.x - 1; + break; + case 'd': + case 'D': + p.x = gp.x + 1; + break; + case ' ': + // quickly lower + if (!drop) + drop = 1; + break; + case 's': + case 'S': + // lower slowly + counter = 254; + break; + } + + /* TODO: sleep a little while, idle looping? */ + + if (++counter > ACCEL) + counter = 0; + + if (drop == 1 || !counter) + p.y = gp.y + 1; + + if (gp.x == p.x && gp.y == p.y && gp.rot == p.rot) + continue; + + figure_draw(E, gp); + + if (!figure_draw(F, p)) { + p.x = gp.x; + p.rot = gp.rot; + if (drop == 1) { + drop = 2; + counter = ACCEL / 2; + } else if (!figure_draw(F, p) && !counter) + draw_next = 1; + } else { + gp = p; + if (drop == 2) + drop = 0; // Allow use drop key again + } + + figure_draw(F, gp); + field_print(score); + } while (key != 27); + + end(score); +} diff --git a/config.py b/config.py index 975b13a1..6f875baf 100644 --- a/config.py +++ b/config.py @@ -34,6 +34,7 @@ "0:cls.com": "apps+cls", "0:life.com": "apps+life", "0:qe.com": "apps+qe", + "0:tetris.com": "apps+tetris", "0:vt52drv.com": "apps+vt52drv", "0:vt52test.com": "apps+vt52test", } diff --git a/lib/screen.S b/lib/screen.S index 0f2018f4..e77ba4e3 100644 --- a/lib/screen.S +++ b/lib/screen.S @@ -68,6 +68,13 @@ zproc screen_clear_to_eol, .text.screen_clear_to_eol jmp _call_screen zendproc +zproc screen_getchar, .text.screen_getchar + ; TODO: A,X as timeout from timeout_cs + ldy #SCREEN_GETCHAR + jsr _call_screen + rts +zendproc + zproc screen_waitchar, .text.screen_waitchar zrepeat lda #0xff From d2ef79c5fc31a0afd4b2749d3761f5daf57038c4 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Thu, 29 Feb 2024 19:50:54 +0100 Subject: [PATCH 06/39] screen_getchar is handling timeouts now, also added a (most likely wrong) wrapper for using it in tetris.c (screen.S) handling the carry bit for detecting timeouts in scrntest.asm --- apps/scrntest.asm | 2 ++ apps/tetris.c | 2 ++ lib/screen.S | 4 ++- src/arch/apple2e/utils/scrndrv.S | 53 ++++++++++++++++++-------------- 4 files changed, 37 insertions(+), 24 deletions(-) diff --git a/apps/scrntest.asm b/apps/scrntest.asm index 332bfacd..e0bc8085 100644 --- a/apps/scrntest.asm +++ b/apps/scrntest.asm @@ -70,11 +70,13 @@ mainloop: sta cur_x stx cur_y +timeout: \ Get and parse command lda #10 ldx #00 ldy #SCREEN_GETCHAR jsr SCREEN + bcs timeout \ make sure we don't have consecutive key presses because of short timeouts \ Convert to uppercase cmp #0x61 diff --git a/apps/tetris.c b/apps/tetris.c index e035c470..6fb6555f 100644 --- a/apps/tetris.c +++ b/apps/tetris.c @@ -299,5 +299,7 @@ int main() field_print(score); } while (key != 27); + screen_showcursor(1); // visible cursor + end(score); } diff --git a/lib/screen.S b/lib/screen.S index e77ba4e3..14be1091 100644 --- a/lib/screen.S +++ b/lib/screen.S @@ -69,9 +69,11 @@ zproc screen_clear_to_eol, .text.screen_clear_to_eol zendproc zproc screen_getchar, .text.screen_getchar - ; TODO: A,X as timeout from timeout_cs ldy #SCREEN_GETCHAR jsr _call_screen + zif_cs + lda #0 ; is this a good way to report the timeout? + zendif rts zendproc diff --git a/src/arch/apple2e/utils/scrndrv.S b/src/arch/apple2e/utils/scrndrv.S index b648e6ab..43a37c10 100644 --- a/src/arch/apple2e/utils/scrndrv.S +++ b/src/arch/apple2e/utils/scrndrv.S @@ -19,6 +19,7 @@ drv_zp_begin: ptr: .word 0 ptr1: .word 0 +ptr2: .word 0 drv_zp_end: @@ -57,12 +58,13 @@ zproc tty_const zendproc zproc tty_conin + jsr cursor_on ; Display the cursor. - jsr prepare_for_screen_write - lda (ptr), y - sta cursork - lda #0x60 ; flashing block - sta (ptr), y + ;~ jsr prepare_for_screen_write + ;~ lda (ptr), y + ;~ sta cursork + ;~ lda #0x60 ; flashing block + ;~ sta (ptr), y ; Wait for the key. @@ -71,13 +73,15 @@ zproc tty_conin zuntil_mi sta KBD_STROBERESET and #0x7f + + jsr cursor_off clc ; Cursor off again. - tax - lda cursork - sta (ptr), y - txa + ;~ tax + ;~ lda cursork + ;~ sta (ptr), y + ;~ txa rts zendproc @@ -428,23 +432,26 @@ zproc screen_getcursor zendproc zproc screen_getchar + sta ptr2 + stx ptr2+1 jsr cursor_on - ; A,X contain the timeout, TODO: respect timeout - - zrepeat - lda KBD_READ - zuntil_mi - bpl nokey - sta KBD_STROBERESET - and #0x7f - -nokey: +_inner_loop: + lda KBD_READ + zif_mi + sta KBD_STROBERESET + and #0x7f + jsr cursor_off + clc + rts + zendif + dec ptr2 + bne _inner_loop + dec ptr2 + dec ptr2+1 + bne _inner_loop jsr cursor_off - - ; return character in A - ; TODO: carry clear on keyboard event, carry set on timeout? - clc + sec rts zendproc From afbc6b9f8a08175345efc1c8f2b08b4a1c0fbce6 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sun, 10 Mar 2024 13:14:43 +0100 Subject: [PATCH 07/39] removed local srand/rand from tetris.c, llvm-mos has a RNG now --- apps/tetris.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/apps/tetris.c b/apps/tetris.c index 6fb6555f..b7e4700d 100644 --- a/apps/tetris.c +++ b/apps/tetris.c @@ -72,19 +72,6 @@ static void fatal(char* msg) cpm_warmboot(); } -static uint8_t rnd; - -void srand(uint8_t seed) -{ - rnd = seed; -} - -uint8_t rand(void) -{ - rnd = rnd * 5 + 17; - return rnd; -} - int init() { // Init screen From 1e328e05186455bff24b4ecc8c4a9d23becf7b63 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Mon, 11 Mar 2024 17:44:20 +0100 Subject: [PATCH 08/39] replaced echo with printf in zip.py, zipnote complained about 'Invalid commenct format (unknown entry name) with echo --- build/zip.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/zip.py b/build/zip.py index c47d9816..8564ef65 100644 --- a/build/zip.py +++ b/build/zip.py @@ -24,7 +24,7 @@ def zip(self, name, flags="", items: TargetsMap = {}): for k, v in items.items(): cs += [ "cat %s | $(ZIP) -q %s {outs[0]} -" % (filenameof(v), flags), - "echo '@ -\\n@=%s\\n' | $(ZIPNOTE) -w {outs[0]}" % k, + "printf '@ -\\n@=%s\\n' | $(ZIPNOTE) -w {outs[0]}" % k, ] ins += [v] From 30a62ff707fdc4fc43e25a033a425df87a05b36c Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Fri, 29 Mar 2024 10:17:39 +0100 Subject: [PATCH 09/39] added warning message if active disk is missing --- src/bdos/filesystem.S | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/bdos/filesystem.S b/src/bdos/filesystem.S index 6a77bccb..5898bacc 100644 --- a/src/bdos/filesystem.S +++ b/src/bdos/filesystem.S @@ -1770,6 +1770,13 @@ zproc select_active_drive zuntil_mi clc + zelse + lda #<1f + ldx #>1f + jmp harderror +1: + .ascii "BDOS: disk missing" + .byte 13, 10, 0 zendif rts zendproc From a49e123de6bbe8250c2cf77d415db87205243d20 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Fri, 29 Mar 2024 10:18:31 +0100 Subject: [PATCH 10/39] added CCP_MONITOR for optional monitor in CCP (hits 2K boundary if enabled) --- src/build.py | 1 + src/ccp.S | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/src/build.py b/src/build.py index 6f4fdec4..efa49912 100644 --- a/src/build.py +++ b/src/build.py @@ -1,5 +1,6 @@ from build.llvm import llvmprogram llvmprogram( +# name="ccp", srcs=["./ccp.S"], cflags=["-DCCP_MONITOR"], deps=["include", "lib+bdos", "lib+xfcb"] name="ccp", srcs=["./ccp.S"], deps=["include", "lib+bdos", "lib+xfcb"] ) diff --git a/src/ccp.S b/src/ccp.S index 8056a90e..ccba503a 100644 --- a/src/ccp.S +++ b/src/ccp.S @@ -101,8 +101,10 @@ MAINLOOP: ; Monitor command? +#ifdef CCP_MONITOR cmp #'@' beq monitor_command +#endif ; Otherwise parse it as a normal command. @@ -144,6 +146,8 @@ commands_hi: jmptabhi entry_USER jmptabhi entry_TRANSIENT +#ifdef CCP_MONITOR + zproc monitor_command lda #0 sta temp+0 @@ -234,6 +238,8 @@ monitor_digit: jmp monitor_nextchar zendproc +#endif + zproc read_command_from_keyboard ; Read from keyboard. From c40b79c7846318e746a5922161156f40cf80b393 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Fri, 29 Mar 2024 10:18:56 +0100 Subject: [PATCH 11/39] split apple disks in two --- .gitignore | 1 + build.py | 1 + src/arch/apple2e/build.py | 18 ++++++++++++++++-- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index df62bc16..303a2baf 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ .*.swp .obj apple2e.po +apple2e2.po atari800.atr atari800hd.atr atari800xlhd.atr diff --git a/build.py b/build.py index 45e69528..9c810b49 100644 --- a/build.py +++ b/build.py @@ -19,6 +19,7 @@ "bbcmicro.ssd": "src/arch/bbcmicro+diskimage", "oric.dsk": "src/arch/oric+diskimage", "apple2e.po": "src/arch/apple2e+diskimage", + "apple2e2.po": "src/arch/apple2e+diskimage2", "atari800.atr": "src/arch/atari800+atari800_diskimage", "atari800hd.atr": "src/arch/atari800+atari800hd_diskimage", "atari800xlhd.atr": "src/arch/atari800+atari800xlhd_diskimage", diff --git a/src/arch/apple2e/build.py b/src/arch/apple2e/build.py index 8f136dc8..785f560c 100644 --- a/src/arch/apple2e/build.py +++ b/src/arch/apple2e/build.py @@ -5,6 +5,9 @@ MINIMAL_APPS_SRCS, BIG_APPS, BIG_APPS_SRCS, + SCREEN_APPS, + SCREEN_APPS_SRCS, + PASCAL_APPS, ) llvmclibrary( @@ -67,12 +70,23 @@ "0:scrndrv.com": "src/arch/apple2e/utils+scrndrv", } | MINIMAL_APPS - | MINIMAL_APPS_SRCS | BIG_APPS - | BIG_APPS_SRCS | SCREEN_APPS, ) +mkcpmfs( + name="diskimage2", + format="appleiie", + bootimage=".+bios_shuffled", + size=143360, + items={ + } + | PASCAL_APPS + | MINIMAL_APPS_SRCS + | BIG_APPS_SRCS + | SCREEN_APPS_SRCS, +) + mametest( name="mametest", target="apple2e", From 4c268b917f4a9f2b7c4811db0116a16f6754ffbe Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sat, 23 Nov 2024 13:59:09 +0100 Subject: [PATCH 12/39] removed local small CCP hack --- src/build.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/build.py b/src/build.py index 92a616d3..66a4ea7a 100644 --- a/src/build.py +++ b/src/build.py @@ -1,7 +1,6 @@ from build.llvm import llvmprogram llvmprogram( -# name="ccp", srcs=["./ccp.S"], cflags=["-DCCP_MONITOR"], deps=["include", "lib+bdos", "lib+xfcb"] name="ccp", srcs=["./ccp.S"], deps=["include", "lib+bdos", "lib+xfcb"] ) From 95861217dc78bae6f68b3adf3e4e9269bb5d125c Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sat, 23 Nov 2024 14:23:54 +0100 Subject: [PATCH 13/39] apple2e: merged 40-column mode from split driver version back into main bios, the standalone driver might be an idea for a Videx 80-column driver.. --- src/arch/apple2e/apple2e.S | 74 +++++++++++++++++++++++++++------ src/arch/apple2e/build.py | 19 +++------ src/arch/apple2e/utils/build.py | 12 ------ src/arch/atari800/build.py | 4 +- 4 files changed, 68 insertions(+), 41 deletions(-) delete mode 100644 src/arch/apple2e/utils/build.py diff --git a/src/arch/apple2e/apple2e.S b/src/arch/apple2e/apple2e.S index 4f8e7df6..5ad0ea66 100644 --- a/src/arch/apple2e/apple2e.S +++ b/src/arch/apple2e/apple2e.S @@ -1,14 +1,25 @@ -; CP/M-65 Copyright © 2023 David Given +; CP/M-65 Copyright © 2023 David Given ; This file is licensed under the terms of the 2-clause BSD license. Please ; see the COPYING file in the root project directory for the full text. #include "zif.inc" #include "cpm65.inc" -#include "apple2e.inc" #include "wait.inc" #include "driver.inc" #include "jumptables.inc" +SCREEN_80STOREOFF = 0xc000 +SCREEN_80STOREON = 0xc001 +SCREEN_80COLOFF = 0xc00c +SCREEN_80COLON = 0xc00d +SCREEN_STDCHARSET = 0xc00e +SCREEN_ALTCHARSET = 0xc00f +SCREEN_PAGE2OFF = 0xc054 +SCREEN_PAGE2ON = 0xc055 + +KBD_READ = 0xc000 +KBD_STROBERESET = 0xc010 + ; It's tempting to bake in the 0x60 offset for the drive unit at slot 6... but this ; changes the timing of the instructions which access these registers, and then ; writes don't work! You _must_ use lda , x or sta , x instructions @@ -38,7 +49,29 @@ DECODE_TABLE_START = 0x96 SCREENF_CURSORSHOWN = 0x80 SCREENF_INVERSE = 0x40 +;#define APPLE2 +;#define APPLE2PLUS +;#define APPLE2EUROPLUS +;#define APPLE2JPLUS +;#define APPLE2E +;#define APPLE2EENHANCED +;#define APPLE2C +;#define APPLE2GS + +#define TTY_MODE_40COLUMNS 1 +#define TTY_MODE_80COLUMNS 2 + +#if defined APPLE2C || defined APPLE2GS || defined APPLE2EENHANCED || defined APPLE2E +#define TTY_MODE TTY_MODE_80COLUMNS SCRWIDTH = 80 +; TODO: we might to want 40 columns on newer models (really?) +#elif defined APPLE2JPLUS || defined APPLE2EUROPLUS || defined APPLE2PLUS || defined APPLE2 +#define TTY_MODE TTY_MODE_40COLUMNS +SCRWIDTH = 40 +; TOPO: we might have a Videx and use that one for 80 columns mode +#else +#error Unknown Apple II model +#endif SCRHEIGHT = 24 .extern biosentry @@ -306,9 +339,11 @@ zproc screen_clear txa zrepeat dey +#if TTY_MODE == TTY_MODE_80COLUMNS sta SCREEN_PAGE2ON sta (ptr), y sta SCREEN_PAGE2OFF +#endif sta (ptr), y zuntil_eq @@ -410,12 +445,19 @@ zproc screen_scrollup txa jsr calculate_screen_address ; ptr is source pointer +#if TTY_MODE == TTY_MODE_80COLUMNS ldy #(SCRWIDTH/2)-1 +#endif +#if TTY_MODE == TTY_MODE_40COLUMNS + ldy #(SCRWIDTH)-1 +#endif zrepeat +#if TTY_MODE == TTY_MODE_80COLUMNS sta SCREEN_PAGE2OFF lda (ptr), y sta (ptr1), y sta SCREEN_PAGE2ON +#endif lda (ptr), y sta (ptr1), y dey @@ -443,12 +485,19 @@ zproc screen_scrolldown txa jsr calculate_screen_address ; ptr is source pointer +#if TTY_MODE == TTY_MODE_80COLUMNS ldy #(SCRWIDTH/2)-1 +#endif +#if TTY_MODE == TTY_MODE_40COLUMNS + ldy #(SCRWIDTH)-1 +#endif zrepeat +#if TTY_MODE == TTY_MODE_80COLUMNS sta SCREEN_PAGE2OFF lda (ptr), y sta (ptr1), y sta SCREEN_PAGE2ON +#endif lda (ptr), y sta (ptr1), y dey @@ -459,13 +508,20 @@ zproc screen_scrolldown zendproc ; fall through zproc clear_line_at_ptr - ldy #(SCRWIDTH/2)-1 +#if TTY_MODE == TTY_MODE_80COLUMNS + ldy #(SCRWIDTH/2)-1 +#endif +#if TTY_MODE == TTY_MODE_40COLUMNS + ldy #(SCRWIDTH)-1 +#endif lda #32 jsr apply_style zrepeat +#if TTY_MODE == TTY_MODE_80COLUMNS sta SCREEN_PAGE2OFF sta (ptr), y sta SCREEN_PAGE2ON +#endif sta (ptr), y dey zuntil_mi @@ -712,11 +768,8 @@ zproc tty_conin sta motor_countdown ; Display the cursor. - jsr prepare_for_screen_write - lda (ptr), y - sta cursork - lda #0x60 ; flashing block - sta (ptr), y + + jsr draw_cursor ; Wait for the key. @@ -728,10 +781,6 @@ zproc tty_conin clc ; Cursor off again. - tax - lda cursork - sta (ptr), y - txa rts zendproc @@ -1425,7 +1474,6 @@ encode_tab: .fill 64 ; must be within one page .bss cursorx: .fill 1 cursory: .fill 1 -cursork: .fill 1 cursorf: .fill 1 ; SCREEN flags current_bank: .fill 1 current_phase: .fill 1 diff --git a/src/arch/apple2e/build.py b/src/arch/apple2e/build.py index dff83987..fe9ba048 100644 --- a/src/arch/apple2e/build.py +++ b/src/arch/apple2e/build.py @@ -1,5 +1,5 @@ from tools.build import mkcpmfs, shuffle, mametest -from build.llvm import llvmrawprogram, llvmcfile, llvmclibrary +from build.llvm import llvmrawprogram, llvmcfile from config import ( MINIMAL_APPS, MINIMAL_APPS_SRCS, @@ -11,19 +11,11 @@ PASCAL_APPS, ) -llvmclibrary( - name="common", - hdrs={"apple2e.inc": "./apple2e.inc"}, - deps=["include"], - cflags=["-DAPPLE2E"], -# cflags=["-DAPPLE2PLUS"], -) - llvmcfile( name="bios_obj", srcs=["./apple2e.S"], - cflags=["-DAPPLE2E"], -# cflags=["-DAPPLE2PLUS"], +# cflags=["-DAPPLE2E"], + cflags=["-DAPPLE2PLUS"], deps=["include", "src/lib+bioslib"], ) @@ -31,8 +23,8 @@ name="bios_prelink", srcs=[".+bios_obj"], deps=["src/lib+bioslib"], - cflags=["-DAPPLE2E"], -# cflags=["-DAPPLE2PLUS"], +# cflags=["-DAPPLE2E"], + cflags=["-DAPPLE2PLUS"], linkscript="./apple2e-prelink.ld", ldflags=["--defsym=BIOS_SIZE=0x4000"], ) @@ -68,7 +60,6 @@ items={ "0:ccp.sys@sr": "src+ccp-tiny", "0:bdos.sys@sr": "src/bdos", - "0:scrndrv.com": "src/arch/apple2e/utils+scrndrv", "0:scrntest.com": "apps+scrntest", "0:cls.com": "apps+cls", "0:atbasic.com": "third_party/altirrabasic", diff --git a/src/arch/apple2e/utils/build.py b/src/arch/apple2e/utils/build.py deleted file mode 100644 index 3ee454fd..00000000 --- a/src/arch/apple2e/utils/build.py +++ /dev/null @@ -1,12 +0,0 @@ -from build.llvm import llvmprogram - -llvmprogram( - name="scrndrv", - srcs=["./scrndrv.S"], - cflags=["-DAPPLE2E"], -# cflags=["-DAPPLE2PLUS"], - deps=[ - "include", - "src/arch/apple2e+common", - ], -) diff --git a/src/arch/atari800/build.py b/src/arch/atari800/build.py index 4248254b..0348087f 100644 --- a/src/arch/atari800/build.py +++ b/src/arch/atari800/build.py @@ -33,8 +33,8 @@ "1:tty80drv.com": "src/arch/atari800/utils+tty80drv", "1:olivetti.fnt": "third_party/fonts/atari/olivetti.fnt", } - | MINIMAL_APPS - | SCREEN_APPS, + | MINIMAL_APPS, +# | SCREEN_APPS, ) simplerule( From 2cc6d6d233181b0ff1f318def7d5cfbc0758ea6e Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sat, 23 Nov 2024 14:29:41 +0100 Subject: [PATCH 14/39] apple2e: removed duplicate scrntest entry, exists in apps already for disk 2 --- src/arch/apple2e/build.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/arch/apple2e/build.py b/src/arch/apple2e/build.py index fe9ba048..45741954 100644 --- a/src/arch/apple2e/build.py +++ b/src/arch/apple2e/build.py @@ -60,7 +60,6 @@ items={ "0:ccp.sys@sr": "src+ccp-tiny", "0:bdos.sys@sr": "src/bdos", - "0:scrntest.com": "apps+scrntest", "0:cls.com": "apps+cls", "0:atbasic.com": "third_party/altirrabasic", "0:atbasic.txt": "cpmfs+atbasic_txt_cpm", From 62f43e8b8222cef91ecdb21d4a0bda19de9ac373 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sat, 23 Nov 2024 14:42:42 +0100 Subject: [PATCH 15/39] added apple2e_b.po to release github workflow --- .github/workflows/release.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e1a0ebcf..60e52b6a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -86,6 +86,7 @@ jobs: name: Development build ${{ env.RELEASE_DATE }} files: | cpm65/images/apple2e.po + cpm65/images/apple2e_b.po cpm65/images/atari800.atr cpm65/images/atari800b.atr cpm65/images/atari800c.atr From b54178f5c6935112d62e070fea71d3bc7e1c71f1 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sat, 23 Nov 2024 14:44:29 +0100 Subject: [PATCH 16/39] ignoring images/* instead of individual image files in root dir --- .gitignore | 27 +-------------------------- 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/.gitignore b/.gitignore index 2dd9b930..2186e2d6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,31 +1,6 @@ *~ .*.swp .obj -apple2e.po -apple2e_b.po -atari800.atr -atari800b.atr -atari800c.atr -atari800d.atr -atari800hd.atr -atari800xlhd.atr -bbcmicro.ssd bin -c64.d64 -pet.d64 -vic20.d64 -pet4032.d64 -pet8032.d64 -pet8096.d64 -x16.zip -oric.dsk -kim-1-iec.zip -kim-1-k1013.zip -kim-1-sdcard.zip +images/* __pycache__ -neo6502.zip -sorbus.zip -nano6502.img -nano6502_sysonly.img -*.os5 -*.os8 From 0e21ddec1890678446b31da5a3282c84689b7db9 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sat, 23 Nov 2024 15:07:31 +0100 Subject: [PATCH 17/39] apple2e: removed loadable scrndrv.S (is now fixed) --- src/arch/apple2e/utils/scrndrv.S | 600 ------------------------------- 1 file changed, 600 deletions(-) delete mode 100644 src/arch/apple2e/utils/scrndrv.S diff --git a/src/arch/apple2e/utils/scrndrv.S b/src/arch/apple2e/utils/scrndrv.S deleted file mode 100644 index 43a37c10..00000000 --- a/src/arch/apple2e/utils/scrndrv.S +++ /dev/null @@ -1,600 +0,0 @@ -; CP/M-65 Copyright © 2022 David Given -; This file is licensed under the terms of the 2-clause BSD license. Please -; see the COPYING file in the root project directory for the full text. -; -; 40/80 columns TTY/SCREEN driver for the Apple ][ -; Copyright © 2024 Andreas Baumann -; This file is licensed under the terms of the 2-clause BSD license. Please -; see the COPYING file in the root project directory for the full text. - -#include "zif.inc" -#include "cpm65.inc" -#include "apple2e.inc" -#include "driver.inc" -#include "jumptables.inc" - -ZEROPAGE - -drv_zp_begin: - -ptr: .word 0 -ptr1: .word 0 -ptr2: .word 0 - -drv_zp_end: - -; ------------------------------------------------------------------------- - -zproc main - jmp init -zendproc - -; --- TTY driver --------------------------------------------------------- - -drv_TTY: - .word DRVID_TTY - .word drvstrat_TTY - .word 0 - .ascii "TTY" - .byte 0 - -zproc drvstrat_TTY - jmpdispatch tty_jmptable_lo, tty_jmptable_hi - -tty_jmptable_lo: - jmptablo tty_const - jmptablo tty_conin - jmptablo tty_conout - -tty_jmptable_hi: - jmptabhi tty_const - jmptabhi tty_conin - jmptabhi tty_conout - -zendproc - -zproc tty_const - jmp next_tty -zendproc - -zproc tty_conin - jsr cursor_on - ; Display the cursor. - ;~ jsr prepare_for_screen_write - ;~ lda (ptr), y - ;~ sta cursork - ;~ lda #0x60 ; flashing block - ;~ sta (ptr), y - - ; Wait for the key. - - zrepeat - lda KBD_READ - zuntil_mi - sta KBD_STROBERESET - and #0x7f - - jsr cursor_off - clc - - ; Cursor off again. - ;~ tax - ;~ lda cursork - ;~ sta (ptr), y - ;~ txa - - rts -zendproc - -; Writes the character in A. - -zproc tty_conout - cmp #13 - zif_eq - lda #0 - sta cursorx - rts - zendif - cmp #127 - zif_eq - dec cursorx - zif_mi - inc cursorx - zendif - jsr prepare_for_screen_write - lda #0xa0 - sta (ptr), y - rts - zendif - cmp #10 - beq write_nl - - pha - jsr prepare_for_screen_write - pla - eor #0x80 - sta (ptr), y - - inc cursorx - lda cursorx - cmp #SCREEN_WIDTH - zif_eq - lda #0 - sta cursorx - jmp write_nl - zendif - rts -zendproc - -zproc write_nl - inc cursory - lda cursory - cmp #SCREEN_HEIGHT - zif_eq - dec cursory - jmp scroll_up - zendif - rts -zendproc - -zproc scroll_up - ldx #0 ; current line - zrepeat - txa - jsr calculate_screen_address - lda ptr+0 - sta ptr1+0 - lda ptr+1 - sta ptr1+1 ; ptr1 is dest pointer - - inx - txa - jsr calculate_screen_address ; ptr is source pointer - - ldy #39 - zrepeat -#if TTY_MODE == TTY_MODE_80COLUMNS - sta SCREEN_PAGE2OFF - lda (ptr), y - sta (ptr1), y - sta SCREEN_PAGE2ON -#endif - lda (ptr), y - sta (ptr1), y - dey - zuntil_mi - - cpx #23 - zuntil_eq - - ldy #39 - lda #32|0x80 - zrepeat -#if TTY_MODE == TTY_MODE_80COLUMNS - sta SCREEN_PAGE2OFF - sta (ptr), y - sta SCREEN_PAGE2ON -#endif - sta (ptr), y - dey - zuntil_mi - rts -zendproc - -; Sets ptr to the current cursor row address; also sets up the page stuff. -; Leaves Y to the screen line offset. - -zproc prepare_for_screen_write - lda cursory - jsr calculate_screen_address - lda cursorx -#if TTY_MODE == TTY_MODE_80COLUMNS - lsr a -#endif - tay - lda #0 - rol - eor #1 - tax -#if TTY_MODE == TTY_MODE_80COLUMNS - sta SCREEN_PAGE2OFF, x -#endif - rts -zendproc - -; Given a row number in A, set ptr to the address of that -; row of video memory. -; -; Given a row 000abcde, the address is 000001cd eabab000. -; Preserves X and Y. -zproc calculate_screen_address - pha - lsr a - and #0x03 - ora #0x04 - sta ptr+1 - pla - - lsr a ; 0000abcd, e -> carry - php - and #0x0c ; 0000ab00 - sta ptr+0 - lsr a - lsr a ; 000000ab - ora ptr+0 ; 0000abab - asl a - asl a - asl a - asl a ; abab0000 - plp - ror a ; eabab000 - sta ptr+0 - rts -zendproc - -zproc clear_screen - lda #24 - sta ptr1 - zrepeat - lda ptr1 - jsr calculate_screen_address - ldy #40 - lda #32|0x80 - zrepeat - dey -#if TTY_MODE == TTY_MODE_80COLUMNS - sta SCREEN_PAGE2ON - sta (ptr), y - sta SCREEN_PAGE2OFF -#endif - sta (ptr), y - zuntil_eq - - dec ptr1 - zuntil_mi - lda #0 - sta cursorx - sta cursory - rts -zendproc - -zproc cursor_on - ldx cursorvisible - cpx #1 - zif_eq - jsr prepare_for_screen_write - lda (ptr), y - sta cursork - lda #0x60 ; flashing block - sta (ptr), y - zendif - rts -zendproc - -zproc cursor_off - ldx cursorvisible - cpx #1 - zif_eq - tax - lda cursork - sta (ptr), y - txa - zendif - rts -zendproc - -; --- SCREEN driver --------------------------------------------------------- - -drv_SCREEN: - .word DRVID_SCREEN - .word drvstrat_SCREEN - .word 0 - .ascii "SCREEN" - .byte 0 - -; SCREEN driver strategy routine. -; Y=SCREEN opcode. -zproc drvstrat_SCREEN - jmpdispatch screen_jmptable_lo, screen_jmptable_hi - -screen_jmptable_lo: - jmptablo screen_version - jmptablo screen_getsize - jmptablo screen_clear - jmptablo screen_setcursor - jmptablo screen_getcursor - jmptablo screen_putchar - jmptablo screen_putstring - jmptablo screen_getchar - jmptablo screen_showcursor - jmptablo screen_scrollup - jmptablo screen_scrolldown - jmptablo screen_cleartoeol - jmptablo screen_setstyle - -screen_jmptable_hi: - jmptabhi screen_version - jmptabhi screen_getsize - jmptabhi screen_clear - jmptabhi screen_setcursor - jmptabhi screen_getcursor - jmptabhi screen_putchar - jmptabhi screen_putstring - jmptabhi screen_getchar - jmptabhi screen_showcursor - jmptabhi screen_scrollup - jmptabhi screen_scrolldown - jmptabhi screen_cleartoeol - jmptabhi screen_setstyle -zendproc - -zproc fail - sec - rts -zendproc - -; ------------------------------------------------------------------------- - -; INITIALIZE DRIVER - -zproc init - -; BDOS: where is the BIOS - ldy #BDOS_GET_BIOS - jsr BDOS - sta BIOS+1 - stx BIOS+2 - -; find current TTY driver which we overload (we do not call it), -; so that the TTY driver shares the same variables as the SCREEN -; driver (not so easy to to if the BDOS gets relocated during boot). -; This leads to some code duplications, which is not good. - lda #DRVID_TTY - ldy #BIOS_FINDDRV - jsr BIOS - sta next_tty+1 - stx next_tty+2 - -; register new drivers - lda #drv_SCREEN - ldy #BIOS_ADDDRV - jsr BIOS - - lda #drv_TTY - ldy #BIOS_ADDDRV - jsr BIOS - -; claim memory for our driver (TODO: compute this) - ldy #BIOS_GETTPA - jsr BIOS - clc - adc #10 - ;~ lda #>reserve_tpa_end - ldy #BIOS_SETTPA - jsr BIOS - - ldy #BIOS_GETZP - jsr BIOS - clc - adc #drv_zp_end-drv_zp_begin - ldy #BIOS_SETZP - jsr BIOS - -; initialize variables - lda #0 - sta cursorx - sta cursory - lda #1 - sta cursorvisible - -; as we cannot get the position of the TTY cursor, -; so just clear the screen - jsr clear_screen - -; print that we are loaded - lda #banner - ldy #BDOS_WRITE_STRING - jsr BDOS - -; just returning works - rts -zendproc - -zproc screen_version - lda #0 - rts -zendproc - -zproc screen_getsize - lda #SCREEN_WIDTH-1 - ldx #SCREEN_HEIGHT-1 - rts -zendproc - -zproc screen_clear - jmp clear_screen -zendproc - -zproc screen_setcursor - sta cursorx - stx cursory - rts -zendproc - -zproc screen_getcursor - lda cursorx - ldx cursory - rts -zendproc - -zproc screen_getchar - sta ptr2 - stx ptr2+1 - jsr cursor_on - -_inner_loop: - lda KBD_READ - zif_mi - sta KBD_STROBERESET - and #0x7f - jsr cursor_off - clc - rts - zendif - dec ptr2 - bne _inner_loop - dec ptr2 - dec ptr2+1 - bne _inner_loop - jsr cursor_off - sec - rts -zendproc - -zproc screen_showcursor - sta cursorvisible - rts -zendproc - -zproc screen_putchar - ;~ ; TODO: we have to check how the various machines do this, - ;~ ; especially for lower-case characters - ;~ ;sec - ;~ ;sbc stylemask - jmp tty_conout -zendproc - -zproc screen_putstring - sta ptr1+0 - stx ptr1+1 - zrepeat - ldy #0 - lda (ptr1), y - zbreakif_eq - jsr screen_putchar - inc ptr1+0 - zif_eq - inc ptr1+1 - zendif - zuntil_eq - rts -zendproc - -zproc screen_scrollup - jmp scroll_up -zendproc - -zproc screen_scrolldown - jmp scroll_down -zendproc - -zproc screen_cleartoeol - lda cursory - jsr calculate_screen_address ; ptr is source pointer - ldy cursorx - lda #32|0x80 - zrepeat -#if TTY_MODE == TTY_MODE_80COLUMNS - sta SCREEN_PAGE2OFF - sta (ptr), y - sta SCREEN_PAGE2ON -#endif - sta (ptr), y - iny - cpy #40 - zuntil_eq - rts -zendproc - -zproc setcolour - ; colours, are you kidding? ;-) - rts -zendproc - -zproc screen_setstyle - ; TODO: see "Using 6502 Assembly Language, appendix A-2" - ; TODO: see how we handle inverse with lowercase in Apple IIe and clone case - and #STYLE_REVERSE - zif_eq - lda #0x00 - sta cursorstylemask - zelse - lda #0x80 - sta cursorstylemask - zendif - rts -zendproc - -zproc scroll_down - ldx #22 ; current line - zrepeat - txa - jsr calculate_screen_address - lda ptr+0 - sta ptr1+0 - lda ptr+1 - sta ptr1+1 ; ptr1 is dest pointer - - dex - txa - jsr calculate_screen_address ; ptr is source pointer - - ldy #39 - zrepeat -#if TTY_MODE == TTY_MODE_80COLUMNS - sta SCREEN_PAGE2OFF - lda (ptr), y - sta (ptr1), y - sta SCREEN_PAGE2ON -#endif - lda (ptr), y - sta (ptr1), y - dey - zuntil_mi - - cpx #0 - zuntil_eq - - ldy #39 - lda #32|0x80 - zrepeat -#if TTY_MODE == TTY_MODE_80COLUMNS - sta SCREEN_PAGE2OFF - sta (ptr), y - sta SCREEN_PAGE2ON -#endif - sta (ptr), y - dey - zuntil_mi - rts -zendproc - -zproc BIOS - jmp $1234 -zendproc - -zproc next_tty - jmp $1234 -zendproc - -.data - -banner: - .ascii "Apple II screen driver loaded." - .byte 13, 10, 0 - -.bss - -cursorx: .fill 1 -cursory: .fill 1 -cursork: .fill 1 -cursorvisible: .fill 1 -cursorstylemask: .fill 1 - -; Increase TPA bottom to here - -reserve_tpa_end: From def54d7089efeae7d3052630aaa2252606001184 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sat, 23 Nov 2024 15:08:13 +0100 Subject: [PATCH 18/39] apple2e: removed common.S --- src/arch/apple2e/build.py | 8 +- src/arch/apple2e/common.S | 224 -------------------------------------- 2 files changed, 4 insertions(+), 228 deletions(-) delete mode 100644 src/arch/apple2e/common.S diff --git a/src/arch/apple2e/build.py b/src/arch/apple2e/build.py index 45741954..edb8f923 100644 --- a/src/arch/apple2e/build.py +++ b/src/arch/apple2e/build.py @@ -14,8 +14,8 @@ llvmcfile( name="bios_obj", srcs=["./apple2e.S"], -# cflags=["-DAPPLE2E"], - cflags=["-DAPPLE2PLUS"], + cflags=["-DAPPLE2E"], +# cflags=["-DAPPLE2PLUS"], deps=["include", "src/lib+bioslib"], ) @@ -23,8 +23,8 @@ name="bios_prelink", srcs=[".+bios_obj"], deps=["src/lib+bioslib"], -# cflags=["-DAPPLE2E"], - cflags=["-DAPPLE2PLUS"], + cflags=["-DAPPLE2E"], +# cflags=["-DAPPLE2PLUS"], linkscript="./apple2e-prelink.ld", ldflags=["--defsym=BIOS_SIZE=0x4000"], ) diff --git a/src/arch/apple2e/common.S b/src/arch/apple2e/common.S deleted file mode 100644 index 0cb5ccf1..00000000 --- a/src/arch/apple2e/common.S +++ /dev/null @@ -1,224 +0,0 @@ -#include "zif.inc" -#include "apple2e.inc" -#include "cpm65.inc" - -ZEROPAGE - -.global ptr -.global ptr1 - -ptr: .word 0 -ptr1: .word 0 - -.data - -; Writes the character in A. - -zproc conout - cmp #13 - zif_eq - lda #0 - sta cursorx - rts - zendif - cmp #127 - zif_eq - dec cursorx - zif_mi - inc cursorx - zendif - jsr prepare_for_screen_write - lda #0xa0 - sta (ptr), y - rts - zendif - cmp #10 - beq write_nl - - pha - jsr prepare_for_screen_write - pla - eor #0x80 - sta (ptr), y - - inc cursorx - lda cursorx - cmp #SCREEN_WIDTH - zif_eq - lda #0 - sta cursorx - jmp write_nl - zendif - rts -zendproc - -zproc write_nl - inc cursory - lda cursory - cmp #SCREEN_HEIGHT - zif_eq - dec cursory - jmp scroll_up - zendif - rts -zendproc - -zproc scroll_up - ldx #0 ; current line - zrepeat - txa - jsr calculate_screen_address - lda ptr+0 - sta ptr1+0 - lda ptr+1 - sta ptr1+1 ; ptr1 is dest pointer - - inx - txa - jsr calculate_screen_address ; ptr is source pointer - - ldy #39 - zrepeat -#if TTY_MODE == TTY_MODE_80COLUMNS - sta SCREEN_PAGE2OFF - lda (ptr), y - sta (ptr1), y - sta SCREEN_PAGE2ON -#endif - lda (ptr), y - sta (ptr1), y - dey - zuntil_mi - - cpx #23 - zuntil_eq - - ldy #39 - lda #32|0x80 - zrepeat -#if TTY_MODE == TTY_MODE_80COLUMNS - sta SCREEN_PAGE2OFF - sta (ptr), y - sta SCREEN_PAGE2ON -#endif - sta (ptr), y - dey - zuntil_mi - rts -zendproc - -; Sets ptr to the current cursor row address; also sets up the page stuff. -; Leaves Y to the screen line offset. - -zproc prepare_for_screen_write - lda cursory - jsr calculate_screen_address - lda cursorx -#if TTY_MODE == TTY_MODE_80COLUMNS - lsr a -#endif - tay - lda #0 - rol - eor #1 - tax -#if TTY_MODE == TTY_MODE_80COLUMNS - sta SCREEN_PAGE2OFF, x -#endif - rts -zendproc - -; Given a row number in A, set ptr to the address of that -; row of video memory. -; -; Given a row 000abcde, the address is 000001cd eabab000. -; Preserves X and Y. -zproc calculate_screen_address - pha - lsr a - and #0x03 - ora #0x04 - sta ptr+1 - pla - - lsr a ; 0000abcd, e -> carry - php - and #0x0c ; 0000ab00 - sta ptr+0 - lsr a - lsr a ; 000000ab - ora ptr+0 ; 0000abab - asl a - asl a - asl a - asl a ; abab0000 - plp - ror a ; eabab000 - sta ptr+0 - rts -zendproc - -zproc clear_screen - lda #24 - sta ptr1 - zrepeat - lda ptr1 - jsr calculate_screen_address - ldy #40 - lda #32|0x80 - zrepeat - dey -#if TTY_MODE == TTY_MODE_80COLUMNS - sta SCREEN_PAGE2ON - sta (ptr), y - sta SCREEN_PAGE2OFF -#endif - sta (ptr), y - zuntil_eq - - dec ptr1 - zuntil_mi - lda #0 - sta cursorx - sta cursory - rts -zendproc - -zproc cursor_on - ldx cursorvisible - cpx #1 - zif_eq - jsr prepare_for_screen_write - lda (ptr), y - sta cursork - lda #0x60 ; flashing block - sta (ptr), y - zendif - rts -zendproc - -zproc cursor_off - ldx cursorvisible - cpx #1 - zif_eq - tax - lda cursork - sta (ptr), y - txa - zendif - rts -zendproc - -.bss - -.global cursorx -.global cursory -.global cursork -.global cursorvisible -.global cursorstylemask -.global conout -cursorx: .fill 1 -cursory: .fill 1 -cursork: .fill 1 -cursorvisible: .fill 1 -cursorstylemask: .fill 1 From dd365be31cb57291715e448f1b98aba5238a75b1 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sun, 24 Nov 2024 18:18:49 +0100 Subject: [PATCH 19/39] apple2a: handling 40-column in screen_cleartoeol --- src/arch/apple2e/apple2e.S | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/arch/apple2e/apple2e.S b/src/arch/apple2e/apple2e.S index 5ad0ea66..0c4d7bfc 100644 --- a/src/arch/apple2e/apple2e.S +++ b/src/arch/apple2e/apple2e.S @@ -537,6 +537,7 @@ zproc screen_cleartoeol ldx cursorx zrepeat txa +#if TTY_MODE == TTY_MODE_80COLUMNS lsr a pha rol a @@ -546,13 +547,19 @@ zproc screen_cleartoeol sta SCREEN_PAGE2OFF, y pla +#endif tay lda #32 jsr apply_style sta (ptr), y inx +#if TTY_MODE == TTY_MODE_80COLUMNS cpx #SCRWIDTH +#endif +#if TTY_MODE == TTY_MODE_40COLUMNS + cpx #40 +#endif zuntil_eq rts zendproc From 5b73e3c50529803da5b22428d33e5fabe645a35d Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sun, 24 Nov 2024 20:24:41 +0100 Subject: [PATCH 20/39] moved tetris from apps to third_party --- apps/build.py | 1 - config.py | 2 +- src/arch/apple2e/build.py | 14 +++++++------- third_party/tetris/LICENSE | 13 +++++++++++++ third_party/tetris/build.py | 9 +++++++++ {apps => third_party/tetris}/tetris.c | 0 6 files changed, 30 insertions(+), 9 deletions(-) create mode 100644 third_party/tetris/LICENSE create mode 100644 third_party/tetris/build.py rename {apps => third_party/tetris}/tetris.c (100%) diff --git a/apps/build.py b/apps/build.py index 08b2ef26..1fe6d3ed 100644 --- a/apps/build.py +++ b/apps/build.py @@ -57,7 +57,6 @@ def asm(self, name, src: Target = None, deps: Targets = []): "qe", "stat", "submit", - "tetris", ]: llvmprogram(name=prog, srcs=["./%s.c" % prog], deps=["lib+cpm65"]) diff --git a/config.py b/config.py index 74f6b6cd..8bcb49bb 100644 --- a/config.py +++ b/config.py @@ -44,7 +44,7 @@ "0:life.com": "apps+life", "0:qe.com": "apps+qe", "0:scrntest.com": "apps+scrntest", - "0:tetris.com": "apps+tetris", + "0:tetris.com": "third_party/tetris", "0:vt52drv.com": "apps+vt52drv", "0:vt52test.com": "apps+vt52test", "0:kbdtest.com": "apps+kbdtest", diff --git a/src/arch/apple2e/build.py b/src/arch/apple2e/build.py index edb8f923..efb673b1 100644 --- a/src/arch/apple2e/build.py +++ b/src/arch/apple2e/build.py @@ -14,8 +14,8 @@ llvmcfile( name="bios_obj", srcs=["./apple2e.S"], - cflags=["-DAPPLE2E"], -# cflags=["-DAPPLE2PLUS"], +# cflags=["-DAPPLE2E"], + cflags=["-DAPPLE2PLUS"], deps=["include", "src/lib+bioslib"], ) @@ -23,8 +23,8 @@ name="bios_prelink", srcs=[".+bios_obj"], deps=["src/lib+bioslib"], - cflags=["-DAPPLE2E"], -# cflags=["-DAPPLE2PLUS"], +# cflags=["-DAPPLE2E"], + cflags=["-DAPPLE2PLUS"], linkscript="./apple2e-prelink.ld", ldflags=["--defsym=BIOS_SIZE=0x4000"], ) @@ -61,9 +61,6 @@ "0:ccp.sys@sr": "src+ccp-tiny", "0:bdos.sys@sr": "src/bdos", "0:cls.com": "apps+cls", - "0:atbasic.com": "third_party/altirrabasic", - "0:atbasic.txt": "cpmfs+atbasic_txt_cpm", - "0:qe.com": "apps+qe", } | MINIMAL_APPS | MINIMAL_APPS_SRCS, @@ -75,6 +72,9 @@ bootimage=".+bios_shuffled", size=143360, items={ + "0:atbasic.com": "third_party/altirrabasic", + "0:atbasic.txt": "cpmfs+atbasic_txt_cpm", + "0:qe.com": "apps+qe", } | SCREEN_APPS | SCREEN_APPS_SRCS diff --git a/third_party/tetris/LICENSE b/third_party/tetris/LICENSE new file mode 100644 index 00000000..db5a691e --- /dev/null +++ b/third_party/tetris/LICENSE @@ -0,0 +1,13 @@ + Copyright (c) 2022 Eugene P. + + Permission to use, copy, modify, and distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/third_party/tetris/build.py b/third_party/tetris/build.py new file mode 100644 index 00000000..f4d01be5 --- /dev/null +++ b/third_party/tetris/build.py @@ -0,0 +1,9 @@ +from build.ab import Rule, Target, Targets, simplerule +from build.llvm import llvmprogram +from tools.build import unixtocpm + +llvmprogram( + name="tetris", + srcs=["./tetris.c"], + deps=["lib+cpm65"] +) diff --git a/apps/tetris.c b/third_party/tetris/tetris.c similarity index 100% rename from apps/tetris.c rename to third_party/tetris/tetris.c From fa68c6ac23454a228b1956ae48dc04f18db1e200 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Mon, 25 Nov 2024 17:04:17 +0100 Subject: [PATCH 21/39] tetris: removed unixtocpm import --- third_party/tetris/build.py | 1 - 1 file changed, 1 deletion(-) diff --git a/third_party/tetris/build.py b/third_party/tetris/build.py index f4d01be5..d67de8a2 100644 --- a/third_party/tetris/build.py +++ b/third_party/tetris/build.py @@ -1,6 +1,5 @@ from build.ab import Rule, Target, Targets, simplerule from build.llvm import llvmprogram -from tools.build import unixtocpm llvmprogram( name="tetris", From bbd1c56224e738937765aa38dd41a20a874bd9e1 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Mon, 25 Nov 2024 17:04:39 +0100 Subject: [PATCH 22/39] tetris: added upstream info --- third_party/tetris/UPSTREAM.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 third_party/tetris/UPSTREAM.md diff --git a/third_party/tetris/UPSTREAM.md b/third_party/tetris/UPSTREAM.md new file mode 100644 index 00000000..931bb584 --- /dev/null +++ b/third_party/tetris/UPSTREAM.md @@ -0,0 +1,2 @@ +This was downloaded from https://codeberg.org/eu/tetris. + From 893d235500abdae9ccd46c0d4cfd54eaaf3fc244 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Mon, 25 Nov 2024 17:04:52 +0100 Subject: [PATCH 23/39] apple2e: fixed inverse mode on 40-columns (was flashing) --- src/arch/apple2e/apple2e.S | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/arch/apple2e/apple2e.S b/src/arch/apple2e/apple2e.S index 0c4d7bfc..13ca891f 100644 --- a/src/arch/apple2e/apple2e.S +++ b/src/arch/apple2e/apple2e.S @@ -319,6 +319,10 @@ zproc apply_style bit cursorf zif_vc ora #0x80 ; non inverted +#if TTY_MODE == TTY_MODE_40COLUMNS + zelse + and #0x3f ; inverted 40 columns +#endif zendif rts zendproc From 3fec73b102903cb37d54590969e7928a7d2c30e0 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sat, 30 Nov 2024 14:55:38 +0100 Subject: [PATCH 24/39] scrntest: set initial state of screen_cursor visibility to on --- apps/scrntest.asm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/scrntest.asm b/apps/scrntest.asm index 3ba2844a..deb795e2 100644 --- a/apps/scrntest.asm +++ b/apps/scrntest.asm @@ -54,6 +54,8 @@ lda #1 sta cur_vis + ldy #SCREEN_SHOWCURSOR + jsr SCREEN lda #0 sta style From 412502ebe92a94a617361a5096d33d1d6f5b3c16 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sat, 30 Nov 2024 14:56:18 +0100 Subject: [PATCH 25/39] apple2e: implemented screen_showcursor --- src/arch/apple2e/apple2e.S | 45 +++++++++++++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 6 deletions(-) diff --git a/src/arch/apple2e/apple2e.S b/src/arch/apple2e/apple2e.S index 13ca891f..90975459 100644 --- a/src/arch/apple2e/apple2e.S +++ b/src/arch/apple2e/apple2e.S @@ -48,6 +48,7 @@ DECODE_TABLE_START = 0x96 SCREENF_CURSORSHOWN = 0x80 SCREENF_INVERSE = 0x40 +SCREENF_CURSORENABLED = 0x20 ;#define APPLE2 ;#define APPLE2PLUS @@ -131,6 +132,7 @@ _start: jsr initdrivers lda #0 + ora #(SCREENF_CURSORENABLED) sta cursorf ; Print the startup banner. @@ -276,7 +278,7 @@ screen_jmptable_lo: jmptablo screen_putchar jmptablo screen_putstring jmptablo screen_getchar - jmptablo fail ; screen_showcursor + jmptablo screen_showcursor jmptablo screen_scrollup jmptablo screen_scrolldown jmptablo screen_cleartoeol @@ -290,7 +292,7 @@ screen_jmptable_hi: jmptabhi screen_putchar jmptabhi screen_putstring jmptabhi screen_getchar - jmptabhi fail + jmptabhi screen_showcursor jmptabhi screen_scrollup jmptabhi screen_scrolldown jmptabhi screen_cleartoeol @@ -410,7 +412,12 @@ zproc screen_putstring rts zendproc +; XA = timeout in cs + zproc screen_getchar + sta ptr + stx ptr+1 + ; Turn the disk motor off. ldx #DISK_SLOT @@ -433,6 +440,28 @@ zproc screen_getchar rts zendproc +zproc screen_showcursor + cmp #0 + zif_eq + jsr prepare_for_screen_write + lda (ptr), y + ora #0x80 + sta (ptr), y + lda cursorf + and #(~SCREENF_CURSORENABLED) & 0xff ; unset bit 5, cursor is disabled + sta cursorf + zelse + lda cursorf + ora #SCREENF_CURSORENABLED ; set bit 5, cursor is enabled + sta cursorf + jsr prepare_for_screen_write + lda (ptr), y + and #0x7f + sta (ptr), y + zendif + rts +zendproc + zproc screen_scrollup jsr hide_cursor @@ -611,10 +640,14 @@ zproc hide_cursor zendproc zproc toggle_cursor - jsr prepare_for_screen_write - lda (ptr), y - eor #0x80 - sta (ptr), y + lda cursorf + and #(SCREENF_CURSORENABLED) ; draw cursor only if bit 5 it set + zif_ne + jsr prepare_for_screen_write + lda (ptr), y + eor #0x80 + sta (ptr), y + zendif lda cursorf eor #SCREENF_CURSORSHOWN From 3e45209ff44c6a0053af49445e5af97d0712e54d Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sat, 30 Nov 2024 14:57:24 +0100 Subject: [PATCH 26/39] tetris: sorted out flickering and some portability issues --- third_party/tetris/tetris.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/third_party/tetris/tetris.c b/third_party/tetris/tetris.c index b7e4700d..445f25d8 100644 --- a/third_party/tetris/tetris.c +++ b/third_party/tetris/tetris.c @@ -22,12 +22,12 @@ #include #include "lib/screen.h" -#define WIDTH 12 -#define HEIGHT 20 +#define WIDTH (uint8_t)12 +#define HEIGHT (uint8_t)20 #define W (WIDTH + 2) #define H (HEIGHT + 1) -#define WXH (W * H) +#define WXH (uint16_t)(W * H) #define E '.' #define F '#' @@ -56,7 +56,7 @@ uint16_t figure[][4] = { uint8_t field[WXH]; struct player { - uint8_t figure_index, rot, x, y; + int8_t figure_index, rot, x, y; } gp; static void cr() @@ -81,8 +81,12 @@ int init() screen_showcursor(0); // invisible cursor // Init random generator - srand(42); - + // TODO: can we access the zero page from a user program? Or do we + // need a system call to get sort of a time since boot? +// uint16_t seed = (*((uint8_t *)0x004F) << 8) | *((uint8_t *)0x004E) ; + uint16_t seed = 21342; + srand( seed ); + // Init field memset(field, E, WXH-W); @@ -112,7 +116,7 @@ int figure_draw(char ch, struct player p) for (y = 0; y < 4; y++) { for (x = 0; x < 4; x++) { if (figure[p.figure_index][p.rot] & mask) { - int offset = (y + p.y) * W + x + p.x; + int16_t offset = (y + p.y) * W + x + p.x; if (ch == F && field[offset] != E) return 0; @@ -179,7 +183,7 @@ void end(uint16_t score) cpm_warmboot(); } -void field_print(int score) +void field_print(uint16_t score) { uint8_t y, x, sy, sx; @@ -212,7 +216,7 @@ int main() if (draw_next == 1) { draw_next = 0; - gp.figure_index = rand() % 7; + gp.figure_index = (uint8_t)rand() % 7; gp.x = W / 2 - 2; gp.y = 0; gp.rot = 0; @@ -228,7 +232,7 @@ int main() } p = gp; - key = screen_getchar(10); +// key = screen_getchar(10); switch (key) { case 'w': From 463a7ee3e227a52a8c5d0bd6bacbf5240f93b42e Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sun, 1 Dec 2024 13:16:16 +0100 Subject: [PATCH 27/39] scrntest: added "B" command to toggle blocking and non-blocking screen_getchar --- apps/scrntest.asm | 77 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 75 insertions(+), 2 deletions(-) diff --git a/apps/scrntest.asm b/apps/scrntest.asm index deb795e2..43da3379 100644 --- a/apps/scrntest.asm +++ b/apps/scrntest.asm @@ -15,8 +15,11 @@ .zp style, 1 .zp ptr1, 2 .zp ptr2, 2 +.zp kbd_blocking, 1 +.zp spinner_pos, 1 .label string_init .label string_a +.label chars_spinner .label BIOS .label SCREEN .label update_cursor @@ -59,6 +62,10 @@ lda #0 sta style + sta spinner_pos + + lda #1 + sta kbd_blocking help: \ Clear screen and print help @@ -95,9 +102,55 @@ mainloop: stx cur_y timeout: + \ Show spinnig bar to test non-blocking keyboard read + lda #39 + ldx #0 + ldy #SCREEN_SETCURSOR + jsr SCREEN + ldy spinner_pos + iny + tya + cmp #4 + .zif eq + ldy #0 + .zendif + sty spinner_pos + ldx kbd_blocking + .zif ne + lda #'*' + .zendif + ldx kbd_blocking + .zif eq + lda chars_spinner, y + .zendif + ldy #SCREEN_PUTCHAR + jsr SCREEN + + lda #39 + ldx #1 + ldy #SCREEN_SETCURSOR + jsr SCREEN + lda #32 + ldy #SCREEN_PUTCHAR + jsr SCREEN + + lda cur_x + ldx cur_y + ldy #SCREEN_SETCURSOR + jsr SCREEN + \ Get and parse command - lda #10 - ldx #00 + + ldy kbd_blocking + .zif ne + lda #0xff + ldx #0x7f + .zendif + ldy kbd_blocking + .zif eq + lda #0x10 + ldx #0x0 + .zendif ldy #SCREEN_GETCHAR jsr SCREEN bcs timeout \ make sure we don't have consecutive key presses because of short timeouts @@ -252,6 +305,21 @@ case_done: jsr SCREEN jmp mainloop .zendif + + \ Toggle keyboard read mode + cmp #'B' + .zif eq + lda kbd_blocking + .zif eq + lda #1 + sta kbd_blocking + jmp mainloop + .zendif + lda #0 + sta kbd_blocking + jmp mainloop + + .zendif \ Clear screen and print help cmp #'H' @@ -402,6 +470,7 @@ string_init: .byte "J - Scroll down\r\n" .byte "L - Clear to End of Line\r\n" .byte "I - Toggle style\r\n" + .byte "B - Toggle blocking/non-blocking read\r\n" .byte "H - Clear screen and print this help\r\n" .byte "Q - Quit\r\n" .byte 0 @@ -410,3 +479,7 @@ string_a: .byte "String" .byte 0 +chars_spinner: + .byte "-\\|/" + .byte 0 + From 9f142e81d5a2be6b8b7f509a688c02c207fd3d0e Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sun, 1 Dec 2024 15:55:45 +0100 Subject: [PATCH 28/39] tetris: played with some timeouts for screen_getchar and ACCEL --- third_party/tetris/tetris.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/third_party/tetris/tetris.c b/third_party/tetris/tetris.c index 445f25d8..0226aa85 100644 --- a/third_party/tetris/tetris.c +++ b/third_party/tetris/tetris.c @@ -33,7 +33,7 @@ #define F '#' // Simple acceleration calculation (unplayable over 9000 points) -#define ACCEL (100 - score / 100) +#define ACCEL (50 - score / 100) /* Example: figure "J" rotation 0 * 0b0100010001100000 @@ -232,7 +232,7 @@ int main() } p = gp; -// key = screen_getchar(10); + key = screen_getchar(10); switch (key) { case 'w': From 6609bca0e43fab72ae1b94b3762f55decb8eeca8 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sun, 1 Dec 2024 15:56:16 +0100 Subject: [PATCH 29/39] scrntest: some testing of getchar timeouts --- apps/scrntest.asm | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/apps/scrntest.asm b/apps/scrntest.asm index 43da3379..8b84a224 100644 --- a/apps/scrntest.asm +++ b/apps/scrntest.asm @@ -115,14 +115,14 @@ timeout: ldy #0 .zendif sty spinner_pos + \ldx kbd_blocking + \.zif ne + \ lda #'*' + \.zendif ldx kbd_blocking - .zif ne - lda #'*' - .zendif - ldx kbd_blocking - .zif eq + \.zif eq lda chars_spinner, y - .zendif + \.zendif ldy #SCREEN_PUTCHAR jsr SCREEN @@ -148,7 +148,7 @@ timeout: .zendif ldy kbd_blocking .zif eq - lda #0x10 + lda #10 \ 0.1 second timeout ldx #0x0 .zendif ldy #SCREEN_GETCHAR From 7460f0d670e1b3724c087002c81f36d01e845208 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sun, 1 Dec 2024 15:56:41 +0100 Subject: [PATCH 30/39] apple2e: implemented some timeout handling screen_getchar (untuned) --- src/arch/apple2e/apple2e.S | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/src/arch/apple2e/apple2e.S b/src/arch/apple2e/apple2e.S index 90975459..40944cde 100644 --- a/src/arch/apple2e/apple2e.S +++ b/src/arch/apple2e/apple2e.S @@ -412,11 +412,20 @@ zproc screen_putstring rts zendproc -; XA = timeout in cs +; XA = timeout in cs (X=MSB, A=LSB) +; carry set on timeout +; carry clean when A=key zproc screen_getchar sta ptr stx ptr+1 + ; this feels wrong, but how is otherwise X=0 working with DEC and underflows? + inc ptr+1 + + ; TODO: adjust here + ;~ clc + ;~ rol ptr+1 + ;~ rol ptr ; Turn the disk motor off. @@ -429,15 +438,27 @@ zproc screen_getchar jsr draw_cursor - ; Wait for the key. + ; Wait for the key, or time out - zrepeat - lda KBD_READ - zuntil_mi +_wait_loop: + ldy #$ff ; 255 * 5 cycles +_inner_loop: + lda KBD_READ ; 4 cycles + bpl _no_key ; 3 cycles, branch usually taken + ; got a key sta KBD_STROBERESET and #0x7f clc rts +_no_key: + dey ; 2 cycles + bne _inner_loop ; 3 cycles usually (unless 0) + dec ptr ; 5 cycles + bne _wait_loop ; 3 cycles (2 if 0) + dec ptr+1 ; 5 cycles + bne _wait_loop ; 3 cycles (2 if 0) + sec + rts zendproc zproc screen_showcursor From db211e87a9fa8af47ac771c22e8b5eea32f0c99d Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sat, 14 Dec 2024 11:55:01 +0100 Subject: [PATCH 31/39] added a second tetris (because we need more tetris) --- config.py | 1 + third_party/tetris2/build.py | 8 + third_party/tetris2/tetris2.c | 257 ++++++++++++++++++++++++++++++++ third_party/tetris2/tetris2.pas | 240 +++++++++++++++++++++++++++++ 4 files changed, 506 insertions(+) create mode 100644 third_party/tetris2/build.py create mode 100644 third_party/tetris2/tetris2.c create mode 100644 third_party/tetris2/tetris2.pas diff --git a/config.py b/config.py index 8bcb49bb..ecf911c5 100644 --- a/config.py +++ b/config.py @@ -45,6 +45,7 @@ "0:qe.com": "apps+qe", "0:scrntest.com": "apps+scrntest", "0:tetris.com": "third_party/tetris", + "0:tetris2.com": "third_party/tetris2", "0:vt52drv.com": "apps+vt52drv", "0:vt52test.com": "apps+vt52test", "0:kbdtest.com": "apps+kbdtest", diff --git a/third_party/tetris2/build.py b/third_party/tetris2/build.py new file mode 100644 index 00000000..c574b03d --- /dev/null +++ b/third_party/tetris2/build.py @@ -0,0 +1,8 @@ +from build.ab import Rule, Target, Targets, simplerule +from build.llvm import llvmprogram + +llvmprogram( + name="tetris2", + srcs=["./tetris2.c"], + deps=["lib+cpm65"] +) diff --git a/third_party/tetris2/tetris2.c b/third_party/tetris2/tetris2.c new file mode 100644 index 00000000..cdd7725c --- /dev/null +++ b/third_party/tetris2/tetris2.c @@ -0,0 +1,257 @@ +/* Simple Tetris in the terminal, adapted for CP/M-65, */ +/* generated by using p2c with tetris.pas for CP/M 2.2 Apple ][ */ +/* A.Baumann, 14.12.2024, 0BSD clause */ + +#include +#include +#include +#include +#include +#include +#include "lib/screen.h" + +#define Delay 100 +#define BoardHeight 20 +#define BoardWidth 10 +#define NofShapes 5 + +static uint8_t Shapes[5][4][4] = { + /* I */ + { { 0, 0, 0, 0 }, + { 1, 1, 1, 1 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 } }, + /* O */ + { { 0, 1, 1, 0 }, + { 0, 1, 1, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 } }, + /* T */ + { { 0, 1, 0, 0 }, + { 1, 1, 1, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 } }, + /* L */ + { { 0, 0, 1, 0 }, + { 1, 1, 1, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 } }, + /* Z */ + { { 1, 1, 0, 0 }, + { 0, 1, 1, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 } } +}; + +uint8_t Board[BoardHeight][BoardWidth]; +bool GameOver; +uint8_t CurrentPiece, CurrentRotation, PosX, PosY; + +static void InitializeBoard(void) +{ + memset(Board, 0, sizeof(uint8_t) * BoardWidth * sizeof(uint8_t) * 10); +} + +static void DrawBoard(void) +{ + uint8_t x, y; + + for (y = 1; y <= BoardHeight; y++) { + for (x = 1; x <= BoardWidth; x++) { + screen_setcursor(x,y); + if (Board[y-1][x-1] == 1) + screen_putchar('#'); + else + screen_putchar('.'); + } + } +} + + +static void DrawPiece(bool Erase) +{ + uint8_t x, y; + + for (y = 0; y <= 3; y++) { + for (x = 0; x <= 3; x++) { + if (Shapes[CurrentPiece][y][x] == 1) { + screen_setcursor(PosX + x, PosY + y); + if (Erase) + screen_putchar('.'); + else + screen_putchar('#'); + } + } + } +} + +static bool CanMove(int8_t dx, int8_t dy) +{ + int8_t x, y; + + for (y = 0; y <= 3; y++) { + for (x = 0; x <= 3; x++) { + if (Shapes[CurrentPiece][y][x] == 1) { + if (PosX + x + dx < 1 || PosX + x + dx > BoardWidth || + PosY + y + dy > BoardHeight || + Board[PosY + y + dy - 1][PosX + x + dx - 1] == 1) + return false; + } + } + } + return true; +} + +static void NewPiece(void) +{ + CurrentPiece = (uint8_t)rand() % NofShapes; + CurrentRotation = 0; + PosX = BoardWidth / 2 - 2; + PosY = 1; + if (!CanMove(0, 0)) + GameOver = true; +} + +static void RotatePiece(void) +{ + uint8_t Temp[4][4]; + uint8_t x, y; + + for (y = 0; y <= 3; y++) { + for (x = 0; x <= 3; x++) + Temp[y][x] = Shapes[CurrentPiece][3 - x][y]; + } + if (!CanMove(0, 0)) + return; + for (y = 0; y <= 3; y++) { + for (x = 0; x <= 3; x++) + Shapes[CurrentPiece][y][x] = Temp[y][x]; + } +} + +static void PlacePiece(void) +{ + uint8_t x, y; + + for (y = 0; y <= 3; y++) { + for (x = 0; x <= 3; x++) { + if (Shapes[CurrentPiece][y][x] == 1) + Board[PosY + y - 1][PosX + x - 1] = 1; + } + } +} + +static void ClearLines(void) +{ + uint8_t x, y, ny; + bool Full; + bool Redraw = false; + + for (y = BoardHeight; y >= 1; y--) { + Full = true; + for (x = 0; x < BoardWidth; x++) { + if (Board[y-1][x] == 0) + Full = false; + } + if (Full) { + for (ny = y; ny >= 2; ny--) { + for (x = 0; x < BoardWidth; x++) + Board[ny-1][x] = Board[ny-2][x]; + } + for (x = 0; x < BoardWidth; x++) + Board[0][x] = 0; + Redraw = true; + } + } + if (Redraw) + DrawBoard(); +} + +static void HandleInput(void) +{ + uint8_t c; + + c = screen_getchar(Delay); + if (c > 0) { + c = toupper(c); + switch (c) { + case 'A': + if (CanMove(-1, 0)) { + DrawPiece(true); + PosX--; + DrawPiece(false); + } + break; + + case 'D': + if (CanMove(1, 0)) { + DrawPiece(true); + PosX++; + DrawPiece(false); + } + break; + + case 'S': + if (CanMove(0, 1)) { + DrawPiece(true); + PosY++; + DrawPiece(false); + } + break; + + case ' ': + while (CanMove(0, 1)) { + DrawPiece(true); + PosY++; + DrawPiece(false); + } + break; + + case 'W': + DrawPiece(true); + RotatePiece(); + DrawPiece(false); + break; + + case 'Q': + GameOver = true; + break; + } + } +} + +int main(void) +{ + if(!screen_init()) { + cpm_printstring("No SCREEN driver, exiting\n\r"); + cpm_warmboot(); + } + screen_clear(); + screen_showcursor(0); + + srand( 21342 ); + InitializeBoard(); + DrawBoard(); + GameOver = false; + NewPiece(); + while (!GameOver) { + DrawPiece(false); + HandleInput(); + if (CanMove(0, 1)) { + DrawPiece(true); + PosY++; + DrawPiece(false); + } else { + PlacePiece(); + ClearLines(); + NewPiece(); + } + if (PosY >= BoardHeight) + GameOver = true; + } + screen_clear(); + printf("Thanks for playing.\n"); + screen_showcursor(1); + + cpm_warmboot(); +} diff --git a/third_party/tetris2/tetris2.pas b/third_party/tetris2/tetris2.pas new file mode 100644 index 00000000..bfd89e52 --- /dev/null +++ b/third_party/tetris2/tetris2.pas @@ -0,0 +1,240 @@ +(* Simple Tetris in the terminal, for CP/M 2.2 Apple ][ *) +(* A.Baumann, 13.12.2024, 0BSD clause *) + +PROGRAM Tetris; + +CONST + Delay = 20; + BoardHeight = 20; + BoardWidth = 10; + NofShapes = 5; + Shapes : ARRAY[0..4,0..3,0..3] OF Byte = + (((0,0,0,0),(1,1,1,1),(0,0,0,0),(0,0,0,0)), (* I *) + ((0,1,1,0),(0,1,1,0),(0,0,0,0),(0,0,0,0)), (* O *) + ((0,1,0,0),(1,1,1,0),(0,0,0,0),(0,0,0,0)), (* T *) + ((0,0,1,0),(1,1,1,0),(0,0,0,0),(0,0,0,0)), (* L *) + ((1,1,0,0),(0,1,1,0),(0,0,0,0),(0,0,0,0))); (* Z *) + +VAR + Board : ARRAY[1..BoardHeight,1..BoardWidth] OF Byte; + GameOver : Boolean; + CurrentPiece : Integer; + CurrentRotation : Integer; + PosX, PosY : Integer; + +PROCEDURE InitializeBoard; +BEGIN + FillChar(Board,SizeOf(Board),0) +END; + +PROCEDURE DrawBoard; +VAR + x, y : Integer; +BEGIN + FOR y := 1 TO BoardHeight DO + BEGIN + FOR x := 1 TO BoardWidth DO + BEGIN + GotoXY(x,y); + IF Board[y,x] = 1 THEN + Write('#') + ELSE + Write('.') + END + END +END; + +PROCEDURE DrawPiece(Erase : Boolean); +VAR + x, y : Integer; +BEGIN + FOR y := 0 TO 3 DO + FOR x := 0 TO 3 DO + IF Shapes[CurrentPiece,y,x] = 1 THEN + BEGIN + GotoXY(PosX+x,PosY+y); + IF Erase THEN + Write('.') + ELSE + Write('#') + END +END; + +FUNCTION ReadKey : Char; +BEGIN + ReadKey := Chr(BDOS(6,$FF)) +END; + +FUNCTION CanMove(dx, dy : Integer) : Boolean; +VAR + x, y : Integer; +BEGIN + CanMove := True; + FOR y := 0 TO 3 DO + FOR x := 0 TO 3 DO + IF Shapes[CurrentPiece,y,x] = 1 THEN + BEGIN + IF (PosX+x+dx<1) OR (PosX+x+dx>BoardWidth) OR + (PosY+y+dy>BoardHeight) OR + (Board[PosY+y+dy,PosX+x+dx]=1) THEN + BEGIN + CanMove := False; + Exit + END + END +END; + +PROCEDURE NewPiece; +BEGIN + CurrentPiece := Random(NofShapes); + CurrentRotation := 0; + PosX := (BoardWidth div 2)-2; + PosY := 1; + IF NOT CanMove(0,0) THEN + GameOver := True +END; + +PROCEDURE RotatePiece; +VAR + Temp : ARRAY[0..3,0..3] OF Byte; + x, y : Integer; +BEGIN + FOR y := 0 TO 3 DO + FOR x := 0 TO 3 DO + Temp[y,x] := Shapes[CurrentPiece,3-x,y]; + IF CanMove(0,0) THEN + FOR y := 0 TO 3 DO + FOR x := 0 TO 3 DO + Shapes[CurrentPiece,y,x] := Temp[y,x]; +END; + +PROCEDURE PlacePiece; +VAR + x, y : Integer; +BEGIN + FOR y := 0 TO 3 DO + FOR x := 0 TO 3 DO + IF Shapes[CurrentPiece,y,x] = 1 THEN + Board[PosY+y,PosX+x] := 1 +END; + +PROCEDURE ClearLines; +VAR + x, y, ny : Integer; + Full : Boolean; + Redraw : Boolean; +BEGIN + Redraw := False; + FOR y := BoardHeight DOWNTO 1 DO + BEGIN + Full := True; + FOR x := 1 TO BoardWidth DO + IF Board[y,x] = 0 THEN + BEGIN + Full := False + END; + IF Full THEN + BEGIN + FOR ny := y DOWNTO 2 DO + FOR x := 1 TO BoardWidth DO + Board[ny,x] := Board[ny-1,x]; + FOR X := 1 TO BoardWidth DO + Board[1,x] := 0; + Redraw := True + END + END; + IF Redraw THEN + DrawBoard +END; + +PROCEDURE HandleInput; +VAR + c : Char; + i, j : Integer; +BEGIN + i := 0; + WHILE NOT KeyPressed AND (i= BoardHeight THEN + GameOver := True; + END; + ClrScr; + WriteLn('Thanks for playing.'); + CrtExit; +END. From 9878aef6c5234aba0fd48e106f0bc14507a037e0 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sat, 14 Dec 2024 13:24:33 +0100 Subject: [PATCH 32/39] tetris2: code cleanup and fixed some portability issues --- third_party/tetris2/tetris2.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/third_party/tetris2/tetris2.c b/third_party/tetris2/tetris2.c index cdd7725c..e8b9b7a0 100644 --- a/third_party/tetris2/tetris2.c +++ b/third_party/tetris2/tetris2.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -15,7 +16,7 @@ #define BoardWidth 10 #define NofShapes 5 -static uint8_t Shapes[5][4][4] = { +static uint8_t Shapes[NofShapes][4][4] = { /* I */ { { 0, 0, 0, 0 }, { 1, 1, 1, 1 }, @@ -36,7 +37,7 @@ static uint8_t Shapes[5][4][4] = { { 1, 1, 1, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } }, - /* Z */ + /* Z */ { { 1, 1, 0, 0 }, { 0, 1, 1, 0 }, { 0, 0, 0, 0 }, @@ -45,7 +46,8 @@ static uint8_t Shapes[5][4][4] = { uint8_t Board[BoardHeight][BoardWidth]; bool GameOver; -uint8_t CurrentPiece, CurrentRotation, PosX, PosY; +uint8_t CurrentPiece, CurrentRotation; +int8_t PosX, PosY; static void InitializeBoard(void) { @@ -95,7 +97,7 @@ static bool CanMove(int8_t dx, int8_t dy) if (PosX + x + dx < 1 || PosX + x + dx > BoardWidth || PosY + y + dy > BoardHeight || Board[PosY + y + dy - 1][PosX + x + dx - 1] == 1) - return false; + return false; } } } @@ -229,7 +231,7 @@ int main(void) screen_clear(); screen_showcursor(0); - srand( 21342 ); + srand( 21342 ); InitializeBoard(); DrawBoard(); GameOver = false; @@ -249,9 +251,9 @@ int main(void) if (PosY >= BoardHeight) GameOver = true; } - screen_clear(); + screen_clear(); printf("Thanks for playing.\n"); screen_showcursor(1); - cpm_warmboot(); + cpm_warmboot(); } From 92e38ba31cebae7da5d0ace4eca578a374cc2567 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sat, 14 Dec 2024 13:27:55 +0100 Subject: [PATCH 33/39] tetris: adapted some timers --- third_party/tetris/tetris.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/third_party/tetris/tetris.c b/third_party/tetris/tetris.c index 0226aa85..79bc93b1 100644 --- a/third_party/tetris/tetris.c +++ b/third_party/tetris/tetris.c @@ -33,7 +33,7 @@ #define F '#' // Simple acceleration calculation (unplayable over 9000 points) -#define ACCEL (50 - score / 100) +#define ACCEL (10 - score / 100) /* Example: figure "J" rotation 0 * 0b0100010001100000 From 5c0a6e6b429a4902f9198a64e3031bd2e13f5e82 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sun, 15 Dec 2024 14:54:52 +0100 Subject: [PATCH 34/39] apple2e: added a third floppy dedicated to pascal, made every floppy bootable --- build.py | 1 + config.py | 1 + cpmfs/build.py | 2 +- cpmfs/pasc.txt | 6 ++++++ src/arch/apple2e/build.py | 24 ++++++++++++++++++++---- 5 files changed, 29 insertions(+), 5 deletions(-) create mode 100644 cpmfs/pasc.txt diff --git a/build.py b/build.py index 933e1e46..bc7ca91f 100644 --- a/build.py +++ b/build.py @@ -20,6 +20,7 @@ "images/oric.dsk": "src/arch/oric+diskimage", "images/apple2e.po": "src/arch/apple2e+diskimage", "images/apple2e_b.po": "src/arch/apple2e+diskimage_b", + "images/apple2e_c.po": "src/arch/apple2e+diskimage_c", "images/atari800.atr": "src/arch/atari800+atari800_diskimage", "images/atari800b.atr": "src/arch/atari800+atari800b_diskimage", "images/atari800c.atr": "src/arch/atari800+atari800c_diskimage", diff --git a/config.py b/config.py index ecf911c5..d248bcca 100644 --- a/config.py +++ b/config.py @@ -61,6 +61,7 @@ PASCAL_APPS = { "0:pint.com": "third_party/pascal-m+pint", + "0:pasc.txt": "cpmfs+pasc_txt_cpm", "0:pasc.obb": "third_party/pascal-m+pasc-obb", "0:pload.com": "third_party/pascal-m+loader", "0:hello.pas": "cpmfs+hello_pas_cpm", diff --git a/cpmfs/build.py b/cpmfs/build.py index 579f0004..d2e0f1c2 100644 --- a/cpmfs/build.py +++ b/cpmfs/build.py @@ -1,6 +1,6 @@ from tools.build import unixtocpm -for f in ["asm", "atbasic", "bedit"]: +for f in ["asm", "atbasic", "bedit", "pasc"]: unixtocpm(name="%s_txt_cpm" % f, src="./%s.txt" % f) unixtocpm(name="demo_sub_cpm", src="./demo.sub") diff --git a/cpmfs/pasc.txt b/cpmfs/pasc.txt new file mode 100644 index 00000000..3fdbb20c --- /dev/null +++ b/cpmfs/pasc.txt @@ -0,0 +1,6 @@ +Pascal-M +-------- + +pint pasc.obb hello.pas hello.obp +pload hello.obp hello.obb +pint hello.obb diff --git a/src/arch/apple2e/build.py b/src/arch/apple2e/build.py index efb673b1..3ad96121 100644 --- a/src/arch/apple2e/build.py +++ b/src/arch/apple2e/build.py @@ -63,7 +63,8 @@ "0:cls.com": "apps+cls", } | MINIMAL_APPS - | MINIMAL_APPS_SRCS, + | MINIMAL_APPS_SRCS + | SCREEN_APPS_SRCS ) mkcpmfs( @@ -72,16 +73,31 @@ bootimage=".+bios_shuffled", size=143360, items={ + "0:ccp.sys@sr": "src+ccp-tiny", + "0:bdos.sys@sr": "src/bdos", + "0:cls.com": "apps+cls", "0:atbasic.com": "third_party/altirrabasic", "0:atbasic.txt": "cpmfs+atbasic_txt_cpm", "0:qe.com": "apps+qe", } + | MINIMAL_APPS | SCREEN_APPS - | SCREEN_APPS_SRCS - | BIG_SCREEN_APPS - | PASCAL_APPS, ) +mkcpmfs( + name="diskimage_c", + format="appleiie", + bootimage=".+bios_shuffled", + size=143360, + items={ + "0:ccp.sys@sr": "src+ccp-tiny", + "0:bdos.sys@sr": "src/bdos", + "0:copy.com": "apps+copy", + } + | MINIMAL_APPS + | BIG_SCREEN_APPS + | PASCAL_APPS +) mametest( name="mametest", From 34517f2691b54b67e7e8e4de3eef80730380c983 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sun, 29 Dec 2024 21:24:58 +0100 Subject: [PATCH 35/39] tetris2: fixed several bugs --- third_party/tetris2/tetris2.c | 53 ++++++----- third_party/tetris2/tetris2.pas | 153 ++++++++++++++++---------------- 2 files changed, 110 insertions(+), 96 deletions(-) diff --git a/third_party/tetris2/tetris2.c b/third_party/tetris2/tetris2.c index e8b9b7a0..ed01c6bf 100644 --- a/third_party/tetris2/tetris2.c +++ b/third_party/tetris2/tetris2.c @@ -14,7 +14,7 @@ #define Delay 100 #define BoardHeight 20 #define BoardWidth 10 -#define NofShapes 5 +#define NofShapes 7 static uint8_t Shapes[NofShapes][4][4] = { /* I */ @@ -32,11 +32,21 @@ static uint8_t Shapes[NofShapes][4][4] = { { 1, 1, 1, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } }, + /* J */ + { { 1, 0, 0, 0 }, + { 1, 1, 1, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 } }, /* L */ { { 0, 0, 1, 0 }, { 1, 1, 1, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } }, + /* S */ + { { 0, 1, 1, 0 }, + { 1, 1, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 } }, /* Z */ { { 1, 1, 0, 0 }, { 0, 1, 1, 0 }, @@ -46,12 +56,12 @@ static uint8_t Shapes[NofShapes][4][4] = { uint8_t Board[BoardHeight][BoardWidth]; bool GameOver; -uint8_t CurrentPiece, CurrentRotation; +uint8_t CurrentPiece; int8_t PosX, PosY; static void InitializeBoard(void) { - memset(Board, 0, sizeof(uint8_t) * BoardWidth * sizeof(uint8_t) * 10); + memset(Board, 0, sizeof(uint8_t) * BoardWidth * sizeof(uint8_t) * BoardWidth); } static void DrawBoard(void) @@ -107,7 +117,6 @@ static bool CanMove(int8_t dx, int8_t dy) static void NewPiece(void) { CurrentPiece = (uint8_t)rand() % NofShapes; - CurrentRotation = 0; PosX = BoardWidth / 2 - 2; PosY = 1; if (!CanMove(0, 0)) @@ -117,18 +126,22 @@ static void NewPiece(void) static void RotatePiece(void) { uint8_t Temp[4][4]; + uint8_t Save[4][4]; uint8_t x, y; - for (y = 0; y <= 3; y++) { + for (y = 0; y <= 3; y++) + for (x = 0; x <= 3; x++) + Save[y][x] = Shapes[CurrentPiece][y][x]; + for (y = 0; y <= 3; y++) for (x = 0; x <= 3; x++) Temp[y][x] = Shapes[CurrentPiece][3 - x][y]; - } - if (!CanMove(0, 0)) - return; - for (y = 0; y <= 3; y++) { + for (y = 0; y <= 3; y++) for (x = 0; x <= 3; x++) Shapes[CurrentPiece][y][x] = Temp[y][x]; - } + if (!CanMove(0, 0)) + for (y = 0; y <= 3; y++) + for (x = 0; x <= 3; x++) + Shapes[CurrentPiece][y][x] = Save[y][x]; } static void PlacePiece(void) @@ -143,7 +156,7 @@ static void PlacePiece(void) } } -static void ClearLines(void) +static bool ClearLines(void) { uint8_t x, y, ny; bool Full; @@ -165,8 +178,7 @@ static void ClearLines(void) Redraw = true; } } - if (Redraw) - DrawBoard(); + return Redraw; } static void HandleInput(void) @@ -175,9 +187,8 @@ static void HandleInput(void) c = screen_getchar(Delay); if (c > 0) { - c = toupper(c); switch (c) { - case 'A': + case 'A': case 'a': if (CanMove(-1, 0)) { DrawPiece(true); PosX--; @@ -185,7 +196,7 @@ static void HandleInput(void) } break; - case 'D': + case 'D': case 'd': if (CanMove(1, 0)) { DrawPiece(true); PosX++; @@ -193,7 +204,7 @@ static void HandleInput(void) } break; - case 'S': + case 'S': case 's': if (CanMove(0, 1)) { DrawPiece(true); PosY++; @@ -209,13 +220,13 @@ static void HandleInput(void) } break; - case 'W': + case 'W': case 'w': DrawPiece(true); RotatePiece(); DrawPiece(false); break; - case 'Q': + case 'Q': case 'q': GameOver = true; break; } @@ -245,7 +256,9 @@ int main(void) DrawPiece(false); } else { PlacePiece(); - ClearLines(); + while (ClearLines()) { + DrawBoard(); + } NewPiece(); } if (PosY >= BoardHeight) diff --git a/third_party/tetris2/tetris2.pas b/third_party/tetris2/tetris2.pas index bfd89e52..14fbd34a 100644 --- a/third_party/tetris2/tetris2.pas +++ b/third_party/tetris2/tetris2.pas @@ -4,22 +4,23 @@ PROGRAM Tetris; CONST - Delay = 20; + DelayTicks = 40; BoardHeight = 20; BoardWidth = 10; - NofShapes = 5; - Shapes : ARRAY[0..4,0..3,0..3] OF Byte = + NofShapes = 7; + Shapes : ARRAY[1..7,0..3,0..3] OF Byte = (((0,0,0,0),(1,1,1,1),(0,0,0,0),(0,0,0,0)), (* I *) ((0,1,1,0),(0,1,1,0),(0,0,0,0),(0,0,0,0)), (* O *) ((0,1,0,0),(1,1,1,0),(0,0,0,0),(0,0,0,0)), (* T *) + ((1,0,0,0),(1,1,1,0),(0,0,0,0),(0,0,0,0)), (* J *) ((0,0,1,0),(1,1,1,0),(0,0,0,0),(0,0,0,0)), (* L *) + ((0,1,1,0),(1,1,0,0),(0,0,0,0),(0,0,0,0)), (* S *) ((1,1,0,0),(0,1,1,0),(0,0,0,0),(0,0,0,0))); (* Z *) VAR Board : ARRAY[1..BoardHeight,1..BoardWidth] OF Byte; GameOver : Boolean; CurrentPiece : Integer; - CurrentRotation : Integer; PosX, PosY : Integer; PROCEDURE InitializeBoard; @@ -75,19 +76,22 @@ IF Shapes[CurrentPiece,y,x] = 1 THEN BEGIN IF (PosX+x+dx<1) OR (PosX+x+dx>BoardWidth) OR - (PosY+y+dy>BoardHeight) OR - (Board[PosY+y+dy,PosX+x+dx]=1) THEN - BEGIN - CanMove := False; - Exit - END + (PosY+y+dy>BoardHeight) THEN + BEGIN + CanMove := False; + Exit + END; + IF (Board[PosY+y+dy,PosX+x+dx]>=1) THEN + BEGIN + CanMove := False; + Exit + END END END; PROCEDURE NewPiece; BEGIN - CurrentPiece := Random(NofShapes); - CurrentRotation := 0; + CurrentPiece := 1+Random(NofShapes); PosX := (BoardWidth div 2)-2; PosY := 1; IF NOT CanMove(0,0) THEN @@ -96,16 +100,22 @@ PROCEDURE RotatePiece; VAR - Temp : ARRAY[0..3,0..3] OF Byte; + Temp, Save : ARRAY[0..3,0..3] OF Byte; x, y : Integer; BEGIN + FOR y := 0 TO 3 DO + FOR x := 0 TO 3 DO + Save[y,x] := Shapes[CurrentPiece,y,x]; FOR y := 0 TO 3 DO FOR x := 0 TO 3 DO Temp[y,x] := Shapes[CurrentPiece,3-x,y]; - IF CanMove(0,0) THEN + FOR y := 0 TO 3 DO + FOR x := 0 TO 3 DO + Shapes[CurrentPiece,y,x] := Temp[y,x]; + IF NOT CanMove(0,0) THEN FOR y := 0 TO 3 DO FOR x := 0 TO 3 DO - Shapes[CurrentPiece,y,x] := Temp[y,x]; + Shapes[CurrentPiece,y,x] := Save[y,x]; END; PROCEDURE PlacePiece; @@ -115,16 +125,15 @@ FOR y := 0 TO 3 DO FOR x := 0 TO 3 DO IF Shapes[CurrentPiece,y,x] = 1 THEN - Board[PosY+y,PosX+x] := 1 + Board[PosY+y,PosX+x] := CurrentPiece END; -PROCEDURE ClearLines; +FUNCTION ClearLines : Boolean; VAR x, y, ny : Integer; Full : Boolean; - Redraw : Boolean; BEGIN - Redraw := False; + ClearLines := False; FOR y := BoardHeight DOWNTO 1 DO BEGIN Full := True; @@ -138,72 +147,65 @@ FOR ny := y DOWNTO 2 DO FOR x := 1 TO BoardWidth DO Board[ny,x] := Board[ny-1,x]; - FOR X := 1 TO BoardWidth DO + FOR x := 1 TO BoardWidth DO Board[1,x] := 0; - Redraw := True + ClearLines := True END END; - IF Redraw THEN - DrawBoard END; PROCEDURE HandleInput; VAR c : Char; - i, j : Integer; + i : Integer; BEGIN i := 0; - WHILE NOT KeyPressed AND (i= BoardHeight THEN - GameOver := True; END; ClrScr; WriteLn('Thanks for playing.'); From 3f16ab757ccf63c53be168dddaaeba54a9207dbb Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sun, 5 Jan 2025 19:32:59 +0100 Subject: [PATCH 36/39] tetris2: added pause mode, fixed line elimination, showing next char, printing letter instead of # for pieces --- third_party/tetris2/tetris2.c | 90 +++++++++++++++++++++------------ third_party/tetris2/tetris2.pas | 81 ++++++++++++++++++++--------- 2 files changed, 115 insertions(+), 56 deletions(-) diff --git a/third_party/tetris2/tetris2.c b/third_party/tetris2/tetris2.c index ed01c6bf..7234d24e 100644 --- a/third_party/tetris2/tetris2.c +++ b/third_party/tetris2/tetris2.c @@ -11,7 +11,7 @@ #include #include "lib/screen.h" -#define Delay 100 +#define Delay 200 #define BoardHeight 20 #define BoardWidth 10 #define NofShapes 7 @@ -53,15 +53,16 @@ static uint8_t Shapes[NofShapes][4][4] = { { 0, 0, 0, 0 }, { 0, 0, 0, 0 } } }; +static uint8_t ShapeChars[NofShapes] = {'I', 'O', 'T', 'J', 'L', 'S', 'Z' }; uint8_t Board[BoardHeight][BoardWidth]; bool GameOver; -uint8_t CurrentPiece; +uint8_t CurrentPiece, NextPiece; int8_t PosX, PosY; static void InitializeBoard(void) { - memset(Board, 0, sizeof(uint8_t) * BoardWidth * sizeof(uint8_t) * BoardWidth); + memset(Board, 0xFF, sizeof(Board)); } static void DrawBoard(void) @@ -71,8 +72,8 @@ static void DrawBoard(void) for (y = 1; y <= BoardHeight; y++) { for (x = 1; x <= BoardWidth; x++) { screen_setcursor(x,y); - if (Board[y-1][x-1] == 1) - screen_putchar('#'); + if (Board[y-1][x-1] != 0xFF) + screen_putchar(ShapeChars[Board[y-1][x-1]]); else screen_putchar('.'); } @@ -80,18 +81,18 @@ static void DrawBoard(void) } -static void DrawPiece(bool Erase) +static void DrawPiece(uint8_t piece, int8_t x, int8_t y,bool Erase) { - uint8_t x, y; + uint8_t nx, ny; - for (y = 0; y <= 3; y++) { - for (x = 0; x <= 3; x++) { - if (Shapes[CurrentPiece][y][x] == 1) { - screen_setcursor(PosX + x, PosY + y); + for (ny = 0; ny <= 3; ny++) { + for (nx = 0; nx <= 3; nx++) { + if (Shapes[piece][ny][nx] == 1) { + screen_setcursor(x + nx, y + ny); if (Erase) screen_putchar('.'); else - screen_putchar('#'); + screen_putchar(ShapeChars[piece]); } } } @@ -106,7 +107,7 @@ static bool CanMove(int8_t dx, int8_t dy) if (Shapes[CurrentPiece][y][x] == 1) { if (PosX + x + dx < 1 || PosX + x + dx > BoardWidth || PosY + y + dy > BoardHeight || - Board[PosY + y + dy - 1][PosX + x + dx - 1] == 1) + Board[PosY + y + dy - 1][PosX + x + dx - 1] != 0xFF) return false; } } @@ -114,9 +115,24 @@ static bool CanMove(int8_t dx, int8_t dy) return true; } +static void DrawNextPiece(void) +{ + int8_t x, y; + + for (y = 10; y <= 13; y++) { + for (x = 12; x <= 15; x++) { + screen_setcursor(x, y); + screen_putchar('.'); + } + } + DrawPiece(NextPiece, 12, 10, false); +} + static void NewPiece(void) { - CurrentPiece = (uint8_t)rand() % NofShapes; + CurrentPiece = NextPiece; + NextPiece = (uint8_t)rand() % NofShapes; + DrawNextPiece(); PosX = BoardWidth / 2 - 2; PosY = 1; if (!CanMove(0, 0)) @@ -151,7 +167,7 @@ static void PlacePiece(void) for (y = 0; y <= 3; y++) { for (x = 0; x <= 3; x++) { if (Shapes[CurrentPiece][y][x] == 1) - Board[PosY + y - 1][PosX + x - 1] = 1; + Board[PosY + y - 1][PosX + x - 1] = CurrentPiece; } } } @@ -162,10 +178,10 @@ static bool ClearLines(void) bool Full; bool Redraw = false; - for (y = BoardHeight; y >= 1; y--) { + for (y = 1; y <= BoardHeight; y++) { Full = true; for (x = 0; x < BoardWidth; x++) { - if (Board[y-1][x] == 0) + if (Board[y-1][x] == 0xFF) Full = false; } if (Full) { @@ -174,7 +190,7 @@ static bool ClearLines(void) Board[ny-1][x] = Board[ny-2][x]; } for (x = 0; x < BoardWidth; x++) - Board[0][x] = 0; + Board[0][x] = 0xFF; Redraw = true; } } @@ -190,40 +206,51 @@ static void HandleInput(void) switch (c) { case 'A': case 'a': if (CanMove(-1, 0)) { - DrawPiece(true); + DrawPiece(CurrentPiece, PosX, PosY, true); PosX--; - DrawPiece(false); + DrawPiece(CurrentPiece, PosX, PosY, false); } break; case 'D': case 'd': if (CanMove(1, 0)) { - DrawPiece(true); + DrawPiece(CurrentPiece, PosX, PosY, true); PosX++; - DrawPiece(false); + DrawPiece(CurrentPiece, PosX, PosY, false); } break; case 'S': case 's': if (CanMove(0, 1)) { - DrawPiece(true); + DrawPiece(CurrentPiece, PosX, PosY, true); PosY++; - DrawPiece(false); + DrawPiece(CurrentPiece, PosX, PosY, false); } break; case ' ': while (CanMove(0, 1)) { - DrawPiece(true); + DrawPiece(CurrentPiece, PosX, PosY, true); PosY++; - DrawPiece(false); + DrawPiece(CurrentPiece, PosX, PosY, false); } break; case 'W': case 'w': - DrawPiece(true); + DrawPiece(CurrentPiece, PosX, PosY, true); RotatePiece(); - DrawPiece(false); + DrawPiece(CurrentPiece, PosX, PosY, false); + break; + + case 'P': case 'p': + screen_setcursor(12,7); + cpm_printstring("Game paused."); + screen_setcursor(12,8); + cpm_printstring("Press any key to continue."); + screen_waitchar(); + screen_clear(); + DrawBoard(); + DrawNextPiece(); break; case 'Q': case 'q': @@ -246,14 +273,15 @@ int main(void) InitializeBoard(); DrawBoard(); GameOver = false; + NextPiece = (uint8_t)rand() % NofShapes; NewPiece(); while (!GameOver) { - DrawPiece(false); + DrawPiece(CurrentPiece, PosX, PosY, false); HandleInput(); if (CanMove(0, 1)) { - DrawPiece(true); + DrawPiece(CurrentPiece, PosX, PosY, true); PosY++; - DrawPiece(false); + DrawPiece(CurrentPiece, PosX, PosY, false); } else { PlacePiece(); while (ClearLines()) { diff --git a/third_party/tetris2/tetris2.pas b/third_party/tetris2/tetris2.pas index 14fbd34a..370c071d 100644 --- a/third_party/tetris2/tetris2.pas +++ b/third_party/tetris2/tetris2.pas @@ -16,11 +16,13 @@ ((0,0,1,0),(1,1,1,0),(0,0,0,0),(0,0,0,0)), (* L *) ((0,1,1,0),(1,1,0,0),(0,0,0,0),(0,0,0,0)), (* S *) ((1,1,0,0),(0,1,1,0),(0,0,0,0),(0,0,0,0))); (* Z *) + ShapeChars : ARRAY[0..7] OF Char = + (' ','I','O','T','J','L','S','Z'); VAR Board : ARRAY[1..BoardHeight,1..BoardWidth] OF Byte; GameOver : Boolean; - CurrentPiece : Integer; + CurrentPiece, NextPiece : Integer; PosX, PosY : Integer; PROCEDURE InitializeBoard; @@ -37,27 +39,27 @@ FOR x := 1 TO BoardWidth DO BEGIN GotoXY(x,y); - IF Board[y,x] = 1 THEN - Write('#') + IF Board[y,x] >= 1 THEN + Write(ShapeChars[Board[y,x]]) ELSE Write('.') END END END; -PROCEDURE DrawPiece(Erase : Boolean); +PROCEDURE DrawPiece(Piece : Integer; x, y : Integer; Erase : Boolean); VAR - x, y : Integer; + nx, ny : Integer; BEGIN - FOR y := 0 TO 3 DO - FOR x := 0 TO 3 DO - IF Shapes[CurrentPiece,y,x] = 1 THEN + FOR ny := 0 TO 3 DO + FOR nx := 0 TO 3 DO + IF Shapes[Piece,ny,nx] = 1 THEN BEGIN - GotoXY(PosX+x,PosY+y); + GotoXY(nx+x,ny+y); IF Erase THEN Write('.') ELSE - Write('#') + Write(ShapeChars[Piece]) END END; @@ -89,9 +91,24 @@ END END; +PROCEDURE DrawNextPiece; +VAR + x, y : Integer; +BEGIN + FOR y := 10 TO 13 DO + FOR x := 12 TO 15 DO + BEGIN + GotoXY(x,y); + Write('.') + END; + DrawPiece(NextPiece,12,10,False); +END; + PROCEDURE NewPiece; BEGIN - CurrentPiece := 1+Random(NofShapes); + CurrentPiece := NextPiece; + NextPiece := 1+Random(NofShapes); + DrawNextPiece; PosX := (BoardWidth div 2)-2; PosY := 1; IF NOT CanMove(0,0) THEN @@ -134,7 +151,7 @@ Full : Boolean; BEGIN ClearLines := False; - FOR y := BoardHeight DOWNTO 1 DO + FOR y := 1 TO BoardHeight DO BEGIN Full := True; FOR x := 1 TO BoardWidth DO @@ -169,36 +186,48 @@ 'A','a',#8: IF CanMove(-1,0) THEN BEGIN - DrawPiece(True); + DrawPiece(CurrentPiece,PosX,PosY,True); PosX := PosX-1; - DrawPiece(False) + DrawPiece(CurrentPiece,PosX,PosY,False) END; 'D','d',#9: IF CanMove(1,0) THEN BEGIN - DrawPiece(True); + DrawPiece(CurrentPiece,PosX,PosY,True); PosX := PosX+1; - DrawPiece(False) + DrawPiece(CurrentPiece,PosX,PosY,False) END; 'S','s',#10: IF CanMove(0,1) THEN BEGIN - DrawPiece(True); + DrawPiece(CurrentPiece,PosX,PosY,True); PosY := PosY+1; - DrawPiece(False) + DrawPiece(CurrentPiece,PosX,PosY,False) END; ' ': WHILE CanMove(0,1) DO BEGIN - DrawPiece(True); + DrawPiece(CurrentPiece,PosX,PosY,True); PosY := PosY+1; - DrawPiece(False) + DrawPiece(CurrentPiece,PosX,PosY,False) END; 'W','w',#11: BEGIN - DrawPiece(True); + DrawPiece(CurrentPiece,PosX,PosY,True); RotatePiece; - DrawPiece(False) + DrawPiece(CurrentPiece,PosX,PosY,False) + END; + 'P','p': + BEGIN + GotoXY(12,7); + Write('Game paused.'); + GotoXY(12,8); + Write('Press any key to continue.'); + WHILE NOT KeyPressed DO + Delay(10); + ClrScr; + DrawBoard; + DrawNextPiece END; 'Q','q': GameOver := True; @@ -216,16 +245,17 @@ ClrScr; DrawBoard; GameOver := False; + NextPiece := 1+Random(NofShapes); NewPiece; WHILE NOT GameOver DO BEGIN - DrawPiece(False); + DrawPiece(CurrentPiece,PosX,PosY,False); HandleInput; IF CanMove(0,1) THEN BEGIN - DrawPiece(True); + DrawPiece(CurrentPiece,PosX,PosY,True); PosY := PosY+1; - DrawPiece(False) + DrawPiece(CurrentPiece,PosX,PosY,False) END ELSE BEGIN @@ -237,5 +267,6 @@ END; ClrScr; WriteLn('Thanks for playing.'); + Delay(2000); CrtExit; END. From 6adbf105096f731f637a95dadfb20516edc0428b Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sun, 5 Jan 2025 19:51:13 +0100 Subject: [PATCH 37/39] tetris2: using inverse mode for pieces, use also screen cursor keys --- third_party/tetris2/tetris2.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/third_party/tetris2/tetris2.c b/third_party/tetris2/tetris2.c index 7234d24e..7ce06e2d 100644 --- a/third_party/tetris2/tetris2.c +++ b/third_party/tetris2/tetris2.c @@ -72,12 +72,16 @@ static void DrawBoard(void) for (y = 1; y <= BoardHeight; y++) { for (x = 1; x <= BoardWidth; x++) { screen_setcursor(x,y); - if (Board[y-1][x-1] != 0xFF) + if (Board[y-1][x-1] != 0xFF) { + screen_setstyle(1); screen_putchar(ShapeChars[Board[y-1][x-1]]); - else + } else { + screen_setstyle(0); screen_putchar('.'); + } } } + screen_setstyle(0); } @@ -85,6 +89,7 @@ static void DrawPiece(uint8_t piece, int8_t x, int8_t y,bool Erase) { uint8_t nx, ny; + screen_setstyle(!Erase); for (ny = 0; ny <= 3; ny++) { for (nx = 0; nx <= 3; nx++) { if (Shapes[piece][ny][nx] == 1) { @@ -96,6 +101,7 @@ static void DrawPiece(uint8_t piece, int8_t x, int8_t y,bool Erase) } } } + screen_setstyle(0); } static bool CanMove(int8_t dx, int8_t dy) @@ -204,7 +210,7 @@ static void HandleInput(void) c = screen_getchar(Delay); if (c > 0) { switch (c) { - case 'A': case 'a': + case 'A': case 'a': case SCREEN_KEY_LEFT: if (CanMove(-1, 0)) { DrawPiece(CurrentPiece, PosX, PosY, true); PosX--; @@ -212,7 +218,7 @@ static void HandleInput(void) } break; - case 'D': case 'd': + case 'D': case 'd': case SCREEN_KEY_RIGHT: if (CanMove(1, 0)) { DrawPiece(CurrentPiece, PosX, PosY, true); PosX++; @@ -220,7 +226,7 @@ static void HandleInput(void) } break; - case 'S': case 's': + case 'S': case 's': case SCREEN_KEY_DOWN: if (CanMove(0, 1)) { DrawPiece(CurrentPiece, PosX, PosY, true); PosY++; @@ -236,7 +242,7 @@ static void HandleInput(void) } break; - case 'W': case 'w': + case 'W': case 'w': case SCREEN_KEY_UP: DrawPiece(CurrentPiece, PosX, PosY, true); RotatePiece(); DrawPiece(CurrentPiece, PosX, PosY, false); From 31673057e66a6ffa016d94cecbe9d28af1c190fd Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sat, 23 Aug 2025 08:54:00 +0200 Subject: [PATCH 38/39] adapted to new zif style --- apps/scrntest.asm | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/apps/scrntest.asm b/apps/scrntest.asm index 5f0e9221..0399170a 100644 --- a/apps/scrntest.asm +++ b/apps/scrntest.asm @@ -112,18 +112,18 @@ timeout: iny tya cmp #4 - .zif eq + zif eq ldy #0 - .zendif + zendif sty spinner_pos \ldx kbd_blocking - \.zif ne + \zif ne \ lda #'*' - \.zendif + \zendif ldx kbd_blocking - \.zif eq + \zif eq lda chars_spinner, y - \.zendif + \zendif ldy #SCREEN_PUTCHAR jsr SCREEN @@ -143,15 +143,15 @@ timeout: \ Get and parse command ldy kbd_blocking - .zif ne + zif ne lda #0xff ldx #0x7f - .zendif + zendif ldy kbd_blocking - .zif eq + zif eq lda #10 \ 0.1 second timeout ldx #0x0 - .zendif + zendif ldy #SCREEN_GETCHAR jsr SCREEN bcs timeout \ make sure we don't have consecutive key presses because of short timeouts @@ -305,22 +305,22 @@ case_done: ldy #SCREEN_SETSTYLE jsr SCREEN jmp mainloop - .zendif + zendif \ Toggle keyboard read mode cmp #'B' - .zif eq + zif eq lda kbd_blocking - .zif eq + zif eq lda #1 sta kbd_blocking jmp mainloop - .zendif + zendif lda #0 sta kbd_blocking jmp mainloop - .zendif + zendif \ Draw line numbers cmp #'N' From 21ff3eced69c392fef120f5d6a14f02ec13b663a Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sat, 23 Aug 2025 13:42:33 +0200 Subject: [PATCH 39/39] using some new zifs --- src/arch/apple2e/apple2e.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/arch/apple2e/apple2e.S b/src/arch/apple2e/apple2e.S index b9b6b3e5..8758bcee 100644 --- a/src/arch/apple2e/apple2e.S +++ b/src/arch/apple2e/apple2e.S @@ -463,7 +463,7 @@ zendproc zproc screen_showcursor cmp #0 - zif_eq + zif eq jsr prepare_for_screen_write lda (ptr), y ora #0x80 @@ -663,7 +663,7 @@ zendproc zproc toggle_cursor lda cursorf and #(SCREENF_CURSORENABLED) ; draw cursor only if bit 5 it set - zif_ne + zif ne jsr prepare_for_screen_write lda (ptr), y eor #0x80