mirror of
https://github.com/irmen/prog8.git
synced 2025-11-23 14:17:51 +00:00
added c64.banks() and c64.getbanks() and c64 banking example
This commit is contained in:
@@ -15,7 +15,7 @@ class C64MachineDefinition: IMachineDefinition {
|
|||||||
override val FLOAT_MAX_NEGATIVE = Mflpt5.FLOAT_MAX_NEGATIVE
|
override val FLOAT_MAX_NEGATIVE = Mflpt5.FLOAT_MAX_NEGATIVE
|
||||||
override val FLOAT_MEM_SIZE = Mflpt5.FLOAT_MEM_SIZE
|
override val FLOAT_MEM_SIZE = Mflpt5.FLOAT_MEM_SIZE
|
||||||
override val PROGRAM_LOAD_ADDRESS = 0x0801u
|
override val PROGRAM_LOAD_ADDRESS = 0x0801u
|
||||||
override val PROGRAM_TOP_ADDRESS = 0xbfffu
|
override val PROGRAM_TOP_ADDRESS = 0x9fffu // $bfff if basic rom is banked out
|
||||||
|
|
||||||
override val BSSHIGHRAM_START = 0xc000u
|
override val BSSHIGHRAM_START = 0xc000u
|
||||||
override val BSSHIGHRAM_END = 0xcfffu
|
override val BSSHIGHRAM_END = 0xcfffu
|
||||||
|
|||||||
@@ -307,6 +307,31 @@ c64 {
|
|||||||
|
|
||||||
; ---- end of SID registers ----
|
; ---- end of SID registers ----
|
||||||
|
|
||||||
|
asmsub banks(ubyte banks @A) {
|
||||||
|
; -- set the memory bank configuration
|
||||||
|
; see https://www.c64-wiki.com/wiki/Bank_Switching
|
||||||
|
%asm {{
|
||||||
|
and #%00000111
|
||||||
|
sta P8ZP_SCRATCH_REG
|
||||||
|
sei
|
||||||
|
lda $01
|
||||||
|
and #%11111000
|
||||||
|
ora P8ZP_SCRATCH_REG
|
||||||
|
sta $01
|
||||||
|
cli
|
||||||
|
rts
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline asmsub getbanks() -> ubyte @A {
|
||||||
|
; -- get the current memory bank configuration
|
||||||
|
; see https://www.c64-wiki.com/wiki/Bank_Switching
|
||||||
|
%asm {{
|
||||||
|
lda $01
|
||||||
|
and #%00000111
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
sub get_vic_memory_base() -> uword {
|
sub get_vic_memory_base() -> uword {
|
||||||
; one of the 4 possible banks. $0000/$4000/$8000/$c000.
|
; one of the 4 possible banks. $0000/$4000/$8000/$c000.
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ class TestCompilerOnExamplesC64: FunSpec({
|
|||||||
val onlyC64 = cartesianProduct(
|
val onlyC64 = cartesianProduct(
|
||||||
listOf(
|
listOf(
|
||||||
"balloonflight",
|
"balloonflight",
|
||||||
|
"banking",
|
||||||
"bdmusic",
|
"bdmusic",
|
||||||
"bdmusic-irq",
|
"bdmusic-irq",
|
||||||
"charset",
|
"charset",
|
||||||
@@ -116,6 +117,7 @@ class TestCompilerOnExamplesCx16: FunSpec({
|
|||||||
"sprites/dragons",
|
"sprites/dragons",
|
||||||
"zsmkit/demo1",
|
"zsmkit/demo1",
|
||||||
"zsmkit/demo2",
|
"zsmkit/demo2",
|
||||||
|
"banking/program",
|
||||||
"amiga",
|
"amiga",
|
||||||
"audioroutines",
|
"audioroutines",
|
||||||
"automatons",
|
"automatons",
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ Memory map for the C64 and the X16
|
|||||||
|
|
||||||
This is the default memory map of the 64 Kb addressable memory for those two systems.
|
This is the default memory map of the 64 Kb addressable memory for those two systems.
|
||||||
Both systems have ways to alter the memory map and/or to switch memory banks, but that is not shown here.
|
Both systems have ways to alter the memory map and/or to switch memory banks, but that is not shown here.
|
||||||
|
See :ref:`banking` for details about that.
|
||||||
|
|
||||||
.. image:: memorymap.svg
|
.. image:: memorymap.svg
|
||||||
|
|
||||||
|
|||||||
@@ -31,10 +31,19 @@ ROM/RAM bank selection
|
|||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
On certain systems prog8 provides support for managing the ROM or RAM banks that are active.
|
On certain systems prog8 provides support for managing the ROM or RAM banks that are active.
|
||||||
For example, on the Commander X16, you can use ``cx16.getrombank()`` to get the active ROM bank,
|
|
||||||
and ``cx16.rombank(10)`` to make rom bank 10 active. Likewise, ``cx16.getrambank()`` to get the active RAM bank,
|
|
||||||
and ``cx16.rambank(10)`` to make ram bank 10 active. This is explicit manual banking control.
|
|
||||||
|
|
||||||
|
======= ============================================= ===========
|
||||||
|
system get banks (returns byte) set banks
|
||||||
|
======= ============================================= ===========
|
||||||
|
c64 ``c64.getbanks()`` ``c64.banks(x)``
|
||||||
|
c128 *TODO* *TODO*
|
||||||
|
cx16 ``cx16.getrombank()`` , ``cx16.getrambank()`` ``cx16.rombank(x)`` , ``cx16.rambank(x)``
|
||||||
|
other N/A N/A
|
||||||
|
======= ============================================= ===========
|
||||||
|
|
||||||
|
Calling a subroutine in another memory bank can be done by using the ``callfar`` or ``callfar2`` builtin functions.
|
||||||
|
|
||||||
|
When you are using the routines above, you are doing explicit manual banks control.
|
||||||
However, Prog8 also provides something more sophisticated than this, when dealing with banked subroutines:
|
However, Prog8 also provides something more sophisticated than this, when dealing with banked subroutines:
|
||||||
|
|
||||||
External subroutines defined with ``romsub`` can have a non-standard ROM or RAM bank specified as well.
|
External subroutines defined with ``romsub`` can have a non-standard ROM or RAM bank specified as well.
|
||||||
|
|||||||
@@ -1,14 +1,22 @@
|
|||||||
TODO
|
TODO
|
||||||
====
|
====
|
||||||
|
|
||||||
|
on the C64, if not using floats, disable basic ROM in startup to gain another 8Kb of RAM. Make sure to set memtop to $bfff in this case or $9fff when basic is banked in
|
||||||
|
update the memory map picture, and add footnote that BASIC ROM is usually banked out. ALso mention this in the 'banking' chapter
|
||||||
|
|
||||||
add support for banked romsubs on the C64 as well (banks basic/kernal rom in/out)
|
add support for banked romsubs on the C64 as well (banks basic/kernal rom in/out)
|
||||||
|
|
||||||
|
make @bank accept a variable as well to make it dynamic
|
||||||
|
|
||||||
rename 'romsub' to 'extsub' ? keep romsub as alias?
|
rename 'romsub' to 'extsub' ? keep romsub as alias?
|
||||||
|
|
||||||
for releasenotes: gfx2.width and gfx2.height got renamed as gfx_lores.WIDTH/HEIGHT or gfx_hires4.WIDTH/HEIGTH constants. Screen mode routines also renamed.
|
for releasenotes: gfx2.width and gfx2.height got renamed as gfx_lores.WIDTH/HEIGHT or gfx_hires4.WIDTH/HEIGTH constants. Screen mode routines also renamed.
|
||||||
|
|
||||||
regenerate symbol dump files
|
regenerate symbol dump files
|
||||||
|
|
||||||
|
improve ability to create library files in prog8; for instance there's still stuff injected into the start of the start() routine AND there is separate setup logic going on before calling it.
|
||||||
|
Make up our mind! Maybe all setup does need to be put into start() ? because the program cannot function correctly when the variables aren't initialized properly bss is not cleared etc. etc.
|
||||||
|
|
||||||
Improve register load order in subroutine call args assignments:
|
Improve register load order in subroutine call args assignments:
|
||||||
in certain situations, the "wrong" order of evaluation of function call arguments is done which results
|
in certain situations, the "wrong" order of evaluation of function call arguments is done which results
|
||||||
in overwriting registers that already got their value, which requires a lot of stack juggling (especially on plain 6502 cpu!)
|
in overwriting registers that already got their value, which requires a lot of stack juggling (especially on plain 6502 cpu!)
|
||||||
|
|||||||
45
examples/c64/banking.p8
Normal file
45
examples/c64/banking.p8
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
%import string
|
||||||
|
%import textio
|
||||||
|
%option no_sysinit
|
||||||
|
%zeropage basicsafe
|
||||||
|
|
||||||
|
; some bank switching on the C64. See https://www.c64-wiki.com/wiki/Bank_Switching
|
||||||
|
|
||||||
|
main {
|
||||||
|
sub start() {
|
||||||
|
; copy basic rom to ram and replace ready prompt
|
||||||
|
sys.memcopy($a000, $a000, $2000)
|
||||||
|
void string.copy(iso:"HELLO!\r", $a378)
|
||||||
|
|
||||||
|
txt.print("8 bytes at $f000 (kernal rom):\n")
|
||||||
|
for cx16.r0 in $f000 to $f007 {
|
||||||
|
txt.print_ubhex(@(cx16.r0), false)
|
||||||
|
txt.spc()
|
||||||
|
}
|
||||||
|
txt.nl()
|
||||||
|
|
||||||
|
; store some other data in the RAM below those kernal ROM locations
|
||||||
|
; switch off kernal rom to see those bytes
|
||||||
|
; we cannot print during this time and the IRQ has to be disabled temporarily as well.
|
||||||
|
void string.copy("hello !?", $f000)
|
||||||
|
sys.set_irqd()
|
||||||
|
c64.banks(%101) ; switch off roms
|
||||||
|
ubyte[8] buffer
|
||||||
|
sys.memcopy($f000, &buffer, 8)
|
||||||
|
c64.banks(%111) ; kernal rom back on
|
||||||
|
sys.clear_irqd()
|
||||||
|
txt.print("8 bytes at $f000 (ram this time):\n")
|
||||||
|
for cx16.r0L in buffer {
|
||||||
|
txt.print_ubhex(cx16.r0L, false)
|
||||||
|
txt.spc()
|
||||||
|
}
|
||||||
|
txt.nl()
|
||||||
|
|
||||||
|
|
||||||
|
; we can switch off the basic rom now, but this is not persistent after program exit
|
||||||
|
c64.banks(%110)
|
||||||
|
|
||||||
|
; ...so we print a message for the user to do it manually to see the changed prompt.
|
||||||
|
txt.print("\ntype: poke 1,54\nto switch off basic rom :-)\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,18 +1,45 @@
|
|||||||
|
%import string
|
||||||
%import textio
|
%import textio
|
||||||
%option no_sysinit
|
%option no_sysinit
|
||||||
%zeropage basicsafe
|
%zeropage basicsafe
|
||||||
|
|
||||||
|
; some bank switching on the C64. See https://www.c64-wiki.com/wiki/Bank_Switching
|
||||||
|
|
||||||
main {
|
main {
|
||||||
romsub @bank 10 $C09F = audio_init()
|
|
||||||
romsub @bank 5 $A000 = hiram_routine()
|
|
||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
; put an rts in hiram bank 5 to not crash
|
; copy basic rom to ram and replace ready prompt
|
||||||
cx16.rambank(5)
|
sys.memcopy($a000, $a000, $2000)
|
||||||
@($a000) = $60
|
void string.copy(iso:"HELLO!\r", $a378)
|
||||||
cx16.rambank(0)
|
|
||||||
|
|
||||||
audio_init()
|
txt.print("8 bytes at $f000 (kernal rom):\n")
|
||||||
hiram_routine()
|
for cx16.r0 in $f000 to $f007 {
|
||||||
|
txt.print_ubhex(@(cx16.r0), false)
|
||||||
|
txt.spc()
|
||||||
|
}
|
||||||
|
txt.nl()
|
||||||
|
|
||||||
|
; store some other data in the RAM below those kernal ROM locations
|
||||||
|
; switch off kernal rom to see those bytes
|
||||||
|
; we cannot print during this time and the IRQ has to be disabled temporarily as well.
|
||||||
|
void string.copy("hello !?", $f000)
|
||||||
|
sys.set_irqd()
|
||||||
|
c64.banks(%101) ; switch off roms
|
||||||
|
ubyte[8] buffer
|
||||||
|
sys.memcopy($f000, &buffer, 8)
|
||||||
|
c64.banks(%111) ; kernal rom back on
|
||||||
|
sys.clear_irqd()
|
||||||
|
txt.print("8 bytes at $f000 (ram this time):\n")
|
||||||
|
for cx16.r0L in buffer {
|
||||||
|
txt.print_ubhex(cx16.r0L, false)
|
||||||
|
txt.spc()
|
||||||
|
}
|
||||||
|
txt.nl()
|
||||||
|
|
||||||
|
|
||||||
|
; we can switch off the basic rom now, but this is not persistent after program exit
|
||||||
|
c64.banks(%110)
|
||||||
|
|
||||||
|
; ...so we print a message for the user to do it manually to see the changed prompt.
|
||||||
|
txt.print("\ntype: poke 1,54\nto switch off basic rom :-)\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user