mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2024-06-12 18:42:14 +00:00
working on 6502 debugging/disasm; reload apple pgm after reboot
This commit is contained in:
parent
59fd2a2945
commit
0b9194bd1c
554
presets/apple2/conway.a
Normal file
554
presets/apple2/conway.a
Normal file
|
@ -0,0 +1,554 @@
|
|||
; Conway II
|
||||
; Lee W. Fastenau
|
||||
; thelbane@gmail.com
|
||||
; Created 03/14/2017
|
||||
; from https://github.com/thelbane/ConwayII
|
||||
|
||||
processor 6502
|
||||
|
||||
ZPA0 equ $06
|
||||
ZPA1 equ $07
|
||||
ZPA2 equ $08
|
||||
ZPA3 equ $09
|
||||
|
||||
HTAB equ $24
|
||||
VTAB equ $25
|
||||
TXTROW equ $28
|
||||
|
||||
ZPB0 equ $EB
|
||||
ZPB1 equ $EC
|
||||
ZPB2 equ $ED
|
||||
ZPB3 equ $EE
|
||||
ZPB4 equ $EF
|
||||
|
||||
ZPC0 equ $FA
|
||||
ZPC1 equ $FB
|
||||
ZPC2 equ $FC
|
||||
ZPC3 equ $FD
|
||||
|
||||
STACK equ $100
|
||||
|
||||
TXTPG0 equ $0400
|
||||
TXTPG1 equ $0800
|
||||
CLICK equ $C030
|
||||
HOME equ $FC58
|
||||
RDKEY EQU $FD0C
|
||||
COUT equ $FDED
|
||||
OUTPORT equ $FE95
|
||||
|
||||
EXITDOS equ $03D0
|
||||
|
||||
mac LOG_REGION
|
||||
if {3} && >. != >{2}
|
||||
echo "(",{2},"-",.,")",{1},"*** BOUNDARY CROSSED ***"
|
||||
err
|
||||
else
|
||||
echo "(",{2},"-",.,")",{1}
|
||||
endif
|
||||
endm
|
||||
|
||||
; ------------------------------------
|
||||
; Build Options
|
||||
; ------------------------------------
|
||||
|
||||
NOISY equ 1 ; 0 = Sound off, 1 = Sound on
|
||||
CHARSET equ 1 ; 0 = Olde Skoole, 1 = Pixel, 2 = Inverse, 3 = Small O's, 4 = Enhanced
|
||||
INIT_PATTERN equ 0 ; 0 = Glider gun, 1 = "Random", 2 = Edge test
|
||||
TEST_PERF equ 0 ; 0 = Normal, 1 = Instrument for emulator cycle counting (forces Glider gun layout and sound off)
|
||||
|
||||
; ------------------------------------
|
||||
; Constants
|
||||
; ------------------------------------
|
||||
|
||||
soundEnabled equ NOISY && !TEST_PERF
|
||||
initialPattern equ INIT_PATTERN - [TEST_PERF * INIT_PATTERN]
|
||||
|
||||
textRow equ ZPA0
|
||||
textRowH equ ZPA1
|
||||
|
||||
mainData equ ZPC0
|
||||
mainDataH equ ZPC1
|
||||
|
||||
altData equ ZPC2
|
||||
altDataH equ ZPC3
|
||||
|
||||
currentPage equ ZPA2
|
||||
temp equ ZPA3
|
||||
|
||||
fieldWidth equ 40
|
||||
fieldHeight equ 24
|
||||
|
||||
dataWidth equ fieldWidth+2
|
||||
dataHeight equ fieldHeight+2
|
||||
|
||||
normalText equ %10000000 ; 'X | normalText
|
||||
inverseText equ %00111111 ; 'X & inverseText
|
||||
|
||||
if CHARSET == 0
|
||||
charOn equ '* | normalText
|
||||
charOff equ '. | normalText
|
||||
endif
|
||||
|
||||
if CHARSET == 1
|
||||
charOn equ ' & inverseText
|
||||
charOff equ ' | normalText
|
||||
endif
|
||||
|
||||
if CHARSET == 2
|
||||
charOn equ ' | normalText
|
||||
charOff equ ': & inverseText
|
||||
endif
|
||||
|
||||
if CHARSET == 3
|
||||
charOn equ 'o | normalText
|
||||
charOff equ ' | normalText
|
||||
endif
|
||||
|
||||
if CHARSET == 4
|
||||
charOn equ $ff ; | normalText
|
||||
charOff equ ' | normalText
|
||||
endif
|
||||
|
||||
n_offset equ dataWidth+1 ; Alt data topleft offset from current cell
|
||||
|
||||
y_topleft equ 0 ; Alt data pointer offsets
|
||||
y_top equ 1
|
||||
y_topright equ 2
|
||||
y_left equ dataWidth
|
||||
y_right equ dataWidth+2
|
||||
y_bottomleft equ dataWidth*2
|
||||
y_bottom equ dataWidth*2+1
|
||||
y_bottomright equ dataWidth*2+2
|
||||
|
||||
; ------------------------------------
|
||||
; Entry Point
|
||||
; ------------------------------------
|
||||
seg program
|
||||
org $803
|
||||
|
||||
start subroutine
|
||||
lda #0
|
||||
sta currentPage ; Point main data segment to first block
|
||||
jsr OUTPORT ; PR#0 (Set output to 40-column text screen)
|
||||
jsr initScreen ; Render initial cell layout
|
||||
jsr updateData ; Initialize backing data based on displayed cells
|
||||
if TEST_PERF
|
||||
jsr perfTest
|
||||
else
|
||||
jsr runLoop
|
||||
endif
|
||||
jmp EXITDOS
|
||||
|
||||
runLoop subroutine
|
||||
.loop jsr iterate ; Modify and display next generation
|
||||
jmp .loop ; Until cows come home
|
||||
|
||||
perfTest subroutine
|
||||
jsr RDKEY
|
||||
.startTimer
|
||||
lda #50
|
||||
sta .counter
|
||||
.loop jsr iterate
|
||||
dec .counter
|
||||
bne .loop
|
||||
.endTimer
|
||||
.break jsr RDKEY
|
||||
echo "Breakpoint:", .break
|
||||
rts
|
||||
.counter ds.b 1
|
||||
echo "START TIMER BREAKPOINT:",.startTimer
|
||||
echo "END TIMER BREAKPOINT:",.endTimer
|
||||
|
||||
mac INCREMENT_ADC
|
||||
ldy #y_{1} ; +2 2
|
||||
lda (altData),y ; +5/6 8
|
||||
adc #1 ; +5 13 Relies on carry being clear
|
||||
sta (altData),y ; +6 19
|
||||
endm
|
||||
|
||||
mac INCREMENT_INX
|
||||
ldy #y_{1} ; +2 2
|
||||
lda (altData),y ; +5/6 8
|
||||
tax ; +2 10
|
||||
inx ; +2 12
|
||||
txa ; +2 14
|
||||
sta (altData),y ; +6 20
|
||||
endm
|
||||
|
||||
mac INCREMENT
|
||||
INCREMENT_ADC {1}
|
||||
endm
|
||||
|
||||
iterate subroutine
|
||||
jsr toggleDataPages
|
||||
jsr clearBorders
|
||||
lda #fieldHeight-1
|
||||
sta .row
|
||||
.rowLoop jsr getTextRow
|
||||
lda #fieldWidth-1
|
||||
sta .column
|
||||
lda #0
|
||||
ldy #y_top ; clean up stale data
|
||||
sta (altData),y
|
||||
ldy #y_topright
|
||||
sta (altData),y
|
||||
.columnLoop ldy .column ; get neighbor bit flags
|
||||
lda (mainData),y ; at current data address
|
||||
tay
|
||||
lda rulesTable,y ; convert bit flags to cell state character (or 0 for do nothing)
|
||||
beq .doNothing ; rule says do nothing, so update the neighbor data
|
||||
ldy #0 ; .column
|
||||
.column equ .-1
|
||||
sta (textRow),y ; set char based on rule
|
||||
bne .setBits
|
||||
.doNothing ldy .column
|
||||
lda (textRow),y
|
||||
.setBits cmp #charOn ; A = cell character
|
||||
bne .clearTopLeft ; cell is disabled, so clear the topleft neighbor
|
||||
if soundEnabled
|
||||
bit CLICK
|
||||
endif
|
||||
ldy #y_topleft ; set top left value to one (previous value is stale)
|
||||
lda #1
|
||||
sta (altData),y
|
||||
if soundEnabled
|
||||
bit CLICK ; (Pretend I'm not here... I just click the speaker)
|
||||
endif
|
||||
clc
|
||||
INCREMENT top
|
||||
INCREMENT topright
|
||||
INCREMENT left
|
||||
INCREMENT right
|
||||
INCREMENT bottomleft
|
||||
INCREMENT bottom
|
||||
INCREMENT bottomright
|
||||
jmp .continue
|
||||
.clearTopLeft ldy #y_topleft ; cell is off, so clear top left value to remove stale data
|
||||
lda #0
|
||||
sta (altData),y
|
||||
.continue sec
|
||||
lda altData
|
||||
sbc #1
|
||||
sta altData
|
||||
lda altDataH
|
||||
sbc #0
|
||||
sta altDataH
|
||||
.nextColumn dec .column
|
||||
bmi .nextRow
|
||||
jmp .columnLoop
|
||||
.nextRow sec
|
||||
lda mainData
|
||||
sbc #dataWidth
|
||||
sta mainData
|
||||
lda mainDataH
|
||||
sbc #0
|
||||
sta mainDataH
|
||||
sec
|
||||
lda altData
|
||||
sbc #2
|
||||
sta altData
|
||||
lda altDataH
|
||||
sbc #0
|
||||
sta altDataH
|
||||
dec .row
|
||||
lda #0 ; .row
|
||||
.row equ .-1
|
||||
bmi .end
|
||||
jmp .rowLoop
|
||||
.end rts
|
||||
|
||||
updateData subroutine
|
||||
jsr toggleDataPages
|
||||
jsr clearBorders
|
||||
lda #fieldHeight-1
|
||||
sta .row
|
||||
.rowLoop jsr getTextRow
|
||||
lda #fieldWidth-1
|
||||
sta .column
|
||||
lda #0
|
||||
ldy #y_top ; clean up stale data
|
||||
sta (altData),y
|
||||
ldy #y_topright
|
||||
sta (altData),y
|
||||
.columnLoop ldy #0 ; .column
|
||||
.column equ .-1
|
||||
lda (textRow),y
|
||||
cmp #charOff
|
||||
beq .clearTopLeft
|
||||
ldy #y_topleft ; set top left value to one (previous value is stale)
|
||||
lda #1
|
||||
sta (altData),y
|
||||
clc
|
||||
INCREMENT top
|
||||
INCREMENT topright
|
||||
INCREMENT left
|
||||
INCREMENT right
|
||||
INCREMENT bottomleft
|
||||
INCREMENT bottom
|
||||
INCREMENT bottomright
|
||||
jmp .nextColumn
|
||||
.clearTopLeft ldy #y_topleft
|
||||
lda #0
|
||||
sta (altData),y
|
||||
.nextColumn sec
|
||||
lda altData
|
||||
sbc #1
|
||||
sta altData
|
||||
lda altDataH
|
||||
sbc #0
|
||||
sta altDataH
|
||||
dec .column
|
||||
bpl .columnLoop
|
||||
.nextRow sec
|
||||
lda altData
|
||||
sbc #2
|
||||
sta altData
|
||||
lda altDataH
|
||||
sbc #0
|
||||
sta altDataH
|
||||
dec .row
|
||||
lda #0 ; .row
|
||||
.row equ .-1
|
||||
bmi .end
|
||||
jmp .rowLoop
|
||||
.end rts
|
||||
|
||||
toggleDataPages subroutine ; toggles the current data page and sets up the pointers
|
||||
lda #1
|
||||
eor currentPage
|
||||
sta currentPage
|
||||
bne .page1
|
||||
.page0 lda <#datapg0_lastRow
|
||||
sta mainData
|
||||
lda >#datapg0_lastRow
|
||||
sta mainDataH
|
||||
lda <#datapg1_tln
|
||||
sta altData
|
||||
lda >#datapg1_tln
|
||||
sta altDataH
|
||||
jmp .continue
|
||||
.page1 lda <#datapg1_lastRow
|
||||
sta mainData
|
||||
lda >#datapg1_lastRow
|
||||
sta mainDataH
|
||||
lda <#datapg0_tln
|
||||
sta altData
|
||||
lda >#datapg0_tln
|
||||
sta altDataH
|
||||
.continue rts
|
||||
|
||||
clearBorders subroutine
|
||||
|
||||
mac CLEAR_BORDERS
|
||||
.bottomRow set datapg{2}_end - [dataWidth * 2] + 1
|
||||
ldx #fieldWidth
|
||||
.hloop lda #0
|
||||
sta .bottomRow,x
|
||||
dex
|
||||
bne .hloop
|
||||
.rightColumn set ZPB0
|
||||
.rightAddr set datapg{1}_end - dataWidth - 2
|
||||
lda <#.rightAddr
|
||||
sta <.rightColumn
|
||||
lda >#.rightAddr
|
||||
sta >.rightColumn
|
||||
ldy #0
|
||||
ldx #fieldHeight
|
||||
.vloop lda #0
|
||||
sta (.rightColumn),y
|
||||
lda #dataWidth
|
||||
sec
|
||||
sbc <.rightColumn
|
||||
sta <.rightColumn
|
||||
lda #0
|
||||
sbc >.rightColumn
|
||||
sta >.rightColumn
|
||||
dex
|
||||
bne .vloop
|
||||
endm
|
||||
|
||||
lda currentPage
|
||||
bne .page1
|
||||
.page0 CLEAR_BORDERS 0,1
|
||||
rts
|
||||
.page1 CLEAR_BORDERS 1,0
|
||||
rts
|
||||
|
||||
initScreen subroutine
|
||||
lda <#initData
|
||||
sta mainData
|
||||
lda >#initData
|
||||
sta mainDataH
|
||||
lda #initDataLen-1 ; get data length
|
||||
sta .dataoffset ; save it
|
||||
lda #fieldHeight-1 ; load the field height
|
||||
sta .row ; save in row counter
|
||||
.1 jsr getTextRow ; update textRow (A = row)
|
||||
lda #fieldWidth-1 ; load the field width (reset every new row)
|
||||
sta .column ; save in column counter
|
||||
ldy .dataoffset
|
||||
lda (mainData),y ; get the current data byte
|
||||
sta .byte ; save it
|
||||
lda #8 ; init the byte counter
|
||||
sta .bit ; save in bit counter
|
||||
.2 ldy .column
|
||||
lda #0
|
||||
.byte equ .-1
|
||||
lsr
|
||||
sta .byte
|
||||
bcs .turnOn
|
||||
.turnOff lda #charOff
|
||||
bne .draw
|
||||
.turnOn lda #charOn
|
||||
.draw sta (textRow),y
|
||||
dec .bit
|
||||
bne .skipbit
|
||||
lda #8 ; reset bit counter
|
||||
sta .bit ; decrease data byte reference
|
||||
sec
|
||||
dec .dataoffset
|
||||
ldy #0 ; .dataoffset
|
||||
.dataoffset equ .-1
|
||||
lda (mainData),y
|
||||
sta .byte
|
||||
.skipbit lda .column ; start to calculate init byte offset
|
||||
dec .column
|
||||
ldy #0 ; .column
|
||||
.column equ .-1
|
||||
bpl .2
|
||||
dec .row
|
||||
lda #0 ; .row
|
||||
.row equ .-1
|
||||
bpl .1
|
||||
rts
|
||||
|
||||
.bit ds.b 1
|
||||
|
||||
; inputs:
|
||||
; A = row
|
||||
; outputs:
|
||||
; A = ?, X = A << 1, textRow = address of first character in row A
|
||||
getTextRow subroutine
|
||||
asl
|
||||
tax
|
||||
lda textRowsTable,x
|
||||
sta textRow
|
||||
lda textRowsTable+1,x
|
||||
sta textRowH
|
||||
rts
|
||||
|
||||
rulesTable dc.b charOff ;0 neighbors
|
||||
dc.b charOff ;1
|
||||
dc.b 0 ;2
|
||||
dc.b charOn ;3
|
||||
dc.b charOff ;4
|
||||
dc.b charOff ;5
|
||||
dc.b charOff ;6
|
||||
dc.b charOff ;7
|
||||
dc.b charOff ;8
|
||||
|
||||
; ------------------------------------
|
||||
; Tables
|
||||
; ------------------------------------
|
||||
textRowsTable subroutine ; Lookup table for text page 0 row addresses
|
||||
.pg equ 1024
|
||||
.y set 0
|
||||
repeat 24
|
||||
dc.w .pg + (.y & %11111000) * 5 + ((.y & %00000111) << 7)
|
||||
.y set .y + 1
|
||||
repend
|
||||
LOG_REGION "textRowsTable", textRowsTable, 0
|
||||
|
||||
if initialPattern == 0 ; Glider gun
|
||||
initData dc.b %00000000,%00000000,%00000000,%00000000,%00000000
|
||||
dc.b %00000000,%00000000,%00000000,%01000000,%00000000
|
||||
dc.b %00000000,%00000000,%00000001,%01000000,%00000000
|
||||
dc.b %00000000,%00000110,%00000110,%00000000,%00011000
|
||||
dc.b %00000000,%00001000,%10000110,%00000000,%00011000
|
||||
dc.b %01100000,%00010000,%01000110,%00000000,%00000000
|
||||
dc.b %01100000,%00010001,%01100001,%01000000,%00000000
|
||||
dc.b %00000000,%00010000,%01000000,%01000000,%00000000
|
||||
dc.b %00000000,%00001000,%10000000,%00000000,%00000000
|
||||
dc.b %00000000,%00000110,%00000000,%00000000,%00000000
|
||||
dc.b %00000000,%00000000,%00000000,%00000000,%00000000
|
||||
dc.b %00000000,%00000000,%00000000,%00000000,%00000000
|
||||
dc.b %00000000,%00000000,%00000000,%00000000,%00000000
|
||||
dc.b %00000000,%00000000,%00000000,%00000000,%00000000
|
||||
dc.b %00000000,%00000000,%00000000,%00000000,%00000000
|
||||
dc.b %00000000,%00000000,%00000000,%00000000,%00000000
|
||||
dc.b %00000000,%00000000,%00000000,%00000000,%00000000
|
||||
dc.b %00000000,%00000000,%00000000,%00000000,%00000000
|
||||
dc.b %00000000,%00000000,%00000000,%00000000,%00000000
|
||||
dc.b %00000000,%00000000,%00000000,%00000000,%00000000
|
||||
dc.b %00000000,%00000000,%00000000,%00000000,%00000000
|
||||
dc.b %00000000,%00000000,%00000000,%00000000,%00000000
|
||||
dc.b %00000000,%00000000,%00000000,%00000000,%00000000
|
||||
dc.b %00000000,%00000000,%00000000,%00000000,%00000000
|
||||
endif
|
||||
if initialPattern == 1 ; "Random"
|
||||
initData dc.b %00000000,%00000000,%00000000,%00000000,%00000000
|
||||
dc.b %00000000,%00000000,%00000000,%00000000,%00000000
|
||||
dc.b %00000000,%00000000,%00000000,%00000000,%01000000
|
||||
dc.b %00000000,%00000000,%00000000,%00000000,%10100000
|
||||
dc.b %00000000,%00000000,%00000000,%00000000,%10100000
|
||||
dc.b %00000000,%00000000,%00000000,%00000000,%01000000
|
||||
dc.b %00000000,%00000000,%00000000,%00000000,%00000000
|
||||
dc.b %00000000,%00000000,%00000000,%00000000,%00000000
|
||||
dc.b %00000000,%00000000,%00000000,%00000000,%00000000
|
||||
dc.b %00000000,%00000000,%00000000,%00000000,%00000000
|
||||
dc.b %00000000,%00000000,%00000000,%00000000,%00000000
|
||||
dc.b %00000000,%00000000,%00000000,%00000000,%00000000
|
||||
dc.b %00000000,%00000000,%00000000,%00000000,%00000000
|
||||
dc.b %00000000,%00000000,%00000000,%00000000,%00000000
|
||||
dc.b %00000000,%00000000,%00000000,%00000000,%00000000
|
||||
dc.b %00000000,%00000000,%00000000,%00000000,%00000000
|
||||
dc.b %00000000,%00100000,%00000000,%00000000,%00000000
|
||||
dc.b %00000000,%10110000,%00000000,%00000000,%00000000
|
||||
dc.b %00000000,%10100000,%00000000,%00000000,%00000000
|
||||
dc.b %00000000,%10000000,%00000000,%00000000,%00000000
|
||||
dc.b %00000010,%00000000,%00000000,%00000000,%00000000
|
||||
dc.b %00001010,%00000000,%00000000,%00000000,%00000000
|
||||
dc.b %00000000,%00000000,%00000000,%00000000,%00000000
|
||||
dc.b %00000000,%00000000,%00000000,%00000000,%00000000
|
||||
endif
|
||||
if initialPattern == 2 ; Edge test
|
||||
initData dc.b %11000000,%00000000,%00011000,%00000000,%00000011
|
||||
dc.b %11000000,%00000000,%00100100,%00000000,%00000011
|
||||
dc.b %00000000,%00000000,%00011000,%00000000,%00000000
|
||||
dc.b %00000000,%00000000,%00000000,%00000000,%00000000
|
||||
dc.b %00000000,%00000000,%00000000,%00000000,%00000000
|
||||
dc.b %11100000,%00000000,%00000000,%00000000,%00000111
|
||||
dc.b %00000000,%00000000,%00000000,%00000000,%00000000
|
||||
dc.b %00000000,%00000000,%00000000,%00000000,%00000000
|
||||
dc.b %00000000,%00011100,%00000000,%00111000,%00000000
|
||||
dc.b %00000000,%00010000,%11011011,%00001000,%00000000
|
||||
dc.b %00000000,%00001000,%11011011,%00010000,%00000000
|
||||
dc.b %00000000,%00000000,%00000000,%00000000,%00000000
|
||||
dc.b %00000000,%00000000,%00000000,%00000000,%00000000
|
||||
dc.b %00000000,%00001000,%11011011,%00010000,%00000000
|
||||
dc.b %00000000,%00010000,%11011011,%00001000,%00000000
|
||||
dc.b %00000000,%00011100,%00000000,%00111000,%00000000
|
||||
dc.b %00000000,%00000000,%00000000,%00000000,%00000000
|
||||
dc.b %00000000,%00000000,%00000000,%00000000,%00000000
|
||||
dc.b %11100000,%00000000,%00000000,%00000000,%00000111
|
||||
dc.b %00000000,%00000000,%00000000,%00000000,%00000000
|
||||
dc.b %00000000,%00000000,%00000000,%00000000,%00000000
|
||||
dc.b %00000000,%00000000,%00011000,%00000000,%00000000
|
||||
dc.b %11000000,%00000000,%00100100,%00000000,%00000011
|
||||
dc.b %11000000,%00000000,%00011000,%00000000,%00000011
|
||||
endif
|
||||
initDataLen equ .-initData
|
||||
|
||||
dataSeg equ .
|
||||
seg.u conwayData ; uninitialized data segment
|
||||
org dataSeg
|
||||
|
||||
datapg0 ds.b dataWidth * dataHeight ; data page 0
|
||||
datapg0_lastRow equ . - dataWidth - fieldWidth ; first visible cell of the last row
|
||||
datapg0_tln equ . - [n_offset * 2] ; topleft neighbor of the bottomright-most visible cell
|
||||
datapg0_end equ .
|
||||
|
||||
datapg1 ds.b dataWidth * dataHeight ; data page 1
|
||||
datapg1_lastRow equ . - dataWidth - fieldWidth ; first visible cell of the last row
|
||||
datapg1_tln equ . - [n_offset * 2] ; topleft neighbor of the bottomright-most visible cell
|
||||
datapg1_end equ .
|
238
presets/apple2/siegegame.c
Normal file
238
presets/apple2/siegegame.c
Normal file
|
@ -0,0 +1,238 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <conio.h>
|
||||
#include <apple2.h>
|
||||
#include <joystick.h>
|
||||
|
||||
#define COLS 40
|
||||
#define ROWS 24
|
||||
|
||||
typedef unsigned char byte;
|
||||
typedef signed char sbyte;
|
||||
typedef unsigned short word;
|
||||
|
||||
const byte** BASL = 0x28;
|
||||
|
||||
byte getchar(byte x, byte y) {
|
||||
// JSR VTABZ
|
||||
// LDA (BASL) ($28)
|
||||
gotoxy(x,y);
|
||||
return (*BASL)[x];
|
||||
}
|
||||
|
||||
void delay(byte count) {
|
||||
while (count--) {
|
||||
word i;
|
||||
for (i=0; i<200; i++) ;
|
||||
}
|
||||
}
|
||||
|
||||
////////// GAME DATA
|
||||
|
||||
typedef struct {
|
||||
byte x;
|
||||
byte y;
|
||||
byte dir;
|
||||
word score;
|
||||
char head_attr;
|
||||
char tail_attr;
|
||||
int collided:1;
|
||||
int human:1;
|
||||
} Player;
|
||||
|
||||
Player players[2];
|
||||
|
||||
byte credits = 0;
|
||||
byte frames_per_move;
|
||||
|
||||
#define START_SPEED 12
|
||||
#define MAX_SPEED 5
|
||||
#define MAX_SCORE 7
|
||||
|
||||
///////////
|
||||
|
||||
const char BOX_CHARS[8] = { '+', '+', '+', '+',
|
||||
'-', '-', '!', '!'};
|
||||
|
||||
void draw_box(byte x, byte y, byte x2, byte y2, const char* chars) {
|
||||
byte x1 = x;
|
||||
cputcxy(x, y, chars[2]);
|
||||
cputcxy(x2, y, chars[3]);
|
||||
cputcxy(x, y2, chars[0]);
|
||||
cputcxy(x2, y2, chars[1]);
|
||||
while (++x < x2) {
|
||||
cputcxy(x, y, chars[5]);
|
||||
cputcxy(x, y2, chars[4]);
|
||||
}
|
||||
while (++y < y2) {
|
||||
cputcxy(x1, y, chars[6]);
|
||||
cputcxy(x2, y, chars[7]);
|
||||
}
|
||||
}
|
||||
|
||||
void draw_playfield() {
|
||||
draw_box(0,1,COLS-1,ROWS-1,BOX_CHARS);
|
||||
cputsxy(0,0,"Plyr1:");
|
||||
cputsxy(20,0,"Plyr2:");
|
||||
cputcxy(7,0,players[0].score+'0');
|
||||
cputcxy(27,0,players[1].score+'0');
|
||||
}
|
||||
|
||||
typedef enum { D_RIGHT, D_DOWN, D_LEFT, D_UP } dir_t;
|
||||
const char DIR_X[4] = { 1, 0, -1, 0 };
|
||||
const char DIR_Y[4] = { 0, 1, 0, -1 };
|
||||
|
||||
void init_game() {
|
||||
memset(players, 0, sizeof(players));
|
||||
players[0].head_attr = '1';
|
||||
players[1].head_attr = '2';
|
||||
players[0].tail_attr = 1;
|
||||
players[1].tail_attr = 9;
|
||||
frames_per_move = START_SPEED;
|
||||
}
|
||||
|
||||
void reset_players() {
|
||||
players[0].x = players[0].y = 5;
|
||||
players[0].dir = D_RIGHT;
|
||||
players[1].x = COLS-6;
|
||||
players[1].y = ROWS-6;
|
||||
players[1].dir = D_LEFT;
|
||||
players[0].collided = players[1].collided = 0;
|
||||
}
|
||||
|
||||
void draw_player(Player* p) {
|
||||
cputcxy(p->x, p->y, p->head_attr);
|
||||
}
|
||||
|
||||
void move_player(Player* p) {
|
||||
cputcxy(p->x, p->y, p->tail_attr);
|
||||
p->x += DIR_X[p->dir];
|
||||
p->y += DIR_Y[p->dir];
|
||||
if (getchar(p->x, p->y) & 0x7f != ' ')
|
||||
p->collided = 1;
|
||||
draw_player(p);
|
||||
}
|
||||
|
||||
void human_control(Player* p) {
|
||||
byte dir = 0xff;
|
||||
byte joy;
|
||||
if (!p->human) return;
|
||||
joy = joy_read (JOY_1);
|
||||
if (joy & JOY_LEFT_MASK) dir = D_LEFT;
|
||||
if (joy & JOY_RIGHT_MASK) dir = D_RIGHT;
|
||||
if (joy & JOY_UP_MASK) dir = D_UP;
|
||||
if (joy & JOY_DOWN_MASK) dir = D_DOWN;
|
||||
// don't let the player reverse
|
||||
if (dir < 0x80 && dir != (p->dir ^ 2)) {
|
||||
p->dir = dir;
|
||||
}
|
||||
}
|
||||
|
||||
byte ai_try_dir(Player* p, dir_t dir, byte shift) {
|
||||
byte x,y;
|
||||
dir &= 3;
|
||||
x = p->x + (DIR_X[dir] << shift);
|
||||
y = p->y + (DIR_Y[dir] << shift);
|
||||
if (x < COLS && y < ROWS && getchar(x, y) == ' ') {
|
||||
p->dir = dir;
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ai_control(Player* p) {
|
||||
dir_t dir;
|
||||
if (p->human) return;
|
||||
dir = p->dir;
|
||||
if (!ai_try_dir(p, dir, 0)) {
|
||||
ai_try_dir(p, dir+1, 0);
|
||||
ai_try_dir(p, dir-1, 0);
|
||||
} else {
|
||||
ai_try_dir(p, dir-1, 0) && ai_try_dir(p, dir-1, 1+(rand() & 3));
|
||||
ai_try_dir(p, dir+1, 0) && ai_try_dir(p, dir+1, 1+(rand() & 3));
|
||||
ai_try_dir(p, dir, rand() & 3);
|
||||
}
|
||||
}
|
||||
|
||||
byte gameover;
|
||||
|
||||
void flash_colliders() {
|
||||
byte i;
|
||||
// flash players that collided
|
||||
for (i=0; i<56; i++) {
|
||||
//cv_set_frequency(CV_SOUNDCHANNEL_0, 1000+i*8);
|
||||
//cv_set_attenuation(CV_SOUNDCHANNEL_0, i/2);
|
||||
if (players[0].collided) players[0].head_attr ^= 0x80;
|
||||
if (players[1].collided) players[1].head_attr ^= 0x80;
|
||||
delay(2);
|
||||
draw_player(&players[0]);
|
||||
draw_player(&players[1]);
|
||||
}
|
||||
//cv_set_attenuation(CV_SOUNDCHANNEL_0, 28);
|
||||
}
|
||||
|
||||
void make_move() {
|
||||
byte i;
|
||||
for (i=0; i<frames_per_move; i++) {
|
||||
human_control(&players[0]);
|
||||
delay(1);
|
||||
}
|
||||
ai_control(&players[0]);
|
||||
ai_control(&players[1]);
|
||||
// if players collide, 2nd player gets the point
|
||||
move_player(&players[1]);
|
||||
move_player(&players[0]);
|
||||
}
|
||||
|
||||
void declare_winner(byte winner) {
|
||||
byte i;
|
||||
clrscr();
|
||||
for (i=0; i<ROWS/2-3; i++) {
|
||||
draw_box(i,i,COLS-1-i,ROWS-1-i,BOX_CHARS);
|
||||
delay(1);
|
||||
}
|
||||
cputsxy(12,10,"WINNER:");
|
||||
cputsxy(12,13,"PLAYER ");
|
||||
cputcxy(12+7, 13, '1'+winner);
|
||||
delay(75);
|
||||
gameover = 1;
|
||||
}
|
||||
|
||||
void play_round() {
|
||||
reset_players();
|
||||
clrscr();
|
||||
//setup_attrib_table();
|
||||
draw_playfield();
|
||||
while (1) {
|
||||
make_move();
|
||||
if (players[0].collided || players[1].collided) break;
|
||||
}
|
||||
flash_colliders();
|
||||
// add scores to players that didn't collide
|
||||
if (players[0].collided) players[1].score++;
|
||||
if (players[1].collided) players[0].score++;
|
||||
// increase speed
|
||||
if (frames_per_move > MAX_SPEED) frames_per_move--;
|
||||
// game over?
|
||||
if (players[0].score != players[1].score) {
|
||||
if (players[0].score >= MAX_SCORE)
|
||||
declare_winner(0);
|
||||
else if (players[1].score >= MAX_SCORE)
|
||||
declare_winner(1);
|
||||
}
|
||||
}
|
||||
|
||||
void play_game() {
|
||||
gameover = 0;
|
||||
init_game();
|
||||
players[0].human = 1;
|
||||
while (!gameover) {
|
||||
play_round();
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
joy_install (joy_static_stddrv);
|
||||
play_game();
|
||||
}
|
|
@ -2,6 +2,10 @@
|
|||
|
||||
var APPLE2_PRESETS = [
|
||||
{id:'sieve.c', name:'Sieve'},
|
||||
{id:'mandel.c', name:'Mandelbrot'},
|
||||
{id:'tgidemo.c', name:'TGI Graphics Demo'},
|
||||
{id:'siegegame.c', name:'Siege Game'},
|
||||
{id:'conway.a', name:"Conway's Game of Life (asm)"},
|
||||
// {id:'tb_6502.s', name:'Tom Bombem (assembler game)'},
|
||||
];
|
||||
|
||||
|
@ -21,10 +25,10 @@ var Apple2Platform = function(mainElement) {
|
|||
var kbdlatch = 0;
|
||||
var soundstate = 0;
|
||||
var pgmbin;
|
||||
//var VM_BASE = 0x6000; // where to JMP after pr#6
|
||||
//var PGM_BASE = 0x6000; // where to load ROM
|
||||
var VM_BASE = 0x803; // where to JMP after pr#6
|
||||
var PGM_BASE = 0x7ff; // where to load ROM
|
||||
var LOAD_BASE = VM_BASE; //0x7c9; // where to load ROM
|
||||
var PGM_BASE = VM_BASE; //0x800; // where to load ROM
|
||||
var HDR_SIZE = PGM_BASE - LOAD_BASE;
|
||||
// language card switches
|
||||
var auxRAMselected = false;
|
||||
var auxRAMbank = 1;
|
||||
|
@ -110,7 +114,12 @@ var Apple2Platform = function(mainElement) {
|
|||
} else {
|
||||
switch (address) {
|
||||
// JMP VM_BASE
|
||||
case 0xc600: return 0x4c;
|
||||
case 0xc600: {
|
||||
// load program into RAM
|
||||
if (pgmbin)
|
||||
ram.mem.set(pgmbin.slice(HDR_SIZE), PGM_BASE);
|
||||
return 0x4c;
|
||||
}
|
||||
case 0xc601: return VM_BASE&0xff;
|
||||
case 0xc602: return (VM_BASE>>8)&0xff;
|
||||
default: return noise();
|
||||
|
@ -264,8 +273,6 @@ var Apple2Platform = function(mainElement) {
|
|||
}
|
||||
this.reset = function() {
|
||||
cpu.reset();
|
||||
if (pgmbin)
|
||||
ram.mem.set(pgmbin, PGM_BASE);
|
||||
}
|
||||
this.readAddress = function(addr) {
|
||||
return bus.read(addr);
|
||||
|
|
|
@ -18,8 +18,8 @@ var Atari8MAMEPlatform = function(mainElement) {
|
|||
biosfile:'a5200/5200.rom',
|
||||
//cfgfile:'atari5200.cfg',
|
||||
driver:'a5200',
|
||||
width:280*2,
|
||||
height:216*2,
|
||||
width:336*2,
|
||||
height:225*2,
|
||||
romfn:'/emulator/cart.rom',
|
||||
romsize:0x4000,
|
||||
preInit:function(_self) {
|
||||
|
|
|
@ -687,6 +687,7 @@ function getDisasmViewPC() {
|
|||
function getCurrentPC() {
|
||||
var line = getCurrentLine();
|
||||
while (line >= 0) {
|
||||
// TODO: what if in disassembler?
|
||||
var pc = sourcefile.line2offset[line];
|
||||
if (pc >= 0) return pc;
|
||||
line--;
|
||||
|
@ -788,6 +789,7 @@ function updateDisassembly() {
|
|||
if (div.is(':visible')) {
|
||||
var state = lastDebugState || platform.saveState();
|
||||
var pc = state.c ? state.c.PC : 0;
|
||||
// do we have an assembly listing?
|
||||
if (assemblyfile && assemblyfile.text) {
|
||||
var asmtext = assemblyfile.text;
|
||||
if (platform_id == 'base_z80') { // TODO
|
||||
|
@ -799,12 +801,15 @@ function updateDisassembly() {
|
|||
if (findPC) {
|
||||
var lineno = assemblyfile.findLineForOffset(findPC);
|
||||
if (lineno) {
|
||||
// set cursor while debugging
|
||||
if (platform.getDebugCallback()) disasmview.setCursor(lineno-1, 0);
|
||||
jumpToLine(disasmview, lineno-1);
|
||||
return; // success, don't disassemble in next step
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (platform.disassemble) {
|
||||
// fall through to platform disassembler?
|
||||
if (platform.disassemble) {
|
||||
var curline = 0;
|
||||
var selline = 0;
|
||||
// TODO: not perfect disassembler
|
||||
|
@ -821,6 +826,7 @@ function updateDisassembly() {
|
|||
var srcline = editor.getLine(srclinenum-1);
|
||||
if (srcline && srcline.trim().length) {
|
||||
s += "; " + srclinenum + ":\t" + srcline + "\n";
|
||||
curline++;
|
||||
}
|
||||
}
|
||||
var bytes = "";
|
||||
|
|
|
@ -85,17 +85,16 @@ var PLATFORM_PARAMS = {
|
|||
define: '__APPLE2__',
|
||||
cfgfile: 'apple2.cfg',
|
||||
libargs: ['apple2.lib'],
|
||||
code_offset: 0x803, // TODO
|
||||
code_offset: 0x803, // TODO: parse segment list
|
||||
},
|
||||
'apple2-e': {
|
||||
define: '__APPLE2__',
|
||||
cfgfile: 'apple2.cfg',
|
||||
libargs: ['apple2.lib'],
|
||||
code_offset: 0x803, // TODO
|
||||
},
|
||||
'atari8-5200': {
|
||||
define: '__APPLE2__',
|
||||
cfgfile: 'apple2-hgr.cfg',
|
||||
define: '__ATARI5200__',
|
||||
cfgfile: 'atari5200.cfg',
|
||||
libargs: ['atari5200.lib'],
|
||||
//code_offset: 0x803, // TODO
|
||||
},
|
||||
|
@ -605,7 +604,9 @@ function assemblelinkCA65(code, platform) {
|
|||
LD65.callMain(['--cfg-path', '/share/cfg',
|
||||
'--lib-path', '/share/lib',
|
||||
'--lib-path', '/share/target/apple2/drv',
|
||||
'-D', '__EXEHDR__=0',
|
||||
'-C', params.cfgfile,
|
||||
'-Ln', 'main.vice',
|
||||
//'--dbgfile', 'main.dbg',
|
||||
'-o', 'main', '-m', 'main.map', 'main.o'].concat(libargs));
|
||||
endtime("link");
|
||||
|
@ -615,6 +616,7 @@ function assemblelinkCA65(code, platform) {
|
|||
try {
|
||||
var aout = FS.readFile("main", {encoding:'binary'});
|
||||
var mapout = FS.readFile("main.map", {encoding:'utf8'});
|
||||
var viceout = FS.readFile("main.vice", {encoding:'utf8'});
|
||||
} catch (e) {
|
||||
return {errors:errors};
|
||||
}
|
||||
|
@ -622,12 +624,21 @@ function assemblelinkCA65(code, platform) {
|
|||
//console.log(lstout);
|
||||
//console.log(mapout);
|
||||
var srclines = parseSourceLines(lstout, /[.]dbg\s+line, "main[.]c", (\d+)/i, /^\s*([0-9A-F]+)r/i, params.code_offset);
|
||||
// parse symbol map (TODO: omit segments, constants)
|
||||
var symbolmap = {};
|
||||
for (var s of viceout.split("\n")) {
|
||||
var toks = s.split(" ");
|
||||
if (toks[0] == 'al') {
|
||||
symbolmap[toks[2].substr(1)] = parseInt(toks[1], 16);
|
||||
}
|
||||
}
|
||||
return {
|
||||
output:aout.slice(0),
|
||||
lines:listing.lines,
|
||||
srclines:srclines,
|
||||
errors:listing.errors,
|
||||
intermediate:{listing:lstout+"\n"+mapout, map:mapout}, // TODO
|
||||
symbolmap:symbolmap,
|
||||
intermediate:{listing:lstout+"\n"+mapout+"\n"+viceout, map:mapout, symbols:viceout}, // TODO
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -671,8 +682,8 @@ function compileCC65(code, platform) {
|
|||
var asmout = FS.readFile("main.s", {encoding:'utf8'});
|
||||
//console.log(asmout);
|
||||
var result = assemblelinkCA65(asmout, platform, errors);
|
||||
result.asmlines = result.lines;
|
||||
result.lines = result.srclines;
|
||||
//result.asmlines = result.lines;
|
||||
//result.lines = result.srclines;
|
||||
result.srclines = null;
|
||||
return result;
|
||||
} catch(e) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user