mirror of
https://github.com/irmen/prog8.git
synced 2025-07-01 18:24:06 +00:00
Compare commits
5 Commits
languageSe
...
v11.4
Author | SHA1 | Date | |
---|---|---|---|
1b420f7fe7 | |||
6a9a82ff9d | |||
aa36e6b19f | |||
51cb6aad50 | |||
b5ce409592 |
@ -96,7 +96,7 @@ What does Prog8 provide?
|
||||
- "c64": Commodore-64 (6502 like CPU)
|
||||
- "c128": Commodore-128 (6502 like CPU - the Z80 cpu mode is not supported)
|
||||
- "pet32": Commodore PET (limited support)
|
||||
- via external configurable targets: Atari 800 XL, Neo6502, NES, C64OS, ...
|
||||
- via external configurable targets: Atari 800 XL, Neo6502, NES, C64 OS, Foenix F256, ...
|
||||
- If you only use standard kernal and prog8 library routines, it is possible to compile the *exact same program* for different machines (just change the compiler target flag)
|
||||
|
||||
|
||||
|
@ -317,10 +317,25 @@ c128 {
|
||||
&ubyte VM4 = $0A2F ; starting page for VDC attribute mem
|
||||
|
||||
|
||||
; TODO c128 a bunch of kernal routines are missing here that are specific to the c128
|
||||
|
||||
extsub $FF6E = JSRFAR()
|
||||
extsub $FF68 = SETBNK(ubyte databank @A, ubyte filenamebank @X)
|
||||
extsub $FF47 = SPIN_SPOUT() clobbers(A) ; set up serial bus for fast communications mode
|
||||
extsub $FF4A = CLOSE_ALL(ubyte device @X) clobbers(X) ; close all channels to specific device
|
||||
extsub $FF4D = C64_MODE() ; restart machine in C64 mode (does not return)
|
||||
extsub $FF50 = DMA_CALL(ubyte bank @X, ubyte command @Y) clobbers(A,X) ; send a command to a DMA device
|
||||
extsub $FF53 = BOOT_CALL(ubyte device @X, ubyte drive @A) clobbers(A,X,Y) ; try to autoboot the given disk
|
||||
extsub $FF56 = PHOENIX() clobbers(A,X,Y) ; search for and autostart ROMs, cartridges, then default disk
|
||||
extsub $FF59 = LKUPLA(ubyte lfn @A) -> bool @Pc, ubyte @X ; look up logical file number to see if it's open; returns device
|
||||
extsub $FF5C = LKUPSA(ubyte sa @Y) -> bool @Pc, ubyte @A, ubyte @X ; look up secondary address to see if it's in use; returns lfn and device
|
||||
extsub $FF5F = SWAPPER() clobbers(A,X,Y) ; swap active screen (between 40- and 80-column)
|
||||
extsub $FF62 = DLCHR() clobbers(A,X,Y) ; copy character ROM into VDC video RAM
|
||||
extsub $FF65 = PFKEY(ubyte zpaddr @A, ubyte key @X, ubyte length @Y) ; redefine programmable function key (string descriptor in zp, addr in A)
|
||||
extsub $FF68 = SETBNK(ubyte data_bank @A, ubyte filename_bank @X) ; set memory bank for load/save
|
||||
extsub $FF6B = GETCFG(ubyte bank @X) -> ubyte @A ; translate bank number to MMU configuration register value
|
||||
extsub $FF6E = JSRFAR() clobbers(A,X) ; call routine in another bank (parameters set in zero page addresses 2-8)
|
||||
extsub $FF71 = JMPFAR() clobbers(A,X) ; jump without return to another bank (parameters set as for JSRFAR)
|
||||
extsub $FF74 = INDFET(ubyte zpaddr @A, ubyte bank @X, ubyte offset @Y) clobbers(X) -> ubyte @A ; fetch byte from another bank (address in zp, ptr in A)
|
||||
extsub $FF77 = INDSTA(ubyte value @A, ubyte bank @X, ubyte offset @Y) clobbers(X) ; store byte to another bank (address in zp, ptr in $02b9)
|
||||
extsub $FF7A = INDCMP(ubyte value @A, ubyte bank @X, ubyte offset @Y) clobbers(X) -> bool @Pz, bool @Pc, bool @Pv; compare byte in another bank (address in zp, ptr in $02c8)
|
||||
extsub $FF7D = PRIMM() ; print immediate string
|
||||
|
||||
|
||||
; ---- C128 specific system utility routines: ----
|
||||
|
@ -494,8 +494,25 @@ c128 {
|
||||
&ubyte VM2
|
||||
&ubyte VM3
|
||||
&ubyte VM4
|
||||
JSRFAR () = $ff6e
|
||||
SETBNK (ubyte databank @A, ubyte filenamebank @X) = $ff68
|
||||
BOOT_CALL (ubyte device @X, ubyte drive @A) -> clobbers (A,X,Y) = $ff53
|
||||
C64_MODE () = $ff4d
|
||||
CLOSE_ALL (ubyte device @X) -> clobbers (X) = $ff4a
|
||||
DLCHR () -> clobbers (A,X,Y) = $ff62
|
||||
DMA_CALL (ubyte bank @X, ubyte command @Y) -> clobbers (A,X) = $ff50
|
||||
GETCFG (ubyte bank @X) -> ubyte @A = $ff6b
|
||||
INDCMP (ubyte value @A, ubyte bank @X, ubyte offset @Y) -> clobbers (X) -> bool @Pz, bool @Pc, bool @Pv = $ff7a
|
||||
INDFET (ubyte zpaddr @A, ubyte bank @X, ubyte offset @Y) -> clobbers (X) -> ubyte @A = $ff74
|
||||
INDSTA (ubyte value @A, ubyte bank @X, ubyte offset @Y) -> clobbers (X) = $ff77
|
||||
JMPFAR () -> clobbers (A,X) = $ff71
|
||||
JSRFAR () -> clobbers (A,X) = $ff6e
|
||||
LKUPLA (ubyte lfn @A) -> bool @Pc, ubyte @X = $ff59
|
||||
LKUPSA (ubyte sa @Y) -> bool @Pc, ubyte @A, ubyte @X = $ff5c
|
||||
PFKEY (ubyte zpaddr @A, ubyte key @X, ubyte length @Y) = $ff65
|
||||
PHOENIX () -> clobbers (A,X,Y) = $ff56
|
||||
PRIMM () = $ff7d
|
||||
SETBNK (ubyte data_bank @A, ubyte filename_bank @X) = $ff68
|
||||
SPIN_SPOUT () -> clobbers (A) = $ff47
|
||||
SWAPPER () -> clobbers (A,X,Y) = $ff5f
|
||||
banks (ubyte banks @A)
|
||||
disable_basic () -> clobbers (A)
|
||||
getbanks () -> ubyte @A
|
||||
|
@ -27,8 +27,8 @@ You can compile programs for various machines that are built in into the compile
|
||||
* Commodore 128 (limited support)
|
||||
* Commodore PET (limited support)
|
||||
* any other 65(C)02 target machine or setup can be configured to a great extent in a user written configuration file.
|
||||
There are some examples included for the Atari 800 XL, NEO6502 and such.
|
||||
* some users have been experimenting with a NES and a C64OS target as well.
|
||||
There are some examples included for the Atari 800 XL, NEO6502, Foenix F256, and such.
|
||||
* some users have been experimenting with a NES and a C64 OS target as well.
|
||||
|
||||
Some language features are mentioned below, and you can also read :ref:`comparingprog8` if you
|
||||
want to quickly read about how Prog8 compares to well-known other languages.
|
||||
|
@ -1032,6 +1032,7 @@ sys (part of syslib)
|
||||
- 7 = Neo6502
|
||||
- 8 = Atari 8 bits
|
||||
- 16 = Commander X16
|
||||
- 25 = Foenix F256 family
|
||||
- 64 = Commodore 64
|
||||
- 128 = Commodore 128
|
||||
- 255 = Virtual machine
|
||||
|
@ -244,16 +244,9 @@ you have to make sure the resulting value fits into the byte or word size of the
|
||||
Booleans
|
||||
^^^^^^^^
|
||||
|
||||
Booleans are a distinct type in Prog8 and can have only the values ``true`` or ``false``.
|
||||
It can be casted to and from other integer types though
|
||||
where a nonzero integer is considered to be true, and zero is false.
|
||||
Logical expressions, comparisons and some other code tends to compile more efficiently if
|
||||
you explicitly use ``bool`` types instead of 0/1 integers.
|
||||
The in-memory representation of a boolean value is just a byte containing 0 or 1.
|
||||
|
||||
If you find that you need a whole bunch of boolean variables or perhaps even an array of them,
|
||||
consider using integer bit mask variable + bitwise operators instead.
|
||||
This saves a lot of memory and may be faster as well.
|
||||
Booleans are a distinct type called ``bool`` in Prog8 and can have only the values ``true`` or ``false``.
|
||||
In memory, they are stored as a byte containing 0 or 1.
|
||||
You can cast any numeric to a bool, in which case 0 will become ``false`` and any nonzero value will become ``true``.
|
||||
|
||||
|
||||
Floating point numbers
|
||||
|
@ -1,6 +1,6 @@
|
||||
.PHONY: all clean
|
||||
|
||||
all: main-c64.prg main-cx16.prg main-pet.prg atari-hello.xex atari-fibonacci.xex neo-hello.bin
|
||||
all: main-c64.prg main-cx16.prg main-pet.prg atari-hello.xex atari-fibonacci.xex neo-hello.bin f256-hello.bin
|
||||
|
||||
clean:
|
||||
rm -f *.prg *.PRG *.xex *.bin *.asm *.vice-*
|
||||
@ -26,6 +26,9 @@ atari-fibonacci.xex: src/atari-fibonacci.p8
|
||||
neo-hello.bin: src/neo-hello.p8
|
||||
prog8c -target targetconfigs/neo6502.properties src/neo-hello.p8
|
||||
|
||||
f256-hello.bin: src/f256-hello.p8
|
||||
prog8c -target targetconfigs/f256.properties src/f256-hello.p8
|
||||
|
||||
run-atari-hello:
|
||||
prog8c -target targetconfigs/atari.properties src/atari-hello.p8 -emu
|
||||
|
||||
|
907
examples/customtarget/libraries/f256/syslib.p8
Normal file
907
examples/customtarget/libraries/f256/syslib.p8
Normal file
@ -0,0 +1,907 @@
|
||||
; Prog8 definitions for the Foenix F256x
|
||||
|
||||
%option no_symbol_prefixing, ignore_unused
|
||||
|
||||
; compatiblity layer
|
||||
cbm {
|
||||
%option no_symbol_prefixing, ignore_unused
|
||||
|
||||
; dumb hack to make some code compile.
|
||||
; TODO: figure out how the kernel clock works, not just
|
||||
; reading the RTC hardware
|
||||
ubyte TIME_LO = $00
|
||||
|
||||
;
|
||||
; Only reads keys right now.
|
||||
;
|
||||
asmsub CHRIN() -> ubyte @A {
|
||||
%asm {{
|
||||
- stz f256.event.type ; invalidate existing event type
|
||||
jsr f256.event.NextEvent
|
||||
lda f256.event.type
|
||||
cmp #f256.event.key.PRESSED
|
||||
bne -
|
||||
lda f256.event.key.ascii ; return upper or lower ASCII
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
; I though the alias was working but it isn't.
|
||||
;alias CHROUT = f256.chrout
|
||||
asmsub CHROUT(ubyte character @ A) {
|
||||
%asm {{
|
||||
jmp f256.chrout
|
||||
}}
|
||||
}
|
||||
|
||||
; TODO: set carry properly?
|
||||
; TODO: on CBM any device other than keyboard or RS-232 should jump to CHRIN
|
||||
asmsub GETIN() -> bool @Pc, ubyte @A {
|
||||
%asm {{
|
||||
- stz f256.event.type ; invalidate previous event type
|
||||
lda f256.event.pending ; return zero if no pending event
|
||||
cmp #$ff ; $ff == no events pending
|
||||
beq + ; done.
|
||||
jsr f256.event.NextEvent
|
||||
lda f256.event.type
|
||||
cmp #f256.event.key.PRESSED
|
||||
bne -
|
||||
;lda f256.event.key.raw ; return key id / scan code? (case issue?)
|
||||
lda f256.event.key.ascii ; return upper or lower ASCII
|
||||
clc ; clear carry when returning character
|
||||
rts ; return ascii key
|
||||
+ sec ; set carry when no character returned
|
||||
lda #0 ; return zero if no key
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
|
||||
asmsub GETINx() -> bool @Pc, ubyte @A {
|
||||
%asm {{
|
||||
rts
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
||||
f256 {
|
||||
%option no_symbol_prefixing, ignore_unused, force_output
|
||||
;
|
||||
; Foenix F256 hardware definitions
|
||||
;
|
||||
|
||||
; MMU controls
|
||||
&ubyte mem_ctrl = $0000
|
||||
&ubyte io_ctrl = $0001
|
||||
|
||||
; text screen size
|
||||
const ubyte DEFAULT_WIDTH = 80
|
||||
const ubyte DEFAULT_HEIGHT = 60
|
||||
|
||||
; screen / color memory
|
||||
const uword Colors = $C000 ; IO page 2
|
||||
const uword Screen = $C000 ; IO page 3
|
||||
|
||||
; self tracked screen coordinates
|
||||
; potentially could be at $04/$05 in reserved ZP area?
|
||||
ubyte screen_row = 0
|
||||
ubyte screen_col = 0
|
||||
ubyte screen_color = $f2 ; default text/background color
|
||||
&uword screen_ptr = $02 ; and $03. used to calculate screen/color ram offsets
|
||||
|
||||
;
|
||||
; calculates screen memory pointer for the start of a row
|
||||
; in screen_ptr in zeropage.
|
||||
; ldy column
|
||||
; sta (screen_ptr), y
|
||||
;
|
||||
asmsub rowptr(ubyte row @Y) {
|
||||
%asm {{
|
||||
stz screen_ptr ; reset to start of screen ram
|
||||
lda #>f256.Screen
|
||||
sta screen_ptr+1
|
||||
cpy #0 ; row in @Y will be our loop counter
|
||||
beq ptr_done
|
||||
rowloop:
|
||||
clc
|
||||
lda screen_ptr ; load count
|
||||
adc #DEFAULT_WIDTH
|
||||
bcc +
|
||||
inc screen_ptr+1
|
||||
+ sta screen_ptr
|
||||
dey
|
||||
bne rowloop
|
||||
ptr_done:
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
;
|
||||
; calculates screen memory pointer for the specific col/row
|
||||
; in screen_ptr in zeropage. Points directly to character after.
|
||||
; ldy #0
|
||||
; sta (screen_ptr), y
|
||||
;
|
||||
asmsub chrptr(ubyte col @X, ubyte row @Y) clobbers(A) {
|
||||
%asm {{
|
||||
phx ; preserve col
|
||||
jsr rowptr ; calculate pointer to row
|
||||
pla ; restore col
|
||||
clc
|
||||
adc screen_ptr
|
||||
sta screen_ptr
|
||||
bcc +
|
||||
inc screen_ptr+1
|
||||
+ rts
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub chrout(ubyte character @ A) {
|
||||
%asm {{
|
||||
phx ; preserve x
|
||||
phy ; preserve y
|
||||
cmp #$0d ; check for carriage return
|
||||
beq crlf
|
||||
cmp #$0a ; check for line feed
|
||||
beq crlf
|
||||
pha ; preserve a
|
||||
ldy screen_row
|
||||
jsr rowptr ; calculates screen pointer to start of row
|
||||
ldy screen_col ; column will be our index against the row pointer
|
||||
lda #2
|
||||
sta f256.io_ctrl ; map in screen memory
|
||||
pla
|
||||
sta (screen_ptr),y
|
||||
lda #3
|
||||
sta f256.io_ctrl ; map in color memory
|
||||
lda screen_color
|
||||
sta (screen_ptr),y
|
||||
lda #0
|
||||
sta f256.io_ctrl ; return to default map
|
||||
inc screen_col
|
||||
lda screen_col
|
||||
cmp #DEFAULT_WIDTH
|
||||
bcc + ; less than DEFAULT_WIDTH
|
||||
crlf:
|
||||
stz screen_col
|
||||
inc screen_row
|
||||
lda screen_row
|
||||
cmp #DEFAULT_HEIGHT
|
||||
bcc +
|
||||
sec
|
||||
jsr scroll_up
|
||||
dec screen_row
|
||||
+ ply
|
||||
plx
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
;
|
||||
; implement here so chrout can work without importing textio.
|
||||
;
|
||||
asmsub scroll_up (bool alsocolors @ Pc) clobbers(A,X) {
|
||||
; ---- scroll the whole screen 1 character up
|
||||
; contents of the bottom row are unchanged, you should refill/clear this yourself
|
||||
; Carry flag determines if screen color data must be scrolled too
|
||||
%asm {{
|
||||
bcc _scroll_screen
|
||||
|
||||
+ ; scroll the screen and the color memory
|
||||
ldx #DEFAULT_WIDTH-1
|
||||
-
|
||||
lda #2
|
||||
sta f256.io_ctrl ; map in screen memory
|
||||
.for row=1, row<=DEFAULT_HEIGHT, row+=1
|
||||
lda f256.Screen + DEFAULT_WIDTH*row,x
|
||||
sta f256.Screen + DEFAULT_WIDTH*(row-1),x
|
||||
.next
|
||||
lda #3
|
||||
sta f256.io_ctrl ; map in color memory
|
||||
.for row=1, row<=DEFAULT_HEIGHT, row+=1
|
||||
lda f256.Colors + DEFAULT_WIDTH*row,x
|
||||
sta f256.Colors + DEFAULT_WIDTH*(row-1),x
|
||||
.next
|
||||
|
||||
|
||||
dex
|
||||
bpl -
|
||||
lda #0
|
||||
sta f256.io_ctrl ; restore I/O configuration
|
||||
rts
|
||||
|
||||
_scroll_screen ; scroll only the screen memory
|
||||
ldx #DEFAULT_WIDTH-1
|
||||
-
|
||||
lda #2
|
||||
sta f256.io_ctrl ; map in screen memory
|
||||
.for row=1, row<=DEFAULT_HEIGHT, row+=1
|
||||
lda f256.Screen + DEFAULT_WIDTH*row,x
|
||||
sta f256.Screen + DEFAULT_WIDTH*(row-1),x
|
||||
.next
|
||||
dex
|
||||
bpl -
|
||||
lda #0
|
||||
sta f256.io_ctrl ; restore I/O configuration
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
; args
|
||||
sub args() {
|
||||
&uword ext = $00f8
|
||||
&ubyte extlen = $00fa
|
||||
&uword buf = $00fb
|
||||
&ubyte buflen = $00fd
|
||||
&uword ptr = $00fe
|
||||
}
|
||||
|
||||
; kernel event calls & event types
|
||||
sub event() {
|
||||
&uword dest = $00f0
|
||||
&ubyte pending = $00f2
|
||||
&ubyte[8] packet = $00e8 ; 8-byte buffer in ZP for kernel events.
|
||||
|
||||
; event buffer fields
|
||||
&ubyte type = &packet ; event type (definitions below)
|
||||
&ubyte buf = &packet+1 ; page id or zero
|
||||
&ubyte ext = &packet+2 ; page id or zero
|
||||
|
||||
; kernel event calls
|
||||
extsub $ff00 = NextEvent() ; Copy next event to application buffer.
|
||||
extsub $ff04 = ReadData() ; Copy primary bulk event data to application.
|
||||
extsub $ff08 = ReadExt() ; Copy secondary bulk event data to application.
|
||||
|
||||
sub init() {
|
||||
f256.event.dest = &f256.event.packet
|
||||
}
|
||||
|
||||
; event type definitions
|
||||
const uword reserved = $00 ; $01
|
||||
const uword deprecated = $02 ; $03
|
||||
const uword JOYSTICK = $04 ; $05 ; game controller changes
|
||||
const uword DEVICE = $06 ; $07 ; device added or removed
|
||||
sub key() {
|
||||
const uword PRESSED = $08 ; $09
|
||||
const uword RELEASED = $0a ; $0b
|
||||
&ubyte keyboard = &packet+3 ; keyboard id
|
||||
&ubyte raw = &packet+4 ; raw key id/code
|
||||
&ubyte ascii = &packet+5 ; ASCII value
|
||||
&ubyte flags = &packet+6 ; flag (META)
|
||||
const ubyte META = $80 ; meta key no ASCII value
|
||||
}
|
||||
sub mouse() {
|
||||
const uword DELTA = $0c ; $0d
|
||||
const uword CLICKS = $0e ; $0f
|
||||
}
|
||||
sub block() {
|
||||
const uword NAME = $10 ; $11
|
||||
const uword SIZE = $12 ; $13
|
||||
const uword DATA = $14 ; $15 ; read request succeeded
|
||||
const uword WROTE = $16 ; $17 ; write request completed
|
||||
const uword FORMATTED = $18 ; $19 ; low-level format completed
|
||||
const uword ERROR = $1a ; $1b
|
||||
}
|
||||
sub fs() {
|
||||
const uword SIZE = $1c ; $1d
|
||||
const uword CREATED = $1e ; $1f
|
||||
const uword CHECKED = $20 ; $21
|
||||
const uword DATA = $22 ; $23 ; read request succeeded
|
||||
const uword WROTE = $24 ; $25 ; write request completed
|
||||
const uword ERROR = $26 ; $27
|
||||
}
|
||||
sub file() {
|
||||
const uword NOT_FOUND = $28 ; $29 ; file was not found
|
||||
const uword OPENED = $2a ; $2b ; file successfully opened
|
||||
const uword DATA = $2c ; $2d ; read request succeeded
|
||||
const uword WROTE = $2e ; $2f ; write request completed
|
||||
const uword EOF = $30 ; $31 ; all file data has been read
|
||||
const uword CLOSED = $32 ; $33 ; close request completed
|
||||
const uword RENAMED = $34 ; $35 ; renamed request completed
|
||||
const uword DELETED = $36 ; $37 ; delete request completed
|
||||
const uword ERROR = $38 ; $39 ; error occurred, close file if opened
|
||||
const uword SEEK = $3a ; $3b ; seek request completed
|
||||
}
|
||||
sub directory() {
|
||||
const uword OPENED = $3c ; $3d ; directory open succeeded
|
||||
const uword VOLUME = $3e ; $3f ; volume record found
|
||||
const uword FILE = $40 ; $41 ; file record found
|
||||
const uword FREE = $42 ; $43 ; file-system free-space record found
|
||||
const uword EOF = $44 ; $45 ; all data read
|
||||
const uword CLOSED = $46 ; $47 ; directory file closed
|
||||
const uword ERROR = $48 ; $49 ; error occurred, close if opened
|
||||
const uword CREATED = $4a ; $4b ; directory created
|
||||
const uword DELETED = $4a ; $4b ; directory deleted
|
||||
}
|
||||
sub net() {
|
||||
const uword TCP = $4c ; $4d
|
||||
const uword UDP = $4e ; $4f
|
||||
}
|
||||
sub timer() {
|
||||
const uword EXPIRED = $50 ; $51
|
||||
}
|
||||
sub clock() {
|
||||
const uword TICK = $52 ; $53
|
||||
}
|
||||
sub irq() {
|
||||
const uword IRQ = $54 ; $55
|
||||
}
|
||||
}
|
||||
|
||||
; kernel display calls
|
||||
sub display() {
|
||||
&ubyte x = $00f3
|
||||
&ubyte y = $00f4
|
||||
&uword color = &f256.args.ext
|
||||
&uword text = &f256.args.buf
|
||||
&ubyte buflen = &f256.args.buflen
|
||||
const uword GetSize_ = $ffd0 ; Get screen dimensions
|
||||
const uword DrawRow_ = $ffd4 ; Draw text/color buffers left-to-right
|
||||
const uword DrawColumn_ = $ffd8 ; Draw text/color buffers top-to-bottom
|
||||
}
|
||||
|
||||
|
||||
|
||||
;
|
||||
&uword NMI_VEC = $FFFA ; 6502 nmi vector
|
||||
&uword RESET_VEC = $FFFC ; 6502 reset vector
|
||||
&uword IRQ_VEC = $FFFE ; 6502 interrupt vector
|
||||
|
||||
;%asminclude "api.asm"
|
||||
}
|
||||
|
||||
sys {
|
||||
; ------- lowlevel system routines --------
|
||||
|
||||
const ubyte target = 25 ; compilation target specifier. 255=virtual, 128=C128, 64=C64, 32=PET, 25=Foenix F256, 16=CommanderX16, 8=atari800XL, 7=Neo6502
|
||||
|
||||
const ubyte SIZEOF_BOOL = sizeof(bool)
|
||||
const ubyte SIZEOF_BYTE = sizeof(byte)
|
||||
const ubyte SIZEOF_UBYTE = sizeof(ubyte)
|
||||
const ubyte SIZEOF_WORD = sizeof(word)
|
||||
const ubyte SIZEOF_UWORD = sizeof(uword)
|
||||
const ubyte SIZEOF_LONG = sizeof(long)
|
||||
; const ubyte SIZEOF_POINTER = sizeof(&sys.wait)
|
||||
const ubyte SIZEOF_FLOAT = 0 ; undefined, no floats supported
|
||||
const byte MIN_BYTE = -128
|
||||
const byte MAX_BYTE = 127
|
||||
const ubyte MIN_UBYTE = 0
|
||||
const ubyte MAX_UBYTE = 255
|
||||
const word MIN_WORD = -32768
|
||||
const word MAX_WORD = 32767
|
||||
const uword MIN_UWORD = 0
|
||||
const uword MAX_UWORD = 65535
|
||||
; MIN_FLOAT and MAX_FLOAT are defined in the floats module if importec
|
||||
|
||||
|
||||
asmsub reset_system() {
|
||||
; Soft-reset the system back to initial power-on status
|
||||
; TODO
|
||||
%asm {{
|
||||
sei
|
||||
jmp (f256.RESET_VEC)
|
||||
}}
|
||||
}
|
||||
|
||||
sub wait(uword jiffies) {
|
||||
; --- wait approximately the given number of jiffies (1/60th seconds)
|
||||
; TODO
|
||||
}
|
||||
|
||||
asmsub waitvsync() clobbers(A) {
|
||||
; --- busy wait till the next vsync has occurred (approximately), without depending on custom irq handling.
|
||||
; TODO
|
||||
%asm {{
|
||||
nop
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub internal_stringcopy(uword source @R0, uword target @AY) clobbers (A,Y) {
|
||||
; Called when the compiler wants to assign a string value to another string.
|
||||
%asm {{
|
||||
sta P8ZP_SCRATCH_W1
|
||||
sty P8ZP_SCRATCH_W1+1
|
||||
lda cx16.r0
|
||||
ldy cx16.r0+1
|
||||
jmp prog8_lib.strcpy
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub memcopy(uword source @R0, uword target @R1, uword count @AY) clobbers(A,X,Y) {
|
||||
; note: only works for NON-OVERLAPPING memory regions!
|
||||
; note: can't be inlined because is called from asm as well
|
||||
%asm {{
|
||||
ldx cx16.r0
|
||||
stx P8ZP_SCRATCH_W1 ; source in ZP
|
||||
ldx cx16.r0+1
|
||||
stx P8ZP_SCRATCH_W1+1
|
||||
ldx cx16.r1
|
||||
stx P8ZP_SCRATCH_W2 ; target in ZP
|
||||
ldx cx16.r1+1
|
||||
stx P8ZP_SCRATCH_W2+1
|
||||
cpy #0
|
||||
bne _longcopy
|
||||
|
||||
; copy <= 255 bytes
|
||||
tay
|
||||
bne _copyshort
|
||||
rts ; nothing to copy
|
||||
|
||||
_copyshort
|
||||
dey
|
||||
beq +
|
||||
- lda (P8ZP_SCRATCH_W1),y
|
||||
sta (P8ZP_SCRATCH_W2),y
|
||||
dey
|
||||
bne -
|
||||
+ lda (P8ZP_SCRATCH_W1),y
|
||||
sta (P8ZP_SCRATCH_W2),y
|
||||
rts
|
||||
|
||||
_longcopy
|
||||
sta P8ZP_SCRATCH_B1 ; lsb(count) = remainder in last page
|
||||
tya
|
||||
tax ; x = num pages (1+)
|
||||
ldy #0
|
||||
- lda (P8ZP_SCRATCH_W1),y
|
||||
sta (P8ZP_SCRATCH_W2),y
|
||||
iny
|
||||
bne -
|
||||
inc P8ZP_SCRATCH_W1+1
|
||||
inc P8ZP_SCRATCH_W2+1
|
||||
dex
|
||||
bne -
|
||||
ldy P8ZP_SCRATCH_B1
|
||||
bne _copyshort
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub memset(uword mem @R0, uword numbytes @R1, ubyte value @A) clobbers(A,X,Y) {
|
||||
%asm {{
|
||||
ldy cx16.r0
|
||||
sty P8ZP_SCRATCH_W1
|
||||
ldy cx16.r0+1
|
||||
sty P8ZP_SCRATCH_W1+1
|
||||
ldx cx16.r1
|
||||
ldy cx16.r1+1
|
||||
jmp prog8_lib.memset
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub memsetw(uword mem @R0, uword numwords @R1, uword value @AY) clobbers(A,X,Y) {
|
||||
%asm {{
|
||||
ldx cx16.r0
|
||||
stx P8ZP_SCRATCH_W1
|
||||
ldx cx16.r0+1
|
||||
stx P8ZP_SCRATCH_W1+1
|
||||
ldx cx16.r1
|
||||
stx P8ZP_SCRATCH_W2
|
||||
ldx cx16.r1+1
|
||||
stx P8ZP_SCRATCH_W2+1
|
||||
jmp prog8_lib.memsetw
|
||||
}}
|
||||
}
|
||||
|
||||
inline asmsub read_flags() -> ubyte @A {
|
||||
%asm {{
|
||||
php
|
||||
pla
|
||||
}}
|
||||
}
|
||||
|
||||
inline asmsub clear_carry() {
|
||||
%asm {{
|
||||
clc
|
||||
}}
|
||||
}
|
||||
|
||||
inline asmsub set_carry() {
|
||||
%asm {{
|
||||
sec
|
||||
}}
|
||||
}
|
||||
|
||||
inline asmsub clear_irqd() {
|
||||
%asm {{
|
||||
cli
|
||||
}}
|
||||
}
|
||||
|
||||
inline asmsub set_irqd() {
|
||||
%asm {{
|
||||
sei
|
||||
}}
|
||||
}
|
||||
|
||||
inline asmsub irqsafe_set_irqd() {
|
||||
%asm {{
|
||||
php
|
||||
sei
|
||||
}}
|
||||
}
|
||||
|
||||
inline asmsub irqsafe_clear_irqd() {
|
||||
%asm {{
|
||||
plp
|
||||
}}
|
||||
}
|
||||
|
||||
sub disable_caseswitch() {
|
||||
; no-op
|
||||
}
|
||||
|
||||
sub enable_caseswitch() {
|
||||
; no-op
|
||||
}
|
||||
|
||||
asmsub save_prog8_internals() {
|
||||
%asm {{
|
||||
lda P8ZP_SCRATCH_B1
|
||||
sta save_SCRATCH_ZPB1
|
||||
lda P8ZP_SCRATCH_REG
|
||||
sta save_SCRATCH_ZPREG
|
||||
lda P8ZP_SCRATCH_W1
|
||||
sta save_SCRATCH_ZPWORD1
|
||||
lda P8ZP_SCRATCH_W1+1
|
||||
sta save_SCRATCH_ZPWORD1+1
|
||||
lda P8ZP_SCRATCH_W2
|
||||
sta save_SCRATCH_ZPWORD2
|
||||
lda P8ZP_SCRATCH_W2+1
|
||||
sta save_SCRATCH_ZPWORD2+1
|
||||
rts
|
||||
.section BSS
|
||||
save_SCRATCH_ZPB1 .byte ?
|
||||
save_SCRATCH_ZPREG .byte ?
|
||||
save_SCRATCH_ZPWORD1 .word ?
|
||||
save_SCRATCH_ZPWORD2 .word ?
|
||||
.send BSS
|
||||
; !notreached!
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub restore_prog8_internals() {
|
||||
%asm {{
|
||||
lda save_prog8_internals.save_SCRATCH_ZPB1
|
||||
sta P8ZP_SCRATCH_B1
|
||||
lda save_prog8_internals.save_SCRATCH_ZPREG
|
||||
sta P8ZP_SCRATCH_REG
|
||||
lda save_prog8_internals.save_SCRATCH_ZPWORD1
|
||||
sta P8ZP_SCRATCH_W1
|
||||
lda save_prog8_internals.save_SCRATCH_ZPWORD1+1
|
||||
sta P8ZP_SCRATCH_W1+1
|
||||
lda save_prog8_internals.save_SCRATCH_ZPWORD2
|
||||
sta P8ZP_SCRATCH_W2
|
||||
lda save_prog8_internals.save_SCRATCH_ZPWORD2+1
|
||||
sta P8ZP_SCRATCH_W2+1
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub exit(ubyte returnvalue @A) {
|
||||
; -- immediately exit the program with a return code in the A register
|
||||
%asm {{
|
||||
sta p8_sys_startup.cleanup_at_exit._exitcode
|
||||
ldx prog8_lib.orig_stackpointer
|
||||
txs
|
||||
jmp p8_sys_startup.cleanup_at_exit
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub exit2(ubyte resulta @A, ubyte resultx @X, ubyte resulty @Y) {
|
||||
; -- immediately exit the program with result values in the A, X and Y registers.
|
||||
%asm {{
|
||||
sta p8_sys_startup.cleanup_at_exit._exitcode
|
||||
stx p8_sys_startup.cleanup_at_exit._exitcodeX
|
||||
sty p8_sys_startup.cleanup_at_exit._exitcodeY
|
||||
ldx prog8_lib.orig_stackpointer
|
||||
txs
|
||||
jmp p8_sys_startup.cleanup_at_exit
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub exit3(ubyte resulta @A, ubyte resultx @X, ubyte resulty @Y, bool carry @Pc) {
|
||||
; -- immediately exit the program with result values in the A, X and Y registers, and the Carry flag in the status register.
|
||||
%asm {{
|
||||
sta p8_sys_startup.cleanup_at_exit._exitcode
|
||||
lda #0
|
||||
rol a
|
||||
sta p8_sys_startup.cleanup_at_exit._exitcarry
|
||||
stx p8_sys_startup.cleanup_at_exit._exitcodeX
|
||||
sty p8_sys_startup.cleanup_at_exit._exitcodeY
|
||||
ldx prog8_lib.orig_stackpointer
|
||||
txs
|
||||
jmp p8_sys_startup.cleanup_at_exit
|
||||
}}
|
||||
}
|
||||
|
||||
inline asmsub progend() -> uword @AY {
|
||||
%asm {{
|
||||
lda #<prog8_program_end
|
||||
ldy #>prog8_program_end
|
||||
}}
|
||||
}
|
||||
|
||||
inline asmsub progstart() -> uword @AY {
|
||||
%asm {{
|
||||
lda #<prog8_program_start
|
||||
ldy #>prog8_program_start
|
||||
}}
|
||||
}
|
||||
|
||||
inline asmsub push(ubyte value @A) {
|
||||
%asm {{
|
||||
pha
|
||||
}}
|
||||
}
|
||||
|
||||
inline asmsub pushw(uword value @AY) {
|
||||
%asm {{
|
||||
pha
|
||||
tya
|
||||
pha
|
||||
}}
|
||||
}
|
||||
|
||||
inline asmsub push_returnaddress(uword address @XY) {
|
||||
%asm {{
|
||||
; push like JSR would: address-1, MSB first then LSB
|
||||
cpx #0
|
||||
bne +
|
||||
dey
|
||||
+ dex
|
||||
tya
|
||||
pha
|
||||
txa
|
||||
pha
|
||||
}}
|
||||
}
|
||||
|
||||
inline asmsub pop() -> ubyte @A {
|
||||
%asm {{
|
||||
pla
|
||||
}}
|
||||
}
|
||||
|
||||
inline asmsub popw() -> uword @AY {
|
||||
%asm {{
|
||||
pla
|
||||
tay
|
||||
pla
|
||||
}}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
cx16 {
|
||||
; the sixteen virtual 16-bit registers in both normal unsigned mode and signed mode (s)
|
||||
&uword r0 = $0010
|
||||
&uword r1 = $0012
|
||||
&uword r2 = $0014
|
||||
&uword r3 = $0016
|
||||
&uword r4 = $0018
|
||||
&uword r5 = $001a
|
||||
&uword r6 = $001c
|
||||
&uword r7 = $001e
|
||||
&uword r8 = $0020
|
||||
&uword r9 = $0022
|
||||
&uword r10 = $0024
|
||||
&uword r11 = $0026
|
||||
&uword r12 = $0028
|
||||
&uword r13 = $002a
|
||||
&uword r14 = $002c
|
||||
&uword r15 = $002e
|
||||
|
||||
; signed word versions
|
||||
&word r0s = $0010
|
||||
&word r1s = $0012
|
||||
&word r2s = $0014
|
||||
&word r3s = $0016
|
||||
&word r4s = $0018
|
||||
&word r5s = $001a
|
||||
&word r6s = $001c
|
||||
&word r7s = $001e
|
||||
&word r8s = $0020
|
||||
&word r9s = $0022
|
||||
&word r10s = $0024
|
||||
&word r11s = $0026
|
||||
&word r12s = $0028
|
||||
&word r13s = $002a
|
||||
&word r14s = $002c
|
||||
&word r15s = $002e
|
||||
|
||||
; ubyte versions (low and high bytes)
|
||||
&ubyte r0L = $0010
|
||||
&ubyte r1L = $0012
|
||||
&ubyte r2L = $0014
|
||||
&ubyte r3L = $0016
|
||||
&ubyte r4L = $0018
|
||||
&ubyte r5L = $001a
|
||||
&ubyte r6L = $001c
|
||||
&ubyte r7L = $001e
|
||||
&ubyte r8L = $0020
|
||||
&ubyte r9L = $0022
|
||||
&ubyte r10L = $0024
|
||||
&ubyte r11L = $0026
|
||||
&ubyte r12L = $0028
|
||||
&ubyte r13L = $002a
|
||||
&ubyte r14L = $002c
|
||||
&ubyte r15L = $002e
|
||||
|
||||
&ubyte r0H = $0011
|
||||
&ubyte r1H = $0013
|
||||
&ubyte r2H = $0015
|
||||
&ubyte r3H = $0017
|
||||
&ubyte r4H = $0019
|
||||
&ubyte r5H = $001b
|
||||
&ubyte r6H = $001d
|
||||
&ubyte r7H = $001f
|
||||
&ubyte r8H = $0021
|
||||
&ubyte r9H = $0023
|
||||
&ubyte r10H = $0025
|
||||
&ubyte r11H = $0027
|
||||
&ubyte r12H = $0029
|
||||
&ubyte r13H = $002b
|
||||
&ubyte r14H = $002d
|
||||
&ubyte r15H = $002f
|
||||
|
||||
; signed byte versions (low and high bytes)
|
||||
&byte r0sL = $0010
|
||||
&byte r1sL = $0012
|
||||
&byte r2sL = $0014
|
||||
&byte r3sL = $0016
|
||||
&byte r4sL = $0018
|
||||
&byte r5sL = $001a
|
||||
&byte r6sL = $001c
|
||||
&byte r7sL = $001e
|
||||
&byte r8sL = $0020
|
||||
&byte r9sL = $0022
|
||||
&byte r10sL = $0024
|
||||
&byte r11sL = $0026
|
||||
&byte r12sL = $0028
|
||||
&byte r13sL = $002a
|
||||
&byte r14sL = $002c
|
||||
&byte r15sL = $002e
|
||||
|
||||
&byte r0sH = $0011
|
||||
&byte r1sH = $0013
|
||||
&byte r2sH = $0015
|
||||
&byte r3sH = $0017
|
||||
&byte r4sH = $0019
|
||||
&byte r5sH = $001b
|
||||
&byte r6sH = $001d
|
||||
&byte r7sH = $001f
|
||||
&byte r8sH = $0021
|
||||
&byte r9sH = $0023
|
||||
&byte r10sH = $0025
|
||||
&byte r11sH = $0027
|
||||
&byte r12sH = $0029
|
||||
&byte r13sH = $002b
|
||||
&byte r14sH = $002d
|
||||
&byte r15sH = $002f
|
||||
|
||||
; boolean versions
|
||||
&bool r0bL = $0010
|
||||
&bool r1bL = $0012
|
||||
&bool r2bL = $0014
|
||||
&bool r3bL = $0016
|
||||
&bool r4bL = $0018
|
||||
&bool r5bL = $001a
|
||||
&bool r6bL = $001c
|
||||
&bool r7bL = $001e
|
||||
&bool r8bL = $0020
|
||||
&bool r9bL = $0022
|
||||
&bool r10bL = $0024
|
||||
&bool r11bL = $0026
|
||||
&bool r12bL = $0028
|
||||
&bool r13bL = $002a
|
||||
&bool r14bL = $002c
|
||||
&bool r15bL = $002e
|
||||
|
||||
&bool r0bH = $0011
|
||||
&bool r1bH = $0013
|
||||
&bool r2bH = $0015
|
||||
&bool r3bH = $0017
|
||||
&bool r4bH = $0019
|
||||
&bool r5bH = $001b
|
||||
&bool r6bH = $001d
|
||||
&bool r7bH = $001f
|
||||
&bool r8bH = $0021
|
||||
&bool r9bH = $0023
|
||||
&bool r10bH = $0025
|
||||
&bool r11bH = $0027
|
||||
&bool r12bH = $0029
|
||||
&bool r13bH = $002b
|
||||
&bool r14bH = $002d
|
||||
&bool r15bH = $002f
|
||||
|
||||
|
||||
asmsub save_virtual_registers() clobbers(A,Y) {
|
||||
%asm {{
|
||||
ldy #31
|
||||
- lda cx16.r0,y
|
||||
sta _cx16_vreg_storage,y
|
||||
dey
|
||||
bpl -
|
||||
rts
|
||||
|
||||
.section BSS
|
||||
_cx16_vreg_storage
|
||||
.word ?,?,?,?,?,?,?,?
|
||||
.word ?,?,?,?,?,?,?,?
|
||||
.send BSS
|
||||
; !notreached!
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub restore_virtual_registers() clobbers(A,Y) {
|
||||
%asm {{
|
||||
ldy #31
|
||||
- lda save_virtual_registers._cx16_vreg_storage,y
|
||||
sta cx16.r0,y
|
||||
dey
|
||||
bpl -
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
sub cpu_is_65816() -> bool {
|
||||
; Returns true when you have a 65816 cpu, false when it's a 6502.
|
||||
return false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
p8_sys_startup {
|
||||
; program startup and shutdown machinery. Needs to reside in normal system ram.
|
||||
|
||||
asmsub init_system() {
|
||||
; Initializes the machine to a sane starting state.
|
||||
; Called automatically by the loader program logic.
|
||||
%asm {{
|
||||
sei
|
||||
cld
|
||||
clc
|
||||
; TODO reset screen mode etc etc?
|
||||
clv
|
||||
; TODO what about IRQ handler?
|
||||
cli
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub init_system_phase2() {
|
||||
%asm {{
|
||||
; initialize kernel event interface
|
||||
lda #<f256.event.packet
|
||||
sta f256.event.dest+0
|
||||
stz f256.event.dest+1
|
||||
;sta f256.args.ext+0 ; check cc65 crt0.s for setup?
|
||||
;stz f256.args.ext+1
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub cleanup_at_exit() {
|
||||
; executed when the main subroutine does rts
|
||||
%asm {{
|
||||
lda _exitcarry
|
||||
lsr a
|
||||
lda _exitcode
|
||||
ldx _exitcodeX
|
||||
ldy _exitcodeY
|
||||
rts
|
||||
|
||||
.section BSS
|
||||
_exitcarry .byte ?
|
||||
_exitcode .byte ?
|
||||
_exitcodeX .byte ?
|
||||
_exitcodeY .byte ?
|
||||
.send BSS
|
||||
|
||||
; !notreached!
|
||||
}}
|
||||
}
|
||||
|
||||
}
|
446
examples/customtarget/libraries/f256/textio.p8
Normal file
446
examples/customtarget/libraries/f256/textio.p8
Normal file
@ -0,0 +1,446 @@
|
||||
; Prog8 definitions for the Text I/O and Screen routines for the Foenix F256
|
||||
;
|
||||
|
||||
%import syslib
|
||||
%import conv
|
||||
%import shared_cbm_textio_functions
|
||||
|
||||
txt {
|
||||
%option no_symbol_prefixing, ignore_unused
|
||||
|
||||
;alias chrout = f256.chrout
|
||||
asmsub chrout(ubyte character @A) {
|
||||
%asm {{
|
||||
jmp f256.chrout
|
||||
}}
|
||||
}
|
||||
|
||||
; text screen size
|
||||
const ubyte DEFAULT_WIDTH = f256.DEFAULT_WIDTH
|
||||
const ubyte DEFAULT_HEIGHT = f256.DEFAULT_HEIGHT
|
||||
|
||||
|
||||
sub clear_screen() {
|
||||
fill_screen(' ', f256.screen_color)
|
||||
f256.screen_col = 0
|
||||
f256.screen_row = 0
|
||||
}
|
||||
|
||||
sub cls() {
|
||||
clear_screen()
|
||||
}
|
||||
|
||||
sub home() {
|
||||
f256.screen_row = 0
|
||||
f256.screen_col = 0
|
||||
}
|
||||
|
||||
sub nl() {
|
||||
f256.chrout($0d)
|
||||
;f256.chrout($0a)
|
||||
}
|
||||
|
||||
sub spc() {
|
||||
f256.chrout(' ')
|
||||
}
|
||||
|
||||
sub bell() {
|
||||
; beep
|
||||
; c64.MVOL = 11
|
||||
; c64.AD1 = %00110111
|
||||
; c64.SR1 = %00000000
|
||||
; c64.FREQ1 = 8500
|
||||
; c64.CR1 = %00010000
|
||||
; c64.CR1 = %00010001
|
||||
}
|
||||
|
||||
asmsub column(ubyte col @A) clobbers(A, X, Y) {
|
||||
; ---- set the cursor on the given column (starting with 0) on the current line
|
||||
%asm {{
|
||||
sta f256.screen_col
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
|
||||
asmsub get_column() -> ubyte @Y {
|
||||
%asm {{
|
||||
ldy f256.screen_col
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub row(ubyte rownum @A) clobbers(A, X, Y) {
|
||||
; ---- set the cursor on the given row (starting with 0) on the current line
|
||||
%asm {{
|
||||
sta f256.screen_row
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub get_row() -> ubyte @X {
|
||||
%asm {{
|
||||
ldx f256.screen_row
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub get_cursor() -> ubyte @X, ubyte @Y {
|
||||
%asm {{
|
||||
ldx f256.screen_row
|
||||
ldy f256.screen_col
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub fill_screen (ubyte character @ A, ubyte color @ Y) clobbers(A) {
|
||||
; ---- fill the character screen with the given fill character and character color.
|
||||
; (assumes screen and color matrix are at their default addresses)
|
||||
|
||||
%asm {{
|
||||
pha
|
||||
tya
|
||||
jsr clear_screencolors
|
||||
pla
|
||||
jsr clear_screenchars
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub clear_screenchars (ubyte character @ A) clobbers(Y) {
|
||||
; ---- clear the character screen with the given fill character (leaves colors)
|
||||
; (assumes screen matrix is at the default address)
|
||||
%asm {{
|
||||
ldy f256.io_ctrl ; load current mapping
|
||||
phy ; save to stack
|
||||
ldy #2
|
||||
sty f256.io_ctrl ; map in screen memory
|
||||
ldy #240
|
||||
- sta f256.Screen+240*0-1,y
|
||||
sta f256.Screen+240*1-1,y
|
||||
sta f256.Screen+240*2-1,y
|
||||
sta f256.Screen+240*3-1,y
|
||||
sta f256.Screen+240*4-1,y
|
||||
sta f256.Screen+240*5-1,y
|
||||
sta f256.Screen+240*6-1,y
|
||||
sta f256.Screen+240*7-1,y
|
||||
sta f256.Screen+240*8-1,y
|
||||
sta f256.Screen+240*9-1,y
|
||||
sta f256.Screen+240*10-1,y
|
||||
sta f256.Screen+240*11-1,y
|
||||
sta f256.Screen+240*12-1,y
|
||||
sta f256.Screen+240*13-1,y
|
||||
sta f256.Screen+240*14-1,y
|
||||
sta f256.Screen+240*15-1,y
|
||||
sta f256.Screen+240*16-1,y
|
||||
sta f256.Screen+240*17-1,y
|
||||
sta f256.Screen+240*18-1,y
|
||||
sta f256.Screen+240*19-1,y
|
||||
dey
|
||||
bne -
|
||||
ply ; previous mapping from stack
|
||||
sty f256.io_ctrl ; restore previous map
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub clear_screencolors (ubyte color @ A) clobbers(Y) {
|
||||
; ---- clear the character screen colors with the given color (leaves characters).
|
||||
; (assumes color matrix is at the default address)
|
||||
%asm {{
|
||||
ldy f256.io_ctrl ; load current mapping
|
||||
phy ; save to stack
|
||||
ldy #3
|
||||
sty f256.io_ctrl ; map in color memory
|
||||
ldy #240
|
||||
- sta f256.Colors+240*0-1,y
|
||||
sta f256.Colors+240*1-1,y
|
||||
sta f256.Colors+240*2-1,y
|
||||
sta f256.Colors+240*3-1,y
|
||||
sta f256.Colors+240*4-1,y
|
||||
sta f256.Colors+240*5-1,y
|
||||
sta f256.Colors+240*6-1,y
|
||||
sta f256.Colors+240*7-1,y
|
||||
sta f256.Colors+240*8-1,y
|
||||
sta f256.Colors+240*9-1,y
|
||||
sta f256.Colors+240*10-1,y
|
||||
sta f256.Colors+240*11-1,y
|
||||
sta f256.Colors+240*12-1,y
|
||||
sta f256.Colors+240*13-1,y
|
||||
sta f256.Colors+240*14-1,y
|
||||
sta f256.Colors+240*15-1,y
|
||||
sta f256.Colors+240*16-1,y
|
||||
sta f256.Colors+240*17-1,y
|
||||
sta f256.Colors+240*18-1,y
|
||||
sta f256.Colors+240*19-1,y
|
||||
dey
|
||||
bne -
|
||||
ply ; previous mapping from stack
|
||||
sty f256.io_ctrl ; restore previous map
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
sub color (ubyte txtcol) {
|
||||
f256.screen_color = txtcol
|
||||
}
|
||||
|
||||
sub lowercase() {
|
||||
; c64.VMCSB |= 2
|
||||
}
|
||||
|
||||
sub uppercase() {
|
||||
; c64.VMCSB &= ~2
|
||||
}
|
||||
|
||||
asmsub scroll_left (bool alsocolors @ Pc) clobbers(A, X, Y) {
|
||||
; ---- scroll the whole screen 1 character to the left
|
||||
; contents of the rightmost column are unchanged, you should clear/refill this yourself
|
||||
; Carry flag determines if screen color data must be scrolled too
|
||||
|
||||
%asm {{
|
||||
bcc _scroll_screen
|
||||
|
||||
+ ; scroll the screen and the color memory
|
||||
ldx #0
|
||||
ldy #38
|
||||
-
|
||||
.for row=0, row<=24, row+=1
|
||||
lda f256.Screen + 40*row + 1,x
|
||||
sta f256.Screen + 40*row + 0,x
|
||||
lda f256.Colors + 40*row + 1,x
|
||||
sta f256.Colors + 40*row + 0,x
|
||||
.next
|
||||
inx
|
||||
dey
|
||||
bpl -
|
||||
rts
|
||||
|
||||
_scroll_screen ; scroll only the screen memory
|
||||
ldx #0
|
||||
ldy #38
|
||||
-
|
||||
.for row=0, row<=24, row+=1
|
||||
lda f256.Screen + 40*row + 1,x
|
||||
sta f256.Screen + 40*row + 0,x
|
||||
.next
|
||||
inx
|
||||
dey
|
||||
bpl -
|
||||
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub scroll_right (bool alsocolors @ Pc) clobbers(A,X) {
|
||||
; ---- scroll the whole screen 1 character to the right
|
||||
; contents of the leftmost column are unchanged, you should clear/refill this yourself
|
||||
; Carry flag determines if screen color data must be scrolled too
|
||||
%asm {{
|
||||
bcc _scroll_screen
|
||||
|
||||
+ ; scroll the screen and the color memory
|
||||
ldx #38
|
||||
-
|
||||
.for row=0, row<=24, row+=1
|
||||
lda f256.Screen + 40*row + 0,x
|
||||
sta f256.Screen + 40*row + 1,x
|
||||
lda f256.Colors + 40*row + 0,x
|
||||
sta f256.Colors + 40*row + 1,x
|
||||
.next
|
||||
dex
|
||||
bpl -
|
||||
rts
|
||||
|
||||
_scroll_screen ; scroll only the screen memory
|
||||
ldx #38
|
||||
-
|
||||
.for row=0, row<=24, row+=1
|
||||
lda f256.Screen + 40*row + 0,x
|
||||
sta f256.Screen + 40*row + 1,x
|
||||
.next
|
||||
dex
|
||||
bpl -
|
||||
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
; stub for call moved to the f256 block.
|
||||
alias scroll_up = f256.scroll_up
|
||||
;asmsub scroll_up (bool alsocolors @ Pc) clobbers(A,X) {
|
||||
; %asm {{
|
||||
; jmp f256.scroll_up
|
||||
; }}
|
||||
;}
|
||||
|
||||
asmsub scroll_down (bool alsocolors @ Pc) clobbers(A,X) {
|
||||
; ---- scroll the whole screen 1 character down
|
||||
; contents of the top row are unchanged, you should refill/clear this yourself
|
||||
; Carry flag determines if screen color data must be scrolled too
|
||||
%asm {{
|
||||
bcc _scroll_screen
|
||||
|
||||
+ ; scroll the screen and the color memory
|
||||
ldx #39
|
||||
-
|
||||
.for row=23, row>=0, row-=1
|
||||
lda f256.Colors + 40*row,x
|
||||
sta f256.Colors + 40*(row+1),x
|
||||
lda f256.Screen + 40*row,x
|
||||
sta f256.Screen + 40*(row+1),x
|
||||
.next
|
||||
dex
|
||||
bpl -
|
||||
rts
|
||||
|
||||
_scroll_screen ; scroll only the screen memory
|
||||
ldx #39
|
||||
-
|
||||
.for row=23, row>=0, row-=1
|
||||
lda f256.Screen + 40*row,x
|
||||
sta f256.Screen + 40*(row+1),x
|
||||
.next
|
||||
dex
|
||||
bpl -
|
||||
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub setchr (ubyte col @X, ubyte row @Y, ubyte character @A) clobbers(A, Y) {
|
||||
; ---- sets the character in the screen matrix at the given position
|
||||
%asm {{
|
||||
pha ; preserve character
|
||||
jsr f256.chrptr ; calculate offset
|
||||
pla ; restore character
|
||||
ldy f256.io_ctrl ; load current mapping
|
||||
phy ; save on stack
|
||||
ldy #2
|
||||
sty f256.io_ctrl ; map in screen memory
|
||||
ldy #0
|
||||
sta (f256.screen_ptr), y ; write character
|
||||
ply
|
||||
sty f256.io_ctrl ; restore previous mapping
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub getchr (ubyte col @A, ubyte row @Y) clobbers(Y) -> ubyte @ A {
|
||||
; ---- get the character in the screen matrix at the given location
|
||||
%asm {{
|
||||
phx ; preserve
|
||||
tax ; move column to X for call
|
||||
jsr f256.chrptr ; calculate offset to character
|
||||
ldy f256.io_ctrl ; load current mapping
|
||||
phy ; save on stack
|
||||
ldy #2
|
||||
sty f256.io_ctrl ; map in screen memory
|
||||
ldy #0
|
||||
lda (f256.screen_ptr),y ; get character
|
||||
ply
|
||||
sty f256.io_ctrl ; restore previous mapping
|
||||
plx ; restore
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub setclr (ubyte col @X, ubyte row @Y, ubyte color @A) clobbers(A, Y) {
|
||||
; ---- set the color in A on the screen matrix at the given position
|
||||
%asm {{
|
||||
pha ; preserve character
|
||||
jsr f256.chrptr ; calculate offset
|
||||
pla ; restore character
|
||||
ldy f256.io_ctrl ; load current mapping
|
||||
phy ; save on stack
|
||||
ldy #3
|
||||
sty f256.io_ctrl ; map in color memory
|
||||
ldy #0
|
||||
sta (f256.screen_ptr), y ; write color
|
||||
ply
|
||||
sty f256.io_ctrl ; restore previous mapping
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub getclr (ubyte col @A, ubyte row @Y) clobbers(Y) -> ubyte @ A {
|
||||
; ---- get the color in the screen color matrix at the given location
|
||||
%asm {{
|
||||
phx ; preserve
|
||||
tax ; move column to X for call
|
||||
jsr f256.chrptr ; calculate offset to character
|
||||
ldy f256.io_ctrl ; load current mapping
|
||||
phy ; save on stack
|
||||
ldy #3
|
||||
sty f256.io_ctrl ; map in color memory
|
||||
ldy #0
|
||||
lda (f256.screen_ptr),y ; get color
|
||||
ply
|
||||
sty f256.io_ctrl ; restore previous mapping
|
||||
plx ; restore
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
sub setcc (ubyte col, ubyte row, ubyte character, ubyte charcolor) {
|
||||
; ---- set char+color at the given position on the screen
|
||||
%asm {{
|
||||
ldx col ; setup parameters
|
||||
ldy row
|
||||
jsr f256.chrptr ; calculate offset
|
||||
ldy f256.io_ctrl ; load current mapping
|
||||
phy ; save on stack
|
||||
ldy #2
|
||||
sty f256.io_ctrl ; map in screen memory
|
||||
ldy #0
|
||||
lda character
|
||||
sta (f256.screen_ptr), y
|
||||
ldy #3
|
||||
sty f256.io_ctrl ; map in color memory
|
||||
ldy #0
|
||||
lda charcolor
|
||||
sta (f256.screen_ptr), y
|
||||
ply ; previous mapping from stack
|
||||
sty f256.io_ctrl ; restore previous map
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub plot (ubyte col @ Y, ubyte row @ X) {
|
||||
%asm {{
|
||||
sty f256.screen_col
|
||||
stx f256.screen_row
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub width() clobbers(X,Y) -> ubyte @A {
|
||||
; -- returns the text screen width (number of columns)
|
||||
%asm {{
|
||||
lda DEFAULT_WIDTH
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
asmsub height() clobbers(X, Y) -> ubyte @A {
|
||||
; -- returns the text screen height (number of rows)
|
||||
%asm {{
|
||||
lda DEFAULT_HEIGHT
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
; TODO: jmp to cbm.CHRIN?
|
||||
asmsub waitkey() -> ubyte @A {
|
||||
%asm {{
|
||||
- stz f256.event.type ; invalidate existing event type
|
||||
jsr f256.event.NextEvent
|
||||
lda f256.event.type
|
||||
cmp #f256.event.key.PRESSED
|
||||
bne -
|
||||
;lda f256.event.key.raw ; return scan code?
|
||||
lda f256.event.key.ascii ; return upper or lower ASCII
|
||||
rts
|
||||
}}
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
Various examples for configurable target machines, such as the NEO6502, Atari 800,
|
||||
and "tiny" example configurations for the X16 or C64 that provide more example materials.
|
||||
Foenix F256, and "tiny" example configurations for the X16 or C64 that provide
|
||||
more example materials.
|
||||
|
||||
Look in the Makefile to see how to build or run the various programs.
|
||||
|
||||
@ -7,4 +8,4 @@ The user 'adiee5' has been working on a Nintendo Entertainment System (NES) comp
|
||||
and example program, you can find those efforts here on GitHub: https://github.com/adiee5/prog8-nes-target
|
||||
Note that the NES is a very alien architecture for Prog8 still and the support is very limited
|
||||
(for example, prog8 is not aware that the program code usually is going to end up in a ROM cartridge,
|
||||
and currently still generates code that might nog work in ROM.)
|
||||
and currently still generates code that might not work in ROM.)
|
||||
|
84
examples/customtarget/src/f256-hello.p8
Normal file
84
examples/customtarget/src/f256-hello.p8
Normal file
@ -0,0 +1,84 @@
|
||||
;
|
||||
; Simplistic example of some text output and
|
||||
; reading keys.
|
||||
;
|
||||
%launcher none
|
||||
%import textio
|
||||
|
||||
main {
|
||||
str hello = "Hello, World from Prog8!"
|
||||
|
||||
sub start() {
|
||||
ubyte i
|
||||
ubyte key
|
||||
|
||||
txt.cls()
|
||||
|
||||
txt.nl()
|
||||
txt.print(hello)
|
||||
txt.nl()
|
||||
|
||||
for i in 0 to 15 {
|
||||
txt.color($f0 + i)
|
||||
txt.print("This is color ")
|
||||
txt.print_ub(i)
|
||||
txt.nl()
|
||||
}
|
||||
txt.color($f2)
|
||||
|
||||
txt.row(30)
|
||||
txt.print("Using setchr() to draw 'ABC'")
|
||||
txt.nl()
|
||||
|
||||
txt.setchr(20, 20, 'A')
|
||||
txt.setchr(21, 21, 'B')
|
||||
txt.setchr(22, 22, 'C')
|
||||
|
||||
txt.nl()
|
||||
txt.print("Using setchr(getchr()) to draw 'ABC'")
|
||||
txt.nl()
|
||||
|
||||
txt.setchr(25, 25, txt.getchr(20, 20))
|
||||
txt.setchr(26, 26, txt.getchr(21, 21))
|
||||
txt.setchr(27, 27, txt.getchr(22, 22))
|
||||
|
||||
txt.setclr(20,20, $f3)
|
||||
txt.setclr(21,21, $f4)
|
||||
txt.setclr(22,22, $f5)
|
||||
|
||||
txt.setclr(25,25, txt.getclr(20,20))
|
||||
txt.setclr(26,26, txt.getclr(21,21))
|
||||
txt.setclr(27,27, txt.getclr(22,22))
|
||||
|
||||
|
||||
txt.nl()
|
||||
txt.print("Waiting for a key... ")
|
||||
key = txt.waitkey()
|
||||
txt.nl()
|
||||
txt.print("KEY: ")
|
||||
txt.chrout(key)
|
||||
txt.nl()
|
||||
txt.nl()
|
||||
|
||||
txt.print("Press keys to show them, ctrl-c resets machine.")
|
||||
txt.nl()
|
||||
|
||||
; look for keys forever
|
||||
repeat {
|
||||
void, key = cbm.GETIN()
|
||||
|
||||
if key != $00 {
|
||||
txt.plot(0,40)
|
||||
txt.print("key: ")
|
||||
txt.chrout(key)
|
||||
txt.spc()
|
||||
txt.print_ubhex(key, true)
|
||||
}
|
||||
|
||||
; ctrl-c exists / resets machine
|
||||
if key == $03
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
55
examples/customtarget/targetconfigs/f256.properties
Normal file
55
examples/customtarget/targetconfigs/f256.properties
Normal file
@ -0,0 +1,55 @@
|
||||
# configuration file for a Foenix F256 Prog8 compilation target
|
||||
# generates '.bin' files that are in '.pgz' Foenix format.
|
||||
|
||||
cpu = 65C02
|
||||
encoding = iso
|
||||
#output_type = LIBRARY
|
||||
output_type = RAW
|
||||
#load_address = $0200
|
||||
#load_address = $1000
|
||||
load_address = $2000
|
||||
memtop = $c000
|
||||
bss_highram_start = 0
|
||||
bss_highram_end = 0
|
||||
bss_goldenram_start = 0
|
||||
bss_goldenram_end = 0
|
||||
|
||||
# io_regions specifies memory-mapped I/O registers that should be treated differentely.
|
||||
# it can be zero or more memory address ranges (inclusive) separated by comma
|
||||
io_regions = $c000-$dfff
|
||||
|
||||
# zeropage scratch variables. zp_scratch_reg must always be zp_scratch_b1+1 !
|
||||
zp_scratch_b1 = $e2
|
||||
zp_scratch_reg = $e3
|
||||
zp_scratch_w1 = $e4
|
||||
zp_scratch_w2 = $e6
|
||||
|
||||
# free zeropage locations for the various zp usage methods
|
||||
# zero or more zeropage address ranges (inclusive).
|
||||
#
|
||||
# $00-$01 - memory & I/O control (MMU)
|
||||
# $02-$07 - TODO: document (zp_scratch would fit here?)
|
||||
# $08-$0f - additional (optional) hardware registers (TODO: find & document)
|
||||
# ...
|
||||
# $e8-$ef - event array (8 bytes for next event)
|
||||
# $f0-$ff - kernel arguments table
|
||||
|
||||
zp_fullsafe = $22-$e7
|
||||
zp_kernalsafe = $22-$e7
|
||||
zp_basicsafe = $22-$e7
|
||||
|
||||
# the start of the 32 bytes used by the R0-R15 virtual registers. Can be in Zeropage or elsewhere.
|
||||
virtual_registers = $10
|
||||
|
||||
# Where can we find the standard library (syslib.p8). You can still add more paths manually using -srcdirs
|
||||
library = ./libraries/f256
|
||||
|
||||
# if a non-empty custom launcher code string is supplied, the compiler won't output ANY launcher / init code by itself,
|
||||
# and instead outputs whatever is specified here. (You can use \n here for newline and \ for line continuantions)
|
||||
custom_launcher_code =
|
||||
|
||||
# additional options passed to the assembler program
|
||||
#assembler_options = --c256-pgx
|
||||
assembler_options = --c256-pgz --output-exec=$2000
|
||||
#assembler_options = --output-exec=\$2000 --c256-pgz
|
||||
#--c256-pgz --output main.pgz
|
Reference in New Issue
Block a user