Jump to content
IGNORED

K65


zbyti

Recommended Posts

@funkheld I don't have the strength to help you, ask @xxl, @fenrock or @ivop for help, they have patience for you.

 

Quote

starfiled not funktion

no pun intended? :D starfiled not funkheld ;) 

 

make
/home/zbyti/Programs/k65/bin/k65 @main.k65proj
K65 compiler, version 0.2.1, build Mar  5 2020 22:22:19.
Copyright (C) 2012-2020 Krzysztof Kluczek ( devkk.net ).
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Executing script: /home/zbyti/Programs/k65/bin//system.nut
Executing script: /home/zbyti/Programs/k65/bin//system_atarixl.nut
Compiling file: ../../include/defs.k65 ...
Compiling file: main.k65 ...
Linking...

Bank            Used  Free  BlkFree NoCrossFree
main              556 19923   19711         256
 --- Total ---    556 19923

atari800 main.xex
Using Atari800 config file: /home/zbyti/.atari800.cfg
Created by Atari 800 Emulator, Version 4.2.0

Joystick 0 found
Video Mode: 1008x720x32 windowed, pixel format: BGR16
OpenGL initialized successfully. Version: 2.1 Mesa 20.0.8
OpenGL Pixel Buffer Objects available.
All OK.
rm main.gmap main.lst main.sym

 

Edited by zbyti
pun
  • Haha 1
Link to comment
Share on other sites

  • 3 weeks later...
+---------------------------------------------------------------------------+
| Type 2: Standard 16 KB cartridge                                          |
+---------------------------------------------------------------------------+

 Standard 16 KB cartridge, that occupies 16 KB of address space between
 $8000 and $BFFF.

system_atarixl16cart.nut

output_file_name <- "program.rom"
low_addr <- 0x8000
high_addr <- 0xBFFF

function opt_lowaddr(cmd)
{
	if( !parse_isint() )
		error("Address argument missing")
	local addr = parse_int();
	if( addr<low_addr || addr>=high_addr )
		error("Address outside 0x8000..0xBFFF range")
	low_addr = addr;
}
OPTIONS.lowaddr <- opt_lowaddr

function opt_hiaddr(opt)
{
	if( !parse_isint() )
		error("Address argument missing")
	local addr = parse_int();
	if( addr<low_addr || addr>=high_addr )
		error("Address outside 0x8000..0xBFFF range")
	high_addr = addr;
}
OPTIONS.hiaddr <- opt_hiaddr

function no_system(cmd)
{
}
OPTIONS.noos <- no_system

// creates a bank with default parameters
function link_create_bank(name)
{
	local bnum = bank_count();

	if( bnum>0 )
		error("Atari XL supports only single bank");

	bank_create( name, 1, low_addr, high_addr, 0 );
}

// executed in linker just after initializing all other sections
function link_make_sections()
{
	// generate start
	as <- sec_create()
	sec_set_name(as,"__start")
	sec_set_type(as,"system")
	sec_set_fixaddr(as,low_addr)
	sec_add_bank(as,"main")
	sec_asm(as,"    JMP		main");
	sec_set_referenced(as,1)
	sec_init(as)
}

// write final binary to file
function link_write_binary(path)
{
	bin_fopen_wb(path);

	local nbanks = bank_count();

	if( nbanks!=1 )
		error("Atari XL supports only single bank");

	local bstart = bank_get_start(0);

	bin_emit(0,bstart,1024*16-8);
	bin_write_word(0x0060);
	bin_write_word(low_addr);
	bin_write_word(0x0400);
	bin_write_word(0xBFF8);

	bin_fclose();
}

main.k65proj

-system AtariXL16cart

../../../include/a8_defs.k65    main
main.k65                        main

-o main.rom

-link
!atari800 -cart-type 2 -cart main.rom

main.rom main.car

Edited by zbyti
ROM to CAR
Link to comment
Share on other sites

  • 5 months later...
  • 1 month later...
  • 2 weeks later...
  • 2 months later...
//-----------------------------------------------------------------------------

[
  SCREEN       = 960
  SCREEN_DIV   = 4
  SCREEN_BLOCK = SCREEN/SCREEN_DIV
]

//-----------------------------------------------------------------------------

var RTCLOK=0x14, SAVMSC=0x58, RND=0xD20A

var screen[2]=0x80

//-----------------------------------------------------------------------------

inline wait {
  c- a+RTCLOK { a?RTCLOK } !=
}

inline draw {
  y=SCREEN_BLOCK {
    a=RND n-?{ a=0x46 } else { a=0x47 }
    (screen),y=a y--
  }!=
  a=screen c- a+SCREEN_BLOCK screen=a c+?{ y=screen+1 y++ screen+1=y }
}

//-----------------------------------------------------------------------------

main {
  {
    y=SAVMSC y-- screen=y screen+1=a=SAVMSC+1
    x=SCREEN_DIV { draw x-- }!=
    a=100 wait
  } always
}

//-----------------------------------------------------------------------------

atari000.png.c43847559fecddb5c3f7763e968047df.png

 

main.xex

Edited by zbyti
Link to comment
Share on other sites

//-----------------------------------------------------------------------------

[
  SCREEN       = 960
  SCREEN_DIV   = 4
  SCREEN_BLOCK = SCREEN/SCREEN_DIV
]

//-----------------------------------------------------------------------------

var RTCLOK=0x14, SAVMSC=0x58, RND=0xD20A

var screen[2]=0x80

//-----------------------------------------------------------------------------

inline wait {
  a=100 c- a+RTCLOK { a?RTCLOK } !=
}

inline draw {
  y=SCREEN_BLOCK {
    a=0x46 x=RND n-?{ a=0x47 }
    (screen),y=a y--
  }!=
  a=screen c- a+SCREEN_BLOCK screen=a c+?{ screen+1++ }
}

//-----------------------------------------------------------------------------

main {
  {
    y=SAVMSC y-- screen=y screen+1=a=SAVMSC+1
    a=SCREEN_DIV a!! { draw a?? y=a y-- a=y a!! }!= a??
    wait
  } always
}

//-----------------------------------------------------------------------------

little faster draw procedure

 

you can also use (instead of indirect addressing) self modifying code

Edited by zbyti
Link to comment
Share on other sites

//-----------------------------------------------------------------------------

[
  SCREEN_SIZE  = 960
  SCREEN_DIV   = 4
  SCREEN_BLOCK = SCREEN_SIZE / SCREEN_DIV
]

//-----------------------------------------------------------------------------

var RTCLOK=0x14, SAVMSC=0x58, RND=0xD20A

var screen=0, counter=0x80

//-----------------------------------------------------------------------------

inline wait {
  a=100 c- a+RTCLOK { a?RTCLOK } !=
}

func draw {
  y=SCREEN_BLOCK {
    a=0x46 x=RND n-?{ a=0x47 }
    SCR: screen,y=a y--
  }!=
  a=SCR+1 c- a+SCREEN_BLOCK SCR+1=a c+?{ SCR+2++ }
}

//-----------------------------------------------------------------------------

main {
  {
    y=SAVMSC y-- SCR+1=y SCR+2=a=SAVMSC+1
    counter=a=SCREEN_DIV { draw counter-- }!=
    wait
  } always
}

//-----------------------------------------------------------------------------

 

Link to comment
Share on other sites

a=PORTA a^0xFF a&0b1111
z-? {
  a>> c+?{ COLBK=a=RANDOM goto .JOY_END }  //up    1
  a>> c+?{ COLBK=a=RANDOM goto .JOY_END }  //down  2
  a>> c+?{ COLBK=a=RANDOM goto .JOY_END }  //left  4
           COLBK=a=RANDOM                  //right 8
  .JOY_END:
}
func joy_check {
  a=PORTA a^0xFF a&0b1111
  z-?{
    a>> c+?{ a!! arm_fighter_up    a?? } //up    1
    a>> c+?{ a!! arm_fighter_down  a?? } //down  2
    a>> c+?{ a!! arm_fighter_left  a?? } //left  4
    a>> c+?{ a!! arm_fighter_right a?? } //right 8
  }
}

snippets for joy ;) 

Edited by zbyti
Link to comment
Share on other sites

//-----------------------------------------------------------------------------

[
  SCREEN_X_SIZE   = 40
  SCREEN_Y_SIZE   = 24
  FIGHTER_X_SIZE  = 7
  FIGHTER_Y_SIZE  = 4

  FIGHTER_MIN_X   = 0
  FIGHTER_MAX_X   = SCREEN_X_SIZE - FIGHTER_X_SIZE
  FIGHTER_MIN_Y   = 0
  FIGHTER_MAX_Y   = SCREEN_Y_SIZE - FIGHTER_Y_SIZE
]

//-----------------------------------------------------------------------------

var RTCLOK=0x14, SAVMSC=0x58

//-----------------------------------------------------------------------------

var fighter_pos[2]=0x80, tmp[2], iter, joy_dir, fighter_pos_x, fighter_pos_y

//-----------------------------------------------------------------------------

inline pause {
  a=RTCLOK { a?RTCLOK }==
}

//-----------------------------------------------------------------------------

func draw_fighter {
  tmp=a=fighter_pos tmp+1=a=fighter_pos+1

  x=0 iter=a=FIGHTER_Y_SIZE {

    y=[FIGHTER_X_SIZE-1] {
      (tmp),y=a=fighter_gfx,x
      x++ y--
    }>=0

    a=tmp c- a+SCREEN_X_SIZE tmp=a c+?{ tmp+1++ }
    iter--
  }!=
}

//-----------------------------------------------------------------------------

func move_up {
  a=fighter_pos_y a?FIGHTER_MIN_Y !={
    a=fighter_pos c+ a-SCREEN_X_SIZE fighter_pos=a c-?{ fighter_pos+1-- }
    fighter_pos_y--
  }
}

func move_down {
  a=fighter_pos_y a?FIGHTER_MAX_Y !={
    a=fighter_pos c- a+SCREEN_X_SIZE fighter_pos=a c+?{ fighter_pos+1++ }
    fighter_pos_y++
  }
}

func move_right {
  a=fighter_pos_x a?FIGHTER_MAX_X !={
    a=fighter_pos c- a+1 fighter_pos=a c+?{ fighter_pos+1++ }
    fighter_pos_x++
  }
}

func move_left {
  a=fighter_pos_x a?FIGHTER_MIN_X !={
    a=fighter_pos c+ a-1 fighter_pos=a c-?{ fighter_pos+1-- }
    fighter_pos_x--
  }
}

//-----------------------------------------------------------------------------

func joy_check {
  a=PORTA a^0xFF a&0b1111 joy_dir=a
  z-?{
    joy_dir>> c+?{ move_up    }
    joy_dir>> c+?{ move_down  }
    joy_dir>> c+?{ move_left  }
    joy_dir>> c+?{ move_right }
  }
}

//-----------------------------------------------------------------------------

main {
  fighter_pos=a=SAVMSC fighter_pos+1=a=SAVMSC+1
  fighter_pos_x=a=FIGHTER_MIN_X fighter_pos_y=a=FIGHTER_MIN_Y
  draw_fighter

  {
    pause

    a=RTCLOK a&1 =={
      joy_check draw_fighter
    }

  } always
}

//-----------------------------------------------------------------------------

data fighter_gfx {
  align 256
  0x00 0x00 0x00 0x00 0x00 0x00 0x00
  0x00 0x00 0x00 0x55 0x00 0x4A 0x00
  0x00 0x7F 0x80 0xD2 0x80 0xC4 0x00
  0x00 0x00 0x00 0x00 0x00 0x00 0x00
}

//-----------------------------------------------------------------------------

Screenshot_2021-11-23_11-33-52.thumb.png.54dc214842ce2df7fd3cc48b547e36d4.png

main.xex

Edited by zbyti
  • Like 2
Link to comment
Share on other sites

//-----------------------------------------------------------------------------
// Endless Scroll
//-----------------------------------------------------------------------------
[
  HSCROL_START  = 0xF
  HSCROL_END    = HSCROL_START - 4
  SCROLL_OFFSET = 40 + 1
]

//-----------------------------------------------------------------------------

var RTCLOK=0x14, SDLSTL=0x230, SDLSTH=0x231

//-----------------------------------------------------------------------------

var hscroll_i=0x80, screen=0x6000

//-----------------------------------------------------------------------------

inline pause {
  a=RTCLOK { a?RTCLOK } ==
}

//-----------------------------------------------------------------------------

main {
  SDLSTL=a=&<dl SDLSTH=a=&>dl
  hscroll_i=a=HSCROL_START x=0

  {
    a=hscroll_i a?HSCROL_END =={

      a=RANDOM a&15 c- a+33

      screen,x=screen+SCROLL_OFFSET,x=a
      screen+0x100,x=screen+[0x100+SCROLL_OFFSET],x=a
      screen+0x200,x=screen+[0x200+SCROLL_OFFSET],x=a

      LMS1++ LMS2++ LMS3++ x++

      x?SCROLL_OFFSET =={
        x=0 a=x LMS1=LMS2=LMS3=a
      }

      hscroll_i=a=HSCROL_START

    }

    HSCROL=a=hscroll_i hscroll_i--

    pause

  } always
}

//-----------------------------------------------------------------------------

data dl {
  nocross
  0x70 0x70 0x70
  0x52 LMS1: &<screen &>screen
  0x52 LMS2: &<screen &>screen+0x100
  0x52 LMS3: &<screen &>screen+0x200
}

//-----------------------------------------------------------------------------

 

Screenshot_2021-11-23_20-44-45.thumb.png.bf97576da0d4ae4588d3c28f1e920738.png

main.xex

 

Edited by zbyti
  • Like 1
Link to comment
Share on other sites

Thanks @zbyti for those examples and the documentation. From a first read, it looks like K65 is essentially a powerful assembler rather than what would be considered a traditional programming language (typically something more abstract and portable, like C). It has many features that make coding in assembly much more efficient.

 

Have you found any limitations using it compared to other assemblers? I wonder if K65 should be regarded now as the main tool for coding directly on the 6502.

  • Thanks 1
Link to comment
Share on other sites

@RSA

 

I don't know well the other ASM available today to make a proper comparison, but from what I noticed compared to MADS:

 

- there are no macros like `ADW` etc.
- it is not possible to write your own procedure with parameters
- there are no libraries such as players with relocators or popular depackers.
- blocks {...} after exceeding -127 ... +127 do not act like (for example) `JNE`

 

and most importantly: the K65 compiler in version 0.2.1 does report syntax errors very poorly - so it is better to write error-free code ;) 

 

Neither of these things prevents me from exclusively writing in K65 on 8-bit.

 

It's very easy to make new targets for new 8-bit platforms.

 

In K65, KK/Altari wrote some winning demos for the Atari 2600, and Druidarium for A8 took second place on copyparty a few years ago.

 

If you found the K65 readable, you will surely find it useful :) 

 

---

ps.

current version on: https://github.com/Krzysiek-K/k65

Edited by zbyti
  • Thanks 1
Link to comment
Share on other sites

  • 2 months later...

Winner of the Lovebyte 2022, oldskool 128B, coded by superogue. Without undocumented codes ;) 

 

https://www.pouet.net/prod.php?which=91099

 

var RTCLOK2=0x14
var ROWCRS=0x54, COLCRS

var tmp=0x80

var PCOLR0=0x02C0
var COLOR0=0x02C4

var COLPF1=0xD017, COLPF2
var VCOUNT=0xD40B

var SOP=0xEF90
var SPB=0xF1A4

main {
  //gfx mode E
  a=0x0F call SOP

  //draw highways
  {
    a=ROWCRS x=a a+COLCRS

    tmp=a a&1 hc_centre=a

    y=a a=x a&8 !={ hc_centre=a=5 } a=x a-COLCRS

    a!! a&tmp a>> a>> a>> a>> a>> c- a-1 a?? c-?{ a=tmp } a>> a&0x1F a>>

    x=a a=y PCOLR0,x=a a=highway_colors,x
    a?5 !={
      y?1 !={ a=y } 
    }

    call SPB

    a=y
  } n-?

  COLOR0++ y=2

  //animate city traffic
  {
    a=VCOUNT
    x=a a-RTCLOK2 a&0x2F a-0x2C a=y c+?{ a=0x1C } COLPF1=a
    a=x a+RTCLOK2 a&0x1F a-0x1C a=y c+?{ a=0x16 } COLPF2=a
  } v-?
}

data highway_colors {
             5 1 1 2 1 1
  hc_centre: 1 1
             1 1 3 1 1 5
}

https://github.com/zbyti/k65-playground/tree/main/src/a8/interstate

Edited by zbyti
  • Like 3
Link to comment
Share on other sites

Mortal Coil by @F#READY translated to K65

 

/*

Mortal Coil, for Outline 2k17, 128 bytes compo
Kind of rotating starfield using one missile and DMA off!

Credits to 'White Flame' for describing sine wave generation, found here:
http://codebase64.org/doku.php?id=base:generating_approximate_sines_in_assembly

F#READY, May 2017

-----------------

translated by zbyti without annoying sound ;)

-----------------

*/

//GTIA
var HPOSM0    = 0xD004
var GRAFM     = 0xD011, COLPM0
var GRACTL    = 0xD01D

//POKEY
var RANDOM    = 0xD20A

//ANTIC
var WSYNC     = 0xD40A, VCOUNT

//OS
var RTCLOK2   = 0x14
var DMA       = 0x22F

//custom variables
var positions	= 0x3000
var colors      = 0x3100
var sinewave	= 0x3200

var temp        = 0x80

//-----------------------------------------------------------------------------

inline wait {
  { a=VCOUNT } !=
}

//-----------------------------------------------------------------------------

inline makesine {
  y=0x3F
  {
    c-
    .value_lo: a=0 .delta_lo: a+0 .value_lo+1=a
    .value_hi: a=0 .delta_hi: a+0 .value_hi+1=a

    sinewave+0xC0,x=sinewave+0x80,y=a 
    a^0x7F
    sinewave+0x40,x=sinewave+0x00,y=a

    a=.delta_lo+1 a+8 .delta_lo+1=a c+?{ .delta_hi+1++ }
    
    x++ y--
  } >=0
}

//-----------------------------------------------------------------------------

inline fillrnd {
  { a=RANDOM positions,y=colors,y=a y-- } !=
}

//-----------------------------------------------------------------------------

inline putmsl {
  x=RTCLOK2 y=254
  {
    a=positions,x positions,x++ temp=x x=a
    a=sinewave,x c- x=temp a+sinewave,x a>> a+0x40

    HPOSM0=WSYNC=a a=colors,x COLPM0=a

    x++ y--      
  } !=
}

//-----------------------------------------------------------------------------

main {
  DMA=x=0 makesine GRACTL=a=3 fillrnd
  { wait putmsl } ==
}

https://github.com/zbyti/k65-playground/tree/main/src/a8/mortalcoil

Edited by zbyti
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...