Jump to content
Mr SQL

Abstract Assembly Development Kit

Recommended Posts

post-30777-0-80565900-1349021720_thumb.jpg

 

The Abstract Assembly Development kit

 

Is an Assembly Language Programming Framework for the Atari2600 that provides the equivelent of Hardware based horizontal scrolling and a screen buffer! It also abstracts and/or eliminates Racing The Beam (scanlines) and timing/cycle counting and flipping the portions of the screen backwards and forwards (large WYSIWYG bitmaps are supported) so the developer can focus just on the logic for their Assembly games and leverage high level calls to the phantom hardware.

 

This framework is an excellent resource for advanced bB developers to rapidly gain a working knowledge of Assembly language programming; you just have to start writing code to learn Assembly but it's daunting and near impossible to learn the chipset and concepts such as programming without a screen buffer let alone horizontal scrolling without hardware support (when I learned Assembly in the 80's I had these things all available in hardware, the 2600 is quite a unique beast!)

 

Anyone may use the kit however they wish (no strings attached), please enjoy!

 

Examples to try:

 

ScrollOut: Scrollout2.bin

 

This has a demo and an unfinished breakout style game; the demo scrolls horizontally and diagonally a few times and then starts breaking out, pressing the fire button will scroll a "Eady Player One!" banner and then start the game; the camera initially follows the paddle but once you launch the ball it follows the ball, making it very difficult to hit the ball with the paddle when it scrolls diagonally/vertically and you have to find it - this game will be changed so that it only scrolls horizontally (no vertical/diagonal scrolling), so that it will be fun :)

 

ScrollDraw: Scrolldraw.bin

 

This is the traditional "draw on the screen" demo only it scrolls and the camera follows the cursor, source code to show how simple this assembly program is follows!

 

Sample Code from ScrollDraw:

 

Here is a short simple Assembly example from ScrollDraw.bin, drawing on a large scrolling virtual world; try the demo's and take a look at the code and let's discuss it! I'll be posting the source for the framework shortly, it already works with the version of DASM that comes with bB so you have everything you need:

 

; ---------------------------------------------------------

; ------ Your Assembly code goes here:

;----------------------------------------------------------

;-----SCROLL Draw:

;-----Simple Demo for the Abstract Assembly Development Kit

; Hold the Button Down to Draw or Erase

;-------------------------------------------------------

; bity, bitx - x and y vars for the large virtual world

; BITindex, x value for horizontaly scrolling anywhere in the large virtual world

; BYTErowoffset, calculated from YIndex for vertical scrolling (hardware support already exists)

 

; moved joystick? Then Move the Draw Cursor

lda #$10 ; #16 or %00001111

bit SWCHA ; like AND but we drop the result in the bit bucket behind the CPU

bne skipup

lda bity

beq skipup ; don't decrement bitx further if it is at zero

dec bity

skipup

lda #$20 ; 26 or 00011010

bit SWCHA

bne skipdown

lda bity

cmp #19

beq skipdown ; don't increment it past 19

inc bity

skipdown

bit SWCHA

BVS skipleft

lda bitx

beq skipleft ; don't decrement the x position value past zero

dec bitx

skipleft

bit SWCHA

BMI skipright

lda bitx

cmp #96

beq skipright ; virtual world is 96 pixels wide

inc bitx

skipright

; ---------------End Drawing Routine

;-----------------------------------

;Follow the Cursor with the Camera:

; Camera X Axis: -----------

lda bitx

cmp #10

bcs followXaxis ; >=10

lda #0

sta BITIndex ; (X position for camera is 0 - nothing to scroll to yet)

jmp donefollowXaxis

followXaxis

sec ; set carry for subtracts, clear it for additions

sbc #10

cmp #72

bcc dontadjustxaxis ; <72

lda #72 ; adjust x axis so code to the right of the virtual world is not shown on screen

dontadjustxaxis

sta BITIndex

donefollowXaxis

 

; Camera Y Axis: -----------

lda bity

cmp #6

bcs followYaxis ; if >=6

lda #0 ; keep Y pos for virtual world at the top for the top 6 pixels

sta YIndex ; superfluous

jmp offsetdone

 

followYaxis

lda bity

sec ;set carry for subtracts, clear for additions

sbc #6

sta YIndex

donefollowYaxis

cmp #10

bcc dontadjust ; <10

lda #10

sta YIndex ; don't show the code below the virtual world; this sets the bottom border

dontadjust

; Now turn Y Index into a Row Offset for the bitmap (it's 12 bytes across)

lda #0

ldy YIndex

offsetcalc sec ; set carry before additions

clc

adc #12

dey

beq offsetdone

jmp offsetcalc

offsetdone

sta BYTErowoffset

;-----------------------------------------------------

;----- Done Following the draw cursor with the camera

;--- Turn on the target bit in the virtual world:

lda #1 ; argument to turn pixel on always

jsr getbitstatus ; call subroutine, passing argument

;---- Done Turning on the target bit

;---------Erase the target bit under the cursor?

;--- if button is pressed, erase it:

bit INPT4

bmi skiperase

lda #0 ; argument to invert bit, since it was just set it will be turned off

jsr getbitstatus ; call subroutine, passing argument

skiperase

; note: The getbitstatus subroutine can get, set, invert or clear a bit

;-----------------

;-- Now Call the Twin Engines that emulate hardware level

;-- Horizontal Scrolling and Scaling

;----------------------------------------slide view window along bitmapped panorama currently loaded into CBS RAM:

jsr pushabstractextendedplayfield

;--------- expand and flip 30 bytes of system RAM buffer into 60 Bytes for display:

jsr AbstractPlayfieldBuilder

;-------------------------------------------

;----------End Scrolling Draw Demo

 

; ---- Resume Framework...

  • Like 5

Share this post


Link to post
Share on other sites

Thanks for this! Very interesting! :thumbsup:

 

post-2955-0-52283900-1349031965_thumb.pngpost-2955-0-35878400-1349031990_thumb.png

 

I am not an advanced bB developer yet, but I can imagine a lot of possiblities with this.

 

So if I understand correctly, the Abstract Assembly Development Kit (AADK) is combined with your asm code before you create a binary file using DASM? (i.e. you write batariBasic code with assembly routines mixed, in, compile it all into an asm file, then apply the AADK to it?)

 

I'm just confused about the order the process will be.

 

Note: I used Alt-P in Stella for the phosophor effect because otherwise the picture is an empty black screen.

Share this post


Link to post
Share on other sites

Thanks for this! Very interesting! :thumbsup:

 

post-2955-0-52283900-1349031965_thumb.pngpost-2955-0-35878400-1349031990_thumb.png

 

I am not an advanced bB developer yet, but I can imagine a lot of possiblities with this.

 

So if I understand correctly, the Abstract Assembly Development Kit (AADK) is combined with your asm code before you create a binary file using DASM? (i.e. you write batariBasic code with assembly routines mixed, in, compile it all into an asm file, then apply the AADK to it?)

 

I'm just confused about the order the process will be.

 

Note: I used Alt-P in Stella for the phosophor effect because otherwise the picture is an empty black screen.

 

You're welcome Gateway, great screenshots!

 

The scrolldraw.asm example, or any Assembly program you build with the AADK (nice acronym) just gets dropped right into the Framework file (it's all one Assembly file) right between:

 

; ---------------------------------------------------------

; ------ Your Assembly code goes here:

;----------------------------------------------------------

 

and

 

; ---- Resume Framework...

 

I'm writing the manual right now and will post it soon and the AADK source with the ScrollDraw.asm example inline.

 

btw, I think you just imagined an interesting possiblity I hadn't thought of:

 

You could probably use bB to write your game loop and game logic - and then paste the resultant assembly code it generates (just for your loops and logic, no part of the bB framework code would work) into the AADK; the AADK even offers the variables a-j which you could use directly in your program with no changes (Pretty cool idea, I will add it to the manual!). You would still have to edit your bB Assembly output to hook up the abstract calls for the phantom hardware but the api's are very straight forward/high level and editing the large virtual world bitmaps is very similar to the playfield screens in bB - all WYSIWYG, same for the musical score table.

Share this post


Link to post
Share on other sites

Thanks for the manual, etc. I will try to give you some feedback in a few days after I play around with it in my free time. 8)

Share this post


Link to post
Share on other sites
pushabstractextendedplayfield and AbstractPlayfieldBuilder are the equivalent of DrawScreen in bB

 

If these are one to one equivalents then why the different function names? Couldn't there be one, say, "aa_drawscreen" routine?

 

I'm using the newb mentality when posing these questions. Obviously. :)

Share this post


Link to post
Share on other sites

If these are one to one equivalents then why the different function names? Couldn't there be one, say, "aa_drawscreen" routine?

 

I'm using the newb mentality when posing these questions. Obviously. :)

loon,

excellent question! You could wrap them with an aa_drawscreen function that calls them both in order, agree that would be even more abstract. But I've left them as two seperate functions because one of the engines could potentially be used independantly, depending upon the kind of game you are building:

 

pushabstractextendedplayfield pans a 20x10 pixel playfield out of your 92x20 pixel virtual world and maps it to 30 of the 60 bytes of the 2600's RAM set aside for screen memory, still storing it in WYSIWYG format.

 

AbstractPlayfieldBuilder takes no arguments and simply upsizes the 30 bytes to 60 bytes, doubling the size of the pixels and also flipping them to and fro to suit the 2600's unique playfield architecture; for building games that don't scroll it is possible to load the bottom 30 bytes of reserved screen memory with a WYSIWYG 20x10 bitmap (from any 3 byte wide x 10 row table) and just call this routine to upsize and flip the bits around.

Share this post


Link to post
Share on other sites

Thanks for the manual, etc. I will try to give you some feedback in a few days after I play around with it in my free time. 8)

Fantastic Gateway! I'm looking forward to hearing about your experience :)

Share this post


Link to post
Share on other sites

Okay, so am I trying to compile your scrolldraw.asm example into a bin file (I changed the colors for the playfield as a test). It wants vcs.h and macro.h.

 

So I found a vcs.h file that seems to work and I found a macro.h file, however it just shows a blank screen in Stella.

 

Are you using an updated macro file? The macro file I have here came with DASM I believe, that was included with batariBasic.

 

If you have a newer macro.h file you are using, let me know where I can access it. Thanks. :)

 

EDIT: To clarify, I am using your scrolldraw.asm file that includes the whole framework and the only thing I changed was the color early in the framework file (I haven't changed anything yet in the scrolldraw game file itself)

Edited by Gateway

Share this post


Link to post
Share on other sites

Gateway,

no Macro's are actually used, I just included the reference in case anyone wants to use them (you could actually comment it out or remove the reference just in case there is something wrong with your macro.h file).

 

You mentioned you had to turn on phosphor before with alt-p or the screen was blank; that is interesting, I'm curious what version of Stella you are using?

 

Also, installing the open GL drivers for windows improves the look making it considerably closer to the real hardware with smoother scrolling (no pixels breaking rank).

Share this post


Link to post
Share on other sites

You should store the data transposed in RAM, so you can access each column of playfield with the same Y value.

 

I did a little analysis of your kernel:

 

 LDY $8E
LF29C: STX COLUPF
 LDA $00A0,Y ;why
 STA PF0
 INY	 ;are
 LDA $00A0,Y ;you
 STA PF1
 INY	 ;wasting
 LDA $00A0,Y ;cycles
 STA PF2
 INY ;on
 LDA $00A0,Y ;these
 STA PF0
 INY ;instructions
 LDA $00A0,Y ;you
 STA PF1
 INY ;could
 LDA $00A0,Y ;probably
 STA PF2
 INY ;fit this in one scanline
 INX
 STA WSYNC ;why?
 LDA #$00
 STA PF0
 STA PF1
 STA PF2
 DEC $8F
 BEQ LF2D9
 TYA ;this would be completely unnecessary
 SEC
 SBC #$06
 TAY
 JMP LF2DE
LF2D9: LDA #$0A
 STA $8F
 NOP ;wut
 STA WSYNC
 CPX #$C0
 BNE LF29C

 

Instead you should do something like:

   ldy #YRES-1
LoopY
   ldx #10	 ;stretch factor
LoopX
  sta WSYNC
  lda PF0DataL,Y
  sta PF0
  lda PF1DataL,Y
  sta PF1
  lda PF2DataL,Y
  sta PF2

  ;do useful things, like set COLUPF

  lda PF0DataR,Y
  sta PF0
  lda PF1DataR,Y
  sta PF1
  lda PF2DataR,Y
  sta PF2

  ;20-25-ish cycles to spare here
  dex
  bne LoopX
  dey
  bpl LoopY

Something like the above should fit in one scanline.

 

edit: OK, these forums could stand to suck less. DON'T REFORMAT MY CODE DAMNIT!

Edited by Tjoppen

Share this post


Link to post
Share on other sites

You should store the data transposed in RAM, so you can access each column of playfield with the same Y value.

Tjoppen,

yes this is an excellent idea (and I like your code comments!) but it would require either modifications of the rendering engines or more RAM to play with.

 

Via Modication of the Engines:

 

The engine that pulls a 20x10 pixel screen from the panoramic 96x20 pixel WYSIWG bitmap (which is fully malleable and stored in 240 bytes of CBS RAM) deposits it in the bottom 30 bytes of the 60 bytes of the Atari's RAM reserved as a screen buffer.

 

The upsizer engine then expands that bottom 30 bytes into the full 60 bytes creating phatter pixels (and flipping it so it is no longer WYSIWIG but ready for rendering).

 

If I remove the latter engine I could have the first one perform both functions and so render it as six tables, reading with the same Y value via the optimised code you have shown, I may do something like this so I don't have to use an entire frame for the engines but I like having both of them because the latter engine can also be used independently depending upon the game design (scrolling or non-scrolling).

 

Via more RAM:

 

Without modifying the engines I would need an additional 30 bytes of RAM and I'm already only leaving 78 for the stack and variables; here's why:

 

post-30777-0-07890000-1350659449_thumb.jpg

 

I usually sketch something on paper to explore an idea; as you can see from the illustrations, transposing the bottom half of the screen buffer (30 of 60 bytes) to six tables in 60 bytes breaks the same memory space (I haven't illustrated that the images on the right are not WYSIWYG) while contiguous transposition does not.

Share this post


Link to post
Share on other sites

Can there be a no flicker mode? I'd be willing to sacrifice resolution for a stable picture.

 

Also, the idea of using this as a new screen drawing kernel in bB has obvious appeal to me. It also seems to defeat some of Mr. SQLs intentions with this :) I feel selfish even endorsing the idea :P

Share this post


Link to post
Share on other sites

The engine that pulls a 20x10 pixel screen from the panoramic 96x20 pixel WYSIWG bitmap (which is fully malleable and stored in 240 bytes of CBS RAM) deposits it in the bottom 30 bytes of the 60 bytes of the Atari's RAM reserved as a screen buffer.

 

The upsizer engine then expands that bottom 30 bytes into the full 60 bytes creating phatter pixels (and flipping it so it is no longer WYSIWIG but ready for rendering).

Do the upscaling inside the kernel. There should be enough time to process one byte per scanline, so you compute the next block line while the current one is being drawn (6+6 byte buffer). Then you only need to shift and copy 30 bytes during VBLANK. Ah, and always keep the data flipped IMO - it just means that Y runs up instead of down.

Share this post


Link to post
Share on other sites

Can there be a no flicker mode? I'd be willing to sacrifice resolution for a stable picture.

 

Also, the idea of using this as a new screen drawing kernel in bB has obvious appeal to me. It also seems to defeat some of Mr. SQLs intentions with this :) I feel selfish even endorsing the idea :P

LOL loon! Fine to use bB to build your game logic if you prefer, IMO bB is not too different beyond semantics. I sure wish DASM supported a concatenation character so I could code horizontally in asm too (linefeed almost works but it reverts to CR+LF after I save the file).

 

A no flicker mode may happen sometime in the future, it would "DVD" the picture down to a strip to get the cycles though and I really like using the full screen :)

Edited by Mr SQL
  • Like 1

Share this post


Link to post
Share on other sites

Do the upscaling inside the kernel. There should be enough time to process one byte per scanline, so you compute the next block line while the current one is being drawn (6+6 byte buffer). Then you only need to shift and copy 30 bytes during VBLANK. Ah, and always keep the data flipped IMO - it just means that Y runs up instead of down.

Tjoppen,

upscaling in the kernel would have to entail processing 3 bytes (into 6) per scanline; don't think there is enough time. If I create a non flicker mode I would probably drop the upsizing engine and have the panning engine do that job as well - creating six tables wouldn't be an issue since then there would be no RAM buffer overwrite.

 

I am working on adding phat pixel sprites next :)

Share this post


Link to post
Share on other sites

Tjoppen,

upscaling in the kernel would have to entail processing 3 bytes (into 6) per scanline

No, it entails processing 3 -> 6 bytes in ten scanlines (or however many times the lines are duplicated)...

Share this post


Link to post
Share on other sites

No, it entails processing 3 -> 6 bytes in ten scanlines (or however many times the lines are duplicated)...

Tjoppen you're right :) There are plenty of free cycles in the physical block of scanlines for each row of phat pixels to expand three bytes into six for the next row.

Share this post


Link to post
Share on other sites

Here is the latest version of the Abstract Assembly Development Kit with source and inline demo's to illustrate using the new enhancements, and an updated manual:

 

drawsprt2.asm

drawsprt2.bin

ASDK_Manual.pdf

 

The first sprite demo example is flipping through different sprite animations, the second is more complex where as you scroll around and draw on the playfield scrolling the playfield through the large virtual world, you are also able to scroll it through the moving sprite and draw on it too.

 

The sprite objects, the playfield and the large virtual world are all abstract objects that are x and y coordinate addressable and can be used for RAD development in Assembly in a very similar manner to bB. Sprite definitions are stored in intuitive WYSIWYG format like the large virtual worlds.

 

In the back of the manual there are also some ideas on directly integrating a flicker free version of the scrolling engines into the bB DPC+ kernel at higher resolutions.

  • Like 1

Share this post


Link to post
Share on other sites

I'm entirely missing the point here, but I hope your project swings in one of two directions:

 

Something like the NESHLA

http://neshla.sourceforge.net/

 

Or a replacement kernel for bB :)

 

I'd definitely settle for a tutorial on how to migrate bB output into the user code section of ASDK.

 

I'm actually less interested in what you can pull off with support hardware like DPC+ and what more you can pull off with classic constraints.

 

Thanks again for continuing this project and the excellent documentation and comments in the code!

Share this post


Link to post
Share on other sites

loon,

NESHLA looks really cool, the ASDK is more simplified but definitely along those lines :)

 

That's a great idea! I was planning to start a tutorial on learning Assembly fast with the ASDK and will include examples of how to migrate bB Assembly output into the user code section of the ASDK as well as the similarites in how both frameworks abstract the hardware; Assembly can be nearly as RAD as bB with the abstract calls.

  • Like 1

Share this post


Link to post
Share on other sites

I would love that. I was planning to move on to another system because I just find Assembly on the 2600 too exhausting with all the cycle-counting and such, but if it can be made simpler or more abstract, I'd love to learn to use it and keep on at least for a while longer!

Share this post


Link to post
Share on other sites

I would love that. I was planning to move on to another system because I just find Assembly on the 2600 too exhausting with all the cycle-counting and such, but if it can be made simpler or more abstract, I'd love to learn to use it and keep on at least for a while longer!

 

Awesome Cybearg! Programming Assembly on the 2600 with the ASDK should feel more like that.

 

This will be fun, I'll get that thread started soon! :)

Share this post


Link to post
Share on other sites

I would love that. I was planning to move on to another system because I just find Assembly on the 2600 too exhausting with all the cycle-counting and such, but if it can be made simpler or more abstract, I'd love to learn to use it and keep on at least for a while longer!

Hang in there! I'm really impressed with your demos and your creative talent is very impressive. I hope you stick around, I'd love to see your future projects. :)

Share this post


Link to post
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.

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