1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-12-27 09:31:18 +00:00

Created new functions to:

- generate bitmap load files.
- load bitmap files into banked memory on the cx16, cross banks between address space A000 and BFFF.
- added cx16-kernal.c and cx16-kernal.h to load files.
- created arithmetic to determine bank addressing using dwords over the 512K of memory (used in bnkcpy_vram_address() and LoadFileBanked()).
 - optimized functions for vera and conio.
This commit is contained in:
FlightControl 2021-01-26 21:55:20 +01:00
parent 473722f8eb
commit 2e0d00bf4e
15 changed files with 1096 additions and 5 deletions

View File

@ -3052,3 +3052,763 @@ sta {z1}+1
//FRAGMENT vbuz1=vbuaa_bor_vbuz1
ora {z1}
sta {z1}
//FRAGMENT _deref_pbuz1=_deref_pbuz1
ldy #0
lda ({z1}),y
ldy #0
sta ({z1}),y
//FRAGMENT _deref_pbuz1=vbuc1
lda #{c1}
ldy #0
sta ({z1}),y
//FRAGMENT vbuaa_neq_0_then_la1
cmp #0
bne {la1}
//FRAGMENT pbuc1_derefidx_vbuaa=vbuc2
tay
lda #{c2}
sta {c1},y
//FRAGMENT pbuc1_derefidx_vbuyy=vbuc2
lda #{c2}
sta {c1},y
//FRAGMENT vbuz1=_byte_vwuz2
lda {z2}
sta {z1}
//FRAGMENT _deref_pbuz1=pbuc1_derefidx_vbuz2
ldy {z2}
lda {c1},y
ldy #0
sta ({z1}),y
//FRAGMENT pbuz1=_inc_pbuz2
clc
lda {z2}
adc #1
sta {z1}
lda {z2}+1
adc #0
sta {z1}+1
//FRAGMENT vbuz1_ge_vbuz2_then_la1
lda {z1}
cmp {z2}
bcs {la1}
//FRAGMENT 0_neq__deref_pbuz1_then_la1
ldy #0
lda ({z1}),y
cmp #0
bne {la1}
//FRAGMENT vbuz1=vbuz1_minus_vbuz2
lda {z1}
sec
sbc {z2}
sta {z1}
//FRAGMENT vbuaa_lt_vbuc1_then_la1
cmp #{c1}
bcc {la1}
//FRAGMENT _deref_pbuz1=pbuc1_derefidx_vbuaa
tay
lda {c1},y
ldy #0
sta ({z1}),y
//FRAGMENT _deref_pbuz1=pbuc1_derefidx_vbuxx
lda {c1},x
ldy #0
sta ({z1}),y
//FRAGMENT _deref_pbuz1=pbuc1_derefidx_vbuyy
lda {c1},y
ldy #0
sta ({z1}),y
//FRAGMENT vbuaa_ge_vbuz1_then_la1
cmp {z1}
bcs {la1}
//FRAGMENT vbuxx=vbuxx_minus_vbuz1
txa
sec
sbc {z1}
tax
//FRAGMENT vbuz1=vbuz1_minus_vbuaa
eor #$ff
sec
adc {z1}
sta {z1}
//FRAGMENT vbuxx=vbuxx_minus_vbuaa
sta $ff
txa
sec
sbc $ff
tax
//FRAGMENT vbuz1=vbuz1_minus_vbuxx
txa
eor #$ff
sec
adc {z1}
sta {z1}
//FRAGMENT vbuxx=vbuxx_minus_vbuxx
lda #0
tax
//FRAGMENT vbuz1=vbuz1_minus_vbuyy
tya
eor #$ff
sec
adc {z1}
sta {z1}
//FRAGMENT vbuxx=vbuxx_minus_vbuyy
txa
sty $ff
sec
sbc $ff
tax
//FRAGMENT vbuxx_ge_vbuz1_then_la1
cpx {z1}
bcs {la1}
//FRAGMENT vbuz1_ge_vbuxx_then_la1
lda {z1}
stx $ff
cmp $ff
bcs {la1}
//FRAGMENT vbuz1_ge_vbuyy_then_la1
lda {z1}
sty $ff
cmp $ff
bcs {la1}
//FRAGMENT vbuxx_ge_vbuyy_then_la1
sty $ff
cpx $ff
bcs {la1}
//FRAGMENT vbuyy_ge_vbuz1_then_la1
cpy {z1}
bcs {la1}
//FRAGMENT _deref_pwuc1=_deref_pwuc1_plus_vbuc2
NO_SYNTHESIS
//FRAGMENT _deref_pwuc1=_deref_pwuc1_plus_vbsc2
NO_SYNTHESIS
//FRAGMENT _deref_pwuc1=_deref_pwuc1_plus_vwuc2
lda #<{c2}
clc
adc {c1}
sta {c1}
lda #>{c2}
adc {c1}+1
sta {c1}+1
//FRAGMENT _deref_pwuc1=vbuc2
lda #0
sta {c1}+1
lda #<{c2}
sta {c1}
//FRAGMENT pbuz1_neq_pbuc1_then_la1
lda {z1}+1
cmp #>{c1}
bne {la1}
lda {z1}
cmp #<{c1}
bne {la1}
//FRAGMENT vbuaa=_byte_vwuz1
lda {z1}
//FRAGMENT vbuxx=_byte_vwuz1
lda {z1}
tax
//FRAGMENT vbuyy=_byte_vwuz1
lda {z1}
tay
//FRAGMENT vduz1_lt_vwuc1_then_la1
NO_SYNTHESIS
//FRAGMENT vduz1_lt_vduc1_then_la1
lda {z1}+3
cmp #>{c1}>>$10
bcc {la1}
bne !+
lda {z1}+2
cmp #<{c1}>>$10
bcc {la1}
bne !+
lda {z1}+1
cmp #>{c1}
bcc {la1}
bne !+
lda {z1}
cmp #<{c1}
bcc {la1}
!:
//FRAGMENT vduz1=vduz2_plus_vwuc1
lda {z2}
clc
adc #<{c1}
sta {z1}
lda {z2}+1
adc #>{c1}
sta {z1}+1
lda {z2}+2
adc #0
sta {z1}+2
lda {z2}+3
adc #0
sta {z1}+3
//FRAGMENT vwuz1=vwuz2_bor_vbuz3
lda {z3}
ora {z2}
sta {z1}
lda {z2}+1
sta {z1}+1
//FRAGMENT vwuz1=vwuz2_ror_5
lda {z2}+1
lsr
sta {z1}+1
lda {z2}
ror
sta {z1}
lsr {z1}+1
ror {z1}
lsr {z1}+1
ror {z1}
lsr {z1}+1
ror {z1}
lsr {z1}+1
ror {z1}
//FRAGMENT vwuz1=vwuz2_band_vwuc1
lda {z2}
and #<{c1}
sta {z1}
lda {z2}+1
and #>{c1}
sta {z1}+1
//FRAGMENT vwuz1=vwuz2_plus_vwuc1
clc
lda {z2}
adc #<{c1}
sta {z1}
lda {z2}+1
adc #>{c1}
sta {z1}+1
//FRAGMENT vduz1=vduz1_plus_vwuc1
lda {z1}
clc
adc #<{c1}
sta {z1}
lda {z1}+1
adc #>{c1}
sta {z1}+1
lda {z1}+2
adc #0
sta {z1}+2
lda {z1}+3
adc #0
sta {z1}+3
//FRAGMENT vwuz1=vwuz2_bor_vbuxx
txa
ora {z2}
sta {z1}
lda {z2}+1
sta {z1}+1
//FRAGMENT vwuz1=vwuz2_bor_vbuyy
tya
ora {z2}
sta {z1}
lda {z2}+1
sta {z1}+1
//FRAGMENT vwuz1=vwuz1_rol_8
lda {z1}
sta {z1}+1
lda #0
sta {z1}
//FRAGMENT vwuz1=vwuz1_bor_vbuyy
tya
ora {z1}
sta {z1}
//FRAGMENT vwuz1=vwuz1_band_vwuc1
lda {z1}
and #<{c1}
sta {z1}
lda {z1}+1
and #>{c1}
sta {z1}+1
//FRAGMENT vwuz1=vwuz1_ror_5
lsr {z1}+1
ror {z1}
lsr {z1}+1
ror {z1}
lsr {z1}+1
ror {z1}
lsr {z1}+1
ror {z1}
lsr {z1}+1
ror {z1}
//FRAGMENT vbuz1=_byte_vduz2
lda {z2}
sta {z1}
//FRAGMENT vduz1=pduc1_derefidx_vbuz2
ldy {z2}
lda {c1},y
sta {z1}
lda {c1}+1,y
sta {z1}+1
lda {c1}+2,y
sta {z1}+2
lda {c1}+3,y
sta {z1}+3
//FRAGMENT vduz1_ge_vduz2_then_la1
lda {z1}+3
cmp {z2}+3
bcc !+
bne {la1}
lda {z1}+2
cmp {z2}+2
bcc !+
bne {la1}
lda {z1}+1
cmp {z2}+1
bcc !+
bne {la1}
lda {z1}
cmp {z2}
bcs {la1}
!:
//FRAGMENT vbsz1=_sbyte_vwuz2
lda {z2}
sta {z1}
//FRAGMENT vbsz1=_inc_vbsz1
inc {z1}
//FRAGMENT vbsz1=vbsz2_minus_vbsz3
lda {z2}
sec
sbc {z3}
sta {z1}
//FRAGMENT vbsz1=vbsc1
lda #{c1}
sta {z1}
//FRAGMENT 0_neq_vbsz1_then_la1
lda {z1}
cmp #0
bne {la1}
//FRAGMENT vduz1=vduz1_minus_vduz2
lda {z1}
sec
sbc {z2}
sta {z1}
lda {z1}+1
sbc {z2}+1
sta {z1}+1
lda {z1}+2
sbc {z2}+2
sta {z1}+2
lda {z1}+3
sbc {z2}+3
sta {z1}+3
//FRAGMENT vbuz1_le_vbuc1_then_la1
lda #{c1}
cmp {z1}
bcs {la1}
//FRAGMENT vbuaa=_byte_vduz1
lda {z1}
//FRAGMENT vbuxx=_byte_vduz1
lda {z1}
tax
//FRAGMENT vbuyy=_byte_vduz1
lda {z1}
tay
//FRAGMENT vbuz1=vbuaa_rol_2
asl
asl
sta {z1}
//FRAGMENT vbuz1=vbuyy_rol_2
tya
asl
asl
sta {z1}
//FRAGMENT vbuaa=vbuaa_rol_2
asl
asl
//FRAGMENT vbuaa=vbuxx_rol_2
txa
asl
asl
//FRAGMENT vbuaa=vbuyy_rol_2
tya
asl
asl
//FRAGMENT vbuxx=vbuaa_rol_2
asl
asl
tax
//FRAGMENT vbuxx=vbuyy_rol_2
tya
asl
asl
tax
//FRAGMENT vbuyy=vbuaa_rol_2
asl
asl
tay
//FRAGMENT vbuyy=vbuxx_rol_2
txa
asl
asl
tay
//FRAGMENT vbuyy=vbuyy_rol_2
tya
asl
asl
tay
//FRAGMENT vduz1=pduc1_derefidx_vbuaa
tay
lda {c1},y
sta {z1}
lda {c1}+1,y
sta {z1}+1
lda {c1}+2,y
sta {z1}+2
lda {c1}+3,y
sta {z1}+3
//FRAGMENT vduz1=pduc1_derefidx_vbuxx
lda {c1},x
sta {z1}
lda {c1}+1,x
sta {z1}+1
lda {c1}+2,x
sta {z1}+2
lda {c1}+3,x
sta {z1}+3
//FRAGMENT vduz1=pduc1_derefidx_vbuyy
lda {c1},y
sta {z1}
lda {c1}+1,y
sta {z1}+1
lda {c1}+2,y
sta {z1}+2
lda {c1}+3,y
sta {z1}+3
//FRAGMENT vbsaa=_sbyte_vwuz1
lda {z1}
//FRAGMENT vbsxx=_sbyte_vwuz1
ldx {z1}
//FRAGMENT vbsz1=vbsz2_minus_vbsxx
txa
eor #$ff
sec
adc {z2}
sta {z1}
//FRAGMENT vbsz1=vbsz2_minus_vbsyy
tya
eor #$ff
sec
adc {z2}
sta {z1}
//FRAGMENT vbsz1=vbsxx_minus_vbsz2
txa
sec
sbc {z2}
sta {z1}
//FRAGMENT vbsz1=vbsxx_minus_vbsxx
lda #0
sta {z1}
//FRAGMENT vbsz1=vbsxx_minus_vbsyy
txa
sty $ff
sec
sbc $ff
sta {z1}
//FRAGMENT vbsz1=vbsyy_minus_vbsz2
tya
sec
sbc {z2}
sta {z1}
//FRAGMENT vbsz1=vbsyy_minus_vbsxx
tya
stx $ff
sec
sbc $ff
sta {z1}
//FRAGMENT vbsz1=vbsyy_minus_vbsyy
lda #0
sta {z1}
//FRAGMENT _deref_pbuz1=vbuaa
ldy #0
sta ({z1}),y
//FRAGMENT vbuaa_le_vbuc1_then_la1
cmp #{c1}
bcc {la1}
beq {la1}
//FRAGMENT vbuaa=vbuaa_plus_vbuc1
clc
adc #{c1}
//FRAGMENT vbuxx_le_vbuc1_then_la1
cpx #{c1}
bcc {la1}
beq {la1}
//FRAGMENT vbuyy_lt_vbuc1_then_la1
cpy #{c1}
bcc {la1}
//FRAGMENT vbuyy_le_vbuc1_then_la1
cpy #{c1}
bcc {la1}
beq {la1}
//FRAGMENT vbsxx=_inc_vbsxx
inx
//FRAGMENT vbsyy=_sbyte_vwuz1
ldy {z1}
//FRAGMENT vbsyy=_inc_vbsyy
iny
//FRAGMENT vbuz1=vbuz2_plus_vbuxx
txa
clc
adc {z2}
sta {z1}
//FRAGMENT vbuaa=vbuz1_plus_vbuxx
txa
clc
adc {z1}
//FRAGMENT vbuxx=vbuz1_plus_vbuxx
txa
clc
adc {z1}
tax
//FRAGMENT vbuyy=vbuz1_plus_vbuxx
txa
clc
adc {z1}
tay
//FRAGMENT vbuz1=vbuaa_plus_vbuxx
stx $ff
clc
adc $ff
sta {z1}
//FRAGMENT vbuaa=vbuaa_plus_vbuxx
stx $ff
clc
adc $ff
//FRAGMENT vbuxx=vbuaa_plus_vbuxx
stx $ff
clc
adc $ff
tax
//FRAGMENT vbuyy=vbuaa_plus_vbuxx
stx $ff
clc
adc $ff
tay
//FRAGMENT vbuz1=vbuxx_plus_vbuxx
txa
asl
sta {z1}
//FRAGMENT vbuaa=vbuxx_plus_vbuxx
txa
asl
//FRAGMENT vbuxx=vbuxx_plus_vbuxx
txa
asl
tax
//FRAGMENT vbuyy=vbuxx_plus_vbuxx
txa
asl
tay
//FRAGMENT vbuz1=vbuyy_plus_vbuxx
txa
sty $ff
clc
adc $ff
sta {z1}
//FRAGMENT vbuaa=vbuyy_plus_vbuxx
txa
sty $ff
clc
adc $ff
//FRAGMENT vbuxx=vbuyy_plus_vbuxx
txa
sty $ff
clc
adc $ff
tax
//FRAGMENT vbuyy=vbuyy_plus_vbuxx
txa
sty $ff
clc
adc $ff
tay
//FRAGMENT vbuz1=vbuz2_plus_vbuyy
tya
clc
adc {z2}
sta {z1}
//FRAGMENT vbuaa=vbuz1_plus_vbuyy
tya
clc
adc {z1}
//FRAGMENT vbuxx=vbuz1_plus_vbuyy
tya
clc
adc {z1}
tax
//FRAGMENT vbuyy=vbuz1_plus_vbuyy
tya
clc
adc {z1}
tay
//FRAGMENT vbuz1=vbuaa_plus_vbuyy
sty $ff
clc
adc $ff
sta {z1}
//FRAGMENT vbuaa=vbuaa_plus_vbuyy
sty $ff
clc
adc $ff
//FRAGMENT vbuxx=vbuaa_plus_vbuyy
sty $ff
clc
adc $ff
tax
//FRAGMENT vbuyy=vbuaa_plus_vbuyy
sty $ff
clc
adc $ff
tay
//FRAGMENT vbuz1=vbuxx_plus_vbuyy
txa
sty $ff
clc
adc $ff
sta {z1}
//FRAGMENT vbuaa=vbuxx_plus_vbuyy
txa
sty $ff
clc
adc $ff
//FRAGMENT vbuxx=vbuxx_plus_vbuyy
txa
sty $ff
clc
adc $ff
tax
//FRAGMENT vbuyy=vbuxx_plus_vbuyy
txa
sty $ff
clc
adc $ff
tay
//FRAGMENT vbuz1=vbuyy_plus_vbuyy
tya
asl
sta {z1}
//FRAGMENT vbuaa=vbuyy_plus_vbuyy
tya
asl
//FRAGMENT vbuxx=vbuyy_plus_vbuyy
tya
asl
tax
//FRAGMENT vbuyy=vbuyy_plus_vbuyy
tya
asl
tay
//FRAGMENT vwuz1=vwuz1_bor_vbuxx
txa
ora {z1}
sta {z1}
//FRAGMENT vbuz1=vbuaa_plus_vbuz1
clc
adc {z1}
sta {z1}
//FRAGMENT vwuz1=vwuz2_rol_3
lda {z2}
asl
sta {z1}
lda {z2}+1
rol
sta {z1}+1
asl {z1}
rol {z1}+1
asl {z1}
rol {z1}+1
//FRAGMENT vwuz1=_word_vbuaa
sta {z1}
lda #0
sta {z1}+1
//FRAGMENT vwuz1=vwuz1_rol_3
asl {z1}
rol {z1}+1
asl {z1}
rol {z1}+1
asl {z1}
rol {z1}+1
//FRAGMENT _deref_pssc1=_deref_pssc2_memcpy_vbuc3
ldy #{c3}
!:
lda {c2}-1,y
sta {c1}-1,y
dey
bne !-
//FRAGMENT pbuz1=pbuz2_plus_vwuc1
clc
lda {z2}
adc #<{c1}
sta {z1}
lda {z2}+1
adc #>{c1}
sta {z1}+1
//FRAGMENT pbuz1_neq_vwuc1_then_la1
lda {z1}+1
cmp #>{c1}
bne {la1}
lda {z1}
cmp #<{c1}
bne {la1}
//FRAGMENT vduz1=vduz2_plus_vduz1
lda {z1}
clc
adc {z2}
sta {z1}
lda {z1}+1
adc {z2}+1
sta {z1}+1
lda {z1}+2
adc {z2}+2
sta {z1}+2
lda {z1}+3
adc {z2}+3
sta {z1}+3
//FRAGMENT pbuz1=pbuz1_plus_vwuc1
clc
lda {z1}
adc #<{c1}
sta {z1}
lda {z1}+1
adc #>{c1}
sta {z1}+1
//FRAGMENT vduz1=vduz2_plus_vduc1
lda {z2}
clc
adc #<{c1}
sta {z1}
lda {z2}+1
adc #>{c1}
sta {z1}+1
lda {z2}+2
adc #<{c1}>>$10
sta {z1}+2
lda {z2}+3
adc #>{c1}>>$10
sta {z1}+3
//FRAGMENT vduz1=vduz2_plus_vbuc1
lda #{c1}
clc
adc {z2}
sta {z1}
lda {z2}+1
adc #0
sta {z1}+1
lda {z2}+2
adc #0
sta {z1}+2
lda {z2}+3
adc #0
sta {z1}+3
//FRAGMENT vduz1=vduz1_plus_vbuc1
lda {z1}
clc
adc #{c1}
sta {z1}
bcc !+
inc {z1}+1
bne !+
inc {z1}+2
bne !+
inc {z1}+3
!:

View File

@ -62,4 +62,8 @@ unsigned char cursor(unsigned char onoff);
// If onoff is 1, scrolling is enabled when outputting past the end of the screen
// If onoff is 0, scrolling is disabled and the cursor instead moves to (0,0)
// The function returns the old scroll setting.
unsigned char scroll(unsigned char onoff);
unsigned char scroll(unsigned char onoff);
// Set the layer with which the conio will interact.
// - layer: value of 0 or 1.
void screenlayer(unsigned byte layer);

View File

@ -0,0 +1,14 @@
// Kernal SETNAM function
// SETNAM. Set file name parameters.
void setnam(char* filename);
// SETLFS. Set file parameters.
void setlfs(char device);
// LOAD. Load or verify file. (Must call SETLFS and SETNAM beforehands.)
// - verify: 0 = Load, 1-255 = Verify
//
// Returns a status, 0xff: Success other: Kernal Error Code
char load(char* address, char verify);

View File

@ -262,5 +262,6 @@ struct VERA_SPRITE {
// - bits 0-3 Palette offset (if 4bpp Color index 1-15 is modified by adding 16 x palette offset)
char CTRL2;
};
// 8BPP sprite mode (add to VERA_SPRITE.ADDR to enable)
// xBPP sprite modes
const unsigned int VERA_SPRITE_4BPP = 0x0000;
const unsigned int VERA_SPRITE_8BPP = 0x8000;

View File

@ -7,6 +7,9 @@
#include <cx16-vera.h>
#include <mos6522.h>
// to POKE the address space.
#define POKE(addr,val) (*(unsigned char*) (addr) = (val))
// The VIA#1: ROM/RAM Bank Control
// Port A Bits 0-7 RAM bank
// Port B Bits 0-2 ROM bank
@ -37,11 +40,19 @@ 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;
// Load a file to memory
// Returns a status:
// - 0xff: Success
// - other: Kernal Error Code (https://commodore.ca/manuals/pdfs/commodore_error_messages.pdf)
char LoadFileBanked( char device, char* filename, dword address);
// Put a single byte into VRAM.
// Uses VERA DATA0
// - vbank: Which 64K VRAM bank to put data into (0/1)
@ -64,6 +75,15 @@ char vpeek(char vbank, char* vaddr);
// - num: The number of bytes to copy
void memcpy_to_vram(char vbank, void* vdest, void* src, unsigned int num );
void memcpy_vram_address(dword vdest, byte* src, unsigned int num );
// Copy block of banked internal memory (256 banks at A000-BFFF) to VERA 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.
// - vdest: dword of the destination address in VRAM
// - src: dword of source banked address in RAM. This address is a linair project of the banked memory of 512K to 2048K.
// - num: dword of the number of bytes to copy
void bnkcpy_vram_address(dword vdest, dword src, dword num );
// Copy block of memory (from VRAM to VRAM)
// Copies the values from the location pointed by src to the location pointed by dest.
// The method uses the VERA access ports 0 and 1 to copy data from and to in VRAM.
@ -76,3 +96,6 @@ void memcpy_to_vram(char vbank, void* vdest, void* src, unsigned int num );
// - num: The number of bytes to copy
void memcpy_in_vram(char dest_bank, void *dest, char dest_increment, char src_bank, void *src, char src_increment, unsigned int num );
void memset_vram_address(dword vdest_address, byte data, dword num);
void memset_vram_word(dword vdest_address, word data, dword num);

View File

@ -0,0 +1,50 @@
#include <cx16-kernal.h>
// Kernal SETNAM function
// SETNAM. Set file name parameters.
void setnam(char* filename) {
char filename_len = (char)strlen(filename);
asm {
// Kernal SETNAM function
// SETNAM. Set file name parameters.
// Input: A = File name length; X/Y = Pointer to file name.
lda filename_len
ldx filename
ldy filename+1
jsr $ffbd
}
}
// SETLFS. Set file parameters.
void setlfs(char device) {
asm {
// SETLFS. Set file parameters.
// Input: A = Logical number; X = Device number; Y = Secondary address.
ldx device
lda #1
ldy #0
jsr $ffba
}
}
// LOAD. Load or verify file. (Must call SETLFS and SETNAM beforehands.)
// - verify: 0 = Load, 1-255 = Verify
//
// Returns a status, 0xff: Success other: Kernal Error Code
char load(char* address, char verify) {
char status;
asm {
//LOAD. Load or verify file. (Must call SETLFS and SETNAM beforehands.)
// Input: A: 0 = Load, 1-255 = Verify; X/Y = Load address (if secondary address = 0).
// Output: Carry: 0 = No errors, 1 = Error; A = KERNAL error code (if Carry = 1); X/Y = Address of last byte loaded/verified (if Carry = 0).
ldx address
ldy address+1
lda verify
jsr $ffd5
bcs error
lda #$ff
error:
sta status
}
return status;
}

View File

@ -3,6 +3,24 @@
// https://github.com/commanderx16/x16-docs/blob/master/Commander%20X16%20Programmer's%20Reference%20Guide.md
#include <cx16.h>
#include <cx16-kernal.h>
#define POKE(addr,val) (*(unsigned char*) (addr) = (val))
// Load a file to memory
// Returns a status:
// - 0xff: Success
// - other: Kernal Error Code (https://commodore.ca/manuals/pdfs/commodore_error_messages.pdf)
char LoadFileBanked( char device, char* filename, dword address) {
setnam(filename);
setlfs(device);
byte bank = (byte)(((((word)<(>address)<<8)|>(<address))>>5)+((word)<(>address)<<3));
byte* addr = ((<address)&0x1FFF); // stip off the top 3 bits, which are representing the bank of the word!
addr += 0xA000;
POKE(0x9f61, (byte)bank); // select the bank
return load(addr, 0);
}
// Put a single byte into VRAM.
// Uses VERA DATA0
@ -55,6 +73,57 @@ void memcpy_to_vram(char vbank, void* vdest, void* src, unsigned int num ) {
*VERA_DATA0 = *s;
}
// 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.
// - vdest: dword of the destination address in VRAM
// - src: The source address in RAM
// - num: The number of bytes to copy
void memcpy_vram_address(dword vdest, byte* src, unsigned int num ) {
// Select DATA0
*VERA_CTRL &= ~VERA_ADDRSEL;
// Set address
*VERA_ADDRX_L = <(<vdest);
*VERA_ADDRX_M = >(<vdest);
*VERA_ADDRX_H = <(>vdest);
*VERA_ADDRX_H |= VERA_INC_1;
// Transfer the data
for(word c=0; c<num; c++)
*VERA_DATA0 = *src++;
}
// Copy block of banked internal memory (256 banks at A000-BFFF) to VERA 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.
// - vdest: dword of the destination address in VRAM
// - src: dword of source banked address in RAM. This address is a linair project of the banked memory of 512K to 2048K.
// - num: dword of the number of bytes to copy
void bnkcpy_vram_address(dword vdest, dword src, dword num ) {
// Select DATA0
*VERA_CTRL &= ~VERA_ADDRSEL;
// Set address
*VERA_ADDRX_L = <(<vdest);
*VERA_ADDRX_M = >(<vdest);
*VERA_ADDRX_H = <(>vdest);
*VERA_ADDRX_H |= VERA_INC_1;
dword beg = src;
dword end = src+num;
byte bank = (byte)(((((word)<(>beg)<<8)|>(<beg))>>5)+((word)<(>beg)<<3));
byte* addr = ((<beg)&0x1FFF); // stip off the top 3 bits, which are representing the bank of the word!
addr += 0xA000;
POKE(0x9f61, (byte)bank); // select the bank
for(dword pos=beg; pos<end; pos++) {
if(addr == 0xC000) {
POKE(0x9f61, (byte)++bank); // select the bank
addr = 0xA000;
}
*VERA_DATA0 = *addr;
addr++;
}
}
// Set block of memory to a value in VRAM.
// Sets num bytes to a value to the memory block pointed to by destination in VRAM.
// - vbank: Which 64K VRAM bank to put data into (0/1)
@ -79,7 +148,7 @@ void memset_vram(char vbank, void* vdest, byte data, word num ) {
// - vdest: The destination address in VRAM
// - data: The value to set the vram with.
// - num: The number of bytes to copy
void memset_vram_address(dword vdest_address, byte data, dword num ) {
void memset_vram_address(dword vdest_address, byte data, dword num) {
// Select DATA0
*VERA_CTRL &= ~VERA_ADDRSEL;
// Set address
@ -92,6 +161,21 @@ void memset_vram_address(dword vdest_address, byte data, dword num ) {
*VERA_DATA0 = data;
}
void memset_vram_word(dword vdest_address, word data, dword num) {
// Select DATA0
*VERA_CTRL &= ~VERA_ADDRSEL;
// Set address
*VERA_ADDRX_L = <(<vdest_address);
*VERA_ADDRX_M = >(<vdest_address);
*VERA_ADDRX_H = <(>vdest_address);
*VERA_ADDRX_H |= VERA_INC_1;
// Transfer the data
for(dword i = 0; i<num; i++) {
*VERA_DATA0 = <data;
*VERA_DATA0 = >data;
}
}
// Copy block of memory (from VRAM to VRAM)
// Copies the values from the location pointed by src to the location pointed by dest.
// The method uses the VERA access ports 0 and 1 to copy data from and to in VRAM.

View File

@ -6,6 +6,7 @@
#include <cx16.h>
#include <veralib.h>
// --- VERA function encapsulation ---
// --- VERA layer management ---
@ -714,4 +715,3 @@ void vera_tile_area(byte layer, word tileindex, byte x, byte y, byte w, byte h,
}
}

View File

@ -0,0 +1,34 @@
// Example program for the Commander X16
#include <cx16.h>
#include <6502.h>
#include <veralib.h>
#include <conio.h>
#include <printf.h>
#include <stdio.h>
void main() {
dword src = (dword)0x02000;
dword num = 64*64*2;
word inc = 0x0123;
for(dword src=0x0000;src<0x3F000;src+=num) {
dword calcbeg = src;
dword calcend = src+num+(-1); // TODO code fragment needed.
byte bankbeg = (byte)(((((word)<(>calcbeg)<<8)|>(<calcbeg))>>5)+((word)<(>calcbeg)<<3));
byte bankend = (byte)(((((word)<(>calcend)<<8)|>(<calcend))>>5)+((word)<(>calcend)<<3));
const word borderbeg = 0xA000;
const word borderend = 0xA000+0x1FFF;
word beg = ((<calcbeg)&0x1FFF); // stip off the top 3 bits, which are representing the bank of the word!
word end = ((<calcend)&0x1FFF); // same for the end;
beg += borderbeg;
end += borderbeg;
printf("cbeg=%x, add=%x, cend=%x, bbeg=%x, bend=%x, beg=%x, end=%x\n", calcbeg, num, calcend, bankbeg, bankend, beg, end );
num+=inc;
}
}

View File

@ -8,7 +8,7 @@
#define NUM_SPRITES 32
// A 64*64 8bpp TUT sprite and palette
__align(0x1000) char SPRITE_PIXELS[64*64+0x200] = kickasm(resource "tut.png") {{
__align(0x0400) char SPRITE_PIXELS[64*64+0x200] = kickasm(resource "tut.png") {{
.var pic = LoadPicture("tut.png")
// palette: rgb->idx
.var palette = Hashtable()

View File

@ -43,6 +43,7 @@ void main() {
printf( "\n0. exit.\n");
byte menu = 0;
while(menu==0) {
menu = fgetc();
}

View File

@ -0,0 +1,8 @@
#include <stdio.h>
void main() {
byte test = 0;
while(test==0) test=fgetc();
printf("\nchar = %u\n", test);
}

View File

@ -0,0 +1,10 @@
// Create a D64 disk containing the program and a sprite file
.file [name="%O", type="prg", segments="Program"]
.file [name="SPRITE", type="bin", segments="Sprite"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=%P]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(%E)
.segmentdef Sprite

View File

@ -0,0 +1,102 @@
// Example program for the Commander X16
#pragma link("load.ld")
#include <cx16.h>
#include <cx16-kernal.h>
#include <6502.h>
#include <veralib.h>
#include <conio.h>
#include <printf.h>
#include <stdio.h>
#include <cx16-kernal.h>
#pragma data_seg(Sprite)
export char SPRITE_PIXELS[] = kickasm(resource "ship.png") {{
.var pic = LoadPicture("ship.png")
// palette: rgb->idx
.var palette = Hashtable()
// RGB value for each palette index
.var palList = List()
// Next palette index
.var nxt_idx = 0;
// Extract palette while outputting pixels as palete index values
.for (var y=0; y<64; y++) {
.for (var x=0;x<64; x++) {
// Find palette index (add if not known)
.var rgb = pic.getPixel(x,y);
.var idx = palette.get(rgb)
.if(idx==null) {
.eval idx = nxt_idx++;
.eval palette.put(rgb,idx);
.eval palList.add(rgb)
}
}
}
.if(nxt_idx>16) .error "Image has too many colours "+nxt_idx
.for(var i=0;i<16;i++) {
.var rgb = palList.get(i)
.var red = floor(rgb / [256*256])
.var green = floor(rgb/256) & 255
.var blue = rgb & 255
// bits 4-8: green, bits 0-3 blue
.byte green&$f0 | blue/16
// bits bits 0-3 red
.byte red/16
}
.for (var y=0; y<64; y++) {
.for (var x=0;x<64; x+=2) {
// Find palette index (add if not known)
.var rgb = pic.getPixel(x,y);
.var idx1 = palette.get(rgb)
.if(idx1==null) {
.printnow "unknown rgb value!"
}
// Find palette index (add if not known)
.eval rgb = pic.getPixel(x+1,y);
.var idx2 = palette.get(rgb)
.if(idx2==null) {
.printnow "unknown rgb value!"
}
.byte idx1*16+idx2;
}
}
}};
#pragma data_seg(Data)
void main() {
vera_layer_set_text_color_mode( 1, VERA_LAYER_CONFIG_16C );
screenlayer(1);
clrscr();
printf("\n\nsprite banked file load and display demo.\n");
const dword BANK_SPRITE = 0x12000; // Load in bank 9.
const dword VRAM_SPRITE = 0x10000; // Load in bank 9.
// Sprite attributes: 8bpp, in front, 64x64, address SPRITE_PIXELS_VRAM
struct VERA_SPRITE SPRITE_ATTR = { <(VRAM_SPRITE/32)|VERA_SPRITE_8BPP, 320-32, 240-32, 0x0c, 0xf1 };
char status = LoadFileBanked(8, "SPRITE", BANK_SPRITE );
bnkcpy_vram_address(VERA_PALETTE+32, BANK_SPRITE-2, 32);
bnkcpy_vram_address(VRAM_SPRITE, BANK_SPRITE+32-2, 64*32);
SPRITE_ATTR.ADDR = <(VRAM_SPRITE/32)|VERA_SPRITE_4BPP;
SPRITE_ATTR.X = 100;
SPRITE_ATTR.Y = 100;
memcpy_to_vram((char)>VERA_SPRITE_ATTR, <VERA_SPRITE_ATTR, &SPRITE_ATTR, sizeof(SPRITE_ATTR));
// Enable sprites
*VERA_CTRL &= ~VERA_DCSEL;
*VERA_DC_VIDEO |= VERA_SPRITES_ENABLE;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB