mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-11-26 12:49:21 +00:00
Improved simple VRAM example. #581
This commit is contained in:
parent
02e57b06cb
commit
2d58a799d5
@ -35,9 +35,22 @@ void()** const KERNEL_IRQ = 0x0314;
|
||||
// $0316 (RAM) BRK vector - The vector used when the KERNAL serves IRQ caused by a BRK
|
||||
void()** const KERNEL_BRK = 0x0316;
|
||||
|
||||
// VRAM Address of the default screen
|
||||
char * const DEFAULT_SCREEN = 0x0000;
|
||||
// VRAM Bank (0/1) of the default screen
|
||||
char * const DEFAULT_SCREEN_VBANK = 0;
|
||||
|
||||
// Put a single byte into VRAM.
|
||||
// Uses VERA DATA0
|
||||
// - bank: Which 64K VRAM bank to put data into (0/1)
|
||||
// - addr: The address in VRAM
|
||||
// - vbank: Which 64K VRAM bank to put data into (0/1)
|
||||
// - vaddr: The address in VRAM
|
||||
// - data: The data to put into VRAM
|
||||
void vpoke(char bank, char* addr, char data);
|
||||
void vpoke(char vbank, char* vaddr, char data);
|
||||
|
||||
// Copy block of memory (from RAM to VRAM)
|
||||
// Copies the values of num bytes from the location pointed to by source directly to the memory block pointed to by destination in VRAM.
|
||||
// - vbank: Which 64K VRAM bank to put data into (0/1)
|
||||
// - vdest: The destination address in VRAM
|
||||
// - src: The source address in RAM
|
||||
// - num: The number of bytes to copy
|
||||
void memcpy_to_vram(char vbank, void* vdest, void* src, unsigned int num );
|
||||
|
@ -9,13 +9,33 @@
|
||||
// - bank: Which 64K VRAM bank to put data into (0/1)
|
||||
// - addr: The address in VRAM
|
||||
// - data: The data to put into VRAM
|
||||
void vpoke(char bank, char* addr, char data) {
|
||||
void vpoke(char vbank, char* vaddr, char data) {
|
||||
// Select DATA0
|
||||
*VERA_CTRL &= ~VERA_ADDRSEL;
|
||||
// Set address
|
||||
*VERA_ADDRX_L = <addr;
|
||||
*VERA_ADDRX_M = >addr;
|
||||
*VERA_ADDRX_H = VERA_INC_0 | bank;
|
||||
*VERA_ADDRX_L = <vaddr;
|
||||
*VERA_ADDRX_M = >vaddr;
|
||||
*VERA_ADDRX_H = VERA_INC_0 | vbank;
|
||||
// Set data
|
||||
*VERA_DATA0 = data;
|
||||
}
|
||||
}
|
||||
|
||||
// Copy block of memory (from RAM to VRAM)
|
||||
// Copies the values of num bytes from the location pointed to by source directly to the memory block pointed to by destination in VRAM.
|
||||
// - vbank: Which 64K VRAM bank to put data into (0/1)
|
||||
// - vdest: The destination address in VRAM
|
||||
// - src: The source address in RAM
|
||||
// - num: The number of bytes to copy
|
||||
void memcpy_to_vram(char vbank, void* vdest, void* src, unsigned int num ) {
|
||||
// Select DATA0
|
||||
*VERA_CTRL &= ~VERA_ADDRSEL;
|
||||
// Set address
|
||||
*VERA_ADDRX_L = <vdest;
|
||||
*VERA_ADDRX_M = >vdest;
|
||||
*VERA_ADDRX_H = VERA_INC_1 | vbank;
|
||||
// Transfer the data
|
||||
char *s = src;
|
||||
char *end = (char*)src+num;
|
||||
for(; s!=end; s++)
|
||||
*VERA_DATA0 = *s;
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
"link": "cx16.ld",
|
||||
"start_address": "0x080d",
|
||||
"cpu": "WDC65C02",
|
||||
"emulator": "x16emu -debug -run -prg",
|
||||
"emulator": "x16emu -debug -run -scale 2 -prg",
|
||||
"defines": {
|
||||
"__CX16__": 1
|
||||
}
|
||||
|
@ -5,11 +5,18 @@
|
||||
#include <cx16.h>
|
||||
|
||||
void main() {
|
||||
|
||||
// Copy message to screen one char at a time
|
||||
char MSG[] = "hello world!";
|
||||
// Address of the default screen
|
||||
char* vaddr = 0x0000;
|
||||
char* vaddr = DEFAULT_SCREEN;
|
||||
for(char i=0;MSG[i];i++) {
|
||||
vpoke(0, vaddr++, MSG[i]); // Message
|
||||
vpoke(0, vaddr++, 0x21); // Red background, White foreground
|
||||
}
|
||||
}
|
||||
|
||||
// Copy message (and colors) to screen using memcpy_to_vram
|
||||
char MSG2[] = "h e l l o w o r l d ! "; // Space is 0x20, red background black foreground
|
||||
memcpy_to_vram(0, DEFAULT_SCREEN+0x100, MSG2, sizeof(MSG2));
|
||||
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,9 @@
|
||||
.segment Code
|
||||
|
||||
|
||||
.const VERA_INC_1 = $10
|
||||
.const VERA_ADDRSEL = 1
|
||||
.const SIZEOF_BYTE = 1
|
||||
// $9F20 VRAM Address (7:0)
|
||||
.label VERA_ADDRX_L = $9f20
|
||||
// $9F21 VRAM Address (15:8)
|
||||
@ -30,19 +32,24 @@
|
||||
// Bit 1: DCSEL
|
||||
// Bit 2: ADDRSEL
|
||||
.label VERA_CTRL = $9f25
|
||||
// VRAM Address of the default screen
|
||||
.label DEFAULT_SCREEN = 0
|
||||
.segment Code
|
||||
main: {
|
||||
// Address of the default screen
|
||||
.label vaddr = 2
|
||||
lda #<0
|
||||
lda #<DEFAULT_SCREEN
|
||||
sta.z vaddr
|
||||
lda #>DEFAULT_SCREEN
|
||||
sta.z vaddr+1
|
||||
tay
|
||||
ldy #0
|
||||
__b1:
|
||||
// for(char i=0;MSG[i];i++)
|
||||
lda MSG,y
|
||||
cmp #0
|
||||
bne __b2
|
||||
// memcpy_to_vram(0, DEFAULT_SCREEN+0x100, MSG2, sizeof(MSG2))
|
||||
// Space is 0x20, red background black foreground
|
||||
jsr memcpy_to_vram
|
||||
// }
|
||||
rts
|
||||
__b2:
|
||||
@ -67,33 +74,91 @@ main: {
|
||||
iny
|
||||
jmp __b1
|
||||
.segment Data
|
||||
// Copy message to screen one char at a time
|
||||
MSG: .text "hello world!"
|
||||
.byte 0
|
||||
// Copy message (and colors) to screen using memcpy_to_vram
|
||||
MSG2: .text "h e l l o w o r l d ! "
|
||||
.byte 0
|
||||
}
|
||||
.segment Code
|
||||
// Put a single byte into VRAM.
|
||||
// Uses VERA DATA0
|
||||
// - bank: Which 64K VRAM bank to put data into (0/1)
|
||||
// - addr: The address in VRAM
|
||||
// - data: The data to put into VRAM
|
||||
// vpoke(byte* zp(2) addr, byte register(X) data)
|
||||
vpoke: {
|
||||
.label addr = 2
|
||||
// Copy block of memory (from RAM to VRAM)
|
||||
// Copies the values of num bytes from the location pointed to by source directly to the memory block pointed to by destination in VRAM.
|
||||
// - vbank: Which 64K VRAM bank to put data into (0/1)
|
||||
// - vdest: The destination address in VRAM
|
||||
// - src: The source address in RAM
|
||||
// - num: The number of bytes to copy
|
||||
memcpy_to_vram: {
|
||||
.const num = $19*SIZEOF_BYTE
|
||||
.label vdest = DEFAULT_SCREEN+$100
|
||||
.label src = main.MSG2
|
||||
.label end = src+num
|
||||
// Transfer the data
|
||||
.label s = 4
|
||||
// *VERA_CTRL &= ~VERA_ADDRSEL
|
||||
// Select DATA0
|
||||
lda #VERA_ADDRSEL^$ff
|
||||
and VERA_CTRL
|
||||
sta VERA_CTRL
|
||||
// <addr
|
||||
lda.z addr
|
||||
// *VERA_ADDRX_L = <addr
|
||||
// *VERA_ADDRX_L = <vdest
|
||||
// Set address
|
||||
lda #0
|
||||
sta VERA_ADDRX_L
|
||||
// *VERA_ADDRX_M = >vdest
|
||||
lda #>vdest
|
||||
sta VERA_ADDRX_M
|
||||
// *VERA_ADDRX_H = VERA_INC_1 | vbank
|
||||
lda #VERA_INC_1
|
||||
sta VERA_ADDRX_H
|
||||
lda #<src
|
||||
sta.z s
|
||||
lda #>src
|
||||
sta.z s+1
|
||||
__b1:
|
||||
// for(; s!=end; s++)
|
||||
lda.z s+1
|
||||
cmp #>end
|
||||
bne __b2
|
||||
lda.z s
|
||||
cmp #<end
|
||||
bne __b2
|
||||
// }
|
||||
rts
|
||||
__b2:
|
||||
// *VERA_DATA0 = *s
|
||||
ldy #0
|
||||
lda (s),y
|
||||
sta VERA_DATA0
|
||||
// for(; s!=end; s++)
|
||||
inc.z s
|
||||
bne !+
|
||||
inc.z s+1
|
||||
!:
|
||||
jmp __b1
|
||||
}
|
||||
// Put a single byte into VRAM.
|
||||
// Uses VERA DATA0
|
||||
// - bank: Which 64K VRAM bank to put data into (0/1)
|
||||
// - addr: The address in VRAM
|
||||
// - data: The data to put into VRAM
|
||||
// vpoke(byte* zp(2) vaddr, byte register(X) data)
|
||||
vpoke: {
|
||||
.label vaddr = 2
|
||||
// *VERA_CTRL &= ~VERA_ADDRSEL
|
||||
// Select DATA0
|
||||
lda #VERA_ADDRSEL^$ff
|
||||
and VERA_CTRL
|
||||
sta VERA_CTRL
|
||||
// <vaddr
|
||||
lda.z vaddr
|
||||
// *VERA_ADDRX_L = <vaddr
|
||||
// Set address
|
||||
sta VERA_ADDRX_L
|
||||
// >addr
|
||||
lda.z addr+1
|
||||
// *VERA_ADDRX_M = >addr
|
||||
// >vaddr
|
||||
lda.z vaddr+1
|
||||
// *VERA_ADDRX_M = >vaddr
|
||||
sta VERA_ADDRX_M
|
||||
// *VERA_ADDRX_H = VERA_INC_0 | bank
|
||||
// *VERA_ADDRX_H = VERA_INC_0 | vbank
|
||||
lda #0
|
||||
sta VERA_ADDRX_H
|
||||
// *VERA_DATA0 = data
|
||||
|
@ -3,41 +3,64 @@ void main()
|
||||
main: scope:[main] from
|
||||
[0] phi()
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@4
|
||||
[1] main::vaddr#3 = phi( main/(byte*) 0, main::@4/main::vaddr#2 )
|
||||
[1] main::i#2 = phi( main/0, main::@4/main::i#1 )
|
||||
main::@1: scope:[main] from main main::@5
|
||||
[1] main::vaddr#3 = phi( main/DEFAULT_SCREEN, main::@5/main::vaddr#2 )
|
||||
[1] main::i#2 = phi( main/0, main::@5/main::i#1 )
|
||||
[2] if(0!=main::MSG[main::i#2]) goto main::@2
|
||||
to:main::@3
|
||||
main::@3: scope:[main] from main::@1
|
||||
[3] phi()
|
||||
[4] call memcpy_to_vram
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
[3] return
|
||||
main::@return: scope:[main] from main::@3
|
||||
[5] return
|
||||
to:@return
|
||||
main::@2: scope:[main] from main::@1
|
||||
[4] vpoke::addr#0 = main::vaddr#3
|
||||
[5] vpoke::data#0 = main::MSG[main::i#2]
|
||||
[6] call vpoke
|
||||
to:main::@3
|
||||
main::@3: scope:[main] from main::@2
|
||||
[7] main::vaddr#1 = ++ main::vaddr#3
|
||||
[8] vpoke::addr#1 = main::vaddr#1
|
||||
[9] call vpoke
|
||||
[6] vpoke::vaddr#0 = main::vaddr#3
|
||||
[7] vpoke::data#0 = main::MSG[main::i#2]
|
||||
[8] call vpoke
|
||||
to:main::@4
|
||||
main::@4: scope:[main] from main::@3
|
||||
[10] main::vaddr#2 = ++ main::vaddr#1
|
||||
[11] main::i#1 = ++ main::i#2
|
||||
main::@4: scope:[main] from main::@2
|
||||
[9] main::vaddr#1 = ++ main::vaddr#3
|
||||
[10] vpoke::vaddr#1 = main::vaddr#1
|
||||
[11] call vpoke
|
||||
to:main::@5
|
||||
main::@5: scope:[main] from main::@4
|
||||
[12] main::vaddr#2 = ++ main::vaddr#1
|
||||
[13] main::i#1 = ++ main::i#2
|
||||
to:main::@1
|
||||
|
||||
void vpoke(byte vpoke::bank , byte* vpoke::addr , byte vpoke::data)
|
||||
vpoke: scope:[vpoke] from main::@2 main::@3
|
||||
[12] vpoke::data#2 = phi( main::@2/vpoke::data#0, main::@3/$21 )
|
||||
[12] vpoke::addr#2 = phi( main::@2/vpoke::addr#0, main::@3/vpoke::addr#1 )
|
||||
[13] *VERA_CTRL = *VERA_CTRL & ~VERA_ADDRSEL
|
||||
[14] vpoke::$0 = < vpoke::addr#2
|
||||
[15] *VERA_ADDRX_L = vpoke::$0
|
||||
[16] vpoke::$1 = > vpoke::addr#2
|
||||
[17] *VERA_ADDRX_M = vpoke::$1
|
||||
[18] *VERA_ADDRX_H = 0
|
||||
[19] *VERA_DATA0 = vpoke::data#2
|
||||
to:vpoke::@return
|
||||
vpoke::@return: scope:[vpoke] from vpoke
|
||||
void memcpy_to_vram(byte memcpy_to_vram::vbank , void* memcpy_to_vram::vdest , void* memcpy_to_vram::src , word memcpy_to_vram::num)
|
||||
memcpy_to_vram: scope:[memcpy_to_vram] from main::@3
|
||||
[14] *VERA_CTRL = *VERA_CTRL & ~VERA_ADDRSEL
|
||||
[15] *VERA_ADDRX_L = 0
|
||||
[16] *VERA_ADDRX_M = >memcpy_to_vram::vdest#0
|
||||
[17] *VERA_ADDRX_H = VERA_INC_1
|
||||
to:memcpy_to_vram::@1
|
||||
memcpy_to_vram::@1: scope:[memcpy_to_vram] from memcpy_to_vram memcpy_to_vram::@2
|
||||
[18] memcpy_to_vram::s#2 = phi( memcpy_to_vram/(byte*)memcpy_to_vram::src#0, memcpy_to_vram::@2/memcpy_to_vram::s#1 )
|
||||
[19] if(memcpy_to_vram::s#2!=memcpy_to_vram::end#0) goto memcpy_to_vram::@2
|
||||
to:memcpy_to_vram::@return
|
||||
memcpy_to_vram::@return: scope:[memcpy_to_vram] from memcpy_to_vram::@1
|
||||
[20] return
|
||||
to:@return
|
||||
memcpy_to_vram::@2: scope:[memcpy_to_vram] from memcpy_to_vram::@1
|
||||
[21] *VERA_DATA0 = *memcpy_to_vram::s#2
|
||||
[22] memcpy_to_vram::s#1 = ++ memcpy_to_vram::s#2
|
||||
to:memcpy_to_vram::@1
|
||||
|
||||
void vpoke(byte vpoke::vbank , byte* vpoke::vaddr , byte vpoke::data)
|
||||
vpoke: scope:[vpoke] from main::@2 main::@4
|
||||
[23] vpoke::data#2 = phi( main::@2/vpoke::data#0, main::@4/$21 )
|
||||
[23] vpoke::vaddr#2 = phi( main::@2/vpoke::vaddr#0, main::@4/vpoke::vaddr#1 )
|
||||
[24] *VERA_CTRL = *VERA_CTRL & ~VERA_ADDRSEL
|
||||
[25] vpoke::$0 = < vpoke::vaddr#2
|
||||
[26] *VERA_ADDRX_L = vpoke::$0
|
||||
[27] vpoke::$1 = > vpoke::vaddr#2
|
||||
[28] *VERA_ADDRX_M = vpoke::$1
|
||||
[29] *VERA_ADDRX_H = 0
|
||||
[30] *VERA_DATA0 = vpoke::data#2
|
||||
to:vpoke::@return
|
||||
vpoke::@return: scope:[vpoke] from vpoke
|
||||
[31] return
|
||||
to:@return
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,11 +1,15 @@
|
||||
const nomodify byte* DEFAULT_SCREEN = (byte*) 0
|
||||
const byte SIZEOF_BYTE = 1
|
||||
const nomodify byte VERA_ADDRSEL = 1
|
||||
const nomodify byte* VERA_ADDRX_H = (byte*) 40738
|
||||
const nomodify byte* VERA_ADDRX_L = (byte*) 40736
|
||||
const nomodify byte* VERA_ADDRX_M = (byte*) 40737
|
||||
const nomodify byte* VERA_CTRL = (byte*) 40741
|
||||
const nomodify byte* VERA_DATA0 = (byte*) 40739
|
||||
const nomodify byte VERA_INC_1 = $10
|
||||
void main()
|
||||
const byte* main::MSG[] = "hello world!"
|
||||
const byte* main::MSG2[] = "h e l l o w o r l d ! "
|
||||
byte main::i
|
||||
byte main::i#1 reg byte y 22.0
|
||||
byte main::i#2 reg byte y 4.888888888888889
|
||||
@ -13,20 +17,34 @@ byte* main::vaddr
|
||||
byte* main::vaddr#1 vaddr zp[2]:2 11.0
|
||||
byte* main::vaddr#2 vaddr zp[2]:2 11.0
|
||||
byte* main::vaddr#3 vaddr zp[2]:2 6.6000000000000005
|
||||
void vpoke(byte vpoke::bank , byte* vpoke::addr , byte vpoke::data)
|
||||
void memcpy_to_vram(byte memcpy_to_vram::vbank , void* memcpy_to_vram::vdest , void* memcpy_to_vram::src , word memcpy_to_vram::num)
|
||||
byte* memcpy_to_vram::end
|
||||
const byte* memcpy_to_vram::end#0 end = (byte*)memcpy_to_vram::src#0+memcpy_to_vram::num#0
|
||||
word memcpy_to_vram::num
|
||||
const word memcpy_to_vram::num#0 num = $19*SIZEOF_BYTE
|
||||
byte* memcpy_to_vram::s
|
||||
byte* memcpy_to_vram::s#1 s zp[2]:4 202.0
|
||||
byte* memcpy_to_vram::s#2 s zp[2]:4 134.66666666666666
|
||||
void* memcpy_to_vram::src
|
||||
const void* memcpy_to_vram::src#0 src = (void*)main::MSG2
|
||||
byte memcpy_to_vram::vbank
|
||||
void* memcpy_to_vram::vdest
|
||||
const void* memcpy_to_vram::vdest#0 vdest = (void*)DEFAULT_SCREEN+$100
|
||||
void vpoke(byte vpoke::vbank , byte* vpoke::vaddr , byte vpoke::data)
|
||||
byte~ vpoke::$0 reg byte a 202.0
|
||||
byte~ vpoke::$1 reg byte a 202.0
|
||||
byte* vpoke::addr
|
||||
byte* vpoke::addr#0 addr zp[2]:2 11.0
|
||||
byte* vpoke::addr#1 addr zp[2]:2 22.0
|
||||
byte* vpoke::addr#2 addr zp[2]:2 56.0
|
||||
byte vpoke::bank
|
||||
byte vpoke::data
|
||||
byte vpoke::data#0 reg byte x 22.0
|
||||
byte vpoke::data#2 reg byte x 16.0
|
||||
byte* vpoke::vaddr
|
||||
byte* vpoke::vaddr#0 vaddr zp[2]:2 11.0
|
||||
byte* vpoke::vaddr#1 vaddr zp[2]:2 22.0
|
||||
byte* vpoke::vaddr#2 vaddr zp[2]:2 56.0
|
||||
byte vpoke::vbank
|
||||
|
||||
reg byte y [ main::i#2 main::i#1 ]
|
||||
zp[2]:2 [ main::vaddr#3 main::vaddr#2 main::vaddr#1 vpoke::addr#2 vpoke::addr#0 vpoke::addr#1 ]
|
||||
zp[2]:2 [ main::vaddr#3 main::vaddr#2 main::vaddr#1 vpoke::vaddr#2 vpoke::vaddr#0 vpoke::vaddr#1 ]
|
||||
zp[2]:4 [ memcpy_to_vram::s#2 memcpy_to_vram::s#1 ]
|
||||
reg byte x [ vpoke::data#2 vpoke::data#0 ]
|
||||
reg byte a [ vpoke::$0 ]
|
||||
reg byte a [ vpoke::$1 ]
|
||||
|
Loading…
Reference in New Issue
Block a user