ASM6502
; Paint program for Alterchan
; Рисовалка для Альтерчана
;
; Keyboard controls: / Управление по борьбе с клавиатурой:
; Numpad 1 — Numpad 9 — move cursor/brush (numlock ON!)
; / перемещение кисти/курсора (включить numlock);
; Numpad 5 or 5 — paint pixel with current color/return to background
; / рисовать пиксель текущим цветом/вернуть к цвету фона;
; Numpad + — continuous painting mode ON/OFF
; / включить/выключить режим непрерывного рисования;
; Numpad 0 or SPACE - palette (space may stop the sim or do something if some element in browser is focused)
; / палитра (пробел может остановить эмуль или сделать что-то, если что-нибудь выделено в браузере);
; f/F - fill everything flagged as background with current color
; / залить текущим цветом всё, помеченное как фон
; / (если вместо этого открывается палитра, включить английскую раскладку).

*=0
cursor_low: dcb $ef ; $0,$1 - cursor coords
cursor_high: dcb $03 ; = $03ef for screen center
color: dcb $01 ; $2
color_num: dcb $0f ; $3 - palette color index
border_clr: dcb $b ; $4 - palette border color
palette: ; $5 - and palette array[15] itself

*=$80
mode: dcb $0 ; $80 - continuous brush mode, $0/$ff - OFF/ON
bgcolor: dcb $0 ; $81 - current BG color

*=$fe
rand:
*=$ff
keypress:

*=$200
screen:

*=$600
start: ; ---------- CODE BEGINS HERE ----------

; Init
lda #$ef ;<screen
sta $0 ;set cursor position
lda #$03 ;>screen
sta $1

;Copy frame_clr+palette to ZP for quicker access
ldx #16
copy_loop:
lda palette_slow,x
sta $4,x
dex
bpl copy_loop


; Main loop
main:

; Blink cursor and wait for input
ldy #0
lda ($0),y ;get
pha
lda $2 ;current color
ora #$10
sta ($0),y ;put pixel at cursor address

pla
ldx $80 ;mode
bne skip_blink ;skips returning to image color if mode!=0
sta ($0),y ;return image color
skip_blink:

lda $ff ;keypress
beq main
ldx #0
stx $ff ;keypress

; Act on input (key code in A)
cmp #$35 ; NUM5
bne skip_
lda $2 ;get color
ora #$10 ;bit4 ON
cmp ($0),y ;compare to pixel at cursor
bne paint
lda $81 ;get bgcolor
sta ($0),y ;put pixel at cursor address
jmp main
paint: sta ($0),y ;put pixel at cursor address
jmp main
skip_: cmp #$34 ; NUM4
bne skip0 ;can be replaced by "dcb $d0, $03"
jsr input_move_left
jmp main
skip0: cmp #$36 ; NUM6
bne skip1
jsr input_move_right
jmp main
skip1: cmp #$38 ; NUM8
bne skip2
jsr input_move_up
jmp main
skip2: cmp #$32 ; NUM2
bne skip3
jsr input_move_down
jmp main
skip3: cmp #$31 ; NUM1
bne skip4
jsr input_move_down
jsr input_move_left
jmp main
skip4: cmp #$33 ; NUM3
bne skip5
jsr input_move_down
jsr input_move_right
jmp main
skip5: cmp #$37 ; NUM7
bne skip6
jsr input_move_up
jsr input_move_left
jmp main
skip6: cmp #$39 ; NUM9
bne skip7
jsr input_move_up
jsr input_move_right
jmp main
skip7: cmp #$20 ; SPACE
beq show_color_pal
cmp #$30 ; NUM0
beq show_color_pal
skip8: cmp #$66 ; f key
beq fill_BG
cmp #$46 ; F key
beq fill_BG
cmp #$2b ; NUM+
beq brush_mode
jmp main

; Change brush mode
brush_mode:
lda #1
eor $80
sta $80
jmp main

; Fill background routine
fill_BG:
ldy #0
ldx $2 ;color
stx $81 ;store to bgcolor
fill: lda #$f0
and $200,Y
dcb $d0, $04 ; bne +4 instruction
txa
sta $200,Y
lda #$f0
and $300,Y
dcb $d0, $04 ; bne +4 instruction
txa
sta $300,Y
lda #$f0
and $400,Y
dcb $d0, $04 ; bne +4 instruction
txa
sta $400,Y
lda #$f0
and $500,Y
dcb $d0, $04 ; bne +4 instruction
txa
sta $500,Y
iny ;Y++
bne fill
jmp main

; Color palette selector routine
show_color_pal:

; Save pic to stack
ldx #17
save_loop:
lda $507,x
pha
lda $527,x
pha
lda $547,x
pha
lda $567,x
pha
lda $587,x
pha
lda $5a7,x
pha
dex
bpl save_loop

; Draw borderlines
ldx #17
lda $4 ;border_clr to A
border_loop:
sta $507,x
sta $5a7,x
dex
bpl border_loop

; Draw center borderlines
tax ;border_clr to X
ldx #0
clc
border_loop2:
sta $527,x
sta $538,x
pha
txa
adc #$20 ;next line
tax
pla
cpx #$80
bne border_loop2

; Draw palette
ldx #7
pal_loop:
txa
asl ; A=A*2
tay
lda $5,x ;palette address
sta $528,y
sta $548,y
iny
sta $528,y
sta $548,y
lda $d,x ;palette address + 8 for 2nd row
sta $568,y
sta $588,y
dey
sta $568,y
sta $588,y
dex
bpl pal_loop

; Flash color and wait for input
palette_input_loop:
; Blink current color
lda $3 ;color_num
tax
clc
asl ;A=color_num*2
cmp #16
bmi less_than_16
clc ;+$30 for the 2nd palette row
adc #$30 ;(for ex., $8*2+$30=$40, $528->$568 which is correct)
less_than_16:
tay
cpx #$c
beq darkblink
cpx #$d
beq darkblink
cpx #$f
beq darkblink
cpx #$5
beq darkblink
lda #1 ;white color for blink
bne brightblink
darkblink:
lda #$c ;or gray
brightblink:
sta $528,y
sta $548,y
iny
sta $528,y
sta $548,y

txa
ldx #150 ;cycle 150 times
wait1: dex
bne wait1
tax

lda $5,x ;load color from palette address
sta $528,y
sta $548,y
dey
sta $528,y
sta $548,y

ldx #0 ;cycle 255 times
wait2: dex
bne wait2

lda $ff ;keypress
beq palette_input_loop ;jumps up if no key pressed
ldx #0
stx $ff ;keypress

; Act on input (key code in A)
cmp #$34 ; NUM4
bne skip10
lda $3 ;color_num
clc
adc #$ff ;-1
and #$0f
sta $3
skip10: cmp #$36 ; NUM6
bne skip11
lda $3 ;color_num
clc
adc #1
and #$0f
sta $3
skip11: cmp #$38 ; NUM8
beq num8_2
cmp #$32 ; NUM2
bne skip12
num8_2: lda $3 ;color_num
clc
adc #8
and #$0f
sta $3
skip12: cmp #$31 ; NUM1
beq num1_7
cmp #$37 ; NUM7
bne skip13
num1_7: lda $3 ;color_num
clc
adc #$ff ;-1
and #$0f
sta $3
bpl num8_2 ;always branch (= jmp)
skip13: cmp #$33 ; NUM3
beq num3_9
cmp #$39 ; NUM9
bne skip14
num3_9: lda $3 ;color_num
clc
adc #1
and #$0f
sta $3
bpl num8_2 ;always branch (= jmp)
skip14: cmp #$20 ; SPACE
beq exit_palette
cmp #$30 ; NUM0
beq exit_palette
cmp #$35 ; NUM5
beq exit_palette
jmp palette_input_loop
exit_palette:
; Load pic from stack
ldx #0
load_loop:
pla
sta $5a7,x
pla
sta $587,x
pla
sta $567,x
pla
sta $547,x
pla
sta $527,x
pla
sta $507,x
inx
cpx #18
bne load_loop

ldx $3 ;get color_num
lda $5,x ;palette[color_num]
sta $2 ;to color
jmp main

; Main input handlers (subroutines)
input_move_left:
lda $0
and #$1f
beq edge_l
dec $0
edge_l:
rts ;return

input_move_right:
inc $0
lda #$1f
bit $0 ;Z={A&$0)
beq edge_r
rts ;return
edge_r:
dec $0
rts ;return

input_move_up:
lda $0
tay
sec
sbc #$20
sta $0
bcc borrow_u
rts ;return
borrow_u:
ldx $1
dex
cpx #01
beq edge_u
stx $1
rts ;return
edge_u:
sty $0
rts ;return

input_move_down:
lda $0
tax
clc
adc #$20
sta $0
lda #0
adc $1
cmp #$6
beq edge_d
sta $1
rts ;return
edge_d:
stx $0
rts ;return

; ---------- END ----------

palette_slow:
dcb $b ; border color
dcb $0, $2, $4, $6, $5, $7, $b, $f ; palette[15]
dcb $9, $8, $a, $e, $d, $3, $c, $1

;offscreen_buffer: ;not done yet
;dcb 0
...

Просто оставлю это здесь на случай если кому-нибудь вздумается таким образом порисовать.

Алсо, практическое применение этому ассемблеру вообще существует? Я могу еще на чем-нибудь запустить этот код помимо эмулятора?

>>8AF
И да и нет. 6502/6510 и архитектурно с ним совместимые применяется (в основном, конечно, применялся в прошлом, а не сейчас) дофига где. Из самых распространённых платформ будут, наверное, Commodore 64, NES (Famicom, Dendy), Atari 2600. Проц у них тот же, но видеосистема устроена по другому, другие адреса, другой формат пикселей. И разрешение в большинстве случаев будет не 32x32, а повыше. Нет никакого "Memory location $fe contains a new random byte on every instruction".
Короче, запустить можно, но без портирования, учитывающего особенности обоих платформ ничего как надо не заработает.
Таким образом, из практического применения остаётся академическое, для изучения асмы. И оно весьма актуально, на Западе 65?? был дичайше популярен именно в этой роли, в то время как в Совок его, и 68000 почти не поставляли, видимо, из-за тогдашних санкций, отчего отечественные начинающие погромисты мучались и до сих пор мучаются, если кто не в курсе со всякими i8080/580ВМ80, которые для этого подходят несравнимо хуже. А эмулятор для этого годится больше, чем "живая" Денди или Коммодора.

>>8Ca
А чем вообще сейчас занимается на работе практикующий ассемблерист?

>>8Cf
Контроллерами, например. Для восьмиразрядных асм до сих пор идёт вместе с сишечкой, хоть уже и давно не наравне с ней. А так, конечно, это знание, которое необходимо иметь всем связанным с IT/выч. техникой и электроникой технарям, но чаще всего достаточно самого поверхностного представления. И это поверхностное представление об устройстве процессоров и их погромировании непосредственно на асме, а то и в машинных кодах, насколько знаю, дают на многих релейтед и не очень специальностях, и нередко на примере всё того же сраного i8080.
21ab591b2...431.png, 17.24 KB, 1219x1031, exif ggl iq id3

>>8Ca
Олсо, в эмуляторе написано, что палитра рипнута с C64, а это не совсем так, цвета там грубо округлённые (в вебовской шестнадцатиричной rgb-шной форме).
8b9bbd2fb...e08.png, 17 KB, 1219x1031, exif ggl iq id3

>>8D0
Вот как пикрелейтед бы выглядел с настоящей коммодоровской палитрой (приблизительной, потому как точной не существует — она зависела от NTSC или PAL-видеотракта и цветонастроек телевизора).
Часть инфы с картинок потерялась потому что цвета были сконвертированы, а не просто применена другая палитра. Кое-где пофиксил это вручную. В общем, она не такая кислотная и позволяет в более плавные градации оттенков и яркости. Переделывать эмуль не нужно, это так, для справки.

>>8Ys
Багфикс для эмулятора в [run]:
заменить в https://alterchan.in/skin/util/6502js/6502asm.com/assembler.js (вроде это он) две строчки
if( (reg+val) > 0xff ) regP |= 1; else regP &= 0xfe;```
и
if( (regY+value) > 0xff ) regP |= 1; else regP &= 0xfe;
на
if(reg >= val) regP |= 1; else regP &= 0xfe;
if (regY >= value) regP |= 1; else regP &= 0xfe;```
соответственно. Между прочим, под первой заменой автором закомменчен фактически пофикшенный вариант. А во второй непонятно зачем продублирован код из doCompare() с добавлением "ov = value;" (переменная "ov", вроде бы, вообще нигде не используется) вместо простого "value = popByte(); doCompare( regY, value ); break;", как сделано в других обработчиках CPY/CPX/CMP. Видимо, автор что-то фиксил-недофиксил. Upd: в версии 1.6 он действительно этого таракана исправил. И, как написано, ещё одного. Его уже исправлять не нужно, он не критичный совсем, и, насколько я сейчас сумел проверить, пофикшен не до конца. 1.6, напомню, бета и глючная, хоть и самая быстрая. Не хочу этим за глаза гнать на автора эмуля, он решил очень сложную задачу, за что честь ему и хвала. РАЗМЕТКИ БОГУ РАЗМЕТКИ! СПОЙЛЕРОВ ТРОНУ ИЗ СПОЙЛЕРОВ!
...

>>8YI
Без ```, конечно же. И со спойлерами я что-то погорячился.

Кстати, пишут, что теперь появится ассемблер, встроенный в браузер. Можно будет перепрошивать биос не выходя из порносайта.
http://www.opennet.ru/opennews/art.shtml?num=43651

>>8YO
Джаваскриптам и так доверия нет, а тут ещё и сплошные закрытые исходники будут. Алсо, жаваплагин, флэшеговно и забытый ActiveX. Это вот, новое, вроде обещают, что будет чем-то лучше, но всё же закрадывается подозрение, что обмен шила на мыло (намылив которым юзерам введут очередные гуглозонды).

>>919
Что здесь твориться? В Беларуси