Jump to content
IGNORED

Lynx Noob


oziphantom

Recommended Posts

So I'm poking around the Lynx, its a bit hard to follow..

 

I have the download doc's pack, I forgot just what a character Mical was XD I think having it all in pieces isn't help either.

 

For example

What is the image format for the lynx and how do I make one?

 

What is the boot up sequence? I guess the ROM inits all the registers,warms up RAM, inits Stack, clears D etc to a know state and loads some of the cart in to RAM? Does it just load the first 64K then flick the reset switch so my code starts from RESET.. only that would need to load over the Registers??

 

Is Handy still the best emulator? Is there one with a better monitor? Maybe even one that lets you telnet into the monitor?

Link to comment
Share on other sites

R.J. Mical is a great character.

amsterdam_1.jpg?template=generic

 

Here is my small hour of fame. Kneeling next to R.J.

 

The image format can be literal. In this case you have 2 pixels per byte. In this forum there is a Tiny Sprite editor that produces this format.

http://atariage.com/forums/topic/273118-tiny-sprite-editor-for-lynx/?p=3911758

 

The boot-up sequence is like this:

 

Boot to ROM.

It reads in a few 51 byte encrypted blocks from the cartridge. The Lynx unencrypts these blocks to check that the cart is legal. Then it proceed in loading in the game.

 

If you are interested in creating something for the Lynx the cc65 includes a small encrypted header that makes the cart "legal".

 

Your own code needs to set up pretty much everything. If you are coding in C the cc65 tools set up the basics.

 

Handy is not the best emulator imho.

Link to comment
Share on other sites

I guess it depends on if you enjoy doing everything from scratch or if you want to focus on creating games.

 

I've tried to put together a thread for helping people get started with Lynx programming, "Atari Lynx programming tools and tutorials":

http://atariage.com/forums/topic/256753-atari-lynx-programming-tools-and-tutorials-wip/

 

Personallly I've been using CC65 "the newer Lynx version of CC65". Karri among others have been updating this version and creates great tools for it. For example there's a great game-template for it (links in the thread) and a nice "mini-manual" http://atariage.com/forums/topic/277916-berzerkoids-alpha/?p=4011451etc.etc. I found it easier to install the compiler on a Raspberry Pi than on Visual Studio. Please note that confusingly the older cc65 version is called "newcc65".

Edited by Turbo Laser Lynx
Link to comment
Share on other sites

R.J. Mical is a great character.

amsterdam_1.jpg?template=generic

 

Here is my small hour of fame. Kneeling next to R.J.

 

The image format can be literal. In this case you have 2 pixels per byte. In this forum there is a Tiny Sprite editor that produces this format.

http://atariage.com/forums/topic/273118-tiny-sprite-editor-for-lynx/?p=3911758

 

The boot-up sequence is like this:

 

Boot to ROM.

It reads in a few 51 byte encrypted blocks from the cartridge. The Lynx unencrypts these blocks to check that the cart is legal. Then it proceed in loading in the game.

 

If you are interested in creating something for the Lynx the cc65 includes a small encrypted header that makes the cart "legal".

 

Your own code needs to set up pretty much everything. If you are coding in C the cc65 tools set up the basics.

 

Handy is not the best emulator imho.

By Image I mean LYX,LNX image formats. perhaps ROMs are the term used in the Atari world.

However on the subject of Sprite graphics format, if one has a sprite that uses an even number of bits say 2 does the sprite data go

Mode bit 2 2 X | 2 2 2 2 | or does it then split the bits across byte boundaries such that you get

Mode bit 2 2 1 | 1 2 2 1 |1 2 2

Link to comment
Share on other sites

I guess it depends on if you enjoy doing everything from scratch or if you want to focus on creating games.

 

I've tried to put together a thread for helping people get started with Lynx programming, "Atari Lynx programming tools and tutorials":

http://atariage.com/forums/topic/256753-atari-lynx-programming-tools-and-tutorials-wip/

 

Personallly I've been using CC65 "the newer Lynx version of CC65". Karri among others have been updating this version and creates great tools for it. For example there's a great game-template for it (links in the thread) and a nice "mini-manual" http://atariage.com/forums/topic/277916-berzerkoids-alpha/?p=4011451etc.etc. I found it easier to install the compiler on a Raspberry Pi than on Visual Studio. Please note that confusingly the older cc65 version is called "newcc65".

Well I want to make games, however I don't want to touch C or CC65/CA65. I have my own preferred Assembler and I have a lot of tools built upon it and its format. So I need to know how to build images and the like with my assembler.

 

Also the 65SC02 is the right CPU, and that is a W65C02 minus all the BIT instructions but it does have the WAI etc?

Link to comment
Share on other sites

Well I want to make games, however I don't want to touch C or CC65/CA65. I have my own preferred Assembler and I have a lot of tools built upon it and its format. So I need to know how to build images and the like with my assembler.

 

Also the 65SC02 is the right CPU, and that is a W65C02 minus all the BIT instructions but it does have the WAI etc?

 

Ok, great, I think some of the other guys would be more capable of answering questions on the "low level stuff" :)

Edited by Turbo Laser Lynx
Link to comment
Share on other sites

You are more than welcome to use your own tools for developing for the Lynx. The most interesting starting point could be the "Lynx Loader from Scratch" topic. It is a very minimal 51 byte boot loader that makes no assumption of file directories or code. You can implement whatever you want!

Link to comment
Share on other sites

The cc65 homebrew Lynx carts has this structure:

 

0xFF

51 byte bootloader

 

It looks like this after it is encrypted (RSA) and obfuscated.

 

        .byte $ff, $4a, $94, $5f, $31, $86, $7b, $9a
        .byte $3c, $cd, $53, $8a, $f9, $d7, $d6, $58
        .byte $0f, $31, $09, $4b, $53, $a4, $fa, $4b
        .byte $65, $cf, $29, $63, $c2, $93, $2b, $38
        .byte $05, $09, $0b, $17, $f8, $3e, $e8, $51
        .byte $d5, $5a, $71, $42, $8d, $ea, $06, $e2
        .byte $57, $cb, $81, $15

After this there is a 151 byte bootloader that understands about the cart directory.

 

After this we have the directory telling what files go onto the cart. A single directory entry is 8 bytes.

; ------------------------------------------------------------------------
; Lynx directory
        .segment "DIRECTORY"


__DIRECTORY_START__:
off0=__STARTOFDIRECTORY__+(__DIRECTORY_END__-__DIRECTORY_START__)
blocka=off0/__BLOCKSIZE__
; Entry 0 - first executable
block0=off0/__BLOCKSIZE__
len0=__STARTUP_SIZE__+__INIT_SIZE__+__CODE_SIZE__+__DATA_SIZE__+__RODATA_SIZE__
        .byte   <block0
        .word   off0 & (__BLOCKSIZE__ - 1)
        .byte   $88
        .word   __RAM_START__
        .word   len0
__DIRECTORY_END__:

And then we have just binary files. One after the other. These file can be graphics, sounds, code, data.

 

I kind of understand that you do not want to use high level languages. But there is one special thing in the cc65 that is valuable for large games. It is the linker and the concept of segments.

 

It is fairly easy to compile code for a segment. The linker keeps tracks of all symbolic names like entry points for routines and variables. When you load in an segment you can call all functions directly. In this way you don't have to bother with housekeeping of the content of the segments.

 

The segments is written to the cart as binary blobs. Loading a blob in the right place is done by just loading the blob.

lynx_load(235);

The directory already knows where in memory to load it. And the linker takes care of telling the other blobs how to access stuff in the loaded blob.

 

This system is very unique to cc65. And I must say I just love it. You can also use it from ca65.

 

Edited by karri
Link to comment
Share on other sites

This was a helpful start for me:

https://atarilynxdeveloper.wordpress.com/2014/09/10/programming-tutorial-part-18files/

even though it targets usage of C, it has some indepth details on coding for the Lynx from scratch.

There are quite several super helpful people here on the forum in case you have specific questions.

Also you learn alot from emulator-code.

Link to comment
Share on other sites

ok so piecing this together with the help of the file enthusi posted.,

 

The "ROM" has

 

This starting at 0 in ROM space.

.byte $ff, $4a, $94, $5f, $31, $86, $7b, $9a
.byte $3c, $cd, $53, $8a, $f9, $d7, $d6, $58
.byte $0f, $31, $09, $4b, $53, $a4, $fa, $4b
.byte $65, $cf, $29, $63, $c2, $93, $2b, $38
.byte $05, $09, $0b, $17, $f8, $3e, $e8, $51
.byte $d5, $5a, $71, $42, $8d, $ea, $06, $e2
.byte $57, $cb, $81, $15

the FF says I have 1 page (256bytes?) of compressed data which is loaded into "somewhere" by the Boot ROM.

 

Eventually this code causes this code at $200 to happen ( after $00-1ff is set to 0)

STZ $fff9 ; enabled all ROM, IO
lda #$04
sta $fd8c ; set TX to OpenCollector
lda #$1a
sta $fd8a ; ExtPower,noexp - input, cartAddress,rest,audin - output
ldx #$00
ldy #$97 ; 151 bytes
lda $fcb2 ; Read Cart 0
sta $fb68,x ; write to RAM 
inx
dey
bne $0211
jmp $fb68 ; execute loaded code

To which then fb68+ will contain the contents of the "ROM" assembled after that header. With a start address of $fb68.

 

Is there a codebase, wiki, documents repository one can put this kind of info, shell files etc?

 

The Challange with this format is that, its not banked ROM like everything else in the world, but uses it as a Magnetic Tape and hence you load in data from it, sequentially where you can choose which "block" you start from, akin to the NES's FDS and the N64 Pak ( although I think that does have random starting points as well)

Link to comment
Share on other sites

CC65/CA65 external Linker is I guess handy, personally I find it to be more hassle. Any linking assembler has those features, see WLA-DX, although I don't think it cares about TEXT, CODE, DATA specifically, that is a hang over from CPUs with "Protected mode", so NASM/MASM, gcc etc will have those sections, as to make an exe,com or elf you need to have those "sections".

 

I use TASS64, which has an internal linker, so I get all of those features but I don't have to split the files or update another file. Since it is N pass, and has an internal Linker you can do insane Voodoo stuff. For example say you have an NTSC and PAL ISR chain ( not a problem for Lynx, mind), they have different code and have a different size. Tass can speculatively assembly both "sections" then I can ask it how big they are, leave a gap big enough to hold them, i.e the largest size, and put on of them in the gap at assemble time.

From memory CA65 due to its C pedigree is only 2 pass, my code typically needs about 7 passes. Tass64s ability to do AOS to SOA transformations, along with custom functions is very nice. It extensive macro support is nice ( although CA65s ability to tell you how many params are passed is envious).

For example I find defining images with binary hard to see

%00000000
%00011000
%00111100
%01100110
%01111110
%01100110
%01100110
%01100110

vs

.dfont '........'
.dfont '...##...'
.dfont '..####..'
.dfont '.##..##.'
.dfont '.######.'
.dfont '.##..##.'
.dfont '.##..##.'
.dfont '.##..##.'

which is possible because you can make this "function"

dfont   .function f       
        .proff    
i        := f
        .for n = 0, n < len(f)/8, n = n + 1
r        := bits(0)    
            .for m = 0, m < 8, m = m + 1
r              ..= (i[0] == '#') ? %1 : %0    
i             := i[1:]
                .if i == ''
                    .break
                .endif
            .next
            .pron
            .byte r
            .proff
        .next
        .pron    
.endf

Then on top of all this I have a custom Mid Level Language, which needs to parse the Listing files and the code format so it can understand defines, this allows it to optimise for me, then TASS64 also points out CPU optimisations for extra tidyness.

Oh also the TASS64 G versions of branches are nice, so if you do GNE and the target is in range, it will BNE, if not

BEQ +

jmp target

+

So I don't have to deal with "your branch target is out of range" ;) On the C variant of the 6502 it will do BRA/JMP optimisations for me as well :D

 

But basically, C on a 65XX is a silly idea, and CA65 is better than most, however too weak for my tastes.

Link to comment
Share on other sites

enthusi - it seems very little is know about this system compared to our usual levels. I feel that digging around the commercial releases to see how this or that was done might be useful. To this end I want to pester Tom-Cat to add 65C02 support to Regenerator. Having 2 people ask, might sway him more, if you are willing?

Link to comment
Share on other sites

ok so piecing this together with the help of the file enthusi posted.,

 

The "ROM" has

 

This starting at 0 in ROM space.

.byte $ff, $4a, $94, $5f, $31, $86, $7b, $9a
.byte $3c, $cd, $53, $8a, $f9, $d7, $d6, $58
.byte $0f, $31, $09, $4b, $53, $a4, $fa, $4b
.byte $65, $cf, $29, $63, $c2, $93, $2b, $38
.byte $05, $09, $0b, $17, $f8, $3e, $e8, $51
.byte $d5, $5a, $71, $42, $8d, $ea, $06, $e2
.byte $57, $cb, $81, $15

the FF says I have 1 page (256bytes?) of compressed data which is loaded into "somewhere" by the Boot ROM.

 

Eventually this code causes this code at $200 to happen ( after $00-1ff is set to 0)

STZ $fff9 ; enabled all ROM, IO
lda #$04
sta $fd8c ; set TX to OpenCollector
lda #$1a
sta $fd8a ; ExtPower,noexp - input, cartAddress,rest,audin - output
ldx #$00
ldy #$97 ; 151 bytes
lda $fcb2 ; Read Cart 0
sta $fb68,x ; write to RAM 
inx
dey
bne $0211
jmp $fb68 ; execute loaded code

To which then fb68+ will contain the contents of the "ROM" assembled after that header. With a start address of $fb68.

 

Is there a codebase, wiki, documents repository one can put this kind of info, shell files etc?

 

The Challange with this format is that, its not banked ROM like everything else in the world, but uses it as a Magnetic Tape and hence you load in data from it, sequentially where you can choose which "block" you start from, akin to the NES's FDS and the N64 Pak ( although I think that does have random starting points as well)

 

The first FF means that there is 51 bytes, FE would have been 2 * 51 bytes. Once the decryption + obfusccation step is complete the last byte of the 51 byte packet should be 0 for the boot process to go further. If it is something else the Lynx will again look for a FF (or some other byte) to see if there is a second set of encrypted blocks.

Link to comment
Share on other sites

But basically, C on a 65XX is a silly idea, and CA65 is better than most, however too weak for my tastes.

 

Developing for Lynx in 2018 is a silly idea.

 

But a year ago I was developing a graphical novel for the Lynx using Scratch. That is truly a silly idea :)

 

There will really soon be a game called "Shaken, not stirred" published for the eJagfest event. It is entirely written in C.

Link to comment
Share on other sites

Are the assembler files from the dev kit somewhere? So I can see what the macros the docs reference contain? ADF is fine.

 

Does it not have hardware scrolling? It seems VOFF, HOFF are "concepts" and the buffers don't actually have any more room to hold additional pixels? So you have to draw the whole buffer, each frame?

Link to comment
Share on other sites

 

Developing for Lynx in 2018 is a silly idea.

 

But a year ago I was developing a graphical novel for the Lynx using Scratch. That is truly a silly idea :)

 

There will really soon be a game called "Shaken, not stirred" published for the eJagfest event. It is entirely written in C.

 

The silly ideas are the best! :) A silent protest against the status quo. ;) Development for modern stuff makes you drown in a sea of irrelevance and with "serious" projects you just get sucked into "the mad machinery" compromising all fun, ethics and artistic vision for becoming a money generating zombie. :-D

Edited by Turbo Laser Lynx
Link to comment
Share on other sites

Last week I spent a couple of days setting up an assembly language development environment for lynx.

I started off tinkering with cc65 and going through the lx.net tutorials (not finished yet).

I also have a working cc65 environment on an android tablet so can code on the go but am using a windows dev environment mostly.

I found a couple of bll archives, one from 1999 and one from 2002 and there is sage's archives as well.

I managed to compile the lyxass 0.50 assembler c code with the latest bloodshed dev-cpp without much bother.

After installing all the additional files and setting path information I found some hello world code from an old atariage post. I created a hello world bitmap and assembled the hello world code. Hurrah. It all works perfectly.

This is my first 6502 code, I think as I am more used to 68000 or originally z80.

  • Like 2
Link to comment
Share on other sites

Can you disable rendering of a line? Blank it out somehow? Then in 16 colour mode being able to offset the Buffer by 4 gives you a VSP scroller. If you drop to 30fps you can do erase plots on 1 frame, new draws on 2nd frame, flip. Depending upon the LCD blur it might not be too jerky... or that speed could just be a mess...

Link to comment
Share on other sites

@oziphantom I like your location, I wish I could live there too! ;) I love Commodore's computers, I had a c64/128 -> a500 -> Lynx back in the day and still do. Starting to get really interrested in the Vic-20 too. Well all the old computers and consoles do have their interresting points.

Edited by Turbo Laser Lynx
Link to comment
Share on other sites

Also the 65SC02 is the right CPU, and that is a W65C02 minus all the BIT instructions but it does have the WAI etc?

 

No. It has BRA, P[L/H][X/Y], STZ and T[s/R]B.

 

It does not have BB[R/S], [R/S]MB, STP or WAI.

 

STP would have been useless, obviously, and there's an attempt to provide something a bit like WAI externally, in that you can request that the CPU sleep until the next interrupt, but it doesn't actually work properly on real hardware. So you'll just have to sit in a perpetual loop and accept a bit of extra unpredictable interrupt latency.

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...