1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2025-08-07 06:30:04 +00:00
Files
kickc/src/test/kc/c64dtv-gfxexplorer.kc

794 lines
26 KiB
Plaintext

// Interactive Explorer for C64DTV Screen Modes
import "c64dtv.kc"
import "print.kc"
import "keyboard.kc"
import "bitmap-draw.kc"
void main() {
asm { sei } // Disable normal interrupt (prevent keyboard reading glitches and allows to hide basic/kernal)
// Disable kernal & basic
*PROCPORT_DDR = PROCPORT_DDR_MEMORY_MASK;
*PROCPORT = PROCPORT_RAM_IO;
// Enable DTV extended modes
*DTV_FEATURE = DTV_FEATURE_ENABLE;
keyboard_init();
gfx_init();
while(true) {
// Let the user change the GFX configuration
form_mode();
// Show the GFX configuration
gfx_mode();
}
}
// VIC Screens
const byte* VIC_SCREEN0 = $4000;
const byte* VIC_SCREEN1 = $4400;
const byte* VIC_SCREEN2 = $4800;
const byte* VIC_SCREEN3 = $4c00;
const byte* VIC_SCREEN4 = $5000;
// VIC Charset from ROM
const byte* VIC_CHARSET_ROM = $5800;
// VIC Bitmap
const byte* VIC_BITMAP = $6000;
// 8BPP Chunky Bitmap (contains 8bpp pixels)
const dword PLANE_8BPP_CHUNKY = $20000;
// Plane with horisontal stripes
const dword PLANE_HORISONTAL = $30000;
// Plane with vertical stripes
const dword PLANE_VERTICAL = $32000;
// Plane with horisontal stripes every 2 pixels
const dword PLANE_HORISONTAL2 = $34000;
// Plane with vertical stripes every 2 pixels
const dword PLANE_VERTICAL2 = $36000;
// Plane with blank pixels
const dword PLANE_BLANK = $38000;
// Plane with all pixels
const dword PLANE_FULL = $3a000;
// Plane with all pixels
const dword PLANE_CHARSET8 = $3c000;
// Get plane address from a plane index (from the form)
dword get_plane(byte idx) {
if(idx==0) {
return (dword)VIC_SCREEN0;
} else if(idx==1) {
return (dword)VIC_SCREEN1;
} else if(idx==2) {
return (dword)VIC_SCREEN2;
} else if(idx==3) {
return (dword)VIC_SCREEN3;
} else if(idx==4) {
return (dword)VIC_BITMAP;
} else if(idx==5) {
return (dword)VIC_CHARSET_ROM;
} else if(idx==6) {
return (dword)PLANE_8BPP_CHUNKY;
} else if(idx==7) {
return (dword)PLANE_HORISONTAL;
} else if(idx==8) {
return (dword)PLANE_VERTICAL;
} else if(idx==9) {
return (dword)PLANE_HORISONTAL2;
} else if(idx==10) {
return (dword)PLANE_VERTICAL2;
} else if(idx==11) {
return (dword)PLANE_CHARSET8;
} else if(idx==12) {
return (dword)PLANE_BLANK;
} else if(idx==13) {
return (dword)PLANE_FULL;
}
return (dword)VIC_SCREEN0;
}
// Get the VIC screen address from the screen index
byte* get_vic_screen(byte idx) {
if(idx==0) {
return VIC_SCREEN0;
} else if(idx==1) {
return VIC_SCREEN1;
} else if(idx==2) {
return VIC_SCREEN2;
} else if(idx==3) {
return VIC_SCREEN3;
} else if(idx==4) {
return VIC_SCREEN4;
}
return VIC_SCREEN0;
}
// Get the VIC charset/bitmap address from the index
byte* get_vic_charset(byte idx) {
if(idx==0) {
return VIC_CHARSET_ROM;
} else if(idx==1) {
return VIC_BITMAP;
}
return VIC_CHARSET_ROM;
}
// Screen containing the FORM
const byte* FORM_SCREEN = $0400;
// Charset used for the FORM
const byte* FORM_CHARSET = $1800; // Charset ROM
byte[] FORM_TEXT =
" C64 DTV Graphics Mode Explorer @"z +
" @"z +
" PRESET 0 Standard Charset @"z +
" @"z +
" CONTROL PLANE A VIC II @"z +
" bmm 0 pattern p0 screen s0 @"z +
" mcm 0 start 00 gfx g0 @"z +
" ecm 0 step 00 colors c0 @"z +
" hicolor 0 modulo 00 @"z +
" linear 0 COLORS @"z +
" color off 0 PLANE B palet 0 @"z +
" chunky 0 pattern p0 bgcol0 00 @"z +
" border off 0 start 00 bgcol1 00 @"z +
" overscan 0 step 00 bgcol2 00 @"z +
" modulo 00 bgcol3 00 @"z +
"@"z ;
byte[] FORM_COLS =
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@"z +
" @"z +
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@"z +
" @"z +
" nnnnnnnnnnnn mmmmmmmmmm ooooooooo @"z +
" nnnnnnnnnnnn mmmmmmmmmm ooooooooo @"z +
" nnnnnnnnnnnn mmmmmmmmmm ooooooooo @"z +
" nnnnnnnnnnnn mmmmmmmmmm ooooooooo @"z +
" nnnnnnnnnnnn mmmmmmmmmm @"z +
" nnnnnnnnnnnn jjjjjjjjj @"z +
" nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @"z +
" nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @"z +
" nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @"z +
" nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @"z +
" nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @"z +
" nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @"z +
"@"z ;
// Number of form fields
byte form_fields_cnt = 36;
// Form fields x/y-positions
byte[] form_fields_x = { 8, 12, 12, 12, 12, 12, 12, 12, 12, 12, 25, 24, 25, 24, 25, 24, 25, 25, 24, 25, 24, 25, 24, 25, 37, 37, 37, 37, 36, 37, 36, 37, 36, 37, 36, 37 };
byte[] form_fields_y = { 2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 5, 6, 6, 7, 7, 8, 8, 11, 12, 12, 13, 13, 14, 14, 5, 6, 7, 10, 11, 11, 12, 12, 13, 13, 14, 14 };
// Form field max values (all values are in the interval 0..max)
byte[] form_fields_max = { 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, $d, $f, $f, $f, $f, $f, $f, $d, $f, $f, $f, $f, $f, $f, $3, $1, $4, $1, $f, $f, $f, $f, $f, $f, $f, $f };
// Form fields values
byte[] form_fields_val = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
// Preset: Standard Char Mode
byte[] preset_stdchar = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
// Preset: Extended Color Char Mode
byte[] preset_ecmchar = { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 5, 0, 6 };
// Preset: Standard Bitmap
byte[] preset_stdbm = { 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
// Preset: MC Bitmap
byte[] preset_mcbm = { 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0 };
// Preset: Hicolor Standard Char Mode
byte[] preset_hi_stdchar = { 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 };
// Preset: Hicolor Extended Color Char Mode
byte[] preset_hi_ecmchar = { 5, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 3, 4, 6, 8, 9, $c, $c };
// Preset: Two plane mode
byte[] preset_twoplane = { 6, 1, 0, 1, 1, 1, 0, 0, 0, 0, 7, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 7, 0, $d, 4, 0, 0, 0, 0 };
// Preset: Chunky 8bpp
byte[] preset_chunky = { 7, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 8, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 };
// Preset: Sixs FREDs mode
byte[] preset_sixsfred = { 8, 1, 1, 1, 1, 1, 0, 0, 0, 0, $9, 0, 0, 0, 1, 0, 0, $a, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 };
// Preset: Sixs FREDs 2 mode
byte[] preset_sixsfred2 = { 9, 1, 1, 1, 0, 1, 0, 0, 0, 0, $9, 0, 0, 0, 1, 0, 0, $a, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 };
// Preset: 8bpp Pixel Cell
byte[] preset_8bpppixelcell = { 10, 0, 1, 1, 1, 1, 0, 1, 0, 0, $0, 0, 0, 0, 1, 0, 0, $b, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 };
// Apply a form value preset to the form values
// idx is the ID of the preset
void apply_preset(byte idx) {
byte* preset;
if(idx==0) {
preset = preset_stdchar;
} else if(idx==1){
preset = preset_ecmchar;
} else if(idx==2){
preset = preset_stdbm;
} else if(idx==3){
preset = preset_mcbm;
} else if(idx==4){
preset = preset_hi_stdchar;
} else if(idx==5){
preset = preset_hi_ecmchar;
} else if(idx==6){
preset = preset_twoplane;
} else if(idx==7){
preset = preset_chunky;
} else if(idx==8){
preset = preset_sixsfred;
} else if(idx==9){
preset = preset_sixsfred2;
} else if(idx==10){
preset = preset_8bpppixelcell;
} else {
preset = preset_stdchar;
}
// Copy preset values into the fields
for( byte i=0; i != form_fields_cnt; i++) {
form_fields_val[i] = preset[i];
}
}
// Render form preset name in the form
// idx is the ID of the preset
void render_preset_name(byte idx) {
byte* name;
if(idx==0) {
name = "Standard Charset ";
} else if(idx==1){
name = "Extended Color Charset ";
} else if(idx==2){
name = "Standard Bitmap ";
} else if(idx==3){
name = "Multicolor Bitmap ";
} else if(idx==4){
name = "Hicolor Charset ";
} else if(idx==5){
name = "Hicolor Extended Color Charset";
} else if(idx==6){
name = "Twoplane Bitmap ";
} else if(idx==7){
name = "Chunky 8bpp ";
} else if(idx==8){
name = "Sixs Fred ";
} else if(idx==9){
name = "Sixs Fred 2 ";
} else if(idx==10){
name = "8bpp Pixel Cell ";
} else {
name = "Standard Charset ";
}
// Render it
print_str_at(name, FORM_SCREEN+40*2+10);
}
// Form fields direct addressing
const byte* form_preset = form_fields_val+0;
const byte* form_ctrl_bmm = form_fields_val+1;
const byte* form_ctrl_mcm = form_fields_val+2;
const byte* form_ctrl_ecm = form_fields_val+3;
const byte* form_ctrl_hicol = form_fields_val+4;
const byte* form_ctrl_line = form_fields_val+5;
const byte* form_ctrl_colof = form_fields_val+6;
const byte* form_ctrl_chunk = form_fields_val+7;
const byte* form_ctrl_borof = form_fields_val+8;
const byte* form_ctrl_overs = form_fields_val+9;
const byte* form_a_pattern = form_fields_val+10;
const byte* form_a_start_hi = form_fields_val+11;
const byte* form_a_start_lo = form_fields_val+12;
const byte* form_a_step_hi = form_fields_val+13;
const byte* form_a_step_lo = form_fields_val+14;
const byte* form_a_mod_hi = form_fields_val+15;
const byte* form_a_mod_lo = form_fields_val+16;
const byte* form_b_pattern = form_fields_val+17;
const byte* form_b_start_hi = form_fields_val+18;
const byte* form_b_start_lo = form_fields_val+19;
const byte* form_b_step_hi = form_fields_val+20;
const byte* form_b_step_lo = form_fields_val+21;
const byte* form_b_mod_hi = form_fields_val+22;
const byte* form_b_mod_lo = form_fields_val+23;
const byte* form_vic_screen = form_fields_val+24;
const byte* form_vic_gfx = form_fields_val+25;
const byte* form_vic_cols = form_fields_val+26;
const byte* form_dtv_palet = form_fields_val+27;
const byte* form_vic_bg0_hi = form_fields_val+28;
const byte* form_vic_bg0_lo = form_fields_val+29;
const byte* form_vic_bg1_hi = form_fields_val+30;
const byte* form_vic_bg1_lo = form_fields_val+31;
const byte* form_vic_bg2_hi = form_fields_val+32;
const byte* form_vic_bg2_lo = form_fields_val+33;
const byte* form_vic_bg3_hi = form_fields_val+34;
const byte* form_vic_bg3_lo = form_fields_val+35;
// Change graphics mode to show the selected graphics mode
void gfx_mode() {
// Show the GFX configuration
// DTV Graphics Mode
byte dtv_control = 0;
if(*form_ctrl_line!=0) {
dtv_control = dtv_control | DTV_LINEAR;
}
if(*form_ctrl_borof!=0) {
dtv_control = dtv_control | DTV_BORDER_OFF;
}
if(*form_ctrl_hicol!=0) {
dtv_control = dtv_control | DTV_HIGHCOLOR;
}
if(*form_ctrl_overs!=0) {
dtv_control = dtv_control | DTV_OVERSCAN;
}
if(*form_ctrl_colof!=0) {
dtv_control = dtv_control | DTV_COLORRAM_OFF;
}
if(*form_ctrl_chunk!=0) {
dtv_control = dtv_control | DTV_CHUNKY;
}
*DTV_CONTROL = dtv_control;
// VIC Graphics Mode
byte vic_control = VIC_DEN | VIC_RSEL | 3;
if(*form_ctrl_ecm!=0) {
vic_control = vic_control | VIC_ECM;
}
if(*form_ctrl_bmm!=0) {
vic_control = vic_control | VIC_BMM;
}
*VIC_CONTROL = vic_control;
byte vic_control2 = VIC_CSEL;
if(*form_ctrl_mcm!=0) {
vic_control2 = vic_control2 | VIC_MCM;
}
*VIC_CONTROL2 = vic_control2;
// Linear Graphics Plane A Counter
byte plane_a_offs = *form_a_start_hi<<4|*form_a_start_lo;
dword plane_a = get_plane(*form_a_pattern) + plane_a_offs;
*DTV_PLANEA_START_LO = < < plane_a;
*DTV_PLANEA_START_MI = > < plane_a;
*DTV_PLANEA_START_HI = < > plane_a;
*DTV_PLANEA_STEP = *form_a_step_hi<<4|*form_a_step_lo;
*DTV_PLANEA_MODULO_LO = *form_a_mod_hi<<4|*form_a_mod_lo;
*DTV_PLANEA_MODULO_HI = 0;
// Linear Graphics Plane B Counter
byte plane_b_offs = *form_b_start_hi<<4|*form_b_start_lo;
dword plane_b = get_plane(*form_b_pattern) + plane_b_offs;
*DTV_PLANEB_START_LO = < < plane_b;
*DTV_PLANEB_START_MI = > < plane_b;
*DTV_PLANEB_START_HI = < > plane_b;
*DTV_PLANEB_STEP = *form_b_step_hi<<4|*form_b_step_lo;
*DTV_PLANEB_MODULO_LO = *form_b_mod_hi<<4|*form_b_mod_lo;
*DTV_PLANEB_MODULO_HI = 0;
// VIC Graphics Bank
*CIA2_PORT_A_DDR = %00000011; // Set VIC Bank bits to output - all others to input
*CIA2_PORT_A = %00000011 ^ (byte)((word)VIC_SCREEN0/$4000); // Set VIC Bank
// VIC memory
*VIC_MEMORY = (byte)(((word)get_vic_screen(*form_vic_screen)&$3fff)>>6) | ((>((word)get_vic_charset(*form_vic_gfx)&$3fff))>>2);
// VIC Colors
byte* vic_colors = get_vic_screen(*form_vic_cols);
byte* col=COLS;
for(byte cy: 0..24 ) {
for(byte cx: 0..39) {
*col++ = *vic_colors++;
}
}
// Background colors
*BORDERCOL = 0;
*BGCOL1 = *form_vic_bg0_hi<<4|*form_vic_bg0_lo;
*BGCOL2 = *form_vic_bg1_hi<<4|*form_vic_bg1_lo;
*BGCOL3 = *form_vic_bg2_hi<<4|*form_vic_bg2_lo;
*BGCOL4 = *form_vic_bg3_hi<<4|*form_vic_bg3_lo;
// DTV Palette
if(*form_dtv_palet==0) {
// DTV Palette - default
for(byte i : 0..$f) {
DTV_PALETTE[i] = DTV_PALETTE_DEFAULT[i];
}
} else {
// DTV Palette - Grey Tones
for(byte j : 0..$f) {
DTV_PALETTE[j] = j;
}
}
// Wait for the user to press space
while(true) {
while(*RASTER!=$ff) {}
keyboard_event_scan();
byte keyboard_event = keyboard_event_get();
if(keyboard_event==KEY_SPACE) {
// If space pressed - change to form mode 4
return;
}
}
}
// Initialize the different graphics in the memory
void gfx_init() {
gfx_init_screen0();
gfx_init_screen1();
gfx_init_screen2();
gfx_init_screen3();
gfx_init_screen4();
gfx_init_charset();
gfx_init_vic_bitmap();
gfx_init_plane_8bppchunky();
gfx_init_plane_charset8();
gfx_init_plane_horisontal();
gfx_init_plane_vertical();
gfx_init_plane_horisontal2();
gfx_init_plane_vertical2();
gfx_init_plane_blank();
gfx_init_plane_full();
}
void gfx_init_charset() {
*PROCPORT = $32;
byte* chargen = CHARGEN;
byte* charset = VIC_CHARSET_ROM;
for(byte c: 0..$ff) {
for( byte l: 0..7) {
*charset++ = *chargen++;
}
}
*PROCPORT = $37;
}
// Initialize VIC screen 0 ( value is %yyyyxxxx where yyyy is ypos and xxxx is xpos)
void gfx_init_screen0() {
byte* ch=VIC_SCREEN0;
for(byte cy: 0..24 ) {
for(byte cx: 0..39) {
*ch++ = (cy&$f)<<4|(cx&$f);
}
}
}
// Initialize VIC screen 1 ( value is %0000cccc where cccc is (x+y mod $f))
void gfx_init_screen1() {
byte* ch=VIC_SCREEN1;
for(byte cy: 0..24 ) {
for(byte cx: 0..39) {
*ch++ = (cx+cy)&$f;
}
}
}
// Initialize VIC screen 2 ( value is %ccccrrrr where cccc is (x+y mod $f) and rrrr is %1111-%cccc)
void gfx_init_screen2() {
byte* ch=VIC_SCREEN2;
for(byte cy: 0..24 ) {
for(byte cx: 0..39) {
byte col = (cx+cy)&$f;
byte col2 = ($f-col);
*ch++ = col<<4 | col2;
}
}
}
// Initialize VIC screen 3 ( value is %00xx00yy where xx is xpos and yy is ypos
void gfx_init_screen3() {
byte* ch=VIC_SCREEN3;
for(byte cy: 0..24 ) {
for(byte cx: 0..39) {
*ch++ = (cx&3)<<4|(cy&3);
}
}
}
// Initialize VIC screen 4 - all chars are 00
void gfx_init_screen4() {
byte* ch=VIC_SCREEN4;
for(byte cy: 0..24 ) {
for(byte cx: 0..39) {
*ch++ = 0;
}
}
}
// Initialize VIC bitmap
void gfx_init_vic_bitmap() {
// Draw some lines on the bitmap
bitmap_init(VIC_BITMAP);
bitmap_clear();
byte[] lines_x = { $00, $ff, $ff, $00, $00, $80, $ff, $80, $00, $80 };
byte[] lines_y = { $00, $00, $c7, $c7, $00, $00, $64, $c7, $64, $00 };
byte lines_cnt = 9;
for(byte l=0; l<lines_cnt;l++) {
bitmap_line(lines_x[l], lines_x[l+1], lines_y[l], lines_y[l+1]);
}
}
// Initialize 8BPP Chunky Bitmap (contains 8bpp pixels)
void gfx_init_plane_8bppchunky() {
// 320x200 8bpp pixels for Plane
byte gfxbCpuBank = (byte)(PLANE_8BPP_CHUNKY/$4000);
dtvSetCpuBankSegment1(gfxbCpuBank++);
byte* gfxb = $4000;
for(byte y : 0..199) {
for (word x : 0..319) {
// If we have crossed to $8000 increase the CPU BANK segment and reset to $4000
if(gfxb==$8000) {
dtvSetCpuBankSegment1(gfxbCpuBank++);
gfxb = $4000;
}
byte c = (byte)(x+y);
*gfxb++ = c;
}
}
// Reset CPU BANK segment to $4000
dtvSetCpuBankSegment1((byte)($4000/$4000));
}
// Initialize Plane with Horizontal Stripes
void gfx_init_plane_horisontal() {
byte gfxbCpuBank = (byte)(PLANE_HORISONTAL/$4000);
dtvSetCpuBankSegment1(gfxbCpuBank++);
byte* gfxa = $4000 + (PLANE_HORISONTAL & $3fff);
for(byte ay : 0..199) {
for (byte ax : 0..39) {
if((ay&4)==0) {
*gfxa++ = %00000000;
} else {
*gfxa++ = %11111111;
}
}
}
// Reset CPU BANK segment to $4000
dtvSetCpuBankSegment1((byte)($4000/$4000));
}
// Initialize Plane with Horizontal Stripes every 2 pixels
void gfx_init_plane_horisontal2() {
byte gfxbCpuBank = (byte)(PLANE_HORISONTAL2/$4000);
dtvSetCpuBankSegment1(gfxbCpuBank++);
byte* gfxa = $4000 + (PLANE_HORISONTAL2 & $3fff);
byte[] row_bitmask = { %00000000, %01010101, %10101010, %11111111 };
for(byte ay : 0..199) {
for (byte ax : 0..39) {
byte row = (ay>>1) & 3;
*gfxa++ = row_bitmask[row];
}
}
// Reset CPU BANK segment to $4000
dtvSetCpuBankSegment1((byte)($4000/$4000));
}
// Initialize Plane with Vertical Stripes
void gfx_init_plane_vertical() {
byte gfxbCpuBank = (byte)(PLANE_VERTICAL/$4000);
dtvSetCpuBankSegment1(gfxbCpuBank++);
byte* gfxb = $4000 + (PLANE_VERTICAL & $3fff);
for(byte by : 0..199) {
for ( byte bx : 0..39) {
*gfxb++ = %00001111;
}
}
// Reset CPU BANK segment to $4000
dtvSetCpuBankSegment1((byte)($4000/$4000));
}
// Initialize Plane with 8bpp charset
void gfx_init_plane_charset8() {
// 8bpp cells for Plane B (charset) - ROM charset with 256 colors
byte gfxbCpuBank = (byte)(PLANE_CHARSET8/$4000);
dtvSetCpuBankSegment1(gfxbCpuBank++);
byte* gfxa = $4000 + (PLANE_CHARSET8 & $3fff);
byte* chargen = CHARGEN;
*PROCPORT = PROCPORT_RAM_CHARROM;
byte col = 0;
for(byte ch : $00..$ff) {
for ( byte cr : 0..7) {
byte bits = *chargen++;
for ( byte cp : 0..7) {
byte c = 0;
if((bits & $80) != 0) {
c = col;
}
*gfxa++ = c;
bits = bits<<1;
col++;
}
}
}
*PROCPORT = PROCPORT_RAM_IO;
// Reset CPU BANK segment to $4000
dtvSetCpuBankSegment1((byte)($4000/$4000));
}
// Initialize Plane with Vertical Stripes every 2 pixels
void gfx_init_plane_vertical2() {
gfx_init_plane_fill(PLANE_VERTICAL2, %00011011);
}
// Initialize Plane with blank pixels
void gfx_init_plane_blank() {
gfx_init_plane_fill(PLANE_BLANK, 0);
}
// Initialize Plane with all pixels
void gfx_init_plane_full() {
gfx_init_plane_fill(PLANE_FULL, $ff);
}
// Initialize 320*200 1bpp pixel ($2000) plane with identical bytes
void gfx_init_plane_fill(dword plane_addr, byte fill) {
byte gfxbCpuBank = < >(plane_addr<<2);
dtvSetCpuBankSegment1(gfxbCpuBank++);
byte* gfxb = $4000 + (<plane_addr & $3fff);
for(byte by : 0..199) {
for ( byte bx : 0..39) {
*gfxb++ = fill;
}
}
// Reset CPU BANK segment to $4000
dtvSetCpuBankSegment1((byte)($4000/$4000));
}
// Show the form - and let the user change values
void form_mode() {
// Show the form
// Form Colors
print_set_screen(COLS);
print_cls();
print_str_lines(FORM_COLS);
// Form Text
print_set_screen(FORM_SCREEN);
print_cls();
print_str_lines(FORM_TEXT);
// Form Fields
form_set_screen(FORM_SCREEN);
form_render_values();
render_preset_name(*form_preset);
// DTV Graphics Bank
*DTV_GRAPHICS_VIC_BANK = (byte)((dword)FORM_CHARSET/$10000);
// DTV Color Bank
*DTV_COLOR_BANK_LO = <((word)(DTV_COLOR_BANK_DEFAULT/$400));
*DTV_COLOR_BANK_HI = >((word)(DTV_COLOR_BANK_DEFAULT/$400));
// VIC Graphics Bank
*CIA2_PORT_A_DDR = %00000011; // Set VIC Bank bits to output - all others to input
*CIA2_PORT_A = %00000011 ^ (byte)((word)FORM_CHARSET/$4000); // Set VIC Bank
// DTV Graphics Mode
*DTV_CONTROL = 0;
// VIC Graphics Mode
*VIC_CONTROL = VIC_DEN|VIC_RSEL|3;
*VIC_CONTROL2 = VIC_CSEL;
// VIC Memory Pointers
*VIC_MEMORY = (byte)((((word)FORM_SCREEN&$3fff)/$40)|(((word)FORM_CHARSET&$3fff)/$400));
// DTV Plane A to FORM_SCREEN also
*DTV_PLANEA_START_LO = < FORM_SCREEN;
*DTV_PLANEA_START_MI = > FORM_SCREEN;
*DTV_PLANEA_START_HI = 0;
// DTV Palette - default
for(byte i : 0..$f) {
DTV_PALETTE[i] = DTV_PALETTE_DEFAULT[i];
}
// Screen colors
*BGCOL = 0;
*BORDERCOL = 0;
byte preset_current = *form_preset;
// Let the user change values in the form
while(true) {
while(*RASTER!=$ff) {}
if(form_control()!=0) {
// Space pressed - change to GFX mode
return;
}
if(preset_current!=*form_preset) {
// Preset changed - update field values and render
apply_preset(*form_preset);
preset_current = *form_preset;
form_render_values();
render_preset_name(*form_preset);
}
}
return;
}
// Table with addresses of the y-lines of the form. The first line contains the address of the form screen.
byte[25] form_line_lo;
byte[25] form_line_hi;
// Current selected field in the form
byte form_field_idx = 0;
// The number of frames to use for a full blink cycle
const signed byte FORM_CURSOR_BLINK = 40;
// Counts down to blink for form cursor (it is inversed in the lower half)
signed byte form_cursor_count = FORM_CURSOR_BLINK/2;
// Set the screen to use for the form.
// screen is the start address of the screen to use
void form_set_screen(byte* screen) {
// Calculate the field line table
byte* line = screen;
for(byte y: 0..24) {
form_line_lo[y] = <line;
form_line_hi[y] = >line;
line = line + 40;
}
}
// Get the screen address of a form field
// field_idx is the index of the field to get the screen address for
byte* form_field_ptr(byte field_idx) {
byte y = form_fields_y[field_idx];
byte* line = (byte*) { form_line_hi[y], form_line_lo[y] };
byte x = form_fields_x[field_idx];
byte* field = line+x;
return field;
}
// Render all form values from the form_fields_val array
void form_render_values() {
for( byte idx=0; idx<form_fields_cnt; idx++) {
byte* field = form_field_ptr(idx);
*field = print_hextab[form_fields_val[idx]];
}
}
// Reads keyboard and allows the user to navigate and change the fields of the form
// Returns 0 if space is not pressed, non-0 if space is pressed
byte form_control() {
byte* field = form_field_ptr(form_field_idx);
// Blinking cursor
if(--form_cursor_count < 0) {
form_cursor_count = FORM_CURSOR_BLINK;
}
if(form_cursor_count<FORM_CURSOR_BLINK/2) {
*field = *field | $80;
} else {
*field = *field & $7f;
}
// Scan the keyboard
keyboard_event_scan();
byte key_event = keyboard_event_get();
// Navigation using cursor up/down
if(key_event==KEY_CRSR_DOWN) {
// Unblink the cursor
*field = *field & $7f;
if((keyboard_modifiers&KEY_MODIFIER_SHIFT)==0) {
// Move to next field
if(++form_field_idx==form_fields_cnt) {
form_field_idx = 0;
}
} else {
// Move to previous field
if(--form_field_idx==$ff) {
form_field_idx = form_fields_cnt-1;
}
}
// Always blink cursor in new field
form_cursor_count = FORM_CURSOR_BLINK/2;
// Return to refresh
return 0;
}
// Change value with cursor left/right
if(key_event==KEY_CRSR_RIGHT) {
if((keyboard_modifiers&KEY_MODIFIER_SHIFT)==0) {
// Increase value
if(++form_fields_val[form_field_idx]>form_fields_max[form_field_idx]) {
form_fields_val[form_field_idx] = 0;
}
} else {
// Decrease value
if(--form_fields_val[form_field_idx]==$ff) {
form_fields_val[form_field_idx] = form_fields_max[form_field_idx];
}
}
// Render field value
*field = print_hextab[form_fields_val[form_field_idx]];
return 0;
}
// Check for space press
if(key_event==KEY_SPACE) {
return $ff;
}
return 0;
}