Разработка и ромхакинг > Ромхакинг
[NES] Не могу разобраться с палитрами и атрибутами на асм
baralgin1003:
День добрый! еще остались тут знатоки асма 6502? в общем ситуация такая: разобрался как грузить тайлы, а как их красить понять не могу. Может как то можно подключать палитру через .incbin ? логику работы атрибутов не понял вообще...
Ti_:
--- Цитата: baralgin1003 от 16 Августа 2013, 22:03:04 ---День добрый! еще остались тут знатоки асма 6502? в общем ситуация такая: разобрался как грузить тайлы, а как их красить понять не могу. Может как то можно подключать палитру через .incbin ? логику работы атрибутов не понял вообще...
--- Конец цитаты ---
Ну как понять красить? Палитра в $3F00 загружена? Экран(бекграунд) включил?
Или проблема только в выборе палитры для нужного блока.
Ее можно выставлять только для 4 тайлов сразу (блок 2x2 тайла) . Как я понимаю первые 2 бита в памяти атрибут соотвествуют 1-ому блоку - ну и так далее. Хотя лучше доки почитай - могу врать. :lol:
Ещё смотри там фон кривой по вертикали. Надо -8 смещение выставить, а не 0.
baralgin1003:
как я понял, атрибутами мы выставляем цвет из палитры, а по какому принципу и в какой последовательности это делать, я не пойму.
палитра загружена, бекграунд включен. блок получается 2х2 тайла? это 16х16 пикселей. неужели такую область можно закрастить только одним цветом?
Ti_:
--- Цитата: baralgin1003 от 17 Августа 2013, 00:34:33 ---как я понял, атрибутами мы выставляем цвет из палитры, а по какому принципу и в какой последовательности это делать, я не пойму.
палитра загружена, бекграунд включен. блок получается 2х2 тайла? это 16х16 пикселей. неужели такую область можно закрастить только одним цветом?
--- Конец цитаты ---
Ну, не одним цветом, а одной палитрой. То есть 3 цвета + ещё 4-ый цвет фона, общий для всех. То есть всего имеем до 13 цветов на фон.
В атрибутах и указываешь номер палитры - от 1-ой до 4-ой для этого блока.
http://wiki.nesdev.com/w/index.php/Attribute_table
baralgin1003:
ну да, начинаю разбираться)))
вот еще вопрос: как мне в фон загрузить большую картинку? размером 16х16 тайлов, чтоб была в середине экрана.
сейчас делаю по-деревенски:
--- Код: ---background:
.db $0,$0,$0,$0,$0,$0,$0,$0,$00,$01,$02,$03,$04,$05,$06,$07,$08,$09,$0A,$0B,$0C,$0D,$0E,$0F,$0,$0,$0,$0,$0,$0,$0,$0
.db $0,$0,$0,$0,$0,$0,$0,$0,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$1A,$1B,$1C,$1D,$1E,$1F,$0,$0,$0,$0,$0,$0,$0,$0
.db $0,$0,$0,$0,$0,$0,$0,$0,$20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$2A,$2B,$2C,$2D,$2E,$2F,$0,$0,$0,$0,$0,$0,$0,$0
.db $0,$0,$0,$0,$0,$0,$0,$0,$30,$31,$32,$33,$34,$35,$36,$37,$38,$39,$3A,$3B,$3C,$3D,$3E,$3F,$0,$0,$0,$0,$0,$0,$0,$0
.db $0,$0,$0,$0,$0,$0,$0,$0,$40,$41,$42,$43,$44,$45,$46,$47,$48,$49,$4A,$4B,$4C,$4D,$4E,$4F,$0,$0,$0,$0,$0,$0,$0,$0
.db $0,$0,$0,$0,$0,$0,$0,$0,$50,$51,$52,$53,$54,$55,$56,$57,$58,$59,$5A,$5B,$5C,$5D,$5E,$5F,$0,$0,$0,$0,$0,$0,$0,$0
.db $0,$0,$0,$0,$0,$0,$0,$0,$60,$61,$62,$63,$64,$65,$66,$67,$68,$69,$6A,$6B,$6C,$6D,$6E,$6F,$0,$0,$0,$0,$0,$0,$0,$0
.db $0,$0,$0,$0,$0,$0,$0,$0,$70,$71,$72,$73,$74,$75,$76,$77,$78,$79,$7A,$7B,$7C,$7D,$7E,$7F,$0,$0,$0,$0,$0,$0,$0,$0
.db $0,$0,$0,$0,$0,$0,$0,$0,$80,$81,$82,$83,$84,$85,$86,$87,$88,$89,$8A,$8B,$8C,$8D,$8E,$8F,$0,$0,$0,$0,$0,$0,$0,$0
.db $0,$0,$0,$0,$0,$0,$0,$0,$90,$91,$92,$93,$94,$95,$96,$97,$98,$99,$9A,$9B,$9C,$9D,$9E,$9F,$0,$0,$0,$0,$0,$0,$0,$0
.db $0,$0,$0,$0,$0,$0,$0,$0,$A0,$A1,$A2,$A3,$A4,$A5,$A6,$A7,$A8,$A9,$AA,$AB,$AC,$AD,$AE,$AF,$0,$0,$0,$0,$0,$0,$0,$0
.db $0,$0,$0,$0,$0,$0,$0,$0,$B0,$B1,$B2,$B3,$B4,$B5,$B6,$B7,$B8,$B9,$BA,$BB,$BC,$BD,$BE,$BF,$0,$0,$0,$0,$0,$0,$0,$0
.db $0,$0,$0,$0,$0,$0,$0,$0,$C0,$C1,$C2,$C3,$C4,$C5,$C6,$C7,$C8,$C9,$CA,$CB,$CC,$CD,$CE,$CF,$0,$0,$0,$0,$0,$0,$0,$0
--- Конец кода ---
и дальше в цикле загружаю
--- Код: ---LoadBackgroundLoop:
LDA background, x ; считаем данные (background + the value in x)
STA $2007 ; запишем их в PPU
INX ; X = X + 1
CPX #$FF ; сравним X со значением $FF,
BNE LoadBackgroundLoop ; переход к LoadBackgroundLoop если нет совпадения
--- Конец кода ---
то есть, мне не хватает FF, чтоб перебрать всю директорию .db.
Ti_:
--- Цитата: baralgin1003 от 17 Августа 2013, 12:04:24 ---ну да, начинаю разбираться)))
вот еще вопрос: как мне в фон загрузить большую картинку? размером 16х16 тайлов, чтоб была в середине экрана.
сейчас делаю по-деревенски:
--- Конец цитаты ---
--- Код: ---Ну как-то так можно (карту закидываешь в ром $8000) :
LDY #$00 ; адрес карты тайлов младший
STY 0
LDA #$80 ; адрес карты тайлов старший
STA 1
LDX #4 ; повторить 4 раза
copy:
LDA (0),Y
STA $2007
INY
BNE copy ; 256 байт.
INC 1 ; увеличиваем верхний байт
DEX ; счетчик повторений
BNE copy
; всего закинули 4раза по 256 = 1024 байта
--- Конец кода ---
--- Цитата: baralgin1003 от 17 Августа 2013, 12:04:24 --- размером 16х16 тайлов, чтоб была в середине экрана.
--- Конец цитаты ---
Сделай лучше полную (32x30), можно будет закинуть целиком, не придется сбрасывать адрес после каждых 16 байт. А где нужно просто сам пропиши тайлы.
Плюс такую можно будет открывать в редакторе NESSt (1024 байт полная с атрибутами, 960 без атрибут).
baralgin1003:
сделал, не грузит в PPU :(
серый экран, хотя тайлы приземлились по $8000 (молестером смотрел). почти полный экран сделал (256х191)
пардон, ступил. ща попробую выровнить картинку
не грузит почему то... в PPU картинка сидит, а вот грузит он (скорее всего) так же до FF, при том один тайл. логика программы вроде правильна
evgeny:
Не Y надо увеличивать, а младший байт.
baralgin1003:
действительно, изменив на
--- Код: ---copy:
LDA (0),Y
STA $2007
INC 0
BNE copy ; 256 байт.
DEX ; счетчик повторений
BNE copy
--- Конец кода ---
стала показываться картинка, которая лежит в бекграунд зоне, то, что попало в спрайтовую зону PPU - не отображается
Ti_:
--- Цитата: evgeny от 19 Августа 2013, 09:37:59 ---Не Y надо увеличивать, а младший байт.
--- Конец цитаты ---
--- Цитата: baralgin1003 от 19 Августа 2013, 09:51:11 ---действительно, изменив на
стала показываться картинка,
--- Конец цитаты ---
С чего бы это? У меня работает, пруф:
baralgin1003:
у меня NESASM, перенес твой код туда
.inesprg 1 ; 1x 16KB PRG-кода
.ineschr 1 ; 1x 8KB CHR-кода
.inesmap 0 ; mapper 0 = NROM, без использования мапперов
.inesmir 1 ; фоновое зеркалирование
;;;;;;;;;;;;;;;
.bank 0
.org $C000
RESET:
SEI ; запрещаем внешнее прерывание
CLD ; запрещаем десятичный режим
LDX #$40
STX $4017 ; запрещаем аудио
LDX #$FF
TXS ; Установка стека
INX ; в регистр X кладем 0
STX $2000 ; запрет вектора NMI
STX $2001 ; запрет прорисовки
STX $4010 ; запрет DMC IRQ
vblankwait1: ; подождем vblank, чтобы убедиться, что PPU готов
BIT $2002
BPL vblankwait1
clrmem: ; очистка памяти
LDA #$00
STA $0000, x
STA $0100, x
STA $0200, x
STA $0400, x
STA $0500, x
STA $0600, x
STA $0700, x
LDA #$FE
STA $0200, x ;убрать все спрайты с экрана
INX
BNE clrmem
vblankwait2: ; Second wait for vblank, PPU is ready after this
BIT $2002
BPL vblankwait2
w:
lda $2002
bpl w
dex
bpl w
;-----------------
lda #$20
ldy #0
sta $2006
sty $2006
sty 0
lda #$80
sta 1
;-----------------
LDY #$00 ; адрес карты тайлов младший
STY 0
LDA #$80 ; адрес карты тайлов старший
STA 1
LDX #4 ; повторить 4 раза
copy:
LDA (0),Y
STA $2007
INY
BNE copy ; 256 байт.
INC 1 ; увеличиваем верхний байт
DEX ; счетчик повторений
BNE copy
lda #$3F
sta $2006
sty $2006
copy_palette:
LDA (0),Y
STA $2007
INY
CPY #16
bne copy_palette
;-----------------
lda #8
sta $2001
lda #$B0
sta $2000
cli
LDA #%10010000 ;разрешаем NMI, спрайты из шаблона 0, фон из шаблона Pattern 1
STA $2000
LDA #%00011110 ; разрешим спрайты, разрешим фон
STA $2001
Forever:
JMP Forever ;jump back to Forever, infinite loop
NMI:
LDA #$00
STA $2003 ; set the low byte (00) of the RAM address
LDA #$02
STA $4014 ; set the high byte (02) of the RAM address, start the transfer
; очищем PPU чтобы отрисовать следующий кадр
LDA #%10010000 ;разрешаем NMI, спрайты из шаблона 0, фон из шаблона Pattern 1
STA $2000
LDA #%00011110 ; разрешим спрайты, разрешим фон
STA $2001
LDA #$00 ;;tell the ppu there is no background scrolling
STA $2005
STA $2005
RTI ; return from interrupt
;;;;;;;;;;;;;;
.org $FFFA ;first of the three vectors starts here
.dw NMI ;when an NMI happens (once per frame if enabled) the
;processor will jump to the label NMI:
.dw RESET ;when the processor first turns on or is reset, it will jump
;to the label RESET:
.dw 0 ;external interrupt IRQ is not used in this tutorial
;;;;;;;;;;;;;;
.bank 2
.org $8000
.incbin "map.nam"
.incbin "pal.pal"
.incbin "fore3.chr" ;includes 8KB graphics file from SMB1
PPU вообще пустой. из-за разных асмов может быть такое? подскажи еще, плиз, чем графику лучше делать? твоя картинка в молексе по-другому смотрится, блоки по-разному расположены у нас. из бмп перегонял прогой Map Image. YY-CHR обрезает картинку
Ti_:
--- Цитата: baralgin1003 link=topic=67195.msg971201#msg971201 ---PPU вообще пустой. из-за разных асмов может быть такое?
подскажи еще, плиз, чем графику лучше делать?
--- Конец цитаты ---
Предположу что nesasm воспринимает
--- Код: --- (0),Y как 0,Y .
--- Конец кода ---
Может там другая форма записи нужна вроде
--- Код: ---[0],Y.
--- Конец кода ---
Вообще лучше не юзай его, там есть как минимум один баг - он мне попался когда делал сборщик объектов к хаку котов: длинные строчки 'обрезаются' - при этом никаких ошибок не пишет.
Картинки можно в Nes Screen Tool как вариант. Там есть импорт из БМП.
Насчет спрайтов yy-chr возможностей хватает вроде.
baralgin1003:
юзаю nesasm, потому что нашел по нему туториал ^_^
выдержка из доки:
--- Цитата ---
Operand syntax
--------------
A accumulator
#i immediate
<n zero page
<n,X zero page indexed by X
<n,Y zero page indexed by Y
[n] indirect (*)
[n,X] indirect pre-indexed by X (*)
[n],Y indirect zero page post-indexed by Y
r relative
n absolute
n,X absolute indexed by X
n,Y absolute indexed by Y
(*) can be zero page or absolute
--- Конец цитаты ---
похоже действительно надо заменить скобки
еще отличия:
--- Цитата ---You can start with NESASM. When you get some basics, you can move to another assembler. You can even continue with NESASM for quite long time, I made two games with it without much troubles. I guess it will start to be problematic with a large scale project.
Some differences are:
- NESASM's local labels are starting with . (dot) while Asm6 local labels starting with @. So .label turns into @label.
- NESASM has LOW and HIGH words to get LSB and MSB of a 16-bit value; Asm6 uses < and > symbols instead. So, lda #LOW(n) turns into lda #<n
- NESASM uses [ ] brackets for relative addressing while Asm6 uses ( ) brackets. So lda [TEMP],y turns into lda (TEMP),y
- Asm6 does not use . before .db, .dw, .byte, .word keywords. Just remove the dot.
--- Конец цитаты ---
погуглив, решил таки перебраться на асм6.
а нет ли случайно исходников бегущей строки? хотелось бы поиграться
Guyver(X.B.M.):
Товарищи, подскажите. NESASM3
В игре при нажатии кнопки у меня короткий выводится звук:
--- Цитата --- lda #%00000001
sta $4015 ;enable square 1
lda #%01010111 ;Duty 10, Volume F
sta $4000
lda #$C9 ;0C9 is a C# in NTSC mode
sta $4002
lda #$03
sta $4003
--- Конец цитаты ---
Как сделать два последовательных звука с задержкой между ними? Подскажите примером... Очень нужно.
Shredder:
--- Цитата: Guyver(X.B.M.) от 19 Августа 2017, 13:05:56 ---Как сделать два последовательных звука с задержкой между ними? Подскажите примером... Очень нужно.
--- Конец цитаты ---
Проиграй звук #1, затем загрузи положительное число в одну из ячеек оперативы и поставь на эту ячейку обратный отсчёт. Сделай, чтобы состояние счётчика проверялось постоянно, независимо от нажатий кнопок. Когда счётчик станет меньше 0, проиграй звук #2 и установи 0 в счётчик.
Если интервал между звуками большой, то может понадобиться 2 связанных счётчика.
Guyver(X.B.M.):
Эх, голая теория :о) Я даже просто счётчик с трудом сделаю...
Shredder:
После проги проигрывания звука добавь:
LDA 7F ; это максимальное число со знаком "+" (положительные: интервал 00-7F, отрицательные: 80-FF)
STA 0500 ; загрузка числа 7F в ячейку оперативы #0500, вместо 0500 используй любую свободную ячейку
Далее добавляешь в код в любом месте игры, который выполняется постоянно:
$0000 - LDA 0500 ; проверяем состояние нашей ячейки, загружая её содержимое в аккумулятор
$0001 - BEQ 0007 ; если в ячейке был 0, то пропускаем весь следующий добавленный нами код, словно его нет :)
$0002 - DEC 0500 ; если в ячейке не 0, то вычитаем из счётчика единицу
$0003 - BPL 0007 ; пропускаем загрузку звука #2, если знак предыдущей операции - "плюс"; а если в результате операции получился "минус" (счётчик достиг FF), то устанавливаем счётчик в 0 и прыгаем на любой выбранный адрес с прогой для проигрывания звука #2
$0004 - LDA 00 ; загружаем в аккумулятор 0
$0005 - STA 0500 ; устанавливаем счётчик в 0
$0006 - ; старт загрузки звука #2
$0007
Guyver(X.B.M.):
Допустим, у меня 2 звука, каждый в своей подпрограмме:
Playsound1: ;;звук 1
lda #$FF
sta $4000
lda #%10011010
sta $4001
lda #$C5
sta $4002
lda #$CB
sta $4003
lda #%00000001
sta $4015
rts
Playsound2: ;;звук 2
lda #$FF
sta $4000
lda #%11111010
sta $4001
lda #$35
sta $4002
lda #$3B
sta $4003
lda #%00000001
sta $4015
rts
Так я их вызывать буду в нужный момент:
jsr Playsound1
jsr Playsound2
Непонятен счётчик - я не могу привести его к виду, который понимает NESASM3, вылазит куча ошибок... Помогите с синтаксисом...
MC68k:
--- Цитата ---Допустим, у меня 2 звука, каждый в своей подпрограмме:
--- Конец цитаты ---
--- Код: ---var1 EQU $0700
var2 EQU $0701
lda #%10011010
JSR beep
;здесь задржка. сделать можно по-разному, например
LDA #0
STA var1
LDA #9
STA var2
loop:DEC var1
BNE loop
DEC var2
BNE loop
LDA #%11111010
JSR beep
RTS
beep:STA $4001
LDA #$FF
STA $4000
#$C5
STA $4002
LDA #$CB
STA $4003
LDA #1
STA $4015
RTS
--- Конец кода ---
Guyver(X.B.M.):
Чегой-то не работает. Что есть var1 и var2, можно для примера?
Навигация
Перейти к полной версии