1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-11-25 20:32:25 +00:00

Working on MEGA65 platform target. #507

This commit is contained in:
jespergravgaard 2020-08-09 22:34:40 +02:00
parent 4fe1c9b48e
commit 2cec5191e1
13 changed files with 738 additions and 6 deletions

View File

@ -0,0 +1,95 @@
// MEGA65 Registers and Constants
#ifndef __MEGA65__
#error "Target platform must be MEGA64"
#endif
#include <mos6526.h>
#include <mos6569.h>
#include <mos6581.h>
// I/O Personality selection
volatile char * const IO_KEY = 0xd02f;
// C65 Banking Register
volatile char * const IO_BANK = 0xd030;
// Map 2nd KB of colour RAM $DC00-$DFFF (hiding CIA's)
const char CRAM2K = 0b00000001;
// Processor port data direction register
char* const PROCPORT_DDR = 0x00;
// Mask for PROCESSOR_PORT_DDR which allows only memory configuration to be written
const char PROCPORT_DDR_MEMORY_MASK = 0b00000111;
// Processor Port Register controlling RAM/ROM configuration and the datasette
char* const PROCPORT = 0x01;
// RAM in all three areas 0xA000, 0xD000, 0xE000
const char PROCPORT_RAM_ALL = 0b00000000;
// RAM in 0xA000, 0xE000 I/O in 0xD000
const char PROCPORT_RAM_IO = 0b00000101;
// RAM in 0xA000, 0xE000 CHAR ROM in 0xD000
const char PROCPORT_RAM_CHARROM = 0b00000001;
// RAM in 0xA000, I/O in 0xD000, KERNEL in 0xE000
const char PROCPORT_KERNEL_IO = 0b00000110;
// BASIC in 0xA000, I/O in 0xD000, KERNEL in 0xE000
const char PROCPORT_BASIC_KERNEL_IO = 0b00000111;
// The address of the CHARGEN character set
char* const CHARGEN = 0xd000;
// The SID MOS 6581/8580
struct MOS6581_SID * const SID = 0xd400;
// The VIC-II MOS 6567/6569
struct MOS6569_VICII* const VICII = 0xd000;
// Color Ram
char * const COLORRAM = 0xd800;
// Default address of screen character matrix
char * const DEFAULT_SCREEN = 0x0800;
// The CIA#1: keyboard matrix, joystick #1/#2
struct MOS6526_CIA * const CIA1 = 0xdc00;
// The CIA#2: Serial bus, RS-232, VIC memory bank
struct MOS6526_CIA * const CIA2 = 0xdd00;
// CIA#1 Interrupt for reading in ASM
char * const CIA1_INTERRUPT = 0xdc0d;
// CIA#2 timer A&B as one single 32-bit value
unsigned long* const CIA2_TIMER_AB = 0xdd04;
// CIA#2 Interrupt for reading in ASM
char * const CIA2_INTERRUPT = 0xdd0d;
// The vector used when the KERNAL serves IRQ interrupts
void()** const KERNEL_IRQ = 0x0314;
// The vector used when the KERNAL serves NMI interrupts
void()** const KERNEL_NMI = 0x0318;
// The vector used when the HARDWARE serves IRQ interrupts
void()** const HARDWARE_IRQ = 0xfffe;
// The colors of the C64
const char BLACK = 0x0;
const char WHITE = 0x1;
const char RED = 0x2;
const char CYAN = 0x3;
const char PURPLE = 0x4;
const char GREEN = 0x5;
const char BLUE = 0x6;
const char YELLOW = 0x7;
const char ORANGE = 0x8;
const char BROWN = 0x9;
const char PINK = 0xa;
const char DARK_GREY= 0xb;
const char GREY = 0xc;
const char LIGHT_GREEN = 0xd;
const char LIGHT_BLUE = 0xe;
const char LIGHT_GREY = 0xf;
// Get the value to store into D018 to display a specific screen and charset/bitmap
// Optimized for ASM from (char)((((unsigned int)screen&0x3fff)/0x40)|(((unsigned int)charset&0x3fff)/0x400));
char toD018(char* screen, char* gfx);
// Get the value to store into DD00 (CIA 2 port A) to choose a specific VIC bank
// Optimized for ASM from %00000011 ^ (char)((unsigned int)gfx/0x4000)
char toDd00(char* gfx);
// Get the sprite pointer for a sprite.
// The sprite pointer is the index of the sprite within the graphics bank and equal to the sprite (char)(sprite_addr/64)
// The sprite pointers are stored SCREEN+0x3f8+sprite_id to set the pointer of each sprite
char toSpritePtr(char* sprite);
// Select a specific VIC graphics bank by setting the CIA 2 port A (0xdd00) as needed
void vicSelectGfxBank(char* gfx);

View File

@ -0,0 +1,51 @@
// MEGA65 conio.h implementation
#include <conio.h>
#include <mega65.h>
// The screen width
#define CONIO_WIDTH 80
// The screen height
#define CONIO_HEIGHT 25
// The text screen address
char * const CONIO_SCREEN_TEXT = DEFAULT_SCREEN;
// The color screen address
char * const CONIO_SCREEN_COLORS = COLORRAM;
// The default text color
const char CONIO_TEXTCOLOR_DEFAULT = LIGHT_BLUE;
// Use the shared CMB flat memory implementation
#include "conio-cbm-shared.c"
// Return true if there's a key waiting, return false if not
unsigned char kbhit (void) {
// CIA#1 Port A: keyboard matrix columns and joystick #2
char* const CIA1_PORT_A = 0xdc00;
// CIA#1 Port B: keyboard matrix rows and joystick #1.
char* const CIA1_PORT_B = 0xdc01;
// Map CIA I/O
*IO_BANK &= ~CRAM2K;
// Read keyboard
*CIA1_PORT_A = 0;
unsigned char hit = ~*CIA1_PORT_B;
// Map 2K Color RAM
*IO_BANK |= CRAM2K;
return hit;
}
// Set the color for the background. The old color setting is returned.
unsigned char bgcolor(unsigned char color) {
// The background color register address
char * const CONIO_BGCOLOR = 0xd021;
char old = *CONIO_BGCOLOR;
*CONIO_BGCOLOR = color;
return old;
}
// Set the color for the border. The old color setting is returned.
unsigned char bordercolor(unsigned char color) {
// The border color register address
char * const CONIO_BORDERCOLOR = 0xd020;
char old = *CONIO_BORDERCOLOR;
*CONIO_BORDERCOLOR = color;
return old;
}

View File

@ -11,6 +11,8 @@
#include "conio-plus4.c"
#elif defined(__VIC20__)
#include "conio-vic20.c"
#elif defined(__MEGA65__)
#include "conio-mega65.c"
#elif defined(__NES__)
#include "conio-nes.c"
#else

27
src/main/kc/lib/mega65.c Normal file
View File

@ -0,0 +1,27 @@
// Commodore 64 Registers and Constants
#include <mega65.h>
// Get the value to store into D018 to display a specific screen and charset/bitmap
// Optimized for ASM from (char)((((unsigned int)screen&$3fff)/$40)|(((unsigned int)charset&$3fff)/$400));
inline char toD018(char* screen, char* gfx) {
return (>((((unsigned int)screen&$3fff)*4)))|(((>((unsigned int)gfx))/4)&$f);
}
// Get the value to store into DD00 (CIA 2 port A) to choose a specific VIC bank
// Optimized for ASM from %00000011 ^ (char)((unsigned int)gfx/$4000)
inline char toDd00(char* gfx) {
return %00000011 ^ (>((unsigned int)gfx))/$40;
}
// Get the sprite pointer for a sprite.
// The sprite pointer is the index of the sprite within the graphics bank and equal to the sprite (char)(sprite_addr/64)
// The sprite pointers are stored SCREEN+$3f8+sprite_id to set the pointer of each sprite
inline char toSpritePtr(char* sprite) {
return (char)(((unsigned int)sprite)/$40);
}
// Select a specific VIC graphics bank by setting the CIA 2 port A ($dd00) as needed
inline void vicSelectGfxBank(char* gfx) {
CIA2->PORT_A_DDR = %00000011;
CIA2->PORT_A = toDd00(gfx);
}

View File

@ -192,6 +192,11 @@ public class TestPrograms {
compileAndCompare("examples/nes-demo/nes-demo.c");
}
@Test
public void testMega65Addressing32bit() throws IOException, URISyntaxException {
compileAndCompare("examples/mega65/32bit-addressing-mega65.c");
}
@Test
public void testMega65Hello() throws IOException, URISyntaxException {
compileAndCompare("examples/mega65/hello-mega65.c");

View File

@ -0,0 +1,31 @@
// 32-bit addressing using the new addressing mode
#pragma target(mega65)
// Absolute 32-bit address to use for storing/loading data
volatile __zp unsigned long ADDR32;
void main() {
// Modify Color Ram using 32-bit addressing
ADDR32 = 0xff80000;
asm {
ldz #0
!:
tza
sta ((ADDR32)),z
inz
cpz #80
bne !-
}
// Modify Screen using 32-bit addressing
ADDR32 = 0x00000800;
asm {
lda #'*'
ldz #79
!:
sta ((ADDR32)),z
dez
bpl !-
}
}

View File

@ -1,5 +1,4 @@
// Hello World for MEGA 65
// Hello World for MEGA 65 - putting chars directly to the screen
#pragma target(mega65)
char * SCREEN = 0x0800;

View File

@ -0,0 +1,66 @@
// 32-bit addressing using the new addressing mode
.cpu _45gs02
.file [name="32bit-addressing-mega65.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$2001]
.segmentdef Code [start=$2017]
.segmentdef Data [startAfter="Code"]
.segment Basic
.byte $0a, $20, $0a, $00, $fe, $02, $20, $30, $00 // 10 BANK 0
.byte $15, $20, $14, $00, $9e, $20 // 20 SYS
.text toIntString(__start) // NNNN
.byte $00, $00, $00 //
// Absolute 32-bit address to use for storing/loading data
.label ADDR32 = 2
.segment Code
__start: {
// ADDR32
lda #<0
sta.z ADDR32
sta.z ADDR32+1
lda #<0>>$10
sta.z ADDR32+2
lda #>0>>$10
sta.z ADDR32+3
jsr main
rts
}
main: {
// ADDR32 = 0xff80000
// Modify Color Ram using 32-bit addressing
lda #<$ff80000
sta.z ADDR32
lda #>$ff80000
sta.z ADDR32+1
lda #<$ff80000>>$10
sta.z ADDR32+2
lda #>$ff80000>>$10
sta.z ADDR32+3
// asm
ldz #0
!:
tza
sta.z ((ADDR32)),z
inz
cpz #$50
bne !-
// ADDR32 = 0x00000800
// Modify Screen using 32-bit addressing
lda #<$800
sta.z ADDR32
lda #>$800
sta.z ADDR32+1
lda #<$800>>$10
sta.z ADDR32+2
lda #>$800>>$10
sta.z ADDR32+3
// asm
lda #'*'
ldz #$4f
!:
sta.z ((ADDR32)),z
dez
bpl !-
// }
rts
}

View File

@ -0,0 +1,26 @@
(void()) __start()
__start: scope:[__start] from
[0] phi()
to:__start::__init1
__start::__init1: scope:[__start] from __start
[1] (volatile dword) ADDR32 ← (dword) 0
to:__start::@1
__start::@1: scope:[__start] from __start::__init1
[2] phi()
[3] call main
to:__start::@return
__start::@return: scope:[__start] from __start::@1
[4] return
to:@return
(void()) main()
main: scope:[main] from __start::@1
[5] (volatile dword) ADDR32 ← (dword) $ff80000
asm { ldz#0 !: tza sta((ADDR32)),z inz cpz#80 bne!- }
[7] (volatile dword) ADDR32 ← (word) $800
asm { lda#'*' ldz#79 !: sta((ADDR32)),z dez bpl!- }
to:main::@return
main::@return: scope:[main] from main
[9] return
to:@return

View File

@ -0,0 +1,421 @@
Inlined call call __init
CONTROL FLOW GRAPH SSA
(void()) main()
main: scope:[main] from __start::@1
(volatile dword) ADDR32 ← (number) $ff80000
asm { ldz#0 !: tza sta((ADDR32)),z inz cpz#80 bne!- }
(volatile dword) ADDR32 ← (number) $800
asm { lda#'*' ldz#79 !: sta((ADDR32)),z dez bpl!- }
to:main::@return
main::@return: scope:[main] from main
return
to:@return
(void()) __start()
__start: scope:[__start] from
to:__start::__init1
__start::__init1: scope:[__start] from __start
(volatile dword) ADDR32 ← (dword) 0
to:__start::@1
__start::@1: scope:[__start] from __start::__init1
call main
to:__start::@2
__start::@2: scope:[__start] from __start::@1
to:__start::@return
__start::@return: scope:[__start] from __start::@2
return
to:@return
SYMBOL TABLE SSA
(volatile dword) ADDR32 loadstore
(void()) __start()
(label) __start::@1
(label) __start::@2
(label) __start::@return
(label) __start::__init1
(void()) main()
(label) main::@return
Adding number conversion cast (unumber) $ff80000 in (volatile dword) ADDR32 ← (number) $ff80000
Adding number conversion cast (unumber) $800 in (volatile dword) ADDR32 ← (number) $800
Successful SSA optimization PassNAddNumberTypeConversions
Inlining cast (volatile dword) ADDR32 ← (unumber)(number) $ff80000
Inlining cast (volatile dword) ADDR32 ← (unumber)(number) $800
Successful SSA optimization Pass2InlineCast
Simplifying constant integer cast $ff80000
Simplifying constant integer cast $800
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (dword) $ff80000
Finalized unsigned number type (word) $800
Successful SSA optimization PassNFinalizeNumberTypeConversions
Adding NOP phi() at start of __start
Adding NOP phi() at start of __start::@1
Adding NOP phi() at start of __start::@2
CALL GRAPH
Calls in [__start] to main:3
Created 0 initial phi equivalence classes
Coalesced down to 0 phi equivalence classes
Culled Empty Block (label) __start::@2
Adding NOP phi() at start of __start
Adding NOP phi() at start of __start::@1
FINAL CONTROL FLOW GRAPH
(void()) __start()
__start: scope:[__start] from
[0] phi()
to:__start::__init1
__start::__init1: scope:[__start] from __start
[1] (volatile dword) ADDR32 ← (dword) 0
to:__start::@1
__start::@1: scope:[__start] from __start::__init1
[2] phi()
[3] call main
to:__start::@return
__start::@return: scope:[__start] from __start::@1
[4] return
to:@return
(void()) main()
main: scope:[main] from __start::@1
[5] (volatile dword) ADDR32 ← (dword) $ff80000
asm { ldz#0 !: tza sta((ADDR32)),z inz cpz#80 bne!- }
[7] (volatile dword) ADDR32 ← (word) $800
asm { lda#'*' ldz#79 !: sta((ADDR32)),z dez bpl!- }
to:main::@return
main::@return: scope:[main] from main
[9] return
to:@return
VARIABLE REGISTER WEIGHTS
(volatile dword) ADDR32 loadstore 12.0
(void()) __start()
(void()) main()
Initial phi equivalence classes
Added variable ADDR32 to live range equivalence class [ ADDR32 ]
Complete equivalence classes
[ ADDR32 ]
Allocated zp[4]:2 [ ADDR32 ]
INITIAL ASM
Target platform is mega65 / MEGA45GS02
// File Comments
// 32-bit addressing using the new addressing mode
// Upstart
.cpu _45gs02
.file [name="32bit-addressing-mega65.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$2001]
.segmentdef Code [start=$2017]
.segmentdef Data [startAfter="Code"]
.segment Basic
.byte $0a, $20, $0a, $00, $fe, $02, $20, $30, $00 // 10 BANK 0
.byte $15, $20, $14, $00, $9e, $20 // 20 SYS
.text toIntString(__start) // NNNN
.byte $00, $00, $00 //
// Global Constants & labels
// Absolute 32-bit address to use for storing/loading data
.label ADDR32 = 2
.segment Code
// __start
__start: {
jmp __init1
// __start::__init1
__init1:
// [1] (volatile dword) ADDR32 ← (dword) 0 -- vduz1=vduc1
lda #<0
sta.z ADDR32
lda #>0
sta.z ADDR32+1
lda #<0>>$10
sta.z ADDR32+2
lda #>0>>$10
sta.z ADDR32+3
// [2] phi from __start::__init1 to __start::@1 [phi:__start::__init1->__start::@1]
__b1_from___init1:
jmp __b1
// __start::@1
__b1:
// [3] call main
jsr main
jmp __breturn
// __start::@return
__breturn:
// [4] return
rts
}
// main
main: {
// [5] (volatile dword) ADDR32 ← (dword) $ff80000 -- vduz1=vduc1
// Modify Color Ram using 32-bit addressing
lda #<$ff80000
sta.z ADDR32
lda #>$ff80000
sta.z ADDR32+1
lda #<$ff80000>>$10
sta.z ADDR32+2
lda #>$ff80000>>$10
sta.z ADDR32+3
// asm { ldz#0 !: tza sta((ADDR32)),z inz cpz#80 bne!- }
ldz #0
!:
tza
sta.z ((ADDR32)),z
inz
cpz #$50
bne !-
// [7] (volatile dword) ADDR32 ← (word) $800 -- vduz1=vduc1
// Modify Screen using 32-bit addressing
lda #<$800
sta.z ADDR32
lda #>$800
sta.z ADDR32+1
lda #<$800>>$10
sta.z ADDR32+2
lda #>$800>>$10
sta.z ADDR32+3
// asm { lda#'*' ldz#79 !: sta((ADDR32)),z dez bpl!- }
lda #'*'
ldz #$4f
!:
sta.z ((ADDR32)),z
dez
bpl !-
jmp __breturn
// main::@return
__breturn:
// [9] return
rts
}
// File Data
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [1] (volatile dword) ADDR32 ← (dword) 0 [ ] ( [ ] { } ) always clobbers reg byte a
Statement [5] (volatile dword) ADDR32 ← (dword) $ff80000 [ ADDR32 ] ( main:3 [ ADDR32 ] { } ) always clobbers reg byte a
Statement asm { ldz#0 !: tza sta((ADDR32)),z inz cpz#80 bne!- } always clobbers reg byte a reg byte z
Statement [7] (volatile dword) ADDR32 ← (word) $800 [ ADDR32 ] ( main:3 [ ADDR32 ] { } ) always clobbers reg byte a
Statement asm { lda#'*' ldz#79 !: sta((ADDR32)),z dez bpl!- } always clobbers reg byte a reg byte z
Potential registers zp[4]:2 [ ADDR32 ] : zp[4]:2 ,
REGISTER UPLIFT SCOPES
Uplift Scope [] 12: zp[4]:2 [ ADDR32 ]
Uplift Scope [main]
Uplift Scope [__start]
Uplifting [] best 148 combination zp[4]:2 [ ADDR32 ]
Uplifting [main] best 148 combination
Uplifting [__start] best 148 combination
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// 32-bit addressing using the new addressing mode
// Upstart
.cpu _45gs02
.file [name="32bit-addressing-mega65.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$2001]
.segmentdef Code [start=$2017]
.segmentdef Data [startAfter="Code"]
.segment Basic
.byte $0a, $20, $0a, $00, $fe, $02, $20, $30, $00 // 10 BANK 0
.byte $15, $20, $14, $00, $9e, $20 // 20 SYS
.text toIntString(__start) // NNNN
.byte $00, $00, $00 //
// Global Constants & labels
// Absolute 32-bit address to use for storing/loading data
.label ADDR32 = 2
.segment Code
// __start
__start: {
jmp __init1
// __start::__init1
__init1:
// [1] (volatile dword) ADDR32 ← (dword) 0 -- vduz1=vduc1
lda #<0
sta.z ADDR32
lda #>0
sta.z ADDR32+1
lda #<0>>$10
sta.z ADDR32+2
lda #>0>>$10
sta.z ADDR32+3
// [2] phi from __start::__init1 to __start::@1 [phi:__start::__init1->__start::@1]
__b1_from___init1:
jmp __b1
// __start::@1
__b1:
// [3] call main
jsr main
jmp __breturn
// __start::@return
__breturn:
// [4] return
rts
}
// main
main: {
// [5] (volatile dword) ADDR32 ← (dword) $ff80000 -- vduz1=vduc1
// Modify Color Ram using 32-bit addressing
lda #<$ff80000
sta.z ADDR32
lda #>$ff80000
sta.z ADDR32+1
lda #<$ff80000>>$10
sta.z ADDR32+2
lda #>$ff80000>>$10
sta.z ADDR32+3
// asm { ldz#0 !: tza sta((ADDR32)),z inz cpz#80 bne!- }
ldz #0
!:
tza
sta.z ((ADDR32)),z
inz
cpz #$50
bne !-
// [7] (volatile dword) ADDR32 ← (word) $800 -- vduz1=vduc1
// Modify Screen using 32-bit addressing
lda #<$800
sta.z ADDR32
lda #>$800
sta.z ADDR32+1
lda #<$800>>$10
sta.z ADDR32+2
lda #>$800>>$10
sta.z ADDR32+3
// asm { lda#'*' ldz#79 !: sta((ADDR32)),z dez bpl!- }
lda #'*'
ldz #$4f
!:
sta.z ((ADDR32)),z
dez
bpl !-
jmp __breturn
// main::@return
__breturn:
// [9] return
rts
}
// File Data
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __init1
Removing instruction jmp __b1
Removing instruction jmp __breturn
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction lda #>0
Succesful ASM optimization Pass5UnnecesaryLoadElimination
Removing instruction __b1_from___init1:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction __init1:
Removing instruction __b1:
Removing instruction __breturn:
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
(volatile dword) ADDR32 loadstore zp[4]:2 12.0
(void()) __start()
(label) __start::@1
(label) __start::@return
(label) __start::__init1
(void()) main()
(label) main::@return
zp[4]:2 [ ADDR32 ]
FINAL ASSEMBLER
Score: 107
// File Comments
// 32-bit addressing using the new addressing mode
// Upstart
.cpu _45gs02
.file [name="32bit-addressing-mega65.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$2001]
.segmentdef Code [start=$2017]
.segmentdef Data [startAfter="Code"]
.segment Basic
.byte $0a, $20, $0a, $00, $fe, $02, $20, $30, $00 // 10 BANK 0
.byte $15, $20, $14, $00, $9e, $20 // 20 SYS
.text toIntString(__start) // NNNN
.byte $00, $00, $00 //
// Global Constants & labels
// Absolute 32-bit address to use for storing/loading data
.label ADDR32 = 2
.segment Code
// __start
__start: {
// __start::__init1
// ADDR32
// [1] (volatile dword) ADDR32 ← (dword) 0 -- vduz1=vduc1
lda #<0
sta.z ADDR32
sta.z ADDR32+1
lda #<0>>$10
sta.z ADDR32+2
lda #>0>>$10
sta.z ADDR32+3
// [2] phi from __start::__init1 to __start::@1 [phi:__start::__init1->__start::@1]
// __start::@1
// [3] call main
jsr main
// __start::@return
// [4] return
rts
}
// main
main: {
// ADDR32 = 0xff80000
// [5] (volatile dword) ADDR32 ← (dword) $ff80000 -- vduz1=vduc1
// Modify Color Ram using 32-bit addressing
lda #<$ff80000
sta.z ADDR32
lda #>$ff80000
sta.z ADDR32+1
lda #<$ff80000>>$10
sta.z ADDR32+2
lda #>$ff80000>>$10
sta.z ADDR32+3
// asm
// asm { ldz#0 !: tza sta((ADDR32)),z inz cpz#80 bne!- }
ldz #0
!:
tza
sta.z ((ADDR32)),z
inz
cpz #$50
bne !-
// ADDR32 = 0x00000800
// [7] (volatile dword) ADDR32 ← (word) $800 -- vduz1=vduc1
// Modify Screen using 32-bit addressing
lda #<$800
sta.z ADDR32
lda #>$800
sta.z ADDR32+1
lda #<$800>>$10
sta.z ADDR32+2
lda #>$800>>$10
sta.z ADDR32+3
// asm
// asm { lda#'*' ldz#79 !: sta((ADDR32)),z dez bpl!- }
lda #'*'
ldz #$4f
!:
sta.z ((ADDR32)),z
dez
bpl !-
// main::@return
// }
// [9] return
rts
}
// File Data

View File

@ -0,0 +1,9 @@
(volatile dword) ADDR32 loadstore zp[4]:2 12.0
(void()) __start()
(label) __start::@1
(label) __start::@return
(label) __start::__init1
(void()) main()
(label) main::@return
zp[4]:2 [ ADDR32 ]

View File

@ -1,4 +1,4 @@
// Hello World for MEGA 65
// Hello World for MEGA 65 - putting chars directly to the screen
.cpu _45gs02
.file [name="hello-mega65.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]

View File

@ -122,7 +122,7 @@ Allocated zp[1]:2 [ main::i#2 main::i#1 ]
INITIAL ASM
Target platform is mega65 / MEGA45GS02
// File Comments
// Hello World for MEGA 65
// Hello World for MEGA 65 - putting chars directly to the screen
// Upstart
.cpu _45gs02
.file [name="hello-mega65.prg", type="prg", segments="Program"]
@ -201,7 +201,7 @@ Uplifting [] best 391 combination
ASSEMBLER BEFORE OPTIMIZATION
// File Comments
// Hello World for MEGA 65
// Hello World for MEGA 65 - putting chars directly to the screen
// Upstart
.cpu _45gs02
.file [name="hello-mega65.prg", type="prg", segments="Program"]
@ -284,7 +284,7 @@ FINAL ASSEMBLER
Score: 331
// File Comments
// Hello World for MEGA 65
// Hello World for MEGA 65 - putting chars directly to the screen
// Upstart
.cpu _45gs02
.file [name="hello-mega65.prg", type="prg", segments="Program"]