RetroChallenge Winter Warm-up 2015

final posting

January 31, 2015

I've written a lot of 6502 assembly code for this challenge. Without testing this on a real Apple II, I don't know if the timing is quite right. KEGSMAC and Virtual ][ seem to be different by about 65 cycles (one line.)

*1195:23 KEGSMAC
*1195:30 Virtual ][
*30-23   difference between delay loop parameters
=0D      13 * 5 cycles = 65 cycles

]

]FP

]

]POKE4864,0:POKE104,19:POKE103,0:NEW

]HIMEM:8192

]BLOAD LOOKUP

]BLOAD VBL

]BLOAD FRAME

]BLOAD FILL

]CALL4643

]NOMONC,I,O

]RUN ALT

Here are the 6502 assembly routines that I've ended up with at the end of this challenge:

vbl.s : REM ORG $1100, 153 bytes and expands to 250 bytes with self modifying code, called by FRAME, no parameters.

creates a 256 byte table of byte counts at $1000.$10FF

This is the Vertical BLank detection routine. It non-destructively finds/waits for the start of the vertical blank. It uses HGR: high-resolution (280x192) page 1. It finds a suitable byte to wait for on the floating bus. If the byte is in use on HGR, it temporarily modifies the bytes, waits on the floating bus, and then restores the bytes back to HGR. After reading some of chapters in Sather's book, I found out that my original VBL routine won't work because many addresses on the screen are scanned more than once. I settled on putting the byte to wait on in address $27D0 which is only scanned once. The value $00 seems to show up on the floating bus (in KEGSMAC) even if there are no zeroes in the screen memory. There is a delay at the end of the detection routine, so that the time is at the start of the vertical blank, just past the 192nd line on the screen.

frame.s CALL 3072 : REM ORG $0C00, 239 bytes, needs lookup tables set up, calls VBL, parameters:

IPTRLO	EQU $06
IPTRHI	EQU $07
ICNTLO	EQU $08
ICNTHI	EQU $09

The address that $06.07 points to is the first frame of the animation.

Each frame in the list uses a one byte pointer.
    $00 points to $6000
    $01 points to $6040
    $02 points to $6080, and so on...
    You can repeat frames in the list.
    This is useful for slowing down the animation, or reusing frames.
    These are just pointers, so they can be in any order.
    It animates through ICNT + 1 frames, and repeats until a key is pressed.

Each byte in the 64 byte table contains three values.
    The values from 0 to 5 indicating the graphics mode
    to use for each line on the screen:  3 * 64 is 192 lines.

creates a 3 byte index lookup: $DD8.$DD9

This routine allows the setting of graphics modes line by line, and can also animate through various frames at 60 frames per second. A single frame can be used to mixed various graphics modes and add more color. The frame animation was difficult to test using emulators. There is a delay during the VBL period. All of the code in this routine is time critical. I even used "LDA: $0007" to tell the Merlin32 assembler to output a 4 cycle absolute addressing instruction when accessing the zero page because the regular 3 cycle "LDA $07" zero page addressing would have come up one cycle short.

lookup.s CALL 4643 : REM ORG $1223, 45 bytes, no parameters

creates three 216 byte (6^3) lookup tables: $D00.$DD7 $E00.$ED7 $F00.$FD7

This builds lookup tables for the line by line modes. Three line modes are stored in one byte of memory. I needed to compact the frames, and managed to reduce the memory footprint using these lookup tables.

fill.s CALL 4608 : REM ORG $1200, 35 bytes, parameters:

STARTHI EQU $EC
ENDHI	EQU $ED
COLOR1	EQU $EE
;COLOR2	EQU $EF

This is a utility routine for filling patterns of bytes in memory. It's useful for creating the frames, and filling screens with patterns.

And, this is a demo written in BASIC:

ALT

last
Alternating GR and GR2 with 8 pixels of TEXT in the middle.
 6  POKE 6,7 : REM lo-order address of frame table
 7  POKE 7,0 : REM hi-order address of frame table
 8  POKE 8,0 : REM lo-order number of frames minus one
 9  POKE 9,0 : REM hi-order number of frames minus one
 20 B0 = 3:B1 = 2:B2 = 3 : REM three lines of alternating GR and GR2
 30  GOSUB 600:C1 = B
 40 B0 = 2:B1 = 3:B2 = 2 : REM three lines of alternating GR2 and GR
 50  GOSUB 600:C2 = B
 60  POKE 236,96: POKE 237,97 : REM $6000 (24576) frame start, $40 (64) bytes in size
 70  GOSUB 500
 80 V = 12
 90 B0 = 2:B1 = 4:B2 = 4 : REM bottom 2 lines text 
 91  GOSUB 600
 92  POKE 24576 + 29,B
 93 B0 = 4: GOSUB 600 : REM 6 more lines of text
 94  POKE 24576 + 30,B
 96  POKE 24576 + 31,B
 100  POKE 236,4: POKE 237,8 : REM fill GR with a dark colored pattern
 101 C1 = 1 + 2 * 16
 102 C2 = 4 + 8 * 16
 120  GOSUB 500
 130  POKE 236,8: POKE 237,12 : REM fill GR2 with a light colored pattern
 131 C1 = 11 + 7 * 16
 132 C2 = 14 + 13 * 16
 150  GOSUB 500
 200  VTAB V: HTAB 1
 210  PRINT " 2015 WINTER ";
 211  PRINT "WARMUP - VERT";
 212  PRINT "ICAL BLANKING ";
 400  CALL 3072: END  : REM call the (vbl, and) frame routine
 500  POKE 238,C1: POKE 239,C2
 510  CALL 4608: RETURN  : REM call the fill routine
 600 B = B0 * 6 ^ 0
 610 B = B1 * 6 ^ 1 + B
 620 B = B2 * 6 ^ 2 + B: RETURN 

Demo Version

January 29, 2015

Sather

I rewrote my VBL detection routine. The old one doesn't work very well. Reading a bit of Understanding the Apple II by Jim Sather helped illuminate a few problems.


glitch

January 26, 2015

I am not sure that the VBL detection is working. Between emulators, and bugs, and cycle counting there could be problems lurking. The demo disk from the previous post will walk a bit over DOS 3.3 and cause problems. I compacted the mapping of horizontal lines so that not so much memory is consumed. Despite all of this, I feel like I've progressed a bit.

glitch

An effective resolution of 40+ x 192 x 16 colors on an Apple II.

Time to read some Sather ...


linemode demo

January 25, 2015

My retro software challenge is no longer to rewrite the Forest Fire 6502 assembly language code. I did look into to optimizing Forest Fire, but it started to look like an optimization project. I am having way too much fun fiddling around with the Apple II video.

I've created a demo. I really don't know if this works. I would need to test it on a real Apple II. I am using KEGS, but I don't think it quite emulates what I am doing. I tried the eval version of Virtual ][, and it does better. I set the frame rate to 60.

demo
a snapshot of an evaluation copy of Virtual ][ running my linemode demo. (frame rate = 60)

So, what am I doing? I've created a machine language program to allow switching of graphics modes line by line. I think the Apple II GS has something like this built-in. Anyways, I have a map of 193 lines which can have value from 0 to 5 for the possible video modes on the early model Apple II.

  • 0 = HGR
  • 1 = HGR2
  • 2 = GR
  • 3 = GR2 gr2
  • 4 = TEXT
  • 5 = TEXT2 text2

There are 192 lines on the screen, but I added one line beyond the end so that a video mode can be set in the vertical blank. With this extra line, it should be possible to set the color kill.

I added one more feature to this. There are 60 frames of these 193 line by line video mode settings. So, a limited amount of animation is possible looping every second. The map starts at $6000 for the first frame. $6000.60C1 bytes contain video mode numbers. 60 pages of memory from $60xx to $9Bxx map each frame.

My biggest problem is I don't know if this really works or not.

ww2015-01-25jan.dsk (143,360 bytes)
ww2015-01-25jan.dsk.zip (14,212 bytes)

demo
a snapshot of KEGS running my linemode demo.

side note:

Virtual ][ adds attributes to the .dsk (disk) file. KEGS reports that the disk is in the wrong format, even thought it is not. To remove the attributes, type the following in the Terminal:
# xattr ww2015-01-25jan.dsk
# xattr -d com.apple.FinderInfo ww2015-01-25jan.dsk
# xattr -d com.apple.ResourceFork ww2015-01-25jan.dsk
# xattr ww2015-01-25jan.dsk

vapor

January 16, 2015

Ever heard of vapor-lock? Me neither.

Anyways, I am starting to count cycles. Sixty-five is the magic number for this trick. This program paints the lo-res screen yellow, paints the hi-res screen black, and then mixes them. The screen alternates every line between yellow and black -- every 65 cycles! Look out Atari, the Apple II can do some new tricks.

vapor

I also threw some code in there so that pressing a key will exit from the vapor assembly code. This is handy because I can never remember what the reset key is on a all these different emulators. It's ctrl-F12 on KEGSMAC.

10 FOR I = 768 TO 796
20     READ B : POKE I, B
30 NEXT
40 GR : COLOR = 13
50 FOR I = 0 TO 39
60     VLIN 0, 47 AT I
70 NEXT
80 HGR : A =  PEEK (49234)
90 A =  PEEK (230) * 256 + 8183
100 POKE A,128: CALL 768
110 TEXT : POKE 49168, 0
120 DATA173,80,192,16,251,44
130 DATA86,192,162,12,202,208
140 DATA253,44,87,192,162,10
150 DATA202,208,253,165,0,173
160 DATA0,192,16,233,96
The following is the assembly listing with cycle counting included in the comments. Exact timing for the loop is required to make this work.

$ cat vapor.s
	ORG $0300
LOOP
	LDA $C050  ; READ BUS
	BPL LOOP   ; BRANCH IF POSITIVE
VAPOR
	BIT $C056  ;  4  (4) LO-RES
	LDX #$0C   ; 61 (65) 1 + 12 * (2 + 3)
LOOP12
	DEX        ;  2
	BNE LOOP12 ;  3
	BIT $C057  ;  4  (4) HI-RES
	LDX #$0A   ; 51 (55) 1 + 10 * (2 + 3)
LOOP10
	DEX        ;  2
	BNE LOOP10 ;  3
	LDA $00    ;  3 (58)
	LDA $C000  ;  4 (62)
	BPL VAPOR  ;  3 (65)
	RTS
$ Merlin32 '' vapor.s > /dev/null
$ hexdump -v -e '":" 16/1 "%X " "\n"' vapor.s
:AD 50 C0 10 FB 2C 56 C0 A2 C CA D0 FD 2C 57 C0
:A2 A CA D0 FD A5 0 AD 0 C0 10 E9 60   

64 bit increment

January 14, 2015

I've been messing around with Merlin 32, a 65816 cross-Assembler with OMF! OMF is Object Module Format in case you didn't know. I re-compiled the Merlin 32 source for Linux (Intel 32 bits?) running on a 64 bit AMD, Linux (Arm), and Mac OS X (PowerPC).

I also note a case of someone being very sensitive about case insensitive file systems. In response to Mr. Torvalds, instead of keeping my documents folder to a nice short folder name like doc, I renamed doc to " documents / My Documents" just because I can. I usually try to keep my filenames lower case to play nice, but the "i" in 64bitincrement just cries out to be capitalized. And a feature of Merlin32 is that the program doesn't care, it will find that file no matter how many CAPS you stick in there.

Who says you can't teach an old computer to do 64 bit tricks?
$ cat 64bitIncrement.s
    CLC
    LDA $00
    ADC #$01
    STA $00
    LDA $01
    ADC #$00
    STA $01
    LDA $02
    ADC #$00
    STA $02
    LDA $03
    ADC #$00
    STA $03
    LDA $04
    ADC #$00
    STA $04
    LDA $05
    ADC #$00
    STA $05
    LDA $06
    ADC #$00
    STA $06
    LDA $07
    ADC #$00
    STA $07
    LDA $08
    ADC #$00
    STA $08
    RTS
$ Merlin32 Merlin32_v1.0/Library 64bitIncrement.s
Merlin32 v 1.0, (c) Brutal Deluxe 2011-2015
  + Assemble project files...
    o Loading Sources files...
        - 64bitIncrement.s
    o Loading Macro files...
    o Check for duplicated Macros...
    o Decoding lines types...
    o Process local/variable Labels...
    o Process Asterisk lines...
    o Build External table...
    o Build Equivalence table...
    o Build Variable table...
    o Process Equivalence values...
    o Replace Lup with code...
    o Replace Macros with Code...
    o Process MX directives...
    o Process Conditional directives...
    o Build Label table...
    o Check for duplicated Labels...
    o Check for unknown Source lines...
    o Check for Dum lines...
    o Compute Operand Code size...
    o Compute Operand Data size...
    o Compute Line address...
    o Build Code Line...
    o Compact Code for Direct Page Lines...
    o Check for Err lines...
    o Build Data Line...
    o Build Object Code...
  + Link project files...
    o Build Binary output file...
     => Creating Object file '64bitIncrement'
$ hexdump -v -e '":" 16/1 "%X " "\n"' 64bitIncrement
:18 A5 0 69 1 85 0 A5 1 69 0 85 1 A5 2 69
:0 85 2 A5 3 69 0 85 3 A5 4 69 0 85 4 A5
:5 69 0 85 5 A5 6 69 0 85 6 A5 7 69 0 85
:7 A5 8 69 0 85 8 60 

Merlin 32 makefile and builds for Intel 32 bit (Linux), PowerPC (Mac OS X) and Raspberry Pi (Linux).

jurisdiction

January 3, 2015

This is the part of the retrochallenge where I get distracted. Disassemble the code for the Mouse Card on the Apple II. Build a favicon.ico editor. Create a 6502 disassembler. No, no, and No. Here is what worked for me to be able to telnet to the Apple II emulator. This will facilitate sending large programs to the emulator.

Under APPLESOFT, you can PR#1 and IN#1.  This gets input from the socket also.  You can type in the telnet window, it will be sent on to the emulated IIgs.  You may want to go to the F4 Config Panel and set "mask off high bit" for serial port accesses to make PR#1 work a little nicer.

Emulator (Apple II)

configuration

]IN#1
]PR#1

Terminal (Mac OS X)

$ telnet
telnet> open localhost 6501
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.

]^]
telnet>
mode character
http://kegs.sourceforge.net/README.kegs.txt

control mechanism

January 1, 2015

Happy New Year!

Vertical BLanking (VBL)

I've created a document and simple program describing a means for smooth animation on all models of Apple II, assuming of course that accurate cycle counting is done.

 10  POKE 768,173: POKE 769,80
 20  POKE 770,192: POKE 771,16
 30  POKE 772,251: POKE 773,133
 40  POKE 774,235: POKE 775,96
 50  HGR :A =  PEEK (49234)
 60 A =  PEEK (230) * 256 + 8183
 70  POKE A,128: CALL 768: TEXT
 80  PRINT  PEEK (235);

Emulation

So far, I've settled on using GSport for Apple II emulation. It is an Apple II GS emulator based on Kent Dickey's KEGS. KEGS supports cycle accurate timing and reading of video data from the bus.

  • Support "floating bus" where reading certain $C0xx locations returns the current video data. This allows Bob Bishop's split-screen demos to run and enables Drol's between-level animations to work fully.
  • Fixed refresh rate to 59.923Hz from 60Hz so that exactly 17030 1MHz cycles pass in one screen refresh period.
http://kegs.sourceforge.net/CHANGES.txt
see also: 35 Colors On NTSC (vdgtricks.blogspot.ca) by John W. Linville Retro Tinker

timing is everything

December 30, 2014

I am jumping in with some documentation.

video
source: http://rich12345.tripod.com/aiivideo/vbl.html
I'll be keeping my eye on the 17030 number. 17030 cycles! Yes, I'm going to be counting cycles. The target platform is the Apple II. I will not be using the VBL from the Apple IIe. There is a way to get the VBL on the original Apple II and Apple II+. Not many emulators support this and fewer emulate this to the full extent.

tooling

December 29, 2014 8:42 PM

I'm setting things up in preparation for the challenge.

calculator
### bin
mkdir -p ~/Applications/bin
#echo 'export PATH=~/Applications/bin:$PATH' > ~/.profile
export PATH=~/Applications/bin:$PATH

### asm6
mkdir -p ~/Documents/src/asm6
cd ~/Documents/src/asm6
#curl -O http://hoop-la.ca/apple2/2015/winterwarmup/asm6.zip
curl -O http://home.comcast.net/~olimar/NES/asm6.zip
unzip asm6.zip
make asm6
mv asm6 ~/Applications/bin/

### forestfire
mkdir -p ~/Documents/src/forestfire
cd ~/Documents/src/forestfire
curl -O http://hoop-la.ca/apple2/2012/forestfire/forestfire.s
asm6 forestfire.s

brief synopsis of project

December 29, 2014 [first post]

This is my announcement of intention to enter RC2015/01.

My retro software challenge is to rewrite the Forest Fire 6502 assembly language code.

  • Optimization of 6502 code for speed
  • Make the animation "flicker free" for the Apple II

Tools

forest fire

mmphosis

        http://hoop-la.ca/apple2/2015/winterwarmup/

http://www.wickensonline.co.uk/retrochallenge-2012sc/
        retrochallenge (twitter.com)
        The RC2015/01 Entrants List

previous RetroChallenges

Palm IIIxe hacking winter 2012
Apple-1/Apple II BASIC winter 2011
1960 lisp in Applesoft BASIC summer 2010
Apple-1 hello world winter 2008
Apple II hacker emblem winter 2007

"Seeing a web counter on a modern web page is one example of retrocomputing on the Internet."3511 visitors